diff --git a/romtools/vector_space/__init__.py b/romtools/vector_space/__init__.py index e9c2301..7779ff1 100644 --- a/romtools/vector_space/__init__.py +++ b/romtools/vector_space/__init__.py @@ -239,15 +239,15 @@ def __init__(self, shifter = create_noop_shifter(snapshots) n_var = snapshots.shape[0] shifter.apply_shift(snapshots) - scaled_shifted_snapshots = scaler.pre_scale(snapshots) - snapshot_matrix = _tensor_to_matrix(scaled_shifted_snapshots) + scaler.pre_scale(snapshots) + snapshot_matrix = _tensor_to_matrix(snapshots) svd_picked = np.linalg.svd if svdFnc is None else svdFnc lsv, svals, _ = svd_picked(snapshot_matrix, full_matrices=False, compute_uv=True, hermitian=False) self.__basis = truncater.truncate(lsv, svals) self.__basis = _matrix_to_tensor(n_var, self.__basis) - self.__basis = scaler.post_scale(self.__basis) + scaler.post_scale(self.__basis) self.__basis = _tensor_to_matrix(self.__basis) self.__basis = orthogonalizer.orthogonalize(self.__basis) self.__basis = _matrix_to_tensor(n_var, self.__basis) diff --git a/romtools/vector_space/utils/scaler.py b/romtools/vector_space/utils/scaler.py index 0ca17f8..221a603 100644 --- a/romtools/vector_space/utils/scaler.py +++ b/romtools/vector_space/utils/scaler.py @@ -89,15 +89,15 @@ class Scaler(Protocol): Interface for the Scaler class. """ - def pre_scale(self, data_tensor: np.ndarray) -> np.ndarray: + def pre_scale(self, data_tensor: np.ndarray) -> None: """ - Scales the snapshot matrix before performing SVD + Scales the snapshot matrix in place before performing SVD """ ... - def post_scale(self, data_tensor: np.ndarray) -> np.ndarray: + def post_scale(self, data_tensor: np.ndarray) -> None: """ - Scales the left singular vectors after performing SVD + Scales the left singular vectors in place after performing SVD """ ... @@ -112,11 +112,11 @@ class NoOpScaler: def __init__(self) -> None: pass - def pre_scale(self, data_tensor: np.ndarray) -> np.ndarray: - return data_tensor + def pre_scale(self, data_tensor: np.ndarray): + data_tensor = data_tensor - def post_scale(self, data_tensor) -> np.ndarray: - return data_tensor + def post_scale(self, data_tensor): + data_tensor = data_tensor class VectorScaler: @@ -148,7 +148,7 @@ def __init__(self, scaling_vector) -> None: self.__scaling_vector_matrix = scaling_vector self.__scaling_vector_matrix_inv = 1.0 / scaling_vector - def pre_scale(self, data_tensor: np.ndarray) -> np.ndarray: + def pre_scale(self, data_tensor: np.ndarray) -> None: """ Scales the input data matrix using the inverse of the scaling vector and returns the scaled matrix. @@ -159,9 +159,9 @@ def pre_scale(self, data_tensor: np.ndarray) -> np.ndarray: Returns: np.ndarray: The scaled data matrix. """ - return self.__scaling_vector_matrix_inv[None, :, None] * data_tensor + data_tensor *= self.__scaling_vector_matrix_inv[None, :, None] - def post_scale(self, data_tensor: np.ndarray) -> np.ndarray: + def post_scale(self, data_tensor: np.ndarray) -> None: """ Scales the input data matrix using the scaling vector and returns the scaled matrix. @@ -172,7 +172,7 @@ def post_scale(self, data_tensor: np.ndarray) -> np.ndarray: Returns: np.ndarray: The scaled data matrix. """ - return self.__scaling_vector_matrix[None, :, None] * data_tensor + data_tensor *= self.__scaling_vector_matrix[None, :, None] class ScalarScaler: @@ -186,10 +186,10 @@ def __init__(self, factor: float = 1.0) -> None: self._factor = factor def pre_scale(self, data_tensor: np.ndarray) -> np.ndarray: - return data_tensor / self._factor + data_tensor /= self._factor def post_scale(self, data_tensor: np.ndarray) -> np.ndarray: - return data_tensor * self._factor + data_tensor *= self._factor class VariableScaler: @@ -252,7 +252,7 @@ def initialize_scalings(self, data_tensor: np.ndarray) -> None: self.have_scales_been_initialized = True # These are all inplace operations - def pre_scale(self, data_tensor: np.ndarray) -> np.ndarray: + def pre_scale(self, data_tensor: np.ndarray) -> None: """ Scales the input data matrix before processing, taking into account the previously initialized scaling factors. @@ -270,10 +270,9 @@ def pre_scale(self, data_tensor: np.ndarray) -> np.ndarray: self.initialize_scalings(data_tensor) # scale each field (variable scaling) for i in range(n_var): - data_tensor[i] = data_tensor[i] / self.var_scales_[i] - return data_tensor + data_tensor[i] /= self.var_scales_[i] - def post_scale(self, data_tensor: np.ndarray) -> np.ndarray: + def post_scale(self, data_tensor: np.ndarray) -> None: """ Scales the input data matrix using the scaling vector and returns the scaled matrix. @@ -288,9 +287,7 @@ def post_scale(self, data_tensor: np.ndarray) -> np.ndarray: # scale each field n_var = data_tensor.shape[0] for i in range(n_var): - data_tensor[i] = data_tensor[i] * self.var_scales_[i] - return data_tensor - + data_tensor[i] *= self.var_scales_[i] class VariableAndVectorScaler: """ @@ -320,7 +317,7 @@ def __init__(self, scaling_vector, scaling_type) -> None: self.__my_variable_scaler = VariableScaler(scaling_type) self.__my_vector_scaler = VectorScaler(scaling_vector) - def pre_scale(self, data_tensor: np.ndarray) -> np.ndarray: + def pre_scale(self, data_tensor: np.ndarray) -> None: """ Scales the input data matrix before processing, first using the `VariableScaler` and then the `VectorScaler`. @@ -331,10 +328,10 @@ def pre_scale(self, data_tensor: np.ndarray) -> np.ndarray: Returns: np.ndarray: The scaled data matrix. """ - data_tensor = self.__my_variable_scaler.pre_scale(data_tensor) - return self.__my_vector_scaler.pre_scale(data_tensor) + self.__my_variable_scaler.pre_scale(data_tensor) + self.__my_vector_scaler.pre_scale(data_tensor) - def post_scale(self, data_tensor: np.ndarray) -> np.ndarray: + def post_scale(self, data_tensor: np.ndarray) -> None: """ Scales the input data matrix after processing, first using the `VectorScaler` and then the `VariableScaler`. @@ -345,5 +342,5 @@ def post_scale(self, data_tensor: np.ndarray) -> np.ndarray: Returns: np.ndarray: The scaled data matrix. """ - data_tensor = self.__my_vector_scaler.post_scale(data_tensor) - return self.__my_variable_scaler.post_scale(data_tensor) + self.__my_vector_scaler.post_scale(data_tensor) + self.__my_variable_scaler.post_scale(data_tensor) diff --git a/tests/romtools/test_vector_space.py b/tests/romtools/test_vector_space.py index d9c40d3..eef06e4 100644 --- a/tests/romtools/test_vector_space.py +++ b/tests/romtools/test_vector_space.py @@ -89,12 +89,12 @@ def test_trial_space_from_scaled_pod(): snapshots = np.random.normal(size=(3, 8, 6)) my_scaler = utils.VariableScaler("max_abs") my_vector_space = rt.VectorSpaceFromPOD(copy.deepcopy(snapshots), scaler=my_scaler) - scaled_snapshots = my_scaler.pre_scale(snapshots) - snapshotMatrix = _tensor_to_matrix(scaled_snapshots) + my_scaler.pre_scale(snapshots) + snapshotMatrix = _tensor_to_matrix(snapshots) u, s, v = np.linalg.svd(snapshotMatrix, full_matrices=False) basis_tensor = my_vector_space.get_basis() u = u.reshape(basis_tensor.shape) - u = my_scaler.post_scale(u) + my_scaler.post_scale(u) assert np.allclose(u, basis_tensor), print(u, my_vector_space.get_basis()) assert np.allclose(6, my_vector_space.extents()[-1]) assert np.allclose(0, my_vector_space.get_shift_vector()) @@ -107,12 +107,12 @@ def test_trial_space_from_scaled_pod(): my_scaler = utils.VariableScaler("max_abs") my_vector_space = rt.VectorSpaceFromPOD(snapshots, shifter=my_shifter, scaler=my_scaler) my_shifter.apply_shift(shifted_snapshots) - scaled_shifted_snapshots = my_scaler.pre_scale(shifted_snapshots) - snapshot_matrix = _tensor_to_matrix(scaled_shifted_snapshots) + my_scaler.pre_scale(shifted_snapshots) + snapshot_matrix = _tensor_to_matrix(shifted_snapshots) u, s, v = np.linalg.svd(snapshot_matrix, full_matrices=False) basis_tensor = my_vector_space.get_basis() u = u.reshape(basis_tensor.shape) - u = my_scaler.post_scale(u) + my_scaler.post_scale(u) assert np.allclose(basis_tensor, u) # FAILS assert np.allclose(my_vector_space.get_shift_vector(), np.mean(original_snapshots, axis=2)) assert np.allclose(my_vector_space.extents()[-1], 6) @@ -128,13 +128,13 @@ def test_trial_space_from_scaled_pod(): my_vector_space = rt.VectorSpaceFromPOD(snapshots, shifter=my_shifter, scaler=my_scaler, orthogonalizer=my_orthogonalizer) my_shifter.apply_shift(shifted_snapshots) my_scaler = utils.VariableScaler("max_abs") - scaled_shifted_snapshots = my_scaler.pre_scale(shifted_snapshots) - snapshot_matrix = _tensor_to_matrix(scaled_shifted_snapshots) + my_scaler.pre_scale(shifted_snapshots) + snapshot_matrix = _tensor_to_matrix(shifted_snapshots) u, s, v = np.linalg.svd(snapshot_matrix, full_matrices=False) ushp = u.shape basis_tensor = my_vector_space.get_basis() u = u.reshape(basis_tensor.shape) - u = my_scaler.post_scale(u) + my_scaler.post_scale(u) u = my_orthogonalizer.orthogonalize(u.reshape(ushp)) u = u.reshape(basis_tensor.shape) assert np.allclose(basis_tensor, u) diff --git a/tests/romtools/test_vector_space_utils/test_scaler.py b/tests/romtools/test_vector_space_utils/test_scaler.py index a1fa147..9de47b6 100644 --- a/tests/romtools/test_vector_space_utils/test_scaler.py +++ b/tests/romtools/test_vector_space_utils/test_scaler.py @@ -15,10 +15,11 @@ def test_noop_scaler(): scaler = NoOpScaler() my_snapshots = np.random.normal(size=(3, 10, 2)) - my_scaled_snapshots = scaler.pre_scale(my_snapshots) - my_unscaled_snapshots = scaler.post_scale(my_scaled_snapshots) - assert np.allclose(my_snapshots, my_scaled_snapshots) - assert np.allclose(my_scaled_snapshots, my_unscaled_snapshots) + orig_snapshots = copy.deepcopy(my_snapshots) + scaler.pre_scale(my_snapshots) + assert np.allclose(my_snapshots, orig_snapshots) + scaler.post_scale(my_snapshots) + assert np.allclose(my_snapshots, orig_snapshots) @pytest.mark.mpi(min_size=3) @@ -26,10 +27,11 @@ def test_noop_scaler_mpi(): comm = MPI.COMM_WORLD scaler = NoOpScaler() local_snapshots, _ = generate_random_local_and_global_arrays_impl((3, 10, 2), comm=comm) - scaled_local_snapshots = scaler.pre_scale(local_snapshots) - unscaled_local_snapshots = scaler.post_scale(scaled_local_snapshots) - assert np.allclose(local_snapshots, scaled_local_snapshots) - assert np.allclose(scaled_local_snapshots, unscaled_local_snapshots) + orig_snapshots = copy.deepcopy(local_snapshots) + scaler.pre_scale(local_snapshots) + assert np.allclose(local_snapshots, orig_snapshots) + scaler.post_scale(local_snapshots) + assert np.allclose(local_snapshots, orig_snapshots) def scaling_op(scaling_type, arg): @@ -50,11 +52,11 @@ def test_scalar_scaler(): my_initial_snapshots = copy.deepcopy(my_snapshots) scaler = ScalarScaler(my_scaling_factor) - my_scaled_snapshots = scaler.pre_scale(my_snapshots) + scaler.pre_scale(my_snapshots) + assert np.allclose(my_snapshots, 1.0 / my_scaling_factor * my_initial_snapshots) - assert np.allclose(my_scaled_snapshots, 1.0 / my_scaling_factor * my_initial_snapshots) - my_unscaled_snapshots = scaler.post_scale(my_scaled_snapshots) - assert np.allclose(my_initial_snapshots, my_unscaled_snapshots) + scaler.post_scale(my_snapshots) + assert np.allclose(my_snapshots, my_initial_snapshots) @pytest.mark.mpi_skip @@ -66,11 +68,11 @@ def test_vector_scaler(): my_initial_snapshots = copy.deepcopy(my_snapshots) scaler = VectorScaler(my_scaling_vector) - my_scaled_snapshots = scaler.pre_scale(my_snapshots) + scaler.pre_scale(my_snapshots) + assert np.allclose(my_snapshots, 1.0 / my_scaling_vector[None, :, None] * my_initial_snapshots) - assert np.allclose(my_scaled_snapshots, 1.0 / my_scaling_vector[None, :, None] * my_initial_snapshots) - my_unscaled_snapshots = scaler.post_scale(my_scaled_snapshots) - assert np.allclose(my_initial_snapshots, my_unscaled_snapshots) + scaler.post_scale(my_snapshots) + assert np.allclose(my_snapshots, my_initial_snapshots) @pytest.mark.mpi(min_size=3) @@ -83,11 +85,11 @@ def test_vector_scaler_mpi(): initial_local_snapshots = copy.deepcopy(local_snapshots) scaler = VectorScaler(my_scaling_vector) - scaled_local_snapshots = scaler.pre_scale(local_snapshots) + scaler.pre_scale(local_snapshots) + assert np.allclose(local_snapshots, 1.0 / my_scaling_vector[None, :, None] * initial_local_snapshots) - assert np.allclose(scaled_local_snapshots, 1.0 / my_scaling_vector[None, :, None] * initial_local_snapshots) - unscaled_local_snapshots = scaler.post_scale(scaled_local_snapshots) - assert np.allclose(initial_local_snapshots, unscaled_local_snapshots) + scaler.post_scale(local_snapshots) + assert np.allclose(local_snapshots, initial_local_snapshots) @pytest.mark.mpi_skip @@ -103,13 +105,13 @@ def run_test(scaling_type): my_initial_snapshots = copy.deepcopy(my_snapshots) scaler = VariableScaler(scaling_type) - my_scaled_snapshots = scaler.pre_scale(my_snapshots) + scaler.pre_scale(my_snapshots) for i in range(0, n_var): - assert np.allclose(my_scaled_snapshots[i], 1.0 / scales[i] * my_initial_snapshots[i]) + assert np.allclose(my_snapshots[i], 1.0 / scales[i] * my_initial_snapshots[i]) - my_unscaled_snapshots = scaler.post_scale(my_scaled_snapshots) + scaler.post_scale(my_snapshots) assert np.allclose(scales, scaler.var_scales_) - assert np.allclose(my_initial_snapshots, my_unscaled_snapshots) + assert np.allclose(my_initial_snapshots, my_snapshots) run_test("max_abs") run_test("mean_abs") @@ -130,13 +132,13 @@ def run_test(scaling_type): initial_local_snapshots = copy.deepcopy(local_snapshots) scaler = VariableScaler(scaling_type) - scaled_local_snapshots = scaler.pre_scale(local_snapshots) + scaler.pre_scale(local_snapshots) for i in range(0, n_var): - assert np.allclose(scaled_local_snapshots[i], 1.0 / scales[i] * initial_local_snapshots[i]) + assert np.allclose(local_snapshots[i], 1.0 / scales[i] * initial_local_snapshots[i]) - unscaled_local_snapshots = scaler.post_scale(scaled_local_snapshots) + scaler.post_scale(local_snapshots) assert np.allclose(scales, scaler.var_scales_) - assert np.allclose(initial_local_snapshots, unscaled_local_snapshots) + assert np.allclose(initial_local_snapshots, local_snapshots) run_test("max_abs") run_test("mean_abs") @@ -157,12 +159,12 @@ def run_test(scaling_type): my_initial_snapshots = copy.deepcopy(my_snapshots) scaler = VariableAndVectorScaler(my_scaling_vector, scaling_type) - my_scaled_snapshots = scaler.pre_scale(my_snapshots) + scaler.pre_scale(my_snapshots) for i in range(0, n_var): - assert np.allclose(my_scaled_snapshots[i], 1.0 / scales[i] * (1.0 / my_scaling_vector[None, :, None] * my_initial_snapshots)[i]) + assert np.allclose(my_snapshots[i], 1.0 / scales[i] * (1.0 / my_scaling_vector[None, :, None] * my_initial_snapshots)[i]) - my_unscaled_snapshots = scaler.post_scale(my_scaled_snapshots) - assert np.allclose(my_initial_snapshots, my_unscaled_snapshots) + scaler.post_scale(my_snapshots) + assert np.allclose(my_initial_snapshots, my_snapshots) run_test("max_abs") run_test("mean_abs") @@ -184,12 +186,12 @@ def run_test(scaling_type): initial_local_snapshots = copy.deepcopy(local_snapshots) scaler = VariableAndVectorScaler(my_scaling_vector, scaling_type) - scaled_local_snapshots = scaler.pre_scale(local_snapshots) + scaler.pre_scale(local_snapshots) for i in range(0, n_var): - assert np.allclose(scaled_local_snapshots[i], 1.0 / scales[i] * (1.0 / my_scaling_vector[None, :, None] * initial_local_snapshots)[i]) + assert np.allclose(local_snapshots[i], 1.0 / scales[i] * (1.0 / my_scaling_vector[None, :, None] * initial_local_snapshots)[i]) - unscaled_local_snapshots = scaler.post_scale(scaled_local_snapshots) - assert np.allclose(initial_local_snapshots, unscaled_local_snapshots) + scaler.post_scale(local_snapshots) + assert np.allclose(initial_local_snapshots, local_snapshots) run_test("max_abs") run_test("mean_abs")