def generate_hom_world_with_inclusion(world_dim: list, incl_start: list,
                                      incl_dim: list):
    """ Creates a homogeneous world with inclusion.

    Utility function to create a homogeneous world with an inclusion. Region markers are set to 1 for the background
    world and 2 for the inclusion.

    Parameter:
        world_dim: World dimensions as [x,z].
        incl_start: Inclusion upper left corner as [x,z].
        incl_dim: Inclusion dimension as [x,z].

    Returns:
        The created world.
    """
    # Create geometric objects
    world = mt.createWorld(start=[0, 0], end=[world_dim[0], -world_dim[1]])
    inclusion = mt.createRectangle(
        start=incl_start,
        end=[incl_start[0] + incl_dim[0], incl_start[1] - incl_dim[1]],
        marker=2,
        boundaryMarker=10)
    # Merge geometries
    geom = mt.mergePLC([world, inclusion])
    return geom
def get_fwd_mesh():
    """Generate the forward mesh (with embedded anomalies)"""
    scheme = get_scheme()

    # Mesh generation
    world = mt.createWorld(
        start=[-55, 0], end=[105, -80], worldMarker=True)

    conductive_anomaly = mt.createCircle(
        pos=[10, -7], radius=5, marker=2
    )

    polarizable_anomaly = mt.createCircle(
        pos=[40, -7], radius=5, marker=3
    )

    plc = mt.mergePLC((world, conductive_anomaly, polarizable_anomaly))

    # local refinement of mesh near electrodes
    for s in scheme.sensors():
        plc.createNode(s + [0.0, -0.2])

    mesh_coarse = mt.createMesh(plc, quality=33)
    mesh = mesh_coarse.createH2()
    return mesh
Exemplo n.º 3
0
def simulateSynth(model, tMax=5000, satSteps=150, ertSteps=10, area=0.1,
                  synthPath='synth/'):
    """Create synthetic example."""

    if not os.path.exists('synth/'):
        os.mkdir(synthPath)

    world = mt.createWorld(start=[-20, 0], end=[20, -16], layers=[-2, -8],
                           worldMarker=False)
    for i, b in enumerate(world.boundaries()):
        b.setMarker(i + 1)

    block = mt.createRectangle(start=[-6, -3.5], end=[6, -6.0], marker=4,
                               boundaryMarker=11, area=area)
    geom = mt.mergePLC([world, block])
    geom.save(synthPath + 'synthGeom')
    # pg.show(geom, boundaryMarker=1)

    paraMesh = pg.meshtools.createMesh(geom, quality=32, area=area,
                                       smooth=[1, 10])

    # translate 1 2 3 4 - > 0 1 2 3
    mapMarker = np.array([0, 0, 1, 2, 3], 'float')
    paraMesh.setCellMarkers(mapMarker[np.array(paraMesh.cellMarkers())])
    paraMesh.save(synthPath + 'synth.bms')

    fop = HydroGeophysicalModelling(mesh=paraMesh, tMax=tMax,
                                    satSteps=satSteps,
                                    ertSteps=ertSteps,
                                    verbose=1)

    # openblas have some problems with to high thread count ..
    # we need to dig into
    print("ThreadCount:", pg.threadCount())
    pg.setThreadCount(4)

    print('##### Simulate synthetic data ' + '#'*50)
    pg.tic()
    rhoaR = fop.response(pg.RVector(model)[paraMesh.cellMarkers()])
    pg.toc()
    print('#'*100)

    # add some noise here
    rand = pg.RVector(len(rhoaR))
    pg.randn(rand)

    rhoaR *= (1.0 + rand * fop.ws.derr.flatten())
    fop.ws.rhoaR = rhoaR.reshape(fop.ws.derr.shape)

    # fop.ws.mesh.save(synthPath + 'synth.bms')
    np.save(synthPath + 'synthK', fop.ws.k)
    np.save(synthPath + 'synthVel', fop.ws.vel)
    np.save(synthPath + 'synthSat', fop.ws.sat)

    fop.ws.scheme.save(synthPath + 'synth.shm', 'a b m n')
    np.save(synthPath + 'synthRhoaRatio', fop.ws.rhoaR)
    np.save(synthPath + 'synthRhoa', fop.ws.rhoa)
    np.save(synthPath + 'synthErr', fop.ws.derr)
Exemplo n.º 4
0
    def test_appendTriangleBoundary(self):
        geom = mt.createWorld(start=[-10, 0], end=[10, -10], layers=[-5, -10])
        mesh = mt.createMesh(geom, area=1)

        mesh2 = mt.appendTriangleBoundary(mesh, marker=0)

        # test if boundary markers are preserved
        np.testing.assert_array_equal(
            pg.unique(pg.sort(mesh2.boundaryMarkers())), [-2, -1, 0, 2, 7, 8])
Exemplo n.º 5
0
    def dummySolve(self, info):
        world = mt.createWorld(start=[-10, 0], end=[10, -10],
                                   marker=1, worldMarker=False)
        c1 = mt.createCircle(pos=[0.0, -5.0], radius=3.0, area=.1, marker=2)
        mesh = pg.meshtools.createMesh([world, c1], quality=34.3)

        u = pg.solver.solveFiniteElements(mesh, a=[[1, 100], [2, 1]],
                                              bc={'Dirichlet': [[4, 1.0],
                                                                [2, 0.0]]})
        print(info, mesh)
