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