Пример #1
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
Пример #2
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))

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

        self.mesh = mesh
        self.jtv = jtv
        self.x0 = np.random.rand(len(mesh) * 2)
Пример #3
0
def make_example_mesh():

    # Base mesh parameters
    dh = 5.0  # base cell size
    nbc = 32  # total width of mesh in terms of number of base mesh cells
    h = dh * np.ones(nbc)

    mesh = TreeMesh([h, h, h], x0="CCC")

    # Refine to largest possible cell size
    mesh.refine(3, finalize=False)

    return mesh
Пример #4
0
def baseline_octree_mesh(N, delta):
    """
    Set up a basic regular Cartesian octree mesh as a default; this can then
    be refined once we specify model features or voxelizations, so it is NOT
    currently finalized
    :param N: length of one edge of a cubical volume in cells
    :param delta: length of one edge of a mesh cube
    :return: TreeMesh instance
    """
    h = delta * np.ones(N)
    mesh = TreeMesh([h, h, h], x0="CCC")
    mesh.refine(3, finalize=False)
    return mesh
Пример #5
0
def create_octree_mesh(domain, cellwidth, points, method='surface'):
    """Creates an octree mesh and refines at specified points.

        Parameters
        ----------
        domain : tuple
            ((xmin, xmax),(ymin, ymax),(zmin, zmax)) coordinates of the domain
        cellwidth : int
            width of smallest cell in the mesh
        points : np.ndarray
            array of points that will be refined in the mesh
        method : string
            the discretize method that will be used for refinement. Available are 'surface',
            'radial' and 'box'


        Returns
        -------
        discretize.mesh
            a mesh where the points are refined
    """

    # domain dimensions
    x_length = np.abs(domain[0][0] - domain[0][1])
    y_length = np.abs(domain[1][0] - domain[1][1])
    z_length = np.abs(domain[2][0] - domain[2][1])

    # number of cells needed in each dimension
    nbx = 2**int(np.ceil(np.log(x_length / cellwidth) / np.log(2.0)))
    nby = 2**int(np.ceil(np.log(y_length / cellwidth) / np.log(2.0)))
    nbz = 2**int(np.ceil(np.log(z_length / cellwidth) / np.log(2.0)))

    # define base mesh
    hx = cellwidth * np.ones(nbx)
    hy = cellwidth * np.ones(nby)
    hz = cellwidth * np.ones(nbz)
    mesh = TreeMesh([hx, hy, hz],
                    origin=[domain[0][0], domain[1][0], domain[2][0]])

    # refine mesh around the given surface points
    mesh = refine_tree_xyz(mesh,
                           points,
                           octree_levels=[1, 1, 1],
                           method=method,
                           max_distance=1,
                           finalize=False)

    return mesh
Пример #6
0
###############################################
# Basic Example
# -------------
#
# Here we demonstrate the basic two step process for creating a 2D tree mesh
# (QuadTree mesh). The region of highest discretization if defined within a
# rectangular box. We use the keyword argument *octree_levels* to define the
# rate of cell width increase outside the box.
#

dh = 5  # minimum cell width (base mesh cell width)
nbc = 64  # number of base mesh cells in x

# Define base mesh (domain and finest discretization)
h = dh * np.ones(nbc)
mesh = TreeMesh([h, h])

# Define corner points for rectangular box
xp, yp = np.meshgrid([120., 240.], [80., 160.])
xy = np.c_[mkvc(xp), mkvc(yp)]  # mkvc creates vectors

# Discretize to finest cell size within rectangular box
mesh = refine_tree_xyz(mesh,
                       xy,
                       octree_levels=[2, 2],
                       method='box',
                       finalize=False)

mesh.finalize()  # Must finalize tree mesh before use

mesh.plotGrid(show_it=True)
Пример #7
0
plt.close('all')
dx = 50  # minimum cell width (base mesh cell width) in x
dy = 50  # minimum cell width (base mesh cell width) in y

x_length = 30000.  # domain width in x
y_length = 30000.  # domain width in y

# Compute number of base mesh cells required in x and y
nbcx = 2**int(np.round(np.log(x_length / dx) / np.log(2.)))
nbcy = 2**int(np.round(np.log(y_length / dy) / np.log(2.)))

# Define the base mesh
hx = [(dx, nbcx)]
hy = [(dy, nbcy)]
M = TreeMesh([hx, hy], x0='CC')

# Refine mesh near points
xx = np.linspace(-10000, 10000, 3000)
yy = 400 * np.sin((2 * xx * np.pi) / 1000)
pts = np.c_[mkvc(xx), mkvc(yy)]
M = refine_tree_xyz(M,
                    pts,
                    octree_levels=[2, 2],
                    method='radial',
                    finalize=False)

M.finalize()
print("\n the mesh has {} cells".format(M))
ccMesh = M.gridCC
print('indices:', np.size(ccMesh))
Пример #8
0
dz = 50  # tamanho minimo da celula em z

x_length = 5000  # tamanho do dominio em x
y_length = 5000  # tamanho do dominio em y
z_length = 50000  # tamanho do dominio em z

# Compute number of base mesh cells required in x and y
nbcx = 2**int(np.round(np.log(x_length / dx) / np.log(2.)))
nbcy = 2**int(np.round(np.log(y_length / dy) / np.log(2.)))
nbcz = 2**int(np.round(np.log(z_length / dz) / np.log(2.)))

# Define the base mesh
hx = [(dx, nbcx)]
hy = [(dy, nbcy)]
hz = [(dz, nbcz)]
M = TreeMesh([hx, hy, hz], x0='CCC')

# # Refine surface topography
#[xx, yy] = np.meshgrid(M.vectorNx, M.vectorNy)
#[xx, yy,zz] = np.meshgrid([-5000,5000], [-5000,5000],[-100,100])
#zz = 0.*(xx**2 + yy**2)  - 1000.
##zz = np.zeros([300,300])
#pts = np.c_[mkvc(xx), mkvc(yy), mkvc(zz)]
#M = refine_tree_xyz(
#     M, pts, octree_levels=[1, 1], method='surface', finalize=False
#                   )

# Refine box
xp, yp, zp = np.meshgrid([-600., 600.], [-1000., 1000.], [300., -4000.])
xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)]
Пример #9
0
###############################################
# Basic Example
# -------------
#
# Here we demonstrate the basic two step process for creating a 2D tree mesh
# (QuadTree mesh). The region of highest discretization if defined within a
# rectangular box. We use the keyword argument *octree_levels* to define the
# rate of cell width increase outside the box.
#

dh = 5  # minimum cell width (base mesh cell width)
nbc = 64  # number of base mesh cells in x

# Define base mesh (domain and finest discretization)
h = dh * np.ones(nbc)
mesh = TreeMesh([h, h])

# Define corner points for rectangular box
xp, yp = np.meshgrid([120.0, 240.0], [80.0, 160.0])
xy = np.c_[mkvc(xp), mkvc(yp)]  # mkvc creates vectors

# Discretize to finest cell size within rectangular box
mesh = refine_tree_xyz(mesh,
                       xy,
                       octree_levels=[2, 2],
                       method="box",
                       finalize=False)

mesh.finalize()  # Must finalize tree mesh before use

mesh.plotGrid(show_it=True)
Пример #10
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
Пример #11
0
fig.show()

#########################################################
# Tree Mesh Divergence
# --------------------
#
# For a tree mesh, there needs to be special attention taken for the hanging
# faces to achieve second order convergence for the divergence operator.
# Although the divergence cannot be constructed through Kronecker product
# operations, the initial steps are exactly the same for calculating the
# stencil, volumes, and areas. This yields a divergence defined for every
# cell in the mesh using all faces. There is, however, redundant information
# when hanging faces are included.
#

mesh = TreeMesh([[(1, 16)], [(1, 16)]], levels=4)
mesh.insert_cells(np.array([5.0, 5.0]), np.array([3]))
mesh.number()

fig = plt.figure(figsize=(10, 10))

ax1 = fig.add_subplot(211)

mesh.plotGrid(centers=True, nodes=False, ax=ax1)
ax1.axis("off")
ax1.set_title("Simple QuadTree Mesh")
ax1.set_xlim([-1, 17])
ax1.set_ylim([-1, 17])

for ii, loc in zip(range(mesh.nC), mesh.gridCC):
    ax1.text(loc[0] + 0.2, loc[1], "{0:d}".format(ii), color="r")
Пример #12
0
# We chose to design a coarser mesh to decrease the run time.
# When designing a mesh to solve practical frequency domain problems:
#
#     - Your smallest cell size should be 10%-20% the size of your smallest skin depth
#     - The thickness of your padding needs to be 2-3 times biggest than your largest skin depth
#     - The skin depth is ~500*np.sqrt(rho/f)
#
#

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

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

# Mesh refinement based on topography
mesh = refine_tree_xyz(mesh,
                       xyz_topo,
                       octree_levels=[0, 0, 0, 1],
                       method="surface",
                       finalize=False)

# Mesh refinement near transmitters and receivers
mesh = refine_tree_xyz(mesh,
                       receiver_locations,
                       octree_levels=[2, 4],
                       method="radial",
                       finalize=False)
Пример #13
0
# sphinx_gallery_thumbnail_number = 4
dx = 10  # minimum cell width (base mesh cell width) in x
dy = 10  # minimum cell width (base mesh cell width) in y

x_length = 40000.  # domain width in x
y_length = 40000.  # domain width in y

# Compute number of base mesh cells required in x and y
nbcx = 2**int(np.round(np.log(x_length / dx) / np.log(2.)))
nbcy = 2**int(np.round(np.log(y_length / dy) / np.log(2.)))

# Define the base mesh
hx = [(dx, nbcx)]
hy = [(dy, nbcy)]
M = TreeMesh([hx, hy], x0=['C', -15000])

# definir camada
xx = M.vectorNx
yy = np.zeros(nbcx + 1)  #vetor linha(poderia ser uma função ou pontos)
pts = np.c_[matutils.mkvc(xx), matutils.mkvc(yy)]
M = meshutils.refine_tree_xyz(M,
                              pts,
                              octree_levels=[1, 1],
                              method='box',
                              finalize=False)

#definir um ponto(xc,yc) a ser refinado.
Raio_length = 500
xc = -5000
yc = 2200
Пример #14
0
 def setUp(self):
     mesh = TreeMesh([32, 32])
     mesh.refine_box([0.2, 0.2], [0.5, 0.8], 5)
     self.mesh = mesh
