[AI prototype] PositiveIntegrators.jl#3083
Draft
visr wants to merge 36 commits into
Draft
Conversation
- Updated the Parameters function to streamline state handling and remove unnecessary variables. - Modified water_balance! to work directly with the full state vector, eliminating the need for reduced state vectors. - Enhanced set_current_basin_properties! to directly use basin storage from the state vector. - Introduced apply_flow_to_basins! to manage flow contributions to basin storage more effectively. - Removed redundant state reduction and flow limit functions, simplifying the flow management logic. - Improved cache handling for flow rates in various node types, ensuring accurate flow tracking. - Updated basin and flow data functions to reflect changes in state handling and removed deprecated variables.
…s massbalance exactly
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
``` [47edcb42] ↑ ADTypes v1.21.0 ⇒ v1.22.0 [a93c6f00] ↑ DataFrames v1.8.1 ⇒ v1.8.2 [82cc6244] ↑ DataInterpolations v8.9.0 ⇒ v8.10.0 [459566f4] ↑ DiffEqCallbacks v4.12.0 ⇒ v4.17.0 [a0c0ee7d] ↑ DifferentiationInterface v0.7.16 ⇒ v0.7.18 [6a86dc24] ↑ FiniteDiff v2.29.0 ⇒ v2.31.0 [c27321d9] ↑ Glob v1.4.0 ⇒ v1.5.0 [87dc4568] ↑ HiGHS v1.22.2 ⇒ v1.23.0 [5903a43b] ↑ Infiltrator v1.9.10 ⇒ v1.9.11 [4076af6c] ↑ JuMP v1.30.0 ⇒ v1.30.1 [7ed4a6bd] ↑ LinearSolve v3.69.0 ⇒ v3.79.0 [d1179b25] ↑ MathOptAnalyzer v0.1.1 ⇒ v0.1.2 [85f8d34a] ↑ NCDatasets v0.14.14 ⇒ v0.14.15 [6ad6398a] ↑ OrdinaryDiffEqBDF v1.23.0 ⇒ v2.1.0 [bbf590c4] ↑ OrdinaryDiffEqCore v3.25.0 ⇒ v4.2.1 [4302a76b] ↑ OrdinaryDiffEqDifferentiation v2.4.0 ⇒ v3.1.1 [1344f307] ↑ OrdinaryDiffEqLowOrderRK v1.11.0 ⇒ v2.1.0 [127b3ac7] ↑ OrdinaryDiffEqNonlinearSolve v1.24.0 ⇒ v2.0.0 [43230ef6] ↑ OrdinaryDiffEqRosenbrock v1.27.0 ⇒ v2.2.0 [2d112036] ↑ OrdinaryDiffEqSDIRK v1.13.0 ⇒ v2.3.0 [b1df2697] ↑ OrdinaryDiffEqTsit5 v1.10.0 ⇒ v2.0.0 [aea7be01] ↑ PrecompileTools v1.3.3 ⇒ v1.3.4 [295af30f] ↑ Revise v3.14.1 ⇒ v3.14.3 [loaded: v3.14.1] [0bca4576] ↑ SciMLBase v2.153.1 ⇒ v3.13.0 [0a514795] ↑ SparseMatrixColorings v0.4.26 ⇒ v0.4.27 ```
|
Hey there @visr, can you explain why the automatic sparse Jacobian capabilities are lost here? Anything I can do to help? |
Also drop older compats.
Member
Author
|
Thanks for the offer @gdalle! I didn't dive into it too much yet, but I think the PDS formulation and algorithms just don't use a Jacobian, but use the production matrix P and D instead to form the linear system. It is just a little test. For future reference, in the first version the basic testmodel is about 1000x slower. The FunctionCallingAffect seems to suddenly dominate, here is a profile: PDS-basic.html |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a little test balloon to check if https://github.com/NumericalMathematics/PositiveIntegrators.jl is worth considering.
It is on top of both #3039 and #3082, relevant commit is ad72990. Still untested, and PID is not yet supported. AI analysis:
What PositiveIntegrators.jl offers
Modified Patankar-Runge-Kutta (MPRK) schemes that unconditionally guarantee positivity of solutions by requiring the ODE to be expressed as a Production-Destruction System (PDS):
Available solvers:
MPE(1st order),MPRK22(2nd, adaptive),MPRK43I/MPRK43II(3rd, adaptive),SSPMPRK22/SSPMPRK43,MPDeC(arbitrary order). All are linearly implicit and integrate with the SciML ecosystem.Current Ribasim approach to positivity
isoutofdomain(util.jl): rejects any step whereu.basin[i] < 0, forcing dt reductionifelse(u.basin[i] > 0, u.basin[i], 0.0)when computing levels/areasNatural fit with Ribasim's architecture
Ribasim's
apply_flow_to_basins!in solve.jl already has PDS semantics:This is precisely a production term$p_{\text{dest},\text{src}} = q$ when $q > 0$ . The water balance is a sum of such pairwise flows plus external sources/sinks — the exact structure a PDS requires.
Sparse matrix support — not a bottleneck
The
p_prototypekeyword inPDSProblemacceptsSparseMatrixCSC. From the linear advection benchmark, sparse +KLUFactorization()achieved a 260x speedup over dense (45.8s → 174ms for N=1000, near-zero allocations).For Ribasim this maps cleanly:
KLUFactorizationfor its implicit solversReformulation effort
Production matrix
P!(P, u, p, t)— ModerateEach flow computation currently ends with
apply_flow_to_basins!(du, q, src, dst). The PDS equivalent:du.basin[dst.idx] += q(q > 0)P[dst.idx, src.idx] = qdu.basin[src.idx] -= q(q > 0)du.basin[dst.idx] += q(q < 0, bidirectional)P[src.idx, dst.idx] = -qP[i, i] += precip(diagonal source)P[i, i] += inflow(diagonal source)Destruction vector
D!(d, u, p, t)— SimpleExternal sinks that leave the system entirely:
d[i] += evaporation[i]d[i] += infiltration[i]Sign-splitting for bidirectional flows — Straightforward
LinearResistance and ManningResistance can flow in either direction based on head difference. At each evaluation:
The sparsity pattern must include both directions for these links.
Key challenges
std_rhsfallback for non-MPRK solvers on the full system while MPRK only sees basin states; (b) operator splitting; (c) shift integral states by an offset to keep them positive (fragile). Best option is likely (a): restructure so PID integrals are handled outside the PDS, e.g. as a separate coupled equation.P!fill; sparsity pattern includes both directions. Cheap.std_rhsfor fallbackwater_balance!— pass it as thestd_rhskeyword so non-MPRK algorithms (QNDF, Rodas5P) still work unchanged.PDSProblem <: AbstractODEProblem— all SciML callbacks work.MPRK22,MPRK43I/II,MPDeCall support adaptive dt.CArray(named-tuple-indexed vector). Need to verify PositiveIntegrators.jl doesn't assume plainVector. Thep_prototypeis only for the P matrix;ushould work if it's<: AbstractVector.What you gain
isoutofdomain, no moreifelseclampinglow_storage_thresholdreduction factor becomes unnecessary for positivity (may still be physically motivated)What you lose / trade off
P!matrix fill (but this is arguably more transparent)std_rhslets you keep them as options.water_balance!logic into production-matrix fill vs. standard RHSImplementation path
Phase 1: Proof of concept (basin-only, no PID)
PositiveIntegratorsto Project.tomlp_prototypesparse matrix from network graph at model constructionribasim_P!(P, u, p, t)andribasim_D!(d, u, p, t)by refactoring the flow formulation logicPDSProblem(...; p_prototype, std_rhs = water_balance!)basicmodel (no PID) withMPRK22(1.0; linsolve = KLUFactorization())Phase 2: Handle PID integral states
std_rhs(only MPRK for basin components). Requires checking if PositiveIntegrators.jl supports partial PDS (likely not out of the box).Phase 3: Performance tuning
MPRK43I/MPDeCfor higher accuracyPhase 4: Full integration
isoutofdomainwhen MPRK is selectedVerdict
The fit is natural. Ribasim's water balance is already structured as pairwise flows between basins + external sources/sinks — exactly a PDS. Sparse matrix support with KLU eliminates the performance concern for large models. The main engineering work is:
water_balance!into aP!/D!matrix-fill form (~moderate effort, same logic restructured)