예제 #1
0
    def test_Tile(self):
        """
        Test for TileMap
        """
        rxLocs = np.random.randn(3, 3) * 20
        h = [5, 5, 5]
        padDist = np.ones((3, 2)) * 100

        local_meshes = []

        for ii in range(rxLocs.shape[0]):

            local_mesh = mesh_builder_xyz(rxLocs,
                                          h,
                                          padding_distance=padDist,
                                          mesh_type="tree")
            local_mesh = refine_tree_xyz(
                local_mesh,
                rxLocs[ii, :].reshape((1, -1)),
                method="radial",
                octree_levels=[1],
                finalize=True,
            )

            local_meshes.append(local_mesh)

        mesh = mesh_builder_xyz(rxLocs,
                                h,
                                padding_distance=padDist,
                                mesh_type="tree")

        # This garantees that the local meshes are always coarser or equal
        for local_mesh in local_meshes:
            mesh.insert_cells(
                local_mesh.gridCC,
                local_mesh.cell_levels_by_index(np.arange(local_mesh.nC)),
                finalize=False,
            )
        mesh.finalize()

        # Define an active cells from topo
        activeCells = utils.surface2ind_topo(mesh, rxLocs)

        model = np.random.randn(int(activeCells.sum()))
        total_mass = (model * mesh.vol[activeCells]).sum()

        for local_mesh in local_meshes:

            tile_map = maps.TileMap(
                mesh,
                activeCells,
                local_mesh,
            )

            local_mass = ((tile_map * model) *
                          local_mesh.vol[tile_map.local_active]).sum()

            self.assertTrue((local_mass - total_mass) / total_mass < 1e-8)
예제 #2
0
    def test_surface(self):
        dx = 0.1
        dl = 20

        # Define triangle
        xyz = np.r_[np.c_[-dl / 2, -dl / 2, 0], np.c_[dl / 2, -dl / 2, 0],
                    np.c_[dl / 2, dl / 2, 0], ]
        mesh = mesh_builder_xyz(
            np.c_[0.01, 0.01, 0.01],
            [dx, dx, dx],
            depth_core=0,
            padding_distance=[[0, 20], [0, 20], [0, 20]],
            mesh_type="TREE",
        )

        mesh = refine_tree_xyz(mesh,
                               xyz,
                               octree_levels=[1],
                               method="surface",
                               finalize=True)

        # Volume of triangle
        vol = dl * dl * dx / 2

        residual = (
            np.abs(vol - mesh.cell_volumes[mesh._cell_levels_by_indexes(
                range(mesh.nC)) == mesh.max_level].sum() / 2) / vol * 100)

        self.assertLess(residual, 5)
예제 #3
0
    def test_radial(self):
        dx = 0.25
        rad = 10
        mesh = mesh_builder_xyz(
            np.c_[0.01, 0.01, 0.01],
            [dx, dx, dx],
            depth_core=0,
            padding_distance=[[0, 20], [0, 20], [0, 20]],
            mesh_type="TREE",
        )

        radCell = int(np.ceil(rad / dx))
        mesh = refine_tree_xyz(
            mesh,
            np.c_[0, 0, 0],
            octree_levels=[radCell],
            method="radial",
            finalize=True,
        )
        cell_levels = mesh.cell_levels_by_index(np.arange(mesh.n_cells))

        vol = 4.0 * np.pi / 3.0 * (rad + dx)**3.0

        vol_mesh = mesh.cell_volumes[cell_levels == mesh.max_level].sum()

        self.assertLess(np.abs(vol - vol_mesh) / vol, 0.05)

        levels, cells_per_level = np.unique(cell_levels, return_counts=True)

        self.assertEqual(mesh.n_cells, 311858)
        np.testing.assert_array_equal(levels, [3, 4, 5, 6, 7])
        np.testing.assert_array_equal(cells_per_level,
                                      [232, 1176, 2671, 9435, 298344])
    def test_radial(self):
        dx = 0.25
        rad = 10
        mesh = mesh_builder_xyz(
            np.c_[0.01, 0.01, 0.01],
            [dx, dx, dx],
            depth_core=0,
            padding_distance=[[0, 20], [0, 20], [0, 20]],
            mesh_type="TREE",
        )

        radCell = int(np.ceil(rad / dx))
        mesh = refine_tree_xyz(
            mesh,
            np.c_[0, 0, 0],
            octree_levels=[radCell],
            method="radial",
            finalize=True,
        )

        # Volume of sphere
        vol = 4.0 * np.pi / 3.0 * rad**3.0

        residual = (np.abs(vol - mesh.vol[mesh._cell_levels_by_indexes(
            range(mesh.nC)) == mesh.max_level].sum()) / vol * 100)

        self.assertTrue(residual < 3)
