Example #1
0
    def _evalCross(self, m):
        if self.crossgrad == False:
            return 0.
        elif self.crossgrad == True:
            M = (self.mapping * m).reshape((self.regmesh.nC, self.nModels),
                                           order="F")

            ax = self.regmesh.aveFx2CC * self.regmesh.wx[0] * M[:, 0]
            ay = self.regmesh.aveFy2CC * self.regmesh.wy[0] * M[:, 0]
            az = self.regmesh.aveFz2CC * self.regmesh.wz[0] * M[:, 0]
            bx = self.regmesh.aveFx2CC * self.regmesh.wx[1] * M[:, 1]
            by = self.regmesh.aveFy2CC * self.regmesh.wy[1] * M[:, 1]
            bz = self.regmesh.aveFz2CC * self.regmesh.wz[1] * M[:, 1]
            #ab
            out_ab = cross([ax, ay, az], [bx, by, bz])
            r = np.r_[out_ab[0], out_ab[1], out_ab[2]] * np.sqrt(
                self.betacross)

            if self.nModels == 3:
                cx = self.regmesh.aveFx2CC * self.regmesh.wx[1] * M[:, 1]
                cy = self.regmesh.aveFy2CC * self.regmesh.wy[1] * M[:, 1]
                cz = self.regmesh.aveFz2CC * self.regmesh.wz[1] * M[:, 1]
                #ac
                out_ac = cross([ax, ay, az], [cx, cy, cz])
                #bc
                out_bc = cross([bx, by, bz], [cx, cy, cz])
                r = np.r_[r,
                          np.hstack(out_ac) * np.sqrt(self.betacross),
                          np.hstack(out_bc) * np.sqrt(self.betacross)]

            return 0.5 * r.dot(r)
Example #2
0
def _getCasingHertzMagDipole2Deriv_z_r(srcloc,
                                       obsloc,
                                       freq,
                                       sigma,
                                       a,
                                       b,
                                       mu=mu_0 * np.ones(3),
                                       eps=epsilon_0,
                                       moment=1.):
    HertzZ = _getCasingHertzMagDipole(srcloc, obsloc, freq, sigma, a, b, mu,
                                      eps, moment)
    dHertzZdr = _getCasingHertzMagDipoleDeriv_r(srcloc, obsloc, freq, sigma, a,
                                                b, mu, eps, moment)

    nobs = obsloc.shape[0]
    dxyz = obsloc - np.c_[np.ones(nobs)] * np.r_[srcloc]

    r2 = _r2(dxyz[:, :2])
    r = np.sqrt(r2)
    z = dxyz[:, 2]
    sqrtr2z2 = np.sqrt(r2 + z**2)
    k2 = k(freq, sigma[2], mu[2], eps)

    return dHertzZdr * (-z / sqrtr2z2) * (1j * k2 + 1. / sqrtr2z2) + HertzZ * (
        z * r / sqrtr2z2**3) * (1j * k2 + 2. / sqrtr2z2)
Example #3
0
    def _evalCross(self, m):
        if self.crossgrad == False:
            return 0.0
        elif self.crossgrad == True:
            M = (self.mapping * m).reshape((self.regmesh.nC, self.nModels), order="F")

            ax = self.regmesh.aveFx2CC * self.regmesh.wx[0] * M[:, 0]
            ay = self.regmesh.aveFy2CC * self.regmesh.wy[0] * M[:, 0]
            az = self.regmesh.aveFz2CC * self.regmesh.wz[0] * M[:, 0]
            bx = self.regmesh.aveFx2CC * self.regmesh.wx[1] * M[:, 1]
            by = self.regmesh.aveFy2CC * self.regmesh.wy[1] * M[:, 1]
            bz = self.regmesh.aveFz2CC * self.regmesh.wz[1] * M[:, 1]
            # ab
            out_ab = cross([ax, ay, az], [bx, by, bz])
            r = np.r_[out_ab[0], out_ab[1], out_ab[2]] * np.sqrt(self.betacross)

            if self.nModels == 3:
                cx = self.regmesh.aveFx2CC * self.regmesh.wx[1] * M[:, 1]
                cy = self.regmesh.aveFy2CC * self.regmesh.wy[1] * M[:, 1]
                cz = self.regmesh.aveFz2CC * self.regmesh.wz[1] * M[:, 1]
                # ac
                out_ac = cross([ax, ay, az], [cx, cy, cz])
                # bc
                out_bc = cross([bx, by, bz], [cx, cy, cz])
                r = np.r_[r, np.hstack(out_ac) * np.sqrt(self.betacross), np.hstack(out_bc) * np.sqrt(self.betacross)]

            return 0.5 * r.dot(r)
Example #4
0
def _getCasingHertzMagDipoleDeriv_r(srcloc,obsloc,freq,sigma,a,b,mu=mu_0*np.ones(3),eps=epsilon_0,moment=1.):
    HertzZ = _getCasingHertzMagDipole(srcloc,obsloc,freq,sigma,a,b,mu,eps,moment)
    
    nobs = obsloc.shape[0]
    dxyz = obsloc - np.c_[np.ones(nobs)]*np.r_[srcloc]
    
    r2 = _r2(dxyz[:,:2])
    sqrtr2z2 = np.sqrt(r2 + dxyz[:,2]**2)
    k2 = k(freq,sigma[2],mu[2],eps) 
    
    return -HertzZ * np.sqrt(r2) / sqrtr2z2 * (1j*k2 + 1./ sqrtr2z2)
Example #5
0
def _getCasingHertzMagDipole2Deriv_z_z(srcloc,obsloc,freq,sigma,a,b,mu=mu_0*np.ones(3),eps=epsilon_0,moment=1.):
    HertzZ = _getCasingHertzMagDipole(srcloc,obsloc,freq,sigma,a,b,mu,eps,moment)
    dHertzZdz = _getCasingHertzMagDipoleDeriv_z(srcloc,obsloc,freq,sigma,a,b,mu,eps,moment)
    
    nobs = obsloc.shape[0]
    dxyz = obsloc - np.c_[np.ones(nobs)]*np.r_[srcloc]

    r2 = _r2(dxyz[:,:2])
    r = np.sqrt(r2)
    z = dxyz[:,2]
    sqrtr2z2 = np.sqrt(r2 + z**2)
    k2 = k(freq,sigma[2],mu[2],eps) 
    
    return (dHertzZdz*z + HertzZ)/sqrtr2z2*(-1j*k2 - 1./sqrtr2z2) + HertzZ*z/sqrtr2z2**3*(1j*k2*z + 2.*z/sqrtr2z2)
Example #6
0
    def test_ana_forward(self):

        # Compute 3-component mag data
        self.survey.pair(self.prob_xyz)
        d = self.prob_xyz.fields(self.model)

        ndata = self.locXyz.shape[0]
        dbx = d[0:ndata]
        dby = d[ndata:2*ndata]
        dbz = d[2*ndata:]

        # Compute tmi mag data
        self.survey.pair(self.prob_tmi)
        dtmi = self.prob_tmi.fields(self.model)

        # Compute analytical response from a magnetized sphere
        bxa, bya, bza = PF.MagAnalytics.MagSphereFreeSpace(self.locXyz[:, 0],
                                                           self.locXyz[:, 1],
                                                           self.locXyz[:, 2],
                                                           self.rad, 0, 0, 0,
                                                           self.chi, self.b0)

        # Projection matrix
        Ptmi = mkvc(self.b0)/np.sqrt(np.sum(self.b0**2.))

        btmi = mkvc(Ptmi.dot(np.vstack((bxa, bya, bza))))

        err_xyz = (np.linalg.norm(d-np.r_[bxa, bya, bza]) /
                   np.linalg.norm(np.r_[bxa, bya, bza]))

        err_tmi = np.linalg.norm(dtmi-btmi)/np.linalg.norm(btmi)
        self.assertTrue(err_xyz < 0.005 and err_tmi < 0.005)
Example #7
0
def run(plotIt=True):
    """
        Mesh: Basic: Types
        ==================

        Here we show SimPEG used to create three different types of meshes.

    """
    sz = [16, 16]
    tM = Mesh.TensorMesh(sz)
    qM = Mesh.TreeMesh(sz)
    qM.refine(lambda cell: 4
              if np.sqrt(((np.r_[cell.center] - 0.5)**2).sum()) < 0.4 else 3)
    rM = Mesh.CurvilinearMesh(Utils.meshutils.exampleLrmGrid(sz, 'rotate'))

    if plotIt:
        import matplotlib.pyplot as plt
        fig, axes = plt.subplots(1, 3, figsize=(14, 5))
        opts = {}
        tM.plotGrid(ax=axes[0], **opts)
        axes[0].set_title('TensorMesh')
        qM.plotGrid(ax=axes[1], **opts)
        axes[1].set_title('TreeMesh')
        rM.plotGrid(ax=axes[2], **opts)
        axes[2].set_title('CurvilinearMesh')
        plt.show()
Example #8
0
    def projectFields(self, u):
        """
            This function projects the fields onto the data space.

            Especially, here for we use total magnetic intensity (TMI) data,
            which is common in practice.

            First we project our B on to data location

            .. math::

                \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 * u['B']
        bfy = self.Qfy * u['B']
        bfz = self.Qfz * u['B']

        # Generate unit vector
        B0 = self.prob.survey.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
Example #9
0
    def projectFields(self, u):
        """
            This function projects the fields onto the data space.

            Especially, here for we use total magnetic intensity (TMI) data,
            which is common in practice.

            First we project our B on to data location

            .. math::

                \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*u['B']
        bfy = self.Qfy*u['B']
        bfz = self.Qfz*u['B']

        # Generate unit vector
        B0 = self.prob.survey.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
Example #10
0
def run(plotIt=True):
    """
        Mesh: Basic: Types
        ==================

        Here we show SimPEG used to create three different types of meshes.

    """
    sz = [16, 16]
    tM = Mesh.TensorMesh(sz)
    qM = Mesh.TreeMesh(sz)
    qM.refine(lambda cell: 4 if np.sqrt(((np.r_[cell.center]-0.5)**2).sum()) < 0.4 else 3)
    rM = Mesh.CurvilinearMesh(Utils.meshutils.exampleLrmGrid(sz, 'rotate'))

    if plotIt:
        import matplotlib.pyplot as plt
        fig, axes = plt.subplots(1, 3, figsize=(14, 5))
        opts = {}
        tM.plotGrid(ax=axes[0], **opts)
        axes[0].set_title('TensorMesh')
        qM.plotGrid(ax=axes[1], **opts)
        axes[1].set_title('TreeMesh')
        rM.plotGrid(ax=axes[2], **opts)
        axes[2].set_title('CurvilinearMesh')
        plt.show()
Example #11
0
    def test_ana_forward(self):

        # Compute 3-component mag data
        self.survey.pair(self.prob_xyz)
        d = self.prob_xyz.fields(self.model)

        ndata = self.locXyz.shape[0]
        dbx = d[0:ndata]
        dby = d[ndata:2 * ndata]
        dbz = d[2 * ndata:]

        # Compute tmi mag data
        self.survey.pair(self.prob_tmi)
        dtmi = self.prob_tmi.fields(self.model)

        # Compute analytical response from a magnetized sphere
        bxa, bya, bza = PF.MagAnalytics.MagSphereFreeSpace(
            self.locXyz[:, 0], self.locXyz[:, 1], self.locXyz[:, 2], self.rad,
            0, 0, 0, self.chi, self.b0)

        # Projection matrix
        Ptmi = mkvc(self.b0) / np.sqrt(np.sum(self.b0**2.))

        btmi = mkvc(Ptmi.dot(np.vstack((bxa, bya, bza))))

        err_xyz = (np.linalg.norm(d - np.r_[bxa, bya, bza]) /
                   np.linalg.norm(np.r_[bxa, bya, bza]))

        err_tmi = np.linalg.norm(dtmi - btmi) / np.linalg.norm(btmi)
        self.assertTrue(err_xyz < 0.005 and err_tmi < 0.005)
Example #12
0
 def function(xc):
     r = xc - np.r_[2.,6.]
     dist = np.sqrt(r.dot(r))
     if dist < 1.0:
         return 3
     if dist < 1.5:
         return 2
     else:
         return 1
Example #13
0
def convertObs_DC3D_to_2D(Tx,Rx):
    
    from SimPEG import np
    import numpy.matlib as npm
    """
        Read list of 3D Tx Rx location and change coordinate system to distance
        along line assuming all data is acquired along line
        First transmitter pole is assumed to be at the origin

        Assumes flat topo for now...
    
        Input:
        :param Tx, Rx
        
        Output:
        :figure Tx2d, Rx2d
        
        Created on Mon December 7th, 2015
    
        @author: dominiquef
    
    """
    
                
    Tx2d = []
    Rx2d = []

    for ii in range(len(Tx)):
        
        if ii == 0:
            endp = Tx[0][0:2,0]
        
        nrx = Rx[ii].shape[0]
                  
        rP1 = np.sqrt( np.sum( ( endp - Tx[ii][0:2,0] )**2 , axis=0))
        rP2 = np.sqrt( np.sum( ( endp - Tx[ii][0:2,1] )**2 , axis=0))
        rC1 = np.sqrt( np.sum( ( npm.repmat(endp.T,nrx,1) - Rx[ii][:,0:2] )**2 , axis=1))
        rC2 = np.sqrt( np.sum( ( npm.repmat(endp.T,nrx,1) - Rx[ii][:,3:5] )**2 , axis=1))
        
        Tx2d.append( np.r_[rP1, rP2] )
        Rx2d.append( np.c_[rC1, rC2] )
            #np.savetxt(fid, data, fmt='%e',delimiter=' ',newline='\n')

    return Tx2d, Rx2d
Example #14
0
def _getCasingHertzMagDipoleDeriv_r(srcloc,
                                    obsloc,
                                    freq,
                                    sigma,
                                    a,
                                    b,
                                    mu=mu_0 * np.ones(3),
                                    eps=epsilon_0,
                                    moment=1.):
    HertzZ = _getCasingHertzMagDipole(srcloc, obsloc, freq, sigma, a, b, mu,
                                      eps, moment)

    nobs = obsloc.shape[0]
    dxyz = obsloc - np.c_[np.ones(nobs)] * np.r_[srcloc]

    r2 = _r2(dxyz[:, :2])
    sqrtr2z2 = np.sqrt(r2 + dxyz[:, 2]**2)
    k2 = k(freq, sigma[2], mu[2], eps)

    return -HertzZ * np.sqrt(r2) / sqrtr2z2 * (1j * k2 + 1. / sqrtr2z2)
Example #15
0
def _getCasingHertzMagDipole(srcloc,obsloc,freq,sigma,a,b,mu=mu_0*np.ones(3),eps=epsilon_0,moment=1.):
    Kc1 = getKc(freq,sigma[1],a,b,mu[1],eps)

    nobs = obsloc.shape[0]
    dxyz = obsloc - np.c_[np.ones(nobs)]*np.r_[srcloc]
    
    r2 = _r2(dxyz[:,:2])
    sqrtr2z2 = np.sqrt(r2 + dxyz[:,2]**2)
    k2 = k(freq,sigma[2],mu[2],eps) 
    
    return Kc1 * moment / (4.*np.pi) *np.exp(-1j*k2*sqrtr2z2) / sqrtr2z2
Example #16
0
    def projectFieldsDeriv(self, B):
        """
            This function projects the fields onto the data space.

            .. math::

                \\frac{\partial d_\\text{pred}}{\partial \mathbf{B}} = \mathbf{P}

            Especially, this function is for TMI data type

        """
        # Generate unit vector
        B0 = self.prob.survey.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
Example #17
0
    def projectFieldsDeriv(self, B):
        """
            This function projects the fields onto the data space.

            .. math::

                \\frac{\partial d_\\text{pred}}{\partial \mathbf{B}} = \mathbf{P}

            Especially, this function is for TMI data type

        """
        # Generate unit vector
        B0 = self.prob.survey.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
Example #18
0
def _getCasingHertzMagDipole(srcloc,
                             obsloc,
                             freq,
                             sigma,
                             a,
                             b,
                             mu=mu_0 * np.ones(3),
                             eps=epsilon_0,
                             moment=1.):
    Kc1 = getKc(freq, sigma[1], a, b, mu[1], eps)

    nobs = obsloc.shape[0]
    dxyz = obsloc - np.c_[np.ones(nobs)] * np.r_[srcloc]

    r2 = _r2(dxyz[:, :2])
    sqrtr2z2 = np.sqrt(r2 + dxyz[:, 2]**2)
    k2 = k(freq, sigma[2], mu[2], eps)

    return Kc1 * moment / (4. * np.pi) * np.exp(-1j * k2 * sqrtr2z2) / sqrtr2z2
Example #19
0
def run(plotIt=True):
    """
    1D FDEM and TDEM inversions
    ===========================

    This example is used in the paper Heagy et al 2016 (in prep)

    """

    # Set up cylindrically symmeric mesh
    cs, ncx, ncz, npad = 10., 15, 25, 13  # padded cyl mesh
    hx = [(cs, ncx), (cs, npad, 1.3)]
    hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)]
    mesh = Mesh.CylMesh([hx, 1, hz], '00C')

    # Conductivity model
    layerz = np.r_[-200., -100.]
    layer = (mesh.vectorCCz >= layerz[0]) & (mesh.vectorCCz <= layerz[1])
    active = mesh.vectorCCz < 0.
    sig_half = 1e-2  # Half-space conductivity
    sig_air = 1e-8  # Air conductivity
    sig_layer = 5e-2  # Layer conductivity
    sigma = np.ones(mesh.nCz)*sig_air
    sigma[active] = sig_half
    sigma[layer] = sig_layer

    # Mapping
    actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
    mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap
    mtrue = np.log(sigma[active])

    # ----- FDEM problem & survey -----
    rxlocs = Utils.ndgrid([np.r_[50.], np.r_[0], np.r_[0.]])
    bzi = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'real')
    bzr = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'imag')

    freqs = np.logspace(2, 3, 5)
    srcLoc = np.array([0., 0., 0.])

    print('min skin depth = ', 500./np.sqrt(freqs.max() * sig_half),
          'max skin depth = ', 500./np.sqrt(freqs.min() * sig_half))
    print('max x ', mesh.vectorCCx.max(), 'min z ', mesh.vectorCCz.min(),
          'max z ', mesh.vectorCCz.max())

    srcList = []
    [srcList.append(FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc,
                                       orientation='Z')) for freq in freqs]

    surveyFD = FDEM.Survey(srcList)
    prbFD = FDEM.Problem3D_b(mesh, mapping=mapping)
    prbFD.pair(surveyFD)
    std = 0.03
    surveyFD.makeSyntheticData(mtrue, std)
    surveyFD.eps = np.linalg.norm(surveyFD.dtrue)*1e-5

    # FDEM inversion
    np.random.seed(1)
    dmisfit = DataMisfit.l2_DataMisfit(surveyFD)
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh)
    opt = Optimization.InexactGaussNewton(maxIterCG=10)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    # Inversion Directives
    beta = Directives.BetaSchedule(coolingFactor=4, coolingRate=3)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.)
    target = Directives.TargetMisfit()

    inv = Inversion.BaseInversion(invProb, directiveList=[beta, betaest, target])
    m0 = np.log(np.ones(mtrue.size)*sig_half)
    reg.alpha_s = 5e-1
    reg.alpha_x = 1.
    prbFD.counter = opt.counter = Utils.Counter()
    opt.remember('xc')
    moptFD = inv.run(m0)

    # TDEM problem
    times = np.logspace(-4, np.log10(2e-3), 10)
    print('min diffusion distance ', 1.28*np.sqrt(times.min()/(sig_half*mu_0)),
          'max diffusion distance ', 1.28*np.sqrt(times.max()/(sig_half*mu_0)))
    rx = TDEM.Rx(rxlocs, times, 'bz')
    src = TDEM.Src.MagDipole([rx], waveform=TDEM.Src.StepOffWaveform(),
                             loc=srcLoc)  # same src location as FDEM problem

    surveyTD = TDEM.Survey([src])
    prbTD = TDEM.Problem3D_b(mesh, mapping=mapping)
    prbTD.timeSteps = [(5e-5, 10), (1e-4, 10), (5e-4, 10)]
    prbTD.pair(surveyTD)
    prbTD.Solver = SolverLU

    std = 0.03
    surveyTD.makeSyntheticData(mtrue, std)
    surveyTD.std = std
    surveyTD.eps = np.linalg.norm(surveyTD.dtrue)*1e-5

    # TDEM inversion
    dmisfit = DataMisfit.l2_DataMisfit(surveyTD)
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh)
    opt = Optimization.InexactGaussNewton(maxIterCG=10)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    # Inversion Directives
    beta = Directives.BetaSchedule(coolingFactor=4, coolingRate=3)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.)
    target = Directives.TargetMisfit()

    inv = Inversion.BaseInversion(invProb, directiveList=[beta, betaest, target])
    m0 = np.log(np.ones(mtrue.size)*sig_half)
    reg.alpha_s = 5e-1
    reg.alpha_x = 1.
    prbTD.counter = opt.counter = Utils.Counter()
    opt.remember('xc')
    moptTD = inv.run(m0)

    if plotIt:
        import matplotlib
        fig = plt.figure(figsize = (10, 8))
        ax0 = plt.subplot2grid((2, 2), (0, 0), rowspan=2)
        ax1 = plt.subplot2grid((2, 2), (0, 1))
        ax2 = plt.subplot2grid((2, 2), (1, 1))

        fs = 13  # fontsize
        matplotlib.rcParams['font.size'] = fs

        # Plot the model
        ax0.semilogx(sigma[active], mesh.vectorCCz[active], 'k-', lw=2)
        ax0.semilogx(np.exp(moptFD), mesh.vectorCCz[active], 'bo', ms=6)
        ax0.semilogx(np.exp(moptTD), mesh.vectorCCz[active], 'r*', ms=10)
        ax0.set_ylim(-700, 0)
        ax0.set_xlim(5e-3, 1e-1)

        ax0.set_xlabel('Conductivity (S/m)', fontsize=fs)
        ax0.set_ylabel('Depth (m)', fontsize=fs)
        ax0.grid(which='both', color='k', alpha=0.5, linestyle='-',
                 linewidth=0.2)
        ax0.legend(['True', 'FDEM', 'TDEM'], fontsize=fs, loc=4)

        # plot the data misfits - negative b/c we choose positive to be in the
        # direction of primary

        ax1.plot(freqs, -surveyFD.dobs[::2], 'k-', lw=2)
        ax1.plot(freqs, -surveyFD.dobs[1::2], 'k--', lw=2)

        dpredFD = surveyFD.dpred(moptTD)
        ax1.loglog(freqs, -dpredFD[::2], 'bo', ms=6)
        ax1.loglog(freqs, -dpredFD[1::2], 'b+', markeredgewidth=2., ms=10)

        ax2.loglog(times, surveyTD.dobs, 'k-', lw=2)
        ax2.loglog(times, surveyTD.dpred(moptTD), 'r*', ms=10)
        ax2.set_xlim(times.min(), times.max())

        # Labels, gridlines, etc
        ax2.grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2)
        ax1.grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2)

        ax1.set_xlabel('Frequency (Hz)', fontsize=fs)
        ax1.set_ylabel('Vertical magnetic field (-T)', fontsize=fs)

        ax2.set_xlabel('Time (s)', fontsize=fs)
        ax2.set_ylabel('Vertical magnetic field (-T)', fontsize=fs)

        ax2.legend(("Obs", "Pred"), fontsize=fs)
        ax1.legend(("Obs (real)", "Obs (imag)", "Pred (real)", "Pred (imag)"),
                   fontsize=fs)
        ax1.set_xlim(freqs.max(), freqs.min())

        ax0.set_title("(a) Recovered Models", fontsize=fs)
        ax1.set_title("(b) FDEM observed vs. predicted", fontsize=fs)
        ax2.set_title("(c) TDEM observed vs. predicted", fontsize=fs)

        plt.tight_layout(pad=1.5)
        plt.show()
