![]() |
OpenSWMM Engine
6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
|
Central, reentrant simulation context. More...
#include <SimulationContext.hpp>
Classes | |
| struct | ControlLogEntry |
| struct | Event |
| Event time periods for event-based analysis/reporting. More... | |
| struct | InletDiag |
| Per-inlet-usage performance block for the .rpt street tables. More... | |
| struct | MassBalance |
| struct | MassBalance2D |
| struct | MaxStats |
| Top-N element statistic entry (matching legacy TMaxStats). More... | |
| struct | NegativeSourceStats |
| D-NS1 negative-source clamp bookkeeping (subplan §3.1, X6). More... | |
| struct | OutfallExports |
| Cumulative mass balance totals for runoff and routing. More... | |
| struct | QualityOnlyInflow |
| struct | RoutingStepStats |
| struct | TwoDModelIO |
| Non-owning pointers to the engine's 2D surface-routing model storage (mesh, solver options, boundary conditions, parse-time pending rows). More... | |
| struct | VJDiag |
| Per-virtual-junction momentum-residual accumulators. More... | |
Public Member Functions | |
| void | refreshReportedSpecies () |
| Rebuild derived output columns after pre-initialization reaction edits. | |
| int | n_reported_species () const noexcept |
| Length of reported_species_names (pollutants + age when enabled). | |
| void | logControlAction (const ControlLogEntry &e) |
| Append a control action or count it as dropped at the log cap. | |
| void | finalize_max_stats () |
| Compute top-5 arrays for CFL-critical, flow turns, and non-convergence. | |
| void | reset () |
| Fully reset the context to a CREATED state. | |
| void | save_state () noexcept |
| Snapshot current state into old-step arrays before solving. | |
| void | save_lat_qual_state () noexcept |
| Roll node lateral inflows and node/link quality to their old-step arrays. | |
| void | save_hyd_state () noexcept |
| Roll node and link hydraulic values to old-step arrays. | |
| void | reset_state () noexcept |
| Reset all state variables to initial conditions (cold start). | |
| void | allocate_objects () |
| Allocate all object arrays after input parsing is complete. | |
| void | shrink_all_to_fit () |
| Release excess vector capacity on all owned SoA data stores. | |
| int | n_nodes () const noexcept |
| Number of nodes. | |
| int | n_links () const noexcept |
| Number of links. | |
| int | n_subcatches () const noexcept |
| Number of subcatchments. | |
| int | n_gages () const noexcept |
| Number of rain gages. | |
| int | n_pollutants () const noexcept |
| Number of pollutants. | |
| int | n_landuses () const noexcept |
| Count registered land-use names. | |
| int | n_tables () const noexcept |
| Number of tables (time series + curves). | |
| int | find_timeseries (std::string_view name) const noexcept |
| Find the lowest-index matching time-series table. | |
| int | find_curve (std::string_view name) const noexcept |
| Find the lowest-index matching curve table. | |
| int | find_table_any (std::string_view name) const noexcept |
| Find a named table with time-series precedence. | |
Static Public Member Functions | |
| static void | updateMaxStats (MaxStats arr[], int obj_type, int idx, double value) |
| Insert a candidate into a fixed top-five array by absolute magnitude. | |
Public Attributes | |
| EngineState | state = EngineState::CREATED |
| Current lifecycle state of the engine. | |
| std::time_t | wall_start = 0 |
| Wall-clock time stamped at the start of SWMMEngine::open(). | |
| std::vector< std::string > | title_notes |
| Project title and notes (from [TITLE] section). | |
| std::map< std::string, std::vector< std::string > > | passthrough_sections |
Sections the solver never reads, kept verbatim so a save does not delete them: [LABELS], [BACKDROP], [PROFILE]. | |
| SimulationOptions | options |
| Parsed simulation options (from [OPTIONS] section). | |
| climate::ClimateState | climate_state |
| Daily climate state — temperature, evaporation, wind, humidity. | |
| double | current_time = 0.0 |
| Current simulation time in SECONDS from start_date. | |
| double | current_date = 0.0 |
| Absolute current date/time (decimal days, OADate (days since 12/30/1899)). | |
| double | elapsed_ms = 0.0 |
| Elapsed routing time in MILLISECONDS from start_date. | |
| double | old_elapsed_ms = 0.0 |
| Elapsed routing time (ms) at the START of the current step. | |
| double | next_report_ms = 0.0 |
| Next report instant in MILLISECONDS from start_date. | |
| double | runoff_interp_f = 1.0 |
| Where this routing instant falls between the two runoff times. | |
| double | dt_controls_remaining = 0.0 |
| Time remaining until the next control rule event (seconds). | |
| NodeData | nodes |
| All node state and properties. | |
| NodeSubtypes | node_subtypes |
| Relational side-tables for node subtypes (storage/outfall/divider). | |
| LinkData | links |
| All link state and properties. | |
| LinkSubtypes | link_subtypes |
Relational per-subtype link side-tables (Phase 6) — the link analogue of node_subtypes. Authoritative store for conduit/pump/ orifice/weir/outlet config; shared fields (xsect_*, has_flap_gate, pump_curve_name) stay on links. | |
| SubcatchData | subcatches |
| All subcatchment state and properties. | |
| GageData | gages |
| All rain gage state and properties. | |
| PollutantData | pollutants |
| Pollutant definitions and per-object quality state. | |
| SpeciesRegistry | species_registry |
| Species registry — the single source of truth for transported constituents (master plan §4.1, phase T0a). Pollutants occupy the first slots (index-aligned with the legacy pollutant index); MSX species append via the reactions component (R1); reserved age/temperature species append with phases A1/H1. Rebuilt at each open(). | |
| ReactionData | reactions |
| Multispecies reaction system (EPANET-MSX conventions), parsed from the reactions component's config file or embedded [REACTION_*] sections (phase R1). Compiled bytecode arrives with phase R2. | |
| ArdConfigData | ard_config |
Eulerian ARD transport component configuration, parsed from the model.ard config file registered via [PROCESS_COMPONENTS] (phase E3: the dispersion subset — global mode + per-conduit overrides). | |
| WaterAgeConfigData | water_age_config |
Water-age tracking (phase A1a): per-source initial ages parsed from the waterage component (model.age) + the runtime age state the engines and loaders share. | |
| WaterAgeState | water_age_state |
| LidLayerSpeciesState | lid_layer_state |
| A4: per-(LID unit, layer, species) transported state. | |
| HeatConfigData | heat_config |
Heat transport (phase H1): per-source inlet temperatures parsed from the heat component (model.heat) + the runtime temperature state the engines and loaders share. | |
| HeatState | heat_state |
| BedZoneState | bed_state |
| The bed / hyporheic transient-storage zone (phase H6b). | |
| std::vector< std::string > | reported_species_names |
Species names as REPORTED (phase A2b): the pollutant names, then __WATER_AGE__ when [OPTIONS] WATER_AGE is on. | |
| TableData | tables |
| All time series and rating curves. | |
| NameIndex | node_names |
| Node name → node index. | |
| NameIndex | link_names |
| Link name → link index. | |
| NameIndex | subcatch_names |
| Subcatchment name → subcatchment index. | |
| NameIndex | gage_names |
| Rain gage name → gage index. | |
| NameIndex | pollutant_names |
| Pollutant name → pollutant index. | |
| NameIndex | landuse_names |
| LanduseData | landuses |
| BuildupData | buildup |
| WashoffData | washoff |
| TreatmentData | treatment |
| InitialQualityData | initial_quality |
| Per-element initial quality rows from [INITIAL_QUALITY]. | |
| ExtInflowData | ext_inflows |
| DwfData | dwf_inflows |
| RDIIAssignData | rdii_assigns |
| UnitHydData | unit_hyds |
| Parsed [HYDROGRAPHS] data. | |
| RDIIDecayData | rdii_decay |
| Parsed [RDII_DECAY] data (exponential IA model) | |
| PatternData | patterns |
| TransectStore | transects |
| std::vector< transect::TransectData > | transect_tables |
| Built transect geometry tables (indexed same as transects). | |
| std::uint64_t | xsect_generation = 0 |
| bool | gpkg_units_internal = false |
| StreetStore | streets |
| InletStore | inlets |
| InletUsageStore | inlet_usages |
| ControlRuleStore | control_rules |
| std::vector< Event > | events |
| double | adjust_temp [12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} |
| Monthly climate adjustment factors from [ADJUSTMENTS] section. | |
| double | adjust_evap [12] |
| [ADJUSTMENTS] EVAP: ADDED to the evaporation rate (in/day or mm/day), legacy Adjust.evap | |
| double | adjust_rain [12] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} |
| double | adjust_hydcon [12] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} |
| std::vector< int > | subcatch_n_perv_pattern |
| Per-subcatchment pattern indices for N-PERV, DSTORE, INFIL adjustments. | |
| std::vector< int > | subcatch_d_store_pattern |
| std::vector< int > | subcatch_infil_pattern |
| std::vector< double > | base_n_perv |
| Base values for pattern-adjusted parameters (populated at init). | |
| std::vector< double > | base_ds_perv |
| bool | has_subcatch_adj_patterns = false |
| True if any pattern index >= 0. | |
| SnowpackStore | snowpacks |
| NameIndex | snowpack_names |
| AquiferStore | aquifers |
| NameIndex | aquifer_names |
| LidControlStore | lid_controls |
| std::vector< LidNodeOutlet > | lid_node_outlets |
| NameIndex | lid_names |
| LidUsageStore | lid_usage |
| std::vector< std::pair< int, std::string > > | pending_gw_nodes |
| std::vector< std::pair< int, std::string > > | pending_gw_aquifers |
| std::vector< std::pair< int, std::pair< std::string, std::string > > > | pending_link_nodes |
| SpatialFrame | spatial |
| Coordinate reference system and georeferenced coordinates. | |
| UserFlags | user_flags |
| User-defined flags from [USER_FLAGS] section. | |
| ForcingData | forcing |
| Per-element runtime forcing state (lateral inflows, head boundaries, rainfall, evap, link settings, quality mass fluxes). | |
| std::vector< PluginSpec > | plugin_specs |
| Plugin library specs parsed from [PLUGINS]. | |
| std::vector< ProcessComponentSpec > | process_component_specs |
| Process-component registrations parsed from [PROCESS_COMPONENTS]. | |
| std::vector< std::pair< std::string, std::vector< std::string > > > | embedded_component_sections |
| Embedded component sections found in the legacy .inp ([REACTION_*] today; other component families as they land) — the D-UT8 embedded-fallback path. (tag, lines) pairs in file order; consumed after component resolution with a style warning, or reported ignored when the external file wins. | |
| FilesSpec | files |
| Secondary file references parsed from [FILES]. | |
| StateAccessors | state_accessors |
| Solver-neutral accessors for reading and writing solver-internal state at hot-start save/load time. | |
| struct openswmm::SimulationContext::TwoDModelIO | twod_io |
| std::vector< std::pair< std::string, std::string > > | deferred_section_rows |
| Section rows whose target object had not been parsed yet. | |
| std::vector< std::pair< std::string, long > > | unknown_section_headers |
| Every unknown section header read, as (token as written, 1-based line number), in file order — legacy's "Unknown section '%s' at
line %ld" warning names both. | |
| int | error_code = 0 |
| Most recent error code (0 = no error). | |
| int | warning_code = 0 |
| Most recent warning code (0 = no warning). | |
| std::string | error_message |
| Human-readable message for the last error/warning. | |
| std::vector< std::string > | warnings |
| Accumulated warning messages written to report file. | |
| std::vector< std::string > | errors |
| Accumulated error messages written to report file. | |
| NodeCoupling2DRows | node_coupling_2d |
| [2D_NODE_COUPLING] rows: per-node coupling structure type and its authored parameters (model data, kept with or without a mesh). | |
| std::vector< std::uint8_t > | coupled_node |
| Per-node flag: 1 if the node is a 2D-coupled junction (a non-outfall coupling point), else 0. Empty when the 2D module is inactive. | |
| std::vector< double > | coupled_pond_area |
| Above-rim pond of each 2D-coupled junction under dynamic wave (2D_OPTIONS COUPLING_POND_MODE / COUPLING_RIM_BAND). | |
| std::vector< double > | coupled_pond_band |
| double | coupling_delivery_remaining = 0.0 |
| Remaining seconds of the current 1D↔2D coupling delivery window. | |
| struct openswmm::SimulationContext::OutfallExports | outfall_exports |
| struct openswmm::SimulationContext::MassBalance | mass_balance |
| struct openswmm::SimulationContext::NegativeSourceStats | negsrc |
| std::vector< double > | surface_outfall_link_limit |
| System mass-balance totals for the optional 2D surface domain. | |
| QualityOnlyInflow | surface_outfall_quality |
| D2: booked as external inflow. | |
| QualityOnlyInflow | link_gain_quality |
| gaining conduits: groundwater inflow | |
| bool | runtime_coupling_used = false |
| Runtime prescriptions require a future restart format. | |
| struct openswmm::SimulationContext::MassBalance2D | mass_balance_2d |
| MaxStats | max_courant_crit [MAX_STATS] = {} |
| Top-5 CFL time-step critical elements. | |
| MaxStats | max_flow_turns [MAX_STATS] = {} |
| Top-5 links with highest flow instability index. | |
| MaxStats | max_non_converged [MAX_STATS] = {} |
| Top-5 nodes with highest non-convergence frequency. | |
| MaxStats | max_mass_bal_errs [MAX_STATS] = {} |
| Top-5 nodes with highest continuity errors. | |
| struct openswmm::SimulationContext::RoutingStepStats | routing_stats |
| struct openswmm::SimulationContext::VJDiag | vj_diag |
| struct openswmm::SimulationContext::InletDiag | inlet_diag |
| std::vector< ControlLogEntry > | control_log |
| std::vector< std::string > | control_rule_names |
| Rule names by rule index, interned by ControlEngine as actions are logged. | |
| std::size_t | control_log_dropped = 0 |
| Actions NOT logged because the cap was reached; the report says so once. | |
| std::string | inp_file_path |
| Path to the input .inp file (empty if not opened from a file). | |
Static Public Attributes | |
| static constexpr int | MAX_STATS = 5 |
| static constexpr std::size_t | kMaxControlLog = 1'000'000 |
Central, reentrant simulation context.
Owns all simulation data. Passed by (non-const) reference to every solver function. One context per concurrent simulation.
|
inline |
Allocate all object arrays after input parsing is complete.
Called by InputReader after all [JUNCTIONS], [CONDUITS], etc. sections have been parsed and the final object counts are known. Resizes SoA arrays and pollutant quality matrices.
|
inline |
Compute top-5 arrays for CFL-critical, flow turns, and non-convergence.
Called once at end of simulation before reporting (matching legacy stats_findMaxStats in stats.c).
|
inlinenoexcept |
Find the lowest-index matching curve table.
Uses the TableData name index; caller keeps it synchronized after edits.
| [in] | name | Borrowed case-insensitive table name. |
|
inlinenoexcept |
Find a named table with time-series precedence.
For callers without kind context; a same-named time series wins regardless of curve row order. Caller keeps TableData indexes coherent.
| [in] | name | Borrowed case-insensitive table name. |
|
inlinenoexcept |
Find the lowest-index matching time-series table.
Uses the TableData name index; caller keeps that index synchronized after edits.
| [in] | name | Borrowed case-insensitive table name, looked up without copying. |
|
inline |
Append a control action or count it as dropped at the log cap.
At one million stored entries, only increments control_log_dropped. Otherwise push_back may allocate and throw. Does not write reports or alter the referenced link setting.
| [in] | e | Entry copied into owned storage. Caller supplies valid link/rule indices, target setting and OADate; this helper does not validate them. |
|
inlinenoexcept |
Number of rain gages.
|
inlinenoexcept |
Count registered land-use names.
|
inlinenoexcept |
Number of links.
|
inlinenoexcept |
Number of nodes.
|
inlinenoexcept |
Number of pollutants.
|
inlinenoexcept |
Length of reported_species_names (pollutants + age when enabled).
|
inlinenoexcept |
Number of subcatchments.
|
inlinenoexcept |
Number of tables (time series + curves).
|
inline |
Rebuild derived output columns after pre-initialization reaction edits.
|
inline |
Fully reset the context to a CREATED state.
Clears all object data and name indices. Does NOT free the option structs (they are re-parsed from the input file). Call this before re-running or re-opening a simulation.
|
inlinenoexcept |
Reset all state variables to initial conditions (cold start).
Sets all current and old-step arrays to zero. Invert elevations and static properties are NOT changed.
|
inlinenoexcept |
Roll node and link hydraulic values to old-step arrays.
Called only for an actually routed step; skip when steady routing is bypassed so old hydraulic values are preserved. Does not roll quality/lateral inflow or subcatchment runoff.
|
inlinenoexcept |
Roll node lateral inflows and node/link quality to their old-step arrays.
Called every routing step, including skipped steady-state steps, before inflow/quality assembly. Does not snapshot hydraulic or subcatchment runoff state; owned data arrays must already be allocated/aligned.
|
inlinenoexcept |
Snapshot current state into old-step arrays before solving.
Must be called at the start of each timestep, before the hydraulic and quality solvers update the state.
|
inline |
Release excess vector capacity on all owned SoA data stores.
Called once after parsing and final sizing are complete. During incremental parsing, vectors grow via geometric capacity doubling. This method reclaims that excess by calling shrink_to_fit() on every data store.
|
inlinestatic |
Insert a candidate into a fixed top-five array by absolute magnitude.
Strict greater-than comparison keeps existing ties first; drops the final displaced candidate. NaN magnitudes do not insert. No allocation or model access.
| [in,out] | arr | Non-null array of at least MAX_STATS entries already ordered by descending absolute value. |
| [in] | obj_type | Object category carried unchanged into an inserted entry (normally 0 node or 1 link). |
| [in] | idx | Object index carried unchanged; no model-range validation. |
| [in] | value | Candidate statistic in the same units as existing values. |
| double openswmm::SimulationContext::adjust_evap[12] |
[ADJUSTMENTS] EVAP: ADDED to the evaporation rate (in/day or mm/day), legacy Adjust.evap
| double openswmm::SimulationContext::adjust_hydcon[12] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} |
| double openswmm::SimulationContext::adjust_rain[12] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} |
| double openswmm::SimulationContext::adjust_temp[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} |
Monthly climate adjustment factors from [ADJUSTMENTS] section.
Copied into ClimateState during initialize(). Stored here so that input parsing populates them without accessing SWMMEngine.
| NameIndex openswmm::SimulationContext::aquifer_names |
| AquiferStore openswmm::SimulationContext::aquifers |
| ArdConfigData openswmm::SimulationContext::ard_config |
Eulerian ARD transport component configuration, parsed from the model.ard config file registered via [PROCESS_COMPONENTS] (phase E3: the dispersion subset — global mode + per-conduit overrides).
| std::vector<double> openswmm::SimulationContext::base_ds_perv |
| std::vector<double> openswmm::SimulationContext::base_n_perv |
Base values for pattern-adjusted parameters (populated at init).
| BedZoneState openswmm::SimulationContext::bed_state |
The bed / hyporheic transient-storage zone (phase H6b).
One entry per LINK, carrying a temperature and a per-species concentration. It sits beside heat_state rather than inside it because it holds solute state too — the reference's HTS zone is a transient-storage zone for tracers as much as a thermal mass. Empty and untouched unless [HEAT_FLUXES] SEDIMENT_EXCHANGE is on.
| BuildupData openswmm::SimulationContext::buildup |
| climate::ClimateState openswmm::SimulationContext::climate_state |
Daily climate state — temperature, evaporation, wind, humidity.
Scalar broadcast to all subcatchments; updated at the runoff step boundary by SWMMEngine. Lives on the context so that downstream solvers (RDII exponential IA, future models) can read it through ctx.climate_state without reaching into the engine.
| std::vector<ControlLogEntry> openswmm::SimulationContext::control_log |
Chronological log of the control actions taken during the simulation, capped at kMaxControlLog entries (see logControlAction).
| std::size_t openswmm::SimulationContext::control_log_dropped = 0 |
Actions NOT logged because the cap was reached; the report says so once.
| std::vector<std::string> openswmm::SimulationContext::control_rule_names |
Rule names by rule index, interned by ControlEngine as actions are logged.
| ControlRuleStore openswmm::SimulationContext::control_rules |
| std::vector<std::uint8_t> openswmm::SimulationContext::coupled_node |
Per-node flag: 1 if the node is a 2D-coupled junction (a non-outfall coupling point), else 0. Empty when the 2D module is inactive.
Populated by SurfaceRouter2D::initialize from the coupling map. Lets the 1D dynamic-wave solver treat a coupled junction as pond-capable so its HGL can rise above the crown over the auto-assigned ponded_area (the 2D-cell footprint), regardless of the global ALLOW_PONDING option — which only governs ordinary (uncoupled) junctions. Outfall coupling uses a tailwater head BC instead, so outfalls are NOT flagged here.
| std::vector<double> openswmm::SimulationContext::coupled_pond_area |
Above-rim pond of each 2D-coupled junction under dynamic wave (2D_OPTIONS COUPLING_POND_MODE / COUPLING_RIM_BAND).
Set by SurfaceRouter2D::initialize; EMPTY reproduces the legacy step onto ponded_area. coupled_pond_area (1D ft²) is the pond area A_eq — runtime state under TRACKING, which relaxes it each routing step; coupled_pond_band (ft) is the height above the rim over which the area ramps in (2d/coupling/PondModel.hpp).
| std::vector<double> openswmm::SimulationContext::coupled_pond_band |
| double openswmm::SimulationContext::coupling_delivery_remaining = 0.0 |
Remaining seconds of the current 1D↔2D coupling delivery window.
Set by SurfaceRouter2D::fireAdvanceWindow to the length of the 2D advance window whose junction-exchange volumes it just moved into NodeData::coupling_queue. assembleLateralInflows drains the queue at the uniform rate queue/remaining, counts this down once per routing step, and flushes the whole remainder on the step where remaining ≤ dt — so the 1D node receives exactly the exchanged volume spread over the window instead of as a single-step pulse. 0 (the cold-start default, and the steady state when the 2D advance fires every routing step) reproduces the legacy one-step delivery exactly.
| double openswmm::SimulationContext::current_date = 0.0 |
Absolute current date/time (decimal days, OADate (days since 12/30/1899)).
= options.start_date + current_time
| double openswmm::SimulationContext::current_time = 0.0 |
Current simulation time in SECONDS from start_date.
Updated by TimestepController::advance() with the routing step in seconds (TimestepController.cpp:88). The value 0.0 corresponds to options.start_date.
The companion field current_date is the OADate (decimal days since 12/30/1899) computed via datetime::addSeconds(start_date, current_time).
Callers that need elapsed time in decimal days (e.g. the control engine's SIM_TIME premise) must divide by constants::SEC_PER_DAY. Legacy ElapsedTime is in days; this field stores seconds.
| std::vector<std::pair<std::string, std::string> > openswmm::SimulationContext::deferred_section_rows |
Section rows whose target object had not been parsed yet.
Sections are dispatched in the order they appear in the file, so a property section that names an object defined further down (e.g. an [XSECTIONS] row for a link declared in a later [ORIFICES]) cannot resolve its name on the first pass. Legacy SWMM avoids this with an ID pre-pass; here a handler stashes the unresolved row as (section tag, raw line) and InputReader re-dispatches it once every section has been read. Rows still unresolved after that replay name an object that does not exist and raise ERROR 209, as legacy does.
Parse-time scratch only — empty once reading finishes.
| double openswmm::SimulationContext::dt_controls_remaining = 0.0 |
Time remaining until the next control rule event (seconds).
0.0 means no control step scheduled; updated by the control rule processor.
| DwfData openswmm::SimulationContext::dwf_inflows |
| double openswmm::SimulationContext::elapsed_ms = 0.0 |
Elapsed routing time in MILLISECONDS from start_date.
Legacy-parity clock: accumulated exactly as legacy NewRoutingTime = NewRoutingTime + 1000.0 * routingStep (swmm5.c / routing.c:309). Kept alongside current_time (seconds) because the two accumulations are NOT FP-identical; report scheduling and report datestamps must use this clock to match legacy bit-for-bit.
| std::vector<std::pair<std::string, std::vector<std::string> > > openswmm::SimulationContext::embedded_component_sections |
Embedded component sections found in the legacy .inp ([REACTION_*] today; other component families as they land) — the D-UT8 embedded-fallback path. (tag, lines) pairs in file order; consumed after component resolution with a style warning, or reported ignored when the external file wins.
| int openswmm::SimulationContext::error_code = 0 |
| std::string openswmm::SimulationContext::error_message |
Human-readable message for the last error/warning.
| std::vector<std::string> openswmm::SimulationContext::errors |
Accumulated error messages written to report file.
Matches legacy behavior where errors are collected during parsing/validation and written to the .rpt file. Format: "ERROR NNN: description for ObjectID"
| std::vector<Event> openswmm::SimulationContext::events |
| ExtInflowData openswmm::SimulationContext::ext_inflows |
| FilesSpec openswmm::SimulationContext::files |
Secondary file references parsed from [FILES].
Mirrors legacy SWMM5's TFile struct array — rainfall, runoff, RDII, inflows, outflows, hotstart save/use. The simulation engine consults specific slots when the corresponding feature is requested (e.g. interfacing a routing run with a separately-saved runoff file).
| ForcingData openswmm::SimulationContext::forcing |
Per-element runtime forcing state (lateral inflows, head boundaries, rainfall, evap, link settings, quality mass fluxes).
Set via swmm_forcing_*() API. Applied by applyForcings() in the step loop. Auto-cleared by clear_reset_entries() at end of each step (for RESET-persistence entries).
| NameIndex openswmm::SimulationContext::gage_names |
Rain gage name → gage index.
| GageData openswmm::SimulationContext::gages |
| bool openswmm::SimulationContext::gpkg_units_internal = false |
True when the model was loaded from a GeoPackage, whose hydraulic fields are stored in CANONICAL internal units (feet/cfs/ft³) — NOT the display units a .inp uses. resolve_cross_references then SKIPS the display→ internal conversion (convert_inputs_to_internal) so the round-trip is bit-for-bit identical (no non-invertible ×0.3048). The GeoPackage reader converts only the cross-section raw geom1-4 (the lone display-unit fields it stores) itself. Left false for the .inp path.
| bool openswmm::SimulationContext::has_subcatch_adj_patterns = false |
True if any pattern index >= 0.
| HeatConfigData openswmm::SimulationContext::heat_config |
Heat transport (phase H1): per-source inlet temperatures parsed from the heat component (model.heat) + the runtime temperature state the engines and loaders share.
| HeatState openswmm::SimulationContext::heat_state |
| InitialQualityData openswmm::SimulationContext::initial_quality |
Per-element initial quality rows from [INITIAL_QUALITY].
Pollutant + reserved-species (WATER_AGE/__TEMPERATURE__) per-node/per-link initial values overriding the global [POLLUTANTS] Cinit / sidecar INITIAL_STATE seeds. Names are resolved and constituents classified in PostParseResolver.
| struct openswmm::SimulationContext::InletDiag openswmm::SimulationContext::inlet_diag |
| InletUsageStore openswmm::SimulationContext::inlet_usages |
| InletStore openswmm::SimulationContext::inlets |
| std::string openswmm::SimulationContext::inp_file_path |
Path to the input .inp file (empty if not opened from a file).
|
staticconstexpr |
| NameIndex openswmm::SimulationContext::landuse_names |
| LanduseData openswmm::SimulationContext::landuses |
| LidControlStore openswmm::SimulationContext::lid_controls |
| LidLayerSpeciesState openswmm::SimulationContext::lid_layer_state |
A4: per-(LID unit, layer, species) transported state.
| NameIndex openswmm::SimulationContext::lid_names |
| std::vector<LidNodeOutlet> openswmm::SimulationContext::lid_node_outlets |
| LidUsageStore openswmm::SimulationContext::lid_usage |
| QualityOnlyInflow openswmm::SimulationContext::link_gain_quality |
gaining conduits: groundwater inflow
| NameIndex openswmm::SimulationContext::link_names |
Link name → link index.
| LinkSubtypes openswmm::SimulationContext::link_subtypes |
Relational per-subtype link side-tables (Phase 6) — the link analogue of node_subtypes. Authoritative store for conduit/pump/ orifice/weir/outlet config; shared fields (xsect_*, has_flap_gate, pump_curve_name) stay on links.
| LinkData openswmm::SimulationContext::links |
| struct openswmm::SimulationContext::MassBalance openswmm::SimulationContext::mass_balance |
| struct openswmm::SimulationContext::MassBalance2D openswmm::SimulationContext::mass_balance_2d |
Top-5 CFL time-step critical elements.
Top-5 links with highest flow instability index.
Top-5 nodes with highest continuity errors.
Top-5 nodes with highest non-convergence frequency.
|
staticconstexpr |
| struct openswmm::SimulationContext::NegativeSourceStats openswmm::SimulationContext::negsrc |
| double openswmm::SimulationContext::next_report_ms = 0.0 |
Next report instant in MILLISECONDS from start_date.
Legacy ReportTime: seeded to 1000*report_step at start and advanced by 1000*report_step per period (swmm5.c:721,1044). The grid is anchored at SIM start; periods whose datestamp falls before options.report_start are skipped (not written) but the grid still advances — exactly legacy output_saveResults() (output.c:481).
| NodeCoupling2DRows openswmm::SimulationContext::node_coupling_2d |
[2D_NODE_COUPLING] rows: per-node coupling structure type and its authored parameters (model data, kept with or without a mesh).
Nodes without a row take their class default (core/NodeCoupling2D.hpp). Keyed by node index; delete_node drops and renumbers.
| NameIndex openswmm::SimulationContext::node_names |
Node name → node index.
| NodeSubtypes openswmm::SimulationContext::node_subtypes |
Relational side-tables for node subtypes (storage/outfall/divider).
Phase 1 (shadow) of the relational node refactor: built from nodes at hydraulics init and kept as an exact mirror of the wide subtype arrays. Not yet read by the solver. See docs/relational/RELATIONAL_NODE_REFACTOR_PLAN.md and src/engine/data/NodeSubtypes.hpp.
| NodeData openswmm::SimulationContext::nodes |
| double openswmm::SimulationContext::old_elapsed_ms = 0.0 |
Elapsed routing time (ms) at the START of the current step.
Legacy OldRoutingTime; with elapsed_ms brackets the report instant for interpolated output.
| SimulationOptions openswmm::SimulationContext::options |
Parsed simulation options (from [OPTIONS] section).
| struct openswmm::SimulationContext::OutfallExports openswmm::SimulationContext::outfall_exports |
| std::map<std::string, std::vector<std::string> > openswmm::SimulationContext::passthrough_sections |
Sections the solver never reads, kept verbatim so a save does not delete them: [LABELS], [BACKDROP], [PROFILE].
Keyed by section tag, holding the data lines exactly as they were read (comments and blank lines already stripped by the reader). Legacy SWMM has no case for any of them in parseLine, so their content is whatever the authoring GUI chose to put there and no engine can validate it — which is precisely why replaying it byte-for-byte is both the safest and the most faithful thing to do.
These were registered as no-op handlers, so a model's map labels and backdrop image vanished on the first Open → Save.
| PatternData openswmm::SimulationContext::patterns |
| std::vector<std::pair<int, std::string> > openswmm::SimulationContext::pending_gw_aquifers |
[GROUNDWATER] aquifer names (subcatch index -> aquifer name) not yet defined when the row was read, for [AQUIFERS] placed further down.
| std::vector<std::pair<int, std::string> > openswmm::SimulationContext::pending_gw_nodes |
[GROUNDWATER] receiving-node names (subcatch index -> node name). [GROUNDWATER] normally precedes [JUNCTIONS] in EPA SWMM output.
| std::vector<std::pair<int, std::pair<std::string, std::string> > > openswmm::SimulationContext::pending_link_nodes |
Link end-node names (link index -> {from-node name, to-node name}). Legacy parsing is order-independent, so [CONDUITS] may precede the node sections; without this the link loads silently orphaned (node1/node2 -1).
| std::vector<PluginSpec> openswmm::SimulationContext::plugin_specs |
Plugin library specs parsed from [PLUGINS].
Consumed by PluginFactory::load_plugins() during open(). New in 6.0.0 — no legacy equivalent.
| NameIndex openswmm::SimulationContext::pollutant_names |
Pollutant name → pollutant index.
| PollutantData openswmm::SimulationContext::pollutants |
| std::vector<ProcessComponentSpec> openswmm::SimulationContext::process_component_specs |
Process-component registrations parsed from [PROCESS_COMPONENTS].
Resolved against the ProcessComponentRegistry during open() (after the input read, mirroring the external 2D mesh file); each resolved component's config file is parsed and delivered to its apply hook. Unified Transport suite D-UT8.
| RDIIAssignData openswmm::SimulationContext::rdii_assigns |
| RDIIDecayData openswmm::SimulationContext::rdii_decay |
Parsed [RDII_DECAY] data (exponential IA model)
| ReactionData openswmm::SimulationContext::reactions |
Multispecies reaction system (EPANET-MSX conventions), parsed from the reactions component's config file or embedded [REACTION_*] sections (phase R1). Compiled bytecode arrives with phase R2.
| std::vector<std::string> openswmm::SimulationContext::reported_species_names |
Species names as REPORTED (phase A2b): the pollutant names, then __WATER_AGE__ when [OPTIONS] WATER_AGE is on.
The .out format has exactly one per-species column block, so age reports as a trailing pseudo-pollutant column. This vector is the single naming truth the output writers and the snapshot's pollut_names pointer share — built once at open so the pointer stays valid for the run. n_reported_species() is its length and is what the writers must stride by; plain n_pollutants() remains the TRANSPORT stride for nodes.conc etc. Keeping the two counts distinct and named is deliberate: conflating them is the stride-slip family (roadmap lessons 14/15).
| struct openswmm::SimulationContext::RoutingStepStats openswmm::SimulationContext::routing_stats |
| double openswmm::SimulationContext::runoff_interp_f = 1.0 |
Where this routing instant falls between the two runoff times.
Legacy's f = (routingTime - OldRunoffTime) / (NewRunoffTime - OldRunoffTime), clamped to [0,1] (routing.c:707). It weights EVERY subcatchment quantity handed to a node this step — the runoff flow in addWetWeatherInflows, and the washoff load right beside it in surfqual_getWtdWashoff. SWMMEngine::assembleLateralInflows forms it and publishes it here so the quality loaders use the same number rather than assuming a midpoint.
| bool openswmm::SimulationContext::runtime_coupling_used = false |
Runtime prescriptions require a future restart format.
| NameIndex openswmm::SimulationContext::snowpack_names |
| SnowpackStore openswmm::SimulationContext::snowpacks |
| SpatialFrame openswmm::SimulationContext::spatial |
Coordinate reference system and georeferenced coordinates.
| SpeciesRegistry openswmm::SimulationContext::species_registry |
Species registry — the single source of truth for transported constituents (master plan §4.1, phase T0a). Pollutants occupy the first slots (index-aligned with the legacy pollutant index); MSX species append via the reactions component (R1); reserved age/temperature species append with phases A1/H1. Rebuilt at each open().
| EngineState openswmm::SimulationContext::state = EngineState::CREATED |
Current lifecycle state of the engine.
| StateAccessors openswmm::SimulationContext::state_accessors |
Solver-neutral accessors for reading and writing solver-internal state at hot-start save/load time.
Wired by SWMMEngine at open() time so state-IO plugins can access per-subcatchment infiltration and groundwater state without depending on solver types.
| StreetStore openswmm::SimulationContext::streets |
| std::vector<int> openswmm::SimulationContext::subcatch_d_store_pattern |
| std::vector<int> openswmm::SimulationContext::subcatch_infil_pattern |
| std::vector<int> openswmm::SimulationContext::subcatch_n_perv_pattern |
Per-subcatchment pattern indices for N-PERV, DSTORE, INFIL adjustments.
Index into ctx.tables / pattern tables. -1 = no pattern.
| NameIndex openswmm::SimulationContext::subcatch_names |
Subcatchment name → subcatchment index.
| SubcatchData openswmm::SimulationContext::subcatches |
All subcatchment state and properties.
| std::vector<double> openswmm::SimulationContext::surface_outfall_link_limit |
System mass-balance totals for the optional 2D surface domain.
Accumulated each executed 2D step by SurfaceRouter2D. Unlike the 1D MassBalance (ft³ for US flow units), all volumes here are in the 2D solver's SI internal units (m³). This is a SEPARATE balance from the 1D routing balance: the coupling terms are inflows/outflows of the 2D domain, signed oppositely to the 1D routing_external/routing_flooding terms.
| QualityOnlyInflow openswmm::SimulationContext::surface_outfall_quality |
D2: booked as external inflow.
| TableData openswmm::SimulationContext::tables |
| std::vector<std::string> openswmm::SimulationContext::title_notes |
| std::vector<transect::TransectData> openswmm::SimulationContext::transect_tables |
Built transect geometry tables (indexed same as transects).
| TransectStore openswmm::SimulationContext::transects |
| TreatmentData openswmm::SimulationContext::treatment |
| struct openswmm::SimulationContext::TwoDModelIO openswmm::SimulationContext::twod_io |
| UnitHydData openswmm::SimulationContext::unit_hyds |
Parsed [HYDROGRAPHS] data.
| std::vector<std::pair<std::string, long> > openswmm::SimulationContext::unknown_section_headers |
Every unknown section header read, as (token as written, 1-based line number), in file order — legacy's "Unknown section '%s' at line %ld" warning names both.
| UserFlags openswmm::SimulationContext::user_flags |
User-defined flags from [USER_FLAGS] section.
New in 6.0.0. No legacy equivalent.
| struct openswmm::SimulationContext::VJDiag openswmm::SimulationContext::vj_diag |
| std::time_t openswmm::SimulationContext::wall_start = 0 |
Wall-clock time stamped at the start of SWMMEngine::open().
Reported as "Analysis begun on:" and used as the origin for "Total elapsed time:" in the .rpt. Stamped before input parsing so that parse + cross-reference resolution + validation + module initialization are all included in the reported elapsed time. This matches legacy, which takes its timestamp in report_writeLogo() before project_readInput() (see legacy/engine/report.c). Zero until open() runs.
| int openswmm::SimulationContext::warning_code = 0 |
Most recent warning code (0 = no warning).
| std::vector<std::string> openswmm::SimulationContext::warnings |
Accumulated warning messages written to report file.
Matches legacy behavior where warnings are collected during validation and written after the title section in the .rpt file. Format: "WARNING NN: description for ObjectID"
| WashoffData openswmm::SimulationContext::washoff |
| WaterAgeConfigData openswmm::SimulationContext::water_age_config |
Water-age tracking (phase A1a): per-source initial ages parsed from the waterage component (model.age) + the runtime age state the engines and loaders share.
| WaterAgeState openswmm::SimulationContext::water_age_state |
| std::uint64_t openswmm::SimulationContext::xsect_generation = 0 |
Bumped whenever a link's cross-section/flow properties are recomputed mid-run (C-API setters via recompute_conduit_flow_properties), so consumers holding per-link XSectParams caches know to rebuild (e.g. SWMMEngine's reporting-path cache).