예제 #5
0
    def test_box(self):
        dx = 0.25
        dl = 10

        # Create a box 2*dl in width
        X, Y, Z = np.meshgrid(np.c_[-dl, dl], np.c_[-dl, dl], np.c_[-dl, dl])
        xyz = np.c_[np.ravel(X), np.ravel(Y), np.ravel(Z)]
        mesh = mesh_builder_xyz(
            np.c_[0.01, 0.01, 0.01],
            [dx, dx, dx],
            depth_core=0,
            padding_distance=[[0, 20], [0, 20], [0, 20]],
            mesh_type="TREE",
        )

        mesh = refine_tree_xyz(mesh,
                               xyz,
                               octree_levels=[0, 1],
                               method="box",
                               finalize=True)
        cell_levels = mesh.cell_levels_by_index(np.arange(mesh.n_cells))

        vol = (
            2 *
            (dl + 2 * dx))**3  # 2*dx is cell size at second to highest level
        vol_mesh = np.sum(mesh.cell_volumes[cell_levels == mesh.max_level - 1])
        self.assertLess((vol - vol_mesh) / vol, 0.05)

        levels, cells_per_level = np.unique(cell_levels, return_counts=True)

        self.assertEqual(mesh.n_cells, 80221)
        np.testing.assert_array_equal(levels, [3, 4, 5, 6])
        np.testing.assert_array_equal(cells_per_level, [80, 1762, 4291, 74088])
    def test_box(self):
        dx = 0.25
        dl = 10

        # Create a box 2*dl in width
        X, Y, Z = np.meshgrid(np.c_[-dl, dl], np.c_[-dl, dl], np.c_[-dl, dl])
        xyz = np.c_[np.ravel(X), np.ravel(Y), np.ravel(Z)]
        mesh = mesh_builder_xyz(
            np.c_[0.01, 0.01, 0.01],
            [dx, dx, dx],
            depth_core=0,
            padding_distance=[[0, 20], [0, 20], [0, 20]],
            mesh_type="TREE",
        )

        mesh = refine_tree_xyz(mesh,
                               xyz,
                               octree_levels=[1],
                               method="box",
                               finalize=True)

        # Volume of box
        vol = (2 * dl)**3

        residual = (np.abs(vol - mesh.vol[mesh._cell_levels_by_indexes(
            range(mesh.nC)) == mesh.max_level].sum()) / vol * 100)

        self.assertTrue(residual < 0.5)
예제 #7
0
    def test_errors(self):
        dx = 0.25
        rad = 10
        self.assertRaises(
            ValueError,
            mesh_builder_xyz,
            np.c_[0.01, 0.01, 0.01],
            [dx, dx, dx],
            depth_core=0,
            padding_distance=[[0, 20], [0, 20], [0, 20]],
            mesh_type="cyl",
        )

        mesh = mesh_builder_xyz(
            np.c_[0.01, 0.01, 0.01],
            [dx, dx, dx],
            depth_core=0,
            padding_distance=[[0, 20], [0, 20], [0, 20]],
            mesh_type="tree",
        )

        radCell = int(np.ceil(rad / dx))
        self.assertRaises(
            NotImplementedError,
            refine_tree_xyz,
            mesh,
            np.c_[0, 0, 0],
            octree_levels=[radCell],
            method="other",
            finalize=True,
        )

        self.assertRaises(
            ValueError,
            refine_tree_xyz,
            mesh,
            np.c_[0, 0, 0],
            octree_levels=[radCell],
            octree_levels_padding=[],
            method="surface",
            finalize=True,
        )
예제 #8
0
    def test_active_from_xyz(self):

        # Create 3D topo
        [xx, yy] = np.meshgrid(np.linspace(-200, 200, 50),
                               np.linspace(-200, 200, 50))
        b = 50
        A = 50
        zz = A * np.exp(-0.5 * ((xx / b)**2.0 + (yy / b)**2.0))

        h = [5.0, 5.0, 5.0]

        # Test 1D Mesh
        topo1D = zz[25, :].ravel()
        mesh1D = discretize.TensorMesh([np.ones(10) * 20], x0="C")

        indtopoCC = active_from_xyz(mesh1D,
                                    topo1D,
                                    grid_reference="CC",
                                    method="nearest")
        indtopoN = active_from_xyz(mesh1D,
                                   topo1D,
                                   grid_reference="N",
                                   method="nearest")

        self.assertEqual(indtopoCC.sum(), 3)
        self.assertEqual(indtopoN.sum(), 2)

        # Test 2D Tensor mesh
        topo2D = np.c_[xx[25, :].ravel(), zz[25, :].ravel()]

        mesh_tensor = discretize.TensorMesh([[(h[0], 24)], [(h[1], 20)]],
                                            x0="CC")

        indtopoCC = active_from_xyz(mesh_tensor,
                                    topo2D,
                                    grid_reference="CC",
                                    method="nearest")
        indtopoN = active_from_xyz(mesh_tensor,
                                   topo2D,
                                   grid_reference="N",
                                   method="nearest")

        self.assertEqual(indtopoCC.sum(), 434)
        self.assertEqual(indtopoN.sum(), 412)

        # test 2D Curvilinear mesh
        nodes_x = mesh_tensor.gridN[:, 0].reshape(mesh_tensor.vnN, order="F")
        nodes_y = mesh_tensor.gridN[:, 1].reshape(mesh_tensor.vnN, order="F")
        mesh_curvi = discretize.CurvilinearMesh([nodes_x, nodes_y])

        indtopoCC = active_from_xyz(mesh_curvi,
                                    topo2D,
                                    grid_reference="CC",
                                    method="nearest")
        indtopoN = active_from_xyz(mesh_curvi,
                                   topo2D,
                                   grid_reference="N",
                                   method="nearest")

        self.assertEqual(indtopoCC.sum(), 434)
        self.assertEqual(indtopoN.sum(), 412)

        # Test 2D Tree mesh
        mesh_tree = mesh_builder_xyz(topo2D, h[:2], mesh_type="TREE")
        mesh_tree = refine_tree_xyz(
            mesh_tree,
            topo2D,
            method="surface",
            octree_levels=[1],
            octree_levels_padding=None,
            finalize=True,
        )
        indtopoCC = active_from_xyz(mesh_tree,
                                    topo2D,
                                    grid_reference="CC",
                                    method="nearest")
        indtopoN = active_from_xyz(mesh_tree,
                                   topo2D,
                                   grid_reference="N",
                                   method="nearest")

        self.assertEqual(indtopoCC.sum(), 167)
        self.assertEqual(indtopoN.sum(), 119)

        # Test 3D Tensor meshes
        topo3D = np.c_[xx.ravel(), yy.ravel(), zz.ravel()]

        mesh_tensor = discretize.TensorMesh(
            [[(h[0], 24)], [(h[1], 20)], [(h[2], 30)]], x0="CCC")

        indtopoCC = active_from_xyz(mesh_tensor,
                                    topo3D,
                                    grid_reference="CC",
                                    method="nearest")
        indtopoN = active_from_xyz(mesh_tensor,
                                   topo3D,
                                   grid_reference="N",
                                   method="nearest")

        self.assertEqual(indtopoCC.sum(), 10496)
        self.assertEqual(indtopoN.sum(), 10084)

        # test 3D Curvilinear mesh
        nodes_x = mesh_tensor.gridN[:, 0].reshape(mesh_tensor.vnN, order="F")
        nodes_y = mesh_tensor.gridN[:, 1].reshape(mesh_tensor.vnN, order="F")
        nodes_z = mesh_tensor.gridN[:, 2].reshape(mesh_tensor.vnN, order="F")
        mesh_curvi = discretize.CurvilinearMesh([nodes_x, nodes_y, nodes_z])

        indtopoCC = active_from_xyz(mesh_curvi,
                                    topo3D,
                                    grid_reference="CC",
                                    method="nearest")
        indtopoN = active_from_xyz(mesh_curvi,
                                   topo3D,
                                   grid_reference="N",
                                   method="nearest")

        self.assertEqual(indtopoCC.sum(), 10496)
        self.assertEqual(indtopoN.sum(), 10084)

        # Test 3D Tree mesh
        mesh_tree = mesh_builder_xyz(topo3D, h, mesh_type="TREE")
        mesh_tree = refine_tree_xyz(
            mesh_tree,
            topo3D,
            method="surface",
            octree_levels=[1],
            octree_levels_padding=None,
            finalize=True,
        )
        indtopoCC = active_from_xyz(mesh_tree,
                                    topo3D,
                                    grid_reference="CC",
                                    method="nearest")
        indtopoN = active_from_xyz(mesh_tree,
                                   topo3D,
                                   grid_reference="N",
                                   method="nearest")

        self.assertIn(indtopoCC.sum(), [6292, 6299])
        self.assertIn(indtopoN.sum(), [4632, 4639])

        # Test 3D CYL Mesh
        ncr = 10  # number of mesh cells in r
        ncz = 15  # number of mesh cells in z
        dr = 15  # cell width r
        dz = 10  # cell width z
        npad_r = 4  # number of padding cells in r
        npad_z = 4  # number of padding cells in z
        exp_r = 1.25  # expansion rate of padding cells in r
        exp_z = 1.25  # expansion rate of padding cells in z

        hr = [(dr, ncr), (dr, npad_r, exp_r)]
        hz = [(dz, npad_z, -exp_z), (dz, ncz), (dz, npad_z, exp_z)]

        # A value of 1 is used to define the discretization in phi for this case.
        mesh_cyl = discretize.CylMesh([hr, 1, hz], x0="00C")

        indtopoCC = active_from_xyz(mesh_cyl,
                                    topo3D,
                                    grid_reference="CC",
                                    method="nearest")
        indtopoN = active_from_xyz(mesh_cyl,
                                   topo3D,
                                   grid_reference="N",
                                   method="nearest")

        self.assertEqual(indtopoCC.sum(), 183)
        self.assertEqual(indtopoN.sum(), 171)

        htheta = meshTensor([(1.0, 4)])
        htheta = htheta * 2 * np.pi / htheta.sum()

        mesh_cyl2 = discretize.CylMesh([hr, htheta, hz], x0="00C")
        with self.assertRaises(NotImplementedError):
            indtopoCC = active_from_xyz(mesh_cyl2,
                                        topo3D,
                                        grid_reference="CC",
                                        method="nearest")
