ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ABLMost Class Reference

#include <ERF_ABLMost.H>

Collaboration diagram for ABLMost:

Public Types

enum class  FluxCalcType { MOENG = 0 , DONELAN , CUSTOM , ROTATE }
 
enum class  ThetaCalcType { ADIABATIC = 0 , HEAT_FLUX , SURFACE_TEMPERATURE }
 
enum class  RoughCalcType {
  CONSTANT = 0 , CHARNOCK , MODIFIED_CHARNOCK , DONELAN ,
  WAVE_COUPLED
}
 
enum class  PBLHeightCalcType { None , MYNN25 , YSU }
 

Public Member Functions

 ABLMost (const amrex::Vector< amrex::Geometry > &geom, bool &use_exp_most, bool &use_rot_most, std::string a_pp_prefix, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &Qv_prim, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &z_phys_nd, const TerrainType &a_terrain_type, amrex::Real start_bdy_time=0.0, amrex::Real bdy_time_interval=0.0)
 
void make_MOST_at_level (const int &lev, int nlevs, const amrex::Vector< amrex::MultiFab * > &mfv, std::unique_ptr< amrex::MultiFab > &Theta_prim, std::unique_ptr< amrex::MultiFab > &Qv_prim, std::unique_ptr< amrex::MultiFab > &Qr_prim, std::unique_ptr< amrex::MultiFab > &z_phys_nd, amrex::MultiFab *Hwave, amrex::MultiFab *Lwave, amrex::MultiFab *eddyDiffs, amrex::Vector< amrex::MultiFab * > lsm_data, amrex::Vector< amrex::MultiFab * > lsm_flux, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &sst_lev, amrex::Vector< std::unique_ptr< amrex::iMultiFab >> &lmask_lev)
 
void update_fluxes (const int &lev, const amrex::Real &time, int max_iters=25)
 
template<typename FluxIter >
void compute_fluxes (const int &lev, const int &max_iters, const FluxIter &most_flux, bool is_land)
 
void impose_most_bcs (const int &lev, const amrex::Vector< amrex::MultiFab * > &mfs, amrex::MultiFab *xxmom_flux, amrex::MultiFab *yymom_flux, amrex::MultiFab *zzmom_flux, amrex::MultiFab *xymom_flux, amrex::MultiFab *yxmom_flux, amrex::MultiFab *xzmom_flux, amrex::MultiFab *zxmom_flux, amrex::MultiFab *yzmom_flux, amrex::MultiFab *zymom_flux, amrex::MultiFab *xheat_flux, amrex::MultiFab *yheat_flux, amrex::MultiFab *zheat_flux, amrex::MultiFab *xqv_flux, amrex::MultiFab *yqv_flux, amrex::MultiFab *zqv_flux, amrex::MultiFab *z_phys)
 
template<typename FluxCalc >
void compute_most_bcs (const int &lev, const amrex::Vector< amrex::MultiFab * > &mfs, amrex::MultiFab *xxmom_flux, amrex::MultiFab *yymom_flux, amrex::MultiFab *zzmom_flux, amrex::MultiFab *xymom_flux, amrex::MultiFab *yxmom_flux, amrex::MultiFab *xzmom_flux, amrex::MultiFab *zxmom_flux, amrex::MultiFab *yzmom_flux, amrex::MultiFab *zymom_flux, amrex::MultiFab *xheat_flux, amrex::MultiFab *yheat_flux, amrex::MultiFab *zheat_flux, amrex::MultiFab *xqv_flux, amrex::MultiFab *yqv_flux, amrex::MultiFab *zqv_flux, amrex::MultiFab *z_phys, const FluxCalc &flux_comp)
 
void time_interp_sst (const int &lev, const amrex::Real &time)
 
void get_lsm_tsurf (const int &lev)
 
void update_pblh (const int &lev, amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars, amrex::MultiFab *z_phys_cc, const int RhoQv_comp, const int RhoQc_comp, const int RhoQr_comp)
 
template<typename PBLHeightEstimator >
void compute_pblh (const int &lev, amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars, amrex::MultiFab *z_phys_cc, const PBLHeightEstimator &est, const int RhoQv_comp, const int RhoQc_comp, const int RhoQr_comp)
 
void read_custom_roughness (const int &lev, const std::string &fname)
 
void update_surf_temp (const amrex::Real &time)
 
void update_mac_ptrs (const int &lev, amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars_old, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &Theta_prim, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &Qv_prim, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &Qr_prim)
 
const amrex::MultiFab * get_u_star (const int &lev)
 
const amrex::MultiFab * get_w_star (const int &lev)
 
const amrex::MultiFab * get_t_star (const int &lev)
 
const amrex::MultiFab * get_q_star (const int &lev)
 
const amrex::MultiFab * get_olen (const int &lev)
 
const amrex::MultiFab * get_pblh (const int &lev)
 
const amrex::MultiFab * get_mac_avg (const int &lev, int comp)
 
const amrex::MultiFab * get_t_surf (const int &lev)
 
amrex::Real get_zref ()
 
amrex::FArrayBox * get_z0 (const int &lev)
 
bool have_variable_sea_roughness ()
 
const amrex::iMultiFab * get_lmask (const int &lev)
 
int lmask_min_reduce (amrex::iMultiFab &lmask, const int &nghost)
 
template<typename FluxCalc >
void compute_most_bcs (const int &lev, const Vector< MultiFab * > &mfs, MultiFab *xxmom_flux, MultiFab *yymom_flux, MultiFab *zzmom_flux, MultiFab *xymom_flux, MultiFab *yxmom_flux, MultiFab *xzmom_flux, MultiFab *zxmom_flux, MultiFab *yzmom_flux, MultiFab *zymom_flux, MultiFab *xheat_flux, MultiFab *yheat_flux, MultiFab *zheat_flux, MultiFab *xqv_flux, MultiFab *yqv_flux, MultiFab *zqv_flux, MultiFab *z_phys, const FluxCalc &flux_comp)
 
template<typename PBLHeightEstimator >
void compute_pblh (const int &lev, Vector< Vector< MultiFab >> &vars, MultiFab *z_phys_cc, const PBLHeightEstimator &est, int RhoQv_comp, int RhoQc_comp, int RhoQr_comp)
 

Public Attributes

FluxCalcType flux_type {FluxCalcType::MOENG}
 
ThetaCalcType theta_type {ThetaCalcType::ADIABATIC}
 
RoughCalcType rough_type_land {RoughCalcType::CONSTANT}
 
RoughCalcType rough_type_sea {RoughCalcType::CHARNOCK}
 
PBLHeightCalcType pblh_type {PBLHeightCalcType::None}
 

Private Attributes

amrex::Vector< amrex::Geometry > m_geom
 
bool m_exp_most = false
 
bool m_rotate = false
 
amrex::Real m_start_bdy_time
 
amrex::Real m_bdy_time_interval
 
bool m_include_wstar = false
 
amrex::Real z0_const {0.1}
 
amrex::Real surf_temp
 
amrex::Real surf_heating_rate {0}
 
amrex::Real surf_temp_flux {0}
 
amrex::Real custom_ustar {0}
 
amrex::Real custom_tstar {0}
 
amrex::Real custom_qstar {0}
 
amrex::Real cnk_a {0.0185}
 
bool cnk_visc {false}
 
amrex::Real depth {30.0}
 
amrex::Vector< amrex::FArrayBox > z_0
 
bool m_var_z0 {false}
 
bool use_moisture
 
MOSTAverage m_ma
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > u_star
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > w_star
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > t_star
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > q_star
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > olen
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > pblh
 
amrex::Vector< std::unique_ptr< amrex::MultiFab > > t_surf
 
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_sst_lev
 
amrex::Vector< amrex::Vector< amrex::iMultiFab * > > m_lmask_lev
 
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_lsm_data_lev
 
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_lsm_flux_lev
 
amrex::Vector< amrex::MultiFab * > m_Hwave_lev
 
amrex::Vector< amrex::MultiFab * > m_Lwave_lev
 
amrex::Vector< amrex::MultiFab * > m_eddyDiffs_lev
 

Detailed Description

Monin-Obukhov surface layer profile

van der Laan, P., Kelly, M. C., & Sørensen, N. N. (2017). A new k-epsilon model consistent with Monin-Obukhov similarity theory. Wind Energy, 20(3), 479–489. https://doi.org/10.1002/we.2017

Consistent with Dyer (1974) formulation from page 57, Chapter 2, Modeling the vertical ABL structure in Modelling of Atmospheric Flow Fields, Demetri P Lalas and Corrado F Ratto, January 1996, https://doi.org/10.1142/2975.

Member Enumeration Documentation

◆ FluxCalcType

enum ABLMost::FluxCalcType
strong
Enumerator
MOENG 

Moeng functional form.

DONELAN 

Donelan functional form.

CUSTOM 

Custom constant flux functional form.

ROTATE 

Terrain rotation flux functional form.

499  {
500  MOENG = 0, ///< Moeng functional form
501  DONELAN, ///< Donelan functional form
502  CUSTOM, ///< Custom constant flux functional form
503  ROTATE ///< Terrain rotation flux functional form
504  };

◆ PBLHeightCalcType