Exemplo n.º 6
0
def testShowVariants():
    # Create geometry definition for the modelling domain
    world = mt.createWorld(start=[-10, 0], end=[10, -16],
                        layers=[-8], worldMarker=False)

    # Create a heterogeneous block
    block = mt.createRectangle(start=[-6, -3.5], end=[6, -6.0],
                            marker=4,  boundaryMarker=10, area=0.1)

    circ = mt.createCircle(pos=[0, -11], radius=2, boundaryMarker=11, isHole=True)

    # Merge geometrical entities
    geom = world + block + circ
    mesh = mt.createMesh(geom)

    fig, axs = plt.subplots(3,5)

    pg.show(geom, ax=axs[0][0])
    axs[0][0].set_title('plc, (default)')
    pg.show(geom, fillRegion=False, ax=axs[0][1])
    axs[0][1].set_title('plc, fillRegion=False')
    pg.show(geom, showBoundary=False, ax=axs[0][2])
    axs[0][2].set_title('plc, showBoundary=False')
    pg.show(geom, markers=True, ax=axs[0][3])
    axs[0][3].set_title('plc, markers=True')
    pg.show(mesh, ax=axs[0][4], showBoundary=False)
    axs[0][4].set_title('mesh, showBoundary=False')

    pg.show(mesh, ax=axs[1][0])
    axs[1][0].set_title('mesh, (default)')
    pg.show(mesh, mesh.cellMarkers(), label='Cell markers', ax=axs[1][1])
    axs[1][1].set_title('mesh, cells, (default)')
    pg.show(mesh, markers=True, ax=axs[1][2])
    axs[1][2].set_title('mesh, cells, markers=True')
    pg.show(mesh, mesh.cellMarkers(), label='Cell markers', showMesh=True, ax=axs[1][3])
    axs[1][3].set_title('mesh, cells, showMesh=True')
    pg.show(mesh, mesh.cellMarkers(), label='Cell markers', showBoundary=False, ax=axs[1][4])
    axs[1][4].set_title('mesh, cells, showBoundary=False')

    pg.show(mesh, pg.x(mesh), label='Nodes (x)', ax=axs[2][0])
    axs[2][0].set_title('mesh, nodes, (default)')
    pg.show(mesh, pg.x(mesh), label='Nodes (x)', showMesh=True, ax=axs[2][1])
    axs[2][1].set_title('mesh, nodes, showMesh=True')
    pg.show(mesh, pg.x(mesh), label='Nodes (x)', showBoundary=True, ax=axs[2][2])
    axs[2][2].set_title('mesh, nodes, showBoundary=True')
    pg.show(mesh, pg.y(mesh.cellCenters()), label='Cell center (y)',
            tri=True, shading='flat', ax=axs[2][3])
    axs[2][3].set_title('mesh, cells, tri=True, shading=flat')
    pg.show(mesh, pg.y(mesh.cellCenters()), label='Cell center (y)',
            tri=True, shading='gouraud', ax=axs[2][4])
    axs[2][4].set_title('mesh, cells, tri=True, shading=gouraud')
    ##pg.show(mesh, mesh.cellMarker(), label(markers), axs[1][1])
    axs[2][4].figure.tight_layout()
Exemplo n.º 7
0
def testCBarLevels():
    """
    Expectations
    ------------
    axs[0, 0]: show regions with plc
        Show needs to deliver the regions with Set3 colormap. Each tick on the
        colobar should be in the middle of the related color section.

    axs[1, 0]: show regions with mesh
        really the same thing as on axs[0, 0] but with mesh.

    ax[0, 1]: show mesh with cell data
        if nLevs is given i would expect that the colormap then is levelled.
        currently that is not the fact. but at least its the full range. labels
        need to be at begin/end of each color section.

    ax[1, 1]: show mesh with node data
        the colorbar range misses parts of its full range. labels need to be
        at begin/end of each color section.
    """
    # create a geometry
    world = mt.createWorld(start=[-10, 0],
                           end=[10, -16],
                           layers=[-8],
                           worldMarker=False)

    block = mt.createRectangle(start=[-6, -3.5],
                               end=[6, -6.0],
                               marker=4,
                               boundaryMarker=10,
                               area=0.1)

    circ = mt.createCircle(pos=[0, -11], marker=5, radius=2, boundaryMarker=11)

    poly = mt.mergePLC([world, block, circ])
    mesh = mt.createMesh(poly, quality=34)

    # create random data
    rhomap = [[1, 10], [2, 4], [4, 20], [5, 8]]
    # map data to cell/node count
    cell_data = pg.solver.parseArgToArray(rhomap, mesh.cellCount(), mesh)
    node_data = mt.cellDataToNodeData(mesh, cell_data)

    # plot everything
    fig, axs = pg.plt.subplots(2, 2, figsize=(20, 10))

    pg.show(poly, ax=axs[0, 0])

    pg.show(mesh, ax=axs[1, 0], markers=True)

    pg.show(mesh, cell_data, ax=axs[0, 1], colorBar=True, nLevs=7)

    pg.show(mesh, node_data, ax=axs[1, 1], colorBar=True, nLevs=7)
def plot_fwd_model(axes):
    """This function plots the forward model used to generate the data

    """
    # Mesh generation
    world = mt.createWorld(
        start=[-55, 0], end=[105, -80], worldMarker=True)

    conductive_anomaly = mt.createCircle(
        pos=[10, -7], radius=5, marker=2
    )

    polarizable_anomaly = mt.createCircle(
        pos=[40, -7], radius=5, marker=3
    )

    plc = mt.mergePLC((world, conductive_anomaly, polarizable_anomaly))

    # local refinement of mesh near electrodes
    for s in scheme.sensors():
        plc.createNode(s + [0.0, -0.2])

    mesh_coarse = mt.createMesh(plc, quality=33)
    mesh = mesh_coarse.createH2()

    rhomap = [
        [1, pg.utils.complex.toComplex(100, 0 / 1000)],
        # Magnitude: 50 ohm m, Phase: -50 mrad
        [2, pg.utils.complex.toComplex(50, 0 / 1000)],
        [3, pg.utils.complex.toComplex(100, -50 / 1000)],
    ]

    rho = pg.solver.parseArgToArray(rhomap, mesh.cellCount(), mesh)
    pg.show(
        mesh,
        data=np.log(np.abs(rho)),
        ax=axes[0],
        label=r"$log_{10}(|\rho|~[\Omega m])$"
    )
    pg.show(mesh, data=np.abs(rho), ax=axes[1], label=r"$|\rho|~[\Omega m]$")
    pg.show(
        mesh, data=np.arctan2(np.imag(rho), np.real(rho)) * 1000,
        ax=axes[2],
        label=r"$\phi$ [mrad]",
        cMap='jet_r'
    )
    fig.tight_layout()
    fig.show()
