ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_IntervalMeansCheckpoint.H
Go to the documentation of this file.
1 #ifndef ERF_INTERVAL_MEANS_CHECKPOINT_H_
2 #define ERF_INTERVAL_MEANS_CHECKPOINT_H_
3 
4 #include <cmath>
5 #include <istream>
6 #include <limits>
7 #include <sstream>
8 #include <string>
9 #include <vector>
10 
11 #include <AMReX_BoxArray.H>
12 #include <AMReX_IntVect.H>
13 #include <AMReX_Vector.H>
14 
15 namespace erf_interval_means {
16 
17 namespace detail {
18 
19 inline bool
20 read_int_vector (std::istream& input, amrex::IntVect& value)
21 {
22  char delimiter;
23  if (!(input >> delimiter) || delimiter != '(') return false;
24  for (int idir = 0; idir < AMREX_SPACEDIM; ++idir) {
25  if (idir > 0 && (!(input >> delimiter) || delimiter != ',')) return false;
26  if (!(input >> value[idir])) return false;
27  }
28  return static_cast<bool>(input >> delimiter) && delimiter == ')';
29 }
30 
31 // BoxArray::readFrom calls amrex::Error on malformed input. Checkpoint
32 // metadata is external input, so parse the format emitted by writeOn first
33 // and only construct a BoxArray after the complete record is validated.
34 inline bool
35 read_box_array (std::istream& input, amrex::BoxArray& result)
36 {
37  char delimiter;
38  long long box_count;
39  unsigned long long hash;
40  if (!(input >> delimiter) || delimiter != '(' ||
41  !(input >> box_count >> hash) || box_count < 0 ||
42  box_count > static_cast<long long>(std::numeric_limits<int>::max())) {
43  return false;
44  }
45 
46  std::vector<amrex::Box> boxes;
47  boxes.reserve(static_cast<std::size_t>(box_count));
48  for (long long ibox = 0; ibox < box_count; ++ibox) {
49  if (!(input >> delimiter) || delimiter != '(') return false;
50  amrex::IntVect small, big, type;
51  if (!read_int_vector(input, small) || !read_int_vector(input, big) ||
52  !read_int_vector(input, type) ||
53  !(input >> delimiter) || delimiter != ')') {
54  return false;
55  }
56  boxes.emplace_back(small, big, type);
57  }
58  if (!(input >> delimiter) || delimiter != ')') return false;
59 
60  result = boxes.empty()
61  ? amrex::BoxArray{}
62  : amrex::BoxArray(boxes.data(), static_cast<int>(boxes.size()));
63  return true;
64 }
65 
66 } // namespace detail
67 
69 {
70  int level{-1};
71  double accumulation_count{0.0};
72  int reset_done{0};
73  amrex::BoxArray boxes;
74  amrex::Vector<int> processor_map;
75 };
76 
77 struct Metadata
78 {
79  int levels{0};
80  int components{0};
81  amrex::Vector<LevelMetadata> level;
82 };
83 
84 inline bool
85 parse_metadata (std::istream& input, Metadata& result, std::string& error)
86 {
87  std::string title;
88  if (!std::getline(input, title) || title != "ERF interval means checkpoint v1") {
89  error = "expected ERF interval means checkpoint v1 title";
90  return false;
91  }
92  if (!(input >> result.levels >> result.components) || result.levels < 0 ||
93  result.components < 0) {
94  error = "missing or invalid interval-mean level/component counts";
95  return false;
96  }
97 
98  result.level.clear();
99  result.level.resize(result.levels);
100  for (int lev = 0; lev < result.levels; ++lev) {
101  auto& record = result.level[lev];
102  if (!(input >> record.level >> record.accumulation_count >> record.reset_done) ||
103  record.level != lev || !std::isfinite(record.accumulation_count) ||
104  record.accumulation_count < 0.0 ||
105  (record.reset_done != 0 && record.reset_done != 1)) {
106  error = "invalid interval-mean level record " + std::to_string(lev);
107  return false;
108  }
109 
110  if (!detail::read_box_array(input, record.boxes)) {
111  error = "truncated interval-mean BoxArray record for level " +
112  std::to_string(lev);
113  return false;
114  }
115  std::string box_remainder;
116  if (!std::getline(input, box_remainder)) {
117  error = "truncated interval-mean BoxArray line for level " +
118  std::to_string(lev);
119  return false;
120  }
121 
122  long long map_size = -1;
123  if (!(input >> map_size) || map_size < 0 ||
124  map_size != static_cast<long long>(record.boxes.size())) {
125  error = "invalid interval-mean processor-map size for level " +
126  std::to_string(lev);
127  return false;
128  }
129  record.processor_map.resize(static_cast<std::size_t>(map_size));
130  for (long long ibox = 0; ibox < map_size; ++ibox) {
131  if (!(input >> record.processor_map[static_cast<std::size_t>(ibox)])) {
132  error = "truncated interval-mean processor map for level " +
133  std::to_string(lev);
134  return false;
135  }
136  }
137  }
138  return true;
139 }
140 
141 inline std::string
142 validate_metadata (const Metadata& metadata,
143  int expected_levels,
144  int expected_components,
145  const amrex::Vector<amrex::BoxArray>& expected_boxes)
146 {
147  if (metadata.levels != expected_levels || metadata.components != expected_components) {
148  return "expected " + std::to_string(expected_levels) + " levels and " +
149  std::to_string(expected_components) + " components";
150  }
151  if (static_cast<int>(expected_boxes.size()) < expected_levels ||
152  static_cast<int>(metadata.level.size()) != expected_levels) {
153  return "interval-mean metadata level count does not match the restart";
154  }
155  for (int lev = 0; lev < expected_levels; ++lev) {
156  if (!(metadata.level[lev].boxes == expected_boxes[lev])) {
157  return "interval-mean checkpoint BoxArray does not match level " +
158  std::to_string(lev);
159  }
160  }
161  return {};
162 }
163 
164 inline int
165 global_reset_done (const Metadata& metadata)
166 {
167  for (const auto& record : metadata.level) {
168  if (record.reset_done != 0) return 1;
169  }
170  return 0;
171 }
172 
173 inline int
174 legacy_reset_done (bool time_reset_mode, double checkpoint_time, double reset_time)
175 {
176  return time_reset_mode && checkpoint_time >= reset_time ? 1 : 0;
177 }
178 
179 inline bool
180 initialization_accumulates_state (bool restarting) noexcept
181 {
182  return !restarting;
183 }
184 
185 inline bool
187  bool interval_diagnostic_selected) noexcept
188 {
189  return !restarting && interval_diagnostic_selected;
190 }
191 
192 } // namespace erf_interval_means
193 
194 #endif
bool read_box_array(std::istream &input, amrex::BoxArray &result)
Definition: ERF_IntervalMeansCheckpoint.H:35
bool read_int_vector(std::istream &input, amrex::IntVect &value)
Definition: ERF_IntervalMeansCheckpoint.H:20
Definition: ERF_IntervalMeansCheckpoint.H:15
bool initialization_plot_consumes_interval(bool restarting, bool interval_diagnostic_selected) noexcept
Definition: ERF_IntervalMeansCheckpoint.H:186
int legacy_reset_done(bool time_reset_mode, double checkpoint_time, double reset_time)
Definition: ERF_IntervalMeansCheckpoint.H:174
bool initialization_accumulates_state(bool restarting) noexcept
Definition: ERF_IntervalMeansCheckpoint.H:180
std::string validate_metadata(const Metadata &metadata, int expected_levels, int expected_components, const amrex::Vector< amrex::BoxArray > &expected_boxes)
Definition: ERF_IntervalMeansCheckpoint.H:142
bool parse_metadata(std::istream &input, Metadata &result, std::string &error)
Definition: ERF_IntervalMeansCheckpoint.H:85
int global_reset_done(const Metadata &metadata)
Definition: ERF_IntervalMeansCheckpoint.H:165
Definition: ERF_IntervalMeansCheckpoint.H:69
amrex::BoxArray boxes
Definition: ERF_IntervalMeansCheckpoint.H:73
amrex::Vector< int > processor_map
Definition: ERF_IntervalMeansCheckpoint.H:74
int level
Definition: ERF_IntervalMeansCheckpoint.H:70
int reset_done
Definition: ERF_IntervalMeansCheckpoint.H:72
double accumulation_count
Definition: ERF_IntervalMeansCheckpoint.H:71
Definition: ERF_IntervalMeansCheckpoint.H:78
int levels
Definition: ERF_IntervalMeansCheckpoint.H:79
int components
Definition: ERF_IntervalMeansCheckpoint.H:80
amrex::Vector< LevelMetadata > level
Definition: ERF_IntervalMeansCheckpoint.H:81