Enumerator
None 
MYNN25 
YSU 
520  {
521  None, MYNN25, YSU
522  };

◆ RoughCalcType

Enumerator
CONSTANT 

Constant z0.

CHARNOCK 
MODIFIED_CHARNOCK 
DONELAN 
WAVE_COUPLED 
512  {
513  CONSTANT = 0, ///< Constant z0
514  CHARNOCK,
515  MODIFIED_CHARNOCK,
516  DONELAN,
517  WAVE_COUPLED
518  };

◆ ThetaCalcType

Enumerator
ADIABATIC 
HEAT_FLUX 

Heat-flux specified.

SURFACE_TEMPERATURE 

Surface temperature specified.

506  {
507  ADIABATIC = 0,
508  HEAT_FLUX, ///< Heat-flux specified
509  SURFACE_TEMPERATURE ///< Surface temperature specified
510  };

Constructor & Destructor Documentation

◆ ABLMost()

ABLMost::ABLMost ( const amrex::Vector< amrex::Geometry > &  geom,
bool &  use_exp_most,
bool &  use_rot_most,
std::string  a_pp_prefix,
amrex::Vector< std::unique_ptr< amrex::MultiFab >> &  Qv_prim,
amrex::Vector< std::unique_ptr< amrex::MultiFab >> &  z_phys_nd,
const TerrainType &  a_terrain_type,
amrex::Real  start_bdy_time = 0.0,
amrex::Real  bdy_time_interval = 0.0 
)
inlineexplicit
43  : m_geom(geom),
44  m_exp_most(use_exp_most),
45  m_rotate(use_rot_most),
46  m_start_bdy_time(start_bdy_time),
47  m_bdy_time_interval(bdy_time_interval),
48  m_ma(geom,(z_phys_nd[0]!=nullptr),a_pp_prefix,a_terrain_type)
49  {
50  // We have a moisture model if Qv_prim is a valid pointer
51  use_moisture = (Qv_prim[0].get());
52 
53  // Get roughness
54  amrex::ParmParse pp("erf");
55  pp.query("most.z0", z0_const);
56 
57  // Specify how to compute the flux
58  if (use_rot_most) {
60  } else {
61  std::string flux_string{"moeng"};
62  pp.query("most.flux_type", flux_string);
63  if (flux_string == "donelan") {
65  } else if (flux_string == "moeng") {
67  } else if (flux_string == "custom") {
69  } else {
70  amrex::Abort("Undefined MOST flux type!");
71  }
72  }
73 
74  // Include w* to handle free convection (Beljaars 1995, QJRMS)
75  pp.query("most.include_wstar", m_include_wstar);
76 
77  std::string pblh_string{"none"};
78  pp.query("most.pblh_calc", pblh_string);
79  if (pblh_string == "none") {
81  } else if (pblh_string == "MYNN25") {
83  } else if (pblh_string == "MYNNEDMF") {
85  } else if (pblh_string == "YSU") {
87  } else {
88  amrex::Abort("Undefined PBLH calc type!");
89  }
90 
91  // Get surface temperature
92  auto erf_st = pp.query("most.surf_temp", surf_temp);
93 
94  // Custom type user must specify the fluxes
97  pp.query("most.ustar", custom_ustar);
98  pp.query("most.tstar", custom_tstar);
99  pp.query("most.qstar", custom_qstar);
100  if (custom_qstar != 0) {
101  AMREX_ASSERT_WITH_MESSAGE(use_moisture, "Specified custom MOST qv flux without moisture model!");
102  }
103  amrex::Print() << "Using specified ustar, tstar, qstar for MOST = "
104  << custom_ustar << " "
105  << custom_tstar << " "
106  << custom_qstar << std::endl;
107 
108  // Specify surface temperature or surface flux
109  } else {
110  if (erf_st) {
112  pp.query("most.surf_heating_rate", surf_heating_rate); // [K/h]
113  surf_heating_rate = surf_heating_rate / 3600.0; // [K/s]
114  if (pp.query("most.surf_temp_flux", surf_temp_flux)) {
115  amrex::Abort("Can only specify one of surf_temp_flux or surf_heating_rate");
116  }
117  } else {
118  pp.query("most.surf_temp_flux", surf_temp_flux);
119  if (pp.query("most.surf_heating_rate", surf_heating_rate)) {
120  amrex::Abort("Can only specify one of surf_temp_flux or surf_heating_rate");
121  }
122  if (std::abs(surf_temp_flux) > std::numeric_limits<amrex::Real>::epsilon()) {
124  } else {
126  }
127  }
128  }
129 
130  // Make sure the inputs file doesn't try to use most.roughness_type
131  std::string bogus_input;
132  if (pp.query("most.roughness_type", bogus_input) > 0) {
133  amrex::Abort("most.roughness_type is deprecated; use most.roughness_type_land and/or most.roughness_type_sea");
134  }
135 
136  // Specify how to compute the surface flux over land (if there is any)
137  std::string rough_land_string{"constant"};
138  pp.query("most.roughness_type_land", rough_land_string);
139  if (rough_land_string == "constant") {
141  } else {
142  amrex::Abort("Undefined MOST roughness type for land!");
143  }
144 
145  // Specify how to compute the surface flux over sea (if there is any)
146  std::string rough_sea_string{"charnock"};
147  pp.query("most.roughness_type_sea", rough_sea_string);
148  if (rough_sea_string == "charnock") {
150  pp.query("most.charnock_constant",cnk_a);
151  pp.query("most.charnock_viscosity",cnk_visc);
152  if (cnk_a > 0) {
153  amrex::Print() << "If there is water, Charnock relation with C_a=" << cnk_a
154  << (cnk_visc? " and viscosity" : "")
155  << " will be used"
156  << std::endl;
157  } else {
158  amrex::Print() << "If there is water, Charnock relation with variable Charnock parameter (COARE3.0)"
159  << (cnk_visc? " and viscosity" : "")
160  << " will be used"
161  << std::endl;
162  }
163  } else if (rough_sea_string == "coare3.0") {
165  amrex::Print() << "If there is water, Charnock relation with variable Charnock parameter (COARE3.0)"
166  << (cnk_visc? " and viscosity" : "")
167  << " will be used"
168  << std::endl;
169  cnk_a = -1;
170  } else if (rough_sea_string == "donelan") {
172  } else if (rough_sea_string == "modified_charnock") {
174  pp.query("most.modified_charnock_depth",depth);
175  } else if (rough_sea_string == "wave_coupled") {
177  } else if (rough_sea_string == "constant") {
179  } else {
180  amrex::Abort("Undefined MOST roughness type for sea!");
181  }
182  } // constructor
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:219
amrex::Real m_bdy_time_interval
Definition: ERF_ABLMost.H:536
amrex::Vector< amrex::Geometry > m_geom
Definition: ERF_ABLMost.H:532
amrex::Real custom_ustar
Definition: ERF_ABLMost.H:543
amrex::Real custom_qstar
Definition: ERF_ABLMost.H:545
amrex::Real depth
Definition: ERF_ABLMost.H:548
amrex::Real surf_heating_rate
Definition: ERF_ABLMost.H:541
MOSTAverage m_ma
Definition: ERF_ABLMost.H:554
@ SURFACE_TEMPERATURE
Surface temperature specified.
@ HEAT_FLUX
Heat-flux specified.
bool cnk_visc
Definition: ERF_ABLMost.H:547
amrex::Real m_start_bdy_time
Definition: ERF_ABLMost.H:535
amrex::Real surf_temp
Definition: ERF_ABLMost.H:540
amrex::Real cnk_a
Definition: ERF_ABLMost.H:546
ThetaCalcType theta_type
Definition: ERF_ABLMost.H:525
PBLHeightCalcType pblh_type
Definition: ERF_ABLMost.H:528
@ MOENG
Moeng functional form.
@ CUSTOM
Custom constant flux functional form.
@ ROTATE
Terrain rotation flux functional form.
@ DONELAN
Donelan functional form.
amrex::Real surf_temp_flux
Definition: ERF_ABLMost.H:542
RoughCalcType rough_type_land
Definition: ERF_ABLMost.H:526
bool m_rotate
Definition: ERF_ABLMost.H:534
RoughCalcType rough_type_sea
Definition: ERF_ABLMost.H:527
bool use_moisture
Definition: ERF_ABLMost.H:552
bool m_include_wstar
Definition: ERF_ABLMost.H:538
bool m_exp_most
Definition: ERF_ABLMost.H:533
amrex::Real z0_const
Definition: ERF_ABLMost.H:539
FluxCalcType flux_type
Definition: ERF_ABLMost.H:524
@ CONSTANT
Constant z0.
amrex::Real custom_tstar
Definition: ERF_ABLMost.H:544
Here is the call graph for this function:

Member Function Documentation

◆ compute_fluxes()

template<typename FluxIter >
void ABLMost::compute_fluxes ( const int &  lev,
const int &  max_iters,
const FluxIter &  most_flux,
bool  is_land 
)

Function to compute the fluxes (u^star and t^star) for Monin Obukhov similarity theory

