Exemple #1
0
 def test_compute_modes(self):
     ws = np.identity(self.num_states)
     tol = 1e-6
     weights_full = np.mat(np.random.random((self.num_states, self.num_states)))
     weights_full = np.triu(weights_full) + np.triu(weights_full, 1).H
     weights_full = weights_full*weights_full
     weights_diag = np.random.random(self.num_states)
     weights_list = [None, weights_diag, weights_full]
     vec_array = np.random.random((self.num_states, self.num_vecs))
     for weights in weights_list:
         IP = VectorSpaceMatrices(weights=weights).compute_inner_product_mat
         correlation_mat_true = IP(vec_array, vec_array)
         eigen_vals_true, eigen_vecs_true = util.eigh(correlation_mat_true)
         build_coeff_mat_true = eigen_vecs_true * np.mat(np.diag(
             eigen_vals_true**-0.5))
         modes_true = vec_array.dot(build_coeff_mat_true)
         
         modes, eigen_vals, eigen_vecs, correlation_mat = \
             compute_POD_matrices_snaps_method(vec_array, self.mode_indices, 
             inner_product_weights=weights, return_all=True)
         
         np.testing.assert_allclose(eigen_vals, eigen_vals_true, rtol=tol)
         np.testing.assert_allclose(eigen_vecs, eigen_vecs_true)
         np.testing.assert_allclose(correlation_mat, correlation_mat_true)
         np.testing.assert_allclose(modes, modes_true[:,self.mode_indices])
                     
         modes, eigen_vals, eigen_vecs = \
             compute_POD_matrices_direct_method(vec_array, self.mode_indices, 
             inner_product_weights=weights, return_all=True)
         
         np.testing.assert_allclose(eigen_vals, eigen_vals_true)
         np.testing.assert_allclose(np.abs(eigen_vecs), np.abs(eigen_vecs_true))
         np.testing.assert_allclose(np.abs(modes), np.abs(modes_true[:,self.mode_indices]))
Exemple #2
0
    def test_compute_modes(self):
        ws = np.identity(self.num_states)
        tol = 1e-6

        # Generate different inner product weights.  Each weight matrix should
        # be positive definite semidefinite.
        weights_full = np.mat(
            np.random.random((self.num_states, self.num_states)))
        weights_full = 0.5 * (weights_full + weights_full.T)
        weights_full = weights_full + self.num_states * np.eye(self.num_states)
        weights_diag = np.random.random(self.num_states)
        weights_list = [None, weights_diag, weights_full]
        vec_array = np.random.random((self.num_states, self.num_vecs))
        for weights in weights_list:
            IP = VectorSpaceMatrices(weights=weights).compute_inner_product_mat
            correlation_mat_true = IP(vec_array, vec_array)
            eigvals_true, eigvecs_true = util.eigh(correlation_mat_true)
            build_coeff_mat_true = eigvecs_true * np.mat(
                np.diag(eigvals_true**-0.5))
            modes_true = vec_array.dot(build_coeff_mat_true)

            modes, eigvals, eigvecs, correlation_mat = \
                compute_POD_matrices_snaps_method(vec_array, self.mode_indices,
                inner_product_weights=weights, return_all=True)

            np.testing.assert_allclose(eigvals, eigvals_true, rtol=tol)
            np.testing.assert_allclose(eigvecs, eigvecs_true)
            np.testing.assert_allclose(correlation_mat, correlation_mat_true)
            np.testing.assert_allclose(modes, modes_true[:, self.mode_indices])

            modes, eigvals, eigvecs = \
                compute_POD_matrices_direct_method(
                vec_array, self.mode_indices, inner_product_weights=weights,
                return_all=True)

            np.testing.assert_allclose(eigvals, eigvals_true)
            np.testing.assert_allclose(np.abs(eigvecs), np.abs(eigvecs_true))
            np.testing.assert_allclose(
                np.abs(modes), np.abs(modes_true[:, self.mode_indices]))
Exemple #3
0
    def test_compute_modes(self):
        ws = np.identity(self.num_states)
        tol = 1e-6
        weights_full = np.mat(
            np.random.random((self.num_states, self.num_states)))
        weights_full = np.triu(weights_full) + np.triu(weights_full, 1).H
        weights_full = weights_full * weights_full
        weights_diag = np.random.random(self.num_states)
        weights_list = [None, weights_diag, weights_full]
        vec_array = np.random.random((self.num_states, self.num_vecs))
        for weights in weights_list:
            IP = VectorSpaceMatrices(weights=weights).compute_inner_product_mat
            correlation_mat_true = IP(vec_array, vec_array)
            eigen_vals_true, eigen_vecs_true = util.eigh(correlation_mat_true)
            build_coeff_mat_true = eigen_vecs_true * np.mat(
                np.diag(eigen_vals_true**-0.5))
            modes_true = vec_array.dot(build_coeff_mat_true)

            modes, eigen_vals, eigen_vecs, correlation_mat = \
                compute_POD_matrices_snaps_method(vec_array, self.mode_indices,
                inner_product_weights=weights, return_all=True)

            np.testing.assert_allclose(eigen_vals, eigen_vals_true, rtol=tol)
            np.testing.assert_allclose(eigen_vecs, eigen_vecs_true)
            np.testing.assert_allclose(correlation_mat, correlation_mat_true)
            np.testing.assert_allclose(modes, modes_true[:, self.mode_indices])

            modes, eigen_vals, eigen_vecs = \
                compute_POD_matrices_direct_method(vec_array, self.mode_indices,
                inner_product_weights=weights, return_all=True)

            np.testing.assert_allclose(eigen_vals, eigen_vals_true)
            np.testing.assert_allclose(np.abs(eigen_vecs),
                                       np.abs(eigen_vecs_true))
            np.testing.assert_allclose(
                np.abs(modes), np.abs(modes_true[:, self.mode_indices]))
Exemple #4
0
    def test_eigh(self):
        # Set tolerance for test of eigval/eigvec properties.  Value necessary
        # for test to pass depends on array size, as well as atol and rtol
        # values
        test_atol = 1e-12

        # Generate random array
        num_rows = 100

        # Test arrays that are and are not positive definite
        for is_pos_def in [True, False]:

            # Test both real and complex data
            for is_complex in [True, False]:

                # Generate random array with values between 0 and 1
                array = np.random.random((num_rows, num_rows))
                if is_complex:
                    array = array + 1j * np.random.random((num_rows, num_rows))

                # Make array conjugate-symmetric.  Note that if the array is
                # large, for some reason an in-place operation causes the
                # operation to fail (not sure why...).  Values are still between
                # 0 and 1.
                array = 0.5 * (array + array.conj().T)

                # If necessary, make the array positive definite by first making
                # it symmetric (adding the transpose), and then making it
                # diagonally dominant (each element is less than 1, so add N * I
                # to make the diagonal dominant).  Here an in-place change seems
                # to be ok.
                if is_pos_def:
                    array = array + num_rows * np.eye(num_rows)

                    # Make sure array is positive definite, otherwise
                    # force test to quit.
                    if np.linalg.eig(array)[0].min() < 0.:
                        raise ValueError(
                            'Failed to generate positive definite array '
                            'for test.')

                # Compute full set of eigenvalues to help choose tolerance
                # levels that guarantee truncation (otherwise tests won't
                # actually check those features).
                eigvals_full = np.linalg.eig(array)[0]
                atol_list = [np.median(abs(eigvals_full)), None]
                rtol_list = [
                    np.median(abs(eigvals_full)) / abs(np.max(eigvals_full)),
                    None
                ]

                # Loop through different tolerance values
                for atol in atol_list:
                    for rtol in rtol_list:

                        # For each case, test that returned values are in fact
                        # eigenvalues and eigenvectors of the given array.
                        # Since each pair that is returned (not truncated due to
                        # tolerances) should have this property, we can test
                        # this even if tolerances are passed in.  Compare to the
                        # zero array because then we only have to check the
                        # absolute magnitue of each term, rather than consider
                        # relative errors with respect to nonzero terms.
                        eigvals, eigvecs = util.eigh(
                            array,
                            rtol=rtol,
                            atol=atol,
                            is_positive_definite=is_pos_def)
                        np.testing.assert_allclose(
                            array.dot(eigvecs) - eigvecs.dot(np.diag(eigvals)),
                            np.zeros(eigvecs.shape),
                            atol=test_atol)

                        # If either tolerance is nonzero, make sure that
                        # something is actually truncated, otherwise force test
                        # to quit.  To do this, make sure the eigvec array is
                        # not square.
                        if rtol and eigvals.size == eigvals_full.size:
                            raise ValueError(
                                'Failed to choose relative tolerance that '
                                'forces truncation.')
                        if atol and eigvals.size == eigvals_full.size:
                            raise ValueError(
                                'Failed to choose absolute tolerance that '
                                'forces truncation.')

                        # If the positive definite flag is passed in, make sure
                        # the returned eigenvalues are all positive
                        if is_pos_def:
                            self.assertTrue(eigvals.min() > 0)

                        # If a relative tolerance is passed in, make sure the
                        # relative tolerance is satisfied.
                        if rtol is not None:
                            self.assertTrue(
                                abs(eigvals).min() / abs(eigvals).max() > rtol)

                        # If an absolute tolerance is passed in, make sure the
                        # absolute tolerance is satisfied.
                        if atol is not None:
                            self.assertTrue(abs(eigvals).min() > atol)
Exemple #5
0
    def _helper_compute_DMD_from_data(self,
                                      vec_array,
                                      inner_product,
                                      adv_vec_array=None,
                                      max_num_eigvals=None):
        # Generate adv_vec_array for the case of a sequential dataset
        if adv_vec_array is None:
            adv_vec_array = vec_array[:, 1:]
            vec_array = vec_array[:, :-1]

        # Create lists of vecs, advanced vecs for inner product function
        vecs = [vec_array[:, i] for i in range(vec_array.shape[1])]
        adv_vecs = [adv_vec_array[:, i] for i in range(adv_vec_array.shape[1])]

        # Compute SVD of data vectors
        correlation_mat = inner_product(vecs, vecs)
        correlation_mat_eigvals, correlation_mat_eigvecs = util.eigh(
            correlation_mat)
        U = vec_array.dot(np.array(correlation_mat_eigvecs)).dot(
            np.diag(correlation_mat_eigvals**-0.5))
        U_list = [U[:, i] for i in range(U.shape[1])]

        # Truncate SVD if necessary
        if max_num_eigvals is not None and (max_num_eigvals <
                                            correlation_mat_eigvals.size):
            correlation_mat_eigvals = correlation_mat_eigvals[:max_num_eigvals]
            correlation_mat_eigvecs = correlation_mat_eigvecs[:, :
                                                              max_num_eigvals]
            U = U[:, :max_num_eigvals]
            U_list = U_list[:max_num_eigvals]

        # Compute eigendecomposition of low order linear operator
        A_tilde = inner_product(U_list, adv_vecs).dot(
            np.array(correlation_mat_eigvecs)).dot(
                np.diag(correlation_mat_eigvals**-0.5))
        eigvals, R_low_order_eigvecs, L_low_order_eigvecs =\
            util.eig_biorthog(A_tilde, scale_choice='left')
        R_low_order_eigvecs = np.mat(R_low_order_eigvecs)
        L_low_order_eigvecs = np.mat(L_low_order_eigvecs)

        # Compute build coefficients
        build_coeffs_proj = (correlation_mat_eigvecs.dot(
            np.diag(correlation_mat_eigvals**-0.5)).dot(R_low_order_eigvecs))
        build_coeffs_exact = (correlation_mat_eigvecs.dot(
            np.diag(
                correlation_mat_eigvals**-0.5)).dot(R_low_order_eigvecs).dot(
                    np.diag(eigvals**-1.)))

        # Compute modes
        modes_proj = vec_array.dot(build_coeffs_proj)
        modes_exact = adv_vec_array.dot(build_coeffs_exact)
        adj_modes = U.dot(L_low_order_eigvecs)
        adj_modes_list = [
            np.array(adj_modes[:, i]) for i in range(adj_modes.shape[1])
        ]

        # Compute spectrum
        spectral_coeffs = np.abs(
            np.array(inner_product(adj_modes_list, vecs[0:1])).squeeze())

        return (modes_exact, modes_proj, spectral_coeffs, eigvals,
                R_low_order_eigvecs, L_low_order_eigvecs,
                correlation_mat_eigvals, correlation_mat_eigvecs, adj_modes)
Exemple #6
0
    def test_eigh(self):
        # Set tolerance for test of eigval/eigvec properties.  Value necessary
        # for test to pass depends on array size, as well as atol and rtol
        # values
        test_atol = 1e-12

        # Generate random array
        num_rows = 100

        # Test arrays that are and are not positive definite
        for is_pos_def in [True, False]:

            # Test both real and complex data
            for is_complex in [True, False]:

                # Generate random array with values between 0 and 1
                array = np.random.random((num_rows, num_rows))
                if is_complex:
                    array = array + 1j * np.random.random((num_rows, num_rows))

                # Make array conjugate-symmetric.  Note that if the array is
                # large, for some reason an in-place operation causes the
                # operation to fail (not sure why...).  Values are still between
                # 0 and 1.
                array = 0.5 * (array + array.conj().T)

                # If necessary, make the array positive definite by first making
                # it symmetric (adding the transpose), and then making it
                # diagonally dominant (each element is less than 1, so add N * I
                # to make the diagonal dominant).  Here an in-place change seems
                # to be ok.
                if is_pos_def:
                    array = array + num_rows * np.eye(num_rows)

                    # Make sure array is positive definite, otherwise
                    # force test to quit.
                    if np.linalg.eig(array)[0].min() < 0.:
                        raise ValueError(
                            'Failed to generate positive definite array '
                            'for test.')

                # Compute full set of eigenvalues to help choose tolerance
                # levels that guarantee truncation (otherwise tests won't
                # actually check those features).
                eigvals_full = np.linalg.eig(array)[0]
                atol_list = [np.median(abs(eigvals_full)), None]
                rtol_list = [
                    np.median(abs(eigvals_full)) / abs(np.max(eigvals_full)),
                    None]

                # Loop through different tolerance values
                for atol in atol_list:
                    for rtol in rtol_list:

                        # For each case, test that returned values are in fact
                        # eigenvalues and eigenvectors of the given array.
                        # Since each pair that is returned (not truncated due to
                        # tolerances) should have this property, we can test
                        # this even if tolerances are passed in.  Compare to the
                        # zero array because then we only have to check the
                        # absolute magnitue of each term, rather than consider
                        # relative errors with respect to nonzero terms.
                        eigvals, eigvecs = util.eigh(
                            array, rtol=rtol, atol=atol,
                            is_positive_definite=is_pos_def)
                        np.testing.assert_allclose(
                            array.dot(eigvecs) -
                            eigvecs.dot(np.diag(eigvals)),
                            np.zeros(eigvecs.shape),
                            atol=test_atol)

                        # If either tolerance is nonzero, make sure that
                        # something is actually truncated, otherwise force test
                        # to quit.  To do this, make sure the eigvec array is
                        # not square.
                        if rtol and eigvals.size == eigvals_full.size:
                            raise ValueError(
                                'Failed to choose relative tolerance that '
                                'forces truncation.')
                        if atol and eigvals.size == eigvals_full.size:
                            raise ValueError(
                                'Failed to choose absolute tolerance that '
                                'forces truncation.')

                        # If the positive definite flag is passed in, make sure
                        # the returned eigenvalues are all positive
                        if is_pos_def:
                            self.assertTrue(eigvals.min() > 0)

                        # If a relative tolerance is passed in, make sure the
                        # relative tolerance is satisfied.
                        if rtol is not None:
                            self.assertTrue(
                                abs(eigvals).min() / abs(eigvals).max() > rtol)

                        # If an absolute tolerance is passed in, make sure the
                        # absolute tolerance is satisfied.
                        if atol is not None:
                            self.assertTrue(abs(eigvals).min() > atol)