ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_Utils.cpp File Reference
#include "ERF_Utils.H"
#include <AMReX_iMultiFab.H>
#include <AMReX_MultiFabUtil.H>
#include <AMReX_Reduce.H>
Include dependency graph for ERF_Utils.cpp:

Functions

void cons_to_prim (const MultiFab &cons_state, MultiFab &S_prim, int ng)
 
void fill_wall_dist_ghost_cells (MultiFab &wdist, const Geometry &geom)
 
void make_qt (const MultiFab &cons_state, MultiFab &qt, int n_qstate_into_total)
 
void if_average_down (const MultiFab &S_fine, MultiFab &S_crse, const MultiFab &beta_fine, const MultiFab &beta_crse, const MultiFab &vol_fine, int scomp, int ncomp, const IntVect &ratio)
 
std::pair< int, Real > if_cf_surface_mismatch (const MultiFab &fine_tb, const BoxArray &fine_grids, const BoxArray &crse_grids, const DistributionMapping &crse_dmap, const Geometry &crse_geom, const IntVect &ratio, Real warn)
 
void immersed_wall_dist (MultiFab &wdist, const MultiFab &terrain_blank, const MultiFab &z_phys_nd, const MultiFab &z_phys_cc, const Box &domain, Real small_volfrac, MultiFab *wall_height, const MultiFab *wall_height_crse)
 
void make_ib_wall_face_masks (const MultiFab &terrain_blank, MultiFab &mask13, MultiFab &mask23, MultiFab &mask33, const Box &domain, Real small_volfrac, int spacing, Real dz, Real z0)
 

Function Documentation

◆ cons_to_prim()

void cons_to_prim ( const MultiFab &  cons_state,
MultiFab &  S_prim,
int  ng 
)

Convert conservative variables to primitive variables.

Parameters
[in]cons_stateMultiFab containing conservative state variables
[out]S_primMultiFab to be filled with primitive state variables
[in]ngNumber of ghost cells
18 {
19  BL_PROFILE("cons_to_prim()");
20 
21  int ncomp_prim = S_prim.nComp();
22 
23 #ifdef _OPENMP
24 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
25 #endif
26  for (MFIter mfi(cons_state,TilingIfNotGPU()); mfi.isValid(); ++mfi)
27  {
28  const Box& gbx = mfi.growntilebox(ng);
29  const Array4<const Real>& cons_arr = cons_state.array(mfi);
30  const Array4< Real>& prim_arr = S_prim.array(mfi);
31 
32  //
33  // We may need > one ghost cells of prim in order to compute higher order advective terms
34  //
35  amrex::ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
36  {
37  Real rho = cons_arr(i,j,k,Rho_comp);
38  Real rho_theta = cons_arr(i,j,k,RhoTheta_comp);
39  prim_arr(i,j,k,PrimTheta_comp) = rho_theta / rho;
40  for (int n = 1; n < ncomp_prim; ++n) {
41  prim_arr(i,j,k,PrimTheta_comp + n) = cons_arr(i,j,k,RhoTheta_comp + n) / rho;
42  }
43  });
44  } // mfi
45 }
#define Rho_comp
Definition: ERF_IndexDefines.H:53
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:54
#define PrimTheta_comp
Definition: ERF_IndexDefines.H:79
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ rho
Definition: ERF_Kessler.H:25
@ ng
Definition: ERF_Morrison.H:51

Referenced by ERF::advance_dycore(), ERF::compute_max_buoyancy_gradp_diagnostic(), and ERF::FillPlot3DVars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fill_wall_dist_ghost_cells()

void fill_wall_dist_ghost_cells ( MultiFab &  wdist,
const Geometry &  geom 
)

Fill the ghost cells of the wall distance field.

The wall distance is only computed on the valid region of each box (whether from the analytic shortcuts, the Poisson solve, or the thin-body correction), so without this the ghost cells still hold the large sentinel value they were initialized with. Any operator that reads wall distance from a grown box – e.g. the RANS Dirichlet-k boundary condition in SurfaceLayer::update_fluxes – would then propagate that sentinel into the state.