Пример #15
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  # 只保留磁场强度数据,删除后面的两个参数
Пример #16
0
    def set_mesh(
        self,
        topo=None,
        dx=None,
        dy=None,
        dz=None,
        corezlength=None,
        npad_x=None,
        npad_y=None,
        npad_z=None,
        pad_rate_x=None,
        pad_rate_y=None,
        pad_rate_z=None,
        ncell_per_dipole=None,
        mesh_type="TensorMesh",
        dimension=2,
        method="nearest",
    ):
        """
        Set up a mesh for a given DC survey
        """

        # Update properties
        if npad_x is None:
            npad_x = self.npad_x
        self.npad_x = npad_x

        if npad_z is None:
            npad_z = self.npad_z
        self.npad_z = npad_z

        if pad_rate_x is None:
            pad_rate_x = self.pad_rate_x
        self.pad_rate_x = pad_rate_x

        if pad_rate_z is None:
            pad_rate_z = self.pad_rate_z
        self.pad_rate_z = pad_rate_z

        if ncell_per_dipole is None:
            ncell_per_dipole = self.ncell_per_dipole
        self.ncell_per_dipole = ncell_per_dipole

        # 2D or 3D mesh
        if dimension not in [2, 3]:
            raise NotImplementedError(
                "Set mesh has not been implemented for a 1D system")

        if dimension == 2:
            z_ind = 1
        else:
            z_ind = 2
        a = abs(np.diff(np.sort(self.electrode_locations[:, 0]))).min()
        lineLength = abs(self.electrode_locations[:, 0].max() -
                         self.electrode_locations[:, 0].min())
        dx_ideal = a / ncell_per_dipole
        if dx is None:
            dx = dx_ideal
            print("dx is set to {} m (samllest electrode spacing ({}) / {})".
                  format(dx, a, ncell_per_dipole))
        if dz is None:
            dz = dx * 0.5
            print("dz ({} m) is set to dx ({} m) / {}".format(dz, dx, 2))
        if dimension == 3:
            if dy is None:
                print("dy is set equal to dx")
                dy = dx
            self.dy = dy

            if npad_y is None:
                npad_y = self.npad_y
            self.npad_y = npad_y

            if pad_rate_y is None:
                pad_rate_y = self.pad_rate_y
            self.pad_rate_y = pad_rate_y

        x0 = self.electrode_locations[:, 0].min()
        if topo is None:
            # For 2D mesh
            if dimension == 2:
                # sort by x
                row_idx = np.lexsort((self.electrode_locations[:, 0], ))
            # For 3D mesh
            else:
                # sort by x, then by y
                row_idx = np.lexsort(
                    (self.electrode_locations[:,
                                              1], self.electrode_locations[:,
                                                                           0]))
            locs = self.electrode_locations[row_idx, :]
        else:
            # For 2D mesh
            if dimension == 2:
                mask = np.isin(self.electrode_locations[:, 0], topo[:, 0])
                if np.any(mask):
                    warnings.warn(
                        "Because the x coordinates of some topo and electrodes are the same,"
                        " we excluded electrodes with the same coordinates.",
                        RuntimeWarning,
                    )
                locs_tmp = np.vstack(
                    (topo, self.electrode_locations[~mask, :]))
                row_idx = np.lexsort((locs_tmp[:, 0], ))
            else:
                dtype = [("x", np.float64), ("y", np.float64)]
                mask = np.isin(
                    self.electrode_locations[:, [0, 1]].copy().view(dtype),
                    topo[:, [0, 1]].copy().view(dtype),
                ).flatten()
                if np.any(mask):
                    warnings.warn(
                        "Because the x and y coordinates of some topo and electrodes are the same,"
                        " we excluded electrodes with the same coordinates.",
                        RuntimeWarning,
                    )
                locs_tmp = np.vstack(
                    (topo, self.electrode_locations[~mask, :]))
                row_idx = np.lexsort((locs_tmp[:, 1], locs_tmp[:, 0]))
            locs = locs_tmp[row_idx, :]

        if dx > dx_ideal:
            # warnings.warn(
            #     "Input dx ({}) is greater than expected \n We recommend using {:0.1e} m cells, that is, {} cells per {0.1e} m dipole length".format(dx, dx_ideal, ncell_per_dipole, a)
            # )
            pass

        # Set mesh properties to class instance
        self.dx = dx
        self.dz = dz

        zmax = locs[:, z_ind].max()
        zmin = locs[:, z_ind].min()

        # 3 cells each for buffer
        corexlength = lineLength + dx * 6
        if corezlength is None:
            dz_topo = locs[:, 1].max() - locs[:, 1].min()
            corezlength = self.grids[:, z_ind].max() + dz_topo
            self.corezlength = corezlength

        if mesh_type == "TensorMesh":
            ncx = np.round(corexlength / dx)
            ncz = np.round(corezlength / dz)
            hx = [(dx, npad_x, -pad_rate_x), (dx, ncx),
                  (dx, npad_x, pad_rate_x)]
            hz = [(dz, npad_z, -pad_rate_z), (dz, ncz)]
            x0_mesh = -(
                (dx * pad_rate_x**(np.arange(npad_x) + 1)).sum() + dx * 3 - x0)
            z0_mesh = (-(
                (dz * pad_rate_z**(np.arange(npad_z) + 1)).sum() + dz * ncz) +
                       zmax)

            # For 2D mesh
            if dimension == 2:
                h = [hx, hz]
                x0_for_mesh = [x0_mesh, z0_mesh]
                self.xyzlim = np.vstack(
                    (np.r_[x0, x0 + lineLength], np.r_[zmax - corezlength,
                                                       zmax]))
                fill_value = "extrapolate"

            # For 3D mesh
            else:

                ylocs = np.unique(self.electrode_locations[:, 1])
                ymin, ymax = ylocs.min(), ylocs.max()
                # 3 cells each for buffer in y-direction
                coreylength = ymax - ymin + dy * 6
                ncy = np.round(coreylength / dy)
                hy = [(dy, npad_y, -pad_rate_y), (dy, ncy),
                      (dy, npad_y, pad_rate_y)]
                y0 = ylocs.min() - dy / 2.0
                y0_mesh = -((dy * pad_rate_y**(np.arange(npad_y) + 1)).sum() +
                            dy * 3 - y0)

                h = [hx, hy, hz]
                x0_for_mesh = [x0_mesh, y0_mesh, z0_mesh]
                self.xyzlim = np.vstack((
                    np.r_[x0, x0 + lineLength],
                    np.r_[ymin - dy * 3, ymax + dy * 3],
                    np.r_[zmax - corezlength, zmax],
                ))
            mesh = TensorMesh(h, x0=x0_for_mesh)

        elif mesh_type == "TREE":
            # Quadtree mesh
            if dimension == 2:

                pad_length_x = np.sum(meshTensor([(dx, npad_x, pad_rate_x)]))
                pad_length_z = np.sum(meshTensor([(dz, npad_z, pad_rate_z)]))

                dom_width_x = lineLength + 2 * pad_length_x  # domain width x
                dom_width_z = corezlength + pad_length_z  # domain width z

                nbcx = 2**int(np.ceil(np.log(dom_width_x / dx) /
                                      np.log(2.0)))  # num. base cells x
                nbcz = 2**int(np.ceil(np.log(dom_width_z / dz) /
                                      np.log(2.0)))  # num. base cells z

                length = 0.0
                dz_tmp = dz
                octree_levels = []
                while length < corezlength:
                    length += 5 * dz_tmp
                    octree_levels.append(5)
                    dz_tmp *= 2

                # Define the base mesh
                hx = [(dx, nbcx)]
                hz = [(dz, nbcz)]

                mesh_width = np.sum(meshTensor(hx))
                mesh_height = np.sum(meshTensor(hz))

                array_midpoint = 0.5 * (self.electrode_locations[:, 0].min() +
                                        self.electrode_locations[:, 0].max())
                mesh = TreeMesh(
                    [hx, hz],
                    x0=[array_midpoint - mesh_width / 2, zmax - mesh_height])
                # mesh = TreeMesh([hx, hz], x0='CN')

                # Mesh refinement based on topography
                mesh = refine_tree_xyz(
                    mesh,
                    self.electrode_locations,
                    octree_levels=octree_levels,
                    method="radial",
                    finalize=False,
                )
                mesh.finalize()

                self.xyzlim = np.vstack((
                    np.r_[self.electrode_locations[:, 0].min(),
                          self.electrode_locations[:, 0].max(), ],
                    np.r_[zmax - corezlength, zmax],
                ))

            # Octree mesh
            elif dimension == 3:
                raise NotImplementedError(
                    "set_mesh has not implemented 3D TreeMesh (yet)")

        else:
            raise NotImplementedError(
                "set_mesh currently generates TensorMesh or TreeMesh")

        actind = surface2ind_topo(mesh, locs, method=method, fill_value=np.nan)

        return mesh, actind
