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 = [0, 1, 1, 1]
        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-3, minGNiter=3)
        update_Jacobi = Directives.UpdatePreconditioner()
        self.inv = Inversion.BaseInversion(
            invProb, directiveList=[IRLS, betaest, update_Jacobi])
Example #2
0
#
## Create a survey and forward data
#rx = DC.Rx.Dipole(rxlocM, rxlocN)
#src = DC.Src.Dipole([rx], srclocA, srclocB)
#survey = DC.Survey([src])

actv = sigma != 1e-8

nC = int(actv.sum())



midLocs = survey.srcList[0].rxList[0].locs[0]+ survey.srcList[0].rxList[0].locs[1]
midLocs /= 2

idenMap = Maps.IdentityMap(nP=nC)
expmap = Maps.ExpMap(mesh)
logmap = Maps.LogMap(mesh)
actmap = Maps.InjectActiveCells(mesh, actv, (1e-8))
mapping = actmap

m0 = np.ones_like(sigma)*mref_val
mref = np.ones_like(sigma)*mref_val

problem = DC.Problem3D_N(mesh, sigmaMap=mapping, storeJ=True)
problem.Solver = PardisoSolver
problem.pair(survey)
mtrue = sigma

# Create data
dobs = survey.makeSyntheticData(mtrue, std=0.02)
def run(plotIt=True):
    """
        1D FDEM and TDEM inversions
        ===========================

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

    """

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        plt.tight_layout(pad=1.5)
Example #4
0
        )
else:
    mesh.writeModelUBC(
          'ActiveSurface.act', activeCells
    )

if "adjust_clearance" in list(input_dict.keys()):

    print("Forming cKDTree for clearance calculations")
    tree = cKDTree(mesh.gridCC[activeCells, :])

# Get the layer of cells directly below topo
nC = int(activeCells.sum())  # Number of active cells

# Create active map to go from reduce set to full
activeCellsMap = Maps.InjectActiveCells(mesh, activeCells, no_data_value)

# Create identity map
if input_dict["inversion_type"] in ['mvi', 'mvis']:
    global_weights = np.zeros(3*nC)
else:
    idenMap = Maps.IdentityMap(nP=nC)
    global_weights = np.zeros(nC)


def createLocalProb(meshLocal, local_survey, global_weights, ind):
    """
        CreateLocalProb(rxLoc, global_weights, lims, ind)

        Generate a problem, calculate/store sensitivities for
        given data points
Example #5
0
 def test_mappingDepreciation(self):
     with self.assertRaises(Exception):
         self.prob.mapping
     with self.assertRaises(Exception):
         self.prob.mapping = Maps.IdentityMap(self.mesh)
Example #6
0
            locA = np.r_[-14. + 2 * (i - 11) + 1., z]
            locB = np.r_[14. - 1., z]
            #M = np.c_[np.arange(locA[0]+1.,12.,2),np.ones(nSrc-i)*z]
            #N = np.c_[np.arange(locA[0]+3.,14.,2),np.ones(nSrc-i)*z]
            M = np.c_[np.arange(-12., 10 + 1, 2), np.ones(12) * z]
            N = np.c_[np.arange(-10., 12 + 1, 2), np.ones(12) * z]
            rx = DC.Rx.Dipole(M, N)
            src = DC.Src.Dipole([rx], locA, locB)
            srclist.append(src)
            #print "line2",locA,locB,"\n",[M,N],"\n"

            #rx = DC.Rx.Dipole(-M,-N)
            #src= DC.Src.Dipole([rx],-locA,-locB)
            #srclist.append(src)

mapping = Maps.ExpMap(mesh)
survey = DC.Survey(srclist)
problem = DC.Problem3D_CC(mesh, sigmaMap=mapping)
problem.pair(survey)
problem.Solver = PardisoSolver
dmis = DataMisfit.l2_DataMisfit(survey)
survey.dpred(mtrue)
survey.makeSyntheticData(mtrue, std=0.05, force=True)
survey.eps = 1e-5 * np.linalg.norm(survey.dobs)

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

import spgl1

#Parameter for SPGL1 iterations
nits = 10
    mstart = np.r_[mUnit,m0]
else:
    mref = np.r_[mUnit*0, m0*0]
    mstart = np.r_[mUnit*0, m0]

#actv = mrho!=-100

# Build list of indecies for the geounits
index = []
for unit in geoUnits:
#    if unit!=0:
    index += [mgeo==unit]
nC = len(index)

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

# Creat reduced identity map
homogMap = Maps.HomogeneousMap(index)
homogMap.P

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

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

#%% Plot obs data
static = np.r_[np.ones(nC, dtype='bool'), np.zeros(len(actv), dtype='bool')]
dynamic = np.r_[np.zeros(nC, dtype='bool'), np.ones(len(actv), dtype='bool')]
def run(plotIt=True, saveFig=False, cleanup=True):
    """
    Run 1D inversions for a single sounding of the RESOLVE and SkyTEM
    bookpurnong data

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    plt.tight_layout()

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

    if plotIt:
        plt.show()

    if cleanup:
        print( os.path.split(directory)[:-1])
        os.remove(
            os.path.sep.join(
                directory.split()[:-1] + ["._bookpurnong_inversion"]
            )
        )
        os.remove(downloads)
        shutil.rmtree(directory)
