OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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
9template<class PBase>
11{
12public:
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 }
153private:
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
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< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:733
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Position_t
Definition: Types.h:43
void for_each(const Pred &pred, const OP &op, Vektor< double, 3 > extend_l, Vektor< double, 3 > extend_r)
int get_bucket_id(int i, const Pred &)
Definition: Inform.h:42