Пример #1
0
    def test_haverkamp_k_m(self):

        mesh = discretize.TensorMesh([5])
        expmap = maps.IdentityMap(nP=mesh.nC)
        wires2 = maps.Wires(("one", mesh.nC), ("two", mesh.nC))
        wires3 = maps.Wires(("one", mesh.nC), ("two", mesh.nC),
                            ("three", mesh.nC))

        opts = [
            ("Ks", dict(KsMap=expmap), 1),
            ("A", dict(AMap=expmap), 1),
            ("gamma", dict(gammaMap=expmap), 1),
            ("Ks-A", dict(KsMap=expmap * wires2.one,
                          AMap=expmap * wires2.two), 2),
            (
                "Ks-gamma",
                dict(KsMap=expmap * wires2.one, gammaMap=expmap * wires2.two),
                2,
            ),
            (
                "A-gamma",
                dict(AMap=expmap * wires2.one, gammaMap=expmap * wires2.two),
                2,
            ),
            (
                "Ks-A-gamma",
                dict(
                    KsMap=expmap * wires3.one,
                    AMap=expmap * wires3.two,
                    gammaMap=expmap * wires3.three,
                ),
                3,
            ),
        ]

        u = np.random.randn(mesh.nC)

        for name, opt, nM in opts:
            np.random.seed(2)
            hav = richards.empirical.Haverkamp_k(mesh, **opt)

            def fun(m):
                hav.model = m
                return hav(u), hav.derivM(u)

            print("Haverkamp_k test m deriv:  ", name)

            passed = checkDerivative(fun,
                                     np.random.randn(mesh.nC * nM),
                                     plotIt=False)
            self.assertTrue(passed, True)
Пример #2
0
    def test_Maps(self):
        nP = 10
        m = np.random.rand(2 * nP)

        wires = maps.Wires(("sigma", nP), ("mu", nP))

        objfct1 = objective_function.L2ObjectiveFunction(mapping=wires.sigma)
        objfct2 = objective_function.L2ObjectiveFunction(mapping=wires.mu)

        objfct3 = objfct1 + objfct2

        objfct4 = objective_function.L2ObjectiveFunction(nP=nP)

        self.assertTrue(objfct1.nP == 2 * nP)
        self.assertTrue(objfct2.nP == 2 * nP)
        self.assertTrue(objfct3.nP == 2 * nP)

        # print(objfct1.nP, objfct4.nP, objfct4.W.shape, objfct1.W.shape, m[:nP].shape)
        self.assertTrue(objfct1(m) == objfct4(m[:nP]))
        self.assertTrue(objfct2(m) == objfct4(m[nP:]))

        self.assertTrue(objfct3(m) == objfct1(m) + objfct2(m))

        objfct1.test()
        objfct2.test()
        objfct3.test()
Пример #3
0
    def setUp(self):

        dh = 1.0
        nx = 16
        ny = 16
        nz = 16

        hx = [(dh, nx)]
        hy = [(dh, ny)]
        hz = [(dh, nz)]
        mesh = TreeMesh([hx, hy, hz], "CNN")
        mesh.insert_cells([5, 5, 5], [4])

        # reg
        actv = np.ones(len(mesh), dtype=bool)

        # maps
        wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC))

        cross_grad = regularization.CrossGradient(mesh,
                                                  wire_map=wires,
                                                  indActive=actv)

        self.mesh = mesh
        self.cross_grad = cross_grad
Пример #4
0
    def setUp(self):

        dh = 1.0
        nx = 12
        ny = 12
        nz = 12

        hx = [(dh, nx)]
        hy = [(dh, ny)]
        hz = [(dh, nz)]
        mesh = TensorMesh([hx, hy, hz], "CNN")

        # reg
        actv = np.ones(len(mesh), dtype=bool)

        # maps
        wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC))

        cros_grad = regularization.CrossGradient(
            mesh,
            wire_map=wires,
            indActive=actv,
        )

        self.mesh = mesh
        self.cross_grad = cros_grad
Пример #5
0
    def setUp(self):

        dh = 1.0
        nx = 12
        ny = 12
        nz = 12

        hx = [(dh, nx)]
        hy = [(dh, ny)]
        hz = [(dh, nz)]
        mesh = TensorMesh([hx, hy, hz], "CNN")

        # reg
        actv = np.ones(len(mesh), dtype=bool)

        # maps
        wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC))

        jtv = regularization.JointTotalVariation(
            mesh,
            wire_map=wires,
            indActive=actv,
        )

        self.mesh = mesh
        self.jtv = jtv
        self.x0 = np.random.rand(len(mesh) * 2)
Пример #6
0
def spectral_ip_mappings(
    mesh,
    indActive=None,
    inactive_eta=1e-4,
    inactive_tau=1e-4,
    inactive_c=1e-4,
    is_log_eta=True,
    is_log_tau=True,
    is_log_c=True,
):
    """
    Generates Mappings for Spectral Induced Polarization Simulation.
    Three parameters are required to be input:
    Chargeability (eta), Time constant (tau), and Frequency dependency (c).
    If there is no topography (indActive is None),
    model (m) can be either set to

    m = np.r_[log(eta), log(tau), log(c)] or m = np.r_[eta, tau, c]

    When indActive is not None, m is

    m = np.r_[log(eta[indAcitve]), log(tau[indAcitve]), log(c[indAcitve])] or
    m = np.r_[eta[indAcitve], tau[indAcitve], c[indAcitve]] or

    TODO: Illustrate input and output variables
    """

    if indActive is None:
        indActive = np.ones(mesh.nC, dtype=bool)

    actmap_eta = maps.InjectActiveCells(
        mesh, indActive=indActive, valInactive=inactive_eta
    )
    actmap_tau = maps.InjectActiveCells(
        mesh, indActive=indActive, valInactive=inactive_tau
    )
    actmap_c = maps.InjectActiveCells(mesh, indActive=indActive, valInactive=inactive_c)

    wires = maps.Wires(
        ("eta", indActive.sum()), ("tau", indActive.sum()), ("c", indActive.sum())
    )

    if is_log_eta:
        eta_map = actmap_eta * maps.ExpMap(nP=actmap_eta.nP) * wires.eta
    else:
        eta_map = actmap_eta * wires.eta

    if is_log_tau:
        tau_map = actmap_tau * maps.ExpMap(nP=actmap_tau.nP) * wires.tau
    else:
        tau_map = actmap_tau * wires.tau

    if is_log_c:
        c_map = actmap_c * maps.ExpMap(nP=actmap_c.nP) * wires.c
    else:
        c_map = actmap_c * wires.c

    return eta_map, tau_map, c_map, wires
