OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
openswmm::dynwave::DWSolver Class Reference

Dynamic wave solver — operates on entire link/node system. More...

#include <DynamicWave.hpp>

Collaboration diagram for openswmm::dynwave::DWSolver:

Public Types

using NonConduitFlowFunc = std::function<void(SimulationContext&, double, int)>
 

Public Member Functions

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 DPSLinkArraysdpsState () const
 Read-only access to DPS per-conduit state arrays (for tests/diagnostics).
 
const DPSConfigdpsConfig () const
 Read-only access to DPS configuration (for tests/diagnostics).
 
DPSLinkArraysdpsStateMut ()
 Mutable access to DPS state for tests that need to seed slot conditions.
 

Public Attributes

double head_tol = DEFAULT_HEAD_TOL
 
int max_trials = DEFAULT_MAX_TRIALS
 
double omega = OMEGA
 
SurchargeMethod surcharge_method = SurchargeMethod::EXTRAN
 
NodeContinuity node_continuity = NodeContinuity::EXPLICIT
 
bool anderson_accel = false
 Enable Anderson acceleration.
 
int unsteady_friction = 0
 
double uf_k3 = 0.015
 Brunone-type k3; consumed only when active.
 
double tpa_celerity = 100.0
 
std::vector< int > uf_nb_up_
 
std::vector< int > uf_nb_dn_
 
std::vector< int8_t > uf_sg_up_
 
std::vector< int8_t > uf_sg_dn_
 +1 same sense, -1 opposed
 
double evap_rate = 0.0
 

Detailed Description

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.

Member Typedef Documentation

◆ NonConduitFlowFunc

using openswmm::dynwave::DWSolver::NonConduitFlowFunc = std::function<void(SimulationContext&, double, int)>

Callback for computing non-conduit link flows inside the Picard loop. Parameters: (ctx, dt, picard_step) where step=0 is first iteration.

Member Function Documentation

◆ 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()

DPSLinkArrays & openswmm::dynwave::DWSolver::dpsStateMut ( )
inline

Mutable access to DPS state for tests that need to seed slot conditions.

◆ execute()

int openswmm::dynwave::DWSolver::execute ( SimulationContext & ctx,
double dt,
DWSolver::NonConduitFlowFunc non_conduit_fn = nullptr )

Execute one DW routing timestep.

Parameters
ctxSimulation context.
dtTimestep (seconds).
non_conduit_fnOptional callback to compute pump/orifice/weir/outlet flows inside the Picard iteration loop (matching legacy).
Returns
Number of Picard iterations used.
Here is the call graph for this function:

◆ 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).

Here is the call graph for this function:

◆ init()

void openswmm::dynwave::DWSolver::init ( int n_nodes,
int n_links,
const XSectGroups & groups,
const SimulationContext & ctx )
Here is the call graph for this function:

◆ 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
nRequested thread count ([OPTIONS] THREADS).
warningsOptional sink for human-readable warnings.
Here is the call graph for this function:

Member Data Documentation

◆ 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

double openswmm::dynwave::DWSolver::head_tol = DEFAULT_HEAD_TOL

◆ max_trials

int openswmm::dynwave::DWSolver::max_trials = DEFAULT_MAX_TRIALS

◆ node_continuity

NodeContinuity openswmm::dynwave::DWSolver::node_continuity = NodeContinuity::EXPLICIT

◆ omega

double openswmm::dynwave::DWSolver::omega = OMEGA

◆ surcharge_method

SurchargeMethod openswmm::dynwave::DWSolver::surcharge_method = SurchargeMethod::EXTRAN

◆ 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: