ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
Morrison Class Reference

#include <ERF_Morrison.H>

Inheritance diagram for Morrison:
Collaboration diagram for Morrison:

Public Member Functions

 Morrison ()
 
virtual ~Morrison ()=default
 
void Define (SolverChoice &sc) override
 
void Init (const amrex::MultiFab &cons_in, const amrex::BoxArray &grids, const amrex::Geometry &geom, const amrex::Real &dt_advance, std::unique_ptr< amrex::MultiFab > &z_phys_nd, std::unique_ptr< amrex::MultiFab > &detJ_cc) override
 
void Set_dzmin (const amrex::Real dz_min) override
 
void Copy_State_to_Micro (const amrex::MultiFab &cons_in) override
 
void Copy_State_to_Micro (const amrex::MultiFab &cons_in, const amrex::MultiFab *base_state)
 
void Update_Micro_Vars (amrex::MultiFab &cons_in, const amrex::MultiFab *base_state) override
 
void Copy_Micro_to_State (amrex::MultiFab &cons_in) override
 
void Update_Micro_Vars (amrex::MultiFab &cons_in) override
 
void Update_State_Vars (amrex::MultiFab &cons_in, const amrex::MultiFab &) override
 
void Advance (const amrex::Real &dt_advance, const SolverChoice &sc) override
 
amrex::MultiFab * Qmoist_Ptr (const int &varIdx) override
 
int Qmoist_Size () override
 
int Qstate_Moist_Size () override
 
int Qstate_Moist_NumConc_Size () override
 
void Qmoist_Restart_Vars (const SolverChoice &, std::vector< int > &a_idx, std::vector< std::string > &a_names) const override
 
const SedimentationFlux * Sed_Flux () const override
 The sedimentation face fluxes of the most recent Advance, or null for a scheme that does not sediment (see ERF_SedimentationFlux.H) More...
 
SurfacePrecipAccumulationSources Get_Surface_Precip_Accumulation_Ptrs (const int &) const override
 
void GetPlotVarNames (amrex::Vector< std::string > &a_vec) const override
 Populate a vector with names of all available Morrison plot variables. More...
 
void GetPlotVar (const std::string &a_name, amrex::MultiFab &a_mf) const override
 
void GetPlotVar (const std::string &a_name, amrex::MultiFab &a_mf, const int) const override
 
void AdvanceColumns (const amrex::Real &dt_advance, const SolverChoice &sc)
 
- Public Member Functions inherited from NullMoist
 NullMoist ()
 
virtual ~NullMoist ()=default
 
virtual int Qstate_NonMoist_Size ()
 
virtual void SetCurrentLevel (const int &lev)
 
virtual void InitLevel (const int, const amrex::MultiFab &)
 
virtual int getDiagnosticsInterval () const
 
virtual void Set_Lmask (amrex::iMultiFab *)
 Import ERF's land/water mask. Only schemes whose physics branches on land vs water need to override this. More...
 
virtual void Set_Sed_Inflow (const amrex::MultiFab *inflow)
 The inflow through the top of a fine patch for the next Advance, or null (see ERF_SedimentationFlux.H); the caller keeps it alive for that Advance. More...
 
virtual void Set_RealWidth (const int)
 

Private Types

using FabPtr = std::shared_ptr< amrex::MultiFab >
 

Private Attributes

int m_qmoist_size = 4
 
int n_qstate_moist_size = 11
 
int n_qstate_moist_numconc_size = 5
 
amrex::Vector< int > MicVarMap
 
amrex::Geometry m_geom
 
amrex::Real m_rdOcp {RdoCp}
 
bool m_do_cond
 
MoistureType m_moisture_type = MoistureType::None
 
amrex::Real m_dzmin {0.0}
 
amrex::MultiFab * m_z_phys_nd
 
amrex::MultiFab * m_detJ_cc
 
amrex::Array< FabPtr, MicVar_Morr::NumVars > mic_fab_vars
 
MicrophysicsColumns m_columns
 
SedimentationFlux m_sed
 

Additional Inherited Members

- Protected Member Functions inherited from NullMoist
void set_anelastic_reference_pressure_mode (const SolverChoice &sc)
 
void assert_base_state_available (const amrex::MultiFab *base_state) const
 
- Protected Attributes inherited from NullMoist
const amrex::MultiFab * m_sed_inflow = nullptr
 
int m_level {0}
 
bool m_use_anelastic_reference_pressure {false}
 

Member Typedef Documentation

◆ FabPtr

using Morrison::FabPtr = std::shared_ptr<amrex::MultiFab>
private

Constructor & Destructor Documentation

◆ Morrison()

Morrison::Morrison ( )
inline
130 {}

◆ ~Morrison()

virtual Morrison::~Morrison ( )
virtualdefault

Member Function Documentation

◆ Advance()

void Morrison::Advance ( const amrex::Real &  dt_advance,
const SolverChoice &  sc 
)
overridevirtual

Reimplemented from NullMoist.

181  {
182  m_sed.reset(dt_advance);
183 
184  if (!m_columns.needs_gather()) {
185  AdvanceColumns(dt_advance, sc);
186  return;
187  }
188 
189  // Some column is split between boxes stacked in z. Sedimentation treats each
190  // box's k range as the whole column, so run on a copy of the fields in which
191  // every column lies in one box, then copy the result back.
192  amrex::Array<FabPtr, MicVar_Morr::NumVars> saved;
193  m_columns.gather(mic_fab_vars, saved);
194  MultiFab* z_phys_nd_saved = m_z_phys_nd;
195  auto z_phys_nd_col = m_columns.gather_nodal(m_z_phys_nd);
196  m_z_phys_nd = z_phys_nd_col.get();
197  auto sed_saved = m_sed.down;
198  m_sed.down = m_columns.gather_one(*sed_saved);
199  const MultiFab* inflow_saved = m_sed_inflow;
200  auto inflow_col = (m_sed_inflow) ? m_columns.gather_one(*m_sed_inflow) : nullptr;
201  m_sed_inflow = inflow_col.get();
202 
203  AdvanceColumns(dt_advance, sc);
204 
205  m_sed_inflow = inflow_saved;
206  sed_saved->ParallelCopy(*m_sed.down);
207  m_sed.down = sed_saved;
208  m_z_phys_nd = z_phys_nd_saved;
210  }
void gather(std::array< FabPtr, N > &vars, std::array< FabPtr, N > &saved) const
Swap each non-null field for a copy on the column layout; the originals go to saved.
Definition: ERF_MicrophysicsColumns.H:48
FabPtr gather_one(const amrex::MultiFab &src) const
Copy of a field (cell-centered or z-face; with its ghost cells) on the column layout.
Definition: ERF_MicrophysicsColumns.cpp:100
void scatter(std::array< FabPtr, N > &vars, std::array< FabPtr, N > &saved) const
Copy the column-layout fields back into the originals and restore them.
Definition: ERF_MicrophysicsColumns.H:58
std::unique_ptr< amrex::MultiFab > gather_nodal(const amrex::MultiFab *src) const
Copy of a nodal field (e.g. z_phys_nd) on the column layout, or null for null input.
Definition: ERF_MicrophysicsColumns.cpp:116
bool needs_gather() const
True when some column is split between boxes, so the fields must be gathered.
Definition: ERF_MicrophysicsColumns.H:41
SedimentationFlux m_sed
Definition: ERF_Morrison.H:302
amrex::MultiFab * m_z_phys_nd
Definition: ERF_Morrison.H:292
MicrophysicsColumns m_columns
Definition: ERF_Morrison.H:299
void AdvanceColumns(const amrex::Real &dt_advance, const SolverChoice &sc)
Definition: ERF_AdvanceMorrison.cpp:213
amrex::Array< FabPtr, MicVar_Morr::NumVars > mic_fab_vars
Definition: ERF_Morrison.H:296
const amrex::MultiFab * m_sed_inflow
Definition: ERF_NullMoist.H:168
std::shared_ptr< amrex::MultiFab > down
Definition: ERF_SedimentationFlux.H:39
void reset(amrex::Real a_dt)
Zero the fluxes at the start of an Advance of length a_dt.
Definition: ERF_SedimentationFlux.H:57

◆ AdvanceColumns()

void Morrison::AdvanceColumns ( const amrex::Real &  dt_advance,
const SolverChoice &  sc 
)
215  {
216  // Expose for GPU
217  bool do_cond = m_do_cond;
218 
219  // Store timestep
220  Real dt = dt_advance;
221 
222  // Check if CPP or FORT answer is used
223  ParmParse pp("erf");
224  bool use_morr_cpp_answer = true;
225  pp.queryAdd("use_morr_cpp_answer", use_morr_cpp_answer);
226 #ifndef ERF_USE_MORR_FORT
227  // Without the Fortran bridge, false would skip the microphysics update entirely
228  if (!use_morr_cpp_answer) {
229  Abort("erf.use_morr_cpp_answer = false requires the Morrison Fortran bridge "
230  "(USE_MORR_FORT=TRUE or ERF_ENABLE_MORR_FORT=ON)");
231  }
232 #endif
233 
234  // Ensure that only one of these is true
235  bool run_morr_cpp = use_morr_cpp_answer;
236  bool run_morr_fort = !run_morr_cpp;
237 
238  // The Fortran bridge takes each box's k range as the whole column (the box top
239  // as the model top, its bottom as the ground), so it needs boxes that do span it.
241  "Morrison: erf.use_morr_cpp_answer = false requires every box to span the domain in z "
242  "(no grids split in z, and no refined levels short of the domain top or bottom)");
243 
244  // Only a column standing on the domain bottom has a ground to accumulate precipitation on
245  const int dom_klo = m_geom.Domain().smallEnd(2);
246 
247  std::string filename = std::string("output_cpp") + std::to_string(use_morr_cpp_answer) + ".txt";
248 
249  // Allow user to override constant droplet concentration from inputs file
250  // Constant droplet concentration (if INUM = 1)
251  Real m_ndcnst = Real(250.0); // Droplet number concentration (cm^-3)
252  pp.queryAdd("morrison_ndcnst", m_ndcnst);
253 
254  // Loop through the grids
255  //
256  // The Fortran bridge is a whole-FAB interface: it declares every array over the fab
257  // box and would stage a full-FAB copy of ~14 scratch arrays per tile. Iterate one
258  // box at a time on that path.
259  //
260  const IntVect morr_tile_size = run_morr_fort ? IntVect::TheZeroVector() : TileNoZ();
261  for (MFIter mfi(*mic_fab_vars[MicVar_Morr::qcl],morr_tile_size); mfi.isValid(); ++mfi)
262  {
263  auto box = mfi.tilebox();
264 
265  if (!box.ok()) { // Avoid going farther if the box is inverted (i.e., ilo > ihi or jlo > jhi).
266  continue;
267  }
268 
269  // Get array data from class member variables
270  auto const& theta_arr = mic_fab_vars[MicVar_Morr::theta]->array(mfi);
271 
272  auto const& qv_arr = mic_fab_vars[MicVar_Morr::qv]->array(mfi);
273 
274  auto const& qcl_arr = mic_fab_vars[MicVar_Morr::qcl]->array(mfi);
275  auto const& qpr_arr = mic_fab_vars[MicVar_Morr::qpr]->array(mfi);
276  auto const& qci_arr = mic_fab_vars[MicVar_Morr::qci]->array(mfi);
277  auto const& qps_arr = mic_fab_vars[MicVar_Morr::qps]->array(mfi);
278  auto const& qpg_arr = mic_fab_vars[MicVar_Morr::qpg]->array(mfi);
279 
280  auto const& nc_arr = mic_fab_vars[MicVar_Morr::nc]->array(mfi);
281  auto const& ni_arr = mic_fab_vars[MicVar_Morr::ni]->array(mfi);
282  auto const& nr_arr = mic_fab_vars[MicVar_Morr::nr]->array(mfi);
283  auto const& ns_arr = mic_fab_vars[MicVar_Morr::ns]->array(mfi);
284  auto const& ng_arr = mic_fab_vars[MicVar_Morr::ng]->array(mfi);
285 
286  auto const& rho_arr = mic_fab_vars[MicVar_Morr::rho]->array(mfi);
287  auto const& pres_arr = mic_fab_vars[MicVar_Morr::pres]->array(mfi);
288  auto const& rain_accum_arr = mic_fab_vars[MicVar_Morr::rain_accum]->array(mfi);
289  auto const& snow_accum_arr = mic_fab_vars[MicVar_Morr::snow_accum]->array(mfi);
290  auto const& graupel_accum_arr = mic_fab_vars[MicVar_Morr::graupel_accum]->array(mfi);
291  auto const& precip_accum_arr = mic_fab_vars[MicVar_Morr::precip_accum]->array(mfi);
292  auto const& w_arr = mic_fab_vars[MicVar_Morr::omega]->array(mfi);
293  auto const& sed_arr = m_sed.down->array(mfi);
294  const auto inflow_arr = (m_sed_inflow) ? m_sed_inflow->const_array(mfi)
295  : Array4<const Real>{};
296 
297  // Get radar reflectivity array if radar diagnostics enabled
298  // auto const& refl_arr = m_do_radar_ref ? m_radar->array(mfi) : nullptr;
299  // auto const& refl_arr = m_radar->array(mfi);
300 
301  // Extract box dimensions
302  const int ilo = box.loVect()[0];
303  const int ihi = box.hiVect()[0];
304  const int jlo = box.loVect()[1];
305  const int jhi = box.hiVect()[1];
306  const int klo = box.loVect()[2];
307  const int khi = box.hiVect()[2];
308 
309  Box grown_box(box); grown_box.grow(3);
310 
311  // Every array handed to the Fortran bridge -- both the mic_fab_vars and the staging
312  // FABs below -- is declared there as DIMENSION(ims:ime,jms:jme,kms:kme), and those
313  // bounds are taken from mfi.fabbox(). So the staging FABs must be allocated on the
314  // fab box too; sizing them from a tilebox grown by a hard-coded 3 mis-declares the
315  // strides whenever ngrow_state != 3 or the MFIter tiles the box.
316  // Note fab_box always contains grown_box (ComputeGhostCells() >= 2, so the state
317  // carries at least 3 ghost cells), so this only ever widens the staged region.
318  const Box& fab_box = mfi.fabbox();
319 
320 #if defined(ERF_USE_MORR_FORT) && defined(AMREX_USE_GPU)
321  Arena* Arena_Used = The_Pinned_Arena();
322 #else
323  Arena* Arena_Used = The_Async_Arena();
324 #endif
325 
326  // Calculate Exner function (PII) to convert potential temperature to temperature
327  // PII = (P/P0)^(R/cp)
328  FArrayBox pii_fab(fab_box, 1, Arena_Used);
329  auto const& pii_arr = pii_fab.array();
330 
331  const Real p0 = Real(100000.0); // Reference pressure (Pa)
332 
333  const Real rdcp = m_rdOcp; // R/cp ratio
334 
335  // Calculate Exner function
336  ParallelFor(fab_box, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
337  // NOTE: the Morrison Fortran version uses Pa not hPa so we didn't divide p by 100
338  // so we don't need to multiply by 100 here
339  pii_arr(i,j,k) = std::pow((pres_arr(i,j,k)) / p0, rdcp);
340  });
341 
342  // Create arrays for height differences (dz)
343  FArrayBox dz_fab(fab_box, 1, Arena_Used);
344  auto const& dz_arr = dz_fab.array();
345 
346  // Calculate height differences
347  const Real dz_val = m_geom.CellSize(2);
348  const Array4<const Real> z_arr = (m_z_phys_nd) ? m_z_phys_nd->const_array(mfi) : Array4<const Real> {};
349  // z_phys_nd carries ComputeGhostCells()+2 ghost nodes, i.e. one more than the state,
350  // so the (i+1,j+1,k+1) reads stay in bounds over the whole fab box.
351  ParallelFor(fab_box, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
352  dz_arr(i,j,k) = (z_arr) ? Real(0.25) * ( (z_arr(i ,j ,k+1) - z_arr(i ,j ,k))
353  + (z_arr(i+1,j ,k+1) - z_arr(i+1,j ,k))
354  + (z_arr(i ,j+1,k+1) - z_arr(i ,j+1,k))
355  + (z_arr(i+1,j+1,k+1) - z_arr(i+1,j+1,k)) ) : dz_val;
356  });
357 
358  // The 2D Fortran arrays are declared DIMENSION(ims:ime,jms:jme), so this slab must
359  // carry the fab box extents in x and y.
360  Box fab_boxD(fab_box); fab_boxD.makeSlab(2,0);
361 
362  // Arrays to store precipitation rates
363  FArrayBox rainncv_fab(fab_boxD, 1, Arena_Used);
364  FArrayBox sr_fab(fab_boxD, 1, Arena_Used); // Ratio of snow to total precipitation
365  FArrayBox snowncv_fab(fab_boxD, 1, Arena_Used);
366  FArrayBox graupelncv_fab(fab_boxD, 1, Arena_Used);
367 
368  auto const& rainncv_arr = rainncv_fab.array();
369  auto const& sr_arr = sr_fab.array();
370  auto const& snowncv_arr = snowncv_fab.array();
371  auto const& graupelncv_arr = graupelncv_fab.array();
372 
373  // Initialize precipitation rate arrays to Real(0)
374  ParallelFor(fab_boxD, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
375  rainncv_arr(i,j,k) = Real(0);
376  sr_arr(i,j,k) = Real(0);
377  snowncv_arr(i,j,k) = Real(0);
378  graupelncv_arr(i,j,k) = Real(0);
379  });
380 
381  // Create terrain height array (not actually used by Morrison scheme)
382  FArrayBox ht_fab(Box(IntVect(ilo, jlo, 0), IntVect(ihi, jhi, 0)), 1, Arena_Used);
383  [[maybe_unused]] auto const& ht_arr = ht_fab.array();
384  // ParallelFor(Box(IntVect(ilo, jlo, 0), IntVect(ihi, jhi, 0)), [=] AMREX_GPU_DEVICE (int i, int j, int k) {
385  // ht_arr(i,j,k) = (z_arr) ? Real(0.25) * ( z_arr(i ,j ,k) + z_arr(i+1,j ,k)
386  // + z_arr(i ,j+1,k) + z_arr(i+1,j+1,k) ) : Real(0.); // Not used by Morrison scheme
387  //});
388 
389  // Microphysics options/switches
390  int m_iact = 2; // CCN activation option (1:std::power-law, 2: lognormal aerosol)
391  int m_inum = 1; // Droplet number option (0: predict, 1: constant)
392 
393  int m_iliq = 0; // Liquid-only option (0: include ice, 1: liquid only)
394  int m_inuc = 0; // Ice nucleation option (0: mid-latitude, 1: arctic)
395  // int m_ibase = 2; // Cloud base activation option
396  // int m_isub = 0; // Sub-grid vertical velocity option
397  int m_igraup = 0; // Graupel option (0: include graupel, 1: no graupel)
398  int m_ihail = 0; // Graupel/hail option (0: graupel, 1: hail)
399 
400  if(sc.moisture_type == MoistureType::Morrison_NoIce) {
401  m_iliq = 1; // Liquid-only option (0: include ice, 1: liquid only)
402  m_inuc = 0; // Ice nucleation option (0: mid-latitude, 1: arctic)
403  // m_ibase = 2; // Cloud base activation option
404  // m_isub = 0; // Sub-grid vertical velocity option
405  m_igraup = 1; // Graupel option (0: include graupel, 1: no graupel)
406  m_ihail = 0; // Graupel/hail option (0: graupel, 1: hail)
407  }
408  // bool m_do_radar_ref = false; // Radar reflectivity calculation flag
409 
410  // Physical constants
411  Real m_pi; // Pi constant
412  Real m_R; // Gas constant for dry air (J/kg/K)
413  Real m_Rd; // Gas constant for dry air (J/kg/K)
414  Real m_Rv; // Gas constant for water vapor (J/kg/K)
415  // Real m_cp; // Specific heat at constant pressure (J/kg/K)
416  Real m_g; // Gravitational acceleration (m/s^2)
417  Real m_ep_2; // Molecular weight ratio (Rd/Rv)
418 
419  // Reference density and species densities
420  Real m_rhosu; // Standard air density at 850 mb (kg/m^3)
421  Real m_rhow; // Density of liquid water (kg/m^3)
422  Real m_rhoi; // Bulk density of cloud ice (kg/m^3)
423  Real m_rhosn; // Bulk density of snow (kg/m^3)
424  Real m_rhog; // Bulk density of graupel/hail (kg/m^3)
425 
426  // Fall speed parameters (V=AD^B)
427  Real m_ai, m_bi; // Cloud ice fall speed parameters
428  // Real m_ac; // Cloud droplet fall speed parameters
429  Real m_bc; // Cloud droplet fall speed parameters
430  Real m_as, m_bs; // Snow fall speed parameters
431  Real m_ar, m_br; // Rain fall speed parameters
432  Real m_ag, m_bg; // Graupel/hail fall speed parameters
433 
434  // Microphysical parameters
435  Real m_aimm; // Parameter in Bigg immersion freezing
436  Real m_bimm; // Parameter in Bigg immersion freezing
437  Real m_ecr; // Collection efficiency between droplets/rain and snow/rain
438  Real m_dcs; // Threshold size for cloud ice autoconversion (m)
439  Real m_mi0; // Initial mass of nucleated ice crystal (kg)
440  Real m_mg0; // Mass of embryo graupel (kg)
441  Real m_f1s; // Ventilation parameter for snow
442  Real m_f2s; // Ventilation parameter for snow
443  Real m_f1r; // Ventilation parameter for rain
444  Real m_f2r; // Ventilation parameter for rain
445  Real m_qsmall; // Smallest allowed hydrometeor mixing ratio
446  Real m_eii; // Collection efficiency, ice-ice collisions
447  Real m_eci; // Collection efficiency, ice-droplet collisions
448  Real m_cpw; // Specific heat of liquid water (J/kg/K)
449  Real m_rin; // Radius of contact nuclei (m)
450  Real m_mmult; // Mass of splintered ice particle (kg)
451 
452  // Size distribution parameters
453  Real m_ci, m_di; // Cloud ice size distribution parameters
454  Real m_cs, m_ds; // Snow size distribution parameters
455  Real m_cg, m_dg; // Graupel size distribution parameters
456 
457  // Lambda limits for size distributions
458  Real m_lammaxi, m_lammini; // Cloud ice lambda limits
459  Real m_lammaxr, m_lamminr; // Rain lambda limits
460  Real m_lammaxs, m_lammins; // Snow lambda limits
461  Real m_lammaxg, m_lamming; // Graupel lambda limits
462 
463  // CCN spectra parameters (for IACT = 1)
464  // Real m_k1; // Exponent in CCN activation formula
465  // Real m_c1; // Coefficient in CCN activation formula (cm^-3)
466 
467  // Aerosol activation parameters (for IACT = 2)
468  // Real m_mw; // Molecular weight water (kg/mol)
469  // Real m_osm; // Osmotic coefficient
470  // Real m_vi; // Number of ions dissociated in solution
471  // Real m_epsm; // Aerosol soluble fraction
472  // Real m_rhoa; // Aerosol bulk density (kg/m^3)
473  // Real m_map; // Molecular weight aerosol (kg/mol)
474  // Real m_ma; // Molecular weight of air (kg/mol)
475  // Real m_rr; // Universal gas constant (J/mol/K)
476  // Real m_bact; // Activation parameter
477  // Real m_rm1; // Geometric mean radius, mode 1 (m)
478  // Real m_rm2; // Geometric mean radius, mode 2 (m)
479  Real m_nanew1; // Total aerosol concentration, mode 1 (m^-3)
480  Real m_nanew2; // Total aerosol concentration, mode 2 (m^-3)
481  // Real m_sig1; // Standard deviation of aerosol dist, mode 1
482  // Real m_sig2; // Standard deviation of aerosol dist, mode 2
483  // Real m_f11; // Correction factor for activation, mode 1
484  // Real m_f12; // Correction factor for activation, mode 1
485  // Real m_f21; // Correction factor for activation, mode 2
486  // Real m_f22; // Correction factor for activation, mode 2
487 
488  // Precomputed constants for efficiency
489  Real m_cons1, m_cons2, m_cons3, m_cons4, m_cons5;
490  Real m_cons6, m_cons7, m_cons8, m_cons9, m_cons10;
491  Real m_cons11, m_cons12, m_cons13, m_cons14, m_cons15;
492  Real m_cons16, m_cons17, m_cons18, m_cons19, m_cons20;
493  Real m_cons21, m_cons22, m_cons23, m_cons24, m_cons25;
494  Real m_cons26, m_cons27, m_cons28, m_cons29;
495  Real m_cons31, m_cons32, m_cons34, m_cons35;
496  Real m_cons36, m_cons37, m_cons38, m_cons39, m_cons40;
497  Real m_cons41;
498 
499  // Set microphysics control parameters
500  m_inum = 1; // Use constant droplet number concentration
501  // NOTE: m_ndcnst is NOT reset here. It carries the value queried from
502  // erf.morrison_ndcnst above (default 250 cm^-3); overwriting it
503  // here silently discarded the user's setting on every box, in
504  // both the C++ and the Fortran path.
505  // Mathematical constants
506  m_pi = Real(3.1415926535897932384626434);
507 
508  m_R = Real(287.0); // Gas constant for dry air (J/kg/K)
509  m_Rd = Real(287.0); // Gas constant for dry air (J/kg/K)
510  m_Rv = Real(461.6); // Gas constant for water vapor (J/kg/K)
511  // m_cp = Real(7.0)*Real(287.0)/Real(2); // Specific heat at constant pressure (J/kg/K)
512  m_g = Real(9.81); // Gravitational acceleration (m/s^2)
513  m_ep_2 = m_Rd / m_Rv; // Molecular weight ratio (Rd/Rv)
514 
515  // Reference density
516  m_rhosu = Real(85000.0)/(Real(287.15)*Real(273.15)); // Standard air density at 850 mb (kg/m^3)
517 
518  // Densities for different hydrometeor species
519  m_rhow = Real(997.0); // Density of liquid water (kg/m^3)
520  m_rhoi = Real(500.0); // Bulk density of cloud ice (kg/m^3)
521  m_rhosn = Real(100.0); // Bulk density of snow (kg/m^3)
522 
523  // Set density for graupel or hail based on configuration
524  if (m_ihail == 0) {
525  m_rhog = Real(400.0); // Bulk density of graupel (kg/m^3)
526  } else {
527  m_rhog = Real(900.0); // Bulk density of hail (kg/m^3)
528  }
529 
530  // Fall speed parameters (V=AD^B) for different hydrometeors
531  // Cloud ice
532  m_ai = Real(700.0);
533  m_bi = one;
534 
535  // Cloud droplets
536  // m_ac = Real(3.0E7);
537  m_bc = Real(2);
538 
539  // Snow
540  m_as = Real(11.72);
541  m_bs = Real(0.41);
542 
543  // Rain
544  m_ar = Real(841.99667);
545  m_br = Real(0.8);
546 
547  // Graupel/hail (dependent on configuration)
548  if (m_ihail == 0) {
549  // Graupel parameters
550  m_ag = Real(19.3);
551  m_bg = Real(0.37);
552  } else {
553  // Hail parameters (Matsun and Huggins 1980)
554  m_ag = Real(114.5);
555  m_bg = myhalf;
556  }
557 
558  // Microphysical parameters
559  m_aimm = Real(0.66); // Parameter in Bigg immersion freezing
560  m_bimm = Real(100.0); // Parameter in Bigg immersion freezing
561  m_ecr = one; // Collection efficiency between rain and snow/graupel
562  m_dcs = Real(125.0E-6); // Threshold size for cloud ice autoconversion (m)
563  m_mi0 = Real(4.0)/three*m_pi*m_rhoi*amrex::Math::powi<3>(Real(10.0E-6)); // Initial mass of nucleated ice crystal (kg)
564  m_mg0 = Real(1.6E-10); // Mass of embryo graupel (kg)
565 
566  // Ventilation parameters
567  m_f1s = Real(0.86); // Ventilation parameter for snow
568  m_f2s = Real(0.28); // Ventilation parameter for snow
569  m_f1r = Real(0.78); // Ventilation parameter for rain
570  m_f2r = Real(0.308); // Ventilation parameter for rain
571 
572  // Smallest allowed hydrometeor mixing ratio
573  m_qsmall = Real(1.0E-14);
574 
575  // Collection efficiencies
576  m_eii = Real(0.1); // Ice-ice collision efficiency
577  m_eci = Real(0.7); // Ice-droplet collision efficiency
578 
579  // Specific heat of liquid water (J/kg/K)
580  m_cpw = Real(4187.0);
581 
582  // Size distribution parameters
583  m_ci = m_rhoi * m_pi / Real(6.0);
584  m_di = three;
585  m_cs = m_rhosn * m_pi / Real(6.0);
586  m_ds = three;
587  m_cg = m_rhog * m_pi / Real(6.0);
588  m_dg = three;
589 
590  // Radius of contact nuclei (m)
591  m_rin = Real(0.1E-6);
592 
593  // Mass of splintered ice particle (kg)
594  m_mmult = Real(4.0)/three*m_pi*m_rhoi*amrex::Math::powi<3>(Real(5.0E-6));
595 
596  // Set lambda limits for size distributions
597  // Maximum and minimum values for lambda parameter in size distributions
598  m_lammaxi = one/Real(1.0E-6);
599  m_lammini = one/(Real(2)*m_dcs + Real(100.0E-6));
600  m_lammaxr = one/Real(20.0E-6);
601  m_lamminr = one/Real(2800.0E-6);
602  m_lammaxs = one/Real(10.0E-6);
603  m_lammins = one/Real(2000.0E-6);
604  m_lammaxg = one/Real(20.0E-6);
605  m_lamming = one/Real(2000.0E-6);
606 
607  // Set CCN parameters for different environments
608  if (m_iact == 1) {
609  // Maritime CCN spectrum parameters (modified from Rasmussen et al. 2002)
610  // NCCN = C*S^K, where S is supersaturation in %
611  // m_k1 = Real(0.4); // Exponent in CCN activation formula
612  // m_c1 = Real(120.0); // Coefficient in CCN activation formula (cm^-3)
613  }
614 
615  // Initialize aerosol activation parameters for lognormal distribution
616  if (m_iact == 2) {
617  // Parameters for ammonium sulfate
618  // m_mw = Real(0.018); // Molecular weight of water (kg/mol)
619  // m_osm = one; // Osmotic coefficient
620  // m_vi = three; // Number of ions dissociated in solution
621  // m_epsm = Real(0.7); // Aerosol soluble fraction
622  // m_rhoa = Real(1777.0); // Aerosol bulk density (kg/m^3)
623  // m_map = Real(0.132); // Molecular weight of aerosol (kg/mol)
624  // m_ma = Real(0.0284); // Molecular weight of air (kg/mol)
625  // m_rr = Real(8.3145); // Universal gas constant (J/mol/K)
626  // m_bact = m_vi * m_osm * m_epsm * m_mw * m_rhoa / (m_map * m_rhow);
627  // m_a_w = two * m_mw * Real(0.0761) / (m_rhow * m_r_v * Real(293.15)); // "A" parameter
628 
629  // Aerosol size distribution parameters for MPACE (Morrison et al. 2007, JGR)
630  // Mode 1
631  // m_rm1 = Real(0.052E-6); // Geometric mean radius, mode 1 (m)
632  // m_sig1 = Real(2.04); // Standard deviation of aerosol size distribution, mode 1
633  m_nanew1 = Real(72.2E6); // Total aerosol concentration, mode 1 (m^-3)
634  // m_f11 = myhalf * std::exp(Real(2.5) * amrex::Math::powi<2>(std::log(m_sig1)));
635  // m_f21 = one + fourth * std::log(m_sig1);
636 
637  // Mode 2
638  // m_rm2 = Real(1.3E-6); // Geometric mean radius, mode 2 (m)
639  // m_sig2 = Real(2.5); // Standard deviation of aerosol size distribution, mode 2
640  m_nanew2 = Real(1.8E6); // Total aerosol concentration, mode 2 (m^-3)
641  // m_f12 = myhalf * std::exp(Real(2.5) * amrex::Math::powi<2>(std::log(m_sig2)));
642  // m_f22 = one + fourth * std::log(m_sig2);
643  }
644 
645  // Precompute constants for efficiency
646  m_cons1 = gamma_function(one + m_ds) * m_cs;
647  m_cons2 = gamma_function(one + m_dg) * m_cg;
648  m_cons3 = gamma_function(Real(4.0) + m_bs) / Real(6.0);
649  m_cons4 = gamma_function(Real(4.0) + m_br) / Real(6.0);
650  m_cons5 = gamma_function(one + m_bs);
651  m_cons6 = gamma_function(one + m_br);
652  m_cons7 = gamma_function(Real(4.0) + m_bg) / Real(6.0);
653  m_cons8 = gamma_function(one + m_bg);
654  m_cons9 = gamma_function(Real(5.0)/Real(2) + m_br/Real(2));
655  m_cons10 = gamma_function(Real(5.0)/Real(2) + m_bs/Real(2));
656  m_cons11 = gamma_function(Real(5.0)/Real(2) + m_bg/Real(2));
657  m_cons12 = gamma_function(one + m_di) * m_ci;
658  m_cons13 = gamma_function(m_bs + three) * m_pi / Real(4.0) * m_eci;
659  m_cons14 = gamma_function(m_bg + three) * m_pi / Real(4.0) * m_eci;
660  m_cons15 = -Real(1108.0) * m_eii * std::pow(m_pi, (one-m_bs)/three) *
661  std::pow(m_rhosn, (-Real(2)-m_bs)/three) / (Real(4.0)*Real(720.0));
662  m_cons16 = gamma_function(m_bi + three) * m_pi / Real(4.0) * m_eci;
663  m_cons17 = Real(4.0) * Real(2) * three * m_rhosu * m_pi * m_eci * m_eci *
664  gamma_function(Real(2)*m_bs + Real(2)) / (Real(8.0)*(m_rhog-m_rhosn));
665  m_cons18 = m_rhosn * m_rhosn;
666  m_cons19 = m_rhow * m_rhow;
667  m_cons20 = Real(20.0) * m_pi * m_pi * m_rhow * m_bimm;
668  m_cons21 = Real(4.0) / (m_dcs * m_rhoi);
669  m_cons22 = m_pi * m_rhoi * amrex::Math::powi<3>(m_dcs) / Real(6.0);
670  m_cons23 = m_pi / Real(4.0) * m_eii * gamma_function(m_bs + three);
671  m_cons24 = m_pi / Real(4.0) * m_ecr * gamma_function(m_br + three);
672  m_cons25 = m_pi * m_pi / Real(24.0) * m_rhow * m_ecr * gamma_function(m_br + Real(6.0));
673  m_cons26 = m_pi / Real(6.0) * m_rhow;
674  m_cons27 = gamma_function(one + m_bi);
675  m_cons28 = gamma_function(Real(4.0) + m_bi) / Real(6.0);
676  m_cons29 = Real(4.0)/three * m_pi * m_rhow * amrex::Math::powi<3>(Real(25.0E-6));
677  m_cons31 = m_pi * m_pi * m_ecr * m_rhosn;
678  m_cons32 = m_pi / Real(2) * m_ecr;
679  m_cons34 = Real(5.0)/Real(2) + m_br/Real(2);
680  m_cons35 = Real(5.0)/Real(2) + m_bs/Real(2);
681  m_cons36 = Real(5.0)/Real(2) + m_bg/Real(2);
682  m_cons37 = Real(4.0) * m_pi * Real(1.38E-23) / (Real(6.0) * m_pi * m_rin);
683  m_cons38 = m_pi * m_pi / three * m_rhow;
684  m_cons39 = m_pi * m_pi / Real(36.0) * m_rhow * m_bimm;
685  m_cons40 = m_pi / Real(6.0) * m_bimm;
686  m_cons41 = m_pi * m_pi * m_ecr * m_rhow;
687 
688  // Set CCN parameters for different environments
689  if (m_iact == 1) {
690  // Maritime CCN spectrum parameters (modified from Rasmussen et al. 2002)
691  // NCCN = C*S^K, where S is supersaturation in %
692  // m_k1 = Real(0.4); // Exponent in CCN activation formula
693  // m_c1 = Real(120.0); // Coefficient in CCN activation formula (cm^-3)
694  }
695 
696  // Initialize aerosol activation parameters for IACT=2
697  if (m_iact == 2) {
698  // Parameters for ammonium sulfate
699  // m_mw = Real(0.018); // Molecular weight of water (kg/mol)
700  // m_osm = one; // Osmotic coefficient
701  // m_vi = three; // Number of ions dissociated in solution
702  // m_epsm = Real(0.7); // Aerosol soluble fraction
703  // m_rhoa = Real(1777.0); // Aerosol bulk density (kg/m^3)
704  // m_map = Real(0.132); // Molecular weight of aerosol (kg/mol)
705  // m_ma = Real(0.0284); // Molecular weight of air (kg/mol)
706  // m_rr = Real(8.3145); // Universal gas constant (J/mol/K)
707  // m_bact = m_vi * m_osm * m_epsm * m_mw * m_rhoa / (m_map * m_rhow);
708 
709  // Aerosol size distribution parameters for MPACE (Morrison et al. 2007, JGR)
710  // Mode 1
711  // m_rm1 = Real(0.052E-6); // Geometric mean radius, mode 1 (m)
712  // m_sig1 = Real(2.04); // Standard deviation of aerosol size distribution, mode 1
713  m_nanew1 = Real(72.2E6); // Total aerosol concentration, mode 1 (m^-3)
714  // m_f11 = myhalf * std::exp(Real(2.5) * amrex::Math::powi<2>(std::log(m_sig1)));
715  // m_f21 = one + fourth * std::log(m_sig1);
716 
717  // Mode 2
718  // m_rm2 = Real(1.3E-6); // Geometric mean radius, mode 2 (m)
719  // m_sig2 = Real(2.5); // Standard deviation of aerosol size distribution, mode 2
720  m_nanew2 = Real(1.8E6); // Total aerosol concentration, mode 2 (m^-3)
721  // m_f12 = myhalf * std::exp(Real(2.5) * amrex::Math::powi<2>(std::log(m_sig2)));
722  // m_f22 = one + fourth * std::log(m_sig2);
723  }
724  // Set microphysics control parameters
725  m_iact = 2; // Lognormal aerosol activation
726  m_inuc = 0; // Mid-latitude ice nucleation (Cooper)
727  if (sc.moisture_type == MoistureType::Morrison_NoIce) {
728  m_iliq = 1; // Include ice processes
729  m_igraup = 1; // Include graupel processes
730  } else {
731  m_iliq = 0; // Include ice processes
732  m_igraup = 0; // Include graupel processes
733  }
734  m_ihail = 0; // Use graupel (0) instead of hail (1)
735  // m_isub = 0; // Sub-grid vertical velocity option
736  // m_do_radar_ref = false; // Disable radar reflectivity by default
737  Box boxD(box); boxD.makeSlab(2,0);
738 
739  if(run_morr_cpp) {
740 
741  // One FAB to rule them all
742  FArrayBox morr_fab(grown_box, MORRInd::NumInds, Arena_Used);
743  morr_fab.template setVal<RunOn::Device>(0);
744  auto const& morr_arr = morr_fab.array();
745 
746  ////////////////////////////////////////////////////////////
747  // ParallelFor for testing partial C++ implementation
748  // NOTE: Currently all Array4 values are copied to locals
749  // This means we're not updating or outputting anything
750  ////////////////////////////////////////////////////////////
751  ParallelFor( box, [=] AMREX_GPU_DEVICE (int i, int j, int k)
752  {
753  // Tendencies and mixing ratios
754  morr_arr(i,j,k,MORRInd::qc3d) = qcl_arr(i,j,k); // CLOUD WATER MIXING RATIO
755  morr_arr(i,j,k,MORRInd::qi3d) = qci_arr(i,j,k); // CLOUD ICE MIXING RATIO
756  morr_arr(i,j,k,MORRInd::qni3d) = qps_arr(i,j,k); // SNOW MIXING RATIO
757  morr_arr(i,j,k,MORRInd::qr3d) = qpr_arr(i,j,k); // RAIN MIXING RATIO
758  morr_arr(i,j,k,MORRInd::qg3d) = qpg_arr(i,j,k); // GRAUPEL MIXING RATIO
759 
760  morr_arr(i,j,k,MORRInd::nc3d) = nc_arr(i,j,k); // CLOUD WATER NUMBER CONCENTRATION
761  morr_arr(i,j,k,MORRInd::ni3d) = ni_arr(i,j,k); // CLOUD ICE NUMBER CONCENTRATION
762  morr_arr(i,j,k,MORRInd::ns3d) = ns_arr(i,j,k); // SNOW NUMBER CONCENTRATION
763  morr_arr(i,j,k,MORRInd::nr3d) = nr_arr(i,j,k); // RAIN NUMBER CONCENTRATION
764  morr_arr(i,j,k,MORRInd::ng3d) = ng_arr(i,j,k); // GRAUPEL NUMBER CONCENTRATION
765 
766  morr_arr(i,j,k,MORRInd::t3d) = theta_arr(i,j,k) * pii_arr(i,j,k); // TEMPERATURE
767  morr_arr(i,j,k,MORRInd::qv3d) = qv_arr(i,j,k); // WATER VAPOR MIXING RATIO
768  morr_arr(i,j,k,MORRInd::pres) = pres_arr(i,j,k); // ATMOSPHERIC PRESSURE
769  morr_arr(i,j,k,MORRInd::dzq) = dz_arr(i,j,k); // DIFFERENCE IN HEIGHT ACROSS LEVEL
770  morr_arr(i,j,k,MORRInd::w3d) = w_arr(i,j,k); // GRID-SCALE VERTICAL VELOCITY
771 
772  // NOTE: There are no cumulus tendencies passed to Morrison
773  // and the FORTRAN version zeros these out.
774  morr_arr(i,j,k,MORRInd::qrcu1d) = Real(0); //morr_arr(i,j,k,MORRInd::qrcuten_arr); // RAIN FROM CUMULUS PARAMETERIZATION
775  morr_arr(i,j,k,MORRInd::qscu1d) = Real(0); //morr_arr(i,j,k,MORRInd::qscuten_arr); // SNOW FROM CUMULUS PARAMETERIZATION
776  morr_arr(i,j,k,MORRInd::qicu1d) = Real(0); //morr_arr(i,j,k,MORRInd::qicuten_arr); // ICE FROM CUMULUS PARAMETERIZATION
777  });
778 
779  ParallelFor( boxD, [=] AMREX_GPU_DEVICE (int i, int j, int )
780  {
781  int ltrue=0; // LTRUE: SWITCH = 0: NO HYDROMETEORS IN COLUMN, = 1: HYDROMETEORS IN COLUMN
782  int nstep; // NSTEP: Timestep counter
783  int iinum=m_inum; // iinum: Integer control variable
784 
785  for (int k=klo; k<=khi; k++) {
786  // Microphysical processes
787  // Real nsubc; // NSUBC: Loss of NC during evaporation
788  Real nsubi; // NSUBI: Loss of NI during sublimation
789  Real nsubs; // NSUBS: Loss of NS during sublimation
790  Real nsubr; // NSUBR: Loss of NR during evaporation
791  Real prd; // PRD: Deposition cloud ice
792  Real pre; // PRE: Evaporation of rain
793  Real prds; // PRDS: Deposition snow
794  Real nnuccc; // NNUCCC: Change N due to contact freezing droplets
795  Real mnuccc; // MNUCCC: Change Q due to contact freezing droplets
796  Real pra; // PRA: Accretion droplets by rain
797  Real prc; // PRC: Autoconversion droplets
798  Real pcc; // PCC: Condensation/evaporation droplets
799  Real nnuccd; // NNUCCD: Change N freezing aerosol (primary ice nucleation)
800  Real mnuccd; // MNUCCD: Change Q freezing aerosol (primary ice nucleation)
801  Real mnuccr; // MNUCCR: Change Q due to contact freezing rain
802  Real nnuccr; // NNUCCR: Change N due to contact freezing rain
803  Real npra; // NPRA: Change N due to droplet accretion by rain
804  Real nragg; // NRAGG: Self-collection/breakup of rain
805  Real nsagg; // NSAGG: Self-collection of snow
806  Real nprc; // NPRC: Change NC autoconversion droplets
807  Real nprc1; // NPRC1: Change NR autoconversion droplets
808  Real prai; // PRAI: Change Q accretion cloud ice by snow
809  Real prci; // PRCI: Change Q autoconversion cloud ice to snow
810  Real psacws; // PSACWS: Change Q droplet accretion by snow
811  Real npsacws; // NPSACWS: Change N droplet accretion by snow
812  Real psacwi; // PSACWI: Change Q droplet accretion by cloud ice
813  Real npsacwi; // NPSACWI: Change N droplet accretion by cloud ice
814  Real nprci; // NPRCI: Change N autoconversion cloud ice by snow
815  Real nprai; // NPRAI: Change N accretion cloud ice
816  Real nmults; // NMULTS: Ice multiplication due to riming droplets by snow
817  Real nmultr; // NMULTR: Ice multiplication due to riming rain by snow
818  Real qmults; // QMULTS: Change Q due to ice multiplication droplets/snow
819  Real qmultr; // QMULTR: Change Q due to ice multiplication rain/snow
820  Real pracs; // PRACS: Change Q rain-snow collection
821  Real npracs; // NPRACS: Change N rain-snow collection
822  // Real pccn; // PCCN: Change Q droplet activation
823  Real psmlt; // PSMLT: Change Q melting snow to rain
824  Real evpms; // EVPMS: Change Q melting snow evaporating
825  Real nsmlts; // NSMLTS: Change N melting snow
826  Real nsmltr; // NSMLTR: Change N melting snow to rain
827  Real piacr; // PIACR: Change QR, ice-rain collection
828  Real niacr; // NIACR: Change N, ice-rain collection
829  Real praci; // PRACI: Change QI, ice-rain collection
830  Real piacrs; // PIACRS: Change QR, ice rain collision, added to snow
831  Real niacrs; // NIACRS: Change N, ice rain collision, added to snow
832  Real pracis; // PRACIS: Change QI, ice rain collision, added to snow
833  Real eprd; // EPRD: Sublimation cloud ice
834  Real eprds; // EPRDS: Sublimation snow
835 
836  // Graupel processes
837  Real pracg; // PRACG: Change in Q collection rain by graupel
838  Real psacwg; // PSACWG: Change in Q collection droplets by graupel
839  Real pgsacw; // PGSACW: Conversion Q to graupel due to collection droplets by snow
840  Real pgracs; // PGRACS: Conversion Q to graupel due to collection rain by snow
841  Real prdg; // PRDG: Deposition of graupel
842  Real eprdg; // EPRDG: Sublimation of graupel
843  Real evpmg; // EVPMG: Change Q melting of graupel and evaporation
844  Real pgmlt; // PGMLT: Change Q melting of graupel
845  Real npracg; // NPRACG: Change N collection rain by graupel
846  Real npsacwg; // NPSACWG: Change N collection droplets by graupel
847  Real nscng; // NSCNG: Change N conversion to graupel due to collection droplets by snow
848  Real ngracs; // NGRACS: Change N conversion to graupel due to collection rain by snow
849  Real ngmltg; // NGMLTG: Change N melting graupel
850  Real ngmltr; // NGMLTR: Change N melting graupel to rain
851  Real nsubg; // NSUBG: Change N sublimation/deposition of graupel
852  Real psacr; // PSACR: Conversion due to collection of snow by rain
853  Real nmultg; // NMULTG: Ice multiplication due to accretion droplets by graupel
854  Real nmultrg; // NMULTRG: Ice multiplication due to accretion rain by graupel
855  Real qmultg; // QMULTG: Change Q due to ice multiplication droplets/graupel
856  Real qmultrg; // QMULTRG: Change Q due to ice multiplication rain/graupel
857 
858  // Time-varying atmospheric parameters
859  Real kap; // KAP: Thermal conductivity of air
860  Real evs; // EVS: Saturation vapor pressure
861  Real eis; // EIS: Ice saturation vapor pressure
862  Real qvs; // QVS: Saturation mixing ratio
863  Real qvi; // QVI: Ice saturation mixing ratio
864  Real qvqvs; // QVQVS: Saturation ratio
865  Real qvqvsi; // QVQVSI: Ice saturation ratio
866  Real dv; // DV: Diffusivity of water vapor in air
867  Real sc_schmidt; // SC: Schmidt number
868  Real ab; // AB: Correction to condensation rate due to latent heating
869  Real abi; // ABI: Correction to deposition rate due to latent heating
870 
871  // Dummy variables
872  Real dum; // DUM: General dummy variable
873  Real dum1; // DUM1: General dummy variable
874  Real dumt; // DUMT: Dummy variable for temperature
875  Real dumqv; // DUMQV: Dummy variable for water vapor
876  Real dumqss; // DUMQSS: Dummy saturation mixing ratio
877  Real dums; // DUMS: General dummy variable
878 
879  // Prognostic supersaturation
880  Real dqsdt; // DQSDT: Change of saturation mixing ratio with temperature
881  Real dqsidt; // DQSIDT: Change in ice saturation mixing ratio with temperature
882 
883  Real epsi; // EPSI: 1/phase relaxation time (see M2005), ice
884  Real epss; // EPSS: 1/phase relaxation time (see M2005), snow
885  Real epsr; // EPSR: 1/phase relaxation time (see M2005), rain
886  Real epsg; // EPSG: 1/phase relaxation time (see M2005), graupel
887  Real kc2; // KC2: Total ice nucleation rate
888  Real di0; // DC0: Characteristic diameter for ice
889  Real ds0; // DS0: Characteristic diameter for snow
890  Real dg0; // DG0: Characteristic diameter for graupel
891  Real dumqc; // DUMQC: Dummy variable for cloud water mixing ratio
892  Real ratio; // RATIO: General ratio variable
893  Real sum_dep; // SUM_DEP: Sum of deposition/sublimation
894  Real fudgef; // FUDGEF: Adjustment factor
895 
896  // Real dum2; // DUM2: General dummy variable
897  // Real dumqsi; // DUMQSI: Dummy ice saturation mixing ratio
898  // Real dc0; // DC0: Characteristic diameter for cloud droplets
899  // Real dumqr; // DUMQR: Dummy variable for rain mixing ratio
900 
901  // For WRF-CHEM
902  // Real c2prec; // C2PREC: Cloud to precipitation conversion
903  // Real csed; // CSED: Cloud sedimentation
904  // Real ised; // ISED: Ice sedimentation
905  // Real ssed; // SSED: Snow sedimentation
906  // Real gsed; // GSED: Graupel sedimentation
907  // Real rsed; // RSED: Rain sedimentation
908  // Real tqimelt; // tqimelt: Melting of cloud ice (tendency)
909 
910  // NC3DTEN LOCAL ARRAY INITIALIZED
911  morr_arr(i,j,k,MORRInd::nc3dten) = Real(0);
912 
913  // INITIALIZE VARIABLES FOR WRF-CHEM OUTPUT TO ZERO
914  // c2prec = Real(0);
915  // csed = Real(0);
916  // ised = Real(0);
917  // ssed = Real(0);
918  // gsed = Real(0);
919  // rsed = Real(0);
920 
921  // LATENT HEAT OF VAPORIZATION
922  morr_arr(i,j,k,MORRInd::xxlv) = Real(3.1484E6) - Real(2370.0) * morr_arr(i,j,k,MORRInd::t3d);
923  // LATENT HEAT OF SUBLIMATION
924  morr_arr(i,j,k,MORRInd::xxls) = Real(3.15E6) - Real(2370.0) * morr_arr(i,j,k,MORRInd::t3d) + Real(0.3337E6);
925 
926  // Assuming CP is a constant defined elsewhere (specific heat of dry air at constant pressure)
927  const Real CP = Real(1004.5); // J/kg/K
928  morr_arr(i,j,k,MORRInd::cpm) = CP * (one + Real(0.887) * morr_arr(i,j,k,MORRInd::qv3d));
929 
930  // SATURATION VAPOR PRESSURE AND MIXING RATIO
931  // hm, add fix for low pressure, 5/12/10
932  // Assuming POLYSVP is defined elsewhere
933  evs = std::min(Real(0.99) * morr_arr(i,j,k,MORRInd::pres), calc_saturation_vapor_pressure(morr_arr(i,j,k,MORRInd::t3d), 0)); // PA
934  eis = std::min(Real(0.99) * morr_arr(i,j,k,MORRInd::pres), calc_saturation_vapor_pressure(morr_arr(i,j,k,MORRInd::t3d), 1)); // PA
935  // MAKE SURE ICE SATURATION DOESN'T EXCEED WATER SAT. NEAR FREEZING
936  if (eis > evs) {
937  eis = evs; // temporary update: adjust ice saturation pressure
938  }
939 
940  // SATURATION MIXING RATIOS
941  qvs = m_ep_2 * evs / (morr_arr(i,j,k,MORRInd::pres) - evs); // budget equation: calculate water saturation mixing ratio
942  qvi = m_ep_2 * eis / (morr_arr(i,j,k,MORRInd::pres) - eis); // budget equation: calculate ice saturation mixing ratio
943 
944  // SATURATION RATIOS
945  qvqvs = morr_arr(i,j,k,MORRInd::qv3d) / qvs; // budget equation: calculate water saturation ratio
946  qvqvsi = morr_arr(i,j,k,MORRInd::qv3d) / qvi; // budget equation: calculate ice saturation ratio
947 
948  // AIR DENSITY
949  morr_arr(i,j,k,MORRInd::rho) = morr_arr(i,j,k,MORRInd::pres) / (m_R * morr_arr(i,j,k,MORRInd::t3d)); // budget equation: calculate air density
950 
951  ds0 = three; // Size distribution parameter for snow
952  di0 = three; // Size distribution parameter for cloud ice
953  dg0 = three; // Size distribution parameter for graupel
954 
955  // ADD NUMBER CONCENTRATION DUE TO CUMULUS TENDENCY
956  // ASSUME N0 ASSOCIATED WITH CUMULUS PARAM RAIN IS 10^7 M^-4
957  // ASSUME N0 ASSOCIATED WITH CUMULUS PARAM SNOW IS 2 X 10^7 M^-4
958  // FOR DETRAINED CLOUD ICE, ASSUME MEAN VOLUME DIAM OF 80 MICRON
959  if (morr_arr(i,j,k,MORRInd::qrcu1d) >= Real(1.0e-10)) {
960  dum = Real(1.8e5) * std::pow(morr_arr(i,j,k,MORRInd::qrcu1d) * dt / (m_pi * m_rhow * amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::rho))), fourth); // rate equation: calculate rain number concentration from cumulus
961  morr_arr(i,j,k,MORRInd::nr3d) += dum; // budget equation: update rain number concentration
962  }
963  if (morr_arr(i,j,k,MORRInd::qscu1d) >= Real(1.0e-10)) {
964  dum = Real(3.e5) * std::pow(morr_arr(i,j,k,MORRInd::qscu1d) * dt / (m_cons1 * amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::rho))), one / (ds0 + one)); // rate equation: calculate snow number concentration from cumulus
965  morr_arr(i,j,k,MORRInd::ns3d) += dum; // budget equation: update snow number concentration
966  }
967  if (morr_arr(i,j,k,MORRInd::qicu1d) >= Real(1.0e-10)) {
968  dum = morr_arr(i,j,k,MORRInd::qicu1d) * dt / (m_ci * std::pow(Real(80.0e-6), di0)); // rate equation: calculate cloud ice number concentration from cumulus
969  morr_arr(i,j,k,MORRInd::ni3d) += dum; // budget equation: update cloud ice number concentration
970  }
971 
972  // AT SUBSATURATION, REMOVE SMALL AMOUNTS OF CLOUD/PRECIP WATER
973  // hm modify 7/0/09 change limit to Real(1.e-8)
974  if (qvqvs < Real(0.9)) {
975  if (morr_arr(i,j,k,MORRInd::qr3d) < Real(1.0e-8)) {
976  morr_arr(i,j,k,MORRInd::qv3d) += morr_arr(i,j,k,MORRInd::qr3d); // budget equation: transfer rain to vapor
977  morr_arr(i,j,k,MORRInd::t3d) -= morr_arr(i,j,k,MORRInd::qr3d) * morr_arr(i,j,k,MORRInd::xxlv) / morr_arr(i,j,k,MORRInd::cpm); // budget equation: adjust temperature
978  morr_arr(i,j,k,MORRInd::qr3d) = Real(0); // temporary update: set rain to Real(0)
979  }
980  if (morr_arr(i,j,k,MORRInd::qc3d) < Real(1.0e-8)) {
981  morr_arr(i,j,k,MORRInd::qv3d) += morr_arr(i,j,k,MORRInd::qc3d); // budget equation: transfer cloud water to vapor
982  morr_arr(i,j,k,MORRInd::t3d) -= morr_arr(i,j,k,MORRInd::qc3d) * morr_arr(i,j,k,MORRInd::xxlv) / morr_arr(i,j,k,MORRInd::cpm); // budget equation: adjust temperature
983  morr_arr(i,j,k,MORRInd::qc3d) = Real(0); // temporary update: set cloud water to Real(0)
984  }
985  }
986  if (qvqvsi < Real(0.9)) {
987  if (morr_arr(i,j,k,MORRInd::qi3d) < Real(1.0e-8)) {
988  morr_arr(i,j,k,MORRInd::qv3d) += morr_arr(i,j,k,MORRInd::qi3d); // budget equation: transfer cloud ice to vapor
989  morr_arr(i,j,k,MORRInd::t3d) -= morr_arr(i,j,k,MORRInd::qi3d) * morr_arr(i,j,k,MORRInd::xxls) / morr_arr(i,j,k,MORRInd::cpm); // budget equation: adjust temperature
990  morr_arr(i,j,k,MORRInd::qi3d) = Real(0); // temporary update: set cloud ice to Real(0)
991  }
992  if (morr_arr(i,j,k,MORRInd::qni3d) < Real(1.0e-8)) {
993  morr_arr(i,j,k,MORRInd::qv3d) += morr_arr(i,j,k,MORRInd::qni3d); // budget equation: transfer snow to vapor
994  morr_arr(i,j,k,MORRInd::t3d) -= morr_arr(i,j,k,MORRInd::qni3d) * morr_arr(i,j,k,MORRInd::xxls) / morr_arr(i,j,k,MORRInd::cpm); // budget equation: adjust temperature
995  morr_arr(i,j,k,MORRInd::qni3d) = Real(0); // temporary update: set snow to Real(0)
996  }
997  if (morr_arr(i,j,k,MORRInd::qg3d) < Real(1.0e-8)) {
998  morr_arr(i,j,k,MORRInd::qv3d) += morr_arr(i,j,k,MORRInd::qg3d); // budget equation: transfer graupel to vapor
999  morr_arr(i,j,k,MORRInd::t3d) -= morr_arr(i,j,k,MORRInd::qg3d) * morr_arr(i,j,k,MORRInd::xxls) / morr_arr(i,j,k,MORRInd::cpm); // budget equation: adjust temperature
1000  morr_arr(i,j,k,MORRInd::qg3d) = Real(0); // temporary update: set graupel to Real(0)
1001  }
1002  }
1003  // HEAT OF FUSION
1004  morr_arr(i,j,k,MORRInd::xlf) = morr_arr(i,j,k,MORRInd::xxls) - morr_arr(i,j,k,MORRInd::xxlv);
1005 
1006  // IF MIXING RATIO < QSMALL SET MIXING RATIO AND NUMBER CONC TO ZERO
1007  // Note: QSMALL is not defined in the variable list, so I'll define it
1008  const Real QSMALL = m_qsmall;
1009 
1010  if (morr_arr(i,j,k,MORRInd::qc3d) < QSMALL) {
1011  morr_arr(i,j,k,MORRInd::qc3d) = Real(0);
1012  morr_arr(i,j,k,MORRInd::nc3d) = Real(0);
1013  morr_arr(i,j,k,MORRInd::effc) = Real(0);
1014  }
1015  if (morr_arr(i,j,k,MORRInd::qr3d) < QSMALL) {
1016  morr_arr(i,j,k,MORRInd::qr3d) = Real(0);
1017  morr_arr(i,j,k,MORRInd::nr3d) = Real(0);
1018  morr_arr(i,j,k,MORRInd::effr) = Real(0);
1019  }
1020  if (morr_arr(i,j,k,MORRInd::qi3d) < QSMALL) {
1021  morr_arr(i,j,k,MORRInd::qi3d) = Real(0);
1022  morr_arr(i,j,k,MORRInd::ni3d) = Real(0);
1023  morr_arr(i,j,k,MORRInd::effi) = Real(0);
1024  }
1025  if (morr_arr(i,j,k,MORRInd::qni3d) < QSMALL) {
1026  morr_arr(i,j,k,MORRInd::qni3d) = Real(0);
1027  morr_arr(i,j,k,MORRInd::ns3d) = Real(0);
1028  morr_arr(i,j,k,MORRInd::effs) = Real(0);
1029  }
1030  if (morr_arr(i,j,k,MORRInd::qg3d) < QSMALL) {
1031  morr_arr(i,j,k,MORRInd::qg3d) = Real(0);
1032  morr_arr(i,j,k,MORRInd::ng3d) = Real(0);
1033  morr_arr(i,j,k,MORRInd::effg) = Real(0);
1034  }
1035  // INITIALIZE SEDIMENTATION TENDENCIES FOR MIXING RATIO
1036  morr_arr(i,j,k,MORRInd::qrsten) = Real(0); // temporary update: initialize QRSTEN
1037  morr_arr(i,j,k,MORRInd::qisten) = Real(0); // temporary update: initialize QISTEN
1038  morr_arr(i,j,k,MORRInd::qnisten) = Real(0); // temporary update: initialize QNISTEN
1039  morr_arr(i,j,k,MORRInd::qcsten) = Real(0); // temporary update: initialize QCSTEN
1040  morr_arr(i,j,k,MORRInd::qgsten) = Real(0); // temporary update: initialize QGSTEN
1041 
1042  // MICROPHYSICS PARAMETERS VARYING IN TIME/HEIGHT
1043  morr_arr(i,j,k,MORRInd::mu) = Real(1.496e-6) * std::pow(morr_arr(i,j,k,MORRInd::t3d), Real(1.5)) / (morr_arr(i,j,k,MORRInd::t3d) + Real(120.0)); // budget equation: calculate air viscosity
1044 
1045  // Fall speed with density correction (Heymsfield and Benssemer 2006)
1046  dum = std::pow(m_rhosu / morr_arr(i,j,k,MORRInd::rho), Real(0.54)); // temporary update: calculate density correction factor
1047 
1048  // AA revision 4/1/11: Ikawa and Saito 1991 air-density correction
1049  morr_arr(i,j,k,MORRInd::ain) = std::pow(m_rhosu / morr_arr(i,j,k,MORRInd::rho), Real(0.35)) * m_ai; // budget equation: calculate ice fall speed parameter
1050  morr_arr(i,j,k,MORRInd::arn) = dum * m_ar; // budget equation: calculate rain fall speed parameter
1051  morr_arr(i,j,k,MORRInd::asn) = dum * m_as; // budget equation: calculate snow fall speed parameter
1052 
1053  // AA revision 4/1/11: temperature-dependent Stokes fall speed
1054  morr_arr(i,j,k,MORRInd::acn) = m_g * m_rhow / (Real(18.0) * morr_arr(i,j,k,MORRInd::mu)); // budget equation: calculate cloud droplet fall speed parameter
1055 
1056  // HM ADD GRAUPEL 8/28/06
1057  morr_arr(i,j,k,MORRInd::agn) = dum * m_ag; // budget equation: calculate graupel fall speed parameter
1058  // hm 4/7/09 bug fix, initialize morr_arr(i,j,k,MORRInd::lami) to prevent later division by Real(0)
1059  morr_arr(i,j,k,MORRInd::lami) = Real(0); // temporary update: initialize LAMI
1060 
1061  // If there is no cloud/precip water, and if subsaturated, then skip microphysics for this level
1062  bool skipMicrophysics = false;
1063  bool skipConcentrations = false;
1064  if (morr_arr(i,j,k,MORRInd::qc3d) < QSMALL && morr_arr(i,j,k,MORRInd::qi3d) < QSMALL && morr_arr(i,j,k,MORRInd::qni3d) < QSMALL && morr_arr(i,j,k,MORRInd::qr3d) < QSMALL && morr_arr(i,j,k,MORRInd::qg3d) < QSMALL) {
1065  if ((morr_arr(i,j,k,MORRInd::t3d) < Real(273.15) && qvqvsi < Real(0.999)) || (morr_arr(i,j,k,MORRInd::t3d) >= Real(273.15) && qvqvs < Real(0.999))) {
1066  skipMicrophysics = true;// goto label_200;
1067  }
1068  }
1069 
1070  if(!skipMicrophysics) {
1071 
1072  // Thermal conductivity for air
1073  kap = Real(1.414e3) * morr_arr(i,j,k,MORRInd::mu); // budget equation: calculate thermal conductivity
1074 
1075  // Diffusivity of water vapor
1076  dv = Real(8.794e-5) * std::pow(morr_arr(i,j,k,MORRInd::t3d), Real(1.81)) / morr_arr(i,j,k,MORRInd::pres); // budget equation: calculate vapor diffusivity
1077 
1078  // Schmidt number
1079  sc_schmidt = morr_arr(i,j,k,MORRInd::mu) / (morr_arr(i,j,k,MORRInd::rho) * dv); // budget equation: calculate Schmidt number
1080 
1081  // Psychometric corrections
1082  // Rate of change sat. mix. ratio with temperature
1083  dum = (m_Rv * amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::t3d))); // temporary update: calculate temperature factor
1084  dqsdt = morr_arr(i,j,k,MORRInd::xxlv) * qvs / dum; // budget equation: calculate DQSDT
1085  dqsidt = morr_arr(i,j,k,MORRInd::xxls) * qvi / dum; // budget equation: calculate DQSIDT
1086  abi = one + dqsidt * morr_arr(i,j,k,MORRInd::xxls) / morr_arr(i,j,k,MORRInd::cpm); // budget equation: calculate ABI
1087  ab = one + dqsdt * morr_arr(i,j,k,MORRInd::xxlv) / morr_arr(i,j,k,MORRInd::cpm); // budget equation: calculate AB
1088 
1089  // CASE FOR TEMPERATURE ABOVE FREEZING
1090  if (morr_arr(i,j,k,MORRInd::t3d) >= Real(273.15)) {
1091  //......................................................................
1092  // ALLOW FOR CONSTANT DROPLET NUMBER
1093  // INUM = 0, PREDICT DROPLET NUMBER
1094  // INUM = 1, SET CONSTANT DROPLET NUMBER
1095 
1096  if (m_inum == 1) {
1097  // CONVERT NDCNST FROM CM-3 TO KG-1
1098  morr_arr(i,j,k,MORRInd::nc3d) =
1099  ndcnst_to_number_mixing_ratio(m_ndcnst, rho_arr(i,j,k));
1100  }
1101 
1102  // GET SIZE DISTRIBUTION PARAMETERS
1103  // MELT VERY SMALL SNOW AND GRAUPEL MIXING RATIOS, ADD TO RAIN
1104  if (morr_arr(i,j,k,MORRInd::qni3d) < Real(1.0e-6)) {
1105  morr_arr(i,j,k,MORRInd::qr3d) = morr_arr(i,j,k,MORRInd::qr3d) + morr_arr(i,j,k,MORRInd::qni3d); // Transfer snow to rain
1106  morr_arr(i,j,k,MORRInd::nr3d) = morr_arr(i,j,k,MORRInd::nr3d) + morr_arr(i,j,k,MORRInd::ns3d); // Transfer snow number to rain
1107  morr_arr(i,j,k,MORRInd::t3d) = morr_arr(i,j,k,MORRInd::t3d) - morr_arr(i,j,k,MORRInd::qni3d) * morr_arr(i,j,k,MORRInd::xlf) / morr_arr(i,j,k,MORRInd::cpm); // Adjust temperature
1108  morr_arr(i,j,k,MORRInd::qni3d) = Real(0); // Set snow to Real(0)
1109  morr_arr(i,j,k,MORRInd::ns3d) = Real(0); // Set snow number to Real(0)
1110  }
1111 
1112  if (morr_arr(i,j,k,MORRInd::qg3d) < Real(1.0e-6)) {
1113  morr_arr(i,j,k,MORRInd::qr3d) = morr_arr(i,j,k,MORRInd::qr3d) + morr_arr(i,j,k,MORRInd::qg3d); // Transfer graupel to rain
1114  morr_arr(i,j,k,MORRInd::nr3d) = morr_arr(i,j,k,MORRInd::nr3d) + morr_arr(i,j,k,MORRInd::ng3d); // Transfer graupel number to rain
1115  morr_arr(i,j,k,MORRInd::t3d) = morr_arr(i,j,k,MORRInd::t3d) - morr_arr(i,j,k,MORRInd::qg3d) * morr_arr(i,j,k,MORRInd::xlf) / morr_arr(i,j,k,MORRInd::cpm); // Adjust temperature
1116  morr_arr(i,j,k,MORRInd::qg3d) = Real(0); // Set graupel to Real(0)
1117  morr_arr(i,j,k,MORRInd::ng3d) = Real(0); // Set graupel number to Real(0)
1118  }
1119  // Skip to label 300 if concentrations are below thresholds
1120  if (morr_arr(i,j,k,MORRInd::qc3d) < m_qsmall && morr_arr(i,j,k,MORRInd::qni3d) < Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qr3d) < m_qsmall && morr_arr(i,j,k,MORRInd::qg3d) < Real(1.0e-8)) {
1121  skipConcentrations=true;// goto label_300;
1122  }
1123  if(!skipConcentrations) {
1124  morr_arr(i,j,k,MORRInd::ns3d) = amrex::max(Real(0),morr_arr(i,j,k,MORRInd::ns3d));
1125  morr_arr(i,j,k,MORRInd::nc3d) = amrex::max(Real(0),morr_arr(i,j,k,MORRInd::nc3d));
1126  morr_arr(i,j,k,MORRInd::nr3d) = amrex::max(Real(0),morr_arr(i,j,k,MORRInd::nr3d));
1127  morr_arr(i,j,k,MORRInd::ng3d) = amrex::max(Real(0),morr_arr(i,j,k,MORRInd::ng3d));
1128 
1129  // ========================================================================
1130  // USING WRF APPROACH FOR SIZE DISTRIBUTION PARAMETERS
1131  // ========================================================================
1132  // Rain
1133  if (morr_arr(i,j,k,MORRInd::qr3d) >= m_qsmall) {
1134  // Calculate lambda parameter using cons26 (pi*rhow/6)
1135  morr_arr(i,j,k,MORRInd::lamr) = std::pow(m_pi * m_rhow * morr_arr(i,j,k,MORRInd::nr3d) / morr_arr(i,j,k,MORRInd::qr3d), one/three);
1136  morr_arr(i,j,k,MORRInd::n0r) = morr_arr(i,j,k,MORRInd::nr3d)*morr_arr(i,j,k,MORRInd::lamr);
1137 
1138  // Check for slope and adjust vars
1139  if (morr_arr(i,j,k,MORRInd::lamr) < m_lamminr) {
1140  morr_arr(i,j,k,MORRInd::lamr) = m_lamminr;
1141  morr_arr(i,j,k,MORRInd::n0r) = std::pow(morr_arr(i,j,k,MORRInd::lamr), Real(4.0)) * morr_arr(i,j,k,MORRInd::qr3d) / (m_pi * m_rhow);
1142  morr_arr(i,j,k,MORRInd::nr3d) = morr_arr(i,j,k,MORRInd::n0r) / morr_arr(i,j,k,MORRInd::lamr); // Update number concentration
1143  } else if (morr_arr(i,j,k,MORRInd::lamr) > m_lammaxr) {
1144  morr_arr(i,j,k,MORRInd::lamr) = m_lammaxr;
1145  morr_arr(i,j,k,MORRInd::n0r) = std::pow(morr_arr(i,j,k,MORRInd::lamr), Real(4.0)) * morr_arr(i,j,k,MORRInd::qr3d) / (m_pi * m_rhow);
1146  morr_arr(i,j,k,MORRInd::nr3d) = morr_arr(i,j,k,MORRInd::n0r) / morr_arr(i,j,k,MORRInd::lamr); // Update number concentration
1147  }
1148  }
1149 
1150  // Cloud droplets
1151  if (morr_arr(i,j,k,MORRInd::qc3d) >= m_qsmall) {
1152  // Calculate air density factor (moist air density)
1153  dum = morr_arr(i,j,k,MORRInd::pres)/(Real(287.15)*morr_arr(i,j,k,MORRInd::t3d));
1154 
1155  // MARTIN ET AL. (1994) FORMULA FOR PGAM (WRF implementation)
1156  morr_arr(i,j,k,MORRInd::pgam) = Real(0.0005714)*(morr_arr(i,j,k,MORRInd::nc3d)/Real(1.0e6)*dum) + Real(0.2714);
1157  morr_arr(i,j,k,MORRInd::pgam) = one/(morr_arr(i,j,k,MORRInd::pgam)*morr_arr(i,j,k,MORRInd::pgam)) - one;
1158  morr_arr(i,j,k,MORRInd::pgam) = amrex::max(morr_arr(i,j,k,MORRInd::pgam), Real(2));
1159  morr_arr(i,j,k,MORRInd::pgam) = amrex::min(morr_arr(i,j,k,MORRInd::pgam), Real(10.0));
1160 
1161  // Calculate gamma function values
1162  Real gamma_pgam_plus_1 = gamma_function(morr_arr(i,j,k,MORRInd::pgam) + one);
1163  Real gamma_pgam_plus_4 = gamma_function(morr_arr(i,j,k,MORRInd::pgam) + Real(4.0));
1164 
1165  // Calculate lambda parameter
1166  morr_arr(i,j,k,MORRInd::lamc) = std::pow((m_cons26 * morr_arr(i,j,k,MORRInd::nc3d) * gamma_pgam_plus_4) / (morr_arr(i,j,k,MORRInd::qc3d) * gamma_pgam_plus_1), one/three);
1167 
1168  // Lambda bounds from WRF - 60 micron max diameter, 1 micron min diameter
1169  Real lambda_min = (morr_arr(i,j,k,MORRInd::pgam) + one)/Real(60.0e-6);
1170  Real lambda_max = (morr_arr(i,j,k,MORRInd::pgam) + one)/Real(1.0e-6);
1171 
1172  // Check bounds and update number concentration if needed
1173  if (morr_arr(i,j,k,MORRInd::lamc) < lambda_min) {
1174  morr_arr(i,j,k,MORRInd::lamc) = lambda_min;
1175  // Update cloud droplet number using the same formula as in WRF
1176  morr_arr(i,j,k,MORRInd::nc3d) = std::exp(three*std::log(morr_arr(i,j,k,MORRInd::lamc)) + std::log(morr_arr(i,j,k,MORRInd::qc3d)) +
1177  std::log(gamma_pgam_plus_1) - std::log(gamma_pgam_plus_4))/ m_cons26;
1178  } else if (morr_arr(i,j,k,MORRInd::lamc) > lambda_max) {
1179  morr_arr(i,j,k,MORRInd::lamc) = lambda_max;
1180  // Update cloud droplet number using the same formula as in WRF
1181  morr_arr(i,j,k,MORRInd::nc3d) = std::exp(three*std::log(morr_arr(i,j,k,MORRInd::lamc)) + std::log(morr_arr(i,j,k,MORRInd::qc3d)) +
1182  std::log(gamma_pgam_plus_1) - std::log(gamma_pgam_plus_4))/ m_cons26;
1183  }
1184 
1185  // Calculate intercept parameter
1186  morr_arr(i,j,k,MORRInd::cdist1) = morr_arr(i,j,k,MORRInd::nc3d) / gamma_pgam_plus_1;
1187  }
1188 
1189  // Snow
1190  if (morr_arr(i,j,k,MORRInd::qni3d) >= m_qsmall) {
1191  // Calculate lambda parameter
1192  morr_arr(i,j,k,MORRInd::lams) = std::pow(m_cons1 * morr_arr(i,j,k,MORRInd::ns3d) / morr_arr(i,j,k,MORRInd::qni3d), one/ds0);
1193 
1194  // Calculate intercept parameter
1195  morr_arr(i,j,k,MORRInd::n0s) = morr_arr(i,j,k,MORRInd::ns3d) * morr_arr(i,j,k,MORRInd::lams);
1196 
1197  // Check for slope and adjust vars
1198  if (morr_arr(i,j,k,MORRInd::lams) < m_lammins) {
1199  morr_arr(i,j,k,MORRInd::lams) = m_lammins;
1200  morr_arr(i,j,k,MORRInd::n0s) = std::pow(morr_arr(i,j,k,MORRInd::lams), Real(4.0)) * morr_arr(i,j,k,MORRInd::qni3d) / m_cons1;
1201  morr_arr(i,j,k,MORRInd::ns3d) = morr_arr(i,j,k,MORRInd::n0s) / morr_arr(i,j,k,MORRInd::lams); // Update number concentration
1202  } else if (morr_arr(i,j,k,MORRInd::lams) > m_lammaxs) {
1203  morr_arr(i,j,k,MORRInd::lams) = m_lammaxs;
1204  morr_arr(i,j,k,MORRInd::n0s) = std::pow(morr_arr(i,j,k,MORRInd::lams), Real(4.0)) * morr_arr(i,j,k,MORRInd::qni3d) / m_cons1;
1205  morr_arr(i,j,k,MORRInd::ns3d) = morr_arr(i,j,k,MORRInd::n0s) / morr_arr(i,j,k,MORRInd::lams); // Update number concentration
1206  }
1207  }
1208 
1209  // Graupel
1210  if (morr_arr(i,j,k,MORRInd::qg3d) >= m_qsmall) {
1211  // Calculate lambda parameter
1212  morr_arr(i,j,k,MORRInd::lamg) = std::pow(m_cons2 * morr_arr(i,j,k,MORRInd::ng3d) / morr_arr(i,j,k,MORRInd::qg3d), one/dg0);
1213 
1214  // Calculate intercept parameter
1215  morr_arr(i,j,k,MORRInd::n0g) = morr_arr(i,j,k,MORRInd::ng3d) * morr_arr(i,j,k,MORRInd::lamg);
1216 
1217  // Check for slope and adjust vars
1218  if (morr_arr(i,j,k,MORRInd::lamg) < m_lamming) {
1219  morr_arr(i,j,k,MORRInd::lamg) = m_lamming;
1220  morr_arr(i,j,k,MORRInd::n0g) = std::pow(morr_arr(i,j,k,MORRInd::lamg), Real(4.0)) * morr_arr(i,j,k,MORRInd::qg3d) / m_cons2;
1221  morr_arr(i,j,k,MORRInd::ng3d) = morr_arr(i,j,k,MORRInd::n0g) / morr_arr(i,j,k,MORRInd::lamg); // Update number concentration
1222  } else if (morr_arr(i,j,k,MORRInd::lamg) > m_lammaxg) {
1223  morr_arr(i,j,k,MORRInd::lamg) = m_lammaxg;
1224  morr_arr(i,j,k,MORRInd::n0g) = std::pow(morr_arr(i,j,k,MORRInd::lamg), Real(4.0)) * morr_arr(i,j,k,MORRInd::qg3d) / m_cons2;
1225  morr_arr(i,j,k,MORRInd::ng3d) = morr_arr(i,j,k,MORRInd::n0g) / morr_arr(i,j,k,MORRInd::lamg); // Update number concentration
1226  }
1227  }
1228  ////////////////////// First instance of ZERO OUT PROCESS RATES
1229  // Zero out process rates
1230  prc = Real(0); // Cloud water to rain conversion rate (PRC)
1231  nprc = Real(0); // Change in cloud droplet number due to autoconversion (NPRC)
1232  nprc1 = Real(0); // Change in rain number due to autoconversion (NPRC1)
1233  pra = Real(0); // Accretion of cloud water by rain (PRA)
1234  npra = Real(0); // Change in cloud droplet number due to accretion by rain (NPRA)
1235  nragg = Real(0); // Self-collection/breakup of rain (NRAGG)
1236  nsmlts = Real(0); // Loss of snow number during melting (NSMLTS)
1237  nsmltr = Real(0); // Change in rain number due to snow melting (NSMLTR)
1238  evpms = Real(0); // Melting snow evaporation rate (EVPMS)
1239  pcc = Real(0); // Condensation/evaporation of cloud water (PCC)
1240  pre = Real(0); // Evaporation of rain (PRE)
1241  // nsubc = Real(0); // Loss of cloud droplet number during evaporation (NSUBC)
1242  nsubr = Real(0); // Loss of rain number during evaporation (NSUBR)
1243  pracg = Real(0); // Collection of rain by graupel (PRACG)
1244  npracg = Real(0); // Change in number due to collection of rain by graupel (NPRACG)
1245  psmlt = Real(0); // Melting of snow (PSMLT)
1246  pgmlt = Real(0); // Melting of graupel (PGMLT)
1247  evpmg = Real(0); // Evaporation of melting graupel (EVPMG)
1248  pracs = Real(0); // Collection of snow by rain (PRACS)
1249  npracs = Real(0); // Change in number due to collection of snow by rain (NPRACS)
1250  ngmltg = Real(0); // Loss of graupel number during melting (NGMLTG)
1251  ngmltr = Real(0); // Change in rain number due to graupel melting (NGMLTR)
1252 
1253  // CALCULATION OF MICROPHYSICAL PROCESS RATES, T > Real(273.15) K
1254 
1255  // AUTOCONVERSION OF CLOUD LIQUID WATER TO RAIN
1256  // FORMULA FROM BEHENG (1994)
1257  // USING NUMERICAL SIMULATION OF STOCHASTIC COLLECTION EQUATION
1258  // AND INITIAL CLOUD DROPLET SIZE DISTRIBUTION SPECIFIED
1259  // AS A GAMMA DISTRIBUTION
1260 
1261  // USE MINIMUM VALUE OF Real(1.E-6) TO PREVENT FLOATING POINT ERROR
1262 
1263  if (morr_arr(i,j,k,MORRInd::qc3d) >= Real(1.0e-6)) {
1264  // HM ADD 12/13/06, REPLACE WITH NEWER FORMULA
1265  // FROM KHAIROUTDINOV AND KOGAN 2000, MWR
1266  prc = Real(1350.0) * std::pow(morr_arr(i,j,k,MORRInd::qc3d), Real(2.47)) *
1267  std::pow((morr_arr(i,j,k,MORRInd::nc3d)/Real(1.0e6)*morr_arr(i,j,k,MORRInd::rho)), -Real(1.79));
1268 
1269  // note: nprc1 is change in Nr,
1270  // nprc is change in Nc
1271  nprc1 = prc / m_cons29;
1272  nprc = prc / (morr_arr(i,j,k,MORRInd::qc3d) / morr_arr(i,j,k,MORRInd::nc3d));
1273 
1274  // hm bug fix 3/20/12
1275  nprc = std::min(nprc, morr_arr(i,j,k,MORRInd::nc3d) / dt);
1276  nprc1 = std::min(nprc1, nprc);
1277  }
1278 
1279  // HM ADD 12/13/06, COLLECTION OF SNOW BY RAIN ABOVE FREEZING
1280  // FORMULA FROM IKAWA AND SAITO (1991)
1281 
1282  if (morr_arr(i,j,k,MORRInd::qr3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qni3d) >= Real(1.0e-8)) {
1283  Real ums_local = morr_arr(i,j,k,MORRInd::asn) * m_cons3 / std::pow(morr_arr(i,j,k,MORRInd::lams), m_bs);
1284  Real umr_local = morr_arr(i,j,k,MORRInd::arn) * m_cons4 / std::pow(morr_arr(i,j,k,MORRInd::lamr), m_br);
1285  Real uns_local = morr_arr(i,j,k,MORRInd::asn) * m_cons5 / std::pow(morr_arr(i,j,k,MORRInd::lams), m_bs);
1286  Real unr_local = morr_arr(i,j,k,MORRInd::arn) * m_cons6 / std::pow(morr_arr(i,j,k,MORRInd::lamr), m_br);
1287 
1288  // SET REALISTIC LIMITS ON FALLSPEEDS
1289  // bug fix, 10/08/09
1290  dum = std::pow(m_rhosu/morr_arr(i,j,k,MORRInd::rho), Real(0.54));
1291  ums_local = std::min(ums_local, Real(1.2)*dum);
1292  uns_local = std::min(uns_local, Real(1.2)*dum);
1293  umr_local = std::min(umr_local, Real(9.1)*dum);
1294  unr_local = std::min(unr_local, Real(9.1)*dum);
1295 
1296 
1297  // hm fix, 2/12/13
1298  // for above freezing conditions to get accelerated melting of snow,
1299  // we need collection of rain by snow (following Lin et al. 1983)
1300  ////////////////////////Might needstd::pow expanding
1301  pracs = m_cons41 * (std::sqrt(amrex::Math::powi<2>(Real(1.2)*umr_local-Real(0.95)*ums_local) +
1302  Real(0.08)*ums_local*umr_local) * morr_arr(i,j,k,MORRInd::rho) *
1303  morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::n0s) / amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) *
1304  (Real(5.0)/(amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) * morr_arr(i,j,k,MORRInd::lams)) +
1305  Real(2)/(amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamr)) * amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lams))) +
1306  myhalf/(morr_arr(i,j,k,MORRInd::lamr) * amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lams)))));
1307  }
1308  // ADD COLLECTION OF GRAUPEL BY RAIN ABOVE FREEZING
1309  // ASSUME ALL RAIN COLLECTION BY GRAUPEL ABOVE FREEZING IS SHED
1310  // ASSUME SHED DROPS ARE 1 MM IN SIZE
1311 
1312  if (morr_arr(i,j,k,MORRInd::qr3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qg3d) >= Real(1.0e-8)) {
1313 
1314  Real umg_local = morr_arr(i,j,k,MORRInd::agn) * m_cons7 / std::pow(morr_arr(i,j,k,MORRInd::lamg), m_bg);
1315  Real umr_local = morr_arr(i,j,k,MORRInd::arn) * m_cons4 / std::pow(morr_arr(i,j,k,MORRInd::lamr), m_br);
1316  Real ung_local = morr_arr(i,j,k,MORRInd::agn) * m_cons8 / std::pow(morr_arr(i,j,k,MORRInd::lamg), m_bg);
1317  Real unr_local = morr_arr(i,j,k,MORRInd::arn) * m_cons6 / std::pow(morr_arr(i,j,k,MORRInd::lamr), m_br);
1318 
1319  // SET REALISTIC LIMITS ON FALLSPEEDS
1320  // bug fix, 10/08/09
1321  dum = std::pow(m_rhosu/morr_arr(i,j,k,MORRInd::rho), Real(0.54));
1322  umg_local = std::min(umg_local, Real(20.0)*dum);
1323  ung_local = std::min(ung_local, Real(20.0)*dum);
1324  umr_local = std::min(umr_local, Real(9.1)*dum);
1325  unr_local = std::min(unr_local, Real(9.1)*dum);
1326 
1327  // PRACG IS MIXING RATIO OF RAIN PER SEC COLLECTED BY GRAUPEL/HAIL
1328  pracg = m_cons41 * (std::sqrt(amrex::Math::powi<2>(Real(1.2)*umr_local-Real(0.95)*umg_local) +
1329  Real(0.08)*umg_local*umr_local) * morr_arr(i,j,k,MORRInd::rho) *
1330  morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::n0g) / amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) *
1331  (Real(5.0)/(amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) * morr_arr(i,j,k,MORRInd::lamg)) +
1332  Real(2)/(amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamr)) * amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamg))) +
1333  myhalf/(morr_arr(i,j,k,MORRInd::lamr) * amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamg)))));
1334 
1335  // ASSUME 1 MM DROPS ARE SHED, GET NUMBER SHED PER SEC
1336  dum = pracg/Real(5.2e-7);
1337 
1338  npracg = m_cons32 * morr_arr(i,j,k,MORRInd::rho) * (std::sqrt(Real(1.7)*amrex::Math::powi<2>(unr_local-ung_local) +
1339  Real(0.3)*unr_local*ung_local) * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::n0g) *
1340  (one/(amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) * morr_arr(i,j,k,MORRInd::lamg)) +
1341  one/(amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamr)) * amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamg))) +
1342  one/(morr_arr(i,j,k,MORRInd::lamr) * amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamg)))));
1343  // hm 7/15/13, remove limit so that the number of collected drops can smaller than
1344  // number of shed drops
1345  npracg = npracg - dum;
1346  }
1347  // ACCRETION OF CLOUD LIQUID WATER BY RAIN
1348  // CONTINUOUS COLLECTION EQUATION WITH
1349  // GRAVITATIONAL COLLECTION KERNEL, DROPLET FALL SPEED NEGLECTED
1350 
1351  if (morr_arr(i,j,k,MORRInd::qr3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qc3d) >= Real(1.0e-8)) {
1352  // 12/13/06 HM ADD, REPLACE WITH NEWER FORMULA FROM
1353  // KHAIROUTDINOV AND KOGAN 2000, MWR
1354  dum = morr_arr(i,j,k,MORRInd::qc3d) * morr_arr(i,j,k,MORRInd::qr3d);
1355  pra = Real(67.0) * std::pow(dum, Real(1.15));
1356  npra = pra / (morr_arr(i,j,k,MORRInd::qc3d) / morr_arr(i,j,k,MORRInd::nc3d));
1357  }
1358 
1359  // SELF-COLLECTION OF RAIN DROPS
1360  // FROM BEHENG(1994)
1361  // FROM NUMERICAL SIMULATION OF THE STOCHASTIC COLLECTION EQUATION
1362  // AS DESCRIBED ABOVE FOR AUTOCONVERSION
1363 
1364  if (morr_arr(i,j,k,MORRInd::qr3d) >= Real(1.0e-8)) {
1365  // include breakup add 10/09/09
1366  dum1 = Real(300.0e-6);
1367  if (one/morr_arr(i,j,k,MORRInd::lamr) < dum1) {
1368  dum = one;
1369  } else {
1370  dum = Real(2) - std::exp(Real(2300.0) * (one/morr_arr(i,j,k,MORRInd::lamr) - dum1));
1371  }
1372  nragg = -Real(5.78) * dum * morr_arr(i,j,k,MORRInd::nr3d) * morr_arr(i,j,k,MORRInd::qr3d) * morr_arr(i,j,k,MORRInd::rho);
1373  }
1374  // CALCULATE EVAP OF RAIN (RUTLEDGE AND HOBBS 1983)
1375  if (morr_arr(i,j,k,MORRInd::qr3d) >= m_qsmall) {
1376  epsr = Real(2) * m_pi * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::rho) * dv *
1377  (m_f1r/(morr_arr(i,j,k,MORRInd::lamr)*morr_arr(i,j,k,MORRInd::lamr)) +
1378  m_f2r * std::sqrt(morr_arr(i,j,k,MORRInd::arn)*morr_arr(i,j,k,MORRInd::rho)/morr_arr(i,j,k,MORRInd::mu)) *
1379  std::pow(sc_schmidt, one/three) * m_cons9 /
1380  std::pow(morr_arr(i,j,k,MORRInd::lamr), m_cons34));
1381  } else {
1382  epsr = Real(0);
1383  }
1384  // NO CONDENSATION ONTO RAIN, ONLY EVAP ALLOWED
1385  if (morr_arr(i,j,k,MORRInd::qv3d) < qvs) {
1386  pre = epsr * (morr_arr(i,j,k,MORRInd::qv3d) - qvs) / ab;
1387  pre = std::min(pre, Real(0));
1388  } else {
1389  pre = Real(0);
1390  }
1391  // MELTING OF SNOW
1392  // SNOW MAY PERSIST ABOVE FREEZING, FORMULA FROM RUTLEDGE AND HOBBS, 1984
1393  // IF WATER SUPERSATURATION, SNOW MELTS TO FORM RAIN
1394 
1395  if (morr_arr(i,j,k,MORRInd::qni3d) >= Real(1.0e-8)) {
1396  // fix 053011
1397  // HM, MODIFY FOR V3.2, ADD ACCELERATED MELTING DUE TO COLLISION WITH RAIN
1398  dum = -m_cpw/morr_arr(i,j,k,MORRInd::xlf) * (morr_arr(i,j,k,MORRInd::t3d) - Real(273.15)) * pracs;
1399 
1400  // hm fix 1/20/15
1401  psmlt = Real(2) * m_pi * morr_arr(i,j,k,MORRInd::n0s) * kap * (Real(273.15) - morr_arr(i,j,k,MORRInd::t3d)) /
1402  morr_arr(i,j,k,MORRInd::xlf) * (m_f1s/(morr_arr(i,j,k,MORRInd::lams)*morr_arr(i,j,k,MORRInd::lams)) +
1403  m_f2s * std::sqrt(morr_arr(i,j,k,MORRInd::asn)*morr_arr(i,j,k,MORRInd::rho)/morr_arr(i,j,k,MORRInd::mu)) *
1404  std::pow(sc_schmidt, one/three) * m_cons10 /
1405  std::pow(morr_arr(i,j,k,MORRInd::lams), m_cons35)) + dum;
1406 
1407  // IN WATER SUBSATURATION, SNOW MELTS AND EVAPORATES
1408  if (qvqvs < one) {
1409  epss = Real(2) * m_pi * morr_arr(i,j,k,MORRInd::n0s) * morr_arr(i,j,k,MORRInd::rho) * dv *
1410  (m_f1s/(morr_arr(i,j,k,MORRInd::lams)*morr_arr(i,j,k,MORRInd::lams)) +
1411  m_f2s * std::sqrt(morr_arr(i,j,k,MORRInd::asn)*morr_arr(i,j,k,MORRInd::rho)/morr_arr(i,j,k,MORRInd::mu)) *
1412  std::pow(sc_schmidt, one/three) * m_cons10 /
1413  std::pow(morr_arr(i,j,k,MORRInd::lams), m_cons35));
1414 
1415  // hm fix 8/4/08
1416  evpms = (morr_arr(i,j,k,MORRInd::qv3d) - qvs) * epss / ab;
1417  evpms = std::max(evpms, psmlt);
1418  psmlt = psmlt - evpms;
1419  }
1420  }
1421  // MELTING OF GRAUPEL
1422  // GRAUPEL MAY PERSIST ABOVE FREEZING, FORMULA FROM RUTLEDGE AND HOBBS, 1984
1423  // IF WATER SUPERSATURATION, GRAUPEL MELTS TO FORM RAIN
1424 
1425  if (morr_arr(i,j,k,MORRInd::qg3d) >= Real(1.0e-8)) {
1426  // fix 053011
1427  // HM, MODIFY FOR V3.2, ADD ACCELERATED MELTING DUE TO COLLISION WITH RAIN
1428 
1429  dum = -m_cpw/morr_arr(i,j,k,MORRInd::xlf) * (morr_arr(i,j,k,MORRInd::t3d) - Real(273.15)) * pracg;
1430 
1431  // hm fix 1/20/15
1432  pgmlt = Real(2) * m_pi * morr_arr(i,j,k,MORRInd::n0g) * kap * (Real(273.15) - morr_arr(i,j,k,MORRInd::t3d)) /
1433  morr_arr(i,j,k,MORRInd::xlf) * (m_f1s/(morr_arr(i,j,k,MORRInd::lamg)*morr_arr(i,j,k,MORRInd::lamg)) +
1434  m_f2s * std::sqrt(morr_arr(i,j,k,MORRInd::agn)*morr_arr(i,j,k,MORRInd::rho)/morr_arr(i,j,k,MORRInd::mu)) *
1435  std::pow(sc_schmidt, one/three) * m_cons11 /
1436  std::pow(morr_arr(i,j,k,MORRInd::lamg), m_cons36)) + dum;
1437 
1438  // IN WATER SUBSATURATION, GRAUPEL MELTS AND EVAPORATES
1439  if (qvqvs < one) {
1440  epsg = Real(2) * m_pi * morr_arr(i,j,k,MORRInd::n0g) * morr_arr(i,j,k,MORRInd::rho) * dv *
1441  (m_f1s/(morr_arr(i,j,k,MORRInd::lamg)*morr_arr(i,j,k,MORRInd::lamg)) +
1442  m_f2s * std::sqrt(morr_arr(i,j,k,MORRInd::agn)*morr_arr(i,j,k,MORRInd::rho)/morr_arr(i,j,k,MORRInd::mu)) *
1443  std::pow(sc_schmidt, one/three) * m_cons11 /
1444  std::pow(morr_arr(i,j,k,MORRInd::lamg), m_cons36));
1445 
1446  // hm fix 8/4/08
1447  evpmg = (morr_arr(i,j,k,MORRInd::qv3d) - qvs) * epsg / ab;
1448  evpmg = std::max(evpmg, pgmlt);
1449  pgmlt = pgmlt - evpmg;
1450  }
1451  }
1452  // HM, V3.2
1453  // RESET PRACG AND PRACS TO ZERO, THIS IS DONE BECAUSE THERE IS NO
1454  // TRANSFER OF MASS FROM SNOW AND GRAUPEL TO RAIN DIRECTLY FROM COLLECTION
1455  // ABOVE FREEZING, IT IS ONLY USED FOR ENHANCEMENT OF MELTING AND SHEDDING
1456 
1457  pracg = Real(0);
1458  pracs = Real(0);
1459  // CONSERVATION OF QC
1460  dum = (prc + pra) * dt;
1461 
1462  if (dum > morr_arr(i,j,k,MORRInd::qc3d) && morr_arr(i,j,k,MORRInd::qc3d) >= m_qsmall) {
1463  ratio = morr_arr(i,j,k,MORRInd::qc3d) / dum;
1464  prc = prc * ratio;
1465  pra = pra * ratio;
1466  }
1467 
1468  // CONSERVATION OF SNOW
1469  dum = (-psmlt - evpms + pracs) * dt;
1470 
1471  if (dum > morr_arr(i,j,k,MORRInd::qni3d) && morr_arr(i,j,k,MORRInd::qni3d) >= m_qsmall) {
1472  // NO SOURCE TERMS FOR SNOW AT T > FREEZING
1473  ratio = morr_arr(i,j,k,MORRInd::qni3d) / dum;
1474  psmlt = psmlt * ratio;
1475  evpms = evpms * ratio;
1476  pracs = pracs * ratio;
1477  }
1478 
1479  // CONSERVATION OF GRAUPEL
1480  dum = (-pgmlt - evpmg + pracg) * dt;
1481 
1482  if (dum > morr_arr(i,j,k,MORRInd::qg3d) && morr_arr(i,j,k,MORRInd::qg3d) >= m_qsmall) {
1483  // NO SOURCE TERM FOR GRAUPEL ABOVE FREEZING
1484  ratio = morr_arr(i,j,k,MORRInd::qg3d) / dum;
1485  pgmlt = pgmlt * ratio;
1486  evpmg = evpmg * ratio;
1487  pracg = pracg * ratio;
1488  }
1489 
1490  // CONSERVATION OF QR
1491  // HM 12/13/06, ADDED CONSERVATION OF RAIN SINCE PRE IS NEGATIVE
1492 
1493  dum = (-pracs - pracg - pre - pra - prc + psmlt + pgmlt) * dt;
1494 
1495  if (dum > morr_arr(i,j,k,MORRInd::qr3d) && morr_arr(i,j,k,MORRInd::qr3d) >= m_qsmall) {
1496  ratio = (morr_arr(i,j,k,MORRInd::qr3d)/dt + pracs + pracg + pra + prc - psmlt - pgmlt) / (-pre);
1497  pre = pre * ratio;
1498  }
1499  // Update tendencies
1500  morr_arr(i,j,k,MORRInd::qv3dten) = morr_arr(i,j,k,MORRInd::qv3dten) + (-pre - evpms - evpmg);
1501 
1502  morr_arr(i,j,k,MORRInd::t3dten) = morr_arr(i,j,k,MORRInd::t3dten) + (pre * morr_arr(i,j,k,MORRInd::xxlv) +
1503  (evpms + evpmg) * morr_arr(i,j,k,MORRInd::xxls) +
1504  (psmlt + pgmlt - pracs - pracg) * morr_arr(i,j,k,MORRInd::xlf)) / morr_arr(i,j,k,MORRInd::cpm);
1505 
1506  morr_arr(i,j,k,MORRInd::qc3dten) = morr_arr(i,j,k,MORRInd::qc3dten) + (-pra - prc);
1507  morr_arr(i,j,k,MORRInd::qr3dten) = morr_arr(i,j,k,MORRInd::qr3dten) + (pre + pra + prc - psmlt - pgmlt + pracs + pracg);
1508  morr_arr(i,j,k,MORRInd::qni3dten) = morr_arr(i,j,k,MORRInd::qni3dten) + (psmlt + evpms - pracs);
1509  morr_arr(i,j,k,MORRInd::qg3dten) = morr_arr(i,j,k,MORRInd::qg3dten) + (pgmlt + evpmg - pracg);
1510 
1511  // fix 053011
1512  // HM, bug fix 5/12/08, npracg is subtracted from nr not ng
1513  morr_arr(i,j,k,MORRInd::nc3dten) = morr_arr(i,j,k,MORRInd::nc3dten) + (-npra - nprc);
1514  morr_arr(i,j,k,MORRInd::nr3dten) = morr_arr(i,j,k,MORRInd::nr3dten) + (nprc1 + nragg - npracg);
1515 
1516  // HM ADD, WRF-CHEM, ADD TENDENCIES FOR C2PREC
1517  // c2prec = pra + prc;
1518 
1519  if (pre < Real(0)) {
1520  dum = pre * dt / morr_arr(i,j,k,MORRInd::qr3d);
1521  dum = std::max(-one, dum);
1522  nsubr = dum * morr_arr(i,j,k,MORRInd::nr3d) / dt;
1523  }
1524 
1525  if (evpms + psmlt < Real(0)) {
1526  dum = (evpms + psmlt) * dt / morr_arr(i,j,k,MORRInd::qni3d);
1527  dum = std::max(-one, dum);
1528  nsmlts = dum * morr_arr(i,j,k,MORRInd::ns3d) / dt;
1529  }
1530 
1531  if (psmlt < Real(0)) {
1532  dum = psmlt * dt / morr_arr(i,j,k,MORRInd::qni3d);
1533  dum = std::max(-one, dum);
1534  nsmltr = dum * morr_arr(i,j,k,MORRInd::ns3d) / dt;
1535  }
1536 
1537  if (evpmg + pgmlt < Real(0)) {
1538  dum = (evpmg + pgmlt) * dt / morr_arr(i,j,k,MORRInd::qg3d);
1539  dum = std::max(-one, dum);
1540  ngmltg = dum * morr_arr(i,j,k,MORRInd::ng3d) / dt;
1541  }
1542 
1543  if (pgmlt < Real(0)) {
1544  dum = pgmlt * dt / morr_arr(i,j,k,MORRInd::qg3d);
1545  dum = std::max(-one, dum);
1546  ngmltr = dum * morr_arr(i,j,k,MORRInd::ng3d) / dt;
1547  }
1548 
1549  morr_arr(i,j,k,MORRInd::ns3dten) = morr_arr(i,j,k,MORRInd::ns3dten) + nsmlts;
1550  morr_arr(i,j,k,MORRInd::ng3dten) = morr_arr(i,j,k,MORRInd::ng3dten) + ngmltg;
1551  morr_arr(i,j,k,MORRInd::nr3dten) = morr_arr(i,j,k,MORRInd::nr3dten) + (nsubr - nsmltr - ngmltr);
1552 
1553  }
1554  //Right after 300 CONTINUE
1555 // label_300:
1556  if (do_cond) {
1557  // Calculate saturation adjustment to condense extra vapor above water saturation
1558  dumt = morr_arr(i,j,k,MORRInd::t3d) + dt * morr_arr(i,j,k,MORRInd::t3dten);
1559  dumqv = morr_arr(i,j,k,MORRInd::qv3d) + dt * morr_arr(i,j,k,MORRInd::qv3dten);
1560 
1561  // Fix for low pressure (added 5/12/10)
1562  dum = std::min(Real(0.99) * morr_arr(i,j,k,MORRInd::pres), calc_saturation_vapor_pressure(dumt, 0));
1563  dumqss = m_ep_2 * dum / (morr_arr(i,j,k,MORRInd::pres) - dum);
1564  dumqc = morr_arr(i,j,k,MORRInd::qc3d) + dt * morr_arr(i,j,k,MORRInd::qc3dten);
1565  dumqc = std::max(dumqc, Real(0));
1566 
1567  // Saturation adjustment for liquid
1568  dums = dumqv - dumqss;
1569  pcc = dums / (one + amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::xxlv)) * dumqss / (morr_arr(i,j,k,MORRInd::cpm) * m_Rv * amrex::Math::powi<2>(dumt))) / dt;
1570  if (pcc * dt + dumqc < Real(0)) {
1571  pcc = -dumqc / dt;
1572  }
1573 
1574  // Update tendencies
1575  morr_arr(i,j,k,MORRInd::qv3dten) -= pcc;
1576  morr_arr(i,j,k,MORRInd::t3dten) += pcc * morr_arr(i,j,k,MORRInd::xxlv) / morr_arr(i,j,k,MORRInd::cpm);
1577  morr_arr(i,j,k,MORRInd::qc3dten) += pcc;
1578  }
1579  } else { //cold
1580  //......................................................................
1581  // ALLOW FOR CONSTANT DROPLET NUMBER
1582  // INUM = 0, PREDICT DROPLET NUMBER
1583  // INUM = 1, SET CONSTANT DROPLET NUMBER
1584 
1585  if (m_inum == 1) {
1586  // CONVERT NDCNST FROM CM-3 TO KG-1
1587  morr_arr(i,j,k,MORRInd::nc3d) =
1588  ndcnst_to_number_mixing_ratio(m_ndcnst, rho_arr(i,j,k));
1589  }
1590 
1591  morr_arr(i,j,k,MORRInd::ni3d) = amrex::max(Real(0),morr_arr(i,j,k,MORRInd::ni3d));
1592  morr_arr(i,j,k,MORRInd::ns3d) = amrex::max(Real(0),morr_arr(i,j,k,MORRInd::ns3d));
1593  morr_arr(i,j,k,MORRInd::nc3d) = amrex::max(Real(0),morr_arr(i,j,k,MORRInd::nc3d));
1594  morr_arr(i,j,k,MORRInd::nr3d) = amrex::max(Real(0),morr_arr(i,j,k,MORRInd::nr3d));
1595  morr_arr(i,j,k,MORRInd::ng3d) = amrex::max(Real(0),morr_arr(i,j,k,MORRInd::ng3d));
1596 
1597  // ========================================================================
1598  // USING WRF APPROACH FOR SIZE DISTRIBUTION PARAMETERS
1599  // ========================================================================
1600  // Rain
1601  if (morr_arr(i,j,k,MORRInd::qr3d) >= m_qsmall) {
1602  // Calculate lambda parameter using cons26 (pi*rhow/6)
1603  morr_arr(i,j,k,MORRInd::lamr) = std::pow(m_pi * m_rhow * morr_arr(i,j,k,MORRInd::nr3d) / morr_arr(i,j,k,MORRInd::qr3d), one/three);
1604 
1605  // Check for slope and adjust vars
1606  if (morr_arr(i,j,k,MORRInd::lamr) < m_lamminr) {
1607  morr_arr(i,j,k,MORRInd::lamr) = m_lamminr;
1608  morr_arr(i,j,k,MORRInd::n0r) = std::pow(morr_arr(i,j,k,MORRInd::lamr), Real(4.0)) * morr_arr(i,j,k,MORRInd::qr3d) / (m_pi * m_rhow);
1609  morr_arr(i,j,k,MORRInd::nr3d) = morr_arr(i,j,k,MORRInd::n0r) / morr_arr(i,j,k,MORRInd::lamr); // Update number concentration
1610  } else if (morr_arr(i,j,k,MORRInd::lamr) > m_lammaxr) {
1611  morr_arr(i,j,k,MORRInd::lamr) = m_lammaxr;
1612  morr_arr(i,j,k,MORRInd::n0r) = std::pow(morr_arr(i,j,k,MORRInd::lamr), Real(4.0)) * morr_arr(i,j,k,MORRInd::qr3d) / (m_pi * m_rhow);
1613  morr_arr(i,j,k,MORRInd::nr3d) = morr_arr(i,j,k,MORRInd::n0r) / morr_arr(i,j,k,MORRInd::lamr); // Update number concentration
1614  } else {
1615  // Calculate intercept parameter using WRF formula
1616  morr_arr(i,j,k,MORRInd::n0r) = std::pow(morr_arr(i,j,k,MORRInd::lamr), Real(4.0)) * morr_arr(i,j,k,MORRInd::qr3d) / (m_pi * m_rhow);
1617  }
1618  }
1619 
1620 
1621  // Cloud droplets
1622  if (morr_arr(i,j,k,MORRInd::qc3d) >= m_qsmall) {
1623  // Calculate air density factor (moist air density)
1624  dum = morr_arr(i,j,k,MORRInd::pres)/(Real(287.15)*morr_arr(i,j,k,MORRInd::t3d));
1625 
1626  // MARTIN ET AL. (1994) FORMULA FOR PGAM (WRF implementation)
1627  morr_arr(i,j,k,MORRInd::pgam) = Real(0.0005714)*(morr_arr(i,j,k,MORRInd::nc3d)/Real(1.0e6)*dum) + Real(0.2714);
1628  morr_arr(i,j,k,MORRInd::pgam) = one/(amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::pgam))) - one;
1629  morr_arr(i,j,k,MORRInd::pgam) = amrex::max(morr_arr(i,j,k,MORRInd::pgam), Real(2));
1630  morr_arr(i,j,k,MORRInd::pgam) = amrex::min(morr_arr(i,j,k,MORRInd::pgam), Real(10.0));
1631 
1632  // Calculate gamma function values
1633  Real gamma_pgam_plus_1 = gamma_function(morr_arr(i,j,k,MORRInd::pgam) + one);
1634  Real gamma_pgam_plus_4 = gamma_function(morr_arr(i,j,k,MORRInd::pgam) + Real(4.0));
1635 
1636  // Calculate lambda parameter
1637  morr_arr(i,j,k,MORRInd::lamc) = std::pow((m_cons26 * morr_arr(i,j,k,MORRInd::nc3d) * gamma_pgam_plus_4) / (morr_arr(i,j,k,MORRInd::qc3d) * gamma_pgam_plus_1), one/three);
1638 
1639  // Lambda bounds from WRF - 60 micron max diameter, 1 micron min diameter
1640  Real lambda_min = (morr_arr(i,j,k,MORRInd::pgam) + one)/Real(60.0e-6);
1641  Real lambda_max = (morr_arr(i,j,k,MORRInd::pgam) + one)/Real(1.0e-6);
1642 
1643  // Check bounds and update number concentration if needed
1644  if (morr_arr(i,j,k,MORRInd::lamc) < lambda_min) {
1645  morr_arr(i,j,k,MORRInd::lamc) = lambda_min;
1646  // Update cloud droplet number using the same formula as in WRF
1647  morr_arr(i,j,k,MORRInd::nc3d) = std::exp(three*std::log(morr_arr(i,j,k,MORRInd::lamc)) + std::log(morr_arr(i,j,k,MORRInd::qc3d)) +
1648  std::log(gamma_pgam_plus_1) - std::log(gamma_pgam_plus_4))/ m_cons26;
1649  } else if (morr_arr(i,j,k,MORRInd::lamc) > lambda_max) {
1650  morr_arr(i,j,k,MORRInd::lamc) = lambda_max;
1651  // Update cloud droplet number using the same formula as in WRF
1652  morr_arr(i,j,k,MORRInd::nc3d) = std::exp(three*std::log(morr_arr(i,j,k,MORRInd::lamc)) + std::log(morr_arr(i,j,k,MORRInd::qc3d)) +
1653  std::log(gamma_pgam_plus_1) - std::log(gamma_pgam_plus_4))/ m_cons26;
1654  }
1655 
1656  // Calculate intercept parameter
1657  morr_arr(i,j,k,MORRInd::cdist1) = morr_arr(i,j,k,MORRInd::nc3d) / gamma_pgam_plus_1;
1658  }
1659 
1660  // Snow
1661  if (morr_arr(i,j,k,MORRInd::qni3d) >= m_qsmall) {
1662  // Calculate lambda parameter
1663  morr_arr(i,j,k,MORRInd::lams) = std::pow(m_cons1 * morr_arr(i,j,k,MORRInd::ns3d) / morr_arr(i,j,k,MORRInd::qni3d), one/ds0);
1664 
1665  // Calculate intercept parameter
1666  morr_arr(i,j,k,MORRInd::n0s) = morr_arr(i,j,k,MORRInd::ns3d) * morr_arr(i,j,k,MORRInd::lams);
1667 
1668  // Check for slope and adjust vars
1669  if (morr_arr(i,j,k,MORRInd::lams) < m_lammins) {
1670  morr_arr(i,j,k,MORRInd::lams) = m_lammins;
1671  morr_arr(i,j,k,MORRInd::n0s) = std::pow(morr_arr(i,j,k,MORRInd::lams), Real(4.0)) * morr_arr(i,j,k,MORRInd::qni3d) / m_cons1;
1672  morr_arr(i,j,k,MORRInd::ns3d) = morr_arr(i,j,k,MORRInd::n0s) / morr_arr(i,j,k,MORRInd::lams); // Update number concentration
1673  } else if (morr_arr(i,j,k,MORRInd::lams) > m_lammaxs) {
1674  morr_arr(i,j,k,MORRInd::lams) = m_lammaxs;
1675  morr_arr(i,j,k,MORRInd::n0s) = std::pow(morr_arr(i,j,k,MORRInd::lams), Real(4.0)) * morr_arr(i,j,k,MORRInd::qni3d) / m_cons1;
1676  morr_arr(i,j,k,MORRInd::ns3d) = morr_arr(i,j,k,MORRInd::n0s) / morr_arr(i,j,k,MORRInd::lams); // Update number concentration
1677  }
1678  }
1679 
1680  // Cloud ice
1681  if (morr_arr(i,j,k,MORRInd::qi3d) >= m_qsmall) {
1682  // Calculate lambda parameter
1683  morr_arr(i,j,k,MORRInd::lami) = std::pow(m_cons12 * morr_arr(i,j,k,MORRInd::ni3d) / morr_arr(i,j,k,MORRInd::qi3d), one/three);
1684 
1685  // Calculate intercept parameter (initial calculation)
1686  morr_arr(i,j,k,MORRInd::n0i) = morr_arr(i,j,k,MORRInd::ni3d) * morr_arr(i,j,k,MORRInd::lami);
1687 
1688  // Check for slope (apply bounds)
1689  if (morr_arr(i,j,k,MORRInd::lami) < m_lammini) {
1690  morr_arr(i,j,k,MORRInd::lami) = m_lammini;
1691  // Recalculate morr_arr(i,j,k,MORRInd::n0i) when lambda is adjusted
1692  morr_arr(i,j,k,MORRInd::n0i) = std::pow(morr_arr(i,j,k,MORRInd::lami), Real(4.0)) * morr_arr(i,j,k,MORRInd::qi3d) / m_cons12;
1693  // Update ni3d when lambda is adjusted
1694  morr_arr(i,j,k,MORRInd::ni3d) = morr_arr(i,j,k,MORRInd::n0i) / morr_arr(i,j,k,MORRInd::lami);
1695  } else if (morr_arr(i,j,k,MORRInd::lami) > m_lammaxi) {
1696  morr_arr(i,j,k,MORRInd::lami) = m_lammaxi;
1697  // Recalculate morr_arr(i,j,k,MORRInd::n0i) when lambda is adjusted
1698  morr_arr(i,j,k,MORRInd::n0i) = std::pow(morr_arr(i,j,k,MORRInd::lami), Real(4.0)) * morr_arr(i,j,k,MORRInd::qi3d) / m_cons12;
1699  // Update ni3d when lambda is adjusted
1700  morr_arr(i,j,k,MORRInd::ni3d) = morr_arr(i,j,k,MORRInd::n0i) / morr_arr(i,j,k,MORRInd::lami);
1701  }
1702  }
1703  // Graupel
1704  if (morr_arr(i,j,k,MORRInd::qg3d) >= m_qsmall) {
1705  // Calculate lambda parameter
1706  morr_arr(i,j,k,MORRInd::lamg) = std::pow(m_cons2 * morr_arr(i,j,k,MORRInd::ng3d) / morr_arr(i,j,k,MORRInd::qg3d), one/dg0);
1707 
1708  // Calculate intercept parameter
1709  morr_arr(i,j,k,MORRInd::n0g) = morr_arr(i,j,k,MORRInd::ng3d) * morr_arr(i,j,k,MORRInd::lamg);
1710 
1711  // Check for slope and adjust vars
1712  if (morr_arr(i,j,k,MORRInd::lamg) < m_lamming) {
1713  morr_arr(i,j,k,MORRInd::lamg) = m_lamming;
1714  morr_arr(i,j,k,MORRInd::n0g) = std::pow(morr_arr(i,j,k,MORRInd::lamg), Real(4.0)) * morr_arr(i,j,k,MORRInd::qg3d) / m_cons2;
1715  morr_arr(i,j,k,MORRInd::ng3d) = morr_arr(i,j,k,MORRInd::n0g) / morr_arr(i,j,k,MORRInd::lamg); // Update number concentration
1716  } else if (morr_arr(i,j,k,MORRInd::lamg) > m_lammaxg) {
1717  morr_arr(i,j,k,MORRInd::lamg) = m_lammaxg;
1718  morr_arr(i,j,k,MORRInd::n0g) = std::pow(morr_arr(i,j,k,MORRInd::lamg), Real(4.0)) * morr_arr(i,j,k,MORRInd::qg3d) / m_cons2;
1719  morr_arr(i,j,k,MORRInd::ng3d) = morr_arr(i,j,k,MORRInd::n0g) / morr_arr(i,j,k,MORRInd::lamg); // Update number concentration
1720  }
1721  }
1722  ////////////////////// Second instance of ZERO OUT PROCESS RATES
1723  // Zero out process rates
1724  mnuccc = Real(0); // Change Q due to contact freezing droplets (MNUCCC)
1725  nnuccc = Real(0); // Change N due to contact freezing droplets (NNUCCC)
1726  prc = Real(0); // Autoconversion droplets (PRC)
1727  nprc = Real(0); // Change NC autoconversion droplets (NPRC)
1728  nprc1 = Real(0); // Change NR autoconversion droplets (NPRC1)
1729  nsagg = Real(0); // Self-collection of snow (NSAGG)
1730  psacws = Real(0); // Change Q droplet accretion by snow (PSACWS)
1731  npsacws = Real(0); // Change N droplet accretion by snow (NPSACWS)
1732  psacwi = Real(0); // Change Q droplet accretion by cloud ice (PSACWI)
1733  npsacwi = Real(0); // Change N droplet accretion by cloud ice (NPSACWI)
1734  pracs = Real(0); // Change Q rain-snow collection (PRACS)
1735  npracs = Real(0); // Change N rain-snow collection (NPRACS)
1736  nmults = Real(0); // Ice multiplication due to riming droplets by snow (NMULTS)
1737  qmults = Real(0); // Change Q due to ice multiplication droplets/snow (QMULTS)
1738  nmultr = Real(0); // Ice multiplication due to riming rain by snow (NMULTR)
1739  qmultr = Real(0); // Change Q due to ice multiplication rain/snow (QMULTR)
1740  nmultg = Real(0); // Ice multiplication due to accretion droplets by graupel (NMULTG)
1741  qmultg = Real(0); // Change Q due to ice multiplication droplets/graupel (QMULTG)
1742  nmultrg = Real(0); // Ice multiplication due to accretion rain by graupel (NMULTRG)
1743  qmultrg = Real(0); // Change Q due to ice multiplication rain/graupel (QMULTRG)
1744  mnuccr = Real(0); // Change Q due to contact freezing rain (MNUCCR)
1745  nnuccr = Real(0); // Change N due to contact freezing rain (NNUCCR)
1746  pra = Real(0); // Accretion droplets by rain (PRA)
1747  npra = Real(0); // Change N due to droplet accretion by rain (NPRA)
1748  nragg = Real(0); // Self-collection/breakup of rain (NRAGG)
1749  prci = Real(0); // Change Q autoconversion cloud ice to snow (PRCI)
1750  nprci = Real(0); // Change N autoconversion cloud ice by snow (NPRCI)
1751  prai = Real(0); // Change Q accretion cloud ice by snow (PRAI)
1752  nprai = Real(0); // Change N accretion cloud ice (NPRAI)
1753  nnuccd = Real(0); // Change N freezing aerosol (primary ice nucleation) (NNUCCD)
1754  mnuccd = Real(0); // Change Q freezing aerosol (primary ice nucleation) (MNUCCD)
1755  pcc = Real(0); // Condensation/evaporation droplets (PCC)
1756  pre = Real(0); // Evaporation of rain (PRE)
1757  prd = Real(0); // Deposition cloud ice (PRD)
1758  prds = Real(0); // Deposition snow (PRDS)
1759  eprd = Real(0); // Sublimation cloud ice (EPRD)
1760  eprds = Real(0); // Sublimation snow (EPRDS)
1761  // nsubc = Real(0); // Loss of NC during evaporation (NSUBC)
1762  nsubi = Real(0); // Loss of NI during sublimation (NSUBI)
1763  nsubs = Real(0); // Loss of NS during sublimation (NSUBS)
1764  nsubr = Real(0); // Loss of NR during evaporation (NSUBR)
1765  piacr = Real(0); // Change QR, ice-rain collection (PIACR)
1766  niacr = Real(0); // Change N, ice-rain collection (NIACR)
1767  praci = Real(0); // Change QI, ice-rain collection (PRACI)
1768  piacrs = Real(0); // Change QR, ice rain collision, added to snow (PIACRS)
1769  niacrs = Real(0); // Change N, ice rain collision, added to snow (NIACRS)
1770  pracis = Real(0); // Change QI, ice rain collision, added to snow (PRACIS)
1771 
1772  // Graupel processes
1773  pracg = Real(0); // Change in Q collection rain by graupel (PRACG)
1774  psacr = Real(0); // Conversion due to collection of snow by rain (PSACR)
1775  psacwg = Real(0); // Change in Q collection droplets by graupel (PSACWG)
1776  pgsacw = Real(0); // Conversion Q to graupel due to collection droplets by snow (PGSACW)
1777  pgracs = Real(0); // Conversion Q to graupel due to collection rain by snow (PGRACS)
1778  prdg = Real(0); // Deposition of graupel (PRDG)
1779  eprdg = Real(0); // Sublimation of graupel (EPRDG)
1780  npracg = Real(0); // Change N collection rain by graupel (NPRACG)
1781  npsacwg = Real(0); // Change N collection droplets by graupel (NPSACWG)
1782  nscng = Real(0); // Change N conversion to graupel due to collection droplets by snow (NSCNG)
1783  ngracs = Real(0); // Change N conversion to graupel due to collection rain by snow (NGRACS)
1784  nsubg = Real(0); // Change N sublimation/deposition of graupel (NSUBG)
1785 
1786  ////////////////////// CALCULATION OF MICROPHYSICAL PROCESS RATES
1787  // FREEZING OF CLOUD DROPLETS - ONLY ALLOWED BELOW -4C
1788  if (morr_arr(i,j,k,MORRInd::qc3d) >= m_qsmall && morr_arr(i,j,k,MORRInd::t3d) < Real(269.15)) {
1789  // NUMBER OF CONTACT NUCLEI (M^-3) FROM MEYERS ET AL., 1992
1790  // FACTOR OF 1000 IS TO CONVERT FROM L^-1 TO M^-3
1791  // MEYERS CURVE
1792  Real nacnt = std::exp(-Real(2.80) + Real(0.262) * (Real(273.15) - morr_arr(i,j,k,MORRInd::t3d))) * Real(1000.0);
1793 
1794  // MEAN FREE PATH
1795  dum = Real(7.37) * morr_arr(i,j,k,MORRInd::t3d) / (Real(288.0) * Real(10.0) * morr_arr(i,j,k,MORRInd::pres)) / Real(100.0);
1796 
1797  // EFFECTIVE DIFFUSIVITY OF CONTACT NUCLEI
1798  // BASED ON BROWNIAN DIFFUSION
1799  Real dap = m_cons37 * morr_arr(i,j,k,MORRInd::t3d) * (one + dum / m_rin) / morr_arr(i,j,k,MORRInd::mu);
1800 
1801  // CONTACT FREEZING
1802  mnuccc = m_cons38 * dap * nacnt * std::exp(std::log(morr_arr(i,j,k,MORRInd::cdist1)) +
1803  std::log(gamma_function(morr_arr(i,j,k,MORRInd::pgam) + Real(5.0))) - Real(4.0) * std::log(morr_arr(i,j,k,MORRInd::lamc)));
1804  nnuccc = Real(2) * m_pi * dap * nacnt * morr_arr(i,j,k,MORRInd::cdist1) *
1805  gamma_function(morr_arr(i,j,k,MORRInd::pgam) + Real(2)) / morr_arr(i,j,k,MORRInd::lamc);
1806 
1807  // IMMERSION FREEZING (BIGG 1953)
1808  // hm 7/15/13 fix for consistency w/ original formula
1809  mnuccc = mnuccc + m_cons39 *
1810  std::exp(std::log(morr_arr(i,j,k,MORRInd::cdist1)) + std::log(gamma_function(Real(7.0) + morr_arr(i,j,k,MORRInd::pgam))) - Real(6.0) * std::log(morr_arr(i,j,k,MORRInd::lamc))) *
1811  (std::exp(m_aimm * (Real(273.15) - morr_arr(i,j,k,MORRInd::t3d))) - one);
1812 
1813  nnuccc = nnuccc +
1814  m_cons40 * std::exp(std::log(morr_arr(i,j,k,MORRInd::cdist1)) + std::log(gamma_function(morr_arr(i,j,k,MORRInd::pgam) + Real(4.0))) - three * std::log(morr_arr(i,j,k,MORRInd::lamc))) *
1815  (std::exp(m_aimm * (Real(273.15) - morr_arr(i,j,k,MORRInd::t3d))) - one);
1816 
1817  // PUT IN A CATCH HERE TO PREVENT DIVERGENCE BETWEEN NUMBER CONC. AND
1818  // MIXING RATIO, SINCE STRICT CONSERVATION NOT CHECKED FOR NUMBER CONC
1819  nnuccc = std::min(nnuccc, morr_arr(i,j,k,MORRInd::nc3d) / dt);
1820  }
1821 
1822  // AUTOCONVERSION OF CLOUD LIQUID WATER TO RAIN
1823  // FORMULA FROM BEHENG (1994)
1824  // USING NUMERICAL SIMULATION OF STOCHASTIC COLLECTION EQUATION
1825  // AND INITIAL CLOUD DROPLET SIZE DISTRIBUTION SPECIFIED
1826  // AS A GAMMA DISTRIBUTION
1827 
1828  // USE MINIMUM VALUE OF Real(1.E-6) TO PREVENT FLOATING POINT ERROR
1829  if (morr_arr(i,j,k,MORRInd::qc3d) >= Real(1.0e-6)) {
1830  // hm add 12/13/06, replace with newer formula
1831  // from khairoutdinov and kogan 2000, mwr
1832  prc = Real(1350.0) * std::pow(morr_arr(i,j,k,MORRInd::qc3d), Real(2.47)) *
1833  std::pow((morr_arr(i,j,k,MORRInd::nc3d) / Real(1.0e6) * morr_arr(i,j,k,MORRInd::rho)), -Real(1.79));
1834 
1835  // note: nprc1 is change in nr,
1836  // nprc is change in nc
1837  nprc1 = prc / m_cons29;
1838  nprc = prc / (morr_arr(i,j,k,MORRInd::qc3d) / morr_arr(i,j,k,MORRInd::nc3d));
1839 
1840  // hm bug fix 3/20/12
1841  nprc = std::min(nprc, morr_arr(i,j,k,MORRInd::nc3d) / dt);
1842  nprc1 = std::min(nprc1, nprc);
1843  }
1844  // SNOW AGGREGATION FROM PASSARELLI, 1978, USED BY REISNER, 1998
1845  // THIS IS HARD-WIRED FOR BS = Real(0.4) FOR NOW
1846  if (morr_arr(i,j,k,MORRInd::qni3d) >= Real(1.0e-8)) {
1847  nsagg = m_cons15 * morr_arr(i,j,k,MORRInd::asn) * std::pow(morr_arr(i,j,k,MORRInd::rho), ((Real(2) + m_bs) / three)) *
1848  std::pow(morr_arr(i,j,k,MORRInd::qni3d), ((Real(2) + m_bs) / three)) *
1849  std::pow((morr_arr(i,j,k,MORRInd::ns3d) * morr_arr(i,j,k,MORRInd::rho)), ((Real(4.0) - m_bs) / three)) / morr_arr(i,j,k,MORRInd::rho);
1850  }
1851 
1852  // ACCRETION OF CLOUD DROPLETS ONTO SNOW/GRAUPEL
1853  // HERE USE CONTINUOUS COLLECTION EQUATION WITH
1854  // SIMPLE GRAVITATIONAL COLLECTION KERNEL IGNORING
1855 
1856  // SNOW
1857  if (morr_arr(i,j,k,MORRInd::qni3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qc3d) >= m_qsmall) {
1858  psacws = m_cons13 * morr_arr(i,j,k,MORRInd::asn) * morr_arr(i,j,k,MORRInd::qc3d) * morr_arr(i,j,k,MORRInd::rho) *
1859  morr_arr(i,j,k,MORRInd::n0s) / std::pow(morr_arr(i,j,k,MORRInd::lams), (m_bs + three));
1860 
1861  npsacws = m_cons13 * morr_arr(i,j,k,MORRInd::asn) * morr_arr(i,j,k,MORRInd::nc3d) * morr_arr(i,j,k,MORRInd::rho) *
1862  morr_arr(i,j,k,MORRInd::n0s) / std::pow(morr_arr(i,j,k,MORRInd::lams), (m_bs + three));
1863  }
1864 
1865  // COLLECTION OF CLOUD WATER BY GRAUPEL
1866  if (morr_arr(i,j,k,MORRInd::qg3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qc3d) >= m_qsmall) {
1867  psacwg = m_cons14 * morr_arr(i,j,k,MORRInd::agn) * morr_arr(i,j,k,MORRInd::qc3d) * morr_arr(i,j,k,MORRInd::rho) *
1868  morr_arr(i,j,k,MORRInd::n0g) / std::pow(morr_arr(i,j,k,MORRInd::lamg), (m_bg + three));
1869 
1870  npsacwg = m_cons14 * morr_arr(i,j,k,MORRInd::agn) * morr_arr(i,j,k,MORRInd::nc3d) * morr_arr(i,j,k,MORRInd::rho) *
1871  morr_arr(i,j,k,MORRInd::n0g) / std::pow(morr_arr(i,j,k,MORRInd::lamg), (m_bg + three));
1872  }
1873  // hm, add 12/13/06
1874  // CLOUD ICE COLLECTING DROPLETS, ASSUME THAT CLOUD ICE MEAN DIAM > 100 MICRON
1875  // BEFORE RIMING CAN OCCUR
1876  // ASSUME THAT RIME COLLECTED ON CLOUD ICE DOES NOT LEAD
1877  // TO HALLET-MOSSOP SPLINTERING
1878  if (morr_arr(i,j,k,MORRInd::qi3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qc3d) >= m_qsmall) {
1879  // PUT IN SIZE DEPENDENT COLLECTION EFFICIENCY BASED ON STOKES LAW
1880  // FROM THOMPSON ET AL. 2004, MWR
1881  if (one / morr_arr(i,j,k,MORRInd::lami) >= Real(100.0e-6)) {
1882  psacwi = m_cons16 * morr_arr(i,j,k,MORRInd::ain) * morr_arr(i,j,k,MORRInd::qc3d) * morr_arr(i,j,k,MORRInd::rho) *
1883  morr_arr(i,j,k,MORRInd::n0i) / std::pow(morr_arr(i,j,k,MORRInd::lami), (m_bi + three));
1884 
1885  npsacwi = m_cons16 * morr_arr(i,j,k,MORRInd::ain) * morr_arr(i,j,k,MORRInd::nc3d) * morr_arr(i,j,k,MORRInd::rho) *
1886  morr_arr(i,j,k,MORRInd::n0i) / std::pow(morr_arr(i,j,k,MORRInd::lami), (m_bi + three));
1887  }
1888  }
1889 
1890  // ACCRETION OF RAIN WATER BY SNOW
1891  // FORMULA FROM IKAWA AND SAITO, 1991, USED BY REISNER ET AL, 1998
1892  if (morr_arr(i,j,k,MORRInd::qr3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qni3d) >= Real(1.0e-8)) {
1893  Real ums_local = morr_arr(i,j,k,MORRInd::asn) * m_cons3 / std::pow(morr_arr(i,j,k,MORRInd::lams), m_bs);
1894  Real umr_local = morr_arr(i,j,k,MORRInd::arn) * m_cons4 / std::pow(morr_arr(i,j,k,MORRInd::lamr), m_br);
1895  Real uns_local = morr_arr(i,j,k,MORRInd::asn) * m_cons5 / std::pow(morr_arr(i,j,k,MORRInd::lams), m_bs);
1896  Real unr_local = morr_arr(i,j,k,MORRInd::arn) * m_cons6 / std::pow(morr_arr(i,j,k,MORRInd::lamr), m_br);
1897 
1898  // SET REASLISTIC LIMITS ON FALLSPEEDS
1899  // bug fix, 10/08/09
1900  dum = std::pow(m_rhosu / morr_arr(i,j,k,MORRInd::rho), Real(0.54));
1901  ums_local = std::min(ums_local, Real(1.2) * dum);
1902  uns_local = std::min(uns_local, Real(1.2) * dum);
1903  umr_local = std::min(umr_local, Real(9.1) * dum);
1904  unr_local = std::min(unr_local, Real(9.1) * dum);
1905 
1906  pracs = m_cons41 * (std::sqrt(amrex::Math::powi<2>(Real(1.2) * umr_local - Real(0.95) * ums_local) +
1907  Real(0.08) * ums_local * umr_local) * morr_arr(i,j,k,MORRInd::rho) * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::n0s) /
1908  amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) * (Real(5.0) / (amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) * morr_arr(i,j,k,MORRInd::lams)) +
1909  Real(2) / (amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamr)) * amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lams))) +
1910  myhalf / (morr_arr(i,j,k,MORRInd::lamr) * amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lams)))));
1911 
1912  npracs = m_cons32 * morr_arr(i,j,k,MORRInd::rho) * std::sqrt(Real(1.7) * amrex::Math::powi<2>(unr_local - uns_local) +
1913  Real(0.3) * unr_local * uns_local) * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::n0s) *
1914  (one / (amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) * morr_arr(i,j,k,MORRInd::lams)) +
1915  one / (amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamr)) * amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lams))) +
1916  one / (morr_arr(i,j,k,MORRInd::lamr) * amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lams))));
1917 
1918  // MAKE SURE PRACS DOESN'T EXCEED TOTAL RAIN MIXING RATIO
1919  // AS THIS MAY OTHERWISE RESULT IN TOO MUCH TRANSFER OF WATER DURING
1920  // RIME-SPLINTERING
1921  pracs = std::min(pracs, morr_arr(i,j,k,MORRInd::qr3d) / dt);
1922 
1923  // COLLECTION OF SNOW BY RAIN - NEEDED FOR GRAUPEL CONVERSION CALCULATIONS
1924  // ONLY CALCULATE IF SNOW AND RAIN MIXING RATIOS EXCEED Real(0.1) G/KG
1925  // hm modify for wrfv3.1
1926  if (morr_arr(i,j,k,MORRInd::qni3d) >= Real(0.1e-3) && morr_arr(i,j,k,MORRInd::qr3d) >= Real(0.1e-3)) {
1927  psacr = m_cons31 * (std::sqrt(amrex::Math::powi<2>(Real(1.2) * umr_local - Real(0.95) * ums_local) +
1928  Real(0.08) * ums_local * umr_local) * morr_arr(i,j,k,MORRInd::rho) * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::n0s) /
1929  amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lams)) * (Real(5.0) / (amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lams)) * morr_arr(i,j,k,MORRInd::lamr)) +
1930  Real(2) / (amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lams)) * amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamr))) +
1931  myhalf / (morr_arr(i,j,k,MORRInd::lams) * amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)))));
1932  }
1933  }
1934 
1935  // COLLECTION OF RAINWATER BY GRAUPEL, FROM IKAWA AND SAITO 1990,
1936  // USED BY REISNER ET AL 1998
1937  if (morr_arr(i,j,k,MORRInd::qr3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qg3d) >= Real(1.0e-8)) {
1938  Real umg_local = morr_arr(i,j,k,MORRInd::agn) * m_cons7 / std::pow(morr_arr(i,j,k,MORRInd::lamg), m_bg);
1939  Real umr_local = morr_arr(i,j,k,MORRInd::arn) * m_cons4 / std::pow(morr_arr(i,j,k,MORRInd::lamr), m_br);
1940  Real ung_local = morr_arr(i,j,k,MORRInd::agn) * m_cons8 / std::pow(morr_arr(i,j,k,MORRInd::lamg), m_bg);
1941  Real unr_local = morr_arr(i,j,k,MORRInd::arn) * m_cons6 / std::pow(morr_arr(i,j,k,MORRInd::lamr), m_br);
1942 
1943  // SET REASLISTIC LIMITS ON FALLSPEEDS
1944  // bug fix, 10/08/09
1945  dum = std::pow(m_rhosu / morr_arr(i,j,k,MORRInd::rho), Real(0.54));
1946  umg_local = std::min(umg_local, Real(20.0) * dum);
1947  ung_local = std::min(ung_local, Real(20.0) * dum);
1948  umr_local = std::min(umr_local, Real(9.1) * dum);
1949  unr_local = std::min(unr_local, Real(9.1) * dum);
1950 
1951  pracg = m_cons41 * (std::sqrt(amrex::Math::powi<2>(Real(1.2) * umr_local - Real(0.95) * umg_local) +
1952  Real(0.08) * umg_local * umr_local) * morr_arr(i,j,k,MORRInd::rho) * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::n0g) /
1953  amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) * (Real(5.0) / (amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) * morr_arr(i,j,k,MORRInd::lamg)) +
1954  Real(2) / (amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamr)) * amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamg))) +
1955  myhalf / (morr_arr(i,j,k,MORRInd::lamr) * amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamg)))));
1956 
1957  npracg = m_cons32 * morr_arr(i,j,k,MORRInd::rho) * std::sqrt(Real(1.7) * amrex::Math::powi<2>(unr_local - ung_local) +
1958  Real(0.3) * unr_local * ung_local) * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::n0g) *
1959  (one / (amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) * morr_arr(i,j,k,MORRInd::lamg)) +
1960  one / (amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamr)) * amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::lamg))) +
1961  one / (morr_arr(i,j,k,MORRInd::lamr) * amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamg))));
1962 
1963  // MAKE SURE PRACG DOESN'T EXCEED TOTAL RAIN MIXING RATIO
1964  // AS THIS MAY OTHERWISE RESULT IN TOO MUCH TRANSFER OF WATER DURING
1965  // RIME-SPLINTERING
1966  pracg = std::min(pracg, morr_arr(i,j,k,MORRInd::qr3d) / dt);
1967  }
1968 
1969  // RIME-SPLINTERING - SNOW
1970  // HALLET-MOSSOP (1974)
1971  // NUMBER OF SPLINTERS FORMED IS BASED ON MASS OF RIMED WATER
1972  // hm add threshold snow and droplet mixing ratio for rime-splintering
1973  // to limit rime-splintering in stratiform clouds
1974  // these thresholds correspond with graupel thresholds in rh 1984
1975  //v1.4
1976  if (morr_arr(i,j,k,MORRInd::qni3d) >= Real(0.1e-3)) {
1977  if (morr_arr(i,j,k,MORRInd::qc3d) >= Real(0.5e-3) || morr_arr(i,j,k,MORRInd::qr3d) >= Real(0.1e-3)) {
1978  if (psacws > Real(0) || pracs > Real(0)) {
1979  if (morr_arr(i,j,k,MORRInd::t3d) < Real(270.16) && morr_arr(i,j,k,MORRInd::t3d) > Real(265.16)) {
1980  Real fmult = Real(0);
1981 
1982  if (morr_arr(i,j,k,MORRInd::t3d) > Real(270.16)) {
1983  fmult = Real(0);
1984  } else if (morr_arr(i,j,k,MORRInd::t3d) <= Real(270.16) && morr_arr(i,j,k,MORRInd::t3d) > Real(268.16)) {
1985  fmult = (Real(270.16) - morr_arr(i,j,k,MORRInd::t3d)) / Real(2);
1986  } else if (morr_arr(i,j,k,MORRInd::t3d) >= Real(265.16) && morr_arr(i,j,k,MORRInd::t3d) <= Real(268.16)) {
1987  fmult = (morr_arr(i,j,k,MORRInd::t3d) - Real(265.16)) / three;
1988  } else if (morr_arr(i,j,k,MORRInd::t3d) < Real(265.16)) {
1989  fmult = Real(0);
1990  }
1991 
1992  // 1000 IS TO CONVERT FROM KG TO G
1993  // SPLINTERING FROM DROPLETS ACCRETED ONTO SNOW
1994  if (psacws > Real(0)) {
1995  nmults = Real(35.0e4) * psacws * fmult * Real(1000.0);
1996  qmults = nmults * m_mmult;
1997 
1998  // CONSTRAIN SO THAT TRANSFER OF MASS FROM SNOW TO ICE CANNOT BE MORE MASS
1999  // THAN WAS RIMED ONTO SNOW
2000  qmults = std::min(qmults, psacws);
2001  psacws = psacws - qmults;
2002  }
2003 
2004  // RIMING AND SPLINTERING FROM ACCRETED RAINDROPS
2005  if (pracs > Real(0)) {
2006  nmultr = Real(35.0e4) * pracs * fmult * Real(1000.0);
2007  qmultr = nmultr * m_mmult;
2008 
2009  // CONSTRAIN SO THAT TRANSFER OF MASS FROM SNOW TO ICE CANNOT BE MORE MASS
2010  // THAN WAS RIMED ONTO SNOW
2011  qmultr = std::min(qmultr, pracs);
2012  pracs = pracs - qmultr;
2013  }
2014  }
2015  }
2016  }
2017  }
2018 
2019  // RIME-SPLINTERING - GRAUPEL
2020  // HALLET-MOSSOP (1974)
2021  // NUMBER OF SPLINTERS FORMED IS BASED ON MASS OF RIMED WATER
2022  // hm add threshold snow mixing ratio for rime-splintering
2023  // to limit rime-splintering in stratiform clouds
2024  // v1.4
2025  if (morr_arr(i,j,k,MORRInd::qg3d) >= Real(0.1e-3)) {
2026  if (morr_arr(i,j,k,MORRInd::qc3d) >= Real(0.5e-3) || morr_arr(i,j,k,MORRInd::qr3d) >= Real(0.1e-3)) {
2027  if (psacwg > Real(0) || pracg > Real(0)) {
2028  if (morr_arr(i,j,k,MORRInd::t3d) < Real(270.16) && morr_arr(i,j,k,MORRInd::t3d) > Real(265.16)) {
2029  Real fmult = Real(0);
2030 
2031  if (morr_arr(i,j,k,MORRInd::t3d) > Real(270.16)) {
2032  fmult = Real(0);
2033  } else if (morr_arr(i,j,k,MORRInd::t3d) <= Real(270.16) && morr_arr(i,j,k,MORRInd::t3d) > Real(268.16)) {
2034  fmult = (Real(270.16) - morr_arr(i,j,k,MORRInd::t3d)) / Real(2);
2035  } else if (morr_arr(i,j,k,MORRInd::t3d) >= Real(265.16) && morr_arr(i,j,k,MORRInd::t3d) <= Real(268.16)) {
2036  fmult = (morr_arr(i,j,k,MORRInd::t3d) - Real(265.16)) / three;
2037  } else if (morr_arr(i,j,k,MORRInd::t3d) < Real(265.16)) {
2038  fmult = Real(0);
2039  }
2040 
2041  // 1000 IS TO CONVERT FROM KG TO G
2042  // SPLINTERING FROM DROPLETS ACCRETED ONTO GRAUPEL
2043  if (psacwg > Real(0)) {
2044  nmultg = Real(35.0e4) * psacwg * fmult * Real(1000.0);
2045  qmultg = nmultg * m_mmult;
2046 
2047  // CONSTRAIN SO THAT TRANSFER OF MASS FROM GRAUPEL TO ICE CANNOT BE MORE MASS
2048  // THAN WAS RIMED ONTO GRAUPEL
2049  qmultg = std::min(qmultg, psacwg);
2050  psacwg = psacwg - qmultg;
2051  }
2052 
2053  // RIMING AND SPLINTERING FROM ACCRETED RAINDROPS
2054  if (pracg > Real(0)) {
2055  nmultrg = Real(35.0e4) * pracg * fmult * Real(1000.0);
2056  qmultrg = nmultrg * m_mmult;
2057 
2058  // CONSTRAIN SO THAT TRANSFER OF MASS FROM GRAUPEL TO ICE CANNOT BE MORE MASS
2059  // THAN WAS RIMED ONTO GRAUPEL
2060  qmultrg = std::min(qmultrg, pracg);
2061  pracg = pracg - qmultrg;
2062  }
2063  }
2064  }
2065  }
2066  }
2067 
2068  // CONVERSION OF RIMED CLOUD WATER ONTO SNOW TO GRAUPEL/HAIL
2069  if (psacws > Real(0)) {
2070  // ONLY ALLOW CONVERSION IF QNI > Real(0.1) AND QC > myhalf G/KG FOLLOWING RUTLEDGE AND HOBBS (1984)
2071  if (morr_arr(i,j,k,MORRInd::qni3d) >= Real(0.1e-3) && morr_arr(i,j,k,MORRInd::qc3d) >= Real(0.5e-3)) {
2072  // PORTION OF RIMING CONVERTED TO GRAUPEL (REISNER ET AL. 1998, ORIGINALLY IS1991)
2073  pgsacw = std::min(psacws, m_cons17 * dt * morr_arr(i,j,k,MORRInd::n0s) * morr_arr(i,j,k,MORRInd::qc3d) * morr_arr(i,j,k,MORRInd::qc3d) *
2074  morr_arr(i,j,k,MORRInd::asn) * morr_arr(i,j,k,MORRInd::asn) /
2075  (morr_arr(i,j,k,MORRInd::rho) * std::pow(morr_arr(i,j,k,MORRInd::lams), (Real(2) * m_bs + Real(2)))));
2076 
2077  // MIX RAT CONVERTED INTO GRAUPEL AS EMBRYO (REISNER ET AL. 1998, ORIG M1990)
2078  dum = std::max(m_rhosn / (m_rhog - m_rhosn) * pgsacw, Real(0));
2079 
2080  // NUMBER CONCENTRAITON OF EMBRYO GRAUPEL FROM RIMING OF SNOW
2081  nscng = dum / m_mg0 * morr_arr(i,j,k,MORRInd::rho);
2082  // LIMIT MAX NUMBER CONVERTED TO SNOW NUMBER
2083  nscng = std::min(nscng, morr_arr(i,j,k,MORRInd::ns3d) / dt);
2084 
2085  // PORTION OF RIMING LEFT FOR SNOW
2086  psacws = psacws - pgsacw;
2087  }
2088  }
2089 
2090  // CONVERSION OF RIMED RAINWATER ONTO SNOW CONVERTED TO GRAUPEL
2091  if (pracs > Real(0)) {
2092  // ONLY ALLOW CONVERSION IF QNI > Real(0.1) AND QR > Real(0.1) G/KG FOLLOWING RUTLEDGE AND HOBBS (1984)
2093  if (morr_arr(i,j,k,MORRInd::qni3d) >= Real(0.1e-3) && morr_arr(i,j,k,MORRInd::qr3d) >= Real(0.1e-3)) {
2094  // PORTION OF COLLECTED RAINWATER CONVERTED TO GRAUPEL (REISNER ET AL. 1998)
2095  dum = m_cons18 * amrex::Math::powi<3>(Real(4.0) / morr_arr(i,j,k,MORRInd::lams)) * amrex::Math::powi<3>(Real(4.0) / morr_arr(i,j,k,MORRInd::lams)) /
2096  (m_cons18 * amrex::Math::powi<3>(Real(4.0) / morr_arr(i,j,k,MORRInd::lams)) * amrex::Math::powi<3>(Real(4.0) / morr_arr(i,j,k,MORRInd::lams)) +
2097  m_cons19 * amrex::Math::powi<3>(Real(4.0) / morr_arr(i,j,k,MORRInd::lamr)) * amrex::Math::powi<3>(Real(4.0) / morr_arr(i,j,k,MORRInd::lamr)));
2098  dum = std::min(dum, Real(1));
2099  dum = std::max(dum, Real(0));
2100 
2101  pgracs = (one - dum) * pracs;
2102  ngracs = (one - dum) * npracs;
2103 
2104  // LIMIT MAX NUMBER CONVERTED TO MIN OF EITHER RAIN OR SNOW NUMBER CONCENTRATION
2105  ngracs = std::min(ngracs, morr_arr(i,j,k,MORRInd::nr3d) / dt);
2106  ngracs = std::min(ngracs, morr_arr(i,j,k,MORRInd::ns3d) / dt);
2107 
2108  // AMOUNT LEFT FOR SNOW PRODUCTION
2109  pracs = pracs - pgracs;
2110  npracs = npracs - ngracs;
2111 
2112  // CONVERSION TO GRAUPEL DUE TO COLLECTION OF SNOW BY RAIN
2113  psacr = psacr * (one - dum);
2114  }
2115  }
2116 
2117  // FREEZING OF RAIN DROPS
2118  // FREEZING ALLOWED BELOW -4 C
2119  if (morr_arr(i,j,k,MORRInd::t3d) < Real(269.15) && morr_arr(i,j,k,MORRInd::qr3d) >= m_qsmall) {
2120  // IMMERSION FREEZING (BIGG 1953)
2121  // hm fix 7/15/13 for consistency w/ original formula
2122  mnuccr = m_cons20 * morr_arr(i,j,k,MORRInd::nr3d) * (std::exp(m_aimm * (Real(273.15) - morr_arr(i,j,k,MORRInd::t3d))) - one) /
2123  amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) / amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr));
2124 
2125  nnuccr = m_pi * morr_arr(i,j,k,MORRInd::nr3d) * m_bimm * (std::exp(m_aimm * (Real(273.15) - morr_arr(i,j,k,MORRInd::t3d))) - one) /
2126  amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr));
2127 
2128  // PREVENT DIVERGENCE BETWEEN MIXING RATIO AND NUMBER CONC
2129  nnuccr = std::min(nnuccr, morr_arr(i,j,k,MORRInd::nr3d) / dt);
2130  }
2131 
2132  // ACCRETION OF CLOUD LIQUID WATER BY RAIN
2133  // CONTINUOUS COLLECTION EQUATION WITH
2134  // GRAVITATIONAL COLLECTION KERNEL, DROPLET FALL SPEED NEGLECTED
2135  if (morr_arr(i,j,k,MORRInd::qr3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qc3d) >= Real(1.0e-8)) {
2136  // 12/13/06 hm add, replace with newer formula from
2137  // khairoutdinov and kogan 2000, mwr
2138  dum = morr_arr(i,j,k,MORRInd::qc3d) * morr_arr(i,j,k,MORRInd::qr3d);
2139  pra = Real(67.0) * std::pow(dum, Real(1.15));
2140  npra = pra / (morr_arr(i,j,k,MORRInd::qc3d) / morr_arr(i,j,k,MORRInd::nc3d));
2141  }
2142 
2143  // SELF-COLLECTION OF RAIN DROPS
2144  // FROM BEHENG(1994)
2145  // FROM NUMERICAL SIMULATION OF THE STOCHASTIC COLLECTION EQUATION
2146  // AS DESCRINED ABOVE FOR AUTOCONVERSION
2147  if (morr_arr(i,j,k,MORRInd::qr3d) >= Real(1.0e-8)) {
2148  // include breakup add 10/09/09
2149  dum1 = Real(300.0e-6);
2150  if (one / morr_arr(i,j,k,MORRInd::lamr) < dum1) {
2151  dum = one;
2152  } else if (one / morr_arr(i,j,k,MORRInd::lamr) >= dum1) {
2153  dum = Real(2) - std::exp(Real(2300.0) * (one / morr_arr(i,j,k,MORRInd::lamr) - dum1));
2154  }
2155  nragg = -Real(5.78) * dum * morr_arr(i,j,k,MORRInd::nr3d) * morr_arr(i,j,k,MORRInd::qr3d) * morr_arr(i,j,k,MORRInd::rho);
2156  }
2157 
2158  // AUTOCONVERSION OF CLOUD ICE TO SNOW
2159  // FOLLOWING HARRINGTON ET AL. (1995) WITH MODIFICATION
2160  // HERE IT IS ASSUMED THAT AUTOCONVERSION CAN ONLY OCCUR WHEN THE
2161  // ICE IS GROWING, I.E. IN CONDITIONS OF ICE SUPERSATURATION
2162  if (morr_arr(i,j,k,MORRInd::qi3d) >= Real(1.0e-8) && qvqvsi >= one) {
2163  nprci = m_cons21 * (morr_arr(i,j,k,MORRInd::qv3d) - qvi) * morr_arr(i,j,k,MORRInd::rho) *
2164  morr_arr(i,j,k,MORRInd::n0i) * std::exp(-morr_arr(i,j,k,MORRInd::lami) * m_dcs) * dv / abi;
2165  prci = m_cons22 * nprci;
2166  nprci = std::min(nprci, morr_arr(i,j,k,MORRInd::ni3d) / dt);
2167  }
2168 
2169  // ACCRETION OF CLOUD ICE BY SNOW
2170  // FOR THIS CALCULATION, IT IS ASSUMED THAT THE VS >> VI
2171  // AND DS >> DI FOR CONTINUOUS COLLECTION
2172  if (morr_arr(i,j,k,MORRInd::qni3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qi3d) >= m_qsmall) {
2173  prai = m_cons23 * morr_arr(i,j,k,MORRInd::asn) * morr_arr(i,j,k,MORRInd::qi3d) * morr_arr(i,j,k,MORRInd::rho) * morr_arr(i,j,k,MORRInd::n0s) /
2174  std::pow(morr_arr(i,j,k,MORRInd::lams), (m_bs + three));
2175  nprai = m_cons23 * morr_arr(i,j,k,MORRInd::asn) * morr_arr(i,j,k,MORRInd::ni3d) *
2176  morr_arr(i,j,k,MORRInd::rho) * morr_arr(i,j,k,MORRInd::n0s) /
2177  std::pow(morr_arr(i,j,k,MORRInd::lams), (m_bs + three));
2178  nprai = std::min(nprai, morr_arr(i,j,k,MORRInd::ni3d) / dt);
2179  }
2180 
2181  // hm, add 12/13/06, collision of rain and ice to produce snow or graupel
2182  // follows reisner et al. 1998
2183  // assumed fallspeed and size of ice crystal << than for rain
2184  if (morr_arr(i,j,k,MORRInd::qr3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::qi3d) >= Real(1.0e-8) && morr_arr(i,j,k,MORRInd::t3d) <= Real(273.15)) {
2185  // allow graupel formation from rain-ice collisions only if rain mixing ratio > Real(0.1) g/kg,
2186  // otherwise add to snow
2187  if (morr_arr(i,j,k,MORRInd::qr3d) >= Real(0.1e-3)) {
2188  niacr = m_cons24 * morr_arr(i,j,k,MORRInd::ni3d) * morr_arr(i,j,k,MORRInd::n0r)* morr_arr(i,j,k,MORRInd::arn) /
2189  std::pow(morr_arr(i,j,k,MORRInd::lamr), (m_br + three)) * morr_arr(i,j,k,MORRInd::rho);
2190  piacr = m_cons25 * morr_arr(i,j,k,MORRInd::ni3d) * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::arn) /
2191  std::pow(morr_arr(i,j,k,MORRInd::lamr), (m_br + three)) / amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) * morr_arr(i,j,k,MORRInd::rho);
2192  praci = m_cons24 * morr_arr(i,j,k,MORRInd::qi3d) * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::arn) /
2193  std::pow(morr_arr(i,j,k,MORRInd::lamr), (m_br + three)) * morr_arr(i,j,k,MORRInd::rho);
2194  niacr = std::min(niacr, morr_arr(i,j,k,MORRInd::nr3d) / dt);
2195  niacr = std::min(niacr, morr_arr(i,j,k,MORRInd::ni3d) / dt);
2196  } else {
2197  niacrs = m_cons24 * morr_arr(i,j,k,MORRInd::ni3d) * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::arn) /
2198  std::pow(morr_arr(i,j,k,MORRInd::lamr), (m_br + three)) * morr_arr(i,j,k,MORRInd::rho);
2199  piacrs = m_cons25 * morr_arr(i,j,k,MORRInd::ni3d) * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::arn) /
2200  std::pow(morr_arr(i,j,k,MORRInd::lamr), (m_br + three)) / amrex::Math::powi<3>(morr_arr(i,j,k,MORRInd::lamr)) * morr_arr(i,j,k,MORRInd::rho);
2201  pracis = m_cons24 * morr_arr(i,j,k,MORRInd::qi3d) * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::arn) /
2202  std::pow(morr_arr(i,j,k,MORRInd::lamr), (m_br + three)) * morr_arr(i,j,k,MORRInd::rho);
2203  niacrs = std::min(niacrs, morr_arr(i,j,k,MORRInd::nr3d) / dt);
2204  niacrs = std::min(niacrs, morr_arr(i,j,k,MORRInd::ni3d) / dt);
2205  }
2206  }
2207 
2208  // NUCLEATION OF CLOUD ICE FROM HOMOGENEOUS AND HETEROGENEOUS FREEZING ON AEROSOL
2209  if (m_inuc == 0) {
2210  // ADD THRESHOLD ACCORDING TO GREG THOMSPON
2211  if ((qvqvs >= Real(0.999) && morr_arr(i,j,k,MORRInd::t3d) <= Real(265.15)) || qvqvsi >= Real(1.08)) {
2212  // hm, modify dec. 5, 2006, replace with cooper curve
2213  kc2 = Real(0.005) * std::exp(Real(0.304) * (Real(273.15) - morr_arr(i,j,k,MORRInd::t3d))) * Real(1000.0); // CONVERT FROM L-1 TO M-3
2214  // LIMIT TO 500 L-1
2215  kc2 = std::min(kc2, Real(500.0e3));
2216  kc2 = std::max(kc2 / morr_arr(i,j,k,MORRInd::rho), Real(0)); // CONVERT TO KG-1
2217 
2218  if (kc2 > morr_arr(i,j,k,MORRInd::ni3d) + morr_arr(i,j,k,MORRInd::ns3d) + morr_arr(i,j,k,MORRInd::ng3d)) {
2219  nnuccd = (kc2 - morr_arr(i,j,k,MORRInd::ni3d) - morr_arr(i,j,k,MORRInd::ns3d) - morr_arr(i,j,k,MORRInd::ng3d)) / dt;
2220  mnuccd = nnuccd * m_mi0;
2221  }
2222  }
2223  } else if (m_inuc == 1) {
2224  if (morr_arr(i,j,k,MORRInd::t3d) < Real(273.15) && qvqvsi > one) {
2225  kc2 = Real(0.16) * Real(1000.0) / morr_arr(i,j,k,MORRInd::rho); // CONVERT FROM L-1 TO KG-1
2226  if (kc2 > morr_arr(i,j,k,MORRInd::ni3d) + morr_arr(i,j,k,MORRInd::ns3d) + morr_arr(i,j,k,MORRInd::ng3d)) {
2227  nnuccd = (kc2 - morr_arr(i,j,k,MORRInd::ni3d) - morr_arr(i,j,k,MORRInd::ns3d) - morr_arr(i,j,k,MORRInd::ng3d)) / dt;
2228  mnuccd = nnuccd * m_mi0;
2229  }
2230  }
2231  }
2232 
2233  // CALCULATE EVAP/SUB/DEP TERMS FOR QI,QNI,QR
2234  // NO VENTILATION FOR CLOUD ICE
2235  epsi = Real(0);
2236  if (morr_arr(i,j,k,MORRInd::qi3d) >= m_qsmall) {
2237  epsi = Real(2) * m_pi * morr_arr(i,j,k,MORRInd::n0i) * morr_arr(i,j,k,MORRInd::rho) * dv / (morr_arr(i,j,k,MORRInd::lami) * morr_arr(i,j,k,MORRInd::lami));
2238  }
2239 
2240  // VENTILATION FOR SNOW
2241  epss = Real(0);
2242  if (morr_arr(i,j,k,MORRInd::qni3d) >= m_qsmall) {
2243  epss = Real(2) * m_pi * morr_arr(i,j,k,MORRInd::n0s) * morr_arr(i,j,k,MORRInd::rho) * dv *
2244  (m_f1s / (morr_arr(i,j,k,MORRInd::lams) * morr_arr(i,j,k,MORRInd::lams)) +
2245  m_f2s * std::pow(morr_arr(i,j,k,MORRInd::asn) * morr_arr(i,j,k,MORRInd::rho) / morr_arr(i,j,k,MORRInd::mu), myhalf) *
2246  std::pow(sc_schmidt, (one / three)) * m_cons10 /
2247  std::pow(morr_arr(i,j,k,MORRInd::lams), m_cons35));
2248  }
2249 
2250  // Ventilation for graupel
2251  epsg = Real(0);
2252  if (morr_arr(i,j,k,MORRInd::qg3d) >= m_qsmall) {
2253  epsg = Real(2) * m_pi * morr_arr(i,j,k,MORRInd::n0g) * morr_arr(i,j,k,MORRInd::rho) * dv *
2254  (m_f1s / (morr_arr(i,j,k,MORRInd::lamg) * morr_arr(i,j,k,MORRInd::lamg)) +
2255  m_f2s * std::pow(morr_arr(i,j,k,MORRInd::agn) * morr_arr(i,j,k,MORRInd::rho) / morr_arr(i,j,k,MORRInd::mu), myhalf) *
2256  std::pow(sc_schmidt, (one / three)) * m_cons11 /
2257  std::pow(morr_arr(i,j,k,MORRInd::lamg), m_cons36));
2258  }
2259 
2260  // VENTILATION FOR RAIN
2261  epsr = Real(0);
2262  if (morr_arr(i,j,k,MORRInd::qr3d) >= m_qsmall) {
2263  epsr = Real(2) * m_pi * morr_arr(i,j,k,MORRInd::n0r) * morr_arr(i,j,k,MORRInd::rho) * dv *
2264  (m_f1r / (morr_arr(i,j,k,MORRInd::lamr) * morr_arr(i,j,k,MORRInd::lamr)) +
2265  m_f2r * std::pow(morr_arr(i,j,k,MORRInd::arn) * morr_arr(i,j,k,MORRInd::rho) / morr_arr(i,j,k,MORRInd::mu), myhalf) *
2266  std::pow(sc_schmidt, (one / three)) * m_cons9 /
2267  std::pow(morr_arr(i,j,k,MORRInd::lamr), m_cons34));
2268  }
2269 
2270  // ONLY INCLUDE REGION OF ICE SIZE DIST < DCS
2271  // DUM IS FRACTION OF D*N(D) < DCS
2272  // LOGIC BELOW FOLLOWS THAT OF HARRINGTON ET AL. 1995 (JAS)
2273  if (morr_arr(i,j,k,MORRInd::qi3d) >= m_qsmall) {
2274  dum = (one - std::exp(-morr_arr(i,j,k,MORRInd::lami) * m_dcs) * (one + morr_arr(i,j,k,MORRInd::lami) * m_dcs));
2275  prd = epsi * (morr_arr(i,j,k,MORRInd::qv3d) - qvi) / abi * dum;
2276  } else {
2277  dum = Real(0);
2278  }
2279 
2280  // ADD DEPOSITION IN TAIL OF ICE SIZE DIST TO SNOW IF SNOW IS PRESENT
2281  if (morr_arr(i,j,k,MORRInd::qni3d) >= m_qsmall) {
2282  prds = epss * (morr_arr(i,j,k,MORRInd::qv3d) - qvi) / abi +
2283  epsi * (morr_arr(i,j,k,MORRInd::qv3d) - qvi) / abi * (one - dum);
2284  } else {
2285  // OTHERWISE ADD TO CLOUD ICE
2286  prd = prd + epsi * (morr_arr(i,j,k,MORRInd::qv3d) - qvi) / abi * (one - dum);
2287  }
2288 
2289  // VAPOR DPEOSITION ON GRAUPEL
2290  prdg = epsg * (morr_arr(i,j,k,MORRInd::qv3d) - qvi) / abi;
2291 
2292  // NO CONDENSATION ONTO RAIN, ONLY EVAP
2293  if (morr_arr(i,j,k,MORRInd::qv3d) < qvs) {
2294  pre = epsr * (morr_arr(i,j,k,MORRInd::qv3d) - qvs) / ab;
2295  pre = std::min(pre, Real(0));
2296  } else {
2297  pre = Real(0);
2298  }
2299 
2300  // MAKE SURE NOT PUSHED INTO ICE SUPERSAT/SUBSAT
2301  // FORMULA FROM REISNER 2 SCHEME
2302  dum = (morr_arr(i,j,k,MORRInd::qv3d) - qvi) / dt;
2303 
2304  fudgef = Real(0.9999);
2305  sum_dep = prd + prds + mnuccd + prdg;
2306 
2307  if ((dum > Real(0) && sum_dep > dum * fudgef) ||
2308  (dum < Real(0) && sum_dep < dum * fudgef)) {
2309  mnuccd = fudgef * mnuccd * dum / sum_dep;
2310  prd = fudgef * prd * dum / sum_dep;
2311  prds = fudgef * prds * dum / sum_dep;
2312  prdg = fudgef * prdg * dum / sum_dep;
2313  }
2314 
2315  // IF CLOUD ICE/SNOW/GRAUPEL VAP DEPOSITION IS NEG, THEN ASSIGN TO SUBLIMATION PROCESSES
2316  if (prd < Real(0)) {
2317  eprd = prd;
2318  prd = Real(0);
2319  }
2320  if (prds < Real(0)) {
2321  eprds = prds;
2322  prds = Real(0);
2323  }
2324  if (prdg < Real(0)) {
2325  eprdg = prdg;
2326  prdg = Real(0);
2327  }
2328  // CONSERVATION OF WATER
2329  // THIS IS ADOPTED LOOSELY FROM RESINER CODE. HOWEVER, HERE WE
2330  // ONLY ADJUST PROCESSES THAT ARE NEGATIVE, RATHER THAN ALL PROCESSES.
2331 
2332  // IF MIXING RATIOS LESS THAN QSMALL, THEN NO DEPLETION OF WATER
2333  // THROUGH MICROPHYSICAL PROCESSES, SKIP CONSERVATION
2334 
2335  // NOTE: CONSERVATION CHECK NOT APPLIED TO NUMBER CONCENTRATION SPECIES. ADDITIONAL CATCH
2336  // BELOW WILL PREVENT NEGATIVE NUMBER CONCENTRATION
2337  // FOR EACH MICROPHYSICAL PROCESS WHICH PROVIDES A SOURCE FOR NUMBER, THERE IS A CHECK
2338  // TO MAKE SURE THAT CAN'T EXCEED TOTAL NUMBER OF DEPLETED SPECIES WITH THE TIME
2339  // STEP
2340 
2341  // ****SENSITIVITY - NO ICE
2342  if (m_iliq == 1) {
2343  mnuccc = Real(0);
2344  nnuccc = Real(0);
2345  mnuccr = Real(0);
2346  nnuccr = Real(0);
2347  mnuccd = Real(0);
2348  nnuccd = Real(0);
2349  }
2350 
2351  // ****SENSITIVITY - NO GRAUPEL
2352  if (m_igraup == 1) {
2353  pracg = Real(0);
2354  psacr = Real(0);
2355  psacwg = Real(0);
2356  prdg = Real(0);
2357  eprdg = Real(0);
2358  evpmg = Real(0);
2359  pgmlt = Real(0);
2360  npracg = Real(0);
2361  npsacwg = Real(0);
2362  nscng = Real(0);
2363  ngracs = Real(0);
2364  nsubg = Real(0);
2365  ngmltg = Real(0);
2366  ngmltr = Real(0);
2367 
2368  // fix 053011
2369  piacrs = piacrs + piacr;
2370  piacr = Real(0);
2371 
2372  // fix 070713
2373  pracis = pracis + praci;
2374  praci = Real(0);
2375  psacws = psacws + pgsacw;
2376  pgsacw = Real(0);
2377  pracs = pracs + pgracs;
2378  pgracs = Real(0);
2379  }
2380 
2381  // CONSERVATION OF QC
2382  dum = (prc + pra + mnuccc + psacws + psacwi + qmults + psacwg + pgsacw + qmultg) * dt;
2383 
2384  if (dum > morr_arr(i,j,k,MORRInd::qc3d) && morr_arr(i,j,k,MORRInd::qc3d) >= m_qsmall) {
2385  ratio = morr_arr(i,j,k,MORRInd::qc3d) / dum;
2386 
2387  prc = prc * ratio;
2388  pra = pra * ratio;
2389  mnuccc = mnuccc * ratio;
2390  psacws = psacws * ratio;
2391  psacwi = psacwi * ratio;
2392  qmults = qmults * ratio;
2393  qmultg = qmultg * ratio;
2394  psacwg = psacwg * ratio;
2395  pgsacw = pgsacw * ratio;
2396  }
2397 
2398  // CONSERVATION OF QI
2399  dum = (-prd - mnuccc + prci + prai - qmults - qmultg - qmultr - qmultrg
2400  - mnuccd + praci + pracis - eprd - psacwi) * dt;
2401 
2402  if (dum > morr_arr(i,j,k,MORRInd::qi3d) && morr_arr(i,j,k,MORRInd::qi3d) >= m_qsmall) {
2403  ratio = (morr_arr(i,j,k,MORRInd::qi3d) / dt + prd + mnuccc + qmults + qmultg + qmultr + qmultrg +
2404  mnuccd + psacwi) /
2405  (prci + prai + praci + pracis - eprd);
2406 
2407  prci = prci * ratio;
2408  prai = prai * ratio;
2409  praci = praci * ratio;
2410  pracis = pracis * ratio;
2411  eprd = eprd * ratio;
2412  }
2413 
2414  // CONSERVATION OF QR
2415  dum = ((pracs - pre) + (qmultr + qmultrg - prc) + (mnuccr - pra) +
2416  piacr + piacrs + pgracs + pracg) * dt;
2417 
2418  if (dum > morr_arr(i,j,k,MORRInd::qr3d) && morr_arr(i,j,k,MORRInd::qr3d) >= m_qsmall) {
2419  ratio = (morr_arr(i,j,k,MORRInd::qr3d) / dt + prc + pra) /
2420  (-pre + qmultr + qmultrg + pracs + mnuccr + piacr + piacrs + pgracs + pracg);
2421 
2422  pre = pre * ratio;
2423  pracs = pracs * ratio;
2424  qmultr = qmultr * ratio;
2425  qmultrg = qmultrg * ratio;
2426  mnuccr = mnuccr * ratio;
2427  piacr = piacr * ratio;
2428  piacrs = piacrs * ratio;
2429  pgracs = pgracs * ratio;
2430  pracg = pracg * ratio;
2431  }
2432 
2433  // CONSERVATION OF QNI
2434  if (m_igraup == 0) {
2435  dum = (-prds - psacws - prai - prci - pracs - eprds + psacr - piacrs - pracis) * dt;
2436 
2437  if (dum > morr_arr(i,j,k,MORRInd::qni3d) && morr_arr(i,j,k,MORRInd::qni3d) >= m_qsmall) {
2438  ratio = (morr_arr(i,j,k,MORRInd::qni3d) / dt + prds + psacws + prai + prci + pracs + piacrs + pracis) /
2439  (-eprds + psacr);
2440 
2441  eprds = eprds * ratio;
2442  psacr = psacr * ratio;
2443  }
2444  } else if (m_igraup == 1) {
2445  // FOR NO GRAUPEL, NEED TO INCLUDE FREEZING OF RAIN FOR SNOW
2446  dum = (-prds - psacws - prai - prci - pracs - eprds + psacr - piacrs - pracis - mnuccr) * dt;
2447 
2448  if (dum > morr_arr(i,j,k,MORRInd::qni3d) && morr_arr(i,j,k,MORRInd::qni3d) >= m_qsmall) {
2449  ratio = (morr_arr(i,j,k,MORRInd::qni3d) / dt + prds + psacws + prai + prci + pracs + piacrs + pracis + mnuccr) /
2450  (-eprds + psacr);
2451 
2452  eprds = eprds * ratio;
2453  psacr = psacr * ratio;
2454  }
2455  }
2456 
2457  // CONSERVATION OF QG
2458  dum = (-psacwg - pracg - pgsacw - pgracs - prdg - mnuccr - eprdg - piacr - praci - psacr) * dt;
2459 
2460  if (dum > morr_arr(i,j,k,MORRInd::qg3d) && morr_arr(i,j,k,MORRInd::qg3d) >= m_qsmall) {
2461  ratio = (morr_arr(i,j,k,MORRInd::qg3d) / dt + psacwg + pracg + pgsacw + pgracs + prdg + mnuccr + psacr +
2462  piacr + praci) / (-eprdg);
2463 
2464  eprdg = eprdg * ratio;
2465  }
2466 
2467  // TENDENCIES
2468  morr_arr(i,j,k,MORRInd::qv3dten) = morr_arr(i,j,k,MORRInd::qv3dten) + (-pre - prd - prds - mnuccd - eprd - eprds - prdg - eprdg);
2469 
2470  // bug fix hm, 3/1/11, include piacr and piacrs
2471  morr_arr(i,j,k,MORRInd::t3dten) = morr_arr(i,j,k,MORRInd::t3dten) + (pre * morr_arr(i,j,k,MORRInd::xxlv) +
2472  (prd + prds + mnuccd + eprd + eprds + prdg + eprdg) * morr_arr(i,j,k,MORRInd::xxls) +
2473  (psacws + psacwi + mnuccc + mnuccr + qmults + qmultg + qmultr + qmultrg + pracs +
2474  psacwg + pracg + pgsacw + pgracs + piacr + piacrs) * morr_arr(i,j,k,MORRInd::xlf)) / morr_arr(i,j,k,MORRInd::cpm);
2475 
2476  morr_arr(i,j,k,MORRInd::qc3dten) = morr_arr(i,j,k,MORRInd::qc3dten) +
2477  (-pra - prc - mnuccc + pcc -
2478  psacws - psacwi - qmults - qmultg - psacwg - pgsacw);
2479 
2480  morr_arr(i,j,k,MORRInd::qi3dten) = morr_arr(i,j,k,MORRInd::qi3dten) +
2481  (prd + eprd + psacwi + mnuccc - prci -
2482  prai + qmults + qmultg + qmultr + qmultrg + mnuccd - praci - pracis);
2483 
2484  morr_arr(i,j,k,MORRInd::qr3dten) = morr_arr(i,j,k,MORRInd::qr3dten) +
2485  (pre + pra + prc - pracs - mnuccr - qmultr - qmultrg -
2486  piacr - piacrs - pracg - pgracs);
2487  if (m_igraup == 0) {
2488  morr_arr(i,j,k,MORRInd::qni3dten) = morr_arr(i,j,k,MORRInd::qni3dten) +
2489  (prai + psacws + prds + pracs + prci + eprds - psacr + piacrs + pracis);
2490 
2491  morr_arr(i,j,k,MORRInd::ns3dten) = morr_arr(i,j,k,MORRInd::ns3dten) + (nsagg + nprci - nscng - ngracs + niacrs);
2492 
2493  morr_arr(i,j,k,MORRInd::qg3dten) = morr_arr(i,j,k,MORRInd::qg3dten) + (pracg + psacwg + pgsacw + pgracs +
2494  prdg + eprdg + mnuccr + piacr + praci + psacr);
2495 
2496  morr_arr(i,j,k,MORRInd::ng3dten) = morr_arr(i,j,k,MORRInd::ng3dten) + (nscng + ngracs + nnuccr + niacr);
2497  } else if (m_igraup == 1) {
2498  // FOR NO GRAUPEL, NEED TO INCLUDE FREEZING OF RAIN FOR SNOW
2499  morr_arr(i,j,k,MORRInd::qni3dten) = morr_arr(i,j,k,MORRInd::qni3dten) +
2500  (prai + psacws + prds + pracs + prci + eprds - psacr + piacrs + pracis + mnuccr);
2501 
2502  morr_arr(i,j,k,MORRInd::ns3dten) = morr_arr(i,j,k,MORRInd::ns3dten) + (nsagg + nprci - nscng - ngracs + niacrs + nnuccr);
2503  }
2504 
2505  morr_arr(i,j,k,MORRInd::nc3dten) = morr_arr(i,j,k,MORRInd::nc3dten) + (-nnuccc - npsacws -
2506  npra - nprc - npsacwi - npsacwg);
2507 
2508  morr_arr(i,j,k,MORRInd::ni3dten) = morr_arr(i,j,k,MORRInd::ni3dten) +
2509  (nnuccc - nprci - nprai + nmults + nmultg + nmultr + nmultrg +
2510  nnuccd - niacr - niacrs);
2511 
2512  morr_arr(i,j,k,MORRInd::nr3dten) = morr_arr(i,j,k,MORRInd::nr3dten) + (nprc1 - npracs - nnuccr +
2513  nragg - niacr - niacrs - npracg - ngracs);
2514 
2515  // hm add, wrf-chem, add tendencies for c2prec
2516  // c2prec = pra + prc + psacws + qmults + qmultg + psacwg + pgsacw + mnuccc + psacwi;
2517 
2518  if (do_cond) {
2519  // CALCULATE SATURATION ADJUSTMENT TO CONDENSE EXTRA VAPOR ABOVE
2520  // WATER SATURATION
2521  dumt = morr_arr(i,j,k,MORRInd::t3d) + dt * morr_arr(i,j,k,MORRInd::t3dten);
2522  dumqv = morr_arr(i,j,k,MORRInd::qv3d) + dt * morr_arr(i,j,k,MORRInd::qv3dten);
2523 
2524  // hm, add fix for low pressure, 5/12/10
2525  dum = std::min(Real(0.99) * morr_arr(i,j,k,MORRInd::pres), calc_saturation_vapor_pressure(dumt, 0));
2526  dumqss = m_ep_2 * dum / (morr_arr(i,j,k,MORRInd::pres) - dum);
2527 
2528  dumqc = morr_arr(i,j,k,MORRInd::qc3d) + dt * morr_arr(i,j,k,MORRInd::qc3dten);
2529  dumqc = std::max(dumqc, Real(0));
2530 
2531  // SATURATION ADJUSTMENT FOR LIQUID
2532  dums = dumqv - dumqss;
2533 
2534  pcc = dums / (one + amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::xxlv)) * dumqss / (morr_arr(i,j,k,MORRInd::cpm) * m_Rv * amrex::Math::powi<2>(dumt))) / dt;
2535 
2536  if (pcc * dt + dumqc < Real(0)) {
2537  pcc = -dumqc / dt;
2538  }
2539 
2540  morr_arr(i,j,k,MORRInd::qv3dten) = morr_arr(i,j,k,MORRInd::qv3dten) - pcc;
2541  morr_arr(i,j,k,MORRInd::t3dten) = morr_arr(i,j,k,MORRInd::t3dten) + pcc * morr_arr(i,j,k,MORRInd::xxlv) / morr_arr(i,j,k,MORRInd::cpm);
2542  morr_arr(i,j,k,MORRInd::qc3dten) = morr_arr(i,j,k,MORRInd::qc3dten) + pcc;
2543  }
2544  // SUBLIMATE, MELT, OR EVAPORATE NUMBER CONCENTRATION
2545  // THIS FORMULATION ASSUMES 1:1 RATIO BETWEEN MASS LOSS AND
2546  // LOSS OF NUMBER CONCENTRATION
2547  if (eprd < Real(0)) {
2548  dum = eprd * dt / morr_arr(i,j,k,MORRInd::qi3d);
2549  dum = std::max(-one, dum);
2550  nsubi = dum * morr_arr(i,j,k,MORRInd::ni3d) / dt;
2551  }
2552 
2553  if (eprds < Real(0)) {
2554  dum = eprds * dt / morr_arr(i,j,k,MORRInd::qni3d);
2555  dum = std::max(-one, dum);
2556  nsubs = dum * morr_arr(i,j,k,MORRInd::ns3d) / dt;
2557  }
2558 
2559  if (pre < Real(0)) {
2560  dum = pre * dt / morr_arr(i,j,k,MORRInd::qr3d);
2561  dum = std::max(-one, dum);
2562  nsubr = dum * morr_arr(i,j,k,MORRInd::nr3d) / dt;
2563  }
2564 
2565  if (eprdg < Real(0)) {
2566  dum = eprdg * dt / morr_arr(i,j,k,MORRInd::qg3d);
2567  dum = std::max(-one, dum);
2568  nsubg = dum * morr_arr(i,j,k,MORRInd::ng3d) / dt;
2569  }
2570 
2571  // UPDATE TENDENCIES
2572  morr_arr(i,j,k,MORRInd::ni3dten) = morr_arr(i,j,k,MORRInd::ni3dten) + nsubi;
2573  morr_arr(i,j,k,MORRInd::ns3dten) = morr_arr(i,j,k,MORRInd::ns3dten) + nsubs;
2574  morr_arr(i,j,k,MORRInd::ng3dten) = morr_arr(i,j,k,MORRInd::ng3dten) + nsubg;
2575  morr_arr(i,j,k,MORRInd::nr3dten) = morr_arr(i,j,k,MORRInd::nr3dten) + nsubr;
2576  }
2577  ltrue = 1;
2578  }
2579  // label_200:
2580  } // k
2581 
2582  for(int k=klo; k<=khi; k++) {
2583  // INITIALIZE PRECIP AND SNOW RATES
2584  morr_arr(i,j,k,MORRInd::precrt) = Real(0);
2585  morr_arr(i,j,k,MORRInd::snowrt) = Real(0);
2586  // hm added 7/13/13
2587  morr_arr(i,j,k,MORRInd::snowprt) = Real(0);
2588  morr_arr(i,j,k,MORRInd::grplprt) = Real(0);
2589  morr_arr(i,j,k,MORRInd::rainonlyprt) = Real(0);
2590  morr_arr(i,j,k,MORRInd::snowonlyprt) = Real(0);
2591  } // k
2592 
2593  nstep = 1;
2594 
2595  // At the top of a fine patch, rain, snow, ... come in from the coarse level.
2596  // Add what enters during this step to the top cell as a tendency, before the
2597  // fall speeds are computed, so it falls with what is already there; record it
2598  // on the top face.
2599  if (inflow_arr && inflow_arr(i,j,khi+1,MorrSed::NumComps) > Real(0.5)) {
2600  const Real fac = one / (morr_arr(i,j,khi,MORRInd::rho) * morr_arr(i,j,khi,MORRInd::dzq) * dt);
2601  morr_arr(i,j,khi,MORRInd::qc3dten) += inflow_arr(i,j,khi+1,MorrSed::qc) * fac;
2602  morr_arr(i,j,khi,MORRInd::qi3dten) += inflow_arr(i,j,khi+1,MorrSed::qi) * fac;
2603  morr_arr(i,j,khi,MORRInd::qr3dten) += inflow_arr(i,j,khi+1,MorrSed::qr) * fac;
2604  morr_arr(i,j,khi,MORRInd::qni3dten) += inflow_arr(i,j,khi+1,MorrSed::qs) * fac;
2605  morr_arr(i,j,khi,MORRInd::qg3dten) += inflow_arr(i,j,khi+1,MorrSed::qg) * fac;
2606  morr_arr(i,j,khi,MORRInd::nc3dten) += inflow_arr(i,j,khi+1,MorrSed::nc) * fac;
2607  morr_arr(i,j,khi,MORRInd::ni3dten) += inflow_arr(i,j,khi+1,MorrSed::ni) * fac;
2608  morr_arr(i,j,khi,MORRInd::nr3dten) += inflow_arr(i,j,khi+1,MorrSed::nr) * fac;
2609  morr_arr(i,j,khi,MORRInd::ns3dten) += inflow_arr(i,j,khi+1,MorrSed::ns) * fac;
2610  morr_arr(i,j,khi,MORRInd::ng3dten) += inflow_arr(i,j,khi+1,MorrSed::ng) * fac;
2611  for (int n = 0; n < MorrSed::NumComps; ++n) {
2612  sed_arr(i,j,khi+1,n) += inflow_arr(i,j,khi+1,n);
2613  }
2614  ltrue = 1;
2615  }
2616 
2617  if (ltrue != 0) {
2618  //goto 400
2619  // CALCULATE SEDIMENTATION
2620  // THE NUMERICS HERE FOLLOW FROM REISNER ET AL. (1998)
2621  // FALLOUT TERMS ARE CALCULATED ON SPLIT TIME STEPS TO ENSURE NUMERICAL
2622  // STABILITY, I.E. COURANT# < 1
2623  // Loop from top to bottom (KTE to KTS)
2624  for(int k=khi; k>=klo; k--) {
2625 
2626  Real dum; // DUM: General dummy variable
2627 
2628  Real di0; // DI0: Characteristic diameter for ice
2629  Real ds0; // DS0: Characteristic diameter for snow
2630  Real dg0; // DG0: Characteristic diameter for graupel
2631  Real lammax; // LAMMAX: Maximum value for slope parameter
2632  Real lammin; // LAMMIN: Minimum value for slope parameter
2633 
2634  ds0 = three; // Size distribution parameter for snow
2635  di0 = three; // Size distribution parameter for cloud ice
2636  dg0 = three; // Size distribution parameter for graupel
2637 
2638  // Update prognostic variables with tendencies
2639  morr_arr(i,j,k,MORRInd::dumi) = morr_arr(i,j,k,MORRInd::qi3d) + morr_arr(i,j,k,MORRInd::qi3dten) * dt;
2640  morr_arr(i,j,k,MORRInd::dumqs) = morr_arr(i,j,k,MORRInd::qni3d) + morr_arr(i,j,k,MORRInd::qni3dten) * dt;
2641  morr_arr(i,j,k,MORRInd::dumr) = morr_arr(i,j,k,MORRInd::qr3d) + morr_arr(i,j,k,MORRInd::qr3dten) * dt;
2642  morr_arr(i,j,k,MORRInd::dumfni) = morr_arr(i,j,k,MORRInd::ni3d) + morr_arr(i,j,k,MORRInd::ni3dten) * dt;
2643  morr_arr(i,j,k,MORRInd::dumfns) = morr_arr(i,j,k,MORRInd::ns3d) + morr_arr(i,j,k,MORRInd::ns3dten) * dt;
2644  morr_arr(i,j,k,MORRInd::dumfnr) = morr_arr(i,j,k,MORRInd::nr3d) + morr_arr(i,j,k,MORRInd::nr3dten) * dt;
2645  morr_arr(i,j,k,MORRInd::dumc) = morr_arr(i,j,k,MORRInd::qc3d) + morr_arr(i,j,k,MORRInd::qc3dten) * dt;
2646  morr_arr(i,j,k,MORRInd::dumfnc) = morr_arr(i,j,k,MORRInd::nc3d) + morr_arr(i,j,k,MORRInd::nc3dten) * dt;
2647  morr_arr(i,j,k,MORRInd::dumg) = morr_arr(i,j,k,MORRInd::qg3d) + morr_arr(i,j,k,MORRInd::qg3dten) * dt;
2648  morr_arr(i,j,k,MORRInd::dumfng) = morr_arr(i,j,k,MORRInd::ng3d) + morr_arr(i,j,k,MORRInd::ng3dten) * dt;
2649 
2650  // SWITCH FOR CONSTANT DROPLET NUMBER
2651  if (iinum == 1) {
2652  morr_arr(i,j,k,MORRInd::dumfnc) = morr_arr(i,j,k,MORRInd::nc3d);
2653  }
2654 
2655  // MAKE SURE NUMBER CONCENTRATIONS ARE POSITIVE
2656  morr_arr(i,j,k,MORRInd::dumfni) = amrex::max(Real(0), morr_arr(i,j,k,MORRInd::dumfni));
2657  morr_arr(i,j,k,MORRInd::dumfns) = amrex::max(Real(0), morr_arr(i,j,k,MORRInd::dumfns));
2658  morr_arr(i,j,k,MORRInd::dumfnc) = amrex::max(Real(0), morr_arr(i,j,k,MORRInd::dumfnc));
2659  morr_arr(i,j,k,MORRInd::dumfnr) = amrex::max(Real(0), morr_arr(i,j,k,MORRInd::dumfnr));
2660  morr_arr(i,j,k,MORRInd::dumfng) = amrex::max(Real(0), morr_arr(i,j,k,MORRInd::dumfng));
2661 
2662  // CLOUD ICE
2663  if (morr_arr(i,j,k,MORRInd::dumi) >= m_qsmall) {
2664  morr_arr(i,j,k,MORRInd::dlami) = std::pow(m_cons12 * morr_arr(i,j,k,MORRInd::dumfni) / morr_arr(i,j,k,MORRInd::dumi), one/di0);
2665  morr_arr(i,j,k,MORRInd::dlami) = amrex::max(morr_arr(i,j,k,MORRInd::dlami), m_lammini);
2666  morr_arr(i,j,k,MORRInd::dlami) = amrex::min(morr_arr(i,j,k,MORRInd::dlami), m_lammaxi);
2667  }
2668 
2669  // RAIN
2670  if (morr_arr(i,j,k,MORRInd::dumr) >= m_qsmall) {
2671  morr_arr(i,j,k,MORRInd::dlamr) = std::pow(m_pi * m_rhow * morr_arr(i,j,k,MORRInd::dumfnr) / morr_arr(i,j,k,MORRInd::dumr), one/three);
2672  morr_arr(i,j,k,MORRInd::dlamr) = amrex::max(morr_arr(i,j,k,MORRInd::dlamr), m_lamminr);
2673  morr_arr(i,j,k,MORRInd::dlamr) = amrex::min(morr_arr(i,j,k,MORRInd::dlamr), m_lammaxr);
2674  }
2675 
2676  // CLOUD DROPLETS
2677  if (morr_arr(i,j,k,MORRInd::dumc) >= m_qsmall) {
2678  dum = morr_arr(i,j,k,MORRInd::pres) / (Real(287.15) * morr_arr(i,j,k,MORRInd::t3d));
2679  morr_arr(i,j,k,MORRInd::pgam) = Real(0.0005714) * (morr_arr(i,j,k,MORRInd::nc3d) / Real(1.0e6) * dum) + Real(0.2714);
2680  morr_arr(i,j,k,MORRInd::pgam) = one / (morr_arr(i,j,k,MORRInd::pgam) * morr_arr(i,j,k,MORRInd::pgam)) - one;
2681  morr_arr(i,j,k,MORRInd::pgam) = amrex::max(morr_arr(i,j,k,MORRInd::pgam), Real(2));
2682  morr_arr(i,j,k,MORRInd::pgam) = amrex::min(morr_arr(i,j,k,MORRInd::pgam), Real(10.0));
2683 
2684  morr_arr(i,j,k,MORRInd::dlamc) = std::pow(m_cons26 * morr_arr(i,j,k,MORRInd::dumfnc) * gamma_function(morr_arr(i,j,k,MORRInd::pgam) + Real(4.0)) /
2685  (morr_arr(i,j,k,MORRInd::dumc) * gamma_function(morr_arr(i,j,k,MORRInd::pgam) + one)), one/three);
2686  lammin = (morr_arr(i,j,k,MORRInd::pgam) + one) / Real(60.0e-6);
2687  lammax = (morr_arr(i,j,k,MORRInd::pgam) + one) / Real(1.0e-6);
2688  morr_arr(i,j,k,MORRInd::dlamc) = amrex::max(morr_arr(i,j,k,MORRInd::dlamc), lammin);
2689  morr_arr(i,j,k,MORRInd::dlamc) = amrex::min(morr_arr(i,j,k,MORRInd::dlamc), lammax);
2690  }
2691 
2692  // SNOW
2693  if (morr_arr(i,j,k,MORRInd::dumqs) >= m_qsmall) {
2694  morr_arr(i,j,k,MORRInd::dlams) = std::pow(m_cons1 * morr_arr(i,j,k,MORRInd::dumfns) / morr_arr(i,j,k,MORRInd::dumqs), one/ds0);
2695  morr_arr(i,j,k,MORRInd::dlams) = amrex::max(morr_arr(i,j,k,MORRInd::dlams), m_lammins);
2696  morr_arr(i,j,k,MORRInd::dlams) = amrex::min(morr_arr(i,j,k,MORRInd::dlams), m_lammaxs);
2697  }
2698 
2699  // GRAUPEL
2700  if (morr_arr(i,j,k,MORRInd::dumg) >= m_qsmall) {
2701  morr_arr(i,j,k,MORRInd::dlamg) = std::pow(m_cons2 * morr_arr(i,j,k,MORRInd::dumfng) / morr_arr(i,j,k,MORRInd::dumg), one/dg0);
2702  morr_arr(i,j,k,MORRInd::dlamg) = amrex::max(morr_arr(i,j,k,MORRInd::dlamg), m_lamming);
2703  morr_arr(i,j,k,MORRInd::dlamg) = amrex::min(morr_arr(i,j,k,MORRInd::dlamg), m_lammaxg);
2704  }
2705 
2706  // Calculate number-weighted and mass-weighted terminal fall speeds
2707  // CLOUD WATER
2708  if (morr_arr(i,j,k,MORRInd::dumc) >= m_qsmall) {
2709  morr_arr(i,j,k,MORRInd::unc) = morr_arr(i,j,k,MORRInd::acn) * gamma_function(one + m_bc + morr_arr(i,j,k,MORRInd::pgam)) /
2710  (std::pow(morr_arr(i,j,k,MORRInd::dlamc), m_bc) * gamma_function(morr_arr(i,j,k,MORRInd::pgam) + one));
2711  morr_arr(i,j,k,MORRInd::umc) = morr_arr(i,j,k,MORRInd::acn) * gamma_function(Real(4.) + m_bc + morr_arr(i,j,k,MORRInd::pgam)) /
2712  (std::pow(morr_arr(i,j,k,MORRInd::dlamc), m_bc) * gamma_function(morr_arr(i,j,k,MORRInd::pgam) + Real(4.)));
2713  } else {
2714  morr_arr(i,j,k,MORRInd::umc) = Real(0);
2715  morr_arr(i,j,k,MORRInd::unc) = Real(0);
2716  }
2717 
2718  // CLOUD ICE
2719  if (morr_arr(i,j,k,MORRInd::dumi) >= m_qsmall) {
2720  morr_arr(i,j,k,MORRInd::uni) = morr_arr(i,j,k,MORRInd::ain) * m_cons27 / std::pow(morr_arr(i,j,k,MORRInd::dlami), m_bi);
2721  morr_arr(i,j,k,MORRInd::umi) = morr_arr(i,j,k,MORRInd::ain) * m_cons28 / std::pow(morr_arr(i,j,k,MORRInd::dlami), m_bi);
2722  } else {
2723  morr_arr(i,j,k,MORRInd::umi) = Real(0);
2724  morr_arr(i,j,k,MORRInd::uni) = Real(0);
2725  }
2726 
2727  // RAIN
2728  if (morr_arr(i,j,k,MORRInd::dumr) >= m_qsmall) {
2729  morr_arr(i,j,k,MORRInd::unr) = morr_arr(i,j,k,MORRInd::arn) * m_cons6 / std::pow(morr_arr(i,j,k,MORRInd::dlamr), m_br);
2730  morr_arr(i,j,k,MORRInd::umr) = morr_arr(i,j,k,MORRInd::arn) * m_cons4 / std::pow(morr_arr(i,j,k,MORRInd::dlamr), m_br);
2731  } else {
2732  morr_arr(i,j,k,MORRInd::umr) = Real(0);
2733  morr_arr(i,j,k,MORRInd::unr) = Real(0);
2734  }
2735 
2736  // SNOW
2737  if (morr_arr(i,j,k,MORRInd::dumqs) >= m_qsmall) {
2738  morr_arr(i,j,k,MORRInd::ums) = morr_arr(i,j,k,MORRInd::asn) * m_cons3 / std::pow(morr_arr(i,j,k,MORRInd::dlams), m_bs);
2739  morr_arr(i,j,k,MORRInd::uns) = morr_arr(i,j,k,MORRInd::asn) * m_cons5 / std::pow(morr_arr(i,j,k,MORRInd::dlams), m_bs);
2740  } else {
2741  morr_arr(i,j,k,MORRInd::ums) = Real(0);
2742  morr_arr(i,j,k,MORRInd::uns) = Real(0);
2743  }
2744 
2745  // GRAUPEL
2746  if (morr_arr(i,j,k,MORRInd::dumg) >= m_qsmall) {
2747  morr_arr(i,j,k,MORRInd::umg) = morr_arr(i,j,k,MORRInd::agn) * m_cons7 / std::pow(morr_arr(i,j,k,MORRInd::dlamg), m_bg);
2748  morr_arr(i,j,k,MORRInd::ung) = morr_arr(i,j,k,MORRInd::agn) * m_cons8 / std::pow(morr_arr(i,j,k,MORRInd::dlamg), m_bg);
2749  } else {
2750  morr_arr(i,j,k,MORRInd::umg) = Real(0);
2751  morr_arr(i,j,k,MORRInd::ung) = Real(0);
2752  }
2753 
2754  // SET REALISTIC LIMITS ON FALLSPEED
2755  // Bug fix, 10/08/09
2756  dum = std::pow(m_rhosu / morr_arr(i,j,k,MORRInd::rho), Real(0.54));
2757  morr_arr(i,j,k,MORRInd::ums) = std::min(morr_arr(i,j,k,MORRInd::ums), Real(1.2) * dum);
2758  morr_arr(i,j,k,MORRInd::uns) = std::min(morr_arr(i,j,k,MORRInd::uns), Real(1.2) * dum);
2759 
2760  // Fix 053011
2761  // Fix for correction by AA 4/6/11
2762  morr_arr(i,j,k,MORRInd::umi) = std::min(morr_arr(i,j,k,MORRInd::umi), Real(1.2) * std::pow(m_rhosu / morr_arr(i,j,k,MORRInd::rho), Real(0.35)));
2763  morr_arr(i,j,k,MORRInd::uni) = std::min(morr_arr(i,j,k,MORRInd::uni), Real(1.2) * std::pow(m_rhosu / morr_arr(i,j,k,MORRInd::rho), Real(0.35)));
2764  morr_arr(i,j,k,MORRInd::umr) = std::min(morr_arr(i,j,k,MORRInd::umr), Real(9.1) * dum);
2765  morr_arr(i,j,k,MORRInd::unr) = std::min(morr_arr(i,j,k,MORRInd::unr), Real(9.1) * dum);
2766  morr_arr(i,j,k,MORRInd::umg) = std::min(morr_arr(i,j,k,MORRInd::umg), Real(20.) * dum);
2767  morr_arr(i,j,k,MORRInd::ung) = std::min(morr_arr(i,j,k,MORRInd::ung), Real(20.) * dum);
2768 
2769  // Set fall speed values
2770  morr_arr(i,j,k,MORRInd::fr) = morr_arr(i,j,k,MORRInd::umr); // RAIN FALL SPEED
2771  morr_arr(i,j,k,MORRInd::fi) = morr_arr(i,j,k,MORRInd::umi); // CLOUD ICE FALL SPEED
2772  morr_arr(i,j,k,MORRInd::fni) = morr_arr(i,j,k,MORRInd::uni); // CLOUD ICE NUMBER FALL SPEED
2773  morr_arr(i,j,k,MORRInd::fs) = morr_arr(i,j,k,MORRInd::ums); // SNOW FALL SPEED
2774  morr_arr(i,j,k,MORRInd::fns) = morr_arr(i,j,k,MORRInd::uns); // SNOW NUMBER FALL SPEED
2775  morr_arr(i,j,k,MORRInd::fnr) = morr_arr(i,j,k,MORRInd::unr); // RAIN NUMBER FALL SPEED
2776  morr_arr(i,j,k,MORRInd::fc) = morr_arr(i,j,k,MORRInd::umc); // CLOUD WATER FALL SPEED
2777  morr_arr(i,j,k,MORRInd::fnc) = morr_arr(i,j,k,MORRInd::unc); // CLOUD NUMBER FALL SPEED
2778  morr_arr(i,j,k,MORRInd::fg) = morr_arr(i,j,k,MORRInd::umg); // GRAUPEL FALL SPEED
2779  morr_arr(i,j,k,MORRInd::fng) = morr_arr(i,j,k,MORRInd::ung); // GRAUPEL NUMBER FALL SPEED
2780 
2781  // V3.3 MODIFY FALLSPEED BELOW LEVEL OF PRECIP
2782  if (morr_arr(i,j,k,MORRInd::fr) < Real(1.e-10)) {
2783  morr_arr(i,j,k,MORRInd::fr) = morr_arr(i,j,k+1,MORRInd::fr);
2784  }
2785  if (morr_arr(i,j,k,MORRInd::fi) < Real(1.e-10)) {
2786  morr_arr(i,j,k,MORRInd::fi) = morr_arr(i,j,k+1,MORRInd::fi);
2787  }
2788  if (morr_arr(i,j,k,MORRInd::fni) < Real(1.e-10)) {
2789  morr_arr(i,j,k,MORRInd::fni) = morr_arr(i,j,k+1,MORRInd::fni);
2790  }
2791  if (morr_arr(i,j,k,MORRInd::fs) < Real(1.e-10)) {
2792  morr_arr(i,j,k,MORRInd::fs) = morr_arr(i,j,k+1,MORRInd::fs);
2793  }
2794  if (morr_arr(i,j,k,MORRInd::fns) < Real(1.e-10)) {
2795  morr_arr(i,j,k,MORRInd::fns) = morr_arr(i,j,k+1,MORRInd::fns);
2796  }
2797  if (morr_arr(i,j,k,MORRInd::fnr) < Real(1.e-10)) {
2798  morr_arr(i,j,k,MORRInd::fnr) = morr_arr(i,j,k+1,MORRInd::fnr);
2799  }
2800  if (morr_arr(i,j,k,MORRInd::fc) < Real(1.e-10)) {
2801  morr_arr(i,j,k,MORRInd::fc) = morr_arr(i,j,k+1,MORRInd::fc);
2802  }
2803  if (morr_arr(i,j,k,MORRInd::fnc) < Real(1.e-10)) {
2804  morr_arr(i,j,k,MORRInd::fnc) = morr_arr(i,j,k+1,MORRInd::fnc);
2805  }
2806  if (morr_arr(i,j,k,MORRInd::fg) < Real(1.e-10)) {
2807  morr_arr(i,j,k,MORRInd::fg) = morr_arr(i,j,k+1,MORRInd::fg);
2808  }
2809  if (morr_arr(i,j,k,MORRInd::fng) < Real(1.e-10)) {
2810  morr_arr(i,j,k,MORRInd::fng) = morr_arr(i,j,k+1,MORRInd::fng);
2811  }
2812 
2813  // CALCULATE NUMBER OF SPLIT TIME STEPS
2814  // Find maximum fall speed at this point
2815  morr_arr(i,j,k,MORRInd::rgvm) = std::max({morr_arr(i,j,k,MORRInd::fr), morr_arr(i,j,k,MORRInd::fi), morr_arr(i,j,k,MORRInd::fs), morr_arr(i,j,k,MORRInd::fc),
2816  morr_arr(i,j,k,MORRInd::fni), morr_arr(i,j,k,MORRInd::fnr), morr_arr(i,j,k,MORRInd::fns), morr_arr(i,j,k,MORRInd::fnc),
2817  morr_arr(i,j,k,MORRInd::fg), morr_arr(i,j,k,MORRInd::fng)});
2818 
2819  // Calculate number of steps (dt and nstep would need to be defined elsewhere)
2820  nstep = std::max(static_cast<int>(morr_arr(i,j,k,MORRInd::rgvm) * dt / morr_arr(i,j,k,MORRInd::dzq) + one), nstep);
2821  // MULTIPLY VARIABLES BY RHO
2822  morr_arr(i,j,k,MORRInd::dumr) = morr_arr(i,j,k,MORRInd::dumr) * morr_arr(i,j,k,MORRInd::rho); // Rain water content * density
2823  morr_arr(i,j,k,MORRInd::dumi) = morr_arr(i,j,k,MORRInd::dumi) * morr_arr(i,j,k,MORRInd::rho); // Cloud ice content * density
2824  morr_arr(i,j,k,MORRInd::dumfni) = morr_arr(i,j,k,MORRInd::dumfni) * morr_arr(i,j,k,MORRInd::rho); // Cloud ice number * density
2825  morr_arr(i,j,k,MORRInd::dumqs) = morr_arr(i,j,k,MORRInd::dumqs) * morr_arr(i,j,k,MORRInd::rho); // Snow content * density
2826  morr_arr(i,j,k,MORRInd::dumfns) = morr_arr(i,j,k,MORRInd::dumfns) * morr_arr(i,j,k,MORRInd::rho); // Snow number * density
2827  morr_arr(i,j,k,MORRInd::dumfnr) = morr_arr(i,j,k,MORRInd::dumfnr) * morr_arr(i,j,k,MORRInd::rho); // Rain number * density
2828  morr_arr(i,j,k,MORRInd::dumc) = morr_arr(i,j,k,MORRInd::dumc) * morr_arr(i,j,k,MORRInd::rho); // Cloud water content * density
2829  morr_arr(i,j,k,MORRInd::dumfnc) = morr_arr(i,j,k,MORRInd::dumfnc) * morr_arr(i,j,k,MORRInd::rho); // Cloud droplet number * density
2830  morr_arr(i,j,k,MORRInd::dumg) = morr_arr(i,j,k,MORRInd::dumg) * morr_arr(i,j,k,MORRInd::rho); // Graupel content * density
2831  morr_arr(i,j,k,MORRInd::dumfng) = morr_arr(i,j,k,MORRInd::dumfng) * morr_arr(i,j,k,MORRInd::rho); // Graupel number * density
2832  } // k
2833 
2834  // Main time stepping loop for sedimentation
2835  for (int n = 1; n <= nstep; n++) {
2836  // Calculate initial fallout for each hydrometeor type for all levels
2837  for (int k = klo; k <= khi; k++) {
2838  morr_arr(i,j,k,MORRInd::faloutr) = morr_arr(i,j,k,MORRInd::fr) * morr_arr(i,j,k,MORRInd::dumr);
2839  morr_arr(i,j,k,MORRInd::falouti) = morr_arr(i,j,k,MORRInd::fi) * morr_arr(i,j,k,MORRInd::dumi);
2840  morr_arr(i,j,k,MORRInd::faloutni) = morr_arr(i,j,k,MORRInd::fni) * morr_arr(i,j,k,MORRInd::dumfni);
2841  morr_arr(i,j,k,MORRInd::falouts) = morr_arr(i,j,k,MORRInd::fs) * morr_arr(i,j,k,MORRInd::dumqs);
2842  morr_arr(i,j,k,MORRInd::faloutns) = morr_arr(i,j,k,MORRInd::fns) * morr_arr(i,j,k,MORRInd::dumfns);
2843  morr_arr(i,j,k,MORRInd::faloutnr) = morr_arr(i,j,k,MORRInd::fnr) * morr_arr(i,j,k,MORRInd::dumfnr);
2844  morr_arr(i,j,k,MORRInd::faloutc) = morr_arr(i,j,k,MORRInd::fc) * morr_arr(i,j,k,MORRInd::dumc);
2845  morr_arr(i,j,k,MORRInd::faloutnc) = morr_arr(i,j,k,MORRInd::fnc) * morr_arr(i,j,k,MORRInd::dumfnc);
2846  morr_arr(i,j,k,MORRInd::faloutg) = morr_arr(i,j,k,MORRInd::fg) * morr_arr(i,j,k,MORRInd::dumg);
2847  morr_arr(i,j,k,MORRInd::faloutng) = morr_arr(i,j,k,MORRInd::fng) * morr_arr(i,j,k,MORRInd::dumfng);
2848 
2849  // falout is the flux out of the bottom of cell k (face k) for this substep
2850  const Real dt_sub = dt / nstep;
2851  sed_arr(i,j,k,MorrSed::qc) += morr_arr(i,j,k,MORRInd::faloutc) * dt_sub;
2852  sed_arr(i,j,k,MorrSed::qi) += morr_arr(i,j,k,MORRInd::falouti) * dt_sub;
2853  sed_arr(i,j,k,MorrSed::qr) += morr_arr(i,j,k,MORRInd::faloutr) * dt_sub;
2854  sed_arr(i,j,k,MorrSed::qs) += morr_arr(i,j,k,MORRInd::falouts) * dt_sub;
2855  sed_arr(i,j,k,MorrSed::qg) += morr_arr(i,j,k,MORRInd::faloutg) * dt_sub;
2856  sed_arr(i,j,k,MorrSed::nc) += morr_arr(i,j,k,MORRInd::faloutnc) * dt_sub;
2857  sed_arr(i,j,k,MorrSed::ni) += morr_arr(i,j,k,MORRInd::faloutni) * dt_sub;
2858  sed_arr(i,j,k,MorrSed::nr) += morr_arr(i,j,k,MORRInd::faloutnr) * dt_sub;
2859  sed_arr(i,j,k,MorrSed::ns) += morr_arr(i,j,k,MORRInd::faloutns) * dt_sub;
2860  sed_arr(i,j,k,MorrSed::ng) += morr_arr(i,j,k,MORRInd::faloutng) * dt_sub;
2861  } //k
2862 
2863  // Process top of model level
2864  int k = khi;
2865 
2866  // Calculate tendencies at top level
2867  morr_arr(i,j,k,MORRInd::faltndr) = morr_arr(i,j,k,MORRInd::faloutr) / morr_arr(i,j,k,MORRInd::dzq);
2868  morr_arr(i,j,k,MORRInd::faltndi) = morr_arr(i,j,k,MORRInd::falouti) / morr_arr(i,j,k,MORRInd::dzq);
2869  morr_arr(i,j,k,MORRInd::faltndni) = morr_arr(i,j,k,MORRInd::faloutni) / morr_arr(i,j,k,MORRInd::dzq);
2870  morr_arr(i,j,k,MORRInd::faltnds) = morr_arr(i,j,k,MORRInd::falouts) / morr_arr(i,j,k,MORRInd::dzq);
2871  morr_arr(i,j,k,MORRInd::faltndns) = morr_arr(i,j,k,MORRInd::faloutns) / morr_arr(i,j,k,MORRInd::dzq);
2872  morr_arr(i,j,k,MORRInd::faltndnr) = morr_arr(i,j,k,MORRInd::faloutnr) / morr_arr(i,j,k,MORRInd::dzq);
2873  morr_arr(i,j,k,MORRInd::faltndc) = morr_arr(i,j,k,MORRInd::faloutc) / morr_arr(i,j,k,MORRInd::dzq);
2874  morr_arr(i,j,k,MORRInd::faltndnc) = morr_arr(i,j,k,MORRInd::faloutnc) / morr_arr(i,j,k,MORRInd::dzq);
2875  morr_arr(i,j,k,MORRInd::faltndg) = morr_arr(i,j,k,MORRInd::faloutg) / morr_arr(i,j,k,MORRInd::dzq);
2876  morr_arr(i,j,k,MORRInd::faltndng) = morr_arr(i,j,k,MORRInd::faloutng) / morr_arr(i,j,k,MORRInd::dzq);
2877 
2878  // Add fallout terms to Eulerian tendencies (scaled by time step and density)
2879  morr_arr(i,j,k,MORRInd::qrsten) = morr_arr(i,j,k,MORRInd::qrsten) - morr_arr(i,j,k,MORRInd::faltndr) / nstep / morr_arr(i,j,k,MORRInd::rho);
2880  morr_arr(i,j,k,MORRInd::qisten) = morr_arr(i,j,k,MORRInd::qisten) - morr_arr(i,j,k,MORRInd::faltndi) / nstep / morr_arr(i,j,k,MORRInd::rho);
2881  morr_arr(i,j,k,MORRInd::ni3dten) = morr_arr(i,j,k,MORRInd::ni3dten) - morr_arr(i,j,k,MORRInd::faltndni) / nstep / morr_arr(i,j,k,MORRInd::rho);
2882  morr_arr(i,j,k,MORRInd::qnisten) = morr_arr(i,j,k,MORRInd::qnisten) - morr_arr(i,j,k,MORRInd::faltnds) / nstep / morr_arr(i,j,k,MORRInd::rho);
2883  morr_arr(i,j,k,MORRInd::ns3dten) = morr_arr(i,j,k,MORRInd::ns3dten) - morr_arr(i,j,k,MORRInd::faltndns) / nstep / morr_arr(i,j,k,MORRInd::rho);
2884  morr_arr(i,j,k,MORRInd::nr3dten) = morr_arr(i,j,k,MORRInd::nr3dten) - morr_arr(i,j,k,MORRInd::faltndnr) / nstep / morr_arr(i,j,k,MORRInd::rho);
2885  morr_arr(i,j,k,MORRInd::qcsten) = morr_arr(i,j,k,MORRInd::qcsten) - morr_arr(i,j,k,MORRInd::faltndc) / nstep / morr_arr(i,j,k,MORRInd::rho);
2886  morr_arr(i,j,k,MORRInd::nc3dten) = morr_arr(i,j,k,MORRInd::nc3dten) - morr_arr(i,j,k,MORRInd::faltndnc) / nstep / morr_arr(i,j,k,MORRInd::rho);
2887  morr_arr(i,j,k,MORRInd::qgsten) = morr_arr(i,j,k,MORRInd::qgsten) - morr_arr(i,j,k,MORRInd::faltndg) / nstep / morr_arr(i,j,k,MORRInd::rho);
2888  morr_arr(i,j,k,MORRInd::ng3dten) = morr_arr(i,j,k,MORRInd::ng3dten) - morr_arr(i,j,k,MORRInd::faltndng) / nstep / morr_arr(i,j,k,MORRInd::rho);
2889 
2890  // Update temporary working variables
2891  morr_arr(i,j,k,MORRInd::dumr) = morr_arr(i,j,k,MORRInd::dumr) - morr_arr(i,j,k,MORRInd::faltndr) * dt / nstep;
2892  morr_arr(i,j,k,MORRInd::dumi) = morr_arr(i,j,k,MORRInd::dumi) - morr_arr(i,j,k,MORRInd::faltndi) * dt / nstep;
2893  morr_arr(i,j,k,MORRInd::dumfni) = morr_arr(i,j,k,MORRInd::dumfni) - morr_arr(i,j,k,MORRInd::faltndni) * dt / nstep;
2894  morr_arr(i,j,k,MORRInd::dumqs) = morr_arr(i,j,k,MORRInd::dumqs) - morr_arr(i,j,k,MORRInd::faltnds) * dt / nstep;
2895  morr_arr(i,j,k,MORRInd::dumfns) = morr_arr(i,j,k,MORRInd::dumfns) - morr_arr(i,j,k,MORRInd::faltndns) * dt / nstep;
2896  morr_arr(i,j,k,MORRInd::dumfnr) = morr_arr(i,j,k,MORRInd::dumfnr) - morr_arr(i,j,k,MORRInd::faltndnr) * dt / nstep;
2897  morr_arr(i,j,k,MORRInd::dumc) = morr_arr(i,j,k,MORRInd::dumc) - morr_arr(i,j,k,MORRInd::faltndc) * dt / nstep;
2898  morr_arr(i,j,k,MORRInd::dumfnc) = morr_arr(i,j,k,MORRInd::dumfnc) - morr_arr(i,j,k,MORRInd::faltndnc) * dt / nstep;
2899  morr_arr(i,j,k,MORRInd::dumg) = morr_arr(i,j,k,MORRInd::dumg) - morr_arr(i,j,k,MORRInd::faltndg) * dt / nstep;
2900  morr_arr(i,j,k,MORRInd::dumfng) = morr_arr(i,j,k,MORRInd::dumfng) - morr_arr(i,j,k,MORRInd::faltndng) * dt / nstep;
2901 
2902  // Process remaining levels from top to bottom
2903  for (k = khi-1; k >= klo; k--) {
2904  // Calculate tendencies based on difference between levels
2905  morr_arr(i,j,k,MORRInd::faltndr) = (morr_arr(i,j,k+1,MORRInd::faloutr) - morr_arr(i,j,k,MORRInd::faloutr)) / morr_arr(i,j,k,MORRInd::dzq);
2906  morr_arr(i,j,k,MORRInd::faltndi) = (morr_arr(i,j,k+1,MORRInd::falouti) - morr_arr(i,j,k,MORRInd::falouti)) / morr_arr(i,j,k,MORRInd::dzq);
2907  morr_arr(i,j,k,MORRInd::faltndni) = (morr_arr(i,j,k+1,MORRInd::faloutni) - morr_arr(i,j,k,MORRInd::faloutni)) / morr_arr(i,j,k,MORRInd::dzq);
2908  morr_arr(i,j,k,MORRInd::faltnds) = (morr_arr(i,j,k+1,MORRInd::falouts) - morr_arr(i,j,k,MORRInd::falouts)) / morr_arr(i,j,k,MORRInd::dzq);
2909  morr_arr(i,j,k,MORRInd::faltndns) = (morr_arr(i,j,k+1,MORRInd::faloutns) - morr_arr(i,j,k,MORRInd::faloutns)) / morr_arr(i,j,k,MORRInd::dzq);
2910  morr_arr(i,j,k,MORRInd::faltndnr) = (morr_arr(i,j,k+1,MORRInd::faloutnr) - morr_arr(i,j,k,MORRInd::faloutnr)) / morr_arr(i,j,k,MORRInd::dzq);
2911  morr_arr(i,j,k,MORRInd::faltndc) = (morr_arr(i,j,k+1,MORRInd::faloutc) - morr_arr(i,j,k,MORRInd::faloutc)) / morr_arr(i,j,k,MORRInd::dzq);
2912  morr_arr(i,j,k,MORRInd::faltndnc) = (morr_arr(i,j,k+1,MORRInd::faloutnc) - morr_arr(i,j,k,MORRInd::faloutnc)) / morr_arr(i,j,k,MORRInd::dzq);
2913  morr_arr(i,j,k,MORRInd::faltndg) = (morr_arr(i,j,k+1,MORRInd::faloutg) - morr_arr(i,j,k,MORRInd::faloutg)) / morr_arr(i,j,k,MORRInd::dzq);
2914  morr_arr(i,j,k,MORRInd::faltndng) = (morr_arr(i,j,k+1,MORRInd::faloutng) - morr_arr(i,j,k,MORRInd::faloutng)) / morr_arr(i,j,k,MORRInd::dzq);
2915 
2916  // Add fallout terms to Eulerian tendencies (positive here, as mass flows in from above)
2917  morr_arr(i,j,k,MORRInd::qrsten) = morr_arr(i,j,k,MORRInd::qrsten) + morr_arr(i,j,k,MORRInd::faltndr) / nstep / morr_arr(i,j,k,MORRInd::rho);
2918  morr_arr(i,j,k,MORRInd::qisten) = morr_arr(i,j,k,MORRInd::qisten) + morr_arr(i,j,k,MORRInd::faltndi) / nstep / morr_arr(i,j,k,MORRInd::rho);
2919  morr_arr(i,j,k,MORRInd::ni3dten) = morr_arr(i,j,k,MORRInd::ni3dten) + morr_arr(i,j,k,MORRInd::faltndni) / nstep / morr_arr(i,j,k,MORRInd::rho);
2920  morr_arr(i,j,k,MORRInd::qnisten) = morr_arr(i,j,k,MORRInd::qnisten) + morr_arr(i,j,k,MORRInd::faltnds) / nstep / morr_arr(i,j,k,MORRInd::rho);
2921  morr_arr(i,j,k,MORRInd::ns3dten) = morr_arr(i,j,k,MORRInd::ns3dten) + morr_arr(i,j,k,MORRInd::faltndns) / nstep / morr_arr(i,j,k,MORRInd::rho);
2922  morr_arr(i,j,k,MORRInd::nr3dten) = morr_arr(i,j,k,MORRInd::nr3dten) + morr_arr(i,j,k,MORRInd::faltndnr) / nstep / morr_arr(i,j,k,MORRInd::rho);
2923  morr_arr(i,j,k,MORRInd::qcsten) = morr_arr(i,j,k,MORRInd::qcsten) + morr_arr(i,j,k,MORRInd::faltndc) / nstep / morr_arr(i,j,k,MORRInd::rho);
2924  morr_arr(i,j,k,MORRInd::nc3dten) = morr_arr(i,j,k,MORRInd::nc3dten) + morr_arr(i,j,k,MORRInd::faltndnc) / nstep / morr_arr(i,j,k,MORRInd::rho);
2925  morr_arr(i,j,k,MORRInd::qgsten) = morr_arr(i,j,k,MORRInd::qgsten) + morr_arr(i,j,k,MORRInd::faltndg) / nstep / morr_arr(i,j,k,MORRInd::rho);
2926  morr_arr(i,j,k,MORRInd::ng3dten) = morr_arr(i,j,k,MORRInd::ng3dten) + morr_arr(i,j,k,MORRInd::faltndng) / nstep / morr_arr(i,j,k,MORRInd::rho);
2927  // Update temporary working variables
2928  morr_arr(i,j,k,MORRInd::dumr) = morr_arr(i,j,k,MORRInd::dumr) + morr_arr(i,j,k,MORRInd::faltndr) * dt / nstep;
2929  morr_arr(i,j,k,MORRInd::dumi) = morr_arr(i,j,k,MORRInd::dumi) + morr_arr(i,j,k,MORRInd::faltndi) * dt / nstep;
2930  morr_arr(i,j,k,MORRInd::dumfni) = morr_arr(i,j,k,MORRInd::dumfni) + morr_arr(i,j,k,MORRInd::faltndni) * dt / nstep;
2931  morr_arr(i,j,k,MORRInd::dumqs) = morr_arr(i,j,k,MORRInd::dumqs) + morr_arr(i,j,k,MORRInd::faltnds) * dt / nstep;
2932  morr_arr(i,j,k,MORRInd::dumfns) = morr_arr(i,j,k,MORRInd::dumfns) + morr_arr(i,j,k,MORRInd::faltndns) * dt / nstep;
2933  morr_arr(i,j,k,MORRInd::dumfnr) = morr_arr(i,j,k,MORRInd::dumfnr) + morr_arr(i,j,k,MORRInd::faltndnr) * dt / nstep;
2934  morr_arr(i,j,k,MORRInd::dumc) = morr_arr(i,j,k,MORRInd::dumc) + morr_arr(i,j,k,MORRInd::faltndc) * dt / nstep;
2935  morr_arr(i,j,k,MORRInd::dumfnc) = morr_arr(i,j,k,MORRInd::dumfnc) + morr_arr(i,j,k,MORRInd::faltndnc) * dt / nstep;
2936  morr_arr(i,j,k,MORRInd::dumg) = morr_arr(i,j,k,MORRInd::dumg) + morr_arr(i,j,k,MORRInd::faltndg) * dt / nstep;
2937  morr_arr(i,j,k,MORRInd::dumfng) = morr_arr(i,j,k,MORRInd::dumfng) + morr_arr(i,j,k,MORRInd::faltndng) * dt / nstep;
2938  }
2939  // Get precipitation and snowfall accumulation during the time step
2940  // Factor of 1000 converts from m to mm, but division by density
2941  // of liquid water cancels this factor of 1000
2942  int kts=klo;
2943  morr_arr(i,j,klo,MORRInd::precrt) += (morr_arr(i,j,kts,MORRInd::faloutr) + morr_arr(i,j,kts,MORRInd::faloutc) + morr_arr(i,j,kts,MORRInd::falouts) +
2944  morr_arr(i,j,kts,MORRInd::falouti) + morr_arr(i,j,kts,MORRInd::faloutg)) * dt / nstep;
2945  morr_arr(i,j,klo,MORRInd::snowrt) += (morr_arr(i,j,kts,MORRInd::falouts) + morr_arr(i,j,kts,MORRInd::falouti) + morr_arr(i,j,kts,MORRInd::faloutg)) * dt / nstep;
2946 
2947  // Added 7/13/13
2948  morr_arr(i,j,klo,MORRInd::snowprt) += (morr_arr(i,j,kts,MORRInd::falouti) + morr_arr(i,j,kts,MORRInd::falouts)) * dt / nstep;
2949  morr_arr(i,j,klo,MORRInd::grplprt) += morr_arr(i,j,kts,MORRInd::faloutg) * dt / nstep;
2950  morr_arr(i,j,klo,MORRInd::rainonlyprt) += morr_arr(i,j,kts,MORRInd::faloutr) * dt / nstep;
2951  morr_arr(i,j,klo,MORRInd::snowonlyprt) += morr_arr(i,j,kts,MORRInd::falouts) * dt / nstep;
2952  }
2953 
2954  for(int k=klo; k<=khi; k++) {
2955  Real evs; // EVS: Saturation vapor pressure
2956  Real eis; // EIS: Ice saturation vapor pressure
2957  Real qvs; // QVS: Saturation mixing ratio
2958  Real qvi; // QVI: Ice saturation mixing ratio
2959  Real qvqvs; // QVQVS: Saturation ratio
2960  Real qvqvsi; // QVQVSI: Ice saturation ratio
2961 
2962  // ADD ON SEDIMENTATION TENDENCIES FOR MIXING RATIO TO REST OF TENDENCIES
2963  morr_arr(i,j,k,MORRInd::qr3dten) = morr_arr(i,j,k,MORRInd::qr3dten) + morr_arr(i,j,k,MORRInd::qrsten);
2964  morr_arr(i,j,k,MORRInd::qi3dten) = morr_arr(i,j,k,MORRInd::qi3dten) + morr_arr(i,j,k,MORRInd::qisten);
2965  morr_arr(i,j,k,MORRInd::qc3dten) = morr_arr(i,j,k,MORRInd::qc3dten) + morr_arr(i,j,k,MORRInd::qcsten);
2966  morr_arr(i,j,k,MORRInd::qg3dten) = morr_arr(i,j,k,MORRInd::qg3dten) + morr_arr(i,j,k,MORRInd::qgsten);
2967  morr_arr(i,j,k,MORRInd::qni3dten) = morr_arr(i,j,k,MORRInd::qni3dten) + morr_arr(i,j,k,MORRInd::qnisten);
2968  // PUT ALL CLOUD ICE IN SNOW CATEGORY IF MEAN DIAMETER EXCEEDS 2 * dcs
2969  // bug fix
2970  if (morr_arr(i,j,k,MORRInd::qi3d) >= m_qsmall && morr_arr(i,j,k,MORRInd::t3d) < Real(273.15) && morr_arr(i,j,k,MORRInd::lami) >= Real(1.e-10)) {
2971  if (one/morr_arr(i,j,k,MORRInd::lami) >= Real(2)*m_dcs) {
2972  morr_arr(i,j,k,MORRInd::qni3dten) = morr_arr(i,j,k,MORRInd::qni3dten) + morr_arr(i,j,k,MORRInd::qi3d)/dt + morr_arr(i,j,k,MORRInd::qi3dten);
2973  morr_arr(i,j,k,MORRInd::ns3dten) = morr_arr(i,j,k,MORRInd::ns3dten) + morr_arr(i,j,k,MORRInd::ni3d)/dt + morr_arr(i,j,k,MORRInd::ni3dten);
2974  morr_arr(i,j,k,MORRInd::qi3dten) = -morr_arr(i,j,k,MORRInd::qi3d)/dt;
2975  morr_arr(i,j,k,MORRInd::ni3dten) = -morr_arr(i,j,k,MORRInd::ni3d)/dt;
2976  }
2977  }
2978 
2979  // Add tendencies to ensure consistency between mixing ratio and number concentration
2980  morr_arr(i,j,k,MORRInd::qc3d) = morr_arr(i,j,k,MORRInd::qc3d) + morr_arr(i,j,k,MORRInd::qc3dten)*dt;
2981  morr_arr(i,j,k,MORRInd::qi3d) = morr_arr(i,j,k,MORRInd::qi3d) + morr_arr(i,j,k,MORRInd::qi3dten)*dt;
2982  morr_arr(i,j,k,MORRInd::qni3d) = morr_arr(i,j,k,MORRInd::qni3d) + morr_arr(i,j,k,MORRInd::qni3dten)*dt;
2983  morr_arr(i,j,k,MORRInd::qr3d) = morr_arr(i,j,k,MORRInd::qr3d) + morr_arr(i,j,k,MORRInd::qr3dten)*dt;
2984  morr_arr(i,j,k,MORRInd::nc3d) = morr_arr(i,j,k,MORRInd::nc3d) + morr_arr(i,j,k,MORRInd::nc3dten)*dt;
2985  morr_arr(i,j,k,MORRInd::ni3d) = morr_arr(i,j,k,MORRInd::ni3d) + morr_arr(i,j,k,MORRInd::ni3dten)*dt;
2986  morr_arr(i,j,k,MORRInd::ns3d) = morr_arr(i,j,k,MORRInd::ns3d) + morr_arr(i,j,k,MORRInd::ns3dten)*dt;
2987  morr_arr(i,j,k,MORRInd::nr3d) = morr_arr(i,j,k,MORRInd::nr3d) + morr_arr(i,j,k,MORRInd::nr3dten)*dt;
2988  if (m_igraup == 0) {
2989  morr_arr(i,j,k,MORRInd::qg3d) = morr_arr(i,j,k,MORRInd::qg3d) + morr_arr(i,j,k,MORRInd::qg3dten)*dt;
2990  morr_arr(i,j,k,MORRInd::ng3d) = morr_arr(i,j,k,MORRInd::ng3d) + morr_arr(i,j,k,MORRInd::ng3dten)*dt;
2991  }
2992 
2993  // ADD TEMPERATURE AND WATER VAPOR TENDENCIES FROM MICROPHYSICS
2994  morr_arr(i,j,k,MORRInd::t3d) = morr_arr(i,j,k,MORRInd::t3d) + morr_arr(i,j,k,MORRInd::t3dten)*dt;
2995  morr_arr(i,j,k,MORRInd::qv3d) = morr_arr(i,j,k,MORRInd::qv3d) + morr_arr(i,j,k,MORRInd::qv3dten)*dt;
2996  // SATURATION VAPOR PRESSURE AND MIXING RATIO
2997  // hm, add fix for low pressure, 5/12/10
2998  // Assuming POLYSVP is defined elsewhere
2999  evs = std::min(Real(0.99) * morr_arr(i,j,k,MORRInd::pres), calc_saturation_vapor_pressure(morr_arr(i,j,k,MORRInd::t3d), 0)); // PA
3000  eis = std::min(Real(0.99) * morr_arr(i,j,k,MORRInd::pres), calc_saturation_vapor_pressure(morr_arr(i,j,k,MORRInd::t3d), 1)); // PA
3001 
3002  // MAKE SURE ICE SATURATION DOESN'T EXCEED WATER SAT. NEAR FREEZING
3003  if (eis > evs) {
3004  eis = evs; // temporary update: adjust ice saturation pressure
3005  }
3006 
3007  // SATURATION MIXING RATIOS
3008  qvs = m_ep_2 * evs / (morr_arr(i,j,k,MORRInd::pres) - evs); // budget equation: calculate water saturation mixing ratio
3009  qvi = m_ep_2 * eis / (morr_arr(i,j,k,MORRInd::pres) - eis); // budget equation: calculate ice saturation mixing ratio
3010 
3011  // SATURATION RATIOS
3012  qvqvs = morr_arr(i,j,k,MORRInd::qv3d) / qvs; // budget equation: calculate water saturation ratio
3013  qvqvsi = morr_arr(i,j,k,MORRInd::qv3d) / qvi; // budget equation: calculate ice saturation ratio
3014  // AT SUBSATURATION, REMOVE SMALL AMOUNTS OF CLOUD/PRECIP WATER
3015  if (qvqvs < Real(0.9)) {
3016  if (morr_arr(i,j,k,MORRInd::qr3d) < Real(1.0e-8)) {
3017  morr_arr(i,j,k,MORRInd::qv3d) += morr_arr(i,j,k,MORRInd::qr3d);
3018  morr_arr(i,j,k,MORRInd::t3d) -= morr_arr(i,j,k,MORRInd::qr3d) * morr_arr(i,j,k,MORRInd::xxlv) / morr_arr(i,j,k,MORRInd::cpm);
3019  morr_arr(i,j,k,MORRInd::qr3d) = Real(0);
3020  }
3021  if (morr_arr(i,j,k,MORRInd::qc3d) < Real(1.0e-8)) {
3022  morr_arr(i,j,k,MORRInd::qv3d) += morr_arr(i,j,k,MORRInd::qc3d);
3023  morr_arr(i,j,k,MORRInd::t3d) -= morr_arr(i,j,k,MORRInd::qc3d) * morr_arr(i,j,k,MORRInd::xxlv) / morr_arr(i,j,k,MORRInd::cpm);
3024  morr_arr(i,j,k,MORRInd::qc3d) = Real(0);
3025  }
3026  }
3027  if (qvqvsi < Real(0.9)) {
3028  if (morr_arr(i,j,k,MORRInd::qi3d) < Real(1.0e-8)) {
3029  morr_arr(i,j,k,MORRInd::qv3d) += morr_arr(i,j,k,MORRInd::qi3d);
3030  morr_arr(i,j,k,MORRInd::t3d) -= morr_arr(i,j,k,MORRInd::qi3d) * morr_arr(i,j,k,MORRInd::xxls) / morr_arr(i,j,k,MORRInd::cpm);
3031  morr_arr(i,j,k,MORRInd::qi3d) = Real(0);
3032  }
3033  if (morr_arr(i,j,k,MORRInd::qni3d) < Real(1.0e-8)) {
3034  morr_arr(i,j,k,MORRInd::qv3d) += morr_arr(i,j,k,MORRInd::qni3d);
3035  morr_arr(i,j,k,MORRInd::t3d) -= morr_arr(i,j,k,MORRInd::qni3d) * morr_arr(i,j,k,MORRInd::xxls) / morr_arr(i,j,k,MORRInd::cpm);
3036  morr_arr(i,j,k,MORRInd::qni3d) = Real(0);
3037  }
3038  if (morr_arr(i,j,k,MORRInd::qg3d) < Real(1.0e-8)) {
3039  morr_arr(i,j,k,MORRInd::qv3d) += morr_arr(i,j,k,MORRInd::qg3d);
3040  morr_arr(i,j,k,MORRInd::t3d) -= morr_arr(i,j,k,MORRInd::qg3d) * morr_arr(i,j,k,MORRInd::xxls) / morr_arr(i,j,k,MORRInd::cpm);
3041  morr_arr(i,j,k,MORRInd::qg3d) = Real(0);
3042  }
3043  }
3044  // IF MIXING RATIO < QSMALL SET MIXING RATIO AND NUMBER CONC TO ZERO
3045  if (morr_arr(i,j,k,MORRInd::qc3d) < m_qsmall) {
3046  morr_arr(i,j,k,MORRInd::qc3d) = Real(0);
3047  morr_arr(i,j,k,MORRInd::nc3d) = Real(0);
3048  morr_arr(i,j,k,MORRInd::effc) = Real(0);
3049  }
3050  if (morr_arr(i,j,k,MORRInd::qr3d) < m_qsmall) {
3051  morr_arr(i,j,k,MORRInd::qr3d) = Real(0);
3052  morr_arr(i,j,k,MORRInd::nr3d) = Real(0);
3053  morr_arr(i,j,k,MORRInd::effr) = Real(0);
3054  }
3055  if (morr_arr(i,j,k,MORRInd::qi3d) < m_qsmall) {
3056  morr_arr(i,j,k,MORRInd::qi3d) = Real(0);
3057  morr_arr(i,j,k,MORRInd::ni3d) = Real(0);
3058  morr_arr(i,j,k,MORRInd::effi) = Real(0);
3059  }
3060  if (morr_arr(i,j,k,MORRInd::qni3d) < m_qsmall) {
3061  morr_arr(i,j,k,MORRInd::qni3d) = Real(0);
3062  morr_arr(i,j,k,MORRInd::ns3d) = Real(0);
3063  morr_arr(i,j,k,MORRInd::effs) = Real(0);
3064  }
3065  if (morr_arr(i,j,k,MORRInd::qg3d) < m_qsmall) {
3066  morr_arr(i,j,k,MORRInd::qg3d) = Real(0);
3067  morr_arr(i,j,k,MORRInd::ng3d) = Real(0);
3068  morr_arr(i,j,k,MORRInd::effg) = Real(0);
3069  }
3070  /*
3071  // Skip calculations if there is no cloud/precipitation water
3072  if ((morr_arr(i,j,k,MORRInd::qc3d) < m_qsmall && // CLOUD WATER MIXING RATIO (KG/KG)
3073  morr_arr(i,j,k,MORRInd::qi3d) < m_qsmall && // CLOUD ICE MIXING RATIO (KG/KG)
3074  morr_arr(i,j,k,MORRInd::qni3d) < m_qsmall && // SNOW MIXING RATIO (KG/KG)
3075  morr_arr(i,j,k,MORRInd::qr3d) < m_qsmall && // RAIN MIXING RATIO (KG/KG)
3076  morr_arr(i,j,k,MORRInd::qg3d) < m_qsmall)) { // GRAUPEL MIX RATIO (KG/KG)
3077  goto label_500;
3078  } else {*/
3079  if (!(morr_arr(i,j,k,MORRInd::qc3d) < m_qsmall && // CLOUD WATER MIXING RATIO (KG/KG)
3080  morr_arr(i,j,k,MORRInd::qi3d) < m_qsmall && // CLOUD ICE MIXING RATIO (KG/KG)
3081  morr_arr(i,j,k,MORRInd::qni3d) < m_qsmall && // SNOW MIXING RATIO (KG/KG)
3082  morr_arr(i,j,k,MORRInd::qr3d) < m_qsmall && // RAIN MIXING RATIO (KG/KG)
3083  morr_arr(i,j,k,MORRInd::qg3d) < m_qsmall)) { // GRAUPEL MIX RATIO (KG/KG)
3084  // CALCULATE INSTANTANEOUS PROCESSES
3085 
3086  // ADD MELTING OF CLOUD ICE TO FORM RAIN
3087  if (morr_arr(i,j,k,MORRInd::qi3d) >= m_qsmall && morr_arr(i,j,k,MORRInd::t3d) >= Real(273.15)) {
3088  morr_arr(i,j,k,MORRInd::qr3d) = morr_arr(i,j,k,MORRInd::qr3d) + morr_arr(i,j,k,MORRInd::qi3d);
3089  morr_arr(i,j,k,MORRInd::t3d) = morr_arr(i,j,k,MORRInd::t3d) - morr_arr(i,j,k,MORRInd::qi3d) * morr_arr(i,j,k,MORRInd::xlf) / morr_arr(i,j,k,MORRInd::cpm);
3090  morr_arr(i,j,k,MORRInd::qi3d) = Real(0);
3091  morr_arr(i,j,k,MORRInd::nr3d) = morr_arr(i,j,k,MORRInd::nr3d) + morr_arr(i,j,k,MORRInd::ni3d);
3092  morr_arr(i,j,k,MORRInd::ni3d) = Real(0);
3093  }
3094  // ****SENSITIVITY - NO ICE
3095  if ((m_iliq != 1)) {
3096 
3097  // HOMOGENEOUS FREEZING OF CLOUD WATER
3098  if (morr_arr(i,j,k,MORRInd::t3d) <= Real(233.15) && morr_arr(i,j,k,MORRInd::qc3d) >= m_qsmall) {
3099  morr_arr(i,j,k,MORRInd::qi3d) = morr_arr(i,j,k,MORRInd::qi3d) + morr_arr(i,j,k,MORRInd::qc3d);
3100  morr_arr(i,j,k,MORRInd::t3d) = morr_arr(i,j,k,MORRInd::t3d) + morr_arr(i,j,k,MORRInd::qc3d) * morr_arr(i,j,k,MORRInd::xlf) / morr_arr(i,j,k,MORRInd::cpm);
3101  morr_arr(i,j,k,MORRInd::qc3d) = Real(0);
3102  morr_arr(i,j,k,MORRInd::ni3d) = morr_arr(i,j,k,MORRInd::ni3d) + morr_arr(i,j,k,MORRInd::nc3d);
3103  morr_arr(i,j,k,MORRInd::nc3d) = Real(0);
3104  }
3105  // HOMOGENEOUS FREEZING OF RAIN
3106  if (m_igraup == 0) {
3107  if (morr_arr(i,j,k,MORRInd::t3d) <= Real(233.15) && morr_arr(i,j,k,MORRInd::qr3d) >= m_qsmall) {
3108  morr_arr(i,j,k,MORRInd::qg3d) = morr_arr(i,j,k,MORRInd::qg3d) + morr_arr(i,j,k,MORRInd::qr3d);
3109  morr_arr(i,j,k,MORRInd::t3d) = morr_arr(i,j,k,MORRInd::t3d) + morr_arr(i,j,k,MORRInd::qr3d) * morr_arr(i,j,k,MORRInd::xlf) / morr_arr(i,j,k,MORRInd::cpm);
3110  morr_arr(i,j,k,MORRInd::qr3d) = Real(0);
3111  morr_arr(i,j,k,MORRInd::ng3d) = morr_arr(i,j,k,MORRInd::ng3d) + morr_arr(i,j,k,MORRInd::nr3d);
3112  morr_arr(i,j,k,MORRInd::nr3d) = Real(0);
3113  }
3114  } else if (m_igraup == 1) {
3115  if (morr_arr(i,j,k,MORRInd::t3d) <= Real(233.15) && morr_arr(i,j,k,MORRInd::qr3d) >= m_qsmall) {
3116  morr_arr(i,j,k,MORRInd::qni3d) = morr_arr(i,j,k,MORRInd::qni3d) + morr_arr(i,j,k,MORRInd::qr3d);
3117  morr_arr(i,j,k,MORRInd::t3d) = morr_arr(i,j,k,MORRInd::t3d) + morr_arr(i,j,k,MORRInd::qr3d) * morr_arr(i,j,k,MORRInd::xlf) / morr_arr(i,j,k,MORRInd::cpm);
3118  morr_arr(i,j,k,MORRInd::qr3d) = Real(0);
3119  morr_arr(i,j,k,MORRInd::ns3d) = morr_arr(i,j,k,MORRInd::ns3d) + morr_arr(i,j,k,MORRInd::nr3d);
3120  morr_arr(i,j,k,MORRInd::nr3d) = Real(0);
3121  }
3122  }
3123 
3124  }/* else {
3125  Real dontdoanything=m_iliq;//printf("m_iliq: %d\n",m_iliq);// goto label_778;
3126  }*/
3127 
3128 // label_778:
3129  // MAKE SURE NUMBER CONCENTRATIONS AREN'T NEGATIVE
3130  morr_arr(i,j,k,MORRInd::ni3d) = std::max(Real(0), morr_arr(i,j,k,MORRInd::ni3d));
3131  morr_arr(i,j,k,MORRInd::ns3d) = std::max(Real(0), morr_arr(i,j,k,MORRInd::ns3d));
3132  morr_arr(i,j,k,MORRInd::nc3d) = std::max(Real(0), morr_arr(i,j,k,MORRInd::nc3d));
3133  morr_arr(i,j,k,MORRInd::nr3d) = std::max(Real(0), morr_arr(i,j,k,MORRInd::nr3d));
3134  morr_arr(i,j,k,MORRInd::ng3d) = std::max(Real(0), morr_arr(i,j,k,MORRInd::ng3d));
3135 
3136  // CLOUD ICE
3137  if (morr_arr(i,j,k,MORRInd::qi3d) >= m_qsmall) {
3138  morr_arr(i,j,k,MORRInd::lami) = std::pow(m_cons12 * morr_arr(i,j,k,MORRInd::ni3d) / morr_arr(i,j,k,MORRInd::qi3d), one/m_di);
3139  // CHECK FOR SLOPE
3140  // ADJUST VARS
3141  if (morr_arr(i,j,k,MORRInd::lami) < m_lammini) {
3142  morr_arr(i,j,k,MORRInd::lami) = m_lammini;
3143  morr_arr(i,j,k,MORRInd::n0i) = amrex::Math::powi<4>(morr_arr(i,j,k,MORRInd::lami)) * morr_arr(i,j,k,MORRInd::qi3d) / m_cons12;
3144  morr_arr(i,j,k,MORRInd::ni3d) = morr_arr(i,j,k,MORRInd::n0i) / morr_arr(i,j,k,MORRInd::lami);
3145  } else if (morr_arr(i,j,k,MORRInd::lami) > m_lammaxi) {
3146  morr_arr(i,j,k,MORRInd::lami) = m_lammaxi;
3147  morr_arr(i,j,k,MORRInd::n0i) = amrex::Math::powi<4>(morr_arr(i,j,k,MORRInd::lami)) * morr_arr(i,j,k,MORRInd::qi3d) / m_cons12;
3148  morr_arr(i,j,k,MORRInd::ni3d) = morr_arr(i,j,k,MORRInd::n0i) / morr_arr(i,j,k,MORRInd::lami);
3149  }
3150  }
3151 
3152  // RAIN
3153  if (morr_arr(i,j,k,MORRInd::qr3d) >= m_qsmall) {
3154  morr_arr(i,j,k,MORRInd::lamr) = std::pow(m_pi * m_rhow * morr_arr(i,j,k,MORRInd::nr3d) / morr_arr(i,j,k,MORRInd::qr3d), one/three);
3155 
3156  // CHECK FOR SLOPE
3157  // ADJUST VARS
3158  if (morr_arr(i,j,k,MORRInd::lamr) < m_lamminr) {
3159  morr_arr(i,j,k,MORRInd::lamr) = m_lamminr;
3160  morr_arr(i,j,k,MORRInd::n0r) = amrex::Math::powi<4>(morr_arr(i,j,k,MORRInd::lamr)) * morr_arr(i,j,k,MORRInd::qr3d) / (m_pi * m_rhow);
3161  morr_arr(i,j,k,MORRInd::nr3d) = morr_arr(i,j,k,MORRInd::n0r) / morr_arr(i,j,k,MORRInd::lamr);
3162  } else if (morr_arr(i,j,k,MORRInd::lamr) > m_lammaxr) {
3163  morr_arr(i,j,k,MORRInd::lamr) = m_lammaxr;
3164  morr_arr(i,j,k,MORRInd::n0r) = amrex::Math::powi<4>(morr_arr(i,j,k,MORRInd::lamr)) * morr_arr(i,j,k,MORRInd::qr3d) / (m_pi * m_rhow);
3165  morr_arr(i,j,k,MORRInd::nr3d) = morr_arr(i,j,k,MORRInd::n0r) / morr_arr(i,j,k,MORRInd::lamr);
3166  }
3167  }
3168 
3169  // CLOUD DROPLETS
3170  // MARTIN ET AL. (1994) FORMULA FOR PGAM
3171  if (morr_arr(i,j,k,MORRInd::qc3d) >= m_qsmall) {
3172  Real dum = morr_arr(i,j,k,MORRInd::pres) / (Real(287.15) * morr_arr(i,j,k,MORRInd::t3d));
3173  morr_arr(i,j,k,MORRInd::pgam) = Real(0.0005714) * (morr_arr(i,j,k,MORRInd::nc3d) / Real(1.0e6) * dum) + Real(0.2714);
3174  morr_arr(i,j,k,MORRInd::pgam) = one/(amrex::Math::powi<2>(morr_arr(i,j,k,MORRInd::pgam))) - one;
3175  morr_arr(i,j,k,MORRInd::pgam) = std::max(morr_arr(i,j,k,MORRInd::pgam), Real(2));
3176  morr_arr(i,j,k,MORRInd::pgam) = std::min(morr_arr(i,j,k,MORRInd::pgam), Real(10.0));
3177 
3178  // CALCULATE LAMC
3179  morr_arr(i,j,k,MORRInd::lamc) = std::pow(m_cons26 * morr_arr(i,j,k,MORRInd::nc3d) * gamma_function(morr_arr(i,j,k,MORRInd::pgam) + Real(4.0)) /
3180  (morr_arr(i,j,k,MORRInd::qc3d) * gamma_function(morr_arr(i,j,k,MORRInd::pgam) + one)), one/three);
3181 
3182  // LAMMIN, 60 MICRON DIAMETER
3183  // LAMMAX, 1 MICRON
3184  Real lammin = (morr_arr(i,j,k,MORRInd::pgam) + one) / Real(60.0e-6);
3185  Real lammax = (morr_arr(i,j,k,MORRInd::pgam) + one) / Real(1.0e-6);
3186 
3187  if (morr_arr(i,j,k,MORRInd::lamc) < lammin) {
3188  morr_arr(i,j,k,MORRInd::lamc) = lammin;
3189  morr_arr(i,j,k,MORRInd::nc3d) = std::exp(three * std::log(morr_arr(i,j,k,MORRInd::lamc)) + std::log(morr_arr(i,j,k,MORRInd::qc3d)) +
3190  std::log(gamma_function(morr_arr(i,j,k,MORRInd::pgam) + one)) - std::log(gamma_function(morr_arr(i,j,k,MORRInd::pgam) + Real(4.0)))) / m_cons26;
3191  } else if (morr_arr(i,j,k,MORRInd::lamc) > lammax) {
3192  morr_arr(i,j,k,MORRInd::lamc) = lammax;
3193  morr_arr(i,j,k,MORRInd::nc3d) = std::exp(three * std::log(morr_arr(i,j,k,MORRInd::lamc)) + std::log(morr_arr(i,j,k,MORRInd::qc3d)) +
3194  std::log(gamma_function(morr_arr(i,j,k,MORRInd::pgam) + one)) - std::log(gamma_function(morr_arr(i,j,k,MORRInd::pgam) + Real(4.0)))) / m_cons26;
3195  }
3196  }
3197 
3198  // SNOW
3199  if (morr_arr(i,j,k,MORRInd::qni3d) >= m_qsmall) {
3200  morr_arr(i,j,k,MORRInd::lams) = std::pow(m_cons1 * morr_arr(i,j,k,MORRInd::ns3d) / morr_arr(i,j,k,MORRInd::qni3d), one/m_ds);
3201 
3202  // CHECK FOR SLOPE
3203  // ADJUST VARS
3204  if (morr_arr(i,j,k,MORRInd::lams) < m_lammins) {
3205  morr_arr(i,j,k,MORRInd::lams) = m_lammins;
3206  morr_arr(i,j,k,MORRInd::n0s) = amrex::Math::powi<4>(morr_arr(i,j,k,MORRInd::lams)) * morr_arr(i,j,k,MORRInd::qni3d) / m_cons1;
3207  morr_arr(i,j,k,MORRInd::ns3d) = morr_arr(i,j,k,MORRInd::n0s) / morr_arr(i,j,k,MORRInd::lams);
3208  } else if (morr_arr(i,j,k,MORRInd::lams) > m_lammaxs) {
3209  morr_arr(i,j,k,MORRInd::lams) = m_lammaxs;
3210  morr_arr(i,j,k,MORRInd::n0s) = amrex::Math::powi<4>(morr_arr(i,j,k,MORRInd::lams)) * morr_arr(i,j,k,MORRInd::qni3d) / m_cons1;
3211  morr_arr(i,j,k,MORRInd::ns3d) = morr_arr(i,j,k,MORRInd::n0s) / morr_arr(i,j,k,MORRInd::lams);
3212  }
3213  }
3214 
3215  // GRAUPEL
3216  if (morr_arr(i,j,k,MORRInd::qg3d) >= m_qsmall) {
3217  morr_arr(i,j,k,MORRInd::lamg) = std::pow(m_cons2 * morr_arr(i,j,k,MORRInd::ng3d) / morr_arr(i,j,k,MORRInd::qg3d), one/m_dg);
3218 
3219  // CHECK FOR SLOPE
3220  // ADJUST VARS
3221  if (morr_arr(i,j,k,MORRInd::lamg) < m_lamming) {
3222  morr_arr(i,j,k,MORRInd::lamg) = m_lamming;
3223  morr_arr(i,j,k,MORRInd::n0g) = amrex::Math::powi<4>(morr_arr(i,j,k,MORRInd::lamg)) * morr_arr(i,j,k,MORRInd::qg3d) / m_cons2;
3224  morr_arr(i,j,k,MORRInd::ng3d) = morr_arr(i,j,k,MORRInd::n0g) / morr_arr(i,j,k,MORRInd::lamg);
3225  } else if (morr_arr(i,j,k,MORRInd::lamg) > m_lammaxg) {
3226  morr_arr(i,j,k,MORRInd::lamg) = m_lammaxg;
3227  morr_arr(i,j,k,MORRInd::n0g) = amrex::Math::powi<4>(morr_arr(i,j,k,MORRInd::lamg)) * morr_arr(i,j,k,MORRInd::qg3d) / m_cons2;
3228  morr_arr(i,j,k,MORRInd::ng3d) = morr_arr(i,j,k,MORRInd::n0g) / morr_arr(i,j,k,MORRInd::lamg);
3229  }
3230  }
3231  }
3232 
3233 // label_500:
3234  // CALCULATE EFFECTIVE RADIUS
3235  if (morr_arr(i,j,k,MORRInd::qi3d) >= m_qsmall) {
3236  morr_arr(i,j,k,MORRInd::effi) = three / morr_arr(i,j,k,MORRInd::lami) / Real(2) * Real(1.0e6);
3237  } else {
3238  morr_arr(i,j,k,MORRInd::effi) = Real(25.0);
3239  }
3240 
3241  if (morr_arr(i,j,k,MORRInd::qni3d) >= m_qsmall) {
3242  morr_arr(i,j,k,MORRInd::effs) = three / morr_arr(i,j,k,MORRInd::lams) / Real(2) * Real(1.0e6);
3243  } else {
3244  morr_arr(i,j,k,MORRInd::effs) = Real(25.0);
3245  }
3246 
3247  if (morr_arr(i,j,k,MORRInd::qr3d) >= m_qsmall) {
3248  morr_arr(i,j,k,MORRInd::effr) = three / morr_arr(i,j,k,MORRInd::lamr) / Real(2) * Real(1.0e6);
3249  } else {
3250  morr_arr(i,j,k,MORRInd::effr) = Real(25.0);
3251  }
3252 
3253  if (morr_arr(i,j,k,MORRInd::qc3d) >= m_qsmall) {
3254  morr_arr(i,j,k,MORRInd::effc) = gamma_function(morr_arr(i,j,k,MORRInd::pgam) + Real(4.0)) / gamma_function(morr_arr(i,j,k,MORRInd::pgam) + three) / morr_arr(i,j,k,MORRInd::lamc) / Real(2) * Real(1.0e6);
3255  } else {
3256  morr_arr(i,j,k,MORRInd::effc) = Real(25.0);
3257  }
3258 
3259  if (morr_arr(i,j,k,MORRInd::qg3d) >= m_qsmall) {
3260  morr_arr(i,j,k,MORRInd::effg) = three / morr_arr(i,j,k,MORRInd::lamg) / Real(2) * Real(1.0e6);
3261  } else {
3262  morr_arr(i,j,k,MORRInd::effg) = Real(25.0);
3263  }
3264 
3265  // HM ADD 1/10/06, ADD UPPER BOUND ON ICE NUMBER, THIS IS NEEDED
3266  // TO PREVENT VERY LARGE ICE NUMBER DUE TO HOMOGENEOUS FREEZING
3267  // OF DROPLETS, ESPECIALLY WHEN INUM = 1, SET MAX AT 10 CM-3
3268  // HM, 12/28/12, LOWER MAXIMUM ICE CONCENTRATION TO ADDRESS PROBLEM
3269  // OF EXCESSIVE AND PERSISTENT ANVIL
3270  // NOTE: THIS MAY CHANGE/REDUCE SENSITIVITY TO AEROSOL/CCN CONCENTRATION
3271  morr_arr(i,j,k,MORRInd::ni3d) = std::min(morr_arr(i,j,k,MORRInd::ni3d), Real(0.3e6) / morr_arr(i,j,k,MORRInd::rho));
3272 
3273  // ADD BOUND ON DROPLET NUMBER - CANNOT EXCEED AEROSOL CONCENTRATION
3274  if (iinum == 0 && m_iact == 2) {
3275  morr_arr(i,j,k,MORRInd::nc3d) = std::min(morr_arr(i,j,k,MORRInd::nc3d), (m_nanew1 + m_nanew2) / morr_arr(i,j,k,MORRInd::rho));
3276  }
3277 
3278  // SWITCH FOR CONSTANT DROPLET NUMBER
3279  if (iinum == 1) {
3280  // CHANGE NDCNST FROM CM-3 TO KG-1
3281  morr_arr(i,j,k,MORRInd::nc3d) =
3282  ndcnst_to_number_mixing_ratio(m_ndcnst, rho_arr(i,j,k));
3283  }
3284  }
3285 
3286  }/* else {
3287  goto label_400;
3288  }
3289  label_400:*/
3290  //End of _micro
3291 
3292  if(use_morr_cpp_answer) {
3293  for (int k=klo; k<=khi; k++) {
3294  // Transfer 1D variables back to 3D arrays
3295  qcl_arr(i,j,k) = morr_arr(i,j,k,MORRInd::qc3d);
3296  qci_arr(i,j,k) = morr_arr(i,j,k,MORRInd::qi3d);
3297  qps_arr(i,j,k) = morr_arr(i,j,k,MORRInd::qni3d);
3298  qpr_arr(i,j,k) = morr_arr(i,j,k,MORRInd::qr3d);
3299  nc_arr(i,j,k) = morr_arr(i,j,k,MORRInd::nc3d);
3300  ni_arr(i,j,k) = morr_arr(i,j,k,MORRInd::ni3d);
3301  ns_arr(i,j,k) = morr_arr(i,j,k,MORRInd::ns3d);
3302  nr_arr(i,j,k) = morr_arr(i,j,k,MORRInd::nr3d);
3303  qpg_arr(i,j,k) = morr_arr(i,j,k,MORRInd::qg3d);
3304  ng_arr(i,j,k) = morr_arr(i,j,k,MORRInd::ng3d);
3305 
3306  // Temperature and potential temperature conversion
3307  theta_arr(i,j,k) = morr_arr(i,j,k,MORRInd::t3d) / pii_arr(i,j,k); // Convert temp back to potential temp
3308  qv_arr(i,j,k) = morr_arr(i,j,k,MORRInd::qv3d);
3309 
3310  //Deleted wrf-check, effc, and precr type data as not used by ERF
3311  /*
3312  // NEED gpu-compatible summation for rain_accum, check SAM or Kessler for better example
3313  rain_accum_arr(i,j,k) = rain_accum_arr(i,j,k) + morr_arr(i,j,k,MORRInd::precrt);
3314  snow_accum_arr(i,j,k) = snow_accum_arr(i,j,k) + morr_arr(i,j,k,MORRInd::snowprt);
3315  graupel_accum_arr(i,j,k) = graupel_accum_arr(i,j,k) + morr_arr(i,j,k,MORRInd::grplprt);
3316  */
3317 
3318  rainncv_arr(i,j,0) = morr_arr(i,j,klo,MORRInd::precrt);
3319  snowncv_arr(i,j,0) = morr_arr(i,j,klo,MORRInd::snowprt);
3320  graupelncv_arr(i,j,0) = morr_arr(i,j,klo,MORRInd::grplprt);
3321  sr_arr(i,j,0) = morr_arr(i,j,klo,MORRInd::snowrt) / (morr_arr(i,j,klo,MORRInd::precrt) + Real(1.e-12));
3322  } // k
3323 
3324  // Update precipitation accumulation variables
3325  // These are outside the k-loop in the original code
3326  if (klo == dom_klo) {
3327  // Each species alone, and the total, which also holds the cloud water
3328  // and cloud ice that fell out
3329  rain_accum_arr(i,j,klo) += morr_arr(i,j,klo,MORRInd::rainonlyprt);
3330  snow_accum_arr(i,j,klo) += morr_arr(i,j,klo,MORRInd::snowonlyprt);
3331  graupel_accum_arr(i,j,klo) += morr_arr(i,j,klo,MORRInd::grplprt);
3332  precip_accum_arr(i,j,klo) += morr_arr(i,j,klo,MORRInd::precrt);
3333  }
3334 
3335  } // cpp
3336  });
3337 
3338  }
3339 
3340  if (run_morr_fort) {
3341 #ifdef ERF_USE_MORR_FORT
3342 #include "ERF_Morrison_Advance_F.H"
3343 #endif
3344  } // run_morr_fort
3345 
3346  }
3347  }
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(axis >=0 &&axis< AMREX_SPACEDIM, "prob.axis must be 0, 1 or 2")
ParmParse pp("prob")
const int khi
Definition: ERF_InitCustomPert_Bubble.H:25
const int klo
Definition: ERF_InitCustomPert_KE.H:9
auto qv_arr
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:222
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Real gamma_function(Real x)
Definition: ERF_MorrisonGammaFunction.H:300
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real calc_saturation_vapor_pressure(const amrex::Real T, const int type)
Definition: ERF_MorrisonVaporPressure.H:36
Arena * Arena_Used
Definition: ERF_Morrison_Advance_F.H:23
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);})
constexpr amrex::Real three
Definition: ERF_NumericalConstants.H:39
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
constexpr amrex::Real fourth
Definition: ERF_NumericalConstants.H:42
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
auto rho_arr
Definition: ERF_UpdateWSubsidence_SineMassFlux.H:3
bool boxes_span_domain() const
True when every box spans the domain in z (required by the Fortran bridges)
Definition: ERF_MicrophysicsColumns.H:44
amrex::Geometry m_geom
Definition: ERF_Morrison.H:281
amrex::Real m_rdOcp
Definition: ERF_Morrison.H:284
bool m_do_cond
Definition: ERF_Morrison.H:285
@ qisten
Definition: ERF_AdvanceMorrison.cpp:76
@ dumfnc
Definition: ERF_AdvanceMorrison.cpp:136
@ qi3dten
Definition: ERF_AdvanceMorrison.cpp:48
@ agn
Definition: ERF_AdvanceMorrison.cpp:99
@ pres
Definition: ERF_AdvanceMorrison.cpp:65
@ precrt
Definition: ERF_AdvanceMorrison.cpp:82
@ dumc
Definition: ERF_AdvanceMorrison.cpp:135
@ falouti
Definition: ERF_AdvanceMorrison.cpp:115
@ ni3d
Definition: ERF_AdvanceMorrison.cpp:58
@ dumi
Definition: ERF_AdvanceMorrison.cpp:100
@ faloutnc
Definition: ERF_AdvanceMorrison.cpp:143
@ snowprt
Definition: ERF_AdvanceMorrison.cpp:84
@ lamg
Definition: ERF_AdvanceMorrison.cpp:40
@ xxls
Definition: ERF_AdvanceMorrison.cpp:156
@ n0s
Definition: ERF_AdvanceMorrison.cpp:43
@ fns
Definition: ERF_AdvanceMorrison.cpp:125
@ grplprt
Definition: ERF_AdvanceMorrison.cpp:85
@ dumfns
Definition: ERF_AdvanceMorrison.cpp:121
@ qni3d
Definition: ERF_AdvanceMorrison.cpp:56
@ ung
Definition: ERF_AdvanceMorrison.cpp:139
@ faloutng
Definition: ERF_AdvanceMorrison.cpp:129
@ qc3dten
Definition: ERF_AdvanceMorrison.cpp:47
@ w3d
Definition: ERF_AdvanceMorrison.cpp:67
@ rgvm
Definition: ERF_AdvanceMorrison.cpp:113
@ arn
Definition: ERF_AdvanceMorrison.cpp:96
@ lami
Definition: ERF_AdvanceMorrison.cpp:37
@ qscu1d
Definition: ERF_AdvanceMorrison.cpp:80
@ qcsten
Definition: ERF_AdvanceMorrison.cpp:78
@ fc
Definition: ERF_AdvanceMorrison.cpp:141
@ fnr
Definition: ERF_AdvanceMorrison.cpp:150
@ pgam
Definition: ERF_AdvanceMorrison.cpp:46
@ qrcu1d
Definition: ERF_AdvanceMorrison.cpp:79
@ fng
Definition: ERF_AdvanceMorrison.cpp:112
@ ng3dten
Definition: ERF_AdvanceMorrison.cpp:71
@ dlami
Definition: ERF_AdvanceMorrison.cpp:153
@ faloutni
Definition: ERF_AdvanceMorrison.cpp:116
@ faloutnr
Definition: ERF_AdvanceMorrison.cpp:148
@ NumInds
Definition: ERF_AdvanceMorrison.cpp:160
@ dumfni
Definition: ERF_AdvanceMorrison.cpp:102
@ n0g
Definition: ERF_AdvanceMorrison.cpp:45
@ dlams
Definition: ERF_AdvanceMorrison.cpp:151
@ n0i
Definition: ERF_AdvanceMorrison.cpp:42
@ effs
Definition: ERF_AdvanceMorrison.cpp:90
@ faltndg
Definition: ERF_AdvanceMorrison.cpp:133
@ cpm
Definition: ERF_AdvanceMorrison.cpp:158
@ qr3dten
Definition: ERF_AdvanceMorrison.cpp:50
@ t3d
Definition: ERF_AdvanceMorrison.cpp:63
@ rainonlyprt
Definition: ERF_AdvanceMorrison.cpp:86
@ dumqs
Definition: ERF_AdvanceMorrison.cpp:120
@ qg3d
Definition: ERF_AdvanceMorrison.cpp:72
@ lamr
Definition: ERF_AdvanceMorrison.cpp:39
@ qr3d
Definition: ERF_AdvanceMorrison.cpp:57
@ nc3d
Definition: ERF_AdvanceMorrison.cpp:68
@ qg3dten
Definition: ERF_AdvanceMorrison.cpp:70
@ nr3dten
Definition: ERF_AdvanceMorrison.cpp:53
@ dzq
Definition: ERF_AdvanceMorrison.cpp:66
@ dumfnr
Definition: ERF_AdvanceMorrison.cpp:147
@ uns
Definition: ERF_AdvanceMorrison.cpp:123
@ faltndng
Definition: ERF_AdvanceMorrison.cpp:134
@ effc
Definition: ERF_AdvanceMorrison.cpp:88
@ qnisten
Definition: ERF_AdvanceMorrison.cpp:77
@ faloutg
Definition: ERF_AdvanceMorrison.cpp:128
@ t3dten
Definition: ERF_AdvanceMorrison.cpp:61
@ qv3d
Definition: ERF_AdvanceMorrison.cpp:64
@ ni3dten
Definition: ERF_AdvanceMorrison.cpp:51
@ uni
Definition: ERF_AdvanceMorrison.cpp:105
@ umi
Definition: ERF_AdvanceMorrison.cpp:106
@ qni3dten
Definition: ERF_AdvanceMorrison.cpp:49
@ faloutr
Definition: ERF_AdvanceMorrison.cpp:114
@ dumr
Definition: ERF_AdvanceMorrison.cpp:101
@ faloutns
Definition: ERF_AdvanceMorrison.cpp:127
@ effi
Definition: ERF_AdvanceMorrison.cpp:89
@ faltndni
Definition: ERF_AdvanceMorrison.cpp:119
@ unc
Definition: ERF_AdvanceMorrison.cpp:137
@ umc
Definition: ERF_AdvanceMorrison.cpp:138
@ snowonlyprt
Definition: ERF_AdvanceMorrison.cpp:87
@ qv3dten
Definition: ERF_AdvanceMorrison.cpp:62
@ faltndns
Definition: ERF_AdvanceMorrison.cpp:131
@ nc3dten
Definition: ERF_AdvanceMorrison.cpp:69
@ dumg
Definition: ERF_AdvanceMorrison.cpp:103
@ dlamc
Definition: ERF_AdvanceMorrison.cpp:154
@ rho
Definition: ERF_AdvanceMorrison.cpp:93
@ effr
Definition: ERF_AdvanceMorrison.cpp:91
@ faltndnc
Definition: ERF_AdvanceMorrison.cpp:145
@ xxlv
Definition: ERF_AdvanceMorrison.cpp:157
@ faltndc
Definition: ERF_AdvanceMorrison.cpp:144
@ faltndnr
Definition: ERF_AdvanceMorrison.cpp:149
@ fni
Definition: ERF_AdvanceMorrison.cpp:110
@ umr
Definition: ERF_AdvanceMorrison.cpp:107
@ faloutc
Definition: ERF_AdvanceMorrison.cpp:142
@ ain
Definition: ERF_AdvanceMorrison.cpp:95
@ effg
Definition: ERF_AdvanceMorrison.cpp:92
@ faltnds
Definition: ERF_AdvanceMorrison.cpp:130
@ xlf
Definition: ERF_AdvanceMorrison.cpp:159
@ asn
Definition: ERF_AdvanceMorrison.cpp:97
@ fr
Definition: ERF_AdvanceMorrison.cpp:108
@ fnc
Definition: ERF_AdvanceMorrison.cpp:146
@ fi
Definition: ERF_AdvanceMorrison.cpp:109
@ dumfng
Definition: ERF_AdvanceMorrison.cpp:104
@ faltndr
Definition: ERF_AdvanceMorrison.cpp:117
@ lams
Definition: ERF_AdvanceMorrison.cpp:38
@ fs
Definition: ERF_AdvanceMorrison.cpp:124
@ qicu1d
Definition: ERF_AdvanceMorrison.cpp:81
@ qrsten
Definition: ERF_AdvanceMorrison.cpp:75
@ qgsten
Definition: ERF_AdvanceMorrison.cpp:74
@ cdist1
Definition: ERF_AdvanceMorrison.cpp:41
@ dlamg
Definition: ERF_AdvanceMorrison.cpp:155
@ mu
Definition: ERF_AdvanceMorrison.cpp:94
@ lamc
Definition: ERF_AdvanceMorrison.cpp:36
@ ns3dten
Definition: ERF_AdvanceMorrison.cpp:52
@ ns3d
Definition: ERF_AdvanceMorrison.cpp:59
@ dlamr
Definition: ERF_AdvanceMorrison.cpp:152
@ ng3d
Definition: ERF_AdvanceMorrison.cpp:73
@ qi3d
Definition: ERF_AdvanceMorrison.cpp:55
@ acn
Definition: ERF_AdvanceMorrison.cpp:98
@ falouts
Definition: ERF_AdvanceMorrison.cpp:126
@ faltndi
Definition: ERF_AdvanceMorrison.cpp:118
@ fg
Definition: ERF_AdvanceMorrison.cpp:111
@ qc3d
Definition: ERF_AdvanceMorrison.cpp:54
@ umg
Definition: ERF_AdvanceMorrison.cpp:140
@ unr
Definition: ERF_AdvanceMorrison.cpp:132
@ ums
Definition: ERF_AdvanceMorrison.cpp:122
@ n0r
Definition: ERF_AdvanceMorrison.cpp:44
@ snowrt
Definition: ERF_AdvanceMorrison.cpp:83
@ nr3d
Definition: ERF_AdvanceMorrison.cpp:60
@ qv
Definition: ERF_Morrison.H:37
@ ng
Definition: ERF_Morrison.H:51
@ graupel_accum
Definition: ERF_Morrison.H:55
@ nc
Definition: ERF_Morrison.H:47
@ qpg
Definition: ERF_Morrison.H:44
@ pres
Definition: ERF_Morrison.H:33
@ nr
Definition: ERF_Morrison.H:48
@ qcl
Definition: ERF_Morrison.H:38
@ theta
Definition: ERF_Morrison.H:31
@ ni
Definition: ERF_Morrison.H:49
@ ns
Definition: ERF_Morrison.H:50
@ omega
Definition: ERF_Morrison.H:57
@ qps
Definition: ERF_Morrison.H:43
@ rho
Definition: ERF_Morrison.H:30
@ qpr
Definition: ERF_Morrison.H:42
@ qci
Definition: ERF_Morrison.H:39
@ rain_accum
Definition: ERF_Morrison.H:53
@ precip_accum
Definition: ERF_Morrison.H:56
@ snow_accum
Definition: ERF_Morrison.H:54
@ NumComps
Definition: ERF_Morrison.H:120
@ nr
Definition: ERF_Morrison.H:117
@ ng
Definition: ERF_Morrison.H:119
@ qg
Definition: ERF_Morrison.H:114
@ qr
Definition: ERF_Morrison.H:112
@ qi
Definition: ERF_Morrison.H:111
@ nc
Definition: ERF_Morrison.H:115
@ qs
Definition: ERF_Morrison.H:113
@ qc
Definition: ERF_Morrison.H:110
@ ns
Definition: ERF_Morrison.H:118
@ ni
Definition: ERF_Morrison.H:116
@ psacr
Definition: ERF_WSM6.H:332
@ praci
Definition: ERF_WSM6.H:328
@ psmlt
Definition: ERF_WSM6.H:338
@ pgmlt
Definition: ERF_WSM6.H:339
@ piacr
Definition: ERF_WSM6.H:326
@ pracs
Definition: ERF_WSM6.H:329
real(c_double), parameter p0
Definition: ERF_module_model_constants.F90:40
MoistureType moisture_type
Moisture or microphysics model.
Definition: ERF_DataStruct.H:2942
Here is the call graph for this function:

