mirror of
https://github.com/wassname/simpeg.git
synced 2026-07-20 12:40:44 +08:00
Working Jvec for the MT problem - not currently working. Dimensional mismatch with matrices.
This commit is contained in:
@@ -23,3 +23,100 @@ class BaseMTProblem(BaseFDEMProblem):
|
||||
# Use the forward and devs from BaseFDEMProblem
|
||||
# Might need to add more stuff here.
|
||||
|
||||
def Jvec(self, m, v, f=None):
|
||||
if f is None:
|
||||
f = self.fields(m)
|
||||
|
||||
self.curModel = m
|
||||
|
||||
Jv = self.dataPair(self.survey)
|
||||
|
||||
for freq in self.survey.freqs:
|
||||
dA_du = self.getA(freq) #
|
||||
dA_duI = self.Solver(dA_du, **self.solverOpts)
|
||||
|
||||
for src in self.survey.getSrcByFreq(freq):
|
||||
ftype = self._fieldType + 'Solution'
|
||||
u_src = f[src, ftype]
|
||||
dA_dm = self.getADeriv_m(freq, u_src, v)
|
||||
dRHS_dm = self.getRHSDeriv_m(freq, v)
|
||||
if dRHS_dm is None:
|
||||
du_dm = dA_duI * ( - dA_dm )
|
||||
else:
|
||||
du_dm = dA_duI * ( - dA_dm + dRHS_dm )
|
||||
for rx in src.rxList:
|
||||
# df_duFun = u.deriv_u(rx.fieldsUsed, m)
|
||||
if 'e' in self._fieldType:
|
||||
projField = 'b'
|
||||
elif 'b' in self._fieldType:
|
||||
projField = 'e'
|
||||
df_duFun = getattr(f, '_%sDeriv_u'%projField, None)
|
||||
df_du = df_duFun(src, du_dm, adjoint=False)
|
||||
if df_du is not None:
|
||||
du_dm = df_du
|
||||
|
||||
df_dmFun = getattr(f, '_%sDeriv_m'%projField, None)
|
||||
df_dm = df_dmFun(src, v, adjoint=False)
|
||||
if df_dm is not None:
|
||||
du_dm += df_dm
|
||||
|
||||
P = lambda v: rx.projectFieldsDeriv(src, self.mesh, f, v) # wrt u, also have wrt m
|
||||
|
||||
|
||||
Jv[src, rx] = P(du_dm)
|
||||
|
||||
return Utils.mkvc(Jv)
|
||||
|
||||
def Jtvec(self, m, v, f=None):
|
||||
if f is None:
|
||||
f = self.fields(m)
|
||||
|
||||
self.curModel = m
|
||||
|
||||
# Ensure v is a data object.
|
||||
if not isinstance(v, self.dataPair):
|
||||
v = self.dataPair(self.survey, v)
|
||||
|
||||
Jtv = np.zeros(m.size)
|
||||
|
||||
for freq in self.survey.freqs:
|
||||
AT = self.getA(freq).T
|
||||
ATinv = self.Solver(AT, **self.solverOpts)
|
||||
|
||||
for src in self.survey.getSrcByFreq(freq):
|
||||
ftype = self._fieldType + 'Solution'
|
||||
u_src = f[src, ftype]
|
||||
|
||||
for rx in src.rxList:
|
||||
PTv = rx.projectFieldsDeriv(src, self.mesh, f, v[src, rx], adjoint=True) # wrt u, need possibility wrt m
|
||||
|
||||
df_duTFun = getattr(f, '_%sDeriv_u'%rx.projField, None)
|
||||
df_duT = df_duTFun(src, PTv, adjoint=True)
|
||||
if df_duT is not None:
|
||||
dA_duIT = ATinv * df_duT
|
||||
else:
|
||||
dA_duIT = ATinv * PTv
|
||||
|
||||
dA_dmT = self.getADeriv_m(freq, u_src, dA_duIT, adjoint=True)
|
||||
|
||||
dRHS_dmT = self.getRHSDeriv_m(src, dA_duIT, adjoint=True)
|
||||
|
||||
if dRHS_dmT is None:
|
||||
du_dmT = - dA_dmT
|
||||
else:
|
||||
du_dmT = -dA_dmT + dRHS_dmT
|
||||
|
||||
df_dmFun = getattr(f, '_%sDeriv_m'%rx.projField, None)
|
||||
dfT_dm = df_dmFun(src, PTv, adjoint=True)
|
||||
if dfT_dm is not None:
|
||||
du_dmT += dfT_dm
|
||||
|
||||
real_or_imag = rx.projComp
|
||||
if real_or_imag == 'real':
|
||||
Jtv += du_dmT.real
|
||||
elif real_or_imag == 'imag':
|
||||
Jtv += - du_dmT.real
|
||||
else:
|
||||
raise Exception('Must be real or imag')
|
||||
|
||||
return Jtv
|
||||
+82
-9
@@ -9,15 +9,88 @@ from simpegEM.Utils.EMUtils import omega
|
||||
##############
|
||||
class FieldsMT(Problem.Fields):
|
||||
"""Field Storage for a MT survey."""
|
||||
knownFields = {'b_px': 'F','b_py': 'F', 'e_px': 'E','e_py': 'E','b_1d':'E','e_1d':'F'}
|
||||
knownFields = {}
|
||||
dtype = complex
|
||||
|
||||
|
||||
def _b_1dDeriv_u(self,src,v,adjoint=False):
|
||||
"""
|
||||
The derivative of b_1d wrt u
|
||||
"""
|
||||
nG = self.mesh.nodalGrad
|
||||
if adjoint:
|
||||
return - 1./( 1j*omega(src.freq) ) * ( nG.T * v)
|
||||
return - 1./( 1j*omega(src.freq) ) * ( nG * v)
|
||||
class FieldsMT_1D(FieldsMT):
|
||||
"""
|
||||
Fields storage for the 1D MT solution.
|
||||
"""
|
||||
knownFields = {'e_1dSolution':'F'}
|
||||
aliasFields = {
|
||||
'e_1d' : ['e_1dSolution','F','_e'],
|
||||
'e_1dPrimary' : ['e_1dSolution','F','_ePrimary'],
|
||||
'e_1dSecondary' : ['e_1dSolution','F','_eSecondary'],
|
||||
'b_1d' : ['e_1dSolution','E','_b'],
|
||||
'b_1dPrimary' : ['e_1dSolution','E','_bPrimary'],
|
||||
'b_1dSecondary' : ['e_1dSolution','E','_bSecondary']
|
||||
}
|
||||
|
||||
def __init__(self,mesh,survey,**kwargs):
|
||||
FieldsMT.__init__(self,mesh,survey,**kwargs)
|
||||
|
||||
def _ePrimary(self, eSolution, srcList):
|
||||
ePrimary = np.zeros_like(eSolution)
|
||||
for i, src in enumerate(srcList):
|
||||
ep = src.ePrimary(self.survey.prob)
|
||||
if ep is not None:
|
||||
ePrimary[:,i] = ep[:,-1]
|
||||
return ePrimary
|
||||
|
||||
def _eSecondary(self, eSolution, srcList):
|
||||
return eSolution
|
||||
|
||||
def _e(self, eSolution, srcList):
|
||||
return self._ePrimary(eSolution,srcList) + self._eSecondary(eSolution,srcList)
|
||||
|
||||
def _eDeriv_u(self, src, v, adjoint = False):
|
||||
return None
|
||||
|
||||
def _eDeriv_m(self, src, v, adjoint = False):
|
||||
# assuming primary does not depend on the model
|
||||
return None
|
||||
|
||||
def _bPrimary(self, eSolution, srcList):
|
||||
bPrimary = np.zeros([self.survey.mesh.nE,eSolution.shape[1]], dtype = complex)
|
||||
for i, src in enumerate(srcList):
|
||||
bp = src.bPrimary(self.survey.prob)
|
||||
if bp is not None:
|
||||
bPrimary[:,i] += bp[:,-1]
|
||||
return bPrimary
|
||||
|
||||
def _bSecondary(self, eSolution, srcList):
|
||||
C = self.mesh.nodalGrad
|
||||
b = (C * eSolution)
|
||||
for i, src in enumerate(srcList):
|
||||
b[:,i] *= - 1./(1j*omega(src.freq))
|
||||
# There is no magnetic source in the MT problem
|
||||
# S_m, _ = src.eval(self.survey.prob)
|
||||
# if S_m is not None:
|
||||
# b[:,i] += 1./(1j*omega(src.freq)) * S_m
|
||||
return b
|
||||
|
||||
def _b(self, eSolution, srcList):
|
||||
return self._bPrimary(eSolution, srcList) + self._bSecondary(eSolution, srcList)
|
||||
|
||||
def _bSecondaryDeriv_u(self, src, v, adjoint = False):
|
||||
C = self.mesh.nodalGrad
|
||||
if adjoint:
|
||||
return - 1./(1j*omega(src.freq)) * (C.T * v)
|
||||
return - 1./(1j*omega(src.freq)) * (C * v)
|
||||
|
||||
def _bSecondaryDeriv_m(self, src, v, adjoint = False):
|
||||
S_mDeriv, _ = src.evalDeriv(self.survey.prob, adjoint)
|
||||
S_mDeriv = S_mDeriv(v)
|
||||
if S_mDeriv is not None:
|
||||
return 1./(1j * omega(src.freq)) * S_mDeriv
|
||||
return None
|
||||
|
||||
def _bDeriv_u(self, src, v, adjoint=False):
|
||||
# Primary does not depend on u
|
||||
return self._bSecondaryDeriv_u(src, v, adjoint)
|
||||
|
||||
def _bDeriv_m(self, src, v, adjoint=False):
|
||||
# Assuming the primary does not depend on the model
|
||||
return self._bSecondaryDeriv_m(src, v, adjoint)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ from SimPEG import mkvc
|
||||
from scipy.constants import mu_0
|
||||
from simpegMT.BaseMT import BaseMTProblem
|
||||
from simpegMT.SurveyMT import SurveyMT
|
||||
from simpegMT.FieldsMT import FieldsMT
|
||||
from simpegMT.FieldsMT import FieldsMT_1D
|
||||
from simpegMT.DataMT import DataMT
|
||||
from simpegMT.Utils.MT1Danalytic import getEHfields
|
||||
import numpy as np
|
||||
@@ -18,19 +18,19 @@ class eForm_psField(BaseMTProblem):
|
||||
|
||||
"""
|
||||
# From FDEMproblem: Used to project the fields. Currently not used for MTproblem.
|
||||
_fieldType = 'e'
|
||||
_fieldType = 'e_1d'
|
||||
_eqLocs = 'EF'
|
||||
|
||||
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseMTProblem.__init__(self, mesh, **kwargs)
|
||||
self.fieldsPair = FieldsMT_1D
|
||||
|
||||
def getA(self, freq,):
|
||||
def getA(self, freq):
|
||||
"""
|
||||
Function to get the A matrix.
|
||||
|
||||
:param float freq: Frequency
|
||||
:param logic full: Return full A or the inner part
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: A
|
||||
"""
|
||||
@@ -54,11 +54,13 @@ class eForm_psField(BaseMTProblem):
|
||||
"""
|
||||
|
||||
dsig_dm = self.curModel.sigmaDeriv
|
||||
MeMui = self.mesh.getEdgeInnerProduct(1.0/mu_0)
|
||||
# Need to make the dMf_dsig symmetirc (nN,nN), don't know how to do this
|
||||
dMf_dsig = self.mesh.getFaceInnerProductDeriv(self.curModel.sigma)(u) * self.curModel.sigmaDeriv
|
||||
if adjoint:
|
||||
return 1j * omega(freq) * ( dsig_dm.T * ( dMf_dsig.T * v ) )
|
||||
|
||||
return 1j * omega(freq) * ( dMf_dsig * ( dsig_dm * v ) )
|
||||
return 1j * omega(freq) * ( dMf_dsig.T * v )
|
||||
# Note: output has to be nN/nF, not nC/nE.
|
||||
return 1j * omega(freq) * ( (dMf_dsig * dMf_dsig.T)**(1/2) * v)
|
||||
|
||||
def getRHS(self, freq):
|
||||
"""
|
||||
@@ -73,7 +75,7 @@ class eForm_psField(BaseMTProblem):
|
||||
S_e = Src.S_e(self)
|
||||
return -1j * omega(freq) * S_e
|
||||
|
||||
def getRHSderiv_m(self, freq, u, v, adjoint=False):
|
||||
def getRHSDeriv_m(self, freq, v, adjoint=False):
|
||||
"""
|
||||
The derivative of the RHS wrt sigma
|
||||
"""
|
||||
@@ -91,7 +93,7 @@ class eForm_psField(BaseMTProblem):
|
||||
# Set the current model
|
||||
self.curModel = m
|
||||
|
||||
F = FieldsMT(self.mesh, self.survey)
|
||||
F = FieldsMT_1D(self.mesh, self.survey)
|
||||
for freq in self.survey.freqs:
|
||||
if self.verbose:
|
||||
startTime = time.time()
|
||||
@@ -110,12 +112,12 @@ class eForm_psField(BaseMTProblem):
|
||||
|
||||
# Store the fields
|
||||
# NOTE: only store
|
||||
F[Src, 'e_1d'] = e[:,1] # Only storing the yx polarization as 1d
|
||||
F[Src, 'e_1dSolution'] = e[:,1] # Only storing the yx polarization as 1d
|
||||
# F[Src, 'e_py'] = 0*e[:,0]
|
||||
# Note curl e = -iwb so b = -curl e /iw
|
||||
b = -( self.mesh.nodalGrad * e )/( 1j*omega(freq) )
|
||||
# b = -( self.mesh.nodalGrad * e )/( 1j*omega(freq) )
|
||||
# F[Src, 'b_px'] = 0*b[:,0]
|
||||
F[Src, 'b_1d'] = b[:,1]
|
||||
# F[Src, 'b_1d'] = b[:,1]
|
||||
if self.verbose:
|
||||
print 'Ran for {:f} seconds'.format(time.time()-startTime)
|
||||
sys.stdout.flush()
|
||||
|
||||
+26
-18
@@ -83,7 +83,7 @@ class RxMT(Survey.BaseRx):
|
||||
"""Component projection (real/imag)"""
|
||||
return self.knownRxTypes[self.rxType][1]
|
||||
|
||||
def projectFields(self, src, mesh, u):
|
||||
def projectFields(self, src, mesh, f):
|
||||
'''
|
||||
Project the fields and return the
|
||||
'''
|
||||
@@ -91,8 +91,8 @@ class RxMT(Survey.BaseRx):
|
||||
if self.projType is 'Z1D':
|
||||
Pex = mesh.getInterpolationMat(self.locs,'Fx')
|
||||
Pbx = mesh.getInterpolationMat(self.locs,'Ex')
|
||||
ex = Pex*mkvc(u[src,'e_1d'],2)
|
||||
bx = Pbx*mkvc(u[src,'b_1d'],2)/mu_0
|
||||
ex = Pex*mkvc(f[src,'e_1d'],2)
|
||||
bx = Pbx*mkvc(f[src,'b_1d'],2)/mu_0
|
||||
f_part_complex = ex/bx
|
||||
# elif self.projType is 'Z2D':
|
||||
elif self.projType is 'Z3D':
|
||||
@@ -103,14 +103,14 @@ class RxMT(Survey.BaseRx):
|
||||
Pby = mesh.getInterpolationMat(self.locs,'Fy')
|
||||
# Get the fields at location
|
||||
# px: x-polaration and py: y-polaration.
|
||||
ex_px = Pex*u[src,'e_px']
|
||||
ey_px = Pey*u[src,'e_px']
|
||||
ex_py = Pex*u[src,'e_py']
|
||||
ey_py = Pey*u[src,'e_py']
|
||||
hx_px = Pbx*u[src,'b_px']/mu_0
|
||||
hy_px = Pby*u[src,'b_px']/mu_0
|
||||
hx_py = Pbx*u[src,'b_py']/mu_0
|
||||
hy_py = Pby*u[src,'b_py']/mu_0
|
||||
ex_px = Pex*f[src,'e_px']
|
||||
ey_px = Pey*f[src,'e_px']
|
||||
ex_py = Pex*f[src,'e_py']
|
||||
ey_py = Pey*f[src,'e_py']
|
||||
hx_px = Pbx*f[src,'b_px']/mu_0
|
||||
hy_px = Pby*f[src,'b_px']/mu_0
|
||||
hx_py = Pbx*f[src,'b_py']/mu_0
|
||||
hy_py = Pby*f[src,'b_py']/mu_0
|
||||
# Make the complex data
|
||||
if 'zxx' in self.rxType:
|
||||
f_part_complex = (ex_px*hy_py - ex_py*hy_px)/(hx_px*hy_py - hx_py*hy_px)
|
||||
@@ -140,7 +140,7 @@ class RxMT(Survey.BaseRx):
|
||||
Pbx = mesh.getInterpolationMat(self.locs,'Ex')
|
||||
# ex = Pex*mkvc(f[src,'e_1d'],2)
|
||||
# bx = Pbx*mkvc(f[src,'b_1d'],2)/mu_0
|
||||
deriv_complex = Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0))*(Pex*v) - Utils.sdiag(Pex*mkvc(f[src,'e_1d'],2))*(Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)).T*Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)))*(Pbx*f._b_1dDeriv_u(src,v)/mu_0)
|
||||
deriv_complex = Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0))*(Pex*v) - Utils.sdiag(Pex*mkvc(f[src,'e_1d'],2))*(Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)).T*Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)))*(Pbx*f._bDeriv_u(src,v)/mu_0)
|
||||
# elif self.projType is 'Z2D
|
||||
elif self.projType is 'Z3D':
|
||||
pass
|
||||
@@ -156,7 +156,8 @@ class RxMT(Survey.BaseRx):
|
||||
###############
|
||||
### Sources ###
|
||||
###############
|
||||
class srcMT(Survey.BaseSrc):
|
||||
# Note: Should like inheret from FDEM
|
||||
class srcMT(SrcFDEM): # Survey.BaseSrc):
|
||||
'''
|
||||
Sources for the MT problem.
|
||||
Use the SimPEG BaseSrc, since the source fields share properties with the transmitters.
|
||||
@@ -205,7 +206,11 @@ class srcMT_polxy_1Dprimary(srcMT):
|
||||
def bPrimary(self,problem):
|
||||
# Project ePrimary to bPrimary
|
||||
# Satisfies the primary(background) field conditions
|
||||
bBG_bp = (- problem.mesh.edgeCurl * self.ePrimary )/( 1j*omega(freq) )
|
||||
if problem.mesh.dim == 1:
|
||||
C = problem.mesh.nodalGrad
|
||||
elif problem.mesh.dim == 3:
|
||||
C = problem.mesh.edgeCurl
|
||||
bBG_bp = (- C * self.ePrimary(problem) )/( 1j*omega(self.freq) )
|
||||
return bBG_bp
|
||||
|
||||
def S_e(self,problem):
|
||||
@@ -231,15 +236,18 @@ class srcMT_polxy_1Dprimary(srcMT):
|
||||
def S_eDeriv(self, problem, v, adjoint = False):
|
||||
# Need to deal with
|
||||
if problem.mesh.dim == 1:
|
||||
pass
|
||||
# Need to use the faceInnerProduct
|
||||
MsigmaDeriv = problem.mesh.getFaceInnerProductDeriv(problem.curModel.sigma)(self.ePrimary(problem)[:,-1]) * problem.curModel.sigmaDeriv
|
||||
MsigmaDeriv = ( MsigmaDeriv * MsigmaDeriv.T)**2
|
||||
if problem.mesh.dim == 2:
|
||||
pass
|
||||
if problem.mesh.dim == 3:
|
||||
MesigmaDeriv = problem.MeSigmaDeriv(self.ePrimary(problem))
|
||||
MsigmaDeriv = problem.MeSigmaDeriv(self.ePrimary(problem))
|
||||
if adjoint:
|
||||
return MesigmaDeriv.T * v
|
||||
return MsigmaDeriv.T * v
|
||||
else:
|
||||
return MesigmaDeriv * v
|
||||
# Moved the v in front to make the multi work
|
||||
return MsigmaDeriv * v
|
||||
|
||||
|
||||
##############
|
||||
|
||||
Reference in New Issue
Block a user