OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
HashPairBuilderPeriodic.h
Go to the documentation of this file.
1 #ifndef HASH_PAIR_BUILDER_PERIODIC_H
2 #define HASH_PAIR_BUILDER_PERIODIC_H
3 
4 #include <algorithm>
5 #include <limits>
6 #include <cmath>
7 #include <set>
8 
9 template<class PBase>
11 {
12 public:
13  enum { Dim = PBase::Dim };
14  typedef typename PBase::Position_t Position_t;
15 
17 
18  template<class Pred, class OP>
19  void for_each(const Pred& pred, const OP &op,Vektor<double,3> extend_l, Vektor<double,3> extend_r )
20  {
21  const std::size_t END = std::numeric_limits<std::size_t>::max();
22  std::size_t size = particles.getLocalNum()+particles.getGhostNum();
23 
24  rmin_m = extend_l;
25  rmax_m = extend_r;
26 
27  Vektor<double,3> period = extend_r-extend_l;
28 
29  Inform dmsg("debug_msg:");
30  dmsg << "R_min = " << rmin_m << " R_max = " << rmax_m << endl;
31 
32  //make sure that the chaining mesh covers the whole domain and has a gridwidth>r_cut
33  buckets_per_dim[0]=floor(period[0]/pred.getRange(0));
34  buckets_per_dim[1]=floor(period[1]/pred.getRange(1));
35  buckets_per_dim[2]=floor(period[2]/pred.getRange(2));
36 
37  for (unsigned dim = 0; dim<3; ++dim)
38  h_chaining[dim] = period[dim]/buckets_per_dim[dim];
39 
40  dmsg << " period = " << period << endl;
41  dmsg << "buckets per dim = " << buckets_per_dim << endl;
42  dmsg << "h_chaining = " << h_chaining << endl;
43 
44  std::size_t Nbucket = buckets_per_dim[0]*buckets_per_dim[1]*buckets_per_dim[2];
45 
46  std::size_t *buckets = new size_t[Nbucket]; //index of first particle in this bucket
47  std::size_t *next = new size_t[size]; //index of next particle in this bucket. END indicates last particle of bucket
48  std::fill(buckets, buckets+Nbucket, END);
49  std::fill(next, next+size, END);
50 
51  //in 3D we interact with 14 neighboring cells (including self cell interaction)
52  unsigned neigh = 14;
53 
54  int offset[14][3] = {{ 1, 1, 1}, { 0, 1, 1}, {-1, 1, 1},
55  { 1, 0, 1}, { 0, 0, 1}, {-1, 0, 1},
56  { 1,-1, 1}, { 0,-1, 1}, {-1,-1, 1},
57  { 1, 1, 0}, { 0, 1, 0}, {-1, 1, 0},
58  { 1, 0, 0}, { 0, 0, 0}};
59 
60  //assign all particles to a bucket
61  for(std::size_t i = 0;i<size;++i) {
62  unsigned bucket_id = get_bucket_id(i,pred);
63  next[i] = buckets[bucket_id];
64  buckets[bucket_id] = i;
65  }
66 
67  //loop over all buckets
68  for (int bx=0; bx<buckets_per_dim[0]; ++bx) {
69  for (int by=0; by<buckets_per_dim[1]; ++by) {
70  for (int bz=0; bz<buckets_per_dim[2]; ++bz) {
71  unsigned bucket_id_self = bz*buckets_per_dim[1]*buckets_per_dim[0]+by*buckets_per_dim[0]+bx;
72  //compute index of neighboring bucket to interact with
73  for (unsigned n=0; n<neigh;++n){
74  int bx_neigh, by_neigh, bz_neigh;
75  Vektor<double,3> shift(0,0,0);
76 
77  bx_neigh = bx+offset[n][0];
78  if (bx_neigh < 0) {
79  //bucket in -x direction exceed domain boundary
80  bx_neigh+=buckets_per_dim[0];//consider last bucket in +x instead
81  shift[0] = -period[0];//shift particles in negative x direction by domain size
82  }
83  else if (bx_neigh >= buckets_per_dim[0]) {
84  //bucket in +x direction exceeds domain boundary
85  bx_neigh -=buckets_per_dim[0];//consider first bucket in +x instead
86  shift[0] = period[0];//shift particles in positive x direction by domain size
87  }
88  //do the same for y and z direction:
89  by_neigh = by+offset[n][1];
90  if (by_neigh < 0) {
91  by_neigh+=buckets_per_dim[1];
92  shift[1] = -period[1];
93  }
94  else if (by_neigh >= buckets_per_dim[1]) {
95  by_neigh -=buckets_per_dim[1];
96  shift[1] = period[1];
97  }
98  bz_neigh = bz+offset[n][2];
99  if (bz_neigh < 0) {
100  bz_neigh+=buckets_per_dim[2];
101  shift[2] = -period[2];
102  }
103  else if (bz_neigh >= buckets_per_dim[2]) {
104  bz_neigh -=buckets_per_dim[2];
105  shift[2] = period[2];
106  }
107 
108  if (bx_neigh >= 0 && bx_neigh<buckets_per_dim[0] &&
109  by_neigh >= 0 && by_neigh<buckets_per_dim[1] &&
110  bz_neigh >= 0 && bz_neigh<buckets_per_dim[2]) {
111 
112  //compute bucket id of neighboring cell
113  unsigned bucket_id_neigh =
114  bz_neigh*buckets_per_dim[1]*buckets_per_dim[0]+by_neigh*buckets_per_dim[0]+bx_neigh;
115 
116  std::size_t i = buckets[bucket_id_self];
117  std::size_t j;
118  //loop over all particles in self cell
119  //self offset avoids double counting in self cell
120  int self_offset = 0;
121  while (i != END) {
122  j = buckets[bucket_id_neigh];
123  //increase offset by number of processed particles in self cell
124  for (int o=0;o<self_offset;o++){
125  j = next[j];
126  }
127  //loop over all particles in nieghbor cell
128  while(j != END) {
129  if(pred(particles.R[i], particles.R[j]+shift, period))
130  {
131  if (i!=j) { //because particle i's interaction with itself cancells out
132  op(i, j, particles, shift);
133  }
134  }
135  j = next[j];
136  }
137  i = next[i];
138  //adjust self_offset
139  if (bucket_id_self==bucket_id_neigh)
140  self_offset++;
141  else
142  self_offset=0;
143  }
144  }
145  }
146 
147  }
148  }
149  }
150  delete[] buckets;
151  delete[] next;
152  }
153 private:
154 
155  //returns the bucket id of particle i
156  template<class Pred>
157  int get_bucket_id(int i, const Pred& pred)
158  {
159  Vektor<int,3> loc;
160  for (unsigned d=0; d<3; ++d)
161  loc[d] = (particles.R[i][d]-rmin_m[d])/h_chaining[d];
162  //loc[d] = (particles.R[i][d]-rmin_m[d])/pred.getRange(d);
163  int bucket_id = loc[2]*buckets_per_dim[1]*buckets_per_dim[0]+loc[1]*buckets_per_dim[0]+loc[0];
164  //std::cout << "bucket id of particle " << i << "with coords " << particles.R[i] << " = [" << loc[0] << "," << loc[1] << "," << loc[2] << "] => bucket id = " << bucket_id << std::endl;
165  //std::cout << particles.R[i][0] << "," << particles.R[i][1] << "," << particles.R[i][2] << "," << bucket_id << std::endl;
166 
167  return bucket_id;
168  }
169 
170  PBase &particles;
172 
176 };
177 
178 
179 #endif
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:123
void for_each(const Pred &pred, const OP &op, Vektor< double, 3 > extend_l, Vektor< double, 3 > extend_r)
Position_t
Definition: Types.h:28
const unsigned Dim
Definition: Inform.h:41
int get_bucket_id(int i, const Pred &pred)
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:816
Inform & endl(Inform &inf)
Definition: Inform.cpp:42