ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
plotfile2d Namespace Reference

Classes

struct  DiagnosticDescriptor
 
struct  SampledBracket
 
struct  SampledWindSources
 
struct  SelectedSurfacePrecipAccumulationComponents
 
struct  SampledFieldDescriptor
 
struct  SampledFieldSelection
 
struct  SampledVerticalCoordinateMetadata
 
struct  SampledLevelMetadata
 
struct  Plotfile2DOutputDescriptor
 
struct  SampledLevelDefinition
 
struct  PlotVariableSelection
 
struct  WaterPathDescriptor
 
struct  SelectedWaterPathComponents
 

Enumerations

enum class  DiagnosticID {
  ZSurf , LandMask , MapFac , LatM ,
  LonM , UStar , WStar , TStar ,
  QStar , Olen , Pblh , TSurf ,
  QSurf , Z0 , U10m , V10m ,
  UEast10m , VNorth10m , OLR , TopographicShadow ,
  TerrainDirectFactor , TerrainIncidence , UnshadedSwFluxDn , TerrainSwFluxDn ,
  SebTsfc , SebQsfc , SebHfx , SebLh ,
  SensFlux , LatenFlux , SurfPres , SeaLevelPressure ,
  PrecipTotalAccum , PrecipRainAccum , PrecipSnowAccum , PrecipGraupelAccum ,
  PrecipHailAccum , PrecipFrozenAccum , IntegratedQv , IntegratedQc ,
  IntegratedQi , IntegratedQr , IntegratedQs , IntegratedQg ,
  SurfaceDiagnosticSource , SensibleHeatFlux , LatentHeatFlux , ShocUStar ,
  ShocOlen , ShocWthvSfc , LandSurfaceTsfC , LandSurfaceEmissivity ,
  LandSurfaceAlbDirVis , LandSurfaceAlbDirNir , LandSurfaceAlbDifVis , LandSurfaceAlbDifNir ,
  LandSurfaceCosZenith , LandSurfaceSwFluxDn , LandSurfaceSwFluxDnDirVis , LandSurfaceSwFluxDnDirNir ,
  LandSurfaceSwFluxDnDifVis , LandSurfaceSwFluxDnDifNir , LandSurfaceLwFluxDn , LandSurfaceGrdflx ,
  LandSurfaceFira , LandSurfaceSav , LandSurfaceSag , LandSurfaceAlbedo ,
  LandSurfaceSfcrunoff , LandSurfaceUdrunoff , LandSurfaceSnow , LandSurfaceSnowh ,
  NoahmpTemperature2mVegetated , NoahmpTemperature2mBare , NoahmpWaterVaporMixingRatio2mVegetated , NoahmpWaterVaporMixingRatio2mBare ,
  NoahmpVegetationFraction , Temperature2m , WaterVaporMixingRatio2m , NearSurfaceDiagnosticSource ,
  DynamicSoilBase
}
 
enum class  DiagnosticCategory {
  Geometry , SurfaceLayer , Radiation , SurfaceFlux ,
  PBL , SurfaceState , Precipitation , ColumnIntegral ,
  LandSurface , SampledLevel
}
 
enum class  MissingPolicy { AlwaysAvailable , FillZeroWhenUnavailable , FillMinus999WhenUnavailable }
 
enum class  SampledFieldID {
  Rho , Theta , Temp , Pressure ,
  HeightMSL , HeightAGL , Qv , Qc ,
  Qi , Qr , Qs , Qg ,
  UEast , VNorth , W , WindSpeed ,
  WindDir
}
 
enum class  SampledCoordinate { ModelIndex , HeightMSL , HeightAGL , Pressure }
 
enum class  SampledInterpolation { None , Linear }
 

Functions

const amrex::Vector< DiagnosticDescriptor > & diagnostic_catalog ()
 
amrex::Vector< std::string > diagnostic_names ()
 
const DiagnosticDescriptor * find_diagnostic (const std::string &name)
 
amrex::Vector< std::string > dynamic_soil_diagnostic_names (int nsoil)
 
amrex::Vector< std::string > dynamic_soil_diagnostic_names (const amrex::Vector< std::string > &active_lsm_names)
 
const DiagnosticDescriptor * find_dynamic_soil_diagnostic (const std::string &name)
 
bool is_dynamic_soil_diagnostic_name (const std::string &name)
 
void fill_component_with_value (MultiFab &dst, int dst_comp, Real value)
 
void fill_component_from_klevel (MultiFab &dst, int dst_comp, const MultiFab &src, int src_k, int src_comp)
 
void fill_component_from_klevel_or_value (MultiFab &dst, int dst_comp, const MultiFab *src, int src_k, Real missing_value, int src_comp)
 
void fill_land_surface_component_from_klevel_or_missing (MultiFab &dst, int dst_comp, const MultiFab *src, int src_k, Real missing_value)
 
void fill_sensible_heat_flux_from_klevel_or_missing (MultiFab &dst, int dst_comp, const MultiFab *src, int src_k, Real missing_value)
 
void fill_latent_heat_flux_from_klevel_or_missing (MultiFab &dst, int dst_comp, const MultiFab *src, int src_k, Real missing_value)
 
void fill_component_with_value (amrex::MultiFab &dst, int dst_comp, amrex::Real value)
 
void fill_component_from_klevel (amrex::MultiFab &dst, int dst_comp, const amrex::MultiFab &src, int src_k, int src_comp=0)
 
void fill_component_from_klevel_or_value (amrex::MultiFab &dst, int dst_comp, const amrex::MultiFab *src, int src_k, amrex::Real missing_value, int src_comp=0)
 
void fill_land_surface_component_from_klevel_or_missing (amrex::MultiFab &dst, int dst_comp, const amrex::MultiFab *src, int src_k, amrex::Real missing_value)
 
void fill_sensible_heat_flux_from_klevel_or_missing (amrex::MultiFab &dst, int dst_comp, const amrex::MultiFab *src, int src_k, amrex::Real missing_value)
 
void fill_latent_heat_flux_from_klevel_or_missing (amrex::MultiFab &dst, int dst_comp, const amrex::MultiFab *src, int src_k, amrex::Real missing_value)
 
void fill_sampled_level_component (MultiFab &dst, int dst_comp, const Plotfile2DOutputDescriptor &descriptor, const MultiFab &cons, const MultiFab *z_phys_cc, const MultiFab &z_phys_nd, bool have_z_phys_cc, const MoistureComponentIndices &moisture_indices, int klo, int khi, const SampledWindSources &wind_sources, const MultiFab *p_hse)
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool sampled_target_is_bracketed (amrex::Real target, amrex::Real c0, amrex::Real c1) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real linear_interpolate (amrex::Real lo_value, amrex::Real hi_value, amrex::Real lo_coord, amrex::Real hi_coord, amrex::Real target) noexcept
 
void fill_sampled_level_component (amrex::MultiFab &dst, int dst_comp, const Plotfile2DOutputDescriptor &descriptor, const amrex::MultiFab &cons, const amrex::MultiFab *z_phys_cc, const amrex::MultiFab &z_phys_nd, bool have_z_phys_cc, const MoistureComponentIndices &moisture_indices, int klo, int khi, const SampledWindSources &wind_sources={}, const amrex::MultiFab *p_hse=nullptr)
 
const char * diagnostic_category_to_string (DiagnosticCategory category) noexcept
 
const char * missing_policy_to_string (MissingPolicy policy) noexcept
 
std::string missing_value_json (MissingPolicy policy)
 
std::string escape_json_string (const std::string &value)
 
std::string metadata_json_filename (const std::string &plotfilename)
 
std::string format_2d_metadata_json (const amrex::Vector< std::string > &varnames)
 
std::string format_2d_metadata_json (const amrex::Vector< Plotfile2DOutputDescriptor > &descriptors)
 
void write_2d_metadata_json (const std::string &plotfilename, const amrex::Vector< std::string > &varnames)
 
void write_2d_metadata_json (const std::string &plotfilename, const amrex::Vector< Plotfile2DOutputDescriptor > &descriptors)
 
bool is_precipitation_accumulation (DiagnosticID id) noexcept
 
bool is_precipitation_accumulation_name (const std::string &name)
 
bool precipitation_diagnostic_available (DiagnosticID id, const MoistureComponentIndices &moisture_indices) noexcept
 
SelectedSurfacePrecipAccumulationComponents selected_precipitation_accumulation_components (const amrex::Vector< std::string > &plot_var_names, const SurfacePrecipAccumulationSources &sources)
 
void fill_precipitation_accumulations (MultiFab &dst, const SurfacePrecipAccumulationSources &sources, const SelectedSurfacePrecipAccumulationComponents &selected, const int klo)
 
void fill_precipitation_accumulations (amrex::MultiFab &dst, const SurfacePrecipAccumulationSources &sources, const SelectedSurfacePrecipAccumulationComponents &selected, const int klo)
 
const amrex::Vector< SampledFieldDescriptor > & sampled_field_catalog ()
 
const SampledFieldDescriptor * find_sampled_field (const std::string &name)
 
amrex::Vector< std::string > available_sampled_field_names (const SolverChoice &solver_choice)
 
SampledFieldSelection select_requested_sampled_fields (const amrex::Vector< std::string > &requested, const SolverChoice &solver_choice)
 
std::string sampled_field_id_to_string (SampledFieldID field_id)
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool sampled_field_is_wind (SampledFieldID field_id) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool sampled_field_is_scalar_state (SampledFieldID field_id) noexcept
 
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real sampled_field_value (SampledFieldID field_id, const amrex::Array4< const amrex::Real > &cons_arr, const amrex::Array4< const amrex::Real > &z_phys_cc_arr, const amrex::Array4< const amrex::Real > &z_phys_nd_arr, const amrex::Array4< const amrex::Real > &p_hse_arr, bool have_z_phys_cc, bool use_hse_pressure, int i, int j, int k, const MoistureComponentIndices &moisture_indices) noexcept
 
const char * sampled_field_name (SampledFieldID field_id) noexcept
 
const char * sampled_coordinate_to_string (SampledCoordinate coordinate) noexcept
 
const char * sampled_coordinate_tag (SampledCoordinate coordinate) noexcept
 
const char * sampled_coordinate_default_units (SampledCoordinate coordinate) noexcept
 
const char * sampled_coordinate_default_interpolation (SampledCoordinate coordinate) noexcept
 
const char * sampled_interpolation_to_string (SampledInterpolation interpolation) noexcept
 
SampledCoordinate sampled_coordinate_from_string (const std::string &value)
 
SampledInterpolation sampled_interpolation_from_string (const std::string &value)
 
std::string validate_sampled_coordinate_string (const std::string &level_set_name, const std::string &value)
 
std::string sampled_level_error_prefix (const std::string &level_set_name, const std::string &parameter_name)
 
std::string sampled_level_value_tag (amrex::Real value, const std::string &units)
 
std::string sampled_output_name (const std::string &field_name, SampledCoordinate coordinate, amrex::Real value, const std::string &units)
 
std::string validate_sampled_level_definition (const SampledLevelDefinition &level_set)
 
SampledLevelDefinition parse_sampled_level_definition (const std::string &level_set_name, const std::string &pp_prefix)
 
amrex::Vector< std::string > parse_requested_sampled_level_sets (const std::string &pp_prefix, int which)
 
amrex::Vector< Plotfile2DOutputDescriptor > build_sampled_level_output_descriptors_from_definitions (const amrex::Vector< SampledLevelDefinition > &level_sets, const amrex::Vector< std::string > &static_plot_vars, const SolverChoice &solver_choice)
 
amrex::Vector< Plotfile2DOutputDescriptor > build_sampled_level_output_descriptors (const std::string &pp_prefix, int which, const amrex::Vector< std::string > &static_plot_vars, const SolverChoice &solver_choice)
 
PlotVariableSelection select_requested_plot_variables (const amrex::Vector< std::string > &requested, const amrex::Vector< std::string > &available)
 
std::string format_unavailable_2d_plot_var_warning (const std::string &parameter_name, const std::string &unavailable_name, const amrex::Vector< std::string > &available_names)
 
std::string format_plot2d_parameter_name (const std::string &pp_prefix, const std::string &parameter_name)
 
std::string format_2d_component_count_error (int lev, int filled, int expected)
 
std::string format_invalid_2d_stream_error (int which)
 
AMREX_FORCE_INLINE bool use_native_shoc_consumed_flux_source (bool native_shoc_owns_scalar_fluxes, bool native_shoc_has_consumed_flux_diagnostics, bool host_flux_field_available) noexcept
 
bool is_condensed_water_path (DiagnosticID id) noexcept
 
amrex::Vector< WaterPathDescriptor > active_condensed_water_path_descriptors (const SolverChoice &solver_choice)
 
bool is_condensed_water_path_name (const std::string &name)
 
bool is_noahmp_active (const SolverChoice &solver_choice) noexcept
 
bool is_land_surface_provider_field (DiagnosticID id) noexcept
 
bool active_lsm_contains (const amrex::Vector< std::string > &active_lsm_names, const char *name)
 
bool is_topographic_radiation_field (DiagnosticID id) noexcept
 
amrex::Vector< std::string > available_diagnostic_names (const SolverChoice &solver_choice)
 
