4 # Isothermal Euler system
5 # d rho/d t + d q/d x =0
6 # d q/d t + d (q^2/rho+p)/d x = 0, where q = rho*u and p = c^2*rho
7 # UU = (rho,q) : conservative variable
8 # Scheme : Conservative stagerred scheme (Ait Ameur et al)
9 # Author : Katia Ait Ameur
10 # Date : November 2020
16 import matplotlib.pyplot as plt
17 import matplotlib.animation as manimation
20 c0=330.#reference sound speed for water at 15 bars
24 def initial_conditions_Riemann_problem(a,b,nx):
25 print("Initial data Riemann problem")
26 dx = (b - a) / nx #space step
27 x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh)
28 rho_initial = [ (xi<(a+b)/2)*rho0 + (xi>=(a+b)/2)*rho0*2 for xi in x]
29 q_initial = [ (xi<(a+b)/2)*rho0*(-300) + (xi>=(a+b)/2)*rho0*2*(-300) for xi in x]
31 return rho_initial, q_initial
33 def matrix_coef(rho_l,q_l,rho_r,q_r):
34 m_coef = -0.5*(q_l-q_r)/rho_r
37 def jacobianMatricesm(coeff,rho_l,q_l,rho_r,q_r):
38 RoeMat = cdmath.Matrix(2,2);
39 Dmac = cdmath.Matrix(2,2);
43 Dmac_coef = matrix_coef(rho_l,q_l,rho_r,q_r)
44 if rho_l<0 or rho_r<0 :
45 print( "rho_l=",rho_l, " rho_r= ",rho_r)
46 raise ValueError("Negative density")
47 u = (u_l*sqrt(rho_l)+u_r*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));
50 RoeMat[1,0] = c0*c0 - u*u
55 Dmac[1,0]= -c0*c0-u*u;
58 return (RoeMat-Dmac)*coeff*0.5
60 def jacobianMatricesp(coeff,rho_l,q_l,rho_r,q_r):
61 RoeMat = cdmath.Matrix(2,2);
62 Dmac = cdmath.Matrix(2,2);
66 Dmac_coef = matrix_coef(rho_l,q_l,rho_r,q_r)
67 if rho_l<0 or rho_r<0 :
68 print( "rho_l=",rho_l, " rho_r= ",rho_r)
69 raise ValueError("Negative density")
70 u = (u_l*sqrt(rho_l)+u_r*sqrt(rho_r))/(sqrt(rho_l)+sqrt(rho_r));
73 RoeMat[1,0] = c0*c0 - u*u
78 Dmac[1,0]= -c0*c0-u*u;
81 return (RoeMat+Dmac)*coeff*0.5
83 def EulerSystemStaggered(ntmax, tmax, cfl, a,b,nx, output_freq, meshName):
99 Un =cdmath.Vector(nbCells*(dim+1))
100 dUn=cdmath.Vector(nbCells*(dim+1))
101 dUk=cdmath.Vector(nbCells*(dim+1))
102 Rhs=cdmath.Vector(nbCells*(dim+1))
104 # Initial conditions #
105 print("Construction of the initial condition …")
106 rho_field, q_field = initial_conditions_Riemann_problem(a,b,nx)
107 v_field = [ q_field[i]/rho_field[i] for i in range(nx)]
108 p_field = [ rho_field[i]*(c0*c0) for i in range(nx)]
110 max_initial_rho=max(rho_field)
111 min_initial_rho=min(rho_field)
112 max_initial_q=max(q_field)
113 min_initial_q=min(q_field)
114 max_initial_p=max(p_field)
115 min_initial_p=min(p_field)
116 max_initial_v=max(v_field)
117 min_initial_v=min(v_field)
119 for k in range(nbCells):
120 Un[k*nbComp+0] = rho_field[k]
121 Un[k*nbComp+1] = q_field[k]
123 print("Starting computation of the non linear Euler system with staggered scheme …")
124 divMat=cdmath.SparseMatrixPetsc(nbCells*nbComp,nbCells*nbComp,(nbVoisinsMax+1)*nbComp)
127 fig, ([axDensity, axMomentum],[axVelocity, axPressure]) = plt.subplots(2, 2,sharex=True, figsize=(10,10))
128 fig.suptitle('Conservative staggered scheme')
129 lineDensity, = axDensity.plot([a+0.5*dx + i*dx for i in range(nx)], rho_field, label='Density') #new picture for video # Returns a tuple of line objects, thus the comma
130 axDensity.set(xlabel='x (m)', ylabel='Density')
131 axDensity.set_xlim(a,b)
132 axDensity.set_ylim(min_initial_rho - 0.1*(max_initial_rho-min_initial_rho), max_initial_rho + 0.1*(max_initial_rho-min_initial_rho) )
134 lineMomentum, = axMomentum.plot([a+0.5*dx + i*dx for i in range(nx)], q_field, label='Momentum')
135 axMomentum.set(xlabel='x (m)', ylabel='Momentum')
136 axMomentum.set_xlim(a,b)
137 axMomentum.set_ylim(min_initial_q - 0.1*(max_initial_q-min_initial_q), max_initial_q + 0.1*(max_initial_q-min_initial_q) )
139 lineVelocity, = axVelocity.plot([a+0.5*dx + i*dx for i in range(nx)], v_field, label='Velocity')
140 axVelocity.set(xlabel='x (m)', ylabel='Velocity')
141 axVelocity.set_xlim(a,b)
142 axVelocity.set_ylim(min_initial_v - 0.4*abs(min_initial_v), max_initial_v + 0.05*abs(max_initial_v) )
144 linePressure, = axPressure.plot([a+0.5*dx + i*dx for i in range(nx)], p_field, label='Pressure')
145 axPressure.set(xlabel='x (m)', ylabel='Pressure')
146 axPressure.set_xlim(a,b)
147 axPressure.set_ylim(min_initial_p - 0.05*abs(min_initial_p), max_initial_p + 0.05*abs(max_initial_p) )
148 axPressure.ticklabel_format(axis='y', style='sci', scilimits=(0,0))
152 FFMpegWriter = manimation.writers['ffmpeg']
153 metadata = dict(title="Conservative staggered scheme for the 1D isothermal Euler System", artist = "CEA Saclay", comment="Shock tube")
154 writer=FFMpegWriter(fps=10, metadata=metadata, codec='h264')
155 with writer.saving(fig, "1DEuler_System_ConservativeStaggered"+".mp4", ntmax):
157 plt.savefig("EulerSystem"+str(dim)+"D_ConservativeStaggered"+meshName+"_0"+".png")
160 while (it<ntmax and time <= tmax and not isStationary):
165 while (k<newton_max and residu > precision ):
167 divMat.zeroEntries()#sets the matrix coefficients to zero
168 for j in range(nbCells):#
170 rho_r = Uk[j*nbComp+0]
172 rho_l = rho_r # Conditions de Neumann
174 Am= jacobianMatricesm(dt/dx,rho_l,q_l,rho_r,q_r)
175 divMat.addValue(j*nbComp,(j+1)*nbComp,Am)
176 divMat.addValue(j*nbComp, j*nbComp,Am*(-1.))
178 dUi[0] = Uk[(j+1)*nbComp+0]-Uk[j*nbComp+0]
179 dUi[1] = Uk[(j+1)*nbComp+1]-Uk[j*nbComp+1]
180 temp=cdmath.Vector(2)
182 #print("Bloc 0 matrix : ", Am)
183 Rhs[j*nbComp+0] = -temp[0]-(Uk[j*nbComp+0]-Un[j*nbComp+0])
184 Rhs[j*nbComp+1] = -temp[1]-(Uk[j*nbComp+1]-Un[j*nbComp+1])
185 elif ( j==nbCells-1) :
186 rho_l = Uk[j*nbComp+0]
188 rho_r = rho_l # Conditions de Neumann
190 Ap= jacobianMatricesp(dt/dx,rho_l,q_l,rho_r,q_r)
191 divMat.addValue(j*nbComp, j*nbComp,Ap)
192 divMat.addValue(j*nbComp,(j-1)*nbComp,Ap*(-1.))
194 dUi[0] = Uk[(j-1)*nbComp+0]-Uk[j*nbComp+0]
195 dUi[1] = Uk[(j-1)*nbComp+1]-Uk[j*nbComp+1]
196 temp=cdmath.Vector(2)
198 Rhs[j*nbComp+0] = temp[0]-(Uk[j*nbComp+0]-Un[j*nbComp+0])
199 Rhs[j*nbComp+1] = temp[1]-(Uk[j*nbComp+1]-Un[j*nbComp+1])
201 rho_l = Uk[(j-1)*nbComp+0]
202 q_l = Uk[(j-1)*nbComp+1]
203 rho_r = Uk[j*nbComp+0]
205 Ap = jacobianMatricesp(dt/dx,rho_l,q_l,rho_r,q_r)
206 ###############################################################
207 rho_l = Uk[j*nbComp+0]
209 rho_r = Uk[(j+1)*nbComp+0]
210 q_r = Uk[(j+1)*nbComp+1]
211 Am = jacobianMatricesm(dt/dx,rho_l,q_l,rho_r,q_r)
212 divMat.addValue(j*nbComp,(j+1)*nbComp,Am)
213 divMat.addValue(j*nbComp, j*nbComp,Am*(-1.))
214 divMat.addValue(j*nbComp, j*nbComp,Ap)
215 divMat.addValue(j*nbComp,(j-1)*nbComp,Ap*(-1.))
216 dUi1=cdmath.Vector(2)
217 dUi2=cdmath.Vector(2)
218 dUi1[0] = Uk[(j+1)*nbComp+0]-Uk[j*nbComp+0]
219 dUi1[1] = Uk[(j+1)*nbComp+1]-Uk[j*nbComp+1]
220 dUi2[0] = Uk[(j-1)*nbComp+0]-Uk[j*nbComp+0]
221 dUi2[1] = Uk[(j-1)*nbComp+1]-Uk[j*nbComp+1]
222 temp1 = cdmath.Vector(2)
223 temp2 = cdmath.Vector(2)
226 Rhs[j*nbComp+0] = -temp1[0] + temp2[0] -(Uk[j*nbComp+0]-Un[j*nbComp+0])
227 Rhs[j*nbComp+1] = -temp1[1] + temp2[1] -(Uk[j*nbComp+1]-Un[j*nbComp+1])
228 divMat.diagonalShift(1)#only after filling all coefficients
229 LS=cdmath.LinearSolver(divMat,Rhs,iterGMRESMax, precision, "GMRES","LU")
234 if(not LS.getStatus()):
235 print("Linear system did not converge ", LS.getNumberOfIter(), " GMRES iterations")
236 raise ValueError("Pas de convergence du système linéaire");
240 for k in range(nbCells):
241 rho_field[k] = Un[k*(dim+1)+0]
242 q_field[k] = Un[k*(dim+1)+1]
243 v_field = [ q_field[i]/rho_field[i] for i in range(nx)]
244 p_field = [ rho_field[i]*(c0*c0) for i in range(nx)]
246 lineDensity.set_ydata(rho_field)
247 lineMomentum.set_ydata(q_field)
248 lineVelocity.set_ydata(v_field)
249 linePressure.set_ydata(p_field)
255 if(it==1 or it%output_freq==0 or it>=ntmax or isStationary or time >=tmax):
256 print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
257 #print("Last linear system converged in ", LS.getNumberOfIter(), " GMRES iterations", ", residu final: ",residu)
259 plt.savefig("EulerSystem"+str(dim)+"D_ConservativeStaggered"+meshName+"_"+str(it)+".png")
261 print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
263 print("Nombre de pas de temps maximum ntmax= ", ntmax, " atteint")
266 print("Régime stationnaire atteint au pas de temps ", it, ", t= ", time)
267 print("------------------------------------------------------------------------------------")
268 plt.savefig("EulerSystem"+str(dim)+"Staggered"+meshName+"_Stat.png")
271 print("Temps maximum Tmax= ", tmax, " atteint")
274 def solve( a,b,nx, meshName, meshType, cfl):
275 print("Resolution of the Euler system in dimension 1 on "+str(nx)+ " cells")
276 print("Initial data : ", "Riemann problem")
277 print("Boundary conditions : ", "Neumann")
278 print("Mesh name : ",meshName , ", ", nx, " cells")
283 EulerSystemStaggered(ntmax, tmax, cfl, a,b,nx, output_freq, meshName)
286 if __name__ == """__main__""":
291 solve( a,b,nx,"SquareRegularSquares","RegularSquares",cfl)