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

Structure-of-Arrays storage for all nodes. More...

#include <NodeData.hpp>

Collaboration diagram for openswmm::NodeData:

Public Member Functions

int count () const noexcept
 Number of nodes.
 
void resize (int n)
 Replace the base node store with a requested row count.
 
void grow_to (int n)
 Extend base node columns while preserving existing prefixes.
 
void reserve_to (int n)
 Reserve capacity for n nodes without changing count().
 
void erase_at (int idx)
 Erase one node row from the columns visited by this helper.
 
void resize_loads (int n_pollutants)
 Set the pollutant load stride and zero positive-sized load storage.
 
void resize_quality (int n_pollutants)
 Set the pollutant stride and replace positive-sized quality arrays.
 
void shrink_to_fit ()
 Release excess vector capacity accumulated during parsing.
 
void save_state () noexcept
 Snapshot current state into old-step arrays before solving.
 
void save_hyd_state () noexcept
 Snapshot depth, volume, inflow and net inflow for a routed hydraulic step.
 
void save_lat_qual_state () noexcept
 Snapshot lateral inflow and pollutant concentrations every routing step.
 
void reset_state () noexcept
 Apply initial node depths and clear the hydraulic/quality state visited here.
 
void clearInflowSources () noexcept
 Zero routing-phase inflow source arrays.
 

Public Attributes

std::vector< NodeType > type
 Node type for each node.
 
std::vector< double > invert_elev
 Invert elevation (project length units).
 
std::vector< double > full_depth
 Full depth of the node (project length units).
 
std::vector< double > init_depth
 Initial water depth (project length units).
 
std::vector< double > sur_depth
 Maximum depth allowed at the node (ponding or surcharge limit).
 
std::vector< double > ponded_area
 Ponding area at the surface (sq project length units).
 
std::vector< double > storage_area
 Physical junction area (ft2); zero retains legacy behavior.
 
std::vector< uint8_t > is_virtual
 Virtual-junction flag (0 = regular node, 1 = virtual junction).
 
std::vector< uint8_t > is_inlet
 Inlet-junction flag (0 = plain node, 1 = inlet junction).
 
std::vector< double > rim_depth
 Rendering-only rim (ground) depth above the invert, project length units. 0 = unset.
 
std::vector< double > depth
 Current water depth above invert (project length units).
 
std::vector< double > head
 Current water surface head (project length units = invert + depth).
 
std::vector< double > volume
 Current water volume (project volume units).
 
std::vector< double > lat_flow
 Current lateral inflow (project flow units).
 
std::vector< double > user_lat_flow
 User-forced lateral inflow set via the API (project flow units).
 
std::vector< double > runoff_inflow
 Interpolated surface runoff from subcatchments (project flow units).
 
std::vector< double > gw_inflow
 Interpolated groundwater flow from subcatchments (project flow units).
 
std::vector< double > ext_inflow
 External (timeseries/baseline) inflows (project flow units).
 
std::vector< double > dwf_inflow
 Dry weather flow inflows (project flow units).
 
std::vector< double > rdii_inflow
 RDII unit hydrograph inflows (project flow units).
 
std::vector< double > iface_inflow
 Interface file (upstream model coupling) inflows (project flow units).
 
std::vector< double > coupling_inflow
 2D ↔ 1D coupling exchange flow at the node (project flow units).
 
std::vector< double > coupling_volume
 Pending 1D↔2D exchange VOLUME for the next routing step (1D units, ft³).
 
std::vector< uint8_t > aquifer2d_bed
 
std::vector< double > coupling_queue
 Delivery queue for the 1D↔2D junction exchange (1D units, ft³).
 
std::vector< double > coupling_qual_queue
 S3 — species MASS queue for the 2D→1D junction drain, per (node, pollutant), 1D mass units (conc × ft³).
 
std::vector< double > coupling_qual_inflow
 S3 — this step's delivered 2D→1D species mass RATE per (node, pollutant) (mass/sec); read by QualitySolver::addCouplingLoads().
 
std::vector< double > coupling_age_vol_queue
 S4 — the tuple's age-volume and temperature-volume halves, per node (age·ft³ / °C·ft³ queued; age·ft³/s / °C·ft³/s delivered). Same queue/drain rule as coupling_qual_queue; consumed by addCouplingLoads into node_age_vol_in / node_temp_vol_in when the 2D surface carries the row (coupling_tuple_age / coupling_tuple_temp), which replaces the EXTERNAL_INFLOW stand-in S3 used. Sized with the node count (cheap); untouched on decks without a 2D surface.
 
std::vector< double > coupling_temp_vol_queue
 
std::vector< double > coupling_age_vol_inflow
 
std::vector< double > coupling_temp_vol_inflow
 
bool coupling_tuple_age = false
 set by SurfaceRouter2D at initialize
 
bool coupling_tuple_temp = false
 
std::vector< double > qual_mass_in
 Accumulated quality mass inflow rate per (node, pollutant).
 
std::vector< double > qual_vol_in
 Accumulated volume inflow rate per node (ft3/sec).
 
std::vector< double > iface_qual_mass
 Routing interface file quality mass rate per (node, pollutant) (mass/sec).
 