Пример #17
0
dh = 25.0  # base cell width
dom_width_x = 6000.0  # domain width x
dom_width_y = 6000.0  # domain width y
dom_width_z = 4000.0  # domain width z
nbcx = 2**int(np.round(np.log(dom_width_x / dh) /
                       np.log(2.0)))  # num. base cells x
nbcy = 2**int(np.round(np.log(dom_width_y / dh) /
                       np.log(2.0)))  # num. base cells y
nbcz = 2**int(np.round(np.log(dom_width_z / dh) /
                       np.log(2.0)))  # num. base cells z

# Define the base mesh
hx = [(dh, nbcx)]
hy = [(dh, nbcy)]
hz = [(dh, nbcz)]
mesh = TreeMesh([hx, hy, hz], x0="CCN")

# Mesh refinement based on topography
k = np.sqrt(np.sum(topo_xyz[:, 0:2]**2, axis=1)) < 1200
mesh = refine_tree_xyz(mesh,
                       topo_xyz[k, :],
                       octree_levels=[0, 6, 8],
                       method="surface",
                       finalize=False)

# Mesh refinement near sources and receivers.
electrode_locations = np.r_[dc_data.survey.locations_a,
                            dc_data.survey.locations_b,
                            dc_data.survey.locations_m,
                            dc_data.survey.locations_n, ]
