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

#include <ERF_SAM.H>

Inheritance diagram for SAM:
Collaboration diagram for SAM:

Public Member Functions

 SAM ()
 
virtual ~SAM ()=default
 
void Cloud (const SolverChoice &sc)
 
void IceFall (const SolverChoice &sc)
 
void Precip (const SolverChoice &sc)
 
void PrecipFall (const SolverChoice &sc)
 
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
 
const amrex::MultiFab * Qmoist_Ptr (const int &varIdx) const
 
void Compute_Coefficients (bool use_anelastic_reference_pressure=false)
 
SAMCoefficientRow CoefficientRowAt (int k) const
 
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
 
SurfacePrecipAccumulationSources Get_Surface_Precip_Accumulation_Ptrs (const int &) const override
 
- Public Member Functions inherited from NullMoist
 NullMoist ()
 
virtual ~NullMoist ()=default
 
virtual int Qstate_NonMoist_Size ()
 
virtual void GetPlotVarNames (amrex::Vector< std::string > &a_vec) const
 
virtual void GetPlotVar (const std::string &, amrex::MultiFab &) const
 
virtual void GetPlotVar (const std::string &a_name, amrex::MultiFab &a_mf, const int) const
 
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_RealWidth (const int)
 

Static Public Member Functions

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real NewtonIterSat (int &i, int &j, int &k, const int &SAM_moisture_type, const amrex::Real &fac_cond, const amrex::Real &fac_fus, const amrex::Real &, const amrex::Real &an, const amrex::Real &bn, const amrex::Array4< amrex::Real > &tabs_array, const amrex::Array4< amrex::Real > &pres_array, const amrex::Array4< amrex::Real > &qv_array, const amrex::Array4< amrex::Real > &qc_array, const amrex::Array4< amrex::Real > &qi_array, const amrex::Array4< amrex::Real > &qn_array, const amrex::Array4< amrex::Real > &qt_array)
 

Private Types

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

Private Attributes

int m_qmoist_size = 3
 
int n_qstate_moist_size = 6
 
int n_qstate_moist_numconc_size = 0
 
amrex::Vector< int > MicVarMap
 
amrex::Geometry m_geom
 
amrex::Real dt
 
int nlev
 
int zlo
 
int zhi
 
int m_axis
 
amrex::Real m_fac_cond
 
amrex::Real m_fac_fus
 
amrex::Real m_fac_sub
 
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::NumVarsmic_fab_vars
 
amrex::TableData< amrex::Real, 1 > accrrc
 
amrex::TableData< amrex::Real, 1 > accrsi
 
amrex::TableData< amrex::Real, 1 > accrsc
 
amrex::TableData< amrex::Real, 1 > coefice
 
amrex::TableData< amrex::Real, 1 > evaps1
 
amrex::TableData< amrex::Real, 1 > evaps2
 
amrex::TableData< amrex::Real, 1 > accrgi
 
amrex::TableData< amrex::Real, 1 > accrgc
 
amrex::TableData< amrex::Real, 1 > evapg1
 
amrex::TableData< amrex::Real, 1 > evapg2
 
amrex::TableData< amrex::Real, 1 > evapr1
 
amrex::TableData< amrex::Real, 1 > evapr2
 
amrex::TableData< amrex::Real, 1 > rho1d
 
amrex::TableData< amrex::Real, 1 > pres1d
 
amrex::TableData< amrex::Real, 1 > tabs1d
 
amrex::TableData< amrex::Real, 1 > qt1d
 
amrex::TableData< amrex::Real, 1 > qv1d
 
amrex::TableData< amrex::Real, 1 > qn1d
 

Static Private Attributes

static constexpr amrex::Real CFL_MAX = myhalf
 

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
int m_level {0}
 
bool m_use_anelastic_reference_pressure {false}
 

Member Typedef Documentation

◆ FabPtr

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

Constructor & Destructor Documentation

◆ SAM()

SAM::SAM ( )
inline
62 {}

◆ ~SAM()

virtual SAM::~SAM ( )
virtualdefault

Member Function Documentation

◆ Advance()

void SAM::Advance ( const amrex::Real dt_advance,
const SolverChoice sc 
)
inlineoverridevirtual

Reimplemented from NullMoist.

143  {
144  dt = dt_advance;
145 
146  this->Cloud(sc);
147  this->IceFall(sc);
148  this->Precip(sc);
149  this->PrecipFall(sc);
150  }
void Precip(const SolverChoice &sc)
Definition: ERF_Precip.cpp:12
void IceFall(const SolverChoice &sc)
Definition: ERF_IceFall.cpp:13
void Cloud(const SolverChoice &sc)
Definition: ERF_CloudSAM.cpp:14
void PrecipFall(const SolverChoice &sc)
Definition: ERF_PrecipFall.cpp:19
amrex::Real dt
Definition: ERF_SAM.H:360
Here is the call graph for this function:

◆ Cloud()

void SAM::Cloud ( const SolverChoice sc)

Split cloud components according to saturation pressures; source theta from latent heat.

