Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
a6b4d33
added empty notebook for nested OpInf tutorial
nicolearetz Sep 2, 2025
7cfe878
continued notebook for nested OpInf: load data, build reduced space
nicolearetz Sep 3, 2025
3326a16
fixed Gram Schmidt
nicolearetz Sep 3, 2025
9871a0a
finished reduced space in nested tutorial notebook
nicolearetz Sep 4, 2025
49567c5
finished reference OpInf model for nested tutorial
nicolearetz Sep 4, 2025
f234ec1
format changes according to flake
nicolearetz Sep 9, 2025
11fc5f4
added regularization towards an initial guess in parametric continuou…
nicolearetz Sep 10, 2025
2bfbc6c
finished standard OpInf approach example for nested Opinf tutorial no…
nicolearetz Sep 10, 2025
b46f773
added initial guesses to non-parametric
nicolearetz Oct 20, 2025
7a232ec
added documentation about initial guesses
nicolearetz Oct 20, 2025
3546224
fixed codes and tests
nicolearetz Oct 20, 2025
33b3a8f
started on nested OpInf notebook
nicolearetz Oct 20, 2025
d297a15
Merge pull request #2 from nicolearetz/nested-OpInf
nicolearetz Oct 20, 2025
dc8dee8
removed nested notebook because not finished yet
nicolearetz Oct 20, 2025
7d911c4
merge changes
nicolearetz Oct 20, 2025
9479c77
deleted nested opinf notebook (not ready yet)
nicolearetz Oct 20, 2025
66b3d36
added restriction to subspaces for polyn. operators
nicolearetz Oct 21, 2025
c0cf985
added tests for restriction to subspaces
nicolearetz Oct 21, 2025
cc1bc40
added tests for space extension and restriction
nicolearetz Oct 21, 2025
30face8
added nested OpInf notebook
nicolearetz Oct 22, 2025
3600e2a
fixed merge conflicts?
nicolearetz Oct 22, 2025
9bb97d4
deleted nested tutorial notebook (not ready yet)
nicolearetz Oct 22, 2025
5ff4c5c
Merge branch 'Willcox-Research-Group:main' into main
nicolearetz Oct 22, 2025
848fde1
removed initial_guess from model classes
nicolearetz Oct 22, 2025
2e8e667
removed initial guesses from model classes
nicolearetz Oct 22, 2025
88deae6
added tests for regularization towards initial guesses
nicolearetz Oct 29, 2025
cf25bba
added documentation
nicolearetz Oct 29, 2025
abd7889
fixed typo
nicolearetz Oct 29, 2025
4b3df00
removed data folder for tutorials
nicolearetz Nov 10, 2025
95560b0
renamed remove_initial_guess to _subtract_initial_guess for consisten…
nicolearetz Nov 10, 2025
9be1759
removed _Ohat variable from models as it already exists as attribute
nicolearetz Nov 10, 2025
c191842
tweak docstrings about Ohat initial guess
shanemcq18 Nov 10, 2025
baabb15
added documentation for restrict_to_subspace and restrict_matrix_to_s…
nicolearetz Nov 17, 2025
2a92b9a
added docstring for PolynomialOperator._columnIndices_p
nicolearetz Nov 17, 2025
caa9e2d
added docstring for PolynomialOperator.extend_to_dimension
nicolearetz Nov 17, 2025
37e58bd
added docstring for PolynomialOperator._extend_matrix_to_dimension
nicolearetz Nov 17, 2025
2ec4dee
Merge branch 'main' of https://github.com/nicolearetz/rom-operator-in…
nicolearetz Nov 17, 2025
e7ad590
fixed naming error
nicolearetz Nov 17, 2025
dad5d87
fixed errors caused by changed function names
nicolearetz Nov 17, 2025
d3c5141
fixed test for initial guess
nicolearetz Nov 17, 2025
12ea086
copy function for polynomial operators
nicolearetz Jan 9, 2026
faf8885
added missing .shape to an error message
nicolearetz Jan 10, 2026
3d546ce
added operator expansion and restriction for input operators
nicolearetz Jan 12, 2026
f68b069
minor comment tweaks
shanemcq18 Jan 13, 2026
f4fd736
deprecate Python 3.9, test on 3.14, fix mpl tcl issue
shanemcq18 Jan 13, 2026
c3e5492
version 0.5.16 -> 0.5.17
shanemcq18 Jan 15, 2026
5b845e3
DerivativeEstimatorTemplate.mask no longer abstract, fixes ddt docs
shanemcq18 Jan 15, 2026
c258a59
modify GitHub Actions mpl backend, attempt 2
shanemcq18 Jan 15, 2026
079dc6a
modify GitHub Actions mpl backend, attempt 3
shanemcq18 Jan 15, 2026
3992df9
modify GitHub Actions mpl backend, FIXED!
shanemcq18 Jan 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/test_src.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ jobs:
- windows-latest
- macos-latest
python-version:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand All @@ -39,5 +39,8 @@ jobs:
python -m pip install --upgrade pip
python -m pip install tox
- name: Run tests
if: runner.os == 'Windows'
env:
MPLBACKEND: Agg # Fix a bug in GitHub Actions for Windows
run: |
python -m tox -e py${{ matrix.python-version }}
2 changes: 1 addition & 1 deletion .github/workflows/test_style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: 3.12
python-version: 3.14
- name: Install tox
run: |
python -m pip install --upgrade pip
Expand Down
2 changes: 1 addition & 1 deletion docs/source/contributing/how_to_contribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Style checks, unit tests, and documentation builds are managed with [`tox`](http
For each of these tasks, `tox` creates a new virtual environment, installs the dependencies (e.g., `pytest` for running unit tests), and executes the task recipe.

:::{note}
Unit tests are executed for Python 3.9 through 3.12 if they are installed on your system.
Unit tests are executed for Python 3.10 through 3.14 if they are installed on your system.
The best way to install multiple Python versions varies by platform; for MacOS, [we suggest](https://stackoverflow.com/questions/36968425/how-can-i-install-multiple-versions-of-python-on-latest-os-x-and-use-them-in-par#answer-65094122) using [Homebrew](https://brew.sh/).

```shell
Expand Down
4 changes: 2 additions & 2 deletions docs/source/contributing/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ If all tests pass, a line coverage report will be generated.
Open `htmlcov/index.html` in a browser to view the report.

:::{note}
Running `tox` without any arguments tests the code for Python 3.9 through 3.12 (if they are installed on your system).
To test a single Python version, use `tox -e py310` for Python 3.10, `tox -e py311` for Python3.11, and so on.
Running `tox` without any arguments tests the code for Python 3.10 through 3.14 (if they are installed on your system).
To test a single Python version, use `tox -e py314` for Python 3.14, `tox -e py313` for Python3.13, and so on.
:::

## GitHub Actions
Expand Down
9 changes: 9 additions & 0 deletions docs/source/opinf/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@
New versions may introduce substantial new features or API adjustments.
:::

## Version 0.5.17

- Dropped support for Python 3.9, added test coverage for Python 3.14.
- Tikhonov / L2 least-squares now take an initial guess
- Expansion of operators to larger or smaller bases (for nested OpInf)
- Parametric and nonparametric polynomial operators of arbitrary order
- Bases now have a `fit_compress()` method
- Update `utils.TimedBlock` to use `time.process_time()`

## Version 0.5.16

Backend improvements to the regularization selection procedure.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ authors = [
]
maintainers = [{ name = "Shane A. McQuarrie", email = "[email protected]" }]
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.9"
requires-python = ">=3.10"
license = { file = "LICENSE" }
keywords = [
"operator inference",
Expand Down
2 changes: 1 addition & 1 deletion src/opinf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
https://github.com/Willcox-Research-Group/rom-operator-inference-Python3
"""

__version__ = "0.5.16"
__version__ = "0.5.17"

from . import (
basis,
Expand Down
47 changes: 47 additions & 0 deletions src/opinf/basis/_pod.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,64 @@ def method_of_snapshots(
eigvals = eigvals[::-1]
eigvecs = eigvecs[:, ::-1]

# can at most have as many non-zero eigenvalues as there was data
if eigvals.shape[0] > states.shape[0]:
eigvals[states.shape[0] :] = 0
if eigvals.shape[0] > states.shape[1]:
eigvals[states.shape[1] :] = 0

# By definition the Gramian is symmetric positive semi-definite.
# If any eigenvalues are smaller than zero, they are only measuring
# numerical error and can be truncated.
positives = eigvals > max(minthresh, abs(np.min(eigvals)))

if sum(positives) > states.shape[0]:
print(eigvals)
print(positives)
raise RuntimeError(
f"""selected more non-zero singular values {sum(positives)}
than there are state dimensions ({states.shape[0]})"""
)

# can at most have as many non-zero entries as there were state dofs
eigvecs = eigvecs[:, positives]
eigvals = eigvals[positives]

# Rescale and square root eigenvalues to get singular values.
svals = np.sqrt(eigvals * n_states)
V = states @ (eigvecs / svals)

# if basis functions are not orthonormal, apply Gram-Schmidt
counter = 0

def inner_product(V):
if inner_product_matrix is None:
return V.T @ V
return V.T @ _Wmult(inner_product_matrix, V)

while (
not np.isclose(inner_product(V), np.eye(V.shape[1])).all()
) and counter < 10:
for i in range(V.shape[1]):
v_i = V[:, i]
for j in range(i):
v_i = (
v_i
- (v_i.T @ _Wmult(inner_product_matrix, V[:, j])) * V[:, j]
)
norm_vi = np.sqrt(v_i.T @ _Wmult(inner_product_matrix, v_i))
V[:, i] = v_i / norm_vi

if V.shape[0] != states.shape[0]:
print(V.shape, counter)
raise RuntimeError(
"something went seriously wrong in computation of V"
)
counter += 1

if not np.isclose(inner_product(V), np.eye(V.shape[1])).all():
raise RuntimeWarning("Computed basis functions are not orthonormal.")

return V, svals, eigvecs.T


Expand Down
3 changes: 1 addition & 2 deletions src/opinf/ddt/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ def estimate(self, states, inputs=None):
"""
raise NotImplementedError # pragma: no cover

@abc.abstractmethod
def mask(self, arr):
"""Map an array from the training time domain to the domain of the
estimated time derivatives.
Expand All @@ -171,7 +170,7 @@ def mask(self, arr):
>>> Q3.shape == Q.shape
True
"""
raise NotImplementedError # pragma: no cover
return arr

# Verification ------------------------------------------------------------
def verify_shapes(self, r: int = 5, m: int = 3): # pragma: no cover
Expand Down
Loading