Files
simpeg/simpegEM/TDEM/SurveyTDEM.py
T
2014-05-15 12:20:56 -07:00

157 lines
5.1 KiB
Python

from SimPEG import Utils, Survey, np
from SimPEG.Survey import BaseSurvey
from simpegEM.Utils import Sources
class RxTDEM(Survey.BaseTimeRx):
knownRxTypes = {
'ex':['e', 'Ex', 'N'],
'ey':['e', 'Ey', 'N'],
'ez':['e', 'Ez', 'N'],
'bx':['b', 'Fx', 'N'],
'by':['b', 'Fy', 'N'],
'bz':['b', 'Fz', 'N'],
'dbxdt':['b', 'Fx', 'CC'],
'dbydt':['b', 'Fy', 'CC'],
'dbzdt':['b', 'Fz', 'CC'],
}
def __init__(self, locs, times, rxType):
Survey.BaseTimeRx.__init__(self, locs, times, rxType)
@property
def projField(self):
"""Field Type projection (e.g. e b ...)"""
return self.knownRxTypes[self.rxType][0]
@property
def projGLoc(self):
"""Grid Location projection (e.g. Ex Fy ...)"""
return self.knownRxTypes[self.rxType][1]
@property
def projTLoc(self):
"""Time Location projection (e.g. CC N)"""
return self.knownRxTypes[self.rxType][2]
def getTimeP(self, timeMesh):
"""
Returns the time projection matrix.
.. note::
This is not stored in memory, but is created on demand.
"""
if self.rxType in ['dbxdt','dbydt','dbzdt']:
return timeMesh.getInterpolationMat(self.times, self.projTLoc)*timeMesh.faceDiv
else:
return timeMesh.getInterpolationMat(self.times, self.projTLoc)
def projectFields(self, tx, mesh, timeMesh, u):
P = self.getP(mesh, timeMesh)
u_part = Utils.mkvc(u[tx, self.projField, :])
return P*u_part
def projectFieldsDeriv(self, tx, mesh, timeMesh, u, v, adjoint=False):
P = self.getP(mesh, timeMesh)
if not adjoint:
return P * Utils.mkvc(v[tx, self.projField, :])
elif adjoint:
return P.T * v[tx, self]
class FieldsTDEM(Survey.TimeFields):
"""Fancy Field Storage for a TDEM survey."""
knownFields = {'b': 'F', 'e': 'E'}
def tovec(self):
nTx, nF, nE = self.survey.nTx, self.mesh.nF, self.mesh.nE
u = np.empty(0 if nTx == 1 else (0, nTx))
for i in range(self.survey.prob.nT):
if 'b' in self:
b = self[:,'b',i+1]
else:
b = np.zeros(nF if nTx == 1 else (nF, nTx))
if 'e' in self:
e = self[:,'e',i+1]
else:
e = np.zeros(nE if nTx == 1 else (nE, nTx))
u = np.concatenate((u, b, e))
return Utils.mkvc(u)
class TxTDEM(Survey.BaseTx):
rxPair = RxTDEM
knownTxTypes = ['VMD_MVP']
def getInitialFields(self, mesh):
F0 = getattr(self, '_getInitialFields_' + self.txType)(mesh)
return F0
def _getInitialFields_VMD_MVP(self, mesh):
"""Vertical magnetic dipole, magnetic vector potential"""
if mesh._meshType is 'CYL':
if mesh.isSymmetric:
MVP = Sources.MagneticDipoleVectorPotential(self.loc, mesh.gridEy, 'y')
else:
raise NotImplementedError('Non-symmetric cyl mesh not implemented yet!')
elif mesh._meshType is 'TENSOR':
MVPx = Sources.MagneticDipoleVectorPotential(self.loc, mesh.gridEx, 'x')
MVPy = Sources.MagneticDipoleVectorPotential(self.loc, mesh.gridEy, 'y')
MVPz = Sources.MagneticDipoleVectorPotential(self.loc, mesh.gridEz, 'z')
MVP = np.concatenate((MVPx, MVPy, MVPz))
else:
raise Exception('Unknown mesh for VMD')
return {"b": mesh.edgeCurl*MVP}
def getJs(self, mesh, time):
return None
class SurveyTDEM(Survey.BaseSurvey):
"""
docstring for SurveyTDEM
"""
txPair = TxTDEM
def __init__(self, txList, **kwargs):
# Sort these by frequency
self.txList = txList
Survey.BaseSurvey.__init__(self, **kwargs)
def projectFields(self, u):
data = Survey.Data(self)
for tx in self.txList:
for rx in tx.rxList:
data[tx, rx] = rx.projectFields(tx, self.mesh, self.prob.timeMesh, u)
return data
def projectFieldsDeriv(self, u, v=None, adjoint=False):
assert v is not None, 'v to multiply must be provided.'
if not adjoint:
data = Survey.Data(self)
for tx in self.txList:
for rx in tx.rxList:
data[tx, rx] = rx.projectFieldsDeriv(tx, self.mesh, self.prob.timeMesh, u, v)
return data
else:
f = FieldsTDEM(self.mesh, self)
for tx in self.txList:
for rx in tx.rxList:
Ptv = rx.projectFieldsDeriv(tx, self.mesh, self.prob.timeMesh, u, v, adjoint=True)
Ptv = Ptv.reshape((-1, self.prob.timeMesh.nN), order='F')
if rx.projField not in f: # first time we are projecting
f[tx, rx.projField, :] = Ptv
else: # there are already fields, so let's add to them!
f[tx, rx.projField, :] += Ptv
return f