std::vector< double > ext_qual_mass
 Direct external inflow quality mass rate per (node, pollutant) (mass/sec).
 
std::vector< double > dwf_qual_mass
 Per-node DWF pollutant mass-rate ADJUSTMENT (mass/sec), net of the global default: row mass (q·pattern-adjusted value) minus q·Pollut.dwfConcen when the global default is set. Adding it on top of the global-default DWF load reproduces legacy addDryWeatherInflows' add-row-then-subtract-default exactly. Flat 2D: [node * n_pollutants + pollutant].
 
std::vector< double > lid_drain_qual_load
 LID drain quality mass rate per (node, pollutant) (mass/sec).
 
std::vector< double > lid_drain_qual_vol
 LID drain volume inflow rate per node (ft3/sec).
 
std::vector< double > lid_drain_qual_load_old
 
std::vector< double > lid_drain_qual_vol_old
 Previous runoff step's lid_drain_qual_vol (the q half of the pair).
 
std::vector< double > lid_drain_inflow
 LID drain WATER inflow rate per node (ft3/sec) — the routing twin of lid_drain_qual_vol.
 
std::vector< double > conc
 Current quality concentration at each node.
 
std::vector< double > conc_old
 Previous-step quality at each node.
 
std::vector< double > hrt
 Hydraulic residence time for storage nodes (seconds).
 
std::vector< double > user_conc_mass_flux
 User-forced quality mass flux at each node (mass/sec).
 
int conc_n_pollutants = 0
 Number of pollutants in the quality arrays.
 
std::vector< double > inflow
 Current total inflow to the node (project flow units).
 
std::vector< double > outflow
 Current total outflow from the node (project flow units).
 
std::vector< double > overflow
 Current overflow / ponded flow (project flow units).
 
std::vector< double > losses
 Node losses (evaporation + seepage) (project flow units).
 
std::vector< double > crown_elev
 Crown elevation — top of highest connecting conduit (project length units).
 
std::vector< int > degree
 legacy Node.degree: the OUTFLOW-link count (toposort_sortLinks, a reversed conduit counted from its other end, an outfall's link at its downstream node), negated under the dynamic wave for a node with no inflow links (validateGeneralLayout): < 0 headwater (EXTRAN surcharge corr 0.6), == 0 terminal. Set in SWMMEngine::initialize (the resolver's connectivity count is provisional).
 
std::vector< double > old_net_inflow
 Net inflow from previous timestep (inflow - outflow) for averaging.
 
std::vector< double > full_volume
 Full volume at node (project volume units).
 
std::vector< double > rpt_full_volume
 Full volume in the LEGACY convention (legacy Node.fullVolume as node_validate leaves it): 0 for junctions, outfalls and dividers, the pump curve's maximum volume for a Type-1 pump's wet well (link.c:1529), the curve volume for storage.
 
std::vector< double > old_depth
 Depth at the previous timestep.
 
std::vector< double > old_volume
 Volume at the previous timestep.
 
std::vector< double > old_lat_flow
 Lateral flow at the previous timestep.
 
std::vector< double > old_inflow
 Total inflow at the previous timestep (for output interpolation).
 
