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