Example #9
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
        Utils.PlotUtils.plot2Ddata(rxLoc, d)

        # %%
        # 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$)')
geoUnits = np.unique(mgeo).tolist()

# Build a dictionary for the units
mstart = np.asarray([np.median(m0[mgeo == unit]) for unit in geoUnits])

#actv = mrho!=-100

# Build list of indecies for the geounits
index = []
for unit in geoUnits:
    #    if unit!=0:
    index += [mgeo == unit]
nC = len(index)

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

# Creat reduced identity map
homogMap = Maps.HomogeneousMap(index)

#ndata = survey.srcField.rxList[0].locs.shape[0]
#
#actv = driver.activeCells
#nC = len(actv)

# Create static map
#static = driver.staticCells
#dynamic = driver.dynamicCells
#
#staticCells = Maps.InjectActiveCells(None, dynamic, driver.m0[static], nC=nC)
Example #11
0
class MyPropMap(Maps.PropMap):
    sigma = Maps.Property("Electrical Conductivity", defaultInvProp=True)
    mu = Maps.Property("Mu", defaultVal=mu_0)
Example #12
0
# Get cells inside the sphere
sph_ind = PF.MagAnalytics.spheremodel(mesh, 0., 0., 0., rad)

# Adjust susceptibility for volume difference
Vratio = (4. / 3. * np.pi * rad**3.) / (np.sum(sph_ind) * cs**3.)
model = np.ones(mesh.nC) * 1e-8
model[sph_ind] = 0.01

rxLoc = np.asarray([np.r_[0, 0, 4.]])

bzi = FDEM.Rx.Point_bSecondary(rxLoc, 'z', 'real')
bzr = FDEM.Rx.Point_bSecondary(rxLoc, 'z', 'imag')

freqs = [400]  #np.logspace(2, 3, 5)
srcLoc = np.r_[0, 0, 4.]

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

mapping = Maps.IdentityMap(mesh)
surveyFD = FDEM.Survey(srcList)
prbFD = FDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=PardisoSolver)
prbFD.pair(surveyFD)
std = 0.03
surveyFD.makeSyntheticData(model, std)

#Mesh.TensorMesh.writeUBC(mesh,'MeshGrav.msh')
#Mesh.TensorMesh.writeModelUBC(mesh,'MeshGrav.den',model)
#PF.Gravity.writeUBCobs("Obs.grv",survey,d)
Example #13
0
survey = driver.survey

# %% STEP 1: EQUIVALENT SOURCE LAYER
# The first step inverts for an equiavlent source layer in order to convert the
# observed TMI data to magnetic field Amplitude.

# Get the active cells for equivalent source is the top only
active = driver.activeCells
surf = PF.MagneticsDriver.actIndFull2layer(mesh, active)

# Get the layer of cells directyl below topo
#surf = Utils.actIndFull2layer(mesh, active)
nC = len(surf)  # Number of active cells

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

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

# Create static map
prob = PF.Magnetics.MagneticIntegral(mesh,
                                     chiMap=idenMap,
                                     actInd=surf,
                                     equiSourceLayer=True)
prob.solverOpts['accuracyTol'] = 1e-4

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