amrex::Vector< std::string > available_diagnostic_names (const SolverChoice &solver_choice, bool has_surface_layer)
 
amrex::Vector< std::string > available_diagnostic_names (const SolverChoice &solver_choice, bool has_surface_layer, const amrex::Vector< std::string > &active_lsm_names)
 
SelectedWaterPathComponents selected_condensed_water_path_components (const amrex::Vector< std::string > &plot_var_names, const SolverChoice &solver_choice)
 
void fill_condensed_water_paths (MultiFab &dst, const MultiFab &cons, const SelectedWaterPathComponents &selected, const Geometry &geom, const MultiFab &detJ)
 
void fill_condensed_water_paths (amrex::MultiFab &dst, const amrex::MultiFab &cons, const SelectedWaterPathComponents &selected, const amrex::Geometry &geom, const amrex::MultiFab &detJ)
 

Variables

static constexpr int MaxSurfacePrecipAccumulationComponents = 6
 
static constexpr int MaxCondensedWaterPathComponents = 5
 

Enumeration Type Documentation

◆ DiagnosticCategory

Enumerator
Geometry 
SurfaceLayer 
Radiation 
SurfaceFlux 
PBL 
SurfaceState 
Precipitation 
ColumnIntegral 
LandSurface 
SampledLevel 
100 {
101  Geometry,
102  SurfaceLayer,
103  Radiation,
104  SurfaceFlux,
105  PBL,
106  SurfaceState,
109  LandSurface,
111 };
Wrapper class for managing land surface models across AMR levels.
Definition: ERF_LandSurface.H:19
Definition: ERF_Radiation.H:44
Definition: ERF_SurfaceLayer.H:60

◆ DiagnosticID

Enumerator
ZSurf 
LandMask 
MapFac 
LatM 
LonM 
UStar 
WStar 
TStar 
QStar 
Olen 
Pblh 
TSurf 
QSurf 
Z0 
U10m 
V10m 
UEast10m 
VNorth10m 
OLR 
TopographicShadow 
TerrainDirectFactor 
TerrainIncidence 
UnshadedSwFluxDn 
TerrainSwFluxDn 
SebTsfc 
SebQsfc 
SebHfx 
SebLh 
SensFlux 
LatenFlux 
SurfPres 
SeaLevelPressure 
PrecipTotalAccum 
PrecipRainAccum 
PrecipSnowAccum 
PrecipGraupelAccum 
PrecipHailAccum 
PrecipFrozenAccum 
IntegratedQv 
IntegratedQc 
IntegratedQi 
IntegratedQr 
IntegratedQs 
IntegratedQg 
SurfaceDiagnosticSource 
SensibleHeatFlux 
LatentHeatFlux 
ShocUStar 
ShocOlen 
ShocWthvSfc 
LandSurfaceTsfC 
LandSurfaceEmissivity 
LandSurfaceAlbDirVis 
LandSurfaceAlbDirNir 
LandSurfaceAlbDifVis 
LandSurfaceAlbDifNir 
LandSurfaceCosZenith 
LandSurfaceSwFluxDn 
LandSurfaceSwFluxDnDirVis 
LandSurfaceSwFluxDnDirNir 
LandSurfaceSwFluxDnDifVis 
LandSurfaceSwFluxDnDifNir 
LandSurfaceLwFluxDn 
LandSurfaceGrdflx 
LandSurfaceFira 
LandSurfaceSav 
LandSurfaceSag 
LandSurfaceAlbedo 
LandSurfaceSfcrunoff 
LandSurfaceUdrunoff 
LandSurfaceSnow 
LandSurfaceSnowh 
NoahmpTemperature2mVegetated 
NoahmpTemperature2mBare 
NoahmpWaterVaporMixingRatio2mVegetated 
NoahmpWaterVaporMixingRatio2mBare 
NoahmpVegetationFraction 
Temperature2m 
WaterVaporMixingRatio2m 
NearSurfaceDiagnosticSource 
DynamicSoilBase 
15 {
16  ZSurf,
17  LandMask,
18  MapFac,
19  LatM,
20  LonM,
21  UStar,
22  WStar,
23  TStar,
24  QStar,
25  Olen,
26  Pblh,
27  TSurf,
28  QSurf,
29  Z0,
30  U10m,
31  V10m,
32  UEast10m,
33  VNorth10m,
34  OLR,
40  SebTsfc,
41  SebQsfc,
42  SebHfx,
43  SebLh,
44  SensFlux,
45  LatenFlux,
46  SurfPres,
63  ShocUStar,
64  ShocOlen,
97 };
SurfaceDiagnosticSource
Definition: ERF_SurfaceDiagnosticSource.H:16

◆ MissingPolicy

Enumerator
AlwaysAvailable 
FillZeroWhenUnavailable 
FillMinus999WhenUnavailable 

◆ SampledCoordinate

Enumerator
ModelIndex 
HeightMSL 
HeightAGL 
Pressure 

◆ SampledFieldID

Enumerator
Rho 
Theta 
Temp 
Pressure 
HeightMSL 
HeightAGL 
Qv 
Qc 
Qi 
Qr 
Qs 
Qg 
UEast 
VNorth 
W 
WindSpeed 
WindDir 

◆ SampledInterpolation

Enumerator
None 
Linear 
33 {
34  None,
35  Linear
36 };
@ None
Definition: ERF_LSM_Types.H:6

Function Documentation

◆ active_condensed_water_path_descriptors()

amrex::Vector< WaterPathDescriptor > plotfile2d::active_condensed_water_path_descriptors ( const SolverChoice &  solver_choice)
70 {
71  amrex::Vector<WaterPathDescriptor> descriptors;
72  descriptors.reserve(MaxCondensedWaterPathComponents);
73 
74  for (const auto& spec : condensed_specs) {
75  const int source_component = source_component_for(spec.id, solver_choice.moisture_indices);
76  if (source_component >= 0) {
77  descriptors.push_back({spec.id, spec.name, source_component});
78  }
79  }
80 
81  return descriptors;
82 }
static constexpr int MaxCondensedWaterPathComponents
Definition: ERF_Plotfile2DWaterPath.H:24
MoistureComponentIndices moisture_indices
Index map of the moisture data carried by the active scheme: conserved-state components for the speci...
Definition: ERF_DataStruct.H:2993

◆ active_lsm_contains()

bool plotfile2d::active_lsm_contains ( const amrex::Vector< std::string > &  active_lsm_names,
const char *  name 
)
139 {
140  return std::find(active_lsm_names.begin(), active_lsm_names.end(), name) !=
141  active_lsm_names.end();
142 }
const char * name
Definition: ERF_Plotfile2DWaterPath.cpp:28

Referenced by available_diagnostic_names().

Here is the caller graph for this function:

◆ available_diagnostic_names() [1/3]

amrex::Vector< std::string > plotfile2d::available_diagnostic_names ( const SolverChoice &  solver_choice)
160 {
161  return available_diagnostic_names(solver_choice, true);
162 }
amrex::Vector< std::string > available_diagnostic_names(const SolverChoice &solver_choice, bool has_surface_layer, const amrex::Vector< std::string > &active_lsm_names)
Definition: ERF_Plotfile2DWaterPath.cpp:173

Referenced by ERF::init_stations(), and ERF::setPlotVariables2D().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ available_diagnostic_names() [2/3]

amrex::Vector< std::string > plotfile2d::available_diagnostic_names ( const SolverChoice &  solver_choice,
bool  has_surface_layer 
)
167 {
168  return available_diagnostic_names(solver_choice, has_surface_layer,
169  amrex::Vector<std::string>{});
170 }
Here is the call graph for this function:

◆ available_diagnostic_names() [3/3]

amrex::Vector< std::string > plotfile2d::available_diagnostic_names ( const SolverChoice &  solver_choice,
bool  has_surface_layer,
const amrex::Vector< std::string > &  active_lsm_names 
)
176 {
177  amrex::Vector<std::string> names;
178  names.reserve(diagnostic_catalog().size());
179  const bool has_noahmp = is_noahmp_active(solver_choice);
180  const bool has_moisture = solver_choice.moisture_type != MoistureType::None;
181 
182  for (const auto& descriptor : diagnostic_catalog()) {
184  !solver_choice.topographicChoice.active()) {
185  continue;
186  }
188  ((!active_lsm_names.empty() &&
189  !active_lsm_contains(active_lsm_names, descriptor.name)) ||
190  (active_lsm_names.empty() && !has_noahmp))) {
191  continue;
192  }
193  if (descriptor.id == DiagnosticID::Temperature2m && !(has_noahmp || has_surface_layer)) {
194  continue;
195  }
196  if ((descriptor.id == DiagnosticID::WaterVaporMixingRatio2m ||
197  descriptor.id == DiagnosticID::NearSurfaceDiagnosticSource) &&
198  !(has_moisture && (has_noahmp || has_surface_layer))) {
199  if (descriptor.id == DiagnosticID::NearSurfaceDiagnosticSource &&
200  (has_noahmp || has_surface_layer)) {
201  names.push_back(descriptor.name);
202  }
203  continue;
204  }
206  if (source_component_for(descriptor.id, solver_choice.moisture_indices) >= 0) {
207  names.push_back(descriptor.name);
208  }
209  continue;
210  }
211 
214  names.push_back(descriptor.name);
215  }
216  continue;
217  }
218 
219  names.push_back(descriptor.name);
220  }
221 
222  if (has_noahmp || !active_lsm_names.empty()) {
223  amrex::ParmParse pp("erf");
224  int nsoil = 4;
225  const auto soil_names = active_lsm_names.empty()
226  ? (pp.queryAdd("lsm_nsoil", nsoil), dynamic_soil_diagnostic_names(nsoil))
227  : dynamic_soil_diagnostic_names(active_lsm_names);
228  names.insert(names.end(), soil_names.begin(), soil_names.end());
229  }
230 
231  return names;
232 }
ParmParse pp("prob")
DiagnosticDescriptor descriptor
Definition: ERF_Plotfile2DCatalog.cpp:119
amrex::Vector< std::string > dynamic_soil_diagnostic_names(int nsoil)
Definition: ERF_Plotfile2DCatalog.cpp:196
bool is_precipitation_accumulation(DiagnosticID id) noexcept
Definition: ERF_Plotfile2DPrecip.cpp:52
bool is_condensed_water_path(DiagnosticID id) noexcept
Definition: ERF_Plotfile2DWaterPath.cpp:54
bool active_lsm_contains(const amrex::Vector< std::string > &active_lsm_names, const char *name)
Definition: ERF_Plotfile2DWaterPath.cpp:137
const amrex::Vector< DiagnosticDescriptor > & diagnostic_catalog()
Definition: ERF_Plotfile2DCatalog.cpp:165
bool is_topographic_radiation_field(DiagnosticID id) noexcept
Definition: ERF_Plotfile2DWaterPath.cpp:144
bool precipitation_diagnostic_available(DiagnosticID id, const MoistureComponentIndices &moisture_indices) noexcept
Definition: ERF_Plotfile2DPrecip.cpp:75
bool is_noahmp_active(const SolverChoice &solver_choice) noexcept
Definition: ERF_Plotfile2DWaterPath.cpp:91
bool is_land_surface_provider_field(DiagnosticID id) noexcept
Definition: ERF_Plotfile2DWaterPath.cpp:101
TopographicShadingChoice topographicChoice
Definition: ERF_DataStruct.H:2624
MoistureType moisture_type
Moisture or microphysics model.
Definition: ERF_DataStruct.H:2942
bool active() const
Definition: ERF_RadStruct.H:113

Referenced by available_diagnostic_names().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ available_sampled_field_names()

amrex::Vector< std::string > plotfile2d::available_sampled_field_names ( const SolverChoice &  solver_choice)
95 {
96  amrex::Vector<std::string> names;
97  names.reserve(sampled_field_catalog().size());
98 
99  for (const auto& descriptor : sampled_field_catalog()) {
100  if (field_is_available(descriptor.id, solver_choice)) {
101  names.push_back(descriptor.name);
102  }
103  }
104 
105  return names;
106 }
const amrex::Vector< SampledFieldDescriptor > & sampled_field_catalog()
Definition: ERF_Plotfile2DSampledField.cpp:76
Here is the call graph for this function:

◆ build_sampled_level_output_descriptors()

amrex::Vector< Plotfile2DOutputDescriptor > plotfile2d::build_sampled_level_output_descriptors ( const std::string &  pp_prefix,
int  which,
const amrex::Vector< std::string > &  static_plot_vars,
const SolverChoice &  solver_choice 
)
496 {
497  amrex::Vector<SampledLevelDefinition> level_sets;
498  for (const auto& level_set_name : parse_requested_sampled_level_sets(pp_prefix, which)) {
499  level_sets.push_back(parse_sampled_level_definition(level_set_name, pp_prefix));
500  }
501 
503  static_plot_vars,
504  solver_choice);
505 }
SampledLevelDefinition parse_sampled_level_definition(const std::string &level_set_name, const std::string &pp_prefix)
Definition: ERF_Plotfile2DSampledLevel.cpp:311
amrex::Vector< std::string > parse_requested_sampled_level_sets(const std::string &pp_prefix, int which)
Definition: ERF_Plotfile2DSampledLevel.cpp:371
amrex::Vector< Plotfile2DOutputDescriptor > build_sampled_level_output_descriptors_from_definitions(const amrex::Vector< SampledLevelDefinition > &level_sets, const amrex::Vector< std::string > &static_plot_vars, const SolverChoice &solver_choice)
Definition: ERF_Plotfile2DSampledLevel.cpp:389

