OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
DynamicWave.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
43
44#ifndef OPENSWMM_DYNAMIC_WAVE_HPP
45#define OPENSWMM_DYNAMIC_WAVE_HPP
46
47#include "XSectBatch.hpp"
48#include "../core/Constants.hpp"
50#include "../data/NodeData.hpp"
51#include "../data/LinkData.hpp"
52#include <cstdint>
53#include <functional>
54#include <string>
55#include <vector>
56
57namespace openswmm {
58
60class Router;
61
62namespace dynwave {
63
64// ============================================================================
65// Constants — imported from global Constants.hpp
66// ============================================================================
67
78
79// ============================================================================
80// Dynamic Preissmann Slot (DPS) configuration and per-link state
81// Sharior, Hodges & Vasconcelos (2023), J. Hydraul. Eng. 149(11)
82// ============================================================================
83
85struct DPSConfig {
86 double c_pT = 25.0;
87 double alpha = 3.0;
88 double r = 0.5;
89 double c_pT_sq = 625.0;
90};
91
104 std::vector<double> As;
105 std::vector<double> hs;
106 std::vector<double> hs_prev_iter;
107 std::vector<double> P;
108 std::vector<double> P_hat;
109 std::vector<double> P_hat_0;
110 std::vector<double> T_s_target;
111 std::vector<double> t_s;
112 std::vector<uint8_t> surcharged;
113
124 void resize(std::size_t n) {
125 As.assign(n, 0.0);
126 hs.assign(n, 0.0);
127 hs_prev_iter.assign(n, 0.0);
128 P.assign(n, 1.0);
129 P_hat.assign(n, 1.0);
130 P_hat_0.assign(n, 1.0);
131 T_s_target.assign(n, 0.0);
132 t_s.assign(n, 0.0);
133 surcharged.assign(n, 0);
134 }
135};
136
137// ============================================================================
138// Per-node extended state for DW iterations
139// ============================================================================
140
144 std::vector<double> new_surf_area;
145 std::vector<double> old_surf_area;
146 std::vector<double> sumdqdh;
147 std::vector<double> dYdT;
148 std::vector<double> conduit_loss;
149 std::vector<double> loss_factor;
150 std::vector<uint8_t> converged;
151 std::vector<uint8_t> is_surcharged;
152
162 void resize(std::size_t n) {
163 new_surf_area.assign(n, 0.0);
164 old_surf_area.assign(n, 0.0);
165 sumdqdh.assign(n, 0.0);
166 dYdT.assign(n, 0.0);
167 conduit_loss.assign(n, 0.0);
168 loss_factor.assign(n, 1.0);
169 converged.assign(n, 0);
170 is_surcharged.assign(n, 0);
171 }
172};
173
174// ============================================================================
175// DW solver — batch-oriented
176// ============================================================================
177
182enum class SurchargeMethod : int {
183 EXTRAN = 0,
184 SLOT = 1,
186 2,
187 TPA = 3
191};
192
209
218class DWSolver {
219public:
238 void init(int n_nodes, int n_links, const XSectGroups& groups, const SimulationContext& ctx);
239
254 void setNumThreads(int n, std::vector<std::string>* warnings = nullptr);
255
258 using NonConduitFlowFunc = std::function<void(SimulationContext&, double, int)>;
259
284 int execute(SimulationContext& ctx, double dt, NonConduitFlowFunc non_conduit_fn = nullptr);
285
294 bool lastConverged() const { return last_converged_; }
295
313 double getRoutingStep(SimulationContext& ctx, double fixed_step, double courant_factor);
314
328 void accumulateLinkStepStats(SimulationContext& ctx, double dt, double fixed_step,
329 double courant_factor) const;
330
333 double omega = OMEGA;
336 bool anderson_accel = false;
337
343 double uf_k3 = 0.015;
344
348 double tpa_celerity = 100.0;
349
359 std::vector<int> uf_nb_up_, uf_nb_dn_;
360 std::vector<int8_t> uf_sg_up_, uf_sg_dn_;
361
364 double evap_rate = 0.0;
365
366private:
367 friend class ::openswmm::Router; // explicit internal checkpoint fields only
368 int n_nodes_ = 0;
369 int n_links_ = 0;
370 int n_conduits_ = 0;
371 int num_threads_ = 1;
372 const XSectGroups* groups_ = nullptr;
373
377 bool any_conduit_seep_ = false;
378
383 bool losses_all_zero_ = true;
384
385 // Pre-built conduit index list for skipping non-conduits in inner loops
386 std::vector<int> conduit_idx_;
387
388 // Pre-computed per-link invariants (populated once at first execute, reused)
389 // Using uint8_t instead of bool to allow .data() pointer access for SIMD/restrict
390 std::vector<uint8_t> is_open_;
391 std::vector<uint8_t> is_force_main_;
392 std::vector<uint8_t> has_losses_;
393 std::vector<double> barrels_d_;
394 std::vector<double> cached_length_;
395 std::vector<double> inv_length_;
396
397 // ------------------------------------------------------------------------
398 // Phase A — Conduit-dense "hot tile" of timestep-invariant data.
399 //
400 // Sized n_conduits_, accessed by ci (0..n_conduits_-1) for dense linear
401 // memory access pattern. This replaces sparse `links.X[uj]` /
402 // `nodes.X[un]` reads inside the Picard inner loops, where uj/un are
403 // sparse-indexed via conduit_idx_ + links.node1/node2. Each ci-indexed
404 // read maps to one contiguous cache line that holds 8+ conduits' data,
405 // versus the sparse pattern where each uj read can miss into a new line.
406 //
407 // All fields below are populated once in init() (or refreshConduitTile
408 // when a hot-start changes invariants) and remain constant for the rest
409 // of the simulation. None of these change per Picard iter, per
410 // timestep, or per outfall update.
411 // ------------------------------------------------------------------------
412 std::vector<int> tile_uj_;
417 std::vector<int> tile_crow_;
418 std::vector<int> tile_n1_;
419 std::vector<int> tile_n2_;
420 std::vector<double> tile_inv1_elev_;
421 std::vector<double> tile_inv2_elev_;
422 std::vector<double> tile_z1_off_;
423 std::vector<double> tile_z2_off_;
424 std::vector<double> tile_y_full_;
425 std::vector<double> tile_a_full_;
426 std::vector<double> tile_r_full_;
427 std::vector<double> tile_w_max_;
428 std::vector<double>
429 tile_length_;
430 std::vector<double> tile_inv_length_;
431 std::vector<double>
432 tile_links_length_;
433 std::vector<double> tile_beta_;
434 std::vector<double> tile_q_max_;
435 std::vector<double> tile_rough_factor_;
436 std::vector<double> tile_barrels_d_;
437 std::vector<uint8_t> tile_is_open_;
438 std::vector<uint8_t> tile_is_force_main_;
439 std::vector<uint8_t> tile_is_closed_;
440 std::vector<uint8_t> tile_has_losses_;
441 std::vector<int> tile_xsect_batch_shape_;
442 std::vector<XsectShape> tile_shape_;
449 std::vector<uint8_t> tile_has_offset_;
454 std::vector<int> tile_uj_to_ci_;
457 std::vector<int> tile_culvert_code_;
458 std::vector<double> tile_slope_;
459 std::vector<double> tile_q_limit_;
460 std::vector<double> tile_loss_inlet_;
461 std::vector<double> tile_loss_outlet_;
462 std::vector<double> tile_loss_avg_;
463 std::vector<double> tile_roughness_;
464 std::vector<double>
465 tile_fm_sbot_;
466 std::vector<double>
467 tile_fm_rbot_;
468 std::vector<uint8_t> tile_has_flap_gate_;
469 std::vector<int8_t> tile_direction_;
470
482 void refreshConduitTile(const SimulationContext& ctx);
483
484 // Per-timestep constants
485 double dt_gravity_ = 0.0;
486
487 bool last_converged_ = false;
488
498 double min_surf_area_ = constants::MIN_SURFAREA;
499
500 // Pre-allocated width-capping buffers (avoids thread_local per-call allocation)
501 std::vector<double> wcap_d1_, wcap_d2_, wcap_dm_;
502
503 // Variable timestep state (matching legacy VariableStep in dynwave.c)
504 mutable double variable_step_ = 0.0;
505
506 // Per-node working state (SoA)
507 DWNodeArrays xnode_;
508
509 // Per-link pre-computed geometry (batch-filled by XSectGroups each iteration)
510 std::vector<double> area1_;
511 std::vector<double> area2_;
512 std::vector<double> area_mid_;
513 std::vector<double> hrad_mid_;
514 std::vector<double> width_mid_;
515 std::vector<double> depth1_;
516 std::vector<double> depth2_;
517 std::vector<double> depth_mid_;
518
519 // Per-link momentum working arrays
520 std::vector<double> velocity_;
521 std::vector<double> froude_;
522 std::vector<double> sigma_;
523 std::vector<double> dqdh_;
524 std::vector<double> new_flow_;
528 std::vector<double> q1_;
529
530 // Per-link area from previous iteration (for unsteady term)
531 std::vector<double> area_old_;
532
533 // Per-link bypass flag (true when both end nodes converged; skip momentum solve)
534 // uint8_t instead of bool: avoids std::vector<bool> bit-packing overhead
535 std::vector<uint8_t> bypassed_;
536
537 // ------------------------------------------------------------------------
538 // B2 threading — CSR node→incident-conduit adjacency for the parallel
539 // node-centric flow gather (see gatherConduitNodeFlows). Built once in
540 // init() from static topology.
541 //
542 // PROOF OF BIT-EXACTNESS vs the serial per-link scatter: legacy
543 // findLinkFlows (dynwave.c:385-388) scatters conduits one link at a time
544 // in ascending link index; each link updates node1's accumulators, then
545 // node2's. For a given NODE, the projection of that global order is
546 // simply its incident conduit links in ascending link index (node1-end
547 // entry before node2-end entry when both ends touch the same node). CSR
548 // entries are stored per node in exactly that order, so the per-node
549 // gather performs the identical FP accumulation sequence on each
550 // accumulator (inflow, outflow, sumdqdh, new_surf_area) — bit-exact at
551 // any thread count, since each node is owned by exactly one thread.
552 // ------------------------------------------------------------------------
553 std::vector<int> csr_row_;
554 std::vector<int32_t> csr_link_;
555 std::vector<uint8_t> csr_is_n2_;
556 std::vector<uint8_t> csr_other_outfall_;
557
558 // ------------------------------------------------------------------------
559 // Virtual junctions — zero-storage, momentum-transmitting pair nodes
560 // (see plans/VIRTUAL_JUNCTION_IMPLEMENTATION_PLAN.md). vjunc_ is empty for
561 // models without [VIRTUAL_JUNCTIONS]; every hot-loop hook below is gated
562 // on that emptiness so VJ-free models compile down to the original paths.
563 // ------------------------------------------------------------------------
564 struct VJuncPair {
565 int node = -1;
566 int link_a = -1, link_b = -1;
567 int up_link = -1, dn_link = -1;
568 uint8_t through = 0;
569 double lambda = 0.0;
570
571 // Per-Picard-iteration cache (filled by vjPrepareIteration):
572 double sigma_j = 1.0;
573 double a_up_mid = 0.0;
574 double r_up_mid = 0.0;
575 double dq4j = 0.0;
576 uint8_t active = 0;
577 int8_t dirn = 0;
578
579 // Momentum-residual diagnostic accumulators (whole run):
580 double resid_max = 0.0;
581 double resid_sum = 0.0;
582 long long resid_n = 0;
583 };
584 std::vector<VJuncPair> vjunc_;
588 std::vector<int32_t> vj_pair_n1_;
589 std::vector<int32_t> vj_pair_n2_;
590
599 static constexpr double kVjWetSeedFrac = 0.02;
600 std::vector<double> vj_wet_floor_;
601
613 void buildVirtualJunctionPairs(const SimulationContext& ctx);
627 void vjPrepareIteration(const SimulationContext& ctx, double dt);
638 void vjAccumulateResiduals(SimulationContext& ctx);
639
640 // Node-dense tile of the per-node invariants setNodeDepth touches every
641 // Picard iteration. setNodeDepth reads ~20 SoA arrays per node; the seven
642 // step-invariant ones below otherwise cost seven separate cache streams
643 // (legacy's AoS TNode record pays 1-2 lines per node for the same reads).
644 // Rebuilt once per routing step in execute() — amortised over the Picard
645 // iterations and automatically correct even if the editing API mutates
646 // node geometry mid-run. y_crown pre-evaluates crownElev − invertElev
647 // with the identical operands the per-call subtraction used, so the
648 // value is bit-identical (legacy setNodeDepth recomputes it per call).
649 struct NodeTile {
650 double full_depth;
651 double y_crown;
652 double invert_elev;
653 double ponded_area;
654 double sur_depth;
655 double full_volume;
656 double rpt_full_volume;
657 int32_t degree;
658 uint8_t is_storage;
659 uint8_t is_outfall;
660 uint8_t is_virtual;
661 };
662 std::vector<NodeTile> node_tile_;
663 // Unit system for node volume/surf-area table dispatch, hoisted from the
664 // per-call ucf::getUnitSystem(options.flow_units) (options are fixed
665 // during a run).
666 int unit_sys_ = 0;
667
668 // Per-link surface area contributions to upstream/downstream nodes
669 // (matching legacy Link[].surfArea1/surfArea2 from dwflow.c findSurfArea)
670 std::vector<double> surf_area1_;
671 std::vector<double> surf_area2_;
672
673 // Per-link upstream geometry (for proper weighted hyd. radius)
674 std::vector<double> hrad1_;
675 std::vector<double> width1_;
676 std::vector<double> width2_;
677
678 // Per-link head values (persisted from computeLinkGeometry for solveMomentumBatch,
679 // may be modified by flow classification for UP_CRITICAL/DN_CRITICAL cases)
680 std::vector<double> h1_;
681 std::vector<double> h2_;
682 std::vector<double> fasnh_;
683
684 // Anderson acceleration state (per-node, depth-2 mixing)
685 std::vector<double> aa_y_prev_;
686 std::vector<double> aa_g_prev_;
687 std::vector<double> aa_r_prev_;
688 std::vector<uint8_t> aa_skip_;
689
690 // Per-conduit momentum category (rebuilt each Picard iteration).
691 // solveMomentumBatch dispatches on category_[uj] inline — no auxiliary
692 // per-category index list is needed.
693 std::vector<MomentumCategory> category_;
694
695 // Internal methods
709 void initNodeStates(SimulationContext& ctx);
721 void findBypassedLinks(const SimulationContext& ctx);
737 void computeLinkGeometry(SimulationContext& ctx);
756 void recomputeConduitLossOne(SimulationContext& ctx, double dt, int ci);
757
759 void limitConduitLosses(SimulationContext& ctx, double dt);
776 void momentumKernels(SimulationContext& ctx, double dt, int step);
777
794 void processDryLink(SimulationContext& ctx, double dt, std::size_t uj);
816 void processManningLink(SimulationContext& ctx, double dt, int step, std::size_t uj,
817 MomentumCategory cat);
847 void traceLinkTerms(const SimulationContext& ctx, std::size_t uj, double qLast, double v,
848 double sig, double rho, double aWtd, double rWtd, double dq1, double dq2,
849 double dq3, double dq4, double dq5, double dq6, double qOld, double q,
850 double aMidConv);
869 void processForceMainLink(SimulationContext& ctx, double dt, int step, std::size_t uj,
870 MomentumCategory cat);
896 void applyFlowLimits(SimulationContext& ctx, double dt, int step, std::size_t uj, double& q,
897 double qLast, double barrels_d, bool isFull);
912 void updateNodeFlows(SimulationContext& ctx);
923 void buildConduitNodeCSR(const SimulationContext& ctx);
937 void gatherConduitNodeFlows(SimulationContext& ctx);
949 void computeAASkipFlags(const SimulationContext& ctx);
968 void updateNodeDepthsTeam(SimulationContext& ctx, double dt, int step, int& unconv_shared);
987 void setNodeDepth(SimulationContext& ctx, int node_idx, double dt, int step);
1007 void commitNodeDepthState(SimulationContext& ctx, int node_idx, double y_new, double dV,
1008 double dt);
1023 double getLinkStep(const SimulationContext& ctx, int link_idx) const;
1024
1025public:
1034 bool isInitialized() const noexcept { return !xnode_.sumdqdh.empty(); }
1035
1045 uint8_t& nodeSurchargedFlag(int idx) {
1046 return xnode_.is_surcharged[static_cast<std::size_t>(idx)];
1047 }
1048
1058 double* nodeNewSurfAreaDataMut() { return xnode_.new_surf_area.data(); }
1059
1070 bool isBypassed(int j) const {
1071 const auto uj = static_cast<std::size_t>(j);
1072 return uj < bypassed_.size() && bypassed_[uj] != 0;
1073 }
1074
1084 double& nodeSumDqdh(int n) { return xnode_.sumdqdh[static_cast<std::size_t>(n)]; }
1085
1099 void setNodeDepthForTest(SimulationContext& ctx, int node_idx, double dt, int step) {
1100 setNodeDepth(ctx, node_idx, dt, step);
1101 }
1102
1104 const std::vector<uint8_t>& aaSkipFlags() const { return aa_skip_; }
1105
1107 const DPSLinkArrays& dpsState() const { return dps_; }
1109 const DPSConfig& dpsConfig() const { return dps_config_; }
1111 DPSLinkArrays& dpsStateMut() { return dps_; }
1112
1113private:
1114 // Preissmann slot helpers (matching legacy dwflow.c)
1128 double getSlotWidth(double y, double y_full, double w_max, XsectShape shape) const;
1133 double getCrownCutoff() const;
1134
1135 // Dynamic Preissmann Slot (DPS) state and methods
1136 DPSConfig dps_config_;
1137 DPSLinkArrays dps_;
1138 double sim_time_ = 0.0;
1139
1152 void applyDPSGeometry(SimulationContext& ctx);
1153
1154 // -- TPA (SurchargeMethod::TPA, issue #156 Phase 5) ----------------------
1156 std::vector<double> tpa_w_;
1161 std::vector<uint8_t> tpa_latch_;
1163 std::vector<uint8_t> tpa_latch_changed_;
1164
1177 void updateTpaLatch(SimulationContext& ctx);
1178
1191 void applyTpaGeometry(SimulationContext& ctx);
1192
1204 void updateDPSState(SimulationContext& ctx, double dt);
1205
1217 void spatialSmoothP(const SimulationContext& ctx);
1218};
1219
1220} // namespace dynwave
1221} // namespace openswmm
1222
1223#endif // OPENSWMM_DYNAMIC_WAVE_HPP
Global physical, numerical, and model constants for OpenSWMM Engine.
Structure-of-Arrays (SoA) storage for all node types.
Simulation options parsed from the [OPTIONS] section.
Cross-section geometry — unified batch + per-element API.
Top-level routing orchestrator.
Definition Routing.hpp:101
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
double tpa_celerity
Definition DynamicWave.hpp:348
double evap_rate
Definition DynamicWave.hpp:364
std::vector< int > uf_nb_dn_
Definition DynamicWave.hpp:359
void setNumThreads(int n, std::vector< std::string > *warnings=nullptr)
Set the number of OpenMP threads for parallel loops.
Definition DynamicWave.cpp:1294
SurchargeMethod surcharge_method
Definition DynamicWave.hpp:334
void init(int n_nodes, int n_links, const XSectGroups &groups, const SimulationContext &ctx)
Allocate and initialize dynamic-wave working state for a resolved network.
Definition DynamicWave.cpp:540
double uf_k3
Brunone-type k3; consumed only when active.
Definition DynamicWave.hpp:343
bool isBypassed(int j) const
Check whether a link holds its previous Picard flow/geometry this iteration.
Definition DynamicWave.hpp:1070
DPSLinkArrays & dpsStateMut()
Mutable access to DPS state for tests that need to seed slot conditions.
Definition DynamicWave.hpp:1111
std::vector< int8_t > uf_sg_up_
Definition DynamicWave.hpp:360
std::vector< int > uf_nb_up_
Definition DynamicWave.hpp:359
const DPSLinkArrays & dpsState() const
Read-only access to DPS per-conduit state arrays (for tests/diagnostics).
Definition DynamicWave.hpp:1107
bool lastConverged() const
Report the final Picard convergence flag from the most recent execute.
Definition DynamicWave.hpp:294
double head_tol
Definition DynamicWave.hpp:331
void accumulateLinkStepStats(SimulationContext &ctx, double dt, double fixed_step, double courant_factor) const
Record convergence and timestep summaries for conduit reporting.
Definition DynamicWave.cpp:4868
int unsteady_friction
Definition DynamicWave.hpp:342
NodeContinuity node_continuity
Definition DynamicWave.hpp:335
const DPSConfig & dpsConfig() const
Read-only access to DPS configuration (for tests/diagnostics).
Definition DynamicWave.hpp:1109
bool anderson_accel
Enable Anderson acceleration.
Definition DynamicWave.hpp:336
double omega
Definition DynamicWave.hpp:333
int execute(SimulationContext &ctx, double dt, NonConduitFlowFunc non_conduit_fn=nullptr)
Advance one dynamic-wave routing interval through the bounded Picard loop.
Definition DynamicWave.cpp:1326
std::vector< int8_t > uf_sg_dn_
+1 same sense, -1 opposed
Definition DynamicWave.hpp:360
double & nodeSumDqdh(int n)
Borrow mutable node flow/head sensitivity accumulation.
Definition DynamicWave.hpp:1084
uint8_t & nodeSurchargedFlag(int idx)
Borrow mutable per-node surcharge diagnostic state.
Definition DynamicWave.hpp:1045
void setNodeDepthForTest(SimulationContext &ctx, int node_idx, double dt, int step)
Apply the private continuity update directly for a test fixture.
Definition DynamicWave.hpp:1099
double * nodeNewSurfAreaDataMut()
Borrow writable per-node Picard surface-area accumulation storage.
Definition DynamicWave.hpp:1058
int max_trials
Definition DynamicWave.hpp:332
double getRoutingStep(SimulationContext &ctx, double fixed_step, double courant_factor)
Compute the next native routing interval from link/node/virtual-pair constraints.
Definition DynamicWave.cpp:4664
std::function< void(SimulationContext &, double, int)> NonConduitFlowFunc
Definition DynamicWave.hpp:258
const std::vector< uint8_t > & aaSkipFlags() const
Access per-node AA skip flags (read-only, for testing/diagnostics).
Definition DynamicWave.hpp:1104
bool isInitialized() const noexcept
Check whether the node head-sensitivity working array is nonempty.
Definition DynamicWave.hpp:1034
constexpr double MIN_SURFAREA
Definition Constants.hpp:95
constexpr double DEFAULT_HEAD_TOL
Definition Constants.hpp:128
constexpr double FUDGE
Definition Constants.hpp:91
constexpr double EXTRAN_CROWN_CUTOFF
Definition Constants.hpp:144
constexpr double MAX_VELOCITY
Definition Constants.hpp:136
constexpr double SLOT_WIDTH_FACTOR
Preissmann slot width factor (slot_width = y_full * this factor).
Definition Constants.hpp:150
constexpr double OMEGA
Definition Constants.hpp:124
constexpr int DEFAULT_MAX_TRIALS
Definition Constants.hpp:132
constexpr double MIN_TIMESTEP
Definition Constants.hpp:140
constexpr double SLOT_CROWN_CUTOFF
Preissmann slot crown cutoff fraction.
Definition Constants.hpp:147
Definition DynamicWave.cpp:127
constexpr double DEFAULT_HEAD_TOL
Definition Constants.hpp:128
constexpr double OMEGA
Definition Constants.hpp:124
constexpr int DEFAULT_MAX_TRIALS
Definition Constants.hpp:132
SurchargeMethod
Surcharge method: EXTRAN (classic) or SLOT (Preissmann).
Definition DynamicWave.hpp:182
@ SLOT
Preissmann slot — fictitious narrow slot above crown.
Definition DynamicWave.hpp:184
@ TPA
Definition DynamicWave.hpp:187
@ DYNAMIC_SLOT
Dynamic slot — slot width varies with flow conditions (experimental) Sharior, S., Hodges,...
Definition DynamicWave.hpp:185
@ EXTRAN
Classic EXTRAN approach — dQ/dH for surcharged nodes.
Definition DynamicWave.hpp:183
MomentumCategory
Momentum category for branch-free per-category kernel dispatch.
Definition DynamicWave.hpp:200
@ MANNING_OPEN
Standard Manning, open channel (Froude-based sigma)
Definition DynamicWave.hpp:202
@ MANNING_CLOSED_FULL
Manning, closed conduit, surcharged (fr=0, sig=0)
Definition DynamicWave.hpp:204
@ FORCE_MAIN_HW
Force main, Hazen-Williams friction.
Definition DynamicWave.hpp:205
@ FORCE_MAIN_DW
Force main, Darcy-Weisbach friction.
Definition DynamicWave.hpp:206
@ MANNING_CLOSED_FS
Manning, closed conduit, free surface.
Definition DynamicWave.hpp:203
@ N_CATEGORIES
Definition DynamicWave.hpp:207
@ SKIP_DRY
DRY/UP_DRY/DN_DRY, aMid<=FUDGE, or is_closed.
Definition DynamicWave.hpp:201
Definition Node.cpp:38
Definition ExchangeLaw.hpp:60
NodeContinuity
Node continuity formulation for depth update.
Definition SimulationOptions.hpp:145
@ EXPLICIT
Classic explicit two-branch (default)
Definition SimulationOptions.hpp:146
XsectShape
Conduit cross-section shape code.
Definition LinkData.hpp:64
double * y
Definition odesolve.c:37
Central, reentrant simulation context.
Definition SimulationContext.hpp:390
DPS configuration parameters (derived from SimulationOptions at init).
Definition DynamicWave.hpp:85
double alpha
Surcharge shock parameter (>= 2)
Definition DynamicWave.hpp:87
double c_pT_sq
c_pT^2 (pre-computed)
Definition DynamicWave.hpp:89
double c_pT
Target pressure celerity (ft/s, internal units)
Definition DynamicWave.hpp:86
double r
Decay time scale for P → 1 (seconds)
Definition DynamicWave.hpp:88
Definition DynamicWave.hpp:143
std::vector< double > loss_factor
Affordable fraction of conduit loss.
Definition DynamicWave.hpp:149
std::vector< double > dYdT
Definition DynamicWave.hpp:147
std::vector< double > old_surf_area
Surface area from last non-surcharged state.
Definition DynamicWave.hpp:145
std::vector< double > conduit_loss
Incident net conduit loss (cfs)
Definition DynamicWave.hpp:148
std::vector< double > new_surf_area
Definition DynamicWave.hpp:144
void resize(std::size_t n)
Reset per-node Picard geometry, derivative and convergence state.
Definition DynamicWave.hpp:162
std::vector< uint8_t > is_surcharged
TRUE when node depth > crown elevation.
Definition DynamicWave.hpp:151
std::vector< double > sumdqdh
Definition DynamicWave.hpp:146
std::vector< uint8_t > converged
Definition DynamicWave.hpp:150