def _testP2_(mesh, show=False): """ Laplace u = 2 solves u = x² for u(r=0)=0 and u(r=1)=1 Test for u == exact x² for P2 base functions """ meshp2 = mesh.createP2() u = pg.solve(meshp2, f=-2, bc={'Dirichlet': [[1, 0], [2, 1]]}) # find test pos different from node pos meshTests = mesh.createH2() meshTests = meshTests.createH2() c = [c.center() for c in meshTests.cells()] startPos = meshTests.node(0).pos() if mesh.dim() == 2: c = [b.center() for b in meshTests.boundaries(meshTests.boundaryMarkers()==4)] c.sort(key=lambda c_: c_.distance(startPos)) ui = pg.interpolate(meshp2, u, c) xi = pg.utils.cumDist(c) + startPos.distance(c[0]) if show: pg.plt.plot(xi, ui) pg.plt.plot(xi, xi**2) pg.wait() np.testing.assert_allclose(ui, xi**2)
def VESManagerApp(): """Call VESManager as console app""" parser = VESManager.createArgParser(dataSuffix='ves') options = parser.parse_args() verbose = not options.quiet if verbose: print("VES Manager console application.") print(options._get_kwargs()) mgr = VESManager(verbose=verbose, debug=pg.debug()) ab2, mn2, ra, err = mgr.loadData(options.dataFileName) mgr.showData(ra, err) mgr.invert( ra, err, ab2, mn2, maxIter=options.maxIter, lam=options.lam, ) mgr.showResultAndFit() pg.wait()
def waitOnExit(): backend = matplotlib.get_backend() if not 'inline' in backend: if 'Qt' in backend or 'Wx' in backend: if len(plt.get_fignums()) > 0: pg.info('Showing pending widgets on exit. ' 'Close all figures or Ctrl-C to quit the programm') pg.wait()
def tapeMeasureToCoordinates(tape, pos): """Interpolate 2D tape measured topography to 2D Cartesian coordinates. Tape and pos value are expected to be sorted along distance to the orign. TODO optional smooth curve with harmfit Parameters ---------- tape : [[x,z]] | [RVector3] | R3Vector List of tape measured topography points with measured distance (x) from origin and height (z) pos : iterable Query positions along the tape measured profile Returns ------- res : ndarray(N, 2) Same as pos but with interpolated height values. The Distance between pos points and res (along curve) points remains. Examples -------- >>> # no need to import matplotlib. pygimli's show does >>> import numpy as np >>> import pygimli as pg >>> import pygimli.meshtools as mt >>> elec = np.arange(11.) >>> topo = np.array([[0., 0.], [3., 2.], [4., 2.], [6., 1.], [10., 1.]]) >>> _= pg.plt.plot(topo[:,0], topo[:,1]) >>> p = mt.tapeMeasureToCoordinates(topo, elec) >>> pg.plt.gca().plot(p[:,0], p[:,1], 'o') #doctest: +ELLIPSIS [...] >>> pg.plt.gca().set_aspect(1) >>> pg.wait() """ if isinstance(tape, pg.R3Vector) or isinstance(tape, pg.stdVectorRVector3): xTape = pg.x(tape) zTape = pg.z(tape) else: xTape = tape[:, 0] zTape = tape[:, 1] t = pg.utils.cumDist(pos) # print(t) tTape = pg.utils.cumDist(tape) xt = np.interp(t, tTape, xTape) zt = np.interp(t, tTape, zTape) pg.plt.plot(xTape, zTape) pg.plt.plot(xt, zt, 'o') pg.wait() return np.vstack([xt, zt]).T
def showModel(outPath): # geom = pg.load('synth/' + 'synthGeom.bms') # pd = pg.load(outPath + '/paraDomain.bms') paraMesh = pg.load(outPath + '/paraMesh.bms') model = pg.load(outPath + "/model.vector") fopMesh = pg.load(outPath + "fopMesh.bms") fopModel = pg.load(outPath + "fopModel.vector") allModel = np.zeros(len(model) + 2) allModel[2:] = model # allModel[0] = fopModel[fopMesh.findCellByMarker( # pg.MARKER_FIXEDVALUE_REGION - 0)[0].id()] allModel[1] = fopModel[fopMesh.findCellByMarker( pg.MARKER_FIXEDVALUE_REGION - 1)[0].id()] ax = savefig(paraMesh, None, allModel[paraMesh.cellMarkers()], 'Hydraulic conductivity $K$ in m$/$s', cMin=1e-5, cMax=1e-2, nLevs=4, cMap='viridis') pg.wait() pg.show(fopMesh, ax=ax, linewidth=0.2) paraMesh.createNeighborInfos() bs = [] for b in paraMesh.boundaries(): if b.leftCell() and b.rightCell(): if b.leftCell().marker() > 1 or b.rightCell().marker() > 1: bs.append(b) pg.viewer.mpl.drawSelectedMeshBoundaries(ax, bs, color=(0.0, 0.0, 0.0, 1.0), linewidth=1.0) pg.viewer.mpl.saveFigure(ax.figure, 'hydrInversionModel') print('Done!') pg.wait()
def _test_(mesh, show=False): vTest = 0.1 u = pg.solve(mesh, a=1, f=0, bc={'Node': [mesh.findNearestNode([0.0, 0.0]), 0.], 'Neumann': [[1, -vTest], [2, vTest]]}, verbose=0) if show: if mesh.dim() == 1: pg.plt.plot(pg.x(mesh), u) elif mesh.dim() == 2: pg.show(grid, pg.abs(v)) pg.show(grid, v, showMesh=1) pg.wait() v = pg.solver.grad(mesh, u) #print("|v|:", min(pg.abs(v)), max(pg.abs(v)), pg.mean(pg.abs(v))) np.testing.assert_allclose(pg.abs(v), np.ones(mesh.cellCount())*vTest) return v
def _testP1_(mesh, show=False): """ Laplace u = 0 solves u = x for u(r=0)=0 and u(r=1)=1 Test for u == exact x for P1 base functions """ u = pg.solve(mesh, a=1, b=0, f=0, bc={'Dirichlet': [[1, 0], [2, 1]]}) if show: if mesh.dim()==1: pg.plt.plot(pg.x(mesh), u) pg.wait() elif mesh.dim()==2: pg.show(mesh, u, label='u') pg.wait() xMin = mesh.xmin() xSpan = (mesh.xmax() - xMin) np.testing.assert_allclose(u, (pg.x(mesh)-xMin)/ xSpan) return u
def VESManagerApp(): """Call VESManager as console app""" parser = VESManager.createArgParser(dataSuffix='ves') options = parser.parse_args() verbose = not options.quiet if verbose: print("VES Manager console application.") print(options._get_kwargs()) mgr = VESManager(verbose=verbose, debug=pg.debug()) ab2, mn2, ra, err = mgr.loadData(options.dataFileName) mgr.showData(ra, err) mgr.invert(ra, err, ab2, mn2, maxIter=options.maxIter, lam=options.lam, ) mgr.showResultAndFit() pg.wait()
def showModel(outPath): # geom = pg.load('synth/' + 'synthGeom.bms') # pd = pg.load(outPath + '/paraDomain.bms') paraMesh = pg.load(outPath + '/paraMesh.bms') model = pg.load(outPath + "/model.vector") fopMesh = pg.load(outPath + "fopMesh.bms") fopModel = pg.load(outPath + "fopModel.vector") allModel = np.zeros(len(model)+2) allModel[2:] = model # allModel[0] = fopModel[fopMesh.findCellByMarker( # pg.MARKER_FIXEDVALUE_REGION - 0)[0].id()] allModel[1] = fopModel[fopMesh.findCellByMarker( pg.MARKER_FIXEDVALUE_REGION - 1)[0].id()] ax = savefig(paraMesh, None, allModel[paraMesh.cellMarkers()], 'Hydraulic conductivity $K$ in m$/$s', cMin=1e-5, cMax=1e-2, nLevs=4, cMap='viridis') pg.wait() pg.show(fopMesh, ax=ax, linewidth=0.2) paraMesh.createNeighbourInfos() bs = [] for b in paraMesh.boundaries(): if b.leftCell() and b.rightCell(): if b.leftCell().marker() > 1 or b.rightCell().marker() > 1: bs.append(b) pg.mplviewer.drawSelectedMeshBoundaries( ax, bs, color=(0.0, 0.0, 0.0, 1.0), linewidth=1.0) pg.mplviewer.saveFigure(ax.figure, 'hydrInversionModel') print('Done!') pg.wait()
def test_VESManager(showProgress=False): """ run from console with: python -c 'import pygimli.physics.ert.ves as pg; pg.test_VESManager(1)' """ thicks = [2., 10.] res = [100., 5., 30] phi = [0., 20., 0.] # model fails thicks = [2., 6., 10.] res = [100., 500., 20., 800.] phi = [0., 20., 50., 0] synthModel = pg.cat(thicks, res) ab2 = np.logspace(np.log10(1.5), np.log10(100.), 25) mgr = VESManager(verbose=True, debug=False) mgr.fop.setRegionProperties(0, limits=[0.5, 200], trans='log') ra, err = mgr.simulate(synthModel, ab2=ab2, mn2=1.0, noiseLevel=0.01) mgr.exportData('synth.ves', ra, err) mgr.invert(ra, err, nLayer=4, lam=100, showProgress=showProgress) pg.wait() ### Test -- reinit with new parameter count mgr.invert(ra, err, nLayer=3, showProgress=showProgress) #np.testing.assert_array_less(mgr.inv.inv.chi2(), 1) ### Test -- reinit with new data basis ab2 = np.logspace(np.log10(1.5), np.log10(50.), 10) ra, err = mgr.simulate(synthModel, ab2=ab2, mn2=1.0, noiseLevel=0.01) mgr2 = VESManager(verbose=False, debug=False) mgr2.invert(ra, err, nLayer=3, ab2=ab2, mn2=1.0, showProgress=showProgress) #np.testing.assert_array_less(mgr2.inv.inv.chi2(), 1) pg.wait() ### Test -- reinit with complex resistivies mgr.complex = True synthModel = pg.cat(synthModel, phi) ra, err = mgr.simulate(synthModel, ab2=ab2, mn2=1.0, noiseLevel=0.01) mgr.exportData('synthc.ves', ra, err) mgr.invert(ra, err, showProgress=showProgress) np.testing.assert_array_less(mgr.inv.inv.chi2(), 1) if showProgress: print("test done"); pg.wait()
circle(boundary_center.x(), boundary_center.y(), "m.boundary(%d).center()" % bid, c="red") # Mark boundary together with left and right cell bid = 17 b = m.boundaries()[bid] # equivalent to mesh.boundary(17) n1 = b.allNodes()[0] n2 = b.allNodes()[1] ax.plot([n1.x(), n2.x()], [n1.y(), n2.y()], "r-", lw=3, zorder=10) ax.annotate('b = mesh.boundary(%d)' % bid, xy=(b.center().x(), b.center().y()), xycoords='data', xytext=(8, 40), textcoords='offset points', weight='bold', color="red", arrowprops=dict(arrowstyle='->', connectionstyle="arc", color="red")) circle(n1.x(), n1.y(), "b.allNodes()[0].x()\nb.allNodes()[0].y()", radius=0.1, c="green") # Mark neighboring cells left = b.leftCell() right = b.rightCell() circle(left.center().x(), left.center().y(), "b.leftCell().center()", c="blue") circle(right.center().x(), right.center().y(), "b.rightCell().center()", c="blue") ax.text(3.0, -0.5, "Made with matplotlib & pyGIMLi", fontsize=10, ha="right", color='.5') fig.tight_layout(pad=5.7) pg.wait()
for i in range(poly.nodeCount() - 1): poly.createEdge(poly.node(i), poly.node(i + 1)) poly.createEdge(poly.node(poly.nodeCount() - 1), poly.node(0)) ############################################################################### # We call the TriangleWrapper to generate the mesh and set the x values as the # data for a color transition. tri = pg.TriangleWrapper(poly) mesh = pg.Mesh(2) tri.setSwitches('-pzeAfa5q33') tri.generate(mesh) data = [] for cell in mesh.cells(): data.append(cell.center().x()) ############################################################################### # Last, we create a BERT caption, visualize the mesh and fine-tune the figure. fig, ax = plt.subplots(figsize=(4, 3)) ax.axis('off') offset = -10 t = ax.text(1.7, offset, 'BERT', fontsize=37, fontweight='bold') pg.show(mesh, data, ax=ax, cmap='RdBu', logScale=False, showLater=True) pg.show(mesh, ax=ax) ax.set_ylim(offset, mesh.ymax()) pg.wait()
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.RMatrix(1, mesh.cellCount()) rB[0] = pg.solver.parseArgToArray(rFluid, mesh.cellCount(), mesh) elif isinstance(rFluid, pg.RVector): rB = pg.RMatrix(1, len(rFluid)) rB[0] = pg.solver.parseArgToArray(rFluid, mesh.cellCount(), mesh) elif hasattr(rFluid, 'ndim') and rFluid.ndim == 1: rB = pg.RMatrix(1, len(rFluid)) rB[0] = pg.solver.parseArgToArray(rFluid, mesh.cellCount(), mesh) elif hasattr(rFluid, 'ndim') and rFluid.ndim == 2: rB = pg.RMatrix(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.RMatrix(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.RMatrix(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
def _test_ConvectionAdvection(): """Test against a reference solution. taken from https://www.ctcms.nist.gov/fipy/examples/flow/generated/examples.flow.stokesCavity.html """ N = 21 # 21 reference maxIter = 11 # 11 reference Nx = N Ny = N x = np.linspace(-1.0, 1.0, Nx + 1) y = np.linspace(-1.0, 1.0, Ny + 1) grid = pg.createGrid(x=x, y=y) a = pg.Vector(grid.cellCount(), 1.0) b7 = grid.findBoundaryByMarker(1)[0] for b in grid.findBoundaryByMarker(1): if b.center()[1] < b.center()[1]: b7 = b b7.setMarker(7) swatch = pg.core.Stopwatch(True) # velBoundary = [[1, [0.0, 0.0]], # [2, [0.0, 0.0]], # [3, [1.0, 0.0]], # [4, [0.0, 0.0]], # [7, [0.0, 0.0]]] velBoundaryX = { 'Dirichlet': { '1,2,4,7': 0.0, 3: 1.0, } } velBoundaryY = { 'Dirichlet': { '1,2,4,7': 0.0, 3: 0.0, } } # velBoundaryX = {'Dirichlet':{'1,2,7': 0.0, # 3: 1.0,}} # velBoundaryY = {'Dirichlet':{'3,4,7': 0.0}} preBoundary = {'Dirichlet': {7: 0.0}} vel, pres, pCNorm, divVNorm = __solveStokes(grid, a, [velBoundaryX, velBoundaryY], preBoundary, maxIter=maxIter, verbose=1) print("time", len(pCNorm), swatch.duration(True)) referenceSolutionDivV = 0.029187181920161752 #fipy print("divNorm: ", divVNorm[-1]) print("to reference: ", divVNorm[-1] - referenceSolutionDivV) np.testing.assert_approx_equal(divVNorm[-1], referenceSolutionDivV, significant=8) fig = pg.plt.figure() ax1 = fig.add_subplot(1, 3, 1) ax2 = fig.add_subplot(1, 3, 2) ax3 = fig.add_subplot(1, 3, 3) show(grid, data=pg.meshtools.cellDataToNodeData(grid, pres), label='Pressure', cMap='RdBu', ax=ax1) show(grid, data=pg.core.logTransDropTol( pg.meshtools.cellDataToNodeData(grid, vel[:, 0]), 1e-2), label='$v_x$', ax=ax2) show(grid, data=pg.core.logTransDropTol( pg.meshtools.cellDataToNodeData(grid, vel[:, 1]), 1e-2), label='$v_y$', ax=ax3) show(grid, data=vel, ax=ax1, showMesh=True) pg.plt.figure() pg.plt.semilogy(pCNorm, label='norm') pg.plt.legend() pg.wait()
def _test_(mesh, p2=False, show=False): """ \Laplace u = 0 x = [0, -1], y, z int_0^1 u = 0 du/dn = 1 (xMin) (inflow on -x) du/dn = -1 (xMax) (outflow on +x) du/dn = 0 (rest) u = 0.5 -x linear solution, i.e., exact with p1 du/dn = -1 (xMin) (outflow -x) du/dn = -1 (xMax) (outflow +x) du/dn = 0 (rest) u = -1/6 + x -x² quadratic solution, i.e., exact with p2 """ uExact = lambda x, a, b, c: a + b * x + c * x**2 bc = {'Neumann': {1: 1.0, 2: -1.0}} uE = uExact(pg.x(mesh), 0.5, -1.0, 0.0) if p2 is True: mesh = mesh.createP2() bc['Neumann'][1] = -1.0 uE = uExact(pg.x(mesh), -1 / 6, 1.0, -1.0) u = pg.solve(mesh, a=1, f=0, bc=bc, verbose=0) v = pg.solver.grad(mesh, u) if show: if mesh.dim() == 1: idx = np.argsort(pg.x(mesh)) fig, ax = pg.plt.subplots() ax.plot(pg.x(mesh)[idx], uE[idx], label='exact') ax.plot(pg.x(mesh)[idx], u[idx], 'o', label='FEM') model, response = pg.frameworks.fit(uExact, u[idx], x=pg.x(mesh)[idx]) print(model) ax.plot(pg.x(mesh)[idx], response, 'x', label='FIT') ax.grid(True) ax.legend() elif mesh.dim() == 2: pg.show(mesh, u, label='u') ax, _ = pg.show(mesh, pg.abs(v), label='abs(grad(u))') pg.show(mesh, v, showMesh=1, ax=ax) pg.info("int Domain:", pg.solver.intDomain(u, mesh)) pg.info("int Domain:", pg.solver.intDomain([1.0] * mesh.nodeCount(), mesh), sum(mesh.cellSizes())) pg.wait() ## test du/dn of solution and compare with Neumann BC for m, val in bc['Neumann'].items(): for b in mesh.boundaries(mesh.boundaryMarkers() == m): ## for non Tailor Hood Elements, the gradient is only # known at the cell center so the accuracy for the # gradient depends on the distance boundary to cell # center. Accuracy = du/dx(dx) = 1-2x = 2 * dx c = b.leftCell() dx = c.center().dist(b.center()) dudn = b.norm(c).dot(v[c.id()]) if p2: np.testing.assert_allclose(dudn, val, atol=2 * dx) #print(dudn, val) else: np.testing.assert_allclose(dudn, val) np.testing.assert_allclose(pg.solver.intDomain([1.0]*\ mesh.nodeCount(), mesh), sum(mesh.cellSizes())) np.testing.assert_allclose(pg.solver.intDomain(u, mesh), 0.0, atol=1e-8) np.testing.assert_allclose(np.linalg.norm(u - uE), 0.0, atol=1e-8) return v
def showSynthData(synthPath): geom = pg.load(synthPath + 'synthGeom.bms') mesh = pg.load(synthPath + 'synth.bms') k = np.load(synthPath + 'synthK.npy') vel = np.load(synthPath + 'synthVel.npy') sat = np.load(synthPath + 'synthSat.npy') scheme = pg.DataContainer(synthPath + 'synth.shm', 'a b m n') # rhoaR = np.load(synthPath + 'synthRhoaRatio.npy') # rhoa = np.load(synthPath + 'synthRhoa.npy') row = 3 col = 2 # START model perm + input savefig(mesh, geom, k, 'Hydraulic conductivity $K$ in m$/$s', out='hydrConductModel', cMin=1e-5, cMax=1e-2, nLevs=4, cmap='viridis') # START velocity axVel, _ = pg.show(mesh, np.sqrt(vel[0]**2 + vel[1]**2), logScale=0, colorBar=1, pad=0.55, label='Velocity $|v|$ in m$/$s', hold=1) meshC = pg.meshtools.createMesh(geom, quality=33, area=0.5, smooth=[1, 10]) pg.show(mesh, data=vel, ax=axVel, coarseMesh=meshC, color='black', linewidth=0.5, dropTol=1e-6) pg.show(geom, ax=axVel, fillRegion=False) saveAxes(axVel, 'hydrVelocity', adjust=True) # START Saturation axs = plt.subplots(row, col, sharex=True, sharey=True, figsize=(10.*0.65, 7.25*0.65))[1].flatten() satScale = 0.001 for i, a in enumerate(axs): savefig(mesh, geom, sat[i*len(sat)/(len(axs))+1] * satScale, # /mesh.cellSizes(), label=None, out=None, cMin=0, cMax=2.5, ax=a, adjust=True) pg.mplviewer.drawSensors(a, scheme.sensorPositions(), diam=0.15, color='green') add_inner_title(a, "t = %d days" % days[i], 3, color="w") if i < (row-1)*col: a.set_xlabel('') if i % col: a.set_ylabel('') a.set_ylim([-16, 0]) pg.mplviewer.saveFigure(axs[0].figure, "hydrSaturation") pg.mplviewer.createColorBarOnly(cMin=0, cMax=2.5, logScale=False, cMap='Spectral_r', nLevs=5, label=r'Concentration $c$ in g$/$l', orientation='horizontal', savefig='hydrSaturationCbar') # END Saturation pg.wait()
def showSynthData(synthPath): geom = pg.load(synthPath + 'synthGeom.bms') mesh = pg.load(synthPath + 'synth.bms') k = np.load(synthPath + 'synthK.npy') vel = np.load(synthPath + 'synthVel.npy') sat = np.load(synthPath + 'synthSat.npy') scheme = pg.DataContainer(synthPath + 'synth.shm', 'a b m n') # rhoaR = np.load(synthPath + 'synthRhoaRatio.npy') # rhoa = np.load(synthPath + 'synthRhoa.npy') row = 3 col = 2 # START model perm + input savefig(mesh, geom, k, 'Hydraulic conductivity $K$ in m$/$s', out='hydrConductModel', cMin=1e-5, cMax=1e-2, nLevs=4, cmap='viridis') # START velocity axVel, _ = pg.show(mesh, np.sqrt(vel[0]**2 + vel[1]**2), logScale=0, colorBar=1, pad=0.55, label='Velocity $|v|$ in m$/$s', hold=1) meshC = pg.meshtools.createMesh(geom, quality=33, area=0.5, smooth=[1, 10]) pg.show(mesh, data=vel, ax=axVel, coarseMesh=meshC, color='black', linewidth=0.5, dropTol=1e-6) pg.show(geom, ax=axVel, fillRegion=False) saveAxes(axVel, 'hydrVelocity', adjust=True) # START Saturation axs = plt.subplots(row, col, sharex=True, sharey=True, figsize=(10. * 0.65, 7.25 * 0.65))[1].flatten() satScale = 0.001 for i, a in enumerate(axs): savefig( mesh, geom, sat[i * len(sat) / (len(axs)) + 1] * satScale, # /mesh.cellSizes(), label=None, out=None, cMin=0, cMax=2.5, ax=a, adjust=True) pg.viewer.mpl.drawSensors(a, scheme.sensorPositions(), diam=0.15, color='green') add_inner_title(a, "t = %d days" % days[i], 3, color="w") if i < (row - 1) * col: a.set_xlabel('') if i % col: a.set_ylabel('') a.set_ylim([-16, 0]) pg.viewer.mpl.saveFigure(axs[0].figure, "hydrSaturation") pg.viewer.mpl.createColorBarOnly(cMin=0, cMax=2.5, logScale=False, cMap='Spectral_r', nLevs=5, label=r'Concentration $c$ in g$/$l', orientation='horizontal', savefig='hydrSaturationCbar') # END Saturation pg.wait()