Example #1
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
Example #2
0
def jacobianMatrices():
    A = cdmath.Matrix(2, 2)
    absA = cdmath.Matrix(2, 2)

    absA[0, 0] = c0
    absA[1, 1] = c0
    A[1, 0] = 1
    A[0, 1] = c0 * c0

    return A, absA
Example #3
0
def jacobianMatrices():
    test_desc["Numerical_method_name"]="Upwind"
    A=cdmath.Matrix(2,2)
    absA=cdmath.Matrix(2,2)

    absA[0,0]=c0
    absA[1,1]=c0
    A[1,0]=1
    A[0,1]=c0*c0
    
    return A, absA
Example #4
0
def jacobianMatrices(normal, coeff, signun):
    dim = normal.size()
    A = cdmath.Matrix(dim + 1, dim + 1)
    absA = cdmath.Matrix(dim + 1, dim + 1)

    for i in range(dim):
        A[i + 1, 0] = normal[i] * coeff
        absA[i + 1, 0] = -signun * A[i + 1, 0]
        A[0, i + 1] = c0 * c0 * normal[i] * coeff
        absA[0, i + 1] = signun * A[0, i + 1]

    return (A - absA) / 2
Example #5
0
def jacobianMatrices(normal,coeff):
    dim=normal.size()
    A=cdmath.Matrix(dim+1,dim+1)
    absA=cdmath.Matrix(dim+1,dim+1)

    absA[0,0]=c0*coeff
    for i in range(dim):
        A[i+1,0]=      normal[i]*coeff
        A[0,i+1]=c0*c0*normal[i]*coeff
        for j in range(dim):
            absA[i+1,j+1]=c0*normal[i]*normal[j]*coeff
    
    return (A - absA)/2
Example #6
0
def jacobianMatrices(normal):
    dim=normal.size()
    A=cdmath.Matrix(dim+1,dim+1)
    absA=cdmath.Matrix(dim+1,dim+1)

    absA[0,0]=c0
    for i in range(dim):
        A[i+1,0]=normal[i]
        A[0,i+1]=c0*c0*normal[i]
        for j in range(dim):
            absA[i+1,j+1]=c0*normal[i]*normal[j]
    
    return A, absA
Example #7
0
def staggeredMatrices(coeff, scaling):
    dim = 1
    S1 = cdmath.Matrix(dim + 1, dim + 1)
    S2 = cdmath.Matrix(dim + 1, dim + 1)

    for i in range(dim):
        if (scaling == 0):
            S1[0, i + 1] = c0 * c0 * coeff
            S2[i + 1, 0] = coeff
        else:
            S1[0, i + 1] = c0 * coeff
            S2[i + 1, 0] = c0 * coeff

    return S1, S2
Example #8
0
def jacobianMatrices(normal, coeff):
    test_desc["Numerical_method_name"] = "Upwind"
    dim = normal.size()
    A = cdmath.Matrix(dim + 1, dim + 1)
    absA = cdmath.Matrix(dim + 1, dim + 1)

    absA[0, 0] = c0 * coeff
    for i in range(dim):
        A[i + 1, 0] = normal[i] * coeff
        A[0, i + 1] = c0 * c0 * normal[i] * coeff
        for j in range(dim):
            absA[i + 1, j + 1] = c0 * normal[i] * normal[j] * coeff

    return (A - absA) / 2
Example #9
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
Example #10
0
def jacobianMatrices(normal, coeff, signun):
    dim = normal.size()
    A = cdmath.Matrix(dim + 1, dim + 1)

    for i in range(dim):
        A[i + 1, 0] = normal[i] * coeff
        A[0, i + 1] = c0 * c0 * normal[i] * coeff

    return A / 2
def jacobianMatrices(coeff,scaling):
    dim=1
    A=cdmath.Matrix(dim+1,dim+1)
    absA=cdmath.Matrix(dim+1,dim+1)

    absA[0,0]=c0*coeff
    for i in range(dim):
        for j in range(dim):
            absA[i+1,j+1]=c0*coeff
        if( scaling==0):
            A[0,i+1]=c0*c0*coeff
            A[i+1,0]=      coeff
        elif( scaling==1):
            A[0,i+1]=      coeff
            A[i+1,0]=      coeff
        else:
            A[0,i+1]=   c0*coeff
            A[i+1,0]=   c0*coeff
       
    return A,absA
Example #12
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
Example #13
0
def jacobianMatrices(normal, coeff, signun, scaling):
    test_desc["Numerical_method_name"] = "Pseudo staggered"

    dim = normal.size()
    A = cdmath.Matrix(dim + 1, dim + 1)
    absA = cdmath.Matrix(dim + 1, dim + 1)

    for i in range(dim):
        if (scaling == 0):
            A[0, i + 1] = c0 * c0 * normal[i] * coeff
            A[i + 1, 0] = normal[i] * coeff
        elif (scaling == 1):
            A[0, i + 1] = normal[i] * coeff
            A[i + 1, 0] = normal[i] * coeff
        else:
            A[0, i + 1] = c0 * normal[i] * coeff
            A[i + 1, 0] = c0 * normal[i] * coeff
        absA[0, i + 1] = signun * A[0, i + 1]
        absA[i + 1, 0] = -signun * A[i + 1, 0]

    return (A - absA) / 2