Referenced by ERF::Write2DPlotFile().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_sampled_level_output_descriptors_from_definitions()

amrex::Vector< Plotfile2DOutputDescriptor > plotfile2d::build_sampled_level_output_descriptors_from_definitions ( const amrex::Vector< SampledLevelDefinition > &  level_sets,
const amrex::Vector< std::string > &  static_plot_vars,
const SolverChoice &  solver_choice 
)
393 {
394  amrex::Vector<Plotfile2DOutputDescriptor> descriptors;
395  descriptors.reserve(static_plot_vars.size());
396 
397  std::unordered_set<std::string> output_names;
398 
399  for (const auto& name : static_plot_vars) {
400  const auto* static_descriptor = find_diagnostic(name);
401  if (static_descriptor == nullptr) {
402  static_descriptor = find_dynamic_soil_diagnostic(name);
403  }
404  if (static_descriptor == nullptr) {
405  amrex::Abort("Unknown built-in 2D plotfile diagnostic '" + name + "'");
406  }
407 
408  Plotfile2DOutputDescriptor descriptor;
409  descriptor.name = static_descriptor->name;
410  descriptor.long_name = static_descriptor->long_name;
411  descriptor.units = static_descriptor->units;
412  descriptor.category = static_descriptor->category;
413  descriptor.missing_policy = static_descriptor->missing_policy;
414  descriptor.missing_value =
415  (descriptor.missing_policy == MissingPolicy::FillZeroWhenUnavailable) ? amrex::Real(0.0)
416  : amrex::Real(-999.0);
417  descriptor.static_diagnostic = static_descriptor;
418 
419  if (!output_names.insert(descriptor.name).second) {
420  amrex::Abort(build_duplicate_output_error(descriptor.name));
421  }
422 
423  descriptors.push_back(std::move(descriptor));
424  }
425 
426  for (const auto& level_set : level_sets) {
427  const auto field_selection = select_requested_sampled_fields(level_set.fields, solver_choice);
428  if (!field_selection.unavailable.empty()) {
429  if (amrex::ParallelDescriptor::IOProcessor()) {
430  for (const auto& field_name : field_selection.unavailable) {
431  amrex::Warning(sampled_level_error_prefix(level_set.name, "fields") +
432  "skipping unavailable field '" + field_name + "'");
433  }
434  }
435  }
436 
437  if (field_selection.accepted.empty()) {
438  amrex::Abort(sampled_level_error_prefix(level_set.name, "fields") +
439  "all requested fields unavailable");
440  }
441 
442  const std::string coordinate_units = level_set.units.empty()
443  ? sampled_coordinate_default_units(level_set.coordinate)
444  : level_set.units;
445  const std::string interpolation_name = sampled_interpolation_to_string(level_set.interpolation);
446  const std::string canonical_units =
447  (level_set.coordinate == SampledCoordinate::Pressure && coordinate_units == "hPa") ? "Pa"
448  : coordinate_units;
449 
450  for (const auto& value : level_set.values) {
451  amrex::Real canonical_value = value;
452  if (level_set.coordinate == SampledCoordinate::Pressure &&
453  coordinate_units == "hPa") {
454  canonical_value = value * amrex::Real(100.0);
455  }
456 
457  for (const auto& field : field_selection.accepted) {
458  Plotfile2DOutputDescriptor descriptor;
459  descriptor.name = sampled_output_name(field.name, level_set.coordinate, value, coordinate_units);
460  descriptor.long_name = std::string(field.long_name) + " sampled on " +
461  sampled_coordinate_to_string(level_set.coordinate) + " levels";
462  descriptor.units = field.units;
463  descriptor.category = DiagnosticCategory::SampledLevel;
464  descriptor.missing_policy = MissingPolicy::FillMinus999WhenUnavailable;
465  descriptor.missing_value = level_set.missing_value;
466  descriptor.sampled_level = SampledLevelMetadata{
467  level_set.name,
468  field.name,
469  SampledVerticalCoordinateMetadata{
470  sampled_coordinate_to_string(level_set.coordinate),
471  value,
472  coordinate_units,
473  canonical_value,
474  canonical_units,
475  interpolation_name
476  }
477  };
478 
479  if (!output_names.insert(descriptor.name).second) {
480  amrex::Abort(build_duplicate_output_error(descriptor.name));
481  }
482 
483  descriptors.push_back(std::move(descriptor));
484  }
485  }
486  }
487 
488  return descriptors;
489 }
std::string name
Definition: ERF_Plotfile2DCatalog.cpp:116
std::string units
Definition: ERF_Plotfile2DCatalog.cpp:118
amrex::Real Real
Definition: ERF_ShocInterface.H:19
SampledFieldSelection select_requested_sampled_fields(const amrex::Vector< std::string > &requested, const SolverChoice &solver_choice)
Definition: ERF_Plotfile2DSampledField.cpp:109
const char * sampled_coordinate_to_string(SampledCoordinate coordinate) noexcept
Definition: ERF_Plotfile2DSampledLevel.cpp:119
const DiagnosticDescriptor * find_dynamic_soil_diagnostic(const std::string &name)
Definition: ERF_Plotfile2DCatalog.cpp:227
const char * sampled_interpolation_to_string(SampledInterpolation interpolation) noexcept
Definition: ERF_Plotfile2DSampledLevel.cpp:155
const char * sampled_coordinate_default_units(SampledCoordinate coordinate) noexcept
Definition: ERF_Plotfile2DSampledLevel.cpp:143
std::string sampled_output_name(const std::string &field_name, SampledCoordinate coordinate, amrex::Real value, const std::string &units)
Definition: ERF_Plotfile2DSampledLevel.cpp:238
const DiagnosticDescriptor * find_diagnostic(const std::string &name)
Definition: ERF_Plotfile2DCatalog.cpp:184
std::string sampled_level_error_prefix(const std::string &level_set_name, const std::string &parameter_name)
Definition: ERF_Plotfile2DSampledLevel.cpp:218

Referenced by build_sampled_level_output_descriptors(), and ERF::sample_stations().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ diagnostic_catalog()

const amrex::Vector< DiagnosticDescriptor > & plotfile2d::diagnostic_catalog ( )
166 {
167  return catalog_storage();
168 }

Referenced by available_diagnostic_names(), diagnostic_names(), and find_diagnostic().

Here is the caller graph for this function:

◆ diagnostic_category_to_string()

const char * plotfile2d::diagnostic_category_to_string ( DiagnosticCategory  category)
noexcept
101 {
102  switch (category) {
103  case DiagnosticCategory::Geometry: return "Geometry";
104  case DiagnosticCategory::SurfaceLayer: return "SurfaceLayer";
105  case DiagnosticCategory::Radiation: return "Radiation";
106  case DiagnosticCategory::SurfaceFlux: return "SurfaceFlux";
107  case DiagnosticCategory::PBL: return "PBL";
108  case DiagnosticCategory::SurfaceState: return "SurfaceState";
109  case DiagnosticCategory::Precipitation: return "Precipitation";
110  case DiagnosticCategory::ColumnIntegral: return "ColumnIntegral";
111  case DiagnosticCategory::LandSurface: return "LandSurface";
112  case DiagnosticCategory::SampledLevel: return "SampledLevel";
113  }
114 
115  amrex::Abort("Unhandled DiagnosticCategory in 2D metadata writer");
116  return "";
117 }

◆ diagnostic_names()

amrex::Vector< std::string > plotfile2d::diagnostic_names ( )
172 {
173  amrex::Vector<std::string> names;
174  names.reserve(diagnostic_catalog().size());
175 
176  for (const auto& descriptor : diagnostic_catalog()) {
177  names.push_back(descriptor.name);
178  }
179 
180  return names;
181 }
Here is the call graph for this function:

◆ dynamic_soil_diagnostic_names() [1/2]

amrex::Vector< std::string > plotfile2d::dynamic_soil_diagnostic_names ( const amrex::Vector< std::string > &  active_lsm_names)
215 {
216  amrex::Vector<std::string> names;
217  for (const auto& name : active_lsm_names) {
219  ensure_dynamic_soil_descriptor(name);
220  names.push_back(name);
221  }
222  }
223  return names;
224 }
bool is_dynamic_soil_diagnostic_name(const std::string &name)
Definition: ERF_Plotfile2DCatalog.cpp:236
Here is the call graph for this function:

◆ dynamic_soil_diagnostic_names() [2/2]

amrex::Vector< std::string > plotfile2d::dynamic_soil_diagnostic_names ( int  nsoil)
197 {
198  amrex::Vector<std::string> names;
199  if (nsoil < 1) {
200  return names;
201  }
202  names.reserve(3*nsoil);
203  for (const char* group : {"smois", "sh2o", "tslb"}) {
204  for (int layer = 1; layer <= nsoil; ++layer) {
205  const std::string name = std::string(group) + "_" + std::to_string(layer);
206  ensure_dynamic_soil_descriptor(name);
207  names.push_back(name);
208  }
209  }
210  return names;
211 }

Referenced by available_diagnostic_names().

Here is the caller graph for this function:

◆ escape_json_string()

std::string plotfile2d::escape_json_string ( const std::string &  value)
147 {
148  std::string escaped;
149  escaped.reserve(value.size() + 8);
150 
151  for (unsigned char c : value) {
152  switch (c) {
153  case '\"': escaped += "\\\""; break;
154  case '\\': escaped += "\\\\"; break;
155  case '\n': escaped += "\\n"; break;
156  case '\t': escaped += "\\t"; break;
157  case '\r': escaped += "\\r"; break;
158  default:
159  if (c < 0x20) {
160  append_escaped_codepoint(escaped, c);
161  } else {
162  escaped.push_back(static_cast<char>(c));
163  }
164  break;
165  }
166  }
167 
168  return escaped;
169 }

◆ fill_component_from_klevel() [1/2]

void plotfile2d::fill_component_from_klevel ( amrex::MultiFab &  dst,
int  dst_comp,
const amrex::MultiFab &  src,
int  src_k,
int  src_comp = 0 
)

◆ fill_component_from_klevel() [2/2]

void plotfile2d::fill_component_from_klevel ( MultiFab &  dst,
int  dst_comp,
const MultiFab &  src,
int  src_k,
int  src_comp 
)
44 {
45  // Iterate over dst because it defines the 2D output component layout. The
46  // source must be box-compatible with dst on the horizontal tile covered by
47  // each MFIter.
48 #ifdef _OPENMP
49 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
50 #endif
51  for (MFIter mfi(dst, TilingIfNotGPU()); mfi.isValid(); ++mfi)
52  {
53  const Box& bx = mfi.tilebox();
54  const auto& dst_arr = dst.array(mfi);
55  const auto& src_arr = src.const_array(mfi);
56 
57  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
58  dst_arr(i, j, k, dst_comp) = src_arr(i, j, src_k, src_comp);
59  });
60  }
61 }
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})

Referenced by fill_component_from_klevel_or_value().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fill_component_from_klevel_or_value() [1/2]

void plotfile2d::fill_component_from_klevel_or_value ( amrex::MultiFab &  dst,
int  dst_comp,
const amrex::MultiFab *  src,
int  src_k,
amrex::Real  missing_value,
int  src_comp = 0 
)

◆ fill_component_from_klevel_or_value() [2/2]

void plotfile2d::fill_component_from_klevel_or_value ( MultiFab &  dst,
int  dst_comp,
const MultiFab *  src,
int  src_k,
Real  missing_value,
int  src_comp 
)
70 {
71  if (src) {
72  fill_component_from_klevel(dst, dst_comp, *src, src_k, src_comp);
73  } else {
74  fill_component_with_value(dst, dst_comp, missing_value);
75  }
76 }
void fill_component_from_klevel(MultiFab &dst, int dst_comp, const MultiFab &src, int src_k, int src_comp)
Definition: ERF_Plotfile2DFill.cpp:39
void fill_component_with_value(MultiFab &dst, int dst_comp, Real value)
Definition: ERF_Plotfile2DFill.cpp:33

Referenced by ERF::FillPlot2DVars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fill_component_with_value() [1/2]

void plotfile2d::fill_component_with_value ( amrex::MultiFab &  dst,
int  dst_comp,
amrex::Real  value 
)

◆ fill_component_with_value() [2/2]

void plotfile2d::fill_component_with_value ( MultiFab &  dst,
int  dst_comp,
Real  value 
)

◆ fill_condensed_water_paths() [1/2]

void plotfile2d::fill_condensed_water_paths ( amrex::MultiFab &  dst,
const amrex::MultiFab &  cons,
const SelectedWaterPathComponents &  selected,
const amrex::Geometry &  geom,
const amrex::MultiFab &  detJ 
)

◆ fill_condensed_water_paths() [2/2]

