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 #2
0
def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit):
    dim=my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()
    meshName=my_mesh.getName()
    
    dt = 0.
    time = 0.
    it=0;
    isStationary=False;
    nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS)

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

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

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

    dx_min=my_mesh.minRatioVolSurf()

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

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

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

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

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

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

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

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

        #Postprocessing : Extraction of the diagonal data
        diag_data_press=VTK_routines.Extract_field_data_over_line_to_numpyArray(pressure_field,[0,1,0],[1,0,0], resolution)    
        diag_data_vel  =VTK_routines.Extract_field_data_over_line_to_numpyArray(velocity_field,[0,1,0],[1,0,0], resolution)    
        #Postprocessing : save 2D picture
        PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat")
        PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat")
        
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
Example #3
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
            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
SolSyst = LS.solve()

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

# 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
Example #5
0
def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution,test_bc):
    dim=my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()
    
    dt = 0.
    time = 0.
    it=0;
    isStationary=False;
    
    nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS)
    isImplicit=False
    
    #iteration vectors
    Un=cdmath.Vector(nbCells*(dim+1))
    dUn=cdmath.Vector(nbCells*(dim+1))
    
    # Initial conditions #
    print("Construction of the initial condition …")
    pressure_field, velocity_field = initial_conditions_wave_system(my_mesh)
    initial_pressure, initial_velocity = initial_conditions_wave_system(my_mesh)

    for k in range(nbCells):
        Un[k*(dim+1)+0] =     initial_pressure[k]
        Un[k*(dim+1)+1] =rho0*initial_velocity[k,0]
        Un[k*(dim+1)+2] =rho0*initial_velocity[k,1]
        if(dim==3):
            Un[k*(dim+1)+3] =rho0*initial_velocity[k,2]
            
    #sauvegarde de la donnée initiale
    pressure_field.setTime(time,it);
    pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure");
    velocity_field.setTime(time,it);
    velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity");
    #Postprocessing : save 2D picture
    PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_initial")
    PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_initial")

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

    dt = cfl * dx_min / c0

    divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,test_bc)
    if(isImplicit):
        #Adding the identity matrix on the diagonal
        for j in range(nbCells*(dim+1)):
            divMat.addValue(j,j,1)
        
        iterGMRESMax=50
        LS=cdmath.LinearSolver(divMat,Un,iterGMRESMax, precision, "GMRES","ILU")
        LS.setComputeConditionNumber()
        
        test_desc["Linear_solver_algorithm"]=LS.getNameOfMethod()
        test_desc["Linear_solver_preconditioner"]=LS.getNameOfPc()
        test_desc["Linear_solver_precision"]=LS.getTolerance()
        test_desc["Linear_solver_maximum_iterations"]=LS.getNumberMaxOfIter()
        test_desc["Numerical_parameter_space_step"]=dx_min
        test_desc["Numerical_parameter_time_step"]=dt
        test_desc["Linear_solver_with_scaling"]=scaling
    
        test_desc['Linear_system_max_actual_iterations_number']=0
        test_desc["Linear_system_max_actual_error"]=0
        test_desc["Linear_system_max_actual_condition number"]=0

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

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

        else:
            dUn=divMat*Un
            Un-=dUn
        
        maxVector=dUn.maxVector(dim+1)
        isStationary= maxVector[0]/p0<precision and maxVector[1]/rho0<precision and maxVector[2]/rho0<precision;
        if(dim==3):
            isStationary=isStationary and maxVector[3]/rho0<precision
        time=time+dt;
        it=it+1;
    
        #Sauvegardes
        if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
            print"-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)
            print "Variation temporelle relative : pressure ", maxVector[0]/p0 ,", velocity x", maxVector[1]/rho0 ,", velocity y", maxVector[2]/rho0
            if(isImplicit):
                print "Linear system converged in ", iterGMRES, " GMRES iterations"

            delta_press=0
            delta_v=cdmath.Vector(dim)
            for k in range(nbCells):
                pressure_field[k]=Un[k*(dim+1)+0]
                velocity_field[k,0]=Un[k*(dim+1)+1]/rho0
                if(dim>1):
                    velocity_field[k,1]=Un[k*(dim+1)+2]/rho0
                    if(dim>2):
                        velocity_field[k,2]=Un[k*(dim+1)+3]/rho0
                if (abs(initial_pressure[k]-pressure_field[k])>delta_press):
                    delta_press=abs(initial_pressure[k]-pressure_field[k])
                if (abs(initial_velocity[k,0]-velocity_field[k,0])>delta_v[0]):
                    delta_v[0]=abs(initial_velocity[k,0]-velocity_field[k,0])
                if (abs(initial_velocity[k,1]-velocity_field[k,1])>delta_v[1]):
                    delta_v[1]=abs(initial_velocity[k,1]-velocity_field[k,1])
                if(dim==3):
                    if (abs(initial_velocity[k,2]-velocity_field[k,2])>delta_v[2]):
                        delta_v[2]=abs(initial_velocity[k,2]-velocity_field[k,2])
                
            pressure_field.setTime(time,it);
            pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure",False);
            velocity_field.setTime(time,it);
            velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity",False);

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

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

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

        #Postprocessing : Extraction of the diagonal data
        if(dim==2):
            diag_data_press=VTK_routines.Extract_field_data_over_line_to_numpyArray(pressure_field,[0,1,0],[1,0,0], resolution)    
            diag_data_vel  =VTK_routines.Extract_field_data_over_line_to_numpyArray(velocity_field,[0,1,0],[1,0,0], resolution)    
        elif(dim==3):
            diag_data_press=VTK_routines.Extract_field_data_over_line_to_numpyArray(pressure_field,[0,0,0],[1,1,1], resolution)    
            diag_data_vel  =VTK_routines.Extract_field_data_over_line_to_numpyArray(velocity_field,[0,0,0],[1,1,1], resolution)    
        #Postprocessing : save 2D picture
        PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat")
        PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat")
        
        return delta_press/p0, delta_v.maxVector()[0], nbCells, time, it, velocity_field.getNormEuclidean().max(), diag_data_press, diag_data_vel
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
        raise ValueError("Maximum time reached : Stationary state not found !!!!!!!")