15 {
16  if (!m_do_cond) { return; }
17 
18  constexpr Real an = one/(tbgmax-tbgmin);
19  constexpr Real bn = tbgmin*an;
20 
21  Real fac_cond = m_fac_cond;
22  Real fac_sub = m_fac_sub;
23  Real fac_fus = m_fac_fus;
24  Real rdOcp = m_rdOcp;
25 
26  int SAM_moisture_type = 1;
27  if (sam_is_no_ice(sc.moisture_type)) {
28  SAM_moisture_type = 2;
29  }
30 
31  for ( MFIter mfi(*(mic_fab_vars[MicVar::tabs]), TilingIfNotGPU()); mfi.isValid(); ++mfi) {
32  auto qt_array = mic_fab_vars[MicVar::qt]->array(mfi);
33  auto qn_array = mic_fab_vars[MicVar::qn]->array(mfi);
34  auto qv_array = mic_fab_vars[MicVar::qv]->array(mfi);
35  auto qcl_array = mic_fab_vars[MicVar::qcl]->array(mfi);
36  auto qci_array = mic_fab_vars[MicVar::qci]->array(mfi);
37 
38  auto tabs_array = mic_fab_vars[MicVar::tabs]->array(mfi);
39  auto theta_array = mic_fab_vars[MicVar::theta]->array(mfi);
40  auto pres_array = mic_fab_vars[MicVar::pres]->array(mfi);
41 
42  auto tbx = mfi.tilebox();
43 
44  ParallelFor(tbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
45  {
46  // Saturation moisture fractions
47  Real omn;
48  Real qsat;
49  Real qsatw;
50  Real qsati;
51 
52  // Newton iteration vars
53  Real delta_qv, delta_qc, delta_qi;
54 
55  // NOTE: Conversion before iterations is necessary to
56  // convert cloud water to ice or vice versa.
57  // This ensures the omn splitting is enforced
58  // before the Newton iteration, which assumes it is.
59 
60  const SAMCloudPhaseChange phase_change =
61  sam_partition_cloud_phase(SAM_moisture_type,
62  tabs_array(i,j,k),
63  qn_array(i,j,k),
64  qcl_array(i,j,k),
65  qci_array(i,j,k),
66  fac_cond, fac_fus,
67  an, bn);
68  omn = phase_change.omn;
69  delta_qc = phase_change.delta_qc;
70  delta_qi = phase_change.delta_qi;
71  qcl_array(i,j,k) = phase_change.qcl;
72  qci_array(i,j,k) = phase_change.qci;
73  tabs_array(i,j,k) = phase_change.tabs;
74  // Cloud adjustment updates tabs under the held-pressure SAM source
75  // convention, then refreshes theta from the same stored pressure.
76  theta_array(i,j,k) = sam_theta_from_stored_mbar_converted_to_pa(tabs_array(i,j,k),
77  pres_array(i,j,k), rdOcp);
78 
79  // Saturation moisture fractions
80  erf_qsatw(tabs_array(i,j,k), pres_array(i,j,k), qsatw);
81  erf_qsati(tabs_array(i,j,k), pres_array(i,j,k), qsati);
82  qsat = sam_mixed_qsat(omn, qsatw, qsati);
83 
84  // We have enough total moisture to relax to equilibrium
85  if (qt_array(i,j,k) > qsat) {
86 
87  // Update temperature
88  tabs_array(i,j,k) = NewtonIterSat(i, j, k , SAM_moisture_type ,
89  fac_cond , fac_fus , fac_sub ,
90  an , bn ,
91  tabs_array, pres_array,
92  qv_array , qcl_array , qci_array,
93  qn_array , qt_array);
94 
95  // Update theta
96  theta_array(i,j,k) = sam_theta_from_stored_mbar_converted_to_pa(tabs_array(i,j,k),
97  pres_array(i,j,k), rdOcp);
98 
99  //
100  // We cannot blindly relax to qsat, but we can convert qc/qi -> qv.
101  // The concept here is that if we put all the moisture into qv and modify
102  // the temperature, we can then check if qv > qsat occurs (for final T/P/qv).
103  // If the reduction in T/qsat and increase in qv does trigger the
104  // aforementioned condition, we can do Newton iteration to drive qv = qsat.
105  //
106  } else {
107  // Changes in each component
108  delta_qv = qcl_array(i,j,k) + qci_array(i,j,k);
109  delta_qc = qcl_array(i,j,k);
110  delta_qi = qci_array(i,j,k);
111 
112  // Partition the change in non-precipitating q
113  qv_array(i,j,k) += delta_qv;
114  qcl_array(i,j,k) = zero;
115  qci_array(i,j,k) = zero;
116  qn_array(i,j,k) = zero;
117  qt_array(i,j,k) = qv_array(i,j,k);
118 
119  // Update temperature (endothermic since we evap/sublime)
120  tabs_array(i,j,k) -= fac_cond * delta_qc + fac_sub * delta_qi;
121 
122  // Update theta
123  theta_array(i,j,k) = sam_theta_from_stored_mbar_converted_to_pa(tabs_array(i,j,k),
124  pres_array(i,j,k), rdOcp);
125 
126  // Verify assumption that qv > qsat does not occur
127  erf_qsatw(tabs_array(i,j,k), pres_array(i,j,k), qsatw);
128  erf_qsati(tabs_array(i,j,k), pres_array(i,j,k), qsati);
129  qsat = sam_mixed_qsat(omn, qsatw, qsati);
130  if (qt_array(i,j,k) > qsat) {
131 
132  // Update temperature
133  tabs_array(i,j,k) = NewtonIterSat(i, j, k , SAM_moisture_type ,
134  fac_cond , fac_fus , fac_sub ,
135  an , bn ,
136  tabs_array, pres_array,
137  qv_array , qcl_array , qci_array,
138  qn_array , qt_array);
139 
140  // Update theta
141  theta_array(i,j,k) = sam_theta_from_stored_mbar_converted_to_pa(tabs_array(i,j,k),
142  pres_array(i,j,k), rdOcp);
143 
144  }
145  }
146  });
147  } // mfi
148 }
const Real rdOcp
Definition: ERF_InitCustomPert_ABL.H:72
constexpr amrex::Real tbgmax
Definition: ERF_MicrophysicsConstants.H:49
constexpr amrex::Real tbgmin
Definition: ERF_MicrophysicsConstants.H:48
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_qsatw(amrex::Real t, amrex::Real p, amrex::Real &qsatw)
Definition: ERF_MicrophysicsUtils.H:264
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_qsati(amrex::Real t, amrex::Real p, amrex::Real &qsati)
Definition: ERF_MicrophysicsUtils.H:254
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 one
Definition: ERF_NumericalConstants.H:30
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:29
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE SAMCloudPhaseChange sam_partition_cloud_phase(const int &SAM_moisture_type, const amrex::Real &tabs, const amrex::Real &qn, const amrex::Real &qcl, const amrex::Real &qci, const amrex::Real fac_cond, const amrex::Real fac_fus, const amrex::Real an, const amrex::Real bn) noexcept
Definition: ERF_SAMUtils.H:391
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool sam_is_no_ice(const MoistureType &moisture_type) noexcept
Definition: ERF_SAMUtils.H:333
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sam_theta_from_stored_mbar_converted_to_pa(const amrex::Real &tabs, const amrex::Real &pres_mbar, const amrex::Real rdOcp) noexcept
Definition: ERF_SAMUtils.H:172
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sam_mixed_qsat(const amrex::Real &omn, const amrex::Real &qsatw, const amrex::Real &qsati) noexcept
Definition: ERF_SAMUtils.H:445
amrex::Real Real
Definition: ERF_ShocInterface.H:19
amrex::Array< FabPtr, MicVar::NumVars > mic_fab_vars
Definition: ERF_SAM.H:384
amrex::Real m_rdOcp
Definition: ERF_SAM.H:372
amrex::Real m_fac_fus
Definition: ERF_SAM.H:370
bool m_do_cond
Definition: ERF_SAM.H:373
amrex::Real m_fac_cond
Definition: ERF_SAM.H:369
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real NewtonIterSat(int &i, int &j, int &k, const int &SAM_moisture_type, const amrex::Real &fac_cond, const amrex::Real &fac_fus, const amrex::Real &, const amrex::Real &an, const amrex::Real &bn, const amrex::Array4< amrex::Real > &tabs_array, const amrex::Array4< amrex::Real > &pres_array, const amrex::Array4< amrex::Real > &qv_array, const amrex::Array4< amrex::Real > &qc_array, const amrex::Array4< amrex::Real > &qi_array, const amrex::Array4< amrex::Real > &qn_array, const amrex::Array4< amrex::Real > &qt_array)
Definition: ERF_SAM.H:216
amrex::Real m_fac_sub
Definition: ERF_SAM.H:371
@ pres
Definition: ERF_SAM.H:36
@ qci
Definition: ERF_SAM.H:42
@ qv
Definition: ERF_SAM.H:40
@ qt
Definition: ERF_SAM.H:38
@ qn
Definition: ERF_SAM.H:39
@ theta
Definition: ERF_SAM.H:34
@ qcl
Definition: ERF_SAM.H:41
@ tabs
Definition: ERF_SAM.H:35
@ qsatw
Definition: ERF_WSM6.H:340
@ qsati
Definition: ERF_WSM6.H:340
Definition: ERF_SAMUtils.H:23
amrex::Real delta_qi
Definition: ERF_SAMUtils.H:27
amrex::Real qcl
Definition: ERF_SAMUtils.H:29
amrex::Real tabs
Definition: ERF_SAMUtils.H:33
amrex::Real delta_qc
Definition: ERF_SAMUtils.H:26
amrex::Real omn
Definition: ERF_SAMUtils.H:24
amrex::Real qci
Definition: ERF_SAMUtils.H:30
MoistureType moisture_type
Moisture or microphysics model.
Definition: ERF_DataStruct.H:2237

Referenced by Advance().

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

◆ CoefficientRowAt()

SAMCoefficientRow SAM::CoefficientRowAt ( int  k) const
274 {
275  AMREX_ALWAYS_ASSERT(k >= zlo && k <= zhi);
276 
277  SAMCoefficientRow row{};
278  row.accrrc = copy_table_value_to_host(accrrc, zlo, zhi, k);
279  row.accrsi = copy_table_value_to_host(accrsi, zlo, zhi, k);
280  row.accrsc = copy_table_value_to_host(accrsc, zlo, zhi, k);
281  row.coefice = copy_table_value_to_host(coefice, zlo, zhi, k);
282  row.evaps1 = copy_table_value_to_host(evaps1, zlo, zhi, k);
283  row.evaps2 = copy_table_value_to_host(evaps2, zlo, zhi, k);
284  row.accrgi = copy_table_value_to_host(accrgi, zlo, zhi, k);
285  row.accrgc = copy_table_value_to_host(accrgc, zlo, zhi, k);
286  row.evapg1 = copy_table_value_to_host(evapg1, zlo, zhi, k);
287  row.evapg2 = copy_table_value_to_host(evapg2, zlo, zhi, k);
288  row.evapr1 = copy_table_value_to_host(evapr1, zlo, zhi, k);
289  row.evapr2 = copy_table_value_to_host(evapr2, zlo, zhi, k);
290  return row;
291 }
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
int zlo
Definition: ERF_SAM.H:363
amrex::TableData< amrex::Real, 1 > evapr2
Definition: ERF_SAM.H:398
amrex::TableData< amrex::Real, 1 > evapg1
Definition: ERF_SAM.H:395
amrex::TableData< amrex::Real, 1 > accrgi
Definition: ERF_SAM.H:393
amrex::TableData< amrex::Real, 1 > evapg2
Definition: ERF_SAM.H:396
amrex::TableData< amrex::Real, 1 > evaps1
Definition: ERF_SAM.H:391
amrex::TableData< amrex::Real, 1 > accrsi
Definition: ERF_SAM.H:388
amrex::TableData< amrex::Real, 1 > accrrc
Definition: ERF_SAM.H:387
amrex::TableData< amrex::Real, 1 > evapr1
Definition: ERF_SAM.H:397
amrex::TableData< amrex::Real, 1 > evaps2
Definition: ERF_SAM.H:392
amrex::TableData< amrex::Real, 1 > accrgc
Definition: ERF_SAM.H:394
amrex::TableData< amrex::Real, 1 > accrsc
Definition: ERF_SAM.H:389
amrex::TableData< amrex::Real, 1 > coefice
Definition: ERF_SAM.H:390
int zhi
Definition: ERF_SAM.H:363
Definition: ERF_SAMUtils.H:99
amrex::Real accrrc
Definition: ERF_SAMUtils.H:100
Here is the call graph for this function:

◆ Compute_Coefficients()

