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 , 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 , 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 
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 
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  OLR,
31  SensFlux,
32  LatenFlux,
33  SurfPres,
50  ShocUStar,
51  ShocOlen,
82 };
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

Function Documentation

◆ active_condensed_water_path_descriptors()

amrex::Vector< WaterPathDescriptor > plotfile2d::active_condensed_water_path_descriptors ( const SolverChoice solver_choice)
69 {
70  amrex::Vector<WaterPathDescriptor> descriptors;
71  descriptors.reserve(MaxCondensedWaterPathComponents);
72 
73  for (const auto& spec : condensed_specs) {
74  const int source_component = source_component_for(spec.id, solver_choice.moisture_indices);
75  if (source_component >= 0) {
76  descriptors.push_back({spec.id, spec.name, source_component});
77  }
78  }
79 
80  return descriptors;
81 }
static constexpr int MaxCondensedWaterPathComponents
Definition: ERF_Plotfile2DWaterPath.H:24
MoistureComponentIndices moisture_indices
Conserved-state component indices for active moisture species.
Definition: ERF_DataStruct.H:1621

◆ active_lsm_contains()

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

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)
143 {
144  return available_diagnostic_names(solver_choice, true);
145 }
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:156

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 
)
150 {
151  return available_diagnostic_names(solver_choice, has_surface_layer,
152  amrex::Vector<std::string>{});
153 }
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 
)
159 {
160  amrex::Vector<std::string> names;
161  names.reserve(diagnostic_catalog().size());
162  const bool has_noahmp = is_noahmp_active(solver_choice);
163  const bool has_moisture = solver_choice.moisture_type != MoistureType::None;
164 
165  for (const auto& descriptor : diagnostic_catalog()) {
167  ((!active_lsm_names.empty() &&
168  !active_lsm_contains(active_lsm_names, descriptor.name)) ||
169  (active_lsm_names.empty() && !has_noahmp))) {
170  continue;
171  }
172  if (descriptor.id == DiagnosticID::Temperature2m && !(has_noahmp || has_surface_layer)) {
173  continue;
174  }
175  if ((descriptor.id == DiagnosticID::WaterVaporMixingRatio2m ||
176  descriptor.id == DiagnosticID::NearSurfaceDiagnosticSource) &&
177  !(has_moisture && (has_noahmp || has_surface_layer))) {
178  if (descriptor.id == DiagnosticID::NearSurfaceDiagnosticSource &&
179  (has_noahmp || has_surface_layer)) {
180  names.push_back(descriptor.name);
181  }
182  continue;
183  }
185  if (source_component_for(descriptor.id, solver_choice.moisture_indices) >= 0) {
186  names.push_back(descriptor.name);
187  }
188  continue;
189  }
190 
193  names.push_back(descriptor.name);
194  }
195  continue;
196  }
197 
198  names.push_back(descriptor.name);
199  }
200 
201  if (has_noahmp || !active_lsm_names.empty()) {
202  amrex::ParmParse pp("erf");
203  int nsoil = 4;
204  const auto soil_names = active_lsm_names.empty()
205  ? (pp.query("lsm_nsoil", nsoil), dynamic_soil_diagnostic_names(nsoil))
206  : dynamic_soil_diagnostic_names(active_lsm_names);
207  names.insert(names.end(), soil_names.begin(), soil_names.end());
208  }
209 
210  return names;
211 }
ParmParse pp("prob")
DiagnosticDescriptor descriptor
Definition: ERF_Plotfile2DCatalog.cpp:104
amrex::Vector< std::string > dynamic_soil_diagnostic_names(int nsoil)
Definition: ERF_Plotfile2DCatalog.cpp:181
bool is_precipitation_accumulation(DiagnosticID id) noexcept
Definition: ERF_Plotfile2DPrecip.cpp:52
bool is_condensed_water_path(DiagnosticID id) noexcept
Definition: ERF_Plotfile2DWaterPath.cpp:53
bool active_lsm_contains(const amrex::Vector< std::string > &active_lsm_names, const char *name)
Definition: ERF_Plotfile2DWaterPath.cpp:134
const amrex::Vector< DiagnosticDescriptor > & diagnostic_catalog()
Definition: ERF_Plotfile2DCatalog.cpp:150
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:90
bool is_land_surface_provider_field(DiagnosticID id) noexcept
Definition: ERF_Plotfile2DWaterPath.cpp:100
MoistureType moisture_type
Moisture or microphysics model.
Definition: ERF_DataStruct.H:1604

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 
)
495 {
496  amrex::Vector<SampledLevelDefinition> level_sets;
497  for (const auto& level_set_name : parse_requested_sampled_level_sets(pp_prefix, which)) {
498  level_sets.push_back(parse_sampled_level_definition(level_set_name, pp_prefix));
499  }
500 
502  static_plot_vars,
503  solver_choice);
504 }
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:370
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:388

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

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 ( )
151 {
152  return catalog_storage();
153 }

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 ( )
157 {
158  amrex::Vector<std::string> names;
159  names.reserve(diagnostic_catalog().size());
160 
161  for (const auto& descriptor : diagnostic_catalog()) {
162  names.push_back(descriptor.name);
163  }
164 
165  return names;
166 }
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)
200 {
201  amrex::Vector<std::string> names;
202  for (const auto& name : active_lsm_names) {
204  ensure_dynamic_soil_descriptor(name);
205  names.push_back(name);
206  }
207  }
208  return names;
209 }
bool is_dynamic_soil_diagnostic_name(const std::string &name)
Definition: ERF_Plotfile2DCatalog.cpp:221
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)
182 {
183  amrex::Vector<std::string> names;
184  if (nsoil < 1) {
185  return names;
186  }
187  names.reserve(3*nsoil);
188  for (const char* group : {"smois", "sh2o", "tslb"}) {
189  for (int layer = 1; layer <= nsoil; ++layer) {
190  const std::string name = std::string(group) + "_" + std::to_string(layer);
191  ensure_dynamic_soil_descriptor(name);
192  names.push_back(name);
193  }
194  }
195  return names;
196 }

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

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

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

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 
)
142 {
143  if (!src) {
144  fill_component_with_value(dst, dst_comp, missing_value);
145  return;
146  }
147 
148 #ifdef _OPENMP
149 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
150 #endif
151  for (MFIter mfi(dst, TilingIfNotGPU()); mfi.isValid(); ++mfi)
152  {
153  // Keep unit conversion in the surface-flux diagnostic helper so this
154  // mechanical layer does not duplicate physical constants or units.
155  const Box& bx = mfi.tilebox();
156  const auto& dst_arr = dst.array(mfi);
157  const auto& src_arr = src->const_array(mfi);
158 
159  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
160  dst_arr(i, j, k, dst_comp) =
162  src_arr(i, j, src_k, 0));
163  });
164  }
165 }
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 
)
144 {
145  if (selected.n == 0) {
146  return;
147  }
148 
149  AMREX_ALWAYS_ASSERT(selected.n >= 0);
151 
152  for (int n = 0; n < selected.n; ++n) {
153  AMREX_ALWAYS_ASSERT(selected.dst_comp[n] >= 0);
154  AMREX_ALWAYS_ASSERT(selected.dst_comp[n] < dst.nComp());
155  dst.setVal(0.0, selected.dst_comp[n], 1, 0);
156  }
157 
158  if (!surface_precip_has_any_source(sources)) {
159  return;
160  }
161 
162  // Normalize scheme-native precipitation accumulators to kg/m^2 at the
163  // output boundary, then build the derived total and frozen fields from the
164  // normalized species values.
165  const SurfacePrecipAccumulationSource* anchor = first_available_source(sources);
166  AMREX_ALWAYS_ASSERT(anchor != nullptr);
167  const MultiFab& anchor_mf = *anchor->accum;
168  const bool has_total_source = surface_precip_has_source(sources.total);
169  const bool has_rain_source = surface_precip_has_source(sources.rain);
170  const bool has_snow_source = surface_precip_has_source(sources.snow);
171  const bool has_graupel_source = surface_precip_has_source(sources.graupel);
172  const bool has_hail_source = surface_precip_has_source(sources.hail);
173  const amrex::Real total_factor = sources.total.native_to_kg_m2;
174  const amrex::Real rain_factor = sources.rain.native_to_kg_m2;
175  const amrex::Real snow_factor = sources.snow.native_to_kg_m2;
176  const amrex::Real graupel_factor = sources.graupel.native_to_kg_m2;
177  const amrex::Real hail_factor = sources.hail.native_to_kg_m2;
178 
179  for (MFIter mfi(anchor_mf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
180  {
181  const Box& bx = mfi.tilebox();
182  const auto dst_arr = dst.array(mfi);
183  const auto total_arr = has_total_source ? sources.total.accum->const_array(mfi) : Array4<const Real>{};
184  const auto rain_arr = has_rain_source ? sources.rain.accum->const_array(mfi) : Array4<const Real>{};
185  const auto snow_arr = has_snow_source ? sources.snow.accum->const_array(mfi) : Array4<const Real>{};
186  const auto graupel_arr = has_graupel_source ? sources.graupel.accum->const_array(mfi) : Array4<const Real>{};
187  const auto hail_arr = has_hail_source ? sources.hail.accum->const_array(mfi) : Array4<const Real>{};
188 
189  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept
190  {
191  if (k != klo) {
192  return;
193  }
194 
195  const amrex::Real total_source =
196  has_total_source ? total_arr(i, j, k, 0) * total_factor : amrex::Real(0.0);
197  const amrex::Real rain_source =
198  has_rain_source ? rain_arr(i, j, k, 0) * rain_factor : amrex::Real(0.0);
199  const amrex::Real snow =
200  has_snow_source ? snow_arr(i, j, k, 0) * snow_factor : amrex::Real(0.0);
201  const amrex::Real graupel =
202  has_graupel_source ? graupel_arr(i, j, k, 0) * graupel_factor : amrex::Real(0.0);
203  const amrex::Real hail =
204  has_hail_source ? hail_arr(i, j, k, 0) * hail_factor : amrex::Real(0.0);
205  const amrex::Real frozen = snow + graupel + hail;
206  const amrex::Real total = has_total_source ? total_source : rain_source + frozen;
207  // Total-plus-frozen-subset schemes derive rain as total - frozen.
208  // Clamp to zero to avoid negative output from roundoff or small
209  // scheme inconsistencies.
210  const amrex::Real rain = has_rain_source ? rain_source
211  : amrex::max(amrex::Real(0.0), total - frozen);
212 
213  for (int n = 0; n < selected.n; ++n) {
214  switch (selected.id[n]) {
215  case DiagnosticID::PrecipTotalAccum:
216  dst_arr(i, j, 0, selected.dst_comp[n]) = total;
217  break;
218  case DiagnosticID::PrecipRainAccum:
219  dst_arr(i, j, 0, selected.dst_comp[n]) = rain;
220  break;
221  case DiagnosticID::PrecipSnowAccum:
222  dst_arr(i, j, 0, selected.dst_comp[n]) = snow;
223  break;
224  case DiagnosticID::PrecipGraupelAccum:
225  dst_arr(i, j, 0, selected.dst_comp[n]) = graupel;
226  break;
227  case DiagnosticID::PrecipHailAccum:
228  dst_arr(i, j, 0, selected.dst_comp[n]) = hail;
229  break;
230  case DiagnosticID::PrecipFrozenAccum:
231  dst_arr(i, j, 0, selected.dst_comp[n]) = frozen;
232  break;
233  default:
234  break;
235  }
236  }
237  });
238  }
239 }
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:133
@ rain
Definition: ERF_NOAHMP_Fields.H:131
@ total
Definition: ERF_NOAHMP_Fields.H:130
@ hail
Definition: ERF_NOAHMP_Fields.H:134
@ snow
Definition: ERF_NOAHMP_Fields.H:132
static constexpr int MaxSurfacePrecipAccumulationComponents
Definition: ERF_Plotfile2DPrecip.H:27
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 
)
181 {
182  const auto* sampled = descriptor.sampled_level ? &*descriptor.sampled_level : nullptr;
183  if (sampled == nullptr) {
184  fill_component_with_value(dst, dst_comp, descriptor.missing_value);
185  return;
186  }
187 
188  const auto* field_descriptor = find_sampled_field(sampled->source_field);
189  if (field_descriptor == nullptr) {
190  Abort("Unknown sampled-level source field '" + sampled->source_field + "'");
191  }
192 
193  const auto coordinate = sampled_coordinate_from_string(sampled->vertical_coordinate.type);
194  const auto field_id = field_descriptor->id;
195  const Real target = sampled->vertical_coordinate.canonical_value;
196  const int target_k = static_cast<int>(std::nearbyint(target));
197  const Real missing_value = descriptor.missing_value;
198  const bool is_wind_field = sampled_field_is_wind(field_id);
199  const bool have_rotation = (wind_sources.cos_alpha != nullptr) || (wind_sources.sin_alpha != nullptr);
200 
201  if (is_wind_field) {
202  if (wind_sources.xvel == nullptr || wind_sources.yvel == nullptr || wind_sources.zvel == nullptr) {
203  Abort("Sampled-level wind field '" + sampled->source_field + "' requires xvel, yvel, and zvel sources");
204  }
205  if ((wind_sources.cos_alpha == nullptr) != (wind_sources.sin_alpha == nullptr)) {
206  Abort("Sampled-level wind field '" + sampled->source_field + "' requires both cos_alpha and sin_alpha when rotation is supplied");
207  }
208  }
209 
210 #ifdef _OPENMP
211 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
212 #endif
213  for (MFIter mfi(dst, TilingIfNotGPU()); mfi.isValid(); ++mfi)
214  {
215  const Box& bx = mfi.tilebox();
216  const auto& dst_arr = dst.array(mfi);
217  const auto& cons_arr = cons.const_array(mfi);
218  const auto& z_phys_nd_arr = z_phys_nd.const_array(mfi);
219  const auto& z_phys_cc_arr = have_z_phys_cc && z_phys_cc != nullptr
220  ? z_phys_cc->const_array(mfi)
221  : cons.const_array(mfi);
222  const auto& xvel_arr = is_wind_field ? wind_sources.xvel->const_array(mfi) : cons.const_array(mfi);
223  const auto& yvel_arr = is_wind_field ? wind_sources.yvel->const_array(mfi) : cons.const_array(mfi);
224  const auto& zvel_arr = is_wind_field ? wind_sources.zvel->const_array(mfi) : cons.const_array(mfi);
225  const auto& cos_alpha_arr = have_rotation ? wind_sources.cos_alpha->const_array(mfi) : cons.const_array(mfi);
226  const auto& sin_alpha_arr = have_rotation ? wind_sources.sin_alpha->const_array(mfi) : cons.const_array(mfi);
227 
228  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
229  if (coordinate == SampledCoordinate::ModelIndex) {
230  if (target_k < klo || target_k > khi) {
231  dst_arr(i, j, k, dst_comp) = missing_value;
232  return;
233  }
234 
235  if (is_wind_field) {
236  const SampledEarthWind wind = earth_wind_at_cell_center(
237  i, j, target_k, xvel_arr, yvel_arr, zvel_arr, cos_alpha_arr, sin_alpha_arr,
238  have_rotation);
239  dst_arr(i, j, k, dst_comp) = wind_field_from_earth_wind(field_id, wind, missing_value);
240  } else {
241  dst_arr(i, j, k, dst_comp) =
242  sampled_field_value(field_id, cons_arr, z_phys_cc_arr, z_phys_nd_arr,
243  have_z_phys_cc, i, j, target_k, moisture_indices);
244  }
245  return;
246  }
247 
248  const auto bracket = find_sampled_bracket(coordinate, target, klo, khi, i, j,
249  cons_arr, z_phys_cc_arr, z_phys_nd_arr,
250  have_z_phys_cc, moisture_indices);
251  if (!bracket.found) {
252  dst_arr(i, j, k, dst_comp) = missing_value;
253  return;
254  }
255 
256  const Real coord_lo =
257  sampled_field_value((coordinate == SampledCoordinate::HeightMSL)
258  ? SampledFieldID::HeightMSL
259  : (coordinate == SampledCoordinate::HeightAGL)
260  ? SampledFieldID::HeightAGL
261  : SampledFieldID::Pressure,
262  cons_arr, z_phys_cc_arr, z_phys_nd_arr,
263  have_z_phys_cc, i, j, bracket.klo, moisture_indices);
264  const Real coord_hi =
265  sampled_field_value((coordinate == SampledCoordinate::HeightMSL)
266  ? SampledFieldID::HeightMSL
267  : (coordinate == SampledCoordinate::HeightAGL)
268  ? SampledFieldID::HeightAGL
269  : SampledFieldID::Pressure,
270  cons_arr, z_phys_cc_arr, z_phys_nd_arr,
271  have_z_phys_cc, i, j, bracket.khi, moisture_indices);
272  if (is_wind_field) {
273  const SampledEarthWind wind_lo = earth_wind_at_cell_center(
274  i, j, bracket.klo, xvel_arr, yvel_arr, zvel_arr, cos_alpha_arr, sin_alpha_arr,
275  have_rotation);
276  if (bracket.klo == bracket.khi) {
277  dst_arr(i, j, k, dst_comp) = wind_field_from_earth_wind(field_id, wind_lo, missing_value);
278  return;
279  }
280 
281  const SampledEarthWind wind_hi = earth_wind_at_cell_center(
282  i, j, bracket.khi, xvel_arr, yvel_arr, zvel_arr, cos_alpha_arr, sin_alpha_arr,
283  have_rotation);
284  SampledEarthWind wind_interp;
285  wind_interp.u_east = linear_interpolate(wind_lo.u_east, wind_hi.u_east, coord_lo, coord_hi, target);
286  wind_interp.v_north = linear_interpolate(wind_lo.v_north, wind_hi.v_north, coord_lo, coord_hi, target);
287  wind_interp.w = linear_interpolate(wind_lo.w, wind_hi.w, coord_lo, coord_hi, target);
288  dst_arr(i, j, k, dst_comp) = wind_field_from_earth_wind(field_id, wind_interp, missing_value);
289  } else {
290  const Real field_lo =
291  sampled_field_value(field_id, cons_arr, z_phys_cc_arr, z_phys_nd_arr,
292  have_z_phys_cc, i, j, bracket.klo, moisture_indices);
293  if (bracket.klo == bracket.khi) {
294  dst_arr(i, j, k, dst_comp) = field_lo;
295  return;
296  }
297 
298  const Real field_hi =
299  sampled_field_value(field_id, cons_arr, z_phys_cc_arr, z_phys_nd_arr,
300  have_z_phys_cc, i, j, bracket.khi, moisture_indices);
301  dst_arr(i, j, k, dst_comp) =
302  linear_interpolate(field_lo, field_hi, coord_lo, coord_hi, target);
303  }
304  });
305  }
306 }
const int khi
Definition: ERF_InitCustomPert_Bubble.H:21
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_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:91
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::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 
)
111 {
112  if (!src) {
113  fill_component_with_value(dst, dst_comp, missing_value);
114  return;
115  }
116 
117 #ifdef _OPENMP
118 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
119 #endif
120  for (MFIter mfi(dst, TilingIfNotGPU()); mfi.isValid(); ++mfi)
121  {
122  // Keep unit conversion in the surface-flux diagnostic helper so this
123  // mechanical layer does not duplicate physical constants or units.
124  const Box& bx = mfi.tilebox();
125  const auto& dst_arr = dst.array(mfi);
126  const auto& src_arr = src->const_array(mfi);
127 
128  ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
129  dst_arr(i, j, k, dst_comp) =
131  src_arr(i, j, src_k, 0));
132  });
133  }
134 }
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)
170 {
171  for (const auto& descriptor : diagnostic_catalog()) {
172  if (name == descriptor.name) {
173  return &descriptor;
174  }
175  }
176 
177  return nullptr;
178 }

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)
213 {
215  return nullptr;
216  }
217  return ensure_dynamic_soil_descriptor(name);
218 }

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)
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::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)
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
54 {
55  switch (id) {
56  case DiagnosticID::IntegratedQc:
57  case DiagnosticID::IntegratedQi:
58  case DiagnosticID::IntegratedQr:
59  case DiagnosticID::IntegratedQs:
60  case DiagnosticID::IntegratedQg:
61  return true;
62  default:
63  return false;
64  }
65 }

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

