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, const MultiFab *p_hse)
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool sampled_target_is_bracketed (amrex::Real target, amrex::Real c0, amrex::Real c1) noexcept
 
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real linear_interpolate (amrex::Real lo_value, amrex::Real hi_value, amrex::Real lo_coord, amrex::Real hi_coord, amrex::Real target) noexcept
 
void fill_sampled_level_component (amrex::MultiFab &dst, int dst_comp, const Plotfile2DOutputDescriptor &descriptor, const amrex::MultiFab &cons, const amrex::MultiFab *z_phys_cc, const amrex::MultiFab &z_phys_nd, bool have_z_phys_cc, const MoistureComponentIndices &moisture_indices, int klo, int khi, const SampledWindSources &wind_sources={}, const amrex::MultiFab *p_hse=nullptr)
 
const char * diagnostic_category_to_string (DiagnosticCategory category) noexcept
 
const char * missing_policy_to_string (MissingPolicy policy) noexcept
 
std::string missing_value_json (MissingPolicy policy)
 
std::string escape_json_string (const std::string &value)
 
std::string metadata_json_filename (const std::string &plotfilename)
 
std::string format_2d_metadata_json (const amrex::Vector< std::string > &varnames)
 
std::string format_2d_metadata_json (const amrex::Vector< Plotfile2DOutputDescriptor > &descriptors)
 
void write_2d_metadata_json (const std::string &plotfilename, const amrex::Vector< std::string > &varnames)
 
void write_2d_metadata_json (const std::string &plotfilename, const amrex::Vector< Plotfile2DOutputDescriptor > &descriptors)
 
bool is_precipitation_accumulation (DiagnosticID id) noexcept
 
bool is_precipitation_accumulation_name (const std::string &name)
 
bool precipitation_diagnostic_available (DiagnosticID id, const MoistureComponentIndices &moisture_indices) noexcept
 
SelectedSurfacePrecipAccumulationComponents selected_precipitation_accumulation_components (const amrex::Vector< std::string > &plot_var_names, const SurfacePrecipAccumulationSources &sources)
 
void fill_precipitation_accumulations (MultiFab &dst, const SurfacePrecipAccumulationSources &sources, const SelectedSurfacePrecipAccumulationComponents &selected, const int klo)
 
void fill_precipitation_accumulations (amrex::MultiFab &dst, const SurfacePrecipAccumulationSources &sources, const SelectedSurfacePrecipAccumulationComponents &selected, const int klo)
 
const amrex::Vector< SampledFieldDescriptor > & sampled_field_catalog ()
 
const 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, const amrex::Array4< const amrex::Real > &p_hse_arr, bool have_z_phys_cc, bool use_hse_pressure, int i, int j, int k, const MoistureComponentIndices &moisture_indices) noexcept
 
const char * sampled_field_name (SampledFieldID field_id) noexcept
 
const char * sampled_coordinate_to_string (SampledCoordinate coordinate) noexcept
 
const char * sampled_coordinate_tag (SampledCoordinate coordinate) noexcept
 
const char * sampled_coordinate_default_units (SampledCoordinate coordinate) noexcept
 
const char * sampled_coordinate_default_interpolation (SampledCoordinate coordinate) noexcept
 
const char * sampled_interpolation_to_string (SampledInterpolation interpolation) noexcept
 
SampledCoordinate sampled_coordinate_from_string (const std::string &value)
 
SampledInterpolation sampled_interpolation_from_string (const std::string &value)
 
std::string validate_sampled_coordinate_string (const std::string &level_set_name, const std::string &value)
 
std::string sampled_level_error_prefix (const std::string &level_set_name, const std::string &parameter_name)
 
std::string sampled_level_value_tag (amrex::Real value, const std::string &units)
 
std::string sampled_output_name (const std::string &field_name, SampledCoordinate coordinate, amrex::Real value, const std::string &units)
 
std::string validate_sampled_level_definition (const SampledLevelDefinition &level_set)
 
SampledLevelDefinition parse_sampled_level_definition (const std::string &level_set_name, const std::string &pp_prefix)
 
amrex::Vector< std::string > parse_requested_sampled_level_sets (const std::string &pp_prefix, int which)
 
