MTKTearing: keep array differential equations intact through structural simplification - #158
Draft
ChrisRackauckas-Claude wants to merge 2 commits into
Draft
ChrisRackauckas-Claude wants to merge 2 commits into
ChrisRackauckas-Claude wants to merge 2 commits into
Conversation
…structural simplification Array equations `D(x[slice]) ~ rhs` are still scalarized into rows of the bipartite graph, so matching, Pantelides, dummy derivatives, tearing and alias elimination see exact per-element incidence. The rows now remember the array equation they came from (`ArrayEquationGroup`, `row_group`, `row_elem`), and every pass that rewrites a row in a way the array equation cannot represent (differentiation, removal, dummy derivative substitution, solving for another variable, inline linear SCCs, clock partition splits) marks the group dirty. Rows of the integer-linear subsystem that belong to a group are kept out of Gaussian elimination so they are neither reduced nor used as pivots. With `preserve_array_equations = true` on `DefaultReassembleAlgorithm` (or as a `mtkcompile` keyword) intact groups are emitted as a single array equation over scalar unknowns; dirty groups are emitted scalarized as before. The default output is unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
…collection Fold the split/merge helpers into linear_subsys_adjmat! via is_intact_array_group_row, and cover the mixed array-DE + linear algebraic case. Co-authored-by: Cursor <cursoragent@cursor.com>
Author
|
Local check: this branch’s |
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.
Companion to SciML/ModelingToolkit.jl#5102. Bumps ModelingToolkitTearing to 1.21.0.
Array differential equations such as the MethodOfLines discretization
D(u[2:(n-1)]) ~ lap(u)are currently always flattened byscalarize_tearing_state_eqs!, so nothing downstream ofmtkcompilecan ever see them as arrays again. This PR teaches the structural simplification pipeline to keep those equations as first-class units when that is valid while still running matching, Pantelides, dummy derivatives, tearing and alias elimination on them. It is not a switch that turns any algorithm off.Design
Incidence stays scalar; the array structure is carried alongside
TearingStatestill scalarizes every equation into rows of the bipartite graph andfullvarsstill holds scalar variables. This is deliberate: forD(u[2:(n-1)]) ~ lap(u)each element depends on a different subset ofu, and per-element incidence is exactly what index reduction and tearing need to make correct decisions (whichu[k]are states, whether a boundary equationu[1] ~ 0makesD(u[1])a dummy derivative, and so on). Collapsing an array equation into one graph node would either lose that information or require every algorithm to reason about slices.Instead, when the constructor scalarizes an eligible equation it records an
ArrayEquationGroup:and two per-row vectors on
TearingState:row_group[i](index of the group of equation rowi,0for scalar rows) androw_elem[i](linear element index within the group). Rows appended later (eq_derivative!) are always scalar.Eligibility (
canonicalize_array_equation): one side isD(x)orD(x[slice])for an array unknownxwith a constant-index slice, the other side has no derivatives and matching shape. The residual forms emitted by MethodOfLines,D(x[slice]) .- f ~ 0andD(x[slice]) .+ f ~ 0, are canonicalized toD(x[slice]) ~ ±f. Algebraic array equations and equations with derivatives on both sides are scalarized as before.Every algorithm runs; any rewrite the array equation cannot represent marks the group dirty
The algorithms are unchanged. Wherever a pass modifies a row so that it is no longer "element
kofD(x[slice]) ~ rhssolved forD(x[k])", the group is marked dirty (dirty_array_group!):eq_derivative!rm_eqs_vars!substitute_derivatives_algevars!codegen_equation!(algebraic and solved branches), inline linear SCC pathD(x[k]), or a previously solved derivative was substituted into its RHSsystem_subset,shift_discrete_system,substitute_sample_time__mtkcompileSubstituting an eliminated alias or zero variable into a row does not dirty the group: the eliminated variable stays available as an observed equation and the array equation remains correct.
Integer-linear elimination cannot pivot on array-equation rows
linear_subsys_adjmat!leaves the rows of intact groups out ofmm(is_intact_array_group_row). Otherwise alias elimination could pivot onD(x[1]) ~ -x[1] + yto eliminateyfromy ~ sum(x), which would leaveD(x[1])matched to a rewritten equation. Their solvability is still recorded insolvable_graph, so tearing still seesD(x[k])as solvable from its row. Rows of dirty groups are ordinary scalar rows and take part in the elimination. This is why the MTK side needs no changes toalias_elimination!.Emission
At the end of reassembly
blt_reorder_generated_equations!places the rows of each intact group contiguously and in element order (tagged with the earliest SCC among them; they are all differential equations of selected states so algebraic BLT order is unaffected). Withpreserve_array_equations = trueonDefaultReassembleAlgorithm(also accepted as amtkcompilekeyword, which already forwards to the reassemble algorithm),collapse_array_equations!replaces each intact run by the single array equation. Unknowns stay scalar (x[k]) in the same order as the rows they replace, so mass matrices and the ODE/DAE code generators lay the equation out over the right slots.row_to_equation_indicesmaps graph rows to emitted equations for consumers such asmap_variables_to_equations. Dirty groups are emitted scalarized exactly as today.The default is
preserve_array_equations = false, so the output ofmtkcompileis unchanged by this PR. The opt-in exists only because explicitODEProblemcodegen for array equations is landing separately (SciML/ModelingToolkit.jl#5101);DAEProblemalready handles them. Once that is in, the default can flip.What still scalarizes, and why
q,v): the differentiated row and its dummy-derivative substitutions are not representable as the original array equation.D(x[k]), e.g. when tearing/state selection picks a different state and the row becomes algebraic in it.In every case the fallback is exactly the current behaviour.
Tests
lib/ModelingToolkitTearing/test/runtests.jl, testset "Array equation groups":TearingStatetracks eligible equations as groups with correctrow_group/row_elem.eq_derivative!dirties the group; the appended row is scalar.mmbut remain solvable for their derivatives; dirty groups take part;alias_elimination!leaves the array equation intact.preserve_array_equations(keyword and algorithm option) emits one array equation over scalar unknowns;row_to_equation_indicesis correct; default output unchanged.Full MTKTearing test suite passes locally both against the companion MTK branch and against registered ModelingToolkit v11.42.0 / ModelingToolkitBase v1.69.0 (this PR does not depend on the MTK PR).
How to verify O(1) through
mtkcompileSee SciML/ModelingToolkit.jl#5102 (
test/structural_transformation/array_equations.jl): a heat equation in MethodOfLines residual form compiled withmtkcompile(heat; preserve_array_equations = true)yields one array equation plus observed boundary conditions,DAEProblemsolves it to the same result as the scalarized system, and theExprsize ofgenerate_rhs(...; implicit_dae = true)is identical forn = 24, 48, 96.Made with Cursor