def generate_layered_world_with_inclusion(world_dim: list, layer_heights: list,
                                          incl_start: list, incl_dim: list):
    """ Creates a layered world with inclusion.

    Utility function to create a layered world with an inclusion. Region markers are starting at 1 and increasing with
    depth. The inclusion has the highest marker number.

    Parameter:
        world_dim: World dimensions as [x,z].
        layer_heights: Heights of the single layers.
        incl_start: Inclusion upper left corner as [x,z].
        incl_dim: Inclusion dimension as [x,z].

    Returns:
        The created world.
    """
    # Check parameter integrity
    if sum(layer_heights) > world_dim[1]:
        return None
    # Create geometric objects
    world = mt.createWorld(start=[0, 0], end=[world_dim[0], -world_dim[1]])
    current_depth = 0
    layers = []
    for i in range(len(layer_heights)):
        layer = mt.createRectangle(
            start=[0, -current_depth],
            end=[world_dim[0], -(current_depth + layer_heights[i])],
            marker=i + 1,
            boundaryMarker=10)
        current_depth += layer_heights[i]
        layers.append(layer)
    if current_depth != world_dim[1]:
        layer = mt.createRectangle(start=[0, -current_depth],
                                   end=[world_dim[0], -world_dim[1]],
                                   marker=i + 2,
                                   boundaryMarker=10)
        layers.append(layer)
    inclusion = mt.createRectangle(
        start=incl_start,
        end=[incl_start[0] + incl_dim[0], incl_start[1] - incl_dim[1]],
        marker=len(layers) + 1,
        boundaryMarker=10)
    # Merge geometries
    geom = mt.mergePLC([world, inclusion] + layers)
    return geom
Exemplo n.º 10
0
def create_geometry(position=0, depth=3, radius=4):
    elecs = np.linspace(-25, 25, 15)  # x coordinate of the electrodes
    # Create geometry definition for the modelling domain.
    # worldMarker=True indicates the default boundary conditions for the ERT
    world = mt.createWorld(start=[-50, 0], end=[50, -50], worldMarker=True)

    # Create a circular heterogeneous body
    block = mt.createCircle(pos=[position, -depth],
                            radius=radius,
                            marker=2,
                            boundaryMarker=0,
                            area=5)

    # Merge geometry definition into a Piecewise Linear Complex (PLC)
    geom = mt.mergePLC([world, block])
    fig, ax = plt.subplots(figsize=(10, 6))
    pg.show(geom, ax=ax, hold=True)
    ax.plot(elecs, np.zeros_like(elecs), "kv")
    ax.set_ylim(-20, 0)
    return geom
def generate_tiled_world(world_dim: list, tile_size: list):
    """ Creates a tiled layered world.

    Utility function to create a tiled layered world. Region marker 1 is upper left corner.

    Parameter:
        world_dim: World dimensions as [x,z].
        tile_size: Tile dimensions as [x,z].

    Returns:
        The created world.
    """
    # Create world
    world = mt.createWorld(start=[0, 0], end=[world_dim[0], -world_dim[1]])
    # Create tile counts
    n_tiles_x = int(np.ceil(world_dim[0] / tile_size[0]))
    n_tiles_y = int(np.ceil(world_dim[1] / tile_size[1]))
    # Create and merge tiles
    for j in range(n_tiles_y):
        for i in range(n_tiles_x):
            x_start = int(i * tile_size[0])
            x_end = int((i + 1) * tile_size[0])
            y_start = int(-j * tile_size[1])
            y_end = int(-(j + 1) * tile_size[1])
            if x_end > world_dim[0]:
                x_end = world_dim[0]
            if y_end < -world_dim[1]:
                y_end = -world_dim[1]
            marker = 1
            if ((-1)**i) * ((-1)**j) < 0:
                marker = 2
            tile = mt.createRectangle(start=[x_start, y_start],
                                      end=[x_end, y_end],
                                      marker=marker,
                                      boundaryMarker=10)
            world = mt.mergePLC([world, tile])
    return world
def generate_layered_world(world_dim: list, layer_heights: list):
    """ Creates a layered world.

    Utility function to create a layered world. Region markers are starting at 1 and increasing with depth.

    Parameter:
        world_dim: World dimensions as [x,z].
        layer_heights: Heights of the single layers.

    Returns:
        The created world.
    """
    # Check parameter integrity
    if sum(layer_heights) > world_dim[1]:
        return None
    # Create geometric objects
    world = mt.createWorld(start=[0, 0], end=[world_dim[0], -world_dim[1]])
    current_depth = 0
    layers = []
    for i in range(len(layer_heights)):
        layer = mt.createRectangle(
            start=[0, -current_depth],
            end=[world_dim[0], -(current_depth + layer_heights[i])],
            marker=i + 1,
            boundaryMarker=10)
        current_depth += layer_heights[i]
        layers.append(layer)
    if current_depth != world_dim[1]:
        layer = mt.createRectangle(start=[0, -current_depth],
                                   end=[world_dim[0], -world_dim[1]],
                                   marker=i + 2,
                                   boundaryMarker=10)
        layers.append(layer)
    # Merge geometries
    geom = mt.mergePLC([world] + layers)
    return geom
