resolved conflicts

This commit is contained in:
seogi
2014-02-28 16:44:12 -08:00
parent 5816f75728
commit 18546d038b
6 changed files with 695 additions and 217 deletions
+22 -3
View File
@@ -111,13 +111,13 @@ In applied geophysics, which means in practice, it is common to refer to measure
.. math ::
\triangle\vec{B} = |\vec{B}_0-\vec{B}_s|-|\vec{B}_0| \approx |\vec{B}_s|cos \theta
\triangle\vec{B} = |\hat{B}_o-\vec{B}_s|-|\hat{B}_o| \approx |\vec{B}_s|cos \theta
where \\(\\theta\\) is the angle between total and anomalous fields. Equivalently, we can use the vector dot product to show that the anomalous field is aproximately equal to the projection of that field onto the direction of the inducing field. Using this approach we would write
where \\(\\theta\\) is the angle between total and anomalous fields, \\(\\hat{B}_o\\) is the unit vector for \\(\\vec{B}_o\\). Equivalently, we can use the vector dot product to show that the anomalous field is aproximately equal to the projection of that field onto the direction of the inducing field. Using this approach we would write
.. math ::
\triangle\vec{B} = |\vec{B}_s|cos \theta = |\vec{B}_o||\vec{B}_s|cos \theta = \vec{B}_o \cdot \vec{B}_s
\triangle\vec{B} = |\vec{B}_s|cos \theta = |\hat{B}_o||\vec{B}_s|cos \theta = \hat{B}_o \cdot \vec{B}_s
This is important because, in practice we usually use a total field magnetometer (like a proton precession or optically pumped sensor), which can measure only that part of the anomalous field which is in the direction of the earth's main field.
@@ -128,6 +128,19 @@ Sphere in a whole space
Forward problem
===============
Differential equation approach
------------------------------
.. math ::
\mathbf{A}\mathbf{u} = \mathbf{rhs}
\mathbf{A} = \Div(\MfMui)^{-1}\Div^{T}
\mathbf{rhs} = \Div(\MfMui)^{-1}\mathbf{M}^f_{\mu_0^{-1}}\mathbf{B}_0 - \Div\mathbf{B}_0+\diag(v)\mathbf{D} \mathbf{P}_{out}^T \mathbf{B}_{sBC}
\mathbf{B}_s = (\MfMui)^{-1}\mathbf{M}^f_{\mu_0^{-1}}\mathbf{B}_0-\mathbf{B}_0 -(\MfMui)^{-1}\Div^T \mathbf{u}
Inverse problem
@@ -143,6 +156,12 @@ Mag Differential eq. approach
:undoc-members:
:inherited-members:
.. autoclass:: simpegPF.BaseMag.BaseMagData
:show-inheritance:
:members:
:undoc-members:
:inherited-members:
Mag Integral eq. approach
*************************
+47 -16
View File
@@ -11,10 +11,14 @@ class BaseMagData(Data.BaseData):
def __init__(self, **kwargs):
Data.BaseData.__init__(self, **kwargs)
#TODO: change to inc, dec, intensity
def setBackgroundField(self, x=1., y=0., z=0.):
# Primary field in x-direction (background)
self.B0 = np.r_[x,y,z]
def setBackgroundField(self, Inc, Dec, Btot):
Bx = Btot*np.cos(Inc/180.*np.pi)*np.sin(Dec/180.*np.pi)
By = Btot*np.cos(Inc/180.*np.pi)*np.cos(Dec/180.*np.pi)
Bz = -Btot*np.sin(Inc/180.*np.pi)
self.B0 = np.r_[Bx,By,Bz]
@property
def Qfx(self):
@@ -34,36 +38,63 @@ class BaseMagData(Data.BaseData):
self._Qfz = self.prob.mesh.getInterpolationMat(self.rxLoc,'Fz')
return self._Qfz
def projectFields(self, B):
def projectFields(self, u):
"""
This function projects the fields onto the data space.
Esepcially, here for we use total magnetic intensity (TMI) data,
which is common in practice.
First we project our B on to data location
.. math::
d_\\text{pred} = \mathbf{P} u(m)
\mathbf{B}_{rec} = \mathbf{P} \mathbf{B}
then we take the dot product between B and b_0
.. math ::
\\text{TMI} = \\vec{B}_s \cdot \hat{B}_0
"""
#TODO: There can be some different tyes of data like |B| or B
# bfx = self.Qfx*B
# bfy = self.Qfy*B
bfz = self.Qfz*B
return bfz
bfx = self.Qfx*u['B']
bfy = self.Qfy*u['B']
bfz = self.Qfz*u['B']
# return np.sqrt(bfx**2 + bfy**2 + bfz**2)
# Generate unit vector
B0 = self.prob.data.B0
Bot = np.sqrt(B0[0]**2+B0[1]**2+B0[2]**2)
box = B0[0]/Bot
boy = B0[1]/Bot
boz = B0[2]/Bot
# return bfx*box + bfx*boy + bfx*boz
return bfx*box + bfy*boy + bfz*boz
# return np.sqrt(bfx**2 + bfy**2 + bfz**2)
@Utils.count
def projectFieldsDeriv(self, B):
"""
This function projects the fields onto the data space.
.. math::
\\frac{\partial d_\\text{pred}}{\partial u} = \mathbf{P}
\\frac{\partial d_\\text{pred}}{\partial \mathbf{B}} = \mathbf{P}
Esepcially, this function is for TMI data type
"""
return self.Qfz
# Generate unit vector
B0 = self.prob.data.B0
Bot = np.sqrt(B0[0]**2+B0[1]**2+B0[2]**2)
box = B0[0]/Bot
boy = B0[1]/Bot
boz = B0[2]/Bot
return self.Qfx*box+self.Qfy*boy+self.Qfz*boz
def projectFieldsAsVector(self, B):
+197 -94
View File
@@ -41,6 +41,7 @@ class MagneticsDiffSecondary(Problem.BaseProblem):
self._MfMu0 = self.mesh.getFaceMass(1/mu_0)
# self._MfMu0 = self.mesh.getFaceInnerProduct(1/mu_0)
@Utils.requires('data')
def getB0(self):
b0 = self.data.B0
B0 = np.r_[b0[0]*np.ones(self.mesh.nFx),
@@ -49,17 +50,21 @@ class MagneticsDiffSecondary(Problem.BaseProblem):
return B0
def getRHS(self, m):
"""
.. math ::
\mathbf{rhs} = \Div(\MfMui)^{-1}\mathbf{M}^f_{\mu_0^{-1}}\mathbf{B}_0 - \Div\mathbf{B}_0+\diag(v)\mathbf{D} \mathbf{P}_{out}^T \mathbf{B}_{sBC}
"""
B0 = self.getB0()
Dface = self.mesh.faceDiv
Mc = Utils.sdiag(self.mesh.vol)
chi = self.model.transform(m, asMu=False)
Bbc, const = CongruousMagBC(self.mesh, self.data.B0, chi)
self.Bbc_const = const
Bbc, Bbc_const = CongruousMagBC(self.mesh, self.data.B0, chi)
self.Bbc = Bbc
#TODO: put congrous BC back in
# return self._Div*self.MfMuI*self.MfMu0*B0 - self._Div*B0 #+ Mc*Dface*self._Pout.T*Bbc
self.Bbc_const = Bbc_const
return self._Div*self.MfMuI*self.MfMu0*B0 - self._Div*B0 + Mc*Dface*self._Pout.T*Bbc
def getA(self, m):
@@ -68,41 +73,39 @@ class MagneticsDiffSecondary(Problem.BaseProblem):
The A matrix has the form:
.. math ::
\mathbf{A}\mathbf{u} = \mathbf{rhs}
\mathbf{A} = - \Div(\MfMui)^{-1}\Div^{T}
\mathbf{rhs} = - \Div(\MfMui)^{-1}\mathbf{M}^f_{\\frac{1}{\mu_0}}\mathbf{B}_0 + \Div\mathbf{B}_0-\diag(v)\mathbf{D} \mathbf{P}_{out}^T \mathbf{B}_{sBC}
.. math ::
\mathbf{A} = \Div(\MfMui)^{-1}\Div^{T}
"""
return self._Div*self.MfMuI*self._Div.T
def fields(self, m):
"""
Return magnetic potential (u) and flux (B)
u: defined on the cell center [nC x 1]
B: defined on the cell center [nF x 1]
After we compute u, then we update B.
.. math ::
\mathbf{B}_s = (\MfMui)^{-1}\mathbf{M}^f_{\mu_0^{-1}}\mathbf{B}_0-\mathbf{B}_0 -(\MfMui)^{-1}\Div^T \mathbf{u}
"""
self.makeMassMatrices(m)
A = self.getA(m)
rhs = self.getRHS(m)
m1 = sp.linalg.interface.aslinearoperator(Utils.sdiag(1/A.diagonal()))
u, info = sp.linalg.bicgstab(A, rhs, tol=1e-6, maxiter=1000, M=m1)
B0 = self.getB0()
B = self.MfMuI*self.MfMu0*B0-B0-self.MfMuI*self._Div.T*u
#TODO: Create a mag fields object class.
# F = self.getInitialFields()
# e.g. {'B': B, 'u': u}
return {'B': B, 'u': u}
# return self.forward(m, self.getRHS, self.calcFields, F=F)
@Utils.timeIt
def Jvec(self, m, v, u=None):
def Jvec(self, m, v, fields=None):
"""
Computing Jacobian multiplied by vector
@@ -122,7 +125,7 @@ class MagneticsDiffSecondary(Problem.BaseProblem):
\\frac{\delta \mathbf{u}}{\delta \mathbf{m}} = - [\\nabla_u \mathbf{C}(\mathbf{u})]^{-1}\\nabla_m \mathbf{C}(\mathbf{m})
With some linear algebra we can have
.. math ::
\\nabla_u \mathbf{C}(\mathbf{u}) = \mathbf{A}
@@ -138,66 +141,177 @@ class MagneticsDiffSecondary(Problem.BaseProblem):
\dMfMuI = \diag(\MfMui)^{-1}_{vec} \mathbf{Av}_{F2CC}^T\diag(\mathbf{v})\diag(\\frac{1}{\mu^2})
\\frac{\partial \mathbf{rhs}(\mathbf{m})}{\partial \mathbf{m}} = \\frac{\partial \mathbf{\mu}}{\partial \mathbf{m}} \left[
\Div \diag(\M^f_{\mu_{0}^{-1} \mathbf{B}_0}) \dMfMuI \\right] - \diag(\mathbf{v})\mathbf{D} \mathbf{P}_{out}^T\\frac{\partial B_{sBC}}{\partial \mathbf{m}}
\Div \diag(\M^f_{\mu_{0}^{-1}}\mathbf{B}_0) \dMfMuI \\right] - \diag(\mathbf{v})\mathbf{D} \mathbf{P}_{out}^T\\frac{\partial B_{sBC}}{\partial \mathbf{m}}
In the end,
.. math ::
\\frac{\delta \mathbf{u}}{\delta \mathbf{m}} =
- [ \mathbf{A} ]^{-1}\left[ \\frac{\partial \mathbf{A}}{\partial \mathbf{m}}(\mathbf{m})\mathbf{u}
- \\frac{\partial \mathbf{rhs}(\mathbf{m})}{\partial \mathbf{m}} \\right]
A little tricky point here is we are not interested in potential (u), but interested in magnetic flux (B).
Thus, we need sensitivity for B. Now we take derivative of B w.r.t m and have
.. math ::
\\frac{\delta \mathbf{B}} {\delta \mathbf{m}} = \\frac{\partial \mathbf{\mu} } {\partial \mathbf{m} }
\left[
\diag(\M^f_{\mu_{0}^{-1} } \mathbf{B}_0) \dMfMuI \\
- \diag (\Div^T\mathbf{u})\dMfMuI
\\right ]
- (\MfMui)^{-1}\Div^T\\frac{\delta\mathbf{u}}{\delta \mathbf{m}}
Finally we evaluate the above, but we should remember that
.. note ::
We only want to evalute
.. math ::
\mathbf{J}\mathbf{v} = \\frac{\delta \mathbf{P}\mathbf{B}} {\delta \mathbf{m}}\mathbf{v}
Since forming sensitivity matrix is very expensive in that this monster is "big" and "dense" matrix!!
"""
if u is None:
u = self.fields(m)
#TODO: B, u = u['B'], u['u']
B, u = u['B'], u['u']
if fields is None:
fields = self.fields(m)
B, u = fields['B'], fields['u']
mu = self.model.transform(m, asMu=True)
dmudm = self.model.transform(m, asMu=True)
P = self.data.projectFieldsDeriv(u)
A = self.getA(m)
dCdu = A
# (Av_m)^-1
# -(Av_m)^-2 * MfMu_dm * d/dm(1/mu(m))
# (Av_m)^-2 * MfMu_dm * diag(mu(m)^-2) * mT_dm
#TODO: only works for diagonal MfMui
# Some chain rule!
# harm_dm = Utils.sdiag(self.MfMui.diagonal()**(-2))
# MfMu_dm = self.mesh.getFaceMassDeriv()
# dmuI_dm = Utils.sdiag(mu**(-2))
# mT_dm = self.model.transformDeriv(m, asMu=True)
getFIPconst = 1./3
MfMuIvec = 1/self.MfMui.diagonal()*getFIPconst
dMfMuI = Utils.sdiag(MfMuIvec**2)*self.mesh.aveF2CC.T*Utils.sdiag(self.mesh.vol*1./mu**2)
dmudm = self.model.transformDeriv(m, asMu=True)
dmdmu = Utils.sdiag(1/(dmudm.diagonal()))
vol = self.mesh.vol
Div = self._Div
# lots-o-bracket for vector multiplication first!
# MfMu_dmXv = harm_dm * ( MfMu_dm * ( dmuI_dm * ( mT_dm * v ) ) )
#dCdm_A = D * ( Utils.sdiag( D.T * u ) * MfMu_dmXv )
dCdm_A = dmudm*Div * ( Utils.sdiag( Div.T * u * dMfMuI ) )
# rhs = D * MfMuI * MfMu0 * B0
Dface = self.mesh.faceDiv
P = self.data.projectFieldsDeriv(B) # Projection matrix
B0 = self.getB0()
#TODO: add congrous stuff
dCdm_RHS = dmudm* Div * Utils.sdiag( self.MfMu0*B0 ) * dMfMuI - Utils.sdiag(self.mesh.vol)*self.mesh.faceDiv*self.Pout.T*self.Bbc*self.Bbc_const
MfMuIvec = 1/self.MfMui.diagonal()
dMfMuI = Utils.sdiag(MfMuIvec**2)*self.mesh.aveF2CC.T*Utils.sdiag(vol*1./mu**2)
# A = self._Div*self.MfMuI*self._Div.T
# RHS = Div*MfMuI*MfMu0*B0 - Div*B0 + Mc*Dface*Pout.T*Bbc
# C(m,u) = A*m-rhs
# dudm = -(dCdu)^(-1)dCdm
# c(m,u) = A(m)u - rhs(m)
dCdm = dCdm_A - dCdm_RHS
dCdu = self.getA(m)
dCdm_A = Div * ( Utils.sdiag( Div.T * u )* dMfMuI *dmudm )
dCdm_RHS1 = Div * (Utils.sdiag( self.MfMu0*B0 ) * dMfMuI)
temp1 = (Dface*(self._Pout.T*self.Bbc_const*self.Bbc))
dCdm_RHS2v = (Utils.sdiag(vol)*temp1)*np.inner(vol, v)
dCdm_RHSv = dCdm_RHS1*(dmudm*v) + dCdm_RHS2v
dCdm_v = dCdm_A*v - dCdm_RHSv
solve = Solver(dCdu)
m1 = sp.linalg.interface.aslinearoperator(Utils.sdiag(1/dCdu.diagonal()))
sol, info = sp.linalg.bicgstab(dCdu, dCdm_v, tol=1e-8, maxiter=1000, M=m1)
#TODO: Multiply by the dP(u(m))/du
# We transformed u in our fields object.
# ( dBdu * + dBdm(u) )
Jv = - P * solve.solve(dCdm)
return Utils.mkvc(Jv)
if info > 0:
raise Exception ("Iterative solver did not work well")
# B = self.MfMuI*self.MfMu0*B0-B0-self.MfMuI*self._Div.T*u
# dBdm = d\mudm*dBd\mu
dudm = -sol
dBdmv = ( Utils.sdiag(self.MfMu0*B0)*(dMfMuI * (dmudm*v)) \
- Utils.sdiag(Div.T*u)*(dMfMuI* (dmudm*v)) \
- self.MfMuI*(Div.T* (dudm)) )
return Utils.mkvc(P*dBdmv)
@Utils.timeIt
def Jtvec(self, m, v, fields=None):
"""
Computing Jacobian^T multiplied by vector.
.. math ::
(\\frac{\delta \mathbf{P}\mathbf{B}} {\delta \mathbf{m}})^{T} = \left[ \mathbf{P}_{deriv}\\frac{\partial \mathbf{\mu} } {\partial \mathbf{m} }
\left[
\diag(\M^f_{\mu_{0}^{-1} } \mathbf{B}_0) \dMfMuI \\
- \diag (\Div^T\mathbf{u})\dMfMuI
\\right ]\\right]^{T}
- \left[\mathbf{P}_{deriv}(\MfMui)^{-1}\Div^T\\frac{\delta\mathbf{u}}{\delta \mathbf{m}} \\right]^{T}
where
.. math ::
\mathbf{P}_{derv} = \\frac{\partial \mathbf{P}}{\partial\mathbf{B}}
.. note ::
Here we only want to compute
.. math ::
\mathbf{J}^{T}\mathbf{v} = (\\frac{\delta \mathbf{P}\mathbf{B}} {\delta \mathbf{m}})^{T} \mathbf{v}
"""
if fields is None:
fields = self.fields(m)
B, u = fields['B'], fields['u']
mu = self.model.transform(m, asMu=True)
dmudm = self.model.transformDeriv(m, asMu=True)
dmdmu = Utils.sdiag(1/(dmudm.diagonal()))
vol = self.mesh.vol
Div = self._Div
Dface = self.mesh.faceDiv
P = self.data.projectFieldsDeriv(B) # Projection matrix
B0 = self.getB0()
MfMuIvec = 1/self.MfMui.diagonal()
dMfMuI = Utils.sdiag(MfMuIvec**2)*self.mesh.aveF2CC.T*Utils.sdiag(vol*1./mu**2)
# A = self._Div*self.MfMuI*self._Div.T
# RHS = Div*MfMuI*MfMu0*B0 - Div*B0 + Mc*Dface*Pout.T*Bbc
# C(m,u) = A*m-rhs
# dudm = -(dCdu)^(-1)dCdm
dCdu = self.getA(m)
s = Div * ( self.MfMuI.T * ( P.T*v ) )
m1 = sp.linalg.interface.aslinearoperator(Utils.sdiag(1/(dCdu.T).diagonal()))
sol, info = sp.linalg.bicgstab(dCdu.T, s, tol=1e-8, maxiter=1000, M=m1)
if info > 0:
raise Exception ("Iterative solver did not work well")
# dCdm_A = Div * ( Utils.sdiag( Div.T * u )* dMfMuI *dmudm )
dCdm_Atsol = ( dMfMuI.T*( Utils.sdiag( Div.T * u ) * (Div.T * dmudm)) ) * sol
# dCdm_RHS1 = Div * (Utils.sdiag( self.MfMu0*B0 ) * dMfMuI)
dCdm_RHS1tsol = (dMfMuI.T*( Utils.sdiag( self.MfMu0*B0 ) ) * Div.T * dmudm) * sol
# temp1 = (Dface*(self._Pout.T*self.Bbc_const*self.Bbc))
# dCdm_RHS2v = (Utils.sdiag(vol)*temp1)*np.inner(vol, v)
temp1sol = ( Dface.T*( Utils.sdiag(vol)*sol ) )
temp2 = self.Bbc_const*(self._Pout.T*self.Bbc).T
dCdm_RHS2tsol = vol*np.inner(temp2, temp1sol)
dCdm_RHStsol = dCdm_RHS1tsol - dCdm_RHS2tsol
# dCdm_RHSv = dCdm_RHS1*(dmudm*v) + dCdm_RHS2v
# dCdm_v = dCdm_A*v - dCdm_RHSv
Ctv = dCdm_Atsol - dCdm_RHStsol
# B = self.MfMuI*self.MfMu0*B0-B0-self.MfMuI*self._Div.T*u
# dBdm = d\mudm*dBd\mu
# dPBdm^T*v = Atemp^T*P^T*v - Btemp^T*P^T*v - Ctv
Atemp = Utils.sdiag(self.MfMu0*B0)*(dMfMuI * (dmudm))
Btemp = Utils.sdiag(Div.T*u)*(dMfMuI* (dmudm))
Jtv = Atemp.T*(P.T*v) - Btemp.T*(P.T*v) - Ctv
return Utils.mkvc(Jtv)
@@ -218,7 +332,12 @@ if __name__ == '__main__':
# mu = (1.+chi)*mu_0
data = BaseMag.BaseMagData()
data.setBackgroundField(x=1., y=1., z=0.)
Inc = 90.
Dec = 0.
Btot = 51000
data.setBackgroundField(Inc, Dec, Btot)
xr = np.linspace(-300, 300, 41)
yr = np.linspace(-300, 300, 41)
X, Y = np.meshgrid(xr, yr)
@@ -230,30 +349,14 @@ if __name__ == '__main__':
prob.pair(data)
B = prob.fields(chi)
# mesh.plotSlice(B, 'F', view='vec', showIt=True)
dpred = data.dpred(chi, u=B)
# ##################
# # Test J
# ##################
# d_chi = 0.8*chi #np.random.rand(mesh.nCz)
# d_sph_ind = spheremodel(mesh, 0., 0., -100., 50)
# d_chi[d_sph_ind] = 0.02
# from SimPEG.Tests import checkDerivative
# derChk = lambda m: [prob.data.dpred(m), lambda mx: -prob.Jvec(chi, mx)]
# print '\n'
# passed = checkDerivative(derChk, chi, plotIt=False, dx=d_chi, num=2)
# # plt.pcolor(X, Y, dpred.reshape(X.shape, order='F'))
# # plt.show()
dpred = data.dpred(chi)
fig = plt.figure( figsize = (8,5) )
ax = plt.subplot(111)
dat = plt.imshow(np.reshape(dpred, (xr.size, yr.size), order='F'), extent=[min(xr), max(xr), min(yr), max(yr)])
plt.colorbar(dat, ax = ax)
plt.show()
+12 -5
View File
@@ -4,7 +4,7 @@ import matplotlib.pyplot as plt
import simpegPF as PF
class MagProblemTests(unittest.TestCase):
class MagFwdProblemTests(unittest.TestCase):
def setUp(self):
@@ -29,7 +29,13 @@ class MagProblemTests(unittest.TestCase):
def test_anal_forward(self):
data = PF.BaseMag.BaseMagData()
data.setBackgroundField(x=1., y=1., z=0.)
Inc = 90.
Dec = 0.
Btot = 51000
b0 = PF.MagAnalytics.IDTtoxyz(Inc, Dec, Btot)
data.setBackgroundField(Inc, Dec, Btot)
xr = np.linspace(-300, 300, 41)
yr = np.linspace(-300, 300, 41)
X, Y = np.meshgrid(xr, yr)
@@ -38,9 +44,10 @@ class MagProblemTests(unittest.TestCase):
data.rxLoc = rxLoc
self.prob.pair(data)
B = self.prob.fields(self.chi)
u = self.prob.fields(self.chi)
B = u['B']
bxa,bya,bza = PF.MagAnalytics.MagSphereAnalFunA(rxLoc[:,0],rxLoc[:,1],rxLoc[:,2],100.,0.,0.,0.,0.01,np.array([1.,1.,0.]),'secondary')
bxa,bya,bza = PF.MagAnalytics.MagSphereAnalFunA(rxLoc[:,0],rxLoc[:,1],rxLoc[:,2],100.,0.,0.,0.,0.01, b0,'secondary')
dpred = data.projectFieldsAsVector(B)
err = np.linalg.norm(dpred-np.r_[bxa, bya, bza])/np.linalg.norm(np.r_[bxa, bya, bza])
@@ -50,6 +57,6 @@ class MagProblemTests(unittest.TestCase):
else:
print "Anaytic test is passed"
pass
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,316 @@
import unittest
from SimPEG import *
from simpegPF import BaseMag
import matplotlib.pyplot as plt
import simpegPF as PF
from scipy.constants import mu_0
class MagSensProblemTests(unittest.TestCase):
def setUp(self):
hxind = ((5,25,1.3),(21, 25.),(5,25,1.3))
hyind = ((5,25,1.3),(21, 25.),(5,25,1.3))
hzind = ((5,25,1.3),(20, 25.),(5,25,1.3))
hx, hy, hz = Utils.meshTensors(hxind, hyind, hzind)
M = Mesh.TensorMesh([hx, hy, hz], [-hx.sum()/2,-hy.sum()/2,-hz.sum()/2])
chibkg = 0.001
chiblk = 0.01
chi = np.ones(M.nC)*chibkg
Inc = 90.
Dec = 0.
Btot = 51000
b0 = PF.MagAnalytics.IDTtoxyz(Inc, Dec, Btot)
sph_ind = PF.MagAnalytics.spheremodel(M, 0., 0., 0., 100)
chi[sph_ind] = chiblk
model = PF.BaseMag.BaseMagModel(M)
data = BaseMag.BaseMagData()
data.setBackgroundField(Inc, Dec, Btot)
xr = np.linspace(-300, 300, 41)
yr = np.linspace(-300, 300, 41)
X, Y = np.meshgrid(xr, yr)
Z = np.ones((xr.size, yr.size))*150
rxLoc = np.c_[Utils.mkvc(X), Utils.mkvc(Y), Utils.mkvc(Z)]
data.rxLoc = rxLoc
prob = PF.Magnetics.MagneticsDiffSecondary(M, model)
prob.pair(data)
dpre = data.dpred(chi)
fields = prob.fields(chi)
self.u = fields['u']
self.B = fields['B']
self.data = data
self.model = model
self.prob = prob
self.M = M
self.chi = chi
def test_mass(self):
print '\n >>Derivative for MfMuI works.'
mu = self.model.transform(self.chi, asMu=True)
def MfmuI(mu):
chi = mu/mu_0-1
self.prob.makeMassMatrices(chi)
vol = self.prob.mesh.vol
aveF2CC = self.prob.mesh.aveF2CC
MfMuI = self.prob.MfMuI.diagonal()
return MfMuI
def dMfmuI(mu, v):
chi = mu/mu_0-1
self.prob.makeMassMatrices(chi)
vol = self.prob.mesh.vol
aveF2CC = self.prob.mesh.aveF2CC
MfMuI = self.prob.MfMuI.diagonal()
dMfMuI = Utils.sdiag(MfMuI**2)*aveF2CC.T*Utils.sdiag(vol*1./mu**2)
return dMfMuI*v
d_mu = mu*0.8
derChk = lambda m: [MfmuI(m), lambda mx: dMfmuI(self.chi, mx)]
passed = Tests.checkDerivative(derChk, mu, num=4, dx = d_mu, plotIt=False)
self.assertTrue(passed)
def test_dCdm_Av(self):
print '\n >>Derivative for Cm_A.'
Div = self.prob._Div
vol = self.prob.mesh.vol
aveF2CC = self.prob.mesh.aveF2CC
def Cm_A(chi):
dmudm = self.model.transformDeriv(chi, asMu=True)
u = self.u
# chi = mu/mu_0-1
self.prob.makeMassMatrices(chi)
mu = self.model.transform(self.chi, asMu=True)
A = self.prob.getA(self.chi)
MfMuIvec = 1/self.prob.MfMui.diagonal()
dMfMuI = Utils.sdiag(MfMuIvec**2)*aveF2CC.T*Utils.sdiag(vol*1./mu**2)
Cm_A = A*u
return Cm_A
def dCdm_A(chi, v):
dmudm = self.model.transformDeriv(chi, asMu=True)
u = self.u
self.prob.makeMassMatrices(chi)
mu = self.model.transform(self.chi, asMu=True)
A = self.prob.getA(self.chi)
MfMuIvec = 1/self.prob.MfMui.diagonal()
dMfMuI = Utils.sdiag(MfMuIvec**2)*aveF2CC.T*Utils.sdiag(vol*1./mu**2)
Cm_A = A*u
dCdm_A = Div * ( Utils.sdiag( Div.T * u )* dMfMuI *dmudm )
return dCdm_A*v
d_chi = self.chi*0.8
derChk = lambda m: [Cm_A(m), lambda mx: dCdm_A(self.chi, mx)]
passed = Tests.checkDerivative(derChk, self.chi, num=4, dx = d_chi, plotIt=False)
self.assertTrue(passed)
def test_dCdmu_RHS(self):
print '\n >>Derivative for Cm_RHS.'
u = self.u
Div = self.prob._Div
mu = self.model.transform(self.chi, asMu=True)
vol = self.prob.mesh.vol
Mc = Utils.sdiag(vol)
aveF2CC = self.prob.mesh.aveF2CC
B0 = self.prob.getB0()
Dface = self.prob.mesh.faceDiv
def Cm_RHS(chi):
self.prob.makeMassMatrices(chi)
dmudm = self.model.transformDeriv(chi, asMu=True)
dchidmu = Utils.sdiag(1/(dmudm.diagonal()))
Bbc, Bbc_const = PF.MagAnalytics.CongruousMagBC(self.prob.mesh, self.data.B0, chi)
MfMuIvec = 1/self.prob.MfMui.diagonal()
dMfMuI = Utils.sdiag(MfMuIvec**2)*aveF2CC.T*Utils.sdiag(vol*1./mu**2)
RHS1 = Div*self.prob.MfMuI*self.prob.MfMu0*B0
RHS2 = Mc*Dface*self.prob._Pout.T*Bbc
RHS = RHS1 + RHS2 + Div*B0
return RHS
def dCdm_RHS(chi, v):
self.prob.makeMassMatrices(chi)
dmudm = self.model.transformDeriv(chi, asMu=True)
dmdmu = Utils.sdiag(1/(dmudm.diagonal()))
Bbc, Bbc_const = PF.MagAnalytics.CongruousMagBC(self.prob.mesh, self.data.B0, chi)
MfMuIvec = 1/self.prob.MfMui.diagonal()
dMfMuI = Utils.sdiag(MfMuIvec**2)*aveF2CC.T*Utils.sdiag(vol*1./mu**2)
dCdm_RHS1 = Div * (Utils.sdiag( self.prob.MfMu0*B0 ) * dMfMuI)
temp1 = (Dface*(self.prob._Pout.T*Bbc_const*Bbc))
dCdm_RHS2v = (Utils.sdiag(vol)*temp1)*np.inner(vol, v)
dCdm_RHSv = dCdm_RHS1*(dmudm*v) + dCdm_RHS2v
return dCdm_RHSv
d_chi = self.chi*0.8
derChk = lambda m: [Cm_RHS(m), lambda mx: dCdm_RHS(self.chi, mx)]
passed = Tests.checkDerivative(derChk, self.chi, num=4, dx = d_chi, plotIt=False)
self.assertTrue(passed)
def test_dudm(self):
print ">> Derivative test for dudm"
u = self.u
Div = self.prob._Div
mu = self.model.transform(self.chi, asMu=True)
vol = self.prob.mesh.vol
Mc = Utils.sdiag(vol)
aveF2CC = self.prob.mesh.aveF2CC
B0 = self.prob.getB0()
Dface = self.prob.mesh.faceDiv
def ufun(chi):
u = self.prob.fields(chi)['u']
return u
def dudm(chi, v):
chi = mu/mu_0-1
self.prob.makeMassMatrices(chi)
u = self.u
dmudm = self.model.transformDeriv(chi, asMu=True)
dmdmu = Utils.sdiag(1/(dmudm.diagonal()))
Bbc, Bbc_const = PF.MagAnalytics.CongruousMagBC(self.prob.mesh, self.data.B0, chi)
MfMuIvec = 1/self.prob.MfMui.diagonal()
dMfMuI = Utils.sdiag(MfMuIvec**2)*aveF2CC.T*Utils.sdiag(vol*1./mu**2)
dCdu = self.prob.getA(chi)
dCdm_A = Div * ( Utils.sdiag( Div.T * u )* dMfMuI *dmudm )
dCdm_RHS1 = Div * (Utils.sdiag( self.prob.MfMu0*B0 ) * dMfMuI)
temp1 = (Dface*(self.prob._Pout.T*Bbc_const*Bbc))
dCdm_RHS2v = (Utils.sdiag(vol)*temp1)*np.inner(vol, v)
dCdm_RHSv = dCdm_RHS1*(dmudm*v) + dCdm_RHS2v
dCdm_v = dCdm_A*v - dCdm_RHSv
m1 = sp.linalg.interface.aslinearoperator(Utils.sdiag(1/dCdu.diagonal()))
sol, info = sp.linalg.bicgstab(dCdu, dCdm_v, tol=1e-8, maxiter=1000, M=m1)
dudm = -sol
return dudm
d_chi = 10.0*self.chi #np.random.rand(mesh.nCz)
d_sph_ind = PF.MagAnalytics.spheremodel(self.prob.mesh, 0., 0., -50., 50)
d_chi[d_sph_ind] = 0.1
derChk = lambda m: [ufun(m), lambda mx: dudm(self.chi, mx)]
# TODO: I am not sure why the order get worse as step decreases .. --;
passed = Tests.checkDerivative(derChk, self.chi, num=2, dx = d_chi, plotIt=False)
self.assertTrue(passed)
def test_dBdm(self):
print ">> Derivative test for dBdm"
u = self.u
Div = self.prob._Div
mu = self.model.transform(self.chi, asMu=True)
vol = self.prob.mesh.vol
Mc = Utils.sdiag(vol)
aveF2CC = self.prob.mesh.aveF2CC
B0 = self.prob.getB0()
Dface = self.prob.mesh.faceDiv
def Bfun(chi):
B = self.prob.fields(chi)['B']
return B
def dBdm(chi, v):
chi = mu/mu_0-1
self.prob.makeMassMatrices(chi)
u = self.u
dmudm = self.model.transformDeriv(chi, asMu=True)
dmdmu = Utils.sdiag(1/(dmudm.diagonal()))
Bbc, Bbc_const = PF.MagAnalytics.CongruousMagBC(self.prob.mesh, self.data.B0, chi)
MfMuIvec = 1/self.prob.MfMui.diagonal()
dMfMuI = Utils.sdiag(MfMuIvec**2)*aveF2CC.T*Utils.sdiag(vol*1./mu**2)
dCdu = self.prob.getA(chi)
dCdm_A = Div * ( Utils.sdiag( Div.T * u )* dMfMuI *dmudm )
dCdm_RHS1 = Div * (Utils.sdiag( self.prob.MfMu0*B0 ) * dMfMuI)
temp1 = (Dface*(self.prob._Pout.T*Bbc_const*Bbc))
dCdm_RHS2v = (Utils.sdiag(vol)*temp1)*np.inner(vol, v)
dCdm_RHSv = dCdm_RHS1*(dmudm*v) + dCdm_RHS2v
dCdm_v = dCdm_A*v - dCdm_RHSv
m1 = sp.linalg.interface.aslinearoperator(Utils.sdiag(1/dCdu.diagonal()))
sol, info = sp.linalg.bicgstab(dCdu, dCdm_v, tol=1e-8, maxiter=1000, M=m1)
dudm = -sol
dBdmv = ( Utils.sdiag(self.prob.MfMu0*B0)*(dMfMuI * (dmudm*v)) \
- Utils.sdiag(Div.T*u)*(dMfMuI* (dmudm*v)) \
- self.prob.MfMuI*(Div.T* (dudm)) )
return dBdmv
d_chi = 10.0*self.chi #np.random.rand(mesh.nCz)
d_sph_ind = PF.MagAnalytics.spheremodel(self.prob.mesh, 0., 0., -50., 50)
d_chi[d_sph_ind] = 0.1
derChk = lambda m: [Bfun(m), lambda mx: dBdm(self.chi, mx)]
# TODO: I am not sure why the order get worse as step decreases .. --;
passed = Tests.checkDerivative(derChk, self.chi, num=3, dx = d_chi, plotIt=False)
self.assertTrue(passed)
def test_Jvec(self):
print ">> Derivative test for Jvec"
mu = self.model.transform(self.chi, asMu=True)
d_chi = 10.0*self.chi #np.random.rand(mesh.nCz)
d_sph_ind = PF.MagAnalytics.spheremodel(self.prob.mesh, 0., 0., -50., 50)
d_chi[d_sph_ind] = 0.1
a = self.prob.Jvec(self.chi, d_chi)
derChk = lambda m: [self.data.dpred(m), lambda mx: self.prob.Jvec(self.chi, mx)]
# TODO: I am not sure why the order get worse as step decreases .. --;
passed = Tests.checkDerivative(derChk, self.chi, num=2, dx = d_chi, plotIt=False)
self.assertTrue(passed)
def test_Jtvec(self):
print ">> Derivative test for Jtvec"
mu = self.model.transform(self.chi, asMu=True)
dobs = self.data.dpred(self.chi)
def misfit (m, dobs):
dpre = self.data.dpred(m)
misfit = 0.5*np.linalg.norm(dpre-dobs)**2
residual = dpre-dobs
dmisfit = self.prob.Jtvec(self.chi, residual)
return misfit, dmisfit
# TODO: I am not sure why the order get worse as step decreases .. --;
derChk = lambda m: misfit(m, dobs)
passed = Tests.checkDerivative(derChk, self.chi, num=4, plotIt=False)
self.assertTrue(passed)
if __name__ == '__main__':
unittest.main()
File diff suppressed because one or more lines are too long