OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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
9template<class PBase>
11{
12public:
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 (int bx=0; bx<buckets_per_dim[0]; ++bx) {
90 for (int by=0; by<buckets_per_dim[1]; ++by) {
91 for (int 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 int bx_neigh = bx+offset[n][0];
97 int by_neigh = by+offset[n][1];
98 int 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 }
180private:
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
const unsigned Dim
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
Definition: PETE.h:728
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:733
void bounds(const PETE_Expr< T1 > &expr, Vektor< T2, D > &minval, Vektor< T2, D > &maxval)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Position_t
Definition: Types.h:43
void for_each(const Pred &pred, const OP &op)
int mod(int x, int m)
Vektor< double, 3 > rmin_m
Vektor< double, 3 > rmax_m
int sum(int i, const Pred &pred, int f[], int offset[])
PBase::Position_t Position_t
int get_bucket_id(int i, const Pred &pred)
Vektor< int, 3 > buckets_per_dim
HashPairBuilder(PBase &p)
Definition: Inform.h:42