ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_InitCustomPert_Bubble.H
Go to the documentation of this file.
1  ParmParse pp_prob("prob");
2 
3  Real T_0 = amrex::Real(300.0); pp_prob.query("T_0", T_0);
4  Real x_c = zero; pp_prob.query("x_c", x_c);
5  Real y_c = zero; pp_prob.query("y_c", y_c);
6  Real z_c = zero; pp_prob.query("z_c", z_c);
7  Real x_r = zero; pp_prob.query("x_r", x_r);
8  Real y_r = zero; pp_prob.query("y_r", y_r);
9  Real z_r = zero; pp_prob.query("z_r", z_r);
10 
11  Real T_pert = -amrex::Real(15.0); pp_prob.query("T_pert", T_pert);
12 
13  bool T_pert_is_airtemp = true; pp_prob.query("T_pert_is_airtemp", T_pert_is_airtemp);
14  bool perturb_rho = true; pp_prob.query("perturb_rho", perturb_rho);
15 
16  bool do_moist_bubble = false; pp_prob.query("do_moist_bubble", do_moist_bubble);
17  do_moist_bubble &= (sc.moisture_type != MoistureType::None);
18 
19  Real theta_pert = two; pp_prob.query("theta_pert", theta_pert);
20 
21  const int khi = geomdata.Domain().bigEnd()[2];
22 
23  AMREX_ALWAYS_ASSERT(bx.length()[2] == khi+1);
24 
25  const Real dz = geomdata.CellSize()[2];
26  const Real rdOcp = sc.rdOcp;
27 
28  amrex::Print() << "Bubble delta T = " << T_pert << " K" << std::endl;
29  amrex::Print() << " centered at ("
30  << x_c << " " << y_c << " " << z_c << ")" << std::endl;
31  amrex::Print() << " with extent ("
32  << x_r << " " << y_r << " " << z_r << ")" << std::endl;
33 
34  if (T_0 <= 0)
35  {
36  amrex::Print() << "Ignoring T_0 = " << T_0
37  << ", background fields should have been initialized with erf.init_type"
38  << std::endl;
39  }
40 
41  Real qt_init = amrex::Real(0.02); pp_prob.query("qt_init", qt_init);
42 
43  Real eq_pot_temp = amrex::Real(320.0); pp_prob.query("eq_pot_temp",eq_pot_temp);
44 
45  bool use_empirical = false;
46  pp_prob.query("use_empircal_psat",use_empirical);
47 
48  if (do_moist_bubble) {
49  Vector<Real> h_r(khi+2);
50  Vector<Real> h_p(khi+2);
51  Vector<Real> h_t(khi+2);
52  Vector<Real> h_q_v(khi+2);
53 
54  Gpu::DeviceVector<Real> d_r(khi+2);
55  Gpu::DeviceVector<Real> d_p(khi+2);
56  Gpu::DeviceVector<Real> d_t(khi+2);
57  Gpu::DeviceVector<Real> d_q_v(khi+2);
58 
59  HSEutils::init_isentropic_hse_no_terrain(h_t.data(), h_r.data(),h_p.data(),h_q_v.data(),dz,khi,
61 
62  Gpu::copyAsync(Gpu::hostToDevice, h_r.begin(), h_r.end(), d_r.begin());
63  Gpu::copyAsync(Gpu::hostToDevice, h_p.begin(), h_p.end(), d_p.begin());
64  Gpu::copyAsync(Gpu::hostToDevice, h_t.begin(), h_t.end(), d_t.begin());
65  Gpu::copyAsync(Gpu::hostToDevice, h_q_v.begin(), h_q_v.end(), d_q_v.begin());
66 
67  Real* theta_back = d_t.data();
68  Real* p_back = d_p.data();
69  Real* q_v_back = d_q_v.data();
70 
71  int moisture_type = 1;
72 
73  if (sc.moisture_type == MoistureType::SAM) {
74  moisture_type = 1;
75  } else if (sc.moisture_type == MoistureType::SAM_NoIce ||
76  sc.moisture_type == MoistureType::SAM_NoPrecip_NoIce) {
77  moisture_type = 2;
78  }
79 
80  ParallelFor(bx, [=,zero_d=zero,one_d=one,tbgmin_d=tbgmin,a_bg_d=a_bg]
81  AMREX_GPU_DEVICE(int i, int j, int k)
82  {
83  // Geometry (note we must include these here to get the data on device)
84  const auto prob_lo = geomdata.ProbLo();
85  const auto dx = geomdata.CellSize();
86  const Real x = prob_lo[0] + (i + myhalf) * dx[0];
87  const Real y = prob_lo[1] + (j + myhalf) * dx[1];
88  const Real z = prob_lo[2] + (k + myhalf) * dx[2];
89 
90  Real rad, delta_theta, theta_total, rho, RH;
91 
92  // Introduce the warm bubble. Assume that the bubble is pressure matched with the background
93  rad = zero_d;
94  if (x_r > 0) rad += amrex::Math::powi<2>((x - x_c)/x_r);
95  if (y_r > 0) rad += amrex::Math::powi<2>((y - y_c)/y_r);
96  if (z_r > 0) rad += amrex::Math::powi<2>((z - z_c)/z_r);
97  rad = std::sqrt(rad);
98 
99  if (rad <= amrex::Real(1)) {
100  delta_theta = theta_pert*amrex::Math::powi<2>(std::cos(PI*rad/two));
101  } else {
102  delta_theta = zero;
103  }
104 
105  theta_total = theta_back[k]*(delta_theta/amrex::Real(300.0) + 1);
107  rho = p_back[k]/(R_d*T*(one + RvoRd*q_v_back[k]));
110 
111  // Compute background quantities
112  Real T_back = getTgivenPandTh(p_back[k], theta_back[k], RdoCp);
113  Real rho_back = p_back[k]/(R_d*T_back*(one + RvoRd*q_v_back[k]));
114 
115  // This version perturbs rho but not p
116  state_pert(i, j, k, RhoTheta_comp) = rho*theta_total - rho_back*theta_back[k]*(one + RvoRd*q_v_back[k]);
118 
119  // Set scalar = 0 everywhere
121 
122  // mean states
125 
126  // Cold microphysics are present
127  int nstate = state_pert.nComp();
128  if (nstate == NVAR_max) {
129  Real omn;
130  if(moisture_type == 1) {
131  omn = std::max(zero_d,std::min(one_d,(T-tbgmin_d)*a_bg_d));
132  } else if(moisture_type == 2) {
133  omn = one;
134  } else {
135  omn = zero;
136  Abort("Invalid moisture type specified");
137  }
138  Real qn = state_pert(i, j, k, RhoQ2_comp);
139  state_pert(i, j, k, RhoQ2_comp) = qn * omn;
140  state_pert(i, j, k, RhoQ3_comp) = qn * (one - omn);
141  }
142  });
143  } else {
144  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
145  {
146  // Geometry (note we must include these here to get the data on device)
147  const auto prob_lo = geomdata.ProbLo();
148  const auto dx = geomdata.CellSize();
149 
150  const Real x = prob_lo[0] + (i + myhalf) * dx[0];
151  const Real y = prob_lo[1] + (j + myhalf) * dx[1];
152  const Real z = prob_lo[2] + (k + myhalf) * dx[2];
153 
154  //perturb_rho_theta(x, y, z, p_hse(i,j,k), r_hse(i,j,k), rdOcp,
155  // state_pert(i, j, k, Rho_comp),
156  // state_pert(i, j, k, RhoTheta_comp));
157 
158  // Perturbation air temperature
159  // - The bubble is either cylindrical (for 2-D problems, if two
160  // radial extents are specified) or an ellipsoid (if all three
161  // radial extents are specified).
162  Real L = zero;
163  if (x_r > 0) L += amrex::Math::powi<2>((x - x_c)/x_r);
164  if (y_r > 0) L += amrex::Math::powi<2>((y - y_c)/y_r);
165  if (z_r > 0) L += amrex::Math::powi<2>((z - z_c)/z_r);
166  L = std::sqrt(L);
167  Real dT;
168  if (L > amrex::Real(1)) {
169  dT = zero;
170  } else {
171  dT = T_pert * amrex::Math::powi<2>(std::cos(PI*L/two));
172  }
173 
174  // Temperature that satisfies the EOS given the hydrostatically balanced (r,p)
175  const Real Tbar_hse = p_hse(i,j,k) / (R_d * r_hse(i,j,k));
176 
177  // Note: theta_perturbed is theta PLUS perturbation in theta
178  Real theta_perturbed;
179  if (T_pert_is_airtemp) {
180  // dT is air temperature
181  theta_perturbed = (Tbar_hse + dT)*std::pow(p_0/p_hse(i,j,k), rdOcp);
182  } else {
183  // dT is potential temperature
184  theta_perturbed = Tbar_hse*std::pow(p_0/p_hse(i,j,k), rdOcp) + dT;
185  }
186 
187  if (perturb_rho)
188  {
189  // this version perturbs rho but not p (i.e., rho*theta)
190  // - hydrostatic rebalance is needed (TODO: is this true?)
191  // - this is the approach taken in the density current problem
192  state_pert(i,j,k,Rho_comp) = getRhoThetagivenP(p_hse(i,j,k)) / theta_perturbed - r_hse(i,j,k);
193  state_pert(i,j,k,RhoTheta_comp) = zero; // i.e., hydrostatically balanced pressure stays const
194  }
195  else
196  {
197  // this version perturbs rho*theta (i.e., p) but not rho
198  state_pert(i,j,k,Rho_comp) = zero; // i.e., hydrostatically balanced density stays const
199  state_pert(i,j,k,RhoTheta_comp) = r_hse(i,j,k) * theta_perturbed - getRhoThetagivenP(p_hse(i,j,k));
200  }
201  });
202  } // do_moist_bubble
constexpr amrex::Real a_bg
Definition: ERF_Constants.H:120
constexpr amrex::Real two
Definition: ERF_Constants.H:10
constexpr amrex::Real one
Definition: ERF_Constants.H:9
constexpr amrex::Real zero
Definition: ERF_Constants.H:8
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:13
constexpr amrex::Real PI
Definition: ERF_Constants.H:42
constexpr amrex::Real p_0
Definition: ERF_Constants.H:61
constexpr amrex::Real RvoRd
Definition: ERF_Constants.H:56
constexpr amrex::Real tbgmin
Definition: ERF_Constants.H:74
constexpr amrex::Real R_d
Definition: ERF_Constants.H:47
constexpr amrex::Real RdoCp
Definition: ERF_Constants.H:54
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 RhoScalar_comp
Definition: ERF_IndexDefines.H:40
#define Rho_comp
Definition: ERF_IndexDefines.H:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:43
#define NVAR_max
Definition: ERF_IndexDefines.H:24
#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
const int khi
Definition: ERF_InitCustomPert_Bubble.H:21
state_pert(i, j, k, RhoTheta_comp)
Real T_back
Definition: ERF_InitCustomPert_Bubble.H:112
Real z_c
Definition: ERF_InitCustomPert_Bubble.H:6
Real rho_back
Definition: ERF_InitCustomPert_Bubble.H:113
bool T_pert_is_airtemp
Definition: ERF_InitCustomPert_Bubble.H:13
Real x_r
Definition: ERF_InitCustomPert_Bubble.H:7
bool do_moist_bubble
Definition: ERF_InitCustomPert_Bubble.H:16
const Real rdOcp
Definition: ERF_InitCustomPert_Bubble.H:26
Real x_c
Definition: ERF_InitCustomPert_Bubble.H:4
ParmParse pp_prob("prob")
Real T
Definition: ERF_InitCustomPert_Bubble.H:106
background fields should have been initialized with erf init_type<< std::endl;} Real qt_init=amrex::Real(0.02);pp_prob.query("qt_init", qt_init);Real eq_pot_temp=amrex::Real(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,[=, zero_d=zero, one_d=one, tbgmin_d=tbgmin, a_bg_d=a_bg] 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+myhalf) *dx[0];const Real y=prob_lo[1]+(j+myhalf) *dx[1];const Real z=prob_lo[2]+(k+myhalf) *dx[2];Real rad, delta_theta, theta_total, rho, RH;rad=zero_d;if(x_r > rad
Definition: ERF_InitCustomPert_Bubble.H:94
do_moist_bubble &Real theta_pert
Definition: ERF_InitCustomPert_Bubble.H:19
Real q_v_hot
Definition: ERF_InitCustomPert_Bubble.H:109
theta_total
Definition: ERF_InitCustomPert_Bubble.H:105
Real T_0
Definition: ERF_InitCustomPert_Bubble.H:3
Real z_r
Definition: ERF_InitCustomPert_Bubble.H:9
Real y_c
Definition: ERF_InitCustomPert_Bubble.H:5
bool perturb_rho
Definition: ERF_InitCustomPert_Bubble.H:14
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
RH
Definition: ERF_InitCustomPert_Bubble.H:108
Real T_pert
Definition: ERF_InitCustomPert_Bubble.H:11
rho
Definition: ERF_InitCustomPert_Bubble.H:107
const Real dz
Definition: ERF_InitCustomPert_Bubble.H:25
Real y_r
Definition: ERF_InitCustomPert_Bubble.H:8
int nstate
Definition: ERF_InitCustomPert_Bubble.H:127
const amrex::Real * prob_lo
Definition: ERF_InitCustomPert_DataAssimilation_ISV.H:16
Real eq_pot_temp
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:23
bool use_empirical
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:25
Real qt_init
Definition: ERF_InitCustomPert_MultiSpeciesBubble.H:24
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)
ParallelFor(grown_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);})
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:449
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=-one, const Real z_tr_2=-one, const Real theta_0=amrex::Real(0), const Real theta_tr=amrex::Real(0), const Real T_tr=amrex::Real(0))
Definition: ERF_HSEUtils.H:626
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE Real compute_relative_humidity(const Real p_b, const Real T_b, const bool use_empirical, const int which_zone, const Real scaled_height)
Definition: ERF_HSEUtils.H:429
@ qn
Definition: ERF_Morrison.H:34