ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_TerrainMetrics.H
Go to the documentation of this file.
1 #ifndef ERF_TERRAIN_METRIC_H_
2 #define ERF_TERRAIN_METRIC_H_
3 
4 #include <AMReX.H>
5 #include <AMReX_Geometry.H>
6 #include <AMReX_MultiFab.H>
7 #include <ERF_IndexDefines.H>
8 #include <cmath>
10 
11 /**
12  * Routine to define default z_phys_nd and z_phys_cc
13  */
14 void
15 init_default_zphys (int lev, const amrex::Geometry& geom,
16  amrex::MultiFab& z_phys_nd, amrex::MultiFab& z_phys_cc,
17  amrex::Real z_offset = zero);
18 
19 /**
20  * The cells of a (cell-centered) BoxArray as boxes that are never stacked on each other:
21  * wherever a box sits on the top face of another, the run of cells in z that the two belong
22  * to becomes a single box. Returns ba itself when no two boxes of ba are stacked.
23  *
24  * @param[in] ba cell-centered BoxArray
25  */
26 amrex::BoxArray
27 join_boxes_stacked_in_z (const amrex::BoxArray& ba);
28 
29 /**
30  * Utility routines for constructing terrain metric terms
31  */
32 
33 // Declare functions for ERF.cpp
34 /**
35  * Initialize staggered z-levels and stretched vertical spacing.
36  *
37  * @param[out] zlevels_stag Staggered z-levels.
38  * @param[out] stretched_dz_h Host stretched vertical spacing.
39  * @param[out] stretched_dz_d Device stretched vertical spacing.
40  * @param[in] geom Geometry information.
41  * @param[in] ref_ratio Refinement ratios.
42  * @param[in] grid_stretching_ratio Ratio for grid stretching; zero with a positive dz0
43  * solves for the ratio that closes on the domain top.
44  * @param[in] zsurf Surface height.
45  * @param[in] dz0 Initial vertical spacing.
46  */
47 void
48 init_zlevels (amrex::Vector<amrex::Vector<amrex::Real>>& zlevels_stag,
49  amrex::Vector<amrex::Vector<amrex::Real>>& stretched_dz_h,
50  amrex::Vector<amrex::Gpu::DeviceVector<amrex::Real>>& stretched_dz_d,
51  amrex::Vector<amrex::Geometry> const& geom,
52  amrex::Vector<amrex::IntVect> const& ref_ratio,
53  const amrex::Real grid_stretching_ratio,
54  const amrex::Real zsurf,
55  const amrex::Real dz0);
56 
57 /**
58  * How the terrain-fitted mesh on a fine level is built when erf.terrain_smoothing != 0.
59  *
60  * The STF and Sullivan TF transformations are not defined on a level that does not
61  * reach the top of the domain, so on a fine level we instead start from the mesh
62  * interpolated from the coarse level. A caller that has done that interpolation --
63  * and, for Transform, has also written the fine-resolution terrain into the k=0 slab
64  * and saved the pre-overwrite field -- says so by passing anything other than None.
65  * Every other caller keeps the historical behavior of aborting, because it has not
66  * prepared z_phys_nd in a way this path can use.
67  */
68 enum struct FineTerrain {
69  None, //!< caller has not prepared a fine mesh from the coarse level
70  Interpolate, //!< use the coordinates interpolated from the coarse level as-is
71  Transform //!< add the fine terrain as a correction that decays with height
72 };
73 
74 /**
75  * Read erf.amr_terrain_refinement and translate it into a FineTerrain.
76  *
77  * Aborts on any value other than "interpolate" or "transform" so that a typo cannot
78  * silently select a path that leaves the fine mesh untransformed.
79  */
82 
83 /**
84  * Construct terrain-fitted coordinates.
85  *
86  * @param[in] lev Level index.
87  * @param[in] geom Geometry information.
88  * @param[out] z_phys_nd Nodal physical height field.
89  * @param[in] z_levels_h Host z-levels.
90  * @param[in] phys_bc_type Physical boundary condition types.
91  * @param[in] fine_terrain How a fine level with terrain_smoothing != 0 is to be built.
92  * @param[in] z_phys_interp Mesh interpolated from the coarse level before the fine
93  * terrain was written into the k=0 slab; required by, and
94  * only used for, FineTerrain::Transform.
95  */
96 void
97 make_terrain_fitted_coords (int lev, const amrex::Geometry& geom,
98  amrex::MultiFab& z_phys_nd,
99  amrex::Vector<amrex::Real> const& z_levels_h,
100  amrex::GpuArray<ERF_BC, AMREX_SPACEDIM*2>& phys_bc_type,
101  FineTerrain fine_terrain = FineTerrain::None,
102  amrex::MultiFab const* z_phys_interp = nullptr);
103 
104 /** Verify that a fitted mesh is horizontally flat and follows z_levels_h. */
105 void
107  const amrex::MultiFab& z_phys_nd,
108  const amrex::Vector<amrex::Real>& z_levels_h);
109 
110 /**
111  * Initialize the terrain grid mapping.
112  *
113  * @param[in] lev Level index.
114  * @param[in] geom Geometry information.
115  * @param[out] z_phys_nd Nodal physical height field.
116  * @param[in] z_levels_h Host z-levels.
117  * @param[in] fine_terrain How a fine level with terrain_smoothing != 0 is to be built.
118  * @param[in] z_phys_interp Mesh interpolated from the coarse level; see above.
119  */
120 void
121 init_which_terrain_grid (int lev, const amrex::Geometry& geom,
122  amrex::MultiFab& z_phys_nd,
123  amrex::Vector<amrex::Real> const& z_levels_h,
124  FineTerrain fine_terrain = FineTerrain::None,
125  amrex::MultiFab const* z_phys_interp = nullptr);
126 
127 /**
128  * Finish the terrain-fitted mesh on a fine level whose interior was set by
129  * interpolation from the coarse level (erf.terrain_smoothing != 0).
130  *
131  * For FineTerrain::Transform this adds the fine-resolution terrain as a correction
132  * that decays linearly to zero at the top of the fine grids. For both modes it then
133  * fills the nodes outside the lateral domain boundary and the layer below the
134  * surface, which init_which_terrain_grid()'s BTF branch would otherwise have filled.
135  *
136  * @param[in] lev Level index.
137  * @param[in] geom Geometry information.
138  * @param[in,out] z_phys_nd Nodal physical height field.
139  * @param[in] z_levels_h Host z-levels.
140  * @param[in] fine_terrain Interpolate or Transform.
141  * @param[in] z_phys_interp Mesh interpolated from the coarse level; see above.
142  */
143 void
144 init_fine_terrain_grid (int lev, const amrex::Geometry& geom,
145  amrex::MultiFab& z_phys_nd,
146  amrex::Vector<amrex::Real> const& z_levels_h,
147  FineTerrain fine_terrain,
148  amrex::MultiFab const* z_phys_interp);
149 
150 // Compute the min dz at cell center with terrain
151 /**
152  * Compute the minimum vertical spacing with terrain.
153  *
154  * @param[in] z_phys_nd Nodal physical height field.
155  * @return Minimum vertical grid spacing.
156  */
158 get_dzmin_terrain (amrex::MultiFab& z_phys_nd);
159 
160 /**
161  * Re-derive the stretched vertical spacing at one level from the nominal z-levels.
162  *
163  * init_zlevels() fills both zlevels_stag and stretched_dz_* together, but
164  * zlevels_stag can be replaced after construction (init_from_wrfinput() does this
165  * when erf.avg_grid_faces_to_nodes = false, and restart reads it back from the
166  * checkpoint). Call this whenever zlevels_stag[lev] changes so that the cell
167  * heights never drift out of sync with the levels they are supposed to describe.
168  *
169  * @param[in] lev Level index.
170  * @param[in] zlevels_stag Staggered z-levels (the source of truth).
171  * @param[out] stretched_dz_h Host stretched vertical spacing.
172  * @param[out] stretched_dz_d Device stretched vertical spacing.
173  */
174 void
176  amrex::Vector<amrex::Vector<amrex::Real>> const& zlevels_stag,
177  amrex::Vector<amrex::Vector<amrex::Real>>& stretched_dz_h,
178  amrex::Vector<amrex::Gpu::DeviceVector<amrex::Real>>& stretched_dz_d);
179 
180 //*****************************************************************************************
181 // Compute terrain metric terms at cell-center
182 //*****************************************************************************************
183 // Metric is at cell center
184 /**
185  * Compute the zeta metric term at the cell center.
186  *
187  * @param[in] i x-index
188  * @param[in] j y-index
189  * @param[in] k z-index
190  * @param[in] cellSizeInv Inverse cell spacing.
191  * @param[in] z_nd Nodal physical height field.
192  * @return Zeta metric term.
193  */
194 AMREX_GPU_HOST_DEVICE
195 AMREX_FORCE_INLINE
197 Compute_h_zeta_AtCellCenter (const int &i, const int &j, const int &k,
198  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
199  const amrex::Array4<const amrex::Real>& z_nd)
200 {
201  amrex::Real dzInv = cellSizeInv[2];
202  amrex::Real met_h_zeta = fourth * dzInv *
203  ( z_nd(i+1,j,k+1) + z_nd(i+1,j+1,k+1) + z_nd(i,j,k+1) + z_nd(i,j+1,k+1)
204  - z_nd(i+1,j,k ) - z_nd(i+1,j+1,k ) - z_nd(i,j,k ) - z_nd(i,j+1,k ) );
205  return met_h_zeta;
206 }
207 
208 // Metric is at cell center
209 /**
210  * Compute the xi metric term at the cell center.
211  *
212  * @param[in] i x-index
213  * @param[in] j y-index
214  * @param[in] k z-index
215  * @param[in] cellSizeInv Inverse cell spacing.
216  * @param[in] z_nd Nodal physical height field.
217  * @return Xi metric term.
218  */
219 AMREX_GPU_HOST_DEVICE
220 AMREX_FORCE_INLINE
222 Compute_h_xi_AtCellCenter (const int &i, const int &j, const int &k,
223  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
224  const amrex::Array4<const amrex::Real>& z_nd)
225 {
226  amrex::Real dxInv = cellSizeInv[0];
227  amrex::Real met_h_xi = fourth * dxInv *
228  ( z_nd(i+1,j,k) + z_nd(i+1,j+1,k) + z_nd(i+1,j,k+1) + z_nd(i+1,j+1,k+1)
229  - z_nd(i ,j,k) - z_nd(i ,j+1,k) - z_nd(i ,j,k+1) - z_nd(i ,j+1,k+1) );
230  return met_h_xi;
231 }
232 
233 // Metric is at cell center
234 /**
235  * Compute the eta metric term at the cell center.
236  *
237  * @param[in] i x-index
238  * @param[in] j y-index
239  * @param[in] k z-index
240  * @param[in] cellSizeInv Inverse cell spacing.
241  * @param[in] z_nd Nodal physical height field.
242  * @return Eta metric term.
243  */
244 AMREX_GPU_HOST_DEVICE
245 AMREX_FORCE_INLINE
247 Compute_h_eta_AtCellCenter (const int &i, const int &j, const int &k,
248  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
249  const amrex::Array4<const amrex::Real>& z_nd)
250 {
251  amrex::Real dyInv = cellSizeInv[1];
252  amrex::Real met_h_eta = fourth * dyInv *
253  ( z_nd(i,j+1,k) + z_nd(i+1,j+1,k) + z_nd(i,j+1,k+1) + z_nd(i+1,j+1,k+1)
254  - z_nd(i,j ,k) - z_nd(i+1,j ,k) - z_nd(i,j ,k+1) - z_nd(i+1,j ,k+1) );
255  return met_h_eta;
256 }
257 
258 
259 //*****************************************************************************************
260 // Compute terrain metric terms at face-centers
261 //*****************************************************************************************
262 // Metric coincides with U location
263 /**
264  * Compute the zeta metric term at the i-face.
265  *
266  * @param[in] i x-index
267  * @param[in] j y-index
268  * @param[in] k z-index
269  * @param[in] cellSizeInv Inverse cell spacing.
270  * @param[in] z_nd Nodal physical height field.
271  * @return Zeta metric term.
272  */
273 AMREX_GPU_DEVICE
274 AMREX_FORCE_INLINE
276 Compute_h_zeta_AtIface (const int &i, const int &j, const int &k,
277  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
278  const amrex::Array4<const amrex::Real>& z_nd)
279 {
280  amrex::Real met_h_zeta = myhalf * cellSizeInv[2] * ( (z_nd(i,j ,k+1) - z_nd(i,j ,k))
281  + (z_nd(i,j+1,k+1) - z_nd(i,j+1,k)) );
282  return met_h_zeta;
283 }
284 
285 // Metric coincides with U location
286 /**
287  * Compute the xi metric term at the i-face.
288  *
289  * @param[in] i x-index
290  * @param[in] j y-index
291  * @param[in] k z-index
292  * @param[in] cellSizeInv Inverse cell spacing.
293  * @param[in] z_nd Nodal physical height field.
294  * @return Xi metric term.
295  */
296 AMREX_GPU_HOST_DEVICE
297 AMREX_FORCE_INLINE
299 Compute_h_xi_AtIface (const int &i, const int &j, const int &k,
300  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
301  const amrex::Array4<const amrex::Real>& z_nd)
302 {
303  amrex::Real met_h_xi = amrex::Real(0.125) * cellSizeInv[0] * (
304  (z_nd(i+1,j ,k ) - z_nd(i-1,j ,k )) + (z_nd(i+1,j ,k+1) - z_nd(i-1,j ,k+1)) +
305  (z_nd(i+1,j+1,k ) - z_nd(i-1,j+1,k )) + (z_nd(i+1,j+1,k+1) - z_nd(i-1,j+1,k+1)) );
306  return met_h_xi;
307 }
308 
309 // Metric coincides with U location
310 /**
311  * Compute the eta metric term at the i-face.
312  *
313  * @param[in] i x-index
314  * @param[in] j y-index
315  * @param[in] k z-index
316  * @param[in] cellSizeInv Inverse cell spacing.
317  * @param[in] z_nd Nodal physical height field.
318  * @return Eta metric term.
319  */
320 AMREX_GPU_DEVICE
321 AMREX_FORCE_INLINE
323 Compute_h_eta_AtIface (const int &i, const int &j, const int &k,
324  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
325  const amrex::Array4<const amrex::Real>& z_nd)
326 {
327  amrex::Real met_h_eta = myhalf * cellSizeInv[1] * ( (z_nd(i,j+1,k ) - z_nd(i,j,k ))
328  + (z_nd(i,j+1,k+1) - z_nd(i,j,k+1)) );
329  return met_h_eta;
330 }
331 
332 // Metric coincides with V location
333 /**
334  * Compute the zeta metric term at the j-face.
335  *
336  * @param[in] i x-index
337  * @param[in] j y-index
338  * @param[in] k z-index
339  * @param[in] cellSizeInv Inverse cell spacing.
340  * @param[in] z_nd Nodal physical height field.
341  * @return Zeta metric term.
342  */
343 AMREX_GPU_DEVICE
344 AMREX_FORCE_INLINE
346 Compute_h_zeta_AtJface (const int &i, const int &j, const int &k,
347  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
348  const amrex::Array4<const amrex::Real>& z_nd)
349 {
350  amrex::Real met_h_zeta = myhalf * cellSizeInv[2] * ( (z_nd(i ,j,k+1) - z_nd(i ,j,k ))
351  + (z_nd(i+1,j,k+1) - z_nd(i+1,j,k )) );
352  return met_h_zeta;
353 }
354 
355 // Metric coincides with V location
356 /**
357  * Compute the xi metric term at the j-face.
358  *
359  * @param[in] i x-index
360  * @param[in] j y-index
361  * @param[in] k z-index
362  * @param[in] cellSizeInv Inverse cell spacing.
363  * @param[in] z_nd Nodal physical height field.
364  * @return Xi metric term.
365  */
366 AMREX_GPU_DEVICE
367 AMREX_FORCE_INLINE
369 Compute_h_xi_AtJface (const int &i, const int &j, const int &k,
370  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
371  const amrex::Array4<const amrex::Real>& z_nd)
372 {
373  amrex::Real met_h_xi = myhalf * cellSizeInv[0] * ( (z_nd(i+1,j,k ) - z_nd(i,j,k ))
374  + (z_nd(i+1,j,k+1) - z_nd(i,j,k+1)) );
375  return met_h_xi;
376 }
377 
378 // Metric coincides with V location
379 /**
380  * Compute the eta metric term at the j-face.
381  *
382  * @param[in] i x-index
383  * @param[in] j y-index
384  * @param[in] k z-index
385  * @param[in] cellSizeInv Inverse cell spacing.
386  * @param[in] z_nd Nodal physical height field.
387  * @return Eta metric term.
388  */
389 AMREX_GPU_HOST_DEVICE
390 AMREX_FORCE_INLINE
392 Compute_h_eta_AtJface (const int &i, const int &j, const int &k,
393  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
394  const amrex::Array4<const amrex::Real>& z_nd)
395 {
396  amrex::Real met_h_eta = amrex::Real(0.125) * cellSizeInv[1] *
397  ( (z_nd(i ,j+1,k ) - z_nd(i ,j-1,k )) + (z_nd(i ,j+1,k+1) - z_nd(i ,j-1,k+1)) +
398  (z_nd(i+1,j+1,k ) - z_nd(i+1,j-1,k )) + (z_nd(i+1,j+1,k+1) - z_nd(i+1,j-1,k+1)) );
399  return met_h_eta;
400 }
401 
402 // Metric coincides with K location
403 /**
404  * Compute the zeta metric term at the k-face.
405  *
406  * @param[in] i x-index
407  * @param[in] j y-index
408  * @param[in] k z-index
409  * @param[in] cellSizeInv Inverse cell spacing.
410  * @param[in] z_nd Nodal physical height field.
411  * @return Zeta metric term.
412  */
413 AMREX_GPU_HOST_DEVICE
414 AMREX_FORCE_INLINE
416 Compute_h_zeta_AtKface (const int &i, const int &j, const int &k,
417  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
418  const amrex::Array4<const amrex::Real>& z_nd)
419 {
420  amrex::Real met_h_zeta = amrex::Real(0.125) * cellSizeInv[2] *
421  ( (z_nd(i ,j ,k+1) - z_nd(i ,j ,k-1)) + (z_nd(i+1,j ,k+1) - z_nd(i+1,j ,k-1)) +
422  (z_nd(i ,j+1,k+1) - z_nd(i ,j+1,k-1)) + (z_nd(i+1,j+1,k+1) - z_nd(i+1,j+1,k-1)) );
423  return met_h_zeta;
424 }
425 
426 // Metric coincides with K location
427 /**
428  * Compute the xi metric term at the k-face.
429  *
430  * @param[in] i x-index
431  * @param[in] j y-index
432  * @param[in] k z-index
433  * @param[in] cellSizeInv Inverse cell spacing.
434  * @param[in] z_nd Nodal physical height field.
435  * @return Xi metric term.
436  */
437 AMREX_GPU_HOST_DEVICE
438 AMREX_FORCE_INLINE
440 Compute_h_xi_AtKface (const int &i, const int &j, const int &k,
441  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
442  const amrex::Array4<const amrex::Real>& z_nd)
443 {
444  amrex::Real met_h_xi = myhalf * cellSizeInv[0] * ( (z_nd(i+1,j ,k) - z_nd(i,j ,k))
445  + (z_nd(i+1,j+1,k) - z_nd(i,j+1,k)) );
446  return met_h_xi;
447 }
448 
449 // Metric coincides with K location
450 /**
451  * Compute the eta metric term at the k-face.
452  *
453  * @param[in] i x-index
454  * @param[in] j y-index
455  * @param[in] k z-index
456  * @param[in] cellSizeInv Inverse cell spacing.
457  * @param[in] z_nd Nodal physical height field.
458  * @return Eta metric term.
459  */
460 AMREX_GPU_HOST_DEVICE
461 AMREX_FORCE_INLINE
463 Compute_h_eta_AtKface (const int &i, const int &j, const int &k,
464  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
465  const amrex::Array4<const amrex::Real>& z_nd)
466 {
467  amrex::Real met_h_eta = myhalf * cellSizeInv[1] * ( (z_nd(i ,j+1,k) - z_nd(i ,j,k))
468  + (z_nd(i+1,j+1,k) - z_nd(i+1,j,k)) );
469  return met_h_eta;
470 }
471 
472 
473 //*****************************************************************************************
474 // Compute terrain metric terms at edge-centers
475 //*****************************************************************************************
476 // -- EdgeCenterK --
477 
478 // Metric is at edge and center Z (red pentagon)
479 /**
480  * Compute the zeta metric term at the k-edge center.
481  *
482  * @param[in] i x-index
483  * @param[in] j y-index
484  * @param[in] k z-index
485  * @param[in] cellSizeInv Inverse cell spacing.
486  * @param[in] z_nd Nodal physical height field.
487  * @return Zeta metric term.
488  */
489 AMREX_GPU_DEVICE
490 AMREX_FORCE_INLINE
492 Compute_h_zeta_AtEdgeCenterK (const int &i, const int &j, const int &k,
493  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
494  const amrex::Array4<const amrex::Real>& z_nd)
495 {
496  amrex::Real dzInv = cellSizeInv[2];
497  amrex::Real met_h_zeta = dzInv * (z_nd(i,j,k+1) - z_nd(i,j,k));
498  return met_h_zeta;
499 }
500 
501 // Metric is at edge and center Z (red pentagon)
502 /**
503  * Compute the xi metric term at the k-edge center.
504  *
505  * @param[in] i x-index
506  * @param[in] j y-index
507  * @param[in] k z-index
508  * @param[in] cellSizeInv Inverse cell spacing.
509  * @param[in] z_nd Nodal physical height field.
510  * @return Xi metric term.
511  */
512 AMREX_GPU_DEVICE
513 AMREX_FORCE_INLINE
515 Compute_h_xi_AtEdgeCenterK (const int &i, const int &j, const int &k,
516  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
517  const amrex::Array4<const amrex::Real>& z_nd)
518 {
519  amrex::Real dxInv = cellSizeInv[0];
520  amrex::Real met_h_xi = fourth * dxInv *
521  ( z_nd(i+1,j,k) + z_nd(i+1,j,k+1)
522  - z_nd(i-1,j,k) - z_nd(i-1,j,k+1) );
523  return met_h_xi;
524 }
525 
526 // Metric is at edge and center Z (red pentagon)
527 /**
528  * Compute the eta metric term at the k-edge center.
529  *
530  * @param[in] i x-index
531  * @param[in] j y-index
532  * @param[in] k z-index
533  * @param[in] cellSizeInv Inverse cell spacing.
534  * @param[in] z_nd Nodal physical height field.
535  * @return Eta metric term.
536  */
537 AMREX_GPU_DEVICE
538 AMREX_FORCE_INLINE
540 Compute_h_eta_AtEdgeCenterK (const int &i, const int &j, const int &k,
541  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
542  const amrex::Array4<const amrex::Real>& z_nd)
543 {
544  amrex::Real dyInv = cellSizeInv[1];
545  amrex::Real met_h_eta = fourth * dyInv *
546  ( z_nd(i,j+1,k) + z_nd(i,j+1,k+1)
547  - z_nd(i,j-1,k) - z_nd(i,j-1,k+1) );
548  return met_h_eta;
549 }
550 
551 // -- EdgeCenterJ --
552 
553 // Metric is at edge and center Y (magenta cross)
554 /**
555  * Compute the zeta metric term at the j-edge center.
556  *
557  * @param[in] i x-index
558  * @param[in] j y-index
559  * @param[in] k z-index
560  * @param[in] cellSizeInv Inverse cell spacing.
561  * @param[in] z_nd Nodal physical height field.
562  * @return Zeta metric term.
563  */
564 AMREX_GPU_DEVICE
565 AMREX_FORCE_INLINE
567 Compute_h_zeta_AtEdgeCenterJ (const int &i, const int &j, const int &k,
568  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
569  const amrex::Array4<const amrex::Real>& z_nd)
570 {
571  amrex::Real dzInv = cellSizeInv[2];
572  amrex::Real met_h_zeta = fourth * dzInv * ( z_nd(i,j,k+1) + z_nd(i,j+1,k+1)
573  - z_nd(i,j,k-1) - z_nd(i,j+1,k-1) );
574  return met_h_zeta;
575 }
576 
577 // Metric is at edge and center Y (magenta cross)
578 /**
579  * Compute the xi metric term at the j-edge center.
580  *
581  * @param[in] i x-index
582  * @param[in] j y-index
583  * @param[in] k z-index
584  * @param[in] cellSizeInv Inverse cell spacing.
585  * @param[in] z_nd Nodal physical height field.
586  * @return Xi metric term.
587  */
588 AMREX_GPU_DEVICE
589 AMREX_FORCE_INLINE
591 Compute_h_xi_AtEdgeCenterJ (const int &i, const int &j, const int &k,
592  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
593  const amrex::Array4<const amrex::Real>& z_nd)
594 {
595  amrex::Real dxInv = cellSizeInv[0];
596  amrex::Real met_h_xi = fourth * dxInv *
597  ( z_nd(i+1,j+1,k) + z_nd(i+1,j ,k)
598  - z_nd(i-1,j+1,k) - z_nd(i-1,j ,k) );
599  return met_h_xi;
600 }
601 
602 // Metric is at edge and center Y (magenta cross)
603 /**
604  * Compute the eta metric term at the j-edge center.
605  *
606  * @param[in] i x-index
607  * @param[in] j y-index
608  * @param[in] k z-index
609  * @param[in] cellSizeInv Inverse cell spacing.
610  * @param[in] z_nd Nodal physical height field.
611  * @return Eta metric term.
612  */
613 AMREX_GPU_DEVICE
614 AMREX_FORCE_INLINE
616 Compute_h_eta_AtEdgeCenterJ (const int &i, const int &j, const int &k,
617  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
618  const amrex::Array4<const amrex::Real>& z_nd)
619 {
620  amrex::Real dyInv = cellSizeInv[1];
621  amrex::Real met_h_eta = dyInv * ( z_nd(i,j+1,k) - z_nd(i,j,k) );
622  return met_h_eta;
623 }
624 
625 // -- EdgeCenterI --
626 
627 // Metric is at edge and center X (purple hexagon)
628 /**
629  * Compute the zeta metric term at the i-edge center.
630  *
631  * @param[in] i x-index
632  * @param[in] j y-index
633  * @param[in] k z-index
634  * @param[in] cellSizeInv Inverse cell spacing.
635  * @param[in] z_nd Nodal physical height field.
636  * @return Zeta metric term.
637  */
638 AMREX_GPU_DEVICE
639 AMREX_FORCE_INLINE
641 Compute_h_zeta_AtEdgeCenterI (const int &i, const int &j, const int &k,
642  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
643  const amrex::Array4<const amrex::Real>& z_nd)
644 {
645  amrex::Real dzInv = cellSizeInv[2];
646  amrex::Real met_h_zeta = fourth * dzInv * ( z_nd(i,j,k+1) + z_nd(i+1,j,k+1)
647  - z_nd(i,j,k-1) - z_nd(i+1,j,k-1) );
648  return met_h_zeta;
649 }
650 
651 // Metric is at edge and center X (purple hexagon)
652 /**
653  * Compute the xi metric term at the i-edge center.
654  *
655  * @param[in] i x-index
656  * @param[in] j y-index
657  * @param[in] k z-index
658  * @param[in] cellSizeInv Inverse cell spacing.
659  * @param[in] z_nd Nodal physical height field.
660  * @return Xi metric term.
661  */
662 AMREX_GPU_DEVICE
663 AMREX_FORCE_INLINE
665 Compute_h_xi_AtEdgeCenterI (const int &i, const int &j, const int &k,
666  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
667  const amrex::Array4<const amrex::Real>& z_nd)
668 {
669  amrex::Real dxInv = cellSizeInv[0];
670  amrex::Real met_h_xi = dxInv * ( z_nd(i+1,j,k) - z_nd(i,j,k) );
671  return met_h_xi;
672 }
673 
674 // Metric is at edge and center X (purple hexagon)
675 /**
676  * Compute the eta metric term at the i-edge center.
677  *
678  * @param[in] i x-index
679  * @param[in] j y-index
680  * @param[in] k z-index
681  * @param[in] cellSizeInv Inverse cell spacing.
682  * @param[in] z_nd Nodal physical height field.
683  * @return Eta metric term.
684  */
685 AMREX_GPU_DEVICE
686 AMREX_FORCE_INLINE
688 Compute_h_eta_AtEdgeCenterI (const int &i, const int &j, const int &k,
689  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
690  const amrex::Array4<const amrex::Real>& z_nd)
691 {
692  amrex::Real dyInv = cellSizeInv[1];
693  amrex::Real met_h_eta = fourth * dyInv *
694  ( z_nd(i+1,j+1,k) + z_nd(i,j+1,k)
695  - z_nd(i+1,j-1,k) - z_nd(i,j-1,k) );
696  return met_h_eta;
697 }
698 
699 // Relative height above terrain surface at cell center from z_nd (nodal absolute height)
700 /**
701  * Compute the physical height at the cell center.
702  *
703  * @param[in] i x-index
704  * @param[in] j y-index
705  * @param[in] k z-index
706  * @param[in] z_nd Nodal physical height field.
707  * @return Physical height at cell center.
708  */
709 AMREX_GPU_DEVICE
710 AMREX_FORCE_INLINE
712 Compute_Z_AtCellCenter (const int &i, const int &j, const int &k,
713  const amrex::Array4<const amrex::Real>& z_nd)
714 {
715  const amrex::Real z_cc = amrex::Real(0.125)*( z_nd(i ,j ,k) + z_nd(i ,j ,k+1)
716  + z_nd(i+1,j ,k) + z_nd(i+1,j ,k+1)
717  + z_nd(i ,j+1,k) + z_nd(i ,j+1,k+1)
718  + z_nd(i+1,j+1,k) + z_nd(i+1,j+1,k+1));
719 
720  return z_cc;
721 }
722 
723 // Relative height above terrain surface at cell center from z_nd (nodal absolute height)
724 /**
725  * Compute the physical height at the W-face.
726  *
727  * @param[in] i x-index
728  * @param[in] j y-index
729  * @param[in] k z-index
730  * @param[in] z_nd Nodal physical height field.
731  * @return Physical height at W-face.
732  */
733 AMREX_GPU_HOST_DEVICE
734 AMREX_FORCE_INLINE
736 Compute_Z_AtWFace (const int &i, const int &j, const int &k,
737  const amrex::Array4<const amrex::Real>& z_nd)
738 {
739  const amrex::Real z_wf = fourth*( z_nd(i ,j ,k) + z_nd(i+1,j ,k)
740  + z_nd(i ,j+1,k) + z_nd(i+1,j+1,k) );
741 
742  return z_wf;
743 }
744 
745 // Relative height above terrain surface at cell center from z_nd (nodal absolute height)
746 /**
747  * Compute the relative height above the terrain surface at the cell center.
748  *
749  * @param[in] i x-index
750  * @param[in] j y-index
751  * @param[in] k z-index
752  * @param[in] z_nd Nodal physical height field.
753  * @return Relative height at cell center.
754  */
755 AMREX_GPU_HOST_DEVICE
756 AMREX_FORCE_INLINE
758 Compute_Zrel_AtCellCenter (const int &i, const int &j, const int &k,
759  const amrex::Array4<const amrex::Real>& z_nd)
760 {
761  const amrex::Real z_cc = amrex::Real(0.125)*( z_nd(i ,j ,k) + z_nd(i ,j ,k+1) +
762  + z_nd(i+1,j ,k) + z_nd(i+1,j ,k+1)
763  + z_nd(i ,j+1,k) + z_nd(i ,j+1,k+1)
764  + z_nd(i+1,j+1,k) + z_nd(i+1,j+1,k+1));
765 
766  // Note: we assume the z_nd array spans from the bottom to top of the domain
767  // i.e. no domain decomposition across processors in vertical direction
768  const amrex::Real z0_cc = fourth*( z_nd(i ,j ,0) + z_nd(i ,j+1,0)
769  + z_nd(i+1,j ,0) + z_nd(i+1,j+1,0));
770 
771  return (z_cc - z0_cc);
772 }
773 
774 
775 //*****************************************************************************************
776 // Contravariant velocity computation
777 //*****************************************************************************************
778 
779 // Define omega given u,v and w (4th order)
780 /**
781  * Compute the contravariant vertical velocity omega from w.
782  *
783  * @param[in] i x-index
784  * @param[in] j y-index
785  * @param[in] k z-index
786  * @param[in] w Vertical velocity.
787  * @param[in] u_arr X-velocity array.
788  * @param[in] v_arr Y-velocity array.
789  * @param[in] mf_u X-velocity map factor.
790  * @param[in] mf_v Y-velocity map factor.
791  * @param[in] z_nd Nodal physical height field.
792  * @param[in] dxInv Inverse cell spacing.
793  * @return Contravariant vertical velocity.
794  */
795 AMREX_GPU_DEVICE
796 AMREX_FORCE_INLINE
798 OmegaFromW (int& i, int& j, int& k, amrex::Real w,
799  const amrex::Array4<const amrex::Real>& u_arr,
800  const amrex::Array4<const amrex::Real>& v_arr,
801  const amrex::Array4<const amrex::Real>& mf_u,
802  const amrex::Array4<const amrex::Real>& mf_v,
803  const amrex::Array4<const amrex::Real>& z_nd,
804  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dxInv)
805 {
806  // This is dh/dxi at hi and lo edges
807  amrex::Real z_x_p2 = Compute_Z_AtWFace(i+2,j,k,z_nd);
808  amrex::Real z_x_p1 = Compute_Z_AtWFace(i+1,j,k,z_nd);
809  amrex::Real z_x_m1 = Compute_Z_AtWFace(i-1,j,k,z_nd);
810  amrex::Real z_x_m2 = Compute_Z_AtWFace(i-2,j,k,z_nd);
811  amrex::Real met_xi = (amrex::Real(1.0/amrex::Real(12.0))*(z_x_m2 - z_x_p2)
812  + amrex::Real(8.0/amrex::Real(12.0))*(z_x_p1 - z_x_m1)) * dxInv[0];
813 
814  // This is dh/deta at hi and lo edges
815  amrex::Real z_y_p2 = Compute_Z_AtWFace(i,j+2,k,z_nd);
816  amrex::Real z_y_p1 = Compute_Z_AtWFace(i,j+1,k,z_nd);
817  amrex::Real z_y_m1 = Compute_Z_AtWFace(i,j-1,k,z_nd);
818  amrex::Real z_y_m2 = Compute_Z_AtWFace(i,j-2,k,z_nd);
819  amrex::Real met_eta = (amrex::Real(1.0/amrex::Real(12.0))*(z_y_m2 - z_y_p2)
820  + amrex::Real(8.0/amrex::Real(12.0))*(z_y_p1 - z_y_m1)) * dxInv[1];
821 
822  // Use extrapolation instead of interpolation if at the bottom boundary
823  amrex::Real u_hi = (k == 0) ? amrex::Real(1.5) * u_arr(i+1,j ,k ) - myhalf * u_arr(i+1,j ,k+1) :
824  myhalf * ( u_arr(i+1,j ,k-1) + u_arr(i+1,j ,k ) );
825  amrex::Real u_lo = (k == 0) ? amrex::Real(1.5) * u_arr(i ,j ,k ) - myhalf * u_arr(i ,j ,k+1) :
826  myhalf * ( u_arr(i ,j ,k-1) + u_arr(i ,j ,k ) );
827  amrex::Real mf_u_hi = mf_u(i+1,j,0);
828  amrex::Real mf_u_lo = mf_u(i ,j,0);
829 
830  amrex::Real v_hi = (k == 0) ? amrex::Real(1.5) * v_arr(i ,j+1,k ) - myhalf * v_arr(i ,j+1,k+1) :
831  myhalf * ( v_arr(i ,j+1,k-1) + v_arr(i ,j+1,k ) );
832  amrex::Real v_lo = (k == 0) ? amrex::Real(1.5) * v_arr(i ,j ,k ) - myhalf * v_arr(i ,j ,k+1) :
833  myhalf * ( v_arr(i ,j ,k-1) + v_arr(i ,j ,k ) );
834  amrex::Real mf_v_hi = mf_v(i,j+1,0);
835  amrex::Real mf_v_lo = mf_v(i,j ,0);
836 
837  amrex::Real u_met = met_xi * myhalf * ( u_hi*mf_u_hi + u_lo*mf_u_lo );
838  amrex::Real v_met = met_eta * myhalf * ( v_hi*mf_v_hi + v_lo*mf_v_lo );
839 
840  amrex::Real omega = w - u_met - v_met;
841  return omega;
842 }
843 
844 // Define w given u and v arrays and scalar omega (4th order)
845 /**
846  * Compute the vertical velocity w from the contravariant omega.
847  *
848  * @param[in] i x-index
849  * @param[in] j y-index
850  * @param[in] k z-index
851  * @param[in] omega Contravariant vertical velocity.
852  * @param[in] u_arr X-velocity array.
853  * @param[in] v_arr Y-velocity array.
854  * @param[in] mf_u X-velocity map factor.
855  * @param[in] mf_v Y-velocity map factor.
856  * @param[in] z_nd Nodal physical height field.
857  * @param[in] dxInv Inverse cell spacing.
858  * @return Vertical velocity w.
859  */
860 AMREX_GPU_DEVICE
861 AMREX_FORCE_INLINE
863 WFromOmega (int& i, int& j, int& k, amrex::Real omega,
864  const amrex::Array4<const amrex::Real>& u_arr,
865  const amrex::Array4<const amrex::Real>& v_arr,
866  const amrex::Array4<const amrex::Real>& mf_u,
867  const amrex::Array4<const amrex::Real>& mf_v,
868  const amrex::Array4<const amrex::Real>& z_nd,
869  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dxInv)
870 {
871  // This is dh/dxi at hi and lo edges
872  amrex::Real z_x_p2 = Compute_Z_AtWFace(i+2,j,k,z_nd);
873  amrex::Real z_x_p1 = Compute_Z_AtWFace(i+1,j,k,z_nd);
874  amrex::Real z_x_m1 = Compute_Z_AtWFace(i-1,j,k,z_nd);
875  amrex::Real z_x_m2 = Compute_Z_AtWFace(i-2,j,k,z_nd);
876  amrex::Real met_xi = (amrex::Real(1.0/amrex::Real(12.0))*(z_x_m2 - z_x_p2)
877  + amrex::Real(8.0/amrex::Real(12.0))*(z_x_p1 - z_x_m1)) * dxInv[0];
878 
879  // This is dh/deta at hi and lo edges
880  amrex::Real z_y_p2 = Compute_Z_AtWFace(i,j+2,k,z_nd);
881  amrex::Real z_y_p1 = Compute_Z_AtWFace(i,j+1,k,z_nd);
882  amrex::Real z_y_m1 = Compute_Z_AtWFace(i,j-1,k,z_nd);
883  amrex::Real z_y_m2 = Compute_Z_AtWFace(i,j-2,k,z_nd);
884  amrex::Real met_eta = (amrex::Real(1.0/amrex::Real(12.0))*(z_y_m2 - z_y_p2)
885  + amrex::Real(8.0/amrex::Real(12.0))*(z_y_p1 - z_y_m1)) * dxInv[1];
886 
887  // Use extrapolation instead of interpolation if at the bottom boundary
888  amrex::Real u_hi = (k == 0) ? amrex::Real(1.5) * u_arr(i+1,j ,k ) - myhalf * u_arr(i+1,j ,k+1) :
889  myhalf * ( u_arr(i+1,j ,k-1) + u_arr(i+1,j ,k ) );
890  amrex::Real u_lo = (k == 0) ? amrex::Real(1.5) * u_arr(i ,j ,k ) - myhalf * u_arr(i ,j ,k+1) :
891  myhalf * ( u_arr(i ,j ,k-1) + u_arr(i ,j ,k ) );
892  amrex::Real mf_u_hi = mf_u(i+1,j,0);
893  amrex::Real mf_u_lo = mf_u(i ,j,0);
894 
895  amrex::Real v_hi = (k == 0) ? amrex::Real(1.5) * v_arr(i ,j+1,k ) - myhalf * v_arr(i ,j+1,k+1) :
896  myhalf * ( v_arr(i ,j+1,k-1) + v_arr(i ,j+1,k ) );
897  amrex::Real v_lo = (k == 0) ? amrex::Real(1.5) * v_arr(i ,j ,k ) - myhalf * v_arr(i ,j ,k+1) :
898  myhalf * ( v_arr(i ,j ,k-1) + v_arr(i ,j ,k ) );
899  amrex::Real mf_v_hi = mf_v(i,j+1,0);
900  amrex::Real mf_v_lo = mf_v(i,j ,0);
901 
902  amrex::Real u_met = met_xi * myhalf * ( u_hi*mf_u_hi + u_lo*mf_u_lo );
903  amrex::Real v_met = met_eta * myhalf * ( v_hi*mf_v_hi + v_lo*mf_v_lo );
904 
905  amrex::Real w = omega + u_met + v_met;
906  return w;
907 }
908 
909 //
910 // NOTE: 2nd order kept here for debugging purposes
911 //
912 
913 # if 0
914 // Define omega given u,v and w (2nd order)
915 /**
916  * Compute the contravariant vertical velocity omega from w (2nd order).
917  *
918  * @param[in] i x-index
919  * @param[in] j y-index
920  * @param[in] k z-index
921  * @param[in] w Vertical velocity.
922  * @param[in] u_arr X-velocity array.
923  * @param[in] v_arr Y-velocity array.
924  * @param[in] mf_u X-velocity map factor.
925  * @param[in] mf_v Y-velocity map factor.
926  * @param[in] z_nd Nodal physical height field.
927  * @param[in] dxInv Inverse cell spacing.
928  * @return Contravariant vertical velocity.
929  */
930 AMREX_GPU_DEVICE
931 AMREX_FORCE_INLINE
933 OmegaFromW (int& i, int& j, int& k, amrex::Real w,
934  const amrex::Array4<const amrex::Real>& u_arr,
935  const amrex::Array4<const amrex::Real>& v_arr,
936  const amrex::Array4<const amrex::Real>& mf_u,
937  const amrex::Array4<const amrex::Real>& mf_v,
938  const amrex::Array4<const amrex::Real>& z_nd,
939  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dxInv)
940 {
941  // This is dh/dxi at hi and lo edges
942  amrex::Real z_x_h = Compute_Z_AtWFace(i+1,j,k,z_nd);
943  amrex::Real z_x_l = Compute_Z_AtWFace(i-1,j,k,z_nd);
944  amrex::Real met_xi = myhalf * (z_x_h - z_x_l) * dxInv[0];
945 
946  // This is dh/deta at hi and lo edges
947  amrex::Real z_y_h = Compute_Z_AtWFace(i,j+1,k,z_nd);
948  amrex::Real z_y_l = Compute_Z_AtWFace(i,j-1,k,z_nd);
949  amrex::Real met_eta = myhalf * (z_y_h - z_y_l) * dxInv[1];
950 
951  // Use extrapolation instead of interpolation if at the bottom boundary
952  amrex::Real u_hi = (k == 0) ? amrex::Real(1.5) * u_arr(i+1,j ,k ) - myhalf * u_arr(i+1,j ,k+1) :
953  myhalf * ( u_arr(i+1,j ,k-1) + u_arr(i+1,j ,k ) );
954  amrex::Real u_lo = (k == 0) ? amrex::Real(1.5) * u_arr(i ,j ,k ) - myhalf * u_arr(i ,j ,k+1) :
955  myhalf * ( u_arr(i ,j ,k-1) + u_arr(i ,j ,k ) );
956  amrex::Real mf_u_hi = mf_u(i+1,j,0);
957  amrex::Real mf_u_lo = mf_u(i ,j,0);
958 
959  amrex::Real v_hi = (k == 0) ? amrex::Real(1.5) * v_arr(i ,j+1,k ) - myhalf * v_arr(i ,j+1,k+1) :
960  myhalf * ( v_arr(i ,j+1,k-1) + v_arr(i ,j+1,k ) );
961  amrex::Real v_lo = (k == 0) ? amrex::Real(1.5) * v_arr(i ,j ,k ) - myhalf * v_arr(i ,j ,k+1) :
962  myhalf * ( v_arr(i ,j ,k-1) + v_arr(i ,j ,k ) );
963  amrex::Real mf_v_hi = mf_v(i,j+1,0);
964  amrex::Real mf_v_lo = mf_v(i,j ,0);
965 
966  amrex::Real u_met = met_xi * myhalf * ( u_hi*mf_u_hi + u_lo*mf_u_lo );
967  amrex::Real v_met = met_eta * myhalf * ( v_hi*mf_v_hi + v_lo*mf_v_lo );
968 
969  amrex::Real omega = w - u_met - v_met;
970  return omega;
971 }
972 
973 // Define w given u and v arrays and scalar omega (2nd order)
974 /**
975  * Compute the vertical velocity w from the contravariant omega (2nd order).
976  *
977  * @param[in] i x-index
978  * @param[in] j y-index
979  * @param[in] k z-index
980  * @param[in] omega Contravariant vertical velocity.
981  * @param[in] u_arr X-velocity array.
982  * @param[in] v_arr Y-velocity array.
983  * @param[in] mf_u X-velocity map factor.
984  * @param[in] mf_v Y-velocity map factor.
985  * @param[in] z_nd Nodal physical height field.
986  * @param[in] dxInv Inverse cell spacing.
987  * @return Vertical velocity w.
988  */
989 AMREX_GPU_DEVICE
990 AMREX_FORCE_INLINE
992 WFromOmega (int& i, int& j, int& k, amrex::Real omega,
993  const amrex::Array4<const amrex::Real>& u_arr,
994  const amrex::Array4<const amrex::Real>& v_arr,
995  const amrex::Array4<const amrex::Real>& mf_u,
996  const amrex::Array4<const amrex::Real>& mf_v,
997  const amrex::Array4<const amrex::Real>& z_nd,
998  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dxInv)
999 {
1000  // This is dh/dxi at hi and lo edges
1001  amrex::Real z_x_h = Compute_Z_AtWFace(i+1,j,k,z_nd);
1002  amrex::Real z_x_l = Compute_Z_AtWFace(i-1,j,k,z_nd);
1003  amrex::Real met_xi = myhalf * (z_x_h - z_x_l) * dxInv[0];
1004 
1005  // This is dh/deta at hi and lo edges
1006  amrex::Real z_y_h = Compute_Z_AtWFace(i,j+1,k,z_nd);
1007  amrex::Real z_y_l = Compute_Z_AtWFace(i,j-1,k,z_nd);
1008  amrex::Real met_eta = myhalf * (z_y_h - z_y_l) * dxInv[1];
1009 
1010  // Use extrapolation instead of interpolation if at the bottom boundary
1011  amrex::Real u_hi = (k == 0) ? amrex::Real(1.5) * u_arr(i+1,j ,k ) - myhalf * u_arr(i+1,j ,k+1) :
1012  myhalf * ( u_arr(i+1,j ,k-1) + u_arr(i+1,j ,k ) );
1013  amrex::Real u_lo = (k == 0) ? amrex::Real(1.5) * u_arr(i ,j ,k ) - myhalf * u_arr(i ,j ,k+1) :
1014  myhalf * ( u_arr(i ,j ,k-1) + u_arr(i ,j ,k ) );
1015  amrex::Real mf_u_hi = mf_u(i+1,j,0);
1016  amrex::Real mf_u_lo = mf_u(i ,j,0);
1017 
1018  amrex::Real v_hi = (k == 0) ? amrex::Real(1.5) * v_arr(i ,j+1,k ) - myhalf * v_arr(i ,j+1,k+1) :
1019  myhalf * ( v_arr(i ,j+1,k-1) + v_arr(i ,j+1,k ) );
1020  amrex::Real v_lo = (k == 0) ? amrex::Real(1.5) * v_arr(i ,j ,k ) - myhalf * v_arr(i ,j ,k+1) :
1021  myhalf * ( v_arr(i ,j ,k-1) + v_arr(i ,j ,k ) );
1022  amrex::Real mf_v_hi = mf_v(i,j+1,0);
1023  amrex::Real mf_v_lo = mf_v(i,j ,0);
1024 
1025  amrex::Real u_met = met_xi * myhalf * ( u_hi*mf_u_hi + u_lo*mf_u_lo );
1026  amrex::Real v_met = met_eta * myhalf * ( v_hi*mf_v_hi + v_lo*mf_v_lo );
1027 
1028  amrex::Real w = omega + u_met + v_met;
1029  return w;
1030 }
1031 #endif
1032 
1033 
1034 //*****************************************************************************************
1035 // Rotate scalar flux vector and stress tensor for MOST
1036 //*****************************************************************************************
1037 /**
1038  * Rotate a scalar flux vector into terrain-following coordinates.
1039  *
1040  * @param[in] i x-index
1041  * @param[in] j y-index
1042  * @param[in] klo z-index
1043  * @param[in] flux Scalar flux value.
1044  * @param[in] dxInv Inverse cell spacing.
1045  * @param[in] zphys_arr Physical height field.
1046  * @param[out] phi1_arr Rotated flux component 1.
1047  * @param[out] phi2_arr Rotated flux component 2.
1048  * @param[out] phi3_arr Rotated flux component 3.
1049  */
1050 AMREX_GPU_DEVICE
1051 AMREX_FORCE_INLINE
1052 void
1053 rotate_scalar_flux (const int& i,
1054  const int& j,
1055  const int& klo,
1056  const int& /*dir*/,
1057  const amrex::Real& flux,
1058  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dxInv,
1059  const amrex::Array4<const amrex::Real>& zphys_arr,
1060  const amrex::Array4<amrex::Real>& phi1_arr,
1061  const amrex::Array4<amrex::Real>& phi2_arr,
1062  const amrex::Array4<amrex::Real>& phi3_arr)
1063 {
1064  amrex::Real h_xi = Compute_h_xi_AtCellCenter(i, j, klo, dxInv, zphys_arr);
1065  amrex::Real h_eta = Compute_h_eta_AtCellCenter(i, j, klo, dxInv, zphys_arr);
1066  amrex::Real InvNorm = one / std::sqrt(one + h_xi*h_xi + h_eta*h_eta);
1067  phi1_arr(i,j,klo) = -h_xi * flux * InvNorm;
1068  phi2_arr(i,j,klo) = -h_eta * flux * InvNorm;
1069  phi3_arr(i,j,klo) = flux * InvNorm;
1070 }
1071 
1072 /**
1073  * Rotate the stress tensor for the MOST model.
1074  *
1075  * @param[in] i x-index
1076  * @param[in] j y-index
1077  * @param[in] klo z-index
1078  * @param[in] flux Flux value used for rotation.
1079  * @param[in] dxInv Inverse cell spacing.
1080  * @param[in] zphys_arr Physical height field.
1081  * @param[in] u_arr X-velocity array.
1082  * @param[in] v_arr Y-velocity array.
1083  * @param[in] w_arr Z-velocity array.
1084  * @param[out] tau11_arr Stress component tau11.
1085  * @param[out] tau22_arr Stress component tau22.
1086  * @param[out] tau33_arr Stress component tau33.
1087  * @param[out] tau12_arr Stress component tau12.
1088  * @param[out] tau21_arr Stress component tau21.
1089  * @param[out] tau13_arr Stress component tau13.
1090  * @param[out] tau31_arr Stress component tau31.
1091  * @param[out] tau23_arr Stress component tau23.
1092  * @param[out] tau32_arr Stress component tau32.
1093  */
1094 AMREX_GPU_DEVICE
1095 AMREX_FORCE_INLINE
1096 void
1097 rotate_stress_tensor (const int& i,
1098  const int& j,
1099  const int& klo,
1100  const int& /*dir*/,
1101  const amrex::Real& flux,
1102  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& dxInv,
1103  const amrex::Array4<const amrex::Real>& zphys_arr,
1104  const amrex::Array4<const amrex::Real>& u_arr,
1105  const amrex::Array4<const amrex::Real>& v_arr,
1106  const amrex::Array4<const amrex::Real>& w_arr,
1107  const amrex::Array4<amrex::Real>& /*tau11_arr*/,
1108  const amrex::Array4<amrex::Real>& /*tau22_arr*/,
1109  const amrex::Array4<amrex::Real>& /*tau33_arr*/,
1110  const amrex::Array4<amrex::Real>& /*tau12_arr*/,
1111  const amrex::Array4<amrex::Real>& /*tau21_arr*/,
1112  const amrex::Array4<amrex::Real>& tau13_arr,
1113  const amrex::Array4<amrex::Real>& tau31_arr,
1114  const amrex::Array4<amrex::Real>& tau23_arr,
1115  const amrex::Array4<amrex::Real>& tau32_arr)
1116 {
1117  // Unit-normal vector
1118  amrex::Array1D<amrex::Real,0,2> n_hat;
1119 
1120  // Unit-tangent vectors
1121  amrex::Array1D<amrex::Real,0,2> u_t_hat;
1122 
1123  // Final basis vector for right-hand coord sys
1124  amrex::Array1D<amrex::Real,0,2> a_hat;
1125 
1126  // Rotation matrix
1127  amrex::Array2D<amrex::Real,0,2,0,2> R_mat;
1128 
1129  // Metric data
1130  amrex::Real h_xi = Compute_h_xi_AtIface(i, j, klo, dxInv, zphys_arr);
1131  amrex::Real h_eta = Compute_h_eta_AtIface(i, j, klo, dxInv, zphys_arr);
1132  amrex::Real h_zeta = Compute_h_zeta_AtIface(i, j, klo, dxInv, zphys_arr);
1133 
1134  // Populate the inward normal vector
1135  amrex::Real Inormn = one/std::sqrt(one + h_xi*h_xi + h_eta*h_eta);
1136  n_hat(0) = -Inormn*h_xi; n_hat(1) = -Inormn*h_eta; n_hat(2) = Inormn;
1137 
1138  // Populate the u_t vector (u_t = u - (u \cdot n)n)
1139  amrex::Real u = u_arr(i,j,klo);
1140  amrex::Real v = fourth * ( v_arr(i ,j,klo) + v_arr(i ,j+1,klo)
1141  + v_arr(i-1,j,klo) + v_arr(i-1,j+1,klo) );
1142  amrex::Real w = myhalf * ( w_arr(i ,j,klo) + w_arr(i-1,j ,klo) );
1143  amrex::Real u_dot_n = n_hat(0)*u + n_hat(1)*v + n_hat(2)*w;
1144  u_t_hat(0) = u - u_dot_n*n_hat(0);
1145  u_t_hat(1) = v - u_dot_n*n_hat(1);
1146  u_t_hat(2) = w - u_dot_n*n_hat(2);
1147  amrex::Real Norm_u_t = u_t_hat(0)*u_t_hat(0)
1148  + u_t_hat(1)*u_t_hat(1)
1149  + u_t_hat(2)*u_t_hat(2);
1150 
1151  // NOTE: the direction of the tangential velocity is undefined when that
1152  // velocity vanishes (a quiescent surface cell, or flow normal to the
1153  // terrain), so we cannot normalize. Leaving u_t_hat as the zero vector
1154  // is the only rotation-invariant choice, and it is the right limit for
1155  // a quiescent cell since the flux vanishes with the surface wind too.
1156  amrex::Real Inorm_u_t = (Norm_u_t > zero) ? one/std::sqrt(Norm_u_t) : zero;
1157  for (int icol(0); icol<3; ++icol) {
1158  u_t_hat(icol) *= Inorm_u_t;
1159  }
1160 
1161  // Populate the a_hat = n_hat X u_t_hat vector
1162  a_hat(0) = n_hat(1)*u_t_hat(2) - n_hat(2)*u_t_hat(1);
1163  a_hat(1) = -(n_hat(0)*u_t_hat(2) - n_hat(2)*u_t_hat(0));
1164  a_hat(2) = n_hat(0)*u_t_hat(1) - n_hat(1)*u_t_hat(0);
1165 
1166  // Copy column vectors into R_mat
1167  // NOTE: basis vectors form rows of R_mat
1168  int icol = 0;
1169  for (int jrow(0); jrow<3; ++jrow) {
1170  R_mat(icol,jrow) = u_t_hat(jrow);
1171  }
1172  icol = 1;
1173  for (int jrow(0); jrow<3; ++jrow) {
1174  R_mat(icol,jrow) = a_hat(jrow);
1175  }
1176  icol = 2;
1177  for (int jrow(0); jrow<3; ++jrow) {
1178  R_mat(icol,jrow) = n_hat(jrow);
1179  }
1180 
1181  // Body-fixed stresses
1182  amrex::Real T11 = two*R_mat(0,0)*R_mat(2,0)*flux;
1183  amrex::Real T22 = two*R_mat(0,1)*R_mat(2,1)*flux;
1184  //amrex::Real T33 = two*R_mat(0,2)*R_mat(2,2)*flux;
1185  amrex::Real T12 = (R_mat(0,0)*R_mat(2,1) + R_mat(2,0)*R_mat(0,1))*flux;
1186  amrex::Real T13 = (R_mat(0,0)*R_mat(2,2) + R_mat(0,2)*R_mat(2,0))*flux;
1187  amrex::Real T23 = (R_mat(0,2)*R_mat(2,1) + R_mat(0,1)*R_mat(2,2))*flux;
1188 
1189  // Populate the stress tensor (apply JT)
1190  // NOTE: We cannot set the stresses that do not live at the
1191  // bottom face --- e.g., tau11/22/33/12/21.
1192  tau13_arr(i,j,klo) = -h_xi*T11 - h_eta*T12 + T13;
1193  tau31_arr(i,j,klo) = h_zeta*T13;
1194 
1195  tau23_arr(i,j,klo) = -h_xi*T12 - h_eta*T22 + T23;
1196  tau32_arr(i,j,klo) = h_zeta*T23;
1197 }
1198 #endif
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
const int klo
Definition: ERF_InitCustomPert_ABL.H:75
Dimensionless numeric literals and pure mathematical constants.
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
Real w
Definition: ERF_Plotfile2DInterpolator.cpp:22
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real OmegaFromW(int &i, int &j, int &k, amrex::Real w, const amrex::Array4< const amrex::Real > &u_arr, const amrex::Array4< const amrex::Real > &v_arr, const amrex::Array4< const amrex::Real > &mf_u, const amrex::Array4< const amrex::Real > &mf_v, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxInv)
Definition: ERF_TerrainMetrics.H:798
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtEdgeCenterJ(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:616
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtEdgeCenterK(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:515
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtKface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:440
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtEdgeCenterJ(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:591
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtJface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:392
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtEdgeCenterJ(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:567
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void rotate_scalar_flux(const int &i, const int &j, const int &klo, const int &, const amrex::Real &flux, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxInv, const amrex::Array4< const amrex::Real > &zphys_arr, const amrex::Array4< amrex::Real > &phi1_arr, const amrex::Array4< amrex::Real > &phi2_arr, const amrex::Array4< amrex::Real > &phi3_arr)
Definition: ERF_TerrainMetrics.H:1053
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtEdgeCenterK(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:492
void init_zlevels(amrex::Vector< amrex::Vector< amrex::Real >> &zlevels_stag, amrex::Vector< amrex::Vector< amrex::Real >> &stretched_dz_h, amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real >> &stretched_dz_d, amrex::Vector< amrex::Geometry > const &geom, amrex::Vector< amrex::IntVect > const &ref_ratio, const amrex::Real grid_stretching_ratio, const amrex::Real zsurf, const amrex::Real dz0)
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtEdgeCenterI(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:641
void validate_flat_terrain(int lev, const amrex::MultiFab &z_phys_nd, const amrex::Vector< amrex::Real > &z_levels_h)
FineTerrain
Definition: ERF_TerrainMetrics.H:68
@ Transform
add the fine terrain as a correction that decays with height
@ None
caller has not prepared a fine mesh from the coarse level
@ Interpolate
use the coordinates interpolated from the coarse level as-is
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_Z_AtCellCenter(const int &i, const int &j, const int &k, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:712
FineTerrain which_fine_terrain()
Definition: ERF_TerrainMetrics.cpp:451
void init_which_terrain_grid(int lev, const amrex::Geometry &geom, amrex::MultiFab &z_phys_nd, amrex::Vector< amrex::Real > const &z_levels_h, FineTerrain fine_terrain=FineTerrain::None, amrex::MultiFab const *z_phys_interp=nullptr)
amrex::BoxArray join_boxes_stacked_in_z(const amrex::BoxArray &ba)
void init_fine_terrain_grid(int lev, const amrex::Geometry &geom, amrex::MultiFab &z_phys_nd, amrex::Vector< amrex::Real > const &z_levels_h, FineTerrain fine_terrain, amrex::MultiFab const *z_phys_interp)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtCellCenter(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:222
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtIface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:276
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtKface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:463
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtKface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:416
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_Zrel_AtCellCenter(const int &i, const int &j, const int &k, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:758
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtJface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:369
void update_stretched_dz(int lev, amrex::Vector< amrex::Vector< amrex::Real >> const &zlevels_stag, amrex::Vector< amrex::Vector< amrex::Real >> &stretched_dz_h, amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real >> &stretched_dz_d)
void make_terrain_fitted_coords(int lev, const amrex::Geometry &geom, amrex::MultiFab &z_phys_nd, amrex::Vector< amrex::Real > const &z_levels_h, amrex::GpuArray< ERF_BC, AMREX_SPACEDIM *2 > &phys_bc_type, FineTerrain fine_terrain=FineTerrain::None, amrex::MultiFab const *z_phys_interp=nullptr)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_Z_AtWFace(const int &i, const int &j, const int &k, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:736
amrex::Real get_dzmin_terrain(amrex::MultiFab &z_phys_nd)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtCellCenter(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:247
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtEdgeCenterK(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:540
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtCellCenter(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:197
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtIface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:323
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtEdgeCenterI(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:665
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_zeta_AtJface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:346
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_xi_AtIface(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:299
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void rotate_stress_tensor(const int &i, const int &j, const int &klo, const int &, const amrex::Real &flux, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxInv, const amrex::Array4< const amrex::Real > &zphys_arr, const amrex::Array4< const amrex::Real > &u_arr, const amrex::Array4< const amrex::Real > &v_arr, const amrex::Array4< const amrex::Real > &w_arr, const amrex::Array4< amrex::Real > &, const amrex::Array4< amrex::Real > &, const amrex::Array4< amrex::Real > &, const amrex::Array4< amrex::Real > &, const amrex::Array4< amrex::Real > &, const amrex::Array4< amrex::Real > &tau13_arr, const amrex::Array4< amrex::Real > &tau31_arr, const amrex::Array4< amrex::Real > &tau23_arr, const amrex::Array4< amrex::Real > &tau32_arr)
Definition: ERF_TerrainMetrics.H:1097
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_h_eta_AtEdgeCenterI(const int &i, const int &j, const int &k, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:688
void init_default_zphys(int lev, const amrex::Geometry &geom, amrex::MultiFab &z_phys_nd, amrex::MultiFab &z_phys_cc, amrex::Real z_offset=zero)
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real WFromOmega(int &i, int &j, int &k, amrex::Real omega, const amrex::Array4< const amrex::Real > &u_arr, const amrex::Array4< const amrex::Real > &v_arr, const amrex::Array4< const amrex::Real > &mf_u, const amrex::Array4< const amrex::Real > &mf_v, const amrex::Array4< const amrex::Real > &z_nd, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dxInv)
Definition: ERF_TerrainMetrics.H:863
@ omega
Definition: ERF_Morrison.H:55