ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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_Interpolater.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_TerrainMetrics.H"
16 #include "ERF_PBLHeight.H"
17 
18 /** Abstraction layer for different surface layer schemes (e.g. MOST, Cd)
19  *
20  * van der Laan, P., Kelly, M. C., & Sørensen, N. N. (2017). A new k-epsilon
21  * model consistent with Monin-Obukhov similarity theory. Wind Energy,
22  * 20(3), 479–489. https://doi.org/10.1002/we.2017
23  *
24  * Consistent with Dyer (1974) formulation from page 57, Chapter 2, Modeling
25  * the vertical ABL structure in Modelling of Atmospheric Flow Fields,
26  * Demetri P Lalas and Corrado F Ratto, January 1996,
27  * https://doi.org/10.1142/2975.
28  */
30 {
31 
32 public:
33  // Constructor
34  explicit SurfaceLayer (const amrex::Vector<amrex::Geometry>& geom,
35  bool& use_rot_surface_flux,
36  std::string a_pp_prefix,
37  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Qv_prim,
38  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& z_phys_nd,
39  const TerrainType& a_terrain_type,
40  amrex::Real start_bdy_time = 0.0,
41  amrex::Real bdy_time_interval = 0.0)
42  : m_geom(geom),
43  m_rotate(use_rot_surface_flux),
44  m_start_bdy_time(start_bdy_time),
45  m_bdy_time_interval(bdy_time_interval),
46  m_ma(geom, (z_phys_nd[0] != nullptr), a_pp_prefix, a_terrain_type)
47  {
48  // We have a moisture model if Qv_prim is a valid pointer
49  use_moisture = (Qv_prim[0].get());
50 
51  // Get roughness
52  amrex::ParmParse pp("erf");
53  pp.query("most.z0", z0_const);
54 
55  // Specify how to compute the flux
56  if (use_rot_surface_flux) {
58  } else {
59  std::string flux_string_in;
60  std::string flux_string{"moeng"};
61  auto read_flux = pp.query("surface_layer.flux_type", flux_string_in);
62  if (read_flux) {
63  flux_string = amrex::toLower(flux_string_in);
64  }
65  if (flux_string == "donelan") {
67  } else if (flux_string == "moeng") {
69  } else if (flux_string == "custom") {
71  } else {
72  amrex::Abort("Undefined MOST flux type!");
73  }
74  }
75 
76  // Include w* to handle free convection (Beljaars 1995, QJRMS)
77  pp.query("most.include_wstar", m_include_wstar);
78 
79  std::string pblh_string_in;
80  std::string pblh_string{"none"};
81  auto read_pblh = pp.query("most.pblh_calc", pblh_string_in);
82  if (read_pblh) {
83  pblh_string = amrex::toLower(pblh_string_in);
84  }
85  if (pblh_string == "none") {
87  } else if (pblh_string == "mynn25") {
89  } else if (pblh_string == "mynnedmf") {
91  } else if (pblh_string == "ysu") {
93  } else if (pblh_string == "mrf") {
95  } else {
96  amrex::Abort("Undefined PBLH calc type!");
97  }
98 
99  // Get surface temperature
100  auto erf_st = pp.query("most.surf_temp", surf_temp);
101  if (erf_st) { default_land_surf_temp = surf_temp; }
102 
103  // Get surface moisture
104  bool erf_sq = false;
105  if (use_moisture) { erf_sq = pp.query("most.surf_moist", surf_moist); }
106  if (erf_sq) { default_land_surf_moist = surf_moist; }
107 
108  // Custom type user must specify the fluxes
112  pp.query("most.ustar", custom_ustar);
113  pp.query("most.tstar", custom_tstar);
114  pp.query("most.qstar", custom_qstar);
115  pp.query("most.rhosurf", custom_rhosurf);
116  if (custom_qstar != 0) {
117  AMREX_ASSERT_WITH_MESSAGE(use_moisture,
118  "Specified custom MOST qv flux without moisture model!");
119  }
120  amrex::Print() << "Using specified ustar, tstar, qstar for MOST = "
121  << custom_ustar << " " << custom_tstar << " "
122  << custom_qstar << std::endl;
123 
124  // Specify surface temperature/moisture or surface flux
125  } else {
126  if (erf_st) {
128  pp.query("most.surf_heating_rate", surf_heating_rate); // [K/h]
129  surf_heating_rate = surf_heating_rate / 3600.0; // [K/s]
130  if (pp.query("most.surf_temp_flux", surf_temp_flux)) {
131  amrex::Abort("Can only specify one of surf_temp_flux or surf_heating_rate");
132  }
133  } else {
134  pp.query("most.surf_temp_flux", surf_temp_flux);
135 
136  if (pp.query("most.surf_heating_rate", surf_heating_rate)) {
137  amrex::Abort("Can only specify one of surf_temp_flux or surf_heating_rate");
138  }
139  if (std::abs(surf_temp_flux) >
142  } else {
144  }
145 
146  }
147 
148  if (erf_sq) {
150  } else {
151  pp.query("most.surf_moist_flux", surf_moist_flux);
152  if (std::abs(surf_moist_flux) >
155  } else {
157  }
158  }
159  }
160 
161  // Make sure the inputs file doesn't try to use most.roughness_type
162  std::string bogus_input;
163  if (pp.query("most.roughness_type", bogus_input) > 0) {
164  amrex::Abort("most.roughness_type is deprecated; use "
165  "most.roughness_type_land and/or most.roughness_type_sea");
166  }
167 
168  // Specify how to compute the surface flux over land (if there is any)
169  std::string rough_land_string_in;
170  std::string rough_land_string{"constant"};
171  auto read_rough_land =
172  pp.query("most.roughness_type_land", rough_land_string_in);
173  if (read_rough_land) {
174  rough_land_string = amrex::toLower(rough_land_string_in);
175  }
176  if (rough_land_string == "constant") {
178  } else {
179  amrex::Abort("Undefined MOST roughness type for land!");
180  }
181 
182  // Specify how to compute the surface flux over sea (if there is any)
183  std::string rough_sea_string_in;
184  std::string rough_sea_string{"charnock"};
185  auto read_rough_sea = pp.query("most.roughness_type_sea", rough_sea_string_in);
186  if (read_rough_sea) {
187  rough_sea_string = amrex::toLower(rough_sea_string_in);
188  }
189  if (rough_sea_string == "charnock") {
191  pp.query("most.charnock_constant", cnk_a);
192  pp.query("most.charnock_viscosity", cnk_visc);
193  if (cnk_a > 0) {
194  amrex::Print() << "If there is water, Charnock relation with C_a="
195  << cnk_a << (cnk_visc ? " and viscosity" : "")
196  << " will be used" << std::endl;
197  } else {
198  amrex::Print() << "If there is water, Charnock relation with variable "
199  "Charnock parameter (COARE3.0)"
200  << (cnk_visc ? " and viscosity" : "") << " will be used"
201  << std::endl;
202  }
203  } else if (rough_sea_string == "coare3.0") {
205  amrex::Print() << "If there is water, Charnock relation with variable "
206  "Charnock parameter (COARE3.0)"
207  << (cnk_visc ? " and viscosity" : "") << " will be used"
208  << std::endl;
209  cnk_a = -1;
210  } else if (rough_sea_string == "donelan") {
212  } else if (rough_sea_string == "modified_charnock") {
214  pp.query("most.modified_charnock_depth", depth);
215  } else if (rough_sea_string == "wave_coupled") {
217  } else if (rough_sea_string == "constant") {
219  } else {
220  amrex::Abort("Undefined MOST roughness type for sea!");
221  }
222  } // constructor
223 
224  void make_SurfaceLayer_at_level (const int& lev,
225  int nlevs,
226  const amrex::Vector<amrex::MultiFab*>& mfv,
227  std::unique_ptr<amrex::MultiFab>& Theta_prim,
228  std::unique_ptr<amrex::MultiFab>& Qv_prim,
229  std::unique_ptr<amrex::MultiFab>& Qr_prim,
230  std::unique_ptr<amrex::MultiFab>& z_phys_nd,
231  amrex::MultiFab* Hwave,
232  amrex::MultiFab* Lwave,
233  amrex::MultiFab* eddyDiffs,
234  amrex::Vector<amrex::MultiFab*> lsm_data,
235  amrex::Vector<amrex::MultiFab*> lsm_flux,
236  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& sst_lev,
237  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& tsk_lev,
238  amrex::Vector<std::unique_ptr<amrex::iMultiFab>>& lmask_lev)
239  {
240  // Update MOST Average
242  Theta_prim, Qv_prim, Qr_prim,
243  z_phys_nd);
244 
245  // Get CC vars
246  amrex::MultiFab& mf = *(mfv[0]);
247 
248  amrex::ParmParse pp("erf");
249 
250  // Do we have a time-varying surface roughness that needs to be saved?
251  if (lev == 0) {
252  const int nghost = 0; // ghost cells not included
253  int lmask_min = lmask_min_reduce(*lmask_lev[0].get(), nghost);
254  amrex::ParallelDescriptor::ReduceIntMin(lmask_min);
255 
256  m_var_z0 = (lmask_min < 1) & (rough_type_sea != RoughCalcType::CONSTANT);
257  if (m_var_z0) {
258  std::string rough_sea_string{"charnock"};
259  pp.query("most.roughness_type_sea", rough_sea_string);
260  amrex::Print() << "Variable sea roughness (type " << rough_sea_string
261  << ")" << std::endl;
262  }
263  }
264 
265  if ((lev == 0) || (lev > nlevs - 1)) {
266  m_Hwave_lev.resize(nlevs);
267  m_Lwave_lev.resize(nlevs);
268  m_eddyDiffs_lev.resize(nlevs);
269 
270  m_lsm_data_lev.resize(nlevs);
271  m_lsm_flux_lev.resize(nlevs);
272 
273  m_sst_lev.resize(nlevs);
274  m_tsk_lev.resize(nlevs);
275  m_lmask_lev.resize(nlevs);
276 
277  // Size the MOST params for all levels
278  z_0.resize(nlevs);
279  u_star.resize(nlevs);
280  w_star.resize(nlevs);
281  t_star.resize(nlevs);
282  q_star.resize(nlevs);
283  t_surf.resize(nlevs);
284  q_surf.resize(nlevs);
285  olen.resize(nlevs);
286  pblh.resize(nlevs);
287  }
288 
289  // Get pointers to SST,TSK and LANDMASK data
290  int nt_tot_sst = sst_lev.size();
291  m_sst_lev[lev].resize(nt_tot_sst);
292  for (int nt(0); nt < nt_tot_sst; ++nt) {
293  m_sst_lev[lev][nt] = sst_lev[nt].get();
294  }
295  int nt_tot_tsk = tsk_lev.size();
296  m_tsk_lev[lev].resize(nt_tot_tsk);
297  for (int nt(0); nt < nt_tot_tsk; ++nt) {
298  m_tsk_lev[lev][nt] = tsk_lev[nt].get();
299  }
300  int nt_tot_lmask = lmask_lev.size();
301  m_lmask_lev[lev].resize(nt_tot_lmask);
302  for (int nt(0); nt < nt_tot_lmask; ++nt) {
303  m_lmask_lev[lev][nt] = lmask_lev[nt].get();
304  }
305 
306  // Get pointers to wave data
307  m_Hwave_lev[lev] = Hwave;
308  m_Lwave_lev[lev] = Lwave;
309  m_eddyDiffs_lev[lev] = eddyDiffs;
310 
311  // Get pointers to LSM data and Fluxes
312  int nvar = lsm_data.size();
313  m_lsm_data_lev[lev].resize(nvar);
314  m_lsm_flux_lev[lev].resize(nvar);
315  for (int n(0); n < nvar; ++n) {
316  m_lsm_data_lev[lev][n] = lsm_data[n];
317  m_lsm_flux_lev[lev][n] = lsm_flux[n];
318  }
319 
320  // Check if there is a user-specified roughness file to be read
321  std::string fname;
322  bool read_z0 = false;
323  if ( (flux_type == FluxCalcType::MOENG) ||
325  read_z0 = pp.query("most.roughness_file_name", fname);
326  }
327 
328  // Attributes for MFs and FABs
329  //--------------------------------------------------------
330  // Create a 2D ba, dm, & ghost cells
331  amrex::BoxArray ba = mf.boxArray();
332  amrex::BoxList bl2d = ba.boxList();
333  for (auto& b : bl2d) {
334  b.setRange(2, 0);
335  }
336  amrex::BoxArray ba2d(std::move(bl2d));
337  const amrex::DistributionMapping& dm = mf.DistributionMap();
338  const int ncomp = 1;
339  amrex::IntVect ng = mf.nGrowVect();
340  ng[2] = 0;
341 
342  // Z0 heights FAB
343  //--------------------------------------------------------
344  amrex::Arena* Arena_Used = amrex::The_Arena();
345 #ifdef AMREX_USE_GPU
346  Arena_Used = amrex::The_Pinned_Arena();
347 #endif
348  amrex::Box bx = amrex::grow(m_geom[lev].Domain(), ng);
349  bx.setSmall(2, 0);
350  bx.setBig(2, 0);
351  z_0[lev].resize(bx, 1, Arena_Used);
352  z_0[lev].setVal<amrex::RunOn::Device>(z0_const);
353  if (read_z0) {
354  read_custom_roughness(lev, fname);
355  }
356 
357  // 2D MFs for U*, T*, T_surf
358  //--------------------------------------------------------
359  u_star[lev] = std::make_unique<amrex::MultiFab>(ba2d, dm, ncomp, ng);
360  u_star[lev]->setVal(1.E34);
361 
362  w_star[lev] = std::make_unique<amrex::MultiFab>(ba2d, dm, ncomp, ng);
363  w_star[lev]->setVal(1.E34);
364 
365  t_star[lev] = std::make_unique<amrex::MultiFab>(ba2d, dm, ncomp, ng);
366  t_star[lev]->setVal(0.0); // default to neutral
367 
368  q_star[lev] = std::make_unique<amrex::MultiFab>(ba2d, dm, ncomp, ng);
369  q_star[lev]->setVal(0.0); // default to dry
370 
371  olen[lev] = std::make_unique<amrex::MultiFab>(ba2d, dm, ncomp, ng);
372  olen[lev]->setVal(1.E34);
373 
374  pblh[lev] = std::make_unique<amrex::MultiFab>(ba2d, dm, ncomp, ng);
375  pblh[lev]->setVal(1.E34);
376 
377  t_surf[lev] = std::make_unique<amrex::MultiFab>(ba2d, dm, ncomp, ng);
378  t_surf[lev]->setVal(default_land_surf_temp);
379 
380  q_surf[lev] = std::make_unique<amrex::MultiFab>(ba2d, dm, ncomp, ng);
381  q_surf[lev]->setVal(default_land_surf_moist);
382 
383  // TODO: Do we want lsm_data to have theta at 0 index always?
384  // Do we want an external enum struct for indexing?
385  if (m_sst_lev[lev][0] || m_tsk_lev[lev][0] || m_lsm_data_lev[lev][0]) {
386  // Valid SST, TSK or LSM data; t_surf set before computing fluxes (avoids
387  // extended lambda capture) Note that land temp will be set from m_tsk_lev
388  // while sea temp will be set from m_sst_lev
390  }
391 
392 
393  }
394 
395  void
396  update_fluxes (const int& lev,
397  const amrex::Real& time,
398  int max_iters = 500);
399 
400  template <typename FluxIter>
401  void compute_fluxes (const int& lev,
402  const int& max_iters,
403  const FluxIter& most_flux,
404  bool is_land);
405 
406  void impose_SurfaceLayer_bcs (const int& lev,
407  amrex::Vector<const amrex::MultiFab*> mfs,
408  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Tau_lev,
409  amrex::MultiFab* xheat_flux,
410  amrex::MultiFab* yheat_flux,
411  amrex::MultiFab* zheat_flux,
412  amrex::MultiFab* xqv_flux,
413  amrex::MultiFab* yqv_flux,
414  amrex::MultiFab* zqv_flux,
415  const amrex::MultiFab* z_phys);
416 
417  template <typename FluxCalc>
418  void compute_SurfaceLayer_bcs (const int& lev,
419  amrex::Vector<const amrex::MultiFab*> mfs,
420  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Tau_lev,
421  amrex::MultiFab* xheat_flux,
422  amrex::MultiFab* yheat_flux,
423  amrex::MultiFab* zheat_flux,
424  amrex::MultiFab* xqv_flux,
425  amrex::MultiFab* yqv_flux,
426  amrex::MultiFab* zqv_flux,
427  const amrex::MultiFab* z_phys,
428  const FluxCalc& flux_comp);
429 
430  void fill_tsurf_with_sst_and_tsk (const int& lev,
431  const amrex::Real& time);
432 
433  void get_lsm_tsurf (const int& lev);
434 
435  /* wrapper around compute_pblh */
436  void update_pblh (const int& lev,
437  amrex::Vector<amrex::Vector<amrex::MultiFab>>& vars,
438  amrex::MultiFab* z_phys_cc,
439  const MoistureComponentIndices& moisture_indices);
440 
441  template <typename PBLHeightEstimator>
442  void compute_pblh (const int& lev,
443  amrex::Vector<amrex::Vector<amrex::MultiFab>>& vars,
444  amrex::MultiFab* z_phys_cc,
445  const PBLHeightEstimator& est,
446  const MoistureComponentIndices& moisture_indice);
447 
448  void read_custom_roughness (const int& lev,
449  const std::string& fname);
450 
451  void update_surf_temp (const amrex::Real& time)
452  {
453  if (surf_heating_rate != 0) {
454  int nlevs = m_geom.size();
455  for (int lev = 0; lev < nlevs; lev++) {
456  t_surf[lev]->setVal(surf_temp + surf_heating_rate * time);
457  amrex::Print() << "Surface temp at t=" << time << ": "
458  << surf_temp + surf_heating_rate * time << std::endl;
459  }
460  }
461  }
462 
463  void update_mac_ptrs (const int& lev,
464  amrex::Vector<amrex::Vector<amrex::MultiFab>>& vars_old,
465  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Theta_prim,
466  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Qv_prim,
467  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Qr_prim)
468  {
469  m_ma.update_field_ptrs(lev, vars_old, Theta_prim, Qv_prim, Qr_prim);
470  }
471 
472  amrex::MultiFab* get_u_star (const int& lev) { return u_star[lev].get(); }
473 
474  amrex::MultiFab* get_w_star (const int& lev) { return w_star[lev].get(); }
475 
476  amrex::MultiFab* get_t_star (const int& lev) { return t_star[lev].get(); }
477 
478  amrex::MultiFab* get_q_star (const int& lev) { return q_star[lev].get(); }
479 
480  amrex::MultiFab* get_olen (const int& lev) { return olen[lev].get(); }
481 
482  amrex::MultiFab* get_pblh (const int& lev) { return pblh[lev].get(); }
483 
484  const amrex::MultiFab* get_mac_avg (const int& lev, int comp)
485  {
486  return m_ma.get_average(lev, comp);
487  }
488 
489  amrex::MultiFab* get_t_surf (const int& lev) { return t_surf[lev].get(); }
490 
491  amrex::MultiFab* get_q_surf (const int& lev) { return q_surf[lev].get(); }
492 
493  amrex::Real get_zref () { return m_ma.get_zref(); }
494 
495  amrex::FArrayBox* get_z0 (const int& lev) { return &z_0[lev]; }
496 
498 
499  amrex::iMultiFab* get_lmask (const int& lev) { return m_lmask_lev[lev][0]; }
500 
501  int lmask_min_reduce (amrex::iMultiFab& lmask,
502  const int& nghost)
503  {
504  int lmask_min = amrex::ReduceMin(lmask, nghost, [=] AMREX_GPU_HOST_DEVICE(
505  amrex::Box const& bx, amrex::Array4<int const> const& lm_arr) -> int
506  {
507  int locmin = std::numeric_limits<int>::max();
508  const auto lo = lbound(bx);
509  const auto hi = ubound(bx);
510  for (int j = lo.y; j <= hi.y; ++j) {
511  for (int i = lo.x; i <= hi.x; ++i) {
512  locmin = std::min(locmin, lm_arr(i, j, 0));
513  }
514  }
515  return locmin;
516  });
517 
518  return lmask_min;
519  }
520 
521  enum struct FluxCalcType {
522  MOENG = 0, ///< Moeng functional form
523  DONELAN, ///< Donelan functional form
524  CUSTOM, ///< Custom constant flux functional form
525  ROTATE ///< Terrain rotation flux functional form
526  };
527 
528  enum struct ThetaCalcType {
529  ADIABATIC = 0,
530  HEAT_FLUX, ///< Heat-flux specified
531  SURFACE_TEMPERATURE ///< Surface temperature specified
532  };
533 
534  enum struct MoistCalcType {
535  ADIABATIC = 0,
536  MOISTURE_FLUX, ///< Qv-flux specified
537  SURFACE_MOISTURE ///< Surface Qv specified
538  };
539 
540  enum struct RoughCalcType {
541  CONSTANT = 0, ///< Constant z0
542  CHARNOCK,
544  DONELAN,
546  };
547 
548  enum struct PBLHeightCalcType { None, MYNN25, YSU, MRF };
549 
556 
557 private:
558  // Set in constructor
559  amrex::Vector<amrex::Geometry> m_geom;
560  bool m_rotate = false;
561  amrex::Real m_start_bdy_time;
562  amrex::Real m_bdy_time_interval;
563 
564  bool m_include_wstar = false;
565  amrex::Real z0_const{0.1};
566  amrex::Real default_land_surf_temp{300.};
567  amrex::Real surf_temp;
568  amrex::Real surf_heating_rate{0};
569  amrex::Real surf_temp_flux{0};
570  amrex::Real default_land_surf_moist{0.};
571  amrex::Real surf_moist;
572  amrex::Real surf_moist_flux{0};
573  amrex::Real custom_ustar{0};
574  amrex::Real custom_tstar{0};
575  amrex::Real custom_qstar{0};
576  amrex::Real custom_rhosurf{0}; // use specified value instead of rho from first cell
577  bool specified_rho_surf{false};
578  amrex::Real cnk_a{0.0185};
579  bool cnk_visc{false};
580  amrex::Real depth{30.0};
581  amrex::Vector<amrex::FArrayBox> z_0;
582  bool m_var_z0{false};
583 
585 
587  amrex::Vector<std::unique_ptr<amrex::MultiFab>> u_star;
588  amrex::Vector<std::unique_ptr<amrex::MultiFab>> w_star;
589  amrex::Vector<std::unique_ptr<amrex::MultiFab>> t_star;
590  amrex::Vector<std::unique_ptr<amrex::MultiFab>> q_star;
591  amrex::Vector<std::unique_ptr<amrex::MultiFab>> olen;
592  amrex::Vector<std::unique_ptr<amrex::MultiFab>> pblh;
593  amrex::Vector<std::unique_ptr<amrex::MultiFab>> t_surf;
594  amrex::Vector<std::unique_ptr<amrex::MultiFab>> q_surf;
595 
596  amrex::Vector<amrex::Vector<amrex::MultiFab*>> m_sst_lev;
597  amrex::Vector<amrex::Vector<amrex::MultiFab*>> m_tsk_lev;
598  amrex::Vector<amrex::Vector<amrex::iMultiFab*>> m_lmask_lev;
599  amrex::Vector<amrex::Vector<amrex::MultiFab*>> m_lsm_data_lev;
600  amrex::Vector<amrex::Vector<amrex::MultiFab*>> m_lsm_flux_lev;
601  amrex::Vector<amrex::MultiFab*> m_Hwave_lev;
602  amrex::Vector<amrex::MultiFab*> m_Lwave_lev;
603  amrex::Vector<amrex::MultiFab*> m_eddyDiffs_lev;
604 };
605 
606 #endif /* SURFACELAYER_H */
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real pp(amrex::Real y)
Definition: ERF_MicrophysicsUtils.H:230
Definition: ERF_MOSTAverage.H:14
amrex::Real get_zref() const
Definition: ERF_MOSTAverage.H:104
const amrex::MultiFab * get_average(const int &lev, const int &comp) const
Definition: ERF_MOSTAverage.H:101
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:246
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:70
Definition: ERF_SurfaceLayer.H:30
ThetaCalcType theta_type
Definition: ERF_SurfaceLayer.H:551
int lmask_min_reduce(amrex::iMultiFab &lmask, const int &nghost)
Definition: ERF_SurfaceLayer.H:501
bool m_include_wstar
Definition: ERF_SurfaceLayer.H:564
bool specified_rho_surf
Definition: ERF_SurfaceLayer.H:577
bool m_rotate
Definition: ERF_SurfaceLayer.H:560
PBLHeightCalcType pblh_type
Definition: ERF_SurfaceLayer.H:555
amrex::Vector< amrex::Vector< amrex::iMultiFab * > > m_lmask_lev
Definition: ERF_SurfaceLayer.H:598
amrex::iMultiFab * get_lmask(const int &lev)
Definition: ERF_SurfaceLayer.H:499
bool use_moisture
Definition: ERF_SurfaceLayer.H:584
amrex::MultiFab * get_q_surf(const int &lev)
Definition: ERF_SurfaceLayer.H:491
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 TerrainType &a_terrain_type, amrex::Real start_bdy_time=0.0, amrex::Real bdy_time_interval=0.0)
Definition: ERF_SurfaceLayer.H:34
amrex::MultiFab * get_w_star(const int &lev)
Definition: ERF_SurfaceLayer.H:474
void update_surf_temp(const amrex::Real &time)
Definition: ERF_SurfaceLayer.H:451
RoughCalcType rough_type_land
Definition: ERF_SurfaceLayer.H:553
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:558
amrex::Vector< std::unique_ptr< amrex::MultiFab > > t_surf
Definition: ERF_SurfaceLayer.H:593
amrex::Real z0_const
Definition: ERF_SurfaceLayer.H:565
amrex::Real cnk_a
Definition: ERF_SurfaceLayer.H:578
amrex::Vector< amrex::FArrayBox > z_0
Definition: ERF_SurfaceLayer.H:581
amrex::Real surf_temp
Definition: ERF_SurfaceLayer.H:567
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:463
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< amrex::MultiFab * > lsm_flux, 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:224
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:590
amrex::Real m_start_bdy_time
Definition: ERF_SurfaceLayer.H:561
amrex::Vector< amrex::MultiFab * > m_Lwave_lev
Definition: ERF_SurfaceLayer.H:602
void get_lsm_tsurf(const int &lev)
Definition: ERF_SurfaceLayer.cpp:525
amrex::MultiFab * get_olen(const int &lev)
Definition: ERF_SurfaceLayer.H:480
amrex::Real surf_moist_flux
Definition: ERF_SurfaceLayer.H:572
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:554
void update_fluxes(const int &lev, const amrex::Real &time, int max_iters=500)
Definition: ERF_SurfaceLayer.cpp:12
amrex::Real surf_moist
Definition: ERF_SurfaceLayer.H:571
amrex::Vector< std::unique_ptr< amrex::MultiFab > > w_star
Definition: ERF_SurfaceLayer.H:588
amrex::MultiFab * get_u_star(const int &lev)
Definition: ERF_SurfaceLayer.H:472
amrex::Real m_bdy_time_interval
Definition: ERF_SurfaceLayer.H:562
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_lsm_data_lev
Definition: ERF_SurfaceLayer.H:599
amrex::Real custom_qstar
Definition: ERF_SurfaceLayer.H:575
amrex::Vector< std::unique_ptr< amrex::MultiFab > > u_star
Definition: ERF_SurfaceLayer.H:587
amrex::Real custom_rhosurf
Definition: ERF_SurfaceLayer.H:576
amrex::Vector< std::unique_ptr< amrex::MultiFab > > q_surf
Definition: ERF_SurfaceLayer.H:594
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_sst_lev
Definition: ERF_SurfaceLayer.H:596
FluxCalcType
Definition: ERF_SurfaceLayer.H:521
@ MOENG
Moeng functional form.
@ CUSTOM
Custom constant flux functional form.
@ ROTATE
Terrain rotation flux functional form.
@ DONELAN
Donelan functional form.
MoistCalcType
Definition: ERF_SurfaceLayer.H:534
@ SURFACE_MOISTURE
Surface Qv specified.
@ MOISTURE_FLUX
Qv-flux specified.
amrex::Real depth
Definition: ERF_SurfaceLayer.H:580
amrex::Vector< amrex::MultiFab * > m_Hwave_lev
Definition: ERF_SurfaceLayer.H:601
amrex::Real default_land_surf_moist
Definition: ERF_SurfaceLayer.H:570
bool m_var_z0
Definition: ERF_SurfaceLayer.H:582
amrex::MultiFab * get_t_star(const int &lev)
Definition: ERF_SurfaceLayer.H:476
bool have_variable_sea_roughness()
Definition: ERF_SurfaceLayer.H:497
void compute_fluxes(const int &lev, const int &max_iters, const FluxIter &most_flux, bool is_land)
Definition: ERF_SurfaceLayer.cpp:178
amrex::MultiFab * get_q_star(const int &lev)
Definition: ERF_SurfaceLayer.H:478
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_lsm_flux_lev
Definition: ERF_SurfaceLayer.H:600
PBLHeightCalcType
Definition: ERF_SurfaceLayer.H:548
amrex::MultiFab * get_pblh(const int &lev)
Definition: ERF_SurfaceLayer.H:482
void fill_tsurf_with_sst_and_tsk(const int &lev, const amrex::Real &time)
Definition: ERF_SurfaceLayer.cpp:452
amrex::Real surf_temp_flux
Definition: ERF_SurfaceLayer.H:569
amrex::Vector< amrex::Geometry > m_geom
Definition: ERF_SurfaceLayer.H:559
amrex::Vector< std::unique_ptr< amrex::MultiFab > > t_star
Definition: ERF_SurfaceLayer.H:589
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_tsk_lev
Definition: ERF_SurfaceLayer.H:597
amrex::Real custom_tstar
Definition: ERF_SurfaceLayer.H:574
bool cnk_visc
Definition: ERF_SurfaceLayer.H:579
amrex::Real surf_heating_rate
Definition: ERF_SurfaceLayer.H:568
RoughCalcType
Definition: ERF_SurfaceLayer.H:540
FluxCalcType flux_type
Definition: ERF_SurfaceLayer.H:550
MoistCalcType moist_type
Definition: ERF_SurfaceLayer.H:552
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:245
amrex::Vector< amrex::MultiFab * > m_eddyDiffs_lev
Definition: ERF_SurfaceLayer.H:603
const amrex::MultiFab * get_mac_avg(const int &lev, int comp)
Definition: ERF_SurfaceLayer.H:484
amrex::Real custom_ustar
Definition: ERF_SurfaceLayer.H:573
amrex::Vector< std::unique_ptr< amrex::MultiFab > > olen
Definition: ERF_SurfaceLayer.H:591
amrex::FArrayBox * get_z0(const int &lev)
Definition: ERF_SurfaceLayer.H:495
amrex::MultiFab * get_t_surf(const int &lev)
Definition: ERF_SurfaceLayer.H:489
amrex::Vector< std::unique_ptr< amrex::MultiFab > > pblh
Definition: ERF_SurfaceLayer.H:592
amrex::Real default_land_surf_temp
Definition: ERF_SurfaceLayer.H:566
amrex::Real get_zref()
Definition: ERF_SurfaceLayer.H:493
ThetaCalcType
Definition: ERF_SurfaceLayer.H:528
@ 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:585
MOSTAverage m_ma
Definition: ERF_SurfaceLayer.H:586
@ ng
Definition: ERF_Morrison.H:48
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
Definition: ERF_DataStruct.H:99