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 , OLR , SensFlux ,
  LatenFlux , SurfPres , 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 ,
  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 DiagnosticDescriptorfind_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 DiagnosticDescriptorfind_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)
 
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 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 SampledFieldDescriptorfind_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, bool have_z_phys_cc, 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< Plotfile2DOutputDescriptorbuild_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< Plotfile2DOutputDescriptorbuild_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< WaterPathDescriptoractive_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)
 
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 

◆ DiagnosticID

Enumerator
ZSurf 
LandMask 
MapFac 
LatM 
LonM 
UStar 
WStar 
TStar 
QStar 
Olen 
Pblh 
TSurf 
QSurf 
Z0 
OLR 
SensFlux 
LatenFlux 
SurfPres 
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 
NoahmpTemperature2mVegetated 
NoahmpTemperature2mBare 
NoahmpWaterVaporMixingRatio2mVegetated 
NoahmpWaterVaporMixingRatio2mBare 
NoahmpVegetationFraction 
Temperature2m 
WaterVaporMixingRatio2m 
NearSurfaceDiagnosticSource 
DynamicSoilBase 
12 {
13  ZSurf,
14  LandMask,
15  MapFac,
16  LatM,
17  LonM,
18  UStar,
19  WStar,
20  TStar,
21  QStar,
22  Olen,
23  Pblh,
24  TSurf,
25  QSurf,
26  Z0,
27  OLR,
28  SensFlux,
29  LatenFlux,
30  SurfPres,
46  ShocUStar,
47  ShocOlen,
78 };
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 
WindSpeed 
WindDir 

◆ SampledInterpolation

Enumerator
None 
Linear 

Function Documentation

◆ active_condensed_water_path_descriptors()

amrex::Vector< WaterPathDescriptor > plotfile2d::active_condensed_water_path_descriptors ( const SolverChoice solver_choice)
66 {
67  amrex::Vector<WaterPathDescriptor> descriptors;
68  descriptors.reserve(MaxCondensedWaterPathComponents);
69 
70  for (const auto& spec : condensed_specs) {
71  const int source_component = source_component_for(spec.id, solver_choice.moisture_indices);
72  if (source_component >= 0) {
73  descriptors.push_back({spec.id, spec.name, source_component});
74  }
75  }
76 
77  return descriptors;
78 }
static constexpr int MaxCondensedWaterPathComponents
Definition: ERF_Plotfile2DWaterPath.H:21
MoistureComponentIndices moisture_indices
Definition: ERF_DataStruct.H:1441

◆ active_lsm_contains()

bool plotfile2d::active_lsm_contains ( const amrex::Vector< std::string > &  active_lsm_names,
const char *  name 
)
133 {
134  return std::find(active_lsm_names.begin(), active_lsm_names.end(), name) !=
135  active_lsm_names.end();
136 }
const char * name
Definition: ERF_Plotfile2DWaterPath.cpp:24

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)
140 {
141  return available_diagnostic_names(solver_choice, true);
142 }
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:153

Referenced by 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 
)
147 {
148  return available_diagnostic_names(solver_choice, has_surface_layer,
149  amrex::Vector<std::string>{});
150 }
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 
)
156 {
157  amrex::Vector<std::string> names;
158  names.reserve(diagnostic_catalog().size());
159  const bool has_noahmp = is_noahmp_active(solver_choice);
160  const bool has_moisture = solver_choice.moisture_type != MoistureType::None;
161 
162  for (const auto& descriptor : diagnostic_catalog()) {
164  ((!active_lsm_names.empty() &&
165  !active_lsm_contains(active_lsm_names, descriptor.name)) ||
166  (active_lsm_names.empty() && !has_noahmp))) {
167  continue;
168  }
169  if (descriptor.id == DiagnosticID::Temperature2m && !(has_noahmp || has_surface_layer)) {
170  continue;
171  }
172  if ((descriptor.id == DiagnosticID::WaterVaporMixingRatio2m ||
173  descriptor.id == DiagnosticID::NearSurfaceDiagnosticSource) &&
174  !(has_moisture && (has_noahmp || has_surface_layer))) {
175  if (descriptor.id == DiagnosticID::NearSurfaceDiagnosticSource &&
176  (has_noahmp || has_surface_layer)) {
177  names.push_back(descriptor.name);
178  }
179  continue;
180  }
182  if (source_component_for(descriptor.id, solver_choice.moisture_indices) >= 0) {
183  names.push_back(descriptor.name);
184  }
185  continue;
186  }
187 
190  names.push_back(descriptor.name);
191  }
192  continue;
193  }
194 
195  names.push_back(descriptor.name);
196  }
197 
198  if (has_noahmp || !active_lsm_names.empty()) {
199  amrex::ParmParse pp("erf");
200  int nsoil = 4;
201  const auto soil_names = active_lsm_names.empty()
202  ? (pp.query("lsm_nsoil", nsoil), dynamic_soil_diagnostic_names(nsoil))
203  : dynamic_soil_diagnostic_names(active_lsm_names);
204  names.insert(names.end(), soil_names.begin(), soil_names.end());
205  }
206 
207  return names;
208 }
ParmParse pp("prob")
DiagnosticDescriptor descriptor
Definition: ERF_Plotfile2DCatalog.cpp:100
amrex::Vector< std::string > dynamic_soil_diagnostic_names(int nsoil)
Definition: ERF_Plotfile2DCatalog.cpp:177
bool is_precipitation_accumulation(DiagnosticID id) noexcept
Definition: ERF_Plotfile2DPrecip.cpp:49
bool is_condensed_water_path(DiagnosticID id) noexcept
Definition: ERF_Plotfile2DWaterPath.cpp:50
bool active_lsm_contains(const amrex::Vector< std::string > &active_lsm_names, const char *name)
Definition: ERF_Plotfile2DWaterPath.cpp:131
const amrex::Vector< DiagnosticDescriptor > & diagnostic_catalog()
Definition: ERF_Plotfile2DCatalog.cpp:146
bool precipitation_diagnostic_available(DiagnosticID id, const MoistureComponentIndices &moisture_indices) noexcept
Definition: ERF_Plotfile2DPrecip.cpp:72
bool is_noahmp_active(const SolverChoice &solver_choice) noexcept
Definition: ERF_Plotfile2DWaterPath.cpp:87
bool is_land_surface_provider_field(DiagnosticID id) noexcept
Definition: ERF_Plotfile2DWaterPath.cpp:97
MoistureType moisture_type
Definition: ERF_DataStruct.H:1424

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)
92 {
93  amrex::Vector<std::string> names;
94  names.reserve(sampled_field_catalog().size());
95 
96  for (const auto& descriptor : sampled_field_catalog()) {
97  if (field_is_available(descriptor.id, solver_choice)) {
98  names.push_back(descriptor.name);
99  }
100  }
101 
102  return names;
103 }
const amrex::Vector< SampledFieldDescriptor > & sampled_field_catalog()
Definition: ERF_Plotfile2DSampledField.cpp:73
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 
)
492 {
493  amrex::Vector<SampledLevelDefinition> level_sets;
494  for (const auto& level_set_name : parse_requested_sampled_level_sets(pp_prefix, which)) {
495  level_sets.push_back(parse_sampled_level_definition(level_set_name, pp_prefix));
496  }
497 
499  static_plot_vars,
500  solver_choice);
501 }
SampledLevelDefinition parse_sampled_level_definition(const std::string &level_set_name, const std::string &pp_prefix)
Definition: ERF_Plotfile2DSampledLevel.cpp:308
amrex::Vector< std::string > parse_requested_sampled_level_sets(const std::string &pp_prefix, int which)
Definition: ERF_Plotfile2DSampledLevel.cpp:367
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:385

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

Referenced by build_sampled_level_output_descriptors().

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 ( )
147 {
148  return catalog_storage();
149 }

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
98 {
99  switch (category) {
100  case DiagnosticCategory::Geometry: return "Geometry";
101  case DiagnosticCategory::SurfaceLayer: return "SurfaceLayer";
102  case DiagnosticCategory::Radiation: return "Radiation";
103  case DiagnosticCategory::SurfaceFlux: return "SurfaceFlux";
104  case DiagnosticCategory::PBL: return "PBL";
105  case DiagnosticCategory::SurfaceState: return "SurfaceState";
106  case DiagnosticCategory::Precipitation: return "Precipitation";
107  case DiagnosticCategory::ColumnIntegral: return "ColumnIntegral";
108  case DiagnosticCategory::LandSurface: return "LandSurface";
109  case DiagnosticCategory::SampledLevel: return "SampledLevel";
110  }
111 
112  amrex::Abort("Unhandled DiagnosticCategory in 2D metadata writer");
113  return "";
114 }

◆ diagnostic_names()

