AutoPas  3.0.0
Loading...
Searching...
No Matches
LCC04SoACellHandler.h
Go to the documentation of this file.
1
7#pragma once
8
15
16namespace autopas {
17
30template <class ParticleCell, class PairwiseFunctor>
32 public:
43 explicit LCC04SoACellHandler(PairwiseFunctor *pairwiseFunctor, const std::array<unsigned long, 3> &cellsPerDimension,
44 double interactionLength, const std::array<double, 3> &cellLength,
45 DataLayoutOption dataLayout, bool useNewton3,
46 const std::array<unsigned long, 3> &overlap = {1ul, 1ul, 1ul})
47 : _interactionLength(interactionLength),
48 _cellLength(cellLength),
49 _overlap(overlap),
50 _cellsPerDimension(cellsPerDimension),
51 _cacheOffset(DEFAULT_CACHE_LINE_SIZE / sizeof(unsigned int)),
52 _pairwiseFunctor(pairwiseFunctor),
53 _dataLayout(dataLayout),
54 _useNewton3(useNewton3) {
55 setupIntervals(cellsPerDimension);
56 }
57
66 void processBaseCell(std::vector<ParticleCell> &cells, unsigned long x, unsigned long y, unsigned long z);
67
72
73 private:
77 const double _interactionLength;
78
82 const std::array<double, 3> _cellLength;
83
87 const std::array<unsigned long, 3> _overlap;
88
89 const std::array<unsigned long, 3> _cellsPerDimension;
90
94 std::vector<std::vector<ParticleCell>> _combinationSlices;
95
99 std::vector<unsigned int> _currentSlices;
100
104 std::vector<std::vector<unsigned long>> _baseOffsets;
105
109 using interval_t = std::pair<unsigned long, unsigned long>;
110
114 std::vector<std::vector<std::pair<unsigned long, interval_t>>> _offsets;
115
119 std::vector<std::vector<std::vector<unsigned long>>> _combinationSlicesOffsets;
120
124 const unsigned int _cacheOffset;
125
129 PairwiseFunctor *_pairwiseFunctor;
130
134 DataLayoutOption _dataLayout;
135
139 bool _useNewton3;
140
150 void writeBufferIntoCell(std::vector<ParticleCell> &cells, unsigned long baseIndex,
151 std::vector<ParticleCell> &combinationSlice,
152 std::vector<std::vector<unsigned long>> &combinationSlicesOffsets, unsigned long bufferSlice,
153 unsigned long cellSlice);
154
164 void writeCellIntoBuffer(const std::vector<ParticleCell> &cells, unsigned long baseIndex,
165 std::vector<ParticleCell> &combinationSlice,
166 std::vector<std::vector<unsigned long>> &combinationSlicesOffsets, unsigned int bufferSlice,
167 unsigned int cellSlice);
168
173 void setupIntervals(const std::array<unsigned long, 3> &cellsPerDimension);
174};
175
176template <class ParticleCell, class PairwiseFunctor>
178 unsigned long x, unsigned long y,
179 unsigned long z) {
180 const unsigned long baseIndex = utils::ThreeDimensionalMapping::threeToOneD(x, y, z, _cellsPerDimension);
181
182 // get all information for current thread
183 const auto threadID = static_cast<size_t>(autopas_get_thread_num());
184 auto &currentSlice = _currentSlices[threadID * _cacheOffset];
185 auto &combinationSlice = _combinationSlices[threadID];
186 auto &combinationSlicesOffsets = _combinationSlicesOffsets[threadID];
187
188 const size_t numSlices = _baseOffsets.size();
189
190 // First cell needs to initialize whole buffer
191 if (x == 0ul) {
192 currentSlice = 0ul;
193 for (unsigned int slice = 0ul; slice < numSlices; slice++) {
194 writeCellIntoBuffer(cells, baseIndex, combinationSlice, combinationSlicesOffsets, slice, slice);
195 }
196 } else {
197 writeCellIntoBuffer(cells, baseIndex, combinationSlice, combinationSlicesOffsets, currentSlice, numSlices - 1ul);
198
199 ++currentSlice %= numSlices;
200 }
201
202 // compute interactions
203 for (unsigned long slice = 0; slice < numSlices; slice++) {
204 for (auto const &[offset1, interval] : _offsets[(slice + currentSlice) % numSlices]) {
205 ParticleCell *cell1 = nullptr;
206 size_t cell1ViewStart = 0;
207 size_t cell1ViewEnd;
208
209 // special cases (cell1 one is also stored in a combination slice)
210 // base cell
211 if (offset1 == 0ul) {
212 const auto numParticlesBaseCell = cells[baseIndex].size();
213 if (numParticlesBaseCell == 0) {
214 continue;
215 }
216 // two cases interval in current stripe
217 cell1 = &combinationSlice[currentSlice];
218 auto stripeView = cell1->_particleSoABuffer.constructView(0, numParticlesBaseCell);
219 if (slice == currentSlice) {
220 // Process stripe with itself
221 _pairwiseFunctor->SoAFunctorSingle(stripeView, _useNewton3);
222
223 auto restView =
224 cell1->_particleSoABuffer.constructView(numParticlesBaseCell, cell1->_particleSoABuffer.size());
225 _pairwiseFunctor->SoAFunctorPair(stripeView, restView, _useNewton3);
226 if (not _useNewton3) {
227 _pairwiseFunctor->SoAFunctorPair(restView, stripeView, _useNewton3);
228 }
229 cell1ViewEnd = cell1->_particleSoABuffer.size();
230 continue;
231 } else {
232 // interval in other stripe
233 cell1ViewEnd = numParticlesBaseCell;
234 }
235 } else if (offset1 == _baseOffsets.front().back()) {
236 cell1 = &combinationSlice[currentSlice];
237 cell1ViewStart = combinationSlicesOffsets[currentSlice][combinationSlicesOffsets[currentSlice].size() - 2];
238 cell1ViewEnd = cell1->_particleSoABuffer.size();
239 } else if (offset1 == _baseOffsets.back().front()) {
240 const auto index = (currentSlice + numSlices - 1) % numSlices;
241 if (combinationSlicesOffsets[index][1] == 0) {
242 continue;
243 }
244 cell1 = &combinationSlice[index];
245 cell1ViewEnd = combinationSlicesOffsets[index][1];
246 } else {
247 const unsigned long cellIndex1 = baseIndex + offset1;
248 cell1 = &cells[cellIndex1];
249 cell1ViewEnd = cell1->_particleSoABuffer.size();
250 }
251
252 auto &currentCS = combinationSlice[slice];
253 const auto &currentCSOffsets = combinationSlicesOffsets[slice];
254 auto currentCSViewStart = currentCSOffsets[interval.first];
255 auto currentCSViewEnd = currentCSOffsets[interval.second];
256
257 auto cell1View = cell1->_particleSoABuffer.constructView(cell1ViewStart, cell1ViewEnd);
258 auto currentCSView = currentCS._particleSoABuffer.constructView(currentCSViewStart, currentCSViewEnd);
259 _pairwiseFunctor->SoAFunctorPair(cell1View, currentCSView, _useNewton3);
260 if (not _useNewton3) {
261 _pairwiseFunctor->SoAFunctorPair(currentCSView, cell1View, _useNewton3);
262 }
263 }
264 }
265
266 // write information of combined SoA buffers back to cell
267 writeBufferIntoCell(cells, baseIndex, combinationSlice, combinationSlicesOffsets, currentSlice, 0ul);
268
269 // last cell in stripe need to save whole buffer
270 if (x == _cellsPerDimension[0] - _overlap[0] - 1l) {
271 for (unsigned long slice = 1; slice < numSlices; slice++) {
272 const long bufferSlice = (currentSlice + slice) % numSlices;
273 writeBufferIntoCell(cells, baseIndex, combinationSlice, combinationSlicesOffsets, bufferSlice, slice);
274 }
275 }
276}
277
278template <class ParticleCell, class PairwiseFunctor>
280 const std::vector<ParticleCell> &cells, const unsigned long baseIndex, std::vector<ParticleCell> &combinationSlice,
281 std::vector<std::vector<unsigned long>> &combinationSlicesOffsets, const unsigned int bufferSlice,
282 const unsigned int cellSlice) {
283 // delete old data
284 combinationSlice[bufferSlice]._particleSoABuffer.clear();
285 combinationSlicesOffsets[bufferSlice].clear();
286 // fill buffer and compute partial sums
287 unsigned long sum = 0ul;
288 combinationSlicesOffsets[bufferSlice].push_back(sum);
289 for (const auto offset : _baseOffsets[cellSlice]) {
290 const unsigned long otherIndex = baseIndex + offset;
291 const ParticleCell &otherCell = cells[otherIndex];
292 combinationSlice[bufferSlice]._particleSoABuffer.append(otherCell._particleSoABuffer);
293 sum += otherCell.size();
294 combinationSlicesOffsets[bufferSlice].push_back(sum);
295 }
296}
297
298template <class ParticleCell, class PairwiseFunctor>
299inline void LCC04SoACellHandler<ParticleCell, PairwiseFunctor>::writeBufferIntoCell(
300 std::vector<ParticleCell> &cells, const unsigned long baseIndex, std::vector<ParticleCell> &combinationSlice,
301 std::vector<std::vector<unsigned long>> &combinationSlicesOffsets, const unsigned long bufferSlice,
302 const unsigned long cellSlice) {
303 auto &buffer = combinationSlice[bufferSlice]._particleSoABuffer;
304 for (long i = _baseOffsets[cellSlice].size() - 1l; i >= 0; i--) {
305 const auto start = combinationSlicesOffsets[bufferSlice][i];
306 const auto end = combinationSlicesOffsets[bufferSlice][i + 1];
307
308 if (start == end) {
309 continue;
310 }
311 buffer.resizeArrays(end);
312 auto bufferView = buffer.constructView(start, buffer.size());
313
314 const unsigned long currentOffset = baseIndex + _baseOffsets[cellSlice][i];
315 // clear old cell buffer
316 cells[currentOffset]._particleSoABuffer.clear();
317 // make sure everything is correct
318 if (bufferView.size() != cells[currentOffset].size()) {
319 const auto pos = utils::ThreeDimensionalMapping::oneToThreeD(currentOffset, _cellsPerDimension);
320 AutoPasLog(ERROR,
321 "Particle number in SoA buffer and cell doesn't match. current position: [{} {} {}] is: {} should: {}",
322 pos[0], pos[1], pos[2], buffer.size(), cells[currentOffset].size());
323 }
324 // append new cell buffer
325 cells[currentOffset]._particleSoABuffer.append(bufferView);
326 }
327}
328
329template <class ParticleCell, class PairwiseFunctor>
330inline void LCC04SoACellHandler<ParticleCell, PairwiseFunctor>::setupIntervals(
331 const std::array<unsigned long, 3> &cellsPerDimension) {
332 _baseOffsets.resize(_overlap[0] + 1);
333 for (unsigned long x = 0ul; x <= _overlap[0]; ++x) {
334 for (unsigned long y = 0ul; y <= _overlap[1]; ++y) {
335 _baseOffsets[x].push_back(utils::ThreeDimensionalMapping::threeToOneD(x, y, 0ul, cellsPerDimension));
336 }
337 }
338
339 std::vector<LCC08CellHandlerUtility::OffsetPairVector> cellPairOffsets =
340 LCC08CellHandlerUtility::computePairwiseCellOffsetsC08<LCC08CellHandlerUtility::C08OffsetMode::c04CellPairs>(
341 cellsPerDimension, this->_cellLength, this->_interactionLength);
342
343 // Create intervals
344 const unsigned long numStripes = cellPairOffsets.size();
345 _offsets.resize(numStripes);
346
347 // iterate over all stripes
348 for (unsigned long i = 0; i < numStripes; ++i) {
349 auto &currentStripe = cellPairOffsets[i];
350 // Sort
351 std::stable_sort(currentStripe.begin(), currentStripe.end(),
352 [](const auto &a, const auto &b) -> bool { return a.first < b.first; });
353
354 // Collect intervals
355 unsigned long current = currentStripe.front().first;
356 unsigned long startID =
357 std::distance(_baseOffsets[i].begin(),
358 std::find(_baseOffsets[i].begin(), _baseOffsets[i].end(), currentStripe.front().second));
359 unsigned long endID = startID;
360 for (unsigned long j = 0; j < currentStripe.size(); j++) {
361 if (current != currentStripe[j].first) {
362 auto interval = std::make_pair(startID, endID);
363 _offsets[i].push_back(std::make_pair(current, interval));
364 startID = std::distance(_baseOffsets[i].begin(),
365 std::find(_baseOffsets[i].begin(), _baseOffsets[i].end(), currentStripe[j].second));
366 endID = startID;
367 current = currentStripe[j].first;
368 }
369 endID++;
370 }
371 // last interval
372 auto interval = std::make_pair(startID, endID);
373 _offsets[i].push_back(std::make_pair(current, interval));
374 }
375}
376
377template <class ParticleCell, class PairwiseFunctor>
379 const auto numThreads = static_cast<size_t>(autopas_get_max_threads());
380 if (_combinationSlices.size() != numThreads) {
381 _combinationSlices.resize(numThreads);
382 const auto cellOffsetsSize = _overlap[0] + 1;
383 std::for_each(_combinationSlices.begin(), _combinationSlices.end(),
384 [cellOffsetsSize](auto &e) { e.resize(cellOffsetsSize); });
385 _combinationSlicesOffsets.resize(numThreads);
386 std::for_each(_combinationSlicesOffsets.begin(), _combinationSlicesOffsets.end(),
387 [cellOffsetsSize](auto &e) { e.resize(cellOffsetsSize); });
388 _currentSlices.resize(numThreads * _cacheOffset);
389 }
390}
391
392} // namespace autopas
#define AutoPasLog(lvl, fmt,...)
Macro for logging providing common meta information without filename.
Definition: Logger.h:24
This class provides the base for traversals using the c08 base step, but rather use 4 instead of 8 co...
Definition: LCC04SoACellHandler.h:31
void processBaseCell(std::vector< ParticleCell > &cells, unsigned long x, unsigned long y, unsigned long z)
Computes one interaction for each spacial direction based on the lower left frontal corner of a 2x2x2...
Definition: LCC04SoACellHandler.h:177
void resizeBuffers()
Resize all buffers to match the current number of threads.
Definition: LCC04SoACellHandler.h:378
LCC04SoACellHandler(PairwiseFunctor *pairwiseFunctor, const std::array< unsigned long, 3 > &cellsPerDimension, double interactionLength, const std::array< double, 3 > &cellLength, DataLayoutOption dataLayout, bool useNewton3, const std::array< unsigned long, 3 > &overlap={1ul, 1ul, 1ul})
Constructor of the c04 traversal with combined SoA buffers.
Definition: LCC04SoACellHandler.h:43
PairwiseFunctor class.
Definition: PairwiseFunctor.h:31
Class for Cells of Particles.
Definition: ParticleCell.h:51
virtual size_t size() const =0
Get the number of all particles stored in this cell (owned, halo and dummy).
constexpr std::array< T, 3 > oneToThreeD(T ind, const std::array< T, 3 > &dims)
Convert a 1d index to a 3d index.
Definition: ThreeDimensionalMapping.h:55
constexpr T threeToOneD(T x, T y, T z, const std::array< T, 3 > &dims)
Convert a 3d index to a 1d index.
Definition: ThreeDimensionalMapping.h:29
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:32
int autopas_get_max_threads()
Dummy for omp_get_max_threads() when no OpenMP is available.
Definition: WrapOpenMP.h:144
int autopas_get_thread_num()
Dummy for omp_set_lock() when no OpenMP is available.
Definition: WrapOpenMP.h:132
constexpr unsigned int DEFAULT_CACHE_LINE_SIZE
Default size for a cache line.
Definition: AlignedAllocator.h:21