mirror of
https://github.com/wassname/simpeg.git
synced 2026-09-12 12:51:28 +08:00
updates to face innerProducts
Increase Speed Add derivatives Add tests
This commit is contained in:
@@ -10,7 +10,8 @@ class InnerProducts(object):
|
||||
def __init__(self):
|
||||
raise Exception('InnerProducts is a base class providing inner product matrices for meshes and cannot run on its own. Inherit to your favorite Mesh class.')
|
||||
|
||||
def getFaceInnerProduct(self, materialProperty=None, returnP=False, invertProperty=False):
|
||||
def getFaceInnerProduct(self, materialProperty=None, returnP=False,
|
||||
invertProperty=False):
|
||||
"""
|
||||
:param numpy.array materialProperty: material property (tensor properties are possible) at each cell center (nC, (1, 3, or 6))
|
||||
:param bool returnP: returns the projection matrices
|
||||
@@ -18,6 +19,14 @@ class InnerProducts(object):
|
||||
:rtype: scipy.csr_matrix
|
||||
:return: M, the inner product matrix (nF, nF)
|
||||
"""
|
||||
fast = None
|
||||
|
||||
if returnP is False and hasattr(self, '_fastFaceInnerProduct'):
|
||||
fast = self._fastFaceInnerProduct(materialProperty=materialProperty, invertProperty=invertProperty)
|
||||
|
||||
if fast is not None:
|
||||
return fast
|
||||
|
||||
if invertProperty:
|
||||
materialProperty = invPropertyTensor(self, materialProperty)
|
||||
|
||||
@@ -62,6 +71,34 @@ class InnerProducts(object):
|
||||
else:
|
||||
return A
|
||||
|
||||
def getFaceInnerProductDeriv(self, materialProperty=None, P=None):
|
||||
"""
|
||||
:param numpy.array materialProperty: material property (tensor properties are possible) at each cell center (nC, (1, 3, or 6))
|
||||
:rtype: scipy.csr_matrix
|
||||
:return: M, the inner product matrix (nF, nF)
|
||||
"""
|
||||
|
||||
fast = None
|
||||
|
||||
if hasattr(self, '_fastFaceInnerProductDeriv'):
|
||||
fast = self._fastFaceInnerProductDeriv(materialProperty=materialProperty)
|
||||
|
||||
if fast is not None:
|
||||
return fast
|
||||
|
||||
raise NotImplementedError('Derivatives for the material property specified are not yet implemented.')
|
||||
|
||||
if P is None:
|
||||
M, P = getFaceInnerProduct(self, materialProperty=materialProperty, returnP=True)
|
||||
|
||||
d = self.dim
|
||||
|
||||
if d == 1:
|
||||
P[0].T * sp.identity(n) * P[0]
|
||||
|
||||
|
||||
|
||||
|
||||
def getEdgeInnerProduct(self, materialProperty=None, returnP=False, invertProperty=False):
|
||||
"""
|
||||
:param numpy.array materialProperty: material property (tensor properties are possible) at each cell center (nC, (1, 3, or 6))
|
||||
|
||||
@@ -39,6 +39,7 @@ class TensorMesh(BaseRectangularMesh, TensorView, DiffOperators, InnerProducts):
|
||||
|
||||
def __init__(self, h_in, x0=None):
|
||||
assert type(h_in) is list, 'h_in must be a list'
|
||||
assert len(h_in) in [1,2,3], 'h_in must be of dimension 1, 2, or 3'
|
||||
h = range(len(h_in))
|
||||
for i, h_i in enumerate(h_in):
|
||||
if type(h_i) in [int, long, float]:
|
||||
@@ -491,6 +492,49 @@ class TensorMesh(BaseRectangularMesh, TensorView, DiffOperators, InnerProducts):
|
||||
indzu = (self.gridCC[:,2]==max(self.gridCC[:,2]))
|
||||
return indxd, indxu, indyd, indyu, indzd, indzu
|
||||
|
||||
def _fastFaceInnerProduct(self, materialProperty=None, invertProperty=False):
|
||||
"""
|
||||
Fast version of getFaceInnerProduct.
|
||||
This does not handle the case of a full tensor materialProperty.
|
||||
|
||||
:param numpy.array materialProperty: material property (tensor properties are possible) at each cell center (nC, (1, 3, or 6))
|
||||
:param bool returnP: returns the projection matrices
|
||||
:param bool invertProperty: inverts the material property
|
||||
:rtype: scipy.csr_matrix
|
||||
:return: M, the inner product matrix (nF, nF)
|
||||
"""
|
||||
if materialProperty is None:
|
||||
materialProperty = np.ones(self.nC)
|
||||
|
||||
if materialProperty.size == self.nC:
|
||||
if invertProperty:
|
||||
materialProperty = 1./materialProperty
|
||||
Av = self.aveF2CC
|
||||
V = Utils.sdiag(self.vol)
|
||||
return self.dim * Utils.sdiag(Av.T * V * materialProperty)
|
||||
if materialProperty.size == self.nC*self.dim:
|
||||
if invertProperty:
|
||||
materialProperty = 1./materialProperty
|
||||
Av = self.aveF2CCV
|
||||
V = sp.kron(sp.identity(self.dim), Utils.sdiag(self.vol))
|
||||
return Utils.sdiag(Av.T * V * Utils.mkvc(materialProperty))
|
||||
|
||||
|
||||
|
||||
def _fastFaceInnerProductDeriv(self, materialProperty=None):
|
||||
"""
|
||||
:param numpy.array materialProperty: material property (tensor properties are possible) at each cell center (nC, (1, 3, or 6))
|
||||
:rtype: scipy.csr_matrix
|
||||
:return: M, the inner product matrix (nF, nF)
|
||||
"""
|
||||
if materialProperty is None or materialProperty.size == self.nC:
|
||||
Av = self.aveF2CC
|
||||
return self.dim * Av.T * Utils.sdiag(self.vol)
|
||||
if materialProperty.size == self.nC*self.dim: # anisotropic
|
||||
Av = self.aveF2CCV
|
||||
V = sp.kron(sp.identity(self.dim), Utils.sdiag(self.vol))
|
||||
return Av.T * V
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print('Welcome to tensor mesh!')
|
||||
|
||||
@@ -30,7 +30,7 @@ class TestInnerProducts(OrderTest):
|
||||
sigma = np.c_[call(sigma1, Gc)]
|
||||
analytic = 647./360 # Found using sympy.
|
||||
elif self.sigmaTest == 3:
|
||||
sigma = np.c_[call(sigma1, Gc), call(sigma2, Gc), call(sigma3, Gc)]
|
||||
sigma = np.r_[call(sigma1, Gc), call(sigma2, Gc), call(sigma3, Gc)]
|
||||
analytic = 37./12 # Found using sympy.
|
||||
elif self.sigmaTest == 6:
|
||||
sigma = np.c_[call(sigma1, Gc), call(sigma2, Gc), call(sigma3, Gc),
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import numpy as np
|
||||
import unittest
|
||||
from SimPEG import *
|
||||
from TestUtils import checkDerivative
|
||||
|
||||
|
||||
class TestInnerProductsDerivs(unittest.TestCase):
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def test_FaceIP_derivs_isotropic(self):
|
||||
for d in range(3):
|
||||
mesh = Mesh.TensorMesh([10,5,4][d:])
|
||||
M,Ps = mesh.getFaceInnerProduct(returnP=True)
|
||||
v = np.random.rand(mesh.nF)
|
||||
def fun(sig):
|
||||
M = mesh.getFaceInnerProduct(sig)
|
||||
Md = mesh.getFaceInnerProductDeriv(sig)
|
||||
return M*v, Utils.sdiag(v)*Md
|
||||
sig = np.random.rand(mesh.nC)
|
||||
passed = checkDerivative(fun, sig, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_FaceIP_derivs_anisotropic(self):
|
||||
for d in range(3):
|
||||
mesh = Mesh.TensorMesh([10,5,4][d:])
|
||||
M,Ps = mesh.getFaceInnerProduct(returnP=True)
|
||||
v = np.random.rand(mesh.nF)
|
||||
def fun(sig):
|
||||
M = mesh.getFaceInnerProduct(sig)
|
||||
Md = mesh.getFaceInnerProductDeriv(sig)
|
||||
return M*v, Utils.sdiag(v)*Md
|
||||
sig = np.random.rand(mesh.nC*mesh.dim)
|
||||
passed = checkDerivative(fun, sig, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user