Peano
Loading...
Searching...
No Matches
plotSolution.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2
3
22
23
24import matplotlib
25
26matplotlib.use("Agg")
27
28import matplotlib.pyplot as plt
29from scipy import stats
30from scipy.special import gamma as Gamma
31import numpy as np
32import sys
33
35
36
37"""
38!
39Computes the analytical solution of the 3D Sedov blast wave.
40The script works for a given initial box and dumped energy and computes the
41solution at a later time t.
42
43
44python3 plotSolution.py time
45
46where:
47@param time_step_sim : time to plot solution of
48"""
49
50
51if len(sys.argv) < 2:
52 time = 0.05
53else:
54 time = float(sys.argv[1])
55
56# -------------------------
57# Extract data
58# -------------------------
59
60pvdfile = "particles.pvd"
61reader = ParticleVTUReader(pvdfile=pvdfile, snapshot_time=time)
62partData = reader.load()
63time = reader.get_snapshot_time()
64boxsize = 1.0
65
66x = partData.x[:, 0] - 0.5 * boxsize
67vel_x = partData.v[:, 0]
68pressure = partData.pressure
69density = partData.density
70mass = partData.mass
71energy = partData.u
72
73r = np.abs(x)
74v_r = x * vel_x / r
75
76
77# -------------------------
78# Get analytical solution
79# -------------------------
80
81
82def calc_a(g, nu=3):
83 """
84 exponents of the polynomials of the sedov solution
85 g - the polytropic gamma
86 nu - the dimension
87 """
88 a = [0] * 8
89
90 a[0] = 2.0 / (nu + 2)
91 a[2] = (1 - g) / (2 * (g - 1) + nu)
92 a[3] = nu / (2 * (g - 1) + nu)
93 a[5] = 2 / (g - 2)
94 a[6] = g / (2 * (g - 1) + nu)
95
96 a[1] = (((nu + 2) * g) / (2.0 + nu * (g - 1.0))) * (
97 (2.0 * nu * (2.0 - g)) / (g * (nu + 2.0) ** 2) - a[2]
98 )
99 a[4] = a[1] * (nu + 2) / (2 - g)
100 a[7] = (2 + nu * (g - 1)) * a[1] / (nu * (2 - g))
101 return a
102
103
104def calc_beta(v, g, nu=3):
105 """
106 beta values for the sedov solution (coefficients of the polynomials of the similarity variables)
107 v - the similarity variable
108 g - the polytropic gamma
109 nu- the dimension
110 """
111
112 beta = (
113 (nu + 2)
114 * (g + 1)
115 * np.array(
116 (
117 0.25,
118 (g / (g - 1)) * 0.5,
119 -(2 + nu * (g - 1))
120 / 2.0
121 / ((nu + 2) * (g + 1) - 2 * (2 + nu * (g - 1))),
122 -0.5 / (g - 1),
123 ),
124 )
125 )
126
127 beta = np.outer(beta, v)
128
129 beta += (g + 1) * np.array(
130 (
131 0.0,
132 -1.0 / (g - 1),
133 (nu + 2) / ((nu + 2) * (g + 1) - 2.0 * (2 + nu * (g - 1))),
134 1.0 / (g - 1),
135 ),
136 ).reshape((4, 1))
137
138 return beta
139
140
141def sedov(t, E0, rho0, g, n=1000, nu=3):
142 """
143 solve the sedov problem
144 t - the time
145 E0 - the initial energy
146 rho0 - the initial density
147 n - number of points (10000)
148 nu - the dimension
149 g - the polytropic gas gamma
150 """
151 # the similarity variable
152 v_min = 2.0 / ((nu + 2) * g)
153 v_max = 4.0 / ((nu + 2) * (g + 1))
154
155 v = v_min + np.arange(n) * (v_max - v_min) / (n - 1.0)
156
157 a = calc_a(g, nu)
158 beta = calc_beta(v, g=g, nu=nu)
159 lbeta = np.log(beta)
160
161 r = np.exp(-a[0] * lbeta[0] - a[2] * lbeta[1] - a[1] * lbeta[2])
162 rho = ((g + 1.0) / (g - 1.0)) * np.exp(
163 a[3] * lbeta[1] + a[5] * lbeta[3] + a[4] * lbeta[2]
164 )
165 p = np.exp(
166 nu * a[0] * lbeta[0] + (a[5] + 1) * lbeta[3] + (a[4] - 2 * a[1]) * lbeta[2]
167 )
168 u = beta[0] * r * 4.0 / ((g + 1) * (nu + 2))
169 p *= 8.0 / ((g + 1) * (nu + 2) * (nu + 2))
170
171 # we have to take extra care at v=v_min, since this can be a special point.
172 # It is not a singularity, however, the gradients of our variables (wrt v) are.
173 # r -> 0, u -> 0, rho -> 0, p-> constant
174
175 u[0] = 0.0
176 rho[0] = 0.0
177 r[0] = 0.0
178 p[0] = p[1]
179
180 # volume of an n-sphere
181 vol = (np.pi ** (nu / 2.0) / Gamma(nu / 2.0 + 1)) * np.power(r, nu)
182
183 # note we choose to evaluate the integral in this way because the
184 # volumes of the first few elements (i.e near v=vmin) are shrinking
185 # very slowly, so we dramatically improve the error convergence by
186 # finding the volumes exactly. This is most important for the
187 # pressure integral, as this is on the order of the volume.
188
189 # (dimensionless) energy of the model solution
190 de = rho * u * u * 0.5 + p / (g - 1)
191 # integrate (trapezium rule)
192 q = np.inner(de[1:] + de[:-1], np.diff(vol)) * 0.5
193
194 # the factor to convert to this particular problem
195 fac = (q * (t**nu) * rho0 / E0) ** (-1.0 / (nu + 2))
196
197 # shock speed
198 shock_speed = fac * (2.0 / (nu + 2))
199 rho_s = ((g + 1) / (g - 1)) * rho0
200 r_s = shock_speed * t * (nu + 2) / 2.0
201 p_s = (2.0 * rho0 * shock_speed * shock_speed) / (g + 1)
202 u_s = (2.0 * shock_speed) / (g + 1)
203
204 r *= fac * t
205 u *= fac
206 p *= fac * fac * rho0
207 rho *= rho0
208 return r, p, rho, u, r_s, p_s, rho_s, u_s, shock_speed
209
210
211# Parameters
212rho_0 = 1.0 # Background Density
213P_0 = 1.0e-6 # Background Pressure
214E_0 = 1.0 # Energy of the explosion
215gas_gamma = 5.0 / 3.0 # Gas polytropic index
216
217# The main properties of the solution
218r_s, P_s, rho_s, v_s, r_shock, _, _, _, _ = sedov(time, E_0, rho_0, gas_gamma, 1000, 1)
219
220# Append points for after the shock
221r_s = np.insert(r_s, np.size(r_s), [r_shock, r_shock * 3])
222rho_s = np.insert(rho_s, np.size(rho_s), [rho_0, rho_0])
223P_s = np.insert(P_s, np.size(P_s), [P_0, P_0])
224v_s = np.insert(v_s, np.size(v_s), [0, 0])
225
226# Additional arrays
227u_s = P_s / (rho_s * (gas_gamma - 1.0)) # internal energy
228# s_s = P_s / rho_s**gas_gamma # entropic function
229
230
231# -------------------------
232# Plot, plot, plot!
233# -------------------------
234
235sim_props = {
236 "marker": ".",
237 "ms": 4,
238 "markeredgecolor": "none",
239 "alpha": 1.0,
240 "zorder": -1,
241 "rasterized": True,
242 "linestyle": "none",
243}
244solution_props = {
245 "linestyle": "--",
246 "color": "C1",
247 "alpha": 0.6,
248 "linewidth": 2.0,
249}
250
251
252fig = plt.figure(figsize=(7.0, 7.0))
253fig.suptitle(f"t={time}")
254
255ax1 = fig.add_subplot(2, 2, 1)
256ax2 = fig.add_subplot(2, 2, 2)
257ax3 = fig.add_subplot(2, 2, 3)
258ax4 = fig.add_subplot(2, 2, 4)
259
260ax1.plot(r, v_r, **sim_props)
261ax1.plot(r_s, v_s, **solution_props)
262ax1.set_ylabel(r"Radial velocity $v_r$")
263ax1.set_ylim(-0.2, 3.8)
264
265ax2.plot(r, density, **sim_props)
266ax2.plot(r_s, rho_s, **solution_props)
267ax2.set_ylabel(r"Density $\rho$")
268ax2.set_ylim(-0.2, 5.2)
269
270ax3.plot(r, pressure, **sim_props)
271ax3.plot(r_s, P_s, **solution_props)
272ax3.set_ylabel(r"Pressure $p$")
273ax3.set_ylim(-1.0, 12.5)
274
275ax4.plot(r, energy, **sim_props)
276ax4.plot(r_s, u_s, **solution_props)
277ax4.set_ylabel(r"Internal Energy $u$")
278ax4.set_ylim(-2.0, 22)
279
280for ax in fig.axes:
281 ax.tick_params(direction="in", top=True, right=True)
282 ax.set_xlim(0, 1.3 * r_shock)
283 ax.set_xlabel(r"Radius $r$")
284
285plt.tight_layout()
286fname = f"sedov_profile-{time:.4f}.png"
287fig.savefig(fname)
288print("Saved", fname)
Reads in particle fields from a single .vtu file, or all .vtu at a given snapshot time specified in t...
calc_beta(v, g, nu=3)
beta values for the sedov solution (coefficients of the polynomials of the similarity variables) v - ...
calc_a(g, nu=3)
exponents of the polynomials of the sedov solution g - the polytropic gamma nu - the dimension
Definition sedov.py:1