mirror of
https://github.com/wassname/simpeg.git
synced 2026-07-12 07:46:56 +08:00
Wrapper utils for Solvers
This commit is contained in:
+23
-3
@@ -1,7 +1,7 @@
|
||||
import numpy as np
|
||||
import scipy.sparse as sp
|
||||
import scipy.sparse.linalg as linalg
|
||||
from Utils.matutils import mkvc, sdiag
|
||||
from Utils import mkvc, sdiag
|
||||
import warnings
|
||||
|
||||
DEFAULTS = {'direct':'scipy', 'iter':'scipy', 'triangular':'fortran', 'diagonal':'python'}
|
||||
@@ -214,12 +214,18 @@ class Solver(object):
|
||||
def solveIter(self, b, backend=None, M=None, iterSolver='CG', tol=1e-6, maxIter=50):
|
||||
if backend is None: backend = DEFAULTS['iter']
|
||||
|
||||
algorithms = {'CG':sp.linalg.cg}
|
||||
algorithms = {'CG':sp.linalg.cg, 'QMR':sp.linalg.qmr}
|
||||
assert iterSolver in algorithms, "iterSolver must be 'CG', or implement it yourself and add it here!"
|
||||
alg = algorithms[iterSolver]
|
||||
|
||||
if iterSolver == 'CG':
|
||||
opts = {'M':M}
|
||||
elif iterSolver == 'QMR':
|
||||
#TODO: make preconditioner better.
|
||||
opts = {'M1':np.sqrt(M), 'M2':np.sqrt(M)}
|
||||
|
||||
if len(b.shape) == 1 or b.shape[1] == 1:
|
||||
x, self.info = alg(self.A, b, M=M, tol=tol, maxiter=maxIter)
|
||||
x, self.info = alg(self.A, b, tol=tol, maxiter=maxIter)
|
||||
else:
|
||||
x = np.empty_like(b)
|
||||
for i in range(b.shape[1]):
|
||||
@@ -381,3 +387,17 @@ if __name__ == '__main__':
|
||||
toc = time() - tic
|
||||
print x
|
||||
print 'Error CG = ', np.linalg.norm(x-e, np.inf), 'Time: ', toc, 'Info: ', iSolve.info
|
||||
|
||||
|
||||
|
||||
A = -D*D.T
|
||||
A[0,0] *= 10 # remove the constant null space from the matrix
|
||||
e = np.ones(M.nC)
|
||||
b = A.dot(e)
|
||||
|
||||
iSolve = Solver(A, doDirect=False, options={'iterSolver': 'QMR', 'M':'J'})
|
||||
tic = time()
|
||||
x = iSolve.solve(b)
|
||||
toc = time() - tic
|
||||
print x
|
||||
print 'Error QMR = ', np.linalg.norm(x-e, np.inf), 'Time: ', toc, 'Info: ', iSolve.info
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import numpy as np
|
||||
from matutils import mkvc
|
||||
import warnings
|
||||
|
||||
def DSolverWrap(fun, factorize=True, checkAccuracy=True, accuracyTol=1e-8):
|
||||
|
||||
def __init__(self, A, **kwargs):
|
||||
self.A = A.tocsc()
|
||||
self.kwargs = kwargs
|
||||
if factorize:
|
||||
self.solver = fun(self.A, **kwargs)
|
||||
|
||||
def solve(self, b):
|
||||
if len(b.shape) == 1 or b.shape[1] == 1:
|
||||
# Just one RHS
|
||||
if factorize:
|
||||
X = self.solver.solve(b.flatten(), **self.kwargs)
|
||||
else:
|
||||
X = fun(self.A, b.flatten(), **self.kwargs)
|
||||
else: # Multiple RHSs
|
||||
X = np.empty_like(b)
|
||||
for i in range(b.shape[1]):
|
||||
if factorize:
|
||||
X[:,i] = self.solver.solve(b[:,i])
|
||||
else:
|
||||
X[:,i] = fun(self.A, b[:,i], **self.kwargs)
|
||||
|
||||
if checkAccuracy:
|
||||
nrm = np.linalg.norm(mkvc(self.A*X - b)) / np.linalg.norm(Utils.mkvc(b))
|
||||
if nrm > accuracyTol:
|
||||
msg = '### SolverWarning ###: Accuracy on solve is above tolerance: %e > %e' % (nrm, accuracyTol)
|
||||
print msg
|
||||
warnings.warn(msg, RuntimeWarning)
|
||||
return X
|
||||
|
||||
return type(fun.__name__, (object,), {"__init__": __init__, "solve": solve})
|
||||
|
||||
|
||||
|
||||
def ISolverWrap(fun, checkAccuracy=True, accuracyTol=1e-5):
|
||||
|
||||
def __init__(self, A, **kwargs):
|
||||
self.A = A.tocsc()
|
||||
self.kwargs = kwargs
|
||||
|
||||
def solve(self, b):
|
||||
if len(b.shape) == 1 or b.shape[1] == 1:
|
||||
# Just one RHS
|
||||
out = fun(self.A, b.flatten(), **self.kwargs)
|
||||
if type(out) is tuple and len(out) == 2:
|
||||
# We are dealing with scipy output with an info!
|
||||
X = out[0]
|
||||
self.info = out[1]
|
||||
else:
|
||||
X = out
|
||||
else: # Multiple RHSs
|
||||
X = np.empty_like(b)
|
||||
for i in range(b.shape[1]):
|
||||
out = fun(self.A, b[:,i], **self.kwargs)
|
||||
if type(out) is tuple and len(out) == 2:
|
||||
# We are dealing with scipy output with an info!
|
||||
X[:,i] = out[0]
|
||||
self.info = out[1]
|
||||
else:
|
||||
X[:,i] = out
|
||||
|
||||
if checkAccuracy:
|
||||
nrm = np.linalg.norm(mkvc(self.A*X - b)) / np.linalg.norm(Utils.mkvc(b))
|
||||
if nrm > accuracyTol:
|
||||
msg = '### SolverWarning ###: Accuracy on solve is above tolerance: %e > %e' % (nrm, accuracyTol)
|
||||
print msg
|
||||
warnings.warn(msg, RuntimeWarning)
|
||||
return X
|
||||
|
||||
return type(fun.__name__, (object,), {"__init__": __init__, "solve": solve})
|
||||
@@ -4,6 +4,7 @@ from lrmutils import volTetra, faceInfo, indexCube
|
||||
from interputils import interpmat
|
||||
from ipythonutils import easyAnimate as animate
|
||||
import ModelBuilder
|
||||
import SolverUtils
|
||||
|
||||
import types
|
||||
import time
|
||||
|
||||
@@ -15,6 +15,14 @@ Matrix Utilities
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
|
||||
Solver Utilities
|
||||
================
|
||||
|
||||
.. automodule:: SimPEG.Utils.SolverUtils
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
||||
LRM Utilities
|
||||
=============
|
||||
|
||||
|
||||
Reference in New Issue
Block a user