Example #6
0
def WaveSystemVF(ntmax,
                 tmax,
                 cfl,
                 my_mesh,
                 output_freq,
                 meshName,
                 resolution,
                 scaling,
                 test_bc,
                 with_source=False):
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

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

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

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

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

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

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

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

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

    dx_min = my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0

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

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

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

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

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

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

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

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

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

        maxVector = dUn.maxVector(dim + 1)

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

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

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

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

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

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

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

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

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

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

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

    scaling = 0

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

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

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

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

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

    dx_min = my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0

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

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

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

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

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

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

        time = time + dt
        it = it + 1

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    dx_min = my_mesh.minRatioVolSurf()

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

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

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

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

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

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

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

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

        maxVector = dUn.maxVector(dim + 1)

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

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

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

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

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

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

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

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

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

        return delta_press, delta_q.maxVector(
        )[0], nbCells, time, it, momentum_field.getNormEuclidean().max(
        ), diag_data_press, diag_data_vel, test_desc[
            "Linear_system_max_actual_condition number"]
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
        raise ValueError(
            "Maximum time reached : Stationary state not found !!!!!!!")
Example #9
0
def WaveSystemVF(ntmax, tmax, cfl, a, b, nx, output_freq, meshName, scaling):
    dim = 1
    nbCells = nx

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

    dx = (b - a) / nx
    dt = cfl * dx / c0

    nbVoisinsMax = 2

    #iteration vectors
    Un_staggered = cdmath.Vector(nbCells * (dim + 1))
    dUn_staggered = cdmath.Vector(nbCells * (dim + 1))

    # Initial conditions #
    print("Construction of the initial condition …")
    pressure_field_staggered, velocity_field_staggered = initial_conditions_Riemann_problem(
        a, b, nx)
    max_initial_p = max(pressure_field_staggered)
    min_initial_p = min(pressure_field_staggered)
    max_initial_v = max(velocity_field_staggered)
    min_initial_v = min(velocity_field_staggered)

    for k in range(nbCells):
        Un_staggered[k * (dim + 1) + 0] = pressure_field_staggered[k]
        Un_staggered[k * (dim + 1) + 1] = rho0 * velocity_field_staggered[k]

    # Video settings
    FFMpegWriter = manimation.writers['ffmpeg']
    metadata = dict(title="Finite volumes schemes for the 2D Wave System",
                    artist="CEA Saclay",
                    comment="Shock propagation")
    writer = FFMpegWriter(fps=10, metadata=metadata, codec='h264')
    with writer.saving(plt.figure(), "2DWaveSystem_Staggered" + ".mp4", ntmax):
        #sauvegarde de la donnée initiale
        plt.xlabel('x (m)')
        plt.ylabel('Pressure -Pa)')
        plt.xlim(a, b)
        plt.ylim(min_initial_p - 0.1 * (max_initial_p - min_initial_p),
                 max_initial_p + 0.1 * (max_initial_p - min_initial_p))
        plt.title("Riemann problem for Wave system on " + str(nx) + " cells")
        line2, = plt.plot(
            [a + 0.5 * dx + i * dx for i in range(nx)],
            pressure_field_staggered,
            label='Staggered scheme'
        )  #new picture for video # Returns a tuple of line objects, thus the comma
        plt.legend()
        writer.grab_frame()
        plt.savefig("WaveSystem" + str(dim) + "DStaggered" + meshName +
                    "_pressure" + "_0" + ".png")
        np.savetxt("WaveSystem" + str(dim) + "DStaggered" + meshName +
                   "_pressure" + "_0" + ".txt",
                   pressure_field_staggered,
                   delimiter="\n")
        np.savetxt("WaveSystem" + str(dim) + "DStaggered" + meshName +
                   "_velocity" + "_0" + ".txt",
                   velocity_field_staggered,
                   delimiter="\n")

        divMat_staggered = computeStaggeredDivergenceMatrix(
            a, b, nx, nbVoisinsMax, dt, scaling)

        iterGMRESMax = 50

        divMat_staggered.diagonalShift(
            1)  #only after  filling all coefficients
        LS_staggered = cdmath.LinearSolver(divMat_staggered, Un_staggered,
                                           iterGMRESMax, precision, "GMRES",
                                           "ILU")

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

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

            for k in range(nbCells):
                pressure_field_staggered[k] = Un_staggered[k * (dim + 1) + 0]
                velocity_field_staggered[k] = Un_staggered[k * (dim + 1) +
                                                           1] / rho0

            line2.set_ydata(pressure_field_staggered)
            writer.grab_frame()

            time = time + dt
            it = it + 1

            #Sauvegardes
            if (it == 1 or it % output_freq == 0 or it >= ntmax or isStationary
                    or time >= tmax):
                print "-- Iter: " + str(it) + ", Time: " + str(
                    time) + ", dt: " + str(dt)
                print "Linear system converged in ", LS_staggered.getNumberOfIter(
                ), " GMRES iterations"

                np.savetxt("WaveSystem" + str(dim) + "DStaggered" + meshName +
                           "_pressure" + str(it) + ".txt",
                           pressure_field_staggered,
                           delimiter="\n")
                np.savetxt("WaveSystem" + str(dim) + "DStaggered" + meshName +
                           "_velocity" + str(it) + ".txt",
                           velocity_field_staggered,
                           delimiter="\n")
                plt.savefig("WaveSystem" + str(dim) + "DStaggered" + meshName +
                            "_pressure" + str(it) + ".png")

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

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

        np.savetxt("WaveSystem" + str(dim) + "DStaggered" + meshName +
                   "_pressure_Stat.txt",
                   pressure_field_staggered,
                   delimiter="\n")
        np.savetxt("WaveSystem" + str(dim) + "DStaggered" + meshName +
                   "_velocity_Stat.txt",
                   velocity_field_staggered,
                   delimiter="\n")
        plt.savefig("WaveSystem" + str(dim) + "DStaggered" + meshName +
                    "_pressure_Stat.png")

        return
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
        return
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
Example #11
0
def TransportEquationVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName,
                        resolution, test_bc, velocity, isImplicit):
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

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

    nbVoisinsMax = my_mesh.getMaxNbNeighbours(cdmath.CELLS)

    #iteration vectors
    Un = cdmath.Vector(nbCells)
    dUn = cdmath.Vector(nbCells)

    # Initial conditions #
    print("Construction of the initial condition …")
    stat_field = initial_conditions_transport_equation(my_mesh)
    for k in range(nbCells):
        Un[k] = stat_field[k]
    unknown_field = initial_conditions_transport_equation(my_mesh)
    S = cdmath.Vector(nbCells)  #source term is zero

    total_mass_initial = unknown_field.integral()  #For conservation test later

    #sauvegarde de la donnée initiale
    unknown_field.writeVTK("TransportEquation" + str(dim) + "DUpwind" +
                           meshName)

    dx_min = my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / velocity.norm()

    divMat = computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, test_bc,
                                     velocity)
    if (isImplicit):
        #Adding the identity matrix on the diagonal
        divMat.diagonalShift(1)  #only after  filling all coefficients
        #for j in range(nbCells*(dim+1)):
        #    divMat.addValue(j,j,1)

        iterGMRESMax = 50
        LS = cdmath.LinearSolver(divMat, Un + S * dt, iterGMRESMax, precision,
                                 "GMRES", "ILU")
        LS.setComputeConditionNumber()

    print(
        "Starting computation of the linear transport equation with an Upwind scheme …"
    )

    # Starting time loop
    while (it < ntmax and time <= tmax and not isStationary):
        if (isImplicit):
            dUn = Un.deepCopy()
            LS.setSndMember(Un + S * dt)
            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 - S * dt
            Un -= dUn

        maxVector = dUn.maxVector(1)
        isStationary = maxVector[0] < precision

        time = time + dt
        it = it + 1

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

            for k in range(nbCells):
                unknown_field[k] = Un[k]

            unknown_field.setTime(time, it)
            unknown_field.writeVTK(
                "TransportEquation" + str(dim) + "DUpwind" + meshName, False)

    print "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)
    print "Variation temporelle relative : ", maxVector[0]

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

        unknown_field.setTime(time, 0)
        unknown_field.writeVTK("TransportEquation" + str(dim) + "DUpwind" +
                               meshName + "_Stat")

        #Postprocessing : Extraction of the diagonal data
        if (dim == 2):
            diag_data_u = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                unknown_field, [0, 1, 0], [1, 0, 0], resolution)
        elif (dim == 3):
            diag_data_u = VTK_routines.Extract_field_data_over_line_to_numpyArray(
                unknown_field, [0, 0, 0], [1, 1, 1], resolution)
        #Postprocessing : save 2D picture
        PV_routines.Save_PV_data_to_picture_file(
            "TransportEquation" + str(dim) + "DUpwind" + meshName + "_Stat" +
            '_0.vtu', "unknown", 'CELLS',
            "TransportEquation" + str(dim) + "DUpwind" + meshName + "_Stat")

        return nbCells, time, it, unknown_field.getNormEuclidean().max(
        ), diag_data_u
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
        raise ValueError(
            "Maximum time reached : Stationary state not found !!!!!!!")
def Transport1DCenteredImplicit(nx, cfl):
    print "Simulation of 1D transport equation with implicit centered scheme"

    ##################### Simulation parameters
    a = 0.0  # space domain :  a <= x <= b
    b = 1.0
    dx = (b - a) / nx  #space step

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

    if (cfl > nx):
        raise (
            "Impossible to run this simulation with cfl>nx. Choose another value for nx or cfl."
        )

    x = [a + 0.5 * dx + i * dx
         for i in range(nx)]  # array of cell center (1D mesh)

    ########################## Initial data

    u_initial = [
        0.5 * (1 + sin(4 * pi * xi - pi * .5)) * int(xi < 0.5) * int(0 < xi) +
        int(0.6 < xi) * int(xi < 0.85) for xi in x
    ]
    # to be used with a=0, b=1
    u = [
        0.5 * (1 + sin(4 * pi * xi - pi * .5)) * int(xi < 0.5) * int(0 < xi) +
        int(0.6 < xi) * int(xi < 0.85) for xi in x
    ]
    # to be used with a=0, b=1

    max_initial = max(u_initial)
    min_initial = min(u_initial)
    total_var_initial = np.sum(
        [abs(u_initial[i] - u_initial[(i - 1) % nx]) for i in range(nx)])

    time = 0.
    it = 0
    output_freq = 10

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

    # Video settings
    FFMpegWriter = manimation.writers['ffmpeg']
    metadata = dict(title="Centered implicit scheme for transport equation, " +
                    "CFL=" + str(cfl),
                    artist="CEA Saclay",
                    comment="Stable for any CFL>0")
    writer = FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
    with writer.saving(
            plt.figure(), "1DTransportEquation_CenteredImplicit_" + str(nx) +
            "Cells_CFL" + str(cfl) + ".mp4", ntmax):
        ########################### Postprocessing initialisation
        # Picture frame
        plt.legend()
        plt.xlabel('x')
        plt.ylabel('u')
        plt.xlim(a, b)
        plt.ylim(min_initial - 0.1 * (max_initial - min_initial),
                 max_initial + 0.1 * (max_initial - min_initial))
        plt.title("Centered implicit scheme for transport equation, " +
                  "CFL=" + str(cfl))
        line1, = plt.plot(
            x, u, label='u'
        )  #new picture for video # Returns a tuple of line objects, thus the comma

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

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

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

            time += dt
            it += 1

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

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

    print(
        "Simulation of transport equation with implicit centered scheme done.")

    #return min, max, total variation and l1 error
    return min(u), max(u), np.sum([
        abs(u[i] - u[(i - 1) % nx]) for i in range(nx)
    ]), dx * np.sum([abs(u[i] - u_initial[i]) for i in range(nx)])
Example #13
0
def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename, resolution):
    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)
    iterGMRESMax = 50

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

    # Initial conditions #
    print("Construction of the initial condition …")
    if (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")

    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 * velocity_field[k, 2]

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

    dx_min = my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0

    divMat = computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt)

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

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

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

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

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

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

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

    print "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)
    print "Variation temporelle relative : pressure ", maxVector[
        0] / p0, ", velocity x", maxVector[
            1] / rho0, ", velocity y", maxVector[2] / rho0
    print

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

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

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

    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
Example #14
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(nx,cfl,a,b, isSmooth):
    start = time.time()
    print "Transport equation, implicit scheme, nx= ", nx, " cfl= ", cfl
    ##################### Simulation parameters
    dx = (b - a) / nx #space step

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

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

    Time = 0.
    it = 0
    output_freq = 50

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

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

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

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

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

        Time += dt
        it += 1

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

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

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

    #return min, max, sol, total variation, l1 error and elapsed time
    return min(u), max(u), u, np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]), dx*np.sum([abs(u[i] - u_initial[i]) for i in range(nx)]), end-start
Example #16
0
def WaveSystemStaggered(ntmax, tmax, cfl, my_mesh, output_freq, meshName,
                        resolution, scaling, test_bc):
    dim = my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()

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

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

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

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

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

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

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

    dx_min = my_mesh.minRatioVolSurf()

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

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

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

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

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

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

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

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

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

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

        time = time + dt
        it = it + 1

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

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

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

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

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

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

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

        return delta_press / p0, delta_v.maxVector(
        )[0], nbCells, time, it, velocity_field.getNormEuclidean().max(
        ), diag_data_press, diag_data_vel, test_desc[
            "Linear_system_max_actual_condition number"]
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
        raise ValueError(
            "Maximum time reached : Stationary state not found !!!!!!!")
Example #17
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())
        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, "GMRES", "ILU")
SolSyst = LS.solve()

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

# 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("FiniteVolumes3DPoisson_CUBE_ResultField")
Example #18
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
Example #19
0
def TransportEquationVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution,test_bc,velocity,with_source=False):
    dim=my_mesh.getMeshDimension()
    nbCells = my_mesh.getNumberOfCells()
    
    dt = 0.
    time = 0.
    it=0;
    isStationary=False
    
    nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS)
    isImplicit=True
    
    #iteration vectors
    Un =cdmath.Vector(nbCells)
    dUn=cdmath.Vector(nbCells)
    
    # Initial conditions #
    print("Construction of the initial condition …")
    if(with_source):
        unknown_field = cdmath.Field("Unknown", cdmath.CELLS, my_mesh, 1)
        for k in range(nbCells):# fields initialisation
            unknown_field[k]   = 0
        S, stat_field=source_term_and_stat_solution_transport_equation(my_mesh)
    else:#The initial datum is a stationary field
        stat_field = initial_conditions_transport_equation(my_mesh)
        for k in range(nbCells):
            Un[k] =     stat_field[k]
        unknown_field = initial_conditions_transport_equation(my_mesh)
        S = cdmath.Vector(nbCells)#source term is zero
            
    #sauvegarde de la donnée initiale
    stat_field.setTime(time,it);
    stat_field.writeVTK("TransportEquation"+str(dim)+"DUpwind"+meshName);
    #Postprocessing : save 2D picture
    PV_routines.Save_PV_data_to_picture_file("TransportEquation"+str(dim)+"DUpwind"+meshName+'_0.vtu',"Unknown",'CELLS',"TransportEquation"+str(dim)+"DUpwind"+meshName+"_initial")

    total_mass_initial=unknown_field.integral()#For conservation test later
    
    dx_min=my_mesh.minRatioVolSurf()

    dt = cfl * dx_min / c0

    divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,test_bc,velocity)
    if(isImplicit):
        #Adding the identity matrix on the diagonal
        divMat.diagonalShift(1)#only after  filling all coefficients
        #for j in range(nbCells*(dim+1)):
        #    divMat.addValue(j,j,1)
        
        iterGMRESMax=50
        LS=cdmath.LinearSolver(divMat,Un+S*dt,iterGMRESMax, precision, "GMRES","ILU")
        LS.setComputeConditionNumber()
        
        test_desc["Linear_solver_algorithm"]=LS.getNameOfMethod()
        test_desc["Linear_solver_preconditioner"]=LS.getNameOfPc()
        test_desc["Linear_solver_precision"]=LS.getTolerance()
        test_desc["Linear_solver_maximum_iterations"]=LS.getNumberMaxOfIter()
        test_desc["Numerical_parameter_space_step"]=dx_min
        test_desc["Numerical_parameter_time_step"]=dt
    
        test_desc['Linear_system_max_actual_iterations_number']=0
        test_desc["Linear_system_max_actual_error"]=0
        test_desc["Linear_system_max_actual_condition number"]=0

    print("Starting computation of the linear transport equation with an Upwind scheme …")
    
    # Starting time loop
    while (it<ntmax and time <= tmax and not isStationary):
        if(isImplicit):
            dUn=Un.deepCopy()
            LS.setSndMember(Un+S*dt)
            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

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

        else:
            dUn=divMat*Un-S*dt
            Un-=dUn
        
        maxVector=dUn.maxVector(1)
        isStationary= maxVector[0]<precision 

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

            delta=0
            for k in range(nbCells):
                unknown_field[k]  =Un[k]
                if (abs(stat_field[k]-unknown_field[k])>delta):
                    delta=abs(stat_field[k]-unknown_field[k])
                
            unknown_field.setTime(time,it);
            unknown_field.writeVTK("TransportEquation"+str(dim)+"DUpwind"+meshName,False);

            print "Ecart au stationnaire exact = ",delta
            print
    print"-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)
    print "Variation temporelle relative : ", maxVector[0]

    if(it>=ntmax):
        print "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint"
        raise ValueError("Maximum number of time steps reached : Stationary state not found !!!!!!!")
    elif(isStationary):
        print "Régime stationnaire atteint au pas de temps ", it, ", t= ", time
        if(not with_source and test_bc=="Periodic"):
            print "Mass loss: ", (total_masse_initial-unknown_field.integral()).norm(), " precision required= ", precision
            assert (total_mass_initial-unknown_field.integral()).norm()<precision
            if():
        print "------------------------------------------------------------------------------------"

        unknown_field.setTime(time,0);
        unknown_field.writeVTK("TransportEquation"+str(dim)+"DUpwind"+meshName+"_Stat");

        #Postprocessing : Extraction of the diagonal data
        if(dim==2):
            diag_data_press=VTK_routines.Extract_field_data_over_line_to_numpyArray(unknown_field,[0,1,0],[1,0,0], resolution)    
        elif(dim==3):
            diag_data_press=VTK_routines.Extract_field_data_over_line_to_numpyArray(unknown_field,[0,0,0],[1,1,1], resolution)    
        #Postprocessing : save 2D picture
        PV_routines.Save_PV_data_to_picture_file("TransportEquation"+str(dim)+"DUpwind"+meshName+"_Stat"+'_0.vtu',"Unknown",'CELLS',"TransportEquation"+str(dim)+"DUpwind"+meshName+"_Stat")
        
        return delta, nbCells, time, it, unknwon_field.getNormEuclidean().max(), diag_data_press, diag_data_vel
    else:
        print "Temps maximum Tmax= ", tmax, " atteint"
        raise ValueError("Maximum time reached : Stationary state not found !!!!!!!")