def test_dense_solve_single_rhs(self): context = MUMPSContext(self.A, verbose=False) context.factorize() e = np.ones(self.n, dtype=np.complex64) rhs = self.A * e x = context.solve(rhs=rhs) assert np.allclose(x, e)
def test_dense_solve_single_rhs(self): context = MUMPSContext((self.n, self.arow, self.acol, self.aval, self.sym), verbose=False) context.factorize() e = np.ones(self.n, dtype=np.complex64) rhs = np.dot(self.A, e) x = context.solve(rhs=rhs) assert np.allclose(x, e)
def test_dense_solve_single_rhs(self): context = MUMPSContext( (self.n, self.arow, self.acol, self.aval, self.sym), verbose=False) context.factorize() e = np.ones(self.n, dtype=np.complex64) rhs = np.dot(self.A, e) x = context.solve(rhs=rhs) assert np.allclose(x, e)
def test_iterative_refinement_single_rhs(self): context = MUMPSContext((self.n, self.arow, self.acol, self.aval, self.sym), verbose=False) context.factorize() e = np.ones(self.n, dtype=np.float64) rhs = np.dot(self.A, e) x = context.solve(rhs=rhs) x = context.refine(rhs, 3) assert np.allclose(x, e)
def test_iterative_refinement_single_rhs(self): context = MUMPSContext(self.A, verbose=False) context.factorize() e = np.ones(self.n, dtype=np.complex64) rhs = self.A * e x = context.solve(rhs=rhs) x = context.refine(rhs, 3) assert np.allclose(x, e)
def test_iterative_refinement_single_rhs(self): context = MUMPSContext( (self.n, self.arow, self.acol, self.aval, self.sym), verbose=False) context.factorize() e = np.ones(self.n, dtype=np.float64) rhs = np.dot(self.A, e) x = context.solve(rhs=rhs) x = context.refine(rhs, 3) assert np.allclose(x, e)
def test_dense_solve_multiple_rhs(self): context = MUMPSContext((self.n, self.arow, self.acol, self.aval, self.sym), verbose=False) context.factorize() B = np.ones([self.n, 3], dtype=np.complex64) B[:, 1] = 2 * B[:, 1] B[:, 2] = 3 * B[:, 2] rhs = np.dot(self.A, B) x = context.solve(rhs=rhs) assert np.allclose(x, B, 1e-6)
def test_dense_solve_multiple_rhs(self): context = MUMPSContext( (self.n, self.arow, self.acol, self.aval, self.sym), verbose=False) context.factorize() B = np.ones([self.n, 3], dtype=np.complex64) B[:, 1] = 2 * B[:, 1] B[:, 2] = 3 * B[:, 2] rhs = np.dot(self.A, B) x = context.solve(rhs=rhs) assert np.allclose(x, B, 1e-6)
def test_dense_solve_multiple_rhs(self): context = MUMPSContext(self.A, verbose=False) context.factorize() B = np.ones([self.n, 3], dtype=np.complex64) B[:, 1] = 2 * B[:, 1] B[:, 2] = 3 * B[:, 2] rhs = np.ones([self.n, 3], dtype=np.complex64) rhs[:, 0] = self.A * B[:, 0] rhs[:, 1] = self.A * B[:, 1] rhs[:, 2] = self.A * B[:, 2] x = context.solve(rhs=rhs) assert np.allclose(x, B, 1e-6)
def test_sparse_solve_multiple_rhs(self): context = MUMPSContext((self.n, self.arow, self.acol, self.aval, self.sym), verbose=False) context.factorize() acol_csc = np.array([1, 5, 9, 13, 17], dtype = np.int32)-1 arow_csc = np.array([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4], dtype=np.int32) - 1 aval_csc = np.array([1, 5, 9, 13, 2, 0, 10, 14, 3, 7, 0, 15, 4, 8, 12, 0], dtype=np.complex64) x = context.solve(rhs_col_ptr=acol_csc, rhs_row_ind=arow_csc, rhs_val=aval_csc) assert np.allclose(x, np.eye(4, dtype=np.complex64), 1e-4, 1e-4)
def test_sparse_solve_multiple_rhs(self): context = MUMPSContext(self.A, verbose=False) context.factorize() acol_csc = np.array([1, 5, 9, 13, 17], dtype=np.int32) - 1 arow_csc = np.array([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4], dtype=np.int32) - 1 aval_csc = np.array( [1, 5, 9, 13, 2, 0, 10, 14, 3, 7, 0, 15, 4, 8, 12, 0], dtype=np.complex64) x = context.solve(rhs_col_ptr=acol_csc, rhs_row_ind=arow_csc, rhs_val=aval_csc) assert np.allclose(x, np.eye(4), 1e-6, 1e-6)
print A (n, m) = A.shape e = np.ones(n, 'd') #rhs = np.zeros(n, 'd') rhs = A*e context = MUMPSContext(A, verbose=True) print 'MUMPS version: ', context.version_number context.analyze() context.factorize() x = context.solve(rhs=rhs) x = context.refine(rhs, 10) print x sys.exit(0) print "= " * 80 B = np.ones([n, 3], "d") B[: ,1] = 2 * B[:,1] B[: ,2] = 3 * B[:,2] rhs = A * B x = context.solve(rhs=rhs)
def Solve(self, A, b, reuse_factorisation=False): """Solves the linear system of equations""" if not issparse(A): raise ValueError("Linear system is not of sparse type") if A.shape == (0,0) and b.shape[0] == 0: warn("Empty linear system!!! Nothing to solve!!!") return np.copy(b) self.reuse_factorisation = reuse_factorisation if self.solver_type != "direct" and self.reuse_factorisation is True: warn("Re-using factorisation for non-direct solvers is not possible. The pre-conditioner is going to be reused instead") # DECIDE IF THE SOLVER TYPE IS APPROPRIATE FOR THE PROBLEM if self.switcher_message is False and self.dont_switch_solver is False: # PREFER PARDISO OR MUMPS OVER AMG IF AVAILABLE if self.has_pardiso: self.solver_type = "direct" self.solver_subtype = "pardiso" elif self.has_mumps: self.solver_type = "direct" self.solver_subtype = "mumps" elif b.shape[0] > 100000 and self.has_amg_solver: self.solver_type = "amg" self.solver_subtype = "gmres" print('Large system of equations. Switching to algebraic multigrid solver') self.switcher_message = True # elif mesh.points.shape[0]*MainData.nvar > 50000 and MainData.C < 4: # self.solver_type = "direct" # self.solver_subtype = "MUMPS" # print 'Large system of equations. Switching to MUMPS solver' elif b.shape[0] > 70000 and self.geometric_discretisation=="hex" and self.has_amg_solver: self.solver_type = "amg" self.solver_subtype = "gmres" print('Large system of equations. Switching to algebraic multigrid solver') self.switcher_message = True else: self.solver_type = "direct" self.solver_subtype = "umfpack" if self.solver_type == 'direct': # CALL DIRECT SOLVER if self.solver_subtype=='umfpack' and self.has_umfpack: if A.dtype != np.float64: A = A.astype(np.float64) if self.solver_context_manager is None: if self.reuse_factorisation is False: sol = spsolve(A,b,permc_spec='MMD_AT_PLUS_A',use_umfpack=True) # from scikits import umfpack # sol = umfpack.spsolve(A, b) else: from scikits import umfpack lu = umfpack.splu(A) sol = lu.solve(b) self.solver_context_manager = lu else: sol = self.solver_context_manager.solve(b) elif self.solver_subtype=='mumps' and self.has_mumps: from mumps.mumps_context import MUMPSContext t_solve = time() A = A.tocoo() # False means non-symmetric - Do not change it to True. True means symmetric pos def # which is not the case for electromechanics if self.solver_context_manager is None: context = MUMPSContext((A.shape[0], A.row, A.col, A.data, False), verbose=False) context.analyze() context.factorize() sol = context.solve(rhs=b) if self.reuse_factorisation: self.solver_context_manager = context else: sol = self.solver_context_manager.solve(rhs=b) print("MUMPS solver time is {}".format(time() - t_solve)) return sol elif self.solver_subtype == "pardiso" and self.has_pardiso: # NOTE THAT THIS PARDISO SOLVER AUTOMATICALLY SAVES THE RIGHT FACTORISATION import pypardiso from pypardiso.scipy_aliases import pypardiso_solver as ps A = A.tocsr() t_solve = time() sol = pypardiso.spsolve(A,b) if self.reuse_factorisation is False: ps.remove_stored_factorization() ps.free_memory() print("Pardiso solver time is {}".format(time() - t_solve)) else: # FOR 'super_lu' if A.dtype != np.float64: A = A.astype(np.float64) A = A.tocsc() if self.solver_context_manager is None: if self.reuse_factorisation is False: sol = spsolve(A,b,permc_spec='MMD_AT_PLUS_A',use_umfpack=True) else: lu = splu(A) sol = lu.solve(b) self.solver_context_manager = lu else: sol = self.solver_context_manager.solve(b) elif self.solver_type == "iterative": # CALL ITERATIVE SOLVER if self.solver_subtype == "gmres": sol = gmres(A,b,tol=self.iterative_solver_tolerance)[0] if self.solver_subtype == "lgmres": sol = lgmres(A,b,tol=self.iterative_solver_tolerance)[0] elif self.solver_subtype == "bicgstab": sol = bicgstab(A,b,tol=self.iterative_solver_tolerance)[0] else: sol = cg(A,b,tol=self.iterative_solver_tolerance)[0] # PRECONDITIONED ITERATIVE SOLVER - CHECK # P = spilu(A.tocsc(), drop_tol=1e-5) # M_x = lambda x: P.solve(x) # m = A.shape[1] # n = A.shape[0] # M = LinearOperator((n * m, n * m), M_x) # sol = cg(A, b, tol=self.iterative_solver_tolerance, M=M)[0] elif self.solver_type == "amg": if self.has_amg_solver is False: raise ImportError('Algebraic multigrid solver was not found. Please install it using "pip install pyamg"') from pyamg import ruge_stuben_solver, rootnode_solver, smoothed_aggregation_solver if A.dtype != b.dtype: # DOWN-CAST b = b.astype(A.dtype) if not isspmatrix_csr(A): A = A.tocsr() t_solve = time() if self.iterative_solver_tolerance > 1e-9: self.iterative_solver_tolerance = 1e-10 # AMG METHOD amg_func = None if self.preconditioner_type=="smoothed_aggregation": # THIS IS TYPICALLY FASTER BUT THE TOLERANCE NEED TO BE SMALLER, TYPICALLY 1e-10 amg_func = smoothed_aggregation_solver elif self.preconditioner_type == "ruge_stuben": amg_func = ruge_stuben_solver elif self.preconditioner_type == "rootnode": amg_func = rootnode_solver else: amg_func = rootnode_solver ml = amg_func(A) # ml = amg_func(A, smooth=('energy', {'degree':2}), strength='evolution' ) # ml = amg_func(A, max_levels=3, diagonal_dominance=True) # ml = amg_func(A, coarse_solver=spsolve) # ml = amg_func(A, coarse_solver='cholesky') if self.solver_context_manager is None: # M = ml.aspreconditioner(cycle='V') M = ml.aspreconditioner() if self.reuse_factorisation: self.solver_context_manager = M else: M = self.solver_context_manager # EXPLICIT CALL TO KYROLOV SOLVERS WITH AMG PRECONDITIONER # sol, info = bicgstab(A, b, M=M, tol=self.iterative_solver_tolerance) # sol, info = cg(A, b, M=M, tol=self.iterative_solver_tolerance) # sol, info = gmres(A, b, M=M, tol=self.iterative_solver_tolerance) # IMPLICIT CALL TO KYROLOV SOLVERS WITH AMG PRECONDITIONER residuals = [] sol = ml.solve(b, tol=self.iterative_solver_tolerance, accel=self.solver_subtype, residuals=residuals) print("AMG solver time is {}".format(time() - t_solve)) elif self.solver_type == "petsc" and self.has_petsc: if self.solver_subtype != "gmres" and self.solver_subtype != "minres" and self.solver_subtype != "cg": self.solver_subtype == "cg" if self.iterative_solver_tolerance < 1e-9: self.iterative_solver_tolerance = 1e-7 from petsc4py import PETSc t_solve = time() pA = PETSc.Mat().createAIJ(size=A.shape, csr=(A.indptr, A.indices, A.data)) pb = PETSc.Vec().createWithArray(b) ksp = PETSc.KSP() ksp.create(PETSc.COMM_WORLD) # ksp.create() ksp.setType(self.solver_subtype) ksp.setTolerances(atol=self.iterative_solver_tolerance, rtol=self.iterative_solver_tolerance) # ILU ksp.getPC().setType('icc') # CREATE INITIAL GUESS psol = PETSc.Vec().createWithArray(np.ones(b.shape[0])) # SOLVE ksp.setOperators(pA) ksp.setFromOptions() ksp.solve(pb, psol) sol = psol.getArray() # print('Converged in', ksp.getIterationNumber(), 'iterations.') print("Petsc linear iterative solver time is {}".format(time() - t_solve)) else: warn("{} solver is not available. Default solver is going to be used".format(self.solver_type)) # FOR 'super_lu' if A.dtype != np.float64: A = A.astype(np.float64) A = A.tocsc() if self.solver_context_manager is None: if self.reuse_factorisation is False: sol = spsolve(A,b,permc_spec='MMD_AT_PLUS_A',use_umfpack=True) else: lu = splu(A) sol = lu.solve(b) self.solver_context_manager = lu else: sol = self.solver_context_manager.solve(b) return sol
[13, 14, 15, 0]], dtype=np.float64) arow = np.array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3], dtype=np.int32) acol = np.array([0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], dtype=np.int32) aval = np.array([1, 2, 3, 4, 5, 0, 7, 8, 9, 10, 0, 12, 13, 14, 15, 0], dtype=np.float64) context = MUMPSContext((n, arow, acol, aval, False), verbose=True) print 'MUMPS version: ', context.version_number context.analyze() context.factorize() e = np.ones(n, dtype=np.float64) rhs = np.dot(A, e) x = context.solve(rhs=rhs) print rhs, x x = context.refine(rhs, -1) print rhs, x sys.exit(0) np.testing.assert_almost_equal(x,e) print "= " * 80 B = np.ones([n, 3], dtype=np.float64) B[: ,1] = 2 * B[:,1] B[: ,2] = 3 * B[:,2] rhs = np.dot(A,B) x = context.solve(rhs=rhs)
acol = np.array([0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], dtype=np.int32) aval = np.array([1, 2, 3, 4, 5, 0, 7, 8, 9, 10, 0, 12, 13, 14, 15, 0], dtype=np.float64) context = MUMPSContext((n, arow, acol, aval, False), verbose=True) print 'MUMPS version: ', context.version_number context.analyze() context.factorize() e = np.ones(n, dtype=np.float64) rhs = np.dot(A, e) x = context.solve(rhs=rhs) print rhs, x x = context.refine(rhs, -1) print rhs, x sys.exit(0) np.testing.assert_almost_equal(x, e) print "= " * 80 B = np.ones([n, 3], dtype=np.float64) B[:, 1] = 2 * B[:, 1] B[:, 2] = 3 * B[:, 2] rhs = np.dot(A, B) x = context.solve(rhs=rhs) np.testing.assert_almost_equal(x, B)