def generate_dipped_layered_world(world_dim: list, layer_borders: list,
                                  dipping_angle: float):
    """ Creates a dipped layered world.

    Utility function to create a dipped layered world. Region markers are increasing with depth.

    Parameter:
        world_dim: World dimensions as [x,z].
        layer_borders: List of layer borders at world X = 0.
        dipping_angle: Angle at which the layers are dipping. Value describing counter-clockwise angle.

    Returns:
        The created world.
    """

    # Nested function to find the index to add a specific node
    def get_insert_index(nodes, node):
        i = 0
        # Get edge starting index
        while (i < len(nodes)) and (nodes[i][3] < node[3]):
            i = i + 1
        edge_start = i
        # Get edge ending index
        while (i < len(nodes)) and (nodes[i][3] <= node[3]):
            i = i + 1
        edge_end = i
        # Check for input error
        if (node[3] == 0) or (node[3] == 2) or (node[3] == 4) or (node[3]
                                                                  == 6):
            print('Function can only be used for non-default edges (1,3,5,7)')
            return -1
        # Find index based on specific edge
        i = edge_start
        if node[3] == 1:
            while (i < edge_end) and (node[1] > nodes[i][1]):
                i = i + 1
        if node[3] == 3:
            while (i < edge_end) and (node[2] < nodes[i][2]):
                i = i + 1
        if node[3] == 5:
            while (i < edge_end) and (node[1] < nodes[i][1]):
                i = i + 1
        if node[3] == 7:
            while (i < edge_end) and (node[2] > nodes[i][2]):
                i = i + 1
        return i

    # Nested function to find the connecting node of a given node
    def get_connecting_node(nodes_list, node, node_connections_list):
        for i in range(len(node_connections_list)):
            if node_connections_list[i][0] == nodes_list[node][0]:
                for j in range(len(nodes_list)):
                    if node_connections_list[i][1] == nodes_list[j][0]:
                        return j
        return -1

    # Nested function to find the next node on the world border
    def get_next_node(nodes_list, current_node):
        if current_node >= len(nodes_list) - 1:
            return 0
        else:
            return current_node + 1

    # Nested function to create a polygon from a set of nodes
    def get_polygon_from_nodes(node_set):
        vertices = []
        for i in range(len(node_set)):
            vertices.append([node_set[i][1], node_set[i][2]])
        return vertices

    # Correct angle
    while dipping_angle > 180:
        dipping_angle -= 360
    while dipping_angle < -180:
        dipping_angle += 360
    # Create background world
    world = mt.createWorld(start=[0, 0],
                           end=[world_dim[0], -world_dim[1]],
                           worldMarker=True)
    # Remove layers out of world scope
    removed_indices = 0
    for i in range(len(layer_borders)):
        if (dipping_angle >= 0 and layer_borders[i - removed_indices] > 0) or (
                dipping_angle <= 0
                and layer_borders[i - removed_indices] < -world_dim[1]):
            layer_borders.pop(i - removed_indices)
            removed_indices = removed_indices + 1
    # Compute layer height difference based on dipping angle
    dipping_diff = world_dim[0] * math.tan(dipping_angle / 180 * math.pi)
    # Compute nodes on world border (id,x,y,edge)
    nodes = [[0, 0, 0, 0], [1, world_dim[0], 0, 2],
             [2, world_dim[0], -world_dim[1], 4], [3, 0, -world_dim[1], 6]]
    node_connections = []
    next_id = 4
    for i in range(len(layer_borders)):
        # Find starting node
        if layer_borders[i] <= 0 and layer_borders[i] >= -world_dim[1]:
            # Layer starts at left world border (default case)
            start_node = [next_id, 0, layer_borders[i], 7]
        else:
            if layer_borders[i] > 0:
                # Layer starts above world
                x = layer_borders[i] * math.tan(
                    (90 + dipping_angle) * math.pi / 180)
                start_node = [next_id, x, 0, 1]
            else:
                # Layer starts below world
                x = -(layer_borders[i] + world_dim[1]) * math.tan(
                    (90 - dipping_angle) * math.pi / 180)
                start_node = [next_id, x, -world_dim[1], 5]
        nodes.insert(get_insert_index(nodes, start_node), start_node)
        next_id = next_id + 1
        # Find ending node
        if layer_borders[i] + dipping_diff <= 0 and layer_borders[
                i] + dipping_diff >= -world_dim[1]:
            # Layer ends at right world border (default case)
            end_node = [
                next_id, world_dim[0], layer_borders[i] + dipping_diff, 3
            ]
        else:
            if layer_borders[i] + dipping_diff > 0:
                # Layer ends above world
                x = -layer_borders[i] / math.tan(dipping_angle / 180 * math.pi)
                end_node = [next_id, x, 0, 1]
            else:
                # Layer ends below world
                x = world_dim[0] - (layer_borders[i] + dipping_diff +
                                    world_dim[1]) / math.tan(
                                        dipping_angle / 180 * math.pi)
                end_node = [next_id, x, -world_dim[1], 5]
        nodes.insert(get_insert_index(nodes, end_node), end_node)
        next_id = next_id + 1
        # Save node connections
        node_connections.append([start_node[0], end_node[0]])
        node_connections.append([end_node[0], start_node[0]])
    # Compute polygons from nodes
    polygons = []
    first_node = 0
    edge_to_finish = 4
    if dipping_angle < 0:
        for i in range(len(nodes)):
            if nodes[i][3] == 2:
                break
        first_node = i
        edge_to_finish = 6
    while edge_to_finish != -1:
        polygon = []
        last_node_was_connected = False
        has_connected_nodes = False
        current_node_index = first_node
        polygon.append(nodes[first_node])
        while (len(polygon) == 1) or (polygon[len(polygon) - 1] != polygon[0]):
            if (last_node_was_connected
                    == False) and (len(polygon) != 1) and (get_connecting_node(
                        nodes, current_node_index, node_connections) != -1):
                current_node_index = get_connecting_node(
                    nodes, current_node_index, node_connections)
                polygon.append(nodes[current_node_index])
                last_node_was_connected = True
                has_connected_nodes = True
                if nodes[current_node_index][3] == edge_to_finish:
                    edge_to_finish = -1
                continue
            current_node_index = get_next_node(nodes, current_node_index)
            polygon.append(nodes[current_node_index])
            if not has_connected_nodes:
                first_node = current_node_index
            last_node_was_connected = False
            if nodes[current_node_index][3] == edge_to_finish:
                edge_to_finish = -1
        polygons.append(polygon[:-1])
    # Merge geometries
    for i in range(len(polygons)):
        poly = mt.createPolygon(get_polygon_from_nodes(polygons[i]),
                                marker=i + 1,
                                isClosed=True)
        world = mt.mergePLC([world, poly])
    return world
