ls1-MarDyn
ls1-MarDyn molecular dynamics code
C04CellPairTraversal.h
1/*
2 * C04CellPairTraversal.h
3 *
4 * Created on: 26 Mar 2018
5 * Author: tchipevn
6 */
7
8#ifndef SRC_PARTICLECONTAINER_LINKEDCELLTRAVERSALS_C04CELLPAIRTRAVERSAL_H_
9#define SRC_PARTICLECONTAINER_LINKEDCELLTRAVERSALS_C04CELLPAIRTRAVERSAL_H_
10
11#include "C08BasedTraversals.h"
12#include "utils/GetChunkSize.h"
13#include "utils/mardyn_assert.h"
14#include "utils/threeDimensionalMapping.h"
15
17};
18
19template <class CellTemplate>
20class C04CellPairTraversal: public C08BasedTraversals<CellTemplate> {
21public:
22 C04CellPairTraversal(std::vector<CellTemplate>& cells,
23 const std::array<unsigned long, 3>& dims) :
25 computeOffsets32Pack();
26 }
27 virtual ~~C04CellPairTraversal() {
28 }
29
30 virtual void rebuild(std::vector<CellTemplate> &cells,
31 const std::array<unsigned long, 3> &dims, double cellLength[3], double cutoff,
33 C08BasedTraversals<CellTemplate>::rebuild(cells, dims, cellLength, cutoff, data);
34 computeOffsets32Pack();
35 }
36
37 void traverseCellPairs(CellProcessor& cellProcessor);
38 void traverseCellPairsOuter(CellProcessor& cellProcessor) {}
39 void traverseCellPairsInner(CellProcessor& cellProcessor, unsigned stage, unsigned stageCount) {}
40
41private:
42 void traverseCellPairsBackend(CellProcessor& cellProcessor,
43 const std::array<long, 3>& start,
44 const std::array<long, 3>& end);
45
46 void traverseSingleColor(CellProcessor& cellProcessor,
47 int color,
48 const std::array<long, 3>& start,
49 const std::array<long, 3>& end);
50
51 void processBasePack32(CellProcessor& cellProcessor,
52 const std::array<long, 3>& base3DIndex,
53 const std::array<long, 3>& start,
54 const std::array<long, 3>& end) const;
55
56 void computeOffsets32Pack();
57
58 long parity(long x, long y, long z) const {
59 return (x + y + z + 24) % 8;
60 }
61
62
63 std::array<std::array<long, 3>, 32> _cellOffsets32Pack;
64};
65
66template<class CellTemplate>
68 CellProcessor& cellProcessor) {
69 std::array<long, 3> start, end;
70 for (int d = 0; d < 3; ++d) {
71 start[d] = 0l;
72 end[d] = static_cast<long>(this->_dims[d]) - 1;
73 }
74 traverseCellPairsBackend(cellProcessor, start, end);
75}
76
77template<class CellTemplate>
79 using threeDimensionalMapping::threeToOneD;
80 using std::make_pair;
81
82 int i = 0;
83 long z = 0l;
84 _cellOffsets32Pack[i++] = {1l, 1l, z};
85 _cellOffsets32Pack[i++] = {1l, 2l, z};
86 _cellOffsets32Pack[i++] = {2l, 1l, z};
87 _cellOffsets32Pack[i++] = {2l, 2l, z};
88
89 /* z = 1ul; z = 2ul */
90 for (z = 1l; z < 3l; ++z) {
91 for (long y = 0l; y < 4l; y++) {
92 for (long x = 0l; x < 4l; x++) {
93 if ((x == 0l and y == 0l) or
94 (x == 3l and y == 0l) or
95 (x == 0l and y == 3l) or
96 (x == 3l and y == 3l)) {
97 continue;
98 }
99 _cellOffsets32Pack[i++] = {x, y, z};
100 }
101 }
102 }
103
104
105 z = 3ul;
106 _cellOffsets32Pack[i++] = {1l, 1l, z};
107 _cellOffsets32Pack[i++] = {1l, 2l, z};
108 _cellOffsets32Pack[i++] = {2l, 1l, z};
109 _cellOffsets32Pack[i++] = {2l, 2l, z};
110
111 mardyn_assert(i == 32);
112
113}
114
115template<class CellTemplate>
117 CellProcessor& cellProcessor,
118 const std::array<long, 3>& base3DIndex,
119 const std::array<long, 3>& start,
120 const std::array<long, 3>& end
121 ) const {
122 using threeDimensionalMapping::threeToOneD;
123 std::array<long, 3> index;
124 std::array<long, 3> signedDims;
125 for (int d = 0; d < 3; ++d) {
126 signedDims[d] = static_cast<long>(this->_dims[d]);
127 }
128
129 for (auto Offset32Pack : _cellOffsets32Pack) {
130 // compute 3D index
131 bool isIn = true;
132 for (int d = 0; d < 3; ++d) {
133 index[d] = base3DIndex[d] + Offset32Pack[d];
134 isIn = isIn and (index[d] >= start[d]) and (index[d] < end[d]);
135 }
136
137 if (isIn) {
138 unsigned long ulIndex = static_cast<unsigned long>(threeToOneD(index, signedDims));
140 } else {
141 continue;
142 }
143 }
144}
145
146template<class CellTemplate>
148 CellProcessor & cellProcessor,
149 const std::array<long, 3>& start,
150 const std::array<long, 3>& end) {
151
152 #if defined(_OPENMP)
153 #pragma omp parallel
154 #endif
155 {
156
157 for (int color = 0; color < 4; ++color) {
158
159 traverseSingleColor(cellProcessor, color, start, end);
160
161 #if defined(_OPENMP)
162 if (color < 3) {
163 #pragma omp barrier
164 }
165 #endif
166 }
167 } /* close parallel region */
168}
169
170template<class CellTemplate>
172 int color,
173 const std::array<long, 3>& start,
174 const std::array<long, 3>& end) {
175
176 std::array<long, 3> intersectionStart;
177 for (int d = 0; d < 3; ++d) {
178 intersectionStart[d] = start[d] - 2;
179 }
180
181 // we need to traverse one BCC grid, which consists of two cartesian grids
182
183 // colors 0 and 2 form one cartesian grid
184 // colors 1 and 3 form another cartesian grid, whose origin is shifted by (2,2,2)
185
186 // determine a starting point of one of the grids
187 std::array<long, 3> startOfThisColor {0l, 0l, 0l};
188
189 switch(color % 2) {
190 case 0:
191 // colours 0 and 2
192 startOfThisColor = intersectionStart;
193 break;
194 case 1:
195 // colours 1 and 3
196 startOfThisColor = start;
197 break;
198 default:
199 mardyn_assert(false);
200 }
201
202 long correctParity;
203 correctParity = parity(startOfThisColor[0], startOfThisColor[1], startOfThisColor[2]);
204 if (color >= 2) {
205 correctParity += 4;
206 }
207
208 // to fix compiler complaints about perfectly nested loop.
209 const long startX = startOfThisColor[0], endX = end[0];
210 const long startY = startOfThisColor[1], endY = end[1];
211 const long startZ = startOfThisColor[2], endZ = end[2];
212
213 const auto loop_size = static_cast<size_t>(std::ceil(static_cast<double>(endX - startX) / 4) *
214 std::ceil(static_cast<double>(endY - startY) / 4) *
215 std::ceil(static_cast<double>(endZ - startZ) / 4));
216
217 // magic numbers: empirically determined to be somewhat efficient.
218 // Here, we use a smaller max_chunk_size compared to C08, as c04 work items are bigger.
219 const int chunk_size = chunk_size::getChunkSize(loop_size, 10000, 20);
220
221 // first cartesian grid
222 #if defined(_OPENMP)
223 #pragma omp for schedule(dynamic, chunk_size) collapse(3) nowait
224 #endif
225 for (long z = startZ; z < endZ; z += 4) {
226 for (long y = startY; y < endY; y += 4) {
227 for (long x = startX; x < endX; x += 4) {
228
229 long par = parity(x, y, z);
230
231 if (par != correctParity) {
232 continue;
233 }
234
235 std::array<long, 3> base3DIndex = {x, y, z};
236 processBasePack32(cellProcessor, base3DIndex, start, end);
237 }
238 }
239 }
240}
241
242#endif /* SRC_PARTICLECONTAINER_LINKEDCELLTRAVERSALS_C04CELLPAIRTRAVERSAL_H_ */
Definition: C04CellPairTraversal.h:20
virtual void rebuild(std::vector< CellTemplate > &cells, const std::array< unsigned long, 3 > &dims, double cellLength[3], double cutoff, CellPairTraversalData *data)
Definition: C04CellPairTraversal.h:30
Definition: C08BasedTraversals.h:17
virtual void rebuild(std::vector< CellTemplate > &cells, const std::array< unsigned long, 3 > &dims, double cellLength[3], double cutoff, CellPairTraversalData *data)
Definition: C08BasedTraversals.h:28
Definition: CellProcessor.h:29
Definition: C04CellPairTraversal.h:16
Definition: CellPairTraversals.h:16