Exemplo n.º 1
0
def createMeshPatches(ax, mesh, verbose=True, **kwargs):
    """Utility function to create 2d mesh patches within a given ax."""
    if not mesh:
        print("drawMeshBoundaries(ax, mesh): invalid mesh")
        return

    if mesh.nodeCount() < 2:
        print("drawMeshBoundaries(ax, mesh): to few nodes")
        return

    swatch = pg.Stopwatch(True)

    if kwargs.pop('fitView', True):
        ax.set_xlim(mesh.xmin(), mesh.xmax())
        ax.set_ylim(mesh.ymin(), mesh.ymax())

    polys = []

    for cell in mesh.cells():
        if cell.shape().nodeCount() == 3:
            polys.append(
                list(
                    zip([cell.node(0).x(),
                         cell.node(1).x(),
                         cell.node(2).x()],
                        [cell.node(0).y(),
                         cell.node(1).y(),
                         cell.node(2).y()])))
        elif cell.shape().nodeCount() == 4:
            polys.append(
                list(
                    zip([
                        cell.node(0).x(),
                        cell.node(1).x(),
                        cell.node(2).x(),
                        cell.node(3).x()
                    ], [
                        cell.node(0).y(),
                        cell.node(1).y(),
                        cell.node(2).y(),
                        cell.node(3).y()
                    ])))
        else:
            print(("unknown shape to patch: ", cell.shape(),
                   cell.shape().nodeCount()))

    patches = mpl.collections.PolyCollection(polys,
                                             antialiaseds=False,
                                             picker=True)  # ,lod=True

    #    patches.set_edgecolor(None)
    patches.set_edgecolor('face')
    #    patches.set_linewidth(1.001)
    ax.add_collection(patches)

    updateAxes_(ax)

    if verbose:
        print(("plotting time = ", swatch.duration(True)))
    return patches
Exemplo n.º 2
0
    def test_Performance(self):
        """
        """
        #pg.setDebug(True)

        sw = pg.Stopwatch(True)
        #print(timeit.repeat('r = grid.cellSizes() * np1', setup=setup, number=1000))
        #print(timeit.repeat('r = c * np1', setup=setup, number=1000))

        print(
            ("np(np)", timeit.repeat('np.array(np1)', setup=setup,
                                     number=5000)))
        print(("pg(pg)",
               timeit.repeat('pg.RVector(pg1)', setup=setup, number=5000)))
        print(("pg(np)",
               timeit.repeat('pg.RVector(np1)', setup=setup, number=5000)))
        print(
            ("np(pg)", timeit.repeat('np.array(pg1)', setup=setup,
                                     number=5000)))
        print(("np * np",
               timeit.repeat('np3 = np1 * np2', setup=setup, number=5000)))
        print(("pg * pg",
               timeit.repeat('pg3 = pg1 * pg2', setup=setup, number=5000)))
        print(("pg * np", timeit.repeat('pg1 * np1', setup=setup,
                                        number=5000)))
        print(("np * pg", timeit.repeat('np1 * pg1', setup=setup,
                                        number=5000)))
        print(("sum(np)", timeit.repeat('sum(np1)', setup=setup, number=300)))
        print(("sum(pg)", timeit.repeat('sum(pg1)', setup=setup, number=300)))
        print(
            ("pg.sum(pg)", timeit.repeat('pg.sum(pg1)',
                                         setup=setup,
                                         number=300)))
        print(
            ("pg.sum(st)", timeit.repeat('pg.sum(st)', setup=setup,
                                         number=300)))

        print(("s", sw.duration(True)))

        N = 10001
        np1 = np.linspace(1.1, 1.2, N)
        np2 = np.linspace(2.1, 2.1, N)

        pg1 = pg.RVector(np1)
        pg2 = pg.RVector(np2)

        # print(sw.duration(True))
        print((sum(np1 * np1)))
        print((sum(pg1 * pg1)))
        print((sum(np1 * pg1)))
        print((sum(pg1 * np1)))
Exemplo n.º 3
0
def divergence(mesh, V, span=None):
    div = mesh.divergence(V)
    return div
      
    
    swatch = pg.Stopwatch(True)
    ret = np.zeros((mesh.cellCount(), 3))
    
    for b in mesh.boundaries():
        leftCell = b.leftCell() 
        rightCell = b.rightCell()
        
        #flow = b.norm() * b.size()
        vec = mesh.boundarySizedNormals()[b.id()] * V[b.id()]
        
        #flow = mesh.boundaryFlow()[b.id()]
        if b.leftCell():
            ret[leftCell.id(),:] += vec.array()
            #ret[leftCell.id(),:] += vec
            #ret[leftCell.id(), 0] += vec[0]
            #ret[leftCell.id(), 1] += vec[1]
            #ret[leftCell.id(), 2] += vec[2]
            #ret[leftCell.id()] += vec.array()
            #ret[leftCell.id()] += vec.array()
            
        if b.rightCell():
            ret[rightCell.id(), :] -= vec.array()
            #ret[rightCell.id(), :] -= vec
            #ret[rightCell.id(), 0] -= vec[0]
            #ret[rightCell.id(), 1] -= vec[1]
            #ret[rightCell.id(), 2] -= vec[2]
            
    print('     C', swatch.duration(True))
    
    ret[:,0] /= mesh.cellSizes()
    ret[:,1] /= mesh.cellSizes()
    ret[:,2] /= mesh.cellSizes()
    print('     D', swatch.duration(True))
    
    if type(V[0]) == float:
        return ret
    
    return ret[:,0] + ret[:,1] +ret[:,2]
Exemplo n.º 4
0
def appendTetrahedronBoundary(mesh, xbound=100, ybound=100, zbound=100,
                              marker=1, quality=2, isSubSurface=False,
                              verbose=False):
    """
    Return new mesh surrounded by tetrahedron boundary box.

    Creates a tetrahedral box around a given mesh
    suitable for geo-simulation (surface boundary at top).

    Parameters
    ----------
    mesh : mesh object
        Mesh to which the tetrahedron boundary should be appended.
    xbound : float, optional
        Horizontal prolongation distance in x-direction.
    ybound : float, optional
        Horizonal prolongation distance in y-direction.
    zbound : float, optional
        Vertical prolongation distance.
    marker : int, optional
        Marker of new cells.
    quality : float, optional
        Triangle quality.
    isSubSurface : boolean, optional
        Apply boundary conditions suitable for geo-simulaion and prolongate
        mesh to the surface if necessary.
    verbose : boolean, optional
        Be verbose.

    See Also
    --------
    appendTriangleBoundary

    Notes
    -----
    Boundaries of mesh need marker 1.
    """
    # create boundary for mesh from boundary marker == 1

    if isSubSurface:
        raise Exception('Implement me')

    meshBoundary = pg.Mesh()
    meshBoundary.createH2()

    bounds = []
    for b in meshBoundary.boundaries():
        if b.marker() == 1:
            bounds.append(b)

    meshBoundaryPoly = pg.Mesh()
    meshBoundaryPoly.createMeshByBoundaries(
        meshBoundary, meshBoundary.findBoundaryByMarker(1))

    meshBoundaryPoly.exportAsTetgenPolyFile("paraBoundary.poly")
    # system( 'polyConvert -V paraBoundary' )

    # create worldSurface.poly including boundary mesh for a nice surface mesh
    # it will be later the tetgen input with preserve boundary
    polyCreateWorld('worldSurface', x=xbound, y=ybound, depth=zbound, marker=1,
                    verbose=verbose)
    os.system('polyMerge -N worldSurface paraBoundary worldSurface')
    polyAddVIP('worldSurface', mesh.cell(0).center(), isHoleMarker=True,
               verbose=verbose)
    worldBoundary = tetgen('worldSurface', quality=1.12, verbose=verbose)
    # worldBoundary.exportBoundaryVTU('worldSurface')

    worldPoly = pg.Mesh()
    worldPoly.createMeshByBoundaries(worldBoundary,
                                     worldBoundary.findBoundaryByMarker(-2, 0))
    worldPoly.exportAsTetgenPolyFile("worldSurface.poly")

    os.system('polyMerge -N worldSurface paraBoundary boundaryWorld')

    # mesh should have to be a hole
    polyAddVIP('boundaryWorld', mesh.cell(0).center(), isHoleMarker=True,
               verbose=verbose)
    # system( 'polyConvert -o world-poly -V boundaryWorld' )

    boundMesh = tetgen('boundaryWorld', quality=quality, preserveBoundary=True,
                       verbose=verbose)
    # boundMesh.exportVTK( 'boundaryWorld' )

    # merge mesh and worldBoundary
    for c in boundMesh.cells():
        c.setMarker(marker)

    if verbose:
        print("merge grid and boundary")

    swatch = pg.Stopwatch(True)
    for c in meshBoundary.cells():
        nodes = pg.stdVectorNodes()
        for n in c.nodes():
            nodes.append(boundMesh.createNodeWithCheck(n.pos()))

        boundMesh.createCell(nodes, c.marker())
    if verbose:
        print(" done.", swatch.duration(True))

    try:
        os.remove('boundaryWorld.bms')
        os.remove('worldSurface.bms')
        os.remove('boundaryWorld.poly')
        os.remove('paraBoundary.poly')
        os.remove('worldSurface.poly')
    except BaseException as e:
        print(e)

    return boundMesh
Exemplo n.º 5
0
def calcApparentResistivities(mesh, meshERT, poro, rhoBrine):
    ert = ERT(verbose=False)

    meshFOP = appendTriangleBoundary(meshERT,
                                     xbound=50,
                                     ybound=50,
                                     marker=1,
                                     quality=34.0,
                                     smooth=False,
                                     markerBoundary=1,
                                     isSubSurface=False,
                                     verbose=False)

    swatch = pg.Stopwatch(True)

    print("res 1:", swatch.duration(True))

    resis = resistivityArchie(rBrine=rhoBrine,
                              porosity=poro,
                              S=1.0,
                              mesh=mesh,
                              meshI=meshFOP)

    print("res 2:", swatch.duration(True))

    ertPointsX = [pg.RVector3(x, 0) for x in np.arange(-19, 19.1, 1)]
    ertScheme = ert.createData(ertPointsX, scheme="Dipole Dipole (CC-PP)")

    solutionName = createCacheName('appRes', mesh) + "-" + \
        str(ertScheme.size()) + "-" + str(len(rhoBrine))

    try:
        rhoa = np.load(solutionName + '.bmat.npy')
        ertData = pb.DataContainerERT(solutionName + '.dat')
    except Exception as e:
        print(e)
        print("Building .... ")
        rhoa = np.zeros((len(resis), ertScheme.size()))
        ertScheme.set('k', pb.geometricFactor(ertScheme))
        ertData = ert.simulate(meshFOP, resis[0], ertScheme)

        errPerc = 1
        errVolt = 1e-5
        voltage = ertData('rhoa') / ertData('k')
        ertData.set('err', pg.abs(errVolt / voltage) + errPerc / 100.0)
        print('err min:',
              min(ertData('err')) * 100, 'max:',
              max(ertData('err')) * 100)
        ertData.save(solutionName + '.dat', 'a b m n rhoa err k')
        for i in range(0, len(resis)):
            tic = time.time()
            rhoa[i] = ert.fop.response(resis[i])

            rand = pg.RVector(len(rhoa[i]))
            pg.randn(rand)

            rhoa[i] *= (1.0 + rand * ertData('err'))

            print(i, "/", len(resis), " : ",
                  time.time() - tic, "s", "min:", min(resis[i]), "max:",
                  max(resis[i]), "min:", min(rhoa[i]), "max:", max(rhoa[i]))

        np.save(solutionName + '.bmat', rhoa)

    return meshFOP, resis, ertData, rhoa