amrex::Vector< std::string > plotfile2d::diagnostic_names ( )
153 {
154  amrex::Vector<std::string> names;
155  names.reserve(diagnostic_catalog().size());
156 
157  for (const auto& descriptor : diagnostic_catalog()) {
158  names.push_back(descriptor.name);
159  }
160 
161  return names;
162 }
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)
196 {
197  amrex::Vector<std::string> names;
198  for (const auto& name : active_lsm_names) {
200  ensure_dynamic_soil_descriptor(name);
201  names.push_back(name);
202  }
203  }
204  return names;
205 }
bool is_dynamic_soil_diagnostic_name(const std::string &name)
Definition: ERF_Plotfile2DCatalog.cpp:217
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)
178 {
179  amrex::Vector<std::string> names;
180  if (nsoil < 1) {
181  return names;
182  }
183  names.reserve(3*nsoil);
184  for (const char* group : {"smois", "sh2o", "tslb"}) {
185  for (int layer = 1; layer <= nsoil; ++layer) {
186  const std::string name = std::string(group) + "_" + std::to_string(layer);
187  ensure_dynamic_soil_descriptor(name);
188  names.push_back(name);
189  }
190  }
191  return names;
192 }

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)
144 {
145  std::string escaped;
146  escaped.reserve(value.size() + 8);
147 
148  for (unsigned char c : value) {
149  switch (c) {
150  case '\"': escaped += "\\\""; break;
151  case '\\': escaped += "\\\\"; break;
152  case '\n': escaped += "\\n"; break;
153  case '\t': escaped += "\\t"; break;
154  case '\r': escaped += "\\r"; break;
155  default:
156  if (c < 0x20) {
157  append_escaped_codepoint(escaped, c);
158  } else {
159  escaped.push_back(static_cast<char>(c));
160  }
161  break;
162  }
163  }
164 
165  return escaped;
166 }

◆ 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 
)
40 {
41  // Iterate over dst because it defines the 2D output component layout. The
42  // source must be box-compatible with dst on the horizontal tile covered by
43  // each MFIter.
44 #ifdef _OPENMP
45 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
46 #endif
47  for (MFIter mfi(dst, TilingIfNotGPU()); mfi.isValid(); ++mfi)
48  {
49  const Box& bx = mfi.tilebox();
50  const auto& dst_arr = dst.array(mfi);
51  const auto& src_arr = src.const_array(mfi);
52 
53  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
54  dst_arr(i, j, k, dst_comp) = src_arr(i, j, src_k, src_comp);
55  });
56  }
57 }
ParallelFor(grown_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 
)
66 {
67  if (src) {
68  fill_component_from_klevel(dst, dst_comp, *src, src_k, src_comp);
69  } else {
70  fill_component_with_value(dst, dst_comp, missing_value);
71  }
72 }
void fill_component_from_klevel(MultiFab &dst, int dst_comp, const MultiFab &src, int src_k, int src_comp)
Definition: ERF_Plotfile2DFill.cpp:35
void fill_component_with_value(MultiFab &dst, int dst_comp, Real value)
Definition: ERF_Plotfile2DFill.cpp:29

Referenced by ERF::Write2DPlotFile().

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 
)
241 {
242  if (selected.n == 0) {
243  return;
244  }
245 
246  // Validate selected components on the host before device kernels use them.
247  AMREX_ALWAYS_ASSERT(selected.n >= 0);
249  for (int n = 0; n < selected.n; ++n) {
250  AMREX_ALWAYS_ASSERT(selected.dst_comp[n] >= 0);
251  AMREX_ALWAYS_ASSERT(selected.dst_comp[n] < dst.nComp());
252  AMREX_ALWAYS_ASSERT(selected.src_comp[n] >= 0);
253  AMREX_ALWAYS_ASSERT(selected.src_comp[n] < cons.nComp());
254  }
255 
256  for (int n = 0; n < selected.n; ++n) {
257  dst.setVal(0., selected.dst_comp[n], 1, 0);
258  }
259 
260  const auto& dx = geom.CellSizeArray();
261 
262 #ifdef _OPENMP
263 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
264 #endif
265  for (MFIter mfi(cons, TilingIfNotGPU()); mfi.isValid(); ++mfi)
266  {
267  const Box& bx = mfi.tilebox();
268  const auto dst_arr = dst.array(mfi);
269  const auto src_arr = cons.const_array(mfi);
270 
271  if (SolverChoice::mesh_type == MeshType::ConstantDz) {
272  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
273  for (int n = 0; n < selected.n; ++n) {
274  amrex::HostDevice::Atomic::Add(
275  &dst_arr(i, j, 0, selected.dst_comp[n]),
276  src_arr(i, j, k, selected.src_comp[n]));
277  }
278  });
279  } else {
280  const auto& detJ_arr = detJ.const_array(mfi);
281  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
282  const amrex::Real metric = detJ_arr(i, j, k);
283  for (int n = 0; n < selected.n; ++n) {
284  amrex::HostDevice::Atomic::Add(
285  &dst_arr(i, j, 0, selected.dst_comp[n]),
286  src_arr(i, j, k, selected.src_comp[n]) * metric);
287  }
288  });
289  }
290  }
291 
292  for (int n = 0; n < selected.n; ++n) {
293  dst.mult(dx[2], selected.dst_comp[n], 1, 0);
294  }
295 }
const Real dx
Definition: ERF_InitCustomPert_ABL.H:23
AMREX_ALWAYS_ASSERT(bx.length()[2]==khi+1)
@ cons
Definition: ERF_IndexDefines.H:175
static MeshType mesh_type
Definition: ERF_DataStruct.H:1239

Referenced by ERF::Write2DPlotFile().

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

