In [1]:
import SimPEG as simpeg
from scipy.constants import mu_0
def omega(freq):
    """Change frequency to angular frequency, omega"""
    return 2.*np.pi*freq


Efficiency Warning: Interpolation will be slow, use setup.py!

            python setup.py build_ext --inplace
    

In [2]:
%pylab inline


Populating the interactive namespace from numpy and matplotlib

In [3]:
# M = Mesh.TensorMesh([[(100.,32)],[(100.,34)],[(100.,18)]], x0='CCC')
M = simpeg.Mesh.TensorMesh([[(100,5,-1.5),(100.,5),(100,5,1.5)],[(100,5,-1.5),(100.,5),(100,5,1.5)],[(100,10,-1.5),(100.,10),(100,10,1.5)]], x0=['C','C','C'])

In [4]:
print M.vectorNz


[-17499.51171875 -11733.0078125   -7888.671875    -5325.78125     -3617.1875
  -2478.125       -1718.75        -1212.5          -875.           -650.
   -500.           -400.           -300.           -200.           -100.
      0.            100.            200.            300.            400.
    500.            650.            875.           1212.5          1718.75
   2478.125        3617.1875       5325.78125      7888.671875
  11733.0078125   17499.51171875]

In [5]:
# Set parameters
freq = 10
conds = [0.01]
elev = 300
# Setup the models
sig = np.zeros(M.nC) + 1e-8
sig[M.gridCC[:,2]<=elev] = conds[0]
# sig[M.gridCC[:,2]<-600] = 1e-1
sigBG = np.zeros(M.nC) + 1e-8
sigBG[M.gridCC[:,2]<=elev] = conds[0]

In [6]:
# Plot the models
colorbar(M.plotImage(log10(sig)))
colorbar(M.plotImage(log10(sigBG)))


Out[6]:
<matplotlib.colorbar.Colorbar instance at 0x7f12d2e2d128>

In [7]:
# Get the mass matrix 
# The model
Msig = M.getEdgeInnerProduct(sig)
MsigBG = M.getEdgeInnerProduct(sigBG)
Mmu = M.getFaceInnerProduct(mu_0, invProp=True)

In [8]:
# Form the A matrices
C = M.edgeCurl
A = C.T*Mmu*C - 1j*omega(freq)*Msig
ABG = C.T*Mmu*C - 1j*omega(freq)*MsigBG

We are using splu in scipy package. This is bit slow, but on the cluster you can use mumps, which might a lot faster. We can think about having better iterative solver.


In [9]:
%%time
# Solve the systems for each polarization
Ainv = simpeg.SolverLU(A)


CPU times: user 34.7 s, sys: 420 ms, total: 35.2 s
Wall time: 35.5 s

In [10]:
# Need to solve x and y polarizations of the source.
from simpegMT.Utils import get1DEfields
# Get a 1d solution for a halfspace background
mesh1d = simpeg.Mesh.TensorMesh([M.hz],np.array([M.x0[2]]))
e0_1d = get1DEfields(mesh1d,M.r(sigBG,'CC','CC','M')[0,0,:],freq,sourceAmp=1).conj() # conjugate to comply with phase behavior
# Setup x (east) polarization (_x)
ex_x = np.zeros(M.vnEx,dtype=complex)
ey_x = np.zeros((M.nEy,1),dtype=complex)
ez_x = np.zeros((M.nEz,1),dtype=complex)
# Assign the source to ex_x
for i in arange(M.vnEx[0]):
    for j in arange(M.vnEx[1]):
        ex_x[i,j,:] = -e0_1d #Negative to comply with phase orientation.

eBG_x = np.vstack((simpeg.Utils.mkvc(ex_x,2),ey_x,ez_x))
# Note 100% sure why this has to be negative.
rhs_x = -ABG*eBG_x

