1 #ifndef ERF_TURB_PERT_STRUCT_H_
2 #define ERF_TURB_PERT_STRUCT_H_
5 #include <AMReX_MultiFabUtil.H>
19 Source, Direct, CPM, None
29 const PerturbationType& pert_type,
32 if (
pt_type.size() < max_level + 1) {
33 pt_type.resize(max_level + 1, -1);
36 if (pert_type == PerturbationType::Source) {
38 }
else if (pert_type == PerturbationType::Direct) {
40 }
else if (pert_type == PerturbationType::CPM) {
53 const amrex::Vector<amrex::BoxArray>& subdomains_lev,
54 const amrex::GpuArray<amrex::Real,3>
dx,
55 const amrex::BoxArray& ba,
56 const amrex::DistributionMapping& dm,
57 const int ngrow_state,
58 std::string pp_prefix,
59 const amrex::Vector<amrex::IntVect> refRatio,
69 amrex::ParmParse
pp(pp_prefix);
79 pp.query(
"perturbation_T_intensity",
tpi_Ti);
83 if (
tpi_layers < 0) { amrex::Abort(
"Please provide a valid perturbation layer value (ie. 3-5)"); }
84 if (
tpi_offset < 0) { amrex::Abort(
"Please provide a valid inflow cell offset value for perturbation region (ie. 0-5)"); }
86 if (
tpi_boxDim[i] < 3) { amrex::Abort(
"Please provide valid dimensions for perturbation boxes."); }
88 if (
tpi_nonDim <
zero) { amrex::Abort(
"Please provide a valid nondimensional number (ie. Ri = amrex::Real(0.042))"); }
89 if (
input_Ug <
zero) { amrex::Abort(
"Please provide a valid geostrophic wind speed (ie. Ug = amrex::Real(10.0) m/s)"); }
90 if (
tpi_Tinf <
zero) { amrex::Abort(
"Please provide a valid ambient temperature value (ie. T_0 = T_infty)"); }
91 if (
tpi_Ti <
zero) { amrex::Abort(
"Please provide a valid temperature intensity value (ie. 0-one)"); }
94 amrex::BoxList tmp_bl;
101 for (
int isub = 0;
isub < subdomains_lev.size(); ++
isub) {
102 const amrex::BoxArray& subdomain = subdomains_lev[
isub];
103 amrex::Box subdomain_box(subdomain.minimalBox());
105 if (subdomain_box.numPts() != subdomain.numPts()) {
106 amrex::Abort(
"Turbulent perturbations require rectangular subdomains. "
107 "Level " + std::to_string(lev) +
108 ", subdomain " + std::to_string(
isub) +
109 " is not a rectangular region fully covered by grids.");
112 const amrex::IntVect& valid_box_lo = subdomain_box.smallEnd();
113 const amrex::IntVect& valid_box_hi = subdomain_box.bigEnd();
116 amrex::Box lo_x_bx(amrex::IntVect(0), amrex::IntVect(1), amrex::IntVect(0));
117 amrex::Box hi_x_bx(amrex::IntVect(0), amrex::IntVect(1), amrex::IntVect(0));
118 amrex::Box lo_y_bx(amrex::IntVect(0), amrex::IntVect(1), amrex::IntVect(0));
119 amrex::Box hi_y_bx(amrex::IntVect(0), amrex::IntVect(1), amrex::IntVect(0));
127 amrex::PrintToFile(
"BoxPerturbationOutput") <<
" West face";
133 amrex::PrintToFile(
"BoxPerturbationOutput") <<
" East face";
140 amrex::PrintToFile(
"BoxPerturbationOutput") <<
" North face";
146 amrex::PrintToFile(
"BoxPerturbationOutput") <<
" South face";
151 amrex::Box lo_x_lo_y_u = lo_x_bx & lo_y_bx;
152 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)));
156 amrex::Box hi_x_lo_y_u = hi_x_bx & lo_y_bx;
157 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)));
161 amrex::Box lo_x_hi_y_u = lo_x_bx & hi_y_bx;
162 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)));
166 amrex::Box hi_x_hi_y_u = hi_x_bx & hi_y_bx;
167 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)));
178 amrex::BoxArray tmp_ba(tmp_bl);
179 tmp_ba.maxSize(boxSize);
181 const int num_levels = max_level + 1;
182 if (
pb_ba.size() < num_levels) {
183 pb_ba.resize(num_levels);
184 pb_mag.resize(num_levels);
185 pb_dir.resize(num_levels);
189 pb_amp.resize(num_levels);
210 pb_cell[lev].define(ba, dm, 1, ngrow_state);
250 amrex::MultiFab& mf_xvel,
251 amrex::MultiFab& mf_yvel,
252 amrex::MultiFab& mf_cons)
258 srand( (
unsigned) time(NULL) );
260 auto m_ixtype = mf_cons.boxArray().ixType();
263 int fix_random_seed = 0;
264 amrex::ParmParse
pp(
"erf");
265 pp.query(
"fix_random_seed", fix_random_seed);
266 if (fix_random_seed) {
268 amrex::InitRandom(1024UL, amrex::ParallelDescriptor::NProcs(), 1024UL);
274 for (
int boxIdx = 0; boxIdx <
pb_ba[lev].size(); boxIdx++) {
276 bool update_box =
true;
296 if (wind_direction >
PI / 4) { wind_direction =
PI / 2 - wind_direction; }
340 for (
int boxIdx = 0; boxIdx <
pb_ba[lev].size(); boxIdx++) {
350 const amrex::Box& vbx,
352 const amrex::IndexType& m_ixtype,
353 const amrex::Array4<amrex::Real>& src_arr,
354 const amrex::Array4<amrex::Real const>& pert_cell)
356 for (
int boxIdx = 0; boxIdx <
pb_ba[lev].size(); boxIdx++) {
357 amrex::Box pbx = amrex::convert(
pb_ba[lev][boxIdx], m_ixtype);
358 amrex::Box ubx = pbx & vbx;
360 ParallelFor(ubx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
361 src_arr(i,j,k,comp) += pert_cell(i,j,k);
389 int total_ref_ratio = 1;
390 for (
int level = lev; level >= 1; level--) {
391 total_ref_ratio *=
ref_ratio[level-1][2];
403 pb_amp[lev][boxIdx] /= interval;
413 const amrex::IndexType& m_ixtype)
415 for (amrex::MFIter mfi(
pb_cell[lev],
TileNoZ()); mfi.isValid(); ++mfi) {
416 amrex::Box vbx = mfi.validbox();
417 amrex::Box pbx = amrex::convert(
pb_ba[lev][boxIdx], m_ixtype);
418 amrex::Box ubx = pbx & vbx;
421 const amrex::Array4<amrex::Real>& pert_cell =
pb_cell[lev].array(mfi);
425 ParallelFor(ubx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
426 pert_cell(i,j,k) = rand_number_const * amp_copy;
429 ParallelForRNG(ubx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k,
const amrex::RandomEngine& engine) noexcept {
431 pert_cell(i,j,k) = (rand_double*
two -
one) * amp_copy;
442 const amrex::IndexType& m_ixtype)
445 for (amrex::MFIter mfi(
pb_cell[lev],
TileNoZ()); mfi.isValid(); ++mfi) {
446 amrex::Box vbx = mfi.validbox();
447 amrex::Box pbx = amrex::convert(
pb_ba[lev][boxIdx], m_ixtype);
448 amrex::Box ubx = pbx & vbx;
450 const amrex::Array4<amrex::Real>& pert_cell =
pb_cell[lev].array(mfi);
451 ParallelFor(ubx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
452 pert_cell(i,j,k) =
zero;
463 const amrex::BoxArray m_pb_ba =
pb_ba[lev];
467 amrex::Vector<amrex::Real> avg_h(1,
zero);
468 amrex::Gpu::DeviceVector<amrex::Real> avg_d(1,
zero);
472 for (amrex::MFIter mfi(
pb_cell[lev],
TileNoZ()) ; mfi.isValid(); ++mfi) {
473 const amrex::Box& vbx = mfi.validbox();
474 amrex::Box pbx = amrex::convert(m_pb_ba[boxIdx], vbx.ixType());
475 amrex::Box ubx = pbx & vbx;
477 const amrex::Array4<const amrex::Real>& pert_cell =
pb_cell[lev].const_array(mfi);
479 ParallelFor(amrex::Gpu::KernelInfo().setReduction(
true), ubx, [=]
480 AMREX_GPU_DEVICE(
int i,
int j,
int k, amrex::Gpu::Handler
const& handler) noexcept {
481 amrex::Gpu::deviceReduceSum(&avg[0], pert_cell(i,j,k)*norm, handler);
483 amrex::Gpu::copy(amrex::Gpu::deviceToHost, avg_d.begin(), avg_d.end(), avg_h.begin());
486 m_pb_netZero[boxIdx] = avg_h[0];
497 const amrex::BoxArray m_pb_ba =
pb_ba[lev];
498 for (amrex::MFIter mfi(
pb_cell[lev],
TileNoZ()) ; mfi.isValid(); ++mfi) {
499 const amrex::Box& vbx = mfi.validbox();
500 amrex::Box pbx = amrex::convert(m_pb_ba[boxIdx], vbx.ixType());
501 amrex::Box ubx = pbx & vbx;
504 const amrex::Array4<amrex::Real>& pert_cell =
pb_cell[lev].array(mfi);
505 ParallelFor(ubx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept {
506 pert_cell(i,j,k) -= adjust;
513 #define USE_VOLUME_AVERAGE
518 amrex::MultiFab& mf_cons,
519 amrex::MultiFab& mf_xvel,
520 amrex::MultiFab& mf_yvel)
524 const amrex::BoxArray m_pb_ba =
pb_ba[lev];
527 m_pb_mag[boxIdx] =
zero;
528 m_pb_dir[boxIdx] =
zero;
534 amrex::Vector<amrex::Real> avg_h(n_avg,
zero);
535 amrex::Gpu::DeviceVector<amrex::Real> avg_d(n_avg,
zero);
539 for (amrex::MFIter mfi(mf_cons,
TileNoZ()); mfi.isValid(); ++mfi) {
542 const amrex::Box& vbx = mfi.validbox();
545 auto ixtype_u = mf_xvel.boxArray().ixType();
546 amrex::Box vbx_u = amrex::convert(vbx,ixtype_u);
547 amrex::Box pbx_u = amrex::convert(m_pb_ba[boxIdx], ixtype_u);
548 amrex::Box ubx_u = pbx_u & vbx_u;
551 auto ixtype_v = mf_yvel.boxArray().ixType();
552 amrex::Box vbx_v = amrex::convert(vbx,ixtype_v);
553 amrex::Box pbx_v = amrex::convert(m_pb_ba[boxIdx], ixtype_v);
554 amrex::Box ubx_v = pbx_v & vbx_v;
558 const amrex::Array4<const amrex::Real>& xvel_arry = mf_xvel.const_array(mfi);
560 #ifdef USE_VOLUME_AVERAGE
562 ParallelFor(amrex::Gpu::KernelInfo().setReduction(
true), ubx_u, [=]
563 AMREX_GPU_DEVICE(
int i,
int j,
int k, amrex::Gpu::Handler
const& handler) noexcept {
564 amrex::Gpu::deviceReduceSum(&avg[0], xvel_arry(i,j,k)*norm, handler);
568 #ifdef USE_SLAB_AVERAGE
569 amrex::Box ubxSlab_lo = makeSlab(ubx_u,2,ubx_u.smallEnd(2));
570 amrex::Box ubxSlab_hi = makeSlab(ubx_u,2,ubx_u.bigEnd(2));
575 ParallelFor(amrex::Gpu::KernelInfo().setReduction(
true), ubxSlab_lo, [=]
576 AMREX_GPU_DEVICE(
int i,
int j,
int k, amrex::Gpu::Handler
const& handler) noexcept {
577 amrex::Gpu::deviceReduceSum(&avg[0], xvel_arry(i,j,k)*norm_lo, handler);
581 ParallelFor(amrex::Gpu::KernelInfo().setReduction(
true), ubxSlab_hi, [=]
582 AMREX_GPU_DEVICE(
int i,
int j,
int k, amrex::Gpu::Handler
const& handler) noexcept {
583 amrex::Gpu::deviceReduceSum(&avg[2], xvel_arry(i,j,k)*norm_hi, handler);
590 const amrex::Array4<const amrex::Real>& yvel_arry = mf_yvel.const_array(mfi);
592 #ifdef USE_VOLUME_AVERAGE
594 ParallelFor(amrex::Gpu::KernelInfo().setReduction(
true), ubx_v, [=]
595 AMREX_GPU_DEVICE(
int i,
int j,
int k, amrex::Gpu::Handler
const& handler) noexcept {
596 amrex::Gpu::deviceReduceSum(&avg[1], yvel_arry(i,j,k)*norm, handler);
600 #ifdef USE_SLAB_AVERAGE
601 amrex::Box ubxSlab_lo = makeSlab(ubx_v,2,ubx_v.smallEnd(2));
602 amrex::Box ubxSlab_hi = makeSlab(ubx_v,2,ubx_v.bigEnd(2));
607 ParallelFor(amrex::Gpu::KernelInfo().setReduction(
true), ubxSlab_lo, [=]
608 AMREX_GPU_DEVICE(
int i,
int j,
int k, amrex::Gpu::Handler
const& handler) noexcept {
609 amrex::Gpu::deviceReduceSum(&avg[1], yvel_arry(i,j,k)*norm_lo, handler);
613 ParallelFor(amrex::Gpu::KernelInfo().setReduction(
true), ubxSlab_hi, [=]
614 AMREX_GPU_DEVICE(
int i,
int j,
int k, amrex::Gpu::Handler
const& handler) noexcept {
615 amrex::Gpu::deviceReduceSum(&avg[3], yvel_arry(i,j,k)*norm_hi, handler);
622 amrex::Gpu::copy(amrex::Gpu::deviceToHost, avg_d.begin(), avg_d.end(), avg_h.begin());
625 #ifdef USE_VOLUME_AVERAGE
626 m_pb_mag[boxIdx] = sqrt(avg_h[0]*avg_h[0] + avg_h[1]*avg_h[1]);
630 #ifdef USE_SLAB_AVERAGE
631 m_pb_mag[boxIdx] =
myhalf*( sqrt(avg_h[0]*avg_h[0] + avg_h[1]*avg_h[1])
632 + sqrt(avg_h[2]*avg_h[2] + avg_h[3]*avg_h[3]));
659 amrex::Vector<amrex::BoxArray>
pb_ba;
660 amrex::Vector<amrex::Vector<amrex::Real>>
pb_mag;
661 amrex::Vector<amrex::Vector<amrex::Real>>
pb_dir;
696 amrex::Vector<amrex::Vector<amrex::Real>>
pb_amp;
703 return min + r * (max - min);
constexpr amrex::Real two
Definition: ERF_Constants.H:8
constexpr amrex::Real one
Definition: ERF_Constants.H:7
constexpr amrex::Real zero
Definition: ERF_Constants.H:6
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:11
constexpr amrex::Real PI
Definition: ERF_Constants.H:16
constexpr amrex::Real CONST_GRAV
Definition: ERF_Constants.H:32
ParallelForRNG(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k, const amrex::RandomEngine &engine) noexcept { const Real x=prob_lo_x+(i+myhalf) *dx;const Real y=prob_lo_y+(j+myhalf) *dy;const Real z=z_cc(i, j, k);const Real r=std::sqrt((x-xc) *(x-xc)+(y-yc) *(y-yc)+(z-zc) *(z-zc));if((z<=pert_ref_height) &&(T_0_Pert_Mag !=amrex::Real(0))) { Real rand_double=amrex::Random(engine);state_pert(i, j, k, RhoTheta_comp)=(rand_double *amrex::Real(2) - amrex::Real(1)) *T_0_Pert_Mag;if(!pert_rhotheta) { state_pert(i, j, k, RhoTheta_comp) *=r_hse(i, j, k);} } state_pert(i, j, k, RhoScalar_comp)=A_0 *exp(-amrex::Real(10.) *r *r);if(state_pert.nComp() > RhoKE_comp) { if(rhoKE_0 > 0) { state_pert(i, j, k, RhoKE_comp)=rhoKE_0;} else { state_pert(i, j, k, RhoKE_comp)=r_hse(i, j, k) *KE_0;} if(KE_decay_height > 0) { state_pert(i, j, k, RhoKE_comp) *=amrex::max(std::pow(1 - amrex::min(z/KE_decay_height, amrex::Real(1)), KE_decay_order), Real(1e-12));} } })
const Real dx
Definition: ERF_InitCustomPert_ABL.H:23
amrex::Real beta
Definition: ERF_InitCustomPert_DataAssimilation_ISV.H:10
ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept { const Real *dx=geomdata.CellSize();const Real x=(i+0.5) *dx[0];const Real y=(j+0.5) *dx[1];const Real Omg=erf_vortex_Gaussian(x, y, xc, yc, R, beta, sigma);const Real deltaT=-(gamma - 1.0)/(2.0 *sigma *sigma) *Omg *Omg;const Real rho_norm=std::pow(1.0+deltaT, inv_gm1);const Real T=(1.0+deltaT) *T_inf;const Real p=std::pow(rho_norm, Gamma)/Gamma *rho_0 *a_inf *a_inf;const Real rho_theta=rho_0 *rho_norm *(T *std::pow(p_0/p, rdOcp));state_pert(i, j, k, RhoTheta_comp)=rho_theta - getRhoThetagivenP(p_hse(i, j, k));const Real r2d_xy=std::sqrt((x-xc) *(x-xc)+(y-yc) *(y-yc));state_pert(i, j, k, RhoScalar_comp)=0.25 *(1.0+std::cos(PI *std::min(r2d_xy, R)/R));})
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, None)
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:22
amrex::Vector< amrex::MultiFab > pb_cell
Definition: ERF_TurbPertStruct.H:665
int tpi_layers
Definition: ERF_TurbPertStruct.H:670
void pseudoRandomPert(const int &boxIdx, const int &lev, const amrex::IndexType &m_ixtype)
Definition: ERF_TurbPertStruct.H:411
amrex::Real tpi_Tinf
Definition: ERF_TurbPertStruct.H:679
amrex::Vector< amrex::Vector< amrex::Real > > pb_local_etime
Definition: ERF_TurbPertStruct.H:695
amrex::Vector< amrex::IntVect > ref_ratio
Definition: ERF_TurbPertStruct.H:690
void calc_tpi_amp(const int &lev, const int &boxIdx, const amrex::Real &interval)
Definition: ERF_TurbPertStruct.H:373
amrex::Real input_Ug
Definition: ERF_TurbPertStruct.H:691
amrex::Vector< amrex::BoxArray > pb_ba
Definition: ERF_TurbPertStruct.H:659
void netZeroBuoyantAdjust(const int &boxIdx, const int &lev)
Definition: ERF_TurbPertStruct.H:493
void calc_tpi_update(const int lev, const amrex::Real dt, amrex::MultiFab &mf_xvel, amrex::MultiFab &mf_yvel, amrex::MultiFab &mf_cons)
Definition: ERF_TurbPertStruct.H:248
amrex::Vector< amrex::Vector< amrex::Real > > pb_mag
Definition: ERF_TurbPertStruct.H:660
amrex::Vector< amrex::Real > tpi_lref
Definition: ERF_TurbPertStruct.H:685
amrex::Vector< int > pt_type
Definition: ERF_TurbPertStruct.H:656
int tpi_offset
Definition: ERF_TurbPertStruct.H:671
amrex::Vector< amrex::Real > tpi_Hpb
Definition: ERF_TurbPertStruct.H:682
void init_tpi_type(const int lev, const PerturbationType &pert_type, const int max_level)
Definition: ERF_TurbPertStruct.H:28
amrex::Vector< amrex::Vector< amrex::Real > > pb_netZero
Definition: ERF_TurbPertStruct.H:697
amrex::Real tpi_Ti
Definition: ERF_TurbPertStruct.H:678
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)
Definition: ERF_TurbPertStruct.H:52
amrex::Real tpi_pert_adjust
Definition: ERF_TurbPertStruct.H:688
void debug(amrex::Real)
Definition: ERF_TurbPertStruct.H:638
amrex::Vector< amrex::Vector< amrex::Real > > pb_interval
Definition: ERF_TurbPertStruct.H:694
amrex::Vector< amrex::Vector< amrex::Real > > pb_dir
Definition: ERF_TurbPertStruct.H:661
void zero_amp(const int &boxIdx, const int &lev, const amrex::IndexType &m_ixtype)
Definition: ERF_TurbPertStruct.H:440
amrex::Vector< int > tpi_boxDim
Definition: ERF_TurbPertStruct.H:673
amrex::Vector< amrex::Real > tpi_Wpb
Definition: ERF_TurbPertStruct.H:684
amrex::Real tpi_nonDim
Definition: ERF_TurbPertStruct.H:677
void calc_tpi_meanMag_perBox(const int &boxIdx, const int &lev, amrex::MultiFab &mf_cons, amrex::MultiFab &mf_xvel, amrex::MultiFab &mf_yvel)
Definition: ERF_TurbPertStruct.H:516
void netZeroBuoyantAdd(const int &boxIdx, const int &lev)
Definition: ERF_TurbPertStruct.H:459
~TurbulentPerturbation()
Definition: ERF_TurbPertStruct.H:26
amrex::Real RandomReal(const amrex::Real min, const amrex::Real max)
Definition: ERF_TurbPertStruct.H:700
amrex::Vector< amrex::Real > tpi_Lpb
Definition: ERF_TurbPertStruct.H:683
amrex::Real tpi_net_buoyant
Definition: ERF_TurbPertStruct.H:687
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)
Definition: ERF_TurbPertStruct.H:349
amrex::Vector< int > tpi_direction
Definition: ERF_TurbPertStruct.H:674
amrex::Vector< amrex::Vector< amrex::Real > > pb_amp
Definition: ERF_TurbPertStruct.H:696