ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_InitCustomPert_SquallLine.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  const bool use_moisture = (sc.moisture_type != MoistureType::None);
7 
8  const int khi = geomdata.Domain().bigEnd()[2];
9 
10  AMREX_ALWAYS_ASSERT(bx.length()[2] == khi+1);
11 
12  // This is what we do at k = 0 -- note we assume p = p_0 and T = T_0 at z=0
13  const Real& dz = geomdata.CellSize()[2];
14 
15  // Call the routine to calculate the 1d background condition
16 
17  Vector<Real> h_r(khi+2);
18  Vector<Real> h_p(khi+2);
19  Vector<Real> h_t(khi+2);
20  Vector<Real> h_q_v(khi+2);
21 
22  Gpu::DeviceVector<Real> d_r(khi+2);
23  Gpu::DeviceVector<Real> d_p(khi+2);
24  Gpu::DeviceVector<Real> d_t(khi+2);
25  Gpu::DeviceVector<Real> d_q_v(khi+2);
26 
27  ParmParse pp_prob("prob");
28  Real q_t = amrex::Real(0.02);
29  pp_prob.query("qt_init",q_t);
30 
32  pp_prob.query("eq_pot_temp",eq_pot_temp);
33 
34  bool use_empirical = false;
35  pp_prob.query("use_empirical_psat",use_empirical);
36 
37  Real height = amrex::Real(1200.0);
38  pp_prob.query("height",height);
39 
40  Real z_tr = amrex::Real(12000.0);
41  pp_prob.query("z_tr",z_tr);
42 
43  Real x_c = zero ; pp_prob.query("x_c", x_c);
44  Real z_c = amrex::Real(1.5e3); pp_prob.query("z_c", z_c);
45  Real x_r = amrex::Real(4.0e3); pp_prob.query("x_r", x_r);
46  Real z_r = amrex::Real(1.5e3); pp_prob.query("z_r", z_r);
47  Real T_tr = amrex::Real(213.0); pp_prob.query("T_tr", T_tr);
48  Real theta_c = three; pp_prob.query("theta_c", theta_c);
49 
50  Real theta_0 = amrex::Real(300.0); pp_prob.query("theta_0", theta_0);
51  Real theta_tr = amrex::Real(343.0); pp_prob.query("theta_tr", theta_tr);
52 
54 
55  if (use_z_phys) {
56  HSEutils::init_isentropic_hse_no_terrain(h_t.data(), h_r.data(),h_p.data(),h_q_v.data(),m_zlevels_stag[lev].data(),khi,
59  } else {
60  HSEutils::init_isentropic_hse_no_terrain(h_t.data(), h_r.data(),h_p.data(),h_q_v.data(),dz,geomdata.ProbLo(2),khi,
63  }
64 
65  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, h_r.begin(), h_r.end(), d_r.begin());
66  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, h_p.begin(), h_p.end(), d_p.begin());
67  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, h_t.begin(), h_t.end(), d_t.begin());
68  amrex::Gpu::copyAsync(amrex::Gpu::hostToDevice, h_q_v.begin(), h_q_v.end(), d_q_v.begin());
69 
70  Real* t = d_t.data();
71  Real* p = d_p.data();
72 
73  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
74  {
75  // Geometry (note we must include these here to get the data on device)
76  const auto prob_lo = geomdata.ProbLo();
77  const auto dx = geomdata.CellSize();
78  const Real z = use_z_phys ? z_cc(i,j,k) : prob_lo[2] + (k + myhalf) * dx[2];
79  // The humidity zones (height, z_tr) are heights above the ground, as in the profile
80  // from init_isentropic_hse_no_terrain; the bubble centre z_c is a coordinate, like x_c
81  const Real z_agl = z - erf_prob_heights::z_ground_cc(i,j,z_sfc_nd);
82  const Real x = prob_lo[0] + (i + myhalf) * dx[0];
83  Real rad, delta_theta, theta_total, temperature, rho, RH, scalar;
84 
85  Real scaled_height = z_agl / z_tr;
86  int which_zone = -1;
87  if (z_agl <= height) {
88  which_zone = 1;
89  } else if (z_agl <= z_tr) {
90  which_zone = 2;
91  } else {
92  which_zone = 3;
93  }
94 
95  // Introduce the warm bubble. Assume that the bubble is pressure matche with the background
96  rad = std::sqrt( amrex::Math::powi<2>((x - x_c)/x_r) +
97  amrex::Math::powi<2>((z - z_c)/z_r) );
98 
99  if(rad <= r_c){
100  delta_theta = theta_c*amrex::Math::powi<2>(std::cos(PI*rad/two));
101  scalar = amrex::Math::powi<2>(std::cos(PI*rad/two));
102  }
103  else{
104  delta_theta = zero;
105  scalar = zero;
106  }
107 
108  theta_total = t[k] + delta_theta;
109 
110  temperature = getTgivenPandTh(p[k], theta_total, RdoCp);
111  Real T_b = getTgivenPandTh(p[k], t[k] , RdoCp);
112 
113  RH = HSEutils::compute_relative_humidity(p[k], T_b, use_empirical, which_zone, scaled_height);
114 
115  Real q_v_hot;
116  if (z_agl < height) {
117  q_v_hot = amrex::Real(0.014);
118  } else {
119  q_v_hot = HSEutils::vapor_mixing_ratio(p[k], T_b, RH, use_empirical, which_zone);
120  }
121 
122  rho = p[k]/(R_d*temperature*(one + RvoRd*q_v_hot));
123 
124  // Compute background quantities
125  Real temperature_back = getTgivenPandTh(p[k], t[k], RdoCp);
126  Real T_back = getTgivenPandTh(p[k], t[k], RdoCp);
127 
128  Real RH_back = HSEutils::compute_relative_humidity(p[k], T_back, use_empirical, which_zone, scaled_height);
129 
130  Real q_v_back;
131  if (z_agl < height) {
132  q_v_back = amrex::Real(0.014);
133  } else {
134  q_v_back = HSEutils::vapor_mixing_ratio(p[k], T_back, RH_back, use_empirical, which_zone);
135  }
136  Real rho_back = p[k]/(R_d*temperature_back*(one + RvoRd*q_v_back));
137 
138  // This version perturbs rho but not p
139  state_pert(i, j, k, RhoTheta_comp) = rho*theta_total - rho_back*t[k]*(one + RvoRd*q_v_back);// rho*d_t[k]*(one + R_v_by_R_d*q_v_hot);
140  state_pert(i, j, k, Rho_comp) = rho - rho_back*(one + q_v_back);
141 
142  // Set scalar = 0 everywhere
143  state_pert(i, j, k, RhoScalar_comp) = rho*scalar;
144 
145  // mean states
146  if (use_moisture) {
147  state_pert(i, j, k, RhoQ1_comp) = rho*q_v_hot;
148  state_pert(i, j, k, RhoQ2_comp) = zero;
149  }
150 
151  });
152 
153  // The kernel above reads d_r, d_p, d_t and d_q_v; wait for it before they are freed
154  Gpu::streamSynchronize();
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 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:57
#define Rho_comp
Definition: ERF_IndexDefines.H:53
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:54
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:67
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:66
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_SquallLine.H:4
Vector< Real > h_t(khi+2)
Gpu::DeviceVector< Real > d_t(khi+2)
const int khi
Definition: ERF_InitCustomPert_SquallLine.H:8
Real T_tr
Definition: ERF_InitCustomPert_SquallLine.H:47
Real z_c
Definition: ERF_InitCustomPert_SquallLine.H:44
const bool use_moisture
Definition: ERF_InitCustomPert_SquallLine.H:6
Real x_r
Definition: ERF_InitCustomPert_SquallLine.H:45
Real x_c
Definition: ERF_InitCustomPert_SquallLine.H:43
ParmParse pp_prob("prob")
Real q_t
Definition: ERF_InitCustomPert_SquallLine.H:28
Real theta_c
Definition: ERF_InitCustomPert_SquallLine.H:48
const Real & dz
Definition: ERF_InitCustomPert_SquallLine.H:13
Real * t
Definition: ERF_InitCustomPert_SquallLine.H:70
Vector< Real > h_q_v(khi+2)
Real z_r
Definition: ERF_InitCustomPert_SquallLine.H:46
Gpu::DeviceVector< Real > d_p(khi+2)
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 z=use_z_phys ? z_cc(i, j, k) :prob_lo[2]+(k+myhalf) *dx[2];const Real z_agl=z - erf_prob_heights::z_ground_cc(i, j, z_sfc_nd);const Real x=prob_lo[0]+(i+myhalf) *dx[0];Real rad, delta_theta, theta_total, temperature, rho, RH, scalar;Real scaled_height=z_agl/z_tr;int which_zone=-1;if(z_agl<=height) { which_zone=1;} else if(z_agl<=z_tr) { which_zone=2;} else { which_zone=3;} rad=std::sqrt(amrex::Math::powi< 2 >((x - x_c)/x_r)+amrex::Math::powi< 2 >((z - z_c)/z_r));if(rad<=r_c){ delta_theta=theta_c *amrex::Math::powi< 2 >(std::cos(PI *rad/two));scalar=amrex::Math::powi< 2 >(std::cos(PI *rad/two));} else{ delta_theta=zero;scalar=zero;} theta_total=t[k]+delta_theta;temperature=getTgivenPandTh(p[k], theta_total, RdoCp);Real T_b=getTgivenPandTh(p[k], t[k], RdoCp);RH=HSEutils::compute_relative_humidity(p[k], T_b, use_empirical, which_zone, scaled_height);Real q_v_hot;if(z_agl< height) { q_v_hot=amrex::Real(0.014);} else { q_v_hot=HSEutils::vapor_mixing_ratio(p[k], T_b, RH, use_empirical, which_zone);} rho=p[k]/(R_d *temperature *(one+RvoRd *q_v_hot));Real temperature_back=getTgivenPandTh(p[k], t[k], RdoCp);Real T_back=getTgivenPandTh(p[k], t[k], RdoCp);Real RH_back=HSEutils::compute_relative_humidity(p[k], T_back, use_empirical, which_zone, scaled_height);Real q_v_back;if(z_agl< height) { q_v_back=amrex::Real(0.014);} else { q_v_back=HSEutils::vapor_mixing_ratio(p[k], T_back, RH_back, use_empirical, which_zone);} Real rho_back=p[k]/(R_d *temperature_back *(one+RvoRd *q_v_back));state_pert(i, j, k, RhoTheta_comp)=rho *theta_total - rho_back *t[k] *(one+RvoRd *q_v_back);state_pert(i, j, k, Rho_comp)=rho - rho_back *(one+q_v_back);state_pert(i, j, k, RhoScalar_comp)=rho *scalar;if(use_moisture) { state_pert(i, j, k, RhoQ1_comp)=rho *q_v_hot;state_pert(i, j, k, RhoQ2_comp)=zero;} })
Real height
Definition: ERF_InitCustomPert_SquallLine.H:37
Gpu::DeviceVector< Real > d_q_v(khi+2)
Real eq_pot_temp
Definition: ERF_InitCustomPert_SquallLine.H:31
bool use_empirical
Definition: ERF_InitCustomPert_SquallLine.H:34
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
Real r_c
Definition: ERF_InitCustomPert_SquallLine.H:53
Vector< Real > h_r(khi+2)
Real theta_tr
Definition: ERF_InitCustomPert_SquallLine.H:51
Vector< Real > h_p(khi+2)
Gpu::DeviceVector< Real > d_r(khi+2)
Real theta_0
Definition: ERF_InitCustomPert_SquallLine.H:50
Real z_tr
Definition: ERF_InitCustomPert_SquallLine.H:40
Real * p
Definition: ERF_InitCustomPert_SquallLine.H:71
constexpr amrex::Real three
Definition: ERF_NumericalConstants.H:39
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 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:455
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
@ None
Definition: ERF_LSM_Types.H:6
@ rho
Definition: ERF_Kessler.H:25
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real z_ground_cc(int i, int j, amrex::Array4< amrex::Real const > const &z_sfc_nd) noexcept
Definition: ERF_ProbHeights.H:49