void plotfile2d::fill_condensed_water_paths ( MultiFab &  dst,
const MultiFab &  cons,
const SelectedWaterPathComponents &  selected,
const Geometry &  geom,
const MultiFab &  detJ 
)
265 {
266  if (selected.n == 0) {
267  return;
268  }
269 
270  // Validate selected components on the host before device kernels use them.
271  AMREX_ALWAYS_ASSERT(selected.n >= 0);
273  for (int n = 0; n < selected.n; ++n) {
274  AMREX_ALWAYS_ASSERT(selected.dst_comp[n] >= 0);
275  AMREX_ALWAYS_ASSERT(selected.dst_comp[n] < dst.nComp());
276  AMREX_ALWAYS_ASSERT(selected.src_comp[n] >= 0);
277  AMREX_ALWAYS_ASSERT(selected.src_comp[n] < cons.nComp());
278  }
279 
280  for (int n = 0; n < selected.n; ++n) {
281  dst.setVal(0., selected.dst_comp[n], 1, 0);
282  }
283 
284  const auto& dx = geom.CellSizeArray();
285 
286  //
287  // NOTE: TileNoZ, not TilingIfNotGPU: the atomic adds accumulate a whole column into
288  // dst_arr(i,j,0), so if the grid were tiled in z the tiles covering one column
289  // would add into the same entry concurrently. On the host HostDevice::Atomic::Add
290  // is "#pragma omp atomic" -- atomic but unordered -- so the column sum would then
291  // depend on thread scheduling in its last bits. Keeping each column inside a
292  // single tile makes the k accumulation serial and the result independent of both
293  // the tile size and the thread count.
294  //
295 #ifdef _OPENMP
296 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
297 #endif
298  for (MFIter mfi(cons, TileNoZ()); mfi.isValid(); ++mfi)
299  {
300  const Box& bx = mfi.tilebox();
301  const auto dst_arr = dst.array(mfi);
302  const auto src_arr = cons.const_array(mfi);
303 
304  if (SolverChoice::mesh_type == MeshType::ConstantDz) {
305  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
306  for (int n = 0; n < selected.n; ++n) {
307  amrex::HostDevice::Atomic::Add(
308  &dst_arr(i, j, 0, selected.dst_comp[n]),
309  src_arr(i, j, k, selected.src_comp[n]));
310  }
311  });
312  } else {
313  const auto& detJ_arr = detJ.const_array(mfi);
314  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
315  const amrex::Real metric = detJ_arr(i, j, k);
316  for (int n = 0; n < selected.n; ++n) {
317  amrex::HostDevice::Atomic::Add(
318  &dst_arr(i, j, 0, selected.dst_comp[n]),
319  src_arr(i, j, k, selected.src_comp[n]) * metric);
320  }
321  });
322  }
323  }
324 
325  for (int n = 0; n < selected.n; ++n) {
326  dst.mult(dx[2], selected.dst_comp[n], 1, 0);
327  }
328 }
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
AMREX_FORCE_INLINE amrex::IntVect TileNoZ()
Definition: ERF_TileNoZ.H:11
@ cons
Definition: ERF_IndexDefines.H:254
static MeshType mesh_type
Vertical mesh representation.
Definition: ERF_DataStruct.H:2604

Referenced by ERF::FillPlot2DVars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fill_land_surface_component_from_klevel_or_missing() [1/2]

void plotfile2d::fill_land_surface_component_from_klevel_or_missing ( amrex::MultiFab &  dst,
int  dst_comp,
const amrex::MultiFab *  src,
int  src_k,
amrex::Real  missing_value 
)

◆ fill_land_surface_component_from_klevel_or_missing() [2/2]

void plotfile2d::fill_land_surface_component_from_klevel_or_missing ( MultiFab &  dst,
int  dst_comp,
const MultiFab *  src,
int  src_k,
Real  missing_value 
)
84 {
85  if (!src) {
86  fill_component_with_value(dst, dst_comp, missing_value);
87  return;
88  }
89 
90 #ifdef _OPENMP
91 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
92 #endif
93  for (MFIter mfi(dst, TilingIfNotGPU()); mfi.isValid(); ++mfi)
94  {
95  const Box& bx = mfi.tilebox();
96  const auto& dst_arr = dst.array(mfi);
97  const auto& src_arr = src->const_array(mfi);
98  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
99  const Real value = src_arr(i, j, src_k, 0);
100  dst_arr(i, j, k, dst_comp) = is_valid_land_surface_value(value)
101  ? value : missing_value;
102  });
103  }
104 }

Referenced by ERF::FillPlot2DVars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fill_latent_heat_flux_from_klevel_or_missing() [1/2]

void plotfile2d::fill_latent_heat_flux_from_klevel_or_missing ( amrex::MultiFab &  dst,
int  dst_comp,
const amrex::MultiFab *  src,
int  src_k,
amrex::Real  missing_value 
)

◆ fill_latent_heat_flux_from_klevel_or_missing() [2/2]

void plotfile2d::fill_latent_heat_flux_from_klevel_or_missing ( MultiFab &  dst,
int  dst_comp,
const MultiFab *  src,
int  src_k,
Real  missing_value 
)
143 {
144  if (!src) {
145  fill_component_with_value(dst, dst_comp, missing_value);
146  return;
147  }
148 
149 #ifdef _OPENMP
150 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
151 #endif
152  for (MFIter mfi(dst, TilingIfNotGPU()); mfi.isValid(); ++mfi)
153  {
154  // Keep unit conversion in the surface-flux diagnostic helper so this
155  // mechanical layer does not duplicate physical constants or units.
156  const Box& bx = mfi.tilebox();
157  const auto& dst_arr = dst.array(mfi);
158  const auto& src_arr = src->const_array(mfi);
159 
160  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
161  dst_arr(i, j, k, dst_comp) =
163  src_arr(i, j, src_k, 0));
164  });
165  }
166 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real latent_heat_flux_wm2_from_rhoqv_flux(amrex::Real rhoqv_flux) noexcept
Definition: ERF_SurfaceFluxDiagnostics.H:36

Referenced by fill_seb_turbulent_flux(), and ERF::FillPlot2DVars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fill_precipitation_accumulations() [1/2]

void plotfile2d::fill_precipitation_accumulations ( amrex::MultiFab &  dst,
const SurfacePrecipAccumulationSources &  sources,
const SelectedSurfacePrecipAccumulationComponents &  selected,
const int  klo 
)

◆ fill_precipitation_accumulations() [2/2]

