Esempio n. 1
0
def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,test_bc):
    nbCells = my_mesh.getNumberOfCells()
    dim=my_mesh.getMeshDimension()
    nbComp=dim+1
    normal=cdmath.Vector(dim)

    implMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp)

    idMoinsJacCL=cdmath.Matrix(nbComp)
    
    for j in range(nbCells):#On parcourt les cellules
        Cj = my_mesh.getCell(j)
        nbFaces = Cj.getNumberOfFaces();

        for k in range(nbFaces) :
            indexFace = Cj.getFacesId()[k];
            Fk = my_mesh.getFace(indexFace);
            for i in range(dim) :
                normal[i] = Cj.getNormalVector(k, i);#normale sortante

            Am=jacobianMatrices( normal,dt*Fk.getMeasure()/Cj.getMeasure());

            cellAutre =-1
            if ( not Fk.isBorder()) :
                # hypothese: La cellule d'index indexC1 est la cellule courante index j */
                if (Fk.getCellsId()[0] == j) :
                    # hypothese verifiée 
                    cellAutre = Fk.getCellsId()[1];
                elif(Fk.getCellsId()[1] == j) :
                    # hypothese non verifiée 
                    cellAutre = Fk.getCellsId()[0];
                else :
                    raise ValueError("computeFluxes: problem with mesh, unknown cel number")
                    
                implMat.addValue(j*nbComp,cellAutre*nbComp,Am)
                implMat.addValue(j*nbComp,        j*nbComp,Am*(-1.))
            else  :
                if( test_bc=="Periodic" and Fk.getGroupName() != "Wall" and Fk.getGroupName() != "Paroi" and Fk.getGroupName() != "Neumann"):#Periodic boundary condition unless Wall/Neumann specified explicitly
                    test_desc["Boundary_conditions"]="Periodic"
                    indexFP = my_mesh.getIndexFacePeriodic(indexFace)
                    Fp = my_mesh.getFace(indexFP)
                    cellAutre = Fp.getCellsId()[0]
                    
                    implMat.addValue(j*nbComp,cellAutre*nbComp,Am)
                    implMat.addValue(j*nbComp,        j*nbComp,Am*(-1.))
                elif( test_bc=="Wall" or Fk.getGroupName() == "Wall" or Fk.getGroupName() == "Paroi"):#Wall boundary condition
                    test_desc["Boundary_conditions"]="Wall"
                    v=cdmath.Vector(dim+1)
                    for i in range(dim) :
                        v[i+1]=normal[i]
                    idMoinsJacCL=v.tensProduct(v)*2
                    
                    implMat.addValue(j*nbComp,j*nbComp,Am*(-1.)*idMoinsJacCL)
                    
                elif(test_bc!="Neumann" and Fk.getGroupName() != "Neumann"):#Nothing to do for Neumann boundary condition
                    print Fk.getGroupName()
                    raise ValueError("computeFluxes: Unknown boundary condition name");
                
    return implMat
Esempio n. 2
0
def computeStaggeredDivergenceMatrix(a, b, nx, nbVoisinsMax, dt, scaling):
    nbCells = nx
    dx = (b - a) / nx
    dim = 1
    nbComp = dim + 1
    normal = cdmath.Vector(dim)

    implMat = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp,
                                       (nbVoisinsMax + 1) * nbComp)

    S1, S2 = staggeredMatrices(dt / dx, scaling)
    for k in range(nbCells):  #On parcourt les cellules
        if (k == 0):
            implMat.addValue(k * nbComp, (k + 1) * nbComp, S1)
            implMat.addValue(k * nbComp, k * nbComp, S1 * (-1.))
        elif (k == nbCells - 1):
            implMat.addValue(k * nbComp, k * nbComp, S2)
            implMat.addValue(k * nbComp, (k - 1) * nbComp, S2 * (-1.))
        else:
            implMat.addValue(k * nbComp, (k + 1) * nbComp, S1)
            implMat.addValue(k * nbComp, k * nbComp, S1 * (-1.))

            implMat.addValue(k * nbComp, k * nbComp, S2)
            implMat.addValue(k * nbComp, (k - 1) * nbComp, S2 * (-1.))

    return implMat
def computeUpwindDivergenceMatrix(a,b,nx,nbVoisinsMax,dt,scaling):
    nbCells = nx
    dx=(b-a)/nx
    dim=1
    nbComp=dim+1
    normal=cdmath.Vector(dim)

    implMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp)

    A,absA= jacobianMatrices(dt/dx,scaling)
    for j in range(nbCells):#On parcourt les cellules
        if ( j==0) :
            implMat.addValue(j*nbComp,(j+1)*nbComp,(A-absA)/2)
            implMat.addValue(j*nbComp,    j*nbComp,(A-absA)/2*(-1.))
        elif ( j==nbCells-1) :
            implMat.addValue(j*nbComp,    j*nbComp,(A+absA)/2)
            implMat.addValue(j*nbComp,(j-1)*nbComp,(A+absA)/2*(-1.))
        else :
            implMat.addValue(j*nbComp,(j+1)*nbComp,(A-absA)/2)
            implMat.addValue(j*nbComp,    j*nbComp,(A-absA)/2*(-1.))

            implMat.addValue(j*nbComp,    j*nbComp,(A+absA)/2)
            implMat.addValue(j*nbComp,(j-1)*nbComp,(A+absA)/2*(-1.))
                
    return implMat
Esempio n. 4
0
def computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, test_bc, velocity):
    nbCells = my_mesh.getNumberOfCells()
    dim = my_mesh.getMeshDimension()
    nbComp = 1
    normal = cdmath.Vector(dim)

    implMat = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp,
                                       (nbVoisinsMax + 1) * nbComp)

    for j in range(nbCells):  #On parcourt les cellules
        Cj = my_mesh.getCell(j)
        nbFaces = Cj.getNumberOfFaces()

        for k in range(nbFaces):
            indexFace = Cj.getFacesId()[k]
            Fk = my_mesh.getFace(indexFace)
            for i in range(dim):
                normal[i] = Cj.getNormalVector(k, i)
                #normale sortante

            Am = upwinding_coeff(normal,
                                 dt * Fk.getMeasure() / Cj.getMeasure(),
                                 velocity)

            cellAutre = -1
            if (not Fk.isBorder()):
                # hypothese: La cellule d'index indexC1 est la cellule courante index j */
                if (Fk.getCellsId()[0] == j):
                    # hypothese verifiée
                    cellAutre = Fk.getCellsId()[1]
                elif (Fk.getCellsId()[1] == j):
                    # hypothese non verifiée
                    cellAutre = Fk.getCellsId()[0]
                else:
                    raise ValueError(
                        "computeFluxes: problem with mesh, unknown cel number")

                implMat.addValue(j * nbComp, cellAutre * nbComp, Am)
                implMat.addValue(j * nbComp, j * nbComp, Am * (-1.))
            else:
                if (
                        test_bc == "Periodic"
                        and Fk.getGroupName() != "Neumann"
                ):  #Periodic boundary condition unless Wall/Neumann specified explicitly
                    indexFP = my_mesh.getIndexFacePeriodic(
                        indexFace,
                        my_mesh.getName() == "squareWithBrickWall",
                        my_mesh.getName() == "squareWithHexagons")
                    Fp = my_mesh.getFace(indexFP)
                    cellAutre = Fp.getCellsId()[0]

                    implMat.addValue(j * nbComp, cellAutre * nbComp, Am)
                    implMat.addValue(j * nbComp, j * nbComp, Am * (-1.))
                elif (test_bc != "Neumann" and Fk.getGroupName() != "Neumann"
                      ):  #Nothing to do for Neumann boundary condition
                    print Fk.getGroupName()
                    raise ValueError(
                        "computeFluxes: Unknown boundary condition name")

    return implMat
Esempio n. 5
0
def Flux(U):

    result = cdmath.Vector(2)
    result[0] = c0 * c0 * U[1]
    result[1] = U[0]

    return result
def source_term_and_stat_solution_transport_equation(my_mesh,velocity):
    test_desc["Source_term"]="True"
    dim     = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    source_vector = cdmath.Vector(nbCells)

    stat_field = cdmath.Field("Stationary field", cdmath.CELLS, my_mesh, 1)

    for k in range(nbCells):
        x = my_mesh.getCell(k).x()
        y = my_mesh.getCell(k).y()
        z = my_mesh.getCell(k).z()

        if(dim==1):
            source_vector[k] = 2*pi*velocity[0]*cos(2*pi*x)
            stat_field[k]    =                  sin(2*pi*x)
        elif(dim==2):
            source_vector[k*(dim+1)+0] = 2*pi*(velocity[0]*cos(2*pi*x)*sin(2*pi*y)+velocity[1]*sin(2*pi*x)*cos(2*pi*y))
            stat_field[k]   =                              sin(2*pi*x)*sin(2*pi*y)
        elif(dim==3):
            source_vector[k*(dim+1)+0] = 2*pi*(velocity[0]*cos(2*pi*x)*sin(2*pi*y)*sin(2*pi*z)+velocity[1]*sin(2*pi*x)*cos(2*pi*y)*sin(2*pi*z)+velocity[2]*sin(2*pi*x)*sin(2*pi*y)*cos(2*pi*z))
            stat_field[k]   =                              sin(2*pi*x)*sin(2*pi*y)*sin(2*pi*z)

    return source_vector, stat_field
Esempio n. 7
0
def source_term_and_stat_solution_wave_system(my_mesh):
    test_desc["Source_term"] = "True"
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    source_vector = cdmath.Vector(nbCells * (dim + 1))

    stat_pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    stat_momentum_field = cdmath.Field("Momentum", cdmath.CELLS, my_mesh, 3)

    for k in range(nbCells):
        x = my_mesh.getCell(k).x()
        y = my_mesh.getCell(k).y()
        z = my_mesh.getCell(k).z()

        if (dim == 1):
            source_vector[k * (dim + 1) + 0] = -2 * c0 * c0 * sign(x - 1. / 2)
            source_vector[k * (dim + 1) + 1] = 0

            stat_pressure_field[k] = abs(x - 1. / 2) * (x - 1. / 2)
            stat_momentum_field[k, 0] = -2 * abs(x - 1. / 2)
            stat_momentum_field[k, 1] = 0
            stat_momentum_field[k, 2] = 0
        elif (dim == 2):
            source_vector[k * (dim + 1) + 0] = -2 * c0 * c0 * (
                sign(x - 1. / 2) * (y - 1. / 2) * abs(y - 1. / 2) +
                (x - 1. / 2) * abs(x - 1. / 2) * sign(y - 1. / 2))
            source_vector[k * (dim + 1) + 1] = 0
            source_vector[k * (dim + 1) + 2] = 0

            stat_pressure_field[k] = (x - 1. / 2) * abs(x - 1. / 2) * (
                y - 1. / 2) * abs(y - 1. / 2)
            stat_momentum_field[
                k, 0] = -2 * abs(x - 1. / 2) * (y - 1. / 2) * abs(y - 1. / 2)
            stat_momentum_field[
                k, 1] = -2 * (x - 1. / 2) * abs(x - 1. / 2) * abs(y - 1. / 2)
            stat_momentum_field[k, 2] = 0
        elif (dim == 3):
            source_vector[k * (dim + 1) + 0] = -2 * c0 * c0 * (
                sign(x - 1. / 2) * (y - 1. / 2) * abs(y - 1. / 2) *
                (z - 1. / 2) * abs(z - 1. / 2) +
                (x - 1. / 2) * abs(x - 1. / 2) * sign(y - 1. / 2) *
                (z - 1. / 2) * abs(z - 1. / 2) +
                (x - 1. / 2) * abs(x - 1. / 2) *
                (y - 1. / 2) * abs(y - 1. / 2) * sign(z - 1. / 2))
            source_vector[k * (dim + 1) + 1] = 0
            source_vector[k * (dim + 1) + 2] = 0
            source_vector[k * (dim + 1) + 3] = 0

            stat_pressure_field[k] = (x - 1. / 2) * abs(x - 1. / 2) * (
                y - 1. / 2) * abs(y - 1. / 2) * (z - 1. / 2) * abs(z - 1. / 2)
            stat_momentum_field[k, 0] = -2 * abs(x - 1. / 2) * (
                y - 1. / 2) * abs(y - 1. / 2) * (z - 1. / 2) * abs(z - 1. / 2)
            stat_momentum_field[k, 1] = -2 * (x - 1. / 2) * abs(
                x - 1. / 2) * abs(y - 1. / 2) * (z - 1. / 2) * abs(z - 1. / 2)
            stat_momentum_field[k, 2] = -2 * (x - 1. / 2) * abs(x - 1. / 2) * (
                y - 1. / 2) * abs(y - 1. / 2) * abs(z - 1. / 2)

    return source_vector, stat_pressure_field, stat_momentum_field
Esempio n. 8
0
def jacobianMatrices(normale, coeff, rho_l, q_l, rho_r, q_r):
    RoeMat = cdmath.Matrix(3, 3)
    AbsRoeMa = cdmath.Matrix(3, 3)

    tangent = cdmath.Vector(2)
    tangent[0] = normale[1]
    tangent[1] = -normale[0]

    u_l = q_l / rho_l
    u_r = q_r / rho_r
    if rho_l < 0 or rho_r < 0:
        print "rho_l=", rho_l, " rho_r= ", rho_r
        raise ValueError("Negative density")
    u = (u_l * sqrt(rho_l) + u_r * sqrt(rho_r)) / (sqrt(rho_l) + sqrt(rho_r))
    un = u * normale

    RoeMat[0, 0] = 0
    RoeMat[0, 1] = normale[0]
    RoeMat[0, 2] = normale[1]
    RoeMat[1, 0] = c0 * c0 * normale[0] - un * u[0]
    RoeMat[2, 0] = c0 * c0 * normale[1] - un * u[1]
    RoeMat[1, 1] = un + normale[0] * u[0]
    RoeMat[1, 2] = normale[1] * u[0]
    RoeMat[2, 2] = un + normale[1] * u[1]
    RoeMat[2, 1] = normale[0] * u[1]

    AbsRoeMa[0, 0] = (abs(un - c0) * (un + c0) + abs(un + c0) *
                      (c0 - un)) / (2 * c0)
    AbsRoeMa[0, 1] = (abs(un + c0) - abs(un - c0)) / (2 * c0) * normale[0]
    AbsRoeMa[0, 2] = (abs(un + c0) - abs(un - c0)) / (2 * c0) * normale[1]
    AbsRoeMa[1, 0] = (abs(un - c0) * (un + c0) *
                      (u[0] - c0 * normale[0]) - abs(un + c0) * (un - c0) *
                      (u[0] + c0 * normale[0])) / (2 * c0) - abs(un) * (
                          u * tangent) * tangent[0]
    AbsRoeMa[2, 0] = (abs(un - c0) * (un + c0) *
                      (u[1] - c0 * normale[1]) - abs(un + c0) * (un - c0) *
                      (u[1] + c0 * normale[1])) / (2 * c0) - abs(un) * (
                          u * tangent) * tangent[1]
    #subMatrix=(abs(un+c0)*((u-c0*normale)^normale)-abs(un-c0)*((u-c0*normale)^normale))/(2*c0)+abs(un)*(tangent^tangent);
    AbsRoeMa[1, 1] = (abs(un + c0) *
                      ((u[0] - c0 * normale[0]) * normale[0]) - abs(un - c0) *
                      ((u[0] - c0 * normale[0]) * normale[0])) / (
                          2 * c0) + abs(un) * (tangent[0] * tangent[0])
    #subMatrix[0,0];
    AbsRoeMa[1, 2] = (abs(un + c0) *
                      ((u[0] - c0 * normale[0]) * normale[1]) - abs(un - c0) *
                      ((u[0] - c0 * normale[0]) * normale[1])) / (
                          2 * c0) + abs(un) * (tangent[0] * tangent[1])
    #subMatrix[0,1];
    AbsRoeMa[2, 1] = (abs(un + c0) *
                      ((u[1] - c0 * normale[1]) * normale[0]) - abs(un - c0) *
                      ((u[1] - c0 * normale[1]) * normale[0])) / (
                          2 * c0) + abs(un) * (tangent[1] * tangent[0])
    AbsRoeMa[2, 2] = (abs(un + c0) *
                      ((u[1] - c0 * normale[1]) * normale[1]) - abs(un - c0) *
                      ((u[1] - c0 * normale[1]) * normale[1])) / (
                          2 * c0) + abs(un) * (tangent[1] * tangent[1])

    return (RoeMat - AbsRoeMa) * coeff / 2, un
