OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
SurfaceTransportState.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
58
59#ifndef OPENSWMM_ENGINE_2D_SURFACE_TRANSPORT_STATE_HPP
60#define OPENSWMM_ENGINE_2D_SURFACE_TRANSPORT_STATE_HPP
61
62#include <cstddef>
63#include <string>
64#include <string_view>
65#include <vector>
66
67namespace openswmm::twoD {
68
70 int n_species = 0;
71 int n_cells = 0;
72
73 // ---- S4 row layout — the 1D engines' convention, verbatim -------------
74 // rows [0, n_pollut) pollutants; [n_pollut, n_pollut + n_msx) MSX species
75 // in ReactionData order; then the reserved __WATER_AGE__ row; then the
76 // reserved __TEMPERATURE__ row LAST (H1 fixed the reported column order
77 // so adding heat to an age model never moves the age column). Set by the
78 // router after resize(); -1 ⇒ the row is not carried.
79 int n_pollut = 0;
80 int n_msx = 0;
81 int age_row = -1;
82 int temp_row = -1;
86 std::vector<std::string> row_names;
90 bool signedRow(int s) const noexcept { return s == temp_row; }
91 int rowIndex(std::string_view name) const noexcept {
92 for (std::size_t i = 0; i < row_names.size(); ++i)
93 if (row_names[i] == name) return static_cast<int>(i);
94 return -1;
95 }
96
100 std::vector<double> cell_mass;
101
102 // ---- Ledgers (per species), m³·conc, cumulative over the run. ----------
103 // These are what S3's coupling tuple and the continuity table will read;
104 // in S1 they are the record that mass left the surface and where.
105 std::vector<double> lost_infiltration;
106 std::vector<double> lost_boundary;
107 std::vector<double> lost_coupling;
111 std::vector<double> exch_mass;
121 std::vector<double> exch_spill;
122
123 // ---- S2 source concentrations (species units) -------------------------
126 std::vector<double> rain_conc;
131 std::vector<double> bc_conc;
134 struct BoundaryQualityRow { int slot = -1; int species = -1; double conc = 0.0; };
135 std::vector<BoundaryQualityRow> bc_quality_rows;
136
137 // ---- S2 dispersion limiter telemetry ----------------------------------
144
147 std::vector<double> gained_rainfall;
148 std::vector<double> gained_boundary;
151 std::vector<double> gained_coupling;
152
153 // ---- S3 outfall-discharge species source ------------------------------
161 std::vector<double> coupling_src;
162
163 bool active() const noexcept { return n_species > 0 && n_cells > 0; }
164
165 void resize(int n_spec, int n_tri, int n_coupling_points) {
166 n_species = (n_spec > 0) ? n_spec : 0;
167 n_cells = (n_tri > 0) ? n_tri : 0;
168 n_pollut = n_species; n_msx = 0; age_row = -1; temp_row = -1; // S4: router refines
169 row_names.clear();
170 const auto ns = static_cast<std::size_t>(n_species);
171 cell_mass.assign(ns * static_cast<std::size_t>(n_cells), 0.0);
172 lost_infiltration.assign(ns, 0.0);
173 lost_boundary.assign(ns, 0.0);
174 lost_coupling.assign(ns, 0.0);
175 exch_mass.assign(ns * static_cast<std::size_t>(
176 n_coupling_points > 0 ? n_coupling_points
177 : 0),
178 0.0);
179 exch_spill.assign(static_cast<std::size_t>(
180 n_coupling_points > 0 ? n_coupling_points : 0),
181 0.0);
182 rain_conc.clear(); // S2: router fills when pollutants carry one
183 bc_conc.clear(); // S2: solver sizes at initialize
184 bc_quality_rows.clear();
186 gained_rainfall.assign(ns, 0.0);
187 gained_boundary.assign(ns, 0.0);
188 gained_coupling.assign(ns, 0.0);
189 coupling_src.clear(); // S3: router sizes when outfalls exist
190 }
191
192 void clear() { *this = SurfaceTransportState{}; }
193
194 std::size_t idx(int s, int c) const noexcept {
195 return static_cast<std::size_t>(s) * static_cast<std::size_t>(n_cells) +
196 static_cast<std::size_t>(c);
197 }
198
203 double concentration(int s, int c, double volume_m3,
204 double dry_volume_m3) const noexcept {
205 if (!(volume_m3 > dry_volume_m3)) return 0.0;
206 return cell_mass[idx(s, c)] / volume_m3;
207 }
208
211 double totalIncludingLedgers(int s) const noexcept {
212 double m = 0.0;
213 const auto base = static_cast<std::size_t>(s) *
214 static_cast<std::size_t>(n_cells);
215 for (int c = 0; c < n_cells; ++c)
216 m += cell_mass[base + static_cast<std::size_t>(c)];
217 const auto us = static_cast<std::size_t>(s);
218 // Sources are SUBTRACTED so the quantity is "what was there at t=0":
219 // surface + everything that left − everything that arrived.
220 return m + lost_infiltration[us] + lost_boundary[us] +
221 lost_coupling[us] -
222 (us < gained_rainfall.size() ? gained_rainfall[us] : 0.0) -
223 (us < gained_boundary.size() ? gained_boundary[us] : 0.0) -
224 (us < gained_coupling.size() ? gained_coupling[us] : 0.0);
225 }
226};
227
228} // namespace openswmm::twoD
229
230#endif // OPENSWMM_ENGINE_2D_SURFACE_TRANSPORT_STATE_HPP
Definition NodeCoupling.cpp:16
Definition SurfaceTransportState.hpp:134
double conc
Definition SurfaceTransportState.hpp:134
int slot
Definition SurfaceTransportState.hpp:134
int species
Definition SurfaceTransportState.hpp:134
Definition SurfaceTransportState.hpp:69
std::vector< double > cell_mass
Definition SurfaceTransportState.hpp:100
std::vector< double > lost_boundary
left through an open edge
Definition SurfaceTransportState.hpp:106
std::vector< double > exch_mass
Definition SurfaceTransportState.hpp:111
std::vector< double > rain_conc
Definition SurfaceTransportState.hpp:126
int rowIndex(std::string_view name) const noexcept
Definition SurfaceTransportState.hpp:91
bool active() const noexcept
Definition SurfaceTransportState.hpp:163
std::vector< double > lost_infiltration
left through the bed
Definition SurfaceTransportState.hpp:105
void clear()
Definition SurfaceTransportState.hpp:192
bool signedRow(int s) const noexcept
Definition SurfaceTransportState.hpp:90
int age_row
Definition SurfaceTransportState.hpp:81
std::vector< double > gained_rainfall
Definition SurfaceTransportState.hpp:147
long dispersion_limiter_binds
Definition SurfaceTransportState.hpp:143
std::size_t idx(int s, int c) const noexcept
Definition SurfaceTransportState.hpp:194
double totalIncludingLedgers(int s) const noexcept
Definition SurfaceTransportState.hpp:211
std::vector< double > coupling_src
Definition SurfaceTransportState.hpp:161
int n_cells
Definition SurfaceTransportState.hpp:71
std::vector< double > gained_coupling
Definition SurfaceTransportState.hpp:151
int n_msx
Definition SurfaceTransportState.hpp:80
std::vector< double > bc_conc
Definition SurfaceTransportState.hpp:131
std::vector< double > gained_boundary
Definition SurfaceTransportState.hpp:148
void resize(int n_spec, int n_tri, int n_coupling_points)
Definition SurfaceTransportState.hpp:165
std::vector< double > lost_coupling
Definition SurfaceTransportState.hpp:107
std::vector< std::string > row_names
Definition SurfaceTransportState.hpp:86
int n_pollut
Definition SurfaceTransportState.hpp:79
double concentration(int s, int c, double volume_m3, double dry_volume_m3) const noexcept
Definition SurfaceTransportState.hpp:203
std::vector< double > exch_spill
Definition SurfaceTransportState.hpp:121
int temp_row
Definition SurfaceTransportState.hpp:82
int n_species
rows carried; 0 ⇒ transport is off everywhere
Definition SurfaceTransportState.hpp:70
std::vector< BoundaryQualityRow > bc_quality_rows
Definition SurfaceTransportState.hpp:135