mirror of
https://github.com/wassname/simpeg.git
synced 2026-07-09 03:45:57 +08:00
264 lines
8.3 KiB
Python
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
|