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()
]
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
# 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()
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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()
Exemple #9
0
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)
Exemple #10
0
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.")
Exemple #11
0
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
Exemple #13
0
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 ) )
Exemple #14
0
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
Exemple #15
0
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
Exemple #16
0
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
Exemple #17
0
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
Exemple #18
0
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
Exemple #19
0
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
Exemple #20
0
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
Exemple #21
0
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
Exemple #22
0
    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
Exemple #23
0
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()
Exemple #24
0
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
Exemple #25
0
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)
Exemple #26
0
    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
Exemple #27
0
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
Exemple #28
0
    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)
Exemple #29
0
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 )
Exemple #30
0
    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