Example #20
0
def MagneticDipoleVectorPotential(srcLoc, obsLoc, component, moment=1.,
                                  orientation=np.r_[0., 0., 1.],
                                  mu=mu_0):
    """
        Calculate the vector potential of a set of magnetic dipoles
        at given locations 'ref. <http://en.wikipedia.org/wiki/Dipole#Magnetic_vector_potential>'

        :param numpy.ndarray srcLoc: Location of the source(s) (x, y, z)
        :param numpy.ndarray,SimPEG.Mesh obsLoc: Where the potentials will be
                                                 calculated (x, y, z) or a
                                                 SimPEG Mesh
        :param str,list component: The component to calculate - 'x', 'y', or
                                   'z' if an array, or grid type if mesh, can
                                   be a list
        :param numpy.ndarray orientation: The vector dipole moment
        :rtype: numpy.ndarray
        :return: The vector potential each dipole at each observation location
    """
    # TODO: break this out!

    if isinstance(orientation, str):
        orientation = orientationDict[orientation]

    assert np.linalg.norm(np.array(orientation), 2) == 1., ("orientation must "
                                                            "be a unit vector")

    if type(component) in [list, tuple]:
        out = range(len(component))
        for i, comp in enumerate(component):
            out[i] = MagneticDipoleVectorPotential(srcLoc, obsLoc, comp,
                                                   orientation=orientation,
                                                   mu=mu)
        return np.concatenate(out)

    if isinstance(obsLoc, Mesh.BaseMesh):
        mesh = obsLoc
        assert component in ['Ex', 'Ey', 'Ez', 'Fx', 'Fy', 'Fz'], ("Components"
                                 "must be in: ['Ex','Ey','Ez','Fx','Fy','Fz']")
        return MagneticDipoleVectorPotential(srcLoc, getattr(mesh, 'grid' +
                                                             component),
                                             component[1],
                                             orientation=orientation)

    if component == 'x':
        dimInd = 0
    elif component == 'y':
        dimInd = 1
    elif component == 'z':
        dimInd = 2
    else:
        raise ValueError('Invalid component')

    srcLoc = np.atleast_2d(srcLoc)
    obsLoc = np.atleast_2d(obsLoc)
    orientation = np.atleast_2d(orientation)

    nObs = obsLoc.shape[0]
    nSrc = srcLoc.shape[0]

    m = moment*np.array(orientation).repeat(nObs, axis=0)
    A = np.empty((nObs, nSrc))
    for i in range(nSrc):
        dR = obsLoc - srcLoc[i, np.newaxis].repeat(nObs, axis=0)
        mCr = np.cross(m, dR)
        r = np.sqrt((dR**2).sum(axis=1))
        A[:, i] = +(mu/(4*np.pi)) * mCr[:, dimInd]/(r**3)
    if nSrc == 1:
        return A.flatten()
    return A
Example #21
0
def gen_DCIPsurvey(endl, mesh, stype, a, b, n):
    """
        Load in endpoints and survey specifications to generate Tx, Rx location
        stations.

        Assumes flat topo for now...

        Input:
        :param endl -> input endpoints [x1, y1, z1, x2, y2, z2]
        :object mesh -> SimPEG mesh object
        :switch stype -> "dpdp" (dipole-dipole) | "pdp" (pole-dipole) | 'gradient'
        : param a, n -> pole seperation, number of rx dipoles per tx

        Output:
        :param Tx, Rx -> List objects for each tx location
            Lines: P1x, P1y, P1z, P2x, P2y, P2z

        Created on Wed December 9th, 2015

        @author: dominiquef
        !! Require clean up to deal with DCsurvey
    """

    from SimPEG import np

    def xy_2_r(x1,x2,y1,y2):
        r = np.sqrt( np.sum((x2 - x1)**2 + (y2 - y1)**2) )
        return r

    ## Evenly distribute electrodes and put on surface
    # Mesure survey length and direction
    dl_len = xy_2_r(endl[0,0],endl[1,0],endl[0,1],endl[1,1])

    dl_x = ( endl[1,0] - endl[0,0] ) / dl_len
    dl_y = ( endl[1,1] - endl[0,1] ) / dl_len

    nstn = np.floor( dl_len / a )

    # Compute discrete pole location along line
    stn_x = endl[0,0] + np.array(range(int(nstn)))*dl_x*a
    stn_y = endl[0,1] + np.array(range(int(nstn)))*dl_y*a

    if mesh.dim==2:
        ztop = mesh.vectorNy[-1]
        # Create line of P1 locations
        M = np.c_[stn_x, np.ones(nstn).T*ztop]
        # Create line of P2 locations
        N = np.c_[stn_x+a*dl_x, np.ones(nstn).T*ztop]

    elif mesh.dim==3:
        ztop = mesh.vectorNz[-1]
        # Create line of P1 locations
        M = np.c_[stn_x, stn_y, np.ones(nstn).T*ztop]
        # Create line of P2 locations
        N = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*ztop]


    ## Build list of Tx-Rx locations depending on survey type
    # Dipole-dipole: Moving tx with [a] spacing -> [AB a MN1 a MN2 ... a MNn]
    # Pole-dipole: Moving pole on one end -> [A a MN1 a MN2 ... MNn a B]
    SrcList = []


    if stype != 'gradient':

        for ii in range(0, int(nstn)-1):


            if stype == 'dipole-dipole':
                tx = np.c_[M[ii,:],N[ii,:]]
            elif stype == 'pole-dipole':
                tx = np.c_[M[ii,:],M[ii,:]]
            else:
                raise Exception('The stype must be "dipole-dipole" or "pole-dipole"')

            # Rx.append(np.c_[M[ii+1:indx,:],N[ii+1:indx,:]])

            # Current elctrode seperation
            AB = xy_2_r(tx[0,1],endl[1,0],tx[1,1],endl[1,1])

            # Number of receivers to fit
            nstn = np.min([np.floor( (AB - b) / a ) , n])

            # Check if there is enough space, else break the loop
            if nstn <= 0:
                continue

            # Compute discrete pole location along line
            stn_x = N[ii,0] + dl_x*b + np.array(range(int(nstn)))*dl_x*a
            stn_y = N[ii,1] + dl_y*b + np.array(range(int(nstn)))*dl_y*a

            # Create receiver poles

            if mesh.dim==3:
                # Create line of P1 locations
                P1 = np.c_[stn_x, stn_y, np.ones(nstn).T*ztop]
                # Create line of P2 locations
                P2 = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*ztop]
                rxClass = DC.Rx.Dipole(P1, P2)

            elif mesh.dim==2:
                # Create line of P1 locations
                P1 = np.c_[stn_x, np.ones(nstn).T*ztop]
                # Create line of P2 locations
                P2 = np.c_[stn_x+a*dl_x, np.ones(nstn).T*ztop]
                rxClass = DC.Rx.Dipole_ky(P1, P2)

            if stype == 'dipole-dipole':
                srcClass = DC.Src.Dipole([rxClass], M[ii,:],N[ii,:])
            elif stype == 'pole-dipole':
                srcClass = DC.Src.Pole([rxClass], M[ii,:])
            SrcList.append(srcClass)

    elif stype == 'gradient':

        # Gradient survey only requires Tx at end of line and creates a square
        # grid of receivers at in the middle at a pre-set minimum distance

        # Get the edge limit of survey area
        min_x = endl[0,0] + dl_x * b
        min_y = endl[0,1] + dl_y * b

        max_x = endl[1,0] - dl_x * b
        max_y = endl[1,1] - dl_y * b

        box_l = np.sqrt( (min_x - max_x)**2 + (min_y - max_y)**2 )
        box_w = box_l/2.

        nstn = np.floor( box_l / a )

        # Compute discrete pole location along line
        stn_x = min_x + np.array(range(int(nstn)))*dl_x*a
        stn_y = min_y + np.array(range(int(nstn)))*dl_y*a

        # Define number of cross lines
        nlin = int(np.floor( box_w / a ))
        lind = list(range(-nlin,nlin+1))

        ngrad = nstn * len(lind)

        rx = np.zeros([ngrad,6])
        for ii in range( len(lind) ):

            # Move line in perpendicular direction by dipole spacing
            lxx = stn_x - lind[ii]*a*dl_y
            lyy = stn_y + lind[ii]*a*dl_x


            M = np.c_[ lxx, lyy , np.ones(nstn).T*ztop]
            N = np.c_[ lxx+a*dl_x, lyy+a*dl_y, np.ones(nstn).T*ztop]
            rx[(ii*nstn):((ii+1)*nstn),:] = np.c_[M,N]

            if mesh.dim==3:
                rxClass = DC.Rx.Dipole(rx[:,:3], rx[:,3:])
            elif mesh.dim==2:
                M = M[:,[0,2]]
                N = N[:,[0,2]]
                rxClass = DC.Rx.Dipole_ky(rx[:,[0,2]], rx[:,[3,5]])
            srcClass = DC.Src.Dipole([rxClass], M[0,:], N[-1,:])
        SrcList.append(srcClass)
    else:
        print("""stype must be either 'pole-dipole', 'dipole-dipole' or 'gradient'. """)


    return SrcList
Example #22
0
def run(plotIt=True):
    """
    1D FDEM Mu Inversion
    ====================

    1D inversion of Magnetic Susceptibility from FDEM data assuming a fixed
    electrical conductivity

    """

    # Set up cylindrically symmeric mesh
    cs, ncx, ncz, npad = 10., 15, 25, 13  # padded cyl mesh
    hx = [(cs, ncx), (cs, npad, 1.3)]
    hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)]
    mesh = Mesh.CylMesh([hx, 1, hz], '00C')

    # Geologic Parameters model
    layerz = np.r_[-100., -50.]
    layer = (mesh.vectorCCz >= layerz[0]) & (mesh.vectorCCz <= layerz[1])
    active = mesh.vectorCCz < 0.

    # Electrical Conductivity
    sig_half = 1e-2  # Half-space conductivity
    sig_air = 1e-8  # Air conductivity
    sig_layer = 1e-2  # Layer conductivity
    sigma = np.ones(mesh.nCz) * sig_air
    sigma[active] = sig_half
    sigma[layer] = sig_layer

    # mur - relative magnetic permeability
    mur_half = 1.
    mur_air = 1.
    mur_layer = 2.
    mur = np.ones(mesh.nCz) * mur_air
    mur[active] = mur_half
    mur[layer] = mur_layer

    mtrue = mur[active]

    # Maps
    actMap = Maps.InjectActiveCells(mesh, active, mur_air, nC=mesh.nCz)
    surj1Dmap = Maps.SurjectVertical1D(mesh)
    murMap = Maps.MuRelative(mesh)

    # Mapping
    muMap = murMap * surj1Dmap * actMap

    # ----- FDEM problem & survey -----
    rxlocs = Utils.ndgrid([np.r_[10.], np.r_[0], np.r_[30.]])
    bzr = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'real')
    # bzi = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'imag')

    freqs = np.linspace(2000, 10000, 10)  #np.logspace(3, 4, 10)
    srcLoc = np.array([0., 0., 30.])

    print('min skin depth = ', 500. / np.sqrt(freqs.max() * sig_half),
          'max skin depth = ', 500. / np.sqrt(freqs.min() * sig_half))
    print('max x ', mesh.vectorCCx.max(), 'min z ', mesh.vectorCCz.min(),
          'max z ', mesh.vectorCCz.max())

    srcList = [
        FDEM.Src.MagDipole([bzr], freq, srcLoc, orientation='Z')
        for freq in freqs
    ]

    surveyFD = FDEM.Survey(srcList)
    prbFD = FDEM.Problem3D_b(mesh,
                             sigma=surj1Dmap * sigma,
                             muMap=muMap,
                             Solver=Solver)
    prbFD.pair(surveyFD)
    std = 0.03
    surveyFD.makeSyntheticData(mtrue, std)
    surveyFD.eps = np.linalg.norm(surveyFD.dtrue) * 1e-6

    # FDEM inversion
    np.random.seed(13472)
    dmisfit = DataMisfit.l2_DataMisfit(surveyFD)
    regMesh = Mesh.TensorMesh([mesh.hz[muMap.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh)
    opt = Optimization.InexactGaussNewton(maxIterCG=10)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    # Inversion Directives    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.)

    beta = Directives.BetaSchedule(coolingFactor=4, coolingRate=3)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.)
    target = Directives.TargetMisfit()
    directiveList = [beta, betaest, target]

    inv = Inversion.BaseInversion(invProb, directiveList=directiveList)
    m0 = mur_half * np.ones(mtrue.size)
    reg.alpha_s = 2e-2
    reg.alpha_x = 1.
    prbFD.counter = opt.counter = Utils.Counter()
    opt.remember('xc')
    moptFD = inv.run(m0)

    dpredFD = surveyFD.dpred(moptFD)

    if plotIt:
        fig, ax = plt.subplots(1, 3, figsize=(10, 6))

        fs = 13  # fontsize
        matplotlib.rcParams['font.size'] = fs

        # Plot the conductivity model
        ax[0].semilogx(sigma[active], mesh.vectorCCz[active], 'k-', lw=2)
        ax[0].set_ylim(-500, 0)
        ax[0].set_xlim(5e-3, 1e-1)

        ax[0].set_xlabel('Conductivity (S/m)', fontsize=fs)
        ax[0].set_ylabel('Depth (m)', fontsize=fs)
        ax[0].grid(which='both',
                   color='k',
                   alpha=0.5,
                   linestyle='-',
                   linewidth=0.2)
        ax[0].legend(['Conductivity Model'], fontsize=fs, loc=4)

        # Plot the permeability model
        ax[1].plot(mur[active], mesh.vectorCCz[active], 'k-', lw=2)
        ax[1].plot(moptFD, mesh.vectorCCz[active], 'b-', lw=2)
        ax[1].set_ylim(-500, 0)
        ax[1].set_xlim(0.5, 2.1)

        ax[1].set_xlabel('Relative Permeability', fontsize=fs)
        ax[1].set_ylabel('Depth (m)', fontsize=fs)
        ax[1].grid(which='both',
                   color='k',
                   alpha=0.5,
                   linestyle='-',
                   linewidth=0.2)
        ax[1].legend(['True', 'Predicted'], fontsize=fs, loc=4)

        # plot the data misfits - negative b/c we choose positive to be in the
        # direction of primary

        ax[2].plot(freqs, -surveyFD.dobs, 'k-', lw=2)
        # ax[2].plot(freqs, -surveyFD.dobs[1::2], 'k--', lw=2)

        ax[2].loglog(freqs, -dpredFD, 'bo', ms=6)
        # ax[2].loglog(freqs, -dpredFD[1::2], 'b+', markeredgewidth=2., ms=10)

        # Labels, gridlines, etc
        ax[2].grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2)
        ax[2].grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2)

        ax[2].set_xlabel('Frequency (Hz)', fontsize=fs)
        ax[2].set_ylabel('Vertical magnetic field (-T)', fontsize=fs)

        # ax[2].legend(("Obs", "Pred"), fontsize=fs)
        ax[2].legend(("z-Obs (real)", "z-Pred (real)"), fontsize=fs)
        ax[2].set_xlim(freqs.max(), freqs.min())

        ax[0].set_title("(a) Conductivity Model", fontsize=fs)
        ax[1].set_title("(b) $\mu_r$ Model", fontsize=fs)
        ax[2].set_title("(c) FDEM observed vs. predicted", fontsize=fs)
        # ax[2].set_title("(c) TDEM observed vs. predicted", fontsize=fs)

        plt.tight_layout(pad=1.5)
