OpenSWMM Engine  6.0.0-alpha.1
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.1)
Loading...
Searching...
No Matches
ArkodeSurfaceSolver.hpp
Go to the documentation of this file.
1
32
33#ifndef OPENSWMM_ENGINE_2D_ARKODE_SURFACE_SOLVER_HPP
34#define OPENSWMM_ENGINE_2D_ARKODE_SURFACE_SOLVER_HPP
35
36#include "../data/MeshData.hpp"
39#include "ISurfaceSolver.hpp"
40#include "InertialEdges.hpp"
41
42#ifdef OPENSWMM_HAS_2D
43
44#include <vector>
45#include <memory>
46
47// Forward declarations for SUNDIALS types (avoid pulling in full headers)
48struct SUNContext_;
49typedef struct SUNContext_* SUNContext;
50typedef struct _generic_N_Vector* N_Vector;
51typedef struct _generic_SUNLinearSolver* SUNLinearSolver;
52
53namespace openswmm::twoD {
54
55class ArkodeSurfaceSolver;
56#if defined(OPENSWMM_HAVE_HYPRE)
57class HypreAmgPreconditioner; // complete type only in the .cpp (guarded)
58#endif
59
67struct ArkodeSolverContext {
68 MeshData* mesh = nullptr;
69 SurfaceStateData* state = nullptr;
70 SolverOptions2D* opts = nullptr;
71 ArkodeSurfaceSolver* solver = nullptr;
72 bool amg_active = false;
73};
74
78class ArkodeSurfaceSolver : public ISurfaceSolver {
79public:
80 ArkodeSurfaceSolver();
81 ~ArkodeSurfaceSolver() override;
82
83 ArkodeSurfaceSolver(const ArkodeSurfaceSolver&) = delete;
84 ArkodeSurfaceSolver& operator=(const ArkodeSurfaceSolver&) = delete;
85
86 ArkodeSurfaceSolver(ArkodeSurfaceSolver&& o) noexcept;
87 ArkodeSurfaceSolver& operator=(ArkodeSurfaceSolver&& o) noexcept;
88
89 void initialize(MeshData& mesh, SurfaceStateData& state,
90 SolverOptions2D& opts) override;
91
92 double advance(double t_current, double t_target) override;
93
94 void reinitialize(double t0) override;
95
96 void finalize() override;
97
98 long last_num_steps() const noexcept override { return last_nsteps_; }
99
100 double last_step_size() const noexcept override { return last_h_; }
101
102 const std::vector<double>& last_coupling_exchange() const noexcept override {
103 return last_coupling_exchange_;
104 }
105
106 bool is_initialized() const noexcept override { return arkode_mem_ != nullptr; }
107
108private:
109 void* arkode_mem_ = nullptr;
110 SUNLinearSolver ls_ = nullptr;
111 N_Vector y_ = nullptr;
112 N_Vector abstol_ = nullptr;
113 SUNContext sun_ctx_ = nullptr;
114
115 ArkodeSolverContext ctx_;
116
117 long last_nsteps_ = 0;
118 double last_h_ = 0.0;
119
120 // ── Live node-coupling (macro-step) state augmentation ────────────────────
121 // Identical scheme to CvodeSurfaceSolver: when state.node_coupling is set the
122 // state vector grows to nt + nc_; the extra nc_ entries integrate ∫Q_k dt per
123 // coupling point (the conservative 1D↔2D booking). nc_ == 0 ⇒ no augmentation.
124 int nc_ = 0;
125 std::vector<double> coupling_accum_start_;
126 std::vector<double> last_coupling_exchange_;
127
128 // ── Local-inertial momentum (MOMENTUM=inertial) ───────────────────────────
129 // Effective momentum closure, resolved in initialize() (env overrides opts).
130 // When INERTIAL, the state grows to nt + ne_ + nc_: the extra ne_ entries are
131 // the per-edge discharge q (LISFLOOD-FP), integrated implicitly with gravity
132 // + friction. edges_ holds the unique-edge layout + per-cell incidence.
133 MomentumType momentum_ = MomentumType::DW;
134 int ne_ = 0;
135 InertialEdges edges_;
136
137 // Inertial IMEX split. When true (default) the gravity-wave transport
138 // (continuity + surface-gradient) is EXPLICIT and only the stiff per-edge
139 // friction is implicit — the LISFLOOD-FP semi-implicit scheme. The implicit
140 // operator is then diagonal (exact preconditioner, no global solve), so it
141 // scales O(n)/step to 1M cells. When false, gravity is implicit too (the
142 // plan's Schur-coupled scheme) — kept for comparison; needs AMG to scale.
143 // env OPENSWMM_2D_GRAVITY_IMPLICIT selects the false (implicit-gravity) path.
144 bool gravity_explicit_ = true;
145
146 // Block-Jacobi preconditioner scratch for the inertial [V,q] system:
147 // prec_dV_[i] = diagonal of the Schur η-operator at cell i (1 + Σ gravity)
148 // prec_wq_[e] = 1/(1 + γ·R_e), the exact friction-damped q-block diagonal.
149 // Rebuilt in psetup_inertial_fn; applied in psolve_inertial_fn. No global
150 // solve / no AMG ⇒ scales to 1M cells.
151 std::vector<double> prec_dV_;
152 std::vector<double> prec_wq_;
153
155 std::vector<double> precond_diag_;
156
157#if defined(OPENSWMM_HAVE_HYPRE)
158 std::unique_ptr<HypreAmgPreconditioner> amg_precond_;
159#endif
160
161 // ------------------------------------------------------------------
162 // SUNDIALS callbacks (ARKRhsFn / ARKLsPrecSetupFn / ARKLsPrecSolveFn).
163 // The preconditioner signatures match CVODE's verbatim in SUNDIALS 7.
164 // ------------------------------------------------------------------
165
167 static int fe_fn(double t, N_Vector y, N_Vector ydot, void* user_data);
168
170 static int fi_fn(double t, N_Vector y, N_Vector ydot, void* user_data);
171
174 static int fe_inertial_fn(double t, N_Vector y, N_Vector ydot, void* user_data);
175
178 static int fi_inertial_fn(double t, N_Vector y, N_Vector ydot, void* user_data);
179
183 static int psetup_inertial_fn(double t, N_Vector y, N_Vector fy,
184 int jok, int* jcurPtr, double gamma,
185 void* user_data);
186
188 static int psolve_inertial_fn(double t, N_Vector y, N_Vector fy,
189 N_Vector r, N_Vector z,
190 double gamma, double delta, int lr,
191 void* user_data);
192
194 static int psetup_fn(double t, N_Vector y, N_Vector fy,
195 int jok, int* jcurPtr, double gamma,
196 void* user_data);
197
199 static int psolve_fn(double t, N_Vector y, N_Vector fy,
200 N_Vector r, N_Vector z,
201 double gamma, double delta, int lr,
202 void* user_data);
203};
204
205} // namespace openswmm::twoD
206
207#endif // OPENSWMM_HAS_2D
208
209#endif // OPENSWMM_ENGINE_2D_ARKODE_SURFACE_SOLVER_HPP
Backend-neutral interface for the 2D surface-routing time integrator.
Unique interior-edge structure for the local-inertial momentum DOFs.
Structure-of-Arrays (SoA) storage for 2D triangular mesh geometry.
Configuration options for the 2D surface routing solver.
Structure-of-Arrays (SoA) storage for 2D surface routing state.
BoomerAMG preconditioner over the 2D diffusion Newton matrix.
Definition HypreAmgPreconditioner.hpp:42
Abstract time integrator for the 2D surface-routing ODE system.
Definition ISurfaceSolver.hpp:49
Definition NodeCoupling.cpp:15
MomentumType
Surface-momentum closure for the 2D flux.
Definition SolverOptions2D.hpp:97
double * y
Definition odesolve.c:28