scheme = ert.createERTData(
    elecs=np.linspace(start=0, stop=50, num=51),
    schemeName='dd'
)
# Not strictly required, but we switch potential electrodes to yield positive
# geometric factors. Note that this was also done for the synthetic data
# inverted later.
m = scheme['m']
n = scheme['n']
scheme['m'] = n
scheme['n'] = m
scheme.set('k', [1 for x in range(scheme.size())])

###############################################################################
# Mesh generation for the inversion
world = mt.createWorld(
    start=[-15, 0], end=[65, -30], worldMarker=False, marker=2)

# local refinement of mesh near electrodes
for s in scheme.sensors():
    world.createNode(s + [0.0, -0.4])

mesh_coarse = mt.createMesh(world, quality=33)
mesh = mesh_coarse.createH2()
for nr, c in enumerate(mesh.cells()):
    c.setMarker(nr)
pg.show(mesh)
###############################################################################
# Define start model of the inversion
# [magnitude, phase]
start_model = np.ones(mesh.cellCount()) * pg.utils.complex.toComplex(
    80, -0.01 / 1000)
measurements = np.array((
    [0, 3, 6, 9],  # Dipole-Dipole
    [0, 9, 3, 6],  # Wenner
    [0, 9, 4, 5]   # Schlumberger
))

for i, elec in enumerate("abmn"):
    scheme[elec] = measurements[:,i]

scheme["k"] = ert.createGeometricFactors(scheme)

###############################################################################
# Now we set up a 2D mesh.

world = mt.createWorld(start=[0, 0], end=[30, -10], worldMarker=True)
for pos in scheme.sensorPositions():
    world.createNode(pos)

mesh = mt.createMesh(world, area=.05, quality=33, marker=1)

###############################################################################
# As a last step we invoke the ERT manager and calculate the Jacobian for a
# homogeneous half-space.

fop = ert.ERTModelling()
fop.setData(scheme)
fop.setMesh(mesh)

model = np.ones(mesh.cellCount())
fop.createJacobian(model)
#parametros inversion

quality = 34.5
maxCellArea = 1
robustData = True
paraDX = 0.25
lam = 20

#PARAMETROS MODELADO

noise = 0
rhomap = [[0, 500], [1, 50], [2, 100], [3, 2000]]
#CREACION MODELO GENERAL

background = mt.createWorld(start=[-10, 0], end=[81, -20], area=1, marker=0)

pol0 = mt.createPolygon([[-10, -2.5], [27.5, -2.5], [30, 0], [-10, 0]],
                        isClosed=True,
                        marker=1)
pol1 = mt.createPolygon([[-10, -20], [10, -20], [27.5, -2.5], [-10, -2.5]],
                        isClosed=True,
                        marker=2)
pol2 = mt.createPolygon([[60, 0], [65, 0], [45, -20], [40, -20]],
                        isClosed=True,
                        marker=3)

world = mt.mergePLC([background, pol0, pol1, pol2])
mesh = mt.createMesh(world, quality=33, area=0.1, smooth=[1, 2])

#EXPORTACION DATOS DE RESISTIVIDAD DEL MODELO (VECTOR)
Exemplo n.º 17
0
def simulateSynth(model,
                  tMax=5000,
                  satSteps=150,
                  ertSteps=10,
                  area=0.1,
                  synthPath='synth/'):
    """Create synthetic example."""

    if not os.path.exists('synth/'):
        os.mkdir(synthPath)

    world = mt.createWorld(start=[-20, 0],
                           end=[20, -16],
                           layers=[-2, -8],
                           worldMarker=False)
    for i, b in enumerate(world.boundaries()):
        b.setMarker(i + 1)

    block = mt.createRectangle(start=[-6, -3.5],
                               end=[6, -6.0],
                               marker=4,
                               boundaryMarker=11,
                               area=area)
    geom = mt.mergePLC([world, block])
    geom.save(synthPath + 'synthGeom')
    # pg.show(geom, boundaryMarker=1)

    paraMesh = pg.meshtools.createMesh(geom,
                                       quality=32,
                                       area=area,
                                       smooth=[1, 10])

    # translate 1 2 3 4 - > 0 1 2 3
    mapMarker = np.array([0, 0, 1, 2, 3], 'float')
    paraMesh.setCellMarkers(mapMarker[np.array(paraMesh.cellMarkers())])
    paraMesh.save(synthPath + 'synth.bms')

    fop = HydroGeophysicalModelling(mesh=paraMesh,
                                    tMax=tMax,
                                    satSteps=satSteps,
                                    ertSteps=ertSteps,
                                    verbose=1)

    # openblas have some problems with to high thread count ..
    # we need to dig into
    print("TC", pg.threadCount())
    pg.setThreadCount(4)

    print('##### Simulate synthetic data ' + '#' * 50)
    pg.tic()
    rhoaR = fop.response(pg.RVector(model)[paraMesh.cellMarkers()])
    pg.toc()
    print('#' * 100)

    # add some noise here
    rand = pg.RVector(len(rhoaR))
    pg.randn(rand)

    rhoaR *= (1.0 + rand * fop.ws.derr.flatten())
    fop.ws.rhoaR = rhoaR.reshape(fop.ws.derr.shape)

    # fop.ws.mesh.save(synthPath + 'synth.bms')
    np.save(synthPath + 'synthK', fop.ws.k)
    np.save(synthPath + 'synthVel', fop.ws.vel)
    np.save(synthPath + 'synthSat', fop.ws.sat)

    fop.ws.scheme.save(synthPath + 'synth.shm', 'a b m n')
    np.save(synthPath + 'synthRhoaRatio', fop.ws.rhoaR)
    np.save(synthPath + 'synthRhoa', fop.ws.rhoa)
    np.save(synthPath + 'synthErr', fop.ws.derr)