Parameters
[in]levCurrent level
[in]max_itersmaximum iterations to use
[in]most_fluxstructure to iteratively compute ustar and tstar
149 {
150  // Pointers to the computed averages
151  const auto *const tm_ptr = m_ma.get_average(lev,2); // potential temperature
152  const auto *const qvm_ptr = m_ma.get_average(lev,3); // water vapor mixing ratio
153  const auto *const tvm_ptr = m_ma.get_average(lev,4); // virtual potential temperature
154  const auto *const umm_ptr = m_ma.get_average(lev,5); // horizontal velocity magnitude
155 
156  for (MFIter mfi(*u_star[lev]); mfi.isValid(); ++mfi)
157  {
158  Box gtbx = mfi.growntilebox();
159 
160  auto u_star_arr = u_star[lev]->array(mfi);
161  auto t_star_arr = t_star[lev]->array(mfi);
162  auto q_star_arr = q_star[lev]->array(mfi);
163  auto t_surf_arr = t_surf[lev]->array(mfi);
164  auto olen_arr = olen[lev]->array(mfi);
165 
166  const auto tm_arr = tm_ptr->array(mfi);
167  const auto tvm_arr = tvm_ptr->array(mfi);
168  const auto qvm_arr = qvm_ptr->array(mfi);
169  const auto umm_arr = umm_ptr->array(mfi);
170  const auto z0_arr = z_0[lev].array();
171 
172  // PBL height if we need to calculate wstar for the Beljaars correction
173  // TODO: can/should we apply this in LES mode?
174  const auto w_star_arr = (m_include_wstar) ? w_star[lev].get()->array(mfi) : Array4<Real> {};
175  const auto pblh_arr = (m_include_wstar) ? pblh[lev].get()->array(mfi) : Array4<Real> {};
176 
177  // Wave properties if they exist
178  const auto Hwave_arr = (m_Hwave_lev[lev]) ? m_Hwave_lev[lev]->array(mfi) : Array4<Real> {};
179  const auto Lwave_arr = (m_Lwave_lev[lev]) ? m_Lwave_lev[lev]->array(mfi) : Array4<Real> {};
180  const auto eta_arr = (m_eddyDiffs_lev[lev]) ? m_eddyDiffs_lev[lev]->array(mfi) : Array4<Real> {};
181 
182  // Land mask array if it exists
183  auto lmask_arr = (m_lmask_lev[lev][0]) ? m_lmask_lev[lev][0]->array(mfi) :
184  Array4<int> {};
185 
186  ParallelFor(gtbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
187  {
188  if (( is_land && lmask_arr(i,j,k) == 1) ||
189  (!is_land && lmask_arr(i,j,k) == 0))
190  {
191  most_flux.iterate_flux(i, j, k, max_iters,
192  z0_arr, umm_arr, tm_arr, tvm_arr, qvm_arr,
193  u_star_arr, w_star_arr, // to be updated
194  t_star_arr, q_star_arr, // to be updated
195  t_surf_arr, olen_arr, // to be updated
196  pblh_arr, Hwave_arr, Lwave_arr, eta_arr);
197  }
198  });
199  }
200 }
amrex::Vector< amrex::MultiFab * > m_eddyDiffs_lev
Definition: ERF_ABLMost.H:569
amrex::Vector< std::unique_ptr< amrex::MultiFab > > q_star
Definition: ERF_ABLMost.H:558
amrex::Vector< std::unique_ptr< amrex::MultiFab > > olen
Definition: ERF_ABLMost.H:559
amrex::Vector< std::unique_ptr< amrex::MultiFab > > w_star
Definition: ERF_ABLMost.H:556
amrex::Vector< amrex::FArrayBox > z_0
Definition: ERF_ABLMost.H:549
amrex::Vector< std::unique_ptr< amrex::MultiFab > > t_surf
Definition: ERF_ABLMost.H:561
amrex::Vector< std::unique_ptr< amrex::MultiFab > > pblh
Definition: ERF_ABLMost.H:560
amrex::Vector< amrex::MultiFab * > m_Hwave_lev
Definition: ERF_ABLMost.H:567
amrex::Vector< amrex::Vector< amrex::iMultiFab * > > m_lmask_lev
Definition: ERF_ABLMost.H:564
amrex::Vector< amrex::MultiFab * > m_Lwave_lev
Definition: ERF_ABLMost.H:568
amrex::Vector< std::unique_ptr< amrex::MultiFab > > t_star
Definition: ERF_ABLMost.H:557
amrex::Vector< std::unique_ptr< amrex::MultiFab > > u_star
Definition: ERF_ABLMost.H:555
const amrex::MultiFab * get_average(const int &lev, const int &comp) const
Definition: ERF_MOSTAverage.H:100

◆ compute_most_bcs() [1/2]

template<typename FluxCalc >
void ABLMost::compute_most_bcs ( const int &  lev,
const amrex::Vector< amrex::MultiFab * > &  mfs,
amrex::MultiFab *  xxmom_flux,
amrex::MultiFab *  yymom_flux,
amrex::MultiFab *  zzmom_flux,
amrex::MultiFab *  xymom_flux,
amrex::MultiFab *  yxmom_flux,
amrex::MultiFab *  xzmom_flux,
amrex::MultiFab *  zxmom_flux,
amrex::MultiFab *  yzmom_flux,
amrex::MultiFab *  zymom_flux,
amrex::MultiFab *  xheat_flux,
amrex::MultiFab *  yheat_flux,
amrex::MultiFab *  zheat_flux,
amrex::MultiFab *  xqv_flux,
amrex::MultiFab *  yqv_flux,
amrex::MultiFab *  zqv_flux,
amrex::MultiFab *  z_phys,
const FluxCalc &  flux_comp 
)

◆ compute_most_bcs() [2/2]

template<typename FluxCalc >
void ABLMost::compute_most_bcs ( const int &  lev,
const Vector< MultiFab * > &  mfs,
MultiFab *  xxmom_flux,
MultiFab *  yymom_flux,
MultiFab *  zzmom_flux,
MultiFab *  xymom_flux,
MultiFab *  yxmom_flux,
MultiFab *  xzmom_flux,
MultiFab *  zxmom_flux,
MultiFab *  yzmom_flux,
MultiFab *  zymom_flux,
MultiFab *  xheat_flux,
MultiFab *  yheat_flux,
MultiFab *  zheat_flux,
MultiFab *  xqv_flux,
MultiFab *  yqv_flux,
MultiFab *  zqv_flux,
MultiFab *  z_phys,
const FluxCalc &  flux_comp 
)

Function to calculate MOST fluxes for populating ghost cells.