Пример #7
0
    def test_basic(self):
        mesh = discretize.TensorMesh([10, 10, 10])

        wires = maps.Wires(("sigma", mesh.nCz), ("mu_casing", 1),)

        model = np.arange(mesh.nCz + 1)

        assert isinstance(wires.sigma, maps.Projection)
        assert wires.nP == mesh.nCz + 1

        named_model = wires * model

        named_model.sigma == model[: mesh.nCz]
        assert named_model.mu_casing == 10
Пример #8
0
def model_soundings(h0, h1, rho0, rho1, rho2):
    hz = np.r_[h0, h1]
    rho = np.r_[rho0, rho1, rho2]

    srcList_w = []
    srcList_s = []
    AB2 = np.arange(4, 89, 3) + 0.5
    for i, a in enumerate(AB2):
        a_loc = -a
        b_loc = a
        m_loc_wen = -a + (a * 2) // 3
        n_loc_wen = -m_loc_wen

        m_loc_sch = -1.5
        n_loc_sch = 1.5
        rx_w = DC.Rx.Dipole(np.r_[m_loc_wen, 0, 0], np.r_[n_loc_wen, 0, 0])
        rx_s = DC.Rx.Dipole(np.r_[m_loc_sch, 0, 0], np.r_[n_loc_sch, 0, 0])

        locA = np.r_[a_loc, 0, 0]
        locB = np.r_[b_loc, 0, 0]
        src = DC.Src.Dipole([rx_w], locA, locB)
        srcList_w.append(src)
        src = DC.Src.Dipole([rx_s], locA, locB)
        srcList_s.append(src)

    m = np.r_[rho, hz]

    wires = maps.Wires(('rho', rho.size), ('t', rho.size - 1))
    mapping_rho = maps.IdentityMap(nP=rho.size) * wires.rho
    mapping_t = maps.IdentityMap(nP=hz.size) * wires.t

    survey = DC.Survey(srcList_w)
    simulation = DC.Simulation1DLayers(rhoMap=mapping_rho,
                                       thicknessesMap=mapping_t,
                                       survey=survey,
                                       data_type='apparent_resistivity')
    data_w = simulation.make_synthetic_data(m)

    survey = DC.Survey(srcList_s)
    simulation = DC.Simulation1DLayers(rhoMap=mapping_rho,
                                       thicknessesMap=mapping_t,
                                       survey=survey,
                                       data_type='apparent_resistivity')
    data_s = simulation.make_synthetic_data(m)
    return data_w, data_s
Пример #9
0
    def test_mappings_and_cell_weights(self):
        mesh = discretize.TensorMesh([8, 7, 6])
        m = np.random.rand(2 * mesh.nC)
        v = np.random.rand(2 * mesh.nC)

        cell_weights = np.random.rand(mesh.nC)

        wires = maps.Wires(("sigma", mesh.nC), ("mu", mesh.nC))

        reg = regularization.SimpleSmall(mesh,
                                         mapping=wires.sigma,
                                         cell_weights=cell_weights)

        objfct = objective_function.L2ObjectiveFunction(W=utils.sdiag(
            np.sqrt(cell_weights)),
                                                        mapping=wires.sigma)

        self.assertTrue(reg(m) == objfct(m))
        self.assertTrue(np.all(reg.deriv(m) == objfct.deriv(m)))
        self.assertTrue(np.all(reg.deriv2(m, v=v) == objfct.deriv2(m, v=v)))
Пример #10
0
    def test_mappings(self):
        mesh = discretize.TensorMesh([8, 7, 6])
        m = np.random.rand(2 * mesh.nC)

        wires = maps.Wires(("sigma", mesh.nC), ("mu", mesh.nC))

        for regType in ["Tikhonov", "Sparse", "Simple"]:
            reg1 = getattr(regularization, regType)(mesh, mapping=wires.sigma)
            reg2 = getattr(regularization, regType)(mesh, mapping=wires.mu)

            reg3 = reg1 + reg2

            self.assertTrue(reg1.nP == 2 * mesh.nC)
            self.assertTrue(reg2.nP == 2 * mesh.nC)
            self.assertTrue(reg3.nP == 2 * mesh.nC)

            print(reg3(m), reg1(m), reg2(m))
            self.assertTrue(reg3(m) == reg1(m) + reg2(m))

            reg1.test(eps=TOL)
            reg2.test(eps=TOL)
            reg3.test(eps=TOL)
Пример #11
0
    def setUp(self):

        dh = 1.0
        nx = 12
        ny = 12

        hx = [(dh, nx)]
        hy = [(dh, ny)]
        mesh = TensorMesh([hx, hy], "CN")

        # reg
        actv = np.ones(len(mesh), dtype=bool)

        # maps
        wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC))

        corr = regularization.LinearCorrespondence(
            mesh,
            wire_map=wires,
            indActive=actv,
        )

        self.mesh = mesh
        self.corr = corr
Пример #12
0
    def setUp(self):

        dh = 1.0
        nx = 16
        ny = 16

        hx = [(dh, nx)]
        hy = [(dh, ny)]
        mesh = TreeMesh([hx, hy], "CN")
        mesh.insert_cells([5, 5], [4])

        # reg
        actv = np.ones(len(mesh), dtype=bool)

        # maps
        wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC))

        jtv = regularization.JointTotalVariation(mesh,
                                                 wire_map=wires,
                                                 indActive=actv)

        self.mesh = mesh
        self.jtv = jtv
        self.x0 = np.random.rand(len(mesh) * 2)
Пример #13
0
def run(plotIt=True):

    H0 = (50000.0, 90.0, 0.0)

    # Create a mesh
    dx = 5.0

    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 = discretize.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.0, 20.0, 20)
    yr = np.linspace(-20.0, 20.0, 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.0

    # Create a MAGsurvey
    rxLoc = np.c_[utils.mkvc(X.T), utils.mkvc(Y.T), utils.mkvc(Z.T)]
    rxLoc = magnetics.Point(rxLoc)
    srcField = magnetics.SourceField([rxLoc], parameters=H0)
    survey = magnetics.Survey(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.model_builder.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 = magnetics.Simulation3DIntegral(
        mesh,
        survey=survey,
        chiMap=idenMap,
        actInd=actv,
        store_sensitivities="forward_only",
    )

    # Compute linear forward operator and compute some data
    data = prob.make_synthetic_data(
        model, relative_error=0.0, noise_floor=1, add_noise=True
    )

    # 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 = magnetics.Simulation3DIntegral(
        mesh, survey=survey, chiMap=sumMap, actInd=actv, store_sensitivities="ram"
    )

    # Make depth weighting
    wr = np.zeros(sumMap.shape[1])
    print(prob.nC)
    # print(prob.M.shape) # why does this reset nC
    G = prob.G

    # Take the cell number out of the scaling.
    # Want to keep high sens for large volumes
    scale = utils.sdiag(
        np.r_[utils.mkvc(1.0 / 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)
            / data.standard_deviation[ii]
        ) ** 2.0

    # 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 = discretize.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 = data_misfit.L2DataMisfit(simulation=prob, data=data)

    # Add directives to the inversion
    opt = optimization.ProjectedGNCG(
        maxIter=100,
        lower=0.0,
        upper=1.0,
        maxIterLS=20,
        maxIterCG=10,
        tolCG=1e-3,
        tolG=1e-3,
        eps=1e-6,
    )
    invProb = inverse_problem.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",
        )
Пример #14
0
    def setUp(self):

        cs = 25.0
        hx = [(cs, 0, -1.3), (cs, 21), (cs, 0, 1.3)]
        hy = [(cs, 0, -1.3), (cs, 21), (cs, 0, 1.3)]
        hz = [(cs, 0, -1.3), (cs, 20)]
        mesh = discretize.TensorMesh([hx, hy, hz], x0="CCN")
        blkind0 = utils.model_builder.getIndicesSphere(
            np.r_[-100.0, -100.0, -200.0], 75.0, mesh.gridCC)
        blkind1 = utils.model_builder.getIndicesSphere(
            np.r_[100.0, 100.0, -200.0], 75.0, mesh.gridCC)
        sigma = np.ones(mesh.nC) * 1e-2
        eta = np.zeros(mesh.nC)
        tau = np.ones_like(sigma) * 1.0
        eta[blkind0] = 0.1
        eta[blkind1] = 0.1
        tau[blkind0] = 0.1
        tau[blkind1] = 0.01

        x = mesh.vectorCCx[(mesh.vectorCCx > -155.0)
                           & (mesh.vectorCCx < 155.0)]
        y = mesh.vectorCCy[(mesh.vectorCCy > -155.0)
                           & (mesh.vectorCCy < 155.0)]
        Aloc = np.r_[-200.0, 0.0, 0.0]
        Bloc = np.r_[200.0, 0.0, 0.0]
        M = utils.ndgrid(x - 25.0, y, np.r_[0.0])
        N = utils.ndgrid(x + 25.0, y, np.r_[0.0])

        times = np.arange(10) * 1e-3 + 1e-3
        rx = sip.receivers.Dipole(M, N, times)
        print(rx.nD)
        print(rx.locations)
        src = sip.sources.Dipole([rx], Aloc, Bloc)
        survey = sip.Survey([src])
        print(f"Survey ND = {survey.nD}")
        print(f"Survey ND = {src.nD}")

        wires = maps.Wires(("eta", mesh.nC), ("taui", mesh.nC))
        problem = sip.Simulation3DCellCentered(
            mesh,
            survey=survey,
            rho=1.0 / sigma,
            etaMap=wires.eta,
            tauiMap=wires.taui,
            storeJ=False,
        )
        problem.solver = Solver
        mSynth = np.r_[eta, 1.0 / tau]
        problem.model = mSynth
        dobs = problem.make_synthetic_data(mSynth, add_noise=True)
        # Now set up the problem to do some minimization
        dmis = data_misfit.L2DataMisfit(data=dobs, simulation=problem)
        reg = regularization.Tikhonov(mesh)
        opt = optimization.InexactGaussNewton(maxIterLS=20,
                                              maxIter=10,
                                              tolF=1e-6,
                                              tolX=1e-6,
                                              tolG=1e-6,
                                              maxIterCG=6)
        invProb = inverse_problem.BaseInvProblem(dmis, reg, opt, beta=1e4)
        inv = inversion.BaseInversion(invProb)

        self.inv = inv
        self.reg = reg
        self.p = problem
        self.mesh = mesh
        self.m0 = mSynth
        self.survey = survey
        self.dmis = dmis
        self.dobs = dobs
Пример #15
0
 def setup_maps(self, mesh, k_fun, theta_fun):
     wires = maps.Wires(("Ks", mesh.nC), ("A", mesh.nC), ("theta_s", mesh.nC))
     k_fun.KsMap = maps.ExpMap(nP=mesh.nC) * wires.Ks
     k_fun.AMap = wires.A
     theta_fun.theta_sMap = wires.theta_s
Пример #16
0
ind_sphere = model_builder.getIndicesSphere(np.r_[-20.0, 0.0, -15.0], 20.0,
                                            mesh.gridCC)
ind_sphere = ind_sphere[ind_active]  # So same size and order as model
model[ind_sphere, :] = np.c_[sphere_sigma_value, sphere_mu_value]

# Add a conductive and non-permeable dyke
xp = np.kron(np.ones((2)), [-10.0, 10.0, 55.0, 35.0])
yp = np.kron([-1000.0, 1000.0], np.ones((4)))
zp = np.kron(np.ones((2)), [-120.0, -120.0, 45.0, 45.0])
xyz_pts = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)]
ind_polygon = model_builder.PolygonInd(mesh, xyz_pts)
ind_polygon = ind_polygon[ind_active]  # So same size and order as model
model[ind_polygon, 0] = dyke_sigma_value

# Create model vector and wires
model = mkvc(model)
wire_map = maps.Wires(("log_sigma", N), ("mu", N))

# Use combo maps to map from model to mesh
sigma_map = active_map * maps.ExpMap() * wire_map.log_sigma
mu_map = active_map * wire_map.mu

# Plot
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111)
ind_slice = int(mesh.hy.size / 2)
mesh.plotSlice(sigma_map * model, normal="Y", ax=ax, ind=ind_slice, grid=True)
ax.set_title("Model slice at y = {} m".format(mesh.x0[1] +
                                              np.sum(mesh.hy[0:ind_slice])))
plt.show()
Пример #17
0
    def setUp(self):

        cs = 25.0
        hx = [(cs, 0, -1.3), (cs, 21), (cs, 0, 1.3)]
        hy = [(cs, 0, -1.3), (cs, 21), (cs, 0, 1.3)]
        hz = [(cs, 0, -1.3), (cs, 20), (cs, 0, 1.3)]
        mesh = discretize.TensorMesh([hx, hy, hz], x0="CCC")
        blkind0 = utils.model_builder.getIndicesSphere(
            np.r_[-100.0, -100.0, -200.0], 75.0, mesh.gridCC)
        blkind1 = utils.model_builder.getIndicesSphere(
            np.r_[100.0, 100.0, -200.0], 75.0, mesh.gridCC)
        sigma = np.ones(mesh.nC) * 1e-2
        airind = mesh.gridCC[:, 2] > 0.0
        sigma[airind] = 1e-8
        eta = np.zeros(mesh.nC)
        tau = np.ones_like(sigma) * 1.0
        c = np.ones_like(sigma) * 0.5

        eta[blkind0] = 0.1
        eta[blkind1] = 0.1
        tau[blkind0] = 0.1
        tau[blkind1] = 0.01

        actmapeta = maps.InjectActiveCells(mesh, ~airind, 0.0)
        actmaptau = maps.InjectActiveCells(mesh, ~airind, 1.0)
        actmapc = maps.InjectActiveCells(mesh, ~airind, 1.0)

        x = mesh.vectorCCx[(mesh.vectorCCx > -155.0)
                           & (mesh.vectorCCx < 155.0)]
        y = mesh.vectorCCy[(mesh.vectorCCy > -155.0)
                           & (mesh.vectorCCy < 155.0)]
        Aloc = np.r_[-200.0, 0.0, 0.0]
        Bloc = np.r_[200.0, 0.0, 0.0]
        M = utils.ndgrid(x - 25.0, y, np.r_[0.0])
        N = utils.ndgrid(x + 25.0, y, np.r_[0.0])

        times = np.arange(10) * 1e-3 + 1e-3
        rx = sip.receivers.Dipole(M, N, times)
        src = sip.sources.Dipole([rx], Aloc, Bloc)
        survey = sip.Survey([src])

        wires = maps.Wires(("eta", actmapeta.nP), ("taui", actmaptau.nP),
                           ("c", actmapc.nP))
        problem = sip.Simulation3DNodal(
            mesh,
            survey=survey,
            sigma=sigma,
            etaMap=actmapeta * wires.eta,
            tauiMap=actmaptau * wires.taui,
            cMap=actmapc * wires.c,
            actinds=~airind,
            storeJ=False,
            verbose=False,
        )

        problem.solver = Solver
        mSynth = np.r_[eta[~airind], 1.0 / tau[~airind], c[~airind]]
        dobs = problem.make_synthetic_data(mSynth, add_noise=True)
        # Now set up the problem to do some minimization
        dmis = data_misfit.L2DataMisfit(data=dobs, simulation=problem)
        reg_eta = regularization.Sparse(mesh,
                                        mapping=wires.eta,
                                        indActive=~airind)
        reg_taui = regularization.Sparse(mesh,
                                         mapping=wires.taui,
                                         indActive=~airind)
        reg_c = regularization.Sparse(mesh, mapping=wires.c, indActive=~airind)
        reg = reg_eta + reg_taui + reg_c
        opt = optimization.InexactGaussNewton(maxIterLS=20,
                                              maxIter=10,
                                              tolF=1e-6,
                                              tolX=1e-6,
                                              tolG=1e-6,
                                              maxIterCG=6)
        invProb = inverse_problem.BaseInvProblem(dmis, reg, opt, beta=1e4)
        inv = inversion.BaseInversion(invProb)

        self.inv = inv
        self.reg = reg
        self.p = problem
        self.mesh = mesh
        self.m0 = mSynth
        self.survey = survey
        self.dmis = dmis
        self.dobs = dobs
Пример #18
0
    def dpred(self):
        target = self.survey.source.target
        collection = self.survey.source.collection
        '''Mesh'''
        # Conductivity in S/m (or resistivity in Ohm m)
        background_conductivity = 1e-6
        air_conductivity = 1e-8

        # Permeability in H/m
        background_permeability = mu_0
        air_permeability = mu_0

        dh = 0.1  # base cell width
        dom_width = 20.0  # domain width
        # num. base cells
        nbc = 2**int(np.round(np.log(dom_width / dh) / np.log(2.0)))

        # Define the base mesh
        h = [(dh, nbc)]
        mesh = TreeMesh([h, h, h], x0="CCC")

        # Mesh refinement near transmitters and receivers
        mesh = refine_tree_xyz(mesh,
                               collection.receiver_location,
                               octree_levels=[2, 4],
                               method="radial",
                               finalize=False)

        # Refine core mesh region
        xp, yp, zp = np.meshgrid([-1.5, 1.5], [-1.5, 1.5], [-6, -4])
        xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)]
        mesh = refine_tree_xyz(mesh,
                               xyz,
                               octree_levels=[0, 6],
                               method="box",
                               finalize=False)

        mesh.finalize()
        '''Maps'''

        # Find cells that are active in the forward modeling (cells below surface)
        ind_active = mesh.gridCC[:, 2] < 0

        # Define mapping from model to active cells
        active_sigma_map = maps.InjectActiveCells(mesh, ind_active,
                                                  air_conductivity)
        active_mu_map = maps.InjectActiveCells(mesh, ind_active,
                                               air_permeability)

        # Define model. Models in SimPEG are vector arrays
        N = int(ind_active.sum())
        model = np.kron(
            np.ones((N, 1)), np.c_[background_conductivity,
                                   background_permeability])

        ind_cylinder = self.getIndicesCylinder(
            [target.position[0], target.position[1], target.position[2]],
            target.radius, target.length, [target.pitch, target.roll],
            mesh.gridCC)
        ind_cylinder = ind_cylinder[ind_active]
        model[ind_cylinder, :] = np.c_[target.conductivity,
                                       target.permeability]

        # Create model vector and wires
        model = mkvc(model)
        wire_map = maps.Wires(("sigma", N), ("mu", N))

        # Use combo maps to map from model to mesh
        sigma_map = active_sigma_map * wire_map.sigma
        mu_map = active_mu_map * wire_map.mu
        '''Simulation'''
        simulation = fdem.simulation.Simulation3DMagneticFluxDensity(
            mesh,
            survey=self.survey.survey,
            sigmaMap=sigma_map,
            muMap=mu_map,
            Solver=Solver)
        '''Predict'''

        # Compute predicted data for your model.
        dpred = simulation.dpred(model)
        dpred = dpred * 1e9

        # Data are organized by frequency, transmitter location, then by receiver.
        # We had nFreq transmitters and each transmitter had 2 receivers (real and
        # imaginary component). So first we will pick out the real and imaginary
        # data
        bx_real = dpred[0:len(dpred):6]
        bx_imag = dpred[1:len(dpred):6]
        bx_total = np.sqrt(np.square(bx_real) + np.square(bx_imag))
        by_real = dpred[2:len(dpred):6]
        by_imag = dpred[3:len(dpred):6]
        by_total = np.sqrt(np.square(by_real) + np.square(by_imag))
        bz_real = dpred[4:len(dpred):6]
        bz_imag = dpred[5:len(dpred):6]
        bz_total = np.sqrt(np.square(bz_real) + np.square(bz_imag))

        mag_data = np.c_[mkvc(bx_total), mkvc(by_total), mkvc(bz_total)]
        if collection.SNR is not None:
            mag_data = self.mag_data_add_noise(mag_data, collection.SNR)
        data = np.c_[collection.receiver_location, mag_data]
        # data = (data, )

        return data  # 只保留磁场强度数据,删除后面的两个参数
# ---------
#
# We can now attempt the inverse calculations. We put great care
# into designing an inversion methology that would yield a geologically
# reasonable solution for the non-induced problem.
# The inversion is done in two stages. First we compute a smooth
# solution using a Cartesian coordinate system, then a sparse
# inversion in the Spherical domain.
#

# Create sensitivity weights from our linear forward operator
rxLoc = survey.source_field.receiver_list[0].locations

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

m0 = np.ones(3 * nC) * 1e-4  # Starting model

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

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

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

reg = reg_p + reg_s + reg_t
resistivities = np.r_[1e3, 1e3, 1e3]
layer_thicknesses = np.r_[50.0, 50.0]

# Define a mesh for plotting and regularization.
mesh = TensorMesh([(np.r_[layer_thicknesses, layer_thicknesses[-1]])], "0")
print(mesh)

# Define model. We are inverting for the layer resistivities and layer thicknesses.
# Since the bottom layer extends to infinity, it is not a model parameter for
# which we need to invert. For a 3 layer model, there is a total of 5 parameters.
# For stability, our model is the log-resistivity and log-thickness.
starting_model = np.r_[np.log(resistivities), np.log(layer_thicknesses)]

# Since the model contains two different properties for each layer, we use
# wire maps to distinguish the properties.
wire_map = maps.Wires(("rho", mesh.nC), ("t", mesh.nC - 1))
resistivity_map = maps.ExpMap(nP=mesh.nC) * wire_map.rho
layer_map = maps.ExpMap(nP=mesh.nC - 1) * wire_map.t

#######################################################################
# Define the Physics
# ------------------
#
# Here we define the physics of the problem. The data consists of apparent
# resistivity values. This is defined here.
#

simulation = dc.simulation_1d.Simulation1DLayers(
    survey=survey,
    rhoMap=resistivity_map,
    thicknessesMap=layer_map,
Пример #21
0
    mesh=mesh,
    n_components=3,
    covariance_type="full",
    tol=1e-8,
    reg_covar=1e-3,
    max_iter=1000,
    n_init=100,
    init_params="kmeans",
    random_state=None,
    warm_start=False,
    verbose=0,
    verbose_interval=10,
)
clfnomapping = clfnomapping.fit(model2d)

wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC))

relatrive_error = 0.01
noise_floor = 0.0