Esempio n. 9
0
def computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, scaling, test_bc):
    nbCells = my_mesh.getNumberOfCells()
    dim = my_mesh.getMeshDimension()
    nbComp = dim + 1
    normal = cdmath.Vector(dim)

    implMat = cdmath.SparseMatrixPetsc(nbCells * nbComp, nbCells * nbComp,
                                       (nbVoisinsMax + 1) * nbComp)

    idMoinsJacCL = cdmath.Matrix(nbComp)

    for j in range(nbCells):  #On parcourt les cellules
        Cj = my_mesh.getCell(j)
        nbFaces = Cj.getNumberOfFaces()

        for k in range(nbFaces):
            indexFace = Cj.getFacesId()[k]
            Fk = my_mesh.getFace(indexFace)
            for i in range(dim):
                normal[i] = Cj.getNormalVector(k, i)
                #normale sortante

            Am = jacobianMatrices(normal,
                                  dt * Fk.getMeasure() / Cj.getMeasure(),
                                  scaling)

            cellAutre = -1
            if (not Fk.isBorder()):
                # hypothese: La cellule d'index indexC1 est la cellule courante index j */
                if (Fk.getCellsId()[0] == j):
                    # hypothese verifiée
                    cellAutre = Fk.getCellsId()[1]
                elif (Fk.getCellsId()[1] == j):
                    # hypothese non verifiée
                    cellAutre = Fk.getCellsId()[0]
                else:
                    raise ValueError(
                        "computeFluxes: problem with mesh, unknown cell number"
                    )

                implMat.addValue(j * nbComp, cellAutre * nbComp, Am)
                implMat.addValue(j * nbComp, j * nbComp, Am * (-1.))
            else:
                indexFP = my_mesh.getIndexFacePeriodic(
                    indexFace,
                    my_mesh.getName() == "squareWithBrickWall",
                    my_mesh.getName() == "squareWithHexagons")
                Fp = my_mesh.getFace(indexFP)
                cellAutre = Fp.getCellsId()[0]

                implMat.addValue(j * nbComp, cellAutre * nbComp, Am)
                implMat.addValue(j * nbComp, j * nbComp, Am * (-1.))

    return implMat
Esempio n. 10
0
def Flux(U, normal):
    dim=normal.size()

    result=cdmath.Vector(dim+1)
    for i in range(dim):
        result[0]  +=normal[i]*U[i+1]
        result[i+1] =normal[i]*U[0]
        
    result[0]=c0*c0*result[0]
    
    return result
Esempio n. 11
0
def gradientNodal(M, values):
    matrices = [0] * (len(values) - 1)
    for i in range(len(values) - 1):
        matrices[i] = M.deepCopy()
        for j in range(len(values)):
            matrices[i][j, i] = values[j]

    result = cdmath.Vector(len(values) - 1)
    for i in range(len(values) - 1):
        result[i] = matrices[i].determinant()

    return result
def source_term_and_stat_solution_wave_system(my_mesh):
    test_desc["Source_term"] = "True"
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    source_vector = cdmath.Vector(nbCells * (dim + 1))

    stat_pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
    stat_velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)

    for k in range(nbCells):
        x = my_mesh.getCell(k).x()
        y = my_mesh.getCell(k).y()
        z = my_mesh.getCell(k).z()

        if (dim == 1):
            source_vector[k * (dim + 1) +
                          0] = c0 * c0 * 4 * pi * pi * sin(2 * pi * x)
            source_vector[k * (dim + 1) + 1] = 0

            stat_pressure_field[k] = sin(2 * pi * x)
            stat_velocity_field[k, 0] = -2 * pi * cos(2 * pi * x) / rho0
            stat_velocity_field[k, 1] = 0
            stat_velocity_field[k, 2] = 0
        elif (dim == 2):
            source_vector[k * (dim + 1) + 0] = 2 * c0 * c0 * 4 * pi * pi * sin(
                2 * pi * x) * sin(2 * pi * y)
            source_vector[k * (dim + 1) + 1] = 0
            source_vector[k * (dim + 1) + 2] = 0

            stat_pressure_field[k] = sin(2 * pi * x) * sin(2 * pi * y)
            stat_velocity_field[k, 0] = -2 * pi * cos(2 * pi * x) * sin(
                2 * pi * y) / rho0
            stat_velocity_field[k, 1] = -2 * pi * sin(2 * pi * x) * cos(
                2 * pi * y) / rho0
            stat_velocity_field[k, 2] = 0
        elif (dim == 3):
            source_vector[k * (dim + 1) + 0] = 3 * c0 * c0 * 4 * pi * pi * sin(
                2 * pi * x) * sin(2 * pi * y) * sin(2 * pi * z)
            source_vector[k * (dim + 1) + 1] = 0
            source_vector[k * (dim + 1) + 2] = 0
            source_vector[k * (dim + 1) + 3] = 0

            stat_pressure_field[k] = sin(2 * pi * x) * sin(2 * pi * y) * sin(
                2 * pi * z)
            stat_velocity_field[k, 0] = -2 * pi * cos(2 * pi * x) * sin(
                2 * pi * y) * sin(2 * pi * z) / rho0
            stat_velocity_field[k, 1] = -2 * pi * sin(2 * pi * x) * cos(
                2 * pi * y) * sin(2 * pi * z) / rho0
            stat_velocity_field[k, 2] = -2 * pi * sin(2 * pi * x) * sin(
                2 * pi * y) * cos(2 * pi * z) / rho0

    return source_vector, stat_pressure_field, stat_velocity_field
Esempio n. 13
0
def computeFluxes(U, SumFluxes):
    my_mesh = U.getMesh()
    nbCells = my_mesh.getNumberOfCells()
    dim = my_mesh.getMeshDimension()
    nbComp = U.getNumberOfComponents()
    Fj = cdmath.Vector(nbComp)
    Fjp1 = cdmath.Vector(nbComp)
    Fjm1 = cdmath.Vector(nbComp)
    Uj = cdmath.Vector(nbComp)
    Ujp1 = cdmath.Vector(nbComp)
    Ujm1 = cdmath.Vector(nbComp)
    normal = cdmath.Vector(dim)
    sumFluxCourant = cdmath.Vector(nbComp)
    sumFluxCourant2 = cdmath.Vector(nbComp)

    A, absA = jacobianMatrices()

    for j in range(nbCells):  #On parcourt les cellules
        Cj = my_mesh.getCell(j)

        for i in range(nbComp):
            Uj[i] = U[j, i]
            sumFluxCourant[i] = 0

        if (j == 0):
            for i in range(nbComp):
                Ujp1[i] = U[j + 1, i]
                Ujm1[i] = U[j, i]
        elif (j == nbCells - 1):
            for i in range(nbComp):
                Ujp1[i] = U[j, i]
                Ujm1[i] = U[j - 1, i]
        else:
            for i in range(nbComp):
                Ujp1[i] = U[j + 1, i]
                Ujm1[i] = U[j - 1, i]

        Fr = numericalFlux(Uj, Ujp1, absA)
        Fl = numericalFlux(Ujm1, Uj, absA)

        sumFluxCourant = (Fr - Fl) * 0.5 / Cj.getMeasure()

        #On divise par le volume de la cellule la contribution des flux au snd membre
        for i in range(nbComp):
            SumFluxes[j, i] = sumFluxCourant[i]
Esempio n. 14
0
def computeFluxes(U, SumFluxes):
    my_mesh =U.getMesh();
    nbCells = my_mesh.getNumberOfCells();
    dim=my_mesh.getMeshDimension();
    nbComp=U.getNumberOfComponents();
    Fj=cdmath.Vector(nbComp)
    Fjp1=cdmath.Vector(nbComp)
    Fjm1=cdmath.Vector(nbComp)
    Uj=cdmath.Vector(nbComp)
    Ujp1=cdmath.Vector(nbComp)
    Ujm1=cdmath.Vector(nbComp)
    normal=cdmath.Vector(dim)
    sumFluxCourant=cdmath.Vector(nbComp)

    A, absA=jacobianMatrices();

    for j in range(nbCells):#On parcourt les cellules
        for i in range(nbComp) :
            Uj[i]=U[j,i];
            sumFluxCourant[i]=0;

        test_desc["Boundary_conditions"]="Neumann"
        if ( j==0) :
            for i in range(nbComp) :
                Ujp1[i]=U[j+1,i];
                Ujm1[i]=U[j  ,i];
        elif ( j==nbCells-1) :
            for i in range(nbComp) :
                Ujp1[i]=U[j  ,i];
                Ujm1[i]=U[j-1,i];
        else :
            for i in range(nbComp) :
                Ujp1[i]=U[j+1,i];
                Ujm1[i]=U[j-1,i];
            
        Fr=numericalFlux(Uj,Ujp1,absA)
        Fl=numericalFlux(Ujm1,Uj,absA)

        sumFluxCourant = (Fr - Fl)*0.5/Cj.getMeasure()
            
            Fcourant=Flux(Ucourant,normal);
            Fautre  =Flux(Uautre,  normal);

            A, absA=jacobianMatrices( normal);
            
            sumFluxCourant = sumFluxCourant + (Fcourant+Fautre +absA*(Ucourant-Uautre))*Fk.getMeasure()*0.5

        #On divise par le volume de la cellule la contribution des flux au snd membre
        for i in range(nbComp):
            SumFluxes[j,i]=sumFluxCourant[i];
Esempio n. 15
0
def solve(my_mesh, meshName, resolution, meshType, cfl, test_bc):
    print "Resolution of the Transport Equation in dimension ", my_mesh.getMeshDimension(
    )
    print "Numerical method : ", "Upwind"
    print "Initial data : ", "Spherical shock"
    print "Mesh name : ", meshName, ", ", my_mesh.getNumberOfCells(), " cells"

    # Problem data
    tmax = 10000.
    ntmax = 30000
    output_freq = 1000

    isImplicit = True

    dim = my_mesh.getMeshDimension()
    velocity = cdmath.Vector(dim)
    for i in range(dim):
        velocity[i] = 1

    nbCells, t_final, ndt_final, max_unknown, diag_data_u = TransportEquationVF(
        ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution, test_bc,
        velocity, isImplicit)

    return nbCells, t_final, ndt_final, max_unknown, diag_data_u
