1 #ifndef ERF_TURB_PERT_STRUCT_H_
2 #define ERF_TURB_PERT_STRUCT_H_
6 #include <AMReX_MultiFabUtil.H>
21 Source, Direct, CPM, CPM_W,
None
58 const PerturbationType& pert_type,
61 if (
pt_type.size() < max_level + 1) {
62 pt_type.resize(max_level + 1, -1);
65 if (pert_type == PerturbationType::Source) {
67 }
else if (pert_type == PerturbationType::Direct) {
69 }
else if (pert_type == PerturbationType::CPM) {
71 }
else if (pert_type == PerturbationType::CPM_W) {
92 const amrex::Vector<amrex::BoxArray>& subdomains_lev,
93 const amrex::GpuArray<amrex::Real,3>
dx,
94 const amrex::BoxArray& ba,
95 const amrex::DistributionMapping& dm,
96 const int ngrow_state,
97 std::string pp_prefix,
98 const amrex::Vector<amrex::IntVect> refRatio,
100 const bool automatic =
false)
106 amrex::ParmParse
pp(pp_prefix);
117 amrex::Abort(
"Uniform CPM refresh requires positive, finite "
118 "perturbation_refresh_height and perturbation_refresh_wind_period");
129 amrex::Abort(
"perturbation_box_dims must have 3 entries (Nx Ny Nz)");
132 amrex::Abort(
"perturbation_direction must have 6 entries (west south bottom east north top)");
141 pp.queryAdd(
"perturbation_T_infinity",
tpi_Tinf);
144 pp.queryAdd(
"perturbation_T_intensity",
tpi_Ti);
158 amrex::ParmParse pp_erf(
"erf");
179 if (
tpi_offset < 0) { amrex::Abort(
"Please provide a valid inflow cell offset value for perturbation region (ie. 0-5)"); }
180 if (
tpi_layers < 0) { amrex::Abort(
"Please provide a valid perturbation layer value (ie. 3-5)"); }
182 amrex::Abort(
"Automatic perturbations and uniform CPM refresh require perturbation_layers > 0");
184 if (
tpi_nonDim <
zero) { amrex::Abort(
"Please provide a valid nondimensional number (ie. Ri = amrex::Real(0.042))"); }
186 if (
tpi_boxDim[i] < 3) { amrex::Abort(
"Please provide valid dimensions for perturbation boxes."); }
188 if (
input_Ug <
zero) { amrex::Abort(
"Please provide a valid geostrophic wind speed (ie. Ug = amrex::Real(10.0) m/s)"); }
189 if (
tpi_Tinf <
zero) { amrex::Abort(
"Please provide a valid ambient temperature value (ie. T_0 = T_infty)"); }
190 if (
tpi_Ti <
zero) { amrex::Abort(
"Please provide a valid temperature intensity value (ie. 0-one)"); }
193 amrex::BoxList tmp_bl;
200 for (
int isub = 0;
isub < subdomains_lev.size(); ++
isub) {
201 const amrex::BoxArray& subdomain = subdomains_lev[
isub];
202 amrex::Box subdomain_box(subdomain.minimalBox());
204 if (subdomain_box.numPts() != subdomain.numPts()) {
205 amrex::Abort(
"Turbulent perturbations require rectangular subdomains. "
206 "Level " + std::to_string(lev) +
207 ", subdomain " + std::to_string(
isub) +
208 " is not a rectangular region fully covered by grids.");
211 const amrex::IntVect& valid_box_lo = subdomain_box.smallEnd();
212 const amrex::IntVect& valid_box_hi = subdomain_box.bigEnd();
217 for (
int face = 0; face < 4; ++face) {
219 if (region.ok()) { tmp_bl.push_back(region); }
229 amrex::Box lo_x_bx(amrex::IntVect(0), amrex::IntVect(1), amrex::IntVect(0));
230 amrex::Box hi_x_bx(amrex::IntVect(0), amrex::IntVect(1), amrex::IntVect(0));
231 amrex::Box lo_y_bx(amrex::IntVect(0), amrex::IntVect(1), amrex::IntVect(0));
232 amrex::Box hi_y_bx(amrex::IntVect(0), amrex::IntVect(1), amrex::IntVect(0));
240 amrex::PrintToFile(
"BoxPerturbationOutput") <<
" West face";
246 amrex::PrintToFile(
"BoxPerturbationOutput") <<
" East face";
253 amrex::PrintToFile(
"BoxPerturbationOutput") <<
" North face";
259 amrex::PrintToFile(
"BoxPerturbationOutput") <<
" South face";
264 amrex::Box lo_x_lo_y_u = lo_x_bx & lo_y_bx;
265 lo_y_bx.setSmall(amrex::IntVect(lo_x_lo_y_u.bigEnd(0)+1, lo_x_lo_y_u.smallEnd(1), lo_x_lo_y_u.smallEnd(2)));
269 amrex::Box hi_x_lo_y_u = hi_x_bx & lo_y_bx;
270 lo_y_bx.setBig(amrex::IntVect(hi_x_lo_y_u.smallEnd(0)-1, hi_x_lo_y_u.bigEnd(1), hi_x_lo_y_u.bigEnd(2)));
274 amrex::Box lo_x_hi_y_u = lo_x_bx & hi_y_bx;
275 hi_y_bx.setSmall(amrex::IntVect(lo_x_hi_y_u.bigEnd(0)+1, lo_x_hi_y_u.smallEnd(1), lo_x_hi_y_u.smallEnd(2)));
279 amrex::Box hi_x_hi_y_u = hi_x_bx & hi_y_bx;
280 hi_y_bx.setBig(amrex::IntVect(hi_x_hi_y_u.smallEnd(0)-1, hi_x_hi_y_u.bigEnd(1), hi_x_hi_y_u.bigEnd(2)));
291 amrex::BoxArray tmp_ba(tmp_bl);
292 if (
auto_mode) { tmp_ba.removeOverlap(); }
293 tmp_ba.maxSize(boxSize);
295 amrex::Abort(
"Automatic perturbation strips are empty; reduce perturbation_offset");
298 const int num_levels = max_level + 1;
299 if (
pb_ba.size() < num_levels) {
300 pb_ba.resize(num_levels);
301 pb_mag.resize(num_levels);
302 pb_Ug.resize(num_levels);
303 pb_dir.resize(num_levels);
307 pb_amp.resize(num_levels);
337 pb_cell[lev].define(convert(ba, amrex::IntVect(0,0,1)), dm, 1, ngrow_state);
339 pb_cell[lev].define(ba, dm, 1, ngrow_state);
387 amrex::Box region = subdomain;
390 const int dir = face % 2;
393 region.setBig(dir, std::min(region.bigEnd(dir), region.smallEnd(dir)+width-1));
395 region.setSmall(dir, std::max(region.smallEnd(dir), region.bigEnd(dir)-width+1));
430 clock.interval = speed >
zero
433 clock.next_refresh = time;
434 clock.next_wind_update = time + wind_period;
448 time < clock.next_refresh ||
pb_ba[lev].empty()) {
return false; }
450 clock.next_refresh = time + clock.interval;
453 const auto m_ixtype =
pb_cell[lev].ixType();
454 for (
int b = 0; b <
pb_ba[lev].size(); ++b) {
467 const amrex::Vector<AutomaticPerturbationFace>& faces,
468 const amrex::Geometry& geom,
469 const amrex::MultiFab* z_cc,
470 const amrex::MultiFab* z_nd,
471 const amrex::MultiFab* z_ground)
478 const bool on_w_faces = (
pt_type[lev] == 3);
479 const bool terrain = (z_cc !=
nullptr);
481 const int klo = geom.Domain().smallEnd(2);
482 const auto dx = geom.CellSizeArray();
483 const auto problo = geom.ProbLoArray();
484 for (
const auto& face : faces) {
485 if (!face.inflow()) {
continue; }
486 const amrex::Real speed = std::hypot(face.u, face.v);
487 for (
const auto& isect :
pb_ba[lev].intersections(face.region)) {
488 const int b = isect.first;
489 pb_Ug[lev][b] = std::max(
pb_Ug[lev][b], face.Ug);
490 if (speed >
pb_mag[lev][b]) {
492 pb_dir[lev][b] = std::atan2(std::abs(face.u), std::abs(face.v));
496 const amrex::Box region = amrex::convert(face.region,
auto_mask[lev].ixType());
497 for (amrex::MFIter mfi(
auto_mask[lev]); mfi.isValid(); ++mfi) {
498 const amrex::Box bx = mfi.validbox() & region;
499 if (!bx.ok()) {
continue; }
500 const auto mask =
auto_mask[lev].array(mfi);
501 const auto cc = terrain ? z_cc->const_array(mfi) : amrex::Array4<const amrex::Real>{};
502 const auto nd = terrain ? z_nd->const_array(mfi) : amrex::Array4<const amrex::Real>{};
503 const auto ground = terrain ? z_ground->const_array(mfi) : amrex::Array4<const amrex::Real>{};
504 ParallelFor(bx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept {
509 ground(i,j+1,
klo) + ground(i+1,j+1,
klo));
510 z = on_w_faces ?
fourth*(nd(i,j,k) + nd(i+1,j,k) +
511 nd(i,j+1,k) + nd(i+1,j+1,k))
514 if (
z > zs &&
z-zs <=
height) { mask(i,j,k) =
one; }
536 amrex::MultiFab& mf_xvel,
537 amrex::MultiFab& mf_yvel,
538 amrex::MultiFab& mf_cons)
540 auto m_ixtype = mf_cons.boxArray().ixType();
541 if (
pt_type[lev] == 3) { m_ixtype = amrex::IndexType(amrex::IntVect(0,0,1)); }
543 const int nboxes =
pb_ba[lev].size();
548 amrex::Vector<int> update_box(nboxes, 0);
549 for (
int boxIdx = 0; boxIdx < nboxes; boxIdx++) {
561 for (
int boxIdx = 0; boxIdx < nboxes; boxIdx++) {
562 if ( update_box[boxIdx] ) {
565 double interval = 0.0;
569 if (wind_direction >
PI / 4) { wind_direction =
PI / 2 - wind_direction; }
621 const amrex::Box& vbx,
623 const amrex::IndexType& m_ixtype,
624 const amrex::Array4<amrex::Real>& src_arr,
625 const amrex::Array4<amrex::Real const>& pert_cell,
629 for (
int boxIdx = 0; boxIdx <
pb_ba[lev].size(); boxIdx++) {
630 amrex::Box pbx = amrex::convert(
pb_ba[lev][boxIdx], m_ixtype);
631 if (
pt_type[lev] == 3) { pbx.setBig(2, pbx.bigEnd(2) - 1); }
632 amrex::Box ubx = pbx & vbx;
635 ParallelFor(ubx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept {
636 src_arr(i,j,k) += scale * pert_cell(i,j,k);
639 ParallelFor(ubx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept {
640 src_arr(i,j,k,comp) += scale * pert_cell(i,j,k);
660 const double& interval)
667 pb_amp[lev][boxIdx] = (Ug * Ug) / (Ec *
cp);
668 }
else if (
pt_type[lev] == 3) {
676 if (Um ==
zero) {
return; }
683 int total_ref_ratio = 1;
684 for (
int level = lev; level >= 1; level--) {
685 total_ref_ratio *=
ref_ratio[level-1][2];
709 const amrex::IndexType& m_ixtype)
711 for (amrex::MFIter mfi(
pb_cell[lev],
TileNoZ()); mfi.isValid(); ++mfi) {
712 amrex::Box vbx = mfi.tilebox();
713 amrex::Box pbx = amrex::convert(
pb_ba[lev][boxIdx], m_ixtype);
714 if (
pt_type[lev] == 3) { pbx.setBig(2, pbx.bigEnd(2) - 1); }
715 amrex::Box ubx = pbx & vbx;
718 const amrex::Array4<amrex::Real>& pert_cell =
pb_cell[lev].array(mfi);
720 const auto mask = use_mask ?
auto_mask[lev].const_array(mfi)
721 : amrex::Array4<const amrex::Real>{};
726 ParallelFor(ubx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
727 pert_cell(i,j,k) = (use_mask && mask(i,j,k) ==
zero) ?
zero : rand_number_const * amp_copy;
732 ParallelFor(ubx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
733 pert_cell(i,j,k) = (use_mask && mask(i,j,k) ==
zero) ?
zero
749 const amrex::IndexType& m_ixtype)
752 for (amrex::MFIter mfi(
pb_cell[lev],
TileNoZ()); mfi.isValid(); ++mfi) {
753 amrex::Box vbx = mfi.tilebox();
754 amrex::Box pbx = amrex::convert(
pb_ba[lev][boxIdx], m_ixtype);
755 if (
pt_type[lev] == 3) { pbx.setBig(2, pbx.bigEnd(2) - 1); }
756 amrex::Box ubx = pbx & vbx;
758 const amrex::Array4<amrex::Real>& pert_cell =
pb_cell[lev].array(mfi);
759 ParallelFor(ubx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
760 pert_cell(i,j,k) =
zero;
775 const int nboxes =
pb_ba[lev].size();
776 if (nboxes == 0) {
return; }
779 amrex::Vector<amrex::Real> sums(2*nboxes,
zero);
780 for (amrex::MFIter mfi(
pb_cell[lev]); mfi.isValid(); ++mfi) {
781 const amrex::Box& vbx = mfi.validbox();
782 const amrex::Array4<const amrex::Real>& pert_cell =
pb_cell[lev].const_array(mfi);
783 for (
const auto& isect :
pb_ba[lev].intersections(vbx)) {
784 sums[2*isect.first ] +=
box_sum(pert_cell, isect.second);
790 amrex::ParallelAllReduce::Sum(sums.data(),
static_cast<int>(sums.size()),
791 amrex::ParallelContext::CommunicatorSub());
796 for (
int boxIdx = 0; boxIdx < nboxes; boxIdx++) {
797 pb_netZero[lev][boxIdx] = (sums[2*boxIdx+1] >
zero) ? sums[2*boxIdx] / sums[2*boxIdx+1] :
zero;
803 for (
int b = 0; b < nboxes; ++b) { sum += sums[2*b]; count += sums[2*b+1]; }
808 for (amrex::MFIter mfi(
pb_cell[lev]); mfi.isValid(); ++mfi) {
809 const amrex::Box& vbx = mfi.validbox();
810 const amrex::Array4<amrex::Real>& pert_cell =
pb_cell[lev].array(mfi);
812 const auto mask = use_mask ?
auto_mask[lev].const_array(mfi)
813 : amrex::Array4<const amrex::Real>{};
814 for (
const auto& isect :
pb_ba[lev].intersections(vbx)) {
815 ParallelFor(isect.second, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
816 if (!use_mask || mask(i,j,k) >
zero) { pert_cell(i,j,k) -= adjust; }
834 const amrex::Vector<int>& update_box,
835 amrex::MultiFab& mf_cons,
836 amrex::MultiFab& mf_xvel,
837 amrex::MultiFab& mf_yvel)
839 const amrex::BoxArray& m_pb_ba =
pb_ba[lev];
840 const int nboxes = m_pb_ba.size();
843 amrex::Vector<amrex::Real> sums(4*nboxes,
zero);
844 for (amrex::MFIter mfi(mf_cons); mfi.isValid(); ++mfi) {
845 const amrex::Box& vbx = mfi.validbox();
846 const amrex::Array4<const amrex::Real>& xvel_arry = mf_xvel.const_array(mfi);
847 const amrex::Array4<const amrex::Real>& yvel_arry = mf_yvel.const_array(mfi);
848 for (
const auto& isect : m_pb_ba.intersections(vbx)) {
849 const int boxIdx = isect.first;
850 if (!update_box[boxIdx]) {
continue; }
851 const amrex::Box& pbx = m_pb_ba[boxIdx];
855 amrex::Box ubx_u = amrex::surroundingNodes(isect.second, 0);
856 if (isect.second.bigEnd(0) < pbx.bigEnd(0)) { ubx_u.growHi(0, -1); }
857 amrex::Box ubx_v = amrex::surroundingNodes(isect.second, 1);
858 if (isect.second.bigEnd(1) < pbx.bigEnd(1)) { ubx_v.growHi(1, -1); }
860 sums[4*boxIdx ] +=
box_sum(xvel_arry, ubx_u);
861 sums[4*boxIdx+1] +=
static_cast<amrex::Real>(ubx_u.numPts());
862 sums[4*boxIdx+2] +=
box_sum(yvel_arry, ubx_v);
863 sums[4*boxIdx+3] +=
static_cast<amrex::Real>(ubx_v.numPts());
866 amrex::ParallelAllReduce::Sum(sums.data(),
static_cast<int>(sums.size()),
867 amrex::ParallelContext::CommunicatorSub());
869 for (
int boxIdx = 0; boxIdx < nboxes; boxIdx++) {
870 if (!update_box[boxIdx]) {
continue; }
871 const amrex::Real u_avg = (sums[4*boxIdx+1] >
zero) ? sums[4*boxIdx ] / sums[4*boxIdx+1] :
zero;
872 const amrex::Real v_avg = (sums[4*boxIdx+3] >
zero) ? sums[4*boxIdx+2] / sums[4*boxIdx+3] :
zero;
873 pb_mag[lev][boxIdx] = std::sqrt(u_avg*u_avg + v_avg*v_avg);
886 amrex::ReduceOps<amrex::ReduceOpSum> reduce_op;
887 amrex::ReduceData<amrex::Real> reduce_data(reduce_op);
888 using ReduceTuple =
typename decltype(reduce_data)::Type;
889 reduce_op.eval(bx, reduce_data, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) noexcept -> ReduceTuple
893 return amrex::get<0>(reduce_data.value(reduce_op));
920 amrex::Vector<amrex::BoxArray>
pb_ba;
921 amrex::Vector<amrex::Vector<amrex::Real>>
pb_mag;
922 amrex::Vector<amrex::Vector<amrex::Real>>
pb_dir;
942 amrex::Vector<amrex::Vector<amrex::Real>>
pb_Ug;
978 amrex::Vector<amrex::Vector<amrex::Real>>
pb_amp;
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:72
auto problo
Definition: ERF_InitCustomPertVels_ABL.H:36
long random_seed
Definition: ERF_InitCustomPert_ABL.H:6
int fix_random_seed
Definition: ERF_InitCustomPert_ABL.H:5
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
const int klo
Definition: ERF_InitCustomPert_KE.H:9
Real height
Definition: ERF_InitCustomPert_SquallLine.H:37
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
constexpr amrex::Real fourth
Definition: ERF_NumericalConstants.H:42
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
constexpr amrex::Real PI
Definition: ERF_NumericalConstants.H:46
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
AMREX_ENUM(PerturbationType, Source, Direct, CPM, CPM_W, None)
@ None
Definition: ERF_LSM_Types.H:6
@ beta
Definition: ERF_SLM.H:152
void apply(const amrex::Box &bx, const amrex::Box &domain, const int quantity, const int flux_comp, const amrex::Array4< const amrex::Real > &state, const amrex::Array4< const amrex::Real > &prim, const amrex::Array4< const amrex::Real > &base_state, const amrex::Array4< const amrex::Real > &u, const amrex::Array4< const amrex::Real > &v, const amrex::Array4< const amrex::Real > &w, const amrex::Array4< amrex::Real > &rhs, const amrex::Array4< amrex::Real > &xflux, const amrex::Array4< amrex::Real > &yflux, const amrex::Array4< amrex::Real > &zflux, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dx_inv, const erf_wall_thermodynamics::Boundary &walls, const amrex::Real alpha_T, const amrex::Real alpha_C, const amrex::Real rdOcp, const bool cloudy=false)
Definition: ERF_CloudChamberWallFlux.H:1037
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real hash_symmetric(int i, int j, int k, int comp, int lev, std::uint64_t seed) noexcept
Definition: ERF_HashRNG.H:91
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE std::uint64_t splitmix64(std::uint64_t x) noexcept
Definition: ERF_HashRNG.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real hash_uniform(int i, int j, int k, int comp, int lev, std::uint64_t seed) noexcept
Definition: ERF_HashRNG.H:68
real(c_double), parameter g
Definition: ERF_module_model_constants.F90:19
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
real(c_double), parameter cp
Definition: ERF_module_model_constants.F90:22
integer, private isub
Definition: ERF_module_mp_morr_two_moment.F90:164
Definition: ERF_TurbPertStruct.H:25
int face
Definition: ERF_TurbPertStruct.H:27
amrex::Real Ug
Definition: ERF_TurbPertStruct.H:30
amrex::Real height
Definition: ERF_TurbPertStruct.H:31
amrex::Real u
Definition: ERF_TurbPertStruct.H:28
amrex::Box region
Definition: ERF_TurbPertStruct.H:26
amrex::Real v
Definition: ERF_TurbPertStruct.H:29
bool inflow() const
Definition: ERF_TurbPertStruct.H:33
Runtime state and operations for turbulent perturbation forcing.
Definition: ERF_TurbPertStruct.H:42
amrex::Real tpi_Tinf
Reference temperature used by the perturbation formulation [K].
Definition: ERF_TurbPertStruct.H:958
int tpi_layers
Number of layers of perturbation boxes.
Definition: ERF_TurbPertStruct.H:949
amrex::Vector< amrex::Real > tpi_Wpb
Perturbation-box width for each AMR level [m].
Definition: ERF_TurbPertStruct.H:963
amrex::Real input_w_amp
Input vertical velocity perturbation amplitude.
Definition: ERF_TurbPertStruct.H:971
void calc_tpi_update(const int lev, const double dt, amrex::MultiFab &mf_xvel, amrex::MultiFab &mf_yvel, amrex::MultiFab &mf_cons)
Update perturbation amplitudes and intervals when each box is ready.
Definition: ERF_TurbPertStruct.H:534
void calc_tpi_amp(const int &lev, const int &boxIdx, const double &interval)
Compute the perturbation amplitude for one perturbation box.
Definition: ERF_TurbPertStruct.H:658
amrex::Box automatic_face_box(const amrex::Box &subdomain, int face) const
Definition: ERF_TurbPertStruct.H:385
bool uniform_wind_update_due(int lev, double time) const
Definition: ERF_TurbPertStruct.H:410
void pseudoRandomPert(const int &boxIdx, const int &lev, const amrex::IndexType &m_ixtype)
Assign pseudo-random perturbations to cells in one perturbation box.
Definition: ERF_TurbPertStruct.H:707
amrex::Real tpi_pert_adjust
Per-cell perturbation adjustment used for net-zero buoyancy.
Definition: ERF_TurbPertStruct.H:967
amrex::Vector< int > tpi_direction
Boundary directions where perturbations are applied.
Definition: ERF_TurbPertStruct.H:953
int perturbation_klo
Lower vertical index bound for perturbations.
Definition: ERF_TurbPertStruct.H:972
amrex::Vector< amrex::Vector< amrex::Real > > pb_Ug
Definition: ERF_TurbPertStruct.H:942
void set_uniform_advection(int lev, double time, amrex::Real speed, double wind_period)
Definition: ERF_TurbPertStruct.H:425
void netZeroBuoyant(const int &lev)
Remove the mean of the box-perturbation field, so the net buoyant forcing is zero.
Definition: ERF_TurbPertStruct.H:773
int tpi_offset
Cell offset for the start of the perturbation region.
Definition: ERF_TurbPertStruct.H:950
static constexpr int hash_comp_interval
Hash salt of the refresh-interval variation.
Definition: ERF_TurbPertStruct.H:986
void init_tpi(const int lev, const amrex::Vector< amrex::BoxArray > &subdomains_lev, const amrex::GpuArray< amrex::Real, 3 > dx, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm, const int ngrow_state, std::string pp_prefix, const amrex::Vector< amrex::IntVect > refRatio, const int max_level, const bool automatic=false)
Initialize turbulent perturbation regions and per-box storage.
Definition: ERF_TurbPertStruct.H:91
bool uniform_refresh_enabled(int lev) const
Definition: ERF_TurbPertStruct.H:405
static constexpr int hash_comp_cpm
Hash salt of the per-box CPM values.
Definition: ERF_TurbPertStruct.H:985
amrex::Vector< amrex::Real > tpi_Lpb
Perturbation-box length for each AMR level [m].
Definition: ERF_TurbPertStruct.H:962
amrex::Real uniform_sampling_height() const
Definition: ERF_TurbPertStruct.H:415
amrex::Vector< amrex::Vector< amrex::Real > > pb_netZero
Per-box storage used for net-zero buoyancy calculation.
Definition: ERF_TurbPertStruct.H:979
bool auto_mode
Definition: ERF_TurbPertStruct.H:941
void configure_automatic(int lev, double time, double period, const amrex::Vector< AutomaticPerturbationFace > &faces, const amrex::Geometry &geom, const amrex::MultiFab *z_cc, const amrex::MultiFab *z_nd, const amrex::MultiFab *z_ground)
Definition: ERF_TurbPertStruct.H:466
bool uniform_sampling_face(int face) const
Definition: ERF_TurbPertStruct.H:418
amrex::Vector< UniformClock > uniform_clock
Definition: ERF_TurbPertStruct.H:939
amrex::Real uniform_wind_period
Definition: ERF_TurbPertStruct.H:938
amrex::Real uniform_height
Definition: ERF_TurbPertStruct.H:937
amrex::Vector< amrex::Vector< amrex::Real > > pb_mag
Mean velocity magnitude for each perturbation box [m/s].
Definition: ERF_TurbPertStruct.H:921
amrex::Real tpi_net_buoyant
Accumulated net buoyant perturbation used for correction.
Definition: ERF_TurbPertStruct.H:966
amrex::Vector< amrex::Vector< amrex::Real > > pb_dir
Mean velocity direction for each perturbation box.
Definition: ERF_TurbPertStruct.H:922
static constexpr int hash_comp_cell
Hash salt of the per-cell perturbation values.
Definition: ERF_TurbPertStruct.H:984
amrex::Vector< amrex::Vector< int > > pb_nupdate
Number of times each perturbation box has been refreshed; keys its random numbers.
Definition: ERF_TurbPertStruct.H:980
amrex::Vector< int > auto_ready
Definition: ERF_TurbPertStruct.H:946
amrex::Real input_Ug
Input geostrophic wind speed used to scale CPM perturbations.
Definition: ERF_TurbPertStruct.H:970
void calc_tpi_meanMag(const int &lev, const amrex::Vector< int > &update_box, amrex::MultiFab &mf_cons, amrex::MultiFab &mf_xvel, amrex::MultiFab &mf_yvel)
Compute the mean horizontal velocity magnitude and direction of the refreshing perturbation boxes.
Definition: ERF_TurbPertStruct.H:833
amrex::Vector< int > tpi_boxDim
Dimensions of each perturbation box.
Definition: ERF_TurbPertStruct.H:952
amrex::Vector< amrex::Vector< double > > pb_interval
Perturbation update interval for each box [s].
Definition: ERF_TurbPertStruct.H:976
void apply_tpi(const int &lev, const amrex::Box &vbx, const int &comp, const amrex::IndexType &m_ixtype, const amrex::Array4< amrex::Real > &src_arr, const amrex::Array4< amrex::Real const > &pert_cell, const amrex::Real scale=one)
Apply stored turbulent perturbations to a source or state array.
Definition: ERF_TurbPertStruct.H:620
void init_tpi_type(const int lev, const PerturbationType &pert_type, const int max_level)
Store the integer perturbation-type selector for one AMR level.
Definition: ERF_TurbPertStruct.H:57
void debug(double)
Write perturbation debug information when debug output is enabled.
Definition: ERF_TurbPertStruct.H:899
amrex::Vector< amrex::Vector< double > > pb_local_etime
Local elapsed time for each perturbation box [s].
Definition: ERF_TurbPertStruct.H:977
amrex::Vector< amrex::Real > tpi_lref
Perturbation-box reference length for each AMR level [m].
Definition: ERF_TurbPertStruct.H:964
double uniform_refresh_interval(int lev) const
Definition: ERF_TurbPertStruct.H:438
amrex::Vector< amrex::MultiFab > pb_cell
Per-cell perturbation amplitude storage.
Definition: ERF_TurbPertStruct.H:926
void zero_amp(const int &boxIdx, const int &lev, const amrex::IndexType &m_ixtype)
Reset CPM perturbation amplitudes in one perturbation box to zero.
Definition: ERF_TurbPertStruct.H:747
amrex::Vector< amrex::IntVect > ref_ratio
Refinement ratios used by multilevel perturbation scaling.
Definition: ERF_TurbPertStruct.H:969
static amrex::Real box_sum(const amrex::Array4< const amrex::Real > &arr, const amrex::Box &bx)
Sum an array over a box.
Definition: ERF_TurbPertStruct.H:884
bool automatic_update_due(int lev, double time) const
Definition: ERF_TurbPertStruct.H:400
int perturbation_khi
Upper vertical index bound for perturbations.
Definition: ERF_TurbPertStruct.H:973
amrex::Real tpi_Ti
Temperature intensity used by the perturbation formulation.
Definition: ERF_TurbPertStruct.H:957
bool uniform_mode
Definition: ERF_TurbPertStruct.H:936
amrex::Real uniform_sampling_period() const
Definition: ERF_TurbPertStruct.H:416
amrex::Vector< amrex::BoxArray > pb_ba
Perturbation-box BoxArray for each AMR level.
Definition: ERF_TurbPertStruct.H:920
~TurbulentPerturbation()
Destroy turbulent perturbation state.
Definition: ERF_TurbPertStruct.H:49
amrex::Vector< double > auto_next_update
Definition: ERF_TurbPertStruct.H:944
amrex::Vector< int > pt_type
Integer perturbation type for each AMR level.
Definition: ERF_TurbPertStruct.H:917
amrex::Vector< amrex::Vector< amrex::Real > > pb_amp
Perturbation amplitude for each perturbation box.
Definition: ERF_TurbPertStruct.H:978
amrex::Vector< amrex::MultiFab > auto_mask
Definition: ERF_TurbPertStruct.H:943
amrex::Real tpi_nonDim
Nondimensional number used by the perturbation formulation.
Definition: ERF_TurbPertStruct.H:956
std::uint64_t tpi_seed
Seed of the hashed random numbers (1024 with erf.fix_random_seed, else erf.random_seed,...
Definition: ERF_TurbPertStruct.H:983
bool calc_tpi_uniform_update(int lev, double time)
Definition: ERF_TurbPertStruct.H:442
amrex::Vector< amrex::Real > tpi_Hpb
Perturbation-box height for each AMR level [m].
Definition: ERF_TurbPertStruct.H:961