Beispiel #1
0
tilestep = 7
for tt in tiles[tilestep:2 * tilestep]:
    print('Tile ' + str(tt) + ' of ' + str(len(tiles)))
    midX = np.mean([X1[tt], X2[tt]])
    midY = np.mean([Y1[tt], Y2[tt]])

    # Create new mesh
    padx = np.r_[dx[0] * expf**(np.asarray(range(npadxy)) + 1)]
    pady = np.r_[dx[1] * expf**(np.asarray(range(npadxy)) + 1)]

    hx = np.r_[padx[::-1], core_x, padx]
    hy = np.r_[pady[::-1], core_y, pady]
    #        hz = np.r_[padb*2.,[33,26],np.ones(25)*22,[18,15,12,10,8,7,6], np.ones(18)*5,5*expf**(np.asarray(range(2*npad)))]
    hz = mesh.hz

    mesh_t = Mesh.TensorMesh([hx, hy, hz], 'CC0')

    #    mtemp._x0 = [x0[ii]-np.sum(padb), y0[ii]-np.sum(padb), mesh.x0[2]]

    mesh_t._x0 = (mesh_t.x0[0] + midX, mesh_t.x0[1] + midY, mesh.x0[2])

    Mesh.TensorMesh.writeUBC(
        mesh_t,
        work_dir + out_dir + tile_dirl2 + "MAG_Tile" + str(tt) + ".msh")
    Mesh.TensorMesh.writeUBC(
        mesh_t,
        work_dir + out_dir + tile_dirlp + "MAG_Tile" + str(tt) + ".msh")

    #        meshes.append(mtemp)
    # Grab the right data
    xlim = [mesh_t.vectorCCx[npadxy], mesh_t.vectorCCx[-npadxy]]
Beispiel #2
0
    def getRHS(self):
        """
        RHS for the DC problem

        q
        """

        RHS = self.getSourceTerm()
        return RHS

    def getRHSDeriv(self, src, v, adjoint=False):
        """
        Derivative of the right hand side with respect to the model
        """
        # TODO: add qDeriv for RHS depending on m
        # qDeriv = src.evalDeriv(self, adjoint=adjoint)
        # return qDeriv
        return Zero()


if __name__ == '__main__':

    cs = 12.5
    hx = [(cs, 7, -1.3), (cs, 21), (cs, 7, 1.3)]
    hy = [(cs, 7, -1.3), (cs, 21), (cs, 7, 1.3)]
    hz = [(cs, 7, -1.3), (cs, 20)]
    mesh = Mesh.TensorMesh([hx, hy, hz], x0="CCN")
    sigma = np.ones(mesh.nC)
    prob = BaseIPProblem(mesh, sigma=sigma)
Beispiel #3
0
def plotCurrentDensity(mesh,
                       fields_j,
                       saveFig=False,
                       figsize=(4, 5),
                       fontsize=12,
                       csx=5.,
                       csz=5.,
                       xmax=1000.,
                       zmin=0.,
                       zmax=-1200.,
                       real_or_imag='real',
                       mirror=False,
                       ax=None,
                       fig=None,
                       clim=None):
    csx, ncx = csx, np.ceil(xmax / csx)
    csz, ncz = csz, np.ceil((zmin - zmax) / csz)

    if mirror is True:
        xlim = [-xmax, xmax]
        x0 = [-xmax, -csx / 2., zmax]
        ncx *= 2.
    else:
        xlim = [0., xmax]
        x0 = [0, -csx / 2., zmax]

    ylim = [zmax, zmin]

    # define the tensor mesh
    meshcart = Mesh.TensorMesh([[(csx, ncx)], [(csx, 1)], [(csz, ncz)]], x0)

    projF = mesh.getInterpolationMatCartMesh(meshcart, 'F')

    jcart = projF * fields_j
    jcart = getattr(jcart, real_or_imag)

    if ax is None:
        fig, ax = plt.subplots(1, 1, figsize=figsize)
    if saveFig is True:
        # this looks obnoxious inline, but nice in the saved png
        f = meshcart.plotSlice(jcart,
                               normal='Y',
                               vType='F',
                               view='vec',
                               pcolorOpts={
                                   'norm': LogNorm(),
                                   'cmap': plt.get_cmap('viridis')
                               },
                               streamOpts={
                                   'arrowsize': 6,
                                   'color': 'k'
                               },
                               ax=ax)
    else:
        f = meshcart.plotSlice(jcart,
                               normal='Y',
                               vType='F',
                               view='vec',
                               pcolorOpts={
                                   'norm': LogNorm(),
                                   'cmap': plt.get_cmap('viridis')
                               },
                               ax=ax)
    plt.colorbar(f[0],
                 label='{} current density (A/m$^2$)'.format(real_or_imag))

    if clim is not None:
        f.set_clim(clim)

    ax.set_ylim(ylim)
    ax.set_xlim(xlim)
    # ax.set_title('Current Density')
    ax.set_xlabel('radius (m)', fontsize=fontsize)
    ax.set_ylabel('z (m)', fontsize=fontsize)

    if saveFig is True:
        fig.savefig('primaryCurrents', dpi=300, bbox_inches='tight')

    return ax
Beispiel #4
0
 def test_ParametricSplineMap(self):
     M2 = Mesh.TensorMesh([np.ones(10), np.ones(10)], "CN")
     x = M2.vectorCCx
     mParamSpline = Maps.ParametricSplineMap(M2, x, normal='Y', order=1)
     self.assertTrue(mParamSpline.test())
     self.assertTrue(mParamSpline.testVec())
Beispiel #5
0
import SimPEG.VRM as VRM
import numpy as np
from SimPEG import mkvc, Mesh, Maps
import matplotlib.pyplot as plt
import matplotlib as mpl

##########################################################################
# Defining the mesh
# -----------------
#

cs, ncx, ncy, ncz, npad = 2., 35, 35, 20, 5
hx = [(cs, npad, -1.3), (cs, ncx), (cs, npad, 1.3)]
hy = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)]
hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)]
mesh = Mesh.TensorMesh([hx, hy, hz], 'CCC')

##########################################################################
# Defining the model
# ------------------
#
# Create xi model (amalgamated magnetic property). Here the model is made by
# summing a set of 3D Gaussian distributions. And only active cells have a
# model value.
#

topoCells = mesh.gridCC[:, 2] < 0.  # Define topography

xyzc = mesh.gridCC[topoCells, :]
c = 2 * np.pi * 8**2
pc = np.r_[4e-4, 4e-4, 4e-4, 6e-4, 8e-4, 6e-4, 8e-4, 8e-4]
def run(plotIt=True):
    """
        PF: Magnetic: Inversion Linear
        ===============================

        Create a synthetic block model and invert
        with a compact norm

    """

    # Define the inducing field parameter
    H0 = (50000, 90, 0)

    # Create a mesh
    dx = 5.

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

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

    # Get index of the center
    midx = int(mesh.nCx / 2)
    midy = int(mesh.nCy / 2)

    # Lets create a simple Gaussian topo and set the active cells
    [xx, yy] = np.meshgrid(mesh.vectorNx, mesh.vectorNy)
    zz = -np.exp((xx**2 + yy**2) / 75**2) + mesh.vectorNz[-1]

    # We would usually load a topofile
    topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)]

    # Go from topo to actv cells
    actv = Utils.surface2ind_topo(mesh, topo, 'N')
    actv = np.asarray([inds for inds, elem in enumerate(actv, 1) if elem],
                      dtype=int) - 1

    # Create active map to go from reduce space to full
    actvMap = Maps.InjectActiveCells(mesh, actv, -100)
    nC = len(actv)

    # Create and array of observation points
    xr = np.linspace(-20., 20., 20)
    yr = np.linspace(-20., 20., 20)
    X, Y = np.meshgrid(xr, yr)

    # Move the observation points 5m above the topo
    Z = -np.exp((X**2 + Y**2) / 75**2) + mesh.vectorNz[-1] + 5.

    # Create a MAGsurvey
    rxLoc = np.c_[Utils.mkvc(X.T), Utils.mkvc(Y.T), Utils.mkvc(Z.T)]
    rxLoc = PF.BaseMag.RxObs(rxLoc)
    srcField = PF.BaseMag.SrcField([rxLoc], param=H0)
    survey = PF.BaseMag.LinearSurvey(srcField)

    # We can now create a susceptibility model and generate data
    # Here a simple block in half-space
    model = np.zeros((mesh.nCx, mesh.nCy, mesh.nCz))
    model[(midx - 2):(midx + 2), (midy - 2):(midy + 2), -6:-2] = 0.02
    model = Utils.mkvc(model)
    model = model[actv]

    # Create active map to go from reduce set to full
    actvMap = Maps.InjectActiveCells(mesh, actv, -100)

    # Creat reduced identity map
    idenMap = Maps.IdentityMap(nP=nC)

    # Create the forward model operator
    prob = PF.Magnetics.MagneticIntegral(mesh, chiMap=idenMap, actInd=actv)

    # Pair the survey and problem
    survey.pair(prob)

    # Compute linear forward operator and compute some data
    d = prob.fields(model)

    # Add noise and uncertainties
    # We add some random Gaussian noise (1nT)
    data = d + np.random.randn(len(d))
    wd = np.ones(len(data)) * 1.  # Assign flat uncertainties

    survey.dobs = data
    survey.std = wd
    survey.mtrue = model

    # Create sensitivity weights from our linear forward operator
    rxLoc = survey.srcField.rxList[0].locs
    wr = np.sum(prob.G**2., axis=0)**0.5
    wr = (wr / np.max(wr))

    # Create a regularization
    reg = Regularization.Sparse(mesh, indActive=actv, mapping=idenMap)
    reg.cell_weights = wr

    # Data misfit function
    dmis = DataMisfit.l2_DataMisfit(survey)
    dmis.Wd = 1 / wd

    # Add directives to the inversion
    opt = Optimization.ProjectedGNCG(maxIter=100,
                                     lower=0.,
                                     upper=1.,
                                     maxIterLS=20,
                                     maxIterCG=10,
                                     tolCG=1e-3)
    invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
    betaest = Directives.BetaEstimate_ByEig()

    # Here is where the norms are applied
    # Use pick a treshold parameter empirically based on the distribution of
    #  model parameters
    IRLS = Directives.Update_IRLS(norms=([0, 1, 1, 1]),
                                  eps=(5e-4, 5e-4),
                                  f_min_change=1e-3,
                                  minGNiter=3)
    update_Jacobi = Directives.Update_lin_PreCond()
    inv = Inversion.BaseInversion(invProb,
                                  directiveList=[IRLS, betaest, update_Jacobi])

    # Run the inversion
    m0 = np.ones(nC) * 1e-4  # Starting model
    mrec = inv.run(m0)

    if plotIt:
        # Here is the recovered susceptibility model
        ypanel = midx
        zpanel = -5
        m_l2 = actvMap * reg.l2model
        m_l2[m_l2 == -100] = np.nan

        m_lp = actvMap * mrec
        m_lp[m_lp == -100] = np.nan

        m_true = actvMap * model
        m_true[m_true == -100] = np.nan

        # Plot the data
        PF.Magnetics.plot_obs_2D(rxLoc, d=d)

        plt.figure()

        # Plot L2 model
        ax = plt.subplot(321)
        mesh.plotSlice(m_l2,
                       ax=ax,
                       normal='Z',
                       ind=zpanel,
                       grid=True,
                       clim=(model.min(), model.max()))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]),
                 color='w')
        plt.title('Plan l2-model.')
        plt.gca().set_aspect('equal')
        plt.ylabel('y')
        ax.xaxis.set_visible(False)
        plt.gca().set_aspect('equal', adjustable='box')

        # Vertica section
        ax = plt.subplot(322)
        mesh.plotSlice(m_l2,
                       ax=ax,
                       normal='Y',
                       ind=midx,
                       grid=True,
                       clim=(model.min(), model.max()))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]),
                 color='w')
        plt.title('E-W l2-model.')
        plt.gca().set_aspect('equal')
        ax.xaxis.set_visible(False)
        plt.ylabel('z')
        plt.gca().set_aspect('equal', adjustable='box')

        # Plot Lp model
        ax = plt.subplot(323)
        mesh.plotSlice(m_lp,
                       ax=ax,
                       normal='Z',
                       ind=zpanel,
                       grid=True,
                       clim=(model.min(), model.max()))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]),
                 color='w')
        plt.title('Plan lp-model.')
        plt.gca().set_aspect('equal')
        ax.xaxis.set_visible(False)
        plt.ylabel('y')
        plt.gca().set_aspect('equal', adjustable='box')

        # Vertical section
        ax = plt.subplot(324)
        mesh.plotSlice(m_lp,
                       ax=ax,
                       normal='Y',
                       ind=midx,
                       grid=True,
                       clim=(model.min(), model.max()))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]),
                 color='w')
        plt.title('E-W lp-model.')
        plt.gca().set_aspect('equal')
        ax.xaxis.set_visible(False)
        plt.ylabel('z')
        plt.gca().set_aspect('equal', adjustable='box')

        # Plot True model
        ax = plt.subplot(325)
        mesh.plotSlice(m_true,
                       ax=ax,
                       normal='Z',
                       ind=zpanel,
                       grid=True,
                       clim=(model.min(), model.max()))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]),
                 color='w')
        plt.title('Plan true model.')
        plt.gca().set_aspect('equal')
        plt.xlabel('x')
        plt.ylabel('y')
        plt.gca().set_aspect('equal', adjustable='box')

        # Vertical section
        ax = plt.subplot(326)
        mesh.plotSlice(m_true,
                       ax=ax,
                       normal='Y',
                       ind=midx,
                       grid=True,
                       clim=(model.min(), model.max()))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]),
                 color='w')
        plt.title('E-W true model.')
        plt.gca().set_aspect('equal')
        plt.xlabel('x')
        plt.ylabel('z')
        plt.gca().set_aspect('equal', adjustable='box')
Beispiel #7
0
    def setUp(self):

        np.random.seed(0)

        # Define the inducing field parameter
        H0 = (50000, 90, 0)

        # Create a mesh
        dx = 5.

        hxind = [(dx, 5, -1.3), (dx, 5), (dx, 5, 1.3)]
        hyind = [(dx, 5, -1.3), (dx, 5), (dx, 5, 1.3)]
        hzind = [(dx, 5, -1.3), (dx, 6)]

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

        # Get index of the center
        midx = int(mesh.nCx / 2)
        midy = int(mesh.nCy / 2)

        # Lets create a simple Gaussian topo and set the active cells
        [xx, yy] = np.meshgrid(mesh.vectorNx, mesh.vectorNy)
        zz = -np.exp((xx**2 + yy**2) / 75**2) + mesh.vectorNz[-1]

        # Go from topo to actv cells
        topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)]
        actv = Utils.surface2ind_topo(mesh, topo, 'N')
        actv = np.asarray([inds for inds, elem in enumerate(actv, 1) if elem],
                          dtype=int) - 1

        # Create active map to go from reduce space to full
        actvMap = Maps.InjectActiveCells(mesh, actv, -100)
        nC = len(actv)

        # Create and array of observation points
        xr = np.linspace(-20., 20., 20)
        yr = np.linspace(-20., 20., 20)
        X, Y = np.meshgrid(xr, yr)

        # Move the observation points 5m above the topo
        Z = -np.exp((X**2 + Y**2) / 75**2) + mesh.vectorNz[-1] + 5.

        # Create a MAGsurvey
        rxLoc = np.c_[Utils.mkvc(X.T), Utils.mkvc(Y.T), Utils.mkvc(Z.T)]
        rxLoc = PF.BaseMag.RxObs(rxLoc)
        srcField = PF.BaseMag.SrcField([rxLoc], param=H0)
        survey = PF.BaseMag.LinearSurvey(srcField)

        # We can now create a susceptibility model and generate data
        # Here a simple block in half-space
        model = np.zeros((mesh.nCx, mesh.nCy, mesh.nCz))
        model[(midx - 2):(midx + 2), (midy - 2):(midy + 2), -6:-2] = 0.02
        model = Utils.mkvc(model)
        self.model = model[actv]

        # Create active map to go from reduce set to full
        actvMap = Maps.InjectActiveCells(mesh, actv, -100)

        # Creat reduced identity map
        idenMap = Maps.IdentityMap(nP=nC)

        # Create the forward model operator
        prob = PF.Magnetics.MagneticIntegral(mesh,
                                             mapping=idenMap,
                                             actInd=actv)

        # Pair the survey and problem
        survey.pair(prob)

        # Compute linear forward operator and compute some data
        d = prob.fields(self.model)

        # Add noise and uncertainties (1nT)
        data = d + np.random.randn(len(d))
        wd = np.ones(len(data)) * 1.

        survey.dobs = data
        survey.std = wd

        # Create sensitivity weights from our linear forward operator
        wr = np.sum(prob.G**2., axis=0)**0.5
        wr = (wr / np.max(wr))

        # Create a regularization
        reg = Regularization.Sparse(mesh, indActive=actv, mapping=idenMap)
        reg.cell_weights = wr

        # Data misfit function
        dmis = DataMisfit.l2_DataMisfit(survey)
        dmis.Wd = 1 / wd

        # Add directives to the inversion
        opt = Optimization.ProjectedGNCG(maxIter=100,
                                         lower=0.,
                                         upper=1.,
                                         maxIterLS=20,
                                         maxIterCG=10,
                                         tolCG=1e-3)

        invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
        betaest = Directives.BetaEstimate_ByEig()

        # Here is where the norms are applied
        IRLS = Directives.Update_IRLS(norms=([0, 1, 1, 1]),
                                      eps=(1e-3, 1e-3),
                                      f_min_change=1e-3,
                                      minGNiter=3)
        update_Jacobi = Directives.Update_lin_PreCond()
        self.inv = Inversion.BaseInversion(
            invProb, directiveList=[IRLS, betaest, update_Jacobi])
Beispiel #8
0
def run(plotIt=True):

    H0 = (50000., 90., 0.)

    # Create a mesh
    dx = 5.

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

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

    # Lets create a simple Gaussian topo and set the active cells
    [xx, yy] = np.meshgrid(mesh.vectorNx, mesh.vectorNy)
    zz = -np.exp((xx**2 + yy**2) / 75**2) + mesh.vectorNz[-1]

    # We would usually load a topofile
    topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)]

    # Go from topo to array of indices of active cells
    actv = Utils.surface2ind_topo(mesh, topo, 'N')
    actv = np.where(actv)[0]

    # Create and array of observation points
    xr = np.linspace(-20., 20., 20)
    yr = np.linspace(-20., 20., 20)
    X, Y = np.meshgrid(xr, yr)

    # Move the observation points 5m above the topo
    Z = -np.exp((X**2 + Y**2) / 75**2) + mesh.vectorNz[-1] + 5.

    # Create a MAGsurvey
    rxLoc = np.c_[Utils.mkvc(X.T), Utils.mkvc(Y.T), Utils.mkvc(Z.T)]
    rxLoc = PF.BaseMag.RxObs(rxLoc)
    srcField = PF.BaseMag.SrcField([rxLoc], param=H0)
    survey = PF.BaseMag.LinearSurvey(srcField)

    # We can now create a susceptibility model and generate data
    model = np.zeros(mesh.nC)

    # Change values in half the domain
    model[mesh.gridCC[:, 0] < 0] = 0.01

    # Add a block in half-space
    model = Utils.ModelBuilder.addBlock(mesh.gridCC, model,
                                        np.r_[-10, -10, 20], np.r_[10, 10,
                                                                   40], 0.05)

    model = Utils.mkvc(model)
    model = model[actv]

    # Create active map to go from reduce set to full
    actvMap = Maps.InjectActiveCells(mesh, actv, np.nan)

    # Create reduced identity map
    idenMap = Maps.IdentityMap(nP=len(actv))

    # Create the forward model operator
    prob = PF.Magnetics.MagneticIntegral(mesh, chiMap=idenMap, actInd=actv)

    # Pair the survey and problem
    survey.pair(prob)

    # Compute linear forward operator and compute some data
    d = prob.fields(model)

    # Add noise and uncertainties
    # We add some random Gaussian noise (1nT)
    data = d + np.random.randn(len(d))
    wd = np.ones(len(data)) * 1.  # Assign flat uncertainties

    survey.dobs = data
    survey.std = wd
    survey.mtrue = model

    # Plot the data
    rxLoc = survey.srcField.rxList[0].locs

    # Create a homogenous maps for the two domains
    domains = [mesh.gridCC[actv, 0] < 0, mesh.gridCC[actv, 0] >= 0]
    homogMap = Maps.SurjectUnits(domains)

    # Create a wire map for a second model space, voxel based
    wires = Maps.Wires(('h**o', len(domains)), ('hetero', len(actv)))

    # Create Sum map
    sumMap = Maps.SumMap([homogMap * wires.h**o, wires.hetero])

    # Create the forward model operator
    prob = PF.Magnetics.MagneticIntegral(mesh, chiMap=sumMap, actInd=actv)

    # Pair the survey and problem
    survey.unpair()
    survey.pair(prob)

    # Make depth weighting
    wr = np.zeros(sumMap.shape[1])

    # Take the cell number out of the scaling.
    # Want to keep high sens for large volumes
    scale = Utils.sdiag(np.r_[Utils.mkvc(1. / homogMap.P.sum(axis=0)),
                              np.ones_like(actv)])

    for ii in range(survey.nD):
        wr += ((prob.G[ii, :] *
                prob.chiMap.deriv(np.ones(sumMap.shape[1]) * 1e-4) * scale) /
               survey.std[ii])**2.

    # Scale the model spaces independently
    wr[wires.h**o.index] /= (np.max((wires.h**o * wr)))
    wr[wires.hetero.index] /= (np.max(wires.hetero * wr))
    wr = wr**0.5

    ## Create a regularization
    # For the homogeneous model
    regMesh = Mesh.TensorMesh([len(domains)])

    reg_m1 = Regularization.Sparse(regMesh, mapping=wires.h**o)
    reg_m1.cell_weights = wires.h**o * wr
    reg_m1.norms = np.c_[0, 2, 2, 2]
    reg_m1.mref = np.zeros(sumMap.shape[1])

    # Regularization for the voxel model
    reg_m2 = Regularization.Sparse(mesh, indActive=actv, mapping=wires.hetero)
    reg_m2.cell_weights = wires.hetero * wr
    reg_m2.norms = np.c_[0, 1, 1, 1]
    reg_m2.mref = np.zeros(sumMap.shape[1])

    reg = reg_m1 + reg_m2

    # Data misfit function
    dmis = DataMisfit.l2_DataMisfit(survey)
    dmis.W = 1 / wd

    # Add directives to the inversion
    opt = Optimization.ProjectedGNCG(maxIter=100,
                                     lower=0.,
                                     upper=1.,
                                     maxIterLS=20,
                                     maxIterCG=10,
                                     tolCG=1e-3,
                                     tolG=1e-3,
                                     eps=1e-6)
    invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
    betaest = Directives.BetaEstimate_ByEig()

    # Here is where the norms are applied
    # Use pick a threshold parameter empirically based on the distribution of
    #  model parameters
    IRLS = Directives.Update_IRLS(f_min_change=1e-3, minGNiter=1)
    update_Jacobi = Directives.UpdatePreconditioner()
    inv = Inversion.BaseInversion(invProb,
                                  directiveList=[IRLS, betaest, update_Jacobi])

    # Run the inversion
    m0 = np.ones(sumMap.shape[1]) * 1e-4  # Starting model
    prob.model = m0
    mrecSum = inv.run(m0)
    if plotIt:

        mesh.plot_3d_slicer(actvMap * model,
                            aspect="equal",
                            zslice=30,
                            pcolorOpts={"cmap": 'inferno_r'},
                            transparent='slider')

        mesh.plot_3d_slicer(actvMap * sumMap * mrecSum,
                            aspect="equal",
                            zslice=30,
                            pcolorOpts={"cmap": 'inferno_r'},
                            transparent='slider')
Beispiel #9
0
rxLoc = survey.srcField.rxList[0].locs
wr = np.zeros(nC)
for ii in range(survey.nD):
    wr += ((prob.F[ii, :] * prob.chiMap.deriv(m0)) / survey.std[ii])**2.

wr = (wr / np.max(wr))
wr = wr**0.5

Mesh.TensorMesh.writeModelUBC(mesh, work_dir + out_dir + 'SensWeights.sus',
                              actvMap * (homogMap.P * wr))
# wr = PF.Magnetics.get_dist_wgt(mesh, rxLoc, actv, 3, 1)

# Create reduced identity map
idenMap = Maps.IdentityMap(nP=nC)

regMesh = Mesh.TensorMesh([nC])
# Create a regularization
reg = Regularization.Sparse(regMesh, mapping=idenMap)
reg.norms = driver.lpnorms

if driver.eps is not None:
    reg.eps_p = driver.eps[0]
    reg.eps_q = driver.eps[1]