prob1 = simulation.LinearSimulation(mesh, G=G, model_map=wires.m1)
survey1 = prob1.make_synthetic_data(m,
                                    relative_error=relatrive_error,
                                    noise_floor=noise_floor,
                                    add_noise=True)

prob2 = simulation.LinearSimulation(mesh, G=G, model_map=wires.m2)
survey2 = prob2.make_synthetic_data(m,
                                    relative_error=relatrive_error,
                                    noise_floor=noise_floor,
                                    add_noise=True)
#

# Define density contrast values for each unit in g/cc.
background_dens, background_susc = 1e-6, 1e-6

# Find the indicies of the active cells in forward model (ones below surface)
ind_active = surface2ind_topo(mesh, xyz_topo)

# Define mapping from model to active cells
nC = int(ind_active.sum())
model_map = maps.IdentityMap(
    nP=nC)  # model consists of a value for each active cell

# Create Wires Map that maps from stacked models to individual model components
# m1 refers to density model, m2 refers to susceptibility
wires = maps.Wires(("density", nC), ("susceptibility", nC))

# Define and plot starting model
starting_model = np.r_[background_dens * np.ones(nC),
                       background_susc * np.ones(nC)]

##############################################
# Define the Physics
# ------------------
#
# Here, we define the physics of the gravity and magnetic problems by using the simulation
# class.
#

simulation_grav = gravity.simulation.Simulation3DIntegral(survey=survey_grav,
                                                          mesh=mesh,
Пример #23
0
def fdem_forward_simulation(detector, target, collection):
    """
    Get FDEM simulation data using SimPEG.

    Parameters
    ----------
    detector : class Detector
    target : class Target
    collention : class Collection

    Returns
    -------
    receiver_locations : numpy.ndarray, shape(N * 3)
        All acquisition locations of the detector. Each row represents an
        acquisition location and the three columns represent x, y and z axis
        locations of an acquisition location.
    mag_data : numpy.ndarray, shape(N*3)
        All secondary fields of acquisition locations.
    mesh : SimPEG mesh
    mapped_model : numpy.ndarray

    References
    ----------
    https://docs.simpeg.xyz/content/tutorials/01-models_mapping/plot_1_tensor_models.html#sphx-glr-content-tutorials-01-models-mapping-plot-1-tensor-models-py
    http://discretize.simpeg.xyz/en/master/tutorials/mesh_generation/4_tree_mesh.html#sphx-glr-tutorials-mesh-generation-4-tree-mesh-py
    https://docs.simpeg.xyz/content/tutorials/07-fdem/plot_fwd_2_fem_cyl.html#sphx-glr-content-tutorials-07-fdem-plot-fwd-2-fem-cyl-py
    https://docs.simpeg.xyz/content/examples/05-fdem/plot_inv_fdem_loop_loop_2Dinversion.html#sphx-glr-content-examples-05-fdem-plot-inv-fdem-loop-loop-2dinversion-py

    """

    # Frequencies being predicted
    frequencies = [detector.frequency]

    # Conductivity in S/m (or resistivity in Ohm m)
    background_conductivity = 1e-6
    air_conductivity = 1e-8

    # Permeability in H/m
    background_permeability = mu_0
    air_permeability = mu_0
    """Survey"""

    # Defining transmitter locations
    acquisition_spacing = collection.spacing
    acq_area_xmin, acq_area_xmax = collection.x_min, collection.x_max
    acq_area_ymin, acq_area_ymax = collection.y_min, collection.y_max
    Nx = int((acq_area_xmax - acq_area_xmin) / acquisition_spacing + 1)
    Ny = int((acq_area_ymax - acq_area_ymin) / acquisition_spacing + 1)
    xtx, ytx, ztx = np.meshgrid(np.linspace(acq_area_xmin, acq_area_xmax, Nx),
                                np.linspace(acq_area_ymin, acq_area_ymax, Ny),
                                [collection.height])
    source_locations = np.c_[mkvc(xtx), mkvc(ytx), mkvc(ztx)]
    ntx = np.size(xtx)

    # Define receiver locations
    xrx, yrx, zrx = np.meshgrid(np.linspace(acq_area_xmin, acq_area_xmax, Nx),
                                np.linspace(acq_area_ymin, acq_area_ymax, Ny),
                                [collection.height])
    receiver_locations = np.c_[mkvc(xrx), mkvc(yrx), mkvc(zrx)]

    # Create empty list to store sources
    source_list = []

    # Each unique location and frequency defines a new transmitter
    for ii in range(len(frequencies)):
        for jj in range(ntx):

            # Define receivers of different type at each location
            bxr_receiver = fdem.receivers.PointMagneticFluxDensitySecondary(
                receiver_locations[jj, :], "x", "real")
            bxi_receiver = fdem.receivers.PointMagneticFluxDensitySecondary(
                receiver_locations[jj, :], "x", "imag")
            byr_receiver = fdem.receivers.PointMagneticFluxDensitySecondary(
                receiver_locations[jj, :], "y", "real")
            byi_receiver = fdem.receivers.PointMagneticFluxDensitySecondary(
                receiver_locations[jj, :], "y", "imag")
            bzr_receiver = fdem.receivers.PointMagneticFluxDensitySecondary(
                receiver_locations[jj, :], "z", "real")
            bzi_receiver = fdem.receivers.PointMagneticFluxDensitySecondary(
                receiver_locations[jj, :], "z", "imag")
            receivers_list = [
                bxr_receiver, bxi_receiver, byr_receiver, byi_receiver,
                bzr_receiver, bzi_receiver
            ]

            # Must define the transmitter properties and associated receivers
            source_list.append(
                fdem.sources.MagDipole(receivers_list,
                                       frequencies[ii],
                                       source_locations[jj],
                                       orientation="z",
                                       moment=detector.get_mag_moment()))

    survey = fdem.Survey(source_list)
    '''Mesh'''

    dh = 0.1  # base cell width
    dom_width = 20.0  # domain width
    # num. base cells
    nbc = 2**int(np.round(np.log(dom_width / dh) / np.log(2.0)))

    # Define the base mesh
    h = [(dh, nbc)]
    mesh = TreeMesh([h, h, h], x0="CCC")

    # Mesh refinement near transmitters and receivers
    mesh = refine_tree_xyz(mesh,
                           receiver_locations,
                           octree_levels=[2, 4],
                           method="radial",
                           finalize=False)

    # Refine core mesh region
    xp, yp, zp = np.meshgrid([-1.5, 1.5], [-1.5, 1.5], [-6, -4])
    xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)]
    mesh = refine_tree_xyz(mesh,
                           xyz,
                           octree_levels=[0, 6],
                           method="box",
                           finalize=False)

    mesh.finalize()
    '''Maps'''

    # Find cells that are active in the forward modeling (cells below surface)
    ind_active = mesh.gridCC[:, 2] < 0

    # Define mapping from model to active cells
    active_sigma_map = maps.InjectActiveCells(mesh, ind_active,
                                              air_conductivity)
    active_mu_map = maps.InjectActiveCells(mesh, ind_active, air_permeability)

    # Define model. Models in SimPEG are vector arrays
    N = int(ind_active.sum())
    model = np.kron(np.ones((N, 1)), np.c_[background_conductivity,
                                           background_permeability])

    ind_cylinder = getIndicesCylinder(
        [target.position[0], target.position[1], target.position[2]],
        target.radius, target.length, [target.pitch, target.roll], mesh.gridCC)
    ind_cylinder = ind_cylinder[ind_active]
    model[ind_cylinder, :] = np.c_[target.conductivity, target.permeability]

    # Create model vector and wires
    model = mkvc(model)
    wire_map = maps.Wires(("sigma", N), ("mu", N))

    # Use combo maps to map from model to mesh
    sigma_map = active_sigma_map * wire_map.sigma
    mu_map = active_mu_map * wire_map.mu
    '''Simulation'''

    simulation = fdem.simulation.Simulation3DMagneticFluxDensity(
        mesh, survey=survey, sigmaMap=sigma_map, muMap=mu_map, Solver=Solver)
    '''Predict'''

    # Compute predicted data for a your model.
    dpred = simulation.dpred(model)
    dpred = dpred * 1e9

    # Data are organized by frequency, transmitter location, then by receiver.
    # We had nFreq transmitters and each transmitter had 2 receivers (real and
    # imaginary component). So first we will pick out the real and imaginary
    # data
    bx_real = dpred[0:len(dpred):6]
    bx_imag = dpred[1:len(dpred):6]
    bx_total = np.sqrt(np.square(bx_real) + np.square(bx_imag))
    by_real = dpred[2:len(dpred):6]
    by_imag = dpred[3:len(dpred):6]
    by_total = np.sqrt(np.square(by_real) + np.square(by_imag))
    bz_real = dpred[4:len(dpred):6]
    bz_imag = dpred[5:len(dpred):6]
    bz_total = np.sqrt(np.square(bz_real) + np.square(bz_imag))

    mag_data = np.c_[mkvc(bx_total), mkvc(by_total), mkvc(bz_total)]

    return receiver_locations, mag_data, mesh, sigma_map * model