Ghost cells shared with a neighboring box or across a periodic boundary are filled by FillBoundary; ghost cells outside the domain in a non-periodic direction are filled by zero-order extrapolation. Note that the analytic wall distances vary only with k, so the extrapolation is exact in those cases.

Parameters
[in,out]wdistMultiFab holding the wall distance
[in]geomGeometry at this level
69 {
70  BL_PROFILE("fill_wall_dist_ghost_cells()");
71 
72  wdist.FillBoundary(geom.periodicity());
73 
74  const Box& domain = geom.Domain();
75  const auto dom_lo = amrex::lbound(domain);
76  const auto dom_hi = amrex::ubound(domain);
77 
78  const GpuArray<int,AMREX_SPACEDIM> is_per = {AMREX_D_DECL(geom.isPeriodic(0),
79  geom.isPeriodic(1),
80  geom.isPeriodic(2))};
81 
82  for (MFIter mfi(wdist); mfi.isValid(); ++mfi)
83  {
84  const Box& gbx = mfi.fabbox();
85  const Array4<Real>& d_arr = wdist.array(mfi);
86 
87  //
88  // Note that the cells we read from are always inside the domain in
89  // every non-periodic direction, hence already filled, and are disjoint
90  // from the cells we write to.
91  //
92  ParallelFor(gbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
93  {
94  const int ii = (is_per[0]) ? i : amrex::min(amrex::max(i,dom_lo.x),dom_hi.x);
95  const int jj = (is_per[1]) ? j : amrex::min(amrex::max(j,dom_lo.y),dom_hi.y);
96  const int kk = (is_per[2]) ? k : amrex::min(amrex::max(k,dom_lo.z),dom_hi.z);
97  if (ii != i || jj != j || kk != k) {
98  d_arr(i,j,k) = d_arr(ii,jj,kk);
99  }
100  });
101  } // mfi
102 }

Referenced by ERF::make_wall_dist(), and ERF::poisson_wall_dist().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ if_average_down()

void if_average_down ( const MultiFab &  S_fine,
MultiFab &  S_crse,
const MultiFab &  beta_fine,
const MultiFab &  beta_crse,
const MultiFab &  vol_fine,
int  scomp,
int  ncomp,
const IntVect &  ratio 
)

Fluid-mass-weighted average down over immersed-forcing levels (see ERF_Utils.H).