Referenced by ERF::Write2DPlotFile().

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 
)
139 {
140  if (!src) {
141  fill_component_with_value(dst, dst_comp, missing_value);
142  return;
143  }
144 
145 #ifdef _OPENMP
146 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
147 #endif
148  for (MFIter mfi(dst, TilingIfNotGPU()); mfi.isValid(); ++mfi)
149  {
150  // Keep unit conversion in the surface-flux diagnostic helper so this
151  // mechanical layer does not duplicate physical constants or units.
152  const Box& bx = mfi.tilebox();
153  const auto& dst_arr = dst.array(mfi);
154  const auto& src_arr = src->const_array(mfi);
155 
156  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
157  dst_arr(i, j, k, dst_comp) =
159  src_arr(i, j, src_k, 0));
160  });
161  }
162 }
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 ERF::Write2DPlotFile().

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

Referenced by ERF::Write2DPlotFile().

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 = {} 
)

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

Referenced by ERF::Write2DPlotFile().

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 
)
108 {
109  if (!src) {
110  fill_component_with_value(dst, dst_comp, missing_value);
111  return;
112  }
113 
114 #ifdef _OPENMP
115 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
116 #endif
117  for (MFIter mfi(dst, TilingIfNotGPU()); mfi.isValid(); ++mfi)
118  {
119  // Keep unit conversion in the surface-flux diagnostic helper so this
120  // mechanical layer does not duplicate physical constants or units.
121  const Box& bx = mfi.tilebox();
122  const auto& dst_arr = dst.array(mfi);
123  const auto& src_arr = src->const_array(mfi);
124 
125  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
126  dst_arr(i, j, k, dst_comp) =
128  src_arr(i, j, src_k, 0));
129  });
130  }
131 }
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 ERF::Write2DPlotFile().

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)
166 {
167  for (const auto& descriptor : diagnostic_catalog()) {
168  if (name == descriptor.name) {
169  return &descriptor;
170  }
171  }
172 
173  return nullptr;
174 }

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

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)
209 {
211  return nullptr;
212  }
213  return ensure_dynamic_soil_descriptor(name);
214 }

Referenced by build_sampled_level_output_descriptors_from_definitions(), format_2d_metadata_json(), and ERF::Write2DPlotFile().

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)
80 {
81  for (const auto& descriptor : sampled_field_catalog()) {
82  if (name == descriptor.name) {
83  return &descriptor;
84  }
85  }
86 
87  return nullptr;
88 }

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 
)
87 {
88  std::ostringstream os;
89  os << "Write2DPlotFile internal error at level " << lev
90  << ": filled " << filled
91  << " components but expected " << expected
92  << ". The 2D plot variable list and fill blocks are inconsistent.";
93  return os.str();
94 }

Referenced by ERF::Write2DPlotFile().

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

◆ format_2d_metadata_json() [2/2]

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

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)
98 {
99  std::ostringstream os;
100  os << "Write2DPlotFile received invalid stream index " << which
101  << "; expected 1 or 2.";
102  return os.str();
103 }

◆ format_plot2d_parameter_name()

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

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 
)
65 {
66  std::ostringstream os;
67  os << "WARNING: Requested 2D plot variable '" << unavailable_name
68  << "' from '" << parameter_name
69  << "' is not available and will be skipped. Available built-in 2D plot variables are: "
70  << join_names(available_names) << ".";
71  return os.str();
72 }

◆ is_condensed_water_path()

bool plotfile2d::is_condensed_water_path ( DiagnosticID  id)
noexcept
51 {
52  switch (id) {
53  case DiagnosticID::IntegratedQc:
54  case DiagnosticID::IntegratedQi:
55  case DiagnosticID::IntegratedQr:
56  case DiagnosticID::IntegratedQs:
57  case DiagnosticID::IntegratedQg:
58  return true;
59  default:
60  return false;
61  }
62 }

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)
82 {
83  const auto* descriptor = find_diagnostic(name);
85 }
Here is the call graph for this function:

◆ is_dynamic_soil_diagnostic_name()