In [11]:
# Setup y (north) polarization (_y)
ex_y = np.zeros(M.nEx, dtype='complex128')
ey_y = np.zeros((M.vnEy), dtype='complex128')
ez_y = np.zeros(M.nEz, dtype='complex128')
# Assign the source to ex_x
for i in arange(M.vnEy[0]):
    for j in arange(M.vnEy[1]):
        ey_y[i,j,:] = e0_1d

In [12]:
eBG_y = np.r_[ex_y,simpeg.Utils.mkvc(ey_y),ez_y]
# Note 100% sure why this has to be negative.
rhs_y = -ABG*eBG_y

In [14]:
%%time
# Solve each polarization
e_x = Ainv*rhs_x
e_y = Ainv*rhs_y


CPU times: user 346 ms, sys: 1 ms, total: 347 ms
Wall time: 480 ms

I want to visualize electrical field, which is a vector, so I average them on to cell center. Also I want to see current density ($\vec{j} = \sigma \vec{e}$).


In [15]:
Meinv = M.getEdgeInnerProduct(np.ones_like(sig), invMat=True)

In [16]:
j_x = Meinv*Msig*e_x
j_y = Meinv*Msig*e_y

In [17]:
e_x_CC = M.aveE2CCV*e_x
e_y_CC = M.aveE2CCV*e_y
j_x_CC = M.aveE2CCV*j_x
j_y_CC = M.aveE2CCV*j_y
# j_x_CC = Utils.sdiag(np.r_[sig, sig, sig])*e_x_CC

In [31]:
e_x


Out[31]:
array([  6.95763292e-07 -5.19497296e-07j,
         6.95763292e-07 -5.19497296e-07j,
         6.95763292e-07 -5.19497296e-07j, ...,
        -9.19690759e-13 +1.90393072e-10j,
        -9.42272240e-13 +1.17287969e-10j,  -2.84432632e-12 -1.10938670e-10j])

Then use "plotSlice" function, to visualize 2D sections


In [18]:
fig, ax = plt.subplots(1,2, figsize = (12, 5))
dat0 = M.plotSlice(abs(e_y_CC), vType='CCv', view='vec', streamOpts={'color': 'k'}, normal='X', ax = ax[0])
cb0 = plt.colorbar(dat0[0], ax = ax[0])
dat1 = M.plotSlice(abs(j_y_CC), vType='CCv', view='vec', streamOpts={'color': 'k'}, normal='X', ax = ax[1])
cb1 = plt.colorbar(dat1[0], ax = ax[1])


Is it reasonable?: Based on that you put resistive target that makes sense to me; current does not want to flow on resistive target so they just do roundabout:). And see air interface. It is continuous on current but not on electric field, which looks reasonable.


In [19]:
# Calculate the data
rx_x, rx_y = np.meshgrid(np.arange(-250,251,50),np.arange(-250,251,50))
rx_loc = np.hstack((simpeg.Utils.mkvc(rx_x,2),simpeg.Utils.mkvc(rx_y,2),elev+np.zeros((np.prod(rx_x.shape),1))))
# Get the projection matrices
Qex = M.getInterpolationMat(rx_loc,'Ex')
Qey = M.getInterpolationMat(rx_loc,'Ey')
Qez = M.getInterpolationMat(rx_loc,'Ez')
Qfx = M.getInterpolationMat(rx_loc,'Fx')
Qfy = M.getInterpolationMat(rx_loc,'Fy')
Qfz = M.getInterpolationMat(rx_loc,'Fz')

