Exemplo n.º 1
0
    def createJacobian(self, slowness):
        """Generate Jacobian matrix using fat-ray after Jordi et al. (2016)."""
        self.J = pg.Matrix(self.data().size(), self.mesh().cellCount())
        self.sensorNodes = [self.mesh().findNearestNode(pos)
                            for pos in self.data().sensorPositions()]
        if (self.iMat.cols() != self.mesh().nodeCount() or
            self.iMat.rows() != self.mesh().cellCount()):
            self.iMat = self.mesh().interpolationMatrix(
                    self.mesh().cellCenters())
        Di = self.dijkstra()
        slowPerCell = self.createMappedModel(slowness, 1e16)
        Di.setGraph(self.createGraph(slowPerCell))
        numN = self.mesh().nodeCount()
        data = self.data()
        numS = data.sensorCount()
        Tmat = pg.Matrix(numS, numN)
        Dmat = pg.Matrix(numS, numS)
        for i, node in enumerate(self.sensorNodes):
            Di.setStartNode(node)
            Tmat[i] = Di.distances()  # (0, numN)
            Dmat[i] = Tmat[i][self.sensorNodes]

        for i in range(data.size()):
            iS = int(data("s")[i])
            iG = int(data("g")[i])
            tsr = Dmat[iS][iG]  # shot-receiver travel time
            dt = self.iMat * (Tmat[iS] + Tmat[iG]) - tsr
            weight = np.maximum(1 - 2 * self.frequency * dt, 0.0)  # 1 on ray
            wa = weight  # * np.sqrt(self.mesh().cellSizes())
            if np.sum(wa) > 0:  # not if all values are zero
                wa /= np.sum(wa)

            self.J[i] = wa * tsr / slowness

        self.setJacobian(self.J)
Exemplo n.º 2
0
def resistivityArchie(rBrine,
                      porosity,
                      a=1.0,
                      m=2.0,
                      S=1.0,
                      n=2.0,
                      mesh=None,
                      meshI=None):
    """
    .. math::
        \rho = a\rho_{\text{Brine}}\phi^{-m}\S_w^{-n}

    * :math:`\rho` - the electrical conductivity of the fluid saturated rock
    * :math:`\rho_{\text{Brine}}` - electrical conductivity of the brine
    * :math:`\phi` - porosity 0.0 --1.0
    * :math:`a` - tortuosity factor. (common 1)
    * :math:`m` - cementation exponent of the rock
            (usually in the range 1.3 -- 2.5 for sandstones)
    * :math:`n` - is the saturation exponent (usually close to 2)

    """
    rB = None

    if rBrine.ndim == 1:
        rB = pg.Matrix(1, len(rBrine))
        rB[0] = parseArgToArray(rBrine, mesh.cellCount(), mesh)
    elif rBrine.ndim == 2:
        rB = pg.Matrix(len(rBrine), len(rBrine[0]))
        for i in range(len(rBrine)):
            rB[i] = rBrine[i]

    porosity = parseArgToArray(porosity, mesh.cellCount(), mesh)
    a = parseArgToArray(a, mesh.cellCount(), mesh)
    m = parseArgToArray(m, mesh.cellCount(), mesh)
    S = parseArgToArray(S, mesh.cellCount(), mesh)
    n = parseArgToArray(n, mesh.cellCount(), mesh)

    r = pg.Matrix(len(rBrine), len(rBrine[0]))
    for i in range(len(r)):
        r[i] = rB[i] * a * porosity**(-m) * S**(-n)

    rI = pg.Matrix(len(r), meshI.cellCount())
    if meshI:
        pg.interpolate(mesh, r, meshI.cellCenters(), rI)

    for i in range(len(rI)):
        rI[i] = pg.solver.fillEmptyToCellArray(meshI, rI[i])

    return rI
Exemplo n.º 3
0
    def loadKernel(self, name=''):
        """Load kernel matrix from mrsk or two bmat files."""
        from scipy.io import loadmat  # loading Matlab mat files

        if name[-5:].lower() == '.mrsk':
            kdata = loadmat(name, struct_as_record=False,
                            squeeze_me=True)['kdata']
            self.K = kdata.K
            self.z = np.hstack((0., kdata.model.z))
        else:  # try load real/imag parts (backward compat.)
            KR = pg.Matrix(name + 'KR.bmat')
            KI = pg.Matrix(name + 'KI.bmat')
            self.K = np.zeros((KR.rows(), KR.cols()), dtype='complex')
            for i in range(KR.rows()):
                self.K[i] = np.array(KR[i]) + np.array(KI[i]) * 1j
Exemplo n.º 4
0
 def __init__(self, verbose=True):
     """Constructor."""
     super(GravimetryModelling, self).__init__(verbose)
     self._J = pg.Matrix()
     # unless doing reference counting we need to hold the reference here
     self.sensorPositions = None
     self.setJacobian(self._J)
Exemplo n.º 5
0
def calcERT(ertScheme, rhoa):
    ert = ERT(verbose=False)

    solutionName = createCacheName('ERT') + "-" + str(ertScheme.size()) + \
        "-" + str(len(rhoa))
    try:
        ertModels = pg.load(solutionName + '.bmat')
        ertMesh = pg.load(solutionName + '.bms')
    except Exception as e:
        print(e)
        print("Building .... ")
        ertModels = ert.invert(ertScheme,
                               values=rhoa,
                               maxiter=10,
                               lambd=50,
                               paraDX=0.5,
                               paraDZ=0.5,
                               nLayers=20,
                               paraDepth=15,
                               verbose=1)
        ertMesh = ert.fop.regionManager().paraDomain()
        ertModels.save(solutionName + '.bmat')
        ertMesh.save(solutionName)

    ertRatioModels = pg.Matrix(ertModels)
    for i in range(len(ertModels)):
        ertRatioModels[i] /= ertModels[0]

    return ertMesh, ertModels, ertRatioModels
Exemplo n.º 6
0
    def test_RMatrixToNumpy(self):
        """Implemented through automatic iterator """
        M = np.arange(20.).reshape((5, 4))
        A = pg.Matrix(M)
        N = np.array(A)
        self.assertEqual(A.rows(), N.shape[0])
        self.assertEqual(A.cols(), N.shape[1])
        self.assertEqual(sum(A[0]), sum(N[0]))
        self.assertEqual(sum(A[1]), sum(N[1]))
        self.assertEqual(sum(A[2]), sum(N[2]))
        self.assertEqual(sum(A[3]), sum(N[3]))

        M = np.arange(16.).reshape((4, 4))
        A = pg.Matrix(M)
        M2 = np.array(A)
        np.testing.assert_equal(M, M2)
        A = np.array(pg.Matrix(4, 4))
Exemplo n.º 7
0
    def testRMatrixIndex(self):
        A = pg.Matrix(4, 4)
        A[0] = pg.Vector(4, 1)

        np.testing.assert_equal(sum(A[0]), 4)

        A[1, 2] = 2.0
        # np.testing.assert_equal(sum(A[1]), 2)
        np.testing.assert_equal(A[1, 2], 2)
Exemplo n.º 8
0
def numpy2gmat(nmat):
    """Convert numpy.array into pygimli RMatrix.

    TODO implement correct rval
    """
    gmat = pg.Matrix()
    for arr in nmat:
        gmat.push_back(arr)  # pg.asvector(arr))
    return gmat