예제 #9
0
octree_levels = [8, 4]

# Create tiles
local_indices = [rxLoc[:, 0] <= 0, rxLoc[:, 0] > 0]
local_surveys = []
local_meshes = []
for local_index in local_indices:

    receivers = gravity.receivers.Point(rxLoc[local_index, :])
    srcField = gravity.sources.SourceField([receivers])
    local_survey = gravity.survey.Survey(srcField)

    # Create a local mesh that covers all points, but refined on the local survey
    local_mesh = mesh_builder_xyz(topo,
                                  h,
                                  padding_distance=padDist,
                                  depth_core=100,
                                  mesh_type="tree")
    local_mesh = refine_tree_xyz(
        local_mesh,
        local_survey.receiver_locations,
        method="surface",
        octree_levels=octree_levels,
        finalize=True,
    )

    local_surveys.append(local_survey)
    local_meshes.append(local_mesh)

###############################################################################
# Global Mesh
# Here, we create a TreeMesh with base cell size of 5 m. We created a small
# utility function to center the mesh around points and to figure out the
# outermost dimension for adequate padding distance.
# The second stage allows us to refine the mesh around points or surfaces
# (point assumed to follow some horizontal trend)
# The refinement process is repeated twice to allow for a finer level around
# the survey locations.
#

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

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

###########################################################################
# A simple function to plot vectors in TreeMesh
#
예제 #11
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
            ],
        )
