OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
GwTransportData.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2//
3// Copyright 2026 Caleb Buahin
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
44
45#ifndef OPENSWMM_ENGINE_2D_GW_TRANSPORT_DATA_HPP
46#define OPENSWMM_ENGINE_2D_GW_TRANSPORT_DATA_HPP
47
48#include <cstdint>
49#include <limits>
50#include <set>
51#include <unordered_map>
52#include <string>
53#include <vector>
54
55namespace openswmm::twoD {
56
58enum class GwZone : int8_t {
59 SAT = 0,
60 UNSAT = 1,
61 LAYER = 2
62};
63
65enum class GwScope : int8_t {
66 GLOBAL = 0,
67 TAG = 1,
68 CELL = 2
69};
70
76 std::string unsat_transport = "BULK";
77 // Explicit opt-in; dormant legacy CONDUCTION flags never activate it.
78 std::string thermal_model = "WATER_ONLY";
80 bool lateral_conduction = false;
83 std::string soil_et_heat = "LATENT_SURFACE";
84 std::set<std::string> thermal_authored;
86 bool transport_msx = true;
87 bool transport_age = true;
89 bool dispersion = true;
90 bool conduction = true;
93 std::string surface_thermal_bc = "AIR";
97 std::string deep_thermal_bc = "GEOTHERMAL_FLUX";
98 std::string deep_thermal_arg;
99 double deep_depth = 0.0;
101 std::string thermal_mixing = "ARITHMETIC";
103 double c_diff = 0.4;
107 bool authored = false;
108};
109
113 std::string tag;
114 int cell = -1;
115 double rho_s = 2650.0;
116 double c_s = 880.0;
117 double lambda_s = 2.0;
118 double a_s = 0.0;
119 double alpha_L = 1.0;
120 double alpha_T = 0.1;
121 double D_m = 1.0e-9;
122 double D_v = 1.0e-9;
123 double geo_flux = 0.065;
124};
125
129 std::string tag;
130 int cell = -1;
131 std::string species;
132 double kd = 0.0;
133 double decay = -1.0;
134};
135
139 std::string tag;
140 int cell = -1;
142 int layer = -1;
143 std::string species;
144 double value = 0.0;
145};
146
149 int cell = -1;
150 int edge = -1;
151 std::string species;
153 std::string kind = "CONC";
154 double value = 0.0;
155 std::string ts_name;
156};
157
160 std::string species;
161 std::string kind = "CONC";
162 double value = 0.0;
163 std::string ts_name;
164};
165
168 std::string name;
170 std::string tag;
171 int cell = -1;
172 double x = 0.0, y = 0.0;
173 bool by_xy = false;
174 double flow = 0.0;
175 std::string flow_ts;
176 double scale = 1.0;
177 std::vector<GwSourceSpeciesTerm> species;
178};
179
189 std::vector<GwParamsRow> params;
190 std::vector<GwSorptionRow> sorption;
191 std::vector<GwInitialQualityRow> initial_quality;
194 std::vector<GwBoundaryQualityRow> boundary_quality;
195 std::vector<GwSourceRow> sources;
196
202 bool empty() const noexcept {
203 return !options.authored && params.empty() && sorption.empty() && initial_quality.empty() &&
204 initial_quality_file.empty() && boundary_quality.empty() && sources.empty();
205 }
206
212 void clear() { *this = GwTransportData{}; }
213
214 // Derived authoring indexes contain positions, never vector pointers. Direct
215 // key edits or bulk replacement must invalidate them; parser and FILE reload
216 // do so explicitly. Size checks also catch ordinary direct append/erase.
223 void invalidateAuthoringIndexes() noexcept { source_index_size_ = quality_index_size_ = noRow; }
224 static constexpr std::size_t noRow = std::numeric_limits<std::size_t>::max();
225
236 std::size_t findSource(const std::string& name) {
237 if (source_index_size_ != sources.size()) {
238 source_index_size_ = noRow;
239 source_index_.clear();
240 source_index_.reserve(sources.size());
241 for (std::size_t i = 0; i < sources.size(); ++i)
242 source_index_.emplace(sources[i].name, i); // first match wins
243 source_index_size_ = sources.size();
244 }
245 const auto it = source_index_.find(name);
246 return it == source_index_.end() ? noRow : it->second;
247 }
248
257 std::size_t findInitialQuality(const GwInitialQualityRow& row) {
258 if (quality_index_size_ != initial_quality.size()) {
259 quality_index_size_ = noRow;
260 quality_index_.clear();
261 quality_index_.reserve(initial_quality.size());
262 for (std::size_t i = 0; i < initial_quality.size(); ++i)
263 quality_index_.emplace(QualityKey(initial_quality[i]), i);
264 quality_index_size_ = initial_quality.size();
265 }
266 const auto it = quality_index_.find(QualityKey(row));
267 return it == quality_index_.end() ? noRow : it->second;
268 }
269
280 if (source_index_size_ != noRow && source_index_size_ + 1 == sources.size()) {
281 source_index_.emplace(sources.back().name, sources.size() - 1);
282 source_index_size_ = sources.size();
283 }
284 }
285
296 if (quality_index_size_ != noRow && quality_index_size_ + 1 == initial_quality.size()) {
297 quality_index_.emplace(QualityKey(initial_quality.back()), initial_quality.size() - 1);
298 quality_index_size_ = initial_quality.size();
299 }
300 }
301
310 void removeSource(std::size_t index) {
311 if (source_index_size_ == sources.size() && index + 1 == sources.size()) {
312 const auto it = source_index_.find(sources[index].name);
313 if (it != source_index_.end() && it->second == index)
314 source_index_.erase(it);
315 --source_index_size_;
316 } else
317 source_index_size_ = noRow;
318 sources.erase(sources.begin() + index);
319 }
320
329 void removeInitialQuality(std::size_t index) {
330 if (quality_index_size_ == initial_quality.size() && index + 1 == initial_quality.size()) {
331 const auto it = quality_index_.find(QualityKey(initial_quality[index]));
332 if (it != quality_index_.end() && it->second == index)
333 quality_index_.erase(it);
334 --quality_index_size_;
335 } else
336 quality_index_size_ = noRow;
337 initial_quality.erase(initial_quality.begin() + index);
338 }
339
340private:
341 struct QualityKey {
342 GwScope scope;
343 std::string tag;
344 int cell;
345 GwZone zone;
346 int layer;
347 std::string species;
354 explicit QualityKey(const GwInitialQualityRow& r)
355 : scope(r.scope), tag(r.tag), cell(r.cell), zone(r.zone), layer(r.layer),
356 species(r.species) {}
363 bool operator==(const QualityKey& r) const noexcept {
364 return scope == r.scope && tag == r.tag && cell == r.cell && zone == r.zone &&
365 layer == r.layer && species == r.species;
366 }
367 };
368 struct QualityHash {
375 std::size_t operator()(const QualityKey& r) const noexcept {
376 std::size_t h = 0;
377 const auto combine = [&h](std::size_t v) {
378 h ^= v + 0x9e3779b9u + (h << 6) + (h >> 2);
379 };
380 combine(std::hash<int>{}(static_cast<int>(r.scope)));
381 combine(std::hash<std::string>{}(r.tag));
382 combine(std::hash<int>{}(r.cell));
383 combine(std::hash<int>{}(static_cast<int>(r.zone)));
384 combine(std::hash<int>{}(r.layer));
385 combine(std::hash<std::string>{}(r.species));
386 return h;
387 }
388 };
389 std::unordered_map<std::string, std::size_t> source_index_;
390 std::unordered_map<QualityKey, std::size_t, QualityHash> quality_index_;
391 std::size_t source_index_size_ = noRow;
392 std::size_t quality_index_size_ = noRow;
393};
394
401const char* gwZoneToken(GwZone z) noexcept;
409bool parseGwZone(const std::string& token, GwZone& z) noexcept;
416const char* gwScopeToken(GwScope s) noexcept;
417
418} // namespace openswmm::twoD
419
420#endif // OPENSWMM_ENGINE_2D_GW_TRANSPORT_DATA_HPP
Definition ExchangeLaw.hpp:60
@ CELL
Definition SolverOptions2D.hpp:143
const char * gwScopeToken(GwScope s) noexcept
Borrow the input-section token for an aquifer row scope.
Definition GwTransportSections.cpp:235
GwScope
Scope of a per-cell row.
Definition GwTransportData.hpp:65
@ GLOBAL
the * row
Definition GwTransportData.hpp:66
@ CELL
one cell, by 0-based index (1-based in the file)
Definition GwTransportData.hpp:68
@ TAG
every cell carrying tag
Definition GwTransportData.hpp:67
const char * gwZoneToken(GwZone z) noexcept
Borrow the input-section token for an aquifer zone.
Definition GwTransportSections.cpp:196
GwZone
Which zone of the two-zone column a row addresses.
Definition GwTransportData.hpp:58
@ UNSAT
unsaturated (upper) zone
Definition GwTransportData.hpp:60
@ SAT
saturated (lower) zone
Definition GwTransportData.hpp:59
@ LAYER
an explicit layer index (layer field)
Definition GwTransportData.hpp:61
bool parseGwZone(const std::string &token, GwZone &z) noexcept
Parse one aquifer zone token without changing state on failure.
Definition GwTransportSections.cpp:214
One [GW_BOUNDARY_QUALITY] row — a lateral edge BC.
Definition GwTransportData.hpp:148
int edge
local edge 0..nv-1 of that cell
Definition GwTransportData.hpp:150
int cell
0-based cell index
Definition GwTransportData.hpp:149
std::string species
Definition GwTransportData.hpp:151
double value
constant form
Definition GwTransportData.hpp:154
std::string ts_name
TS form (kind == "TS", or a TS argument)
Definition GwTransportData.hpp:155
std::string kind
CONC | TS | MASSFLUX | HEATFLUX.
Definition GwTransportData.hpp:153
One [GW_INITIAL_QUALITY] row.
Definition GwTransportData.hpp:137
GwZone zone
Definition GwTransportData.hpp:141
std::string species
Definition GwTransportData.hpp:143
double value
Definition GwTransportData.hpp:144
std::string tag
Definition GwTransportData.hpp:139
int layer
LAYER zone only.
Definition GwTransportData.hpp:142
GwScope scope
Definition GwTransportData.hpp:138
int cell
Definition GwTransportData.hpp:140
One [GW_TRANSPORT_PARAMS] row: solute + thermal matrix properties.
Definition GwTransportData.hpp:111
double rho_s
grain density (kg/m3)
Definition GwTransportData.hpp:115
double alpha_L
longitudinal dispersivity (m)
Definition GwTransportData.hpp:119
double lambda_s
grain thermal conductivity (W/m/K)
Definition GwTransportData.hpp:117
double a_s
specific surface area (m2/kg)
Definition GwTransportData.hpp:118
double D_v
vapour diffusivity (m2/s)
Definition GwTransportData.hpp:122
double D_m
molecular diffusivity (m2/s)
Definition GwTransportData.hpp:121
GwScope scope
Definition GwTransportData.hpp:112
double c_s
grain specific heat (J/kg/K)
Definition GwTransportData.hpp:116
double geo_flux
geothermal flux (W/m2) or deep temp (degC)
Definition GwTransportData.hpp:123
double alpha_T
transverse dispersivity (m)
Definition GwTransportData.hpp:120
int cell
CELL scope (0-based)
Definition GwTransportData.hpp:114
std::string tag
TAG scope.
Definition GwTransportData.hpp:113
One [GW_SORPTION] row: retardation input for one species in one scope.
Definition GwTransportData.hpp:127
double decay
1/day; < 0 = "use [POLLUTANTS] kdecay"
Definition GwTransportData.hpp:133
GwScope scope
Definition GwTransportData.hpp:128
int cell
Definition GwTransportData.hpp:130
std::string species
Definition GwTransportData.hpp:131
std::string tag
Definition GwTransportData.hpp:129
double kd
partition coefficient (L/kg)
Definition GwTransportData.hpp:132
One [GW_SOURCES] row — a well / point source or sink.
Definition GwTransportData.hpp:167
std::string name
Definition GwTransportData.hpp:168
double y
XY form (retained for the writer)
Definition GwTransportData.hpp:172
double scale
source-total multiplier, also applied to MASS (not CONC)
Definition GwTransportData.hpp:176
GwScope scope
CELL | TAG | (XY resolves to CELL)
Definition GwTransportData.hpp:169
bool by_xy
Definition GwTransportData.hpp:173
int cell
Definition GwTransportData.hpp:171
std::vector< GwSourceSpeciesTerm > species
Definition GwTransportData.hpp:177
double x
Definition GwTransportData.hpp:172
double flow
m3/s, + inject / − extract
Definition GwTransportData.hpp:174
std::string tag
Definition GwTransportData.hpp:170
std::string flow_ts
when the FLOW argument is a series
Definition GwTransportData.hpp:175
One [GW_SOURCES] species term.
Definition GwTransportData.hpp:159
std::string species
Definition GwTransportData.hpp:160
std::string kind
CONC | MASS.
Definition GwTransportData.hpp:161
double value
Definition GwTransportData.hpp:162
std::string ts_name
Definition GwTransportData.hpp:163
Every [GW_*] authoring row of one model.
Definition GwTransportData.hpp:187
std::size_t findSource(const std::string &name)
Resolve the first exact named groundwater source with lazy index rebuild.
Definition GwTransportData.hpp:236
std::vector< GwSourceRow > sources
Definition GwTransportData.hpp:195
void clear()
Replace all groundwater transport authoring state with default empty data.
Definition GwTransportData.hpp:212
std::size_t findInitialQuality(const GwInitialQualityRow &row)
Resolve the first complete initial-quality row key using a lazy cache.
Definition GwTransportData.hpp:257
std::vector< GwInitialQualityRow > initial_quality
Definition GwTransportData.hpp:191
void removeInitialQuality(std::size_t index)
Erase one initial_quality row while maintaining or invalidating its lookup cache.
Definition GwTransportData.hpp:329
bool empty() const noexcept
Test whether any groundwater transport section was authored or has rows.
Definition GwTransportData.hpp:202
static constexpr std::size_t noRow
Definition GwTransportData.hpp:224
std::vector< GwSorptionRow > sorption
Definition GwTransportData.hpp:190
std::string initial_quality_file
[GW_INITIAL_QUALITY] FILE <csv> (element,zone,species,value).
Definition GwTransportData.hpp:193
GwTransportOptions options
Definition GwTransportData.hpp:188
void removeSource(std::size_t index)
Erase one sources row while maintaining or invalidating its lookup cache.
Definition GwTransportData.hpp:310
std::vector< GwBoundaryQualityRow > boundary_quality
Definition GwTransportData.hpp:194
std::vector< GwParamsRow > params
Definition GwTransportData.hpp:189
void initialQualityAppended()
Incrementally extend a valid initial_quality authoring index after one append.
Definition GwTransportData.hpp:295
void invalidateAuthoringIndexes() noexcept
Mark source/initial-quality name indexes stale after direct key edits.
Definition GwTransportData.hpp:223
void sourceAppended()
Incrementally extend a valid sources authoring index after one append.
Definition GwTransportData.hpp:279
Definition GwTransportData.hpp:75
double c_diff
Explicit diffusion Courant number for the kernel's tier bound.
Definition GwTransportData.hpp:103
std::string surface_thermal_bc
Definition GwTransportData.hpp:93
std::string surface_thermal_arg
Definition GwTransportData.hpp:94
bool authored
Definition GwTransportData.hpp:107
double thermal_max_step
Definition GwTransportData.hpp:81
std::string thermal_mixing
THERMAL_MIXING ARITHMETIC | GEOMETRIC.
Definition GwTransportData.hpp:101
bool transport_msx
Definition GwTransportData.hpp:86
double water_conductivity
Definition GwTransportData.hpp:81
double air_conductivity
Definition GwTransportData.hpp:81
bool transport_temperature
Definition GwTransportData.hpp:88
std::string thermal_model
Definition GwTransportData.hpp:78
int thermal_layers
Definition GwTransportData.hpp:79
bool transport_pollutants
Definition GwTransportData.hpp:85
std::string deep_thermal_bc
Definition GwTransportData.hpp:97
std::string soil_et_heat
Definition GwTransportData.hpp:83
std::string unsat_transport
explicit SIGMA chemistry opt-in
Definition GwTransportData.hpp:76
bool lateral_conduction
Definition GwTransportData.hpp:80
double deep_depth
Definition GwTransportData.hpp:99
bool dispersion
α_L / α_T / D_m active
Definition GwTransportData.hpp:89
bool transport_age
Definition GwTransportData.hpp:87
std::string deep_thermal_arg
Definition GwTransportData.hpp:98
double surface_resistance
Definition GwTransportData.hpp:82
std::set< std::string > thermal_authored
Definition GwTransportData.hpp:84
bool conduction
Definition GwTransportData.hpp:90