Exemplo n.º 6
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.RMatrix()
    vels = []

    swatch = pg.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.º 7
0
def divergence(mesh, F=None, normMap=None, order=1):
    """Divergence for callable function F((x,y,z)).

    MOVE THIS to a better place

    Divergence for callable function F((x,y,z)). Return sum div over boundary.

    Parameters
    ----------

    Returns
    -------
    """
    if F is None:
        F = lambda r: r

    diverg = 0
    directionCheck = False

    if mesh.cellCount() > 0:
        directionCheck = True

    bNorms = None
    if normMap is not None:
        bNorms = np.zeros((mesh.boundaryCount(), 2))
        for pair in normMap:
            bounds = mesh.findBoundaryByMarker(pair[0])
            for b in bounds:
                bN = [0.0, 0.0]
                if not isinstance(pair[1][0], str):
                    bN[0] = pair[1][0]
                if not isinstance(pair[1][1], str):
                    bN[1] = pair[1][1]

                bNorms[b.id()] = bN

    for b in mesh.boundaries():

        if directionCheck:
            if b.leftCell() is None and b.rightCell() is None:
                # print(b.id(), b.leftCell(), b.rightCell())
                sw = pg.Stopwatch(True)
                mesh.createNeighbourInfos()
                print("NeighbourInfos()", sw.duration(True))
                # return gauss(grid, F)

            # don't calc for inner boundaries
            if b.leftCell() is not None and b.rightCell() is not None:
                continue

        tmpdiv = 0
        shape = b.shape()

        if order == 1:
            if bNorms is not None:
                tmpdiv = shape.norm().dot(bNorms[b.id()]) * shape.domainSize()
            else:
                tmpdiv = shape.norm().dot(F(
                    shape.center())) * shape.domainSize()
        else:
            weights = pg.IntegrationRules.instance().weights(shape, order)
            abscissa = pg.IntegrationRules.instance().abscissa(shape, order)

            for i, p in enumerate(abscissa):
                rPos = shape.xyz(p)
                tmpdiv += shape.norm().dot(F(rPos)) * \
                    weights[i] * shape.domainSize()

        if directionCheck and b.leftCell() is None:
            tmpdiv *= -1
            # raise Exception("invalid mesh: left is None .. every
            # boundary need leftCell")

        diverg += tmpdiv

    return diverg
Exemplo n.º 8
0
def crankNicolson(times, theta, S, I, f, u0=None, verbose=0):
    """
        S = const over time
        f = const over time

    """

    if len(times) < 2:
        raise BaseException("We need at least 2 times for Crank "
                            "Nicolsen time discretization." + str(len(times)))
    sw = pg.Stopwatch(True)

    if u0 is None:
        u0 = np.zeros(len(f))

    u = np.zeros((len(times), len(f)))
    u[0, :] = u0
    dt = (times[1] - times[0])

    rhs = np.zeros((len(times), len(f)))

    rhs[:] = f

    A = (I + dt * theta * S)

    solver = pg.LinSolver(A, verbose=verbose)

    timeAssemble = []
    timeSolve = []
    # print('0', min(u[0]), max(u[0]), min(f), max(f))
    for n in range(1, len(times)):

        if verbose:
            pg.tic()

#        pg.tic()
#        bRef = (I + (dt * (theta - 1.)) * S) * u[n - 1] + \
#            dt * ((1.0 - theta) * rhs[n - 1] + theta * rhs[n])
#        pg.toc()
#
#        pg.tic()
#        b = u[n - 1] + ((dt * (theta - 1.)) * S) * u[n - 1] + \
#            dt * ((1.0 - theta) * rhs[n - 1] + theta * rhs[n])
#        pg.toc()
#
#        pg.tic()
        b = u[n - 1] + S.mult(dt * (theta - 1.) * u[n - 1]) + \
            dt * ((1.0 - theta) * rhs[n - 1] + theta * rhs[n])
        #        pg.toc()
        #
        #        print(np.linalg.norm(b-b1))
        #        np.testing.assert_allclose(bRef, b)

        if verbose:
            timeAssemble.append(pg.dur())

        if verbose:
            pg.tic()

        u[n, :] = solver.solve(b)

        if verbose:
            timeSolve.append(pg.dur())

        # A = (I + dt * theta * S)
        # u[n, : ] = linsolve(A, b)

        if verbose and (n % verbose == 0):
            # print(min(u[n]), max(u[n]))
            print("timesteps:", n, "/", len(times), 'runtime:', sw.duration(),
                  "s", 'assemble:', np.mean(timeAssemble), 'solve:',
                  np.mean(timeSolve))


#    import matplotlib.pyplot as plt
#    plt.figure()
#    plt.plot(timeAssemble)
#    plt.figure()
#    plt.plot(timeSolve)
#    plt.show()

    return u
Exemplo n.º 9
0
def drawShapes(ax, mesh, u):
    '''
    '''

    ax.set_aspect('equal')

    Nx = 21
    Ny = 21
    nLevels = 12

    tix = np.linspace(-1.0, 1.0, Nx)
    tiy = np.linspace(-1.0, 1.0, Ny)
    X, Y = np.meshgrid(tix, tiy)

    uc = pg.RVector(len(X.flat))

    c = mesh.cell(0)

    imax = pg.find(u == max(u))[0]

    for i in range(c.nodeCount()):
        print(c.rst(i))
    print(imax)
    print(c.createShapeFunctions()[imax])
    print("dx", c.createShapeFunctions()[imax].derive(0))
    print("dy", c.createShapeFunctions()[imax].derive(1))

    # draw nodes
    for i in range(c.nodeCount()):
        col = 'black'
        if i == imax:
            col = 'red'

        ax.plot(c.node(i).pos()[0], c.node(i).pos()[1], '.', markersize=12,
                linewidth=0, color=col)

    # draw boundary
    drawMeshBoundaries(ax, mesh)
    ptns = []
    grads = []

    swatch = pg.Stopwatch(True)
    for i, x in enumerate(X.flat):
        p = c.shape().xyz(pg.RVector3(X.flat[i], Y.flat[i]))

        X.flat[i] = p[0]
        Y.flat[i] = p[1]

#        ax.plot(p[0], p[1], '.', zorder=10, color='black', markersize = 1)

        if not c.shape().isInside(p):
            uc[i] = -99.0
            continue

        uc[i] = c.pot(p, u)

        gr = c.grad(p, u)
        ptns.append(p)
        grads.append(gr)

    print(swatch.duration(True))

    for i, p in enumerate(ptns):
        ax.quiver(p[0], p[1], grads[i][0], grads[i][1], zorder=10)

    Z = np.ma.masked_where(uc == -99., uc)
    Z = Z.reshape(Ny, Nx)
    ax.contourf(X, Y, Z, nLevels)
Exemplo n.º 10
0
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()
Exemplo n.º 11
0
def test2d():
    mesh = pg.Mesh('mesh/world2d.bms')
    print(mesh)

    xMin = mesh.boundingBox().min()[0]
    yMax = mesh.boundingBox().max()[0]
    x = np.arange(xMin, yMax, 1.)

    mesh.createNeighbourInfos()
    rho = pg.RVector(len(mesh.cellAttributes()), 1.) * 2000.0
    rho.setVal(0.0, pg.find(mesh.cellAttributes() == 1.0))

    swatch = pg.Stopwatch(True)
    pnts = []
    spnts = pg.stdVectorRVector3()

    for i in x:
        pnts.append(pg.RVector3(i, 0.0001))
        spnts.append(pg.RVector3(i, 0.0001))

#    gzC, GC = calcGCells(pnts, mesh, rho, 1)
    gzC = pg.calcGCells(spnts, mesh, rho, 1)
    print("calcGCells", swatch.duration(True))
    #    gzB, GB = calcGBounds(pnts, mesh, rho)
    #    gzB = pg.calcGBounds(spnts, mesh, rho)
    #    print("calcGBounds", swatch.duration(True))

    gZ_Mesh = gzC

    ax1, ax2 = getaxes()

    # sphere analytical solution
    gAna = analyticalCircle2D(spnts,
                              radius=2.0,
                              pos=pg.RVector3(0.0, -5.0),
                              dDensity=2000)
    gAna2 = analyticalCircle2D(spnts,
                               radius=2.0,
                               pos=pg.RVector3(5.0, -5.0),
                               dDensity=2000)

    gAna = gAna + gAna2

    ax1.plot(x, gAna, '-x', label='analytical')
    ax1.plot(x, gZ_Mesh, label='WonBevis1987-mesh')

    print(gAna / gZ_Mesh)

    #    rho=GB[0]/mesh.cellSizes()

    drawModel(ax2, mesh, rho)
    for i in (0, 1):
        drawSelectedMeshBoundaries(ax2,
                                   mesh.findBoundaryByMarker(i),
                                   color=(1.0, 1.0, 1.0, 1.0),
                                   linewidth=0.3)

    # sphere polygone
    radius = 2.
    depth = 5.
    poly1 = pg.stdVectorRVector3()
    poly2 = pg.stdVectorRVector3()
    nSegment = 124
    for i in range(nSegment):
        xp = np.sin((i + 1) * (2. * np.pi) / nSegment)
        yp = np.cos((i + 1) * (2. * np.pi) / nSegment)
        poly1.append(pg.RVector3(xp * radius, yp * radius - depth))
        poly2.append(pg.RVector3(xp * radius + 5., yp * radius - depth))

    gZ_Poly = calcPolydgdz(spnts, poly1, 2000)
    gZ_Poly += calcPolydgdz(spnts, poly2, 2000)

    ax1.plot(x, gZ_Poly, label='WonBevis1987-Poly')
    ax2.plot(pg.x(poly1), pg.y(poly1), color='red')
    ax2.plot(pg.x(poly2), pg.y(poly2), color='red')

    ax2.plot(pg.x(spnts), pg.y(spnts), marker='x', color='black')

    # test some special case
    for i, p in enumerate(poly1):
        poly1[i] = pg.RVector3(poly1[i] - pg.RVector3(5.0, -6.))

    ax2.plot(pg.x(poly1), pg.y(poly1), color='green')

    gz = calcPolydgdz(spnts, poly1, 2000)
    ax1.plot(x, gz, label='Special Case', color='green')
    ax1.set_ylabel('dg/dz [mGal]')
    ax2.set_ylabel('Tiefe [m]')

    ax1.legend()
    ax2.set_xlim([x[0], x[-1]])
    ax2.grid()
Exemplo n.º 12
0
def solveFiniteVolume(mesh, a=1.0, f=0.0, fn=0.0, vel=0.0, u0=None,
                      times=None,
                      uL=None, relax=1.0,
                      ws=None, scheme='CDS', **kwargs):
    """
    """
    # The Workspace is to hold temporary data or preserve matrix rebuild
    swatch = pg.Stopwatch(True)
    sparse = True

    workspace = WorkSpace()
    if ws:
        workspace = ws

    a = solver.parseArgToArray(a, [mesh.cellCount(), mesh.boundaryCount()])
    f = solver.parseArgToArray(f, mesh.cellCount())
    fn = solver.parseArgToArray(fn, mesh.cellCount())

    boundsDirichlet = None
    boundsNeumann = None

    if not hasattr(workspace, 'S'):

        if 'uBoundary' in kwargs:
            boundsDirichlet = pg.solver.parseArgToBoundaries(
                    kwargs['uBoundary'], mesh)

        if 'duBoundary' in kwargs:
            boundsNeumann = pg.solver.parseArgToBoundaries(
                    kwargs['duBoundary'], mesh)

        workspace.S, workspace.rhsBCScales = diffusionConvectionKernel(
                mesh=mesh, a=a, f=f, uBoundaries=boundsDirichlet,
                duBoundaries=boundsNeumann, u0=u0, fn=fn, vel=vel,
                scheme=scheme, sparse=sparse,
                userData=kwargs.pop('userData', None))
        print('FVM kernel 1:', swatch.duration(True))
        dof = len(workspace.rhsBCScales)

#        workspace.uDir = np.zeros(dof)

#        if u0 is not None:
#            workspace.uDir = np.array(u0)
#
#        if len(boundsDirichlet):
#            for boundary, val in boundsDirichlet.items():
#                workspace.uDir[boundary.leftCell().id()] = val

        workspace.ap = np.zeros(dof)

        # for nonlinears

        if uL is not None:
            for i in range(dof):
                val = 0.0
                if sparse:
                    val = workspace.S.getVal(i, i) / relax
                    workspace.S.setVal(i, i, val)
#                    workspace.S[i, i] /= relax
#                    workspace.ap[i] = workspace.S[i, i]
                else:
                    val = workspace.S[i, i] / relax
                    workspace.S[i, i] = val

                workspace.ap[i] = val


        print('FVM kernel 2:', swatch.duration(True))
    # endif: not hasattr(workspace, 'S'):

    workspace.rhs = np.zeros(len(workspace.rhsBCScales))
    workspace.rhs[0:mesh.cellCount()] = f  # * mesh.cellSizes()

#    if len(workspace.uDir):
    workspace.rhs += workspace.rhsBCScales

    # for nonlinear: relax progress with scaled last result
    if uL is not None:
        workspace.rhs += (1. - relax) * workspace.ap * uL
    # print('FVM: Prep:', swatch.duration(True))

    if not hasattr(times, '__len__'):

        if sparse and not hasattr(workspace, 'solver'):
            Sm = pg.RSparseMatrix(workspace.S)
            # hold Sm until we have reference counting,
            # loosing Sm here will kill LinSolver later
            workspace.Sm = Sm
            workspace.solver = pg.LinSolver(Sm, True)

        u = None
        if sparse:
            u = workspace.solver.solve(workspace.rhs)
        else:
            u = np.linalg.solve(workspace.S, workspace.rhs)
        print('FVM solve:', swatch.duration(True))
        return u[0:mesh.cellCount():1]
    else:
        theta = kwargs.pop('theta', 0.5)
        verbose = kwargs.pop('verbose', False)

        if sparse:
            I = solver.identity(len(workspace.rhs))
        else:
            I = np.diag(np.ones(len(workspace.rhs)))

        print("solve cN")
        return solver.crankNicolson(times, theta, workspace.S, I,
                                    f=workspace.rhs, u0=u0, verbose=verbose)
Exemplo n.º 13
0
def diffusionConvectionKernel(mesh, a=None, f=None,
                              uBoundaries=None, duBoundaries=None,
                              fn=None, vel=0, u0=0,
                              scheme='CDS', sparse=False, time=0.0, 
                              userData=None):
    """
        Peclet Number - ratio between convection/diffusion * Length
        
        Advection .. forced convection
    """
    if a is None:
        a = pg.RVector(mesh.boundaryCount(), 1.0)
    
    AScheme = None
    if scheme == 'CDS':
        # CDS - central differences scheme .. maybe irregular for Peclet-number |F/D| > 2
        # diffusion dominant
        # Error of order 2
        AScheme = lambda peclet_: 1.0 - 0.5 * abs(peclet_)    
    elif scheme == 'UDS':
        # UDS - upwind scheme  
        # Convection dominant
        # Error of order 1
        AScheme = lambda peclet_: 1.0
    elif scheme == 'HS':
        # HS - hybrid scheme. 
        # Diffusion dominant for Peclet-number |(F/D)| < 2
        # Convection dominant else
        AScheme = lambda peclet_: max(0.0, 1.0 - 0.5 * abs(peclet_))
    elif scheme == 'PS':
        # PS - power-law scheme. 
        # Identical to HS for Peclet-number |(F/D)| > 10 and near to ES else
        AScheme = lambda peclet_: max(0.0, (1.0 - 0.1 * abs(peclet_))**5.0)
    elif scheme == 'ES':
        # ES - exponential scheme  
        # Only stationary one-dimensional but exact solution
        AScheme = lambda peclet_: (peclet_) / (np.exp(abs(peclet_))-1.0) \
            if peclet_ != 0.0 else 1
    else:
        raise
        
    useHalfBoundaries = False
    
    dof = mesh.cellCount()
    
    if not uBoundaries:
        uBoundaries = []
    if not duBoundaries:
        duBoundaries = []
            
    if useHalfBoundaries:
        dof = mesh.cellCount() + len(uBoundaries)

    S = None
    if sparse:
        S = pg.RSparseMapMatrix(dof, dof, 0)
    else:
        S = np.zeros((dof, dof))
            
    rhsBoundaryScales = np.zeros(dof)
    
    swatch = pg.Stopwatch(True)

    # we need this to fast identify uBoundary and value by boundary
    uBoundaryID = []
    uBoundaryVals = [None] * mesh.boundaryCount()
    for i, [boundary, val] in enumerate(uBoundaries):
        if not isinstance(boundary, pg.Boundary):
            raise BaseException("Please give boundary, value list")
        uBoundaryID.append(boundary.id())
        uBoundaryVals[boundary.id()] = val
    duBoundaryID = []
    duBoundaryVals = [None] * mesh.boundaryCount()
    for i, [boundary, val] in enumerate(duBoundaries):
        if not isinstance(boundary, pg.Boundary):
            raise BaseException("Please give boundary, value list")
        duBoundaryID.append(boundary.id())
        duBoundaryVals[boundary.id()] = val
   
    for cell in mesh.cells():

        for bi in range(cell.boundaryCount()):
            boundary = pg.findBoundary(cell.boundaryNodes(bi))
            
            ncell = boundary.leftCell()
            if ncell == cell:
                ncell = boundary.rightCell()
            
            v = findVelocity(mesh, vel, boundary, cell, ncell)
            
            # Convection part
            F = boundary.norm(cell).dot(v) * boundary.size()
            
            # Diffusion part
            D = findDiffusion(mesh, a, boundary, cell, ncell)
                           
            aB = D * AScheme(F / D) + max(-F, 0.0)
            
            aB /= cell.size()
                       
            #print(cell.center(), boundary.center(), boundary.norm(cell), aB)
            if ncell:
                # no boundary
                if sparse:
                    S.addVal(cell.id(), ncell.id(), -aB)
                    S.addVal(cell.id(), cell.id(),  +aB)
                else:
                    S[cell.id(), ncell.id()] -= aB
                    S[cell.id(),  cell.id()] += aB
            
            elif not useHalfBoundaries:
                
                if boundary.id() in uBoundaryID:
                    val = pg.solver.generateBoundaryValue(boundary,
                                                        uBoundaryVals[boundary.id()],
                                                        time=time,
                                                        userData=userData)
                                                
                    if sparse:
                        S.addVal(cell.id(), cell.id(), aB)
                    else:
                        S[cell.id(), cell.id()] += aB    
                
                    rhsBoundaryScales[cell.id()] += aB * val
                    
                if boundary.id() in duBoundaryID:                    
                    # Neumann boundary condition
                    val = pg.solver.generateBoundaryValue(boundary,
                                                    duBoundaryVals[boundary.id()],
                                                    time=time,
                                                    userData=userData)
                    if sparse:
                        # amount of flow through the boundary
                        S.addVal(cell.id(), cell.id(), val * boundary.size()/cell.size())
                    else:
                        S[cell.id(), cell.id()] += val* boundary.size()/cell.size()
        
        if fn != None:
            if sparse:
                S.addVal(cell.id(), cell.id(), -fn[cell.id()]) #* cell.shape().domainSize())
            else:
                S[cell.id(), cell.id()] -= fn[cell.id()] #* cell.shape().domainSize()
     
    
    if useHalfBoundaries:        
        for i, [b, val] in enumerate(uDirBounds):
            bIdx = mesh.cellCount() + i
        
            c = b.leftCell()
            if not c:
                c = b.rightCell()
        
            if c:
                n = b.norm(c)
                v = findVelocity(mesh, vel, b, c, nc=None)
                F = n.dot(v) * b.size()

                D = findDiffusion(mesh, a, b, c)
                aB = D * AScheme(F / D) + max(-F, 0.0)
                        
                        
                if useHalfBoundaries:
                    if sparse:
                        S.setVal(c.id(), c.id(), 1.)
                        S.addVal(c.id(), bIdx, -aB)
                    else:
                        S[bIdx, bIdx] = 1.
                        S[c.id(), bIdx] -= aB
                
                    rhsBoundaryScales[bIdx] = aB
                        
    return S, rhsBoundaryScales