unique_locations = np.unique(electrode_locations, axis=0)
def plotVectorSectionsOctree(
    mesh,
    m,
    normal="X",
    ind=0,
    vmin=None,
    vmax=None,
    scale=1.0,
    vec="k",
    axs=None,
    actvMap=None,
    fill=True,
):
    """
    Plot section through a 3D tensor model
    """
    # plot recovered model
    normalInd = {"X": 0, "Y": 1, "Z": 2}[normal]
    antiNormalInd = {"X": [1, 2], "Y": [0, 2], "Z": [0, 1]}[normal]

    h2d = (mesh.h[antiNormalInd[0]], mesh.h[antiNormalInd[1]])
    x2d = (mesh.x0[antiNormalInd[0]], mesh.x0[antiNormalInd[1]])

    #: Size of the sliced dimension
    szSliceDim = len(mesh.h[normalInd])
    if ind is None:
        ind = int(szSliceDim // 2)

    cc_tensor = [None, None, None]
    for i in range(3):
        cc_tensor[i] = np.cumsum(np.r_[mesh.x0[i], mesh.h[i]])
        cc_tensor[i] = (cc_tensor[i][1:] + cc_tensor[i][:-1]) * 0.5
    slice_loc = cc_tensor[normalInd][ind]

    # Create a temporary TreeMesh with the slice through
    temp_mesh = TreeMesh(h2d, x2d)
    level_diff = mesh.max_level - temp_mesh.max_level

    XS = [None, None, None]
    XS[antiNormalInd[0]], XS[antiNormalInd[1]] = np.meshgrid(
        cc_tensor[antiNormalInd[0]], cc_tensor[antiNormalInd[1]])
    XS[normalInd] = np.ones_like(XS[antiNormalInd[0]]) * slice_loc
    loc_grid = np.c_[XS[0].reshape(-1), XS[1].reshape(-1), XS[2].reshape(-1)]
    inds = np.unique(mesh._get_containing_cell_indexes(loc_grid))

    grid2d = mesh.gridCC[inds][:, antiNormalInd]
    levels = mesh._cell_levels_by_indexes(inds) - level_diff
    temp_mesh.insert_cells(grid2d, levels)
    tm_gridboost = np.empty((temp_mesh.nC, 3))
    tm_gridboost[:, antiNormalInd] = temp_mesh.gridCC
    tm_gridboost[:, normalInd] = slice_loc

    # Interpolate values to mesh.gridCC if not 'CC'
    mx = actvMap * m[:, 0]
    my = actvMap * m[:, 1]
    mz = actvMap * m[:, 2]

    m = np.c_[mx, my, mz]

    # Interpolate values from mesh.gridCC to grid2d
    ind_3d_to_2d = mesh._get_containing_cell_indexes(tm_gridboost)
    v2d = m[ind_3d_to_2d, :]
    amp = np.sum(v2d**2.0, axis=1)**0.5

    if axs is None:
        axs = plt.subplot(111)

    if fill:
        temp_mesh.plotImage(amp, ax=axs, clim=[vmin, vmax], grid=True)

    axs.quiver(
        temp_mesh.gridCC[:, 0],
        temp_mesh.gridCC[:, 1],
        v2d[:, antiNormalInd[0]],
        v2d[:, antiNormalInd[1]],
        pivot="mid",
        scale_units="inches",
        scale=scale,
        linewidths=(1, ),
        edgecolors=(vec),
        headaxislength=0.1,
        headwidth=10,
        headlength=30,
    )