void SAM::Compute_Coefficients ( bool  use_anelastic_reference_pressure = false)
155 {
156  auto accrrc_t = accrrc.table();
157  auto accrsi_t = accrsi.table();
158  auto accrsc_t = accrsc.table();
159  auto coefice_t = coefice.table();
160  auto evaps1_t = evaps1.table();
161  auto evaps2_t = evaps2.table();
162  auto accrgi_t = accrgi.table();
163  auto accrgc_t = accrgc.table();
164  auto evapg1_t = evapg1.table();
165  auto evapg2_t = evapg2.table();
166  auto evapr1_t = evapr1.table();
167  auto evapr2_t = evapr2.table();
168 
169  auto rho1d_t = rho1d.table();
170  auto pres1d_t = pres1d.table();
171  auto tabs1d_t = tabs1d.table();
172 
173  Real gam3 = erf_gammafff(three );
174  Real gamr1 = erf_gammafff(three+b_rain );
175  Real gamr2 = erf_gammafff((Real(5.0)+b_rain)/two);
176  Real gams1 = erf_gammafff(three+b_snow );
177  Real gams2 = erf_gammafff((Real(5.0)+b_snow)/two);
178  Real gamg1 = erf_gammafff(three+b_grau );
179  Real gamg2 = erf_gammafff((Real(5.0)+b_grau)/two);
180 
181  // calculate the plane average variables
187  rho_ave.compute_averages(ZDir(), rho_ave.field());
188  if (use_anelastic_reference_pressure) {
189  pres_ave.compute_averages(ZDir(), pres_ave.field());
190  tabs_ave.compute_averages(ZDir(), tabs_ave.field());
191  } else {
192  theta_ave.compute_averages(ZDir(), theta_ave.field());
193  qv_ave.compute_averages(ZDir(), qv_ave.field());
194  }
195 
196  // get host variable rho, and rhotheta
197  int ncell = rho_ave.ncell_line();
198 
199  Gpu::HostVector<Real> rho_h(ncell), theta_h(ncell), qv_h(ncell);
200  Gpu::HostVector<Real> pres_h(ncell), tabs_h(ncell);
201  rho_ave.line_average(0, rho_h);
202  if (use_anelastic_reference_pressure) {
203  pres_ave.line_average(0, pres_h);
204  tabs_ave.line_average(0, tabs_h);
205  } else {
206  theta_ave.line_average(0, theta_h);
207  qv_ave.line_average(0, qv_h);
208  }
209 
210  // copy data to device
211  Gpu::DeviceVector<Real> rho_d(ncell), theta_d(ncell), qv_d(ncell);
212  Gpu::DeviceVector<Real> pres_d(ncell), tabs_d(ncell);
213  Gpu::copyAsync(Gpu::hostToDevice, rho_h.begin(), rho_h.end(), rho_d.begin());
214  if (use_anelastic_reference_pressure) {
215  Gpu::copyAsync(Gpu::hostToDevice, pres_h.begin(), pres_h.end(), pres_d.begin());
216  Gpu::copyAsync(Gpu::hostToDevice, tabs_h.begin(), tabs_h.end(), tabs_d.begin());
217  } else {
218  Gpu::copyAsync(Gpu::hostToDevice, theta_h.begin(), theta_h.end(), theta_d.begin());
219  Gpu::copyAsync(Gpu::hostToDevice, qv_h.begin(), qv_h.end(), qv_d.begin());
220  }
221  Gpu::streamSynchronize();
222 
223  Real* rho_dptr = rho_d.data();
224  Real* theta_dptr = theta_d.data();
225  Real* qv_dptr = qv_d.data();
226  Real* pres_dptr = pres_d.data();
227  Real* tabs_dptr = tabs_d.data();
228 
229  ParallelFor(nlev, [=] AMREX_GPU_DEVICE (int k) noexcept
230  {
231  rho1d_t(k) = rho_dptr[k];
232  if (use_anelastic_reference_pressure) {
233  pres1d_t(k) = pres_dptr[k];
234  tabs1d_t(k) = amrex::min(tabs_dptr[k], Real(273.16));
235  } else {
236  Real RhoTheta = rho_dptr[k]*theta_dptr[k];
237  Real pressure = getPgivenRTh(RhoTheta, qv_dptr[k]);
238  pres1d_t(k) = sam_pa_to_mbar(pressure);
239  // NOTE: Limit the temperature to the melting point of ice to avoid
240  // a divide by 0 condition when computing cold coefficients.
241  tabs1d_t(k) = amrex::min(getTgivenRandRTh(rho_dptr[k], RhoTheta, qv_dptr[k]),
242  Real(273.16));
243  }
244  });
245 
246  if(round(gam3) != 2) {
247  std::cout << "cannot compute gamma-function in Microphysics::Init" << std::endl;
248  std::exit(-1);
249  }
250 
251  // Populate all the coefficients
252  ParallelFor(nlev, [=] AMREX_GPU_DEVICE (int k) noexcept
253  {
254  const SAMCoefficientRow row =
255  sam_compute_coefficient_row(rho1d_t(k), tabs1d_t(k),
256  gamr1, gamr2, gams1, gams2, gamg1, gamg2);
257  accrrc_t(k) = row.accrrc;
258  accrsi_t(k) = row.accrsi;
259  accrsc_t(k) = row.accrsc;
260  coefice_t(k) = row.coefice;
261  evaps1_t(k) = row.evaps1;
262  evaps2_t(k) = row.evaps2;
263  accrgi_t(k) = row.accrgi;
264  accrgc_t(k) = row.accrgc;
265  evapg1_t(k) = row.evapg1;
266  evapg2_t(k) = row.evapg2;
267  evapr1_t(k) = row.evapr1;
268  evapr2_t(k) = row.evapr2;
269  });
270 }
DirectionSelector< 2 > ZDir
Definition: ERF_DirectionSelector.H:55
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getTgivenRandRTh(const amrex::Real rho, const amrex::Real rhotheta, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:46
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getPgivenRTh(const amrex::Real rhotheta, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:81
pp get("wavelength", wavelength)
constexpr amrex::Real b_grau
Definition: ERF_MicrophysicsConstants.H:67
constexpr amrex::Real b_rain
Definition: ERF_MicrophysicsConstants.H:63
constexpr amrex::Real b_snow
Definition: ERF_MicrophysicsConstants.H:65
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real erf_gammafff(amrex::Real x)
Definition: ERF_MicrophysicsUtils.H:55
constexpr amrex::Real three
Definition: ERF_NumericalConstants.H:32
constexpr amrex::Real two
Definition: ERF_NumericalConstants.H:31
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sam_pa_to_mbar(const amrex::Real &pres_pa) noexcept
Definition: ERF_SAMUtils.H:166
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE SAMCoefficientRow sam_compute_coefficient_row(const amrex::Real &rho, const amrex::Real &tabs, const amrex::Real &gamr1, const amrex::Real &gamr2, const amrex::Real &gams1, const amrex::Real &gams2, const amrex::Real &gamg1, const amrex::Real &gamg2) noexcept
Definition: ERF_SAMUtils.H:804
Vector< Real > rho_h(khi+1, zero)
Gpu::DeviceVector< Real > rho_d(khi+1, zero)
Definition: ERF_PlaneAverage.H:14
amrex::TableData< amrex::Real, 1 > rho1d
Definition: ERF_SAM.H:401
int m_axis
Definition: ERF_SAM.H:366
amrex::TableData< amrex::Real, 1 > pres1d
Definition: ERF_SAM.H:402
int nlev
Definition: ERF_SAM.H:363
amrex::Geometry m_geom
Definition: ERF_SAM.H:357
amrex::TableData< amrex::Real, 1 > tabs1d
Definition: ERF_SAM.H:403
@ rho
Definition: ERF_SAM.H:33
amrex::Real coefice
Definition: ERF_SAMUtils.H:103
amrex::Real evaps2
Definition: ERF_SAMUtils.H:105
amrex::Real accrsi
Definition: ERF_SAMUtils.H:101
amrex::Real accrgc
Definition: ERF_SAMUtils.H:107
amrex::Real accrgi
Definition: ERF_SAMUtils.H:106
amrex::Real accrsc
Definition: ERF_SAMUtils.H:102
amrex::Real evapg1
Definition: ERF_SAMUtils.H:108
amrex::Real evapr1
Definition: ERF_SAMUtils.H:110
amrex::Real evapg2
Definition: ERF_SAMUtils.H:109
amrex::Real evapr2
Definition: ERF_SAMUtils.H:111
amrex::Real evaps1
Definition: ERF_SAMUtils.H:104

Referenced by Update_Micro_Vars().

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

◆ Copy_Micro_to_State()

void SAM::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.

16 {
17  // Get the temperature, density, theta, qt and qp from input
18  for ( MFIter mfi(cons,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
19  const auto& box3d = mfi.tilebox();
20 
21  auto states_arr = cons.array(mfi);
22 
23  auto rho_arr = mic_fab_vars[MicVar::rho]->array(mfi);
24  auto theta_arr = mic_fab_vars[MicVar::theta]->array(mfi);
25 
26  auto qv_arr = mic_fab_vars[MicVar::qv]->array(mfi);
27  auto qc_arr = mic_fab_vars[MicVar::qcl]->array(mfi);
28  auto qi_arr = mic_fab_vars[MicVar::qci]->array(mfi);
29 
30  auto qpr_arr = mic_fab_vars[MicVar::qpr]->array(mfi);
31  auto qps_arr = mic_fab_vars[MicVar::qps]->array(mfi);
32  auto qpg_arr = mic_fab_vars[MicVar::qpg]->array(mfi);
33 
34  // get potential total density, temperature, qt, qp
35  ParallelFor( box3d, [=] AMREX_GPU_DEVICE (int i, int j, int k)
36  {
37  SAMPrimitiveCell primitive{};
38  primitive.rho = rho_arr(i,j,k);
39  primitive.theta = theta_arr(i,j,k);
40  primitive.qv = qv_arr(i,j,k);
41  primitive.qcl = qc_arr(i,j,k);
42  primitive.qci = qi_arr(i,j,k);
43  primitive.qpr = qpr_arr(i,j,k);
44  primitive.qps = qps_arr(i,j,k);
45  primitive.qpg = qpg_arr(i,j,k);
46  sam_primitive_to_cons(primitive, states_arr, i, j, k);
47  });
48  }
49 
50  // Fill interior ghost cells and periodic boundaries
51  cons.FillBoundary(m_geom.periodicity());
52 }
auto qv_arr
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:210
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void sam_primitive_to_cons(const SAMPrimitiveCell &primitive, const amrex::Array4< amrex::Real > &states_arr, const int &i, const int &j, const int &k) noexcept
Definition: ERF_SAMUtils.H:314
auto rho_arr
Definition: ERF_UpdateWSubsidence_SineMassFlux.H:3
@ qpr
Definition: ERF_SAM.H:45
@ qpg
Definition: ERF_SAM.H:47
@ qps
Definition: ERF_SAM.H:46
@ cons
Definition: ERF_IndexDefines.H:214
Definition: ERF_SAMUtils.H:52
amrex::Real rho
Definition: ERF_SAMUtils.H:53

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 SAM::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 SAM::Copy_State_to_Micro ( const amrex::MultiFab &  cons_in,
const amrex::MultiFab *  base_state 
)

◆ Define()

void SAM::Define ( SolverChoice sc)
inlineoverridevirtual

Reimplemented from NullMoist.

82  {
84  m_fac_cond = lcond / sc.c_p;
85  m_fac_fus = lfus / sc.c_p;
86  m_fac_sub = lsub / sc.c_p;
87  m_axis = sc.ave_plane;
88  m_rdOcp = sc.rdOcp;
89  m_do_cond = (!sc.uses_shoc_family());
91  }
constexpr amrex::Real lfus
Definition: ERF_MicrophysicsConstants.H:110
constexpr amrex::Real lsub
Definition: ERF_MicrophysicsConstants.H:111
constexpr amrex::Real lcond
Definition: ERF_MicrophysicsConstants.H:109
void set_anelastic_reference_pressure_mode(const SolverChoice &sc)
Definition: ERF_NullMoist.H:155
MoistureType m_moisture_type
Definition: ERF_SAM.H:374
int ave_plane
Averaging plane index used by diagnostics.
Definition: ERF_DataStruct.H:2260
amrex::Real rdOcp
Ratio of dry-air gas constant to c_p.
Definition: ERF_DataStruct.H:2062
bool uses_shoc_family() const noexcept
Query whether any SHOC-family PBL scheme is active.
Definition: ERF_DataStruct.H:2177
amrex::Real c_p
Specific heat at constant pressure for dry air [J/(kg-K)].
Definition: ERF_DataStruct.H:2061
Here is the call graph for this function:

◆ Get_Surface_Precip_Accumulation_Ptrs()

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

Reimplemented from NullMoist.

197  {
198  if (m_moisture_type == MoistureType::SAM_NoPrecip_NoIce) {
199  return {};
200  }
201 
203  sources.rain = {mic_fab_vars[MicVar::rain_accum].get(), rhor / amrex::Real(1000.0)};
204 
205  if (m_moisture_type == MoistureType::SAM) {
206  sources.snow = {mic_fab_vars[MicVar::snow_accum].get(), rhos / amrex::Real(1000.0)};
207  sources.graupel = {mic_fab_vars[MicVar::graup_accum].get(), rhog / amrex::Real(1000.0)};
208  }
209 
210  return sources;
211  }
constexpr amrex::Real rhog
Definition: ERF_MicrophysicsConstants.H:41
constexpr amrex::Real rhos
Definition: ERF_MicrophysicsConstants.H:40
constexpr amrex::Real rhor
Definition: ERF_MicrophysicsConstants.H:39
@ snow_accum
Definition: ERF_SAM.H:50
@ rain_accum
Definition: ERF_SAM.H:49
@ graup_accum
Definition: ERF_SAM.H:51
Definition: ERF_SurfacePrecipitation.H:34
SurfacePrecipAccumulationSource rain
Definition: ERF_SurfacePrecipitation.H:36
SurfacePrecipAccumulationSource snow
Definition: ERF_SurfacePrecipitation.H:37
SurfacePrecipAccumulationSource graupel
Definition: ERF_SurfacePrecipitation.H:38

◆ IceFall()

void SAM::IceFall ( const SolverChoice sc)

Sedimentation of cloud ice (A32)

13  {
14 
16  return;
17 
18  Real dtn = dt;
19  // NOTE: coef carries only the reference vertical spacing. The physical
20  // spacing is supplied by the inverse Jacobian in the tendency below,
21  // since detJ = dz_phys/CellSize(2). Dividing by m_dzmin here as well
22  // would apply the vertical metric twice. m_dzmin is still the correct
23  // length scale for the substep (CFL) count, which must bound the
24  // thinnest cell in the domain.
25  Real coef = dtn * m_geom.InvCellSize(2);
26 
27  auto domain = m_geom.Domain();
28  int k_lo = domain.smallEnd(2);
29  int k_hi = domain.bigEnd(2);
30 
33  auto qn = mic_fab_vars[MicVar::qn];
34  auto qt = mic_fab_vars[MicVar::qt];
37 
38  MultiFab fz;
39  IntVect ng = qcl->nGrowVect();
40  BoxArray ba = qcl->boxArray();
41  DistributionMapping dm = qcl->DistributionMap();
42  fz.define(convert(ba, IntVect(0,0,1)), dm, 1, ng);
43  fz.setVal(0.);
44 
45  for (MFIter mfi(fz, TileNoZ()); mfi.isValid(); ++mfi) {
46  auto qci_array = qci->array(mfi);
47  auto rho_array = rho->array(mfi);
48  auto fz_array = fz.array(mfi);
49 
50  const auto& box3d = mfi.tilebox();
51 
52  ParallelFor(box3d, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
53  {
54  const Real rho_km1 = (k == k_lo) ? rho_array(i,j,k) : rho_array(i,j,k-1);
55  const Real rho_k = (k == k_hi + 1) ? rho_array(i,j,k-1) : rho_array(i,j,k);
56  const Real qci_km1 = (k == k_lo) ? qci_array(i,j,k) : qci_array(i,j,k-1);
57  const Real qci_k = (k == k_hi + 1) ? qci_array(i,j,k-1) : qci_array(i,j,k);
58  const SAMFaceState face_state = sam_face_average_state(k, k_lo, k_hi,
59  rho_km1, rho_k,
60  zero, zero,
61  qci_km1, qci_k,
62  zero, zero);
63  const Real vt_ice = sam_cloud_ice_terminal_velocity(face_state.qci_avg);
64 
65  // NOTE: Fz is the sedimentation flux from the advective operator.
66  // In the terrain-following coordinate system, the z-deriv in
67  // the divergence uses the normal velocity (Omega). However,
68  // there are no u/v components to the sedimentation velocity.
69  // Therefore, we simply end up with a division by detJ when
70  // evaluating the source term: dJinv * (flux_hi - flux_lo) * dzinv.
71  fz_array(i,j,k) = face_state.rho_avg * vt_ice * face_state.qci_avg;
72  });
73  }
74 
75  // Compute number of substeps from maximum terminal velocity
76  Real wt_max;
77  int n_substep;
78  auto const& ma_fz_arr = fz.const_arrays();
79  GpuTuple<Real> max = ParReduce(TypeList<ReduceOpMax>{},
80  TypeList<Real>{},
81  fz, IntVect(0),
82  [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
83  -> GpuTuple<Real>
84  {
85  return { ma_fz_arr[box_no](i,j,k) };
86  });
87  wt_max = get<0>(max);
88  // ParReduce over a MultiFab gives the local rank maximum here. IceFall
89  // needs one global substep count across ranks, matching PrecipFall.
90  ParallelDescriptor::ReduceRealMax(wt_max);
93  "SAM::IceFall: the minimum cell height was never set (Set_dzmin), so the fall substeps cannot be sized");
94  n_substep = sam_substep_count_from_reduced_flux(wt_max, dtn, m_dzmin);
95  AMREX_ALWAYS_ASSERT(n_substep >= 1);
96  coef /= Real(n_substep);
97  dtn /= Real(n_substep);
98 
99  // Substep the vertical advection
100  for (int nsub(0); nsub<n_substep; ++nsub) {
101  for (MFIter mfi(*qci, TileNoZ()); mfi.isValid(); ++mfi) {
102  auto qci_array = qci->array(mfi);
103  auto qn_array = qn->array(mfi);
104  auto qt_array = qt->array(mfi);
105  auto rho_array = rho->array(mfi);
106  auto fz_array = fz.array(mfi);
107 
108  const auto dJ_array = (m_detJ_cc) ? m_detJ_cc->const_array(mfi) : Array4<const Real>{};
109 
110  const auto& tbx = mfi.tilebox();
111  const auto& tbz = mfi.tilebox(IntVect(0,0,1),IntVect(0));
112 
113  // Update vertical flux every substep
114  ParallelFor(tbz, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
115  {
116  const Real rho_km1 = (k == k_lo) ? rho_array(i,j,k) : rho_array(i,j,k-1);
117  const Real rho_k = (k == k_hi + 1) ? rho_array(i,j,k-1) : rho_array(i,j,k);
118  const Real qci_km1 = (k == k_lo) ? qci_array(i,j,k) : qci_array(i,j,k-1);
119  const Real qci_k = (k == k_hi + 1) ? qci_array(i,j,k-1) : qci_array(i,j,k);
120  const SAMFaceState face_state = sam_face_average_state(k, k_lo, k_hi,
121  rho_km1, rho_k,
122  zero, zero,
123  qci_km1, qci_k,
124  zero, zero);
125  const Real vt_ice = sam_cloud_ice_terminal_velocity(face_state.qci_avg);
126 
127  // NOTE: Fz is the sedimentation flux from the advective operator.
128  // In the terrain-following coordinate system, the z-deriv in
129  // the divergence uses the normal velocity (Omega). However,
130  // there are no u/v components to the sedimentation velocity.
131  // Therefore, we simply end up with a division by detJ when
132  // evaluating the source term: dJinv * (flux_hi - flux_lo) * dzinv.
133  fz_array(i,j,k) = face_state.rho_avg * vt_ice * face_state.qci_avg;
134  });
135 
136  // Update precip every substep
137  ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
138  {
139  // Jacobian determinant
140  Real dJinv = (dJ_array) ? one/dJ_array(i,j,k) : one;
141 
142  //==================================================
143  // Cloud ice sedimentation (A32)
144  //==================================================
145  Real dqi = sam_sedimentation_tendency(fz_array(i,j,k+1), fz_array(i,j,k),
146  rho_array(i,j,k), dJinv, coef);
147  dqi = std::max(-qci_array(i,j,k), dqi);
148 
149  // Add this increment to both non-precipitating and total water.
150  qci_array(i,j,k) += dqi;
151  qn_array(i,j,k) += dqi;
152  qt_array(i,j,k) += dqi;
153 
154  // NOTE: Sedimentation does not affect the potential temperature,
155  // but it does affect the liquid/ice static energy.
156  // No source to Theta occurs here.
157  });
158  } // mfi
159  } // nsub
160 }
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_cloud_chamber_config.active, "Cloud Chamber: initializer reached without a parsed configuration")
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int sam_substep_count_from_reduced_flux(const amrex::Real &reduced_flux, const amrex::Real &dt, const amrex::Real &dz) noexcept
Definition: ERF_SAMUtils.H:916
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE SAMFaceState sam_face_average_state(const int &k, const int &k_lo, const int &k_hi, const amrex::Real &rho_km1, const amrex::Real &rho_k, const amrex::Real tabs_km1, const amrex::Real tabs_k, const amrex::Real &qci_km1, const amrex::Real &qci_k, const amrex::Real qp_km1, const amrex::Real qp_k) noexcept
Definition: ERF_SAMUtils.H:869
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sam_sedimentation_tendency(const amrex::Real &fz_hi, const amrex::Real &fz_lo, const amrex::Real &rho, const amrex::Real &dJinv, const amrex::Real &coef) noexcept
Definition: ERF_SAMUtils.H:1103
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sam_cloud_ice_terminal_velocity(const amrex::Real &qci_avg) noexcept
Definition: ERF_SAMUtils.H:861
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
amrex::MultiFab * m_detJ_cc
Definition: ERF_SAM.H:381
amrex::Real m_dzmin
Definition: ERF_SAM.H:377
@ qcl
Definition: ERF_Kessler.H:32
@ tabs
Definition: ERF_Kessler.H:27
@ rho
Definition: ERF_Kessler.H:25
@ qt
Definition: ERF_Kessler.H:30
@ ng
Definition: ERF_Morrison.H:50
@ qn
Definition: ERF_Morrison.H:35
@ qci
Definition: ERF_Morrison.H:38
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
Definition: ERF_SAMUtils.H:133
amrex::Real qci_avg
Definition: ERF_SAMUtils.H:136
amrex::Real rho_avg
Definition: ERF_SAMUtils.H:134

Referenced by Advance().

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

◆ Init()

void SAM::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.

44 {
45  dt = dt_advance;
46  m_geom = geom;
47 
48  m_z_phys_nd = z_phys_nd.get();
49  m_detJ_cc = detJ_cc.get();
50 
51  MicVarMap.resize(m_qmoist_size);
53 
54  // initialize microphysics variables
55  for (auto ivar = 0; ivar < MicVar::NumVars; ++ivar) {
56  mic_fab_vars[ivar] = std::make_shared<MultiFab>(cons_in.boxArray(), cons_in.DistributionMap(),
57  1, cons_in.nGrowVect());
58  mic_fab_vars[ivar]->setVal(0.);
59  }
60 
61  // NOTE: For multi-level not all ranks will own a box.
62  // Furthermore, the plane average allocates space
63  // for the entire domain. We make this consistent.
64  nlev = m_geom.Domain().length(2);
65  zlo = m_geom.Domain().smallEnd(2);
66  zhi = m_geom.Domain().bigEnd(2);
67 
68  // parameters
69  accrrc.resize({zlo}, {zhi});
70  accrsi.resize({zlo}, {zhi});
71  accrsc.resize({zlo}, {zhi});
72  coefice.resize({zlo}, {zhi});
73  evaps1.resize({zlo}, {zhi});
74  evaps2.resize({zlo}, {zhi});
75  accrgi.resize({zlo}, {zhi});
76  accrgc.resize({zlo}, {zhi});
77  evapg1.resize({zlo}, {zhi});
78  evapg2.resize({zlo}, {zhi});
79  evapr1.resize({zlo}, {zhi});
80  evapr2.resize({zlo}, {zhi});
81 
82  // data (input)
83  rho1d.resize({zlo}, {zhi});
84  pres1d.resize({zlo}, {zhi});
85  tabs1d.resize({zlo}, {zhi});
86 }
int m_qmoist_size
Definition: ERF_SAM.H:342
amrex::MultiFab * m_z_phys_nd
Definition: ERF_SAM.H:380
amrex::Vector< int > MicVarMap
Definition: ERF_SAM.H:354
@ NumVars
Definition: ERF_SAM.H:52

◆ NewtonIterSat()

AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real SAM::NewtonIterSat ( int &  i,
int &  j,
int &  k,
const int &  SAM_moisture_type,
const amrex::Real fac_cond,
const amrex::Real fac_fus,
const amrex::Real ,
const amrex::Real an,
const amrex::Real bn,
const amrex::Array4< amrex::Real > &  tabs_array,
const amrex::Array4< amrex::Real > &  pres_array,
const amrex::Array4< amrex::Real > &  qv_array,
const amrex::Array4< amrex::Real > &  qc_array,
const amrex::Array4< amrex::Real > &  qi_array,
const amrex::Array4< amrex::Real > &  qn_array,
const amrex::Array4< amrex::Real > &  qt_array 
)
inlinestatic
230  {
231  // Solution tolerance
232 #ifdef AMREX_USE_FLOAT
233  constexpr amrex::Real tol = amrex::Real(1.e-4);
234 #else
235  constexpr amrex::Real tol = amrex::Real(1.e-8);
236 #endif
237  constexpr int max_iter = 20;
238 
239  // Saturation moisture fractions
240  amrex::Real omn, domn;
241  amrex::Real qsatm, dqsatm;
242  amrex::Real qsatw, dqsatw;
243  amrex::Real qsati, dqsati;
244  amrex::Real qn, qif, dqif;
245 
246  // Newton iteration vars
247  int niter = 0;
248  amrex::Real F, dFdT;
249 
250  //=======================================================================
251  // Mixed-phase Newton iteration to qv=qsat (cloud phase only)
252  //=======================================================================
253 
254  // Initial guess for temperature & pressure
255  amrex::Real tabs = tabs_array(i,j,k);
256  amrex::Real pres = pres_array(i,j,k);
257 
258  // Mixed saturation moisture fractions
261  omn = sam_cloud_liquid_fraction(SAM_moisture_type, tabs, an, bn);
262  qsatm = sam_mixed_qsat(omn, qsatw, qsati);
263 
264  // Saturation derivative WRT temperature
265  domn = zero;
266  if ( (SAM_moisture_type == 1) &&
267  (tabs < tbgmax) && (tabs > tbgmin) ) {
268  domn = an;
269  }
270  erf_dtqsatw(tabs, pres, dqsatw);
271  erf_dtqsati(tabs, pres, dqsati);
272  dqsatm = sam_mixed_dqsat_dT(omn, domn, qsatw, qsati, dqsatw, dqsati);
273 
274  // Enforce omega splitting
275  qn = (qt_array(i,j,k) - qsatm);
276  qif = qn * (one - omn);
277  dqif = sam_mixed_dqif_dT(omn, domn, qn, dqsatm);
278 
279  // Function for root finding (conserve latent proxy):
280  // 0 = -T_new + T_old + L_v/C_p * (qv,0 - qs,m) - L_f/C_p * (qi,0 - qi,f)
281  F = sam_newton_residual(tabs, tabs_array(i,j,k),
282  fac_cond, qv_array(i,j,k), qsatm,
283  fac_fus , qi_array(i,j,k), qif );
284  while (std::abs(F) > tol && niter < max_iter) {
285  // Derivative of function (T_new iterated on)
286  dFdT = sam_newton_residual_derivative(fac_cond, fac_fus, dqsatm, dqif);
287 
288  // Update the temperature
289  tabs -= F/dFdT;
290 
291  // Mixed saturation moisture fractions
294  omn = sam_cloud_liquid_fraction(SAM_moisture_type, tabs, an, bn);
295  qsatm = sam_mixed_qsat(omn, qsatw, qsati);
296 
297  // Saturation derivative WRT temperature
298  domn = zero;
299  if ( (SAM_moisture_type == 1) &&
300  (tabs < tbgmax) && (tabs > tbgmin) ) {
301  domn = an;
302  }
303  erf_dtqsatw(tabs, pres, dqsatw);
304  erf_dtqsati(tabs, pres, dqsati);
305  dqsatm = sam_mixed_dqsat_dT(omn, domn, qsatw, qsati, dqsatw, dqsati);
306 
307  // Enforce omega splitting
308  qn = (qt_array(i,j,k) - qsatm);
309  qif = qn * (one - omn);
310  dqif = sam_mixed_dqif_dT(omn, domn, qn, dqsatm);
311 
312  // Function for root finding (conserve latent proxy):
313  // 0 = -T_new + T_old + L_v/C_p * (qv,0 - qs,m) - L_f/C_p * (qi,0 - qi,f)
314  F = sam_newton_residual(tabs, tabs_array(i,j,k),
315  fac_cond, qv_array(i,j,k), qsatm,
316  fac_fus , qi_array(i,j,k), qif );
317 
318  // Update iteration
319  ++niter;
320  }
321 
322  // NOTE: the while loop already enforces the iteration limit, so the
323  // residual alone determines whether we found a valid root; testing
324  // niter < max_iter here would spuriously fail a solve that
325  // converged on exactly the last allowed iteration.
326  bool valid_solution = (std::abs(F) <= tol);
327  AMREX_ALWAYS_ASSERT_WITH_MESSAGE(valid_solution, "SAM mixed phase saturation adjustment failed to converge.");
328 
329  // Partition the change in non-precipitating q
330  qv_array(i,j,k) = qsatm;
331  qc_array(i,j,k) = qn * omn;
332  qi_array(i,j,k) = qn * (one - omn);
333  qn_array(i,j,k) = qn;
334  qt_array(i,j,k) = qv_array(i,j,k) + qn_array(i,j,k);
335 
336  // Return to temperature
337  return tabs;
338  }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_dtqsatw(amrex::Real t, amrex::Real p, amrex::Real &dtqsatw)
Definition: ERF_MicrophysicsUtils.H:280
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_dtqsati(amrex::Real t, amrex::Real p, amrex::Real &dtqsati)
Definition: ERF_MicrophysicsUtils.H:271
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sam_newton_residual(const amrex::Real &tabs_new, const amrex::Real &tabs_old, const amrex::Real fcond, const amrex::Real &qv, const amrex::Real &qsatm, const amrex::Real ffus, const amrex::Real &qi, const amrex::Real &qif) noexcept
Definition: ERF_SAMUtils.H:477
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sam_mixed_dqif_dT(const amrex::Real &omn, const amrex::Real &domn, const amrex::Real &qn, const amrex::Real &dqsatm) noexcept
Definition: ERF_SAMUtils.H:467
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sam_newton_residual_derivative(const amrex::Real fcond, const amrex::Real ffus, const amrex::Real &dqsatm, const amrex::Real &dqif) noexcept
Definition: ERF_SAMUtils.H:491
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sam_cloud_liquid_fraction(const int &SAM_moisture_type, const amrex::Real &tabs, const amrex::Real an, const amrex::Real bn) noexcept
Definition: ERF_SAMUtils.H:346
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sam_mixed_dqsat_dT(const amrex::Real &omn, const amrex::Real &domn, const amrex::Real &qsatw, const amrex::Real &qsati, const amrex::Real &dqsatw, const amrex::Real &dqsati) noexcept
Definition: ERF_SAMUtils.H:454
Here is the call graph for this function:

◆ Precip()

void SAM::Precip ( const SolverChoice sc)

Autoconversion (A30), Accretion (A28), Evaporation (A24)

13 {
14  if (sam_is_no_precip(sc.moisture_type)) return;
15 
16  Real powr1 = (three + b_rain) / Real(4.0);
17  Real powr2 = (Real(5.0) + b_rain) / Real(8.0);
18  Real pows1 = (three + b_snow) / Real(4.0);
19  Real pows2 = (Real(5.0) + b_snow) / Real(8.0);
20  Real powg1 = (three + b_grau) / Real(4.0);
21  Real powg2 = (Real(5.0) + b_grau) / Real(8.0);
22 
23  auto accrrc_t = accrrc.table();
24  auto accrsc_t = accrsc.table();
25  auto accrsi_t = accrsi.table();
26  auto accrgc_t = accrgc.table();
27  auto accrgi_t = accrgi.table();
28  auto coefice_t = coefice.table();
29  auto evapr1_t = evapr1.table();
30  auto evapr2_t = evapr2.table();
31  auto evaps1_t = evaps1.table();
32  auto evaps2_t = evaps2.table();
33  auto evapg1_t = evapg1.table();
34  auto evapg2_t = evapg2.table();
35 
36  Real fac_cond = m_fac_cond;
37  Real fac_sub = m_fac_sub;
38  Real fac_fus = m_fac_fus;
39  Real rdOcp = m_rdOcp;
40 
42 
43  Real dtn = dt;
44 
45  int SAM_moisture_type = 1;
46  if (sc.moisture_type == MoistureType::SAM_NoIce) {
47  SAM_moisture_type = 2;
48  }
49 
50  const SAMPrecipConfig precip_config{
51  SAM_moisture_type,
52  true,
53  dtn,
54  rdOcp,
55  fac_cond,
56  fac_fus,
57  fac_sub,
58  eps,
59  powr1,
60  pows1,
61  powg1,
62  powr2,
63  pows2,
64  powg2};
65  // get the temperature, density, theta, qt and qp from input
66  for ( MFIter mfi(*(mic_fab_vars[MicVar::tabs]),TilingIfNotGPU()); mfi.isValid(); ++mfi) {
67  auto rho_array = mic_fab_vars[MicVar::rho]->array(mfi);
68  auto theta_array = mic_fab_vars[MicVar::theta]->array(mfi);
69  auto tabs_array = mic_fab_vars[MicVar::tabs]->array(mfi);
70  auto pres_array = mic_fab_vars[MicVar::pres]->array(mfi);
71 
72  // Non-precipitating
73  auto qv_array = mic_fab_vars[MicVar::qv]->array(mfi);
74  auto qcl_array = mic_fab_vars[MicVar::qcl]->array(mfi);
75  auto qci_array = mic_fab_vars[MicVar::qci]->array(mfi);
76  auto qn_array = mic_fab_vars[MicVar::qn]->array(mfi);
77  auto qt_array = mic_fab_vars[MicVar::qt]->array(mfi);
78 
79  // Precipitating
80  auto qpr_array = mic_fab_vars[MicVar::qpr]->array(mfi);
81  auto qps_array = mic_fab_vars[MicVar::qps]->array(mfi);
82  auto qpg_array = mic_fab_vars[MicVar::qpg]->array(mfi);
83  auto qp_array = mic_fab_vars[MicVar::qp]->array(mfi);
84 
85  auto tbx = mfi.tilebox();
86 
87  ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
88  {
89  SAMCellState state{};
90  state.rho = rho_array(i,j,k);
91  state.theta = theta_array(i,j,k);
92  state.tabs = tabs_array(i,j,k);
93  state.pres_mbar = pres_array(i,j,k);
94  state.qv = qv_array(i,j,k);
95  state.qcl = qcl_array(i,j,k);
96  state.qci = qci_array(i,j,k);
97  state.qn = qn_array(i,j,k);
98  state.qt = qt_array(i,j,k);
99  state.qpr = qpr_array(i,j,k);
100  state.qps = qps_array(i,j,k);
101  state.qpg = qpg_array(i,j,k);
102  state.qp = qp_array(i,j,k);
103 
104  const SAMCoefficientRow coeffs{
105  accrrc_t(k),
106  accrsi_t(k),
107  accrsc_t(k),
108  coefice_t(k),
109  evaps1_t(k),
110  evaps2_t(k),
111  accrgi_t(k),
112  accrgc_t(k),
113  evapg1_t(k),
114  evapg2_t(k),
115  evapr1_t(k),
116  evapr2_t(k)};
117 
118  // The scalar helper owns the local held-pressure source update;
119  // this public kernel handles state staging and coefficient lookup.
120  state = sam_precip_cell_update(state, coeffs, precip_config);
121 
122  theta_array(i,j,k) = state.theta;
123  tabs_array(i,j,k) = state.tabs;
124  qv_array(i,j,k) = state.qv;
125  qcl_array(i,j,k) = state.qcl;
126  qci_array(i,j,k) = state.qci;
127  qn_array(i,j,k) = state.qn;
128  qt_array(i,j,k) = state.qt;
129  qpr_array(i,j,k) = state.qpr;
130  qps_array(i,j,k) = state.qps;
131  qpg_array(i,j,k) = state.qpg;
132  qp_array(i,j,k) = state.qp;
133  });
134  }
135 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE SAMCellState sam_precip_cell_update(SAMCellState state, const SAMCoefficientRow &coeffs, const SAMPrecipConfig &config, SAMPrecipCellDiagnostics *diagnostics=nullptr) noexcept
Definition: ERF_SAMUtils.H:652
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool sam_is_no_precip(const MoistureType &moisture_type) noexcept
Definition: ERF_SAMUtils.H:340
@ qp
Definition: ERF_SAM.H:44
Definition: ERF_SAMUtils.H:70

Referenced by Advance().

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

◆ PrecipFall()

void SAM::PrecipFall ( const SolverChoice sc)

Precipitation fluxes P_{r/s/g} (A19)

Code modified from SAMXX, the C++ version of the SAM code.

Parameters
[in]hydro_typeType selection for the precipitation advection hydrodynamics scheme (0-3)
20 {
21  if (sam_is_no_precip(sc.moisture_type)) return;
22 
23  // Conservative component-sedimentation contract: rain, snow, and graupel
24  // sediment with separate component fluxes. Each face flux is limited by
25  // the donor cell's available component mass, including detJ when present.
26  // The same limited bottom fluxes update surface accumulation and the
27  // in-column qpr/qps/qpg flux-divergence update. This closes component and
28  // total precipitation column budgets up to roundoff. Sedimentation does
29  // not update theta.
30 
31  Real rho_0 = Real(1.29);
32 
33  Real gamr3 = erf_gammafff(Real(4.0)+b_rain);
34  Real gams3 = erf_gammafff(Real(4.0)+b_snow);
35  Real gamg3 = erf_gammafff(Real(4.0)+b_grau);
36 
37  Real vrain = (a_rain*gamr3/Real(6.0))*std::pow((PI*rhor*nzeror),-crain);
38  Real vsnow = (a_snow*gams3/Real(6.0))*std::pow((PI*rhos*nzeros),-csnow);
39  Real vgrau = (a_grau*gamg3/Real(6.0))*std::pow((PI*rhog*nzerog),-cgrau);
40 
41  Real dtn = dt;
42  // NOTE: coef carries only the reference vertical spacing. The physical
43  // spacing is supplied by the inverse Jacobian in the tendency below,
44  // since detJ = dz_phys/CellSize(2). Dividing by m_dzmin here as well
45  // would apply the vertical metric twice. m_dzmin is still the correct
46  // length scale for the substep (CFL) count, which must bound the
47  // thinnest cell in the domain.
48  Real coef = dtn * m_geom.InvCellSize(2);
49 
50  auto domain = m_geom.Domain();
51  int k_lo = domain.smallEnd(2);
52  int k_hi = domain.bigEnd(2);
53 
57  auto qp = mic_fab_vars[MicVar::qp];
63 
64  auto ba = tabs->boxArray();
65  auto dm = tabs->DistributionMap();
66  auto ngrow = tabs->nGrowVect();
67 
68  MultiFab fz;
69  fz.define(convert(ba, IntVect(0,0,1)), dm, 3, ngrow);
70 
71  // Precompute the vertical component fluxes for the legacy reduced-flux substep rule.
72  for (MFIter mfi(fz, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
73  auto qpr_array = qpr->const_array(mfi);
74  auto qps_array = qps->const_array(mfi);
75  auto qpg_array = qpg->const_array(mfi);
76  auto rho_array = rho->const_array(mfi);
77  auto tabs_array = tabs->const_array(mfi);
78  auto fz_array = fz.array(mfi);
79 
80  const auto& box3d = mfi.tilebox();
81 
82  ParallelFor(box3d, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
83  {
84  const SAMPrecipComponentFaceState face_state =
85  sam_precip_component_face_state(rho_array, tabs_array,
86  qpr_array, qps_array, qpg_array,
87  i, j, k, k_lo, k_hi);
88  const SAMPrecipFluxComponents raw_fluxes =
90  vrain, vsnow, vgrau);
91  const SAMPrecipFluxComponents corrected_fluxes =
93  rho_0,
94  face_state.rho_avg);
95 
96  fz_array(i,j,k,0) = corrected_fluxes.rain;
97  fz_array(i,j,k,1) = corrected_fluxes.snow;
98  fz_array(i,j,k,2) = corrected_fluxes.graupel;
99  });
100  }
101 
102  // Compute the legacy reduced-flux substep count from the maximum
103  // density-corrected sedimentation flux rather than a direct fall speed.
104  Real max_reduced_flux;
105  int n_substep;
106  auto const& ma_fz_arr = fz.const_arrays();
107  GpuTuple<Real> max = ParReduce(TypeList<ReduceOpMax>{},
108  TypeList<Real>{},
109  fz, IntVect(0),
110  [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k) noexcept
111  -> GpuTuple<Real>
112  {
113  return { ma_fz_arr[box_no](i,j,k,0)
114  + ma_fz_arr[box_no](i,j,k,1)
115  + ma_fz_arr[box_no](i,j,k,2) };
116  });
117  max_reduced_flux = get<0>(max);
118  // ParReduce over a MultiFab gives the local rank maximum here. PrecipFall
119  // needs one global substep count across ranks, including ranks that own no
120  // active tiles for this reduction, so keep the explicit MPI max reduction.
121  ParallelDescriptor::ReduceRealMax(max_reduced_flux);
122  max_reduced_flux += std::numeric_limits<Real>::epsilon();
124  "SAM::PrecipFall: the minimum cell height was never set (Set_dzmin), so the fall substeps cannot be sized");
125  n_substep = sam_substep_count_from_reduced_flux(max_reduced_flux, dtn, m_dzmin);
126  AMREX_ALWAYS_ASSERT(n_substep >= 1);
127  coef /= Real(n_substep);
128  dtn /= Real(n_substep);
129 
130  // Substep the vertical advection
131  for (int nsub(0); nsub<n_substep; ++nsub)
132  {
133  // Refresh ghosts so both sides of a shared z face use the same donor values
134  qpr->FillBoundary(m_geom.periodicity());
135  qps->FillBoundary(m_geom.periodicity());
136  qpg->FillBoundary(m_geom.periodicity());
137  mic_fab_vars[MicVar::rho]->FillBoundary(m_geom.periodicity());
138 
139  for (MFIter mfi(*qp, TileNoZ()); mfi.isValid(); ++mfi) {
140  auto qpr_array = qpr->array(mfi);
141  auto qps_array = qps->array(mfi);
142  auto qpg_array = qpg->array(mfi);
143  auto qp_array = qp->array(mfi);
144  auto rho_array = rho->const_array(mfi);
145  auto tabs_array = tabs->const_array(mfi);
146  auto fz_array = fz.array(mfi);
147 
148  auto rain_accum_array = rain_accum->array(mfi);
149  auto snow_accum_array = snow_accum->array(mfi);
150  auto graup_accum_array = graup_accum->array(mfi);
151 
152  const auto dJ_array = (m_detJ_cc) ? m_detJ_cc->const_array(mfi) : Array4<const Real>{};
153 
154  const auto& tbx = mfi.tilebox();
155  const auto& tbz = mfi.tilebox(IntVect(0,0,1),IntVect(0));
156 
157  // Update vertical flux every substep
158  ParallelFor(tbz, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
159  {
160  const SAMPrecipComponentFaceState face_state =
161  sam_precip_component_face_state(rho_array, tabs_array,
162  qpr_array, qps_array, qpg_array,
163  i, j, k, k_lo, k_hi);
164  const SAMPrecipFluxComponents raw_fluxes =
166  vrain, vsnow, vgrau);
167  const SAMPrecipFluxComponents corrected_fluxes =
169  rho_0,
170  face_state.rho_avg);
171  const int donor_k = sam_precip_face_donor_k(k, k_lo, k_hi);
172  const Real detJ_donor = (dJ_array) ? dJ_array(i,j,donor_k) : one;
173 
174  // NOTE: Fz is the sedimentation flux from the advective operator.
175  // In the terrain-following coordinate system, the z-deriv in
176  // the divergence uses the normal velocity (Omega). However,
177  // there are no u/v components to the sedimentation velocity.
178  // Therefore, we simply end up with a division by detJ when
179  // evaluating the source term: dJinv * (flux_hi - flux_lo) * dzinv.
180  fz_array(i,j,k,0) = sam_limit_precip_component_flux(corrected_fluxes.rain,
181  rho_array(i,j,donor_k),
182  qpr_array(i,j,donor_k),
183  detJ_donor,
184  coef);
185  fz_array(i,j,k,1) = sam_limit_precip_component_flux(corrected_fluxes.snow,
186  rho_array(i,j,donor_k),
187  qps_array(i,j,donor_k),
188  detJ_donor,
189  coef);
190  fz_array(i,j,k,2) = sam_limit_precip_component_flux(corrected_fluxes.graupel,
191  rho_array(i,j,donor_k),
192  qpg_array(i,j,donor_k),
193  detJ_donor,
194  coef);
195 
196  if (k == k_lo) {
197  const SAMSurfaceAccumulation surface_accum =
199  {fz_array(i,j,k,0), fz_array(i,j,k,1), fz_array(i,j,k,2)},
200  dtn);
201  rain_accum_array(i,j,k) = rain_accum_array(i,j,k) + surface_accum.rain;
202  snow_accum_array(i,j,k) = snow_accum_array(i,j,k) + surface_accum.snow;
203  graup_accum_array(i,j,k) = graup_accum_array(i,j,k) + surface_accum.graupel;
204  }
205  });
206 
207  // Update precip every substep
208  ParallelFor(tbx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
209  {
210  // Jacobian determinant
211  Real dJinv = (dJ_array) ? one/dJ_array(i,j,k) : one;
212 
213  //==================================================
214  // Precipitating sedimentation (A19)
215  //==================================================
216  const Real dqpr = sam_sedimentation_tendency(fz_array(i,j,k+1,0), fz_array(i,j,k,0),
217  rho_array(i,j,k), dJinv, coef);
218  const Real dqps = sam_sedimentation_tendency(fz_array(i,j,k+1,1), fz_array(i,j,k,1),
219  rho_array(i,j,k), dJinv, coef);
220  const Real dqpg = sam_sedimentation_tendency(fz_array(i,j,k+1,2), fz_array(i,j,k,2),
221  rho_array(i,j,k), dJinv, coef);
222 
223  qpr_array(i,j,k) = std::max(Real(0.0), qpr_array(i,j,k) + dqpr);
224  qps_array(i,j,k) = std::max(Real(0.0), qps_array(i,j,k) + dqps);
225  qpg_array(i,j,k) = std::max(Real(0.0), qpg_array(i,j,k) + dqpg);
226  qp_array(i,j,k) = qpr_array(i,j,k) + qps_array(i,j,k) + qpg_array(i,j,k);
227 
228  // NOTE: Sedimentation does not affect the potential temperature,
229  // but it does affect the liquid/ice static energy.
230  // No source to Theta occurs here.
231  });
232  } // mfi
233  } // nsub
234 }
Real rho_0
Definition: ERF_InitCustomPert_ABL.H:18
constexpr amrex::Real csnow
Definition: ERF_MicrophysicsConstants.H:70
constexpr amrex::Real nzerog
Definition: ERF_MicrophysicsConstants.H:95
constexpr amrex::Real cgrau
Definition: ERF_MicrophysicsConstants.H:71
constexpr amrex::Real a_grau
Definition: ERF_MicrophysicsConstants.H:66
constexpr amrex::Real nzeror
Definition: ERF_MicrophysicsConstants.H:93
constexpr amrex::Real a_rain
Definition: ERF_MicrophysicsConstants.H:62
constexpr amrex::Real nzeros
Definition: ERF_MicrophysicsConstants.H:94
constexpr amrex::Real a_snow
Definition: ERF_MicrophysicsConstants.H:64
constexpr amrex::Real crain
Definition: ERF_MicrophysicsConstants.H:69
constexpr amrex::Real PI
Definition: ERF_NumericalConstants.H:39
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE SAMPrecipFluxComponents sam_precip_component_fluxes_from_face_state(const SAMPrecipComponentFaceState &face_state, const amrex::Real &vrain, const amrex::Real &vsnow, const amrex::Real &vgrau) noexcept
Definition: ERF_SAMUtils.H:1046
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE SAMSurfaceAccumulation sam_surface_accumulation_from_component_fluxes(const SAMPrecipFluxComponents &component_fluxes, const amrex::Real &dtn) noexcept
Definition: ERF_SAMUtils.H:1116
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sam_limit_precip_component_flux(const amrex::Real &raw_flux, const amrex::Real &rho_donor, const amrex::Real &q_donor, const amrex::Real &detJ_donor, const amrex::Real &coef) noexcept
Definition: ERF_SAMUtils.H:1088
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE SAMPrecipComponentFaceState sam_precip_component_face_state(const amrex::Array4< const amrex::Real > &rho_array, const amrex::Array4< const amrex::Real > &tabs_array, const amrex::Array4< const amrex::Real > &qpr_array, const amrex::Array4< const amrex::Real > &qps_array, const amrex::Array4< const amrex::Real > &qpg_array, const int &i, const int &j, const int &k, const int &k_lo, const int &k_hi) noexcept
Definition: ERF_SAMUtils.H:965
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int sam_precip_face_donor_k(const int &face_k, const int &k_lo, const int &k_hi) noexcept
Definition: ERF_SAMUtils.H:902
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE SAMPrecipFluxComponents sam_precip_flux_components_density_corrected(const SAMPrecipFluxComponents &precip_fluxes, const amrex::Real &rho_0, const amrex::Real &rho_avg) noexcept
Definition: ERF_SAMUtils.H:1073
@ qp
Definition: ERF_Kessler.H:34
@ rain_accum
Definition: ERF_Kessler.H:36
@ qpg
Definition: ERF_Morrison.H:43
@ qps
Definition: ERF_Morrison.H:42
@ graup_accum
Definition: ERF_Morrison.H:54
@ qpr
Definition: ERF_Morrison.H:41
@ snow_accum
Definition: ERF_Morrison.H:53
Definition: ERF_SAMUtils.H:125
amrex::Real rho_avg
Definition: ERF_SAMUtils.H:126
Definition: ERF_SAMUtils.H:146
amrex::Real snow
Definition: ERF_SAMUtils.H:148
amrex::Real rain
Definition: ERF_SAMUtils.H:147
amrex::Real graupel
Definition: ERF_SAMUtils.H:149
Definition: ERF_SAMUtils.H:140
amrex::Real rain
Definition: ERF_SAMUtils.H:141
amrex::Real snow
Definition: ERF_SAMUtils.H:142
amrex::Real graupel
Definition: ERF_SAMUtils.H:143

