4 #===============================================================================================================================
5 # Name : Résolution VF du système des ondes 2D sans terme source
6 # \partial_t p + c^2 \div q = 0
7 # \partial_t q + \grad p = 0
8 # Author : Michaël Ndjinga
9 # Copyright : CEA Saclay 2019
10 # Description : Propagation d'une onde de choc sphérique
11 # Utilisation du schéma MAC sur un maillage cartésien
12 # Initialisation par une surpression sphérique
13 # Conditions aux limites périodiques
14 # Création et sauvegarde du champ résultant et des figures
15 #================================================================================================================================
24 p0=155e5#reference pressure in a pressurised nuclear vessel
25 c0=700.#reference sound speed for water at 155 bars, 600K
26 rho0=p0/c0*c0#reference density
29 def initial_conditions_shock(my_mesh, isCircle):
30 print( "Initial data : Spherical wave")
31 dim = my_mesh.getMeshDimension()
32 nbCells = my_mesh.getNumberOfCells()
44 pressure_field = cdmath.Field("Pressure", cdmath.CELLS, my_mesh, 1)
45 velocity_field = cdmath.Field("Velocity", cdmath.CELLS, my_mesh, 3)
47 for i in range(nbCells):
48 velocity_field[i,0] = 0
49 velocity_field[i,1] = 0
50 velocity_field[i,2] = 0
52 x = my_mesh.getCell(i).x()
53 valX = (x - xcentre) * (x - xcentre)
58 y = my_mesh.getCell(i).y()
59 valY = (y - ycentre) * (y - ycentre)
60 val = sqrt(valX + valY)
62 y = my_mesh.getCell(i).y()
63 z = my_mesh.getCell(i).z()
64 valY = (y - ycentre) * (y - ycentre)
65 valZ = (z - zcentre) * (z - zcentre)
66 val = sqrt(valX + valY + valZ)
69 pressure_field[i] = p0
72 pressure_field[i] = p0/2
76 return pressure_field, velocity_field
78 def computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,scaling):
79 nbCells = my_mesh.getNumberOfCells()
80 dim=my_mesh.getMeshDimension()
83 if(not my_mesh.isStructured()):
84 raise ValueError("WaveSystemStaggered: the mesh should be structured");
86 NxNyNz=my_mesh.getCellGridStructure()
87 DxDyDz=my_mesh.getDXYZ()
89 implMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp)
91 idMoinsJacCL=cdmath.Matrix(nbComp)
98 for k in range(nbCells):
99 implMat.addValue(k,1*nbCells + k , -c0*c0*dt/dx)
100 implMat.addValue(k,1*nbCells + (k+1)%nx, c0*c0*dt/dx)
102 implMat.addValue( 1*nbCells + k ,k, dt/dx)
103 implMat.addValue( 1*nbCells + (k+1)%nx,k, -dt/dx)
105 for k in range(nbCells):
106 implMat.addValue(k,1*nbCells + k , -c0*dt/dx)
107 implMat.addValue(k,1*nbCells + (k+1)%nx, c0*dt/dx)
109 implMat.addValue( 1*nbCells + k ,k, c0*dt/dx)
110 implMat.addValue( 1*nbCells + (k+1)%nx,k, -c0*dt/dx)
112 elif( dim == 2) :# k = j*nx+i
119 for k in range(nbCells):
123 implMat.addValue(k,1*nbCells + j*nx + i , -c0*c0*dt/dx)
124 implMat.addValue(k,1*nbCells + j*nx + (i+1)%nx, c0*c0*dt/dx)
126 implMat.addValue(k,2*nbCells + j *nx + i, -c0*c0*dt/dy)
127 implMat.addValue(k,2*nbCells + ((j+1)%ny)*nx + i, c0*c0*dt/dy)
129 implMat.addValue( 1*nbCells + j*nx + i , k, dt/dx)
130 implMat.addValue( 1*nbCells + j*nx + (i+1)%nx, k, -dt/dx)
132 implMat.addValue( 2*nbCells + j *nx + i,k, dt/dy)
133 implMat.addValue( 2*nbCells + ((j+1)%ny)*nx + i,k, -dt/dy)
136 for k in range(nbCells):
140 implMat.addValue(k,1*nbCells + j*nx + i , -c0*dt/dx)
141 implMat.addValue(k,1*nbCells + j*nx + (i+1)%nx, c0*dt/dx)
143 implMat.addValue(k,2*nbCells + j *nx + i, -c0*dt/dy)
144 implMat.addValue(k,2*nbCells + ((j+1)%ny)*nx + i, c0*dt/dy)
146 implMat.addValue( 1*nbCells + j*nx + i , k, c0*dt/dx)
147 implMat.addValue( 1*nbCells + j*nx + (i+1)%nx, k, -c0*dt/dx)
149 implMat.addValue( 2*nbCells + j *nx + i,k, c0*dt/dy)
150 implMat.addValue( 2*nbCells + ((j+1)%ny)*nx + i,k, -c0*dt/dy)
152 elif( dim == 3) :# k = l*nx*ny+j*nx+i
161 for k in range(nbCells):
166 implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + i , -c0*c0*dt/dx)
167 implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + (i+1)%nx, c0*c0*dt/dx)
169 implMat.addValue(k,2*nbCells + l*nx*ny + j *nx + i, -c0*c0*dt/dy)
170 implMat.addValue(k,2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i, c0*c0*dt/dy)
172 implMat.addValue(k,3*nbCells + l*nx*ny + j*nx + i, -c0*c0*dt/dz)
173 implMat.addValue(k,3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i, c0*c0*dt/dz)
175 implMat.addValue( 1*nbCells + l*nx*ny + j*nx + i , k, dt/dx)
176 implMat.addValue( 1*nbCells + l*nx*ny + j*nx + (i+1)%nx, k, -dt/dx)
178 implMat.addValue( 2*nbCells + l*nx*ny + j *nx + i,k, dt/dy)
179 implMat.addValue( 2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i,k, -dt/dy)
181 implMat.addValue( 3*nbCells + l*nx*ny + j*nx + i,k, dt/dz)
182 implMat.addValue( 3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i,k, -dt/dz)
185 for k in range(nbCells):
190 implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + i , -c0*dt/dx)
191 implMat.addValue(k,1*nbCells + l*nx*ny + j*nx + (i+1)%nx, c0*dt/dx)
193 implMat.addValue(k,2*nbCells + l*nx*ny + j *nx + i, -c0*dt/dy)
194 implMat.addValue(k,2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i, c0*dt/dy)
196 implMat.addValue(k,3*nbCells + l*nx*ny + j*nx + i, -c0*dt/dz)
197 implMat.addValue(k,3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i, c0*dt/dz)
199 implMat.addValue( 1*nbCells + l*nx*ny + j*nx + i , k, c0*dt/dx)
200 implMat.addValue( 1*nbCells + l*nx*ny + j*nx + (i+1)%nx, k, -c0*dt/dx)
202 implMat.addValue( 2*nbCells + l*nx*ny + j *nx + i,k, c0*dt/dy)
203 implMat.addValue( 2*nbCells + l*nx*ny + ((j+1)%ny)*nx + i,k, -c0*dt/dy)
205 implMat.addValue( 3*nbCells + l*nx*ny + j*nx + i,k, c0*dt/dz)
206 implMat.addValue( 3*nbCells + ((l+1)%nz)*nx*ny + j*nx + i,k, -c0*dt/dz)
210 def WaveSystemStaggered(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution):
211 dim=my_mesh.getMeshDimension()
212 nbCells = my_mesh.getNumberOfCells()
221 nbVoisinsMax=my_mesh.getMaxNbNeighbours(cdmath.CELLS)
225 Un=cdmath.Vector(nbCells*(dim+1))
226 dUn=cdmath.Vector(nbCells*(dim+1))
228 # Initial conditions #
229 print("Construction of the initial condition …")
230 if(dim==1 or meshName.find("square")>-1 or meshName.find("Square")>-1 or meshName.find("cube")>-1 or meshName.find("Cube")>-1):
231 pressure_field, velocity_field = initial_conditions_shock(my_mesh,False)
232 elif(meshName.find("disk")>-1 or meshName.find("Disk")>-1):
233 pressure_field, velocity_field = initial_conditions_shock(my_mesh,True)
235 print( "Mesh name : ", meshName )
236 raise ValueError("Mesh name should contain substring square, cube or disk")
238 for k in range(nbCells):
239 Un[k + 0*nbCells] = pressure_field[k]
240 Un[k + 1*nbCells] = rho0*velocity_field[k,0] # value on the left face
242 Un[k + 2*nbCells] = rho0*velocity_field[k,1] # value on the bottom face
244 Un[k + 3*nbCells] = rho0*velocity_field[k,2]
248 for k in range(nbCells):
251 #sauvegarde de la donnée initiale
252 pressure_field.setTime(time,it);
253 pressure_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure");
254 velocity_field.setTime(time,it);
255 velocity_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity");
256 #Postprocessing : save 2D picture
257 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")
258 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")
260 dx_min=my_mesh.minRatioVolSurf()
262 dt = cfl * dx_min / c0
264 divMat=computeDivergenceMatrix(my_mesh,nbVoisinsMax,dt,scaling)
266 #Add the identity matrix on the diagonal
267 for j in range(nbCells*(dim+1)):
268 divMat.addValue(j,j,1)
270 LS=cdmath.LinearSolver(divMat,Un,iterGMRESMax, precision, "GMRES","LU")
272 print("Starting computation of the linear wave system with an pseudo staggered scheme …")
275 while (it<ntmax and time <= tmax and not isStationary):
279 cvgceLS=LS.getStatus();
280 iterGMRES=LS.getNumberOfIter();
282 print( "Linear system did not converge ", iterGMRES, " GMRES iterations")
283 raise ValueError("Pas de convergence du système linéaire");
287 for k in range(nbCells):
288 max_dp = max(max_dp,abs(dUn[k]))
290 max_dq=max(max_dq,abs(dUn[k+(1+i)*nbCells]))
292 isStationary= max_dp/p0<precision and max_dq/rho0<precision
298 if(it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
299 print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
300 print( "Variation temporelle relative : pressure ", max_dp/p0 ,", velocity ", max_dq/rho0 )
301 print( "Linear system converged in ", iterGMRES, " GMRES iterations" )
303 for k in range(nbCells):
304 pressure_field[k]=Un[k]
305 velocity_field[k,0]=Un[k+1*nbCells]/rho0
307 velocity_field[k,1]=Un[k+2*nbCells]/rho0
309 velocity_field[k,2]=Un[k+3*nbCells]/rho0
311 pressure_field.setTime(time,it);
312 pressure_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure",False);
313 velocity_field.setTime(time,it);
314 velocity_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity",False);
316 print( "-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt) )
317 print( "Variation temporelle relative : pressure ", max_dp/p0 ,", velocity ", max_dq/rho0 )
321 print( "Nombre de pas de temps maximum ntmax= ", ntmax, " atteint")
323 print( "Régime stationnaire atteint au pas de temps ", it, ", t= ", time)
324 print( "------------------------------------------------------------------------------------")
326 pressure_field.setTime(time,0);
327 pressure_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_pressure_Stat");
328 velocity_field.setTime(time,0);
329 velocity_field.writeVTK("WaveSystem"+str(dim)+"DStaggered"+meshName+"_velocity_Stat");
331 #Postprocessing : save 2D picture
332 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")
333 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")
336 print( "Temps maximum Tmax= ", tmax, " atteint")
339 def solve(my_mesh,meshName,resolution):
340 print( "Resolution of the Wave system in dimension ", my_mesh.getSpaceDimension() )
341 print( "Numerical method : staggered scheme" )
342 print( "Initial data : Spherical wave" )
343 print( "Periodic boundary conditions" )
344 print( "Mesh name : ",meshName , my_mesh.getNumberOfCells(), " cells" )
349 cfl = 1./my_mesh.getSpaceDimension()
352 WaveSystemStaggered(ntmax, tmax, cfl, my_mesh, output_freq, meshName, resolution)
354 def solve_file( filename,meshName, resolution):
355 my_mesh = cdmath.Mesh(filename+".med")
357 return solve(my_mesh, meshName+str(my_mesh.getNumberOfCells()),resolution)
360 if __name__ == """__main__""":
361 if len(sys.argv) >1 :
362 my_mesh = cdmath.Mesh(sys.argv[1])
363 solve(my_mesh,my_mesh.getName(),100)
366 my_mesh = cdmath.Mesh(0,1,nx,0,1,nx)
367 solve(my_mesh,"square",100)