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 test_ldc_lin(): nx = 4 ny = nx nz = nx dim = 3 dof = 4 parameters = {'Reynolds Number': 100} n = nx * ny * nz * dof discretization = Discretization(parameters, nx, ny, nz, dim, dof) atom = discretization.linear_part() A = assemble_jacobian(atom, nx, ny, nz, dof) B = read_matrix('ldc_lin_%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 B.begA[i + 1] - B.begA[i] == A.begA[i + 1] - A.begA[i] for j in range(B.begA[i], B.begA[i + 1]): assert B.jcoA[j] == A.jcoA[j] assert B.coA[j] == A.coA[j]
def test_bilin_uniform(): parameters, nx, ny, nz, dim, dof, x, y, z = create_test_problem() discretization = Discretization(parameters, nx, ny, nz, dim, dof) state = create_divfree_state(discretization) atomJ, atomF = discretization.nonlinear_part(state) A = discretization.assemble_jacobian(atomF) for i in range(A.n): for j in range(A.begA[i], A.begA[i + 1]): assert i != A.jcoA[j]
def test_u_z(): parameters, nx, ny, nz, dim, dof, x, y, z = create_test_problem() discretization = Discretization(parameters, nx, ny, nz, dim, dof, x, y, z) atom = discretization.w_z() for i in range(nx): dx = x[i] - x[i - 1] for j in range(ny): dy = y[j] - y[j - 1] for k in range(nz): print(i, j, k) assert atom[i, j, k, 3, 2, 1, 1, 0] == pytest.approx(-dy * dx) assert atom[i, j, k, 3, 2, 1, 1, 1] == pytest.approx(dy * dx)
def test_u_y(): parameters, nx, ny, nz, dim, dof, x, y, z = create_test_problem() discretization = Discretization(parameters, nx, ny, nz, dim, dof, x, y, z) atom = discretization.v_y() for i in range(nx): dx = x[i] - x[i - 1] for j in range(ny): for k in range(nz): dz = z[k] - z[k - 1] print(i, j, k) assert atom[i, j, k, 3, 1, 1, 0, 1] == pytest.approx(-dx * dz) assert atom[i, j, k, 3, 1, 1, 1, 1] == pytest.approx(dx * dz)
def test_p_x(): parameters, nx, ny, nz, dim, dof, x, y, z = create_test_problem() discretization = Discretization(parameters, nx, ny, nz, dim, dof, x, y, z) atom = discretization.p_x() for i in range(nx): for j in range(ny): dy = y[j] - y[j - 1] for k in range(nz): dz = z[k] - z[k - 1] print(i, j, k) assert atom[i, j, k, 0, 3, 1, 1, 1] == pytest.approx(-dy * dz) assert atom[i, j, k, 0, 3, 2, 1, 1] == pytest.approx(dy * dz)
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
def test_bilin_stretched(): parameters, nx, ny, nz, dim, dof, x, y, z = create_test_problem() x = utils.create_stretched_coordinate_vector(0, 1, nx, 1.5) y = utils.create_stretched_coordinate_vector(0, 1, ny, 1.5) z = utils.create_stretched_coordinate_vector(0, 1, nz, 1.5) discretization = Discretization(parameters, nx, ny, nz, dim, dof, x, y, z) state = create_divfree_state(discretization) atomJ, atomF = discretization.nonlinear_part(state) A = discretization.assemble_jacobian(atomF) for i in range(A.n): for j in range(A.begA[i], A.begA[i + 1]): assert i != A.jcoA[j]
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])
def test_T_zz(): parameters, nx, ny, nz, dim, dof, x, y, z = create_test_problem() discretization = Discretization(parameters, nx, ny, nz, dim, dof, x, y, z) atom = discretization.T_zz() for i in range(nx): dx = x[i] - x[i - 1] for j in range(ny): dy = y[j] - y[j - 1] for k in range(nz): dz = (z[k] - z[k - 2]) / 2 dzp1 = (z[k + 1] - z[k - 1]) / 2 print(i, j, k) assert atom[i, j, k, 4, 4, 1, 1, 0] == pytest.approx(1 / dz * dy * dx) assert atom[i, j, k, 4, 4, 1, 1, 2] == pytest.approx(1 / dzp1 * dy * dx)
def test_T_xx(): parameters, nx, ny, nz, dim, dof, x, y, z = create_test_problem() discretization = Discretization(parameters, nx, ny, nz, dim, dof, x, y, z) atom = discretization.T_xx() for i in range(nx): dx = (x[i] - x[i - 2]) / 2 dxp1 = (x[i + 1] - x[i - 1]) / 2 for j in range(ny): dy = y[j] - y[j - 1] for k in range(nz): dz = z[k] - z[k - 1] print(i, j, k) assert atom[i, j, k, 4, 4, 0, 1, 1] == pytest.approx(1 / dx * dy * dz) assert atom[i, j, k, 4, 4, 2, 1, 1] == pytest.approx(1 / dxp1 * dy * dz)
def test_w_yy(): parameters, nx, ny, nz, dim, dof, x, y, z = create_test_problem() discretization = Discretization(parameters, nx, ny, nz, dim, dof, x, y, z) atom = discretization.w_yy() for i in range(nx): dx = x[i] - x[i - 1] for j in range(ny): dy = (y[j] - y[j - 2]) / 2 dyp1 = (y[j + 1] - y[j - 1]) / 2 for k in range(nz): dz = (z[k + 1] - z[k - 1]) / 2 print(i, j, k) assert atom[i, j, k, 2, 2, 1, 0, 1] == pytest.approx(1 / dy * dz * dx) assert atom[i, j, k, 2, 2, 1, 2, 1] == pytest.approx(1 / dyp1 * dz * dx)
def test_v_yy(): parameters, nx, ny, nz, dim, dof, x, y, z = create_test_problem() discretization = Discretization(parameters, nx, ny, nz, dim, dof, x, y, z) atom = discretization.v_yy() for i in range(nx): dx = x[i] - x[i - 1] for j in range(ny): dy = y[j] - y[j - 1] dyp1 = y[j + 1] - y[j] for k in range(nz): dz = z[k] - z[k - 1] print(i, j, k) assert atom[i, j, k, 1, 1, 1, 0, 1] == pytest.approx(1 / dy * dx * dz) assert atom[i, j, k, 1, 1, 1, 2, 1] == pytest.approx(1 / dyp1 * dx * dz)
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])
def test_bous_bil(): nx = 4 ny = nx nz = nx dim = 3 dof = 5 parameters = { 'Reynolds Number': 1, 'Rayleigh Number': 100, 'Prandtl 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) atom, atomF = discretization.nonlinear_part(state) A = discretization.assemble_jacobian(atom) B = read_bous_matrix('bous_bil_%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) if i + 1 >= len(B.begA): break 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 B.begA[i + 1] - B.begA[i] == A.begA[i + 1] - A.begA[i] for j in range(B.begA[i], B.begA[i + 1]): assert B.jcoA[j] == A.jcoA[j] assert B.coA[j] == A.coA[j]
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])
def test_assemble_jacobian(): nx = 4 ny = nx nz = nx dim = 3 dof = 4 parameters = {'Reynolds Number': 100} n = nx * ny * nz * dof discretization = Discretization(parameters, nx, ny, nz, dim, dof) atom = discretization.linear_part() discretization.boundaries(atom) A = discretization.assemble_jacobian(atom) B = assemble_jacobian(atom, nx, ny, nz, dof) 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 B.begA[i + 1] - B.begA[i] == A.begA[i + 1] - A.begA[i] for j in range(B.begA[i], B.begA[i + 1]): assert B.jcoA[j] == A.jcoA[j] assert B.coA[j] == A.coA[j]
def test_ldc_bil(): nx = 4 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) atom, atomF = discretization.nonlinear_part(state) A = discretization.assemble_jacobian(atom) B = read_matrix('ldc_bil_%sx%sx%s.txt' % (nx, ny, nz)) for i in range(n): print(i) if i + 1 >= len(B.begA): break 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 B.begA[i + 1] - B.begA[i] == A.begA[i + 1] - A.begA[i] for j in range(B.begA[i], B.begA[i + 1]): assert B.jcoA[j] == A.jcoA[j] assert B.coA[j] == A.coA[j]
def test_bous_bnd(): 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 discretization = Discretization(parameters, nx, ny, nz, dim, dof) atom = discretization.linear_part() discretization.boundaries(atom) A = discretization.assemble_jacobian(atom) B = read_bous_matrix('bous_bnd_%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 B.begA[i + 1] - B.begA[i] == A.begA[i + 1] - A.begA[i] for j in range(B.begA[i], B.begA[i + 1]): assert B.jcoA[j] == A.jcoA[j] assert B.coA[j] == pytest.approx(A.coA[j])
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))
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))