reg.cell_weights = wr  #driver.cell_weights*mesh.vol**0.5
reg.mref = np.zeros(nC)
# Data misfit function
dmis = DataMisfit.l2_DataMisfit(survey)
dmis.W = 1. / survey.std

# Add directives to the inversion
Beispiel #10
0
def gettopoCC(mesh, actind, option="top"):
    """
        Get topography from active indices of mesh.
    """

    if mesh._meshType == "TENSOR":

        if mesh.dim == 3:

            mesh2D = Mesh.TensorMesh([mesh.hx, mesh.hy], mesh.x0[:2])
            zc = mesh.gridCC[:, 2]
            ACTIND = actind.reshape((mesh.vnC[0] * mesh.vnC[1], mesh.vnC[2]),
                                    order='F')
            ZC = zc.reshape((mesh.vnC[0] * mesh.vnC[1], mesh.vnC[2]),
                            order='F')
            topoCC = np.zeros(ZC.shape[0])

            for i in range(ZC.shape[0]):
                ind = np.argmax(ZC[i, :][ACTIND[i, :]])
                if option == "top":
                    dz = mesh.hz[ACTIND[i, :]][ind] * 0.5
                elif option == "center":
                    dz = 0.
                else:
                    raise Exception()
                topoCC[i] = (ZC[i, :][ACTIND[i, :]].max() + dz)
            return mesh2D, topoCC

        elif mesh.dim == 2:

            mesh1D = Mesh.TensorMesh([mesh.hx], [mesh.x0[0]])
            yc = mesh.gridCC[:, 1]
            ACTIND = actind.reshape((mesh.vnC[0], mesh.vnC[1]), order='F')
            YC = yc.reshape((mesh.vnC[0], mesh.vnC[1]), order='F')
            topoCC = np.zeros(YC.shape[0])
            for i in range(YC.shape[0]):
                ind = np.argmax(YC[i, :][ACTIND[i, :]])
                if option == "top":
                    dy = mesh.hy[ACTIND[i, :]][ind] * 0.5
                elif option == "center":
                    dy = 0.
                else:
                    raise Exception()
                topoCC[i] = (YC[i, :][ACTIND[i, :]].max() + dy)
            return mesh1D, topoCC

    elif mesh._meshType == "TREE":
        if mesh.dim == 3:
            uniqXY = uniqueRows(mesh.gridCC[:, :2])
            npts = uniqXY[0].shape[0]
            ZC = mesh.gridCC[:, 2]
            topoCC = np.zeros(npts)
            if option == "top":
                # TODO: this assume same hz, need to be modified
                dz = mesh.hz.min() * 0.5
            elif option == "center":
                dz = 0.
            for i in range(npts):
                inds = uniqXY[2] == i
                actind_z = actind[inds]
                if actind_z.sum() > 0.:
                    topoCC[i] = (ZC[inds][actind_z]).max() + dz
                else:
                    topoCC[i] = (ZC[inds]).max() + dz
            return uniqXY[0], topoCC
        else:
            raise NotImplementedError(
                "gettopoCC is not implemented for Quad tree mesh")
Beispiel #11
0
def readUBC_DC2DMesh(fileName):
    """
        Read UBC GIF 2DTensor mesh and generate 2D Tensor mesh in simpeg

        Input:
        :param fileName, path to the UBC GIF mesh file

        Output:
        :param SimPEG TensorMesh 2D object
        :return

        Created on Thu Nov 12 13:14:10 2015

        @author: dominiquef

    """

    from SimPEG import np
    # Open file
    fopen = open(fileName,'r')

    # Read down the file and unpack dx vector
    def unpackdx(fid,nrows):
        for ii in range(nrows):

            line = fid.readline()
            var = np.array(line.split(),dtype=float)

            if ii==0:
                x0= var[0]
                xvec = np.ones(int(var[2])) * (var[1] - var[0]) / int(var[2])
                xend = var[1]

            else:
                xvec = np.hstack((xvec,np.ones(int(var[1])) * (var[0] - xend) / int(var[1])))
                xend = var[0]

        return x0, xvec

    #%% Start with dx block
    # First line specifies the number of rows for x-cells
    line = fopen.readline()
    nl = np.array(line.split(),dtype=float)

    [x0, dx] = unpackdx(fopen,nl)


    #%% Move down the file until reaching the z-block
    line = fopen.readline()
    if not line:
        line = fopen.readline()

    #%% End with dz block
    # First line specifies the number of rows for z-cells
    line = fopen.readline()
    nl = np.array(line.split(),dtype=float)

    [z0, dz] = unpackdx(fopen,nl)

    # Flip z0 to be the bottom of the mesh for SimPEG
    z0 = z0 - sum(dz)
    dz = dz[::-1]
    #%% Make the mesh using SimPEG

    from SimPEG import Mesh
    tensMsh = Mesh.TensorMesh([dx,dz],(x0, z0))
    return tensMsh
def run(plotIt=True):

    M = Mesh.TensorMesh([np.ones(40)], x0='N')
    M.setCellGradBC('dirichlet')
    # We will use the haverkamp empirical model with parameters from Celia1990
    k_fun, theta_fun = Richards.Empirical.haverkamp(M,
                                                    A=1.1750e+06,
                                                    gamma=4.74,
                                                    alpha=1.6110e+06,
                                                    theta_s=0.287,
                                                    theta_r=0.075,
                                                    beta=3.96)

    # Here we are making saturated hydraulic conductivity
    # an exponential mapping to the model (defined below)
    k_fun.KsMap = Maps.ExpMap(nP=M.nC)

    # Setup the boundary and initial conditions
    bc = np.array([-61.5, -20.7])
    h = np.zeros(M.nC) + bc[0]
    prob = Richards.RichardsProblem(M,
                                    hydraulic_conductivity=k_fun,
                                    water_retention=theta_fun,
                                    boundary_conditions=bc,
                                    initial_conditions=h,
                                    do_newton=False,
                                    method='mixed',
                                    debug=False)
    prob.timeSteps = [(5, 25, 1.1), (60, 40)]

    # Create the survey
    locs = -np.arange(2, 38, 4.)
    times = np.arange(30, prob.timeMesh.vectorCCx[-1], 60)
    rxSat = Richards.SaturationRx(locs, times)
    survey = Richards.RichardsSurvey([rxSat])
    survey.pair(prob)

    # Create a simple model for Ks
    Ks = 1e-3
    mtrue = np.ones(M.nC) * np.log(Ks)
    mtrue[15:20] = np.log(5e-2)
    mtrue[20:35] = np.log(3e-3)
    mtrue[35:40] = np.log(1e-2)

    # Create some synthetic data and fields
    Hs = prob.fields(mtrue)
    data = survey.makeSyntheticData(mtrue, std=0, f=Hs, force=True)

    if plotIt:
        plt.figure(figsize=(14, 9))

        plt.subplot(221)
        plt.plot(np.log10(np.exp(mtrue)), M.gridCC)
        plt.title('(a) True model and data locations')
        plt.ylabel('Depth, cm')
        plt.xlabel('Hydraulic conductivity, $log_{10}(K_s)$')
        plt.plot([-3.25] * len(locs), locs, 'ro')
        plt.legend(('True model', 'Data locations'))

        plt.subplot(222)
        plt.plot(times / 60, data.reshape((-1, len(locs))))
        plt.title('(b) True data over time at all depths')
        plt.xlabel('Time, minutes')
        plt.ylabel('Saturation')

        ax = plt.subplot(212)
        mesh2d = Mesh.TensorMesh([prob.timeMesh.hx / 60, prob.mesh.hx], '0N')
        sats = [theta_fun(_) for _ in Hs]
        clr = mesh2d.plotImage(np.c_[sats][1:, :], ax=ax)
        cmap0 = matplotlib.cm.RdYlBu_r
        clr[0].set_cmap(cmap0)
        c = plt.colorbar(clr[0])
        c.set_label('Saturation $\\theta$')
        plt.xlabel('Time, minutes')
        plt.ylabel('Depth, cm')
        plt.title('(c) Saturation over time')

        plt.tight_layout()
Beispiel #13
0
def getDiffOpRot(mesh, psi, theta, phi, vec, forward=True):

    hz = np.kron(mesh.hz, np.kron(np.ones(mesh.vnC[1]), np.ones(mesh.vnC[0])))
    hy = np.kron(np.ones(mesh.vnC[2]), np.kron(mesh.hy, np.ones(mesh.vnC[0])))
    hx = np.kron(np.ones(mesh.vnC[2]), np.kron(np.ones(mesh.vnC[1]), mesh.hx))

    unitMesh = Mesh.TensorMesh([np.ones(3), np.ones(3), np.ones(3)], x0='CCC')

    stencil = []
    for ii in range(unitMesh.nC):
        stencil += [
            np.kron(np.r_[-1, 1], [0.5, 0.5, 0.5]).reshape(
                (2, 3)) + np.kron(np.ones(2), unitMesh.gridCC[ii, :]).reshape(
                    (2, 3))
        ]

    if isinstance(theta, float):
        theta = np.ones(mesh.nC) * theta

    if isinstance(phi, float):
        phi = np.ones(mesh.nC) * phi

    if isinstance(psi, float):
        psi = np.ones(mesh.nC) * psi

    if forward:
        ind = 1
    else:
        ind = -1

    if vec == 'X':
        px = np.kron(np.ones(mesh.nC), np.c_[ind, 0, 0])
        theta = np.arctan2((np.sin(theta) / hz), (np.cos(theta) / hx))
        phi = np.arctan2((np.sin(phi) / hy), (np.cos(phi) / hx))
        psi = np.arctan2((np.sin(psi) / hz), (np.cos(psi) / hy))

    elif vec == 'Y':
        px = np.kron(np.ones(mesh.nC), np.c_[0, ind, 0])
        theta = np.arctan2((np.sin(theta) / hz), (np.cos(theta) / hx))
        phi = np.arctan2((np.sin(phi) / hx), (np.cos(phi) / hy))
        psi = np.arctan2((np.sin(psi) / hz), (np.cos(psi) / hy))

    else:
        px = np.kron(np.ones(mesh.nC), np.c_[0, 0, ind])
        theta = np.arctan2((np.sin(theta) / hx), (np.cos(theta) / hz))
        phi = np.arctan2((np.sin(phi) / hy), (np.cos(phi) / hx))
        psi = np.arctan2((np.sin(psi) / hy), (np.cos(psi) / hz))

    #     v = np.ones((mesh.nC,27))
    #     for ii in range(mesh.nC):


#     S = Utils.sdiag(mkvc(np.c_[1/ratiox**0.5, 1/ratioy**0.5, 1/ratioz**0.5]))

# Create sparse rotation operators
    rxa = mkvc(np.c_[np.ones(mesh.nC), np.cos(psi), np.cos(psi)].T)
    rxb = mkvc(np.c_[np.zeros(mesh.nC), np.sin(psi), np.zeros(mesh.nC)].T)
    rxc = mkvc(np.c_[np.zeros(mesh.nC), -np.sin(psi), np.zeros(mesh.nC)].T)
    Rx = sp.sparse.diags([rxb[:-1], rxa, rxc[:-1]], [-1, 0, 1])

    rya = mkvc(np.c_[np.cos(theta), np.ones(mesh.nC), np.cos(theta)].T)
    ryb = mkvc(np.c_[-np.sin(theta), np.zeros(mesh.nC), np.zeros(mesh.nC)].T)
    ryc = mkvc(np.c_[np.sin(theta), np.zeros(mesh.nC), np.zeros(mesh.nC)].T)
    Ry = sp.sparse.diags([ryb[:-2], rya, ryc[:-2]], [-2, 0, 2])

    rza = mkvc(np.c_[np.cos(phi), np.cos(phi), np.ones(mesh.nC)].T)
    rzb = mkvc(np.c_[np.sin(phi), np.zeros(mesh.nC), np.zeros(mesh.nC)].T)
    rzc = mkvc(np.c_[-np.sin(phi), np.zeros(mesh.nC), np.zeros(mesh.nC)].T)
    Rz = sp.sparse.diags([rzb[:-1], rza, rzc[:-1]], [-1, 0, 1])

    # Rotate all cell vectors
    rx = (Rz * (Ry * (Rx * px.T))).reshape((mesh.nC, 3))

    # Move the bottom-SW and top-NE nodes
    nBSW = np.kron(stencil[13][0], np.ones((mesh.nC, 1))) + rx
    nTNE = np.kron(stencil[13][1], np.ones((mesh.nC, 1))) + rx

    # Compute fractional volumes with base stencil
    V = []
    for s in stencil:

        sBSW = np.kron(s[0], np.ones((mesh.nC, 1)))
        sTNE = np.kron(s[1], np.ones((mesh.nC, 1)))

        V += [(np.max([
            np.min([sTNE[:, 0], nTNE[:, 0]], axis=0) -
            np.max([sBSW[:, 0], nBSW[:, 0]], axis=0),
            np.zeros(mesh.nC)
        ],
                      axis=0) * np.max([
                          np.min([sTNE[:, 1], nTNE[:, 1]], axis=0) -
                          np.max([sBSW[:, 1], nBSW[:, 1]], axis=0),
                          np.zeros(mesh.nC)
                      ],
                                       axis=0) *
               np.max([
                   np.min([sTNE[:, 2], nTNE[:, 2]], axis=0) -
                   np.max([sBSW[:, 2], nBSW[:, 2]], axis=0),
                   np.zeros(mesh.nC)
               ],
                      axis=0))]

    count = -1
    Gx = speye(mesh.nC)

    for ii in range(3):
        flagz = [0, 0, 0]
        flagz[ii] = 1

        for jj in range(3):
            flagy = [0, 0, 0]
            flagy[jj] = 1

            for kk in range(3):

                flagx = [0, 0, 0]
                flagx[kk] = 1

                count += 1
                Gx -= sdiag(np.ones(mesh.nC) * V[count]) * kron3(
                    ddx(mesh.nCz, flagz), ddx(mesh.nCy, flagy),
                    ddx(mesh.nCx, flagx))

    return Gx, rx
Beispiel #14
0
def run(plotIt=True):

    cs, ncx, ncz, npad = 5., 25, 15, 15
    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')

    active = mesh.vectorCCz < 0.
    layer = (mesh.vectorCCz < 0.) & (mesh.vectorCCz >= -100.)
    actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
    mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap
    sig_half = 2e-3
    sig_air = 1e-8
    sig_layer = 1e-3
    sigma = np.ones(mesh.nCz) * sig_air
    sigma[active] = sig_half
    sigma[layer] = sig_layer
    mtrue = np.log(sigma[active])

    rxOffset = 1e-3
    rx = EM.TDEM.Rx.Point_dbdt(np.array([[rxOffset, 0., 30]]),
                               np.logspace(-5, -3, 31), 'z')
    src = EM.TDEM.Src.MagDipole([rx], loc=np.array([0., 0., 80]))
    survey = EM.TDEM.Survey([src])
    prb = EM.TDEM.Problem3D_e(mesh, sigmaMap=mapping)

    prb.Solver = SolverLU
    prb.timeSteps = [(1e-06, 20), (1e-05, 20), (0.0001, 20)]
    prb.pair(survey)

    # create observed data
    std = 0.05

    survey.dobs = survey.makeSyntheticData(mtrue, std)
    survey.std = std
    survey.eps = 1e-5 * np.linalg.norm(survey.dobs)

    dmisfit = DataMisfit.l2_DataMisfit(survey)
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Tikhonov(regMesh, alpha_s=1e-2, alpha_x=1.)
    opt = Optimization.InexactGaussNewton(maxIter=5, LSshorten=0.5)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    # Create an inversion object
    beta = Directives.BetaSchedule(coolingFactor=5, coolingRate=2)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
    inv = Inversion.BaseInversion(invProb, directiveList=[beta, betaest])
    m0 = np.log(np.ones(mtrue.size) * sig_half)
    prb.counter = opt.counter = Utils.Counter()
    opt.remember('xc')

    mopt = inv.run(m0)

    if plotIt:
        fig, ax = plt.subplots(1, 2, figsize=(10, 6))
        ax[0].loglog(rx.times, survey.dtrue, 'b.-')
        ax[0].loglog(rx.times, survey.dobs, 'r.-')
        ax[0].legend(('Noisefree', '$d^{obs}$'), fontsize=16)
        ax[0].set_xlabel('Time (s)', fontsize=14)
        ax[0].set_ylabel('$B_z$ (T)', fontsize=16)
        ax[0].set_xlabel('Time (s)', fontsize=14)
        ax[0].grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5)

        plt.semilogx(sigma[active], mesh.vectorCCz[active])
        plt.semilogx(np.exp(mopt), mesh.vectorCCz[active])
        ax[1].set_ylim(-600, 0)
        ax[1].set_xlim(1e-4, 1e-2)
        ax[1].set_xlabel('Conductivity (S/m)', fontsize=14)
        ax[1].set_ylabel('Depth (m)', fontsize=14)
        ax[1].grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5)
        plt.legend(['$\sigma_{true}$', '$\sigma_{pred}$'])
Beispiel #15
0
def run_simulation(fname="tdem_gs_half.h5",
                   sigma_block=0.01,
                   sigma_halfspace=0.01):
    from SimPEG.EM import TDEM, Analytics, mu_0
    import numpy as np
    from SimPEG import Mesh, Maps, Utils, EM, Survey
    from pymatsolver import Pardiso

    cs = 20
    ncx, ncy, ncz = 20, 20, 20
    npad = 10
    hx = [(cs, npad, -1.5), (cs, ncx), (cs, npad, 1.5)]
    hy = [(cs, npad, -1.5), (cs, ncy), (cs, npad, 1.5)]
    hz = [(cs, npad, -1.5), (cs, ncz), (cs, npad, 1.5)]
    mesh = Mesh.TensorMesh([hx, hy, hz], "CCC")
    sigma = np.ones(mesh.nC) * sigma_halfspace
    blk_ind = Utils.ModelBuilder.getIndicesBlock(np.r_[-40, -40, -160],
                                                 np.r_[40, 40,
                                                       -80], mesh.gridCC)
    sigma[mesh.gridCC[:, 2] > 0.0] = 1e-8
    sigma[blk_ind] = sigma_block

    xmin, xmax = -200.0, 200.0
    ymin, ymax = -200.0, 200.0
    x = mesh.vectorCCx[np.logical_and(mesh.vectorCCx > xmin,
                                      mesh.vectorCCx < xmax)]
    y = mesh.vectorCCy[np.logical_and(mesh.vectorCCy > ymin,
                                      mesh.vectorCCy < ymax)]
    xyz = Utils.ndgrid(x, y, np.r_[-1.0])

    px = np.r_[-200.0, 200.0]
    py = np.r_[0.0, 0.0]
    pz = np.r_[0.0, 0.0]
    srcLoc = np.c_[px, py, pz]

    from scipy.interpolate import interp1d

    prb = TDEM.Problem3D_b(mesh, sigma=sigma, verbose=True)
    prb.Solver = Pardiso
    prb.solverOpts = {"is_symmetric": False}
    prb.timeSteps = [(1e-3, 10), (2e-5, 10), (1e-4, 10), (5e-4, 10),
                     (1e-3, 10)]
    t0 = 0.01 + 1e-4
    out = EM.Utils.VTEMFun(prb.times, 0.01, t0, 200)
    wavefun = interp1d(prb.times, out)
    waveform = EM.TDEM.Src.RawWaveform(offTime=t0, waveFct=wavefun)
    input_currents = wavefun(prb.times)

    times = np.logspace(-4, -2, 21)
    rx_ex = TDEM.Rx.Point_e(xyz, times + t0, orientation="x")
    rx_ey = TDEM.Rx.Point_e(xyz, times + t0, orientation="y")
    rx_by = TDEM.Rx.Point_e(xyz, times + t0, orientation="y")

    rxList = [rx_ex, rx_ey, rx_by]
    src = TDEM.Src.LineCurrent(rxList, loc=srcLoc, waveform=waveform)
    survey = TDEM.Survey([src])
    survey.pair(prb)

    f = prb.fields(sigma)

    xyzlim = np.array([[xmin, xmax], [ymin, ymax], [-400, 0.0]])
    actinds, meshCore = Utils.ExtractCoreMesh(xyzlim, mesh)
    Pex = mesh.getInterpolationMat(meshCore.gridCC, locType="Ex")
    Pey = mesh.getInterpolationMat(meshCore.gridCC, locType="Ey")
    Pez = mesh.getInterpolationMat(meshCore.gridCC, locType="Ez")
    Pfx = mesh.getInterpolationMat(meshCore.gridCC, locType="Fx")
    Pfy = mesh.getInterpolationMat(meshCore.gridCC, locType="Fy")
    Pfz = mesh.getInterpolationMat(meshCore.gridCC, locType="Fz")

    sigma_core = sigma[actinds]

    def getEBJcore(src0):
        B0 = np.r_[Pfx * f[src0, "b"], Pfy * f[src0, "b"], Pfz * f[src0, "b"]]
        E0 = np.r_[Pex * f[src0, "e"], Pey * f[src0, "e"], Pez * f[src0, "e"]]
        J0 = Utils.sdiag(np.r_[sigma_core, sigma_core, sigma_core]) * E0
        return E0, B0, J0

    E, B, J = getEBJcore(src)
    tdem_gs = {
        "E": E,
        "B": B,
        "J": J,
        "sigma": sigma_core,
        "mesh": meshCore.serialize(),
        "time": prb.times - t0,
        "input_currents": input_currents,
    }
    dd.io.save(fname, tdem_gs)
Beispiel #16
0
pad_x_factor = 1.3
pad_y_factor = 1.3
pad_z_factor = 1.3

# =============================================================================
# 
# =============================================================================
### ( initial width, number of cells, increase by factor)
### (pad, center, pad)
hx_ind = [(dx, pad_x, -pad_x_factor), (dx, nx), (dx, pad_x, pad_x_factor)]
hy_ind = [(dy, pad_y, -pad_y_factor), (dy, ny), (dy, pad_y, pad_y_factor)]
hz_ind = [(dz, pad_z, -pad_z_factor), (dz, nz), (3.5, 1), (2, 5)]

### make a mesh
mesh = Mesh.TensorMesh([hx_ind, hy_ind, hz_ind], 'CCC')

# Get index of the center
mid_x = int(mesh.nCx/2)
mid_y = int(mesh.nCy/2)

# Lets create a simple Gaussian topo and set the active cells
[xx, yy] = np.meshgrid(mesh.vectorNx, mesh.vectorNy)
zz = -np.exp((xx**2 + yy**2) / 75**2) + mesh.vectorNz[-1]

### We would usually load a topofile
topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)]

### Go from topo to array of indices of active cells
active_cells = Utils.surface2ind_topo(mesh, topo, 'N')
active_cells = np.where(active_cells)[0]
def halfSpaceProblemAnaDiff(meshType,
                            srctype="MagDipole",
                            sig_half=1e-2,
                            rxOffset=50.,
                            bounds=None,
                            plotIt=False,
                            rxType='bz'):

    if bounds is None:
        bounds = [1e-5, 1e-3]
    if meshType == 'CYL':
        cs, ncx, ncz, npad = 15., 30, 10, 15
        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')

    elif meshType == 'TENSOR':
        cs, nc, npad = 20., 13, 5
        hx = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)]
        hy = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)]
        hz = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)]
        mesh = Mesh.TensorMesh([hx, hy, hz], 'CCC')

    active = mesh.vectorCCz < 0.
    actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
    mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap

    prb = EM.TDEM.Problem3D_b(mesh, sigmaMap=mapping)
    prb.Solver = Solver
    prb.timeSteps = [(1e-3, 5), (1e-4, 5), (5e-5, 10), (5e-5, 10), (1e-4, 10)]
    out = EM.Utils.VTEMFun(prb.times, 0.00595, 0.006, 100)
    wavefun = interp1d(prb.times, out)
    t0 = 0.006
    waveform = EM.TDEM.Src.RawWaveform(offTime=t0, waveFct=wavefun)

    rx = getattr(EM.TDEM.Rx,
                 'Point_{}'.format(rxType[:-1]))(np.array([[rxOffset, 0.,
                                                            0.]]),
                                                 np.logspace(-4, -3, 31) + t0,
                                                 rxType[-1])

    if srctype == "MagDipole":
        src = EM.TDEM.Src.MagDipole([rx],
                                    waveform=waveform,
                                    loc=np.array([0, 0., 0.]))
    elif srctype == "CircularLoop":
        src = EM.TDEM.Src.CircularLoop([rx],
                                       waveform=waveform,
                                       loc=np.array([0., 0., 0.]),
                                       radius=13.)

    survey = EM.TDEM.Survey([src])
    prb.pair(survey)

    sigma = np.ones(mesh.nCz) * 1e-8
    sigma[active] = sig_half
    sigma = np.log(sigma[active])

    if srctype == "MagDipole":
        bz_ana = mu_0 * EM.Analytics.hzAnalyticDipoleT(rx.locs[0][0] + 1e-3,
                                                       rx.times - t0, sig_half)
    elif srctype == "CircularLoop":
        bz_ana = mu_0 * EM.Analytics.hzAnalyticCentLoopT(
            13, rx.times - t0, sig_half)

    bz_calc = survey.dpred(sigma)
    ind = np.logical_and(rx.times - t0 > bounds[0], rx.times - t0 < bounds[1])
    log10diff = (np.linalg.norm(
        np.log10(np.abs(bz_calc[ind])) - np.log10(np.abs(bz_ana[ind]))) /
                 np.linalg.norm(np.log10(np.abs(bz_ana[ind]))))

    print(' |bz_ana| = {ana} |bz_num| = {num} |bz_ana-bz_num| = {diff}'.format(
        ana=np.linalg.norm(bz_ana),
        num=np.linalg.norm(bz_calc),
        diff=np.linalg.norm(bz_ana - bz_calc)))
    print('Difference: {}'.format(log10diff))

    if plotIt is True:
        plt.loglog(rx.times[bz_calc > 0] - t0, bz_calc[bz_calc > 0], 'r',
                   rx.times[bz_calc < 0] - t0, -bz_calc[bz_calc < 0], 'r--')
        plt.loglog(rx.times - t0, abs(bz_ana), 'b*')
        plt.title('sig_half = {:e}'.format(sig_half))
        plt.show()

    return log10diff
Beispiel #18
0
def run(plotIt=True, saveFig=False, cleanup=True):
    """
    Run 1D inversions for a single sounding of the RESOLVE and SkyTEM
    bookpurnong data

    :param bool plotIt: show the plots?
    :param bool saveFig: save the figure
    :param bool cleanup: remove the downloaded results
    """
    downloads, directory = download_and_unzip_data()

    resolve = h5py.File(os.path.sep.join([directory, "booky_resolve.hdf5"]),
                        "r")
    skytem = h5py.File(os.path.sep.join([directory, "booky_skytem.hdf5"]), "r")
    river_path = resolve["river_path"].value

    # Choose a sounding location to invert
    xloc, yloc = 462100.0, 6196500.0
    rxind_skytem = np.argmin(
        abs(skytem["xy"][:, 0] - xloc) + abs(skytem["xy"][:, 1] - yloc))
    rxind_resolve = np.argmin(
        abs(resolve["xy"][:, 0] - xloc) + abs(resolve["xy"][:, 1] - yloc))

    # Plot both resolve and skytem data on 2D plane
    fig = plt.figure(figsize=(13, 6))
    title = ["RESOLVE In-phase 400 Hz", "SkyTEM High moment 156 $\mu$s"]
    ax1 = plt.subplot(121)
    ax2 = plt.subplot(122)
    axs = [ax1, ax2]
    out_re = Utils.plot2Ddata(resolve["xy"],
                              resolve["data"][:, 0],
                              ncontour=100,
                              contourOpts={"cmap": "viridis"},
                              ax=ax1)
    vmin, vmax = out_re[0].get_clim()
    cb_re = plt.colorbar(out_re[0],
                         ticks=np.linspace(vmin, vmax, 3),
                         ax=ax1,
                         fraction=0.046,
                         pad=0.04)
    temp_skytem = skytem["data"][:, 5].copy()
    temp_skytem[skytem["data"][:, 5] > 7e-10] = 7e-10
    out_sky = Utils.plot2Ddata(skytem["xy"][:, :2],
                               temp_skytem,
                               ncontour=100,
                               contourOpts={
                                   "cmap": "viridis",
                                   "vmax": 7e-10
                               },
                               ax=ax2)
    vmin, vmax = out_sky[0].get_clim()
    cb_sky = plt.colorbar(out_sky[0],
                          ticks=np.linspace(vmin, vmax * 0.99, 3),
                          ax=ax2,
                          format="%.1e",
                          fraction=0.046,
                          pad=0.04)
    cb_re.set_label("Bz (ppm)")
    cb_sky.set_label("dB$_z$ / dt (V/A-m$^4$)")

    for i, ax in enumerate(axs):
        xticks = [460000, 463000]
        yticks = [6195000, 6198000, 6201000]
        ax.set_xticks(xticks)
        ax.set_yticks(yticks)
        ax.plot(xloc, yloc, 'wo')
        ax.plot(river_path[:, 0], river_path[:, 1], 'k', lw=0.5)

        ax.set_aspect("equal")
        if i == 1:
            ax.plot(skytem["xy"][:, 0],
                    skytem["xy"][:, 1],
                    'k.',
                    alpha=0.02,
                    ms=1)
            ax.set_yticklabels([str(" ") for f in yticks])
        else:
            ax.plot(resolve["xy"][:, 0],
                    resolve["xy"][:, 1],
                    'k.',
                    alpha=0.02,
                    ms=1)
            ax.set_yticklabels([str(f) for f in yticks])
            ax.set_ylabel("Northing (m)")
        ax.set_xlabel("Easting (m)")
        ax.set_title(title[i])
        ax.axis('equal')
    # plt.tight_layout()

    if saveFig is True:
        fig.savefig("resolve_skytem_data.png", dpi=600)

    # ------------------ Mesh ------------------ #
    # Step1: Set 2D cylindrical mesh
    cs, ncx, ncz, npad = 1., 10., 10., 20
    hx = [(cs, ncx), (cs, npad, 1.3)]
    npad = 12
    temp = np.logspace(np.log10(1.), np.log10(12.), 19)
    temp_pad = temp[-1] * 1.3**np.arange(npad)
    hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad]
    mesh = Mesh.CylMesh([hx, 1, hz], '00C')
    active = mesh.vectorCCz < 0.

    # Step2: Set a SurjectVertical1D mapping
    # Note: this sets our inversion model as 1D log conductivity
    # below subsurface

    active = mesh.vectorCCz < 0.
    actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
    mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap
    sig_half = 1e-1
    sig_air = 1e-8
    sigma = np.ones(mesh.nCz) * sig_air
    sigma[active] = sig_half

    # Initial and reference model
    m0 = np.log(sigma[active])

    # ------------------ RESOLVE Forward Simulation ------------------ #
    # Step3: Invert Resolve data

    # Bird height from the surface
    b_height_resolve = resolve["src_elevation"].value
    src_height_resolve = b_height_resolve[rxind_resolve]

    # Set Rx (In-phase and Quadrature)
    rxOffset = 7.86
    bzr = EM.FDEM.Rx.Point_bSecondary(np.array(
        [[rxOffset, 0., src_height_resolve]]),
                                      orientation='z',
                                      component='real')

    bzi = EM.FDEM.Rx.Point_b(np.array([[rxOffset, 0., src_height_resolve]]),
                             orientation='z',
                             component='imag')

    # Set Source (In-phase and Quadrature)
    frequency_cp = resolve["frequency_cp"].value
    freqs = frequency_cp.copy()
    srcLoc = np.array([0., 0., src_height_resolve])
    srcList = [
        EM.FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation='Z')
        for freq in freqs
    ]

    # Set FDEM survey (In-phase and Quadrature)
    survey = EM.FDEM.Survey(srcList)
    prb = EM.FDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=Solver)
    prb.pair(survey)

    # ------------------ RESOLVE Inversion ------------------ #

    # Primary field
    bp = -mu_0 / (4 * np.pi * rxOffset**3)

    # Observed data
    cpi_inds = [0, 2, 6, 8, 10]
    cpq_inds = [1, 3, 7, 9, 11]
    dobs_re = np.c_[resolve["data"][rxind_resolve, :][cpi_inds],
                    resolve["data"][
                        rxind_resolve, :][cpq_inds]].flatten() * bp * 1e-6

    # Uncertainty
    std = np.repeat(np.r_[np.ones(3) * 0.1, np.ones(2) * 0.15], 2)
    floor = 20 * abs(bp) * 1e-6
    uncert = abs(dobs_re) * std + floor

    # Data Misfit
    survey.dobs = dobs_re
    dmisfit = DataMisfit.l2_DataMisfit(survey)
    dmisfit.W = 1. / uncert

    # Regularization
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh, mapping=Maps.IdentityMap(regMesh))

    # Optimization
    opt = Optimization.InexactGaussNewton(maxIter=5)

    # statement of the inverse problem
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    # Inversion directives and parameters
    target = Directives.TargetMisfit()  # stop when we hit target misfit
    invProb.beta = 2.
    # betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
    inv = Inversion.BaseInversion(invProb, directiveList=[target])
    reg.alpha_s = 1e-3
    reg.alpha_x = 1.
    reg.mref = m0.copy()
    opt.LSshorten = 0.5
    opt.remember('xc')
    # run the inversion
    mopt_re = inv.run(m0)
    dpred_re = invProb.dpred

    # ------------------ SkyTEM Forward Simulation ------------------ #
    # Step4: Invert SkyTEM data

    # Bird height from the surface
    b_height_skytem = skytem["src_elevation"].value
    src_height = b_height_skytem[rxind_skytem]
    srcLoc = np.array([[0., 0., src_height]])

    # Radius of the source loop
    area = skytem["area"].value
    radius = np.sqrt(area / np.pi)
    rxLoc = np.array([[radius, 0., src_height]])

    # Parameters for current waveform
    t0 = skytem["t0"].value
    times = skytem["times"].value
    waveform_skytem = skytem["waveform"].value
    offTime = t0
    times_off = times - t0

    # Note: we are Using theoretical VTEM waveform,
    # but effectively fits SkyTEM waveform
    peakTime = 1.0000000e-02
    a = 3.

    dbdt_z = EM.TDEM.Rx.Point_dbdt(locs=rxLoc,
                                   times=times_off[:-3] + offTime,
                                   orientation='z')  # vertical db_dt

    rxList = [dbdt_z]  # list of receivers
    srcList = [
        EM.TDEM.Src.CircularLoop(rxList,
                                 loc=srcLoc,
                                 radius=radius,
                                 orientation='z',
                                 waveform=EM.TDEM.Src.VTEMWaveform(
                                     offTime=offTime, peakTime=peakTime, a=3.))
    ]
    # solve the problem at these times
    timeSteps = [(peakTime / 5, 5), ((offTime - peakTime) / 5, 5), (1e-5, 5),
                 (5e-5, 5), (1e-4, 10), (5e-4, 15)]
    prob = EM.TDEM.Problem3D_e(mesh,
                               timeSteps=timeSteps,
                               sigmaMap=mapping,
                               Solver=Solver)
    survey = EM.TDEM.Survey(srcList)
    prob.pair(survey)

    src = srcList[0]
    rx = src.rxList[0]
    wave = []
    for time in prob.times:
        wave.append(src.waveform.eval(time))
    wave = np.hstack(wave)
    out = survey.dpred(m0)

    # plot the waveform
    fig = plt.figure(figsize=(5, 3))
    times_off = times - t0
    plt.plot(waveform_skytem[:, 0], waveform_skytem[:, 1], 'k.')
    plt.plot(prob.times, wave, 'k-', lw=2)
    plt.legend(("SkyTEM waveform", "Waveform (fit)"), fontsize=10)
    for t in rx.times:
        plt.plot(np.ones(2) * t, np.r_[-0.03, 0.03], 'k-')
    plt.ylim(-0.1, 1.1)
    plt.grid(True)
    plt.xlabel("Time (s)")
    plt.ylabel("Normalized current")

    if saveFig:
        fig.savefig("skytem_waveform", dpi=200)

    # Observed data
    dobs_sky = skytem["data"][rxind_skytem, :-3] * area

    # ------------------ SkyTEM Inversion ------------------ #
    # Uncertainty
    std = 0.12
    floor = 7.5e-12
    uncert = abs(dobs_sky) * std + floor

    # Data Misfit
    survey.dobs = -dobs_sky
    dmisfit = DataMisfit.l2_DataMisfit(survey)
    uncert = 0.12 * abs(dobs_sky) + 7.5e-12
    dmisfit.W = Utils.sdiag(1. / uncert)

    # Regularization
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh, mapping=Maps.IdentityMap(regMesh))

    # Optimization
    opt = Optimization.InexactGaussNewton(maxIter=5)

    # statement of the inverse problem
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)

    # Directives and Inversion Parameters
    target = Directives.TargetMisfit()
    # betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
    invProb.beta = 20.
    inv = Inversion.BaseInversion(invProb, directiveList=[target])
    reg.alpha_s = 1e-1
    reg.alpha_x = 1.
    opt.LSshorten = 0.5
    opt.remember('xc')
    reg.mref = mopt_re  # Use RESOLVE model as a reference model

    # run the inversion
    mopt_sky = inv.run(m0)
    dpred_sky = invProb.dpred

    # Plot the figure from the paper
    plt.figure(figsize=(12, 8))

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

    ax0 = plt.subplot2grid((2, 2), (0, 0), rowspan=2)
    ax1 = plt.subplot2grid((2, 2), (0, 1))
    ax2 = plt.subplot2grid((2, 2), (1, 1))

    # Recovered Models
    sigma_re = np.repeat(np.exp(mopt_re), 2, axis=0)
    sigma_sky = np.repeat(np.exp(mopt_sky), 2, axis=0)
    z = np.repeat(mesh.vectorCCz[active][1:], 2, axis=0)
    z = np.r_[mesh.vectorCCz[active][0], z, mesh.vectorCCz[active][-1]]

    ax0.semilogx(sigma_re, z, 'k', lw=2, label="RESOLVE")
    ax0.semilogx(sigma_sky, z, 'b', lw=2, label="SkyTEM")
    ax0.set_ylim(-50, 0)
    # ax0.set_xlim(5e-4, 1e2)
    ax0.grid(True)
    ax0.set_ylabel("Depth (m)")
    ax0.set_xlabel("Conducivity (S/m)")
    ax0.legend(loc=3)
    ax0.set_title("(a) Recovered Models")

    # RESOLVE Data
    ax1.loglog(frequency_cp,
               dobs_re.reshape((5, 2))[:, 0] / bp * 1e6,
               'k-',
               label="Obs (real)")
    ax1.loglog(frequency_cp,
               dobs_re.reshape((5, 2))[:, 1] / bp * 1e6,
               'k--',
               label="Obs (imag)")
    ax1.loglog(frequency_cp,
               dpred_re.reshape((5, 2))[:, 0] / bp * 1e6,
               'k+',
               ms=10,
               markeredgewidth=2.,
               label="Pred (real)")
    ax1.loglog(frequency_cp,
               dpred_re.reshape((5, 2))[:, 1] / bp * 1e6,
               'ko',
               ms=6,
               markeredgecolor='k',
               markeredgewidth=0.5,
               label="Pred (imag)")
    ax1.set_title("(b) RESOLVE")
    ax1.set_xlabel("Frequency (Hz)")
    ax1.set_ylabel("Bz (ppm)")
    ax1.grid(True)
    ax1.legend(loc=3, fontsize=11)

    # SkyTEM data
    ax2.loglog(times_off[3:] * 1e6, dobs_sky / area, 'b-', label="Obs")
    ax2.loglog(times_off[3:] * 1e6,
               -dpred_sky / area,
               'bo',
               ms=4,
               markeredgecolor='k',
               markeredgewidth=0.5,
               label="Pred")
    ax2.set_xlim(times_off.min() * 1e6 * 1.2, times_off.max() * 1e6 * 1.1)

    ax2.set_xlabel("Time ($\mu s$)")
    ax2.set_ylabel("dBz / dt (V/A-m$^4$)")
    ax2.set_title("(c) SkyTEM High-moment")
    ax2.grid(True)
    ax2.legend(loc=3)

    a3 = plt.axes([0.86, .33, .1, .09], facecolor=[0.8, 0.8, 0.8, 0.6])
    a3.plot(prob.times * 1e6, wave, 'k-')
    a3.plot(rx.times * 1e6,
            np.zeros_like(rx.times),
            'k|',
            markeredgewidth=1,
            markersize=12)
    a3.set_xlim([prob.times.min() * 1e6 * 0.75, prob.times.max() * 1e6 * 1.1])
    a3.set_title('(d) Waveform', fontsize=11)
    a3.set_xticks([prob.times.min() * 1e6, t0 * 1e6, prob.times.max() * 1e6])
    a3.set_yticks([])
    # a3.set_xticklabels(['0', '2e4'])
    a3.set_xticklabels(['-1e4', '0', '1e4'])

    plt.tight_layout()

    if saveFig:
        plt.savefig("booky1D_time_freq.png", dpi=600)

    if plotIt:
        plt.show()

    if cleanup:
        print(os.path.split(directory)[:-1])
        os.remove(
            os.path.sep.join(directory.split()[:-1] +
                             ["._bookpurnong_inversion"]))
        os.remove(downloads)
        shutil.rmtree(directory)
Beispiel #19
0
def run(plotIt=True):
    """
        EM: TDEM: 1D: Inversion with VTEM waveform
        ==========================================

        Here we will create and run a TDEM 1D inversion,
        with VTEM waveform of which initial condition
        is zero, but have some on- and off-time.
    """

    cs, ncx, ncz, npad = 5., 25, 24, 15
    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')

    active = mesh.vectorCCz < 0.
    layer = (mesh.vectorCCz < -50.) & (mesh.vectorCCz >= -150.)
    actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
    mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap
    sig_half = 1e-3
    sig_air = 1e-8
    sig_layer = 1e-2
    sigma = np.ones(mesh.nCz) * sig_air
    sigma[active] = sig_half
    sigma[layer] = sig_layer
    mtrue = np.log(sigma[active])

    x = np.r_[30, 50, 70, 90]
    rxloc = np.c_[x, x * 0., np.zeros_like(x)]

    prb = EM.TDEM.Problem3D_b(mesh, sigmaMap=mapping)
    prb.Solver = Solver
    prb.timeSteps = [(1e-3, 5), (1e-4, 5), (5e-5, 10), (5e-5, 5), (1e-4, 10),
                     (5e-4, 10)]

    # Use VTEM waveform
    out = EM.Utils.VTEMFun(prb.times, 0.00595, 0.006, 100)

    # Forming function handle for waveform using 1D linear interpolation
    wavefun = interp1d(prb.times, out)
    t0 = 0.006
    waveform = EM.TDEM.Src.RawWaveform(offTime=t0, waveFct=wavefun)

    rx = EM.TDEM.Rx.Point_dbdt(rxloc, np.logspace(-4, -2.5, 11) + t0, 'z')
    src = EM.TDEM.Src.CircularLoop([rx],
                                   waveform=waveform,
                                   loc=np.array([0., 0., 0.]),
                                   radius=10.)
    survey = EM.TDEM.Survey([src])
    prb.pair(survey)
    # create observed data
    std = 0.02

    survey.dobs = survey.makeSyntheticData(mtrue, std)
    # dobs = survey.dpred(mtrue)
    survey.std = std
    survey.eps = 1e-11

    dmisfit = DataMisfit.l2_DataMisfit(survey)
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Simple(regMesh)
    opt = Optimization.InexactGaussNewton(maxIter=5, LSshorten=0.5)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)
    target = Directives.TargetMisfit()
    # Create an inversion object
    beta = Directives.BetaSchedule(coolingFactor=1., coolingRate=2.)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
    invProb.beta = 1e2
    inv = Inversion.BaseInversion(invProb, directiveList=[beta, target])
    m0 = np.log(np.ones(mtrue.size) * sig_half)
    prb.counter = opt.counter = Utils.Counter()
    opt.remember('xc')
    mopt = inv.run(m0)

    if plotIt:
        fig, ax = plt.subplots(1, 2, figsize=(10, 6))
        Dobs = survey.dobs.reshape((len(rx.times), len(x)))
        Dpred = invProb.dpred.reshape((len(rx.times), len(x)))
        for i in range(len(x)):
            ax[0].loglog(rx.times - t0, -Dobs[:, i].flatten(), 'k')
            ax[0].loglog(rx.times - t0, -Dpred[:, i].flatten(), 'k.')
            if i == 0:
                ax[0].legend(('$d^{obs}$', '$d^{pred}$'), fontsize=16)
        ax[0].set_xlabel('Time (s)', fontsize=14)
        ax[0].set_ylabel('$db_z / dt$ (nT/s)', fontsize=16)
        ax[0].set_xlabel('Time (s)', fontsize=14)
        ax[0].grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5)

        plt.semilogx(sigma[active], mesh.vectorCCz[active])
        plt.semilogx(np.exp(mopt), mesh.vectorCCz[active])
        ax[1].set_ylim(-600, 0)
        ax[1].set_xlim(1e-4, 1e-1)
        ax[1].set_xlabel('Conductivity (S/m)', fontsize=14)
        ax[1].set_ylabel('Depth (m)', fontsize=14)
        ax[1].grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5)
        plt.legend(['$\sigma_{true}$', '$\sigma_{pred}$'])
    def setUp(self):

        cs = 0.5
        npad = 11
        hx = [(cs, npad, -1.5), (cs, 15), (cs, npad, 1.5)]
        hy = [(cs, npad, -1.5), (cs, 15), (cs, npad, 1.5)]
        hz = [(cs, npad, -1.5), (cs, 15), (cs, npad, 1.5)]
        mesh = Mesh.TensorMesh([hx, hy, hz], x0="CCC")
        sigma = np.ones(mesh.nC) * 1e-2

        # Set up survey parameters for numeric solution
        x = mesh.vectorNx[(mesh.vectorNx > -75.) & (mesh.vectorNx < 75.)]
        y = mesh.vectorNy[(mesh.vectorNy > -75.) & (mesh.vectorNy < 75.)]

        Aloc = np.r_[1.25, 0., 0.]
        Bloc = np.r_[-1.25, 0., 0.]
        M = Utils.ndgrid(x - 25., y, np.r_[0.])
        N = Utils.ndgrid(x + 25., y, np.r_[0.])

        rx = DC.Rx.Dipole(M, N)
        src = DC.Src.Dipole([rx], Aloc, Bloc)
        survey = DC.Survey([src])

        # Create Dipole Obj for Analytic Solution
        edipole = fdem.ElectricDipoleWholeSpace(
            sigma=1e-2,  # conductivity of 1 S/m
            mu=mu_0,  # permeability of free space (this is the default)
            epsilon=
            epsilon_0,  # permittivity of free space (this is the default)
            location=np.r_[0., 0., 0.],  # location of the dipole
            orientation='X',  # horizontal dipole (can also be a unit-vector)
            quasistatic=True,  # don't use the quasistatic assumption
            frequency=0.0,  # DC
            length=2.5  # length of dipole
        )

        # evaluate the electric field and current density
        Ex_analytic = np.zeros_like([mesh.nEx, 1])
        Ey_analytic = np.zeros_like([mesh.nEy, 1])
        Ez_analytic = np.zeros_like([mesh.nEz, 1])
        Ex_analytic = np.real(edipole.electric_field(mesh.gridEx))[:, 0]
        Ey_analytic = np.real(edipole.electric_field(mesh.gridEy))[:, 1]
        Ez_analytic = np.real(edipole.electric_field(mesh.gridEz))[:, 2]
        E_analytic = np.hstack([Ex_analytic, Ey_analytic, Ez_analytic])

        Jx_analytic = np.zeros_like([mesh.nEx, 1])
        Jy_analytic = np.zeros_like([mesh.nEy, 1])
        Jz_analytic = np.zeros_like([mesh.nEz, 1])
        Jx_analytic = np.real(edipole.current_density(mesh.gridEx))[:, 0]
        Jy_analytic = np.real(edipole.current_density(mesh.gridEy))[:, 1]
        Jz_analytic = np.real(edipole.current_density(mesh.gridEz))[:, 2]
        J_analytic = np.hstack([Jx_analytic, Jy_analytic, Jz_analytic])

        # Find edges at which to compare solutions
        edgeGrid = np.vstack([mesh.gridEx, mesh.gridEy, mesh.gridEz])
        # print(faceGrid.shape)

        ROI_large_BNW = np.array([-75, 75, -75])
        ROI_large_TSE = np.array([75, -75, 75])
        ROI_largeInds = Utils.ModelBuilder.getIndicesBlock(
            ROI_large_BNW, ROI_large_TSE, edgeGrid)[0]
        # print(ROI_largeInds.shape)

        ROI_small_BNW = np.array([-4, 4, -4])
        ROI_small_TSE = np.array([4, -4, 4])
        ROI_smallInds = Utils.ModelBuilder.getIndicesBlock(
            ROI_small_BNW, ROI_small_TSE, edgeGrid)[0]
        # print(ROI_smallInds.shape)

        ROIedgeInds = np.setdiff1d(ROI_largeInds, ROI_smallInds)
        # print(ROIedgeInds.shape)
        # print(len(ROI_largeInds) - len(ROI_smallInds))

        self.survey = survey
        self.mesh = mesh
        self.sigma = sigma
        self.E_analytic = E_analytic
        self.J_analytic = J_analytic
        self.ROIedgeInds = ROIedgeInds
Beispiel #21
0
 def test_ParametricPolyMap(self):
     M2 = Mesh.TensorMesh([np.ones(10), np.ones(10)], "CN")
     mParamPoly = Maps.ParametricPolyMap(M2, 2, logSigma=True, normal='Y')
     self.assertTrue(mParamPoly.test(m=np.r_[1., 1., 0., 0., 0.]))
     self.assertTrue(mParamPoly.testVec(m=np.r_[1., 1., 0., 0., 0.]))
Beispiel #22
0
def getFDEMProblem(fdemType, comp, SrcList, freq, useMu=False, verbose=False):
    cs = 10.
    ncx, ncy, ncz = 0, 0, 0
    npad = 8
    hx = [(cs, npad, -1.3), (cs, ncx), (cs, npad, 1.3)]
    hy = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)]
    hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)]
    mesh = Mesh.TensorMesh([hx, hy, hz], ['C', 'C', 'C'])

    if useMu is True:
        mapping = [('sigma', Maps.ExpMap(mesh)),
                   ('mu', Maps.IdentityMap(mesh))]
    else:
        mapping = Maps.ExpMap(mesh)

    x = np.array(
        [np.linspace(-5. * cs, -2. * cs, 3),
         np.linspace(5. * cs, 2. * cs, 3)]
    ) + cs / 4.  #don't sample right by the source, slightly off alignment from either staggered grid
    XYZ = Utils.ndgrid(x, x, np.linspace(-2. * cs, 2. * cs, 5))
    Rx0 = getattr(EM.FDEM.Rx, 'Point_' + comp[0])
    if comp[2] == 'r':
        real_or_imag = 'real'
    elif comp[2] == 'i':
        real_or_imag = 'imag'
    rx0 = Rx0(XYZ, comp[1], 'imag')

    Src = []

    for SrcType in SrcList:
        if SrcType is 'MagDipole':
            Src.append(
                EM.FDEM.Src.MagDipole([rx0], freq=freq, loc=np.r_[0., 0., 0.]))
        elif SrcType is 'MagDipole_Bfield':
            Src.append(
                EM.FDEM.Src.MagDipole_Bfield([rx0],
                                             freq=freq,
                                             loc=np.r_[0., 0., 0.]))
        elif SrcType is 'CircularLoop':
            Src.append(
                EM.FDEM.Src.CircularLoop([rx0],
                                         freq=freq,
                                         loc=np.r_[0., 0., 0.]))
        elif SrcType is 'RawVec':
            if fdemType is 'e' or fdemType is 'b':
                S_m = np.zeros(mesh.nF)
                S_e = np.zeros(mesh.nE)
                S_m[Utils.closestPoints(mesh, [0., 0., 0.], 'Fz') +
                    np.sum(mesh.vnF[:1])] = 1e-3
                S_e[Utils.closestPoints(mesh, [0., 0., 0.], 'Ez') +
                    np.sum(mesh.vnE[:1])] = 1e-3
                Src.append(
                    EM.FDEM.Src.RawVec([rx0], freq, S_m,
                                       mesh.getEdgeInnerProduct() * S_e))

            elif fdemType is 'h' or fdemType is 'j':
                S_m = np.zeros(mesh.nE)
                S_e = np.zeros(mesh.nF)
                S_m[Utils.closestPoints(mesh, [0., 0., 0.], 'Ez') +
                    np.sum(mesh.vnE[:1])] = 1e-3
                S_e[Utils.closestPoints(mesh, [0., 0., 0.], 'Fz') +
                    np.sum(mesh.vnF[:1])] = 1e-3
                Src.append(
                    EM.FDEM.Src.RawVec([rx0], freq,
                                       mesh.getEdgeInnerProduct() * S_m, S_e))

    if verbose:
        print('  Fetching {0!s} problem'.format((fdemType)))

    if fdemType == 'e':
        survey = EM.FDEM.Survey(Src)
        prb = EM.FDEM.Problem3D_e(mesh, mapping=mapping)

    elif fdemType == 'b':
        survey = EM.FDEM.Survey(Src)
        prb = EM.FDEM.Problem3D_b(mesh, mapping=mapping)

    elif fdemType == 'j':
        survey = EM.FDEM.Survey(Src)
        prb = EM.FDEM.Problem3D_j(mesh, mapping=mapping)

    elif fdemType == 'h':
        survey = EM.FDEM.Survey(Src)
        prb = EM.FDEM.Problem3D_h(mesh, mapping=mapping)

    else:
        raise NotImplementedError()
    prb.pair(survey)

    try:
        from pymatsolver import PardisoSolver
        prb.Solver = PardisoSolver
    except ImportError:
        prb.Solver = SolverLU
    # prb.solverOpts = dict(check_accuracy=True)

    return prb
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)
Beispiel #24
0
def meshBuilder(xyz, h, padDist, meshGlobal=None,
                expFact=1.3,
                meshType='TENSOR',
                verticalAlignment='top'):
    """
        Function to quickly generate a Tensor mesh
        given a cloud of xyz points, finest core cell size
        and padding distance.
        If a meshGlobal is provided, the core cells will be centered
        on the underlaying mesh to reduce interpolation errors.

        :param numpy.ndarray xyz: n x 3 array of locations [x, y, z]
        :param numpy.ndarray h: 1 x 3 cell size for the core mesh
        :param numpy.ndarray padDist: 2 x 3 padding distances [W,E,S,N,Down,Up]
        [OPTIONAL]
        :param numpy.ndarray padCore: Number of core cells around the xyz locs
        :object SimPEG.Mesh: Base mesh used to shift the new mesh for overlap
        :param float expFact: Expension factor for padding cells [1.3]
        :param string meshType: Specify output mesh type: "TensorMesh"

        RETURNS:
        :object SimPEG.Mesh: Mesh object

    """

    assert meshType in ['TENSOR', 'TREE'], ('Revise meshType. Only ' +
                                            ' TENSOR | TREE mesh ' +
                                            'are implemented')

    # Get extent of points
    limx = np.r_[xyz[:, 0].max(), xyz[:, 0].min()]
    limy = np.r_[xyz[:, 1].max(), xyz[:, 1].min()]
    limz = np.r_[xyz[:, 2].max(), xyz[:, 2].min()]

    # Get center of the mesh
    midX = np.mean(limx)
    midY = np.mean(limy)

    if verticalAlignment == 'center':
        midZ = np.mean(limz)
    else:
        midZ = limz[0]

    nCx = int(limx[0]-limx[1]) / h[0]
    nCy = int(limy[0]-limy[1]) / h[1]
    nCz = int(np.max([
            limz[0]-limz[1],
            int(np.min(np.r_[nCx*h[0], nCy*h[1]])/3)
            ]) / h[2])

    if meshType == 'TENSOR':
        # Make sure the core has odd number of cells for centereing
        # on global mesh
        if meshGlobal is not None:
            nCx += 1 - int(nCx % 2)
            nCy += 1 - int(nCy % 2)
            nCz += 1 - int(nCz % 2)

        # Figure out paddings
        def expand(dx, pad):
            L = 0
            nC = 0
            while L < pad:
                nC += 1
                L = np.sum(dx * expFact**(np.asarray(range(nC))+1))

            return nC

        # Figure number of padding cells required to fill the space
        npadEast = expand(h[0], padDist[0, 0])
        npadWest = expand(h[0], padDist[0, 1])
        npadSouth = expand(h[1], padDist[1, 0])
        npadNorth = expand(h[1], padDist[1, 1])
        npadDown = expand(h[2], padDist[2, 0])
        npadUp = expand(h[2], padDist[2, 1])

        # Create discretization
        hx = [(h[0], npadWest, -expFact),
              (h[0], nCx),
              (h[0], npadEast, expFact)]
        hy = [(h[1], npadSouth, -expFact),
              (h[1], nCy), (h[1],
              npadNorth, expFact)]
        hz = [(h[2], npadDown, -expFact),
              (h[2], nCz),
              (h[2], npadUp, expFact)]

        # Create mesh
        mesh = Mesh.TensorMesh([hx, hy, hz], 'CC0')

        # Re-set the mesh at the center of input locations
        # Set origin
        if verticalAlignment == 'center':
            mesh.x0 = [midX-np.sum(mesh.hx)/2., midY-np.sum(mesh.hy)/2., midZ - np.sum(mesh.hz)/2.]
        elif verticalAlignment == 'top':
            mesh.x0 = [midX-np.sum(mesh.hx)/2., midY-np.sum(mesh.hy)/2., midZ - np.sum(mesh.hz)]
        else:
            assert NotImplementedError("verticalAlignment must be 'center' | 'top'")

    elif meshType == 'TREE':

        # Figure out full extent required from input
        extent = np.max(np.r_[nCx * h[0] + padDist[0, :].sum(),
                              nCy * h[1] + padDist[1, :].sum(),
                              nCz * h[2] + padDist[2, :].sum()])

        maxLevel = int(np.log2(extent/h[0]))+1

        # Number of cells at the small octree level
        # equal in 3D
        nCx, nCy, nCz = 2**(maxLevel), 2**(maxLevel), 2**(maxLevel)

        # nCy = 2**(int(np.log2(extent/h[1]))+1)
        # nCz = 2**(int(np.log2(extent/h[2]))+1)

        # Define the mesh and origin
        mesh = Mesh.TreeMesh([np.ones(nCx)*h[0],
                              np.ones(nCx)*h[1],
                              np.ones(nCx)*h[2]])

        # Shift mesh if global mesh is used
        center = np.r_[midX, midY, midZ]
        if meshGlobal is not None:

            tree = cKDTree(meshGlobal.gridCC)
            _, ind = tree.query(center, k=1)
            center = meshGlobal.gridCC[ind, :]

        # Set origin
        if verticalAlignment == 'center':
            mesh.x0 = np.r_[center[0] - (nCx-1)*h[0]/2., center[1] - (nCy-1)*h[1]/2., center[2] - (nCz-1)*h[2]/2.]
        elif verticalAlignment == 'top':
            mesh.x0 = np.r_[center[0] - (nCx-1)*h[0]/2., center[1] - (nCy-1)*h[1]/2., center[2] - (nCz-1)*h[2]]
        else:
            assert NotImplementedError("verticalAlignment must be 'center' | 'top'")

    return mesh
Beispiel #25
0
def set_mesh_1d(hz):
    return Mesh.TensorMesh([hz], x0=[0])
def run(N=100, plotIt=True):

    np.random.seed(1)

    std_noise = 1e-2

    mesh = Mesh.TensorMesh([N])

    m0 = np.ones(mesh.nC) * 1e-4
    mref = np.zeros(mesh.nC)

    nk = 20
    jk = np.linspace(1., 60., nk)
    p = -0.25
    q = 0.25

    def g(k):
        return (np.exp(p * jk[k] * mesh.vectorCCx) *
                np.cos(np.pi * q * jk[k] * mesh.vectorCCx))

    G = np.empty((nk, mesh.nC))

    for i in range(nk):
        G[i, :] = g(i)

    mtrue = np.zeros(mesh.nC)
    mtrue[mesh.vectorCCx > 0.3] = 1.
    mtrue[mesh.vectorCCx > 0.45] = -0.5
    mtrue[mesh.vectorCCx > 0.6] = 0

    prob = Problem.LinearProblem(mesh, G=G)
    survey = Survey.LinearSurvey()
    survey.pair(prob)
    survey.dobs = prob.fields(mtrue) + std_noise * np.random.randn(nk)

    wd = np.ones(nk) * std_noise

    # Distance weighting
    wr = np.sum(prob.getJ(m0)**2., axis=0)**0.5
    wr = wr / np.max(wr)

    dmis = DataMisfit.l2_DataMisfit(survey)
    dmis.W = 1. / wd

    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)

    # Creat reduced identity map
    idenMap = Maps.IdentityMap(nP=mesh.nC)

    reg = Regularization.Sparse(mesh, mapping=idenMap)
    reg.mref = mref
    reg.cell_weights = wr
    reg.eps_p, reg.eps_q = 1e-1, 1e-1
    reg.norms = np.c_[0., 0., 2., 2.]
    reg.mref = np.zeros(mesh.nC)

    opt = Optimization.ProjectedGNCG(maxIter=100,
                                     lower=-2.,
                                     upper=2.,
                                     maxIterLS=20,
                                     maxIterCG=10,
                                     tolCG=1e-3)
    invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
    update_Jacobi = Directives.UpdatePreconditioner()

    # Set the IRLS directive, penalize the lowest 25 percentile of model values
    # Start with an l2-l2, then switch to lp-norms

    IRLS = Directives.Update_IRLS(maxIRLSiter=20,
                                  minGNiter=1,
                                  f_min_change=1e-4)
    saveDict = Directives.SaveOutputEveryIteration(save_txt=False)
    inv = Inversion.BaseInversion(
        invProb, directiveList=[IRLS, betaest, update_Jacobi, saveDict])

    # Run inversion
    mrec = inv.run(m0)

    print("Final misfit:" + str(invProb.dmisfit(mrec)))

    if plotIt:
        fig, axes = plt.subplots(2, 2, figsize=(12 * 1.2, 8 * 1.2))
        for i in range(prob.G.shape[0]):
            axes[0, 0].plot(prob.G[i, :])
        axes[0, 0].set_title('Columns of matrix G')

        axes[0, 1].plot(mesh.vectorCCx, mtrue, 'b-')
        axes[0, 1].plot(mesh.vectorCCx, invProb.l2model, 'r-')
        # axes[0, 1].legend(('True Model', 'Recovered Model'))
        axes[0, 1].set_ylim(-1.0, 1.25)

        axes[0, 1].plot(mesh.vectorCCx, mrec, 'k-', lw=2)
        axes[0, 1].legend(('True Model', 'Smooth l2-l2',
                           'Sparse norms: {0}'.format(*reg.norms)),
                          fontsize=12)

        axes[1, 1].plot(saveDict.phi_d, 'k', lw=2)

        twin = axes[1, 1].twinx()
        twin.plot(saveDict.phi_m, 'k--', lw=2)
        axes[1, 1].plot(np.r_[IRLS.iterStart, IRLS.iterStart],
                        np.r_[0, np.max(saveDict.phi_d)], 'k:')
        axes[1, 1].text(IRLS.iterStart,
                        0.,
                        'IRLS Start',
                        va='bottom',
                        ha='center',
                        rotation='vertical',
                        size=12,
                        bbox={'facecolor': 'white'})

        axes[1, 1].set_ylabel('$\phi_d$', size=16, rotation=0)
        axes[1, 1].set_xlabel('Iterations', size=14)
        axes[1, 0].axis('off')
        twin.set_ylabel('$\phi_m$', size=16, rotation=0)

    return prob, survey, mesh, mrec
Beispiel #27
0
def run(plotIt=True):

    # Create a mesh
    dx = 5.

    hxind = [(dx, 5, -1.3), (dx, 15), (dx, 5, 1.3)]
    hyind = [(dx, 5, -1.3), (dx, 15), (dx, 5, 1.3)]
    hzind = [(dx, 5, -1.3), (dx, 7), (3.5, 1), (2, 5)]

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

    # Get index of the center
    midx = int(mesh.nCx / 2)
    midy = int(mesh.nCy / 2)

    # Lets create a simple Gaussian topo and set the active cells
    [xx, yy] = np.meshgrid(mesh.vectorNx, mesh.vectorNy)
    zz = -np.exp((xx**2 + yy**2) / 75**2) + mesh.vectorNz[-1]

    # We would usually load a topofile
    topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)]

    # Go from topo to actv cells
    actv = Utils.surface2ind_topo(mesh, topo, 'N')
    actv = np.asarray([inds for inds, elem in enumerate(actv, 1) if elem],
                      dtype=int) - 1

    # Create active map to go from reduce space to full
    actvMap = Maps.InjectActiveCells(mesh, actv, -100)
    nC = len(actv)

    # Create and array of observation points
    xr = np.linspace(-30., 30., 20)
    yr = np.linspace(-30., 30., 20)
    X, Y = np.meshgrid(xr, yr)

    # Move the observation points 5m above the topo
    Z = -np.exp((X**2 + Y**2) / 75**2) + mesh.vectorNz[-1] + 0.1

    # Create a MAGsurvey
    rxLoc = np.c_[Utils.mkvc(X.T), Utils.mkvc(Y.T), Utils.mkvc(Z.T)]
    rxLoc = PF.BaseGrav.RxObs(rxLoc)
    srcField = PF.BaseGrav.SrcField([rxLoc])
    survey = PF.BaseGrav.LinearSurvey(srcField)

    # We can now create a susceptibility model and generate data
    # Here a simple block in half-space
    model = np.zeros((mesh.nCx, mesh.nCy, mesh.nCz))
    model[(midx - 5):(midx - 1), (midy - 2):(midy + 2), -10:-6] = 0.75
    model[(midx + 1):(midx + 5), (midy - 2):(midy + 2), -10:-6] = -0.75
    model = Utils.mkvc(model)
    model = model[actv]

    # Create active map to go from reduce set to full
    actvMap = Maps.InjectActiveCells(mesh, actv, -100)

    # Create reduced identity map
    idenMap = Maps.IdentityMap(nP=nC)

    # Create the forward model operator
    prob = PF.Gravity.GravityIntegral(mesh, rhoMap=idenMap, actInd=actv)

    # Pair the survey and problem
    survey.pair(prob)

    # Compute linear forward operator and compute some data
    d = prob.fields(model)

    # Add noise and uncertainties
    # We add some random Gaussian noise (1nT)
    data = d + np.random.randn(len(d)) * 1e-3
    wd = np.ones(len(data)) * 1e-3  # Assign flat uncertainties

    survey.dobs = data
    survey.std = wd
    survey.mtrue = model

    # Create sensitivity weights from our linear forward operator
    rxLoc = survey.srcField.rxList[0].locs
    wr = np.sum(prob.G**2., axis=0)**0.5
    wr = (wr / np.max(wr))

    # Create a regularization
    reg = Regularization.Sparse(mesh, indActive=actv, mapping=idenMap)
    reg.cell_weights = wr
    reg.norms = np.c_[1, 0, 0, 0]

    # Data misfit function
    dmis = DataMisfit.l2_DataMisfit(survey)
    dmis.W = Utils.sdiag(1 / wd)

    # Add directives to the inversion
    opt = Optimization.ProjectedGNCG(maxIter=100,
                                     lower=-1.,
                                     upper=1.,
                                     maxIterLS=20,
                                     maxIterCG=10,
                                     tolCG=1e-3)
    invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
    betaest = Directives.BetaEstimate_ByEig()

    # Here is where the norms are applied
    # Use pick a treshold parameter empirically based on the distribution of
    # model parameters
    IRLS = Directives.Update_IRLS(
        f_min_change=1e-4,
        maxIRLSiter=30,
        coolEpsFact=1.5,
        beta_tol=1e-1,
    )
    saveDict = Directives.SaveOutputEveryIteration(save_txt=False)
    update_Jacobi = Directives.UpdatePreconditioner()
    inv = Inversion.BaseInversion(
        invProb, directiveList=[IRLS, betaest, update_Jacobi, saveDict])

    # Run the inversion
    m0 = np.ones(nC) * 1e-4  # Starting model
    mrec = inv.run(m0)

    if plotIt:
        # Here is the recovered susceptibility model
        ypanel = midx
        zpanel = -7
        m_l2 = actvMap * invProb.l2model
        m_l2[m_l2 == -100] = np.nan

        m_lp = actvMap * mrec
        m_lp[m_lp == -100] = np.nan

        m_true = actvMap * model
        m_true[m_true == -100] = np.nan

        vmin, vmax = mrec.min(), mrec.max()

        # Plot the data
        PF.Gravity.plot_obs_2D(rxLoc, d=data)

        plt.figure()

        # Plot L2 model
        ax = plt.subplot(321)
        mesh.plotSlice(m_l2,
                       ax=ax,
                       normal='Z',
                       ind=zpanel,
                       grid=True,
                       clim=(vmin, vmax))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]),
                 color='w')
        plt.title('Plan l2-model.')
        plt.gca().set_aspect('equal')
        plt.ylabel('y')
        ax.xaxis.set_visible(False)
        plt.gca().set_aspect('equal', adjustable='box')

        # Vertica section
        ax = plt.subplot(322)
        mesh.plotSlice(m_l2,
                       ax=ax,
                       normal='Y',
                       ind=midx,
                       grid=True,
                       clim=(vmin, vmax))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]),
                 color='w')
        plt.title('E-W l2-model.')
        plt.gca().set_aspect('equal')
        ax.xaxis.set_visible(False)
        plt.ylabel('z')
        plt.gca().set_aspect('equal', adjustable='box')

        # Plot Lp model
        ax = plt.subplot(323)
        mesh.plotSlice(m_lp,
                       ax=ax,
                       normal='Z',
                       ind=zpanel,
                       grid=True,
                       clim=(vmin, vmax))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]),
                 color='w')
        plt.title('Plan lp-model.')
        plt.gca().set_aspect('equal')
        ax.xaxis.set_visible(False)
        plt.ylabel('y')
        plt.gca().set_aspect('equal', adjustable='box')

        # Vertical section
        ax = plt.subplot(324)
        mesh.plotSlice(m_lp,
                       ax=ax,
                       normal='Y',
                       ind=midx,
                       grid=True,
                       clim=(vmin, vmax))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]),
                 color='w')
        plt.title('E-W lp-model.')
        plt.gca().set_aspect('equal')
        ax.xaxis.set_visible(False)
        plt.ylabel('z')
        plt.gca().set_aspect('equal', adjustable='box')

        # Plot True model
        ax = plt.subplot(325)
        mesh.plotSlice(m_true,
                       ax=ax,
                       normal='Z',
                       ind=zpanel,
                       grid=True,
                       clim=(vmin, vmax))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]),
                 color='w')
        plt.title('Plan true model.')
        plt.gca().set_aspect('equal')
        plt.xlabel('x')
        plt.ylabel('y')
        plt.gca().set_aspect('equal', adjustable='box')

        # Vertical section
        ax = plt.subplot(326)
        mesh.plotSlice(m_true,
                       ax=ax,
                       normal='Y',
                       ind=midx,
                       grid=True,
                       clim=(vmin, vmax))
        plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]),
                 color='w')
        plt.title('E-W true model.')
        plt.gca().set_aspect('equal')
        plt.xlabel('x')
        plt.ylabel('z')
        plt.gca().set_aspect('equal', adjustable='box')

        # Plot convergence curves
        fig, axs = plt.figure(), plt.subplot()
        axs.plot(saveDict.phi_d, 'k', lw=2)
        axs.plot(np.r_[IRLS.iterStart, IRLS.iterStart],
                 np.r_[0, np.max(saveDict.phi_d)], 'k:')

        twin = axs.twinx()
        twin.plot(saveDict.phi_m, 'k--', lw=2)
        axs.text(IRLS.iterStart,
                 np.max(saveDict.phi_d) / 2.,
                 'IRLS Steps',
                 va='bottom',
                 ha='center',
                 rotation='vertical',
                 size=12,
                 bbox={'facecolor': 'white'})

        axs.set_ylabel('$\phi_d$', size=16, rotation=0)
        axs.set_xlabel('Iterations', size=14)
        twin.set_ylabel('$\phi_m$', size=16, rotation=0)
Beispiel #28
0
from matplotlib.path import Path
import matplotlib.patches as patches

from SimPEG import Mesh, Maps, SolverLU, Utils
from SimPEG.Utils import ExtractCoreMesh
from SimPEG.EM.Static import DC

from ..base import widgetify

# Mesh, mapping can be globals global
npad = 15
growrate = 2.0
cs = 0.5
hx = [(cs, npad, -growrate), (cs, 200), (cs, npad, growrate)]
hy = [(cs, npad, -growrate), (cs, 100)]
mesh = Mesh.TensorMesh([hx, hy], "CN")
expmap = Maps.ExpMap(mesh)
mapping = expmap
dx = 5
xr = np.arange(-40, 41, dx)
dxr = np.diff(xr)
xmin = -40.0
xmax = 40.0
ymin = -40.0
ymax = 8.0
xylim = np.c_[[xmin, ymin], [xmax, ymax]]
indCC, meshcore = ExtractCoreMesh(xylim, mesh)
indx = ((mesh.gridFx[:, 0] >= xmin)
        & (mesh.gridFx[:, 0] <= xmax)
        & (mesh.gridFx[:, 1] >= ymin)
        & (mesh.gridFx[:, 1] <= ymax))
Beispiel #29
0
 def get_mesh(self):
     mesh = Mesh.TensorMesh([np.ones(20)])
     mesh.setCellGradBC('dirichlet')
     return mesh
Beispiel #30
0
 def setUp(self):
     hx = np.random.rand(10.)
     hy = np.random.rand(10.)
     hz = np.random.rand(10.)
     self.mesh = Mesh.TensorMesh([hx, hy, hz])