In [20]:
e_x_loc = np.hstack([simpeg.Utils.mkvc(Qex*e_x,2),simpeg.Utils.mkvc(Qey*e_x,2),simpeg.Utils.mkvc(Qez*e_x,2)])
e_y_loc = np.hstack([simpeg.Utils.mkvc(Qex*e_y,2),simpeg.Utils.mkvc(Qey*e_y,2),simpeg.Utils.mkvc(Qez*e_y,2)])
Ciw = -C/(1j*omega(freq))
b_x_loc = np.hstack([simpeg.Utils.mkvc(Qfx*Ciw*e_x,2),simpeg.Utils.mkvc(Qfy*Ciw*e_x,2),simpeg.Utils.mkvc(Qfz*Ciw*e_x,2)])
b_y_loc = np.hstack([simpeg.Utils.mkvc(Qfx*Ciw*e_y,2),simpeg.Utils.mkvc(Qfy*Ciw*e_y,2),simpeg.Utils.mkvc(Qfz*Ciw*e_y,2)])

In [21]:
from scipy.constants import mu_0
# Make a combined matrix
dt = np.dtype([('ex1',complex),('ey1',complex),('ez1',complex),('hx1',complex),('hy1',complex),('hz1',complex),('ex2',complex),('ey2',complex),('ez2',complex),('hx2',complex),('hy2',complex),('hz2',complex)])
combMat = np.empty((len(e_x_loc)),dtype=dt)
combMat['ex1'] = e_x_loc[:,0]
combMat['ey1'] = e_x_loc[:,1]
combMat['ez1'] = e_x_loc[:,2]
combMat['ex2'] = e_y_loc[:,0]
combMat['ey2'] = e_y_loc[:,1]
combMat['ez2'] = e_y_loc[:,2]
combMat['hx1'] = b_x_loc[:,0]/mu_0
combMat['hy1'] = b_x_loc[:,1]/mu_0
combMat['hz1'] = b_x_loc[:,2]/mu_0
combMat['hx2'] = b_y_loc[:,0]/mu_0
combMat['hy2'] = b_y_loc[:,1]/mu_0
combMat['hz2'] = b_y_loc[:,2]/mu_0

In [22]:
def calculateImpedance(fieldsData):
    ''' 
    Function that calculates MT impedance data from a rec array with E and H field data from both polarizations
    '''
    zxx = (fieldsData['ex1']*fieldsData['hy2'] - fieldsData['ex2']*fieldsData['hy1'])/(fieldsData['hx1']*fieldsData['hy2'] - fieldsData['hx2']*fieldsData['hy1'])
    zxy = (-fieldsData['ex1']*fieldsData['hx2'] + fieldsData['ex2']*fieldsData['hx1'])/(fieldsData['hx1']*fieldsData['hy2'] - fieldsData['hx2']*fieldsData['hy1'])
    zyx = (fieldsData['ey1']*fieldsData['hy2'] - fieldsData['ey2']*fieldsData['hy1'])/(fieldsData['hx1']*fieldsData['hy2'] - fieldsData['hx2']*fieldsData['hy1'])
    zyy = (-fieldsData['ey1']*fieldsData['hx2'] + fieldsData['ey2']*fieldsData['hx1'])/(fieldsData['hx1']*fieldsData['hy2'] - fieldsData['hx2']*fieldsData['hy1'])
    return zxx, zxy, zyx, zyy

zxx, zxy, zyx, zyy = calculateImpedance(combMat)

In [29]:
zxy


Out[29]:
array([-0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j, -0.06237698-0.06472069j,
       -0.06237698-0.06472069j])

In [28]:
ind = np.where(np.sum(np.power(rx_loc - np.array([0,0,elev]),2),axis=1)< 5)
def appResPhs(freq,z):
    app_res = ((1./(8e-7*np.pi**2))/freq)*np.abs(z)**2
    app_phs = np.arctan2(z.imag,z.real)*(180/np.pi)
    return app_res, app_phs

print appResPhs(freq,zxy[ind])
print appResPhs(freq,zyx[ind])


(array([ 102.33002434]), array([-133.94357304]))
(array([ 102.33002434]), array([ 46.05642696]))

In [25]:
e0_1d
h0_1dC = -(mesh1d.nodalGrad*e0_1d)/(1j*omega(freq)*mu_0)
h0_1d = mesh1d.getInterpolationMat(mesh1d.vectorNx,'CC')*h0_1dC

