def modelCavity1(maxArea=0.0025): boundary = [] boundary.append([-1.0, -1.0]) boundary.append([-0.5, -1.0]) boundary.append([-0.5, -0.7]) boundary.append([0.5, -0.7]) boundary.append([0.5, -1.0]) boundary.append([1.0, -1.0]) boundary.append([1.0, 1.0]) boundary.append([-1.0, 1.0]) poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] polyCreateDefaultEdges_(poly, boundaryMarker=[4, 4, 4, 4, 4, 2, 3, 1]) mesh = createMesh(poly, quality=33.4, area=maxArea, smooth=[0, 10]) # Diffusions coefficient, viscosity b7 = mesh.findBoundaryByMarker(1)[0] for b in mesh.findBoundaryByMarker(1): if b.center()[1] < b.center()[1]: b7 = b b7.setMarker(7) velBoundary = [[1, [0.0, 0.0]], [2, [0.0, 0.0]], [3, [1.0, 0.0]], [4, [0.0, 0.0]], [7, [0.0, 0.0]]] preBoundary = [[7, 0.0]] a = pg.RVector(mesh.cellCount(), 10000.0) return mesh, velBoundary, preBoundary, a, 100
def create_mesh(self, only_pd_mesh=False, **kwargs): """Generate a mesh from the polygon. Use the supplied quality if not already specified in the XML. TODO: Allow overrides through **kwargs """ if not hasattr(self, "poly"): raise AttributeError("No polygon created yet!") quality = kwargs.pop("quality", 34.2) smooth = kwargs.pop("smooth", (1, 10)) surf = self.doc.getroot().find("line[@name='surface']") qual = float(surf.get("meshquality", quality)) area = kwargs.pop("area", 0.0) m_with_bg = createMesh(self.poly, qual, smooth=smooth, node_move=False, area=area) if only_pd_mesh: pd = pg.Mesh(2) marker_start = 2 marker_end = -1 pd.createMeshByMarker(m_with_bg, marker_start, marker_end) return pd return m_with_bg
def modelCavity1(maxArea=0.0025): boundary = [] boundary.append([-1.0, -1.0]) boundary.append([ -0.5, -1.0]) boundary.append([ -0.5, -0.7]) boundary.append([ 0.5, -0.7]) boundary.append([ 0.5, -1.0]) boundary.append([ 1.0, -1.0]) boundary.append([ 1.0, 1.0]) boundary.append([-1.0, 1.0]) poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] polyCreateDefaultEdges_(poly, boundaryMarker=[4,4,4,4,4,2,3,1]) mesh = createMesh(poly, quality=33.4, area=maxArea, smooth=[0,10]) # Diffusions coefficient, viscosity b7 = mesh.findBoundaryByMarker(1)[0] for b in mesh.findBoundaryByMarker(1): if b.center()[1] < b.center()[1]: b7 = b b7.setMarker(7) velBoundary=[ [1,[0.0, 0.0]], [2,[0.0, 0.0]], [3,[1.0, 0.0]], [4,[0.0, 0.0]], [7,[0.0, 0.0]]] preBoundary=[[7,0.0]] a = pg.RVector(mesh.cellCount(), 10000.0) return mesh, velBoundary, preBoundary, a, 100
def createMesh(self, only_pd_mesh=False, verbose=False, **kwargs): """Generate a mesh from the polygon. Use the supplied quality if not already specified in the XML. TODO: Allow overrides through **kwargs """ if not hasattr(self, 'poly'): raise AttributeError("No polygon created yet!") quality = kwargs.pop("quality", 34.2) smooth = kwargs.pop("smooth", (1, 10)) surf = self.doc.getroot().find("line[@name='surface']") qual = float(surf.get("meshquality", quality)) area = kwargs.pop('area', 0.0) m_with_bg = createMesh(self.poly, qual, smooth=smooth, node_move=False, area=area, verbose=verbose) if only_pd_mesh: pd = pg.Mesh(2) marker_start = 2 marker_end = -1 pd.createMeshByMarker(m_with_bg, marker_start, marker_end) return pd return m_with_bg
def createModel2(maxArea=0.2, nx=20, grid=True): mesh = None if grid: nx = nx ny = nx mesh = pg.createGrid(x=np.linspace(-10, 10, nx), y=np.linspace(0, 20, ny)) else: layer1 = pt.createRectangle(start=[-10, 20], end=[10, 10], marker=2, boundaryMarker=[1, -1, 2, 4]) layer2 = pt.createRectangle(start=[-10, 10], end=[10, 0], marker=1, boundaryMarker=[1, 3, 2, -1]) mesh = createMesh([layer1, layer2], quality=32, area=maxArea, smooth=[1, 10]) density = mesh.cellAttributes() * 0.0 + 2.0 for c in mesh.cells(): if c.center().y() > 0 and c.center().x() < 0: density[c.id()] = 1.0 return mesh, density
def createModel2(maxArea=0.2, nx=20, grid=True): mesh=None if grid: nx = nx ny = nx mesh = pg.createGrid(x=np.linspace(-10, 10, nx), y=np.linspace(0, 20, ny)) else: layer1 = pt.createRectangle(start=[-10, 20], end=[10, 10], marker=2, boundaryMarker=[1, -1, 2, 4]) layer2 = pt.createRectangle(start=[-10, 10], end=[10, 0], marker=1, boundaryMarker=[1, 3, 2, -1]) mesh = createMesh([layer1, layer2], quality=32, area=maxArea, smooth=[1,10]) density = mesh.cellAttributes()*0.0 + 2.0 for c in mesh.cells(): if c.center().y() > 0 and c.center().x() < 0: density[c.id()] = 1.0 return mesh, density
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 createModel(maxArea=0.2, nx=80, grid=True): mesh=None dens=None if grid: nx = nx ny = nx/2 mesh = pg.createGrid(x=np.linspace(-10, 10, nx), y=np.linspace(-10, 0, ny)) density = mesh.cellAttributes()*0.0 + 1.0 xstart = (nx-1)*int(ny/1.3) + int(nx/2) yoff =nx-1 for i in range(int(ny/20)): density[xstart-nx*0.35+i*yoff: xstart+nx*0.35+i*yoff] *= 2 else: layer1 = pt.createRectangle(start=[-10, 0], end=[10, -10], marker=1, boundaryMarker=[1, 3, 2, 4]) block = pt.createRectangle(start=[-10+0.35*10, -1.8918918918918912], end=[10-0.35*10, -2.2972972972972965], marker=2) mesh = createMesh([layer1, block], quality=32, area=maxArea, smooth=[1,10]) density = mesh.cellAttributes()*0.0 + 1.0 density[mesh.cellMarker()==2] = 2 return mesh, density
def test_cube_cube_coplanar_touchface(self): w = mt.createCube(marker=1) w.scale([2.0, 2.0, 2.0]) c = mt.createCube(marker=2) c.translate([1.5, 0.0, 0.0]) w = mt.mergePLC3D([w, c]) self.assertEqual(w.nodeCount(), 8 + 8) self.assertEqual(w.boundaryCount(), 6 + 5) c = mt.createCube(marker=3) c.translate([-1.5, 0.0, 0.0]) w = mt.mergePLC3D([w, c]) self.assertEqual(w.nodeCount(), 8 + 8 + 8) self.assertEqual(w.boundaryCount(), 6 + 5 + 5) c = mt.createCube(marker=4) c.translate([0.0, 1.5, 0.0]) w = mt.mergePLC3D([w, c]) self.assertEqual(w.nodeCount(), 8 + 8 + 8 + 8) self.assertEqual(w.boundaryCount(), 6 + 5 + 5 + 5) c = mt.createCube(marker=5) c.translate([0.0, 0.0, -1.5]) w = mt.mergePLC3D([w, c]) self.assertEqual(w.nodeCount(), 8 + 8 + 8 + 8 + 8) self.assertEqual(w.boundaryCount(), 6 + 5 + 5 + 5 + 5) pg.show(w) # w.exportPLC('t.poly') pg.show(mt.createMesh(w))
def test_cube_cube_equalface(self): w = mt.createCube(marker=1) c = mt.createCube(marker=2) c.translate([c.xmax() - w.xmin(), 0.0]) w = mt.mergePLC3D([w, c]) self.assertEqual(w.nodeCount(), 8 + 4) self.assertEqual(w.boundaryCount(), 6 + 5) c = mt.createCube(marker=3) c.translate([0.0, w.ymax() - c.ymin(), 0.0]) w = mt.mergePLC3D([w, c]) self.assertEqual(w.nodeCount(), 8 + 4 + 4) self.assertEqual(w.boundaryCount(), 6 + 5 + 5) c = mt.createCube(marker=4) c.translate([0.0, 0.0, c.zmax() - w.zmin()]) w = mt.mergePLC3D([c, w]) self.assertEqual(w.nodeCount(), 8 + 4 + 4 + 4) self.assertEqual(w.boundaryCount(), 6 + 5 + 5 + 5) c = mt.createCube(marker=5) c.translate([0.0, w.ymax() - c.ymin(), c.zmax() - w.zmin()]) w = mt.mergePLC3D([c, w]) self.assertEqual(w.nodeCount(), 8 + 4 + 4 + 4 + 6) self.assertEqual(w.boundaryCount(), 6 + 5 + 5 + 5 + 6) c = mt.createCube(marker=6) c.translate([0.0, c.ymax() - w.ymin(), c.zmax() - w.zmin()]) w = mt.mergePLC3D([w, c]) self.assertEqual(w.nodeCount(), 8 + 4 + 4 + 4 + 6 + 0) self.assertEqual(w.boundaryCount(), 6 + 5 + 5 + 5 + 6 + 3) # w.exportPLC('t.poly') pg.show(mt.createMesh(w))
def test_face_in_face(self): """Test subface with different marker constructed with hole marker.""" w = mt.createCube(marker=1, boundaryMarker=1) b = w.boundary(2) pad = mt.createFacet( mt.createCircle(radius=0.2, segments=12, isHole=True)) b2 = pad.boundary(0) # rotate to match target norm and pos rot = pg.core.getRotation(b2.norm(), b.norm()) pad.transform(rot) pad.translate(b.center()) # create a boundary with new marker match the hole w.copyBoundary(b2) w.createBoundary(w.nodes( [w.createNode(n.pos()).id() for n in b2.nodes()]), marker=2) #print(w.boundaryMarkers()) mesh = mt.createMesh(w) #pg.show(mesh) # w.exportPLC('pad.poly') # mesh.exportBoundaryVTU('b.vtu') np.testing.assert_array_equal( pg.unique(pg.sort(mesh.boundaryMarkers())), [0, 1, 2]) # print(mesh) # mesh.exportBoundaryVTU('b.vtu') pg.show(mesh)
def createMesh(self, depth=None, quality=34.3, paraDX=0.5, boundary=0, paraBoundary=5, apply=True, **kwargs): """Create (inversion) mesh using createParaDomain2D Parameters ---------- apply : bool set Mesh property of the underlying forward operator """ if self.dataContainer is None: raise BaseException('Cannot create mesh without dataContainer.') if depth is None: depth = self.getDepth() self.poly = createParaMeshPLC(self.dataContainer.sensorPositions(), paraDepth=depth, paraDX=paraDX, paraBoundary=paraBoundary, boundary=boundary) mesh = createMesh(self.poly, quality=quality, smooth=(1, 10)) if apply: self.setMesh(mesh) return mesh
def createMesh(self, depth=None, quality=34.3, paraDX=0.5, boundary=0, paraBoundary=5, apply=True, **kwargs): """Create (inversion) mesh using createParaDomain2D Parameters ---------- apply : bool set Mesh property of the underlying forward operator """ if self.dataContainer is None: raise('Cannot create mesh without dataContainer.') if depth is None: depth = self.getDepth() self.poly = createParaMeshPLC(self.dataContainer.sensorPositions(), paraDepth=depth, paraDX=paraDX, paraBoundary=paraBoundary, boundary=boundary) mesh = createMesh(self.poly, quality=quality, smooth=(1, 10)) if apply: self.setMesh(mesh) return mesh
def createTestWorld1(maxArea=0.2, verbose=0): # ___________________8___________________ # | | # 1 7 # |__________________9__________________| # | | # 2 | 4 | 6 # |__________________10_________________| # | | # 3 5 # |__________________4__________________| layer1 = pt.createRectangle(start=[-20, 0], end=[20, -2], marker=1, boundaryMarker=[1, 9, 7, 8]) layer2 = pt.createRectangle(start=[-20, -2], end=[20, -8], marker=2, boundaryMarker=[2, 10, 6, 9]) layer3 = pt.createRectangle(start=[-20, -8], end=[20, -15], marker=3, boundaryMarker=[3, 4, 5, 10]) block = pt.createRectangle(start=[-6, -3.5], end=[6, -6.0], marker=4, boundaryMarker=10, area=0.1) plc = pt.mergePLC([layer1, layer2, layer3, block]) mesh = createMesh(plc, quality=33, area=maxArea, smooth=[1,10], verbose=verbose) return mesh, plc
def createModel(maxArea=0.2, nx=80, grid=True): mesh = None dens = None if grid: nx = nx ny = nx / 2 mesh = pg.createGrid(x=np.linspace(-10, 10, nx), y=np.linspace(-10, 0, ny)) density = mesh.cellAttributes() * 0.0 + 1.0 xstart = (nx - 1) * int(ny / 1.3) + int(nx / 2) yoff = nx - 1 for i in range(int(ny / 20)): density[xstart - nx * 0.35 + i * yoff:xstart + nx * 0.35 + i * yoff] *= 2 else: layer1 = pt.createRectangle(start=[-10, 0], end=[10, -10], marker=1, boundaryMarker=[1, 3, 2, 4]) block = pt.createRectangle( start=[-10 + 0.35 * 10, -1.8918918918918912], end=[10 - 0.35 * 10, -2.2972972972972965], marker=2) mesh = createMesh([layer1, block], quality=32, area=maxArea, smooth=[1, 10]) density = mesh.cellAttributes() * 0.0 + 1.0 density[mesh.cellMarker() == 2] = 2 return mesh, density
def createMesh(self, depth=None, quality=34.3, paraDX=1, boundary=0, paraBoundary=0, secNodes=3, apply=True, **kwargs): """Create (inversion) mesh using createParaDomain2D Parameters ---------- depth : float, optional maximum depth, 0 (default) means maximum offset / 3. paraDX : float relative distance for refinement nodes between two sensors e.g., 0 or 1 means no refinement e.g., 0.5 means 1 additional node between two neighboring sensors e.g., 0.33 means 2 additional equidistant nodes between two sensors boundary : float, optional boundary width to be appended for domain prolongation in absolute para domain width. values < 0 force the boundary to be 4 times para domain width. paraBoundary : float, optional margin for parameter domain in sensor distances (default 2) quality : float, optional mesh quality (smallest angle allowed) apply : bool, optional set mesh property of the underlying forward operator secNodes : int (1) Amount of secondary nodes to improve accuracy of the forward solution. **kwargs: Additional keyword arguments passed to pygimli.meshtools.createParaMeshPLC See also -------- pygimli.meshtools.createParaMeshPLC """ if self.dataContainer is None: raise BaseException('Cannot create mesh without dataContainer.') if depth is None: depth = self.getDepth() self.poly = mt.createParaMeshPLC(self.dataContainer.sensorPositions(), paraDepth=depth, paraDX=paraDX, paraBoundary=paraBoundary, boundary=boundary, **kwargs) mesh = mt.createMesh(self.poly, quality=quality, smooth=(1, 10)) if apply: self.setMesh(mesh, secNodes=secNodes) return mesh
def makeMesh(self, depth=None, quality=34.3, paraDX=0.5, boundary=0, paraBoundary=5): """create (inversion)""" if depth is None: depth = max(self.getOffset()) / 3.0 self.poly = createParaDomain2D( self.data.sensorPositions(), paraDepth=depth, paraDX=paraDX, paraBoundary=paraBoundary, boundary=boundary ) self.mesh = createMesh(self.poly, quality=quality, smooth=(1, 10)) self.mesh.createNeighbourInfos()
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 prepareMesh(self): geom = mt.createPolygon(self.meshPolygonVertexes, isClosed=True, marker=0) self.mesh = mt.createMesh(geom, quality=34.0, area=0.2, smooth=(1, 10)) self.startModel = np.array([1. / 2000.])[self.mesh.cellMarkers()] print(self.mesh.cellMarkers()) print("setting of mesh") self.travelTime.setMesh(self.mesh) pass
def createMesh(self, depth=None, quality=34.3, paraDX=0.5, boundary=0, paraBoundary=5): """Create (inversion) mesh using createParaDomain2D""" if depth is None: depth = max(self.getOffset()) / 3. self.poly = createParaMeshPLC(self.dataContainer.sensorPositions(), paraDepth=depth, paraDX=paraDX, paraBoundary=paraBoundary, boundary=boundary) mesh = createMesh(self.poly, quality=quality, smooth=(1, 10)) self.setMesh(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 test_cubeBasics(self): plc = mt.createCube() for i, b in enumerate(plc.boundaries()): b.setMarker(i + 1) mesh = mt.createMesh(plc) for marker in pg.unique(pg.sort(plc.boundaryMarkers())): b1 = plc.boundaries(plc.boundaryMarkers() == marker)[0] b2 = mesh.boundaries(mesh.boundaryMarkers() == marker)[0] np.testing.assert_array_equal(b1.norm(), b2.norm())
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 modelPlume(maxArea=0.1): boundary = [] boundary.append([-1., 0.0]) #0 boundary.append([-1., -1.0]) #1 boundary.append([-0.1, -1.0]) #2 boundary.append([0.1, -1.0]) #3 boundary.append([1., -1.0]) #4 boundary.append([1., 0.0]) #5 boundary.append([0.1, 0.0]) #6 boundary.append([-0.1, 0.0]) #7 poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] polyCreateDefaultEdges_(poly, boundaryMarker=[1, 2, 3, 2, 4, 5, 6, 7]) #poly.createEdge(nodes[0], nodes[1], 1) # left #poly.createEdge(nodes[1], nodes[2], 2) # bottom1 #poly.createEdge(nodes[2], nodes[3], 3) # bottom2 #poly.createEdge(nodes[3], nodes[4], 2) # bottom3 #poly.createEdge(nodes[4], nodes[5], 4) # right #poly.createEdge(nodes[5], nodes[6], 5) # top1 #poly.createEdge(nodes[6], nodes[7], 6) # topcenter #poly.createEdge(nodes[7], nodes[0], 7) # top2 mesh = createMesh(poly, quality=33.4, area=maxArea, smooth=[0, 10], verbose=False) velBoundary = [ #[1, [0.0, 0.0]], # [2, [0.0, 0.0]], #[3, [0.0, 0.0]], #[4, [0.0, 0.0]], [5, [1.0, 0.0]], [6, [0.0, 0.0]], [7, [-1.0, 0.0]] ] b = mesh.findBoundaryByMarker(2)[0] b.setMarker(8) #preBoundary=None preBoundary = [[8, 0.0]] a = 1 return mesh, velBoundary, preBoundary, a, 100
def createMesh(self, depth=None, quality=34.3, paraDX=1, boundary=0, paraBoundary=0, secNodes=3, apply=True, **kwargs): """Create (inversion) mesh using createParaDomain2D Parameters ---------- depth : float, optional maximum depth, 0 (default) means maximum offset / 3. paraDX : float relative distance for refinement nodes between two sensors e.g., 0 or 1 means no refinement e.g., 0.5 means 1 additional node between two neighboring sensors e.g., 0.33 means 2 additional equidistant nodes between two sensors boundary : float, optional boundary width to be appended for domain prolongation in absolute para domain width. values < 0 force the boundary to be 4 times para domain width. paraBoundary : float, optional margin for parameter domain in sensor distances (default 2) quality : float, optional mesh quality (smallest angle allowed) apply : bool, optional set mesh property of the underlying forward operator secNodes : int (1) Amount of secondary nodes to improve accuracy of the forward solution. **kwargs: Additional keyword arguments passed to pygimli.meshtools.createParaMeshPLC See also -------- pygimli.meshtools.createParaMeshPLC """ if self.dataContainer is None: raise BaseException('Cannot create mesh without dataContainer.') if depth is None: depth = self.getDepth() self.poly = mt.createParaMeshPLC(self.dataContainer.sensorPositions(), paraDepth=depth, paraDX=paraDX, paraBoundary=paraBoundary, boundary=boundary, **kwargs) mesh = mt.createMesh(self.poly, quality=quality, smooth=(1, 10)) if apply: self.setMesh(mesh, secNodes=secNodes) return mesh
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 createMesh(geom, topo, sfile, Q): scheme = pg.DataContainerERT() scheme.setSensorPositions(topo) srv = pd.read_csv(sfile, sep='\t', header=None) for i, elec in enumerate("abmn"): scheme[elec] = srv.values[:, i + 1].astype(np.int) - 1 for p in scheme.sensors(): geom.createNode(p) geom.createNode(p - [0, 0.1]) mesh = mt.createMesh(geom, quality=Q) return scheme, mesh
def modelCavity2(area, refine=True): boundary = [] boundary.append([-1.0, 0.0]) #0 boundary.append([-1.0, -1.0]) #1 boundary.append([-0.2, -1.0]) #2 boundary.append([-0.2, -0.8]) #3 boundary.append([ 0.2, -0.8]) #4 boundary.append([ 0.2, -1.0]) #5 boundary.append([ 1.0, -1.0]) #6 boundary.append([ 1.0, 0.0]) #7 boundary.append([ 0.2, 0.0]) #8 boundary.append([ 0.2, -0.2]) #9 boundary.append([-0.2, -0.2]) #10 boundary.append([-0.2, 0.0]) #11 poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] eMarker = [1, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2] for i in range(len(nodes)): poly.createEdge(nodes[i], nodes[(i+1)%len(nodes)], eMarker[i]) if refine: poly.createNode([-0.21, -0.99]) mesh = createMesh(poly, quality=34.0, area=area, smooth=[0,10]) # Diffusions coefficient, viscosity b7 = mesh.findBoundaryByMarker(2)[0] for b in mesh.findBoundaryByMarker(1): if b.center()[1] < b.center()[1]: b7 = b b7.setMarker(4) velBoundary=[[1,[1.0, 0.0]], [2,[0.0, 0.0]], [3,[1.0, 0.0]], [4,[0.0, 0.0]], ] preBoundary=[[4,0.0]] a = pg.RVector(mesh.cellCount(), 1.0) return mesh, velBoundary, preBoundary, a, 50000
def modelCavity2(area, refine=True): boundary = [] boundary.append([-1.0, 0.0]) #0 boundary.append([-1.0, -1.0]) #1 boundary.append([-0.2, -1.0]) #2 boundary.append([-0.2, -0.8]) #3 boundary.append([0.2, -0.8]) #4 boundary.append([0.2, -1.0]) #5 boundary.append([1.0, -1.0]) #6 boundary.append([1.0, 0.0]) #7 boundary.append([0.2, 0.0]) #8 boundary.append([0.2, -0.2]) #9 boundary.append([-0.2, -0.2]) #10 boundary.append([-0.2, 0.0]) #11 poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] eMarker = [1, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2] for i in range(len(nodes)): poly.createEdge(nodes[i], nodes[(i + 1) % len(nodes)], eMarker[i]) if refine: poly.createNode([-0.21, -0.99]) mesh = createMesh(poly, quality=34.0, area=area, smooth=[0, 10]) # Diffusions coefficient, viscosity b7 = mesh.findBoundaryByMarker(2)[0] for b in mesh.findBoundaryByMarker(1): if b.center()[1] < b.center()[1]: b7 = b b7.setMarker(4) velBoundary = [ [1, [1.0, 0.0]], [2, [0.0, 0.0]], [3, [1.0, 0.0]], [4, [0.0, 0.0]], ] preBoundary = [[4, 0.0]] a = pg.RVector(mesh.cellCount(), 1.0) return mesh, velBoundary, preBoundary, a, 50000
def modelPlume(maxArea=0.1): boundary = [] boundary.append([-1., 0.0])#0 boundary.append([-1., -1.0])#1 boundary.append([-0.1, -1.0])#2 boundary.append([ 0.1, -1.0])#3 boundary.append([ 1., -1.0])#4 boundary.append([ 1., 0.0])#5 boundary.append([ 0.1, 0.0])#6 boundary.append([ -0.1, 0.0])#7 poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] polyCreateDefaultEdges_(poly, boundaryMarker=[1,2,3,2,4,5,6,7]) #poly.createEdge(nodes[0], nodes[1], 1) # left #poly.createEdge(nodes[1], nodes[2], 2) # bottom1 #poly.createEdge(nodes[2], nodes[3], 3) # bottom2 #poly.createEdge(nodes[3], nodes[4], 2) # bottom3 #poly.createEdge(nodes[4], nodes[5], 4) # right #poly.createEdge(nodes[5], nodes[6], 5) # top1 #poly.createEdge(nodes[6], nodes[7], 6) # topcenter #poly.createEdge(nodes[7], nodes[0], 7) # top2 mesh = createMesh(poly, quality=33.4, area=maxArea, smooth=[0,10], verbose=False) velBoundary=[#[1, [0.0, 0.0]], # [2, [0.0, 0.0]], #[3, [0.0, 0.0]], #[4, [0.0, 0.0]], [5, [1.0, 0.0]], [6, [0.0, 0.0]], [7, [-1.0, 0.0]] ] b = mesh.findBoundaryByMarker(2)[0] b.setMarker(8) #preBoundary=None preBoundary=[[8, 0.0]] a=1 return mesh, velBoundary, preBoundary, a, 100
def modelPipe(): boundary = [] #left inflow boundary.append([0.1, 0.0]) # 0 boundary.append([0.0, 0.0]) # 1 boundary.append([0.0, -1.0]) boundary.append([0.0, -1.1]) boundary.append([1.0, -1.1]) boundary.append([1.0, -1.0]) #right outflow boundary.append([1.0, 0.0]) # 1 boundary.append([0.9, 0.0]) # 0 #closing boundary.append([0.9, -1.0]) # 0 boundary.append([0.1, -1.0]) # 0 poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] for i in range(len(nodes)): poly.createEdge(nodes[i], nodes[(i+1)%len(nodes)], 1) poly.boundaries()[0].setMarker(2) for b in poly.boundaries(): if b.norm()[1]==1.0 and b.center()[0]==0.95: b.setMarker(3) if b.norm()[1]==-1.0 and b.center()[0]==0.5: b.setMarker(4) mesh = createMesh(poly, quality=34.0, area=0.0005, smooth=[0,10]) velBoundary=[[1, [0.0, 0.0]], [2, [0.0, -1.0]], [3, [0.0, 1.0]], [4, [0.0, 0.0]] ] #preBoundary=None preBoundary=[[4, 0.0]] a=1 return mesh, velBoundary, preBoundary, a, 400
def modelPlume(): boundary = [] boundary.append([-100., 0.0])#0 boundary.append([-100., -100.0])#1 boundary.append([-10., -100.0])#2 boundary.append([ 10., -100.0])#3 boundary.append([ 100., -100.0])#4 boundary.append([ 100., 0.0])#5 boundary.append([ 10. , 0.0])#6 boundary.append([ -10. , 0.0])#7 poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] poly.createEdge(nodes[0], nodes[1], 1) # left poly.createEdge(nodes[1], nodes[2], 2) # bottom1 poly.createEdge(nodes[2], nodes[3], 3) # bottom2 poly.createEdge(nodes[3], nodes[4], 2) # bottom3 poly.createEdge(nodes[4], nodes[5], 4) # right poly.createEdge(nodes[5], nodes[6], 5) # top1 poly.createEdge(nodes[6], nodes[7], 6) # topcenter poly.createEdge(nodes[7], nodes[0], 7) # top2 mesh = createMesh(poly, quality=33.4, area=20., smooth=[0,10], verbose=False) velBoundary=[#[1, [0.0, 0.0]], # [2, [0.0, 0.0]], #[3, [0.0, 0.0]], #[4, [0.0, 0.0]], [5, [1.0, 0.0]], [6, [0.0, 0.0]], [7, [-1.0, 0.0]] ] b = mesh.findBoundaryByMarker(2)[0] b.setMarker(8) #preBoundary=None preBoundary=[[8, 0.0]] a=1 return mesh, velBoundary, preBoundary, a, 100
def modelCavity(): boundary = [] boundary.append([-1.0, -1.0]) boundary.append([ -0.5, -1.0]) boundary.append([ -0.5, -0.7]) boundary.append([ 0.5, -0.7]) boundary.append([ 0.5, -1.0]) boundary.append([ 1.0, -1.0]) boundary.append([ 1.0, 1.0]) boundary.append([-1.0, 1.0]) poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] poly.createEdge(nodes[0], nodes[1], 4) # bottom poly.createEdge(nodes[1], nodes[2], 4) # bottom poly.createEdge(nodes[2], nodes[3], 4) # bottom poly.createEdge(nodes[3], nodes[4], 4) # bottom poly.createEdge(nodes[4], nodes[5], 4) # bottom poly.createEdge(nodes[5], nodes[6], 2) # right poly.createEdge(nodes[6], nodes[7], 3) # top poly.createEdge(nodes[7], nodes[0], 1) # left mesh = createMesh(poly, quality=33.4, area=0.0025, smooth=[0,10]) # Diffusions coefficient, viscosity b7 = mesh.findBoundaryByMarker(1)[0] for b in mesh.findBoundaryByMarker(1): if b.center()[1] < b.center()[1]: b7 = b b7.setMarker(7) velBoundary=[ [1,[0.0, 0.0]], [2,[0.0, 0.0]], [3,[1.0, 0.0]], [4,[0.0, 0.0]], [7,[0.0, 0.0]]] preBoundary=[[7,0.0]] a = pg.RVector(mesh.cellCount(), 10000.0) return mesh, velBoundary, preBoundary, a, 100
def modelPipe(): boundary = [] #left inflow boundary.append([0.1, 0.0]) # 0 boundary.append([0.0, 0.0]) # 1 boundary.append([0.0, -1.0]) boundary.append([0.0, -1.1]) boundary.append([1.0, -1.1]) boundary.append([1.0, -1.0]) #right outflow boundary.append([1.0, 0.0]) # 1 boundary.append([0.9, 0.0]) # 0 #closing boundary.append([0.9, -1.0]) # 0 boundary.append([0.1, -1.0]) # 0 poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] for i in range(len(nodes)): poly.createEdge(nodes[i], nodes[(i + 1) % len(nodes)], 1) poly.boundaries()[0].setMarker(2) for b in poly.boundaries(): if b.norm()[1] == 1.0 and b.center()[0] == 0.95: b.setMarker(3) if b.norm()[1] == -1.0 and b.center()[0] == 0.5: b.setMarker(4) mesh = createMesh(poly, quality=34.0, area=0.0005, smooth=[0, 10]) velBoundary = [[1, [0.0, 0.0]], [2, [0.0, -1.0]], [3, [0.0, 1.0]], [4, [0.0, 0.0]]] #preBoundary=None preBoundary = [[4, 0.0]] a = 1 return mesh, velBoundary, preBoundary, a, 400
def test_smallcube_in_bigcube(self): """ A small cube in a bigger one, creating two subfaces. author: @frodo4fingers """ w = mt.createCube(marker=1) c = mt.createCube(size=[0.5, 1.0, 1.0], marker=2) w = mt.mergePLC3D([w, c]) self.assertEqual(w.nodeCount(), 8 + 8) self.assertEqual(w.boundaryCount(), 8) # will not work until edge intersection is working # d = mt.createCube(size=[0.8, 1.0, 1.0], # pos=[0.1, 0.0, 1.0], # marker=3) # w = mt.mergePLC3D([w, d]) # self.assertEqual(w.nodeCount(), 8+8) # self.assertEqual(w.boundaryCount(), 8) # print(w) pg.show(w) pg.show(mt.createMesh(w))
def createTestWorld1(maxArea=0.2, verbose=0): # ___________________8___________________ # | | # 1 7 # |__________________9__________________| # | | # 2 | 4 | 6 # |__________________10_________________| # | | # 3 5 # |__________________4__________________| layer1 = pt.createRectangle(start=[-20, 0], end=[20, -2], marker=1, boundaryMarker=[1, 9, 7, 8]) layer2 = pt.createRectangle(start=[-20, -2], end=[20, -8], marker=2, boundaryMarker=[2, 10, 6, 9]) layer3 = pt.createRectangle(start=[-20, -8], end=[20, -15], marker=3, boundaryMarker=[3, 4, 5, 10]) block = pt.createRectangle(start=[-6, -3.5], end=[6, -6.0], marker=4, boundaryMarker=10, area=0.1) plc = pt.mergePLC([layer1, layer2, layer3, block]) mesh = createMesh(plc, quality=33, area=maxArea, smooth=[1, 10], verbose=verbose) return mesh, plc
def __create_meshes(self): """ Creates all the used meshes. Creates the meshes for the simulation, the in-field inversion and the inversion after all data is collected. """ # Add mesh nodes below the sensors based on for pos in self.__scheme.sensorPositions(): self.__world.createNode(pos) self.__world.createNode( pos + pg.RVector3(0, -self.__config.finv_spacing / 2)) # Create mesh for simulation based on the generated world self.__sim_mesh = mt.createMesh(poly=self.__world, quality=self.__config.sim_mesh_quality, area=self.__config.sim_mesh_maxarea) # Create parameter mesh for in-field inversion sensor_distance = self.__scheme.sensorPositions( )[1][0] - self.__scheme.sensorPositions()[0][0] para_dx = self.__config.inv_dx / sensor_distance para_dz = self.__config.inv_dz / sensor_distance n_layers = int(self.__config.inv_depth / self.__config.inv_dz) self.__inv_mesh = mt.createParaMesh2DGrid( sensors=self.__scheme.sensorPositions(), paraDX=para_dx, paraDZ=para_dz, paraDepth=self.__config.inv_depth, nLayers=n_layers) # Create (probably finer) parameter mesh for a final inversion final_para_dx = self.__config.inv_final_dx / sensor_distance final_para_dz = self.__config.inv_final_dz / sensor_distance final_n_layers = int(self.__config.inv_final_depth / self.__config.inv_final_dz) self.__inv_final_mesh = mt.createParaMesh2DGrid( sensors=self.__scheme.sensorPositions(), paraDX=final_para_dx, paraDZ=final_para_dz, paraDepth=self.__config.inv_final_depth, nLayers=final_n_layers)
def create_mesh(geom): elecs = np.linspace(-25, 25, 15) # x coordinate of the electrodes # Create a Dipole Dipole ('dd') measuring scheme scheme = pb.createData(elecs=elecs, schemeName='dd') # Put all electrodes (aka. sensors positions) into the geometry to enforce mesh # refinement. Due to experience known, its convenient to add further refinement # nodes in a distance of 10% of electrode spacing, to achieve sufficient # numerical accuracy. for pos in scheme.sensorPositions(): geom.createNodeWithCheck(pos) geom.createNodeWithCheck(pos + pg.RVector3(0, -0.5)) # Create a mesh for the finite element modelling with appropriate mesh quality. mesh = mt.createMesh(geom, quality=33) # Optional: take a look at the mesh fig, ax = plt.subplots(figsize=(10, 6)) pg.show(mesh, ax=ax, hold=True) ax.set_ylim(-20, 0) ax.plot(elecs, np.zeros_like(elecs), "kv") pg.show(geom, ax=ax) return mesh, scheme
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) ax.plot(sensors[:, 0], sensors[:, 1], "ro") ################################################################################ # Next, we create an empty DataContainer and fill it with sensor positions and
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') pg.show(mesh, ax=axs[1][0])
The sought hydraulic velocity distribution can then be calculated as the gradient field of :math:`\mathbf{v}=-\nabla p`. """ # sphinx_gallery_thumbnail_number = 2 import numpy as np import pygimli as pg import pygimli.meshtools as mt from pygimli.viewer.pv import drawStreamLines, drawSlice plc = mt.createCube(size=[40, 20, 15], marker=1, boundaryMarker=0) cube = mt.createCube(size=[15, 15, 8], marker=2, boundaryMarker=0) geom = plc + cube mesh = mt.createMesh(geom, area=4) for bound in mesh.boundaries(): x = bound.center().x() if x == mesh.xmin(): bound.setMarker(1) elif x == mesh.xmax(): bound.setMarker(2) kMap = {1: 1e-4, 2: 1e-6} kArray = pg.solver.parseMapToCellArray(list(kMap), mesh) # dict does not work kArray = np.column_stack([kArray] * 3) bc = {"Dirichlet": {1: 20.0, 2: 10.0}} h = pg.solver.solveFiniteElements(mesh, kMap, bc=bc)
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) new_y = x * slope + 137
############################################################################### # 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 # Parameters must be specified as a complex number, here converted by the # utility function :func:`pygimli.utils.complex.toComplex`. rhomap = [ [1, pg.utils.complex.toComplex(100, 0 / 1000)], # Magnitude: 50 ohm m, Phase: -50 mrad [2, pg.utils.complex.toComplex(50, 0 / 1000)],
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 = world + c0 + c1 for sen in sensors: geom.createNode(sen) mesh_fwd = mt.createMesh(geom, quality=34, area=0.25) model = np.array([2000., 2300, 1700])[mesh_fwd.cellMarkers()] pg.show(mesh_fwd, model, label=pg.unit('vel'), cMap=pg.cmap('vel'), nLevs=3, logScale=False) ############################################################################### # Next, we create an empty DataContainer and fill it with sensor positions and # all possible shot-recevier pairs for the two-borehole scenario using the # product function in the itertools module (Python standard library). from itertools import product numbers = np.arange(len(depth))
def createFVPostProzessMesh(mesh, u, uDirichlet): """ Create a mesh suitable for node based post processing of cell centered Finite Volume solutions. This is something like cellDataToPointData with extra Dirichlet points but without smoothing due to interpolation. IMPROVE DOC!! Parameters ---------- """ allBounds = pg.solver.parseArgToBoundaries(uDirichlet, mesh) bounds, vals = zip(*allBounds) uDirVals = pg.solver.generateBoundaryValue(bounds, vals) def isBoundary(b): return b.rightCell() is None and b.leftCell() is not None if bounds is None: bounds = [] for b in mesh.boundaries(): if isBoundary(b): bounds.append(b) boundsIdx = [] for b in bounds: boundsIdx.append(b.id()) poly2 = pg.Mesh(2) for p in mesh.cellCenters(): poly2.createNode(p) boundSort = [] boundSort.append(bounds[0]) boundSort[-1].tag() boundSortIdx = [0] lastB = boundSort[-1] lastN = lastB.node(1) while len(boundSort) != len(bounds): newB = None newN = None for b in lastN.boundSet(): if not b.tagged() and isBoundary(b): boundSort.append(b) b.tag() newB = b if newB.node(0) == lastN: newN = newB.node(1) else: newN = newB.node(0) lastN = newN lastB = newB if not newB: raise boundSortIdx.append(boundsIdx.index(newB.id())) bNodes = list(map(lambda b_: poly2.createNode(b_.center()), boundSort)) for i in range(len(bNodes)): poly2.createEdge(bNodes[i], bNodes[(i + 1) % len(bNodes)]) mesh2 = createMesh(poly2, switches='-pezY') return mesh2, pg.cat(u, uDirVals[boundSortIdx])
############################################################################### # For sufficient numerical accuracy it is generally a good idea to refine the # mesh in the vicinity of the electrodes positions. # We force the local mesh refinement by an additional node at 1/2 mm # distance in -z-direction. for s in plc.positions(pg.find(plc.nodeMarkers() == -99)): plc.createNode(s - [0.0, 0.0, 1e-3 / 2]) # Also refine the reference node plc.createNode([0.5, 0.5, -0.5 - 1e-3 / 2]) ############################################################################### # Create the tetrahedron mesh (calling the tetgen mesh generator) mesh = mt.createMesh(plc) ############################################################################### # First we want to simulate our ERT response for a homogeneous resistivity # of 1 :math:`\Omega`m. Usually, simulate will calculate apparent resistivities # (rhoa) and put them into the returned DataContainerERT. # However, for the calculation of rhoa, geometric factors (k) are expected in # the data container. # If simulate does not find any k in the scheme file, it tries to determine # them itself, either analytically (halfspace) or numerically (topography). # Note that the automatic numerical calculating can only be a fallback mode. # You usually want to keep full control about this calculation because you want # the accuracy as high as possible by providing a special mesh with # higher quality, lower max cell area, finer local mesh refinement, # or quadratic base functions (p2). #
def createFVPostProzessMesh(mesh, u, uDirichlet): """ Create a mesh suitable for node based post processing of cell centered Finite Volume solutions. This is something like cellDataToPointData with extra Dirichlet points but without smoothing due to interpolation. IMPROVE DOC!! Parameters ---------- """ allBounds = pg.solver.parseArgToBoundaries(uDirichlet, mesh) bounds, vals = zip(*allBounds) uDirVals = pg.solver.generateBoundaryValue(bounds, vals) def isBoundary(b): return b.rightCell() is None and b.leftCell() is not None if bounds is None: bounds = [] for b in mesh.boundaries(): if isBoundary(b): bounds.append(b) boundsIdx = [] for b in bounds: boundsIdx.append(b.id()) poly2 = pg.Mesh(2) for p in mesh.cellCenters(): poly2.createNode(p) boundSort = [] boundSort.append(bounds[0]) boundSort[-1].tag() boundSortIdx = [0] lastB = boundSort[-1] lastN = lastB.node(1) while len(boundSort) != len(bounds): newB = None newN = None for b in lastN.boundSet(): if not b.tagged() and isBoundary(b): boundSort.append(b) b.tag() newB = b if newB.node(0) == lastN: newN = newB.node(1) else: newN = newB.node(0) lastN = newN lastB = newB if not newB: raise boundSortIdx.append(boundsIdx.index(newB.id())) bNodes = list(map(lambda b_: poly2.createNode(b_.center()), boundSort)) for i in range(len(bNodes)): poly2.createEdge(bNodes[i], bNodes[(i + 1) % len(bNodes)]) mesh2 = createMesh(poly2, switches='-pezY') return mesh2, pg.cat(u, uDirVals[boundSortIdx])
Traveltime in 2D ---------------- """ import numpy as np import pygimli as pg import pygimli.meshtools as mt from pygimli.physics.traveltime import Refraction # Create geometry definition for the modelling domain world = mt.createWorld(start=[-20, 0], end=[20, -16], layers=[-2, -8], worldMarker=False) # Create a mesh from the geometry definition mesh = mt.createMesh(world, quality=33, area=0.1, smooth=[1, 10]) pg.show(mesh, mesh.cellMarker(), label='marker') scheme = pg.physics.traveltime.createRAData(np.linspace(-15., 15., 31)) ra = Refraction() data = ra.simulate(mesh, np.array(mesh.cellMarker())*1000, scheme, noiseLevel=0.01, noiseAbs=1e-5, verbose=1) ra.showVA(data) ra.showData(data) pg.wait()
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) u = pg.solver.solve(mesh, a=1, f=density, uB=[[-2, 0], [-1, 0]])
boundary.append([-1.0, 0.0]) boundary.append([ 0.0, 0.0]) boundary.append([ 1.0, 0.0]) boundary.append([ 1.0, 1.0]) boundary.append([-1.0, 1.0]) poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] poly.createEdge(nodes[0], nodes[1], 4) # dirichlet (inflow) poly.createEdge(nodes[1], nodes[2], 5) # hom neumann (outflow) poly.createEdge(nodes[2], nodes[3], 3) # hom dirichlet (isolation) poly.createEdge(nodes[3], nodes[4], 2) # hom dirichlet (isolation) poly.createEdge(nodes[4], nodes[0], 1) # hom dirichlet (isolation) mesh = createMesh(poly, quality=34, area=0.002, smooth=[0,10]) print(mesh) ax2,cb = show(mesh) vC = np.array(list(map(lambda p_: [ (2.*p_[1] *(1.0 -p_[0]**2)), (-2.*p_[0] *(1.0 -p_[1]**2))], mesh.cellCenters()))) vB = np.array(list(map(lambda p_: [ (2.*p_[1] *(1.0 -p_[0]**2)), (-2.*p_[0] *(1.0 -p_[1]**2))], mesh.boundaryCenters()))) drawStreams(ax2, mesh, vC) f = pg.RVector(mesh.cellCount(), 0.0) ##f[mesh.findCell([-0.75, 0.75]).id()]=1000.0
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]) scheme.set('m', [3, 2, 1]) scheme.set('n', [2, 3, 0]) for pos in scheme.sensorPositions(): world.createNode(pos) # world.createNode(pos + pg.RVector3(0, -0.1)) mesh = mt.createMesh(world, quality=34) rhomap = [ [1, 99.595 + 8.987j], [2, 99.595 + 8.987j], [3, 59.595 + 8.987j], ] ert = pb.ERTManager() data = ert.simulate(mesh, res=rhomap, scheme=scheme, verbose=True) rhoa = data.get('rhoa').array() phia = data.get('phia').array() # make sure all computed responses are equal, especially the first two, which # only differ in the sign of their geometrical factor np.testing.assert_allclose(rhoa, rhoa[0])
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") #pg.show(geom, ax=ax, fillRegion=False, savefig='T_field.pdf') # just hold figure windows open if run outside from spyder, ipython or similar pg.wait()
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)) pg.show(mesh_gradient, vel_gradient, label="Velocity (m/s)") ###############################################################################