Files
simpeg/SimPEG/DiffOperators.py
T
Rowan Cockett ef557beb84 Merged Seogi's code into the Tensor Mesh code base.
This is under the DiffOperators class, which can be inherited with BaseMesh to any Mesh Object.

Cell area and other dimension calculations are included in the TensorMesh class.

Wrote unit tests for cell vol, area, and edges.
2013-07-18 10:41:58 -07:00

157 lines
5.3 KiB
Python

import numpy as np
from scipy import sparse
from sputils import ddx, sdiag, speye, kron3, spzeros, av
class DiffOperators(object):
"""
Class creates the differential operators that you need!
"""
def __init__(self):
raise Exception('You should use a Mesh class.')
def DIV():
doc = "Construct the 3D divergence operator on Faces."
def fget(self):
if(self._DIV is None):
# The number of cell centers in each direction
n = [x.size for x in self.h]
# Compute divergence operator on faces
dd = [ddx(x) for x in n]
if(self.dim == 1):
D = dd[0]
elif(self.dim == 2):
D1 = sparse.kron(speye(n[1]), dd[0])
D2 = sparse.kron(dd[1], speye(n[0]))
D = sparse.hstack((D1, D2), format="csr")
elif(self.dim == 3):
D1 = kron3(speye(n[2]), speye(n[1]), dd[0])
D2 = kron3(speye(n[2]), dd[1], speye(n[0]))
D3 = kron3(dd[2], speye(n[1]), speye(n[0]))
D = sparse.hstack((D1, D2, D3), format="csr")
# Compute areas of cell faces
S = self.area
# Compute cell volumes
V = self.vol
self._DIV = sdiag(1/V)*D*sdiag(S)
return self._DIV
return locals()
_DIV = None
DIV = property(**DIV())
def GRAD():
doc = "Construct the 3D nodal gradient operator."
def fget(self):
if(self._GRAD is None):
# The number of cell centers in each direction
n1 = np.size(self.hx)
n2 = np.size(self.hy)
n3 = np.size(self.hz)
# Compute lengths of cell edges
L = self.edge
# Compute divergence operator on faces
d1 = ddx(n1)
d2 = ddx(n2)
d3 = ddx(n3)
D1 = kron3(speye(n3+1), speye(n2+1), d1)
D2 = kron3(speye(n3+1), d2, speye(n1+1))
D3 = kron3(d3, speye(n2+1), speye(n1+1))
G = sparse.vstack((D1, D2, D3), format="csr")
self._GRAD = sdiag(1/L)*G
return self._GRAD
return locals()
_GRAD = None
GRAD = property(**GRAD())
def CURL():
doc = "Construct the 3D curl operator."
def fget(self):
if(self._CURL is None):
# The number of cell centers in each direction
n1 = np.size(self.hx)
n2 = np.size(self.hy)
n3 = np.size(self.hz)
# Compute lengths of cell edges
L = self.edge
# Compute areas of cell faces
S = self.area
# Compute divergence operator on faces
d1 = ddx(n1)
d2 = ddx(n2)
d3 = ddx(n3)
D32 = kron3(d3, speye(n2), speye(n1+1))
D23 = kron3(speye(n3), d2, speye(n1+1))
D31 = kron3(d3, speye(n2+1), speye(n1))
D13 = kron3(speye(n3), speye(n2+1), d1)
D21 = kron3(speye(n3+1), d2, speye(n1))
D12 = kron3(speye(n3+1), speye(n2), d1)
O1 = spzeros(np.shape(D32)[0], np.shape(D31)[1])
O2 = spzeros(np.shape(D31)[0], np.shape(D32)[1])
O3 = spzeros(np.shape(D21)[0], np.shape(D13)[1])
C = sparse.vstack((sparse.hstack((O1, -D32, D23)),
sparse.hstack((D31, O2, -D13)),
sparse.hstack((-D21, D12, O3))), format="csr")
self._CURL = sdiag(1/S)*(C*sdiag(L))
return self._CURL
return locals()
_CURL = None
CURL = property(**CURL())
def AVE_F():
doc = "Construct the 3D averaging operator on cell faces."
def fget(self):
if(self._AVE_F is None):
# The number of cell centers in each direction
n1 = np.size(self.hx)
n2 = np.size(self.hy)
n3 = np.size(self.hz)
av1 = av(n1)
av2 = av(n2)
av3 = av(n3)
self._AVE_F = sparse.hstack(kron3(speye(n3), speye(n2), av1),
kron3(speye(n3), av2, speye(n3)),
kron3(av3, speye(n2), speye(n3)), format="csr")
return self._AVE_F
return locals()
_AVE_F = None
AVE_F = property(**AVE_F())
def AVE_E():
doc = "Construct the 3D averaging operator on cell edges."
def fget(self):
if(self._AVE_E is None):
# The number of cell centers in each direction
n1 = np.size(self.hx)
n2 = np.size(self.hy)
n3 = np.size(self.hz)
av1 = av(n1)
av2 = av(n2)
av3 = av(n3)
self._AVE_E = sparse.hstack(kron3(av3, av2, speye(n1)),
kron3(av3, speye(n2), av1),
kron3(speye(n3), av2, av1), format="csr")
return self._AVE_E
return locals()
_AVE_E = None
AVE_E = property(**AVE_E())