ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_MakeMomSources.cpp File Reference
#include <AMReX_MultiFab.H>
#include <AMReX_ArrayLim.H>
#include <AMReX_BCRec.H>
#include <AMReX_TableData.H>
#include <AMReX_GpuContainers.H>
#include "ERF_NumericalDiffusion.H"
#include "ERF_PlaneAverage.H"
#include "ERF_TI_slow_headers.H"
#include "ERF_SrcHeaders.H"
#include "ERF_Utils.H"
Include dependency graph for ERF_MakeMomSources.cpp:

Functions

void make_mom_sources (Real time, const Vector< MultiFab > &S_data, MultiFab &z_phys_nd, MultiFab &z_phys_cc, Vector< Real > &stretched_dz_h, const MultiFab &xvel, const MultiFab &yvel, const MultiFab &wvel, MultiFab &xmom_src, MultiFab &ymom_src, MultiFab &zmom_src, const MultiFab &base_state, MultiFab *forest_drag, MultiFab *terrain_blank, MultiFab *cosPhi_mf, MultiFab *sinPhi_mf, const Geometry geom, const SolverChoice &solverChoice, Vector< std::unique_ptr< MultiFab >> &, const Real *dptr_u_geos, const Real *dptr_v_geos, const Real *dptr_wbar_sub, const Vector< Real * > d_rayleigh_ptrs_at_lev, const Vector< Real * > d_sponge_ptrs_at_lev, const Vector< MultiFab > *forecast_state_at_lev, InputSoundingData &input_sounding_data, bool is_slow_step)
 

Function Documentation

◆ make_mom_sources()

void make_mom_sources ( Real  time,
const Vector< MultiFab > &  S_data,
MultiFab &  z_phys_nd,
MultiFab &  z_phys_cc,
Vector< Real > &  stretched_dz_h,
const MultiFab &  xvel,
const MultiFab &  yvel,
const MultiFab &  wvel,
MultiFab &  xmom_src,
MultiFab &  ymom_src,
MultiFab &  zmom_src,
const MultiFab &  base_state,
MultiFab *  forest_drag,
MultiFab *  terrain_blank,
MultiFab *  cosPhi_mf,
MultiFab *  sinPhi_mf,
const Geometry  geom,
const SolverChoice solverChoice,
Vector< std::unique_ptr< MultiFab >> &  ,
const Real dptr_u_geos,
const Real dptr_v_geos,
const Real dptr_wbar_sub,
const Vector< Real * >  d_rayleigh_ptrs_at_lev,
const Vector< Real * >  d_sponge_ptrs_at_lev,
const Vector< MultiFab > *  forecast_state_at_lev,
InputSoundingData input_sounding_data,
bool  is_slow_step 
)

Function for computing the slow RHS for the evolution equations for the density, potential temperature and momentum.