Exemplo n.º 9
0
    def invert(self, sensorPositions, gz, errAbs, verbose=0, **kwargs):
        """
        """
        self.fop.setVerbose(verbose)
        self.inv.setMaxIter(kwargs.pop('maxiter', 10))
        self.inv.setLambda(kwargs.pop('lambd', 10))

        self.fop.setSensorPositions(sensorPositions)
        mesh = kwargs.pop('mesh', None)
        if mesh is None:
            raise ('implement me')

        self.setParaMesh(mesh)

        startModel = pg.Vector(self.fop.regionManager().parameterCount(), 0.0)

        self.inv.setForwardOperator(self.fop)

        self.fop.regionManager().setConstraintType(10)
        # check err here
        self.inv.setData(gz)
        self.inv.setAbsoluteError(errAbs)
        self.inv.setModel(startModel)

        model = self.inv.run()
        return model
        # tl can start here
        values = model
        if values is not None:

            if isinstance(values, pg.Vector):
                values = [values]
            elif isinstance(values, np.ndarray):
                if values.ndim == 1:
                    values = [values]

            allModel = pg.Matrix(len(values) + 1, len(model))
            allModel[0] = model
            self.inv.setVerbose(False)
            for i in range(1, len(values)):
                tic = time.time()
                self.inv.setModel(model)
                self.inv.setReferenceModel(model)
                dData = pg.abs(values[i] - data)

                # relModel = self.inv.invSubStep(pg.log(dData))
                # allModel[i] = model * pg.exp(relModel)

                relModel = self.inv.invSubStep(dData)
                allModel[i] = model + relModel

                print(i, "/", len(values), " : ", time.time() - tic, "s")

            return allModel

        return model
Exemplo n.º 10
0
def loadSIPallData(filename, outnumpy=False):
    """load SIP data with the columns ab/2,mn/2,rhoa and PHI with the
    corresponding frequencies in the first row."""
    if outnumpy:
        A = N.loadtxt(filename)
        fr = A[0, 3:]
        ab2 = A[1:, 0]
        mn2 = A[1:, 1]
        rhoa = A[1:, 2]
        PHI = A[1:, 3:]
    else:
        A = pg.Matrix()
        pg.loadMatrixCol(A, 'sch/dc.ves')
        ndata = A.cols()
        ab2 = A[0](1, ndata)
        mn2 = A[1](1, ndata)
        rhoa = A[2](1, ndata)
        PHI = pg.Matrix()
        fr = []
        for i in range(3, A.rows()):
            fr.append(A[i][0])
            PHI.push_back(A[i](1, ndata))
    return ab2, mn2, rhoa, PHI, fr
Exemplo n.º 11
0
def loadmrsproject(mydir):
    """
    load mrs project from given directory (zkernel.ve)

    (datacube.dat, KR/KI.bmat, zkernel.vec)
    """
    if mydir is None:
        mydir = '.'
    if mydir[-1] != '/':
        mydir = mydir + '/'
    # load files from directory
    zvec = pg.Vector(mydir + 'zkernel.vec')
    KR = pg.Matrix(mydir + 'KR.bmat')
    KI = pg.Matrix(mydir + 'KI.bmat')
    A = pg.Matrix()
    pg.loadMatrixCol(A, mydir + 'datacube.dat')
    t = np.array(A[0])
    # data
    datvec = pg.Vector()
    for i in range(1, len(A)):
        datvec = pg.cat(datvec, A[i])
    # print len(A), len(t)
    return KR, KI, zvec, t, datvec
Exemplo n.º 12
0
    def createJacobian(self, slowness):
        """Generate Jacobian matrix using fat-ray after Jordi et al. (2016)."""
        self.J = pg.Matrix(self.data().size(), self.mesh().cellCount())
        self.sensorNodes = [self.mesh().findNearestNode(pos)
                            for pos in self.data().sensorPositions()]
        Di = self.dijkstra()
        slowPerCell = self.createMappedModel(slowness, 1e16)
        Di.setGraph(self.createGraph(slowPerCell))
        numN = self.mesh().nodeCount()
        data = self.data()
        numS = data.sensorCount()
        Tmat = pg.Matrix(numS, numN)
        Dmat = pg.Matrix(numS, numS)
        print(self.mesh())
        print(self.nnodes, max(self.mids))
        for i, node in enumerate(self.sensorNodes):
            Di.setStartNode(node)
            dist0 = Di.distances()
            dist = Di.distances(withSecNodes=True)
            print("dist len ", len(dist0), len(dist))
            Tmat[i] = dist[self.mids]
#            Tmat[i] = (self.nnodes, len(dist))
            Dmat[i] = Tmat[i][self.sensorNodes]

        for i in range(data.size()):
            iS = int(data("s")[i])
            iG = int(data("g")[i])
            tsr = Dmat[iS][iG]  # shot-receiver travel time
            dt = Tmat[iS] + Tmat[iG] - tsr
            weight = np.maximum(1 - 2 * self.frequency * dt, 0.0)  # 1 on ray
            wa = weight  # * np.sqrt(self.mesh().cellSizes())
            if np.sum(wa) > 0:  # not if all values are zero
                wa /= np.sum(wa)

            self.J[i] = wa * tsr / slowness

        self.setJacobian(self.J)
Exemplo n.º 13
0
    def test_NumpyToRMatrix(self):
        """Implemented in custom_rvalue.cpp."""
        M = np.ndarray((5, 4))
        A = pg.Matrix(M)
        self.assertEqual(A.rows(), M.shape[0])
        self.assertEqual(A.cols(), M.shape[1])

        M = np.arange(20.).reshape((5, 4))
        A = pg.Matrix(M)
        self.assertEqual(sum(A[0]), sum(M[0]))
        self.assertEqual(sum(A[1]), sum(M[1]))
        self.assertEqual(sum(A[2]), sum(M[2]))
        self.assertEqual(sum(A[3]), sum(M[3]))

        M = np.zeros((6, 2), dtype=float)
        M[0:3, 0] = 1
        M[3:, 1] = 1
        A = pg.Matrix(M)
        self.assertEqual(A.col(0), M[:, 0])
        self.assertEqual(A.col(1), M[:, 1])

        A = pg.Matrix(M.T)
        self.assertEqual(A.row(0), M[:, 0])
        self.assertEqual(A.row(1), M[:, 1])
Exemplo n.º 14
0
    def init(self, mesh, tMax, satSteps, ertSteps):
        """Initialize some settings."""

        if mesh is not None:
            self.parMesh = pg.Mesh(mesh)
            self.setMesh(mesh)
            self.createRefinedForwardMesh(refine=False, pRefine=False)

        self.tMax = tMax
        self.satSteps = satSteps
        self.ertSteps = ertSteps
        self.timesAdvection = np.linspace(1, tMax, satSteps)
        self.timesERT = pg.IndexArray(
            np.floor(
                np.linspace(0,
                            len(self.timesAdvection) - 1, self.ertSteps)))

        self._J = pg.Matrix()
        self.setJacobian(self._J)
        self.ws = WorkSpace()
Exemplo n.º 15
0
    def __init__(self, fvec, tvec, verbose=False):  # save reference in class
        """constructor with frequecy and tau vector"""
        self.f = fvec
        self.nf = len(fvec)
        self.t = tvec
        self.nt = len(tvec)
        mesh = pg.meshtools.createMesh1D(len(tvec))  # standard 1d mesh
        super(DebyeComplex, self).__init__(mesh, verbose)
        T, W = np.meshgrid(tvec, fvec * 2. * pi)
        WT = W*T
        self.A = WT**2 / (WT**2 + 1)
        self.B = WT / (WT**2+1)
        self.J = pg.Matrix()
        self.J.resize(len(fvec)*2, len(tvec))
        for i in range(self.nf):
            wt = fvec[i] * 2.0 * pi * tvec
            wt2 = wt**2
            self.J[i] = wt2 / (wt2 + 1.0)
            self.J[i+self.nf] = wt / (wt2 + 1.0)

        self.setJacobian(self.J)
Exemplo n.º 16
0
def interpolate(*args, **kwargs):
    r"""Interpolation convinience function.

    Convenience function to interpolate different kind of data.
    Currently supported interpolation schemes are:

    * Interpolate mesh based data from one mesh to another
     (syntactic sugar for the core based interpolate (see below))

      Parameters:
        args: :gimliapi:`GIMLI::Mesh`, :gimliapi:`GIMLI::Mesh`, iterable
            `outData = interpolate(outMesh, inMesh, vals)`
            Interpolate values based on inMesh to outMesh.
            Values can be of length inMesh.cellCount() interpolated to
            outMesh.cellCenters() or inMesh.nodeCount() which are interpolated tp
            outMesh.positions().

      Returns:
        Interpolated values.

    * Mesh based values to arbitrary points, based on finite element
      interpolation (from gimli core).

      Parameters:
        args: :gimliapi:`GIMLI::Mesh`, ...
            Arguments forwarded to :gimliapi:`GIMLI::interpolate`
        kwargs:
            Arguments forwarded to :gimliapi:`GIMLI::interpolate`

        `interpolate(srcMesh, destMesh)`
            All data from inMesh are interpolated to outMesh

      Returns:
        Interpolated values

    * Interpolate along curve.
      Forwarded to :py:mod:`pygimli.meshtools.interpolateAlongCurve`

      Parameters:
        args: curve, t

        kwargs:
            Arguments forwarded to
            :py:mod:`pygimli.meshtools.interpolateAlongCurve`

    * 1D point set :math:`u(x)` for ascending :math:`x`.
      Find interpolation function :math:`I = u(x)` and
      returns :math:`u_{\text{i}} = I(x_{\text{i}})`
      (interpolation methods are [**linear** via matplotlib,
      cubic **spline** via scipy, fit with **harmonic** functions' via pygimli])
      Note, for 'linear' and 'spline' the interpolate contains all original
      coordinates while 'harmonic' returns an approximate best fit.
      The amount of harmonic coefficients can be specfied with the 'nc' keyword.

      Parameters:
        args: xi, x, u
            * :math:`x_{\text{i}}` - target sample points
            * :math:`x` - function sample points
            * :math:`u` - function values
        kwargs:
            * method : string
                Specify interpolation method 'linear, 'spline', 'harmonic'
            * nc : int
                Number of harmonic coefficients for the 'harmonic' method.

      Returns:
        ui: array of length xi
            :math:`u_{\text{i}} = I(x_{\text{i}})`, with :math:`I = u(x)`


    To use the core functions :gimliapi:`GIMLI::interpolate` start with a
    mesh instance as first argument or use the appropriate keyword arguments.

    TODO

    * 2D parametric to points (method=['linear, 'spline', 'harmonic'])
    * 2D/3D point cloud to points/grids ('Delauney', 'linear, 'spline', 'harmonic')
    * Mesh to points based on nearest neighbour values (pg.core)

    Examples
    --------
    >>> # no need to import matplotlib. pygimli's show does
    >>> import numpy as np
    >>> import pygimli as pg
    >>> fig, ax = pg.plt.subplots(1, 1, figsize=(10, 5))
    >>> u = np.array([1.0, 12.0, 3.0, -4.0, 5.0, 6.0, -1.0])
    >>> xu = np.array(range(len(u)))
    >>> xi = np.linspace(xu[0], xu[-1], 1000)
    >>> _= ax.plot(xu, u, 'o')
    >>> _= ax.plot(xi, pg.interpolate(xi, xu, u, method='linear'),
    ...         color='blue', label='linear')
    >>> _= ax.plot(xi, pg.interpolate(xi, xu, u, method='spline'),
    ...            color='red', label='spline')
    >>> _= ax.plot(xi, pg.interpolate(xi, xu, u, method='harmonic'),
    ...         color='green', label='harmonic')
    >>> _= ax.legend()
    """
    pgcore = False
    if 'srcMesh' in kwargs:
        pgcore = True

    elif len(args) > 0:
        if isinstance(args[0], pg.Mesh):
            if len(args) == 2 and isinstance(args[1], pg.Mesh):
                return pg.core._pygimli_.interpolate(args[0], args[1],
                                                     **kwargs)

            if len(args) == 3 and isinstance(args[1], pg.Mesh):
                pgcore = False  # (outMesh, inMesh, vals)
            else:
                pgcore = True

    if pgcore:
        if len(args) == 3:  # args: outData = (inMesh, inData, outPos)

            if args[1].ndim == 2:  # outData = (inMesh, mat, vR3)

                outMat = pg.Matrix()
                pg.core._pygimli_.interpolate(args[0],
                                              inMat=np.array(args[1]),
                                              destPos=args[2],
                                              outMat=outMat,
                                              **kwargs)
                return np.array(outMat)

        if len(args) == 4:  # args: (inMesh, inData, outPos, outData)

            if args[1].ndim == 1 and args[2].ndim == 1 and args[3].ndim == 1:
                return pg.core._pygimli_.interpolate(args[0],
                                                     inVec=args[1],
                                                     x=args[2],
                                                     y=args[3],
                                                     **kwargs)

            if isinstance(args[1], pg.RMatrix) and \
               isinstance(args[3], pg.RMatrix):
                return pg.core._pygimli_.interpolate(args[0],
                                                     inMat=args[1],
                                                     destPos=args[2],
                                                     outMat=args[3],
                                                     **kwargs)
            if isinstance(args[1], pg.RVector) and \
               isinstance(args[3], pg.RVector):
                return pg.core._pygimli_.interpolate(args[0],
                                                     inVec=args[1],
                                                     destPos=args[2],
                                                     outVec=args[3],
                                                     **kwargs)

        if len(args) == 5:
            if args[1].ndim == 1 and args[2].ndim == 1 and \
               args[3].ndim == 1 and args[4].ndim == 1:
                return pg.core._pygimli_.interpolate(args[0],
                                                     inVec=args[1],
                                                     x=args[2],
                                                     y=args[3],
                                                     z=args[4],
                                                     **kwargs)

        return pg.core._pygimli_.interpolate(*args, **kwargs)
        # end if pg.core:

    if len(args) == 3:

        if isinstance(args[0], pg.Mesh):  # args: (outMesh, inMesh, data)
            outMesh = args[0]
            inMesh = args[1]
            data = args[2]

            if isinstance(data, pg.R3Vector) or isinstance(
                    data, pg.stdVectorRVector3):
                x = pg.interpolate(outMesh, inMesh, pg.x(data))
                y = pg.interpolate(outMesh, inMesh, pg.y(data))
                z = pg.interpolate(outMesh, inMesh, pg.z(data))
                return np.vstack([x, y, z]).T

            if isinstance(data, np.ndarray):
                if data.ndim == 2 and data.shape[1] == 3:
                    x = pg.interpolate(outMesh, inMesh, data[:, 0])
                    y = pg.interpolate(outMesh, inMesh, data[:, 1])
                    z = pg.interpolate(outMesh, inMesh, data[:, 2])
                    return np.vstack([x, y, z]).T

            if len(data) == inMesh.cellCount():
                return pg.interpolate(srcMesh=inMesh,
                                      inVec=data,
                                      destPos=outMesh.cellCenters())
            elif len(data) == inMesh.nodeCount():
                return pg.interpolate(srcMesh=inMesh,
                                      inVec=data,
                                      destPos=outMesh.positions())
            else:
                print(inMesh)
                print(outMesh)
                raise Exception("Don't know how to interpolate data of size",
                                str(len(data)))

            print("data: ", data)
            raise Exception("Cannot interpret data: ", str(len(data)))

        else:  #args: xi, x, u

            xi = args[0]
            x = args[1]
            u = args[2]

            method = kwargs.pop('method', 'linear')

            if 'linear' in method:
                return np.interp(xi, x, u)

            if 'harmonic' in method:
                coeff = kwargs.pop('nc', int(np.ceil(np.sqrt(len(x)))))
                from pygimli.frameworks import harmfitNative
                return harmfitNative(u, x=x, nc=coeff, xc=xi, err=None)[0]

            if 'spline' in method:
                if pg.optImport("scipy",
                                requiredFor="use interpolate splines."):
                    from scipy import interpolate
                    tck = interpolate.splrep(x, u, s=0)
                    return interpolate.splev(xi, tck, der=0)
                else:
                    return xi * 0.

    if len(args) == 2:  # args curve, t
        curve = args[0]
        t = args[1]
        return interpolateAlongCurve(curve, t, **kwargs)
Exemplo n.º 17
0
    def createJacobian(self, model):
        print('=' * 100)

        if self.complex():
            modelRe = model[0:int(len(model)/2)]
            modelIm = model[int(len(model)/2):len(model)]
            modelC = pg.math.toComplex(modelRe, modelIm)
            print("Real", min(modelRe), max(modelRe))
            print("Imag", min(modelIm), max(modelIm))

            u = self.prepareJacobian_(modelC)

            if self._J.rows() == 0:
                #re(data)/re(mod) = im(data)/im(mod)
                # we need a local copy until we have a gimli internal reference counter FIXTHIS
                M1 = pg.Matrix()
                M2 = pg.Matrix()
                self.matrixHeap.append(M1)
                self.matrixHeap.append(M2)

                JRe = self._J.addMatrix(M1)
                JIm = self._J.addMatrix(M2)

                self._J.addMatrixEntry(JRe, 0, 0)
                self._J.addMatrixEntry(JIm, 0, len(modelRe), -1.0)
                self._J.addMatrixEntry(JIm, self.data().size(), 0, 1.0)
                self._J.addMatrixEntry(JRe, self.data().size(), len(modelRe))

            else:
                self._J.clean()


            k = pg.Vector(self.data()('k'))
            self.data().set('k', k*0.0 + 1.0)

            dMapResponse = pb.DataMap()
            dMapResponse.collect(self.electrodes(), self.solution())
            respRe = dMapResponse.data(self.data(), False, False)
            respIm = dMapResponse.data(self.data(), False, True)

            #CVector resp(toComplex(respRe, respIm));
            #RVector am(abs(resp) * dataContainer_->get("k"));
            #RVector ph(-phase(resp));

            print("respRe", pg.math.median(respRe), min(respRe), max(respRe))
            print("respIm", pg.math.median(respIm), min(respIm), max(respIm))

            JC = pg.matrix.CMatrix()
            self.createJacobian_(modelC, u, JC)
            for i in range(JC.rows()):
                #JC[i] *= 1.0/(modelC*modelC) * k[i]
                JC[i] /= (modelC * modelC) / k[i]

            self._J.mat(0).copy(pg.math.real(JC))
            self._J.mat(1).copy(pg.math.imag(JC))

            #self.createJacobian_(modelRe*0.0+1.0, pg.math.real(u), self._J.mat(1))
            #self.createJacobian_(modelRe*0.0+1.0, pg.math.imag(u), self._J.mat(2))
            #self.createJacobian_(modelRe*0.0+1.0, pg.math.imag(u), self._J.mat(3))


            sumsens0 = pg.Vector(self._J.mat(0).rows())
            sumsens1 = pg.Vector(self._J.mat(0).rows())
            sumsens2 = pg.Vector(self._J.mat(0).rows())

            for i in range(self._J.mat(0).rows()):
                #self._J.mat(0)[i] *= 1./modelRe / respRe[i]
                #self._J.mat(1)[i] *= 1./modelIm / respRe[i]

                #self._J.mat(2)[i] *= 1./modelRe / respIm[i]
                #self._J.mat(3)[i] *= 1./modelIm / respIm[i]

                #self._J.mat(0)[i] *= 1./(modelRe * modelRe) * k[i]
                #self._J.mat(1)[i] *= 1./(modelRe * modelIm) * k[i]

                #self._J.mat(2)[i] *= 1./(modelIm * modelRe) * k[i]
                #self._J.mat(3)[i] *= 1./(modelIm * modelIm) * k[i]

                sumsens0[i] = sum(self._J.mat(0)[i])
                sumsens1[i] = sum(self._J.mat(1)[i])
                sumsens2[i] = abs(sum(JC[i]))

            print(pg.math.median(sumsens0), min(sumsens0), max(sumsens0))
            print(pg.math.median(sumsens1), min(sumsens1), max(sumsens1))
            print(pg.math.median(sumsens2), min(sumsens2), max(sumsens2))

            self.data().set('k', k)

            self._J.recalcMatrixSize()
        else:
            # self.setVerbose(True)
            u = self.prepareJacobian_(model)

            #J = pg.Matrix()
            if self._J.rows() == 0:
                print('#' * 100)
                M1 = pg.Matrix()
                Jid = self._J.addMatrix(M1)
                self._J.addMatrixEntry(Jid, 0, 0)
            else:
                self._J.clean()

            self.createJacobian_(model, u, self._J.mat(0))
            self._J.recalcMatrixSize()
Exemplo n.º 18
0
def calc(out, mesh, density, viscosity):
    print(mesh)

    velBoundary = [[1, [0.0, 'nan']], [2, [0.0, 'nan']], [3, ['nan', 0.0]],
                   [4, ['nan', 0.0]]]
    preBoundary = [
        [1, 0.0],
        [2, 0.0],
        [3, 0.0],
        [4, 0.0],
    ]

    densMatrix = pg.Matrix()
    vels = []

    swatch = pg.core.Stopwatch(True)

    class WS():
        pass

    wsfv = WS()

    ax, _ = pg.show(mesh, density)

    v = 1
    nSteps = 3000

    dt = 0.1 * v
    dtSteps = 20

    meshC = pg.createGrid(x=np.linspace(-10, 10, 21), y=np.linspace(0, 20, 21))

    vel = None
    pre = None

    for i in range(nSteps):
        print(i, 'dens', min(density), max(density), "t:", dt * i)

        densMatrix.push_back(density)

        if v > 1:
            viscosity = 1.0 * density  #v3
        elif v < 1:
            viscosity = 1.0 / density  #v3
        else:
            viscosity = 1.0

        vel, pre, pCNorm, divVNorm = solver.solveStokes(
            mesh,
            velBoundary=velBoundary,
            preBoundary=preBoundary,
            viscosity=viscosity,
            density=density,
            pre0=pre,
            vel0=vel,
            f=[density * 0, (density - 1.0) * -9.81],
            maxIter=1000,
            tol=1e-6,
            verbose=1,
            vRelax=0.1,
            pRelax=0.1,
            ws=wsfv)
        vels.append(vel)

        print("stokes:", swatch.duration(True), "div V: ", divVNorm[-1])
        dens2 = solver.solveFiniteVolume(
            mesh,
            a=1. / 500,
            b=0.0,
            u0=density,
            vel=vel,
            times=np.linspace(0, dt, dtSteps),
            #uBoundary=[4, 0],
            scheme='PS',
            verbose=0)
        print("Convekt:", swatch.duration(True))
        density = dens2[-1]

        ax.clear()
        pg.show(mesh, density, axes=ax)
        pg.show(mesh, vel, coarseMesh=meshC, axes=ax, color='white')

    mesh.save(out)
    meshC.save(out + 'C')
    densMatrix.save(out + 'density.bmat')
    np.save(out + 'velo.bmat', vels)
Exemplo n.º 19
0
    def invert(self, data, values=None, verbose=0, **kwargs):
        """
        Invert the given data.

        A parametric mesh for the inversion will be created if non is given
        before.

        Parameters
        ----------
        """
        self.fop.setVerbose(verbose)
        self.inv.setVerbose(verbose)
        self.inv.setMaxIter(kwargs.pop('maxiter', 10))
        self.inv.setLambda(kwargs.pop('lambd', 10))

        if self.paraMesh is None:
            self.paraMesh = createParaMesh2dGrid(data.sensorPositions(),
                                                 **kwargs)
            self.setParaMesh(self.paraMesh)
            if verbose:
                print(self.paraMesh)


#                pg.show(self.paraMesh)

        err = data('err')
        rhoa = data('rhoa')

        startModel = pg.Vector(self.fop.regionManager().parameterCount(),
                               pg.math.median(rhoa))

        self.fop.setData(data)
        self.inv.setForwardOperator(self.fop)

        # check err here
        self.inv.setData(rhoa)
        self.inv.setError(err)
        self.inv.setModel(startModel)

        model = self.inv.run()

        if values is not None:

            if isinstance(values, pg.Vector):
                values = [values]
            elif isinstance(values, np.ndarray):
                if values.ndim == 1:
                    values = [values]

            allModel = pg.Matrix(len(values), len(model))

            self.inv.setVerbose(False)
            for i in range(len(values)):
                print(i)
                tic = time.time()
                self.inv.setModel(model)
                self.inv.setReferenceModel(model)
                dData = pg.abs(values[i] / rhoa)

                relModel = self.inv.invSubStep(pg.log(dData))
                allModel[i] = model * pg.exp(relModel)
                print(i, "/", len(values), " : ",
                      time.time() - tic, "s min/max: ", min(allModel[i]),
                      max(allModel[i]))

            return allModel
        return model
Exemplo n.º 20
0
    def simulate(self, mesh, scheme, res, **kwargs):
        """Simulate an ERT measurement.

        Perform the forward task for a given mesh, a resistivity distribution
        (per cell), a measurement
        scheme and will return data (apparent resistivity) or potential fields.

        This function can also operate on complex resistivity models, thereby
        computing complex apparent resistivities.

        The forward operator itself only calculate potential values
        for the given scheme file.
        To calculate apparent resistivities, geometric factors (k) are needed.
        If there are no values k in the DataContainerERT scheme, then we will
        try to calculate them, either analytic or by using a p2-refined
        version of the given mesh.

        TODO
        ----
        * 2D + Complex + SR

        Args
        ----
        mesh : :gimliapi:`GIMLI::Mesh`
            2D or 3D Mesh to calculate for.

        res : float, array(mesh.cellCount()) | array(N, mesh.cellCount()) | list
            Resistivity distribution for the given mesh cells can be:
            . float for homogeneous resistivity
            . single array of length mesh.cellCount()
            . matrix of N resistivity distributions of length mesh.cellCount()
            . resistivity map as [[regionMarker0, res0],
                                  [regionMarker0, res1], ...]

        scheme : :gimliapi:`GIMLI::DataContainerERT`
            Data measurement scheme.

        Keyword Args
        ------------
        verbose: bool[False]
            Be verbose. Will override class settings.
        calcOnly: bool [False]
            Use fop.calculate instead of fop.response. Useful if you want
            to force the calculation of impedances for homogeneous models.
            No noise handling. Solution is put as token 'u' in the returned
            DataContainerERT.
        noiseLevel: float [0.0]
            add normally distributed noise based on
            scheme('err') or on noiseLevel if scheme did not contain 'err'
        noiseAbs: float [0.0]
            Absolute voltage error in V
        returnArray: bool [False]
            Returns an array of apparent resistivities instead of
            a DataContainerERT
        returnFields: bool [False]
            Returns a matrix of all potential values (per mesh nodes)
            for each injection electrodes.

        Returns
        -------
        DataContainerERT | array(N, data.size()) | array(N, data.size()) |
        array(N, data.size()):
            Data container with resulting apparent resistivity data and
            errors (if noiseLevel or noiseAbs is set).
            Optional returns a Matrix of rhoa values
            (for returnArray==True forces noiseLevel=0).
            In case of a complex valued resistivity model, phase values will be
            returned in the DataContainerERT (see example below), or as an
            additional returned array.

        Examples
        --------
        # TODO: Remove pybert dependencies
        # >>> import pybert as pb
        # >>> import pygimli as pg
        # >>> import pygimli.meshtools as mt
        # >>> world = mt.createWorld(start=[-50, 0], end=[50, -50],
        # ...                        layers=[-1, -5], worldMarker=True)
        # >>> scheme = pb.createData(
        # ...                     elecs=pg.utils.grange(start=-10, end=10, n=21),
        # ...                     schemeName='dd')
        # >>> for pos in scheme.sensorPositions():
        # ...     _= world.createNode(pos)
        # ...     _= world.createNode(pos + [0.0, -0.1])
        # >>> mesh = mt.createMesh(world, quality=34)
        # >>> rhomap = [
        # ...    [1, 100. + 0j],
        # ...    [2, 50. + 0j],
        # ...    [3, 10.+ 0j],
        # ... ]
        # >>> ert = pb.ERTManager()
        # >>> data = ert.simulate(mesh, res=rhomap, scheme=scheme, verbose=True)
        # >>> rhoa = data.get('rhoa').array()
        # >>> phia = data.get('phia').array()
        """
        verbose = kwargs.pop('verbose', self.verbose)
        calcOnly = kwargs.pop('calcOnly', False)
        returnFields = kwargs.pop("returnFields", False)
        returnArray = kwargs.pop('returnArray', False)
        noiseLevel = kwargs.pop('noiseLevel', 0.0)
        noiseAbs = kwargs.pop('noiseAbs', 1e-4)
        seed = kwargs.pop('seed', None)

        #segfaults with self.fop (test & fix)
        fop = self.createForwardOperator(useBert=self.useBert, sr=self.sr)
        fop.data = scheme
        fop.setMesh(mesh, ignoreRegionManager=True)
        fop.verbose = verbose

        rhoa = None
        phia = None

        isArrayData = False
        # parse the given res into mesh-cell-sized array
        if isinstance(res, int) or isinstance(res, float):
            res = np.ones(mesh.cellCount()) * float(res)
        elif isinstance(res, complex):
            res = np.ones(mesh.cellCount()) * res
        elif hasattr(res[0], '__iter__'):  # ndim == 2
            if len(res[0]) == 2:  # res seems to be a res map
                # check if there are markers in the mesh that are not defined in
                # the rhomap. better signal here before it results in some error
                meshMarkers = list(set(mesh.cellMarkers()))
                mapMarkers = [m[0] for m in res]
                if any([mark not in mapMarkers for mark in meshMarkers]):
                    left = [m for m in meshMarkers if m not in mapMarkers]
                    pg.critical(
                        "Mesh contains markers without assigned resistivities {}. Please fix given rhomap."
                        .format(left))
                res = pg.solver.parseArgToArray(res, mesh.cellCount(), mesh)
            else:  # probably nData x nCells array
                # better check for array data here
                isArrayData = True

        if isinstance(res[0], np.complex) or isinstance(res, pg.CVector):
            pg.info("Complex resistivity values found.")
            fop.setComplex(True)
        else:
            fop.setComplex(False)

        if not scheme.allNonZero('k') and not calcOnly:
            if verbose:
                pg.info('Calculate geometric factors.')
            scheme.set('k', fop.calcGeometricFactor(scheme))

        ret = pg.DataContainerERT(scheme)
        ## just be sure that we don't work with artifacts
        ret['u'] *= 0.0
        ret['i'] *= 0.0
        ret['r'] *= 0.0

        if isArrayData:
            rhoa = np.zeros((len(res), scheme.size()))
            for i, r in enumerate(res):
                rhoa[i] = fop.response(r)
                if verbose:
                    print(i, "/", len(res), " : ", pg.dur(), "s", "min r:",
                          min(r), "max r:", max(r), "min r_a:", min(rhoa[i]),
                          "max r_a:", max(rhoa[i]))
        else:  # res is single resistivity array
            if len(res) == mesh.cellCount():

                if calcOnly:
                    fop.mapERTModel(res, 0)

                    dMap = pg.core.DataMap()
                    fop.calculate(dMap)
                    if fop.complex():
                        pg.critical('Implement me')
                    else:
                        ret["u"] = dMap.data(scheme)
                        ret["i"] = np.ones(ret.size())

                    if returnFields:
                        return pg.Matrix(fop.solution())
                    return ret
                else:
                    if fop.complex():
                        res = pg.utils.squeezeComplex(res)

                    resp = fop.response(res)

                    if fop.complex():
                        rhoa, phia = pg.utils.toPolar(resp)
                    else:
                        rhoa = resp
            else:
                print(mesh)
                print("res: ", res)
                raise BaseException(
                    "Simulate called with wrong resistivity array.")

        if not isArrayData:
            ret['rhoa'] = rhoa

            if phia is not None:
                ret.set('phia', phia)
        else:
            ret.set('rhoa', rhoa[0])
            if phia is not None:
                ret.set('phia', phia[0])

        if returnFields:
            return pg.Matrix(fop.solution())

        if noiseLevel > 0:  # if errors in data noiseLevel=1 just triggers
            if not ret.allNonZero('err'):
                # 1A  and #100µV
                ret.set(
                    'err',
                    self.estimateError(ret,
                                       relativeError=noiseLevel,
                                       absoluteUError=noiseAbs,
                                       absoluteCurrent=1))
                print("Data error estimate (min:max) ", min(ret('err')), ":",
                      max(ret('err')))

            rhoa *= 1. + pg.randn(ret.size(), seed=seed) * ret('err')
            ret.set('rhoa', rhoa)

            ipError = None
            if phia is not None:
                if scheme.allNonZero('iperr'):
                    ipError = scheme('iperr')
                else:
                    # np.abs(self.data("phia") +TOLERANCE) * 1e-4absoluteError
                    if noiseLevel > 0.5:
                        noiseLevel /= 100.

                    if 'phiErr' in kwargs:
                        ipError = np.ones(
                            ret.size()) * kwargs.pop('phiErr') / 1000
                    else:
                        ipError = abs(ret["phia"]) * noiseLevel

                    if verbose:
                        print("Data IP abs error estimate (min:max) ",
                              min(ipError), ":", max(ipError))

                phia += np.randn(ret.size(), seed=seed) * ipError
                ret['iperr'] = ipError
                ret['phia'] = phia

        # check what needs to be setup and returned

        if returnArray:
            if phia is not None:
                return rhoa, phia
            else:
                return rhoa

        return ret
Exemplo n.º 21
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
Exemplo n.º 22
0
    def response(self, model):
        """Solve forward task.

        Create apparent resistivity values for a given resistivity distribution
        for self.mesh.
        """
        ### NOTE TODO can't be MT until mixed boundary condition depends on
        ### self.resistivity
        pg.tic()
        if not self.data.allNonZero('k'):
            pg.error('Need valid geometric factors: "k".')
            pg.warn('Fallback "k" values to -sign("rhoa")')
            self.data.set('k', -pg.math.sign(self.data('rhoa')))

        mesh = self.mesh()

        nDof = mesh.nodeCount()
        elecs = self.data.sensorPositions()

        nEle = len(elecs)
        nData = self.data.size()

        self.resistivity = res = self.createMappedModel(model, -1.0)

        if self.verbose:
            print("Calculate response for model:", min(res), max(res))

        rMin = elecs[0].dist(elecs[1]) / 2.0
        rMax = elecs[0].dist(elecs[-1]) * 2.0

        k, w = self.getIntegrationWeights(rMin, rMax)

        self.k = k
        self.w = w

        # pg.show(mesh, res, label='res')
        # pg.wait()

        rhs = self.createRHS(mesh, elecs)

        # store all potential fields
        u = np.zeros((nEle, nDof))
        self.subPotentials = [pg.Matrix(nEle, nDof) for i in range(len(k))]

        for i, ki in enumerate(k):
            ws = dict()
            uE = pg.solve(mesh,
                          a=1. / res,
                          b=-(ki * ki) / res,
                          f=rhs,
                          bc={'Robin': ['*', self.mixedBC]},
                          userData={
                              'sourcePos': elecs,
                              'k': ki
                          },
                          verbose=False,
                          stats=0,
                          debug=False)
            self.subPotentials[i] = uE
            u += w[i] * uE

        # collect potential matrix,
        # i.e., potential for all electrodes and all injections
        pM = np.zeros((nEle, nEle))

        for i in range(nEle):
            pM[i] = pg.interpolate(mesh, u[i, :], destPos=elecs)

        # collect resistivity values for all 4 pole measurements
        r = np.zeros(nData)

        for i in range(nData):
            iA = int(self.data('a')[i])
            iB = int(self.data('b')[i])
            iM = int(self.data('m')[i])
            iN = int(self.data('n')[i])

            uAB = pM[iA] - pM[iB]
            r[i] = uAB[iM] - uAB[iN]

        self.lastResponse = r * self.data('k')

        if self.verbose:
            print("Resp min/max: {0} {1} {2}s".format(min(self.lastResponse),
                                                      max(self.lastResponse),
                                                      pg.dur()))

        return self.lastResponse
Exemplo n.º 23
0
    def createJacobian(self, model):
        """TODO WRITEME."""
        if self.subPotentials is None:
            self.response(model)

        J = self.jacobian()
        J.resize(self.data.size(), self.regionManager().parameterCount())

        cells = self.mesh().findCellByMarker(0, -1)
        Si = pg.matrix.ElementMatrix()
        St = pg.matrix.ElementMatrix()

        u = self.subPotentials

        pg.tic()
        if self.verbose:
            print("Calculate sensitivity matrix for model: ", min(model),
                  max(model))

        Jt = pg.Matrix(self.data.size(), self.regionManager().parameterCount())

        for kIdx, w in enumerate(self.w):
            k = self.k[kIdx]
            w = self.w[kIdx]

            Jt *= 0.
            A = pg.matrix.ElementMatrixMap()

            for i, c in enumerate(cells):
                modelIdx = c.marker()

                # 2.5D
                Si.u2(c)
                Si *= k * k
                Si += St.ux2uy2uz2(c)

                # 3D
                # Si.ux2uy2uz2(c); w = w* 2

                A.add(modelIdx, Si)

            for dataIdx in range(self.data.size()):

                a = int(self.data('a')[dataIdx])
                b = int(self.data('b')[dataIdx])
                m = int(self.data('m')[dataIdx])
                n = int(self.data('n')[dataIdx])
                Jt[dataIdx] = A.mult(u[kIdx][a] - u[kIdx][b],
                                     u[kIdx][m] - u[kIdx][n])

            J += w * Jt

        m2 = model * model
        k = self.data('k')

        for i in range(J.rows()):
            J[i] /= (m2 / k[i])

        if self.verbose:
            sumsens = np.zeros(J.rows())
            for i in range(J.rows()):
                sumsens[i] = pg.sum(J[i])
            print("sens sum: median = ", pg.math.median(sumsens), " min = ",
                  pg.min(sumsens), " max = ", pg.max(sumsens))
Exemplo n.º 24
0
def solveERT(mesh, concentration, verbose=0):
    """Simulate resistivity distribution for given nonsteady concentration."""
    if verbose:
        print("Solve for ERT ...")

    ertScheme = pg.physics.ert.createERTData(pg.utils.grange(-20, 20, dx=1.0),
                                             schemeName='dd')

    meshERT = mt.createParaMesh(ertScheme,
                                quality=33,
                                paraMaxCellSize=0.2,
                                boundaryMaxCellSize=50,
                                smooth=[1, 2])

    scale = 0.001
    concentration *= scale  # mg/m²

    # apply saturation model to simulate unsaturated topsoil
    sat = np.zeros(mesh.cellCount())
    for c in mesh.cells():
        if c.center()[1] < -8:
            sat[c.id()] = 1.
        elif c.center()[1] < -2:
            sat[c.id()] = 1.
        else:
            sat[c.id()] = .5

    cWater = 1. / 100.
    conductivity = concentration * 0.1 + cWater

    rArchie = resistivityArchie(rFluid=1. / conductivity,
                                porosity=0.3,
                                sat=sat,
                                m=1.3,
                                mesh=mesh,
                                meshI=meshERT,
                                fill=1)

    # apply background resistivity model
    rho0 = np.zeros(meshERT.cellCount())
    for c in meshERT.cells():
        if c.center()[1] < -8:
            rho0[c.id()] = 150.
        elif c.center()[1] < -2:
            rho0[c.id()] = 500.
        else:
            rho0[c.id()] = 1000.

    resis = pg.Matrix(rArchie)

    for i, rbI in enumerate(rArchie):
        resis[i] = 1. / ((1. / rbI) + 1. / rho0)

    ert = pg.physics.ert.ERTManager(verbose=False)
    ertScheme.set('k', ert.fop.calcGeometricFactor(ertScheme))

    errPerc = 0.01
    errVolt = 1e-5

    rhoa = ert.simulate(meshERT, resis, ertScheme, verbose=0, returnArray=True)

    voltage = rhoa / ertScheme('k')
    err = np.abs(errVolt / voltage) + errPerc

    dRhoa = rhoa[1:] / rhoa[0]
    dErr = err[1:]

    return meshERT, ertScheme, resis, rhoa, dRhoa, dErr