Referenced by Advance().

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

◆ Qmoist_Ptr() [1/2]

const amrex::MultiFab* SAM::Qmoist_Ptr ( const int &  varIdx) const
inline
161  {
163  return mic_fab_vars[MicVarMap[varIdx]].get();
164  }
Here is the call graph for this function:

◆ Qmoist_Ptr() [2/2]

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

Reimplemented from NullMoist.

154  {
156  return mic_fab_vars[MicVarMap[varIdx]].get();
157  }
Here is the call graph for this function:

◆ Qmoist_Restart_Vars()

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

Reimplemented from NullMoist.

185  {
186  a_idx.clear();
187  a_names.clear();
188 
189  // NOTE: These are the indices to access into qmoist (not mic_fab_vars)
190  a_idx.push_back(0); a_names.push_back("RainAccum");
191  a_idx.push_back(1); a_names.push_back("SnowAccum");
192  a_idx.push_back(2); a_names.push_back("GraupAccum");
193  }

◆ Qmoist_Size()

int SAM::Qmoist_Size ( )
inlineoverridevirtual

Reimplemented from NullMoist.

173 { return SAM::m_qmoist_size; }

◆ Qstate_Moist_NumConc_Size()

int SAM::Qstate_Moist_NumConc_Size ( )
inlineoverridevirtual

Reimplemented from NullMoist.

int n_qstate_moist_numconc_size
Definition: ERF_SAM.H:348

◆ Qstate_Moist_Size()

int SAM::Qstate_Moist_Size ( )
inlineoverridevirtual

Reimplemented from NullMoist.

176 { return SAM::n_qstate_moist_size; }
int n_qstate_moist_size
Definition: ERF_SAM.H:345

◆ Set_dzmin()

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

Reimplemented from NullMoist.

105  {
106  m_dzmin = dz_min;
107  }

◆ Update_Micro_Vars() [1/2]

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

Reimplemented from NullMoist.

127  {
128  this->Copy_State_to_Micro(cons_in);
130  }
bool m_use_anelastic_reference_pressure
Definition: ERF_NullMoist.H:175
void Copy_State_to_Micro(const amrex::MultiFab &cons_in) override
void Compute_Coefficients(bool use_anelastic_reference_pressure=false)
Definition: ERF_InitSAM.cpp:154
Here is the call graph for this function:

◆ Update_Micro_Vars() [2/2]

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

Reimplemented from NullMoist.

◆ Update_State_Vars()

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

Reimplemented from NullMoist.

135  {
136  this->Copy_Micro_to_State(cons_in);
137  }
void Copy_Micro_to_State(amrex::MultiFab &cons_in) override
Definition: ERF_UpdateSAM.cpp:15
Here is the call graph for this function:

