23template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional = true>
35 explicit CellFunctor3B(ParticleFunctor *f,
const double sortingCutoff, DataLayoutOption dataLayout,
bool useNewton3)
36 : _functor(f), _sortingCutoff(sortingCutoff), _dataLayout(dataLayout), _useNewton3(useNewton3) {}
54 const std::array<double, 3> &sortingDirection = {0., 0., 0.});
65 const std::array<double, 3> &sortingDirection = {0., 0., 0.});
71 [[nodiscard]] DataLayoutOption::Value
getDataLayout()
const {
return _dataLayout; }
77 [[nodiscard]]
bool getNewton3()
const {
return _useNewton3; }
122 void processCellPairAoSNoN3(
ParticleCell &cell1,
ParticleCell &cell2,
const std::array<double, 3> &sortingDirection);
136 const std::array<double, 3> &sortingDirection);
150 const std::array<double, 3> &sortingDirection);
164 ParticleFunctor *_functor;
166 const double _sortingCutoff;
173 size_t _sortingThreshold{8};
175 DataLayoutOption _dataLayout;
180template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
182 _sortingThreshold = sortingThreshold;
185template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
187 if ((_dataLayout == DataLayoutOption::soa and cell._particleSoABuffer.
size() == 0) or
188 (_dataLayout == DataLayoutOption::aos and cell.
isEmpty())) {
194 if (not cellHasOwnedParticles) {
199 switch (
static_cast<DataLayoutOption::Value
>(_dataLayout)) {
200 case DataLayoutOption::aos:
201 processCellAoS(cell);
203 case DataLayoutOption::soa:
205 processCellSoAN3(cell);
207 processCellSoANoN3(cell);
213template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
217 if ((_dataLayout == DataLayoutOption::soa and
218 (cell1._particleSoABuffer.
size() == 0 or cell2._particleSoABuffer.
size() == 0)) or
219 (_dataLayout == DataLayoutOption::aos and (cell1.
size() == 0 or cell2.
size() == 0))) {
228 if (((not cell1HasOwnedParticles) and (not _useNewton3) and (not bidirectional)) or
229 ((not cell1HasOwnedParticles) and (not cell2HasOwnedParticles))) {
234 switch (
static_cast<DataLayoutOption::Value
>(_dataLayout)) {
235 case DataLayoutOption::aos:
237 processCellPairAoSN3(cell1, cell2, sortingDirection);
239 processCellPairAoSNoN3(cell1, cell2, sortingDirection);
242 case DataLayoutOption::soa:
244 processCellPairSoAN3(cell1, cell2);
246 processCellPairSoANoN3(cell1, cell2);
252template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
256 if ((_dataLayout == DataLayoutOption::soa and
257 (cell1._particleSoABuffer.
size() == 0 or cell2._particleSoABuffer.
size() == 0 or
258 cell3._particleSoABuffer.
size() == 0)) or
259 (_dataLayout == DataLayoutOption::aos and (cell1.
size() == 0 or cell2.
size() == 0 or cell3.
size() == 0))) {
269 if (((not cell1HasOwnedParticles) and (not _useNewton3) and (not bidirectional)) or
270 ((not cell1HasOwnedParticles) and (not cell2HasOwnedParticles) and (not cell3HasOwnedParticles))) {
275 switch (
static_cast<DataLayoutOption::Value
>(_dataLayout)) {
276 case DataLayoutOption::aos:
278 processCellTripleAoSN3(cell1, cell2, cell3, sortingDirection);
280 processCellTripleAoSNoN3(cell1, cell2, cell3, sortingDirection);
283 case DataLayoutOption::soa:
285 processCellTripleSoAN3(cell1, cell2, cell3);
287 processCellTripleSoANoN3(cell1, cell2, cell3);
293template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
296 const auto interactParticles = [&](
auto &p1,
auto &p2,
auto &p3) {
298 _functor->AoSFunctor(p1, p2, p3,
true);
300 if (not p1.isHalo()) {
301 _functor->AoSFunctor(p1, p2, p3,
false);
303 if (not p2.isHalo()) {
304 _functor->AoSFunctor(p2, p1, p3,
false);
306 if (not p3.isHalo()) {
307 _functor->AoSFunctor(p3, p1, p2,
false);
312 if (cell.
size() > _sortingThreshold) {
315 for (
auto cellIter1 = cellSorted._particles.begin(); cellIter1 != cellSorted._particles.end(); ++cellIter1) {
316 auto &[p1Projection, p1Ptr] = *cellIter1;
318 for (
auto cellIter2 = std::next(cellIter1); cellIter2 != cellSorted._particles.end(); ++cellIter2) {
319 auto &[p2Projection, p2Ptr] = *cellIter2;
320 if (std::abs(p1Projection - p2Projection) > _sortingCutoff) {
324 for (
auto cellIter3 = std::next(cellIter2); cellIter3 != cellSorted._particles.end(); ++cellIter3) {
325 auto &[p3Projection, p3Ptr] = *cellIter3;
326 if (std::abs(p1Projection - p3Projection) > _sortingCutoff or
327 std::abs(p2Projection - p3Projection) > _sortingCutoff) {
330 interactParticles(*p1Ptr, *p2Ptr, *p3Ptr);
335 for (
auto p1Ptr = cell.begin(); p1Ptr != cell.end(); ++p1Ptr) {
338 for (; p2Ptr != cell.end(); ++p2Ptr) {
341 for (; p3Ptr != cell.end(); ++p3Ptr) {
342 interactParticles(*p1Ptr, *p2Ptr, *p3Ptr);
349template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
350void CellFunctor3B<ParticleCell, ParticleFunctor, bidirectional>::processCellPairAoSN3(
351 ParticleCell &cell1, ParticleCell &cell2,
const std::array<double, 3> &sortingDirection) {
352 if ((cell1.size() + cell2.size() > _sortingThreshold) and sortingDirection != std::array<double, 3>{0., 0., 0.}) {
353 SortedCellView<ParticleCell> cell1Sorted(cell1, sortingDirection);
354 SortedCellView<ParticleCell> cell2Sorted(cell2, sortingDirection);
357 for (
auto cellIter1 = cell1Sorted._particles.begin(); cellIter1 != cell1Sorted._particles.end(); ++cellIter1) {
358 auto &[p1Projection, p1Ptr] = *cellIter1;
361 for (
auto cellIter2 = std::next(cellIter1); cellIter2 != cell1Sorted._particles.end(); ++cellIter2) {
362 auto &[p2Projection, p2Ptr] = *cellIter2;
363 if (std::abs(p1Projection - p2Projection) > _sortingCutoff) {
366 for (
auto &[p3Projection, p3Ptr] : cell2Sorted._particles) {
367 if (std::abs(p2Projection - p3Projection) > _sortingCutoff or
368 std::abs(p1Projection - p3Projection) > _sortingCutoff) {
371 _functor->AoSFunctor(*p1Ptr, *p2Ptr, *p3Ptr,
true);
376 for (
auto cellIter2 = cell2Sorted._particles.begin(); cellIter2 != cell2Sorted._particles.end(); ++cellIter2) {
377 auto &[p2Projection, p2Ptr] = *cellIter2;
378 if (std::abs(p1Projection - p2Projection) > _sortingCutoff) {
381 for (
auto cellIter3 = std::next(cellIter2); cellIter3 != cell2Sorted._particles.end(); ++cellIter3) {
382 auto &[p3Projection, p3Ptr] = *cellIter3;
383 if (std::abs(p2Projection - p3Projection) > _sortingCutoff or
384 std::abs(p1Projection - p3Projection) > _sortingCutoff) {
387 _functor->AoSFunctor(*p1Ptr, *p2Ptr, *p3Ptr,
true);
393 for (
auto p1Ptr = cell1.begin(); p1Ptr != cell1.end(); ++p1Ptr) {
397 for (; p2Ptr != cell1.end(); ++p2Ptr) {
398 for (
auto &p3 : cell2) {
399 _functor->AoSFunctor(*p1Ptr, *p2Ptr, p3,
true);
404 for (
auto p2Ptr = cell2.begin(); p2Ptr != cell2.end(); ++p2Ptr) {
407 for (; p3Ptr != cell2.end(); ++p3Ptr) {
408 _functor->AoSFunctor(*p1Ptr, *p2Ptr, *p3Ptr,
true);
415template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
416void CellFunctor3B<ParticleCell, ParticleFunctor, bidirectional>::processCellPairAoSNoN3(
417 ParticleCell &cell1, ParticleCell &cell2,
const std::array<double, 3> &sortingDirection) {
419 const auto interactParticles = [&](
auto &p1,
auto &p2,
auto &p3,
const bool p2FromCell1) {
420 _functor->AoSFunctor(p1, p2, p3,
false);
422 _functor->AoSFunctor(p2, p1, p3,
false);
424 if constexpr (bidirectional) {
425 _functor->AoSFunctor(p2, p1, p3,
false);
428 if constexpr (bidirectional) {
429 _functor->AoSFunctor(p3, p1, p2,
false);
433 if ((cell1.size() + cell2.size() > _sortingThreshold) and sortingDirection != std::array<double, 3>{0., 0., 0.}) {
434 SortedCellView<ParticleCell> cell1Sorted(cell1, sortingDirection);
435 SortedCellView<ParticleCell> cell2Sorted(cell2, sortingDirection);
438 for (
auto cellIter1 = cell1Sorted._particles.begin(); cellIter1 != cell1Sorted._particles.end(); ++cellIter1) {
439 auto &[p1Projection, p1Ptr] = *cellIter1;
442 for (
auto cellIter2 = std::next(cellIter1); cellIter2 != cell1Sorted._particles.end(); ++cellIter2) {
443 auto &[p2Projection, p2Ptr] = *cellIter2;
444 if (std::abs(p1Projection - p2Projection) > _sortingCutoff) {
447 for (
auto &[p3Projection, p3Ptr] : cell2Sorted._particles) {
448 if (std::abs(p2Projection - p3Projection) > _sortingCutoff or
449 std::abs(p1Projection - p3Projection) > _sortingCutoff) {
452 interactParticles(*p1Ptr, *p2Ptr, *p3Ptr,
true);
457 for (
auto cellIter2 = cell2Sorted._particles.begin(); cellIter2 != cell2Sorted._particles.end(); ++cellIter2) {
458 auto &[p2Projection, p2Ptr] = *cellIter2;
459 if (std::abs(p1Projection - p2Projection) > _sortingCutoff) {
462 for (
auto cellIter3 = std::next(cellIter2); cellIter3 != cell2Sorted._particles.end(); ++cellIter3) {
463 auto &[p3Projection, p3Ptr] = *cellIter3;
464 if (std::abs(p2Projection - p3Projection) > _sortingCutoff or
465 std::abs(p1Projection - p3Projection) > _sortingCutoff) {
468 interactParticles(*p1Ptr, *p2Ptr, *p3Ptr,
false);
474 for (
auto p1Ptr = cell1.begin(); p1Ptr != cell1.end(); ++p1Ptr) {
478 for (; p2Ptr != cell1.end(); ++p2Ptr) {
479 for (
auto &p3 : cell2) {
480 interactParticles(*p1Ptr, *p2Ptr, p3,
true);
485 for (
auto p2Ptr = cell2.begin(); p2Ptr != cell2.end(); ++p2Ptr) {
488 for (; p3Ptr != cell2.end(); ++p3Ptr) {
489 interactParticles(*p1Ptr, *p2Ptr, *p3Ptr,
false);
496template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
497void CellFunctor3B<ParticleCell, ParticleFunctor, bidirectional>::processCellTripleAoSN3(
498 ParticleCell &cell1, ParticleCell &cell2, ParticleCell &cell3,
const std::array<double, 3> &sortingDirection) {
499 if ((cell1.size() + cell2.size() + cell3.size() > _sortingThreshold) and
500 sortingDirection != std::array<double, 3>{0., 0., 0.}) {
501 SortedCellView<ParticleCell> cell1Sorted(cell1, sortingDirection);
502 SortedCellView<ParticleCell> cell2Sorted(cell2, sortingDirection);
504 for (
auto &[p1Projection, p1Ptr] : cell1Sorted._particles) {
505 for (
auto &[p2Projection, p2Ptr] : cell2Sorted._particles) {
506 if (std::abs(p1Projection - p2Projection) > _sortingCutoff) {
509 for (
auto &p3 : cell3) {
510 _functor->AoSFunctor(*p1Ptr, *p2Ptr, p3,
true);
515 for (
auto &p1 : cell1) {
516 for (
auto &p2 : cell2) {
517 for (
auto &p3 : cell3) {
518 _functor->AoSFunctor(p1, p2, p3,
true);
525template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
526void CellFunctor3B<ParticleCell, ParticleFunctor, bidirectional>::processCellTripleAoSNoN3(
527 ParticleCell &cell1, ParticleCell &cell2, ParticleCell &cell3,
const std::array<double, 3> &sortingDirection) {
529 const auto interactParticlesNoN3 = [&](
auto &p1,
auto &p2,
auto &p3) {
530 _functor->AoSFunctor(p1, p2, p3,
false);
531 if constexpr (bidirectional) {
532 _functor->AoSFunctor(p2, p1, p3,
false);
533 _functor->AoSFunctor(p3, p1, p2,
false);
537 if (cell1.size() + cell2.size() + cell3.size() > _sortingThreshold and
538 sortingDirection != std::array<double, 3>{0., 0., 0.}) {
539 SortedCellView<ParticleCell> cell1Sorted(cell1, sortingDirection);
540 SortedCellView<ParticleCell> cell2Sorted(cell2, sortingDirection);
542 for (
auto &[p1Projection, p1Ptr] : cell1Sorted._particles) {
543 for (
auto &[p2Projection, p2Ptr] : cell2Sorted._particles) {
544 if (std::abs(p1Projection - p2Projection) > _sortingCutoff) {
548 for (
auto &p3 : cell3) {
549 interactParticlesNoN3(*p1Ptr, *p2Ptr, p3);
554 for (
auto &p1 : cell1) {
555 for (
auto &p2 : cell2) {
556 for (
auto &p3 : cell3) {
557 interactParticlesNoN3(p1, p2, p3);
564template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
565void CellFunctor3B<ParticleCell, ParticleFunctor, bidirectional>::processCellSoAN3(ParticleCell &cell) {
566 _functor->SoAFunctorSingle(cell._particleSoABuffer,
true);
569template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
570void CellFunctor3B<ParticleCell, ParticleFunctor, bidirectional>::processCellSoANoN3(ParticleCell &cell) {
571 _functor->SoAFunctorSingle(cell._particleSoABuffer,
false);
574template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
575void CellFunctor3B<ParticleCell, ParticleFunctor, bidirectional>::processCellPairSoAN3(ParticleCell &cell1,
576 ParticleCell &cell2) {
577 _functor->SoAFunctorPair(cell1._particleSoABuffer, cell2._particleSoABuffer,
true);
580template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
581void CellFunctor3B<ParticleCell, ParticleFunctor, bidirectional>::processCellPairSoANoN3(ParticleCell &cell1,
582 ParticleCell &cell2) {
583 _functor->SoAFunctorPair(cell1._particleSoABuffer, cell2._particleSoABuffer,
false);
584 if (bidirectional) _functor->SoAFunctorPair(cell2._particleSoABuffer, cell1._particleSoABuffer,
false);
587template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
588void CellFunctor3B<ParticleCell, ParticleFunctor, bidirectional>::processCellTripleSoAN3(ParticleCell &cell1,
590 ParticleCell &cell3) {
591 _functor->SoAFunctorTriple(cell1._particleSoABuffer, cell2._particleSoABuffer, cell3._particleSoABuffer,
true);
594template <
class ParticleCell,
class ParticleFunctor,
bool b
idirectional>
595void CellFunctor3B<ParticleCell, ParticleFunctor, bidirectional>::processCellTripleSoANoN3(ParticleCell &cell1,
597 ParticleCell &cell3) {
598 _functor->SoAFunctorTriple(cell1._particleSoABuffer, cell2._particleSoABuffer, cell3._particleSoABuffer,
false);
600 _functor->SoAFunctorTriple(cell2._particleSoABuffer, cell1._particleSoABuffer, cell3._particleSoABuffer,
false);
601 _functor->SoAFunctorTriple(cell3._particleSoABuffer, cell1._particleSoABuffer, cell2._particleSoABuffer,
false);
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).
virtual bool isEmpty() const =0
Check if the cell is empty.
OwnershipState getPossibleParticleOwnerships() const
Get the type of particles contained in this cell.
Definition: ParticleCell.h:151
A cell functor.
Definition: CellFunctor3B.h:24
void processCellTriple(ParticleCell &cell1, ParticleCell &cell2, ParticleCell &cell3, const std::array< double, 3 > &sortingDirection={0., 0., 0.})
Process the interactions between 3 particles, all located in a different cell.
Definition: CellFunctor3B.h:253
void setSortingThreshold(size_t sortingThreshold)
Set the sorting-threshold If the sum of the number of particles in three cells is greater or equal to...
Definition: CellFunctor3B.h:181
void processCell(ParticleCell &cell)
Process the interactions inside one cell.
Definition: CellFunctor3B.h:186
DataLayoutOption::Value getDataLayout() const
Getter.
Definition: CellFunctor3B.h:71
CellFunctor3B(ParticleFunctor *f, const double sortingCutoff, DataLayoutOption dataLayout, bool useNewton3)
The constructor of CellFunctor3B.
Definition: CellFunctor3B.h:35
bool getBidirectional() const
Getter.
Definition: CellFunctor3B.h:83
void processCellPair(ParticleCell &cell1, ParticleCell &cell2, const std::array< double, 3 > &sortingDirection={0., 0., 0.})
Process the interactions between the particles of cell1 with particles of cell2.
Definition: CellFunctor3B.h:214
bool getNewton3() const
Getter.
Definition: CellFunctor3B.h:77
This namespace is used for implementation specifics.
Definition: CellFunctor.h:14
constexpr std::array< T, SIZE > normalize(const std::array< T, SIZE > &a)
Generates a normalized array (|a| = 1).
Definition: ArrayMath.h:304
constexpr int64_t toInt64(const OwnershipState a)
Returns the int64_t value of a given OwnershipState.
Definition: OwnershipState.h:56
@ owned
Owned state, a particle with this state is an actual particle and owned by the current AutoPas object...