SoA mesh geometry and topology for the FV network solver.
More...
#include <NetworkMeshData.hpp>
SoA mesh geometry and topology for the FV network solver.
◆ clear()
| void openswmm::fv::NetworkMeshData::clear |
( |
| ) |
|
|
inline |
◆ deriveFaceGeom()
| void openswmm::fv::NetworkMeshData::deriveFaceGeom |
( |
| ) |
|
|
inline |
Give every face the section of its adjacent cell, sizing face_geom if a caller never populated it. This reproduces the behaviour that preceded face_geom exactly, so it is always safe; NetworkMeshBuilder calls it and then overrides the entries at width-step junctions. Idempotent, and a no-op once face_geom is already the right size.
It exists because face_geom is the one face array a hand-built mesh can silently omit: the unit-test fixtures assemble NetworkMeshData field by field without a SimulationContext, and an omission there is an empty vector that faceSide would index straight into a null page.
◆ n_cells()
| int openswmm::fv::NetworkMeshData::n_cells |
( |
| ) |
const |
|
inlinenoexcept |
◆ n_chains()
| int openswmm::fv::NetworkMeshData::n_chains |
( |
| ) |
const |
|
inlinenoexcept |
◆ n_conduits()
| int openswmm::fv::NetworkMeshData::n_conduits |
( |
| ) |
const |
|
inlinenoexcept |
◆ n_faces()
| int openswmm::fv::NetworkMeshData::n_faces |
( |
| ) |
const |
|
inlinenoexcept |
◆ n_nodes()
| int openswmm::fv::NetworkMeshData::n_nodes |
( |
| ) |
const |
|
inlinenoexcept |
◆ cell_chain
| std::vector<int> openswmm::fv::NetworkMeshData::cell_chain |
◆ cell_chain_pos
| std::vector<int> openswmm::fv::NetworkMeshData::cell_chain_pos |
position within that chain
◆ cell_conduit
| std::vector<int> openswmm::fv::NetworkMeshData::cell_conduit |
◆ cell_dx
| std::vector<double> openswmm::fv::NetworkMeshData::cell_dx |
◆ cell_dzdx
| std::vector<double> openswmm::fv::NetworkMeshData::cell_dzdx |
dz/dx along the cell's OWN axis. The bed is linear within a conduit, so this is exact rather than reconstructed — which matters, because the second-order scheme reconstructs the free surface and the bed SEPARATELY and their difference is the depth it hands the Riemann solver. A limited bed slope would make lake-at-rest only approximately well balanced.
◆ cell_face0
| std::vector<int> openswmm::fv::NetworkMeshData::cell_face0 |
The two faces bounding each cell, with the side the cell occupies on each (0 = left, 1 = right). A 1D cell has exactly two, so this replaces a CSR: the cell update becomes a fixed-width GATHER with no atomics and no scatter races, which is what makes the update deterministic and identical across backends and thread counts.
◆ cell_face1
| std::vector<int> openswmm::fv::NetworkMeshData::cell_face1 |
◆ cell_geom
| std::vector<int> openswmm::fv::NetworkMeshData::cell_geom |
◆ cell_side0
| std::vector<int8_t> openswmm::fv::NetworkMeshData::cell_side0 |
◆ cell_side1
| std::vector<int8_t> openswmm::fv::NetworkMeshData::cell_side1 |
◆ cell_zb
| std::vector<double> openswmm::fv::NetworkMeshData::cell_zb |
bed elevation at cell centre (ft)
◆ chain_cells
| std::vector<int> openswmm::fv::NetworkMeshData::chain_cells |
cell indices in walk order
◆ chain_dir
| std::vector<int8_t> openswmm::fv::NetworkMeshData::chain_dir |
cell axis vs. chain direction (±1)
◆ chain_ptr
| std::vector<int> openswmm::fv::NetworkMeshData::chain_ptr |
[n_chains + 1] row pointers
◆ conduit_cell_begin
| std::vector<int> openswmm::fv::NetworkMeshData::conduit_cell_begin |
first cell of conduit row r
◆ conduit_cell_count
| std::vector<int> openswmm::fv::NetworkMeshData::conduit_cell_count |
◆ conduit_link
| std::vector<int> openswmm::fv::NetworkMeshData::conduit_link |
◆ face_cl
| std::vector<int> openswmm::fv::NetworkMeshData::face_cl |
left cell (-1 ⇒ node on the left)
◆ face_cr
| std::vector<int> openswmm::fv::NetworkMeshData::face_cr |
right cell (-1 ⇒ node on the right)
◆ face_culvert
| std::vector<int> openswmm::fv::NetworkMeshData::face_culvert |
Conduit row whose CULVERT inlet this face is, or -1. Set only on the upstream boundary face of a conduit carrying a culvert code, which is where HEC-5 inlet control physically acts.
◆ face_dir_l
| std::vector<int8_t> openswmm::fv::NetworkMeshData::face_dir_l |
Orientation of each incident cell's own axis relative to the face's LEFT→RIGHT positive direction. +1 is the normal case (the face sits at cell L's downstream end and cell R's upstream end); −1 appears when a virtual junction splices two conduits that both point INTO it (or both out of it), which the [VIRTUAL_JUNCTIONS] rules permit — they constrain cross-section and offsets, not which end attaches.
Q and u are odd under the flip and transform as dir·q; the momentum flux Q·u + g·I₁ is even, which is why only the momentum contribution carries the sign in the cell update and the mass contribution does not.
◆ face_dir_r
| std::vector<int8_t> openswmm::fv::NetworkMeshData::face_dir_r |
◆ face_dx
| std::vector<double> openswmm::fv::NetworkMeshData::face_dx |
centre-to-centre distance (ft)
◆ face_gate
| std::vector<uint8_t> openswmm::fv::NetworkMeshData::face_gate |
Flap-gate mask on a boundary face: bit 0 blocks a POSITIVE mass flux, bit 1 blocks a NEGATIVE one, 0 leaves the face open. A gate is a check valve, so a blocked face behaves as a wall only while the flux would run the wrong way. Both bits can be set at once — a gated conduit pointing out of a gated outfall is sealed in both directions, exactly as DW's two independent checks leave it.
◆ face_geom
| std::vector<int> openswmm::fv::NetworkMeshData::face_geom |
index into geom
Cross-section (index into geom) that this face reconstructs BOTH of its sides in. Almost always the adjacent cells' own section, which leaves the scheme untouched.
It differs only where two conduits of DIFFERENT section meet at a clean degree-2 node, and there it is the section-averaged pair. Without it, such an interface is evaluated twice in two different geometries — each conduit's end face reconstructs the neighbour's state in its OWN section — so the wall the width step physically presents to the flow exerts no force. That missing wall-pressure term is the measured pseudo-2D defect (SWASHES §3.5): depths run too deep wherever the channel contracts and too shallow wherever it expands, antisymmetric in dB/dx and independent of Δx. Reconstructing both sides in one shared section makes the pair a single well-posed Riemann problem, and the hydrostatic-reconstruction correction already applied per side, g·(I₁(cell section, h) − I₁(face section, h*)), becomes exactly the discrete wall-pressure (I₂) source — consistently discretized with the flux it has to balance, which is what every additive closure got wrong.
◆ face_node
| std::vector<int> openswmm::fv::NetworkMeshData::face_node |
coupled node (-1 for interior faces)
◆ face_virtual
| std::vector<uint8_t> openswmm::fv::NetworkMeshData::face_virtual |
1 when the face splices two conduits at a virtual junction. Purely informational (the scheme treats it as any other interior face) — the equivalence test and the reporting path read it.
◆ face_vj_node
| std::vector<int> openswmm::fv::NetworkMeshData::face_vj_node |
Node index of the virtual junction a spliced face replaced (-1 for every other face). face_node must stay -1 for spliced faces — they are interior to the solver — so the reporting path carries the association here instead of re-deriving it (matching inverts collides when two virtual junctions share a bit-identical invert, leaving the loser permanently unreported).
◆ face_zb
| std::vector<double> openswmm::fv::NetworkMeshData::face_zb |
bed elevation at the interface (ft)
◆ geom
| std::vector<FvGeometry> openswmm::fv::NetworkMeshData::geom |
◆ node_area
| std::vector<double> openswmm::fv::NetworkMeshData::node_area |
Storage area of a NON-storage node (junction / outfall / divider), fixed for the run. This is deliberately the ENGINE's own convention — full_volume/full_depth, i.e. MIN_SURFAREA unless a pump wet well overrode it (node::getVolume's JUNCTION branch) — so the solver's volume ledger and the volume the engine reports for the same depth are the SAME function. Any other choice makes the solver hold water the mass balance cannot see, which shows up directly as routing continuity error.
◆ node_can_pond
| std::vector<uint8_t> openswmm::fv::NetworkMeshData::node_can_pond |
Ponding eligibility, resolved at build time from the same rule DW uses ((ALLOW_PONDING || 2D-coupled) && ponded_area > 0). Without it the solver ponded on PONDED_AREA alone and ignored the project option.
◆ node_dummy_drain
| std::vector<uint8_t> openswmm::fv::NetworkMeshData::node_dummy_drain |
1 when the node is the upstream end of a DUMMY link. Such a node is a free-drainage boundary, not a storing junction: the pass-through removes exactly what arrives, so its volume is constant and its head needs no relaxation (the correction would be identically zero — see ExplicitFvSolver::relaxOneNode).
◆ node_face_idx
| std::vector<int> openswmm::fv::NetworkMeshData::node_face_idx |
◆ node_face_ptr
| std::vector<int> openswmm::fv::NetworkMeshData::node_face_ptr |
[n_nodes + 1] row pointers
◆ node_face_sign
| std::vector<double> openswmm::fv::NetworkMeshData::node_face_sign |
+1 flux ENTERS the node, −1 leaves it
◆ node_face_zb
| std::vector<double> openswmm::fv::NetworkMeshData::node_face_zb |
Bed elevation the node presents to each of its faces — the conduit invert at that end (node invert + link offset). Parallel to node_face_idx.
◆ node_full_depth
| std::vector<double> openswmm::fv::NetworkMeshData::node_full_depth |
◆ node_invert
| std::vector<double> openswmm::fv::NetworkMeshData::node_invert |
◆ node_kind
| std::vector<uint8_t> openswmm::fv::NetworkMeshData::node_kind |
0 regular junction, 1 virtual junction (no volume — its faces were spliced into interior faces and it owns none), 2 storage, 3 outfall.
◆ node_ponded_area
| std::vector<double> openswmm::fv::NetworkMeshData::node_ponded_area |
ponding area above the rim (ft²)
◆ node_sur_depth
| std::vector<double> openswmm::fv::NetworkMeshData::node_sur_depth |
SURCHARGE_DEPTH above the rim (ft)
◆ node_vj_face
| std::vector<int> openswmm::fv::NetworkMeshData::node_vj_face |
Spliced face of each virtual junction (−1 for every other node): the reverse of face_vj_node. A lateral inflow at a virtual junction is diverted into the two cells adjoining that face (ExplicitFvSolver::refreshStructFlows), and the reporting path reads the same two cells' conduits for the node's through-flow — neither should scan the face list per node per step.
◆ node_vol_atop
| std::vector<double> openswmm::fv::NetworkMeshData::node_vol_atop |
surface area above dmax (ft²)
◆ node_vol_dmax
| std::vector<double> openswmm::fv::NetworkMeshData::node_vol_dmax |
depth at the table top (ft)
◆ node_vol_off
| std::vector<int> openswmm::fv::NetworkMeshData::node_vol_off |
offset into node_vol_tbl, −1 = none
◆ node_vol_tbl
| std::vector<double> openswmm::fv::NetworkMeshData::node_vol_tbl |
kNodeVolSamples volumes per node
◆ struct_is_dummy
| std::vector<uint8_t> openswmm::fv::NetworkMeshData::struct_is_dummy |
1 for a DUMMY-xsect conduit, 0 for a real structure. Parallel to struct_link.
◆ struct_link
| std::vector<int> openswmm::fv::NetworkMeshData::struct_link |
◆ struct_n1
| std::vector<int> openswmm::fv::NetworkMeshData::struct_n1 |
◆ struct_n2
| std::vector<int> openswmm::fv::NetworkMeshData::struct_n2 |
The documentation for this struct was generated from the following file: