4 #===============================================================================================================================
5 # Name : Résolution VF implicite de l'équation de la chaleur 1D \partial_t u = d \partial_xx u avec conditions aux limites périodiques
6 # Author : Michaël Ndjinga
7 # Copyright : CEA Saclay 2019
8 # Description : Maillage 1D régulier
9 # Création et sauvegarde du champ résultant et des figures
10 # Génération d'une video sauvegardée dans un fichier .mp4
11 #================================================================================================================================
14 from math import sin, pi, ceil
18 import matplotlib.pyplot as plt
19 import matplotlib.animation as manimation
23 def implicitSchemeMatrix(nx,cfl):
24 implMat=cdmath.SparseMatrixPetsc(nx,nx,3)
26 implMat.setValue(i,(i+1)%nx,-cfl)
27 implMat.setValue(i,i,1.+2*cfl)
28 implMat.setValue(i,(i-1)%nx,-cfl)
32 def HeatEquation1DImplicit(nx,cfl):
33 print( "Simulation of 1D heat equation with an implicit scheme")
35 ##################### Simulation parameters
36 a = 0.0 # space domain : a <= x <= b
38 dx = (b - a) / nx #space step
40 d = 1. # thermal diffusivity
41 tmax = (b-a)/d # runs the simulation for 0 <= t <= tMax
42 dt = cfl * dx *dx/ (2*d)
45 x=[a+0.5*dx + i*dx for i in range(nx)] # array of cell center (1D mesh)
47 ########################## Initial data
49 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
50 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
52 max_initial=max(u_initial)
53 min_initial=min(u_initial)
54 total_var_initial = np.sum([abs(u_initial[i] - u_initial[(i-1)%nx]) for i in range(nx)])
60 #Initialisation of the linear system
61 systemMat=implicitSchemeMatrix(nx,cfl)
67 LS=cdmath.LinearSolver(systemMat,Un,iterGMRESMax, precision, "GMRES","ILU")
68 LS.setComputeConditionNumber()
71 FFMpegWriter = manimation.writers['ffmpeg']
72 metadata = dict(title="Implicit scheme for heat equation, "+"CFL="+str(cfl), artist = "CEA Saclay", comment="Stable for any CFL number")
73 writer=FFMpegWriter(fps=output_freq, metadata=metadata, codec='h264')
74 with writer.saving(plt.figure(), "HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+".mp4", ntmax):
75 ########################### Postprocessing initialisation
81 plt.ylim( min_initial - 0.1*(max_initial-min_initial), max_initial + 0.1*(max_initial-min_initial) )
82 plt.title("Implicit scheme for heat equation, "+"CFL="+str(cfl))
83 line1, = plt.plot(x, u, label='u') #new picture for video # Returns a tuple of line objects, thus the comma
85 print("Starting time loop")
86 print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
87 np.savetxt( "HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.txt", u, delimiter="\n")
89 plt.savefig("HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_0.png")
91 ############################# Time loop
92 while (it < ntmax and time <= tmax):
98 if(not LS.getStatus()):
99 print( "Linear system did not converge ", iterGMRES, " GMRES iterations" )
100 raise ValueError("Pas de convergence du système linéaire");
104 assert max(u) <= max_initial
105 assert min(u) >= min_initial
106 assert np.sum([abs(u[i] - u[(i-1)%nx]) for i in range(nx)]) <= total_var_initial
114 if (it % output_freq == 0):
115 print("-- Iter: " + str(it) + ", Time: " + str(time) + ", dt: " + str(dt))
116 np.savetxt( "HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".txt", u, delimiter="\n")
117 plt.savefig("HeatEquation1D_Implicit_"+str(nx)+"Cells_CFL"+str(cfl)+"_ResultField_"+str(it)+".png")
120 print( "Exact solution minimum : ", min(u_initial), "Numerical solution minimum : ", min(u) )
121 print( "Exact solution maximum : ", max(u_initial), "Numerical solution maximum : ", max(u) )
122 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)]) )
123 print( "l1 numerical error : ", dx*np.sum([abs(u[i] - u_initial[i]) for i in range(nx)]) )
125 print("Simulation of heat equation with implicit scheme done.")
127 #return min, max, total variation and l1 error
128 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)])
131 if __name__ == """__main__""":
132 if len(sys.argv) >2 :
133 nx = int(sys.argv[1])
134 cfl = float(sys.argv[2])
135 HeatEquation1DImplicit(nx,cfl)
137 nx = 50 # number of cells
138 cfl = 1 # c*dt/(2*dx) <= CFL
139 HeatEquation1DImplicit(nx,cfl)