ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_SurfaceLayer.H
Go to the documentation of this file.
1 #ifndef ERF_SURFACELAYER_H
2 #define ERF_SURFACELAYER_H
3 
4 #include "AMReX_Geometry.H"
5 #include "AMReX_ParmParse.H"
6 #include "AMReX_FArrayBox.H"
7 #include "AMReX_MultiFab.H"
8 #include "AMReX_iMultiFab.H"
9 #include "AMReX_MFInterpolater.H"
10 
11 #include "ERF_IndexDefines.H"
12 #include "ERF_Constants.H"
13 #include "ERF_MOSTAverage.H"
14 #include "ERF_MOSTStress.H"
15 #include "ERF_EBMOSTStress.H"
17 #include "ERF_TerrainMetrics.H"
18 #include "ERF_PBLHeight.H"
19 #include "ERF_MicrophysicsUtils.H"
20 #include "ERF_EB.H"
21 
22 /** Abstraction layer for different surface layer schemes (e.g. MOST, Cd)
23  *
24  * van der Laan, P., Kelly, M. C., & Sørensen, N. N. (2017). A new k-epsilon
25  * model consistent with Monin-Obukhov similarity theory. Wind Energy,
26  * 20(3), 479–amrex::Real(489.) https://doi.org/amrex::Real(10.1002)/we.2017
27  *
28  * Consistent with Dyer (1974) formulation from page 57, Chapter 2, Modeling
29  * the vertical ABL structure in Modelling of Atmospheric Flow Fields,
30  * Demetri P Lalas and Corrado F Ratto, January 1996,
31  * https://doi.org/amrex::Real(10.1142)/amrex::Real(2975.)
32  */
34 {
35 
36 public:
37  // Constructor
38  explicit SurfaceLayer (const amrex::Vector<amrex::Geometry>& geom,
39  bool& use_rot_surface_flux,
40  std::string a_pp_prefix,
41  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Qv_prim,
42  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& z_phys_nd,
43  const MeshType& a_mesh_type,
44  const TerrainType& a_terrain_type,
45  const TurbChoice& a_turb_choice,
46  amrex::Real start_low_time,
47  amrex::Real final_low_time,
48  amrex::Real low_time_interval = zero,
49  const amrex::Vector<const eb_*>& eb_vec = {})
50  : m_geom(geom),
51  m_rotate(use_rot_surface_flux),
52  m_start_low_time(start_low_time),
53  m_final_low_time(final_low_time),
54  m_low_time_interval(low_time_interval),
55  m_eb_vec(eb_vec),
56  m_terrain_type(a_terrain_type),
57  m_ma(geom, (z_phys_nd[0] != nullptr), a_pp_prefix, a_mesh_type, a_terrain_type, eb_vec)
58  {
59  // We have a moisture model if Qv_prim is a valid pointer
60  use_moisture = (Qv_prim[0].get());
61 
62  // Get roughness
63  amrex::ParmParse pp("erf");
64  pp.query("most.z0", z0_const);
65 
66  // Specify how to compute the flux
67  if (use_rot_surface_flux) {
69  } else {
70  std::string flux_string_in;
71  std::string flux_string{"moeng"};
72  auto read_flux = pp.query("surface_layer.flux_type", flux_string_in);
73  if (read_flux) {
74  flux_string = amrex::toLower(flux_string_in);
75  }
76  if (flux_string == "donelan") {
78  } else if (flux_string == "moeng") {
80  } else if (flux_string == "rico") {
82  } else if (flux_string == "bulk_coeff") {
84  } else if (flux_string == "custom") {
86  } else {
87  amrex::Abort("Undefined MOST flux type!");
88  }
89  }
90 
91  // Include w* to handle free convection (Beljaars 1995, QJRMS)
92  pp.query("most.include_wstar", m_include_wstar);
93 
94  std::string pblh_string_in;
95  std::string pblh_string{"none"};
96  auto read_pblh = pp.query("most.pblh_calc", pblh_string_in);
97  if (read_pblh) {
98  pblh_string = amrex::toLower(pblh_string_in);
99  }
100  if (pblh_string == "none") {
102  } else if (pblh_string == "mynn25") {
104  } else if (pblh_string == "mynnedmf") {
106  } else if (pblh_string == "ysu") {
108  } else if (pblh_string == "mrf") {
110  } else {
111  amrex::Abort("Undefined PBLH calc type!");
112  }
113 
114  // Get surface temperature
115  auto erf_st = pp.query("most.surf_temp", surf_temp);
116  if (erf_st) { default_land_surf_temp = surf_temp; }
117 
118  // Get surface moisture
119  bool erf_sq = false;
120  if (use_moisture) { erf_sq = pp.query("most.surf_moist", surf_moist); }
121  if (erf_sq) { default_land_surf_moist = surf_moist; }
122 
123  // Custom type user must specify the fluxes
128  pp.get("most.ustar", custom_ustar);
129  pp.get("most.tstar", custom_tstar);
130  pp.get("most.qstar", custom_qstar);
131  pp.query("most.rhosurf", custom_rhosurf);
132  if (custom_qstar != 0) {
134  "Specified custom MOST qv flux without moisture model!");
135  }
136  amrex::Print() << "Using specified ustar, tstar, qstar for MOST = "
137  << custom_ustar << " " << custom_tstar << " "
138  << custom_qstar << std::endl;
139 
140  // Bulk transfer coefficient (must specify coeffs and surface values)
141  } else if (flux_type == FluxCalcType::BULK_COEFF) {
142  pp.get("most.Cd", m_Cd);
143  pp.get("most.Ch", m_Ch);
144  pp.get("most.Cq", m_Cq);
145  pp.get("most.surf_temp", default_land_surf_temp);
146  pp.get("most.surf_moist", default_land_surf_moist);
147  amrex::Print() << "Using specified Cd, Ch, Cq for MOST = "
148  << m_Cd << " " << m_Ch << " "
149  << m_Cq << std::endl;
150 
151  // Specify surface temperature/moisture or surface flux
152  } else {
153  if (erf_st) {
155  pp.query("most.surf_heating_rate", surf_heating_rate); // [K/h]
156 
157  // Modify rate to be in units of K / s rather than K / hr
158  surf_heating_rate /= amrex::Real(3600.0); // [K/s]
159 
160  if (pp.query("most.surf_temp_flux", surf_temp_flux)) {
161  amrex::Abort("Can only specify one of surf_temp_flux or surf_heating_rate");
162  }
163  } else {
164  pp.query("most.surf_temp_flux", surf_temp_flux);
165 
166  if (pp.query("most.surf_heating_rate", surf_heating_rate)) {
167  amrex::Abort("Can only specify one of surf_temp_flux or surf_heating_rate");
168  }
169  if (std::abs(surf_temp_flux) >
172  } else {
174  }
175  }
176 
177  if (erf_sq) {
179  } else {
180  pp.query("most.surf_moist_flux", surf_moist_flux);
181  if (std::abs(surf_moist_flux) >
184  } else {
186  }
187  }
188  }
189 
191  {
192  pp.query("most.rico.theta_z0", rico_theta_z0);
193  pp.query("most.rico.qsat_z0", rico_qsat_z0);
194  }
195 
196  // Make sure the inputs file doesn't try to use most.roughness_type
197  std::string bogus_input;
198  if (pp.query("most.roughness_type", bogus_input) > 0) {
199  amrex::Abort("most.roughness_type is deprecated; use "
200  "most.roughness_type_land and/or most.roughness_type_sea");
201  }
202 
203  // Specify how to compute the surface flux over land (if there is any)
204  std::string rough_land_string_in;
205  std::string rough_land_string{"constant"};
206  auto read_rough_land =
207  pp.query("most.roughness_type_land", rough_land_string_in);
208  if (read_rough_land) {
209  rough_land_string = amrex::toLower(rough_land_string_in);
210  }
211  if (rough_land_string == "constant") {
213  } else {
214  amrex::Abort("Undefined MOST roughness type for land!");
215  }
216 
217  // Specify how to compute the surface flux over sea (if there is any)
218  std::string rough_sea_string_in;
219  std::string rough_sea_string{"charnock"};
220  auto read_rough_sea = pp.query("most.roughness_type_sea", rough_sea_string_in);
221  if (read_rough_sea) {
222  rough_sea_string = amrex::toLower(rough_sea_string_in);
223  }
224  if (rough_sea_string == "charnock") {
226  pp.query("most.charnock_constant", cnk_a);
227  pp.query("most.charnock_viscosity", cnk_visc);
228  if (cnk_a > 0) {
229  amrex::Print() << "If there is water, Charnock relation with C_a="
230  << cnk_a << (cnk_visc ? " and viscosity" : "")
231  << " will be used" << std::endl;
232  } else {
233  amrex::Print() << "If there is water, Charnock relation with variable "
234  "Charnock parameter (COARE3.0)"
235  << (cnk_visc ? " and viscosity" : "") << " will be used"
236  << std::endl;
237  }
238  } else if (rough_sea_string == "coare3.0") {
240  amrex::Print() << "If there is water, Charnock relation with variable "
241  "Charnock parameter (COARE3.0)"
242  << (cnk_visc ? " and viscosity" : "") << " will be used"
243  << std::endl;
244  cnk_a = -1;
245  } else if (rough_sea_string == "donelan") {
247  } else if (rough_sea_string == "modified_charnock") {
249  pp.query("most.modified_charnock_depth", depth);
250  } else if (rough_sea_string == "wave_coupled") {
252  } else if (rough_sea_string == "constant") {
254  } else {
255  amrex::Abort("Undefined MOST roughness type for sea!");
256  }
257 
258  // use skin temperature instead of sea-surface temperature
259  // (wrfinput data may have lower resolution SST data)
260  pp.query("most.ignore_sst", m_ignore_sst);
261 
262  // If we're using the RANS k model, then we need to update the dirichlet
263  // BC based on the instantaneous u* and θ*; the turbulence modeling
264  // choices can vary per level but for now, assume that if specified then
265  // all levels are using the same RANS model.
266  m_update_k_rans = (a_turb_choice.rans_type == RANSType::kEqn &&
267  a_turb_choice.dirichlet_k == true);
268  if (m_update_k_rans) {
269  inv_Cmu2 = one / (a_turb_choice.Cmu0 * a_turb_choice.Cmu0);
270  theta_ref = a_turb_choice.theta_ref;
271  }
272 
273  } // constructor
274 
275  void make_SurfaceLayer_at_level (const int& lev,
276  int nlevs,
277  const amrex::Vector<amrex::MultiFab*>& mfv,
278  std::unique_ptr<amrex::MultiFab>& Theta_prim,
279  std::unique_ptr<amrex::MultiFab>& Qv_prim,
280  std::unique_ptr<amrex::MultiFab>& Qr_prim,
281  std::unique_ptr<amrex::MultiFab>& z_phys_nd,
282  amrex::MultiFab* Hwave,
283  amrex::MultiFab* Lwave,
284  amrex::MultiFab* eddyDiffs,
285  amrex::Vector<amrex::MultiFab*> lsm_data,
286  amrex::Vector<std::string> lsm_data_name,
287  amrex::Vector<amrex::MultiFab*> lsm_flux,
288  amrex::Vector<std::string> lsm_flux_name,
289  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& sst_lev,
290  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& tsk_lev,
291  amrex::Vector<std::unique_ptr<amrex::iMultiFab>>& lmask_lev)
292  {
293  // Update MOST Average
295  Theta_prim, Qv_prim, Qr_prim,
296  z_phys_nd);
297 
298  // Get CC vars
299  amrex::MultiFab& mf = *(mfv[0]);
300 
301  amrex::ParmParse pp("erf");
302 
303  // Do we have a time-varying surface roughness that needs to be saved?
304  if (lev == 0) {
305  const int nghost = 0; // ghost cells not included
306  int lmask_min = lmask_min_reduce(*lmask_lev[0].get(), nghost);
307  amrex::ParallelDescriptor::ReduceIntMin(lmask_min);
308 
309  m_var_z0 = (lmask_min < 1) & (rough_type_sea != RoughCalcType::CONSTANT);
310  if (m_var_z0) {
311  std::string rough_sea_string{"charnock"};
312  pp.query("most.roughness_type_sea", rough_sea_string);
313  amrex::Print() << "Variable sea roughness (type " << rough_sea_string
314  << ")" << std::endl;
315  }
316  }
317 
318  if (m_eddyDiffs_lev.size() < lev+1) {
319  m_Hwave_lev.resize(nlevs);
320  m_Lwave_lev.resize(nlevs);
321  m_eddyDiffs_lev.resize(nlevs);
322 
323  m_lsm_data_lev.resize(nlevs);
324  m_lsm_flux_lev.resize(nlevs);
325 
326  m_sst_lev.resize(nlevs);
327  m_tsk_lev.resize(nlevs);
328  m_lmask_lev.resize(nlevs);
329 
330  // Size the MOST params for all levels
331  z_0.resize(nlevs);
332  u_star.resize(nlevs);
333  w_star.resize(nlevs);
334  t_star.resize(nlevs);
335  q_star.resize(nlevs);
336  t_surf.resize(nlevs);
337  q_surf.resize(nlevs);
338  surface_diagnostic_source.resize(nlevs);
339  olen.resize(nlevs);
340  pblh.resize(nlevs);
341  }
342 
343  // Get pointers to SST,TSK and LANDMASK data
344  int nt_tot_sst = sst_lev.size();
345  m_sst_lev[lev].resize(nt_tot_sst);
346  for (int nt(0); nt < nt_tot_sst; ++nt) {
347  m_sst_lev[lev][nt] = sst_lev[nt].get();
348  }
349  int nt_tot_tsk = static_cast<int>(tsk_lev.size());
350  m_tsk_lev[lev].resize(nt_tot_tsk);
351  for (int nt(0); nt < nt_tot_tsk; ++nt) {
352  m_tsk_lev[lev][nt] = tsk_lev[nt].get();
353  }
354  int nt_tot_lmask = static_cast<int>(lmask_lev.size());
355  m_lmask_lev[lev].resize(nt_tot_lmask);
356  for (int nt(0); nt < nt_tot_lmask; ++nt) {
357  m_lmask_lev[lev][nt] = lmask_lev[nt].get();
358  }
359 
360  // Get pointers to wave data
361  m_Hwave_lev[lev] = Hwave;
362  m_Lwave_lev[lev] = Lwave;
363  m_eddyDiffs_lev[lev] = eddyDiffs;
364 
365  // Get pointers to LSM data and Fluxes
366  int ndata = static_cast<int>(lsm_data.size());
367  int nflux = static_cast<int>(lsm_flux.size());
368  m_lsm_data_name.resize(ndata);
369  m_lsm_data_lev[lev].resize(ndata);
370  m_lsm_flux_name.resize(nflux);
371  m_lsm_flux_lev[lev].resize(nflux);
372  for (int n(0); n < ndata; ++n) {
373  m_lsm_data_name[n] = lsm_data_name[n];
374  m_lsm_data_lev[lev][n] = lsm_data[n];
375  const std::string lc_name = amrex::toLower(lsm_data_name[n]);
376  if (lc_name == "theta" || lc_name == "t_surf") {
377  m_has_lsm_tsurf = true;
378  m_lsm_tsurf_indx = n;
379  m_has_ocean_lsm_tsurf = (lc_name == "t_surf");
380  }
381  }
382  int n_valid_lsm_flux = 0;
383  for (int n(0); n < nflux; ++n) {
384  m_lsm_flux_name[n] = lsm_flux_name[n];
385  m_lsm_flux_lev[lev][n] = lsm_flux[n];
386  if (m_lsm_flux_lev[lev][n]) { ++n_valid_lsm_flux; }
387  }
388  AMREX_ALWAYS_ASSERT((n_valid_lsm_flux==0 || n_valid_lsm_flux>=4));
389  if (n_valid_lsm_flux>=4) { m_has_lsm_fluxes = true; }
390 
391  // Check if there is a user-specified roughness file to be read
392  std::string fname;
393  bool read_z0 = false;
394  if ( (flux_type == FluxCalcType::MOENG) ||
396  int count = pp.countval("most.roughness_file_name");
397  if (count > 1) {
398  AMREX_ALWAYS_ASSERT(count >= lev+1);
399  pp.query("most.roughness_file_name", fname, lev);
400  read_z0 = true;
401  } else if (count == 1) {
402  if (lev == 0) {
403  pp.query("most.roughness_file_name", fname);
404  } else {
405  // we will interpolate from the coarsest level
406  fname = "";
407  }
408  read_z0 = true;
409  }
410  // else use z0_const
411  }
412 
413  // Attributes for MFs and FABs
414  //--------------------------------------------------------
415  // Create a 2D ba for planar terrain, 3D for EB terrain
416  amrex::BoxArray ba = mf.boxArray();
417  amrex::BoxArray ba_flux;
418  amrex::IntVect ng{1,1,0};
419 
420  if (m_terrain_type == TerrainType::EB) {
421  // Use full 3D BoxArray for EB terrain
422  ba_flux = ba;
423  ng = amrex::IntVect{1,1,1}; // Include z ghost cells
424  } else {
425  // Collapse to 2D for planar terrain
426  amrex::BoxList bl2d = ba.boxList();
427  for (auto& b : bl2d) { b.setRange(2,0); }
428  ba_flux = amrex::BoxArray(std::move(bl2d));
429  }
430 
431  const amrex::DistributionMapping& dm = mf.DistributionMap();
432  const int ncomp = 1;
433 
434  // Z0 heights FAB
435  //--------------------------------------------------------
436  z_0[lev].define(ba_flux, dm, ncomp, ng);
437  z_0[lev].setVal(z0_const);
438  if (read_z0) {
439  read_custom_roughness(lev, fname);
440  }
441 
442  // 2D MFs for U*, T*, T_surf
443  //--------------------------------------------------------
444  u_star[lev] = std::make_unique<amrex::MultiFab>(ba_flux, dm, ncomp, ng);
445  u_star[lev]->setVal(bogus_large_value);
446 
447  w_star[lev] = std::make_unique<amrex::MultiFab>(ba_flux, dm, ncomp, ng);
448  w_star[lev]->setVal(bogus_large_value);
449 
450  t_star[lev] = std::make_unique<amrex::MultiFab>(ba_flux, dm, ncomp, ng);
451  t_star[lev]->setVal(zero); // default to neutral
452 
453  q_star[lev] = std::make_unique<amrex::MultiFab>(ba_flux, dm, ncomp, ng);
454  q_star[lev]->setVal(zero); // default to dry
455 
456  olen[lev] = std::make_unique<amrex::MultiFab>(ba_flux, dm, ncomp, ng);
457  olen[lev]->setVal(bogus_large_value);
458 
459  pblh[lev] = std::make_unique<amrex::MultiFab>(ba_flux, dm, ncomp, ng);
460  pblh[lev]->setVal(bogus_large_value);
461 
462  t_surf[lev] = std::make_unique<amrex::MultiFab>(ba_flux, dm, ncomp, ng);
463  t_surf[lev]->setVal(default_land_surf_temp);
464 
465  q_surf[lev] = std::make_unique<amrex::MultiFab>(ba_flux, dm, ncomp, ng);
466  q_surf[lev]->setVal(default_land_surf_moist);
467 
468  surface_diagnostic_source[lev] = std::make_unique<amrex::MultiFab>(ba_flux, dm, ncomp, ng);
469  surface_diagnostic_source[lev]->setVal(
471 
472  // TODO: Do we want an enum struct for indexing?
473 
474  bool use_sst = (!m_sst_lev[lev].empty() && m_sst_lev[lev][0]);
475  bool use_tsk = (!m_tsk_lev[lev].empty() && m_tsk_lev[lev][0]);
476  if (use_sst || use_tsk || m_has_lsm_tsurf) {
477  // Valid SST, TSK or LSM data; t_surf set before computing fluxes (avoids
478  // extended lambda capture) Note that land temp will be set from m_tsk_lev
479  // while sea temp will be set from m_sst_lev
481 
482  // Pathways in fill_tsurf_with_sst_and_tsk
483  amrex::Print() << "Using MOST with specified surface temperature ";
484  if (m_has_ocean_lsm_tsurf) {
485  amrex::Print() << "(OceanSurf: t_surf)" << std::endl;
486  } else {
487  // NOTE: SST from the LOW file populates TSK in update_sst_tsk.
488  // So if we have TSK, it contains everything and has been
489  // sanity checked for valid SST values.
490  if (use_tsk) { m_ignore_sst = true; }
491  if (use_tsk) {
492  amrex::Print() << "(land: TSK, ";
493  } else {
494  amrex::Print() << "(land: T0, ";
495  }
496  if (use_tsk && !use_sst) {
497  amrex::Print() << "sea: TSK)" << std::endl;
498  } else {
499  amrex::Print() << "sea: SST)" << std::endl;
501  }
502  }
503  }
504  }
505 
506  void
507  update_fluxes (const int& lev,
508  const amrex::Real& elapsed_time,
509  const amrex::Real& elapsed_time_since_start_low,
510  amrex::MultiFab& cons_in,
511  const std::unique_ptr<amrex::MultiFab>& z_phys_nd,
512  const std::unique_ptr<amrex::MultiFab>& walldist,
513  int max_iters = 100);
514 
515  template <typename FluxIter>
516  void compute_fluxes (const int& lev,
517  const int& max_iters,
518  amrex::MultiFab& cons_in,
519  const FluxIter& most_flux,
520  bool is_land);
521 
522  void init_tke_from_ustar (const int& lev,
523  amrex::MultiFab& cons,
524  const std::unique_ptr<amrex::MultiFab>& z_phys_nd,
525  const amrex::Real tkefac = one,
526  const amrex::Real zscale = amrex::Real(700.0));
527 
528  void impose_SurfaceLayer_bcs (const int& lev,
529  amrex::Vector<const amrex::MultiFab*> mfs,
530  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Tau_lev,
531  amrex::MultiFab* xheat_flux,
532  amrex::MultiFab* yheat_flux,
533  amrex::MultiFab* zheat_flux,
534  amrex::MultiFab* xqv_flux,
535  amrex::MultiFab* yqv_flux,
536  amrex::MultiFab* zqv_flux,
537  const amrex::MultiFab* z_phys);
538 
539  void impose_SurfaceLayer_bcs_EB (const int& lev,
540  amrex::Vector<const amrex::MultiFab*> mfs,
541  amrex::Vector<amrex::Vector<std::unique_ptr<amrex::MultiFab>>>& Tau_lev,
542  amrex::MultiFab* xheat_flux,
543  amrex::MultiFab* yheat_flux,
544  amrex::MultiFab* zheat_flux,
545  amrex::MultiFab* xqv_flux,
546  amrex::MultiFab* yqv_flux,
547  amrex::MultiFab* zqv_flux);
548  template <typename FluxCalc>
549  void compute_SurfaceLayer_bcs (const int& lev,
550  amrex::Vector<const amrex::MultiFab*> mfs,
551  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Tau_lev,
552  amrex::MultiFab* xheat_flux,
553  amrex::MultiFab* yheat_flux,
554  amrex::MultiFab* zheat_flux,
555  amrex::MultiFab* xqv_flux,
556  amrex::MultiFab* yqv_flux,
557  amrex::MultiFab* zqv_flux,
558  const amrex::MultiFab* z_phys,
559  const FluxCalc& flux_comp);
560 
561  template <typename FluxCalc>
562  void compute_SurfaceLayer_bcs_EB (const int& lev,
563  amrex::Vector<const amrex::MultiFab*> mfs,
564  amrex::Vector<amrex::Vector<std::unique_ptr<amrex::MultiFab>>>& Tau_lev,
565  amrex::MultiFab* xheat_flux,
566  amrex::MultiFab* yheat_flux,
567  amrex::MultiFab* zheat_flux,
568  amrex::MultiFab* xqv_flux,
569  amrex::MultiFab* yqv_flux,
570  amrex::MultiFab* zqv_flux,
571  const FluxCalc& flux_comp);
572 
573  void compute_sfc_params_from_lsm_fluxes(const int& lev,
574  amrex::MultiFab& cons_in);
575 
576  void fill_tsurf_with_sst_and_tsk (const int& lev,
577  const amrex::Real& time);
578 
579  void fill_qsurf_with_qsat (const int& lev,
580  const amrex::MultiFab& cons_in,
581  const std::unique_ptr<amrex::MultiFab>& z_phys_nd);
582 
583  void get_lsm_tsurf (const int& lev);
584 
585  /* wrapper around compute_pblh */
586  void update_pblh (const int& lev,
587  amrex::Vector<amrex::Vector<amrex::MultiFab>>& vars,
588  amrex::MultiFab* z_phys_cc,
589  const MoistureComponentIndices& moisture_indices);
590 
591  template <typename PBLHeightEstimator>
592  void compute_pblh (const int& lev,
593  amrex::Vector<amrex::Vector<amrex::MultiFab>>& vars,
594  amrex::MultiFab* z_phys_cc,
595  const PBLHeightEstimator& est,
596  const MoistureComponentIndices& moisture_indice);
597 
598  void read_custom_roughness (const int& lev,
599  const std::string& fname);
600 
601  void update_surf_temp (const amrex::Real& time)
602  {
603  if (m_has_ocean_lsm_tsurf) {
604  return;
605  }
606  if (surf_heating_rate != 0) {
607  int nlevs = static_cast<int>(m_geom.size());
608  for (int lev = 0; lev < nlevs; lev++) {
609  t_surf[lev]->setVal(surf_temp + surf_heating_rate * time);
610  amrex::Print() << "Surface temp at t=" << time << ": "
611  << surf_temp + surf_heating_rate * time << std::endl;
612  }
613  }
614  }
615 
616  void update_mac_ptrs (const int& lev,
617  amrex::Vector<amrex::Vector<amrex::MultiFab>>& vars_old,
618  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Theta_prim,
619  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Qv_prim,
620  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Qr_prim)
621  {
622  m_ma.update_field_ptrs(lev, vars_old, Theta_prim, Qv_prim, Qr_prim);
623  }
624 
625  amrex::MultiFab* get_u_star (const int& lev) { return u_star[lev].get(); }
626 
627  amrex::MultiFab* get_w_star (const int& lev) { return w_star[lev].get(); }
628 
629  amrex::MultiFab* get_t_star (const int& lev) { return t_star[lev].get(); }
630 
631  amrex::MultiFab* get_q_star (const int& lev) { return q_star[lev].get(); }
632 
633  amrex::MultiFab* get_olen (const int& lev) { return olen[lev].get(); }
634 
635  amrex::MultiFab* get_pblh (const int& lev) { return pblh[lev].get(); }
636 
637  const amrex::MultiFab* get_mac_avg (const int& lev, int comp)
638  {
639  return m_ma.get_average(lev, comp);
640  }
641 
642  amrex::MultiFab* get_t_surf (const int& lev) { return t_surf[lev].get(); }
643  void set_t_surf(const int& lev, const amrex::Real tsurf) { t_surf[lev]->setVal(tsurf); }
644 
645  amrex::MultiFab* get_q_surf (const int& lev) { return q_surf[lev].get(); }
646  void set_q_surf(const int& lev, const amrex::Real qsurf) { q_surf[lev]->setVal(qsurf); }
647 
648  amrex::MultiFab* get_surface_diagnostic_source (const int& lev) { return surface_diagnostic_source[lev].get(); }
649 
650  amrex::Real get_zref (const int& lev) { return (m_ma.get_zref(lev))->min(0); }
651 
652  amrex::MultiFab* get_z0 (const int& lev) { return &z_0[lev]; }
653 
655 
656  amrex::iMultiFab* get_lmask (const int& lev) { return m_lmask_lev[lev][0]; }
657 
658  int lmask_min_reduce (amrex::iMultiFab& lmask,
659  const int& nghost)
660  {
661  int lmask_min = amrex::ReduceMin(lmask, nghost, [=] AMREX_GPU_HOST_DEVICE(
662  amrex::Box const& bx, amrex::Array4<int const> const& lm_arr) -> int
663  {
664  int locmin = std::numeric_limits<int>::max();
665  const auto lo = lbound(bx);
666  const auto hi = ubound(bx);
667  for (int j = lo.y; j <= hi.y; ++j) {
668  for (int i = lo.x; i <= hi.x; ++i) {
669  locmin = std::min(locmin, lm_arr(i, j, 0));
670  }
671  }
672  return locmin;
673  });
674 
675  return lmask_min;
676  }
677 
678  void update_sst_ptr(const int lev, const int itime, amrex::MultiFab* sst_ptr) {
679  m_sst_lev[lev][itime] = sst_ptr;
680  }
681 
682  void update_tsk_ptr(const int lev, const int itime, amrex::MultiFab* tsk_ptr) {
683  m_tsk_lev[lev][itime] = tsk_ptr;
684  }
685 
686  enum struct FluxCalcType {
687  MOENG = 0, ///< Moeng functional form
688  DONELAN, ///< Donelan functional form
689  CUSTOM, ///< Custom constant flux functional form
690  BULK_COEFF, ///< Bulk transfer coefficient functional form
691  ROTATE, ///< Terrain rotation flux functional form
692  RICO
693  };
694 
695  enum struct ThetaCalcType {
696  ADIABATIC = 0,
697  HEAT_FLUX, ///< Heat-flux specified
698  SURFACE_TEMPERATURE ///< Surface temperature specified
699  };
700 
701  enum struct MoistCalcType {
702  ADIABATIC = 0,
703  MOISTURE_FLUX, ///< Qv-flux specified
704  SURFACE_MOISTURE ///< Surface Qv specified
705  };
706 
707  enum struct RoughCalcType {
708  CONSTANT = 0, ///< Constant z0
709  CHARNOCK,
711  DONELAN,
713  };
714 
715  enum struct PBLHeightCalcType { None, MYNN25, YSU, MRF };
716 
723 
724 private:
725  // Set in constructor
726  amrex::Vector<amrex::Geometry> m_geom;
727  bool m_rotate = false;
731 
732  bool m_include_wstar = false;
744  amrex::Real custom_rhosurf{0}; // use specified value instead of rho from first cell
745  bool specified_rho_surf{false};
747  bool cnk_visc{false};
749  amrex::Vector<amrex::MultiFab> z_0;
750  bool m_var_z0{false};
751 
754 
756  bool m_has_lsm_fluxes = false;
757  bool m_has_lsm_tsurf = false;
758  bool m_has_ocean_lsm_tsurf = false;
760 
764 
765  bool m_ignore_sst = false;
766 
767  amrex::Vector<const eb_*> m_eb_vec;
768  TerrainType m_terrain_type;
770  amrex::Vector<std::unique_ptr<amrex::MultiFab>> u_star;
771  amrex::Vector<std::unique_ptr<amrex::MultiFab>> w_star;
772  amrex::Vector<std::unique_ptr<amrex::MultiFab>> t_star;
773  amrex::Vector<std::unique_ptr<amrex::MultiFab>> q_star;
774  amrex::Vector<std::unique_ptr<amrex::MultiFab>> olen;
775  amrex::Vector<std::unique_ptr<amrex::MultiFab>> pblh;
776  amrex::Vector<std::unique_ptr<amrex::MultiFab>> t_surf;
777  amrex::Vector<std::unique_ptr<amrex::MultiFab>> q_surf;
778  // Diagnostic-only provenance mask. This records the cell-centered source
779  // path used by the SurfaceLayer scalar diagnostic path. It must not feed
780  // back into flux calculations, boundary conditions, or model state.
781  amrex::Vector<std::unique_ptr<amrex::MultiFab>> surface_diagnostic_source;
782 
783  amrex::Vector<amrex::Vector<amrex::MultiFab*>> m_sst_lev;
784  amrex::Vector<amrex::Vector<amrex::MultiFab*>> m_tsk_lev;
785  amrex::Vector<amrex::Vector<amrex::iMultiFab*>> m_lmask_lev;
786  amrex::Vector<amrex::Vector<amrex::MultiFab*>> m_lsm_data_lev;
787  amrex::Vector<amrex::Vector<amrex::MultiFab*>> m_lsm_flux_lev;
788  amrex::Vector<std::string> m_lsm_data_name;
789  amrex::Vector<std::string> m_lsm_flux_name;
790  amrex::Vector<amrex::MultiFab*> m_Hwave_lev;
791  amrex::Vector<amrex::MultiFab*> m_Lwave_lev;
792  amrex::Vector<amrex::MultiFab*> m_eddyDiffs_lev;
793 
794  bool m_update_k_rans = false;
797 };
798 
799 #endif /* SURFACELAYER_H */
constexpr amrex::Real bogus_large_value
Definition: ERF_Constants.H:26
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
ParmParse pp("prob")
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
pp get("wavelength", wavelength)
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_ASSERT_WITH_MESSAGE(wbar_cutoff_min > wbar_cutoff_max, "ERROR: wbar_cutoff_min < wbar_cutoff_max")
Definition: ERF_MOSTAverage.H:15
amrex::MultiFab * get_zref(const int &lev) const
Definition: ERF_MOSTAverage.H:116
const amrex::MultiFab * get_average(const int &lev, const int &comp) const
Definition: ERF_MOSTAverage.H:113
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:279
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:90
Definition: ERF_SurfaceLayer.H:34
ThetaCalcType theta_type
Definition: ERF_SurfaceLayer.H:718
int lmask_min_reduce(amrex::iMultiFab &lmask, const int &nghost)
Definition: ERF_SurfaceLayer.H:658
amrex::Vector< std::string > m_lsm_data_name
Definition: ERF_SurfaceLayer.H:788
bool m_include_wstar
Definition: ERF_SurfaceLayer.H:732
bool specified_rho_surf
Definition: ERF_SurfaceLayer.H:745
void set_q_surf(const int &lev, const amrex::Real qsurf)
Definition: ERF_SurfaceLayer.H:646
bool m_rotate
Definition: ERF_SurfaceLayer.H:727
PBLHeightCalcType pblh_type
Definition: ERF_SurfaceLayer.H:722
amrex::Vector< amrex::Vector< amrex::iMultiFab * > > m_lmask_lev
Definition: ERF_SurfaceLayer.H:785
amrex::iMultiFab * get_lmask(const int &lev)
Definition: ERF_SurfaceLayer.H:656
bool use_moisture
Definition: ERF_SurfaceLayer.H:755
amrex::MultiFab * get_q_surf(const int &lev)
Definition: ERF_SurfaceLayer.H:645
bool m_has_lsm_tsurf
Definition: ERF_SurfaceLayer.H:757
amrex::MultiFab * get_w_star(const int &lev)
Definition: ERF_SurfaceLayer.H:627
void update_surf_temp(const amrex::Real &time)
Definition: ERF_SurfaceLayer.H:601
amrex::Real m_Cq
Definition: ERF_SurfaceLayer.H:763
amrex::Vector< const eb_ * > m_eb_vec
Definition: ERF_SurfaceLayer.H:767
RoughCalcType rough_type_land
Definition: ERF_SurfaceLayer.H:720
void update_pblh(const int &lev, amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars, amrex::MultiFab *z_phys_cc, const MoistureComponentIndices &moisture_indices)
Definition: ERF_SurfaceLayer.cpp:1177
amrex::Vector< std::unique_ptr< amrex::MultiFab > > t_surf
Definition: ERF_SurfaceLayer.H:776
amrex::Real z0_const
Definition: ERF_SurfaceLayer.H:733
amrex::Vector< std::unique_ptr< amrex::MultiFab > > surface_diagnostic_source
Definition: ERF_SurfaceLayer.H:781
amrex::Real cnk_a
Definition: ERF_SurfaceLayer.H:746
amrex::Real m_Ch
Definition: ERF_SurfaceLayer.H:762
amrex::Real m_start_low_time
Definition: ERF_SurfaceLayer.H:728
amrex::Real surf_temp
Definition: ERF_SurfaceLayer.H:735
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)
Definition: ERF_SurfaceLayer.H:616
void compute_pblh(const int &lev, amrex::Vector< amrex::Vector< amrex::MultiFab >> &vars, amrex::MultiFab *z_phys_cc, const PBLHeightEstimator &est, const MoistureComponentIndices &moisture_indice)
amrex::Vector< std::unique_ptr< amrex::MultiFab > > q_star
Definition: ERF_SurfaceLayer.H:773
int m_lsm_tsurf_indx
Definition: ERF_SurfaceLayer.H:759
amrex::Real rico_qsat_z0
Definition: ERF_SurfaceLayer.H:753
bool m_has_lsm_fluxes
Definition: ERF_SurfaceLayer.H:756
bool m_update_k_rans
Definition: ERF_SurfaceLayer.H:794
amrex::Vector< amrex::MultiFab * > m_Lwave_lev
Definition: ERF_SurfaceLayer.H:791
void update_fluxes(const int &lev, const amrex::Real &elapsed_time, const amrex::Real &elapsed_time_since_start_low, amrex::MultiFab &cons_in, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const std::unique_ptr< amrex::MultiFab > &walldist, int max_iters=100)
Definition: ERF_SurfaceLayer.cpp:12
void get_lsm_tsurf(const int &lev)
Definition: ERF_SurfaceLayer.cpp:1139
void fill_qsurf_with_qsat(const int &lev, const amrex::MultiFab &cons_in, const std::unique_ptr< amrex::MultiFab > &z_phys_nd)
Definition: ERF_SurfaceLayer.cpp:1096
amrex::Real get_zref(const int &lev)
Definition: ERF_SurfaceLayer.H:650
amrex::MultiFab * get_olen(const int &lev)
Definition: ERF_SurfaceLayer.H:633
amrex::Vector< amrex::MultiFab > z_0
Definition: ERF_SurfaceLayer.H:749
amrex::Real surf_moist_flux
Definition: ERF_SurfaceLayer.H:740
void compute_SurfaceLayer_bcs(const int &lev, amrex::Vector< const amrex::MultiFab * > mfs, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &Tau_lev, amrex::MultiFab *xheat_flux, amrex::MultiFab *yheat_flux, amrex::MultiFab *zheat_flux, amrex::MultiFab *xqv_flux, amrex::MultiFab *yqv_flux, amrex::MultiFab *zqv_flux, const amrex::MultiFab *z_phys, const FluxCalc &flux_comp)
RoughCalcType rough_type_sea
Definition: ERF_SurfaceLayer.H:721
void init_tke_from_ustar(const int &lev, amrex::MultiFab &cons, const std::unique_ptr< amrex::MultiFab > &z_phys_nd, const amrex::Real tkefac=one, const amrex::Real zscale=amrex::Real(700.0))
Definition: ERF_SurfaceLayer.cpp:1204
amrex::Real surf_moist
Definition: ERF_SurfaceLayer.H:739
amrex::Vector< std::unique_ptr< amrex::MultiFab > > w_star
Definition: ERF_SurfaceLayer.H:771
bool m_ignore_sst
Definition: ERF_SurfaceLayer.H:765
amrex::MultiFab * get_u_star(const int &lev)
Definition: ERF_SurfaceLayer.H:625
SurfaceLayer(const amrex::Vector< amrex::Geometry > &geom, bool &use_rot_surface_flux, 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 MeshType &a_mesh_type, const TerrainType &a_terrain_type, const TurbChoice &a_turb_choice, amrex::Real start_low_time, amrex::Real final_low_time, amrex::Real low_time_interval=zero, const amrex::Vector< const eb_ * > &eb_vec={})
Definition: ERF_SurfaceLayer.H:38
void compute_fluxes(const int &lev, const int &max_iters, amrex::MultiFab &cons_in, const FluxIter &most_flux, bool is_land)
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_lsm_data_lev
Definition: ERF_SurfaceLayer.H:786
void set_t_surf(const int &lev, const amrex::Real tsurf)
Definition: ERF_SurfaceLayer.H:643
amrex::Real custom_qstar
Definition: ERF_SurfaceLayer.H:743
amrex::Vector< std::unique_ptr< amrex::MultiFab > > u_star
Definition: ERF_SurfaceLayer.H:770
void update_tsk_ptr(const int lev, const int itime, amrex::MultiFab *tsk_ptr)
Definition: ERF_SurfaceLayer.H:682
amrex::Real custom_rhosurf
Definition: ERF_SurfaceLayer.H:744
amrex::Vector< std::unique_ptr< amrex::MultiFab > > q_surf
Definition: ERF_SurfaceLayer.H:777
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_sst_lev
Definition: ERF_SurfaceLayer.H:783
FluxCalcType
Definition: ERF_SurfaceLayer.H:686
@ MOENG
Moeng functional form.
@ BULK_COEFF
Bulk transfer coefficient functional form.
@ CUSTOM
Custom constant flux functional form.
@ ROTATE
Terrain rotation flux functional form.
@ DONELAN
Donelan functional form.
MoistCalcType
Definition: ERF_SurfaceLayer.H:701
@ SURFACE_MOISTURE
Surface Qv specified.
@ MOISTURE_FLUX
Qv-flux specified.
amrex::Real depth
Definition: ERF_SurfaceLayer.H:748
amrex::Vector< amrex::MultiFab * > m_Hwave_lev
Definition: ERF_SurfaceLayer.H:790
amrex::Real default_land_surf_moist
Definition: ERF_SurfaceLayer.H:738
bool m_var_z0
Definition: ERF_SurfaceLayer.H:750
amrex::MultiFab * get_surface_diagnostic_source(const int &lev)
Definition: ERF_SurfaceLayer.H:648
amrex::MultiFab * get_t_star(const int &lev)
Definition: ERF_SurfaceLayer.H:629
bool have_variable_sea_roughness()
Definition: ERF_SurfaceLayer.H:654
void impose_SurfaceLayer_bcs_EB(const int &lev, amrex::Vector< const amrex::MultiFab * > mfs, amrex::Vector< amrex::Vector< std::unique_ptr< amrex::MultiFab >>> &Tau_lev, amrex::MultiFab *xheat_flux, amrex::MultiFab *yheat_flux, amrex::MultiFab *zheat_flux, amrex::MultiFab *xqv_flux, amrex::MultiFab *yqv_flux, amrex::MultiFab *zqv_flux)
Definition: ERF_SurfaceLayer.cpp:447
amrex::MultiFab * get_q_star(const int &lev)
Definition: ERF_SurfaceLayer.H:631
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_lsm_flux_lev
Definition: ERF_SurfaceLayer.H:787
PBLHeightCalcType
Definition: ERF_SurfaceLayer.H:715
amrex::MultiFab * get_pblh(const int &lev)
Definition: ERF_SurfaceLayer.H:635
void compute_SurfaceLayer_bcs_EB(const int &lev, amrex::Vector< const amrex::MultiFab * > mfs, amrex::Vector< amrex::Vector< std::unique_ptr< amrex::MultiFab >>> &Tau_lev, amrex::MultiFab *xheat_flux, amrex::MultiFab *yheat_flux, amrex::MultiFab *zheat_flux, amrex::MultiFab *xqv_flux, amrex::MultiFab *yqv_flux, amrex::MultiFab *zqv_flux, const FluxCalc &flux_comp)
amrex::Real rico_theta_z0
Definition: ERF_SurfaceLayer.H:752
void fill_tsurf_with_sst_and_tsk(const int &lev, const amrex::Real &time)
Definition: ERF_SurfaceLayer.cpp:1009
amrex::Real surf_temp_flux
Definition: ERF_SurfaceLayer.H:737
amrex::Vector< amrex::Geometry > m_geom
Definition: ERF_SurfaceLayer.H:726
amrex::Vector< std::unique_ptr< amrex::MultiFab > > t_star
Definition: ERF_SurfaceLayer.H:772
amrex::Real theta_ref
Definition: ERF_SurfaceLayer.H:796
amrex::MultiFab * get_z0(const int &lev)
Definition: ERF_SurfaceLayer.H:652
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_tsk_lev
Definition: ERF_SurfaceLayer.H:784
amrex::Real custom_tstar
Definition: ERF_SurfaceLayer.H:742
amrex::Real m_final_low_time
Definition: ERF_SurfaceLayer.H:729
bool cnk_visc
Definition: ERF_SurfaceLayer.H:747
amrex::Real surf_heating_rate
Definition: ERF_SurfaceLayer.H:736
void make_SurfaceLayer_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< std::string > lsm_data_name, amrex::Vector< amrex::MultiFab * > lsm_flux, amrex::Vector< std::string > lsm_flux_name, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &sst_lev, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &tsk_lev, amrex::Vector< std::unique_ptr< amrex::iMultiFab >> &lmask_lev)
Definition: ERF_SurfaceLayer.H:275
bool m_has_ocean_lsm_tsurf
Definition: ERF_SurfaceLayer.H:758
RoughCalcType
Definition: ERF_SurfaceLayer.H:707
FluxCalcType flux_type
Definition: ERF_SurfaceLayer.H:717
MoistCalcType moist_type
Definition: ERF_SurfaceLayer.H:719
void compute_sfc_params_from_lsm_fluxes(const int &lev, amrex::MultiFab &cons_in)
Definition: ERF_SurfaceLayer.cpp:940
amrex::Real inv_Cmu2
Definition: ERF_SurfaceLayer.H:795
void impose_SurfaceLayer_bcs(const int &lev, amrex::Vector< const amrex::MultiFab * > mfs, amrex::Vector< std::unique_ptr< amrex::MultiFab >> &Tau_lev, amrex::MultiFab *xheat_flux, amrex::MultiFab *yheat_flux, amrex::MultiFab *zheat_flux, amrex::MultiFab *xqv_flux, amrex::MultiFab *yqv_flux, amrex::MultiFab *zqv_flux, const amrex::MultiFab *z_phys)
Definition: ERF_SurfaceLayer.cpp:387
amrex::Vector< amrex::MultiFab * > m_eddyDiffs_lev
Definition: ERF_SurfaceLayer.H:792
const amrex::MultiFab * get_mac_avg(const int &lev, int comp)
Definition: ERF_SurfaceLayer.H:637
void update_sst_ptr(const int lev, const int itime, amrex::MultiFab *sst_ptr)
Definition: ERF_SurfaceLayer.H:678
amrex::Real custom_ustar
Definition: ERF_SurfaceLayer.H:741
amrex::Vector< std::unique_ptr< amrex::MultiFab > > olen
Definition: ERF_SurfaceLayer.H:774
amrex::MultiFab * get_t_surf(const int &lev)
Definition: ERF_SurfaceLayer.H:642
amrex::Real m_Cd
Definition: ERF_SurfaceLayer.H:761
amrex::Vector< std::unique_ptr< amrex::MultiFab > > pblh
Definition: ERF_SurfaceLayer.H:775
amrex::Real default_land_surf_temp
Definition: ERF_SurfaceLayer.H:734
ThetaCalcType
Definition: ERF_SurfaceLayer.H:695
@ SURFACE_TEMPERATURE
Surface temperature specified.
@ HEAT_FLUX
Heat-flux specified.
void read_custom_roughness(const int &lev, const std::string &fname)
Definition: ERF_SurfaceLayer.cpp:1273
TerrainType m_terrain_type
Definition: ERF_SurfaceLayer.H:768
amrex::Vector< std::string > m_lsm_flux_name
Definition: ERF_SurfaceLayer.H:789
amrex::Real m_low_time_interval
Definition: ERF_SurfaceLayer.H:730
MOSTAverage m_ma
Definition: ERF_SurfaceLayer.H:769
@ ng
Definition: ERF_Morrison.H:48
@ cons
Definition: ERF_IndexDefines.H:174
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real to_plot_value(SurfaceDiagnosticSource source) noexcept
Definition: ERF_SurfaceDiagnosticSource.H:35
Definition: ERF_DataStruct.H:106
Definition: ERF_TurbStruct.H:82
RANSType rans_type
Definition: ERF_TurbStruct.H:473
bool dirichlet_k
Definition: ERF_TurbStruct.H:475
amrex::Real Cmu0
Definition: ERF_TurbStruct.H:451
amrex::Real theta_ref
Definition: ERF_TurbStruct.H:462