Example #23
0
def getKc(freq,sigma,a,b,mu=mu_0,eps=epsilon_0):
    a = float(a)
    b = float(b)
    # return 1./(2*np.pi) * np.sqrt(b / a) * np.exp(-1j*k(freq,sigma,mu,eps)*(b-a))
    return np.sqrt(b / a) * np.exp(-1j*k(freq,sigma,mu,eps)*(b-a))
Example #24
0
 def xy_2_r(x1, x2, y1, y2):
     r = np.sqrt(np.sum((x2 - x1)**2 + (y2 - y1)**2))
     return r
Example #25
0
ylim = (546000, 546750)
xlim = (422900, 423675)
# Takes two points from ginput and create survey
temp = plt.ginput(2)

# Add z coordinate
nz = mesh.vectorNz
endp = np.c_[np.asarray(temp), np.ones(2).T * nz[-1]]

# Create dipole survey receivers and plot
nrx = 10
ab = 40
a = 20

# Evenly distribute transmitters for now and put on surface
dplen = np.sqrt(np.sum((endp[1, :] - endp[0, :])**2))
dp_x = (endp[1, 0] - endp[0, 0]) / dplen
dp_y = (endp[1, 1] - endp[0, 1]) / dplen

nstn = np.floor(dplen / ab)

stn_x = endp[0, 0] + np.cumsum(np.ones(nstn) * dp_x * ab)
stn_y = endp[0, 1] + np.cumsum(np.ones(nstn) * dp_y * ab)

plt.scatter(stn_x, stn_y, s=100, c='w')

M = np.c_[stn_x - a * dp_x, stn_y - a * dp_y, np.ones(nstn).T * nz[-1]]
N = np.c_[stn_x + a * dp_x, stn_y + a * dp_y, np.ones(nstn).T * nz[-1]]

plt.scatter(M[:, 0], M[:, 1], s=10, c='r')
plt.scatter(N[:, 0], N[:, 1], s=10, c='b')
Example #26
0
def MagneticDipoleVectorPotential(srcLoc, obsLoc, component, moment=1.,
                                  orientation=np.r_[0., 0., 1.],
                                  mu=mu_0):
    """
        Calculate the vector potential of a set of magnetic dipoles
        at given locations 'ref. <http://en.wikipedia.org/wiki/Dipole#Magnetic_vector_potential>'

        :param numpy.ndarray srcLoc: Location of the source(s) (x, y, z)
        :param numpy.ndarray,SimPEG.Mesh obsLoc: Where the potentials will be
                                                 calculated (x, y, z) or a
                                                 SimPEG Mesh
        :param str,list component: The component to calculate - 'x', 'y', or
                                   'z' if an array, or grid type if mesh, can
                                   be a list
        :param numpy.ndarray orientation: The vector dipole moment
        :rtype: numpy.ndarray
        :return: The vector potential each dipole at each observation location
    """
    # TODO: break this out!

    if isinstance(orientation, str):
        orientation = orientationDict[orientation]

    assert np.linalg.norm(np.array(orientation), 2) == 1., ("orientation must "
                                                            "be a unit vector")

    if type(component) in [list, tuple]:
        out = list(range(len(component)))
        for i, comp in enumerate(component):
            out[i] = MagneticDipoleVectorPotential(srcLoc, obsLoc, comp,
                                                   orientation=orientation,
                                                   mu=mu)
        return np.concatenate(out)

    if isinstance(obsLoc, Mesh.BaseMesh):
        mesh = obsLoc
        assert component in ['Ex', 'Ey', 'Ez', 'Fx', 'Fy', 'Fz'], ("Components"
                                 "must be in: ['Ex','Ey','Ez','Fx','Fy','Fz']")
        return MagneticDipoleVectorPotential(srcLoc, getattr(mesh, 'grid' +
                                                             component),
                                             component[1],
                                             orientation=orientation)

    if component == 'x':
        dimInd = 0
    elif component == 'y':
        dimInd = 1
    elif component == 'z':
        dimInd = 2
    else:
        raise ValueError('Invalid component')

    srcLoc = np.atleast_2d(srcLoc)
    obsLoc = np.atleast_2d(obsLoc)
    orientation = np.atleast_2d(orientation)

    nObs = obsLoc.shape[0]
    nSrc = srcLoc.shape[0]

    m = moment*np.array(orientation).repeat(nObs, axis=0)
    A = np.empty((nObs, nSrc))
    for i in range(nSrc):
        dR = obsLoc - srcLoc[i, np.newaxis].repeat(nObs, axis=0)
        mCr = np.cross(m, dR)
        r = np.sqrt((dR**2).sum(axis=1))
        A[:, i] = +(mu/(4*np.pi)) * mCr[:, dimInd]/(r**3)
    if nSrc == 1:
        return A.flatten()
    return A
Example #27
0
def MagneticDipoleFields(srcLoc, obsLoc, component,
                         orientation='Z', moment=1., mu=mu_0):
    """
        Calculate the vector potential of a set of magnetic dipoles
        at given locations 'ref. <http://en.wikipedia.org/wiki/Dipole#Magnetic_vector_potential>'

        .. math::

            B = \frac{\mu_0}{4 \pi r^3} \left( \frac{3 \vec{r} (\vec{m} \cdot
                                                                \vec{r})}{r^2})
                                                - \vec{m}
                                        \right) \cdot{\hat{rx}}

        :param numpy.ndarray srcLoc: Location of the source(s) (x, y, z)
        :param numpy.ndarray obsLoc: Where the potentials will be calculated
                                     (x, y, z)
        :param str component: The component to calculate - 'x', 'y', or 'z'
        :param numpy.ndarray moment: The vector dipole moment (vertical)
        :rtype: numpy.ndarray
        :return: The vector potential each dipole at each observation location
    """

    if isinstance(orientation, str):
        assert orientation.upper() in ['X', 'Y', 'Z'], ("orientation must be 'x', "
                                                      "'y', or 'z' or a vector"
                                                      "not {}".format(orientation)
                                                      )
    elif (not np.allclose(np.r_[1., 0., 0.], orientation) or
          not np.allclose(np.r_[0., 1., 0.], orientation) or
          not np.allclose(np.r_[0., 0., 1.], orientation)):
        warnings.warn('Arbitrary trasnmitter orientations ({}) not thouroughly tested '
                      'Pull request on a test anyone? bueller?').format(orientation)

    if isinstance(component, str):
        assert component.upper() in ['X', 'Y', 'Z'], ("component must be 'x', "
                                                      "'y', or 'z' or a vector"
                                                      "not {}".format(component)
                                                      )
    elif (not np.allclose(np.r_[1., 0., 0.], component) or
          not np.allclose(np.r_[0., 1., 0.], component) or
          not np.allclose(np.r_[0., 0., 1.], component)):
        warnings.warn('Arbitrary receiver orientations ({}) not thouroughly tested '
                      'Pull request on a test anyone? bueller?').format(component)

    if isinstance(orientation, str):
        orientation = orientationDict[orientation.upper()]

    if isinstance(component, str):
        component = orientationDict[component.upper()]

    assert np.linalg.norm(orientation, 2) == 1., ('orientation must be a unit '
                                                  'vector. Use "moment=X to '
                                                  'scale source fields')

    if np.linalg.norm(component, 2) != 1.:
        warnings.warn('The magnitude of the receiver component vector is > 1, '
                      ' it is {}. The receiver fields will be scaled.'
                      ).format(np.linalg.norm(component, 2))

    srcLoc = np.atleast_2d(srcLoc)
    component = np.atleast_2d(component)
    obsLoc = np.atleast_2d(obsLoc)
    orientation = np.atleast_2d(orientation)

    nObs = obsLoc.shape[0]
    nSrc = int(srcLoc.size / 3.)

    # use outer product to construct an array of [x_src, y_src, z_src]

    m = moment*orientation.repeat(nObs, axis=0)
    B = []

    for i in range(nSrc):
        srcLoc = srcLoc[i, np.newaxis].repeat(nObs, axis=0)
        rx = component.repeat(nObs, axis=0)
        dR = obsLoc - srcLoc
        r = np.sqrt((dR**2).sum(axis=1))

        # mult each element and sum along the axis (vector dot product)
        m_dot_dR_div_r2 = (m * dR).sum(axis=1) / (r**2)

        # multiply the scalar m_dot_dR by the 3D vector r
        rvec_m_dot_dR_div_r2 = np.vstack([m_dot_dR_div_r2 * dR[:, i] for
                                          i in range(3)]).T
        inside = (3. * rvec_m_dot_dR_div_r2) - m

        # dot product with rx orientation
        inside_dot_rx = (inside * rx).sum(axis=1)
        front = (mu/(4.* np.pi * r**3))

        B.append(Utils.mkvc(front * inside_dot_rx))

    return np.vstack(B).T