Member Data Documentation

◆ accrgc

amrex::TableData<amrex::Real, 1> SAM::accrgc
private

◆ accrgi

amrex::TableData<amrex::Real, 1> SAM::accrgi
private

◆ accrrc

amrex::TableData<amrex::Real, 1> SAM::accrrc
private

◆ accrsc

amrex::TableData<amrex::Real, 1> SAM::accrsc
private

◆ accrsi

amrex::TableData<amrex::Real, 1> SAM::accrsi
private

◆ CFL_MAX

constexpr amrex::Real SAM::CFL_MAX = myhalf
staticconstexprprivate

◆ coefice

amrex::TableData<amrex::Real, 1> SAM::coefice
private

◆ dt

amrex::Real SAM::dt
private

Referenced by Advance().

◆ evapg1

amrex::TableData<amrex::Real, 1> SAM::evapg1
private

◆ evapg2

amrex::TableData<amrex::Real, 1> SAM::evapg2
private

◆ evapr1

amrex::TableData<amrex::Real, 1> SAM::evapr1
private

◆ evapr2

amrex::TableData<amrex::Real, 1> SAM::evapr2
private

◆ evaps1

amrex::TableData<amrex::Real, 1> SAM::evaps1
private

◆ evaps2

amrex::TableData<amrex::Real, 1> SAM::evaps2
private

