23template <
class ParticleCell_T,
class ParticleFunctor_T,
bool b
idirectional = true>
35 explicit CellFunctor3B(ParticleFunctor_T &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.});
64 void processCellTriple(ParticleCell_T &cell1, ParticleCell_T &cell2, ParticleCell_T &cell3,
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; }
100 [[nodiscard]]
bool shouldUseSorting(
size_t particleCount,
const std::array<double, 3> &sortingDirection)
const {
101 return particleCount >= _sortingThreshold and
102 (sortingDirection[0] != 0.0 or sortingDirection[1] != 0.0 or sortingDirection[2] != 0.0);
114 void processCellAoSImpl(ParticleCell_T &cell);
123 void processCellPairAoSImpl(ParticleCell_T &cell1, ParticleCell_T &cell2,
124 const std::array<double, 3> &sortingDirection);
136 void processCellTripleAoSImpl(ParticleCell_T &cell1, ParticleCell_T &cell2, ParticleCell_T &cell3,
137 const std::array<double, 3> &sortingDirection);
144 void processCellPairSoAImpl(ParticleCell_T &cell1, ParticleCell_T &cell2);
152 void processCellTripleSoAImpl(ParticleCell_T &cell1, ParticleCell_T &cell2, ParticleCell_T &cell3);
154 ParticleFunctor_T &_functor;
156 const double _sortingCutoff;
163 size_t _sortingThreshold{8};
165 const DataLayoutOption::Value _dataLayout;
167 const bool _useNewton3;
170template <
class ParticleCell_T,
class ParticleFunctor_T,
bool b
idirectional>
172 _sortingThreshold = sortingThreshold;
175template <
class ParticleCell_T,
class ParticleFunctor_T,
bool b
idirectional>
177 const bool isAoS = _dataLayout == DataLayoutOption::aos ? true :
false;
178 const bool isSoA = _dataLayout == DataLayoutOption::soa ? true :
false;
181 if ((isSoA and cell._particleSoABuffer.size() == 0) or (isAoS and cell.isEmpty())) {
185 if (not cell.canHaveOwnedParticles()) {
190 processCellAoSImpl(cell);
192 _functor.SoAFunctorSingle(cell._particleSoABuffer, _useNewton3);
196template <
class ParticleCell_T,
class ParticleFunctor_T,
bool b
idirectional>
199 ParticleCell_T &cell1, ParticleCell_T &cell2,
const std::array<double, 3> &sortingDirection) {
200 const bool isAoS = _dataLayout == DataLayoutOption::aos ? true :
false;
201 const bool isSoA = _dataLayout == DataLayoutOption::soa ? true :
false;
204 if ((isSoA and (cell1._particleSoABuffer.size() == 0 or cell2._particleSoABuffer.size() == 0)) or
205 (isAoS and (cell1.isEmpty() or cell2.isEmpty()))) {
209 if (not cell1.canHaveOwnedParticles()) {
211 if constexpr (not bidirectional) {
212 if (not _useNewton3) {
217 if (not cell2.canHaveOwnedParticles()) {
223 processCellPairAoSImpl(cell1, cell2, sortingDirection);
225 processCellPairSoAImpl(cell1, cell2);
229template <
class ParticleCell_T,
class ParticleFunctor_T,
bool b
idirectional>
232 ParticleCell_T &cell1, ParticleCell_T &cell2, ParticleCell_T &cell3,
233 const std::array<double, 3> &sortingDirection) {
234 const bool isAoS = _dataLayout == DataLayoutOption::aos ? true :
false;
235 const bool isSoA = _dataLayout == DataLayoutOption::soa ? true :
false;
238 if ((isSoA and (cell1._particleSoABuffer.size() == 0 or cell2._particleSoABuffer.size() == 0 or
239 cell3._particleSoABuffer.size() == 0)) or
240 (isAoS and (cell1.isEmpty() or cell2.isEmpty() or cell3.isEmpty()))) {
244 if (not cell1.canHaveOwnedParticles()) {
246 if constexpr (not bidirectional) {
247 if (not _useNewton3) {
252 if (not cell2.canHaveOwnedParticles() and not cell3.canHaveOwnedParticles()) {
258 processCellTripleAoSImpl(cell1, cell2, cell3, sortingDirection);
260 processCellTripleSoAImpl(cell1, cell2, cell3);
264template <
class ParticleCell_T,
class ParticleFunctor_T,
bool b
idirectional>
267 const auto interactParticles = [
this](
auto &p1,
auto &p2,
auto &p3) {
268 this->_functor.AoSFunctor(p1, p2, p3, this->_useNewton3);
269 if (not this->_useNewton3) {
270 this->_functor.AoSFunctor(p2, p1, p3,
false);
271 this->_functor.AoSFunctor(p3, p1, p2,
false);
275 if (cell.size() >= _sortingThreshold) {
278 for (
auto cellIter1 = cellSorted._particles.begin(); cellIter1 != cellSorted._particles.end(); ++cellIter1) {
279 auto &[p1Projection, p1Ptr] = *cellIter1;
281 for (
auto cellIter2 = std::next(cellIter1); cellIter2 != cellSorted._particles.end(); ++cellIter2) {
282 auto &[p2Projection, p2Ptr] = *cellIter2;
283 if (std::abs(p2Projection - p1Projection) > _sortingCutoff) {
287 for (
auto cellIter3 = std::next(cellIter2); cellIter3 != cellSorted._particles.end(); ++cellIter3) {
288 auto &[p3Projection, p3Ptr] = *cellIter3;
289 if (std::abs(p3Projection - p1Projection) > _sortingCutoff or
290 std::abs(p3Projection - p2Projection) > _sortingCutoff) {
293 interactParticles(*p1Ptr, *p2Ptr, *p3Ptr);
298 for (
auto p1Ptr = cell.begin(); p1Ptr != cell.end(); ++p1Ptr) {
301 for (; p2Ptr != cell.end(); ++p2Ptr) {
304 for (; p3Ptr != cell.end(); ++p3Ptr) {
305 interactParticles(*p1Ptr, *p2Ptr, *p3Ptr);
312template <
class ParticleCell_T,
class ParticleFunctor_T,
bool b
idirectional>
313void CellFunctor3B<ParticleCell_T, ParticleFunctor_T, bidirectional>::processCellPairAoSImpl(
314 ParticleCell_T &cell1, ParticleCell_T &cell2,
const std::array<double, 3> &sortingDirection) {
315 const auto interactParticles = [
this](
auto &p1,
auto &p2,
auto &p3,
const bool p2FromCell1) {
316 this->_functor.AoSFunctor(p1, p2, p3, this->_useNewton3);
317 if (not this->_useNewton3) {
319 this->_functor.AoSFunctor(p2, p1, p3,
false);
321 if constexpr (bidirectional) {
322 this->_functor.AoSFunctor(p2, p1, p3,
false);
325 if constexpr (bidirectional) {
326 this->_functor.AoSFunctor(p3, p1, p2,
false);
331 if (shouldUseSorting(cell1.size() + cell2.size(), sortingDirection)) {
332 SortedCellView<ParticleCell_T> cell1Sorted(cell1, sortingDirection);
333 SortedCellView<ParticleCell_T> cell2Sorted(cell2, sortingDirection);
336 for (
auto cellIter1 = cell1Sorted._particles.begin(); cellIter1 != cell1Sorted._particles.end(); ++cellIter1) {
337 auto &[p1Projection, p1Ptr] = *cellIter1;
340 for (
auto cellIter2 = std::next(cellIter1); cellIter2 != cell1Sorted._particles.end(); ++cellIter2) {
341 auto &[p2Projection, p2Ptr] = *cellIter2;
342 if (std::abs(p2Projection - p1Projection) > _sortingCutoff) {
345 for (
auto &[p3Projection, p3Ptr] : cell2Sorted._particles) {
346 if (std::abs(p3Projection - p2Projection) > _sortingCutoff or
347 std::abs(p3Projection - p1Projection) > _sortingCutoff) {
350 interactParticles(*p1Ptr, *p2Ptr, *p3Ptr,
true);
355 for (
auto cellIter2 = cell2Sorted._particles.begin(); cellIter2 != cell2Sorted._particles.end(); ++cellIter2) {
356 auto &[p2Projection, p2Ptr] = *cellIter2;
357 if (std::abs(p2Projection - p1Projection) > _sortingCutoff) {
360 for (
auto cellIter3 = std::next(cellIter2); cellIter3 != cell2Sorted._particles.end(); ++cellIter3) {
361 auto &[p3Projection, p3Ptr] = *cellIter3;
362 if (std::abs(p3Projection - p2Projection) > _sortingCutoff or
363 std::abs(p3Projection - p1Projection) > _sortingCutoff) {
366 interactParticles(*p1Ptr, *p2Ptr, *p3Ptr,
false);
372 for (
auto p1Ptr = cell1.begin(); p1Ptr != cell1.end(); ++p1Ptr) {
376 for (; p2Ptr != cell1.end(); ++p2Ptr) {
377 for (
auto &p3 : cell2) {
378 interactParticles(*p1Ptr, *p2Ptr, p3,
true);
383 for (
auto p2Ptr = cell2.begin(); p2Ptr != cell2.end(); ++p2Ptr) {
386 for (; p3Ptr != cell2.end(); ++p3Ptr) {
387 interactParticles(*p1Ptr, *p2Ptr, *p3Ptr,
false);
394template <
class ParticleCell_T,
class ParticleFunctor_T,
bool b
idirectional>
395void CellFunctor3B<ParticleCell_T, ParticleFunctor_T, bidirectional>::processCellTripleAoSImpl(
396 ParticleCell_T &cell1, ParticleCell_T &cell2, ParticleCell_T &cell3,
397 const std::array<double, 3> &sortingDirection) {
398 const auto interactParticles = [
this](
auto &p1,
auto &p2,
auto &p3) {
399 this->_functor.AoSFunctor(p1, p2, p3, this->_useNewton3);
401 if constexpr (bidirectional) {
402 if (not this->_useNewton3) {
403 this->_functor.AoSFunctor(p2, p1, p3,
false);
404 this->_functor.AoSFunctor(p3, p1, p2,
false);
409 if (shouldUseSorting(cell1.size() + cell2.size() + cell3.size(), sortingDirection)) {
410 SortedCellView<ParticleCell_T> cell1Sorted(cell1, sortingDirection);
411 SortedCellView<ParticleCell_T> cell2Sorted(cell2, sortingDirection);
413 for (
auto &[p1Projection, p1Ptr] : cell1Sorted._particles) {
414 for (
auto &[p2Projection, p2Ptr] : cell2Sorted._particles) {
415 if (std::abs(p2Projection - p1Projection) > _sortingCutoff) {
418 for (
auto &p3 : cell3) {
419 interactParticles(*p1Ptr, *p2Ptr, p3);
424 for (
auto &p1 : cell1) {
425 for (
auto &p2 : cell2) {
426 for (
auto &p3 : cell3) {
427 interactParticles(p1, p2, p3);
434template <
class ParticleCell_T,
class ParticleFunctor_T,
bool b
idirectional>
435void CellFunctor3B<ParticleCell_T, ParticleFunctor_T, bidirectional>::processCellPairSoAImpl(ParticleCell_T &cell1,
436 ParticleCell_T &cell2) {
437 _functor.SoAFunctorPair(cell1._particleSoABuffer, cell2._particleSoABuffer, _useNewton3);
438 if constexpr (bidirectional) {
439 if (not _useNewton3) {
440 _functor.SoAFunctorPair(cell2._particleSoABuffer, cell1._particleSoABuffer,
false);
445template <
class ParticleCell_T,
class ParticleFunctor_T,
bool b
idirectional>
446void CellFunctor3B<ParticleCell_T, ParticleFunctor_T, bidirectional>::processCellTripleSoAImpl(ParticleCell_T &cell1,
447 ParticleCell_T &cell2,
448 ParticleCell_T &cell3) {
449 _functor.SoAFunctorTriple(cell1._particleSoABuffer, cell2._particleSoABuffer, cell3._particleSoABuffer, _useNewton3);
450 if constexpr (bidirectional) {
451 if (not _useNewton3) {
452 _functor.SoAFunctorTriple(cell2._particleSoABuffer, cell1._particleSoABuffer, cell3._particleSoABuffer,
false);
453 _functor.SoAFunctorTriple(cell3._particleSoABuffer, cell1._particleSoABuffer, cell2._particleSoABuffer,
false);
A cell functor.
Definition: CellFunctor3B.h:24
DataLayoutOption::Value getDataLayout() const
Getter.
Definition: CellFunctor3B.h:71
void processCellTriple(ParticleCell_T &cell1, ParticleCell_T &cell2, ParticleCell_T &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:230
void processCell(ParticleCell_T &cell)
Process the interactions inside one cell.
Definition: CellFunctor3B.h:176
CellFunctor3B(ParticleFunctor_T &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_T &cell1, ParticleCell_T &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:197
bool getNewton3() const
Getter.
Definition: CellFunctor3B.h:77
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:171
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