Parameters
[in]levCurrent level
[in,out]mfsMultifabs to populate
[in]eddyDiffsDiffusion coefficients from turbulence model
[in]flux_compstructure to compute fluxes
306 {
307  const int klo = 0;
308  const int icomp = 0;
309  const auto& dxInv = m_geom[lev].InvCellSizeArray();
310  const auto& dz_no_terrain = m_geom[lev].CellSize(2);
311  for (MFIter mfi(*mfs[0]); mfi.isValid(); ++mfi)
312  {
313  // TODO: No LSM lateral ghost cells, should this change?
314  // Valid CC box
315  Box vbx = mfi.validbox(); vbx.makeSlab(2,klo-1);
316 
317  Box vbxx = surroundingNodes(vbx,0);
318  Box vbxy = surroundingNodes(vbx,1);
319 
320  // Expose for GPU
321  bool exp_most = m_exp_most;
322  bool rot_most = m_rotate;
323 
324  // Get field arrays
325  const auto cons_arr = mfs[Vars::cons]->array(mfi);
326  const auto velx_arr = mfs[Vars::xvel]->array(mfi);
327  const auto vely_arr = mfs[Vars::yvel]->array(mfi);
328  const auto velz_arr = mfs[Vars::zvel]->array(mfi);
329 
330  // Explicit MOST vars
331  auto t13_arr = (m_exp_most) ? xzmom_flux->array(mfi) : Array4<Real>{};
332  auto t31_arr = (m_exp_most && zxmom_flux) ? zxmom_flux->array(mfi) : Array4<Real>{};
333 
334  auto t23_arr = (m_exp_most) ? yzmom_flux->array(mfi) : Array4<Real>{};
335  auto t32_arr = (m_exp_most && zymom_flux) ? zymom_flux->array(mfi) : Array4<Real>{};
336 
337  auto hfx3_arr = (m_exp_most) ? zheat_flux->array(mfi) : Array4<Real>{};
338  auto qfx3_arr = (m_exp_most && zqv_flux) ? zqv_flux->array(mfi) : Array4<Real>{};
339 
340  // Rotated MOST vars
341  auto t11_arr = (m_rotate) ? xxmom_flux->array(mfi) : Array4<Real>{};
342  auto t22_arr = (m_rotate) ? yymom_flux->array(mfi) : Array4<Real>{};
343  auto t33_arr = (m_rotate) ? zzmom_flux->array(mfi) : Array4<Real>{};
344  auto t12_arr = (m_rotate) ? xymom_flux->array(mfi) : Array4<Real>{};
345  auto t21_arr = (m_rotate) ? yxmom_flux->array(mfi) : Array4<Real>{};
346 
347  auto hfx1_arr = (m_rotate) ? xheat_flux->array(mfi) : Array4<Real>{};
348  auto hfx2_arr = (m_rotate) ? yheat_flux->array(mfi) : Array4<Real>{};
349  auto qfx1_arr = (m_rotate && xqv_flux) ? xqv_flux->array(mfi) : Array4<Real>{};
350  auto qfx2_arr = (m_rotate && yqv_flux) ? yqv_flux->array(mfi) : Array4<Real>{};
351 
352  // Viscosity and terrain
353  const auto eta_arr = (!m_exp_most) ? m_eddyDiffs_lev[lev]->array(mfi) : Array4<const Real>{};
354  const auto zphys_arr = (z_phys) ? z_phys->const_array(mfi) : Array4<const Real>{};
355 
356  // Get average arrays
357  const auto *const u_mean = m_ma.get_average(lev,0);
358  const auto *const v_mean = m_ma.get_average(lev,1);
359  const auto *const t_mean = m_ma.get_average(lev,2);
360  const auto *const q_mean = m_ma.get_average(lev,3);
361  const auto *const u_mag_mean = m_ma.get_average(lev,5);
362 
363  const auto um_arr = u_mean->array(mfi);
364  const auto vm_arr = v_mean->array(mfi);
365  const auto tm_arr = t_mean->array(mfi);
366  const auto qm_arr = q_mean->array(mfi);
367  const auto umm_arr = u_mag_mean->array(mfi);
368 
369  // Get derived arrays
370  const auto u_star_arr = u_star[lev]->array(mfi);
371  const auto t_star_arr = t_star[lev]->array(mfi);
372  const auto q_star_arr = q_star[lev]->array(mfi);
373  const auto t_surf_arr = t_surf[lev]->array(mfi);
374 
375  // Get LSM fluxes
376  auto lmask_arr = (m_lmask_lev[lev][0]) ? m_lmask_lev[lev][0]->array(mfi) :
377  Array4<int> {};
378  auto lsm_flux_arr = (m_lsm_flux_lev[lev][0]) ? m_lsm_flux_lev[lev][0]->array(mfi) :
379  Array4<Real> {};
380 
381  for (int var_idx = 0; var_idx < Vars::NumTypes; ++var_idx)
382  {
383  const Box& bx = (*mfs[var_idx])[mfi].box();
384  auto dest_arr = (*mfs[var_idx])[mfi].array();
385 
386  if (var_idx == Vars::cons) {
387  Box b2d = bx;
388  b2d.setBig(2,klo-1);
389  int n = RhoTheta_comp;
390  ParallelFor(b2d, [=] AMREX_GPU_DEVICE (int i, int j, int k)
391  {
392  Real dz = (zphys_arr) ? ( zphys_arr(i,j,klo ) - zphys_arr(i,j,klo-1) ) : dz_no_terrain;
393  Real dz1 = (zphys_arr) ? ( zphys_arr(i,j,klo+1) - zphys_arr(i,j,klo ) ) : dz_no_terrain;
394  Real Tflux = flux_comp.compute_t_flux(i, j, k, n, icomp, dz, dz1, exp_most, eta_arr,
395  cons_arr, velx_arr, vely_arr,
396  umm_arr, tm_arr, u_star_arr, t_star_arr, t_surf_arr,
397  dest_arr);
398 
399  if (rot_most) {
400  rotate_scalar_flux(i, j, klo, Tflux, dxInv, zphys_arr,
401  hfx1_arr, hfx2_arr, hfx3_arr);
402  } else {
403  int is_land = (lmask_arr) ? lmask_arr(i,j,klo) : 1;
404  if (is_land && lsm_flux_arr && vbx.contains(i,j,k)) {
405  lsm_flux_arr(i,j,klo) = Tflux;
406  }
407  else if ((k == klo-1) && vbx.contains(i,j,k) && exp_most) {
408  hfx3_arr(i,j,klo) = Tflux;
409  }
410  }
411  });
412 
413  // TODO: Generalize MOST q flux
415  n = RhoQ1_comp;
416  ParallelFor(b2d, [=] AMREX_GPU_DEVICE (int i, int j, int k)
417  {
418  Real dz = (zphys_arr) ? ( zphys_arr(i,j,klo ) - zphys_arr(i,j,klo-1) ) : dz_no_terrain;
419  Real dz1 = (zphys_arr) ? ( zphys_arr(i,j,klo+1) - zphys_arr(i,j,klo ) ) : dz_no_terrain;
420  Real Qflux = flux_comp.compute_q_flux(i, j, k, n, icomp, dz, dz1, exp_most, eta_arr,
421  cons_arr, velx_arr, vely_arr,
422  umm_arr, qm_arr, u_star_arr, q_star_arr, t_surf_arr,
423  dest_arr);
424 
425  if (rot_most) {
426  rotate_scalar_flux(i, j, klo, Qflux, dxInv, zphys_arr,
427  qfx1_arr, qfx2_arr, qfx3_arr);
428  } else {
429  if ((k == klo-1) && vbx.contains(i,j,k) && exp_most) {
430  qfx3_arr(i,j,klo) = Qflux;
431  }
432  }
433  });
434  }
435 
436  } else if (var_idx == Vars::xvel) {
437 
438  Box xb2d = surroundingNodes(bx,0);
439  xb2d.setBig(2,klo-1);
440 
441  ParallelFor(xb2d, [=] AMREX_GPU_DEVICE (int i, int j, int k)
442  {
443  Real dz = (zphys_arr) ? ( zphys_arr(i,j,klo ) - zphys_arr(i,j,klo-1) ) : dz_no_terrain;
444  Real dz1 = (zphys_arr) ? ( zphys_arr(i,j,klo+1) - zphys_arr(i,j,klo ) ) : dz_no_terrain;
445  Real stressx = flux_comp.compute_u_flux(i, j, k, icomp, dz, dz1, exp_most, eta_arr,
446  cons_arr, velx_arr, vely_arr,
447  umm_arr, um_arr, u_star_arr,
448  dest_arr);
449 
450  if (rot_most) {
451  rotate_stress_tensor(i, j, klo, stressx, dxInv, zphys_arr,
452  velx_arr, vely_arr, velz_arr,
453  t11_arr, t22_arr, t33_arr,
454  t12_arr, t21_arr,
455  t13_arr, t31_arr,
456  t23_arr, t32_arr);
457  } else {
458  if ((k == klo-1) && vbxx.contains(i,j,k) && exp_most) {
459  t13_arr(i,j,klo) = stressx;
460  if (t31_arr) t31_arr(i,j,klo) = stressx;
461  }
462  }
463  });
464 
465  } else if (var_idx == Vars::yvel) {
466 
467  Box yb2d = surroundingNodes(bx,1);
468  yb2d.setBig(2,klo-1);
469 
470  ParallelFor(yb2d, [=] AMREX_GPU_DEVICE (int i, int j, int k)
471  {
472  Real dz = (zphys_arr) ? ( zphys_arr(i,j,klo ) - zphys_arr(i,j,klo-1) ) : dz_no_terrain;
473  Real dz1 = (zphys_arr) ? ( zphys_arr(i,j,klo+1) - zphys_arr(i,j,klo ) ) : dz_no_terrain;
474  Real stressy = flux_comp.compute_v_flux(i, j, k, icomp, dz, dz1, exp_most, eta_arr,
475  cons_arr, velx_arr, vely_arr,
476  umm_arr, vm_arr, u_star_arr,
477  dest_arr);
478 
479  // NOTE: One stress rotation for ALL the stress components
480  if (!rot_most) {
481  if ((k == klo-1) && vbxy.contains(i,j,k) && exp_most) {
482  t23_arr(i,j,klo) = stressy;
483  if (t32_arr) t32_arr(i,j,klo) = stressy;
484  }
485  }
486  });
487  }
488  } // var_idx
489  } // mfiter
490 }
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:42
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void rotate_scalar_flux(const int &i, const int &j, const int &klo, const amrex::Real &flux, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxInv, const amrex::Array4< const amrex::Real > &zphys_arr, const amrex::Array4< amrex::Real > &phi1_arr, const amrex::Array4< amrex::Real > &phi2_arr, const amrex::Array4< amrex::Real > &phi3_arr)
Definition: ERF_TerrainMetrics.H:461
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void rotate_stress_tensor(const int &i, const int &j, const int &klo, const amrex::Real &flux, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxInv, const amrex::Array4< const amrex::Real > &zphys_arr, const amrex::Array4< const amrex::Real > &u_arr, const amrex::Array4< const amrex::Real > &v_arr, const amrex::Array4< const amrex::Real > &w_arr, const amrex::Array4< amrex::Real > &tau11_arr, const amrex::Array4< amrex::Real > &tau22_arr, const amrex::Array4< amrex::Real > &tau33_arr, const amrex::Array4< amrex::Real > &tau12_arr, const amrex::Array4< amrex::Real > &tau21_arr, const amrex::Array4< amrex::Real > &tau13_arr, const amrex::Array4< amrex::Real > &tau31_arr, const amrex::Array4< amrex::Real > &tau23_arr, const amrex::Array4< amrex::Real > &tau32_arr)
Definition: ERF_TerrainMetrics.H:482
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_lsm_flux_lev
Definition: ERF_ABLMost.H:566
@ xvel
Definition: ERF_IndexDefines.H:141
@ cons
Definition: ERF_IndexDefines.H:140
@ zvel
Definition: ERF_IndexDefines.H:143
@ NumTypes
Definition: ERF_IndexDefines.H:144
@ yvel
Definition: ERF_IndexDefines.H:142
Here is the call graph for this function:

