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
def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, filename,resolution, isImplicit): dim=my_mesh.getMeshDimension() nbCells = my_mesh.getNumberOfCells() meshName=my_mesh.getName() dt = 0. time = 0. it=0; isStationary=False; nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS) # Initial conditions # print("Construction of the initial condition …") if(filename.find("square")>-1 or filename.find("Square")>-1 or filename.find("cube")>-1 or filename.find("Cube")>-1): pressure_field, velocity_field = initial_conditions_square_vortex(my_mesh) elif(filename.find("disk")>-1 or filename.find("Disk")>-1): pressure_field, velocity_field = initial_conditions_disk_vortex(my_mesh) else: print "Mesh name : ", filename raise ValueError("Mesh name should contain substring square, cube or disk") #iteration vectors Un =cdmath.Vector(nbCells*(dim+1)) dUn=cdmath.Vector(nbCells*(dim+1)) for k in range(nbCells): Un[k*(dim+1)+0] = pressure_field[k] Un[k*(dim+1)+1] =rho0*velocity_field[k,0] Un[k*(dim+1)+2] =rho0*velocity_field[k,1] if(dim==3): Un[k*(dim+1)+3] =rho0*velocity_field[k,2] #sauvegarde de la donnée initiale pressure_field.setTime(time,it); pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure"); velocity_field.setTime(time,it); velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity"); dx_min=my_mesh.minRatioVolSurf() dt = cfl * dx_min / c0 divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt) if( isImplicit): #Adding the identity matrix on the diagonal divMat.diagonalShift(1)#only after filling all coefficients iterGMRESMax=50 LS=cdmath.LinearSolver(divMat,Un,iterGMRESMax, precision, "GMRES","ILU") LS.setComputeConditionNumber() print("Starting computation of the linear wave system with an UPWIND scheme …") print "coucou2" # Starting time loop while (it<ntmax and time <= tmax and not isStationary): if(isImplicit): dUn=Un.deepCopy() LS.setSndMember(Un) Un=LS.solve(); if(not LS.getStatus()): print "Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations" raise ValueError("Pas de convergence du système linéaire"); dUn-=Un else: dUn=divMat*Un Un-=dUn time=time+dt; it=it+1; #Sauvegardes if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax): print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) for k in range(nbCells): pressure_field[k] =Un[k*(dim+1)+0] velocity_field[k,0]=Un[k*(dim+1)+1]/rho0 if(dim>1): velocity_field[k,1]=Un[k*(dim+1)+2]/rho0 if(dim>2): velocity_field[k,2]=Un[k*(dim+1)+3]/rho0 pressure_field.setTime(time,it); pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure",False); velocity_field.setTime(time,it); velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity",False); print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt)) print if(it>=ntmax): print "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" elif(isStationary): print "Régime stationnaire atteint au pas de temps ", it, ", t= ", time pressure_field.setTime(time,0); pressure_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat"); velocity_field.setTime(time,0); velocity_field.writeVTK("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat"); #Postprocessing : Extraction of the diagonal data diag_data_press=VTK_routines.Extract_field_data_over_line_to_numpyArray(pressure_field,[0,1,0],[1,0,0], resolution) diag_data_vel =VTK_routines.Extract_field_data_over_line_to_numpyArray(velocity_field,[0,1,0],[1,0,0], resolution) #Postprocessing : save 2D picture PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat"+'_0.vtu',"Pressure",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_pressure_Stat") PV_routines.Save_PV_data_to_picture_file("WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat"+'_0.vtu',"Velocity",'CELLS',"WaveSystem"+str(dim)+"DUpwind"+meshName+"_velocity_Stat") else: print "Temps maximum Tmax= ", tmax, " atteint"
def solve(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
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 !!!!!!!")
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 !!!!!!!")
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"
def WaveSystemVF(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution, scaling, test_bc): dim = my_mesh.getMeshDimension() nbCells = my_mesh.getNumberOfCells() dt = 0. time = 0. it = 0 isStationary = False nbVoisinsMax = my_mesh.getMaxNbNeighbours(cdmath.CELLS) iterGMRESMax = 50 #iteration vectors Un = cdmath.Vector(nbCells * (dim + 1)) dUn = cdmath.Vector(nbCells * (dim + 1)) # Initial conditions # print("Construction of the initial condition …") if (meshName.find("square") == -1 and meshName.find("Square") == -1 and meshName.find("cube") == -1 and meshName.find("Cube") == -1): print "Mesh name : ", meshName raise ValueError( "Mesh name should contain substring square or cube to use wave system with stiff source term" ) else: S, stat_pressure, stat_momentum = source_term_and_stat_solution_wave_system( my_mesh) pressure_field = stat_pressure.deepCopy() momentum_field = stat_momentum.deepCopy() for k in range(nbCells): Un[k * (dim + 1) + 0] = pressure_field[k] Un[k * (dim + 1) + 1] = momentum_field[k, 0] Un[k * (dim + 1) + 2] = momentum_field[k, 1] if (dim == 3): Un[k * (dim + 1) + 3] = momentum_field[k, 2] if (scaling == 1): Vn = Un.deepCopy() for k in range(nbCells): Vn[k * (dim + 1) + 0] = Vn[k * (dim + 1) + 0] / (c0 * c0) S[k * (dim + 1) + 0] = S[k * (dim + 1) + 0] / (c0 * c0) elif (scaling == 2): Vn = Un.deepCopy() for k in range(nbCells): Vn[k * (dim + 1) + 0] = Vn[k * (dim + 1) + 0] / c0 S[k * (dim + 1) + 0] = S[k * (dim + 1) + 0] / c0 #sauvegarde de la donnée initiale pressure_field.setTime(time, it) pressure_field.writeVTK("WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure") momentum_field.setTime(time, it) momentum_field.writeVTK("WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum") #Postprocessing : save 2D picture PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure_initial") PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum" + '_0.vtu', "Momentum", 'CELLS', "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum_initial") total_pressure_initial = pressure_field.integral( ) #For conservation test later total_momentum_initial = momentum_field.integral( ) #For conservation test later dx_min = my_mesh.minRatioVolSurf() dt = cfl * dx_min / c0 divMat = computeDivergenceMatrix(my_mesh, nbVoisinsMax, dt, scaling, test_bc) #Adding the momentum friction term for j in range(nbCells): for i in range(dim): divMat.addValue(j * (dim + 1) + 1 + i, j * (dim + 1) + 1 + i, dt) #Add the identity matrix on the diagonal if (scaling == 0 or scaling == 2): divMat.diagonalShift(1) #only after filling all coefficients else: for j in range(nbCells): divMat.addValue(j * (dim + 1), j * (dim + 1), 1 / (c0 * c0)) #/(c0*c0) for i in range(dim): divMat.addValue(j * (dim + 1) + 1 + i, j * (dim + 1) + 1 + i, 1) if (scaling == 0): LS = cdmath.LinearSolver(divMat, Un + S * dt, iterGMRESMax, precision, "GMRES", "ILU") else: LS = cdmath.LinearSolver(divMat, Vn + S * dt, iterGMRESMax, precision, "GMRES", "ILU") LS.setComputeConditionNumber() test_desc["Linear_solver_algorithm"] = LS.getNameOfMethod() test_desc["Linear_solver_preconditioner"] = LS.getNameOfPc() test_desc["Linear_solver_precision"] = LS.getTolerance() test_desc["Linear_solver_maximum_iterations"] = LS.getNumberMaxOfIter() test_desc["Numerical_parameter_space_step"] = dx_min test_desc["Numerical_parameter_time_step"] = dt test_desc["Linear_solver_with_scaling"] = scaling test_desc['Linear_system_max_actual_iterations_number'] = 0 test_desc["Linear_system_max_actual_error"] = 0 test_desc["Linear_system_max_actual_condition number"] = 0 print( "Starting computation of the linear wave system with a pseudo staggered scheme …" ) # Starting time loop while (it < ntmax and time <= tmax and not isStationary): dUn = Un.deepCopy() if (scaling == 0): LS.setSndMember(Un + S * dt) else: LS.setSndMember(Vn + S * dt) if (scaling < 2): Un = LS.solve() if (scaling == 1): Vn = Un.deepCopy() for k in range(nbCells): Vn[k * (dim + 1) + 0] = Vn[k * (dim + 1) + 0] / (c0 * c0) else: #( scaling==2) Vn = LS.solve() Un = Vn.deepCopy() for k in range(nbCells): Un[k * (dim + 1) + 0] = c0 * Vn[k * (dim + 1) + 0] if (not LS.getStatus()): print "Linear system did not converge ", iterGMRES, " GMRES iterations" raise ValueError("Pas de convergence du système linéaire") dUn -= Un test_desc["Linear_system_max_actual_iterations_number"] = max( LS.getNumberOfIter(), test_desc["Linear_system_max_actual_iterations_number"]) test_desc["Linear_system_max_actual_error"] = max( LS.getResidu(), test_desc["Linear_system_max_actual_error"]) test_desc["Linear_system_max_actual_condition number"] = max( LS.getConditionNumber(), test_desc["Linear_system_max_actual_condition number"]) maxVector = dUn.maxVector(dim + 1) isStationary = maxVector[0] < precision and maxVector[ 1] / rho0 < precision and maxVector[2] / rho0 < precision if (dim == 3): isStationary = isStationary and maxVector[3] / rho0 < precision time = time + dt it = it + 1 #Sauvegardes if (it == 1 or it % output_freq == 0 or it >= ntmax or isStationary or time >= tmax): print "-- Iter: " + str(it) + ", Time: " + str( time) + ", dt: " + str(dt) print "Variation temporelle relative : pressure ", maxVector[ 0], ", velocity x", maxVector[ 1] / rho0, ", velocity y", maxVector[2] / rho0 print "Linear system converged in ", LS.getNumberOfIter( ), " GMRES iterations" delta_press = 0 delta_q = cdmath.Vector(dim) for k in range(nbCells): pressure_field[k] = Un[k * (dim + 1) + 0] momentum_field[k, 0] = Un[k * (dim + 1) + 1] / rho0 if (dim > 1): momentum_field[k, 1] = Un[k * (dim + 1) + 2] / rho0 if (dim > 2): momentum_field[k, 2] = Un[k * (dim + 1) + 3] / rho0 if (abs(stat_pressure[k] - pressure_field[k]) > delta_press): delta_press = abs(stat_pressure[k] - pressure_field[k]) if (abs(stat_momentum[k, 0] - momentum_field[k, 0]) > delta_q[0]): delta_q[0] = abs(stat_momentum[k, 0] - momentum_field[k, 0]) if (abs(stat_momentum[k, 1] - momentum_field[k, 1]) > delta_q[1]): delta_q[1] = abs(stat_momentum[k, 1] - momentum_field[k, 1]) if (dim == 3): if (abs(stat_momentum[k, 2] - momentum_field[k, 2]) > delta_q[2]): delta_q[2] = abs(stat_momentum[k, 2] - momentum_field[k, 2]) pressure_field.setTime(time, it) pressure_field.writeVTK( "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure", False) momentum_field.setTime(time, it) momentum_field.writeVTK( "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum", False) print "Ecart au stationnaire exact : error_p= ", delta_press, " error_||q||= ", delta_q.maxVector( )[0] print print "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) print "Variation temporelle relative : pressure ", maxVector[ 0], ", velocity x", maxVector[1] / rho0, ", velocity y", maxVector[ 2] / rho0 print if (it >= ntmax): print "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint" raise ValueError( "Maximum number of time steps reached : Stationary state not found !!!!!!!" ) elif (isStationary): print "Régime stationnaire atteint au pas de temps ", it, ", t= ", time print "------------------------------------------------------------------------------------" pressure_field.setTime(time, 0) pressure_field.writeVTK("WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure_Stat") momentum_field.setTime(time, 0) momentum_field.writeVTK("WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum_Stat") #Postprocessing : Extraction of the diagonal data if (dim == 2): diag_data_press = VTK_routines.Extract_field_data_over_line_to_numpyArray( pressure_field, [0, 1, 0], [1, 0, 0], resolution) diag_data_vel = VTK_routines.Extract_field_data_over_line_to_numpyArray( momentum_field, [0, 1, 0], [1, 0, 0], resolution) elif (dim == 3): diag_data_press = VTK_routines.Extract_field_data_over_line_to_numpyArray( pressure_field, [0, 0, 0], [1, 1, 1], resolution) diag_data_vel = VTK_routines.Extract_field_data_over_line_to_numpyArray( momentum_field, [0, 0, 0], [1, 1, 1], resolution) #Postprocessing : save 2D picture PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure_Stat" + '_0.vtu', "Pressure", 'CELLS', "WaveSystem" + str(dim) + "DPStag" + meshName + "_pressure_Stat") PV_routines.Save_PV_data_to_picture_file( "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum_Stat" + '_0.vtu', "Momentum", 'CELLS', "WaveSystem" + str(dim) + "DPStag" + meshName + "_momentum_Stat") return delta_press, delta_q.maxVector( )[0], nbCells, time, it, momentum_field.getNormEuclidean().max( ), diag_data_press, diag_data_vel, test_desc[ "Linear_system_max_actual_condition number"] else: print "Temps maximum Tmax= ", tmax, " atteint" raise ValueError( "Maximum time reached : Stationary state not found !!!!!!!")
def 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
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)])
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"
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
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 !!!!!!!")
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")
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
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 !!!!!!!")