AutoPas  3.0.0
Loading...
Searching...
No Matches
CellFunctor.h
Go to the documentation of this file.
1
8#pragma once
9
13
24template <class ParticleCell_T, class ParticleFunctor_T, bool bidirectional = true>
26 public:
36 explicit CellFunctor(ParticleFunctor_T &f, const double sortingCutoff, DataLayoutOption dataLayout, bool useNewton3)
37 : _functor(f), _sortingCutoff(sortingCutoff), _dataLayout(dataLayout), _useNewton3(useNewton3) {}
38
43 void processCell(ParticleCell_T &cell);
44
52 void processCellPair(ParticleCell_T &cell1, ParticleCell_T &cell2,
53 const std::array<double, 3> &sortingDirection = {0., 0., 0.});
54
59 [[nodiscard]] DataLayoutOption::Value getDataLayout() const { return _dataLayout; }
60
65 [[nodiscard]] bool getNewton3() const { return _useNewton3; }
66
71 [[nodiscard]] bool getBidirectional() const { return bidirectional; }
72
79 void setSortingThreshold(size_t sortingThreshold);
80
81 private:
88 [[nodiscard]] bool shouldUseSorting(size_t particleCount, const std::array<double, 3> &sortingDirection) const {
89 return particleCount >= _sortingThreshold and
90 (sortingDirection[0] != 0.0 or sortingDirection[1] != 0.0 or sortingDirection[2] != 0.0);
91 }
92
102 void processCellAoSImpl(ParticleCell_T &cell);
103
110 void processCellPairAoSImpl(ParticleCell_T &cell1, ParticleCell_T &cell2,
111 const std::array<double, 3> &sortingDirection);
112
118 void processCellPairSoAImpl(ParticleCell_T &cell1, ParticleCell_T &cell2);
119
120 ParticleFunctor_T &_functor;
121
122 const double _sortingCutoff;
123
128 size_t _sortingThreshold{8};
129
130 const DataLayoutOption::Value _dataLayout;
131
132 const bool _useNewton3;
133};
134
135template <class ParticleCell_T, class ParticleFunctor_T, bool bidirectional>
137 _sortingThreshold = sortingThreshold;
138}
139
140template <class ParticleCell_T, class ParticleFunctor_T, bool bidirectional>
142 const bool isAoS = _dataLayout == DataLayoutOption::aos ? true : false;
143 const bool isSoA = _dataLayout == DataLayoutOption::soa ? true : false;
144
145 // Return early if the cell is empty.
146 if ((isSoA and cell._particleSoABuffer.size() == 0) or (isAoS and cell.isEmpty())) {
147 return;
148 }
149 // Avoid force calculations if the cell contains only halo particles or if the cell is empty (=dummy)
150 if (not cell.canHaveOwnedParticles()) {
151 return;
152 }
153
154 if (isAoS) {
155 processCellAoSImpl(cell);
156 } else if (isSoA) {
157 _functor.SoAFunctorSingle(cell._particleSoABuffer, _useNewton3);
158 }
159}
160
161template <class ParticleCell_T, class ParticleFunctor_T, bool bidirectional>
163 ParticleCell_T &cell1, ParticleCell_T &cell2, const std::array<double, 3> &sortingDirection) {
164 const bool isAoS = _dataLayout == DataLayoutOption::aos ? true : false;
165 const bool isSoA = _dataLayout == DataLayoutOption::soa ? true : false;
166
167 // Return early if a cell is empty.
168 if ((isSoA and (cell1._particleSoABuffer.size() == 0 or cell2._particleSoABuffer.size() == 0)) or
169 (isAoS and (cell1.isEmpty() or cell2.isEmpty()))) {
170 return;
171 }
172
173 if (not cell1.canHaveOwnedParticles()) {
174 // Nothing to do if cell1 has no owned particles and we don't write to cell2 particles.
175 if constexpr (not bidirectional) {
176 if (not _useNewton3) {
177 return;
178 }
179 }
180 // Nothing to do if both cells cannot have owned particles.
181 if (not cell2.canHaveOwnedParticles()) {
182 return;
183 }
184 }
185
186 if (isAoS) {
187 processCellPairAoSImpl(cell1, cell2, sortingDirection);
188 } else if (isSoA) {
189 processCellPairSoAImpl(cell1, cell2);
190 }
191}
192
193template <class ParticleCell_T, class ParticleFunctor_T, bool bidirectional>
195 // helper function
196 const auto interactParticles = [this](auto &p1, auto &p2) {
197 this->_functor.AoSFunctor(p1, p2, this->_useNewton3);
198
199 if (not this->_useNewton3) {
200 this->_functor.AoSFunctor(p2, p1, false);
201 }
202 };
203
204 if (cell.size() >= _sortingThreshold) {
205 SortedCellView<ParticleCell_T> cellSorted(cell, utils::ArrayMath::normalize(cell.getCellLength()));
206
207 for (auto cellIter1 = cellSorted._particles.begin(); cellIter1 != cellSorted._particles.end(); ++cellIter1) {
208 auto &[p1Projection, p1Ptr] = *cellIter1;
209 // start inner loop ahead of the outer loop
210 for (auto cellIter2 = std::next(cellIter1); cellIter2 != cellSorted._particles.end(); ++cellIter2) {
211 auto &[p2Projection, p2Ptr] = *cellIter2;
212 if (std::abs(p2Projection - p1Projection) > _sortingCutoff) {
213 break;
214 }
215 interactParticles(*p1Ptr, *p2Ptr);
216 }
217 }
218 } else {
219 for (auto p1Ptr = cell.begin(); p1Ptr != cell.end(); ++p1Ptr) {
220 auto p2Ptr = p1Ptr;
221 ++p2Ptr;
222 for (; p2Ptr != cell.end(); ++p2Ptr) {
223 interactParticles(*p1Ptr, *p2Ptr);
224 }
225 }
226 }
227}
228
229template <class ParticleCell_T, class ParticleFunctor_T, bool bidirectional>
230void CellFunctor<ParticleCell_T, ParticleFunctor_T, bidirectional>::processCellPairAoSImpl(
231 ParticleCell_T &cell1, ParticleCell_T &cell2, const std::array<double, 3> &sortingDirection) {
232 const auto interactParticles = [this](auto &p1, auto &p2) {
233 this->_functor.AoSFunctor(p1, p2, this->_useNewton3);
234 if constexpr (bidirectional) {
235 if (not this->_useNewton3) {
236 this->_functor.AoSFunctor(p2, p1, false);
237 }
238 }
239 };
240
241 if (shouldUseSorting(cell1.size() + cell2.size(), sortingDirection)) {
242 // Use sorted cell views
243 SortedCellView<ParticleCell_T> cell1Sorted(cell1, sortingDirection);
244 SortedCellView<ParticleCell_T> cell2Sorted(cell2, sortingDirection);
245
246 for (auto &[p1Projection, p1Ptr] : cell1Sorted._particles) {
247 for (auto &[p2Projection, p2Ptr] : cell2Sorted._particles) {
248 if (std::abs(p2Projection - p1Projection) > _sortingCutoff) {
249 break;
250 }
251
252 interactParticles(*p1Ptr, *p2Ptr);
253 }
254 }
255 } else {
256 // Without sorting
257 for (auto &p1 : cell1) {
258 for (auto &p2 : cell2) {
259 interactParticles(p1, p2);
260 }
261 }
262 }
263}
264
265template <class ParticleCell_T, class ParticleFunctor_T, bool bidirectional>
266void CellFunctor<ParticleCell_T, ParticleFunctor_T, bidirectional>::processCellPairSoAImpl(ParticleCell_T &cell1,
267 ParticleCell_T &cell2) {
268 _functor.SoAFunctorPair(cell1._particleSoABuffer, cell2._particleSoABuffer, _useNewton3);
269 if constexpr (bidirectional) {
270 if (not _useNewton3) {
271 _functor.SoAFunctorPair(cell2._particleSoABuffer, cell1._particleSoABuffer, false);
272 }
273 }
274}
275} // namespace autopas::internal
A cell functor.
Definition: CellFunctor.h:25
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: CellFunctor.h:162
bool getNewton3() const
Getter.
Definition: CellFunctor.h:65
bool getBidirectional() const
Getter.
Definition: CellFunctor.h:71
void processCell(ParticleCell_T &cell)
Process the interactions inside one cell.
Definition: CellFunctor.h:141
void setSortingThreshold(size_t sortingThreshold)
Set the sorting-threshold If the sum of the number of particles in two cells is greater or equal to t...
Definition: CellFunctor.h:136
DataLayoutOption::Value getDataLayout() const
Getter.
Definition: CellFunctor.h:59
CellFunctor(ParticleFunctor_T &f, const double sortingCutoff, DataLayoutOption dataLayout, bool useNewton3)
The constructor of CellFunctor.
Definition: CellFunctor.h:36
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