def upwindSchemeMatrix(nx,cfl):
    upwindMat=cdmath.SparseMatrixPetsc(nx,nx,2)
    for i in range(nx):
        upwindMat.setValue(i,i,1+cfl)
        upwindMat.setValue(i,(i-1)%nx,-cfl)

    return upwindMat
def centeredSchemeMatrix(nx,cfl):
    centeredMat=cdmath.SparseMatrixPetsc(nx,nx,2)
    for i in range(nx):
        centeredMat.setValue(i,i,1+cfl)
        centeredMat.setValue(i,(i-1)%nx,-cfl)

    return centeredMat
예제 #3
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
예제 #5
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
예제 #6
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
예제 #7
0
def implicitSchemeMatrix(nx, cfl):
    implMat = cdmath.SparseMatrixPetsc(nx, nx, 3)
    for i in range(nx):
        implMat.setValue(i, (i + 1) % nx, -cfl)
        implMat.setValue(i, i, 1. + 2 * cfl)
        implMat.setValue(i, (i - 1) % nx, -cfl)

    return implMat
예제 #8
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
예제 #9
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
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
    else:  # Détection des noeuds intérieurs
        interiorNodes.append(i)
        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)
예제 #12
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
	phi=atan2(y,x)

	exactSolField[i] = sin(3*phi)*cos(3*theta+ phi) # for the exact solution we use the funtion given in the article of Olshanskii, Reusken 2009, page 19
	my_RHSfield[i] = 9*sin(3*phi)*cos(3*theta+ phi)/(r*r) + (10*sin(3*phi)*cos(3*theta+ phi) + 6*cos(3*phi)*sin(3*theta+ phi))/((R+r*cos(theta))*(R+r*cos(theta))) - 3*sin(theta)*sin(3*phi)*sin(3*theta+ phi)/(r*(R+r*cos(theta))) #for the right hand side we use the function given in the article of Olshanskii, Reusken 2009, page 19
	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)#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)
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)
예제 #14
0
def computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, scaling):
    nbCells = my_mesh.getNumberOfCells()
    dim = my_mesh.getMeshDimension()
    nbComp = dim + 1

    if (not my_mesh.isStructured()):
        raise ValueError("WaveSystemStaggered: the mesh should be structured")

    NxNyNz = my_mesh.getCellGridStructure()
    DxDyDz = my_mesh.getDXYZ()

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

    idMoinsJacCL = cdmath.Matrix(nbComp)

    if (dim == 1):
        nx = NxNyNz[0]
        dx = DxDyDz[0]

        if (scaling == 0):
            for k in range(nbCells):
                implMat.addValue(k, 1 * nbCells + k, -c0 * c0 * dt / dx)
                implMat.addValue(k, 1 * nbCells + (k + 1) % nx,
                                 c0 * c0 * dt / dx)

                implMat.addValue(1 * nbCells + k, k, dt / dx)
                implMat.addValue(1 * nbCells + (k + 1) % nx, k, -dt / dx)
        else:  # scaling >0
            for k in range(nbCells):
                implMat.addValue(k, 1 * nbCells + k, -c0 * dt / dx)
                implMat.addValue(k, 1 * nbCells + (k + 1) % nx, c0 * dt / dx)

                implMat.addValue(1 * nbCells + k, k, c0 * dt / dx)
                implMat.addValue(1 * nbCells + (k + 1) % nx, k, -c0 * dt / dx)

    elif (dim == 2):  # k = j*nx+i
        nx = NxNyNz[0]
        ny = NxNyNz[1]
        dx = DxDyDz[0]
        dy = DxDyDz[1]

        if (scaling == 0):
            for k in range(nbCells):
                i = k % nx
                j = k // nx

                implMat.addValue(k, 1 * nbCells + j * nx + i,
                                 -c0 * c0 * dt / dx)
                implMat.addValue(k, 1 * nbCells + j * nx + (i + 1) % nx,
                                 c0 * c0 * dt / dx)

                implMat.addValue(k, 2 * nbCells + j * nx + i,
                                 -c0 * c0 * dt / dy)
                implMat.addValue(k, 2 * nbCells + ((j + 1) % ny) * nx + i,
                                 c0 * c0 * dt / dy)

                implMat.addValue(1 * nbCells + j * nx + i, k, dt / dx)
                implMat.addValue(1 * nbCells + j * nx + (i + 1) % nx, k,
                                 -dt / dx)

                implMat.addValue(2 * nbCells + j * nx + i, k, dt / dy)
                implMat.addValue(2 * nbCells + ((j + 1) % ny) * nx + i, k,
                                 -dt / dy)

        else:  # scaling >0
            for k in range(nbCells):
                i = k % nx
                j = k // nx

                implMat.addValue(k, 1 * nbCells + j * nx + i, -c0 * dt / dx)
                implMat.addValue(k, 1 * nbCells + j * nx + (i + 1) % nx,
                                 c0 * dt / dx)

                implMat.addValue(k, 2 * nbCells + j * nx + i, -c0 * dt / dy)
                implMat.addValue(k, 2 * nbCells + ((j + 1) % ny) * nx + i,
                                 c0 * dt / dy)

                implMat.addValue(1 * nbCells + j * nx + i, k, c0 * dt / dx)
                implMat.addValue(1 * nbCells + j * nx + (i + 1) % nx, k,
                                 -c0 * dt / dx)

                implMat.addValue(2 * nbCells + j * nx + i, k, c0 * dt / dy)
                implMat.addValue(2 * nbCells + ((j + 1) % ny) * nx + i, k,
                                 -c0 * dt / dy)

    elif (dim == 3):  # k = l*nx*ny+j*nx+i
        nx = NxNyNz[0]
        ny = NxNyNz[1]
        nz = NxNyNz[2]
        dx = DxDyDz[0]
        dy = DxDyDz[1]
        dz = DxDyDz[2]

        if (scaling == 0):
            for k in range(nbCells):
                i = k % nx
                j = (k // nx) % ny
                l = k // (nx * ny)

                implMat.addValue(k, 1 * nbCells + l * nx * ny + j * nx + i,
                                 -c0 * c0 * dt / dx)
                implMat.addValue(
                    k, 1 * nbCells + l * nx * ny + j * nx + (i + 1) % nx,
                    c0 * c0 * dt / dx)

                implMat.addValue(k, 2 * nbCells + l * nx * ny + j * nx + i,
                                 -c0 * c0 * dt / dy)
                implMat.addValue(
                    k, 2 * nbCells + l * nx * ny + ((j + 1) % ny) * nx + i,
                    c0 * c0 * dt / dy)

                implMat.addValue(k, 3 * nbCells + l * nx * ny + j * nx + i,
                                 -c0 * c0 * dt / dz)
                implMat.addValue(
                    k, 3 * nbCells + ((l + 1) % nz) * nx * ny + j * nx + i,
                    c0 * c0 * dt / dz)

                implMat.addValue(1 * nbCells + l * nx * ny + j * nx + i, k,
                                 dt / dx)
                implMat.addValue(
                    1 * nbCells + l * nx * ny + j * nx + (i + 1) % nx, k,
                    -dt / dx)

                implMat.addValue(2 * nbCells + l * nx * ny + j * nx + i, k,
                                 dt / dy)
                implMat.addValue(
                    2 * nbCells + l * nx * ny + ((j + 1) % ny) * nx + i, k,
                    -dt / dy)

                implMat.addValue(3 * nbCells + l * nx * ny + j * nx + i, k,
                                 dt / dz)
                implMat.addValue(
                    3 * nbCells + ((l + 1) % nz) * nx * ny + j * nx + i, k,
                    -dt / dz)

        else:  # scaling >0
            for k in range(nbCells):
                i = k % nx
                j = (k // nx) % ny
                l = k // (nx * ny)

                implMat.addValue(k, 1 * nbCells + l * nx * ny + j * nx + i,
                                 -c0 * dt / dx)
                implMat.addValue(
                    k, 1 * nbCells + l * nx * ny + j * nx + (i + 1) % nx,
                    c0 * dt / dx)

                implMat.addValue(k, 2 * nbCells + l * nx * ny + j * nx + i,
                                 -c0 * dt / dy)
                implMat.addValue(
                    k, 2 * nbCells + l * nx * ny + ((j + 1) % ny) * nx + i,
                    c0 * dt / dy)

                implMat.addValue(k, 3 * nbCells + l * nx * ny + j * nx + i,
                                 -c0 * dt / dz)
                implMat.addValue(
                    k, 3 * nbCells + ((l + 1) % nz) * nx * ny + j * nx + i,
                    c0 * dt / dz)

                implMat.addValue(1 * nbCells + l * nx * ny + j * nx + i, k,
                                 c0 * dt / dx)
                implMat.addValue(
                    1 * nbCells + l * nx * ny + j * nx + (i + 1) % nx, k,
                    -c0 * dt / dx)

                implMat.addValue(2 * nbCells + l * nx * ny + j * nx + i, k,
                                 c0 * dt / dy)
                implMat.addValue(
                    2 * nbCells + l * nx * ny + ((j + 1) % ny) * nx + i, k,
                    -c0 * dt / dy)

                implMat.addValue(3 * nbCells + l * nx * ny + j * nx + i, k,
                                 c0 * dt / dz)
                implMat.addValue(
                    3 * nbCells + ((l + 1) % nz) * nx * ny + j * nx + i, k,
                    -c0 * dt / dz)

    #Add the identity matrix on the diagonal
    #divMat.diagonalShift(1)#only after  filling all coefficients
    for j in range(nbCells * nbComp):
        implMat.addValue(j, j, 1)  #/(c0*c0)

    return implMat
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
예제 #16
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
예제 #17
0
def EulerSystemVF(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 (dim == 1 or 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_shock(
            my_mesh, False)
    elif (filename.find("disk") > -1 or filename.find("Disk") > -1):
        pressure_field, velocity_field = initial_conditions_shock(
            my_mesh, True)
    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]
        if (dim >= 2):
            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]

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

    dx_min = my_mesh.minRatioVolSurf()

    divMat = cdmath.SparseMatrixPetsc(nbCells * (1 + dim), nbCells * (1 + dim),
                                      (nbVoisinsMax + 1) * (1 + dim))
    if (isImplicit):
        iterGMRESMax = 50
        LS = cdmath.LinearSolver(divMat, Un, iterGMRESMax, precision, "GMRES",
                                 "ILU")

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

    # Starting time loop
    while (it < ntmax and time <= tmax and not isStationary):
        divMat.zeroEntries()  #sets the matrix coefficients to zero
        vp_max = computeDivergenceMatrix(my_mesh, divMat,
                                         Un)  #To update at each time step
        dt = cfl * dx_min / vp_max  #To update at each time step

        if (isImplicit):
            #Adding the identity matrix on the diagonal
            divMat.diagonalShift(1)  #only after  filling all coefficients
            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(
                "EulerSystem" + str(dim) + "DUpwind" + "_isImplicit" +
                str(isImplicit) + meshName + "_pressure", False)
            velocity_field.setTime(time, it)
            velocity_field.writeVTK(
                "EulerSystem" + str(dim) + "DUpwind" + "_isImplicit" +
                str(isImplicit) + 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("EulerSystem" + str(dim) + "DUpwind" +
                                "_isImplicit" + str(isImplicit) + meshName +
                                "_pressure_Stat")
        velocity_field.setTime(time, 0)
        velocity_field.writeVTK("EulerSystem" + str(dim) + "DUpwind" +
                                "_isImplicit" + str(isImplicit) + 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(
            "EulerSystem" + str(dim) + "DUpwind" + "_isImplicit" +
            str(isImplicit) + meshName + "_pressure_Stat" + '_0.vtu',
            "Pressure", 'CELLS',
            "EulerSystem" + str(dim) + "DUpwind" + meshName + "_pressure_Stat")
        PV_routines.Save_PV_data_to_picture_file(
            "EulerSystem" + str(dim) + "DUpwind" + "_isImplicit" +
            str(isImplicit) + meshName + "_velocity_Stat" + '_0.vtu',
            "Velocity", 'CELLS',
            "EulerSystem" + str(dim) + "DUpwind" + meshName + "_velocity_Stat")

    else:
        print "Temps maximum Tmax= ", tmax, " atteint"