Example #1
0
    def solve(self):
        # Tikhonov Inversion
        ####################

        # Initial model values
        m0 = np.median(self.ln_sigback) * np.ones(self.mapping.nP)

        # Misfit functional
        dmis = DataMisfit.l2_DataMisfit(self.survey.simpeg_survey)
        # Regularization functional
        regT = Regularization.Simple(self.mesh, indActive=self.actind)

        # Personal preference for this solver with a Jacobi preconditioner
        opt = Optimization.ProjectedGNCG(maxIter=20, lower=-10, upper=10,
                                         maxIterLS=20, maxIterCG=30, tolCG=1e-4)

        # Optimization class keeps value of 'xc'. Seems to be solution for the model parameters
        opt.remember('xc')
        invProb = InvProblem.BaseInvProblem(dmis, regT, opt)

        # Options for the inversion algorithm in particular selection of Beta weight for regularization.

        # How to choose initial estimate for beta
        beta = Directives.BetaEstimate_ByEig(beta0_ratio=1.)
        Target = Directives.TargetMisfit()
        # Beta changing algorithm.
        betaSched = Directives.BetaSchedule(coolingFactor=5., coolingRate=2)
        # Change model weights, seems sensitivity of conductivity ?? Not sure.
        updateSensW = Directives.UpdateSensitivityWeights(threshold=1e-3)
        # Use Jacobi preconditioner ( the only available).
        update_Jacobi = Directives.UpdatePreconditioner()

        inv = Inversion.BaseInversion(invProb, directiveList=[beta, Target,
                                                              betaSched, updateSensW,
                                                              update_Jacobi])

        self.minv = inv.run(m0)
Example #2
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')
Example #3
0
    def run_inversion_cg(
        self,
        maxIter=60,
        m0=0.0,
        mref=0.0,
        percentage=5,
        floor=0.1,
        chifact=1,
        beta0_ratio=1.0,
        coolingFactor=1,
        coolingRate=1,
        alpha_s=1.0,
        alpha_x=1.0,
        use_target=False,
    ):
        survey, prob = self.get_problem_survey()
        survey.eps = percentage
        survey.std = floor
        survey.dobs = self.data.copy()
        self.uncertainty = percentage * abs(survey.dobs) * 0.01 + floor

        m0 = np.ones(self.M) * m0
        mref = np.ones(self.M) * mref
        reg = Regularization.Tikhonov(
            self.mesh, alpha_s=alpha_s, alpha_x=alpha_x, mref=mref
        )
        dmis = DataMisfit.l2_DataMisfit(survey)
        dmis.W = 1.0 / self.uncertainty

        opt = Optimization.InexactGaussNewton(maxIter=maxIter, maxIterCG=20)
        opt.remember("xc")
        opt.tolG = 1e-10
        opt.eps = 1e-10
        invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
        save = Directives.SaveOutputEveryIteration()
        beta_schedule = Directives.BetaSchedule(
            coolingFactor=coolingFactor, coolingRate=coolingRate
        )
        target = Directives.TargetMisfit(chifact=chifact)

        if use_target:
            directives = [
                Directives.BetaEstimate_ByEig(beta0_ratio=beta0_ratio),
                beta_schedule,
                target,
                save,
            ]
        else:
            directives = [
                Directives.BetaEstimate_ByEig(beta0_ratio=beta0_ratio),
                beta_schedule,
                save,
            ]
        inv = Inversion.BaseInversion(invProb, directiveList=directives)
        mopt = inv.run(m0)
        model = opt.recall("xc")
        model.append(mopt)
        pred = []
        for m in model:
            pred.append(survey.dpred(m))
        return model, pred, save
Example #4
0
regT = Regularization.Simple(mesh,
                             indActive=actind,
                             alpha_s=1e-6,
                             alpha_x=1.,
                             alpha_y=1.,
                             alpha_z=1.)

# Optimization Scheme
opt = Optimization.InexactGaussNewton(maxIter=10)

# Form the problem
opt.remember('xc')
invProb = InvProblem.BaseInvProblem(dmis, regT, opt)

# Directives for Inversions
beta = Directives.BetaEstimate_ByEig(beta0_ratio=1e+1)
Target = Directives.TargetMisfit()
betaSched = Directives.BetaSchedule(coolingFactor=5., coolingRate=2)

inv = Inversion.BaseInversion(invProb, directiveList=[beta, Target, betaSched])
# Run Inversion
minv = inv.run(m0)

# Final Plot
############

fig, ax = plt.subplots(2, 2, figsize=(12, 6))
ax = Utils.mkvc(ax)

cyl0v = getCylinderPoints(x0, z0, r0)
cyl1v = getCylinderPoints(x1, z1, r1)
Example #5
0
reg.mref = np.zeros(nC)

# Specify how the optimization will proceed, set susceptibility bounds to inf
opt = Optimization.ProjectedGNCG(maxIter=25, lower=-np.inf,
                                 upper=np.inf, maxIterLS=20,
                                 maxIterCG=20, tolCG=1e-3)

# Define misfit function (obs-calc)
dmis = DataMisfit.l2_DataMisfit(survey)
dmis.W = 1./survey.std

# Create the default L2 inverse problem from the above objects
invProb = InvProblem.BaseInvProblem(dmis, reg, opt)

# Specify how the initial beta is found
betaest = Directives.BetaEstimate_ByEig()

# Beta schedule for inversion
betaSchedule = Directives.BetaSchedule(coolingFactor=2., coolingRate=1)

# Target misfit to stop the inversion,
# try to fit as much as possible of the signal, we don't want to lose anything
targetMisfit = Directives.TargetMisfit(chifact=0.1)

# Put all the parts together
inv = Inversion.BaseInversion(invProb,
                              directiveList=[betaest, betaSchedule, targetMisfit])

# Run the equivalent source inversion
mstart = np.zeros(nC)
mrec = inv.run(mstart)
Example #6
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')

    layerz = -100.

    active = mesh.vectorCCz < 0.
    layer = (mesh.vectorCCz < 0.) & (mesh.vectorCCz >= layerz)
    actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
    mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap
    sig_half = 2e-2
    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])

    if plotIt:
        fig, ax = plt.subplots(1, 1, figsize=(3, 6))
        plt.semilogx(sigma[active], mesh.vectorCCz[active])
        ax.set_ylim(-500, 0)
        ax.set_xlim(1e-3, 1e-1)
        ax.set_xlabel('Conductivity (S/m)', fontsize=14)
        ax.set_ylabel('Depth (m)', fontsize=14)
        ax.grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5)

    rxOffset = 10.
    bzi = EM.FDEM.Rx.Point_b(np.array([[rxOffset, 0., 1e-3]]),
                             orientation='z',
                             component='imag')

    freqs = np.logspace(1, 3, 10)
    srcLoc = np.array([0., 0., 10.])

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

    survey = EM.FDEM.Survey(srcList)
    prb = EM.FDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=Solver)
    prb.pair(survey)

    std = 0.05
    survey.makeSyntheticData(mtrue, std)

    survey.std = std
    survey.eps = np.linalg.norm(survey.dtrue) * 1e-5

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

    dmisfit = DataMisfit.l2_DataMisfit(survey)
    regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
    reg = Regularization.Tikhonov(regMesh)
    opt = Optimization.InexactGaussNewton(maxIter=6)
    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)
    reg.alpha_s = 1e-3
    reg.alpha_x = 1.
    prb.counter = opt.counter = Utils.Counter()
    opt.LSshorten = 0.5
    opt.remember('xc')

    mopt = inv.run(m0)

    if plotIt:
        fig, ax = plt.subplots(1, 1, figsize=(3, 6))
        plt.semilogx(sigma[active], mesh.vectorCCz[active])
        plt.semilogx(np.exp(mopt), mesh.vectorCCz[active])
        ax.set_ylim(-500, 0)
        ax.set_xlim(1e-3, 1e-1)
        ax.set_xlabel('Conductivity (S/m)', fontsize=14)
        ax.set_ylabel('Depth (m)', fontsize=14)
        ax.grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5)
        plt.legend(['$\sigma_{true}$', '$\sigma_{pred}$'], loc='best')
Example #7
0
    def setUp(self):
        np.random.seed(0)
        H0 = (50000., 90., 0.)

        # The magnetization is set along a different
        # direction (induced + remanence)
        M = np.array([45., 90.])

        # Create grid of points for topography
        # Lets create a simple Gaussian topo
        # and set the active cells
        [xx, yy] = np.meshgrid(
            np.linspace(-200, 200, 50),
            np.linspace(-200, 200, 50)
        )
        b = 100
        A = 50
        zz = A*np.exp(-0.5*((xx/b)**2. + (yy/b)**2.))

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

        # Create and array of observation points
        xr = np.linspace(-100., 100., 20)
        yr = np.linspace(-100., 100., 20)
        X, Y = np.meshgrid(xr, yr)
        Z = A*np.exp(-0.5*((X/b)**2. + (Y/b)**2.)) + 5

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

        # Create a mesh
        h = [5, 5, 5]
        padDist = np.ones((3, 2)) * 100
        nCpad = [2, 4, 2]

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

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

        nCx = int(limx[0]-limx[1]) / h[0]
        nCy = int(limy[0]-limy[1]) / h[1]
        nCz = int(limz[0]-limz[1]+int(np.min(np.r_[nCx, nCy])/3)) / h[2]
        # 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
        nCx, nCy, nCz = 2**(maxLevel), 2**(maxLevel), 2**(maxLevel)

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

        # Set origin
        mesh.x0 = np.r_[
            -nCx*h[0]/2.+midX,
            -nCy*h[1]/2.+midY,
            -nCz*h[2]/2.+midZ
        ]

        # Refine the mesh around topography
        # Get extent of points
        F = NearestNDInterpolator(topo[:, :2], topo[:, 2])
        zOffset = 0
        # Cycle through the first 3 octree levels
        for ii in range(3):

            dx = mesh.hx.min()*2**ii

            nCx = int((limx[0]-limx[1]) / dx)
            nCy = int((limy[0]-limy[1]) / dx)

            # Create a grid at the octree level in xy
            CCx, CCy = np.meshgrid(
                np.linspace(limx[1], limx[0], nCx),
                np.linspace(limy[1], limy[0], nCy)
            )

            z = F(mkvc(CCx), mkvc(CCy))

            # level means number of layers in current OcTree level
            for level in range(int(nCpad[ii])):

                mesh.insert_cells(
                    np.c_[
                        mkvc(CCx),
                        mkvc(CCy),
                        z-zOffset
                    ], np.ones_like(z)*maxLevel-ii,
                    finalize=False
                )

                zOffset += dx

        mesh.finalize()
        self.mesh = mesh
        # Define an active cells from topo
        actv = Utils.surface2ind_topo(mesh, topo)
        nC = int(actv.sum())

        model = np.zeros((mesh.nC, 3))

        # Convert the inclination declination to vector in Cartesian
        M_xyz = Utils.matutils.dip_azimuth2cartesian(M[0], M[1])

        # Get the indicies of the magnetized block
        ind = Utils.ModelBuilder.getIndicesBlock(
            np.r_[-20, -20, -10], np.r_[20, 20, 25],
            mesh.gridCC,
        )[0]

        # Assign magnetization values
        model[ind, :] = np.kron(
            np.ones((ind.shape[0], 1)), M_xyz*0.05
        )

        # Remove air cells
        self.model = model[actv, :]

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

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

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

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

        # Compute some data and add some random noise
        data = prob.fields(Utils.mkvc(self.model))
        std = 5  # nT
        data += np.random.randn(len(data))*std
        wd = np.ones(len(data))*std

        # Assigne data and uncertainties to the survey
        survey.dobs = data
        survey.std = wd

        # Create an projection matrix for plotting later
        actvPlot = Maps.InjectActiveCells(mesh, actv, np.nan)

        # Create sensitivity weights from our linear forward operator
        rxLoc = survey.srcField.rxList[0].locs

        # This Mapping connects the regularizations for the three-component
        # vector model
        wires = Maps.Wires(('p', nC), ('s', nC), ('t', nC))

        # Create sensitivity weights from our linear forward operator
        # so that all cells get equal chance to contribute to the solution
        wr = np.sum(prob.G**2., axis=0)**0.5
        wr = (wr/np.max(wr))

        # Create three regularization for the different components
        # of magnetization
        reg_p = Regularization.Sparse(mesh, indActive=actv, mapping=wires.p)
        reg_p.mref = np.zeros(3*nC)
        reg_p.cell_weights = (wires.p * wr)

        reg_s = Regularization.Sparse(mesh, indActive=actv, mapping=wires.s)
        reg_s.mref = np.zeros(3*nC)
        reg_s.cell_weights = (wires.s * wr)

        reg_t = Regularization.Sparse(mesh, indActive=actv, mapping=wires.t)
        reg_t.mref = np.zeros(3*nC)
        reg_t.cell_weights = (wires.t * wr)

        reg = reg_p + reg_s + reg_t
        reg.mref = np.zeros(3*nC)

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

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

        invProb = InvProblem.BaseInvProblem(dmis, reg, opt)

        # A list of directive to control the inverson
        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-3, maxIRLSiter=0, beta_tol=5e-1
        )

        # Pre-conditioner
        update_Jacobi = Directives.UpdatePreconditioner()

        inv = Inversion.BaseInversion(invProb,
                                      directiveList=[IRLS, update_Jacobi, betaest])

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

        self.mstart = Utils.matutils.cartesian2spherical(mrec_MVIC.reshape((nC, 3), order='F'))
        beta = invProb.beta
        dmis.prob.coordinate_system = 'spherical'
        dmis.prob.model = self.mstart

        # Create a block diagonal regularization
        wires = Maps.Wires(('amp', nC), ('theta', nC), ('phi', nC))

        # Create a Combo Regularization
        # Regularize the amplitude of the vectors
        reg_a = Regularization.Sparse(mesh, indActive=actv,
                                      mapping=wires.amp)
        reg_a.norms = np.c_[0., 0., 0., 0.]  # Sparse on the model and its gradients
        reg_a.mref = np.zeros(3*nC)

        # Regularize the vertical angle of the vectors
        reg_t = Regularization.Sparse(mesh, indActive=actv,
                                      mapping=wires.theta)
        reg_t.alpha_s = 0.  # No reference angle
        reg_t.space = 'spherical'
        reg_t.norms = np.c_[2., 0., 0., 0.]  # Only norm on gradients used

        # Regularize the horizontal angle of the vectors
        reg_p = Regularization.Sparse(mesh, indActive=actv,
                                      mapping=wires.phi)
        reg_p.alpha_s = 0.  # No reference angle
        reg_p.space = 'spherical'
        reg_p.norms = np.c_[2., 0., 0., 0.]  # Only norm on gradients used

        reg = reg_a + reg_t + reg_p
        reg.mref = np.zeros(3*nC)

        Lbound = np.kron(np.asarray([0, -np.inf, -np.inf]), np.ones(nC))
        Ubound = np.kron(np.asarray([10, np.inf, np.inf]), np.ones(nC))

        # Add directives to the inversion
        opt = Optimization.ProjectedGNCG(maxIter=20,
                                         lower=Lbound,
                                         upper=Ubound,
                                         maxIterLS=20,
                                         maxIterCG=30,
                                         tolCG=1e-3,
                                         stepOffBoundsFact=1e-3,
                                         )
        opt.approxHinv = None

        invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=beta*10.)

        # Here is where the norms are applied
        IRLS = Directives.Update_IRLS(f_min_change=1e-4, maxIRLSiter=20,
                                      minGNiter=1, beta_tol=0.5,
                                      coolingRate=1, coolEps_q=True,
                                      betaSearch=False)

        # Special directive specific to the mag amplitude problem. The sensitivity
        # weights are update between each iteration.
        ProjSpherical = Directives.ProjectSphericalBounds()
        update_SensWeight = Directives.UpdateSensitivityWeights()
        update_Jacobi = Directives.UpdatePreconditioner()

        self.inv = Inversion.BaseInversion(
            invProb,
            directiveList=[
                ProjSpherical, IRLS, update_SensWeight, update_Jacobi
            ]
        )
def run(plotIt=True):

    # 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 array of indices of active cells
    actv = Utils.surface2ind_topo(mesh, topo, 'N')
    actv = np.where(actv)[0]
    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)

    # Create 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
    reg.mref = np.zeros(nC)
    reg.norms = np.c_[0, 0, 0, 0]
    # reg.eps_p, reg.eps_q = 1e-0, 1e-0

    # 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=20,
                                     tolCG=1e-3)
    invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e-1)

    # 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-4, maxIRLSiter=40)
    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 = -5
        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

        # Plot the data
        Utils.PlotUtils.plot2Ddata(rxLoc, 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')

        # 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,
                 0,
                 '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)
Example #9
0
def run(plotIt=True):
    """
        EM: TDEM: 1D: Inversion
        =======================

        Here we will create and run a TDEM 1D inversion.

    """

    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_b(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_b(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}$'])
Example #10
0
def run_inversion(
    m0, survey, actind, mesh,
    std, eps,
    maxIter=15, beta0_ratio=1e0,
    coolingFactor=5, coolingRate=2,
    upper=np.inf, lower=-np.inf,
    use_sensitivity_weight=False,
    alpha_s=1e-4,
    alpha_x=1.,
    alpha_y=1.,
    alpha_z=1.,
):
    """
    Run IP inversion
    """
    dmisfit = DataMisfit.l2_DataMisfit(survey)
    uncert = abs(survey.dobs) * std + eps
    dmisfit.W = 1./uncert
    # Map for a regularization
    regmap = Maps.IdentityMap(nP=int(actind.sum()))
    # Related to inversion
    if use_sensitivity_weight:
        reg = Regularization.Sparse(
            mesh, indActive=actind, mapping=regmap
        )
        reg.alpha_s = alpha_s
        reg.alpha_x = alpha_x
        reg.alpha_y = alpha_y
        reg.alpha_z = alpha_z
    else:
        reg = Regularization.Sparse(
            mesh, indActive=actind, mapping=regmap,
            cell_weights=mesh.vol[actind]
        )
        reg.alpha_s = alpha_s
        reg.alpha_x = alpha_x
        reg.alpha_y = alpha_y
        reg.alpha_z = alpha_z
    opt = Optimization.ProjectedGNCG(maxIter=maxIter, upper=upper, lower=lower)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)
    beta = Directives.BetaSchedule(
        coolingFactor=coolingFactor, coolingRate=coolingRate
    )
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=beta0_ratio)
    target = Directives.TargetMisfit()

    # Need to have basice saving function
    if use_sensitivity_weight:
        updateSensW = Directives.UpdateSensitivityWeights()
        update_Jacobi = Directives.UpdatePreconditioner()
        directiveList = [
            beta, betaest, target, update_Jacobi
        ]
    else:
        directiveList = [
            beta, betaest, target
        ]
    inv = Inversion.BaseInversion(
        invProb, directiveList=directiveList
        )
    opt.LSshorten = 0.5
    opt.remember('xc')

    # Run inversion
    mopt = inv.run(m0)
    return mopt, invProb.dpred
Example #11
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.G**2., axis=0)**0.5
    wr = wr / np.max(wr)

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

    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e-2)

    reg = Regularization.Sparse(mesh)
    reg.mref = mref
    reg.cell_weights = wr

    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.Update_lin_PreCond()

    # Set the IRLS directive, penalize the lowest 25 percentile of model values
    # Start with an l2-l2, then switch to lp-norms
    norms = [0., 0., 2., 2.]
    IRLS = Directives.Update_IRLS(norms=norms,
                                  prctile=25,
                                  maxIRLSiter=15,
                                  minGNiter=3)

    inv = Inversion.BaseInversion(invProb,
                                  directiveList=[IRLS, betaest, update_Jacobi])

    # Run inversion
    mrec = inv.run(m0)

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

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

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

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

    return prob, survey, mesh, mrec
Example #12
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.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=40, 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
def run(plotIt=True, survey_type="dipole-dipole"):
    np.random.seed(1)
    # Initiate I/O class for DC
    IO = DC.IO()
    # Obtain ABMN locations

    xmin, xmax = 0., 200.
    ymin, ymax = 0., 0.
    zmin, zmax = 0, 0
    endl = np.array([[xmin, ymin, zmin], [xmax, ymax, zmax]])
    # Generate DC survey object
    survey = DC.Utils.gen_DCIPsurvey(endl, survey_type=survey_type, dim=2,
                                     a=10, b=10, n=10)
    survey.getABMN_locations()
    survey = IO.from_ambn_locations_to_survey(
        survey.a_locations, survey.b_locations,
        survey.m_locations, survey.n_locations,
        survey_type, data_dc_type='volt'
    )

    # Obtain 2D TensorMesh
    mesh, actind = IO.set_mesh()
    topo, mesh1D = DC.Utils.genTopography(mesh, -10, 0, its=100)
    actind = Utils.surface2ind_topo(mesh, np.c_[mesh1D.vectorCCx, topo])
    survey.drapeTopo(mesh, actind, option="top")

    # Build a conductivity model
    blk_inds_c = Utils.ModelBuilder.getIndicesSphere(
        np.r_[60., -25.], 12.5, mesh.gridCC
    )
    blk_inds_r = Utils.ModelBuilder.getIndicesSphere(
        np.r_[140., -25.], 12.5, mesh.gridCC
    )
    layer_inds = mesh.gridCC[:, 1] > -5.
    sigma = np.ones(mesh.nC)*1./100.
    sigma[blk_inds_c] = 1./10.
    sigma[blk_inds_r] = 1./1000.
    sigma[~actind] = 1./1e8
    rho = 1./sigma

    # Show the true conductivity model
    if plotIt:
        fig = plt.figure(figsize=(12, 3))
        ax = plt.subplot(111)
        temp = rho.copy()
        temp[~actind] = np.nan
        out = mesh.plotImage(
            temp, grid=True, ax=ax, gridOpts={'alpha': 0.2},
            clim=(10, 1000),
            pcolorOpts={"cmap": "viridis", "norm": colors.LogNorm()}
        )
        ax.plot(
            survey.electrode_locations[:, 0],
            survey.electrode_locations[:, 1], 'k.'
        )
        ax.set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
        ax.set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
        cb = plt.colorbar(out[0])
        cb.set_label("Resistivity (ohm-m)")
        ax.set_aspect('equal')
        plt.show()

    # Use Exponential Map: m = log(rho)
    actmap = Maps.InjectActiveCells(
        mesh, indActive=actind, valInactive=np.log(1e8)
    )
    mapping = Maps.ExpMap(mesh) * actmap

    # Generate mtrue
    mtrue = np.log(rho[actind])

    # Generate 2.5D DC problem
    # "N" means potential is defined at nodes
    prb = DC.Problem2D_N(
        mesh, rhoMap=mapping, storeJ=True,
        Solver=Solver
    )
    # Pair problem with survey
    try:
        prb.pair(survey)
    except:
        survey.unpair()
        prb.pair(survey)

    geometric_factor = survey.set_geometric_factor(
        data_type="apparent_resistivity",
        survey_type='dipole-dipole',
        space_type='half-space'
    )

    # Make synthetic DC data with 5% Gaussian noise
    dtrue = survey.makeSyntheticData(mtrue, std=0.05, force=True)

    IO.data_dc = dtrue
    # Show apparent resisitivty pseudo-section
    if plotIt:
        IO.plotPseudoSection(
            data=survey.dobs, data_type='apparent_resistivity'
        )

    # Show apparent resisitivty histogram
    if plotIt:
        fig = plt.figure()
        out = hist(survey.dobs, bins=20)
        plt.xlabel("Apparent Resisitivty ($\Omega$m)")
        plt.show()

    # Set initial model based upon histogram
    m0 = np.ones(actmap.nP)*np.log(100.)

    # Set uncertainty
    # floor (10 ohm-m)
    eps = 1.
    # percentage
    std = 0.05
    dmisfit = DataMisfit.l2_DataMisfit(survey)
    uncert = abs(survey.dobs) * std + eps
    dmisfit.W = 1./uncert

    # Map for a regularization
    regmap = Maps.IdentityMap(nP=int(actind.sum()))

    # Related to inversion
    reg = Regularization.Sparse(mesh, indActive=actind, mapping=regmap)
    opt = Optimization.InexactGaussNewton(maxIter=15)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)
    beta = Directives.BetaSchedule(coolingFactor=5, coolingRate=2)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
    target = Directives.TargetMisfit()
    updateSensW = Directives.UpdateSensitivityWeights()
    update_Jacobi = Directives.UpdatePreconditioner()
    inv = Inversion.BaseInversion(
        invProb, directiveList=[
            beta, betaest, target, updateSensW, update_Jacobi
        ]
        )
    prb.counter = opt.counter = Utils.Counter()
    opt.LSshorten = 0.5
    opt.remember('xc')

    # Run inversion
    mopt = inv.run(m0)

    # Get diag(JtJ)
    mask_inds = np.ones(mesh.nC, dtype=bool)
    jtj = np.sqrt(updateSensW.JtJdiag[0])
    jtj /= jtj.max()
    temp = np.ones_like(jtj, dtype=bool)
    temp[jtj > 0.005] = False
    mask_inds[actind] = temp
    actind_final = np.logical_and(actind, ~mask_inds)
    jtj_cc = np.ones(mesh.nC)*np.nan
    jtj_cc[actind] = jtj

    # Show the sensitivity
    if plotIt:
        fig = plt.figure(figsize=(12, 3))
        ax = plt.subplot(111)
        temp = rho.copy()
        temp[~actind] = np.nan
        out = mesh.plotImage(
            jtj_cc, grid=True, ax=ax,
            gridOpts={'alpha': 0.2}, clim=(0.005, 0.5),
            pcolorOpts={"cmap": "viridis", "norm": colors.LogNorm()}
        )
        ax.plot(
            survey.electrode_locations[:, 0],
            survey.electrode_locations[:, 1], 'k.'
        )
        ax.set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
        ax.set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
        cb = plt.colorbar(out[0])
        cb.set_label("Sensitivity")
        ax.set_aspect('equal')
        plt.show()

    # Convert obtained inversion model to resistivity
    # rho = M(m), where M(.) is a mapping

    rho_est = mapping*mopt
    rho_est[~actind_final] = np.nan
    rho_true = rho.copy()
    rho_true[~actind_final] = np.nan

    # show recovered conductivity
    if plotIt:
        vmin, vmax = rho.min(), rho.max()
        fig, ax = plt.subplots(2, 1, figsize=(20, 6))
        out1 = mesh.plotImage(
                rho_true, clim=(10, 1000),
                pcolorOpts={"cmap": "viridis", "norm": colors.LogNorm()},
                ax=ax[0]
        )
        out2 = mesh.plotImage(
            rho_est, clim=(10, 1000),
            pcolorOpts={"cmap": "viridis", "norm": colors.LogNorm()},
            ax=ax[1]
        )
        out = [out1, out2]
        for i in range(2):
            ax[i].plot(
                survey.electrode_locations[:, 0],
                survey.electrode_locations[:, 1], 'kv'
            )
            ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
            ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
            cb = plt.colorbar(out[i][0], ax=ax[i])
            cb.set_label("Resistivity ($\Omega$m)")
            ax[i].set_xlabel("Northing (m)")
            ax[i].set_ylabel("Elevation (m)")
            ax[i].set_aspect('equal')
        plt.tight_layout()
        plt.show()
Example #14
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 run(plotIt=True):

    init_t = time()
    np.random.seed(0)

    input_file = sys.argv[1]

    # read json file
    with open(input_file, "r") as json_file:
        input_dict = json.load(json_file)

    work_dir = os.path.abspath(os.path.dirname(input_file))
    path_sep = os.path.sep

    if "example" in list(input_dict.keys()):
        if input_dict["example"] == "horse":
            work_dir = os.path.sep.join([work_dir, "Example2_horseShoe"])
            work_dir += path_sep

        elif input_dict["example"] == "spheric":
            work_dir = os.path.sep.join([work_dir, "Example1_spheric"])
            work_dir += path_sep
    else:
        raise Exception("Missing the selection of examples")

    # read mesh file
    if "mesh_file" in list(input_dict.keys()):
        mesh = Mesh.TensorMesh._readUBC_3DMesh(work_dir +
                                               input_dict["mesh_file"])
    else:
        raise Exception("Missing mesh file")

    # read data file
    if "data_file" in list(input_dict.keys()):
        # Create a MAGsurvey
        survey = Utils.io_utils.readUBCgravityObservations(
            work_dir + input_dict["data_file"])
        xyzLoc = survey.rxLoc
        dobs = survey.dobs
        print("Number of data points: ", dobs.size)
        std = survey.std
    else:
        raise Exception("Missing observed data file")

    # load the topo
    if "topography" in list(input_dict.keys()):
        # Load topo
        topo = np.genfromtxt(work_dir + input_dict["topography"],
                             skip_header=1)
        F = NearestNDInterpolator(topo[:, :2], topo[:, 2])
        newTopo = np.c_[xyzLoc[:, :2], F(xyzLoc[:, :2])]
    # without topo
    else:
        newTopo = np.c_[xyzLoc[:, :2], np.zeros(xyzLoc.shape[0])]

    actv = Utils.surface2ind_topo(mesh, newTopo, gridLoc='CC')
    actv = np.where(actv)[0]
    nC = len(actv)
    print("Number of active cells: ", nC)

    # 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=nC)

    # Create the forward model operator
    prob = PF.Gravity.GravityGradient(mesh,
                                      components=['gzz'],
                                      rhoMap=idenMap,
                                      actInd=actv)

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

    # Create depth weighting
    z0 = 0
    v = 3  # exponent parameter
    temp1 = np.abs(np.max(topo[:, 2]) - mesh.vectorNz)
    index = temp1.argmin()
    sum_factor = mesh.vectorNz[index]
    wz = np.power(-mesh.vectorCCz + sum_factor + z0, -v)
    wz = wz / np.nanmax(wz)
    wz = wz**0.5

    # allocate depth decay to all the cells
    tmp1 = (np.outer(np.ones(mesh.nCx), np.ones(mesh.nCy))).flatten('F')
    wz_depth = (np.outer(tmp1, wz)).flatten('F')
    wz_depth = actvMap.P.T * wz_depth

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

    if "norm_p" and "norm_q" in list(input_dict.keys()):
        p, q = input_dict["norm_p"], input_dict["norm_q"]
    else:
        raise Exception("Missing norm values")

    norms = [p, q, q, q]
    reg.norms = [norms]

    if "alpha_s" in list(input_dict.keys()):
        alpha_s = input_dict["alpha_s"]
    else:
        raise Exception("Missing alpha_s")

    if "alpha_x" in list(input_dict.keys()):
        alpha_x = input_dict["alpha_x"]
    else:
        raise Exception("Missing alpha_x")

    if "alpha_y" in list(input_dict.keys()):
        alpha_y = input_dict["alpha_y"]
    else:
        raise Exception("Missing alpha_y")

    if "alpha_z" in list(input_dict.keys()):
        alpha_z = input_dict["alpha_z"]
    else:
        raise Exception("Missing alpha_z")

    reg.alpha_s = alpha_s
    reg.alpha_x = alpha_x
    reg.alpha_y = alpha_y
    reg.alpha_z = alpha_z

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

    printers = [
        IterationPrinters.iteration, IterationPrinters.beta,
        IterationPrinters.phi_d, IterationPrinters.phi_m, IterationPrinters.f,
        IterationPrinters.iterationCG, IterationPrinters.totalLS
    ]

    stoppers = [StoppingCriteria.iteration]

    if "lower_bound" and "upper_bound" in list(input_dict.keys()):
        lb = input_dict["lower_bound"]
        ub = input_dict["upper_bound"]
    else:
        raise Exception("Missing lower, upper bounds")

    # Add directives to the inversion
    opt = Optimization.ProjectedGNCG(maxIter=1000,
                                     lower=lb,
                                     upper=ub,
                                     maxIterLS=100,
                                     maxIterCG=2000,
                                     tolCG=1e-3,
                                     printers=printers,
                                     stoppers=stoppers)

    invProb = InvProblem.BaseInvProblem(dmis, reg, opt)

    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e-1)

    IRLS = Directives.Update_IRLS(f_min_change=1e-3, maxIRLSiter=100)

    update_Jacobi = Directives.UpdatePreconditioner()

    save_output = Directives.SaveOutputEveryIteration_Single()

    inv = Inversion.BaseInversion(
        invProb, directiveList=[IRLS, update_Jacobi, betaest, save_output])

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

    # make directories (path)
    data_dir = os.path.join(
        work_dir, "Data-{}".format(datetime.now().strftime("%Y-%m-%d-%H-%M")))
    os.mkdir(data_dir)
    data_dir += path_sep

    fig_dir = os.path.join(
        work_dir, "Figs-{}".format(datetime.now().strftime("%Y-%m-%d-%H-%M")))
    os.mkdir(fig_dir)
    fig_dir += path_sep

    # save data files
    dpred = prob.fields(mrec)
    np.savetxt(data_dir + "data_predicted.txt", dpred)

    dnres = (dobs - dpred) / std
    np.savetxt(data_dir + "data_residual_nor.txt", dnres)

    model_dens = actvMap * mrec
    mesh.writeModelUBC(data_dir + "model_rec_dens.txt", model_dens)

    if plotIt:

        # dobs
        fig = plt.figure(figsize=(14, 14))
        ax = plt.subplot()
        im = Utils.PlotUtils.plot2Ddata(xyzLoc,
                                        dobs,
                                        ax=ax,
                                        contourOpts={"cmap": "jet"})
        ax.set_xlabel("Easting (m)", size=22)
        ax.set_ylabel("Northing (m)", size=22)
        ax.set_title("")
        ax.tick_params(labelsize=16)
        ax.ticklabel_format(useOffset=False, style="plain")
        ax.locator_params(nbins=10, axis="x")
        ax.set_title("Observed gravity gradient anomaly", size=22)
        plt.gca().set_aspect("equal", adjustable="box")
        pos = ax.get_position()
        cb_ax = fig.add_axes(
            [pos.x0 + 0.8, pos.y0 + 0.06, pos.width * 0.02, pos.height * 0.8])
        cb = plt.colorbar(im[0], cax=cb_ax, orientation="vertical")
        cb.ax.tick_params(labelsize=16)
        cb.ax.set_title("E", size=22)
        plt.savefig(fig_dir + "plot_obs_grav.png",
                    bbox_inches="tight",
                    dpi=300)

        # dpred
        fig = plt.figure(figsize=(14, 14))
        ax = plt.subplot()
        im = Utils.PlotUtils.plot2Ddata(xyzLoc,
                                        dpred,
                                        ax=ax,
                                        contourOpts={"cmap": "jet"})
        ax.set_xlabel("Easting (m)", size=22)
        ax.set_ylabel("Northing (m)", size=22)
        ax.set_title("")
        ax.tick_params(labelsize=16)
        ax.ticklabel_format(useOffset=False, style="plain")
        ax.locator_params(nbins=10, axis="x")
        ax.set_title("Predicted gravity gradient anomaly", size=22)
        plt.gca().set_aspect("equal", adjustable='box')
        pos = ax.get_position()
        cb_ax = fig.add_axes(
            [pos.x0 + 0.8, pos.y0 + 0.06, pos.width * 0.02, pos.height * 0.8])
        cb = plt.colorbar(im[0], cax=cb_ax, orientation="vertical")
        cb.ax.tick_params(labelsize=16)
        cb.ax.set_title("E", size=22)
        plt.savefig(fig_dir + "plot_pred_grav.png",
                    bbox_inches="tight",
                    dpi=300)

        # nor residual
        fig = plt.figure(figsize=(14, 14))
        ax = plt.subplot()
        im = Utils.PlotUtils.plot2Ddata(xyzLoc,
                                        dnres,
                                        ax=ax,
                                        contourOpts={"cmap": "jet"})
        ax.set_xlabel("Easting (m)", size=22)
        ax.set_ylabel("Northing (m)", size=22)
        ax.set_title("")
        ax.tick_params(labelsize=16)
        ax.ticklabel_format(useOffset=False, style="plain")
        ax.locator_params(nbins=10, axis="x")
        ax.set_title("Normalized residual", size=22)
        plt.gca().set_aspect("equal", adjustable="box")
        pos = ax.get_position()
        cb_ax = fig.add_axes(
            [pos.x0 + 0.8, pos.y0 + 0.06, pos.width * 0.02, pos.height * 0.8])
        cb = plt.colorbar(im[0], cax=cb_ax, orientation="vertical")
        cb.ax.tick_params(labelsize=16)
        cb.ax.set_title("E", size=22)
        plt.savefig(fig_dir + "plot_residual_grav.png",
                    bbox_inches="tight",
                    dpi=300)

        if input_dict["example"] == "horse":
            # plot inverted model
            vmax, vmin = np.nanmax(model_dens), np.nanmin(model_dens)
            fig = plt.figure(figsize=(18, 6))
            # Plot horizontal section of inverted grav model
            ax1 = plt.subplot(121)
            slicePosition = -2000  #meter in z direction
            sliceInd = int(
                round(np.searchsorted(mesh.vectorCCz, slicePosition)))
            mesh.plotSlice(model_dens,
                           ax=ax1,
                           normal="Z",
                           ind=sliceInd,
                           grid=False,
                           clim=(vmin, vmax),
                           pcolorOpts={"cmap": "jet"})
            ax1.set_xlabel("Easting (m)", size=22)
            ax1.set_ylabel("Northing (m)", size=22)
            ax1.set_title("")
            ax1.set_title("(a), z={}m".format(slicePosition + 430),
                          loc="left",
                          size=22)
            ax1.tick_params(labelsize=16)
            ax1.ticklabel_format(useOffset=False, style="plain")
            ax1.locator_params(nbins=8, axis="x")
            ax1.set_aspect("equal", adjustable="box")
            pos1 = ax1.get_position()

            # Vertical section
            ax2 = plt.subplot(122)
            slicePosition = 4790800  #meter in y direction
            sliceInd = int(
                round(np.searchsorted(mesh.vectorCCy, slicePosition)))
            im = mesh.plotSlice(model_dens,
                                ax=ax2,
                                normal="Y",
                                ind=sliceInd,
                                grid=False,
                                clim=(vmin, vmax),
                                pcolorOpts={"cmap": "jet"})
            ax2.set_xlabel("Easting (m)", size=22)
            ax2.set_ylabel("Depth (m)", size=22)
            ax2.set_title("")
            ax2.set_title("(b), y={}".format(slicePosition),
                          loc="left",
                          size=22)
            ax2.tick_params(labelsize=16)
            ax2.ticklabel_format(useOffset=False, style="plain")
            ax2.locator_params(nbins=8, axis="x")
            ax2.set_aspect("equal", adjustable="box")
            pos2 = ax2.get_position()
            pos2_new = [pos2.x0 + 0.02, pos1.y0, pos2.width, pos2.height]
            ax2.set_position(pos2_new)

            cb_ax = fig.add_axes([
                pos2.x0 + 0.09, pos2.y0 + 0.35, pos2.width * 0.6,
                pos2.height * 0.1
            ])
            kwargs = {'format': '%.3f'}
            cb = plt.colorbar(im[0],
                              cax=cb_ax,
                              orientation="horizontal",
                              ticks=np.linspace(vmin, vmax, 4),
                              **kwargs)
            cb.ax.tick_params(labelsize=16)
            cb.set_label("Density (g/cc)", size=22)
            plt.savefig(fig_dir + "plot_model_dens.png",
                        bbox_inches="tight",
                        dpi=300)

        else:
            # plot inverted model
            vmax, vmin = np.nanmax(model_dens), 0
            fig = plt.figure(figsize=(20, 8))
            # Plot horizontal section of inverted grav model
            ax1 = plt.subplot(121)
            slicePosition = -375  #meter in z direction
            sliceInd = int(
                round(np.searchsorted(mesh.vectorCCz, slicePosition)))
            mesh.plotSlice(model_dens,
                           ax=ax1,
                           normal="Z",
                           ind=sliceInd,
                           grid=False,
                           clim=(vmin, vmax),
                           pcolorOpts={"cmap": "jet"})
            circle = plt.Circle((1525, 1525),
                                275,
                                color='white',
                                linewidth=3,
                                fill=False)
            ax1.add_patch(circle)
            ax1.set_xlabel("Easting (m)", size=24)
            ax1.set_ylabel("Northing (m)", size=24)
            ax1.set_title("")
            ax1.set_title("(a), z={}m".format(slicePosition),
                          loc="left",
                          size=24)
            ax1.tick_params(labelsize=24)
            ax1.ticklabel_format(useOffset=False, style="plain")
            ax1.locator_params(nbins=8, axis="x")
            ax1.set_aspect("equal", adjustable="box")
            pos1 = ax1.get_position()

            # Vertical section
            ax2 = plt.subplot(122)
            slicePosition = 1525  #meter in y direction
            sliceInd = int(
                round(np.searchsorted(mesh.vectorCCy, slicePosition)))
            im = mesh.plotSlice(model_dens,
                                ax=ax2,
                                normal="Y",
                                ind=sliceInd,
                                grid=False,
                                clim=(vmin, vmax),
                                pcolorOpts={"cmap": "jet"})
            circle = plt.Circle((1525, -375),
                                275,
                                color='white',
                                linewidth=3,
                                fill=False)
            ax2.add_patch(circle)
            ax2.set_xlabel("Easting (m)", size=24)
            ax2.set_ylabel("Depth (m)", size=24)
            ax2.set_title("")
            ax2.set_title("(b), y={}".format(slicePosition),
                          loc="left",
                          size=24)
            ax2.tick_params(labelsize=24)
            ax2.ticklabel_format(useOffset=False, style="plain")
            ax2.locator_params(nbins=8, axis="x")
            ax2.set_aspect("equal", adjustable="box")
            pos2 = ax2.get_position()
            pos2_new = [pos2.x0 + 0.02, pos1.y0, pos2.width, pos2.height]
            ax2.set_position(pos2_new)

            cb_ax = fig.add_axes([
                pos2.x0 + 0.09, pos2.y0 + 0.35, pos2.width * 0.6,
                pos2.height * 0.1
            ])
            kwargs = {'format': '%.3f'}
            cb = plt.colorbar(im[0],
                              cax=cb_ax,
                              orientation="horizontal",
                              ticks=np.linspace(vmin, vmax, 4),
                              **kwargs)
            cb.ax.tick_params(labelsize=24)
            cb.set_label("Density (g/cc)", size=24)
            plt.savefig(fig_dir + "plot_model_dens.png",
                        bbox_inches="tight",
                        dpi=300)

    elapse = time() - init_t
    print("elapsed time: ", str(timedelta(seconds=elapse)))
Example #16
0
def run(plotIt=False):

    O = np.r_[-1.2, -1.]
    D = np.r_[10., 10.]
    x = np.r_[0., 1.]
    y = np.r_[0., 1.]
    print('length:', StraightRay.lengthInCell(O, D, x, y, plotIt=plotIt))
    O = np.r_[0, -1.]
    D = np.r_[1., 1.] * 1.5
    print('length:', StraightRay.lengthInCell(O,
                                              D,
                                              x * 2,
                                              y * 2,
                                              plotIt=plotIt))

    nC = 20
    M = Mesh.TensorMesh([nC, nC])
    y = np.linspace(0., 1., nC / 2)
    rlocs = np.c_[y * 0 + M.vectorCCx[-1], y]
    rx = StraightRay.Rx(rlocs, None)

    srcList = [
        StraightRay.Src(loc=np.r_[M.vectorCCx[0], yi], rxList=[rx]) for yi in y
    ]

    survey = StraightRay.Survey(srcList)
    problem = StraightRay.Problem(M, slownessMap=Maps.IdentityMap(M))
    problem.pair(survey)

    s = Utils.mkvc(Utils.ModelBuilder.randomModel(M.vnC)) + 1.
    survey.dobs = survey.dpred(s)
    survey.std = 0.01

    # Create an optimization program

    reg = Regularization.Tikhonov(M)
    dmis = DataMisfit.l2_DataMisfit(survey)
    opt = Optimization.InexactGaussNewton(maxIter=40)
    opt.remember('xc')
    invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
    beta = Directives.BetaSchedule()
    betaest = Directives.BetaEstimate_ByEig()
    inv = Inversion.BaseInversion(invProb, directiveList=[beta, betaest])

    # Start the inversion with a model of zeros, and run the inversion
    m0 = np.ones(M.nC) * 1.5
    mopt = inv.run(m0)

    if plotIt is True:
        fig, ax = plt.subplots(1, 2, figsize=(8, 4))
        ax[1].plot(survey.dobs)
        ax[1].plot(survey.dpred(m0), 's')
        ax[1].plot(survey.dpred(mopt), 'o')
        ax[1].legend(['dobs', 'starting dpred', 'dpred'])
        M.plotImage(s, ax=ax[0])
        survey.plot(ax=ax[0])
        ax[0].set_title('survey')

        plt.tight_layout()

    if plotIt is True:
        fig, ax = plt.subplots(1, 3, figsize=(12, 4))
        plt.colorbar(M.plotImage(m0, ax=ax[0])[0], ax=ax[0])
        plt.colorbar(M.plotImage(mopt, ax=ax[1])[0], ax=ax[1])
        plt.colorbar(M.plotImage(s, ax=ax[2])[0], ax=ax[2])

        ax[0].set_title('Starting Model')
        ax[1].set_title('Recovered Model')
        ax[2].set_title('True Model')

        plt.tight_layout()
def run(plotIt=True, saveFig=False):

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        ax1.plot(freqs, -surveyFD.dobs[::2], 'k-', lw=2, label="Obs (real)")
        ax1.plot(freqs, -surveyFD.dobs[1::2], 'k--', lw=2, label="Obs (imag)")

        dpredFD = surveyFD.dpred(moptTD)
        ax1.loglog(freqs,
                   -dpredFD[::2],
                   'bo',
                   ms=6,
                   markeredgecolor='k',
                   markeredgewidth=0.5,
                   label="Pred (real)")
        ax1.loglog(freqs,
                   -dpredFD[1::2],
                   'b+',
                   ms=10,
                   markeredgewidth=2.,
                   label="Pred (imag)")

        ax2.loglog(times, surveyTD.dobs, 'k-', lw=2, label='Obs')
        ax2.loglog(times,
                   surveyTD.dpred(moptTD),
                   'r*',
                   ms=10,
                   markeredgecolor='k',
                   markeredgewidth=0.5,
                   label='Pred')
        ax2.set_xlim(times.min() - 1e-5, times.max() + 1e-4)

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

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

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

        ax2.legend(fontsize=fs, loc=3)
        ax1.legend(fontsize=fs, loc=3)
        ax1.set_xlim(freqs.max() + 1e2, freqs.min() - 1e1)

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

        plt.tight_layout(pad=1.5)

        if saveFig is True:
            plt.savefig('example1.png', dpi=600)
Example #18
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.5
    model[(midx+1):(midx+5), (midy-2):(midy+2), -10:-6] = -0.5
    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 = [0, 1, 1, 1]

    # 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-2, minGNiter=2)
    update_Jacobi = Directives.UpdatePreconditioner()
    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 = -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')
def run(plotIt=True, survey_type="dipole-dipole", p=0., qx=2., qz=2.):
    np.random.seed(1)
    # Initiate I/O class for DC
    IO = DC.IO()
    # Obtain ABMN locations

    xmin, xmax = 0., 200.
    ymin, ymax = 0., 0.
    zmin, zmax = 0, 0
    endl = np.array([[xmin, ymin, zmin], [xmax, ymax, zmax]])
    # Generate DC survey object
    survey = DC.Utils.gen_DCIPsurvey(endl,
                                     survey_type=survey_type,
                                     dim=2,
                                     a=10,
                                     b=10,
                                     n=10)
    survey.getABMN_locations()
    survey = IO.from_ambn_locations_to_survey(survey.a_locations,
                                              survey.b_locations,
                                              survey.m_locations,
                                              survey.n_locations,
                                              survey_type,
                                              data_dc_type='volt')

    # Obtain 2D TensorMesh
    mesh, actind = IO.set_mesh()
    topo, mesh1D = DC.Utils.genTopography(mesh, -10, 0, its=100)
    actind = Utils.surface2ind_topo(mesh, np.c_[mesh1D.vectorCCx, topo])
    survey.drapeTopo(mesh, actind, option="top")

    # Build a conductivity model
    blk_inds_c = Utils.ModelBuilder.getIndicesSphere(np.r_[60., -25.], 12.5,
                                                     mesh.gridCC)
    blk_inds_r = Utils.ModelBuilder.getIndicesSphere(np.r_[140., -25.], 12.5,
                                                     mesh.gridCC)
    layer_inds = mesh.gridCC[:, 1] > -5.
    sigma = np.ones(mesh.nC) * 1. / 100.
    sigma[blk_inds_c] = 1. / 10.
    sigma[blk_inds_r] = 1. / 1000.
    sigma[~actind] = 1. / 1e8
    rho = 1. / sigma

    # Show the true conductivity model
    if plotIt:
        fig = plt.figure(figsize=(12, 3))
        ax = plt.subplot(111)
        temp = rho.copy()
        temp[~actind] = np.nan
        out = mesh.plotImage(temp,
                             grid=True,
                             ax=ax,
                             gridOpts={'alpha': 0.2},
                             clim=(10, 1000),
                             pcolorOpts={
                                 "cmap": "viridis",
                                 "norm": colors.LogNorm()
                             })
        ax.plot(survey.electrode_locations[:, 0],
                survey.electrode_locations[:, 1], 'k.')
        ax.set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
        ax.set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
        cb = plt.colorbar(out[0])
        cb.set_label("Resistivity (ohm-m)")
        ax.set_aspect('equal')
        plt.show()

    # Use Exponential Map: m = log(rho)
    actmap = Maps.InjectActiveCells(mesh,
                                    indActive=actind,
                                    valInactive=np.log(1e8))
    mapping = Maps.ExpMap(mesh) * actmap

    # Generate mtrue
    mtrue = np.log(rho[actind])

    # Generate 2.5D DC problem
    # "N" means potential is defined at nodes
    prb = DC.Problem2D_N(mesh,
                         rhoMap=mapping,
                         storeJ=True,
                         Solver=Solver,
                         verbose=True)
    # Pair problem with survey
    try:
        prb.pair(survey)
    except:
        survey.unpair()
        prb.pair(survey)

    # Make synthetic DC data with 5% Gaussian noise
    dtrue = survey.makeSyntheticData(mtrue, std=0.05, force=True)

    IO.data_dc = dtrue
    # Show apparent resisitivty pseudo-section
    if plotIt:
        IO.plotPseudoSection(data=survey.dobs / IO.G,
                             data_type='apparent_resistivity')

    # Show apparent resisitivty histogram
    if plotIt:
        fig = plt.figure()
        out = hist(survey.dobs / IO.G, bins=20)
        plt.xlabel("Apparent Resisitivty ($\Omega$m)")
        plt.show()

    # Set initial model based upon histogram
    m0 = np.ones(actmap.nP) * np.log(100.)

    # Set uncertainty
    # floor
    eps = 10**(-3.2)
    # percentage
    std = 0.05
    dmisfit = DataMisfit.l2_DataMisfit(survey)
    uncert = abs(survey.dobs) * std + eps
    dmisfit.W = 1. / uncert

    # Map for a regularization
    regmap = Maps.IdentityMap(nP=int(actind.sum()))

    # Related to inversion
    reg = Regularization.Sparse(mesh,
                                indActive=actind,
                                mapping=regmap,
                                gradientType='components')
    #     gradientType = 'components'
    reg.norms = np.c_[p, qx, qz, 0.]
    IRLS = Directives.Update_IRLS(maxIRLSiter=20,
                                  minGNiter=1,
                                  betaSearch=False,
                                  fix_Jmatrix=True)

    opt = Optimization.InexactGaussNewton(maxIter=40)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)
    beta = Directives.BetaSchedule(coolingFactor=5, coolingRate=2)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
    target = Directives.TargetMisfit()
    update_Jacobi = Directives.UpdatePreconditioner()
    inv = Inversion.BaseInversion(invProb, directiveList=[betaest, IRLS])
    prb.counter = opt.counter = Utils.Counter()
    opt.LSshorten = 0.5
    opt.remember('xc')

    # Run inversion
    mopt = inv.run(m0)

    rho_est = mapping * mopt
    rho_est_l2 = mapping * invProb.l2model
    rho_est[~actind] = np.nan
    rho_est_l2[~actind] = np.nan
    rho_true = rho.copy()
    rho_true[~actind] = np.nan

    # show recovered conductivity
    if plotIt:
        vmin, vmax = rho.min(), rho.max()
        fig, ax = plt.subplots(3, 1, figsize=(20, 9))
        out1 = mesh.plotImage(rho_true,
                              clim=(10, 1000),
                              pcolorOpts={
                                  "cmap": "viridis",
                                  "norm": colors.LogNorm()
                              },
                              ax=ax[0])
        out2 = mesh.plotImage(rho_est_l2,
                              clim=(10, 1000),
                              pcolorOpts={
                                  "cmap": "viridis",
                                  "norm": colors.LogNorm()
                              },
                              ax=ax[1])
        out3 = mesh.plotImage(rho_est,
                              clim=(10, 1000),
                              pcolorOpts={
                                  "cmap": "viridis",
                                  "norm": colors.LogNorm()
                              },
                              ax=ax[2])

        out = [out1, out2, out3]
        titles = ["True", "L2", ("L%d, Lx%d, Lz%d") % (p, qx, qz)]
        for i in range(3):
            ax[i].plot(survey.electrode_locations[:, 0],
                       survey.electrode_locations[:, 1], 'kv')
            ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
            ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
            cb = plt.colorbar(out[i][0], ax=ax[i])
            cb.set_label("Resistivity ($\Omega$m)")
            ax[i].set_xlabel("Northing (m)")
            ax[i].set_ylabel("Elevation (m)")
            ax[i].set_aspect('equal')
            ax[i].set_title(titles[i])
        plt.tight_layout()
        plt.show()
Example #20
0
    def run_inversion(
        self,
        maxIter=60,
        m0=0.0,
        mref=0.0,
        percentage=5,
        floor=0.1,
        chifact=1,
        beta0_ratio=1.0,
        coolingFactor=1,
        n_iter_per_beta=1,
        alpha_s=1.0,
        alpha_x=1.0,
        alpha_z=1.0,
        use_target=False,
        use_tikhonov=True,
        use_irls=False,
        p_s=2,
        p_x=2,
        p_y=2,
        p_z=2,
        beta_start=None,
    ):

        self.uncertainty = percentage * abs(self.survey.dobs) * 0.01 + floor

        m0 = np.ones(self.mesh.nC) * m0
        mref = np.ones(self.mesh.nC) * mref

        if ~use_tikhonov:
            reg = Regularization.Sparse(
                self.mesh,
                alpha_s=alpha_s,
                alpha_x=alpha_x,
                alpha_y=alpha_z,
                mref=mref,
                mapping=Maps.IdentityMap(self.mesh),
                cell_weights=self.mesh.vol,
            )
        else:
            reg = Regularization.Tikhonov(
                self.mesh,
                alpha_s=alpha_s,
                alpha_x=alpha_x,
                alpha_y=alpha_z,
                mref=mref,
                mapping=Maps.IdentityMap(self.mesh),
            )
        dmis = DataMisfit.l2_DataMisfit(self.survey)
        dmis.W = 1.0 / self.uncertainty

        opt = Optimization.ProjectedGNCG(maxIter=maxIter, maxIterCG=20)
        opt.lower = 0.0
        opt.remember("xc")
        opt.tolG = 1e-10
        opt.eps = 1e-10
        invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
        save = Directives.SaveOutputEveryIteration()
        beta_schedule = Directives.BetaSchedule(coolingFactor=coolingFactor,
                                                coolingRate=n_iter_per_beta)

        if use_irls:
            IRLS = Directives.Update_IRLS(
                f_min_change=1e-4,
                minGNiter=1,
                silent=False,
                maxIRLSiter=40,
                beta_tol=5e-1,
                coolEpsFact=1.3,
                chifact_start=chifact,
            )

            if beta_start is None:
                directives = [
                    Directives.BetaEstimate_ByEig(beta0_ratio=beta0_ratio),
                    IRLS,
                    save,
                ]
            else:
                directives = [IRLS, save]
                invProb.beta = beta_start
            reg.norms = np.c_[p_s, p_x, p_z, 2]
        else:
            target = Directives.TargetMisfit(chifact=chifact)
            directives = [
                Directives.BetaEstimate_ByEig(beta0_ratio=beta0_ratio),
                beta_schedule,
                save,
            ]
            if use_target:
                directives.append(target)

        inv = Inversion.BaseInversion(invProb, directiveList=directives)
        mopt = inv.run(m0)
        model = opt.recall("xc")
        model.append(mopt)
        pred = []
        for m in model:
            pred.append(self.survey.dpred(m))
        return model, pred, save
Example #21
0
        inversion_type=input_dict["inversion_type"],
        chifact_target=1.)
    )

directiveList.append(
    Directives.Update_IRLS(
        f_min_change=1e-4,
        maxIRLSiter=max_irls_iterations,
        minGNiter=1, beta_tol=0.5, prctile=90, floorEpsEnforced=True,
        coolingRate=1, coolEps_q=True, coolEpsFact=1.2,
        betaSearch=False
    )
)

if initial_beta is None:
    directiveList.append(Directives.BetaEstimate_ByEig(beta0_ratio=1e+1))

directiveList.append(Directives.UpdatePreconditioner())

directiveList.append(
    Directives.SaveUBCModelEveryIteration(
        mapping=activeCellsMap * model_map,
        mesh=mesh,
        fileName=outDir + input_dict["inversion_type"],
        vector=input_dict["inversion_type"][0:3] == 'mvi'
    )
)

directiveList.append(
    Directives.SaveUBCPredictedEveryIteration(
        survey=survey,
Example #22
0
def run(plotIt=True):
    """
    1D FDEM Mu Inversion
    ====================

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

    """

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

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

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

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

    mtrue = mur[active]

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

    # Mapping
    muMap = murMap * surj1Dmap * actMap

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

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

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

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

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

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

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

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

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

    dpredFD = surveyFD.dpred(moptFD)

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

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

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

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

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

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

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

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

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

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

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

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

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

        plt.tight_layout(pad=1.5)
Example #23
0
def run(plotIt=True, cleanAfterRun=True):

    # Start by downloading files from the remote repository
    # directory where the downloaded files are

    url = "https://storage.googleapis.com/simpeg/Chile_GRAV_4_Miller/Chile_GRAV_4_Miller.tar.gz"
    downloads = download(url, overwrite=True)
    basePath = downloads.split(".")[0]

    # unzip the tarfile
    tar = tarfile.open(downloads, "r")
    tar.extractall()
    tar.close()

    input_file = basePath + os.path.sep + 'LdM_input_file.inp'
    # %% User input
    # Plotting parameters, max and min densities in g/cc
    vmin = -0.6
    vmax = 0.6

    # weight exponent for default weighting
    wgtexp = 3.
    # %%
    # Read in the input file which included all parameters at once
    # (mesh, topo, model, survey, inv param, etc.)
    driver = PF.GravityDriver.GravityDriver_Inv(input_file)
    # %%
    # Now we need to create the survey and model information.

    # Access the mesh and survey information
    mesh = driver.mesh
    survey = driver.survey

    # define gravity survey locations
    rxLoc = survey.srcField.rxList[0].locs

    # define gravity data and errors
    d = survey.dobs
    wd = survey.std

    # Get the active cells
    active = driver.activeCells
    nC = len(active)  # Number of active cells

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

    # Create static map
    static = driver.staticCells
    dynamic = driver.dynamicCells

    staticCells = Maps.InjectActiveCells(None,
                                         dynamic,
                                         driver.m0[static],
                                         nC=nC)
    mstart = driver.m0[dynamic]

    # Get index of the center
    midx = int(mesh.nCx / 2)
    # %%
    # Now that we have a model and a survey we can build the linear system ...
    # Create the forward model operator
    prob = PF.Gravity.GravityIntegral(mesh, rhoMap=staticCells, actInd=active)
    prob.solverOpts['accuracyTol'] = 1e-4

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

    # Apply depth weighting
    wr = PF.Magnetics.get_dist_wgt(mesh, rxLoc, active, wgtexp,
                                   np.min(mesh.hx) / 4.)
    wr = wr**2.

    # %% Create inversion objects
    reg = Regularization.Sparse(mesh,
                                indActive=active,
                                mapping=staticCells,
                                gradientType='total')
    reg.mref = driver.mref[dynamic]
    reg.cell_weights = wr * mesh.vol[active]
    reg.norms = np.c_[0., 1., 1., 1.]
    # reg.norms = driver.lpnorms

    # Specify how the optimization will proceed
    opt = Optimization.ProjectedGNCG(maxIter=20,
                                     lower=driver.bounds[0],
                                     upper=driver.bounds[1],
                                     maxIterLS=10,
                                     maxIterCG=20,
                                     tolCG=1e-3)

    # Define misfit function (obs-calc)
    dmis = DataMisfit.l2_DataMisfit(survey)
    dmis.W = 1. / wd

    # create the default L2 inverse problem from the above objects
    invProb = InvProblem.BaseInvProblem(dmis, reg, opt)

    # Specify how the initial beta is found
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e-2)

    # IRLS sets up the Lp inversion problem
    # Set the eps parameter parameter in Line 11 of the
    # input file based on the distribution of model (DEFAULT = 95th %ile)
    IRLS = Directives.Update_IRLS(f_min_change=1e-4,
                                  maxIRLSiter=40,
                                  beta_tol=5e-1)

    # Preconditioning refreshing for each IRLS iteration
    update_Jacobi = Directives.UpdatePreconditioner()

    # Create combined the L2 and Lp problem
    inv = Inversion.BaseInversion(invProb,
                                  directiveList=[IRLS, update_Jacobi, betaest])

    # %%
    # Run L2 and Lp inversion
    mrec = inv.run(mstart)

    if cleanAfterRun:
        os.remove(downloads)
        shutil.rmtree(basePath)

    # %%
    if plotIt:
        # Plot observed data
        PF.Magnetics.plot_obs_2D(rxLoc, d, 'Observed Data')

        # %%
        # Write output model and data files and print misft stats.

        # reconstructing l2 model mesh with air cells and active dynamic cells
        L2out = activeMap * invProb.l2model

        # reconstructing lp model mesh with air cells and active dynamic cells
        Lpout = activeMap * mrec

        # %%
        # Plot out sections and histograms of the smooth l2 model.
        # The ind= parameter is the slice of the model from top down.
        yslice = midx + 1
        L2out[L2out == -100] = np.nan  # set "air" to nan

        plt.figure(figsize=(10, 7))
        plt.suptitle('Smooth Inversion: Depth weight = ' + str(wgtexp))
        ax = plt.subplot(221)
        dat1 = mesh.plotSlice(L2out,
                              ax=ax,
                              normal='Z',
                              ind=-16,
                              clim=(vmin, vmax),
                              pcolorOpts={'cmap': 'bwr'})
        plt.plot(np.array([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 np.array([mesh.vectorCCy[yslice], mesh.vectorCCy[yslice]]),
                 c='gray',
                 linestyle='--')
        plt.scatter(rxLoc[0:, 0], rxLoc[0:, 1], color='k', s=1)
        plt.title('Z: ' + str(mesh.vectorCCz[-16]) + ' m')
        plt.xlabel('Easting (m)')
        plt.ylabel('Northing (m)')
        plt.gca().set_aspect('equal', adjustable='box')
        cb = plt.colorbar(dat1[0],
                          orientation="vertical",
                          ticks=np.linspace(vmin, vmax, 4))
        cb.set_label('Density (g/cc$^3$)')

        ax = plt.subplot(222)
        dat = mesh.plotSlice(L2out,
                             ax=ax,
                             normal='Z',
                             ind=-27,
                             clim=(vmin, vmax),
                             pcolorOpts={'cmap': 'bwr'})
        plt.plot(np.array([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 np.array([mesh.vectorCCy[yslice], mesh.vectorCCy[yslice]]),
                 c='gray',
                 linestyle='--')
        plt.scatter(rxLoc[0:, 0], rxLoc[0:, 1], color='k', s=1)
        plt.title('Z: ' + str(mesh.vectorCCz[-27]) + ' m')
        plt.xlabel('Easting (m)')
        plt.ylabel('Northing (m)')
        plt.gca().set_aspect('equal', adjustable='box')
        cb = plt.colorbar(dat1[0],
                          orientation="vertical",
                          ticks=np.linspace(vmin, vmax, 4))
        cb.set_label('Density (g/cc$^3$)')

        ax = plt.subplot(212)
        mesh.plotSlice(L2out,
                       ax=ax,
                       normal='Y',
                       ind=yslice,
                       clim=(vmin, vmax),
                       pcolorOpts={'cmap': 'bwr'})
        plt.title('Cross Section')
        plt.xlabel('Easting(m)')
        plt.ylabel('Elevation')
        plt.gca().set_aspect('equal', adjustable='box')
        cb = plt.colorbar(dat1[0],
                          orientation="vertical",
                          ticks=np.linspace(vmin, vmax, 4),
                          cmap='bwr')
        cb.set_label('Density (g/cc$^3$)')

        # %%
        # Make plots of Lp model
        yslice = midx + 1
        Lpout[Lpout == -100] = np.nan  # set "air" to nan

        plt.figure(figsize=(10, 7))
        plt.suptitle('Compact Inversion: Depth weight = ' + str(wgtexp) +
                     ': $\epsilon_p$ = ' + str(round(reg.eps_p, 1)) +
                     ': $\epsilon_q$ = ' + str(round(reg.eps_q, 2)))
        ax = plt.subplot(221)
        dat = mesh.plotSlice(Lpout,
                             ax=ax,
                             normal='Z',
                             ind=-16,
                             clim=(vmin, vmax),
                             pcolorOpts={'cmap': 'bwr'})
        plt.plot(np.array([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 np.array([mesh.vectorCCy[yslice], mesh.vectorCCy[yslice]]),
                 c='gray',
                 linestyle='--')
        plt.scatter(rxLoc[0:, 0], rxLoc[0:, 1], color='k', s=1)
        plt.title('Z: ' + str(mesh.vectorCCz[-16]) + ' m')
        plt.xlabel('Easting (m)')
        plt.ylabel('Northing (m)')
        plt.gca().set_aspect('equal', adjustable='box')
        cb = plt.colorbar(dat[0],
                          orientation="vertical",
                          ticks=np.linspace(vmin, vmax, 4))
        cb.set_label('Density (g/cc$^3$)')

        ax = plt.subplot(222)
        dat = mesh.plotSlice(Lpout,
                             ax=ax,
                             normal='Z',
                             ind=-27,
                             clim=(vmin, vmax),
                             pcolorOpts={'cmap': 'bwr'})
        plt.plot(np.array([mesh.vectorCCx[0], mesh.vectorCCx[-1]]),
                 np.array([mesh.vectorCCy[yslice], mesh.vectorCCy[yslice]]),
                 c='gray',
                 linestyle='--')
        plt.scatter(rxLoc[0:, 0], rxLoc[0:, 1], color='k', s=1)
        plt.title('Z: ' + str(mesh.vectorCCz[-27]) + ' m')
        plt.xlabel('Easting (m)')
        plt.ylabel('Northing (m)')
        plt.gca().set_aspect('equal', adjustable='box')
        cb = plt.colorbar(dat[0],
                          orientation="vertical",
                          ticks=np.linspace(vmin, vmax, 4))
        cb.set_label('Density (g/cc$^3$)')

        ax = plt.subplot(212)
        dat = mesh.plotSlice(Lpout,
                             ax=ax,
                             normal='Y',
                             ind=yslice,
                             clim=(vmin, vmax),
                             pcolorOpts={'cmap': 'bwr'})
        plt.title('Cross Section')
        plt.xlabel('Easting (m)')
        plt.ylabel('Elevation (m)')
        plt.gca().set_aspect('equal', adjustable='box')
        cb = plt.colorbar(dat[0],
                          orientation="vertical",
                          ticks=np.linspace(vmin, vmax, 4))
        cb.set_label('Density (g/cc$^3$)')
Example #24
0
    def setUp(self):
        # We will assume a vertical inducing field
        H0 = (50000., 90., 0.)

        # The magnetization is set along a different direction (induced + remanence)
        M = np.array([90., 0.])

        # Block with an effective susceptibility
        chi_e = 0.05

        # Create grid of points for topography
        # Lets create a simple Gaussian topo and set the active cells
        [xx, yy] = np.meshgrid(np.linspace(-200, 200, 50),
                               np.linspace(-200, 200, 50))
        b = 100
        A = 50
        zz = A * np.exp(-0.5 * ((xx / b)**2. + (yy / b)**2.))
        topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)]

        # Create and array of observation points
        xr = np.linspace(-100., 100., 20)
        yr = np.linspace(-100., 100., 20)
        X, Y = np.meshgrid(xr, yr)
        Z = A * np.exp(-0.5 * ((X / b)**2. + (Y / b)**2.)) + 5

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

        # Create a mesh
        h = [5, 5, 5]
        padDist = np.ones((3, 2)) * 100
        nCpad = [4, 4, 2]

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

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

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

        # 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
        # For now equal in 3D
        nCx, nCy, nCz = 2**(maxLevel), 2**(maxLevel), 2**(maxLevel)

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

        # Set origin
        mesh.x0 = np.r_[-nCx * h[0] / 2. + midX, -nCy * h[1] / 2. + midY,
                        -nCz * h[2] / 2. + midZ]

        # Refine the mesh around topography
        # Get extent of points
        F = NearestNDInterpolator(topo[:, :2], topo[:, 2])
        zOffset = 0
        # Cycle through the first 3 octree levels
        for ii in range(3):

            dx = mesh.hx.min() * 2**ii

            nCx = int((limx[0] - limx[1]) / dx)
            nCy = int((limy[0] - limy[1]) / dx)

            # Create a grid at the octree level in xy
            CCx, CCy = np.meshgrid(np.linspace(limx[1], limx[0], nCx),
                                   np.linspace(limy[1], limy[0], nCy))

            z = F(mkvc(CCx), mkvc(CCy))

            # level means number of layers in current OcTree level
            for level in range(int(nCpad[ii])):

                mesh.insert_cells(np.c_[mkvc(CCx),
                                        mkvc(CCy), z - zOffset],
                                  np.ones_like(z) * maxLevel - ii,
                                  finalize=False)

                zOffset += dx

        mesh.finalize()

        # Define an active cells from topo
        actv = Utils.surface2ind_topo(mesh, topo)
        nC = int(actv.sum())

        # Convert the inclination declination to vector in Cartesian
        M_xyz = Utils.matutils.dip_azimuth2cartesian(
            np.ones(nC) * M[0],
            np.ones(nC) * M[1])

        # Get the indicies of the magnetized block
        ind = Utils.ModelBuilder.getIndicesBlock(
            np.r_[-20, -20, -10],
            np.r_[20, 20, 25],
            mesh.gridCC,
        )[0]

        # Assign magnetization value, inducing field strength will
        # be applied in by the :class:`SimPEG.PF.Magnetics` problem
        model = np.zeros(mesh.nC)
        model[ind] = chi_e

        # Remove air cells
        self.model = model[actv]

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

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

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

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

        # Compute some data and add some random noise
        data = prob.fields(self.model)

        # Split the data in components
        nD = rxLoc.shape[0]

        std = 5  # nT
        data += np.random.randn(nD) * std
        wd = np.ones(nD) * std

        # Assigne data and uncertainties to the survey
        survey.dobs = data
        survey.std = wd

        ######################################################################
        # Equivalent Source

        # Get the active cells for equivalent source is the top only
        surf = Utils.modelutils.surface_layer_index(mesh, topo)

        # Get the layer of cells directyl below topo
        nC = np.count_nonzero(surf)  # Number of active cells

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

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

        # Create static map
        prob = PF.Magnetics.MagneticIntegral(mesh,
                                             chiMap=idenMap,
                                             actInd=surf,
                                             parallelized=False,
                                             equiSourceLayer=True)

        prob.solverOpts['accuracyTol'] = 1e-4

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

        # Create a regularization function, in this case l2l2
        reg = Regularization.Sparse(mesh,
                                    indActive=surf,
                                    mapping=Maps.IdentityMap(nP=nC),
                                    scaledIRLS=False)
        reg.mref = np.zeros(nC)

        # Specify how the optimization will proceed,
        # set susceptibility bounds to inf
        opt = Optimization.ProjectedGNCG(maxIter=20,
                                         lower=-np.inf,
                                         upper=np.inf,
                                         maxIterLS=20,
                                         maxIterCG=20,
                                         tolCG=1e-3)

        # Define misfit function (obs-calc)
        dmis = DataMisfit.l2_DataMisfit(survey)
        dmis.W = 1. / survey.std

        # Create the default L2 inverse problem from the above objects
        invProb = InvProblem.BaseInvProblem(dmis, reg, opt)

        # Specify how the initial beta is found
        betaest = Directives.BetaEstimate_ByEig()

        # Target misfit to stop the inversion,
        # try to fit as much as possible of the signal,
        # we don't want to lose anything
        IRLS = Directives.Update_IRLS(f_min_change=1e-3,
                                      minGNiter=1,
                                      beta_tol=1e-1)
        update_Jacobi = Directives.UpdatePreconditioner()
        # Put all the parts together
        inv = Inversion.BaseInversion(
            invProb, directiveList=[betaest, IRLS, update_Jacobi])

        # Run the equivalent source inversion
        mstart = np.ones(nC) * 1e-4
        mrec = inv.run(mstart)

        # Won't store the sensitivity and output 'xyz' data.
        prob.forwardOnly = True
        prob.rx_type = 'xyz'
        prob._G = None
        prob.modelType = 'amplitude'
        prob.model = mrec
        pred = prob.fields(mrec)

        bx = pred[:nD]
        by = pred[nD:2 * nD]
        bz = pred[2 * nD:]

        bAmp = (bx**2. + by**2. + bz**2.)**0.5

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

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

        self.mstart = np.ones(nC) * 1e-4

        # Create the forward model operator
        prob = PF.Magnetics.MagneticIntegral(mesh,
                                             chiMap=idenMap,
                                             actInd=actv,
                                             modelType='amplitude',
                                             rx_type='xyz')
        prob.model = self.mstart
        # Change the survey to xyz components
        surveyAmp = PF.BaseMag.LinearSurvey(survey.srcField)

        # Pair the survey and problem
        surveyAmp.pair(prob)
        # Create a regularization function, in this case l2l2
        wr = np.sum(prob.G**2., axis=0)**0.5
        wr = (wr / np.max(wr))
        # Re-set the observations to |B|
        surveyAmp.dobs = bAmp
        surveyAmp.std = wd

        # Create a sparse regularization
        reg = Regularization.Sparse(mesh, indActive=actv, mapping=idenMap)
        reg.norms = np.c_[0, 0, 0, 0]
        reg.mref = np.zeros(nC)
        reg.cell_weights = wr
        # Data misfit function
        dmis = DataMisfit.l2_DataMisfit(surveyAmp)
        dmis.W = 1. / surveyAmp.std

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

        invProb = InvProblem.BaseInvProblem(dmis, reg, opt)

        # Here is the list of directives
        betaest = Directives.BetaEstimate_ByEig()

        # Specify the sparse norms
        IRLS = Directives.Update_IRLS(f_min_change=1e-3,
                                      minGNiter=1,
                                      coolingRate=1,
                                      betaSearch=False)

        # The sensitivity weights are update between each iteration.
        update_SensWeight = Directives.UpdateSensitivityWeights()
        update_Jacobi = Directives.UpdatePreconditioner(threshold=1 - 3)

        # Put all together
        self.inv = Inversion.BaseInversion(
            invProb,
            directiveList=[betaest, IRLS, update_SensWeight, update_Jacobi])

        self.mesh = mesh
Example #25
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, chiMap=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
        reg.norms = np.c_[0, 0, 0, 0]
        reg.gradientType = 'component'
        # reg.eps_p, reg.eps_q = 1e-3, 1e-3

        # 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)

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

        # Here is where the norms are applied
        IRLS = Directives.Update_IRLS(f_min_change=1e-4, minGNiter=1)
        update_Jacobi = Directives.UpdatePreconditioner()
        self.inv = Inversion.BaseInversion(
            invProb, directiveList=[IRLS, betaest, update_Jacobi])
Example #26
0
def run_inversion(
    m0,
    survey,
    actind,
    mesh,
    wires,
    std,
    eps,
    maxIter=15,
    beta0_ratio=1e0,
    coolingFactor=2,
    coolingRate=2,
    maxIterLS=20,
    maxIterCG=10,
    LSshorten=0.5,
    eta_lower=1e-5,
    eta_upper=1,
    tau_lower=1e-6,
    tau_upper=10.,
    c_lower=1e-2,
    c_upper=1.,
    is_log_tau=True,
    is_log_c=True,
    is_log_eta=True,
    mref=None,
    alpha_s=1e-4,
    alpha_x=1e0,
    alpha_y=1e0,
    alpha_z=1e0,
):
    """
    Run Spectral Spectral IP inversion
    """
    dmisfit = DataMisfit.l2_DataMisfit(survey)
    uncert = abs(survey.dobs) * std + eps
    dmisfit.W = 1. / uncert
    # Map for a regularization
    # Related to inversion

    # Set Upper and Lower bounds
    e = np.ones(actind.sum())

    if np.isscalar(eta_lower):
        eta_lower = e * eta_lower
    if np.isscalar(tau_lower):
        tau_lower = e * tau_lower
    if np.isscalar(c_lower):
        c_lower = e * c_lower

    if np.isscalar(eta_upper):
        eta_upper = e * eta_upper
    if np.isscalar(tau_upper):
        tau_upper = e * tau_upper
    if np.isscalar(c_upper):
        c_upper = e * c_upper

    if is_log_eta:
        eta_upper = np.log(eta_upper)
        eta_lower = np.log(eta_lower)

    if is_log_tau:
        tau_upper = np.log(tau_upper)
        tau_lower = np.log(tau_lower)

    if is_log_c:
        c_upper = np.log(c_upper)
        c_lower = np.log(c_lower)

    m_upper = np.r_[eta_upper, tau_upper, c_upper]
    m_lower = np.r_[eta_lower, tau_lower, c_lower]

    # Set up regularization
    reg_eta = Regularization.Tikhonov(mesh,
                                      mapping=wires.eta,
                                      indActive=actind)
    reg_tau = Regularization.Tikhonov(mesh,
                                      mapping=wires.tau,
                                      indActive=actind)

    reg_c = Regularization.Tikhonov(mesh, mapping=wires.c, indActive=actind)

    # Todo:

    reg_eta.alpha_s = alpha_s
    reg_tau.alpha_s = alpha_s
    reg_c.alpha_s = alpha_s

    reg_eta.alpha_x = alpha_x
    reg_tau.alpha_x = alpha_x
    reg_c.alpha_x = alpha_x

    reg_eta.alpha_y = alpha_y
    reg_tau.alpha_y = alpha_y
    reg_c.alpha_y = alpha_y

    reg_eta.alpha_z = alpha_z
    reg_tau.alpha_z = alpha_z
    reg_c.alpha_z = alpha_z

    reg = reg_eta + reg_tau + reg_c

    # Use Projected Gauss Newton scheme
    opt = Optimization.ProjectedGNCG(maxIter=maxIter,
                                     upper=m_upper,
                                     lower=m_lower,
                                     maxIterLS=maxIterLS,
                                     maxIterCG=maxIterCG,
                                     LSshorten=LSshorten)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)
    beta = Directives.BetaSchedule(coolingFactor=coolingFactor,
                                   coolingRate=coolingRate)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=beta0_ratio)
    target = Directives.TargetMisfit()

    directiveList = [beta, betaest, target]

    inv = Inversion.BaseInversion(invProb, directiveList=directiveList)
    opt.LSshorten = 0.5
    opt.remember('xc')

    # Run inversion
    mopt = inv.run(m0)
    return mopt, invProb.dpred
Example #27
0
survey.dpred(mtrue)
survey.makeSyntheticData(mtrue, std=0.05, force=True)

print '# of data: ', survey.dobs.shape

#Simple Inversion
regmesh = mesh
m0 = (-5.) * np.ones(mapping.nP)
dmis = DataMisfit.l2_DataMisfit(survey)
reg = Regularization.Tikhonov(regmesh)  #,mapping = mapping)#,indActive=actind)
reg.mref = m0
opt = Optimization.InexactGaussNewton(maxIter=20, tolX=1e-6)
opt.remember('xc')
invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
beta = Directives.BetaEstimate_ByEig(beta0=10., beta0_ratio=1e0)
reg.alpha_s = 1e-2
#beta = 0.
#invProb.beta = beta
betaSched = Directives.BetaSchedule(coolingFactor=5, coolingRate=2)
#sav0 = Directives.SaveEveryIteration()
#sav1 = Directives.SaveModelEveryIteration()
sav2 = Directives.SaveOutputDictEveryIteration()
inv = Inversion.BaseInversion(invProb, directiveList=[sav2, beta,
                                                      betaSched])  #sav0,sav1,

mtest = np.load('../Update_W_each_3it_5s_rademacher/finalresult.npy')
print "check misfit with W: ", dmis.eval(mtest) / survey.nD
mm = meshCore.plotImage(mtest[actind])
plt.colorbar(mm[0])
plt.show()
def run(plotIt=True,
        survey_type="dipole-dipole",
        rho_background=1e3,
        rho_block=1e2,
        block_x0=100,
        block_dx=10,
        block_y0=-10,
        block_dy=5):

    np.random.seed(1)
    # Initiate I/O class for DC
    IO = DC.IO()
    # Obtain ABMN locations

    xmin, xmax = 0., 200.
    ymin, ymax = 0., 0.
    zmin, zmax = 0, 0
    endl = np.array([[xmin, ymin, zmin], [xmax, ymax, zmax]])
    # Generate DC survey object
    survey = DC.Utils.gen_DCIPsurvey(endl,
                                     survey_type=survey_type,
                                     dim=2,
                                     a=10,
                                     b=10,
                                     n=10)
    survey.getABMN_locations()
    survey = IO.from_ambn_locations_to_survey(survey.a_locations,
                                              survey.b_locations,
                                              survey.m_locations,
                                              survey.n_locations,
                                              survey_type,
                                              data_dc_type='volt')

    # Obtain 2D TensorMesh
    mesh, actind = IO.set_mesh()
    # Flat topography
    actind = Utils.surface2ind_topo(mesh, np.c_[mesh.vectorCCx,
                                                mesh.vectorCCx * 0.])
    survey.drapeTopo(mesh, actind, option="top")
    # Use Exponential Map: m = log(rho)
    actmap = Maps.InjectActiveCells(mesh,
                                    indActive=actind,
                                    valInactive=np.log(1e8))
    parametric_block = Maps.ParametricBlock(mesh, slopeFact=1e2)
    mapping = Maps.ExpMap(mesh) * parametric_block
    # Set true model
    # val_background,val_block, block_x0, block_dx, block_y0, block_dy
    mtrue = np.r_[np.log(1e3), np.log(10), 100, 10, -20, 10]

    # Set initial model
    m0 = np.r_[np.log(rho_background),
               np.log(rho_block), block_x0, block_dx, block_y0, block_dy]
    rho = mapping * mtrue
    rho0 = mapping * m0
    # Show the true conductivity model
    fig = plt.figure(figsize=(12, 3))
    ax = plt.subplot(111)
    temp = rho.copy()
    temp[~actind] = np.nan
    out = mesh.plotImage(temp,
                         grid=False,
                         ax=ax,
                         gridOpts={'alpha': 0.2},
                         clim=(10, 1000),
                         pcolorOpts={
                             "cmap": "viridis",
                             "norm": colors.LogNorm()
                         })
    ax.plot(survey.electrode_locations[:, 0], survey.electrode_locations[:, 1],
            'k.')
    ax.set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
    ax.set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
    cb = plt.colorbar(out[0])
    cb.set_label("Resistivity (ohm-m)")
    ax.set_aspect('equal')
    ax.set_title("True resistivity model")
    plt.show()
    # Show the true conductivity model
    fig = plt.figure(figsize=(12, 3))
    ax = plt.subplot(111)
    temp = rho0.copy()
    temp[~actind] = np.nan
    out = mesh.plotImage(temp,
                         grid=False,
                         ax=ax,
                         gridOpts={'alpha': 0.2},
                         clim=(10, 1000),
                         pcolorOpts={
                             "cmap": "viridis",
                             "norm": colors.LogNorm()
                         })
    ax.plot(survey.electrode_locations[:, 0], survey.electrode_locations[:, 1],
            'k.')
    ax.set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
    ax.set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
    cb = plt.colorbar(out[0])
    cb.set_label("Resistivity (ohm-m)")
    ax.set_aspect('equal')
    ax.set_title("Initial resistivity model")
    plt.show()

    # Generate 2.5D DC problem
    # "N" means potential is defined at nodes
    prb = DC.Problem2D_N(mesh, rhoMap=mapping, storeJ=True, Solver=Solver)
    # Pair problem with survey
    try:
        prb.pair(survey)
    except:
        survey.unpair()
        prb.pair(survey)

    # Make synthetic DC data with 5% Gaussian noise
    dtrue = survey.makeSyntheticData(mtrue, std=0.05, force=True)

    # Show apparent resisitivty pseudo-section
    IO.plotPseudoSection(data=survey.dobs / IO.G,
                         data_type='apparent_resistivity')

    # Show apparent resisitivty histogram
    fig = plt.figure()
    out = hist(survey.dobs / IO.G, bins=20)
    plt.show()
    # Set uncertainty
    # floor
    eps = 10**(-3.2)
    # percentage
    std = 0.05
    dmisfit = DataMisfit.l2_DataMisfit(survey)
    uncert = abs(survey.dobs) * std + eps
    dmisfit.W = 1. / uncert

    # Map for a regularization
    mesh_1d = Mesh.TensorMesh([parametric_block.nP])
    # Related to inversion
    reg = Regularization.Simple(mesh_1d, alpha_x=0.)
    opt = Optimization.InexactGaussNewton(maxIter=10)
    invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)
    beta = Directives.BetaSchedule(coolingFactor=5, coolingRate=2)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
    target = Directives.TargetMisfit()
    updateSensW = Directives.UpdateSensitivityWeights()
    update_Jacobi = Directives.UpdatePreconditioner()
    invProb.beta = 0.
    inv = Inversion.BaseInversion(invProb, directiveList=[target])
    prb.counter = opt.counter = Utils.Counter()
    opt.LSshorten = 0.5
    opt.remember('xc')

    # Run inversion
    mopt = inv.run(m0)

    # Convert obtained inversion model to resistivity
    # rho = M(m), where M(.) is a mapping

    rho_est = mapping * mopt
    rho_true = rho.copy()
    # show recovered conductivity
    vmin, vmax = rho.min(), rho.max()
    fig, ax = plt.subplots(2, 1, figsize=(20, 6))
    out1 = mesh.plotImage(rho_true,
                          clim=(10, 1000),
                          pcolorOpts={
                              "cmap": "viridis",
                              "norm": colors.LogNorm()
                          },
                          ax=ax[0])
    out2 = mesh.plotImage(rho_est,
                          clim=(10, 1000),
                          pcolorOpts={
                              "cmap": "viridis",
                              "norm": colors.LogNorm()
                          },
                          ax=ax[1])
    out = [out1, out2]
    for i in range(2):
        ax[i].plot(survey.electrode_locations[:, 0],
                   survey.electrode_locations[:, 1], 'kv')
        ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
        ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
        cb = plt.colorbar(out[i][0], ax=ax[i])
        cb.set_label("Resistivity ($\Omega$m)")
        ax[i].set_xlabel("Northing (m)")
        ax[i].set_ylabel("Elevation (m)")
        ax[i].set_aspect('equal')
    ax[0].set_title("True resistivity model")
    ax[1].set_title("Recovered resistivity model")
    plt.tight_layout()
    plt.show()
Example #29
0
# Data misfit function
dmis = DataMisfit.l2_DataMisfit(survey)
dmis.W = 1. / survey.std

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

invProb = InvProblem.BaseInvProblem(dmis, reg, opt)

# A list of directive to control the inverson
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-3, maxIRLSiter=0, beta_tol=5e-1)

# Pre-conditioner
update_Jacobi = Directives.UpdatePreconditioner()

inv = Inversion.BaseInversion(invProb,
                              directiveList=[IRLS, update_Jacobi, betaest])

# Run the inversion
m0 = np.ones(3 * nC) * 1e-4  # Starting model
mrec_MVIC = inv.run(m0)
    def setUp(self):
        # We will assume a vertical inducing field
        H0 = (50000., 90., 0.)

        # The magnetization is set along a different direction (induced + remanence)
        M = np.array([90., 0.])

        # Block with an effective susceptibility
        chi_e = 0.05

        # Create grid of points for topography
        # Lets create a simple Gaussian topo and set the active cells
        [xx, yy] = np.meshgrid(np.linspace(-200, 200, 50),
                               np.linspace(-200, 200, 50))
        b = 100
        A = 50
        zz = A * np.exp(-0.5 * ((xx / b)**2. + (yy / b)**2.))
        topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)]

        # Create and array of observation points
        xr = np.linspace(-100., 100., 20)
        yr = np.linspace(-100., 100., 20)
        X, Y = np.meshgrid(xr, yr)
        Z = A * np.exp(-0.5 * ((X / b)**2. + (Y / b)**2.)) + 5

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

        # Create a mesh
        h = [5, 5, 5]
        padDist = np.ones((3, 2)) * 100
        nCpad = [4, 4, 2]

        self.mesh = meshutils.mesh_builder_xyz(
            xyzLoc,
            h,
            padding_distance=padDist,
            mesh_type='TREE',
        )

        self.mesh = meshutils.refine_tree_xyz(
            self.mesh,
            topo,
            method='surface',
            octree_levels=nCpad,
            octree_levels_padding=nCpad,
            finalize=True,
        )
        # Define an active cells from topo
        actv = Utils.surface2ind_topo(self.mesh, topo)
        nC = int(actv.sum())

        # Convert the inclination declination to vector in Cartesian
        M_xyz = Utils.matutils.dip_azimuth2cartesian(
            np.ones(nC) * M[0],
            np.ones(nC) * M[1])

        # Get the indicies of the magnetized block
        ind = Utils.ModelBuilder.getIndicesBlock(
            np.r_[-20, -20, -15],
            np.r_[20, 20, 20],
            self.mesh.gridCC,
        )[0]

        # Assign magnetization value, inducing field strength will
        # be applied in by the :class:`SimPEG.PF.Magnetics` problem
        model = np.zeros(self.mesh.nC)
        model[ind] = chi_e

        # Remove air cells
        self.model = model[actv]

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

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

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

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

        # Compute some data and add some random noise
        data = prob.fields(self.model)

        # Split the data in components
        nD = xyzLoc.shape[0]

        std = 5  # nT
        data += np.random.randn(nD) * std
        wd = np.ones(nD) * std

        # Assigne data and uncertainties to the survey
        survey.dobs = data
        survey.std = wd

        ######################################################################
        # Equivalent Source

        # Get the active cells for equivalent source is the top only
        surf = Utils.modelutils.surface_layer_index(self.mesh, topo)

        # Get the layer of cells directyl below topo
        nC = np.count_nonzero(surf)  # Number of active cells

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

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

        # Create static map
        prob = PF.Magnetics.MagneticIntegral(self.mesh,
                                             chiMap=idenMap,
                                             actInd=surf,
                                             parallelized=False,
                                             equiSourceLayer=True)

        prob.solverOpts['accuracyTol'] = 1e-4

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

        # Create a regularization function, in this case l2l2
        reg = Regularization.Sparse(self.mesh,
                                    indActive=surf,
                                    mapping=Maps.IdentityMap(nP=nC),
                                    scaledIRLS=False)
        reg.mref = np.zeros(nC)

        # Specify how the optimization will proceed,
        # set susceptibility bounds to inf
        opt = Optimization.ProjectedGNCG(maxIter=20,
                                         lower=-np.inf,
                                         upper=np.inf,
                                         maxIterLS=20,
                                         maxIterCG=20,
                                         tolCG=1e-3)

        # Define misfit function (obs-calc)
        dmis = DataMisfit.l2_DataMisfit(survey)
        dmis.W = 1. / survey.std

        # Create the default L2 inverse problem from the above objects
        invProb = InvProblem.BaseInvProblem(dmis, reg, opt)

        # Specify how the initial beta is found
        betaest = Directives.BetaEstimate_ByEig()

        # Target misfit to stop the inversion,
        # try to fit as much as possible of the signal,
        # we don't want to lose anything
        IRLS = Directives.Update_IRLS(f_min_change=1e-3,
                                      minGNiter=1,
                                      beta_tol=1e-1)
        update_Jacobi = Directives.UpdatePreconditioner()
        # Put all the parts together
        inv = Inversion.BaseInversion(
            invProb, directiveList=[betaest, IRLS, update_Jacobi])

        # Run the equivalent source inversion
        mstart = np.ones(nC) * 1e-4
        mrec = inv.run(mstart)

        # Won't store the sensitivity and output 'xyz' data.
        prob.forwardOnly = True
        prob.rx_type = 'xyz'
        prob._G = None
        prob.modelType = 'amplitude'
        prob.model = mrec
        pred = prob.fields(mrec)

        bx = pred[:nD]
        by = pred[nD:2 * nD]
        bz = pred[2 * nD:]

        bAmp = (bx**2. + by**2. + bz**2.)**0.5

        # AMPLITUDE INVERSION
        # Create active map to go from reduce space to full
        actvMap = Maps.InjectActiveCells(self.mesh, actv, -100)
        nC = int(actv.sum())

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

        self.mstart = np.ones(nC) * 1e-4

        # Create the forward model operator
        prob = PF.Magnetics.MagneticIntegral(self.mesh,
                                             chiMap=idenMap,
                                             actInd=actv,
                                             modelType='amplitude',
                                             rx_type='xyz')
        prob.model = self.mstart
        # Change the survey to xyz components
        surveyAmp = PF.BaseMag.LinearSurvey(survey.srcField)

        # Pair the survey and problem
        surveyAmp.pair(prob)
        # Create a regularization function, in this case l2l2
        wr = np.sum(prob.G**2., axis=0)**0.5
        wr /= np.max(wr)
        # Re-set the observations to |B|
        surveyAmp.dobs = bAmp
        surveyAmp.std = wd

        # Create a sparse regularization
        reg = Regularization.Sparse(self.mesh, indActive=actv, mapping=idenMap)
        reg.norms = np.c_[0, 0, 0, 0]
        reg.mref = np.zeros(nC)
        reg.cell_weights = wr
        # Data misfit function
        dmis = DataMisfit.l2_DataMisfit(surveyAmp)
        dmis.W = 1. / surveyAmp.std

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

        invProb = InvProblem.BaseInvProblem(dmis, reg, opt)

        # Here is the list of directives
        betaest = Directives.BetaEstimate_ByEig()

        # Specify the sparse norms
        IRLS = Directives.Update_IRLS(f_min_change=1e-3,
                                      minGNiter=1,
                                      coolingRate=1,
                                      betaSearch=False)

        # The sensitivity weights are update between each iteration.
        update_SensWeight = Directives.UpdateSensitivityWeights()
        update_Jacobi = Directives.UpdatePreconditioner()

        # Put all together
        self.inv = Inversion.BaseInversion(
            invProb,
            directiveList=[betaest, IRLS, update_SensWeight, update_Jacobi])