mirror of
https://github.com/wassname/simpeg.git
synced 2026-07-31 12:40:46 +08:00
Multiple RHSs on solvers in Fortran. ~2x speed up on matlab implementation for a single RHS. for multiple RHS there are still some problems.
Someone with some knowledge of how fortran works should look at this code. Added a setup.py script that complies things. f2py should work on most computers, because it is included in the numpy distribution.
This commit is contained in:
+32
-10
@@ -1,14 +1,22 @@
|
||||
import numpy as np
|
||||
import scipy.sparse as sparse
|
||||
import scipy.sparse.linalg as linalg
|
||||
from SimPEG.utils import mkvc
|
||||
|
||||
DEFAULTS = {'direct':'scipy', 'forward':'fortran', 'backward':'fortran', 'diagonal':'python'}
|
||||
|
||||
try:
|
||||
import TriSolve
|
||||
except Exception, e:
|
||||
import os
|
||||
# Note: this may not work from SublimeText, if that is the case, just run the command in your shell.
|
||||
os.system('f2py -c TriSolve.f -m TriSolve')
|
||||
import TriSolve
|
||||
try:
|
||||
import os
|
||||
# Note: this may not work from SublimeText, if that is the case, just run the command in your shell.
|
||||
os.system('f2py -c TriSolve.f -m TriSolve')
|
||||
import TriSolve
|
||||
except Exception, e:
|
||||
print 'Warning: Python backend is being used for solver. Run setup.py from the command line.'
|
||||
DEFAULTS['forward'] = 'python'
|
||||
DEFAULTS['backward'] = 'python'
|
||||
|
||||
class Solver(object):
|
||||
"""
|
||||
@@ -76,7 +84,7 @@ class Solver(object):
|
||||
del self.dsolve
|
||||
self.dsolve = None
|
||||
|
||||
def solveDirect(self, b, factorize=False, backend='scipy'):
|
||||
def solveDirect(self, b, factorize=False, backend=None):
|
||||
"""
|
||||
Use solve instead of this interface.
|
||||
|
||||
@@ -85,6 +93,8 @@ class Solver(object):
|
||||
:rtype: numpy.ndarray
|
||||
:return: x
|
||||
"""
|
||||
if backend is None: backend = DEFAULTS['scipy']
|
||||
|
||||
assert np.shape(self.A)[1] == np.shape(b)[0], 'Dimension mismatch'
|
||||
|
||||
if factorize and self.dsolve is None:
|
||||
@@ -111,7 +121,7 @@ class Solver(object):
|
||||
def solveIter(self, b, M=None, iterSolver='CG'):
|
||||
pass
|
||||
|
||||
def solveBackward(self, b, backend='python'):
|
||||
def solveBackward(self, b, backend=None):
|
||||
"""
|
||||
Use solve instead of this interface.
|
||||
|
||||
@@ -121,6 +131,7 @@ class Solver(object):
|
||||
:rtype: numpy.ndarray
|
||||
:return: x
|
||||
"""
|
||||
if backend is None: backend = DEFAULTS['backward']
|
||||
if type(self.A) is not sparse.csr.csr_matrix:
|
||||
from scipy.sparse import csr_matrix
|
||||
self.A = csr_matrix(self.A)
|
||||
@@ -128,7 +139,11 @@ class Solver(object):
|
||||
rowptr = self.A.indptr
|
||||
colind = self.A.indices
|
||||
if backend == 'fortran':
|
||||
x = TriSolve.backward(vals, rowptr, colind, b, self.A.data.size, b.size)
|
||||
if len(b.shape) == 1 or b.shape[1] == 1:
|
||||
x = TriSolve.backward(vals, rowptr, colind, b, self.A.data.size, b.size, 1)
|
||||
x = mkvc(x)
|
||||
else:
|
||||
x = TriSolve.backward(vals, rowptr, colind, b, self.A.data.size, b.shape[0], b.shape[1])
|
||||
elif backend == 'python':
|
||||
x = np.empty_like(b) # empty() is faster than zeros().
|
||||
for i in reversed(xrange(self.A.shape[0])):
|
||||
@@ -138,7 +153,7 @@ class Solver(object):
|
||||
x[i] = (b[i] - np.dot(ith_row[1:], x_vals[1:])) / ith_row[0]
|
||||
return x
|
||||
|
||||
def solveForward(self, b, backend='python'):
|
||||
def solveForward(self, b, backend=None):
|
||||
"""
|
||||
Use solve instead of this interface.
|
||||
|
||||
@@ -148,6 +163,7 @@ class Solver(object):
|
||||
:rtype: numpy.ndarray
|
||||
:return: x
|
||||
"""
|
||||
if backend is None: backend = DEFAULTS['forward']
|
||||
if type(self.A) is not sparse.csr.csr_matrix:
|
||||
from scipy.sparse import csr_matrix
|
||||
self.A = csr_matrix(self.A)
|
||||
@@ -155,7 +171,11 @@ class Solver(object):
|
||||
rowptr = self.A.indptr
|
||||
colind = self.A.indices
|
||||
if backend == 'fortran':
|
||||
x = TriSolve.forward(vals, rowptr, colind, b, self.A.data.size, b.size)
|
||||
if len(b.shape) == 1 or b.shape[1] == 1:
|
||||
x = TriSolve.forward(vals, rowptr, colind, b, self.A.data.size, b.size, 1)
|
||||
x = mkvc(x)
|
||||
else:
|
||||
x = TriSolve.forward(vals, rowptr, colind, b, self.A.data.size, b.shape[0], b.shape[1])
|
||||
elif backend == 'python':
|
||||
x = np.empty_like(b) # empty() is faster than zeros().
|
||||
for i in xrange(self.A.shape[0]):
|
||||
@@ -165,7 +185,7 @@ class Solver(object):
|
||||
x[i] = (b[i] - np.dot(ith_row[:-1], x_vals[:-1])) / ith_row[-1]
|
||||
return x
|
||||
|
||||
def solveDiagonal(self, b, backend='python'):
|
||||
def solveDiagonal(self, b, backend=None):
|
||||
"""
|
||||
Use solve instead of this interface.
|
||||
|
||||
@@ -175,6 +195,8 @@ class Solver(object):
|
||||
:rtype: numpy.ndarray
|
||||
:return: x
|
||||
"""
|
||||
if backend is None: backend = DEFAULTS['diagonal']
|
||||
|
||||
diagA = self.A.diagonal()
|
||||
if len(b.shape) == 1 or b.shape[1] == 1:
|
||||
# Just one RHS
|
||||
|
||||
+26
-16
@@ -1,54 +1,64 @@
|
||||
c File TriSolve.f
|
||||
subroutine forward(al, ial, jal, b, nv, n, x)
|
||||
subroutine forward(al, ial, jal, b, nv, n, nRHS, x)
|
||||
double precision al(nv)
|
||||
integer ial(n+1)
|
||||
integer jal(nv)
|
||||
double precision b(n)
|
||||
double precision x(n)
|
||||
double precision b(n,nRHS)
|
||||
double precision x(n,nRHS)
|
||||
integer nv
|
||||
integer n
|
||||
integer nRHS
|
||||
integer rhs
|
||||
cf2py intent(in) :: al
|
||||
cf2py intent(in) :: ial
|
||||
cf2py intent(in) :: jal
|
||||
cf2py intent(in) :: b
|
||||
cf2py intent(in) :: nv
|
||||
cf2py intent(in) :: n
|
||||
cf2py intent(in) :: nRHS
|
||||
cf2py intent(out) :: x
|
||||
real ( kind = 8 ) t
|
||||
|
||||
do k = 1, n
|
||||
t = b(k)
|
||||
do j = ial(k)+1, ial(k+1)
|
||||
t = t - al(j) * x(jal(j)+1)
|
||||
do rhs = 1, nRHS
|
||||
do k = 1, n
|
||||
t = b(k,rhs)
|
||||
do j = ial(k)+1, ial(k+1)
|
||||
t = t - al(j) * x(jal(j)+1,rhs)
|
||||
end do
|
||||
x(k,rhs) = t/al(ial(k+1))
|
||||
end do
|
||||
x(k) = t/al(ial(k+1))
|
||||
end do
|
||||
end subroutine forward
|
||||
|
||||
|
||||
subroutine backward(au,iau, jau, b, nv, n, x)
|
||||
subroutine backward(au,iau, jau, b, nv, n, nRHS, x)
|
||||
double precision au(nv)
|
||||
integer iau(n+1)
|
||||
integer jau(nv)
|
||||
double precision b(n)
|
||||
double precision x(n)
|
||||
double precision b(n,nRHS)
|
||||
double precision x(n,nRHS)
|
||||
integer nv
|
||||
integer n
|
||||
integer nRHS
|
||||
integer rhs
|
||||
cf2py intent(in) :: au
|
||||
cf2py intent(in) :: iau
|
||||
cf2py intent(in) :: jau
|
||||
cf2py intent(in) :: b
|
||||
cf2py intent(in) :: nv
|
||||
cf2py intent(in) :: n
|
||||
cf2py intent(in) :: nRHS
|
||||
cf2py intent(out) :: x
|
||||
real ( kind = 8 ) t
|
||||
|
||||
do k = n, 1, -1
|
||||
t = b(k)
|
||||
do j = iau(k)+1, iau(k+1)
|
||||
t = t - au(j) * x(jau(j)+1)
|
||||
do rhs = 1, nRHS
|
||||
do k = n, 1, -1
|
||||
t = b(k,rhs)
|
||||
do j = iau(k)+1, iau(k+1)
|
||||
t = t - au(j) * x(jau(j)+1,rhs)
|
||||
end do
|
||||
x(k,rhs) = t/au(iau(k)+1)
|
||||
end do
|
||||
x(k) = t/au(iau(k)+1)
|
||||
end do
|
||||
|
||||
end subroutine backward
|
||||
|
||||
@@ -3,9 +3,9 @@ import sputils
|
||||
import lomutils
|
||||
import interputils
|
||||
import ModelBuilder
|
||||
import Solver
|
||||
from Solver import Solver
|
||||
from matutils import getSubArray, mkvc, ndgrid, ind2sub, sub2ind
|
||||
from sputils import spzeros, kron3, speye, sdiag
|
||||
from lomutils import volTetra, faceInfo, inv2X2BlockDiagonal, inv3X3BlockDiagonal, indexCube, exampleLomGird
|
||||
from interputils import interpmat
|
||||
import Solver
|
||||
from Solver import Solver
|
||||
|
||||
Reference in New Issue
Block a user