def mergeMeshes(meshList, verbose=False): """Merge several meshes into one new mesh and return the new mesh. Merge several meshes into one new mesh and return the new mesh. Parameters ---------- meshList : [:gimliapi:`GIMLI::Mesh`, ...] | [str, ...] List of at least two meshes or (filenames to meshes) to be merged. verbose : bool Give some output See Also -------- merge2Meshes """ if not isinstance(meshList, list): raise Exception("Argument meshList is no list") if len(meshList) < 2: raise Exception( "To few meshes in meshList, at least 2 meshes are needed.") if isinstance(meshList[0], str): mL = [] if verbose: print("Reading meshes ... ") for mFileName in meshList: m = pg.Mesh(2) m.load(mFileName) if verbose: print("loaded", mFileName, m) mL.append(m) meshList = mL #meshList = [pg.Mesh(2); m.load(m) ] if verbose: print("Merging meshes ... ") mesh = meshList[0] if verbose: print(mesh) for m in range(1, len(meshList)): mesh = merge2Meshes(mesh, meshList[m]) if verbose: print(mesh) return mesh
def tetgen(filename, quality=1.2, preserveBoundary=False, verbose=False): """Create a mesh with :term:`Tetgen` from file. Create a :term:`Tetgen` :cite:`Si2004` mesh from a PLC. Forwards to system call tetgen, which must be known to your system. Parameters ---------- filename: str quality: float [1.2] Refines mesh (to improve mesh quality). [1.1 ... ] preserveBoundary: bool [False] Preserve PLC boundary mesh verbose: bool [False] be verbose Returns ------- mesh : :gimliapi:`GIMLI::Mesh` """ filebody = filename.replace('.poly', '') syscal = 'tetgen -pazAC' syscal += 'q' + str(quality) if not verbose: syscal += 'Q' else: syscal += 'V' if preserveBoundary: syscal += 'Y' syscal += ' ' + filebody + '.poly' if verbose: print(syscal) system(syscal) system('meshconvert -it -BD -o ' + filebody + ' ' + filebody + '.1') try: os.remove(filebody + '.1.node') os.remove(filebody + '.1.ele') os.remove(filebody + '.1.face') except BaseException as e: print(e) mesh = pg.Mesh(filebody) return mesh
def restore(self): """Read data from json infos""" if os.path.exists(self._name + '.json'): # Fricking mpl kills locale setting to system default .. this went # horrible wrong for german 'decimal_point': ',' pg.checkAndFixLocaleDecimal_point(verbose=False) try: with open(self._name + '.json') as file: self.info = json.load(file) # if len(self.info['type']) != 1: # pg.error('only single return caches supported for now.') if self.info['type'] == 'DataContainerERT': self._value = pg.DataContainerERT(self.info['file'], removeInvalid=False) # print(self._value) elif self.info['type'] == 'RVector': self._value = pg.Vector() self._value.load(self.info['file'], format=pg.core.Binary) elif self.info['type'] == 'Mesh': pg.tic() self._value = pg.Mesh() self._value.loadBinaryV2(self.info['file'] + '.bms') pg.debug("Restoring cache took:", pg.dur(), "s") elif self.info['type'] == 'ndarray': self._value = np.load(self.info['file'] + '.npy', allow_pickle=True) else: self._value = np.load(self.info['file'] + '.npy', allow_pickle=True) if self.value is not None: self.info['restored'] = self.info['restored'] + 1 self.updateCacheInfo() pg.info('Cache {3} restored ({1}s x {0}): {2}'.\ format(self.info['restored'], round(self.info['dur'], 1), self._name, self.info['codeinfo'])) else: # default try numpy pg.warn('Could not restore cache of type {0}.'.format(self.info['type'])) pg.debug("Restoring cache took:", pg.dur(), "s") except Exception as e: import traceback traceback.print_exc(file=sys.stdout) print(self.info) pg.error('Cache restoring failed.')
def triangle(p2=False): mesh = pg.Mesh() n1 = mesh.createNode(0.0, 0.0, 0.0) n2 = mesh.createNode(1.0, 0.0, 0.0) # n3 = mesh.createNode(1.0, 1.0, 0.0) n4 = mesh.createNode(0.0, 1.0, 0.0) mesh.createTriangle(n1, n2, n4) mesh.rotate(pg.RVector3(0.0, 0.0, 45)) # mesh.createTriangle(n2, n3, n4) if p2: mesh = mesh.createP2() show(mesh)
def quadrangle(p2=False): mesh = pg.Mesh() n1 = mesh.createNode(0.0, 0.0, 0.0) n2 = mesh.createNode(1.0, 0.0, 0.0) n3 = mesh.createNode(1.0, 1.0, 0.0) n4 = mesh.createNode(0.0, 1.0, 0.0) mesh.createQuadrangle(n1, n2, n3, n4) mesh.rotate(pg.RVector3(0.0, 0.0, 45)) mesh.scale(pg.RVector3(1.0, 0.5, 1.0)) if p2: mesh = mesh.createP2() show(mesh)
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 readHydrus3dMesh(filename='MESHTRIA.TXT'): """Import mesh from Hydrus3D. Parameters ---------- fname : str, optional Filename of Hydrus output file. See Also -------- readHydrus2dMesh : Similar routine for two-dimensional meshes. References ---------- .. http://www.pc-progress.com/en/Default.aspx?h3d-description """ f = open(filename, 'r') for i in range(6): line1 = f.readline() nnodes = int(line1.split()[0]) ncells = int(line1.split()[1]) # print(nnodes, ncells) line1 = f.readline() nodes = [] dx = 0.01 mesh = pg.Mesh() for _ in range(nnodes): pos = f.readline().split() p = pg.RVector3( float(pos[1]) * dx, float(pos[2]) * dx, float(pos[3]) * dx * (-1.)) n = mesh.createNode(p) nodes.append(n) line1 = f.readline() line1 = f.readline() cells = [] for _ in range(ncells): pos = f.readline().split() i, j, k, l = int(pos[1]), int(pos[2]), int(pos[3]), int(pos[4]), c = mesh.createTetrahedron(nodes[i - 1], nodes[j - 1], nodes[k - 1], nodes[l - 1]) cells.append(c) f.close() mesh.createNeighbourInfos() return mesh
def refineQuad2Tri(mesh, style=1): """Refine mesh of quadrangles into a mesh of triangle cells. TODO mixed meshes Parameters ---------- mesh : :gimliapi:`GIMLI::Mesh` mesh containing quadrangle cells style: int [1] * 1 bisect each quadrangle into 2 triangles * 2 bisect each quadrangle into 4 triangles Returns ------- ret : :gimliapi:`GIMLI::Mesh` mesh containing triangle cells """ out = pg.Mesh(2) newNode = None for n in mesh.nodes(): out.createNode(n.pos()) for c in mesh.cells(): if style == 1: out.createCell([c.node(0).id(), c.node(1).id(), c.node(2).id()]) out.createCell([c.node(0).id(), c.node(2).id(), c.node(3).id()]) elif style == 2: newNode = out.createNodeWithCheck(c.center()) for i in range(4): out.createCell( [c.node(i).id(), c.node((i + 1) % 4).id(), newNode.id()]) for i in range(c.boundaryCount()): b = c.boundary(i) if b.marker() != 0: out.createBoundary( [b.node(0).id(), b.node(1).id()], b.marker()) out.createNeighbourInfos() return out
def test_io_triangle(self): """ """ # create tempfile in most secure manner, only accesible by this process # id no execution allowed at all, will be deleted as soon as this # process stops try: import tempfile as tmp except ImportError: return _, name2D = tmp.mkstemp(suffix='.poly') # 2D, creating test trinangle poly m = pg.Mesh(2) nodes = [] nodes.append(m.createNode([-1, -2])) nodes.append(m.createNode([-1, 2])) nodes.append(m.createNode([1, 2])) nodes.append(m.createNode([1, -2])) for i in range(4): m.createEdge(nodes[i], nodes[(i + 1) % 4]) nodes.append(m.createNode([-1, -3])) nodes.append(m.createNode([1, -3])) m.createEdge(nodes[0], nodes[4]) m.createEdge(nodes[1], nodes[5]) m.createEdge(nodes[4], nodes[5]) m.addRegionMarker([0., 0.], -3, area=-1) m.addRegionMarker([0., -2.5], 1, area=42.42) pg.meshtools.exportPLC(m, name2D) # 2D, test triangle mesh for consistincy poly = pg.meshtools.readPLC(name2D) np.testing.assert_allclose(poly.regionMarkers()[0].array(), np.array([0., -2.5, 0.])) np.testing.assert_allclose(poly.holeMarkers()[0].array(), np.array([0., 0., 0.])) np.testing.assert_allclose(np.sort(poly.positions().array()), np.sort(m.positions().array())) np.testing.assert_equal(poly.regionMarkers()[0].area(), 42.42) try: os.remove(name2D) except: print("can't remove:", name2D)
def tetrahedron( p2 ): mesh = g.Mesh( 3 ) n0 = mesh.createNode( 0.0, 0.0, 0.0 ) n1 = mesh.createNode( 1.0, 0.0, 0.0 ) n2 = mesh.createNode( 0.0, 1.0, 0.0 ) n3 = mesh.createNode( 0.0, 0.0, 1.0 ) mesh.createTetrahedron( n0, n1, n2, n3 ) mesh.rotate( g.RVector3( 10.0, 34.0, 45 ) ) mesh.scale( g.RVector3( 0.9, 0.8, 0.7 ) ) if p2: mesh = mesh.createP2() show( 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 exportHDF5Mesh(mesh, exportname, group='mesh', indices='cell_indices', pos='coordinates', cells='topology', marker='values'): """Writes given :gimliapi:`GIMLI::Mesh` in a hdf5 format file. 3D tetrahedron meshes only! Boundary markers are ignored. Keywords are explained in :py:mod:`pygimli.meshtools.readHDFS` """ h5py = pg.optImport('h5py', requiredFor='export mesh in .h5 data format') if not isinstance(mesh, pg.Mesh): mesh = pg.Mesh(mesh) # prepare output for writing in hdf data container pg_pos = mesh.positions() mesh_pos = np.array((np.array(pg.x(pg_pos)), np.array(pg.y(pg_pos)), np.array(pg.z(pg_pos)))).T mesh_cells = np.zeros((mesh.cellCount(), 4)) # hard coded for tetrahedrons for i, cell in enumerate(mesh.cells()): mesh_cells[i] = cell.ids() mesh_indices = np.arange(0, mesh.cellCount() + 1, 1, dtype=np.int64) mesh_markers = np.array(mesh.cellMarkers()) with h5py.File(exportname, 'w') as out: for grp in np.atleast_1d(group): # can use more than one group # writing indices idx_name = '{}/{}'.format(grp, indices) out.create_dataset(idx_name, data=mesh_indices, dtype=int) # writing node positions pos_name = '{}/{}'.format(grp, pos) out.create_dataset(pos_name, data=mesh_pos, dtype=float) # writing cells via indices cells_name = '{}/{}'.format(grp, cells) out.create_dataset(cells_name, data=mesh_cells, dtype=int) # writing marker marker_name = '{}/{}'.format(grp, marker) out.create_dataset(marker_name, data=mesh_markers, dtype=int) out[grp][cells].attrs['celltype'] = np.string_('tetrahedron') out[grp][cells].attrs.create('partition', [0]) return True
def createMesh2(): boundary = [] boundary.append([-20.0, 0.0]) boundary.append([-20.0, -20.0]) boundary.append([20.0, -20.0]) boundary.append([20.0, 0.0]) poly = pg.Mesh(2) nodes = [poly.createNode(b) for b in boundary] poly.createEdge(nodes[0], nodes[1], 1) # dirichlet (inflow) poly.createEdge(nodes[1], nodes[2], 3) # hom neumann (outflow) poly.createEdge(nodes[2], nodes[3], 2) # hom dirichlet (isolation) poly.createEdge(nodes[3], nodes[0], 4) # hom dirichlet (isolation) mesh = createMesh(poly, quality=34, area=0.05, smooth=[0, 10]) return mesh
def readHydrus2dMesh(fname='MESHTRIA.TXT'): """ Import mesh from Hydrus2D. Parameters ---------- fname : str, optional Filename of Hydrus output file. See Also -------- readHydrus3dMesh : Similar routine for three-dimensional meshes. References ---------- .. http://www.pc-progress.com/en/Default.aspx?h3d-description """ fid = open(fname) line = fid.readline().split() nnodes = int(line[1]) ncells = int(line[3]) mesh = pg.Mesh() for _ in range(nnodes): line = fid.readline().split() mesh.createNode( pg.RVector3(float(line[1]) / 100., float(line[2]) / 100., 0.)) for _ in range(3): line = fid.readline() for _ in range(ncells): line = fid.readline().split() if len(line) == 4: mesh.createTriangle(mesh.node(int(line[1]) - 1), mesh.node(int(line[2]) - 1), mesh.node(int(line[3]) - 1), 1) elif len(line) == 5: mesh.createTetrahedron(mesh.node(int(line[1]) - 1), mesh.node(int(line[2]) - 1), mesh.node(int(line[3]) - 1), mesh.node(int(line[4]) - 1), 1) fid.close() mesh.createNeighbourInfos() return mesh
def exportHDF5Mesh(mesh, exportname, group='mesh', indices='cell_indices', pos='coordinates', cells='topology', marker='values'): ''' 3D tetrahedron meshes only! Boundary markers are ignored. Keywords are explained in "readH5" ''' h5py = pg.io.opt_import('h5py', requiredTo='export mesh in .h5 data format') if not isinstance(mesh, pg.Mesh): mesh = pg.Mesh(mesh) # prepare output for writing in hdf data container pg_pos = mesh.positions() mesh_pos = np.array((np.array(pg.x(pg_pos)), np.array(pg.y(pg_pos)), np.array(pg.z(pg_pos)))).T mesh_cells = np.zeros((mesh.cellCount(), 4)) # hard coded for tetrahedrons for i, cell in enumerate(mesh.cells()): mesh_cells[i] = cell.ids() mesh_indices = np.arange(0, mesh.cellCount() + 1, 1, dtype=np.int64) mesh_markers = np.array(mesh.cellMarkers()) with h5py.File(exportname, 'w') as out: # writing indices idx_name = '{}/{}'.format(group, indices) out.create_dataset(idx_name, data=mesh_indices, dtype=np.int64) # writing node positions pos_name = '{}/{}'.format(group, pos) out.create_dataset(pos_name, data=mesh_pos, dtype=float) # writing cells via indices cells_name = '{}/{}'.format(group, cells) out.create_dataset(cells_name, data=mesh_cells, dtype=np.int64) # writing marker marker_name = '{}/{}'.format(group, marker) out.create_dataset(marker_name, data=mesh_markers, dtype=np.uint64) out[group][cells].attrs['celltype'] = np.array(('tetrahedron')) out[group][cells].attrs['partition'] = np.array([0], dtype=np.uint64) return True
def createLine(start, end, segments, **kwargs): """Create simple line polygon. Create simple line polygon from start to end. Parameters ---------- start : [x, y] start position end : [x, y] end position segments : int Discrete amount of segments for the line **kwargs: boundaryMarker : int [1] Marker for the resulting boundary edges leftDirection : bool [True] Rotational direction Returns ------- poly : gimliapi:`GIMLI::Mesh` The resulting polygon is a gimliapi:`GIMLI::Mesh`. Examples -------- """ poly = pg.Mesh(2) startPos = pg.RVector3(start) endPos = pg.RVector3(end) a = endPos - startPos dt = 1 / segments for i in range(0, segments + 1): if kwargs.pop('leftDirection', True): p = startPos + a * (dt * i) else: p = endPos - a * (dt * i) poly.createNode(p) polyCreateDefaultEdges_(poly, isClosed=False, **kwargs) return poly
def test_MeshDataAccess(self): mesh = pg.Mesh() a = pg.Vector(10, 1.0) b = [pg.Vector(10, 1.0)] * 3 c = np.array(b).T mesh['a'] = a mesh['b'] = b mesh['v'] = c mesh['vs'] = [c, c, c] # pg.core.setDeepDebug(True) # pg.core.setDeepDebug(False) np.testing.assert_array_equal(mesh['a'], a) np.testing.assert_array_equal(mesh['b'], b) np.testing.assert_array_equal(mesh['v'], c) np.testing.assert_array_equal(mesh['vs'], [c, c, c])
def __init__(self, mesh, ertfop, rstfop, petromodel, fix_poro=True, zWeight=1, verbose=True, corr_l=None, fix_water=False, fix_ice=False, fix_air=False): """Joint petrophysical modeling operator. Parameters ---------- mesh : pyGIMLi mesh ertfop : ERT forward operator rstfop : RST forward operator petromodel : Petrophysical four-phase model zWeight : zWeight for more or less layering verbose : Be more verbose corr_l : tuple Horizontal and vertical correlation lengths. If provided, geostatistical regularization will be used and classical smoothing with zWeight will be ignored. fix_poro|water|ice|air : boolean or vector Fix to starting model or provide weight vector for particular cells. """ pg.ModellingBase.__init__(self, verbose) self.mesh = pg.Mesh(mesh) self.ERT = ertfop self.RST = rstfop self.fops = [self.RST, self.ERT] self.fpm = petromodel self.cellCount = self.mesh.cellCount() self.fix_water = fix_water self.fix_ice = fix_ice self.fix_air = fix_air self.fix_poro = fix_poro self.zWeight = zWeight # self.fix_cells = fix_cells self.corr_l = corr_l self.createConstraints()
def merge2Meshes(m1, m2): """Merge two meshes into one new mesh and return combined mesh.""" mesh = pg.Mesh(m1) for c in m2.cells(): mesh.copyCell(c) for b in m2.boundaries(): mesh.copyBoundary(b) for key in list(mesh.exportDataMap().keys()): d = mesh.exportDataMap()[key] d.resize(mesh.cellCount()) d.setVal(m1.exportDataMap()[key], 0, m1.cellCount()) d.setVal(m2.exportDataMap()[key], m1.cellCount(), m1.cellCount() + m2.cellCount()) mesh.addExportData(key, d) return mesh
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 createHolstein1999Model(): mesh = pg.Mesh(3) mesh.createNode(pg.RVector3(0, 0, 0)) # dummy mesh.createNode(pg.RVector3(+10, 10, -12)) mesh.createNode(pg.RVector3(+10, -10, -12)) mesh.createNode(pg.RVector3(-10, -10, -12)) mesh.createNode(pg.RVector3(-10, 10, -12)) mesh.createNode(pg.RVector3(-20, 30, -12)) mesh.createNode(pg.RVector3(+30, 30, -12)) mesh.createNode(pg.RVector3(+20, 20, -22)) mesh.createNode(pg.RVector3(+20, -30, -22)) mesh.createNode(pg.RVector3(-20, -30, -22)) mesh.createNode(pg.RVector3(-20, 20, -22)) facets = [[1, 6, 5, 4, 3, 2], [1, 2, 8, 7], [2, 3, 9, 8], [3, 4, 10, 9], [4, 5, 10], [5, 6, 7, 10], [1, 7, 6], [7, 8, 9, 10]] return mesh, facets
def init(self, mesh, tMax, satSteps, ertSteps): """Initialize some settings.""" if mesh is not None: self.parMesh = pg.Mesh(mesh) self.setMesh(mesh) self.createRefinedForwardMesh(refine=False, pRefine=False) self.tMax = tMax self.satSteps = satSteps self.ertSteps = ertSteps self.timesAdvection = np.linspace(1, tMax, satSteps) self.timesERT = pg.IndexArray( np.floor( np.linspace(0, len(self.timesAdvection) - 1, self.ertSteps))) self._J = pg.Matrix() self.setJacobian(self._J) self.ws = WorkSpace()
def createFwdMesh_(self): """""" pg.info("Creating forward mesh from region infos.") m = pg.Mesh(self.regionManager().mesh()) regionIds = self.regionManager().regionIdxs() for iId in regionIds: pg.verbose("\tRegion: {0}, Parameter: {1}, PD: {2}," " Single: {3}, Background: {4}, Fixed: {5}" .format(iId, self.regionManager().region(iId).parameterCount(), self.regionManager().region(iId).isInParaDomain(), self.regionManager().region(iId).isSingle(), self.regionManager().region(iId).isBackground(), self.regionManager().region(iId).fixValue(), )) m = self.createRefinedFwdMesh(m) self.setMeshPost(m) self._regionChanged = False super(Modelling, self).setMesh(m, ignoreRegionManager=True)
def createMesh(self, quality=34.6, maxarea=0.1, addpoints=None): """Create (inversion) mesh by circumventing PLC""" data = self.dataContainer sx = list(pg.x(data.sensorPositions())) sz = list(pg.y(data.sensorPositions())) if addpoints is not None: for po in addpoints: sx.append(po[0]) sz.append(po[1]) iS = np.argsort(np.arctan2(sx - np.mean(sx), sz - np.mean(sz))) plc = pg.Mesh(2) nodes = [plc.createNode(sx[i], sz[i], 0) for i in iS] for i in range(len(nodes) - 1): plc.createEdge(nodes[i], nodes[i + 1]) plc.createEdge(nodes[-1], nodes[0]) tri = pg.TriangleWrapper(plc) tri.setSwitches("-pzFq" + str(quality) + "a" + str(maxarea)) self.setMesh(tri.generate())
def test_zweight_2meshes(self): # marker = 0 mesh = pg.meshtools.createGrid(x=np.arange(0, 4), y=np.arange(0, 3)) mesh.setCellMarkers(np.zeros(mesh.cellCount(), dtype=int)) # marker = 1 mesh2 = pg.Mesh(mesh) mesh2.setCellMarkers(np.ones(mesh.cellCount(), dtype=int)) together = pg.meshtools.merge2Meshes( mesh, mesh2.translate(pg.Vector([0., 0., 1.]))) fop = pg.Modelling() fop.setMesh(together) fop.createConstraints() rm = fop.regionManager() rm.setZWeight(0.1) # check distribution of zWeight self.assertTrue(np.isclose(rm.region(0).zWeight(), 0.1)) self.assertTrue(np.isclose(rm.region(1).zWeight(), 0.1)) # self.assertTrue(np.isclose(rm.region(2).zWeight(), 0.1)) w0 = rm.region(0).constraintWeights() w1 = rm.region(1).constraintWeights() # print(w0, w1) # w2 = rm.region(2).constraintWeights() # check actual constraint weight values self.assertTrue(np.isclose(np.min(w0), 0.1)) # check distribution of zWeight self.assertTrue(np.allclose(w0, w1))
def readSTL(fileName, ascii=True): """Read :term:`STL` surface mesh and returns a :gimliapi:`GIMLI::Mesh`. Read :term:`STL` surface mesh and returns a :gimliapi:`GIMLI::Mesh` of triangle boundary faces. Multiple solids are supported with increasing boundary marker. TODO: ASCII=False, read binary STL Parameters ---------- fileName : str name of the .stl file containing the STL surface mesh ascii : bool [True] STL Ascii format """ mesh = pg.Mesh(dim=3) mesh.importSTL(fileName) return mesh
def __init__(self, data, nlay=2, verbose=False): """Parameters: FDEM data class and number of layers.""" super(FDEM2dFOP, self).__init__(verbose) self.nlay = nlay self.FOP = data.FOP(nlay) self.nx = len(data.x) self.nf = len(data.freq()) npar = 2 * nlay - 1 self.mesh2d = pg.Mesh() self.mesh2d.create2DGrid(range(npar + 1), range(self.nx + 1)) self.setMesh(self.mesh2d) self.J = pg.RBlockMatrix() self.FOP1d = [] for i in range(self.nx): self.FOP1d.append(HEMmodelling(nlay, data.z[i])) n = self.J.addMatrix(self.FOP1d[-1].jacobian()) self.J.addMatrixEntry(n, self.nf * 2 * i, npar * i) self.J.recalcMatrixSize() print(self.J.rows(), self.J.cols()) self.setJacobian(self.J)
def test_Refraction(): """Test Refraction manager stability some data/mesh set / data update""" import os datafile = os.path.dirname(__file__) + '/example_topo.sgt' ra = Refraction(datafile, verbose=False, doSave=False) ra.createMesh(depth=80) ra.inv.setMaxIter(1) ra.invert() m1 = ra.model() mesh = pg.Mesh(ra.mesh) ra.setMesh(mesh) ra.invert() m2 = ra.model() np.testing.assert_array_equal(m1, m2) ra.setData(pg.DataContainer(datafile, 's g')) m3 = ra.invert() np.testing.assert_array_equal(m1, m3)
def createMesh(poly, quality=30, area=0.0, smooth=None, switches=None, verbose=False, **kwargs): """Create a mesh for a given geometry polygon. The mesh is created by :term:`triangle` or :term:`tetgen` if the gimli support for these mesh generators are installed. The geometry needs to contain nodes and boundaries and should be valid in the sense that the boundaries are non intersecting. If poly is a list of coordinates a simple Delaunay mesh of the convex hull will be created. TODO: Tetgen support need to be implemented Parameters ---------- poly: :gimliapi:`GIMLI::Mesh` or list * 2D or 3D gimli mesh that contains the PLC. * 2D mesh needs edges * 3D mesh needs ... to be implemented * List of x y pairs [[x0, y0], ... ,[xN, yN]] * PLC or list of PLC quality: float 2D triangle quality sets a minimum angle constraint. Be careful with values above 34 degrees. area: float 2D maximum triangle size in m*m smooth: tuple [smoothing algorithm, number of iterations] 0, no smoothing 1, node center 2, weighted node center switches: str Force triangle to use the gives command switches. Returns ------- mesh: :gimliapi:`GIMLI::Mesh` Examples -------- >>> # no need to import matplotlib. pygimli's show does >>> import pygimli as pg >>> import pygimli.meshtools as mt >>> rect = mt.createRectangle(start=[0, 0], end=[4, 1]) >>> ax, _ = pg.show(mt.createMesh(rect, quality=10)) >>> ax, _ = pg.show(mt.createMesh(rect, quality=33)) >>> ax, _ = pg.show(mt.createMesh(rect, quality=33, area=0.01)) >>> pg.wait() """ # poly == [pg.Mesh, ] if isinstance(poly, list): if isinstance(poly[0], pg.Mesh): return createMesh(pg.meshtools.mergePLC(poly), quality, area, smooth, switches, verbose) # poly == [pos, pos, ] if isinstance(poly, list) or isinstance(poly, type(zip)): delPLC = pg.Mesh(2) for p in poly: delPLC.createNode(p[0], p[1], 0.0) return createMesh(delPLC, switches='-zeY') # poly == Mesh if poly.dim() == 2: if poly.nodeCount() == 0: raise Exception("No nodes in poly to create a valid mesh") tri = pg.TriangleWrapper(poly) if switches is None: # -D Conforming delaunay # -F Uses Steven Fortune's sweepline algorithm # no -a here ignores per region area switches = 'pazeA' if area > 0: switches += 'a' + str(area) pass else: switches += 'a' # switches = switches.replace('.', ',') switches += 'q' + str(quality) if not verbose: switches += 'Q' if verbose: print(switches) tri.setSwitches(switches) mesh = tri.generate() if smooth is not None: mesh.smooth(nodeMoving=kwargs.pop('node_move', False), edgeSwapping=False, smoothFunction=smooth[0], smoothIteration=smooth[1]) return mesh else: raise Exception('not yet implemented')
def createParaMesh2DGrid(sensors, paraDX=1, paraDZ=1, paraDepth=0, nLayers=11, boundary=-1, paraBoundary=2, **kwargs): """Create a grid style mesh for an inversion parameter mesh. Create a grid style mesh for an inversion parameter mesh. Return parameter grid for a given list of sensor positions. Uses and forwards arguments to :py:mod:`pygimli.meshtools.appendTriangleBoundary`. Parameters ---------- sensors : list of RVector3 objects or data container with sensorPositions Sensor positions. Must be sorted in positive x direction paraDX : float, optional Horizontal distance between sensors, relative regarding sensor distance. Value must be greater than 0 otherwise 1 is assumed. paraDZ : float, optional Vertical distance to the first depth layer, relative regarding sensor distance. Value must be greater than 0 otherwise 1 is assumed. paraDepth : float, optional Maximum depth for parametric domain, 0 (default) means 0.4 * maximum sensor range. nLayers : int, optional [11] Number of depth layers. boundary : int, optional [-1] Boundary width to be appended for domain prolongation in absolute para domain width. Values lower than 0 force the boundary to be 4 times para domain width. paraBoundary : int, optional [2] Offset to the parameter domain boundary in absolute sensor spacing. Returns ------- mesh: :gimliapi:`GIMLI::Mesh` Examples -------- >>> import pygimli as pg >>> import matplotlib.pyplot as plt >>> >>> from pygimli.meshtools import createParaMesh2DGrid >>> mesh = createParaMesh2DGrid(sensors=pg.RVector(range(10)), ... boundary=1, paraDX=1, ... paraDZ=1, paraDepth=5) >>> ax, _ = pg.show(mesh, mesh.cellMarkers(), alpha=0.3, cmap="summer", ... hold=True) >>> ax, _ = pg.show(mesh, ax=ax) """ mesh = pg.Mesh(2) # maybe separate x y z and sort if isinstance(sensors, np.ndarray) or isinstance(sensors, pg.RVector): sensors = [pg.RVector3(s, 0) for s in sensors] sensorX = pg.x(sensors) eSpacing = abs(sensorX[1] - sensorX[0]) xmin = min(sensorX) - paraBoundary * eSpacing xmax = max(sensorX) + paraBoundary * eSpacing if paraDX == 0: paraDX = 1. if paraDZ == 0: paraDZ = 1. dx = eSpacing * paraDX dz = eSpacing * paraDZ if paraDepth == 0: paraDepth = 0.4 * (xmax - xmin) x = pg.utils.grange(xmin, xmax, dx=dx) y = -pg.increasingRange(dz, paraDepth, nLayers) mesh.createGrid(x, y) mesh.setCellMarkers([2] * mesh.cellCount()) paraXLimits = [xmin, xmax] # paraYLimits = [min(y), max(y)] # not used if boundary < 0: boundary = abs((paraXLimits[1] - paraXLimits[0]) * 4.0) mesh = pg.meshtools.appendTriangleBoundary(mesh, xbound=boundary, ybound=boundary, marker=1, **kwargs) return mesh