ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_InitCustomPert_CloudChamber.H
Go to the documentation of this file.
1 // Cloud Chamber Stage 1 initializer.
2 //
3 // ERF has already initialized the hydrostatic/base state when this snippet is
4 // called. `state` is therefore the current conserved state and state_pert is
5 // an additive correction. In anelastic mode density is fixed by that base
6 // state, so only RhoTheta and (for SatAdj) RhoQ1/RhoQ2 are corrected here.
7 // The analytic perturbation is evaluated at cell centers and uses no RNG;
8 // consequently it is independent of MPI decomposition, tiling, and restart
9 // layout. theta is potential temperature, qv is vapor mixing ratio, and qc
10 // is SatAdj cloud-water mixing ratio; none of these prescribed values claim
11 // physical panel temperature, wet-wall evaporation, or a wall-transfer law.
13  m_cloud_chamber_config.active,
14  "Cloud Chamber: initializer reached without a parsed configuration");
16  sc.anelastic[lev] == 1 && sc.fixed_density[lev] == 1,
17  "Cloud Chamber: the selected level must use fixed-density anelastic dynamics");
19  sc.terrain_type == TerrainType::None &&
20  sc.buildings_type == BuildingsType::None &&
21  sc.mesh_type == MeshType::ConstantDz,
22  "Cloud Chamber: terrain, buildings, and non-Cartesian mesh modes are unsupported");
23 if (m_cloud_chamber_config.cloudy) {
25  sc.moisture_type == MoistureType::SatAdj,
26  "Cloud Chamber: cloudy mode requires erf.moisture_model = SatAdj");
27 } else {
29  sc.moisture_type == MoistureType::None,
30  "Cloud Chamber: dry mode requires no active moisture model");
31 }
32 
33 const GpuArray<Real, AMREX_SPACEDIM> prob_lo = {
34  geomdata.ProbLo(0), geomdata.ProbLo(1), geomdata.ProbLo(2)};
35 const GpuArray<Real, AMREX_SPACEDIM> dx = {
36  geomdata.CellSize(0), geomdata.CellSize(1), geomdata.CellSize(2)};
37 const auto config = m_cloud_chamber_config;
38 const Real rdOcp = sc.rdOcp;
39 
40 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
41 {
42  const Real x = prob_lo[0] + (Real(i) + Real(0.5)) * dx[0];
43  const Real y = prob_lo[1] + (Real(j) + Real(0.5)) * dx[1];
44  const Real z = prob_lo[2] + (Real(k) + Real(0.5)) * dx[2];
45  const Real rho = state(i,j,k,Rho_comp);
46  const Real temperature = erf_cloud_chamber::linear_profile(
47  config.initial_temperature_bottom, config.initial_temperature_top,
48  z, config.prob_lo[2], config.prob_hi[2] - config.prob_lo[2]) +
50  x, y, z, config.prob_lo,
51  GpuArray<Real, AMREX_SPACEDIM>{
52  config.prob_hi[0] - config.prob_lo[0],
53  config.prob_hi[1] - config.prob_lo[1],
54  config.prob_hi[2] - config.prob_lo[2]},
55  config.temperature_perturbation_amplitude);
56  const Real target_theta = config.physical_initialization ?
57  temperature * std::pow(p_0 / p_hse(i,j,k), rdOcp) :
59  state_pert(i,j,k,RhoTheta_comp) =
60  rho * target_theta - state(i,j,k,RhoTheta_comp);
61 
62  if (config.cloudy) {
63  const Real target_qv = config.physical_initialization ?
65  temperature, p_hse(i,j,k), config.initial_relative_humidity) :
67  state_pert(i,j,k,RhoQ1_comp) =
68  rho * target_qv - state(i,j,k,RhoQ1_comp);
69  // SatAdj owns the first adjustment of cloud water. Starting from
70  // zero makes that source explicit instead of carrying stale state.
71  state_pert(i,j,k,RhoQ2_comp) = -state(i,j,k,RhoQ2_comp);
72  }
73 });
constexpr amrex::Real p_0
Definition: ERF_Constants.H:61
#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 RhoQ1_comp
Definition: ERF_IndexDefines.H:42
state_pert(i, j, k, RhoTheta_comp)
rho
Definition: ERF_InitCustomPert_Bubble.H:107
const GpuArray< Real, AMREX_SPACEDIM > dx
Definition: ERF_InitCustomPert_CloudChamber.H:35
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_cloud_chamber_config.active, "Cloud Chamber: initializer reached without a parsed configuration")
const Real rdOcp
Definition: ERF_InitCustomPert_CloudChamber.H:38
ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept { const Real x=prob_lo[0]+(Real(i)+Real(0.5)) *dx[0];const Real y=prob_lo[1]+(Real(j)+Real(0.5)) *dx[1];const Real z=prob_lo[2]+(Real(k)+Real(0.5)) *dx[2];const Real rho=state(i, j, k, Rho_comp);const Real temperature=erf_cloud_chamber::linear_profile(config.initial_temperature_bottom, config.initial_temperature_top, z, config.prob_lo[2], config.prob_hi[2] - config.prob_lo[2])+erf_cloud_chamber::deterministic_perturbation(x, y, z, config.prob_lo, GpuArray< Real, AMREX_SPACEDIM >{ config.prob_hi[0] - config.prob_lo[0], config.prob_hi[1] - config.prob_lo[1], config.prob_hi[2] - config.prob_lo[2]}, config.temperature_perturbation_amplitude);const Real target_theta=config.physical_initialization ? temperature *std::pow(p_0/p_hse(i, j, k), rdOcp) :erf_cloud_chamber::theta_at(config, x, y, z);state_pert(i, j, k, RhoTheta_comp)=rho *target_theta - state(i, j, k, RhoTheta_comp);if(config.cloudy) { const Real target_qv=config.physical_initialization ? erf_cloud_chamber::vapor_mixing_ratio_from_relative_humidity(temperature, p_hse(i, j, k), config.initial_relative_humidity) :erf_cloud_chamber::qv_at(config, z);state_pert(i, j, k, RhoQ1_comp)=rho *target_qv - state(i, j, k, RhoQ1_comp);state_pert(i, j, k, RhoQ2_comp)=-state(i, j, k, RhoQ2_comp);} })
const auto config
Definition: ERF_InitCustomPert_CloudChamber.H:37
const GpuArray< Real, AMREX_SPACEDIM > prob_lo
Definition: ERF_InitCustomPert_CloudChamber.H:33
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE amrex::Real deterministic_perturbation(amrex::Real x, amrex::Real y, amrex::Real z, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &lo, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &length, amrex::Real amplitude) noexcept
Definition: ERF_CloudChamber.H:114
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE amrex::Real qv_at(const Config &config, amrex::Real z) noexcept
Definition: ERF_CloudChamber.H:151
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE amrex::Real vapor_mixing_ratio_from_relative_humidity(amrex::Real temperature_K, amrex::Real pressure_Pa, amrex::Real relative_humidity) noexcept
Definition: ERF_CloudChamber.H:161
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE amrex::Real theta_at(const Config &config, amrex::Real x, amrex::Real y, amrex::Real z) noexcept
Definition: ERF_CloudChamber.H:129
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE amrex::Real linear_profile(amrex::Real bottom, amrex::Real top, amrex::Real coordinate, amrex::Real lower, amrex::Real length) noexcept
Definition: ERF_CloudChamber.H:104