AutoPas  3.0.0
Loading...
Searching...
No Matches
InteractionListGeneratorFunctor.h
Go to the documentation of this file.
1
7#pragma once
8
9#include <atomic>
10
14#include "autopas/utils/SoA.h"
15namespace autopas {
16
28template <class Particle_T, bool isInternal = false>
30 : public PairwiseFunctor<Particle_T, InteractionListGeneratorFunctor<Particle_T, isInternal>> {
31 public:
35 using SoAArraysType = Particle_T::SoAArraysType;
36
40 using NeighborListAoSType = std::unordered_map<Particle_T *, std::vector<Particle_T *>>;
41
56 InteractionListGeneratorFunctor(NeighborListAoSType &neighborListsAoS, double interactionLength,
57 bool gatherNewton3Lists)
58 : PairwiseFunctor<Particle_T, InteractionListGeneratorFunctor>(interactionLength),
59 _neighborListsAoS(neighborListsAoS),
60 _interactionLengthSquared(interactionLength * interactionLength),
61 _gatherNewton3Lists(gatherNewton3Lists) {}
62
67 std::string getName() override { return "InteractionListGeneratorFunctor"; }
68
79 template <class ParticleIterator_T>
80 void initializeNeighborList(ParticleIterator_T particlesBegin) {
81 _neighborListsAoS.clear();
82 for (auto iter = particlesBegin; iter.isValid(); ++iter) {
83 _neighborListsAoS[&(*iter)];
84 }
85 }
86
91 bool isRelevantForTuning() override { return not isInternal; }
92
97 bool allowsNewton3() override { return true; }
98
104 bool allowsNonNewton3() override { return not _gatherNewton3Lists; }
105
116 void AoSFunctor(Particle_T &i, Particle_T &j, bool newton3) override {
117 using namespace autopas::utils::ArrayMath::literals;
118
119 if (_gatherNewton3Lists and not newton3) [[unlikely]] {
121 "InteractionListGeneratorFunctor should not be used with newton3=false and gatherNewton3Lists=true.");
122 }
123
124 if (i.isDummy() or j.isDummy()) {
125 return;
126 }
127 auto dist = i.getR() - j.getR();
128
129 double distsquare = utils::ArrayMath::dot(dist, dist);
130 if (distsquare < _interactionLengthSquared) {
131 // Assuming this functor is used like any other functor, this is thread safe: _neighborListsAoS is an
132 // unordered_map, meaning we can push_back to particle i's list with the same thread safety as for writing to its
133 // force buffer in e.g. a LJ functor.
134
135 // This is only thread-safe if all keys are inserted prior to applying this functor, as a rehash might lead to
136 // dangling references, but at() protects against this: if the key exists, we can push_back safely; if a key
137 // doesn't, an exception is thrown anyway.
138
139 // - If newton3=false & gatherNewton3Lists=false, we only need to add the i->j interaction to i's list as the j->i
140 // interaction is handled in another call.
141 // - If newton3=true & gatherNewton3Lists=false, we need to add the i->j interaction to j's list and the j->i
142 // interaction to j's list.
143 // - If newton3=true & gatherNewton3Lists=true, we only need to add the i->j interaction to i's list as we don't
144 // want the j->i interaction in the lists. (Could also be the other way around)
145
146 _neighborListsAoS.at(&i).push_back(&j);
147 if (newton3 and not _gatherNewton3Lists) {
148 _neighborListsAoS.at(&j).push_back(&i);
149 }
150 }
151 }
152
157 void SoAFunctorSingle(SoAView<SoAArraysType> soa, bool /*newton3*/) override {
158 if (soa.size() == 0) return;
159
160 auto **const __restrict ptrptr = soa.template begin<Particle_T::AttributeNames::ptr>();
161 const double *const __restrict xptr = soa.template begin<Particle_T::AttributeNames::posX>();
162 const double *const __restrict yptr = soa.template begin<Particle_T::AttributeNames::posY>();
163 const double *const __restrict zptr = soa.template begin<Particle_T::AttributeNames::posZ>();
164 const auto *const __restrict ownedStatePtr = soa.template begin<Particle_T::AttributeNames::ownershipState>();
165
166 size_t numPart = soa.size();
167 for (size_t i = 0; i < numPart; ++i) {
168 if (ownedStatePtr[i] == OwnershipState::dummy) continue;
169 auto &iList = _neighborListsAoS.at(ptrptr[i]);
170 for (size_t j = i + 1; j < numPart; ++j) {
171 if (ownedStatePtr[j] == OwnershipState::dummy) continue;
172 const double drx = xptr[i] - xptr[j];
173 const double dry = yptr[i] - yptr[j];
174 const double drz = zptr[i] - zptr[j];
175
176 const double drx2 = drx * drx;
177 const double dry2 = dry * dry;
178 const double drz2 = drz * drz;
179
180 const double dr2 = drx2 + dry2 + drz2;
181
182 if (dr2 < _interactionLengthSquared) {
183 // This SoAFunctorSingle implementation always used newton3 in practice, regardless of the option.
184 // This is thread safe (see comment in AoS functor)
185 iList.push_back(ptrptr[j]);
186 if (not _gatherNewton3Lists) {
187 _neighborListsAoS.at(ptrptr[j]).push_back(ptrptr[i]);
188 }
189 }
190 }
191 }
192 }
193
204 void SoAFunctorPair(SoAView<SoAArraysType> soa1, SoAView<SoAArraysType> soa2, bool newton3) override {
205 if (_gatherNewton3Lists and not newton3) [[unlikely]] {
207 "InteractionListGeneratorFunctor should not be used with newton3=false and gatherNewton3Lists=true.");
208 }
209
210 if (soa1.size() == 0 or soa2.size() == 0) return;
211
212 auto **const __restrict ptr1ptr = soa1.template begin<Particle_T::AttributeNames::ptr>();
213 const double *const __restrict x1ptr = soa1.template begin<Particle_T::AttributeNames::posX>();
214 const double *const __restrict y1ptr = soa1.template begin<Particle_T::AttributeNames::posY>();
215 const double *const __restrict z1ptr = soa1.template begin<Particle_T::AttributeNames::posZ>();
216 const auto *const __restrict ownedState1Ptr = soa1.template begin<Particle_T::AttributeNames::ownershipState>();
217
218 auto **const __restrict ptr2ptr = soa2.template begin<Particle_T::AttributeNames::ptr>();
219 const double *const __restrict x2ptr = soa2.template begin<Particle_T::AttributeNames::posX>();
220 const double *const __restrict y2ptr = soa2.template begin<Particle_T::AttributeNames::posY>();
221 const double *const __restrict z2ptr = soa2.template begin<Particle_T::AttributeNames::posZ>();
222 const auto *const __restrict ownedState2Ptr = soa2.template begin<Particle_T::AttributeNames::ownershipState>();
223
224 const size_t numPart1 = soa1.size();
225 for (size_t i = 0; i < numPart1; ++i) {
226 auto &iList = _neighborListsAoS.at(ptr1ptr[i]);
227 if (ownedState1Ptr[i] == OwnershipState::dummy) continue;
228 const size_t numPart2 = soa2.size();
229
230 for (size_t j = 0; j < numPart2; ++j) {
231 if (ownedState2Ptr[j] == OwnershipState::dummy) continue;
232 const double drx = x1ptr[i] - x2ptr[j];
233 const double dry = y1ptr[i] - y2ptr[j];
234 const double drz = z1ptr[i] - z2ptr[j];
235
236 const double drx2 = drx * drx;
237 const double dry2 = dry * dry;
238 const double drz2 = drz * drz;
239
240 const double dr2 = drx2 + dry2 + drz2;
241
242 if (dr2 < _interactionLengthSquared) {
243 // This is thread safe (see comment in AoS functor)
244 iList.push_back(ptr2ptr[j]);
245 if (newton3 and not _gatherNewton3Lists) {
246 _neighborListsAoS.at(ptr2ptr[j]).push_back(ptr1ptr[i]);
247 }
248 }
249 }
250 }
251 }
252
268 void SoAFunctorVerlet(SoAView<SoAArraysType> soa, const size_t indexFirst,
269 const std::vector<size_t, AlignedAllocator<size_t>> &verletList, bool newton3) override {
270 if (_gatherNewton3Lists and not newton3) [[unlikely]] {
272 "InteractionListGeneratorFunctor should not be used with newton3=false and gatherNewton3Lists=true.");
273 }
274
275 if (soa.size() == 0 or verletList.empty()) return;
276
277 auto **const __restrict ptrptr = soa.template begin<Particle_T::AttributeNames::ptr>();
278 const double *const __restrict xptr = soa.template begin<Particle_T::AttributeNames::posX>();
279 const double *const __restrict yptr = soa.template begin<Particle_T::AttributeNames::posY>();
280 const double *const __restrict zptr = soa.template begin<Particle_T::AttributeNames::posZ>();
281 const auto *const __restrict ownedStatePtr = soa.template begin<Particle_T::AttributeNames::ownershipState>();
282
283 if (ownedStatePtr[indexFirst] == OwnershipState::dummy) return;
284
285 auto &firstList = _neighborListsAoS.at(ptrptr[indexFirst]);
286 const double xFirst = xptr[indexFirst];
287 const double yFirst = yptr[indexFirst];
288 const double zFirst = zptr[indexFirst];
289
290 for (const size_t j : verletList) {
291 if (ownedStatePtr[j] == OwnershipState::dummy) continue;
292 const double drx = xFirst - xptr[j];
293 const double dry = yFirst - yptr[j];
294 const double drz = zFirst - zptr[j];
295
296 const double drx2 = drx * drx;
297 const double dry2 = dry * dry;
298 const double drz2 = drz * drz;
299
300 const double dr2 = drx2 + dry2 + drz2;
301
302 if (dr2 < _interactionLengthSquared) {
303 // This is thread safe (see comment in AoS functor)
304 firstList.push_back(ptrptr[j]);
305 if (newton3 and not _gatherNewton3Lists) {
306 _neighborListsAoS.at(ptrptr[j]).push_back(ptrptr[indexFirst]);
307 }
308 }
309 }
310 }
311
315 constexpr static std::array<typename Particle_T::AttributeNames, 5> getNeededAttr() {
316 return std::array<typename Particle_T::AttributeNames, 5>{
317 Particle_T::AttributeNames::ptr, Particle_T::AttributeNames::posX, Particle_T::AttributeNames::posY,
318 Particle_T::AttributeNames::posZ, Particle_T::AttributeNames::ownershipState};
319 }
320
324 constexpr static std::array<typename Particle_T::AttributeNames, 5> getNeededAttr(std::false_type) {
325 return getNeededAttr();
326 }
327
331 constexpr static std::array<typename Particle_T::AttributeNames, 0> getComputedAttr() {
332 return std::array<typename Particle_T::AttributeNames, 0>{/*Nothing*/};
333 }
334
335 private:
336 NeighborListAoSType &_neighborListsAoS;
337 double _interactionLengthSquared;
338
343 bool _gatherNewton3Lists{false};
344};
345
346} // namespace autopas
AlignedAllocator class.
Definition: AlignedAllocator.h:29
This functor generates lists of particles within interactionLength of each other: can be used interna...
Definition: InteractionListGeneratorFunctor.h:30
static constexpr std::array< typename Particle_T::AttributeNames, 5 > getNeededAttr(std::false_type)
Get attributes needed for computation without N3 optimization.
Definition: InteractionListGeneratorFunctor.h:324
std::unordered_map< Particle_T *, std::vector< Particle_T * > > NeighborListAoSType
Neighbor list AoS style.
Definition: InteractionListGeneratorFunctor.h:40
bool isRelevantForTuning() override
Whether particle is relevant for tuning.
Definition: InteractionListGeneratorFunctor.h:91
Particle_T::SoAArraysType SoAArraysType
Structure of the SoAs defined by the particle.
Definition: InteractionListGeneratorFunctor.h:35
InteractionListGeneratorFunctor(NeighborListAoSType &neighborListsAoS, double interactionLength, bool gatherNewton3Lists)
Constructor.
Definition: InteractionListGeneratorFunctor.h:56
void SoAFunctorPair(SoAView< SoAArraysType > soa1, SoAView< SoAArraysType > soa2, bool newton3) override
SoAFunctor for the verlet list generation.
Definition: InteractionListGeneratorFunctor.h:204
void SoAFunctorVerlet(SoAView< SoAArraysType > soa, const size_t indexFirst, const std::vector< size_t, AlignedAllocator< size_t > > &verletList, bool newton3) override
SoAFunctorVerlet for interaction list generation.
Definition: InteractionListGeneratorFunctor.h:268
bool allowsNewton3() override
Whether InteractionListGeneratorFunctor allows Newton3.
Definition: InteractionListGeneratorFunctor.h:97
static constexpr std::array< typename Particle_T::AttributeNames, 5 > getNeededAttr()
Get attributes needed for computation.
Definition: InteractionListGeneratorFunctor.h:315
void SoAFunctorSingle(SoAView< SoAArraysType > soa, bool) override
SoAFunctor for verlet list generation.
Definition: InteractionListGeneratorFunctor.h:157
static constexpr std::array< typename Particle_T::AttributeNames, 0 > getComputedAttr()
Get attributes computed by this functor.
Definition: InteractionListGeneratorFunctor.h:331
void AoSFunctor(Particle_T &i, Particle_T &j, bool newton3) override
AoSFunctor for interaction list generation.
Definition: InteractionListGeneratorFunctor.h:116
std::string getName() override
Definition: InteractionListGeneratorFunctor.h:67
void initializeNeighborList(ParticleIterator_T particlesBegin)
Initializes the neighbor list map for the given range of particles: clears any previous contents and ...
Definition: InteractionListGeneratorFunctor.h:80
bool allowsNonNewton3() override
Whether InteractionListGeneratorFunctor allows non-newton3.
Definition: InteractionListGeneratorFunctor.h:104
PairwiseFunctor class.
Definition: PairwiseFunctor.h:45
View on a fixed part of a SoA between a start index and an end index.
Definition: SoAView.h:25
size_t size() const
Returns the number of particles in the view.
Definition: SoAView.h:85
static void exception(const Exception e)
Handle an exception derived by std::exception.
Definition: ExceptionHandler.h:64
constexpr T dot(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Generates the dot product of two arrays.
Definition: ArrayMath.h:233
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:34
@ dummy
Dummy or deleted state, a particle with this state is not an actual particle!