void plotfile2d::fill_precipitation_accumulations ( MultiFab &  dst,
const SurfacePrecipAccumulationSources &  sources,
const SelectedSurfacePrecipAccumulationComponents &  selected,
const int  klo 
)
148 {
149  if (selected.n == 0) {
150  return;
151  }
152 
153  AMREX_ALWAYS_ASSERT(selected.n >= 0);
155 
156  for (int n = 0; n < selected.n; ++n) {
157  AMREX_ALWAYS_ASSERT(selected.dst_comp[n] >= 0);
158  AMREX_ALWAYS_ASSERT(selected.dst_comp[n] < dst.nComp());
159  dst.setVal(0.0, selected.dst_comp[n], 1, 0);
160  }
161 
162  if (!surface_precip_has_any_source(sources)) {
163  return;
164  }
165 
166  // Normalize scheme-native precipitation accumulators to kg/m^2 at the
167  // output boundary, then build the derived total and frozen fields from the
168  // normalized species values.
169  const SurfacePrecipAccumulationSource* anchor = first_available_source(sources);
170  AMREX_ALWAYS_ASSERT(anchor != nullptr);
171  const MultiFab& anchor_mf = *anchor->accum;
172  const bool has_total_source = surface_precip_has_source(sources.total);
173  const bool has_rain_source = surface_precip_has_source(sources.rain);
174  const bool has_snow_source = surface_precip_has_source(sources.snow);
175  const bool has_graupel_source = surface_precip_has_source(sources.graupel);
176  const bool has_hail_source = surface_precip_has_source(sources.hail);
177  const amrex::Real total_factor = sources.total.native_to_kg_m2;
178  const amrex::Real rain_factor = sources.rain.native_to_kg_m2;
179  const amrex::Real snow_factor = sources.snow.native_to_kg_m2;
180  const amrex::Real graupel_factor = sources.graupel.native_to_kg_m2;
181  const amrex::Real hail_factor = sources.hail.native_to_kg_m2;
182 
183  for (MFIter mfi(anchor_mf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
184  {
185  const Box& bx = mfi.tilebox();
186  const auto dst_arr = dst.array(mfi);
187  const auto total_arr = has_total_source ? sources.total.accum->const_array(mfi) : Array4<const Real>{};
188  const auto rain_arr = has_rain_source ? sources.rain.accum->const_array(mfi) : Array4<const Real>{};
189  const auto snow_arr = has_snow_source ? sources.snow.accum->const_array(mfi) : Array4<const Real>{};
190  const auto graupel_arr = has_graupel_source ? sources.graupel.accum->const_array(mfi) : Array4<const Real>{};
191  const auto hail_arr = has_hail_source ? sources.hail.accum->const_array(mfi) : Array4<const Real>{};
192 
193  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
194  {
195  if (k != klo) {
196  return;
197  }
198 
199  const amrex::Real total_source =
200  has_total_source ? total_arr(i, j, k, 0) * total_factor : amrex::Real(0.0);
201  const amrex::Real rain_source =
202  has_rain_source ? rain_arr(i, j, k, 0) * rain_factor : amrex::Real(0.0);
203  const amrex::Real snow =
204  has_snow_source ? snow_arr(i, j, k, 0) * snow_factor : amrex::Real(0.0);
205  const amrex::Real graupel =
206  has_graupel_source ? graupel_arr(i, j, k, 0) * graupel_factor : amrex::Real(0.0);
207  const amrex::Real hail =
208  has_hail_source ? hail_arr(i, j, k, 0) * hail_factor : amrex::Real(0.0);
209  const amrex::Real frozen = snow + graupel + hail;
210  const amrex::Real total = has_total_source ? total_source : rain_source + frozen;
211  // Total-plus-frozen-subset schemes derive rain as total - frozen.
212  // Clamp to zero to avoid negative output from roundoff or small
213  // scheme inconsistencies.
214  const amrex::Real rain = has_rain_source ? rain_source
215  : amrex::max(amrex::Real(0.0), total - frozen);
216 
217  for (int n = 0; n < selected.n; ++n) {
218  switch (selected.id[n]) {
219  case DiagnosticID::PrecipTotalAccum:
220  dst_arr(i, j, 0, selected.dst_comp[n]) = total;
221  break;
222  case DiagnosticID::PrecipRainAccum:
223  dst_arr(i, j, 0, selected.dst_comp[n]) = rain;
224  break;
225  case DiagnosticID::PrecipSnowAccum:
226  dst_arr(i, j, 0, selected.dst_comp[n]) = snow;
227  break;
228  case DiagnosticID::PrecipGraupelAccum:
229  dst_arr(i, j, 0, selected.dst_comp[n]) = graupel;
230  break;
231  case DiagnosticID::PrecipHailAccum:
232  dst_arr(i, j, 0, selected.dst_comp[n]) = hail;
233  break;
234  case DiagnosticID::PrecipFrozenAccum:
235  dst_arr(i, j, 0, selected.dst_comp[n]) = frozen;
236  break;
237  default:
238  break;
239  }
240  }
241  });
242  }
243 }
const int klo
Definition: ERF_InitCustomPert_KE.H:9
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool surface_precip_has_source(const SurfacePrecipAccumulationSource &src) noexcept
Definition: ERF_SurfacePrecipitation.H:43
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool surface_precip_has_any_source(const SurfacePrecipAccumulationSources &src) noexcept
Definition: ERF_SurfacePrecipitation.H:61
@ graupel
Definition: ERF_NOAHMP_Fields.H:140
@ rain
Definition: ERF_NOAHMP_Fields.H:138
@ total
Definition: ERF_NOAHMP_Fields.H:137
@ hail
Definition: ERF_NOAHMP_Fields.H:141
@ snow
Definition: ERF_NOAHMP_Fields.H:139
static constexpr int MaxSurfacePrecipAccumulationComponents
Definition: ERF_Plotfile2DPrecip.H:27
Definition: ERF_SurfacePrecipitation.H:20
const amrex::MultiFab * accum
Definition: ERF_SurfacePrecipitation.H:21
amrex::Real native_to_kg_m2
Definition: ERF_SurfacePrecipitation.H:22
SurfacePrecipAccumulationSource rain
Definition: ERF_SurfacePrecipitation.H:36
SurfacePrecipAccumulationSource snow
Definition: ERF_SurfacePrecipitation.H:37
SurfacePrecipAccumulationSource hail
Definition: ERF_SurfacePrecipitation.H:39
SurfacePrecipAccumulationSource total
Definition: ERF_SurfacePrecipitation.H:35
SurfacePrecipAccumulationSource graupel
Definition: ERF_SurfacePrecipitation.H:38

Referenced by ERF::FillPlot2DVars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fill_sampled_level_component() [1/2]

void plotfile2d::fill_sampled_level_component ( amrex::MultiFab &  dst,
int  dst_comp,
const Plotfile2DOutputDescriptor &  descriptor,
const amrex::MultiFab &  cons,
const amrex::MultiFab *  z_phys_cc,
const amrex::MultiFab &  z_phys_nd,
bool  have_z_phys_cc,
const MoistureComponentIndices &  moisture_indices,
int  klo,
int  khi,
const SampledWindSources &  wind_sources = {},
const amrex::MultiFab *  p_hse = nullptr 
)

◆ fill_sampled_level_component() [2/2]

void plotfile2d::fill_sampled_level_component ( MultiFab &  dst,
int  dst_comp,
const Plotfile2DOutputDescriptor &  descriptor,
const MultiFab &  cons,
const MultiFab *  z_phys_cc,
const MultiFab &  z_phys_nd,
bool  have_z_phys_cc,
const MoistureComponentIndices &  moisture_indices,
int  klo,
int  khi,
const SampledWindSources &  wind_sources,
const MultiFab *  p_hse 
)
170 {
171  const auto* sampled = descriptor.sampled_level ? &*descriptor.sampled_level : nullptr;
172  if (sampled == nullptr) {
173  fill_component_with_value(dst, dst_comp, descriptor.missing_value);
174  return;
175  }
176 
177  const auto* field_descriptor = find_sampled_field(sampled->source_field);
178  if (field_descriptor == nullptr) {
179  Abort("Unknown sampled-level source field '" + sampled->source_field + "'");
180  }
181 
182  const auto coordinate = sampled_coordinate_from_string(sampled->vertical_coordinate.type);
183  const auto field_id = field_descriptor->id;
184  const Real target = sampled->vertical_coordinate.canonical_value;
185  const int target_k = static_cast<int>(std::nearbyint(target));
186  const Real missing_value = descriptor.missing_value;
187  const bool is_wind_field = sampled_field_is_wind(field_id);
188  const bool have_rotation = (wind_sources.cos_alpha != nullptr) || (wind_sources.sin_alpha != nullptr);
189  // The caller passes the base state pressure only for an anelastic run, in which case
190  // that -- not the compressible EOS -- is the pressure of the system
191  const bool use_hse_pressure = (p_hse != nullptr);
192 
193  if (is_wind_field) {
194  if (wind_sources.xvel == nullptr || wind_sources.yvel == nullptr || wind_sources.zvel == nullptr) {
195  Abort("Sampled-level wind field '" + sampled->source_field + "' requires xvel, yvel, and zvel sources");
196  }
197  if ((wind_sources.cos_alpha == nullptr) != (wind_sources.sin_alpha == nullptr)) {
198  Abort("Sampled-level wind field '" + sampled->source_field + "' requires both cos_alpha and sin_alpha when rotation is supplied");
199  }
200  }
201 
202 #ifdef _OPENMP
203 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
204 #endif
205  for (MFIter mfi(dst, TilingIfNotGPU()); mfi.isValid(); ++mfi)
206  {
207  const Box& bx = mfi.tilebox();
208  const auto& dst_arr = dst.array(mfi);
209  const auto& cons_arr = cons.const_array(mfi);
210  const auto& z_phys_nd_arr = z_phys_nd.const_array(mfi);
211  const auto& z_phys_cc_arr = have_z_phys_cc && z_phys_cc != nullptr
212  ? z_phys_cc->const_array(mfi)
213  : cons.const_array(mfi);
214  const auto& p_hse_arr = use_hse_pressure ? p_hse->const_array(mfi) : cons.const_array(mfi);
215  const auto& xvel_arr = is_wind_field ? wind_sources.xvel->const_array(mfi) : cons.const_array(mfi);
216  const auto& yvel_arr = is_wind_field ? wind_sources.yvel->const_array(mfi) : cons.const_array(mfi);
217  const auto& zvel_arr = is_wind_field ? wind_sources.zvel->const_array(mfi) : cons.const_array(mfi);
218  const auto& cos_alpha_arr = have_rotation ? wind_sources.cos_alpha->const_array(mfi) : cons.const_array(mfi);
219  const auto& sin_alpha_arr = have_rotation ? wind_sources.sin_alpha->const_array(mfi) : cons.const_array(mfi);
220 
221  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
222  if (coordinate == SampledCoordinate::ModelIndex) {
223  if (target_k < klo || target_k > khi) {
224  dst_arr(i, j, k, dst_comp) = missing_value;
225  return;
226  }
227 
228  if (is_wind_field) {
229  const SampledEarthWind wind = earth_wind_at_cell_center(
230  i, j, target_k, xvel_arr, yvel_arr, zvel_arr, cos_alpha_arr, sin_alpha_arr,
231  have_rotation);
232  dst_arr(i, j, k, dst_comp) = wind_field_from_earth_wind(field_id, wind, missing_value);
233  } else {
234  dst_arr(i, j, k, dst_comp) =
235  sampled_field_value(field_id, cons_arr, z_phys_cc_arr, z_phys_nd_arr, p_hse_arr,
236  have_z_phys_cc, use_hse_pressure, i, j, target_k, moisture_indices);
237  }
238  return;
239  }
240 
241  const auto bracket = find_sampled_bracket(coordinate, target, klo, khi, i, j,
242  cons_arr, z_phys_cc_arr, z_phys_nd_arr, p_hse_arr,
243  have_z_phys_cc, use_hse_pressure, moisture_indices);
244  if (!bracket.found) {
245  dst_arr(i, j, k, dst_comp) = missing_value;
246  return;
247  }
248 
249  const Real coord_lo =
250  sampled_field_value((coordinate == SampledCoordinate::HeightMSL)
251  ? SampledFieldID::HeightMSL
252  : (coordinate == SampledCoordinate::HeightAGL)
253  ? SampledFieldID::HeightAGL
254  : SampledFieldID::Pressure,
255  cons_arr, z_phys_cc_arr, z_phys_nd_arr, p_hse_arr,
256  have_z_phys_cc, use_hse_pressure, i, j, bracket.klo, moisture_indices);
257  const Real coord_hi =
258  sampled_field_value((coordinate == SampledCoordinate::HeightMSL)
259  ? SampledFieldID::HeightMSL
260  : (coordinate == SampledCoordinate::HeightAGL)
261  ? SampledFieldID::HeightAGL
262  : SampledFieldID::Pressure,
263  cons_arr, z_phys_cc_arr, z_phys_nd_arr, p_hse_arr,
264  have_z_phys_cc, use_hse_pressure, i, j, bracket.khi, moisture_indices);
265  if (is_wind_field) {
266  const SampledEarthWind wind_lo = earth_wind_at_cell_center(
267  i, j, bracket.klo, xvel_arr, yvel_arr, zvel_arr, cos_alpha_arr, sin_alpha_arr,
268  have_rotation);
269  if (bracket.klo == bracket.khi) {
270  dst_arr(i, j, k, dst_comp) = wind_field_from_earth_wind(field_id, wind_lo, missing_value);
271  return;
272  }
273 
274  const SampledEarthWind wind_hi = earth_wind_at_cell_center(
275  i, j, bracket.khi, xvel_arr, yvel_arr, zvel_arr, cos_alpha_arr, sin_alpha_arr,
276  have_rotation);
277  SampledEarthWind wind_interp;
278  wind_interp.u_east = linear_interpolate(wind_lo.u_east, wind_hi.u_east, coord_lo, coord_hi, target);
279  wind_interp.v_north = linear_interpolate(wind_lo.v_north, wind_hi.v_north, coord_lo, coord_hi, target);
280  wind_interp.w = linear_interpolate(wind_lo.w, wind_hi.w, coord_lo, coord_hi, target);
281  dst_arr(i, j, k, dst_comp) = wind_field_from_earth_wind(field_id, wind_interp, missing_value);
282  } else {
283  const Real field_lo =
284  sampled_field_value(field_id, cons_arr, z_phys_cc_arr, z_phys_nd_arr, p_hse_arr,
285  have_z_phys_cc, use_hse_pressure, i, j, bracket.klo, moisture_indices);
286  if (bracket.klo == bracket.khi) {
287  dst_arr(i, j, k, dst_comp) = field_lo;
288  return;
289  }
290 
291  const Real field_hi =
292  sampled_field_value(field_id, cons_arr, z_phys_cc_arr, z_phys_nd_arr, p_hse_arr,
293  have_z_phys_cc, use_hse_pressure, i, j, bracket.khi, moisture_indices);
294  dst_arr(i, j, k, dst_comp) =
295  linear_interpolate(field_lo, field_hi, coord_lo, coord_hi, target);
296  }
297  });
298  }
299 }
const int khi
Definition: ERF_InitCustomPert_Bubble.H:25
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real sampled_field_value(SampledFieldID field_id, const amrex::Array4< const amrex::Real > &cons_arr, const amrex::Array4< const amrex::Real > &z_phys_cc_arr, const amrex::Array4< const amrex::Real > &z_phys_nd_arr, const amrex::Array4< const amrex::Real > &p_hse_arr, bool have_z_phys_cc, bool use_hse_pressure, int i, int j, int k, const MoistureComponentIndices &moisture_indices) noexcept
Definition: ERF_Plotfile2DSampledField.H:95
SampledCoordinate sampled_coordinate_from_string(const std::string &value)
Definition: ERF_Plotfile2DSampledLevel.cpp:165
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool sampled_field_is_wind(SampledFieldID field_id) noexcept
Definition: ERF_Plotfile2DSampledField.H:70
const SampledFieldDescriptor * find_sampled_field(const std::string &name)
Definition: ERF_Plotfile2DSampledField.cpp:82
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real linear_interpolate(amrex::Real lo_value, amrex::Real hi_value, amrex::Real lo_coord, amrex::Real hi_coord, amrex::Real target) noexcept
Definition: ERF_Plotfile2DInterpolator.H:46

Referenced by ERF::FillPlot2DVars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fill_sensible_heat_flux_from_klevel_or_missing() [1/2]

void plotfile2d::fill_sensible_heat_flux_from_klevel_or_missing ( amrex::MultiFab &  dst,
int  dst_comp,
const amrex::MultiFab *  src,
int  src_k,
amrex::Real  missing_value 
)

◆ fill_sensible_heat_flux_from_klevel_or_missing() [2/2]

void plotfile2d::fill_sensible_heat_flux_from_klevel_or_missing ( MultiFab &  dst,
int  dst_comp,
const MultiFab *  src,
int  src_k,
Real  missing_value 
)
112 {
113  if (!src) {
114  fill_component_with_value(dst, dst_comp, missing_value);
115  return;
116  }
117 
118 #ifdef _OPENMP
119 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
120 #endif
121  for (MFIter mfi(dst, TilingIfNotGPU()); mfi.isValid(); ++mfi)
122  {
123  // Keep unit conversion in the surface-flux diagnostic helper so this
124  // mechanical layer does not duplicate physical constants or units.
125  const Box& bx = mfi.tilebox();
126  const auto& dst_arr = dst.array(mfi);
127  const auto& src_arr = src->const_array(mfi);
128 
129  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
130  dst_arr(i, j, k, dst_comp) =
132  src_arr(i, j, src_k, 0));
133  });
134  }
135 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real sensible_heat_flux_wm2_from_rhotheta_flux(amrex::Real rhotheta_flux) noexcept
Definition: ERF_SurfaceFluxDiagnostics.H:29

Referenced by fill_seb_turbulent_flux(), and ERF::FillPlot2DVars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_diagnostic()

const DiagnosticDescriptor * plotfile2d::find_diagnostic ( const std::string &  name)
185 {
186  for (const auto& descriptor : diagnostic_catalog()) {
187  if (name == descriptor.name) {
188  return &descriptor;
189  }
190  }
191 
192  return nullptr;
193 }

Referenced by build_sampled_level_output_descriptors_from_definitions(), ERF::FillPlot2DVars(), format_2d_metadata_json(), ERF::init_stations(), is_condensed_water_path_name(), is_precipitation_accumulation_name(), selected_condensed_water_path_components(), and selected_precipitation_accumulation_components().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_dynamic_soil_diagnostic()

const DiagnosticDescriptor * plotfile2d::find_dynamic_soil_diagnostic ( const std::string &  name)
228 {
230  return nullptr;
231  }
232  return ensure_dynamic_soil_descriptor(name);
233 }

Referenced by build_sampled_level_output_descriptors_from_definitions(), ERF::FillPlot2DVars(), format_2d_metadata_json(), and ERF::init_stations().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_sampled_field()

const SampledFieldDescriptor * plotfile2d::find_sampled_field ( const std::string &  name)
83 {
84  for (const auto& descriptor : sampled_field_catalog()) {
85  if (name == descriptor.name) {
86  return &descriptor;
87  }
88  }
89 
90  return nullptr;
91 }

Referenced by fill_sampled_level_component(), and select_requested_sampled_fields().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ format_2d_component_count_error()

std::string plotfile2d::format_2d_component_count_error ( int  lev,
int  filled,
int  expected 
)
90 {
91  std::ostringstream os;
92  os << "Write2DPlotFile internal error at level " << lev
93  << ": filled " << filled
94  << " components but expected " << expected
95  << ". The 2D plot variable list and fill blocks are inconsistent.";
96  return os.str();
97 }

Referenced by ERF::FillPlot2DVars().

Here is the caller graph for this function:

◆ format_2d_metadata_json() [1/2]

std::string plotfile2d::format_2d_metadata_json ( const amrex::Vector< Plotfile2DOutputDescriptor > &  descriptors)
210 {
211  // Native AMReX 2D plotfiles get a metadata sidecar for the selected
212  // output variables only. The writer formats catalog metadata and sampled-
213  // level metadata; it does not compute diagnostics or encode runtime
214  // source selection.
215  std::ostringstream os;
216  os << "{\n";
217  os << " \"format_version\": 2,\n";
218  os << " \"kind\": \"ERF 2D plotfile metadata\",\n";
219  os << " \"n_variables\": " << static_cast<int>(descriptors.size()) << ",\n";
220  os << " \"variables\": [\n";
221 
222  for (int i = 0; i < static_cast<int>(descriptors.size()); ++i) {
223  append_variable_record(os, descriptors[i], i, i == static_cast<int>(descriptors.size()) - 1);
224  }
225 
226  os << " ]\n";
227  os << "}\n";
228  return os.str();
229 }

◆ format_2d_metadata_json() [2/2]

std::string plotfile2d::format_2d_metadata_json ( const amrex::Vector< std::string > &  varnames)
179 {
180  amrex::Vector<Plotfile2DOutputDescriptor> descriptors;
181  descriptors.reserve(varnames.size());
182 
183  for (const auto& name : varnames) {
184  const auto* static_descriptor = find_diagnostic(name);
185  if (static_descriptor == nullptr) {
186  static_descriptor = find_dynamic_soil_diagnostic(name);
187  }
188  if (static_descriptor == nullptr) {
189  amrex::Abort("2D metadata requested for unknown diagnostic '" + name + "'");
190  }
191 
192  Plotfile2DOutputDescriptor descriptor;
193  descriptor.name = static_descriptor->name;
194  descriptor.long_name = static_descriptor->long_name;
195  descriptor.units = static_descriptor->units;
196  descriptor.category = static_descriptor->category;
197  descriptor.missing_policy = static_descriptor->missing_policy;
198  descriptor.missing_value =
199  (descriptor.missing_policy == MissingPolicy::FillZeroWhenUnavailable) ? amrex::Real(0.0)
200  : amrex::Real(-999.0);
201  descriptor.static_diagnostic = static_descriptor;
202  descriptors.push_back(std::move(descriptor));
203  }
204 
205  return format_2d_metadata_json(descriptors);
206 }
std::string format_2d_metadata_json(const amrex::Vector< Plotfile2DOutputDescriptor > &descriptors)
Definition: ERF_Plotfile2DMetadata.cpp:209

Referenced by write_2d_metadata_json().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ format_invalid_2d_stream_error()

std::string plotfile2d::format_invalid_2d_stream_error ( int  which)
101 {
102  std::ostringstream os;
103  os << "Write2DPlotFile received invalid stream index " << which
104  << "; expected 1 or 2.";
105  return os.str();
106 }

◆ format_plot2d_parameter_name()

std::string plotfile2d::format_plot2d_parameter_name ( const std::string &  pp_prefix,
const std::string &  parameter_name 
)
80 {
81  if (pp_prefix.empty()) {
82  return parameter_name;
83  }
84 
85  return pp_prefix + "." + parameter_name;
86 }

Referenced by ERF::setPlotVariables2D().

Here is the caller graph for this function:

◆ format_unavailable_2d_plot_var_warning()

std::string plotfile2d::format_unavailable_2d_plot_var_warning ( const std::string &  parameter_name,
const std::string &  unavailable_name,
const amrex::Vector< std::string > &  available_names 
)
68 {
69  std::ostringstream os;
70  os << "WARNING: Requested 2D plot variable '" << unavailable_name
71  << "' from '" << parameter_name
72  << "' is not available and will be skipped. Available built-in 2D plot variables are: "
73  << join_names(available_names) << ".";
74  return os.str();
75 }

◆ is_condensed_water_path()

bool plotfile2d::is_condensed_water_path ( DiagnosticID  id)
noexcept
55 {
56  switch (id) {
57  case DiagnosticID::IntegratedQc:
58  case DiagnosticID::IntegratedQi:
59  case DiagnosticID::IntegratedQr:
60  case DiagnosticID::IntegratedQs:
61  case DiagnosticID::IntegratedQg:
62  return true;
63  default:
64  return false;
65  }
66 }

Referenced by available_diagnostic_names(), is_condensed_water_path_name(), and selected_condensed_water_path_components().

Here is the caller graph for this function:

◆ is_condensed_water_path_name()

bool plotfile2d::is_condensed_water_path_name ( const std::string &  name)
86 {
87  const auto* descriptor = find_diagnostic(name);
89 }
Here is the call graph for this function:

◆ is_dynamic_soil_diagnostic_name()

bool plotfile2d::is_dynamic_soil_diagnostic_name ( const std::string &  name)
237 {
238  const auto underscore = name.find('_');
239  if (underscore == std::string::npos) {
240  return false;
241  }
242  const std::string group = name.substr(0, underscore);
243  if (group != "smois" && group != "sh2o" && group != "tslb") {
244  return false;
245  }
246  try {
247  std::size_t parsed = 0;
248  const int layer = std::stoi(name.substr(underscore + 1), &parsed);
249  return parsed == name.size() - underscore - 1 && layer > 0;
250  } catch (...) {
251  return false;
252  }
253 }

Referenced by dynamic_soil_diagnostic_names(), and find_dynamic_soil_diagnostic().

Here is the caller graph for this function:

◆ is_land_surface_provider_field()

bool plotfile2d::is_land_surface_provider_field ( DiagnosticID  id)
noexcept
102 {
103  switch (id) {
104  case DiagnosticID::LandSurfaceTsfC:
105  case DiagnosticID::LandSurfaceEmissivity:
106  case DiagnosticID::LandSurfaceAlbDirVis:
107  case DiagnosticID::LandSurfaceAlbDirNir:
108  case DiagnosticID::LandSurfaceAlbDifVis:
109  case DiagnosticID::LandSurfaceAlbDifNir:
110  case DiagnosticID::LandSurfaceCosZenith:
111  case DiagnosticID::LandSurfaceSwFluxDn:
112  case DiagnosticID::LandSurfaceSwFluxDnDirVis:
113  case DiagnosticID::LandSurfaceSwFluxDnDirNir:
114  case DiagnosticID::LandSurfaceSwFluxDnDifVis:
115  case DiagnosticID::LandSurfaceSwFluxDnDifNir:
116  case DiagnosticID::LandSurfaceLwFluxDn:
117  case DiagnosticID::LandSurfaceGrdflx:
118  case DiagnosticID::LandSurfaceFira:
119  case DiagnosticID::LandSurfaceSav:
120  case DiagnosticID::LandSurfaceSag:
121  case DiagnosticID::LandSurfaceAlbedo:
122  case DiagnosticID::LandSurfaceSfcrunoff:
123  case DiagnosticID::LandSurfaceUdrunoff:
124  case DiagnosticID::LandSurfaceSnow:
125  case DiagnosticID::LandSurfaceSnowh:
126  case DiagnosticID::NoahmpTemperature2mVegetated:
127  case DiagnosticID::NoahmpTemperature2mBare:
128  case DiagnosticID::NoahmpWaterVaporMixingRatio2mVegetated:
129  case DiagnosticID::NoahmpWaterVaporMixingRatio2mBare:
130  case DiagnosticID::NoahmpVegetationFraction:
131  return true;
132  default:
133  return false;
134  }
135 }

Referenced by available_diagnostic_names().

Here is the caller graph for this function:

◆ is_noahmp_active()

bool plotfile2d::is_noahmp_active ( const SolverChoice &  solver_choice)
noexcept
92 {
93 #ifdef ERF_USE_NOAHMP
94  return solver_choice.lsm_type == LandSurfaceType::NOAHMP;
95 #else
96  amrex::ignore_unused(solver_choice);
97  return false;
98 #endif
99 }
LandSurfaceType lsm_type
Land-surface model.
Definition: ERF_DataStruct.H:2953

Referenced by available_diagnostic_names().

Here is the caller graph for this function:

◆ is_precipitation_accumulation()

bool plotfile2d::is_precipitation_accumulation ( DiagnosticID  id)
noexcept
53 {
54  switch (id) {
55  case DiagnosticID::PrecipTotalAccum:
56  case DiagnosticID::PrecipRainAccum:
57  case DiagnosticID::PrecipSnowAccum:
58  case DiagnosticID::PrecipGraupelAccum:
59  case DiagnosticID::PrecipHailAccum:
60  case DiagnosticID::PrecipFrozenAccum:
61  return true;
62  default:
63  return false;
64  }
65 }

Referenced by available_diagnostic_names(), is_precipitation_accumulation_name(), and selected_precipitation_accumulation_components().

Here is the caller graph for this function:

◆ is_precipitation_accumulation_name()

bool plotfile2d::is_precipitation_accumulation_name ( const std::string &  name)
69 {
70  const auto* descriptor = find_diagnostic(name);
72 }
Here is the call graph for this function:

◆ is_topographic_radiation_field()

bool plotfile2d::is_topographic_radiation_field ( DiagnosticID  id)
noexcept
145 {
146  switch (id) {
147  case DiagnosticID::TopographicShadow:
148  case DiagnosticID::TerrainDirectFactor:
149  case DiagnosticID::TerrainIncidence:
150  case DiagnosticID::UnshadedSwFluxDn:
151  case DiagnosticID::TerrainSwFluxDn:
152  return true;
153  default:
154  return false;
155  }
156 }

Referenced by available_diagnostic_names().

Here is the caller graph for this function:

◆ linear_interpolate()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real plotfile2d::linear_interpolate ( amrex::Real  lo_value,
amrex::Real  hi_value,
amrex::Real  lo_coord,
amrex::Real  hi_coord,
amrex::Real  target 
)
noexcept
51 {
52  if (hi_coord == lo_coord) {
53  return lo_value;
54  }
55 
56  const amrex::Real weight = (target - lo_coord) / (hi_coord - lo_coord);
57  return lo_value + weight * (hi_value - lo_value);
58 }

Referenced by fill_sampled_level_component().

Here is the caller graph for this function:

◆ metadata_json_filename()

std::string plotfile2d::metadata_json_filename ( const std::string &  plotfilename)
173 {
174  return plotfilename + "/2DMetadata.json";
175 }

Referenced by write_2d_metadata_json().

Here is the caller graph for this function:

◆ missing_policy_to_string()

const char * plotfile2d::missing_policy_to_string ( MissingPolicy  policy)
noexcept
121 {
122  switch (policy) {
123  case MissingPolicy::AlwaysAvailable: return "AlwaysAvailable";
124  case MissingPolicy::FillZeroWhenUnavailable: return "FillZeroWhenUnavailable";
125  case MissingPolicy::FillMinus999WhenUnavailable: return "FillMinus999WhenUnavailable";
126  }
127 
128  amrex::Abort("Unhandled MissingPolicy in 2D metadata writer");
129  return "";
130 }

◆ missing_value_json()

std::string plotfile2d::missing_value_json ( MissingPolicy  policy)
134 {
135  switch (policy) {
136  case MissingPolicy::AlwaysAvailable: return "null";
137  case MissingPolicy::FillZeroWhenUnavailable: return "0";
138  case MissingPolicy::FillMinus999WhenUnavailable: return "-999";
139  }
140 
141  amrex::Abort("Unhandled MissingPolicy in 2D metadata writer");
142  return {};
143 }

◆ parse_requested_sampled_level_sets()

amrex::Vector< std::string > plotfile2d::parse_requested_sampled_level_sets ( const std::string &  pp_prefix,
int  which 
)
373 {
374  amrex::Vector<std::string> names;
375  amrex::ParmParse pp(pp_prefix);
376 
377  const std::string param_name = "plot2d_level_sets_" + std::to_string(which);
378  if (!pp.contains(param_name.c_str())) {
379  return names;
380  }
381 
382  const int n_sets = pp.countval(param_name.c_str());
383  names.resize(n_sets);
384  pp.getarr(param_name.c_str(), names, 0, n_sets);
385  return names;
386 }

Referenced by build_sampled_level_output_descriptors().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_sampled_level_definition()

