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
67y = partData.x[:, 1] - 0.5 * boxsize
68vel_x = partData.v[:, 0]
69vel_y = partData.v[:, 1]
70pressure = partData.pressure
71density = partData.density
72mass = partData.mass
73energy = partData.u
74
75r = np.sqrt(x**2 + y**2)
76v_r = (x * vel_x + y * vel_y) / r
77
78
79# -------------------------
80# Get analytical solution
81# -------------------------
82
83
84def calc_a(g, nu=3):
85 """
86 exponents of the polynomials of the sedov solution
87 g - the polytropic gamma
88 nu - the dimension
89 """
90 a = [0] * 8
91
92 a[0] = 2.0 / (nu + 2)
93 a[2] = (1 - g) / (2 * (g - 1) + nu)
94 a[3] = nu / (2 * (g - 1) + nu)
95 a[5] = 2 / (g - 2)
96 a[6] = g / (2 * (g - 1) + nu)
97
98 a[1] = (((nu + 2) * g) / (2.0 + nu * (g - 1.0))) * (
99 (2.0 * nu * (2.0 - g)) / (g * (nu + 2.0) ** 2) - a[2]
100 )
101 a[4] = a[1] * (nu + 2) / (2 - g)
102 a[7] = (2 + nu * (g - 1)) * a[1] / (nu * (2 - g))
103 return a
104
105
106def calc_beta(v, g, nu=3):
107 """
108 beta values for the sedov solution (coefficients of the polynomials of the similarity variables)
109 v - the similarity variable
110 g - the polytropic gamma
111 nu- the dimension
112 """
113
114 beta = (
115 (nu + 2)
116 * (g + 1)
117 * np.array(
118 (
119 0.25,
120 (g / (g - 1)) * 0.5,
121 -(2 + nu * (g - 1))
122 / 2.0
123 / ((nu + 2) * (g + 1) - 2 * (2 + nu * (g - 1))),
124 -0.5 / (g - 1),
125 ),
126 )
127 )
128
129 beta = np.outer(beta, v)
130
131 beta += (g + 1) * np.array(
132 (
133 0.0,
134 -1.0 / (g - 1),
135 (nu + 2) / ((nu + 2) * (g + 1) - 2.0 * (2 + nu * (g - 1))),
136 1.0 / (g - 1),
137 ),
138 ).reshape((4, 1))
139
140 return beta
141
142
143def sedov(t, E0, rho0, g, n=1000, nu=3):
144 """
145 solve the sedov problem
146 t - the time
147 E0 - the initial energy
148 rho0 - the initial density
149 n - number of points (10000)
150 nu - the dimension
151 g - the polytropic gas gamma
152 """
153 # the similarity variable
154 v_min = 2.0 / ((nu + 2) * g)
155 v_max = 4.0 / ((nu + 2) * (g + 1))
156
157 v = v_min + np.arange(n) * (v_max - v_min) / (n - 1.0)
158
159 a = calc_a(g, nu)
160 beta = calc_beta(v, g=g, nu=nu)
161 lbeta = np.log(beta)
162
163 r = np.exp(-a[0] * lbeta[0] - a[2] * lbeta[1] - a[1] * lbeta[2])
164 rho = ((g + 1.0) / (g - 1.0)) * np.exp(
165 a[3] * lbeta[1] + a[5] * lbeta[3] + a[4] * lbeta[2]
166 )
167 p = np.exp(
168 nu * a[0] * lbeta[0] + (a[5] + 1) * lbeta[3] + (a[4] - 2 * a[1]) * lbeta[2]
169 )
170 u = beta[0] * r * 4.0 / ((g + 1) * (nu + 2))
171 p *= 8.0 / ((g + 1) * (nu + 2) * (nu + 2))
172
173 # we have to take extra care at v=v_min, since this can be a special point.
174 # It is not a singularity, however, the gradients of our variables (wrt v) are.
175 # r -> 0, u -> 0, rho -> 0, p-> constant
176
177 u[0] = 0.0
178 rho[0] = 0.0
179 r[0] = 0.0
180 p[0] = p[1]
181
182 # volume of an n-sphere
183 vol = (np.pi ** (nu / 2.0) / Gamma(nu / 2.0 + 1)) * np.power(r, nu)
184
185 # note we choose to evaluate the integral in this way because the
186 # volumes of the first few elements (i.e near v=vmin) are shrinking
187 # very slowly, so we dramatically improve the error convergence by
188 # finding the volumes exactly. This is most important for the
189 # pressure integral, as this is on the order of the volume.
190
191 # (dimensionless) energy of the model solution
192 de = rho * u * u * 0.5 + p / (g - 1)
193 # integrate (trapezium rule)
194 q = np.inner(de[1:] + de[:-1], np.diff(vol)) * 0.5
195
196 # the factor to convert to this particular problem
197 fac = (q * (t**nu) * rho0 / E0) ** (-1.0 / (nu + 2))
198
199 # shock speed
200 shock_speed = fac * (2.0 / (nu + 2))
201 rho_s = ((g + 1) / (g - 1)) * rho0
202 r_s = shock_speed * t * (nu + 2) / 2.0
203 p_s = (2.0 * rho0 * shock_speed * shock_speed) / (g + 1)
204 u_s = (2.0 * shock_speed) / (g + 1)
205
206 r *= fac * t
207 u *= fac
208 p *= fac * fac * rho0
209 rho *= rho0
210 return r, p, rho, u, r_s, p_s, rho_s, u_s, shock_speed
211
212
213# Parameters
214rho_0 = 1.0 # Background Density
215P_0 = 1.0e-6 # Background Pressure
216E_0 = 1.0 # Energy of the explosion
217gas_gamma = 5.0 / 3.0 # Gas polytropic index
218
219# The main properties of the solution
220r_s, P_s, rho_s, v_s, r_shock, _, _, _, _ = sedov(time, E_0, rho_0, gas_gamma, 1000, 2)
221
222# Append points for after the shock
223r_s = np.insert(r_s, np.size(r_s), [r_shock, r_shock * 3])
224rho_s = np.insert(rho_s, np.size(rho_s), [rho_0, rho_0])
225P_s = np.insert(P_s, np.size(P_s), [P_0, P_0])
226v_s = np.insert(v_s, np.size(v_s), [0, 0])
227
228# Additional arrays
229u_s = P_s / (rho_s * (gas_gamma - 1.0)) # internal energy
230# s_s = P_s / rho_s**gas_gamma # entropic function
231
232
233# -------------------------
234# Plot, plot, plot!
235# -------------------------
236
237sim_props = {
238 "marker": ".",
239 "ms": 4,
240 "markeredgecolor": "none",
241 "alpha": 0.4,
242 "zorder": -1,
243 "rasterized": True,
244 "linestyle": "none",
245}
246solution_props = {
247 "linestyle": "--",
248 "color": "C1",
249 "alpha": 0.8,
250 "linewidth": 2.0,
251}
252
253
254fig = plt.figure(figsize=(7.0, 7.0))
255fig.suptitle(f"t={time}")
256
257ax1 = fig.add_subplot(2, 2, 1)
258ax2 = fig.add_subplot(2, 2, 2)
259ax3 = fig.add_subplot(2, 2, 3)
260ax4 = fig.add_subplot(2, 2, 4)
261
262ax1.plot(r, v_r, **sim_props)
263ax1.plot(r_s, v_s, **solution_props)
264ax1.set_ylabel(r"Radial velocity $v_r$")
265ax1.set_ylim(-0.2, 3.8)
266
267ax2.plot(r, density, **sim_props)
268ax2.plot(r_s, rho_s, **solution_props)
269ax2.set_ylabel(r"Density $\rho$")
270ax2.set_ylim(-0.2, 5.2)
271
272ax3.plot(r, pressure, **sim_props)
273ax3.plot(r_s, P_s, **solution_props)
274ax3.set_ylabel(r"Pressure $p$")
275ax3.set_ylim(-1.0, 12.5)
276
277ax4.plot(r, energy, **sim_props)
278ax4.plot(r_s, u_s, **solution_props)
279ax4.set_ylabel(r"Internal Energy $u$")
280ax4.set_ylim(-2.0, 22)
281
282for ax in fig.axes:
283 ax.tick_params(direction="in", top=True, right=True)
284 ax.set_xlim(0, 1.3 * r_shock)
285 ax.set_xlabel(r"Radius $r$")
286
287plt.tight_layout()
288fname = f"sedov_profile-{time:.4f}.png"
289fig.savefig(fname)
290print("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