Exemplo n.º 18
0
# *-* coding: utf-8 *-*
# test some characteristics of ERTManager.simulate:
# 1) for complex conductivity models the response should not depend on the sign
#    of the K-factor

if False: # deactivated due to pybert dependency
    import pybert as pb
# import pygimli as pg
    import pygimli.meshtools as mt
    import numpy as np

    world = mt.createWorld(
        start=[-50, 0], end=[50, -50], layers=[-1, -5], worldMarker=True)

    scheme = pb.DataContainerERT()
    elec_positions = [
        [-2, 0, 0],
        [-1, 0, 0],
        [0, 0, 0],
        [1, 0, 0],
        [2, 0, 0],
    ]
    for x, y, z in elec_positions:
        scheme.createSensor((x, y, z))

# Define number of measurements
    scheme.resize(3)

# first two measurements have reversed geometric factor!
    scheme.set('a', [0, 0, 3])
    scheme.set('b', [1, 1, 2])
Exemplo n.º 19
0
###############################################################################
# Analytical solution first
gz_a = gradUCylinderHoriz(pnts, radius, dRho, pos)[:, 1]

###############################################################################
# Integration for a 2D polygon after :cite:`WonBev1987`
circ = createCircle([0, -depth],
                    radius=radius,
                    marker=2,
                    area=0.1,
                    nSegments=16)
gz_p = solveGravimetry(circ, dRho, pnts, complete=False)

###############################################################################
# Integration for complete 2D mesh after :cite:`WonBev1987`
world = createWorld(start=[-20, 0], end=[20, -10], marker=1)
mesh = createMesh([world, circ])
dRhoC = pg.solver.parseMapToCellArray([[1, 0.0], [2, dRho]], mesh)
gc_m = solveGravimetry(mesh, dRhoC, pnts)

###############################################################################
# Finite Element solution for :math:`u`
world = createWorld(start=[-200, 200], end=[200, -200], marker=1)

# Add some nodes to the measurement points to increase the accuracy a bit
[world.createNode(x_, 0.0, 1) for x_ in x]
plc = world + circ
mesh = createMesh(plc, quality=34)
mesh = mesh.createP2()

density = pg.solver.parseMapToCellArray([[1, 0.0], [2, dRho]], mesh)
Exemplo n.º 20
0
from pygimli.physics.ert import VESModelling, VESCModelling
# from pygimli.physics.ert import createERTData

###############################################################################
# First we create a data configuration of a 1D Schlumberger sounding with
# 20 electrodes and and increasing MN/2 electrode spacing from 1m to 24m.
scheme = ert.createData(pg.utils.grange(start=1, end=24, dx=1, n=10, log=True),
                        sounding=True)

###############################################################################
# First we create a geometry that covers the sought geometry.
# We start with a 2 dimensional simulation world
# of a bounding box [-200, -100] [200, 0], the layer at -5m and some suitable
# requested cell sizes.
plc = mt.createWorld(start=[-200, -100],
                     end=[200, 0],
                     layers=[-10],
                     area=[5.0, 500])

###############################################################################
# To achieve a necessary numerical accuracy, we need some local mesh refinement
# in the vicinity of the electrodes. However, since we don't need the
# electrode (aka sensor) positions to be present as nodes in the geometry, we only add forced mesh
# nodes near the electrode positions, right below the earths surface.
for s in scheme.sensors():
    plc.createNode(s + [0.0, -0.2])

# Now we can create our forward modeling mesh.
mesh = mt.createMesh(plc, quality=33)

pg.show(mesh, data=mesh.cellMarkers(), label='Marker', showMesh=True)
Exemplo n.º 21
0
#!/usr/bin/env python
import numpy as np

import pygimli as pg
import pygimli.meshtools as plc

import pybert as pb
from pybert.sip import SIPdata

# Create geometry definition for the modelling domain
world = plc.createWorld(start=[-50, 0],
                        end=[50, -50],
                        layers=[-1, -5],
                        worldMarker=True)
# Create some heterogeneous circle
block = plc.createCircle(pos=[0, -3.],
                         radius=1,
                         marker=4,
                         boundaryMarker=10,
                         area=0.1)
