ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_ShocEnergyFixer.H
Go to the documentation of this file.
1 #ifndef ERF_SHOC_ENERGY_FIXER_H_
2 #define ERF_SHOC_ENERGY_FIXER_H_
3 
4 #include "ERF_ShocColumnData.H"
5 #include "ERF_ShocConstants.H"
6 #include "ERF_ShocThermoUtils.H"
7 
8 #include "ERF_Constants.H"
9 
10 namespace shoc {
11 
13 {
14  amrex::Array4<const amrex::Real> rho;
15  amrex::Array4<const amrex::Real> dz;
16  amrex::Array4<const amrex::Real> zt;
17  amrex::Array4<const amrex::Real> exner;
18  amrex::Array4<const amrex::Real> surf_sens_flux;
19  amrex::Array4<const amrex::Real> surf_lat_flux;
20 
21  amrex::Array4<const amrex::Real> thetal_base;
22  amrex::Array4<const amrex::Real> qv_base;
23  amrex::Array4<const amrex::Real> qc_base;
24  amrex::Array4<const amrex::Real> qi_base;
25  amrex::Array4<const amrex::Real> u_base;
26  amrex::Array4<const amrex::Real> v_base;
27  amrex::Array4<const amrex::Real> tke_base;
28 
29  amrex::Array4<amrex::Real> thetal;
30  amrex::Array4<const amrex::Real> qw;
31  amrex::Array4<const amrex::Real> u;
32  amrex::Array4<const amrex::Real> v;
33  amrex::Array4<const amrex::Real> tke;
34  amrex::Array4<const amrex::Real> shoc_ql;
35 
36  int nlev = 0;
38 };
39 
42  bool include_momentum_energy)
43 {
44  return {
45  col.rho.const_array(),
46  col.dz.const_array(),
47  col.zt.const_array(),
48  col.exner.const_array(),
49  col.surf_sens_flux.const_array(),
50  col.surf_lat_flux.const_array(),
51  col.thetal_base.const_array(),
52  col.qv_base.const_array(),
53  col.qc_base.const_array(),
54  col.qi_base.const_array(),
55  col.u_base.const_array(),
56  col.v_base.const_array(),
57  col.tke_base_state.const_array(),
58  col.thetal.array(),
59  col.qw.const_array(),
60  col.u.const_array(),
61  col.v.const_array(),
62  col.tke.const_array(),
63  col.shoc_ql.const_array(),
64  col.layout.nlev,
65  include_momentum_energy
66  };
67 }
68 
69 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
70 int
71 diagnose_active_top (const amrex::Array4<const amrex::Real>& tke,
72  int ic,
73  int nlev) noexcept
74 {
75  int shoc_top = -1;
76  for (int k = nlev - 1; k >= 0; --k) {
77  if (tke(ic,k,0) > constants::active_tke_threshold()) {
78  shoc_top = k;
79  break;
80  }
81  }
82  return shoc_top;
83 }
84 
85 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
86 void
88  int ic,
89  double dt_d) noexcept
90 {
91  amrex::Real dt = static_cast<amrex::Real>(dt_d);
92 
93  const int shoc_top = diagnose_active_top(v.tke, ic, v.nlev);
94  if (shoc_top < 0) {
95  return;
96  }
97 
98  amrex::Real energy_before = amrex::Real(0.0);
99  amrex::Real energy_after = amrex::Real(0.0);
100  amrex::Real air_mass = amrex::Real(0.0);
101 
102  for (int k = 0; k <= shoc_top; ++k) {
103  const amrex::Real mass = v.rho(ic,k,0) * v.dz(ic,k,0);
104  const amrex::Real tabs_old = shoc::temperature_from_thetal(v.thetal_base(ic,k,0),
105  v.qc_base(ic,k,0),
106  v.qi_base(ic,k,0),
107  v.exner(ic,k,0));
108 
109  amrex::Real tabs_new = amrex::Real(0.0);
110  amrex::Real qv_new = amrex::Real(0.0);
111  amrex::Real qc_new = amrex::Real(0.0);
112  amrex::Real qi_new = amrex::Real(0.0);
113  shoc::reconstruct_pdf_state(v.thetal(ic,k,0), v.qw(ic,k,0), v.exner(ic,k,0),
114  v.qi_base(ic,k,0), v.shoc_ql(ic,k,0),
115  tabs_new, qv_new, qc_new, qi_new);
116 
117  energy_before += mass * moist_energy(tabs_old, v.zt(ic,k,0),
118  v.qv_base(ic,k,0), v.qc_base(ic,k,0), v.qi_base(ic,k,0),
119  v.u_base(ic,k,0), v.v_base(ic,k,0), v.tke_base(ic,k,0));
120  const amrex::Real u_after = v.include_momentum_energy
121  ? v.u(ic,k,0) : v.u_base(ic,k,0);
122  const amrex::Real v_after = v.include_momentum_energy
123  ? v.v(ic,k,0) : v.v_base(ic,k,0);
124  energy_after += mass * moist_energy(tabs_new, v.zt(ic,k,0),
125  qv_new, qc_new, qi_new,
126  u_after, v_after, v.tke(ic,k,0));
127  air_mass += mass;
128  }
129 
130  if (air_mass <= amrex::Real(0.0)) {
131  return;
132  }
133 
134  const amrex::Real latent_flux_coeff = L_v + constants::latent_ice();
135  const amrex::Real energy_target = energy_before
136  + dt * v.rho(ic,0,0)
137  * (Cp_d * v.exner(ic,0,0) * v.surf_sens_flux(ic,0,0)
138  + latent_flux_coeff * v.surf_lat_flux(ic,0,0));
139  const amrex::Real delta_tabs = (energy_target - energy_after) / (Cp_d * air_mass);
140 
141  for (int k = 0; k <= shoc_top; ++k) {
142  v.thetal(ic,k,0) += delta_tabs / amrex::max(v.exner(ic,k,0), amrex::Real(1.0e-12));
143  }
144 }
145 
146 } // namespace shoc
147 
149 {
150 public:
151  static int diagnose_active_top (const amrex::Vector<amrex::Real>& tke);
152 
153  AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
154  static int diagnose_active_top (const amrex::Array4<const amrex::Real>& tke,
155  int ic,
156  int nlev) noexcept
157  {
158  return shoc::diagnose_active_top(tke, ic, nlev);
159  }
160 
161  // Host-only wrapper: col's FArrayBoxes and all vectors must be host-accessible.
162  // Device-owned column data must be staged before calling this routine.
163  static void apply_column (const ShocColumnData& col,
164  int ic,
165  double dt,
166  const amrex::Vector<amrex::Real>& thl_old,
167  const amrex::Vector<amrex::Real>& qv_old,
168  const amrex::Vector<amrex::Real>& qc_old,
169  const amrex::Vector<amrex::Real>& qi_old,
170  const amrex::Vector<amrex::Real>& u_old,
171  const amrex::Vector<amrex::Real>& v_old,
172  const amrex::Vector<amrex::Real>& tke_old,
173  amrex::Vector<amrex::Real>& thl_new,
174  const amrex::Vector<amrex::Real>& qv_new,
175  const amrex::Vector<amrex::Real>& qc_new,
176  const amrex::Vector<amrex::Real>& qi_new,
177  const amrex::Vector<amrex::Real>& u_new,
178  const amrex::Vector<amrex::Real>& v_new,
179  const amrex::Vector<amrex::Real>& tke_new);
180 };
181 
182 #endif
constexpr amrex::Real Cp_d
Definition: ERF_Constants.H:36
constexpr amrex::Real L_v
Definition: ERF_Constants.H:51
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_ShocEnergyFixer.H:149
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE int diagnose_active_top(const amrex::Array4< const amrex::Real > &tke, int ic, int nlev) noexcept
Definition: ERF_ShocEnergyFixer.H:154
static void apply_column(const ShocColumnData &col, int ic, double dt, const amrex::Vector< amrex::Real > &thl_old, const amrex::Vector< amrex::Real > &qv_old, const amrex::Vector< amrex::Real > &qc_old, const amrex::Vector< amrex::Real > &qi_old, const amrex::Vector< amrex::Real > &u_old, const amrex::Vector< amrex::Real > &v_old, const amrex::Vector< amrex::Real > &tke_old, amrex::Vector< amrex::Real > &thl_new, const amrex::Vector< amrex::Real > &qv_new, const amrex::Vector< amrex::Real > &qc_new, const amrex::Vector< amrex::Real > &qi_new, const amrex::Vector< amrex::Real > &u_new, const amrex::Vector< amrex::Real > &v_new, const amrex::Vector< amrex::Real > &tke_new)
Definition: ERF_ShocEnergyFixer.cpp:19
static int diagnose_active_top(const amrex::Vector< amrex::Real > &tke)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real latent_ice() noexcept
Definition: ERF_ShocConstants.H:38
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real active_tke_threshold() noexcept
Definition: ERF_ShocConstants.H:32
Definition: ERF_ShocConstants.H:7
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int diagnose_active_top(const amrex::Array4< const amrex::Real > &tke, int ic, int nlev) noexcept
Definition: ERF_ShocEnergyFixer.H:71
ShocEnergyFixerView make_energy_fixer_view(ShocColumnData &col, bool include_momentum_energy)
Definition: ERF_ShocEnergyFixer.H:41
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void reconstruct_pdf_state(amrex::Real thetal, amrex::Real qw, amrex::Real exner, amrex::Real qi_seed, amrex::Real pdf_ql, amrex::Real &tabs, amrex::Real &qv, amrex::Real &qc, amrex::Real &qi) noexcept
Definition: ERF_ShocThermoUtils.H:86
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real moist_energy(amrex::Real tabs, amrex::Real z, amrex::Real qv, amrex::Real qc, amrex::Real qi, amrex::Real u, amrex::Real v, amrex::Real tke) noexcept
Definition: ERF_ShocThermoUtils.H:64
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real temperature_from_thetal(amrex::Real thetal, amrex::Real qc, amrex::Real qi, amrex::Real exner) noexcept
Definition: ERF_ShocThermoUtils.H:40
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void apply_energy_fix_column(const ShocEnergyFixerView &v, int ic, double dt_d) noexcept
Definition: ERF_ShocEnergyFixer.H:87
Definition: ERF_ShocTypes.H:72
amrex::FArrayBox dz
Definition: ERF_ShocTypes.H:78
amrex::FArrayBox surf_lat_flux
Definition: ERF_ShocTypes.H:145
amrex::FArrayBox v_base
Definition: ERF_ShocTypes.H:134
amrex::FArrayBox rho
Definition: ERF_ShocTypes.H:81
amrex::FArrayBox tke_base_state
Definition: ERF_ShocTypes.H:135
amrex::FArrayBox qv_base
Definition: ERF_ShocTypes.H:130
amrex::FArrayBox shoc_ql
Definition: ERF_ShocTypes.H:111
amrex::FArrayBox tke
Definition: ERF_ShocTypes.H:91
amrex::FArrayBox qi_base
Definition: ERF_ShocTypes.H:132
amrex::FArrayBox exner
Definition: ERF_ShocTypes.H:83
amrex::FArrayBox u_base
Definition: ERF_ShocTypes.H:133
amrex::FArrayBox qc_base
Definition: ERF_ShocTypes.H:131
ShocColumnLayout layout
Definition: ERF_ShocTypes.H:73
amrex::FArrayBox surf_sens_flux
Definition: ERF_ShocTypes.H:144
amrex::FArrayBox qw
Definition: ERF_ShocTypes.H:89
amrex::FArrayBox v
Definition: ERF_ShocTypes.H:93
amrex::FArrayBox zt
Definition: ERF_ShocTypes.H:76
amrex::FArrayBox u
Definition: ERF_ShocTypes.H:92
amrex::FArrayBox thetal_base
Definition: ERF_ShocTypes.H:128
amrex::FArrayBox thetal
Definition: ERF_ShocTypes.H:85
int nlev
Definition: ERF_ShocTypes.H:64
Definition: ERF_ShocEnergyFixer.H:13
amrex::Array4< const amrex::Real > rho
Definition: ERF_ShocEnergyFixer.H:14
amrex::Array4< const amrex::Real > qc_base
Definition: ERF_ShocEnergyFixer.H:23
amrex::Array4< amrex::Real > thetal
Definition: ERF_ShocEnergyFixer.H:29
amrex::Array4< const amrex::Real > surf_lat_flux
Definition: ERF_ShocEnergyFixer.H:19
int nlev
Definition: ERF_ShocEnergyFixer.H:36
amrex::Array4< const amrex::Real > u
Definition: ERF_ShocEnergyFixer.H:31
amrex::Array4< const amrex::Real > zt
Definition: ERF_ShocEnergyFixer.H:16
amrex::Array4< const amrex::Real > tke
Definition: ERF_ShocEnergyFixer.H:33
amrex::Array4< const amrex::Real > tke_base
Definition: ERF_ShocEnergyFixer.H:27
bool include_momentum_energy
Definition: ERF_ShocEnergyFixer.H:37
amrex::Array4< const amrex::Real > u_base
Definition: ERF_ShocEnergyFixer.H:25
amrex::Array4< const amrex::Real > exner
Definition: ERF_ShocEnergyFixer.H:17
amrex::Array4< const amrex::Real > surf_sens_flux
Definition: ERF_ShocEnergyFixer.H:18
amrex::Array4< const amrex::Real > qv_base
Definition: ERF_ShocEnergyFixer.H:22
amrex::Array4< const amrex::Real > v_base
Definition: ERF_ShocEnergyFixer.H:26
amrex::Array4< const amrex::Real > v
Definition: ERF_ShocEnergyFixer.H:32
amrex::Array4< const amrex::Real > shoc_ql
Definition: ERF_ShocEnergyFixer.H:34
amrex::Array4< const amrex::Real > qi_base
Definition: ERF_ShocEnergyFixer.H:24
amrex::Array4< const amrex::Real > thetal_base
Definition: ERF_ShocEnergyFixer.H:21
amrex::Array4< const amrex::Real > dz
Definition: ERF_ShocEnergyFixer.H:15
amrex::Array4< const amrex::Real > qw
Definition: ERF_ShocEnergyFixer.H:30