Пример #24
0
def setupProblem(
    mesh,
    muMod,
    sigmaMod,
    prbtype="ElectricField",
    invertMui=False,
    sigmaInInversion=False,
    freq=1.0,
):
    rxcomp = ["real", "imag"]

    loc = utils.ndgrid([mesh.vectorCCx, np.r_[0.0], mesh.vectorCCz])

    if prbtype in ["ElectricField", "MagneticFluxDensity"]:
        rxfields_y = ["ElectricField", "CurrentDensity"]
        rxfields_xz = ["MagneticFluxDensity", "MagneticField"]

    elif prbtype in ["MagneticField", "CurrentDensity"]:
        rxfields_y = ["MagneticFluxDensity", "MagneticField"]
        rxfields_xz = ["ElectricField", "CurrentDensity"]

    receiver_list_edge = [
        getattr(fdem.receivers, "Point{f}".format(f=f))(loc,
                                                        component=comp,
                                                        orientation=orient)
        for f in rxfields_y for comp in rxcomp for orient in ["y"]
    ]

    receiver_list_face = [
        getattr(fdem.receivers, "Point{f}".format(f=f))(loc,
                                                        component=comp,
                                                        orientation=orient)
        for f in rxfields_xz for comp in rxcomp for orient in ["x", "z"]
    ]

    receiver_list = receiver_list_edge + receiver_list_face

    src_loc = np.r_[0.0, 0.0, 0.0]

    if prbtype in ["ElectricField", "MagneticFluxDensity"]:
        src = fdem.sources.MagDipole(receiver_list=receiver_list,
                                     location=src_loc,
                                     frequency=freq)

    elif prbtype in ["MagneticField", "CurrentDensity"]:
        ind = utils.closestPoints(mesh, src_loc, "Fz") + mesh.vnF[0]
        vec = np.zeros(mesh.nF)
        vec[ind] = 1.0

        src = fdem.sources.RawVec_e(receiver_list=receiver_list,
                                    frequency=freq,
                                    s_e=vec)

    survey = fdem.Survey([src])

    if sigmaInInversion:

        wires = maps.Wires(("mu", mesh.nC), ("sigma", mesh.nC))

        muMap = maps.MuRelative(mesh) * wires.mu
        sigmaMap = maps.ExpMap(mesh) * wires.sigma

        if invertMui:
            muiMap = maps.ReciprocalMap(mesh) * muMap
            prob = getattr(fdem,
                           "Simulation3D{}".format(prbtype))(mesh,
                                                             muiMap=muiMap,
                                                             sigmaMap=sigmaMap)
            # m0 = np.hstack([1./muMod, sigmaMod])
        else:
            prob = getattr(fdem,
                           "Simulation3D{}".format(prbtype))(mesh,
                                                             muMap=muMap,
                                                             sigmaMap=sigmaMap)
        m0 = np.hstack([muMod, sigmaMod])

    else:
        muMap = maps.MuRelative(mesh)

        if invertMui:
            muiMap = maps.ReciprocalMap(mesh) * muMap
            prob = getattr(fdem,
                           "Simulation3D{}".format(prbtype))(mesh,
                                                             sigma=sigmaMod,
                                                             muiMap=muiMap)
            # m0 = 1./muMod
        else:
            prob = getattr(fdem,
                           "Simulation3D{}".format(prbtype))(mesh,
                                                             sigma=sigmaMod,
                                                             muMap=muMap)
        m0 = muMod

    prob.survey = survey

    return m0, prob, survey