print e0_1d, h0_1d, appResPhs(freq,e0_1d/h0_1d)


[  6.95763292e-07 -5.19497296e-07j   9.74760218e-06 -1.09092785e-05j
   1.74907169e-04 +1.24344756e-04j  -5.21083562e-04 +1.34839517e-03j
  -4.87010903e-03 +6.63069113e-04j  -8.61854919e-03 -6.03020882e-03j
  -7.68552978e-03 -1.53974787e-02j  -3.16876824e-03 -2.35863583e-02j
   2.49400722e-03 -2.94018473e-02j   7.73825040e-03 -3.31542272e-02j
   1.19706555e-02 -3.54839735e-02j   1.51424717e-02 -3.69189921e-02j
   1.86057886e-02 -3.82344505e-02j   2.23709926e-02 -3.94030035e-02j
   2.64473102e-02 -4.03949222e-02j   3.08425733e-02 -4.11780213e-02j
   3.55629651e-02 -4.17175972e-02j   4.06127458e-02 -4.19763792e-02j
   4.59939588e-02 -4.19144958e-02j   5.15406437e-02 -4.16710354e-02j
   5.70873289e-02 -4.14275746e-02j   6.54073573e-02 -4.10623825e-02j
   7.78874014e-02 -4.05145921e-02j   9.66074704e-02 -3.96929008e-02j
   1.24687581e-01 -3.84603474e-02j   1.66807761e-01 -3.66114701e-02j
   2.29988062e-01 -3.38380118e-02j   3.24758579e-01 -2.96773825e-02j
   4.66914483e-01 -2.34350351e-02j   6.80148567e-01 -1.40669735e-02j
   1.00000000e+00 -0.00000000e+00j] [  2.28193925e-05 +1.98808291e-05j  -2.58228538e-04 +3.34422815e-04j
  -3.80760340e-03 -1.84599759e-03j   6.28457755e-04 -2.07183543e-02j
   4.66852476e-02 -3.79022309e-02j   1.23507371e-01 -7.33469297e-03j
   1.85411921e-01 +7.40235581e-02j   2.12886863e-01 +1.72701395e-01j
   2.14025522e-01 +2.62118992e-01j   2.02514232e-01 +3.32494576e-01j
   1.87732553e-01 +3.83973226e-01j   1.74175989e-01 +4.20174709e-01j
   1.57301859e-01 +4.57751431e-01j   1.36813469e-01 +4.96570158e-01j
   1.12404317e-01 +5.36469120e-01j   8.37593755e-02 +5.77255592e-01j
   5.05566063e-02 +6.18703401e-01j   1.24687508e-02 +6.60550390e-01j
  -1.93361233e-02 +6.92017214e-01j  -3.08346503e-02 +7.02495869e-01j
  -3.08347046e-02 +7.02495910e-01j  -3.08347965e-02 +7.02495972e-01j
  -3.08349577e-02 +7.02496064e-01j  -3.08352521e-02 +7.02496199e-01j
  -3.08358123e-02 +7.02496397e-01j  -3.08369191e-02 +7.02496682e-01j
  -3.08391789e-02 +7.02497084e-01j  -3.08439181e-02 +7.02497626e-01j
  -3.08540630e-02 +7.02498307e-01j  -3.08761114e-02 +7.02499028e-01j
  -3.08957218e-02 +7.02499433e-01j] (array([  1.04250623e+01,   1.51842290e+01,   3.25755099e+01,
         6.16004358e+01,   8.46106546e+01,   9.15416501e+01,
         9.41057689e+01,   9.54534366e+01,   9.62980028e+01,
         9.68560992e+01,   9.72291393e+01,   9.74787343e+01,
         9.77427801e+01,   9.80109244e+01,   9.82749421e+01,
         9.85284962e+01,   9.87669033e+01,   9.89869077e+01,
         1.02330024e+02,   1.12522515e+02,   1.27437698e+02,
         1.52771347e+02,   1.97433785e+02,   2.79416850e+02,
         4.36117589e+02,   7.47052417e+02,   1.38419269e+03,
         2.72406252e+03,   5.59822214e+03,   1.18542471e+04,
         2.56141002e+04]), array([ -77.81035558, -175.89268984, -170.45525015, -160.60855616,
       -148.68117232, -141.62175107, -138.28949602, -136.70192166,
       -135.91915906, -135.51770546, -135.30300073, -135.18323205,
       -135.08656033, -135.01054362, -134.95270735, -134.91062064,
       -134.88195438, -134.86452348, -133.94357304, -131.46909534,
       -128.48120651, -124.63366007, -119.99533648, -114.8495013 ,
       -109.65593591, -104.892614  , -100.88348042,  -97.73537134,
        -95.3881792 ,  -93.70146842,  -92.51822905]))