◆ compute_pblh() [1/2]

template<typename PBLHeightEstimator >
void ABLMost::compute_pblh ( const int &  lev,
amrex::Vector< amrex::Vector< amrex::MultiFab >> &  vars,
amrex::MultiFab *  z_phys_cc,
const PBLHeightEstimator &  est,
const int  RhoQv_comp,
const int  RhoQc_comp,
const int  RhoQr_comp 
)

◆ compute_pblh() [2/2]

template<typename PBLHeightEstimator >
void ABLMost::compute_pblh ( const int &  lev,
Vector< Vector< MultiFab >> &  vars,
MultiFab *  z_phys_cc,
const PBLHeightEstimator &  est,
int  RhoQv_comp,
int  RhoQc_comp,
int  RhoQr_comp 
)
585 {
586  est.compute_pblh(m_geom[lev],z_phys_cc, pblh[lev].get(),
587  vars[lev][Vars::cons],m_lmask_lev[lev][0],
588  RhoQv_comp, RhoQc_comp, RhoQr_comp);
589 }

◆ get_lmask()

const amrex::iMultiFab* ABLMost::get_lmask ( const int &  lev)
inline
477 { return m_lmask_lev[lev][0]; }

◆ get_lsm_tsurf()

void ABLMost::get_lsm_tsurf ( const int &  lev)
529 {
530  for (MFIter mfi(*t_surf[lev]); mfi.isValid(); ++mfi)
531  {
532  Box gtbx = mfi.growntilebox();
533 
534  // TODO: LSM does not carry lateral ghost cells.
535  // This copies the valid box into the ghost cells.
536  // Fillboundary is called after this to pick up the
537  // interior ghost and periodic directions. Is there
538  // a better approach?
539  Box vbx = mfi.validbox();
540  int i_lo = vbx.smallEnd(0); int i_hi = vbx.bigEnd(0);
541  int j_lo = vbx.smallEnd(1); int j_hi = vbx.bigEnd(1);
542 
543  auto t_surf_arr = t_surf[lev]->array(mfi);
544  auto lmask_arr = (m_lmask_lev[lev][0]) ? m_lmask_lev[lev][0]->array(mfi) :
545  Array4<int> {};
546  const auto lsm_arr = m_lsm_data_lev[lev][0]->const_array(mfi);
547 
548  ParallelFor(gtbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
549  {
550  int is_land = (lmask_arr) ? lmask_arr(i,j,k) : 1;
551  if (is_land) {
552  int li = amrex::min(amrex::max(i, i_lo), i_hi);
553  int lj = amrex::min(amrex::max(j, j_lo), j_hi);
554  t_surf_arr(i,j,k) = lsm_arr(li,lj,k);
555  }
556  });
557  }
558 }
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_lsm_data_lev
Definition: ERF_ABLMost.H:565

◆ get_mac_avg()

const amrex::MultiFab* ABLMost::get_mac_avg ( const int &  lev,
int  comp 
)
inline
463 { return m_ma.get_average(lev,comp); }
Here is the call graph for this function:

◆ get_olen()

const amrex::MultiFab* ABLMost::get_olen ( const int &  lev)
inline
457 { return olen[lev].get(); }

◆ get_pblh()

const amrex::MultiFab* ABLMost::get_pblh ( const int &  lev)
inline
460 { return pblh[lev].get(); }

◆ get_q_star()

const amrex::MultiFab* ABLMost::get_q_star ( const int &  lev)
inline
454 { return q_star[lev].get(); }

◆ get_t_star()

const amrex::MultiFab* ABLMost::get_t_star ( const int &  lev)
inline
451 { return t_star[lev].get(); }

◆ get_t_surf()

const amrex::MultiFab* ABLMost::get_t_surf ( const int &  lev)
inline
466 { return t_surf[lev].get(); }

◆ get_u_star()

const amrex::MultiFab* ABLMost::get_u_star ( const int &  lev)
inline
445 { return u_star[lev].get(); }

◆ get_w_star()

const amrex::MultiFab* ABLMost::get_w_star ( const int &  lev)
inline
448 { return w_star[lev].get(); }

◆ get_z0()

amrex::FArrayBox* ABLMost::get_z0 ( const int &  lev)
inline
472 { return &z_0[lev]; }

◆ get_zref()

amrex::Real ABLMost::get_zref ( )
inline
469 { return m_ma.get_zref(); }
amrex::Real get_zref() const
Definition: ERF_MOSTAverage.H:103
Here is the call graph for this function:

◆ have_variable_sea_roughness()

bool ABLMost::have_variable_sea_roughness ( )
inline
474 { return m_var_z0; }
bool m_var_z0
Definition: ERF_ABLMost.H:550

◆ impose_most_bcs()

void ABLMost::impose_most_bcs ( const int &  lev,
const amrex::Vector< amrex::MultiFab * > &  mfs,
amrex::MultiFab *  xxmom_flux,
amrex::MultiFab *  yymom_flux,
amrex::MultiFab *  zzmom_flux,
amrex::MultiFab *  xymom_flux,
amrex::MultiFab *  yxmom_flux,
amrex::MultiFab *  xzmom_flux,
amrex::MultiFab *  zxmom_flux,
amrex::MultiFab *  yzmom_flux,
amrex::MultiFab *  zymom_flux,
amrex::MultiFab *  xheat_flux,
amrex::MultiFab *  yheat_flux,
amrex::MultiFab *  zheat_flux,
amrex::MultiFab *  xqv_flux,
amrex::MultiFab *  yqv_flux,
amrex::MultiFab *  zqv_flux,
amrex::MultiFab *  z_phys 
)

Wrapper to impose Monin Obukhov similarity theory fluxes by populating ghost cells.

Parameters
[in]levCurrent level
[in,out]mfsMultifabs to populate
[in]eddyDiffsDiffusion coefficients from turbulence model
226 {
227  const int klo = 0;
229  moeng_flux flux_comp(klo);
230  compute_most_bcs(lev, mfs,
231  xxmom_flux,
232  yymom_flux,
233  zzmom_flux,
234  xymom_flux, yxmom_flux,
235  xzmom_flux, zxmom_flux,
236  yzmom_flux, zymom_flux,
237  xheat_flux, yheat_flux, zheat_flux,
238  xqv_flux, yqv_flux, zqv_flux,
239  z_phys, flux_comp);
240  } else if (flux_type == FluxCalcType::DONELAN) {
241  donelan_flux flux_comp(klo);
242  compute_most_bcs(lev, mfs,
243  xxmom_flux,
244  yymom_flux,
245  zzmom_flux,
246  xymom_flux, yxmom_flux,
247  xzmom_flux, zxmom_flux,
248  yzmom_flux, zymom_flux,
249  xheat_flux, yheat_flux, zheat_flux,
250  xqv_flux, yqv_flux, zqv_flux,
251  z_phys, flux_comp);
252  } else if (flux_type == FluxCalcType::ROTATE) {
253  rotate_flux flux_comp(klo);
254  compute_most_bcs(lev, mfs,
255  xxmom_flux,
256  yymom_flux,
257  zzmom_flux,
258  xymom_flux, yxmom_flux,
259  xzmom_flux, zxmom_flux,
260  yzmom_flux, zymom_flux,
261  xheat_flux, yheat_flux, zheat_flux,
262  xqv_flux, yqv_flux, zqv_flux,
263  z_phys, flux_comp);
264  } else {
265  custom_flux flux_comp(klo);
266  compute_most_bcs(lev, mfs,
267  xxmom_flux,
268  yymom_flux,
269  zzmom_flux,
270  xymom_flux, yxmom_flux,
271  xzmom_flux, zxmom_flux,
272  yzmom_flux, zymom_flux,
273  xheat_flux, yheat_flux, zheat_flux,
274  xqv_flux, yqv_flux, zqv_flux,
275  z_phys, flux_comp);
276  }
277 }
void compute_most_bcs(const int &lev, const amrex::Vector< amrex::MultiFab * > &mfs, amrex::MultiFab *xxmom_flux, amrex::MultiFab *yymom_flux, amrex::MultiFab *zzmom_flux, amrex::MultiFab *xymom_flux, amrex::MultiFab *yxmom_flux, amrex::MultiFab *xzmom_flux, amrex::MultiFab *zxmom_flux, amrex::MultiFab *yzmom_flux, amrex::MultiFab *zymom_flux, amrex::MultiFab *xheat_flux, amrex::MultiFab *yheat_flux, amrex::MultiFab *zheat_flux, amrex::MultiFab *xqv_flux, amrex::MultiFab *yqv_flux, amrex::MultiFab *zqv_flux, amrex::MultiFab *z_phys, const FluxCalc &flux_comp)
Definition: ERF_MOSTStress.H:1849
Definition: ERF_MOSTStress.H:1568
Definition: ERF_MOSTStress.H:1260
Definition: ERF_MOSTStress.H:2106

◆ lmask_min_reduce()