std::vector< std::string > comments
 Object comment from the INP file (lines with a single ';' prefix immediately above this object's data row).
 
std::vector< std::string > tags
 Per-object tag from the INP [TAGS] section.
 
std::vector< char > rpt_flag
 Whether this node is included in report/output (0=no, 1=yes).
 
std::vector< double > stat_vol_flooded
 Total volume of water lost as overflow (project volume units).
 
std::vector< double > stat_time_flooded
 Total duration the node was flooded (seconds).
 
std::vector< double > stat_max_depth
 Maximum reported depth (project length units).
 
std::vector< double > stat_max_overflow
 Maximum reported overflow rate (project flow units).
 
std::vector< double > stat_max_overflow_date
 Date/time when maximum overflow occurred (OADate (days since 12/30/1899)).
 
std::vector< double > stat_sum_depth
 
std::vector< double > stat_sum_volume
 
std::vector< double > stat_storage_max_volume
 Maximum stored volume, capped at full volume (ft3).
 
std::vector< double > stat_storage_max_volume_date
 Date of the first maximum stored volume.
 
std::vector< double > stat_max_depth_date
 
std::vector< double > stat_max_rpt_depth
 
std::vector< double > stat_max_inflow_date
 
std::vector< double > stat_time_surcharged
 
std::vector< double > stat_max_surcharge_height
 
std::vector< double > stat_outfall_avg_flow
 Outfall cumulative average flow (flow units × reporting periods).
 
std::vector< double > stat_max_lat_inflow
 
std::vector< double > stat_max_total_inflow
 
std::vector< double > stat_storage_max_outflow
 
std::vector< double > stat_lat_inflow_vol
 
std::vector< double > stat_total_inflow_vol
 Cumulative total inflow volume at each node (ft3).
 
std::vector< double > stat_total_outflow_vol
 
std::vector< double > stat_outfall_max_flow
 Outfall maximum flow (project flow units).
 
std::vector< long > stat_outfall_periods
 Outfall number of non-zero flow periods.
 
std::vector< int > stat_non_converged_count
 Count of non-converging steps per node.
 
std::vector< double > stat_time_courant_critical
 CFL time-step critical count per node.
 
std::vector< double > stat_total_load
 Cumulative pollutant loads at each node.
 
int stat_n_pollutants = 0
 

Detailed Description

Structure-of-Arrays storage for all nodes.

All parallel arrays are indexed by node index [0, count). Use SimulationContext::node_names to translate name → index.

Fields are divided into:

  • Static properties (set during input parsing, not changed during sim)
  • State variables (updated each timestep by the hydraulic solver)
  • Cumulative statistics (totals updated each timestep)

Member Function Documentation

◆ clearInflowSources()

void openswmm::NodeData::clearInflowSources ( )
inlinenoexcept

Zero routing-phase inflow source arrays.

Called at the start of each routing step before processes write to their respective source arrays.

NOTE: runoff_inflow and gw_inflow are zeroed in stepRunoff() Phase 2 before subcatchment accumulation (matching legacy initSystemInflows which zeros newLatFlow each routing step).

Here is the caller graph for this function:

◆ count()

int openswmm::NodeData::count ( ) const
inlinenoexcept

Number of nodes.

Here is the caller graph for this function:

◆ erase_at()

void openswmm::NodeData::erase_at ( int idx)
inline

Erase one node row from the columns visited by this helper.

Visits owned base columns and pollutant/load strides, checking each vector/stride for presence. The old LID drain volume/load arrays are not visited. Caller updates subtype/coupling tables, model references, names and spatial rows. This helper does not enforce BUILDING/OPENED lifecycle. Following rows shift down and element references/iterators are invalidated. Does not make inconsistent stores transactional.

Parameters
[in]idxCaller-validated existing row index; aligned dimensions and representable size products required.
Here is the caller graph for this function:

◆ grow_to()

void openswmm::NodeData::grow_to ( int n)
inline

Extend base node columns while preserving existing prefixes.

New rows use the corresponding resize() defaults. Does not grow flattened pollutant matrices, name indexes, subtype stores or spatial arrays; caller resizes those separately. Requires initially aligned columns and valid size products; allocation failure can interrupt extension.

Parameters
[in]nRequested total count; <=count() is a no-op, including negatives.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reserve_to()

void openswmm::NodeData::reserve_to ( int n)
inline

Reserve capacity for n nodes without changing count().

Parsing grows these arrays one row at a time via grow_to(), so each of the ~60 parallel vectors reallocates and copies O(log n) times over a section — the dominant memory traffic in handler dispatch on a large model.

This reserves capacity only. It deliberately does NOT resize: count() is the vector size, and PostParseResolver compares it against the final name count and calls resize() when they differ — a call with destructive assign semantics. Growing the SIZE speculatively here would trip that path and wipe parsed data. Capacity is invisible to all of it.

Over-reserving is harmless, so callers pass the section's row count as an upper bound.

Parameters
[in]nNonnegative target capacity for the base columns; flat-array products must fit size_t.
Note
Capacity requests can allocate/throw and invalidate element references. They do not grow sizes or synchronize external name/spatial/subtype data.
Here is the caller graph for this function:

◆ reset_state()

void openswmm::NodeData::reset_state ( )
inlinenoexcept

Apply initial node depths and clear the hydraulic/quality state visited here.

Sets current/old depth from init_depth and head=invert_elev+init_depth in feet; volume and old_volume are zeroed, so caller computes geometry-dependent initial volumes. Clears flows, coupling queues and routing-phase inflow sources, plus current/old pollutant concentrations. Does not reset static properties or accumulated statistics; aligned arrays must already exist.

Here is the call graph for this function:

◆ resize()

void openswmm::NodeData::resize ( int n)
inline

Replace the base node store with a requested row count.

Replaces base-node numeric/configuration/state/statistics columns with defaults (JUNCTION type); clears incoming pollutant mass arrays. Does not resize concentration, old concentration, user pollutant forcing, HRT or stat_total_load; call the dedicated quality/load sizing functions. Names, subtype stores and spatial rows live separately. Independent assignments can fail without rollback; borrowed elements may be invalidated.

Parameters
[in]nNonnegative row count; unchecked conversion to size_t, with valid size products for flat statistics.
Here is the caller graph for this function:

◆ resize_loads()

void openswmm::NodeData::resize_loads ( int n_pollutants)
inline

Set the pollutant load stride and zero positive-sized load storage.

Always assigns stat_n_pollutants. Nonpositive counts preserve the existing stat_total_load vector rather than clearing it. Does not resize concentration state or update names.

Parameters
[in]n_pollutantsPollutants per node; positive count sizes count()*n_pollutants, product must fit size_t.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resize_quality()

void openswmm::NodeData::resize_quality ( int n_pollutants)
inline

Set the pollutant stride and replace positive-sized quality arrays.

Always stores conc_n_pollutants; nonpositive counts leave existing vectors unchanged. Zeroes current/old concentrations, HRT, user mass-flux and source/coupling/LID drain load arrays; does not resize old LID drain load storage. Allocation failure may leave partial assignments. No pollutant registry update or initial-concentration seeding.

Parameters
[in]n_pollutantsPollutants per node; positive count requires count()*n_pollutants to fit size_t.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ save_hyd_state()

void openswmm::NodeData::save_hyd_state ( )
inlinenoexcept

Snapshot depth, volume, inflow and net inflow for a routed hydraulic step.

Copies to preallocated old arrays and computes old_net_inflow=inflow-outflow. Requires aligned source/destination arrays. Call only when actually routing; skipped steady steps retain their prior old/new hydraulic pair.

Here is the caller graph for this function:

◆ save_lat_qual_state()

void openswmm::NodeData::save_lat_qual_state ( )
inlinenoexcept

Snapshot lateral inflow and pollutant concentrations every routing step.

Copies lat_flow to old_lat_flow and conc to conc_old; destination arrays must already be long enough. Called even when steady hydraulics are skipped; no allocation or timing/state advancement.

Here is the caller graph for this function:

◆ save_state()

void openswmm::NodeData::save_state ( )
inlinenoexcept

Snapshot current state into old-step arrays before solving.

Here is the call graph for this function:

◆ shrink_to_fit()

void openswmm::NodeData::shrink_to_fit ( )
inline

Release excess vector capacity accumulated during parsing.

Called once after final sizing is complete. Each vector's capacity is reduced to match its size, freeing memory that was over-allocated by geometric growth during incremental parsing.

Member Data Documentation

◆ aquifer2d_bed

std::vector<uint8_t> openswmm::NodeData::aquifer2d_bed

G-X2 (2026-09-19): 1 when the node has a two-zone aquifer bed under it (a [2D_AQUIFER_NODE] row or auto-enrolment). A storage node so flagged exchanges through the conductance channel and its own exfiltration is skipped (one owner). Empty until the 2D router resolved an aquifer.

◆ comments

std::vector<std::string> openswmm::NodeData::comments

Object comment from the INP file (lines with a single ';' prefix immediately above this object's data row).

Multiple comment lines are joined by the literal two-character token "\\n" (backslash + n). Empty string means no comment. Written back to INP by InpWriter as one ';'-prefixed row per part. Also stored verbatim in the GeoPackage 'comment' column.

◆ conc

std::vector<double> openswmm::NodeData::conc

Current quality concentration at each node.

Size = n_nodes * n_pollutants.

See also
Legacy: Node[i].newQual[]

◆ conc_n_pollutants

int openswmm::NodeData::conc_n_pollutants = 0

Number of pollutants in the quality arrays.

◆ conc_old

std::vector<double> openswmm::NodeData::conc_old

Previous-step quality at each node.

◆ coupling_age_vol_inflow

std::vector<double> openswmm::NodeData::coupling_age_vol_inflow

◆ coupling_age_vol_queue

std::vector<double> openswmm::NodeData::coupling_age_vol_queue

S4 — the tuple's age-volume and temperature-volume halves, per node (age·ft³ / °C·ft³ queued; age·ft³/s / °C·ft³/s delivered). Same queue/drain rule as coupling_qual_queue; consumed by addCouplingLoads into node_age_vol_in / node_temp_vol_in when the 2D surface carries the row (coupling_tuple_age / coupling_tuple_temp), which replaces the EXTERNAL_INFLOW stand-in S3 used. Sized with the node count (cheap); untouched on decks without a 2D surface.

◆ coupling_inflow

std::vector<double> openswmm::NodeData::coupling_inflow

2D ↔ 1D coupling exchange flow at the node (project flow units).

Signed: positive = 2D → 1D (surface drainage into the node), negative = 1D → 2D (surcharge spill onto the surface). Written by SurfaceRouter2D::advancePostRouting at the end of step N; read by assembleLateralInflows at the start of step N+1 (so the value persists across the step boundary and is consumed exactly once by the DW solver).

For mass-balance accounting the signed value is split:

  • positive side folds into step_ext_inflow → routing_external
  • negative side folds into routing_flooding (absolute value)

This replaces the earlier scheme of routing coupling Q through forcing.node_lat_inflow_value, which conflated user forcing with 2D coupling and dropped the negative (1D→2D) volume from the mass balance entirely.

See also
docs/1D_2D_COUPLING_GATE_REVIEW.md §11

◆ coupling_qual_inflow

std::vector<double> openswmm::NodeData::coupling_qual_inflow

S3 — this step's delivered 2D→1D species mass RATE per (node, pollutant) (mass/sec); read by QualitySolver::addCouplingLoads().

◆ coupling_qual_queue

std::vector<double> openswmm::NodeData::coupling_qual_queue

S3 — species MASS queue for the 2D→1D junction drain, per (node, pollutant), 1D mass units (conc × ft³).

Filled by SurfaceRouter2D from the marcher's per-point exch_mass (2D→1D drains only, at the CELL's concentration); drained by assembleLateralInflows with the SAME rule as coupling_queue (uniform rate over the remaining delivery span, flushed when remaining ≤ dt) so mass and water arrive in the same proportions. Flat 2D [node * n_pollutants + pollutant]. Never negative: a 1D→2D spill removes mass from the node IMPLICITLY through the reduced mixing volume (the CSTR takes every outflow at the mixed concentration), so no debit is queued for it. In-memory only.

◆ coupling_queue

std::vector<double> openswmm::NodeData::coupling_queue

Delivery queue for the 1D↔2D junction exchange (1D units, ft³).

SurfaceRouter2D::fireAdvanceWindow moves each fired window's coupling_volume here after the 2D mass-balance ledger books it; assembleLateralInflows drains the queue at the uniform rate queue / SimulationContext::coupling_delivery_remaining, so a multi-step advance window's exchange volume arrives spread over the following routing steps instead of as a single-step pulse (window/routing-step × the physical rate — which flooded small junctions instantly and drove a per-window drain/spill churn). Degenerates exactly to the legacy one-step delivery when the 2D advance fires every routing step (delivery window ≤ routing step). Signed like coupling_volume: + = 2D→1D drain, − = 1D→2D spill. In-memory only (not serialized to hotstart).

◆ coupling_temp_vol_inflow

std::vector<double> openswmm::NodeData::coupling_temp_vol_inflow

◆ coupling_temp_vol_queue

std::vector<double> openswmm::NodeData::coupling_temp_vol_queue

◆ coupling_tuple_age

bool openswmm::NodeData::coupling_tuple_age = false

set by SurfaceRouter2D at initialize

◆ coupling_tuple_temp

bool openswmm::NodeData::coupling_tuple_temp = false

◆ coupling_volume

std::vector<double> openswmm::NodeData::coupling_volume

Pending 1D↔2D exchange VOLUME for the next routing step (1D units, ft³).

The exchange is carried across the staggered-coupling step boundary as a volume (not a rate) so it stays mass-conservative under VARIABLE_STEP: the producer (computeCouplingExchange / the live-RHS booking) writes Q·dt here at the end of step N; the consumer (assembleLateralInflows) re-derives the rate coupling_inflow = coupling_volume/dt at the start of step N+1 and clears this, so the 1D node receives exactly the volume 2D exchanged regardless of how the timestep changes. Signed: + = 2D→1D drain, − = 1D→2D spill. In-memory only (not serialized to hotstart). See plan / review §11.

◆ crown_elev

std::vector<double> openswmm::NodeData::crown_elev

Crown elevation — top of highest connecting conduit (project length units).

See also
Legacy: Node[i].crownElev

◆ degree

std::vector<int> openswmm::NodeData::degree

legacy Node.degree: the OUTFLOW-link count (toposort_sortLinks, a reversed conduit counted from its other end, an outfall's link at its downstream node), negated under the dynamic wave for a node with no inflow links (validateGeneralLayout): < 0 headwater (EXTRAN surcharge corr 0.6), == 0 terminal. Set in SWMMEngine::initialize (the resolver's connectivity count is provisional).

See also
Legacy: Node[i].degree

◆ depth

std::vector<double> openswmm::NodeData::depth

Current water depth above invert (project length units).

See also
Legacy: Node[i].newDepth

◆ dwf_inflow

std::vector<double> openswmm::NodeData::dwf_inflow

Dry weather flow inflows (project flow units).

◆ dwf_qual_mass

std::vector<double> openswmm::NodeData::dwf_qual_mass

Per-node DWF pollutant mass-rate ADJUSTMENT (mass/sec), net of the global default: row mass (q·pattern-adjusted value) minus q·Pollut.dwfConcen when the global default is set. Adding it on top of the global-default DWF load reproduces legacy addDryWeatherInflows' add-row-then-subtract-default exactly. Flat 2D: [node * n_pollutants + pollutant].

See also
Legacy: routing.c addDryWeatherInflows() pollutant portion

◆ ext_inflow

std::vector<double> openswmm::NodeData::ext_inflow

External (timeseries/baseline) inflows (project flow units).

◆ ext_qual_mass

std::vector<double> openswmm::NodeData::ext_qual_mass

Direct external inflow quality mass rate per (node, pollutant) (mass/sec).

Written by inflow::InflowSolver::evaluate() each routing step from the [INFLOWS] CONCEN/MASS rows (cleared in clearInflowSources()); read by QualitySolver::addExtInflowLoads() → added to qual_mass_in. Flat 2D: [node * n_pollutants + pollutant]. CONCEN rows are already multiplied by the node's external flow inflow, so this is a mass rate for either row type.

See also
Legacy: routing.c addExternalInflows() pollutant portion

◆ full_depth

std::vector<double> openswmm::NodeData::full_depth

Full depth of the node (project length units).

See also
Legacy: Node[i].fullDepth

◆ full_volume

std::vector<double> openswmm::NodeData::full_volume

Full volume at node (project volume units).

See also
Legacy: Node[i].fullVolume

◆ gw_inflow

std::vector<double> openswmm::NodeData::gw_inflow

Interpolated groundwater flow from subcatchments (project flow units).

◆ head

std::vector<double> openswmm::NodeData::head

Current water surface head (project length units = invert + depth).

See also
Legacy: Node[i].newHead

◆ hrt

std::vector<double> openswmm::NodeData::hrt

Hydraulic residence time for storage nodes (seconds).

◆ iface_inflow

std::vector<double> openswmm::NodeData::iface_inflow

Interface file (upstream model coupling) inflows (project flow units).

◆ iface_qual_mass

std::vector<double> openswmm::NodeData::iface_qual_mass

Routing interface file quality mass rate per (node, pollutant) (mass/sec).

Written by iface::InterfaceManager::readInflows() each routing step (cleared in clearInflowSources()); read by QualitySolver::addIfaceLoads() → added to qual_mass_in. Flat 2D: [node * n_pollutants + pollutant].

See also
Legacy: routing.c addIfaceInflows() quality portion

◆ inflow

std::vector<double> openswmm::NodeData::inflow

Current total inflow to the node (project flow units).

See also
Legacy: Node[i].inflow

◆ init_depth

std::vector<double> openswmm::NodeData::init_depth

Initial water depth (project length units).

See also
Legacy: Node[i].initDepth

◆ invert_elev

std::vector<double> openswmm::NodeData::invert_elev

Invert elevation (project length units).

See also
Legacy: Node[i].invertElev

◆ is_inlet

std::vector<uint8_t> openswmm::NodeData::is_inlet

Inlet-junction flag (0 = plain node, 1 = inlet junction).

An inlet junction is a virtual junction (is_virtual is always set alongside this flag) that additionally carries a street inlet: it sits between two STREET conduits and diverts captured gutter flow to a separate capture node through the usage row InletUsageStore::find_by_node_host(idx) (INP section [INLET_JUNCTIONS]). Refactored engine only.

◆ is_virtual

std::vector<uint8_t> openswmm::NodeData::is_virtual

Virtual-junction flag (0 = regular node, 1 = virtual junction).

A virtual junction is a zero-storage, momentum-transmitting JUNCTION connecting exactly two conduits of identical cross section (INP section [VIRTUAL_JUNCTIONS]). The NodeType stays JUNCTION so the binary .out type-code space is unchanged. Refactored engine only — the legacy engine has no support.

◆ lat_flow

std::vector<double> openswmm::NodeData::lat_flow

Current lateral inflow (project flow units).

See also
Legacy: Node[i].newLatFlow

◆ lid_drain_inflow

std::vector<double> openswmm::NodeData::lid_drain_inflow

LID drain WATER inflow rate per node (ft3/sec) — the routing twin of lid_drain_qual_vol.

Set once per runoff step by the LID block in stepRunoff() and read by assembleLateralInflows() every routing step until the next runoff step overwrites it. It is NOT ext_inflow: that array is cleared by clearInflowSources() at the top of every routing step, i.e. AFTER stepRunoff has added to it, so a drain booked there never reached the network (LID fix round, 2026-08-30 — every drain-to-node case, not only the target-less one). Legacy books it as Node.newLatFlow + EXTERNAL_INFLOW.

◆ lid_drain_qual_load

std::vector<double> openswmm::NodeData::lid_drain_qual_load

LID drain quality mass rate per (node, pollutant) (mass/sec).

Set once per runoff step (cleared at runoff step start); read each routing step by addWetWeatherLoads() → added to qual_mass_in. Flat 2D: [node * n_pollutants + pollutant]. Covers drain-to-node and drain-to-subcatch (routed to outlet node). Matches legacy lid_addDrainInflow() / lid_addDrainRunon() quality.

See also
Legacy: lid.c lid_addDrainInflow(), lid_addDrainRunon()

◆ lid_drain_qual_load_old

std::vector<double> openswmm::NodeData::lid_drain_qual_load_old

Previous runoff step's lid_drain_qual_load, for legacy lid_addDrainInflow's routing-step interpolation: w = (1-f)*oldDrainFlow*oldQual + f*newDrainFlow*newQual (lid.c). Rolled from the current arrays at the top of each runoff step, before A6b refills them.

◆ lid_drain_qual_vol

std::vector<double> openswmm::NodeData::lid_drain_qual_vol

LID drain volume inflow rate per node (ft3/sec).

Set once per runoff step; read each routing step by addWetWeatherLoads() → added to qual_vol_in (denominator for mixing).

See also
Legacy: lid.c lid_addDrainInflow() Node[k].newLatFlow contribution

◆ lid_drain_qual_vol_old

std::vector<double> openswmm::NodeData::lid_drain_qual_vol_old

Previous runoff step's lid_drain_qual_vol (the q half of the pair).

◆ losses

std::vector<double> openswmm::NodeData::losses

Node losses (evaporation + seepage) (project flow units).

See also
Legacy: Node[i].losses

◆ old_depth

std::vector<double> openswmm::NodeData::old_depth

Depth at the previous timestep.

◆ old_inflow

std::vector<double> openswmm::NodeData::old_inflow

Total inflow at the previous timestep (for output interpolation).

See also
Legacy: Node[i].oldFlowInflow (node.c:294, node_getResults node.c:491)

◆ old_lat_flow

std::vector<double> openswmm::NodeData::old_lat_flow

Lateral flow at the previous timestep.

◆ old_net_inflow

std::vector<double> openswmm::NodeData::old_net_inflow

Net inflow from previous timestep (inflow - outflow) for averaging.

See also
Legacy: Node[i].oldNetInflow

◆ old_volume

std::vector<double> openswmm::NodeData::old_volume

Volume at the previous timestep.

◆ outflow

std::vector<double> openswmm::NodeData::outflow

Current total outflow from the node (project flow units).

See also
Legacy: Node[i].outflow

◆ overflow

std::vector<double> openswmm::NodeData::overflow

Current overflow / ponded flow (project flow units).

See also
Legacy: Node[i].overflow

◆ ponded_area

std::vector<double> openswmm::NodeData::ponded_area

Ponding area at the surface (sq project length units).

See also
Legacy: Node[i].pondedArea

◆ qual_mass_in

std::vector<double> openswmm::NodeData::qual_mass_in

Accumulated quality mass inflow rate per (node, pollutant).

Flat 2D: [node * n_pollutants + pollutant]. Units: mass/sec.

◆ qual_vol_in

std::vector<double> openswmm::NodeData::qual_vol_in

Accumulated volume inflow rate per node (ft3/sec).

◆ rdii_inflow

std::vector<double> openswmm::NodeData::rdii_inflow

RDII unit hydrograph inflows (project flow units).

◆ rim_depth

std::vector<double> openswmm::NodeData::rim_depth

Rendering-only rim (ground) depth above the invert, project length units. 0 = unset.

Optional third token of a [VIRTUAL_JUNCTIONS] row. A virtual junction's full_depth is derived — it is always the shared pipe crown — which makes every ground/terrain line a viewer draws collapse to the crown at the break point. This field carries the surface elevation for those drawings and nothing else: it is written by the input and edit paths and read only by renderers. No hydraulics, routing, reporting or output-file code may read it, so a model produces bit-identical results whether or not it is supplied.

◆ rpt_flag

std::vector<char> openswmm::NodeData::rpt_flag

Whether this node is included in report/output (0=no, 1=yes).

See also
Legacy: Node[j].rptFlag

◆ rpt_full_volume

std::vector<double> openswmm::NodeData::rpt_full_volume

Full volume in the LEGACY convention (legacy Node.fullVolume as node_validate leaves it): 0 for junctions, outfalls and dividers, the pump curve's maximum volume for a Type-1 pump's wet well (link.c:1529), the curve volume for storage.

The dynamic wave books node volume in this convention, so a ponded junction holds only the water above its rim and a plain junction none; that is what the .out NODE_VOLUME, the routing mass balance, control rules and quality mixing see. full_volume keeps MIN_SURFAREA*fullDepth for junctions because the FV mesh derives its node area from it.

◆ runoff_inflow

std::vector<double> openswmm::NodeData::runoff_inflow

Interpolated surface runoff from subcatchments (project flow units).

◆ stat_lat_inflow_vol

std::vector<double> openswmm::NodeData::stat_lat_inflow_vol

Cumulative lateral inflow volume at each node (ft3).

See also
Legacy: NodeStats[i].totLatFlow

◆ stat_max_depth

std::vector<double> openswmm::NodeData::stat_max_depth

Maximum reported depth (project length units).

See also
Legacy: NodeStats[i].maxDepth

◆ stat_max_depth_date

std::vector<double> openswmm::NodeData::stat_max_depth_date

Date/time when maximum depth occurred (OADate (days since 12/30/1899)).

See also
Legacy: NodeStats[i].maxDepthDate

◆ stat_max_inflow_date

std::vector<double> openswmm::NodeData::stat_max_inflow_date

Date/time when maximum total inflow occurred (OADate (days since 12/30/1899)).

See also
Legacy: NodeStats[i].maxInflowDate

◆ stat_max_lat_inflow

std::vector<double> openswmm::NodeData::stat_max_lat_inflow

Maximum lateral inflow at each node (project flow units).

See also
Legacy: NodeStats[i].maxLatFlow

◆ stat_max_overflow

std::vector<double> openswmm::NodeData::stat_max_overflow

Maximum reported overflow rate (project flow units).

See also
Legacy: NodeStats[i].maxOverflow

◆ stat_max_overflow_date

std::vector<double> openswmm::NodeData::stat_max_overflow_date

Date/time when maximum overflow occurred (OADate (days since 12/30/1899)).

◆ stat_max_rpt_depth

std::vector<double> openswmm::NodeData::stat_max_rpt_depth

Maximum reported depth (used for output-step max tracking).

See also
Legacy: NodeStats[i].maxRptDepth

◆ stat_max_surcharge_height

std::vector<double> openswmm::NodeData::stat_max_surcharge_height

Maximum surcharge height above crown (project length units).

See also
Legacy: NodeStats[i].maxDepth - Node[i].fullDepth

◆ stat_max_total_inflow

std::vector<double> openswmm::NodeData::stat_max_total_inflow

Maximum total inflow at each node (project flow units).

See also
Legacy: NodeStats[i].maxInflow

◆ stat_n_pollutants

int openswmm::NodeData::stat_n_pollutants = 0

◆ stat_non_converged_count

std::vector<int> openswmm::NodeData::stat_non_converged_count

Count of non-converging steps per node.

Incremented when a routing step fails to converge and the node itself did not converge (matching legacy NodeStats[i].nonConvergedCount).

See also
Legacy: stats_updateConvergenceStats()

◆ stat_outfall_avg_flow

std::vector<double> openswmm::NodeData::stat_outfall_avg_flow

Outfall cumulative average flow (flow units × reporting periods).

See also
Legacy: OutfallStats[k].avgFlow

◆ stat_outfall_max_flow

std::vector<double> openswmm::NodeData::stat_outfall_max_flow

Outfall maximum flow (project flow units).

See also
Legacy: OutfallStats[k].maxFlow

◆ stat_outfall_periods

std::vector<long> openswmm::NodeData::stat_outfall_periods

Outfall number of non-zero flow periods.

See also
Legacy: OutfallStats[k].totalPeriods

◆ stat_storage_max_outflow

std::vector<double> openswmm::NodeData::stat_storage_max_outflow

Peak outflow released by a storage unit (project flow units). Storage only; stays zero elsewhere. Tracked separately from inflow because a pond's whole purpose is that the two differ.

See also
Legacy: StorageStats[k].maxFlow (stats.c:588)

◆ stat_storage_max_volume

std::vector<double> openswmm::NodeData::stat_storage_max_volume

Maximum stored volume, capped at full volume (ft3).

◆ stat_storage_max_volume_date

std::vector<double> openswmm::NodeData::stat_storage_max_volume_date

Date of the first maximum stored volume.

◆ stat_sum_depth

std::vector<double> openswmm::NodeData::stat_sum_depth

Cumulative depth for computing average (project length units × seconds).

See also
Legacy: NodeStats[i].avgDepth

◆ stat_sum_volume

std::vector<double> openswmm::NodeData::stat_sum_volume

Cumulative stored volume for computing average (internal ft³), storage nodes only. Accumulated per routing step alongside stat_sum_depth so the Storage Volume Summary's average is the true time-average of the node's nonlinear volume, not volume-of-the-average-depth (which understates a convex curve).

See also
Legacy: StorageStats[k].avgVol

◆ stat_time_courant_critical

std::vector<double> openswmm::NodeData::stat_time_courant_critical

CFL time-step critical count per node.

Incremented when the node's depth-change rate produces the smallest CFL-limited timestep (matching legacy NodeStats[i].timeCourantCritical).

See also
Legacy: stats_updateCriticalTimeCount()

◆ stat_time_flooded

std::vector<double> openswmm::NodeData::stat_time_flooded

Total duration the node was flooded (seconds).

See also
Legacy: NodeStats[i].timeFlooded

◆ stat_time_surcharged

std::vector<double> openswmm::NodeData::stat_time_surcharged

Total time node was surcharged (seconds).

See also
Legacy: NodeStats[i].timeSurcharged

◆ stat_total_inflow_vol

std::vector<double> openswmm::NodeData::stat_total_inflow_vol

Cumulative total inflow volume at each node (ft3).

◆ stat_total_load

std::vector<double> openswmm::NodeData::stat_total_load

Cumulative pollutant loads at each node.

Flat 2D: [node * n_pollutants + p]. Only meaningful for outfall nodes. Resized by resize_loads() after pollutant count is known.

See also
Legacy: OutfallStats[k].totalLoad[p]

◆ stat_total_outflow_vol

std::vector<double> openswmm::NodeData::stat_total_outflow_vol

Cumulative total outflow volume at each node (ft3).

See also
Legacy: NodeOutflow[j]

◆ stat_vol_flooded

std::vector<double> openswmm::NodeData::stat_vol_flooded

Total volume of water lost as overflow (project volume units).

See also
Legacy: NodeStats[i].volFlooded

◆ storage_area

std::vector<double> openswmm::NodeData::storage_area

Physical junction area (ft2); zero retains legacy behavior.

◆ sur_depth

std::vector<double> openswmm::NodeData::sur_depth

Maximum depth allowed at the node (ponding or surcharge limit).

See also
Legacy: Node[i].surDepth

◆ tags

std::vector<std::string> openswmm::NodeData::tags

Per-object tag from the INP [TAGS] section.

Free-form string label, used by GUIs for filtering and grouping (e.g. catchment-name labels, asset IDs, user-defined groups). Empty string means no tag. Written back to INP by InpWriter as a Node <name> <tag> row in [TAGS]. Index-keyed (per-NodeData field) so swmm_node_rename keeps the tag attached — the earlier name-keyed SimulationContext::node_tags map lost tags on rename.

◆ type

std::vector<NodeType> openswmm::NodeData::type

Node type for each node.

◆ user_conc_mass_flux

std::vector<double> openswmm::NodeData::user_conc_mass_flux

User-forced quality mass flux at each node (mass/sec).

Flat 2D: [node * n_pollutants + pollutant]. Unlike the transient forcing in ForcingData, this persists until the user explicitly changes it and is applied as an additive mass source at each routing step (analogous to user_lat_flow for flow).

◆ user_lat_flow

std::vector<double> openswmm::NodeData::user_lat_flow

User-forced lateral inflow set via the API (project flow units).

Unlike lat_flow, this is not cleared between routing steps. The value persists until the user explicitly changes it and is added to lat_flow at each routing step.

◆ volume

std::vector<double> openswmm::NodeData::volume

Current water volume (project volume units).

See also
Legacy: Node[i].newVolume

The documentation for this struct was generated from the following file: