![]() |
OpenSWMM Engine
6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
|
Cross-section closure for one conduit's cell chain. More...
#include <NetworkMeshData.hpp>
Public Attributes | |
| XSectParams | xs {} |
| section parameters (owns transect table ptrs) | |
| const xsect::XsectEval * | eval = nullptr |
| double | y_full = 0.0 |
| full depth (ft) | |
| double | a_full = 0.0 |
| area when full (ft²) | |
| double | w_max = 0.0 |
| width at widest point (ft) | |
| double | r_full = 0.0 |
| hydraulic radius when full (ft) | |
| double | barrel_scale = 1.0 |
| double | y_crown = 0.0 |
| double | t_slot = 0.0 |
| double | a_crown = 0.0 |
| double | i1_crown = 0.0 |
| I₁(y_full) — the table's last entry, cached for the same reason. | |
| uint8_t | is_open = 0 |
| open section: no crown, no slot taper | |
| double | roughness = 0.01 |
| Manning n. | |
| double | rough_factor = 0.0 |
| g·(n/PHI)² — friction denominator factor | |
| double | loss_inlet = 0.0 |
| entrance loss coefficient K | |
| double | loss_outlet = 0.0 |
| exit loss coefficient K | |
| int | barrels = 1 |
| parallel identical barrels | |
| int | culvert_code = 0 |
| double | slope = 0.0 |
| hydkernels::CulvertCurve | culvert_curve {} |
| uint8_t | culvert_mitered = 0 |
| double | i1_tbl [2 *kI1Samples] = {} |
| double | h_tbl [kI1Samples] = {} |
Cross-section closure for one conduit's cell chain.
One continuous geometry valid from dry bed to full pressurization: the Preissmann slot is folded into A(h)/T(h)/R(h) so every cell evaluates the same flux function and "transition" is just a depth crossing the crown (plan §3.3). t_slot is derived from FV_SLOT_CELERITY, and the slot mouth is tapered over [y_crown, y_full] so dA/dh stays Lipschitz through the crown — a discontinuous dA/dh would produce spurious reflections and corrupt the Riemann solver's wave-speed estimates.
| double openswmm::fv::FvGeometry::a_crown = 0.0 |
A(y_full) INCLUDING the slot area accumulated over the tapered mouth. Cached because every above-crown evaluation and the analytic I₁ extension start from it.
| double openswmm::fv::FvGeometry::a_full = 0.0 |
area when full (ft²)
| double openswmm::fv::FvGeometry::barrel_scale = 1.0 |
barrels as a factor on AREA and TOP WIDTH (see barrels below). Kept beside the fields every area evaluation already loads.
| int openswmm::fv::FvGeometry::barrels = 1 |
parallel identical barrels
| int openswmm::fv::FvGeometry::culvert_code = 0 |
[XSECTIONS] culvert code (0 = not a culvert), and the conduit slope the HEC-5 inlet-control equations need. Cold: read only at the conduit's upstream boundary face, and only when the code is set.
| hydkernels::CulvertCurve openswmm::fv::FvGeometry::culvert_curve {} |
The type code's inlet-control curve, RESOLVED at mesh build. Keeping the resolved coefficients rather than the code is what lets the solver evaluate the closure with no engine dependency — the table lookup is host work, the curve is all the kernel needs.
| uint8_t openswmm::fv::FvGeometry::culvert_mitered = 0 |
| const xsect::XsectEval* openswmm::fv::FvGeometry::eval = nullptr |
Where the section's own geometry is evaluated. A pointer, not a copy: the evaluator carries the shared geometry tables, and which memory space those live in is exactly what differs between the host solver and the device backend. The mesh builder binds this to xsect::hostEval(); a device backend rebinds it to its own device-resident pair, and the same kernel bodies then run unchanged on both (plan §5.1).
| double openswmm::fv::FvGeometry::h_tbl[kI1Samples] = {} |
The INVERSE of the area column: depth sampled uniformly in AREA over [0, a_crown], h_tbl[j] being the exact root of A(h) = j·a_crown/(n−1).
The forward table is uniform in depth, which is the wrong grid to invert on. Bracketing a query area in it costs a binary search — seven dependent loads with unpredictable branches — and near the crown, where A is nearly flat in h, one depth panel spans a wide range of areas, so the bracket it yields is loose and the root-find needs several evaluations of the closure. Profiling put depthOfArea and the area lookups it drives at 87 % of solver time on a Δx = 20 ft run.
Sampling uniformly in area instead makes the panel a single divide, and makes the residuals at its two ends known WITHOUT evaluating the closure — they are the sample areas themselves. Built at init from the bracketed inverse, so it costs nothing at run time.
| double openswmm::fv::FvGeometry::i1_crown = 0.0 |
I₁(y_full) — the table's last entry, cached for the same reason.
| double openswmm::fv::FvGeometry::i1_tbl[2 *kI1Samples] = {} |
First moment I₁(h) = ∫₀ʰ A(η)dη sampled uniformly on h ∈ [0, y_full], followed by the companion A(h) samples on the same grid — 2·kI1Samples entries, [0, kI1Samples) = I₁ and [kI1Samples, 2·kI1Samples) = A. One buffer because both are read together on every evaluation.
Built once at init by composite integration of the same A(h) the solver evaluates. Quadrature error does not threaten well-balancedness — that needs only a single-valued I₁(h) — but it does set the accuracy of the pressure term, hence the fine sub-sampling in buildI1Table.
A fixed inline array rather than a vector: the whole struct is copied into device memory by the accelerated backend, and an owning container cannot cross that boundary. At 129 samples this is 2 kB per DISTINCT cross-section — a few hundred at most in a real model.
| uint8_t openswmm::fv::FvGeometry::is_open = 0 |
open section: no crown, no slot taper
| double openswmm::fv::FvGeometry::loss_inlet = 0.0 |
entrance loss coefficient K
| double openswmm::fv::FvGeometry::loss_outlet = 0.0 |
exit loss coefficient K
| double openswmm::fv::FvGeometry::r_full = 0.0 |
hydraulic radius when full (ft)
| double openswmm::fv::FvGeometry::rough_factor = 0.0 |
g·(n/PHI)² — friction denominator factor
| double openswmm::fv::FvGeometry::roughness = 0.01 |
Manning n.
| double openswmm::fv::FvGeometry::slope = 0.0 |
| double openswmm::fv::FvGeometry::t_slot = 0.0 |
Top width of the slot above the crown, g·A_full/c_slot². Open shapes carry w_max here so the vertical-wall extension is one code path.
| double openswmm::fv::FvGeometry::w_max = 0.0 |
width at widest point (ft)
| XSectParams openswmm::fv::FvGeometry::xs {} |
section parameters (owns transect table ptrs)
| double openswmm::fv::FvGeometry::y_crown = 0.0 |
Depth at which the slot begins to open. Closed shapes: SLOT_CROWN_CUTOFF · y_full (Sjöberg-style, engages just below the crown). Open shapes: y_full, with no taper — the section simply continues with vertical walls.
| double openswmm::fv::FvGeometry::y_full = 0.0 |
full depth (ft)