bool plotfile2d::is_dynamic_soil_diagnostic_name ( const std::string &  name)
218 {
219  const auto underscore = name.find('_');
220  if (underscore == std::string::npos) {
221  return false;
222  }
223  const std::string group = name.substr(0, underscore);
224  if (group != "smois" && group != "sh2o" && group != "tslb") {
225  return false;
226  }
227  try {
228  std::size_t parsed = 0;
229  const int layer = std::stoi(name.substr(underscore + 1), &parsed);
230  return parsed == name.size() - underscore - 1 && layer > 0;
231  } catch (...) {
232  return false;
233  }
234 }

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
98 {
99  switch (id) {
100  case DiagnosticID::LandSurfaceTsfC:
101  case DiagnosticID::LandSurfaceEmissivity:
102  case DiagnosticID::LandSurfaceAlbDirVis:
103  case DiagnosticID::LandSurfaceAlbDirNir:
104  case DiagnosticID::LandSurfaceAlbDifVis:
105  case DiagnosticID::LandSurfaceAlbDifNir:
106  case DiagnosticID::LandSurfaceCosZenith:
107  case DiagnosticID::LandSurfaceSwFluxDn:
108  case DiagnosticID::LandSurfaceSwFluxDnDirVis:
109  case DiagnosticID::LandSurfaceSwFluxDnDirNir:
110  case DiagnosticID::LandSurfaceSwFluxDnDifVis:
111  case DiagnosticID::LandSurfaceSwFluxDnDifNir:
112  case DiagnosticID::LandSurfaceLwFluxDn:
113  case DiagnosticID::LandSurfaceGrdflx:
114  case DiagnosticID::LandSurfaceFira:
115  case DiagnosticID::LandSurfaceSav:
116  case DiagnosticID::LandSurfaceSag:
117  case DiagnosticID::LandSurfaceAlbedo:
118  case DiagnosticID::LandSurfaceSfcrunoff:
119  case DiagnosticID::LandSurfaceUdrunoff:
120  case DiagnosticID::NoahmpTemperature2mVegetated:
121  case DiagnosticID::NoahmpTemperature2mBare:
122  case DiagnosticID::NoahmpWaterVaporMixingRatio2mVegetated:
123  case DiagnosticID::NoahmpWaterVaporMixingRatio2mBare:
124  case DiagnosticID::NoahmpVegetationFraction:
125  return true;
126  default:
127  return false;
128  }
129 }

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
88 {
89 #ifdef ERF_USE_NOAHMP
90  return solver_choice.lsm_type == LandSurfaceType::NOAHMP;
91 #else
92  amrex::ignore_unused(solver_choice);
93  return false;
94 #endif
95 }
LandSurfaceType lsm_type
Definition: ERF_DataStruct.H:1427

Referenced by available_diagnostic_names().

Here is the caller graph for this function:

◆ is_precipitation_accumulation()

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

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)
66 {
67  const auto* descriptor = find_diagnostic(name);
69 }
Here is the call 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
48 {
49  if (hi_coord == lo_coord) {
50  return lo_value;
51  }
52 
53  const amrex::Real weight = (target - lo_coord) / (hi_coord - lo_coord);
54  return lo_value + weight * (hi_value - lo_value);
55 }

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)
170 {
171  return plotfilename + "/2DMetadata.json";
172 }

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
118 {
119  switch (policy) {
120  case MissingPolicy::AlwaysAvailable: return "AlwaysAvailable";
121  case MissingPolicy::FillZeroWhenUnavailable: return "FillZeroWhenUnavailable";
122  case MissingPolicy::FillMinus999WhenUnavailable: return "FillMinus999WhenUnavailable";
123  }
124 
125  amrex::Abort("Unhandled MissingPolicy in 2D metadata writer");
126  return "";
127 }

◆ missing_value_json()

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