Parameters
[in]S_datacurrent solution
[in]xvelx-component of velocity
[in]yvely-component of velocity
[in]xmom_srcsource terms for x-momentum
[in]ymom_srcsource terms for y-momentum
[in]zmom_srcsource terms for z-momentum
[in]geomContainer for geometric information
[in]solverChoiceContainer for solver parameters
[in]mapfacmap factors
[in]dptr_u_geoscustom geostrophic wind profile
[in]dptr_v_geoscustom geostrophic wind profile
[in]dptr_wbar_subsubsidence source term
[in]d_rayleigh_ptrs_at_levVector of {strength of Rayleigh damping, reference value for xvel/yvel/zvel/theta} used to define Rayleigh damping
60 {
61  BL_PROFILE_REGION("erf_make_mom_sources()");
62 
63  Box domain(geom.Domain());
64  const GpuArray<Real, AMREX_SPACEDIM> dxInv = geom.InvCellSizeArray();
65 
66  // Initialize sources to zero each time we may use them
67  xmom_src.setVal(0.0);
68  ymom_src.setVal(0.0);
69  zmom_src.setVal(0.0);
70 
71  MultiFab r_hse (base_state, make_alias, BaseState::r0_comp , 1);
72 
73  // flags to apply certain source terms in substep call only
74  bool use_Rayleigh_fast = solverChoice.rayleigh_damp_substep;
75  bool use_canopy_fast = solverChoice.forest_substep;
76  bool use_ImmersedForcing_fast = solverChoice.immersed_forcing_substep;
77 
78  // *****************************************************************************
79  // Define source term for all three components of momenta from
80  // 1. Coriolis forcing for (xmom,ymom,zmom)
81  // 2. Rayleigh damping for (xmom,ymom,zmom)
82  // 3. Constant / height-dependent geostrophic forcing
83  // 4. Subsidence
84  // 5. Nudging towards input sounding data
85  // 6. Numerical diffusion for (xmom,ymom,zmom)
86  // 7. Sponge
87  // 8. Forest canopy
88  // 9. Immersed forcing
89  // 10. Constant mass flux
90  // *****************************************************************************
91  // NOTE: buoyancy is now computed in a separate routine - it should not appear here
92  // *****************************************************************************
93  //const bool l_use_ndiff = solverChoice.use_num_diff;
94 
95  if (solverChoice.terrain_type == TerrainType::ImmersedForcing) {
96  if (solverChoice.do_forest_drag) {
97  amrex::Error(" Currently forest canopy cannot be used with immersed forcing");
98  }
99  }
100 
101 
102  // *****************************************************************************
103  // Data for Coriolis forcing
104  // *****************************************************************************
105  auto use_coriolis = solverChoice.use_coriolis;
106  auto coriolis_factor = solverChoice.coriolis_factor;
107  auto cosphi = solverChoice.cosphi;
108  auto sinphi = solverChoice.sinphi;
109  auto var_coriolis = solverChoice.variable_coriolis;
110  auto has_lat_lon = solverChoice.has_lat_lon;
111 
112  // *****************************************************************************
113  // Flag for Geostrophic forcing
114  // *****************************************************************************
115  auto abl_geo_forcing = solverChoice.abl_geo_forcing;
116  auto geo_wind_profile = solverChoice.have_geo_wind_profile;
117 
118  // *****************************************************************************
119  // Data for Rayleigh damping
120  // *****************************************************************************
121  auto rayleigh_damp_U = solverChoice.rayleigh_damp_U;
122  auto rayleigh_damp_V = solverChoice.rayleigh_damp_V;
123  auto rayleigh_damp_W = solverChoice.rayleigh_damp_W;
124 
125  Real* ubar = d_rayleigh_ptrs_at_lev[Rayleigh::ubar];
126  Real* vbar = d_rayleigh_ptrs_at_lev[Rayleigh::vbar];
127  Real* wbar = d_rayleigh_ptrs_at_lev[Rayleigh::wbar];
128 
129  // *****************************************************************************
130  // Data for constant mass flux
131  // *****************************************************************************
132  bool enforce_massflux_x = (solverChoice.const_massflux_u != 0);
133  bool enforce_massflux_y = (solverChoice.const_massflux_v != 0);
134  Real U_target = solverChoice.const_massflux_u;
135  Real V_target = solverChoice.const_massflux_v;
136  int massflux_klo = solverChoice.massflux_klo;
137  int massflux_khi = solverChoice.massflux_khi;
138 
139  // These will be updated by integrating through the planar average profiles
140  Real rhoUA_target{0};
141  Real rhoVA_target{0};
142  Real rhoUA{0};
143  Real rhoVA{0};
144 
145  // *****************************************************************************
146  // Planar averages for subsidence, nudging, or constant mass flux
147  // *****************************************************************************
148  Table1D<Real> dptr_r_plane, dptr_u_plane, dptr_v_plane;
149  TableData<Real, 1> r_plane_tab, u_plane_tab, v_plane_tab;
150 
151  if (is_slow_step && (dptr_wbar_sub || solverChoice.nudging_from_input_sounding ||
152  enforce_massflux_x || enforce_massflux_y))
153  {
154  const int offset = 1;
155  const int u_offset = 1;
156  const int v_offset = 1;
157 
158  //
159  // We use the alias here to control ncomp inside the PlaneAverage
160  //
161  MultiFab cons(S_data[IntVars::cons], make_alias, 0, 1);
162 
163  IntVect ng_c = S_data[IntVars::cons].nGrowVect(); ng_c[2] = offset;
164  PlaneAverage r_ave(&cons, geom, solverChoice.ave_plane, ng_c);
165  r_ave.compute_averages(ZDir(), r_ave.field());
166 
167  int ncell = r_ave.ncell_line();
168  Gpu::HostVector< Real> r_plane_h(ncell);
169  Gpu::DeviceVector< Real> r_plane_d(ncell);
170 
171  r_ave.line_average(Rho_comp, r_plane_h);
172 
173  Gpu::copyAsync(Gpu::hostToDevice, r_plane_h.begin(), r_plane_h.end(), r_plane_d.begin());
174 
175  Real* dptr_r = r_plane_d.data();
176 
177  Box tdomain = domain; tdomain.grow(2,ng_c[2]);
178  r_plane_tab.resize({tdomain.smallEnd(2)}, {tdomain.bigEnd(2)});
179 
180  dptr_r_plane = r_plane_tab.table();
181  ParallelFor(ncell, [=] AMREX_GPU_DEVICE (int k) noexcept
182  {
183  dptr_r_plane(k-offset) = dptr_r[k];
184  });
185 
186  // U and V momentum
187  IntVect ng_u = S_data[IntVars::xmom].nGrowVect(); ng_u[2] = u_offset;
188  PlaneAverage u_ave(&(S_data[IntVars::xmom]), geom, solverChoice.ave_plane, ng_u);
189 
190  IntVect ng_v = S_data[IntVars::ymom].nGrowVect(); ng_v[2] = v_offset;
191  PlaneAverage v_ave(&(S_data[IntVars::ymom]), geom, solverChoice.ave_plane, ng_v);
192 
193  u_ave.compute_averages(ZDir(), u_ave.field());
194  v_ave.compute_averages(ZDir(), v_ave.field());
195 
196  int u_ncell = u_ave.ncell_line();
197  int v_ncell = v_ave.ncell_line();
198  Gpu::HostVector< Real> u_plane_h(u_ncell), v_plane_h(v_ncell);
199  Gpu::DeviceVector< Real> u_plane_d(u_ncell), v_plane_d(v_ncell);
200 
201  u_ave.line_average(0, u_plane_h);
202  v_ave.line_average(0, v_plane_h);
203 
204  Gpu::copyAsync(Gpu::hostToDevice, u_plane_h.begin(), u_plane_h.end(), u_plane_d.begin());
205  Gpu::copyAsync(Gpu::hostToDevice, v_plane_h.begin(), v_plane_h.end(), v_plane_d.begin());
206 
207  Real* dptr_u = u_plane_d.data();
208  Real* dptr_v = v_plane_d.data();
209 
210  Box udomain = domain; udomain.grow(2,ng_u[2]);
211  Box vdomain = domain; vdomain.grow(2,ng_v[2]);
212  u_plane_tab.resize({udomain.smallEnd(2)}, {udomain.bigEnd(2)});
213  v_plane_tab.resize({vdomain.smallEnd(2)}, {vdomain.bigEnd(2)});
214 
215  dptr_u_plane = u_plane_tab.table();
216  ParallelFor(u_ncell, [=] AMREX_GPU_DEVICE (int k) noexcept
217  {
218  dptr_u_plane(k-u_offset) = dptr_u[k];
219  });
220 
221  dptr_v_plane = v_plane_tab.table();
222  ParallelFor(v_ncell, [=] AMREX_GPU_DEVICE (int k) noexcept
223  {
224  dptr_v_plane(k-v_offset) = dptr_v[k];
225  });
226 
227  // sum in z for massflux adjustment
228  if (enforce_massflux_x || enforce_massflux_y) {
229  Real Lx = geom.ProbHi(0) - geom.ProbLo(0);
230  Real Ly = geom.ProbHi(1) - geom.ProbLo(1);
231 
232  if (solverChoice.mesh_type == MeshType::ConstantDz) {
233  // note: massflux_khi corresponds to unstaggered indices in this case
234  rhoUA = std::accumulate(u_plane_h.begin() + u_offset + massflux_klo,
235  u_plane_h.begin() + u_offset + massflux_khi+1, 0.0);
236  rhoVA = std::accumulate(v_plane_h.begin() + v_offset + massflux_klo,
237  v_plane_h.begin() + v_offset + massflux_khi+1, 0.0);
238  rhoUA_target = std::accumulate(r_plane_h.begin() + offset + massflux_klo,
239  r_plane_h.begin() + offset + massflux_khi+1, 0.0);
240  rhoVA_target = rhoUA_target;
241 
242  rhoUA *= geom.CellSize(2) * Ly;
243  rhoVA *= geom.CellSize(2) * Lx;
244  rhoUA_target *= geom.CellSize(2) * Ly;
245  rhoVA_target *= geom.CellSize(2) * Lx;
246 
247  } else if (solverChoice.mesh_type == MeshType::StretchedDz) {
248  // note: massflux_khi corresponds to staggered indices in this case
249  for (int k=massflux_klo; k < massflux_khi; ++k) {
250  rhoUA += u_plane_h[k + u_offset] * stretched_dz_h[k];
251  rhoVA += v_plane_h[k + v_offset] * stretched_dz_h[k];
252  rhoUA_target += r_plane_h[k + offset] * stretched_dz_h[k];
253  }
254  rhoVA_target = rhoUA_target;
255 
256  rhoUA *= Ly;
257  rhoVA *= Lx;
258  rhoUA_target *= Ly;
259  rhoVA_target *= Lx;
260  }
261 
262  // at this point, this is integrated rho*dA
263  rhoUA_target *= U_target;
264  rhoVA_target *= V_target;
265 
266  Print() << "Integrated mass flux : " << rhoUA << " " << rhoVA
267  << " (target: " << rhoUA_target << " " << rhoVA_target << ")"
268  << std::endl;
269  }
270  }
271 
272  // *****************************************************************************
273  // Add all the other forcings
274  // *****************************************************************************
275  for ( MFIter mfi(S_data[IntVars::cons]); mfi.isValid(); ++mfi)
276  {
277  Box tbx = mfi.nodaltilebox(0);
278  Box tby = mfi.nodaltilebox(1);
279  Box tbz = mfi.nodaltilebox(2);
280  if (tbz.bigEnd(2) == domain.bigEnd(2)+1) tbz.growHi(2,-1);
281 
282  const Array4<const Real>& cell_data = S_data[IntVars::cons].array(mfi);
283  const Array4<const Real>& rho_u = S_data[IntVars::xmom].array(mfi);
284  const Array4<const Real>& rho_v = S_data[IntVars::ymom].array(mfi);
285  const Array4<const Real>& rho_w = S_data[IntVars::zmom].array(mfi);
286 
287  const Array4<const Real>& u = xvel.array(mfi);
288  const Array4<const Real>& v = yvel.array(mfi);
289  const Array4<const Real>& w = wvel.array(mfi);
290 
291  const Array4< Real>& xmom_src_arr = xmom_src.array(mfi);
292  const Array4< Real>& ymom_src_arr = ymom_src.array(mfi);
293  const Array4< Real>& zmom_src_arr = zmom_src.array(mfi);
294 
295  const Array4<const Real>& r0 = r_hse.const_array(mfi);
296 
297  const Array4<const Real>& f_drag_arr = (forest_drag) ? forest_drag->const_array(mfi) :
298  Array4<const Real>{};
299  const Array4<const Real>& t_blank_arr = (terrain_blank) ? terrain_blank->const_array(mfi) :
300  Array4<const Real>{};
301 
302  const Array4<const Real>& cphi_arr = (cosPhi_mf) ? cosPhi_mf->const_array(mfi) :
303  Array4<const Real>{};
304  const Array4<const Real>& sphi_arr = (sinPhi_mf) ? sinPhi_mf->const_array(mfi) :
305  Array4<const Real>{};
306 
307  const Array4<const Real>& z_nd_arr = z_phys_nd.const_array(mfi);
308  const Array4<const Real>& z_cc_arr = z_phys_cc.const_array(mfi);
309 
310 
311  // *****************************************************************************
312  // 1. Add CORIOLIS forcing (this assumes east is +x, north is +y)
313  // *****************************************************************************
314  if (use_coriolis && is_slow_step) {
315  if(solverChoice.init_type == InitType::HindCast) {
316  const Array4<const Real>& latlon_arr = (*forecast_state_at_lev)[4].array(mfi);
317  ParallelFor(tbx, tby, tbz,
318  [=] AMREX_GPU_DEVICE (int i, int j, int k)
319  {
320  Real rho_v_loc = 0.25 * (rho_v(i,j+1,k) + rho_v(i,j,k) + rho_v(i-1,j+1,k) + rho_v(i-1,j,k));
321  Real rho_w_loc = 0.25 * (rho_w(i,j,k+1) + rho_w(i,j,k) + rho_w(i,j-1,k+1) + rho_w(i,j-1,k));
322  Real latitude = latlon_arr(i,j,k,0);
323  Real sphi_loc = std::sin(latitude*PI/180.0);
324  Real cphi_loc = std::cos(latitude*PI/180.0);
325  xmom_src_arr(i, j, k) += coriolis_factor * (rho_v_loc * sphi_loc - rho_w_loc * cphi_loc);
326  },
327  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
328  Real rho_u_loc = 0.25 * (rho_u(i+1,j,k) + rho_u(i,j,k) + rho_u(i+1,j-1,k) + rho_u(i,j-1,k));
329  Real latitude = latlon_arr(i,j,k,0);
330  Real sphi_loc = std::sin(latitude*PI/180.0);
331  ymom_src_arr(i, j, k) += -coriolis_factor * rho_u_loc * sphi_loc;
332  },
333  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
334  Real rho_u_loc = 0.25 * (rho_u(i+1,j,k) + rho_u(i,j,k) + rho_u(i+1,j,k-1) + rho_u(i,j,k-1));
335  Real latitude = latlon_arr(i,j,k,0);
336  Real cphi_loc = std::cos(latitude*PI/180.0);
337  zmom_src_arr(i, j, k) += coriolis_factor * rho_u_loc * cphi_loc;
338  });
339  }
340  else if (var_coriolis && has_lat_lon) {
341  ParallelFor(tbx, tby, tbz,
342  [=] AMREX_GPU_DEVICE (int i, int j, int k)
343  {
344  Real rho_v_loc = 0.25 * (rho_v(i,j+1,k) + rho_v(i,j,k) + rho_v(i-1,j+1,k) + rho_v(i-1,j,k));
345  Real rho_w_loc = 0.25 * (rho_w(i,j,k+1) + rho_w(i,j,k) + rho_w(i,j-1,k+1) + rho_w(i,j-1,k));
346  Real sphi_loc = 0.5 * (sphi_arr(i,j,0) + sphi_arr(i-1,j,0));
347  Real cphi_loc = 0.5 * (cphi_arr(i,j,0) + cphi_arr(i-1,j,0));
348  xmom_src_arr(i, j, k) += coriolis_factor * (rho_v_loc * sphi_loc - rho_w_loc * cphi_loc);
349  },
350  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
351  Real rho_u_loc = 0.25 * (rho_u(i+1,j,k) + rho_u(i,j,k) + rho_u(i+1,j-1,k) + rho_u(i,j-1,k));
352  Real sphi_loc = 0.5 * (sphi_arr(i,j,0) + sphi_arr(i,j-1,0));
353  ymom_src_arr(i, j, k) += -coriolis_factor * rho_u_loc * sphi_loc;
354  },
355  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
356  Real rho_u_loc = 0.25 * (rho_u(i+1,j,k) + rho_u(i,j,k) + rho_u(i+1,j,k-1) + rho_u(i,j,k-1));
357  zmom_src_arr(i, j, k) += coriolis_factor * rho_u_loc * cphi_arr(i,j,0);
358  });
359  } else {
360  ParallelFor(tbx, tby, tbz,
361  [=] AMREX_GPU_DEVICE (int i, int j, int k)
362  {
363  Real rho_v_loc = 0.25 * (rho_v(i,j+1,k) + rho_v(i,j,k) + rho_v(i-1,j+1,k) + rho_v(i-1,j,k));
364  Real rho_w_loc = 0.25 * (rho_w(i,j,k+1) + rho_w(i,j,k) + rho_w(i,j-1,k+1) + rho_w(i,j-1,k));
365  xmom_src_arr(i, j, k) += coriolis_factor * (rho_v_loc * sinphi - rho_w_loc * cosphi);
366  },
367  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
368  Real rho_u_loc = 0.25 * (rho_u(i+1,j,k) + rho_u(i,j,k) + rho_u(i+1,j-1,k) + rho_u(i,j-1,k));
369  ymom_src_arr(i, j, k) += -coriolis_factor * rho_u_loc * sinphi;
370  },
371  [=] AMREX_GPU_DEVICE (int i, int j, int k) {
372  Real rho_u_loc = 0.25 * (rho_u(i+1,j,k) + rho_u(i,j,k) + rho_u(i+1,j,k-1) + rho_u(i,j,k-1));
373  zmom_src_arr(i, j, k) += coriolis_factor * rho_u_loc * cosphi;
374  });
375  } // var_coriolis
376  } // use_coriolis
377 
378  // *****************************************************************************
379  // 2. Add RAYLEIGH damping
380  // *****************************************************************************
381  Real zlo = geom.ProbLo(2);
382  Real dz = geom.CellSize(2);
383  Real ztop = solverChoice.rayleigh_ztop;
384  Real zdamp = solverChoice.rayleigh_zdamp;
385  Real dampcoef = solverChoice.rayleigh_dampcoef;
386 
387  if ((is_slow_step && !use_Rayleigh_fast) || (!is_slow_step && use_Rayleigh_fast)) {
388  if (rayleigh_damp_U) {
389  ParallelFor(tbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
390  {
391  Real zcc = (z_cc_arr) ? z_cc_arr(i,j,k) : zlo + (k+0.5)*dz;
392  Real zfrac = 1 - (ztop - zcc) / zdamp;
393  if (zfrac > 0) {
394  Real rho_on_u_face = 0.5 * ( cell_data(i,j,k,Rho_comp) + cell_data(i-1,j,k,Rho_comp) );
395  Real uu = rho_u(i,j,k) / rho_on_u_face;
396  Real sinefac = std::sin(PIoTwo*zfrac);
397  xmom_src_arr(i, j, k) -= dampcoef*sinefac*sinefac * (uu - ubar[k]) * rho_on_u_face;
398  }
399  });
400  }
401 
402  if (rayleigh_damp_V) {
403  ParallelFor(tby, [=] AMREX_GPU_DEVICE (int i, int j, int k)
404  {
405  Real zcc = (z_cc_arr) ? z_cc_arr(i,j,k) : zlo + (k+0.5)*dz;
406  Real zfrac = 1 - (ztop - zcc) / zdamp;
407  if (zfrac > 0) {
408  Real rho_on_v_face = 0.5 * ( cell_data(i,j,k,Rho_comp) + cell_data(i,j-1,k,Rho_comp) );
409  Real vv = rho_v(i,j,k) / rho_on_v_face;
410  Real sinefac = std::sin(PIoTwo*zfrac);
411  ymom_src_arr(i, j, k) -= dampcoef*sinefac*sinefac * (vv - vbar[k]) * rho_on_v_face;
412  }
413  });
414  }
415 
416  if (rayleigh_damp_W) {
417  ParallelFor(tbz, [=] AMREX_GPU_DEVICE (int i, int j, int k)
418  {
419  Real zstag = (z_nd_arr) ? z_nd_arr(i,j,k) : zlo + k*dz;
420  Real zfrac = 1 - (ztop - zstag) / zdamp;
421  if (zfrac > 0) {
422  Real rho_on_w_face = 0.5 * ( cell_data(i,j,k,Rho_comp) + cell_data(i,j,k-1,Rho_comp) );
423  Real ww = rho_w(i,j,k) / rho_on_w_face;
424  Real sinefac = std::sin(PIoTwo*zfrac);
425  zmom_src_arr(i, j, k) -= dampcoef*sinefac*sinefac * (ww - wbar[k]) * rho_on_w_face;
426  }
427  });
428  }
429  } // fast or slow step
430 
431  // *****************************************************************************
432  // 3a. Add constant GEOSTROPHIC forcing
433  // *****************************************************************************
434  if (is_slow_step) {
435  ParallelFor(tbx, tby, tbz,
436  [=] AMREX_GPU_DEVICE (int i, int j, int k)
437  {
438  Real rho_on_u_face = 0.5 * ( cell_data(i,j,k,Rho_comp) + cell_data(i-1,j,k,Rho_comp) );
439  xmom_src_arr(i, j, k) += rho_on_u_face * abl_geo_forcing[0];
440  },
441  [=] AMREX_GPU_DEVICE (int i, int j, int k)
442  {
443  Real rho_on_v_face = 0.5 * ( cell_data(i,j,k,Rho_comp) + cell_data(i,j-1,k,Rho_comp) );
444  ymom_src_arr(i, j, k) += rho_on_v_face * abl_geo_forcing[1];
445  },
446  [=] AMREX_GPU_DEVICE (int i, int j, int k)
447  {
448  Real rho_on_w_face = 0.5 * ( cell_data(i,j,k,Rho_comp) + cell_data(i,j,k-1,Rho_comp) );
449  zmom_src_arr(i, j, k) += rho_on_w_face * abl_geo_forcing[2];
450  });
451  }
452 
453  // *****************************************************************************
454  // 3b. Add height-dependent GEOSTROPHIC forcing
455  // *****************************************************************************
456  if (geo_wind_profile && is_slow_step) {
457  ParallelFor(tbx, tby,
458  [=] AMREX_GPU_DEVICE (int i, int j, int k)
459  {
460  Real rho_on_u_face = 0.5 * ( cell_data(i,j,k,Rho_comp) + cell_data(i-1,j,k,Rho_comp) );
461  xmom_src_arr(i, j, k) -= coriolis_factor * rho_on_u_face * dptr_v_geos[k] * sinphi;
462  },
463  [=] AMREX_GPU_DEVICE (int i, int j, int k)
464  {
465  Real rho_on_v_face = 0.5 * ( cell_data(i,j,k,Rho_comp) + cell_data(i,j-1,k,Rho_comp) );
466  ymom_src_arr(i, j, k) += coriolis_factor * rho_on_v_face * dptr_u_geos[k] * sinphi;
467  });
468  } // geo_wind_profile
469 
470  // *****************************************************************************
471  // 4. Add custom SUBSIDENCE terms
472  // *****************************************************************************
473  if (solverChoice.custom_w_subsidence && is_slow_step) {
474  if (solverChoice.custom_forcing_prim_vars) {
475  const int nr = Rho_comp;
476  ParallelFor(tbx, tby,
477  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
478  {
479  Real dzInv = 0.5*dxInv[2];
480  if (z_nd_arr) {
481  Real z_xf_lo = 0.25 * ( z_nd_arr(i,j,k ) + z_nd_arr(i,j+1,k )
482  + z_nd_arr(i,j,k-1) + z_nd_arr(i,j+1,k-1) );
483  Real z_xf_hi = 0.25 * ( z_nd_arr(i,j,k+1) + z_nd_arr(i,j+1,k+1)
484  + z_nd_arr(i,j,k+2) + z_nd_arr(i,j+1,k+2) );
485  dzInv = 1.0 / (z_xf_hi - z_xf_lo);
486  }
487  Real rho_on_u_face = 0.5 * ( cell_data(i,j,k,nr) + cell_data(i-1,j,k,nr) );
488  Real U_hi = dptr_u_plane(k+1) / dptr_r_plane(k+1);
489  Real U_lo = dptr_u_plane(k-1) / dptr_r_plane(k-1);
490  Real wbar_xf = 0.5 * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
491  xmom_src_arr(i, j, k) -= rho_on_u_face * wbar_xf * (U_hi - U_lo) * dzInv;
492  },
493  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
494  {
495  Real dzInv = 0.5*dxInv[2];
496  if (z_nd_arr) {
497  Real z_yf_lo = 0.25 * ( z_nd_arr(i,j,k ) + z_nd_arr(i+1,j,k )
498  + z_nd_arr(i,j,k-1) + z_nd_arr(i+1,j,k-1) );
499  Real z_yf_hi = 0.25 * ( z_nd_arr(i,j,k+1) + z_nd_arr(i+1,j,k+1)
500  + z_nd_arr(i,j,k+2) + z_nd_arr(i+1,j,k+2) );
501  dzInv = 1.0 / (z_yf_hi - z_yf_lo);
502  }
503  Real rho_on_v_face = 0.5 * ( cell_data(i,j,k,nr) + cell_data(i,j-1,k,nr) );
504  Real V_hi = dptr_v_plane(k+1) / dptr_r_plane(k+1);
505  Real V_lo = dptr_v_plane(k-1) / dptr_r_plane(k-1);
506  Real wbar_yf = 0.5 * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
507  ymom_src_arr(i, j, k) -= rho_on_v_face * wbar_yf * (V_hi - V_lo) * dzInv;
508  });
509  } else {
510  ParallelFor(tbx, tby,
511  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
512  {
513  Real dzInv = 0.5*dxInv[2];
514  if (z_nd_arr) {
515  Real z_xf_lo = 0.25 * ( z_nd_arr(i,j,k ) + z_nd_arr(i,j+1,k )
516  + z_nd_arr(i,j,k-1) + z_nd_arr(i,j+1,k-1) );
517  Real z_xf_hi = 0.25 * ( z_nd_arr(i,j,k+1) + z_nd_arr(i,j+1,k+1)
518  + z_nd_arr(i,j,k+2) + z_nd_arr(i,j+1,k+2) );
519  dzInv = 1.0 / (z_xf_hi - z_xf_lo);
520  }
521  Real U_hi = dptr_u_plane(k+1) / dptr_r_plane(k+1);
522  Real U_lo = dptr_u_plane(k-1) / dptr_r_plane(k-1);
523  Real wbar_xf = 0.5 * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
524  xmom_src_arr(i, j, k) -= wbar_xf * (U_hi - U_lo) * dzInv;
525  },
526  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
527  {
528  Real dzInv = 0.5*dxInv[2];
529  if (z_nd_arr) {
530  Real z_yf_lo = 0.25 * ( z_nd_arr(i,j,k ) + z_nd_arr(i+1,j,k )
531  + z_nd_arr(i,j,k-1) + z_nd_arr(i+1,j,k-1) );
532  Real z_yf_hi = 0.25 * ( z_nd_arr(i,j,k+1) + z_nd_arr(i+1,j,k+1)
533  + z_nd_arr(i,j,k+2) + z_nd_arr(i+1,j,k+2) );
534  dzInv = 1.0 / (z_yf_hi - z_yf_lo);
535  }
536  Real V_hi = dptr_v_plane(k+1) / dptr_r_plane(k+1);
537  Real V_lo = dptr_v_plane(k-1) / dptr_r_plane(k-1);
538  Real wbar_yf = 0.5 * (dptr_wbar_sub[k] + dptr_wbar_sub[k+1]);
539  ymom_src_arr(i, j, k) -= wbar_yf * (V_hi - V_lo) * dzInv;
540  });
541  }
542  }
543 
544  // *************************************************************************************
545  // 5. Add nudging towards value specified in input sounding
546  // *************************************************************************************
547  if (solverChoice.nudging_from_input_sounding && is_slow_step)
548  {
549  int itime_n = 0;
550  int itime_np1 = 0;
551  Real coeff_n = Real(1.0);
552  Real coeff_np1 = Real(0.0);
553 
554  Real tau_inv = Real(1.0) / input_sounding_data.tau_nudging;
555 
556  int n_sounding_times = input_sounding_data.input_sounding_time.size();
557 
558  for (int nt = 1; nt < n_sounding_times; nt++) {
559  if (time > input_sounding_data.input_sounding_time[nt]) itime_n = nt;
560  }
561  if (itime_n == n_sounding_times-1) {
562  itime_np1 = itime_n;
563  } else {
564  itime_np1 = itime_n+1;
565  coeff_np1 = (time - input_sounding_data.input_sounding_time[itime_n]) /
566  (input_sounding_data.input_sounding_time[itime_np1] - input_sounding_data.input_sounding_time[itime_n]);
567  coeff_n = Real(1.0) - coeff_np1;
568  }
569 
570  int nr = Rho_comp;
571 
572  const Real* u_inp_sound_n = input_sounding_data.U_inp_sound_d[itime_n].dataPtr();
573  const Real* u_inp_sound_np1 = input_sounding_data.U_inp_sound_d[itime_np1].dataPtr();
574  const Real* v_inp_sound_n = input_sounding_data.V_inp_sound_d[itime_n].dataPtr();
575  const Real* v_inp_sound_np1 = input_sounding_data.V_inp_sound_d[itime_np1].dataPtr();
576  ParallelFor(tbx, tby,
577  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
578  {
579  Real nudge_u = (coeff_n*u_inp_sound_n[k] + coeff_np1*u_inp_sound_np1[k]) - (dptr_u_plane(k)/dptr_r_plane(k));
580  nudge_u *= tau_inv;
581  xmom_src_arr(i, j, k) += cell_data(i, j, k, nr) * nudge_u;
582  },
583  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
584  {
585  Real nudge_v = (coeff_n*v_inp_sound_n[k] + coeff_np1*v_inp_sound_np1[k]) - (dptr_v_plane(k)/dptr_r_plane(k));
586  nudge_v *= tau_inv;
587  ymom_src_arr(i, j, k) += cell_data(i, j, k, nr) * nudge_v;
588  });
589  }
590 
591  // *****************************************************************************
592  // 6. Add NUMERICAL DIFFUSION terms
593  // *****************************************************************************
594 #if 0
595  if (l_use_ndiff) {
596  const Array4<const Real>& mf_ux = mapfac[MapFac::ux]->const_array(mfi);
597  const Array4<const Real>& mf_uy = mapfac[MapFac::uy]->const_array(mfi);
598  const Array4<const Real>& mf_vx = mapfac[MapFac::vx]->const_array(mfi);
599  const Array4<const Real>& mf_vy = mapfac[MapFac::vy]->const_array(mfi);
600  NumericalDiffusion_Xmom(tbx, dt, solverChoice.num_diff_coeff,
601  u, cell_data, xmom_src_arr, mf_ux, mf_uy);
602  NumericalDiffusion_Ymom(tby, dt, solverChoice.num_diff_coeff,
603  v, cell_data, ymom_src_arr, mf_vx, mf_vy);
604  }
605 #endif
606 
607  // *****************************************************************************
608  // 7. Add SPONGING
609  // *****************************************************************************
610  if (is_slow_step) {
611  if (solverChoice.spongeChoice.sponge_type == "input_sponge")
612  {
613  ApplySpongeZoneBCsForMom_ReadFromFile(solverChoice.spongeChoice, geom, tbx, tby, cell_data,
614  z_cc_arr, xmom_src_arr, ymom_src_arr,
615  rho_u, rho_v, d_sponge_ptrs_at_lev);
616  }
617  else
618  {
619  ApplySpongeZoneBCsForMom(solverChoice.spongeChoice, geom, tbx, tby, tbz,
620  xmom_src_arr, ymom_src_arr, zmom_src_arr, rho_u, rho_v, rho_w,
621  r0, z_nd_arr, z_cc_arr);
622  }
623 
624  if(solverChoice.init_type == InitType::HindCast and solverChoice.hindcast_lateral_forcing){
625 
626  const Array4<const Real>& rho_u_forecast_state = (*forecast_state_at_lev)[IntVars::xmom].array(mfi);
627  const Array4<const Real>& rho_v_forecast_state = (*forecast_state_at_lev)[IntVars::ymom].array(mfi);
628  const Array4<const Real>& rho_w_forecast_state = (*forecast_state_at_lev)[IntVars::zmom].array(mfi);
629  const Array4<const Real>& cons_forecast_state = (*forecast_state_at_lev)[IntVars::cons].array(mfi);
630  ApplyBndryForcing_Forecast(solverChoice, geom, tbx, tby, tbz, z_nd_arr,
631  xmom_src_arr, ymom_src_arr, zmom_src_arr,
632  rho_u, rho_v, rho_w,
633  rho_u_forecast_state, rho_v_forecast_state, rho_w_forecast_state,
634  cons_forecast_state);
635  }
636  }
637 
638  // *****************************************************************************
639  // 8. Add CANOPY source terms
640  // *****************************************************************************
641  if (solverChoice.do_forest_drag &&
642  ((is_slow_step && !use_canopy_fast) || (!is_slow_step && use_canopy_fast))) {
643  ParallelFor(tbx, tby, tbz,
644  [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
645  {
646  const Real ux = u(i, j, k);
647  const Real uy = 0.25 * ( v(i, j , k ) + v(i-1, j , k )
648  + v(i, j+1, k ) + v(i-1, j+1, k ) );
649  const Real uz = 0.25 * ( w(i, j , k ) + w(i-1, j , k )
650  + w(i, j , k+1) + w(i-1, j , k+1) );
651  const Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
652  const Real f_drag = 0.5 * (f_drag_arr(i, j, k) + f_drag_arr(i-1, j, k));
653  xmom_src_arr(i, j, k) -= f_drag * ux * windspeed;
654  },
655  [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
656  {
657  const Real ux = 0.25 * ( u(i , j , k ) + u(i , j-1, k )
658  + u(i+1, j , k ) + u(i+1, j-1, k ) );
659  const Real uy = v(i, j, k);
660  const Real uz = 0.25 * ( w(i , j , k ) + w(i , j-1, k )
661  + w(i , j , k+1) + w(i , j-1, k+1) );
662  const amrex::Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
663  const Real f_drag = 0.5 * (f_drag_arr(i, j, k) + f_drag_arr(i, j-1, k));
664  ymom_src_arr(i, j, k) -= f_drag * uy * windspeed;
665  },
666  [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
667  {
668  const amrex::Real ux = 0.25 * ( u(i , j , k ) + u(i+1, j , k )
669  + u(i , j , k-1) + u(i+1, j , k-1) );
670  const amrex::Real uy = 0.25 * ( v(i , j , k ) + v(i , j+1, k )
671  + v(i , j , k-1) + v(i , j+1, k-1) );
672  const amrex::Real uz = w(i, j, k);
673  const amrex::Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
674  const Real f_drag = 0.5 * (f_drag_arr(i, j, k) + f_drag_arr(i, j, k-1));
675  zmom_src_arr(i, j, k) -= f_drag * uz * windspeed;
676  });
677  }
678  // *****************************************************************************
679  // 9. Add Immersed source terms
680  // *****************************************************************************
681  if (solverChoice.terrain_type == TerrainType::ImmersedForcing &&
682  ((is_slow_step && !use_ImmersedForcing_fast) || (!is_slow_step && use_ImmersedForcing_fast))) {
683  const Real drag_coefficient=10.0/dz;
685  ParallelFor(tbx, tby, tbz,
686  [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
687  {
688  const Real ux = u(i, j, k);
689  const Real uy = 0.25 * ( v(i, j , k ) + v(i-1, j , k )
690  + v(i, j+1, k ) + v(i-1, j+1, k ) );
691  const Real uz = 0.25 * ( w(i, j , k ) + w(i-1, j , k )
692  + w(i, j , k+1) + w(i-1, j , k+1) );
693  const Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
694  const Real t_blank = 0.5 * (t_blank_arr(i, j, k) + t_blank_arr(i-1, j, k));
695  const Real CdM = std::min(drag_coefficient / (windspeed + tiny), 1000.0);
696  xmom_src_arr(i, j, k) -= t_blank * CdM * ux * windspeed;
697  },
698  [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
699  {
700  const Real ux = 0.25 * ( u(i , j , k ) + u(i , j-1, k )
701  + u(i+1, j , k ) + u(i+1, j-1, k ) );
702  const Real uy = v(i, j, k);
703  const Real uz = 0.25 * ( w(i , j , k ) + w(i , j-1, k )
704  + w(i , j , k+1) + w(i , j-1, k+1) );
705  const amrex::Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
706  const Real t_blank = 0.5 * (t_blank_arr(i, j, k) + t_blank_arr(i, j-1, k));
707  const Real CdM = std::min(drag_coefficient / (windspeed + tiny), 1000.0);
708  ymom_src_arr(i, j, k) -= t_blank * CdM * uy * windspeed;
709  },
710  [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
711  {
712  const amrex::Real ux = 0.25 * ( u(i , j , k ) + u(i+1, j , k )
713  + u(i , j , k-1) + u(i+1, j , k-1) );
714  const amrex::Real uy = 0.25 * ( v(i , j , k ) + v(i , j+1, k )
715  + v(i , j , k-1) + v(i , j+1, k-1) );
716  const amrex::Real uz = w(i, j, k);
717  const amrex::Real windspeed = std::sqrt(ux * ux + uy * uy + uz * uz);
718  const Real t_blank = 0.5 * (t_blank_arr(i, j, k) + t_blank_arr(i, j, k-1));
719  const Real CdM = std::min(drag_coefficient / (windspeed + tiny), 1000.0);
720  zmom_src_arr(i, j, k) -= t_blank * CdM * uz * windspeed;
721  });
722  }
723 
724  // *****************************************************************************
725  // 10. Enforce constant mass flux
726  // *****************************************************************************
727  if (is_slow_step && (enforce_massflux_x || enforce_massflux_y)) {
728  Real tau_inv = Real(1.0) / solverChoice.const_massflux_tau;
729 
730  ParallelFor(tbx, tby,
731  [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
732  xmom_src_arr(i, j, k) += tau_inv * (rhoUA_target - rhoUA);
733  },
734  [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
735  ymom_src_arr(i, j, k) += tau_inv * (rhoVA_target - rhoVA);
736  });
737  }
738  } // mfi
739 }
void ApplyBndryForcing_Forecast(const SolverChoice &solverChoice, const Geometry geom, const Box &tbx, const Box &tby, const Box &tbz, const Array4< const Real > &z_phys_nd, const Array4< Real > &rho_u_rhs, const Array4< Real > &rho_v_rhs, const Array4< Real > &rho_w_rhs, const Array4< const Real > &rho_u, const Array4< const Real > &rho_v, const Array4< const Real > &rho_w, const Array4< const Real > &rho_u_initial_state, const Array4< const Real > &rho_v_initial_state, const Array4< const Real > &rho_w_initial_state, const Array4< const Real > &cons_initial_state)
Definition: ERF_ApplyBndryForcing_Forecast.cpp:8
void ApplySpongeZoneBCsForMom(const SpongeChoice &spongeChoice, const Geometry geom, const Box &tbx, const Box &tby, const Box &tbz, const Array4< Real > &rho_u_rhs, const Array4< Real > &rho_v_rhs, const Array4< Real > &rho_w_rhs, const Array4< const Real > &rho_u, const Array4< const Real > &rho_v, const Array4< const Real > &rho_w, const Array4< const Real > &r0, const Array4< const Real > &z_phys_nd, const Array4< const Real > &z_phys_cc)
Definition: ERF_ApplySpongeZoneBCs.cpp:118
void ApplySpongeZoneBCsForMom_ReadFromFile(const SpongeChoice &spongeChoice, const Geometry geom, const Box &tbx, const Box &tby, const Array4< const Real > &cell_data, const Array4< const Real > &z_phys_cc, const Array4< Real > &rho_u_rhs, const Array4< Real > &rho_v_rhs, const Array4< const Real > &rho_u, const Array4< const Real > &rho_v, const Vector< Real * > d_sponge_ptrs_at_lev)
Definition: ERF_ApplySpongeZoneBCs_ReadFromFile.cpp:8
constexpr amrex::Real PI
Definition: ERF_Constants.H:6
constexpr amrex::Real PIoTwo
Definition: ERF_Constants.H:7
@ ubar
Definition: ERF_DataStruct.H:91
@ wbar
Definition: ERF_DataStruct.H:91
@ vbar
Definition: ERF_DataStruct.H:91
DirectionSelector< 2 > ZDir
Definition: ERF_DirectionSelector.H:38
#define Rho_comp
Definition: ERF_IndexDefines.H:36
void NumericalDiffusion_Ymom(const Box &bx, const Real dt, const Real num_diff_coeff, const Array4< const Real > &prim_data, const Array4< const Real > &cell_data, const Array4< Real > &rhs, const Array4< const Real > &mfx_arr, const Array4< const Real > &mfy_arr)
Definition: ERF_NumericalDiffusion.cpp:151
void NumericalDiffusion_Xmom(const Box &bx, const Real dt, const Real num_diff_coeff, const Array4< const Real > &prim_data, const Array4< const Real > &cell_data, const Array4< Real > &rhs, const Array4< const Real > &mfx_arr, const Array4< const Real > &mfy_arr)
Definition: ERF_NumericalDiffusion.cpp:85
AMREX_FORCE_INLINE IntVect offset(const int face_dir, const int normal)
Definition: ERF_ReadBndryPlanes.cpp:28
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_PlaneAverage.H:14
@ r0_comp
Definition: ERF_IndexDefines.H:63
@ ymom
Definition: ERF_IndexDefines.H:160
@ cons
Definition: ERF_IndexDefines.H:158
@ zmom
Definition: ERF_IndexDefines.H:161
@ xmom
Definition: ERF_IndexDefines.H:159
@ nr
Definition: ERF_Morrison.H:45
@ xvel
Definition: ERF_IndexDefines.H:141
@ cons
Definition: ERF_IndexDefines.H:140
@ yvel
Definition: ERF_IndexDefines.H:142
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > V_inp_sound_d
Definition: ERF_InputSoundingData.H:410
amrex::Vector< amrex::Real > input_sounding_time
Definition: ERF_InputSoundingData.H:397
amrex::Real tau_nudging
Definition: ERF_InputSoundingData.H:394
amrex::Vector< amrex::Gpu::DeviceVector< amrex::Real > > U_inp_sound_d
Definition: ERF_InputSoundingData.H:410
amrex::Real coriolis_factor
Definition: ERF_DataStruct.H:876
static MeshType mesh_type
Definition: ERF_DataStruct.H:815
bool rayleigh_damp_V
Definition: ERF_DataStruct.H:848
bool rayleigh_damp_substep
Definition: ERF_DataStruct.H:854
amrex::Real rayleigh_zdamp
Definition: ERF_DataStruct.H:852
amrex::Real const_massflux_v
Definition: ERF_DataStruct.H:946
amrex::Real cosphi
Definition: ERF_DataStruct.H:877
amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > abl_geo_forcing
Definition: ERF_DataStruct.H:919
bool hindcast_lateral_forcing
Definition: ERF_DataStruct.H:954
int massflux_klo
Definition: ERF_DataStruct.H:950
bool custom_w_subsidence
Definition: ERF_DataStruct.H:883
bool nudging_from_input_sounding
Definition: ERF_DataStruct.H:889
bool rayleigh_damp_U
Definition: ERF_DataStruct.H:847
amrex::Real rayleigh_ztop
Definition: ERF_DataStruct.H:853
bool immersed_forcing_substep
Definition: ERF_DataStruct.H:857
amrex::Real sinphi
Definition: ERF_DataStruct.H:878
bool have_geo_wind_profile
Definition: ERF_DataStruct.H:921
amrex::Real const_massflux_u
Definition: ERF_DataStruct.H:945
bool use_coriolis
Definition: ERF_DataStruct.H:844
amrex::Real num_diff_coeff
Definition: ERF_DataStruct.H:905
bool variable_coriolis
Definition: ERF_DataStruct.H:924
bool custom_forcing_prim_vars
Definition: ERF_DataStruct.H:885
static TerrainType terrain_type
Definition: ERF_DataStruct.H:806
bool rayleigh_damp_W
Definition: ERF_DataStruct.H:849
SpongeChoice spongeChoice
Definition: ERF_DataStruct.H:825
static InitType init_type
Definition: ERF_DataStruct.H:800
bool has_lat_lon
Definition: ERF_DataStruct.H:923
bool do_forest_drag
Definition: ERF_DataStruct.H:942
amrex::Real const_massflux_tau
Definition: ERF_DataStruct.H:947
int massflux_khi
Definition: ERF_DataStruct.H:951
bool forest_substep
Definition: ERF_DataStruct.H:858
amrex::Real rayleigh_dampcoef
Definition: ERF_DataStruct.H:851
int ave_plane
Definition: ERF_DataStruct.H:926
std::string sponge_type
Definition: ERF_SpongeStruct.H:58
Here is the call graph for this function: