Skip to main content

ModalDyn

Turn time-ordered snapshots into interpretable modes and short-horizon forecasts.

ModalDyn is a compact Dynamic Mode Decomposition (DMD) toolkit for researchers and engineers who want to understand evolving systems, not just fit a black box. Start with NumPy, inspect the model's diagnostics, and use the same estimator API with optional PyTorch CPU or CUDA execution.

PyPI · API guide · Examples · Limitations

Why ModalDyn?

  • A small starting point. The basic installation needs only NumPy; PyTorch is optional.
  • A model you can inspect. Examine eigenvalues, modes, numerical rank, conditioning and fitted one-step error instead of relying on a forecast alone.
  • Several workflows, one package. Reconstruct snapshots, forecast dynamics, include measured controls, or add delay coordinates for partial observations.
  • Explicit computation. Choose the backend and device. A request for unavailable CUDA fails clearly rather than silently falling back to CPU.

Where it fits

These are application ideas, not claims of validation on production datasets:

Your data A useful starting question
Time-ordered fluid or simulation fields Which coherent patterns evolve together, and at which rates?
Vibration or multi-sensor recordings Can a low-dimensional model describe oscillations and forecast a held-out interval?
Measurements from an actuated experiment How do the observed states respond to known control inputs?

DMD approximates dynamics with a linear evolution model. It is especially useful when a few modes explain the behavior over the time window you care about. Choose rank and other settings on training/validation data, then test a future interval that the model has never seen.

Install

Python 3.10+ and NumPy 1.24+ are required.

python -m pip install modaldyn

Optional PyTorch support:

python -m pip install 'modaldyn[torch]'

For a specific CPU or CUDA build, follow the official PyTorch installation guide. The extra does not install a GPU driver or guarantee CUDA availability.

Quickstart: forecast a held-out oscillation

Each column is a snapshot and each row is a feature. In this reproducible synthetic example, two sensor channels follow a damped oscillation. The first 80 snapshots train the model; the last 20 are used only for evaluation.

import numpy as np
from modaldyn import DMD

angle = 0.16
operator = 0.995 * np.array([
    [np.cos(angle), -np.sin(angle)],
    [np.sin(angle),  np.cos(angle)],
])
snapshots = np.empty((2, 100))  # 2 channels, 100 equally spaced observations
snapshots[:, 0] = [1.0, 0.2]
for k in range(99):
    snapshots[:, k + 1] = operator @ snapshots[:, k]

model = DMD(rank=2, dt=0.1).fit(snapshots[:, :80])
reconstruction = model.reconstruct()  # shape (2, 80), includes the first snapshot
forecast = model.forecast(20)        # shape (2, 20), starts AFTER the last training point
truth = snapshots[:, 80:]
relative_error = np.linalg.norm(forecast - truth) / np.linalg.norm(truth)

print("Reconstruction:", reconstruction.shape)
print("Forecast:", forecast.shape)
print("Held-out relative error:", f"{relative_error:.2e}")
print("Retained rank:", model.diagnostics()["rank"])
assert relative_error < 1e-10  # check for this noiseless linear example only

The output shapes are (2, 80) and (2, 20), with retained rank 2. The error is near numerical precision because the example follows an exact linear model. This is a reproducibility check, not a real-world accuracy claim. For measured data, compare against a simple baseline and evaluate multiple held-out windows. Complex-valued modes and forecasts are normal for oscillations; only discard the imaginary part when its residual is negligible.

Example: forecast a system with known controls

Suppose an experiment records two state variables and one actuator input. DMDc fits the relationship x[k+1] = A @ x[k] + B @ u[k]. This synthetic example shows the required alignment: 81 state snapshots pair with 80 control inputs, one input for each transition.

import numpy as np
from modaldyn import DMDc

rng = np.random.default_rng(12)
A = np.array([[0.93, 0.08], [-0.05, 0.97]])
B = np.array([[0.15], [0.40]])
controls = rng.standard_normal((1, 120))
states = np.empty((2, 121))
states[:, 0] = [0.4, -0.2]
for k in range(120):
    states[:, k + 1] = A @ states[:, k] + B @ controls[:, k]

model = DMDc().fit(states[:, :81], controls[:, :80])
forecast = model.forecast(controls[:, 80:])  # 40 supplied FUTURE control inputs
truth = states[:, 81:]
relative_error = np.linalg.norm(forecast - truth) / np.linalg.norm(truth)

print("Controlled forecast:", forecast.shape)  # (2, 40)
print("Held-out relative error:", f"{relative_error:.2e}")
assert forecast.shape == truth.shape
assert relative_error < 1e-10

The future controls are inputs you provide, not values predicted by the model. Reliable identification needs sufficiently informative state/control data. This noiseless example verifies the API and alignment; it does not establish performance on a physical experiment.

Pick the right estimator

Estimator Use it when Keep in mind
DMD You want an exact-DMD baseline Uniform time spacing and a useful low-rank linear approximation
TLSqDMD / FbDMD You are exploring noise-aware formulations Tune TLS rank; forward/backward DMD has experimental spectral-root limits
RandomizedDMD You want a seeded low-rank approximation Specify an integer rank; measure the accuracy/cost trade-off
HankelDMD Delay coordinates may expose hidden dynamics More memory; choose delays without leaking test data
DMDc Measured controls influence the evolution Align each control with its state transition
RobustDMD Sparse corruptions motivate RPCA preprocessing Assumes low-rank structure plus sparse corruption; iterative dense SVDs
StreamingDMD You cannot retain the full snapshot history Dense sufficient statistics still need O(features²) memory

See the API guide for parameters, alignment rules and variant-specific diagnostics.

CPU, PyTorch and CUDA

The examples above use NumPy on CPU. For the PyTorch backend, use backend="torch", device="cpu" in the estimator; device="cuda" requests CUDA explicitly. Forecasts use the selected backend. backend="auto" follows an input tensor's backend/device; NumPy input defaults to NumPy unless CUDA is explicitly requested.

Validation: CI exercises NumPy on Python 3.10–3.13 and PyTorch on CPU. CUDA code and optional tests are included, but GPU hardware correctness and performance have not been established for this release. Skipped CUDA tests are not GPU validation. Small problems may be faster on CPU because transfers and synchronization have a cost.

Scope and trade-offs

This is an alpha research package, not a universal forecasting solution. A small training residual does not guarantee useful future predictions. Nonstationarity, noise, rank choice and insufficient measurements can all change results. Read the limitations before interpreting a model.

ModalDyn favors a compact NumPy-first API and explicit diagnostics/device choice. PyDMD offers a broader variant catalogue; GPU-enabled DMD also exists elsewhere. There is no claim of universal speed or accuracy superiority. The source-backed comparison covers PyDMD, PyKoopman, datafold and flowTorch. Optimized/bagged DMD, EDMD, multiresolution DMD and sparsity-promoting DMD are outside this release.

Learn more and contribute

Original implementation by Giovanny Torres, released under the MIT license. Please cite the relevant algorithm papers listed in the comparison and references when using these methods in research.

Metadata

Release files for modaldyn 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for modaldyn 0.1.2
File Size Uploaded Provenance Actions
modaldyn-0.1.2.tar.gz 47.9 kB With provenance Details for modaldyn-0.1.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for modaldyn 0.1.2
File Interpreter ABI Platform Actions
modaldyn-0.1.2-py3-none-any.whl Python 3 none any Details for modaldyn-0.1.2-py3-none-any.whl

Total release size: 68.8 kB

Release files / modaldyn-0.1.2.tar.gz

Download URL modaldyn-0.1.2.tar.gz
Size 47.9 kB
Tags Source
SHA-256 checksum
How to use checksums
c0a2b3998f9b5d909199d3e875fd5f1fc8db66b8d1f614e132e7ddc7b241a713
BLAKE2b-256 checksum
How to use checksums
458173db8c50665fad5b6a7d5fc050faa552bfc6fd0d51388cd297c9d51ec11f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.

Transparency log

Release files / modaldyn-0.1.2-py3-none-any.whl

Download URL modaldyn-0.1.2-py3-none-any.whl
Size 20.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
268ebf572b39d5484c4d048a96e4b22e9a6e776fb8044c135c904e62ffcc9035
BLAKE2b-256 checksum
How to use checksums
1453ce7047e9669381b3cf2745766a103c7cbc6cc486ceedf4a1eb279594913c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.

Transparency log

Security for modaldyn 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for modaldyn-0.1.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page