int ABLMost::lmask_min_reduce ( amrex::iMultiFab &  lmask,
const int &  nghost 
)
inline
481  {
482  int lmask_min = amrex::ReduceMin(lmask, nghost,
483  [=] AMREX_GPU_HOST_DEVICE (amrex::Box const& bx, amrex::Array4<int const> const& lm_arr) -> int
484  {
485  int locmin = std::numeric_limits<int>::max();
486  const auto lo = lbound(bx);
487  const auto hi = ubound(bx);
488  for (int j = lo.y; j <= hi.y; ++j) {
489  for (int i = lo.x; i <= hi.x; ++i) {
490  locmin = std::min(locmin, lm_arr(i,j,0));
491  }
492  }
493  return locmin;
494  });
495 
496  return lmask_min;
497  }

Referenced by make_MOST_at_level().

Here is the caller graph for this function:

◆ make_MOST_at_level()

void ABLMost::make_MOST_at_level ( const int &  lev,
int  nlevs,
const amrex::Vector< amrex::MultiFab * > &  mfv,
std::unique_ptr< amrex::MultiFab > &  Theta_prim,
std::unique_ptr< amrex::MultiFab > &  Qv_prim,
std::unique_ptr< amrex::MultiFab > &  Qr_prim,
std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
amrex::MultiFab *  Hwave,
amrex::MultiFab *  Lwave,
amrex::MultiFab *  eddyDiffs,
amrex::Vector< amrex::MultiFab * >  lsm_data,
amrex::Vector< amrex::MultiFab * >  lsm_flux,
amrex::Vector< std::unique_ptr< amrex::MultiFab >> &  sst_lev,
amrex::Vector< std::unique_ptr< amrex::iMultiFab >> &  lmask_lev 
)
inline
199  {
200  // Update MOST Average
201  m_ma.make_MOSTAverage_at_level(lev, mfv, Theta_prim, Qv_prim, Qr_prim, z_phys_nd);
202 
203  // Get CC vars
204  amrex::MultiFab& mf = *(mfv[0]);
205 
206  // Get surface temperature
207  amrex::ParmParse pp("erf");
208  auto erf_st = pp.query("most.surf_temp", surf_temp);
209 
210  // Do we have a time-varying surface roughness that needs to be saved?
211  if (lev == 0)
212  {
213  const int nghost = 0; // ghost cells not included
214  int lmask_min = lmask_min_reduce(*lmask_lev[0].get(), nghost);
215  amrex::ParallelDescriptor::ReduceIntMin(lmask_min);
216 
217  m_var_z0 = (lmask_min < 1) & (rough_type_sea != RoughCalcType::CONSTANT);
218  if (m_var_z0) {
219  std::string rough_sea_string{"charnock"};
220  pp.query("most.roughness_type_sea", rough_sea_string);
221  amrex::Print() << "Variable sea roughness (type " << rough_sea_string << ")" << std::endl;
222  }
223  }
224 
225  if ( (lev == 0) || (lev > nlevs-1) ) {
226  m_Hwave_lev.resize(nlevs);
227  m_Lwave_lev.resize(nlevs);
228  m_eddyDiffs_lev.resize(nlevs);
229 
230  m_lsm_data_lev.resize(nlevs);
231  m_lsm_flux_lev.resize(nlevs);
232 
233  m_sst_lev.resize(nlevs);
234  m_lmask_lev.resize(nlevs);
235 
236  // Size the MOST params for all levels
237  z_0.resize(nlevs);
238  u_star.resize(nlevs);
239  w_star.resize(nlevs);
240  t_star.resize(nlevs);
241  q_star.resize(nlevs);
242  t_surf.resize(nlevs);
243  olen.resize(nlevs);
244  pblh.resize(nlevs);
245  }
246 
247 
248  // Get pointers to SST and LANDMASK data
249  int nt_tot_sst = sst_lev.size();
250  m_sst_lev[lev].resize(nt_tot_sst);
251  for (int nt(0); nt<nt_tot_sst; ++nt) {
252  m_sst_lev[lev][nt] = sst_lev[nt].get();
253  }
254  int nt_tot_lmask = lmask_lev.size();
255  m_lmask_lev[lev].resize(nt_tot_lmask);
256  for (int nt(0); nt<nt_tot_lmask; ++nt) {
257  m_lmask_lev[lev][nt] = lmask_lev[nt].get();
258  }
259 
260  // Get pointers to wave data
261  m_Hwave_lev[lev] = Hwave;
262  m_Lwave_lev[lev] = Lwave;
263  m_eddyDiffs_lev[lev] = eddyDiffs;
264 
265  // Get pointers to LSM data and Fluxes
266  int nvar = lsm_data.size();
267  m_lsm_data_lev[lev].resize(nvar);
268  m_lsm_flux_lev[lev].resize(nvar);
269  for (int n(0); n<nvar; ++n) {
270  m_lsm_data_lev[lev][n] = lsm_data[n];
271  m_lsm_flux_lev[lev][n] = lsm_flux[n];
272  }
273 
274  // Check if there is a user-specified roughness file to be read
275  std::string fname;
276  bool read_z0 = false;
277  if ( (flux_type == FluxCalcType::MOENG) ||
279  read_z0 = pp.query("most.roughness_file_name", fname);
280  }
281 
282  // Attributes for MFs and FABs
283  //--------------------------------------------------------
284  // Create a 2D ba, dm, & ghost cells
285  amrex::BoxArray ba = mf.boxArray();
286  amrex::BoxList bl2d = ba.boxList();
287  for (auto& b : bl2d) {
288  b.setRange(2,0);
289  }
290  amrex::BoxArray ba2d(std::move(bl2d));
291  const amrex::DistributionMapping& dm = mf.DistributionMap();
292  const int ncomp = 1;
293  amrex::IntVect ng = mf.nGrowVect(); ng[2]=0;
294 
295  // Z0 heights FAB
296  //--------------------------------------------------------
297  amrex::Arena* Arena_Used = amrex::The_Arena();
298 #ifdef AMREX_USE_GPU
299  Arena_Used = amrex::The_Pinned_Arena();
300 #endif
301  amrex::Box bx = amrex::grow(m_geom[lev].Domain(),ng);
302  bx.setSmall(2,0);
303  bx.setBig(2,0);
304  z_0[lev].resize(bx,1,Arena_Used);
305  z_0[lev].setVal<amrex::RunOn::Device>(z0_const);
306  if (read_z0) read_custom_roughness(lev,fname);
307 
308  // 2D MFs for U*, T*, T_surf
309  //--------------------------------------------------------
310  u_star[lev] = std::make_unique<amrex::MultiFab>(ba2d,dm,ncomp,ng);
311  u_star[lev]->setVal(1.E34);
312 
313  w_star[lev] = std::make_unique<amrex::MultiFab>(ba2d,dm,ncomp,ng);
314  w_star[lev]->setVal(1.E34);
315 
316  t_star[lev] = std::make_unique<amrex::MultiFab>(ba2d,dm,ncomp,ng);
317  t_star[lev]->setVal(0.0); // default to neutral
318 
319  q_star[lev] = std::make_unique<amrex::MultiFab>(ba2d,dm,ncomp,ng);
320  q_star[lev]->setVal(0.0); // default to dry
321 
322  olen[lev] = std::make_unique<amrex::MultiFab>(ba2d,dm,ncomp,ng);
323  olen[lev]->setVal(1.E34);
324 
325  pblh[lev] = std::make_unique<amrex::MultiFab>(ba2d,dm,ncomp,ng);
326  pblh[lev]->setVal(1.E34);
327 
328  t_surf[lev] = std::make_unique<amrex::MultiFab>(ba2d,dm,ncomp,ng);
329 
330  // TODO: Do we want lsm_data to have theta at 0 index always?
331  // Do we want an external enum struct for indexing?
332  if (m_sst_lev[lev][0] || m_lsm_data_lev[lev][0]) {
333  // Valid SST or LSM data; t_surf set before computing fluxes (avoids extended lambda capture)
335  } else if (erf_st) {
336  t_surf[lev]->setVal(surf_temp);
337  } else {
338  t_surf[lev]->setVal(0.0);
339  }
340  }
int lmask_min_reduce(amrex::iMultiFab &lmask, const int &nghost)
Definition: ERF_ABLMost.H:480
void read_custom_roughness(const int &lev, const std::string &fname)
Definition: ERF_ABLMost.cpp:592
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_sst_lev
Definition: ERF_ABLMost.H:563
void make_MOSTAverage_at_level(const int &lev, const amrex::Vector< amrex::MultiFab * > &vars_old, std::unique_ptr< amrex::MultiFab > &Theta_prim, std::unique_ptr< amrex::MultiFab > &Qv_prim, std::unique_ptr< amrex::MultiFab > &Qr_prim, std::unique_ptr< amrex::MultiFab > &z_phys_nd)
Definition: ERF_MOSTAverage.cpp:68
Here is the call graph for this function:

◆ read_custom_roughness()