# Merge geometry definition
geom = plc.mergePLC([world, block])
# create measuring scheme (data container without data)
scheme = pb.createData(elecs=np.linspace(-10, 10, 21), schemeName='dd')
for pos in scheme.sensorPositions():  # put all electrodes (sensors) into geom
    geom.createNode(pos, marker=-99)  # just a historic convention
    geom.createNode(pos + pg.RVector3(0, -0.1))  # refine with 10cm

# pg.show(geom, boundaryMarker=1)
mesh = plc.createMesh(geom)
# pg.show(mesh)
Exemplo n.º 22
0
x = np.arange(-20, 20.1, .5)
pnts = np.array([x, np.zeros(len(x))]).T

###############################################################################
# Analytical solution first
gz_a = gradUCylinderHoriz(pnts, radius, dRho, pos)[:, 1]

###############################################################################
# Integration for a 2D polygon after :cite:`WonBev1987`
circ = createCircle([0, -depth], radius=radius, marker=2, area=0.1,
                    segments=16)
gz_p = solveGravimetry(circ, dRho, pnts, complete=False)

###############################################################################
# Integration for complete 2D mesh after :cite:`WonBev1987`
world = createWorld(start=[-20, 0], end=[20, -10], marker=1)
mesh = createMesh([world, circ])
dRhoC = pg.solver.parseMapToCellArray([[1, 0.0], [2, dRho]], mesh)
gc_m = solveGravimetry(mesh, dRhoC, pnts)

###############################################################################
# Finite Element solution for :math:`u`
world = createWorld(start=[-200, 200], end=[200, -200], marker=1)

# Add some nodes to the measurement points to increase the accuracy a bit
[world.createNode(x_, 0.0,  1) for x_ in x]
plc = mergePLC([world, circ])
mesh = createMesh(plc, quality=34)
mesh = mesh.createP2()

density = pg.solver.parseMapToCellArray([[1, 0.0], [2, dRho]], mesh)
lam = 20
paraDX = 0.25
#creación grid para comparación

grid = pg.createGrid(x=pg.utils.grange(start=0.20, end=0.5, n=500),
                     y=-pg.utils.grange(0, 0.12, n=250, log=False))

grid2 = pg.createGrid(x=pg.utils.grange(start=0.33, end=0.35, n=500),
                      y=-pg.utils.grange(0.04, 0.06, n=250, log=False))

square = mt.createRectangle(start=[0.33, -0.04], end=[0.35, -0.06])

#MODELO

rhomap = [[1, 150], [0, 3000]]
background = mt.createWorld(start=[-1, 0], end=[1, -1], area=1, marker=1)
circle = mt.createCircle(pos=[0.34, -0.05], radius=0.01, marker=0)
world = mt.mergePLC([background, circle])
mesh = mt.createMesh(world, quality=33, area=0.1, smooth=[1, 2])

res_model = pg.solver.parseArgToArray(rhomap, mesh.cellCount(), mesh)

#INTERPOLACIÓN MODELO A GRID

nan = 99.9
model_vector_nn = []
for pos in grid.cellCenters():
    cell = mesh.findCell(pos)
    if cell:
        model_vector_nn.append(res_model[cell.id()])
    else:
def analyticalSolution2Layer(x, zlay=25, v1=1000, v2=3000):
    """Analytical solution for 2 layer case."""
    tdirect = np.abs(x) / v1  # direct wave
    alfa = asin(v1 / v2)  # critically refracted wave angle
    xreflec = tan(alfa) * zlay * 2.  # first critically refracted
    trefrac = (x - xreflec) / v2 + xreflec * v2 / v1**2
    return np.minimum(tdirect, trefrac)


###############################################################################
# Vertical gradient model
# -----------------------
# We first create an unstructured mesh:

sensors = np.arange(131, step=10.0)
plc = mt.createWorld([-20, -60], [150, 0], worldMarker=False)
for pos in sensors:
    plc.createNode([pos, 0.0])
mesh_gradient = mt.createMesh(plc, quality=33, area=3)

###############################################################################
# A vertical gradient model, i.e. :math:`v(z) = a + bz`, is defined per cell.

a = 1000
b = 100

vel_gradient = []
for node in mesh_gradient.nodes():
    vel_gradient.append(a + b * abs(node.y()))
vel_gradient = pg.meshtools.nodeDataToCellData(mesh_gradient,
                                               np.array(vel_gradient))
Exemplo n.º 25
0
CorERTBack = 1
ertSchemeFull = 0
# SimName='M' + 'SoilR' + str(SoilR) + 'AnoR' + str(AnoRstr) +  'Cert' + str(CorERTBack==1)  + 'ERTscheme' + str(ertSchemeFull==1)
SimName = 'M' + 'SoilR' + str(SoilR) + 'AnoR' + str(AnoRstr) + 'Cert' + str(
    CorERTBack == 1) + 'ERTscheme' + str(ertSchemeFull == 1)

path_Figures = PathSimu_salt + '/Sens/' + SimName + '/Figures/'
if not os.path.exists(path_Figures):
    os.makedirs(path_Figures)

path_Data = PathSimu_salt + '/Sens/' + SimName + '/Data/'
if not os.path.exists(path_Data):
    os.makedirs(path_Data)

# Create geometry definition for the modelling domain
world = mt.createWorld(start=[-20, 0], end=[20, -16], worldMarker=False)
# Create a heterogeneous block
block = mt.createRectangle(start=[-5, -2.5],
                           end=[5, -5.0],
                           marker=4,
                           boundaryMarker=10,
                           area=0.1)
# block = mt.createRectangle(start=[-5, -5], end=[5, -7.5],
#                             marker=4,  boundaryMarker=10, area=0.1)
# Merge geometrical entities
# geom = mt.mergePLC([world, block])
geom = mt.mergePLC([world, block])

pg.show(geom, boundaryMarker=True, savefig='geometry.pdf')