◆ is_dynamic_soil_diagnostic_name()

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

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

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
91 {
92 #ifdef ERF_USE_NOAHMP
93  return solver_choice.lsm_type == LandSurfaceType::NOAHMP;
94 #else
95  amrex::ignore_unused(solver_choice);
96  return false;
97 #endif
98 }
LandSurfaceType lsm_type
Land-surface model.
Definition: ERF_DataStruct.H:1607

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:

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

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.query((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.query((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.query((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  if (pp.query((base + "missing_value").c_str(), level_set.missing_value) == 0) {
344  level_set.missing_value = amrex::Real(-999.0);
345  }
346 
347  int n_values = pp.countval((base + "values").c_str());
348  if (n_values <= 0) {
349  amrex::Abort(build_missing_field_error(level_set_name, "values"));
350  }
351  level_set.values.resize(n_values);
352  pp.getarr((base + "values").c_str(), level_set.values, 0, n_values);
353 
354  int n_fields = pp.countval((base + "fields").c_str());
355  if (n_fields <= 0) {
356  amrex::Abort(build_missing_field_error(level_set_name, "fields"));
357  }
358  level_set.fields.resize(n_fields);
359  pp.getarr((base + "fields").c_str(), level_set.fields, 0, n_fields);
360 
361  const std::string error = validate_sampled_level_definition(level_set);
362  if (!error.empty()) {
363  amrex::Abort(error);
364  }
365 
366  return level_set;
367 }
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:147
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
148 {
149  switch (field_id) {
150  case SampledFieldID::Rho: return "rho";
151  case SampledFieldID::Theta: return "theta";
152  case SampledFieldID::Temp: return "temp";
153  case SampledFieldID::Pressure: return "pressure";
154  case SampledFieldID::HeightMSL: return "height_msl";
155  case SampledFieldID::HeightAGL: return "height_agl";
156  case SampledFieldID::Qv: return "qv";
157  case SampledFieldID::Qc: return "qc";
158  case SampledFieldID::Qi: return "qi";
159  case SampledFieldID::Qr: return "qr";
160  case SampledFieldID::Qs: return "qs";
161  case SampledFieldID::Qg: return "qg";
162  case SampledFieldID::UEast: return "u_east";
163  case SampledFieldID::VNorth: return "v_north";
164  case SampledFieldID::W: return "w";
165  case SampledFieldID::WindSpeed: return "wind_speed";
166  case SampledFieldID::WindDir: return "wind_dir";
167  }
168 
169  return "unknown";
170 }

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
98 {
99  const amrex::Real rho = cons_arr(i, j, k, Rho_comp);
100  const bool has_moisture = (moisture_indices.qv >= 0);
101  // Microphysical fields are sampled as mixing ratios. The conserved state
102  // stores rho*q, so field evaluation divides by rho before interpolation.
103  const amrex::Real qv_for_eos = has_moisture
104  ? cons_arr(i, j, k, moisture_indices.qv) / rho
105  : amrex::Real(0.0);
106 
107  switch (field_id) {
108  case SampledFieldID::Rho:
109  return rho;
111  return cons_arr(i, j, k, RhoTheta_comp) / rho;
112  case SampledFieldID::Temp:
113  return getTgivenRandRTh(rho, cons_arr(i, j, k, RhoTheta_comp), qv_for_eos);
114  case SampledFieldID::Pressure:
115  return getPgivenRTh(cons_arr(i, j, k, RhoTheta_comp), qv_for_eos);
116  case SampledFieldID::HeightMSL:
117  if (have_z_phys_cc) {
118  return z_phys_cc_arr(i, j, k);
119  }
120  return Compute_Z_AtCellCenter(i, j, k, z_phys_nd_arr);
121  case SampledFieldID::HeightAGL:
122  return Compute_Zrel_AtCellCenter(i, j, k, z_phys_nd_arr);
123  case SampledFieldID::Qv:
124  return has_moisture ? cons_arr(i, j, k, moisture_indices.qv) / rho : amrex::Real(0.0);
125  case SampledFieldID::Qc:
126  return (moisture_indices.qc >= 0) ? cons_arr(i, j, k, moisture_indices.qc) / rho : amrex::Real(0.0);
127  case SampledFieldID::Qi:
128  return (moisture_indices.qi >= 0) ? cons_arr(i, j, k, moisture_indices.qi) / rho : amrex::Real(0.0);
129  case SampledFieldID::Qr:
130  return (moisture_indices.qr >= 0) ? cons_arr(i, j, k, moisture_indices.qr) / rho : amrex::Real(0.0);
131  case SampledFieldID::Qs:
132  return (moisture_indices.qs >= 0) ? cons_arr(i, j, k, moisture_indices.qs) / rho : amrex::Real(0.0);
133  case SampledFieldID::Qg:
134  return (moisture_indices.qg >= 0) ? cons_arr(i, j, k, moisture_indices.qg) / rho : amrex::Real(0.0);
135  case SampledFieldID::UEast:
136  case SampledFieldID::VNorth:
137  case SampledFieldID::W:
138  case SampledFieldID::WindSpeed:
139  case SampledFieldID::WindDir:
140  return amrex::Real(0.0);
141  }
142 
143  return amrex::Real(0.0);
144 }
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 qi
Cloud ice component index.
Definition: ERF_DataStruct.H:169
int qv
Water vapor component index.
Definition: ERF_DataStruct.H:167
int qs
Snow component index.
Definition: ERF_DataStruct.H:171
int qr
Rain component index.
Definition: ERF_DataStruct.H:170
int qc
Cloud liquid water component index.
Definition: ERF_DataStruct.H:168
int qg
Graupel component index.
Definition: ERF_DataStruct.H:172

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")) {
188  return SampledInterpolation::None;
189  }
190  if (string_iequals(value, "linear")) {
191  return SampledInterpolation::Linear;
192  }
193 
194  amrex::Abort("Unknown sampled-level interpolation '" + value + "'");
195  return SampledInterpolation::None;
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) << "_"
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::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 
)
216 {
217  SelectedWaterPathComponents selected;
218 
219  for (int dst_comp = 0; dst_comp < static_cast<int>(plot_var_names.size()); ++dst_comp) {
220  const auto* descriptor = find_diagnostic(plot_var_names[dst_comp]);
222  continue;
223  }
224 
225  const int src_comp = source_component_for(descriptor->id, solver_choice.moisture_indices);
226  if (src_comp < 0) {
227  continue;
228  }
229 
230  selected.dst_comp[selected.n] = dst_comp;
231  selected.src_comp[selected.n] = src_comp;
232  ++selected.n;
233  }
234 
235  return selected;
236 }

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 
)
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  selected.dst_comp[selected.n] = dst_comp;
132  selected.id[selected.n] = descriptor->id;
133  ++selected.n;
134  }
135 
136  return selected;
137 }
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
26 {
27  return native_shoc_owns_scalar_fluxes &&
28  native_shoc_has_consumed_flux_diagnostics &&
29  host_flux_field_available;
30 }

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 
)
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 }
struct @28 out
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