Dynamic wave solver — operates on entire link/node system.
More...
#include <DynamicWave.hpp>
|
| void | init (int n_nodes, int n_links, const XSectGroups &groups, const SimulationContext &ctx) |
| |
| void | setNumThreads (int n, std::vector< std::string > *warnings=nullptr) |
| | Set the number of OpenMP threads for parallel loops.
|
| |
| int | execute (SimulationContext &ctx, double dt, NonConduitFlowFunc non_conduit_fn=nullptr) |
| | Execute one DW routing timestep.
|
| |
| bool | lastConverged () const |
| |
| double | getRoutingStep (SimulationContext &ctx, double fixed_step, double courant_factor) |
| | Compute CFL-based variable timestep.
|
| |
| bool | isInitialized () const noexcept |
| |
| uint8_t & | nodeSurchargedFlag (int idx) |
| | Direct write access to the per-node is_surcharged flag (for tests/non-conduit scatter).
|
| |
| double * | nodeNewSurfAreaDataMut () |
| |
| bool | isBypassed (int j) const |
| |
| double & | nodeSumDqdh (int n) |
| |
| void | setNodeDepthForTest (SimulationContext &ctx, int node_idx, double dt, int step) |
| |
| const std::vector< uint8_t > & | aaSkipFlags () const |
| | Access per-node AA skip flags (read-only, for testing/diagnostics).
|
| |
| const DPSLinkArrays & | dpsState () const |
| | Read-only access to DPS per-conduit state arrays (for tests/diagnostics).
|
| |
| const DPSConfig & | dpsConfig () const |
| | Read-only access to DPS configuration (for tests/diagnostics).
|
| |
| DPSLinkArrays & | dpsStateMut () |
| | Mutable access to DPS state for tests that need to seed slot conditions.
|
| |
Dynamic wave solver — operates on entire link/node system.
Working arrays are allocated once at init and reused each timestep. The solver pre-computes all cross-section geometry via XSectGroups batch API before entering the momentum arithmetic loop, ensuring the inner loop is branch-free and vectorisable.
◆ NonConduitFlowFunc
Callback for computing non-conduit link flows inside the Picard loop. Parameters: (ctx, dt, picard_step) where step=0 is first iteration.
◆ aaSkipFlags()
| const std::vector< uint8_t > & openswmm::dynwave::DWSolver::aaSkipFlags |
( |
| ) |
const |
|
inline |
Access per-node AA skip flags (read-only, for testing/diagnostics).
◆ dpsConfig()
| const DPSConfig & openswmm::dynwave::DWSolver::dpsConfig |
( |
| ) |
const |
|
inline |
Read-only access to DPS configuration (for tests/diagnostics).
◆ dpsState()
| const DPSLinkArrays & openswmm::dynwave::DWSolver::dpsState |
( |
| ) |
const |
|
inline |
Read-only access to DPS per-conduit state arrays (for tests/diagnostics).
◆ dpsStateMut()
Mutable access to DPS state for tests that need to seed slot conditions.
◆ execute()
Execute one DW routing timestep.
- Parameters
-
| ctx | Simulation context. |
| dt | Timestep (seconds). |
| non_conduit_fn | Optional callback to compute pump/orifice/weir/outlet flows inside the Picard iteration loop (matching legacy). |
- Returns
- Number of Picard iterations used.
◆ getRoutingStep()
| double openswmm::dynwave::DWSolver::getRoutingStep |
( |
SimulationContext & | ctx, |
|
|
double | fixed_step, |
|
|
double | courant_factor ) |
Compute CFL-based variable timestep.
Also updates per-node/link CFL-critical counters (matching legacy stats_updateCriticalTimeCount).
◆ init()
◆ isBypassed()
| bool openswmm::dynwave::DWSolver::isBypassed |
( |
int | j | ) |
const |
|
inline |
Per-link bypass flag (1 = both end nodes converged → flow held this iteration). Read by the non_conduit_fn callback to hold bypassed weir/orifice/pump/outlet flows, matching legacy findLinkFlows.
Reports "not bypassed" when uninitialized, which is the right answer for a caller with no Picard loop: bypassing means "hold the previous
iteration's flow", and there is no previous iteration to hold.
◆ isInitialized()
| bool openswmm::dynwave::DWSolver::isInitialized |
( |
| ) |
const |
|
inlinenoexcept |
True once init() has sized the per-node and per-link work arrays.
The non-conduit structure callback is SHARED with the finite-volume router, which never calls init() — Router::init only constructs the DW solver in its DYNWAVE arm. Everything below indexes arrays that init() allocates, so a caller outside the dynamic-wave loop must test this first. Without it, an FV model containing any pump, orifice, weir or outlet indexes empty vectors.
◆ lastConverged()
| bool openswmm::dynwave::DWSolver::lastConverged |
( |
| ) |
const |
|
inline |
Whether the most recent execute() reached Picard convergence on its final iteration (legacy dynwave.c: a step is "not converging" iff this is false after MaxTrials — NOT merely because it used all trials). Used for the "% of Steps Not Converging" stability statistic.
◆ nodeNewSurfAreaDataMut()
| double * openswmm::dynwave::DWSolver::nodeNewSurfAreaDataMut |
( |
| ) |
|
|
inline |
Mutable pointer to the per-node new_surf_area array (for HydStructures scatter). Null when uninitialized; the two consumers already guard.
◆ nodeSumDqdh()
| double & openswmm::dynwave::DWSolver::nodeSumDqdh |
( |
int | n | ) |
|
|
inline |
Mutable reference to the per-node sumdqdh accumulator at index n. PRECONDITION: isInitialized(). The head-sensitivity accumulator only means anything inside the implicit node-continuity solve.
◆ nodeSurchargedFlag()
| uint8_t & openswmm::dynwave::DWSolver::nodeSurchargedFlag |
( |
int | idx | ) |
|
|
inline |
Direct write access to the per-node is_surcharged flag (for tests/non-conduit scatter).
◆ setNodeDepthForTest()
| void openswmm::dynwave::DWSolver::setNodeDepthForTest |
( |
SimulationContext & | ctx, |
|
|
int | node_idx, |
|
|
double | dt, |
|
|
int | step ) |
|
inline |
Direct call into the private per-node depth update (for tests): runs the node-continuity update on the current ctx/xnode_ state and commits the result. PRECONDITION: execute() has run at least once so the node-invariant tile is built.
◆ setNumThreads()
| void openswmm::dynwave::DWSolver::setNumThreads |
( |
int | n, |
|
|
std::vector< std::string > * | warnings = nullptr ) |
Set the number of OpenMP threads for parallel loops.
Called after init() when the thread count is finalized. Resolution (threadinfo::dwThreads): 0 = auto — omp_get_max_threads(), the conduits-per-thread gate and the Apple Silicon P-core clamp; N > 0 = honoured exactly, subject only to the conduits-per-thread gate, with warnings when N exceeds the machine / runtime limits. SWMM_DW_THREADS forces the count outright (warned).
- Parameters
-
| n | Requested thread count ([OPTIONS] THREADS). |
| warnings | Optional sink for human-readable warnings. |
◆ anderson_accel
| bool openswmm::dynwave::DWSolver::anderson_accel = false |
Enable Anderson acceleration.
◆ evap_rate
| double openswmm::dynwave::DWSolver::evap_rate = 0.0 |
Evaporation rate (ft/s) — set by Router::step() each timestep so that solveMomentumBatch can recompute dq6 per Picard iteration (Gap #14).
◆ head_tol
◆ max_trials
◆ node_continuity
◆ omega
| double openswmm::dynwave::DWSolver::omega = OMEGA |
◆ surcharge_method
◆ tpa_celerity
| double openswmm::dynwave::DWSolver::tpa_celerity = 100.0 |
TPA acoustic celerity a (PROJECT length units per second, converted to ft/s at init like FV_SLOT_CELERITY). Sets the constant slot width w_tpa = g·A_full/a² per conduit (TPA plan §B1). Issue #156.
◆ uf_k3
| double openswmm::dynwave::DWSolver::uf_k3 = 0.015 |
Brunone-type k3; consumed only when active.
◆ uf_nb_dn_
| std::vector<int> openswmm::dynwave::DWSolver::uf_nb_dn_ |
◆ uf_nb_up_
| std::vector<int> openswmm::dynwave::DWSolver::uf_nb_up_ |
Cross-link ∂V/∂x stencil for UF (issue #156). A full link has equal end areas, so the within-link |v2−v1| estimator is structurally ZERO in exactly the pressurized cases UF exists for (measured: pure added inertia, slight ANTI-damping). The gradient therefore comes from the neighboring conduits' previous-iterate velocities across simple degree-2 conduit junctions (links.flow is double-buffered within a Picard iteration, so neighbor reads are deterministic at any thread count). Built once in init() when unsteady_friction != 0; -1 = no simple neighbor on that side (falls back one-sided / within-link).
◆ uf_sg_dn_
| std::vector<int8_t> openswmm::dynwave::DWSolver::uf_sg_dn_ |
+1 same sense, -1 opposed
◆ uf_sg_up_
| std::vector<int8_t> openswmm::dynwave::DWSolver::uf_sg_up_ |
◆ unsteady_friction
| int openswmm::dynwave::DWSolver::unsteady_friction = 0 |
Unsteady friction (issue #156 Phase 3): 0 = NONE (default, bit-inert), 1 = VITKOVSKY. Folded into the momentum denominator (so dqdh_ stays consistent with the surcharge Jacobian) with the same dead-band and half-momentum clamp as kernels::ufUpdate on the FV side.
The documentation for this class was generated from the following files:
- /home/runner/work/openswmm.engine/openswmm.engine/src/engine/hydraulics/DynamicWave.hpp
- /home/runner/work/openswmm.engine/openswmm.engine/src/engine/hydraulics/DynamicWave.cpp