Esempio n. 16
0
def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit):
    dim=my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()
    meshName=my_mesh.getName()
    
    dt = 0.
    time = 0.
    it=0;
    isStationary=False;
    nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS)

    # Initial conditions #
    print("Construction of the initial condition …")
    if(filename.find("square")>-1 or filename.find("Square")>-1 or filename.find("cube")>-1 or filename.find("Cube")>-1):
        pressure_field, velocity_field = initial_conditions_square_vortex(my_mesh)
    elif(filename.find("disk")>-1 or filename.find("Disk")>-1):
        pressure_field, velocity_field = initial_conditions_disk_vortex(my_mesh)
    else:
        print "Mesh name : ", filename
        raise ValueError("Mesh name should contain substring square, cube or disk")

    #iteration vectors
    Un =cdmath.Vector(nbCells*(dim+1))
    dUn=cdmath.Vector(nbCells*(dim+1))
    
    for k in range(nbCells):
        Un[k*(dim+1)+0] =     pressure_field[k]
        Un[k*(dim+1)+1] =rho0*velocity_field[k,0]
        Un[k*(dim+1)+2] =rho0*velocity_field[k,1]
        if(dim==3):
            Un[k*(dim+1)+3] =rho0*velocity_field[k,2]

    #sauvegarde de la donnée initiale
    pressure_field.setTime(time,it);
    pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure");
    velocity_field.setTime(time,it);
    velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity");

    dx_min=my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0
    
    divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt)
    if( isImplicit):
        #Adding the identity matrix on the diagonal
        divMat.diagonalShift(1)#only after  filling all coefficients
        
        iterGMRESMax=50
        LS=cdmath.LinearSolver(divMat,Un,iterGMRESMax, precision, "GMRES","ILU")

        LS.setComputeConditionNumber()
        
    print("Starting computation of the linear wave system with an UPWIND scheme …")
    
    print "coucou2"
    # Starting time loop
    while (it<ntmax and time <= tmax and not isStationary):
        if(isImplicit):
            dUn=Un.deepCopy()
            LS.setSndMember(Un)
            Un=LS.solve();
            if(not LS.getStatus()):
                print "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations"
                raise ValueError("Pas de convergence du système linéaire");
            dUn-=Un

        else:
            dUn=divMat*Un
            Un-=dUn
        
        time=time+dt;
        it=it+1;
 
        #Sauvegardes
        if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
            print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))

            for k in range(nbCells):
                pressure_field[k]  =Un[k*(dim+1)+0]
                velocity_field[k,0]=Un[k*(dim+1)+1]/rho0
                if(dim>1):
                    velocity_field[k,1]=Un[k*(dim+1)+2]/rho0
                    if(dim>2):
                        velocity_field[k,2]=Un[k*(dim+1)+3]/rho0

            pressure_field.setTime(time,it);
            pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure",False);
            velocity_field.setTime(time,it);
            velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity",False);

    print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
    print

    if(it>=ntmax):
        print "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint"
    elif(isStationary):
        print "Régime stationnaire atteint au pas de temps ", it, ", t= ", time

        pressure_field.setTime(time,0);
        pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat");
        velocity_field.setTime(time,0);
        velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat");

        #Postprocessing : Extraction of the diagonal data
        diag_data_press=VTK_routines.Extract_field_data_over_line_to_numpyArray(pressure_field,[0,1,0],[1,0,0], resolution)    
        diag_data_vel  =VTK_routines.Extract_field_data_over_line_to_numpyArray(velocity_field,[0,1,0],[1,0,0], resolution)    
        #Postprocessing : save 2D picture
        PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat")
        PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat")
        
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
def solve(filename,resolution,meshType, testColor):
    start = time.time()
    test_desc["Mesh_type"]=meshType
    test_desc["Test_color"]=testColor
    
    #Chargement du maillage triangulaire de la sphère
    #=======================================================================================
    my_mesh = cdmath.Mesh(filename+".med")
    if(not my_mesh.isTriangular()) :
        raise ValueError("Wrong cell types : mesh is not made of triangles")
    if(my_mesh.getMeshDimension()!=2) :
        raise ValueError("Wrong mesh dimension : expected a surface of dimension 2")
    if(my_mesh.getSpaceDimension()!=3) :
        raise ValueError("Wrong space dimension : expected a space of dimension 3")
    
    nbNodes = my_mesh.getNumberOfNodes()
    nbCells = my_mesh.getNumberOfCells()
    
    test_desc["Space_dimension"]=my_mesh.getSpaceDimension()
    test_desc["Mesh_dimension"]=my_mesh.getMeshDimension()
    test_desc["Mesh_number_of_elements"]=my_mesh.getNumberOfNodes()
    test_desc["Mesh_cell_type"]=my_mesh.getElementTypes()

    print("Mesh building/loading done")
    print("nb of nodes=", nbNodes)
    print("nb of cells=", nbCells)
    
    #Discrétisation du second membre et détermination des noeuds intérieurs
    #======================================================================
    my_RHSfield = cdmath.Field("RHS_field", cdmath.NODES, my_mesh, 1)
    maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
    
    #parcours des noeuds pour discrétisation du second membre et extraction du nb max voisins d'un noeud
    for i in range(nbNodes):
        Ni=my_mesh.getNode(i)
        x = Ni.x()
        y = Ni.y()
        z = Ni.z()
    
        my_RHSfield[i]=12*y*(3*x*x-y*y)/pow(x*x+y*y+z*z,3/2)#vecteur propre du laplacien sur la sphère
        if my_mesh.isBorderNode(i): # Détection des noeuds frontière
            raise ValueError("Mesh should not contain borders")
        else:
            maxNbNeighbours = max(1+Ni.getNumberOfCells(),maxNbNeighbours)
    
    test_desc["Mesh_max_number_of_neighbours"]=maxNbNeighbours

    print("Right hand side discretisation done")
    print("Max nb of neighbours=", maxNbNeighbours)
    print("Integral of the RHS", my_RHSfield.integral(0))
    
    # Construction de la matrice de rigidité et du vecteur second membre du système linéaire
    #=======================================================================================
    Rigidite=cdmath.SparseMatrixPetsc(nbNodes,nbNodes,maxNbNeighbours)# warning : third argument is number of non zero coefficients per line
    RHS=cdmath.Vector(nbNodes)
    
    # Vecteurs gradient de la fonction de forme associée à chaque noeud d'un triangle
    GradShapeFunc0=cdmath.Vector(3)
    GradShapeFunc1=cdmath.Vector(3)
    GradShapeFunc2=cdmath.Vector(3)
    
    normalFace0=cdmath.Vector(3)
    normalFace1=cdmath.Vector(3)
    
    #On parcourt les triangles du domaine
    for i in range(nbCells):
    
        Ci=my_mesh.getCell(i)
    
        #Contribution à la matrice de rigidité
        nodeId0=Ci.getNodeId(0)
        nodeId1=Ci.getNodeId(1)
        nodeId2=Ci.getNodeId(2)
        N0=my_mesh.getNode(nodeId0)
        N1=my_mesh.getNode(nodeId1)
        N2=my_mesh.getNode(nodeId2)
    
        #Build normal to cell Ci
        normalFace0[0]=Ci.getNormalVector(0,0)
        normalFace0[1]=Ci.getNormalVector(0,1)
        normalFace0[2]=Ci.getNormalVector(0,2)
        normalFace1[0]=Ci.getNormalVector(1,0)
        normalFace1[1]=Ci.getNormalVector(1,1)
        normalFace1[2]=Ci.getNormalVector(1,2)
    
        normalCell = normalFace0.crossProduct(normalFace1)
        test = normalFace0.tensProduct(normalFace1)
        normalCell = normalCell/normalCell.norm()
    
        cellMat=cdmath.Matrix(4)
        cellMat[0,0]=N0.x()
        cellMat[0,1]=N0.y()
        cellMat[0,2]=N0.z()
        cellMat[1,0]=N1.x()
        cellMat[1,1]=N1.y()
        cellMat[1,2]=N1.z()
        cellMat[2,0]=N2.x()
        cellMat[2,1]=N2.y()
        cellMat[2,2]=N2.z()
        cellMat[3,0]=normalCell[0]
        cellMat[3,1]=normalCell[1]
        cellMat[3,2]=normalCell[2]
        cellMat[0,3]=1
        cellMat[1,3]=1
        cellMat[2,3]=1
        cellMat[3,3]=0
    
        #Formule des gradients voir EF P1 -> calcul déterminants
        GradShapeFunc0[0]= cellMat.partMatrix(0,0).determinant()/2
        GradShapeFunc0[1]=-cellMat.partMatrix(0,1).determinant()/2
        GradShapeFunc0[2]= cellMat.partMatrix(0,2).determinant()/2
        GradShapeFunc1[0]=-cellMat.partMatrix(1,0).determinant()/2
        GradShapeFunc1[1]= cellMat.partMatrix(1,1).determinant()/2
        GradShapeFunc1[2]=-cellMat.partMatrix(1,2).determinant()/2
        GradShapeFunc2[0]= cellMat.partMatrix(2,0).determinant()/2
        GradShapeFunc2[1]=-cellMat.partMatrix(2,1).determinant()/2
        GradShapeFunc2[2]= cellMat.partMatrix(2,2).determinant()/2
    
        #Création d'un tableau (numéro du noeud, gradient de la fonction de forme
        GradShapeFuncs={nodeId0 : GradShapeFunc0}
        GradShapeFuncs[nodeId1]=GradShapeFunc1
        GradShapeFuncs[nodeId2]=GradShapeFunc2
    
        # Remplissage de  la matrice de rigidité et du second membre
        for j in [nodeId0,nodeId1,nodeId2] : 
            #Ajout de la contribution de la cellule triangulaire i au second membre du noeud j 
            RHS[j]=Ci.getMeasure()/3*my_RHSfield[j]+RHS[j] # intégrale dans le triangle du produit f x fonction de base
            #Contribution de la cellule triangulaire i à la ligne j du système linéaire
            for k in [nodeId0,nodeId1,nodeId2] : 
                Rigidite.addValue(j,k,GradShapeFuncs[j]*GradShapeFuncs[k]/Ci.getMeasure())
    
    print("Linear system matrix building done")
    
    # Résolution du système linéaire
    #=================================
    LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-2,"CG","ILU")#Remplacer CG par CHOLESKY pour solveur direct
    LS.isSingular()#En raison de l'absence de bord
    LS.setComputeConditionNumber()
    SolSyst=LS.solve()

    print "Preconditioner used : ", LS.getNameOfPc()
    print "Number of iterations used : ", LS.getNumberOfIter()
    print "Final residual : ", LS.getResidu()
    print("Linear system solved")
    
    test_desc["Linear_solver_algorithm"]=LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"]=LS.getNameOfPc()
    test_desc["Linear_solver_precision"]=LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"]=LS.getNumberMaxOfIter()
    test_desc["Linear_system_max_actual_iterations_number"]=LS.getNumberOfIter()
    test_desc["Linear_system_max_actual_error"]=LS.getResidu()
    test_desc["Linear_system_max_actual_condition number"]=LS.getConditionNumber()

    # Création du champ résultat
    #===========================
    my_ResultField = cdmath.Field("ResultField", cdmath.NODES, my_mesh, 1)
    for j in range(nbNodes):
        my_ResultField[j]=SolSyst[j];#remplissage des valeurs pour les noeuds intérieurs
    #sauvegarde sur le disque dur du résultat dans un fichier paraview
    my_ResultField.writeVTK("FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes))
    
    end = time.time()

    print("Integral of the numerical solution", my_ResultField.integral(0))
    print("Numerical solution of poisson equation on a sphere using finite elements done")
    
    #Calcul de l'erreur commise par rapport à la solution exacte
    #===========================================================
    #The following formulas use the fact that the exact solution is equal the right hand side divided by 12
    max_abs_sol_exacte=0
    erreur_abs=0
    max_sol_num=0
    min_sol_num=0
    for i in range(nbNodes) :
        if max_abs_sol_exacte < abs(my_RHSfield[i]) :
            max_abs_sol_exacte = abs(my_RHSfield[i])
        if erreur_abs < abs(my_RHSfield[i]/12 - my_ResultField[i]) :
            erreur_abs = abs(my_RHSfield[i]/12 - my_ResultField[i])
        if max_sol_num < my_ResultField[i] :
            max_sol_num = my_ResultField[i]
        if min_sol_num > my_ResultField[i] :
            min_sol_num = my_ResultField[i]
    max_abs_sol_exacte = max_abs_sol_exacte/12
    
    print("Absolute error = max(| exact solution - numerical solution |) = ",erreur_abs )
    print("Relative error = max(| exact solution - numerical solution |)/max(| exact solution |) = ",erreur_abs/max_abs_sol_exacte)
    print ("Maximum numerical solution = ", max_sol_num, " Minimum numerical solution = ", min_sol_num)

    test_desc["Computational_time_taken_by_run"]=end-start
    test_desc["Absolute_error"]=erreur_abs
    test_desc["Relative_error"]=erreur_abs/max_abs_sol_exacte

    #Postprocessing : 
    #================
    # save 3D picture
    PV_routines.Save_PV_data_to_picture_file("FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes)+'_0.vtu',"ResultField",'NODES',"FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes))
    # save 3D clip
    VTK_routines.Clip_VTK_data_to_VTK("FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes)+'_0.vtu',"Clip_VTK_data_to_VTK_"+ "FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes)+'_0.vtu',[0.25,0.25,0.25], [-0.5,-0.5,-0.5],resolution )
    PV_routines.Save_PV_data_to_picture_file("Clip_VTK_data_to_VTK_"+"FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes)+'_0.vtu',"ResultField",'NODES',"Clip_VTK_data_to_VTK_"+"FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes))
    # save plot around circumference
    finiteElementsOnSphere_0vtu = pvs.XMLUnstructuredGridReader(FileName=["FiniteElementsOnSpherePoisson_"+meshType+str(nbNodes)+'_0.vtu'])
    slice1 = pvs.Slice(Input=finiteElementsOnSphere_0vtu)
    slice1.SliceType.Normal = [0.5, 0.5, 0.5]
    renderView1 = pvs.GetActiveViewOrCreate('RenderView')
    finiteElementsOnSphere_0vtuDisplay = pvs.Show(finiteElementsOnSphere_0vtu, renderView1)
    pvs.ColorBy(finiteElementsOnSphere_0vtuDisplay, ('POINTS', 'ResultField'))
    slice1Display = pvs.Show(slice1, renderView1)
    pvs.SaveScreenshot("./FiniteElementsOnSpherePoisson"+"_Slice_"+meshType+str(nbNodes)+'.png', magnification=1, quality=100, view=renderView1)
    plotOnSortedLines1 = pvs.PlotOnSortedLines(Input=slice1)
    pvs.SaveData('./FiniteElementsOnSpherePoisson_PlotOnSortedLines'+meshType+str(nbNodes)+'.csv', proxy=plotOnSortedLines1)
    lineChartView2 = pvs.CreateView('XYChartView')
    plotOnSortedLines1Display = pvs.Show(plotOnSortedLines1, lineChartView2)
    plotOnSortedLines1Display.UseIndexForXAxis = 0
    plotOnSortedLines1Display.XArrayName = 'arc_length'
    plotOnSortedLines1Display.SeriesVisibility = ['ResultField (1)']
    pvs.SaveScreenshot("./FiniteElementsOnSpherePoisson"+"_PlotOnSortedLine_"+meshType+str(nbNodes)+'.png', magnification=1, quality=100, view=lineChartView2)
    pvs.Delete(lineChartView2)

    with open('test_Poisson'+str(my_mesh.getMeshDimension())+'D_EF_'+meshType+str(nbCells)+ "Cells.json", 'w') as outfile:  
        json.dump(test_desc, outfile)

    return erreur_abs/max_abs_sol_exacte, nbNodes, min_sol_num, max_sol_num, end - start
        nbInteriorNodes = nbInteriorNodes + 1
        maxNbNeighbours = max(
            1 + Ni.getNumberOfCells(), maxNbNeighbours
        )  #true only in 2D, otherwise use function Ni.getNumberOfEdges()

print("Right hand side discretisation done")
print("Number of interior nodes=", nbInteriorNodes)
print("Number of boundary nodes=", nbBoundaryNodes)
print("Maximum number of neighbours=", maxNbNeighbours)

# Construction de la matrice de rigidité et du vecteur second membre du système linéaire
#=======================================================================================
Rigidite = cdmath.SparseMatrixPetsc(
    nbInteriorNodes, nbInteriorNodes, maxNbNeighbours
)  # warning : third argument is max number of non zero coefficients per line of the matrix
RHS = cdmath.Vector(nbInteriorNodes)

# Vecteurs gradient de la fonction de forme associée à chaque noeud d'un triangle (hypothèse 2D)
GradShapeFunc0 = cdmath.Vector(2)
GradShapeFunc1 = cdmath.Vector(2)
GradShapeFunc2 = cdmath.Vector(2)

#On parcourt les triangles du domaine
for i in range(nbCells):

    Ci = my_mesh.getCell(i)

    #Contribution à la matrice de rigidité
    nodeId0 = Ci.getNodeId(0)
    nodeId1 = Ci.getNodeId(1)
    nodeId2 = Ci.getNodeId(2)
Esempio n. 19
0
def solve(my_mesh, filename, resolution, meshType, testColor):
    start = time.time()
    test_desc["Mesh_type"] = meshType
    test_desc["Test_color"] = testColor

    nbCells = my_mesh.getNumberOfCells()

    if (my_mesh.getSpaceDimension() != 2 or my_mesh.getMeshDimension() != 2):
        raise ValueError(
            "Wrong space or mesh dimension : space and mesh dimensions should be 2"
        )

    test_desc["Space_dimension"] = my_mesh.getSpaceDimension()
    test_desc["Mesh_dimension"] = my_mesh.getMeshDimension()
    test_desc["Mesh_number_of_elements"] = my_mesh.getNumberOfCells()
    test_desc["Mesh_cell_type"] = my_mesh.getElementTypesNames()

    print("Mesh groups done")
    print("Number of cells  = ", nbCells)

    #Discrétisation du second membre et extraction du nb max de voisins d'une cellule
    #================================================================================
    my_RHSfield = cdmath.Field("RHS_field", cdmath.CELLS, my_mesh, 1)
    maxNbNeighbours = 0  #This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
    #parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule
    for i in range(nbCells):
        Ci = my_mesh.getCell(i)
        x = Ci.x()
        y = Ci.y()

        my_RHSfield[i] = 2 * pi * pi * sin(pi * x) * sin(
            pi * y)  #mettre la fonction definie au second membre de l edp
        # compute maximum number of neighbours
        maxNbNeighbours = max(1 + Ci.getNumberOfFaces(), maxNbNeighbours)

    test_desc["Mesh_max_number_of_neighbours"] = maxNbNeighbours

    print("Right hand side discretisation done")
    print("Max nb of neighbours=", maxNbNeighbours)

    # Construction de la matrice et du vecteur second membre du système linéaire
    #===========================================================================
    Rigidite = cdmath.SparseMatrixPetsc(
        nbCells, nbCells, maxNbNeighbours
    )  # warning : third argument is maximum number of non zero coefficients per line of the matrix
    RHS = cdmath.Vector(nbCells)
    #Parcours des cellules du domaine
    for i in range(nbCells):
        RHS[i] = my_RHSfield[
            i]  #la valeur moyenne du second membre f dans la cellule i
        Ci = my_mesh.getCell(i)
        for j in range(Ci.getNumberOfFaces()):  # parcours des faces voisinnes
            Fj = my_mesh.getFace(Ci.getFaceId(j))
            if not Fj.isBorder():
                k = Fj.getCellId(0)
                if k == i:
                    k = Fj.getCellId(1)
                Ck = my_mesh.getCell(k)
                distance = Ci.getBarryCenter().distance(Ck.getBarryCenter())
                coeff = Fj.getMeasure() / Ci.getMeasure() / distance
                Rigidite.setValue(i, k, -coeff)  # terme extradiagonal
            else:
                coeff = Fj.getMeasure() / Ci.getMeasure() / Ci.getBarryCenter(
                ).distance(Fj.getBarryCenter())
                #For the particular case where the mesh boundary does not coincide with the domain boundary
                x = Fj.getBarryCenter().x()
                y = Fj.getBarryCenter().y()
                RHS[i] += coeff * sin(pi * x) * sin(
                    pi * y
                )  #mettre ici la condition limite du problème de Dirichlet
            Rigidite.addValue(i, i, coeff)  # terme diagonal

    print("Linear system matrix building done")

    # Résolution du système linéaire
    #=================================
    LS = cdmath.LinearSolver(Rigidite, RHS, 500, 1.E-6, "CG", "LU")
    LS.setComputeConditionNumber()
    SolSyst = LS.solve()

    print "Preconditioner used : ", LS.getNameOfPc()
    print "Number of iterations used : ", LS.getNumberOfIter()
    print("Linear system solved")

    test_desc["Linear_solver_algorithm"] = LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"] = LS.getNameOfPc()
    test_desc["Linear_solver_precision"] = LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"] = LS.getNumberMaxOfIter()
    test_desc[
        "Linear_system_max_actual_iterations_number"] = LS.getNumberOfIter()
    test_desc["Linear_system_max_actual_error"] = LS.getResidu()
    test_desc[
        "Linear_system_max_actual_condition number"] = LS.getConditionNumber()

    # Création du champ résultat
    #===========================
    my_ResultField = cdmath.Field("ResultField", cdmath.CELLS, my_mesh, 1)
    for i in range(nbCells):
        my_ResultField[i] = SolSyst[i]
    #sauvegarde sur le disque dur du résultat dans un fichier paraview
    my_ResultField.writeVTK("FiniteVolumes2DPoisson_SQUARE_" + meshType +
                            str(nbCells))

    print(
        "Numerical solution of 2D Poisson equation on a square using finite elements done"
    )

    end = time.time()

    #Calcul de l'erreur commise par rapport à la solution exacte
    #===========================================================
    #The following formulas use the fact that the exact solution is equal the right hand side divided by 2*pi*pi
    max_abs_sol_exacte = max(my_RHSfield.max(),
                             -my_RHSfield.min()) / (2 * pi * pi)
    max_sol_num = my_ResultField.max()
    min_sol_num = my_ResultField.min()
    erreur_abs = 0
    for i in range(nbCells):
        if erreur_abs < abs(my_RHSfield[i] /
                            (2 * pi * pi) - my_ResultField[i]):
            erreur_abs = abs(my_RHSfield[i] / (2 * pi * pi) -
                             my_ResultField[i])

    print(
        "Relative error = max(| exact solution - numerical solution |)/max(| exact solution |) = ",
        erreur_abs / max_abs_sol_exacte)
    print("Maximum numerical solution = ", max_sol_num,
          " Minimum numerical solution = ", min_sol_num)

    #Postprocessing :
    #================
    # Extraction of the diagonal data
    diag_data = VTK_routines.Extract_field_data_over_line_to_numpyArray(
        my_ResultField, [0, 1, 0], [1, 0, 0], resolution)
    # save 2D picture
    PV_routines.Save_PV_data_to_picture_file(
        "FiniteVolumes2DPoisson_SQUARE_" + meshType + str(nbCells) + '_0.vtu',
        "ResultField", 'CELLS',
        "FiniteVolumes2DPoisson_SQUARE_" + meshType + str(nbCells))

    test_desc["Computational_time_taken_by_run"] = end - start
    test_desc["Absolute_error"] = erreur_abs
    test_desc["Relative_error"] = erreur_abs / max_abs_sol_exacte

    with open(
            'test_Poisson' + str(my_mesh.getMeshDimension()) + 'D_VF_' +
            str(nbCells) + "Cells.json", 'w') as outfile:
        json.dump(test_desc, outfile)

    return erreur_abs / max_abs_sol_exacte, nbCells, diag_data, min_sol_num, max_sol_num, end - start
