NDDEM
Multiproc.h
Go to the documentation of this file.
1 
5 #ifndef MULTIPROC
6 #define MULTIPROC
7 
8 #include <cstdlib>
9 #include <cmath>
10 #include <cstdio>
11 #include <vector>
12 #include <ctime>
13 
14 #include "Contacts.h"
15 #include "ContactList.h"
16 #include "Parameters.h"
17 
18 using namespace std ;
19 
22 template<int d>
23 struct CLp_it_t {
24  void init (int N, int P)
25  {
26  it_array_beg.resize(N,null_list.v.begin()) ;
27  it_ends.resize(P) ;
28  //it_array_end.resize(N,null_list.v.begin()) ;
29  }
30 
31  void rebuild ( vector <ContactList<d>> & CLp )
32  {
33  for (size_t i=0 ; i<it_array_beg.size() ; i++)
34  it_array_beg[i] = null_list.v.begin() ;
35  for (size_t i=0 ; i<size(CLp) ; i++)
36  {
37  int curi = -1 ;
38  for (auto it = CLp[i].v.begin() ; it!=CLp[i].v.end() ; it++)
39  {
40  if ( it->i != curi )
41  {
42  it_array_beg[it->i] = it ;
43  curi = it->i ;
44  }
45  }
46  }
47  }
48 
49  std::vector<typename list<cp<d>>::iterator> it_array_beg/*, it_array_end */;
50  std::vector<typename list<cp<d>>::iterator> it_ends ;
52 } ;
53 
54 
55 
58 template <int d>
59 class Multiproc
60 {
61 public:
62 
63  void initialise (int NN, int PP, Parameters<d> & Param) {
64  share.resize(PP+1,0) ;
65  sharecell.resize(PP+1,0) ;
66  num_time=0 ;
67  P=PP ;
68  N=NN ;
69  share[share.size()-1]=NN ;
70  split(N,P) ;
71  disp_share() ;
72  CLp.resize(P,ContactList<d>()) ;
73  CLp_new.resize(P,ContactList<d>()) ;
74  CLw.resize(P,ContactList<d>()) ;
75  CLm.resize(P,ContactListMesh<d>()) ;
76  C.resize(P, Contacts<d>(Param)) ;
77  delayed.resize(P) ;
78  delayedj.resize(P) ;
79  delayed_size.resize(P,0) ;
80  delayedwall.resize(P) ;
81  delayedwallj.resize(P) ;
82  delayedwall_size.resize(P,0) ;
83  timing_contacts.resize(P,0) ;
84  timing_forces.resize(P,0) ;
85  }
86  void disp_share();
87  bool ismine (int ID, int j) {if (j>=share[ID] && j<share[ID+1]) return true ; return false ; }
88  void delaying (int ID, int j, Action<d> & act) ;
89  void delayed_clean() ;
90  void delayingwall (int ID, int j, Action<d> & act) ;
91  void delayedwall_clean() ;
92  void load_balance(ContactStrategies contactstrategy) ;
93  //-----------------------------------
95  {
96  list <cp<d>> insertions ;
97  for (int p=0 ; p<P ; p++)
98  {
99  insertions.splice(insertions.end(), CLp_new[p].v) ;
100  }
101  if (insertions.size() == 0)
102  return ;
103 
104  insertions.sort() ;
105 
106  int curp = 0 ;
107  while (insertions.size() > 0)
108  {
109  int id = insertions.front().i ;
110  for ( ; curp<P && share[curp+1] <= id ; curp++) ;
111 
112  if (CLp_it.it_array_beg[id] == CLp_it.null_list.v.begin())
113  {
114  for ( ; id<share[curp+1] && CLp_it.it_array_beg[id] == CLp_it.null_list.v.begin() ; id++) ;
115  if (id == share[curp+1])
116  CLp[curp].v.splice(CLp[curp].v.end(), insertions, insertions.begin()) ;
117  else
118  CLp[curp].v.splice(CLp_it.it_array_beg[id], insertions, insertions.begin()) ;
119 
120  }
121  else
122  {
123  auto it = CLp_it.it_array_beg[id] ;
124  while ( it != CLp[curp].v.end() && (*it)<insertions.front() ) it ++ ;
125  CLp[curp].v.splice(it, insertions, insertions.begin()) ;
126  }
127  }
128 
129 
130  /*
131  for (curp = 0 ; share[curp+1]<=it1->i && curp<P ; curp++) ;
132 
133  while( it2!=insertions.end() )
134  {
135  it2++ ;
136  if (it2 == insertions.end())
137  {
138  CLp_new[curp].v.splice(CLp_new[curp].v.begin(), insertions, it1, it2) ;
139  }
140  else if (it2->i>=share[curp+1])
141  {
142  CLp_new[curp].v.splice(CLp_new[curp].v.begin(), insertions, it1, it2) ;
143  it1=it2 ;
144  curp++ ;
145  for ( ; share[curp+1]<=it1->i && curp<P ; curp++) ;
146  }
147  } */
148  }
149  //---------------------------------------------
151  {
152  int curi = -1 ;
153  auto it = CLp[ID].v.begin() ;
154  for (int i=share[ID] ; i<share[ID+1] ; i++) CLp_it.it_array_beg[i] = CLp_it.null_list.v.begin() ;
155  while ( CLp_new[ID].v.size()>0 || it != CLp[ID].v.end())
156  {
157  if ( CLp_new[ID].v.size()>0 && *(CLp_new[ID].v.begin()) < *it )
158  {
159  CLp[ID].v.splice(it, CLp_new[ID].v, CLp_new[ID].v.begin()) ;
160  if (it != CLp[ID].v.begin()) it-- ;
161  }
162 
163  if (it->persisting == false)
164  {
165  it = CLp[ID].v.erase(it) ;
166  continue ;
167  }
168 
169  if ( it->i != curi)
170  {
171  CLp_it.it_array_beg[it->i] = it ;
172  if (curi!= -1) CLp_it.it_array_end[curi] = it ;
173  curi = it->i ;
174  }
175  it++ ;
176  }
177  if (curi!= -1) CLp_it.it_array_end[curi] = CLp[ID].v.end() ;
178 
179  return 0 ;
180  }
181 
182  /*void merge_split_CLp ()
183  {
184  __itt_domain* domain = __itt_domain_create("MyDomain");
185  __itt_string_handle* task_nameA = __itt_string_handle_create("A");
186  __itt_string_handle* task_nameB = __itt_string_handle_create("B");
187  __itt_string_handle* task_nameC = __itt_string_handle_create("C");
188 
189  int tot =CLp[0].v.size() ;
190  for (int p=1 ; p<P ; p++)
191  {
192  tot +=CLp[p].v.size() ;
193  CLp[0].v.splice(CLp[0].v.end(), CLp[p].v) ;
194  }
195 
196  CLp[0].v.sort() ;
197 
198  __itt_task_begin(domain, __itt_null, __itt_null, task_nameA);
199  CLp_all.v.merge(CLp[0].v) ; // Ordered merging
200  __itt_task_end(domain);
201  //printf("/%d ", tot) ; fflush(stdout) ;
202  //for (auto &v: CLp_all.v) std::cout<<v.persisting ;
203 
204  __itt_task_begin(domain, __itt_null, __itt_null, task_nameB);
205  CLp_all.make_iterator_array(N) ;
206  __itt_task_end(domain);
207 
208  //printf(" %d ", CLp_all.v.size()) ; fflush(stdout) ;
209  for (auto it = CLp_all.v.begin() ; it!=CLp_all.v.end() ; it++)
210  printf("|%X|", it) ;
211  for (auto it = CLp_all.it_array_beg.begin() ; it!=CLp_all.it_array_beg.end() ; it++)
212  printf("|%X|", *it) ;
213  for (auto it = CLp_all.it_array_end.begin() ; it!=CLp_all.it_array_end.end() ; it++)
214  printf("|%X|", *it) ;
215 
216  for (int p=0 ; p<P ; p++)
217  {
218  if (CLp[p].v.size() !=0) {printf("ERR: CLp %d should be of size 0 at this stage\n", p) ; }
219  auto [it_min, it_max] = CLp_all.it_bounds(share[p], share[p+1], N) ;
220  __itt_task_begin(domain, __itt_null, __itt_null, task_nameC);
221  if (it_min!=it_max) CLp[p].v.splice(CLp[p].v.begin(), CLp_all.v, it_min, it_max) ;
222  __itt_task_end(domain);
223  }
224 
225 
226  tot =0 ;
227  for (int p=0 ; p<P ; p++) tot+=CLp[p].v.size() ;
228  //printf("%d/\n", tot) ; fflush(stdout) ;
229 
230  //if (CLp[0].v.size() !=0) {printf("ERR: CLp %d should be of size 0 at this stage\n", 0) ; }
231  //CLp[0].v.splice(CLp[0].v.begin(), CLp_all.v) ;
232 
233  for (auto &v: CLp[0].v)
234  printf("B> %d %d\n", v.i, v.j);
235  printf("==================\n") ; fflush(stdout) ;
236  }
237  */
238  /*void mergeback_CLp()
239  {
240  if (CLp_all.v.size() != 0) {printf("ERR: CLpall should be of size 0 at this stage\n") ; }
241  for (int p=0 ; p<P ; p++)
242  {
243  CLp_all.v.splice(CLp_all.v.end(), CLp[p].v) ;
244  }
245  }
246 
247  void coalesce_main_list()
248  {
249  CLp_all.coalesce_list() ;
250  num_mem_time=0 ;
251  }*/
252 
253  void splitcells(int C) ;
254  auto contacts2array (ExportData exp, cv2d &X, Parameters<d> &P) ;
255 
256 
257 
258 
259  template <class Archive>
260  void serialize(Archive &ar) {
261  ar( /* CLp_it: Not saved on purpose, need to be rebuilt from scratch (iterator invalidate upon save/reload */
262  CLp, CLw, CLm, CLp_new,
263  share, sharecell, timing_contacts, timing_forces, num_time,
264  delayed, delayedj, delayed_size,
265  delayedwall, delayedwallj, delayedwall_size,
266  P, fullcontactinfo, N) ;
267  }
268 
269  //------------------------------------------------
270  //ContactList<d> CLp_all ; ///< Full contact list merged for all processor (to go from per cell CLp lists to globally atom sorted, and back to per proc).
271  vector <ContactList<d>> CLp ;
272  vector <ContactList<d>> CLp_new ;
273  vector <ContactList<d>> CLw ;
274  vector <ContactListMesh<d>> CLm ;
275  vector <Contacts<d>> C ;
276  vector <int> share ;
277  vector <int> sharecell ;
278  vector <double> timing_contacts, timing_forces ;
279  int num_time ;
281 
282  // Array for temporary storing the reaction forces in the parallel part, to run sequencially after, to avoid data race
283  vector <vector <Action<d>> > delayed ;
284  vector <vector <int> > delayedj ;
285  vector <uint> delayed_size ;
286 
287  vector <vector <Action<d>> > delayedwall ;
288  vector <vector <int> > delayedwallj ;
289  vector <uint> delayedwall_size ;
290 
291  int P ;
292 
293 private:
295  int N ;
296  void split (int N, int P) ;
297 } ;
298 
299 /*****************************************************************************************************
300  * *
301  * *
302  * *
303  * IMPLEMENTATIONS *
304  * *
305  * *
306  * *
307  * ***************************************************************************************************/
308 
309 template <int d>
311 {
312  printf("Processor share [%d threads]:\n", P) ;
313  for (auto i : share)
314  printf("%d ", i) ;
315  printf("\n") ;
316  for (int i=0 ; i<P ; i++)
317  printf("%.1f ", ((N-share[i]- (share[i+1]-share[i])/2)*(share[i+1]-share[i]))/double((N*N-1)/2)*100) ;
318  printf("\n--------\n") ;
319 }
320 //=====================================================
321 template <int d>
322 void Multiproc<d>::split(int N, int P)
323 {
324 double Delta,b1,b2 ;
325 double Nd=N ;
326 
327 double Area=Nd*(Nd-1)/double(2*P) ;
328 bool fallback = false ;
329 
330 share[0]=0 ;
331 for (int i=0 ; i<P-1 ; i++)
332 {
333  /*Delta=Nprime*Nprime-2*Area ;
334  if (Delta<0) {printf("Error: Quadratic equation has no solution(multiproc)\n") ; fflush(stdout) ; fallback = true ; break ;}
335  b1=(Nprime-sqrt(Delta)) ;
336  b2=(Nprime+sqrt(Delta)) ;
337  if (b1>=0 && b1<N)
338  {
339  printf("%d Using b1 %d %d\n", i, int(floor(b1)), int(floor(b2))) ;
340  share[i+1]=share[i]+int(floor(b1)) ;
341  Nprime -= int(floor(b1)) ;
342  }
343  else if (b2>=0 && b2<N)
344  {
345  printf("%d Using b2 %d\n", i, int(floor(b2))) ;
346  share[i+1]=share[i]+int(floor(b2)) ;
347  Nprime -= int(floor(b2)) ;
348  }
349  else printf("No solution ...") ;*/
350 
351  Delta = 4*Nd*Nd + 4 * (-2 * Nd * share[i] + share[i]*double(share[i]) - 2 * Area) ;
352  if (Delta<0) {printf("Error: Quadratic equation has no solution(multiproc)\n") ; fflush(stdout) ; fallback = true ; break ;}
353  b1=(Nd-sqrt(Delta)/2.) ;
354  b2=(Nd+sqrt(Delta)/2.) ;
355  if (b1>=0 && b1<N)
356  {
357  printf("%d Using b1 %d %d\n", i, int(floor(b1)), int(floor(b2))) ;
358  share[i+1]=share[i]+int(floor(b1)) ;
359  }
360  else if (b2>=0 && b2<N)
361  {
362  printf("%d Using b2 %d\n", i, int(floor(b2))) ;
363  share[i+1]=share[i]+int(floor(b2)) ;
364  }
365  else printf("No solution ...") ;
366 }
367 
368 if (fallback)
369  for (int i=1 ; i<P ; i++)
370  share[i] = i*N/P ;
371 
372 share[P]=N ;
373 }
374 //=====================================================
375 template <int d>
377 {
378  for (int p=0 ; p<P ; p++)
379  sharecell[p] = p*(C/P) ;
380  sharecell[P] = C ;
381 }
382 
383 //-------------------------------------------------
384 template <int d>
385 void Multiproc<d>::delaying (int ID, int j, Action<d> & act)
386 {
387  delayed_size[ID]++ ;
388  if (delayed_size[ID] < delayedj[ID].size())
389  {
390  delayed[ID][delayed_size[ID]-1]=act ;
391  delayedj[ID][delayed_size[ID]-1]=j ;
392  }
393  else
394  {
395  delayed[ID].resize(delayed_size[ID]+100, act) ;
396  delayedj[ID].resize(delayed_size[ID]+100, j) ;
397  //delayed[ID].push_back(act) ;
398  //delayedj[ID].push_back(j) ;
399  }
400 }
401 template <int d>
402 void Multiproc<d>::delayingwall (int ID, int j, Action<d> & act)
403 {
404  delayedwall_size[ID]++ ;
405  if (delayedwall_size[ID] < delayedwallj[ID].size())
406  {
407  delayedwall[ID][delayedwall_size[ID]-1]=act ;
408  delayedwallj[ID][delayedwall_size[ID]-1]=j ;
409  }
410  else
411  {
412  delayedwall[ID].resize(delayedwall_size[ID]+100, act) ;
413  delayedwallj[ID].resize(delayedwall_size[ID]+100, j) ;
414  //delayed[ID].push_back(act) ;
415  //delayedj[ID].push_back(j) ;
416  }
417 }
418 //---------------------------------------------
419 template <int d>
421 {
422  for (auto & val : delayed_size)
423  {
424  val=0 ;
425  }
426 }
427 template <int d>
429 {
430  for (auto & val : delayedwall_size)
431  {
432  val=0 ;
433  }
434 }
435 //--------------------------------------------
436 template <int d>
438 {
439  if (contactstrategy == NAIVE)
440  for (int i=0 ; i<P ; i++)
441  timing_forces[i]+= timing_contacts[i] ;
442 
443  if (P==1) return ;
444  double target = std::accumulate(timing_forces.begin(), timing_forces.end(), 0.) / P / num_time ;
445  bool doloadbalance = false ;
446  for (int i=0 ; i<P ; i++) // Checking that it's worth balancing the load
447  {
448  if (abs(1-timing_forces[i]/num_time/target)>0.1)
449  doloadbalance = true ;
450  }
451  if (!doloadbalance)
452  return ;
453 
454  vector <double> timeperatom ;
455  for (int i=0 ; i<P ; i++)
456  timeperatom.push_back( (timing_forces[i] / (share[i+1]-share[i])) / num_time) ;
457 
458  double time ;
459  //for (auto v: timing) printf("%g ", v) ;
460  vector <int> newshare(P+1,0) ;
461 
462  int curp=1 ;
463  for (int p=1 ; p<P ; p++)
464  {
465  //printf("%d\n", newshare.size()) ; fflush(stdout) ;
466  time=0 ; newshare[p] = newshare[p-1] ;
467  //printf("%g\n", target) ; fflush(stdout) ;
468  while (time<target)
469  {
470  if (newshare[p] >= share[curp])
471  curp++ ;
472  newshare[p]++ ;
473  if (newshare[p]==N-(P-p)) { /*printf("BREAKING P ") ; */break ;} // To ensure at least 1 particle per core, not taking any risk
474  time += timeperatom[curp-1] ;
475  }
476  }
477  newshare[P] = N;
478 
479  /* For testing purposes (random allocation to proc)
480  newshare[0] = 0 ; newshare[P]=N ;
481  for (int i=1; i<P ; i++)
482  {
483  do {
484  newshare[i] = newshare[i-1]+rand()%(N-newshare[i-1]-1)+1 ;
485  } while (newshare[i]>=N-(P-i)) ;
486  }*/
487 
488  //if (contactstrategy == NAIVE)
489  //{
490  /*printf("\nBalancing the load: processor migration\n") ;
491  for (int i=0 ; i<P ; i++) printf("%d %ld |", share[i], CLp[i].v.size() ) ;
492  printf("\n") ; fflush(stdout) ;*/
493 
494  share=newshare ;
495  ContactList<d> temp_p, temp_w ;
496 
497  for (int i=0 ; i<P ; i++)
498  {
499  temp_p.v.splice(temp_p.v.end(), CLp[i].v) ;
500  temp_w.v.splice(temp_w.v.end(), CLw[i].v) ;
501  }
502 
503  //for (auto v: temp_p.v) printf("%d ", v.i) ;
504  for (int p=0 ; p<P ; p++)
505  {
506  auto itp=temp_p.v.begin() ;
507  while ( itp != temp_p.v.end() && itp->i < newshare[p+1]) itp++ ;
508  CLp[p].v.splice(CLp[p].v.begin(), temp_p.v, temp_p.v.begin(), itp) ;
509 
510  auto itw=temp_w.v.begin() ;
511  while ( itw != temp_w.v.end() && itw->i < newshare[p+1]) itw++ ;
512  CLw[p].v.splice(CLw[p].v.begin(), temp_w.v, temp_w.v.begin(), itw) ;
513 
514  }
515 
516  //for (int i=0 ; i<P ; i++) printf("%d %ld |", share[i], CLp[i].v.size() ) ;
517  //printf("\n") ; fflush(stdout) ;
518  //}
519  if (contactstrategy == CELLS || contactstrategy == OCTREE)
520  {
521  double target = std::accumulate(timing_contacts.begin(), timing_contacts.end(), 0.) / P / num_time ;
522  bool doloadbalance = false ;
523  for (int i=0 ; i<P ; i++) // Checking that it's worth balancing the load
524  {
525  if (abs(1-timing_contacts[i]/num_time/target)>0.1)
526  doloadbalance = true ;
527  }
528  if (!doloadbalance)
529  return ;
530 
531  vector <double> timepercell ;
532  for (int i=0 ; i<P ; i++)
533  timepercell.push_back( (timing_contacts[i] / (sharecell[i+1]-sharecell[i])) / num_time) ;
534 
535  //for (int i=0 ; i<P ; i++) printf("%d %g %g / ", sharecell[i], timing_contacts[i], timepercell[i]);
536  //printf("\n") ;
537 
538  int curp=1 ; newshare[0]=0 ; newshare[P] = sharecell[P];
539  for (int p=1 ; p<P ; p++)
540  {
541  time=0 ; newshare[p] = newshare[p-1] ;
542  //printf("%g\n", target) ; fflush(stdout) ;
543  while (time<target)
544  {
545  if (newshare[p] >= sharecell[curp])
546  {
547  //printf("C+ %d %d %d ", p, curp, newshare[p]) ;
548  curp++ ;
549  }
550  newshare[p]++ ;
551  if (newshare[p]==newshare[P]-(P-p)) {/*printf("BREAKING C ") ; */ break ;} // To ensure at least 1 cell per core, not taking any risk
552  time += timepercell[curp-1] ;
553  }
554  //printf("=> %d %d | ", p, newshare[p]) ;
555  }
556  sharecell = newshare ;
557 
558  /*vector <double> timepercellnew ;
559  for (int i=0 ; i<P ; i++)
560  timepercellnew.push_back(timepercell[i]*(sharecell[i+1]-sharecell[i])*num_time) ; */
561 
562  //for (int i=0 ; i<P ; i++) printf("%d %g %g|", sharecell[i], timing_contacts[i], timepercellnew[i]) ;
563  //printf("\n") ; fflush(stdout) ;
564  }
565 }
566 //--------------------------------------------------------------------------------
567 template <int d>
569 {
570  vector<vector<double>> res ;
571  vector<std::pair<ExportData, int>> contactmapping ;
572 
573  int n=0 ;
574  for (auto & clp:CLp) n+= clp.v.size() ;
575  res.resize(n) ;
576  ExportData expid= static_cast<ExportData>(1) ;
577  ExportData expall=exprt ;
578  n=0 ;
579  while (static_cast<int>(expall)>0)
580  {
581  if (expall & static_cast<ExportData>(1))
582  {
584  { contactmapping.push_back({expid,n}) ; n+=1 ; }
585  else if (expid & (ExportData::IDS))
586  { contactmapping.push_back({expid,n}) ; n+=2 ; }
589  { contactmapping.push_back({expid,n}) ; n+=d ;}
590  }
591 
592  expall>>=1 ; expid<<=1 ;
593  }
594  for (auto & v: res) v.reserve(n) ;
595 
596  n=0 ;
597  for (auto & clp : CLp)
598  {
599  for (auto & contact : clp.v)
600  {
601  ExportData expid= static_cast<ExportData>(1) ;
602  ExportData expall=exprt ;
603  auto [loc,branch] = contact.compute_branchvector(X,P) ;
604  while (static_cast<int>(expall)>0)
605  {
606  if (expall & static_cast<ExportData>(1))
607  switch (expid)
608  {
609  case ExportData::IDS: res[n].push_back({static_cast<double>(contact.i)}) ; res[n].push_back({static_cast<double>(contact.j)}) ; break ;
610  case ExportData::CONTACTPOSITION: for (int dd=0 ; dd<d ; dd++) res[n].push_back(loc[dd]) ; break ;
611  case ExportData::FN: for (int dd=0 ; dd<d ; dd++) res[n].push_back(contact.infos->Fn[dd]) ; break ;
612  case ExportData::FT: for (int dd=0 ; dd<d ; dd++) res[n].push_back(contact.infos->Ft[dd]) ; break ;
613  case ExportData::GHOSTMASK: res[n].push_back(static_cast<double>(contact.ghost)) ; break ;
614  case ExportData::GHOSTDIR : res[n].push_back(static_cast<double>(contact.ghostdir)) ; break ;
615  case ExportData::BRANCHVECTOR: for (int dd=0 ; dd<d ; dd++) res[n].push_back(branch[dd]) ; break ;
616  case ExportData::FN_EL: for (int dd=0 ; dd<d ; dd++) res[n].push_back(contact.infos->Fn_el[dd]); break ;
617  case ExportData::FN_VISC: for (int dd=0 ; dd<d ; dd++) res[n].push_back(contact.infos->Fn_visc[dd]); break ;
618  case ExportData::FT_EL: for (int dd=0 ; dd<d ; dd++) res[n].push_back(contact.infos->Ft_el[dd]); break ;
619  case ExportData::FT_VISC: for (int dd=0 ; dd<d ; dd++) res[n].push_back(contact.infos->Ft_visc[dd]); break ;
620  case ExportData::FT_FRIC: for (int dd=0 ; dd<d ; dd++) res[n].push_back(contact.infos->Ft_fric[dd]); break ;
621  case ExportData::FT_FRICTYPE: res[n].push_back(static_cast<double>(contact.infos->Ft_isfric)); break ;
622  default: break ;
623  }
624 
625  expall>>=1 ; expid<<=1 ;
626  }
627  n++ ;
628  }
629  }
630 
631  return std::make_pair(contactmapping, res) ;
632 }
633 #endif
634 
Handle force and torque contact information.
Definition: ContactList.h:19
Handles lists of contacts with meshes.
Definition: ContactList.h:298
Handles lists of contacts.
Definition: ContactList.h:208
list< cp< d > > v
Contains the list of contact.
Definition: ContactList.h:277
Calculate contact forces.
Definition: Contacts.h:23
Manual multiprocessor handling for OpenMP, for max efficiency & avoiding bugs & race conditions,...
Definition: Multiproc.h:60
vector< uint > delayed_size
Max length of the delayed vector for each thread. Can grow as needed on call to delaying()
Definition: Multiproc.h:285
void serialize(Archive &ar)
Definition: Multiproc.h:260
int merge_oldnew_contacts(int ID)
Definition: Multiproc.h:150
vector< double > timing_contacts
Definition: Multiproc.h:278
int P
Number of threads.
Definition: Multiproc.h:291
vector< Contacts< d > > C
Dummy Contacts for independent calculation per processor.
Definition: Multiproc.h:275
vector< uint > delayedwall_size
Max length of the delayed wall vector for each thread. Can grow as needed on call to delaying()
Definition: Multiproc.h:289
v2d fullcontactinfo
Definition: Multiproc.h:294
vector< vector< Action< d > > > delayedwall
Records the delayed Action.
Definition: Multiproc.h:287
vector< ContactListMesh< d > > CLm
ContactList particle-mesh for each processor.
Definition: Multiproc.h:274
vector< vector< Action< d > > > delayed
Records the delayed Action.
Definition: Multiproc.h:283
vector< ContactList< d > > CLp
ContactList particle-particle for each processor.
Definition: Multiproc.h:271
void merge_newcontacts()
Definition: Multiproc.h:94
int N
Number of grains.
Definition: Multiproc.h:295
vector< int > share
Particle share between threads. A thread ID own particles with index between share[ID] and share[ID+1...
Definition: Multiproc.h:276
vector< ContactList< d > > CLw
ContactList particle-wall for each processor.
Definition: Multiproc.h:273
CLp_it_t< d > CLp_it
Iterator list for fast access to particle contacts.
Definition: Multiproc.h:280
bool ismine(int ID, int j)
Check if a particle j belongs to the thread ID.
Definition: Multiproc.h:87
int num_time
Number of sample of time spent. Resets when load_balance() is called.
Definition: Multiproc.h:279
vector< int > sharecell
Cell share between threads (for contact detection based on cells). A thread ID own cells with index b...
Definition: Multiproc.h:277
vector< vector< int > > delayedj
Records the j id of the particle in the associated delayed action.
Definition: Multiproc.h:284
vector< ContactList< d > > CLp_new
New particle-particle contacts for each processor.
Definition: Multiproc.h:272
vector< vector< int > > delayedwallj
Records the j id of the wall in the associated delayed action.
Definition: Multiproc.h:288
void initialise(int NN, int PP, Parameters< d > &Param)
Definition: Multiproc.h:63
Generic class to handle the simulation set up.
Definition: Parameters.h:128
vector< vector< double > > v2d
Definition: Typedefs.h:10
void delaying(int ID, int j, Action< d > &act)
Record the action to be added later to the relevent atom in sequencial settings, avoid potential race...
Definition: Multiproc.h:385
ContactStrategies
Definition: Typedefs.h:22
ExportData
Definition: Parameters.h:46
void disp_share()
Display the # of particle on each thread.
Definition: Multiproc.h:310
void load_balance(ContactStrategies contactstrategy)
Modify the atom share between threads to achieve better load balance between the threads based on the...
Definition: Multiproc.h:437
void split(int N, int P)
Function to allocate the grains to threads taking into account the load balance in the contact detect...
Definition: Multiproc.h:322
void delayedwall_clean()
Clean the record of the force on the wal.
Definition: Multiproc.h:428
auto contacts2array(ExportData exp, cv2d &X, Parameters< d > &P)
pack the contact data in a 2d array
Definition: Multiproc.h:568
void delayed_clean()
Clean the record list.
Definition: Multiproc.h:420
const vector< vector< double > > cv2d
Definition: Typedefs.h:14
void delayingwall(int ID, int j, Action< d > &act)
Record the action on the wall. Only usefull if the force on the wall needs to be calculated.
Definition: Multiproc.h:402
void splitcells(int C)
Definition: Multiproc.h:376
@ CELLS
Definition: Typedefs.h:22
@ OCTREE
Definition: Typedefs.h:22
@ NAIVE
Definition: Typedefs.h:22
uint d
int N
Definition: json.hpp:5678
Simple packing structure for the iterators to the contact list regions per particle.
Definition: Multiproc.h:23
void init(int N, int P)
Definition: Multiproc.h:24
void rebuild(vector< ContactList< d >> &CLp)
Definition: Multiproc.h:31
ContactList< d > null_list
Empty list, effectively providing a null iterator.
Definition: Multiproc.h:51
std::vector< typename list< cp< d > >::iterator > it_ends
Definition: Multiproc.h:50
Contains the parameters of the simulation & CG.
Definition: IOLiggghts.h:67