Skip to content

Array code after index reduction: component rolling, torn loops in the RHS, simplification in array form - #93

Closed
JKRT wants to merge 8 commits into
masterfrom
array-ode-reduced
Closed

JKRT wants to merge 8 commits into
masterfrom
array-ode-reduced

Conversation

@JKRT

@JKRT JKRT commented Oct 26, 2026

Copy link
Copy Markdown
Member

Models translated with their arrays kept now stay in array code after index reduction, including models whose components are declared separately (MSL EngineV6's six cylinders), and that array code is faster than the scalar path on EngineV6.

  • Array code after index reduction: derivative unknowns solved in array form (solvedInArrays), an OMJLIR front half for ArrayODEGen; slicing of arrays the plan treats per element; records, functions and if-equations in array code.
  • Component rolling (rollComponents!, OMBACKEND_ROLL_COMPONENTS, now on by default): separately declared components of one class rolled into arrays over the instances; elements keep their names.
  • Algebraic loops: small ones by Newton per element; large ones torn (greedy, strict divisions, pivoting within a variable) and solved where the equations reach them (ArrayBlockSolve.jl), so the solver integrates the states only.
  • Simplification before code generation: literal folding, alias elimination in array form, calls inlined after index reduction, parameter-only values once per solve (invariants!), crossing functions from what the relations need (crossings!).
  • Events: the relation whose crossing the root finder found flips by its direction.
  • Array right-hand side: an error rejects the step (kept until the run ends); a time gradient on the run's time scale near t = 0, wrapped to one type for all models.

EngineV6 (MSL 4.1.0), warm: 0.12 s for 0.25 s (scalar path 0.20 s); 1 s at tolerance 1e-8: 4.6 s (scalar path 16.6 s), load.w matching the scalar path to 1.5e-8.

Coverage-relevant defaults: array index reduction with rolling, and models with large loops plus events or initial equations, now take the array code. MSL 4.1.0 coverage with rolling on is running locally; results follow here. test/runtests.jl 1069/1069; OM.jl suite (all groups) 1773 pass, 0 failures, 11 min. Version not bumped yet.

🤖 Generated with Claude Code

JKRT added 8 commits October 25, 2026 14:24
…on per element, array DAE)

- Reduced models with arrays kept go to ArrayODEGen: derivative unknowns solved in array form
  (IndexReduction.solvedInArrays, checked against the element view), an OMJLIR front half
  (ArrayODEGenerationIR.jl); the scalarized path stays the fallback.
- ArrayODEGen: per-element algebraic loops solved by one generated Newton solve per family of blocks;
  loops through the elements (blocks above NEWTON_BLOCK_SIZE) as an index-1 DAE (mass matrix,
  consistent initialization); an unknown read twice solved linearly. Only in models with arrays.
- Evaluation: sum/product/min/max of an array literal. RHS algebraic buffer kept per problem.

Assisted-by: Claude Opus 5.5
A maximum matching and the strongly connected blocks of the initialization rows (with the
initialization equations' rows), solved block by block before the simultaneous phases.
MSL EngineV6 initializes (the slider-crank loops' positions first; before, the gas forces
at the zero guesses stalled the phases and the free initialization moved load.w).

Assisted-by: Claude Opus 5.5
…uations

- Slicing (ArraySlicing.jl): arrays the plan or the array-form solve treats element by element
  differently are split into element variables, readers unrolled, then retried.
- resolveBindingReferences!: a binding reading an array element (I_31 = I[3, 1]) takes that
  element, not the whole array's binding.
- OMJLIR front half: record/array arguments and record results of functions, subscripted
  expressions, scalar products, if-equations, fixed = false parameters.
- Tests: IndexReduction.BoundaryWithArray, RecordsArray.

Assisted-by: Claude Opus 5.5
…S, off)

- rollComponents!: separately declared components of one class as arrays over the
  instances (OMJLIR T_COMPONENTS part; elements keep their names), their equations
  rolled into for-equations.
- Slicing: rolled arrays split along inner dimensions only; requests collected per
  commit; new derivative arrays name their model array; slice references resolved.
- Inlining, differentiation and the array-form solve for rolled records and slices.
- Test: IndexReduction.SeparatePairs.

Assisted-by: Claude Opus 5.5
…TS, off)

- DAE unknowns solved block by block in schedule order by a sparse Newton (colored
  differences on the model's pattern), with the initial equations and in every event
  iteration; solver initialization off for array DAEs.
- Differentiation of parts and elements of arrays that are no variable (record fields
  expanded into element variables) element by element.
- Scalarized fallback of rolled models: SimCode names by the component member.
- Test: ArrayPath.CoupledLoopEvents.

Assisted-by: Claude Opus 5.5
…, invariants

- Loops of more than NEWTON_BLOCK_SIZE instances torn (greedy, strict, pivoting within a
  variable) and solved where the equations reach them (ArrayBlockSolve.jl: factorization kept
  between calls, polished to round-off); the array DAE and OMBACKEND_ARRAY_DAE_EVENTS removed.
- Before matching: literal operations folded, alias variables read through one representative.
- After index reduction: calls inlined where a function's body runs into one expression.
- invariants!: parameter-only values once per solve; crossings!: what the relations need.
- Events: the relation whose crossing the root finder found flips (by its direction).
- MSL EngineV6 (rolled): 0.12 s for 0.25 s (scalar path 0.20 s); matches it to 1.5e-8.

Assisted-by: Claude Opus 5.5
…rors, time gradient

- OMBACKEND_ROLL_COMPONENTS on by default.
- StepRejectingRHS: an error in the array RHS rejects the step; kept until the run ends
  (a failed run throws it). The per-element Newton makes its unknowns NaN on non-finite
  residuals or a singular Jacobian.
- tgrad!: central differences in t, near t = 0 a billionth of the run (the solver's step
  6e-6 spanned MSL DifferenceAmplifier's 0.2 GHz sources).

Assisted-by: Claude Opus 5.5
The model's own tgrad! type in the problem compiled the solver again for each array
model (OM.jl suite with rolling on: 29 min; wrapped: 11 min). Precompile workload warms
the wrapped type.

Assisted-by: Claude Opus 5.5
@JKRT

JKRT commented Oct 26, 2026

Copy link
Copy Markdown
Member Author

Superseded by #94 (the same work, squashed).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant