iSVD-ROM is a lightweight Python framework for online, adaptive, hyper-reduced reduced-order modeling (ROM) of time-dependent nonlinear PDEs. The reduced basis is updated on the fly using the incremental singular value decomposition (iSVD) driven by a coarse-step full-order model (FOM) that acts as a cheap correction signal. The core projection is a Least-Squares Petrov-Galerkin (LSPG) ROM with DEIM-based hyper-reduction, so every online ingredient — basis, sampling, residual, Jacobian — is updated consistently.
This is the companion code to our paper:
History-Aware Adaptive Reduced-Order Modeling via Incremental SVD.
[paper placeholder — will be linked upon publication]
If you use this code, please cite the paper (see CITATION.cff).
Classical (static) projection-based ROMs train the reduced basis offline on snapshot data and then freeze it online. For transport-dominated, parametric, or long-horizon problems, the frozen subspace quickly stops representing the solution and the ROM accuracy collapses. iSVD-ROM addresses this by continuously adapting the basis online, using a small number of coarse-step FOM evaluations as a periodic correction signal. The history-aware iSVD update merges the adapted information with the existing basis in a numerically stable, rank-preserving way.
Key features:
- History-aware iSVD basis update with a tunable forgetting factor.
- Alternative update rules included for comparison: windowed SVD, direct update, one-step rank-one, Oja's rule, GROUSE.
- LSPG + DEIM hyper-reduction, with QDEIM for sampling index selection.
- Problem-agnostic core: the online loop is decoupled from the equation, so any implicit nonlinear solver can be plugged in.
- Reference implementations for the 1D viscous Burgers equation and the 1D Sod shock tube.
git clone https://github.com/TBD/iSVD-ROM.git
cd iSVD-ROM
pip install -e .Python ≥ 3.9 with NumPy, SciPy, and Matplotlib (see requirements.txt). The demo notebooks also need Jupyter:
pip install -e ".[notebooks]"ffmpeg must be installed separately if you wish to save animations via the animate_comparison helper.
from isvd_rom import compute_pod_basis, qdeim
from isvd_rom.problems.burgers import BurgersSolver, BurgersAdaptiveLSPG
# 1) Run the FOM to get training + reference snapshots.
fom = BurgersSolver(Nx=1000, L=1.0, nu=0.01, dt=1e-3)
snaps = fom.simulate(fom.initial_condition(), n_steps=500)
# 2) Offline basis + DEIM indices from a handful of early snapshots.
Phi, S = compute_pod_basis(snaps[:, :4], r=4)
p_inds = qdeim(Phi, n_sensors=4).tolist()
# 3) Adaptive LSPG + DEIM ROM with iSVD basis update.
rom = BurgersAdaptiveLSPG(
Phi=Phi, Sigma=S, p_inds=p_inds,
dt=1e-3, nu=0.01, dx=fom.dx, L=1.0,
zs=10, # adapt every 10 ROM steps
basis_update_method="iSVD",
basis_update_param=0.1, # iSVD forgetting factor
)
a0 = Phi.T @ snaps[:, 0]
u_pred = rom.simulate(a0, n_steps=500) # shape: (n_steps+1, Nx)See notebooks/burgers.ipynb and notebooks/sod.ipynb for fully worked examples with plots and sensitivity studies over adaptation methods.
Every zs ROM steps, iSVD-ROM performs a single coarse FOM step to obtain an updated full-order state $\tilde{u}k$. This "correction signal" is used to update the reduced basis $\Phi_k \to \Phi{k+1}$ via iSVD (or any of the alternative rules), and then the DEIM indices are refreshed via QDEIM. The reduced coordinates are re-projected onto the new basis and the LSPG Newton iteration continues with refreshed hyper-reduction data. The full algorithm is Algorithm 1 in the paper; the iSVD step itself is Algorithm 2.
offline online (loop)
┌───────────┐ ┌────────────────────────────────────────────────────┐
│ FOM snaps │──▶│ LSPG step (Newton) ────────────────┐ │
└───────────┘ │ │ │ │
│ ▼ │ │
┌───────────┐ │ every zs steps: ▼ │
│ POD basis │──▶│ · one coarse FOM step (signal) ──▶ basis update │
└───────────┘ │ │ │
┌───────────┐ │ ▼ │
│ QDEIM │──▶│ QDEIM re-sampling │
└───────────┘ │ │ │
│ ▼ │
│ reproject coords ─────┘
└────────────────────────────────────────────────────┘
iSVD-ROM/
├── isvd_rom/
│ ├── core/
│ │ ├── basis_adaptation.py # iSVD, windowed SVD, direct, one-step, Oja, GROUSE
│ │ ├── pod.py # POD via thin SVD
│ │ ├── sampling.py # QDEIM
│ │ ├── rom_base.py # LSPGROMBase: generic static ROM
│ │ └── adaptive_rom.py # AdaptiveLSPGBase: generic adaptive loop
│ ├── problems/
│ │ ├── burgers/ # 1D viscous Burgers: FOM + static/adaptive ROM
│ │ └── sod/ # 1D Sod shock tube: FOM + static/adaptive ROM
│ └── utils/
│ └── visualization.py # matplotlib helpers
├── notebooks/
│ ├── burgers.ipynb # Demo 1
│ └── sod.ipynb # Demo 2
├── pyproject.toml
├── requirements.txt
├── LICENSE
├── CITATION.cff
└── README.md
The core modules are entirely problem-agnostic and reusable across equations. The problems modules are concrete templates showing how to couple a specific equation's hyper-reduced residual and Jacobian to the core machinery.
All problem-specific code lives behind two methods on the ROM class. To adapt iSVD-ROM to a new equation you only need to:
- Provide a FOM solver that exposes a
.step(u, tol, max_iter, verbose)method advancing your full state by one time step. Any existing implicit solver you have will do. - Subclass
AdaptiveLSPGBaseand implement:residual_sample(self, a, a_old) -> (ns,) ndarray— the full-order residual restricted to the sampling indicesself.p_inds, evaluated atu = self.Phi @ a.jacobian_sample(self, a) -> (ns, r) ndarray— the corresponding restricted Jacobian times the basis.
from isvd_rom.core.adaptive_rom import AdaptiveLSPGBase
class MyAdaptiveROM(AdaptiveLSPGBase):
def residual_sample(self, a, a_old):
u = self.Phi @ a
# ...compute f(u) at rows self.p_inds...
return self.Phi[self.p_inds] @ (a - a_old) + self.dt * Fp
def jacobian_sample(self, a):
u = self.Phi @ a
# ...compute (df/du)(u) @ Phi at rows self.p_inds...
return JfPhi_sampThen construct and run:
rom = MyAdaptiveROM(
Phi=Phi, Sigma=S, p_inds=p_inds, dt=dt,
fom_solver=my_coarse_fom, zs=10,
basis_update_method="iSVD", basis_update_param=0.1,
)
u_pred = rom.simulate(a0, n_steps=500)isvd_rom/problems/burgers/rom.py and isvd_rom/problems/sod/rom.py are concrete, commented templates demonstrating both of these methods in practice.
The notebooks/burgers.ipynb and notebooks/sod.ipynb notebooks reproduce the 1D Burgers and 1D Sod experiments from the paper. A third experiment (the rotating detonation engine, RDE) was run on a cluster and is out of scope for this repository. The RDE study can be reproduced by plugging the respective FOM solver and hyper-reduced operators into the same AdaptiveLSPGBase class following the template above.
MIT.
Please cite the accompanying paper; a BibTeX entry will be added upon publication. See CITATION.cff for a machine-readable entry.
@article{isvd_rom2026,
title = {History-Aware Adaptive Reduced-Order Modeling via Incremental SVD},
author = {Amirpasha Hedayat and Ali Mohaghegh and Laura Balzano and Cheng Huang and Karthik Duraisamy},
journal = {TBD},
year = {2026},
note = {URL TBD}
}