![]() |
OpenSWMM Engine
6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
|
Plan H6b — bed conduction, deep-ground conduction, and hyporheic exchange, integrated SIMULTANEOUSLY with the surface fluxes. More...
#include "../../../data/BedZoneData.hpp"Go to the source code of this file.
Classes | |
| struct | openswmm::transport::heat::BedCoupling |
| One element's bed coupling, fully reduced to SI conductances. More... | |
| struct | openswmm::transport::heat::PairStep |
| Simultaneous temperature increments for the coupled pair, °C. More... | |
| struct | openswmm::transport::heat::SolutePairStep |
| Simultaneous concentration increments for the coupled pair. More... | |
Namespaces | |
| namespace | openswmm |
| namespace | openswmm::transport |
| namespace | openswmm::transport::heat |
Functions | |
| PairStep | openswmm::transport::heat::relaxPair (const BedCoupling &g, double t_w, double t_b, double j0, double j1, double h, double area_m2, double dt) noexcept |
| One exact step of the coupled (water, bed) pair. | |
| SolutePairStep | openswmm::transport::heat::exchangePair (double c_w, double c_b, double vol_w, double vol_b, double q_exch, double dt) noexcept |
| One exact step of the two-body solute exchange. | |
| BedCoupling | openswmm::transport::heat::bedCouplingForLink (const SimulationContext &ctx, int link, double vol_ft3, double t_gr) noexcept |
| Build a conduit finite-bed pair from current wet perimeter and resolved element material. | |
| BedCoupling | openswmm::transport::heat::bedCouplingFromContact (const SimulationContext &ctx, const SedimentConfig &sc, double bed_m2, double vol_ft3, double t_gr) noexcept |
| Construct finite water/bed conductance and capacity from one SI contact footprint. | |
| double | openswmm::transport::heat::groundTempFor (const SimulationContext &ctx, const SedimentConfig &sc, double t_gr_global) noexcept |
| Choose one element's held deep-ground constant or globally sampled series temperature. | |
| double | openswmm::transport::heat::bedExchangeQ (const SedimentConfig &cfg, double bed_m2) noexcept |
| Compute total finite-bed solute exchange rate from diffusion and hyporheic velocity. | |
| double | openswmm::transport::heat::linkBedAreaM2 (const SimulationContext &ctx, int link) noexcept |
| Compute wetted conduit bed contact area from native geometry. | |
| double | openswmm::transport::heat::linkFreeSurfaceFt2 (const SimulationContext &ctx, int link) noexcept |
| Compute native open-conduit free surface for heat/evaporation binding. | |
| void | openswmm::transport::heat::fillChannelThermalGeometry (const SimulationContext &ctx, ChannelThermalRegion ®ion) noexcept |
| Publish native conduit thermal region geometry in SI. | |
| double | openswmm::transport::heat::groundTemperature (SimulationContext &ctx) noexcept |
| Sample the global held deep-ground temperature at native absolute model time. | |
| bool | openswmm::transport::heat::bedExchangeEnabled (const SimulationContext &ctx) noexcept |
| Test current native finite-bed heat family process enable. | |
| void | openswmm::transport::heat::seedBedTemperature (SimulationContext &ctx) |
| Size and seed native link bed temperatures at their initial owner phase. | |
| void | openswmm::transport::heat::applyBedSoluteExchange (SimulationContext &ctx, double *link_conc, int n_arr, int offset, int n_total, double dt) |
Step every conduit's bed/channel solute exchange for one dt. | |
Plan H6b — bed conduction, deep-ground conduction, and hyporheic exchange, integrated SIMULTANEOUSLY with the surface fluxes.
HeatFluxes.hpp predicted that H6b would be exactly that. It cannot be, for two independent reasons, and both were found by trying:netFluxOut returns W/m² at the FREE SURFACE. Bed exchange acts on the wetted perimeter, which is a different area — and for a closed conduit the free-surface area is zero while the bed area is not. Summing them would multiply the bed flux by the wrong area, and would switch it off entirely in a full pipe.relaxT relaxes one body toward a fixed equilibrium. Two bodies exchanging with each other do not have a fixed equilibrium to relax toward: each one's target moves as the other responds. Treating the bed as a constant- temperature reservoir inside netFluxOut would make a thin bed behave like an infinite heat sink, which is the opposite of what a thin bed does.So H6b adds a coupled stepper rather than a term. D-H5e's rule still holds and is why the stepper is coupled rather than sequential: relaxations do not commute, so the surface families and the bed exchange are solved in ONE step, not one after the other. Doing it sequentially would reintroduce precisely the defect D-H5e removed, one phase after it was removed.
linearized exactly asrelaxT already linearizes it: @code C_w dT_w/dt = -A_s J(T_w) + G_wb (T_b - T_w) C_b dT_b/dt = G_wb (T_w - T_b) + G_bg (T_gr - T_b) @endcode a 2x2 linear systemdu/dt = M u + csolved by its exact matrix exponential,u(dt) = dt * phi1(M dt) * c,phi1(z) = expm1(z)/z`.Both eigenvalues of M are real and non-positive — the discriminant is (a11-a22)^2 + 4 a12 a21 with a12, a21 >= 0, so it can never be negative and the pair can never oscillate. The step therefore cannot overshoot at any dt, which is the property D-H5d bought for the single body and which would have been lost by any explicit coupling.
G_wb cancels identically: C_w dT_w/dt + C_b dT_b/dt = -A_s J + G_bg (T_gr - T_b). Whatever the water loses to the bed, the bed gains. The exchange is therefore conservative BY CONSTRUCTION, not by a bookkeeping step that could be forgotten, and BedExchangeConservesEnergy asserts the identity rather than a tolerance on a ledger.HTSComponent leaves its ground solute exchange commented out (element.cpp:161) and parity keeps it out. Two bodies exchanging with nothing else has a closed form that needs no matrix: the total mass is invariant and the DIFFERENCE decays exponentially. exchangePair uses that form, so conservation is STRUCTURAL — there is no separate bookkeeping step that could be omitted.It is not bit-exact, and the first draft of this file claimed it was. vol_w * dc_w evaluates vol_w * (vol_b * share) while vol_b * dc_b evaluates vol_b * (vol_w * share) — the same factors in a different association, which round differently once share saturates at large dt. The residual is relative round-off, ~1e-16, and the gate asserts that bound rather than equality. Measured, not assumed: a driver over dt in {1, 600, 7200, 1e6} agreed bit for bit on the first three and differed on the fourth.