Repository navigation
Add slow_fast decomposition and modal_reduction - #1087
Merged
Merged
Conversation
`slow_fast(sys, ωc)` decomposes a system additively into a part with the poles of natural frequency less than ωc and a part with the remaining poles and the direct feedthrough term. The natural frequency is |p| in continuous time and |log(p)|/Ts in discrete time, consistent with `damp`. `modal_reduction(sys, ωc)` removes the fast modes by residualization (default) or truncation. The reduced state is either the slow modal coordinates or a subset of the original state variables, in which case the slow invariant subspace is represented as the solution of a nonsymmetric algebraic Riccati equation computed from the ordered Schur basis. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
This is an automated message.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1087 +/- ##
==========================================
+ Coverage 92.09% 92.17% +0.08%
==========================================
Files 42 42
Lines 6056 6119 +63
==========================================
+ Hits 5577 5640 +63
Misses 479 479 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The conditioning check used the 2-norm condition number, which requires an SVD that LinearAlgebra does not provide for BigFloat. The 1-norm condition number is computed from an LU factorization and is available for all number types. Add tests for BigFloat systems, which require GenericSchur for the Schur decomposition. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
This is an automated message.
|
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
baggepinnen
referenced
this pull request
Oct 13, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HigNnun4aJKMoWmY7wyULn
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.















This PR adds a decomposition of a system into slow and fast parts, and a model-reduction method based on it.
slow_fast(sys, ωc)Decomposes
sys = slow + fast, whereslowcontains the poles with natural frequency less thanωcandfastcontains the remaining poles and the direct feedthrough termD. The natural frequency of a polepis|p|in continuous time and|log(p)|/Tsin discrete time, consistent withdamp. The implementation uses an ordered Schur decomposition followed by a Sylvester equation, as inMatrixPencils.ssblkdiag.ssblkdiagcannot be reused because it only supports a half-plane or a disc centred at the origin as the selection region.stab_unstab(sys; smarg)splits continuous-time systems by the real part of the poles, so a lightly damped high-frequency mode is assigned to the slow part. For discrete-time systems, the disc centred at the origin separates the poles by decay rate rather than by frequency.slow_fastassigns such modes by natural frequency in both cases.modal_reduction(sys, ωc; residual = true, coordinates = :modal, states = nothing)Removes the modes with natural frequency greater than or equal to
ωcby residualization (default, preserves the static gain) or truncation. The poles of the reduced model are the slow poles ofsys. The returned matrixTmaps the original state to the reduced state.coordinates = :modal: the reduced state is in the slow modal coordinates. Withresidual = true, the reduced model equalsslow + ss(dcgain(fast)).coordinates = :original: the reduced state is a subsetx[states]of the original state variables. The slow invariant subspace is represented asx2 = X*x1, whereXsolves the nonsymmetric algebraic Riccati equationA22*X - X*A11 - X*A12*X + A21 = 0, and the deviationx2 - X*x1is residualized or truncated. This is the singular perturbation approximation with the exact slow manifold.Xis computed from the ordered Schur basis ofA. This is the same computationMatrixEquations.nareperforms for this equation (added in MatrixEquations.jl v2.7.0), so the MatrixEquations compat bound does not change. Ifstatesis not provided, the retained state variables are selected by a QR decomposition with column pivoting of the slow invariant subspace basis. A user-providedstatesfor which the subspace cannot be represented throws an error.The two choices of coordinates yield reduced models with the same poles and static gain but in general different transfer functions. The method does not account for controllability and observability. The docstring therefore refers to
baltruncfor reduction based on input-output importance.Tests
The tests in
test_matrix_comps.jlcover continuous-time, discrete-time, complex-coefficient andBigFloatsystems, both coordinate choices, the cases where all poles are slow or all are fast, and invalid arguments.BigFloatsystems requireGenericSchurfor the Schur decomposition, as elsewhere in ControlSystemsBase. The conditioning check forcoordinates = :originaluses the 1-norm condition number, since the 2-norm condition number requires an SVD that is unavailable forBigFloatwithout GenericLinearAlgebra. The full ControlSystemsBase test suite passes locally (including Aqua).ExplicitImports.check_no_stale_explicit_importsreports no new stale imports, andordschur!was added to the explicitLinearAlgebraimports.Host: demeter2, session ID: 527acd1d-a7ce-41f9-9f9e-d6aff56e7521, working directory:
~/.julia/dev/ControlSystems/.claude/worktrees/expressive-yawning-squid🤖 Generated with Claude Code