ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_SatAdj.H
Go to the documentation of this file.
1 #ifndef ERF_SATADJ_H
2 #define ERF_SATADJ_H
3 
4 /*
5  * Implementation saturation adjustment microphysics model
6  * The model transports qv and qc and does Newton iterations
7  * to complete condensation/evaporation.
8  */
9 
10 #include <string>
11 #include <vector>
12 #include <memory>
13 
14 #include <AMReX_FArrayBox.H>
15 #include <AMReX_Geometry.H>
16 #include <AMReX_MultiFabUtil.H>
17 #include <AMReX_GpuContainers.H>
18 
19 #include "ERF_EOS.H"
20 #include "ERF_Constants.H"
21 #include "ERF_MicrophysicsUtils.H"
22 #include "ERF_IndexDefines.H"
23 #include "ERF_DataStruct.H"
24 #include "ERF_NullMoist.H"
25 #include "ERF_TileNoZ.H"
26 
27 namespace MicVar_SatAdj {
28  enum {
29  // independent variables
30  rho=0, // density
31  theta, // liquid/ice water potential temperature
32  tabs, // temperature
33  pres, // pressure
34  // non-precipitating vars
35  qv, // cloud vapor
36  qc, // cloud water
37  NumVars
38  };
39 }
40 
41 class SatAdj : public NullMoist {
42 
43  using FabPtr = std::shared_ptr<amrex::MultiFab>;
44 
45 public:
46  // constructor
47  SatAdj () {}
48 
49  // destructor
50  virtual ~SatAdj () = default;
51 
52  // cloud physics
53  void AdvanceSatAdj (const SolverChoice& /*solverChoice*/);
54 
55  // Set up for first time
56  void
57  Define (SolverChoice& sc) override
58  {
59  m_fac_cond = lcond / sc.c_p;
60  m_rdOcp = sc.rdOcp;
61  m_do_cond = (!sc.use_shoc);
62  }
63 
64  // init
65  void
66  Init (const amrex::MultiFab& cons_in,
67  const amrex::BoxArray& /*grids*/,
68  const amrex::Geometry& geom,
69  const amrex::Real& dt_advance,
70  std::unique_ptr<amrex::MultiFab>& /*z_phys_nd*/,
71  std::unique_ptr<amrex::MultiFab>& /*detJ_cc*/) override;
72 
73  // Copy state into micro vars
74  void
75  Copy_State_to_Micro (const amrex::MultiFab& cons_in) override;
76 
77  // Copy state into micro vars
78  void
79  Copy_Micro_to_State (amrex::MultiFab& cons_in) override;
80 
81  // update micro vars
82  void
83  Update_Micro_Vars (amrex::MultiFab& cons_in) override
84  {
85  this->Copy_State_to_Micro(cons_in);
86  }
87 
88  // update state vars
89  void
90  Update_State_Vars (amrex::MultiFab& cons_in,
91  const amrex::MultiFab& /*z_phys_nd*/) override
92  {
93  this->Copy_Micro_to_State(cons_in);
94  }
95 
96  // wrapper to advance micro vars
97  void
98  Advance (const amrex::Real& dt_advance,
99  const SolverChoice& solverChoice) override
100  {
101  dt = dt_advance;
102 
103  this->AdvanceSatAdj(solverChoice);
104  }
105 
106  amrex::MultiFab*
107  Qmoist_Ptr (const int& varIdx) override
108  {
110  return nullptr;
111  }
112 
113  int
114  Qmoist_Size () override { return SatAdj::m_qmoist_size; }
115 
116  int
118 
119  void
121  std::vector<int>& a_idx,
122  std::vector<std::string>& a_names) const override
123  {
124  a_idx.clear();
125  a_names.clear();
126  }
127 
128  void
129  Set_RealWidth (const int real_width) override { m_real_width = real_width; }
130 
131  AMREX_GPU_HOST_DEVICE
132  AMREX_FORCE_INLINE
133  static amrex::Real
135  const amrex::Real tabs_old,
136  const amrex::Real pres_mbar,
137  const amrex::Real qv_old,
138  amrex::Real& qsat)
139  {
140  constexpr amrex::Real tol = amrex::Real(1.0e-8);
141  constexpr int max_niter = 20;
142 
143  amrex::Real dqsat;
144 
145  int niter = 0;
146  amrex::Real fff, dfff;
147  amrex::Real dtabs = one;
148 
149  amrex::Real tabs = tabs_old;
150 
151  //==================================================
152  // Newton iteration to qv=qsat (cloud phase only)
153  //==================================================
154  do {
155  // Saturation moisture fractions
156  erf_qsatw(tabs, pres_mbar, qsat);
157  erf_dtqsatw(tabs, pres_mbar, dqsat);
158 
159  // Function for root finding:
160  // 0 = -T_new + T_old + L_eff/C_p * (qv - qsat)
161  fff = -tabs + tabs_old + fac_cond*(qv_old - qsat);
162 
163  // Derivative of function (T_new iterated on)
164  dfff = -one - fac_cond*dqsat;
165 
166  // Update the temperature
167  dtabs = -fff/dfff;
168  tabs += dtabs;
169 
170  // Update iteration
171  niter = niter+1;
172  } while(std::abs(dtabs) > tol && niter < max_niter);
173 
174  // Update qsat from last iteration (dq = dq/dt * dt)
175  qsat += dqsat*dtabs;
176 
177  return tabs;
178  }
179 
180  AMREX_GPU_HOST_DEVICE
181  AMREX_FORCE_INLINE
182  static void
183  AdjustSatAdjCell (const amrex::Real fac_cond,
184  const amrex::Real rdOcp,
185  amrex::Real& tabs,
186  const amrex::Real pres_mbar,
188  amrex::Real& qv,
189  amrex::Real& qc)
190  {
191  amrex::Real qsat;
192  erf_qsatw(tabs, pres_mbar, qsat);
193 
194  if ((qv + qc) > qsat) {
195 #if defined(AMREX_DEBUG)
196  const amrex::Real qvprev = qv;
197  const amrex::Real qcprev = qc;
198 #endif
199 
200  if (qc < 0) {
201  qv += qc;
202  qc = zero;
203  }
204 
205  tabs = NewtonSolveSatTemperature(fac_cond, tabs, pres_mbar, qv, qsat);
206 
207  const amrex::Real delta_qv = qv - qsat;
208  qv = qsat;
209  qc += delta_qv;
210 
211 #if defined(AMREX_DEBUG)
212  amrex::Real qsatnew;
213  erf_qsatw(tabs, pres_mbar, qsatnew);
214  AMREX_ASSERT(std::abs(qv-qsatnew) < 1e-12);
215  AMREX_ASSERT(std::abs(qv+qc-qvprev-qcprev) < 1e-14);
216 #endif
217 
218  theta = getThgivenTandP(tabs, amrex::Real(100.0)*pres_mbar, rdOcp);
219  } else {
220  const amrex::Real delta_qc = qc;
221 
222  qv += qc;
223  qc = zero;
224 
225  tabs -= fac_cond * delta_qc;
226  theta = getThgivenTandP(tabs, amrex::Real(100.0)*pres_mbar, rdOcp);
227 
228  erf_qsatw(tabs, pres_mbar, qsat);
229  if (qv > qsat) {
230 #if defined(AMREX_DEBUG)
231  const amrex::Real qvprev = qv;
232  const amrex::Real qcprev = qc;
233  const amrex::Real Tprev = tabs;
234 #endif
235 
236  tabs = NewtonSolveSatTemperature(fac_cond, tabs, pres_mbar, qv, qsat);
237 
238  const amrex::Real delta_qv = qv - qsat;
239  qv = qsat;
240  qc += delta_qv;
241 
242 #if defined(AMREX_DEBUG)
243  amrex::Real qsatnew;
244  erf_qsatw(tabs, pres_mbar, qsatnew);
245  AMREX_ASSERT(qv < qvprev);
246  AMREX_ASSERT(qc > qcprev);
247  AMREX_ASSERT(tabs > Tprev);
248  AMREX_ASSERT(std::abs(qv-qsatnew) < 1e-14);
249  AMREX_ASSERT(std::abs(qv+qc-qvprev-qcprev) < 1e-14);
250 #endif
251 
252  theta = getThgivenTandP(tabs, amrex::Real(100.0)*pres_mbar, rdOcp);
253  }
254  }
255  }
256 
257 private:
258  // Number of qmoist variables (no precipitating comps to accumulate)
259  int m_qmoist_size = 0;
260 
261  // Number of qstate variables
263 
264  // geometry
265  amrex::Geometry m_geom;
266 
267  // Nudging + set width
268  int m_real_width{0};
269 
270  // timestep
272 
273  // constants
276  bool m_do_cond;
277 
278  // independent variables
279  amrex::Array<FabPtr, MicVar_SatAdj::NumVars> mic_fab_vars;
280 };
281 #endif
constexpr amrex::Real one
Definition: ERF_Constants.H:7
constexpr amrex::Real zero
Definition: ERF_Constants.H:6
constexpr amrex::Real lcond
Definition: ERF_Constants.H:77
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getThgivenTandP(const amrex::Real T, const amrex::Real P, const amrex::Real rdOcp)
Definition: ERF_EOS.H:18
const Real rdOcp
Definition: ERF_InitCustomPert_Bomex.H:16
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_dtqsatw(amrex::Real t, amrex::Real p, amrex::Real &dtqsatw)
Definition: ERF_MicrophysicsUtils.H:244
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_qsatw(amrex::Real t, amrex::Real p, amrex::Real &qsatw)
Definition: ERF_MicrophysicsUtils.H:228
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_NullMoist.H:8
Definition: ERF_SatAdj.H:41
int n_qstate_moist_size
Definition: ERF_SatAdj.H:262
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE void AdjustSatAdjCell(const amrex::Real fac_cond, const amrex::Real rdOcp, amrex::Real &tabs, const amrex::Real pres_mbar, amrex::Real &theta, amrex::Real &qv, amrex::Real &qc)
Definition: ERF_SatAdj.H:183
amrex::Real m_fac_cond
Definition: ERF_SatAdj.H:274
int Qmoist_Size() override
Definition: ERF_SatAdj.H:114
void Update_Micro_Vars(amrex::MultiFab &cons_in) override
Definition: ERF_SatAdj.H:83
amrex::Geometry m_geom
Definition: ERF_SatAdj.H:265
void Qmoist_Restart_Vars(const SolverChoice &, std::vector< int > &a_idx, std::vector< std::string > &a_names) const override
Definition: ERF_SatAdj.H:120
amrex::Array< FabPtr, MicVar_SatAdj::NumVars > mic_fab_vars
Definition: ERF_SatAdj.H:279
amrex::Real m_rdOcp
Definition: ERF_SatAdj.H:275
SatAdj()
Definition: ERF_SatAdj.H:47
virtual ~SatAdj()=default
void Update_State_Vars(amrex::MultiFab &cons_in, const amrex::MultiFab &) override
Definition: ERF_SatAdj.H:90
amrex::MultiFab * Qmoist_Ptr(const int &varIdx) override
Definition: ERF_SatAdj.H:107
void Set_RealWidth(const int real_width) override
Definition: ERF_SatAdj.H:129
int Qstate_Moist_Size() override
Definition: ERF_SatAdj.H:117
std::shared_ptr< amrex::MultiFab > FabPtr
Definition: ERF_SatAdj.H:43
void Copy_Micro_to_State(amrex::MultiFab &cons_in) override
Definition: ERF_UpdateSatAdj.cpp:12
bool m_do_cond
Definition: ERF_SatAdj.H:276
void Init(const amrex::MultiFab &cons_in, const amrex::BoxArray &, const amrex::Geometry &geom, const amrex::Real &dt_advance, std::unique_ptr< amrex::MultiFab > &, std::unique_ptr< amrex::MultiFab > &) override
Definition: ERF_InitSatAdj.cpp:17
void Advance(const amrex::Real &dt_advance, const SolverChoice &solverChoice) override
Definition: ERF_SatAdj.H:98
int m_qmoist_size
Definition: ERF_SatAdj.H:259
void AdvanceSatAdj(const SolverChoice &)
Definition: ERF_SatAdj.cpp:8
amrex::Real dt
Definition: ERF_SatAdj.H:271
void Define(SolverChoice &sc) override
Definition: ERF_SatAdj.H:57
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE amrex::Real NewtonSolveSatTemperature(const amrex::Real fac_cond, const amrex::Real tabs_old, const amrex::Real pres_mbar, const amrex::Real qv_old, amrex::Real &qsat)
Definition: ERF_SatAdj.H:134
int m_real_width
Definition: ERF_SatAdj.H:268
void Copy_State_to_Micro(const amrex::MultiFab &cons_in) override
Definition: ERF_InitSatAdj.cpp:40
Definition: ERF_SatAdj.H:27
@ theta
Definition: ERF_SatAdj.H:31
@ rho
Definition: ERF_SatAdj.H:30
@ pres
Definition: ERF_SatAdj.H:33
@ NumVars
Definition: ERF_SatAdj.H:37
@ qv
Definition: ERF_SatAdj.H:35
@ tabs
Definition: ERF_SatAdj.H:32
@ qc
Definition: ERF_SatAdj.H:36
Definition: ERF_DataStruct.H:130
amrex::Real rdOcp
Definition: ERF_DataStruct.H:1169
amrex::Real c_p
Definition: ERF_DataStruct.H:1168
bool use_shoc
Definition: ERF_DataStruct.H:1200