void ABLMost::read_custom_roughness ( const int &  lev,
const std::string &  fname 
)
594 {
595  // Read the file if we are on the coarsest level
596  if (lev==0) {
597  // Only the ioproc reads the file and broadcasts
598  if (ParallelDescriptor::IOProcessor()) {
599  Print()<<"Reading MOST roughness file: "<< fname << std::endl;
600  std::ifstream file(fname);
601  Gpu::HostVector<Real> m_x,m_y,m_z0;
602  Real value1,value2,value3;
603  while(file>>value1>>value2>>value3){
604  m_x.push_back(value1);
605  m_y.push_back(value2);
606  m_z0.push_back(value3);
607  }
608  file.close();
609 
610  // Copy data to the GPU
611  int nnode = m_x.size();
612  Gpu::DeviceVector<Real> d_x(nnode),d_y(nnode),d_z0(nnode);
613  Gpu::copy(Gpu::hostToDevice, m_x.begin(), m_x.end(), d_x.begin());
614  Gpu::copy(Gpu::hostToDevice, m_y.begin(), m_y.end(), d_y.begin());
615  Gpu::copy(Gpu::hostToDevice, m_z0.begin(), m_z0.end(), d_z0.begin());
616  Real* xp = d_x.data();
617  Real* yp = d_y.data();
618  Real* z0p = d_z0.data();
619 
620  // Populate z_phys data
621  Real tol = 1.0e-4;
622  auto dx = m_geom[lev].CellSizeArray();
623  auto ProbLoArr = m_geom[lev].ProbLoArray();
624  int ilo = m_geom[lev].Domain().smallEnd(0);
625  int jlo = m_geom[lev].Domain().smallEnd(1);
626  int klo = 0;
627  int ihi = m_geom[lev].Domain().bigEnd(0);
628  int jhi = m_geom[lev].Domain().bigEnd(1);
629 
630  // Grown box with no z range
631  Box xybx = z_0[lev].box();
632  xybx.setRange(2,0);
633 
634  Array4<Real> const& z0_arr = z_0[lev].array();
635  ParallelFor(xybx, [=] AMREX_GPU_DEVICE (int i, int j, int /*k*/)
636  {
637  // Clip indices for ghost-cells
638  int ii = amrex::min(amrex::max(i,ilo),ihi);
639  int jj = amrex::min(amrex::max(j,jlo),jhi);
640 
641  // Location of nodes
642  Real x = ProbLoArr[0] + ii * dx[0];
643  Real y = ProbLoArr[1] + jj * dx[1];
644  int inode = ii + jj * (ihi-ilo+2); // stride is Nx+1
645  if (std::sqrt(std::pow(x-xp[inode],2)+std::pow(y-yp[inode],2)) < tol) {
646  z0_arr(i,j,klo) = z0p[inode];
647  } else {
648  // Unexpected list order, do brute force search
649  Real z0loc = 0.0;
650  bool found = false;
651  for (int n=0; n<nnode; ++n) {
652  Real delta=std::sqrt(std::pow(x-xp[n],2)+std::pow(y-yp[n],2));
653  if (delta < tol) {
654  found = true;
655  z0loc = z0p[n];
656  break;
657  }
658  }
659  AMREX_ASSERT_WITH_MESSAGE(found, "Location read from terrain file does not match the grid!");
660  amrex::ignore_unused(found);
661  z0_arr(i,j,klo) = z0loc;
662  }
663  });
664  } // Is ioproc
665 
666  int ioproc = ParallelDescriptor::IOProcessorNumber();
667  ParallelDescriptor::Barrier();
668  ParallelDescriptor::Bcast(z_0[lev].dataPtr(),z_0[lev].box().numPts(),ioproc);
669  } else {
670  // Create a BC mapper that uses FOEXTRAP at domain bndry
671  Vector<int> bc_lo(3,ERFBCType::foextrap);
672  Vector<int> bc_hi(3,ERFBCType::foextrap);
673  Vector<BCRec> bcr; bcr.push_back(BCRec(bc_lo.data(),bc_hi.data()));
674 
675  // Create ref ratio
676  IntVect ratio;
677  for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
678  ratio[idim] = m_geom[lev].Domain().length(idim) / m_geom[0].Domain().length(idim);
679  }
680 
681  // Create interp object and interpolate from the coarsest grid
682  Interpolater* interp = &cell_cons_interp;
683  interp->interp(z_0[0] , 0,
684  z_0[lev], 0,
685  1, z_0[lev].box(),
686  ratio, m_geom[0], m_geom[lev],
687  bcr, 0, 0, RunOn::Gpu);
688  }
689 }
@ foextrap
Definition: ERF_IndexDefines.H:190

Referenced by make_MOST_at_level().

Here is the caller graph for this function:

◆ time_interp_sst()

void ABLMost::time_interp_sst ( const int &  lev,
const amrex::Real &  time 
)
495 {
496  // Time interpolation
497  Real dT = m_bdy_time_interval;
498  Real time_since_start = time - m_start_bdy_time;
499  int n_time = static_cast<int>( time_since_start / dT);
500  Real alpha = (time_since_start - n_time * dT) / dT;
501  AMREX_ALWAYS_ASSERT( alpha >= 0. && alpha <= 1.0);
502  Real oma = 1.0 - alpha;
503  AMREX_ALWAYS_ASSERT( (n_time >= 0) && (n_time < (m_sst_lev[lev].size()-1)));
504 
505  // Populate t_surf
506  for (MFIter mfi(*t_surf[lev]); mfi.isValid(); ++mfi)
507  {
508  Box gtbx = mfi.growntilebox();
509 
510  auto t_surf_arr = t_surf[lev]->array(mfi);
511  const auto sst_hi_arr = m_sst_lev[lev][n_time+1]->const_array(mfi);
512  const auto sst_lo_arr = m_sst_lev[lev][n_time ]->const_array(mfi);
513  auto lmask_arr = (m_lmask_lev[lev][0]) ? m_lmask_lev[lev][0]->array(mfi) :
514  Array4<int> {};
515 
516  ParallelFor(gtbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
517  {
518  int is_land = (lmask_arr) ? lmask_arr(i,j,k) : 1;
519  if (!is_land) {
520  t_surf_arr(i,j,k) = oma * sst_lo_arr(i,j,k)
521  + alpha * sst_hi_arr(i,j,k);
522  }
523  });
524  }
525 }

◆ update_fluxes()

void ABLMost::update_fluxes ( const int &  lev,
const amrex::Real &  time,
int  max_iters = 25 
)

Wrapper to update ustar and tstar for Monin Obukhov similarity theory.

Parameters
[in]levCurrent level
[in]max_itersmaximum iterations to use
15 {
16  // Update SST data if we have a valid pointer
17  if (m_sst_lev[lev][0]) time_interp_sst(lev, time);
18 
19  // TODO: we want 0 index to always be theta?
20  // Update land surface temp if we have a valid pointer
21  if (m_lsm_data_lev[lev][0]) get_lsm_tsurf(lev);
22 
23  // Fill interior ghost cells
24  t_surf[lev]->FillBoundary(m_geom[lev].periodicity());
25 
26  // Compute plane averages for all vars (regardless of flux type)
28 
29  // ***************************************************************
30  // Iterate the fluxes if moeng type
31  // First iterate over land -- the only model for surface roughness
32  // over land is RoughCalcType::CONSTANT
33  // ***************************************************************
36  bool is_land = true;
40  compute_fluxes(lev, max_iters, most_flux, is_land);
41  } else {
42  amrex::Abort("Unknown value for rough_type_land");
43  }
45  update_surf_temp(time);
48  compute_fluxes(lev, max_iters, most_flux, is_land);
49  } else {
50  amrex::Abort("Unknown value for rough_type_land");
51  }
52  } else if (theta_type == ThetaCalcType::ADIABATIC) {
54  adiabatic most_flux(m_ma.get_zref(), surf_temp_flux);
55  compute_fluxes(lev, max_iters, most_flux, is_land);
56  } else {
57  amrex::Abort("Unknown value for rough_type_land");
58  }
59  } else {
60  amrex::Abort("Unknown value for theta_type");
61  }
62  } // MOENG -- LAND
63 
64  // ***************************************************************
65  // Iterate the fluxes if moeng type
66  // Next iterate over sea -- the models for surface roughness
67  // over sea are CHARNOCK, DONELAN, MODIFIED_CHARNOCK or WAVE_COUPLED
68  // ***************************************************************
71  bool is_land = false;
75  compute_fluxes(lev, max_iters, most_flux, is_land);
78  compute_fluxes(lev, max_iters, most_flux, is_land);
79  } else if (rough_type_sea == RoughCalcType::DONELAN) {
81  compute_fluxes(lev, max_iters, most_flux, is_land);
84  compute_fluxes(lev, max_iters, most_flux, is_land);
85  } else {
86  amrex::Abort("Unknown value for rough_type_sea");
87  }
88 
90  update_surf_temp(time);
93  compute_fluxes(lev, max_iters, most_flux, is_land);
96  compute_fluxes(lev, max_iters, most_flux, is_land);
97  } else if (rough_type_sea == RoughCalcType::DONELAN) {
99  compute_fluxes(lev, max_iters, most_flux, is_land);
102  compute_fluxes(lev, max_iters, most_flux, is_land);
103  } else {
104  amrex::Abort("Unknown value for rough_type_sea");
105  }
106 
107  } else if (theta_type == ThetaCalcType::ADIABATIC) {
110  compute_fluxes(lev, max_iters, most_flux, is_land);
113  compute_fluxes(lev, max_iters, most_flux, is_land);
114  } else if (rough_type_sea == RoughCalcType::DONELAN) {
116  compute_fluxes(lev, max_iters, most_flux, is_land);
119  compute_fluxes(lev, max_iters, most_flux, is_land);
120  } else {
121  amrex::Abort("Unknown value for rough_type_sea");
122  }
123  } else {
124  amrex::Abort("Unknown value for theta_type");
125  }
126 
127  } // MOENG -- SEA
128 
130  u_star[lev]->setVal(custom_ustar);
131  t_star[lev]->setVal(custom_tstar);
132  q_star[lev]->setVal(custom_qstar);
133  }
134 }
void compute_fluxes(const int &lev, const int &max_iters, const FluxIter &most_flux, bool is_land)
Definition: ERF_ABLMost.cpp:145
void time_interp_sst(const int &lev, const amrex::Real &time)
Definition: ERF_ABLMost.cpp:493
void update_surf_temp(const amrex::Real &time)
Definition: ERF_ABLMost.H:421
void get_lsm_tsurf(const int &lev)
Definition: ERF_ABLMost.cpp:528
void compute_averages(const int &lev)
Definition: ERF_MOSTAverage.cpp:665
Definition: ERF_MOSTStress.H:136
Definition: ERF_MOSTStress.H:270
Definition: ERF_MOSTStress.H:207
Definition: ERF_MOSTStress.H:330
Definition: ERF_MOSTStress.H:90
Definition: ERF_MOSTStress.H:478
Definition: ERF_MOSTStress.H:654
Definition: ERF_MOSTStress.H:570
Definition: ERF_MOSTStress.H:735
Definition: ERF_MOSTStress.H:399
Definition: ERF_MOSTStress.H:905
Definition: ERF_MOSTStress.H:1085
Definition: ERF_MOSTStress.H:999
Definition: ERF_MOSTStress.H:1168
Definition: ERF_MOSTStress.H:825

