NDDEM
Tools.h
Go to the documentation of this file.
1 
5 #ifndef TOOLS
6 #define TOOLS
7 #include <cstdlib>
8 #include <cmath>
9 #include <cstdio>
10 #include <vector>
11 #include <cmath>
12 #include <initializer_list>
13 #include "Typedefs.h"
14 #include "Parameters.h"
15 
16 
17 #include <boost/math/special_functions/factorials.hpp>
18 #include <boost/random.hpp>
19 
20 #define MAXDEFDIM 30
21 
22 
23 v1d operator* (v1d a, double b) ;
24 v1f operator* (v1f a, float b) ;
25 v1d operator* (v1d a, cv1d &b) ;
26 v1f operator* (v1f a, cv1f &b) ;
27 v1d operator+ (v1d a, double b) ;
28 v1d operator+ (v1d a, cv1d &b) ;
29 v1f operator+ (v1f a, cv1f &b) ;
30 v1d operator- (v1d a, double b) ;
31 v1d operator- (v1d a, cv1d &b) ;
32 v1f operator- (v1f a, cv1f &b) ;
33 v1d operator- (v1d a, const double * b) ;
34 v1d operator- (const double * a, v1d b) ;
36 v1d operator/ (v1d a, double b) ;
37 v1d & operator-= (v1d & a, cv1d &b) ;
38 v1d & operator*= (v1d & a, double b);
39 v1f & operator*= (v1f & a, double b);
40 v1d & operator+= (v1d & a, cv1d &b) ;
41 v1f & operator+= (v1f & a, cv1f &b) ;
42 v1f & operator/= (v1f & a, cv1f &b) ;
43 v1d & operator/= (v1d & a, double b) ;
44 v1f & operator/= (v1f & a, double b) ;
45 
50 {
51 public :
52  string name ;
54  v2d * data ;
55 } ;
56 
57 
59 class Tools_2D
60 {
61 public:
62  static std::tuple<double,double> contact_ellipse_disk (std::vector<double> & X,
63  double a, double b, double cx, double cy, //Ellipse parameters
64  double gamma=0.1, double tol=1e-5)
65  {
66  auto d0=[&](double u){return sqrt((X[0]-cx-a*cos(u))*(X[0]-cx-a*cos(u))+(X[1]-cy-b*sin(u))*(X[1]-cy-b*sin(u)));} ;
67  auto d1=[&](double u){return (2*a*(X[0]-cx-a*cos(u))*sin(u)-2*b*cos(u)*(X[1]-cy-b*sin(u)));} ;
68  //d2=@(u) (-(-b*cos(u))*(2*b*cos(u))+cos(u)*(2*a*(x-cx-a*cos(u)))+(a*sin(u))*(2*a*sin(u))--sin(u)*(2*b*(y-cy-b*sin(u)))) ;
69 
70  //Gradient descent
71  int n=0 ; double delta=1 ;
72  double to=atan2(X[1]-cy,X[0]-cx), tn ;
73  while (delta>tol)
74  {
75  tn= to - gamma * d1(to) ;
76  delta=fabs(tn-to) ;
77  to=tn ;
78  n++ ;
79  if (n>1000) {printf("ERR: maximum number of iteration reached in gradient descent. gradientdescent_gamma is probably too large\n") ; break ;}
80  }
81 
82  return {to, d0(to)} ;
83  }
84 
85 } ;
86 
87 
88 
99 template <int d>
100 class Tools
101 {
102 public:
105 static void initialise () ;
106 static void clear() ;
107 static bool check_initialised (int dd) {return (dd==d) ; }
108 static int sgn (uint8_t a) {return a & (128) ? -1:1 ; }
109 static int sgn (double a) {return a<0 ? -1:1 ; }
110 static std::pair <double, double> two_max_element (cv1d & v) ;
112 
115 static void unitvec (vector <double> & v, int n) ;
116 static v1d unitvec (int n) {v1d res (d,0) ; res[n]=1 ; return res ; }
117 static void setzero(v2d & a) {for (uint i=0 ; i<a.size() ; i++) for (uint j=0 ; j<a[0].size() ; j++) a[i][j]=0 ; }
118 static void setzero(v1d & a) {for (uint i=0 ; i<a.size() ; i++) a[i]=0 ; }
119 static double norm (const vector <double> & a) {double res=0 ; for (uint i=0 ; i<a.size() ; i++) res+=a[i]*a[i] ; return (sqrt(res)) ; }
120 static void norm (v1d & res, cv2d & a) {for (uint i=0 ; i<a.size() ; i++) res[i] = norm(a[i]) ; }
121 static double normdiff (cv1d & a, cv1d & b) {double res=0 ; for (int i=0 ; i<d ; i++) res+=(a[i]-b[i])*(a[i]-b[i]) ; return (sqrt(res)) ; }
122 static double normsq (const vector <double> & a) {double res=0 ; for (int i=0 ; i<d ; i++) res+=a[i]*a[i] ; return (res) ; }
123 static double normdiffsq (cv1d & a, cv1d & b) {double res=0 ; for (int i=0 ; i<d ; i++) res+=(a[i]-b[i])*(a[i]-b[i]) ; return (res) ; }
124 static void orthonormalise (v1d & A) ;
125 static double skewnorm (cv1d & a) {double res=0 ; for (int i=0 ; i<d*(d-1)/2 ; i++) res+=a[i]*a[i] ; return (sqrt(res)) ; }
126 static double skewnormsq (cv1d & a) {double res=0 ; for (int i=0 ; i<d*(d-1)/2 ; i++) res+=a[i]*a[i] ; return (res) ; }
127 static double dot (cv1d & a, cv1d & b) {double res=0; for (int i=0 ; i<d ; i++) res+=a[i]*b[i] ; return (res) ; }
128 static v1f vsqrt (cv1f & a) {v1f b=a ; for (uint i=0 ; i<a.size() ; i++) b[i]=sqrt(a[i]) ; return b ; }
129 static v1f vsq (cv1f & a) {v1f b=a ; for (uint i=0 ; i<a.size() ; i++) b[i]=a[i]*a[i] ; return b ; }
130 
131 static void surfacevelocity (v1d &res, cv1d &p, double * com, double * vel_com, double * omega_com)
132 {
133  if (vel_com == nullptr && omega_com == nullptr)
134  {
135  res.resize(d) ; setzero(res) ;
136  }
137  else if (omega_com == nullptr)
138  for (int dd=0 ; dd<d ; dd++)
139  res[dd] = vel_com[dd] ;
140  else if (vel_com == nullptr)
141  {
142  skewmatvecmult(res, omega_com, p-com) ;
143  //printf("{%g %g %g %g %g}", omega_com[0], (p-com)[0], (p-com)[1], res[0], res[1]) ;
144  }
145  else
146  {
147  skewmatvecmult(res, omega_com, p-com) ;
148  for (int dd=0 ; dd<d ; dd++)
149  res[dd] = vel_com[dd] - res[dd] ;
150  }
151 }
152 
153 
154 static void setgravity(v2d & a, v1d &g, v1d &m) {for (uint i=0 ; i<a.size() ; i++) a[i]=g*m[i] ; }
155 static v1d randomize_vec (cv1d v) ;
157 
160 static double hyperspherical_xtophi (cv1d &x, v1d &phi) ;
161 static void hyperspherical_phitox (double r, cv1d &phi, v1d &x) ;
163 
166 static double Volume (double R) ;
167 static double InertiaMomentum (double R, double rho) ;
169 
170 
175 static void vMul (v1d & res, cv1d &a, double b) {for (uint i=0 ; i<a.size() ; i++) res[i]=a[i]*b ; }
176 static void vMul (v1d & res, cv1d &a, cv1d & b) {for (uint i=0 ; i<a.size() ; i++) res[i]=a[i]*b[i] ; }
177 static void vMinus (v1d & res, cv1d &a, cv1d & b) {for (uint i=0 ; i<a.size() ; i++) res[i]=a[i]-b[i] ; }
178 static void vPlus (v1d & res, cv1d &a, double b) {for (uint i=0 ; i<a.size() ; i++) res[i]=a[i]+b ; }
179 static void vPlus (v1d & res, cv1d &a, cv1d & b) {for (uint i=0 ; i<a.size() ; i++) res[i]=a[i]+b[i] ; }
180 static void vDiv (v1d & res, cv1d &a, double b) {for (uint i=0 ; i<a.size() ; i++) res[i]=a[i]/b ; }
181 static void vDiv (v1d & res, cv1d &a, cv1d & b) {for (uint i=0 ; i<a.size() ; i++) res[i]=a[i]/b[i] ; }
182 static void vAddFew (v1d &res , cv1d &a, cv1d &b) {for (uint i=0 ; i<a.size() ; i++) res[i] += a[i]+b[i] ; }
183 static void vAddScaled (v1d &res , double v, cv1d &a, cv1d &b) {for (uint i=0 ; i<a.size() ; i++) res[i] += v*(a[i]+b[i]) ; }
184 static void vAddScaled (v1d &res , double v, cv1d &a) {for (uint i=0 ; i<a.size() ; i++) res[i] += v*a[i] ; }
185 static void vSubFew (v1d &res , cv1d &a, cv1d &b) {for (uint i=0 ; i<a.size() ; i++) res[i] -= (a[i]+b[i]) ; }
186 static void vSubScaled (v1d &res , double v, cv1d &a) {for (uint i=0 ; i<a.size() ; i++) res[i] -= v*a[i] ; }
188 
193 static void vAddFew (v1d & res, cv1d &a, cv1d &b, v1d & Corr)
194 {
195  double Tmp, Previous ;
196 
197  for (uint i=0 ; i<a.size() ; i++)
198  {
199  Tmp=(a[i]+b[i])-Corr[i] ;
200  Previous=res[i] ;
201  res[i] += Tmp ;
202  Corr[i] = (res[i]-Previous)-Tmp ;
203  }
204 }
205 static void vSubFew (v1d & res, cv1d &a, cv1d &b, v1d & Corr)
206 {
207  double Tmp, Previous ;
208 
209  for (uint i=0 ; i<a.size() ; i++)
210  {
211  Tmp=(-a[i]-b[i])-Corr[i] ;
212  Previous=res[i] ;
213  res[i] += Tmp ;
214  Corr[i] = (res[i]-Previous)-Tmp ;
215  }
216 }
217 static void vAddOne (v1d & res, cv1d &a, v1d & Corr)
218 {
219  double Tmp, Previous ;
220 
221  for (uint i=0 ; i<a.size() ; i++)
222  {
223  Tmp=a[i]-Corr[i] ;
224  Previous=res[i] ;
225  res[i] += Tmp ;
226  Corr[i] = (res[i]-Previous)-Tmp ;
227  }
228 }
229 static void vSubOne (v1d & res, cv1d &a, v1d & Corr)
230 {
231  double Tmp, Previous ;
232 
233  for (uint i=0 ; i<a.size() ; i++)
234  {
235  Tmp=-a[i]-Corr[i] ;
236  Previous=res[i] ;
237  res[i] += Tmp ;
238  Corr[i] = (res[i]-Previous)-Tmp ;
239  }
240 }
242 
245 static v1d skewmatvecmult (cv1d & M, cv1d &v) ;
246 static v1d skewmatvecmult (const double * M, cv1d &v) ;
247 static void skewmatvecmult (v1d & r, cv1d & M, cv1d &v) ;
248 static void skewmatvecmult (v1d & r, const double * M, cv1d &v) ;
249 static v1d skewmatsquare (cv1d &A) ;
250 static void skewmatsquare (v1d &r, cv1d &A) ;
251 static v1d skewexpand (cv1d &A) ;
252 static void skewexpand (v1d & r, cv1d &A) ;
253 static v1d matmult (cv1d &A, cv1d &B) ;
254 static void matmult (v1d &r, cv1d &A, cv1d &B) ;
255 static void matvecmult (v1d & res, cv1d &A, cv1d &B) ;
256 static v1d wedgeproduct (cv1d &a, cv1d &b) ;
257 static void wedgeproduct (v1d &res, cv1d &a, cv1d &b) ;
258 static v1d transpose (cv1d & a) {v1d b (d*d,0) ; for (int i=0 ; i<d*d ; i++) b[(i/d)*d+i%d] = a[(i%d)*d+(i/d)] ; return b ; }
259 static void transpose_inplace (v1d & a) { for (int i=0 ; i<d ; i++) for (int j=i+1 ; j<d ; j++) std::swap(a[i*d+j], a[j*d+i]) ; }
260 static double det (cv2d & M) ;
261 static double det (cv1d & M) ;
262 static double det (double M[d][d]) ;
263 static v1d inverse (cv1d & M) ;
265 
268 static int savetxt(char path[], const v2d & table, char const header[]) ;
269 static void savecsv (char path[], cv2d & X, cv1d &r, const vector <uint32_t> & PBCFlags, cv1d & Vmag, cv1d & OmegaMag, [[maybe_unused]] cv1d & Z) ;
270 static void savecsv (char path[], cv2d & X, cv2d & V, cv1d &r, const vector <uint32_t> & PBCFlags, cv1d & Vmag, cv1d & OmegaMag, [[maybe_unused]] cv1d & Z) ;
271 static void savecsv (char path[], cv2d & A) ;
272 static void savevtk (char path[], int N, cv2d & Boundaries, cv2d & X, cv1d & r, vector <TensorInfos> data) ;
273 
274 static void print (cv1d M) {printf("[") ; if (M.size()==d*d) for (int i=0 ; i<d ; i++) { for (int j=0 ; j<d ; j++) printf("%g ", M[i*d+j]) ; printf("\n") ; } else for (auto v: M) printf("%g ", v) ; printf("]") ; }
275 
276 static int write1D (char path[], v1d table) ;
277 static int writeinline(initializer_list< v1d >) ;
278 static int writeinline_close(void) ;
280 
281 static v1d Eye ;
282 static boost::random::mt19937 rng ;
283 static boost::random::uniform_01<boost::mt19937> rand ;
284 
285 static int getdim (void) {return d;}
286 
287 static vector < pair <int,int> > MASIndex ;
288 
289 private:
290 static vector < vector <int> > MSigns ;
291 static vector < vector <int> > MIndexAS ;
292 static vector <FILE *> outs ;
293 
294 } ;
295 
296 // Static member definitions ---------------------------------------------------
297 template <int d> vector < vector <int> > Tools<d>::MSigns ;
298 template <int d> vector < vector <int> > Tools<d>::MIndexAS ;
299 template <int d> vector < pair <int,int> > Tools<d>::MASIndex;
300 template <int d> vector < double > Tools<d>::Eye ;
301 template <int d> vector <FILE *> Tools<d>::outs ;
302 template <int d> boost::random::mt19937 Tools<d>::rng ;
303 template <int d> boost::random::uniform_01<boost::mt19937> Tools<d>::rand(rng) ;
304 
305 
306 /*****************************************************************************************************
307  * *
308  * *
309  * *
310  * IMPLEMENTATIONS *
311  * *
312  * *
313  * *
314  * ***************************************************************************************************/
315 
316 
317 template <int d>
319 {
320  MSigns.resize(d, vector <int> (d, 0)) ;
321  for (int i=0 ; i<d ; i++) for (int j=0 ; j<d ; j++) MSigns[i][j]=(i<j)*(1)+(i>j)*(-1) ;
322 
323  MIndexAS.resize(d, vector < int > (d,0)) ;
324  MASIndex.resize(d*(d-1)/2, make_pair(0,0)) ;
325  int n=0 ;
326  for (int i=0 ; i<d ; i++)
327  for (int j=i+1 ; j<d ; j++,n++)
328  {
329  MIndexAS[i][j]=n ; MIndexAS[j][i]=n ;
330  MASIndex[n]=make_pair(i,j) ;
331  //MASIndex.push_back(make_pair(i, j)) ;
332  }
333 
334  Eye.clear() ; Eye.resize(d*d,0) ;
335  for (int de=0 ; de<d ; de++) Eye[de*d+de]=1 ; //initial orientation matrix
336 }
337 //===================================
338 template <int d>
340 {
341  MSigns.clear() ;
342  MIndexAS.clear() ;
343  MASIndex.clear() ;
344  Eye.clear() ;
345 }
346 
347 //===================================
348 template <int d>
349 int Tools<d>::savetxt(char path[], const v2d & table, char const header[])
350 {
351  FILE * out ;
352  out = fopen(path, "w") ; if (out==NULL) {printf("ERR: cannot write in file %s\n", path) ; return 1 ; }
353  fprintf(out, "%s\n", header) ;
354  for (uint i=0 ; i<table.size() ; i++)
355  {
356  for (uint j=0 ; j<table[i].size() ; j++)
357  {
358  fprintf(out, "%.6g",table[i][j]) ;
359  if (j<table[i].size()-1) fprintf(out, ",") ;
360  }
361  if (i<table.size()-1) fprintf(out, "\n") ;
362  }
363  fclose(out) ;
364  return 0 ;
365 }
366 //=======================================
367 template <int d>
368 int Tools<d>::write1D (char path[], v1d table)
369 {
370  FILE * out ;
371  out = fopen(path, "w") ; if (out==NULL) {printf("ERR: cannot write in file %s\n", path) ; return 1 ; }
372  for (uint i=0 ; i<table.size() ; i++)
373  fprintf(out, "%g\n", table[i]) ;
374  fclose(out) ;
375 return 0 ;
376 }
377 
378 //=====================================
379 template <int d>
380 void Tools<d>::savecsv (char path[], cv2d & X, cv1d &r, const vector <uint32_t> & PBCFlags, cv1d & Vmag, cv1d & OmegaMag, [[maybe_unused]] cv1d & Z )
381 {
382  FILE *out ; int dim ;
383  out=fopen(path, "w") ; if (out==NULL) {printf("Cannot open out file\n") ; return ;}
384  dim = X[0].size() ;
385  for (int i=0 ; i<dim ; i++) fprintf(out, "x%d,", i);
386  fprintf(out, "R,PBCFlags,Vmag,Omegamag\n") ;
387  for (uint i=0 ; i<X.size() ; i++)
388  {
389  for (int j=0 ; j<dim ; j++)
390  fprintf(out, "%.6g,", X[i][j]) ;
391  fprintf(out, "%g,%d,%g,%g\n", r[i],PBCFlags[i], Vmag[i], OmegaMag[i]) ;
392  }
393  fclose(out) ;
394 }
395 //=====================================
396 template <int d>
397 void Tools<d>::savecsv (char path[], cv2d & X, cv2d & V, cv1d &r, const vector <uint32_t> & PBCFlags, cv1d & Vmag, cv1d & OmegaMag, [[maybe_unused]] cv1d & Z )
398 {
399  FILE *out ; int dim ;
400  out=fopen(path, "w") ; if (out==NULL) {printf("Cannot open out file\n") ; return ;}
401  dim = X[0].size() ;
402  for (int i=0 ; i<dim ; i++) fprintf(out, "x%d,", i);
403  for (int i=0 ; i<dim ; i++) fprintf(out, "v%d,", i);
404  fprintf(out, "R,PBCFlags,Vmag,Omegamag\n") ;
405  for (uint i=0 ; i<X.size() ; i++)
406  {
407  for (int j=0 ; j<dim ; j++) fprintf(out, "%.6g,", X[i][j]) ;
408  for (int j=0 ; j<dim ; j++) fprintf(out, "%.6g,", V[i][j]) ;
409  fprintf(out, "%g,%d,%g,%g\n", r[i],PBCFlags[i], Vmag[i], OmegaMag[i]) ;
410  }
411  fclose(out) ;
412 }
413 //-----------------------------------------
414 template <int d>
415 void Tools<d>::savecsv (char path[], cv2d & A)
416 {
417  FILE *out ; int dim ;
418  out=fopen(path, "w") ; if (out==NULL) {printf("Cannot open out file\n") ; return ;}
419  dim = A[0].size() ;
420  for (int i=0 ; i<dim-1 ; i++) fprintf(out, "x%d,", i);
421  fprintf(out, "x%d\n", dim-1) ;
422  for (uint i=0 ; i<A.size() ; i++)
423  {
424  for (int j=0 ; j<dim-1 ; j++)
425  fprintf(out, "%.6g,", A[i][j]) ;
426  fprintf(out, "%.6g", A[i][dim-1]) ;
427  fprintf(out, "\n") ;
428  }
429  fclose(out) ;
430 }
431 //=====================================
432 template <int d>
433 void Tools<d>::savevtk (char path[], int N, cv2d & Boundaries, cv2d & X, cv1d & r, vector <TensorInfos> data)
434 {
435  FILE *out ; static bool warn = false ;
436 
437  vector <float> projectioncenter ; for (int i=3 ; i<d ; i++) projectioncenter.push_back((Boundaries[i][1]+Boundaries[i][0])/2) ;
438 
439  out=fopen(path, "w") ; if (out==NULL) {printf("Cannot open out file\n") ; return ;}
440 
441  if (d>3 && warn==false) {
442  printf("WARN: writevtk might misbehave with dimension higher than 3. The 3d projection is always centered in all other dimensions\n") ;
443  warn=true ;
444  }
445  fprintf(out, "# vtk DataFile Version 2.0\nMost Useless DEM (tm) output file\nASCII\nDATASET POLYDATA\n") ;
446 
447  fprintf(out, "POINTS %ld float\n", X.size()) ;
448  for (uint i=0 ; i<X.size() ; i++) fprintf(out, "%g %g %g\n", X[i][0], X[i][1], d<3?0:X[i][2]) ;
449  fprintf(out, "VERTICES %ld %ld\n", X.size(), 2*X.size()) ;
450  for (uint i=0 ; i<X.size() ; i++) fprintf(out, "1 %d\n", i) ;
451 
452  fprintf(out, "\nPOINT_DATA %ld", X.size()) ;
453 
454  for (uint j=3 ; j<X[0].size() ; j++)
455  {
456  fprintf(out, "\nSCALARS Dimension%d float 1 \nLOOKUP_TABLE default \n", j) ;
457  for (uint i=0 ; i<X.size() ; i++)
458  fprintf(out, "%g ", X[i][j]) ;
459  }
460 
461  fprintf(out, "\n\nSCALARS RadiusProjected float 1 \nLOOKUP_TABLE default\n");
462  for (int i=0 ; i<N ; i++)
463  {
464  float value = r[i]*r[i] ;
465  for (int j=3 ; j<d ; j++) value-=(X[i][j]-projectioncenter[j-3])*(X[i][j]-projectioncenter[j-3]) ;
466  if (value<0) fprintf(out, "%g ", 0.0) ;
467  else fprintf(out, "%g ", sqrt(value)) ;
468  }
469 
470  for (auto v : data)
471  {
472  switch (v.order) {
473  case TensorType::SCALAR: fprintf(out, "\nSCALARS %s double 1 \nLOOKUP_TABLE default \n", v.name.c_str()) ;//scalar
474  for (uint i=0 ; i<(*v.data)[0].size() ; i++)
475  fprintf(out, "%g ", (*v.data)[0][i]) ;
476  break ;
477  case TensorType::VECTOR: fprintf(out, "\nVECTORS %s double \n", v.name.c_str()) ;//vector
478  for (auto i : (*v.data))
479  fprintf(out, "%g %g %g\n", i[0], i[1], i[2]) ;
480  break ;
481  case TensorType::TENSOR: fprintf(out, "\nTENSORS %s double \n", v.name.c_str()) ;//tensor
482  for (auto i : (*v.data))
483  fprintf(out, "%g %g %g %g %g %g %g %g %g\n", i[0], i[1], i[2], i[d], i[d+1], i[d+2], i[2*d], i[2*d+1], i[2*d+2]) ;
484  break ;
485  case TensorType::SYMTENSOR: fprintf(out, "\nTENSORS %ssym double \n", v.name.c_str()) ;//tensor
486  for (auto i : (*v.data))
487  fprintf(out, "%g %g %g %g %g %g %g %g %g\n", i[0], i[1], i[2], i[1], i[d], i[d+1], i[2], i[d+1], i[2*d-1]) ;
488  break ;
489  case TensorType::SKEWTENSOR: fprintf(out, "\nTENSORS %sskew double \n", v.name.c_str()) ;//tensor
490  for (v1d i : (*v.data))
491  fprintf(out, "%g %g %g %g %g %g %g %g %g\n", 0.0, i[0], i[1], -i[0], 0.0, i[d-1], -i[1], -i[d-1], 0.0) ;
492  break ;
493  default: break ; /*fprintf(out, "\nPOINT_DATA %ld\nSCALARS %s double 1 \nLOOKUP_TABLE default \n",(*data.data).size(), data.name.c_str()) ;//scalar norm
494  for (uint i=0 ; i<(*data.data).size() ; i++)
495  fprintf(out, "%g ", Tools<d>::norm((*data.data)[i])) ;*/
496  }
497  }
498 
499 
500 
501  fclose(out) ;
502 }
503 //============================================
504 template <int d>
505 int Tools<d>::writeinline(initializer_list< v1d > list)
506 {
507  if (outs.size()==0)
508  {
509  char path[5000] ;
510  outs.resize(list.size(), NULL) ;
511  uint i=0 ;
512  for (auto iter=list.begin() ; iter<list.end() ; iter++, i++)
513  {
514  sprintf(path, "Res-%d.txt", i) ;
515  outs[i]=fopen(path, "w") ;
516  if (outs[i]==NULL) {printf("Error cannot open writeinline file %d", i) ; return (1) ; }
517  }
518  }
519 
520  int i=0 ;
521  for (auto iter=list.begin() ; iter<list.end() ; iter++, i++)
522  {
523  for (uint j=0 ; j<iter->size() ; j++ )
524  fprintf(outs[i], "%g ", iter->at(j)) ;
525  fprintf(outs[i], "\n") ;
526  }
527 
528  return 0 ;
529 }
530 
531 template <int d>
533 {
534  for (uint i=0 ; i<outs.size() ; i++)
535  fclose(outs[i]) ;
536  return 0 ;
537 }
538 //=========================================
539 template <int d>
541 {
542  v1d res ; res.resize(v.size(),0) ;
543  for (uint i=0 ; i<res.size() ; i++) res[i]=rand() ;
544  double n=Tools<d>::norm(v) ; double nr=Tools<d>::norm(res) ;
545  for (uint i=0 ; i<res.size() ; i++) res[i]=res[i]/nr*n ;
546  return (res) ;
547 }
548 //=============================================
549 template <int d>
550 std::pair <double, double> Tools<d>::two_max_element (cv1d & v)
551 {
552  double m1=v[0],m2=v[1] ;
553  if (m1<m2) {double tmp ; tmp=m1 ; m1=m2 ; m2=tmp ;} ;
554 
555  for (uint i=2 ; i<v.size() ; i++)
556  {
557  if (v[i] > m1) {m1=v[i] ; continue ; }
558  if (v[i] > m2) {m2=v[i] ; }
559  }
560  return (make_pair(m1,m2)) ;
561 }
562 
563 //=========================================
564 
565 //-----------------------------------
566 //void Tools<d>::vec2eigen (Eigen::MatrixXd & a, cv1d &b) {for (uint i=0 ; i<d*d ; i++) a(i/3,i%3) = b[i] ; }
567 //void Tools<d>::eigen2vec (v1d &b, const Eigen::MatrixXd & a) {for (uint i=0 ; i<d*d ; i++) b[i] = a(i/3,i%3);}
568 template <int d>
570 {
571  v1d res (d,0) ;
572  for (int i=0 ; i<d ; i++)
573  {
574  for (int j=0 ; j<d ; j++)
575  {
576  if (j==i) continue ;
577  res[i]+= MSigns[i][j]*M[MIndexAS[i][j]]*v[j] ;
578  }
579  }
580  return res ;
581 }
582 template <int d>
583 v1d Tools<d>::skewmatvecmult (const double * M, cv1d & v)
584 {
585  v1d res (d,0) ;
586  for (int i=0 ; i<d ; i++)
587  {
588  for (int j=0 ; j<d ; j++)
589  {
590  if (j==i) continue ;
591  res[i]+= MSigns[i][j]*M[MIndexAS[i][j]]*v[j] ;
592  }
593  }
594  return res ;
595 }
596 //------------------------------------
597 template <int d>
598 void Tools<d>::skewmatvecmult (v1d & r, cv1d & M, cv1d & v)
599 {
600  for (int i=0 ; i<d ; i++)
601  {
602  r[i]=0 ;
603  for (int j=0 ; j<d ; j++)
604  {
605  if (j==i) continue ;
606  r[i]+= MSigns[i][j]*M[MIndexAS[i][j]]*v[j] ;
607  }
608  }
609 }
610 template <int d>
611 void Tools<d>::skewmatvecmult (v1d & r, const double * M, cv1d & v)
612 {
613  for (int i=0 ; i<d ; i++)
614  {
615  r[i]=0 ;
616  for (int j=0 ; j<d ; j++)
617  {
618  if (j==i) continue ;
619  r[i]+= MSigns[i][j]*M[MIndexAS[i][j]]*v[j] ;
620  }
621  }
622 }
623 //------------------------------------
624 template <int d>
626 {
627  v1d res (d*d, 0) ;
628  for (int i=0 ; i<d ; i++)
629  for (int j=i ; j<d ; j++)
630  {
631  for (int k=0 ; k<d ; k++)
632  res[i*d+j]+=A[MIndexAS[i][k]]*A[MIndexAS[k][j]]*MSigns[i][k]*MSigns[k][j] ;
633  }
634 
635  for (int i=1 ; i<d ; i++)
636  for (int j=0 ; j<i ; j++)
637  res[i*d+j]=res[j*d+i] ;
638 
639  return res ;
640 }
641 //-------------------------------------
642 template <int d>
644 {
645  for (int i=0 ; i<d ; i++)
646  for (int j=i ; j<d ; j++)
647  {
648  r[i*d+j]=0 ;
649  for (int k=0 ; k<d ; k++)
650  r[i*d+j]+=A[MIndexAS[i][k]]*A[MIndexAS[k][j]]*MSigns[i][k]*MSigns[k][j] ;
651  }
652 
653  for (int i=1 ; i<d ; i++)
654  for (int j=0 ; j<i ; j++)
655  r[i*d+j]=r[j*d+i] ;
656 
657 }
658 //-------------------------------
659 template <int d>
661 {
662  v1d res (d*d, 0) ;
663  for (int i=0 ; i<d*d; i++)
664  {
665  res[i]=A[MIndexAS[i/d][i%d]]*MSigns[i/d][i%d] ;
666  }
667  return res ;
668 }
669 //-------------------------------
670 template <int d>
672 {
673  for (int i=0 ; i<d*d; i++)
674  {
675  r[i]=A[MIndexAS[i/d][i%d]]*MSigns[i/d][i%d] ;
676  }
677 }
678 //-------------------------------
679 template <int d>
681 {
682  v1d res (d*d, 0) ;
683  for (int i=0 ; i<d; i++)
684  for (int j=0 ; j<d ; j++)
685  for (int k=0 ; k<d ; k++)
686  res[i*d+j]+=A[i*d+k]*B[k*d+j] ;
687  return res ;
688 }
689 //-------------------------------
690 template <int d>
691 void Tools<d>::matmult (v1d & r, cv1d &A, cv1d &B)
692 {
693  setzero(r) ;
694  for (int i=0 ; i<d; i++)
695  for (int j=0 ; j<d ; j++)
696  for (int k=0 ; k<d ; k++)
697  r[i*d+j]+=A[i*d+k]*B[k*d+j] ;
698 }
699 //-------------------------------
700 template <int d>
701 void Tools<d>::matvecmult (v1d & res, cv1d &A, cv1d &v)
702 {
703  for (int i=0 ; i<d ; i++) res[i] = 0.0;
704  for (int i=0 ; i<d; i++)
705  for (int k=0 ; k<d ; k++)
706  res[i]+=A[i*d+k]*v[k] ;
707 }
708 //----------------------------------------
709 template <int d>
711 {
712  v1d res (d*(d-1)/2, 0) ; size_t k ;
713  /*auto iter = MASIndex.begin() ; //TODO speedup (iter allocates)
714  for (k=0 ; iter!= MASIndex.end() ; iter++, k++)
715  res[k]=a[iter->first]*b[iter->second]-a[iter->second]*b[iter->first] ;*/
716 
717  //auto iter = MASIndex.begin() ; //TODO speedup (iter allocates)
718  for (k=0 ; k<MASIndex.size() ; k++)
719  res[k]=a[ MASIndex[k].first ]*b[MASIndex[k].second]-a[MASIndex[k].second]*b[MASIndex[k].first] ;
720 
721  return (res) ;
722 }
723 //----------------------------------------
724 template <int d>
726 {
727  size_t k ;
728  //auto iter = MASIndex.begin() ; //TODO speedup (iter allocates)
729  //printf("////%d %d %d %d////\n", a.size(), b.size(), res.size(), MASIndex.size()) ;
730  for (k=0 ; k<MASIndex.size() ; k++)
731  res[k]=a[ MASIndex[k].first ]*b[MASIndex[k].second]-a[MASIndex[k].second]*b[MASIndex[k].first] ;
732 }
733 //-----------------------------------
734 template <int d>
735 void Tools<d>::unitvec (vector <double> & v, int n)
736 {
737  for (int i=0 ; i<d ; i++) v[i]=(i==n?1:0) ;
738 }
739 //-----------------------------------
740 template <int d>
741 void Tools<d>::orthonormalise (v1d & A) //Gram-Schmidt process
742 {
743  static int first = 0 ; // cycle through the base vector as first vector (to be impartial, random would probably be better but hey ...
744 
745  // Let's get the base vectors first
746  v2d base (d, v1d(d,0)) ;
747  for (int i=0 ; i<d ; i++)
748  for (int j=0 ; j<d ; j++)
749  base[i][j] = A[j*d+(i+first)%d] ;
750 
751  for (int i=0 ; i<d ; i++)
752  {
753  for (int j=0 ; j<i ; j++)
754  base[i] -= base[j] * (dot(base[i],base[j])) ;
755  base[i] /= norm(base[i]) ;
756  }
757 
758  for (int i=first ; i<first+d ; i++)
759  for (int j=0 ; j<d ; j++)
760  A[j*d+(i%d)] = base[i-first][j] ;
761 
762  //first++ ; if (first>=d) first=0 ;
763 }
764 //-----------------------------------
765 template <int d>
766 double Tools<d>::det (cv2d &M)
767 {
768  double res=0 ;
769  //vector<vector<double>>submatrix ; //TODO speedup
770  //submatrix.resize(d-1, vector<double>(d-1)) ;
771  double submatrix[d-1][d-1] ;
772  for (int i=0 ; i<d ; i++)
773  {
774  for (int j=0 ; j<d ; j++)
775  for (int k=0 ; k<d-1 ; k++)
776  {
777  if (j==i) continue ;
778  submatrix[k][j-(j>i?1:0)]=M[k][j] ;
779  }
780  res += ((i+d-1)%2?-1:1) * M[d-1][i] * Tools<d-1>::det(submatrix) ;
781  }
782  return res ;
783 }
784 template <> double Tools<2>::det(cv2d &M) { return M[0][0]*M[1][1]-M[1][0]*M[0][1] ; }
785 template <> double Tools<1>::det(cv2d &M) { return M[0][0] ; }
786 //----------------
787 template <int d>
788 double Tools<d>::det (cv1d &M)
789 {
790  double res=0 ;
791  //vector<double> submatrix ;
792  //submatrix.resize((d-1)*(d-1)) ;
793  double submatrix[d-1][d-1] ;
794  for (int i=0 ; i<d ; i++)
795  {
796  for (int j=0 ; j<d ; j++)
797  for (int k=0 ; k<d-1 ; k++)
798  {
799  if (j==i) continue ;
800  submatrix[k][j-(j>i?1:0)]=M[k*d+j] ;
801  }
802  res += ((i+d-1)%2?-1:1) * M[(d-1)*d+i] * Tools<d-1>::det(submatrix) ;
803  }
804  return res ;
805 }
806 template <> double Tools<2>::det(cv1d &M) { return M[0]*M[3]-M[1]*M[2] ; }
807 template <> double Tools<1>::det(cv1d &M) { return M[0] ; }
808 //----------------------------------------------------------
809 template <int d>
810 double Tools<d>::det (double M[d][d]) //All the other overload (vectors) eventually use that one for their recursion.
811 {
812  double res=0 ;
813  //vector<vector<double>>submatrix ; //TODO speedup
814  //submatrix.resize(d-1, vector<double>(d-1)) ;
815  double submatrix[d-1][d-1] ;
816  for (int i=0 ; i<d ; i++)
817  {
818  for (int j=0 ; j<d ; j++)
819  for (int k=0 ; k<d-1 ; k++)
820  {
821  if (j==i) continue ;
822  submatrix[k][j-(j>i?1:0)]=M[k][j] ;
823  }
824  res += ((i+d-1)%2?-1:1) * M[d-1][i] * Tools<d-1>::det(submatrix) ;
825  }
826  return res ;
827 }
828 template <> double Tools<2>::det (double M[2][2] ) { return M[0][0]*M[1][1]-M[1][0]*M[0][1] ; }
829 template <> double Tools<1>::det (double M[1][1] ) { return M[0][0] ; }
830 //==================================
831 template <int d>
832 vector<double> Tools<d>::inverse (cv1d &M)
833 {
834  vector<double> res (d*d,0) ;
835  vector<double> submatrix (d*d,0) ;
836  for (int i=0 ; i<d ; i++)
837  for (int j=0 ; j<d ; j++)
838  {
839  submatrix = M ;
840  for (int dd=0 ; dd<d ; dd++)
841  submatrix[i*d+dd]=(dd==j?1:0) ;
842  res[i*d+j]=Tools<d>::det(submatrix) ;
843  }
844  double determinant = Tools<d>::det(M) ;
845  for (int i=0 ; i<d*d ; i++)
846  res[i] /= determinant ;
848  return res ;
849 }
850 
851 //==================================
852 template <int d>
853 double Tools<d>::Volume (double R)
854 {
855  if (d%2==0)
856  return (pow(boost::math::double_constants::pi,d/2)*pow(R,d)/( boost::math::factorial<double>(d/2) )) ;
857  else
858  {
859  int k=(d-1)/2 ;
860  return(2* boost::math::factorial<double>(k) * pow(4*boost::math::double_constants::pi, k) *pow(R,d) / (boost::math::factorial<double>(d))) ;
861  }
862 }
863 //----------------------------------------
864 template <int d>
865 double Tools<d>::InertiaMomentum (double R, double rho)
866 {
867  if (d>MAXDEFDIM)
868  {
869  printf("[WARN] Inertia InertiaMomentum not guaranteed for dimension > %d\n", MAXDEFDIM) ;
870  }
871 
872  double res ;
873  if (d%2==0)
874  {
875  uint k=d/2 ;
876  res=pow(boost::math::double_constants::pi,k)*pow(R, d+2) / boost::math::factorial<double>(k+1) ;
877  return (res*rho) ;
878  }
879  else
880  {
881  uint k=(d-1)/2 ;
882  res=pow(2,k+2) * pow(boost::math::double_constants::pi, k) * pow(R, d+2) / boost::math::double_factorial<double> (d+2) ;
883  return (res*rho) ;
884  }
885 }
886 
887 //--------------------------------
888 template <int d>
890 {
891  double rsqr = normsq(x) ;
892  double r= sqrt(rsqr) ;
893  int j;
894  phi=vector<double>(d-1, 0) ;
895  for (j=d-1 ; j>=0 && fabs(x[j])<1e-6 ; j--) ;
896  int lastnonzero=j ;
897  for (j=0 ; j<d-1 ; j++)
898  {
899  if (j==lastnonzero)
900  {
901  if (x[j]<0) phi[j]=M_PI ;
902  else phi[j]=0 ;
903  return r ;
904  }
905  phi[j] = acos(x[j]/sqrt(rsqr)) ;
906  //printf("[%g %g]", x[j], sqrt(rsqr)) ;
907  if (isnan(phi[j])) {phi[j]=acos(sgn(x[j])*x[j]) ;} //TODO Check that ................
908  rsqr -= x[j]*x[j] ;
909  }
910  //printf("%g %g %g | %g | %g %g \n ", x[0], x[1], x[2], normsq(x), phi[0], phi[1]) ;
911  if (x[d-1]<0) phi[d-2] = 2*M_PI - phi[d-2] ;
912  return r ;
913 }
914 
915 template <int d>
916 void Tools<d>::hyperspherical_phitox (double r, cv1d &phi, v1d &x)
917 {
918  x = v1d (d,r) ;
919  for (int i=0 ; i<d-1 ; i++)
920  {
921  x[i] *= cos(phi[i]) ;
922  for (int j=i+1 ; j<d ; j++)
923  x[j] *= sin(phi[i]) ;
924  }
925  x[d-1] *= sin(phi[d-2]) ;
926 }
927 
928 /*
929 Analytical functions for the momentum of inertia (cf mat script)
930 
931 (8*pi*R^5*rho)/15 d=3 double factorial of 5
932 (16*R^7*rho*pi^2)/105 d=5 double factorial of 7
933 (32*R^9*rho*pi^3)/945 d=7 double factorial of 9 etc
934 (64*R^11*rho*pi^4)/10395
935 (128*R^13*rho*pi^5)/135135
936 (256*R^15*rho*pi^6)/2027025
937 (512*R^17*rho*pi^7)/34459425
938 (1024*R^19*rho*pi^8)/654729075
939 (2048*R^21*rho*pi^9)/13749310575
940 (4096*R^23*rho*pi^10)/316234143225
941 (8192*R^25*rho*pi^11)/7905853580625
942 (16384*R^27*rho*pi^12)/213458046676875
943 (32768*R^29*rho*pi^13)/6190283353629375
944 (65536*R^31*rho*pi^14)/191898783962510625
945 
946 (pi*R^4*rho)/2
947 (R^6*rho*pi^2)/6
948 (R^8*rho*pi^3)/24
949 (R^10*rho*pi^4)/120
950 (R^12*rho*pi^5)/720
951 (R^14*rho*pi^6)/5040
952 (R^16*rho*pi^7)/40320
953 (R^18*rho*pi^8)/362880
954 (R^20*rho*pi^9)/3628800
955 (R^22*rho*pi^10)/39916800
956 (R^24*rho*pi^11)/479001600
957 (R^26*rho*pi^12)/6227020800
958 (R^28*rho*pi^13)/87178291200
959 (R^30*rho*pi^14)/1307674368000 (factorial 15)
960 (R^32*rho*pi^15)/20922789888000
961  */
962 
963 
964 
965 
966 //=====================================================================================================NETCDF
967 #ifdef NETCDF
968 int NetCDFWriter::initialise (string path, initializer_list< v2d > & list, vector <string> names)
969 {
970 int dimids[3] ;
971 int ret = nc_create((path+".nc").c_str(), NC_CLOBBER, &ncid) ;
972 if (ret) {printf("An error occured creating the netCDF file\n") ; return 0 ; }
973 
974 nc_def_dim (ncid, "Grains", list.begin()->size(), dimensions) ;
975 nc_def_dim (ncid, "Scalar", 1, dimensions+1) ;
976 nc_def_dim (ncid, "Vector", Tools<d>::getdim(), dimensions+2) ;
977 nc_def_dim (ncid, "Tensor", Tools<d>::getdim()*Tools<d>::getdim(), dimensions+3) ;
978 nc_def_dim (ncid, "SkewTensor", Tools<d>::getdim()*(Tools<d>::getdim()-1)/2, dimensions+4) ;
979 nc_def_dim (ncid, "Time", NC_UNLIMITED, dimensions+5) ;
980 
981 dimids[0]=dimensions[5] ; dimids[2]=dimensions[0] ; // Dimension order: Time, grains, dim
982 for (auto i=names.begin() ; i<names.end() ; i++)
983 {
984  if (list.begin()->at(0).size() == 1) dimids[1]=dimensions[1] ;
985  else if (list.begin()->at(0).size() == Tools<d>::getdim()) dimids[1]=dimensions[2] ;
986  else if (list.begin()->at(0).size() == Tools<d>::getdim()*Tools<d>::getdim()) dimids[1]=dimensions[3] ;
987  else if (list.begin()->at(0).size() == Tools<d>::getdim()*(Tools<d>::getdim()-1)/2) dimids[1]=dimensions[4] ;
988  else {printf("ERR: Unknown dimension size to write in netCDF\n") ; return 1 ; }
989  varid.push_back(0) ;
990  nc_def_var(ncid, (*i).c_str() , NC_DOUBLE, 3, dimids, &(varid[varid.size()-1])) ;
991 }
992 nc_enddef(ncid) ;
993 first = false ;
994 return 0 ;
995 }
996 //--------------------------------------------------------------
997 int NetCDFWriter::saveNetCDF (initializer_list< v2d > & list)
998 {
999 size_t start[3], count[3] ;
1000 for (auto i = varid.begin() ; i<varid.end() ; i++)
1001 {
1002  auto & X=*(list.begin()) ;
1003  start[0]=timerecord ; start[1]=X.size() ; ; start[2]=0 ;
1004  count[0]=count[1]=1 ; count[2]=X[0].size() ;
1005  for (auto j=X.begin() ; j < X.end() ; j++)
1006  nc_put_vara_double (ncid, *i , start, count, j->data());
1007 }
1008 timerecord++ ;
1009 return timerecord ;
1010 }
1011 #endif
1012 
1013 
1014 
1015 #ifdef NETCDF
1016 #include <netcdf.h>
1017 class NetCDFWriter {
1018 public:
1019  int initialise (string path, initializer_list< v2d > & list, vector <string> names) ;
1020  int writeCDF (string path, initializer_list< v2d > & list, vector <string> & names) {if (first) {initialise(path, list, names); first=false;} saveNetCDF(list) ; return 0 ; }
1021  ~NetCDFWriter() {if (!first) nc_close(ncid) ;}
1022 private:
1023  int ncid ;
1024  int timerecord=0 ;
1025  int dimensions[6];
1026  vector <int> varid, stride ;
1027  bool first=true ;
1028  int saveNetCDF (initializer_list< v2d > & list) ;
1029 } ;
1030 #endif
1031 
1032 #endif
boost::random::mt19937 rng(static_cast< unsigned int >(std::time(nullptr)))
v1d & operator+=(v1d &a, cv1d &b)
Definition: Tools.h:64
v1d & operator-=(v1d &a, cv1d &b)
Definition: Tools.h:61
v1f & operator/=(v1f &a, cv1f &b)
Definition: Tools.h:66
v1d operator/(v1d a, double b)
Definition: Tools.h:60
v1d & operator*=(v1d &a, double b)
Definition: Tools.h:62
v1d operator*(v1d a, double b)
Definition: Tools.h:49
v1d operator+(v1d a, double b)
Definition: Tools.h:53
Limited use: used to transfer data to the VTK writer.
Definition: Tools.h:50
TensorType order
Definition: Tools.h:53
string name
Definition: Tools.h:52
v2d * data
Definition: Tools.h:54
Dimension specific mathematics.
Definition: Tools.h:60
static std::tuple< double, double > contact_ellipse_disk(std::vector< double > &X, double a, double b, double cx, double cy, double gamma=0.1, double tol=1e-5)
Definition: Tools.h:62
Static class to handle multi-dimensional mathematics, and more. It gets specialised for speed with te...
Definition: Tools.h:101
static void vAddScaled(v1d &res, double v, cv1d &a, cv1d &b)
Addition of 3 vectors in-place.
Definition: Tools.h:183
static void vAddFew(v1d &res, cv1d &a, cv1d &b, v1d &Corr)
Addition of 3 vectors in-place with error correction (Kahan summation algorithm)
Definition: Tools.h:193
static void vSubFew(v1d &res, cv1d &a, cv1d &b, v1d &Corr)
Subtraction of 2 vectors with error correction.
Definition: Tools.h:205
static void vMul(v1d &res, cv1d &a, double b)
Multiply a vector by a scalar in-place.
Definition: Tools.h:175
static void vDiv(v1d &res, cv1d &a, double b)
Division of a vector by a scalar in-place.
Definition: Tools.h:180
static void vAddFew(v1d &res, cv1d &a, cv1d &b)
Definition: Tools.h:182
static void vSubOne(v1d &res, cv1d &a, v1d &Corr)
Subtraction of 2 vectors in-place with error correction (Kahan summation algorithm)
Definition: Tools.h:229
static int getdim(void)
Return the dimension.
Definition: Tools.h:285
static void vPlus(v1d &res, cv1d &a, double b)
Addition of a vector by a scalar in-place.
Definition: Tools.h:178
static void vDiv(v1d &res, cv1d &a, cv1d &b)
Component-wise discrete of 2 vectors in-place.
Definition: Tools.h:181
static void vAddScaled(v1d &res, double v, cv1d &a)
Addition of a scaled vector .
Definition: Tools.h:184
static void vAddOne(v1d &res, cv1d &a, v1d &Corr)
Addition of 2 vectors in-place with error correction (Kahan summation algorithm)
Definition: Tools.h:217
static void vSubFew(v1d &res, cv1d &a, cv1d &b)
Subtraction of 2 vectors .
Definition: Tools.h:185
static void vPlus(v1d &res, cv1d &a, cv1d &b)
Addition of 2 vectors in-place.
Definition: Tools.h:179
static void vMul(v1d &res, cv1d &a, cv1d &b)
Component-wise multiply 2 vectors in-place.
Definition: Tools.h:176
static void vSubScaled(v1d &res, double v, cv1d &a)
Subtraction of a scaled vector .
Definition: Tools.h:186
static void vMinus(v1d &res, cv1d &a, cv1d &b)
Difference of 2 vectors in-place .
Definition: Tools.h:177
const vector< float > cv1f
Definition: Typedefs.h:16
vector< vector< double > > v2d
Definition: Typedefs.h:10
static void savecsv(char path[], cv2d &X, cv1d &r, const vector< uint32_t > &PBCFlags, cv1d &Vmag, cv1d &OmegaMag, [[maybe_unused]] cv1d &Z)
Save the location and a few more informations in a CSV file.
Definition: Tools.h:380
static double normdiff(cv1d &a, cv1d &b)
Norm of a vector difference .
Definition: Tools.h:121
static void orthonormalise(v1d &A)
Orthonormalise A using the Gram-Shmidt process, in place.
Definition: Tools.h:741
static vector< pair< int, int > > MASIndex
For skew symmetric matrix, make the correspondance between linear index and (row,column) index.
Definition: Tools.h:287
static void setzero(v2d &a)
Set a matrix to zero in-place.
Definition: Tools.h:117
static v1d skewmatsquare(cv1d &A)
Square the skew symetric matrix M.
Definition: Tools.h:625
static v1d wedgeproduct(cv1d &a, cv1d &b)
Wedge product of vectors.
Definition: Tools.h:710
static void unitvec(vector< double > &v, int n)
Construct a unit vector in place.
Definition: Tools.h:735
static v1d Eye
The identity matrix in dimension <d>
Definition: Tools.h:281
static v1f vsqrt(cv1f &a)
Component-wise square root.
Definition: Tools.h:128
static double dot(cv1d &a, cv1d &b)
Dot product.
Definition: Tools.h:127
static vector< FILE * > outs
Store the output file descriptors.
Definition: Tools.h:292
static v1d transpose(cv1d &a)
Transposition.
Definition: Tools.h:258
static double skewnorm(cv1d &a)
Norm of a skew-symetric matrix.
Definition: Tools.h:125
static double InertiaMomentum(double R, double rho)
Compute the hypersphere moment of inertia.
Definition: Tools.h:865
#define MAXDEFDIM
For larger number of dimension, be taken in particular for periodic boundary conditions.
Definition: Tools.h:20
static vector< vector< int > > MSigns
For skew symetric matrix. -1 below the diagonal, 0 on the diagonal, +1 above the diagnal.
Definition: Tools.h:290
vector< float > v1f
Definition: Typedefs.h:12
static int savetxt(char path[], const v2d &table, char const header[])
Definition: Tools.h:349
static double det(cv2d &M)
compute the matrix determinant (probably quite slow, but doesn't really really matters for the usage)
Definition: Tools.h:766
static int writeinline_close(void)
Definition: Tools.h:532
static double skewnormsq(cv1d &a)
Norm squared of a skew-symetrix matrix.
Definition: Tools.h:126
static void savevtk(char path[], int N, cv2d &Boundaries, cv2d &X, cv1d &r, vector< TensorInfos > data)
Save as a vtk file. Dimensions higher than 3 are stored as additional scalars. Additional information...
Definition: Tools.h:433
TensorType
Definition: Tools.h:46
static boost::random::uniform_01< boost::mt19937 > rand
Returns a random number between 0 and 1.
Definition: Tools.h:283
unsigned int uint
Definition: Typedefs.h:8
static double normdiffsq(cv1d &a, cv1d &b)
Norm squared of a vector difference .
Definition: Tools.h:123
static void norm(v1d &res, cv2d &a)
Norm of a 2D-matrix, returns a 1D vector with the norms of the individual vectors.
Definition: Tools.h:120
static void setzero(v1d &a)
Set a vector to zero in-place.
Definition: Tools.h:118
static v1f vsq(cv1f &a)
Component-wise squaring.
Definition: Tools.h:129
static std::pair< double, double > two_max_element(cv1d &v)
Return the two largest elements of v.
Definition: Tools.h:550
static double normsq(const vector< double > &a)
Norm squared.
Definition: Tools.h:122
static void matvecmult(v1d &res, cv1d &A, cv1d &B)
Multiply a matrix with a vector, in place.
Definition: Tools.h:701
static double hyperspherical_xtophi(cv1d &x, v1d &phi)
Convert from cartesian to hyperspherical coordinates.
Definition: Tools.h:889
static v1d inverse(cv1d &M)
compute the matrix inverse (very slow and redundant calculation of the determinant for the comatrix,...
Definition: Tools.h:832
static int writeinline(initializer_list< v1d >)
Definition: Tools.h:505
static v1d skewmatvecmult(cv1d &M, cv1d &v)
Multiply the skew symetric matrix M with vector v.
Definition: Tools.h:569
const vector< double > cv1d
Definition: Typedefs.h:13
static int sgn(double a)
Sign function.
Definition: Tools.h:109
static bool check_initialised(int dd)
Definition: Tools.h:107
const vector< vector< double > > cv2d
Definition: Typedefs.h:14
static v1d matmult(cv1d &A, cv1d &B)
Multiply 2 matrix together.
Definition: Tools.h:680
static int write1D(char path[], v1d table)
Definition: Tools.h:368
static v1d skewexpand(cv1d &A)
Return the skew symetrix matrix M stored on d(d-1)/2 component as a full flattened matrix with d^2 co...
Definition: Tools.h:660
static void hyperspherical_phitox(double r, cv1d &phi, v1d &x)
Convert from hyperspherical to cartesian coordinates.
Definition: Tools.h:916
static void transpose_inplace(v1d &a)
Transpose in-place.
Definition: Tools.h:259
static void setgravity(v2d &a, v1d &g, v1d &m)
Set the gravity. .
Definition: Tools.h:154
static void print(cv1d M)
Definition: Tools.h:274
static void clear()
Get the class ready for a different dimension.
Definition: Tools.h:339
vector< double > v1d
Definition: Typedefs.h:9
static void surfacevelocity(v1d &res, cv1d &p, double *com, double *vel_com, double *omega_com)
Definition: Tools.h:131
static vector< vector< int > > MIndexAS
For skew symmetric matrix, make the correspondance between linear index of a full matrix with the lin...
Definition: Tools.h:291
static int sgn(uint8_t a)
Sign function.
Definition: Tools.h:108
static void initialise()
Initialise the member variables, in particular the variables to handle skew-symmetric flattened matri...
Definition: Tools.h:318
static boost::random::mt19937 rng
Random number generator.
Definition: Tools.h:282
static v1d randomize_vec(cv1d v)
Produce a random vector.
Definition: Tools.h:540
v1d operator-(v1d a, double b)
static double norm(const vector< double > &a)
Norm of a vector.
Definition: Tools.h:119
static double Volume(double R)
Compute the hypersphere volume.
Definition: Tools.h:853
static v1d unitvec(int n)
Construct & return a unit vector.
Definition: Tools.h:116
uint d
int N
v2d Boundaries
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.hpp:25399
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1282
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1181
unsigned char uint8_t
Definition: stdint.h:124