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 createSynthModel(): """Return the modelling mesh, the porosity distribution and the parametric mesh for inversion. """ # Create the synthetic model world = mt.createCircle(boundaryMarker=-1, nSegments=64) tri = mt.createPolygon([[-0.8, -0], [-0.5, -0.7], [0.7, 0.5]], isClosed=True, area=0.0015) c1 = mt.createCircle(radius=0.2, pos=[-0.2, 0.5], nSegments=32, area=0.0025, marker=3) c2 = mt.createCircle(radius=0.2, pos=[0.32, -0.3], nSegments=32, area=0.0025, marker=3) poly = mt.mergePLC([world, tri, c1, c2]) poly.addRegionMarker([0.0, 0, 0], 1, area=0.0015) poly.addRegionMarker([-0.9, 0, 0], 2, area=0.0015) c = mt.createCircle(radius=0.99, nSegments=16, start=np.pi, end=np.pi*3) [poly.createNode(p.pos(), -99) for p in c.nodes()] mesh = pg.meshtools.createMesh(poly, q=34.4, smooth=[1, 10]) mesh.scale(1.0/5.0) mesh.rotate([0., 0., 3.1415/3]) mesh.rotate([0., 0., 3.1415]) petro = pg.solver.parseArgToArray([[1, 0.9], [2, 0.6], [3, 0.3]], mesh.cellCount(), mesh) # Create the parametric mesh that only reflect the domain geometry world = mt.createCircle(boundaryMarker=-1, nSegments=32, area=0.0051) paraMesh = pg.meshtools.createMesh(world, q=34.0, smooth=[1, 10]) paraMesh.scale(1.0/5.0) return mesh, paraMesh, petro
def createSynthModel(): """Return the modeling mesh, the porosity distribution and the parametric mesh for inversion. """ # Create the synthetic model world = mt.createCircle(boundaryMarker=-1, segments=64) tri = mt.createPolygon([[-0.8, -0], [-0.5, -0.7], [0.7, 0.5]], isClosed=True, area=0.0015) c1 = mt.createCircle(radius=0.2, pos=[-0.2, 0.5], segments=32, area=0.0025, marker=3) c2 = mt.createCircle(radius=0.2, pos=[0.32, -0.3], segments=32, area=0.0025, marker=3) poly = mt.mergePLC([world, tri, c1, c2]) poly.addRegionMarker([0.0, 0, 0], 1, area=0.0015) poly.addRegionMarker([-0.9, 0, 0], 2, area=0.0015) c = mt.createCircle(radius=0.99, segments=16, start=np.pi, end=np.pi*3) [poly.createNode(p.pos(), -99) for p in c.nodes()] mesh = pg.meshtools.createMesh(poly, q=34.4, smooth=[1, 10]) mesh.scale(1.0/5.0) mesh.rotate([0., 0., 3.1415/3]) mesh.rotate([0., 0., 3.1415]) petro = pg.solver.parseArgToArray([[1, 0.9], [2, 0.6], [3, 0.3]], mesh.cellCount(), mesh) # Create the parametric mesh that only reflects the domain geometry world = mt.createCircle(boundaryMarker=-1, segments=32, area=0.0051) paraMesh = pg.meshtools.createMesh(world, q=34.0, smooth=[1, 10]) paraMesh.scale(1.0/5.0) return mesh, paraMesh, petro
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 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
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$',
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) res_model = pg.solver.parseArgToArray(rhomap, mesh.cellCount(), mesh) pg.show(mesh, res_model) #INTERPOLACION DATOS MODELO A MESH INVERSION nan = 99.9 model_vector = [] for pos in grid.cellCenters(): cell = mesh.findCell(pos) if cell:
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)
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) u = pg.solver.solve(mesh, a=1, f=density, uB=[[-2, 0], [-1, 0]]) ############################################################################### # Calculate gradient of gravimetric potential # :math:`\frac{\partial u}{\partial (x,z)}` dudz = np.zeros(len(pnts)) for i, p in enumerate(pnts): c = mesh.findCell(p) g = c.grad(p, u) dudz[i] = -g[1] * 4. * np.pi * pg.physics.constants.GmGal # why 4 pi here?
depth = -np.arange(sensor_spacing, bh_length + sensor_spacing, sensor_spacing) sensors = np.zeros((len(depth) * 2, 2)) # two boreholes sensors[len(depth):, 0] = bh_spacing # x sensors[:, 1] = np.hstack([depth] * 2) # y ################################################################################ # Traveltime calculations work on unstructured meshes and structured grids. We # demonstrate this here by simulating the synthetic data on an unstructured mesh # and inverting it on a simple structured grid. # Create forward model and mesh c0 = mt.createCircle(pos=(7.0, -10.0), radius=3, segments=25, marker=1) c1 = mt.createCircle(pos=(12.0, -18.0), radius=4, segments=25, marker=2) geom = mt.mergePLC([world, c0, c1]) for sen in sensors: geom.createNode(sen) mesh_fwd = mt.createMesh(geom, quality=34, area=.25) model = np.array([2000., 2300, 1700])[mesh_fwd.cellMarkers()] pg.show(mesh_fwd, model, label="Velocity (m/s)", nLevs=3, logScale=False) ################################################################################ # Create inversion mesh refinement = 0.25 x = np.arange(0, bh_spacing + refinement, sensor_spacing * refinement) y = -np.arange(0.0, bh_length + 3, sensor_spacing * refinement) mesh = pg.createMesh2D(x, y) ax, _ = pg.show(mesh, hold=True)
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) scheme = pb.createData(elecs=np.linspace(-10, 10, 21), schemeName='dd') # dumm, 1.S 2.S 3.S Body rhovec = np.array([0, 100.0, 50.0, 10.0, 100]) # ohm m tauvec = np.array([0, 1e-3, 1e-3, 0.1, 1.0]) # s mvec = np.array([0.001, 0.01, 0.001, 0.5, 0.5]) # - [0-1]
area=1, marker=2) sup2 = mt.createPolygon([[40, 0], [81, 0], [81, -1.5], [38.8, -1.5]], isClosed=True, area=1, marker=4) sup3 = mt.createPolygon([[30, 0], [40, 0], [39.6, -0.5], [30.4, -0.5]], isClosed=True, area=1, marker=4) pol = mt.createPolygon([[30, 0], [40, 0], [38, -2.5], [32, -2.5]], isClosed=True, area=1, marker=0) square = mt.createRectangle(start=[34, -0.5], end=[36, -2.5], area=1, marker=3) world = mt.mergePLC([background, pol, square, sup, sup2, sup3]) 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: model_vector_nn.append(nan)
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]) 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')
#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: model_vector_nn.append(nan)
pos=[width / 2, width / 2, -depth / 2], marker=1, area=75) #, boundaryMarker=0) for i, b in enumerate(world.boundaries()): # if worldMarker is True: if b.norm()[2] == 1.0: b.setMarker(pg.core.MARKER_BOUND_HOMOGEN_NEUMANN) else: b.setMarker(pg.core.MARKER_BOUND_MIXED) ano = mt.createCube(size=[widthAno, lengthAno, HAno], pos=[width / 2 + shift / 2, width / 2, depthAno], marker=4, area=0.01) plc = mt.mergePLC([world, ano]) # pg.show(plc) # pg.show(world) # plc.exportVTK('plc.vtk') maxA = np.array(ano.boundaryCenters()).max(axis=0) minA = np.array(ano.boundaryCenters()).min(axis=0) #%% n_sensors_surf = 16 * 16 sensors_surf = np.zeros((n_sensors_surf, 3)) # area = [-10.1,10.1,-10.1,10.1] area = [ minA[0] - widthAno * 2, maxA[0] + widthAno * 2, minA[0] - widthAno * 2,
import pygimli.meshtools as mt from pygimli.physics import Refraction ############################################################################### # We start by creating a three-layered slope (The model is taken from the BSc # thesis of Constanze Reinken (University of Bonn). layer1 = mt.createPolygon([[0.0, 137], [117.5, 164], [117.5, 162], [0.0, 135]], isClosed=True, marker=1, area=1) layer2 = mt.createPolygon([[0.0, 126], [0.0, 135], [117.5, 162], [117.5, 153]], isClosed=True, marker=2) layer3 = mt.createPolygon([[0.0, 110], [0.0, 126], [117.5, 153], [117.5, 110]], isClosed=True, marker=3) slope = (164 - 137) / 117.5 geom = mt.mergePLC([layer1, layer2, layer3]) mesh = mt.createMesh(geom, quality=34.3, area=3, smooth=[1, 10]) pg.show(mesh) ############################################################################### # Next we define geophone positions and a measurement scheme, which consists of # shot and receiver indices. numberGeophones = 48 sensors = np.linspace(0., 117.5, numberGeophones) scheme = pg.physics.traveltime.createRAData(sensors) # Adapt sensor positions to slope pos = np.array(scheme.sensorPositions()) for x in pos[:, 0]: i = np.where(pos[:, 0] == x)
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
# In this first part we naively combine objects and assign markers to them, # expecting two regions of concentric rings with markers 1 and 2. Note how the # outer ring is assigned the marker 0 in the figure, although we specified # marker=1 for the larger circle? A marker value of 0 is assigned to a region # if no region marker is found, indicating that the marker for the outer ring # was overwritten/ignored by the inner circle, which was added later. circle_outer = mt.createCircle(pos=[0.0, 0.0], radius=3.0, marker=1) circle_inner = mt.createCircle( pos=[0.0, 0.0], radius=1.0, # area=.3, boundaryMarker=0, marker=2) plc = mt.mergePLC([circle_outer, circle_inner]) ax, cb = pg.show(plc, markers=True) ############################################################################### # The solution to this problem is the region marker, which defines the marker # value of the region that it is placed in. By default all region markers are # assigned the position (0,0,0), thereby overwriting each other (see black dots # in figure below). If no region marker is present in a region, a marker value # of 0 is assigned. fig = ax.get_figure() for nr, marker in enumerate(plc.regionMarker()): print('Position marker number {}:'.format(nr + 1), marker.x(), marker.y(), marker.z()) ax.scatter(marker.x(), marker.y(), s=(2 - nr) * 30, color='k')
#PARAMETROS MODELADO noise=0 rhomap= [[0,100],[1,100],[2,200],[3,1000]] #CREACION MODELO GENERAL background=mt.createWorld(start=[-10,0],end=[81,-20], area=1,marker=0) pol0=mt.createPolygon([[-10,-2.5],[81,-2.5],[81,0],[-10,0]], isClosed=True,marker=1) pol1=mt.createPolygon([[-10,-15],[81,-15],[81,-2.5],[-10,-2.5]], isClosed=True,marker=2) circle1=mt.createCircle(pos=[25.5,-7.5],radius=2,isClosed=True, marker=3) circle2=mt.createCircle(pos=[45.5,-7.5],radius=2,isClosed=True, marker=3) circle3=mt.createCircle(pos=[35.5,-7.5],radius=2,isClosed=True,area=1, marker=3) world = mt.mergePLC([background,circle1,circle2,pol0,pol1]) mesh= mt.createMesh(world, quality=33, area=0.1,smooth=[1,2]) #EXPORTACION DATOS DE RESISTIVIDAD DEL MODELO (VECTOR) res_model=pg.solver.parseArgToArray(rhomap, mesh.cellCount(), mesh) pg.show(mesh,res_model) #INTERPOLACION DATOS MODELO A MESH INVERSION nan=99.9 model_vector = [] for pos in grid.cellCenters(): cell = mesh.findCell(pos) if cell:
# We start by creating a three-layered slope (The model is taken from the BSc # thesis of Constanze Reinken (University of Bonn). layer1 = mt.createPolygon([[0.0, 137], [117.5, 164], [117.5, 162], [0.0, 135]], isClosed=True, marker=1, area=1) layer2 = mt.createPolygon([[0.0, 126], [0.0, 135], [117.5, 162], [117.5, 153]], isClosed=True, marker=2) layer3 = mt.createPolygon([[0.0, 110], [0.0, 126], [117.5, 153], [117.5, 110]], isClosed=True, marker=3) slope = (164 - 137) / 117.5 geom = mt.mergePLC([layer1, layer2, layer3]) mesh = mt.createMesh(geom, quality=34.3, area=3, smooth=[1, 10]) pg.show(mesh) ############################################################################### # Next we define geophone positions and a measurement scheme, which consists of # shot and receiver indices. numberGeophones = 48 sensors = np.linspace(0., 117.5, numberGeophones) scheme = pg.physics.traveltime.createRAData(sensors) # Adapt sensor positions to slope pos = np.array(scheme.sensorPositions()) for x in pos[:, 0]: i = np.where(pos[:, 0] == x)
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 mesh = mt.createMesh(geom, quality=32, area=0.2, smooth=[1, 10]) # pg.show(mesh, savefig='mesh.pdf') rMap = [[1, SoilR], [4, AnoR]] # Map conductivity value per region to each cell in the given mesh R = pg.solver.parseMapToCellArray(rMap, mesh) # Dirichlet conditions for hydraulic potential # Create survey measurement scheme # ertScheme = ert.createERTData(pg.utils.grange(-20, 20, dx=1.0),
# -*- 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') #ax, _ = pg.show(mesh, data=T, label='Temperature $T$', cmap="hot_r")
boundary=0, paraBoundary=2) if case == 1: for depth in (5, 15): start = plc.createNode(mesh.xmin(), -depth, 0.0) end = plc.createNode(mesh.xmax(), -depth, 0.0) plc.createEdge(start, end, marker=1) for sensor in ertData.sensorPositions(): plc.createNode([sensor.x(), sensor.y() - 0.1]) rect = mt.createRectangle([mesh.xmin(), mesh.ymin()], [mesh.xmax(), mesh.ymax()], boundaryMarker=0) geom = mt.mergePLC([plc, rect]) meshRST = mt.createMesh(geom, quality=34, area=1, smooth=[1, 2]) for cell in meshRST.cells(): cell.setMarker(2) for boundary in meshRST.boundaries(): boundary.setMarker(0) pg.show(meshRST) print(meshRST) # %% meshRST.save("paraDomain_%d.bms" % case) meshERT = mt.appendTriangleBoundary(meshRST, xbound=500,
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() pg.show(plc, marker=True) pg.show(plc, markers=True) pg.show(mesh) ############################################################################### # Prepare the model parameterization # We have two markers here: 1: background 2: circle anomaly