ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_MOSTAverage.H
Go to the documentation of this file.
1 #ifndef ERF_MOSTAverage_H
2 #define ERF_MOSTAverage_H
3 
4 #include "AMReX_Gpu.H"
5 #include "AMReX_FArrayBox.H"
6 #include "AMReX_MultiFab.H"
7 #include "AMReX_iMultiFab.H"
8 #include "AMReX_ParmParse.H"
9 
10 #include "ERF_IndexDefines.H"
11 #include "ERF_TerrainMetrics.H"
12 #include "ERF_DataStruct.H"
13 #include "ERF_EB.H"
14 #include "ERF_PlanarBoundary.H"
15 
16 class MOSTAverage {
17 public:
18  /**
19  * Construct the MOST averaging helper.
20  *
21  * @param[in] face orientation of face for MOST averaging
22  * @param[in] geom geometry for all AMR levels
23  * @param[in] has_zphys whether nodal physical-height data are available
24  * @param[in] a_pp_prefix ParmParse prefix
25  * @param[in] m_mesh_type mesh type
26  * @param[in] m_terrain_type terrain representation
27  * @param[in] zlevels_stag nominal staggered z levels for all AMR levels
28  * @param[in] eb_vec optional embedded-boundary geometry data
29  */
30  explicit MOSTAverage (amrex::Orientation face,
31  amrex::Vector<amrex::Geometry> geom,
32  const bool& has_zphys,
33  std::string a_pp_prefix,
34  const MeshType& m_mesh_type,
35  const TerrainType& m_terrain_type,
36  const amrex::Vector<amrex::Vector<amrex::Real>>& zlevels_stag,
37  const amrex::Vector<const eb_*>& eb_vec = {});
38 
39  // MOSTAverage() = default;
40 
41  /**
42  * Destroy the MOST averaging helper.
43  */
45  {}
46 
47  /**
48  * Default move constructor.
49  */
50  MOSTAverage (MOSTAverage&&) noexcept = default;
51 
52  /**
53  * Deleted move-assignment operator.
54  *
55  * @param[in] other source object
56  */
57  MOSTAverage& operator= (MOSTAverage&& other) noexcept = delete;
58 
59  /**
60  * Deleted copy constructor.
61  *
62  * @param[in] other source object
63  */
64  MOSTAverage (const MOSTAverage& other) = delete;
65 
66  /**
67  * Deleted copy-assignment operator.
68  *
69  * @param[in] other source object
70  */
71  MOSTAverage& operator= (const MOSTAverage& other) = delete;
72 
73  /**
74  * Make MOST-average data structures at one level.
75  *
76  * @param[in] lev level index
77  * @param[in] vars_old old-time state and velocity fields
78  * @param[in] Theta_prim primitive potential-temperature field
79  * @param[in] Qv_prim primitive water-vapor field
80  * @param[in] Qr_prim primitive rain-water field
81  * @param[in] z_phys_nd nodal physical-height field
82  */
83  void make_MOSTAverage_at_level (const int& lev,
84  const amrex::Vector<amrex::MultiFab*>& vars_old,
85  std::unique_ptr<amrex::MultiFab>& Theta_prim,
86  std::unique_ptr<amrex::MultiFab>& Qv_prim,
87  std::unique_ptr<amrex::MultiFab>& Qr_prim,
88  std::unique_ptr<amrex::MultiFab>& z_phys_nd);
89 
90  /**
91  * Reset pointers to field MultiFabs.
92  *
93  * @param[in] lev level index
94  * @param[in] vars_old old-time state and velocity fields
95  * @param[in] Theta_prim primitive potential-temperature fields by level
96  * @param[in] Qv_prim primitive water-vapor fields by level
97  * @param[in] Qr_prim primitive rain-water fields by level
98  */
99  void update_field_ptrs (const int& lev,
100  amrex::Vector<amrex::Vector<amrex::MultiFab>>& vars_old,
101  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Theta_prim,
102  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Qv_prim,
103  amrex::Vector<std::unique_ptr<amrex::MultiFab>>& Qr_prim);
104 
105  /**
106  * Update the rotated fields.
107  *
108  * @param[in] lev level index
109  */
110  void set_rotated_fields (const int& lev);
111 
112  /**
113  * Compute number of cells per averaging plane.
114  *
115  * @param[in] lev level index
116  */
117  void set_plane_normalization (const int& lev);
118 
119  /**
120  * Compute total embedded-boundary surface area.
121  *
122  * @param[in] lev level index
123  */
124  void set_eb_normalization (const int& lev);
125 
126  /**
127  * Compute number of cells in the region average.
128  *
129  * @param[in] lev level index
130  */
131  void set_region_normalization (const int& /*lev*/)
132  {m_ncell_region = (2 * m_radius + 1) * (2 * m_radius + 1) * (2 * m_radius + 1);}
133 
134  /**
135  * Populate the 2D k-index iMultiFab without terrain.
136  *
137  * @param[in] lev level index
138  */
139  void set_k_indices_N (const int& lev);
140 
141  /**
142  * Verify that the lateral face-owned FAB contains the reference stencil.
143  *
144  * @param[in] lev level index
145  *
146  * This is a conservative preflight check for the direct regional-average
147  * path. It verifies that the reference point plus averaging radius, with
148  * allowance for staggered-field neighbors, is available in the owned FAB.
149  */
150  void validate_lateral_reference_stencil (const int& lev);
151 
152  /**
153  * Populate the 2D k-index iMultiFab with terrain.
154  *
155  * @param[in] lev level index
156  */
157  void set_k_indices_T (const int& lev);
158 
159  /**
160  * Populate all 2D normal-index iMultiFabs with terrain.
161  *
162  * @param[in] lev level index
163  */
164  void set_norm_indices_T (const int& lev);
165 
166  /**
167  * Populate terrain-aware z positions.
168  *
169  * @param[in] lev level index
170  */
171  void set_z_positions_T (const int& lev);
172 
173  /**
174  * Populate embedded-boundary z positions.
175  *
176  * @param[in] lev level index
177  */
178  void set_z_positions_EB (const int& lev);
179 
180  /**
181  * Populate terrain-aware normal positions.
182  *
183  * @param[in] lev level index
184  */
185  void set_norm_positions_T (const int& lev);
186 
187  /**
188  * Driver for the selected average policy.
189  *
190  * @param[in] lev level index
191  */
192  void compute_averages (const int& lev);
193 
194  /**
195  * Fill averages for the plane policy.
196  *
197  * @param[in] lev level index
198  */
199  void compute_plane_averages (const int& lev);
200 
201  /**
202  * Fill averages for the point or region policy.
203  *
204  * @param[in] lev level index
205  */
206  void compute_region_averages (const int& lev);
207 
208  /**
209  * Fill averages for the embedded-boundary policy.
210  *
211  * @param[in] lev level index
212  */
213  void compute_eb_averages (const int& lev);
214 
215  /**
216  * Write k-index data.
217  *
218  * @param[in] lev level index
219  */
220  void write_k_indices (const int& lev);
221 
222  /**
223  * Write normal-index data.
224  *
225  * @param[in] lev level index
226  */
227  void write_norm_indices (const int& lev);
228 
229  /**
230  * Write XZ planar positions.
231  *
232  * @param[in] lev level index
233  * @param[in] j y-index of the plane to write
234  */
235  void write_xz_positions (const int& lev,
236  const int& j);
237 
238  /**
239  * Write averages on the 2D MultiFab.
240  *
241  * @param[in] lev level index
242  */
243  void write_averages (const int& lev);
244 
245  /**
246  * Return one 2D average MultiFab.
247  *
248  * @param[in] lev level index
249  * @param[in] comp average component index
250  */
251  [[nodiscard]] const amrex::MultiFab* get_average (const int& lev, const int& comp) const { return m_averages[lev][comp].get(); }
252 
253  /**
254  * Return one 2D average MultiFab for modification (used to restore the
255  * exponential filter state from a checkpoint).
256  *
257  * @param[in] lev level index
258  * @param[in] comp average component index
259  */
260  [[nodiscard]] amrex::MultiFab* get_average (const int& lev, const int& comp) { return m_averages[lev][comp].get(); }
261 
262  /**
263  * Return whether the averages are filtered in time (erf.most.time_average).
264  */
265  [[nodiscard]] bool do_time_averaging () const { return m_t_avg; }
266 
267  /**
268  * Return the number of average components.
269  */
270  [[nodiscard]] int get_navg () const { return m_navg; }
271 
272  /**
273  * Return whether the time filter at this level holds meaningful history.
274  * Until it does, the next average is taken to be the instantaneous one.
275  *
276  * @param[in] lev level index
277  */
278  [[nodiscard]] bool time_avg_is_initialized (const int& lev) const
279  {
280  return ( m_t_avg && (lev < static_cast<int>(m_t_init.size())) && (m_t_init[lev] == 1) );
281  }
282 
283  /**
284  * Declare the time filter at this level to hold meaningful history. This is
285  * used on restart, once the filter state has been read back in.
286  *
287  * @param[in] lev level index
288  */
289  void set_time_avg_initialized (const int& lev)
290  {
291  if (m_t_avg) { m_t_init[lev] = 1; }
292  }
293 
294  /**
295  * Return the filtered plane averages, which hold the filter state for the
296  * plane and EB policies. The region policy holds its state in m_averages
297  * instead and never allocates these, in which case this is empty.
298  *
299  * @param[in] lev level index
300  */
301  [[nodiscard]] amrex::Vector<amrex::Real> get_plane_average (const int& lev) const
302  {
303  if (lev < static_cast<int>(m_plane_average.size())) { return m_plane_average[lev]; }
304  return amrex::Vector<amrex::Real>{};
305  }
306 
307  /**
308  * Restore the filtered plane averages from a checkpoint. Returns false if the
309  * checkpoint does not hold what this run expects, e.g. because the averaging
310  * policy changed, in which case nothing is restored.
311  *
312  * @param[in] lev level index
313  * @param[in] pavg filtered plane averages, one per average component
314  */
315  bool set_plane_average (const int& lev, const amrex::Vector<amrex::Real>& pavg)
316  {
317  const int n_have = (lev < static_cast<int>(m_plane_average.size())) ?
318  static_cast<int>(m_plane_average[lev].size()) : 0;
319  if (n_have != static_cast<int>(pavg.size())) { return false; }
320  if (n_have > 0) { m_plane_average[lev] = pavg; }
321  return true;
322  }
323 
324  /**
325  * Return z_ref, which may be computed from a specified k-index.
326  *
327  * @param[in] lev level index
328  */
329  [[nodiscard]] amrex::MultiFab* get_zref (const int& lev) const { return m_zref[lev].get(); }
330 
331  /**
332  * Return the k-index iMultiFab.
333  *
334  * @param[in] lev level index
335  */
336  [[nodiscard]] const amrex::iMultiFab* get_k_indices (const int& lev) const { return m_k_indx[lev].get(); }
337 
338  /**
339  * Whether a height lies in the vertical extent [z_lo, z_hi) of a cell.
340  *
341  * The interval is closed below so that a query height landing exactly on a
342  * face (e.g. the default 10 m on a flat mesh with a 10 m first cell) belongs
343  * to the cell above it rather than to neither cell.
344  *
345  * @param[in] z query height
346  * @param[in] z_lo height of the lower face
347  * @param[in] z_hi height of the upper face
348  */
349  AMREX_GPU_HOST_DEVICE AMREX_INLINE
350  static bool in_cell_z (const amrex::Real& z,
351  const amrex::Real& z_lo,
352  const amrex::Real& z_hi)
353  {
354  return ( (z >= z_lo) && (z < z_hi) );
355  }
356 
357  /**
358  * Index of the highest cell whose center lies at or below a height above the
359  * bottom of the domain, on a column of staggered (face) heights. This is the
360  * stretched-mesh counterpart of floor(zref/dz - 1/2) on a uniform mesh.
361  *
362  * @param[in] zlevels staggered heights of the column (nz+1 faces)
363  * @param[in] zref height above zlevels[0]
364  * @return the cell index, or -1 if zref lies below the first cell center
365  */
366  static int k_index_below (const amrex::Vector<amrex::Real>& zlevels,
367  const amrex::Real& zref)
368  {
369  const int nz = static_cast<int>(zlevels.size()) - 1;
370  int lk = -1;
371  for (int k(0); k < nz; ++k) {
372  if (cell_center_height(zlevels, k) <= zref) { lk = k; } else { break; }
373  }
374  return lk;
375  }
376 
377  /**
378  * Height of a cell center above the bottom of the domain, on a column of
379  * staggered (face) heights.
380  *
381  * @param[in] zlevels staggered heights of the column (nz+1 faces)
382  * @param[in] k cell index
383  */
384  static amrex::Real cell_center_height (const amrex::Vector<amrex::Real>& zlevels,
385  const int& k)
386  {
387  return myhalf * (zlevels[k] + zlevels[k+1]) - zlevels[0];
388  }
389 
390  /**
391  * Height of the top of the column above its bottom, on a column of staggered
392  * (face) heights; the high z face's distances are measured from it.
393  *
394  * @param[in] zlevels staggered heights of the column (nz+1 faces)
395  */
396  static amrex::Real column_height (const amrex::Vector<amrex::Real>& zlevels)
397  {
398  return zlevels.back() - zlevels[0];
399  }
400 
401  /**
402  * Function to compute trilinear interpolation with terrain.
403  *
404  * @param[in] xp X-position
405  * @param[in] yp Y-position
406  * @param[in] zp Z-position
407  * @param[out] interp_vals Values interpolated
408  * @param[in] interp_array Array to interpolate on
409  * @param[in] z_arr Physical heights
410  * @param[in] plo Problem lower bounds
411  * @param[in] dxi Inverse cell size array
412  * @param[in] interp_comp Number of components to interpolate
413  */
414  AMREX_GPU_HOST_DEVICE AMREX_INLINE
415  static void trilinear_interp_T (const amrex::Real& xp,
416  const amrex::Real& yp,
417  const amrex::Real& zp,
418  amrex::Real* interp_vals,
419  amrex::Array4<amrex::Real const> const& interp_array,
420  amrex::Array4<amrex::Real const> const& z_arr,
421  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& plo,
422  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dxi,
423  const int interp_comp)
424  {
425  // Search to get z/k
426  bool found = false;
427  int kmax = ubound(z_arr).z;
428  amrex::Real zval = zero;
429  amrex::Real z_target = zp;
430 
431  // Map position to i,j (must be same mapping in cpp file)
432  amrex::Real ireal = (xp - plo[0]) * dxi[0];
433  amrex::Real jreal = (yp - plo[1]) * dxi[1];
434  int i_new = (int) (ireal - myhalf);
435  int j_new = (int) (jreal - myhalf);
436 
437  for (int lk(0); lk<kmax; ++lk) {
438  amrex::Real z_lo = fourth * ( z_arr(i_new,j_new ,lk ) + z_arr(i_new+1,j_new ,lk )
439  + z_arr(i_new,j_new+1,lk ) + z_arr(i_new+1,j_new+1,lk ) );
440  amrex::Real z_hi = fourth * ( z_arr(i_new,j_new ,lk+1) + z_arr(i_new+1,j_new ,lk+1)
441  + z_arr(i_new,j_new+1,lk+1) + z_arr(i_new+1,j_new+1,lk+1) );
442  if (in_cell_z(z_target, z_lo, z_hi)) {
443  found = true;
444  // Weight between the two cell centers that bracket z_target by
445  // their physical heights, so the interpolation is linear in z
446  // on a stretched or terrain-following column. A weight taken
447  // from the fraction of the containing cell alone (as before)
448  // is exact only for equal cell heights: at the 10 m face of a
449  // 10 m / 11 m pair it returned the wind at 10.25 m. A center
450  // beyond the nodes searched here is mirrored about the shared
451  // face, which gives the equal-height weight at those ends.
452  amrex::Real zc = myhalf * (z_lo + z_hi);
453  if (z_target >= zc) {
454  amrex::Real zc_up = two * z_hi - zc;
455  if (lk + 2 <= kmax) {
456  amrex::Real z_up = fourth * ( z_arr(i_new,j_new ,lk+2) + z_arr(i_new+1,j_new ,lk+2)
457  + z_arr(i_new,j_new+1,lk+2) + z_arr(i_new+1,j_new+1,lk+2) );
458  zc_up = myhalf * (z_hi + z_up);
459  }
460  zval = (amrex::Real) (lk + 1) + (z_target - zc) / (zc_up - zc);
461  } else {
462  amrex::Real zc_dn = two * z_lo - zc;
463  if (lk >= 1) {
464  amrex::Real z_dn = fourth * ( z_arr(i_new,j_new ,lk-1) + z_arr(i_new+1,j_new ,lk-1)
465  + z_arr(i_new,j_new+1,lk-1) + z_arr(i_new+1,j_new+1,lk-1) );
466  zc_dn = myhalf * (z_dn + z_lo);
467  }
468  zval = (amrex::Real) lk + (z_target - zc_dn) / (zc - zc_dn);
469  }
470  break;
471  }
472  }
473 
474  amrex::ignore_unused(found);
475  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(found, "MOSTAverage: Height above terrain not found, try increasing z_ref!");
476 
477  // NOTE: This is the point ahead of the current i,j (e.g. i/j_new + 1);
478  // in z, floor(zval) is the upper of the two bracketing cells
479  const amrex::RealVect lx(ireal + myhalf, jreal + myhalf, zval);
480 
481  const amrex::IntVect ijk = lx.floor();
482 
483  int i = ijk[0]; int j = ijk[1]; int k = ijk[2];
484 
485  // Convert ijk (IntVect) to a RealVect explicitly
486  amrex::RealVect ijk_r(static_cast<amrex::Real>(ijk[0]),
487  static_cast<amrex::Real>(ijk[1]),
488  static_cast<amrex::Real>(ijk[2]));
489 
490  // Weights
491  const amrex::RealVect sx_hi = lx - ijk_r;
492  const amrex::RealVect sx_lo = one - sx_hi;
493 
494  for (int n = 0; n < interp_comp; n++) {
495  interp_vals[n] = sx_lo[0]*sx_lo[1]*sx_lo[2]*interp_array(i-1, j-1, k-1,n) +
496  sx_lo[0]*sx_lo[1]*sx_hi[2]*interp_array(i-1, j-1, k ,n) +
497  sx_lo[0]*sx_hi[1]*sx_lo[2]*interp_array(i-1, j , k-1,n) +
498  sx_lo[0]*sx_hi[1]*sx_hi[2]*interp_array(i-1, j , k ,n) +
499  sx_hi[0]*sx_lo[1]*sx_lo[2]*interp_array(i , j-1, k-1,n) +
500  sx_hi[0]*sx_lo[1]*sx_hi[2]*interp_array(i , j-1, k ,n) +
501  sx_hi[0]*sx_hi[1]*sx_lo[2]*interp_array(i , j , k-1,n) +
502  sx_hi[0]*sx_hi[1]*sx_hi[2]*interp_array(i , j , k ,n);
503  }
504  }
505 
506  /**
507  * Return the number of ghost cells of the 2D data (averages, indices and
508  * positions) that can be filled from the field data at this level.
509  *
510  * With more than one level we must explicitly fill the ghost cells of the 2D
511  * data: an isolated fine patch has no neighboring box for a FillBoundary to
512  * communicate with, while the fields themselves do carry valid ghost data
513  * (filled from the coarse level). The 2D data are allocated with as many
514  * ghost cells as the fields they are built from, but an average reads the
515  * fields over m_radius cells in each direction and the tangential velocity
516  * magnitude (like the interpolation stencil) reaches one cell beyond that.
517  * So a ghost cell of the 2D data can only be computed where the fields carry
518  * m_radius+1 ghost cells past it.
519  *
520  * @param[in] lev level index
521  */
522  [[nodiscard]] amrex::IntVect get_ng_fill (const int& lev) const;
523 
524  /**
525  * Fill the ghost cells of one planar average, and the valid region of its
526  * uncomputed copies when the 3D BoxArray is split in z (see PlanarBoundary).
527  *
528  * @param[in] lev level index
529  * @param[in,out] mf planar average to fill
530  */
531  void fill_planar_boundary (const int& lev, amrex::MultiFab& mf);
532 
533  /**
534  * Fill the ghost cells of one average that cannot be computed from the field
535  * data with a zeroth-order extrapolation of the nearest computed value.
536  *
537  * The averages hold as many ghost cells as the fields, which is more than
538  * can be computed from them (see get_ng_fill), so the outermost layers are
539  * filled here to leave no average undefined. This is done before the
540  * FillBoundary, which then overwrites whatever is shared with a neighbor.
541  *
542  * @param[in] lev level index
543  * @param[in] iavg average component index
544  * @param[in] ng_fill number of ghost cells that hold computed data
545  */
546  void extrap_ghost_cells (const int& lev,
547  const int& iavg,
548  const amrex::IntVect& ng_fill);
549 
550 protected:
551 
552  // Passed through constructor
553  //--------------------------------------------
554  amrex::Orientation m_face; // Face to perform averages on
555  const amrex::Vector<amrex::Geometry> m_geom; // Geometry at each level
556  amrex::Vector<amrex::Vector<amrex::MultiFab*>> m_fields; // Ptr to fields to be averaged
557  amrex::Vector<amrex::MultiFab*> m_z_phys_nd; // Ptr to terrain height coords
558  std::string m_pp_prefix; // ParmParse prefix
559  MeshType m_mesh_type; // Mesh type
560  TerrainType m_terrain_type; // Terrain type
561  amrex::Vector<amrex::Vector<amrex::Real>> m_zlevels_stag; // Nominal staggered z levels (maxlev)
562 
563  // General vars for multiple or all policies
564  //--------------------------------------------
565  int m_nvar{6}; // 6 fields for U/V/W/T/Qv/Qr
566  int m_navg{9}; // 9 averages for U/V/W/T/Qv/Tv/Umag_XY,Umag_XZ,Umag_YZ
567  int m_maxlev{0}; // Total number of levels
568  int m_policy{0}; // Policy for type of averaging
569  bool m_rotate{false}; // Do vector rotations for terrain?
570  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_zref; // Height above surface for MOST BC
571  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_x_pos; // Ptr to 2D mf to hold x position (maxlev)
572  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_y_pos; // Ptr to 2D mf to hold y position (maxlev)
573  amrex::Vector<std::unique_ptr<amrex::MultiFab>> m_z_pos; // Ptr to 2D mf to hold z position (maxlev)
574  amrex::Vector<std::unique_ptr<amrex::iMultiFab>> m_i_indx; // Ptr to 2D imf to hold i indices (maxlev)
575  amrex::Vector<std::unique_ptr<amrex::iMultiFab>> m_j_indx; // Ptr to 2D imf to hold j indices (maxlev)
576  amrex::Vector<std::unique_ptr<amrex::iMultiFab>> m_k_indx; // Ptr to 2D imf to hold k indices (maxlev)
577  amrex::Vector<amrex::Vector<std::unique_ptr<amrex::MultiFab>>> m_averages; // Ptr to 2D mf to hold averages (maxlev,navg)
578  amrex::Vector<PlanarBoundary> m_planar_bndry; // Fills the planar averages on a split BoxArray (maxlev)
579  amrex::Vector<amrex::Vector<std::unique_ptr<amrex::MultiFab>>> m_rot_fields; // Rotated field data
580 
581  // Vars for planar average policy
582  //--------------------------------------------
583  amrex::Vector<amrex::Vector<int>> m_ncell_plane; // Number of cells in plane (maxlev,navg)
584  amrex::Vector<amrex::Vector<amrex::Real>> m_plane_average; // Plane avgs (maxlev,navg)
585 
586  // Vars for point/region average policy
587  //--------------------------------------------
588  int m_radius{0}; // Radius around k_index
589  int m_ncell_region{1}; // Number of cells in local region
590  amrex::Vector<int> m_k_in; // Specified k_index for region avg (maxlev)
591 
592  // Vars for normal vector policy
593  //--------------------------------------------
594  bool m_interp{false}; // Do interpolation on destination?
595  bool m_norm_vec{false}; // Use normal vector to find IJK?
596 
597  // Vars for EB averaging policy
598  //--------------------------------------------
599  amrex::Vector<const eb_*> m_eb_vec; // Vector of pointers to EB objects (one per level)
600  amrex::Vector<amrex::Vector<amrex::Real>> m_total_bndry_area; // Total EB surface areas (maxlev, navg)
601 
602  // Time average w/ exponential filter fun
603  //--------------------------------------------
604  bool m_t_avg{false}; // Flag to do moving average in time
605  amrex::Vector<int> m_t_init; // Flag to specify if averages are initialized
606  double m_time_window{1.0e-16}; // Width of the exp filter function
607  amrex::Real m_fact_new, m_fact_old; // Time average factors for new and old means
608 
609  // Surface velocity correction
610  //--------------------------------------------
611  bool include_subgrid_vel = false;
612  amrex::Vector<amrex::Real> m_Vsg; // Subgrid velocity scale (Mahrt & Sun 1995 MWR)
613 
614  // Default values
615  //--------------------------------------------
617 
618  // Sentinel used to detect whether most.zref was set by the user. zref_default
619  // is itself a legal user value, so "was it specified" cannot be read off the
620  // value unless we probe with something unreachable first. For lateral and
621  // z-high faces, most.zref is a wall-relative distance; z-low retains its
622  // legacy absolute-coordinate convention. See the parse sites in
623  // ERF_MOSTAverage.cpp: they use ParmParse::queryAdd, whose return value is
624  // only meaningful on the first parse of a key, and these routines run once
625  // per level.
627 };
628 #endif
Declares the embedded-boundary factory manager used by ERF levels.
const Real lx
Definition: ERF_InitCustomPertVels_CloudChamber.H:10
const Real zc
Definition: ERF_InitCustomPert_ABL.H:56
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(axis >=0 &&axis< AMREX_SPACEDIM, "prob.axis must be 0, 1 or 2")
constexpr amrex::Real two
Definition: ERF_NumericalConstants.H:38
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
constexpr amrex::Real fourth
Definition: ERF_NumericalConstants.H:42
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_MOSTAverage.H:16
int m_navg
Definition: ERF_MOSTAverage.H:566
bool m_t_avg
Definition: ERF_MOSTAverage.H:604
void write_xz_positions(const int &lev, const int &j)
Definition: ERF_MOSTAverage.cpp:3179
void compute_plane_averages(const int &lev)
Definition: ERF_MOSTAverage.cpp:1488
int m_policy
Definition: ERF_MOSTAverage.H:568
static amrex::Real column_height(const amrex::Vector< amrex::Real > &zlevels)
Definition: ERF_MOSTAverage.H:396
amrex::Vector< amrex::Vector< std::unique_ptr< amrex::MultiFab > > > m_averages
Definition: ERF_MOSTAverage.H:577
bool set_plane_average(const int &lev, const amrex::Vector< amrex::Real > &pavg)
Definition: ERF_MOSTAverage.H:315
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_y_pos
Definition: ERF_MOSTAverage.H:572
MOSTAverage(amrex::Orientation face, amrex::Vector< amrex::Geometry > geom, const bool &has_zphys, std::string a_pp_prefix, const MeshType &m_mesh_type, const TerrainType &m_terrain_type, const amrex::Vector< amrex::Vector< amrex::Real >> &zlevels_stag, const amrex::Vector< const eb_ * > &eb_vec={})
static int k_index_below(const amrex::Vector< amrex::Real > &zlevels, const amrex::Real &zref)
Definition: ERF_MOSTAverage.H:366
const amrex::Real zref_sentinel
Definition: ERF_MOSTAverage.H:626
double m_time_window
Definition: ERF_MOSTAverage.H:606
amrex::MultiFab * get_average(const int &lev, const int &comp)
Definition: ERF_MOSTAverage.H:260
int m_radius
Definition: ERF_MOSTAverage.H:588
void set_z_positions_EB(const int &lev)
Definition: ERF_MOSTAverage.cpp:979
void write_averages(const int &lev)
Definition: ERF_MOSTAverage.cpp:3221
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > m_i_indx
Definition: ERF_MOSTAverage.H:574
void compute_region_averages(const int &lev)
Definition: ERF_MOSTAverage.cpp:2087
amrex::Vector< amrex::MultiFab * > m_z_phys_nd
Definition: ERF_MOSTAverage.H:557
amrex::Vector< int > m_t_init
Definition: ERF_MOSTAverage.H:605
void compute_averages(const int &lev)
Definition: ERF_MOSTAverage.cpp:1459
void validate_lateral_reference_stencil(const int &lev)
Definition: ERF_MOSTAverage.cpp:940
void set_rotated_fields(const int &lev)
Definition: ERF_MOSTAverage.cpp:513
amrex::Vector< amrex::Vector< amrex::Real > > m_total_bndry_area
Definition: ERF_MOSTAverage.H:600
void set_region_normalization(const int &)
Definition: ERF_MOSTAverage.H:131
void set_z_positions_T(const int &lev)
Definition: ERF_MOSTAverage.cpp:1275
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_x_pos
Definition: ERF_MOSTAverage.H:571
amrex::Orientation m_face
Definition: ERF_MOSTAverage.H:554
amrex::Vector< amrex::Real > get_plane_average(const int &lev) const
Definition: ERF_MOSTAverage.H:301
void set_norm_positions_T(const int &lev)
Definition: ERF_MOSTAverage.cpp:1354
amrex::Vector< amrex::Real > m_Vsg
Definition: ERF_MOSTAverage.H:612
bool do_time_averaging() const
Definition: ERF_MOSTAverage.H:265
void set_k_indices_T(const int &lev)
Definition: ERF_MOSTAverage.cpp:1007
amrex::Vector< amrex::Vector< std::unique_ptr< amrex::MultiFab > > > m_rot_fields
Definition: ERF_MOSTAverage.H:579
bool m_rotate
Definition: ERF_MOSTAverage.H:569
amrex::MultiFab * get_zref(const int &lev) const
Definition: ERF_MOSTAverage.H:329
amrex::Vector< amrex::Vector< amrex::Real > > m_plane_average
Definition: ERF_MOSTAverage.H:584
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_z_pos
Definition: ERF_MOSTAverage.H:573
amrex::Vector< amrex::Vector< int > > m_ncell_plane
Definition: ERF_MOSTAverage.H:583
void set_plane_normalization(const int &lev)
Definition: ERF_MOSTAverage.cpp:581
void write_k_indices(const int &lev)
Definition: ERF_MOSTAverage.cpp:3023
TerrainType m_terrain_type
Definition: ERF_MOSTAverage.H:560
std::string m_pp_prefix
Definition: ERF_MOSTAverage.H:558
void set_time_avg_initialized(const int &lev)
Definition: ERF_MOSTAverage.H:289
bool m_norm_vec
Definition: ERF_MOSTAverage.H:595
int m_nvar
Definition: ERF_MOSTAverage.H:565
int get_navg() const
Definition: ERF_MOSTAverage.H:270
void fill_planar_boundary(const int &lev, amrex::MultiFab &mf)
Definition: ERF_MOSTAverage.cpp:2069
amrex::Real m_fact_new
Definition: ERF_MOSTAverage.H:607
const amrex::iMultiFab * get_k_indices(const int &lev) const
Definition: ERF_MOSTAverage.H:336
AMREX_GPU_HOST_DEVICE static AMREX_INLINE bool in_cell_z(const amrex::Real &z, const amrex::Real &z_lo, const amrex::Real &z_hi)
Definition: ERF_MOSTAverage.H:350
int m_ncell_region
Definition: ERF_MOSTAverage.H:589
void set_norm_indices_T(const int &lev)
Definition: ERF_MOSTAverage.cpp:1162
amrex::Vector< PlanarBoundary > m_planar_bndry
Definition: ERF_MOSTAverage.H:578
amrex::Vector< std::unique_ptr< amrex::MultiFab > > m_zref
Definition: ERF_MOSTAverage.H:570
int m_maxlev
Definition: ERF_MOSTAverage.H:567
const amrex::MultiFab * get_average(const int &lev, const int &comp) const
Definition: ERF_MOSTAverage.H:251
void extrap_ghost_cells(const int &lev, const int &iavg, const amrex::IntVect &ng_fill)
Definition: ERF_MOSTAverage.cpp:1996
void set_eb_normalization(const int &lev)
Definition: ERF_MOSTAverage.cpp:639
bool include_subgrid_vel
Definition: ERF_MOSTAverage.H:611
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:442
static amrex::Real cell_center_height(const amrex::Vector< amrex::Real > &zlevels, const int &k)
Definition: ERF_MOSTAverage.H:384
~MOSTAverage()
Definition: ERF_MOSTAverage.H:44
MeshType m_mesh_type
Definition: ERF_MOSTAverage.H:559
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > m_j_indx
Definition: ERF_MOSTAverage.H:575
amrex::Vector< amrex::Vector< amrex::Real > > m_zlevels_stag
Definition: ERF_MOSTAverage.H:561
void set_k_indices_N(const int &lev)
Definition: ERF_MOSTAverage.cpp:733
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:172
MOSTAverage(MOSTAverage &&) noexcept=default
void write_norm_indices(const int &lev)
Definition: ERF_MOSTAverage.cpp:3093
amrex::Vector< amrex::Vector< amrex::MultiFab * > > m_fields
Definition: ERF_MOSTAverage.H:556
amrex::Vector< int > m_k_in
Definition: ERF_MOSTAverage.H:590
amrex::Vector< const eb_ * > m_eb_vec
Definition: ERF_MOSTAverage.H:599
const amrex::Real zref_default
Definition: ERF_MOSTAverage.H:616
amrex::Real m_fact_old
Definition: ERF_MOSTAverage.H:607
bool time_avg_is_initialized(const int &lev) const
Definition: ERF_MOSTAverage.H:278
bool m_interp
Definition: ERF_MOSTAverage.H:594
const amrex::Vector< amrex::Geometry > m_geom
Definition: ERF_MOSTAverage.H:555
AMREX_GPU_HOST_DEVICE static AMREX_INLINE void trilinear_interp_T(const amrex::Real &xp, const amrex::Real &yp, const amrex::Real &zp, amrex::Real *interp_vals, amrex::Array4< amrex::Real const > const &interp_array, amrex::Array4< amrex::Real const > const &z_arr, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &plo, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxi, const int interp_comp)
Definition: ERF_MOSTAverage.H:415
void compute_eb_averages(const int &lev)
Definition: ERF_MOSTAverage.cpp:2720
amrex::IntVect get_ng_fill(const int &lev) const
Definition: ERF_MOSTAverage.cpp:473
amrex::Vector< std::unique_ptr< amrex::iMultiFab > > m_k_indx
Definition: ERF_MOSTAverage.H:576
Definition: ERF_ConsoleIO.cpp:17