134 {
135  BL_PROFILE("if_average_down()");
136  AMREX_ALWAYS_ASSERT(S_fine.is_cell_centered() && S_crse.is_cell_centered());
137  AMREX_ALWAYS_ASSERT(scomp >= 0 && ncomp > 0 && scomp + ncomp <= S_crse.nComp());
138  AMREX_ALWAYS_ASSERT(S_fine.boxArray().coarsenable(ratio));
139  AMREX_ALWAYS_ASSERT(beta_fine.boxArray() == S_fine.boxArray() && vol_fine.boxArray() == S_fine.boxArray());
140  AMREX_ALWAYS_ASSERT(beta_fine.DistributionMap() == S_fine.DistributionMap() &&
141  vol_fine.DistributionMap() == S_fine.DistributionMap());
142  AMREX_ALWAYS_ASSERT(beta_crse.boxArray() == S_crse.boxArray() &&
143  beta_crse.DistributionMap() == S_crse.DistributionMap());
144 
145  // Per coarse cell, on the coarsened fine layout: the fluid-mass-weighted sums of the
146  // components, the fluid volume and the fluid mass
147  BoxArray cba = S_fine.boxArray(); cba.coarsen(ratio);
148  const int nsum = ncomp + 2;
149  MultiFab csum(cba, S_fine.DistributionMap(), nsum, 0);
150  const int rx = ratio[0], ry = ratio[1], rz = ratio[2];
151 
152 #ifdef _OPENMP
153 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
154 #endif
155  for (MFIter mfi(csum, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
156  auto const c = csum.array(mfi);
157  auto const f = S_fine.const_array(mfi);
158  auto const b = beta_fine.const_array(mfi);
159  auto const v = vol_fine.const_array(mfi);
160  ParallelFor(mfi.tilebox(), [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
161  {
162  Real w = zero, wr = zero;
163  for (int n = 0; n < ncomp; ++n) { c(i,j,k,n) = zero; }
164  for (int kk = k*rz; kk < (k+1)*rz; ++kk) {
165  for (int jj = j*ry; jj < (j+1)*ry; ++jj) {
166  for (int ii = i*rx; ii < (i+1)*rx; ++ii) {
167  // fluid volume of the fine cell (prvalues: the constants are not odr-used)
168  const Real wf = (one - amrex::min(amrex::max(b(ii,jj,kk), Real(zero)), Real(one)))
169  * v(ii,jj,kk);
170  w += wf;
171  wr += wf * f(ii,jj,kk,Rho_comp);
172  for (int n = 0; n < ncomp; ++n) { c(i,j,k,n) += wf * f(ii,jj,kk,scomp+n); }
173  }}}
174  c(i,j,k,ncomp) = w;
175  c(i,j,k,ncomp+1) = wr;
176  });
177  }
178 
179  // The sums on the coarse layout: zero where the fine level does not cover the coarse level
180  MultiFab csum_c(S_crse.boxArray(), S_crse.DistributionMap(), nsum, 0);
181  csum_c.setVal(zero);
182  csum_c.ParallelCopy(csum, 0, 0, nsum);
183 
184 #ifdef _OPENMP
185 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
186 #endif
187  for (MFIter mfi(S_crse, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
188  auto const s = S_crse.array(mfi);
189  auto const c = csum_c.const_array(mfi);
190  auto const bc = beta_crse.const_array(mfi);
191  ParallelFor(mfi.tilebox(), [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
192  {
193  // uncovered coarse cells, coarse cells solid on their own level and coarse cells
194  // without a fluid fine cell under them keep their value
195  if (c(i,j,k,ncomp) > zero && c(i,j,k,ncomp+1) > zero && bc(i,j,k) < one) {
196  // the coarse density: the fluid-volume mean of the fine density when it is in
197  // the range, else the coarse cell's own
198  const Real rho_c = (scomp == Rho_comp) ? c(i,j,k,ncomp+1) / c(i,j,k,ncomp)
199  : s(i,j,k,Rho_comp);
200  const Real fac = rho_c / c(i,j,k,ncomp+1);
201  for (int n = 0; n < ncomp; ++n) {
202  s(i,j,k,scomp+n) = (scomp+n == Rho_comp) ? rho_c : fac * c(i,j,k,n);
203  }
204  }
205  });
206  }
207 }
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
Real w
Definition: ERF_Plotfile2DInterpolator.cpp:23
real(c_double), private bc
Definition: ERF_module_mp_morr_two_moment.F90:182

Referenced by ERF::AverageDownTo().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ if_cf_surface_mismatch()

std::pair<int, Real> if_cf_surface_mismatch ( const MultiFab &  fine_tb,
const BoxArray &  fine_grids,
const BoxArray &  crse_grids,
const DistributionMapping &  crse_dmap,
const Geometry &  crse_geom,
const IntVect &  ratio,
Real  warn 
)
217 {
218  const IntVect rr = ratio;
219  const iMultiFab covered = makeFineMask(crse_grids, crse_dmap, IntVect(1,1,0), fine_grids, rr,
220  crse_geom.periodicity(), 0, 1);
221 
222  // spread of the fine fractions under each coarse cell, formed on the coarsened fine layout
223  MultiFab ftmp(amrex::coarsen(fine_grids, rr), fine_tb.DistributionMap(), 1, 0);
224  const int rx = rr[0], ry = rr[1], rz = rr[2];
225  for (MFIter mfi(ftmp, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
226  auto const s = ftmp.array(mfi);
227  auto const f = fine_tb.const_array(mfi);
228  ParallelFor(mfi.tilebox(), [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
229  {
230  Real bmin = Real(one), bmax = Real(zero);
231  for (int kk = k*rz; kk < (k+1)*rz; ++kk) {
232  for (int jj = j*ry; jj < (j+1)*ry; ++jj) {
233  for (int ii = i*rx; ii < (i+1)*rx; ++ii) {
234  const Real b = amrex::min(amrex::max(f(ii,jj,kk), Real(zero)), Real(one));
235  bmin = amrex::min(bmin, b);
236  bmax = amrex::max(bmax, b);
237  }}}
238  s(i,j,k) = bmax - bmin;
239  });
240  }
241  MultiFab spread(crse_grids, crse_dmap, 1, 0);
242  spread.setVal(zero);
243  spread.ParallelCopy(ftmp, 0, 0, 1);
244 
245  const Box& dom = crse_geom.Domain();
246  const int per_x = crse_geom.isPeriodic(0), per_y = crse_geom.isPeriodic(1);
247  const int dlo_x = dom.smallEnd(0), dhi_x = dom.bigEnd(0), dlo_y = dom.smallEnd(1), dhi_y = dom.bigEnd(1);
248  ReduceOps<ReduceOpSum, ReduceOpMax> reduce_op;
249  ReduceData<int, Real> reduce_data(reduce_op);
250  using ReduceTuple = typename decltype(reduce_data)::Type;
251  for (MFIter mfi(spread, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
252  auto const m = covered.const_array(mfi);
253  auto const sp = spread.const_array(mfi);
254  reduce_op.eval(mfi.tilebox(), reduce_data, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept -> ReduceTuple
255  {
256  if (m(i,j,k) != 1) { return {0, Real(zero)}; }
257  const bool edge = ((per_x || i > dlo_x) && m(i-1,j,k) == 0) || ((per_x || i < dhi_x) && m(i+1,j,k) == 0)
258  || ((per_y || j > dlo_y) && m(i,j-1,k) == 0) || ((per_y || j < dhi_y) && m(i,j+1,k) == 0);
259  if (!edge) { return {0, Real(zero)}; }
260  return {(sp(i,j,k) >= warn) ? 1 : 0, sp(i,j,k)};
261  });
262  }
263  ReduceTuple hv = reduce_data.value(reduce_op);
264  int nflagged = amrex::get<0>(hv);
265  Real worst = amrex::get<1>(hv);
266  ParallelDescriptor::ReduceIntSum(nflagged);
267  ParallelDescriptor::ReduceRealMax(worst);
268  return {nflagged, worst};
269 }
real(c_double), private rr
Definition: ERF_module_mp_morr_two_moment.F90:224

Referenced by ERF::check_if_cf_mismatch().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ immersed_wall_dist()

void immersed_wall_dist ( MultiFab &  wdist,
const MultiFab &  terrain_blank,
const MultiFab &  z_phys_nd,
const MultiFab &  z_phys_cc,
const Box &  domain,
Real  small_volfrac,
MultiFab *  wall_height,
const MultiFab *  wall_height_crse 
)
280 {
281  BL_PROFILE("immersed_wall_dist()");
282 
283  const int klo = domain.smallEnd(2);
284  const int khi = domain.bigEnd(2);
285  const Real small = small_volfrac;
286  const Real d_floor = std::numeric_limits<Real>::epsilon();
287  const bool have_crse = (wall_height_crse != nullptr);
288 
289  for (MFIter mfi(wdist); mfi.isValid(); ++mfi)
290  {
291  const Box& bx = mfi.validbox();
292  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(have_crse || (bx.smallEnd(2) == klo && bx.bigEnd(2) == khi),
293  "immersed_wall_dist: the wall distance over immersed terrain needs whole columns in each box");
294 
295  const int kb_lo = bx.smallEnd(2);
296  const int kb_hi = bx.bigEnd(2);
297  Box bx2d = bx; bx2d.setRange(2, klo);
298  auto const tb_arr = terrain_blank.const_array(mfi);
299  auto const znd_arr = z_phys_nd.const_array(mfi);
300  auto const zcc_arr = z_phys_cc.const_array(mfi);
301  auto dist_arr = wdist.array(mfi);
302  auto const hw_arr = (wall_height) ? wall_height->array(mfi) : Array4<Real>{};
303  auto const hc_arr = (have_crse) ? wall_height_crse->const_array(mfi) : Array4<const Real>{};
304 
305  ParallelFor(bx2d, [=] AMREX_GPU_DEVICE (int i, int j, int) noexcept
306  {
307  // the height of the cell face kk, the mean of its four nodes
308  auto z_face = [=] (int kk) -> Real {
309  return fourth * ( znd_arr(i,j,kk) + znd_arr(i+1,j,kk)
310  + znd_arr(i,j+1,kk) + znd_arr(i+1,j+1,kk) );
311  };
312  // topmost cell of the box that is not fluid
313  int kt = kb_lo - 1;
314  for (int kk = kb_hi; kk >= kb_lo; --kk) {
315  if (!ib_wall::is_fluid(tb_arr(i,j,kk), small)) { kt = kk; break; }
316  }
317  // The box sees the surface of its column if it holds the whole column, if it has
318  // fluid above its top solid cell, or if it starts at the bottom and holds no solid.
319  // Otherwise (a fine box wholly inside the solid, or above the surface) the wall
320  // height comes from the coarser level.
321  const bool whole = (kb_lo == klo) && (kb_hi == khi);
322  const bool sees = whole || (kt >= kb_lo && kt < kb_hi) || (kt < kb_lo && kb_lo == klo);
323  const bool local = sees || !have_crse;
324 
325  // h: the surface height; kw: the wall cell (none below kb_lo). A local box without
326  // solid starts at the bottom (klo).
327  Real h;
328  int kw = kb_lo - 1;
329  if (!local) {
330  h = hc_arr(i,j,klo);
331  } else {
332  kw = kb_lo;
333  h = z_face(kb_lo);
334  if (kt >= kb_lo) {
335  const Real b = amrex::min(tb_arr(i,j,kt), Real(one));
336  h = z_face(kt) + b * (z_face(kt+1) - z_face(kt));
337  kw = ib_wall::is_solid(tb_arr(i,j,kt), small) ? kt + 1 : kt;
338  }
339  }
340  if (hw_arr) { hw_arr(i,j,klo) = h; }
341  for (int kk = kb_lo; kk <= kb_hi; ++kk) {
342  // the wall cell is represented by its fluid centroid
343  const Real d = (kk == kw) ? myhalf * (z_face(kk+1) - h)
344  : std::abs(zcc_arr(i,j,kk) - h);
345  dist_arr(i,j,kk) = amrex::max(d, d_floor);
346  }
347  });
348  } // mfi
349 }
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(axis >=0 &&axis< AMREX_SPACEDIM, "prob.axis must be 0, 1 or 2")
const int khi
Definition: ERF_InitCustomPert_Bubble.H:25
const int klo
Definition: ERF_InitCustomPert_KE.H:9
constexpr amrex::Real fourth
Definition: ERF_NumericalConstants.H:42
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool is_fluid(amrex::Real beta, amrex::Real small) noexcept
Definition: ERF_ImmersedWallCell.H:40
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool is_solid(amrex::Real beta, amrex::Real small) noexcept
Definition: ERF_ImmersedWallCell.H:47
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12

Referenced by ERF::poisson_wall_dist().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ make_ib_wall_face_masks()

void make_ib_wall_face_masks ( const MultiFab &  terrain_blank,
MultiFab &  mask13,
MultiFab &  mask23,
MultiFab &  mask33,
const Box &  domain,
Real  small_volfrac,
int  spacing,
Real  dz,
Real  z0 
)
377 {
378  BL_PROFILE("make_ib_wall_face_masks()");
379  // the masks are built on their ghost cells too, reading the blanking one cell sideways and two
380  // cells up and down the column (clamped to the domain in k, not to the box)
381  AMREX_ALWAYS_ASSERT(terrain_blank.nGrowVect().allGE(mask13.nGrowVect() + IntVect(1,1,2)) &&
382  terrain_blank.nGrowVect().allGE(mask23.nGrowVect() + IntVect(1,1,2)) &&
383  terrain_blank.nGrowVect().allGE(mask33.nGrowVect() + IntVect(0,0,2)));
384 
385  const int klo = domain.smallEnd(2);
386  const int khi = domain.bigEnd(2);
387  const Real small = small_volfrac;
388 
389  // the solid fraction of a face column, clamped to the domain in k, fluid below small
390  for (MFIter mfi(mask13); mfi.isValid(); ++mfi) {
391  auto const tb = terrain_blank.const_array(mfi);
392  auto const m = mask13.array(mfi);
393  ParallelFor(mfi.fabbox(), [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
394  {
395  auto b = [=] (int kk) -> Real {
396  const int kc = amrex::min(amrex::max(kk, klo), khi);
397  const Real v = myhalf * (tb(i-1,j,kc) + tb(i,j,kc));
398  return (v < small) ? zero : v;
399  };
400  m(i,j,k) = ib_wall_face_mask_value(k, klo, khi, small, dz, z0, spacing, b);
401  });
402  }
403  for (MFIter mfi(mask23); mfi.isValid(); ++mfi) {
404  auto const tb = terrain_blank.const_array(mfi);
405  auto const m = mask23.array(mfi);
406  ParallelFor(mfi.fabbox(), [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
407  {
408  auto b = [=] (int kk) -> Real {
409  const int kc = amrex::min(amrex::max(kk, klo), khi);
410  const Real v = myhalf * (tb(i,j-1,kc) + tb(i,j,kc));
411  return (v < small) ? zero : v;
412  };
413  m(i,j,k) = ib_wall_face_mask_value(k, klo, khi, small, dz, z0, spacing, b);
414  });
415  }
416  for (MFIter mfi(mask33); mfi.isValid(); ++mfi) {
417  auto const tb = terrain_blank.const_array(mfi);
418  auto const m = mask33.array(mfi);
419  ParallelFor(mfi.fabbox(), [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
420  {
421  auto b = [=] (int kk) -> Real {
422  const Real v = tb(i,j,amrex::min(amrex::max(kk, klo), khi));
423  return (v < small) ? zero : v;
424  };
425  m(i,j,k) = ib_wall_face_mask_value(k, klo, khi, small, dz, z0, spacing, b);
426  });
427  }
428 }
Real z0
Definition: ERF_InitCustomPertVels_ScalarAdvDiff.H:12
@ dz
Definition: ERF_AdvanceWDM6.cpp:273

Referenced by ERF::make_ib_wall_face_masks_lev().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ make_qt()

void make_qt ( const MultiFab &  cons_state,
MultiFab &  qt,
int  n_qstate_into_total 
)

Compute the total water mixing ratio from conservative variables.

Parameters
[in]cons_stateMultiFab containing conservative state variables
[out]qtMultiFab to store the total water mixing ratio
[in]n_qstate_into_totalNumber of moisture components to include in the total
113 {
114  BL_PROFILE("make_qt()");
115 
116  // All moisture models are guaranteed to have RhoQ1_comp.
117  MultiFab::Copy(qt, cons_state, RhoQ1_comp, 0, 1, qt.nGrowVect());
118 
119  for (int n = 1; n < n_qstate_into_total; ++n) {
120  MultiFab::Add(qt, cons_state, RhoQ1_comp+n, 0, 1, qt.nGrowVect());
121  }
122 
123  MultiFab::Divide(qt, cons_state, Rho_comp, 0, 1, qt.nGrowVect());
124 }
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:66
@ qt
Definition: ERF_Kessler.H:30

Referenced by ERF::compute_max_buoyancy_gradp_diagnostic(), ERF::compute_max_pressure_gradient_diagnostic(), and ERF::FillPlot3DVars().

Here is the caller graph for this function: