ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_BuoyancyUtils.H
Go to the documentation of this file.
1 #ifndef ERF_BUOYANCY_UTILS_H_
2 #define ERF_BUOYANCY_UTILS_H_
3 
4 #include <ERF_EOS.H>
5 #include <ERF_Constants.H>
6 
7 AMREX_GPU_DEVICE
8 AMREX_FORCE_INLINE
9 amrex::Real
10 buoyancy_dry_anelastic (int& i, int& j, int& k,
11  amrex::Real const& grav_gpu,
12  const amrex::Array4<const amrex::Real>& r0_arr,
13  const amrex::Array4<const amrex::Real>& th0_arr,
14  const amrex::Array4<const amrex::Real>& cell_data)
15 {
16  // Note: this is the same term as the moist anelastic buoyancy when qv = qc = qt = 0
17  amrex::Real theta_d_lo = cell_data(i,j,k-1,RhoTheta_comp)/cell_data(i,j,k-1,Rho_comp);
18  amrex::Real theta_d_hi = cell_data(i,j,k ,RhoTheta_comp)/cell_data(i,j,k ,Rho_comp);
19 
20  amrex::Real theta_d_wface = amrex::Real(0.5) * (theta_d_lo + theta_d_hi);
21  amrex::Real theta_d0_wface = amrex::Real(0.5) * (th0_arr(i,j,k) + th0_arr(i,j,k-1));
22  amrex::Real rho0_wface = amrex::Real(0.5) * (r0_arr(i,j,k) + r0_arr(i,j,k-1));
23 
24  return (-rho0_wface * grav_gpu * (theta_d_wface - theta_d0_wface) / theta_d0_wface);
25 }
26 
27 AMREX_GPU_DEVICE
28 AMREX_FORCE_INLINE
29 amrex::Real
30 buoyancy_moist_anelastic (int& i, int& j, int& k,
31  amrex::Real const& grav_gpu,
32  amrex::Real const& rv_over_rd,
33  const amrex::Array4<const amrex::Real>& r0_arr,
34  const amrex::Array4<const amrex::Real>& th0_arr,
35  const amrex::Array4<const amrex::Real>& cell_data)
36 {
37  amrex::Real theta_d_lo = cell_data(i,j,k-1,RhoTheta_comp)/r0_arr(i,j,k-1);
38  amrex::Real qv_lo = cell_data(i,j,k-1,RhoQ1_comp) /r0_arr(i,j,k-1);
39  amrex::Real qc_lo = cell_data(i,j,k-1,RhoQ2_comp) /r0_arr(i,j,k-1);
40  amrex::Real qt_lo = qv_lo + qc_lo;
41  amrex::Real theta_v_lo = theta_d_lo * (1.0 - (1.0 - rv_over_rd)*qt_lo - rv_over_rd*qc_lo);
42 
43  amrex::Real theta_d_hi = cell_data(i,j,k,RhoTheta_comp)/r0_arr(i,j,k);
44  amrex::Real qv_hi = cell_data(i,j,k,RhoQ1_comp) /r0_arr(i,j,k);
45  amrex::Real qc_hi = cell_data(i,j,k,RhoQ2_comp) /r0_arr(i,j,k);
46  amrex::Real qt_hi = qv_hi + qc_hi;
47  amrex::Real theta_v_hi = theta_d_hi * (1.0 - (1.0 - rv_over_rd)*qt_hi - rv_over_rd*qc_hi);
48 
49  amrex::Real theta_v_wface = amrex::Real(0.5) * (theta_v_lo + theta_v_hi);
50  amrex::Real theta_v0_wface = amrex::Real(0.5) * (th0_arr(i,j,k) + th0_arr(i,j,k-1));
51  amrex::Real rho0_wface = amrex::Real(0.5) * (r0_arr(i,j,k) + r0_arr(i,j,k-1));
52 
53  return (-rho0_wface * grav_gpu * (theta_v_wface - theta_v0_wface) / theta_v0_wface);
54 }
55 
56 AMREX_GPU_DEVICE
57 AMREX_FORCE_INLINE
58 amrex::Real
59 buoyancy_rhopert (int& i, int& j, int& k,
60  const int& n_qstate,
61  amrex::Real const& grav_gpu,
62  const amrex::Array4<const amrex::Real>& r0_arr,
63  const amrex::Array4<const amrex::Real>& cell_data)
64 {
65  amrex::Real rhop_hi = cell_data(i,j,k ,Rho_comp) - r0_arr(i,j,k );
66  amrex::Real rhop_lo = cell_data(i,j,k-1,Rho_comp) - r0_arr(i,j,k-1);
67  for (int q_offset(0); q_offset<n_qstate; ++q_offset) {
68  rhop_hi += cell_data(i,j,k ,RhoQ1_comp+q_offset);
69  rhop_lo += cell_data(i,j,k-1,RhoQ1_comp+q_offset);
70  }
71  return( grav_gpu * amrex::Real(0.5) * ( rhop_hi + rhop_lo ) );
72 }
73 
74 AMREX_GPU_DEVICE
75 AMREX_FORCE_INLINE
76 amrex::Real
77 buoyancy_dry_Tpert (int& i, int& j, int& k,
78  amrex::Real const& grav_gpu,
79  amrex::Real const& rd_over_cp,
80  const amrex::Array4<const amrex::Real>& r0_arr,
81  const amrex::Array4<const amrex::Real>& p0_arr,
82  const amrex::Array4<const amrex::Real>& th0_arr,
83  const amrex::Array4<const amrex::Real>& cell_data)
84 {
85  amrex::Real t0_hi = getTgivenPandTh(p0_arr(i,j,k), th0_arr(i,j,k), rd_over_cp);
86  amrex::Real t_hi = getTgivenRandRTh(cell_data(i,j,k ,Rho_comp), cell_data(i,j,k ,RhoTheta_comp));
87 
88  amrex::Real t0_lo = getTgivenPandTh(p0_arr(i,j,k-1), th0_arr(i,j,k-1), rd_over_cp);
89  amrex::Real t_lo = getTgivenRandRTh(cell_data(i,j,k-1,Rho_comp), cell_data(i,j,k-1,RhoTheta_comp));
90 
91  amrex::Real tprime_hi = (t_hi-t0_hi)/t0_hi;
92  amrex::Real tprime_lo = (t_lo-t0_lo)/t0_lo;
93 
94  amrex::Real tp_avg = amrex::Real(0.5) * (tprime_hi + tprime_lo);
95  amrex::Real r0_avg = amrex::Real(0.5) * (r0_arr(i,j,k) + r0_arr(i,j,k-1));
96 
97  return ( -r0_avg * grav_gpu * tp_avg);
98 }
99 
100 AMREX_GPU_DEVICE
101 AMREX_FORCE_INLINE
102 amrex::Real
103 buoyancy_dry_Thpert (int& i, int& j, int& k,
104  amrex::Real const& grav_gpu,
105  const amrex::Array4<const amrex::Real>& r0_arr,
106  const amrex::Array4<const amrex::Real>& th0_arr,
107  const amrex::Array4<const amrex::Real>& cell_prim)
108 {
109  //
110  // TODO: we are currently using Theta_prime/Theta_0 to replace T_prime/T_0 - P_prime/P_0
111  // but I don't think that is quite right.
112  //
113  amrex::Real thetaprime_hi = (cell_prim(i,j,k ,PrimTheta_comp) - th0_arr(i,j,k )) / th0_arr(i,j,k );
114  amrex::Real thetaprime_lo = (cell_prim(i,j,k-1,PrimTheta_comp) - th0_arr(i,j,k-1)) / th0_arr(i,j,k-1);
115 
116  amrex::Real thp_avg = amrex::Real(0.5) * (thetaprime_hi + thetaprime_lo);
117  amrex::Real r0_avg = amrex::Real(0.5) * (r0_arr(i,j,k) + r0_arr(i,j,k-1));
118 
119  return ( -r0_avg * grav_gpu * thp_avg);
120 }
121 
122 AMREX_GPU_DEVICE
123 AMREX_FORCE_INLINE
124 amrex::Real
125 buoyancy_moist_Tpert (int& i, int& j, int& k,
126  const int& n_qstate,
127  amrex::Real const& grav_gpu,
128  amrex::Real const& rd_over_cp,
129  const amrex::Array4<const amrex::Real>& r0_arr,
130  const amrex::Array4<const amrex::Real>& th0_arr,
131  const amrex::Array4<const amrex::Real>& p0_arr,
132  const amrex::Array4<const amrex::Real>& cell_prim,
133  const amrex::Array4<const amrex::Real>& cell_data)
134 {
135  //
136  // Note: this currently assumes the base state qv0 is identically zero
137  // TODO: generalize this to allow for moist base state
138  //
139  amrex::Real qv_hi = (n_qstate >= 1) ? cell_prim(i,j,k ,PrimQ1_comp) : 0.0;
140  amrex::Real qv_lo = (n_qstate >= 1) ? cell_prim(i,j,k-1,PrimQ1_comp) : 0.0;
141 
142  amrex::Real qc_hi = (n_qstate >= 2) ? cell_prim(i,j,k ,PrimQ2_comp) : 0.0;
143  amrex::Real qc_lo = (n_qstate >= 2) ? cell_prim(i,j,k-1,PrimQ2_comp) : 0.0;
144 
145  amrex::Real qp_hi = (n_qstate >= 3) ? cell_prim(i,j,k ,PrimQ3_comp) : 0.0;
146  amrex::Real qp_lo = (n_qstate >= 3) ? cell_prim(i,j,k-1,PrimQ3_comp) : 0.0;
147 
148  amrex::Real t0_hi = getTgivenPandTh(p0_arr(i,j,k), th0_arr(i,j,k), rd_over_cp);
149  amrex::Real t0_lo = getTgivenPandTh(p0_arr(i,j,k), th0_arr(i,j,k), rd_over_cp);
150 
151  amrex::Real t_hi = getTgivenRandRTh(cell_data(i,j,k ,Rho_comp), cell_data(i,j,k ,RhoTheta_comp), qv_hi);
152  amrex::Real t_lo = getTgivenRandRTh(cell_data(i,j,k-1,Rho_comp), cell_data(i,j,k-1,RhoTheta_comp), qv_lo);
153 
154  amrex::Real q_hi = 0.61 * qv_hi - (qc_hi + qp_hi) + (t_hi-t0_hi)/t0_hi;
155  amrex::Real q_lo = 0.61 * qv_lo - (qc_lo + qp_lo) + (t_lo-t0_lo)/t0_lo;
156 
157  amrex::Real qavg = amrex::Real(0.5) * (q_hi + q_lo);
158  amrex::Real r0avg = amrex::Real(0.5) * (r0_arr(i,j,k) + r0_arr(i,j,k-1));
159 
160  return ( -r0avg * grav_gpu * qavg);
161 }
162 
163 AMREX_GPU_DEVICE
164 AMREX_FORCE_INLINE
165 amrex::Real
166 buoyancy_moist_Thpert (int& i, int& j, int& k,
167  const int& n_qstate,
168  amrex::Real const& grav_gpu,
169  const amrex::Array4<const amrex::Real>& r0_arr,
170  const amrex::Array4<const amrex::Real>& th0_arr,
171  const amrex::Array4<const amrex::Real>& cell_prim)
172 {
173  //
174  // Note: this currently assumes the base state qv0 is identically zero
175  // TODO: generalize this to allow for moist base state
176  //
177  amrex::Real qv_hi = (n_qstate >= 1) ? cell_prim(i,j,k ,PrimQ1_comp) : 0.0;
178  amrex::Real qv_lo = (n_qstate >= 1) ? cell_prim(i,j,k-1,PrimQ1_comp) : 0.0;
179 
180  amrex::Real qc_hi = (n_qstate >= 2) ? cell_prim(i,j,k ,PrimQ2_comp) : 0.0;
181  amrex::Real qc_lo = (n_qstate >= 2) ? cell_prim(i,j,k-1,PrimQ2_comp) : 0.0;
182 
183  amrex::Real qp_hi = (n_qstate >= 3) ? cell_prim(i,j,k ,PrimQ3_comp) : 0.0;
184  amrex::Real qp_lo = (n_qstate >= 3) ? cell_prim(i,j,k-1,PrimQ3_comp) : 0.0;
185 
186  //
187  // TODO: we are currently using Theta_prime/Theta_0 to replace T_prime/T_0 - P_prime/P_0
188  // but I don't think that is quite right.
189  //
190  amrex::Real q_hi = amrex::Real(0.61) * qv_hi - (qc_hi + qp_hi)
191  + (cell_prim(i,j,k ,PrimTheta_comp) - th0_arr(i,j,k )) / th0_arr(i,j,k );
192 
193  amrex::Real q_lo = amrex::Real(0.61) * qv_lo - (qc_lo + qp_lo)
194  + (cell_prim(i,j,k-1,PrimTheta_comp) - th0_arr(i,j,k-1)) / th0_arr(i,j,k-1);
195 
196  amrex::Real qavg = amrex::Real(0.5) * (q_hi + q_lo);
197  amrex::Real r0avg = amrex::Real(0.5) * (r0_arr(i,j,k) + r0_arr(i,j,k-1));
198 
199  return ( -r0avg * grav_gpu * qavg);
200 }
201 
202 // **************************************************************************************
203 // Routines below this line are not currently used
204 // **************************************************************************************
205 
206 AMREX_GPU_DEVICE
207 AMREX_FORCE_INLINE
208 amrex::Real
209 buoyancy_dry_anelastic_T (int& i, int& j, int& k,
210  amrex::Real const& grav_gpu,
211  amrex::Real const& rd_over_cp,
212  const amrex::Array4<const amrex::Real>& r0_arr,
213  const amrex::Array4<const amrex::Real>& p0_arr,
214  const amrex::Array4<const amrex::Real>& cell_data)
215 {
216  amrex::Real rt0_hi = getRhoThetagivenP(p0_arr(i,j,k));
217  amrex::Real t0_hi = getTgivenPandTh(p0_arr(i,j,k), rt0_hi/r0_arr(i,j,k), rd_over_cp);
218  amrex::Real t_hi = getTgivenPandTh(p0_arr(i,j,k), cell_data(i,j,k,RhoTheta_comp)/r0_arr(i,j,k), rd_over_cp);
219  amrex::Real q_hi = (t_hi-t0_hi)/t0_hi;
220 
221  amrex::Real rt0_lo = getRhoThetagivenP(p0_arr(i,j,k-1));
222  amrex::Real t0_lo = getTgivenPandTh(p0_arr(i,j,k-1), rt0_lo/r0_arr(i,j,k-1), rd_over_cp);
223  amrex::Real t_lo = getTgivenPandTh(p0_arr(i,j,k-1), cell_data(i,j,k-1,RhoTheta_comp)/r0_arr(i,j,k-1), rd_over_cp);
224  amrex::Real q_lo = (t_lo-t0_lo)/t0_lo;
225 
226  amrex::Real r0_q_avg = amrex::Real(0.5) * (r0_arr(i,j,k) * q_hi + r0_arr(i,j,k-1) * q_lo);
227  return (-r0_q_avg * grav_gpu);
228 }
229 
230 #endif
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real buoyancy_rhopert(int &i, int &j, int &k, const int &n_qstate, amrex::Real const &grav_gpu, const amrex::Array4< const amrex::Real > &r0_arr, const amrex::Array4< const amrex::Real > &cell_data)
Definition: ERF_BuoyancyUtils.H:59
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real buoyancy_dry_anelastic(int &i, int &j, int &k, amrex::Real const &grav_gpu, const amrex::Array4< const amrex::Real > &r0_arr, const amrex::Array4< const amrex::Real > &th0_arr, const amrex::Array4< const amrex::Real > &cell_data)
Definition: ERF_BuoyancyUtils.H:10
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real buoyancy_dry_Thpert(int &i, int &j, int &k, amrex::Real const &grav_gpu, const amrex::Array4< const amrex::Real > &r0_arr, const amrex::Array4< const amrex::Real > &th0_arr, const amrex::Array4< const amrex::Real > &cell_prim)
Definition: ERF_BuoyancyUtils.H:103
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real buoyancy_dry_Tpert(int &i, int &j, int &k, amrex::Real const &grav_gpu, amrex::Real const &rd_over_cp, const amrex::Array4< const amrex::Real > &r0_arr, const amrex::Array4< const amrex::Real > &p0_arr, const amrex::Array4< const amrex::Real > &th0_arr, const amrex::Array4< const amrex::Real > &cell_data)
Definition: ERF_BuoyancyUtils.H:77
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real buoyancy_moist_anelastic(int &i, int &j, int &k, amrex::Real const &grav_gpu, amrex::Real const &rv_over_rd, const amrex::Array4< const amrex::Real > &r0_arr, const amrex::Array4< const amrex::Real > &th0_arr, const amrex::Array4< const amrex::Real > &cell_data)
Definition: ERF_BuoyancyUtils.H:30
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real buoyancy_moist_Thpert(int &i, int &j, int &k, const int &n_qstate, amrex::Real const &grav_gpu, const amrex::Array4< const amrex::Real > &r0_arr, const amrex::Array4< const amrex::Real > &th0_arr, const amrex::Array4< const amrex::Real > &cell_prim)
Definition: ERF_BuoyancyUtils.H:166
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real buoyancy_moist_Tpert(int &i, int &j, int &k, const int &n_qstate, amrex::Real const &grav_gpu, amrex::Real const &rd_over_cp, const amrex::Array4< const amrex::Real > &r0_arr, const amrex::Array4< const amrex::Real > &th0_arr, const amrex::Array4< const amrex::Real > &p0_arr, const amrex::Array4< const amrex::Real > &cell_prim, const amrex::Array4< const amrex::Real > &cell_data)
Definition: ERF_BuoyancyUtils.H:125
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real buoyancy_dry_anelastic_T(int &i, int &j, int &k, amrex::Real const &grav_gpu, amrex::Real const &rd_over_cp, const amrex::Array4< const amrex::Real > &r0_arr, const amrex::Array4< const amrex::Real > &p0_arr, const amrex::Array4< const amrex::Real > &cell_data)
Definition: ERF_BuoyancyUtils.H:209
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getRhoThetagivenP(const amrex::Real p, const amrex::Real qv=0.0)
Definition: ERF_EOS.H:175
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getTgivenRandRTh(const amrex::Real rho, const amrex::Real rhotheta, const amrex::Real qv=0.0)
Definition: ERF_EOS.H:46
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 PrimQ1_comp
Definition: ERF_IndexDefines.H:53
#define PrimQ2_comp
Definition: ERF_IndexDefines.H:54
#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 PrimTheta_comp
Definition: ERF_IndexDefines.H:50
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:42
#define PrimQ3_comp
Definition: ERF_IndexDefines.H:55