30template <
class ParticleCell,
class PairwiseFunctor>
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),
50 _cellsPerDimension(cellsPerDimension),
52 _pairwiseFunctor(pairwiseFunctor),
53 _dataLayout(dataLayout),
54 _useNewton3(useNewton3) {
55 setupIntervals(cellsPerDimension);
66 void processBaseCell(std::vector<ParticleCell> &cells,
unsigned long x,
unsigned long y,
unsigned long z);
77 const double _interactionLength;
82 const std::array<double, 3> _cellLength;
87 const std::array<unsigned long, 3> _overlap;
89 const std::array<unsigned long, 3> _cellsPerDimension;
94 std::vector<std::vector<ParticleCell>> _combinationSlices;
99 std::vector<unsigned int> _currentSlices;
104 std::vector<std::vector<unsigned long>> _baseOffsets;
109 using interval_t = std::pair<unsigned long, unsigned long>;
114 std::vector<std::vector<std::pair<unsigned long, interval_t>>> _offsets;
119 std::vector<std::vector<std::vector<unsigned long>>> _combinationSlicesOffsets;
124 const unsigned int _cacheOffset;
134 DataLayoutOption _dataLayout;
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);
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);
173 void setupIntervals(
const std::array<unsigned long, 3> &cellsPerDimension);
176template <
class ParticleCell,
class PairwiseFunctor>
178 unsigned long x,
unsigned long y,
184 auto ¤tSlice = _currentSlices[threadID * _cacheOffset];
185 auto &combinationSlice = _combinationSlices[threadID];
186 auto &combinationSlicesOffsets = _combinationSlicesOffsets[threadID];
188 const size_t numSlices = _baseOffsets.size();
193 for (
unsigned int slice = 0ul; slice < numSlices; slice++) {
194 writeCellIntoBuffer(cells, baseIndex, combinationSlice, combinationSlicesOffsets, slice, slice);
197 writeCellIntoBuffer(cells, baseIndex, combinationSlice, combinationSlicesOffsets, currentSlice, numSlices - 1ul);
199 ++currentSlice %= numSlices;
203 for (
unsigned long slice = 0; slice < numSlices; slice++) {
204 for (
auto const &[offset1, interval] : _offsets[(slice + currentSlice) % numSlices]) {
206 size_t cell1ViewStart = 0;
211 if (offset1 == 0ul) {
212 const auto numParticlesBaseCell = cells[baseIndex].
size();
213 if (numParticlesBaseCell == 0) {
217 cell1 = &combinationSlice[currentSlice];
218 auto stripeView = cell1->_particleSoABuffer.constructView(0, numParticlesBaseCell);
219 if (slice == currentSlice) {
221 _pairwiseFunctor->SoAFunctorSingle(stripeView, _useNewton3);
224 cell1->_particleSoABuffer.constructView(numParticlesBaseCell, cell1->_particleSoABuffer.
size());
225 _pairwiseFunctor->SoAFunctorPair(stripeView, restView, _useNewton3);
226 if (not _useNewton3) {
227 _pairwiseFunctor->SoAFunctorPair(restView, stripeView, _useNewton3);
229 cell1ViewEnd = cell1->_particleSoABuffer.
size();
233 cell1ViewEnd = numParticlesBaseCell;
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) {
244 cell1 = &combinationSlice[index];
245 cell1ViewEnd = combinationSlicesOffsets[index][1];
247 const unsigned long cellIndex1 = baseIndex + offset1;
248 cell1 = &cells[cellIndex1];
249 cell1ViewEnd = cell1->_particleSoABuffer.
size();
252 auto ¤tCS = combinationSlice[slice];
253 const auto ¤tCSOffsets = combinationSlicesOffsets[slice];
254 auto currentCSViewStart = currentCSOffsets[interval.first];
255 auto currentCSViewEnd = currentCSOffsets[interval.second];
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);
267 writeBufferIntoCell(cells, baseIndex, combinationSlice, combinationSlicesOffsets, currentSlice, 0ul);
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);
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) {
284 combinationSlice[bufferSlice]._particleSoABuffer.clear();
285 combinationSlicesOffsets[bufferSlice].clear();
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;
292 combinationSlice[bufferSlice]._particleSoABuffer.append(otherCell._particleSoABuffer);
293 sum += otherCell.
size();
294 combinationSlicesOffsets[bufferSlice].push_back(sum);
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];
311 buffer.resizeArrays(end);
312 auto bufferView = buffer.constructView(start, buffer.size());
314 const unsigned long currentOffset = baseIndex + _baseOffsets[cellSlice][i];
316 cells[currentOffset]._particleSoABuffer.clear();
318 if (bufferView.size() != cells[currentOffset].size()) {
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());
325 cells[currentOffset]._particleSoABuffer.append(bufferView);
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) {
339 std::vector<LCC08CellHandlerUtility::OffsetPairVector> cellPairOffsets =
340 LCC08CellHandlerUtility::computePairwiseCellOffsetsC08<LCC08CellHandlerUtility::C08OffsetMode::c04CellPairs>(
341 cellsPerDimension, this->_cellLength, this->_interactionLength);
344 const unsigned long numStripes = cellPairOffsets.size();
345 _offsets.resize(numStripes);
348 for (
unsigned long i = 0; i < numStripes; ++i) {
349 auto ¤tStripe = cellPairOffsets[i];
351 std::stable_sort(currentStripe.begin(), currentStripe.end(),
352 [](
const auto &a,
const auto &b) ->
bool { return a.first < b.first; });
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));
367 current = currentStripe[j].first;
372 auto interval = std::make_pair(startID, endID);
373 _offsets[i].push_back(std::make_pair(current, interval));
377template <
class ParticleCell,
class PairwiseFunctor>
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);
#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