![]() |
OpenSWMM Engine
6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
|
Structure-of-Arrays storage for all subcatchments. More...
#include <SubcatchData.hpp>
Public Member Functions | |
| void | resize_total_load (int n_sc, int n_poll) |
| Replace cumulative subcatchment pollutant-load storage. | |
| void | resize_coverage (int n_sc, int n_lu) |
| Resize the coverage and sweep matrices. | |
| int | count () const noexcept |
| Count subcatchment rows from the area column. | |
| void | resize (int n) |
| Replace the base subcatchment store with a requested row count. | |
| void | grow_to (int n) |
| Extend base subcatchment columns while preserving existing prefixes. | |
| void | reserve_to (int n) |
Reserve capacity for n subcatchments without changing count(). | |
| void | erase_at (int idx) |
| Erase one subcatchment row from the columns visited by this helper. | |
| void | resize_quality (int n_pollutants) |
| Set the pollutant stride and replace positive-sized quality arrays. | |
| void | resize_washoff_load (int n_pollutants) |
| Zero the washoff-load matrix for a positive pollutant count. | |
| void | shrink_to_fit () |
| Release excess vector capacity accumulated during parsing. | |
| void | save_state () noexcept |
| Snapshot runoff-step discharge, run-on, concentration and ponded depth. | |
| void | reset_state () noexcept |
| Clear the subcatchment dynamic arrays visited here. | |
Public Attributes | |
| std::vector< int > | outlet_node |
| Index of the drain-to node or subcatchment. | |
| std::vector< int > | outlet_subcatch |
| Index of the subcatch that receives overflow (-1 if none). | |
| std::vector< std::string > | outlet_name |
| Outlet name string for deferred resolution. | |
| std::vector< std::string > | snowpack_name |
| Snow pack name string for deferred resolution. | |
| std::vector< std::string > | gage_name |
| Rain gage name string for deferred resolution. | |
| std::vector< int > | gage |
| Rain gage index for this subcatchment. | |
| std::vector< double > | area |
| Subcatchment area (project area units). | |
| std::vector< double > | width |
| Width of overland flow path (project length units). | |
| std::vector< double > | slope |
| Average slope of catchment (fraction). | |
| std::vector< double > | curb_length |
| Total curb length (project length units). | |
| std::vector< double > | rain_scale_factor |
| Subcatchment-level rainfall scale factor (default 1.0 = no scaling). | |
| std::vector< double > | snow_scale_factor |
| Subcatchment-level snowfall scale factor (default 1.0 = no scaling). | |
| std::vector< double > | frac_imperv |
| Fraction of area that is impervious (0–1). | |
| std::vector< double > | frac_imperv_no_store |
| Fraction of impervious area with no depression storage (0–1). | |
| std::vector< double > | pct_zero |
| The AUTHORED [SUBAREAS] PctZero column, in percent. | |
| std::vector< double > | n_imperv |
| Manning's n for impervious area. | |
| std::vector< double > | n_perv |
| Manning's n for pervious area. | |
| std::vector< double > | ds_imperv |
| Depression storage depth for impervious area (project length units). | |
| std::vector< double > | ds_perv |
| Depression storage depth for pervious area (project length units). | |
| std::vector< int > | subarea_routing |
| Inter-subarea routing mode. | |
| std::vector< double > | pct_routed |
| Fraction of runoff routed between subareas (0–1). | |
| std::vector< int > | infil_model |
| Infiltration model: 0=HORTON, 1=MOD_HORTON, 2=GREEN_AMPT, 3=MOD_GREEN_AMPT, 4=CURVE_NUMBER. | |
| std::vector< double > | infil_p1 |
| Infiltration param 1: f0 (Horton), suction (GA), CN (CN). | |
| std::vector< double > | infil_p2 |
| Infiltration param 2: fmin (Horton), conductivity (GA), unused (CN). | |
| std::vector< double > | infil_p3 |
| Infiltration param 3: decay (Horton), initial deficit (GA), drying time (CN). | |
| std::vector< double > | infil_p4 |
| Infiltration param 4: dry time (Horton), 0 (GA/CN). | |
| std::vector< double > | infil_p5 |
| Infiltration param 5: max infil (Horton), 0 (GA/CN). | |
| std::vector< double > | runoff |
| Current total runoff flow rate (project flow units). | |
| std::vector< double > | rainfall |
| Current total rainfall depth rate (project length/time units). | |
| std::vector< double > | evap_loss |
| Current evaporation loss rate (project length/time units). | |
| std::vector< double > | infil_loss |
| Current infiltration loss rate (project length/time units). | |
| std::vector< double > | ponded_depth |
| Current total ponded depth over subcatchment (project length units). | |
| std::vector< double > | old_ponded_depth |
| Ponded depth at the START of the runoff step (project length). | |
| std::vector< double > | washoff_vout1 |
| This runoff step's PRE-LID outflow volume, ft³ (legacy vOut1). | |
| std::vector< double > | gw_flow |
| Groundwater outflow rate (project flow units). | |
| std::vector< double > | snow_depth |
| Area-weighted snow pack SWE depth (ft), end of runoff step. | |
| std::vector< double > | lid_drain_flow |
| Total LID drain outflow (cfs) over the current runoff step. | |
| std::vector< double > | old_runoff |
| Runoff at the previous timestep. | |
| std::vector< double > | old_gw_flow |
| GW flow at the previous runoff evaluation (for interpolation). | |
| std::vector< double > | old_snow_depth |
| Snow depth at the previous runoff evaluation (for interpolation). | |
| std::vector< double > | old_lid_drain_flow |
| LID drain outflow at the previous runoff evaluation (for interpolation). | |
| std::vector< double > | runon_inflow |
| Runoff inflow from upstream subcatchments (project flow units). | |
| std::vector< double > | old_runon_inflow |
| Previous-step runon inflow (for interpolation). | |
| std::vector< double > | runon_rate |
| Legacy Subcatch.runon: the run-on as a depth rate (ft/s). | |
| std::vector< double > | outfall_runon_vol |
| Gap #28: accumulated outfall-routed volume (ft³) between runoff steps. | |
| std::vector< double > | gw_sw_head |
| Surface water head at GW receiving node (project length units). | |
| std::vector< double > | gw_node_avail_flow |
| Available node flow for GW negative flow limit (cfs/ft2). | |
| std::vector< double > | gw_max_infil_vol |
| Gap #40: max infiltration volume (ft) upper GW zone can accept next step. | |
| std::vector< double > | washoff_load |
| Washoff mass rate per (subcatch, pollutant) (mass/sec). | |
| std::vector< double > | conc |
| Current quality concentration in subcatchment runoff. | |
| std::vector< double > | conc_old |
| Previous-step quality in subcatchment runoff. | |
| std::vector< double > | ponded_qual |
| Ponded surface water quality mass per (subcatch, pollutant). | |
| std::vector< double > | runon_qual_rate |
| Incoming run-on pollutant mass RATE per (subcatch, pollutant), mg/sec. | |
| std::vector< double > | lid_drain_runon_qual |
| std::vector< double > | subarea_runoff_rate |
Area-averaged subarea runoff RATE, ft/sec — legacy's subcatch_getRunoff return value (runoff / area). | |
| std::vector< double > | init_loading |
| The [LOADINGS] initial surface buildup, mass per unit AREA. | |
| int | conc_n_pollutants = 0 |
| Number of pollutants in the quality arrays. | |
| std::vector< std::string > | comments |
| Object comment from the INP file (';'-prefixed lines immediately above this subcatchment's data row), joined by literal "\\n". Empty string means no comment. | |
| std::vector< std::string > | tags |
Per-object tag from the INP [TAGS] section. | |
| std::vector< char > | rpt_flag |
| Whether this subcatchment is included in report/output (0=no, 1=yes). | |
| std::vector< double > | stat_precip_vol |
| Total precipitation volume (project volume units). | |
| std::vector< double > | stat_runon_vol |
| Cumulative received runon volume (ft3). | |
| std::vector< double > | stat_gw_time |
| Elapsed groundwater time (seconds). | |
| std::vector< double > | stat_evap_vol |
| Cumulative evaporation volume (ft3) | |
| std::vector< double > | stat_infil_vol |
| Cumulative infiltration volume (ft3) | |
| std::vector< double > | stat_imperv_vol |
| Cumulative impervious runoff volume (ft3) | |
| std::vector< double > | stat_perv_vol |
| Cumulative pervious runoff volume (ft3) | |
| std::vector< double > | stat_runoff_vol |
| Total runoff volume (project volume units). | |
| std::vector< double > | stat_max_runoff |
| Maximum reported runoff rate (project flow units). | |
| std::vector< double > | stat_gw_infil_vol |
| Cumulative infiltration to GW (ft³) | |
| std::vector< double > | stat_gw_upper_evap_vol |
| Cumulative upper zone evap (ft³) | |
| std::vector< double > | stat_gw_lower_evap_vol |
| Cumulative lower zone evap (ft³) | |
| std::vector< double > | stat_gw_deep_perc_vol |
| Cumulative deep percolation (ft³) | |
| std::vector< double > | stat_gw_flow_vol |
| Cumulative lateral GW outflow (ft³) | |
| std::vector< double > | stat_gw_max_flow |
| Peak lateral GW outflow (CFS) | |
| std::vector< double > | stat_gw_sum_theta |
| Time integral of upper-zone theta (seconds) | |
| std::vector< double > | stat_gw_sum_depth |
| Time integral of water table elevation (ft-seconds) | |
| std::vector< double > | stat_gw_final_theta |
| Upper-zone theta at last GW step. | |
| std::vector< double > | stat_gw_final_depth |
| Water table elevation at last GW step (ft) | |
| std::vector< long > | stat_gw_steps |
| Step count for GW averages. | |
| std::vector< int > | gw_aquifer |
| Aquifer index for this subcatchment (-1 = none). | |
| std::vector< int > | gw_node |
| Receiving node index for groundwater flow (-1 = none). | |
| std::vector< double > | gw_surf_elev |
| Surface elevation for groundwater calculations. | |
| std::vector< double > | gw_a1 |
| Groundwater flow coefficient A1. | |
| std::vector< double > | gw_b1 |
| Groundwater flow exponent B1. | |
| std::vector< double > | gw_a2 |
| Groundwater flow coefficient A2. | |
| std::vector< double > | gw_b2 |
| Groundwater flow exponent B2. | |
| std::vector< double > | gw_a3 |
| Groundwater flow coefficient A3. | |
| std::vector< double > | gw_tw |
| [GROUNDWATER] Dsw: fixed surface-water depth (project length units, 0 = live node depth). | |
| std::vector< double > | gw_hstar |
[GROUNDWATER] Egwt: threshold groundwater table elevation (project length units) below which no lateral flow occurs. constants::MISSING when the row gave * or omitted it, in which case legacy uses the receiving node's invert (gwater.c Hstar). | |
| std::vector< double > | gw_bot_elev |
| [GROUNDWATER] Ebot: aquifer bottom elevation override; MISSING = the aquifer's. | |
| std::vector< double > | gw_wt_elev |
| [GROUNDWATER] Wgw: initial water-table elevation override; MISSING = the aquifer's. | |
| std::vector< double > | gw_upper_moist |
| [GROUNDWATER] Umc: initial upper-zone moisture override; MISSING = the aquifer's. | |
| std::vector< int > | snowpack |
| Snowpack index for this subcatchment (-1 = none). | |
| std::vector< double > | snow_net_imperv |
| Snow-modified net precipitation for impervious subareas (ft/sec). | |
| std::vector< double > | snow_net_perv |
| Snow-modified net precipitation for pervious subarea (ft/sec). | |
| std::vector< double > | snow_melt_imperv |
The MELT-ONLY part of snow_net_imperv (ft/sec). | |
| std::vector< double > | snow_melt_perv |
The melt-only part of snow_net_perv (ft/sec). See above. | |
| std::vector< double > | snow_melt_age_imperv |
S2b — WATER AGE of the meltwater in snow_melt_imperv (sec). | |
| std::vector< double > | snow_melt_age_perv |
S2b — water age of the meltwater in snow_melt_perv (sec). See above. | |
| std::vector< double > | total_lid_area_ft2 |
| Total LID area for this subcatchment (ft²). | |
| std::vector< double > | lid_return_to_perv_cfs |
| LID surface return flow to pervious area (CFS). | |
| std::vector< double > | lid_drain_runon_cfs |
| LID drain flow routed to a target subcatchment (CFS). | |
| std::vector< double > | total_load |
| Total washoff load per (subcatchment x pollutant) (mass units). | |
| int | total_load_n_pollutants = 0 |
| Number of pollutants in total_load matrix. | |
| std::vector< double > | coverage |
| Coverage fraction per (subcatchment x landuse). | |
| int | coverage_n_landuses = 0 |
| Number of landuses stored in the coverage and sweep matrices. | |
| std::vector< double > | sweep_last_swept |
| Gap #34: days since last swept per (subcatch x landuse). | |
| std::vector< unsigned char > | sweep_now |
| std::vector< double > | sweep_last_date |
Structure-of-Arrays storage for all subcatchments.
Pollutant-related arrays are stored separately in PollutantData, indexed as [subcatch_idx * n_pollutants + pollutant_idx].
|
inlinenoexcept |
Count subcatchment rows from the area column.
|
inline |
Erase one subcatchment row from the columns visited by this helper.
Visits owned base columns and configured pollutant/load/coverage/sweeping strides when present. Caller separately repairs outlet/gage/snowpack references, names and spatial geometry; no engine lifecycle check occurs here. Following rows shift down and element references/iterators are invalidated. Does not make inconsistent stores transactional.
| [in] | idx | Caller-validated existing row index; aligned dimensions and representable size products required. |
|
inline |
Extend base subcatchment 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.
| [in] | n | Requested total count; <=count() is a no-op, including negatives. |
|
inline |
Reserve capacity for n subcatchments without changing count().
Parsing grows these arrays one row at a time via grow_to(), so each of the ~76 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.
| [in] | n | Nonnegative target capacity for the base columns; flat-array products must fit size_t. |
|
inlinenoexcept |
Clear the subcatchment dynamic arrays visited here.
Zeroes runoff/rain/evap/infiltration, ponded depth, old runoff/GW/snow/LID values, run-on and current/old concentrations/washoff loads. Snow net/melt/age channels become -1 (unresolved). Does not rebuild initial stores, reset statistics or clear all pending outfall/LID/ponded-quality accumulators; wider initialization owns those.
|
inline |
Replace the base subcatchment store with a requested row count.
Replaces base subcatchment geometry/state/statistic columns with defaults; references start unresolved, rainfall/snow factors=1, Manning n=0.013/0.1 and snow-routing channels=-1. outlet_name/snowpack_name/gage_name preserve retained prefixes through resize. Pollutant and land-use matrices require separate sizing; names/spatial geometry are external. Independent assignments can fail without rollback; borrowed elements may be invalidated.
| [in] | n | Nonnegative row count; unchecked conversion to size_t, with valid size products for flat statistics. |
|
inline |
Resize the coverage and sweep matrices.
| n_sc | Number of subcatchments. |
| n_lu | Number of landuses. |
|
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, initial loading, ponded/run-on/LID drain species loads and washoff_load. Allocation failure may leave partial assignments. No pollutant registry update or initial-concentration seeding.
| [in] | n_pollutants | Pollutants per subcatchment; positive count requires count()*n_pollutants to fit size_t. |
|
inline |
Replace cumulative subcatchment pollutant-load storage.
Stores total_load_n_pollutants and assigns n_sc*n_poll zeros, including clearing for a zero dimension. Does not resize other arrays; no negative/overflow guard or rollback on allocation failure.
| [in] | n_sc | Nonnegative subcatchment row count, normally count(). |
| [in] | n_poll | Nonnegative pollutant stride; dimension product must fit size_t. |
|
inline |
Zero the washoff-load matrix for a positive pollutant count.
Does not update conc_n_pollutants or any other quality dimensions; caller keeps strides coherent.
| [in] | n_pollutants | Positive count allocates count()*n_pollutants entries; <=0 leaves existing storage untouched. |
|
inlinenoexcept |
Snapshot runoff-step discharge, run-on, concentration and ponded depth.
Copies runoff/runon_inflow/conc/ponded_depth to corresponding old arrays, which must already be long enough. Call once per runoff evaluation so routing-step interpolation retains its original endpoints; no allocation.
|
inline |
Release excess vector capacity accumulated during parsing.
| std::vector<double> openswmm::SubcatchData::area |
| std::vector<std::string> openswmm::SubcatchData::comments |
Object comment from the INP file (';'-prefixed lines immediately above this subcatchment's data row), joined by literal "\\n". Empty string means no comment.
| std::vector<double> openswmm::SubcatchData::conc |
Current quality concentration in subcatchment runoff.
Size = n_subcatches * n_pollutants.
| int openswmm::SubcatchData::conc_n_pollutants = 0 |
Number of pollutants in the quality arrays.
| std::vector<double> openswmm::SubcatchData::conc_old |
Previous-step quality in subcatchment runoff.
| std::vector<double> openswmm::SubcatchData::coverage |
Coverage fraction per (subcatchment x landuse).
Indexed as [sc_idx * n_landuses + lu_idx]. Values are 0–1.
| int openswmm::SubcatchData::coverage_n_landuses = 0 |
Number of landuses stored in the coverage and sweep matrices.
| std::vector<double> openswmm::SubcatchData::curb_length |
Total curb length (project length units).
| std::vector<double> openswmm::SubcatchData::ds_imperv |
| std::vector<double> openswmm::SubcatchData::ds_perv |
| std::vector<double> openswmm::SubcatchData::evap_loss |
Current evaporation loss rate (project length/time units).
| std::vector<double> openswmm::SubcatchData::frac_imperv |
Fraction of area that is impervious (0–1).
| std::vector<double> openswmm::SubcatchData::frac_imperv_no_store |
Fraction of impervious area with no depression storage (0–1).
| std::vector<int> openswmm::SubcatchData::gage |
| std::vector<std::string> openswmm::SubcatchData::gage_name |
Rain gage name string for deferred resolution.
Stored during parsing (SUBCATCHMENTS column 1) so PostParseResolver can resolve/validate gage once RAINGAGES has been parsed, regardless of section order, and raise ERR_NAME for an undefined gage (legacy fatal). Parse-time config only.
| std::vector<double> openswmm::SubcatchData::gw_a1 |
Groundwater flow coefficient A1.
| std::vector<double> openswmm::SubcatchData::gw_a2 |
Groundwater flow coefficient A2.
| std::vector<double> openswmm::SubcatchData::gw_a3 |
Groundwater flow coefficient A3.
| std::vector<int> openswmm::SubcatchData::gw_aquifer |
Aquifer index for this subcatchment (-1 = none).
| std::vector<double> openswmm::SubcatchData::gw_b1 |
Groundwater flow exponent B1.
| std::vector<double> openswmm::SubcatchData::gw_b2 |
Groundwater flow exponent B2.
| std::vector<double> openswmm::SubcatchData::gw_bot_elev |
[GROUNDWATER] Ebot: aquifer bottom elevation override; MISSING = the aquifer's.
| std::vector<double> openswmm::SubcatchData::gw_flow |
Groundwater outflow rate (project flow units).
| std::vector<double> openswmm::SubcatchData::gw_hstar |
[GROUNDWATER] Egwt: threshold groundwater table elevation (project length units) below which no lateral flow occurs. constants::MISSING when the row gave * or omitted it, in which case legacy uses the receiving node's invert (gwater.c Hstar).
| std::vector<double> openswmm::SubcatchData::gw_max_infil_vol |
Gap #40: max infiltration volume (ft) upper GW zone can accept next step.
= (total_depth - lower_depth) * (porosity - theta) / frac_perv. Updated after each GW step; used by Runoff to cap infil rate (vol/dt). DBL_MAX (no constraint) when no GW is active.
| std::vector<int> openswmm::SubcatchData::gw_node |
Receiving node index for groundwater flow (-1 = none).
| std::vector<double> openswmm::SubcatchData::gw_node_avail_flow |
Available node flow for GW negative flow limit (cfs/ft2).
| std::vector<double> openswmm::SubcatchData::gw_surf_elev |
Surface elevation for groundwater calculations.
| std::vector<double> openswmm::SubcatchData::gw_sw_head |
Surface water head at GW receiving node (project length units).
Assembled from nodes.depth + nodes.invert_elev - aquifer bottom.
| std::vector<double> openswmm::SubcatchData::gw_tw |
[GROUNDWATER] Dsw: fixed surface-water depth (project length units, 0 = live node depth).
| std::vector<double> openswmm::SubcatchData::gw_upper_moist |
[GROUNDWATER] Umc: initial upper-zone moisture override; MISSING = the aquifer's.
| std::vector<double> openswmm::SubcatchData::gw_wt_elev |
[GROUNDWATER] Wgw: initial water-table elevation override; MISSING = the aquifer's.
| std::vector<double> openswmm::SubcatchData::infil_loss |
Current infiltration loss rate (project length/time units).
| std::vector<int> openswmm::SubcatchData::infil_model |
Infiltration model: 0=HORTON, 1=MOD_HORTON, 2=GREEN_AMPT, 3=MOD_GREEN_AMPT, 4=CURVE_NUMBER.
| std::vector<double> openswmm::SubcatchData::infil_p1 |
Infiltration param 1: f0 (Horton), suction (GA), CN (CN).
| std::vector<double> openswmm::SubcatchData::infil_p2 |
Infiltration param 2: fmin (Horton), conductivity (GA), unused (CN).
| std::vector<double> openswmm::SubcatchData::infil_p3 |
Infiltration param 3: decay (Horton), initial deficit (GA), drying time (CN).
| std::vector<double> openswmm::SubcatchData::infil_p4 |
Infiltration param 4: dry time (Horton), 0 (GA/CN).
| std::vector<double> openswmm::SubcatchData::infil_p5 |
Infiltration param 5: max infil (Horton), 0 (GA/CN).
| std::vector<double> openswmm::SubcatchData::init_loading |
The [LOADINGS] initial surface buildup, mass per unit AREA.
Size = n_subcatches * n_pollutants. This is NOT a concentration: legacy seeds each land use with initBuildup[p] * fArea in landuse_getInitBuildup (landuse.c:388-395), whatever DRY_DAYS is and whether or not the land use has a buildup function. It used to be parked in conc, which is the reported washoff concentration — so it was both unreachable by the initial-buildup seeding and able to leak into the first reported concentration.
| std::vector<double> openswmm::SubcatchData::lid_drain_flow |
Total LID drain outflow (cfs) over the current runoff step.
| std::vector<double> openswmm::SubcatchData::lid_drain_runon_cfs |
LID drain flow routed to a target subcatchment (CFS).
Accumulated each runoff step when drain_subcatch >= 0. Drained into runon_inflow[] by assembleRunon() (after the clear), then reset, so the drain reaches the target as runon next step. Matches legacy lid_addDrainRunon() in lid.c.
| std::vector<double> openswmm::SubcatchData::lid_drain_runon_qual |
[sc * np + p] pollutant load (concentration mass / s, removal already applied) a LID underdrain routed to this subcatchment delivered in the last runoff step; joins runon_qual_rate at the next assembleRunon, the drain water's own lag (legacy lid_addDrainRunon).
| std::vector<double> openswmm::SubcatchData::lid_return_to_perv_cfs |
LID surface return flow to pervious area (CFS).
Set by LIDSolver output routing when to_perv==1. Consumed by RunoffSolver as additional pervious-subarea inflow next step. Matches legacy lid_getFlowToPerv() called in subcatch_getRunon().
| std::vector<double> openswmm::SubcatchData::n_imperv |
| std::vector<double> openswmm::SubcatchData::n_perv |
| std::vector<double> openswmm::SubcatchData::old_gw_flow |
GW flow at the previous runoff evaluation (for interpolation).
| std::vector<double> openswmm::SubcatchData::old_lid_drain_flow |
LID drain outflow at the previous runoff evaluation (for interpolation).
| std::vector<double> openswmm::SubcatchData::old_ponded_depth |
Ponded depth at the START of the runoff step (project length).
Legacy forms Vinflow = vRunon + subcatch_getDepth(j) * nonLidArea at the top of subcatch_getRunoff, BEFORE the subareas are stepped, and only later re-derives the ponded store from the new depth. findPondedLoads runs after the step, so it needs the opening depth kept aside.
| std::vector<double> openswmm::SubcatchData::old_runoff |
Runoff at the previous timestep.
| std::vector<double> openswmm::SubcatchData::old_runon_inflow |
Previous-step runon inflow (for interpolation).
| std::vector<double> openswmm::SubcatchData::old_snow_depth |
Snow depth at the previous runoff evaluation (for interpolation).
| std::vector<double> openswmm::SubcatchData::outfall_runon_vol |
Gap #28: accumulated outfall-routed volume (ft³) between runoff steps.
Matches legacy Outfall[i].vRouted. Drained to runon_inflow at each assembleRunon() call, then reset to 0.
| std::vector<std::string> openswmm::SubcatchData::outlet_name |
Outlet name string for deferred resolution.
Stored during parsing so PostParseResolver can re-resolve outlet_node / outlet_subcatch when sections appear out of order.
| std::vector<int> openswmm::SubcatchData::outlet_node |
| std::vector<int> openswmm::SubcatchData::outlet_subcatch |
Index of the subcatch that receives overflow (-1 if none).
| std::vector<double> openswmm::SubcatchData::pct_routed |
Fraction of runoff routed between subareas (0–1).
The remainder (1 - pct_routed) goes to the outlet. fOutlet = 1 - pct_routed for the routed subarea.
| std::vector<double> openswmm::SubcatchData::pct_zero |
The AUTHORED [SUBAREAS] PctZero column, in percent.
Kept alongside the 0-1 fraction because legacy forms the impervious-without-storage subarea fraction as fracImperv * x[4] / 100.0 (subcatch.c:268) — it multiplies by the PERCENT and divides after. fracImperv * (x[4]/100) is a different double for about a tenth of all percentages, and the difference lands straight in the subarea's area, so the runoff kernel needs the number legacy multiplied by. A model loaded from GeoPackage, which stores only the fraction, recovers it as fraction * 100.
| std::vector<double> openswmm::SubcatchData::ponded_depth |
Current total ponded depth over subcatchment (project length units).
| std::vector<double> openswmm::SubcatchData::ponded_qual |
Ponded surface water quality mass per (subcatch, pollutant).
Persists between wet/dry events. Updated each timestep as: wPonded = pondedQual + rain_deposition + runon_load cPonded = wPonded / V_inflow pondedQual_new = cPonded * ponded_depth * non_lid_area
| std::vector<double> openswmm::SubcatchData::rain_scale_factor |
Subcatchment-level rainfall scale factor (default 1.0 = no scaling).
Optional trailing token 9 of [SUBCATCHMENTS]. Multiplies the gage-derived rainfall for this subcatchment only, composing multiplicatively with the gage's own scale factor: rainfall = gage_rain * gage.scale_factor * rain_scale_factor API/forcing overrides are deliberately NOT scaled.
| std::vector<double> openswmm::SubcatchData::rainfall |
| std::vector<char> openswmm::SubcatchData::rpt_flag |
Whether this subcatchment is included in report/output (0=no, 1=yes).
| std::vector<double> openswmm::SubcatchData::runoff |
Current total runoff flow rate (project flow units).
| std::vector<double> openswmm::SubcatchData::runon_inflow |
Runoff inflow from upstream subcatchments (project flow units).
Assembled by assembleRunon(); zero if no upstream subcatch.
| std::vector<double> openswmm::SubcatchData::runon_qual_rate |
Incoming run-on pollutant mass RATE per (subcatch, pollutant), mg/sec.
Legacy uses Subcatch.newQual[] as a temporary accumulator for this between subcatch_getRunon and surfqual_getWashoff: upstream subcatchments add oldRunoff * oldQual * LperFT3 (subcatch.c:553) and findPondedLoads / findLidLoads consume it as wRunon = newQual * tStep (surfqual.c:443,561). v6 keeps the washoff concentration in conc, so the accumulator needs its own storage. Rebuilt by assembleRunon() every runoff substep, like runon_inflow.
| std::vector<double> openswmm::SubcatchData::runon_rate |
Legacy Subcatch.runon: the run-on as a depth rate (ft/s).
Accumulated per contributor in legacy subcatch_addRunonFlow's order and form — each flow divided by the non-LID area (or the full area when there is none) BEFORE the add — so the sum rounds as legacy's does. runon_inflow is the same water in CFS for the ledgers.
| std::vector<double> openswmm::SubcatchData::slope |
| std::vector<double> openswmm::SubcatchData::snow_depth |
Area-weighted snow pack SWE depth (ft), end of runoff step.
| std::vector<double> openswmm::SubcatchData::snow_melt_age_imperv |
S2b — WATER AGE of the meltwater in snow_melt_imperv (sec).
The pack's own residence time, area-blended over plowable and non-plowable impervious with the identical weights snow_melt_imperv uses. Reusing the blend is not tidiness: the rate and the age it describes have to come from the same weighting or a caller mixing by one and ageing by the other gets a mixture that never existed.
-1.0 means no snowpack active, matching snow_net_* and snow_melt_*. Only meaningful where snow_melt_imperv > 0.
| std::vector<double> openswmm::SubcatchData::snow_melt_age_perv |
S2b — water age of the meltwater in snow_melt_perv (sec). See above.
| std::vector<double> openswmm::SubcatchData::snow_melt_imperv |
The MELT-ONLY part of snow_net_imperv (ft/sec).
Same plowable/non-plowable area blend as snow_net_imperv, over imelt alone — so snow_net_imperv − snow_melt_imperv is the rain that fell on the snow-free fraction and reached the ground directly.
Published for S2: arriving water under a pack is two different waters. Meltwater is at 0 °C essentially by definition — that is what melting means — and carries the pack's age; rain-through carries the configured RAINFALL values. Their SUM is all snow_net_* records, and a sum cannot say what the water is worth. Following A4's precedent: the split exists as a local in the solver, so publish it rather than reconstruct it downstream.
-1.0 means no snowpack active, matching snow_net_*.
| std::vector<double> openswmm::SubcatchData::snow_melt_perv |
The melt-only part of snow_net_perv (ft/sec). See above.
| std::vector<double> openswmm::SubcatchData::snow_net_imperv |
Snow-modified net precipitation for impervious subareas (ft/sec).
Set by SWMMEngine after each snow execute step. Combines plowable + non-plowable imperv: imelt + rainfall*(1-asc). -1.0 means no snowpack active (use raw rainfall instead).
| std::vector<double> openswmm::SubcatchData::snow_net_perv |
| std::vector<double> openswmm::SubcatchData::snow_scale_factor |
Subcatchment-level snowfall scale factor (default 1.0 = no scaling).
Optional trailing token 10 of [SUBCATCHMENTS]. Composes with the gage snow catch factor (SCF): snowfall = gage_rain * gage.scale_factor * gage.snow_factor
| std::vector<int> openswmm::SubcatchData::snowpack |
Snowpack index for this subcatchment (-1 = none).
| std::vector<std::string> openswmm::SubcatchData::snowpack_name |
Snow pack name string for deferred resolution.
Stored during parsing (SUBCATCHMENTS column 8) so PostParseResolver can resolve snowpack once SNOWPACKS has been parsed, regardless of section order. Parse-time config — not part of the simulation state snapshot.
| std::vector<double> openswmm::SubcatchData::stat_evap_vol |
Cumulative evaporation volume (ft3)
| std::vector<double> openswmm::SubcatchData::stat_gw_deep_perc_vol |
Cumulative deep percolation (ft³)
| std::vector<double> openswmm::SubcatchData::stat_gw_final_depth |
Water table elevation at last GW step (ft)
| std::vector<double> openswmm::SubcatchData::stat_gw_final_theta |
Upper-zone theta at last GW step.
| std::vector<double> openswmm::SubcatchData::stat_gw_flow_vol |
Cumulative lateral GW outflow (ft³)
| std::vector<double> openswmm::SubcatchData::stat_gw_infil_vol |
Cumulative infiltration to GW (ft³)
| std::vector<double> openswmm::SubcatchData::stat_gw_lower_evap_vol |
Cumulative lower zone evap (ft³)
| std::vector<double> openswmm::SubcatchData::stat_gw_max_flow |
Peak lateral GW outflow (CFS)
| std::vector<long> openswmm::SubcatchData::stat_gw_steps |
Step count for GW averages.
| std::vector<double> openswmm::SubcatchData::stat_gw_sum_depth |
Time integral of water table elevation (ft-seconds)
| std::vector<double> openswmm::SubcatchData::stat_gw_sum_theta |
Time integral of upper-zone theta (seconds)
| std::vector<double> openswmm::SubcatchData::stat_gw_time |
Elapsed groundwater time (seconds).
| std::vector<double> openswmm::SubcatchData::stat_gw_upper_evap_vol |
Cumulative upper zone evap (ft³)
| std::vector<double> openswmm::SubcatchData::stat_imperv_vol |
Cumulative impervious runoff volume (ft3)
| std::vector<double> openswmm::SubcatchData::stat_infil_vol |
Cumulative infiltration volume (ft3)
| std::vector<double> openswmm::SubcatchData::stat_max_runoff |
Maximum reported runoff rate (project flow units).
| std::vector<double> openswmm::SubcatchData::stat_perv_vol |
Cumulative pervious runoff volume (ft3)
| std::vector<double> openswmm::SubcatchData::stat_precip_vol |
Total precipitation volume (project volume units).
| std::vector<double> openswmm::SubcatchData::stat_runoff_vol |
Total runoff volume (project volume units).
| std::vector<double> openswmm::SubcatchData::stat_runon_vol |
Cumulative received runon volume (ft3).
| std::vector<int> openswmm::SubcatchData::subarea_routing |
Inter-subarea routing mode.
0 = TO_OUTLET (all runoff goes to outlet), 1 = TO_IMPERV (pervious → impervious), 2 = TO_PERV (impervious → pervious).
| std::vector<double> openswmm::SubcatchData::subarea_runoff_rate |
Area-averaged subarea runoff RATE, ft/sec — legacy's subcatch_getRunoff return value (runoff / area).
The quantity legacy hands findWashoffLoads and landuse_getWashoffQual. It is NOT runoff (cfs): it carries no fOutlet and no LID adjustment, and it never round-trips through a volume, so the two surface-quality paths (pollutant and reactions species) that both need it read one number rather than each re-deriving it a ULP apart.
| std::vector<double> openswmm::SubcatchData::sweep_last_date |
[sc * n_landuses + lu] absolute date (days) the land use was last swept — legacy landFactor[].lastSwept. The sweep decision compares the step's start date with it, as legacy does; sweep_last_swept stays the readable "days since last swept". Runtime only.
| std::vector<double> openswmm::SubcatchData::sweep_last_swept |
Gap #34: days since last swept per (subcatch x landuse).
Flat 2D: [sc_idx * n_landuses + lu_idx]. Matches legacy Subcatch[i].landFactor[j].lastSwept. Per-(subcatch,landuse) tracking so each subcatchment sweeps independently on its own schedule.
| std::vector<unsigned char> openswmm::SubcatchData::sweep_now |
[sc * n_landuses + lu] 1 when the land use sweeps this runoff step (decided at the step's start, applied by the surface kernel between buildup and washoff).
| std::vector<std::string> openswmm::SubcatchData::tags |
Per-object tag from the INP [TAGS] section.
Free-form string label. Index-keyed so swmm_subcatch_rename keeps the tag attached.
| std::vector<double> openswmm::SubcatchData::total_lid_area_ft2 |
| std::vector<double> openswmm::SubcatchData::total_load |
Total washoff load per (subcatchment x pollutant) (mass units).
| int openswmm::SubcatchData::total_load_n_pollutants = 0 |
Number of pollutants in total_load matrix.
| std::vector<double> openswmm::SubcatchData::washoff_load |
Washoff mass rate per (subcatch, pollutant) (mass/sec).
Flat 2D: [subcatch * n_pollutants + pollutant].
| std::vector<double> openswmm::SubcatchData::washoff_vout1 |
This runoff step's PRE-LID outflow volume, ft³ (legacy vOut1).
vOut1 = Voutflow + vLidRain + vLidRunon, the denominator the washoff concentration is formed over. The surface-quality step runs before the LID units, so it is the only place this volume still exists; the mass bookings that need it happen after the units have run and runoff has become the POST-LID value.
| std::vector<double> openswmm::SubcatchData::width |