ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_SimplifiedSEB.H
Go to the documentation of this file.
1 #ifndef ERF_SIMPLIFIED_SEB_H_
2 #define ERF_SIMPLIFIED_SEB_H_
3 
4 #include <AMReX_GpuControl.H>
5 #include <AMReX_Math.H>
6 #include <AMReX_FArrayBox.H>
7 #include <cmath>
8 
9 #include <ERF_Constants.H>
10 #include <ERF_MicrophysicsConstants.H> // rhor, the density of water
11 
12 /**
13  * @file ERF_SimplifiedSEB.H
14  * @brief Simplified SEB — Diagnostic mode residual computation.
15  *
16  * Implements diagnostic-only surface energy balance residual diagnosis.
17  * No prognostic update to surface temperature or fluxes; residual is computed
18  * and reported for validation and diagnostic purposes only.
19  *
20  * Surface Energy Balance Equation:
21  * R_net(i,j) = SW_net(i,j) + LW_net(i,j)
22  * = [sw_flux_sfc(i,j)] + [lw_flux_sfc(i,j)]
23  *
24  * SEB_residual(i,j) = R_net(i,j) - hfx_sfc(i,j) - lh_sfc(i,j) - grdflx_sfc(i,j)
25  *
26  * Where:
27  * - sw_flux_sfc: net shortwave flux at surface [W/m^2]
28  * - lw_flux_sfc: net longwave flux at surface [W/m^2]
29  * - hfx_sfc: sensible heat flux (H) [W/m^2]
30  * - lh_sfc: latent heat flux (LE) [W/m^2]
31  * - grdflx_sfc: ground heat flux (G) [W/m^2]
32  *
33  * A perfectly closed budget gives SEB_residual = 0; non-zero residual
34  * indicates energy not accounted for by the four main SEB terms.
35  *
36  * References:
37  * -----------
38  * - Oke, T. R., 1987: Boundary Layer Climates (2nd ed.), Routledge.
39  */
40 
41 /**
42  * @brief Diagnose the surface energy balance residual.
43  *
44  * Computes the SEB residual from net radiative flux and turbulent/ground
45  * heat fluxes. All inputs are guarded with amrex::Math::isfinite() to safely handle
46  * NaN/Inf; if any input is non-finite, returns 0.0 (safe no-op).
47  *
48  * **GPU Safety**:
49  * - AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
50  * - No host-side I/O
51  * - No dynamic allocation
52  * - Safe for use in device reduction kernels
53  *
54  * @param[in] sw_net Shortwave net flux at surface [W/m^2]
55  * @param[in] lw_net Longwave net flux at surface [W/m^2]
56  * @param[in] hfx Sensible heat flux [W/m^2]
57  * @param[in] lh Latent heat flux [W/m^2]
58  * @param[in] grdflx Ground heat flux [W/m^2]
59  *
60  * @return SEB residual [W/m^2] = (sw_net + lw_net) - hfx - lh - grdflx
61  * Returns 0.0 if any input is non-finite (NaN or Inf)
62  */
63 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
65  amrex::Real lw_net,
66  amrex::Real hfx,
67  amrex::Real lh,
68  amrex::Real grdflx)
69 {
70  // Guard all inputs against non-finite values (NaN, Inf)
71  if (!amrex::Math::isfinite(sw_net) || !amrex::Math::isfinite(lw_net) ||
72  !amrex::Math::isfinite(hfx) || !amrex::Math::isfinite(lh) || !amrex::Math::isfinite(grdflx)) {
73  return 0.0; // Safe no-op: return zero residual if any input is invalid
74  }
75 
76  // Compute net radiation
77  amrex::Real r_net = sw_net + lw_net;
78 
79  // Compute SEB residual
80  amrex::Real seb_residual = r_net - hfx - lh - grdflx;
81 
82  return seb_residual;
83 }
84 
85 /**
86  * @brief Compute prognostic surface temperature tendency using force-restore formulation.
87  *
88  * Computes dT_s/dt from SEB residual and restoring term toward deep soil temperature:
89  * dT_s/dt = SEB_residual / C_s - (2*pi/tau) * (T_s - T_deep)
90  *
91  * All inputs are guarded with amrex::Math::isfinite() to safely handle NaN/Inf; if any input
92  * is non-finite, any parameter is non-positive (C_s <= 0, tau <= 0), returns 0.0 (safe no-op).
93  *
94  * **GPU Safety**:
95  * - AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
96  * - No host-side I/O
97  * - No dynamic allocation
98  * - Safe for use in device kernels
99  *
100  * @param[in] seb_residual SEB residual [W/m^2] = R_net - H - LE - G
101  * @param[in] t_s Current surface temperature [K]
102  * @param[in] t_deep Deep soil temperature [K]
103  * @param[in] c_s Effective surface heat capacity [J/(m^2*K)]
104  * @param[in] tau Force-restore timescale [s]
105  *
106  * @return Temperature tendency dT_s/dt [K/s]
107  * Returns 0.0 if any input is non-finite or any parameter is non-positive
108  */
109 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
111  amrex::Real t_s,
112  amrex::Real t_deep,
113  amrex::Real c_s,
114  amrex::Real tau)
115 {
116  // Guard all inputs against non-finite values
117  if (!amrex::Math::isfinite(seb_residual) || !amrex::Math::isfinite(t_s) ||
118  !amrex::Math::isfinite(t_deep) || !amrex::Math::isfinite(c_s) || !amrex::Math::isfinite(tau)) {
119  return 0.0; // Safe no-op
120  }
121 
122  // Validate parameter ranges
123  if (c_s <= 0.0 || tau <= 0.0) {
124  return 0.0; // Safe no-op for invalid parameters
125  }
126 
127  // Compute tendency: SEB_residual / C_s - (2*pi/tau) * (T_s - T_deep)
128  amrex::Real seb_term = seb_residual / c_s;
129  amrex::Real restore_term = (2.0 * PI / tau) * (t_s - t_deep);
130  amrex::Real dt_s_dt = seb_term - restore_term;
131 
132  return dt_s_dt;
133 }
134 
135 /**
136  * @brief Compute prognostic surface moisture tendency using force-restore formulation.
137  *
138  * Computes dq_s/dt from latent heat flux and restoring term toward deep soil moisture:
139  * dq_s/dt = -(LE / (L_v * rhor * d_s)) - (1/tau_q) * (q_s - q_deep)
140  *
141  * Constants:
142  * - L_v = 2.5e6 J/kg (latent heat of vaporization)
143  * - rhor = 1000.0 kg/m^3 (water density, from ERF_Constants.H)
144  *
145  * All inputs are guarded with amrex::Math::isfinite() to safely handle NaN/Inf; if any input
146  * is non-finite, any parameter is non-positive (d_s <= 0, tau_q <= 0), returns 0.0 (safe no-op).
147  *
148  * **GPU Safety**:
149  * - AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
150  * - No host-side I/O
151  * - No dynamic allocation
152  * - Safe for use in device kernels
153  *
154  * @param[in] le Latent heat flux [W/m^2]
155  * @param[in] q_s Current surface moisture [kg/kg]
156  * @param[in] q_deep Deep soil moisture [kg/kg]
157  * @param[in] d_s Effective surface moisture layer depth [m]
158  * @param[in] tau_q Moisture force-restore timescale [s]
159  *
160  * @return Moisture tendency dq_s/dt [kg/kg/s]
161  * Returns 0.0 if any input is non-finite or any parameter is non-positive
162  */
163 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
165  amrex::Real q_s,
166  amrex::Real q_deep,
167  amrex::Real d_s,
168  amrex::Real tau_q)
169 {
170  // Guard all inputs against non-finite values
171  if (!amrex::Math::isfinite(le) || !amrex::Math::isfinite(q_s) ||
172  !amrex::Math::isfinite(q_deep) || !amrex::Math::isfinite(d_s) || !amrex::Math::isfinite(tau_q)) {
173  return 0.0; // Safe no-op
174  }
175 
176  // Validate parameter ranges
177  if (d_s <= 0.0 || tau_q <= 0.0) {
178  return 0.0; // Safe no-op for invalid parameters
179  }
180 
181  // L_v and rhor both come from ERF_Constants.H. A local L_v here shadowed
182  // the global one, and a local water density duplicated rhor.
183 
184  // Compute tendency: -(LE / (L_v * rhor * d_s)) - (1/tau_q) * (q_s - q_deep)
185  amrex::Real le_term = -(le / (L_v * rhor * d_s));
186  amrex::Real restore_term = (1.0 / tau_q) * (q_s - q_deep);
187  amrex::Real dq_s_dt = le_term - restore_term;
188 
189  return dq_s_dt;
190 }
191 
192 #endif // ERF_SIMPLIFIED_SEB_H_
constexpr amrex::Real L_v
Definition: ERF_Constants.H:51
Physical constants and tuning parameters used only by the moisture and cloud-physics code.
constexpr amrex::Real rhor
Definition: ERF_MicrophysicsConstants.H:39
constexpr amrex::Real PI
Definition: ERF_NumericalConstants.H:39
amrex::Real Real
Definition: ERF_ShocInterface.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real diagnose_seb_residual(amrex::Real sw_net, amrex::Real lw_net, amrex::Real hfx, amrex::Real lh, amrex::Real grdflx)
Diagnose the surface energy balance residual.
Definition: ERF_SimplifiedSEB.H:64
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real prognostic_dqs_dt(amrex::Real le, amrex::Real q_s, amrex::Real q_deep, amrex::Real d_s, amrex::Real tau_q)
Compute prognostic surface moisture tendency using force-restore formulation.
Definition: ERF_SimplifiedSEB.H:164
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real prognostic_dTs_dt(amrex::Real seb_residual, amrex::Real t_s, amrex::Real t_deep, amrex::Real c_s, amrex::Real tau)
Compute prognostic surface temperature tendency using force-restore formulation.
Definition: ERF_SimplifiedSEB.H:110