39#ifndef OPENSWMM_ENGINE_FV_EXPLICIT_FV_SOLVER_HPP
40#define OPENSWMM_ENGINE_FV_EXPLICIT_FV_SOLVER_HPP
53struct SpeciesKernelView;
68 double advance(
double t_current,
double t_target,
76 RunStats
run_stats() const noexcept override;
79 if (div_link_ < 0)
return false;
89 const std::vector<double>&
node_exchange() const noexcept {
return node_exch_; }
103 return inlet_control_;
163 return tier_occupancy_;
168 void refreshDepths();
169 void refreshNodeAreas();
170 void rebuildActiveLists();
177 double censusDt(
bool press_edit =
false)
const;
178 void reconstructState();
179 void computeFaceFlux(
int face);
183 void reconstructScalars(
double dt);
185 void computeFluxes();
186 void limitPositivity(
double dt);
199 void relaxNodeFluxes(
double dt,
const FvStepForcing& forcing);
225 void settleAlgebraicNode(
int node,
double carry);
229 std::vector<std::uint8_t> node_alg_;
232 std::vector<std::uint8_t> node_pass_static_;
238 std::vector<std::uint8_t> node_pass_;
245 std::vector<std::uint8_t> node_pub_static_;
246 std::vector<std::uint8_t> node_pub_;
250 std::vector<double> node_carry_;
259 std::vector<double> cell_qlat_;
260 std::vector<std::uint8_t> node_lat_div_;
262 std::size_t un)
const noexcept {
263 if (!node_lat_div_.empty() && node_lat_div_[un])
return 0.0;
264 return forcing.node_lateral ? forcing.node_lateral[un] : 0.0;
286 std::vector<double> face_a_rim_;
287 std::vector<double> face_lat_spill_;
288 double injectDivertedLateral(std::size_t uc,
double a_new,
double dt,
290 void bookLateralSpills(
const std::vector<int>* nodes);
292 std::vector<double> node_vfull_;
298 bool algebraicActive(
int n)
const noexcept {
299 const auto un =
static_cast<std::size_t
>(n);
300 if (!node_alg_[un])
return false;
302 state_->
node_volume[un] > node_vfull_[un])
return false;
311 bool incidentPressurized(std::size_t un)
const noexcept {
313 p < mesh_->node_face_ptr[un + 1]; ++p) {
314 const auto uf =
static_cast<std::size_t
>(
317 : mesh_->face_cr[uf];
319 const auto uc =
static_cast<std::size_t
>(c);
320 if (tpaCell(uc))
return true;
321 const FvGeometry& g =
323 if (!g.is_open && state_->
cell_h[uc] >= g.y_crown)
return true;
327 void updateCells(
double dt,
const FvStepForcing& forcing);
328 void updateNodes(
double dt,
const FvStepForcing& forcing);
329 void dispersionSolve(
double dt);
337 void refreshStructFlows(
const FvStepForcing& forcing);
338 std::vector<double> node_qstruct_;
348 std::vector<double> node_qdummy_;
353 std::vector<double> dummy_vol_;
363 template <
class ArrivedFn>
364 void refreshDummyFlows(
double dt,
const FvStepForcing& forcing,
365 ArrivedFn&& arrived);
370 double nodeQDummy(std::size_t un)
const noexcept {
371 return node_qdummy_.empty() ? 0.0 : node_qdummy_[un];
374 double nodeDepthFromVolume(
int node,
double volume)
const;
396 bool ltsEligible() const noexcept {
399 state_ && state_->n_species == 0;
402 bool faceIsLive(
int f)
const noexcept {
403 return all_faces_live_ ||
404 (!live_stamp_.empty() &&
405 live_stamp_[
static_cast<std::size_t
>(f)] == live_gen_);
410 std::vector<std::uint32_t> live_stamp_;
411 std::uint32_t live_gen_ = 0;
416 bool all_faces_live_ =
true;
452 double algebraicNodeStableDt(
int n)
const noexcept;
454 double frictionFor(
const FvGeometry& g,
double q,
double u,
double h,
466 void applyNodeCapacity(
int node,
double v_prev,
double& vol,
double& depth);
471 double cellStableDt(
int cell)
const;
472 double nodeStableDt(
int node)
const;
477 int assignTiers(
double& dt0);
491 void fireFaces(
const std::vector<int>& faces,
double dt0);
492 void fireCells(
const std::vector<int>& cells,
double dt0,
493 const FvStepForcing& forcing);
494 void fireNodes(
const std::vector<int>& nodes,
double dt0,
495 const FvStepForcing& forcing);
496 void runMacroCycle(
double dt0,
int nsub,
const FvStepForcing& forcing);
502 void settleAccumulators();
510 void takeSubstep(
double dt,
const FvStepForcing& forcing);
516 bool anyPressurizedCell()
const;
520 bool nodePressFolded(
int n)
const;
521 PressurizedView pressView(
const FvStepForcing& forcing);
522 PressurizedHeadSolver press_;
524 bool press_step_ =
false;
531 void rkAverage(
const FvStepForcing& forcing);
539 void faceSide(
int face,
int cell,
int node,
double zstar,
int dir,
540 double u_interior, kernels::FaceState& out,
541 double& i1_unreconstructed,
double& z_side,
542 bool measure_only)
const;
544 NetworkMeshData* mesh_ =
nullptr;
545 NetworkStateData* state_ =
nullptr;
550 const FvStepForcing* forcing_ =
nullptr;
556 std::vector<double> f_mass_, f_mom_, f_sstar_, f_corr_l_, f_corr_r_;
563 std::vector<double> f_phi_l_, f_phi_r_;
566 std::vector<double> f_phi_flux_;
570 std::vector<double> lo_flux_, anti_flux_, td_, anew_, rplus_, rminus_;
575 std::vector<kernels::FaceState> f_state_l_, f_state_r_;
576 std::vector<kernels::FaceFlux> f_flux_;
580 std::vector<double> cell_slope_;
588 std::vector<double> cell_eta_slope_, cell_u_slope_;
595 std::vector<char> cell_ho2_;
599 std::vector<double> cell_eta_;
600 std::vector<double> cell_u_;
606 std::vector<double> uf_grad_;
612 void computeUfGradients(
const std::vector<int>* cells);
616 std::vector<uint8_t> tpa_scratch_;
617 std::vector<uint8_t> save_tpa_;
621 void updateTpaFlags();
624 bool tpaCell(std::size_t uc)
const noexcept {
625 return tpa_ && state_->cell_tpa[uc] != 0;
627 std::vector<double> cell_q_int_;
633 std::vector<double> node_exch_;
634 std::vector<double> node_in_, node_out_;
635 std::vector<double> flood_vol_;
636 std::vector<uint8_t> inlet_control_;
645 std::vector<double> save_cell_a_, save_cell_q_, save_cell_phi_;
646 std::vector<double> save_node_vol_, save_node_head_;
647 std::vector<double> save_exch_, save_in_, save_out_, save_flood_, save_qint_,
653 std::vector<double> rk_cell_a_, rk_cell_q_, rk_cell_phi_;
654 std::vector<double> rk_node_vol_, rk_node_head_;
655 std::vector<double> rk_exch_, rk_in_, rk_out_, rk_flood_, rk_qint_,
657 std::vector<uint8_t> rk_tpa_;
661 static constexpr double kStepAcceptRatio = 0.5;
662 static constexpr int kMaxStepRetries = 8;
671 static constexpr double kMinSubstep = 1.0e-6;
683 static constexpr double kDivergedVelocity = 1000.0;
684 static constexpr double kDivergedDepth = 10000.0;
686 double div_value_ = 0.0;
687 const char* div_what_ =
nullptr;
692 std::vector<int> active_faces_;
693 std::vector<char> cell_active_;
694 std::vector<char> halo_prev_;
695 bool lists_valid_ =
false;
696 int since_rebuild_ = 0;
697 static constexpr int kRebuildInterval = 8;
702 std::vector<std::uint8_t> cell_tier_, face_tier_, node_tier_;
703 std::vector<std::vector<int>> cells_by_tier_, faces_by_tier_, nodes_by_tier_;
710 std::vector<std::vector<int>> due_f_upto_, due_c_upto_, due_n_upto_;
716 bool lts_valid_ =
false;
717 int lts_countdown_ = 0;
718 double lts_dt0_ = 0.0;
719 static constexpr int kRetierEveryCycles = 8;
724 std::vector<double> acc_a_, acc_q_, acc_nvol_;
731 std::array<long, kMaxLtsTiers> tier_occupancy_{};
734 long last_nsteps_ = 0;
735 double last_h_ = 0.0;
736 double suggested_h_ = 0.0;
737 long total_steps_ = 0;
738 long total_flux_ = 0;
740 double sim_time_ = 0.0;
745 mutable long dt_argmin_pressurized_ = 0;
746 mutable long dt_argmin_band_ = 0;
747 mutable long dt_argmin_free_ = 0;
748 mutable long dt_argmin_node_ = 0;
749 double active_sum_ = 0.0;
750 double active_min_ = -1.0;
751 double active_max_ = -1.0;
757 double dt_cache_ = 0.0;
764 double dt_census_ = 0.0;
768 int census_count_ = 0;
Single-source scalar kernels for the explicit FV 1D network solver.
Option struct for the explicit finite-volume 1D network solver.
Backend-neutral interface for the explicit FV 1D network integrator.
SoA storage for the 1D finite-volume network mesh and its state.
Implicit acoustic/slot head update on the pressurized subset (slot program R2a, Strategy E).
ExplicitFvSolver(const ExplicitFvSolver &)=delete
const std::array< long, kMaxLtsTiers > & tier_occupancy() const noexcept
Definition ExplicitFvSolver.hpp:162
int lts_tiers() const noexcept
Definition ExplicitFvSolver.hpp:158
const std::vector< uint8_t > & inlet_control() const noexcept
Definition ExplicitFvSolver.hpp:102
bool is_initialized() const noexcept override
True once initialize() has completed and the solver is ready.
Definition ExplicitFvSolver.hpp:77
const std::vector< double > & node_flood_volume() const noexcept
Per-node flooding VOLUME (ft³) over the last advance().
Definition ExplicitFvSolver.hpp:107
ExplicitFvSolver()=default
long last_num_steps() const noexcept override
Substep count used by the last advance() call.
Definition ExplicitFvSolver.hpp:73
double last_step_size() const noexcept override
Last internal substep size (s).
Definition ExplicitFvSolver.hpp:74
void reinitialize(double t0) override
Reinitialize at t0 after external state edits (hot start, API writes).
Definition ExplicitFvSolver.cpp:240
double nodeVolumeFromDepth(int node, double depth) const
Definition ExplicitFvSolver.cpp:292
bool divergence(Divergence &d) const noexcept override
Definition ExplicitFvSolver.hpp:78
ExplicitFvSolver & operator=(const ExplicitFvSolver &)=delete
RunStats run_stats() const noexcept override
Read cumulative statistics. Default: zeros (backend has no counters).
Definition ExplicitFvSolver.cpp:256
const std::vector< double > & dummy_volume() const noexcept
Definition ExplicitFvSolver.hpp:115
void finalize() override
Release all backend resources.
Definition ExplicitFvSolver.cpp:251
double advance(double t_current, double t_target, const FvStepForcing &forcing) override
Definition ExplicitFvSolver.cpp:3694
const std::vector< std::uint8_t > & node_passthrough() const noexcept
Definition ExplicitFvSolver.hpp:125
double suggested_step() const noexcept override
Definition ExplicitFvSolver.hpp:75
const std::vector< double > & node_exchange() const noexcept
Definition ExplicitFvSolver.hpp:89
const std::vector< double > & node_outflow_volume() const noexcept
Definition ExplicitFvSolver.hpp:98
const std::vector< double > & node_inflow_volume() const noexcept
Definition ExplicitFvSolver.hpp:97
~ExplicitFvSolver() override=default
const std::vector< double > & cell_flow_integral() const noexcept
Definition ExplicitFvSolver.hpp:148
void initialize(NetworkMeshData &mesh, NetworkStateData &state, const FvOptions &opts) override
One-time setup. mesh, state and opts must outlive the solver.
Definition ExplicitFvSolver.cpp:58
const std::vector< std::uint8_t > & node_publish_stage() const noexcept
Definition ExplicitFvSolver.hpp:140
Abstract time integrator for the explicit FV 1D network.
Definition INetworkSolver.hpp:121
Definition ExplicitFvSolver.cpp:25
@ RK2
SSP-RK2 (Heun) — strong-stability-preserving.
Definition FvOptions.hpp:77
Definition ExplicitFvSolver.hpp:52
Knobs for FLOW_ROUTING FV.
Definition FvOptions.hpp:123
Definition INetworkSolver.hpp:53
Definition INetworkSolver.hpp:188
SoA mesh geometry and topology for the FV network solver.
Definition NetworkMeshData.hpp:176
std::vector< int > cell_geom
index into geom
Definition NetworkMeshData.hpp:182
std::vector< int > node_face_idx
face indices
Definition NetworkMeshData.hpp:377
std::vector< int > face_cl
left cell (-1 ⇒ node on the left)
Definition NetworkMeshData.hpp:214
std::vector< uint8_t > node_can_pond
Definition NetworkMeshData.hpp:397
std::vector< int > node_face_ptr
[n_nodes + 1] row pointers
Definition NetworkMeshData.hpp:376
std::vector< FvGeometry > geom
Definition NetworkMeshData.hpp:432
Mutable solver state — the conserved variables and the node volumes.
Definition NetworkMeshData.hpp:489
std::vector< double > cell_h
depth (ft)
Definition NetworkMeshData.hpp:497
std::vector< double > node_volume
stored volume (ft³)
Definition NetworkMeshData.hpp:502
Non-owning view over everything the species kernels read and write.
Definition SpeciesTransportKernels.hpp:96