OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
SortingPairBuilder.h
Go to the documentation of this file.
1#ifndef SORTING_PAIR_BUILDER_H
2#define SORTING_PAIR_BUILDER_H
3
4#include <algorithm>
5
6//predicate used to sort index array with std::sort
7template<class A>
9{
10 ProxyPred_t(const A &a, unsigned d) : array(a), dim(d) { }
11
12 template<class T>
13 bool operator()(const T &a, const T &b)
14 { return array[a][dim] < array[b][dim]; }
15
16 unsigned dim;
17 const A &array;
18};
19
20//simplifies usage by allowing the omission of the template parameter
21template<class A>
22ProxyPred_t<A> ProxyPred(const A &a, unsigned d)
23{
24 return ProxyPred_t<A>(a, d);
25}
26
27template<class PBase>
29{
30public:
31 enum { Dim = PBase::Dim };
32 typedef typename PBase::Position_t Position_t;
33
34 SortingPairBuilder(PBase &p) : particles(p) { }
35
36 template<class Pred, class OP>
37 void for_each(const Pred& pred, const OP &op)
38 {
39 std::size_t size = particles.getLocalNum()+particles.getGhostNum();
40
41 Position_t mean[Dim];
42 Position_t variance[Dim];
43
44 //calculate mean position
45 std::fill(mean, mean+Dim, 0);
46 for(std::size_t i = 0;i<size;++i)
47 for(int d = 0;d<Dim;++d)
48 mean[d] += particles.R[i][d];
49
50 for(int d = 0;d<Dim;++d)
51 mean[d] /= size;
52
53 //calculate variance for each dimension
54 std::fill(variance, variance+Dim, 0);
55 for(std::size_t i = 0;i<size;++i)
56 for(int d = 0;d<Dim;++d)
57 variance[d] += (mean[d]-particles.R[i][d])*(mean[d]-particles.R[i][d]);
58
59 int dimension = 0;
60 int var = variance[0];
61 for(int d = 1;d<Dim;++d)
62 if(variance[d]>var)
63 {
64 dimension = d;
65 var = variance[d];
66 }
67
68 //sort index array
69 std::size_t *indices = new std::size_t[size];
70 for(std::size_t i = 0;i<size;++i)
71 indices[i] = i;
72
73 std::sort(indices, indices+size, ProxyPred(particles.R, dimension));
74
75 for(std::size_t i = 0;i<size;++i)
76 for(std::size_t j = i+1;j<size;++j)
77 if(pred(particles.R[indices[i]], particles.R[indices[j]]))
78 op(indices[i], indices[j], particles);
79 else if(particles.R[indices[j]][dimension] - particles.R[indices[i]][dimension]
80 > pred.getRange(dimension))
81 break;
82 }
83private:
84 PBase &particles;
85};
86
87#endif
const unsigned Dim
std::complex< double > a
ProxyPred_t< A > ProxyPred(const A &a, unsigned d)
Position_t
Definition: Types.h:43
bool operator()(const T &a, const T &b)
ProxyPred_t(const A &a, unsigned d)
void for_each(const Pred &pred, const OP &op)
PBase::Position_t Position_t