.Simulation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
Statistics.h
1 #ifndef __SIMULATION_STATISTICS_H__
2 #define __SIMULATION_STATISTICS_H__
3 
4 #include <algorithm>
5 #include <boost/array.hpp>
6 #include <boost/circular_buffer.hpp>
7 #include <boost/multi_array.hpp>
8 
9 #include "./CollisionRecord.h"
10 #include "../Constants/AtomicProperties.h"
11 #include "../InfoStruct/InfoStruct.h"
12 #include "../Math/Functions.h"
13 #include "../Units/Units.h"
14 #include "../Vector/Vector.hpp"
15 
16 namespace MDSimulation
17 {
18  class Statistics
19  {
20  public:
21 
22  typedef boost::multi_array<double, 2> Real2d;
23  typedef boost::multi_array<double, 1> Real1d;
24  typedef boost::multi_array<int, 2> Int2d;
25  typedef boost::multi_array<int, 1> Int1d;
26 
27  typedef boost::multi_array<DoubleVector, 2> Vector2d;
28 
29  const InfoStruct& Info;
30  const int Bins;
31  const int CollisionNum;
32 
33  unsigned long long TotalCollisions;
34  unsigned long long TotalCellCrossings;
35  unsigned long long TotalWallCollisions;
36  unsigned long long TotalConeBoundaryCollisions;
38  double FusionRate;
39  double MaxCollisionEnergy;
40 
42  std::map<std::pair<int, int>, double> MaxCollisionEnergySpecies;
43 
44  // SNAPSHOT STATISTICS
45  double KineticEnergyPerAtom;
46  double CurrentRadius;
47 
48  boost::circular_buffer<CollisionRecord> Collisions;
50  // Total atoms per binCurrentParticle = -1;
51  Int1d TotalAtomsPerBin;
52 
53  // Atomic count per species per bin
54  Int2d AtomsPerBin;
55  // Atomic charge per species per bin
56  Int2d ChargePerBin;
57  // Velocity-squared per species per bin
58  Real2d VelocitySquaredPerBin;
59  // Radial velocity per species per bin
60  Real2d RadialVelocityPerBin;
61  // Largest temperature in each bin
62  Real2d MaxTemperature;
63  // The square of each particle's velocity corrected for the aggregate
64  // motion of each bin.
65  Real2d ThermalVelocitySquared;
66 
67  // Velocity of the bin's center of mass
68  Vector2d VelocityCoM;
69 
70  Statistics(const InfoStruct& info, const int bins, const int collisions);
71 
81  double CollisionDistanceQuantile(const double p);
82 
83  void RegisterCollision(CollisionRecord& rec);
84 
85  template <typename Iter>
86  void ComputeStatistics(Iter begin, const Iter end, const double radius);
87 
88  template <typename Stream>
89  void WriteCollisions(Stream& stream) const;
90 
91  template <typename Writer>
92  void WriteStatistics(Writer& writer) const;
93 
94  private:
95 
96  void Zero();
97 
98  template <typename Writer>
99  void WriteTemperature(Writer& writer, const int bin) const;
100 
101  template <typename Writer>
102  void WriteVelocity(Writer& writer, const int bin) const;
103 
104  template <typename Writer>
105  void WriteIonization(Writer& writer, const int bin) const;
106 
107  template <typename Writer>
108  void WritePercentage(Writer& writer, const int bin) const;
109 
110  template <typename Writer>
111  void WriteMaxTemperature(Writer& writer, const int bin) const;
112 
113  template <typename Writer>
114  void WriteKineticEnergy(Writer& writer, const int bin) const;
115 
116  template <typename Writer>
117  void WriteEnergyCoM(Writer& writer, const int bin) const;
118  };
119 
120  template <typename Iter>
121  void Statistics::ComputeStatistics(
122  Iter begin,
123  const Iter end,
124  const double radius)
125  {
126  this->Zero();
127 
128  CurrentRadius = radius;
129 
130  for (Iter particle = begin; particle != end; ++particle)
131  {
132  // Atom Type
133  const int type = particle->Type;
134  const double v2 = dot(particle->Velocity, particle->Velocity);
135 
136  // Total kinetic energy: 0.5*m*v*v
137  KineticEnergyPerAtom += 0.5 * Info.AtomicMass[type] * v2;
138 
139  // Distance from bubble center
140  const double r = norm2(particle->Position);
141 
142  // Determine bin # to which this atom belongs
143  int bin = int(r * (double) Bins / radius);
144  bin = std::min(bin, Bins - 1);
145 
146  assert(type < Constants::ELEMENT_TYPES);
147  assert(type >= 0);
148 
149  // Increase atom count in the bin
150  AtomsPerBin[type][bin]++;
151 
152  // Increase total count of atoms
153  TotalAtomsPerBin[bin]++;
154 
155  // Increase charge per bin
156  ChargePerBin[type][bin] += particle->Charge;
157 
158  // Increase SUM(v*v) per bin
159  VelocitySquaredPerBin[type][bin] += v2;
160 
161  // Increase sum of radial velocities per bin
162  RadialVelocityPerBin[type][bin] +=
163  dot(particle->Position, particle->Velocity) / r;
164 
165  VelocityCoM[type][bin] += particle->Velocity;
166  }
167 
168  for (int bin = 0; bin < Bins; ++bin)
169  {
170  for (int type = 0; type < Constants::ELEMENT_TYPES; ++type)
171  {
172  VelocityCoM[type][bin] /= AtomsPerBin[type][bin];
173  }
174  }
175 
176  for (Iter particle = begin; particle != end; ++particle)
177  {
178  const int type = particle->Type;
179 
180  // Distance from bubble center
181  const double r = norm2(particle->Position);
182 
183  // Determine bin # to which this atom belongs
184  int bin = int(r * (double) Bins / radius);
185  bin = std::min(bin, Bins - 1);
186 
187  const DoubleVector vCoM(particle->Velocity - VelocityCoM[type][bin]);
188  ThermalVelocitySquared[type][bin] += dot(vCoM, vCoM);
189  }
190 
191  for (int bin = 0; bin < Bins; ++bin)
192  {
193  for (int type = 0; type < Constants::ELEMENT_TYPES; ++type)
194  {
195  if (AtomsPerBin[type][bin] > 0)
196  {
197  const double radial =
198  RadialVelocityPerBin[type][bin] / AtomsPerBin[type][bin];
199  const double squared =
200  VelocitySquaredPerBin[type][bin] / AtomsPerBin[type][bin];
201 
202  // Calculate species temperature
203  const double temperature =
204  Info.AtomicMass[type] / 3.0 * (squared - Sqr(radial));
205 
206  MaxTemperature[type][bin] =
207  std::max(MaxTemperature[type][bin], temperature);
208  }
209  }
210  }
211  }
212 
213  template <typename Stream>
214  void Statistics::WriteCollisions(Stream& stream) const
215  {
216  for (auto it = Collisions.begin(); it != Collisions.end(); ++it)
217  {
218  stream << it->Time * Units::T << ','
219  << it->Position[0] * Units::L << ','
220  << it->Position[1] * Units::L << ','
221  << it->Position[2] * Units::L << ','
222  << it->DeltaV * Units::L / Units::T << ','
223  << it->Energy * Units::Energy << ','
224  << it->Distance * Units::L << ','
225  << it->Type1 << ','
226  << it->Type2 << '\n';
227  }
228  }
229 
230  template <typename Writer>
231  void Statistics::WriteTemperature(Writer& writer, const int bin) const
232  {
233  writer.String("temperature");
234  writer.StartObject();
235  for (int type = 0; type < Constants::ELEMENT_TYPES; ++type)
236  {
237  const std::string& type_name = Constants::ELEMENT_NAMES[type];
238 
239  writer.String(type_name.c_str());
240  if (AtomsPerBin[type][bin] > 0)
241  {
242  // Calculate species temperature
243  const double temperature =
244  Units::Temperature * Info.AtomicMass[type] / 3.0
245  * (VelocitySquaredPerBin[type][bin] / AtomsPerBin[type][bin]
246  - Sqr(RadialVelocityPerBin[type][bin] / AtomsPerBin[type][bin]));
247 
248  writer.Double(temperature);
249  }
250  else
251  {
252  writer.Double(0.0);
253  }
254  }
255  writer.EndObject(); // End current temperature object
256  }
257 
258  template <typename Writer>
259  void Statistics::WriteVelocity(Writer& writer, const int bin) const
260  {
261  writer.String("velocity");
262  writer.StartObject();
263  for (int type = 0; type < Constants::ELEMENT_TYPES; ++type)
264  {
265  const std::string& type_name = Constants::ELEMENT_NAMES[type];
266 
267  writer.String(type_name.c_str());
268  if (AtomsPerBin[type][bin] > 0)
269  {
270  const double velocity =
271  RadialVelocityPerBin[type][bin] / AtomsPerBin[type][bin];
272  writer.Double(velocity * Units::L / Units::T);
273  }
274  else
275  {
276  writer.Double(0.0);
277  }
278  }
279  writer.EndObject(); // End current velocity object
280  }
281 
282  template <typename Writer>
283  void Statistics::WriteIonization(Writer& writer, const int bin) const
284  {
285  writer.String("ionization");
286  writer.StartObject();
287  for (int type = 0; type < Constants::ELEMENT_TYPES; ++type)
288  {
289  const std::string& type_name = Constants::ELEMENT_NAMES[type];
290 
291  writer.String(type_name.c_str());
292  if (AtomsPerBin[type][bin] > 0)
293  {
294  writer.Double(double(ChargePerBin[type][bin]) / AtomsPerBin[type][bin]);
295  }
296  else
297  {
298  writer.Double(0.0);
299  }
300  }
301  writer.EndObject(); // End current ionization object
302  }
303 
304  template <typename Writer>
305  void Statistics::WritePercentage(Writer& writer, const int bin) const
306  {
307  writer.String("percentage");
308  writer.StartObject();
309  for (int type = 0; type < Constants::ELEMENT_TYPES; ++type)
310  {
311  const std::string& type_name = Constants::ELEMENT_NAMES[type];
312 
313  writer.String(type_name.c_str());
314  if (AtomsPerBin[type][bin] > 0)
315  {
316  writer.Double((double) AtomsPerBin[type][bin] / (double) TotalAtomsPerBin[bin]);
317  }
318  else
319  {
320  writer.Double(0.0);
321  }
322  }
323  writer.EndObject(); // End current ionization object
324  }
325 
326  template <typename Writer>
327  void Statistics::WriteMaxTemperature(Writer& writer, const int bin) const
328  {
329  writer.String("max_temperature");
330  writer.StartObject();
331  for (int type = 0; type < Constants::ELEMENT_TYPES; ++type)
332  {
333  const std::string& type_name = Constants::ELEMENT_NAMES[type];
334 
335  writer.String(type_name.c_str());
336  writer.Double(MaxTemperature[type][bin] * Units::Temperature);
337  }
338  writer.EndObject(); // End current max temperature object
339  }
340 
341  template <typename Writer>
342  void Statistics::WriteKineticEnergy(Writer& writer, const int bin) const
343  {
344  writer.String("kinetic_energy");
345  writer.StartObject();
346  for (int type = 0; type < Constants::ELEMENT_TYPES; ++type)
347  {
348  const std::string& type_name = Constants::ELEMENT_NAMES[type];
349 
350  writer.String(type_name.c_str());
351  if (AtomsPerBin[type][bin] > 0)
352  {
353  const double ke =
354  0.5 * Info.AtomicMass[type] * VelocitySquaredPerBin[type][bin];
355  writer.Double(ke * Units::Energy);
356  }
357  else
358  {
359  writer.Double(0.0);
360  }
361  }
362  writer.EndObject(); // End current temperature object
363  }
364 
365  template <typename Writer>
366  void Statistics::WriteEnergyCoM(Writer& writer, const int bin) const
367  {
368  writer.String("kinetic_energy_com");
369  writer.StartObject();
370 
371  for (int type = 0; type < Constants::ELEMENT_TYPES; ++type)
372  {
373  const std::string& type_name = Constants::ELEMENT_NAMES[type];
374 
375  writer.String(type_name.c_str());
376  if (AtomsPerBin[type][bin] > 0)
377  {
378  const double thermal =
379  0.5 * Info.AtomicMass[type] * ThermalVelocitySquared[type][bin];
380  writer.Double(thermal * Units::Energy);
381  }
382  else
383  {
384  writer.Double(0.0);
385  }
386  }
387  writer.EndObject(); // End current temperature object
388  }
389 
390  template <typename Writer>
391  void Statistics::WriteStatistics(Writer& writer) const
392  {
393  writer.StartArray();
394  for (int bin = 0; bin < Bins; ++bin)
395  {
396  // Bin volume (from cone volume)
397  const double volume = Info.ConeSolidAngle / 3.0
398  * Pow3(CurrentRadius / Bins * Units::L)
399  * (Pow3(bin + 1) - Pow3(bin));
400 
401  const double density = TotalAtomsPerBin[bin] / volume;
402 
403  writer.StartObject();
404 
405  const double radius = (bin + 0.5) * CurrentRadius * Units::L / Bins;
406  writer.String("r"), writer.Double(radius);
407  writer.String("n"), writer.Double(TotalAtomsPerBin[bin]);
408  writer.String("density"), writer.Double(density);
409 
410  // Write temperature information for each element
411  this->WriteTemperature(writer, bin);
412  this->WriteVelocity(writer, bin);
413  this->WriteIonization(writer, bin);
414  this->WritePercentage(writer, bin);
415  this->WriteMaxTemperature(writer, bin);
416  this->WriteKineticEnergy(writer, bin);
417  this->WriteEnergyCoM(writer, bin);
418 
419  writer.EndObject(); // End the current bin object.
420  }
421 
422  writer.EndArray();
423 
424  writer.String("FusionRate"); writer.Uint64((uint64_t)FusionRate);
425  writer.String("MaxCollisionEnergy");
426  writer.Double(MaxCollisionEnergy * Units::M * Sqr(Units::L / Units::T));
427 
428  writer.String("CollisionEnergies");
429  writer.StartObject();
430  for (auto it = MaxCollisionEnergySpecies.begin();
431  it != MaxCollisionEnergySpecies.end(); ++ it)
432  {
433  const std::pair<int, int>& key = it->first;
434  const double energy = it->second;
435 
436  std::string key_name = Constants::ELEMENT_NAMES[key.first] + "-"
437  + Constants::ELEMENT_NAMES[key.second];
438 
439  writer.String(key_name.c_str());
440  writer.Double(energy * Units::Energy);
441  }
442  writer.EndObject();
443  }
444 }
445 
446 #endif
unsigned long long TotalCollisions
number of collision events
Definition: Statistics.h:33
unsigned long long TotalCellCrossings
number of cell crossing events
Definition: Statistics.h:34
unsigned long long TotalConeBoundaryCollisions
number of boundary collisions
Definition: Statistics.h:36
std::map< std::pair< int, int >, double > MaxCollisionEnergySpecies
Largest collision energy by the types of collision partners.
Definition: Statistics.h:42
double CollisionDistanceQuantile(const double p)
Given a probability p, compute the quantile that corresponds to that probability. ...
Definition: Statistics.cpp:81
tvmet::Vector< double, 3UL > DoubleVector
Vector type for representing particle positions and velocities as double precision floating point val...
Definition: Vector.hpp:23
Real2d MaxTemperature
Max temp at each bin.
Definition: Statistics.h:62
Definition: Statistics.h:18
double FusionRate
number of fusions that have occurred
Definition: Statistics.h:38
Definition: CollisionRecord.h:8
boost::circular_buffer< CollisionRecord > Collisions
Collision records.
Definition: Statistics.h:48
const int ELEMENT_TYPES
The number of different particle types in the simulation.
Definition: AtomicProperties.h:22
Defines the structure used to hold the configurable constants of the simulation.
Definition: InfoStruct.h:36
const std::string ELEMENT_NAMES[ELEMENT_TYPES]
The names of the elements.
Definition: AtomicProperties.h:28
unsigned long long TotalWallCollisions
number of wall collision events
Definition: Statistics.h:35