PFASST++
boris_analyse.py
Go to the documentation of this file.
1 import math
2 import csv
3 import numpy as np
4 import matplotlib.pyplot as plt
5 from mpl_toolkits.mplot3d import Axes3D
6 
7 
8 colors = ['b', 'r', 'y', 'c', 'm']
9 
10 
11 def distance(a, b):
12  d = a - b
13  return math.sqrt(np.power(d, 2).sum())
14 
15 
16 class BorisData(object):
17  def __init__(self, build_dir, nsteps, niter, nparticles):
18  self._build_dir = build_dir
19  self._nsteps = nsteps
20  self._niter = niter
21  self._nparticles = nparticles
22 
23  self._x = np.ndarray((self._nparticles, self._nsteps + 1), dtype=np.double)
24  self._y = np.ndarray((self._nparticles, self._nsteps + 1), dtype=np.double)
25  self._z = np.ndarray((self._nparticles, self._nsteps + 1), dtype=np.double)
26  self._x_c = np.ndarray(self._nsteps + 1, dtype=np.double)
27  self._y_c = np.ndarray(self._nsteps + 1, dtype=np.double)
28  self._z_c = np.ndarray(self._nsteps + 1, dtype=np.double)
29  self._x_ref = np.ndarray(self._nsteps + 1, dtype=np.double)
30  self._y_ref = np.ndarray(self._nsteps + 1, dtype=np.double)
31  self._z_ref = np.ndarray(self._nsteps + 1, dtype=np.double)
32  self._residual = np.ndarray(self._nsteps + 1, dtype=np.double)
33  self._energy = np.ndarray(self._nsteps + 1, dtype=np.double)
34  self._drift = np.ndarray(self._nsteps + 1, dtype=np.double)
35  self._distances = np.ndarray((self._nparticles, self._nsteps + 1), dtype=np.double)
36  self._dist_min = np.ndarray(self._nsteps + 1, dtype=np.double)
37  self._dist_max = np.ndarray(self._nsteps + 1, dtype=np.double)
38  self._dist_mean = np.ndarray(self._nsteps + 1, dtype=np.double)
39 
40  self._read_data()
41 
42  @property
43  def nsteps(self):
44  return self._nsteps
45 
46  @property
47  def niter(self):
48  return self._niter
49 
50  @property
51  def nparticles(self):
52  return self._nparticles
53 
54  @property
55  def x(self):
56  return self._x
57 
58  @property
59  def y(self):
60  return self._y
61 
62  @property
63  def z(self):
64  return self._z
65 
66  @property
67  def x_c(self):
68  return self._x_c
69 
70  @property
71  def y_c(self):
72  return self._y_c
73 
74  @property
75  def z_c(self):
76  return self._z_c
77 
78  @property
79  def x_ref(self):
80  return self._x_ref
81 
82  @property
83  def y_ref(self):
84  return self._y_ref
85 
86  @property
87  def z_ref(self):
88  return self._z_ref
89 
90  @property
91  def residual(self):
92  return self._residual
93 
94  @property
95  def energy(self):
96  return self._energy
97 
98  @property
99  def drift(self):
100  return self._drift
101 
102  @property
103  def distances(self):
104  return self._distances
105 
106  @property
107  def dist_min(self):
108  return self._dist_min
109 
110  @property
111  def dist_max(self):
112  return self._dist_max
113 
114  @property
115  def dist_mean(self):
116  return self._dist_mean
117 
118  def _get_coords(self, step, p):
119  return np.asarray([self.x[p][step], self.y[p][step], self.z[p][step]])
120 
121  def _read_data(self):
122  data_file = self._build_dir + "/s%d_i%d_dt0.015625_m5_p%d.csv" % (self.nsteps, self.niter, self.nparticles)
123  ref_file = self._build_dir + "/s%d_i%d_dt0.015625_m5_p1.csv" % (self.nsteps, self.niter)
124 
125  with open(data_file) as csvfile:
126  csv_file = csv.reader(csvfile, delimiter=',')
127  for row in csv_file:
128  step = int(row[0])
129  iter = int(row[1])
130  part = int(row[2])
131  if iter == 0 and step == 1:
132  self._x[part][0] = row[3]
133  self._y[part][0] = row[4]
134  self._z[part][0] = row[5]
135  self._energy[0] = row[9]
136  self._drift[0] = row[10]
137  self._residual[0] = row[11]
138  if part == -1:
139  self._x_c[0] = row[3]
140  self._y_c[0] = row[4]
141  self._z_c[0] = row[5]
142  if iter == self.niter - 1:
143  self._energy[step] = row[9]
144  self._drift[step] = row[10]
145  self._residual[step] = row[11]
146  if part == -1:
147  self._x_c[step] = row[3]
148  self._y_c[step] = row[4]
149  self._z_c[step] = row[5]
150  else:
151  self._x[part][step] = row[3]
152  self._y[part][step] = row[4]
153  self._z[part][step] = row[5]
154 
155  with open(ref_file) as csvfile:
156  csv_file = csv.reader(csvfile, delimiter=',')
157  for row in csv_file:
158  step = int(row[0])
159  iter = int(row[1])
160  if iter == self.niter - 1:
161  self._x_ref[step] = row[3]
162  self._y_ref[step] = row[4]
163  self._z_ref[step] = row[5]
164  if iter == 0 and step == 1:
165  self._x_ref[0] = row[3]
166  self._y_ref[0] = row[4]
167  self._z_ref[0] = row[5]
168 
169  for step in range(self._nsteps + 1):
170  center = np.asarray([self.x_c[step], self.y_c[step], self.z_c[step]])
171  for p in range(self._nparticles):
172  self._distances[p][step] = distance(self._get_coords(step, p), center)
173  self._dist_min = self._distances.min(axis=0)
174  self._dist_max = self._distances.max(axis=0)
175  self._dist_mean = self._distances.mean(axis=0)
176 
177 
178 def get_meetup_after(data, after=0):
179  _dist = data.dist_max - data.dist_min
180  return np.where(_dist[after:] == _dist[after:].min())[0][0] + after
181 
182 
183 def plot_trajectories(data, until=None):
184  if until is None:
185  until = data.nsteps
186  ndisplay = until + 1
187 
188  print("Initial Center of Mass: % 10.4f\t% 10.4f\t% 10.4f" % (data.x_c[:1][0], data.y_c[:1][0], data.z_c[:1][0]))
189  print("Last Center of Mass: % 10.4f\t% 10.4f\t% 10.4f" % (data.x_c[until:ndisplay][0], data.y_c[until:ndisplay][0], data.z_c[until:ndisplay][0]))
190  print("Initial Energy: %16.4f" % data.energy[0])
191  print("Final Energy: %16.4f" % data.energy[-1])
192  print("Final Drift: %16.4f" % data.drift[-1])
193  print("Final Residual: %16.4e (max: %.4e)" % (data.residual[-1], data.residual.max()))
194 
195  plt.figure(figsize=(15, 15), dpi=1200)
196  ax = plt.axes(projection='3d')
197  plt.title("Trajectory of Particles\ndashed: single; black solid: reference; green solid: center of mass; dot: initial point; cross: end point")
198  ax.plot(data.x_ref[:ndisplay], data.y_ref[:ndisplay], data.z_ref[:ndisplay], '--k')
199  if data.nparticles <= 5:
200  for p in range(data.nparticles):
201  ax.plot(data.x[p][:ndisplay], data.y[p][:ndisplay], data.z[p][:ndisplay], '--%s' % colors[p])
202  ax.plot(data.x_c[:ndisplay], data.y_c[:ndisplay], data.z_c[:ndisplay], '-g')
203  ax.plot(data.x_c[:1], data.y_c[:1], data.z_c[:1], 'ok')
204  ax.plot(data.x_c[until:ndisplay], data.y_c[until:ndisplay], data.z_c[until:ndisplay], 'xk', markeredgewidth=2, markersize=5)
205 
206 
207 def plot_analytics(data, start=0, until=None, wo_drift=False):
208  if until is None:
209  until = data.nsteps
210  ndisplay = until + 1
211  figid = 1
212  maxfig = 4 if wo_drift else 5
213  figheight = 10 if wo_drift else 15
214  steprange = range(start, ndisplay)
215 
216  plt.figure(figsize=(15, figheight), dpi=1200)
217  plt.subplots_adjust(wspace=0.1)
218 
219  plt.subplot(maxfig, 1, figid)
220  plt.plot(steprange, data.energy[start:ndisplay])
221  plt.grid()
222  plt.xlim(start, until)
223  plt.ylabel("Energy")
224  figid += 1
225 
226  if wo_drift == False:
227  plt.subplot(maxfig, 1, figid)
228  plt.plot(steprange, data.drift[start:ndisplay] / data.energy[start:ndisplay])
229  plt.grid()
230  plt.xlim(start, until)
231  plt.ylabel("Relative Drift\n(regarding total energy)")
232  figid += 1
233 
234  plt.subplot(maxfig, 1, figid)
235  plt.plot(steprange, data.residual[start:ndisplay])
236  plt.grid()
237  plt.xlim(start, until)
238  plt.yscale("log")
239  plt.ylabel("Residual")
240  plt.xlabel("Step")
241  figid += 1
242 
243  plt.subplot(maxfig, 1, figid)
244  plt.plot(steprange, data.distances.transpose()[start:ndisplay])
245  plt.grid()
246  plt.xlim(start, until)
247  plt.ylabel("Distance of Particles\nfrom Center of Mass")
248  figid += 1
249 
250  plt.subplot(maxfig, 1, figid)
251  plt.plot(steprange, data.dist_min.transpose()[start:ndisplay], '-r')
252  plt.plot(steprange, data.dist_max.transpose()[start:ndisplay], '-b')
253  plt.plot(steprange, data.dist_mean.transpose()[start:ndisplay], '-g')
254  plt.grid()
255  plt.xlim(start, until)
256  plt.ylabel("Stats of Distance of Particles\nfrom Center of Mass")
257  figid += 1
258 
259 
260 def plot_particle_meetup(data, step, width=10):
261  start = step - width
262  stop = step + width + 1
263 
264  plt.figure(figsize=(15, 15), dpi=1200)
265  ax = plt.axes(projection='3d')
266  plt.title("Particle Meetup at step %d\ndot: start; square: end" % step)
267  if data.nparticles <= 5:
268  for p in range(data.nparticles):
269  ax.plot(data.x[p][start:stop], data.y[p][start:stop], data.z[p][start:stop], '--%s' % colors[p])
270  ax.plot(data.x_c[start:stop], data.y_c[start:stop], data.z_c[start:stop], '-g')
271  ax.plot(data.x_c[step:step+1], data.y_c[step:step+1], data.z_c[step:step+1], 'xk', markeredgewidth=3, markersize=10)
272  ax.plot(data.x_c[start:start+1], data.y_c[start:start+1], data.z_c[start:start+1], 'ok')
273  ax.plot(data.x_c[stop-1:stop], data.y_c[stop-1:stop], data.z_c[stop-1:stop], 'sk')
274 
275  plot_analytics(data, start, stop-1, True)
def distance(a, b)
def _get_coords(self, step, p)
def __init__(self, build_dir, nsteps, niter, nparticles)
def plot_particle_meetup