amrex::Vector< 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 
85 {
86  Geometry,
88  Radiation,
90  PBL,
96 };
Wrapper class for managing land surface models across AMR levels.
Definition: ERF_LandSurface.H:19
Definition: ERF_Radiation.H:45
Definition: ERF_SurfaceLayer.H:39

◆ 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
Index map of the moisture data carried by the active scheme: conserved-state components for the speci...
Definition: ERF_DataStruct.H:2144

◆ 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.queryAdd("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:2124

Referenced by available_diagnostic_names().

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

◆ available_sampled_field_names()

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

◆ build_sampled_level_output_descriptors()

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

Referenced by ERF::Write2DPlotFile().

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

◆ build_sampled_level_output_descriptors_from_definitions()

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

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:43
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool surface_precip_has_any_source(const SurfacePrecipAccumulationSources &src) noexcept
Definition: ERF_SurfacePrecipitation.H:61
@ graupel
Definition: ERF_NOAHMP_Fields.H: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:20
const amrex::MultiFab * accum
Definition: ERF_SurfacePrecipitation.H:21
amrex::Real native_to_kg_m2
Definition: ERF_SurfacePrecipitation.H:22
SurfacePrecipAccumulationSource rain
Definition: ERF_SurfacePrecipitation.H:36
SurfacePrecipAccumulationSource snow
Definition: ERF_SurfacePrecipitation.H:37
SurfacePrecipAccumulationSource hail
Definition: ERF_SurfacePrecipitation.H:39
SurfacePrecipAccumulationSource total
Definition: ERF_SurfacePrecipitation.H:35
SurfacePrecipAccumulationSource graupel
Definition: ERF_SurfacePrecipitation.H:38

Referenced by ERF::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 = {},
const amrex::MultiFab *  p_hse = nullptr 
)

◆ fill_sampled_level_component() [2/2]

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

Referenced by ERF::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:2127

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

Referenced by build_sampled_level_output_descriptors().

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

◆ parse_sampled_level_definition()

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

Referenced by build_sampled_level_output_descriptors().

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

◆ precipitation_diagnostic_available()

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

Referenced by available_diagnostic_names().

Here is the caller graph for this function:

◆ sampled_coordinate_default_interpolation()

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

Referenced by parse_sampled_level_definition(), and validate_sampled_level_definition().

Here is the caller graph for this function:

◆ sampled_coordinate_default_units()

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

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

Here is the caller graph for this function:

◆ sampled_coordinate_from_string()

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

Referenced by fill_sampled_level_component(), and parse_sampled_level_definition().

Here is the caller graph for this function:

◆ sampled_coordinate_tag()

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

Referenced by sampled_output_name().

Here is the caller graph for this function:

◆ sampled_coordinate_to_string()

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

Referenced by build_sampled_level_output_descriptors_from_definitions(), and validate_sampled_level_definition().

Here is the caller graph for this function:

◆ sampled_field_catalog()

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

Referenced by available_sampled_field_names(), and find_sampled_field().

Here is the caller graph for this function:

◆ sampled_field_id_to_string()

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

◆ sampled_field_is_scalar_state()

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

◆ sampled_field_is_wind()

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

Referenced by fill_sampled_level_component(), and sampled_field_is_scalar_state().

Here is the caller graph for this function:

◆ sampled_field_name()

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

Referenced by sampled_field_id_to_string().

Here is the caller graph for this function:

◆ sampled_field_value()

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

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) << "_"
245  << sampled_level_value_tag(value, units);
246  return os.str();
247 }
const char * sampled_coordinate_tag(SampledCoordinate coordinate) noexcept
Definition: ERF_Plotfile2DSampledLevel.cpp:131
std::string sampled_level_value_tag(amrex::Real value, const std::string &units)
Definition: ERF_Plotfile2DSampledLevel.cpp:228

Referenced by build_sampled_level_output_descriptors_from_definitions().

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

◆ sampled_target_is_bracketed()

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

◆ select_requested_plot_variables()

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

Referenced by ERF::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:49
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool surface_precip_has_any_frozen_source(const SurfacePrecipAccumulationSources &src) noexcept
Definition: ERF_SurfacePrecipitation.H:71

Referenced by ERF::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 }
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