Files
simpeg/simpegEM/TDEM/SurveyTDEM.py
T

264 lines
8.3 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'],
'ey':['e', 'Ey'],
'ez':['e', 'Ez'],
'bx':['b', 'Fx'],
'by':['b', 'Fy'],
'bz':['b', 'Fz'],
}
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]
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, 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)
if rx.projField not in f: # first time we are projecting
Ptv = Ptv.reshape((-1, 1, self.prob.timeMesh.nN), order='F')
f[tx, rx.projField, :] = Ptv
else:
Ptv = Ptv.reshape((-1, self.prob.timeMesh.nN), order='F')
addedPtv = f[tx, rx.projField, :] + Ptv
addedPtv = addedPtv.reshape((-1, 1, self.prob.timeMesh.nN), order='F')
f[tx, rx.projField, :] = addedPtv
return f
# class SurveyTDEM1D(BaseSurvey):
# """
# docstring for SurveyTDEM1D
# """
# txLoc = None #: txLoc
# txType = None #: txType
# rxLoc = None #: rxLoc
# rxType = None #: rxType
# timeCh = None #: timeCh
# nTx = 1 #: Number of transmitters
# @property
# def nTimeCh(self):
# """Number of time channels"""
# return self.timeCh.size
# def __init__(self, **kwargs):
# BaseSurvey.__init__(self, **kwargs)
# Utils.setKwargs(self, **kwargs)
# def projectFields(self, u):
# #TODO: this is hardcoded to 1Tx
# return self.Qrx.dot(u.b[:,:,0].T).T
# def projectFieldsAdjoint(self, d):
# # TODO: make the following self.nTimeCh
# d = d.reshape((self.prob.nT, self.nTx), order='F')
# #TODO: *Qtime.T need to multiply by a time projection. (outside for loop??)
# ii = 0
# F = FieldsTDEM(self.prob.mesh, self.nTx, self.prob.nT, 'b')
# for ii in range(self.prob.nT):
# b = self.Qrx.T*d[ii,:]
# F.set_b(b, ii)
# F.set_e(np.zeros((self.prob.mesh.nE,self.nTx)), ii)
# return F
# ####################################################
# # Interpolation Matrices
# ####################################################
# @property
# def Qrx(self):
# if self._Qrx is None:
# if self.rxType == 'bz':
# locType = 'Fz'
# self._Qrx = self.prob.mesh.getInterpolationMat(self.rxLoc, locType=locType)
# return self._Qrx
# _Qrx = None
# class FieldsTDEM_OLD(object):
# """docstring for FieldsTDEM"""
# phi0 = None #: Initial electric potential
# A0 = None #: Initial magnetic vector potential
# e0 = None #: Initial electric field
# b0 = None #: Initial magnetic flux density
# j0 = None #: Initial current density
# h0 = None #: Initial magnetic field
# phi = None #: Electric potential
# A = None #: Magnetic vector potential
# e = None #: Electric field
# b = None #: Magnetic flux density
# j = None #: Current density
# h = None #: Magnetic field
# def __init__(self, mesh, nTx, nT, store='b'):
# self.nT = nT #: Number of times
# self.nTx = nTx #: Number of transmitters
# self.mesh = mesh
# def update(self, newFields, tInd):
# self.set_b(newFields['b'], tInd)
# self.set_e(newFields['e'], tInd)
# def fieldVec(self):
# u = np.ndarray((0, self.nTx))
# for i in range(self.nT):
# u = np.r_[u, self.get_b(i), self.get_e(i)]
# if self.nTx == 1:
# u = u.flatten()
# return u
# ####################################################
# # Get Methods
# ####################################################
# def get_b(self, ind):
# if ind == -1:
# return self.b0
# else:
# return self.b[ind,:,:]
# def get_e(self, ind):
# if ind == -1:
# return self.e0
# else:
# return self.e[ind,:,:]
# ####################################################
# # Set Methods
# ####################################################
# def set_b(self, b, ind):
# if self.b is None:
# self.b = np.zeros((self.nT, np.sum(self.mesh.nF), self.nTx))
# self.b[:] = np.nan
# if len(b.shape) == 1:
# b = b[:, np.newaxis]
# self.b[ind,:,:] = b
# def set_e(self, e, ind):
# if self.e is None:
# self.e = np.zeros((self.nT, np.sum(self.mesh.nE), self.nTx))
# self.e[:] = np.nan
# if len(e.shape) == 1:
# e = e[:, np.newaxis]
# self.e[ind,:,:] = e
# def __contains__(self, key):
# return key in self.children