OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
SurfaceStateData.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
31
32#ifndef OPENSWMM_ENGINE_2D_SURFACE_STATE_DATA_HPP
33#define OPENSWMM_ENGINE_2D_SURFACE_STATE_DATA_HPP
34
35#include <vector>
36#include <cstring>
37#include <cmath>
38#include <algorithm>
39#include <vector>
40
41#include "SurfaceTransportState.hpp" // S1 — species mass per cell
42#include "MeshData.hpp" // kMaxCellVerts edge-slot stride
43
44namespace openswmm { struct NodeData; } // 1D node data (held during a 2D advance)
45
46namespace openswmm::twoD {
47
48struct CouplingPoint; // fwd decl — 1D↔2D coupling descriptor (NodeCoupling.hpp)
49
57struct BoundaryData; // fwd decl — per-edge boundary conditions (BoundaryData.hpp)
58
60
61 // -----------------------------------------------------------------------
62 // State variables — per triangle [0, n_triangles)
63 // -----------------------------------------------------------------------
64
72 const BoundaryData* boundary = nullptr;
73
78 const NodeData* nodes_1d = nullptr;
83 const std::vector<double>* node_row_conc = nullptr;
84 const std::vector<CouplingPoint>* node_coupling = nullptr;
85
92
93 std::vector<double> depth;
94 std::vector<double> head;
95 std::vector<double> volume;
96
97 // Gradient fields (per triangle)
98 std::vector<double> grad_hx;
99 std::vector<double> grad_hy;
100 std::vector<double> grad_hx_lim;
101 std::vector<double> grad_hy_lim;
102
103 // Reconstructed head at vertices — [0, n_vertices)
104 std::vector<double> vert_head;
105
114 std::vector<double> vert_depth_signed;
115
116 // Cell-centred velocity (RT0 reconstruction from edge fluxes) — per triangle
117 std::vector<double> face_vx;
118 std::vector<double> face_vy;
119
120 // Per-cell continuity residual — per triangle (m³/s, ≈0 when conservative)
121 std::vector<double> cell_continuity_err;
122
123 // Fluxes — flat 2D: [cell * kMaxCellVerts + edge]
124 std::vector<double> edge_flux;
125
126 // Source/sink terms — per triangle
127 std::vector<double> rainfall;
128 std::vector<double> evap_rate;
129
137 std::vector<double> infil_rate;
138
148 std::vector<double> infil_applied;
149
150 std::vector<double> coupling_flux;
151
169 std::vector<double> coupling_applied;
170 std::vector<double> net_source;
171
172 // -----------------------------------------------------------------------
173 // Forcing overrides (optional external control)
174 // -----------------------------------------------------------------------
175
176 std::vector<int8_t> rainfall_forced;
177 std::vector<int8_t> rainfall_persist;
178 std::vector<double> rainfall_force_val;
179 std::vector<int8_t> evap_forced;
180 std::vector<int8_t> evap_persist;
181 std::vector<double> evap_force_val;
182 std::vector<int8_t> coupling_forced;
183 std::vector<int8_t> coupling_persist;
184 std::vector<double> coupling_force_val;
185
191 bool forcing_dirty = false;
192
198 bool forcing_ever_set = false;
199
200 // -----------------------------------------------------------------------
201 // Previous step state
202 // -----------------------------------------------------------------------
203
204 std::vector<double> old_depth;
205 std::vector<double> old_volume;
206
207 // -----------------------------------------------------------------------
208 // Cumulative statistics
209 // -----------------------------------------------------------------------
210
211 std::vector<double> stat_max_depth;
212 std::vector<double> stat_max_velocity;
213 std::vector<double> stat_max_cont_err;
214 std::vector<double> stat_cum_volume;
215
219 double evap_loss_total = 0.0;
220
221 // -----------------------------------------------------------------------
222 // Lifecycle
223 // -----------------------------------------------------------------------
224
225 void resize(int n_triangles, int n_vertices) {
226 auto nt = static_cast<std::size_t>(n_triangles);
227 auto nv = static_cast<std::size_t>(n_vertices);
228 auto n3 = nt * static_cast<std::size_t>(kMaxCellVerts);
229
230 depth.assign(nt, 0.0);
231 head.assign(nt, 0.0);
232 volume.assign(nt, 0.0);
233 grad_hx.assign(nt, 0.0);
234 grad_hy.assign(nt, 0.0);
235 grad_hx_lim.assign(nt, 0.0);
236 grad_hy_lim.assign(nt, 0.0);
237 vert_head.assign(nv, 0.0);
238 vert_depth_signed.assign(nv, 0.0);
239 face_vx.assign(nt, 0.0);
240 face_vy.assign(nt, 0.0);
241 cell_continuity_err.assign(nt, 0.0);
242 edge_flux.assign(n3, 0.0);
243 rainfall.assign(nt, 0.0);
244 evap_rate.assign(nt, 0.0);
245 infil_rate.assign(nt, 0.0);
246 infil_applied.assign(nt, 0.0);
247 coupling_applied.assign(nt, 0.0);
248 coupling_flux.assign(nt, 0.0);
249 net_source.assign(nt, 0.0);
250
251 rainfall_forced.assign(nt, 0);
252 rainfall_persist.assign(nt, 0);
253 rainfall_force_val.assign(nt, 0.0);
254 evap_forced.assign(nt, 0);
255 evap_persist.assign(nt, 0);
256 evap_force_val.assign(nt, 0.0);
257 coupling_forced.assign(nt, 0);
258 coupling_persist.assign(nt, 0);
259 coupling_force_val.assign(nt, 0.0);
260
261 old_depth.assign(nt, 0.0);
262 old_volume.assign(nt, 0.0);
263 stat_max_depth.assign(nt, 0.0);
264 stat_max_velocity.assign(nt, 0.0);
265 stat_max_cont_err.assign(nt, 0.0);
266 stat_cum_volume.assign(nt, 0.0);
267 evap_loss_total = 0.0;
268 }
269
270 void save_state() noexcept {
271 std::memcpy(old_depth.data(), depth.data(),
272 depth.size() * sizeof(double));
273 std::memcpy(old_volume.data(), volume.data(),
274 volume.size() * sizeof(double));
275 }
276
277 void reset_state() noexcept {
278 std::memcpy(depth.data(), old_depth.data(),
279 old_depth.size() * sizeof(double));
280 std::memcpy(volume.data(), old_volume.data(),
281 old_volume.size() * sizeof(double));
282 }
283
285 void clear_reset_forcings() noexcept {
286 if (!forcing_ever_set) return;
287 for (std::size_t i = 0; i < rainfall_forced.size(); ++i) {
288 if (rainfall_persist[i] == 0 && rainfall_forced[i] != 0) {
289 rainfall_forced[i] = 0;
290 rainfall_force_val[i] = 0.0;
291 forcing_dirty = true;
292 }
293 if (evap_persist[i] == 0 && evap_forced[i] != 0) {
294 evap_forced[i] = 0;
295 evap_force_val[i] = 0.0;
296 forcing_dirty = true;
297 }
298 if (coupling_persist[i] == 0 && coupling_forced[i] != 0) {
299 coupling_forced[i] = 0;
300 coupling_force_val[i] = 0.0;
301 forcing_dirty = true;
302 }
303 }
304 }
305
313 void update_statistics([[maybe_unused]] const std::vector<double>& tri_area,
314 double dt,
315 [[maybe_unused]] int nthreads = 1) noexcept {
316 // Each cell updates only its own envelope slots (max/cum into [i]);
317 // schedule(static) keeps this bit-identical to serial for any thread
318 // count. int loop index for OpenMP canonical-loop form.
319 const int n = static_cast<int>(depth.size());
320#if defined(SWMM_USE_OPENMP)
321#pragma omp parallel for schedule(static) num_threads(nthreads)
322#endif
323 for (int i = 0; i < n; ++i) {
324 if (depth[i] > stat_max_depth[i])
325 stat_max_depth[i] = depth[i];
326
327 const double speed = std::sqrt(face_vx[i] * face_vx[i]
328 + face_vy[i] * face_vy[i]);
329 if (speed > stat_max_velocity[i])
330 stat_max_velocity[i] = speed;
331
332 const double aerr = std::abs(cell_continuity_err[i]);
333 if (aerr > stat_max_cont_err[i])
334 stat_max_cont_err[i] = aerr;
335
336 // Cell water volume × dt (VFR: V is the integrated state, not h̄·A).
337 stat_cum_volume[i] += volume[i] * dt;
338 }
339 }
340};
341
342} // namespace openswmm::twoD
343
344#endif // OPENSWMM_ENGINE_2D_SURFACE_STATE_DATA_HPP
Structure-of-Arrays (SoA) storage for 2D triangular mesh geometry.
Overland transport S1 — per-cell species MASS on the 2D surface.
Definition NodeCoupling.cpp:16
constexpr int kMaxCellVerts
Definition MeshData.hpp:49
Definition NodeCoupling.cpp:16
Structure-of-Arrays storage for all nodes.
Definition NodeData.hpp:130
SoA storage for per-edge boundary conditions.
Definition BoundaryData.hpp:71
Descriptor for a single coupling point between 2D and 1D.
Definition NodeCoupling.hpp:57
Definition SurfaceStateData.hpp:59
std::vector< double > grad_hy_lim
Limited gradient Y.
Definition SurfaceStateData.hpp:101
std::vector< double > infil_rate
Definition SurfaceStateData.hpp:137
std::vector< double > grad_hy
∂h/∂y (unlimited gradient)
Definition SurfaceStateData.hpp:99
void save_state() noexcept
Definition SurfaceStateData.hpp:270
std::vector< int8_t > coupling_forced
0=computed, 1=override, 2=add
Definition SurfaceStateData.hpp:182
std::vector< double > coupling_flux
Exchange with SWMM node (m/s, + = into 2D)
Definition SurfaceStateData.hpp:150
bool forcing_ever_set
Definition SurfaceStateData.hpp:198
std::vector< double > vert_depth_signed
Definition SurfaceStateData.hpp:114
std::vector< int8_t > rainfall_forced
0=computed, 1=override, 2=add
Definition SurfaceStateData.hpp:176
double evap_loss_total
Definition SurfaceStateData.hpp:219
std::vector< double > stat_max_depth
Maximum depth ψ_o seen at each cell (m)
Definition SurfaceStateData.hpp:211
std::vector< double > cell_continuity_err
Definition SurfaceStateData.hpp:121
std::vector< double > net_source
Net source/sink per cell (m/s)
Definition SurfaceStateData.hpp:170
SurfaceTransportState transport
Definition SurfaceStateData.hpp:91
std::vector< double > rainfall_force_val
Forced rainfall value.
Definition SurfaceStateData.hpp:178
std::vector< double > stat_max_cont_err
Max |cell_continuity_err| (m³/s)
Definition SurfaceStateData.hpp:213
std::vector< double > stat_cum_volume
Cumulative volume through cell (m³)
Definition SurfaceStateData.hpp:214
std::vector< int8_t > evap_persist
0=reset, 1=persist
Definition SurfaceStateData.hpp:180
void clear_reset_forcings() noexcept
Clear RESET forcings after each step.
Definition SurfaceStateData.hpp:285
bool forcing_dirty
Definition SurfaceStateData.hpp:191
const std::vector< double > * node_row_conc
Definition SurfaceStateData.hpp:83
std::vector< double > depth
Mean wetted depth h̄ = V/A_wet (m) [reconstructed].
Definition SurfaceStateData.hpp:93
std::vector< double > face_vx
Cell velocity X component (m/s)
Definition SurfaceStateData.hpp:117
std::vector< double > grad_hx
∂h/∂x (unlimited gradient)
Definition SurfaceStateData.hpp:98
const std::vector< CouplingPoint > * node_coupling
non-outfall points
Definition SurfaceStateData.hpp:84
std::vector< double > rainfall
Rainfall intensity (m/s)
Definition SurfaceStateData.hpp:127
std::vector< double > volume
Cell water volume V (m³) — the integrated state.
Definition SurfaceStateData.hpp:95
std::vector< double > coupling_force_val
Forced coupling value.
Definition SurfaceStateData.hpp:184
std::vector< double > evap_force_val
Forced evaporation value.
Definition SurfaceStateData.hpp:181
std::vector< double > vert_head
Head reconstructed at vertices.
Definition SurfaceStateData.hpp:104
std::vector< int8_t > evap_forced
0=computed, 1=override, 2=add
Definition SurfaceStateData.hpp:179
void reset_state() noexcept
Definition SurfaceStateData.hpp:277
std::vector< double > head
Free-surface elevation η (m) [reconstructed].
Definition SurfaceStateData.hpp:94
std::vector< double > grad_hx_lim
Limited gradient X.
Definition SurfaceStateData.hpp:100
const NodeData * nodes_1d
Definition SurfaceStateData.hpp:78
std::vector< int8_t > coupling_persist
0=reset, 1=persist
Definition SurfaceStateData.hpp:183
void resize(int n_triangles, int n_vertices)
Definition SurfaceStateData.hpp:225
std::vector< double > face_vy
Cell velocity Y component (m/s)
Definition SurfaceStateData.hpp:118
std::vector< double > coupling_applied
Definition SurfaceStateData.hpp:169
std::vector< double > evap_rate
Evaporation demand rate (m/s, >= 0)
Definition SurfaceStateData.hpp:128
std::vector< double > stat_max_velocity
Max cell speed |v| = √(vx²+vy²) (m/s)
Definition SurfaceStateData.hpp:212
const BoundaryData * boundary
Definition SurfaceStateData.hpp:72
std::vector< double > old_depth
Mean depth at start of coupling interval.
Definition SurfaceStateData.hpp:204
std::vector< int8_t > rainfall_persist
0=reset, 1=persist
Definition SurfaceStateData.hpp:177
std::vector< double > old_volume
Volume at start of coupling interval (m³)
Definition SurfaceStateData.hpp:205
void update_statistics(const std::vector< double > &tri_area, double dt, int nthreads=1) noexcept
Definition SurfaceStateData.hpp:313
std::vector< double > edge_flux
Normal flux through each edge.
Definition SurfaceStateData.hpp:124
std::vector< double > infil_applied
Definition SurfaceStateData.hpp:148
Definition SurfaceTransportState.hpp:69