Skip to content

Fix input-derivative pairing; default to inline linear-SCC reassembly#83

Merged
baggepinnen merged 2 commits into
masterfrom
fbc/default-linearize-kwargs
Jul 3, 2026
Merged

Fix input-derivative pairing; default to inline linear-SCC reassembly#83
baggepinnen merged 2 commits into
masterfrom
fbc/default-linearize-kwargs

Conversation

@baggepinnen

Copy link
Copy Markdown
Member

Two changes to the linearization pipeline, found while linearizing a planar two-joint robot (a model whose large linear SCCs take the numerical LinearSolve-based path under the default reassembly).

Fix: input-derivative column pairing in causal_simplification call sites

ModelingToolkit.linearize with allow_input_derivatives = true returns B with 2nu columns, where column nu + i is the derivative of input i. The pairing passed to causal_simplification was derived by broadcasting 1:nu against the set of nonzero derivative columns:

duinds = findall(any(!iszero, eachcol(matrices.B[:, nu+1:end]))) .+ nu
u2du = (1:nu) .=> duinds

When exactly one derivative column is nonzero this silently broadcasts to [1 => k, 2 => k, ...], pairing every input to the same derivative channel; other partial subsets throw a DimensionMismatch. The result is a wrong reduced system whenever inputs enter retained algebraic equations. On the robot, the input complementary sensitivity collapsed to a rank-1 projector (Ti(0) ≈ [1 1; 0 0] instead of I), i.e. the loop transfer's input columns came out identical.

The pairing is now positional over all inputs, [i => i + nu for i in 1:nu]; all-zero derivative columns contribute nothing (and filtering them out is not an option, since causal_simplification infers the input count from the number of pairs).

Verified on a minimal 5-equation model with a 3×3 linear SCC and two inputs: the numerically-reassembled linearization now matches the symbolically-inlined one to a relative error of 6e-16 (previously ~100% error); the robot's input complementary sensitivity matches to 8e-13 across frequency.

Default: inline linear-SCC reassembly for all linearizations

DEFAULT_LINEARIZE_KWARGS = (; reassemble_alg = DefaultReassembleAlgorithm(; inline_linear_sccs = true, analytical_linear_scc_limit = 1)) is now forwarded by every linearization-based function (named_ss, get_named_sensitivity/get_named_comp_sensitivity/get_named_looptransfer, batch_ss/batch_linearize, trajectory_ss, build_quadratic_cost_matrix). Caller-supplied keyword arguments take precedence, so the ModelingToolkit default remains reachable.

With the pairing fix above, both reassembly paths produce correct linearizations; the inline default is kept because it avoids the input-derivative-augmented form entirely (no spurious marginal modes, better conditioned realizations) on models with linear SCCs.

🤖 Generated with Claude Code

baggepinnen and others added 2 commits July 3, 2026 09:11
Add DEFAULT_LINEARIZE_KWARGS passing reassemble_alg =
DefaultReassembleAlgorithm(; inline_linear_sccs = true,
analytical_linear_scc_limit = 1) to every linearization-based function
(named_ss, get_named_sensitivity and friends, batch_ss/batch_linearize,
trajectory_ss, build_quadratic_cost_matrix). The numerical linear-SCC
fallback in generated code can produce silently rank-deficient linearizations
on models with large linear SCCs (observed on a planar two-joint robot, where
the two torque-input columns of the loop transfer came out numerically
identical, collapsing the input complementary sensitivity to a rank-1
projector instead of I at low frequency). Caller-supplied keyword arguments
take precedence, so the ModelingToolkit default remains reachable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W4JdEEqr6ifdSbp6MvbrU8
MTK's linearize with allow_input_derivatives = true returns B with 2nu
columns where column nu + i is the derivative of input i. The pairing passed
to causal_simplification was derived by broadcasting 1:nu against the set of
NONZERO derivative columns, which silently pairs every input to the same
derivative channel when exactly one column is nonzero (and errors for other
partial subsets). This produced wrong linearizations whenever inputs enter
retained algebraic equations, e.g. through the numerical (non-inlined)
linear-SCC reassembly: on a planar two-joint robot the input complementary
sensitivity collapsed to a rank-1 projector instead of I at low frequency.
The pairing is now positional over all inputs; all-zero derivative columns
contribute nothing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W4JdEEqr6ifdSbp6MvbrU8
@baggepinnen
baggepinnen merged commit 0e11e2e into master Jul 3, 2026
1 of 2 checks passed
@baggepinnen
baggepinnen deleted the fbc/default-linearize-kwargs branch July 3, 2026 10:01
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