ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_InitCustomPert_MultiSpeciesBubble.H
Go to the documentation of this file.
1 
2  // On a mesh other than ConstantDz, heights come from z_cc and the vertical levels,
3  // not from geomdata's prob_lo[2] and CellSize(2)
4  const bool use_z_phys = use_physical_z();
5 
6  ParmParse pp_prob("prob");
7  Real T_0 = amrex::Real(300.0); pp_prob.query("T_0", T_0);
8 
9  // center of thermal perturbation
10  Real x_c = zero; pp_prob.query("x_c", x_c);
11  Real y_c = zero; pp_prob.query("y_c", y_c);
12  Real z_c = zero; pp_prob.query("z_c", z_c);
13 
14  // radial extent of thermal perturbation
15  Real x_r = zero; pp_prob.query("x_r", x_r);
16  Real y_r = zero; pp_prob.query("y_r", y_r);
17  Real z_r = zero; pp_prob.query("z_r", z_r);
18 
19  // perturbation temperature
20  Real T_pert = -amrex::Real(15.0); pp_prob.query("T_pert", T_pert);
21  bool T_pert_is_airtemp = true ; pp_prob.query("T_pert_is_airtemp", T_pert_is_airtemp);
22  bool perturb_rho = true ; pp_prob.query("perturb_rho", perturb_rho);
23 
24  // Moist bubble params
25  bool do_moist_bubble = false; pp_prob.query("do_moist_bubble", do_moist_bubble);
26  Real theta_pert = two; pp_prob.query("theta_pert", theta_pert);
27  Real eq_pot_temp = amrex::Real(320.0); pp_prob.query("eq_pot_temp",eq_pot_temp);
28  Real qt_init = amrex::Real(0.02); pp_prob.query("qt_init", qt_init);
29  bool use_empirical = false; pp_prob.query("use_empirical_psat",use_empirical);
30 
31  std::vector<std::string> m_species;
32  int m_num_species = 0;
33  const int m_ncomp_per_species = 2; // rho*qc, rho*qc
34  const int m_nstart_sp = RhoQ6_comp+1; // Start after all 6 SuperDroplets components
35 
36  // check for SDM species
37  m_species.clear();
38  ParmParse pp_sdm("super_droplets_moisture");
39  std::string species_input = "species";
40  if (pp_sdm.contains(species_input.c_str())) {
41  int num_species = pp_sdm.countval(species_input.c_str());
42  std::string sp_name;
43  for (int i = 0; i < num_species; i++) {
44  pp_sdm.get(species_input.c_str(), sp_name, i);
45  m_species.push_back(sp_name);
46  }
47  }
48 
49  m_num_species = m_species.size();
50 
51  std::vector<amrex::Real> m_qv_init_species = std::vector<amrex::Real>(m_num_species,zero);
52  for (int i = 0; i < m_num_species; i++) {
53  std::string key_str = "qv_init_" + m_species[i];
54  pp_prob.query(key_str.c_str(), m_qv_init_species[i]);
55  }
56 
57  AMREX_ALWAYS_ASSERT(sc.moisture_type == MoistureType::SuperDroplets);
58 
59  const auto khi = geomdata.Domain().bigEnd()[2];
60  const Real dz = geomdata.CellSize()[2];
61 
62 #ifndef AMREX_USE_GPU
63  if (T_0 <= 0)
64  {
65  amrex::Print() << "Ignoring T_0 = " << T_0
66  << ", background fields should have been initialized with erf.init_type"
67  << std::endl;
68  }
69 #endif
70 
71  const Real rdOcp = sc.rdOcp;
72 
74  Vector<Real> h_r(khi+2);
75  Vector<Real> h_p(khi+2);
76  Vector<Real> h_t(khi+2);
77  Vector<Real> h_q_v(khi+2);
78 
79  Gpu::DeviceVector<Real> d_r(khi+2);
80  Gpu::DeviceVector<Real> d_p(khi+2);
81  Gpu::DeviceVector<Real> d_t(khi+2);
82  Gpu::DeviceVector<Real> d_q_v(khi+2);
83 
84  if (use_z_phys) {
85  HSEutils::init_isentropic_hse_no_terrain(h_t.data(), h_r.data(), h_p.data(),
86  h_q_v.data(), m_zlevels_stag[lev].data(), khi, qt_init, eq_pot_temp, use_empirical);
87  } else {
88  HSEutils::init_isentropic_hse_no_terrain(h_t.data(), h_r.data(), h_p.data(),
89  h_q_v.data(), dz, geomdata.ProbLo(2), khi, qt_init, eq_pot_temp, use_empirical);
90  }
91 
92  Gpu::copy(Gpu::hostToDevice, h_r.begin(), h_r.end(), d_r.begin());
93  Gpu::copy(Gpu::hostToDevice, h_p.begin(), h_p.end(), d_p.begin());
94  Gpu::copy(Gpu::hostToDevice, h_t.begin(), h_t.end(), d_t.begin());
95  Gpu::copy(Gpu::hostToDevice, h_q_v.begin(), h_q_v.end(), d_q_v.begin());
96 
97  Real* theta_back = d_t.data();
98  Real* p_back = d_p.data();
99  Real* q_v_back = d_q_v.data();
100 
101  int which_zone = -1;
102 
103  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
104  {
105  // Geometry (note we must include these here to get the data on device)
106  const auto prob_lo = geomdata.ProbLo();
107  const auto dx = geomdata.CellSize();
108 
109  const auto x = prob_lo[0] + (i + myhalf) * dx[0];
110  const auto y = prob_lo[1] + (j + myhalf) * dx[1];
111  const auto z = use_z_phys ? z_cc(i,j,k) : prob_lo[2] + (k + myhalf) * dx[2];
112 
113  Real rad, delta_theta, theta_total, rho, RH;
114 
115  // Introduce the warm bubble.
116  // Assume that the bubble is pressure matched with the background
117  rad = zero;
118  if (x_r > 0) rad += amrex::Math::powi<2>((x - x_c)/x_r);
119  if (y_r > 0) rad += amrex::Math::powi<2>((y - y_c)/y_r);
120  if (z_r > 0) rad += amrex::Math::powi<2>((z - z_c)/z_r);
121  rad = std::sqrt(rad);
122 
123  if (rad <= one){
124  delta_theta = theta_pert*amrex::Math::powi<2>(std::cos(PI*rad/two));
125  } else {
126  delta_theta = zero;
127  }
128 
129  theta_total = theta_back[k]*(delta_theta/amrex::Real(300.0) + one);
130  Real T = getTgivenPandTh(p_back[k], theta_total, RdoCp);
131  rho = p_back[k]/(R_d*T*(one + RvoRd*q_v_back[k]));
132  RH = one; // compute_relative_humidity();
133  Real q_v_hot = HSEutils::vapor_mixing_ratio(p_back[k], T, RH, use_empirical, which_zone);
134 
135  // Compute background quantities
136  Real T_back = getTgivenPandTh(p_back[k], theta_back[k], RdoCp);
137  Real rho_back = p_back[k]/(R_d*T_back*(one + RvoRd*q_v_back[k]));
138 
139  // This version perturbs rho but not p
140  state_pert(i, j, k, RhoTheta_comp) = rho*theta_total - rho_back*theta_back[k]*(one + RvoRd*q_v_back[k]);
141  state_pert(i, j, k, Rho_comp) = rho - rho_back*(one + qt_init);
142 
143  // mean states
144  state_pert(i, j, k, RhoQ1_comp) = rho*q_v_hot;
145  });
146 
147  // The kernel above reads d_r, d_p, d_t and d_q_v; wait for it before they are freed
148  Gpu::streamSynchronize();
149  } else {
150  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
151  {
152  // Geometry (note we must include these here to get the data on device)
153  const auto prob_lo = geomdata.ProbLo();
154  const auto dx = geomdata.CellSize();
155 
156  const Real x = prob_lo[0] + (i + myhalf) * dx[0];
157  const Real y = prob_lo[1] + (j + myhalf) * dx[1];
158  const Real z = use_z_phys ? z_cc(i,j,k) : prob_lo[2] + (k + myhalf) * dx[2];
159 
160  // perturb_rho_theta(x, y, z, p_hse(i,j,k), r_hse(i,j,k), rdOcp,
161  // state_pert(i, j, k, Rho_comp),
162  // state_pert(i, j, k, RhoTheta_comp));
163 
164  // Perturbation air temperature
165  // - The bubble is either cylindrical (for 2-D problems, if two
166  // radial extents are specified) or an ellipsoid (if all three
167  // radial extents are specified).
168  Real L = zero;
169  if (x_r > 0) L += amrex::Math::powi<2>((x - x_c)/x_r);
170  if (y_r > 0) L += amrex::Math::powi<2>((y - y_c)/y_r);
171  if (z_r > 0) L += amrex::Math::powi<2>((z - z_c)/z_r);
172  L = std::sqrt(L);
173  Real dT;
174  if (L > one) {
175  dT = zero;
176  }
177  else {
178  dT = T_pert * amrex::Math::powi<2>(std::cos(PI*L/two));
179  }
180 
181  // Temperature that satisfies the EOS given the hydrostatically balanced (r,p)
182  const Real Tbar_hse = p_hse(i,j,k) / (R_d * r_hse(i,j,k));
183 
184  // Note: theta_perturbed is theta PLUS perturbation in theta
185  Real theta_perturbed;
186  if (T_pert_is_airtemp) {
187  // dT is air temperature
188  theta_perturbed = (Tbar_hse + dT)*std::pow(p_0/p_hse(i,j,k), rdOcp);
189  } else {
190  // dT is potential temperature
191  theta_perturbed = Tbar_hse*std::pow(p_0/p_hse(i,j,k), rdOcp) + dT;
192  }
193 
194  if (perturb_rho)
195  {
196  // this version perturbs rho but not p (i.e., rho*theta)
197  // - hydrostatic rebalance is needed (TODO: is this true?)
198  // - this is the approach taken in the density current problem
199  state_pert(i,j,k,RhoTheta_comp) = zero; // i.e., hydrostatically balanced pressure stays const
200  state_pert(i,j,k,Rho_comp ) = getRhoThetagivenP(p_hse(i,j,k)) / theta_perturbed - r_hse(i,j,k);
201  }
202  else
203  {
204  // this version perturbs rho*theta (i.e., p) but not rho
205  state_pert(i,j,k,Rho_comp) = zero; // i.e., hydrostatically balanced density stays const
206  state_pert(i,j,k,RhoTheta_comp) = r_hse(i,j,k) * theta_perturbed - getRhoThetagivenP(p_hse(i,j,k));
207  }
208 
209  });
210  } // do_moist_bubble
211 
212  // if other species are present
215  int ncomp_species = state_pert.nComp() - nstart;
217  Gpu::DeviceVector<Real> qv_init_d(n_sp);
218  Gpu::copy( Gpu::hostToDevice,
219  m_qv_init_species.begin(),
220  m_qv_init_species.end(),
221  qv_init_d.begin() );
222  auto qv_arr = qv_init_d.data();
223 
224  ParallelFor(bx, [=]
225  AMREX_GPU_DEVICE(int i, int j, int k) noexcept
226  {
227  const auto prob_lo = geomdata.ProbLo();
228  const auto dx = geomdata.CellSize();
229 
230  const Real x = prob_lo[0] + (i + myhalf) * dx[0];
231  const Real y = prob_lo[1] + (j + myhalf) * dx[1];
232  const Real z = use_z_phys ? z_cc(i,j,k) : prob_lo[2] + (k + myhalf) * dx[2];
233 
234  amrex::Real L = zero;
235  if (x_r > 0) L += amrex::Math::powi<2>((x - x_c)/x_r);
236  if (y_r > 0) L += amrex::Math::powi<2>((y - y_c)/y_r);
237  if (z_r > 0) L += amrex::Math::powi<2>((z - z_c)/z_r);
238  L = std::sqrt(L);
239 
240  if (L < one) {
241  auto rho = state(i,j,k,Rho_comp) + state_pert(i,j,k,Rho_comp);
242  for (int ns = 0; ns < n_sp; ns++) {
243  state_pert(i, j, k, nstart+2*ns) = rho*qv_arr[ns];
244  state_pert(i, j, k, nstart+2*ns+1) = zero;
245  }
246  }
247  });
248 
249  // The kernel above reads qv_init_d; wait for it before it is freed
250  Gpu::streamSynchronize();
constexpr amrex::Real p_0
Definition: ERF_Constants.H:69
constexpr amrex::Real RvoRd
Definition: ERF_Constants.H:59
constexpr amrex::Real R_d
Definition: ERF_Constants.H:49
constexpr amrex::Real RdoCp
Definition: ERF_Constants.H:57
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getRhoThetagivenP(const amrex::Real p, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:172
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getTgivenPandTh(const amrex::Real P, const amrex::Real th, const amrex::Real rdOcp)
Definition: ERF_EOS.H:32
#define Rho_comp
Definition: ERF_IndexDefines.H:53
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:54
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:66
#define RhoQ6_comp
Definition: ERF_IndexDefines.H:71
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
const GpuArray< Real, AMREX_SPACEDIM > prob_lo
Definition: ERF_InitCustomPert_CloudChamber.H:33
const bool use_z_phys
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:4
Real theta_pert
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:26
int m_num_species
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:32
std::string species_input
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:39
Real z_c
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:12
bool T_pert_is_airtemp
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:21
Real x_r
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:15
bool do_moist_bubble
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:25
const int m_nstart_sp
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:34
int ncomp_species
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:215
const Real rdOcp
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:71
Real x_c
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:10
ParmParse pp_prob("prob")
Gpu::DeviceVector< Real > qv_init_d(n_sp)
auto qv_arr
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:222
Real T_0
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:7
auto n_sp
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:213
std::vector< amrex::Real > m_qv_init_species
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:51
Real z_r
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:17
ParmParse pp_sdm("super_droplets_moisture")
Real y_c
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:11
auto nstart
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:214
Real eq_pot_temp
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:27
bool perturb_rho
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:22
bool use_empirical
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:29
Real T_pert
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:20
const int m_ncomp_per_species
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:33
ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept { const auto prob_lo=geomdata.ProbLo();const auto dx=geomdata.CellSize();const Real x=prob_lo[0]+(i+myhalf) *dx[0];const Real y=prob_lo[1]+(j+myhalf) *dx[1];const Real z=use_z_phys ? z_cc(i, j, k) :prob_lo[2]+(k+myhalf) *dx[2];amrex::Real L=zero;if(x_r > 0) L+=amrex::Math::powi< 2 >((x - x_c)/x_r);if(y_r > 0) L+=amrex::Math::powi< 2 >((y - y_c)/y_r);if(z_r > 0) L+=amrex::Math::powi< 2 >((z - z_c)/z_r);L=std::sqrt(L);if(L< one) { auto rho=state(i, j, k, Rho_comp)+state_pert(i, j, k, Rho_comp);for(int ns=0;ns< n_sp;ns++) { state_pert(i, j, k, nstart+2 *ns)=rho *qv_arr[ns];state_pert(i, j, k, nstart+2 *ns+1)=zero;} } })
const Real dz
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:60
AMREX_ALWAYS_ASSERT(sc.moisture_type==MoistureType::SuperDroplets)
const auto khi
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:59
Real qt_init
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:28
Real y_r
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:16
std::vector< std::string > m_species
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:31
Vector< Real > h_t(khi+2)
Gpu::DeviceVector< Real > d_t(khi+2)
Vector< Real > h_q_v(khi+2)
Gpu::DeviceVector< Real > d_p(khi+2)
Gpu::DeviceVector< Real > d_q_v(khi+2)
Vector< Real > h_r(khi+2)
Vector< Real > h_p(khi+2)
Gpu::DeviceVector< Real > d_r(khi+2)
constexpr amrex::Real two
Definition: ERF_NumericalConstants.H:38
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
constexpr amrex::Real PI
Definition: ERF_NumericalConstants.H:46
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE Real vapor_mixing_ratio(const Real p_b, const Real T_b, const Real RH, const bool use_empirical, int which_zone)
Definition: ERF_HSEUtils.H:475
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE void init_isentropic_hse_no_terrain(Real *theta, Real *r, Real *p, Real *q_v, const Real &dz, const Real &z_bot, const int &khi, const Real q_t, const Real eq_pot_temp, const bool use_empirical, const bool T_from_theta=false, const Real z_tr_1=-one, const Real z_tr_2=-one, const Real theta_0=amrex::Real(300), const Real theta_tr=amrex::Real(300), const Real T_tr=amrex::Real(300))
Definition: ERF_HSEUtils.H:769
@ rho
Definition: ERF_Kessler.H:25
@ ns
Definition: ERF_Morrison.H:50
@ T
Definition: ERF_IndexDefines.H:168