OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
Report2DVars.hpp
Go to the documentation of this file.
1
15
16#ifndef OPENSWMM_ENGINE_2D_REPORT2D_VARS_HPP
17#define OPENSWMM_ENGINE_2D_REPORT2D_VARS_HPP
18
19#include "SolverOptions2D.hpp"
20
21#include <cctype>
22#include <cmath>
23#include <cstdio>
24#include <limits>
25#include <string>
26#include <vector>
27
29
37inline const std::vector<std::string>& tokens() {
38 static const std::vector<std::string> kTokens = {
39 "DEPTH", "VELOCITY", "EDGE_FLUX", "NODE_HEAD", "SPECIES", "RAINFALL",
40 "INFILTRATION", "COUPLING", "GRADIENTS", "CONTINUITY", "ENVELOPES",
41 "BUILDUP", // S7
42 "GROUNDWATER", "GW_DETAILED", // G-O
43 "HEAT", "TURBULENCE",
44 };
45 return kTokens;
46}
47
55inline bool iequalsTok(const std::string& a, const char* b) {
56 std::size_t i = 0;
57 for (; i < a.size() && b[i]; ++i)
58 if (std::toupper(static_cast<unsigned char>(a[i])) !=
59 std::toupper(static_cast<unsigned char>(b[i])))
60 return false;
61 return i == a.size() && b[i] == '\0';
62}
63
72inline std::vector<std::string> splitList(const std::string& text) {
73 std::vector<std::string> toks;
74 std::string cur;
75 for (char c : text) {
76 if (c == ',' || c == ' ' || c == '\t' || c == '\r' || c == '\n') {
77 if (!cur.empty()) {
78 toks.push_back(cur);
79 cur.clear();
80 }
81 } else {
82 cur += c;
83 }
84 }
85 if (!cur.empty())
86 toks.push_back(cur);
87 return toks;
88}
89
102inline std::string parseMask(const std::string& text, unsigned& mask) {
103 mask = 0;
104 const auto toks = splitList(text);
105 if (toks.empty())
106 return "REPORT_2D_VARIABLES needs DEFAULT|MINIMAL|ALL or a token list";
107 const auto& names = tokens();
108 for (const auto& t : toks) {
109 if (iequalsTok(t, "DEFAULT")) {
110 mask |= DEFAULT_MASK;
111 continue;
112 }
113 if (iequalsTok(t, "MINIMAL")) {
114 mask |= MINIMAL_MASK;
115 continue;
116 }
117 if (iequalsTok(t, "ALL")) {
118 mask |= ALL_MASK;
119 continue;
120 }
121 if (iequalsTok(t, "NONE")) {
122 continue;
123 }
124 bool found = false;
125 for (std::size_t i = 0; i < names.size(); ++i) {
126 if (iequalsTok(t, names[i].c_str())) {
127 mask |= (1u << i);
128 found = true;
129 break;
130 }
131 }
132 if (!found) {
133 std::string all;
134 for (const auto& n : names) {
135 if (!all.empty())
136 all += "|";
137 all += n;
138 }
139 return "Unknown REPORT_2D_VARIABLES token '" + t +
140 "' (expected DEFAULT|MINIMAL|ALL|NONE or " + all + ")";
141 }
142 }
143 mask |= DEPTH;
144 return {};
145}
146
154inline std::string formatMask(unsigned mask) {
155 mask &= ALL_MASK;
156 if (mask == DEFAULT_MASK)
157 return "DEFAULT";
158 if (mask == MINIMAL_MASK)
159 return "MINIMAL";
160 if (mask == ALL_MASK)
161 return "ALL";
162 const auto& names = tokens();
163 std::string out;
164 for (std::size_t i = 0; i < names.size(); ++i) {
165 if (mask & (1u << i)) {
166 if (!out.empty())
167 out += ' ';
168 out += names[i];
169 }
170 }
171 return out.empty() ? std::string("DEPTH") : out;
172}
173
181inline std::string formatSpecies(const std::vector<std::string>& species) {
182 if (species.empty())
183 return "ALL";
184 std::string out;
185 for (const auto& n : species) {
186 if (!out.empty())
187 out += ' ';
188 out += n;
189 }
190 return out;
191}
192
201inline std::vector<std::string> parseSpecies(const std::string& text) {
202 auto v = splitList(text);
203 if (v.size() == 1 && iequalsTok(v[0], "ALL"))
204 v.clear();
205 return v;
206}
207
216inline std::string formatStep(double seconds) {
217 char buf[64];
218 if (!(seconds > 0))
219 return "00:00:00";
220 // Fractional report/infiltration cadences must survive API and INP
221 // roundtrips. These 2D keys accept bare numeric seconds directly.
222 if (std::floor(seconds) != seconds ||
223 seconds >= static_cast<double>(std::numeric_limits<long>::max())) {
224 std::snprintf(buf, sizeof(buf), "%.17g", seconds);
225 return buf;
226 }
227 const long total = seconds > 0.0 ? static_cast<long>(seconds) : 0L;
228 std::snprintf(buf, sizeof(buf), "%02ld:%02ld:%02ld", total / 3600, (total % 3600) / 60,
229 total % 60);
230 return buf;
231}
232
233} // namespace openswmm::twoD::report2d
234
235#endif // OPENSWMM_ENGINE_2D_REPORT2D_VARS_HPP
Configuration options for the 2D surface routing solver.
Dataset groups the 2D results writer can emit ([2D_OPTIONS] REPORT_2D_VARIABLES). One bit per group; ...
Definition Report2DVars.hpp:28
const std::vector< std::string > & tokens()
Group tokens in bit order (index i ↔ bit 1u << i).
Definition Report2DVars.hpp:37
std::string parseMask(const std::string &text, unsigned &mask)
Parse a token list or a preset (DEFAULT | MINIMAL | ALL | NONE) into a bitmask. DEPTH is always inclu...
Definition Report2DVars.hpp:102
std::string formatMask(unsigned mask)
Preset name when the mask equals one, else the space-separated token list.
Definition Report2DVars.hpp:154
std::vector< std::string > splitList(const std::string &text)
Split on whitespace / commas.
Definition Report2DVars.hpp:72
std::string formatStep(double seconds)
Preserve whole and fractional 2D cadence values.
Definition Report2DVars.hpp:216
std::vector< std::string > parseSpecies(const std::string &text)
Species list from text; "ALL" (alone) → empty list.
Definition Report2DVars.hpp:201
@ ALL_MASK
Definition SolverOptions2D.hpp:235
@ DEPTH
Mesh2_face_depth, Mesh2_face_head.
Definition SolverOptions2D.hpp:216
@ MINIMAL_MASK
MINIMAL: depth map + render reconstruction + envelopes only.
Definition SolverOptions2D.hpp:240
@ DEFAULT_MASK
DEFAULT: everything a user renders or plots; solver diagnostics off.
Definition SolverOptions2D.hpp:237
std::string formatSpecies(const std::vector< std::string > &species)
"ALL" for an empty (unfiltered) list, else the space-separated names.
Definition Report2DVars.hpp:181
bool iequalsTok(const std::string &a, const char *b)
Compare one report token against a required literal ignoring byte case.
Definition Report2DVars.hpp:55