Exemplo n.º 25
0
sigmaFluid = c[timesERT] * 0.1 + 0.01
# Calculate bulk resistivity based on Archie's Law
resBulk = petro.resistivityArchie(rFluid=1. / sigmaFluid,
                                  porosity=0.3,
                                  m=1.3,
                                  mesh=mesh,
                                  meshI=meshERT,
                                  fill=1)
# apply background resistivity model
rho0 = np.zeros(meshERT.cellCount()) + 1000.
for c in meshERT.cells():
    if c.center()[1] < -8:
        rho0[c.id()] = 150.
    elif c.center()[1] < -2:
        rho0[c.id()] = 500.
resis = pg.Matrix(resBulk)
for i, rbI in enumerate(resBulk):
    resis[i] = 1. / ((1. / rbI) + 1. / rho0)
# Initialize ert method manager
ERT = ERTManager(verbose=False)
# Run  simulation for  the apparent resistivities
rhoa = ERT.simulate(meshERT, resis, ertScheme, verbose=0, returnArray=True)

# Solve the electrical forward problem using the ERT method manager
axs = pg.plt.subplots(3, 2, sharex=True, sharey=True)[1].flatten()
for i in range(6):
    ERT.showData(ertScheme, vals=rhoa[i] / rhoa[0], ax=axs[i])

# just hold figure windows open if run outside from spyder, ipython or similar
pg.wait()
Exemplo n.º 26
0
def solvePressureWave(mesh,
                      velocities,
                      times,
                      sourcePos,
                      uSource,
                      verbose=False):
    r"""
    Solve pressure wave equation.

    Solve pressure wave for a given source function

    .. math::
        \frac{\partial^2 u}{\partial t^2} & = \diverg(a\grad u) + f\\
        finalize equation


    Parameters
    ----------
    mesh : :gimliapi:`GIMLI::Mesh`
        Mesh to solve on

    velocities : array
        velocities for each cell of the mesh

    time : array
        Time base definition

    sourcePos : RVector3
        Source position

    uSource : array
        u(t, sourcePos) source movement of length(times)
        Usually a Ricker wavelet of the desired seismic signal frequency.

    Returns
    -------
    u : RMatrix

        Return

    Examples
    --------
    See TODO write example
    """
    A = pg.matrix.SparseMatrix()
    M = pg.matrix.SparseMatrix()

    #    F = pg.Vector(mesh.nodeCount(), 0.0)
    rhs = pg.Vector(mesh.nodeCount(), 0.0)
    u = pg.Matrix(len(times), mesh.nodeCount())
    v = pg.Matrix(len(times), mesh.nodeCount())

    sourceID = mesh.findNearestNode(sourcePos)

    if len(uSource) != len(times):
        raise Exception("length of uSource does not fit length of times: " +
                        str(uSource) + " != " + len(times))

    A.fillStiffnessMatrix(mesh, velocities * velocities)
    M.fillMassMatrix(mesh)
    #    M.fillMassMatrix(mesh, velocities)

    FV = 0
    if FV:
        A, rhs = pygimli.solver.diffusionConvectionKernel(mesh,
                                                          velocities *
                                                          velocities,
                                                          sparse=1)

        M = pygimli.solver.identity(len(rhs))

        u = pg.Matrix(len(times), mesh.cellCount())
        v = pg.Matrix(len(times), mesh.cellCount())
        sourceID = mesh.findCell(sourcePos).id()

    dt = times[1] - times[0]

    theta = 0.51
    #theta = 1.
    S1 = M + dt * dt * theta * theta * A
    S2 = M

    solver1 = pg.core.LinSolver(S1, verbose=False)
    solver2 = pg.core.LinSolver(S2, verbose=False)
    swatch = pg.core.Stopwatch(True)

    #    ut = pg.Vector(mesh.nodeCount(), .0)
    #    vt = pg.Vector(mesh.nodeCount(), .0)

    timeIter1 = np.zeros(len(times))
    timeIter2 = np.zeros(len(times))
    timeIter3 = np.zeros(len(times))
    timeIter4 = np.zeros(len(times))

    progress = pg.utils.ProgressBar(its=len(times), width=40, sign='+')

    for n in range(1, len(times)):
        u[n - 1, sourceID] = uSource[n - 1]

        # solve for u
        tic = time.time()
        # + * dt*dt * F
        rhs = dt * M * v[n - 1] + (M - dt * dt * theta *
                                   (1. - theta) * A) * u[n - 1]
        timeIter1[n - 1] = time.time() - tic

        tic = time.time()
        u[n] = solver1.solve(rhs)
        timeIter2[n - 1] = time.time() - tic

        # solve for v
        tic = time.time()
        rhs = M * v[n - 1] - dt * \
            ((1. - theta) * A * u[n - 1] + theta * A * u[n])  # + dt * F
        timeIter3[n - 1] = time.time() - tic

        tic = time.time()
        v[n] = solver2.solve(rhs)
        timeIter4[n - 1] = time.time() - tic

        #         same as above
        #        rhs = M * v[n-1] - dt * A * u[n-1] + dt * F
        #        v[n] = solver1.solve(rhs)

        t1 = swatch.duration(True)

        if verbose:
            progress(n)

    return u
Exemplo n.º 27
0
def calcSeismics(meshIn, vP):
    """Do seismic computations."""
    meshSeis = meshIn.createH2()
    meshSeis = mt.appendTriangleBoundary(meshSeis,
                                         xbound=25,
                                         ybound=22.0,
                                         marker=1,
                                         quality=32.0,
                                         area=0.3,
                                         smooth=True,
                                         markerBoundary=1,
                                         isSubSurface=False,
                                         verbose=False)
    print(meshSeis)
    meshSeis = meshSeis.createH2()
    meshSeis = meshSeis.createH2()
    # meshSeis = meshSeis.createP2()

    meshSeis.smooth(1, 1, 1, 4)
    vP = pg.interpolate(meshIn, vP, meshSeis.cellCenters())

    mesh = meshSeis
    vP = pg.solver.fillEmptyToCellArray(mesh, vP)

    print(mesh)
    # ax, cbar = pg.show(mesh, data=vP)
    # pg.show(mesh, axes=ax)

    geophPointsX = np.arange(-19, 19.1, 1)
    geophPoints = np.vstack((geophPointsX, np.zeros(len(geophPointsX)))).T
    sourcePos = geophPoints[4]

    c = mesh.findCell(sourcePos)
    h1 = pg.findBoundary(c.boundaryNodes(0)).size()
    h2 = pg.findBoundary(c.boundaryNodes(1)).size()
    h3 = pg.findBoundary(c.boundaryNodes(2)).size()
    print([h1, h2, h3])
    h = pg.math.median([h1, h2, h3])

    # h = pg.math.median(mesh.boundarySizes())
    f0scale = 0.25
    cfl = 0.5
    dt = cfl * h / max(vP)
    print("Courant-Friedrich-Lewy number:", cfl)

    tmax = 40. / min(vP)
    times = np.arange(0.0, tmax, dt)

    solutionName = createCacheName('seis', mesh, times) + "cfl-" + str(cfl)
    try:
        # u = pg.load(solutionName + '.bmat')
        uI = pg.load(solutionName + 'I.bmat')
    except Exception as e:
        print(e)
        f0 = f0scale * 1. / dt
        print("h:", round(h, 2), "dt:", round(dt, 5), "1/dt:",
              round(1 / dt, 1), "f0", round(f0, 2), "Wavelength: ",
              round(max(vP) / f0, 2), " m")

        uSource = ricker(times, f0, t0=1. / f0)

        plt.figure()
        plt.plot(times, uSource, '-*')
        plt.show(block=0)
        plt.pause(0.01)
        u = solvePressureWave(mesh,
                              vP,
                              times,
                              sourcePos=sourcePos,
                              uSource=uSource,
                              verbose=10)

        u.save(solutionName)
        uI = pg.Matrix()
        print("interpolate node to cell data ... ")
        pg.interpolate(mesh, u, mesh.cellCenters(), uI)
        print("... done")
        uI.save(solutionName + 'I')

#    nodes = [mesh.findNearestNode(p) for p in geophPoints]
#    fig = plt.figure()
#    axs = fig.add_subplot(1,1,1)
#    drawSeismogramm(axs, mesh, u, nodes, dt, i=None)
#    plt.show()

    dpi = 92
    scale = 1
    fig = plt.figure(facecolor='white',
                     figsize=(scale * 800 / dpi, scale * 490 / dpi),
                     dpi=dpi)
    ax = fig.add_subplot(1, 1, 1)
    gci = pg.viewer.mpl.drawModel(ax,
                                  mesh,
                                  data=uI[0],
                                  cMin=-1,
                                  cMax=1,
                                  cmap='bwr')
    pg.viewer.mpl.drawMeshBoundaries(ax, meshIn, hideMesh=1)
    ax.set_xlim((-20, 20))
    ax.set_ylim((-15, 0))
    ax.set_ylabel('Depth [m]')
    ax.set_xlabel('$x$ [m]')

    ticks = ax.yaxis.get_majorticklocs()
    tickLabels = []
    for t in ticks:
        tickLabels.append(str(int(abs(t))))

    ax.set_yticklabels(tickLabels)

    plt.tight_layout()

    #    ax, cbar = pg.show(mesh, data=vP)
    #    pg.showNow()
    #    ax = fig.add_subplot(1,1,1)

    def animate(i):
        i = i * 5
        if i > len(uI) - 1:
            return
        print("Frame:", i, "/", len(uI))
        ui = uI[i]
        ui = ui / max(pg.abs(ui))
        ui = pg.logDropTol(ui, 1e-2)
        cMax = max(pg.abs(ui))

        pg.viewer.mpl.setMappableData(gci,
                                      ui,
                                      cMin=-cMax,
                                      cMax=cMax,
                                      logScale=False)
        # plt.pause(0.001)

    anim = animation.FuncAnimation(fig,
                                   animate,
                                   frames=int(len(uI) / 5),
                                   interval=0.001,
                                   repeat=0)  # , blit=True)
    out = 'seis' + str(f0scale) + "cfl-" + str(cfl)
    anim.save(out + ".mp4",
              writer=None,
              fps=20,
              dpi=dpi,
              codec=None,
              bitrate=24 * 1024,
              extra_args=None,
              metadata=None,
              extra_anim=None,
              savefig_kwargs=None)
    try:
        print("create frames ... ")
        os.system('mkdir -p anim-' + out)
        os.system('ffmpeg -i ' + out + '.mp4 anim-' + out + '/movie%d.jpg')
    except:
        pass
Exemplo n.º 28
0
def resistivityArchie(rFluid,
                      porosity,
                      a=1.0,
                      m=2.0,
                      sat=1.0,
                      n=2.0,
                      mesh=None,
                      meshI=None,
                      fill=None,
                      show=False):
    r"""Resistivity of rock for the petrophysical model from Archies law.

    Calculates resistivity of rock for the petrophysical model from
    Archie's law. :cite:`Archie1942`

    .. math::
        \rho = a\rho_{\text{fl}}\phi^{-m} S^{-n}

    * :math:`\rho` - the electrical resistivity of the fluid saturated rock in
      :math:`\Omega\text{m}`
    * :math:`\rho_{\text{fl}}` - rFluid: electrical resistivity of the fluid in
      :math:`\Omega\text{m}`
    * :math:`\phi` - porosity 0.0 --1.0
    * :math:`S` - fluid saturation 0.0 --1.0 [sat]
    * :math:`a` - Tortuosity factor. (common 1)
    * :math:`m` - Cementation exponent of the rock (usually in the
      range 1.3 -- 2.5 for sandstones)
    * :math:`n` - is the saturation exponent (usually close to 2)

    If mesh is not None the resulting values are calculated for each cell of
    the mesh.
    All parameter can be scalar, array of length mesh.cellCount()
    or callable(pg.cell). If rFluid is non-steady n-step distribution
    than rFluid can be a matrix of size(n, mesh.cellCount())
    If meshI is not None the result is interpolated to meshI.cellCenters()
    and prolonged (if fill ==1).

    Notes
    -----
        We experience some unstable nonlinear behavior.
        Until this is clarified all results are rounded to the precision 1e-6.

    Examples
    --------
    >>> #

    WRITEME
    """
    phi = porosity
    if isinstance(porosity, list):
        phi = np.array(porosity)

    if mesh is None:
        return rFluid * a * phi**(-m) * sat**(-n)

    rB = None

    if isinstance(rFluid, float):
        rB = pg.Matrix(1, mesh.cellCount())
        rB[0] = pg.solver.parseArgToArray(rFluid, mesh.cellCount(), mesh)

    elif isinstance(rFluid, pg.Vector):
        rB = pg.Matrix(1, len(rFluid))
        rB[0] = pg.solver.parseArgToArray(rFluid, mesh.cellCount(), mesh)

    elif hasattr(rFluid, 'ndim') and rFluid.ndim == 1:
        rB = pg.Matrix(1, len(rFluid))
        rB[0] = pg.solver.parseArgToArray(rFluid, mesh.cellCount(), mesh)

    elif hasattr(rFluid, 'ndim') and rFluid.ndim == 2:
        rB = pg.Matrix(len(rFluid), len(rFluid[0]))
        for i, rFi in enumerate(rFluid):
            rB[i] = rFi

    phi = pg.solver.parseArgToArray(phi, mesh.cellCount(), mesh)
    a = pg.solver.parseArgToArray(a, mesh.cellCount(), mesh)
    m = pg.solver.parseArgToArray(m, mesh.cellCount(), mesh)
    S = pg.solver.parseArgToArray(sat, mesh.cellCount(), mesh)
    n = pg.solver.parseArgToArray(n, mesh.cellCount(), mesh)

    if show:
        pg.show(mesh, S, label='S')
        pg.show(mesh, phi, label='p')
        pg.wait()

    r = pg.Matrix(len(rB), len(rB[0]))
    for i, _ in enumerate(r):
        r[i] = rB[i] * a * phi**(-m) * S**(-n)

    r.round(1e-6)

    if meshI is None:
        if len(r) == 1:
            return r[0].copy()
        return r

    rI = pg.Matrix(len(r), meshI.cellCount())
    if meshI:
        pg.interpolate(mesh, r, meshI.cellCenters(), rI)

    if fill:
        for i, ri_ in enumerate(rI):
            # slope == True produce unstable behavior .. check!!!!!!
            rI[i] = mt.fillEmptyToCellArray(meshI, ri_, slope=False)

    rI.round(1e-6)

    if len(rI) == 1:
        # copy here because of missing refcounter TODO
        return rI[0].array()
    return rI