Пример #25
0
# Load Topo
topo_file = io_utils.download(
    "https://storage.googleapis.com/simpeg/pgi_tutorial_assets/CDED_Lake_warp.xyz"
)
topo = np.genfromtxt(topo_file, skip_header=1)
# find the active cells
actv = utils.surface2ind_topo(mesh, topo, gridLoc="CC")
# Create active map to go from reduce set to full
ndv = np.nan
actvMap = maps.InjectActiveCells(mesh, actv, ndv)
nactv = int(actv.sum())

# Create simulations and data misfits
# Wires mapping
wires = maps.Wires(("den", actvMap.nP), ("sus", actvMap.nP))
gravmap = actvMap * wires.den
magmap = actvMap * wires.sus
idenMap = maps.IdentityMap(nP=nactv)
# Grav problem
simulation_grav = pf.gravity.simulation.Simulation3DIntegral(
    survey=data_grav.survey,
    mesh=mesh,
    rhoMap=wires.den,
    actInd=actv,
)
dmis_grav = data_misfit.L2DataMisfit(data=data_grav,
                                     simulation=simulation_grav)
# Mag problem
simulation_mag = pf.magnetics.simulation.Simulation3DIntegral(
    survey=data_mag.survey,
Пример #26
0
    def setUp(self):
        np.random.seed(0)
        H0 = (50000.0, 90.0, 0.0)

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

        # 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.0 + (yy / b)**2.0))

        # 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.0, 100.0, 20)
        yr = np.linspace(-100.0, 100.0, 20)
        X, Y = np.meshgrid(xr, yr)
        Z = A * np.exp(-0.5 * ((X / b)**2.0 + (Y / b)**2.0)) + 5

        # Create a MAGsurvey
        xyzLoc = np.c_[utils.mkvc(X.T), utils.mkvc(Y.T), utils.mkvc(Z.T)]
        rxLoc = mag.Point(xyzLoc)
        srcField = mag.SourceField([rxLoc], parameters=H0)
        survey = mag.Survey(srcField)

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

        mesh = mesh_builder_xyz(xyzLoc,
                                h,
                                padding_distance=padDist,
                                depth_core=100,
                                mesh_type="tree")
        mesh = refine_tree_xyz(mesh,
                               topo,
                               method="surface",
                               octree_levels=[4, 4],
                               finalize=True)
        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.mat_utils.dip_azimuth2cartesian(M[0], M[1])

        # Get the indicies of the magnetized block
        ind = utils.model_builder.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
        sim = mag.Simulation3DIntegral(
            self.mesh,
            survey=survey,
            model_type="vector",
            chiMap=idenMap,
            actInd=actv,
            store_sensitivities="disk",
        )
        self.sim = sim

        # Compute some data and add some random noise
        data = sim.make_synthetic_data(utils.mkvc(self.model),
                                       relative_error=0.0,
                                       noise_floor=5.0,
                                       add_noise=True)

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

        # 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_s = regularization.Sparse(mesh, indActive=actv, mapping=wires.s)
        reg_s.mref = np.zeros(3 * nC)

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

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

        # Data misfit function
        dmis = data_misfit.L2DataMisfit(simulation=sim, data=data)
        # dmis.W = 1./survey.std

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

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

        # A list of directive to control the inverson
        betaest = directives.BetaEstimate_ByEig(beta0_ratio=1e1)

        # 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,
                                      max_irls_iterations=0,
                                      beta_tol=5e-1)

        # Pre-conditioner
        update_Jacobi = directives.UpdatePreconditioner()
        sensitivity_weights = directives.UpdateSensitivityWeights(
            everyIter=False)
        inv = inversion.BaseInversion(
            invProb,
            directiveList=[sensitivity_weights, IRLS, update_Jacobi, betaest])

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

        sim.chiMap = maps.SphericalSystem(nP=nC * 3)
        self.mstart = sim.chiMap.inverse(mrec_MVIC)
        dmis.simulation.model = self.mstart
        beta = invProb.beta

        # 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, 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.0  # No reference angle
        reg_t.space = "spherical"
        reg_t.norms = np.c_[2.0, 0.0, 0.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.0  # No reference angle
        reg_p.space = "spherical"
        reg_p.norms = np.c_[2.0, 0.0, 0.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=5,
            lower=Lbound,
            upper=Ubound,
            maxIterLS=5,
            maxIterCG=5,
            tolCG=1e-3,
            stepOffBoundsFact=1e-3,
        )
        opt.approxHinv = None

        invProb = inverse_problem.BaseInvProblem(dmis, reg, opt, beta=beta)

        # Here is where the norms are applied
        IRLS = directives.Update_IRLS(
            f_min_change=1e-4,
            max_irls_iterations=5,
            minGNiter=1,
            beta_tol=0.5,
            coolingRate=1,
            coolEps_q=True,
            sphericalDomain=True,
        )

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

        self.inv = inversion.BaseInversion(
            invProb,
            directiveList=[
                ProjSpherical, IRLS, sensitivity_weights, update_Jacobi
            ],
        )