Repository navigation
Conversation
`maybe_zeros_descend` did not descend into `BSImpl.Div`, so a quotient whose numerator is built from `maybe_zeros` (e.g. (Ixy*Iyz + Ixz*Iyy)/det(J)) was treated as safe to divide by. Descend into both the numerator and the denominator: a zero numerator makes the quotient zero, and a zero denominator makes it non-finite. Fixes JuliaComputing#166 and the reported case of SciML/ModelingToolkit.jl#5279 (inline linear SCC pivoting on I21 - I11*I32/I31). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 16, 2026
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.
Fixes #166. Also fixes the case reported in SciML/ModelingToolkit.jl#5279 (see below).
Problem
_check_allow_symbolic_parameterusesquery_maybe_zerosto refuse division by an expression that may be zero.maybe_zeros_descenddid not descend intoBSImpl.Div, andMaybeZeroQueryFnhas noDivcase. So any quotient was treated as safe, including one whose numerator is built frommaybe_zerosentries, such as(Ixy*Iyz + Ixz*Iyy) / det(J). A product holding such a quotient was also missed, for exampler * ((p + q) / s).Change
maybe_zeros_descendnow returnstrueforBSImpl.Div, soSU.queryvisits the numerator and the denominator with the existing predicate. A quotient is flagged when:max/min/ifelse, ...), orThere are no other changes: the predicate and the other descent rules are as before.
Effect on tearing
This only changes anything when an expression in
maybe_zeros(sys)(declared, or found bydiscover_maybe_zeros) appears inside a division in a coefficient or a linear-SCC matrix entry. Those coefficients are no longer divided by. Instead the variable is not solved for through that equation, and an inline linear SCC uses the numericsafe_ldivpath instead ofsym_lu. All existing tests in both packages give the same results.Tests
New testsets in
lib/ModelingToolkitTearing/test/runtests.jl:`maybe_zeros` is respected inside divisionsquery_maybe_zeroson quotients: numerator maybe-zero, denominator maybe-zero, nested in products and powers, and negative cases;(p*r + q)/s * y ~ xis not solved forywhenmaybe_zeros = [p, q];maybe_zeroscheck does not look inside a division, so tearing divides by a parameter expression that is zero (NaN in initialization) #166 case: trimming a rigid body by initialisation (D(w) ~ 0with the moments asmissingparameters, explicitadj(J)/det(J), onlyIxznon-zero). The initialisationLinearProblemused to hold[-Inf NaN; -Inf NaN]and is now finite.Inline linear SCC does not pivot on a quotient with a maybe-zero numerator: the inline_linear_sccs: analytical sym_lu divides by (I21 - I11*I32/I31), which is 0 when only I31 is non-zero (NaN in rigid-body Euler equations) SciML/ModelingToolkit.jl#5279 Euler-equation reproducer withinline_linear_sccs = trueand onlyI31non-zero. Onmainthe RHS is NaN. Now it matchesJ \ (-w × Jw).Before the fix, 12 of the 18 checks in (1) and both checks in (2) fail. After it, all pass. The full suites pass for StateSelection and ModelingToolkitTearing (Julia 1.12.5, ModelingToolkit 11.45.4, SymbolicUtils 4.51.0, Symbolics 7.45.0).
Not covered
A compiled system is still only safe for the zeros known at compile time. If no products of inertia are declared or found as maybe-zero (for example, all defaults non-zero) and they are set to zero later in
ODEProblem, both tearing and the analytic linear-SCC solve can still divide by zero. That is the existingmaybe_zeroscontract, so I've left it out of this PR. It is discussed in SciML/ModelingToolkit.jl#5279.🤖 Generated with Claude Code