Esempio n. 20
0
def WaveSystemVF(ntmax,
                 tmax,
                 cfl,
                 my_mesh,
                 output_freq,
                 meshName,
                 resolution,
                 scaling,
                 test_bc,
                 with_source=False):
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    dt = 0.
    time = 0.
    it = 0
    isStationary = False

    nbVoisinsMax = my_mesh.getMaxNbNeighbours(cdmath.CELLS)
    isImplicit = scaling > 0

    #iteration vectors
    Un = cdmath.Vector(nbCells * (dim + 1))
    dUn = cdmath.Vector(nbCells * (dim + 1))

    # Initial conditions #
    print("Construction of the initial condition …")
    if (with_source):  #Trivial initial datum
        if (meshName.find("square") == -1 and meshName.find("Square") == -1):
            raise ValueError(
                "Mesh name should contain substring square to use wave system with source term"
            )
        pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
        velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)
        for k in range(nbCells):  # fields initialisation
            pressure_field[k] = 0
            velocity_field[k, 0] = 0
            velocity_field[k, 1] = 0
            velocity_field[k, 2] = 0
        S, stat_pressure, stat_velocity = source_term_and_stat_solution_wave_system(
            my_mesh)
    else:  #The initial datum is a stationary field
        if (meshName.find("square") > -1 or meshName.find("Square") > -1
                or meshName.find("cube") > -1 or meshName.find("Cube") > -1):
            pressure_field, velocity_field = initial_conditions_square_vortex(
                my_mesh)
            stat_pressure, stat_velocity = initial_conditions_square_vortex(
                my_mesh)
        elif (meshName.find("disk") > -1 or meshName.find("Disk") > -1):
            pressure_field, velocity_field = initial_conditions_disk_vortex(
                my_mesh)
            stat_pressure, stat_velocity = initial_conditions_disk_vortex(
                my_mesh)
        else:
            print("Mesh name : ", meshName)
            raise ValueError(
                "Mesh name should contain substring square, cube or disk")
        S = cdmath.Vector(nbCells * (dim + 1))  #source term is zero

    for k in range(nbCells):
        Un[k * (dim + 1) + 0] = pressure_field[k]
        Un[k * (dim + 1) + 1] = rho0 * velocity_field[k, 0]
        Un[k * (dim + 1) + 2] = rho0 * velocity_field[k, 1]
        if (dim == 3):
            Un[k * (dim + 1) + 3] = rho0 * velocity_field[k, 2]

    if (scaling == 1):
        Vn = Un.deepCopy()
        for k in range(nbCells):
            Vn[k * (dim + 1) + 0] = Vn[k * (dim + 1) + 0] / (c0 * c0)
            S[k * (dim + 1) + 0] = S[k * (dim + 1) + 0] / (c0 * c0)
    elif (scaling == 2):
        Vn = Un.deepCopy()
        for k in range(nbCells):
            Vn[k * (dim + 1) + 0] = Vn[k * (dim + 1) + 0] / c0
            S[k * (dim + 1) + 0] = S[k * (dim + 1) + 0] / c0

    #sauvegarde de la donnée initiale
    pressure_field.setTime(time, it)
    pressure_field.writeVTK("WaveSystem" + str(dim) + "DUpwind" + meshName +
                            "_pressure")
    velocity_field.setTime(time, it)
    velocity_field.writeVTK("WaveSystem" + str(dim) + "DUpwind" + meshName +
                            "_velocity")
    #Postprocessing : save 2D picture
    PV_routines.Save_PV_data_to_picture_file(
        "WaveSystem" + str(dim) + "DUpwind" + meshName + "_pressure" +
        '_0.vtu', "Pressure", 'CELLS',
        "WaveSystem" + str(dim) + "DUpwind" + meshName + "_pressure_initial")
    PV_routines.Save_PV_data_to_picture_file(
        "WaveSystem" + str(dim) + "DUpwind" + meshName + "_velocity" +
        '_0.vtu', "Velocity", 'CELLS',
        "WaveSystem" + str(dim) + "DUpwind" + meshName + "_velocity_initial")

    total_pressure_initial = pressure_field.integral(
    )  #For conservation test later
    total_velocity_initial = velocity_field.integral(
    )  #For conservation test later

    dx_min = my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0

    divMat = computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, scaling,
                                     test_bc)
    #Adding the momentum friction term
    if (with_source):
        for j in range(nbCells):
            for i in range(dim):
                divMat.addValue(j * (dim + 1) + 1 + i,
                                j * (dim + 1) + 1 + i, dt)

    if (isImplicit):
        #Adding the identity matrix on the diagonal
        if (scaling == 0 or scaling == 2):
            divMat.diagonalShift(1)  #only after  filling all coefficients
            #for j in range(nbCells*(dim+1)):
            #    divMat.addValue(j,j,1)
        else:
            for j in range(nbCells):
                divMat.addValue(j * (dim + 1), j * (dim + 1),
                                1 / (c0 * c0))  #/(c0*c0)
                for i in range(dim):
                    divMat.addValue(j * (dim + 1) + 1 + i,
                                    j * (dim + 1) + 1 + i, 1)

        iterGMRESMax = 50
        if (scaling == 0):
            LS = cdmath.LinearSolver(divMat, Un + S * dt, iterGMRESMax,
                                     precision, "GMRES", "ILU")
        else:
            LS = cdmath.LinearSolver(divMat, Vn + S * dt, iterGMRESMax,
                                     precision, "GMRES", "ILU")
        LS.setComputeConditionNumber()

        test_desc["Linear_solver_algorithm"] = LS.getNameOfMethod()
        test_desc["Linear_solver_preconditioner"] = LS.getNameOfPc()
        test_desc["Linear_solver_precision"] = LS.getTolerance()
        test_desc["Linear_solver_maximum_iterations"] = LS.getNumberMaxOfIter()
        test_desc["Numerical_parameter_space_step"] = dx_min
        test_desc["Numerical_parameter_time_step"] = dt
        test_desc["Linear_solver_with_scaling"] = scaling

        test_desc['Linear_system_max_actual_iterations_number'] = 0
        test_desc["Linear_system_max_actual_error"] = 0
        test_desc["Linear_system_max_actual_condition number"] = 0

    print(
        "Starting computation of the linear wave system with an Upwind scheme …"
    )

    # Starting time loop
    while (it < ntmax and time <= tmax and not isStationary):
        if (isImplicit):
            dUn = Un.deepCopy()
            if (scaling == 0):
                LS.setSndMember(Un + S * dt)
            else:
                LS.setSndMember(Vn + S * dt)
            if (scaling < 2):
                Un = LS.solve()
                if (scaling == 1):
                    Vn = Un.deepCopy()
                    for k in range(nbCells):
                        Vn[k * (dim + 1) + 0] = Vn[k *
                                                   (dim + 1) + 0] / (c0 * c0)
            else:  #( scaling==2)
                Vn = LS.solve()
                Un = Vn.deepCopy()
                for k in range(nbCells):
                    Un[k * (dim + 1) + 0] = c0 * Vn[k * (dim + 1) + 0]
            if (not LS.getStatus()):
                print("Linear system did not converge ", LS.getNumberOfIter(),
                      " GMRES iterations")
                raise ValueError("Pas de convergence du système linéaire")
            dUn -= Un

            test_desc["Linear_system_max_actual_iterations_number"] = max(
                LS.getNumberOfIter(),
                test_desc["Linear_system_max_actual_iterations_number"])
            test_desc["Linear_system_max_actual_error"] = max(
                LS.getResidu(), test_desc["Linear_system_max_actual_error"])
            test_desc["Linear_system_max_actual_condition number"] = max(
                LS.getConditionNumber(),
                test_desc["Linear_system_max_actual_condition number"])

        else:
            dUn = divMat * Un - S * dt
            Un -= dUn

        maxVector = dUn.maxVector(dim + 1)

        if (with_source):
            isStationary = maxVector[0] < precision and maxVector[
                1] / rho0 < precision and maxVector[2] / rho0 < precision
        else:
            isStationary = maxVector[0] / p0 < precision and maxVector[
                1] / rho0 < precision and maxVector[2] / rho0 < precision

        if (dim == 3):
            isStationary = isStationary and maxVector[3] / rho0 < precision
        time = time + dt
        it = it + 1

        #Sauvegardes
        if (it == 1 or it % output_freq == 0 or it >= ntmax or isStationary
                or time >= tmax):
            print "-- Iter: " + str(it) + ", Time: " + str(
                time) + ", dt: " + str(dt)
            if (with_source):
                print("Variation temporelle relative : pressure ",
                      maxVector[0], ", velocity x", maxVector[1] / rho0,
                      ", velocity y", maxVector[2] / rho0)
            else:
                print("Variation temporelle relative : pressure ",
                      maxVector[0] / p0, ", velocity x", maxVector[1] / rho0,
                      ", velocity y", maxVector[2] / rho0)
            if (isImplicit):
                print("Linear system converged in ", LS.getNumberOfIter(),
                      " GMRES iterations")

            delta_press = 0
            delta_v = cdmath.Vector(dim)
            for k in range(nbCells):
                pressure_field[k] = Un[k * (dim + 1) + 0]
                velocity_field[k, 0] = Un[k * (dim + 1) + 1] / rho0
                if (dim > 1):
                    velocity_field[k, 1] = Un[k * (dim + 1) + 2] / rho0
                    if (dim > 2):
                        velocity_field[k, 2] = Un[k * (dim + 1) + 3] / rho0
                if (abs(stat_pressure[k] - pressure_field[k]) > delta_press):
                    delta_press = abs(stat_pressure[k] - pressure_field[k])
                if (abs(stat_velocity[k, 0] - velocity_field[k, 0]) >
                        delta_v[0]):
                    delta_v[0] = abs(stat_velocity[k, 0] -
                                     velocity_field[k, 0])
                if (abs(stat_velocity[k, 1] - velocity_field[k, 1]) >
                        delta_v[1]):
                    delta_v[1] = abs(stat_velocity[k, 1] -
                                     velocity_field[k, 1])
                if (dim == 3):
                    if (abs(stat_velocity[k, 2] - velocity_field[k, 2]) >
                            delta_v[2]):
                        delta_v[2] = abs(stat_velocity[k, 2] -
                                         velocity_field[k, 2])

            pressure_field.setTime(time, it)
            pressure_field.writeVTK(
                "WaveSystem" + str(dim) + "DUpwind" + meshName + "_pressure",
                False)
            velocity_field.setTime(time, it)
            velocity_field.writeVTK(
                "WaveSystem" + str(dim) + "DUpwind" + meshName + "_velocity",
                False)

            if (with_source):
                print("Ecart au stationnaire exact : error_p= ", delta_press,
                      " error_||u||= ",
                      delta_v.maxVector()[0])
            else:
                print("Ecart au stationnaire exact : error_p= ",
                      delta_press / p0, " error_||u||= ",
                      delta_v.maxVector()[0])
            print
    print "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)
    if (with_source):
        print("Variation temporelle relative : pressure ", maxVector[0],
              ", velocity x", maxVector[1] / rho0, ", velocity y",
              maxVector[2] / rho0)
    else:
        print("Variation temporelle relative : pressure ", maxVector[0] / p0,
              ", velocity x", maxVector[1] / rho0, ", velocity y",
              maxVector[2] / rho0)
    print

    if (it >= ntmax):
        print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint")
        raise ValueError(
            "Maximum number of time steps reached : Stationary state not found !!!!!!!"
        )
    elif (isStationary):
        print("Régime stationnaire atteint au pas de temps ", it, ", t= ",
              time)
        if (not with_source):
            print("Mass loss: ",
                  (total_pressure_initial - pressure_field.integral()).norm() /
                  p0, " precision required= ", precision)
            print("Momentum loss: ",
                  (total_velocity_initial - velocity_field.integral()).norm() /
                  velocity_field.normL1().norm(), " precision required= ",
                  precision)
            assert (total_pressure_initial -
                    pressure_field.integral()).norm() / p0 < precision
            if (test_bc == "Periodic"):
                assert (total_velocity_initial -
                        velocity_field.integral()).norm() < 2 * precision
        print(
            "------------------------------------------------------------------------------------"
        )

        pressure_field.setTime(time, 0)
        pressure_field.writeVTK("WaveSystem" + str(dim) + "DUpwind" +
                                meshName + "_pressure_Stat")
        velocity_field.setTime(time, 0)
        velocity_field.writeVTK("WaveSystem" + str(dim) + "DUpwind" +
                                meshName + "_velocity_Stat")

        #Postprocessing : Extraction of the diagonal data
        if (dim == 2):
            diag_data_press = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                pressure_field, [0, 1, 0], [1, 0, 0], resolution)
            diag_data_vel = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                velocity_field, [0, 1, 0], [1, 0, 0], resolution)
        elif (dim == 3):
            diag_data_press = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                pressure_field, [0, 0, 0], [1, 1, 1], resolution)
            diag_data_vel = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                velocity_field, [0, 0, 0], [1, 1, 1], resolution)
        #Postprocessing : save 2D picture
        PV_routines.Save_PV_data_to_picture_file(
            "WaveSystem" + str(dim) + "DUpwind" + meshName + "_pressure_Stat" +
            '_0.vtu', "Pressure", 'CELLS',
            "WaveSystem" + str(dim) + "DUpwind" + meshName + "_pressure_Stat")
        PV_routines.Save_PV_data_to_picture_file(
            "WaveSystem" + str(dim) + "DUpwind" + meshName + "_velocity_Stat" +
            '_0.vtu', "Velocity", 'CELLS',
            "WaveSystem" + str(dim) + "DUpwind" + meshName + "_velocity_Stat")

        if (not with_source):
            return delta_press / p0, delta_v.maxVector(
            )[0], nbCells, time, it, velocity_field.getNormEuclidean().max(
            ), diag_data_press, diag_data_vel
        else:
            return delta_press, delta_v.maxVector(
            )[0], nbCells, time, it, velocity_field.getNormEuclidean().max(
            ), diag_data_press, diag_data_vel
    else:
        print("Temps maximum Tmax= ", tmax, " atteint")
        raise ValueError(
            "Maximum time reached : Stationary state not found !!!!!!!")
        raise ValueError("Mesh should not contain borders")
    else:
        maxNbNeighbours = max(
            1 + Ni.getNumberOfCells(), maxNbNeighbours
        )  #true only for planar cells, otherwise use function Ni.getNumberOfEdges()

