OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
HashPairBuilder.h
Go to the documentation of this file.
1 #ifndef HASH_PAIR_BUILDER_H
2 #define HASH_PAIR_BUILDER_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 
16  HashPairBuilder(PBase &p) : particles(p) { }
17 
18  template<class Pred, class OP>
19  void for_each(const Pred& pred, const OP &op)
20  {
21  const std::size_t END = std::numeric_limits<std::size_t>::max();
22  // int f[3];
23 
24  std::size_t size = particles.getLocalNum()+particles.getGhostNum();
25  /*
26  int edge = std::pow(size/8, 1./Dim);
27 
28  std::size_t Nbucket = 1;
29  for(int d = 0;d<Dim;++d)
30  {
31  f[d] = edge;
32  Nbucket *= f[d];
33  if(pred.getRange(d)==0)
34  return;
35  }
36  */
37 
39  Inform dmsg("debug_msg:");
40  dmsg << "R_min = " << rmin_m << " R_max = " << rmax_m << endl;
41 
42  buckets_per_dim[0]=ceil((rmax_m[0]-rmin_m[0])/pred.getRange(0));
43  buckets_per_dim[1]=ceil((rmax_m[1]-rmin_m[1])/pred.getRange(1));
44  buckets_per_dim[2]=ceil((rmax_m[2]-rmin_m[2])/pred.getRange(2));
45 
46  //dmsg << "buckets per dim = " << buckets_per_dim << endl;
47  std::size_t Nbucket = buckets_per_dim[0]*buckets_per_dim[1]*buckets_per_dim[2];
48 
49  std::size_t *buckets = new size_t[Nbucket];
50  std::size_t *next = new size_t[size];
51  std::fill(buckets, buckets+Nbucket, END);
52  std::fill(next, next+size, END);
53 
54  /*
55  int neigh = 1;
56  for(int d = 0;d<Dim;++d)
57  neigh *= 3;
58  neigh /= 2;
59  */
60 
61  //in 3D we interact with 14 neighboring cells (including self cell interaction)
62  int neigh = 14;
63 
64  int offset[14][3] = {{ 1, 1, 1}, { 0, 1, 1}, {-1, 1, 1},
65  { 1, 0, 1}, { 0, 0, 1}, {-1, 0, 1},
66  { 1,-1, 1}, { 0,-1, 1}, {-1,-1, 1},
67  { 1, 1, 0}, { 0, 1, 0}, {-1, 1, 0},
68  { 1, 0, 0}, { 0, 0, 0}};
69 
70  //assign all particles to a bucket
71  for(std::size_t i = 0;i<size;++i)
72  {
73  //std::size_t pos = sum(i, pred, f, offset[13]);
74  unsigned bucket_id = get_bucket_id(i,pred);
75  next[i] = buckets[bucket_id];
76  buckets[bucket_id] = i;
77  }
78 
79  for (std::size_t i=0; i< Nbucket; ++i) {
80  //dmsg << "Bucket " << i << " stores particles " << endl;
81  std::size_t j = buckets[i];
82  while (j!= END) {
83  //dmsg << j << " :: " << particles.R[j] << endl;
84  j = next[j];
85  }
86  }
87 
88  //loop over all buckets
89  for (unsigned bx=0; bx<buckets_per_dim[0]; ++bx) {
90  for (unsigned by=0; by<buckets_per_dim[1]; ++by) {
91  for (unsigned bz=0; bz<buckets_per_dim[2]; ++bz) {
92  //dmsg << "bx = " << bx << "by = " << by << " bz = " << bz <<endl;
93  unsigned bucket_id_self = bz*buckets_per_dim[1]*buckets_per_dim[0]+by*buckets_per_dim[0]+bx;
94  //compute index of neighboring cell to interact with
95  for (int n=0; n<neigh;++n){
96  unsigned bx_neigh = bx+offset[n][0];
97  unsigned by_neigh = by+offset[n][1];
98  unsigned bz_neigh = bz+offset[n][2];
99  //check if neighbor cell is within boundaries
100  //dmsg << " looking at neighbor n = " << n << endl;
101  if (bx_neigh >= 0 && bx_neigh<buckets_per_dim[0] &&
102  by_neigh >= 0 && by_neigh<buckets_per_dim[1] &&
103  bz_neigh >= 0 && bz_neigh<buckets_per_dim[2]) {
104 
105  //compute bucket id of neighboring cell
106  unsigned bucket_id_neigh =
107  bz_neigh*buckets_per_dim[1]*buckets_per_dim[0]+by_neigh*buckets_per_dim[0]+bx_neigh;
108  //dmsg << "looking at buckets " << bucket_id_self << " and " << bucket_id_neigh << endl;
109 
110  std::size_t i = buckets[bucket_id_self];
111  //dmsg << "head of chain is " << i << endl;
112  std::size_t j;
113  //loop over all particles in self cell
114 
115  //self offset avoids double counting in self cell
116  int self_offset = 0;
117  while (i != END) {
118  //dmsg << "start i while loop " << endl;
119  j = buckets[bucket_id_neigh];
120  //increase offset by number of processed particles in self cell
121  for (int o=0;o<self_offset;o++){
122  j = next[j];
123  }
124  //loop over all particles in nieghbor cell
125  while(j != END) {
126  //dmsg << "start j while loop" << endl;
127  if(pred(particles.R[i], particles.R[j]))
128  {
129  //dmsg << "processing pair (" << i << "," << j << ")"<<endl;
130  if (i!=j)
131  op(i, j, particles);
132  }
133  j = next[j];
134  }
135  i = next[i];
136  //adjust self_offset
137  if (bucket_id_self==bucket_id_neigh)
138  self_offset++;
139  else
140  self_offset=0;
141  }
142  }
143  //dmsg << "proceed with next neighbor cell " << endl;
144  }
145 
146  }
147  }
148  }
149  /*
150  for(std::size_t i = 0;i<size;++i)
151  {
152  std::size_t j = next[i];
153  while(j != END)
154  {
155  if(pred(particles.R[i], particles.R[j]))
156  op(i, j, particles);
157  j = next[j];
158  }
159 
160  for(int k = 0;k<neigh;++k)
161  {
162  std::size_t tmppos = sum(i, pred, f, offset[k]);
163 
164  j = buckets[tmppos];
165  while(j != END)
166  {
167  if(pred(particles.R[i], particles.R[j]))
168  op(i, j, particles);
169  j = next[j];
170  }
171  }
172 
173  }
174  */
175  delete[] buckets;
176  delete[] next;
177 
178  //dmsg << "particle particle interactions DONE" << endl;
179  }
180 private:
181 
182  template<class Pred>
183  int sum(int i, const Pred& pred, int f[], int offset[])
184  {
185  std::cout << "SUM " << pred.getRange(1) << "f[1]=" << f[1] << std::endl;
186  int sum = 0;
187  for(int d = 0;d<Dim;++d)
188  {
189  double scaled = particles.R[i][d]/pred.getRange(d);
190  int pos = mod(int(floor(scaled+offset[d])), f[d]);
191  for(int dd = 0;dd<d;++dd)
192  pos*=f[dd];
193  sum += pos;
194  }
195  std::cout << "END SUM" << std::endl;
196 
197  return sum;
198  }
199 
200  //returns the bucket id of particle i
201  template<class Pred>
202  int get_bucket_id(int i, const Pred& pred)
203  {
204  Vektor<int,3> loc;
205  for (unsigned d=0; d<3; ++d)
206  loc[d] = (particles.R[i][d]-rmin_m[d])/pred.getRange(d);
207  int bucket_id = loc[2]*buckets_per_dim[1]*buckets_per_dim[0]+loc[1]*buckets_per_dim[0]+loc[0];
208  //std::cout << "bucket id of particle " << i << " = [" << loc[0] << "," << loc[1] << "," << loc[2] << "] => bucket id = " << bucket_id << std::endl;
209  return bucket_id;
210  }
211 
212  int mod(int x, int m)
213  {
214  if(x>=0)
215  return x%m;
216  else
217  return (m - ((-x)%m))%m;
218  }
219 
220  PBase &particles;
222 
225 };
226 #endif
HashPairBuilder(PBase &p)
Vektor< double, 3 > rmax_m
Vektor< int, 3 > buckets_per_dim
void for_each(const Pred &pred, const OP &op)
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:123
Vektor< double, 3 > rmin_m
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
Definition: PETE.h:811
int get_bucket_id(int i, const Pred &pred)
Position_t
Definition: Types.h:28
void bounds(const PETE_Expr< T1 > &expr, Vektor< T2, D > &minval, Vektor< T2, D > &maxval)
int mod(int x, int m)
PBase::Position_t Position_t
const unsigned Dim
Definition: Inform.h:41
int sum(int i, const Pred &pred, int f[], int offset[])
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