◆ parse_requested_sampled_level_sets()

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

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 
)
310 {
311  SampledLevelDefinition level_set;
312  level_set.name = level_set_name;
313 
314  amrex::ParmParse pp(pp_prefix);
315  const std::string base = "plot2d.level_set." + level_set_name + ".";
316 
317  std::string coordinate_value;
318  if (!pp.query((base + "coordinate").c_str(), coordinate_value)) {
319  amrex::Abort(build_missing_field_error(level_set_name, "coordinate"));
320  }
321  const std::string coordinate_error =
322  validate_sampled_coordinate_string(level_set_name, coordinate_value);
323  if (!coordinate_error.empty()) {
324  amrex::Abort(coordinate_error);
325  }
326  level_set.coordinate = sampled_coordinate_from_string(coordinate_value);
327 
328  if (pp.query((base + "units").c_str(), level_set.units) == 0) {
329  level_set.units = sampled_coordinate_default_units(level_set.coordinate);
330  }
331 
332  std::string interpolation_value;
333  if (pp.query((base + "interpolation").c_str(), interpolation_value) == 0) {
334  level_set.interpolation =
336  } else {
337  level_set.interpolation = sampled_interpolation_from_string(interpolation_value);
338  }
339 
340  if (pp.query((base + "missing_value").c_str(), level_set.missing_value) == 0) {
341  level_set.missing_value = amrex::Real(-999.0);
342  }
343 
344  int n_values = pp.countval((base + "values").c_str());
345  if (n_values <= 0) {
346  amrex::Abort(build_missing_field_error(level_set_name, "values"));
347  }
348  level_set.values.resize(n_values);
349  pp.getarr((base + "values").c_str(), level_set.values, 0, n_values);
350 
351  int n_fields = pp.countval((base + "fields").c_str());
352  if (n_fields <= 0) {
353  amrex::Abort(build_missing_field_error(level_set_name, "fields"));
354  }
355  level_set.fields.resize(n_fields);
356  pp.getarr((base + "fields").c_str(), level_set.fields, 0, n_fields);
357 
358  const std::string error = validate_sampled_level_definition(level_set);
359  if (!error.empty()) {
360  amrex::Abort(error);
361  }
362 
363  return level_set;
364 }
std::string validate_sampled_coordinate_string(const std::string &level_set_name, const std::string &value)
Definition: ERF_Plotfile2DSampledLevel.cpp:196
std::string validate_sampled_level_definition(const SampledLevelDefinition &level_set)
Definition: ERF_Plotfile2DSampledLevel.cpp:247
SampledInterpolation sampled_interpolation_from_string(const std::string &value)
Definition: ERF_Plotfile2DSampledLevel.cpp:182
const char * sampled_coordinate_default_interpolation(SampledCoordinate coordinate) noexcept
Definition: ERF_Plotfile2DSampledLevel.cpp:146

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
74 {
75  const bool has_any_precip = has_any_precip_component(moisture_indices);
76 
77  switch (id) {
78  case DiagnosticID::PrecipTotalAccum:
79  case DiagnosticID::PrecipFrozenAccum:
80  return has_any_precip;
81  case DiagnosticID::PrecipRainAccum:
82  return has_rain_component(moisture_indices);
83  case DiagnosticID::PrecipSnowAccum:
84  return has_snow_component(moisture_indices);
85  case DiagnosticID::PrecipGraupelAccum:
86  return has_graupel_component(moisture_indices);
87  case DiagnosticID::PrecipHailAccum:
88  return false;
89  default:
90  return false;
91  }
92 }

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
147 {
148  return coordinate_interpolation_default(coordinate);
149 }

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
141 {
142  return coordinate_units_default(coordinate);
143 }

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)
163 {
164  if (string_iequals(value, "model_index")) {
165  return SampledCoordinate::ModelIndex;
166  }
167  if (string_iequals(value, "height_msl")) {
168  return SampledCoordinate::HeightMSL;
169  }
170  if (string_iequals(value, "height_agl")) {
171  return SampledCoordinate::HeightAGL;
172  }
173  if (string_iequals(value, "pressure")) {
174  return SampledCoordinate::Pressure;
175  }
176 
177  amrex::Abort("Unknown sampled-level coordinate '" + value + "'");
178  return SampledCoordinate::ModelIndex;
179 }

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
129 {
130  switch (coordinate) {
131  case SampledCoordinate::ModelIndex: return "k";
132  case SampledCoordinate::HeightMSL: return "z_msl";
133  case SampledCoordinate::HeightAGL: return "z_agl";
134  case SampledCoordinate::Pressure: return "p";
135  }
136  return "unknown";
137 }

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
117 {
118  switch (coordinate) {
119  case SampledCoordinate::ModelIndex: return "model_index";
120  case SampledCoordinate::HeightMSL: return "height_msl";
121  case SampledCoordinate::HeightAGL: return "height_agl";
122  case SampledCoordinate::Pressure: return "pressure";
123  }
124  return "unknown";
125 }

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 ( )
74 {
75  return field_catalog_storage();
76 }

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)
135 {
136  return sampled_field_name(field_id);
137 }
const char * sampled_field_name(SampledFieldID field_id) noexcept
Definition: ERF_Plotfile2DSampledField.H:144
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
83 {
84  return !sampled_field_is_wind(field_id);
85 }
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
68 {
69  switch (field_id) {
70  case SampledFieldID::UEast:
71  case SampledFieldID::VNorth:
72  case SampledFieldID::W:
73  case SampledFieldID::WindSpeed:
74  case SampledFieldID::WindDir:
75  return true;
76  default:
77  return false;
78  }
79 }

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
145 {
146  switch (field_id) {
147  case SampledFieldID::Rho: return "rho";
148  case SampledFieldID::Theta: return "theta";
149  case SampledFieldID::Temp: return "temp";
150  case SampledFieldID::Pressure: return "pressure";
151  case SampledFieldID::HeightMSL: return "height_msl";
152  case SampledFieldID::HeightAGL: return "height_agl";
153  case SampledFieldID::Qv: return "qv";
154  case SampledFieldID::Qc: return "qc";
155  case SampledFieldID::Qi: return "qi";
156  case SampledFieldID::Qr: return "qr";
157  case SampledFieldID::Qs: return "qs";
158  case SampledFieldID::Qg: return "qg";
159  case SampledFieldID::UEast: return "u_east";
160  case SampledFieldID::VNorth: return "v_north";
161  case SampledFieldID::W: return "w";
162  case SampledFieldID::WindSpeed: return "wind_speed";
163  case SampledFieldID::WindDir: return "wind_dir";
164  }
165 
166  return "unknown";
167 }

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,
bool  have_z_phys_cc,
int  i,
int  j,
int  k,
const MoistureComponentIndices moisture_indices 
)
noexcept
95 {
96  const amrex::Real rho = cons_arr(i, j, k, Rho_comp);
97  const bool has_moisture = (moisture_indices.qv >= 0);
98  // Microphysical fields are sampled as mixing ratios. The conserved state
99  // stores rho*q, so field evaluation divides by rho before interpolation.
100  const amrex::Real qv_for_eos = has_moisture
101  ? cons_arr(i, j, k, moisture_indices.qv) / rho
102  : amrex::Real(0.0);
103 
104  switch (field_id) {
105  case SampledFieldID::Rho:
106  return rho;
108  return cons_arr(i, j, k, RhoTheta_comp) / rho;
109  case SampledFieldID::Temp:
110  return getTgivenRandRTh(rho, cons_arr(i, j, k, RhoTheta_comp), qv_for_eos);
111  case SampledFieldID::Pressure:
112  return getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp), qv_for_eos);
113  case SampledFieldID::HeightMSL:
114  if (have_z_phys_cc) {
115  return z_phys_cc_arr(i, j, k);
116  }
117  return Compute_Z_AtCellCenter(i, j, k, z_phys_nd_arr);
118  case SampledFieldID::HeightAGL:
119  return Compute_Zrel_AtCellCenter(i, j, k, z_phys_nd_arr);
120  case SampledFieldID::Qv:
121  return has_moisture ? cons_arr(i, j, k, moisture_indices.qv) / rho : amrex::Real(0.0);
122  case SampledFieldID::Qc:
123  return (moisture_indices.qc >= 0) ? cons_arr(i, j, k, moisture_indices.qc) / rho : amrex::Real(0.0);
124  case SampledFieldID::Qi:
125  return (moisture_indices.qi >= 0) ? cons_arr(i, j, k, moisture_indices.qi) / rho : amrex::Real(0.0);
126  case SampledFieldID::Qr:
127  return (moisture_indices.qr >= 0) ? cons_arr(i, j, k, moisture_indices.qr) / rho : amrex::Real(0.0);
128  case SampledFieldID::Qs:
129  return (moisture_indices.qs >= 0) ? cons_arr(i, j, k, moisture_indices.qs) / rho : amrex::Real(0.0);
130  case SampledFieldID::Qg:
131  return (moisture_indices.qg >= 0) ? cons_arr(i, j, k, moisture_indices.qg) / rho : amrex::Real(0.0);
132  case SampledFieldID::UEast:
133  case SampledFieldID::VNorth:
134  case SampledFieldID::W:
135  case SampledFieldID::WindSpeed:
136  case SampledFieldID::WindDir:
137  return amrex::Real(0.0);
138  }
139 
140  return amrex::Real(0.0);
141 }
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:36
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:37
rho
Definition: ERF_InitCustomPert_Bubble.H:107
AMREX_GPU_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:389
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:361
int qs
Definition: ERF_DataStruct.H:111
int qr
Definition: ERF_DataStruct.H:110
int qi
Definition: ERF_DataStruct.H:109
int qv
Definition: ERF_DataStruct.H:107
int qc
Definition: ERF_DataStruct.H:108
int qg
Definition: ERF_DataStruct.H:112

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)
183 {
184  if (string_iequals(value, "none")) {
185  return SampledInterpolation::None;
186  }
187  if (string_iequals(value, "linear")) {
188  return SampledInterpolation::Linear;
189  }
190 
191  amrex::Abort("Unknown sampled-level interpolation '" + value + "'");
192  return SampledInterpolation::None;
193 }

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
153 {
154  switch (interpolation) {
155  case SampledInterpolation::None: return "none";
156  case SampledInterpolation::Linear: return "linear";
157  }
158  return "unknown";
159 }

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 
)
217 {
218  std::ostringstream os;
219  os << "Sampled-level definition '" << level_set_name << "' parameter '"
220  << parameter_name << "': ";
221  return os.str();
222 }

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 
)
226 {
227  std::string tag = format_numeric_tag(value);
228  if (!units.empty() && units != "1") {
229  tag += units;
230  }
231  return tag;
232 }

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 
)
239 {
240  std::ostringstream os;
241  os << field_name << "_" << sampled_coordinate_tag(coordinate) << "_"
243  return os.str();
244 }
const char * sampled_coordinate_tag(SampledCoordinate coordinate) noexcept
Definition: ERF_Plotfile2DSampledLevel.cpp:128
std::string sampled_level_value_tag(amrex::Real value, const std::string &units)
Definition: ERF_Plotfile2DSampledLevel.cpp:225

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

