GitHub

Rust API Reference

Complete reference for the koopman_dmd Rust crate

Core Types

DmdConfig

Configuration struct for standard DMD. Implements Default.

pub struct DmdConfig {
    pub rank: Option<usize>,
    pub center: bool,
    pub lifting: Option<LiftingConfig>,
}
Field Type Default Description
rank Option<usize> None Truncation rank for the SVD. None selects rank automatically via a singular-value threshold.
center bool false Subtract the temporal mean from each row before decomposition. The mean is stored and added back during reconstruction.
lifting Option<LiftingConfig> None Optional nonlinear lifting to augment the observable space (see Lifting).

DmdResult

Output struct returned by dmd(). Contains the full spectral decomposition and metadata needed for reconstruction and prediction.

pub struct DmdResult {
    pub eigenvalues:   Vec<C64>,
    pub modes:         Vec<Vec<C64>>,
    pub amplitudes:    Vec<C64>,
    pub a_matrix:      Vec<Vec<C64>>,
    pub rank:          usize,
    pub data_dim:      (usize, usize),
    pub x_last:        Vec<f64>,
    pub center:        bool,
    pub x_mean:        Option<Vec<f64>>,
    pub lifting_info:  Option<LiftingInfo>,
}
Field Type Description
eigenvalues Vec<C64> Complex DMD eigenvalues (discrete-time).
modes Vec<Vec<C64>> DMD modes as column vectors. Each inner Vec is one mode.
amplitudes Vec<C64> Amplitude coefficients weighting each mode's contribution.
a_matrix Vec<Vec<C64>> Reduced linear operator in the POD basis.
rank usize Truncation rank used in the decomposition.
data_dim (usize, usize) Shape of the original data matrix (rows, columns).
x_last Vec<f64> Last column of the data matrix, used as the default initial condition for prediction.
center bool Whether mean centering was applied.
x_mean Option<Vec<f64>> Row-wise mean vector, present when center = true.
lifting_info Option<LiftingInfo> Metadata about applied lifting, present when a lifting config was supplied.

C64

Custom complex number type used throughout the library. Wraps a 64-bit real and imaginary pair.

pub struct C64 {
    pub re: f64,
    pub im: f64,
}
Method Signature Description
new fn new(re: f64, im: f64) -> C64 Construct a complex number from real and imaginary parts.
norm fn norm(&self) -> f64 Modulus (absolute value): sqrt(re^2 + im^2).
arg fn arg(&self) -> f64 Phase angle in radians: atan2(im, re).
conj fn conj(&self) -> C64 Complex conjugate: (re, -im).
zero fn zero() -> C64 Returns 0 + 0i.

DmdError

Error type for all fallible operations. Implements std::error::Error and Display.

pub enum DmdError {
    InvalidInput(String),
    NumericalError(String),
    ConvergenceError(String),
}
Variant Description
InvalidInput(String) The input data or configuration is invalid (e.g., dimension mismatch, empty matrix, rank exceeding matrix dimensions).
NumericalError(String) A numerical computation failed (e.g., singular matrix, NaN produced during SVD).
ConvergenceError(String) An iterative algorithm did not converge within the allowed iterations or tolerance.

DMD Functions

dmd

Perform Dynamic Mode Decomposition on a snapshot matrix. Returns the full spectral decomposition including eigenvalues, modes, and amplitudes.

pub fn dmd(
    data: &Mat<f64>,
    config: &DmdConfig,
) -> Result<DmdResult, DmdError>
Parameter Type Description
data &Mat<f64> Snapshot matrix with state variables as rows and time steps as columns.
config &DmdConfig Decomposition configuration (rank, centering, lifting).

Returns: Result<DmdResult, DmdError> -- the full decomposition on success, or an error if the input is invalid or the computation fails.

use koopman_dmd::{dmd, DmdConfig};

let config = DmdConfig { rank: Some(4), ..DmdConfig::default() };
let result = dmd(&data, &config)?;
println!("Eigenvalues: {:?}", result.eigenvalues);

predict_modes

Predict future states using the spectral formula. Each time step is computed independently from eigenvalues, modes, and amplitudes, so errors do not accumulate over long horizons.

pub fn predict_modes(
    result: &DmdResult,
    n_ahead: usize,
    x0: Option<&[f64]>,
) -> Result<Mat<f64>, DmdError>
Parameter Type Description
result &DmdResult A previously computed DMD decomposition.
n_ahead usize Number of future time steps to predict.
x0 Option<&[f64]> Initial condition. If None, uses result.x_last.

Returns: Result<Mat<f64>, DmdError> -- predicted state matrix with shape (n_vars, n_ahead).

predict_matrix

Predict future states by recursive application of the linear operator. Each step multiplies the previous state by the reconstructed matrix A.

pub fn predict_matrix(
    result: &DmdResult,
    n_ahead: usize,
    x0: Option<&[f64]>,
) -> Result<Mat<f64>, DmdError>
Parameter Type Description
result &DmdResult A previously computed DMD decomposition.
n_ahead usize Number of future time steps to predict.
x0 Option<&[f64]> Initial condition. If None, uses result.x_last.

Returns: Result<Mat<f64>, DmdError> -- predicted state matrix with shape (n_vars, n_ahead).

dmd_reconstruct

Reconstruct the original data from the DMD decomposition. If centering was applied, the stored mean is added back automatically.

pub fn dmd_reconstruct(
    result: &DmdResult,
    n_time: usize,
    x0: Option<&[f64]>,
) -> Result<Mat<f64>, DmdError>
Parameter Type Description
result &DmdResult A previously computed DMD decomposition.
n_time usize Number of time steps to reconstruct.
x0 Option<&[f64]> Initial condition. If None, uses the first snapshot from the original data.

Returns: Result<Mat<f64>, DmdError> -- reconstructed data matrix.

use koopman_dmd::{dmd, dmd_reconstruct, predict_modes, DmdConfig};

let result = dmd(&data, &DmdConfig::default())?;

// Reconstruct the training window
let fitted = dmd_reconstruct(&result, 100, None)?;

// Predict 50 steps ahead from a custom initial condition
let ic = vec![1.0, 0.0, 0.0];
let forecast = predict_modes(&result, 50, Some(&ic))?;

Analysis Functions

dmd_spectrum

Extract frequency, growth rate, and energy information for each DMD mode. Converts discrete-time eigenvalues to continuous-time frequencies using the sampling interval dt.

pub fn dmd_spectrum(
    result: &DmdResult,
    dt: f64,
) -> Vec<ModeInfo>
Parameter Type Description
result &DmdResult A previously computed DMD decomposition.
dt f64 Sampling interval (time between consecutive snapshots).

Returns: Vec<ModeInfo> -- one entry per mode containing frequency, growth rate, amplitude, and energy.

dmd_stability

Classify eigenvalues as stable, unstable, or neutral based on their modulus relative to the unit circle.

pub fn dmd_stability(
    result: &DmdResult,
    tol: f64,
) -> StabilityResult
Parameter Type Description
result &DmdResult A previously computed DMD decomposition.
tol f64 Tolerance for classifying eigenvalues as neutral. Eigenvalues with |lambda| - 1 < tol are considered neutral.

Returns: StabilityResult -- lists of stable, unstable, and neutral eigenvalue indices, plus an overall stability classification.

dmd_error

Compute reconstruction error metrics by comparing the DMD reconstruction against the original data matrix.

pub fn dmd_error(
    result: &DmdResult,
    data: &Mat<f64>,
) -> Result<ErrorMetrics, DmdError>
Parameter Type Description
result &DmdResult A previously computed DMD decomposition.
data &Mat<f64> Original snapshot matrix to compare against.

Returns: Result<ErrorMetrics, DmdError> -- RMSE and relative Frobenius-norm error.

dmd_residual

Compute the residual of the DMD decomposition, measuring how well the linear operator reproduces the one-step dynamics.

pub fn dmd_residual(
    result: &DmdResult,
) -> ResidualResult
Parameter Type Description
result &DmdResult A previously computed DMD decomposition.

Returns: ResidualResult -- per-mode and aggregate residual norms.

dmd_dominant_modes

Select the most significant modes according to a ranking criterion (amplitude, energy, or growth rate).

pub fn dmd_dominant_modes(
    result: &DmdResult,
    criterion: DominantCriterion,
    n: usize,
) -> Vec<ModeInfo>
Parameter Type Description
result &DmdResult A previously computed DMD decomposition.
criterion DominantCriterion Ranking criterion: Amplitude, Energy, or GrowthRate.
n usize Number of top modes to return.

Returns: Vec<ModeInfo> -- the top n modes sorted by the chosen criterion in descending order.

dmd_pseudospectrum

Compute the pseudospectrum of the DMD operator on a grid in the complex plane. Useful for assessing sensitivity of eigenvalues to perturbations.

pub fn dmd_pseudospectrum(
    result: &DmdResult,
    re_range: (f64, f64),
    im_range: (f64, f64),
    resolution: usize,
) -> PseudospectrumResult
Parameter Type Description
result &DmdResult A previously computed DMD decomposition.
re_range (f64, f64) Range of the real axis (min, max).
im_range (f64, f64) Range of the imaginary axis (min, max).
resolution usize Number of grid points along each axis.

Returns: PseudospectrumResult -- grid coordinates and resolvent norm values for contour plotting.

dmd_convergence

Evaluate how the DMD decomposition changes across a sequence of truncation ranks. Useful for selecting an appropriate rank.

pub fn dmd_convergence(
    data: &Mat<f64>,
    ranks: &[usize],
) -> Vec<ConvergenceResult>
Parameter Type Description
data &Mat<f64> Snapshot matrix.
ranks &[usize] List of truncation ranks to evaluate.

Returns: Vec<ConvergenceResult> -- one entry per rank with eigenvalues, reconstruction error, and mode stability metrics.

use koopman_dmd::{dmd, dmd_spectrum, dmd_stability, dmd_convergence, DmdConfig};

let result = dmd(&data, &DmdConfig::default())?;

// Spectral analysis with dt = 0.01
let spectrum = dmd_spectrum(&result, 0.01);
for mode in &spectrum {
    println!("freq={:.4} growth={:.4} energy={:.4}",
        mode.frequency, mode.growth_rate, mode.energy);
}

// Stability classification
let stab = dmd_stability(&result, 1e-6);
println!("Stable modes:   {:?}", stab.stable);
println!("Unstable modes: {:?}", stab.unstable);

// Convergence study
let conv = dmd_convergence(&data, &[2, 4, 8, 16]);
for c in &conv {
    println!("rank={} error={:.6}", c.rank, c.error);
}

Lifting

Nonlinear lifting functions augment the observable space for Extended DMD. The lifted data is passed through standard DMD and the results are projected back to the original state space.

LiftingConfig

pub enum LiftingConfig {
    Polynomial { degree: usize },
    Trigonometric { harmonics: usize },
    Delay { delays: usize },
}
Variant Fields Description
Polynomial degree: usize Augment with polynomial terms up to the given degree (e.g., degree 2 adds x^2, xy, y^2 for 2-D state).
Trigonometric harmonics: usize Augment with sine and cosine terms at the specified number of harmonic frequencies.
Delay delays: usize Augment via time-delay embedding, appending the specified number of lagged copies of the state.

lift_data

Apply a lifting transformation to a snapshot matrix and return the augmented matrix together with metadata for inverse projection.

pub fn lift_data(
    data: &Mat<f64>,
    config: &LiftingConfig,
) -> (Mat<f64>, LiftingInfo)
Parameter Type Description
data &Mat<f64> Original snapshot matrix.
config &LiftingConfig Lifting configuration specifying the augmentation strategy.

Returns: a tuple of the lifted data matrix and a LiftingInfo struct recording the original dimensions and lifting parameters.

use koopman_dmd::{dmd, lift_data, DmdConfig, LiftingConfig};

// Polynomial lifting with degree 3
let config = DmdConfig {
    lifting: Some(LiftingConfig::Polynomial { degree: 3 }),
    ..DmdConfig::default()
};
let result = dmd(&data, &config)?;

// Or lift manually
let (lifted, info) = lift_data(&data, &LiftingConfig::Trigonometric { harmonics: 5 });

Hankel-DMD

Hankel-DMD uses time-delay embedding via Hankel matrices to capture higher-order dynamics from scalar or low-dimensional measurements. The data is restructured into a block-Hankel matrix before the standard DMD algorithm is applied.

HankelConfig

pub struct HankelConfig {
    pub delays: Option<usize>,
    pub rank: Option<usize>,
    pub dt: f64,
}
Field Type Default Description
delays Option<usize> None Number of delay embeddings. None selects automatically.
rank Option<usize> None Truncation rank for the SVD on the Hankel matrix.
dt f64 1.0 Sampling interval for continuous-time frequency conversion.

hankel_dmd

Perform Hankel-DMD on a snapshot matrix. Constructs the delay-embedded Hankel matrix internally and returns a specialized result type.

pub fn hankel_dmd(
    data: &Mat<f64>,
    config: &HankelConfig,
) -> Result<HankelDmdResult, DmdError>
Parameter Type Description
data &Mat<f64> Snapshot matrix (may be scalar time series as a 1-by-n matrix).
config &HankelConfig Hankel-DMD configuration.

Returns: Result<HankelDmdResult, DmdError> -- decomposition result including the Hankel structure metadata.

hankel_reconstruct

Reconstruct the original (non-embedded) time series from a Hankel-DMD result.

pub fn hankel_reconstruct(
    result: &HankelDmdResult,
    n_time: usize,
) -> Result<Mat<f64>, DmdError>

hankel_predict

Predict future time steps from a Hankel-DMD result, projecting back to the original observation space.

pub fn hankel_predict(
    result: &HankelDmdResult,
    n_ahead: usize,
) -> Result<Mat<f64>, DmdError>
use koopman_dmd::{hankel_dmd, hankel_reconstruct, hankel_predict, HankelConfig};

let config = HankelConfig {
    delays: Some(10),
    rank: Some(6),
    dt: 0.01,
};
let result = hankel_dmd(&signal, &config)?;
let fitted = hankel_reconstruct(&result, 200)?;
let future = hankel_predict(&result, 50)?;

GLA (Generalized Laplace Analysis)

Generalized Laplace Analysis extracts Koopman eigenvalues and eigenfunctions from trajectory data using spectral methods. Unlike standard DMD, GLA can resolve eigenvalues that are not well-separated and handles continuous spectra.

GlaConfig

pub struct GlaConfig {
    pub eigenvalues: Option<Vec<C64>>,
    pub n_eigenvalues: usize,
    pub tol: f64,
    pub max_iter: Option<usize>,
}
Field Type Default Description
eigenvalues Option<Vec<C64>> None Known or initial-guess eigenvalues. If None, eigenvalues are estimated from the data.
n_eigenvalues usize 10 Number of eigenvalues to extract (ignored when eigenvalues is provided).
tol f64 1e-10 Convergence tolerance for the iterative solver.
max_iter Option<usize> None Maximum number of iterations. None uses a library default.

gla

Run Generalized Laplace Analysis on trajectory data.

pub fn gla(
    data: &Mat<f64>,
    config: &GlaConfig,
) -> Result<GlaResult, DmdError>
Parameter Type Description
data &Mat<f64> Trajectory data matrix.
config &GlaConfig GLA configuration.

Returns: Result<GlaResult, DmdError> -- extracted eigenvalues, eigenfunctions, and convergence information.

gla_predict

Predict future states using the GLA decomposition.

pub fn gla_predict(
    result: &GlaResult,
    n_ahead: usize,
) -> Result<Mat<f64>, DmdError>

gla_reconstruct

Reconstruct the training trajectory from the GLA decomposition.

pub fn gla_reconstruct(
    result: &GlaResult,
    n_time: usize,
) -> Result<Mat<f64>, DmdError>
use koopman_dmd::{gla, gla_predict, gla_reconstruct, GlaConfig, C64};

// Extract 8 eigenvalues with default tolerance
let config = GlaConfig {
    eigenvalues: None,
    n_eigenvalues: 8,
    tol: 1e-10,
    max_iter: Some(1000),
};
let result = gla(&trajectory, &config)?;
println!("Eigenvalues: {:?}", result.eigenvalues);

let fitted = gla_reconstruct(&result, 500)?;
let future = gla_predict(&result, 100)?;

Harmonic Analysis

Harmonic time averages isolate Koopman modes at specific frequencies. Given a dynamical map and an observable, the harmonic time average at frequency omega converges to the projection of the observable onto the Koopman eigenfunction at that frequency.

Observable

pub enum Observable {
    Identity,
    SinPi,
    CosPi,
    SinPiXY,
    Quadratic,
}
Variant Description
Identity The identity observable g(x) = x.
SinPi g(x) = sin(pi * x) applied to the first component.
CosPi g(x) = cos(pi * x) applied to the first component.
SinPiXY g(x, y) = sin(pi * x * y) for 2-D state vectors.
Quadratic g(x) = x^2 applied component-wise.

harmonic_time_average

Compute the harmonic time average of an observable along a trajectory generated by a dynamical map at a specified frequency.

pub fn harmonic_time_average(
    ic: &[f64],
    map: &dyn MapFn,
    obs: &Observable,
    omega: f64,
    n_iter: usize,
) -> Result<HtaResult, DmdError>
Parameter Type Description
ic &[f64] Initial condition for the trajectory.
map &dyn MapFn Dynamical map to iterate (see Maps).
obs &Observable Observable function to evaluate along the trajectory.
omega f64 Target frequency for the harmonic average.
n_iter usize Number of map iterations to compute the average over.

Returns: Result<HtaResult, DmdError> -- the converged harmonic time average value and convergence diagnostics.

classify_phase_space

Classify regions of phase space based on harmonic time average behavior. Identifies periodic islands, chaotic seas, and cantori.

pub fn classify_phase_space(
    map: &dyn MapFn,
    obs: &Observable,
    omega: f64,
    n_iter: usize,
    grid: &[(f64, f64)],
) -> Vec<PhaseClassification>

hta_convergence

Monitor convergence of the harmonic time average as a function of iteration count. Useful for determining sufficient averaging length.

pub fn hta_convergence(
    ic: &[f64],
    map: &dyn MapFn,
    obs: &Observable,
    omega: f64,
    checkpoints: &[usize],
) -> Vec<HtaResult>

hta_from_values

Compute the harmonic time average from pre-computed observable values rather than generating a trajectory internally.

pub fn hta_from_values(
    values: &[f64],
    omega: f64,
) -> HtaResult
use koopman_dmd::{
    harmonic_time_average, hta_convergence,
    Observable, StandardMap,
};

let map = StandardMap { epsilon: 0.5 };
let ic = [0.1, 0.2];

// Single harmonic time average
let hta = harmonic_time_average(&ic, &map, &Observable::CosPi, 0.0, 10000)?;
println!("HTA value: {:?}", hta.value);

// Convergence study
let checkpoints = vec![100, 500, 1000, 5000, 10000];
let conv = hta_convergence(&ic, &map, &Observable::CosPi, 0.0, &checkpoints);

Maps

Built-in dynamical maps implement the MapFn trait. These are used for testing, benchmarking, and as inputs to harmonic analysis and mesochronic computations.

MapFn (Trait)

pub trait MapFn {
    /// Advance the state by one step.
    fn step(&self, state: &[f64]) -> Vec<f64>;

    /// Dimension of the state space.
    fn dim(&self) -> usize;
}

Built-in Maps

Struct Fields Dimension Description
StandardMap epsilon: f64 2 Chirikov standard map on the torus. Perturbation strength controlled by epsilon.
FroeschleMap epsilon: f64 4 Four-dimensional symplectic map generalizing the standard map.
ExtendedStandardMap epsilon: f64 4 Coupled pair of standard maps with additional coupling parameter.
HenonMap a: f64, b: f64 2 Henon map with classical parameters a = 1.4, b = 0.3 by default.
LogisticMap r: f64 1 Logistic map x -> r * x * (1 - x).

generate_trajectory

Generate a trajectory by iterating a map from an initial condition.

pub fn generate_trajectory(
    ic: &[f64],
    map: &dyn MapFn,
    n: usize,
) -> Mat<f64>
Parameter Type Description
ic &[f64] Initial condition (length must match map.dim()).
map &dyn MapFn Dynamical map to iterate.
n usize Number of steps (output has n + 1 columns including the initial condition).

Returns: Mat<f64> -- trajectory matrix with shape (dim, n + 1).

use koopman_dmd::{generate_trajectory, StandardMap, HenonMap};

// Standard map trajectory
let smap = StandardMap { epsilon: 0.97 };
let traj = generate_trajectory(&[0.1, 0.2], &smap, 10000);

// Henon map trajectory
let henon = HenonMap { a: 1.4, b: 0.3 };
let traj = generate_trajectory(&[0.0, 0.0], &henon, 5000);

Mesochronic

Mesochronic analysis computes finite-time Koopman operator properties over a grid of initial conditions, producing phase-space portraits that reveal the structure of the dynamics.

mesochronic_compute

Compute a mesochronic harmonic portrait over a 2-D grid of initial conditions. For each grid point, a trajectory is generated and the harmonic time average is evaluated.

pub fn mesochronic_compute(
    map: &dyn MapFn,
    x_range: (f64, f64),
    y_range: (f64, f64),
    resolution: usize,
    observable: &Observable,
    omega: f64,
    n_iter: usize,
) -> Result<MhpResult, DmdError>
Parameter Type Description
map &dyn MapFn Dynamical map to iterate at each grid point.
x_range (f64, f64) Range of the first state variable (min, max).
y_range (f64, f64) Range of the second state variable (min, max).
resolution usize Number of grid points along each axis.
observable &Observable Observable function to evaluate.
omega f64 Frequency for the harmonic time average.
n_iter usize Number of map iterations per grid point.

Returns: Result<MhpResult, DmdError> -- grid coordinates and harmonic time average values at each point.

mesochronic_scatter

Compute mesochronic values at a scattered set of initial conditions (not on a regular grid). Useful for adaptive refinement or sampling along specific structures.

pub fn mesochronic_scatter(
    map: &dyn MapFn,
    points: &[(f64, f64)],
    observable: &Observable,
    omega: f64,
    n_iter: usize,
) -> Result<Vec<HtaResult>, DmdError>

mesochronic_section

Compute mesochronic values along a 1-D cross-section of phase space. Produces a line profile through the mesochronic portrait.

pub fn mesochronic_section(
    map: &dyn MapFn,
    start: (f64, f64),
    end: (f64, f64),
    n_points: usize,
    observable: &Observable,
    omega: f64,
    n_iter: usize,
) -> Result<Vec<HtaResult>, DmdError>
use koopman_dmd::{
    mesochronic_compute, mesochronic_section,
    StandardMap, Observable,
};

let map = StandardMap { epsilon: 0.97 };

// Full 2-D portrait
let portrait = mesochronic_compute(
    &map,
    (0.0, 1.0),      // x range
    (0.0, 1.0),      // y range
    256,             // resolution
    &Observable::CosPi,
    0.0,             // omega
    5000,            // iterations
)?;

// 1-D cross-section
let section = mesochronic_section(
    &map,
    (0.0, 0.5),      // start point
    (1.0, 0.5),      // end point
    500,             // number of sample points
    &Observable::CosPi,
    0.0,
    5000,
)?;