OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
ArdEngine.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2//
3// Copyright 2026 Caleb Buahin
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
63
64#ifndef OPENSWMM_ENGINE_TRANSPORT_ARD_ENGINE_HPP
65#define OPENSWMM_ENGINE_TRANSPORT_ARD_ENGINE_HPP
66
67#include <fstream>
68#include <string>
69#include <vector>
70
74
75namespace openswmm {
77}
78
79namespace openswmm::transport {
80
81class ArdEngine {
82public:
89 bool init(SimulationContext& ctx);
90
98 void step(SimulationContext& ctx, double dt);
99
105 bool initialized() const noexcept { return initialized_; }
106 std::string checkpointState() const;
107 // Decode only into a fresh staging engine; caller installs after every
108 // physical/output record has passed validation. Detailed writers excluded.
109 void restoreCheckpointState(const std::string&, SimulationContext&);
116 const std::vector<std::string>& warnings() const noexcept { return warnings_; }
117
128
131 std::vector<double> totalMass(const SimulationContext& ctx) const;
132 std::vector<ChannelThermalRegion> thermalRegions() const;
134 const std::vector<ChannelThermalIncrement>&);
135 std::vector<ChannelSpeciesRegion> speciesRegions(const SimulationContext&) const;
137 const std::vector<ChannelSpeciesIncrement>&);
138
139private:
140 // Continuity-consistent face fluxes from the link/node fields of the
141 // current routing step (plan §3.2): within each conduit the face flux
142 // ramps linearly so every cell receives an equal share of the conduit's
143 // volume change, and the two end faces carry the flux the node exchange
144 // actually saw. Splice faces (virtual junctions) take the mean of the
145 // two conduits' end values.
146 void projectHydraulics(SimulationContext& ctx, double dt);
147
148 // One advection substep of length dt_sub: kernel reconstruction + FCT on
149 // interior faces, donor-upwinded node boundary fluxes, cell mass/area
150 // update, node CSTR update (external loads prorated by dt_sub / dt_step),
151 // then the implicit dispersion solve over the updated cells (E3,
152 // sequential Lie split: one full advection step, then one full
153 // dispersion step — NOT Strang, which would halve the advection).
154 void substep(SimulationContext& ctx, double dt_sub, double load_frac);
155
156 // E3: refresh cell_disp_ from the routing step's hydraulics. Per-conduit
157 // overrides always win; otherwise VALUE mode broadcasts the global
158 // coefficient and FISCHER mode evaluates D = 0.011 v²B²/(Y·U*),
159 // U* = √(g·Y·S) from the link fields (all internal ft units).
160 void updateDispersion(SimulationContext& ctx);
161
162 void publish(SimulationContext& ctx);
163
166
167 // Projected per-face volumetric flux for the current routing step and the
168 // per-cell start-of-step areas it is consistent with.
169 std::vector<double> face_q_;
170
171 // Node stores: species mass [node * ns + s] and water volume the mass
172 // sits in (tracked from the same fluxes, so node concentration is
173 // self-consistent between substeps).
174 std::vector<double> node_mass_;
175 std::vector<double> node_vol_;
176
177 // Lateral loads at VIRTUAL junctions (plans/VJ_LATERAL_INFLOW_PLAN_
178 // 2026-09-04.md §E4). A virtual junction owns no faces — its conduits
179 // were spliced into one interior face — so a node store there could
180 // never discharge and the per-step resync zeroed it: the load was
181 // destroyed. Its water and mass go straight into the two cells adjoining
182 // the splice, half each, mirroring the hydraulic solver's cell_qlat_
183 // split. Rebuilt every substep; has_vj_src_ gates the whole path so a
184 // deck without a fed virtual junction executes no new arithmetic.
185 std::vector<double> cell_src_vol_;
186 std::vector<double> cell_src_mass_;
187 bool has_vj_src_ = false;
188
189 // Kernel scratch (sized once in init; see SpeciesKernelView).
190 std::vector<double> f_mass_, f_sstar_, f_phi_l_, f_phi_r_, f_phi_flux_, cell_slope_, lo_flux_,
191 anti_flux_, td_, anew_, rplus_, rminus_, cell_u_;
192 std::vector<fv::kernels::FaceState> f_state_l_, f_state_r_;
193 std::vector<fv::kernels::FaceFlux> f_flux_;
194 std::vector<char> cell_active_;
195 std::vector<int> active_faces_;
196
197 // E5a: transport boundaries/sources resolved onto the mesh at init.
198 // Boundaries: the node's external inflow water carries the species at
199 // bc_now_ (evaluated once per routing step: VALUE or timeseries).
200 // Sources: internal-rate mass distributed over the conduit's wet cells.
201 void updateTransportRows(SimulationContext& ctx);
202 std::vector<int> bc_node_, bc_srow_, bc_ts_;
203 std::vector<double> bc_value_, bc_now_;
204 std::vector<int> src_crow_, src_srow_, src_ts_;
205 std::vector<double> src_value_, src_len_, src_now_;
206
207 // E3 dispersion state. disp_active_ gates the whole path: when false the
208 // substep passes no per-cell array and dispersionSolve early-outs — the
209 // pre-E3 behavior, bit-identical for existing ARD decks.
210 bool disp_active_ = false;
211 int disp_mode_ = 0;
212 double disp_global_ft_ = 0.0;
213 std::vector<double> conduit_disp_ft_;
214 std::vector<double> cell_disp_;
215
216 // E5b: per-cell CSV sidecar ([TRANSPORT_OPTIONS] DETAILED_OUTPUT).
217 // Written every routing step (documented decision — a detail feature
218 // for short diagnostic runs; cadence control can come later if sizes
219 // demand it). Columns: time_s, element, kind (L link cell / N node
220 // store), cell index, species name, concentration.
221 void writeDetailRows(SimulationContext& ctx);
222 std::ofstream detail_out_;
223 bool detail_active_ = false;
224 double detail_time_s_ = 0.0;
225
228 int age_row_ = -1;
229
232 int nm_ = 0;
233
236 void applyHeatFluxes(SimulationContext& ctx, double dt);
237
240 void applyBedSoluteExchange(SimulationContext& ctx, double dt);
241
246 int cellLink(std::size_t cell) const noexcept;
247
252 int temp_row_ = -1;
253
254 std::vector<std::string> warnings_;
255 bool initialized_ = false;
256 bool warned_cfl_clamp_ = false;
257};
258
259} // namespace openswmm::transport
260
261#endif // OPENSWMM_ENGINE_TRANSPORT_ARD_ENGINE_HPP
Thermal state and geometry associated with routed channels.
Single-source scalar kernels for the explicit FV 1D network solver.
SoA storage for the 1D finite-volume network mesh and its state.
Definition ArdEngine.hpp:81
void step(SimulationContext &ctx, double dt)
One transport step over the routing step dt.
Definition ArdEngine.cpp:1404
bool initialized() const noexcept
Read successful mesh/state initialization flag.
Definition ArdEngine.hpp:105
void restoreCheckpointState(const std::string &, SimulationContext &)
Decode completed ARD state into a fresh staging owner against compatible context.
Definition ArdEngine.cpp:2157
std::string applyThermalIncrements(SimulationContext &, const std::vector< ChannelThermalIncrement > &)
Add validated per-cell signed temperature increments then publish all families.
Definition ArdEngine.cpp:111
std::string checkpointState() const
Export completed ARD numerical state without serializing live diagnostic writer.
Definition ArdEngine.cpp:2128
const std::vector< std::string > & warnings() const noexcept
Borrow initialization diagnostics retained by this transport owner.
Definition ArdEngine.hpp:116
bool init(SimulationContext &ctx)
Build the transport mesh and size all state; call once after the model is fully resolved (Router::ini...
Definition ArdEngine.cpp:265
std::vector< ChannelThermalRegion > thermalRegions() const
Export wet transport-cell thermal regions and their SI geometry.
Definition ArdEngine.cpp:65
std::string applySpeciesIncrements(SimulationContext &, const std::vector< ChannelSpeciesIncrement > &)
Validate unique cell species deltas then apply nonthermal rows and republish.
Definition ArdEngine.cpp:170
void absorbTreatedNodeConc(SimulationContext &ctx)
E5b treatment interop: absorb treated node concentrations back into the node stores.
Definition ArdEngine.cpp:1542
std::vector< double > totalMass(const SimulationContext &ctx) const
Sum represented inventory over cells and physical node stores for every carried row.
Definition ArdEngine.cpp:2080
std::vector< ChannelSpeciesRegion > speciesRegions(const SimulationContext &) const
Export carried row concentrations over available wet thermal transport-cell regions.
Definition ArdEngine.cpp:134
Definition ExplicitFvSolver.hpp:53
Definition ExchangeLaw.hpp:60
Central, reentrant simulation context.
Definition SimulationContext.hpp:390
SoA mesh geometry and topology for the FV network solver.
Definition NetworkMeshData.hpp:123
Mutable solver state — the conserved variables and the node volumes.
Definition NetworkMeshData.hpp:519