26 it_array_beg.resize(
N,null_list.v.begin()) ;
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++)
38 for (
auto it = CLp[i].v.begin() ; it!=CLp[i].v.end() ; it++)
42 it_array_beg[it->i] = it ;
49 std::vector<typename list<cp<d>>::iterator> it_array_beg;
50 std::vector<typename list<cp<d>>::iterator>
it_ends ;
64 share.resize(PP+1,0) ;
65 sharecell.resize(PP+1,0) ;
69 share[share.size()-1]=NN ;
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) ;
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() ;
96 list <cp<d>> insertions ;
97 for (
int p=0 ; p<P ; p++)
99 insertions.splice(insertions.end(), CLp_new[p].v) ;
101 if (insertions.size() == 0)
107 while (insertions.size() > 0)
109 int id = insertions.front().i ;
110 for ( ; curp<P && share[curp+1] <= id ; curp++) ;
112 if (CLp_it.it_array_beg[
id] == CLp_it.null_list.v.begin())
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()) ;
118 CLp[curp].v.splice(CLp_it.it_array_beg[
id], insertions, insertions.begin()) ;
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()) ;
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())
157 if ( CLp_new[ID].v.size()>0 && *(CLp_new[ID].v.begin()) < *it )
159 CLp[ID].v.splice(it, CLp_new[ID].v, CLp_new[ID].v.begin()) ;
160 if (it != CLp[ID].v.begin()) it-- ;
163 if (it->persisting ==
false)
165 it = CLp[ID].v.erase(it) ;
171 CLp_it.it_array_beg[it->i] = it ;
172 if (curi!= -1) CLp_it.it_array_end[curi] = it ;
177 if (curi!= -1) CLp_it.it_array_end[curi] = CLp[ID].v.end() ;
253 void splitcells(
int C) ;
259 template <
class Archive>
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) ;
271 vector <ContactList<d>>
CLp ;
273 vector <ContactList<d>>
CLw ;
274 vector <ContactListMesh<d>>
CLm ;
275 vector <Contacts<d>>
C ;
296 void split (
int N,
int P) ;
312 printf(
"Processor share [%d threads]:\n", P) ;
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") ;
327 double Area=Nd*(Nd-1)/
double(2*P) ;
328 bool fallback = false ;
331 for (
int i=0 ; i<P-1 ; i++)
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.) ;
357 printf(
"%d Using b1 %d %d\n", i,
int(floor(b1)),
int(floor(b2))) ;
358 share[i+1]=share[i]+int(floor(b1)) ;
360 else if (b2>=0 && b2<
N)
362 printf(
"%d Using b2 %d\n", i,
int(floor(b2))) ;
363 share[i+1]=share[i]+int(floor(b2)) ;
365 else printf(
"No solution ...") ;
369 for (
int i=1 ; i<P ; i++)
378 for (
int p=0 ; p<P ; p++)
379 sharecell[p] = p*(C/P) ;
388 if (delayed_size[ID] < delayedj[ID].size())
390 delayed[ID][delayed_size[ID]-1]=act ;
391 delayedj[ID][delayed_size[ID]-1]=j ;
395 delayed[ID].resize(delayed_size[ID]+100, act) ;
396 delayedj[ID].resize(delayed_size[ID]+100, j) ;
404 delayedwall_size[ID]++ ;
405 if (delayedwall_size[ID] < delayedwallj[ID].size())
407 delayedwall[ID][delayedwall_size[ID]-1]=act ;
408 delayedwallj[ID][delayedwall_size[ID]-1]=j ;
412 delayedwall[ID].resize(delayedwall_size[ID]+100, act) ;
413 delayedwallj[ID].resize(delayedwall_size[ID]+100, j) ;
422 for (
auto & val : delayed_size)
430 for (
auto & val : delayedwall_size)
439 if (contactstrategy ==
NAIVE)
440 for (
int i=0 ; i<P ; i++)
441 timing_forces[i]+= timing_contacts[i] ;
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++)
448 if (abs(1-timing_forces[i]/num_time/target)>0.1)
449 doloadbalance = true ;
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) ;
460 vector <int> newshare(P+1,0) ;
463 for (
int p=1 ; p<P ; p++)
466 time=0 ; newshare[p] = newshare[p-1] ;
470 if (newshare[p] >= share[curp])
473 if (newshare[p]==
N-(P-p)) { break ;}
474 time += timeperatom[curp-1] ;
497 for (
int i=0 ; i<P ; i++)
499 temp_p.
v.splice(temp_p.
v.end(), CLp[i].v) ;
500 temp_w.
v.splice(temp_w.
v.end(), CLw[i].v) ;
504 for (
int p=0 ; p<P ; p++)
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) ;
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) ;
519 if (contactstrategy ==
CELLS || contactstrategy ==
OCTREE)
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++)
525 if (abs(1-timing_contacts[i]/num_time/target)>0.1)
526 doloadbalance = true ;
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) ;
538 int curp=1 ; newshare[0]=0 ; newshare[P] = sharecell[P];
539 for (
int p=1 ; p<P ; p++)
541 time=0 ; newshare[p] = newshare[p-1] ;
545 if (newshare[p] >= sharecell[curp])
551 if (newshare[p]==newshare[P]-(P-p)) { break ;}
552 time += timepercell[curp-1] ;
556 sharecell = newshare ;
570 vector<vector<double>> res ;
571 vector<std::pair<ExportData, int>> contactmapping ;
574 for (
auto & clp:CLp) n+= clp.v.size() ;
579 while (
static_cast<int>(expall)>0)
584 { contactmapping.push_back({expid,n}) ; n+=1 ; }
586 { contactmapping.push_back({expid,n}) ; n+=2 ; }
589 { contactmapping.push_back({expid,n}) ; n+=
d ;}
592 expall>>=1 ; expid<<=1 ;
594 for (
auto & v: res) v.reserve(n) ;
597 for (
auto & clp : CLp)
599 for (
auto & contact : clp.v)
603 auto [loc,branch] = contact.compute_branchvector(X,P) ;
604 while (
static_cast<int>(expall)>0)
609 case ExportData::IDS: res[n].push_back({
static_cast<double>(contact.i)}) ; res[n].push_back({
static_cast<double>(contact.j)}) ; 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 ;
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 ;
625 expall>>=1 ; expid<<=1 ;
631 return std::make_pair(contactmapping, res) ;
Handle force and torque contact information.
Definition: ContactList.h:19
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
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