from pygimli.solver import solve """ """ import numpy as np import matplotlib.pyplot as plt from matplotlib import animation from pygimli.viewer import show from pygimli.viewer.mpl import drawStreams import time grid = pg.createGrid(x=np.linspace(-1.0, 1.0, 31), y=np.linspace(-1.0, 1.0, 31)) vals = pg.Vector(grid.cellCount(), 1.) for c in grid.cells(): if abs(c.center()[0]) < 0.1: vals[c.id()] = 10.0 #grid = grid.createP2() times = np.arange(0, 2, 1. / 20) #material? neumannBC = [ [1, -0.5], # left [2, 0.5] ] # right dirichletBC = [ [3, lambda b, t: 1.0 + np.cos(2.0 * np.pi * t)], # top
def transMult(self, b): ret = pg.Vector(self.cols()) print("TestMatrix::transMult") return ret
y = np.arange(-20, 0.0, dx)[::-1] mesh = pg.createGrid(x=x, y=y) mesh = createMesh2() print(mesh) h = pg.math.median(mesh.boundarySizes()) v1 = 1000 v2 = 3000 tmax = 10.1 / v1 z = 2. f0 = 1000.0 # A low wavelength of 50 Hz velocities = pg.Vector(mesh.cellCount(), v1) for c in mesh.cells(): velocities[c.id()] = v1 if c.center()[1] < -z: velocities[c.id()] = v2 dt = h * 0.5 / max(velocities) times = np.arange(0.0, tmax, dt) print(mesh, "h:", h, "dt:", dt, "n_t", len(times)) uSource = ricker(f0, times, t0=1. / f0) solutionName = 'uGridBig-' + str(dt) + '-' + str(h) nx = len(x)
if __name__ == '__main__': nlay = 4 # number of layers lam = 200. # (initial) regularization parameter errPerc = 3. # relative error of 3 percent ab2 = np.logspace(-1, 2, 50) # AB/2 distance (current electrodes) mn2 = ab2 / 3. # MN/2 distance (potential electrodes) f = pg.DC1dModelling(nlay, ab2, mn2) synres = [100., 500., 20., 800.] # synthetic resistivity synthk = [0.5, 3.5, 6.] # synthetic thickness (nlay-th layer is infinite) rhoa = f(synthk + synres) rhoa = rhoa * (pg.randn(len(rhoa)) * errPerc / 100. + 1.) transLog = pg.RTransLog() inv = LSQRInversion(rhoa, f, transLog, transLog, True) inv.setRelativeError(errPerc / 100) startModel = pg.cat(pg.Vector(nlay - 1, 5), pg.Vector(nlay, pg.median(rhoa))) print(inv.response()) inv.setModel(startModel) inv.setMarquardtScheme() inv.setLambda(1000) G = pg.RMatrix(rows=1, cols=len(startModel)) for i in range(3): G[0][i] = 1 c = pg.Vector(1, pg.sum(synthk)) inv.setParameterConstraints(G, c, 100) # print("Start", inv.chi2(), inv.relrms(), pg.sum(inv.model()(0, nlay-1))) if 0: for i in range(10): inv.oneStep() print(i, inv.chi2(), inv.relrms(), pg.sum(inv.model()(0,
def fitDebyeModel(self, ePhi=0.001, lam=1e3, lamFactor=0.8, mint=None, maxt=None, nt=None, new=True, showFit=False, cType=1, verbose=False): """Fit a (smooth) continuous Debye model (Debye decomposition). Parameters ---------- ePhi : float absolute error of phase angle lam : float regularization parameter lamFactor : float regularization factor for subsequent iterations mint/maxt : float minimum/maximum tau values to use (else automatically from f) nt : int number of tau values (default number of frequencies * 2) new : bool new implementation (experimental) showFit : bool show fit cType : int constraint type (1/2=smoothness 1st/2nd order, 0=minimum norm) """ nf = len(self.f) if mint is None: mint = .1 / max(self.f) if maxt is None: maxt = .5 / min(self.f) if nt is None: nt = nf * 2 # discretize tau, setup DD and perform DD inversion self.tau = np.logspace(log10(mint), log10(maxt), nt) phi = self.phi tLin, tLog, tM = pg.trans.Trans(), pg.trans.TransLog( ), pg.trans.TransLog() # pg.trans.TransLogLU(0., 1.) if new: reNorm, imNorm = self.zNorm() fDD = DebyeComplex(self.f, self.tau) Znorm = pg.cat(reNorm, imNorm) IDD = pg.core.Inversion(Znorm, fDD, tLog, tM, False) IDD.setAbsoluteError(max(Znorm) * 0.003 + ePhi) else: fDD = DebyePhi(self.f, self.tau) IDD = pg.core.Inversion(phi, fDD, tLin, tM, True) IDD.setAbsoluteError(ePhi) # 1 mrad fDD.regionManager().setConstraintType(cType) IDD.stopAtChi1(False) startModel = pg.Vector(nt, 0.01) IDD.setModel(startModel) IDD.setLambda(lam) IDD.setLambdaFactor(lamFactor) self.mDD = IDD.run() IDD.echoStatus() if new: print("ARMS=", IDD.absrms(), "RRMS=", IDD.absrms() / max(Znorm) * 100) resp = np.array(IDD.response()) respRe = resp[:nf] respIm = resp[nf:] respC = ((1 - respRe) + respIm * 1j) * max(self.amp) self.phiDD = np.angle(respC) self.ampDD = np.abs(respC) if showFit: fig, ax = self.showData(znorm=True, nrows=3) self.fig['DebyeFit'] = fig ax[0].plot(self.f, respRe, 'r-') ax[1].plot(self.f, respIm, 'r-') ax[2].semilogx(self.tau, self.mDD, 'r-') ax[2].set_xlim(max(self.tau), min(self.tau)) ax[2].set_ylim(0., max(self.mDD)) ax[2].grid(True) ax[2].set_xlabel(r'$\tau$ (s)') ax[2].set_ylabel('$m$ (-)') else: self.phiDD = IDD.response() if showFit: fig, ax = self.showData(nrows=3) self.fig['DebyeSpectrum'] = fig ax[2].semilogx(self.tau, self.mDD, 'r-')
def thkVel(self, model): """Return thickness and velocity vectors from model.""" thk = pg.cat(pg.Vector(1, self.d0), model(0, self.nlay - 1)) relvel = model(self.nlay - 1, self.nlay * 2 - 1) vel = self.v0 * np.cumprod(pg.cat(pg.Vector(1, 1.0), relvel)) return thk, vel
def startModel(self): return pg.Vector(self.nc_, 0.5)
print("Number of electrodes:", ertData.sensorCount()) print(ertData) rstData = pg.DataContainer("rst.data", "s g") print("Number of shot/receivers:", rstData.sensorCount()) maxrst = pg.max(pg.x(rstData.sensors())) idx = [] for i, sensor in enumerate(ertData.sensors()): if sensor[0] >= 50.0: idx.append(i) ertData.removeSensorIdx(idx) ertData.removeInvalid() ertData.removeUnusedSensors() ertData.set("err", pg.Vector(ertData.size(), erte)) ertData.save("ert_filtered.data") rstData.set("err", pg.Vector(rstData.size(), rste)) # # # Remove two data points with high v_a at zero-offset # Calculate offset px = pg.x(rstData.sensorPositions()) gx = np.array([px[int(g)] for g in rstData("g")]) sx = np.array([px[int(s)] for s in rstData("s")]) offset = np.absolute(gx - sx) va = offset / rstData("t") rstData.markInvalid((offset < 5) & (va > 800)) # # # Remove shot 27, too high apparent velocities rstData.markInvalid(np.isclose(rstData("s"), 27))
import pygimli as pg # log = logging.getLogger('pyGIMLi') # logging.basicConfig(level=logging.DEBUG, # format='%(asctime)s - %(name)s - ' + \ # '%(levelname)s - %(message)s', # datefmt='%m/%d/%Y %H:%M:%S', # #filename='example.log' # ) pg.version() # test pygimli log pg.info("Start numeric log test." + str(pg.log(pg.Vector(1, 1.)))) pg.setVerbose(True) pg.verbose("some verbose notes") pg.warn("Start warning test.") def testTraceback1(): def testTraceback2(): pg.error("Start error test.: int", 1, " vec", pg.Vector(2)) testTraceback2() testTraceback1() @pg.v def testVerboseDecorator1(): pg.verbose('testVerboseDecorator1 should be seen even if verbose is false')
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.core.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.core.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.Vector(3) >>> p[0] = 0.0 >>> p[1] = 1.0 >>> p[2] = 2.0 >>> print(diff(p)) 2 [1.0, 1.0] """ d = None if isinstance(v, np.ndarray): if v.ndim == 2: if v.shape[1] < 4: # v = pg.core.R3Vector(v.T) vt = v.copy() v = pg.core.R3Vector(len(vt)) for i, vi in enumerate(vt): v.setVal(pg.RVector3(vi), i) else: v = pg.core.R3Vector(v) else: v = pg.Vector(v) elif isinstance(v, list): v = pg.core.R3Vector(v) if isinstance(v, pg.core.R3Vector) or isinstance( v, pg.core.stdVectorRVector3): d = pg.core.R3Vector(len(v) - 1) else: d = pg.Vector(len(v) - 1) for i, _ in enumerate(d): d[i] = v[i + 1] - v[i] return d
def rand(n, minVal=0.0, maxVal=1.0): """Create RVector of length n with normally distributed random numbers.""" r = pg.Vector(n) pg.rand(r, minVal, maxVal) return r
def grange(start, end, dx=0, n=0, log=False): """Create array with possible increasing spacing. Create either array from start step-wise filled with dx until end reached [start, end] (like np.array with defined end). Fill the array from start to end with n steps. [start, end] (like np.linespace) Fill the array from start to end with n steps but logarithmic increasing, dx will be ignored. Parameters ---------- start: float First value of the resulting array end: float Last value of the resulting array dx: float Linear step length, n will be ignored n: int Amount of steps log: bool Logarithmic increasing range of length = n from start to end. dx will be ignored. Examples -------- >>> from pygimli.utils import grange >>> v1 = grange(start=0, end=10, dx=3) >>> v2 = grange(start=0, end=10, n=3) >>> print(v1) 4 [0.0, 3.0, 6.0, 9.0] >>> print(v2) 3 [0.0, 5.0, 10.0] Returns ------- ret: :gimliapi:`GIMLI::RVector` Return resulting array """ s = float(start) e = float(end) d = float(dx) if dx != 0 and not log: if end < start and dx > 0: # print("grange: decreasing range but increasing dx, swap dx sign") d = -d if end > start and dx < 0: # print("grange: increasing range but decreasing dx, swap dx sign") d = -d ret = pg.Vector(range(int(floor(abs((e - s) / d)) + 1))) ret *= d ret += s return ret elif n > 0: if not log: return grange(start, end, dx=(e - s) / (n - 1)) else: return pg.core.increasingRange(start, end, n)[1:] else: raise Exception('Either dx or n have to be given.')
def streamlineDir(mesh, field, startCoord, dLengthSteps, dataMesh=None, maxSteps=1000, down=True, verbose=False, coords=(0, 1)): """ down = -1, up = 1, both = 0 """ xd = [] yd = [] vd = [] pot = None vx = None vy = None isVectorData = False if isinstance(field, pg.core.R3Vector): field = field.array() if hasattr(field[0], '__len__'): if abs(max(field[:, 0])) == 0 and abs(max(field[:, 1]) == 0): raise BaseException("No data range streamline: min/max == ", min(field[:, 0])) vx = pg.Vector(field[:, 0]) vy = pg.Vector(field[:, 1]) isVectorData = True else: if min(field) == max(field): raise BaseException( "No scalar data range for any gradients " " to draw a streamline: min/max == ", min(field)) if dataMesh is not None: if len(field) == dataMesh.nodeCount(): pot = pg.Vector(field) elif len(field) == dataMesh.cellCount(): pot = pg.core.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.Vector(field) elif len(field) == mesh.cellCount(): pot = pg.core.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[coords[0]]) yd.append(pos[coords[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: print(mesh, len(vx), len(vy)) raise Exception("Data length neightor node size or cell size.") 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[coords[0]]) yd.append(pos[coords[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
print('Create response', str(par)) time.sleep(1) return par * 3.0 def response_mt(self, par, i=0): """ this need to be implemented as read only function! don't use self.mapModel until this is changed into a read only version """ print('Create response_mt(' + str(i) + ')', str(par)) time.sleep(1) return par * 2.0 nPars = 4 m = pg.Vector(nPars, 1) fop = TestModelling(nPars, verbose=True) fop.setMultiThreadJacobian(1) pg.tic() fop.createJacobian(m) pg.toc() print(fop.jacobian()) fop.setMultiThreadJacobian(4) pg.tic() fop.createJacobian(m) pg.toc() print(fop.jacobian())
cMax=1e-2, nLevs=4, cMap='viridis') ax, _ = pg.show(mesh, data=pg.abs(vel), logScale=0, label='Velocity $v$ in m$/$s') ax, _ = pg.show(mesh, data=vel, ax=ax, color='black', linewidth=0.5, dropTol=1e-6) print('Solve Advection-diffusion equation ...') S = pg.Vector(mesh.cellCount(), 0.0) # Fill injection source vector for a fixed injection position sourceCell = mesh.findCell([-19.1, -4.6]) S[sourceCell.id()] = 1.0 / sourceCell.size() # g/(l s) # Choose 800 time steps for 6 days in seconds t = pg.utils.grange(0, 6 * 24 * 3600, n=800) # Create dispersitivity, depending on the absolute velocity dispersion = pg.abs(vel) * 1e-2 # Solve for injection time, but we need velocities on cell nodes vel = mt.cellDataToNodeData(mesh, vel) c1 = pg.solver.solveFiniteVolume(mesh, a=dispersion, f=S, vel=vel, times=t, uB=[1, 0],
def testTraceback2(): pg.error("Start error test.: int", 1, " vec", pg.Vector(2))
def test_Interpolate(self): grid = pg.createGrid(x=[0.0, 1.0], y=[0.0, 1.0]) u = pg.RVector(grid.nodeCount(), 1.) # test with pg.interpolate queryPos = [0.2, 0.2] uI = pg.interpolate(srcMesh=grid, inVec=u, destPos=[queryPos, queryPos]) np.testing.assert_allclose(uI[0], 1.) # test manual interpolation c = grid.findCell(queryPos) uI = c.pot(queryPos, u) np.testing.assert_allclose(uI, 1.) # test with manual interpolationMatrix generation I = pg.RSparseMapMatrix(1, grid.nodeCount()) cI = c.N(c.shape().rst(queryPos)) for i in range(c.nodeCount()): I.addVal(0, c.node(i).id(), cI[i]) uI = I.mult(u) np.testing.assert_allclose(uI[0], 1) # test with automatic interpolationMatrix generation I = grid.interpolationMatrix([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]]) uI = I * u np.testing.assert_allclose(uI, u) # api test https://github.com/gimli-org/gimli/issues/131 x = np.linspace(grid.xmin(), grid.xmax(), 11) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x), x) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x=x), x) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x, x * 0.), x) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x=x, y=x * 0), x) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x, x * 0, x * 0), x) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x=x, y=x * 0, z=x * 0), x) x = pg.Vector(x) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x), x) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x=x), x) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x, x * 0.), x) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x=x, y=x * 0), x) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x, x * 0, x * 0), x) np.testing.assert_allclose( pg.interpolate(grid, pg.x(grid.positions()), x=x, y=x * 0, z=x * 0), x)
if __name__ == '__main__': nlay = 4 # number of layers lam = 200. # (initial) regularization parameter errPerc = 3. # relative error of 3 percent ab2 = np.logspace(-1, 2, 50) # AB/2 distance (current electrodes) mn2 = ab2 / 3. # MN/2 distance (potential electrodes) f = pg.DC1dModelling(nlay, ab2, mn2) synres = [100., 500., 20., 800.] # synthetic resistivity synthk = [0.5, 3.5, 6.] # synthetic thickness (nlay-th layer is infinite) rhoa = f(synthk + synres) rhoa = rhoa * (pg.randn(len(rhoa)) * errPerc / 100. + 1.) transLog = pg.RTransLog() inv = LSQRInversion(rhoa, f, transLog, transLog, True) inv.setRelativeError(errPerc / 100) startModel = pg.cat( pg.Vector(nlay - 1, 5), pg.Vector(nlay, pg.median(rhoa))) print(inv.response()) inv.setModel(startModel) inv.setMarquardtScheme() inv.setLambda(1000) G = pg.RMatrix(rows=1, cols=len(startModel)) for i in range(3): G[0][i] = 1 c = pg.Vector(1, pg.sum(synthk)) inv.setParameterConstraints(G, c, 100) # print("Start", inv.chi2(), inv.relrms(), pg.sum(inv.model()(0, nlay-1))) if 0: for i in range(10): inv.oneStep() print(i, inv.chi2(), inv.relrms(), pg.sum(inv.model()(0, nlay - 1)))
def fillEmptyToCellArray(mesh, vals, slope=True): """ Prolongate empty cell values to complete cell attributes. It is possible to have zero values that are filled with appropriate attributes. This function tries to fill empty values successively by prolongation of the non-zeros. Parameters ---------- mesh : :gimliapi:`GIMLI::Mesh` For each cell of mesh a value will be returned. vals : array Array of size cellCount(). Returns ------- atts : array Array of length mesh.cellCount() Examples -------- >>> import pygimli as pg >>> import numpy as np >>> import matplotlib.pyplot as plt >>> >>> # Create a mesh with 3 layers and an outer region for extrapolation >>> layers = pg.meshtools.createWorld([0,-50],[100,0], layers=[-15,-35]) >>> inner = pg.meshtools.createMesh(layers, area=3) >>> mesh = pg.meshtools.appendTriangleBoundary(inner, xbound=120, ybound=50, ... area=20, marker=0) >>> >>> # Create data for the inner region only >>> layer_vals = [20,30,50] >>> data = np.array(layer_vals)[inner.cellMarkers() - 1] >>> >>> # The following fails since len(data) != mesh.cellCount(), extrapolate >>> # pg.show(mesh, data) >>> >>> # Create data vector, where zeros fill the outer region >>> data_with_outer = np.array([0] + layer_vals)[mesh.cellMarkers()] >>> >>> # Actual extrapolation >>> extrapolated_data = pg.meshtools.fillEmptyToCellArray(mesh, ... data_with_outer, slope=False) >>> extrapolated_data_with_slope = pg.meshtools.fillEmptyToCellArray(mesh, ... data_with_outer, slope=True) >>> >>> # Visualization >>> fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(10,8), sharey=True) >>> _ = pg.show(mesh, data_with_outer, ax=ax1, cMin=0) >>> _ = pg.show(mesh, extrapolated_data, ax=ax2, cMin=0) >>> _ = pg.show(mesh, extrapolated_data_with_slope, ax=ax3, cMin=0) >>> _ = ax1.set_title("Original data") >>> _ = ax2.set_title("Extrapolated with slope=False") >>> _ = ax3.set_title("Extrapolated with slope=True") """ # atts = pg.Vector(mesh.cellCount(), 0.0) # not used # oldAtts = mesh.cellAttributes() # not used mesh.setCellAttributes(vals) mesh.createNeighborInfos() # std::vector< Cell * > # empties = [] if slope: # search all cells with empty neighbors ids = pg.find(mesh.cellAttributes() != 0.0) for c in mesh.cells(ids): for i in range(c.neighborCellCount()): nc = c.neighborCell(i) if nc: if nc.attribute() == 0.0: # c.setAttribute(99999) b = pg.core.findCommonBoundary(c, nc) # search along a slope pos = b.center() - b.norm() * 1000. sf = pg.Vector() startCell = c while startCell: startCell.shape().isInside(pos, sf, False) nextC = startCell.neighborCell(sf) if nextC: if nextC.attribute() == 0.0: nextC.setAttribute(c.attribute()) else: break startCell = nextC vals = mesh.cellAttributes() mesh.prolongateEmptyCellsValues(vals, background=-9e99) mesh.setCellAttributes(vals) return vals
# stream lines. By default, the drawStreams method draws one segment of a # stream line per cell of the mesh. This can be a little confusing for dense # meshes so we can give a second (coarse) mesh as a new cell base to draw the # streams. If `drawStreams` gets scalar data, the gradients will be calculated. gridCoarse = pg.createGrid(x=np.linspace(-10.0, 10.0, 20), y=np.linspace(-15.0, .0, 20)) drawStreams(ax, mesh, u, coarseMesh=gridCoarse, color='Black') ############################################################################### # We know the exact solution so we can compare it to the numerical results. # Unfortunately, the point source singularity does not allow a good integration # measure for the accuracy of the resulting field so we just look for the # differences. # uAna = pg.Vector( list( map(lambda p__: uAnalytical(p__, sourcePosA, k, sigma), mesh.positions()))) uAna -= pg.Vector( list( map(lambda p__: uAnalytical(p__, sourcePosB, k, sigma), mesh.positions()))) ax = pg.show(mesh, data=pg.abs(uAna - u), cMap="Reds", orientation='horizontal', label='|$u_{exact}$ -$u$|', logScale=True, cMin=1e-7, cMax=1e-1, contourLines=False,
def test_RVector(self): """ implemented in custom_rvalue.cpp""" a = pg.Vector(10) self.assertEqual(a.size(), 10.0) self.assertEqual(sum(a), 0.0)
def drawStreamLine_(ax, mesh, c, data, dataMesh=None, linewidth=1.0, dropTol=0.0, **kwargs): """Draw a single streamline. Draw a single streamline into a given mesh for given data stating at the center of cell c. The Streamline will be enlarged until she reached a cell that already contains a streamline. TODO linewidth and color depends on absolute velocity or background color saturation Parameters ---------- ax : matplotlib.ax ax to draw into mesh : :gimliapi:`GIMLI::Mesh` 2d mesh c : :gimliapi:`GIMLI::Cell` Start point is c.center() data : iterable float | [float, float] If data is an array (per cell or node) gradients are calculated otherwise the data will be interpreted as vector field per nodes or cell centers. dataMesh : :gimliapi:`GIMLI::Mesh` [None] Optional mesh for the data. If you want high resolution data to plot on coarse draw mesh. linewidth : float [1.0] Streamline linewidth dropTol : float [0.0] Don't draw stream lines with velocity lower than drop tolerance. Keyword Arguments ----------------- **kwargs arrowSize: int Size of the arrow's head. arrowColor: str Color of the arrow's head. Additional kwargs are being forwarded to mpl.LineCollection, mpl.Polygon """ x, y, v = streamline(mesh, data, startCoord=c.center(), dLengthSteps=5, dataMesh=dataMesh, maxSteps=10000, verbose=False, coords=[0, 1]) if 'color' not in kwargs: kwargs['color'] = 'black' arrowSize = kwargs.pop('arrowSize', 12) arrowColor = kwargs.pop('arrowColor', 'black') lines = None if len(x) > 2: points = np.array([x, y]).T.reshape(-1, 1, 2) segments = np.concatenate([points[:-1], points[1:]], axis=1) lwidths = pg.Vector(len(v), linewidth) lwidths[pg.find(pg.Vector(v) < dropTol)] = 0.0 lines = mpl.collections.LineCollection(segments, linewidths=lwidths, **kwargs) ax.add_collection(lines) # probably the limits are wrong without plot call # lines = ax.plot(x, y, **kwargs) # updateAxes_(ax, lines) # ax.plot(x, y, '.-', color='black', **kwargs) if len(x) > 3: xmid = int(len(x) / 2) ymid = int(len(y) / 2) dx = x[xmid + 1] - x[xmid] dy = y[ymid + 1] - y[ymid] c = mesh.findCell([x[xmid], y[ymid]]) if v[xmid] > dropTol: absArrowSize = True if absArrowSize: ax.annotate( '', xytext=(x[xmid] - dx, y[ymid] - dy), xy=(x[xmid], y[ymid]), arrowprops=dict(arrowstyle="-|>", color=arrowColor), size=arrowSize, **kwargs, ) else: ax.arrow(x[xmid], y[ymid], dx, dy, shape='full', lw=0, length_includes_head=True, fc=arrowColor, head_width=.35, **kwargs) # dx90 = -dy # dy90 = dx # aLen = 3 # aWid = 1 # xy = list(zip([x[xmid] + dx90*aWid, x[xmid] + dx*aLen, # x[xmid] - dx90*aWid], # [y[ymid] + dy90*aWid, y[ymid] + dy*aLen, # y[ymid] - dy90*aWid])) # arrow = mpl.patches.Polygon(xy, ls=None, lw=0, closed=True, # **kwargs) #ax.add_patch(arrow) return lines
def oneStep(self): """One inversion step.""" model = self.model() if len(self.response()) != len(self.data()): self.setResponse(self.forwardOperator().response(model)) self.forwardOperator().createJacobian(model) self.checkTransFunctions() tD = self.transData() tM = self.transModel() nData = self.data().size() # nModel = len(model) self.A = pg.matrix.BlockMatrix( ) # to be filled with scaled J and C matrices # part 1: data part J = self.forwardOperator().jacobian() # self.dScale = 1.0 / pg.log(self.error()+1.0) self.dScale = 1.0 / (tD.deriv(self.data()) * self.error() * self.data()) self.leftJ = tD.deriv(self.response()) * self.dScale # self.leftJ = self.dScale / tD.deriv(self.response()) self.rightJ = 1.0 / tM.deriv(model) self.JJ = pg.matrix.MultLeftRightMatrix(J, self.leftJ, self.rightJ) # self.A.addMatrix(self.JJ, 0, 0) self.mat1 = self.A.addMatrix(self.JJ) self.A.addMatrixEntry(self.mat1, 0, 0) # part 2: normal constraints self.checkConstraints() self.C = self.forwardOperator().constraints() self.leftC = pg.Vector(self.C.rows(), 1.0) self.rightC = pg.Vector(self.C.cols(), 1.0) self.CC = pg.matrix.MultLeftRightMatrix(self.C, self.leftC, self.rightC) self.mat2 = self.A.addMatrix(self.CC) lam = self.getLambda() self.A.addMatrixEntry(self.mat2, nData, 0, sqrt(lam)) # % part 3: parameter constraints if self.G is not None: self.rightG = 1.0 / tM.deriv(model) self.GG = pg.matrix.MultRightMatrix(self.G, self.rightG) self.mat3 = self.A.addMatrix(self.GG) nConst = self.C.rows() self.A.addMatrixEntry(self.mat3, nData + nConst, 0, sqrt(self.my)) self.A.recalcMatrixSize() # right-hand side vector deltaD = (tD.fwd(self.data()) - tD.fwd(self.response())) * self.dScale deltaC = -(self.CC * tM.fwd(model) * sqrt(lam)) deltaC *= 1.0 - self.localRegularization() # operates on DeltaM only rhs = pg.cat(deltaD, deltaC) if self.G is not None: deltaG = (self.c - self.G * model) * sqrt(self.my) rhs = pg.cat(pg.cat(deltaD, deltaC), deltaG) dM = lsqr(self.A, rhs) tau, responseLS = self.lineSearchInter(dM) if tau < 0.1: # did not work out tau = self.lineSearchQuad(dM, responseLS) if tau > 0.9: # save time and take 1 tau = 1.0 else: self.forwardOperator().response(self.model()) if tau < 0.1: # still not working tau = 0.1 # tra a small value self.setModel(tM.update(self.model(), dM * tau)) # print("model", min(self.model()), max(self.model())) if tau == 1.0: self.setResponse(responseLS) else: # compute new response self.setResponse(self.forwardOperator().response(self.model())) self.setLambda(self.getLambda() * self.lambdaFactor()) return True
def drawModel(ax, mesh, data=None, tri=False, rasterized=False, cMin=None, cMax=None, logScale=False, xlabel=None, ylabel=None, fitView=True, verbose=False, **kwargs): """Draw a 2d mesh and color the cell by the data. Parameters ---------- ax : mpl axis instance, optional Axis instance where the mesh is plotted (default is current axis). mesh : :gimliapi:`GIMLI::Mesh` The plotted mesh to browse through. data : array, optional Data to draw. Should either equal numbers of cells or nodes of the corresponding `mesh`. tri : boolean, optional use MPL tripcolor (experimental) rasterized : boolean, optional Rasterize mesh patches to reduce file size and avoid zooming artifacts in some PDF viewers. fitView : bool [True] Adjust ax limits to mesh bounding box. Keyword Arguments ----------------- **kwargs Additional kwargs forwarded to the draw functions and mpl methods, respectively. Returns ------- gci : matplotlib graphics object Examples -------- >>> import numpy as np >>> import matplotlib.pyplot as plt >>> import pygimli as pg >>> from pygimli.viewer.mpl import drawModel >>> n = np.linspace(0, -2, 11) >>> mesh = pg.createGrid(x=n, y=n) >>> mx = pg.x(mesh.cellCenter()) >>> my = pg.y(mesh.cellCenter()) >>> data = np.cos(1.5 * mx) * np.sin(1.5 * my) >>> fig, ax = plt.subplots() >>> drawModel(ax, mesh, data) <matplotlib.collections.PolyCollection object at ...> """ # deprecated .. remove me if 'cMap' in kwargs or 'cmap' in kwargs: pg.warn('cMap|cmap argument is deprecated for draw functions. ' + 'Please use show or customize a colorbar.') # deprecated .. remove me if mesh.nodeCount() == 0: pg.error("drawModel: The mesh is empty.", mesh) if tri or 'shading' in kwargs: gci = drawField(ax, mesh, data, cMin=cMin, cMax=cMax, logScale=logScale, **kwargs) else: gci = pg.viewer.mpl.createMeshPatches(ax, mesh, rasterized=rasterized, verbose=verbose) ax.add_collection(gci) if data is None: data = pg.Vector(mesh.cellCount()) if len(data) != mesh.cellCount(): print(data, mesh) pg.info("drawModel have wrong data length .. " + " indexing data from cellMarkers()") viewdata = data[mesh.cellMarkers()] else: viewdata = data pg.viewer.mpl.setMappableData(gci, viewdata, cMin=cMin, cMax=cMax, logScale=logScale, **kwargs) gci.set_antialiased(True) gci.set_linewidths(0.1) gci.set_edgecolors("face") if xlabel is not None: ax.set_xlabel(xlabel) if ylabel is not None: ax.set_ylabel(ylabel) if fitView is True: ax.autoscale(enable=True, axis='both', tight=True) ax.set_aspect('equal') updateAxes_(ax) return gci
def mult(self, b): ret = pg.Vector(self.rows()) print("TestMatrix::mult") return ret
# based on LAPACK (numpy.linalg). The inverse square root is defined by # # .. math:: # # \textbf{C}_\text{M}^{-0.5} = \textbf{Q}\textbf{D}^{-0.5}\textbf{Q}^{T} # # In order to avoid a matrix inverse (square root), a special matrix is derived # that does the decomposition and stores the eigenvectors and eigenvalues values. # A multiplication is done by multiplying with Q and scaling with the diagonal D. # This matrix is implemented in the :mod:`pygimli.matrix` module # by the class :py:mod:`pg.matrix.Cm05Matrix` Cm05 = pg.matrix.Cm05Matrix(CM) # %% # However, this matrix does not return a zero vector for a constant vector out = Cm05 * pg.Vector(mesh.cellCount(), 1.0) print(min(out), max(out)) # %% # as desired for a roughness operator. Therefore, an additional matrix called # :py:mod:`pg.matrix.GeostatisticalConstraintsMatrix` # was implemented where this spur is corrected for. # It is, like the correlation matrix, created by a mesh, a list of correlation # lengths I, a dip angle# that distorts the x/y plane and a strike angle # towards the third direction. # C = pg.matrix.GeostatisticConstraintsMatrix(mesh=mesh, I=5) # %% # In order to extract a certain column, we generate a vector with a single 1 vec = pg.Vector(mesh.cellCount())
def response(self, model): print("TestModelling::response") res = pg.Vector(1, 1.0) return res
S[N, N+1] += -aW S[N, N] += aW rhs[0] += uDir[0] rhs[N+1] += uDir[1] return S, rhs x = np.linspace(.0, 1.0, 11) dx = x[1]-x[0] grid = pg.createGrid(x=x) N = grid.cellCount() # force vector per cell f = pg.Vector(grid.cellCount(), 0.0) # diffusions coefficient a = pg.Vector(grid.cellCount(), 2.1) # velocity per cell [x-direction] v = pg.Vector(grid.cellCount(), 20.1) print('Peclet-number:', v[0]/(a[0] / dx)) ud0=0 udN=1 def uAna(x, L, v, D): """ u = \frac{1 - \e(-v_x x / D)}{1 - \e(-v_x L / D)} Check for -v -- herleiten
def createDefaultStartModel(self, models): sm = pg.Vector() for i, f in enumerate(self._fops1D): sm = pg.cat(sm, f.createDefaultStartModel(models[i])) return sm
def createStartModel(self, dataVals): return pg.Vector([1.0, 3.0])