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
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)
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])
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)
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()
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
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)
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)
# *-* 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])
############################################################################### # 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)
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)
#!/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)
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))
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
# -*- 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
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])
#!/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')
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))