Repository navigation
Solve SCCSteadyStateProblem; stop routing SteadyStateProblem through a lowering - #178
ChrisRackauckas wants to merge 12 commits into
Conversation
…a lowering DynamicSS and SICNM solve SCCSteadyStateProblem block by block, SSRootfind and nonlinear algorithms through SCCNonlinearProblem(prob); the solution is built on the SCC problem in its compressed layout, and save_idxs selects in that layout (integers or states via variable_index). SteadyStateProblem solves keep the problem's own layout again, fixing SciML#171. Ports the LV, chain, mixed-SCC, resid, save_idxs and eltype cases of SciML#175/SciML#177. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.3 Agent-Model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium Agent-Session: local headless run, log /Users/chrisrackauckas/sandbox/master/green/scc-ssprob/log.txt
… blocks Solving an SCCSteadyStateProblem with save_idxs now builds the solution on a problem whose index provider (SCCSavedStates) lists the saved states in selection order, so sol[s] resolves saved states in any order, unsaved states and observed expressions throw, parameters index as usual, and sol.original is the full solution. LinearProblem blocks are dispatched before the stateless shortcut so 0x0 blocks solve directly; a stateless nonlinear block's residual is evaluated once and must be empty. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.3 Agent-Model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium Agent-Session: local headless run, log /Users/chrisrackauckas/sandbox/master/green/scc-ssprob/fu1/log.txt
…ut cases DynamicSS(Tsit5()) over the layout testset plateaued at a tolerance-sized residual noise floor at the stability-limited step size and flipped between Success and Failure under small perturbations; the L-stable Rodas5P contracts the residual with margin. Documents the save_idxs contract in the SCC docs. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.3 Agent-Model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium Agent-Session: local headless run, log /Users/chrisrackauckas/sandbox/master/green/scc-ssprob/fu1/log.txt
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.3 (change, left uncommitted), Claude Code 2.1.285 (commit) Agent-Model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium Agent-Session: local headless run (SCC stack follow-up 1); committed by local Claude session 3c311569-dda6-4687-bc9f-65febb212c33
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.3 Agent-Model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium Agent-Session: local headless run, log /Users/chrisrackauckas/sandbox/master/green/scc-ssprob/fu2/log.txt
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.3 Agent-Model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium Agent-Session: local headless run, log /Users/chrisrackauckas/sandbox/master/green/scc-ssprob/fu2/log.txt
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.3 Agent-Model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium Agent-Session: local headless run, log /Users/chrisrackauckas/sandbox/master/green/scc-ssprob/fu2/log.txt
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.3 Agent-Model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium Agent-Session: local headless run, log /Users/chrisrackauckas/sandbox/master/green/scc-ssprob/fu2/log.txt
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.3 Agent-Model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium Agent-Session: local headless run, log /Users/chrisrackauckas/sandbox/master/green/scc-ssprob/fu2/log.txt
…ved problems The saved-state view of an SCCSteadyStateProblem forwarded parameter_values but not set_parameter!, so setp on it updated only the top-level parameter object and left unaliased block caches stale: re-solving returned y = 2 while sol.ps[:k] == 3. set_parameter! and finalize_parameters_hook! now forward to the wrapped problem. Building the view indexed state_values(prob) unconditionally, so save_idxs threw MethodError getindex(::Nothing, ...) on all-LinearProblem problems without initial guesses. Such views have uType Nothing and state_values nothing; remaking one with a saved-layout u0 fills the unsaved positions with zeros. remake copied the old state vector and assigned into it, truncating BigFloat replacements to Float64 and throwing on ForwardDiff duals. The expanded state now uses the promoted element type. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.92 Agent-Model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium Agent-Session: local headless run, log /Users/chrisrackauckas/sandbox/master/green/fu/SciML_SteadyStateDiffEq.jl-178-0909/log.txt
New commit 86e034a addresses the three blocking findings from the third independent review (gpt-6.1-sol):
The fix was written by Devin (SWE-2 Fusion, Opus 5.5). A fourth review is queued. 🤖 Posted by an AI agent — harness: Claude Code 2.1.285 · model: claude-opus-5-5 |
Solve-time `u0`/`p` keywords on `SCCSteadyStateProblem`, `SCCNonlinearProblem` and the saved-state view were forwarded into the block solves instead of remaking the problem: nonlinear algorithms silently ignored them, and `DynamicSS`/`SICNM` block solves received full-layout `u0`/`p`, leaving the solution's `prob` reporting stale state and parameter values. Route the keywords through `remake` before dispatch so `u0` is chunked into the blocks, `parameters_alias` is enforced, and the returned solution is expressed on the updated problem. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.92 Agent-Model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium Agent-Session: local headless run, log /Users/chrisrackauckas/sandbox/master/green/fu/SciML_SteadyStateDiffEq.jl-178-1100/log.txt
New commit f278d45 addresses the two blocking findings from the fourth independent review (gpt-6.1-sol):
The new testset "solve-time u0 and p overrides" had 20 passes, 50 failures and 2 errors without the fix, and passes all 102 checks with it. 🤖 Posted by an AI agent — harness: Claude Code 2.1.285 · model: claude-opus-5-5 |
This fixes a failure on the default branch's CI. The diagnosis and the evidence below come from the investigating agent's report; "confirmed by running" and "read in logs" are kept apart there.
Part of a three-PR stack implementing Chris's direction (2026-10-14) to replace the post-solve SCC reversal with an SCC form of SteadyStateProblem stored in the compressed layout: SciMLBase (new type) → ModelingToolkit (constructs it) → SteadyStateDiffEq (solves it). Supersedes #175 and #177; fixes #171. CI on the downstream PRs cannot pass until the upstream ones are released.
SteadyStateDiffEq.jl
Branch
scc-steadystate(on master)a3b9bd1Solve SCCSteadyStateProblem; stop routing SteadyStateProblem through a loweringFiles:
src/solve.jl:__solve_scc_blocksis shared by both SCC types and skips stateless blocks.solve(::SCCSteadyStateProblem, …; save_idxs):DynamicSS/SICNMsolve block byblock;
SSRootfind, a bare solve, or a nonlinear alg go throughSCCNonlinearProblem(prob).save_idxstakes integers or states (resolved viavariable_index).__solve_scc_lowering, thesolve(::SteadyStateProblem, …)interception andthe
SSRootfindlowering branch.Also
src/SteadyStateDiffEq.jl(export),src/algorithms.jl(docstrings),docs/src/index.md(section "SCC-split steady states"),test/qa/qa.jl(reexportlist),
Project.toml(2.18.0 → 2.19.0, SciMLBase3.59, MTK11.46) andtest/scc.jl.test/scc.jlcontains the ported cases fromRestore original state order for SCC steady-state solutions #175 and
Map SCC-lowered steady-state solutions back onto the problem's state (stacked on #173) #177. A shared
layout_cases()provideschain, LV, mix and the observed-
XYsystem. Two testsets loop over it:u/resid=length(prob.u0),u[variable_index],sol[states], observed, resid ≈ 0,save_idxs = [2], plus Map SCC-lowered steady-state solutions back onto the problem's state (stacked on #173) #177's eltype case.sol.prob === prob, compressed layout,sol.u[variable_index(prob, s)] == sol[s], integer and symbolicsave_idxs,original.Block-built
SCCSteadyStateProblems are tested for every algorithm, plussave_idxsandshort-
tspanfailures. LV runs only the nonlinear algorithms (its equilibrium is a center).Before (new
test/scc.jlagainst all-masterenv-before, viascratch/run_scc_before.jl;ssde_scc_before_r2.log):sol.prob isa …,length(sol.u) == length(prob.u0)andlength(sol.resid) == length(prob.u0), i.e. issue solve(::SteadyStateProblem) returns the lowered problem's solution: sol.u reordered/empty, sol.prob.f.sys time-independent #171.UndefVarError: SCCSteadyStateProblem not defined in SciMLBase.dt_epsilon,u[2] = 1.4e47).After (
ssde_scc_r2.log, env-stack):ssde_core_r2.logandssde_sicnm.log: all green. Runic --check and typos: clean.IntegrationTest evidence (SciMLBase
test/downstream/comprehensive_indexing.jl):comprehensive_indexing_before.log):State indexing/Observederror withBoundsError: attempt to access 1-element Vector{Float64} at index [[1, 2]](solve(::SteadyStateProblem) returns the lowered problem's solution: sol.u reordered/empty, sol.prob.f.sys time-independent #171).comprehensive_indexing_after_r2.log): fully green.OptimizationSolutionindexing(
comprehensive_indexing_before_rest.log) also occur on master with the current deps,and pass on env-stack.
Not verified:
GROUP=QA(JET/Aqua/ExplicitImports), the full SSDE suite outsidescc.jl/core.jl/sicnm.jl, and the docs build.Open design questions for Chris
SteadyStateProblem+ nonlinear alg. WithNewtonRaphson()the solution'ssol.probis the convertedNonlinearProblem, as before the lowering existed (onlySSRootfind/DynamicSS/SICNMgivesol.prob isa SteadyStateProblem). The testsencode this. Should SSDE rewrap it? I left it alone because it changes the dispatch
surface that SciMLSensitivity uses.
lowered_problemgo now as SciMLBase4.0 (
scc-steadystate-remove-lowered), or stay deprecated-but-unused in 3.x? The 4.0path needs
SciMLBase = "3.59, 4"compat in MTK/SSDE and in every package that capsSciMLBase below 4.
SCCNonlinearProblem(::SteadyStateProblem)method was a public-ish extension in MTKBase 1.77. I released its removal as a minor
(1.78.0), on the grounds that it was only meaningful with the lowering. A strict reading
makes it a major.
SCCSteadyStateProblem(sys, op)builds a fullSteadyStateProblem(including its initialization problem) only to processop, thencompiles the residual system.
build_initializeprob = falsebreaks hierarchicalinitialization_eqs. Is a lighter op-processing path worth adding?DynamicSS(Tsit5())withthe default
tspan = Infruns out of maxiters before the termination callback fires,even though the ODE is globally stable. A hand-written
SteadyStateProblembehaves thesame, so this is not caused by this change. The tests use
tspan = 100. Worth an SSDEissue?
SteadyStateSolution(=NonlinearSolution) on anSCCSteadyStateProblemcarries the compressed layout throughsol.prob.f.sys, and nodedicated SCC solution type was added. Is that the intended end state?
🤖 Posted by an AI agent — harness: Devin CLI 3000.11.3 (fix), Claude Code 2.1.285 (PR) · model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium / claude-opus-5-5
Conversation: local Claude session 3c311569-dda6-4687-bc9f-65febb212c33 (fleet master)
🤖 Generated with Claude Code
Risk assessment (independent review, Codex gpt-6.1-sol, head e941945)
git diff origin/HEAD...HEAD, upstream type/remake implementation, and all failing-check logs.git diff --check origin/HEAD...HEADpassed; the checkout remained clean. Ran Julia 1.12.4 with four threads, the requested depot path andtimeout 3600, using scratch source copies and SciMLBase prerequisite PR head867dba9a21cbf2e280be419d8b5bc74aa1be70e0.julia --project="$S/env" "$S/head-run.jl"passed all 422 assertions copied unchanged from test/scc.jl's six block-focused testsets (96/24/128/32/102/40). The standalone probes inprobe.jlandprobe-small.jlconfirmed both findings below; selection-array mutation and symbolic parameter-remake probes passed.python3 "$S/run-final-checks.py"ran the same reduced parameter-override test against base and head, then ordinary head dependency resolution: base 0 passed / 2 failed (u=[1], reportedp=[1]); head 2 passed (u=[3], reportedp=[3]); registry resolution failed because available SciMLBase versions end at 3.58.0 while this head requires 3.59. Here$Sis this report's siblingscratchdirectory. G1 pass: analytic equilibria and independent linear-system references; the reduced override regression also uses the analytic rootu=p. G2 not applicable: no GPU kernel, AD-rule, Reactant or MPI implementation is changed; Dual-value preservation is covered by the selected tests. G3 pass: tests exercise parameter propagation and remake isolation, and the caller-selection mutation probe preserved the saved layout.🤖 Posted by an AI agent — harness: Codex CLI 0.162.1 · model: gpt-6.1-sol
Conversation: local headless review run (no public session URL); transcript kept by the fleet master.