MercuryDPM  0.11
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
StatisticsPoint.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 
26 std::ostream& operator<<(std::ostream& os, const CG S)
27 {
28  if (S == HeavisideSphere)
29  os << "HeavisideSphere";
30  else if (S == Gaussian)
31  os << "Gaussian";
32  else if (S == Polynomial)
33  os << "Polynomial";
34  return os;
35 }
36 
37 template<StatType T>
39 
40 template<StatType T>
42 {
43  Nu = 0.0;
44  Density = 0.0;
45  Momentum.setZero();
56  Fabric.setZero();
58  Dissipation = 0.0;
59  Potential = 0.0;
63 }
64 
65 template<StatType T>
67 {
69  P.Nu = mathsFunc::square(Nu);
70  P.Density = mathsFunc::square(Density);
71  P.Momentum = Vec3D::square(Momentum);
72  P.DisplacementMomentum = Vec3D::square(DisplacementMomentum);
73  P.Displacement = MatrixSymmetric3D::square(Displacement);
74  P.MomentumFlux = MatrixSymmetric3D::square(MomentumFlux);
75  P.DisplacementMomentumFlux = MatrixSymmetric3D::square(DisplacementMomentumFlux);
76  P.EnergyFlux = Vec3D::square(EnergyFlux);
77  P.NormalStress = Matrix3D::square(NormalStress);
78  P.TangentialStress = Matrix3D::square(TangentialStress);
79  P.NormalTraction = Vec3D::square(NormalTraction);
80  P.TangentialTraction = Vec3D::square(TangentialTraction);
82  P.CollisionalHeatFlux = Vec3D::square(CollisionalHeatFlux);
83  P.Dissipation = mathsFunc::square(Dissipation);
84  P.Potential = mathsFunc::square(Potential);
85  P.LocalAngularMomentum = Vec3D::square(LocalAngularMomentum);
86  P.LocalAngularMomentumFlux = Matrix3D::square(LocalAngularMomentumFlux);
87  P.ContactCoupleStress = Matrix3D::square(ContactCoupleStress);
88  return P;
89 }
90 
91 template<StatType T>
93 {
94  Nu = P.Nu;
95  Density = P.Density;
96  Momentum = P.Momentum;
97  DisplacementMomentum = P.DisplacementMomentum;
98  Displacement = P.Displacement;
99  MomentumFlux = P.MomentumFlux;
100  DisplacementMomentumFlux = P.DisplacementMomentumFlux;
101  EnergyFlux = P.EnergyFlux;
102  NormalStress = P.NormalStress;
103  TangentialStress = P.TangentialStress;
104  NormalTraction = P.NormalTraction;
105  TangentialTraction = P.TangentialTraction;
106  Fabric = P.Fabric;
107  CollisionalHeatFlux = P.CollisionalHeatFlux;
108  Dissipation = P.Dissipation;
109  Potential = P.Potential;
110  LocalAngularMomentum = P.LocalAngularMomentum;
111  LocalAngularMomentumFlux = P.LocalAngularMomentumFlux;
112  ContactCoupleStress = P.ContactCoupleStress;
113  return *this;
114 }
115 
116 template<StatType T>
118 {
119  Nu += P.Nu;
120  Density += P.Density;
121  Momentum += P.Momentum;
122  DisplacementMomentum += P.DisplacementMomentum;
123  Displacement += P.Displacement;
124  MomentumFlux += P.MomentumFlux;
125  DisplacementMomentumFlux += P.DisplacementMomentumFlux;
126  EnergyFlux += P.EnergyFlux;
127  NormalStress += P.NormalStress;
128  TangentialStress += P.TangentialStress;
129  NormalTraction += P.NormalTraction;
130  TangentialTraction += P.TangentialTraction;
131  Fabric += P.Fabric;
132  CollisionalHeatFlux += P.CollisionalHeatFlux;
133  Dissipation += P.Dissipation;
134  Potential += P.Potential;
135  LocalAngularMomentum += P.LocalAngularMomentum;
136  LocalAngularMomentumFlux += P.LocalAngularMomentumFlux;
137  ContactCoupleStress += P.ContactCoupleStress;
138  return *this;
139 }
140 
141 template<StatType T>
143 {
144  Nu -= P.Nu;
145  Density -= P.Density;
146  Momentum -= P.Momentum;
147  DisplacementMomentum -= P.DisplacementMomentum;
148  Displacement -= P.Displacement;
149  MomentumFlux -= P.MomentumFlux;
150  DisplacementMomentumFlux -= P.DisplacementMomentumFlux;
151  EnergyFlux -= P.EnergyFlux;
152  NormalStress -= P.NormalStress;
153  TangentialStress -= P.TangentialStress;
154  NormalTraction -= P.NormalTraction;
155  TangentialTraction -= P.TangentialTraction;
156  Fabric -= P.Fabric;
157  CollisionalHeatFlux -= P.CollisionalHeatFlux;
158  Dissipation -= P.Dissipation;
159  Potential -= P.Potential;
160  LocalAngularMomentum -= P.LocalAngularMomentum;
161  LocalAngularMomentumFlux -= P.LocalAngularMomentumFlux;
162  ContactCoupleStress -= P.ContactCoupleStress;
163  return *this;
164 }
165 
166 template<StatType T>
168 {
169  Nu /= a;
170  Density /= a;
171  Momentum /= a;
173  Displacement /= a;
174  MomentumFlux /= a;
176  EnergyFlux /= a;
177  NormalStress /= a;
178  TangentialStress /= a;
179  NormalTraction /= a;
180  TangentialTraction /= a;
181  Fabric /= a;
182  CollisionalHeatFlux /= a;
183  Dissipation /= a;
184  Potential /= a;
187  ContactCoupleStress /= a;
188  return *this;
189 }
190 
191 //in the first average, one timestep in Displacement is missing
192 template<StatType T>
194 {
195  Nu /= n;
196  Density /= n;
197  Momentum /= n;
198  if (n == 1)
199  {
203  }
204  else
205  {
206  DisplacementMomentum /= n - 1;
207  Displacement /= n - 1;
208  DisplacementMomentumFlux /= n - 1;
209  }
210  MomentumFlux /= n;
211  EnergyFlux /= n;
212  NormalStress /= n;
213  TangentialStress /= n;
214  NormalTraction /= n;
215  TangentialTraction /= n;
216  Fabric /= n;
217  CollisionalHeatFlux /= n;
218  Dissipation /= n;
219  Potential /= n;
222  ContactCoupleStress /= n;
223 }
224 
225 template<StatType T>
227 {
229 }
230 
231 template<StatType T>
233 {
234  return Vec3D(P.Y * Q.Z - P.Z * Q.Y, P.Z * Q.X - P.X * Q.Z, P.X * Q.Y - P.Y * Q.X);
235 }
236 
238 {
239  return Matrix3D(
240  P.Y * Q.ZX - P.Z * Q.YX, P.Z * Q.XX - P.X * Q.ZX, P.X * Q.YX - P.Y * Q.XX,
241  P.Y * Q.ZY - P.Z * Q.YY, P.Z * Q.XY - P.X * Q.ZY, P.X * Q.YY - P.Y * Q.XY,
242  P.Y * Q.ZZ - P.Z * Q.YZ, P.Z * Q.XZ - P.X * Q.ZZ, P.X * Q.YZ - P.Y * Q.XZ);
243 }
244 
245 template<StatType T>
247 {
248  return P.X * Q.X + P.Y * Q.Y + P.Z * Q.Z;
249 }
250 
251 template<StatType T>
253 {
255  if (getCGShape() == HeavisideSphere)
256  {
257  return (getCGWidthSquared() < dist2) ? 0.0 : getCGInverseVolume();
258  }
259  else if (getCGShape() == Gaussian)
260  {
261  return (getCutoff2() < dist2) ? 0.0 : getCGInverseVolume() * exp(-dist2 / (2.0 * getCGWidthSquared()));
262  }
263  else if (getCGShape() == Polynomial)
264  {
265  return (getCutoff2() < dist2) ? 0.0 : getCGInverseVolume() * evaluatePolynomial(sqrt(dist2) / getCutoff());
266  }
267  else
268  {
269  std::cerr << "error in CG_function" << std::endl;
270  exit(-1);
271  }
272 }
273 
274 template<StatType T>
276 {
278  if (getCGShape() == HeavisideSphere)
279  {
280  if (getCGWidthSquared() < dist2)
281  return 0.0;
282  else
283  {
284  Mdouble wn = sqrt(getCGWidthSquared() - dist2);
285  return getCGInverseVolume() * 2.0 * wn;
287  //return getCGInverseVolume()*(std::min(wn,gb->getObjectDistanceLeft()) +std::min(wn,gb->getObjectDistanceRight()));
288  }
289  }
290  else if (getCGShape() == Gaussian)
291  {
292  return (getCutoff2() < dist2) ? 0.0 : getCGInverseVolume() * exp(-dist2 / (2.0 * getCGWidthSquared()));
293  }
294  else if (getCGShape() == Polynomial)
295  {
296  return (getCutoff2() < dist2) ? 0.0 : getCGInverseVolume() * evaluatePolynomial(sqrt(dist2) / getCutoff());
297  }
298  else
299  {
300  std::cerr << "error in CG_function_2D" << std::endl;
301  exit(-1);
302  }
303 }
304 
305 template<StatType T>
307 {
309  if (getCGShape() == HeavisideSphere)
310  {
311  return (getCGWidthSquared() < dist2) ? 0.0 : (getCGInverseVolume() * constants::pi * (getCGWidthSquared() - dist2));
312  }
313  else if (getCGShape() == Gaussian)
314  {
315  return (getCutoff2() < dist2) ? 0.0 : getCGInverseVolume() * exp(-dist2 / (2.0 * getCGWidthSquared()));
316  }
317  else if (getCGShape() == Polynomial)
318  {
319  return (getCutoff2() < dist2) ? 0.0 : getCGInverseVolume() * evaluatePolynomial(sqrt(dist2) / getCutoff());
320  }
321  else
322  {
323  std::cerr << "error in CG_function_1D" << std::endl;
324  exit(-1);
325  }
326 }
327 
328 template<StatType T>
330 {
331  //CG_type_todo
332  if (getCGShape() == Gaussian)
333  {
334  return (P - Position) * (phi / getCGWidthSquared());
335  }
336  else if (getCGShape() == Polynomial)
337  {
340  }
341  else
342  {
343  std::cerr << "error in CG_gradient" << std::endl;
344  exit(-1);
345  }
346 }
347 
349 template<StatType T>
350 Vec3D StatisticsPoint<T>::CG_integral_gradient(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance)
351 {
352  Vec3D P_P1 = Position - P1;
353  Vec3D P_P2 = Position - P2;
354  Mdouble a = dotNonAveraged(P_P1, P1_P2_normal);
355  Mdouble b = dotNonAveraged(P_P2, P1_P2_normal);
356  Vec3D tangential = P_P1 - a * P1_P2_normal;
357  //CG_type_todo
358  if (getCGShape() == Gaussian)
359  {
360  Mdouble wsq2 = sqrt(2 * getCGWidthSquared());
361  Mdouble f = sqrt(2 * constants::pi * getCGWidthSquared());
362  return Vec3D(0.0, 0.0, (exp(-mathsFunc::square(a / wsq2)) - exp(-mathsFunc::square(b / wsq2))) / f / (P2.Z - P1.Z));
363  }
364  else if (getCGShape() == Polynomial)
365  {
366  double wn2 = getCGWidthSquared() - dotNonAveraged(tangential, tangential);
367  if ((wn2 <= 0) | (a * fabs(a) >= wn2) | (b * fabs(b) <= -wn2))
368  {
369  return Vec3D(0, 0, 0);
370  }
371  else
372  {
374  double wn = std::sqrt(wn2);
375  double w = getCGWidth();
376  double delta = w * 1e-3;
377  double I = getCGInverseVolume() * evaluateIntegral(std::max(a, -wn) / w, std::min(b, wn) / w, tangential.getLength() / w) * w / P1_P2_distance;
378  Vec3D delta_P_P1 = P_P1 + Vec3D(delta, 0, 0);
379  Vec3D delta_P_P2 = P_P2 + Vec3D(delta, 0, 0);
380  a = dotNonAveraged(delta_P_P1, P1_P2_normal);
381  b = dotNonAveraged(delta_P_P2, P1_P2_normal);
382  tangential = delta_P_P1 - a * P1_P2_normal;
383  wn = std::sqrt(getCGWidthSquared() - dotNonAveraged(tangential, tangential));
384  double Ix = getCGInverseVolume() * evaluateIntegral(std::max(a, -wn) / w, std::min(b, wn) / w, tangential.getLength() / w) * w / P1_P2_distance;
385  delta_P_P1 = P_P1 + Vec3D(0, delta, 0);
386  delta_P_P2 = P_P2 + Vec3D(0, delta, 0);
387  a = dotNonAveraged(delta_P_P1, P1_P2_normal);
388  b = dotNonAveraged(delta_P_P2, P1_P2_normal);
389  tangential = delta_P_P1 - a * P1_P2_normal;
390  wn = std::sqrt(getCGWidthSquared() - dotNonAveraged(tangential, tangential));
391  double Iy = getCGInverseVolume() * evaluateIntegral(std::max(a, -wn) / w, std::min(b, wn) / w, tangential.getLength() / w) * w / P1_P2_distance;
392  delta_P_P1 = P_P1 + Vec3D(0, 0, delta);
393  delta_P_P2 = P_P2 + Vec3D(0, 0, delta);
394  a = dotNonAveraged(delta_P_P1, P1_P2_normal);
395  b = dotNonAveraged(delta_P_P2, P1_P2_normal);
396  tangential = delta_P_P1 - a * P1_P2_normal;
397  wn = std::sqrt(getCGWidthSquared() - dotNonAveraged(tangential, tangential));
398  double Iz = getCGInverseVolume() * evaluateIntegral(std::max(a, -wn) / w, std::min(b, wn) / w, tangential.getLength() / w) * w / P1_P2_distance;
399  return Vec3D(Ix - I, Iy - I, Iz - I) / delta;
400  }
401  }
402  else
403  {
404  return Vec3D(0, 0, 0);
405  }
406  //~ if (getCGShape()==Gaussian) return Vec3D(0.0,0.0,0.0);
407  //~ else { std::cerr << "error in CG_function" << std::endl; exit(-1); }
408 }
409 
410 template<StatType T>
412 {
413  Vec3D P_P1 = Position - P1;
414  Vec3D P_P2 = Position - P2;
415  Mdouble a = dotNonAveraged(P_P1, P1_P2_normal);
416  Mdouble b = dotNonAveraged(P_P2, P1_P2_normal);
417  Vec3D tangential = P_P1 - a * P1_P2_normal;
418  //CG_type_todo
419  if (getCGShape() == Gaussian)
420  {
421  Mdouble wsq2 = sqrt(2 * getCGWidthSquared());
422  Mdouble f = sqrt(2 * constants::pi * getCGWidthSquared());
423  return (exp(-mathsFunc::square(a / wsq2)) - exp(-mathsFunc::square(b / wsq2))) / f / (P2.Z - P1.Z);
424  }
425  else if (getCGShape() == Polynomial)
426  {
427  double wn2 = getCGWidthSquared() - dotNonAveraged(tangential, tangential);
428  if ((wn2 <= 0) | (a * fabs(a) >= wn2) | (b * fabs(b) <= -wn2))
429  {
430  return 0;
431  }
432  else if ((P1_P2_distance < 1e-12) | (Vec3D::getLengthSquared(tangential) < 1e-24))
433  {
434  //if the normal is parallel to the averaging direction
435  std::cout << "normal is parallel to the averaging direction: "
436  << " P1_P2_distance " << P1_P2_distance
437  << " tangential " << tangential << std::endl;
439  return 0; //CG_gradient_1D(P1,CG_function(P1));
440  }
441  else
442  {
443  double wn = sqrt(wn2);
444  double w = getCGWidth();
446  double delta = w * 3e-6;
447  //double I = getCGInverseVolume()*evaluateIntegral(std::max(a,-wn)/w,std::min(b,wn)/w,dot(tangential,tangential)/w)*w / P1_P2_distance;
448  Vec3D delta_P_P1 = P_P1 + Vec3D(delta, delta, delta);
449  Vec3D delta_P_P2 = P_P2 + Vec3D(delta, delta, delta);
450  a = dotNonAveraged(delta_P_P1, P1_P2_normal);
451  b = dotNonAveraged(delta_P_P2, P1_P2_normal);
452  tangential = delta_P_P1 - a * P1_P2_normal;
453  wn = sqrt(getCGWidthSquared() - dotNonAveraged(tangential, tangential));
454  double I2 = getCGInverseVolume() * evaluateIntegral(std::max(a, -wn) / w, std::min(b, wn) / w, dotNonAveraged(tangential, tangential) / w) * w / P1_P2_distance;
455 
456  delta_P_P1 = P_P1 - Vec3D(delta, delta, delta);
457  delta_P_P2 = P_P2 - Vec3D(delta, delta, delta);
458  a = dotNonAveraged(delta_P_P1, P1_P2_normal);
459  b = dotNonAveraged(delta_P_P2, P1_P2_normal);
460  tangential = delta_P_P1 - a * P1_P2_normal;
461  wn = sqrt(getCGWidthSquared() - dotNonAveraged(tangential, tangential));
462  double I1 = getCGInverseVolume() * evaluateIntegral(std::max(a, -wn) / w, std::min(b, wn) / w, dotNonAveraged(tangential, tangential) / w) * w / P1_P2_distance;
463 
464  return (I2 - I1) / (2. * delta);
465  }
466  }
467  else
468  return 0;
469 }
470 
477 template <StatType T>
479 Mdouble StatisticsPoint<T>::CG_integral(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Vec3D& rpsi)
480 {
481  //apply the cutoff in normal direction:
482  Vec3D P_P1 = Position - P1;
483  Mdouble a = dotNonAveraged(P_P1,P1_P2_normal);
484  if ( a > getCutoff() ) return 0.0;
485  Vec3D P_P2 = Position - P2;
486  Mdouble b = dotNonAveraged(P_P2,P1_P2_normal);
487  if ( -b > getCutoff() ) return 0.0;
488  //apply the cutoff in tangential direction:
489  Vec3D tangential = P_P1 - a * P1_P2_normal;
490  if (dotNonAveraged(tangential,tangential)>getCutoff2()) return 0.0;
491  //evaluate:
493  {
494  Mdouble wn2 = getCGWidthSquared() - dotNonAveraged(tangential,tangential);
495  if ((wn2<=0) | (a*fabs(a)>=wn2) | (b*fabs(b)<=-wn2))
496  {
497  return 0;
498  }
499  else
500  {
501  Mdouble wn = sqrt(wn2);
502  return getCGInverseVolume()*( std::min(b,wn)-std::max(a,-wn) ) / P1_P2_distance;
503  }
504  }
505  else if (getCGShape()==Gaussian)
506  { //Gaussian
507  static Mdouble InvVolumeExp = compute_Gaussian_invvolume(gb->getSystemDimensions()-1);
508  static Mdouble w_sqrt_2 = constants::sqrt_2*getCGWidth();
509  static Mdouble P1_P2_distance_for_cutoff=-1, InvVolumeErf=-1;
510  if (P1_P2_distance_for_cutoff!=P1_P2_distance)
511  {
512  P1_P2_distance_for_cutoff = P1_P2_distance;
513  Mdouble amax = -getCutoff();
514  Mdouble bmax = getCutoff()+P1_P2_distance;
515  InvVolumeErf = P1_P2_distance/(
516  erf(bmax/w_sqrt_2)*bmax+w_sqrt_2/constants::sqrt_pi*exp(-bmax*bmax/(w_sqrt_2*w_sqrt_2))
517  -erf(amax/w_sqrt_2)*amax-w_sqrt_2/constants::sqrt_pi*exp(-amax*amax/(w_sqrt_2*w_sqrt_2)));
518  // std::cout << "InvVolumeErf" << InvVolumeErf << " InvVolumeExp" << InvVolumeExp << " f" << getCGInverseVolume() * sqrt(2*constants::pi*getCGWidthSquared()) << std::endl;
519  }
520  Mdouble psi=exp(-dotNonAveraged(tangential,tangential)/(2.0*getCGWidthSquared())) * InvVolumeExp
521  * ( erf(b/w_sqrt_2) - erf(a/w_sqrt_2) ) * InvVolumeErf /2./P1_P2_distance;
522  rpsi=Position*psi;
523  return psi;
524  }
525  else if (getCGShape()==Polynomial)
526  {
527  double wn2 = getCGWidthSquared() - dotNonAveraged(tangential,tangential);
528  if ((wn2<=0) | (a*fabs(a)>=wn2) | (b*fabs(b)<=-wn2))
529  {
530  return 0;
531  }
532  else
533  {
534  double wn = sqrt(wn2);
535  double w = getCGWidth();
536  return getCGInverseVolume()*evaluateIntegral(std::max(a,-wn)/w,std::min(b,wn)/w,tangential.getLength()/w)*w / P1_P2_distance;
537  }
538  //CG_type_todo
539  }
540  else
541  { std::cerr << "error in CG_integral" << std::endl; exit(-1);}
542 }
543 
545 template<StatType T>
546 Mdouble StatisticsPoint<T>::CG_integral_2D(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Mdouble& rpsi_scalar)
547 {
548  //apply the cutoff in normal direction:
549  Vec3D P_P1 = Position - P1;
550  Mdouble a = dotNonAveraged(P_P1, P1_P2_normal);
551  if (a > getCutoff())
552  return 0.0;
553  Vec3D P_P2 = Position - P2;
554  Mdouble b = dotNonAveraged(P_P2, P1_P2_normal);
555  if (-b > getCutoff())
556  return 0.0;
557  //apply the cutoff in tangential direction:
558  Vec3D tangential = P_P1 - a * P1_P2_normal;
559  if (dotNonAveraged(tangential, tangential) > getCutoff2())
560  return 0.0;
561  if (getCGShape() == HeavisideSphere)
562  {
563  Mdouble wn2 = getCGWidthSquared() - dotNonAveraged(tangential, tangential);
564  if ((wn2 <= 0) || (a * fabs(a) >= wn2) || (b * fabs(b) <= -wn2))
565  {
566  return 0;
567  }
568  else
569  {
570  Mdouble wn = sqrt(wn2);
571  //if the normal is parallel to the averaging direction
572  if (std::max(fabs(a), fabs(b)) < 1e-20)
573  {
574  return getCGInverseVolume() * 2 * wn;
575  }
576  return getCGInverseVolume() / P1_P2_distance
577  * (((b >= wn) ? (constants::pi * wn2 / 2.0) : (b * sqrt(wn2 - mathsFunc::square(b)) + wn2 * asin(b / wn)))
578  + ((a <= -wn) ? (constants::pi * wn2 / 2.0) : (-a * sqrt(wn2 - mathsFunc::square(a)) - wn2 * asin(a / wn))));
579  }
580  }
581  else if (getCGShape() == Gaussian)
582  { //Gaussian
583  if (dotNonAveraged(P1_P2_normal, P1_P2_normal) < 1e-20)
584  {
585  //since we average parallel to the force line, the CG integral is shaped like the CG function
587  return getCGInverseVolume() * exp(-dotNonAveraged(P_P1, P_P1) / (2.0 * getCGWidthSquared()));
588  }
589  static Mdouble InvVolumeExp = compute_Gaussian_invvolume(gb->getSystemDimensions() - 2);
590  static Mdouble w_sqrt_2 = constants::sqrt_2 * getCGWidth();
591  static Mdouble P1_P2_distance_for_cutoff = -1, InvVolumeErf = -1;
592  if (P1_P2_distance_for_cutoff != P1_P2_distance)
593  {
594  P1_P2_distance_for_cutoff = P1_P2_distance;
595  Mdouble amax = -getCutoff();
596  Mdouble bmax = getCutoff() + P1_P2_distance;
597  InvVolumeErf = P1_P2_distance / (
598  erf(bmax / w_sqrt_2) * bmax + w_sqrt_2 / constants::sqrt_pi * exp(-bmax * bmax / (w_sqrt_2 * w_sqrt_2))
599  - erf(amax / w_sqrt_2) * amax - w_sqrt_2 / constants::sqrt_pi * exp(-amax * amax / (w_sqrt_2 * w_sqrt_2))
600  ) / averagingVolume();
601  //std::cout << "InvVolumeErf" << InvVolumeErf << " InvVolumeExp" << InvVolumeExp << " f" << getCGInverseVolume() * sqrt(2*constants::pi*getCGWidthSquared()) << std::endl;
602  }
603  //Note: use dot(t,t), GetLength2(t), as dot only works on non-averaged directions
604  //we also define rpsi
605  Mdouble psi = exp(-dotNonAveraged(tangential, tangential) / (2.0 * getCGWidthSquared())) * InvVolumeExp
606  * (erf(b / w_sqrt_2) - erf(a / w_sqrt_2)) * InvVolumeErf / 2. / P1_P2_distance;
607  Mdouble phi1 = getCGInverseVolume() * exp(-dotNonAveraged(P_P1, P_P1) / (2.0 * getCGWidthSquared()));
608  Mdouble phi2 = getCGInverseVolume() * exp(-dotNonAveraged(P_P2, P_P2) / (2.0 * getCGWidthSquared()));
609  rpsi_scalar = -a / P1_P2_distance * psi + getCGWidthSquared() / P1_P2_distance / P1_P2_distance * (phi1 - phi2);
610  return psi;
611  }
612  else if (getCGShape() == Polynomial)
613  {
614  double wn2 = getCGWidthSquared() - dotNonAveraged(tangential, tangential);
615  if ((wn2 <= 0) | (a * fabs(a) >= wn2) | (b * fabs(b) <= -wn2))
616  {
617  return 0;
618  }
619  else if (P1_P2_distance < 1e-20)
620  {
621  //if the normal is parallel to the averaging direction
622  return CG_function_1D(P_P1);
623  }
624  else
625  {
626  double wn = sqrt(wn2);
627  double w = getCGWidth();
628  return getCGInverseVolume() * evaluateIntegral(std::max(a, -wn) / w, std::min(b, wn) / w, tangential.getLength() / w) * w / P1_P2_distance;
629  }
630  //CG_type_todo
631  }
632  else
633  {
634  std::cerr << "error in CG_integral_2D" << std::endl;
635  exit(-1);
636  }
637 }
638 
640 template<StatType T>
641 Mdouble StatisticsPoint<T>::CG_integral_1D(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Mdouble& rpsi_scalar)
642 {
643  //apply the cutoff in normal direction:
644  Vec3D P_P1 = Position - P1;
645  Mdouble a = dotNonAveraged(P_P1, P1_P2_normal);
646  if (a > getCutoff())
647  return 0.0;
648  Vec3D P_P2 = Position - P2;
649  Mdouble b = dotNonAveraged(P_P2, P1_P2_normal);
650  if (-b > getCutoff())
651  return 0.0;
652  //apply the cutoff in tangential direction:
653  Vec3D tangential = P_P1 - a * P1_P2_normal;
654  if (dotNonAveraged(tangential, tangential) > getCutoff2())
655  return 0.0;
656  if (getCGShape() == HeavisideSphere)
657  {
658  Mdouble wn2 = getCGWidthSquared() - dotNonAveraged(tangential, tangential);
659  if ((wn2 <= 0) | (a * fabs(a) >= wn2) | (b * fabs(b) <= -wn2))
660  {
661  return 0;
662  }
663  else
664  {
665  //if the normal is parallel to the averaging direction
666  if (std::max(fabs(a), fabs(b)) < 1e-20)
667  {
668  return getCGInverseVolume() * constants::pi * wn2;
669  }
670  Mdouble wn = sqrt(wn2);
671  return getCGInverseVolume() / P1_P2_distance
672  * (((b >= wn) ? (2.0 / 3.0 * constants::pi * wn2 * wn) : (b * constants::pi * (wn2 - mathsFunc::square(b) / 3.0)))
673  - ((a <= -wn) ? (-2.0 / 3.0 * constants::pi * wn2 * wn) : (a * constants::pi * (wn2 - mathsFunc::square(a) / 3.0))));
674  }
675  }
676  else if (getCGShape() == Gaussian)
677  { //Gaussian
678  if (fabs(b - a) < 1e-20)
679  {
680  return getCGInverseVolume() * exp(-dotNonAveraged(P_P1, P_P1) / (2.0 * getCGWidthSquared()));
681  }
682  static Mdouble w_sqrt_2 = constants::sqrt_2 * getCGWidth();
683  static Mdouble P1_P2_distance_for_cutoff = -1, InvVolumeErf = -1;
684  if (P1_P2_distance_for_cutoff != P1_P2_distance)
685  {
686  P1_P2_distance_for_cutoff = P1_P2_distance;
687  Mdouble amax = -getCutoff();
688  Mdouble bmax = getCutoff() + P1_P2_distance;
689  InvVolumeErf = P1_P2_distance / (
690  erf(bmax / w_sqrt_2) * bmax + w_sqrt_2 / constants::sqrt_pi * exp(-bmax * bmax / (w_sqrt_2 * w_sqrt_2))
691  - erf(amax / w_sqrt_2) * amax - w_sqrt_2 / constants::sqrt_pi * exp(-amax * amax / (w_sqrt_2 * w_sqrt_2))
692  ) / averagingVolume();
693  //std::cout << "InvVolumeErf" << InvVolumeErf << " InvVolumeExp" << InvVolumeExp << " f" << getCGInverseVolume() * sqrt(2*constants::pi*getCGWidthSquared()) << std::endl;
694  }
695  //Note: use dot(t,t), GetLength2(t), as dot only works on non-averaged directions
696  Mdouble psi = (erf(b / w_sqrt_2) - erf(a / w_sqrt_2)) * InvVolumeErf / 2. / P1_P2_distance;
697  Mdouble phi1 = getCGInverseVolume() * exp(-dotNonAveraged(P_P1, P_P1) / (2.0 * getCGWidthSquared()));
698  Mdouble phi2 = getCGInverseVolume() * exp(-dotNonAveraged(P_P2, P_P2) / (2.0 * getCGWidthSquared()));
699  rpsi_scalar = -a / P1_P2_distance * psi + getCGWidthSquared() / P1_P2_distance / P1_P2_distance * (phi1 - phi2);
700  return psi;
701  }
702  else if (getCGShape() == Polynomial)
703  {
704  //~ std::cout << setprecision(12) << P1_P2_normal << std::endl;
705  double wn2 = getCGWidthSquared() - dotNonAveraged(tangential, tangential);
706  if ((wn2 <= 0) | (a * fabs(a) >= wn2) | (b * fabs(b) <= -wn2))
707  {
708  return 0;
709  }
710  else if ((P1_P2_distance < 1e-12) | (Vec3D::getLengthSquared(tangential) < 1e-24))
711  {
712  //~ } else if (fabs(b-a)<1e-12) {
713  //if the normal is parallel to the averaging direction
714  //~ std::cout << "normal is parallel to the averaging direction: "
715  //~ << " P_P1 " << P1_P2_distance
716  //~ << " psi= " << CG_function_1D(P1) << std::endl;
717  return CG_function_1D(P1);
718  }
719  else
720  {
721  double wn = sqrt(wn2);
722  double w = getCGWidth();
723  return getCGInverseVolume() * evaluateIntegral(std::max(a, -wn) / w, std::min(b, wn) / w, dotNonAveraged(tangential, tangential) / w) * w / P1_P2_distance;
724  }
725  }
726  else
727  {
728  std::cerr << "error in CG_integral_1D" << std::endl;
729  exit(-1);
730  }
731  std::cout << "eind testje" << rpsi_scalar << std::endl;
732 }
733 
734 template<StatType T>
736 {
737  std::stringstream ss;
738  ss << "Nu "
739  << "Density "
740  << "MomentumX "
741  << "MomentumY "
742  << "MomentumZ "
743  << "DisplacementMomentumX "
744  << "DisplacementMomentumY "
745  << "DisplacementMomentumZ "
746  << "DisplacementXX "
747  << "DisplacementXY "
748  << "DisplacementXZ "
749  << "DisplacementYY "
750  << "DisplacementYZ "
751  << "DisplacementZZ "
752  << "MomentumFluxXX "
753  << "MomentumFluxXY "
754  << "MomentumFluxXZ "
755  << "MomentumFluxYY "
756  << "MomentumFluxYZ "
757  << "MomentumFluxZZ "
758  << "DisplacementMomentumFluxXX "
759  << "DisplacementMomentumFluxXY "
760  << "DisplacementMomentumFluxXZ "
761  << "DisplacementMomentumFluxYY "
762  << "DisplacementMomentumFluxYZ "
763  << "DisplacementMomentumFluxZZ "
764  << "EnergyFluxX "
765  << "EnergyFluxY "
766  << "EnergyFluxZ "
767  << "NormalStressXX "
768  << "NormalStressXY "
769  << "NormalStressXZ "
770  << "NormalStressYX "
771  << "NormalStressYY "
772  << "NormalStressYZ "
773  << "NormalStressZX "
774  << "NormalStressZY "
775  << "NormalStressZZ "
776  << "TangentialStressXX "
777  << "TangentialStressXY "
778  << "TangentialStressXZ "
779  << "TangentialStressYX "
780  << "TangentialStressYY "
781  << "TangentialStressYZ "
782  << "TangentialStressZX "
783  << "TangentialStressZY "
784  << "TangentialStressZZ "
785  << "NormalTractionX "
786  << "NormalTractionY "
787  << "NormalTractionZ "
788  << "TangentialTractionX "
789  << "TangentialTractionY "
790  << "TangentialTractionZ "
791  << "FabricXX "
792  << "FabricXY "
793  << "FabricXZ "
794  << "FabricYY "
795  << "FabricYZ "
796  << "FabricZZ "
797  << "CollisionalHeatFluxX "
798  << "CollisionalHeatFluxY "
799  << "CollisionalHeatFluxZ "
800  << "Dissipation "
801  << "Potential "
802  << "LocalAngularMomentumX "
803  << "LocalAngularMomentumY "
804  << "LocalAngularMomentumZ "
805  << "LocalAngularMomentumFluxXX "
806  << "LocalAngularMomentumFluxXY "
807  << "LocalAngularMomentumFluxXZ "
808  << "LocalAngularMomentumFluxYX "
809  << "LocalAngularMomentumFluxYY "
810  << "LocalAngularMomentumFluxYZ "
811  << "LocalAngularMomentumFluxZX "
812  << "LocalAngularMomentumFluxZY "
813  << "LocalAngularMomentumFluxZZ "
814  << "ContactCoupleStressXX "
815  << "ContactCoupleStressXY "
816  << "ContactCoupleStressXZ "
817  << "ContactCoupleStressYX "
818  << "ContactCoupleStressYY "
819  << "ContactCoupleStressYZ "
820  << "ContactCoupleStressZX "
821  << "ContactCoupleStressZY "
822  << "ContactCoupleStressZZ ";
823  return ss.str();
824 }
825 
826 template<StatType T>
827 std::string StatisticsPoint<T>::print() const
828 {
829  std::stringstream ss;
830  ss << "Nu " << Nu
831  << ", Density " << Density
832  << ",\n Momentum " << Momentum
833  << ",\n DisplacementMomentum " << DisplacementMomentum
834  << ",\n Displacement " << Displacement
835  << ",\n MomentumFlux " << MomentumFlux
836  << ",\n DisplacementMomentumFlux " << DisplacementMomentumFlux
837  << ",\n EnergyFlux " << EnergyFlux
838  << ",\n NormalStress " << NormalStress
839  << ",\n TangentialStress " << TangentialStress
840  << ",\n NormalTraction " << NormalTraction
841  << ",\n TangentialTraction " << TangentialTraction
842  << ",\n Fabric " << Fabric
843  << ",\n CollisionalHeatFlux " << CollisionalHeatFlux
844  << ",\n Dissipation " << Dissipation
845  << ",\n Potential " << Potential
846  << ",\n LocalAngularMomentum " << LocalAngularMomentum
847  << ",\n LocalAngularMomentumFlux " << LocalAngularMomentumFlux
848  << ",\n ContactCoupleStress " << ContactCoupleStress;
849  return ss.str();
850 }
851 
852 template<StatType T>
854 {
855  std::stringstream ss;
856  ss << "Nu " << std::sqrt(Nu)
857  << ", Density " << std::sqrt(Density)
858  << ", Momentum " << Vec3D::sqrt(Momentum)
859  << ", DisplacementMomentum " << Vec3D::sqrt(DisplacementMomentum)
860  << ", Displacement " << MatrixSymmetric3D::sqrt(Displacement)
861  << ", MomentumFlux " << MatrixSymmetric3D::sqrt(MomentumFlux)
862  << ", DisplacementMomentumFlux " << MatrixSymmetric3D::sqrt(DisplacementMomentumFlux)
863  << ", EnergyFlux " << Vec3D::sqrt(EnergyFlux)
864  << ", NormalStress " << Matrix3D::sqrt(NormalStress)
865  << ", TangentialStress " << Matrix3D::sqrt(TangentialStress)
866  << ", NormalTraction " << Vec3D::sqrt(NormalTraction)
867  << ", TangentialTraction " << Vec3D::sqrt(TangentialTraction)
868  << ", Fabric " << MatrixSymmetric3D::sqrt(Fabric)
869  << ", CollisionalHeatFlux " << Vec3D::sqrt(CollisionalHeatFlux)
870  << ", Dissipation " << std::sqrt(Dissipation)
871  << ", Potential " << std::sqrt(Potential)
872  << ", LocalAngularMomentum " << Vec3D::sqrt(LocalAngularMomentum)
873  << ", LocalAngularMomentumFlux " << Matrix3D::sqrt(LocalAngularMomentumFlux)
874  << ", ContactCoupleStress " << Matrix3D::sqrt(ContactCoupleStress);
875 
876  return ss.str();
877 }
878 
879 template<StatType T>
880 std::string StatisticsPoint<T>::write() const
881 {
882  std::stringstream ss;
883  ss.precision(16);
884  ss << Nu
885  << " " << Density
886  << " " << Momentum
887  << " " << DisplacementMomentum
888  << " " << Displacement
889  << " " << MomentumFlux
890  << " " << DisplacementMomentumFlux
891  << " " << EnergyFlux
892  << " " << NormalStress
893  << " " << TangentialStress
894  << " " << NormalTraction
895  << " " << TangentialTraction
896  << " " << Fabric
897  << " " << CollisionalHeatFlux
898  << " " << Dissipation
899  << " " << Potential
900  << " " << LocalAngularMomentum
901  << " " << LocalAngularMomentumFlux
902  << " " << ContactCoupleStress;
903  return ss.str();
904 }
905 
906 template<StatType T>
908 {
910 }
911 
912 template<StatType T>
914 {
915  if (dim == 0)
916  {
917  return 1.;
918  }
919 
920  //this is the prefactor 1/V of phi(r)=1/V*exp(-|r|^2/w^2) for dim=1
921  double CG_invvolume_computed = 1. / (constants::sqrt_2 * constants::sqrt_pi * getCGWidth());
922  //take into account the cutoff radius and the dimension of the problem
923  if (dim == 3)
924  {
925  CG_invvolume_computed = mathsFunc::cubic(CG_invvolume_computed);
926  //Wolfram alpha: erf(c/(sqrt(2) w))-(sqrt(2/pi) c e^(-c^2/(2 w^2)))/w
927  CG_invvolume_computed /= erf(getCutoff() / (constants::sqrt_2 * getCGWidth()))
929  }
930  else if (dim == 2)
931  {
932  CG_invvolume_computed = mathsFunc::square(CG_invvolume_computed);
933  //Wolfram alpha: integrate(x*exp(-x^2/(2w^2)),{x,0,c})/integrate(x*exp(-x^2/(2w^2)),{x,0,inf})=1-e^(-c^2/(2 w^2))
934  CG_invvolume_computed /= 1 - exp(-getCutoff2() / (2 * getCGWidthSquared()));
935  }
936  else
937  {
938  CG_invvolume_computed /= erf(getCutoff() / (constants::sqrt_2 * getCGWidth()));
939  }
940  return CG_invvolume_computed;
941 }
942 
943 template<StatType T>
945 {
947  CG_invvolume = 1.0 / (4.0 / 3.0 * constants::pi * sqrt(getCGWidthSquared()) * getCGWidthSquared());
948 }
949 
950 template<StatType T>
952 {
953  if (dim == 3)
954  CG_invvolume = 1.0 / (sqrt(getCGWidthSquared()) * getCGWidthSquared());
955  else if (dim == 2)
957  else
958  CG_invvolume = 1.0 / sqrt(getCGWidthSquared());
959 }
960 
961 template<StatType T> void StatisticsPoint<T>::setCGInverseVolume()
962 {
963  if (getCGShape() == HeavisideSphere)
964  {
966  }
967  else if (getCGShape() == Gaussian)
968  {
970  } else if (getCGShape()==Polynomial)
971  {
973  }
974  else
975  { std::cerr << "error in CG_function" << std::endl; exit(-1);}
977  }
978 
980 {
981  return gb->getSystemDimensions();
982 }
984 {
985  return gb->getSystemDimensions() - 1;
986 }
988 {
989  return gb->getSystemDimensions() - 1;
990 }
992 {
993  return 2;
994 }
996 {
997  return 1;
998 }
1000 {
1001  return 1;
1002 }
1004 {
1005  return gb->getSystemDimensions() - 2;
1006 }
1008 {
1009  return 0;
1010 }
1012 {
1013  exit(-1);
1014 }
1016 {
1017  exit(-1);
1018 }
1020 {
1021  exit(-1);
1022 }
1024 {
1025  exit(-1);
1026 }
1028 {
1029  exit(-1);
1030 }
1032 {
1033  exit(-1);
1034 }
1035 
1037 {
1038  return 1.0;
1039 }
1041 {
1042  return ((gb->getSystemDimensions() != 3) ? (1.0) : (getZMaxStat() - getZMinStat()));
1043 }
1045 {
1046  return (getYMaxStat() - getYMinStat());
1047 }
1049 {
1050  return (getXMaxStat() - getXMinStat());
1051 }
1053 {
1054  return (getYMaxStat() - getYMinStat())
1055  * ((gb->getSystemDimensions() != 3) ? (1.0) : (getZMaxStat() - getZMinStat()));
1056 }
1058 {
1059  return (getXMaxStat() - getXMinStat())
1060  * ((gb->getSystemDimensions() != 3) ? (1.0) : (getZMaxStat() - getZMinStat()));
1061 }
1063 {
1064  return (getXMaxStat() - getXMinStat())
1065  * (getYMaxStat() - getYMinStat());
1066 }
1068 {
1069  return (getXMaxStat() - getXMinStat())
1070  * (getYMaxStat() - getYMinStat())
1071  * ((gb->getSystemDimensions() != 3) ? (1.0) : (getZMaxStat() - getZMinStat()));
1072 }
1074 {
1075  exit(-1);
1076 }
1078 {
1079  exit(-1);
1080 }
1082 {
1083  exit(-1);
1084 }
1086 {
1087  exit(-1);
1088 }
1090 {
1091  exit(-1);
1092 }
1094 {
1095  exit(-1);
1096 }
1097 
1099 {
1100  return CG_function_2D(PI);
1101 }
1103 {
1104  Mdouble dist2 = getDistanceSquaredNonAveraged(PI);
1106  Mdouble RI2 = mathsFunc::square(Position.X) + mathsFunc::square(Position.Y);
1107  Mdouble Z2 = mathsFunc::square(PI.Z - Position.Z);
1108  if (getCGShape() == Gaussian)
1109  {
1110  return (getCutoff2() < dist2) ? 0.0 : getCGInverseVolume()
1111  * exp(-(R2 + RI2 + Z2) / (2.0 * getCGWidthSquared())) * besselFunc::I0(sqrt(R2 * RI2) / getCGWidthSquared());
1112  }
1113  else
1114  {
1115  std::cerr << "error in CG_function<RZ>" << std::endl;
1116  exit(-1);
1117  }
1118 }
1120 {
1121  std::cerr << "error in CG_function<AZ>" << std::endl;
1122  exit(-1);
1123 }
1125 {
1126  Mdouble dist2 = getDistanceSquaredNonAveraged(PI);
1128  Mdouble RI2 = mathsFunc::square(Position.X) + mathsFunc::square(Position.Y);
1129  if (getCGShape() == Gaussian)
1130  {
1131  return (getCutoff2() < dist2) ? 0.0 : getCGInverseVolume()
1132  * exp(-(R2 + RI2) / (2.0 * getCGWidthSquared())) * besselFunc::I0(sqrt(R2 * RI2) / getCGWidthSquared());
1133  }
1134  else
1135  {
1136  std::cerr << "error in CG_function<R>" << std::endl;
1137  exit(-1);
1138  }
1139 }
1141 {
1142  std::cerr << "error in CG_function<A>" << std::endl;
1143  exit(-1);
1144 }
1145 
1147 {
1148  return CG_function_2D(PI);
1149 }
1151 {
1152  return CG_function_2D(PI);
1153 }
1155 {
1156  return CG_function_2D(PI);
1157 }
1159 {
1160  return CG_function_1D(PI);
1161 }
1163 {
1164  return CG_function_1D(PI);
1165 }
1167 {
1168  return CG_function_1D(PI);
1169 }
1171 {
1172  return getCGInverseVolume();
1173 }
1174 
1175 template<> Vec3D StatisticsPoint<YZ>::CG_gradient(const Vec3D &P, const Mdouble phi)
1176 {
1177  //CG_type_todo
1178  if (getCGShape() == Gaussian)
1179  {
1180  return Vec3D(0.0, P.Y - Position.Y, P.Z - Position.Z) * (phi / getCGWidthSquared());
1181  }
1182  else
1183  {
1184  std::cerr << "error in CG_gradient<YZ>" << std::endl;
1185  exit(-1);
1186  }
1187 }
1188 template<> Vec3D StatisticsPoint<XZ>::CG_gradient(const Vec3D &P, const Mdouble phi)
1189 {
1190  //CG_type_todo
1191  if (getCGShape() == Gaussian)
1192  {
1193  return Vec3D(P.X - Position.X, 0.0, P.Z - Position.Z) * (phi / getCGWidthSquared());
1194  }
1195  else
1196  {
1197  std::cerr << "error in CG_gradient<XZ>" << std::endl;
1198  exit(-1);
1199  }
1200 }
1201 template<> Vec3D StatisticsPoint<XY>::CG_gradient(const Vec3D &P, const Mdouble phi)
1202 {
1203  //CG_type_todo
1204  if (getCGShape() == Gaussian)
1205  {
1206  return Vec3D(P.X - Position.X, P.Y - Position.Y, 0.0) * (phi / getCGWidthSquared());
1207  }
1208  else
1209  {
1210  std::cerr << "error in CG_gradient<XY>" << std::endl;
1211  exit(-1);
1212  }
1213 }
1214 
1215 template<> Vec3D StatisticsPoint<X>::CG_gradient(const Vec3D &P, const Mdouble phi)
1216 {
1217  //CG_type_todo
1218  if (getCGShape() == Gaussian)
1219  {
1220  return Vec3D((P.X - Position.X) * (phi / getCGWidthSquared()), 0.0, 0.0);
1221  }
1222  else if (getCGShape() == Polynomial)
1223  {
1224  Mdouble r = fabs(Position.X - P.X) / getCGWidth();
1225  return Vec3D(getCGInverseVolume() * evaluatePolynomialGradient(r) / r / getCGWidthSquared() * (Position.X - P.X), 0, 0);
1226  }
1227  else
1228  {
1229  std::cerr << "error in CG_gradient<X>" << std::endl;
1230  exit(-1);
1231  }
1232 }
1233 template<> Vec3D StatisticsPoint<Y>::CG_gradient(const Vec3D &P, const Mdouble phi)
1234 {
1235  //CG_type_todo
1236  if (getCGShape() == Gaussian)
1237  {
1238  return Vec3D(0.0, (P.Y - Position.Y) * (phi / getCGWidthSquared()), 0.0);
1239  }
1240  else if (getCGShape() == Polynomial)
1241  {
1242  Mdouble r = fabs(Position.Y - P.Y) / getCGWidth();
1243  return Vec3D(0, getCGInverseVolume() * evaluatePolynomialGradient(r) / r / getCGWidthSquared() * (Position.Y - P.Y), 0);
1244  }
1245  else
1246  {
1247  std::cerr << "error in CG_gradient<Y>" << std::endl;
1248  exit(-1);
1249  }
1250 }
1251 template<> Vec3D StatisticsPoint<Z>::CG_gradient(const Vec3D &P, const Mdouble phi)
1252 {
1253  //CG_type_todo
1254  if (getCGShape() == Gaussian)
1255  {
1256  return Vec3D(0.0, 0.0, (P.Z - Position.Z) * (phi / getCGWidthSquared()));
1257  }
1258  else if (getCGShape() == Polynomial)
1259  {
1260  Mdouble r = fabs(Position.Z - P.Z) / getCGWidth();
1261  return Vec3D(0, 0, getCGInverseVolume() * evaluatePolynomialGradient(r) / r / getCGWidthSquared() * (Position.Z - P.Z));
1262  }
1263  else
1264  {
1265  std::cerr << "error in CG_gradient<Z>" << std::endl;
1266  exit(-1);
1267  }
1268 }
1269 
1271 {
1272  return Vec3D(0.0, 0.0, 0.0);
1273 }
1274 
1275 //~ template<> Vec3D StatisticsPoint<Z>::CG_integral_gradient(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance) {
1276 //~ Vec3D P_P1 = Position - P1;
1277 //~ Vec3D P_P2 = Position - P2;
1278 //~ Mdouble a = dot(P_P1,P1_P2_normal);
1279 //~ Mdouble b = dot(P_P2,P1_P2_normal);
1280 //~ Vec3D tangential = P_P1 - a * P1_P2_normal;
1281 //~ if (getCGShape()==Gaussian) {
1282 //~ Mdouble wsq2 = sqrt(2*getCGWidthSquared());
1283 //~ Mdouble f = sqrt(2*constants::pi*getCGWidthSquared());
1284 //~ return Vec3D(0.0,0.0,(exp(-mathsFunc::square(a/wsq2))-exp(-mathsFunc::square(b/wsq2)))/f/(P2.Z-P1.Z));
1285 //~ } else { std::cerr << "error in CG_function" << std::endl; exit(-1); }
1286 //~ }
1287 
1288 template<> Mdouble StatisticsPoint<RA>::CG_integral(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Vec3D& rpsi)
1289 {
1290  Mdouble rpsi_scalar;
1291  Mdouble psi = CG_integral_2D(P1, P2, P1_P2_normal, P1_P2_distance, rpsi_scalar);
1292  rpsi = Position * psi;
1293  return psi;
1294 }
1296 {
1297  Vec3D P=(P1+P2)/2; return CG_function(P);
1298 }
1300 {
1301  std::cerr << "error in CG_function<AZ>" << std::endl; exit(-1);
1302 }
1304 {
1305  Vec3D P=(P1+P2)/2; return CG_function(P);
1306 }
1308 {
1309  std::cerr << "error in CG_function<A>" << std::endl; exit(-1);
1310 }
1311 
1312 template<> Mdouble StatisticsPoint<XY>::CG_integral(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Vec3D& rpsi)
1313 {
1314  Mdouble rpsi_scalar = 0;
1315  Mdouble psi = CG_integral_2D(P1, P2, P1_P2_normal, P1_P2_distance, rpsi_scalar);
1316  rpsi = Vec3D(Position.X * psi, Position.Y * psi, P1.Z * psi - (P1.Z - P2.Z) * rpsi_scalar);
1317  return psi;
1318 }
1319 template<> Mdouble StatisticsPoint<XZ>::CG_integral(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Vec3D& rpsi)
1320 {
1321  Mdouble rpsi_scalar = 0;
1322  Mdouble psi = CG_integral_2D(P1, P2, P1_P2_normal, P1_P2_distance, rpsi_scalar);
1323  rpsi = Vec3D(Position.X * psi, P1.Y * psi - (P1.Y - P2.Y) * rpsi_scalar, Position.Z * psi);
1324  return psi;
1325 }
1326 template<> Mdouble StatisticsPoint<YZ>::CG_integral(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Vec3D& rpsi)
1327 {
1328  Mdouble rpsi_scalar = 0;
1329  Mdouble psi = CG_integral_2D(P1, P2, P1_P2_normal, P1_P2_distance, rpsi_scalar);
1330  rpsi = Vec3D(P1.X * psi - (P1.X - P2.X) * rpsi_scalar, Position.Y * psi, Position.Z * psi);
1331  return psi;
1332 }
1333 template<> Mdouble StatisticsPoint<X>::CG_integral(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Vec3D& rpsi)
1334 {
1335  Mdouble rpsi_scalar = 0;
1336  Mdouble psi = CG_integral_1D(P1, P2, P1_P2_normal, P1_P2_distance, rpsi_scalar);
1337  rpsi = Vec3D(Position.X * psi, P1.Y * psi - (P1.Y - P2.Y) * rpsi_scalar, P1.Z * psi - (P1.Z - P2.Z) * rpsi_scalar);
1338  return psi;
1339 }
1340 template<> Mdouble StatisticsPoint<Y>::CG_integral(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Vec3D& rpsi)
1341 {
1342  Mdouble rpsi_scalar = 0;
1343  Mdouble psi = CG_integral_1D(P1, P2, P1_P2_normal, P1_P2_distance, rpsi_scalar);
1344  rpsi = Vec3D(P1.X * psi - (P1.X - P2.X) * rpsi_scalar, Position.Y * psi, P1.Z * psi - (P1.Z - P2.Z) * rpsi_scalar);
1345  return psi;
1346 }
1347 template<> Mdouble StatisticsPoint<Z>::CG_integral(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Vec3D& rpsi)
1348 {
1349  Mdouble rpsi_scalar = 0;
1350  Mdouble psi = CG_integral_1D(P1, P2, P1_P2_normal, P1_P2_distance, rpsi_scalar);
1351  rpsi = Vec3D(P1.X * psi - (P1.X - P2.X) * rpsi_scalar, P1.Y * psi - (P1.Y - P2.Y) * rpsi_scalar, Position.Z * psi);
1352  return psi;
1353 }
1354 template<> Mdouble StatisticsPoint<O>::CG_integral(Vec3D &P1, Vec3D &P2 UNUSED, Vec3D &P1_P2_normal UNUSED, Mdouble P1_P2_distance UNUSED, Vec3D& rpsi)
1355 {
1356  Mdouble psi = getCGInverseVolume();
1357  rpsi=P1*psi;
1358  return psi;
1359 }
1360 
1361 template<> Vec3D StatisticsPoint<Z>::CG_integral_gradient(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance)
1362 {
1363  return Vec3D(0, 0, CG_integral_gradient_1D(P1, P2, P1_P2_normal, P1_P2_distance));
1364 }
1365 
1367 template<StatType T> std::ostream& operator<<(std::ostream& os, const StatisticsPoint<T> &stat)
1368 {
1369  os.precision(16);
1370  if (stat.mirrorParticle < 0)
1371  {
1372  //only write std particles, not mirrored particles
1373  os << stat.getPosition() << " " << stat.write() << std::endl;
1374  }
1375  return os;
1376 }
1377 
1378 template<> std::ostream& operator<<(std::ostream& os, const StatisticsPoint<RAZ> &stat)
1379 {
1380  os.precision(16);
1381  if (stat.mirrorParticle < 0)
1382  os << stat.getPosition().getCylindricalCoordinates() << " " << stat.write() << std::endl;
1383  return os;
1384 }
1385 template<> std::ostream& operator<<(std::ostream& os, const StatisticsPoint<RA> &stat)
1386 {
1387  os.precision(16);
1388  if (stat.mirrorParticle < 0)
1389  os << stat.getPosition().getCylindricalCoordinates() << " " << stat.write() << std::endl;
1390  return os;
1391 }
1392 template<> std::ostream& operator<<(std::ostream& os, const StatisticsPoint<RZ> &stat)
1393 {
1394  os.precision(16);
1395  if (stat.mirrorParticle < 0)
1396  os << stat.getPosition().getCylindricalCoordinates() << " " << stat.write() << std::endl;
1397  return os;
1398 }
1399 template<> std::ostream& operator<<(std::ostream& os, const StatisticsPoint<AZ> &stat)
1400 {
1401  os.precision(16);
1402  if (stat.mirrorParticle < 0)
1403  os << stat.getPosition().getCylindricalCoordinates() << " " << stat.write() << std::endl;
1404  return os;
1405 }
1406 template<> std::ostream& operator<<(std::ostream& os, const StatisticsPoint<R> &stat)
1407 {
1408  os.precision(16);
1409  if (stat.mirrorParticle < 0)
1410  os << stat.getPosition().getCylindricalCoordinates() << " " << stat.write() << std::endl;
1411  return os;
1412 }
1413 template<> std::ostream& operator<<(std::ostream& os, const StatisticsPoint<A> &stat)
1414 {
1415  os.precision(16);
1416  if (stat.mirrorParticle < 0)
1417  os << stat.getPosition().getCylindricalCoordinates() << " " << stat.write() << std::endl;
1418  return os;
1419 }
1420 
1422 {
1423  return mathsFunc::square(P.X - Position.X) + mathsFunc::square(P.Y - Position.Y);
1424 }
1426 {
1427  return mathsFunc::square(P.X - Position.X) + mathsFunc::square(P.Z - Position.Z);
1428 }
1430 {
1431  return mathsFunc::square(P.Y - Position.Y) + mathsFunc::square(P.Z - Position.Z);
1432 }
1434 {
1435  return mathsFunc::square(P.X - Position.X);
1436 }
1438 {
1439  return mathsFunc::square(P.Y - Position.Y);
1440 }
1442 {
1443  return mathsFunc::square(P.Z - Position.Z);
1444 }
1446 {
1447  return 0;
1448 }
1449 
1451 {
1452  return P.X * Q.X + P.Y * Q.Y;
1453 }
1455 {
1456  return P.X * Q.X + P.Z * Q.Z;
1457 }
1459 {
1460  return P.Y * Q.Y + P.Z * Q.Z;
1461 }
1463 {
1464  return P.X * Q.X;
1465 }
1467 {
1468  return P.Y * Q.Y;
1469 }
1471 {
1472  return P.Z * Q.Z;
1473 }
1475 {
1476  return 0;
1477 }
1478 
1480 {
1481  return P;
1482 }
1484 {
1485  return Vec3D(P.X, P.Y, 0);
1486 }
1488 {
1489  return Vec3D(P.X, 0, P.Z);
1490 }
1492 {
1493  return Vec3D(0, P.Y, P.Z);
1494 }
1496 {
1497  return Vec3D(P.X, 0, 0);
1498 }
1500 {
1501  return Vec3D(0, P.Y, 0);
1502 }
1504 {
1505  return Vec3D(0, 0, P.Z);
1506 }
1508 {
1509  return Vec3D(0, 0, 0);
1510 }
1511 
1513 {
1514  return Vec3D(0, 0, P.X * Q.Y - P.Y * Q.X);
1515 }
1517 {
1518  return Vec3D(0, P.Z * Q.X - P.X * Q.Z, 0);
1519 }
1521 {
1522  return Vec3D(P.Y * Q.Z - P.Z * Q.Y, 0, 0);
1523 }
1525 { return Vec3D(0,0,0);}
1527 { return Vec3D(0,0,0);}
1529 { return Vec3D(0,0,0);}
1531 { return Vec3D(0,0,0);}
1532 
1534 {
1535  return Matrix3D(
1536  0, 0, P.X * Q.YX - P.Y * Q.XX,
1537  0, 0, P.X * Q.YY - P.Y * Q.XY,
1538  0, 0, P.X * Q.YZ - P.Y * Q.XZ);
1539 }
1541 {
1542  return Matrix3D(
1543  0, P.Z * Q.XX - P.X * Q.ZX, 0,
1544  0, P.Z * Q.XY - P.X * Q.ZY, 0,
1545  0, P.Z * Q.XZ - P.X * Q.ZZ, 0);
1546 }
1548 {
1549  return Matrix3D(
1550  P.Y * Q.ZX - P.Z * Q.YX, 0, 0,
1551  P.Y * Q.ZY - P.Z * Q.YY, 0, 0,
1552  P.Y * Q.ZZ - P.Z * Q.YZ, 0, 0);
1553 }
1555 {
1556  return Matrix3D(0,0,0,0,0,0,0,0,0);
1557 }
1559 {
1560  return Matrix3D(0,0,0,0,0,0,0,0,0);
1561 }
1563 {
1564  return Matrix3D(0,0,0,0,0,0,0,0,0);
1565 }
1567 {
1568  return Matrix3D(0,0,0,0,0,0,0,0,0);
1569 }
1570 
Mdouble XY
Definition: Matrix.h:42
Vec3D crossNonAveraged(Vec3D P, Vec3D &Q)
Returns the cross product of two vectors in the coordinates that are not averaged about...
Mdouble CG_function(const Vec3D &PI)
Returns the value of the course graining function phi(P,PI)
static MatrixSymmetric3D square(const MatrixSymmetric3D &A)
Calculates the pointwise square.
Mdouble CG_invvolume
Prefactor of CG function which depends on $w.
MatrixSymmetric3D DisplacementMomentumFlux
Momentum flux from linear displacement, .
Mdouble X
the vector components
Definition: Vector.h:52
Mdouble evaluatePolynomial(Mdouble r)
see StatisticsVector::evaluatePolynomial
Mdouble ZY
Definition: Matrix.h:42
Matrix3D ContactCoupleStress
Mdouble Dissipation
Dissipation form collisions, .
Mdouble CG_function_1D(const Vec3D &PI)
Returns the value of the course graining function phi(P,PI) averaged along a plane.
Mdouble XZ
Definition: Matrix.h:42
Mdouble ZX
Definition: Matrix.h:42
const Mdouble sqrt_pi
Definition: ExtendedMath.h:43
Vec3D CG_integral_gradient(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance)
gradient of phi
Mdouble CG_function_2D(const Vec3D &PI)
returns the value of the course graining function phi(P,PI) averaged along a line ...
void firstTimeAverage(const int n)
Defines a division operator needed to time-average values (because the displacement does not have a v...
Mdouble evaluateIntegral(Mdouble n1, Mdouble n2, Mdouble t)
see StatisticsVector::evaluateIntegral
void setZero()
Sets all elements to zero.
Definition: Vector.cc:52
std::ostream & operator<<(std::ostream &os, const CG S)
static Vec3D sqrt(const Vec3D &a)
Calculates the pointwise square root of a Vec3D.
Definition: Vector.cc:256
void set_Gaussian_invvolume(int dim)
sets CG_invvolume if CG_type=Gaussian
Matrix3D NormalStress
Stress from normal forces, .
Mdouble getCGWidth() const
see StatisticsVector::getCGWidth
static Vec3D square(const Vec3D &a)
Calculates the pointwise square of a Vec3D.
Definition: Vector.cc:225
Matrix3D matrixCrossNonAveraged(Vec3D P, Matrix3D &Q)
Returns the cross product of two vectors in the coordinates that are not averaged about...
Mdouble ZZ
Definition: Matrix.h:42
T square(T val)
squares a number
Definition: ExtendedMath.h:91
Mdouble getLengthSquared() const
Calculates the squared length of this Vec3D: .
Definition: Vector.cc:313
static Mdouble getLength(const Vec3D &a)
Calculates the length of a Vec3D: .
Definition: Vector.cc:427
Mdouble YZ
Definition: Matrix.h:42
void set_Heaviside_invvolume()
sets CG_invvolume if CG_type=HeaviSideSphere
Vec3D CollisionalHeatFlux
Heat flux from collisions, .
std::string write_variable_names()
Outputs names of statistical variables in computer-readable format.
CG
enum used to store the type of coarse-graining function used
Mdouble Nu
Particle volume fraction, .
Vec3D NormalTraction
Traction from normal forces, .
Mdouble getCutoff()
see StatisticsVector::getCutoff
Mdouble CG_integral_2D(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Mdouble &rpsi_scalar)
Returns the value of the coarse graining integral averaged along a line.
Vec3D DisplacementMomentum
Momentum from linear displacement, , where , with the time intervall between outputs.
MatrixSymmetric3D Fabric
Fabric tensor, .
void setCGInverseVolume()
sets CG_invvolume
std::string print() const
Outputs statistical variables in human-readable format.
Vec3D CG_gradient(const Vec3D &P, const Mdouble phi)
gradient of phi
double averagingVolume()
Vec3D EnergyFlux
Energy flux, .
Mdouble Density
Density, .
const Mdouble pi
Definition: ExtendedMath.h:42
MatrixSymmetric3D Displacement
Linear displacement, .
std::string write() const
Outputs statistical variables in computer-readable format.
void set_zero()
Sets all statistical variables to zero.
void setZero()
Sets all elements to zero.
Mdouble YX
Definition: Matrix.h:42
#define UNUSED
Definition: GeneralDefine.h:37
Mdouble getCutoff2()
see StatisticsVector::getCutoff2
T cubic(T val)
calculates the cube of a number
Definition: ExtendedMath.h:99
StatisticsPoint< T > & operator+=(const StatisticsPoint< T > &P)
Defines a plus operator needed to average values ( )
const Mdouble sqrt_2
Definition: ExtendedMath.h:45
StatisticsPoint< T > & operator/=(const Mdouble a)
Defines a division operator needed to average values ( )
Vec3D TangentialTraction
Traction from tangential forces, .
Mdouble getCGWidthSquared() const
see StatisticsVector::getCGWidthSquared
Matrix3D LocalAngularMomentumFlux
Mdouble dotNonAveraged(const Vec3D &P, const Vec3D &Q)
Returns the dot product of two vectors in the coordinates that are not averaged about.
Mdouble Y
Definition: Vector.h:52
StatisticsPoint< T > & operator=(const StatisticsPoint< T > &P)
Defines a equal operator needed for copy constructor.
Vec3D clearAveragedDirections(Vec3D P)
Returns a vector where the averaged directions are zero.
static Matrix3D sqrt(const Matrix3D &A)
Calculates the pointwise square root.
Definition: Matrix.cc:272
Mdouble Potential
Elastic energy .
Mdouble CG_integral_gradient_1D(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance)
Mdouble getLength() const
Calculates the length of this Vec3D: .
Definition: Vector.cc:416
This class stores statistical values for a given spatial position; to be used in combination with Sta...
MatrixSymmetric3D MomentumFlux
Momentum flux, .
Mdouble XX
all nine matrix elements
Definition: Matrix.h:42
void setZero()
Sets all elements to zero.
Definition: Matrix.cc:58
StatisticsPoint< T > & operator-=(const StatisticsPoint< T > &P)
Defines a plus operator needed to calculate variance.
This class is used to extract statistical data from MD simulations.
Mdouble getCGInverseVolume()
returns CG_invvolume
StatisticsPoint< T > getSquared()
Squares all statistical variables; needed for variance.
double compute_Gaussian_invvolume(int dim)
computes CG_invvolume if CG_type=Gaussian
Mdouble CG_integral(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Vec3D &rpsi)
Returns the value of the coarse graining integral .
Mdouble I0(Mdouble x)
Mdouble YY
Definition: Matrix.h:42
Implementation of a 3D matrix.
Definition: Matrix.h:36
Implementation of a 3D vector (by Vitaliy).
Definition: Vector.h:45
Vec3D Momentum
Momentum, .
static MatrixSymmetric3D sqrt(const MatrixSymmetric3D &A)
Calculates the pointwise square root.
Vec3D Position
Position at which evaluation occurs.
Mdouble Z
Definition: Vector.h:52
Mdouble CG_integral_1D(Vec3D &P1, Vec3D &P2, Vec3D &P1_P2_normal, Mdouble P1_P2_distance, Mdouble &rpsi_scalar)
Returns the value of the coarse graining integral averaged along a plane.
static StatisticsVector< T > * gb
Pointer to StatisticsVector (to obtain global parameters)
Mdouble evaluatePolynomialGradient(Mdouble r)
see StatisticsVector::evaluatePolynomialGradient
void set_Polynomial_invvolume(int dim)
sets CG_invvolume if CG_type=Polynomial
static Matrix3D square(const Matrix3D &A)
Calculates the pointwise square.
Definition: Matrix.cc:260
std::string print_sqrt() const
Outputs root of statistical variables in human-readable format.
CG getCGShape() const
see StatisticsVector::getCGShape
Matrix3D TangentialStress
Stress from tangential forces, .
Mdouble getDistanceSquaredNonAveraged(const Vec3D &P)
returns the coarse graining distance in the coordinates that are not averaged about ...