MercuryDPM  0.11
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
StatisticsVector.hcc
Go to the documentation of this file.
1 //Copyright (c) 2013-2014, The MercuryDPM Developers Team. All rights reserved.
2 //For the list of developers, see <http://www.MercuryDPM.org/Team>.
3 //
4 //Redistribution and use in source and binary forms, with or without
5 //modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name MercuryDPM nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 //WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 //DISCLAIMED. IN NO EVENT SHALL THE MERCURYDPM DEVELOPERS TEAM BE LIABLE FOR ANY
19 //DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 //(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 //ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 //(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
27 
28 #include "Particles/BaseParticle.h"
32 
33 std::ostream& operator<<(std::ostream& os, const StatType S)
34 {
35  if (S == O)
36  os << "O";
37  else if (S == X)
38  os << "X";
39  else if (S == Y)
40  os << "Y";
41  else if (S == Z)
42  os << "Z";
43  else if (S == XY)
44  os << "XY";
45  else if (S == XZ)
46  os << "XZ";
47  else if (S == YZ)
48  os << "YZ";
49  else if (S == XYZ)
50  os << "XYZ";
51  else if (S == RAZ)
52  os << "RAZ";
53  else if (S == RA)
54  os << "RA";
55  else if (S == AZ)
56  os << "AZ";
57  else if (S == RZ)
58  os << "RZ";
59  else if (S == R)
60  os << "R";
61  else if (S == A)
62  os << "A";
63  return os;
64 }
65 
66 template<StatType T>
68 {
69  // set w2
70  if (new_ > 0.0)
71  w2 = new_;
72  else
73  w2 = mathsFunc::square(w_over_rmax * particleHandler.getLargestParticle()->getRadius());
74  //(2.0*getXMax()/nx);
75 
76  // set cutoff radius
77  if (getCGShape() == HeavisideSphere || getCGShape() == Polynomial)
78  {
79  cutoff = sqrt(w2);
80  }
81  else if (getCGShape() == Gaussian)
82  {
83  if (getSuperExact())
84  cutoff = 5.0 * sqrt(w2);
85  else
86  cutoff = 3.0 * sqrt(w2);
88  }
89  else
90  {
91  std::cerr << "error in CG_function" << std::endl;
92  exit(-1);
93  }
94 }
95 
96 template<StatType T>
98 {
99  for (unsigned int i = 0; i < Points.size(); i++)
100  Points[i].set_zero();
101  if (getDoGradient())
102  for (unsigned int i = 0; i < Points.size(); i++)
103  {
104  dx[i].set_zero();
105  dy[i].set_zero();
106  dz[i].set_zero();
107  }
108  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it != particleHandler.end(); ++it)
109  {
110  (*it)->setPreviousPosition((*it)->getPosition());
111  }
112 }
113 
114 template<StatType T>
116 {
117  //stores the template parameter Stattype in a variable
118  set_statType();
119 
120  // sets connection between StatisticsPoint and StatisticsVector
122  // set nx, ny,nz
123  nx = ny = nz = 1;
124  nxMirrored = nyMirrored = nzMirrored = 0;
125 
126  // set default CG variables
127  CG_type = Gaussian;
128  // in get_statistics_..., w2 is set to w_over_rmax*rmax if w2==0
129  w_over_rmax = 1;
130 
131  // bounded domain
132  //~ boundedDomain = false;
133 
134  // set default values; variables will only be used if the default
135  // is overwritten; thus the default is a nonsense value
136  w2 = 0.0;
137  setCGTimeAveragingInterval(0);
138  setCGTimeMin(-1e20);
139  setTimeMaxStat(NAN);
140  rmin = 0;
141  hmax = 1e20;
142  rmax = 1e20;
143  indSpecies = -1; //all species
144 
145  //set default options - Not used it physially don't make sense i.e if ?max<?min
146  xminStat = NAN;
147  xmaxStat = NAN;
148  yminStat = NAN;
149  ymaxStat = NAN;
150  zminStat = NAN;
151  zmaxStat = NAN;
152 
153  // set default options
154  ignoreFixedParticles = true; //this should be true if you want statistics only of the flow
155  StressTypeForFixedParticles = 1;
156  verbosity = 1;
157  walls = true;
158  periodicWalls = true;
159  format = 0;
160  mirrorAtDomainBoundary = false;
161  setSuperExact(false);
162  VelocityProfile.resize(0); //equivalent to do not use velocityprofile
163  setStepSize(1);
164 
165  // time averaging
166  setDoTimeAverage(true);
167  nTimeAverage = 0;
168  nTimeAverageReset = -1;
169  //calculate variance
170  setDoVariance(false);
171  //calculate gradient
172  setDoGradient(false);
173  doDoublePoints = false;
174 
175  // additional stuff
176  statFile.setFileType(FileType::ONE_FILE);
177 }
178 
179 template<StatType T>
181  : DPMBase()
182 {
183  //assumes that we want the statistical method copied, but resets the time averaging
184  constructor();
185  //~ StatType statType; //this has to be constant, right?
186  nx = other.nx;
187  ny = other.ny;
188  nz = other.nz;
189  xminStat = other.xminStat;
190  yminStat = other.yminStat;
191  zminStat = other.zminStat;
192  xmaxStat = other.xmaxStat;
193  ymaxStat = other.ymaxStat;
194  zmaxStat = other.zmaxStat;
195  nxMirrored = other.nxMirrored;
196  nyMirrored = other.nyMirrored;
197  nzMirrored = other.nzMirrored;
198  Points = other.Points;
199  dx = other.dx;
200  dy = other.dy;
201  dz = other.dz;
202 
203  timeAverage = other.timeAverage;
204  timeVariance = other.timeVariance;
209  nTimeAverage = 0;
210  for (unsigned int i = 0; i < timeAverage.size(); i++)
211  timeAverage[i].set_zero();
212  for (unsigned int i = 0; i < timeVariance.size(); i++)
213  timeVariance[i].set_zero();
214  for (unsigned int i = 0; i < dxTimeAverage.size(); i++)
215  dxTimeAverage[i].set_zero();
216  for (unsigned int i = 0; i < dyTimeAverage.size(); i++)
217  dyTimeAverage[i].set_zero();
218  for (unsigned int i = 0; i < dzTimeAverage.size(); i++)
219  dzTimeAverage[i].set_zero();
220  doVariance = other.doVariance;
221  doGradient = other.doGradient;
222  CG_type = other.CG_type;
223  CGPolynomial = other.CGPolynomial;
224  w2 = other.w2;
225  cutoff = other.cutoff;
226  cutoff2 = other.cutoff2;
227  w_over_rmax = other.w_over_rmax;
228  tminStat = other.tminStat;
229  tmaxStat = other.tmaxStat;
230  tintStat = other.tintStat;
231  rmin = other.rmin;
232  rmax = other.rmax;
233  hmax = other.hmax;
234  indSpecies = other.indSpecies;
235  walls = other.walls;
239  verbosity = other.verbosity;
240  format = other.format;
242  isMDCLR = other.isMDCLR;
243  superexact = other.superexact;
244 }
245 
246 template<StatType T>
247 void StatisticsVector<T>::constructor(std::string name)
248 {
249  //call default constructor
250  constructor();
251 
252  // set name
253  setName(name.c_str());
254 
255  if (!strcmp(getName().c_str(), "c3d"))
256  {
257  //write here what to do with Stefan's data
258  std::cout << "MDCLR data" << std::endl;
259  exit(-1);
260  }
261  else
262  {
263  //write here what to do with Mercury data
264  isMDCLR = false;
265  if (readRestartFile()==0)
266  {
267  std::cout << "no restart file given: using default density 1" << std::endl;
269  speciesHandler.copyAndAddObject(LinearViscoelasticSpecies());
270 
271  }
272  setAppend(false);
273  //~ setTimeMaxStat(t+dt); //note:doesn't work if restart data is not the latest
274  }
275 }
276 
277 //Constructor that accepts arguments from the command line
278 template<StatType T>
280 {
281  //check if filename is given
282  if (argc < 2)
283  {
284  std::cerr << "fstatistics.exe filename [-options]" << std::endl
285  << "Type -help for more information" << std::endl;
286  exit(-1);
287  }
288 
289  //print help if required
290  if (!strcmp(argv[1], "-help"))
291  {
292  print_help();
293  }
294 
295  //create StatisticsVector
296  std::string filename(argv[1]);
297  constructor(filename);
298 
299  //check for options (standardly '-option argument')
300  readStatArguments(argc, argv);
301 }
302 
303 template<StatType T>
305 {
306  //This opens the file the data will be recalled from
307  std::fstream is;
308  is.open(filename, std::fstream::in);
309  if (!is.is_open() || is.bad())
310  {
311  std::cout << "Loading data file " << filename << " failed" << std::endl;
312  return false;
313  }
314 
315  //Read the file; we assume that the stat file we read in has the same stattype and domain size as the problem.
316  std::string line_string;
317  getline(is, line_string);
318  std::string dummy;
319  is >> dummy >> dummy;
320  is >> dummy >> dummy;
321  double xmin, xmax, ymin, ymax, zmin, zmax;
322  is >> dummy >> xmin >> xmax >> ymin >> ymax >> zmin >> zmax;
323  VelocityProfile_Min = Vec3D(xmin, ymin, zmin);
324  int nx, ny, nz;
325  is >> dummy >> nx >> ny >> nz;
326  double dx = (xmax - xmin) / (nx - 1);
327  double dy = (ymax - ymin) / (ny - 1);
328  double dz = (zmax - zmin) / (nz - 1);
329  VelocityProfile_D = Vec3D(dx, dy, dz);
330  std::string statType;
331  is >> dummy >> statType;
332  getline(is, line_string);
333  getline(is, line_string);
334 
335  setNX(nx);
336  setNY(ny);
337  setNZ(nz);
338  setXMinStat(xmin);
339  setYMinStat(ymin);
340  setZMinStat(zmin);
341  setXMaxStat(xmax);
342  setYMaxStat(ymax);
343  setZMaxStat(zmax);
344 
345  VelocityProfile.resize(nx * ny * nz);
346  Vec3D M;
347  double rho;
348  int n = 0;
349  for (int i = 0; i < nx; i++)
350  for (int j = 0; j < ny; j++)
351  for (int k = 0; k < nz; k++)
352  {
353  is >> dummy >> dummy >> dummy >> dummy >> rho >> M.X >> M.Y >> M.Z;
354  getline(is, line_string);
355  VelocityProfile[n] = M / rho;
356  n++;
357  }
358 
359  //Close the file
360  is.close();
361  std::cout << "Loaded data file " << filename << std::endl;
362  return true;
363 }
364 
365 template<StatType T>
367 {
368  double i, j, k;
369  double l, m, n;
370  l = modf((Position.X - VelocityProfile_Min.X) / VelocityProfile_D.X, &i);
371  m = modf((Position.Y - VelocityProfile_Min.Y) / VelocityProfile_D.Y, &j);
372  n = modf((Position.Z - VelocityProfile_Min.Z) / VelocityProfile_D.Z, &k);
373  if (nx < 1)
374  i = 0.0;
375  if (ny < 1)
376  j = 0.0;
377  if (nz < 1)
378  k = 0.0;
379  int ix = static_cast<int>((i * ny + j) * nz + k);
380  Vec3D V;
381  if (nx <= 1)
382  V.X = VelocityProfile[ix].X;
383  else
384  V.X = VelocityProfile[ix].X * (1 - l) + VelocityProfile[ix + ny * nz].X * l;
385  if (ny <= 1)
386  V.Y = VelocityProfile[ix].Y;
387  else
388  V.Y = VelocityProfile[ix].Y * (1 - m) + VelocityProfile[ix + nz].Y * m;
389  if (nz <= 1)
390  V.Z = VelocityProfile[ix].Z;
391  else
392  V.Z = VelocityProfile[ix].Z * (1 - n) + VelocityProfile[ix + 1].Z * n;
393  return V;
394 }
395 
396 //Constructor that accepts arguments from the command line
397 template<StatType T>
398 void StatisticsVector<T>::readStatArguments(int argc, char *argv[])
399 {
400  //check for options (standardly '-option argument')
401  for (int i = 2; i < argc; i += 2)
402  {
403  std::cout << "interpreting input argument " << argv[i];
404  if (i + 1 < argc)
405  std::cout << " " << argv[i + 1];
406  std::cout << std::endl;
407 
408  if (!strcmp(argv[i], "-CGtype"))
409  {
410  //CG_type_todo
411  if (!strcmp(argv[i + 1], "HeavisideSphere"))
412  {
413  setCGShape(HeavisideSphere);
414  }
415  else if (!strcmp(argv[i + 1], "Gaussian"))
416  {
417  setCGShape(Gaussian);
418  }
419  else
420  {
421  setCGShape(argv[i + 1]);
422  }
423  }
424  else if (!strcmp(argv[i], "-w"))
425  {
426  double old = getCGWidth();
427  setCGWidth(atof(argv[i + 1]));
428  std::cout << " w changed from " << old << " to " << getCGWidth() << std::endl;
429  }
430  else if (!strcmp(argv[i], "-help"))
431  {
432  print_help();
433  i--; //requires no argument
434  }
435  else if (!strcmp(argv[i], "-velocityprofile"))
436  {
437  loadVelocityProfile(argv[i + 1]);
438  }
439  else if (!strcmp(argv[i], "-h"))
440  {
441  set_h(atof(argv[i + 1]));
442  }
443  else if (!strcmp(argv[i], "-hx"))
444  {
445  set_hx(atof(argv[i + 1]));
446  }
447  else if (!strcmp(argv[i], "-hy"))
448  {
449  set_hy(atof(argv[i + 1]));
450  }
451  else if (!strcmp(argv[i], "-hz"))
452  {
453  set_hz(atof(argv[i + 1]));
454  }
455  else if (!strcmp(argv[i], "-n"))
456  {
457  setN(atoi(argv[i + 1]));
458  }
459  else if (!strcmp(argv[i], "-nx"))
460  {
461  setNX(atoi(argv[i + 1]));
462  }
463  else if (!strcmp(argv[i], "-ny"))
464  {
465  setNY(atoi(argv[i + 1]));
466  }
467  else if (!strcmp(argv[i], "-nz"))
468  {
469  setNZ(atoi(argv[i + 1]));
470  }
471  else if (!strcmp(argv[i], "-x"))
472  {
473  setXMinStat(atof(argv[i + 1]));
474  setXMaxStat(atof(argv[i + 2]));
475  i++; //requires two arguments
476  }
477  else if (!strcmp(argv[i], "-y"))
478  {
479  setYMinStat(atof(argv[i + 1]));
480  setYMaxStat(atof(argv[i + 2]));
481  i++; //requires two arguments
482  }
483  else if (!strcmp(argv[i], "-z"))
484  {
485  setZMinStat(atof(argv[i + 1]));
486  setZMaxStat(atof(argv[i + 2]));
487  i++; //requires two arguments
488  }
489  else if (!strcmp(argv[i], "-positions"))
490  {
491  loadPositions(argv[i+1]);
492  }
493  else if (!strcmp(argv[i], "-indSpecies"))
494  {
495  indSpecies = atoi(argv[i + 1]);
496  }
497  else if (!strcmp(argv[i], "-rmin"))
498  {
499  rmin = atof(argv[i + 1]);
500  }
501  else if (!strcmp(argv[i], "-rmax"))
502  {
503  rmax = atof(argv[i + 1]);
504  }
505  else if (!strcmp(argv[i], "-hmax"))
506  {
507  hmax = atof(argv[i + 1]);
508  }
509  else if (!strcmp(argv[i], "-periodicwalls"))
510  {
511  setDoPeriodicWalls(atoi(argv[i + 1]));
512  }
513  else if (!strcmp(argv[i], "-walls"))
514  {
515  setCGWidthalls(atoi(argv[i + 1]));
516  }
517  else if (!strcmp(argv[i], "-verbosity"))
518  {
519  setVerbosityLevel(atoi(argv[i + 1]));
520  }
521  else if (!strcmp(argv[i], "-verbose"))
522  {
523  verbose();
524  i--; //requires no argument
525  }
526  else if (!strcmp(argv[i], "-format"))
527  {
528  format = atoi(argv[i + 1]);
529  }
530  else if (!strcmp(argv[i], "-doDoublePoints"))
531  {
532  if (argc <= i + 1 || argv[i + 1][0] == '-')
533  {
534  setDoDoublePoints(true);
535  i--; //no argument
536  }
537  else
538  setDoDoublePoints(atoi(argv[i + 1]));
539  std::cout << "set doDoublePoints=" << getDoDoublePoints() << std::endl;
540  }
541  else if (!strcmp(argv[i], "-w_over_rmax"))
542  {
543  setCGWidth_over_rmax(atof(argv[i + 1]));
544  }
545  else if (!strcmp(argv[i], "-tmin"))
546  {
547  setCGTimeMin(atof(argv[i + 1]));
548  }
549  else if (!strcmp(argv[i], "-tmax"))
550  {
551  setTimeMaxStat(atof(argv[i + 1]));
552  }
553  else if (!strcmp(argv[i], "-tint"))
554  {
555  setCGTimeAveragingInterval(atof(argv[i + 1]));
556  //~ } else if (!strcmp(argv[i],"-timesteps")) {
557  //~ setCGTimeAveragingInterval(atof(argv[i+1])*getTimeStep());
558  }
559  else if (!strcmp(argv[i], "-stepsize"))
560  {
561  int stepSize = atoi(argv[i + 1]);
562  setStepSize(stepSize);
563  }
564  else if (!strcmp(argv[i], "-loaddatafile"))
565  {
566  readDataFile(argv[i + 1]);
567  setCGTimeMin(getTime());
568  setTimeMaxStat(getTimeMax());
569  }
570  else if (!strcmp(argv[i], "-statfilename") | !strcmp(argv[i], "-o"))
571  {
572  statFile.setName(argv[i + 1]);
574  // setName(argv[i+1]);
575  }
576  else if (!strcmp(argv[i], "-timeaverage"))
577  {
578  setDoTimeAverage(atoi(argv[i + 1]));
579  }
580  else if (!strcmp(argv[i], "-timeaveragereset"))
581  {
582  nTimeAverageReset = atoi(argv[i + 1]);
583  }
584  else if (!strcmp(argv[i], "-gradient"))
585  {
586  // use default argument if no argument is given
587  if (argc <= i + 1 || argv[i + 1][0] == '-')
588  {
589  setDoGradient(true);
590  i--; //no argument
591  }
592  else
593  setDoGradient(atoi(argv[i + 1]));
594  }
595  else if (!strcmp(argv[i], "-timevariance"))
596  {
597  // use default argument if no argument is given
598  if (argc <= i + 1 || argv[i + 1][0] == '-')
599  {
600  setDoVariance(true);
601  i--; //no argument
602  }
603  else
604  setDoVariance(atoi(argv[i + 1]));
605  }
606  else if (!strcmp(argv[i], "-superexact"))
607  {
608  // use default argument if no argument is given
609  if (argc <= i + 1 || argv[i + 1][0] == '-')
610  {
611  setSuperExact(true);
612  i--; //no argument
613  }
614  else
615  setSuperExact(atoi(argv[i + 1]));
616  }
617  else if (!strcmp(argv[i], "-ignoreFixedParticles"))
618  {
619  // use default argument if no argument is given
620  if (argc <= i + 1 || argv[i + 1][0] == '-')
621  {
622  setDoIgnoreFixedParticles(true);
623  i--; //no argument
624  }
625  else
626  setDoIgnoreFixedParticles(atoi(argv[i + 1]));
627  }
628  else if (!strcmp(argv[i], "-StressTypeForFixedParticles"))
629  {
630  StressTypeForFixedParticles = atoi(argv[i + 1]);
631  }
632  else if (!strcmp(argv[i], "-mirrorAtDomainBoundary"))
633  {
634  setMirrorAtDomainBoundary(atof(argv[i + 1]));
635  }
636  else if (!strcmp(argv[i], "-stattype") || !strcmp(argv[i], "-statType"))
637  {
638  //this was already used in Statistics()
639  }
640  else if (readNextArgument(i, argc, argv))
641  {
642  //~ std::cout << " (read as MD argument, not statistics)" << std::endl;
643  }
644  else
645  {
646  std::cerr << "Error: option unknown: " << argv[i] << std::endl;
647  exit(-1);
648  }
649  }
650 }
651 
652 //Constructor that accepts arguments from the command line
653 template<StatType T>
655 {
656  std::cout << "fstatistics.exe filename [-options]: " << std::endl
657  << "This program evaluates statistical data from .fstat, .data, and. restart files and writes it into a .stat file" << std::endl << std::endl;
658  std::cout << "OPTIONS:" << std::endl << std::endl;
659  std::cout << "-stattype [X,Y,Z,XY,XZ,YZ,XYZ,RAZ,RA,AZ,RZ,R,A]: " << std::endl
660  << "Used to obtain statistics averaged in all coordinate directions but the ones specified; f.e. -stattype Z yields depth-profiles. Default is XYZ." << std::endl << std::endl
661  << "-CGtype [HeavisideSphere,Gaussian]: " << std::endl
662  << "Averaging function; default: Gaussian" << std::endl << std::endl
663  << "-w,-w_over_rmax [Mdouble]: " << std::endl
664  << "Averaging width, absolute or in multiples of the radius of the largest particle in the restart file; default: w_over_rmax=1" << std::endl << std::endl
665  << "-n,nx,ny,nz [uint]: " << std::endl
666  << "Specifies the amount of grid points in coordinate directions for which statistics are evaluated; use -n to set all 3 directions at once; is set to one in averaged directions (see stattype). Default n=1" << std::endl << std::endl
667  << "-h,hx,hy,hz [Mdouble]: " << std::endl
668  << "Defines the amount of grid points by setting the mesh size " << std::endl << std::endl
669  << "-x,y,z [Mdouble Mdouble]: " << std::endl
670  << "Specifies the domain of the grid; f.e. for -x 0 1 all grid points will have x-values within [0,1]. Default -x xmin xmax (from restart file)" << std::endl << std::endl
671  << "-indSpecies [int]: " << std::endl
672  << "-rmin,rmax [Mdouble]: " << std::endl
673  << "-hmax [Mdouble]: " << std::endl
674  << "Allows to only obtain statistics for specific particles" << std::endl << std::endl
675  << "-periodicwalls [bool]: " << std::endl
676  << "neglects periodic walls" << std::endl << std::endl
677  << "-walls [uint]: " << std::endl
678  << "only takes into account the first n walls" << std::endl << std::endl
679  << "-verbosity [uint]: " << std::endl
680  << "amount of screen output (0 minimal, 1 normal, 2 maximal)" << std::endl << std::endl
681  << "-verbose: " << std::endl
682  << "identical to -verbosity 2" << std::endl << std::endl
683  << "-format [uint]: " << std::endl
684  << "???" << std::endl << std::endl
685  << "-tmin,tmax,tint [Mdouble]: " << std::endl
686  << "redefines the time interval [tmin,tmax] for which statistics are evaluated. Default values from restart file; tint sets tmin to tmax-tint." << std::endl << std::endl
687  << "-stepsize [uint]: " << std::endl
688  << "to skip some timesteps. Default: 1 " << std::endl << std::endl
689  << "-statfilename [std::string]: " << std::endl
690  << "to change the name of the output file" << std::endl << std::endl
691  << "-timeaverage [bool]: " << std::endl
692  << "To average in time (1) or to print statistics for all time steps (0). Default: 1" << std::endl << std::endl
693  << "-timevariance [bool]: " << std::endl
694  << "to print the time variance; only for time averaged data. Default: ?" << std::endl << std::endl
695  << "-gradient: " << std::endl
696  << "to plot the first derivative of each statistical value" << std::endl << std::endl
697  << "-ignoreFixedParticles: " << std::endl
698  << "-StressTypeForFixedParticles: " << std::endl
699  << "-mirrorAtDomainBoundary [Mdouble]" << std::endl << std::endl
700  << "" << std::endl << std::endl
701  << "OUTPUT:" << std::endl << std::endl
702  << "1-3: Coordinates " << std::endl
703  << "4: Nu " << std::endl
704  << "5: Density " << std::endl
705  << "6-8: Momentum " << std::endl
706  << "9-11: DisplacementMomentum " << std::endl
707  << "12-17: Displacement" << std::endl
708  << "18-23: MomentumFlux" << std::endl
709  << "24-29: DisplacementMomentumFlux" << std::endl
710  << "30-32: EnergyFlux " << std::endl
711  << "33-41: NormalStress " << std::endl
712  << "42-50: TangentialStress " << std::endl
713  << "51-53: NormalTraction " << std::endl
714  << "54-56: TangentialTraction " << std::endl
715  << "57-62: Fabric " << std::endl
716  << "63-65: CollisionalHeatFlux " << std::endl
717  << "66: Dissipation " << std::endl
718  << "67: Potential " << std::endl
719  << "68-70: LocalAngularMomentum " << std::endl
720  << "71-79: LocalAngularMomentumFlux " << std::endl
721  << "80-88: ContactCoupleStress " << std::endl;
722  exit(0);
723 }
724 
725 template<StatType T>
726 void StatisticsVector<T>::setCGShape(const char* new_)
727 {
728  if (!strcmp(new_, "Heaviside"))
729  {
730  int dim = 3;
731  int numcoeff = 1;
732  double heavisidecoeff[] = {1};
733  set_Polynomial(heavisidecoeff, numcoeff, dim);
734  }
735  else if (!strcmp(new_, "Linear"))
736  {
737  int dim = 3;
738  int numcoeff = 2;
739  double lincoeff[] = {-1, 1};
740  set_Polynomial(lincoeff, numcoeff, dim);
741  }
742  else if (!strcmp(new_, "Lucy"))
743  {
744  int dim = 3;
745  int numcoeff = 5;
746  double lucycoeff[] = {-3, 8, -6, 0, 1};
747  set_Polynomial(lucycoeff, numcoeff, dim);
748  }
749  else if (!strcmp(new_, "Gaussian"))
750  {
751  setCGShape(Gaussian);
752  return;
753  }
754  else if (!strcmp(new_, "HeavisideSphere"))
755  {
756  setCGShape(HeavisideSphere);
757  return;
758  }
759  else
760  {
761  std::cerr << "Error: unknown CG_type: " << new_ << std::endl;
762  exit(-1);
763  }
764  setPolynomialName(new_);
765  setCGShape(Polynomial);
766 }
767 
768 template<StatType T>
770 {
771  if (new_ == Polynomial && CGPolynomial.getOrder() < 0)
772  {
773  std::cerr << "Polynomial is not specified" << std::endl;
774  exit(-1);
775  }
776  CG_type = new_;
777 }
778 
780 template<StatType T>
782 {
783  std::stringstream ss;
784  ss << "Statistical parameters: name=" << getName()
785  << ",\n nx=" << nx
786  << ", ny=" << ny
787  << ", nz=" << nz
788  << ", CG_type=";
789  if (getCGShape() == HeavisideSphere)
790  {
791  ss << "HeavisideSphere";
792  }
793  else if (getCGShape() == Gaussian)
794  {
795  ss << "Gaussian";
796  }
797  else if (getCGShape() == Polynomial)
798  {
799  ss << getPolynomialName();
800  }
801  else
802  {
803  std::cerr << "error in CG_function" << std::endl;
804  exit(-1);
805  }
806 
807  ss << ", w=" << sqrt(w2)
808  << ", cutoff=" << cutoff
809  << ",\n tStat=[" << getCGTimeMin() << "," << getTimeMaxStat() << "]"
810  << ", xStat=[" << getXMinStat() << "," << getXMaxStat() << "]"
811  << ", yStat=[" << getYMinStat() << "," << getYMaxStat() << "]"
812  << ", zStat=[" << getZMinStat() << "," << getZMaxStat() << "]"
813  << ",\n ignoreFixedParticles=" << ignoreFixedParticles
814  << ", StressTypeForFixedParticles=" << StressTypeForFixedParticles
815  << ",\n mirrorAtDomainBoundary=" << getMirrorAtDomainBoundary()
816  << ",\n doTimeAverage=" << getDoTimeAverage()
817  << ", doVariance=" << getDoVariance()
818  << ", doGradient=" << getDoGradient()
819  << ", verbosity=" << verbosity
820  << std::endl;
821  return ss.str();
822 }
823 
826 template<StatType T>
828 {
829  std::stringstream ss;
830  ss << "w " << sqrt(getCGWidthSquared())
831  << " dim " << getSystemDimensions()
832  << " domainStat " << getXMinStat() << " " << getXMaxStat()
833  << " " << getYMinStat() << " " << getYMaxStat()
834  << " " << getZMinStat() << " " << getZMaxStat()
835  << " n " << nx << " " << ny << " " << nz
836  << " statType " << statType;
837  if (CG_type == Polynomial)
838  ss << " CGPolynomial " << CGPolynomial;
839  else
840  ss << " CG_type " << CG_type << " cutoff " << cutoff;
841  if (doVariance)
842  ss << " doVariance";
843  if (doGradient)
844  ss << " doGradient";
845  if (doTimeAverage)
846  {
847  ss << " doTimeAverage";
848  if (nTimeAverageReset != -1)
849  ss << " nTimeAverageReset " << nTimeAverageReset;
850  }
851  if (indSpecies != -1)
852  ss << " indSpecies " << indSpecies;
853  if (rmin != 0)
854  ss << " rmin " << rmin;
855  if (rmax != 1e20)
856  ss << " rmax " << rmax;
857  if (hmax != 1e20)
858  ss << " hmax " << hmax;
859  if (!walls)
860  ss << " noWalls";
861  if (!periodicWalls)
862  ss << " noPeriodicWalls";
863  if (!ignoreFixedParticles)
864  ss << " includeFixedParticles";
865  if (StressTypeForFixedParticles != 1)
866  ss << " StressTypeForFixedParticles " << StressTypeForFixedParticles;
867  return ss.str();
868 }
869 
871 template<StatType T>
873 {
874  StatisticsPoint<T> avg;
875  avg.set_zero();
876  for (unsigned int i = 0; i < P.size(); i++)
877  avg += P[i];
878  avg /= P.size();
879  return avg;
880 }
881 
882 template<StatType T>
884 {
885  reset_statistics();
886 
888 
890 
891  //set tmin and tmax if tint is set
892  if (getCGTimeAveragingInterval() != 0.0)
893  {
894  setCGTimeMin(getTime());
895  setTimeMaxStat(getCGTimeMin() + getCGTimeAveragingInterval());
896  std::cout << "tint set, time goes from: " << getCGTimeMin() << " to: " << getTimeMaxStat() << std::endl;
897  }
898 
899  statFile.open();
900 
901  statFile.getFstream() << Points.begin()->write_variable_names() << std::endl;
902  statFile.getFstream() << print_CG() << std::endl;
903 
904  //std::couts variables
905  if (verbosity > 1)
906  std::cout << std::endl;
907  if (verbosity > 0)
908  std::cout << std::endl << printStat() << std::endl;
909 
910 }
911 
912 template<StatType T>
913 bool StatisticsVector<T>::readNextDataFile(unsigned int format)
914 {
915  static unsigned int count = 0;
916 
917  if (count)
918  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it != particleHandler.end(); ++it)
919  {
920  (*it)->setPreviousPosition((*it)->getPosition());
921  }
922 
923  bool ret_val = DPMBase::readNextDataFile(format);
924 
925  if (!count)
926  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it != particleHandler.end(); ++it)
927  {
928  (*it)->setPreviousPosition((*it)->getPosition());
929  }
930 
931  count++;
932  return ret_val;
933 }
934 
935 template<StatType T>
937 {
938  std::cout << "writing statistics for t=" << getTime() << std::endl;
939 
940  // write to .stat file
941  statFile.getFstream() << std::left << std::setprecision(8) << std::setw(6) << getTime() << std::endl;
942  for (unsigned int i = 0; i < Points.size(); i++)
943  statFile.getFstream() << Points[i];
944  //std::cout << "S" << Points[2] << std::endl;
945  if (getDoGradient())
946  {
947  statFile.getFstream() << std::left << std::setprecision(8) << std::setw(6) << getTime() << std::endl;
948  for (unsigned int i = 0; i < dx.size(); i++)
949  statFile.getFstream() << dx[i];
950  statFile.getFstream() << std::left << std::setprecision(8) << std::setw(6) << getTime() << std::endl;
951  for (unsigned int i = 0; i < dy.size(); i++)
952  statFile.getFstream() << dy[i];
953  statFile.getFstream() << std::left << std::setprecision(8) << std::setw(6) << getTime() << std::endl;
954  for (unsigned int i = 0; i < dz.size(); i++)
955  statFile.getFstream() << dz[i];
956  }
957 
958 }
959 
960 template<StatType T>
962 {
963  if (getDoTimeAverage())
964  write_time_average_statistics();
965  statFile.close();
966 }
967 
968 template<StatType T>
970 {
971  if (check_current_time_for_statistics() && usethese)
972  {
973  if (getMirrorAtDomainBoundary() != 0.0)
974  {
975  for (unsigned int i = 0; i < Points.size(); i++)
976  {
977  if (Points[i].mirrorParticle >= 0)
978  {
979  //add values to the mirrorParticle
980  Points[Points[i].mirrorParticle] += Points[i];
981  Points[i].set_zero();
982  if (getDoGradient())
983  {
984  dx[Points[i].mirrorParticle] += dx[i];
985  dy[Points[i].mirrorParticle] += dy[i];
986  dz[Points[i].mirrorParticle] += dz[i];
987  }
988  }
989  }
990  }
991  //~ for (unsigned int i=0; i<Points.size(); i++)
992  //~ Points[i].Displacement /= mathsFunc::square(Points[i].Density);
993  if (getDoTimeAverage())
994  {
995  for (unsigned int i = 0; i < timeAverage.size(); i++)
996  {
997  timeAverage[i] += Points[i];
998  if (getDoVariance())
999  timeVariance[i] += Points[i].getSquared();
1000  if (getDoGradient())
1001  {
1002  dxTimeAverage[i] += dx[i];
1003  dyTimeAverage[i] += dy[i];
1004  dzTimeAverage[i] += dz[i];
1005  }
1006  }
1007  nTimeAverage++;
1008  if (nTimeAverage == nTimeAverageReset)
1009  {
1010  std::cout << "write time average" << std::endl;
1011  write_time_average_statistics();
1012  nTimeAverage = 0;
1013  for (unsigned int i = 0; i < timeAverage.size(); i++)
1014  timeAverage[i].set_zero();
1015  }
1016  }
1017  else
1018  {
1019  write_statistics();
1020  }
1021  }
1022  reset_statistics();
1023 }
1024 
1025 template<StatType T>
1027 {
1028  static bool first = true;
1029 
1030  if (verbosity)
1031  std::cout << std::endl << "averaging " << nTimeAverage << " timesteps " << std::endl;
1032  if (nTimeAverage == 0)
1033  {
1034  fprintf(stderr, "\n\n\tERROR :: Can not do TimeAverage of 0 timesteps\n\n");
1035  //exit(-1);
1036  return;
1037  }
1038  if (first)
1039  {
1040  std::cout << "first" << nTimeAverage << std::endl;
1041  for (unsigned int i = 0; i < timeAverage.size(); i++)
1042  {
1043  timeAverage[i].firstTimeAverage(nTimeAverage);
1044  if (getDoVariance())
1045  {
1046  timeVariance[i].firstTimeAverage(nTimeAverage);
1047  timeVariance[i] -= timeAverage[i].getSquared();
1048  }
1049  if (getDoGradient())
1050  {
1051  dxTimeAverage[i].firstTimeAverage(nTimeAverage);
1052  dyTimeAverage[i].firstTimeAverage(nTimeAverage);
1053  dzTimeAverage[i].firstTimeAverage(nTimeAverage);
1054  }
1055  }
1056  first = false;
1057  }
1058  else
1059  {
1060  std::cout << "next" << nTimeAverage << std::endl;
1061  for (unsigned int i = 0; i < timeAverage.size(); i++)
1062  {
1063  timeAverage[i] /= nTimeAverage;
1064  if (getDoVariance())
1065  {
1066  timeVariance[i] /= nTimeAverage;
1067  timeVariance[i] -= timeAverage[i].getSquared();
1068  }
1069  if (getDoGradient())
1070  {
1071  dxTimeAverage[i] /= nTimeAverage;
1072  dyTimeAverage[i] /= nTimeAverage;
1073  dzTimeAverage[i] /= nTimeAverage;
1074  }
1075  }
1076  }
1077 
1078  // write average to .stat file
1079  statFile.getFstream() << std::left << std::setprecision(8) << std::setw(6) << getCGTimeMin() << " " << getTime() << std::endl;
1080  for (unsigned int i = 0; i < timeAverage.size(); i++)
1081  statFile.getFstream() << timeAverage[i];
1082  // write to std::cout
1083  StatisticsPoint<T> avg = average(timeAverage);
1084  std::cout << "Averages: " << avg.print() << std::endl;
1085 
1086  if (getDoVariance())
1087  {
1088  // write variance to .stat file
1089  statFile.getFstream() << std::left << std::setprecision(8) << std::setw(6) << getCGTimeMin() << " " << getTime() << " " << std::endl;
1090  for (unsigned int i = 0; i < timeVariance.size(); i++)
1091  statFile.getFstream() << timeVariance[i];
1092  //StatisticsPoint<T> var = average(timeVariance);
1093  } //end if (getDoVariance)
1094 
1095  if (getDoGradient())
1096  {
1097  // write variance to .stat file
1098  statFile.getFstream() << std::left << std::setprecision(8) << std::setw(6) << getCGTimeMin() << " " << getTime() << " " << std::endl;
1099  for (unsigned int i = 0; i < timeAverage.size(); i++)
1100  statFile.getFstream() << dxTimeAverage[i];
1101  statFile.getFstream() << std::left << std::setprecision(8) << std::setw(6) << getCGTimeMin() << " " << getTime() << " " << std::endl;
1102  for (unsigned int i = 0; i < timeAverage.size(); i++)
1103  statFile.getFstream() << dyTimeAverage[i];
1104  statFile.getFstream() << std::left << std::setprecision(8) << std::setw(6) << getCGTimeMin() << " " << getTime() << " " << std::endl;
1105  for (unsigned int i = 0; i < timeAverage.size(); i++)
1106  statFile.getFstream() << dzTimeAverage[i];
1107  }
1108 
1109  setCGTimeMin(getTime());
1110 
1111 }
1112 template<StatType T>
1114 {
1115  std::cout << "set " << " positions" << std::endl;
1116  dataFile.setCounter(0);
1117  fStatFile.setCounter(0);
1118 
1119  //This opens the file the data will be recalled from
1120  if (dataFile.getFileType() == FileType::ONE_FILE)
1121  dataFile.open(std::fstream::in);
1122  if (fStatFile.getFileType() == FileType::ONE_FILE)
1123  fStatFile.open(std::fstream::in);
1124 
1125 
1126  //load first set of timesteps to obtain xdim, ydim, zdim
1127 
1128  //try to read data files; if data.0000 does not exist, try the next, up to .9999
1129  for (int i = 1; i < 10000; i++)
1130  {
1131  if (readNextDataFile(format))
1132  break;
1133  fStatFile.openNextFile(std::fstream::in);
1134  }
1135 
1136  //set tminstat to smallest time evaluated
1137  if (getTime() >= getCGTimeMin())
1138  setCGTimeMin(getTime() - getTimeStep());
1139 
1140  //This creates the file statistics will be saved to
1141  //getStatFile.open(std::fstream::out);
1142 
1143  if (verbosity > 1)
1144  {
1145  std::cout << "Input from " << dataFile.getName() << std::endl;
1146  std::cout << "Input from " << fStatFile.getName() << std::endl;
1147  std::cout << "Output to " << statFile.getName() << std::endl << std::endl;
1148  }
1149 
1150  initialiseStatistics();
1151 
1152  //std::couts collision time
1154 // if (verbosity > 1)
1155 // {
1156 // //getLargestParticle()->computeMass(getSpecies()); //This should already have been done in readNextdataFile;
1157 // Mdouble mass = particleHandler.getLargestParticle()->getMass();
1158 // std::cout << "Collision Time " << speciesHandler.getObject(0)->getCollisionTime(mass)
1159 // << " and restitution coefficient " << speciesHandler.getObject(0)->getRestitutionCoefficient(mass)
1160 // << " for mass " << mass << std::endl
1161 // << std::endl;
1162 // }
1163  //std::couts particles
1164  if (verbosity > 2)
1165  {
1166  DPMBase::write(std::cout, true);
1167  std::cout << std::endl;
1168  }
1169  else if (verbosity)
1170  {
1171  //DPMBase::write(std::cout, false);
1172  //std::cout << std::endl;
1173  }
1174 
1175 
1176  //this increases the file counter
1177  if ((fStatFile.getFileType() == FileType::MULTIPLE_FILES || fStatFile.getFileType() == FileType::MULTIPLE_FILES_PADDED) && getTime() < getCGTimeMin())
1178  {
1179  if (verbosity > 1)
1180  findNextExistingDataFile(getCGTimeMin());
1181  else
1182  findNextExistingDataFile(getCGTimeMin(), false);
1183  for (unsigned int i = 1; i < dataFile.getCounter(); i++)
1184  jump_fstat();
1185 
1186  }
1187 
1188  //Output statistics for each time step
1189  std::cout << "Start statistics" << std::endl;
1190  do
1191  {
1192  if (getTime() > getTimeMaxStat())
1193  {
1194  std::cout
1195  << "reached end t=" << std::setprecision(9) << getTime()
1196  << " tmaxStat=" << std::setprecision(9) << getTimeMaxStat()
1197  << std::endl;
1198  break;
1199  }
1200  else if (getTime() < getCGTimeMin())
1201  {
1202  if (verbosity > 1)
1203  std::cout << "Jumping statistics t=" << getTime() << " tminStat()=" << getCGTimeMin() << std::endl;
1204  jump_fstat();
1205  }
1206  else
1207  {
1208  if (verbosity)
1209  std::cout << "Get statistics for t=" << std::setprecision(9) << getTime() << std::endl;
1210  if (verbosity > 1)
1211  std::cout << "#particles=" << particleHandler.getNumberOfObjects() << std::endl;
1212 
1213  if (!walls)
1214  wallHandler.clear();
1216  if (!periodicWalls)
1217  boundaryHandler.clear();
1218 
1219  outputStatistics();
1220  gather_force_statistics_from_fstat_and_data();
1221  processStatistics(true);
1222 
1223  }
1224  //if step size>1, skip a number of steps.
1225  if (dataFile.getFileType() == FileType::ONE_FILE)
1226  for (unsigned int i = 1; i < getStepSize(); i++)
1227  {
1228  //you only get here if you change the step size and you use a single data file
1229  readNextDataFile(format);
1230  jump_fstat();
1231  }
1232  } while (readNextDataFile(format));
1233  //set tmax to largest time evaluated
1234  if (getTime() < getTimeMaxStat())
1235  setTimeMaxStat(getTime());
1236 
1237  finishStatistics();
1238  dataFile.close();
1239  fStatFile.close();
1240 }
1241 
1242 template<StatType T>
1244 {
1245  if (particleHandler.getNumberOfObjects() < 1)
1246  return;
1247  std::vector<BaseParticle*>::iterator it = particleHandler.begin();
1248  setXMin((*it)->getPosition().X - (*it)->getRadius());
1249  setYMin((*it)->getPosition().Y - (*it)->getRadius());
1250  setZMin((*it)->getPosition().Z - (*it)->getRadius());
1251  setXMax((*it)->getPosition().X + (*it)->getRadius());
1252  setYMax((*it)->getPosition().Y + (*it)->getRadius());
1253  setZMax((*it)->getPosition().Z + (*it)->getRadius());
1254  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it != particleHandler.end(); ++it)
1255  {
1256  setXMin(std::min(getXMin(), (*it)->getPosition().X - (*it)->getRadius()));
1257  setYMin(std::min(getYMin(), (*it)->getPosition().Y - (*it)->getRadius()));
1258  setZMin(std::min(getZMin(), (*it)->getPosition().Z - (*it)->getRadius()));
1259  setXMax(std::max(getXMax(), (*it)->getPosition().X + (*it)->getRadius()));
1260  setYMax(std::max(getYMax(), (*it)->getPosition().Y + (*it)->getRadius()));
1261  setZMax(std::max(getZMax(), (*it)->getPosition().Z + (*it)->getRadius()));
1262  } //end for all particles
1263 }
1264 
1265 template<StatType T>
1267 {
1268  //uncomment if you want data file output
1269  //MD::outputXBallsData();
1270 
1271  unsigned int N;
1272  Mdouble dummy;
1273  std::string dummyStr;
1274 
1275  //read first parameters and check if we reached the end of the file
1276 
1277  //Ignoring first line
1278  getline(p3p_file, dummyStr);
1279  if (verbosity>2)
1280  std::cout << dummyStr << std::endl;
1281  //Reading second line
1282  p3p_file >> dummy;
1283  setTime(dummy);
1284  p3p_file >> N;
1285  std::cout << "t= " << getTime() << ": loading " << N << " particles ..." << std::endl;
1286  getline(p3p_file, dummyStr);
1287  //std::cout << dummyStr << std::endl;
1288  //Ignoring third line
1289  getline(p3p_file, dummyStr);
1290  if (verbosity>2)
1291  std::cout << dummyStr << std::endl;
1292  if (p3p_file.eof() || p3p_file.peek() == -1)
1293  {
1294  std::cout << "reached end of p3p file" << std::endl;
1295  return false;
1296  }
1297 
1298  BaseParticle P0;
1299  if (particleHandler.getNumberOfObjects() < N)
1300  while (particleHandler.getNumberOfObjects() < N)
1301  particleHandler.copyAndAddObject(P0);
1302  else
1303  while (particleHandler.getNumberOfObjects() > N)
1304  particleHandler.removeLastObject();
1305 
1306  //Read forth to (N+3)rd line
1307  Vec3D dummyVec;
1308  Vec3D position, velocity, angle, angularVelocity;
1309  int dummyInt;
1310  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it != particleHandler.end(); ++it)
1311  {
1312  p3p_file >> dummyInt;
1313  (*it)->setIndex(dummyInt); //ID
1314  //std::cout << " ID " << (*it)->getIndex() << std::endl;
1315  p3p_file >> dummyInt;
1316  (*it)->setIndSpecies(dummyInt - 1); //Group
1317  p3p_file >> dummy;
1318  (*it)->setRadius(pow(dummy / (4. / 3. * constants::pi), 1. / 3.)); //Volume
1319  p3p_file >> dummy;
1320  (*it)->setMass(dummy); //Mass
1321  p3p_file
1322  >> position
1323  >> velocity
1324  >> angularVelocity;
1325  (*it)->setPosition(position);
1326  (*it)->setVelocity(velocity);
1327  (*it)->setAngularVelocity(angularVelocity);
1328  //clean up tangential springs
1329  } //end for all particles
1330  //auto_setSystemDimensions();
1331 
1332  getline(p3p_file, dummyStr);
1333  if (verbosity>2)
1334  std::cout << dummyStr << std::endl;
1335 
1336  //fix particles, if data_FixedParticles!=0
1337 
1338  return true;
1339 }
1340 
1342 template<StatType T>
1344 {
1345  //This opens the files the data will be recalled from
1346  std::string p3p_filename = getName().c_str();
1347  p3p_filename += ".p3p";
1348  bool opened = helpers::openFile(p3p_file, p3p_filename, std::fstream::in);
1349  std::string p3c_filename = getName().c_str();
1350  p3c_filename += ".p3c";
1351  helpers::openFile(p3c_file, p3c_filename, std::fstream::in);
1352  std::string p3w_filename = getName().c_str();
1353  p3w_filename += ".p3w";
1354  helpers::openFile(p3w_file, p3w_filename, std::fstream::in);
1355  int version = 3;
1356  //If p3 is not available, open p4 files
1357  if (!opened)
1358  {
1359  std::cerr << "Warning could not open " << p3p_filename << std::endl;
1360  version = 4;
1361  p3p_filename = getName().c_str();
1362  p3p_filename += ".p4p";
1363  opened = helpers::openFile(p3p_file, p3p_filename, std::fstream::in);
1364  p3c_filename = getName().c_str();
1365  p3c_filename += ".p4c";
1366  opened = helpers::openFile(p3c_file, p3c_filename, std::fstream::in);
1367  p3w_filename = getName().c_str();
1368  p3w_filename += ".p4w";
1369  opened = helpers::openFile(p3w_file, p3w_filename, std::fstream::in);
1370  if (!opened)
1371  {
1372  std::cerr << "could not open " << p3p_filename << std::endl;
1373  exit(-1);
1374  }
1375  }
1376  std::cout << "opened " << p3p_filename << std::endl;
1377 
1378  //load first set of timesteps to obtain xdim, ydim, zdim
1379 
1380  //try to read data files; if data.0000 does not exist, try the next, up to .9999
1381  read_next_from_p3p_file();
1382 
1383  //set tminstat to smallest time evaluated
1384  if (getTime() >= getCGTimeMin())
1385  setCGTimeMin(getTime() - getTimeStep());
1387 
1388  dataFile.open(std::fstream::out);
1390  setParticleDimensions(3);
1391  DPMBase::outputXBallsData(dataFile.getFstream());
1393  //exit(-1);
1394 
1395  //This creates the file statistics will be saved to
1396  //getStatFile.open(std::fstream::out);
1397 
1398  initialiseStatistics();
1399 
1400  //std::couts collision time
1401  if (verbosity > 1)
1402  {
1403  //getLargestParticle()->computeMass(getSpecies()); //This should already have been done in read_next_from_p3p_file();
1404  Mdouble mass = particleHandler.getLargestParticle()->getMass();
1405  auto species = dynamic_cast<LinearViscoelasticSpecies*>(speciesHandler.getObject(0));
1406  if (species!= nullptr)
1407  {
1408  std::cout << "Collision Time " << species->getCollisionTime(mass)
1409  << " and restitution coefficient " << species->getRestitutionCoefficient(mass)
1410  << " for mass " << mass << std::endl
1411  << std::endl;
1412  }
1413  //std::couts particles
1414  }
1415  if (verbosity > 2)
1416  {
1417  DPMBase::write(std::cout, true);
1418  std::cout << std::endl;
1419  }
1420  else if (verbosity)
1421  {
1422  DPMBase::write(std::cout,false);
1423  std::cout << std::endl;
1424  }
1425 
1426  //Output statistics for each time step
1427  std::cout << "Start statistics" << std::endl;
1428  do
1429  {
1430  if (getTime() > getTimeMaxStat())
1431  {
1432  std::cout << "reached end t=" << std::setprecision(9) << getTime() << " tmaxStat=" << std::setprecision(9) << getTimeMaxStat() << std::endl;
1433  break;
1434  }
1435  else if (getTime() >= getCGTimeMin())
1436  {
1437  if (verbosity)
1438  std::cout << "Get statistics for t=" << std::setprecision(9) << getTime() << std::endl;
1439  if (verbosity > 1)
1440  std::cout << "#particles=" << particleHandler.getNumberOfObjects() << std::endl;
1441 
1442  if (!walls)
1443  wallHandler.clear();
1445  if (!periodicWalls)
1446  boundaryHandler.clear();
1447 
1448  outputStatistics();
1449  gather_force_statistics_from_p3c(version);
1450  processStatistics(true);
1451 
1452  }
1453  else
1454  {
1455  if (verbosity > 1)
1456  std::cout
1457  << "Jumping statistics t=" << getTime()
1458  << " tminStat()=" << getCGTimeMin() << std::endl;
1459  jump_p3c();
1460  }
1461  //if step size>1, skip a number of steps.
1462  for (unsigned int i = 1; i < getStepSize(); i++)
1463  {
1464  //you only get here if you change the step size and you use a single data file
1465  read_next_from_p3p_file();
1466  jump_p3c();
1467  }
1468  } while (read_next_from_p3p_file());
1469  //set tmax to largest time evaluated
1470  if (getTime() < getTimeMaxStat())
1471  setTimeMaxStat(getTime());
1472 
1473  finishStatistics();
1474  p3p_file.close();
1475  p3c_file.close();
1476  p3w_file.close();
1477 }
1478 
1480 template<StatType T>
1482 {
1483  std::string dummyStr;
1484  Mdouble N, dummy;
1485 
1486  //Ignoring first line
1487  getline(p3c_file, dummyStr);
1488  std::cout << dummyStr << std::endl;
1489  //Reading second line
1490  p3c_file >> dummy;
1491  setTime(dummy);
1492  p3c_file >> N;
1493  std::cout << "ignoring t= " << getTime() << ": loading " << N << " contacts ..." << std::endl;
1494  getline(p3c_file, dummyStr);
1495  //Ignoring third line
1496  getline(p3c_file, dummyStr);
1497  std::cout << dummyStr << std::endl;
1498  //go through N lines in the p3c file
1499  for (int i = 0; i < N; i++)
1500  getline(p3c_file, dummyStr);
1501 
1502  //Ignoring first line
1503  getline(p3w_file, dummyStr);
1504  if (verbosity>2)
1505  std::cout << dummyStr << std::endl;
1506  //Reading second line
1507  p3w_file >> dummy;
1508  setTime(dummy);
1509  p3w_file >> N;
1510  std::cout << "ignoring t= " << getTime() << ": loading " << N << " wall contacts ..." << std::endl;
1511  getline(p3w_file, dummyStr);
1512  //Ignoring third line
1513  getline(p3w_file, dummyStr);
1514  //go through N lines in the p3w file
1515  for (int i = 0; i < N; i++)
1516  getline(p3w_file, dummyStr);
1517 
1518 }
1519 
1521 template<StatType T>
1523 {
1524  std::string dummyStr;
1525  Mdouble N, dummy;
1526 
1527  //Ignoring first line
1528  getline(p3c_file, dummyStr);
1529  if (verbosity>2)
1530  std::cout << dummyStr << std::endl;
1531  //Reading second line
1532  p3c_file >> dummy;
1533  setTime(dummy);
1534  p3c_file >> N;
1535  std::cout << "t= " << getTime() << ": loading " << N << " contacts ..." << std::endl;
1536  getline(p3c_file, dummyStr);
1537  //Ignoring third line
1538  getline(p3c_file, dummyStr);
1539  if (verbosity>2)
1540  std::cout << dummyStr << std::endl;
1541  //Checking for end of file
1542  //if (p3c_file.eof()||p3c_file.peek()==-1) return false;
1543 
1544  //set up index list
1545  unsigned int Nmax = 0;
1546  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it != particleHandler.end(); ++it)
1547  Nmax = std::max(Nmax, (*it)->getIndex());
1548  static std::vector<int> index;
1549  index.resize(Nmax+1);
1550  {
1551  int i = 0;
1552  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it != particleHandler.end(); ++it)
1553  {
1554  index[(*it)->getIndex()] = i;
1555  i++;
1556  }
1557  }
1558 
1559  // ==> Particledata_4.2to4.25s.csv.p4c <==
1560  // TIMESTEP CONTACTS
1561  // 4.2001 31367
1562  // P1 P2 CX CY CZ FX FY FZ
1563  // 9711 9424 0.0549396 0.009705380.149582 4.37283e-05 2.02347e-05 -0.000250662
1564 
1565  // ==> /Users/weinhartt/CarlosLabra/ConfinedCompression_P3P_Spheres.csv.p3c <==
1566  // TIMESTEP CONTACTS
1567  // 6.500010000000e-01 21886
1568  // P1 P2 FX FY FZ
1569  // 1126 218 -1.899612000000e-02 6.716474700000e-02 -1.527340000000e-02
1570 
1571  int index1_p3, index2_p3;
1572  int index1, index2;
1573  Vec3D Contact, Force;
1574  Mdouble delta, fdotn, fdott;
1575  Vec3D P1_P2_normal, P1_P2_tangential;
1576  Mdouble dist;
1577  BaseParticle* P1;
1578  BaseParticle* P2;
1579 
1580  Vec3D contact;
1581  int counter = 0;
1582  //go through N lines in the p4c file
1583  for (int i = 0; i < N; i++)
1584  {
1585  counter++;
1586  if (version == 3)
1587  {
1588  p3c_file
1589  >> index1_p3
1590  >> index2_p3
1591  >> Force;
1592  }
1593  else //p4p
1594  {
1595  p3c_file
1596  >> index1_p3
1597  >> index2_p3
1598  >> Contact
1599  >> Force;
1600  }
1601  index1 = index[index1_p3];
1602  index2 = index[index2_p3];
1603  P1 = particleHandler.getObject(index1);
1604  P2 = particleHandler.getObject(index2);
1605  P1_P2_normal = P1->getPosition() - P2->getPosition();
1606  // deal with periodic boundaries; correct if the distance between two particles is bigger than half the domain size
1607  // (only works if periodic walls are >2d apart)
1609  std::cout << "#forces=" << std::setprecision(9) << P1_P2_normal.Y << "|" << getYMax()-getYMin() << std::endl;
1610  if (2.0*P1_P2_normal.X > getXMax()-getXMin())
1611  P1_P2_normal.X -= getXMax()-getXMin();
1612  else if (2.0*P1_P2_normal.X < getXMin()-getXMax())
1613  P1_P2_normal.X += getXMax()-getXMin();
1614 
1615  else if (2.0*P1_P2_normal.Y > getYMax()-getYMin())
1616  P1_P2_normal.Y -= getYMax()-getYMin();
1617  else if (2.0*P1_P2_normal.Y < getYMin()-getYMax())
1618  P1_P2_normal.Y += getYMax()-getYMin();
1619 
1620  else if (2.0*P1_P2_normal.Z > getZMax()-getZMin())
1621  P1_P2_normal.Z -= getZMax()-getZMin();
1622  else if (2.0*P1_P2_normal.Z < getZMin()-getZMax())
1623  P1_P2_normal.Z += getZMax()-getZMin();
1624  std::cout << "#forces=" << std::setprecision(9) << P1_P2_normal.Y << "|" << getYMax()-getYMin() << std::endl;
1625 
1626  dist = Vec3D::getLength(P1_P2_normal);
1627  P1_P2_normal /= dist;
1628  delta = P1->getRadius() + P2->getRadius() - dist;
1629  if (version == 3)
1630  {
1631  Contact = P2->getPosition() + P1_P2_normal * (P2->getRadius() - delta / 2);
1632  }
1633  fdotn = -Vec3D::dot(Force, P1_P2_normal) / Vec3D::getLengthSquared(P1_P2_normal);
1634  P1_P2_tangential = Force + fdotn * P1_P2_normal; //get tangential force
1635  fdott = Vec3D::getLength(P1_P2_tangential);
1636  if (fdott == 0)
1637  {
1638  P1_P2_tangential = Vec3D(0, 0, 0);
1639  }
1640  else
1641  {
1642  P1_P2_tangential /= fdott;
1643  }
1644  //Finished reading file
1645  std::cout << "#forces=" << P1_P2_normal << "|" << fdotn << std::endl;
1646  gatherContactStatistics(index1, index2, Contact, delta, 0, fdotn, fdott, P1_P2_normal, -P1_P2_tangential);
1647  gatherContactStatistics(index2, index1, Contact, delta, 0, fdotn, fdott, -P1_P2_normal, P1_P2_tangential);
1648  }
1649 
1650  if (verbosity > 1)
1651  std::cout << "#forces=" << counter << std::endl;
1652  //Ignoring last line
1653  getline(p3c_file, dummyStr);
1654  if (verbosity>2)
1655  std::cout << dummyStr << std::endl;
1656 
1657  gather_force_statistics_from_p3w(version, index);
1658 }
1659 
1661 template<StatType T>
1662 void StatisticsVector<T>::gather_force_statistics_from_p3w(int version, std::vector<int>& index)
1663 {
1664  std::string dummyStr;
1665  Mdouble N, dummy;
1666 
1667  //Ignoring first line
1668  getline(p3w_file, dummyStr);
1669  if (verbosity>2)
1670  std::cout << dummyStr << std::endl;
1671  //Reading second line
1672  p3w_file >> dummy;
1673  setTime(dummy);
1674  p3w_file >> N;
1675  std::cout << "t= " << getTime() << ": loading " << N << " wall contacts ..." << std::endl;
1676  getline(p3w_file, dummyStr);
1677  //Ignoring third line
1678  getline(p3w_file, dummyStr);
1679  if (verbosity>2)
1680  std::cout << dummyStr << std::endl;
1681 
1682  // ==> /Users/weinhartt/CarlosLabra/ConfinedCompression_P3P_Spheres.csv.p3w <==
1683  // TIMESTEP CONTACTS
1684  // 6.500010000000e-01 3778
1685  // P1 FX FY FZ NX NY NZ (N=Branch)
1686  // 671 0.000000000000e+00 0.000000000000e+00 1.965970000000e-01 0.000000000000e+00 0.000000000000e+00 -1.991510000000e-03
1687  // ==> Particledata_4.2to4.25s.csv.p4w <==
1688  // TIMESTEP CONTACTS
1689  // 4.2001 5770
1690  // P1 CX CY CZ FX FY FZ
1691  // 10590 0.00944221 0.0120.130307 -3.14611e-06 -0.000512936 0.000102539
1692  // 10146 0.0615829 00.162907 2.02968e-05 0.000948522 0.000188616
1693 
1694  int index1_p3;
1695  int index1, index2;
1696  Vec3D Contact, Force, Branch;
1697  Mdouble delta, fdotn, fdott;
1698  Vec3D P1_P2_normal, P1_P2_tangential;
1699  Mdouble dist;
1700  BaseParticle* P1;
1701 
1702  Vec3D contact;
1703  int counter = 0;
1704  //go through each line in the fstat file; break when eof or '#' or newline
1705  for (int i = 0; i < N; i++)
1706  {
1707  counter++;
1708  if (version == 3)
1709  {
1710  p3w_file
1711  >> index1_p3
1712  >> Force
1713  >> Branch;
1714  }
1715  else
1716  {
1717  p3w_file
1718  >> index1_p3
1719  >> Contact
1720  >> Force;
1721  }
1722  index1 = index[index1_p3];
1723  index2 = -1;
1724  P1 = particleHandler.getObject(index1);
1725  if (version == 3)
1726  {
1727  //Branch *= -1;
1728  Contact = P1->getPosition() + Branch;
1729  }
1730  else
1731  {
1732  Branch = Contact - P1->getPosition();
1733  }
1734  dist = Vec3D::getLength(Branch);
1735  P1_P2_normal = Branch / dist;
1736  delta = P1->getRadius() - dist; //check
1737  fdotn = -Vec3D::dot(Force, P1_P2_normal) / Vec3D::getLengthSquared(P1_P2_normal);
1738  P1_P2_tangential = Force + fdotn * P1_P2_normal; //get tangential force
1739  fdott = Vec3D::getLength(P1_P2_tangential);
1740  if (fdott == 0)
1741  {
1742  P1_P2_tangential = Vec3D(0, 0, 0);
1743  }
1744  else
1745  {
1746  P1_P2_tangential /= fdott;
1747  }
1748  //Finished reading fstat file
1749  gatherContactStatistics(index1, index2, Contact, delta, 0, fdotn, fdott, P1_P2_normal, -P1_P2_tangential);
1750  }
1751 
1752  if (verbosity > 1)
1753  std::cout << "#wall forces=" << counter << std::endl;
1754  //Ignoring last line
1755  getline(p3w_file, dummyStr);
1756  if (verbosity>2)
1757  std::cout << dummyStr << std::endl;
1758 }
1759 
1760 
1762 template<StatType T>
1764 {
1765  std::cout << "set " << " positions" << std::endl;
1766  int N = positions_.size();
1767  if (N!=0)
1768  {
1769  std::cout << "setting " << N << " positions" << std::endl;
1770  Points.resize(N);
1771  for (int i = 0; i<N; i++) {
1772  Points[i].setPosition(positions_[i]);
1773  }
1774  nx = N; ny=1; nz=1;
1775  }
1776  else //set automatically on mesh
1777  {
1778  //Dimensions of the domain / n
1779  Vec3D diff = Vec3D(
1780  (getXMaxStat() - getXMinStat()) / nx,
1781  (getYMaxStat() - getYMinStat()) / ny,
1782  (getZMaxStat() - getZMinStat()) / nz);
1783  //Center of the domain
1784  Vec3D avg = 0.5 * Vec3D(
1785  getXMaxStat() + getXMinStat(),
1786  getYMaxStat() + getYMinStat(),
1787  getZMaxStat() + getZMinStat());
1788  //Left endpoint of the domain
1789  Vec3D Min = Vec3D(
1790  getXMinStat(),
1791  getYMinStat(),
1792  getZMinStat());
1793 
1794  int num[3] = {0, 0, 0};
1795  if (getMirrorAtDomainBoundary() != 0.0)
1796  {
1797  if (statType == X || statType == XY || statType == XZ || statType == XYZ)
1798  {
1799  //add so many points to domain on both ends
1800  //todo: the 8 is arbitrary
1801  num[0] = static_cast<int>(std::floor(std::max(getMirrorAtDomainBoundary(), getCutoff()) / diff.X));
1802  nx += 2 * num[0];
1803  Min.X -= num[0] * diff.X;
1804  }
1805  if (statType == Y || statType == XY || statType == YZ || statType == XYZ)
1806  {
1807  num[1] = static_cast<int>(std::floor(std::max(getMirrorAtDomainBoundary(), getCutoff()) / diff.Y));
1808  ny += 2 * num[1];
1809  Min.Y -= num[1] * diff.Y;
1810  }
1811  if (statType == Z || statType == XZ || statType == XZ || statType == XYZ)
1812  {
1813  num[2] = static_cast<int>(std::floor(std::max(getMirrorAtDomainBoundary(), getCutoff()) / diff.Z));
1814  nz += 2 * num[2];
1815  Min.Z -= num[2] * diff.Z;
1816  }
1817  }
1818 
1819  //Set position of statistics points and set variables to 0
1820  N = std::max(nx, 1) * std::max(ny, 1) * std::max(nz, 1);
1821  Points.resize(N);
1822  {
1823  int n = 0;
1824  for (int i = 0; i < std::max(nx, 1); i++)
1825  for (int j = 0; j < std::max(ny, 1); j++)
1826  for (int k = 0; k < std::max(nz, 1); k++)
1827  {
1828  Points[n].setPosition(Vec3D((nx > 1) ? (Min.X + diff.X * (i + 0.5)) : avg.X,
1829  (ny > 1) ? (Min.Y + diff.Y * (j + 0.5)) : avg.Y,
1830  (nz > 1) ? (Min.Z + diff.Z * (k + 0.5)) : avg.Z));
1831  if (doDoublePoints)
1832  Points[n].setPosition(Points[n].getPosition()
1833  - Vec3D((i % 2) ? (0.99 * diff.X) : 0, (j % 2) ? (0.99 * diff.Y) : 0, (k % 2) ? (0.99 * diff.Z) : 0));
1834  if (getMirrorAtDomainBoundary() != 0.0) if ((i < num[0]) || (i > nx - num[0]) || (j < num[1]) || (j > ny - num[1]) || (k < num[2]) || (k > nz - num[2]))
1835  {
1836  Points[n].mirrorParticle = n +
1837  +((i < num[0]) ? (2 * (num[0] - i) - 1) * ny * nz : 0) + ((i > nx - num[0]) ? (2 * (nx - num[0] - i) + 1) * ny * nz : 0)
1838  + ((j < num[1]) ? (2 * (num[1] - j) - 1) * nz : 0) + ((j > ny - num[1]) ? (2 * (ny - num[1] - j) + 1) * nz : 0)
1839  + ((k < num[2]) ? (2 * (num[2] - k) - 1) : 0) + ((k > nz - num[2]) ? (2 * (nz - num[2] - k) + 1) : 0);
1840  }
1841  n++;
1842  }
1843  }
1844  if (statType == RAZ || statType == RZ || statType == RA || statType == AZ || statType == R || statType == A)
1845  {
1846  for (unsigned int k = 0; k < Points.size(); k++)
1847  {
1848  Points[k].setPosition(Points[k].getPosition().getFromCylindricalCoordinates());
1849  }
1850  }
1851  }
1852  for (int i = 0; i<N; i++)
1853  {
1854  Points[i].setCGInverseVolume();
1855  Points[i].set_zero();
1856  }
1857  if (getDoGradient())
1858  {
1859  dx.resize(N);
1860  dy.resize(N);
1861  dz.resize(N);
1862  for (int n = 0; n < N; n++)
1863  {
1864  dx[n].setPosition(Points[n].getPosition());
1865  dx[n].mirrorParticle = Points[n].mirrorParticle;
1866  dx[n].set_zero();
1867  dy[n].setPosition(Points[n].getPosition());
1868  dy[n].mirrorParticle = Points[n].mirrorParticle;
1869  dy[n].set_zero();
1870  dz[n].setPosition(Points[n].getPosition());
1871  dz[n].mirrorParticle = Points[n].mirrorParticle;
1872  dz[n].set_zero();
1873  }
1874  }
1875 
1876  //Set TimeAverage the same way
1877  if (getDoTimeAverage())
1878  {
1879  timeAverage.resize(N);
1880  {
1881  int n = 0;
1882  for (int i = 0; i < std::max(nx, 1); i++)
1883  for (int j = 0; j < std::max(ny, 1); j++)
1884  for (int k = 0; k < std::max(nz, 1); k++)
1885  {
1886  timeAverage[n].setPosition(Points[n].getPosition());
1887  timeAverage[n].set_zero();
1888  timeAverage[n].mirrorParticle = Points[n].mirrorParticle;
1889  n++;
1890  }
1891  }
1892 
1893  if (getDoVariance())
1894  {
1895  timeVariance.resize(N);
1896  for (int n = 0; n < N; n++)
1897  {
1898  timeVariance[n].setPosition(timeAverage[n].getPosition());
1899  timeVariance[n].mirrorParticle = Points[n].mirrorParticle;
1900  timeVariance[n].set_zero();
1901  }
1902  }
1903 
1904  if (getDoGradient())
1905  {
1906  dxTimeAverage.resize(N);
1907  dyTimeAverage.resize(N);
1908  dzTimeAverage.resize(N);
1909  for (int n = 0; n < N; n++)
1910  {
1911  dxTimeAverage[n].setPosition(timeAverage[n].getPosition());
1912  dxTimeAverage[n].mirrorParticle = Points[n].mirrorParticle;
1913  dxTimeAverage[n].set_zero();
1914  dyTimeAverage[n].setPosition(timeAverage[n].getPosition());
1915  dyTimeAverage[n].mirrorParticle = Points[n].mirrorParticle;
1916  dyTimeAverage[n].set_zero();
1917  dzTimeAverage[n].setPosition(timeAverage[n].getPosition());
1918  dzTimeAverage[n].mirrorParticle = Points[n].mirrorParticle;
1919  dzTimeAverage[n].set_zero();
1920  }
1921  }
1922 
1923  } //end if (getDoTimeAverage())
1924 }
1925 
1926 template<StatType T>
1927 bool StatisticsVector<T>::loadPositions(const char* filename)
1928 {
1929  //This opens the file the data will be recalled from
1930  std::fstream is;
1931  is.open(filename, std::fstream::in);
1932  if (!is.is_open() || is.bad())
1933  {
1934  std::cout << "Loading positions file " << filename << " failed" << std::endl;
1935  return false;
1936  }
1937 
1938  double N=0;
1939  is >> N;
1940  positions_.resize(N);
1941  for (int i=0; i<N; i++)
1942  {
1943  is >> positions_[i];
1944  }
1945  //Close the file
1946  is.close();
1947  std::cout << "Loaded " << positions_.size() << " positions from file " << filename << std::endl;
1948  return true;
1949 }
1950 
1952 template<StatType T>
1954 {
1955  if (fStatFile.getFileType() == FileType::MULTIPLE_FILES || fStatFile.getFileType() == FileType::MULTIPLE_FILES_PADDED)
1956  {
1957  fStatFile.openNextFile();
1958  if (verbosity > 1)
1959  std::cout << "Using fstat file counter: " << fStatFile.getCounter() << std::endl;
1961  }
1962  else
1963  {
1964  //read in first three lines (should start with '#')
1965  std::string dummy;
1966  getline(fStatFile.getFstream(), dummy);
1967  getline(fStatFile.getFstream(), dummy);
1968  getline(fStatFile.getFstream(), dummy);
1969  //read in all lines belonging to this timestep
1970  while ((fStatFile.getFstream().peek() != -1) && (fStatFile.getFstream().peek() != '#'))
1971  getline(fStatFile.getFstream(), dummy);
1972  }
1973 }
1974 
1975 template<StatType T>
1977 {
1978  return P->getRadius() > rmin
1979  && P->getRadius() < rmax
1980  && P->getPosition().Z < hmax
1981  && (indSpecies<0 || P->getIndSpecies() == indSpecies);
1982 }
1983 
1984 template<StatType T>
1985 void StatisticsVector<T>::gatherContactStatistics(unsigned int index1, int index2, Vec3D Contact, Mdouble delta, Mdouble ctheta UNUSED, Mdouble fdotn, Mdouble fdott, Vec3D P1_P2_normal_, Vec3D P1_P2_tangential)
1986 {
1987  Vec3D P1_P2_VelocityAverage, P1_P2_VelocityDifference, P1_P2_Force;
1988  Mdouble norm_dist;
1989  if (check_current_time_for_statistics())
1990  {
1991  //make sure that for a particle-fixed particle collision the fixed particle is on index2 (switch particles if needed)
1992  if (particleHandler.getObject(index1)->isFixed())
1993  {
1994  int tmp = index1;
1995  index1 = index2;
1996  index2 = tmp;
1997  P1_P2_normal_ *= -1;
1998  }
1999 
2000  if (satisfiesInclusionCriteria(particleHandler.getObject(index1)))
2001  {
2002  P1_P2_normal = P1_P2_normal_;
2003 
2004  if (getSystemDimensions() == 2)
2005  Contact.Z = 0.0;
2006 
2007  if (index2 < 0)
2008  { //wall-particle collision
2009  P1_P2_distance = particleHandler.getObject(index1)->getRadius() - delta;
2010  P2 = Contact;
2011  P1 = Contact - P1_P2_normal * P1_P2_distance; //note, here we use a minus
2012  norm_dist = P1_P2_distance;
2013  P1_P2_VelocityAverage = (particleHandler.getObject(index1)->getVelocity()) / 2;
2014  P1_P2_VelocityDifference = (particleHandler.getObject(index1)->getVelocity());
2015 
2016  if (StressTypeForFixedParticles == 3)
2017  {
2019  P1_P2_distance += 300;
2021  P2 += 300 * P1_P2_normal;
2022  //this is because wall-particle collisions appear only once in fstat
2023  norm_dist = P1_P2_distance;
2024  }
2025  }
2026  else if (particleHandler.getObject(index2)->isFixed() || !satisfiesInclusionCriteria(particleHandler.getObject(index2)))
2027  { //particle-fixed particle collision (external force acts at contact point)
2028  if (particleHandler.getObject(index2)->isFixed() && StressTypeForFixedParticles == 3)
2029  {
2030  //infinite extension of stress
2031  P1_P2_distance = particleHandler.getObject(index1)->getRadius() + particleHandler.getObject(index2)->getRadius() - delta;
2032  P1 = Contact + P1_P2_normal * (0.5 * P1_P2_distance); //flowing particle
2033  P2 = Contact - P1_P2_normal * (0.5 * P1_P2_distance); //fixed particle
2034  if (P1_P2_normal.Z < 0)
2035  { //in this case revert flowing and fixed particle
2036  //std::cerr << "Warning: Force normal upwards on base z=" << P1.Z << "." << P2.Z << std::endl;
2037  //turning force the other way to achieve sigma=0 at z=inf
2038  P1_P2_normal *= -1.0;
2039  fdotn *= -1.0;
2040  }
2042  P1_P2_distance = setInfinitelyLongDistance();
2044  P2 = P1 - P1_P2_normal * P1_P2_distance; //move endpoint of force line downwards beyond fixed particles out of the domain
2045  if (P1_P2_normal.Z < 0)
2046  std::cout << P1_P2_distance << " z" << P1.Z << " " << P2.Z << " f" << fdotn << std::endl;
2048  }
2049  else if (StressTypeForFixedParticles == 1 || (!particleHandler.getObject(index2)->isFixed() && StressTypeForFixedParticles == 3))
2050  {
2051  //add force from flowing particle to contact point to stress
2052  P1_P2_distance = particleHandler.getObject(index1)->getRadius() + particleHandler.getObject(index2)->getRadius() - delta;
2053  P1 = Contact + P1_P2_normal * (0.5 * P1_P2_distance); //1st particle
2054  //P2 = Contact; //Contact point;
2055  //P1_P2_distance /= 2.0;
2056  P1_P2_distance = particleHandler.getObject(index1)->getRadius() - delta / 2; //Contact point;
2057  P2 = P1 - P1_P2_normal * P1_P2_distance; //Contact point (corrected for polydispersed particles);
2058  }
2059  else
2060  {
2061  //add force from flowing particle to fixed particle to stress
2062  P1_P2_distance = particleHandler.getObject(index1)->getRadius() + particleHandler.getObject(index2)->getRadius() - delta;
2063  P1 = Contact + P1_P2_normal * (0.5 * P1_P2_distance);
2064  P2 = Contact - P1_P2_normal * (0.5 * P1_P2_distance);
2065  }
2067  norm_dist = P1_P2_distance; //*2.0*Particles[index1].Radius/(Particles[index2].Radius+Particles[index1].Radius);
2068  //This is the length of the contact in particle 1.
2069  P1_P2_VelocityAverage = particleHandler.getObject(index2)->getVelocity() / 2;
2070  P1_P2_VelocityDifference = -particleHandler.getObject(index2)->getVelocity();
2071  }
2072  else
2073  { //particle-particle collision
2074 
2075  if (particleHandler.getObject(index2)->isFixed())
2076  std::cout << "ERROR" << std::endl;
2077  P1_P2_distance = particleHandler.getObject(index1)->getRadius() + particleHandler.getObject(index2)->getRadius() - delta;
2078 
2079  P1 = Contact + P1_P2_normal * (0.5 * P1_P2_distance);
2080  P2 = Contact - P1_P2_normal * (0.5 * P1_P2_distance);
2081  //This is the length of the contact in particle 1.
2082  norm_dist = P1_P2_distance * particleHandler.getObject(index1)->getRadius() / (particleHandler.getObject(index2)->getRadius() + particleHandler.getObject(index1)->getRadius());
2083  P1_P2_VelocityAverage = (particleHandler.getObject(index1)->getVelocity() + particleHandler.getObject(index2)->getVelocity()) / 2;
2084  P1_P2_VelocityDifference = (particleHandler.getObject(index1)->getVelocity() - particleHandler.getObject(index2)->getVelocity());
2085  }
2087  //Particles[max(index1,index2)] is chosen so that it is the non-wall, non-fixed particle
2089  P1_P2_Fabric = MatrixSymmetric3D::selfDyadic(P1_P2_normal) * particleHandler.getObject(index1)->getVolume();
2090  //fix
2091  //~ P1_P2_Fabric = SymmetrizedDyadic(P1_P2_normal, P1_P2_normal) * particleHandler.getObject(max(index1,index2))->getVolume(speciesHandler.getObject());
2093  P1_P2_NormalStress = Matrix3D::dyadic(P1_P2_normal, P1_P2_normal) * (fdotn * norm_dist);
2094  P1_P2_TangentialStress = Matrix3D::dyadic(P1_P2_tangential, P1_P2_normal) * (fdott * norm_dist);
2095  P1_P2_NormalTraction = P1_P2_normal * fdotn;
2096  P1_P2_TangentialTraction = P1_P2_tangential * fdott;
2097  P1_P2_ContactCoupleStress = Matrix3D::dyadic(P1_P2_NormalTraction + P1_P2_TangentialTraction, -0.5 * P1_P2_normal * norm_dist);
2098  P1_P2_Contact = Contact;
2099  //P1_P2_Potential = (speciesHandler.getObject(0)->getStiffness() * mathsFunc::square(delta) + dynamic_cast<FrictionalSpecies*>(speciesHandler.getObject(0))->getSlidingStiffness() * mathsFunc::square(ctheta)) / 2;
2100  P1_P2_Potential = 0.0;
2101  P1_P2_Force = fdotn * P1_P2_normal + fdott * P1_P2_tangential;
2102  P1_P2_Dissipation = Vec3D::dot(P1_P2_VelocityDifference, P1_P2_Force) / 2;
2103  P1_P2_CollisionalHeatFlux = P1_P2_normal * (P1_P2_distance / 2 * Vec3D::dot(P1_P2_VelocityAverage, fdotn * P1_P2_normal + fdott * P1_P2_tangential)) + P1_P2_Potential * P1_P2_VelocityAverage;
2104  //Now P1_P2 distance and normal are in non-averaged directions - This is the projection of the distance on to the CG directions. Required for the later statistics hence done now, not before.
2105  P1_P2_distance *= sqrt(Points[0].dotNonAveraged(P1_P2_normal, P1_P2_normal));
2106 
2107  //If the normal to the contact and the averaging direction are EXACTLY+- parallel then set the normal to zero. Otherwise you would end up with nan, which is not good.
2109  if (P1_P2_distance > 1e-12)
2110  P1_P2_normal = (P1 - P2) / P1_P2_distance;
2111  else
2112  P1_P2_normal = Vec3D(0.0, 0.0, 0.0);
2113  //P1_P2_normal = (P1-P2)/P1_P2_distance;
2114 
2115  //if 2nd particle is wall, fixed particle or not-included particle
2116  if (index2 < 0 || particleHandler.getObject(index2)->isFixed() || !satisfiesInclusionCriteria(particleHandler.getObject(index2)))
2117  {
2118  // << "/" << P2 << std::endl;
2120  if (StressTypeForFixedParticles != 0)
2121  { //only if wall - flow contact adds anything to the stress
2122  evaluate_force_statistics();
2123  }
2124  if (StressTypeForFixedParticles != 3 || !(index2 < 0 || particleHandler.getObject(index2)->isFixed()))
2125  { //only if stress is not infinitely extended
2126  Vec3D P;
2127  if (StressTypeForFixedParticles == 0)
2128  {
2129  P = P1; //Traction at flow particle
2130  }
2131  else
2132  {
2133  P = P2; //Traction at contact point, resp wall particle
2134  }
2135  evaluate_wall_force_statistics(P);
2136  }
2137  }
2138  else
2139  {
2140  evaluate_force_statistics();
2141  }
2142  }
2143  }
2144 }
2145 
2147 template<StatType T>
2149 {
2150  //read in first three lines (should start with '#')
2151  std::string dummy;
2152  if (fStatFile.getFileType() == FileType::MULTIPLE_FILES || fStatFile.getFileType() == FileType::MULTIPLE_FILES_PADDED)
2153  fStatFile.openNextFile(std::fstream::in);
2154  getline(fStatFile.getFstream(), dummy);
2155  getline(fStatFile.getFstream(), dummy);
2156  getline(fStatFile.getFstream(), dummy);
2157 
2158  static Mdouble time;
2159  static int index1, index2;
2160  static Vec3D Contact;
2161  static Mdouble delta, ctheta, fdotn, fdott;
2162  static Vec3D P1_P2_normal_, P1_P2_tangential;
2163  static BaseParticle PI;
2164  static BaseParticle PJ;
2165 
2166  int counter = 0;
2167  //go through each line in the fstat file; break when eof or '#' or newline
2168  while ((fStatFile.getFstream().peek() != -1) && (fStatFile.getFstream().peek() != '#'))
2169  { //(!fStatFile.eof())
2170  counter++;
2171  /* # 1: time
2172  # 2: particle Number i
2173  # 3: contact partner j (particles >= 0, walls < 0)
2174  # 4: x-position \
2175  # 5: y-position > of the contact point (I hope)
2176  # 6: z-position /
2177  # 7: delta = overlap at the contact
2178  # 8: ctheta = length of the tangential spring
2179  # 9: P1_P2_normal force |f^n|
2180  # 10: remaining (tangential) force |f^t|=|f-f^n|
2181  # 11-13: P1_P2_normal unit vector nx, ny, nz
2182  # 14-16: tangential unit vector tx, ty, tz
2183  */
2184  fStatFile.getFstream()
2185  >> time
2186  >> index1
2187  >> index2
2188  >> Contact
2189  >> delta
2190  >> ctheta
2191  >> fdotn
2192  >> fdott
2193  >> P1_P2_normal_
2194  >> P1_P2_tangential;
2196  fStatFile.getFstream().ignore(256, '\n');
2197  //Finished reading fstat file
2198  gatherContactStatistics(index1, index2, Contact, delta, ctheta, fdotn, fdott, P1_P2_normal_, P1_P2_tangential);
2199 
2200  }
2201  if (verbosity > 1)
2202  std::cout << "#forces=" << counter << ", t=" << time << std::endl;
2203 }
2204 
2206 template<StatType T>
2208 {
2210  if (periodicWalls)
2211  {
2212  for (unsigned int k = wp; k < boundaryHandler.getNumberOfObjects(); k++)
2213  {
2215  PeriodicBoundary *b0 = dynamic_cast<PeriodicBoundary *>(boundaryHandler.getObject(k));
2216  if (b0)
2217  {
2218  b0->getDistance(P1);
2219  b0->shiftPositions(P1, P2);
2220  evaluate_force_statistics(k + 1);
2221  b0->shiftPositions(P1, P2);
2222  }
2223  AngledPeriodicBoundary* b1 = dynamic_cast<AngledPeriodicBoundary*>(boundaryHandler.getObject(k));
2224  if (b1 != nullptr)
2225  {
2226  b1->distance(P1);
2227  b1->shiftPositions(P1, P2);
2228  evaluate_force_statistics(k + 1);
2229  b1->shiftPositions(P1, P2);
2230  }
2231  }
2232  }
2233 
2235  //evaluate fields that only depend on CParticle parameters
2236  Mdouble psi; //Course graining integral
2237  Vec3D rpsi = Vec3D(0, 0, 0);
2238  static unsigned int counter = 0;
2239  for (unsigned int i = 0; i < Points.size(); i++)
2240  {
2241  psi = Points[i].CG_integral(P1, P2, P1_P2_normal, P1_P2_distance, rpsi);
2242  if (psi != 0.0)
2243  {
2244  counter++;
2245  if (!std::isfinite(psi))
2246  {
2247  std::cerr << "error: psi =" << psi << " is infinite for "
2248  << "P1=" << P1
2249  << ", P2=" << P2
2250  << ", P1_P2_normal=" << P1_P2_normal
2251  << ", P1_P2_distance=" << P1_P2_distance
2252  << ", t=" << getTime() << std::endl;
2253  psi = 0;
2254  }
2255  Points[i].ContactCoupleStress += (Matrix3D::cross(P1_P2_Contact * psi, P1_P2_ContactCoupleStress) - Matrix3D::cross(rpsi, P1_P2_ContactCoupleStress)) * (-0.5);
2256  Points[i].NormalStress += P1_P2_NormalStress * psi;
2257  Points[i].TangentialStress += P1_P2_TangentialStress * psi;
2258  Points[i].Fabric += P1_P2_Fabric * psi;
2259  Points[i].CollisionalHeatFlux += P1_P2_CollisionalHeatFlux * psi;
2260  Points[i].Dissipation += P1_P2_Dissipation * psi;
2261  Points[i].Potential += P1_P2_Potential * psi;
2262  if (getDoGradient())
2263  {
2264  Vec3D d_psi = Points[i].CG_integral_gradient(P1, P2, P1_P2_normal, P1_P2_distance);
2265 
2266  dx[i].NormalStress += P1_P2_NormalStress * d_psi.X;
2267  dx[i].TangentialStress += P1_P2_TangentialStress * d_psi.X;
2268  dx[i].Fabric += P1_P2_Fabric * d_psi.X;
2269  dx[i].CollisionalHeatFlux += P1_P2_CollisionalHeatFlux * d_psi.X;
2270  dx[i].Dissipation += P1_P2_Dissipation * d_psi.X;
2271  dx[i].Potential += P1_P2_Potential * d_psi.X;
2272 
2273  dy[i].NormalStress += P1_P2_NormalStress * d_psi.Y;
2274  dy[i].TangentialStress += P1_P2_TangentialStress * d_psi.Y;
2275  dy[i].Fabric += P1_P2_Fabric * d_psi.Y;
2276  dy[i].CollisionalHeatFlux += P1_P2_CollisionalHeatFlux * d_psi.Y;
2277  dy[i].Dissipation += P1_P2_Dissipation * d_psi.Y;
2278  dy[i].Potential += P1_P2_Potential * d_psi.Y;
2279 
2280  dz[i].NormalStress += P1_P2_NormalStress * d_psi.Z;
2281  dz[i].TangentialStress += P1_P2_TangentialStress * d_psi.Z;
2282  dz[i].Fabric += P1_P2_Fabric * d_psi.Z;
2283  dz[i].CollisionalHeatFlux += P1_P2_CollisionalHeatFlux * d_psi.Z;
2284  dz[i].Dissipation += P1_P2_Dissipation * d_psi.Z;
2285  dz[i].Potential += P1_P2_Potential * d_psi.Z;
2286  } //end if getDoGradient
2287  } //end if phi
2288  } // end forall Points
2289  //std::cout << "NCeval" << counter << std::endl;
2290 }
2291 
2293 template<StatType T>
2295 {
2297  if (periodicWalls)
2298  for (unsigned int k = wp; k < boundaryHandler.getNumberOfObjects(); k++)
2299  {
2300  PeriodicBoundary* b0 = dynamic_cast<PeriodicBoundary*>(boundaryHandler.getObject(k));
2301  if (b0)
2302  {
2303  b0->getDistance(P1);
2304  b0->shiftPositions(P1, P2);
2305  evaluate_force_statistics(k + 1);
2306  b0->shiftPositions(P1, P2);
2307  }
2308  }
2309 
2310  //evaluate fields that only depend on CParticle parameters
2311  Mdouble phi; //Course graining integral
2312  for (unsigned int i = 0; i < Points.size(); i++)
2313  {
2314  phi = Points[i].CG_function(P);
2315  if (phi != 0.0)
2316  {
2317  Points[i].NormalTraction += P1_P2_NormalTraction * phi;
2318  Points[i].TangentialTraction += P1_P2_TangentialTraction * phi;
2319  if (getDoGradient())
2320  {
2322  Vec3D d_phi = Points[i].CG_gradient(P, phi);
2323  dx[i].NormalTraction += P1_P2_NormalTraction * d_phi.X;
2324  dy[i].NormalTraction += P1_P2_NormalTraction * d_phi.Y;
2325  dz[i].NormalTraction += P1_P2_NormalTraction * d_phi.Z;
2326  dx[i].TangentialTraction += P1_P2_TangentialTraction * d_phi.X;
2327  dy[i].TangentialTraction += P1_P2_TangentialTraction * d_phi.Y;
2328  dz[i].TangentialTraction += P1_P2_TangentialTraction * d_phi.Z;
2329  } //end if getDoGradient
2330  } //end if phi
2331  } // end forall Points
2332 
2333 }
2334 
2335 template<StatType T>
2337 {
2338  if (check_current_time_for_statistics())
2339  {
2341  for (unsigned int i = 0; i < Points.size(); i++)
2342  Points[i].setCGInverseVolume();
2343 
2344  for (std::vector<BaseParticle*>::iterator P = particleHandler.begin(); P != particleHandler.end(); ++P)
2345  {
2347  //unfix particles (turn off to ignore fixed particles)
2348  if ((!ignoreFixedParticles) && (*P)->isFixed())
2349  {
2350  (*P)->unfix();
2351  }
2352  //ignore fixed particles
2353 
2355  if (satisfiesInclusionCriteria(*P) && !(*P)->isFixed())
2356  {
2357  evaluate_particle_statistics(P);
2358  }
2359 
2360  }
2361  }
2362 }
2363 
2364 template<StatType T>
2365 void StatisticsVector<T>::evaluate_particle_statistics(std::vector<BaseParticle*>::iterator P, int wp)
2366 {
2368  bool doDisplacement = false;
2369 
2370  if (periodicWalls)
2371  {
2372  for (unsigned int k = wp; k < boundaryHandler.getNumberOfObjects(); k++)
2373  {
2374  PeriodicBoundary* b = dynamic_cast<PeriodicBoundary*>(boundaryHandler.getObject(k));
2375  if (b != nullptr)
2376  {
2377  Mdouble dist = b->getDistance(P1);
2378  if (mathsFunc::square(dist - (*P)->getInteractionRadius()) < getCutoff2())
2379  {
2380  b->shiftPosition(*P);
2381  evaluate_particle_statistics(P, k + 1);
2382  b->shiftPosition(*P);
2383  }
2384  }
2385  AngledPeriodicBoundary* c = dynamic_cast<AngledPeriodicBoundary*>(boundaryHandler.getObject(k));
2386  if (c != nullptr)
2387  {
2388  Mdouble dist = c->distance(P1);
2389  if (mathsFunc::square(dist - (*P)->getInteractionRadius()) < getCutoff2())
2390  {
2391  c->shiftPosition(*P);
2392  evaluate_particle_statistics(P, k + 1);
2393  c->shiftPosition(*P);
2394  }
2395  }
2396  }
2397  }
2398 
2399  //evaluate fields that only depend on CParticle parameters
2400  Mdouble phi; //Course graining function
2401  Vec3D V = Vec3D(0, 0, 0);
2402  if (VelocityProfile.size())
2403  V = getVelocityProfile((*P)->getPosition());
2404 
2405  for (unsigned int i = 0; i < Points.size(); i++)
2406  {
2407  phi = Points[i].CG_function((*P)->getPosition());
2408  if (phi != 0.0)
2409  {
2410  if (!std::isfinite(phi))
2411  {
2412  std::cout
2413  << "t =" << DPMBase::getTime()
2414  << "error: phi =" << phi
2415  << " is infinite for P=" << (*P)->getPosition()
2416  << ", Point=" << Points[i].getPosition()
2417  << std::endl;
2418  phi = 0;
2419  }
2420  Points[i].Nu += (*P)->getVolume() * phi;
2421  Points[i].Density += (*P)->getMass() * phi;
2422  if (VelocityProfile.size())
2423  {
2424  Points[i].Momentum += ((*P)->getVelocity() - V) * ((*P)->getMass() * phi);
2425  Points[i].MomentumFlux += MatrixSymmetric3D::selfDyadic((*P)->getVelocity() - V) * ((*P)->getMass() * phi);
2426  }
2427  else
2428  {
2429  Points[i].Momentum += (*P)->getVelocity() * ((*P)->getMass() * phi);
2430  Points[i].MomentumFlux += MatrixSymmetric3D::selfDyadic((*P)->getVelocity()) * ((*P)->getMass() * phi);
2431  }
2432  Points[i].DisplacementMomentum += (*P)->getDisplacement2(getXMin(), getXMax(), getYMin(), getYMax(), getZMin(), getZMax(), getTimeStep() * dataFile.getSaveCount()) * ((*P)->getMass() * phi);
2433  Points[i].DisplacementMomentumFlux += MatrixSymmetric3D::selfDyadic((*P)->getDisplacement2(getXMin(), getXMax(), getYMin(), getYMax(), getZMin(), getZMax(), getTimeStep() * dataFile.getSaveCount())) * ((*P)->getMass() * phi);
2434  Points[i].EnergyFlux += (*P)->getVelocity() * ((*P)->getMass() * (*P)->getVelocity().getLengthSquared() / 2 * phi);
2435 
2436  Vec3D LocalAngularMomentum = Vec3D::cross(Points[0].clearAveragedDirections((*P)->getPosition() - Points[i].getPosition()), (*P)->getVelocity()) * (*P)->getMass()
2437  + (*P)->getAngularVelocity() * (*P)->getInertia();
2438  Points[i].LocalAngularMomentum += phi * LocalAngularMomentum;
2439  Points[i].LocalAngularMomentumFlux += Matrix3D::dyadic(LocalAngularMomentum, (*P)->getVelocity() * phi);
2440 
2441  //Note: Displacement is only computed directly if gradients are cmputed
2442  if (getDoGradient())
2443  {
2444 
2445  Vec3D d_phi = Points[i].CG_gradient((*P)->getPosition(), phi);
2446 
2447  if (doDisplacement)
2448  {
2450  for (std::vector<BaseParticle*>::iterator Q = particleHandler.begin(); Q != particleHandler.end(); ++Q)
2451  {
2452  double phiQ = Points[i].CG_function((*Q)->getPosition()); //Course graining function
2453  Points[i].Displacement += MatrixSymmetric3D::symmetrisedDyadic((*P)->getDisplacement2(getXMin(), getXMax(), getYMin(), getYMax(), getZMin(), getZMax(), getTimeStep() * dataFile.getSaveCount()) - (*Q)->getDisplacement2(getXMin(), getXMax(), getYMin(), getYMax(), getZMin(), getZMax(), getTimeStep() * dataFile.getSaveCount()), d_phi) * ((*P)->getMass() * (*Q)->getMass() * phiQ);
2454  }
2455  //end:Displacement
2456  }
2457 
2458  dx[i].Nu += (*P)->getVolume() * d_phi.X;
2459  dx[i].Density += (*P)->getMass() * d_phi.X;
2460  dx[i].Momentum += (*P)->getVelocity() * ((*P)->getMass() * d_phi.X);
2461  dx[i].DisplacementMomentum += (*P)->getDisplacement2(getXMin(), getXMax(), getYMin(), getYMax(), getZMin(), getZMax(), getTimeStep() * dataFile.getSaveCount()) * ((*P)->getMass() * d_phi.X);
2462  dx[i].MomentumFlux += MatrixSymmetric3D::selfDyadic((*P)->getVelocity()) * ((*P)->getMass() * d_phi.X);
2463  dx[i].DisplacementMomentumFlux += MatrixSymmetric3D::selfDyadic((*P)->getDisplacement2(getXMin(), getXMax(), getYMin(), getYMax(), getZMin(), getZMax(), getTimeStep() * dataFile.getSaveCount())) * ((*P)->getMass() * d_phi.X);
2464  dx[i].EnergyFlux += (*P)->getVelocity() * ((*P)->getMass() * (*P)->getVelocity().getLengthSquared() / 2 * d_phi.X);
2465 
2466  dy[i].Nu += (*P)->getVolume() * d_phi.Y;
2467  dy[i].Density += (*P)->getMass() * d_phi.Y;
2468  dy[i].Momentum += (*P)->getVelocity() * ((*P)->getMass() * d_phi.Y);
2469  dy[i].DisplacementMomentum += (*P)->getDisplacement2(getXMin(), getXMax(), getYMin(), getYMax(), getZMin(), getZMax(), getTimeStep() * dataFile.getSaveCount()) * ((*P)->getMass() * d_phi.Y);
2470  dy[i].MomentumFlux += MatrixSymmetric3D::selfDyadic((*P)->getVelocity()) * ((*P)->getMass() * d_phi.Y);
2471  dy[i].DisplacementMomentumFlux += MatrixSymmetric3D::selfDyadic((*P)->getDisplacement2(getXMin(), getXMax(), getYMin(), getYMax(), getZMin(), getZMax(), getTimeStep() * dataFile.getSaveCount())) * ((*P)->getMass() * d_phi.Y);
2472  dy[i].EnergyFlux += (*P)->getVelocity() * ((*P)->getMass() * (*P)->getVelocity().getLengthSquared() / 2 * d_phi.Y);
2473 
2474  dz[i].Nu += (*P)->getVolume() * d_phi.Z;
2475  dz[i].Density += (*P)->getMass() * d_phi.Z;
2476  dz[i].Momentum += (*P)->getVelocity() * ((*P)->getMass() * d_phi.Z);
2477  dz[i].DisplacementMomentum += (*P)->getDisplacement2(getXMin(), getXMax(), getYMin(), getYMax(), getZMin(), getZMax(), getTimeStep() * dataFile.getSaveCount()) * ((*P)->getMass() * d_phi.Z);
2478  dz[i].MomentumFlux += MatrixSymmetric3D::selfDyadic((*P)->getVelocity()) * ((*P)->getMass() * d_phi.Z);
2479  dz[i].DisplacementMomentumFlux += MatrixSymmetric3D::selfDyadic((*P)->getDisplacement2(getXMin(), getXMax(), getYMin(), getYMax(), getZMin(), getZMax(), getTimeStep() * dataFile.getSaveCount())) * ((*P)->getMass() * d_phi.Z);
2480  dz[i].EnergyFlux += (*P)->getVelocity() * ((*P)->getMass() * (*P)->getVelocity().getLengthSquared() / 2 * d_phi.Z);
2481  } //end if getDoGradient
2482  } //end if phi
2483  } // end forall Points
2484 }
2485 
2486 //template class StatisticsPoint<XYZ>;
2487 
2488 //Templated functions
2489 
2490 template<> void StatisticsVector<XY>::setNZ(int new_ UNUSED)
2491 {
2492  nz = 1;
2493 }
2494 template<> void StatisticsVector<XZ>::setNY(int new_ UNUSED)
2495 {
2496  ny = 1;
2497 }
2498 template<> void StatisticsVector<YZ>::setNX(int new_ UNUSED)
2499 {
2500  nx = 1;
2501 }
2502 template<> void StatisticsVector<X>::setNY(int new_ UNUSED)
2503 {
2504  ny = 1;
2505 }
2506 template<> void StatisticsVector<X>::setNZ(int new_ UNUSED)
2507 {
2508  nz = 1;
2509 }
2510 template<> void StatisticsVector<Y>::setNX(int new_ UNUSED)
2511 {
2512  nx = 1;
2513 }
2514 template<> void StatisticsVector<Y>::setNZ(int new_ UNUSED)
2515 {
2516  nz = 1;
2517 }
2518 template<> void StatisticsVector<Z>::setNX(int new_ UNUSED)
2519 {
2520  nx = 1;
2521 }
2522 template<> void StatisticsVector<Z>::setNY(int new_ UNUSED)
2523 {
2524  ny = 1;
2525 }
2526 template<> void StatisticsVector<O>::setNX(int new_ UNUSED)
2527 {
2528  nx = 1;
2529 }
2530 template<> void StatisticsVector<O>::setNY(int new_ UNUSED)
2531 {
2532  ny = 1;
2533 }
2534 template<> void StatisticsVector<O>::setNZ(int new_ UNUSED)
2535 {
2536  nz = 1;
2537 }
2538 
2540 {
2541  statType = RAZ;
2542 }
2544 {
2545  statType = RZ;
2546 }
2548 {
2549  statType = AZ;
2550 }
2552 {
2553  statType = RA;
2554 }
2556 {
2557  statType = A;
2558 }
2560 {
2561  statType = R;
2562 }
2564 {
2565  statType = XYZ;
2566 }
2568 {
2569  statType = XY;
2570 }
2572 {
2573  statType = XZ;
2574 }
2576 {
2577  statType = YZ;
2578 }
2580 {
2581  statType = X;
2582 }
2584 {
2585  statType = Y;
2586 }
2588 {
2589  statType = Z;
2590 }
2592 {
2593  statType = O;
2594 }
2595 
2597 {
2599  return std::min(std::min(fabs((P1.Z - getZMinStat() + 5 * getCGWidth()) / P1_P2_normal.Z),
2600  std::max((getXMaxStat() - P2.X + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X, -(P2.X - getXMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X)),
2601  std::max((getYMaxStat() - P2.Y + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y, -(P2.Y - getYMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y));
2602 }
2604 {
2605  return std::min(std::max((getYMaxStat() - P2.Y + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y, -(P2.Y - getYMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y),
2606  std::max((getXMaxStat() - P2.X + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X, -(P2.X - getXMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X));
2607 }
2609 {
2610  return std::min(fabs((P1.Z - getZMinStat() + 5 * getCGWidth()) / P1_P2_normal.Z),
2611  std::max((getXMaxStat() - P2.X + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X, -(P2.X - getXMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X));
2612 }
2614 {
2615  return std::min(fabs((P1.Z - getZMinStat() + 5 * getCGWidth()) / P1_P2_normal.Z),
2616  std::max((getYMaxStat() - P2.Y + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y, -(P2.Y - getYMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y));
2617 }
2619 {
2620  return std::max((getXMaxStat() - P2.X + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X, -(P2.X - getXMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X);
2621 }
2623 {
2624  return std::max((getYMaxStat() - P2.Y + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y, -(P2.Y - getYMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y);
2625 }
2626 
2628 {
2629  return std::min(std::min(fabs((P1.Z - getZMinStat() + 5 * getCGWidth()) / P1_P2_normal.Z),
2630  std::max((getXMaxStat() - P1.X + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X, -(P1.X - getXMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X)),
2631  std::max((getYMaxStat() - P1.Y + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y, -(P1.Y - getYMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y));
2632 }
2634 {
2635  return std::min(std::max((getYMaxStat() - P1.Y + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y, -(P1.Y - getYMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y),
2636  std::max((getXMaxStat() - P1.X + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X, -(P1.X - getXMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X));
2637 }
2639 {
2640  return std::min(fabs((P1.Z - getZMinStat() + 5 * getCGWidth()) / P1_P2_normal.Z),
2641  std::max((getXMaxStat() - P1.X + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X, -(P1.X - getXMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X));
2642 }
2644 {
2645  return std::min(fabs((P1.Z - getZMinStat() + 5 * getCGWidth()) / P1_P2_normal.Z),
2646  std::max((getYMaxStat() - P1.Y + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y, -(P1.Y - getYMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y));
2647 }
2649 {
2650  return std::max((getXMaxStat() - P1.X + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X, -(P1.X - getXMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.X);
2651 }
2653 {
2654  return std::max((getYMaxStat() - P1.Y + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y, -(P1.Y - getYMinStat() + 5 * sqrt(getCGWidthSquared())) / P1_P2_normal.Y);
2655 }
2657 {
2658  return fabs((P1.Z - getZMinStat() + 5 * getCGWidth()) / P1_P2_normal.Z);
2659 }
2661 {
2662  return 0;
2663 }
2664 
2665 template<StatType T>
2667 {
2668  if (statFile.saveCurrentTimestep(getNtimeSteps()))
2669  {
2670  outputStatistics();
2672  processStatistics(true);
2673  }
2674 
2676 }
StatisticsVector()
Basic constructor only calls constructor()
void readStatArguments(int argc, char *argv[])
bool periodicWalls
Turns off periodic walls before evaluation (needed for averaging, because we do not yet check if part...
StatisticsPoint< T > average(std::vector< StatisticsPoint< T > > &P)
Output average of statistical variables.
void gather_force_statistics_from_fstat_and_data()
get force statistics from particle collisions
std::vector< StatisticsPoint< T > > dyTimeAverage
a vector used to sum up all statistical gradients in dy for time-averaging
virtual void write(std::ostream &os, bool writeAllParticles=true) const
Loads all MD data and plots statistics for all timesteps in the .data file.
Definition: DPMBase.cc:1642
Mdouble getDistance(BaseParticle &p)
Returns the distance of the wall to the particle.
std::string printStat()
Outputs member variable values to a std::string.
The DPMBase header includes quite a few header files, defining all the handlers, which are essential...
Definition: DPMBase.h:61
Mdouble X
the vector components
Definition: Vector.h:52
each time-step will be written into/read from separate files numbered consecutively, with numbers padded by zeros to a minimum of four digits: name_.0000, name_.0001, ..
bool walls
Turns off walls before evaluation.
StatType statType
Possible values X,Y,Z,XY,XZ,YZ,XYZ,RAZ,RA,RZ,AZ,R,A are used to determine if the statistics are avera...
void initialiseStatistics()
Initializes statistics, i.e. setting w2, setting the grid and writing the header lines in the ...
StatType
Creates averaged statistics (only valid if density field is homogenous along averaged direction) ...
void write_time_average_statistics()
Writes out time averaged statistics.
void shiftPositions(Vec3D &P1, Vec3D &P2)
only needed in StatisticsVector
void shiftPosition(BaseParticle *p)
shifts the particle
void processStatistics(bool usethese)
Processes all gathered statistics and resets them afterwards. (Processing means either calculating ti...
bool satisfiesInclusionCriteria(BaseParticle *P)
Mdouble w_over_rmax
if w is not set manually then w will be set by multiplying this value by the largest particle radius ...
Mdouble tmaxStat
Statistical output will only be created if t
std::vector< StatisticsPoint< T > > dz
A vector that stores the gradient in z of all statistical variables at a given position.
Mdouble cutoff
The distance from the origin at which the cg function vanishes; cutoff=w for HeavisideSphere or Polyn...
void gather_force_statistics_from_p3w(int version, std::vector< int > &index)
get force statistics from particle collisions
std::vector< StatisticsPoint< T > > dy
A vector that stores the gradient in y of all statistical variables at a given position.
Mdouble xminStat
By default the domain is set to the domain of the MD problem (indicated by setting the stat-domain va...
void constructor()
this is the actual constructor, sets up all basic things
bool loadPositions(const char *filename)
bool loadVelocityProfile(const char *filename)
Mdouble w2
coarse graining width squared; for HeavisideSphere and Gaussian
Mdouble tintStat
Statistical output will only be created if tmaxStat-tintStat< t< tmaxStat.
void setNX(int new_)
void write_statistics()
Writes regular statistics.
bool readNextDataFile(unsigned int format)
void jump_p3c()
get force statistics from particle collisions
void setCGShape(const char *new_)
std::vector< StatisticsPoint< T > > dx
A vector that stores the gradient in x of all statistical variables at a given position.
static Mdouble dot(const Vec3D &a, const Vec3D &b)
Calculates the dot product of two Vec3D: .
Definition: Vector.cc:187
virtual void writeOutputFiles()
Writes the simulation data onto all the files i.e. .data, .ene, .fstat ...
Definition: DPMBase.cc:1848
void setSystemDimensions(unsigned int newDim)
Allows for the dimension of the simulation to be changed.
Definition: DPMBase.cc:453
void evaluate_wall_force_statistics(Vec3D P, int wp=0)
get force statistics (i.e. first particle is a wall particle)
T square(T val)
squares a number
Definition: ExtendedMath.h:91
int nx
Grid size nx,ny,nz (by default the points of evaluation are placed in an grid on the domain [xminStat...
virtual void outputXBallsData(std::ostream &os) const
This function writes the location of the walls and particles in a format the XBalls program can read...
Definition: DPMBase.cc:947
Mdouble getLengthSquared() const
Calculates the squared length of this Vec3D: .
Definition: Vector.cc:313
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
Defines a pair of periodic walls. Inherits from BaseBoundary.
CG
enum used to store the type of coarse-graining function used
static Matrix3D dyadic(const Vec3D &a, const Vec3D &b)
Calculates the dyadic product of a two Vec3D: .
Definition: Matrix.cc:285
int nTimeAverage
A counter needed to average over time.
void setCGWidth2(Mdouble new_)
Set CG variables w2 and CG_invvolume.
std::vector< StatisticsPoint< T > > dxTimeAverage
a vector used to sum up all statistical gradients in dx for time-averaging
std::ostream & operator<<(std::ostream &os, const StatType S)
std::vector< StatisticsPoint< T > > dzTimeAverage
a vector used to sum up all statistical gradients in dz for time-averaging
void setNZ(int new_)
Mdouble indSpecies
defines the species for which statistics are extracted (-1 for all species)
void evaluate_force_statistics(int wp=0)
get force statistics
void statistics_from_p3()
this is a modified version of statistics_from_fstat_and_data. It is used to read p3d files ...
Mdouble tminStat
Statistical output will only be created if t>tminStat.
Mdouble rmin
defines the minimum radius of the particles for which statistics are extracted
const Mdouble pi
Definition: ExtendedMath.h:42
Vec3D getVelocityProfile(Vec3D Position)
NORMALIZED_POLYNOMIAL< T > CGPolynomial
Stores the Polynomial, if the cg function is an axisymmetric function Polynomial in r...
all data will be written into/ read from a single file called name_
static Matrix3D cross(const Vec3D &a, const Matrix3D &b)
'Special' cross product; CP of vector with each column of a matrix
Definition: Matrix.cc:299
void statistics_from_fstat_and_data()
get StatisticsPoint
void evaluate_particle_statistics(std::vector< BaseParticle * >::iterator P, int wp=0)
Calculates statistics for a single Particle.
#define UNUSED
Definition: GeneralDefine.h:37
virtual void writeXBallsScript() const
This writes a script which can be used to load the xballs problem to display the data just generated...
Mdouble distance(const BaseParticle &P)
Returns the distance of the wall to the particle and sets left_wall = true, if the left wall is the w...
int format
format of the data input file
bool doTimeAverage
Determines if output is averaged over time.
void setNY(int new_)
static Vec3D cross(const Vec3D &a, const Vec3D &b)
Calculates the cross product of two Vec3D: .
Definition: Vector.cc:268
Mdouble getRadius() const
Returns the particle's radius_.
bool readNextDataFile(unsigned int format=0)
Reads the next data file with default format=0. However, one can modify the format based on whether t...
Definition: DPMBase.cc:1224
std::vector< StatisticsPoint< T > > timeVariance
a vector used to sum up the variance in time of all statistical values
Species< LinearViscoelasticNormalSpecies > LinearViscoelasticSpecies
Mdouble mirrorAtDomainBoundary
0: Statistics near the wall are equal to statistics away from the wall; 1: Statistics are mirrored at...
bool doVariance
Determines if variance is outputted.
Mdouble Y
Definition: Vector.h:52
static MatrixSymmetric3D symmetrisedDyadic(const Vec3D &a, const Vec3D &b)
Calculates the symmetrised dyadic product of two Vec3D: .
std::vector< StatisticsPoint< T > > Points
A vector that stores the values of the statistical variables at a given position. ...
static MatrixSymmetric3D selfDyadic(const Vec3D &a)
Calculates the dyadic product of a Vec3D with itself: .
void shiftPositions(Vec3D &postition1, Vec3D &postion2)
shifts two positions
Mdouble getLength() const
Calculates the length of this Vec3D: .
Definition: Vector.cc:416
int verbosity
Determines how much is outputted to the terminal.
void outputStatistics()
Calculates statistics for Particles (i.e. not collisions)
CG CG_type
coarse graining type (Gaussian, Heaviside, Polynomial)
void gatherContactStatistics()
Definition: DPMBase.cc:687
Mdouble hmax
defines the maximum height of the particles for which statistics are extracted
This class is used to extract statistical data from MD simulations.
virtual void writeRestartFile()
Stores all the particle data for current save time step. Calls the write function.
Definition: DPMBase.cc:1365
void writeOutputFiles()
Writes the simulation data onto all the files i.e. .data, .ene, .fstat ...
std::vector< StatisticsPoint< T > > timeAverage
A vector used to sum up all statistical values in Points for time-averaging.
each time-step will be written into/read from separate files numbered consecutively: name_...
Contains material and contact force properties.
Definition: Interaction.h:35
Mdouble setInfinitelyLongDistance()
bool superexact
If true, cutoff radius for Gaussian is set to 5*w (from 3*w)
virtual void reset_statistics()
Set all statistical variables to zero.
unsigned int getIndSpecies() const
Returns the index of the Species of this BaseInteractable.
void finishStatistics()
Finish all statistics (i.e. write out final data)
bool ignoreFixedParticles
Determines if fixed particles contribute to particle statistics (density, ...)
void setPositions()
Set position of StatisticsPoint points and set variables to 0.
static void set_gb(StatisticsVector< T > *new_gb)
see StatisticsVector::setCGShape
Implementation of a 3D vector (by Vitaliy).
Definition: Vector.h:45
bool openFile(std::fstream &file, std::string filename, std::fstream::openmode mode)
Provides a simple interface for opening a file.
Definition: Helpers.cc:466
int StressTypeForFixedParticles
Stress type for fixed particles.
void shiftPosition(BaseParticle *P)
shifts the particle (after distance set the left_wall value)
Mdouble Z
Definition: Vector.h:52
Mdouble rmax
defines the maximum radius of the particles for which statistics are extracted
Mdouble getTime() const
Access function for the time.
Definition: DPMBase.cc:158
std::string print_CG()
Output coarse graining variables.
bool doGradient
Determines if gradient is outputted.
void gather_force_statistics_from_p3c(int version)
get force statistics from particle collisions
int nxMirrored
extension of grid size from mirrored points