Repository navigation
Focus the package on the symbolic array reduced model - #179
Merged
ChrisRackauckas merged 2 commits intoSep 7, 2026
Merged
ChrisRackauckas merged 2 commits into
ChrisRackauckas merged 2 commits into
Conversation
Remove the scalar low-level deim method and the scalarized helpers (get_deqs, only_dvs, _sort_observed_equations), and move the offline analysis into FullOrderModel in src/full_order.jl. Term separation uses the public Symbolics.semilinear_form. deim(prob, sol, k) accepts ODEProblems, and the mtkcompile + ODEProblem path is tested next to the array DAEProblem path. Dispatch on ModelingToolkit.System, drop Setfield and the unused AbstractMORProblem, and document the internal pipeline. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Agent-Harness: Claude Code 2.1.263 (Claude Code) Agent-Model: claude-fable-5-1 Agent-Session: https://claude.ai/code/session_01H5RuLDtEazwTKPkNbPeZVu Claude-Session: https://claude.ai/code/session_01H5RuLDtEazwTKPkNbPeZVu
Store the projected matrices, the distinct symbolic forcing expressions' basis map, the DEIM stencil rows of the state basis, and the DEIM projector as array parameters, so the reduced equation is A*ŷ + g + G*forcing + C*F with only the sampled nonlinear terms scalar. Evaluate the initial derivative numerically from the same projection and add a uniform-forcing graph-size regression. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Agent-Harness: Claude Code 2.1.263 Agent-Model: claude-fable-5-1 Agent-Session: https://claude.ai/code/session_01H5RuLDtEazwTKPkNbPeZVu Claude-Session: https://claude.ai/code/session_01H5RuLDtEazwTKPkNbPeZVu
ChrisRackauckas
marked this pull request as ready for review
September 7, 2026 00:38
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.
Ignore this PR until reviewed by @ChrisRackauckas.
Follow-up to #178. The package is now organized around the symbolic array form of the reduced model: the only symbolic outputs are one array differential equation for the reduced state and one array (or scalar) reconstruction equation per source field. Everything that was left over from the scalarized representation is gone.
What changed
D(ŷ) ~ A*ŷ + g + G*forcing + C*FwhereA = V'AV,g = V'g_numeric,G,C = V'U(P'U)⁻¹, and the stencil rowsV_Sof the state basis are array parameters of the reduced system,forcingis the array of distinct symbolic forcing expressions, andFis the array of DEIM-sampled nonlinear terms written in(V_S*ŷ)[i]. Before,V'*gandprojector*sampledwere evaluated eagerly intokscalar sums, so only the samples themselves (which are inherently scalar) remain scalar. Numeric matrices are parameters rather than literals because a sum of array terms holding literal matrices breaksmtkcompile(isless(::Matrix, ::Matrix)in SymbolicUtils argument sorting).deim(full_vars, A, g, F, ŷ, V, U)method. It returned scalarized projection equationsy_i ~ (Vŷ)_i, which the high-level path discarded. The numeric projection now lives in the internalProjectionstruct and the symbolic assembly in_reduced_rhs; the initial derivative is evaluated numerically from the same projection.src/full_order.jl.FullOrderModelholds the explicit first-order form of a source system (compiled as needed,linear * y + forcing + nonlinearsplit, source fields, snapshot row map, trained parameter values, preserved observed equations).separate_termsis reimplemented on top of the publicSymbolics.semilinear_forminstead of reaching intoSymbolicUtils.dict/.coeffinternals; it no longer takes the independent variable. Thesrc/utils.jlhelpers (get_deqs,only_dvs) and_sort_observed_equationsare removed; the reduced observed equations are ordered by construction.deim(prob, sol, pod_dim)now acceptsODEProblems (Union{AbstractODEProblem, AbstractDAEProblem}) in addition toDAEProblems.ODEProblem(mtkcompile(rom), ...; build_initializeprob = false)is tested as a supported path alongside the arrayDAEProblempath.ModelingToolkit.System;ODESystemis a deprecated alias in MTK v11. TheSetfielddependency and the@set! sys.complete = falsehack are gone (mtkcompileonly rejects already-compiled systems). The unusedAbstractMORProblemtype is removed from the code and the developer docs. Parameter defaults are stored as plain numbers.FullOrderModel,SourceField, andseparate_terms.AGENTS.mdrecords the term-classification rule, the scalar-unknown requirement, and the two supported problem constructors.Not changed: the numerical algorithm (POD via TSVD, DEIM indices, Galerkin projection, least-squares reconstruction of eliminated states), the
D(ŷ)initial condition (still required byDAEProblemwithbuild_initializeprob = false;guessesdo not supplydu0), and the POD API.A new regression in
test/array_structure.jlchecks that a forcing term present on every grid row (.+ sin(t)) yields the same reduced graph for 4 and 12 states; a naive lazyG*forcingwith one entry per row would fail it.Verification
Julia 1.12.7, ModelingToolkit 11.41.0, MethodOfLines 1.3.0, Symbolics 7.39.0.
GROUP=Core julia +1 --project -e 'using Pkg; Pkg.test()'GROUP=QA julia +1 --project -e 'using Pkg; Pkg.test()'julia +1 --project=@runic -m Runic --check .,typos ., andgit diff --checkall exit 0.New capability: failing before, passing after
deim(::ODEProblem, sol, k)on unmodifiedmain(benchmark-style cubic array system from@mtkcompile,ODEProblem+Tsit5):Same script on this branch:
The new
test/deim.jltestsets "ODEProblem sources and scalar code generation" and "nonautonomous linear terms" cover this path, themtkcompile+ODEProblemconstruction, and exact recovery (relative error < 1e-6) of a rank-two nonautonomous linear system with two POD/DEIM modes. The nonautonomous case also passes onmain(relative error 4.2e-11 there); it is regression coverage for the term classification, not a bug fix.Benchmark
benchmark/array_compilation.jl, fresh process per size, two POD/DEIM modes:Offline reduction is faster than
mainbecause the initial derivative is evaluated numerically from the projection instead of by symbolic substitution into the scalarized right-hand side. The first residual evaluation is about 0.4 s slower: the generated code now performs theA*ŷ,C*F, andV_S*ŷarray products with parameter matrices instead of inlined scalar sums. All numbers are grid-independent, and both the FitzHugh-Nagumo graph-size regression (reduced_system_size(5) == reduced_system_size(20)) and the new uniform-forcing regression pass. Branch numbers were measured while the Core/QA/docs runs shared the machine.Not verified
sol[field]convenience indexing still goes through Array observed state is misclassified as parameter-only by getu ModelingToolkit.jl#5072; tests useSymbolicIndexingInterface.observedfor non-PDE fields, as before.DAEProblem(rom, nothing, tspan)with the default initialization still fails inside MTK (discover_maybe_zeroson array initial conditions); not addressed here.Review notes
deim(sys, snapshot, V, U)method is a small follow-up on top of_reduced_system.semilinear_form, so symbolic-coefficient linear terms come back as symbolic matrix entries and are moved to the nonlinear part explicitly.Links
🤖 Generated with Claude Code (model: claude-fable-5-1)
https://claude.ai/code/session_01H5RuLDtEazwTKPkNbPeZVu