In [26]:
# Get the analytic solution for the halfspace.
import simpegMT as simpegmt
sig1DBG = M.r(sigBG,'CC','CC','M')[0,0,:]
anaEd, anaEu, anaHd, anaHu = simpegmt.Utils.MT1Danalytic.getEHfields(mesh1d,sig1DBG,freq,mesh1d.vectorNx)
anaEtemp = anaEd+anaEu
anaHtemp = anaHd+anaHu
# Scale the solution
anaE = (anaEtemp/anaEtemp[-1])#.conj()
anaH = (anaHtemp/anaEtemp[-1])#.conj()

In [27]:
anaZ = anaE/anaH
print anaZ, appResPhs(freq,anaZ)


[ 0.06283185+0.06283185j  0.06283185+0.06283185j  0.06283185+0.06283185j
  0.06283185+0.06283185j  0.06283185+0.06283185j  0.06283185+0.06283185j
  0.06283185+0.06283185j  0.06283185+0.06283185j  0.06283185+0.06283185j
  0.06283185+0.06283185j  0.06283185+0.06283185j  0.06283185+0.06283185j
  0.06283185+0.06283185j  0.06283185+0.06283185j  0.06283185+0.06283185j
  0.06283185+0.06283185j  0.06283185+0.06283185j  0.06283185+0.06283185j
  0.06283185+0.06283185j  0.06283186+0.07072753j  0.06283186+0.0786232j
  0.06283186+0.09046671j  0.06283188+0.10823197j  0.06283192+0.13487985j
  0.06283203+0.17485166j  0.06283233+0.23480933j  0.06283320+0.32474574j
  0.06283584+0.4596502j   0.06284399+0.66200657j  0.06286981+0.96554066j
  0.06295315+1.42084151j] (array([   100.        ,    100.        ,    100.        ,    100.        ,
          100.        ,    100.        ,    100.        ,    100.        ,
          100.        ,    100.        ,    100.        ,    100.        ,
          100.        ,    100.        ,    100.        ,    100.        ,
          100.        ,    100.        ,    100.        ,    113.3559252 ,
          128.29098377,    153.65444595,    198.36160419,    280.41175545,
          437.21314017,    748.29899993,   1385.66608888,   2725.87734814,
         5600.55464041,  11857.38236111,  25618.47494334]), array([ 44.99999841,  44.99999841,  44.99999841,  44.99999841,
        44.99999841,  44.99999841,  44.99999841,  44.99999841,
        44.99999841,  44.99999841,  44.99999841,  44.99999841,
        44.99999841,  44.99999841,  44.99999841,  44.99999841,
        44.99999841,  44.99999841,  44.99999841,  48.38323441,
        51.36984352,  55.21885339,  59.86356014,  65.02219199,
        70.23436618,  75.01927161,  79.04947649,  82.2157119 ,
        84.57718798,  86.27452602,  87.46305803]))

In [27]:


In [27]: