OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
Routing.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
35
36#ifndef OPENSWMM_ROUTING_HPP
37#define OPENSWMM_ROUTING_HPP
38
39#include "XSectBatch.hpp"
40#include "KinematicWave.hpp"
41#include "DynamicWave.hpp"
42#include "Divider.hpp"
43#include "fv/FvOptions.hpp"
44#include "fv/INetworkSolver.hpp"
46
47#include <memory>
48#include <string>
49#include <functional>
50#include <vector>
51
52namespace openswmm {
53
55
56// ============================================================================
57// Routing model enum
58// ============================================================================
59
60enum class RouteModel : int {
61 STEADY = 0,
62 KINWAVE = 1,
63 DYNWAVE = 2,
64 FV = 3
65};
66
67// ============================================================================
68// Routing orchestrator
69// ============================================================================
70
78class Router {
79public:
89 void init(SimulationContext& ctx, RouteModel model);
90
99 int step(SimulationContext& ctx, double dt,
100 double evap_rate = 0.0,
101 dynwave::DWSolver::NonConduitFlowFunc non_conduit_fn = nullptr);
102
112 double fixed_step, double courant);
113
115 const XSectGroups& xsectGroups() const { return groups_; }
116
119 bool hasCycle() const { return cycle_detected_; }
120
122 void setDWNumThreads(int n, std::vector<std::string>* warnings = nullptr) {
123 dw_solver_.setNumThreads(n, warnings);
124 }
125
127 dynwave::DWSolver& dwSolver() { return dw_solver_; }
128
133 void setStructureSolver(hydstruct::StructureSolver* s) { structures_ = s; }
134
140 bool lastStepConverged() const {
141 return (model_ == RouteModel::DYNWAVE) ? dw_solver_.lastConverged() : true;
142 }
143
146 const fv::INetworkSolver* fvSolver() const { return fv_solver_.get(); }
147
149 const fv::NetworkMeshData& fvMesh() const { return fv_mesh_; }
150
152 const std::string& fvBackend() const { return fv_backend_; }
153
156 const std::vector<std::string>& fvWarnings() const { return fv_warnings_; }
157 const std::vector<std::string>& fvErrors() const { return fv_errors_; }
158
159private:
161 XSectGroups groups_;
162
165 hydstruct::StructureSolver* structures_ = nullptr;
166
169 std::vector<char> steady_storage_updated_;
172 std::vector<double> steady_y_;
173
174 // --- Explicit finite-volume solver (FLOW_ROUTING FV) -------------------
175 // The mesh and state are owned here, not by the solver, exactly as
176 // SurfaceRouter2D owns MeshData/SurfaceStateData: the solver is swappable
177 // (CPU or Kokkos plugin) and must not own what survives a backend change.
178 fv::NetworkMeshData fv_mesh_;
179 fv::NetworkStateData fv_state_;
180 fv::FvOptions fv_opts_;
181 std::unique_ptr<fv::INetworkSolver> fv_solver_;
182 std::string fv_backend_;
183 std::vector<std::string> fv_warnings_, fv_errors_;
184
185 // Per-step forcing buffers, allocated once at init.
186 std::vector<double> fv_lateral_, fv_fixed_head_, fv_struct_flow_, fv_cond_loss_;
187
192 std::vector<double> fv_link_q_cap_;
193
199 std::vector<double> fv_struct_int_;
200 double fv_struct_t_prev_ = 0.0;
201
202 void initFv(SimulationContext& ctx);
203 int stepFv(SimulationContext& ctx, double dt,
205 void publishFv(SimulationContext& ctx, double dt);
206 kinwave::KWSolver kw_solver_;
207 dynwave::DWSolver dw_solver_;
208 // Divider data moved to ctx.node_subtypes.dividers (relational side-table).
209 std::vector<int> steady_sorted_links_;
210 bool cycle_detected_ = false;
211
212
214 void initNodeFlows(SimulationContext& ctx, double dt, double evap_rate);
215
217 void computeConduitLosses(SimulationContext& ctx, double dt, double evap_rate);
218
222 void refreshFvBoundaryFlows(SimulationContext& ctx, double t_elapsed,
223 const std::function<void()>& eval_structures);
224
226 void accumulateStructureFlows(const SimulationContext& ctx, double t_now);
227
229 void updateLinkStates(SimulationContext& ctx);
230
233 int executeSteadyFlow(SimulationContext& ctx, double dt);
234};
235
236} // namespace openswmm
237
238#endif // OPENSWMM_ROUTING_HPP
Flow divider node logic — cutoff, overflow, tabular, weir.
Dynamic wave routing solver — batch-oriented St. Venant equations.
Option struct for the explicit finite-volume 1D network solver.
Backend-neutral interface for the explicit FV 1D network integrator.
Kinematic wave routing solver — batch-oriented design.
SoA storage for the 1D finite-volume network mesh and its state.
Cross-section geometry — unified batch + per-element API.
Top-level routing orchestrator.
Definition Routing.hpp:78
double getAdaptiveStep(SimulationContext &ctx, double fixed_step, double courant)
Compute adaptive timestep (DW only).
Definition Routing.cpp:431
const fv::INetworkSolver * fvSolver() const
Definition Routing.hpp:146
void setStructureSolver(hydstruct::StructureSolver *s)
Definition Routing.hpp:133
void setDWNumThreads(int n, std::vector< std::string > *warnings=nullptr)
Set the DWSolver OpenMP thread count (delegates to DWSolver::setNumThreads).
Definition Routing.hpp:122
dynwave::DWSolver & dwSolver()
Access the DW solver (for non-conduit node state scatter).
Definition Routing.hpp:127
const XSectGroups & xsectGroups() const
Access the shape-grouped xsect manager.
Definition Routing.hpp:115
const std::vector< std::string > & fvErrors() const
Definition Routing.hpp:157
void init(SimulationContext &ctx, RouteModel model)
Initialise the router for the given model.
Definition Routing.cpp:75
const fv::NetworkMeshData & fvMesh() const
The FV mesh built at init (empty unless FLOW_ROUTING FV).
Definition Routing.hpp:149
bool hasCycle() const
Definition Routing.hpp:119
bool lastStepConverged() const
Definition Routing.hpp:140
int step(SimulationContext &ctx, double dt, double evap_rate=0.0, dynwave::DWSolver::NonConduitFlowFunc non_conduit_fn=nullptr)
Execute one routing timestep.
Definition Routing.cpp:345
const std::string & fvBackend() const
Backend label chosen by the FV factory ("cpu (...)", "omp (...)", ...).
Definition Routing.hpp:152
const std::vector< std::string > & fvWarnings() const
Definition Routing.hpp:156
Shape-grouped cross-section manager for batch computation.
Definition XSectBatch.hpp:243
Dynamic wave solver — operates on entire link/node system.
Definition DynamicWave.hpp:193
std::function< void(SimulationContext &, double, int)> NonConduitFlowFunc
Definition DynamicWave.hpp:216
Abstract time integrator for the explicit FV 1D network.
Definition INetworkSolver.hpp:121
Definition HydStructures.hpp:170
Kinematic wave solver state.
Definition KinematicWave.hpp:165
Definition NodeCoupling.cpp:16
@ FV
Explicit conservative finite volume (Godunov, HLL/HLLC)
Definition SimulationOptions.hpp:79
@ KINWAVE
Kinematic wave approximation.
Definition SimulationOptions.hpp:77
@ STEADY
Steady-state (no routing)
Definition SimulationOptions.hpp:76
@ DYNWAVE
Dynamic wave (full Saint-Venant, implicit Picard)
Definition SimulationOptions.hpp:78
RouteModel
Definition Routing.hpp:60
@ DYNWAVE
Dynamic wave (St. Venant, implicit Picard)
Definition Routing.hpp:63
Central, reentrant simulation context.
Definition SimulationContext.hpp:353
Knobs for FLOW_ROUTING FV.
Definition FvOptions.hpp:123
SoA mesh geometry and topology for the FV network solver.
Definition NetworkMeshData.hpp:176
Mutable solver state — the conserved variables and the node volumes.
Definition NetworkMeshData.hpp:489