.. math :: 
    \vector{v}\cdot\nabla u = \frac{1}{P}\delta u
    
"""

import pygimli as pg
import pygimli.solver as solver
from pygimli.viewer import show, showMesh
from pygimli.mplviewer import drawMesh, drawModel, drawField, drawStreams
from pygimli.meshtools import createMesh
from solverFVM import solveFiniteVolume, createFVPostProzessMesh, diffusionConvectionKernel

import matplotlib.pyplot as plt
import numpy as np

swatch = pg.Stopwatch(True)

x = np.linspace(-1.0, 1.0, 41)
y = np.linspace( 0.0, 1.0, 21)
dx = x[1] - x[0]
dy = y[1] - y[0]
print(dx,dy)

grid = pg.createGrid(x=x, y=y)

# force vector per cell
f = pg.RVector(grid.cellCount(), 0.0)
#f[grid.findCell([-0.85, 0.55]).id()]=10.0

# velocity per cell [x-direction, y-direction]
vC = np.array(list(map(lambda p_: [ (2.*p_[1] *(1.0 -p_[0]**2)),
Exemplo n.º 15
0
def solveFiniteElements(mesh,
                        a=1.0,
                        b=0.0,
                        f=0.0,
                        times=None,
                        userData=None,
                        verbose=False,
                        stats=None,
                        **kwargs):
    r"""Solve partial differential equation with Finite Elements.

    This function is a syntactic sugar proxy for using the Finite Element
    functionality of the library core to solve elliptic and parabolic partial
    differential of the following type:

    .. math::

        \frac{\partial u}{\partial t} & = \nabla\cdot(a \nabla u) + b u + f(\mathbf{r},t) \\
        u(\mathbf{r}, t) & = u_B  \quad\mathbf{r}\in\Gamma_{\text{Dirichlet}}\\
        \frac{\partial u(\mathbf{r}, t)}{\partial \mathbf{n}} & = u_{\partial \text{B}} \quad\mathbf{r}\in\Gamma_{\text{Neumann}}\\
        u(\mathbf{r}, t=0) & = u_0 \quad\text{with} \quad\mathbf{r}\in\Omega\quad\text{for}\quad t\neq 0

    The Domain :math:`\Omega` and the Boundary :math:`\Gamma` are defined
    through the given mesh with appropriate boundary marker.

    The solution :math:`u(\mathbf{r}, t)` is given for each node in mesh.


    TODO:

        * unsteady ub and dub

    Parameters
    ----------
    mesh : :gimliapi:`GIMLI::Mesh`
        Mesh represents spatial discretization of the calculation domain

    a   : value | array | callable(cell, userData)
        Cell values

    b   : value | array | callable(cell, userData)
        Cell values

    u0 : value | array | callable(pos, userData)
        Node values

    uB : value | array | callable(pos, userData)
        Dirichlet values for u at the boundary

    uN : list([node, value])
        Dirichlet values for u at given nodes

    duB : value | array | callable(pos, userData)
        Neumann values for du/dn at the boundary

    f : value | array(cells) | array(nodes) | callable(args, kwargs)
        force values

    times : array [None]
        Solve as time dependent problem for the given times.

    theta : float [1]
        - :math:`theta = 0` means explicit Euler, maybe stable for
         :math:`\Delta t \quad\text{near}\quad h`
        - :math:`theta = 0.5`, Crank-Nicolsen, maybe instable
        - :math:`theta = 1`, implicit Euler

        If unsure choose :math:`\theta = 0.5 + \epsilon`, which is probably stable.

    progress : bool
        Give some calculation progress.

    ret :
        Workspace for results so no new memory will be allocated.

    Returns
    -------

    u : array
        Returns the solution u either 1,n array for stationary problems or
        for m,n array for m time steps

    Examples
    --------
    >>> import pygimli as pg
    >>> from pygimli.meshtools import polytools as plc
    >>> from pygimli.mplviewer import drawField, drawMesh
    >>> import matplotlib.pyplot as plt
    >>> world = plc.createWorld(start=[-10, 0], end=[10, -10],
    ...                         marker=1, worldMarker=False)
    >>> c1 = plc.createCircle(pos=[0.0, -5.0], radius=3.0, area=.1, marker=2)
    >>> mesh = pg.meshtools.createMesh([world, c1], quality=34.3)
    >>> u = pg.solver.solveFiniteElements(mesh, a=[[1, 100], [2, 1]],
    ...                                   uB=[[4, 1.0], [2, 0.0]])
    >>> fig, ax = plt.subplots()
    >>> pc = drawField(ax, mesh, u)
    >>> drawMesh(ax, mesh)
    >>> plt.show()

    See Also
    --------

    other solver TODO
    """

    if 'uDirichlet' in kwargs or 'uBoundary' in kwargs:
        raise BaseException("use uB instead")

    if 'uBoundary' in kwargs:
        raise BaseException("use duB instead")

    debug = kwargs.pop('debug', False)

    mesh.createNeighbourInfos()
    if verbose:
        print("Mesh: ", str(mesh))

    dof = mesh.nodeCount()

    swatch = pg.Stopwatch(True)
    swatch2 = pg.Stopwatch(True)

    # check for material parameter
    a = parseArgToArray(a, ndof=mesh.cellCount(), mesh=mesh, userData=userData)
    b = parseArgToArray(b, ndof=mesh.cellCount(), mesh=mesh, userData=userData)

    if debug:
        print("2: ", swatch2.duration(True))
    # assemble the stiffness matrix
    A = createStiffnessMatrix(mesh, a)

    if debug:
        print("3: ", swatch2.duration(True))
    M = createMassMatrix(mesh, b)

    if debug:
        print("4: ", swatch2.duration(True))
    S = A + M

    if debug:
        print("5: ", swatch2.duration(True))
    if times is None:

        rhs = assembleForceVector(mesh, f, userData=userData)

        if debug:
            print("6a: ", swatch2.duration(True))

        if 'duB' in kwargs:
            assembleNeumannBC(S,
                              parseArgToBoundaries(kwargs['duB'], mesh),
                              time=0.0,
                              userData=userData)

        if debug:
            print("6b: ", swatch2.duration(True))
        if 'uB' in kwargs:
            assembleDirichletBC(S,
                                parseArgToBoundaries(kwargs['uB'], mesh),
                                rhs,
                                time=0.0,
                                userData=userData)

        if 'uN' in kwargs:
            assembleDirichletBC(S, [],
                                nodePairs=kwargs['uN'],
                                rhs=rhs,
                                time=0.0,
                                userData=userData)

        if debug:
            print("6c: ", swatch2.duration(True))

        # create result array

        u = kwargs.pop('ret', None)

        singleForce = True
        if hasattr(rhs, 'ndim'):
            if rhs.ndim == 2:
                singleForce = False
                if u is None:
                    u = np.zeros(rhs.shape)
        else:
            if isinstance(a[0], complex):
                if u is None:
                    u = pg.CVector(rhs.size(), 0.0)
                rhs = pg.toComplex(rhs)
            else:
                if u is None:
                    u = pg.RVector(rhs.size(), 0.0)

        assembleTime = swatch.duration(True)
        if stats:
            stats.assembleTime = assembleTime

        if verbose:
            print(("Asssemblation time: ", assembleTime))

        # showSparseMatrix(S)

        solver = pg.LinSolver(False)
        solver.setMatrix(S, 0)

        if singleForce:
            u = solver.solve(rhs)
        else:
            for i, r in enumerate(rhs):
                solver.solve(r, u[i])

        solverTime = swatch.duration(True)
        if verbose:
            if stats:
                stats.solverTime = solverTime
            print(("Solving time: ", solverTime))

        return u

    else:
        if debug:
            print("start TL", swatch.duration())

        M = createMassMatrix(mesh)
        F = assembleForceVector(mesh, f)

        if 'u0' in kwargs:
            u0 = parseArgToArray(kwargs['u0'], dof, mesh, userData)

        theta = kwargs.pop('theta', 1)

        if 'duB' not in kwargs:
            A = createStiffnessMatrix(mesh, a)

            if 'uB' in kwargs:
                assembleDirichletBC(A,
                                    parseArgToBoundaries(kwargs['uB'], mesh),
                                    rhs=F)

            if 'uN' in kwargs:
                assembleDirichletBC(A, [], nodePairs=kwargs['uN'], rhs=F)

            return crankNicolson(times, theta, A, M, F, u0=u0, verbose=verbose)

        rhs = np.zeros((len(times), dof))
        # rhs kann zeitabhängig sein ..wird hier nicht berücksichtigt
        rhs[:] = F  # this is slow: optimize

        if debug:
            print("rhs", swatch.duration())
        U = np.zeros((len(times), dof))
        U[0, :] = u0

        # init state
        u = pg.RVector(dof, 0.0)

        if debug:
            print("u0", swatch.duration())

        measure = 0.
        for n in range(1, len(times)):
            swatch.reset()

            dt = times[n] - times[n - 1]

            # previous timestep
            # print "i: ", i, dt, U[i - 1]

            if 'duB' in kwargs:
                # aufschreiben und checken ob neumann auf A oder auf S mit
                # skaliertem val*dt angewendet wird
                A = createStiffnessMatrix(mesh, a)
                assembleNeumannBC(A,
                                  parseArgToBoundaries(kwargs['duB'], mesh),
                                  time=times[n],
                                  userData=userData)

            swatch.reset()
            # (A + a*B)u is fastest,
            # followed by A*u + (B*u)*a and finally A*u + a*B*u and
            b = (M + (dt * (theta - 1.)) * A) * U[n - 1] + \
                dt * ((1.0 - theta) * rhs[n - 1] + theta * rhs[n])

            # print ('a',swatch.duration(True))
            # b = M * U[n - 1] - (A * U[n - 1]) * (dt*(1.0 - theta)) + \
            # dt * ((1.0 - theta) * rhs[n - 1] + theta * rhs[n])

            # print ('b',swatch.duration(True))

            # b = M * U[n - 1] - (dt*(1.0 - theta)) * A * U[n - 1] + \
            # dt * ((1.0 - theta) * rhs[n - 1] + theta * rhs[n])
            # print ('c',swatch.duration(True))

            measure += swatch.duration()

            S = M + A * dt * theta

            if 'uB' in kwargs:
                assembleDirichletBC(S,
                                    parseArgToBoundaries(kwargs['uB'], mesh),
                                    rhs=b,
                                    time=times[n],
                                    userData=userData)

            if 'uN' in kwargs:
                assembleDirichletBC(S, [],
                                    nodePairs=kwargs['uN'],
                                    rhs=b,
                                    time=times[n],
                                    userData=userData)

            # u = S/b
            t_prep = swatch.duration(True)
            solver = pg.LinSolver(S, verbose)
            solver.solve(b, u)

            if 'plotTimeStep' in kwargs:
                kwargs['plotTimeStep'](u, times[n])

            U[n, :] = np.asarray(u)

            if 'progress' in kwargs:
                if kwargs['progress']:
                    print(("\t" + str(n) + "/" + str(len(times) - 1) + ": " +
                           str(t_prep) + "/" + str(swatch.duration())))

        if debug:
            print("Measure(" + str(len(times)) + "): ", measure,
                  measure / len(times))
        return U
Exemplo n.º 16
0
def solvePressureWave(mesh, velocities, times, sourcePos, uSource, verbose):
    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.RSparseMatrix()
    M = pg.RSparseMatrix()

    #    F = pg.RVector(mesh.nodeCount(), 0.0)
    rhs = pg.RVector(mesh.nodeCount(), 0.0)
    u = pg.RMatrix(len(times), mesh.nodeCount())
    v = pg.RMatrix(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.RMatrix(len(times), mesh.cellCount())
        v = pg.RMatrix(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.LinSolver(S1, verbose=False)
    solver2 = pg.LinSolver(S2, verbose=False)
    swatch = pg.Stopwatch(True)

    #    ut = pg.RVector(mesh.nodeCount(), .0)
    #    vt = pg.RVector(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.º 17
0
def crankNicolson(times, theta, S, I, f, u0=None, progress=None, debug=None):
    """
        S = constant over time
        f = constant over time
    """

    if len(times) < 2:
        raise BaseException("We need at least 2 times for Crank "
                            "Nicolsen time discretization." + str(len(times)))
    sw = pg.Stopwatch(True)

    if u0 is None:
        u0 = np.zeros(len(f))

    u = np.zeros((len(times), len(f)))
    u[0, :] = u0
    dt = times[1] - times[0]

    rhs = np.zeros((len(times), len(f)))

    rhs[:] = f

    A = I + S * dt * theta

    solver = pg.LinSolver(A, verbose=False)

    timeAssemble = []
    timeSolve = []
    # print('0', min(u[0]), max(u[0]), min(f), max(f))

    timeMeasure = False
    if progress:
        timeMeasure = True

    for n in range(1, len(times)):

        if timeMeasure:
            pg.tic()


#        pg.tic()
#bRef = (I + (dt * (theta - 1.)) * S) * u[n - 1] + \
#dt * ((1.0 - theta) * rhs[n - 1] + theta * rhs[n])
#        pg.toc()
#
#        pg.tic()
#b = I * u[n - 1] + ((dt * (theta - 1.)) * S) * u[n - 1] + \
#dt * ((1.0 - theta) * rhs[n - 1] + theta * rhs[n])
#        pg.toc()
#
#        pg.tic()
        b = I * u[n - 1] + S.mult(dt * (theta - 1.) * u[n - 1]) + \
            dt * ((1.0 - theta) * rhs[n - 1] + theta * rhs[n])
        #        pg.toc()
        #
        #        print(np.linalg.norm(b-b1))
        #np.testing.assert_allclose(bRef, b)

        if timeMeasure:
            timeAssemble.append(pg.dur())

        if timeMeasure:
            pg.tic()

        u[n, :] = solver.solve(b)

        if timeMeasure:
            timeSolve.append(pg.dur())

        # A = (I + dt * theta * S)
        # u[n, : ] = linsolve(A, b)

        if progress:
            progress.update(n,
                            ' t_prep: ' + str(round(timeAssemble[-1], 5)) + 's' + \
                            ' t_step: ' + str(round(timeSolve[-1], 5)) + 's')

        #if verbose and (n % verbose == 0):
        ## print(min(u[n]), max(u[n]))
        #print("timesteps:", n, "/", len(times),
        #'runtime:', sw.duration(), "s",
        #'assemble:', np.mean(timeAssemble),
        #'solve:', np.mean(timeSolve))
    return u