Example #28
0
def MagneticLoopVectorPotential(srcLoc, obsLoc, component, radius, orientation='Z', mu=mu_0):
    """
        Calculate the vector potential of horizontal circular loop
        at given locations

        :param numpy.ndarray srcLoc: Location of the source(s) (x, y, z)
        :param numpy.ndarray,SimPEG.Mesh obsLoc: Where the potentials will be calculated (x, y, z) or a SimPEG Mesh
        :param str,list component: The component to calculate - 'x', 'y', or 'z' if an array, or grid type if mesh, can be a list
        :param numpy.ndarray I: Input current of the loop
        :param numpy.ndarray radius: radius of the loop
        :rtype: numpy.ndarray
        :return: The vector potential each dipole at each observation location
    """

    if isinstance(orientation, str):
        if orientation.upper() != 'Z':
            raise NotImplementedError('Only Z oriented loops implemented')
    elif not np.allclose(orientation, np.r_[0., 0., 1.]):
        raise NotImplementedError('Only Z oriented loops implemented')

    if type(component) in [list, tuple]:
        out = list(range(len(component)))
        for i, comp in enumerate(component):
            out[i] = MagneticLoopVectorPotential(srcLoc, obsLoc, comp, radius,
                                                 orientation, mu)
        return np.concatenate(out)

    if isinstance(obsLoc, Mesh.BaseMesh):
        mesh = obsLoc
        assert component in ['Ex','Ey','Ez','Fx','Fy','Fz'], "Components must be in: ['Ex','Ey','Ez','Fx','Fy','Fz']"
        return MagneticLoopVectorPotential(srcLoc, getattr(mesh,'grid'+component), component[1], radius, mu)

    srcLoc = np.atleast_2d(srcLoc)
    obsLoc = np.atleast_2d(obsLoc)

    n = obsLoc.shape[0]
    nSrc = srcLoc.shape[0]

    if component=='z':
        A = np.zeros((n, nSrc))
        if nSrc ==1:
            return A.flatten()
        return A

    else:

        A = np.zeros((n, nSrc))
        for i in range (nSrc):
            x = obsLoc[:, 0] - srcLoc[i, 0]
            y = obsLoc[:, 1] - srcLoc[i, 1]
            z = obsLoc[:, 2] - srcLoc[i, 2]
            r = np.sqrt(x**2 + y**2)
            m = (4 * radius * r) / ((radius + r)**2 + z**2)
            m[m > 1.] = 1.
            # m might be slightly larger than 1 due to rounding errors
            # but ellipke requires 0 <= m <= 1
            K = ellipk(m)
            E = ellipe(m)
            ind = (r > 0) & (m < 1)
            # % 1/r singular at r = 0 and K(m) singular at m = 1
            Aphi = np.zeros(n)
            # % Common factor is (mu * I) / pi with I = 1 and mu = 4e-7 * pi.
            Aphi[ind] = ((mu / (np.pi * np.sqrt(m[ind])) *
                         np.sqrt(radius / r[ind]) *((1. - m[ind] / 2.) *
                         K[ind] - E[ind])))
            if component == 'x':
                A[ind, i] = Aphi[ind] * (-y[ind] / r[ind] )
            elif component == 'y':
                A[ind, i] = Aphi[ind] * ( x[ind] / r[ind] )
            else:
                raise ValueError('Invalid component')

        if nSrc == 1:
            return A.flatten()
        return A
Example #29
0
# if not gin:
#     print 'SimPED - Simulation has ended with return'
#     break
#==============================================================================

# Add z coordinate to all survey... assume flat
nz = mesh.vectorNz
var = np.c_[np.asarray(gin),np.ones(2).T*nz[-1]]

# Snap the endpoints to the grid. Easier to create 2D section.
indx = Utils.closestPoints(mesh, var )
endl = np.c_[mesh.gridCC[indx,0],mesh.gridCC[indx,1],np.ones(2).T*nz[-1]]
      
[Tx, Rx] = DC.gen_DCIPsurvey(endl, mesh, stype, a, b, n)
 
dl_len = np.sqrt( np.sum((endl[0,:] - endl[1,:])**2) ) 
dl_x = ( Tx[-1][0,1] - Tx[0][0,0] ) / dl_len
dl_y = ( Tx[-1][1,1] - Tx[0][1,0]  ) / dl_len
azm =  np.arctan(dl_y/dl_x)
  
# Plot stations along line   
plt.scatter(Tx[0][0,:],Tx[0][1,:],s=20,c='g')
plt.scatter(Rx[0][:,0::3],Rx[0][:,1::3],s=20,c='y')

#%% Forward model data
data = []#np.zeros( nstn*nrx )
unct = []
problem = DC.ProblemDC_CC(mesh)
    
for ii in range(len(Tx)):
    start_time = time.time()
def run(loc=None, sig=None, radi=None, param=None, stype='dpdp', plotIt=True):
    """
        DC Forward Simulation
        =====================

        Forward model conductive spheres in a half-space and plot a pseudo-section

        Created by @fourndo on Mon Feb 01 19:28:06 2016

    """

    assert stype in ['pdp', 'dpdp'], "Source type (stype) must be pdp or dpdp (pole dipole or dipole dipole)"


    if loc is None:
        loc = np.c_[[-50.,0.,-50.],[50.,0.,-50.]]
    if sig is None:
        sig = np.r_[1e-2,1e-1,1e-3]
    if radi is None:
        radi = np.r_[25.,25.]
    if param is None:
        param = np.r_[30.,30.,5]


    # First we need to create a mesh and a model.

    # This is our mesh
    dx    = 5.

    hxind = [(dx,15,-1.3), (dx, 75), (dx,15,1.3)]
    hyind = [(dx,15,-1.3), (dx, 10), (dx,15,1.3)]
    hzind = [(dx,15,-1.3),(dx, 15)]

    mesh = Mesh.TensorMesh([hxind, hyind, hzind], 'CCN')


    # Set background conductivity
    model = np.ones(mesh.nC) * sig[0]

    # First anomaly
    ind = Utils.ModelBuilder.getIndicesSphere(loc[:,0],radi[0],mesh.gridCC)
    model[ind] = sig[1]

    # Second anomaly
    ind = Utils.ModelBuilder.getIndicesSphere(loc[:,1],radi[1],mesh.gridCC)
    model[ind] = sig[2]

    # Get index of the center
    indy = int(mesh.nCy/2)


    # Plot the model for reference
    # Define core mesh extent
    xlim = 200
    zlim = 125

    # Specify the survey type: "pdp" | "dpdp"


    # Then specify the end points of the survey. Let's keep it simple for now and survey above the anomalies, top of the mesh
    ends = [(-175,0),(175,0)]
    ends = np.c_[np.asarray(ends),np.ones(2).T*mesh.vectorNz[-1]]

    # Snap the endpoints to the grid. Easier to create 2D section.
    indx = Utils.closestPoints(mesh, ends )
    locs = np.c_[mesh.gridCC[indx,0],mesh.gridCC[indx,1],np.ones(2).T*mesh.vectorNz[-1]]

    # We will handle the geometry of the survey for you and create all the combination of tx-rx along line
    # [Tx, Rx] = DC.gen_DCIPsurvey(locs, mesh, stype, param[0], param[1], param[2])
    survey, Tx, Rx = DC.gen_DCIPsurvey(locs, mesh, stype, param[0], param[1], param[2])

    # Define some global geometry
    dl_len = np.sqrt( np.sum((locs[0,:] - locs[1,:])**2) )
    dl_x = ( Tx[-1][0,1] - Tx[0][0,0] ) / dl_len
    dl_y = ( Tx[-1][1,1] - Tx[0][1,0]  ) / dl_len
    azm =  np.arctan(dl_y/dl_x)

    #Set boundary conditions
    mesh.setCellGradBC('neumann')

    # Define the differential operators needed for the DC problem
    Div = mesh.faceDiv
    Grad = mesh.cellGrad
    Msig = Utils.sdiag(1./(mesh.aveF2CC.T*(1./model)))

    A = Div*Msig*Grad

    # Change one corner to deal with nullspace
    A[0,0] = 1
    A = sp.csc_matrix(A)

    # We will solve the system iteratively, so a pre-conditioner is helpful
    # This is simply a Jacobi preconditioner (inverse of the main diagonal)
    dA = A.diagonal()
    P = sp.spdiags(1/dA,0,A.shape[0],A.shape[0])

    # Now we can solve the system for all the transmitters
    # We want to store the data
    data = []

    # There is probably a more elegant way to do this, but we can just for-loop through the transmitters
    for ii in range(len(Tx)):

        start_time = time.time() # Let's time the calculations

        #print("Transmitter %i / %i\r" % (ii+1,len(Tx)))

        # Select dipole locations for receiver
        rxloc_M = np.asarray(Rx[ii][:,0:3])
        rxloc_N = np.asarray(Rx[ii][:,3:])


        # For usual cases "dpdp" or "gradient"
        if stype == 'pdp':
            # Create an "inifinity" pole
            tx =  np.squeeze(Tx[ii][:,0:1])
            tinf = tx + np.array([dl_x,dl_y,0])*dl_len*2
            inds = Utils.closestPoints(mesh, np.c_[tx,tinf].T)
            RHS = mesh.getInterpolationMat(np.asarray(Tx[ii]).T, 'CC').T*( [-1] / mesh.vol[inds] )
        else:
            inds = Utils.closestPoints(mesh, np.asarray(Tx[ii]).T )
            RHS = mesh.getInterpolationMat(np.asarray(Tx[ii]).T, 'CC').T*( [-1,1] / mesh.vol[inds] )

        # Iterative Solve
        Ainvb = sp.linalg.bicgstab(P*A,P*RHS, tol=1e-5)

        # We now have the potential everywhere
        phi = Utils.mkvc(Ainvb[0])

        # Solve for phi on pole locations
        P1 = mesh.getInterpolationMat(rxloc_M, 'CC')
        P2 = mesh.getInterpolationMat(rxloc_N, 'CC')

        # Compute the potential difference
        dtemp = (P1*phi - P2*phi)*np.pi

        data.append( dtemp )
        print '\rTransmitter {0} of {1} -> Time:{2} sec'.format(ii,len(Tx),time.time()- start_time),

    print 'Transmitter {0} of {1}'.format(ii,len(Tx))
    print 'Forward completed'

    # Let's just convert the 3D format into 2D (distance along line) and plot
    # [Tx2d, Rx2d] = DC.convertObs_DC3D_to_2D(survey, np.ones(survey.nSrc))
    survey2D = DC.convertObs_DC3D_to_2D(survey, np.ones(survey.nSrc))
    survey2D.dobs =np.hstack(data)
    # Here is an example for the first tx-rx array
    if plotIt:
        import matplotlib.pyplot as plt
        fig = plt.figure()
        ax = plt.subplot(2,1,1, aspect='equal')
        mesh.plotSlice(np.log10(model), ax =ax, normal = 'Y', ind = indy,grid=True)
        ax.set_title('E-W section at '+str(mesh.vectorCCy[indy])+' m')
        plt.gca().set_aspect('equal', adjustable='box')

        plt.scatter(Tx[0][0,:],Tx[0][2,:],s=40,c='g', marker='v')
        plt.scatter(Rx[0][:,0::3],Rx[0][:,2::3],s=40,c='y')
        plt.xlim([-xlim,xlim])
        plt.ylim([-zlim,mesh.vectorNz[-1]+dx])


        ax = plt.subplot(2,1,2, aspect='equal')

        # Plot the location of the spheres for reference
        circle1=plt.Circle((loc[0,0]-Tx[0][0,0],loc[2,0]),radi[0],color='w',fill=False, lw=3)
        circle2=plt.Circle((loc[0,1]-Tx[0][0,0],loc[2,1]),radi[1],color='k',fill=False, lw=3)
        ax.add_artist(circle1)
        ax.add_artist(circle2)

        # Add the speudo section
        DC.plot_pseudoSection(survey2D,ax,stype)

        # plt.scatter(Tx2d[0][:],Tx[0][2,:],s=40,c='g', marker='v')
        # plt.scatter(Rx2d[0][:],Rx[0][:,2::3],s=40,c='y')
        # plt.plot(np.r_[Tx2d[0][0],Rx2d[-1][-1,-1]],np.ones(2)*mesh.vectorNz[-1], color='k')
        plt.ylim([-zlim,mesh.vectorNz[-1]+dx])

        plt.show()

        return fig, ax