Referenced by 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 
)
108 {
109  SampledFieldSelection selection;
110 
111  std::unordered_set<std::string> seen;
112 
113  for (const auto& name : requested) {
114  const auto* descriptor = find_sampled_field(name);
115  if (descriptor == nullptr) {
116  selection.unavailable.push_back(name);
117  continue;
118  }
119 
120  if (!field_is_available(descriptor->id, solver_choice)) {
121  selection.unavailable.push_back(name);
122  continue;
123  }
124 
125  if (seen.insert(name).second) {
126  selection.accepted.push_back(*descriptor);
127  }
128  }
129 
130  return selection;
131 }

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 
)
213 {
214  SelectedWaterPathComponents selected;
215 
216  for (int dst_comp = 0; dst_comp < static_cast<int>(plot_var_names.size()); ++dst_comp) {
217  const auto* descriptor = find_diagnostic(plot_var_names[dst_comp]);
219  continue;
220  }
221 
222  const int src_comp = source_component_for(descriptor->id, solver_choice.moisture_indices);
223  if (src_comp < 0) {
224  continue;
225  }
226 
227  selected.dst_comp[selected.n] = dst_comp;
228  selected.src_comp[selected.n] = src_comp;
229  ++selected.n;
230  }
231 
232  return selected;
233 }

Referenced by ERF::Write2DPlotFile().

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 
)
97 {
98  SelectedSurfacePrecipAccumulationComponents selected;
99 
100  for (int dst_comp = 0; dst_comp < static_cast<int>(plot_var_names.size()); ++dst_comp) {
101  const auto* descriptor = find_diagnostic(plot_var_names[dst_comp]);
103  continue;
104  }
105 
106  const bool has_total = surface_precip_has_total_source(sources);
107  const bool has_rain = surface_precip_has_source(sources.rain);
108 
109  const bool source_available =
110  (descriptor->id == DiagnosticID::PrecipTotalAccum)
112  : (descriptor->id == DiagnosticID::PrecipRainAccum)
113  ? (has_rain || has_total)
114  : (descriptor->id == DiagnosticID::PrecipSnowAccum)
116  : (descriptor->id == DiagnosticID::PrecipGraupelAccum)
118  : (descriptor->id == DiagnosticID::PrecipHailAccum)
120  : (descriptor->id == DiagnosticID::PrecipFrozenAccum)
122  : false;
123 
124  if (!source_available) {
125  continue;
126  }
127 
128  selected.dst_comp[selected.n] = dst_comp;
129  selected.id[selected.n] = descriptor->id;
130  ++selected.n;
131  }
132 
133  return selected;
134 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool surface_precip_has_total_source(const SurfacePrecipAccumulationSources &src) noexcept
Definition: ERF_SurfacePrecipitation.H:36
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool surface_precip_has_any_frozen_source(const SurfacePrecipAccumulationSources &src) noexcept
Definition: ERF_SurfacePrecipitation.H:58

Referenced by ERF::Write2DPlotFile().

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
23 {
24  return native_shoc_owns_scalar_fluxes &&
25  native_shoc_has_consumed_flux_diagnostics &&
26  host_flux_field_available;
27 }

Referenced by ERF::Write2DPlotFile().

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 
)
198 {
199  if (string_iequals(value, "isentropic")) {
200  return sampled_level_error_prefix(level_set_name, "coordinate") +
201  "isentropic output needs a crossing policy";
202  }
203 
204  if (string_iequals(value, "model_index") ||
205  string_iequals(value, "height_msl") ||
206  string_iequals(value, "height_agl") ||
207  string_iequals(value, "pressure")) {
208  return {};
209  }
210 
211  return "Unknown sampled-level coordinate '" + value + "'";
212 }

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

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 
)
253 {
254  if (!amrex::ParallelDescriptor::IOProcessor()) {
255  return;
256  }
257 
258  const std::string filename = metadata_json_filename(plotfilename);
259  std::ofstream outfile(filename, std::ios::out | std::ios::trunc);
260  if (!outfile.good()) {
261  amrex::FileOpenFailed(filename);
262  }
263 
264  outfile << format_2d_metadata_json(descriptors);
265  if (!outfile.good()) {
266  amrex::FileOpenFailed(filename);
267  }
268 }
struct @29 out
std::string metadata_json_filename(const std::string &plotfilename)
Definition: ERF_Plotfile2DMetadata.cpp:169
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 
)
231 {
232  // Native AMReX 2D plotfiles write this sidecar next to the plotfile
233  // directory on the I/O processor only.
234  if (!amrex::ParallelDescriptor::IOProcessor()) {
235  return;
236  }
237 
238  const std::string filename = metadata_json_filename(plotfilename);
239  std::ofstream outfile(filename, std::ios::out | std::ios::trunc);
240  if (!outfile.good()) {
241  amrex::FileOpenFailed(filename);
242  }
243 
244  outfile << format_2d_metadata_json(varnames);
245  if (!outfile.good()) {
246  amrex::FileOpenFailed(filename);
247  }
248 }

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