# Create a regularization function, in this case l2l2
Example #14
0
def run(plotIt=True):
    """
        EM: FDEM: 1D: Inversion
        =======================

        Here we will create and run a FDEM 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')

    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 #15
0
def halfSpaceProblemAnaDiff(meshType,
                            srctype="MagDipole",
                            sig_half=1e-2,
                            rxOffset=50.,
                            bounds=None,
                            plotIt=False):
    if bounds is None:
        bounds = [1e-5, 1e-3]
    if meshType == 'CYL':
        cs, ncx, ncz, npad = 5., 30, 10, 15
        hx = [(cs, ncx), (cs, npad, 1.3)]
        hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)]
        mesh = Mesh.CylMesh([hx, 1, hz], '00C')

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

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

    rx = EM.TDEM.Rx(np.array([[rxOffset, 0., 0.]]), np.logspace(-5, -4, 21),
                    'bz')

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

    survey = EM.TDEM.Survey([src])
    prb = EM.TDEM.Problem3D_b(mesh, sigmaMap=mapping)
    prb.Solver = Solver

    prb.timeSteps = [(1e-06, 40), (5e-06, 40), (1e-05, 40), (5e-05, 40),
                     (0.0001, 40), (0.0005, 40)]

    sigma = np.ones(mesh.nCz) * 1e-8
    sigma[active] = sig_half
    sigma = np.log(sigma[active])
    prb.pair(survey)
    if srctype == "MagDipole":
        bz_ana = mu_0 * EM.Analytics.hzAnalyticDipoleT(rx.locs[0][0] + 1e-3,
                                                       rx.times, sig_half)
    elif srctype == "CircularLoop":
        bz_ana = mu_0 * EM.Analytics.hzAnalyticDipoleT(13, rx.times, sig_half)

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

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

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

    return log10diff
Example #16
0
# mesh
csx, ncx, npadx = 25., 16, 10
csz, ncz, npadz = 25., 8, 10
pf = 1.5

# primary mesh
hx = [(csx, ncx), (csx, npadx, pf)]
hz = [(csz, npadz, -pf), (csz, ncz), (csz, npadz, pf)]
meshp = Mesh.CylMesh([hx, 1., hz], x0='0CC')

# secondary mesh
h = [(csz, npadz - 4, -pf), (csz, ncz), (csz, npadz - 4, pf)]
meshs = Mesh.TensorMesh(3 * [h], x0='CCC')

# mappings
primaryMapping = (Maps.ExpMap(meshp) * Maps.SurjectFull(meshp) *
                  Maps.Projection(nP=8, index=[0]))

mapping = (
    Maps.ExpMap(meshs) * Maps.ParametrizedBlockInLayer(meshs) *
    Maps.Projection(nP=8, index=np.hstack([np.r_[0], np.arange(0, 8)])))

primaryMap2Meshs = (Maps.ExpMap(meshs) * Maps.SurjectFull(meshs) *
                    Maps.Projection(nP=8, index=[0]))


class PrimSecFDEMTest(object):

    # --------------------- Run some tests! --------------------- #
    def DataTest(self):
        print('\nTesting Data')
Example #17
0
                                    orientation="z",
                                    radius=100,
                                    waveform=quarter_sine)

src_list_magnetostatic = [src_magnetostatic]
src_list_ramp_on = [src_ramp_on]

###############################################################################
# Create the simulations
# ----------------------
#
# To simulate magnetic flux data, we use the b-formulation of Maxwell's
# equations

prob_magnetostatic = TDEM.Problem3D_b(mesh=mesh,
                                      sigmaMap=Maps.IdentityMap(mesh),
                                      timeSteps=ramp,
                                      Solver=Pardiso)
prob_ramp_on = TDEM.Problem3D_b(mesh=mesh,
                                sigmaMap=Maps.IdentityMap(mesh),
                                timeSteps=ramp,
                                Solver=Pardiso)

survey_magnetostatic = TDEM.Survey(srcList=src_list_magnetostatic)
survey_ramp_on = TDEM.Survey(src_list_ramp_on)

prob_magnetostatic.pair(survey_magnetostatic)
prob_ramp_on.pair(survey_ramp_on)

###############################################################################
# Run the long on-time simulation
Example #18
0
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
    )
    # 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)

    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 #19
0
import matplotlib.pyplot as plt
from pymatsolver import PardisoSolver
from SimPEG import Maps

cs, ncx, ncy, ncz, = 50., 20, 1, 20
npad_x, npad_y, npad_z = 10, 10, 10
pad_rate = 1.3
hx = [(cs,npad_x,-pad_rate), (cs,ncx), (cs,npad_x,pad_rate)]
hy = [(cs,npad_y,-pad_rate), (cs,ncy), (cs,npad_y,pad_rate)]
hz = [(cs,npad_z,-pad_rate), (cs,ncz), (cs,npad_z,pad_rate)]
mesh_3d = Mesh.TensorMesh([hx,hy,hz], 'CCC')
mesh_2d = Mesh.TensorMesh([hx,hz], 'CC')
inds = mesh_2d.vectorCCy<0.
mesh_2d_inv = Mesh.TensorMesh([hx,mesh_2d.hy[inds]], 'CN')
actind = mesh_2d.gridCC[:,1]<0.
map_2Dto3D = Maps.Surject2Dto3D(mesh_3d)
parametric_block = Maps.ParametricBlock(mesh_2d_inv) #, slopeFact=1
expmap = Maps.ExpMap(mesh_2d)
actmap = Maps.InjectActiveCells(mesh_2d, indActive=actind, valInactive=np.log(1e-8))
mapping = map_2Dto3D* expmap * actmap *  parametric_block

x = mesh_3d.vectorCCx[np.logical_and(mesh_3d.vectorCCx>-450, mesh_3d.vectorCCx<450)]
time = np.logspace(np.log10(5e-5), np.log10(2.5e-3), 21)
srcList = []
ind_start=0
for xloc in x:
    location = np.array([[xloc, 0., 30.]])
    rx_z = EM.TDEM.Rx.Point_dbdt(location, time[ind_start:], 'z')
    rx_x = EM.TDEM.Rx.Point_dbdt(location, time[ind_start:], 'x')
    src = EM.TDEM.Src.CircularLoop([rx_z], orientation='z', loc=location)
    srcList.append(src)
Example #20
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 #21
0
locx = [int(mesh.nCx / 2)]  #[int(mesh.nCx/2)-3, int(mesh.nCx/2)+3]
midy = int(mesh.nCy / 2)
midz = -5

# Lets create a simple flat topo and set the active cells
[xx, yy] = np.meshgrid(mesh.vectorNx, mesh.vectorNy)
zz = np.ones_like(xx) * mesh.vectorNz[-1]
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 = int(len(actv))

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

# Move the observation points 5m above the topo
Z = np.ones_like(X) * mesh.vectorNz[-1] + dx

# 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=(B[0], B[1], B[2]))
survey = PF.BaseMag.LinearSurvey(srcField)
Example #22
0
hxind = [(cs,10,1.3),(cs, 21),(cs,10,1.3)]
hyind = [(cs,10,1.3),(cs, 21),(cs,10,1.3)]
hzind = [(cs,10,1.3),(cs, 21),(cs,10,1.3)]
mesh = Mesh.TensorMesh([hxind, hyind, hzind], 'CCC')

# Get cells inside the sphere
sph_ind = PF.MagAnalytics.spheremodel(mesh, 0., 0., 0., rad)

# Adjust susceptibility for volume difference
Vratio = (4./3.*np.pi*rad**3.) / (np.sum(sph_ind)*cs**3.)
model = np.zeros(mesh.nC)
model[sph_ind] = chi*Vratio
m = model[sph_ind]

# Creat reduced identity map for Linear Pproblem
idenMap = Maps.IdentityMap(nP=int(sum(sph_ind)))

# Create plane of observations
xr = np.linspace(-10, 10, 21)
yr = np.linspace(-10, 10, 21)
X, Y = np.meshgrid(xr, yr)

# Move obs plane 2 radius away from sphere
Z = np.ones((xr.size, yr.size))*2.*rad
locXyz = np.c_[Utils.mkvc(X), Utils.mkvc(Y), Utils.mkvc(Z)]
rxLoc = PF.BaseMag.RxObs(locXyz)
srcField = PF.BaseMag.SrcField([rxLoc], param=H0)
survey = PF.BaseMag.LinearSurvey(srcField)

prob_xyz = PF.Magnetics.MagneticIntegral(mesh, chiMap=idenMap,
                                              actInd=sph_ind,
Example #23
0
def createLocalProb(meshLocal, local_survey, global_weights, ind):
    """
        CreateLocalProb(rxLoc, global_weights, lims, ind)

        Generate a problem, calculate/store sensitivities for
        given data points
    """

    # Need to find a way to compute sensitivities only for intersecting cells
    activeCells_t = np.ones(meshLocal.nC, dtype='bool')  # meshUtils.modelutils.activeTopoLayer(meshLocal, topo)

    # Create reduced identity map
    if input_dict["inversion_type"] in ['mvi', 'mvis']:
        nBlock = 3
    else:
        nBlock = 1

    tileMap = Maps.Tile((mesh, activeCells), (meshLocal, activeCells_t), nBlock=nBlock)

    activeCells_t = tileMap.activeLocal

    if "adjust_clearance" in list(input_dict.keys()):

        print("Setting Z values of data to respect clearance height")

        _, c_ind = tree.query(local_survey.rxLoc)
        dz = input_dict["adjust_clearance"]

        z = mesh.gridCC[activeCells, 2][c_ind] + mesh.h_gridded[activeCells, 2][c_ind]/2 + dz
        local_survey.srcField.rxList[0].locs[:, 2] = z

    if input_dict["inversion_type"] == 'grav':
        prob = PF.Gravity.GravityIntegral(
            meshLocal, rhoMap=tileMap, actInd=activeCells_t,
            parallelized=parallelized,
            Jpath=outDir + "Tile" + str(ind) + ".zarr",
            maxRAM=max_ram,
            n_cpu=n_cpu,
            max_chunk_size=max_chunk_size
            )

    elif input_dict["inversion_type"] == 'mag':
        prob = PF.Magnetics.MagneticIntegral(
            meshLocal, chiMap=tileMap, actInd=activeCells_t,
            parallelized=parallelized,
            Jpath=outDir + "Tile" + str(ind) + ".zarr",
            maxRAM=max_ram,
            n_cpu=n_cpu,
            max_chunk_size=max_chunk_size
            )

    elif input_dict["inversion_type"] in ['mvi', 'mvis']:
        prob = PF.Magnetics.MagneticIntegral(
            meshLocal, chiMap=tileMap, actInd=activeCells_t,
            parallelized=parallelized,
            Jpath=outDir + "Tile" + str(ind) + ".zarr",
            maxRAM=max_ram,
            modelType='vector',
            n_cpu=n_cpu,
            max_chunk_size=max_chunk_size
        )

    local_survey.pair(prob)

    # Data misfit function
    local_misfit = DataMisfit.l2_DataMisfit(local_survey)
    local_misfit.W = 1./local_survey.std

    wr = prob.getJtJdiag(np.ones(tileMap.shape[1]), W=local_misfit.W)

    activeCellsTemp = Maps.InjectActiveCells(mesh, activeCells, 1e-8)

    global_weights += wr

    del meshLocal

    if output_tile_files:
        if input_dict["inversion_type"] == 'grav':

            Utils.io_utils.writeUBCgravityObservations(outDir + 'Survey_Tile' + str(ind) +'.dat', local_survey, local_survey.dobs)

        elif input_dict["inversion_type"] == 'mag':

            Utils.io_utils.writeUBCmagneticsObservations(outDir + 'Survey_Tile' + str(ind) +'.dat', local_survey, local_survey.dobs)

        Mesh.TreeMesh.writeUBC(
          mesh, outDir + 'Octree_Tile' + str(ind) + '.msh',
          models={outDir + 'JtJ_Tile' + str(ind) + ' .act': activeCellsTemp*wr[:nC]}
        )

    return local_misfit, global_weights
Example #24
0
# Compute active cells
activeCells = Utils.surface2ind_topo(mesh, topo)

#    activeCells = Utils.modelutils.activeTopoLayer(mesh, topo)

Mesh.TreeMesh.writeUBC(
    mesh,
    workDir + dsep + outDir + 'OctreeMeshGlobal.msh',
    models={workDir + dsep + outDir + 'ActiveSurface.act': activeCells})

# Get the layer of cells directly below topo
#activeCells = Utils.actIndFull2layer(mesh, active)
nC = int(activeCells.sum())  # Number of active cells
print(nC)
# Create active map to go from reduce set to full
activeCellsMap = Maps.InjectActiveCells(mesh, activeCells, ndv)

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

if tileProblem:

    # Loop over different tile size and break problem until
    # memory footprint false below maxRAM
    usedRAM = np.inf
    count = 1
    while usedRAM > maxRAM:
        print("Tiling:" + str(count))

        tiles, binCount = Utils.modelutils.tileSurveyPoints(rxLoc, count)
def run(runIt=False, plotIt=True, saveIt=False, saveFig=False, cleanup=True):
    """
    Run the bookpurnong 1D stitched RESOLVE inversions.

    :param bool runIt: re-run the inversions? Default downloads and plots saved results
    :param bool plotIt: show the plots?
    :param bool saveIt: save the re-inverted results?
    :param bool saveFig: save the figure
    :param bool cleanup: remove the downloaded results
    """

    # download the data
    downloads, directory = download_and_unzip_data()

    # Load resolve data
    resolve = h5py.File(os.path.sep.join([directory, "booky_resolve.hdf5"]),
                        "r")

    river_path = resolve["river_path"].value  # River path
    nSounding = resolve["data"].shape[0]  # the # of soundings

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

    # fetch the frequencies we are considering
    cpi_inds = [0, 2, 6, 8, 10]  # Indices for HCP in-phase
    cpq_inds = [1, 3, 7, 9, 11]  # Indices for HCP quadrature
    frequency_cp = resolve["frequency_cp"].value

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

    # survey parameters
    rxOffset = 7.86  # tx-rx separation
    bp = -mu_0 / (4 * np.pi * rxOffset**3)  # primary magnetic field

    # re-run the inversion
    if runIt:

        # set up the mappings - we are inverting for 1D log conductivity
        # below the earth's surface.
        actMap = Maps.InjectActiveCells(mesh,
                                        active,
                                        np.log(1e-8),
                                        nC=mesh.nCz)
        mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap

        # build starting and reference model
        sig_half = 1e-1
        sig_air = 1e-8
        sigma = np.ones(mesh.nCz) * sig_air
        sigma[active] = sig_half
        m0 = np.log(1e-1) * np.ones(active.sum())  # starting model
        mref = np.log(1e-1) * np.ones(active.sum())  # reference model

        # initalize empty lists for storing inversion results
        mopt_re = []  # recovered model
        dpred_re = []  # predicted data
        dobs_re = []  # observed data

        # downsample the data for the inversion
        nskip = 40

        # set up a noise model
        # 10% for the 3 lowest frequencies, 15% for the two highest
        std = np.repeat(np.r_[np.ones(3) * 0.1, np.ones(2) * 0.15], 2)
        floor = abs(20 * bp * 1e-6)  # floor of 20ppm

        # loop over the soundings and invert each
        for rxind in range(nSounding):

            # convert data from ppm to magnetic field (A/m^2)
            dobs = np.c_[resolve["data"][rxind, :][cpi_inds].astype(float),
                         resolve["data"][rxind, :][cpq_inds].
                         astype(float)].flatten() * bp * 1e-6

            # perform the inversion
            src_height = b_height_resolve[rxind].astype(float)
            mopt, dpred, dobs = resolve_1Dinversions(mesh,
                                                     dobs,
                                                     src_height,
                                                     frequency_cp,
                                                     m0,
                                                     mref,
                                                     mapping,
                                                     std=std,
                                                     floor=floor)

            # add results to our list
            mopt_re.append(mopt)
            dpred_re.append(dpred)
            dobs_re.append(dobs)

        # save results
        mopt_re = np.vstack(mopt_re)
        dpred_re = np.vstack(dpred_re)
        dobs_re = np.vstack(dobs_re)

        if saveIt:
            np.save("mopt_re_final", mopt_re)
            np.save("dobs_re_final", dobs_re)
            np.save("dpred_re_final", dpred_re)

    mopt_re = resolve["mopt"].value
    dobs_re = resolve["dobs"].value
    dpred_re = resolve["dpred"].value

    sigma = np.exp(mopt_re)
    indz = -7  # depth index

    # so that we can visually compare with literature (eg Viezzoli, 2010)
    cmap = "jet"

    # dummy figure for colobar
    fig = plt.figure()
    out = plt.scatter(np.ones(3),
                      np.ones(3),
                      c=np.linspace(-2, 1, 3),
                      cmap=cmap)
    plt.close(fig)

    # plot from the paper
    fs = 13  # fontsize
    # matplotlib.rcParams['font.size'] = fs
    plt.figure(figsize=(13, 7))
    ax0 = plt.subplot2grid((2, 3), (0, 0), rowspan=2, colspan=2)
    ax1 = plt.subplot2grid((2, 3), (0, 2))
    ax2 = plt.subplot2grid((2, 3), (1, 2))

    # titles of plots
    title = [("(a) Recovered model, %.1f m depth") %
             (-mesh.vectorCCz[active][indz]), "(b) Obs (Real 400 Hz)",
             "(c) Pred (Real 400 Hz)"]

    temp = sigma[:, indz]
    tree = cKDTree(list(zip(resolve["xy"][:, 0], resolve["xy"][:, 1])))
    d, d_inds = tree.query(list(zip(resolve["xy"][:, 0], resolve["xy"][:, 1])),
                           k=20)
    w = 1. / (d + 100.)**2.
    w = Utils.sdiag(1. / np.sum(w, axis=1)) * (w)
    xy = resolve["xy"]
    temp = (temp.flatten()[d_inds] * w).sum(axis=1)
    Utils.plot2Ddata(xy,
                     temp,
                     ncontour=100,
                     scale="log",
                     dataloc=False,
                     contourOpts={
                         "cmap": cmap,
                         "vmin": -2,
                         "vmax": 1.
                     },
                     ax=ax0)
    ax0.plot(resolve["xy"][:, 0], resolve["xy"][:, 1], 'k.', alpha=0.02, ms=1)

    cb = plt.colorbar(out,
                      ax=ax0,
                      ticks=np.linspace(-2, 1, 4),
                      format="$10^{%.1f}$")
    cb.set_ticklabels(["0.01", "0.1", "1", "10"])
    cb.set_label("Conductivity (S/m)")
    ax0.plot(river_path[:, 0], river_path[:, 1], 'k-', lw=0.5)

    # plot observed and predicted data
    freq_ind = 0
    axs = [ax1, ax2]
    temp_dobs = dobs_re[:, freq_ind].copy()
    ax1.plot(river_path[:, 0], river_path[:, 1], 'k-', lw=0.5)
    out = Utils.plot2Ddata(resolve["xy"].value,
                           temp_dobs / abs(bp) * 1e6,
                           ncontour=100,
                           scale="log",
                           dataloc=False,
                           ax=ax1,
                           contourOpts={"cmap": "viridis"})
    vmin, vmax = out[0].get_clim()
    cb = plt.colorbar(out[0],
                      ticks=np.linspace(vmin, vmax, 3),
                      ax=ax1,
                      format="%.1e",
                      fraction=0.046,
                      pad=0.04)
    cb.set_label("Bz (ppm)")
    temp_dpred = dpred_re[:, freq_ind].copy()
    # temp_dpred[mask_:_data] = np.nan
    ax2.plot(river_path[:, 0], river_path[:, 1], 'k-', lw=0.5)
    Utils.plot2Ddata(resolve["xy"].value,
                     temp_dpred / abs(bp) * 1e6,
                     ncontour=100,
                     scale="log",
                     dataloc=False,
                     contourOpts={
                         "vmin": vmin,
                         "vmax": vmax,
                         "cmap": "viridis"
                     },
                     ax=ax2)
    cb = plt.colorbar(out[0],
                      ticks=np.linspace(vmin, vmax, 3),
                      ax=ax2,
                      format="%.1e",
                      fraction=0.046,
                      pad=0.04)
    cb.set_label("Bz (ppm)")

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

        ax.set_aspect("equal")
        ax.plot(resolve["xy"][:, 0],
                resolve["xy"][:, 1],
                'k.',
                alpha=0.02,
                ms=1)

        ax.set_yticklabels([str(f) for f in yticks])
        ax.set_ylabel("Northing (m)")
        ax.set_xlabel("Easting (m)")
        ax.set_title(title[i])

    plt.tight_layout()

    if plotIt:
        plt.show()

    if saveFig is True:
        fig.savefig("obspred_resolve.png", dpi=200)

    if cleanup:
        os.remove(downloads)
        shutil.rmtree(directory)
Example #26
0
    def createLocalProb(rxLoc, wrGlobal, lims, ind):
        # createLocalProb(rxLoc, wrGlobal, lims, ind)
        # Generate a problem, calculate/store sensitivities for
        # given data points

        # Grab the data for current tile
        ind_t = np.all([
            rxLoc[:, 0] >= lims[0], rxLoc[:, 0] <= lims[1],
            rxLoc[:, 1] >= lims[2], rxLoc[:, 1] <= lims[3], surveyMask
        ],
                       axis=0)

        # Remember selected data in case of tile overlap
        surveyMask[ind_t] = False

        # Create new survey
        if driver["dataFile"][0] == 'GRAV':
            rxLoc_t = PF.BaseGrav.RxObs(rxLoc[ind_t, :])
            srcField = PF.BaseGrav.SrcField([rxLoc_t])
            survey_t = PF.BaseGrav.LinearSurvey(srcField)
            survey_t.dobs = survey.dobs[ind_t]
            survey_t.std = survey.std[ind_t]
            survey_t.ind = ind_t

            Utils.io_utils.writeUBCgravityObservations(
                workDir + dsep + outDir + "Tile" + str(ind) + '.dat', survey_t,
                survey_t.dobs)

        elif driver["dataFile"][0] == 'MAG':
            rxLoc_t = PF.BaseMag.RxObs(rxLoc[ind_t, :])
            srcField = PF.BaseMag.SrcField([rxLoc_t],
                                           param=survey.srcField.param)
            survey_t = PF.BaseMag.LinearSurvey(srcField)
            survey_t.dobs = survey.dobs[ind_t]
            survey_t.std = survey.std[ind_t]
            survey_t.ind = ind_t

            Utils.io_utils.writeUBCmagneticsObservations(
                workDir + dsep + outDir + "Tile" + str(ind) + '.dat', survey_t,
                survey_t.dobs)

        meshLocal = Utils.modelutils.meshBuilder(newTopo,
                                                 h,
                                                 padDist,
                                                 meshType='TREE',
                                                 meshGlobal=meshInput,
                                                 verticalAlignment='center')

        if topo is not None:
            meshLocal = Utils.modelutils.refineTree(meshLocal,
                                                    topo,
                                                    dtype='surface',
                                                    octreeLevels=octreeTopo,
                                                    finalize=False)

        # Refine the mesh around loc
        meshLocal = Utils.modelutils.refineTree(
            meshLocal,
            newTopo[ind_t, :],
            dtype='surface',
            octreeLevels=octreeObs,
            octreeLevels_XY=octreeLevels_XY,
            finalize=True)

        # Need to find a way to compute sensitivities only for intersecting cells
        activeCells_t = np.ones(
            meshLocal.nC, dtype='bool'
        )  # meshUtils.modelutils.activeTopoLayer(meshLocal, topo)

        # Create reduced identity map
        tileMap = Maps.Tile((mesh, activeCells), (meshLocal, activeCells_t))

        activeCells_t = tileMap.activeLocal

        print(activeCells_t.sum(), meshLocal.nC)
        if driver["dataFile"][0] == 'GRAV':
            prob = PF.Gravity.GravityIntegral(meshLocal,
                                              rhoMap=tileMap,
                                              actInd=activeCells_t,
                                              parallelized=parallelized,
                                              Jpath=workDir + dsep + outDir +
                                              "Tile" + str(ind) + ".zarr",
                                              maxRAM=maxRAM / n_cpu,
                                              n_cpu=n_cpu,
                                              n_chunks=n_chunks)

        elif driver["dataFile"][0] == 'MAG':
            prob = PF.Magnetics.MagneticIntegral(
                meshLocal,
                chiMap=tileMap,
                actInd=activeCells_t,
                parallelized=parallelized,
                Jpath=workDir + dsep + outDir + "Tile" + str(ind) + ".zarr",
                maxRAM=maxRAM / n_cpu,
                n_cpu=n_cpu,
                n_chunks=n_chunks)

        survey_t.pair(prob)

        # Write out local active and obs for validation
        Mesh.TreeMesh.writeUBC(
            meshLocal,
            workDir + dsep + outDir + dsep + 'Octree_Tile' + str(ind) + '.msh',
            models={
                workDir + dsep + outDir + dsep + 'ActiveGlobal_Tile' + str(ind) + ' .act':
                activeCells_t
            })

        if driver["dataFile"][0] == 'GRAV':

            Utils.io_utils.writeUBCgravityObservations(
                workDir + dsep + outDir + dsep + 'Tile' + str(ind) + '.dat',
                survey_t, survey_t.dobs)

        elif driver["dataFile"][0] == 'MAG':

            Utils.io_utils.writeUBCmagneticsObservations(
                workDir + dsep + outDir + dsep + 'Tile' + str(ind) + '.dat',
                survey_t, survey_t.dobs)

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

        wr = prob.getJtJdiag(np.ones(tileMap.P.shape[1]), W=dmis.W)

        wrGlobal += wr

        del meshLocal

        # Create combo misfit function
        return dmis
Example #27
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 #28
0
def run(plotIt=True):

    # Set up cylindrically symmetric mesh
    cs, ncx, ncz, npad = 10., 15, 25, 13  # padded cylindrical 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

    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(("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)

        plt.tight_layout(pad=1.5)
    def setUp(self):

        ndv = -100
        # Create a self.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)]

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

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

        # Lets create a simple Gaussian topo and set the active cells
        [xx, yy] = np.meshgrid(self.mesh.vectorNx, self.mesh.vectorNy)
        zz = -np.exp((xx**2 + yy**2) / 75**2) + self.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(self.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
        self.actvMap = Maps.InjectActiveCells(self.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) + self.mesh.vectorNz[-1] + 5.

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

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

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

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

        # Create the forward model operator
        prob = PF.Gravity.GravityIntegral(self.mesh,
                                          rhoMap=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)) * 0.001
        wd = np.ones(len(data)) * .001

        survey.dobs = data
        survey.std = wd

        # PF.Gravity.plot_obs_2D(survey.srcField.rxList[0].locs, d=data)

        # Create sensitivity weights from our linear forward operator
        wr = PF.Magnetics.get_dist_wgt(self.mesh, locXYZ, actv, 2., 2.)
        wr = wr**2.

        # Create a regularization
        reg = Regularization.Sparse(self.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 = 5e-2, 1e-2

        # Data misfit function
        dmis = DataMisfit.l2_DataMisfit(survey)
        dmis.W = 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, beta=1e+8)

        # Here is where the norms are applied
        IRLS = Directives.Update_IRLS(f_min_change=1e-4, minGNiter=1)
        update_Jacobi = Directives.UpdatePreconditioner(mapping=idenMap)

        self.inv = Inversion.BaseInversion(invProb,
                                           directiveList=[IRLS, update_Jacobi])
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=1e-2)

    # 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 = [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(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(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, invProb.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