ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_NearSurfaceDiagnostics.H
Go to the documentation of this file.
1 #ifndef ERF_NEAR_SURFACE_DIAGNOSTICS_H_
2 #define ERF_NEAR_SURFACE_DIAGNOSTICS_H_
3 
4 #include <AMReX_GpuQualifiers.H>
5 #include <AMReX_MultiFab.H>
6 #include <AMReX_iMultiFab.H>
7 #include <cmath>
8 
9 #include "ERF_Constants.H"
10 #include "ERF_MOSTStress.H"
12 
14 {
15 
17 {
23 };
24 
26 {
29 };
30 
31 struct MostState
32 {
39 };
40 
42 {
45 };
46 
47 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
48 bool valid_real (amrex::Real value) noexcept
49 {
50  return std::isfinite(value);
51 }
52 
53 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
55 {
56  return valid_real(value) && value > amrex::Real(-9990.0) &&
58 }
59 
60 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
61 bool native_bundle_temperature_is_valid (const NativeBundle& bundle) noexcept;
62 
63 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
64 bool native_bundle_mixing_ratio_is_valid (const NativeBundle& bundle) noexcept;
65 
66 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
67 bool native_bundle_vegetation_fraction_is_valid (const NativeBundle& bundle) noexcept;
68 
69 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
70 bool native_bundle_is_valid (const NativeBundle& bundle) noexcept
71 {
72  return native_bundle_temperature_is_valid(bundle) &&
75 }
76 
77 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
78 bool native_bundle_temperature_is_valid (const NativeBundle& bundle) noexcept
79 {
80  return valid_noahmp_component(bundle.temperature_vegetated) &&
81  valid_noahmp_component(bundle.temperature_bare) &&
82  bundle.temperature_vegetated > amrex::Real(0.0) &&
83  bundle.temperature_bare > amrex::Real(0.0) &&
84  valid_noahmp_component(bundle.vegetation_fraction) &&
85  bundle.vegetation_fraction >= amrex::Real(0.0) &&
86  bundle.vegetation_fraction <= amrex::Real(1.0);
87 }
88 
89 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
91 {
92  return valid_noahmp_component(bundle.mixing_ratio_vegetated) &&
93  valid_noahmp_component(bundle.mixing_ratio_bare) &&
94  valid_noahmp_component(bundle.vegetation_fraction) &&
95  bundle.mixing_ratio_vegetated >= amrex::Real(0.0) &&
96  bundle.mixing_ratio_bare >= amrex::Real(0.0) &&
97  bundle.vegetation_fraction >= amrex::Real(0.0) &&
98  bundle.vegetation_fraction <= amrex::Real(1.0);
99 }
100 
101 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
103 {
104  return valid_noahmp_component(bundle.vegetation_fraction) &&
105  bundle.vegetation_fraction >= amrex::Real(0.0) &&
106  bundle.vegetation_fraction <= amrex::Real(1.0);
107 }
108 
109 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
111 {
112  const amrex::Real f = bundle.vegetation_fraction;
113  return {
114  f * bundle.temperature_vegetated + (amrex::Real(1.0)-f) * bundle.temperature_bare,
115  f * bundle.mixing_ratio_vegetated + (amrex::Real(1.0)-f) * bundle.mixing_ratio_bare
116  };
117 }
118 
119 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
120 bool evaluate_most_factor (const MostState& state,
122  amrex::Real& factor) noexcept
123 {
124  if (!valid_real(state.roughness_height) ||
125  !valid_real(state.obukhov_length) ||
126  state.roughness_height <= amrex::Real(0.0) ||
127  height <= state.roughness_height ||
128  state.obukhov_length == amrex::Real(0.0)) {
129  return false;
130  }
131  const similarity_funs sfuns;
132  factor = std::log(height / state.roughness_height) -
133  sfuns.calc_psi_h(height / state.obukhov_length);
134  return valid_real(factor);
135 }
136 
137 // Evaluate ERF's integrated scalar profile without changing the production
138 // surface-layer state. The inputs use theta and mixing-ratio scales.
139 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
140 bool evaluate_most_profile (const MostState& state,
142  MostProfile& profile) noexcept
143 {
144  if (!valid_real(state.theta_surface) || !valid_real(state.theta_star) ||
145  !valid_real(state.mixing_ratio_surface) || !valid_real(state.mixing_ratio_star)) {
146  return false;
147  }
148 
149  amrex::Real profile_factor = amrex::Real(0.0);
150  if (!evaluate_most_factor(state, height, profile_factor)) {
151  return false;
152  }
153 
154  profile.potential_temperature = state.theta_surface +
155  state.theta_star / KAPPA * profile_factor;
156  profile.mixing_ratio = state.mixing_ratio_surface +
157  state.mixing_ratio_star / KAPPA * profile_factor;
158  return valid_real(profile.potential_temperature) &&
159  valid_real(profile.mixing_ratio) &&
160  profile.potential_temperature > amrex::Real(0.0) &&
161  profile.mixing_ratio >= amrex::Real(0.0);
162 }
163 
164 struct Sources
165 {
166  const amrex::MultiFab* native_temperature_vegetated = nullptr;
167  const amrex::MultiFab* native_temperature_bare = nullptr;
168  const amrex::MultiFab* native_mixing_ratio_vegetated = nullptr;
169  const amrex::MultiFab* native_mixing_ratio_bare = nullptr;
170  const amrex::MultiFab* native_vegetation_fraction = nullptr;
171 
172  const amrex::MultiFab* theta_surface = nullptr;
173  const amrex::MultiFab* theta_star = nullptr;
174  const amrex::MultiFab* mixing_ratio_surface = nullptr;
175  const amrex::MultiFab* mixing_ratio_star = nullptr;
176  const amrex::MultiFab* roughness_height = nullptr;
177  const amrex::MultiFab* obukhov_length = nullptr;
178  const amrex::MultiFab* source_mask = nullptr;
179  const amrex::iMultiFab* land_mask = nullptr;
180  const amrex::MultiFab* cons = nullptr;
181  const amrex::MultiFab* z_phys_nd = nullptr;
182 
184  int klo = 0;
185  bool moist = false;
186  bool has_lsm = false;
187 };
188 
189 // Fill any requested unified 2-m components. A component index below zero
190 // means that the caller did not select that field. A source-only request uses
191 // the temperature path; provenance paired with humidity describes humidity
192 // without adding a temperature prerequisite. Dry runs retain a meaningful
193 // temperature source while humidity remains unavailable.
194 void fill (amrex::MultiFab& dst,
195  int temperature_comp,
196  int mixing_ratio_comp,
197  int source_comp,
198  const Sources& sources,
199  amrex::Real missing_value = amrex::Real(-999.0));
200 
201 } // namespace near_surface_diagnostics
202 
203 #endif
constexpr amrex::Real KAPPA
Definition: ERF_Constants.H:63
constexpr amrex::Real lsm_undefined
Definition: ERF_Constants.H:35
Real value
Definition: ERF_HurricaneDiagnostics.cpp:30
Real height
Definition: ERF_InitCustomPert_SquallLine.H:33
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_NearSurfaceDiagnostics.cpp:14
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool native_bundle_vegetation_fraction_is_valid(const NativeBundle &bundle) noexcept
Definition: ERF_NearSurfaceDiagnostics.H:102
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool native_bundle_temperature_is_valid(const NativeBundle &bundle) noexcept
Definition: ERF_NearSurfaceDiagnostics.H:78
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE NativeAggregate aggregate_native_bundle(const NativeBundle &bundle) noexcept
Definition: ERF_NearSurfaceDiagnostics.H:110
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool native_bundle_is_valid(const NativeBundle &bundle) noexcept
Definition: ERF_NearSurfaceDiagnostics.H:70
void fill(MultiFab &dst, int temperature_comp, int mixing_ratio_comp, int source_comp, const Sources &sources, Real missing_value)
Definition: ERF_NearSurfaceDiagnostics.cpp:41
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool native_bundle_mixing_ratio_is_valid(const NativeBundle &bundle) noexcept
Definition: ERF_NearSurfaceDiagnostics.H:90
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool valid_noahmp_component(amrex::Real value) noexcept
Definition: ERF_NearSurfaceDiagnostics.H:54
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool evaluate_most_profile(const MostState &state, amrex::Real height, MostProfile &profile) noexcept
Definition: ERF_NearSurfaceDiagnostics.H:140
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool valid_real(amrex::Real value) noexcept
Definition: ERF_NearSurfaceDiagnostics.H:48
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool evaluate_most_factor(const MostState &state, amrex::Real height, amrex::Real &factor) noexcept
Definition: ERF_NearSurfaceDiagnostics.H:120
Definition: ERF_NearSurfaceDiagnostics.H:42
amrex::Real potential_temperature
Definition: ERF_NearSurfaceDiagnostics.H:43
amrex::Real mixing_ratio
Definition: ERF_NearSurfaceDiagnostics.H:44
Definition: ERF_NearSurfaceDiagnostics.H:32
amrex::Real mixing_ratio_star
Definition: ERF_NearSurfaceDiagnostics.H:36
amrex::Real theta_star
Definition: ERF_NearSurfaceDiagnostics.H:34
amrex::Real theta_surface
Definition: ERF_NearSurfaceDiagnostics.H:33
amrex::Real obukhov_length
Definition: ERF_NearSurfaceDiagnostics.H:38
amrex::Real mixing_ratio_surface
Definition: ERF_NearSurfaceDiagnostics.H:35
amrex::Real roughness_height
Definition: ERF_NearSurfaceDiagnostics.H:37
Definition: ERF_NearSurfaceDiagnostics.H:26
amrex::Real temperature
Definition: ERF_NearSurfaceDiagnostics.H:27
amrex::Real mixing_ratio
Definition: ERF_NearSurfaceDiagnostics.H:28
Definition: ERF_NearSurfaceDiagnostics.H:17
amrex::Real mixing_ratio_vegetated
Definition: ERF_NearSurfaceDiagnostics.H:20
amrex::Real temperature_vegetated
Definition: ERF_NearSurfaceDiagnostics.H:18
amrex::Real vegetation_fraction
Definition: ERF_NearSurfaceDiagnostics.H:22
amrex::Real mixing_ratio_bare
Definition: ERF_NearSurfaceDiagnostics.H:21
amrex::Real temperature_bare
Definition: ERF_NearSurfaceDiagnostics.H:19
Definition: ERF_NearSurfaceDiagnostics.H:165
const amrex::MultiFab * theta_surface
Definition: ERF_NearSurfaceDiagnostics.H:172
const amrex::MultiFab * z_phys_nd
Definition: ERF_NearSurfaceDiagnostics.H:181
bool moist
Definition: ERF_NearSurfaceDiagnostics.H:185
bool has_lsm
Definition: ERF_NearSurfaceDiagnostics.H:186
int klo
Definition: ERF_NearSurfaceDiagnostics.H:184
const amrex::iMultiFab * land_mask
Definition: ERF_NearSurfaceDiagnostics.H:179
const amrex::MultiFab * obukhov_length
Definition: ERF_NearSurfaceDiagnostics.H:177
const amrex::MultiFab * roughness_height
Definition: ERF_NearSurfaceDiagnostics.H:176
const amrex::MultiFab * native_temperature_bare
Definition: ERF_NearSurfaceDiagnostics.H:167
const amrex::MultiFab * cons
Definition: ERF_NearSurfaceDiagnostics.H:180
const amrex::MultiFab * theta_star
Definition: ERF_NearSurfaceDiagnostics.H:173
const amrex::MultiFab * native_temperature_vegetated
Definition: ERF_NearSurfaceDiagnostics.H:166
const amrex::MultiFab * mixing_ratio_surface
Definition: ERF_NearSurfaceDiagnostics.H:174
const amrex::MultiFab * native_mixing_ratio_bare
Definition: ERF_NearSurfaceDiagnostics.H:169
amrex::Real dz
Definition: ERF_NearSurfaceDiagnostics.H:183
const amrex::MultiFab * source_mask
Definition: ERF_NearSurfaceDiagnostics.H:178
const amrex::MultiFab * mixing_ratio_star
Definition: ERF_NearSurfaceDiagnostics.H:175
const amrex::MultiFab * native_mixing_ratio_vegetated
Definition: ERF_NearSurfaceDiagnostics.H:168
const amrex::MultiFab * native_vegetation_fraction
Definition: ERF_NearSurfaceDiagnostics.H:170
Definition: ERF_MOSTStress.H:40
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real calc_psi_h(amrex::Real zeta) const
Definition: ERF_MOSTStress.H:104