print("Right hand side discretisation done")
print("Max nb of neighbours=", maxNbNeighbours)
print("Integral of the RHS", my_RHSfield.integral(0))

# Construction de la matrice de rigidité et du vecteur second membre du système linéaire
#=======================================================================================
Rigidite = cdmath.SparseMatrixPetsc(
    nbNodes, nbNodes, maxNbNeighbours
)  # warning : third argument is number of non zero coefficients per line
RHS = cdmath.Vector(nbNodes)

# Vecteurs gradient de la fonction de forme associée à chaque noeud d'un triangle
GradShapeFunc0 = cdmath.Vector(3)
GradShapeFunc1 = cdmath.Vector(3)
GradShapeFunc2 = cdmath.Vector(3)

normalFace0 = cdmath.Vector(3)
normalFace1 = cdmath.Vector(3)

#On parcourt les triangles du domaine
for i in range(nbCells):

    Ci = my_mesh.getCell(i)

    #Contribution à la matrice de rigidité
Esempio n. 22
0
def solve(filename, resolution, meshName, testColor):
    start = time.time()
    test_desc["Mesh_name"] = meshName
    test_desc["Test_color"] = testColor

    #Chargement du maillage triangulaire du disque unité D(0,1)
    #=======================================================================================
    my_mesh = cdmath.Mesh(filename + ".med")
    if (my_mesh.getSpaceDimension() != 2 or my_mesh.getMeshDimension() != 2):
        raise ValueError(
            "Wrong space or mesh dimension : space and mesh dimensions should be 2"
        )
    if (not my_mesh.isTriangular()):
        raise ValueError("Wrong cell types : mesh is not made of triangles")

    nbNodes = my_mesh.getNumberOfNodes()
    nbCells = my_mesh.getNumberOfCells()

    test_desc["Space_dimension"] = my_mesh.getSpaceDimension()
    test_desc["Mesh_dimension"] = my_mesh.getMeshDimension()
    test_desc["Mesh_number_of_elements"] = my_mesh.getNumberOfNodes()
    test_desc["Mesh_cell_type"] = my_mesh.getElementTypesNames()

    print("Mesh loading done")
    print("Number of nodes=", nbNodes)
    print("Number of cells=", nbCells)

    #Détermination des noeuds intérieurs
    #======================================================================
    my_ExactSol = cdmath.Field("Exact_field", cdmath.NODES, my_mesh, 1)
    nbInteriorNodes = 0
    nbBoundaryNodes = 0
    maxNbNeighbours = 0  #This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
    interiorNodes = []
    boundaryNodes = []
    eps = 1e-6

    #parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud
    for i in range(nbNodes):
        Ni = my_mesh.getNode(i)
        x = Ni.x()
        y = Ni.y()

        #Robust calculation of atan(2x/(x**2+y**2-1)
        #my_ExactSol[i]=atan2(2*x*sign(x**2+y**2-1),abs(x**2+y**2-1))#mettre la solution exacte de l'edp
        if x**2 + y**2 - 1 > eps:
            print("!!! Warning Mesh ", meshName,
                  " !!! Node is not in the unit disk.", ", eps=", eps,
                  ", x**2+y**2-1=", x**2 + y**2 - 1)
            #raise ValueError("!!! Domain should be the unit disk.")
        if x**2 + y**2 - 1 < -eps:
            my_ExactSol[i] = atan(2 * x / (x**2 + y**2 - 1))
        elif x > 0:  #x**2+y**2-1>=0
            my_ExactSol[i] = -pi / 2
        elif x < 0:  #x**2+y**2-1>=0
            my_ExactSol[i] = pi / 2
        else:  #x=0
            my_ExactSol[i] = 0

        if my_mesh.isBorderNode(i):  # Détection des noeuds frontière
            boundaryNodes.append(i)
            nbBoundaryNodes = nbBoundaryNodes + 1
        else:  # Détection des noeuds intérieurs
            interiorNodes.append(i)
            nbInteriorNodes = nbInteriorNodes + 1
            maxNbNeighbours = max(
                1 + Ni.getNumberOfCells(), maxNbNeighbours
            )  #true only in 2D, need a function Ni.getNumberOfNeighbourNodes()

    test_desc["Mesh_max_number_of_neighbours"] = maxNbNeighbours

    print("Right hand side discretisation done")
    print("Number of interior nodes=", nbInteriorNodes)
    print("Number of boundary nodes=", nbBoundaryNodes)
    print("Max number of neighbours=", maxNbNeighbours)

    # Construction de la matrice de rigidité et du vecteur second membre du système linéaire
    #=======================================================================================
    Rigidite = cdmath.SparseMatrixPetsc(
        nbInteriorNodes, nbInteriorNodes, maxNbNeighbours
    )  # warning : third argument is maximum number of non zero coefficients per line of the matrix
    RHS = cdmath.Vector(nbInteriorNodes)

    M = cdmath.Matrix(3, 3)
    # Vecteurs gradient de la fonction de forme associée à chaque noeud d'un triangle (hypothèse 2D)
    GradShapeFunc0 = cdmath.Vector(2)
    GradShapeFunc1 = cdmath.Vector(2)
    GradShapeFunc2 = cdmath.Vector(2)

    #On parcourt les triangles du domaine
    for i in range(nbCells):

        Ci = my_mesh.getCell(i)

        #Contribution à la matrice de rigidité
        nodeId0 = Ci.getNodeId(0)
        nodeId1 = Ci.getNodeId(1)
        nodeId2 = Ci.getNodeId(2)

        N0 = my_mesh.getNode(nodeId0)
        N1 = my_mesh.getNode(nodeId1)
        N2 = my_mesh.getNode(nodeId2)

        M[0, 0] = N0.x()
        M[0, 1] = N0.y()
        M[0, 2] = 1
        M[1, 0] = N1.x()
        M[1, 1] = N1.y()
        M[1, 2] = 1
        M[2, 0] = N2.x()
        M[2, 1] = N2.y()
        M[2, 2] = 1

        #Values of each shape function at each node
        values0 = [1, 0, 0]
        values1 = [0, 1, 0]
        values2 = [0, 0, 1]

        GradShapeFunc0 = gradientNodal(M, values0) / 2
        GradShapeFunc1 = gradientNodal(M, values1) / 2
        GradShapeFunc2 = gradientNodal(M, values2) / 2

        #Création d'un tableau (numéro du noeud, gradient de la fonction de forme)
        GradShapeFuncs = {nodeId0: GradShapeFunc0}
        GradShapeFuncs[nodeId1] = GradShapeFunc1
        GradShapeFuncs[nodeId2] = GradShapeFunc2

        # Remplissage de  la matrice de rigidité et du second membre
        for j in [nodeId0, nodeId1, nodeId2]:
            if boundaryNodes.count(
                    j
            ) == 0:  #seuls les noeuds intérieurs contribuent au système linéaire (matrice de rigidité et second membre)
                j_int = interiorNodes.index(
                    j)  #indice du noeud j en tant que noeud intérieur
                #Pas de contribution au second membre car pas de terme source
                boundaryContributionAdded = False  #Needed in case j is a border cell
                #Contribution de la cellule triangulaire i à la ligne j_int du système linéaire
                for k in [nodeId0, nodeId1, nodeId2]:
                    if boundaryNodes.count(
                            k
                    ) == 0:  #seuls les noeuds intérieurs contribuent à la matrice du système linéaire
                        k_int = interiorNodes.index(
                            k)  #indice du noeud k en tant que noeud intérieur
                        Rigidite.addValue(
                            j_int, k_int, GradShapeFuncs[j] *
                            GradShapeFuncs[k] / Ci.getMeasure())
                    elif boundaryContributionAdded == False:  #si condition limite non nulle au bord (ou maillage non recouvrant), ajouter la contribution du bord au second membre de la cellule j
                        if boundaryNodes.count(nodeId0) != 0:
                            u0 = my_ExactSol[nodeId0]
                        else:
                            u0 = 0
                        if boundaryNodes.count(nodeId1) != 0:
                            u1 = my_ExactSol[nodeId1]
                        else:
                            u1 = 0
                        if boundaryNodes.count(nodeId2) != 0:
                            u2 = my_ExactSol[nodeId2]
                        else:
                            u2 = 0
                        boundaryContributionAdded = True  #Contribution from the boundary to matrix line j is done in one step
                        GradGh = gradientNodal(M, [u0, u1, u2]) / 2
                        RHS[j_int] += -(GradGh *
                                        GradShapeFuncs[j]) / Ci.getMeasure()

    print("Linear system matrix building done")

    # Résolution du système linéaire
    #=================================
    LS = cdmath.LinearSolver(
        Rigidite, RHS, 100, 1.E-6, "CG",
        "LU")  #Remplacer CG par CHOLESKY pour solveur direct
    LS.setComputeConditionNumber()
    SolSyst = LS.solve()

    print("Preconditioner used : ", LS.getNameOfPc())
    print("Number of iterations used : ", LS.getNumberOfIter())
    print("Linear system solved")

    test_desc["Linear_solver_algorithm"] = LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"] = LS.getNameOfPc()
    test_desc["Linear_solver_precision"] = LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"] = LS.getNumberMaxOfIter()
    test_desc[
        "Linear_system_max_actual_iterations_number"] = LS.getNumberOfIter()
    test_desc["Linear_system_max_actual_error"] = LS.getResidu()
    test_desc[
        "Linear_system_max_actual_condition number"] = LS.getConditionNumber()

    # Création du champ résultat
    #===========================
    my_ResultField = cdmath.Field("ResultField", cdmath.NODES, my_mesh, 1)
    for j in range(nbInteriorNodes):
        my_ResultField[interiorNodes[j]] = SolSyst[j]
        #remplissage des valeurs pour les noeuds intérieurs
    for j in range(nbBoundaryNodes):
        my_ResultField[boundaryNodes[j]] = my_ExactSol[boundaryNodes[j]]
        #remplissage des valeurs pour les noeuds frontière (condition limite)
    #sauvegarde sur le disque dur du résultat dans un fichier paraview
    my_ResultField.writeVTK("FiniteElements2DPoissonStiffBC_DISK_" + meshName +
                            str(nbNodes))

    print(
        "Numerical solution of 2D Poisson equation on a disk using finite elements done"
    )

    end = time.time()

    #Calcul de l'erreur commise par rapport à la solution exacte
    #===========================================================
    l2_norm_sol_exacte = my_ExactSol.normL2()[0]
    l2_error = (my_ExactSol - my_ResultField).normL2()[0]

    print(
        "L2 relative error = norm( exact solution - numerical solution )/norm( exact solution ) = ",
        l2_error / l2_norm_sol_exacte)
    print("Maximum numerical solution = ", my_ResultField.max(),
          " Minimum numerical solution = ", my_ResultField.min())
    print("Maximum exact solution = ", my_ExactSol.max(),
          " Minimum exact solution = ", my_ExactSol.min())

    #Postprocessing :
    #================
    # Extraction of the diagonal data
    diag_data = VTK_routines.Extract_field_data_over_line_to_numpyArray(
        my_ResultField, [0, -1, 0], [0, 1, 0], resolution)
    # save 2D picture
    PV_routines.Save_PV_data_to_picture_file(
        "FiniteElements2DPoissonStiffBC_DISK_" + meshName + str(nbNodes) +
        '_0.vtu', "ResultField", 'NODES',
        "FiniteElements2DPoissonStiffBC_DISK_" + meshName + str(nbNodes))

    test_desc["Computational_time_taken_by_run"] = end - start
    test_desc["Absolute_error"] = l2_error
    test_desc["Relative_error"] = l2_error / l2_norm_sol_exacte

    with open(
            'test_PoissonStiffBC' + str(my_mesh.getMeshDimension()) + 'D_EF_' +
            "DISK_" + meshName + str(nbCells) + "Cells.json", 'w') as outfile:
        json.dump(test_desc, outfile)

    return l2_error / l2_norm_sol_exacte, nbNodes, diag_data, my_ResultField.min(
    ), my_ResultField.max(), end - start
Esempio n. 23
0
def computeFluxes(U, SumFluxes):
    my_mesh =U.getMesh();
    nbCells = my_mesh.getNumberOfCells();
    dim=my_mesh.getMeshDimension();
    nbComp=U.getNumberOfComponents();
    Fcourant=cdmath.Vector(nbComp)
    Fautre=cdmath.Vector(nbComp)
    Ucourant=cdmath.Vector(nbComp)
    Uautre=cdmath.Vector(nbComp)
    normal=cdmath.Vector(dim)
    sumFluxCourant=cdmath.Vector(nbComp)

    for j in range(nbCells):#On parcourt les cellules         
        Cj = my_mesh.getCell(j)
        nbFaces = Cj.getNumberOfFaces();
        for i in range(nbComp) :
            Ucourant[i]=U[j,i];
            sumFluxCourant[i]=0;

        for k in range(nbFaces) :
            indexFace = Cj.getFacesId()[k];
            Fk = my_mesh.getFace(indexFace);
            for i in range(dim) :
                normal[i] = Cj.getNormalVector(k, i);#normale sortante

            cellAutre = -1;
            if ( not Fk.isBorder()) :
                # hypothese: La cellule d'index indexC1 est la cellule courante index j */
                if (Fk.getCellsId()[0] == j) :
                    # hypothese verifiée 
                    cellAutre = Fk.getCellsId()[1];
                elif(Fk.getCellsId()[1] == j) :
                    # hypothese non verifiée 
                    cellAutre = Fk.getCellsId()[0];
                else :
                    raise ValueError("computeFluxes: problem with mesh, unknown cel number");
                
                for i in range(nbComp):
                    Uautre[i]=U[cellAutre,i]
            else :
                if(Fk.getGroupName() != "Neumann"):#Wall boundary condition unless Wall/Neumann specified explicitly
                    for i in range(nbComp):
                        Uautre[i]=Ucourant[i]
                    qn=0# normal momentum
                    for i in range(dim):
                        qn+=Ucourant[i+1]*normal[i]
                    for i in range(dim):
                        Uautre[i+1]-=2*qn*normal[i]
                elif(Fk.getGroupName() == "Neumann"):
                    for i in range(nbComp):
                        Uautre[i]=Ucourant[i]
                else:
                    print Fk.getGroupName()
                    raise ValueError("computeFluxes: Unknown boundary condition name");
            
            Fcourant=Flux(Ucourant,normal);
            Fautre  =Flux(Uautre,  normal);

            A, absA=jacobianMatrices( normal);
            sumFluxCourant = sumFluxCourant + (Fcourant+Fautre +absA*(Ucourant-Uautre))*Fk.getMeasure()*0.5
                
        #On divise par le volume de la cellule la contribution des flux au snd membre
        for i in range(nbComp):
            SumFluxes[j,i]=sumFluxCourant[i]/Cj.getMeasure()