◆ Copy_Micro_to_State()

void Morrison::Copy_Micro_to_State ( amrex::MultiFab &  cons_in)
overridevirtual

Updates conserved and microphysics variables in the provided MultiFabs from the internal MultiFabs that store Microphysics module data.

Parameters
[out]consConserved variables
[out]qmoistqv, qc, qi, qr, qs, qg

Reimplemented from NullMoist.

17 {
18  // Get the temperature, density, theta, qt and qp from input
19  for ( MFIter mfi(cons,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
20  const auto& box3d = mfi.tilebox();
21 
22  auto states_arr = cons.array(mfi);
23 
24  auto rho_arr = mic_fab_vars[MicVar_Morr::rho]->array(mfi);
25  auto theta_arr = mic_fab_vars[MicVar_Morr::theta]->array(mfi);
26 
27  auto qv_arr = mic_fab_vars[MicVar_Morr::qv]->array(mfi);
28  auto qc_arr = mic_fab_vars[MicVar_Morr::qcl]->array(mfi);
29  auto qi_arr = mic_fab_vars[MicVar_Morr::qci]->array(mfi);
30 
31  auto qpr_arr = mic_fab_vars[MicVar_Morr::qpr]->array(mfi);
32  auto qps_arr = mic_fab_vars[MicVar_Morr::qps]->array(mfi);
33  auto qpg_arr = mic_fab_vars[MicVar_Morr::qpg]->array(mfi);
34 
35  auto nc_arr = mic_fab_vars[MicVar_Morr::nc]->array(mfi);
36  auto ni_arr = mic_fab_vars[MicVar_Morr::ni]->array(mfi);
37  auto nr_arr = mic_fab_vars[MicVar_Morr::nr]->array(mfi);
38  auto ns_arr = mic_fab_vars[MicVar_Morr::ns]->array(mfi);
39  auto ng_arr = mic_fab_vars[MicVar_Morr::ng]->array(mfi);
40 
41  // get potential total density, temperature, qt, qp
42  ParallelFor( box3d, [=] AMREX_GPU_DEVICE (int i, int j, int k)
43  {
44  states_arr(i,j,k,RhoTheta_comp) = rho_arr(i,j,k)*theta_arr(i,j,k);
45 
46  states_arr(i,j,k,RhoQ1_comp) = rho_arr(i,j,k)*std::max(Real(0),qv_arr(i,j,k));
47  states_arr(i,j,k,RhoQ2_comp) = rho_arr(i,j,k)*std::max(Real(0),qc_arr(i,j,k));
48  states_arr(i,j,k,RhoQ3_comp) = rho_arr(i,j,k)*std::max(Real(0),qi_arr(i,j,k));
49 
50  states_arr(i,j,k,RhoQ4_comp) = rho_arr(i,j,k)*std::max(Real(0),qpr_arr(i,j,k));
51  states_arr(i,j,k,RhoQ5_comp) = rho_arr(i,j,k)*std::max(Real(0),qps_arr(i,j,k));
52  states_arr(i,j,k,RhoQ6_comp) = rho_arr(i,j,k)*std::max(Real(0),qpg_arr(i,j,k));
53 
54  states_arr(i,j,k,RhoQ7_comp) = rho_arr(i,j,k)*std::max(Real(0),nc_arr(i,j,k));
55  states_arr(i,j,k,RhoQ8_comp) = rho_arr(i,j,k)*std::max(Real(0),ni_arr(i,j,k));
56  states_arr(i,j,k,RhoQ9_comp) = rho_arr(i,j,k)*std::max(Real(0),nr_arr(i,j,k));
57  states_arr(i,j,k,RhoQ10_comp) = rho_arr(i,j,k)*std::max(Real(0),ns_arr(i,j,k));
58  states_arr(i,j,k,RhoQ11_comp) = rho_arr(i,j,k)*std::max(Real(0),ng_arr(i,j,k));
59  });
60  }
61 
62  // Fill interior ghost cells and periodic boundaries
63  cons.FillBoundary(m_geom.periodicity());
64 }
#define RhoQ4_comp
Definition: ERF_IndexDefines.H:69
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:54
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:67
#define RhoQ3_comp
Definition: ERF_IndexDefines.H:68
#define RhoQ11_comp
Definition: ERF_IndexDefines.H:76
#define RhoQ9_comp
Definition: ERF_IndexDefines.H:74
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:66
#define RhoQ6_comp
Definition: ERF_IndexDefines.H:71
#define RhoQ8_comp
Definition: ERF_IndexDefines.H:73
#define RhoQ5_comp
Definition: ERF_IndexDefines.H:70
#define RhoQ7_comp
Definition: ERF_IndexDefines.H:72
#define RhoQ10_comp
Definition: ERF_IndexDefines.H:75
@ cons
Definition: ERF_IndexDefines.H:254

Referenced by Update_State_Vars().

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

◆ Copy_State_to_Micro() [1/2]

void Morrison::Copy_State_to_Micro ( const amrex::MultiFab &  cons_in)
overridevirtual

Reimplemented from NullMoist.

Referenced by Update_Micro_Vars().

Here is the caller graph for this function:

◆ Copy_State_to_Micro() [2/2]

void Morrison::Copy_State_to_Micro ( const amrex::MultiFab &  cons_in,
const amrex::MultiFab *  base_state 
)

◆ Define()

void Morrison::Define ( SolverChoice &  sc)
inlineoverridevirtual

Reimplemented from NullMoist.

138  {
140  m_rdOcp = sc.rdOcp;
141  m_do_cond = (!sc.uses_shoc_family());
143  }
MoistureType m_moisture_type
Definition: ERF_Morrison.H:286
void set_anelastic_reference_pressure_mode(const SolverChoice &sc)
Definition: ERF_NullMoist.H:171
amrex::Real rdOcp
Ratio of dry-air gas constant to c_p.
Definition: ERF_DataStruct.H:2738
bool uses_shoc_family() const noexcept
Query whether any SHOC-family PBL scheme is active.
Definition: ERF_DataStruct.H:2864
Here is the call graph for this function:

◆ Get_Surface_Precip_Accumulation_Ptrs()

SurfacePrecipAccumulationSources Morrison::Get_Surface_Precip_Accumulation_Ptrs ( const int &  ) const
inlineoverridevirtual

Reimplemented from NullMoist.

233  {
235  sources.total = {mic_fab_vars[MicVar_Morr::precip_accum].get(), rhor / amrex::Real(1000.0)};
236  sources.rain = {mic_fab_vars[MicVar_Morr::rain_accum].get(), rhor / amrex::Real(1000.0)};
237 
238  if (m_moisture_type == MoistureType::Morrison) {
239  sources.snow = {mic_fab_vars[MicVar_Morr::snow_accum].get(), rhor / amrex::Real(1000.0)};
240  sources.graupel = {mic_fab_vars[MicVar_Morr::graupel_accum].get(), rhor / amrex::Real(1000.0)};
241  }
242 
243  return sources;
244  }
constexpr amrex::Real rhor
Definition: ERF_MicrophysicsConstants.H:39
Definition: ERF_SurfacePrecipitation.H:34
SurfacePrecipAccumulationSource rain
Definition: ERF_SurfacePrecipitation.H:36
SurfacePrecipAccumulationSource snow
Definition: ERF_SurfacePrecipitation.H:37
SurfacePrecipAccumulationSource total
Definition: ERF_SurfacePrecipitation.H:35
SurfacePrecipAccumulationSource graupel
Definition: ERF_SurfacePrecipitation.H:38

◆ GetPlotVar() [1/2]

void Morrison::GetPlotVar ( const std::string &  a_name,
amrex::MultiFab &  a_mf 
) const
overridevirtual

Reimplemented from NullMoist.

Referenced by GetPlotVar().

Here is the caller graph for this function:

◆ GetPlotVar() [2/2]

void Morrison::GetPlotVar ( const std::string &  a_name,
amrex::MultiFab &  a_mf,
const int   
) const
inlineoverridevirtual

Reimplemented from NullMoist.

257  {
258  GetPlotVar(a_name, a_mf);
259  }
void GetPlotVar(const std::string &a_name, amrex::MultiFab &a_mf) const override
Here is the call graph for this function:

◆ GetPlotVarNames()

void Morrison::GetPlotVarNames ( amrex::Vector< std::string > &  a_vec) const
overridevirtual

Populate a vector with names of all available Morrison plot variables.

This function returns the names of all Morrison microphysics variables that can be written to plotfiles. These names correspond to the diagnostic fields defined in the plot_entries table.

Parameters
[out]a_vecVector to be populated with plot variable names
Note
The returned vector will contain 19 variable names, including both prognostic quantities (mixing ratios, number concentrations) and diagnostic quantities (temperature, pressure, derived moisture totals).

Reimplemented from NullMoist.

102 {
103  a_vec.clear();
104  a_vec.reserve(sizeof(plot_entries) / sizeof(plot_entries[0]));
105  for (const auto& entry : plot_entries) {
106  a_vec.emplace_back(entry.name);
107  }
108 }

◆ Init()

void Morrison::Init ( const amrex::MultiFab &  cons_in,
const amrex::BoxArray &  grids,
const amrex::Geometry &  geom,
const amrex::Real &  dt_advance,
std::unique_ptr< amrex::MultiFab > &  z_phys_nd,
std::unique_ptr< amrex::MultiFab > &  detJ_cc 
)
overridevirtual

Initializes the Microphysics module.

Parameters
[in]cons_inConserved variables input
[in]qc_inCloud variables input
[in,out]qv_inVapor variables input
[in]qi_inIce variables input
[in]gridsThe boxes on which we will evolve the solution
[in]geomGeometry associated with these MultiFabs and grids
[in]dt_advanceTimestep for the advance

Reimplemented from NullMoist.

27 {
28  [[maybe_unused]] amrex::Real dt = dt_advance;
29  m_geom = geom;
30 
31  m_z_phys_nd = z_phys_nd.get();
32  m_detJ_cc = detJ_cc.get();
33 
34  m_columns.define(cons_in.boxArray(), geom.Domain());
35 
36  MicVarMap.resize(m_qmoist_size);
39 
40 #if defined(ERF_USE_MORR_FORT) && defined(AMREX_USE_GPU)
41  Arena* Arena_Used = The_Managed_Arena();
42 #else
43  Arena* Arena_Used = The_Arena();
44 #endif
45 
46  // initialize microphysics variables
47  for (auto ivar = 0; ivar < MicVar_Morr::NumVars; ++ivar) {
48  mic_fab_vars[ivar] = std::make_shared<MultiFab>(cons_in.boxArray(), cons_in.DistributionMap(),
49  1, cons_in.nGrowVect(),
50  MFInfo().SetArena(Arena_Used));
51  mic_fab_vars[ivar]->setVal(0.);
52  }
53 
54  m_sed.define(cons_in.boxArray(), cons_in.DistributionMap(),
55  {RhoQ2_comp, RhoQ3_comp, RhoQ4_comp, RhoQ5_comp, RhoQ6_comp,
56  RhoQ7_comp, RhoQ8_comp, RhoQ9_comp, RhoQ10_comp, RhoQ11_comp});
57 
58 #ifdef ERF_USE_MORR_FORT
59  bool use_cpp = true;
60  amrex::ParmParse pp("erf");
61  pp.queryAdd("use_morr_cpp_answer", use_cpp);
62 
63  if (!use_cpp) {
64  MoistureType moisture_type;
65  pp.query_enum_case_insensitive("moisture_model",moisture_type);
66  int morr_noice = (moisture_type == MoistureType::Morrison_NoIce);
67  int morr_rimed_ice = 0; // This is used to set something called "ihail"
68  morr_two_moment_init_c(morr_rimed_ice, morr_noice);
69  }
70 #endif
71 }
void morr_two_moment_init_c(int morr_rimed_ice, int morr_noice)
void define(const amrex::BoxArray &ba, const amrex::Box &domain)
Build from a level's grids; call from the scheme's Init (which also runs on regrid)
Definition: ERF_MicrophysicsColumns.cpp:9
amrex::Vector< int > MicVarMap
Definition: ERF_Morrison.H:278
amrex::MultiFab * m_detJ_cc
Definition: ERF_Morrison.H:293
int m_qmoist_size
Definition: ERF_Morrison.H:269
@ NumVars
Definition: ERF_Morrison.H:58
void define(const amrex::BoxArray &cc_ba, const amrex::DistributionMapping &dm, const amrex::Vector< int > &a_cons_comp)
Definition: ERF_SedimentationFlux.H:43
Here is the call graph for this function:

◆ Qmoist_Ptr()

amrex::MultiFab* Morrison::Qmoist_Ptr ( const int &  varIdx)
inlineoverridevirtual

Reimplemented from NullMoist.

197  {
199  return mic_fab_vars[MicVarMap[varIdx]].get();
200  }
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
Here is the call graph for this function:

◆ Qmoist_Restart_Vars()

void Morrison::Qmoist_Restart_Vars ( const SolverChoice &  ,
std::vector< int > &  a_idx,
std::vector< std::string > &  a_names 
) const
inlineoverridevirtual

Reimplemented from NullMoist.

215  {
216  a_idx.clear();
217  a_names.clear();
218 
219  // The ordering here needs to match that in
220  // MicVarMap = {MicVar_Morr::rain_accum, MicVar_Morr::snow_accum,
221  // MicVar_Morr::graupel_accum, MicVar_Morr::precip_accum};
222  //
223  a_idx.push_back(0); a_names.push_back("RainAccum");
224  a_idx.push_back(1); a_names.push_back("SnowAccum");
225  a_idx.push_back(2); a_names.push_back("GraupAccum");
226  a_idx.push_back(3); a_names.push_back("PrecipAccum");
227  }

◆ Qmoist_Size()

int Morrison::Qmoist_Size ( )
inlineoverridevirtual

Reimplemented from NullMoist.

203 { return Morrison::m_qmoist_size; }

◆ Qstate_Moist_NumConc_Size()

int Morrison::Qstate_Moist_NumConc_Size ( )
inlineoverridevirtual

Reimplemented from NullMoist.

int n_qstate_moist_numconc_size
Definition: ERF_Morrison.H:275

◆ Qstate_Moist_Size()

int Morrison::Qstate_Moist_Size ( )
inlineoverridevirtual

Reimplemented from NullMoist.

int n_qstate_moist_size
Definition: ERF_Morrison.H:272

◆ Sed_Flux()

const SedimentationFlux* Morrison::Sed_Flux ( ) const
inlineoverridevirtual

The sedimentation face fluxes of the most recent Advance, or null for a scheme that does not sediment (see ERF_SedimentationFlux.H)

Reimplemented from NullMoist.

229 { return &m_sed; }

◆ Set_dzmin()

void Morrison::Set_dzmin ( const amrex::Real  dz_min)
inlineoverridevirtual

Reimplemented from NullMoist.

157  {
158  m_dzmin = dz_min;
159  }
amrex::Real m_dzmin
Definition: ERF_Morrison.H:289

◆ Update_Micro_Vars() [1/2]

void Morrison::Update_Micro_Vars ( amrex::MultiFab &  cons_in)
inlineoverridevirtual

Reimplemented from NullMoist.

179  {
180  this->Copy_State_to_Micro(cons_in);
181  }
void Copy_State_to_Micro(const amrex::MultiFab &cons_in) override
Here is the call graph for this function:

◆ Update_Micro_Vars() [2/2]

void Morrison::Update_Micro_Vars ( amrex::MultiFab &  cons_in,
const amrex::MultiFab *  base_state 
)
overridevirtual

Reimplemented from NullMoist.

◆ Update_State_Vars()

void Morrison::Update_State_Vars ( amrex::MultiFab &  cons_in,
const amrex::MultiFab &   
)
inlineoverridevirtual

Reimplemented from NullMoist.

186  {
187  this->Copy_Micro_to_State(cons_in);
188  }
void Copy_Micro_to_State(amrex::MultiFab &cons_in) override
Definition: ERF_UpdateMorrison.cpp:16
Here is the call graph for this function:

Member Data Documentation

◆ m_columns

MicrophysicsColumns Morrison::m_columns
private

◆ m_detJ_cc

amrex::MultiFab* Morrison::m_detJ_cc
private

◆ m_do_cond

bool Morrison::m_do_cond
private

Referenced by Define().

◆ m_dzmin

amrex::Real Morrison::m_dzmin {0.0}
private

Referenced by Set_dzmin().

◆ m_geom

amrex::Geometry Morrison::m_geom
private

◆ m_moisture_type

MoistureType Morrison::m_moisture_type = MoistureType::None
private

◆ m_qmoist_size

int Morrison::m_qmoist_size = 4
private

Referenced by Qmoist_Ptr(), and Qmoist_Size().

◆ m_rdOcp

amrex::Real Morrison::m_rdOcp {RdoCp}
private

Referenced by Define().

◆ m_sed

SedimentationFlux Morrison::m_sed
private

Referenced by Sed_Flux().

◆ m_z_phys_nd

amrex::MultiFab* Morrison::m_z_phys_nd
private

◆ mic_fab_vars

amrex::Array<FabPtr, MicVar_Morr::NumVars> Morrison::mic_fab_vars
private

◆ MicVarMap

amrex::Vector<int> Morrison::MicVarMap
private

Referenced by Qmoist_Ptr().

◆ n_qstate_moist_numconc_size

int Morrison::n_qstate_moist_numconc_size = 5
private

◆ n_qstate_moist_size

int Morrison::n_qstate_moist_size = 11
private

Referenced by Qstate_Moist_Size().


The documentation for this class was generated from the following files: