diff --git a/.github/workflows/testing_pr.yml b/.github/workflows/testing_pr.yml index de77bf0..bbdef74 100644 --- a/.github/workflows/testing_pr.yml +++ b/.github/workflows/testing_pr.yml @@ -5,7 +5,6 @@ on: branches: - "master" - jobs: build: runs-on: ${{ matrix.os }} @@ -14,21 +13,47 @@ jobs: matrix: os: [windows-latest, macos-latest, ubuntu-latest] python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + + env: + CFLAGS: "-Wno-error=implicit-function-declaration -Wno-error=incompatible-pointer-types" + CXXFLAGS: "-Wno-error=implicit-function-declaration -Wno-error=incompatible-pointer-types" steps: - uses: actions/checkout@v4 - - name: Set up Python uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} + - name: Install system dependencies (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y libboost-serialization-dev libprotobuf-dev protobuf-compiler libopenblas-dev liblapack-dev + + - name: Set up Java for PyCOMPSs + if: runner.os == 'Linux' + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '11' + - name: Install Python dependencies + shell: bash run: | python3 -m pip install --upgrade pip + python3 -m pip install setuptools wheel + if [ "$RUNNER_OS" == "Linux" ]; then + python3 -m pip install pycompss --no-build-isolation + fi python3 -m pip install .[test] - name: Test with pytest + shell: bash run: | - python3 -m pytest + if [ "$RUNNER_OS" == "Linux" ]; then + python3 -m pytest + else + python3 -m pytest --ignore=tests/test_parallel/ + fi \ No newline at end of file diff --git a/ezyrb/parallel/__init__.py b/ezyrb/parallel/__init__.py index 0d60b17..91e7e25 100644 --- a/ezyrb/parallel/__init__.py +++ b/ezyrb/parallel/__init__.py @@ -18,7 +18,10 @@ from .reduction import Reduction from .pod import POD from .ae import AE -from .ae_eddl import AE_EDDL +try: + from .ae_eddl import AE_EDDL +except ImportError: + pass from .approximation import Approximation from .rbf import RBF from .linear import Linear diff --git a/ezyrb/parallel/pod.py b/ezyrb/parallel/pod.py index 680aff8..60548fe 100644 --- a/ezyrb/parallel/pod.py +++ b/ezyrb/parallel/pod.py @@ -11,8 +11,17 @@ from numpy.linalg import eigh import numpy as np -from pycompss.api.task import task -from pycompss.api.parameter import INOUT, IN +try: + from pycompss.api.task import task + from pycompss.api.parameter import INOUT, IN +except ImportError: + # Fallback: Define a 'do-nothing' decorator and dummy constants + def task(*args, **kwargs): + return lambda f: f + + INOUT = None + IN = None + from .reduction import Reduction diff --git a/ezyrb/parallel/reducedordermodel.py b/ezyrb/parallel/reducedordermodel.py index fe3bb4b..8df6e28 100644 --- a/ezyrb/parallel/reducedordermodel.py +++ b/ezyrb/parallel/reducedordermodel.py @@ -4,12 +4,15 @@ import copy import pickle import numpy as np -from scipy.spatial.qhull import Delaunay +from scipy.spatial import Delaunay from sklearn.model_selection import KFold from pycompss.api.api import compss_wait_on +from ..database import Database +from ..reducedordermodel import ReducedOrderModelInterface -class ReducedOrderModel: + +class ReducedOrderModel(ReducedOrderModelInterface): """ Reduced Order Model class. @@ -22,36 +25,14 @@ class ReducedOrderModel: order model. :param ezyrb.Approximation approximation: the approximation method to use in reduced order model. - :param object scaler_red: the scaler for the reduced variables (eg. modal - coefficients). Default is None. - - :cvar ezyrb.Database database: the database used for training the reduced - order model. - :cvar ezyrb.Reduction reduction: the reduction method used in reduced order - model. - :cvar ezyrb.Approximation approximation: the approximation method used in - reduced order model. - :cvar object scaler_red: the scaler for the reduced variables (eg. modal - coefficients). - - :Example: - - >>> from ezyrb import ReducedOrderModel as ROM - >>> from ezyrb import POD, RBF, Database - >>> pod = POD() - >>> rbf = RBF() - >>> # param, snapshots and new_param are assumed to be declared - >>> db = Database(param, snapshots) - >>> rom = ROM(db, pod, rbf).fit() - >>> rom.predict(new_param) - + :param list plugins: list of plugins to use in the reduced order model. """ - def __init__(self, database, reduction, approximation, scaler_red=None): + def __init__(self, database, reduction, approximation, plugins=None): self.database = database self.reduction = reduction self.approximation = approximation - self.scaler_red = scaler_red + self.plugins = plugins if plugins is not None else [] def fit(self, *args, **kwargs): r""" @@ -60,52 +41,115 @@ def fit(self, *args, **kwargs): :param \*args: additional parameters to pass to the `fit` method. :param \**kwargs: additional parameters to pass to the `fit` method. """ - self.reduction.fit(self.database.snapshots.T) + # Assign the initial training database + self.train_full_database = self.database + + self._execute_plugins("fit_preprocessing") + self._execute_plugins("fit_before_reduction") + + # Fit reduction and transform + self.reduction.fit(self.train_full_database.snapshots_matrix.T) reduced_output = self.reduction.transform( - self.database.snapshots.T, self.scaler_red + self.train_full_database.snapshots_matrix.T + ).T + + # Store the reduced database for plugins + self.train_reduced_database = Database( + self.train_full_database.parameters_matrix, reduced_output ) + self._execute_plugins("fit_after_reduction") + self._execute_plugins("fit_before_approximation") + + # Fit approximation on the reduced database self.approximation.fit( - self.database.parameters, reduced_output, *args, **kwargs + self.train_reduced_database.parameters_matrix, + self.train_reduced_database.snapshots_matrix, + *args, **kwargs ) + self._execute_plugins("fit_after_approximation") + self._execute_plugins("fit_postprocessing") + return self - def predict(self, mu): - """ - Calculate predicted solution for given mu + def predict(self, parameters): + r""" + Predict the solution for given parameters mu. + + This method distributes the evaluation tasks across the + available computational nodes using the PyCOMPSs framework. """ - mu = np.atleast_2d(mu) - if hasattr(self, "database") and self.database.scaler_parameters: - mu = self.database.scaler_parameters.transform(mu) + is_db = hasattr(parameters, 'parameters_matrix') + mu = parameters.parameters_matrix if is_db else np.atleast_2d(parameters) + + # Setup dummy test_full_database required by some preprocessing plugins + dummy_snaps = np.zeros((len(mu), self.train_full_database.snapshots_matrix.shape[1])) + self.test_full_database = Database(mu, dummy_snaps) + + # The scaler plugin modifies parameters here BEFORE approximation, + # so we must initialize this object early with dummy snapshots. + dummy_red_snaps = np.zeros((len(mu), self.train_reduced_database.snapshots_matrix.shape[1])) + self.predict_reduced_database = Database(mu, dummy_red_snaps) + + self._execute_plugins("predict_preprocessing") + self._execute_plugins("predict_before_approximation") + + # Predict the reduced solution (using potentially scaled parameters) + predicted_red_sol = self.approximation.predict( + self.predict_reduced_database.parameters_matrix + ) + + # Update by creating a NEW database, as snapshots_matrix is read-only + self.predict_reduced_database = Database( + self.predict_reduced_database.parameters_matrix, + predicted_red_sol + ) - predicted_red_sol = self.approximation.predict(mu, self.scaler_red) + self._execute_plugins("predict_after_approximation") + self._execute_plugins("predict_before_expansion") + # Expand back to full space predicted_sol = self.reduction.inverse_transform( - predicted_red_sol, self.database + self.predict_reduced_database.snapshots_matrix.T + ).T + + # Store the final result for plugins + self.predicted_full_database = Database( + self.predict_reduced_database.parameters_matrix, predicted_sol ) - return predicted_sol + self._execute_plugins("predict_after_expansion") + self._execute_plugins("predict_postprocessing") - def save(self, fname, save_db=True, save_reduction=True, save_approx=True): + if is_db: + return self.predicted_full_database + return self.predicted_full_database.snapshots_matrix + + def test_error(self, test, norm=np.linalg.norm, relative=True): """ - Save the object to `fname` using the pickle module. - - :param str fname: the name of file where the reduced order model will - be saved. - :param bool save_db: Flag to select if the `Database` will be saved. - :param bool save_reduction: Flag to select if the `Reduction` will be - saved. - :param bool save_approx: Flag to select if the `Approximation` will be - saved. - - Example: - - >>> from ezyrb import ReducedOrderModel as ROM - >>> rom = ROM(...) # Construct here the rom - >>> rom.fit() - >>> rom.save('ezyrb.rom') + Compute the mean norm of the relative error vectors of predicted + test snapshots. """ + predicted_test = self.predict(test.parameters_matrix) + + if hasattr(predicted_test, 'snapshots_matrix'): + pred_snaps = predicted_test.snapshots_matrix + else: + pred_snaps = predicted_test + + if relative: + return np.mean( + norm(pred_snaps - test.snapshots_matrix, axis=1) + / norm(test.snapshots_matrix, axis=1) + ) + else: + return np.mean( + norm(pred_snaps - test.snapshots_matrix, axis=1) + ) + + def save(self, fname, save_db=True, save_reduction=True, save_approx=True): + """Save the object to `fname` using the pickle module.""" rom_to_store = copy.copy(self) if not save_db: @@ -120,39 +164,13 @@ def save(self, fname, save_db=True, save_reduction=True, save_approx=True): @staticmethod def load(fname): - """ - Load the object from `fname` using the pickle module. - - :return: The `ReducedOrderModel` loaded - - Example: - - >>> from ezyrb import ReducedOrderModel as ROM - >>> rom = ROM.load('ezyrb.rom') - >>> rom.predict(new_param) - """ + """Load the object from `fname` using the pickle module.""" with open(fname, "rb") as output: rom = pickle.load(output) - return rom def kfold_cv_error(self, n_splits, *args, norm=np.linalg.norm, **kwargs): - r""" - Split the database into k consecutive folds (no shuffling by default). - Each fold is used once as a validation while the k - 1 remaining folds - form the training set. If `n_splits` is equal to the number of - snapshots this function is the same as `loo_error` but the error here - is relative and not absolute. - - :param int n_splits: number of folds. Must be at least 2. - :param function norm: function to apply to compute the relative error - between the true snapshot and the predicted one. - Default value is the L2 norm. - :param \*args: additional parameters to pass to the `fit` method. - :param \**kwargs: additional parameters to pass to the `fit` method. - :return: the vector containing the errors corresponding to each fold. - :rtype: numpy.ndarray - """ + """Split the database into k consecutive folds.""" error = [] predicted_test = [] # to save my future objects original_test = [] @@ -163,11 +181,15 @@ def kfold_cv_error(self, n_splits, *args, norm=np.linalg.norm, **kwargs): new_db, copy.deepcopy(self.reduction), copy.deepcopy(self.approximation), + plugins=[copy.deepcopy(p) for p in self.plugins] ).fit(*args, **kwargs) test = self.database[test_index] - predicted_test.append(rom.predict(test.parameters)) - original_test.append(test.snapshots) + pred = rom.predict(test.parameters_matrix) + if hasattr(pred, 'snapshots_matrix'): + pred = pred.snapshots_matrix + predicted_test.append(pred) + original_test.append(test.snapshots_matrix) predicted_test = compss_wait_on(predicted_test) for j in range(len(predicted_test)): @@ -181,24 +203,7 @@ def kfold_cv_error(self, n_splits, *args, norm=np.linalg.norm, **kwargs): return np.array(error) def loo_error(self, *args, norm=np.linalg.norm, **kwargs): - r""" - Estimate the approximation error using *leave-one-out* strategy. The - main idea is to create several reduced spaces by combining all the - snapshots except one. The error vector is computed as the difference - between the removed snapshot and the projection onto the properly - reduced space. The procedure repeats for each snapshot in the database. - The `norm` is applied on each vector of error to obtained a float - number. - - :param function norm: the function used to assign at each vector of - error a float number. It has to take as input a 'numpy.ndarray` and - returns a float. Default value is the L2 norm. - :param \*args: additional parameters to pass to the `fit` method. - :param \**kwargs: additional parameters to pass to the `fit` method. - :return: the vector that contains the errors estimated for all - parametric points. - :rtype: numpy.ndarray - """ + """Estimate the approximation error using *leave-one-out* strategy.""" error = np.zeros(len(self.database)) db_range = list(range(len(self.database))) predicted_test = [] # to save my future objects @@ -214,10 +219,14 @@ def loo_error(self, *args, norm=np.linalg.norm, **kwargs): new_db, copy.deepcopy(self.reduction), copy.deepcopy(self.approximation), + plugins=[copy.deepcopy(p) for p in self.plugins] ).fit(*args, **kwargs) - predicted_test.append(rom.predict(test_db.parameters)) - original_test.append(test_db.snapshots) + pred = rom.predict(test_db.parameters_matrix) + if hasattr(pred, 'snapshots_matrix'): + pred = pred.snapshots_matrix + predicted_test.append(pred) + original_test.append(test_db.snapshots_matrix) predicted_test = compss_wait_on(predicted_test) for j in range(len(predicted_test)): @@ -229,24 +238,11 @@ def loo_error(self, *args, norm=np.linalg.norm, **kwargs): return error def optimal_mu(self, error=None, k=1): - """ - Return the parametric points where new high-fidelity solutions have to - be computed in order to globally reduce the estimated error. These - points are the barycentric center of the region (simplex) with higher - error. - - :param numpy.ndarray error: the estimated error evaluated for each - snapshot; if error array is not passed, it is computed using - :func:`loo_error` with the default function. Default value is None. - :param int k: the number of optimal points to return. Default value is - 1. - :return: the optimal points - :rtype: numpy.ndarray - """ + """Return the parametric points where new high-fidelity solutions have to be computed.""" if error is None: error = self.loo_error() - mu = self.database.parameters + mu = self.database.parameters_matrix tria = Delaunay(mu) error_on_simplex = np.array( @@ -268,19 +264,8 @@ def optimal_mu(self, error=None, k=1): return np.asarray(barycentric_point) def _simplex_volume(self, vertices): - """ - Method implementing the computation of the volume of a N dimensional - simplex. - Source from: `wikipedia.org/wiki/Simplex - `_. - - :param numpy.ndarray simplex_vertices: Nx3 array containing the - parameter values representing the vertices of a simplex. N is the - dimensionality of the parameters. - :return: N dimensional volume of the simplex. - :rtype: float - """ + """Method implementing the computation of the volume of a N dimensional simplex.""" distance = np.transpose([vertices[0] - vi for vi in vertices[1:]]) return np.abs( np.linalg.det(distance) / math.factorial(vertices.shape[1]) - ) + ) \ No newline at end of file diff --git a/ezyrb/reducedordermodel.py b/ezyrb/reducedordermodel.py index cbe0a8d..6f6ef9b 100644 --- a/ezyrb/reducedordermodel.py +++ b/ezyrb/reducedordermodel.py @@ -462,7 +462,8 @@ def kfold_cv_error( Split the database into k consecutive folds (no shuffling by default). Each fold is used once as a validation while the k - 1 remaining folds form the training set. If `n_splits` is equal to the number of - snapshots this function is the same as `loo_error`. + snapshots this function is the same as `loo_error` but the error here + is relative and not absolute. :param int n_splits: number of folds. Must be at least 2. :param function norm: function to apply to compute the relative error diff --git a/pyproject.toml b/pyproject.toml index 863409b..33e8213 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,12 +30,16 @@ docs = [ ] test = [ "pytest", - "pytest-cov" + "pytest-cov", + "torch" ] dev = [ "black", "pylint" ] +parallel = [ + "pycompss" +] [project.urls] Homepage = "https://github.com/mathLab/EZyRB" diff --git a/tests/test_ae.py b/tests/test_ae.py index 2d70eed..d13639f 100644 --- a/tests/test_ae.py +++ b/tests/test_ae.py @@ -23,7 +23,7 @@ def test_reconstruction(activation): assert snapshots_1.shape == snapshots.shape assert snapshots_2.shape == snapshots.shape - np.testing.assert_array_equal(snapshots_1, snapshots_2) + np.testing.assert_allclose(snapshots_1, snapshots_2, rtol=1e-5, atol=1e-5) rerr = np.linalg.norm(snapshots_2 - snapshots)/np.linalg.norm(snapshots) assert rerr < 0.6 # Relaxed tolerance for sklearn diff --git a/tests/test_parallel/__init__.py b/tests/test_parallel/__init__.py new file mode 100644 index 0000000..e1ed488 --- /dev/null +++ b/tests/test_parallel/__init__.py @@ -0,0 +1 @@ +# This file marks tests/test_parallel as a package. diff --git a/tests/test_parallel/conftest.py b/tests/test_parallel/conftest.py new file mode 100644 index 0000000..60b27b0 --- /dev/null +++ b/tests/test_parallel/conftest.py @@ -0,0 +1,2 @@ +import matplotlib +matplotlib.use('Agg') diff --git a/tests/test_parallel/test_ae.py b/tests/test_parallel/test_ae.py new file mode 100644 index 0000000..028b2f3 --- /dev/null +++ b/tests/test_parallel/test_ae.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_ae import * diff --git a/tests/test_parallel/test_ann.py b/tests/test_parallel/test_ann.py new file mode 100644 index 0000000..da94bd3 --- /dev/null +++ b/tests/test_parallel/test_ann.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_ann import * diff --git a/tests/test_parallel/test_approximation.py b/tests/test_parallel/test_approximation.py new file mode 100644 index 0000000..914fd96 --- /dev/null +++ b/tests/test_parallel/test_approximation.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_approximation import * diff --git a/tests/test_parallel/test_database.py b/tests/test_parallel/test_database.py new file mode 100644 index 0000000..bea7117 --- /dev/null +++ b/tests/test_parallel/test_database.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_database import * diff --git a/tests/test_parallel/test_gpr.py b/tests/test_parallel/test_gpr.py new file mode 100644 index 0000000..e02e54a --- /dev/null +++ b/tests/test_parallel/test_gpr.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_gpr import * diff --git a/tests/test_parallel/test_k_neighbors_regressor.py b/tests/test_parallel/test_k_neighbors_regressor.py new file mode 100644 index 0000000..abcea93 --- /dev/null +++ b/tests/test_parallel/test_k_neighbors_regressor.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_k_neighbors_regressor import * diff --git a/tests/test_parallel/test_linear.py b/tests/test_parallel/test_linear.py new file mode 100644 index 0000000..f489b6e --- /dev/null +++ b/tests/test_parallel/test_linear.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_linear import * diff --git a/tests/test_parallel/test_nnshift.py b/tests/test_parallel/test_nnshift.py new file mode 100644 index 0000000..6285e18 --- /dev/null +++ b/tests/test_parallel/test_nnshift.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_nnshift import * diff --git a/tests/test_parallel/test_parameter.py b/tests/test_parallel/test_parameter.py new file mode 100644 index 0000000..5b4c7c3 --- /dev/null +++ b/tests/test_parallel/test_parameter.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_parameter import * diff --git a/tests/test_parallel/test_pod.py b/tests/test_parallel/test_pod.py new file mode 100644 index 0000000..0f2f1c1 --- /dev/null +++ b/tests/test_parallel/test_pod.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_pod import * diff --git a/tests/test_parallel/test_podae.py b/tests/test_parallel/test_podae.py new file mode 100644 index 0000000..3f1d613 --- /dev/null +++ b/tests/test_parallel/test_podae.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_podae import * diff --git a/tests/test_parallel/test_radius_neighbors_regressor.py b/tests/test_parallel/test_radius_neighbors_regressor.py new file mode 100644 index 0000000..ace7848 --- /dev/null +++ b/tests/test_parallel/test_radius_neighbors_regressor.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_radius_neighbors_regressor import * diff --git a/tests/test_parallel/test_reducedordermodel.py b/tests/test_parallel/test_reducedordermodel.py new file mode 100644 index 0000000..30d57ba --- /dev/null +++ b/tests/test_parallel/test_reducedordermodel.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_reducedordermodel import * diff --git a/tests/test_parallel/test_regular_grid.py b/tests/test_parallel/test_regular_grid.py new file mode 100644 index 0000000..dba4d22 --- /dev/null +++ b/tests/test_parallel/test_regular_grid.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_regular_grid import * diff --git a/tests/test_parallel/test_scaler.py b/tests/test_parallel/test_scaler.py new file mode 100644 index 0000000..3cbe3c2 --- /dev/null +++ b/tests/test_parallel/test_scaler.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_scaler import * diff --git a/tests/test_parallel/test_shift.py b/tests/test_parallel/test_shift.py new file mode 100644 index 0000000..3c97d36 --- /dev/null +++ b/tests/test_parallel/test_shift.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_shift import * diff --git a/tests/test_parallel/test_sklearn_wrappers.py b/tests/test_parallel/test_sklearn_wrappers.py new file mode 100644 index 0000000..eef74e4 --- /dev/null +++ b/tests/test_parallel/test_sklearn_wrappers.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_sklearn_wrappers import * diff --git a/tests/test_parallel/test_snapshot.py b/tests/test_parallel/test_snapshot.py new file mode 100644 index 0000000..f19cea5 --- /dev/null +++ b/tests/test_parallel/test_snapshot.py @@ -0,0 +1,7 @@ +import pytest + +import ezyrb +from ezyrb.parallel import ReducedOrderModel as ParallelROM +ezyrb.ReducedOrderModel = ParallelROM + +from tests.test_snapshot import *