ModelOrderReduction.POD — Type
POD(snapshots; min_renergy = 1.0, min_nmodes = 1,
    max_nmodes = length(snapshots[1])) -> POD
POD(snapshots, nmodes::Int) -> POD

Proper orthogonal decomposition reduction problem built from state snapshots. Call reduce! with an SVD backend to compute its basis and spectrum.

Arguments

  • snapshots::AbstractMatrix{T}: a state-by-snapshot matrix, where each column is a state snapshot.
  • snapshots::AbstractVector{<:AbstractVector{T}}: a vector of state snapshots.
  • nmodes::Int: the fixed number of retained modes. This positional form disables energy-based truncation.

Keywords

  • min_renergy::T = 1.0: minimum captured relative spectral energy when selecting modes.
  • min_nmodes::Int = 1: lower bound on the number of retained modes.
  • max_nmodes::Int = length(snapshots[1]): upper bound on the number of retained modes.

Fields

  • snapshots::S: the input snapshot data.
  • min_renergy::T: the minimum relative spectral energy used for truncation.
  • min_nmodes::Int: the lower bound on the number of retained modes.
  • max_nmodes::Int: the upper bound on the number of retained modes.
  • nmodes::Int: the selected number of retained modes.
  • rbasis::Union{Missing, Matrix{T}}: the reduced basis after reduce!, or missing before reduction.
  • renergy::T: the captured relative spectral energy.
  • spectrum::Union{Missing, Vector{T}}: the singular-value spectrum after reduce!, or missing before reduction.

Throws

  • AssertionError: if the snapshots are not vector-valued or the truncation bounds are invalid.

Returns

  • POD: an initialized reduction problem. The basis and spectrum are populated by reduce!.

Examples

julia> using ModelOrderReduction

julia> pod = POD([3.0 0.0; 0.0 1.0], 1);

julia> pod.nmodes
1
source
ModelOrderReduction.reduce! — Function
reduce!(pod::POD, alg::SVD) -> nothing

Compute the reduced basis and full singular-value spectrum for pod using dense SVD.

Arguments

  • pod::POD: reduction problem to update in place.
  • alg::SVD: dense singular value decomposition backend.

Returns

  • nothing: pod is updated in place.

Examples

julia> using ModelOrderReduction

julia> pod = POD([3.0 0.0; 0.0 1.0], 1);

julia> reduce!(pod, SVD()); size(pod.rbasis)
(2, 1)
source
reduce!(pod::POD, alg::TSVD) -> nothing

Compute the reduced basis and truncated singular-value spectrum for pod using a truncated SVD.

Arguments

  • pod::POD: reduction problem to update in place.
  • alg::TSVD: truncated singular value decomposition backend.

Returns

  • nothing: pod is updated in place.

Throws

  • An exception propagated by TSVD.tsvd if the snapshot matrix is not accepted by the truncated SVD backend.

Examples

julia> using ModelOrderReduction

julia> pod = POD([3.0 0.0; 0.0 1.0], 1);

julia> reduce!(pod, TSVD()); pod.nmodes
1
source
reduce!(pod::POD, alg::RSVD) -> nothing

Compute the reduced basis and approximate singular-value spectrum for pod using a randomized SVD.

Arguments

  • pod::POD: reduction problem to update in place.
  • alg::RSVD: randomized singular value decomposition backend.

Returns

  • nothing: pod is updated in place.

Throws

  • An exception propagated by RandomizedLinAlg.rsvd if the snapshot matrix is not accepted by the randomized SVD backend.

Examples

julia> using ModelOrderReduction

julia> pod = POD([3.0 0.0; 0.0 1.0], 1);

julia> reduce!(pod, RSVD()); pod.nmodes
1
source
ModelOrderReduction.SVD — Type
SVD(; kwargs...) -> SVD

Dense singular value decomposition backend for reduce!.

Keywords

  • kwargs...: keyword arguments forwarded to LinearAlgebra.svd.

Fields

  • kwargs: the named tuple of keyword arguments forwarded to the decomposition.

Examples

julia> using ModelOrderReduction

julia> SVD() isa SVD
true
source
ModelOrderReduction.TSVD — Type
TSVD(; kwargs...) -> TSVD

Truncated singular value decomposition backend for reduce!. Use this backend when only the requested reduced modes should be computed.

Keywords

  • kwargs...: keyword arguments forwarded to TSVD.tsvd.

Fields

  • kwargs: the named tuple of keyword arguments forwarded to the decomposition.

Examples

julia> using ModelOrderReduction

julia> TSVD() isa TSVD
true
source
ModelOrderReduction.RSVD — Type
RSVD([p::Int = 0]) -> RSVD

Randomized singular value decomposition backend for reduce!.

Arguments

  • p::Int = 0: number of oversampling vectors used by RandomizedLinAlg.rsvd.

Fields

  • p::Int: the oversampling parameter.

Throws

  • MethodError: if p is not an Int.

Examples

julia> using ModelOrderReduction

julia> RSVD(2).p
2
source
ModelOrderReduction.deim — Function
deim(
    sys::ModelingToolkit.System,
    snapshot::AbstractMatrix,
    pod_dim::Integer;
    deim_dim::Integer = pod_dim,
    name::Symbol = Symbol(nameof(sys), :_deim),
    snapshot_times = nothing,
    kwargs...
) -> ModelingToolkit.System

Reduce a first-order ModelingToolkit.System with Proper Orthogonal Decomposition (POD) and the Discrete Empirical Interpolation Method (DEIM).

The rows of snapshot follow ModelingToolkit.unknowns(sys) and each column is one time instance. The state basis is the POD basis of snapshot, and the DEIM basis is the POD basis of the nonlinear terms evaluated at the snapshot columns. Both bases are computed with TSVD.

sys may contain algebraic equations or array equations. It is structurally simplified as needed, which may scalarize the equations offline, but the returned system always has one array differential equation for the reduced state and one reconstruction observed equation per source field. The reduced equation is array linear algebra in the reduced state: the projected matrices, the stencil rows of the state basis, and the full-grid reconstruction coefficients are array parameters of the reduced system, and only the DEIM-sampled nonlinear terms are scalar expressions. Unknowns eliminated during simplification are reconstructed by a least-squares fit to snapshot. Terms that are linear in the unknowns with numeric coefficients are projected exactly; every other state-dependent term is interpolated by DEIM. Pass MethodOfLines symbolic_discretize systems before structural simplification so every element of each field is available for reconstruction.

Nonlinear terms are evaluated at the numeric parameter defaults of sys. Use the problem/solution method for problem-specific parameter values. The reduced state and its derivative at the first snapshot column are stored as initial conditions.

The reduced system inherits the time span of sys, so a problem can be built from it without repeating one. Passing a time span explicitly still overrides it, and a source system without one produces a reduced system without one.

Construct a DAEProblem with build_initializeprob = false from the returned system to keep array code generation, or call ModelingToolkit.mtkcompile on it and construct an ODEProblem to generate scalar code for the reduced equation. Reconstruct fields with SymbolicIndexingInterface.observed(reduced_system, field).

Arguments

  • sys::ModelingToolkit.System: first-order source system without subsystems.
  • snapshot::AbstractMatrix: state-by-time snapshot matrix for sys.
  • pod_dim::Integer: number of POD state modes to retain.

Keywords

  • deim_dim::Integer = pod_dim: number of DEIM modes for the nonlinear terms.
  • name::Symbol = Symbol(nameof(sys), :_deim): name of the reduced system.
  • snapshot_times = nothing: time of each snapshot column; required when the equations depend on the independent variable.
  • kwargs...: keyword arguments forwarded to Symbolics.substitute.

Returns

  • ModelingToolkit.System: the completed reduced system.

Throws

  • DimensionMismatch: if snapshot does not have one row per unknown of sys, or if snapshot_times does not have one entry per column.
  • ArgumentError: if sys does not simplify to an explicit first-order ODE, or if a nonlinear term cannot be evaluated numerically.

Examples

reduced_system = deim(source_system, snapshots, 4; deim_dim = 6)
source
deim(
    prob::Union{SciMLBase.AbstractODEProblem, SciMLBase.AbstractDAEProblem},
    sol,
    pod_dim::Integer;
    deim_dim::Integer = pod_dim,
    name::Union{Nothing, Symbol} = nothing,
    kwargs...
) -> ModelingToolkit.System

Reduce the symbolic system behind prob with POD-DEIM, using one of its saved solutions sol as the training snapshot.

prob must have been constructed from a ModelingToolkit.System, such as the array-form DAEProblem returned by MethodOfLines. The saved states are the snapshot columns, the saved times supply the independent variable for time-dependent terms, and the parameter values of prob are used for training and become the defaults of the reduced system. The reduced system also inherits the time span of prob, which is the interval it was trained on, so a problem can be built from it without repeating one. sol may be the SciMLBase.PDETimeSeriesSolution returned by MethodOfLines or its underlying SciMLBase.AbstractODESolution. See the system method for the reduction itself and for how to construct problems from the returned system.

Arguments

  • prob: symbolic first-order problem whose function stores a ModelingToolkit.System.
  • sol: saved solution obtained from prob.
  • pod_dim::Integer: number of POD state modes to retain.

Keywords

  • deim_dim::Integer = pod_dim: number of DEIM modes for the nonlinear terms.
  • name::Union{Nothing, Symbol} = nothing: name of the reduced system. The default appends _deim to the name of the full system.
  • kwargs...: keyword arguments forwarded to Symbolics.substitute.

Returns

  • ModelingToolkit.System: the completed reduced system.

Throws

  • ArgumentError: if prob has no symbolic system, if sol was not obtained from prob or does not start at the beginning of prob, or if the system does not simplify to an explicit first-order ODE.
  • DimensionMismatch: if the saved states do not match the unknowns of the system.

Examples

full_problem = discretize(pde_system, discretization; fallback = false)
full_solution = solve(full_problem)
reduced_system = deim(full_problem, full_solution, 4)
reduced_problem = DAEProblem(reduced_system, nothing; build_initializeprob = false)
source
ModelOrderReduction.pod — Function
pod(
    sys::ModelingToolkit.System,
    snapshot::AbstractMatrix,
    pod_dim::Integer;
    name::Symbol = Symbol(nameof(sys), :_pod),
    snapshot_times = nothing,
    kwargs...
) -> ModelingToolkit.System

Reduce a first-order ModelingToolkit.System with Proper Orthogonal Decomposition (POD) Galerkin projection, without Discrete Empirical Interpolation (DEIM).

The rows of snapshot follow ModelingToolkit.unknowns(sys) and each column is one time instance. The state basis is the POD basis of snapshot, computed with TSVD.

When the source system is an explicit first-order model whose differential equations are written in terms of the source field variables (including array equations), the reduced dynamics are assembled by substituting $\mathbf y = V\hat{\mathbf y}$ into those equations and left-multiplying by $V^T$. The state basis and its transpose are array parameters, so the generated residual is array linear algebra whose symbolic size does not grow with the full-order grid. When the source has already been scalarized, the same Galerkin projection is applied to the compiled residual; the online nonlinear cost then scales with the full-order dimension (use deim to hyper-reduce it).

sys may contain algebraic equations or array equations. It is structurally simplified as needed. The returned system always has one array differential equation for the reduced state and one reconstruction observed equation per source field. Unknowns eliminated during simplification are reconstructed by a least-squares fit to snapshot.

The reduced system inherits the time span of sys, so a problem can be built from it without repeating one. Passing a time span explicitly still overrides it, and a source system without one produces a reduced system without one.

Construct a DAEProblem with build_initializeprob = false from the returned system to keep array code generation, or call ModelingToolkit.mtkcompile on it and construct an ODEProblem to generate scalar code for the reduced equation. Reconstruct fields with SymbolicIndexingInterface.observed(reduced_system, field).

Arguments

  • sys::ModelingToolkit.System: first-order source system without subsystems.
  • snapshot::AbstractMatrix: state-by-time snapshot matrix for sys.
  • pod_dim::Integer: number of POD state modes to retain.

Keywords

  • name::Symbol = Symbol(nameof(sys), :_pod): name of the reduced system.
  • snapshot_times = nothing: time of each snapshot column; required when the equations depend on the independent variable.
  • kwargs...: keyword arguments forwarded to Symbolics.substitute.

Returns

  • ModelingToolkit.System: the completed reduced system.

Throws

  • DimensionMismatch: if snapshot does not have one row per unknown of sys, or if snapshot_times does not have one entry per column.
  • ArgumentError: if sys does not simplify to an explicit first-order ODE, or if a residual term cannot be evaluated numerically.

Examples

reduced_system = pod(source_system, snapshots, 4)
source
pod(
    prob::Union{SciMLBase.AbstractODEProblem, SciMLBase.AbstractDAEProblem},
    sol,
    pod_dim::Integer;
    name::Union{Nothing, Symbol} = nothing,
    kwargs...
) -> ModelingToolkit.System

Reduce the symbolic system behind prob with POD Galerkin projection, using one of its saved solutions sol as the training snapshot.

prob must have been constructed from a ModelingToolkit.System, such as the array-form DAEProblem returned by MethodOfLines. The saved states are the snapshot columns, the saved times supply the independent variable for time-dependent terms, and the parameter values of prob are used for training and become the defaults of the reduced system. The reduced system also inherits the time span of prob, which is the interval it was trained on, so a problem can be built from it without repeating one. sol may be the SciMLBase.PDETimeSeriesSolution returned by MethodOfLines or its underlying SciMLBase.AbstractODESolution. See the system method for the reduction itself and for how to construct problems from the returned system.

Arguments

  • prob: symbolic first-order problem whose function stores a ModelingToolkit.System.
  • sol: saved solution obtained from prob.
  • pod_dim::Integer: number of POD state modes to retain.

Keywords

  • name::Union{Nothing, Symbol} = nothing: name of the reduced system. The default appends _pod to the name of the full system.
  • kwargs...: keyword arguments forwarded to Symbolics.substitute.

Returns

  • ModelingToolkit.System: the completed reduced system.

Throws

  • ArgumentError: if prob has no symbolic system, if sol was not obtained from prob or does not start at the beginning of prob, or if the system does not simplify to an explicit first-order ODE.
  • DimensionMismatch: if the saved states do not match the unknowns of the system.

Examples

full_problem = discretize(pde_system, discretization; fallback = false)
full_solution = solve(full_problem)
reduced_system = pod(full_problem, full_solution, 4)
reduced_problem = DAEProblem(
    reduced_system, nothing; build_initializeprob = false
)
source
ModelOrderReduction.baltrunc — Function
baltrunc(A, B, C, D = nothing; n = nothing, atol = 0, rtol = 1e-3,
         residual = false) -> BalancedTruncation

Balanced truncation of a continuous-time linear time-invariant system

\[\dot x = A x + B u,\qquad y = C x + D u.\]

The square-root method balances the controllability and observability Gramians and truncates states with small Hankel singular values. If n is omitted, the reduced order keeps singular values at least atol and at least rtol times the largest singular value.

When residual = true, truncated states are eliminated by residualization (singular perturbation) so that the static gain is matched.

Only real floating-point systems are supported. A must be Hurwitz.

Arguments

  • A::AbstractMatrix: state matrix.
  • B::AbstractVecOrMat: input matrix (vectors are treated as single-input).
  • C::AbstractMatrix: output matrix.
  • D: feedthrough matrix. Defaults to a zero matrix conforming to (C, B).

Keywords

  • n = nothing: reduced order. When nothing, choose the order from atol / rtol.
  • atol = 0: absolute Hankel-singular-value cutoff.
  • rtol = 1e-3: relative Hankel-singular-value cutoff.
  • residual = false: use residualization instead of plain truncation.

Returns

Throws

  • ArgumentError: if the system dimensions are inconsistent, A is not square, A is not Hurwitz, no positive Hankel singular values remain, or n is invalid.

Examples

julia> using ModelOrderReduction

julia> A = [-1.0 0.0; 0.0 -2.0]; B = reshape([1.0, 1.0], 2, 1); C = [1.0 1.0];

julia> bt = baltrunc(A, B, C; n = 1);

julia> size(bt.A)
(1, 1)

References

  • Moore, B. C. (1981). Principal component analysis in linear systems. IEEE Transactions on Automatic Control.
  • Antoulas, A. C. (2005). Approximation of Large-Scale Dynamical Systems. SIAM.
source
ModelOrderReduction.BalancedTruncation — Type
struct BalancedTruncation{T<:AbstractFloat}

Reduced continuous-time LTI model produced by baltrunc.

The reduced dynamics are

\[\dot x_r = A_r x_r + B_r u,\qquad y = C_r x_r + D_r u,\]

with reconstruction $x \approx T_r x_r$ and reduction $x_r = S x$ for plain truncation. When residualization is used, $T_r$ is still the balanced truncation map for the retained states; the static contribution of the discarded states is folded into $(A_r, B_r, C_r, D_r)$ rather than into $T_r$.

Fields

  • A::Matrix{T} where T<:AbstractFloat: reduced state matrix $A_r$

  • B::Matrix{T} where T<:AbstractFloat: reduced input matrix $B_r$

  • C::Matrix{T} where T<:AbstractFloat: reduced output matrix $C_r$

  • D::Matrix{T} where T<:AbstractFloat: feedthrough matrix $D_r$

  • hsv::Vector{T} where T<:AbstractFloat: retained Hankel singular values

  • Tr::Matrix{T} where T<:AbstractFloat: right projector $T_r$ with $x \approx T_r x_r$ under plain truncation

  • S::Matrix{T} where T<:AbstractFloat: left projector $S$ with $x_r = S x$

source
ModelOrderReduction.opinf — Function
opinf(X, Xdot; nmodes, basis = nothing, linear = true, quadratic = false,
      inputs = nothing, constant = false, λ = 0) -> OperatorInferenceModel

Learn a polynomial reduced model by Operator Inference.

Snapshot matrix X and derivative matrix Xdot store one snapshot per column (state dimension × number of snapshots). A POD basis with nmodes columns is computed from X unless basis is provided. The projected least-squares problem

\[\min_O \| D O^\top - \dot X_r^\top \|_F^2 + \lambda \|O\|_F^2\]

is solved for the selected operator blocks.

Arguments

  • X::AbstractMatrix: state snapshots as columns.
  • Xdot::AbstractMatrix: time-derivative snapshots as columns, conforming to X.

Keywords

  • nmodes::Integer: number of POD modes. Required when basis is omitted.
  • basis = nothing: optional orthonormal basis $V$. When provided, nmodes defaults to size(basis, 2).
  • linear = true: infer a linear operator $A$.
  • quadratic = false: infer a quadratic operator $H$ on unique monomials.
  • inputs = nothing: optional input snapshots as an (input dimension × snapshots) matrix, or a length-snapshots vector for a single input.
  • constant = false: infer a constant forcing term $c$.
  • λ = 0: Tikhonov regularization weight applied isotropically to all operator coefficients. When positive, the ridge problem is solved via an augmented QR factorization.

Returns

Throws

  • ArgumentError / DimensionMismatch: if sizes are inconsistent, the basis is not orthonormal, or no operator block is requested.

Examples

julia> using ModelOrderReduction, LinearAlgebra

julia> Atrue = [-1.0 0.0; 0.0 -2.0];

julia> X = reduce(hcat, [[exp(-t), exp(-2t)] for t in 0:0.05:3]);

julia> Xdot = Atrue * X;

julia> model = opinf(X, Xdot; basis = Matrix{Float64}(I, 2, 2));

julia> model.A ≈ Atrue
true

References

  • Peherstorfer, B. & Willcox, K. (2016). Data-driven operator inference for nonintrusive projection-based model reduction. CMAME.
  • Qian, E., Kramer, B., Peherstorfer, B. & Willcox, K. (2020). Lift & Learn.
source
opinf(
    X::AbstractVector{<:AbstractVector},
    Xdot::AbstractVector{<:AbstractVector};
    kwargs...
)

Operator Inference from a vector-of-snapshots representation, matching the POD snapshot convention.

source
ModelOrderReduction.OperatorInferenceModel — Type
struct OperatorInferenceModel{T<:AbstractFloat}

Reduced model learned by opinf.

With reduced coordinates $x_r = V^\top x$, the inferred dynamics are

\[\dot x_r = c + A x_r + B u + H\,\mathrm{quad}(x_r),\]

where $\mathrm{quad}$ stacks the unique quadratic monomials $x_i x_j$ for $1 \le i \le j \le r$ in row-major lower-triangular order $(x_1^2, x_1 x_2, \ldots, x_1 x_r, x_2^2, \ldots, x_r^2)$.

Fields

  • basis::Matrix{T} where T<:AbstractFloat: POD / trial basis $V$ with orthonormal columns

  • A::Union{Nothing, Matrix{T}} where T<:AbstractFloat: linear operator $A$, or nothing if not inferred

  • H::Union{Nothing, Matrix{T}} where T<:AbstractFloat: quadratic operator $H$ with size(H, 2) == r(r + 1) ÷ 2, or nothing

  • B::Union{Nothing, Matrix{T}} where T<:AbstractFloat: input operator $B$, or nothing if not inferred

  • c::Union{Nothing, Vector{T}} where T<:AbstractFloat: constant term $c$, or nothing if not inferred

source
ModelOrderReduction.reduced_dynamics — Function
reduced_dynamics(
    model::OperatorInferenceModel{T},
    xr::AbstractVector
) -> Any
reduced_dynamics(
    model::OperatorInferenceModel{T},
    xr::AbstractVector,
    u::Union{Nothing, AbstractVector}
) -> Any

Evaluate the reduced right-hand side of model at reduced state xr with optional input u.

source