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