◆ update_mac_ptrs()

void ABLMost::update_mac_ptrs ( const int &  lev,
amrex::Vector< amrex::Vector< amrex::MultiFab >> &  vars_old,
amrex::Vector< std::unique_ptr< amrex::MultiFab >> &  Theta_prim,
amrex::Vector< std::unique_ptr< amrex::MultiFab >> &  Qv_prim,
amrex::Vector< std::unique_ptr< amrex::MultiFab >> &  Qr_prim 
)
inline
442  { m_ma.update_field_ptrs(lev,vars_old,Theta_prim,Qv_prim,Qr_prim); }
void update_field_ptrs(const int &lev, amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars_old, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &Theta_prim, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &Qv_prim, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &Qr_prim)
Definition: ERF_MOSTAverage.cpp:244
Here is the call graph for this function:

◆ update_pblh()

void ABLMost::update_pblh ( const int &  lev,
amrex::Vector< amrex::Vector< amrex::MultiFab >> &  vars,
amrex::MultiFab *  z_phys_cc,
const int  RhoQv_comp,
const int  RhoQc_comp,
const int  RhoQr_comp 
)
567 {
569  MYNNPBLH estimator;
570  compute_pblh(lev, vars, z_phys_cc, estimator, RhoQv_comp, RhoQc_comp, RhoQr_comp);
571  } else if (pblh_type == PBLHeightCalcType::YSU) {
572  amrex::Error("YSU PBLH calc not implemented yet");
573  }
574 }
void compute_pblh(const int &lev, amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars, amrex::MultiFab *z_phys_cc, const PBLHeightEstimator &est, const int RhoQv_comp, const int RhoQc_comp, const int RhoQr_comp)
Definition: ERF_PBLHeight.H:8

◆ update_surf_temp()

void ABLMost::update_surf_temp ( const amrex::Real &  time)
inline
422  {
423  if (surf_heating_rate != 0) {
424  int nlevs = m_geom.size();
425  for (int lev = 0; lev < nlevs; lev++)
426  {
427  t_surf[lev]->setVal(surf_temp + surf_heating_rate*time);
428  amrex::Print() << "Surface temp at t=" << time
429  << ": "
430  << surf_temp + surf_heating_rate*time
431  << std::endl;
432  }
433  }
434  }

Member Data Documentation

◆ cnk_a

amrex::Real ABLMost::cnk_a {0.0185}
private

Referenced by ABLMost().

◆ cnk_visc

bool ABLMost::cnk_visc {false}
private

Referenced by ABLMost().

◆ custom_qstar

amrex::Real ABLMost::custom_qstar {0}
private

Referenced by ABLMost().

◆ custom_tstar

amrex::Real ABLMost::custom_tstar {0}
private

Referenced by ABLMost().

◆ custom_ustar

amrex::Real ABLMost::custom_ustar {0}
private

Referenced by ABLMost().

◆ depth

amrex::Real ABLMost::depth {30.0}
private

Referenced by ABLMost().

◆ flux_type

FluxCalcType ABLMost::flux_type {FluxCalcType::MOENG}

Referenced by ABLMost(), and make_MOST_at_level().

◆ m_bdy_time_interval

amrex::Real ABLMost::m_bdy_time_interval
private

◆ m_eddyDiffs_lev

amrex::Vector<amrex::MultiFab*> ABLMost::m_eddyDiffs_lev
private

Referenced by make_MOST_at_level().

◆ m_exp_most

bool ABLMost::m_exp_most = false
private

◆ m_geom

amrex::Vector<amrex::Geometry> ABLMost::m_geom
private

◆ m_Hwave_lev

amrex::Vector<amrex::MultiFab*> ABLMost::m_Hwave_lev
private

Referenced by make_MOST_at_level().

◆ m_include_wstar

bool ABLMost::m_include_wstar = false
private

Referenced by ABLMost().

◆ m_lmask_lev

amrex::Vector<amrex::Vector<amrex::iMultiFab*> > ABLMost::m_lmask_lev
private

Referenced by get_lmask(), and make_MOST_at_level().

◆ m_lsm_data_lev

amrex::Vector<amrex::Vector<amrex::MultiFab*> > ABLMost::m_lsm_data_lev
private

Referenced by make_MOST_at_level().

◆ m_lsm_flux_lev

amrex::Vector<amrex::Vector<amrex::MultiFab*> > ABLMost::m_lsm_flux_lev
private

Referenced by make_MOST_at_level().

◆ m_Lwave_lev

amrex::Vector<amrex::MultiFab*> ABLMost::m_Lwave_lev
private

Referenced by make_MOST_at_level().

◆ m_ma

MOSTAverage ABLMost::m_ma
private

◆ m_rotate

bool ABLMost::m_rotate = false
private

◆ m_sst_lev

amrex::Vector<amrex::Vector<amrex::MultiFab*> > ABLMost::m_sst_lev
private

Referenced by make_MOST_at_level().

◆ m_start_bdy_time

amrex::Real ABLMost::m_start_bdy_time
private

◆ m_var_z0

bool ABLMost::m_var_z0 {false}
private

◆ olen

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ABLMost::olen
private

Referenced by get_olen(), and make_MOST_at_level().

◆ pblh

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ABLMost::pblh
private

Referenced by get_pblh(), and make_MOST_at_level().

◆ pblh_type

Referenced by ABLMost().

◆ q_star

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ABLMost::q_star
private

Referenced by get_q_star(), and make_MOST_at_level().

◆ rough_type_land

RoughCalcType ABLMost::rough_type_land {RoughCalcType::CONSTANT}

Referenced by ABLMost().

◆ rough_type_sea

RoughCalcType ABLMost::rough_type_sea {RoughCalcType::CHARNOCK}

Referenced by ABLMost(), and make_MOST_at_level().

◆ surf_heating_rate

amrex::Real ABLMost::surf_heating_rate {0}
private

Referenced by ABLMost(), and update_surf_temp().

◆ surf_temp

amrex::Real ABLMost::surf_temp
private

◆ surf_temp_flux

amrex::Real ABLMost::surf_temp_flux {0}
private

Referenced by ABLMost().

◆ t_star

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ABLMost::t_star
private

Referenced by get_t_star(), and make_MOST_at_level().

◆ t_surf

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ABLMost::t_surf
private

◆ theta_type

ThetaCalcType ABLMost::theta_type {ThetaCalcType::ADIABATIC}

Referenced by ABLMost(), and make_MOST_at_level().

◆ u_star

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ABLMost::u_star
private

Referenced by get_u_star(), and make_MOST_at_level().

◆ use_moisture

bool ABLMost::use_moisture
private

Referenced by ABLMost().

◆ w_star

amrex::Vector<std::unique_ptr<amrex::MultiFab> > ABLMost::w_star
private

Referenced by get_w_star(), and make_MOST_at_level().

◆ z0_const

amrex::Real ABLMost::z0_const {0.1}
private

Referenced by ABLMost(), and make_MOST_at_level().

◆ z_0

amrex::Vector<amrex::FArrayBox> ABLMost::z_0
private

Referenced by get_z0(), and make_MOST_at_level().


The documentation for this class was generated from the following files: