def solver_direct(A, b, timing=False, solver=SOLVER): # solves linear system of equations b = b.astype(np.complex128) b = b.reshape((-1, )) if not b.any(): return np.zeros(b.shape) if timing: t = time() if solver.lower() == 'pardiso': pSolve = pardisoSolver( A, mtype=13) # Matrix is complex unsymmetric due to SC-PML pSolve.factor() x = pSolve.solve(b) pSolve.clear() elif solver.lower() == 'scipy': x = spl.spsolve(A, b) else: raise ValueError( 'Invalid solver choice: {}, options are pardiso or scipy'.format( str(solver))) if timing: print('Linear system solve took {:.2f} seconds'.format(time() - t)) return x
def solver_complex(Al, Bl, dfe, timing=False, solver=SOLVER): dfe = dfe.astype(np.complex128) dfe = dfe.reshape((-1, )) A_adj = sp.vstack((sp.hstack((np.real(Al + Bl), np.imag(Al + Bl))), sp.hstack((np.imag(Bl - Al), np.real(Al - Bl))))) A_adj = sp.csr_matrix(A_adj.transpose()) src_adj = np.hstack((-np.real(dfe), -np.imag(dfe))) if timing: t = time() if solver.lower() == 'pardiso': pSolve = pardisoSolver( A_adj, mtype=13) # Matrix is complex unsymmetric due to SC-PML pSolve.factor() x = pSolve.solve(src_adj) pSolve.clear() elif solver.lower() == 'scipy': x = spl.spsolve(A_adj, src_adj) else: raise ValueError( 'Invalid solver choice: {}, options are pardiso or scipy'.format( str(solver))) if timing: print('Linear system solve took {:.2f} seconds'.format(time() - t)) return x
def _solve_direct(A, b): """ Direct solver """ if using_mkl: pSolve = pardisoSolver(A, mtype=13) pSolve.factor() x = pSolve.solve(b) pSolve.clear() return x else: return spl.spsolve(A, b)
def solve_sparse(A, b, matrix_type='symm', verbose=False): ''' Abstraction of the solution of the sparse system Ax=b using the fastest solver available for sparse and non-sparse matrices. Parameters ---------- A : sp.sparse.CSR sparse matrix in CSR-format b : ndarray right hand side of equation matrixd_type : {'spd', 'symm', 'unsymm'}, optional Specifier for the matrix type: - 'spd' : symmetric positive definite - 'symm' : symmetric indefinite, default. - 'unsymm' : generally unsymmetric Returns ------- x : ndarray solution of system Ax=b Notes ----- This tool uses the Intel MKL library provided by Anaconda. If the Intel MKL is not installed, especially for large systems the computation time can go crazy. To adjust the number of threads used for the computation, it is recommended to use the mkl-service module provided by Anaconda: >>> import mkl >>> mkl.get_max_threads() 2 >>> mkl.set_num_threads(1) >>> mkl.get_max_threads() 1 ''' if sp.sparse.issparse(A): if use_pardiso: mtype = mtypes[matrix_type] pSolve = pardisoSolver(A, mtype=mtype, verbose=verbose) x = pSolve.run_pardiso(13, b) pSolve.clear() else: x = sp.sparse.linalg.spsolve(A, b) else: x = sp.linalg.solve(A, b) return x
def test_RealNonSym(self): nSize = 100 A = sp.rand(nSize, nSize, 0.05, format='csr', random_state=100) A = A + sp.spdiags(np.ones(nSize), 0, nSize, nSize) A = A.tocsr() np.random.seed(1) xTrue = np.random.rand(nSize) rhs = A.dot(xTrue) pSolve = pardisoSolver(A, mtype=11) pSolve.run_pardiso(12) x = pSolve.run_pardiso(33, rhs) self.assertLess(np.linalg.norm(x-xTrue)/np.linalg.norm(xTrue), 1e-12)
def test_ComplexNonSym_RealRHS(self): nSize = 100 A = sp.rand(nSize, nSize, 0.05, format='csr', random_state=100) A = A + sp.spdiags(np.ones(nSize), 0, nSize, nSize) A.data = A.data + 1j*np.random.rand(A.nnz) A = A.tocsr() np.random.seed(1) rhs = np.random.rand(nSize) pSolve = pardisoSolver(A, mtype=13) pSolve.run_pardiso(12) x = pSolve.run_pardiso(33, rhs) pSolve.clear() self.assertLess(np.linalg.norm(A.dot(x)-rhs), 1e-12)
def test_RealNonSym(self): nSize = 100 A = sp.rand(nSize, nSize, 0.05, format='csr', random_state=100) A = A + sp.spdiags(np.ones(nSize), 0, nSize, nSize) A = A.tocsr() np.random.seed(1) xTrue = np.random.rand(nSize) rhs = A.dot(xTrue) pSolve = pardisoSolver(A, mtype=11) pSolve.run_pardiso(12) x = pSolve.run_pardiso(33, rhs) self.assertLess( np.linalg.norm(x - xTrue) / np.linalg.norm(xTrue), 1e-12)
def test_ComplexNonSym_RealRHS(self): nSize = 100 A = sp.rand(nSize, nSize, 0.05, format='csr', random_state=100) A = A + sp.spdiags(np.ones(nSize), 0, nSize, nSize) A.data = A.data + 1j * np.random.rand(A.nnz) A = A.tocsr() np.random.seed(1) rhs = np.random.rand(nSize) pSolve = pardisoSolver(A, mtype=13) pSolve.run_pardiso(12) x = pSolve.run_pardiso(33, rhs) pSolve.clear() self.assertLess(np.linalg.norm(A.dot(x) - rhs), 1e-12)
def test_RealPosInd(self): A = sp.rand(nSize, nSize, 0.05, format='csr', random_state=100) d = np.ones(nSize) d[nSize/2:] = -1. A = A.T.dot(A) + sp.spdiags(d, 0, nSize, nSize) A = A.tocsr() np.random.seed(1) xTrue = np.random.rand(nSize) rhs = A.dot(xTrue) pSolve = pardisoSolver(A, mtype=-2) pSolve.run_pardiso(12) x = pSolve.run_pardiso(33, rhs) self.assertLess(np.linalg.norm(x-xTrue)/np.linalg.norm(xTrue), 1e-12)
def test_FactorSolve(self): nSize = 100 A = sp.rand(nSize, nSize, 0.05, format='csr', random_state=100) A = A + sp.spdiags(np.ones(nSize), 0, nSize, nSize) A = A.tocsr() np.random.seed(1) xTrue = np.random.rand(nSize) rhs = A.dot(xTrue) pSolve = pardisoSolver(A, mtype=11) pSolve.factor() x = pSolve.solve(rhs) pSolve.clear() self.assertLess(np.linalg.norm(x-xTrue)/np.linalg.norm(xTrue), 1e-12)
def test_ComplexHerm(self): nSize = 100 A = sp.rand(nSize, nSize, 0.05, format='csr', random_state=100) A.data = A.data + 1j*np.random.rand(A.nnz) A = A.T.dot(A.conj()) + sp.spdiags(np.ones(nSize), 0, nSize, nSize) A = A.tocsr() np.random.seed(1) xTrue = np.random.rand(nSize) + 1j*np.random.rand(nSize) rhs = A.dot(xTrue) pSolve = pardisoSolver(A, mtype=4) pSolve.run_pardiso(12) x = pSolve.run_pardiso(33, rhs) pSolve.clear() self.assertLess(np.linalg.norm(x-xTrue)/np.linalg.norm(xTrue), 1e-12)
def test_RealPosInd(self): A = sp.rand(nSize, nSize, 0.05, format='csr', random_state=100) d = np.ones(nSize) d[nSize / 2:] = -1. A = A.T.dot(A) + sp.spdiags(d, 0, nSize, nSize) A = A.tocsr() np.random.seed(1) xTrue = np.random.rand(nSize) rhs = A.dot(xTrue) pSolve = pardisoSolver(A, mtype=-2) pSolve.run_pardiso(12) x = pSolve.run_pardiso(33, rhs) self.assertLess( np.linalg.norm(x - xTrue) / np.linalg.norm(xTrue), 1e-12)
def test_FactorSolve(self): nSize = 100 A = sp.rand(nSize, nSize, 0.05, format='csr', random_state=100) A = A + sp.spdiags(np.ones(nSize), 0, nSize, nSize) A = A.tocsr() np.random.seed(1) xTrue = np.random.rand(nSize) rhs = A.dot(xTrue) pSolve = pardisoSolver(A, mtype=11) pSolve.factor() x = pSolve.solve(rhs) pSolve.clear() self.assertLess( np.linalg.norm(x - xTrue) / np.linalg.norm(xTrue), 1e-12)
def test_ComplexHerm(self): nSize = 100 A = sp.rand(nSize, nSize, 0.05, format='csr', random_state=100) A.data = A.data + 1j * np.random.rand(A.nnz) A = A.T.dot(A.conj()) + sp.spdiags(np.ones(nSize), 0, nSize, nSize) A = A.tocsr() np.random.seed(1) xTrue = np.random.rand(nSize) + 1j * np.random.rand(nSize) rhs = A.dot(xTrue) pSolve = pardisoSolver(A, mtype=4) pSolve.run_pardiso(12) x = pSolve.run_pardiso(33, rhs) pSolve.clear() self.assertLess( np.linalg.norm(x - xTrue) / np.linalg.norm(xTrue), 1e-12)
def make_solver(B, symmetric=False, spd=False): """Return a :class:`LinearOperator` that acts as a linear solver for the (dense or sparse) square matrix `B`. If `B` is symmetric, passing ``symmetric=True`` may try to take advantage of this. If `B` is symmetric and positive definite, pass ``spd=True``. """ if spd: symmetric = True if scipy.sparse.issparse(B): if HAVE_MKL: # use MKL Pardiso mtype = 11 # real, nonsymmetric if symmetric: mtype = 2 if spd else -2 solver = pyMKL.pardisoSolver(B, mtype) solver.factor() return PardisoSolverWrapper(B.shape, B.dtype, solver) else: # use SuperLU (unless scipy uses UMFPACK?) -- really slow! spLU = scipy.sparse.linalg.splu(B.tocsc(), permc_spec='NATURAL') return scipy.sparse.linalg.LinearOperator(B.shape, dtype=B.dtype, matvec=spLU.solve, matmat=spLU.solve) else: if symmetric: chol = scipy.linalg.cho_factor(B, check_finite=False) solve = lambda x: scipy.linalg.cho_solve( chol, x, check_finite=False) return scipy.sparse.linalg.LinearOperator(B.shape, dtype=B.dtype, matvec=solve, matmat=solve) else: LU = scipy.linalg.lu_factor(B, check_finite=False) solve = lambda x: scipy.linalg.lu_solve(LU, x, check_finite=False) return scipy.sparse.linalg.LinearOperator(B.shape, dtype=B.dtype, matvec=solve, matmat=solve)
def solver_complex2real(A11, A12, b, timing=False, solver=DEFAULT_SOLVER): # solves linear system of equations [A11, A12; A21*, A22*]*[x; x*] = [b; b*] b = b.astype(np.complex128) b = b.reshape((-1, )) N = b.size if not b.any(): return zeros(b.shape) b_re = np.real(b).astype(np.float64) b_im = np.imag(b).astype(np.float64) Areal = sp.vstack( (sp.hstack( (np.real(A11) + np.real(A12), -np.imag(A11) + np.imag(A12))), sp.hstack( (np.imag(A11) + np.imag(A12), np.real(A11) - np.real(A12))))) if timing: t = time() if solver.lower() == 'pardiso': pSolve = pardisoSolver(Areal, mtype=11) # Matrix is real unsymmetric pSolve.factor() x = pSolve.solve(np.hstack((b_re, b_im))) pSolve.clear() elif solver.lower() == 'scipy': x = spsolve(Areal, np.hstack((b_re, b_im))) else: raise ValueError( 'Invalid solver choice: {}, options are pardiso or scipy'.format( str(solver))) if timing: print('Linear system solve took {:.2f} seconds'.format(time() - t)) return (x[:N] + 1j * x[N:2 * N])
def __init__(self, A, matrix_type='symm', verbose=False): ''' Parameters ---------- A : sp.sparse.CSR sparse matrix in CSR-format matrixd_type : {'spd', 'symm', 'unsymm'}, optional Specifier for the matrix type: - 'spd' : symmetric positive definite - 'symm' : symmetric indefinite - 'unsymm' : generally unsymmetric verbose : bool Flag for verbosity. ''' if use_pardiso: mtype = mtypes[matrix_type] self.pSolve = pardisoSolver(A, mtype=mtype, verbose=verbose) self.pSolve.run_pardiso(12) # Analysis and numerical factorization else: self.pSolve = sp.sparse.linalg.splu(A)