def animate(data): i = data[0] imax = data[1] ui = data[2] mesh = data[3] print(i,'/', imax) global ax ax.clear() ax = show(mesh, data=ui, showLater=True, axes=ax, levels=np.linspace(0, 3, 16))[0] if min(ui) != max(ui): pass
f=pointSource, duB=neumannBC, userData={ 'sourcePos': sourcePosB, 'k': k }, verbose=True) # uAna = pg.RVector(map(lambda p__: uAnalytical(p__, sourcePosA, k), # grid.positions())) # uAna -= pg.RVector(map(lambda p__: uAnalytical(p__, sourcePosB, k), # grid.positions())) # err = (1.0 -u/uAna) * 100.0 # print "error min max", min(err), max(err) ax = show(grid, data=u, filled=True, colorBar=True, orientation='horizontal', label='Solution u')[0] show(grid, ax=ax) gridCoarse = pg.createGrid(x=np.linspace(-10.0, 10.0, 20), y=np.linspace(-15.0, .0, 20)) # Instead of the grid we want to add streamlines to the plot to show the # gradients of the solution. drawStreams(ax, grid, u, coarseMesh=gridCoarse, color='Black') pg.wait()
u -= solve(grid, a=sigma, b=-sigma * k*k, f=pointSource(grid, sourcePosB), bc={'Robin': robBC}, userData={'sourcePos': sourcePosB, 'k': k}, verbose=True) # uAna = pg.RVector(map(lambda p__: uAnalytical(p__, sourcePosA, k), # grid.positions())) # uAna -= pg.RVector(map(lambda p__: uAnalytical(p__, sourcePosB, k), # grid.positions())) # err = (1.0 -u/uAna) * 100.0 # print("error min max", min(err), max(err)) ax = show(grid, data=u, fillContour=True, colorBar=True, cMap="RdBu_r", orientation='horizontal', label='Solution u', nLevs=11, logScale=False, hold=True, showMesh=True)[0] # Additional to the image of the potential we want to see the current flow too. # The current flows along the gradient of our solution and can be plotted as # stream lines. On 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 basis to draw the # streams. If the drawStreams get 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, grid, u, coarseMesh=gridCoarse, color='Black') pg.wait()
#fig = plt.figure(figsize=(11,7), dpi=100) #ax1 = fig.add_subplot(1,3,1) #ax2 = fig.add_subplot(1,3,2) #ax3 = fig.add_subplot(1,3,3) grid=pg.createGrid(x,y) fig = plt.figure() ax1 = fig.add_subplot(1, 3, 1) ax2 = fig.add_subplot(1, 3, 2) ax3 = fig.add_subplot(1, 3, 3) pl = pg.logTransDropTol(np.array((p.T).flat), 1e-2) ul = pg.logTransDropTol(np.array((u.T).flat), 1e-2) vl = pg.logTransDropTol(np.array((v.T).flat), 1e-2) show(grid, pl, logScale=False, showLater=True, colorBar=True, axes=ax1, cmap='b2r') show(grid, ul, logScale=False, showLater=True, colorBar=True, axes=ax2) show(grid, vl, logScale=False, showLater=True, colorBar=True, axes=ax3) vel = np.vstack([np.array((u.T).flat), np.array((v.T).flat)]).T drawStreams(ax1, grid, vel) #im1 = ax1.contourf(X,Y,p,alpha=0.5) ###plnttong the pressure field as a contour #divider1 = make_axes_locatable(ax1) #cax1 = divider1.append_axes("right", size="20%", pad=0.05) #cbar1 = plt.colorbar(im1, cax=cax1) #im2 = ax2.contourf(X,Y,u,alpha=0.5) ###plnttong the pressure field as a contour #divider2 = make_axes_locatable(ax2) #cax2 = divider2.append_axes("right", size="20%", pad=0.05) #cbar2 = plt.colorbar(im2, cax=cax2)
# The boundary 1 (top) and 2 (left) are directly mapped to the values 1 and 2. # On side 3 (bottom) a lambda function 3+x is used (p is the boundary position # and p[0] its x coordinate. On side 4 (right) a function uDirichlet is used # that simply returns 4 in this example but can compute anything as a function # of the individual boundaries b. ############################################################################### # Short test: setting single node dirichlet BC u = solve(grid, f=1., uB=[grid.node(2), 0.]) ax, _ = pg.show( grid, u, label='Solution $u$', ) show(grid, ax=ax) def uDirichlet(b): """ Return a solution value for coordinate p. """ return 4.0 dirichletBC = [ [1, 1.0], # left [grid.findBoundaryByMarker(2), 2.0], # right [grid.findBoundaryByMarker(3), lambda p: 3.0 + p.center()[0]], # top [grid.findBoundaryByMarker(4), uDirichlet] ] # bottom
scheme='UDS' dirichletBC = [[1, lambda b_: 1. - np.tanh(10.)], [2, lambda b_: 1. - np.tanh(10.)], [3, lambda b_: 1. - np.tanh(10.)], [4, lambda b_: 1. + np.tanh(10 * (2 * b_.center()[0] + 1.))], ] print ("start", swatch.duration()) uGrid = solveFiniteVolume(grid, a=1./Peclet, f=f, vel=vB, uBoundary=dirichletBC, duBoundary=neumannBC, scheme=scheme) pg.showLater(1) ax1,cb = show(grid) drawStreams(ax1, grid, vC, coarseMesh=pg.createGrid(x=np.linspace(-1.0, 1.0, 41), y=np.linspace(0.0, 1.0, 21)), ) print(swatch.duration()) #grid2, u2 = createFVPostProzessMesh(grid, u, dirichletBC) show(grid, data=uGrid, logScale=False, interpolate=1, tri=1, colorBar=True, axes=ax1) #unstructured boundary = [] boundary.append([-1.0, 0.0])
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 uDirichlet(boundary): """Return a solution value for a given boundary. Scalar values are applied to all nodes of the boundary.""" return 4.0 dirichletBC = {1: 1, # left 2: 2.0, # right 3: lambda boundary: 3.0 + boundary.center()[0], # top 4: uDirichlet} # bottom ############################################################################### # The boundary conditions are passed using the bc keyword dictionary. u = solve(grid, f=1., bc={'Dirichlet': dirichletBC}) # Note that showMesh returns the created figure ax and the created colorBar. ax, cbar = show(grid, data=u, label='Solution $u$') show(grid, ax=ax) ax.text(0, 1.01, '$u=3+x$', ha='center') ax.text(-1.01, 0, '$u=1$', va='center', ha='right', rotation='vertical') ax.text(0, -1.01, '$u=4$', ha='center', va='top') ax.text(1.02, 0, '$u=2$', va='center', ha='left', rotation='vertical') ax.set_title('$\\nabla\cdot(1\\nabla u)=1$') ax.set_xlim([-1.1, 1.1]) # some boundary for the text ax.set_ylim([-1.1, 1.1]) ############################################################################### # Alternatively we can define the gradients of the solution on the boundary,
dirichletBC = [ [1, 1.0], # left [grid.findBoundaryByMarker(2), 2.0], # right [grid.findBoundaryByMarker(3), lambda p: 3.0 + p.center()[0]], # top [grid.findBoundaryByMarker(4), uDirichlet], ] # bottom ############################################################################### # The BC are passed using the uBoundary keyword. Note that showMesh returns the # created figure axes ax while drawMesh plots on it and it can also be used as # a class with plotting or decoration methods. u = solve(grid, f=1.0, uB=dirichletBC) ax = show( grid, data=u, colorBar=True, orientation="vertical", label="Solution $u$", levels=np.linspace(1.0, 4.0, 17), hold=1 )[0] show(grid, axes=ax) ax.text(0, 1.01, "$u=3+x$", ha="center") ax.text(-1.01, 0, "$u=1$", va="center", ha="right", rotation="vertical") ax.text(0, -1.01, "$u=4$", ha="center", va="top") ax.text(1.02, 0, "$u=2$", va="center", ha="left", rotation="vertical") ax.set_title("$\\nabla\cdot(1\\nabla u)=1$") ax.set_xlim([-1.1, 1.1]) # some boundary for the text ax.set_ylim([-1.1, 1.1]) ###############################################################################
def _test_ConvectionAdvection(): """Test agains a refernce solution.""" 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.RVector(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.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]]] preBoundary = [[7, 0.0]] vel, pres, pCNorm, divVNorm = __solveStokes(grid, a, velBoundary, preBoundary, maxIter=maxIter, verbose=1) print("time", len(pCNorm), swatch.duration(True)) # referencesolution = 1.2889506342694153 referencesolutionDivV = 0.029187181920161752 print("divNorm: ", divVNorm[-1]) print("to reference: ", divVNorm[-1] - referencesolutionDivV) fig = 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), logScale=False, showLater=True, colorBar=True, ax=ax1, cbar='b2r') show(grid, data=pg.logTransDropTol( pg.meshtools.cellDataToNodeData(grid, vel[:, 0]), 1e-2), logScale=False, showLater=True, colorBar=True, ax=ax2) show(grid, data=pg.logTransDropTol( pg.meshtools.cellDataToNodeData(grid, vel[:, 1]), 1e-2), logScale=False, showLater=True, colorBar=True, ax=ax3) show(grid, data=vel, ax=ax1) show(grid, showLater=True, ax=ax1) plt.figure() plt.semilogy(pCNorm, label='norm') plt.legend() plt.ioff() plt.show()
velBoundary, preBoundary, maxIter=maxIter, verbose=1) print("time", len(pCNorm), swatch.duration(True)) referencesolution = 1.2889506342694153 referencesolutionDivV = 0.029187181920161752 print("divNorm: ", divVNorm[-1]) print("to reference: ", divVNorm[-1] - referencesolutionDivV) fig = 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.cellDataToPointData(grid, pres), logScale=False, showLater=True, colorBar=True, axes=ax1, cbar='b2r') show(grid, data=pg.logTransDropTol( pg.cellDataToPointData( grid, vel[ :, 0]), 1e-2), logScale=False, showLater=True, colorBar=True, axes=ax2) show(grid, data=pg.logTransDropTol( pg.cellDataToPointData( grid, vel[ :, 1]), 1e-2), logScale=False, showLater=True, colorBar=True, axes=ax3) show(grid, data=vel, axes=ax1) show(grid, showLater=True, axes=ax1)
def divergence(mesh, F): div = pg.RVector(mesh.cellCount()) for c in mesh.cells(): div[c.id()] = divergenceCell(c, F) return div grid = pg.createGrid(x=np.arange(3. + 1), y=np.arange(2. + 1)) pot = np.arange(3. * 2) print(grid, pot) plt.ion() show(grid, pot) pN = pg.cellDataToPointData(grid, pot) ax, cbar = show(grid, pN) ax, cbar = show(grid, axes=ax) vF = np.zeros((grid.boundaryCount(), 2)) cellGrad = cellDataToCellGrad(grid, pot) print(cellGrad) cellGrad = cellDataToCellGrad2(grid, pot) print(cellGrad) boundGrad = cellDataToBoundaryGrad(grid, pot) boundGrad2 = cellDataToBoundaryGrad(grid, pot, 1)
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 3D Visualization (Proof of concept) ----------------------------------- """ import pygimli as pg from pygimli.viewer import show mesh = pg.createMesh3D(1,1,1) """ If interactive is set to True, a Mayavi window pops up which allows for interactive introspection. If it is set to False, mayavi produces a pixel array of the scene which is plotted in a mpl figure and therefore automatically picked up by the plot2rst extension for the documentation. """ show(mesh, interactive=False) """ .. image:: PLOT2RST.current_figure :scale: 75 """ <<<<<<< .working ======= pg.showNow()>>>>>>> .new
k = 1e-3 sigma = 1 u = solve(grid, a=sigma, b=sigma * k*k, f=pointSource, duB=neumannBC, userData={'sourcePos': sourcePosA, 'k': k}, verbose=True) u -= solve(grid, a=sigma, b=sigma * k*k, f=pointSource, duB=neumannBC, userData={'sourcePos': sourcePosB, 'k': k}, verbose=True) # uAna = pg.RVector(map(lambda p__: uAnalytical(p__, sourcePosA, k), # grid.positions())) # uAna -= pg.RVector(map(lambda p__: uAnalytical(p__, sourcePosB, k), # grid.positions())) # err = (1.0 -u/uAna) * 100.0 # print("error min max", min(err), max(err)) ax = show(grid, data=u, filled=True, colorBar=True, cmap="RdBu_r", orientation='horizontal', label='Solution u', hold=True)[0] show(grid, ax=ax, hold=True) gridCoarse = pg.createGrid(x=np.linspace(-10.0, 10.0, 20), y=np.linspace(-15.0, .0, 20)) # Instead of the grid we want to add streamlines to the plot to show the # gradients of the solution. drawStreams(ax, grid, u, coarseMesh=gridCoarse, color='Black') pg.wait()
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 3D Visualization (Proof of concept) ----------------------------------- """ import pygimli as pg from pygimli.viewer import show mesh = pg.meshtools.createMesh3D(1,1,1) """ If interactive is set to True, a Mayavi window pops up which allows for interactive introspection. If it is set to False, mayavi produces a pixel array of the scene which is plotted in a mpl figure and therefore automatically picked up by the plot2rst extension for the documentation. """ show(mesh, interactive=False) """ .. image:: PLOT2RST.current_figure :scale: 75 """ <<<<<<< .working ======= pg.showNow()>>>>>>> .new
neumannBC = [[1, mixedBC], #left boundary [2, mixedBC], #right boundary [4, mixedBC]] #bottom boundary k = 1e-3 u = solve(grid, a=1, b=k*k, f=pointSource, duB=neumannBC, userData={'sourcePos': sourcePosA, 'k': k}, verbose=True) u -= solve(grid, a=1, b=k*k, f=pointSource, duB=neumannBC, userData={'sourcePos': sourcePosB, 'k': k}, verbose=True) #uAna = pg.RVector(map(lambda p__: uAnalytical(p__, sourcePosA, k), grid.positions())) #uAna -= pg.RVector(map(lambda p__: uAnalytical(p__, sourcePosB, k), grid.positions())) #err = (1.0 -u/uAna)*100.0 #print "error min max", min(err), max(err) ax = show(grid, data=u, filled=True, colorBar=True, orientation='horizontal', label='Solution u')[0] show(grid, axes=ax) gridCoarse = pg.createGrid(x=np.linspace(-10.0, 10.0, 20), y=np.linspace(-15.0, .0, 20)) # Instead of the grid we want to add streamlines to the plot to show the gradients # of the solution. drawStreams(ax, grid, u, coarseMesh=gridCoarse, color='Black') pg.wait()
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 [4, 1.0]] #bottom pg.showLater(1) ax = show(grid)[0] ax.figure.canvas.draw() #plt.ion() #plt.show() u = solve(grid, a=vals, f=0.5, times=times, u0=pg.RVector(grid.nodeCount(), 0.0), duBoundary=neumannBC, uBoundary=dirichletBC, ##plotTimeStep=updateDrawU, verbose=False, progress=True) uMin = min(u.flat)
Peclet = 500 # vel/diffus scheme='UDS' dirichletBC = [[1, lambda b_: 1. - np.tanh(10.)], [2, lambda b_: 1. - np.tanh(10.)], [3, lambda b_: 1. - np.tanh(10.)], [4, lambda b_: 1. + np.tanh(10 * (2 * b_.center()[0] + 1.))], ] print ("start", swatch.duration()) uGrid = solveFiniteVolume(grid, a=1./Peclet, f=f, vel=vB, uBoundary=dirichletBC, duBoundary=neumannBC, scheme=scheme) ax1,cb = show(grid) drawStreams(ax1, grid, vC, coarseMesh=pg.createGrid(x=np.linspace(-1.0, 1.0, 41), y=np.linspace(0.0, 1.0, 21)), ) print(swatch.duration()) #grid2, u2 = createFVPostProzessMesh(grid, u, dirichletBC) show(grid, data=uGrid, logScale=False, interpolate=1, tri=1, colorBar=True, axes=ax1) #unstructured boundary = [] boundary.append([-1.0, 0.0])
# uAna = pg.RVector(map(lambda p__: uAnalytical(p__, sourcePosA, k), # grid.positions())) # uAna -= pg.RVector(map(lambda p__: uAnalytical(p__, sourcePosB, k), # grid.positions())) # err = (1.0 -u/uAna) * 100.0 # print("error min max", min(err), max(err)) ax = show(grid, data=u, fillContour=True, colorBar=True, cMap="RdBu_r", orientation='horizontal', label='Solution u', nLevs=11, logScale=False, hold=True, showMesh=True)[0] # Additional to the image of the potential we want to see the current flow too. # The current flows along the gradient of our solution and can be plotted as # stream lines. On 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 basis to draw the # streams. If the drawStreams get 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))
print("time", len(pCNorm), swatch.duration(True)) referencesolution = 1.2889506342694153 referencesolutionDivV = 0.029187181920161752 print("divNorm: ", divVNorm[-1]) print("to reference: ", divVNorm[-1] - referencesolutionDivV) fig = 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.core.cellDataToPointData(grid, pres), logScale=False, showLater=True, colorBar=True, axes=ax1, cbar='b2r') show(grid, data=pg.logTransDropTol(pg.core.cellDataToPointData(grid, vel[:, 0]), 1e-2), logScale=False, showLater=True, colorBar=True, axes=ax2) show(grid, data=pg.logTransDropTol(pg.core.cellDataToPointData(grid, vel[:, 1]), 1e-2), logScale=False, showLater=True,
vel, pre, pCNorm, divVNorm = solveStokes_NEEDNAME(mesh, velBoundary, preBoundary, viscosity=a, pre0=pre, vel0=vel, maxIter=maxIter, tol=1e-2, verbose=1) print(" Time: ", swatch.duration(True)) print("OverallTime:", swatchG.duration(True)) fig = plt.figure() ax1 = fig.add_subplot(1, 1, 1) plt.ion() ax, cbar = show(mesh, data=pg.cellDataToPointData(mesh, np.sqrt(vel[:,0]*vel[:,0] +vel[:,1]*vel[:,1])), logScale=False, colorBar=True, axes=ax1, cbar='b2r') cbar.ax.set_xlabel('Geschwindigkeit in m$/$s') meshC, velBoundary, preBoundary, a, maxIter = modelCavity2(0.001, False) show(mesh, data=vel, coarseMesh=meshC, axes=ax1) #show(mesh, data=vel, axes=ax1) show(meshC, axes=ax1) #show(mesh, axes=ax1) plt.figure() plt.semilogy(pCNorm, label='norm') plt.semilogy(divVNorm, label='norm') plt.legend()
neumannBC = [[1, mixedBC], #left boundary [2, mixedBC], #right boundary ] dirichletBC = [[4, 0]] #bottom boundary k = 0.1 uFE = solver.solveFiniteElements(grid, a=a, b=k*k, f=pointSource, duBoundary=neumannBC, uBoundary=dirichletBC, userData={'sourcePos': sourcePosA, 'k': k}, verbose=True) pg.showLater(1) ax1, cb = show(grid, uFE, cMin=0, cMax=1, nLevs=10, colorBar=True) drawMesh(ax1, grid) f = pg.Vector(grid.cellCount(), 0) f[grid.findCell(sourcePosA).id()]=1.0/grid.findCell(sourcePosA).size() uFV = solveFiniteVolume(grid, a=a, b=k*k, f=f, duBoundary=neumannBC, uBoundary=dirichletBC, userData={'sourcePos': sourcePosA, 'k': k}, verbose=True) #print('FVM:', swatch.duration(True)) ax2, cb = show(grid, uFV, interpolate=1, tri=1,
neumannBC = [[1, mixedBC], #left boundary [2, mixedBC], #right boundary ] dirichletBC = [[4, 0]] #bottom boundary k = 0.1 uFE = solver.solveFiniteElements(grid, a=a, b=k*k, f=pointSource, duBoundary=neumannBC, uBoundary=dirichletBC, userData={'sourcePos': sourcePosA, 'k': k}, verbose=True) pg.showLater(1) ax1, cb = show(grid, uFE, cMin=0, cMax=1, nLevs=10, colorBar=True) drawMesh(ax1, grid) f = pg.RVector(grid.cellCount(), 0) f[grid.findCell(sourcePosA).id()]=1.0/grid.findCell(sourcePosA).size() uFV = solveFiniteVolume(grid, a=a, b=k*k, f=f, duBoundary=neumannBC, uBoundary=dirichletBC, userData={'sourcePos': sourcePosA, 'k': k}, verbose=True) #print('FVM:', swatch.duration(True)) ax2, cb = show(grid, uFV, interpolate=1, tri=1,