def solve(my_mesh, filename, resolution, meshType, testColor):
    start = time.time()
    test_desc["Mesh_type"] = meshType
    test_desc["Test_color"] = testColor

    nbCells = my_mesh.getNumberOfCells()

    if (my_mesh.getSpaceDimension() != 2 or my_mesh.getMeshDimension() != 2):
        raise ValueError(
            "Wrong space or mesh dimension : space and mesh dimensions should be 2"
        )

    test_desc["Space_dimension"] = my_mesh.getSpaceDimension()
    test_desc["Mesh_dimension"] = my_mesh.getMeshDimension()
    test_desc["Mesh_number_of_elements"] = my_mesh.getNumberOfCells()
    test_desc["Mesh_cell_type"] = my_mesh.getElementTypesNames()

    print("Mesh groups done")
    print("Number of cells  = ", nbCells)

    #Discrétisation du second membre et extraction du nb max de voisins d'une cellule
    #================================================================================
    my_ExactSol = cdmath.Field("Exact_field", cdmath.CELLS, my_mesh, 1)
    maxNbNeighbours = 0  #This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
    eps = 1e-6  #For coarse meshes

    #parcours des cellules pour discrétisation du second membre et extraction du nb max de voisins d'une cellule
    for i in range(nbCells):
        Ci = my_mesh.getCell(i)
        x = Ci.x()
        y = Ci.y()

        #Robust calculation of atan(2x/(x**2+y**2-1)
        if x**2 + y**2 - 1 > eps:
            print("!!! Warning Mesh ", meshType,
                  " !!! Cell is not in the unit disk.", ", eps=", eps,
                  ", x**2+y**2 - 1=", x**2 + y**2 - 1)
            #raise ValueError("Exact solution computation !!! Domain should be the unit disk.")
        if x**2 + y**2 - 1 < -eps:
            my_ExactSol[i] = atan(2 * x / (x**2 + y**2 - 1))
        elif x > 0:  #x**2+y**2-1>=0
            my_ExactSol[i] = -pi / 2
        elif x < 0:  #x**2+y**2-1>=0
            my_ExactSol[i] = pi / 2
        else:  #x=0
            my_ExactSol[i] = 0

        # compute maximum number of neighbours
        maxNbNeighbours = max(1 + Ci.getNumberOfFaces(), maxNbNeighbours)

    test_desc["Mesh_max_number_of_neighbours"] = maxNbNeighbours

    print("Right hand side discretisation done")
    print("Max nb of neighbours=", maxNbNeighbours)

    # Construction de la matrice et du vecteur second membre du système linéaire
    #===========================================================================
    Rigidite = cdmath.SparseMatrixPetsc(
        nbCells, nbCells, maxNbNeighbours
    )  # warning : third argument is maximum number of non zero coefficients per line of the matrix
    RHS = cdmath.Vector(nbCells)

    #Parcours des cellules du domaine
    for i in range(nbCells):
        Ci = my_mesh.getCell(i)
        for j in range(Ci.getNumberOfFaces()):  # parcours des faces voisinnes
            Fj = my_mesh.getFace(Ci.getFaceId(j))
            if not Fj.isBorder():
                k = Fj.getCellId(0)
                if k == i:
                    k = Fj.getCellId(1)
                Ck = my_mesh.getCell(k)
                distance = Ci.getBarryCenter().distance(Ck.getBarryCenter())
                coeff = Fj.getMeasure() / Ci.getMeasure() / distance
                Rigidite.setValue(i, k, -coeff)  # terme extradiagonal
            else:
                coeff = Fj.getMeasure() / Ci.getMeasure() / Ci.getBarryCenter(
                ).distance(Fj.getBarryCenter())
                #For the particular case where the mesh boundary does not coincide with the domain boundary
                x = Fj.getBarryCenter().x()
                y = Fj.getBarryCenter().y()
                if x**2 + y**2 - 1 > eps:
                    print("!!! Warning Mesh ", meshType,
                          " !!! Face is not in the unit disk.", ", eps=", eps,
                          ", x**2+y**2 - 1=", x**2 + y**2 - 1)
                    #raise ValueError("!!! Domain should be the unit disk.")
                if x**2 + y**2 - 1 < -eps:
                    RHS[i] += coeff * atan(2 * x / (x**2 + y**2 - 1))
                elif x > 0:  #x**2+y**2-1>=0
                    RHS[i] += coeff * (-pi / 2)
                elif x < 0:  #x**2+y**2-1>=0
                    RHS[i] += coeff * pi / 2
                else:  #x=0
                    RHS[i] += 0
            Rigidite.addValue(i, i, coeff)  # terme diagonal

    print("Linear system matrix building done")

    # Résolution du système linéaire
    #=================================
    LS = cdmath.LinearSolver(Rigidite, RHS, 500, 1.E-6, "CG", "LU")
    LS.setComputeConditionNumber()
    SolSyst = LS.solve()

    print("Preconditioner used : ", LS.getNameOfPc())
    print("Number of iterations used : ", LS.getNumberOfIter())
    print("Linear system solved")

    test_desc["Linear_solver_algorithm"] = LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"] = LS.getNameOfPc()
    test_desc["Linear_solver_precision"] = LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"] = LS.getNumberMaxOfIter()
    test_desc[
        "Linear_system_max_actual_iterations_number"] = LS.getNumberOfIter()
    test_desc["Linear_system_max_actual_error"] = LS.getResidu()
    test_desc[
        "Linear_system_max_actual_condition number"] = LS.getConditionNumber()

    # Création du champ résultat
    #===========================
    my_ResultField = cdmath.Field("ResultField", cdmath.CELLS, my_mesh, 1)
    for i in range(nbCells):
        my_ResultField[i] = SolSyst[i]
    #sauvegarde sur le disque dur du résultat dans un fichier paraview
    my_ResultField.writeVTK("FiniteVolumes2DPoissonStiffBC_DISK_" + meshType +
                            str(nbCells))
    my_ExactSol.writeVTK("ExactSol2DPoissonStiffBC_DISK_" + meshType +
                         str(nbCells))

    print(
        "Numerical solution of 2D Poisson equation on a disk using finite volumes done"
    )

    end = time.time()

    #Calcul de l'erreur commise par rapport à la solution exacte
    #===========================================================
    l2_norm_sol_exacte = my_ExactSol.normL2()[0]
    l2_error = (my_ExactSol - my_ResultField).normL2()[0]

    print(
        "L2 relative error = norm( exact solution - numerical solution )/norm( exact solution ) = ",
        l2_error / l2_norm_sol_exacte)
    print("Maximum numerical solution = ", my_ResultField.max(),
          " Minimum numerical solution = ", my_ResultField.min())
    print("Maximum exact solution = ", my_ExactSol.max(),
          " Minimum exact solution = ", my_ExactSol.min())

    #Postprocessing :
    #================
    # Extraction of the diagonal data
    diag_data = VTK_routines.Extract_field_data_over_line_to_numpyArray(
        my_ResultField, [0, -1, 0], [0, 1, 0], resolution)
    # save 2D picture
    PV_routines.Save_PV_data_to_picture_file(
        "FiniteVolumes2DPoissonStiffBC_DISK_" + meshType + str(nbCells) +
        '_0.vtu', "ResultField", 'CELLS',
        "FiniteVolumes2DPoissonStiffBC_DISK_" + meshType + str(nbCells))
    PV_routines.Save_PV_data_to_picture_file(
        "ExactSol2DPoissonStiffBC_DISK_" + meshType + str(nbCells) + '_0.vtu',
        "Exact_field", 'CELLS',
        "ExactSol2DPoissonStiffBC_DISK_" + meshType + str(nbCells))

    test_desc["Computational_time_taken_by_run"] = end - start
    test_desc["Absolute_error"] = l2_error
    test_desc["Relative_error"] = l2_error / l2_norm_sol_exacte

    with open(
            'test_PoissonStiffBC' + str(my_mesh.getMeshDimension()) + 'D_VF_' +
            "DISK_" + str(nbCells) + "Cells.json", 'w') as outfile:
        json.dump(test_desc, outfile)

    return l2_error / l2_norm_sol_exacte, nbCells, diag_data, my_ResultField.min(
    ), my_ResultField.max(), end - start
Esempio n. 25
0
def WaveSystemStaggered(ntmax, tmax, cfl, my_mesh, output_freq, meshName,
                        resolution, scaling, test_bc):
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    dt = 0.
    time = 0.
    it = 0
    isStationary = False

    nbVoisinsMax = my_mesh.getMaxNbNeighbours(cdmath.CELLS)
    iterGMRESMax = 50

    #iteration vectors
    Un = cdmath.Vector(nbCells * (dim + 1))
    dUn = cdmath.Vector(nbCells * (dim + 1))

    # Initial conditions #
    print("Construction of the initial data …")
    pressure_field, velocity_field = initial_conditions_wave_system_staggered(
        my_mesh)
    initial_pressure, initial_velocity = initial_conditions_wave_system_staggered(
        my_mesh)

    for k in range(nbCells):
        Un[k + 0 * nbCells] = initial_pressure[k]
        Un[k + 1 *
           nbCells] = rho0 * initial_velocity[k, 0]  # value on the left face
        Un[k + 2 *
           nbCells] = rho0 * initial_velocity[k, 1]  # value on the bottom face
        if (dim == 3):
            Un[k + 3 * nbCells] = rho0 * initial_velocity[k, 2]
    if (scaling > 0):
        Vn = Un.deepCopy()
        for k in range(nbCells):
            Vn[k] = Vn[k] / c0

    #sauvegarde de la donnée initiale
    pressure_field.setTime(time, it)
    pressure_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + meshName +
                            "_pressure")
    velocity_field.setTime(time, it)
    velocity_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + meshName +
                            "_velocity")
    #Postprocessing : save 2D picture
    PV_routines.Save_PV_data_to_picture_file(
        "WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure" +
        '_0.vtu', "Pressure", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" +
        meshName + "_pressure_initial")
    PV_routines.Save_PV_data_to_picture_file(
        "WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity" +
        '_0.vtu', "Velocity", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" +
        meshName + "_velocity_initial")

    total_pressure_initial = pressure_field.integral(
    )  #For conservation test later
    total_velocity_initial = velocity_field.integral(
    )  #For conservation test later

    dx_min = my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0
    divMat = computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, scaling)

    if (scaling == 0):
        LS = cdmath.LinearSolver(divMat, Un, iterGMRESMax, precision, "GMRES",
                                 "ILU")
    else:
        LS = cdmath.LinearSolver(divMat, Vn, iterGMRESMax, precision, "GMRES",
                                 "ILU")
    LS.setComputeConditionNumber()

    test_desc["Linear_solver_algorithm"] = LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"] = LS.getNameOfPc()
    test_desc["Linear_solver_precision"] = LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"] = LS.getNumberMaxOfIter()
    test_desc["Numerical_parameter_space_step"] = dx_min
    test_desc["Numerical_parameter_time_step"] = dt
    test_desc["Linear_solver_with_scaling"] = scaling

    test_desc['Linear_system_max_actual_iterations_number'] = 0
    test_desc["Linear_system_max_actual_error"] = 0
    test_desc["Linear_system_max_actual_condition number"] = 0

    print(
        "Starting computation of the linear wave system with a pseudo staggered scheme …"
    )

    # Starting time loop
    while (it < ntmax and time <= tmax and not isStationary):
        dUn = Un.deepCopy()
        if (scaling == 0):
            LS.setSndMember(Un)
            Un = LS.solve()
        else:  #( scaling > 0)
            LS.setSndMember(Vn)
            Vn = LS.solve()
            Un = Vn.deepCopy()
            for k in range(nbCells):
                Un[k] = c0 * Vn[k]

        if (not LS.getStatus()):
            print "Linear system did not converge ", iterGMRES, " GMRES iterations"
            raise ValueError("Pas de convergence du système linéaire")
        dUn -= Un

        test_desc["Linear_system_max_actual_iterations_number"] = max(
            LS.getNumberOfIter(),
            test_desc["Linear_system_max_actual_iterations_number"])
        test_desc["Linear_system_max_actual_error"] = max(
            LS.getResidu(), test_desc["Linear_system_max_actual_error"])
        test_desc["Linear_system_max_actual_condition number"] = max(
            LS.getConditionNumber(),
            test_desc["Linear_system_max_actual_condition number"])

        max_dp = 0
        max_dq = 0
        for k in range(nbCells):
            max_dp = max(max_dp, abs(dUn[k]))
            for i in range(dim):
                max_dq = max(max_dq, abs(dUn[k + (1 + i) * nbCells]))

        isStationary = max_dp / p0 < precision and max_dq / rho0 < precision

        time = time + dt
        it = it + 1

        #Sauvegardes
        if (it % output_freq == 0 or it >= ntmax or isStationary
                or time >= tmax):
            print "-- Iter: " + str(it) + ", Time: " + str(
                time) + ", dt: " + str(dt)
            print "Variation temporelle relative : pressure ", max_dp / p0, ", velocity ", max_dq / rho0
            print "Linear system converged in ", LS.getNumberOfIter(
            ), " GMRES iterations"

            delta_press = 0
            delta_v = cdmath.Vector(dim)
            for k in range(nbCells):
                pressure_field[k] = Un[k]
                velocity_field[k, 0] = Un[k + 1 * nbCells] / rho0
                if (dim > 1):
                    velocity_field[k, 1] = Un[k + 2 * nbCells] / rho0
                    if (dim > 2):
                        velocity_field[k, 2] = Un[k + 3 * nbCells] / rho0
                if (abs(initial_pressure[k] - pressure_field[k]) >
                        delta_press):
                    delta_press = abs(initial_pressure[k] - pressure_field[k])
                if (abs(initial_velocity[k, 0] - velocity_field[k, 0]) >
                        delta_v[0]):
                    delta_v[0] = abs(initial_velocity[k, 0] -
                                     velocity_field[k, 0])
                if (abs(initial_velocity[k, 1] - velocity_field[k, 1]) >
                        delta_v[1]):
                    delta_v[1] = abs(initial_velocity[k, 1] -
                                     velocity_field[k, 1])
                if (dim == 3):
                    if (abs(initial_velocity[k, 2] - velocity_field[k, 2]) >
                            delta_v[2]):
                        delta_v[2] = abs(initial_velocity[k, 2] -
                                         velocity_field[k, 2])

            pressure_field.setTime(time, it)
            pressure_field.writeVTK(
                "WaveSystem" + str(dim) + "DStaggered" + meshName +
                "_pressure", False)
            velocity_field.setTime(time, it)
            velocity_field.writeVTK(
                "WaveSystem" + str(dim) + "DStaggered" + meshName +
                "_velocity", False)

            print "Ecart au stationnaire exact : error_p= ", delta_press / p0, " error_||u||= ", delta_v.maxVector(
            )[0]
            print
    print "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)
    print "Variation temporelle relative : pressure ", max_dp / p0, ", velocity ", max_dq / rho0
    print

    if (it >= ntmax):
        print "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint"
        raise ValueError(
            "Maximum number of time steps reached : Stationary state not found !!!!!!!"
        )
    elif (isStationary):
        print "Régime stationnaire atteint au pas de temps ", it, ", t= ", time
        print "Mass loss: ", (total_pressure_initial -
                              pressure_field.integral()
                              ).norm() / p0, " precision required= ", precision
        print "Momentum loss: ", (
            total_velocity_initial -
            velocity_field.integral()).norm() / velocity_field.normL1().norm(
            ), " precision required= ", precision
        assert (total_pressure_initial -
                pressure_field.integral()).norm() / p0 < precision
        if (test_bc == "Periodic"):
            assert (total_velocity_initial -
                    velocity_field.integral()).norm() < 2 * precision
        print "------------------------------------------------------------------------------------"

        pressure_field.setTime(time, 0)
        pressure_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" +
                                meshName + "_pressure_Stat")
        velocity_field.setTime(time, 0)
        velocity_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" +
                                meshName + "_velocity_Stat")

        #Postprocessing : Extraction of the diagonal data
        if (dim == 2):
            diag_data_press = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                pressure_field, [0, 1, 0], [1, 0, 0], resolution)
            diag_data_vel = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                velocity_field, [0, 1, 0], [1, 0, 0], resolution)
        elif (dim == 3):
            diag_data_press = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                pressure_field, [0, 0, 0], [1, 1, 1], resolution)
            diag_data_vel = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                velocity_field, [0, 0, 0], [1, 1, 1], resolution)
        #Postprocessing : save 2D picture
        PV_routines.Save_PV_data_to_picture_file(
            "WaveSystem" + str(dim) + "DStaggered" + meshName +
            "_pressure_Stat" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" +
            str(dim) + "DStaggered" + meshName + "_pressure_Stat")
        PV_routines.Save_PV_data_to_picture_file(
            "WaveSystem" + str(dim) + "DStaggered" + meshName +
            "_velocity_Stat" + '_0.vtu', "Velocity", 'CELLS', "WaveSystem" +
            str(dim) + "DStaggered" + meshName + "_velocity_Stat")

        return delta_press / p0, delta_v.maxVector(
        )[0], nbCells, time, it, velocity_field.getNormEuclidean().max(
        ), diag_data_press, diag_data_vel, test_desc[
            "Linear_system_max_actual_condition number"]
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
        raise ValueError(
            "Maximum time reached : Stationary state not found !!!!!!!")