# Create a mesh from the geometry definition
Exemplo n.º 26
0
# -*- coding: utf-8 -*-
"""Simplistic version a complete ERT Modelling->Inversion example."""
''' Ci mette circa 3 min a compilare tutto '''

import pybert as pb
import pygimli as pg
import pygimli.meshtools as mt
import matplotlib.pylab as pl

# Create geometry definition for the modelling domain.
# worldMarker=True indicates the default boundary conditions for the ERT
world = mt.createWorld(start=[0, 0],
                       end=[86, -20],
                       layers=[-2, -6],
                       worldMarker=True)

c1 = mt.createCircle(pos=[53.5, -2.0], radius=1.0, marker=4)

# Merge geometry definition into a Piecewise Linear Complex (PLC)
geom = mt.mergePLC([world, c1])

# Optional: show the geometry
#pg.show(geom)

# Create a Dipole Dipole ('dd') measuring scheme with n electrodes.
scheme = pb.createData(elecs=pg.utils.grange(start=0, end=86, n=43),
                       schemeName='dd')

simulData = pg.createERTData(scheme, schemeName='dd')
# Put all electrodes (aka. sensors positions) into the PLC to enforce mesh
# refinement. Due to experience known, its convenient to add further refinement
Exemplo n.º 27
0
import matplotlib.pyplot as plt

#plt.xkcd()

import pygimli as pg
import pygimli.meshtools as mt

# Create geometry definition for the modeling domain
world = mt.createWorld(start=[-10, 0],
                       end=[10, -16],
                       layers=[-8],
                       worldMarker=False)

# Create a heterogeneous block
block = mt.createRectangle(start=[-6, -3.5],
                           end=[6, -6.0],
                           marker=4,
                           boundaryMarker=10,
                           area=0.1)

circ = mt.createCircle(pos=[0, -11], radius=2, boundaryMarker=11, isHole=True)

# Merge geometrical entities
geom = mt.mergePLC([world, block, circ])
mesh = mt.createMesh(geom)

fig, axs = plt.subplots(3, 5)

pg.show(geom, ax=axs[0][0])
axs[0][0].set_title('plc, (default)')
pg.show(geom, fillRegion=False, ax=axs[0][1])
Exemplo n.º 28
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Minimal example of using pygimli to simulate the steady heat equation.
"""

import pygimli as pg
import pygimli.meshtools as mt

# Create geometry definition for the modelling domain
world = mt.createWorld(start=[-20, 0], end=[20, -16], layers=[-2, -8],
                       worldMarker=False)
# Create a heterogeneous block
block = mt.createRectangle(start=[-6, -3.5], end=[6, -6.0],
                           marker=4,  boundaryMarker=10, area=0.1)
# Merge geometrical entities
geom = mt.mergePLC([world, block])
pg.show(geom, boundaryMarker=True, savefig='geometry.pdf')

# Create a mesh from the geometry definition
mesh = mt.createMesh(geom, quality=33, area=0.2, smooth=[1, 10])
pg.show(mesh, savefig='mesh.pdf')

# $\diverg(a\grad T)=0$ with $T(bottom)=1$, $T(top)=0$
T = pg.solver.solveFiniteElements(mesh,
                                  a=[[1, 1.0], [2, 2.0], [3, 3.0], [4, 0.1]],
                                  uB=[[8, 1.0], [4, 0.0]], verbose=True)

ax, _ = pg.show(mesh, data=T, label='Temperature $T$', cmap="hot_r",
                showBoundary=True, savefig='T_field.pdf')
Exemplo n.º 29
0
import pygimli.physics.ert as ert

###############################################################################
# Create a measurement scheme for 51 electrodes, spacing 1
scheme = ert.createERTData(elecs=np.linspace(start=0, stop=50, num=51),
                           schemeName='dd')
m = scheme['m']
n = scheme['n']
scheme['m'] = n
scheme['n'] = m

scheme.set('k', [1 for x in range(scheme.size())])

###############################################################################
# Mesh generation
world = mt.createWorld(start=[-55, 0], end=[105, -80], worldMarker=True)

conductive_anomaly = mt.createCircle(pos=[10, -7], radius=5, marker=2)

polarizable_anomaly = mt.createCircle(pos=[40, -7], radius=5, marker=3)

plc = mt.mergePLC((world, conductive_anomaly, polarizable_anomaly))

# local refinement of mesh near electrodes
for s in scheme.sensors():
    plc.createNode(s + [0.0, -0.2])

mesh_coarse = mt.createMesh(plc, quality=33)
# additional refinements
mesh = mesh_coarse.createH2()
def analyticalSolution2Layer(x, zlay=25, v1=1000, v2=3000):
    """Analytical solution for 2 layer case."""
    tdirect = np.abs(x) / v1  # direct wave
    alfa = asin(v1 / v2)  # critically refracted wave angle
    xreflec = tan(alfa) * zlay * 2.  # first critically refracted
    trefrac = (x - xreflec) / v2 + xreflec * v2 / v1**2
    return np.minimum(tdirect, trefrac)


###############################################################################
# Vertical gradient model
# -----------------------
# We first create an unstructured mesh:

sensors = np.arange(131, step=10.0)
plc = mt.createWorld([-20, -60], [150, 0], worldMarker=False)
for pos in sensors:
    plc.createNode([pos, 0.0])
mesh_gradient = mt.createMesh(plc, quality=33, area=3)

###############################################################################
# A vertical gradient model, i.e. :math:`v(z) = a + bz`, is defined per cell.

a = 1000
b = 100

vel_gradient = []
for node in mesh_gradient.nodes():
    vel_gradient.append(a + b * abs(node.y()))
vel_gradient = pg.meshtools.nodeDataToCellData(mesh_gradient,
                                               np.array(vel_gradient))