AutoPas  3.0.0
Loading...
Searching...
No Matches
VerletListHelpers.h
Go to the documentation of this file.
1
7#pragma once
8
9#include <atomic>
10#include <unordered_map>
11#include <vector>
12
15#include "autopas/utils/SoA.h"
16namespace autopas {
17
22template <class Particle_T>
24 public:
33 std::vector<size_t> offsets;
34 std::vector<size_t, AlignedAllocator<size_t>> indices;
35
40 [[nodiscard]] size_t size() const { return offsets.empty() ? 0u : offsets.size() - 1u; }
45 [[nodiscard]] size_t count(const size_t i) const { return offsets[i + 1] - offsets[i]; }
50 [[nodiscard]] const size_t *begin(const size_t i) const { return indices.data() + offsets[i]; }
55 [[nodiscard]] size_t *begin(const size_t i) { return indices.data() + offsets[i]; }
60 [[nodiscard]] std::span<const size_t> getNeighbors(const size_t i) const { return {begin(i), count(i)}; }
61 };
62
70 public:
76 CRSNeighborListPolicy(std::vector<std::vector<size_t>> &neighborLists,
77 std::unordered_map<const Particle_T *, size_t> &particleToIndex)
78 : _neighborLists(neighborLists), _particleToIndex(particleToIndex) {}
79
85 void add(Particle_T *i, Particle_T *j) { _neighborLists[_particleToIndex[i]].push_back(_particleToIndex[j]); }
86
87 private:
88 std::vector<std::vector<size_t>> &_neighborLists;
89 std::unordered_map<const Particle_T *, size_t> &_particleToIndex;
90 };
91
108 class VerletListCounterFunctor : public PairwiseFunctor<Particle_T, VerletListCounterFunctor> {
109 public:
113 using SoAArraysType = typename Particle_T::SoAArraysType;
114
118 struct alignas(64) PaddedAtomic {
122 std::atomic<size_t> value{0};
123 };
124
130 VerletListCounterFunctor(std::vector<PaddedAtomic> &counts,
131 const std::unordered_map<const Particle_T *, size_t> &particleToIndex,
132 double interactionLength)
133 : PairwiseFunctor<Particle_T, VerletListCounterFunctor>(interactionLength),
134 _counts(counts),
135 _particleToIndex(particleToIndex),
136 _interactionLengthSquared(interactionLength * interactionLength) {}
137
138 std::string getName() override { return "VerletListCounterFunctor"; }
139 bool isRelevantForTuning() override { return false; }
140 bool allowsNewton3() override { return true; }
141 bool allowsNonNewton3() override { return true; }
142
147 void AoSFunctor(Particle_T &i, Particle_T &j, bool /*newton3*/) override {
148 using namespace autopas::utils::ArrayMath::literals;
149 if (i.isDummy() or j.isDummy()) return;
150 const auto displacement = i.getR() - j.getR();
151 if (utils::ArrayMath::dot(displacement, displacement) < _interactionLengthSquared) {
152 _counts[_particleToIndex.at(&i)].value.fetch_add(1, std::memory_order_relaxed);
153 // newton3 ignored: AoSFunctor(j, i) is also called for newton3=false.
154 }
155 }
156
160 void SoAFunctorSingle(SoAView<SoAArraysType> soa, const bool newton3) override {
161 if (soa.size() == 0) return;
162 auto **const __restrict ptrptr = soa.template begin<Particle_T::AttributeNames::ptr>();
163 const double *const __restrict xptr = soa.template begin<Particle_T::AttributeNames::posX>();
164 const double *const __restrict yptr = soa.template begin<Particle_T::AttributeNames::posY>();
165 const double *const __restrict zptr = soa.template begin<Particle_T::AttributeNames::posZ>();
166 const size_t n = soa.size();
167 for (size_t i = 0; i < n; ++i) {
168 const size_t iIdx = _particleToIndex.at(ptrptr[i]);
169 size_t localCount = 0;
170 for (size_t j = i + 1; j < n; ++j) {
171 const double dx = xptr[i] - xptr[j];
172 const double dy = yptr[i] - yptr[j];
173 const double dz = zptr[i] - zptr[j];
174 if (dx * dx + dy * dy + dz * dz < _interactionLengthSquared) {
175 ++localCount;
176 if (not newton3) {
177 _counts[_particleToIndex.at(ptrptr[j])].value.fetch_add(1, std::memory_order_relaxed);
178 }
179 }
180 }
181 _counts[iIdx].value.fetch_add(localCount, std::memory_order_relaxed);
182 }
183 }
184
189 void SoAFunctorPair(SoAView<SoAArraysType> soa1, SoAView<SoAArraysType> soa2, bool /*newton3*/) override {
190 if (soa1.size() == 0 || soa2.size() == 0) return;
191 auto **const __restrict ptr1ptr = soa1.template begin<Particle_T::AttributeNames::ptr>();
192 const double *const __restrict x1ptr = soa1.template begin<Particle_T::AttributeNames::posX>();
193 const double *const __restrict y1ptr = soa1.template begin<Particle_T::AttributeNames::posY>();
194 const double *const __restrict z1ptr = soa1.template begin<Particle_T::AttributeNames::posZ>();
195 auto **const __restrict ptr2ptr = soa2.template begin<Particle_T::AttributeNames::ptr>();
196 const double *const __restrict x2ptr = soa2.template begin<Particle_T::AttributeNames::posX>();
197 const double *const __restrict y2ptr = soa2.template begin<Particle_T::AttributeNames::posY>();
198 const double *const __restrict z2ptr = soa2.template begin<Particle_T::AttributeNames::posZ>();
199 // newton3 ignored: SoAFunctorPair(soa2,soa1) is also called for newton3=false.
200 const size_t n1 = soa1.size(), n2 = soa2.size();
201 for (size_t i = 0; i < n1; ++i) {
202 const size_t iIdx = _particleToIndex.at(ptr1ptr[i]);
203 size_t localCount = 0;
204 for (size_t j = 0; j < n2; ++j) {
205 const double dx = x1ptr[i] - x2ptr[j];
206 const double dy = y1ptr[i] - y2ptr[j];
207 const double dz = z1ptr[i] - z2ptr[j];
208 if (dx * dx + dy * dy + dz * dz < _interactionLengthSquared) {
209 ++localCount;
210 }
211 }
212 _counts[iIdx].value.fetch_add(localCount, std::memory_order_relaxed);
213 }
214 }
215
219 constexpr static std::array<typename Particle_T::AttributeNames, 4> getNeededAttr() {
220 return {Particle_T::AttributeNames::ptr, Particle_T::AttributeNames::posX, Particle_T::AttributeNames::posY,
221 Particle_T::AttributeNames::posZ};
222 }
223
227 constexpr static std::array<typename Particle_T::AttributeNames, 0> getComputedAttr() { return {}; }
228
229 private:
230 std::vector<PaddedAtomic> &_counts;
231 const std::unordered_map<const Particle_T *, size_t> &_particleToIndex;
232 double _interactionLengthSquared;
233 };
234
251 class VerletListFillerFunctor : public PairwiseFunctor<Particle_T, VerletListFillerFunctor> {
252 public:
256 using SoAArraysType = typename Particle_T::SoAArraysType;
261
269 VerletListFillerFunctor(NeighborListCRS &neighborList, std::vector<PaddedAtomic> &fillPos,
270 const std::unordered_map<const Particle_T *, size_t> &particleToIndex,
271 double interactionLength)
272 : PairwiseFunctor<Particle_T, VerletListFillerFunctor>(interactionLength),
273 _neighborList(neighborList),
274 _fillPos(fillPos),
275 _particleToIndex(particleToIndex),
276 _interactionLengthSquared(interactionLength * interactionLength) {}
277
278 std::string getName() override { return "VerletListFillerFunctor"; }
279 bool isRelevantForTuning() override { return false; }
280 bool allowsNewton3() override { return true; }
281 bool allowsNonNewton3() override { return true; }
282
287 void AoSFunctor(Particle_T &i, Particle_T &j, bool /*newton3*/) override {
288 using namespace autopas::utils::ArrayMath::literals;
289 if (i.isDummy() or j.isDummy()) return;
290 const auto displacement = i.getR() - j.getR();
291 if (utils::ArrayMath::dot(displacement, displacement) < _interactionLengthSquared) {
292 const size_t iIdx = _particleToIndex.at(&i);
293 const size_t jIdx = _particleToIndex.at(&j);
294 _neighborList.indices[_fillPos[iIdx].value.fetch_add(1, std::memory_order_relaxed)] = jIdx;
295 // newton3 ignored: AoSFunctor(j, i) is also called for newton3=false.
296 }
297 }
298
302 void SoAFunctorSingle(SoAView<SoAArraysType> soa, const bool newton3) override {
303 if (soa.size() == 0) return;
304 auto **const __restrict ptrptr = soa.template begin<Particle_T::AttributeNames::ptr>();
305 const double *const __restrict xptr = soa.template begin<Particle_T::AttributeNames::posX>();
306 const double *const __restrict yptr = soa.template begin<Particle_T::AttributeNames::posY>();
307 const double *const __restrict zptr = soa.template begin<Particle_T::AttributeNames::posZ>();
308 const size_t n = soa.size();
309 for (size_t i = 0; i < n; ++i) {
310 const size_t iIdx = _particleToIndex.at(ptrptr[i]);
311 for (size_t j = i + 1; j < n; ++j) {
312 const double dx = xptr[i] - xptr[j];
313 const double dy = yptr[i] - yptr[j];
314 const double dz = zptr[i] - zptr[j];
315 if (dx * dx + dy * dy + dz * dz < _interactionLengthSquared) {
316 const size_t jIdx = _particleToIndex.at(ptrptr[j]);
317 _neighborList.indices[_fillPos[iIdx].value.fetch_add(1, std::memory_order_relaxed)] = jIdx;
318 if (not newton3) {
319 _neighborList.indices[_fillPos[jIdx].value.fetch_add(1, std::memory_order_relaxed)] = iIdx;
320 }
321 }
322 }
323 }
324 }
325
330 void SoAFunctorPair(SoAView<SoAArraysType> soa1, SoAView<SoAArraysType> soa2, bool /*newton3*/) override {
331 if (soa1.size() == 0 || soa2.size() == 0) return;
332 auto **const __restrict ptr1ptr = soa1.template begin<Particle_T::AttributeNames::ptr>();
333 const double *const __restrict x1ptr = soa1.template begin<Particle_T::AttributeNames::posX>();
334 const double *const __restrict y1ptr = soa1.template begin<Particle_T::AttributeNames::posY>();
335 const double *const __restrict z1ptr = soa1.template begin<Particle_T::AttributeNames::posZ>();
336 auto **const __restrict ptr2ptr = soa2.template begin<Particle_T::AttributeNames::ptr>();
337 const double *const __restrict x2ptr = soa2.template begin<Particle_T::AttributeNames::posX>();
338 const double *const __restrict y2ptr = soa2.template begin<Particle_T::AttributeNames::posY>();
339 const double *const __restrict z2ptr = soa2.template begin<Particle_T::AttributeNames::posZ>();
340 // newton3 ignored: SoAFunctorPair(soa2,soa1) is also called for newton3=false.
341 const size_t n1 = soa1.size(), n2 = soa2.size();
342 for (size_t i = 0; i < n1; ++i) {
343 const size_t iIdx = _particleToIndex.at(ptr1ptr[i]);
344 for (size_t j = 0; j < n2; ++j) {
345 const double dx = x1ptr[i] - x2ptr[j];
346 const double dy = y1ptr[i] - y2ptr[j];
347 const double dz = z1ptr[i] - z2ptr[j];
348 if (dx * dx + dy * dy + dz * dz < _interactionLengthSquared) {
349 _neighborList.indices[_fillPos[iIdx].value.fetch_add(1, std::memory_order_relaxed)] =
350 _particleToIndex.at(ptr2ptr[j]);
351 }
352 }
353 }
354 }
355
359 constexpr static std::array<typename Particle_T::AttributeNames, 4> getNeededAttr() {
360 return {Particle_T::AttributeNames::ptr, Particle_T::AttributeNames::posX, Particle_T::AttributeNames::posY,
361 Particle_T::AttributeNames::posZ};
362 }
363
367 constexpr static std::array<typename Particle_T::AttributeNames, 0> getComputedAttr() { return {}; }
368
369 private:
370 NeighborListCRS &_neighborList;
371 std::vector<PaddedAtomic> &_fillPos;
372 const std::unordered_map<const Particle_T *, size_t> &_particleToIndex;
373 double _interactionLengthSquared;
374 };
375}; // class VerletListHelpers
376} // namespace autopas
PairwiseFunctor class.
Definition: PairwiseFunctor.h:66
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
Policy for managing neighbor lists using the Compressed-Row-Storage (CRS) format.
Definition: VerletListHelpers.h:69
CRSNeighborListPolicy(std::vector< std::vector< size_t > > &neighborLists, std::unordered_map< const Particle_T *, size_t > &particleToIndex)
Constructor.
Definition: VerletListHelpers.h:76
void add(Particle_T *i, Particle_T *j)
Adds particle j to the neighbor list of particle i.
Definition: VerletListHelpers.h:85
Pass-1 functor for the two-pass CRS build.
Definition: VerletListHelpers.h:108
bool isRelevantForTuning() override
Specifies whether the functor should be considered for the auto-tuning process.
Definition: VerletListHelpers.h:139
void SoAFunctorSingle(SoAView< SoAArraysType > soa, const bool newton3) override
PairwiseFunctor for structure of arrays (SoA)
Definition: VerletListHelpers.h:160
VerletListCounterFunctor(std::vector< PaddedAtomic > &counts, const std::unordered_map< const Particle_T *, size_t > &particleToIndex, double interactionLength)
Definition: VerletListHelpers.h:130
std::string getName() override
Returns name of functor.
Definition: VerletListHelpers.h:138
static constexpr std::array< typename Particle_T::AttributeNames, 0 > getComputedAttr()
Get attributes computed by this functor.
Definition: VerletListHelpers.h:227
bool allowsNonNewton3() override
Specifies whether the functor is capable of non-Newton3-like functors.
Definition: VerletListHelpers.h:141
bool allowsNewton3() override
Specifies whether the functor is capable of Newton3-like functors.
Definition: VerletListHelpers.h:140
void SoAFunctorPair(SoAView< SoAArraysType > soa1, SoAView< SoAArraysType > soa2, bool) override
Definition: VerletListHelpers.h:189
static constexpr std::array< typename Particle_T::AttributeNames, 4 > getNeededAttr()
Get attributes needed for computation.
Definition: VerletListHelpers.h:219
typename Particle_T::SoAArraysType SoAArraysType
Structure of the SoAs defined by the particle.
Definition: VerletListHelpers.h:113
void AoSFunctor(Particle_T &i, Particle_T &j, bool) override
Definition: VerletListHelpers.h:147
Pass-2 functor for the two-pass CRS build.
Definition: VerletListHelpers.h:251
static constexpr std::array< typename Particle_T::AttributeNames, 0 > getComputedAttr()
Get attributes computed by this functor.
Definition: VerletListHelpers.h:367
void AoSFunctor(Particle_T &i, Particle_T &j, bool) override
Definition: VerletListHelpers.h:287
bool allowsNonNewton3() override
Specifies whether the functor is capable of non-Newton3-like functors.
Definition: VerletListHelpers.h:281
std::string getName() override
Returns name of functor.
Definition: VerletListHelpers.h:278
typename VerletListCounterFunctor::PaddedAtomic PaddedAtomic
Atomic counter.
Definition: VerletListHelpers.h:260
void SoAFunctorSingle(SoAView< SoAArraysType > soa, const bool newton3) override
PairwiseFunctor for structure of arrays (SoA)
Definition: VerletListHelpers.h:302
static constexpr std::array< typename Particle_T::AttributeNames, 4 > getNeededAttr()
Get attributes needed for computation.
Definition: VerletListHelpers.h:359
void SoAFunctorPair(SoAView< SoAArraysType > soa1, SoAView< SoAArraysType > soa2, bool) override
Definition: VerletListHelpers.h:330
bool isRelevantForTuning() override
Specifies whether the functor should be considered for the auto-tuning process.
Definition: VerletListHelpers.h:279
bool allowsNewton3() override
Specifies whether the functor is capable of Newton3-like functors.
Definition: VerletListHelpers.h:280
typename Particle_T::SoAArraysType SoAArraysType
Structure of the SoAs defined by the particle.
Definition: VerletListHelpers.h:256
VerletListFillerFunctor(NeighborListCRS &neighborList, std::vector< PaddedAtomic > &fillPos, const std::unordered_map< const Particle_T *, size_t > &particleToIndex, double interactionLength)
Definition: VerletListHelpers.h:269
Class of helpers for the VerletLists class.
Definition: VerletListHelpers.h:23
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
Flat Compressed-Row-Storage (CRS) neighbor list.
Definition: VerletListHelpers.h:32
size_t * begin(const size_t i)
Pointer to the first neighbor index of particle i (mutable).
Definition: VerletListHelpers.h:55
size_t count(const size_t i) const
Number of neighbors of particle i.
Definition: VerletListHelpers.h:45
const size_t * begin(const size_t i) const
Pointer to the first neighbor index of particle i (const).
Definition: VerletListHelpers.h:50
std::span< const size_t > getNeighbors(const size_t i) const
Returns a span of the neighbors of particle i.
Definition: VerletListHelpers.h:60
std::vector< size_t, AlignedAllocator< size_t > > indices
flat neighbor indices
Definition: VerletListHelpers.h:34
std::vector< size_t > offsets
size N+1
Definition: VerletListHelpers.h:33
size_t size() const
Number of particles tracked by this list.
Definition: VerletListHelpers.h:40
One atomic counter per particle, each padded to its own cache line.
Definition: VerletListHelpers.h:118
std::atomic< size_t > value
The actual counter value.
Definition: VerletListHelpers.h:122