Esempio n. 26
0
def WaveSystemStaggered(ntmax, tmax, cfl, my_mesh, output_freq, meshName,
                        resolution):
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    dt = 0.
    time = 0.
    it = 0
    isStationary = False

    scaling = 0

    nbVoisinsMax = my_mesh.getMaxNbNeighbours(cdmath.CELLS)
    iterGMRESMax = 50

    #iteration vectors
    Un = cdmath.Vector(nbCells * (dim + 1))
    dUn = cdmath.Vector(nbCells * (dim + 1))

    # Initial conditions #
    print("Construction of the initial condition …")
    pressure_field, velocity_field = initial_conditions_wave_system(my_mesh)

    for k in range(nbCells):
        Un[k + 0 * nbCells] = pressure_field[k]
        Un[k +
           1 * nbCells] = rho0 * velocity_field[k, 0]  # value on the left face
        Un[k + 2 *
           nbCells] = rho0 * velocity_field[k, 1]  # value on the bottom face
        if (dim == 3):
            Un[k + 3 * nbCells] = rho0 * initial_velocity[k, 2]
    if (scaling > 0):
        Vn = Un.deepCopy()
        for k in range(nbCells):
            Vn[k] = Vn[k] / c0

    #sauvegarde de la donnée initiale
    pressure_field.setTime(time, it)
    pressure_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + meshName +
                            "_pressure")
    velocity_field.setTime(time, it)
    velocity_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" + meshName +
                            "_velocity")
    #Postprocessing : save 2D picture
    PV_routines.Save_PV_data_to_picture_file(
        "WaveSystem" + str(dim) + "DStaggered" + meshName + "_pressure" +
        '_0.vtu', "Pressure", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" +
        meshName + "_pressure_initial")
    PV_routines.Save_PV_data_to_picture_file(
        "WaveSystem" + str(dim) + "DStaggered" + meshName + "_velocity" +
        '_0.vtu', "Velocity", 'CELLS', "WaveSystem" + str(dim) + "DStaggered" +
        meshName + "_velocity_initial")

    dx_min = my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0

    divMat = computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, scaling)

    # Add the identity matrix on the diagonal
    for j in range(nbCells * (dim + 1)):
        divMat.addValue(j, j, 1.)
    LS = cdmath.LinearSolver(divMat, Un, iterGMRESMax, precision, "GMRES",
                             "LU")

    print(
        "Starting computation of the linear wave system with an pseudo staggered scheme …"
    )

    # Starting time loop
    while (it < ntmax and time <= tmax and not isStationary):
        dUn = Un.deepCopy()
        LS.setSndMember(Un)
        Un = LS.solve()
        cvgceLS = LS.getStatus()
        iterGMRES = LS.getNumberOfIter()
        if (not cvgceLS):
            print "Linear system did not converge ", iterGMRES, " GMRES iterations"
            raise ValueError("Pas de convergence du système linéaire")
        dUn -= Un

        max_dp = 0
        max_dq = 0
        for k in range(nbCells):
            max_dp = max(max_dp, abs(dUn[k]))
            for i in range(dim):
                max_dq = max(max_dq, abs(dUn[k + (1 + i) * nbCells]))

        isStationary = max_dp / p0 < precision and max_dq / rho0 < precision

        time = time + dt
        it = it + 1

        #Sauvegardes
        if (it % output_freq == 0 or it >= ntmax or isStationary
                or time >= tmax):
            print "-- Iter: " + str(it) + ", Time: " + str(
                time) + ", dt: " + str(dt)
            print "Variation temporelle relative : pressure ", max_dp / p0, ", velocity ", max_dq / rho0
            print "Linear system converged in ", iterGMRES, " GMRES iterations"

            for k in range(nbCells):
                pressure_field[k] = Un[k]
                velocity_field[k, 0] = Un[k + 1 * nbCells] / rho0
                if (dim > 1):
                    velocity_field[k, 1] = Un[k + 2 * nbCells] / rho0
                    if (dim > 2):
                        velocity_field[k, 2] = Un[k + 3 * nbCells] / rho0

            pressure_field.setTime(time, it)
            pressure_field.writeVTK(
                "WaveSystem" + str(dim) + "DStaggered" + meshName +
                "_pressure", False)
            velocity_field.setTime(time, it)
            velocity_field.writeVTK(
                "WaveSystem" + str(dim) + "DStaggered" + meshName +
                "_velocity", False)

    print "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)
    print "Variation temporelle relative : pressure ", max_dp / p0, ", velocity ", max_dq / rho0
    print

    if (it >= ntmax):
        print "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint"
    elif (isStationary):
        print "Régime stationnaire atteint au pas de temps ", it, ", t= ", time
        print "------------------------------------------------------------------------------------"

        pressure_field.setTime(time, 0)
        pressure_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" +
                                meshName + "_pressure_Stat")
        velocity_field.setTime(time, 0)
        velocity_field.writeVTK("WaveSystem" + str(dim) + "DStaggered" +
                                meshName + "_velocity_Stat")

        #Postprocessing : save 2D picture
        PV_routines.Save_PV_data_to_picture_file(
            "WaveSystem" + str(dim) + "DStaggered" + meshName +
            "_pressure_Stat" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" +
            str(dim) + "DStaggered" + meshName + "_pressure_Stat")
        PV_routines.Save_PV_data_to_picture_file(
            "WaveSystem" + str(dim) + "DStaggered" + meshName +
            "_velocity_Stat" + '_0.vtu', "Velocity", 'CELLS', "WaveSystem" +
            str(dim) + "DStaggered" + meshName + "_velocity_Stat")

    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
Esempio n. 27
0
def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution,
                 scaling, test_bc):
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

    dt = 0.
    time = 0.
    it = 0
    isStationary = False

    nbVoisinsMax = my_mesh.getMaxNbNeighbours(cdmath.CELLS)
    iterGMRESMax = 50

    #iteration vectors
    Un = cdmath.Vector(nbCells * (dim + 1))
    dUn = cdmath.Vector(nbCells * (dim + 1))

    # Initial conditions #
    print("Construction of the initial condition …")
    if (meshName.find("square") == -1 and meshName.find("Square") == -1
            and meshName.find("cube") == -1 and meshName.find("Cube") == -1):
        print "Mesh name : ", meshName
        raise ValueError(
            "Mesh name should contain substring square or cube to use wave system with stiff source term"
        )
    else:
        S, stat_pressure, stat_momentum = source_term_and_stat_solution_wave_system(
            my_mesh)
        pressure_field = stat_pressure.deepCopy()
        momentum_field = stat_momentum.deepCopy()

    for k in range(nbCells):
        Un[k * (dim + 1) + 0] = pressure_field[k]
        Un[k * (dim + 1) + 1] = momentum_field[k, 0]
        Un[k * (dim + 1) + 2] = momentum_field[k, 1]
        if (dim == 3):
            Un[k * (dim + 1) + 3] = momentum_field[k, 2]

    if (scaling == 1):
        Vn = Un.deepCopy()
        for k in range(nbCells):
            Vn[k * (dim + 1) + 0] = Vn[k * (dim + 1) + 0] / (c0 * c0)
            S[k * (dim + 1) + 0] = S[k * (dim + 1) + 0] / (c0 * c0)
    elif (scaling == 2):
        Vn = Un.deepCopy()
        for k in range(nbCells):
            Vn[k * (dim + 1) + 0] = Vn[k * (dim + 1) + 0] / c0
            S[k * (dim + 1) + 0] = S[k * (dim + 1) + 0] / c0

    #sauvegarde de la donnée initiale
    pressure_field.setTime(time, it)
    pressure_field.writeVTK("WaveSystem" + str(dim) + "DPStag" + meshName +
                            "_pressure")
    momentum_field.setTime(time, it)
    momentum_field.writeVTK("WaveSystem" + str(dim) + "DPStag" + meshName +
                            "_momentum")
    #Postprocessing : save 2D picture
    PV_routines.Save_PV_data_to_picture_file(
        "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure" + '_0.vtu',
        "Pressure", 'CELLS',
        "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure_initial")
    PV_routines.Save_PV_data_to_picture_file(
        "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum" + '_0.vtu',
        "Momentum", 'CELLS',
        "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum_initial")

    total_pressure_initial = pressure_field.integral(
    )  #For conservation test later
    total_momentum_initial = momentum_field.integral(
    )  #For conservation test later

    dx_min = my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0
    divMat = computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, scaling,
                                     test_bc)
    #Adding the momentum friction term
    for j in range(nbCells):
        for i in range(dim):
            divMat.addValue(j * (dim + 1) + 1 + i, j * (dim + 1) + 1 + i, dt)

    #Add the identity matrix on the diagonal
    if (scaling == 0 or scaling == 2):
        divMat.diagonalShift(1)  #only after  filling all coefficients
    else:
        for j in range(nbCells):
            divMat.addValue(j * (dim + 1), j * (dim + 1),
                            1 / (c0 * c0))  #/(c0*c0)
            for i in range(dim):
                divMat.addValue(j * (dim + 1) + 1 + i,
                                j * (dim + 1) + 1 + i, 1)
    if (scaling == 0):
        LS = cdmath.LinearSolver(divMat, Un + S * dt, iterGMRESMax, precision,
                                 "GMRES", "ILU")
    else:
        LS = cdmath.LinearSolver(divMat, Vn + S * dt, iterGMRESMax, precision,
                                 "GMRES", "ILU")
    LS.setComputeConditionNumber()

    test_desc["Linear_solver_algorithm"] = LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"] = LS.getNameOfPc()
    test_desc["Linear_solver_precision"] = LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"] = LS.getNumberMaxOfIter()
    test_desc["Numerical_parameter_space_step"] = dx_min
    test_desc["Numerical_parameter_time_step"] = dt
    test_desc["Linear_solver_with_scaling"] = scaling

    test_desc['Linear_system_max_actual_iterations_number'] = 0
    test_desc["Linear_system_max_actual_error"] = 0
    test_desc["Linear_system_max_actual_condition number"] = 0

    print(
        "Starting computation of the linear wave system with a pseudo staggered scheme …"
    )

    # Starting time loop
    while (it < ntmax and time <= tmax and not isStationary):
        dUn = Un.deepCopy()
        if (scaling == 0):
            LS.setSndMember(Un + S * dt)
        else:
            LS.setSndMember(Vn + S * dt)
        if (scaling < 2):
            Un = LS.solve()
            if (scaling == 1):
                Vn = Un.deepCopy()
                for k in range(nbCells):
                    Vn[k * (dim + 1) + 0] = Vn[k * (dim + 1) + 0] / (c0 * c0)
        else:  #( scaling==2)
            Vn = LS.solve()
            Un = Vn.deepCopy()
            for k in range(nbCells):
                Un[k * (dim + 1) + 0] = c0 * Vn[k * (dim + 1) + 0]

        if (not LS.getStatus()):
            print "Linear system did not converge ", iterGMRES, " GMRES iterations"
            raise ValueError("Pas de convergence du système linéaire")
        dUn -= Un

        test_desc["Linear_system_max_actual_iterations_number"] = max(
            LS.getNumberOfIter(),
            test_desc["Linear_system_max_actual_iterations_number"])
        test_desc["Linear_system_max_actual_error"] = max(
            LS.getResidu(), test_desc["Linear_system_max_actual_error"])
        test_desc["Linear_system_max_actual_condition number"] = max(
            LS.getConditionNumber(),
            test_desc["Linear_system_max_actual_condition number"])

        maxVector = dUn.maxVector(dim + 1)

        isStationary = maxVector[0] < precision and maxVector[
            1] / rho0 < precision and maxVector[2] / rho0 < precision

        if (dim == 3):
            isStationary = isStationary and maxVector[3] / rho0 < precision
        time = time + dt
        it = it + 1

        #Sauvegardes
        if (it == 1 or it % output_freq == 0 or it >= ntmax or isStationary
                or time >= tmax):
            print "-- Iter: " + str(it) + ", Time: " + str(
                time) + ", dt: " + str(dt)
            print "Variation temporelle relative : pressure ", maxVector[
                0], ", velocity x", maxVector[
                    1] / rho0, ", velocity y", maxVector[2] / rho0
            print "Linear system converged in ", LS.getNumberOfIter(
            ), " GMRES iterations"

            delta_press = 0
            delta_q = cdmath.Vector(dim)
            for k in range(nbCells):
                pressure_field[k] = Un[k * (dim + 1) + 0]
                momentum_field[k, 0] = Un[k * (dim + 1) + 1] / rho0
                if (dim > 1):
                    momentum_field[k, 1] = Un[k * (dim + 1) + 2] / rho0
                    if (dim > 2):
                        momentum_field[k, 2] = Un[k * (dim + 1) + 3] / rho0
                if (abs(stat_pressure[k] - pressure_field[k]) > delta_press):
                    delta_press = abs(stat_pressure[k] - pressure_field[k])
                if (abs(stat_momentum[k, 0] - momentum_field[k, 0]) >
                        delta_q[0]):
                    delta_q[0] = abs(stat_momentum[k, 0] -
                                     momentum_field[k, 0])
                if (abs(stat_momentum[k, 1] - momentum_field[k, 1]) >
                        delta_q[1]):
                    delta_q[1] = abs(stat_momentum[k, 1] -
                                     momentum_field[k, 1])
                if (dim == 3):
                    if (abs(stat_momentum[k, 2] - momentum_field[k, 2]) >
                            delta_q[2]):
                        delta_q[2] = abs(stat_momentum[k, 2] -
                                         momentum_field[k, 2])

            pressure_field.setTime(time, it)
            pressure_field.writeVTK(
                "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure",
                False)
            momentum_field.setTime(time, it)
            momentum_field.writeVTK(
                "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum",
                False)

            print "Ecart au stationnaire exact : error_p= ", delta_press, " error_||q||= ", delta_q.maxVector(
            )[0]
            print
    print "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)
    print "Variation temporelle relative : pressure ", maxVector[
        0], ", velocity x", maxVector[1] / rho0, ", velocity y", maxVector[
            2] / rho0
    print

    if (it >= ntmax):
        print "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint"
        raise ValueError(
            "Maximum number of time steps reached : Stationary state not found !!!!!!!"
        )
    elif (isStationary):
        print "Régime stationnaire atteint au pas de temps ", it, ", t= ", time
        print "------------------------------------------------------------------------------------"

        pressure_field.setTime(time, 0)
        pressure_field.writeVTK("WaveSystem" + str(dim) + "DPStag" + meshName +
                                "_pressure_Stat")
        momentum_field.setTime(time, 0)
        momentum_field.writeVTK("WaveSystem" + str(dim) + "DPStag" + meshName +
                                "_momentum_Stat")

        #Postprocessing : Extraction of the diagonal data
        if (dim == 2):
            diag_data_press = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                pressure_field, [0, 1, 0], [1, 0, 0], resolution)
            diag_data_vel = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                momentum_field, [0, 1, 0], [1, 0, 0], resolution)
        elif (dim == 3):
            diag_data_press = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                pressure_field, [0, 0, 0], [1, 1, 1], resolution)
            diag_data_vel = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                momentum_field, [0, 0, 0], [1, 1, 1], resolution)
        #Postprocessing : save 2D picture
        PV_routines.Save_PV_data_to_picture_file(
            "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure_Stat" +
            '_0.vtu', "Pressure", 'CELLS',
            "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure_Stat")
        PV_routines.Save_PV_data_to_picture_file(
            "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum_Stat" +
            '_0.vtu', "Momentum", 'CELLS',
            "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum_Stat")

        return delta_press, delta_q.maxVector(
        )[0], nbCells, time, it, momentum_field.getNormEuclidean().max(
        ), diag_data_press, diag_data_vel, test_desc[
            "Linear_system_max_actual_condition number"]
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
        raise ValueError(
            "Maximum time reached : Stationary state not found !!!!!!!")
def solve(nx,cfl,a,b, isSmooth):
    start = time.time()
    print "Transport equation, implicit scheme, nx= ", nx, " cfl= ", cfl
    ##################### Simulation parameters
    dx = (b - a) / nx #space step

    c = 0.25 # advection velocity
    tmax = (b-a)/c # runs the simulation for 0 <= t <= tMax
    dt = cfl * dx / c
    ntmax = ceil(tmax/dt)

    if(cfl>nx):
        raise("Impossible to run this simulation with cfl>nx. Choose another value for nx or cfl.")
        
    x=[a+0.5*dx + i*dx for i in range(nx)]   # array of cell center (1D mesh)
    
    ########################## Initial data
    if(isSmooth):
        print "Smooth initial data"
        u_initial = [ 0.5*(1+sin(2*pi*xi-pi*.5))  for xi in x];# to be used with a=0, b=1
        u = [ 0.5*(1+sin(2*pi*xi-pi*.5))  for xi in x];# to be used with a=0, b=1
    else:
        print "Stiff initial data"
        u_initial = [ int(1./3<xi)*int(xi<2./3)  for xi in x];# to be used with a=0, b=1
        u = [ int(1./3<xi)*int(xi<2./3)  for xi in x];# to be used with a=0, b=1
        
    max_initial=max(u_initial)
    min_initial=min(u_initial)
    total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])

    Time = 0.
    it = 0
    output_freq = 50

    #Linear system initialisation
    systemMat=centeredSchemeMatrix(nx,cfl)
    iterGMRESMax=50
    precision=1.e-5
    Un =cdmath.Vector(nx)
    for i in range(nx):
        Un[i]=u[i]
    LS=cdmath.LinearSolver(systemMat,Un,iterGMRESMax, precision, "GMRES","ILU")

    ########################### Postprocessing initialisation
    # Picture frame
    plt.legend()
    plt.xlabel('x')
    plt.ylabel('u')
    plt.xlim(a,b)
    plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial +  0.1*(max_initial-min_initial) )
    plt.title('Centered implicit scheme for transport equation')
    line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma

    print("Starting time loop")
    print("-- Iter: " + str(it) + ", Time: " + str(Time) + ", dt: " + str(dt))
    np.savetxt( "TransportEquation_CenteredImplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
    plt.savefig("TransportEquation_CenteredImplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_"+str(it)+".png")

    ############################# Time loop
    while (it < ntmax and Time <= tmax):
        # Solve linear system
        for i in range(nx):
            Un[i]=u[i]
        LS.setSndMember(Un)
        Un=LS.solve()
        if(not LS.getStatus()):
            print "Linear system did not converge ", iterGMRES, " GMRES iterations"
            raise ValueError("Pas de convergence du système linéaire");
        for i in range(nx):
            u[i]=Un[i]

        if ( max(u) > max_initial ):
            print "-- Iter: " + str(it) + " max principle violated : max(t) > max(0) : max(t)= ",max(u), " max(0)= ", max_initial
        if ( min(u) < min_initial ):
            print "-- Iter: " + str(it) + " min principle violated : min(t) < min(0) : min(t)= ",min(u), " min(0)= ", min_initial
        if ( np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) > total_var_initial ):
            print "-- Iter: " + str(it) + " total variation increased : var(t) > var(0) : var(t)= ", np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]), " var(0)= ", total_var_initial

        Time += dt
        it += 1

        # Postprocessing
        line1.set_ydata(u)
        if (it % output_freq == 0):
            print("-- Iter: " + str(it) + ", Time: " + str(Time) + ", dt: " + str(dt))
            np.savetxt( "TransportEquation_CenteredImplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n")
            plt.savefig("TransportEquation_CenteredImplicit_"+str(nx)+"Cells_Smoothness"+str(isSmooth)+"_CFL"+str(cfl)+"_ResultField_"+str(it)+".png")
            #plt.show()
            pass
        pass

    print "Exact solution minimum   : ", min(u_initial), "Numerical solution minimum   : ",  min(u)
    print "Exact solution maximum   : ", max(u_initial), "Numerical solution maximum   : ",  max(u)
    print "Exact solution variation : ", np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)]), "Numerical solution variation : ",  np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)])
    print "l1 numerical error       : ", dx*np.sum([abs(u[i] - u_initial[i]) for i in range(nx)])        

    print("Simulation of transport equation with an implicit centered scheme done.")
    
    end = time.time()

    #return min, max, sol, total variation, l1 error and elapsed time
    return min(u), max(u), u, np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]), dx*np.sum([abs(u[i] - u_initial[i]) for i in range(nx)]), end-start
Esempio n. 29
0
def solve(filename,resolution,meshType, testColor):
    start = time.time()
    test_desc["Mesh_type"]=meshType
    test_desc["Test_color"]=testColor
    
    #Chargement du maillage triangulaire du domaine carré [0,1]x[0,1], définition des bords
    #=======================================================================================
    my_mesh = cdmath.Mesh(filename+".med")
    if( my_mesh.getSpaceDimension()!=2 or my_mesh.getMeshDimension()!=2) :
        raise ValueError("Wrong space or mesh dimension : space and mesh dimensions should be 2")
    if(not my_mesh.isTriangular()) :
        raise ValueError("Wrong cell types : mesh is not made of triangles")
    eps=1e-6
    my_mesh.setGroupAtPlan(0.,0,eps,"DirichletBorder")#Bord GAUCHE
    my_mesh.setGroupAtPlan(1.,0,eps,"DirichletBorder")#Bord DROIT
    my_mesh.setGroupAtPlan(0.,1,eps,"DirichletBorder")#Bord BAS
    my_mesh.setGroupAtPlan(1.,1,eps,"DirichletBorder")#Bord HAUT
    
    nbNodes = my_mesh.getNumberOfNodes()
    nbCells = my_mesh.getNumberOfCells()
    
    test_desc["Space_dimension"]=my_mesh.getSpaceDimension()
    test_desc["Mesh_dimension"]=my_mesh.getMeshDimension()
    test_desc["Mesh_number_of_elements"]=my_mesh.getNumberOfNodes()
    test_desc["Mesh_cell_type"]=my_mesh.getElementTypes()

    print("Mesh loading done")
    print("Number of nodes=", nbNodes)
    print("Number of cells=", nbCells)
    
    #Discrétisation du second membre et détermination des noeuds intérieurs
    #======================================================================
    my_RHSfield = cdmath.Field("RHS_field", cdmath.NODES, my_mesh, 1)
    nbInteriorNodes = 0
    nbBoundaryNodes = 0
    maxNbNeighbours = 0#This is to determine the number of non zero coefficients in the sparse finite element rigidity matrix
    interiorNodes=[]
    boundaryNodes=[]
    
    #parcours des noeuds pour discrétisation du second membre et extraction 1) des noeuds intérieur 2) des noeuds frontière 3) du nb max voisins d'un noeud
    for i in range(nbNodes):
        Ni=my_mesh.getNode(i)
        x = Ni.x()
        y = Ni.y()
    
        my_RHSfield[i]=2*pi*pi*sin(pi*x)*sin(pi*y)#mettre la fonction definie au second membre de l'edp
        if my_mesh.isBorderNode(i): # Détection des noeuds frontière
            boundaryNodes.append(i)
            nbBoundaryNodes=nbBoundaryNodes+1
        else: # Détection des noeuds intérieurs
            interiorNodes.append(i)
            nbInteriorNodes=nbInteriorNodes+1
            maxNbNeighbours= max(1+Ni.getNumberOfCells(),maxNbNeighbours) #true only in 2D, need a function Ni.getNumberOfNeighbourNodes()

    test_desc["Mesh_max_number_of_neighbours"]=maxNbNeighbours
    
    print("Right hand side discretisation done")
    print("Number of interior nodes=", nbInteriorNodes)
    print("Number of boundary nodes=", nbBoundaryNodes)
    print("Max number of neighbours=", maxNbNeighbours)
    
    # Construction de la matrice de rigidité et du vecteur second membre du système linéaire
    #=======================================================================================
    Rigidite=cdmath.SparseMatrixPetsc(nbInteriorNodes,nbInteriorNodes,maxNbNeighbours) # warning : third argument is maximum number of non zero coefficients per line of the matrix
    RHS=cdmath.Vector(nbInteriorNodes)
    
    # Vecteurs gradient de la fonction de forme associée à chaque noeud d'un triangle (hypothèse 2D)
    GradShapeFunc0=cdmath.Vector(2)
    GradShapeFunc1=cdmath.Vector(2)
    GradShapeFunc2=cdmath.Vector(2)
    
    #On parcourt les triangles du domaine
    for i in range(nbCells):
    
        Ci=my_mesh.getCell(i)
    
        #Contribution à la matrice de rigidité
        nodeId0=Ci.getNodeId(0)
        nodeId1=Ci.getNodeId(1)
        nodeId2=Ci.getNodeId(2)
    
        N0=my_mesh.getNode(nodeId0)
        N1=my_mesh.getNode(nodeId1)
        N2=my_mesh.getNode(nodeId2)
    
        #Formule des gradients voir EF P1 -> calcul déterminants
        GradShapeFunc0[0]= (N1.y()-N2.y())/2
        GradShapeFunc0[1]=-(N1.x()-N2.x())/2
        GradShapeFunc1[0]=-(N0.y()-N2.y())/2
        GradShapeFunc1[1]= (N0.x()-N2.x())/2
        GradShapeFunc2[0]= (N0.y()-N1.y())/2
        GradShapeFunc2[1]=-(N0.x()-N1.x())/2
    
        #Création d'un tableau (numéro du noeud, gradient de la fonction de forme
        GradShapeFuncs={nodeId0 : GradShapeFunc0}
        GradShapeFuncs[nodeId1]=GradShapeFunc1
        GradShapeFuncs[nodeId2]=GradShapeFunc2
    
    
        # Remplissage de  la matrice de rigidité et du second membre
        for j in [nodeId0,nodeId1,nodeId2] :
            if boundaryNodes.count(j)==0 : #seuls les noeuds intérieurs contribuent au système linéaire (matrice de rigidité et second membre)
                j_int=interiorNodes.index(j)#indice du noeud j en tant que noeud intérieur
                #Ajout de la contribution de la cellule triangulaire i au second membre du noeud j 
                RHS[j_int]=Ci.getMeasure()/3*my_RHSfield[j]+RHS[j_int] # intégrale dans le triangle du produit f x fonction de base
                #Contribution de la cellule triangulaire i à la ligne j_int du système linéaire
                for k in [nodeId0,nodeId1,nodeId2] : 
                    if boundaryNodes.count(k)==0 : #seuls les noeuds intérieurs contribuent à la matrice du système linéaire
                        k_int=interiorNodes.index(k)#indice du noeud k en tant que noeud intérieur
                        Rigidite.addValue(j_int,k_int,GradShapeFuncs[j]*GradShapeFuncs[k]/Ci.getMeasure())
                    #else: si condition limite non nulle au bord, ajouter la contribution du bord au second membre de la cellule j
    
    print("Linear system matrix building done")
    
    # Résolution du système linéaire
    #=================================
    LS=cdmath.LinearSolver(Rigidite,RHS,100,1.E-6,"CG","ILU")#Remplacer CG par CHOLESKY pour solveur direct
    LS.setComputeConditionNumber()
    SolSyst=LS.solve()
    
    print "Preconditioner used : ", LS.getNameOfPc()
    print "Number of iterations used : ", LS.getNumberOfIter()
    print("Linear system solved")
    
    test_desc["Linear_solver_algorithm"]=LS.getNameOfMethod()
    test_desc["Linear_solver_preconditioner"]=LS.getNameOfPc()
    test_desc["Linear_solver_precision"]=LS.getTolerance()
    test_desc["Linear_solver_maximum_iterations"]=LS.getNumberMaxOfIter()
    test_desc["Linear_system_max_actual_iterations_number"]=LS.getNumberOfIter()
    test_desc["Linear_system_max_actual_error"]=LS.getResidu()
    test_desc["Linear_system_max_actual_condition number"]=LS.getConditionNumber()


    # Création du champ résultat
    #===========================
    my_ResultField = cdmath.Field("ResultField", cdmath.NODES, my_mesh, 1)
    for j in range(nbInteriorNodes):
        my_ResultField[interiorNodes[j]]=SolSyst[j];#remplissage des valeurs pour les noeuds intérieurs
    for j in range(nbBoundaryNodes):
        my_ResultField[boundaryNodes[j]]=0;#remplissage des valeurs pour les noeuds frontière (condition limite)
    #sauvegarde sur le disque dur du résultat dans un fichier paraview
    my_ResultField.writeVTK("FiniteElements2DPoisson_SQUARE_"+meshType+str(nbNodes))
    
    print("Numerical solution of 2D Poisson equation on a square using finite elements done")
    
    end = time.time()

    #Calcul de l'erreur commise par rapport à la solution exacte
    #===========================================================
    #The following formulas use the fact that the exact solution is equal the right hand side divided by 2*pi*pi
    max_abs_sol_exacte=max(my_RHSfield.max(),-my_RHSfield.min())/(2*pi*pi)
    max_sol_num=my_ResultField.max()
    min_sol_num=my_ResultField.min()
    erreur_abs=0
    for i in range(nbNodes) :
        if erreur_abs < abs(my_RHSfield[i]/(2*pi*pi) - my_ResultField[i]) :
            erreur_abs = abs(my_RHSfield[i]/(2*pi*pi) - my_ResultField[i])
    
    print("Relative error = max(| exact solution - numerical solution |)/max(| exact solution |) = ",erreur_abs/max_abs_sol_exacte)
    print ("Maximum numerical solution = ", max_sol_num, " Minimum numerical solution = ", min_sol_num)
    
    #Postprocessing : 
    #================
	# Extraction of the diagonal data
    diag_data=VTK_routines.Extract_field_data_over_line_to_numpyArray(my_ResultField,[0,1,0],[1,0,0], resolution)
    # save 2D picture
    PV_routines.Save_PV_data_to_picture_file("FiniteElements2DPoisson_SQUARE_"+meshType+str(nbNodes)+'_0.vtu',"ResultField",'NODES',"FiniteElements2DPoisson_SQUARE_"+meshType+str(nbNodes))
    
    test_desc["Computational_time_taken_by_run"]=end-start
    test_desc["Absolute_error"]=erreur_abs
    test_desc["Relative_error"]=erreur_abs/max_abs_sol_exacte

    with open('test_Poisson'+str(my_mesh.getMeshDimension())+'D_EF_'+"SQUARE_"+meshType+str(nbCells)+ "Cells.json", 'w') as outfile:  
        json.dump(test_desc, outfile)

    return erreur_abs/max_abs_sol_exacte, nbNodes, diag_data, min_sol_num, max_sol_num, end - start
Esempio n. 30
0
    y = Ci.y()
    z = Ci.z()
    my_RHSfield[i] = 3 * pi * pi * sin(pi * x) * sin(pi * y) * sin(
        pi * z)  #mettre la fonction definie au second membre de l edp
    # compute maximum number of neighbours
    maxNbNeighbours = max(1 + Ci.getNumberOfFaces(), maxNbNeighbours)

print("Right hand side discretisation done")
print("Maximum number of neighbours=", maxNbNeighbours)

# Construction de la matrice et du vecteur second membre du système linéaire
#===========================================================================
Rigidite = cdmath.SparseMatrixPetsc(
    nbCells, nbCells, maxNbNeighbours
)  # warning : third argument is max number of non zero coefficients per line of the matrix
RHS = cdmath.Vector(nbCells)
#Parcours des cellules du domaine
for i in range(nbCells):
    RHS[i] = my_RHSfield[
        i]  #la valeur moyenne du second membre f dans la cellule i
    Ci = my_mesh.getCell(i)
    for j in range(Ci.getNumberOfFaces()):  # parcours des faces voisinnes
        Fj = my_mesh.getFace(Ci.getFaceId(j))
        if not Fj.isBorder():
            k = Fj.getCellId(0)
            if k == i:
                k = Fj.getCellId(1)
            Ck = my_mesh.getCell(k)
            distance = Ci.getBarryCenter().distance(Ck.getBarryCenter())
            coeff = Fj.getMeasure() / Ci.getMeasure() / distance
            Rigidite.setValue(i, k, -coeff)  # terme extradiagonal