OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
NetworkMeshData.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
43
44#ifndef OPENSWMM_ENGINE_FV_NETWORK_MESH_DATA_HPP
45#define OPENSWMM_ENGINE_FV_NETWORK_MESH_DATA_HPP
46
47#include <cstdint>
48#include <vector>
49
50#include "../XSectBatch.hpp"
52#include "../XSectKernels.hpp"
53
54namespace openswmm::fv {
55
61inline constexpr int kI1Samples = 129;
62
64inline constexpr int kNodeVolSamples = 129;
65
77struct FvGeometry {
79
86 const xsect::XsectEval* eval = nullptr;
87
88 double y_full = 0.0;
89 double a_full = 0.0;
90 double w_max = 0.0;
91 double r_full = 0.0;
92
95 double barrel_scale = 1.0;
96
100 double y_crown = 0.0;
101
104 double t_slot = 0.0;
105
109 double a_crown = 0.0;
110
112 double i1_crown = 0.0;
113
114 uint8_t is_open = 0;
115
116 // -- Friction and losses (already lengthening-adjusted, see Router::init) --
117
118 double roughness = 0.01;
119 double rough_factor = 0.0;
120 double loss_inlet = 0.0;
121 double loss_outlet = 0.0;
122
123 int barrels = 1;
124
129 double slope = 0.0;
130
136 uint8_t culvert_mitered = 0;
137
152 double i1_tbl[2 * kI1Samples] = {};
153
169 double h_tbl[kI1Samples] = {};
170
171};
172
177
178 // -----------------------------------------------------------------------
179 // Cells — indexed by cell index [0, n_cells)
180 // -----------------------------------------------------------------------
181
182 std::vector<int> cell_geom;
183 std::vector<int> cell_conduit;
184 std::vector<double> cell_dx;
185 std::vector<double> cell_zb;
186
193 std::vector<double> cell_dzdx;
194
200 std::vector<int> cell_face0;
201 std::vector<int> cell_face1;
202 std::vector<int8_t> cell_side0;
203 std::vector<int8_t> cell_side1;
204
205 // -----------------------------------------------------------------------
206 // Faces — indexed by face index [0, n_faces). Flux is positive LEFT → RIGHT.
207 // -----------------------------------------------------------------------
208 // A face with cell_l == -1 has a NODE on its left (a conduit's upstream
209 // boundary); cell_r == -1 puts the node on its right (downstream boundary).
210 // Interior faces (both cells ≥ 0) include virtual junctions, which are
211 // nothing but a splice of two conduits' chains — mass and momentum flux
212 // continuity are then properties of the scheme, not a special treatment.
213
214 std::vector<int> face_cl;
215 std::vector<int> face_cr;
216 std::vector<int> face_node;
217
236 std::vector<int> face_geom;
237
249 if (face_geom.size() == static_cast<std::size_t>(n_faces())) return;
250 face_geom.assign(static_cast<std::size_t>(n_faces()), 0);
251 for (int f = 0; f < n_faces(); ++f) {
252 const auto uf = static_cast<std::size_t>(f);
253 const int c = (face_cl[uf] >= 0) ? face_cl[uf] : face_cr[uf];
254 face_geom[uf] = (c >= 0 &&
255 static_cast<std::size_t>(c) < cell_geom.size())
256 ? cell_geom[static_cast<std::size_t>(c)] : 0;
257 }
258 }
259
266 std::vector<uint8_t> face_gate;
267
271 std::vector<int> face_culvert;
272 std::vector<double> face_zb;
273 std::vector<double> face_dx;
274
285 std::vector<int8_t> face_dir_l;
286 std::vector<int8_t> face_dir_r;
287
291 std::vector<uint8_t> face_virtual;
292
299 std::vector<int> face_vj_node;
300
307 std::vector<int> node_vj_face;
308
309 // -----------------------------------------------------------------------
310 // Conduit → cell map. Cells of a conduit are CONTIGUOUS by construction,
311 // so a begin/count pair is a complete (and cheaper) CSR.
312 // -----------------------------------------------------------------------
313
314 std::vector<int> conduit_cell_begin;
315 std::vector<int> conduit_cell_count;
316 std::vector<int> conduit_link;
317
318 // -----------------------------------------------------------------------
319 // Cell chains (CSR). A chain is a maximal run of cells joined by INTERIOR
320 // faces, so it spans virtual junctions — a spliced pair of conduits is one
321 // chain, which is exactly the property that makes a virtual junction
322 // indistinguishable from an interior cut.
323 //
324 // Chains give the solver an ordered 1D stencil: the second-order scalar
325 // reconstruction reads neighbours along the chain, and the implicit
326 // dispersion solve is one tridiagonal system per chain (D-FV1). `dir` is
327 // the cell's own axis relative to the chain's walking direction.
328 // -----------------------------------------------------------------------
329
330 std::vector<int> chain_ptr;
331 std::vector<int> chain_cells;
332 std::vector<int8_t> chain_dir;
333 std::vector<int> cell_chain;
334 std::vector<int> cell_chain_pos;
335
336 int n_chains() const noexcept {
337 return chain_ptr.empty() ? 0 : static_cast<int>(chain_ptr.size()) - 1;
338 }
339
340 // -----------------------------------------------------------------------
341 // Non-conduit links (pumps, orifices, weirs, outlets). Evaluated by their
342 // existing structure equations outside the solver and applied here as
343 // source/sink pairs on the two node volumes.
344 //
345 // DUMMY-xsect conduits belong here too. Legacy isTrueConduit
346 // (dynwave.c:411-414) is false for them: they carry no cross-section, so
347 // there is nothing to march, and DW routes them through findNonConduitFlow
348 // as a pure pass-through instead. They differ from a real structure in that
349 // their discharge is not a head relation the engine can evaluate outside
350 // the solver — it is whatever arrives at the upstream node — so the solver
351 // computes it itself (`struct_is_dummy`, see ExplicitFvSolver::
352 // refreshDummyFlows) rather than reading FvStepForcing::structure_flow.
353 // -----------------------------------------------------------------------
354
355 std::vector<int> struct_link;
356 std::vector<int> struct_n1;
357 std::vector<int> struct_n2;
358
361 std::vector<uint8_t> struct_is_dummy;
362
368 std::vector<uint8_t> node_dummy_drain;
369
370 // -----------------------------------------------------------------------
371 // Node → face map (CSR). Two-pass gather with NO atomics: the node update
372 // reads its own face list in a fixed order, so the result is deterministic
373 // and identical across backends and thread counts.
374 // -----------------------------------------------------------------------
375
376 std::vector<int> node_face_ptr;
377 std::vector<int> node_face_idx;
378 std::vector<double> node_face_sign;
379
383 std::vector<double> node_face_zb;
384
385 // -----------------------------------------------------------------------
386 // Node properties
387 // -----------------------------------------------------------------------
388
389 std::vector<double> node_invert;
390 std::vector<double> node_full_depth;
391 std::vector<double> node_ponded_area;
392 std::vector<double> node_sur_depth;
393
397 std::vector<uint8_t> node_can_pond;
398
401 std::vector<uint8_t> node_kind;
402
410 std::vector<double> node_area;
411
412 // -- Tabulated storage relation (STORAGE nodes only) ---------------------
413 //
414 // The solver must invert volume → depth every substep, and it must do so
415 // without reaching back into SimulationContext (the GPU plugin has no
416 // access to it). Storage geometry is therefore FLATTENED at mesh build into
417 // a monotone depth→volume table sampled from node::getVolume, exactly as
418 // the cross-sections are flattened for the device path.
419 //
420 // Junctions need none of this: their storage is linear in depth with the
421 // surface area held over the routing step (plan §3.4).
422
423 std::vector<int> node_vol_off;
424 std::vector<double> node_vol_dmax;
425 std::vector<double> node_vol_atop;
426 std::vector<double> node_vol_tbl;
427
428 // -----------------------------------------------------------------------
429 // Geometry closures — one per conduit row
430 // -----------------------------------------------------------------------
431
432 std::vector<FvGeometry> geom;
433
434 // -----------------------------------------------------------------------
435 // Capacity queries
436 // -----------------------------------------------------------------------
437
438 int n_cells() const noexcept { return static_cast<int>(cell_dx.size()); }
439 int n_faces() const noexcept { return static_cast<int>(face_cl.size()); }
440 int n_nodes() const noexcept { return static_cast<int>(node_invert.size()); }
441 int n_conduits() const noexcept {
442 return static_cast<int>(conduit_cell_begin.size());
443 }
444
445 void clear() {
446 cell_geom.clear(); cell_conduit.clear(); cell_dx.clear(); cell_zb.clear();
447 cell_dzdx.clear();
448 cell_face0.clear(); cell_face1.clear();
449 cell_side0.clear(); cell_side1.clear();
450 face_cl.clear(); face_cr.clear(); face_node.clear(); face_gate.clear();
451 face_geom.clear();
452 face_culvert.clear();
453 face_zb.clear(); face_dx.clear(); face_virtual.clear();
454 face_vj_node.clear(); node_vj_face.clear();
455 face_dir_l.clear(); face_dir_r.clear();
456 conduit_cell_begin.clear(); conduit_cell_count.clear(); conduit_link.clear();
457 chain_ptr.clear(); chain_cells.clear(); chain_dir.clear();
458 cell_chain.clear(); cell_chain_pos.clear();
459 struct_link.clear(); struct_n1.clear(); struct_n2.clear();
460 struct_is_dummy.clear(); node_dummy_drain.clear();
461 node_face_ptr.clear(); node_face_idx.clear();
462 node_face_sign.clear(); node_face_zb.clear();
463 node_invert.clear(); node_full_depth.clear(); node_ponded_area.clear();
464 node_sur_depth.clear(); node_can_pond.clear();
465 node_kind.clear();
466 node_area.clear();
467 node_vol_off.clear(); node_vol_dmax.clear();
468 node_vol_atop.clear(); node_vol_tbl.clear();
469 geom.clear();
470 }
471};
472
474enum : uint8_t {
479};
480
490 // Conserved cell variables (per BARREL — link reporting multiplies by
491 // geom.barrels).
492 std::vector<double> cell_a;
493 std::vector<double> cell_q;
494
495 // Derived, refreshed after every cell update so faces read a consistent
496 // depth without re-inverting A(h) per face.
497 std::vector<double> cell_h;
498
499 // Node state. `volume` is the prognostic mass ledger — depth follows from
500 // it through the node's storage relation — so node mass is conserved
501 // exactly (plan §3.4).
502 std::vector<double> node_volume;
503 std::vector<double> node_head;
504 std::vector<double> node_surf_area;
505 std::vector<double> node_overflow;
506
509 std::vector<double> node_overflow_vol;
510
511 // Advected scalars, cell-major: phi[s * n_cells + c]. Empty when transport
512 // is off.
513 std::vector<double> cell_phi;
514 int n_species = 0;
515
525 std::vector<uint8_t> cell_tpa;
526
527 void resize(int n_cells, int n_nodes, int n_species_in) {
528 const auto nc = static_cast<std::size_t>(n_cells);
529 const auto nn = static_cast<std::size_t>(n_nodes);
530 cell_a.assign(nc, 0.0);
531 cell_q.assign(nc, 0.0);
532 cell_h.assign(nc, 0.0);
533 node_volume.assign(nn, 0.0);
534 node_head.assign(nn, 0.0);
535 node_surf_area.assign(nn, 0.0);
536 node_overflow.assign(nn, 0.0);
537 node_overflow_vol.assign(nn, 0.0);
538 n_species = n_species_in;
539 cell_phi.assign(nc * static_cast<std::size_t>(n_species_in), 0.0);
540 }
541};
542
543} // namespace openswmm::fv
544
545#endif // OPENSWMM_ENGINE_FV_NETWORK_MESH_DATA_HPP
Portable scalar closures shared by the host solvers and the device backend: FHWA HEC-5 culvert inlet ...
Cross-section geometry — unified batch + per-element API.
Portable cross-section geometry kernels — one implementation, three consumers (host dynamic wave,...
Definition ExplicitFvSolver.cpp:25
@ kNodeJunction
Definition NetworkMeshData.hpp:475
@ kNodeOutfall
Definition NetworkMeshData.hpp:478
@ kNodeVirtual
Definition NetworkMeshData.hpp:476
@ kNodeStorage
Definition NetworkMeshData.hpp:477
constexpr int kI1Samples
Definition NetworkMeshData.hpp:61
constexpr int kNodeVolSamples
Samples in a STORAGE node's flattened depth→volume table.
Definition NetworkMeshData.hpp:64
Definition XSectBatch.hpp:110
Cross-section closure for one conduit's cell chain.
Definition NetworkMeshData.hpp:77
double r_full
hydraulic radius when full (ft)
Definition NetworkMeshData.hpp:91
const xsect::XsectEval * eval
Definition NetworkMeshData.hpp:86
double rough_factor
g·(n/PHI)² — friction denominator factor
Definition NetworkMeshData.hpp:119
double a_full
area when full (ft²)
Definition NetworkMeshData.hpp:89
double t_slot
Definition NetworkMeshData.hpp:104
double slope
Definition NetworkMeshData.hpp:129
uint8_t is_open
open section: no crown, no slot taper
Definition NetworkMeshData.hpp:114
double i1_crown
I₁(y_full) — the table's last entry, cached for the same reason.
Definition NetworkMeshData.hpp:112
double h_tbl[kI1Samples]
Definition NetworkMeshData.hpp:169
double barrel_scale
Definition NetworkMeshData.hpp:95
double i1_tbl[2 *kI1Samples]
Definition NetworkMeshData.hpp:152
double roughness
Manning n.
Definition NetworkMeshData.hpp:118
double y_crown
Definition NetworkMeshData.hpp:100
hydkernels::CulvertCurve culvert_curve
Definition NetworkMeshData.hpp:135
uint8_t culvert_mitered
Definition NetworkMeshData.hpp:136
double loss_inlet
entrance loss coefficient K
Definition NetworkMeshData.hpp:120
double a_crown
Definition NetworkMeshData.hpp:109
double y_full
full depth (ft)
Definition NetworkMeshData.hpp:88
double w_max
width at widest point (ft)
Definition NetworkMeshData.hpp:90
int barrels
parallel identical barrels
Definition NetworkMeshData.hpp:123
double loss_outlet
exit loss coefficient K
Definition NetworkMeshData.hpp:121
int culvert_code
Definition NetworkMeshData.hpp:128
XSectParams xs
section parameters (owns transect table ptrs)
Definition NetworkMeshData.hpp:78
SoA mesh geometry and topology for the FV network solver.
Definition NetworkMeshData.hpp:176
std::vector< int > cell_geom
index into geom
Definition NetworkMeshData.hpp:182
std::vector< double > node_sur_depth
SURCHARGE_DEPTH above the rim (ft)
Definition NetworkMeshData.hpp:392
std::vector< double > node_ponded_area
ponding area above the rim (ft²)
Definition NetworkMeshData.hpp:391
std::vector< int8_t > face_dir_r
Definition NetworkMeshData.hpp:286
std::vector< double > face_zb
bed elevation at the interface (ft)
Definition NetworkMeshData.hpp:272
int n_faces() const noexcept
Definition NetworkMeshData.hpp:439
std::vector< double > node_face_sign
+1 flux ENTERS the node, −1 leaves it
Definition NetworkMeshData.hpp:378
std::vector< double > node_full_depth
crown / rim depth (ft)
Definition NetworkMeshData.hpp:390
std::vector< int > face_cr
right cell (-1 ⇒ node on the right)
Definition NetworkMeshData.hpp:215
std::vector< double > node_area
Definition NetworkMeshData.hpp:410
std::vector< int > conduit_cell_count
cells in conduit row r
Definition NetworkMeshData.hpp:315
std::vector< double > node_face_zb
Definition NetworkMeshData.hpp:383
std::vector< uint8_t > struct_is_dummy
Definition NetworkMeshData.hpp:361
std::vector< int > cell_face0
Definition NetworkMeshData.hpp:200
std::vector< int8_t > cell_side1
Definition NetworkMeshData.hpp:203
std::vector< uint8_t > face_virtual
Definition NetworkMeshData.hpp:291
std::vector< int > cell_conduit
ConduitData row (for reporting)
Definition NetworkMeshData.hpp:183
std::vector< int > node_face_idx
face indices
Definition NetworkMeshData.hpp:377
std::vector< int > struct_n1
upstream node
Definition NetworkMeshData.hpp:356
std::vector< double > node_vol_atop
surface area above dmax (ft²)
Definition NetworkMeshData.hpp:425
std::vector< double > cell_dzdx
Definition NetworkMeshData.hpp:193
std::vector< double > cell_dx
cell length (ft)
Definition NetworkMeshData.hpp:184
std::vector< int > struct_n2
downstream node
Definition NetworkMeshData.hpp:357
std::vector< int > conduit_link
base LinkData index of conduit row r
Definition NetworkMeshData.hpp:316
int n_chains() const noexcept
Definition NetworkMeshData.hpp:336
std::vector< int > cell_chain
chain of each cell
Definition NetworkMeshData.hpp:333
std::vector< int > face_cl
left cell (-1 ⇒ node on the left)
Definition NetworkMeshData.hpp:214
std::vector< int > cell_chain_pos
position within that chain
Definition NetworkMeshData.hpp:334
void deriveFaceGeom()
Definition NetworkMeshData.hpp:248
std::vector< double > node_vol_dmax
depth at the table top (ft)
Definition NetworkMeshData.hpp:424
std::vector< double > node_invert
invert elevation (ft)
Definition NetworkMeshData.hpp:389
std::vector< int > conduit_cell_begin
first cell of conduit row r
Definition NetworkMeshData.hpp:314
int n_nodes() const noexcept
Definition NetworkMeshData.hpp:440
int n_conduits() const noexcept
Definition NetworkMeshData.hpp:441
std::vector< int > face_node
coupled node (-1 for interior faces)
Definition NetworkMeshData.hpp:216
std::vector< double > face_dx
centre-to-centre distance (ft)
Definition NetworkMeshData.hpp:273
std::vector< int8_t > cell_side0
Definition NetworkMeshData.hpp:202
std::vector< int > chain_cells
cell indices in walk order
Definition NetworkMeshData.hpp:331
std::vector< int > node_vol_off
offset into node_vol_tbl, −1 = none
Definition NetworkMeshData.hpp:423
std::vector< int > face_vj_node
Definition NetworkMeshData.hpp:299
void clear()
Definition NetworkMeshData.hpp:445
std::vector< int8_t > face_dir_l
Definition NetworkMeshData.hpp:285
std::vector< uint8_t > node_kind
Definition NetworkMeshData.hpp:401
std::vector< int > face_culvert
Definition NetworkMeshData.hpp:271
std::vector< uint8_t > node_can_pond
Definition NetworkMeshData.hpp:397
std::vector< int > struct_link
LinkData index.
Definition NetworkMeshData.hpp:355
std::vector< uint8_t > face_gate
Definition NetworkMeshData.hpp:266
std::vector< double > node_vol_tbl
kNodeVolSamples volumes per node
Definition NetworkMeshData.hpp:426
std::vector< int > face_geom
index into geom
Definition NetworkMeshData.hpp:236
std::vector< int > node_face_ptr
[n_nodes + 1] row pointers
Definition NetworkMeshData.hpp:376
int n_cells() const noexcept
Definition NetworkMeshData.hpp:438
std::vector< int > node_vj_face
Definition NetworkMeshData.hpp:307
std::vector< int > cell_face1
Definition NetworkMeshData.hpp:201
std::vector< FvGeometry > geom
Definition NetworkMeshData.hpp:432
std::vector< int > chain_ptr
[n_chains + 1] row pointers
Definition NetworkMeshData.hpp:330
std::vector< int8_t > chain_dir
cell axis vs. chain direction (±1)
Definition NetworkMeshData.hpp:332
std::vector< double > cell_zb
bed elevation at cell centre (ft)
Definition NetworkMeshData.hpp:185
std::vector< uint8_t > node_dummy_drain
Definition NetworkMeshData.hpp:368
Mutable solver state — the conserved variables and the node volumes.
Definition NetworkMeshData.hpp:489
std::vector< double > cell_q
discharge (cfs)
Definition NetworkMeshData.hpp:493
std::vector< double > node_head
water-surface elevation (ft)
Definition NetworkMeshData.hpp:503
std::vector< double > cell_phi
Definition NetworkMeshData.hpp:513
std::vector< double > cell_h
depth (ft)
Definition NetworkMeshData.hpp:497
int n_species
Definition NetworkMeshData.hpp:514
std::vector< uint8_t > cell_tpa
Definition NetworkMeshData.hpp:525
std::vector< double > cell_a
flow area (ft²)
Definition NetworkMeshData.hpp:492
std::vector< double > node_surf_area
storage area used this routing step (ft²)
Definition NetworkMeshData.hpp:504
std::vector< double > node_volume
stored volume (ft³)
Definition NetworkMeshData.hpp:502
std::vector< double > node_overflow
flooding rate this substep (cfs)
Definition NetworkMeshData.hpp:505
std::vector< double > node_overflow_vol
Definition NetworkMeshData.hpp:509
void resize(int n_cells, int n_nodes, int n_species_in)
Definition NetworkMeshData.hpp:527
Inlet-control curve coefficients for one culvert type code.
Definition HydClosureKernels.hpp:110
The geometry layer itself, parameterized on where its tables live.
Definition XSectKernels.hpp:328