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"
41#include "KinematicWave.hpp"
42#include "DynamicWave.hpp"
43#include "Divider.hpp"
44#include "fv/FvOptions.hpp"
45#include "fv/INetworkSolver.hpp"
47#include <array>
48
49#include <memory>
50#include <string>
51#include <functional>
52#include <vector>
53
54namespace openswmm {
55namespace twoD {
56class SurfaceRouter2D;
57}
58
60struct OutfallData;
61
62// ============================================================================
63// Routing model enum
64// ============================================================================
65
66enum class RouteModel : int {
67 STEADY = 0,
68 KINWAVE = 1,
69 DYNWAVE = 2,
70 FV = 3
71};
72
88void applyConduitLengthening(SimulationContext& ctx, RouteModel model);
89
90// ============================================================================
91// Routing orchestrator
92// ============================================================================
93
101class Router {
102public:
122 void init(SimulationContext& ctx, RouteModel model);
123
147 void acceptedQualityWater(const SimulationContext& ctx, double dt, quality::FvTransportWater& out) const;
148
149 int step(SimulationContext& ctx, double dt, double evap_rate = 0.0,
150 dynwave::DWSolver::NonConduitFlowFunc non_conduit_fn = nullptr);
151
179 void beginCheckpointStep(SimulationContext& ctx, double dt);
207 std::string saveCheckpoint(const SimulationContext& ctx, const std::string& path) const;
222 std::string loadCheckpoint(SimulationContext& ctx, const std::string& path);
223
238 double getAdaptiveStep(SimulationContext& ctx, double fixed_step, double courant);
239
241 const XSectGroups& xsectGroups() const { return groups_; }
242
248 bool hasCycle() const { return cycle_detected_; }
249
260 void setDWNumThreads(int n, std::vector<std::string>* warnings = nullptr) {
261 dw_solver_.setNumThreads(n, warnings);
262 }
263
265 dynwave::DWSolver& dwSolver() { return dw_solver_; }
266
277 void setStructureSolver(hydstruct::StructureSolver* s) { structures_ = s; }
278
279 // Internal water-only conduit window: copy persistent DW history and batch
280 // geometry without retaining pointers into the live router. Checkpoint and
281 // external structure sessions are not part of this transaction profile.
293 std::unique_ptr<Router> privateDynamicWaveWindow() const;
305 void publishDynamicWaveWindow(Router& r) noexcept;
306
314 bool lastStepConverged() const {
315 return (model_ == RouteModel::DYNWAVE) ? dw_solver_.lastConverged() : true;
316 }
317
332
334 bool linkStepStatsEnabled() const { return lstep_enabled_; }
335
350 void accumulateLinkStepStats(SimulationContext& ctx, double dt, bool in_window);
351
360 const fv::INetworkSolver* fvSolver() const { return fv_solver_.get(); }
361
363 const fv::NetworkMeshData& fvMesh() const { return fv_mesh_; }
364
366 const std::string& fvBackend() const { return fv_backend_; }
367
375 const std::vector<std::string>& fvWarnings() const { return fv_warnings_; }
384 const std::vector<std::string>& fvErrors() const { return fv_errors_; }
385
386private:
388 friend class SWMMEngine;
389 struct RestartState;
404 std::string checkpointBytes(const SimulationContext& c, std::string& result) const;
426 std::shared_ptr<RestartState>
427 prepareCheckpointBytes(const SimulationContext& c, std::string bytes,
428 const std::array<double, 6>* boundary = nullptr,
429 const double* delivery = nullptr,
430 const OutfallData* feedback = nullptr) const;
442 static void validateJointDelivery(const NodeData& nodes, const std::vector<uint8_t>& coupled,
443 double delivery);
457 static void validateSessionStorage(const std::shared_ptr<RestartState>& s,
458 const SimulationContext& c, double expected, bool routed);
471 void installCheckpoint(SimulationContext& c, std::shared_ptr<RestartState> s) noexcept;
472 SimulationContext* checkpoint_context_ = nullptr; // non-owning, stable lifetime
473 bool checkpoint_owned_session_ = false; // engine owns structure/control memory
474 bool checkpoint_aquifer_session_ =
475 false; // paired engine/surface recovery owns node-bed receipts
476 std::string checkpoint_model_;
477 double checkpoint_time_ = 0.0, checkpoint_step_end_ = 0.0;
478 bool checkpoint_ready_ = false, checkpoint_prepared_ = false, checkpoint_step_finished_ = false;
491 std::string checkpointModel(const SimulationContext& ctx) const;
504 void checkCheckpointProfile(const SimulationContext& ctx) const;
520 void checkCheckpointStep(SimulationContext& ctx, double dt, double evap_rate, bool callback,
521 bool owned_callback = false);
543 int stepImpl(SimulationContext& ctx, double dt, double evap_rate,
544 dynwave::DWSolver::NonConduitFlowFunc non_conduit_fn, bool owned_callback);
545
547 XSectGroups groups_;
548
551 hydstruct::StructureSolver* structures_ = nullptr;
552
555 std::vector<char> steady_storage_updated_;
558 std::vector<double> steady_y_;
559
560 // --- Explicit finite-volume solver (FLOW_ROUTING FV) -------------------
561 // The mesh and state are owned here, not by the solver, exactly as
562 // SurfaceRouter2D owns MeshData/SurfaceStateData: the solver is swappable
563 // (CPU or Kokkos plugin) and must not own what survives a backend change.
564 fv::NetworkMeshData fv_mesh_;
565 fv::NetworkStateData fv_state_;
566 fv::FvOptions fv_opts_;
567 std::unique_ptr<fv::INetworkSolver> fv_solver_;
568 std::string fv_backend_;
569 std::vector<std::string> fv_warnings_, fv_errors_;
570
571 // Per-conduit time step summary ([REPORT] LINK_STEPS). FV samples arrive
572 // through the solver's sink during advance() and wait here, per link,
573 // until accumulateLinkStepStats keeps or discards them.
574 bool lstep_enabled_ = false;
575 double lstep_rs_ = 0.0;
576 std::vector<double> lstep_pmin_, lstep_pmax_, lstep_pdt_time_, lstep_ptime_, lstep_pbin_;
589 static void fvStepSink(void* user, int conduit, double dt, double dur);
590
591 // Per-step forcing buffers, allocated once at init.
592 std::vector<double> fv_lateral_, fv_fixed_head_, fv_struct_flow_, fv_cond_loss_;
593
598 std::vector<double> fv_link_q_cap_;
599
605 std::vector<double> fv_struct_int_;
606 double fv_struct_t_prev_ = 0.0;
607
622 void initFv(SimulationContext& ctx);
642 int stepFv(SimulationContext& ctx, double dt,
660 void publishFv(SimulationContext& ctx, double dt);
661 kinwave::KWSolver kw_solver_;
662 dynwave::DWSolver dw_solver_;
663 // Divider data moved to ctx.node_subtypes.dividers (relational side-table).
664 std::vector<int> steady_sorted_links_;
665 bool cycle_detected_ = false;
666
683 void initNodeFlows(SimulationContext& ctx, double dt, double evap_rate);
684
701 void computeConduitLosses(SimulationContext& ctx, double dt, double evap_rate);
702
717 void refreshFvBoundaryFlows(SimulationContext& ctx, double t_elapsed,
718 const std::function<void()>& eval_structures);
719
731 void accumulateStructureFlows(const SimulationContext& ctx, double t_now);
732
744 void updateLinkStates(SimulationContext& ctx);
745
762 int executeSteadyFlow(SimulationContext& ctx, double dt);
763};
764
765} // namespace openswmm
766
767#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:101
void enableCheckpointing(SimulationContext &ctx)
Attach the internal accepted-boundary hydraulic checkpoint profile at initial time.
Definition RoutingCheckpoint.cpp:1106
std::string saveCheckpoint(const SimulationContext &ctx, const std::string &path) const
Serialize and publish an accepted internal hydraulic checkpoint file.
Definition RoutingCheckpoint.cpp:1188
double getAdaptiveStep(SimulationContext &ctx, double fixed_step, double courant)
Select an outer routing interval from the active model telemetry.
Definition Routing.cpp:677
friend class SWMMEngine
Definition Routing.hpp:388
std::unique_ptr< Router > privateDynamicWaveWindow() const
Create private DW numerical history/group scratch for a restricted internal routing trial.
Definition Routing.cpp:544
const fv::INetworkSolver * fvSolver() const
Borrow the currently owned FV backend interface.
Definition Routing.hpp:360
void accumulateLinkStepStats(SimulationContext &ctx, double dt, bool in_window)
Keep or discard the just-completed interval conduit-step report samples.
Definition Routing.cpp:751
void publishDynamicWaveWindow(Router &r) noexcept
Exchange accepted private DW history and grouped scratch into this router.
Definition Routing.cpp:563
void beginCheckpointStep(SimulationContext &ctx, double dt)
Reserve the next chronological tracked routing boundary before preparation mutates state.
Definition RoutingCheckpoint.cpp:1119
void acceptCheckpointBoundary(SimulationContext &ctx)
Validate and accept a fully postprocessed tracked step at its advanced clock.
Definition RoutingCheckpoint.cpp:1149
void setStructureSolver(hydstruct::StructureSolver *s)
Attach the borrowed structure-equation provider for tree routing.
Definition Routing.hpp:277
void setDWNumThreads(int n, std::vector< std::string > *warnings=nullptr)
Configure the owned dynamic-wave solver worker count.
Definition Routing.hpp:260
dynwave::DWSolver & dwSolver()
Access the DW solver (for non-conduit node state scatter).
Definition Routing.hpp:265
bool enableLinkStepStats(SimulationContext &ctx)
Enable conduit-step reporting when the selected solver can provide it.
Definition Routing.cpp:713
const XSectGroups & xsectGroups() const
Access the shape-grouped xsect manager.
Definition Routing.hpp:241
const std::vector< std::string > & fvErrors() const
Borrow accumulated FV mesh initialization errors.
Definition Routing.hpp:384
void init(SimulationContext &ctx, RouteModel model)
Initialize routing groups, solver state and the selected model dispatch.
Definition Routing.cpp:323
const fv::NetworkMeshData & fvMesh() const
The FV mesh built at init (empty unless FLOW_ROUTING FV).
Definition Routing.hpp:363
bool hasCycle() const
Report the topological cycle diagnostic from the most recent initialization.
Definition Routing.hpp:248
bool lastStepConverged() const
Report the selected routing model legacy convergence statistic.
Definition Routing.hpp:314
int step(SimulationContext &ctx, double dt, double evap_rate=0.0, dynwave::DWSolver::NonConduitFlowFunc non_conduit_fn=nullptr)
Definition Routing.cpp:539
bool linkStepStatsEnabled() const
Whether enableLinkStepStats() succeeded.
Definition Routing.hpp:334
std::string loadCheckpoint(SimulationContext &ctx, const std::string &path)
Validate a stored hydraulic checkpoint privately, then install its selected state.
Definition RoutingCheckpoint.cpp:1298
void acceptedQualityWater(const SimulationContext &ctx, double dt, quality::FvTransportWater &out) const
Dispatch one prepared hydraulic routing interval and publish its current state.
Definition Routing.cpp:2254
const std::string & fvBackend() const
Backend label chosen by the FV factory ("cpu (...)", "omp (...)", ...).
Definition Routing.hpp:366
const std::vector< std::string > & fvWarnings() const
Borrow accumulated FV initialization warnings.
Definition Routing.hpp:375
void restoreFvClassicState(SimulationContext &ctx)
Definition Routing.cpp:2333
Shape-grouped cross-section manager for batch computation.
Definition XSectBatch.hpp:447
Dynamic wave solver — operates on entire link/node system.
Definition DynamicWave.hpp:218
std::function< void(SimulationContext &, double, int)> NonConduitFlowFunc
Definition DynamicWave.hpp:258
Abstract time integrator for the explicit FV 1D network.
Definition INetworkSolver.hpp:135
Definition HydStructures.hpp:201
Kinematic wave solver state.
Definition KinematicWave.hpp:176
Top-level orchestrator for the 2D surface routing module.
Definition SurfaceRouter2D.hpp:86
EXTERN int RouteModel
Definition globals.h:82
Definition ExchangeLaw.hpp:60
Definition ExchangeLaw.hpp:60
void applyConduitLengthening(SimulationContext &ctx, RouteModel model)
Refresh routing lengths and apply dynamic-wave/FV Courant lengthening.
Definition Routing.cpp:153
@ FV
Explicit conservative finite volume (Godunov, HLL/HLLC)
Definition SimulationOptions.hpp:81
@ KINWAVE
Kinematic wave approximation.
Definition SimulationOptions.hpp:79
@ STEADY
Steady-state (no routing)
Definition SimulationOptions.hpp:78
@ DYNWAVE
Dynamic wave (full Saint-Venant, implicit Picard)
Definition SimulationOptions.hpp:80
RouteModel
Definition Routing.hpp:66
@ DYNWAVE
Dynamic wave (St. Venant, implicit Picard)
Definition Routing.hpp:69
Structure-of-Arrays storage for all nodes.
Definition NodeData.hpp:125
Dense SoA for outfall boundary-condition properties (one row per OUTFALL).
Definition NodeSubtypes.hpp:273
Definition RoutingCheckpoint.cpp:462
Central, reentrant simulation context.
Definition SimulationContext.hpp:390
Knobs for FLOW_ROUTING FV.
Definition FvOptions.hpp:123
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
Definition FvTransportWater.hpp:7