예제 #12
0
    def setUp(self):
        # We will assume a vertical inducing field
        H0 = (50000.0, 90.0, 0.0)

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

        # Block with an effective susceptibility
        chi_e = 0.05

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

        # Create an 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)) + 10

        # Create a MAGsurvey
        rxLoc = np.c_[mkvc(X.T), mkvc(Y.T), mkvc(Z.T)]
        rxList = magnetics.receivers.Point(rxLoc)
        srcField = magnetics.sources.SourceField(receiver_list=[rxList],
                                                 parameters=H0)
        survey = magnetics.survey.Survey(srcField)

        ###############################################################################
        # Inversion Mesh

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

        mesh = mesh_builder_xyz(rxLoc,
                                h,
                                padding_distance=padDist,
                                depth_core=100,
                                mesh_type="tree")
        mesh = refine_tree_xyz(mesh,
                               topo,
                               method="surface",
                               octree_levels=[4, 4],
                               finalize=True)

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

        # Convert the inclination declination to vector in Cartesian
        M_xyz = utils.mat_utils.dip_azimuth2cartesian(
            np.ones(nC) * M[0],
            np.ones(nC) * 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 value, inducing field strength will
        # be applied in by the :class:`SimPEG.PF.Magnetics` problem
        model = np.zeros(mesh.nC)
        model[ind] = chi_e

        # Remove air cells
        model = model[actv]

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

        # Create the forward model operator
        simulation = magnetics.Simulation3DIntegral(
            survey=survey,
            mesh=mesh,
            chiMap=idenMap,
            actInd=actv,
            store_sensitivities="forward_only",
        )
        simulation.M = M_xyz

        # Compute some data and add some random noise
        synthetic_data = simulation.dpred(model)

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

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

        # Assigne data and uncertainties to the survey
        data_object = data.Data(survey, dobs=synthetic_data, noise_floor=wd)

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

        # Get the active cells for equivalent source is the top only
        surf = utils.model_utils.surface_layer_index(mesh, topo)
        nC = np.count_nonzero(surf)  # Number of active cells
        mstart = np.ones(nC) * 1e-4

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

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

        # Create static map
        simulation = magnetics.simulation.Simulation3DIntegral(
            mesh=mesh,
            survey=survey,
            chiMap=idenMap,
            actInd=surf,
            store_sensitivities="ram",
        )
        simulation.model = mstart

        # Create a regularization function, in this case l2l2
        reg = regularization.Sparse(mesh,
                                    indActive=surf,
                                    mapping=maps.IdentityMap(nP=nC),
                                    alpha_z=0)
        reg.mref = np.zeros(nC)

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

        # Define misfit function (obs-calc)
        dmis = data_misfit.L2DataMisfit(simulation=simulation,
                                        data=data_object)

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

        # Specify how the initial beta is found
        betaest = directives.BetaEstimate_ByEig(beta0_ratio=2)

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

        # Run the equivalent source inversion
        print("Solving for Equivalent Source")
        mrec = inv.run(mstart)

        ########################################################
        # Forward Amplitude Data
        # ----------------------
        #
        # Now that we have an equialent source layer, we can forward model alh three
        # components of the field and add them up: :math:`|B| = \sqrt{( Bx^2 + Bx^2 + Bx^2 )}`
        #

        rxList = magnetics.receivers.Point(rxLoc,
                                           components=["bx", "by", "bz"])
        srcField = magnetics.sources.SourceField(receiver_list=[rxList],
                                                 parameters=H0)
        surveyAmp = magnetics.survey.Survey(srcField)

        simulation = magnetics.simulation.Simulation3DIntegral(
            mesh=mesh,
            survey=surveyAmp,
            chiMap=idenMap,
            actInd=surf,
            is_amplitude_data=True,
            store_sensitivities="forward_only",
        )

        bAmp = simulation.fields(mrec)

        ######################################################################
        # Amplitude Inversion
        # -------------------
        #
        # Now that we have amplitude data, we can invert for an effective
        # susceptibility. This is a non-linear inversion.
        #

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

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

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

        # Create the forward model operator
        simulation = magnetics.simulation.Simulation3DIntegral(
            survey=surveyAmp,
            mesh=mesh,
            chiMap=idenMap,
            actInd=actv,
            is_amplitude_data=True,
        )

        data_obj = data.Data(survey, dobs=bAmp, noise_floor=wd)

        # Create a sparse regularization
        reg = regularization.Sparse(mesh, indActive=actv, mapping=idenMap)
        reg.norms = np.c_[1, 0, 0, 0]
        reg.mref = np.zeros(nC)

        # Data misfit function
        dmis = data_misfit.L2DataMisfit(simulation=simulation, data=data_obj)

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

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

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

        # Specify the sparse norms
        IRLS = directives.Update_IRLS(
            max_irls_iterations=5,
            f_min_change=1e-3,
            minGNiter=1,
            coolingRate=1,
            beta_search=False,
        )

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

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

        self.mstart = mstart
        self.model = model
        self.sim = simulation
예제 #13
0
    def test_active_from_xyz(self):

        # Create 3D topo
        [xx, yy] = np.meshgrid(np.linspace(-200, 200, 50), np.linspace(-200, 200, 50))
        b = 50
        A = 50
        zz = A * np.exp(-0.5 * ((xx / b) ** 2. + (yy / b) ** 2.))

        h = [5., 5., 5.]

        # Test 1D Mesh
        topo1D = zz[25, :].ravel()
        mesh1D = discretize.TensorMesh(
            [np.ones(10) * 20],
            x0='C'
        )

        indtopoCC = active_from_xyz(mesh1D, topo1D, grid_reference='CC', method='nearest')
        indtopoN = active_from_xyz(mesh1D, topo1D, grid_reference='N', method='nearest')

        self.assertEqual(indtopoCC.sum(), 3)
        self.assertEqual(indtopoN.sum(), 2)

        # Test 2D Tensor mesh
        topo2D = np.c_[xx[25, :].ravel(), zz[25, :].ravel()]

        mesh_tensor = discretize.TensorMesh([
            [(h[0], 24)],
            [(h[1], 20)]
        ],
            x0='CC')

        indtopoCC = active_from_xyz(mesh_tensor, topo2D, grid_reference='CC', method='nearest')
        indtopoN = active_from_xyz(mesh_tensor, topo2D, grid_reference='N', method='nearest')

        self.assertEqual(indtopoCC.sum(), 434)
        self.assertEqual(indtopoN.sum(), 412)

        # Test 2D Tree mesh
        mesh_tree = mesh_builder_xyz(topo2D, h[:2], mesh_type='TREE')
        mesh_tree = refine_tree_xyz(
            mesh_tree, topo2D,
            method="surface",
            octree_levels=[1],
            octree_levels_padding=None,
            finalize=True
        )
        indtopoCC = active_from_xyz(mesh_tree, topo2D, grid_reference='CC', method='nearest')
        indtopoN = active_from_xyz(mesh_tree, topo2D, grid_reference='N', method='nearest')

        self.assertEqual(indtopoCC.sum(), 167)
        self.assertEqual(indtopoN.sum(), 119)

        # Test 3D Tensor meshes
        topo3D = np.c_[xx.ravel(), yy.ravel(), zz.ravel()]

        mesh_tensor = discretize.TensorMesh([
            [(h[0], 24)],
            [(h[1], 20)],
            [(h[2], 30)]
        ],
            x0='CCC')

        indtopoCC = active_from_xyz(mesh_tensor, topo3D, grid_reference='CC', method='nearest')
        indtopoN = active_from_xyz(mesh_tensor, topo3D, grid_reference='N', method='nearest')

        self.assertEqual(indtopoCC.sum(), 10496)
        self.assertEqual(indtopoN.sum(), 10084)

        # Test 3D Tree mesh
        mesh_tree = mesh_builder_xyz(topo3D, h, mesh_type='TREE')
        mesh_tree = refine_tree_xyz(
            mesh_tree, topo3D,
            method="surface",
            octree_levels=[1],
            octree_levels_padding=None,
            finalize=True
        )
        indtopoCC = active_from_xyz(mesh_tree, topo3D, grid_reference='CC', method='nearest')
        indtopoN = active_from_xyz(mesh_tree, topo3D, grid_reference='N', method='nearest')

        self.assertEqual(indtopoCC.sum(), 6299)
        self.assertEqual(indtopoN.sum(), 4639)

        # Test 3D CYL Mesh
        ncr = 10  # number of mesh cells in r
        ncz = 15  # number of mesh cells in z
        dr = 15  # cell width r
        dz = 10  # cell width z
        npad_r = 4  # number of padding cells in r
        npad_z = 4  # number of padding cells in z
        exp_r = 1.25  # expansion rate of padding cells in r
        exp_z = 1.25  # expansion rate of padding cells in z

        hr = [(dr, ncr), (dr, npad_r, exp_r)]
        hz = [(dz, npad_z, -exp_z), (dz, ncz), (dz, npad_z, exp_z)]

        # A value of 1 is used to define the discretization in phi for this case.
        mesh_cyl = discretize.CylMesh([hr, 1, hz], x0='00C')

        indtopoCC = active_from_xyz(mesh_cyl, topo3D, grid_reference='CC', method='nearest')
        indtopoN = active_from_xyz(mesh_cyl, topo3D, grid_reference='N', method='nearest')

        self.assertEqual(indtopoCC.sum(), 183)
        self.assertEqual(indtopoN.sum(), 171)

        htheta = meshTensor([(1., 4)])
        htheta = htheta * 2*np.pi / htheta.sum()

        mesh_cyl2 = discretize.CylMesh([hr, htheta, hz], x0='00C')
        with self.assertRaises(NotImplementedError):
            indtopoCC = active_from_xyz(mesh_cyl2, topo3D, grid_reference='CC', method='nearest')

        def gridIt(h): return [np.cumsum(np.r_[0, x]) for x in h]

        X, Y = ndgrid(gridIt([[5.]*24, [5.]*20]), vector=False)

        mesh_curvi = discretize.CurvilinearMesh([X, Y])
        with self.assertRaises(TypeError):
            indTopoCC = active_from_xyz(mesh_curvi, topo3D, grid_reference='CC', method='nearest')