def jacobianMatrices(normal, coeff, scaling):
    test_desc["Numerical_method_name"] = "Centered scheme"

    dim = normal.size()
    A = cdmath.Matrix(dim + 1, dim + 1)

    for i in range(dim):
        if (scaling == 0):
            A[0, i + 1] = c0 * c0 * normal[i] * coeff
            A[i + 1, 0] = normal[i] * coeff
        elif (scaling == 1):
            A[0, i + 1] = normal[i] * coeff
            A[i + 1, 0] = normal[i] * coeff
        else:
            A[0, i + 1] = c0 * normal[i] * coeff
            A[i + 1, 0] = c0 * normal[i] * coeff

    return A / 2
Example #15
0
def computeDivergenceMatrix(my_mesh, implMat, Un):
    nbCells = my_mesh.getNumberOfCells()
    dim = my_mesh.getMeshDimension()
    nbComp = dim + 1
    normal = cdmath.Vector(dim)
    maxAbsEigVa = 0
    q_l = cdmath.Vector(2)
    q_r = cdmath.Vector(2)

    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

            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"
                    )

                q_l[0] = Un[j * nbComp + 1]
                q_l[1] = Un[j * nbComp + 2]
                q_r[0] = Un[cellAutre * nbComp + 1]
                q_r[1] = Un[cellAutre * nbComp + 2]
                Am, un = jacobianMatrices(normal,
                                          Fk.getMeasure() / Cj.getMeasure(),
                                          Un[j * nbComp], q_l,
                                          Un[cellAutre * nbComp], q_r)

                implMat.addValue(j * nbComp, cellAutre * nbComp, Am)
                implMat.addValue(j * nbComp, j * nbComp, Am * (-1.))
            else:
                if (
                        Fk.getGroupName() != "Periodic"
                        and Fk.getGroupName() != "Neumann"
                ):  #Wall boundary condition unless Periodic/Neumann specified explicitly
                    q_l[0] = Un[j * nbComp + 1]
                    q_l[1] = Un[j * nbComp + 2]
                    q_r = q_l - normal * 2 * (q_l * normal)
                    Am, un = jacobianMatrices(
                        normal,
                        Fk.getMeasure() / Cj.getMeasure(), Un[j * nbComp], q_l,
                        Un[j * nbComp], q_r)

                    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 (Fk.getGroupName() == "Periodic"
                      ):  #Periodic boundary condition
                    q_l[0] = Un[j * nbComp + 1]
                    q_l[1] = Un[j * nbComp + 2]
                    q_r[0] = Un[cellAutre * nbComp + 1]
                    q_r[1] = Un[cellAutre * nbComp + 2]
                    Am, un = jacobianMatrices(
                        normal,
                        Fk.getMeasure() / Cj.getMeasure(), Un[j * nbComp],
                        Un[j * nbComp + 1], Un[j * nbComp + 2],
                        Un[cellAutre * nbComp], Un[cellAutre * nbComp + 1],
                        Un[cellAutre * nbComp + 2])

                    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 (Fk.getGroupName() != "Neumann"
                      ):  #Nothing to do for Neumann boundary condition
                    print Fk.getGroupName()
                    raise ValueError(
                        "computeFluxes: Unknown boundary condition name")

            maxAbsEigVa = max(maxAbsEigVa, abs(un + c0), abs(un - c0))

    return maxAbsEigVa
Example #16
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
Example #17
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
nbInteriorNodes = len(interiorNodes)
nbBoundaryNodes = len(boundaryNodes)

print("nb of interior nodes=", nbInteriorNodes)
print("nb of Boundary nodes=", nbBoundaryNodes)
print("Max nb 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)
RHS = cdmath.Vector(nbInteriorNodes)

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

#On parcourt les tétraèdres du domaine pour remplir la matrice
for i in range(nbCells):

    Ci = my_mesh.getCell(i)

    #Extraction des noeuds de la cellule
    nodeId0 = Ci.getNodeId(0)
    nodeId1 = Ci.getNodeId(1)
    nodeId2 = Ci.getNodeId(2)
    nodeId3 = Ci.getNodeId(3)
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
Example #20
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.getElementTypesNames()

    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
    #======================================================================
    dim = my_mesh.getSpaceDimension()
    K = 10 ^ 4
    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] = (1 + K) * 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
    #=======================================================================================
    DiffusionMatrix = cdmath.Matrix(dim, dim)
    DiffusionMatrix[0, 0] = 1
    DiffusionMatrix[0, 1] = 0
    DiffusionMatrix[1, 0] = 0
    DiffusionMatrix[1, 1] = K

    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] *
                            (DiffusionMatrix * 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("FiniteElements2DAnisotropicDiffusion_SQUARE_" +
                            meshType + str(nbNodes))

    print(
        "Numerical solution of 2D anisotropic diffusion 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 to the right hand side divided by (1+K)*pi*pi
    max_abs_sol_exacte = max(my_RHSfield.max(), -my_RHSfield.min()) / (
        (1 + K) * 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] /
                            ((1 + K) * pi * pi) - my_ResultField[i]):
            erreur_abs = abs(my_RHSfield[i] / ((1 + K) * 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(
        "FiniteElements2DAnisotropicDiffusion_SQUARE_" + meshType +
        str(nbNodes) + '_0.vtu', "ResultField", 'NODES',
        "FiniteElements2DAnisotropicDiffusion_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_Diffusion' + 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
    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)

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)
    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