def run(plotIt=True):
    """
        1D FDEM and TDEM inversions
        ===========================

        This example is used in the paper Heagy et al 2016 (in prep)

    """

    # Set up cylindrically symmeric mesh
    cs, ncx, ncz, npad = 10., 15, 25, 13  # padded cyl mesh
    hx = [(cs, ncx), (cs, npad, 1.3)]
    hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)]
    mesh = Mesh.CylMesh([hx, 1, hz], '00C')

    # Conductivity model
    layerz = np.r_[-200., -100.]
    layer = (mesh.vectorCCz >= layerz[0]) & (mesh.vectorCCz <= layerz[1])
    active = mesh.vectorCCz < 0.
    sig_half = 1e-2  # Half-space conductivity
    sig_air = 1e-8  # Air conductivity
    sig_layer = 5e-2  # Layer conductivity
    sigma = np.ones(mesh.nCz) * sig_air
    sigma[active] = sig_half
    sigma[layer] = sig_layer

    # Mapping
    actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
    mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap
    mtrue = np.log(sigma[active])

    # ----- FDEM problem & survey -----
    rxlocs = Utils.ndgrid([np.r_[50.], np.r_[0], np.r_[0.]])
    bzi = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'real')
    bzr = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'imag')

    freqs = np.logspace(2, 3, 5)
    srcLoc = np.array([0., 0., 0.])

    print('min skin depth = ', 500. / np.sqrt(freqs.max() * sig_half),
          'max skin depth = ', 500. / np.sqrt(freqs.min() * sig_half))
    print('max x ', mesh.vectorCCx.max(), 'min z ', mesh.vectorCCz.min(),
          'max z ', mesh.vectorCCz.max())

    srcList = [
        FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation='Z')
        for freq in freqs
    ]

    surveyFD = FDEM.Survey(srcList)
    prbFD = FDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=Solver)
    prbFD.pair(surveyFD)
    std = 0.03
    surveyFD.makeSyntheticData(mtrue, std)
    surveyFD.eps = np.linalg.norm(surveyFD.dtrue) * 1e-5

    # FDEM inversion
    np.random.seed(1)
    dmisfit = DataMisfit.l2_DataMisfit(surveyFD)
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh)
    opt = Optimization.InexactGaussNewton(maxIterCG=10)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    # Inversion Directives
    beta = Directives.BetaSchedule(coolingFactor=4, coolingRate=3)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.)
    target = Directives.TargetMisfit()
    directiveList = [beta, betaest, target]

    inv = Inversion.BaseInversion(invProb, directiveList=directiveList)
    m0 = np.log(np.ones(mtrue.size) * sig_half)
    reg.alpha_s = 5e-1
    reg.alpha_x = 1.
    prbFD.counter = opt.counter = Utils.Counter()
    opt.remember('xc')
    moptFD = inv.run(m0)

    # TDEM problem
    times = np.logspace(-4, np.log10(2e-3), 10)
    print('min diffusion distance ',
          1.28 * np.sqrt(times.min() / (sig_half * mu_0)),
          'max diffusion distance ',
          1.28 * np.sqrt(times.max() / (sig_half * mu_0)))
    rx = TDEM.Rx.Point_b(rxlocs, times, 'z')
    src = TDEM.Src.MagDipole(
        [rx],
        waveform=TDEM.Src.StepOffWaveform(),
        loc=srcLoc  # same src location as FDEM problem
    )

    surveyTD = TDEM.Survey([src])
    prbTD = TDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=Solver)
    prbTD.timeSteps = [(5e-5, 10), (1e-4, 10), (5e-4, 10)]
    prbTD.pair(surveyTD)

    std = 0.03
    surveyTD.makeSyntheticData(mtrue, std)
    surveyTD.std = std
    surveyTD.eps = np.linalg.norm(surveyTD.dtrue) * 1e-5

    # TDEM inversion
    dmisfit = DataMisfit.l2_DataMisfit(surveyTD)
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh)
    opt = Optimization.InexactGaussNewton(maxIterCG=10)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    inv = Inversion.BaseInversion(invProb, directiveList=directiveList)
    m0 = np.log(np.ones(mtrue.size) * sig_half)
    reg.alpha_s = 5e-1
    reg.alpha_x = 1.
    prbTD.counter = opt.counter = Utils.Counter()
    opt.remember('xc')
    moptTD = inv.run(m0)

    if plotIt:
        plt.figure(figsize=(10, 8))
        ax0 = plt.subplot2grid((2, 2), (0, 0), rowspan=2)
        ax1 = plt.subplot2grid((2, 2), (0, 1))
        ax2 = plt.subplot2grid((2, 2), (1, 1))

        fs = 13  # fontsize
        matplotlib.rcParams['font.size'] = fs

        # Plot the model
        ax0.semilogx(sigma[active], mesh.vectorCCz[active], 'k-', lw=2)
        ax0.semilogx(np.exp(moptFD), mesh.vectorCCz[active], 'bo', ms=6)
        ax0.semilogx(np.exp(moptTD), mesh.vectorCCz[active], 'r*', ms=10)
        ax0.set_ylim(-700, 0)
        ax0.set_xlim(5e-3, 1e-1)

        ax0.set_xlabel('Conductivity (S/m)', fontsize=fs)
        ax0.set_ylabel('Depth (m)', fontsize=fs)
        ax0.grid(which='both',
                 color='k',
                 alpha=0.5,
                 linestyle='-',
                 linewidth=0.2)
        ax0.legend(['True', 'FDEM', 'TDEM'], fontsize=fs, loc=4)

        # plot the data misfits - negative b/c we choose positive to be in the
        # direction of primary

        ax1.plot(freqs, -surveyFD.dobs[::2], 'k-', lw=2)
        ax1.plot(freqs, -surveyFD.dobs[1::2], 'k--', lw=2)

        dpredFD = surveyFD.dpred(moptTD)
        ax1.loglog(freqs, -dpredFD[::2], 'bo', ms=6)
        ax1.loglog(freqs, -dpredFD[1::2], 'b+', markeredgewidth=2., ms=10)

        ax2.loglog(times, surveyTD.dobs, 'k-', lw=2)
        ax2.loglog(times, surveyTD.dpred(moptTD), 'r*', ms=10)
        ax2.set_xlim(times.min(), times.max())

        # Labels, gridlines, etc
        ax2.grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2)
        ax1.grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2)

        ax1.set_xlabel('Frequency (Hz)', fontsize=fs)
        ax1.set_ylabel('Vertical magnetic field (-T)', fontsize=fs)

        ax2.set_xlabel('Time (s)', fontsize=fs)
        ax2.set_ylabel('Vertical magnetic field (-T)', fontsize=fs)

        ax2.legend(("Obs", "Pred"), fontsize=fs)
        ax1.legend(("Obs (real)", "Obs (imag)", "Pred (real)", "Pred (imag)"),
                   fontsize=fs)
        ax1.set_xlim(freqs.max(), freqs.min())

        ax0.set_title("(a) Recovered Models", fontsize=fs)
        ax1.set_title("(b) FDEM observed vs. predicted", fontsize=fs)
        ax2.set_title("(c) TDEM observed vs. predicted", fontsize=fs)

        plt.tight_layout(pad=1.5)
Example #32
0
dby = d[ndata:2*ndata]
dbz = d[2*ndata:]

# Compute tmi mag data
survey.pair(prob_tmi)
dtmi = prob_tmi.fields(m)

# Compute analytical response from a magnetized sphere
bxa, bya, bza = PF.MagAnalytics.MagSphereFreeSpace(locXyz[:, 0],
                                                   locXyz[:, 1],
                                                   locXyz[:, 2],
                                                   rad, 0, 0, 0,
                                                   chi, b0)

# Projection matrix
Ptmi = mkvc(b0)/np.sqrt(np.sum(b0**2.))

btmi = mkvc(Ptmi.dot(np.vstack((bxa, bya, bza))))

err_xyz = (np.linalg.norm(d-np.r_[bxa, bya, bza]) /
           np.linalg.norm(np.r_[bxa, bya, bza]))

err_tmi = np.linalg.norm(dtmi-btmi)/np.linalg.norm(btmi)

#fig = plt.figure()
#axs = plt.subplot(111)
#mesh.plotSlice(model, normal='Z', ind = mesh.nCz/2, ax= axs)
#axs.set_aspect('equal')

#PF.Magnetics.plot_obs_2D(locXyz,dtmi)
Example #33
0
 def length(self):
     if self.dim == 3: raise Exception('face.length is not defined for 2D face')
     return np.sqrt(((self.node1.x0 - self.node0.x0)**2).sum())
Example #34
0
def MagneticLoopVectorPotential(srcLoc, obsLoc, component, radius, orientation='Z', mu=mu_0):
    """
        Calculate the vector potential of horizontal circular loop
        at given locations

        :param numpy.ndarray srcLoc: Location of the source(s) (x, y, z)
        :param numpy.ndarray,SimPEG.Mesh obsLoc: Where the potentials will be calculated (x, y, z) or a SimPEG Mesh
        :param str,list component: The component to calculate - 'x', 'y', or 'z' if an array, or grid type if mesh, can be a list
        :param numpy.ndarray I: Input current of the loop
        :param numpy.ndarray radius: radius of the loop
        :rtype: numpy.ndarray
        :return: The vector potential each dipole at each observation location
    """

    if isinstance(orientation, str):
        if orientation.upper() != 'Z':
            raise NotImplementedError, 'Only Z oriented loops implemented'
    elif not np.allclose(orientation, np.r_[0., 0., 1.]):
        raise NotImplementedError, 'Only Z oriented loops implemented'

    if type(component) in [list, tuple]:
        out = range(len(component))
        for i, comp in enumerate(component):
            out[i] = MagneticLoopVectorPotential(srcLoc, obsLoc, comp, radius,
                                                 orientation, mu)
        return np.concatenate(out)

    if isinstance(obsLoc, Mesh.BaseMesh):
        mesh = obsLoc
        assert component in ['Ex','Ey','Ez','Fx','Fy','Fz'], "Components must be in: ['Ex','Ey','Ez','Fx','Fy','Fz']"
        return MagneticLoopVectorPotential(srcLoc, getattr(mesh,'grid'+component), component[1], radius, mu)

    srcLoc = np.atleast_2d(srcLoc)
    obsLoc = np.atleast_2d(obsLoc)

    n = obsLoc.shape[0]
    nSrc = srcLoc.shape[0]

    if component=='z':
        A = np.zeros((n, nSrc))
        if nSrc ==1:
            return A.flatten()
        return A

    else:

        A = np.zeros((n, nSrc))
        for i in range (nSrc):
            x = obsLoc[:, 0] - srcLoc[i, 0]
            y = obsLoc[:, 1] - srcLoc[i, 1]
            z = obsLoc[:, 2] - srcLoc[i, 2]
            r = np.sqrt(x**2 + y**2)
            m = (4 * radius * r) / ((radius + r)**2 + z**2)
            m[m > 1.] = 1.
            # m might be slightly larger than 1 due to rounding errors
            # but ellipke requires 0 <= m <= 1
            K = ellipk(m)
            E = ellipe(m)
            ind = (r > 0) & (m < 1)
            # % 1/r singular at r = 0 and K(m) singular at m = 1
            Aphi = np.zeros(n)
            # % Common factor is (mu * I) / pi with I = 1 and mu = 4e-7 * pi.
            Aphi[ind] = ((mu / (np.pi * np.sqrt(m[ind])) *
                         np.sqrt(radius / r[ind]) *((1. - m[ind] / 2.) *
                         K[ind] - E[ind])))
            if component == 'x':
                A[ind, i] = Aphi[ind] * (-y[ind] / r[ind] )
            elif component == 'y':
                A[ind, i] = Aphi[ind] * ( x[ind] / r[ind] )
            else:
                raise ValueError('Invalid component')

        if nSrc == 1:
            return A.flatten()
        return A
Example #35
0
 def length(self):
     return np.sqrt(((self.node1.x0 - self.node0.x0)**2).sum())
Example #36
0
def MagneticDipoleFields(srcLoc, obsLoc, component,
                         orientation='Z', moment=1., mu=mu_0):
    """
        Calculate the vector potential of a set of magnetic dipoles
        at given locations 'ref. <http://en.wikipedia.org/wiki/Dipole#Magnetic_vector_potential>'

        .. math::

            B = \frac{\mu_0}{4 \pi r^3} \left( \frac{3 \vec{r} (\vec{m} \cdot
                                                                \vec{r})}{r^2})
                                                - \vec{m}
                                        \right) \cdot{\hat{rx}}

        :param numpy.ndarray srcLoc: Location of the source(s) (x, y, z)
        :param numpy.ndarray obsLoc: Where the potentials will be calculated
                                     (x, y, z)
        :param str component: The component to calculate - 'x', 'y', or 'z'
        :param numpy.ndarray moment: The vector dipole moment (vertical)
        :rtype: numpy.ndarray
        :return: The vector potential each dipole at each observation location
    """

    if isinstance(orientation, str):
        assert orientation.upper() in ['X', 'Y', 'Z'], ("orientation must be 'x', "
                                                      "'y', or 'z' or a vector"
                                                      "not {}".format(orientation)
                                                      )
    elif (not np.allclose(np.r_[1., 0., 0.], orientation) or
          not np.allclose(np.r_[0., 1., 0.], orientation) or
          not np.allclose(np.r_[0., 0., 1.], orientation)):
        warnings.warn('Arbitrary trasnmitter orientations ({}) not thouroughly tested '
                      'Pull request on a test anyone? bueller?').format(orientation)

    if isinstance(component, str):
        assert component.upper() in ['X', 'Y', 'Z'], ("component must be 'x', "
                                                      "'y', or 'z' or a vector"
                                                      "not {}".format(component)
                                                      )
    elif (not np.allclose(np.r_[1., 0., 0.], component) or
          not np.allclose(np.r_[0., 1., 0.], component) or
          not np.allclose(np.r_[0., 0., 1.], component)):
        warnings.warn('Arbitrary receiver orientations ({}) not thouroughly tested '
                      'Pull request on a test anyone? bueller?').format(component)

    if isinstance(orientation, str):
        orientation = orientationDict[orientation.upper()]

    if isinstance(component, str):
        component = orientationDict[component.upper()]

    assert np.linalg.norm(orientation, 2) == 1., ('orientation must be a unit '
                                                  'vector. Use "moment=X to '
                                                  'scale source fields')

    if np.linalg.norm(component, 2) != 1.:
        warnings.warn('The magnitude of the receiver component vector is > 1, '
                      ' it is {}. The receiver fields will be scaled.'
                      ).format(np.linalg.norm(component, 2))

    srcLoc = np.atleast_2d(srcLoc)
    component = np.atleast_2d(component)
    obsLoc = np.atleast_2d(obsLoc)
    orientation = np.atleast_2d(orientation)

    nObs = obsLoc.shape[0]
    nSrc = int(srcLoc.size / 3.)

    # use outer product to construct an array of [x_src, y_src, z_src]

    m = moment*orientation.repeat(nObs, axis=0)
    B = []

    for i in range(nSrc):
        srcLoc = srcLoc[i, np.newaxis].repeat(nObs, axis=0)
        rx = component.repeat(nObs, axis=0)
        dR = obsLoc - srcLoc
        r = np.sqrt((dR**2).sum(axis=1))

        # mult each element and sum along the axis (vector dot product)
        m_dot_dR_div_r2 = (m * dR).sum(axis=1) / (r**2)

        # multiply the scalar m_dot_dR by the 3D vector r
        rvec_m_dot_dR_div_r2 = np.vstack([m_dot_dR_div_r2 * dR[:, i] for
                                          i in range(3)]).T
        inside = (3. * rvec_m_dot_dR_div_r2) - m

        # dot product with rx orientation
        inside_dot_rx = (inside * rx).sum(axis=1)
        front = (mu/(4.* np.pi * r**3))

        B.append(Utils.mkvc(front * inside_dot_rx))

    return np.vstack(B).T
Example #37
0
def getKc(freq, sigma, a, b, mu=mu_0, eps=epsilon_0):
    a = float(a)
    b = float(b)
    # return 1./(2*np.pi) * np.sqrt(b / a) * np.exp(-1j*k(freq,sigma,mu,eps)*(b-a))
    return np.sqrt(b / a) * np.exp(-1j * k(freq, sigma, mu, eps) * (b - a))
def run(loc=None, sig=None, radi=None, param=None, stype='dpdp', plotIt=True):
    """
        DC Forward Simulation
        =====================

        Forward model conductive spheres in a half-space and plot a pseudo-section

        Created by @fourndo on Mon Feb 01 19:28:06 2016

    """

    assert stype in [
        'pdp', 'dpdp'
    ], "Source type (stype) must be pdp or dpdp (pole dipole or dipole dipole)"

    if loc is None:
        loc = np.c_[[-50., 0., -50.], [50., 0., -50.]]
    if sig is None:
        sig = np.r_[1e-2, 1e-1, 1e-3]
    if radi is None:
        radi = np.r_[25., 25.]
    if param is None:
        param = np.r_[30., 30., 5]

    # First we need to create a mesh and a model.

    # This is our mesh
    dx = 5.

    hxind = [(dx, 15, -1.3), (dx, 75), (dx, 15, 1.3)]
    hyind = [(dx, 15, -1.3), (dx, 10), (dx, 15, 1.3)]
    hzind = [(dx, 15, -1.3), (dx, 15)]

    mesh = Mesh.TensorMesh([hxind, hyind, hzind], 'CCN')

    # Set background conductivity
    model = np.ones(mesh.nC) * sig[0]

    # First anomaly
    ind = Utils.ModelBuilder.getIndicesSphere(loc[:, 0], radi[0], mesh.gridCC)
    model[ind] = sig[1]

    # Second anomaly
    ind = Utils.ModelBuilder.getIndicesSphere(loc[:, 1], radi[1], mesh.gridCC)
    model[ind] = sig[2]

    # Get index of the center
    indy = int(mesh.nCy / 2)

    # Plot the model for reference
    # Define core mesh extent
    xlim = 200
    zlim = 125

    # Specify the survey type: "pdp" | "dpdp"

    # Then specify the end points of the survey. Let's keep it simple for now and survey above the anomalies, top of the mesh
    ends = [(-175, 0), (175, 0)]
    ends = np.c_[np.asarray(ends), np.ones(2).T * mesh.vectorNz[-1]]

    # Snap the endpoints to the grid. Easier to create 2D section.
    indx = Utils.closestPoints(mesh, ends)
    locs = np.c_[mesh.gridCC[indx, 0], mesh.gridCC[indx, 1],
                 np.ones(2).T * mesh.vectorNz[-1]]

    # We will handle the geometry of the survey for you and create all the combination of tx-rx along line
    # [Tx, Rx] = DC.gen_DCIPsurvey(locs, mesh, stype, param[0], param[1], param[2])
    survey, Tx, Rx = DC.gen_DCIPsurvey(locs, mesh, stype, param[0], param[1],
                                       param[2])

    # Define some global geometry
    dl_len = np.sqrt(np.sum((locs[0, :] - locs[1, :])**2))
    dl_x = (Tx[-1][0, 1] - Tx[0][0, 0]) / dl_len
    dl_y = (Tx[-1][1, 1] - Tx[0][1, 0]) / dl_len
    azm = np.arctan(dl_y / dl_x)

    #Set boundary conditions
    mesh.setCellGradBC('neumann')

    # Define the differential operators needed for the DC problem
    Div = mesh.faceDiv
    Grad = mesh.cellGrad
    Msig = Utils.sdiag(1. / (mesh.aveF2CC.T * (1. / model)))

    A = Div * Msig * Grad

    # Change one corner to deal with nullspace
    A[0, 0] = 1
    A = sp.csc_matrix(A)

    # We will solve the system iteratively, so a pre-conditioner is helpful
    # This is simply a Jacobi preconditioner (inverse of the main diagonal)
    dA = A.diagonal()
    P = sp.spdiags(1 / dA, 0, A.shape[0], A.shape[0])

    # Now we can solve the system for all the transmitters
    # We want to store the data
    data = []

    # There is probably a more elegant way to do this, but we can just for-loop through the transmitters
    for ii in range(len(Tx)):

        start_time = time.time()  # Let's time the calculations

        #print("Transmitter %i / %i\r" % (ii+1,len(Tx)))

        # Select dipole locations for receiver
        rxloc_M = np.asarray(Rx[ii][:, 0:3])
        rxloc_N = np.asarray(Rx[ii][:, 3:])

        # For usual cases "dpdp" or "gradient"
        if stype == 'pdp':
            # Create an "inifinity" pole
            tx = np.squeeze(Tx[ii][:, 0:1])
            tinf = tx + np.array([dl_x, dl_y, 0]) * dl_len * 2
            inds = Utils.closestPoints(mesh, np.c_[tx, tinf].T)
            RHS = mesh.getInterpolationMat(np.asarray(Tx[ii]).T,
                                           'CC').T * ([-1] / mesh.vol[inds])
        else:
            inds = Utils.closestPoints(mesh, np.asarray(Tx[ii]).T)
            RHS = mesh.getInterpolationMat(np.asarray(Tx[ii]).T,
                                           'CC').T * ([-1, 1] / mesh.vol[inds])

        # Iterative Solve
        Ainvb = sp.linalg.bicgstab(P * A, P * RHS, tol=1e-5)

        # We now have the potential everywhere
        phi = Utils.mkvc(Ainvb[0])

        # Solve for phi on pole locations
        P1 = mesh.getInterpolationMat(rxloc_M, 'CC')
        P2 = mesh.getInterpolationMat(rxloc_N, 'CC')

        # Compute the potential difference
        dtemp = (P1 * phi - P2 * phi) * np.pi

        data.append(dtemp)
        print '\rTransmitter {0} of {1} -> Time:{2} sec'.format(
            ii, len(Tx),
            time.time() - start_time),

    print 'Transmitter {0} of {1}'.format(ii, len(Tx))
    print 'Forward completed'

    # Let's just convert the 3D format into 2D (distance along line) and plot
    # [Tx2d, Rx2d] = DC.convertObs_DC3D_to_2D(survey, np.ones(survey.nSrc))
    survey2D = DC.convertObs_DC3D_to_2D(survey, np.ones(survey.nSrc))
    survey2D.dobs = np.hstack(data)
    # Here is an example for the first tx-rx array
    if plotIt:
        import matplotlib.pyplot as plt
        fig = plt.figure()
        ax = plt.subplot(2, 1, 1, aspect='equal')
        mesh.plotSlice(np.log10(model), ax=ax, normal='Y', ind=indy, grid=True)
        ax.set_title('E-W section at ' + str(mesh.vectorCCy[indy]) + ' m')
        plt.gca().set_aspect('equal', adjustable='box')

        plt.scatter(Tx[0][0, :], Tx[0][2, :], s=40, c='g', marker='v')
        plt.scatter(Rx[0][:, 0::3], Rx[0][:, 2::3], s=40, c='y')
        plt.xlim([-xlim, xlim])
        plt.ylim([-zlim, mesh.vectorNz[-1] + dx])

        ax = plt.subplot(2, 1, 2, aspect='equal')

        # Plot the location of the spheres for reference
        circle1 = plt.Circle((loc[0, 0] - Tx[0][0, 0], loc[2, 0]),
                             radi[0],
                             color='w',
                             fill=False,
                             lw=3)
        circle2 = plt.Circle((loc[0, 1] - Tx[0][0, 0], loc[2, 1]),
                             radi[1],
                             color='k',
                             fill=False,
                             lw=3)
        ax.add_artist(circle1)
        ax.add_artist(circle2)

        # Add the speudo section
        DC.plot_pseudoSection(survey2D, ax, stype)

        # plt.scatter(Tx2d[0][:],Tx[0][2,:],s=40,c='g', marker='v')
        # plt.scatter(Rx2d[0][:],Rx[0][:,2::3],s=40,c='y')
        # plt.plot(np.r_[Tx2d[0][0],Rx2d[-1][-1,-1]],np.ones(2)*mesh.vectorNz[-1], color='k')
        plt.ylim([-zlim, mesh.vectorNz[-1] + dx])

        plt.show()

        return fig, ax
Example #39
0
def gen_DCIPsurvey(endl, mesh, stype, a, b, n):
    """
        Load in endpoints and survey specifications to generate Tx, Rx location
        stations.

        Assumes flat topo for now...

        Input:
        :param endl -> input endpoints [x1, y1, z1, x2, y2, z2]
        :object mesh -> SimPEG mesh object
        :switch stype -> "dpdp" (dipole-dipole) | "pdp" (pole-dipole) | 'gradient'
        : param a, n -> pole seperation, number of rx dipoles per tx

        Output:
        :param Tx, Rx -> List objects for each tx location
            Lines: P1x, P1y, P1z, P2x, P2y, P2z

        Created on Wed December 9th, 2015

        @author: dominiquef
        !! Require clean up to deal with DCsurvey
    """

    from SimPEG import np

    def xy_2_r(x1, x2, y1, y2):
        r = np.sqrt(np.sum((x2 - x1)**2 + (y2 - y1)**2))
        return r

    ## Evenly distribute electrodes and put on surface
    # Mesure survey length and direction
    dl_len = xy_2_r(endl[0, 0], endl[1, 0], endl[0, 1], endl[1, 1])

    dl_x = (endl[1, 0] - endl[0, 0]) / dl_len
    dl_y = (endl[1, 1] - endl[0, 1]) / dl_len

    nstn = np.floor(dl_len / a)

    # Compute discrete pole location along line
    stn_x = endl[0, 0] + np.array(range(int(nstn))) * dl_x * a
    stn_y = endl[0, 1] + np.array(range(int(nstn))) * dl_y * a

    if mesh.dim == 2:
        ztop = mesh.vectorNy[-1]
        # Create line of P1 locations
        M = np.c_[stn_x, np.ones(nstn).T * ztop]
        # Create line of P2 locations
        N = np.c_[stn_x + a * dl_x, np.ones(nstn).T * ztop]

    elif mesh.dim == 3:
        ztop = mesh.vectorNz[-1]
        # Create line of P1 locations
        M = np.c_[stn_x, stn_y, np.ones(nstn).T * ztop]
        # Create line of P2 locations
        N = np.c_[stn_x + a * dl_x, stn_y + a * dl_y, np.ones(nstn).T * ztop]

    ## Build list of Tx-Rx locations depending on survey type
    # Dipole-dipole: Moving tx with [a] spacing -> [AB a MN1 a MN2 ... a MNn]
    # Pole-dipole: Moving pole on one end -> [A a MN1 a MN2 ... MNn a B]
    SrcList = []

    if stype != 'gradient':

        for ii in range(0, int(nstn) - 1):

            if stype == 'dipole-dipole':
                tx = np.c_[M[ii, :], N[ii, :]]
            elif stype == 'pole-dipole':
                tx = np.c_[M[ii, :], M[ii, :]]
            else:
                raise Exception(
                    'The stype must be "dipole-dipole" or "pole-dipole"')

            # Rx.append(np.c_[M[ii+1:indx,:],N[ii+1:indx,:]])

            # Current elctrode seperation
            AB = xy_2_r(tx[0, 1], endl[1, 0], tx[1, 1], endl[1, 1])

            # Number of receivers to fit
            nstn = np.min([np.floor((AB - b) / a), n])

            # Check if there is enough space, else break the loop
            if nstn <= 0:
                continue

            # Compute discrete pole location along line
            stn_x = N[ii, 0] + dl_x * b + np.array(range(int(nstn))) * dl_x * a
            stn_y = N[ii, 1] + dl_y * b + np.array(range(int(nstn))) * dl_y * a

            # Create receiver poles

            if mesh.dim == 3:
                # Create line of P1 locations
                P1 = np.c_[stn_x, stn_y, np.ones(nstn).T * ztop]
                # Create line of P2 locations
                P2 = np.c_[stn_x + a * dl_x, stn_y + a * dl_y,
                           np.ones(nstn).T * ztop]
                rxClass = DC.Rx.Dipole(P1, P2)

            elif mesh.dim == 2:
                # Create line of P1 locations
                P1 = np.c_[stn_x, np.ones(nstn).T * ztop]
                # Create line of P2 locations
                P2 = np.c_[stn_x + a * dl_x, np.ones(nstn).T * ztop]
                rxClass = DC.Rx.Dipole_ky(P1, P2)

            if stype == 'dipole-dipole':
                srcClass = DC.Src.Dipole([rxClass], M[ii, :], N[ii, :])
            elif stype == 'pole-dipole':
                srcClass = DC.Src.Pole([rxClass], M[ii, :])
            SrcList.append(srcClass)

    elif stype == 'gradient':

        # Gradient survey only requires Tx at end of line and creates a square
        # grid of receivers at in the middle at a pre-set minimum distance

        # Get the edge limit of survey area
        min_x = endl[0, 0] + dl_x * b
        min_y = endl[0, 1] + dl_y * b

        max_x = endl[1, 0] - dl_x * b
        max_y = endl[1, 1] - dl_y * b

        box_l = np.sqrt((min_x - max_x)**2 + (min_y - max_y)**2)
        box_w = box_l / 2.

        nstn = np.floor(box_l / a)

        # Compute discrete pole location along line
        stn_x = min_x + np.array(range(int(nstn))) * dl_x * a
        stn_y = min_y + np.array(range(int(nstn))) * dl_y * a

        # Define number of cross lines
        nlin = int(np.floor(box_w / a))
        lind = range(-nlin, nlin + 1)

        ngrad = nstn * len(lind)

        rx = np.zeros([ngrad, 6])
        for ii in range(len(lind)):

            # Move line in perpendicular direction by dipole spacing
            lxx = stn_x - lind[ii] * a * dl_y
            lyy = stn_y + lind[ii] * a * dl_x

            M = np.c_[lxx, lyy, np.ones(nstn).T * ztop]
            N = np.c_[lxx + a * dl_x, lyy + a * dl_y, np.ones(nstn).T * ztop]
            rx[(ii * nstn):((ii + 1) * nstn), :] = np.c_[M, N]

            if mesh.dim == 3:
                rxClass = DC.Rx.Dipole(rx[:, :3], rx[:, 3:])
            elif mesh.dim == 2:
                M = M[:, [0, 2]]
                N = N[:, [0, 2]]
                rxClass = DC.Rx.Dipole_ky(rx[:, [0, 2]], rx[:, [3, 5]])
            srcClass = DC.Src.Dipole([rxClass], M[0, :], N[-1, :])
        SrcList.append(srcClass)
    else:
        print """stype must be either 'pole-dipole', 'dipole-dipole' or 'gradient'. """

    return SrcList
Example #40
0
def gen_DCIPsurvey(endl, mesh, stype, a, b, n):
    
    from SimPEG import np
    import re
    """
        Load in endpoints and survey specifications to generate Tx, Rx location
        stations.
        
        Assumes flat topo for now...
    
        Input:
        :param endl -> input endpoints [x1, y1, z1, x2, y2, z2]
        :object mesh -> SimPEG mesh object
        :switch stype -> "dpdp" (dipole-dipole) | "pdp" (pole-dipole) | 'gradient'
        : param a, n -> pole seperation, number of rx dipoles per tx
        
        Output:
        :param Tx, Rx -> List objects for each tx location
            Lines: P1x, P1y, P1z, P2x, P2y, P2z
        
        Created on Wed December 9th, 2015
    
        @author: dominiquef
    
    """
    def xy_2_r(x1,x2,y1,y2):
        r = np.sqrt( np.sum((x2 - x1)**2 + (y2 - y1)**2) )
        return r 
        
    ## Evenly distribute electrodes and put on surface
    # Mesure survey length and direction
    dl_len = xy_2_r(endl[0,0],endl[1,0],endl[0,1],endl[1,1])
    
    dl_x = ( endl[1,0] - endl[0,0] ) / dl_len
    dl_y = ( endl[1,1] - endl[0,1] ) / dl_len
       
    nstn = np.floor( dl_len / a )
    
    # Compute discrete pole location along line
    stn_x = endl[0,0] + np.array(range(int(nstn)))*dl_x*a
    stn_y = endl[0,1] + np.array(range(int(nstn)))*dl_y*a
    
    # Create line of P1 locations
    M = np.c_[stn_x, stn_y, np.ones(nstn).T*mesh.vectorNz[-1]]
    
    # Create line of P2 locations
    N = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*mesh.vectorNz[-1]]
    
    ## Build list of Tx-Rx locations depending on survey type
    # Dipole-dipole: Moving tx with [a] spacing -> [AB a MN1 a MN2 ... a MNn]
    # Pole-dipole: Moving pole on one end -> [A a MN1 a MN2 ... MNn a B]
    Tx = []
    Rx = []
    
    if not re.match(stype,'gradient'):
        
        for ii in range(0, int(nstn)-1): 
            
            
            if re.match(stype,'dpdp'):
                tx = np.c_[M[ii,:],N[ii,:]]
            elif re.match(stype,'pdp'):
                tx = np.c_[M[ii,:],M[ii,:]]
                
            #Rx.append(np.c_[M[ii+1:indx,:],N[ii+1:indx,:]])
            
            # Current elctrode seperation
            AB = xy_2_r(tx[0,1],endl[1,0],tx[1,1],endl[1,1])
            
            # Number of receivers to fit
            nstn = np.min([np.floor( (AB - b) / a ) , n])
            
            # Check if there is enough space, else break the loop
            if nstn <= 0:
                continue
            
            # Compute discrete pole location along line
            stn_x = N[ii,0] + dl_x*b + np.array(range(int(nstn)))*dl_x*a
            stn_y = N[ii,1] + dl_y*b + np.array(range(int(nstn)))*dl_y*a
            
            # Create receiver poles
            # Create line of P1 locations
            P1 = np.c_[stn_x, stn_y, np.ones(nstn).T*mesh.vectorNz[-1]]
            
            # Create line of P2 locations
            P2 = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*mesh.vectorNz[-1]]
            
            Rx.append(np.c_[P1,P2])
            Tx.append(tx)            
            
#==============================================================================
#     elif re.match(stype,'dpdp'):
#         
#         for ii in range(0, int(nstn)-2):  
#             
#             indx = np.min([ii+n+1,nstn])
#             Tx.append(np.c_[M[ii,:],N[ii,:]])
#             Rx.append(np.c_[M[ii+2:indx,:],N[ii+2:indx,:]])
#==============================================================================
            
    elif re.match(stype,'gradient'):
        
        # Gradient survey only requires Tx at end of line and creates a square
        # grid of receivers at in the middle at a pre-set minimum distance
        Tx.append(np.c_[M[0,:],N[-1,:]])
              
        # Get the edge limit of survey area
        min_x = endl[0,0] + dl_x * b
        min_y = endl[0,1] + dl_y * b
            
        max_x = endl[1,0] - dl_x * b
        max_y = endl[1,1] - dl_y * b
        
        box_l = np.sqrt( (min_x - max_x)**2 + (min_y - max_y)**2 )
        box_w = box_l/2.
        
        nstn = np.floor( box_l / a )
        
        # Compute discrete pole location along line
        stn_x = min_x + np.array(range(int(nstn)))*dl_x*a
        stn_y = min_y + np.array(range(int(nstn)))*dl_y*a
        
        # Define number of cross lines
        nlin = int(np.floor( box_w / a ))
        lind = range(-nlin,nlin+1) 
        
        ngrad = nstn * len(lind)
        
        rx = np.zeros([ngrad,6])
        for ii in range( len(lind) ):
            
            # Move line in perpendicular direction by dipole spacing
            lxx = stn_x - lind[ii]*a*dl_y
            lyy = stn_y + lind[ii]*a*dl_x
            
            
            M = np.c_[ lxx, lyy , np.ones(nstn).T*mesh.vectorNz[-1]]
            N = np.c_[ lxx+a*dl_x, lyy+a*dl_y, np.ones(nstn).T*mesh.vectorNz[-1]]
            
            rx[(ii*nstn):((ii+1)*nstn),:] = np.c_[M,N]
            
        Rx.append(rx)
        
    else:
        print """stype must be either 'pdp', 'dpdp' or 'gradient'. """

        
   
    return Tx, Rx  
Example #41
0
 def xy_2_r(x1,x2,y1,y2):
     r = np.sqrt( np.sum((x2 - x1)**2 + (y2 - y1)**2) )
     return r 
Example #42
0
 def refine(cell):
     if np.sqrt(((np.r_[cell.center] - 0.5)**2).sum()) < 0.4:
         return 4
     return 3