Пример #1
0
def test_bous_2D():
    nx = 4
    ny = nx
    nz = 1
    dim = 3
    dof1 = 5
    parameters = {
        'Reynolds Number': 1,
        'Rayleigh Number': 100,
        'Prandtl Number': 100,
        'Problem Type': 'Rayleigh-Benard'
    }
    n = nx * ny * nz * dof1

    state1 = numpy.zeros(n)
    for i in range(n):
        state1[i] = i + 1

    discretization = Discretization(parameters, nx, ny, nz, dim, dof1)
    A1 = discretization.jacobian(state1)
    rhs1 = discretization.rhs(state1)

    dim = 2
    dof2 = 4
    n = nx * ny * nz * dof2

    state2 = numpy.zeros(n)
    for i in range(n):
        state2[i] = state1[i + (i + 2) // dof2]

    discretization = Discretization(parameters, nx, ny, nz, dim, dof2)
    A2 = discretization.jacobian(state2)
    rhs2 = discretization.rhs(state2)

    for i in range(n):
        print(i)

        i1 = i + (i + 2) // dof2

        print('Expected:')
        print(A1.jcoA[A1.begA[i1]:A1.begA[i1 + 1]])
        print(A1.coA[A1.begA[i1]:A1.begA[i1 + 1]])

        print('Got:')
        print(A2.jcoA[A2.begA[i]:A2.begA[i + 1]])
        print(A2.coA[A2.begA[i]:A2.begA[i + 1]])

        assert A1.begA[i1 + 1] - A1.begA[i1] == A2.begA[i + 1] - A2.begA[i]
        for j in range(A2.begA[i + 1] - A2.begA[i]):
            j1 = A1.begA[i1] + j
            j2 = A2.begA[i] + j
            assert A1.jcoA[j1] == A2.jcoA[j2] + (A2.jcoA[j2] + 2) // dof2
            assert A1.coA[j1] == pytest.approx(A2.coA[j2])

        assert rhs2[i] == pytest.approx(rhs1[i1])
Пример #2
0
def test_jac_consistency():
    parameters, nx, ny, nz, dim, dof, x, y, z = create_test_problem()

    n = dof * nx * ny * nz
    state = numpy.random.random(n)
    pert = numpy.random.random(n)

    discretization = Discretization(parameters, nx, ny, nz, dim, dof, x, y, z)
    A = discretization.jacobian(state)
    rhs = discretization.rhs(state)

    for i in range(3, 12):
        eps = 10**-i
        eps2 = max(eps, 10**(-14 + i))
        rhs2 = discretization.rhs(state + eps * pert)
        assert numpy.linalg.norm((rhs2 - rhs) / eps - A @ pert) < eps2
Пример #3
0
def test_bous():
    nx = 4
    ny = nx
    nz = nx
    dim = 3
    dof = 5
    parameters = {
        'Reynolds Number': 1,
        'Rayleigh Number': 100,
        'Prandtl Number': 100,
        'Problem Type': 'Rayleigh-Benard'
    }
    n = nx * ny * nz * dof

    state = numpy.zeros(n)
    for i in range(n):
        state[i] = i + 1

    discretization = Discretization(parameters, nx, ny, nz, dim, dof)
    A = discretization.jacobian(state)
    rhs = discretization.rhs(state)

    B = read_bous_matrix('bous_%sx%sx%s.txt' % (nx, ny, nz))
    rhs_B = read_bous_vector('bous_rhs_%sx%sx%s.txt' % (nx, ny, nz))

    pytest.skip('The Prandtl number is currently applied in a different place')

    for i in range(n):
        print(i)

        print('Expected:')
        print(B.jcoA[B.begA[i]:B.begA[i + 1]])
        print(B.coA[B.begA[i]:B.begA[i + 1]])

        print('Got:')
        print(A.jcoA[A.begA[i]:A.begA[i + 1]])
        print(A.coA[A.begA[i]:A.begA[i + 1]])

        assert A.begA[i + 1] - A.begA[i] == B.begA[i + 1] - B.begA[i]
        for j in range(A.begA[i], A.begA[i + 1]):
            assert A.jcoA[j] == B.jcoA[j]
            assert A.coA[j] == pytest.approx(B.coA[j])

        assert rhs_B[i] == pytest.approx(rhs[i])
Пример #4
0
def test_ldc8():
    nx = 8
    ny = nx
    nz = nx
    dim = 3
    dof = 4
    parameters = {'Reynolds Number': 100}
    n = nx * ny * nz * dof

    state = numpy.zeros(n)
    for i in range(n):
        state[i] = i + 1

    discretization = Discretization(parameters, nx, ny, nz, dim, dof)
    A = discretization.jacobian(state)
    rhs = discretization.rhs(state)

    if not os.path.isfile('ldc_%sx%sx%s.txt' % (nx, ny, nz)):
        return

    B = read_matrix('ldc_%sx%sx%s.txt' % (nx, ny, nz))
    rhs_B = read_vector('ldc_rhs_%sx%sx%s.txt' % (nx, ny, nz))

    for i in range(n):
        print(i)

        print('Expected:')
        print(B.jcoA[B.begA[i]:B.begA[i + 1]])
        print(B.coA[B.begA[i]:B.begA[i + 1]])

        print('Got:')
        print(A.jcoA[A.begA[i]:A.begA[i + 1]])
        print(A.coA[A.begA[i]:A.begA[i + 1]])

        assert A.begA[i + 1] - A.begA[i] == B.begA[i + 1] - B.begA[i]
        for j in range(A.begA[i], A.begA[i + 1]):
            assert A.jcoA[j] == B.jcoA[j]
            assert A.coA[j] == pytest.approx(B.coA[j])

        assert rhs_B[i] == pytest.approx(rhs[i])
Пример #5
0
class Interface:
    '''This class defines an interface to the NumPy backend for the
    discretization. We use this so we can write higher level methods
    such as pseudo-arclength continuation without knowing anything
    about the underlying methods such as the solvers that are present
    in the backend we are interfacing with.'''
    def __init__(self,
                 parameters,
                 nx,
                 ny,
                 nz,
                 dim,
                 dof,
                 x=None,
                 y=None,
                 z=None):
        self.nx = nx
        self.ny = ny
        self.nz = nz
        self.dim = dim
        self.dof = dof
        self.discretization = Discretization(parameters, nx, ny, nz, dim, dof,
                                             x, y, z)

        self.parameters = parameters

        # Solver caching
        self._lu = None
        self._prec = None

        # Eigenvalue solver caching
        self._subspaces = None

    def set_parameter(self, name, value):
        '''Set a parameter in self.parameters while also letting the
        discretization know that we changed a parameter. '''

        self.discretization.set_parameter(name, value)

    def get_parameter(self, name):
        '''Get a parameter from self.parameters through the discretization.'''
        return self.discretization.get_parameter(name)

    def rhs(self, state):
        '''Right-hand side in M * du / dt = F(u).'''
        return self.discretization.rhs(state)

    def jacobian(self, state):
        '''Jacobian J of F in M * du / dt = F(u).'''
        return self.discretization.jacobian(state)

    def mass_matrix(self):
        '''Mass matrix M in M * du / dt = F(u).'''
        return self.discretization.mass_matrix()

    def solve(self, jac, x):
        '''Solve J y = x for y.'''
        rhs = x.copy()

        # Fix one pressure node
        if self.dof > self.dim:
            if len(rhs.shape) < 2:
                rhs[self.dim] = 0
            else:
                rhs[self.dim, :] = 0

        # First try to use an iterative solver with the previous
        # direct solver as preconditioner
        if self._prec and jac.dtype == rhs.dtype and jac.dtype == self._prec.dtype and \
           self.parameters.get('Use Iterative Solver', False):
            out, info = linalg.gmres(jac,
                                     rhs,
                                     restart=5,
                                     maxiter=1,
                                     tol=1e-8,
                                     atol=0,
                                     M=self._prec)
            if info == 0:
                return out

        # Use a direct solver instead
        if not jac.lu:
            coA = jac.coA
            jcoA = jac.jcoA
            begA = jac.begA

            # Fix one pressure node
            if self.dof > self.dim:
                coA = numpy.zeros(jac.begA[-1], dtype=jac.coA.dtype)
                jcoA = numpy.zeros(jac.begA[-1], dtype=int)
                begA = numpy.zeros(len(jac.begA), dtype=int)

                idx = 0
                for i in range(len(jac.begA) - 1):
                    if i == self.dim:
                        coA[idx] = -1.0
                        jcoA[idx] = i
                        idx += 1
                        begA[i + 1] = idx
                        continue
                    for j in range(jac.begA[i], jac.begA[i + 1]):
                        if jac.jcoA[j] != self.dim:
                            coA[idx] = jac.coA[j]
                            jcoA[idx] = jac.jcoA[j]
                            idx += 1
                    begA[i + 1] = idx

            # Convert the matrix to CSC format since splu expects that
            A = sparse.csr_matrix((coA, jcoA, begA)).tocsc()

            jac.lu = linalg.splu(A)

            # Cache the factorization for use in the iterative solver
            self._lu = jac.lu
            self._prec = linalg.LinearOperator((jac.n, jac.n),
                                               matvec=self._lu.solve,
                                               dtype=jac.dtype)

        return jac.solve(rhs)

    def eigs(self, state, return_eigenvectors=False):
        '''Compute the generalized eigenvalues of beta * J(x) * v = alpha * M * v.'''

        from jadapy import jdqz, Target
        from fvm.JadaInterface import JadaOp, JadaInterface

        jac_op = JadaOp(self.jacobian(state))
        mass_op = JadaOp(self.mass_matrix())
        jada_interface = JadaInterface(self, jac_op, mass_op, jac_op.shape[0],
                                       numpy.complex128)

        parameters = self.parameters.get('Eigenvalue Solver', {})
        target = parameters.get('Target', Target.LargestRealPart)
        subspace_dimensions = [
            parameters.get('Minimum Subspace Dimension', 30),
            parameters.get('Maximum Subspace Dimension', 60)
        ]
        tol = parameters.get('Tolerance', 1e-7)
        num = parameters.get('Number of Eigenvalues', 5)

        result = jdqz.jdqz(jac_op,
                           mass_op,
                           num,
                           tol=tol,
                           subspace_dimensions=subspace_dimensions,
                           target=target,
                           interface=jada_interface,
                           arithmetic='complex',
                           prec=jada_interface.shifted_prec,
                           return_eigenvectors=return_eigenvectors,
                           return_subspaces=True,
                           initial_subspaces=self._subspaces)

        if return_eigenvectors:
            alpha, beta, v, q, z = result
            self._subspaces = [q, z]
            idx = range(len(alpha))
            idx = sorted(idx, key=lambda i: -(alpha[i] / beta[i]).real)

            w = v.copy()
            eigs = alpha.copy()
            for i in range(len(idx)):
                w[:, i] = v[:, idx[i]]
                eigs[i] = alpha[idx[i]] / beta[idx[i]]
            return eigs, w
        else:
            alpha, beta, q, z = result
            self._subspaces = [q, z]
            return numpy.array(sorted(alpha / beta, key=lambda x: -x.real))
Пример #6
0
class Interface:
    def __init__(self, parameters, nx, ny, nz, dim, dof):
        self.nx = nx
        self.ny = ny
        self.nz = nz
        self.dim = dim
        self.dof = dof
        self.discretization = Discretization(parameters, nx, ny, nz, dim, dof)

        self.parameters = parameters

        # Solver caching
        self._lu = None
        self._prec = None

        # Eigenvalue solver caching
        self._subspaces = None

    def set_parameter(self, name, value):
        self.discretization.set_parameter(name, value)

    def get_parameter(self, name):
        return self.discretization.get_parameter(name)

    def rhs(self, state):
        return self.discretization.rhs(state)

    def jacobian(self, state):
        return self.discretization.jacobian(state)

    def mass_matrix(self):
        return self.discretization.mass_matrix()

    # def solve(self, jac, rhs):
    #     coA = numpy.zeros(jac.begA[-1], dtype=jac.coA.dtype)
    #     jcoA = numpy.zeros(jac.begA[-1], dtype=int)
    #     begA = numpy.zeros(len(jac.begA), dtype=int)
    #
    #     idx = 0
    #     for i in range(len(jac.begA)-1):
    #         if i == self.dim:
    #             coA[idx] = -1.0
    #             jcoA[idx] = i
    #             idx += 1
    #             begA[i+1] = idx
    #             continue
    #         for j in range(jac.begA[i], jac.begA[i+1]):
    #             if jac.jcoA[j] != self.dim:
    #                 coA[idx] = jac.coA[j]
    #                 jcoA[idx] = jac.jcoA[j]
    #                 idx += 1
    #         begA[i+1] = idx
    #
    #     A = sparse.csr_matrix((coA, jcoA, begA))
    #     if len(rhs.shape) < 2:
    #         rhs[self.dim] = 0
    #         x = linalg.spsolve(A, rhs)
    #     else:
    #         x = rhs.copy()
    #         #rhs[self.dim, :] = 0
    #         for i in range(x.shape[1]):
    #             x[:, i] = linalg.spsolve(A, rhs[:, i])
    #     return x

    # TODO wei
    def solve(self, jac, x):
        rhs = x.copy()

        # Fix one pressure node
        if self.dof > self.dim:
            if len(rhs.shape) < 2:
                rhs[self.dim] = 0
            else:
                rhs[self.dim, :] = 0

        # Use a direct solver instead
        if True:
            coA = jac.coA
            jcoA = jac.jcoA
            begA = jac.begA

            # Fix one pressure node
            if self.dof > self.dim:
                coA = numpy.zeros(jac.begA[-1], dtype=jac.coA.dtype)
                jcoA = numpy.zeros(jac.begA[-1], dtype=int)
                begA = numpy.zeros(len(jac.begA), dtype=int)

                idx = 0
                for i in range(len(jac.begA) - 1):
                    if i == self.dim:
                        coA[idx] = -1.0
                        jcoA[idx] = i
                        idx += 1
                        begA[i + 1] = idx
                        continue
                    for j in range(jac.begA[i], jac.begA[i + 1]):
                        if jac.jcoA[j] != self.dim:
                            coA[idx] = jac.coA[j]
                            jcoA[idx] = jac.jcoA[j]
                            idx += 1
                    begA[i + 1] = idx

            # Convert the matrix to CSC format since splu expects that
            A = sparse.csr_matrix((coA, jcoA, begA)).tocsc()

            # jac.lu = linalg.splu(A)

            if self.parameters.get('Use Iterative Solver', False):
                if self.parameters.get('Use Preconditioner', False):
                    if self.parameters.get('Use ILU Preconditioner', False):
                        self._prec = linalg.LinearOperator(
                            (jac.n, jac.n),
                            matvec=linalg.spilu(A).solve,
                            dtype=jac.dtype)

                    if self._prec and jac.dtype == rhs.dtype and jac.dtype == self._prec.dtype:
                        out, info = linalg.gmres(A,
                                                 rhs,
                                                 M=self._prec,
                                                 callback=gmres_counter())
                        if info == 0:
                            return out
                else:
                    out, info = linalg.gmres(A, rhs, callback=gmres_counter())
                    if info == 0:
                        return out
            A_lu = linalg.splu(A)

        return A_lu.solve(rhs)

    def solve_bordered(self, jac, fval, dfval, r_x, r_mu, r):
        rhs = fval.copy()

        # Fix one pressure node
        if self.dof > self.dim:
            if len(rhs.shape) < 2:
                rhs[self.dim] = 0
            else:
                rhs[self.dim, :] = 0

        # Use a direct solver instead
        if True:
            coA = jac.coA
            jcoA = jac.jcoA
            begA = jac.begA

            # Fix one pressure node
            if self.dof > self.dim:
                coA = numpy.zeros(jac.begA[-1], dtype=jac.coA.dtype)
                jcoA = numpy.zeros(jac.begA[-1], dtype=int)
                begA = numpy.zeros(len(jac.begA), dtype=int)

                idx = 0
                for i in range(len(jac.begA) - 1):
                    if i == self.dim:
                        coA[idx] = -1.0
                        jcoA[idx] = i
                        idx += 1
                        begA[i + 1] = idx
                        continue
                    for j in range(jac.begA[i], jac.begA[i + 1]):
                        if jac.jcoA[j] != self.dim:
                            coA[idx] = jac.coA[j]
                            jcoA[idx] = jac.jcoA[j]
                            idx += 1
                    begA[i + 1] = idx

            # Convert the matrix to CSC format since splu expects that
            A = sparse.csr_matrix((coA, jcoA, begA)).tocsc().toarray()

            a = numpy.concatenate((A, dfval[:, numpy.newaxis]), axis=1)
            b = numpy.append(r_x, r_mu)
            A = numpy.concatenate((a, b[:, numpy.newaxis].T), axis=0)

            b = numpy.append(-fval, r)

            A_sparse = sparse.csc_matrix(A)
            A_lu = linalg.splu(A_sparse)
            # jac.lu = linalg.splu(A)

            if self.parameters.get('Use Iterative Solver', False):
                if self.parameters.get('Use Preconditioner', False):
                    if self.parameters.get('Use LU Preconditioner', False):
                        self._prec = linalg.LinearOperator(
                            (jac.n + 1, jac.n + 1),
                            matvec=linalg.splu(A).solve,
                            dtype=jac.dtype)
                    elif self.parameters.get('Use ILU Preconditioner', False):
                        self._prec = linalg.LinearOperator(
                            (jac.n + 1, jac.n + 1),
                            matvec=linalg.spilu(A).solve,
                            dtype=jac.dtype)

                    if self._prec and jac.dtype == rhs.dtype and jac.dtype == self._prec.dtype:
                        out, info = linalg.gmres(A_sparse,
                                                 b,
                                                 M=self._prec,
                                                 callback=gmres_counter())
                        if info == 0:
                            return out
                else:
                    out, info = linalg.gmres(A_sparse,
                                             b,
                                             callback=gmres_counter())
                    if info == 0:
                        return out

        return A_lu.solve(b)

    #
    # def solve(self, jac, x):
    #     rhs = x.copy()
    #
    #     # Fix one pressure node
    #     if self.dof > self.dim:
    #         if len(rhs.shape) < 2:
    #             rhs[self.dim] = 0
    #         else:
    #             rhs[self.dim, :] = 0
    #
    #     # First try to use an iterative solver with the previous
    #     # direct solver as preconditioner
    #     if self._prec and jac.dtype == rhs.dtype and jac.dtype == self._prec.dtype and \
    #             self.parameters.get('Use Iterative Solver', False):
    #         out, info = linalg.gmres(jac, rhs, restart=5, maxiter=1, tol=1e-8, atol=0, M=self._prec)
    #         if info == 0:
    #             return out
    #
    #     # no preconditioner
    #     # if self._prec and jac.dtype == rhs.dtype and jac.dtype == self._prec.dtype and \
    #     #         self.parameters.get('Use Iterative Solver', False):
    #     #     out, info = linalg.gmres(jac, rhs, restart=5, maxiter=1, tol=1e-8, atol=0)
    #     #     if info == 0:
    #     #         return out
    #
    #     # Use a direct solver instead
    #     if not jac.lu:
    #         coA = jac.coA
    #         jcoA = jac.jcoA
    #         begA = jac.begA
    #
    #         # Fix one pressure node
    #         if self.dof > self.dim:
    #             coA = numpy.zeros(jac.begA[-1], dtype=jac.coA.dtype)
    #             jcoA = numpy.zeros(jac.begA[-1], dtype=int)
    #             begA = numpy.zeros(len(jac.begA), dtype=int)
    #
    #             idx = 0
    #             for i in range(len(jac.begA) - 1):
    #                 if i == self.dim:
    #                     coA[idx] = -1.0
    #                     jcoA[idx] = i
    #                     idx += 1
    #                     begA[i + 1] = idx
    #                     continue
    #                 for j in range(jac.begA[i], jac.begA[i + 1]):
    #                     if jac.jcoA[j] != self.dim:
    #                         coA[idx] = jac.coA[j]
    #                         jcoA[idx] = jac.jcoA[j]
    #                         idx += 1
    #                 begA[i + 1] = idx
    #
    #         # Convert the matrix to CSC format since splu expects that
    #         A = sparse.csr_matrix((coA, jcoA, begA)).tocsc()
    #
    #         jac.lu = linalg.splu(A)
    #
    #         # Cache the factorization for use in the iterative solver
    #         self._lu = jac.lu
    #         # LU decomposition as the preconditioner
    #         self._prec = linalg.LinearOperator((jac.n, jac.n), matvec=self._lu.solve, dtype=jac.dtype)
    #
    #         # ILU decomposition as the preconditioner
    #         # self._prec = linalg.LinearOperator((jac.n, jac.n), matvec=linalg.spilu(A).solve, dtype=jac.dtype)
    #
    #     return jac.solve(rhs)

    def eigs(self, state, return_eigenvectors=False):
        from jadapy import jdqz, Target
        from fvm.JadaInterface import JadaOp, JadaInterface

        jac_op = JadaOp(self.jacobian(state))
        mass_op = JadaOp(self.mass_matrix())
        jada_interface = JadaInterface(self, jac_op, mass_op, jac_op.shape[0],
                                       numpy.complex128)

        parameters = self.parameters.get('Eigenvalue Solver', {})
        target = parameters.get('Target', Target.LargestRealPart)
        subspace_dimensions = [
            parameters.get('Minimum Subspace Dimension', 30),
            parameters.get('Maximum Subspace Dimension', 60)
        ]
        tol = parameters.get('Tolerance', 1e-7)
        num = parameters.get('Number of Eigenvalues', 5)

        result = jdqz.jdqz(jac_op,
                           mass_op,
                           num,
                           tol=tol,
                           subspace_dimensions=subspace_dimensions,
                           target=target,
                           interface=jada_interface,
                           arithmetic='complex',
                           prec=jada_interface.shifted_prec,
                           return_eigenvectors=return_eigenvectors,
                           return_subspaces=True,
                           initial_subspaces=self._subspaces)

        if return_eigenvectors:
            alpha, beta, v, q, z = result
            self._subspaces = [q, z]
            idx = range(len(alpha))
            idx = sorted(idx, key=lambda i: -(alpha[i] / beta[i]).real)

            w = v.copy()
            eigs = alpha.copy()
            for i in range(len(idx)):
                w[:, i] = v[:, idx[i]]
                eigs[i] = alpha[idx[i]] / beta[idx[i]]
            return eigs, w
        else:
            alpha, beta, q, z = result
            self._subspaces = [q, z]
            return numpy.array(sorted(alpha / beta, key=lambda x: -x.real))