from solverFVM import solveFiniteVolume, createFVPostProzessMesh # build domain nSteps = 20 dPhi = (0.6 * np.pi) / nSteps boundaries = [] for i in range(1, nSteps + 1): boundaries.append([np.cos(dPhi * i), np.sin(dPhi * i)]) poly = pg.Mesh(2) nodes = [] for b in boundaries: nodes.append(poly.createNode(b)) for b in boundaries[::-1]: nodes.append(poly.createNode(pg.RVector3(b) * 0.1)) for i in range(len(nodes)): poly.createEdge(nodes[i], nodes[(i + 1) % len(nodes)], 1) mesh = createMesh(poly, quality=34, area=0.001, smooth=[0, 10]) f = pg.Vector(mesh.cellCount(), 10) a = pg.Vector(mesh.cellCount(), 0.1) #Start FEM solution swatch = pg.core.Stopwatch(True) uDirichlet = [ 1, lambda p_: np.sin(np.arctan2(p_.center()[1], p_.center()[0])) / p_.center().abs() ]
def appendTriangleBoundary(mesh, xbound=10, ybound=10, marker=1, quality=34.0, area=0.0, smooth=False, markerBoundary=1, isSubSurface=False, verbose=False): """Add a triangle mesh boundary to a given mesh. Returns a new mesh that contains a triangulated box around a given mesh suitable for geo-simulation (surface boundary at top). Parameters ---------- mesh : mesh object Mesh to which the triangle boundary should be appended. xbound : float, optional Horizontal prolongation distance. Minimal mesh 0.5 x extension. ybound : float, optional Vertical prolongation distance. Minimal mesh 0.5 y extension. marker : int, optional Marker of new cells. markerBoundary : int, optional Marker of the inner boundary edges between mesh and new boundary. quality : float, optional Triangle quality. area: float, optional Triangle max size within the boundary. smooth : boolean, optional Apply mesh smoothing. isSubSurface : boolean, optional Apply boundary conditions suitable for geo-simulation and prolongate mesh to the surface if necessary. verbose : boolean, optional Be verbose. Examples -------- >>> import matplotlib.pyplot as plt >>> import pygimli as pg >>> from pygimli.mplviewer import drawMesh, drawModel >>> from pygimli.meshtools import appendTriangleBoundary >>> inner = pg.createGrid(range(5), range(5), marker=1) >>> mesh = appendTriangleBoundary(inner, xbound=3, ybound=6, marker=2) >>> fig, (ax1, ax2) = plt.subplots(1,2) >>> p1 = drawMesh(ax1, inner) >>> p2 = drawModel(ax2, mesh, mesh.cellMarkers(), label='marker') >>> p3 = drawMesh(ax2, mesh) >>> txt1 = ax1.set_title("a) Input grid") >>> txt2 = ax2.set_title("b) With triangle boundary") See Also -------- appendTetrahedronBoundary """ surface = 0.0 # find boundaries on left/right/bottom/top side le = [b for b in mesh.boundaries() if b.center().x() == mesh.xmin()] bo = [b for b in mesh.boundaries() if b.center().y() == mesh.ymin()] ri = [b for b in mesh.boundaries() if b.center().x() == mesh.xmax()] top = [b for b in mesh.boundaries() if b.center().y() == mesh.ymax()] # gather all right boundary nodes after sorting in boundaryNodes tmp = [] for b in ri: if b.node(0) not in tmp: tmp.append(b.node(0)) if b.node(1) not in tmp: tmp.append(b.node(1)) tmp.sort(key=lambda n: n.pos().y()) tmp.reverse() boundaryNodes = tmp # gather all bottom boundary nodes and add them to boundaryNodes boNode = [] for b in bo: if b.node(0) not in boNode + boundaryNodes: boNode.append(b.node(0)) if b.node(1) not in boNode + boundaryNodes: boNode.append(b.node(1)) boNode.sort(key=lambda n: n.pos().x()) boNode.reverse() boundaryNodes = boundaryNodes + boNode # gather all left boundary nodes and add them to boundaryNodes tmp = [] for b in le: if b.node(0) not in tmp + boundaryNodes: tmp.append(b.node(0)) if b.node(1) not in tmp + boundaryNodes: tmp.append(b.node(1)) tmp.sort(key=lambda n: n.pos().y()) boundaryNodes = boundaryNodes + tmp if isSubSurface: # gather all top boundary nodes and add them to boundaryNodes topNodes = [] for boundary in top: if boundary.node(0) not in topNodes + boundaryNodes: topNodes.append(boundary.node(0)) if boundary.node(1) not in topNodes + boundaryNodes: topNodes.append(boundary.node(1)) topNodes.sort(key=lambda n: n.pos().x()) boundaryNodes = boundaryNodes + topNodes poly = pg.Mesh() preserveSwitch = '' if isSubSurface: # add all boundary nodes for n in boundaryNodes: poly.createNode(n.pos()) # and connect them by a closed polygon for i in range(0, poly.nodeCount()): poly.createEdge(poly.node(i), poly.node( (i + 1) % poly.nodeCount()), markerBoundary) # add four corners of the world box xtLen = 12 # x bottom boundary sampling points # xBottom = pg.asvector(np.linspace(mesh.xmin() - xbound, # mesh.xmax() + xbound, xtLen)) n1 = poly.createNode(pg.RVector3(mesh.xmax() + xbound, surface, 0.0)) n2 = poly.createNode(pg.RVector3(mesh.xmin() - xbound, surface, 0.0)) n3 = poly.createNode( pg.RVector3(mesh.xmin() - xbound, mesh.ymin() - ybound, 0.0)) n4 = poly.createNode( pg.RVector3(mesh.xmax() + xbound, mesh.ymin() - ybound, 0.0)) # and connect them by a closed polygon poly.createEdge(n1, n2, pg.MARKER_BOUND_HOMOGEN_NEUMANN) poly.createEdge(n2, n3, pg.MARKER_BOUND_MIXED) poly.createEdge(n3, n4, pg.MARKER_BOUND_MIXED) poly.createEdge(n4, n1, pg.MARKER_BOUND_MIXED) else: # no isSubSurface xbound = max(xbound, 0.5 * (mesh.xmax() - mesh.xmin())) ybound = max(ybound, 0.5 * (mesh.ymax() - mesh.ymin())) # add top right node and boundary nodes dxMin = boNode[0].pos().distance(boNode[1].pos()) * 1.1 xtLen = max(5, int(xbound / dxMin / 2.)) # x top boundary sampling points xTop = pg.increasingRange(dxMin, xbound, xtLen) # y boundary sampling points yLeft = pg.increasingRange(xTop[len(xTop) - 1] - xTop[len(xTop) - 2], abs(mesh.ymin() - ybound), xtLen) xtLen = max(5, int((mesh.xmax() - mesh.xmin()) / dxMin / 2.)) # x bottom boundary sampling points xBottom = pg.RVector( np.linspace(mesh.xmin() - xbound, mesh.xmax() + xbound, 2 * xtLen)) for i, val in enumerate(pg.fliplr(xTop)(0, len(xTop) - 1)): poly.createNode([mesh.xmax() + val, mesh.ymax(), 0.0]) for n in boundaryNodes: poly.createNode(n.pos()) # add top left, bottom left and bottom right node for t in xTop(1, len(xTop)): poly.createNode([mesh.xmin() - t, mesh.ymax(), 0.0]) for t in yLeft(1, len(yLeft)): poly.createNode([mesh.xmin() - xbound, mesh.ymax() - t, 0.0]) for t in xBottom(1, len(xBottom) - 1): poly.createNode([t, mesh.ymin() - ybound, 0.0]) for t in pg.fliplr(yLeft)(0, len(yLeft) - 1): poly.createNode([mesh.xmax() + xbound, mesh.ymax() - t, 0.0]) # create a closed polygon through all new nodes for i in range(0, poly.nodeCount()): poly.createEdge(poly.node(i), poly.node( (i + 1) % poly.nodeCount()), markerBoundary) preserveSwitch = 'Y' # poly.exportVTK('out.poly') mesh2 = pg.Mesh(2) # call triangle mesh generation triswitches = '-pzeAfa' + preserveSwitch + 'q' + str(quality) if area > 0: triswitches += 'a' + str(area) if not verbose: triswitches += 'Q' if isSubSurface: margin = 0.0001 poly.addHoleMarker( pg.RVector3(mesh.xmin() + margin, mesh.ymax() - margin)) tri = pg.TriangleWrapper(poly) tri.setSwitches(triswitches) tri.generate(mesh2) else: pg.TriangleWrapper(poly, mesh2, triswitches) if smooth: mesh2.smooth(nodeMoving=True, edgeSwapping=True, smoothFunction=1, smoothIteration=2) mesh2.setCellMarkers([marker] * mesh2.cellCount()) # map copy the cell not the reference, this should not happen # map( lambda cell: mesh2.copyCell( cell ), mesh2.cells() ) for cell in mesh.cells(): mesh2.copyCell(cell) # old neighbor infos need to be cleaned since the new cells are added mesh2.createNeighbourInfos(force=True) for b in mesh2.boundaries(): if b.leftCell() is None or b.rightCell() is None: if b.center().y() == mesh2.ymax(): b.setMarker(pg.MARKER_BOUND_HOMOGEN_NEUMANN) else: b.setMarker(pg.MARKER_BOUND_MIXED) return mesh2
def interpolateAlongCurve(curve, t, **kwargs): """Interpolate along curve. Return curve coordinates for a piecewise linear curve :math:`C(t) = {x_i,y_i,z_i}` at positions :math:`t`. Curve and :math:`t` values are expected to be sorted along distance from the origin of the curve. Parameters ---------- curve : [[x,z]] | [[x,y,z]] | [:gimliapi:`GIMLI::RVector3`] | :gimliapi:`GIMLI::R3Vector` Discrete curve for 2D :math:`x,z` curve=[[x,z]], 3D :math:`x,y,z` t: 1D iterable Query positions along the curve in absolute distance kwargs : If kwargs are given, an additional curve smoothing is applied using :py:mod:`pygimli.meshtools.interpolate`. The kwargs will be delegated. periodic : bool [False] Curve is periodic. Usefull for closed parametric spline interpolation. Returns ------- p : np.array Curve positions at query points :math:`t`. Dimension of p match the size of curve the coordinates. Examples -------- >>> import numpy as np >>> import pygimli as pg >>> import pygimli.meshtools as mt >>> fig, axs = pg.plt.subplots(2,2) >>> topo = np.array([[-2., 0.], [-1., 0.], [0.5, 0.], [3., 2.], [4., 2.], [6., 1.], [10., 1.], [12., 1.]]) >>> t = np.arange(15.0) >>> p = mt.interpolateAlongCurve(topo, t) >>> _= axs[0,0].plot(topo[:,0], topo[:,1], '-x', mew=2) >>> _= axs[0,1].plot(p[:,0], p[:,1], 'o', color='red') #doctest: +ELLIPSIS >>> >>> p = mt.interpolateAlongCurve(topo, t, method='spline') >>> _= axs[1,0].plot(p[:,0], p[:,1], '-o', color='black') #doctest: +ELLIPSIS >>> >>> p = mt.interpolateAlongCurve(topo, t, method='harmonic', nc=3) >>> _= axs[1,1].plot(p[:,0], p[:,1], '-o', color='green') #doctest: +ELLIPSIS >>> >>> pg.plt.show() """ xC = np.zeros(len(curve)) yC = np.zeros(len(curve)) zC = np.zeros(len(curve)) tCurve = kwargs.pop('tCurve', None) if tCurve is None: tCurve = pg.utils.cumDist(curve) dim = 3 # extrapolate starting overlaps if min(t) < min(tCurve): d = pg.RVector3(curve[1]) - pg.RVector3(curve[0]) # d[2] = 0.0 d.normalise() curve = np.insert(curve, [0], [ curve[0] - np.array(d * (min(tCurve) - min(t)))[0:curve.shape[1]] ], axis=0) tCurve = np.insert(tCurve, 0, min(t), axis=0) # extrapolate ending overlaps if max(t) > max(tCurve): d = pg.RVector3(curve[-2]) - pg.RVector3(curve[-1]) # d[2] = 0.0 d.normalise() curve = np.append(curve, [ curve[-1] - np.array(d * (max(t) - max(tCurve)))[0:curve.shape[1]] ], axis=0) tCurve = np.append(tCurve, max(t)) if isinstance(curve, pg.core.R3Vector) or isinstance( curve, pg.core.stdVectorRVector3): xC = pg.x(curve) yC = pg.y(curve) zC = pg.z(curve) else: curve = np.array(curve) if curve.shape[1] == 2: xC = curve[:, 0] zC = curve[:, 1] dim = 2 else: xC = curve[:, 0] yC = curve[:, 1] zC = curve[:, 2] if len(kwargs.keys()) > 0 and (kwargs.get('method', 'linear') != 'linear'): # interpolate more curve points to get a smooth line, guarantee to keep # original positions ti = np.array([np.linspace(tCurve[i], tCurve[i+1], 20)[:-1] for i in range(len(tCurve)-1)]).flatten() ti = np.append(ti, tCurve[-1]) xC = pg.interpolate(ti, tCurve, xC, **kwargs) zC = pg.interpolate(ti, tCurve, zC, **kwargs) if dim == 3: yC = pg.interpolate(ti, tCurve, yC, **kwargs) tCurve = ti xt = interpolate(t, tCurve, xC) zt = interpolate(t, tCurve, zC) if dim == 2: return np.vstack([xt, zt]).T yt = interpolate(t, tCurve, yC) return np.vstack([xt, yt, zt]).T
# def test3d() def functor(x, p): """ """ return (p[1] - x[1]) / (x.dist(p)**2.) # def rz( pos, P ) mesh = pg.Mesh(2) # mesh.load('mesh/world2d.bms') A = mesh.createNode(pg.RVector3(-1., -1.)) B = mesh.createNode(pg.RVector3(-2., -1.)) C = mesh.createNode(pg.RVector3(-2., -2.)) D = mesh.createNode(pg.RVector3(-1., -2.)) mesh.createTriangle(A, B, C) # mesh.createQuadrangle(A, B, C, D) mesh.scale(pg.RVector3(3., 3.)) # mesh.createTriangle(A, B, D) print mesh.cellSizes() x = np.arange(-10, 10, 1.) rho = pg.RVector(len(mesh.cellAttributes()), 1.) * 2000.0 print(rho) pnts = pg.stdVectorRVector3()
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 _createParameterContraintsLines(mesh, cMat, cWeights=None): """Create line segments representing constrains. """ C = None if isinstance(cMat, pg.matrix.SparseMapMatrix): tmp = pg.optImport('tempfile') _, tmpFile = tmp.mkstemp(suffix='.matrix') C = pg.Matrix() cMat.save(tmpFile) pg.loadMatrixCol(C, tmpFile) try: import os os.remove(tmpFile) except Exception as e: pg.error(e) print("can't remove:", tmpFile) else: C = cMat cellList = dict() for c in mesh.cells(): pID = c.marker() if pID not in cellList: cellList[pID] = [] cellList[pID].append(c) paraCenter = dict() for pID, vals in list(cellList.items()): p = pg.RVector3(0.0, 0.0, 0.0) for c in vals: p += c.center() p /= float(len(vals)) paraCenter[pID] = p nConstraints = cMat.rows() start = [] end = [] # swatch = pg.core.Stopwatch(True) # not used i = -1 while i < C[0].size(): cID = C[0][i] a = C[1][i] b = None if i < C[0].size() - 1: if C[0][i + 1] == cID: b = C[1][i + 1] i += 1 if b is not None: if cWeights[cID] > 0: p1 = paraCenter[a] p2 = paraCenter[b] if cWeights is not None: pa = pg.RVector3(p1 + (p2 - p1) / 2.0 * (1.0 - cWeights[cID])) pb = pg.RVector3(p2 + (p1 - p2) / 2.0 * (1.0 - cWeights[cID])) else: pa = p1 pb = p2 start.append(pa) end.append(pb) else: start.append(paraCenter[a]) end.append(paraCenter[a]) i += 1 return start, end
def createRectangle(start=None, end=None, pos=None, size=None, **kwargs): """Create rectangle polygon. Create rectangle with start position and a given size. Give either start and end OR pos and size. Parameters ---------- start : [x, y] Left upper corner. Default [-0.5, 0.5] end : [x, y] Right lower corner. Default [0.5, -0.5] pos : [x, y] Center position. The rectangle will be moved. size : [x, y] width and height. The rectangle will be scaled. **kwargs: marker : int [1] Marker for the resulting triangle cells after mesh generation area : float [0] Maximum cell size for resulting triangles after mesh generation boundaryMarker : int [1] Marker for the resulting boundary edges leftDirection : bool [True] TODO Rotational direction isHole : bool [False] The Polygone will become a hole instead of a triangulation isClosed : bool [True] Add closing edge between last and first node. Returns ------- poly : :gimliapi:`GIMLI::Mesh` The resulting polygon is a :gimliapi:`GIMLI::Mesh`. Examples -------- >>> import matplotlib.pyplot as plt >>> import pygimli as pg >>> from pygimli.meshtools import createRectangle >>> rectangle = createRectangle(start=[4, -4], end=[6, -6], ... marker=4, area=0.1) >>> _ = pg.show(rectangle) """ # if not ((start and end) or (pos and size)): # raise BaseException("createRectangle pls. give either start and end" # "OR pos and size.") if start is None: start = [-0.5, 0.5] if end is None: end = [0.5, -0.5] poly = pg.Mesh(dim=2, isGeometry=True) sPos = pg.RVector3(start) ePos = pg.RVector3(end) poly.createNode(sPos) poly.createNode([sPos[0], ePos[1]]) poly.createNode(ePos) poly.createNode([ePos[0], sPos[1]]) if kwargs.pop('isHole', False): poly.addHoleMarker(sPos + (ePos - sPos) * 0.2) else: poly.addRegionMarker(sPos + (ePos - sPos) * 0.2, marker=kwargs.pop('marker', 1), area=kwargs.pop('area', 0)) if size is not None: poly.scale(size) if pos is not None: poly.translate(pos) polyCreateDefaultEdges_(poly, **kwargs) return poly
def save_p3d(paraDomain, model_array, mesh_cut_tool_param, step, file_name, local_coord=False): """Saves result as .p3d file.""" base_point, gen_vecs = cut_point_cloud.cut_tool_to_gen_vecs( mesh_cut_tool_param) x_nodes = math.floor(np.linalg.norm(gen_vecs[0]) / step) + 1 y_nodes = math.floor(np.linalg.norm(gen_vecs[1]) / step) + 1 z_nodes = math.floor(np.linalg.norm(gen_vecs[2]) / step) + 1 x_knots = [1 / (x_nodes - 1) * i for i in range(x_nodes)] y_knots = [1 / (y_nodes - 1) * i for i in range(y_nodes)] z_knots = [1 / (z_nodes - 1) * i for i in range(z_nodes)] grid = [[[0.0] * x_nodes for _ in range(y_nodes)] for _ in range(z_nodes)] inv_tr_mat = cut_point_cloud.inv_tr(gen_vecs) for i in range(paraDomain.cellCount()): cell = paraDomain.cell(i) for j, n in enumerate(cell.nodes()): nl = cut_point_cloud.tr_to_local(base_point, inv_tr_mat, np.array([n[0], n[1], n[2]])) if j == 0: cxmin = cxmax = nl[0] cymin = cymax = nl[1] czmin = czmax = nl[2] else: if nl[0] < cxmin: cxmin = nl[0] elif nl[0] > cxmax: cxmax = nl[0] if nl[1] < cymin: cymin = nl[1] elif nl[1] > cymax: cymax = nl[1] if nl[2] < czmin: czmin = nl[2] elif nl[2] > czmax: czmax = nl[2] x_s = 0 for i in range(1, len(x_knots)): if x_knots[i] < cxmin: x_s = i else: break x_e = len(x_knots) for i in reversed(range(0, len(x_knots))): if x_knots[i] > cxmax: x_e = i else: break y_s = 0 for i in range(1, len(y_knots)): if y_knots[i] < cymin: y_s = i else: break y_e = len(y_knots) for i in reversed(range(0, len(y_knots))): if y_knots[i] > cymax: y_e = i else: break z_s = 0 for i in range(1, len(z_knots)): if z_knots[i] < czmin: z_s = i else: break z_e = len(z_knots) for i in reversed(range(0, len(z_knots))): if z_knots[i] > czmax: z_e = i else: break r = model_array[cell.id()] shape = cell.shape() for k in range(z_s, z_e): for j in range(y_s, y_e): for i in range(x_s, x_e): v = base_point + gen_vecs[0] * x_knots[i] + gen_vecs[ 1] * y_knots[j] + gen_vecs[2] * z_knots[k] if shape.isInside(pg.RVector3(v)): grid[k][j][i] = r def five_writer(fd): i = 0 def write(s): nonlocal i i += 1 if i > 1: fd.write(" ") fd.write(s) if i >= 5: fd.write("\n") i = 0 def finalize(): nonlocal i if i > 0: fd.write("\n") return write, finalize if local_coord: base_point = np.array([0.0, 0.0, 0.0]) l0 = np.linalg.norm(gen_vecs[0]) l1 = np.linalg.norm(gen_vecs[1]) phi = math.acos( (gen_vecs[0][0] * gen_vecs[1][0] + gen_vecs[0][1] * gen_vecs[1][1]) / (l0 * l1)) gen_vecs[0] = np.array([l0, 0.0, 0.0]) gen_vecs[1] = np.array([l1 * math.cos(phi), l1 * math.sin(phi), 0.0]) with open(file_name + ".p3d", "w") as fd_p3d: with open(file_name + ".q", "w") as fd_q: fd_p3d.write("{} {} {}\n".format(x_nodes, y_nodes, z_nodes)) fd_q.write("{} {} {}\n".format(x_nodes, y_nodes, z_nodes)) fd_q.write("{:.10g} {:.10g} {:.10g} {:.10g}\n".format( 0.0, 0.0, 0.0, 0.0)) x_list = [] y_list = [] z_list = [] p3d_write, p3d_finalize = five_writer(fd_p3d) q_write, q_finalize = five_writer(fd_q) for rrr, zl in zip(grid, z_knots): for rr, yl in zip(rrr, y_knots): for r, xl in zip(rr, x_knots): q_write("{:.10g}".format(r)) v = base_point + gen_vecs[0] * xl + gen_vecs[ 1] * yl + gen_vecs[2] * zl x_list.append(v[0]) y_list.append(v[1]) z_list.append(v[2]) for v in x_list: p3d_write("{:.10g}".format(v)) for v in y_list: p3d_write("{:.10g}".format(v)) for v in z_list: p3d_write("{:.10g}".format(v)) s = "{:.10g}".format(0.0) for _ in range(x_nodes * y_nodes * z_nodes * 4): q_write(s) p3d_finalize() q_finalize()
def drawShapes(ax, mesh, u): ''' ''' ax.set_aspect('equal') Nx = 21 Ny = 21 nLevels = 12 tix = np.linspace(-1.0, 1.0, Nx) tiy = np.linspace(-1.0, 1.0, Ny) X, Y = np.meshgrid(tix, tiy) uc = pg.RVector(len(X.flat)) c = mesh.cell(0) imax = pg.find(u == max(u))[0] for i in range(c.nodeCount()): print(c.rst(i)) print(imax) print(c.createShapeFunctions()[imax]) print("dx", c.createShapeFunctions()[imax].derive(0)) print("dy", c.createShapeFunctions()[imax].derive(1)) # draw nodes for i in range(c.nodeCount()): col = 'black' if i == imax: col = 'red' ax.plot(c.node(i).pos()[0], c.node(i).pos()[1], '.', markersize=12, linewidth=0, color=col) # draw boundary drawMeshBoundaries(ax, mesh) ptns = [] grads = [] swatch = pg.Stopwatch(True) for i, x in enumerate(X.flat): p = c.shape().xyz(pg.RVector3(X.flat[i], Y.flat[i])) X.flat[i] = p[0] Y.flat[i] = p[1] # ax.plot(p[0], p[1], '.', zorder=10, color='black', markersize = 1) if not c.shape().isInside(p): uc[i] = -99.0 continue uc[i] = c.pot(p, u) gr = c.grad(p, u) ptns.append(p) grads.append(gr) print(swatch.duration(True)) for i, p in enumerate(ptns): ax.quiver(p[0], p[1], grads[i][0], grads[i][1], zorder=10) Z = np.ma.masked_where(uc == -99., uc) Z = Z.reshape(Ny, Nx) ax.contourf(X, Y, Z, nLevels)
def inv_st(inversion_conf, project_conf): inv_par = inversion_conf.inversion_param cut_par = inversion_conf.mesh_cut_tool_param remove_old_files() ret, bw_surface = prepare(cut_par, inv_par, project_conf) if not ret: return #return # snap electrodes print() print_headline("Snapping electrodes") if inv_par.meshFrom == MeshFrom.SURFACE_CLOUD: snap_surf.main(inv_par, project_conf, bw_surface, max_dist=inv_par.snapDistance) else: snap_electrodes.main(inv_par, project_conf, max_dist=inv_par.snapDistance) #ball_mesh("inv_mesh.msh", "inv_mesh2.msh", [-622342, -1128822, 22], 5.0) #return print() print_headline("Creating inversion mesh") mesh_from_brep("inv_mesh_tmp.brep", "inv_mesh_tmp.msh2", project_conf, inv_par) print() print_headline("Modify mesh") modify_mesh("inv_mesh_tmp.msh2", "inv_mesh.msh", cut_par) #if inv_par.meshFrom == MeshFrom.SURFACE_CLOUD: print() print_headline("Snapping electrodes final") snap_electrodes.main(inv_par, project_conf, max_dist=inv_par.snapDistance, final=True) print() print_headline("Inversion") # load data file data = pg.DataContainer("input_snapped.dat", sensorTokens='s g', removeInvalid=False) # remove invalid data oldsize = data.size() data.removeInvalid() newsize = data.size() if newsize < oldsize: print('Removed ' + str(oldsize - newsize) + ' values.') # create FOP fop = pg.core.TravelTimeDijkstraModelling(verbose=inv_par.verbose) fop.setThreadCount(psutil.cpu_count(logical=False)) fop.setData(data) # create Inv inv = pg.core.RInversion(verbose=inv_par.verbose, dosave=False) # variables tD, tM are needed to prevent destruct objects tM = pg.core.RTransLogLU(1.0 / inv_par.maxModel, 1.0 / inv_par.minModel) tD = pg.core.RTrans() inv.setTransData(tD) inv.setTransModel(tM) inv.setForwardOperator(fop) # mesh mesh_file = "inv_mesh.msh" if mesh_file == "": depth = inv_par.depth if depth is None: depth = pg.core.DCParaDepth(data) poly = pg.meshtools.createParaMeshPLC( data.sensorPositions(), paraDepth=depth, paraDX=inv_par.paraDX, paraMaxCellSize=inv_par.maxCellArea, paraBoundary=2, boundary=2) if inv_par.verbose: print("creating mesh...") mesh = pg.meshtools.createMesh(poly, quality=inv_par.quality, smooth=(1, 10)) else: mesh = pg.Mesh(pg.load(mesh_file)) mesh.createNeighbourInfos() mesh.createSecondaryNodes() if inv_par.verbose: print(mesh) sys.stdout.flush() # flush before multithreading fop.setMesh(mesh) fop.regionManager().setConstraintType(1) if not inv_par.omitBackground: if fop.regionManager().regionCount() > 1: fop.regionManager().region(1).setBackground(True) if mesh_file == "": fop.createRefinedForwardMesh(True, False) else: fop.createRefinedForwardMesh(inv_par.refineMesh, inv_par.refineP2) paraDomain = fop.regionManager().paraDomain() inv.setForwardOperator(fop) # necessary? # inversion parameters inv.setData(data('t')) absoluteError = 0.001 relativeError = 0.001 inv.setAbsoluteError(absoluteError + data('t') * relativeError) #inv.setRelativeError(pg.RVector(data.size(), 0.03)) fop.regionManager().setZWeight(inv_par.zWeight) inv.setLambda(inv_par.lam) inv.setOptimizeLambda(inv_par.optimizeLambda) inv.setMaxIter(inv_par.maxIter) inv.setRobustData(inv_par.robustData) inv.setBlockyModel(inv_par.blockyModel) inv.setRecalcJacobian(inv_par.recalcJacobian) startModel = fop.createDefaultStartModel() inv.setModel(startModel) # Run the inversion sys.stdout.flush() # flush before multithreading model = inv.run() velocity = 1.0 / model[paraDomain.cellMarkers()] np.savetxt('velocity.vector', velocity) paraDomain.addData('Velocity', velocity) #paraDomain.exportVTK('velocity') # output in local coordinates if inv_par.local_coord: base_point, gen_vecs = cut_point_cloud.cut_tool_to_gen_vecs(cut_par) localparaDomain = pg.Mesh(paraDomain) localparaDomain.translate(pg.RVector3(-base_point)) localparaDomain.rotate( pg.RVector3(0, 0, -math.atan2(gen_vecs[0][1], gen_vecs[0][0]))) localparaDomain.exportVTK('velocity') else: paraDomain.exportVTK('velocity') if inv_par.p3d: print() print_headline("Saving p3d") t = time.time() save_p3d(paraDomain, 1.0 / model.array(), cut_par, inv_par.p3dStep, "velocity", inv_par.local_coord) print("save_p3d elapsed time: {:0.3f} s".format(time.time() - t)) print() print("All done.")
def inv_ert(inversion_conf, project_conf): inv_par = inversion_conf.inversion_param cut_par = inversion_conf.mesh_cut_tool_param remove_old_files() ret, bw_surface = prepare(cut_par, inv_par, project_conf) if not ret: return #return # snap electrodes print() print_headline("Snapping electrodes") if inv_par.meshFrom == MeshFrom.SURFACE_CLOUD: snap_surf.main(inv_par, project_conf, bw_surface, max_dist=inv_par.snapDistance) else: snap_electrodes.main(inv_par, project_conf, max_dist=inv_par.snapDistance) #ball_mesh("inv_mesh.msh", "inv_mesh2.msh", [-622342, -1128822, 22], 5.0) #return print() print_headline("Creating inversion mesh") mesh_from_brep("inv_mesh_tmp.brep", "inv_mesh_tmp.msh2", project_conf, inv_par) print() print_headline("Modify mesh") modify_mesh("inv_mesh_tmp.msh2", "inv_mesh.msh", cut_par) #if inv_par.meshFrom == MeshFrom.SURFACE_CLOUD: print() print_headline("Snapping electrodes final") snap_electrodes.main(inv_par, project_conf, max_dist=inv_par.snapDistance, final=True) print() print_headline("Inversion") # res = pb.Resistivity("input.dat") # res.invert() # np.savetxt('resistivity.vector', res.resistivity) # return # load data file data = pg.DataContainerERT("input_snapped.dat", removeInvalid=False) #data = pg.DataContainerERT("ldp2.dat") #print(data.size()) #print(data("a")) #print(data.sensorIdx()) #return # mark all data valid #data.markValid(data('rhoa') > 0) #data.markValid(data('rhoa') <= 0) #data.markValid(data('u') > 0) # k, rhoa #inv_par.k_ones = True if inv_par.k_ones: data.set("k", np.ones(data.size())) else: data.set("k", misc.geometricFactors(data)) #data.set("err", pb.Resistivity.estimateError(data, absoluteUError=0.0001, relativeError=0.03)) #data.set("k", np.ones(data.size())) #data.set("k", misc.geometricFactors(data)) data.set("rhoa", data("u") / data("i") * data("k")) tolerance = 1e-12 #data.markValid(np.abs(data('rhoa')) > tolerance) data.markValid(data('rhoa') > tolerance) data.markInvalid(data('rhoa') <= tolerance) # udelat poradne # remove invalid data oldsize = data.size() data.removeInvalid() newsize = data.size() if newsize < oldsize: print('Removed ' + str(oldsize - newsize) + ' values.') if not data.allNonZero('rhoa'): print("No or partial rhoa values.") return # check, compute error # if data.allNonZero('err'): # error = data('err') # else: # print("estimate data error") # error = inv_par.relativeError + inv_par.absoluteError / data('rhoa') error = data('err') min_err = 0.0005 for i in range(data.size()): if error[i] < min_err: error[i] = min_err # create FOP fop = pg.core.DCSRMultiElectrodeModelling(verbose=inv_par.verbose) fop.setThreadCount(psutil.cpu_count(logical=False)) fop.setData(data) # create Inv inv = pg.core.RInversion(verbose=inv_par.verbose, dosave=False) # variables tD, tM are needed to prevent destruct objects tM = pg.core.RTransLogLU(inv_par.minModel, inv_par.maxModel) if inv_par.data_log: tD = pg.core.RTransLog() inv.setTransData(tD) inv.setTransModel(tM) inv.setForwardOperator(fop) # mesh mesh_file = "inv_mesh.msh" #mesh_file = inv_par.meshFile if mesh_file == "": depth = inv_par.depth if depth is None: depth = pg.core.DCParaDepth(data) poly = pg.meshtools.createParaMeshPLC( data.sensorPositions(), paraDepth=depth, paraDX=inv_par.paraDX, paraMaxCellSize=inv_par.maxCellArea, paraBoundary=2, boundary=2) if inv_par.verbose: print("creating mesh...") mesh = pg.meshtools.createMesh(poly, quality=inv_par.quality, smooth=(1, 10)) else: mesh = pg.Mesh(pg.load(mesh_file)) mesh.createNeighbourInfos() if inv_par.verbose: print(mesh) sys.stdout.flush() # flush before multithreading fop.setMesh(mesh) fop.regionManager().setConstraintType(1) # print(fop.regionManager().regionCount()) # print(fop.regionManager().paraDomain().cellMarkers()) # pg.show(mesh, data=mesh.cellMarkers()) # print(fop.regionManager().region(1).cellMarkers()) # return if not inv_par.omitBackground: if fop.regionManager().regionCount() > 1: fop.regionManager().region(1).setBackground(True) if mesh_file == "": fop.createRefinedForwardMesh(True, False) else: fop.createRefinedForwardMesh(inv_par.refineMesh, inv_par.refineP2) paraDomain = fop.regionManager().paraDomain() #paraDomain = fop.regionManager().mesh() inv.setForwardOperator(fop) # necessary? # in_ball = find_markers_in_ball(paraDomain, [-622342, -1128822, 22], 5.0) # print(pg.median(data('rhoa'))) # pc = fop.regionManager().parameterCount() # x = pg.RVector(pc, 10000.0) # for i, m in enumerate(paraDomain.cellMarkers()): # if m in in_ball: # x[i] = 1000.0 # resp = fop.response(x) # print(resp) #return # inversion parameters inv.setData(data('rhoa')) #inv.setData(resp) inv.setRelativeError(error) #inv.setRelativeError(pg.RVector(data.size(), 0.03)) fop.regionManager().setZWeight(inv_par.zWeight) inv.setLambda(inv_par.lam) inv.setOptimizeLambda(inv_par.optimizeLambda) inv.setMaxIter(inv_par.maxIter) inv.setRobustData(inv_par.robustData) inv.setBlockyModel(inv_par.blockyModel) inv.setRecalcJacobian(inv_par.recalcJacobian) pc = fop.regionManager().parameterCount() if inv_par.k_ones: # hack of gimli hack v = pg.Vector( pg.Vector( pc, pg.core.median(data('rhoa') * misc.geometricFactors(data)))) v[0] += tolerance * 2 startModel = v else: startModel = pg.Vector(pc, pg.core.median(data('rhoa'))) #startModel = pg.RVector(pc, 2000.0) inv.setModel(startModel) # Run the inversion sys.stdout.flush() # flush before multithreading model = inv.run() resistivity = model[paraDomain.cellMarkers()] np.savetxt('resistivity.vector', resistivity) paraDomain.addData('Resistivity', resistivity) #paraDomain.addExportData('Resistivity (log10)', np.log10(resistivity)) #paraDomain.addExportData('Coverage', coverageDC(fop, inv, paraDomain)) #paraDomain.exportVTK('resistivity') # output in local coordinates if inv_par.local_coord: base_point, gen_vecs = cut_point_cloud.cut_tool_to_gen_vecs(cut_par) localparaDomain = pg.Mesh(paraDomain) localparaDomain.translate(pg.RVector3(-base_point)) localparaDomain.rotate( pg.RVector3(0, 0, -math.atan2(gen_vecs[0][1], gen_vecs[0][0]))) localparaDomain.exportVTK('resistivity') else: paraDomain.exportVTK('resistivity') # measurements on model print() print_headline("Measurements on model") with open("measurements_info.json") as fd: meas_info = MeasurementsInfo.deserialize(json.load(fd)) resp = fop.response(resistivity) # hack of gimli hack v = pg.Vector(startModel) v[0] += tolerance * 2 resp_start = fop.response(v) map = {} map_start = {} map_appres_gimli = {} for i in range(data.size()): map[(data("a")[i], data("b")[i], data("m")[i], data("n")[i])] = resp[i] map_start[(data("a")[i], data("b")[i], data("m")[i], data("n")[i])] = resp_start[i] map_appres_gimli[(data("a")[i], data("b")[i], data("m")[i], data("n")[i])] = data('rhoa')[i] meas_model_info = MeasurementsModelInfo() with open("measurements_model.txt", "w") as fd: fd.write( "meas_number ca cb pa pb I[A] V[V] AppRes[Ohmm] std AppResGimli[Ohmm] AppResModel[Ohmm] ratio AppResStartModel[Ohmm] start_ratio\n" ) fd.write( "-------------------------------------------------------------------------------------------------------------------------------------------------\n" ) for item in meas_info.items: k = (item.inv_ca, item.inv_cb, item.inv_pa, item.inv_pb) if k in map: m_on_m = "{:17.2f} {:17.2f} {:7.2f} {:22.2f} {:7.2f}".format( map_appres_gimli[k], map[k], map[k] / map_appres_gimli[k], map_start[k], map_start[k] / map_appres_gimli[k]) meas_model_info.items.append( MeasurementModelInfoItem( measurement_number=item.measurement_number, ca=item.ca, cb=item.cb, pa=item.pa, pb=item.pb, app_res_model=map[k], app_res_start_model=map_start[k])) else: m_on_m = " not used" fd.write( "{:11} {:3} {:3} {:3} {:3} {:8.6f} {:9.6f} {:12.2f} {:6.4f} {}\n" .format(item.measurement_number, item.ca, item.cb, item.pa, item.pb, item.I, item.V, item.AppRes, item.std, m_on_m)) with open("measurements_model_info.json", "w") as fd: json.dump(meas_model_info.serialize(), fd, indent=4, sort_keys=True) if inv_par.p3d: print() print_headline("Saving p3d") t = time.time() save_p3d(paraDomain, model.array(), cut_par, inv_par.p3dStep, "resistivity", inv_par.local_coord) print("save_p3d elapsed time: {:0.3f} s".format(time.time() - t)) print() print("All done.")
# Optional: show the geometry #pg.show(geom) # Create a Dipole Dipole ('dd') measuring scheme with n electrodes. scheme = pb.createData(elecs=pg.utils.grange(start=0, end=86, n=43), schemeName='dd') simulData = pg.createERTData(scheme, schemeName='dd') # Put all electrodes (aka. sensors positions) into the PLC to enforce mesh # refinement. Due to experience known, its convenient to add further refinement # nodes in a distance of 10% of electrode spacing, to achieve sufficient # numerical accuracy. for pos in scheme.sensorPositions(): geom.createNode(pos) geom.createNode(pos + pg.RVector3(0, -0.1)) # Create a mesh for the finite element modelling with appropriate mesh quality. mesh = mt.createMesh(geom, quality=34) # Create a map to set resistivity values in the appropriate regions # [[regionNumber, resistivity], [regionNumber, resistivity], [...] rhomap = [[0, 2000.], [1, 10.], [2, 50.], [3, 500.], [4, 2000.]] # Optional: take a look at the mesh pg.show(mesh, data=rhomap, label='Resistivity $(\Omega$m)', showMesh=True) # Initialize the ERTManager (The class name is a subject to further change!) ert = pb.ERTManager() # Perform the modeling with the mesh and the measuring scheme itself
P15_6 = T3_3 * E2_2T * (2. * (T3_3 + E2_2T) + -3.) P15_7 = T6_4 * E2_1T P15_8 = T6_5 * E2_1T P15_9 = T6_6 * E2_1T P15_10 = T6_4 * E2_2T P15_11 = T6_5 * E2_2T P15_12 = T6_6 * E2_2T P15_13 = T3_1 * E3_3T P15_14 = T3_2 * E3_3T P15_15 = T3_3 * E3_3T pnts = g.stdVectorRVector3() # quad pnts.append(g.RVector3(0.0, 0.0)) pnts.append(g.RVector3(1.0, 0.0)) pnts.append(g.RVector3(1.0, 1.0)) pnts.append(g.RVector3(0.0, 1.0)) pnts.append(g.RVector3(0.5, 0.5)) #pnts.append( g.RVector3( 0.5, 0.0 ) ) #pnts.append( g.RVector3( 1.0, 0.5 ) ) #pnts.append( g.RVector3( 0.5, 1.0 ) ) #pnts.append( g.RVector3( 0.0, 0.5 ) ) ## tri #pnts.append( g.RVector3( 0.0, 0.0 ) ) #pnts.append( g.RVector3( 1.0, 0.0 ) ) #pnts.append( g.RVector3( 0.0, 1.0 ) ) #pnts.append( g.RVector3( 0.5, 0.0 ) ) #pnts.append( g.RVector3( 0.5, 0.5 ) )
def readEIDORSMesh(fileName, matlabVarname, verbose=False): """Reads finite element model in EIDORS format and returns pygimli mesh. Parameters ---------- fileName : str name of the .mat file containing the EIDORS model matlabVarname : str variable name of .mat file in MATLAB workspace """ if not pg.optImport("scipy", requiredFor="read EIDORS mesh."): raise ImportError('cannot import sciyp') import scipy.io as spio def todict(matobj): dict = {} for strg in matobj._fieldnames: elem = matobj.__dict__[strg] if isinstance(elem, spio.matlab.mio5_params.mat_struct): dict[strg] = todict(elem) else: dict[strg] = elem return dict def check_keys(dict): for key in dict: if isinstance(dict[key], spio.matlab.mio5_params.mat_struct): dict[key] = todict(dict[key]) return dict def loadmat(fileName): data = spio.loadmat(fileName, struct_as_record=False, squeeze_me=True) return check_keys(data) def get_nested(data, *args): if args and data: element = args[0] if element: value = data.get(element) return value if len(args) == 1 else get_nested( value, *args[1:]) matlab_eidors = loadmat(fileName) python_eidors = get_nested(matlab_eidors, matlabVarname) # if input eidors data is forward model instead of an image if 'nodes' in python_eidors.keys(): nodes = get_nested(python_eidors, "nodes") elems = get_nested(python_eidors, "elems") boundary_numbers = get_nested(python_eidors, "boundary_numbers") # it is an image with elem_data and fwd_model else: nodes = get_nested(python_eidors, "fwd_model", "nodes") elems = get_nested(python_eidors, "fwd_model", "elems") boundary_numbers = get_nested(python_eidors, "fwd_model", "boundary_numbers") dim_nodes = np.size(nodes, 1) dim_elems = np.size(elems, 1) if verbose: print('Reading %s... ' % fileName) print('found %s %s-dimensional nodes... ' % (np.size(nodes, 0), dim_nodes)) if dim_elems == 3 and verbose: print('found %s triangles... ' % np.size(elems, 0)) elif dim_elems == 4 and verbose: print('found %s tetrahedrons... ' % np.size(elems, 0)) if 'elem_data' in python_eidors.keys(): elem_data = get_nested(python_eidors, "elem_data") if verbose: print('found %s element data... ' % len(elem_data)) else: if verbose: print("found no element data... ") region_markers = np.unique(boundary_numbers) no_of_regions = len(region_markers) if boundary_numbers is not None: if verbose: print('Found %s Unique Regions with Region Markers' % no_of_regions) print('%s' % region_markers) if boundary_numbers is None: if verbose: print('Found no Unique Region with Region Markers') # create nodes from eidors model mesh = pg.Mesh() # if two dimensional eidors model if (dim_nodes == 2 and dim_elems == 3): if verbose: print('converting to %d-D pygimli mesh... ' % dim_nodes) for i in range(len(nodes)): mesh.createNode(pg.RVector3(nodes[i, 0], nodes[i, 1], 0.)) for i in range(len(elems)): mesh.createTriangle(mesh.node(int(elems[i, 0]) - 1), mesh.node(int(elems[i, 1]) - 1), mesh.node(int(elems[i, 2]) - 1), 1) # for non-planar 2D models if (dim_nodes == 3 and dim_elems == 3): if verbose: print('converting to pygimli mesh...') print('found 3d nodes with 2d elements') for i in range(len(nodes)): mesh.createNode(pg.RVector3(nodes[i, 0], nodes[i, 1], nodes[i, 2])) for i in range(len(elems)): mesh.createTriangle(mesh.node(int(elems[i, 0]) - 1), mesh.node(int(elems[i, 1]) - 1), mesh.node(int(elems[i, 2]) - 1), 1) # if three dimensional eidors model if (dim_nodes == 3 and dim_elems == 4): if verbose: print('converting to %d-D pygimli mesh... ' % dim_nodes) for i in range(len(nodes)): mesh.createNode(pg.RVector3(nodes[i, 0], nodes[i, 1], nodes[i, 2])) for i in range(len(elems)): mesh.createTetrahedron(mesh.node(int(elems[i, 0]) - 1), mesh.node(int(elems[i, 1]) - 1), mesh.node(int(elems[i, 2]) - 1), mesh.node(int(elems[i, 3]) - 1), 1) if boundary_numbers is not None: mesh.setCellMarkers(boundary_numbers.astype(int)) return mesh
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 -------- >>> # no need to import matplotlib. pygimli's show does >>> import pygimli as pg >>> import pygimli.meshtools as mt >>> >>> w = mt.createWorld(start=[0, 0], end=[3, 3]) >>> l1 = mt.createLine(start=[1, 1], end=[1, 2], segments=1, ... leftDirection=False) >>> l2 = mt.createLine(start=[1, 1], end=[2, 1], segments=20, ... leftDirection=True) >>> >>> ax, _ = pg.show(mt.createMesh([w, l1, l2,])) >>> ax, _ = pg.show([w, l1, l2,], ax=ax) >>> pg.wait() """ poly = pg.Mesh(2) startPos = pg.RVector3(start) endPos = pg.RVector3(end) a = endPos - startPos dt = 1. / segments left = kwargs.pop('leftDirection', True) for i in range(0, segments + 1): if left: p = startPos + a * (dt * i) else: p = endPos - a * (dt * i) poly.createNode(p) polyCreateDefaultEdges_(poly, isClosed=False, **kwargs) return poly
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, markers=True, showMesh=True) """ 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] if isinstance(sensors, pg.DataContainer): sensors = sensors.sensorPositions() 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 = paraDX dz = paraDZ if eSpacing > 0: dx = eSpacing * paraDX # dz = eSpacing * paraDZ # not really making sense if paraDepth == 0: paraDepth = 0.4 * (xmax - xmin) # print(xmin, xmax, dx) 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
def streamlineDir(mesh, field, startCoord, dLengthSteps, dataMesh=None, maxSteps=1000, down=True, verbose=False, koords=(0, 1)): """ down = -1, up = 1, both = 0 """ xd = [] yd = [] vd = [] counter = 0 pot = None vx = None vy = None isVectorData = False if hasattr(field[0], '__len__'): if min(field[:, 0]) == max(field[:, 0]) and \ min(field[:, 1]) == max(field[:, 1]): raise BaseException("No data range streamline: min/max == ", min(field[:, 0])) vx = pg.RVector(field[:, 0]) vy = pg.RVector(field[:, 1]) isVectorData = True else: if min(field) == max(field): raise BaseException("No data range for streamline: min/max == ", min(field)) if dataMesh is not None: if len(field) == dataMesh.nodeCount(): pot = pg.RVector(field) elif len(field) == dataMesh.cellCount(): pot = pg.cellDataToPointData(dataMesh, field) else: raise BaseException( "Data length (%i) for streamline is " "neighter nodeCount (%i) nor cellCount (%i)" % (len(field), dataMesh.nodeCount(), dataMesh.nodeCount())) else: if len(field) == mesh.nodeCount(): pot = pg.RVector(field) elif len(field) == mesh.cellCount(): pot = pg.cellDataToPointData(mesh, field) else: raise BaseException( "Data length (%i) for streamline is " "neighter nodeCount (%i) nor cellCount (%i)" % (len(field), mesh.nodeCount(), mesh.nodeCount())) direction = 1 if down: direction = -1 # search downward pos = pg.RVector3(startCoord) c = mesh.findCell(startCoord) dLength = c.center().dist(c.node(0).pos()) / dLengthSteps # stream line starting point if c is not None: xd.append(pos[koords[0]]) yd.append(pos[koords[1]]) vd.append(-1) lastC = c lastU = -direction * 1e99 d = None while c is not None and len(xd) < maxSteps: # valid .. temporary check if there is already a stream within the cell if not c.valid(): break if isVectorData: u = 0. if len(vx) == mesh.cellCount(): d = pg.RVector3(vx[c.id()], vy[c.id()]) elif len(vx) == mesh.nodeCount(): d = pg.RVector3(c.pot(pos, vx), c.pot(pos, vy)) elif dataMesh: cd = dataMesh.findCell(pos) if cd is None: raise BaseException("Cannot find " + str(pos) + " dataMesh") if len(vx) == dataMesh.cellCount(): d = pg.RVector3(vx[cd.id()], vy[cd.id()]) elif len(vx) == dataMesh.nodeCount() and \ len(vy) == dataMesh.nodeCount(): d = pg.RVector3(cd.pot(pos, vx), cd.pot(pos, vy)) else: print(dataMesh) print(len(vx), len(vy)) raise BaseException("data size wrong") else: raise Exception else: if dataMesh: cd = dataMesh.findCell(pos) if not cd: break d = cd.grad(pos, pot) u = cd.pot(pos, pot) else: d = c.grad(pos, pot) u = c.pot(pos, pot) # print "cell:", c.id(), u # always go u down dAbs = d.length() if dAbs == 0.0: print( d, "check this in streamlineDir(", ) break if down: if u > lastU: break else: if u < lastU: break # * min(1.0, ((startCoord - pos).length())) pos += direction * d / dAbs * dLength c = mesh.findCell(pos, False) # Change cell here .. set old cell to be processed if c is not None: xd.append(pos[koords[0]]) yd.append(pos[koords[1]]) # set the stating value here if vd[0] == -1: vd[0] = dAbs vd.append(dAbs) # If the new cell is different from the current we move into the # new cell and make the last to be invalid .. # the last active contains a stream element if c.id() != lastC.id(): lastC.setValid(False) lastC = c dLength = c.center().dist(c.node(0).pos()) / dLengthSteps else: # There is no new cell .. the last active contains a stream element lastC.setValid(False) lastU = u if verbose: print(pos, u) # Stream line has stopped and the current cell (if there is one) .. # .. contains a stream element if c is not None: c.setValid(False) if down: xd.reverse(), yd.reverse(), vd.reverse() return xd, yd, vd
def solveGravimetry(mesh, dDensity=None, pnts=None, complete=False): r"""Solve gravimetric response. 2D with :py:mod:`pygimli.physics.gravimetry.lineIntegralZ_WonBevis` 3D with :py:mod:`pygimli.physics.gravimetry.gravMagBoundarySinghGup` TOWRITE Parameters ---------- mesh : :gimliapi:`GIMLI::Mesh` 2d or 3d mesh with or without cells. dDensity : float | array Density difference. * float -- solve for positive boundary marker only. Assuming one inhomogeneity. * [[int, float]] -- solve for multiple positive boundaries TOIMPL * array -- solve for one delta density value per cell * None -- return per cell kernel matrix G TOIMPL pnts : [[x_i, y_i]] List of measurement positions. complete : bool [False] If True return whole solution or matrix for [dgx, dgy, dgz] and ... TODO Returns ------- """ if pnts is None: pnts = [[0.0, 0.0]] mesh.createNeighbourInfos() Gdg = None Gdgz = None dg = None dgz = None if complete: Gdg = np.zeros((len(pnts), mesh.cellCount(), 3)) Gdgz = np.zeros((len(pnts), mesh.cellCount(), 3)) dg = np.zeros((len(pnts), 3)) dgz = np.zeros((len(pnts), 3)) else: dg = np.zeros(len(pnts)) Gdg = np.zeros((len(pnts), mesh.cellCount())) dgi = None dgzi = None for i, p in enumerate(pnts): mesh.translate(-pg.RVector3(p)) for b in mesh.boundaries(): if b.marker() != 0 or hasattr(dDensity, '__len__') or \ dDensity is None: if mesh.dimension() == 2: # tic = time.time() if complete: dgi, dgzi = lineIntegralZ_WonBevis(b.node(0).pos(), b.node(1).pos()) # times.append(time.time() - tic) dgi *= -2.0 dgzi *= -2.0 else: dgi = pg.lineIntegralZ_WonBevis(b.node(0).pos(), b.node(1).pos()) dgi *= -2.0 * G else: if complete: dgi, dgzi = gravMagBoundarySinghGup(b) else: raise Exception("TOIMPL") if complete: dgi *= [1.0, 1.0, -1.0] dgi *= -G dgzi *= -G if hasattr(dDensity, '__len__') or dDensity is None: cl = b.leftCell() cr = b.rightCell() if cl: Gdg[i][cl.id()] += dgi if complete: Gdgz[i][cl.id()] += dgzi if cr: Gdg[i][cr.id()] -= dgi if complete: Gdgz[i][cr.id()] -= dgzi else: dg[i] += dgi * dDensity if complete: dgz[i] += dgzi * dDensity mesh.translate(pg.RVector3(p)) # import matplotlib.pyplot as plt # print("times:", sum(times), np.mean(times)) # plt.plot(times) if dDensity is None: if complete: return Gdg.transpose([0, 2, 1]), Gdgz.transpose([0, 2, 1]) return Gdg elif hasattr(dDensity, '__len__'): if complete: dg = Gdg.transpose([0, 2, 1]).dot(dDensity) dgz = Gdgz.transpose([0, 2, 1]).dot(dDensity) return dg, dgz else: return Gdg.dot(dDensity) if complete: return dg, dgz return dg
def diff(v): """Calculate approximate derivative. Calculate approximate derivative from v as d = [v_1-v_0, v2-v_1, ...] Parameters ---------- v : array(N) | pg.R3Vector(N) Array of double values or positions Returns ------- d : [type(v)](N-1) | derivative array Examples -------- >>> import pygimli as pg >>> from pygimli.utils import diff >>> p = pg.R3Vector(4) >>> p[0] = [0.0, 0.0] >>> p[1] = [0.0, 1.0] >>> print(diff(p)[0]) RVector3: (0.0, 1.0, 0.0) >>> print(diff(p)[1]) RVector3: (0.0, -1.0, 0.0) >>> print(diff(p)[2]) RVector3: (0.0, 0.0, 0.0) >>> p = pg.RVector(3) >>> p[0] = 0.0 >>> p[1] = 1.0 >>> p[2] = 2.0 >>> print(diff(p)) <class 'pygimli.core._pygimli_.RVector'> 2 [1.0, 1.0] """ d = None if isinstance(v, np.ndarray): if v.ndim == 2: if v.shape[1] < 4: #v = pg.R3Vector(v.T) vt = v.copy() v = pg.R3Vector(len(vt)) for i, vi in enumerate(vt): #print(i, vi) v.setVal(pg.RVector3(vi), i) else: v = pg.R3Vector(v) else: v = pg.RVector(v) elif isinstance(v, list): v = pg.R3Vector(v) if isinstance(v, pg.R3Vector) or isinstance(v, pg.stdVectorRVector3): d = pg.R3Vector(len(v) - 1) else: d = pg.RVector(len(v) - 1) for i, _ in enumerate(d): d[i] = v[i + 1] - v[i] return d
def createRectangle(start=None, end=None, pos=None, size=None, **kwargs): """Create rectangle polygon. Create rectangle with start position and a given size. Give either start and end OR pos and size. Parameters ---------- start : [x, y] Left upper corner. Default [-0.5, 0.5] end : [x, y] Right lower corner. Default [0.5, -0.5] pos : [x, y] Center position. The rectangle will be moved. size : [x, y] Factors for x and y by which the rectangle, defined by **start** and **width**, are scaled. **kwargs: marker : int [1] Marker for the resulting triangle cells after mesh generation markerPosition : floats [x, y] [pos + (end - start) * 0.2] Absolute position of the marker (works for both regions and holes). area : float [0] Maximum cell size for resulting triangles after mesh generation boundaryMarker : int [1] Marker for the resulting boundary edges leftDirection : bool [True] TODO Rotational direction isHole : bool [False] The polygon will become a hole instead of a triangulation isClosed : bool [True] Add closing edge between last and first node. Returns ------- poly : :gimliapi:`GIMLI::Mesh` The resulting polygon is a :gimliapi:`GIMLI::Mesh`. Examples -------- >>> import matplotlib.pyplot as plt >>> import pygimli as pg >>> from pygimli.meshtools import createRectangle >>> rectangle = createRectangle(start=[4, -4], end=[6, -6], ... marker=4, area=0.1) >>> _ = pg.show(rectangle) >>> import matplotlib.pyplot as plt >>> import pygimli as pg >>> from pygimli.meshtools import createRectangle >>> rectangle = createRectangle(pos=[5, -5], size=[2, 2], ... marker=4, area=0.1) >>> _ = pg.show(rectangle) """ if start is None: start = [-0.5, 0.5] if end is None: end = [0.5, -0.5] poly = pg.Mesh(dim=2, isGeometry=True) sPos = pg.RVector3(start) ePos = pg.RVector3(end) verts = [sPos, [sPos[0], ePos[1]], ePos, [ePos[0], sPos[1]]] #TODO refactor with polyCreatePolygon if kwargs.pop("leftDirection", False): for v in verts[::-1]: poly.createNode(v) else: for v in verts: poly.createNode(v) markerposition = kwargs.pop('markerPosition', None) def addMarker(mposition): # use defaults if mposition is None: mposition = sPos + (ePos - sPos) * 0.2 if kwargs.pop('isHole', False): poly.addHoleMarker(mposition) else: poly.addRegionMarker(mposition, marker=kwargs.pop('marker', 1), area=kwargs.pop('area', 0)) # if the user supplies an absolute marker position, we need to add it after # transforming the polygon marker_added = False if markerposition is None: addMarker(markerposition) marker_added = True # Note that we do not support the usage of start/end AND size/pos. Only one # of the pairs. Otherwise strange things will happen with the region # markers! if size is not None: poly.scale(size) if pos is not None: poly.translate(pos) if not marker_added: addMarker(markerposition) polyCreateDefaultEdges_(poly, **kwargs) return poly
def createParaMeshPLC(sensors, paraDX=1, paraDepth=0, paraBoundary=2, paraMaxCellSize=0.0, boundary=-1, boundaryMaxCellSize=0, **kwargs): """Create a PLC mesh for an inversion parameter mesh. Create a PLC mesh for an inversion parameter mesh with for a given list of sensor positions. Sensor positions are assumed to lie on the surface and must be sorted and unique. You can create a parameter mesh without sensors by setting [xmin, xmax] as sensors. The PLC is a :gimliapi:`GIMLI::Mesh` and contains nodes, edges and 2 region markers, one for the parameters domain (marker=2) and a larger boundary around the outside (marker=1) TODO: * closed domains (boundary == 0) * additional topopoints * spline interpolations between sensorpoints or addpoints * subsurface sensors (partly .. see example) Parameters ---------- sensors : [RVector3] | DataContainer with sensorPositions() | [xmin, xmax] Sensor positions. Must be sorted and unique in positive x direction. Depth need to be y-coordinate. paraDX : float [1] Relativ distance for refinement nodes between two sensors (1=none), e.g., 0.5 means 1 additional node between two neighboring sensors e.g., 0.33 means 2 additional equidistant nodes between two sensors paraDepth : float, optional Maximum depth for parametric domain, 0 (default) means 0.4 * maximum sensor range. paraBoundary : float, optional Margin for parameter domain in absolute sensor distances. 2 (default). paraMaxCellSize: double, optional Maximum size for parametric size in m*m boundaryMaxCellSize: double, optional Maximum cells size in the boundary region in m*m boundary : float, optional Boundary width to be appended for domain prolongation in absolute para domain width. Values lover 0 force the boundary to be 4 times para domain width. Returns ------- poly: :gimliapi:`GIMLI::Mesh` piecewise linear complex (PLC) containing nodes and edges Examples -------- >>> # no need to import matplotlib. pygimli's show does >>> import pygimli as pg >>> import pygimli.meshtools as plc >>> # Create the simplest paramesh PLC with a para box of 10 m without >>> # sensors >>> p = plc.createParaMeshPLC([0,10]) >>> # you can add subsurface sensors now with >>> for z in range(1,4): ... n = p.createNode((5,-z), -99) >>> ax,_ = pg.show(p) """ noSensors = False if hasattr(sensors, 'sensorPositions'): # obviously a DataContainer type sensors = sensors.sensorPositions() elif isinstance(sensors, np.ndarray): if sensors.ndim == 1: sensors = [pg.RVector3(s, 0) for s in sensors] else: # assume 2d array with 2 or 3 values per item sensors = [pg.RVector3(s) for s in sensors] elif isinstance(sensors, list): if len(sensors) == 2: # guess we have just a desired Pbox with sensors = [pg.RVector3(sensors[0], 0.0), pg.RVector3(sensors[1], 0.0)] noSensors = True paraBoundary = 0 eSpacing = kwargs.pop('eSpacing', sensors[0].distance(sensors[1])) iz = 1 xmin, ymin, zmin = sensors[0][0], sensors[0][1], sensors[0][2] xmax, ymax, zmax = xmin, ymin, zmin for e in sensors: xmin = min(xmin, e[0]) xmax = max(xmax, e[0]) ymin = min(ymin, e[1]) ymax = max(ymax, e[1]) zmin = min(zmin, e[2]) zmax = max(zmax, e[2]) if abs(ymin) < 1e-8 and abs(ymax) < 1e-8: iz = 2 paraBound = eSpacing * paraBoundary if paraDepth == 0: paraDepth = 0.4 * (xmax - xmin) poly = pg.Mesh(dim=2, isGeometry=True) # define para domain without surface n1 = poly.createNode([xmin - paraBound, sensors[0][iz]]) n2 = poly.createNode([xmin - paraBound, sensors[0][iz] - paraDepth]) n3 = poly.createNode([xmax + paraBound, sensors[-1][iz] - paraDepth]) n4 = poly.createNode([xmax + paraBound, sensors[-1][iz]]) if boundary < 0: boundary = 4 bound = abs(xmax - xmin) * boundary if bound > paraBound: # define world without surface n11 = poly.createNode(n1.pos() - [bound, 0.]) n12 = poly.createNode(n11.pos() - [0., bound + paraDepth]) n14 = poly.createNode(n4.pos() + [bound, 0.]) n13 = poly.createNode(n14.pos() - [0., bound + paraDepth]) poly.createEdge(n1, n11, pg.MARKER_BOUND_HOMOGEN_NEUMANN) poly.createEdge(n11, n12, pg.MARKER_BOUND_MIXED) poly.createEdge(n12, n13, pg.MARKER_BOUND_MIXED) poly.createEdge(n13, n14, pg.MARKER_BOUND_MIXED) poly.createEdge(n14, n4, pg.MARKER_BOUND_HOMOGEN_NEUMANN) poly.addRegionMarker(n12.pos() + [1e-3, 1e-3], 1, boundaryMaxCellSize) poly.createEdge(n1, n2, 1) poly.createEdge(n2, n3, 1) poly.createEdge(n3, n4, 1) poly.addRegionMarker(n2.pos() + [1e-3, 1e-3], 2, paraMaxCellSize) # define surface nSurface = [] nSurface.append(n1) if paraDX == 0.0: paraDX = 1.0 if not noSensors: for i, e in enumerate(sensors): if iz == 2: e.rotateX(-math.pi / 2) if paraDX >= 0.5: nSurface.append(poly.createNode(e, pg.MARKER_NODE_SENSOR)) if i < len(sensors) - 1: e1 = sensors[i + 1] if iz == 2: e1.rotateX(-math.pi / 2) nSurface.append(poly.createNode((e + e1) * 0.5)) # print("Surface add ", e, el, nSurface[-2].pos(), # nSurface[-1].pos()) elif paraDX < 0.5: if i > 0: e1 = sensors[i - 1] if iz == 2: e1.rotateX(-math.pi / 2) nSurface.append(poly.createNode(e - (e - e1) * paraDX)) nSurface.append(poly.createNode(e, pg.MARKER_NODE_SENSOR)) if i < len(sensors) - 1: e1 = sensors[i + 1] if iz == 2: e1.rotateX(-math.pi / 2) nSurface.append(poly.createNode(e + (e1 - e) * paraDX)) # print("Surface add ", nSurface[-3].pos(), nSurface[-2].pos(), # nSurface[-1].pos()) nSurface.append(n4) for i in range(len(nSurface) - 1, 0, -1): poly.createEdge(nSurface[i], nSurface[i - 1], pg.MARKER_BOUND_HOMOGEN_NEUMANN) # print(poly) # pg.meshtools.writePLC(poly, "test.poly") # pg.show(poly) # pg.wait() return poly
else: model_vector_s.append(nan) model_data=pb.pg.RVector(model_vector) model_data_s=pb.pg.RVector(model_vector_s) #72x1 DD ------------------------------------------------------------- world_72_dd=world scheme72_dd = pb.createData(elecs=pg.utils.grange(start=0, end=71, n=72), schemeName='dd') for pos in scheme72_dd.sensorPositions(): world_72_dd.createNode(pos) world_72_dd.createNode(pos + pg.RVector3(0, -0.1)) mesh_72x1_dd= mt.createMesh(world_72_dd, quality=34) #forward modelling data_72x1_dd=pb.simulate(mesh_72x1_dd,res=rhomap,scheme=scheme72_dd,noise=noise, verbose=True) #inversion ert_72x1_dd=pb.ERTManager(data_72x1_dd) inversion_72x1_dd=ert_72x1_dd.invert(quality=quality, maxCellArea=maxCellArea, robustData=robustData, lam=lam,paraDX=paraDX) max_72x1_dd= np.max(inversion_72x1_dd) inversion_mesh_72x1_dd=ert_72x1_dd.paraDomain
def test2d(): mesh = pg.Mesh('mesh/world2d.bms') print(mesh) xMin = mesh.boundingBox().min()[0] yMax = mesh.boundingBox().max()[0] x = np.arange(xMin, yMax, 1.) mesh.createNeighbourInfos() rho = pg.RVector(len(mesh.cellAttributes()), 1.) * 2000.0 rho.setVal(0.0, pg.find(mesh.cellAttributes() == 1.0)) swatch = pg.Stopwatch(True) pnts = [] spnts = pg.stdVectorRVector3() for i in x: pnts.append(pg.RVector3(i, 0.0001)) spnts.append(pg.RVector3(i, 0.0001)) # gzC, GC = calcGCells(pnts, mesh, rho, 1) gzC = pg.calcGCells(spnts, mesh, rho, 1) print("calcGCells", swatch.duration(True)) # gzB, GB = calcGBounds(pnts, mesh, rho) # gzB = pg.calcGBounds(spnts, mesh, rho) # print("calcGBounds", swatch.duration(True)) gZ_Mesh = gzC ax1, ax2 = getaxes() # sphere analytical solution gAna = analyticalCircle2D(spnts, radius=2.0, pos=pg.RVector3(0.0, -5.0), dDensity=2000) gAna2 = analyticalCircle2D(spnts, radius=2.0, pos=pg.RVector3(5.0, -5.0), dDensity=2000) gAna = gAna + gAna2 ax1.plot(x, gAna, '-x', label='analytical') ax1.plot(x, gZ_Mesh, label='WonBevis1987-mesh') print(gAna / gZ_Mesh) # rho=GB[0]/mesh.cellSizes() drawModel(ax2, mesh, rho) for i in (0, 1): drawSelectedMeshBoundaries(ax2, mesh.findBoundaryByMarker(i), color=(1.0, 1.0, 1.0, 1.0), linewidth=0.3) # sphere polygone radius = 2. depth = 5. poly1 = pg.stdVectorRVector3() poly2 = pg.stdVectorRVector3() nSegment = 124 for i in range(nSegment): xp = np.sin((i + 1) * (2. * np.pi) / nSegment) yp = np.cos((i + 1) * (2. * np.pi) / nSegment) poly1.append(pg.RVector3(xp * radius, yp * radius - depth)) poly2.append(pg.RVector3(xp * radius + 5., yp * radius - depth)) gZ_Poly = calcPolydgdz(spnts, poly1, 2000) gZ_Poly += calcPolydgdz(spnts, poly2, 2000) ax1.plot(x, gZ_Poly, label='WonBevis1987-Poly') ax2.plot(pg.x(poly1), pg.y(poly1), color='red') ax2.plot(pg.x(poly2), pg.y(poly2), color='red') ax2.plot(pg.x(spnts), pg.y(spnts), marker='x', color='black') # test some special case for i, p in enumerate(poly1): poly1[i] = pg.RVector3(poly1[i] - pg.RVector3(5.0, -6.)) ax2.plot(pg.x(poly1), pg.y(poly1), color='green') gz = calcPolydgdz(spnts, poly1, 2000) ax1.plot(x, gz, label='Special Case', color='green') ax1.set_ylabel('dg/dz [mGal]') ax2.set_ylabel('Tiefe [m]') ax1.legend() ax2.set_xlim([x[0], x[-1]]) ax2.grid()
def calcApparentResistivities(mesh, meshERT, poro, rhoBrine): ert = ERT(verbose=False) meshFOP = appendTriangleBoundary(meshERT, xbound=50, ybound=50, marker=1, quality=34.0, smooth=False, markerBoundary=1, isSubSurface=False, verbose=False) swatch = pg.Stopwatch(True) print("res 1:", swatch.duration(True)) resis = resistivityArchie(rBrine=rhoBrine, porosity=poro, S=1.0, mesh=mesh, meshI=meshFOP) print("res 2:", swatch.duration(True)) ertPointsX = [pg.RVector3(x, 0) for x in np.arange(-19, 19.1, 1)] ertScheme = ert.createData(ertPointsX, scheme="Dipole Dipole (CC-PP)") solutionName = createCacheName('appRes', mesh) + "-" + str( ertScheme.size()) + "-" + str(len(rhoBrine)) try: rhoa = np.load(solutionName + '.bmat.npy') ertData = pb.DataContainerERT(solutionName + '.dat') except Exception as e: print(e) print("Building .... ") rhoa = np.zeros((len(resis), ertScheme.size())) ertScheme.set('k', pb.geometricFactor(ertScheme)) ertData = ert.simulate(meshFOP, resis[0], ertScheme) errPerc = 1 errVolt = 1e-5 voltage = ertData('rhoa') / ertData('k') ertData.set('err', pg.abs(errVolt / voltage) + errPerc / 100.0) print('err min:', min(ertData('err')) * 100, 'max:', max(ertData('err')) * 100) ertData.save(solutionName + '.dat', 'a b m n rhoa err k') #sys.exit() for i in range(0, len(resis)): tic = time.time() rhoa[i] = ert.fop.response(resis[i]) rand = pg.RVector(len(rhoa[i])) pg.randn(rand) rhoa[i] *= (1.0 + rand * ertData('err')) print(i, "/", len(resis), " : ", time.time() - tic, "s", "min:", min(resis[i]), "max:", max(resis[i]), "min:", min(rhoa[i]), "max:", max(rhoa[i])) np.save(solutionName + '.bmat', rhoa) return meshFOP, resis, ertData, rhoa
nodes.append(plc.createNode(xmin, -zlay * 2, 0.)) # 5 nodes.append(plc.createNode(xmin, -zlay, 0.)) # 6 ############################################################################### # The nodes are connected from from 0 to 6 and back to 0. # An additional edge is drawn from 6 to 3. Node/edge markers do not matter. for i in range(6): plc.createEdge(nodes[i], nodes[i + 1]) plc.createEdge(nodes[6], nodes[0]) plc.createEdge(nodes[6], nodes[3]) ############################################################################### # We insert region markers (0 and 1) into the two layers and generate the mesh. tri = pg.TriangleWrapper(plc) plc.addRegionMarker(pg.RVector3(0., -zlay + .1), 0, 3.) # 10m^2 max area plc.addRegionMarker(pg.RVector3(0., -zlay - .1), 1, 10.) tri.setSwitches('-pzeAfaq34.6') mesh = pg.Mesh(2) tri.generate(mesh) mesh.createNeighbourInfos() print(mesh) ############################################################################### # Next we generate a velocity model from the markers by using a map. # The values are associated to the markers and stored as attributes. v = [1000., 3000.] slomap = pg.stdMapF_F() # mapping markers to real slowness values for i, vi in enumerate(v): slomap.insert(i, 1. / vi)
nodes.append(plc.createNode(xmin, 0., 0.)) nodes.append(plc.createNode(xmax, 0., 0.)) nodes.append(plc.createNode(xmax, -zlay, 0.)) nodes.append(plc.createNode(xmax, -zlay * 2, 0.)) nodes.append(plc.createNode(xmin, -zlay * 2, 0.)) nodes.append(plc.createNode(xmin, -zlay, 0.)) # connect the nodes for i in range(5): plc.createEdge(nodes[i], nodes[i + 1]) plc.createEdge(nodes[5], nodes[0]) plc.createEdge(nodes[5], nodes[2]) # insert region markers into the two layers and make mesh tri = pg.TriangleWrapper(plc) plc.addRegionMarker(pg.RVector3(0., -zlay + .1), 0, 3.) # 10m^2 max area plc.addRegionMarker(pg.RVector3(0., -zlay - .1), 1, 10.) tri.setSwitches('-pzeAfaq34.6') mesh = pg.Mesh(2) tri.generate(mesh) mesh.createNeighbourInfos() print(mesh) # make velocity model v = [1000., 3000.] slomap = pg.stdMapF_F() # map for mapping real slowness values for i, vi in enumerate(v): slomap.insert(i, 1. / vi) mesh.mapCellAttributes(slomap) # map values to attributes using map
def _createParameterContraintsLines(mesh, cMat, cWeight=None): """TODO Documentme.""" C = pg.RMatrix() if isinstance(cMat, pg.SparseMapMatrix): cMat.save('tmpC.matrix') pg.loadMatrixCol(C, 'tmpC.matrix') else: C = cMat paraMarker = mesh.cellMarkers() cellList = dict() for cID in range(len(paraMarker)): if cID not in cellList: cellList[cID] = [] cellList[cID].append(mesh.cell(cID)) paraCenter = dict() for cID, vals in list(cellList.items()): p = pg.RVector3(0.0, 0.0, 0.0) for c in vals: p += c.center() p /= float(len(vals)) paraCenter[cID] = p nConstraints = C[0].size() start = [] end = [] # swatch = pg.Stopwatch(True) # not used for i in range(0, int(nConstraints / 2)): # print i # if i == 1000: break; idL = int(C[1][i * 2]) idR = int(C[1][i * 2 + 1]) # leftCells = [] # rightCells = [] # for c, index in enumerate(paraMarker): # if idL == index: # leftCells.append(mesh.cell(c)) # if idR == index: # rightCells.append(mesh.cell(c)) # p1 = pg.RVector3(0.0,0.0); # for c in leftCells: # p1 += c.center() # p1 /= float(len(leftCells)) # p2 = pg.RVector3(0.0,0.0); # for c in rightCells: # p2 += c.center() # print cWeight[i] # p2 /= float(len(rightCells)) p1 = paraCenter[idL] p2 = paraCenter[idR] if cWeight is not None: pa = pg.RVector3(p1 + (p2 - p1) / 2.0 * (1.0 - cWeight[i])) pb = pg.RVector3(p2 + (p1 - p2) / 2.0 * (1.0 - cWeight[i])) else: pa = p1 pb = p2 start.append(pa) end.append(pb) # updateAxes_(ax) # not existing return start, end
comp_scheme = su.merge_schemes(comp_scheme, scheme_tmp, folder + 'tmp/') for i in range(1, len(schemes)): scheme_tmp = pb.createData(elecs=comp_electrodes[0], schemeName=schemes[i]) for j in range(1, len(comp_electrodes)): scheme_tmp2 = pb.createData(elecs=comp_electrodes[j], schemeName=schemes[i]) scheme_tmp = su.merge_schemes(scheme_tmp, scheme_tmp2, folder + 'tmp/') comp_scheme = su.merge_schemes(comp_scheme, scheme_tmp, folder + 'tmp/') scheme = comp_scheme # create mesh spacing = scheme.sensorPositions()[1][0] - scheme.sensorPositions()[0][0] for pos in scheme.sensorPositions(): world.createNode(pos) world.createNode(pos + pg.RVector3(0, -spacing / 2)) # create mesh from world mesh = mt.createMesh(world, quality=config.sim_mesh_quality) # create inversion mesh sensor_distance = scheme.sensorPositions()[1][0] - scheme.sensorPositions( )[0][0] para_dx = config.inv_final_dx / sensor_distance para_dz = config.inv_final_dz / sensor_distance n_layers = int(config.inv_depth / config.inv_final_dz) inv_mesh = mt.createParaMesh2DGrid(sensors=scheme.sensorPositions(), paraDX=para_dx, paraDZ=para_dz, paraDepth=config.inv_final_depth, nLayers=n_layers)
def drawShapes( ax, mesh, u ): #ax.set_aspect( 'equal' ) N = 11 mesh3 = g.createMesh3D( g.asvector( np.linspace( 0, 1, N ) ), g.asvector( np.linspace( 0, 1, N ) ), g.asvector( np.linspace( 0, 1, N ) ) ) uc = g.RVector( mesh3.nodeCount( ) ) grads = g.stdVectorRVector3( ) pnts = g.stdVectorRVector3( ) c = mesh.cell( 0 ) imax=g.find( u == max( u ) )[0] N = c.createShapeFunctions()[ imax ] print imax, N # print imax, c.shape().createShapeFunctions()[imax] for i in range( c.nodeCount() ): print c.rst( i ), N( c.rst( i ) ) # draw nodes for i in range( c.nodeCount() ): col = 'black' if i == imax: col = 'red' #ax.plot( [c.node( i ).pos()[0], c.node( i ).pos()[0] ], #[c.node( i ).pos()[1], c.node( i ).pos()[1] ], #[c.node( i ).pos()[2], c.node( i ).pos()[2] ], #'.', markersize = 15, linewidth=0, color=col ) newNode = [] for i in range( mesh3.nodeCount( ) ): p = c.shape().xyz( mesh3.node( i ).pos() ) newNode.append( p ) #ax.plot( p[0], p[1], '.', zorder=10, color='black', markersize = 1 ) if not c.shape().isInside( p ): uc[ i ] = -99.0 grads.append( g.RVector3( 0.0, 0.0 ) ) continue uc[ i ] = c.pot( p, u ) gr = c.grad( p, u ).normalise() grads.append( gr ) #ax.plot( [ p[ 0 ], p[ 0 ] + gr[ 0 ]*0.1 ], #[ p[ 1 ], p[ 1 ] + gr[ 1 ]*0.1 ], #[ p[ 2 ], p[ 2 ] + gr[ 2 ]*0.1 ], '-', color='black' ) #pnts.append( p ) #print len(pnts) #Z = np.ma.masked_where( uc == -99., uc ) ##ax.plot( g.x(pnts), g.y(pnts), g.z(pnts), '.' ) for i, n in enumerate( mesh3.nodes() ): n.setPos( newNode[ i ] ) mesh3.addExportData( 'u', uc.setVal( 0.0, g.find( uc == -99 ) ) ) name = 'cell' + str( c.nodeCount() ) + '-' + str( imax ) print "write ", name mesh3.exportVTK( name, grads )
def _trace_back(self, sensor_idx, source_idx, epsilon=1e-5): """ Traces a ray backwards through the mesh from a particular sensor towards the seismic source. """ msh = self.mesh() self.poslist = [] self._jac[source_idx] = np.zeros((msh.cellCount())) pos_offset = pg.RVector3(0., epsilon, 0.) sensor_pos = self.data().sensorPosition(sensor_idx) source_pos = self.data().sensorPosition(source_idx) source_node = msh.findNearestNode(source_pos) current_cell = msh.findCell(sensor_pos - pos_offset) new_cell = current_cell ray_origin = sensor_pos - pos_offset was_on_edge = False while ray_origin.dist(source_pos) > epsilon: self.poslist.append(ray_origin) if new_cell is None: print("Ended up outside mesh!") print("Last valid cell: {}".format(current_cell)) break # other_boundary = pg.findBoundary( # current_cell.node((node_idx+2)%nnodes), # current_cell.node((node_idx+1)%nnodes)) # new_cell = self._get_new_cell(other_boundary, current_cell) # gradient = current_cell.node((node_idx+1)%nnodes).pos() - # current_cell.node(node_idx).pos() else: old_cell_id = current_cell.id() # going to slower cell # if new_cell.attribute() > current_cell.attribute(): # gradient = current_cell.grad(current_cell.center(), # self.timefields[source_idx]) # else: # gradient = new_cell.grad(current_cell.center(), # self.timefields[source_idx]) current_cell = new_cell if not was_on_edge: gradient = current_cell.grad( current_cell.center(), self.timefields[source_idx]) else: was_on_edge = False print("Current cell: {}".format(current_cell.id())) # gradient = current_cell.grad(current_cell.center(), # self.timefields[source_idx]) # gradient_norm = -gradient / gradient.length() gradient_norm = -gradient.norm() nnodes = current_cell.nodeCount() params = np.zeros((nnodes, 2)) gradient_line = pg.Line(ray_origin, ray_origin + gradient_norm) for i in range(nnodes): if current_cell.node(i).id() == source_node: print("cell closest to source") params[i, :] = [ray_origin.dist(source_pos), i] break edge = pg.Line(current_cell.node(i).pos(), current_cell.node((i+1) % nnodes).pos()) # print("Grad: {}".format(gradient_line)) # print("Edge: {}".format(edge)) s_t = self._intersect_lines(gradient_line, edge) # print("s_t: {}".format(s_t)) params[i, :] = [s_t[0], i] t, node_idx, stay_on_edge = self._check_param(params) print("Stay on edge: {}".format(stay_on_edge)) boundary = pg.findBoundary( current_cell.node(node_idx), current_cell.node((node_idx+1) % nnodes)) if stay_on_edge: # break next_node_id, next_cell_id = self._get_next_node( boundary, current_cell.id(), ray_origin, gradient_norm) t = ray_origin.dist(msh.node(next_node_id).pos()) print("Current: {}, next: {}, t: {}".format( current_cell.id(), next_cell_id, t)) print("") self._jac[source_idx][next_cell_id] += t temp = msh.node(next_node_id).pos() - ray_origin ray_origin = msh.node(next_node_id).pos() + \ 1e-5 * temp.norm() - pg.RVector3(0.0, 1e-6, 0.0) # new_cell = mesh.cell(next_cell_id) new_cell = msh.findCell(ray_origin) was_on_edge = True # print("next_cell_id: {}, findCell: {}".format( # next_cell_id, new_cell.id())) else: # print("params: {}, t: {}, i: {}".format(params, t, node_idx)) # Save distance travelled in the cell (t) and update origin self._jac[source_idx][current_cell.id()] = t ray_origin = gradient_line.lineAt(t) # print("ray origin: {}".format(ray_origin)) new_cell = self._get_new_cell(boundary, current_cell) if new_cell.id() == old_cell_id: # If we keep jumping back and forth between two cells. print("Jumping back and forth...") break return self._jac