SampledLevelDefinition plotfile2d::parse_sampled_level_definition ( const std::string &  level_set_name,
const std::string &  pp_prefix 
)
313 {
314  SampledLevelDefinition level_set;
315  level_set.name = level_set_name;
316 
317  amrex::ParmParse pp(pp_prefix);
318  const std::string base = "plot2d.level_set." + level_set_name + ".";
319 
320  std::string coordinate_value;
321  if (!pp.queryAdd((base + "coordinate").c_str(), coordinate_value)) {
322  amrex::Abort(build_missing_field_error(level_set_name, "coordinate"));
323  }
324  const std::string coordinate_error =
325  validate_sampled_coordinate_string(level_set_name, coordinate_value);
326  if (!coordinate_error.empty()) {
327  amrex::Abort(coordinate_error);
328  }
329  level_set.coordinate = sampled_coordinate_from_string(coordinate_value);
330 
331  if (pp.queryAdd((base + "units").c_str(), level_set.units) == 0) {
332  level_set.units = sampled_coordinate_default_units(level_set.coordinate);
333  }
334 
335  std::string interpolation_value;
336  if (pp.queryAdd((base + "interpolation").c_str(), interpolation_value) == 0) {
337  level_set.interpolation =
339  } else {
340  level_set.interpolation = sampled_interpolation_from_string(interpolation_value);
341  }
342 
343  // level_set.missing_value already carries the -999 default from its declaration,
344  // so there is nothing to do when the key is absent; queryAdd records the
345  // effective value in the job info without a presence test.
346  pp.queryAdd((base + "missing_value").c_str(), level_set.missing_value);
347 
348  int n_values = pp.countval((base + "values").c_str());
349  if (n_values <= 0) {
350  amrex::Abort(build_missing_field_error(level_set_name, "values"));
351  }
352  level_set.values.resize(n_values);
353  pp.getarr((base + "values").c_str(), level_set.values, 0, n_values);
354 
355  int n_fields = pp.countval((base + "fields").c_str());
356  if (n_fields <= 0) {
357  amrex::Abort(build_missing_field_error(level_set_name, "fields"));
358  }
359  level_set.fields.resize(n_fields);
360  pp.getarr((base + "fields").c_str(), level_set.fields, 0, n_fields);
361 
362  const std::string error = validate_sampled_level_definition(level_set);
363  if (!error.empty()) {
364  amrex::Abort(error);
365  }
366 
367  return level_set;
368 }
std::string validate_sampled_coordinate_string(const std::string &level_set_name, const std::string &value)
Definition: ERF_Plotfile2DSampledLevel.cpp:199
std::string validate_sampled_level_definition(const SampledLevelDefinition &level_set)
Definition: ERF_Plotfile2DSampledLevel.cpp:250
SampledInterpolation sampled_interpolation_from_string(const std::string &value)
Definition: ERF_Plotfile2DSampledLevel.cpp:185
const char * sampled_coordinate_default_interpolation(SampledCoordinate coordinate) noexcept
Definition: ERF_Plotfile2DSampledLevel.cpp:149

Referenced by build_sampled_level_output_descriptors().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ precipitation_diagnostic_available()

bool plotfile2d::precipitation_diagnostic_available ( DiagnosticID  id,
const MoistureComponentIndices &  moisture_indices 
)
noexcept
77 {
78  const bool has_any_precip = has_any_precip_component(moisture_indices);
79 
80  switch (id) {
81  case DiagnosticID::PrecipTotalAccum:
82  case DiagnosticID::PrecipFrozenAccum:
83  return has_any_precip;
84  case DiagnosticID::PrecipRainAccum:
85  return has_rain_component(moisture_indices);
86  case DiagnosticID::PrecipSnowAccum:
87  return has_snow_component(moisture_indices);
88  case DiagnosticID::PrecipGraupelAccum:
89  return has_graupel_component(moisture_indices);
90  case DiagnosticID::PrecipHailAccum:
91  return false;
92  default:
93  return false;
94  }
95 }

Referenced by available_diagnostic_names().

Here is the caller graph for this function:

◆ sampled_coordinate_default_interpolation()

const char * plotfile2d::sampled_coordinate_default_interpolation ( SampledCoordinate  coordinate)
noexcept
150 {
151  return coordinate_interpolation_default(coordinate);
152 }

Referenced by parse_sampled_level_definition(), and validate_sampled_level_definition().

Here is the caller graph for this function:

◆ sampled_coordinate_default_units()

const char * plotfile2d::sampled_coordinate_default_units ( SampledCoordinate  coordinate)
noexcept
144 {
145  return coordinate_units_default(coordinate);
146 }

Referenced by build_sampled_level_output_descriptors_from_definitions(), parse_sampled_level_definition(), and validate_sampled_level_definition().

Here is the caller graph for this function:

◆ sampled_coordinate_from_string()

SampledCoordinate plotfile2d::sampled_coordinate_from_string ( const std::string &  value)
166 {
167  if (string_iequals(value, "model_index")) {
168  return SampledCoordinate::ModelIndex;
169  }
170  if (string_iequals(value, "height_msl")) {
171  return SampledCoordinate::HeightMSL;
172  }
173  if (string_iequals(value, "height_agl")) {
174  return SampledCoordinate::HeightAGL;
175  }
176  if (string_iequals(value, "pressure")) {
177  return SampledCoordinate::Pressure;
178  }
179 
180  amrex::Abort("Unknown sampled-level coordinate '" + value + "'");
181  return SampledCoordinate::ModelIndex;
182 }

Referenced by fill_sampled_level_component(), and parse_sampled_level_definition().

Here is the caller graph for this function:

◆ sampled_coordinate_tag()

const char * plotfile2d::sampled_coordinate_tag ( SampledCoordinate  coordinate)
noexcept
132 {
133  switch (coordinate) {
134  case SampledCoordinate::ModelIndex: return "k";
135  case SampledCoordinate::HeightMSL: return "z_msl";
136  case SampledCoordinate::HeightAGL: return "z_agl";
137  case SampledCoordinate::Pressure: return "p";
138  }
139  return "unknown";
140 }

Referenced by sampled_output_name().

Here is the caller graph for this function:

◆ sampled_coordinate_to_string()

const char * plotfile2d::sampled_coordinate_to_string ( SampledCoordinate  coordinate)
noexcept
120 {
121  switch (coordinate) {
122  case SampledCoordinate::ModelIndex: return "model_index";
123  case SampledCoordinate::HeightMSL: return "height_msl";
124  case SampledCoordinate::HeightAGL: return "height_agl";
125  case SampledCoordinate::Pressure: return "pressure";
126  }
127  return "unknown";
128 }

Referenced by build_sampled_level_output_descriptors_from_definitions(), and validate_sampled_level_definition().

Here is the caller graph for this function:

◆ sampled_field_catalog()

const amrex::Vector< SampledFieldDescriptor > & plotfile2d::sampled_field_catalog ( )
77 {
78  return field_catalog_storage();
79 }

Referenced by available_sampled_field_names(), and find_sampled_field().

Here is the caller graph for this function:

◆ sampled_field_id_to_string()

std::string plotfile2d::sampled_field_id_to_string ( SampledFieldID  field_id)
138 {
139  return sampled_field_name(field_id);
140 }
const char * sampled_field_name(SampledFieldID field_id) noexcept
Definition: ERF_Plotfile2DSampledField.H:158
Here is the call graph for this function:

◆ sampled_field_is_scalar_state()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool plotfile2d::sampled_field_is_scalar_state ( SampledFieldID  field_id)
noexcept
86 {
87  return !sampled_field_is_wind(field_id);
88 }
Here is the call graph for this function:

◆ sampled_field_is_wind()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool plotfile2d::sampled_field_is_wind ( SampledFieldID  field_id)
noexcept
71 {
72  switch (field_id) {
73  case SampledFieldID::UEast:
74  case SampledFieldID::VNorth:
75  case SampledFieldID::W:
76  case SampledFieldID::WindSpeed:
77  case SampledFieldID::WindDir:
78  return true;
79  default:
80  return false;
81  }
82 }

Referenced by fill_sampled_level_component(), and sampled_field_is_scalar_state().

Here is the caller graph for this function:

◆ sampled_field_name()

const char* plotfile2d::sampled_field_name ( SampledFieldID  field_id)
inlinenoexcept
159 {
160  switch (field_id) {
161  case SampledFieldID::Rho: return "rho";
162  case SampledFieldID::Theta: return "theta";
163  case SampledFieldID::Temp: return "temp";
164  case SampledFieldID::Pressure: return "pressure";
165  case SampledFieldID::HeightMSL: return "height_msl";
166  case SampledFieldID::HeightAGL: return "height_agl";
167  case SampledFieldID::Qv: return "qv";
168  case SampledFieldID::Qc: return "qc";
169  case SampledFieldID::Qi: return "qi";
170  case SampledFieldID::Qr: return "qr";
171  case SampledFieldID::Qs: return "qs";
172  case SampledFieldID::Qg: return "qg";
173  case SampledFieldID::UEast: return "u_east";
174  case SampledFieldID::VNorth: return "v_north";
175  case SampledFieldID::W: return "w";
176  case SampledFieldID::WindSpeed: return "wind_speed";
177  case SampledFieldID::WindDir: return "wind_dir";
178  }
179 
180  return "unknown";
181 }

Referenced by sampled_field_id_to_string().

Here is the caller graph for this function:

◆ sampled_field_value()

AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real plotfile2d::sampled_field_value ( SampledFieldID  field_id,
const amrex::Array4< const amrex::Real > &  cons_arr,
const amrex::Array4< const amrex::Real > &  z_phys_cc_arr,
const amrex::Array4< const amrex::Real > &  z_phys_nd_arr,
const amrex::Array4< const amrex::Real > &  p_hse_arr,
bool  have_z_phys_cc,
bool  use_hse_pressure,
int  i,
int  j,
int  k,
const MoistureComponentIndices &  moisture_indices 
)
noexcept
104 {
105  const amrex::Real rho = cons_arr(i, j, k, Rho_comp);
106  const bool has_moisture = (moisture_indices.qv >= 0);
107  // Microphysical fields are sampled as mixing ratios. The conserved state
108  // stores rho*q, so field evaluation divides by rho before interpolation.
109  const amrex::Real qv_for_eos = has_moisture
110  ? cons_arr(i, j, k, moisture_indices.qv) / rho
111  : amrex::Real(0.0);
112 
113  switch (field_id) {
114  case SampledFieldID::Rho:
115  return rho;
117  return cons_arr(i, j, k, RhoTheta_comp) / rho;
118  case SampledFieldID::Temp:
119  return getTgivenRandRTh(rho, cons_arr(i, j, k, RhoTheta_comp), qv_for_eos);
120  case SampledFieldID::Pressure:
121  // In an anelastic run the compressible EOS does not give the pressure of the
122  // system -- rho is the (frozen) base state density, so getPgivenRTh would
123  // respond to theta perturbations. We use the base state pressure instead,
124  // just as the 3-D plotfile path does.
125  return use_hse_pressure ? p_hse_arr(i, j, k)
126  : getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp), qv_for_eos);
127  case SampledFieldID::HeightMSL:
128  if (have_z_phys_cc) {
129  return z_phys_cc_arr(i, j, k);
130  }
131  return Compute_Z_AtCellCenter(i, j, k, z_phys_nd_arr);
132  case SampledFieldID::HeightAGL:
133  return Compute_Zrel_AtCellCenter(i, j, k, z_phys_nd_arr);
134  case SampledFieldID::Qv:
135  return has_moisture ? cons_arr(i, j, k, moisture_indices.qv) / rho : amrex::Real(0.0);
136  case SampledFieldID::Qc:
137  return (moisture_indices.qc >= 0) ? cons_arr(i, j, k, moisture_indices.qc) / rho : amrex::Real(0.0);
138  case SampledFieldID::Qi:
139  return (moisture_indices.qi >= 0) ? cons_arr(i, j, k, moisture_indices.qi) / rho : amrex::Real(0.0);
140  case SampledFieldID::Qr:
141  return (moisture_indices.qr >= 0) ? cons_arr(i, j, k, moisture_indices.qr) / rho : amrex::Real(0.0);
142  case SampledFieldID::Qs:
143  return (moisture_indices.qs >= 0) ? cons_arr(i, j, k, moisture_indices.qs) / rho : amrex::Real(0.0);
144  case SampledFieldID::Qg:
145  return (moisture_indices.qg >= 0) ? cons_arr(i, j, k, moisture_indices.qg) / rho : amrex::Real(0.0);
146  case SampledFieldID::UEast:
147  case SampledFieldID::VNorth:
148  case SampledFieldID::W:
149  case SampledFieldID::WindSpeed:
150  case SampledFieldID::WindDir:
151  return amrex::Real(0.0);
152  }
153 
154  return amrex::Real(0.0);
155 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getTgivenRandRTh(const amrex::Real rho, const amrex::Real rhotheta, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:46
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getPgivenRTh(const amrex::Real rhotheta, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:81
#define Rho_comp
Definition: ERF_IndexDefines.H:53
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:54
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_Z_AtCellCenter(const int &i, const int &j, const int &k, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:716
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real Compute_Zrel_AtCellCenter(const int &i, const int &j, const int &k, const amrex::Array4< const amrex::Real > &z_nd)
Definition: ERF_TerrainMetrics.H:762
@ rho
Definition: ERF_Kessler.H:25
int qs
snow
Definition: ERF_DataStruct.H:266
int qr
rain
Definition: ERF_DataStruct.H:265
int qi
cloud ice
Definition: ERF_DataStruct.H:264
int qv
water vapor
Definition: ERF_DataStruct.H:262
int qc
cloud liquid water
Definition: ERF_DataStruct.H:263
int qg
graupel
Definition: ERF_DataStruct.H:267

Referenced by fill_sampled_level_component().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sampled_interpolation_from_string()

SampledInterpolation plotfile2d::sampled_interpolation_from_string ( const std::string &  value)
186 {
187  if (string_iequals(value, "none")) {
189  }
190  if (string_iequals(value, "linear")) {
191  return SampledInterpolation::Linear;
192  }
193 
194  amrex::Abort("Unknown sampled-level interpolation '" + value + "'");
196 }

Referenced by parse_sampled_level_definition().

Here is the caller graph for this function:

◆ sampled_interpolation_to_string()

const char * plotfile2d::sampled_interpolation_to_string ( SampledInterpolation  interpolation)
noexcept
156 {
157  switch (interpolation) {
158  case SampledInterpolation::None: return "none";
159  case SampledInterpolation::Linear: return "linear";
160  }
161  return "unknown";
162 }

Referenced by build_sampled_level_output_descriptors_from_definitions().

Here is the caller graph for this function:

◆ sampled_level_error_prefix()

std::string plotfile2d::sampled_level_error_prefix ( const std::string &  level_set_name,
const std::string &  parameter_name 
)
220 {
221  std::ostringstream os;
222  os << "Sampled-level definition '" << level_set_name << "' parameter '"
223  << parameter_name << "': ";
224  return os.str();
225 }

Referenced by build_sampled_level_output_descriptors_from_definitions(), validate_sampled_coordinate_string(), and validate_sampled_level_definition().

Here is the caller graph for this function:

◆ sampled_level_value_tag()

std::string plotfile2d::sampled_level_value_tag ( amrex::Real  value,
const std::string &  units 
)
229 {
230  std::string tag = format_numeric_tag(value);
231  if (!units.empty() && units != "1") {
232  tag += units;
233  }
234  return tag;
235 }

Referenced by sampled_output_name().

Here is the caller graph for this function:

◆ sampled_output_name()

std::string plotfile2d::sampled_output_name ( const std::string &  field_name,
SampledCoordinate  coordinate,
amrex::Real  value,
const std::string &  units 
)
242 {
243  std::ostringstream os;
244  os << field_name << "_" << sampled_coordinate_tag(coordinate) << "_"
245  << sampled_level_value_tag(value, units);
246  return os.str();
247 }
const char * sampled_coordinate_tag(SampledCoordinate coordinate) noexcept
Definition: ERF_Plotfile2DSampledLevel.cpp:131
std::string sampled_level_value_tag(amrex::Real value, const std::string &units)
Definition: ERF_Plotfile2DSampledLevel.cpp:228

Referenced by build_sampled_level_output_descriptors_from_definitions().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sampled_target_is_bracketed()

AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool plotfile2d::sampled_target_is_bracketed ( amrex::Real  target,
amrex::Real  c0,
amrex::Real  c1 
)
noexcept
40 {
41  return (c0 <= target && target <= c1) ||
42  (c1 <= target && target <= c0);
43 }
real(c_double), private c1
Definition: ERF_module_mp_morr_two_moment.F90:212

◆ select_requested_plot_variables()

PlotVariableSelection plotfile2d::select_requested_plot_variables ( const amrex::Vector< std::string > &  requested,
const amrex::Vector< std::string > &  available 
)
36 {
37  PlotVariableSelection selection;
38 
39  std::unordered_set<std::string> requested_set(requested.begin(), requested.end());
40  std::unordered_set<std::string> available_set(available.begin(), available.end());
41  std::unordered_set<std::string> seen_unavailable;
42 
43  // Preserve the canonical built-in ordering so component indices remain
44  // stable even when the user lists variables in a different order.
45  for (const auto& name : available) {
46  if (requested_set.count(name) != 0) {
47  selection.accepted.push_back(name);
48  }
49  }
50 
51  // Report each missing name once, in the order it was requested. The caller
52  // uses these names to emit warnings without duplicating messages for repeats.
53  for (const auto& name : requested) {
54  if (available_set.count(name) == 0) {
55  if (seen_unavailable.insert(name).second) {
56  selection.unavailable.push_back(name);
57  }
58  }
59  }
60 
61  return selection;
62 }

Referenced by ERF::init_stations(), and ERF::setPlotVariables2D().

Here is the caller graph for this function:

◆ select_requested_sampled_fields()

SampledFieldSelection plotfile2d::select_requested_sampled_fields ( const amrex::Vector< std::string > &  requested,
const SolverChoice &  solver_choice 
)
111 {
112  SampledFieldSelection selection;
113 
114  std::unordered_set<std::string> seen;
115 
116  for (const auto& name : requested) {
117  const auto* descriptor = find_sampled_field(name);
118  if (descriptor == nullptr) {
119  selection.unavailable.push_back(name);
120  continue;
121  }
122 
123  if (!field_is_available(descriptor->id, solver_choice)) {
124  selection.unavailable.push_back(name);
125  continue;
126  }
127 
128  if (seen.insert(name).second) {
129  selection.accepted.push_back(*descriptor);
130  }
131  }
132 
133  return selection;
134 }

Referenced by build_sampled_level_output_descriptors_from_definitions().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ selected_condensed_water_path_components()

SelectedWaterPathComponents plotfile2d::selected_condensed_water_path_components ( const amrex::Vector< std::string > &  plot_var_names,
const SolverChoice &  solver_choice 
)
237 {
238  SelectedWaterPathComponents selected;
239 
240  for (int dst_comp = 0; dst_comp < static_cast<int>(plot_var_names.size()); ++dst_comp) {
241  const auto* descriptor = find_diagnostic(plot_var_names[dst_comp]);
243  continue;
244  }
245 
246  const int src_comp = source_component_for(descriptor->id, solver_choice.moisture_indices);
247  if (src_comp < 0) {
248  continue;
249  }
250 
251  selected.dst_comp[selected.n] = dst_comp;
252  selected.src_comp[selected.n] = src_comp;
253  ++selected.n;
254  }
255 
256  return selected;
257 }

Referenced by ERF::FillPlot2DVars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ selected_precipitation_accumulation_components()

SelectedSurfacePrecipAccumulationComponents plotfile2d::selected_precipitation_accumulation_components ( const amrex::Vector< std::string > &  plot_var_names,
const SurfacePrecipAccumulationSources &  sources 
)
100 {
101  SelectedSurfacePrecipAccumulationComponents selected;
102 
103  for (int dst_comp = 0; dst_comp < static_cast<int>(plot_var_names.size()); ++dst_comp) {
104  const auto* descriptor = find_diagnostic(plot_var_names[dst_comp]);
106  continue;
107  }
108 
109  const bool has_total = surface_precip_has_total_source(sources);
110  const bool has_rain = surface_precip_has_source(sources.rain);
111 
112  const bool source_available =
113  (descriptor->id == DiagnosticID::PrecipTotalAccum)
115  : (descriptor->id == DiagnosticID::PrecipRainAccum)
116  ? (has_rain || has_total)
117  : (descriptor->id == DiagnosticID::PrecipSnowAccum)
119  : (descriptor->id == DiagnosticID::PrecipGraupelAccum)
121  : (descriptor->id == DiagnosticID::PrecipHailAccum)
123  : (descriptor->id == DiagnosticID::PrecipFrozenAccum)
125  : false;
126 
127  if (!source_available) {
128  continue;
129  }
130 
131  // The selection holds at most one entry per precipitation diagnostic; a list with
132  // repeated names would otherwise write past the end of these fixed-size arrays
134  "too many precipitation accumulation components requested (is a name repeated?)");
135  selected.dst_comp[selected.n] = dst_comp;
136  selected.id[selected.n] = descriptor->id;
137  ++selected.n;
138  }
139 
140  return selected;
141 }
AMREX_ALWAYS_ASSERT_WITH_MESSAGE(axis >=0 &&axis< AMREX_SPACEDIM, "prob.axis must be 0, 1 or 2")
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool surface_precip_has_total_source(const SurfacePrecipAccumulationSources &src) noexcept
Definition: ERF_SurfacePrecipitation.H:49
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool surface_precip_has_any_frozen_source(const SurfacePrecipAccumulationSources &src) noexcept
Definition: ERF_SurfacePrecipitation.H:71

Referenced by ERF::FillPlot2DVars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ use_native_shoc_consumed_flux_source()

AMREX_FORCE_INLINE bool plotfile2d::use_native_shoc_consumed_flux_source ( bool  native_shoc_owns_scalar_fluxes,
bool  native_shoc_has_consumed_flux_diagnostics,
bool  host_flux_field_available 
)
noexcept
26 {
27  return native_shoc_owns_scalar_fluxes &&
28  native_shoc_has_consumed_flux_diagnostics &&
29  host_flux_field_available;
30 }

Referenced by ERF::surface_flux_sources().

Here is the caller graph for this function:

◆ validate_sampled_coordinate_string()

std::string plotfile2d::validate_sampled_coordinate_string ( const std::string &  level_set_name,
const std::string &  value 
)
201 {
202  if (string_iequals(value, "isentropic")) {
203  return sampled_level_error_prefix(level_set_name, "coordinate") +
204  "isentropic output needs a crossing policy";
205  }
206 
207  if (string_iequals(value, "model_index") ||
208  string_iequals(value, "height_msl") ||
209  string_iequals(value, "height_agl") ||
210  string_iequals(value, "pressure")) {
211  return {};
212  }
213 
214  return "Unknown sampled-level coordinate '" + value + "'";
215 }

Referenced by parse_sampled_level_definition().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_sampled_level_definition()

std::string plotfile2d::validate_sampled_level_definition ( const SampledLevelDefinition &  level_set)
251 {
252  if (level_set.name.empty()) {
253  return "Sampled-level definition name is empty";
254  }
255 
256  if (level_set.fields.empty()) {
257  return sampled_level_error_prefix(level_set.name, "fields") + "missing fields";
258  }
259 
260  if (level_set.values.empty()) {
261  return sampled_level_error_prefix(level_set.name, "values") + "missing values";
262  }
263 
264  const char* default_units = sampled_coordinate_default_units(level_set.coordinate);
265  if (level_set.units.empty() || level_set.units == default_units) {
266  // valid
267  } else if (level_set.coordinate == SampledCoordinate::Pressure &&
268  (level_set.units == "Pa" || level_set.units == "hPa")) {
269  // valid
270  } else {
271  return sampled_level_error_prefix(level_set.name, "units") +
272  "unsupported units '" + level_set.units + "'";
273  }
274 
275  const char* default_interp = sampled_coordinate_default_interpolation(level_set.coordinate);
276  if (level_set.interpolation == SampledInterpolation::None) {
277  if (std::string(default_interp) != "none") {
278  return sampled_level_error_prefix(level_set.name, "interpolation") +
279  "unsupported interpolation 'none' for coordinate '" +
280  sampled_coordinate_to_string(level_set.coordinate) + "'";
281  }
282  } else if (level_set.interpolation == SampledInterpolation::Linear) {
283  if (std::string(default_interp) == "none" && level_set.coordinate == SampledCoordinate::ModelIndex) {
284  return sampled_level_error_prefix(level_set.name, "interpolation") +
285  "unsupported interpolation 'linear' for coordinate 'model_index'";
286  }
287  }
288 
289  if (level_set.coordinate == SampledCoordinate::ModelIndex) {
290  for (const auto value : level_set.values) {
291  const auto rounded = std::nearbyint(value);
292  if (std::abs(value - rounded) > amrex::Real(1.0e-12)) {
293  return sampled_level_error_prefix(level_set.name, "values") +
294  "non-integer model_index value '" + std::to_string(value) + "'";
295  }
296  }
297  }
298 
299  std::unordered_set<std::string> unique_fields(level_set.fields.begin(), level_set.fields.end());
300  const auto n_unique_fields = static_cast<int>(unique_fields.size());
301  const auto n_requested_fields = static_cast<int>(level_set.fields.size());
302  if (n_unique_fields != n_requested_fields) {
303  return sampled_level_error_prefix(level_set.name, "fields") +
304  build_duplicate_output_error(level_set.name);
305  }
306 
307  return {};
308 }

Referenced by parse_sampled_level_definition().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_2d_metadata_json() [1/2]

void plotfile2d::write_2d_metadata_json ( const std::string &  plotfilename,
const amrex::Vector< Plotfile2DOutputDescriptor > &  descriptors 
)
256 {
257  if (!amrex::ParallelDescriptor::IOProcessor()) {
258  return;
259  }
260 
261  const std::string filename = metadata_json_filename(plotfilename);
262  std::ofstream outfile(filename, std::ios::out | std::ios::trunc);
263  if (!outfile.good()) {
264  amrex::FileOpenFailed(filename);
265  }
266 
267  outfile << format_2d_metadata_json(descriptors);
268  if (!outfile.good()) {
269  amrex::FileOpenFailed(filename);
270  }
271 }
std::string metadata_json_filename(const std::string &plotfilename)
Definition: ERF_Plotfile2DMetadata.cpp:172
Here is the call graph for this function:

◆ write_2d_metadata_json() [2/2]

void plotfile2d::write_2d_metadata_json ( const std::string &  plotfilename,
const amrex::Vector< std::string > &  varnames 
)
234 {
235  // Native AMReX 2D plotfiles write this sidecar next to the plotfile
236  // directory on the I/O processor only.
237  if (!amrex::ParallelDescriptor::IOProcessor()) {
238  return;
239  }
240 
241  const std::string filename = metadata_json_filename(plotfilename);
242  std::ofstream outfile(filename, std::ios::out | std::ios::trunc);
243  if (!outfile.good()) {
244  amrex::FileOpenFailed(filename);
245  }
246 
247  outfile << format_2d_metadata_json(varnames);
248  if (!outfile.good()) {
249  amrex::FileOpenFailed(filename);
250  }
251 }

Referenced by ERF::Write2DPlotFile().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ MaxCondensedWaterPathComponents

constexpr int plotfile2d::MaxCondensedWaterPathComponents = 5
staticconstexpr

◆ MaxSurfacePrecipAccumulationComponents

constexpr int plotfile2d::MaxSurfacePrecipAccumulationComponents = 6
staticconstexpr