◆ m_axis

int SAM::m_axis
private

Referenced by Define().

◆ m_detJ_cc

amrex::MultiFab* SAM::m_detJ_cc
private

◆ m_do_cond

bool SAM::m_do_cond
private

Referenced by Define().

◆ m_dzmin

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

Referenced by Set_dzmin().

◆ m_fac_cond

amrex::Real SAM::m_fac_cond
private

Referenced by Define().

◆ m_fac_fus

amrex::Real SAM::m_fac_fus
private

Referenced by Define().

◆ m_fac_sub

amrex::Real SAM::m_fac_sub
private

Referenced by Define().

◆ m_geom

amrex::Geometry SAM::m_geom
private

◆ m_moisture_type

MoistureType SAM::m_moisture_type = MoistureType::None
private

◆ m_qmoist_size

int SAM::m_qmoist_size = 3
private

Referenced by Qmoist_Ptr(), and Qmoist_Size().

◆ m_rdOcp

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

Referenced by Define().

◆ m_z_phys_nd

amrex::MultiFab* SAM::m_z_phys_nd
private

◆ mic_fab_vars

amrex::Array<FabPtr, MicVar::NumVars> SAM::mic_fab_vars
private

◆ MicVarMap

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

Referenced by Qmoist_Ptr().

◆ n_qstate_moist_numconc_size

int SAM::n_qstate_moist_numconc_size = 0
private

◆ n_qstate_moist_size

int SAM::n_qstate_moist_size = 6
private

Referenced by Qstate_Moist_Size().

◆ nlev

int SAM::nlev
private

◆ pres1d

amrex::TableData<amrex::Real, 1> SAM::pres1d
private

◆ qn1d

amrex::TableData<amrex::Real, 1> SAM::qn1d
private

◆ qt1d

amrex::TableData<amrex::Real, 1> SAM::qt1d
private

◆ qv1d

amrex::TableData<amrex::Real, 1> SAM::qv1d
private

◆ rho1d

amrex::TableData<amrex::Real, 1> SAM::rho1d
private

◆ tabs1d

amrex::TableData<amrex::Real, 1> SAM::tabs1d
private

◆ zhi

int SAM::zhi
private

◆ zlo

int SAM::zlo
private

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