AutoPas  3.0.0
Loading...
Searching...
No Matches
VLCAllCellsGeneratorFunctor.h
Go to the documentation of this file.
1
12
13#pragma once
14
15namespace autopas {
16
20template <class Particle_T, enum TraversalOption::Value TraversalOptionEnum>
22 : public PairwiseFunctor<Particle_T, VLCAllCellsGeneratorFunctor<Particle_T, TraversalOptionEnum>> {
24 using SoAArraysType = typename Particle_T::SoAArraysType;
25
26 public:
35 VLCAllCellsGeneratorFunctor(NeighborListsType &neighborLists,
36 std::unordered_map<Particle_T *, std::pair<size_t, size_t>> &particleToCellMap,
37 double cutoffSkin, size_t newListAllocationSize,
38 const std::array<size_t, 3> &cellsPerDim = {})
39 : PairwiseFunctor<Particle_T, VLCAllCellsGeneratorFunctor<Particle_T, TraversalOptionEnum>>(0.),
40 _neighborLists(neighborLists),
41 _particleToCellMap(particleToCellMap),
42 _cutoffSkinSquared(cutoffSkin * cutoffSkin),
43 _cellsPerDim(cellsPerDim),
44 _newListAllocationSize(newListAllocationSize) {}
45
46 std::string getName() override { return "VLCAllCellsGeneratorFunctor"; }
47
48 bool isRelevantForTuning() override { return false; }
49
50 bool allowsNewton3() override {
52 "VLCAllCellsGeneratorFunctor::allowsNewton3() is not implemented, because it should not be called.");
53 return true;
54 }
55
56 bool allowsNonNewton3() override {
58 "VLCAllCellsGeneratorFunctor::allowsNonNewton3() is not implemented, because it should not be called.");
59 return true;
60 }
61
66 void setCells(std::vector<FullParticleCell<Particle_T>> *cells) { _cells = cells; }
67
71 void AoSFunctor(Particle_T &i, Particle_T &j, bool newton3) override {
72 using namespace autopas::utils::ArrayMath::literals;
73
74 if (i.isDummy() or j.isDummy()) {
75 return;
76 }
77 const auto dist = i.getR() - j.getR();
78 const double distSquare = utils::ArrayMath::dot(dist, dist);
79 if (distSquare < _cutoffSkinSquared) {
80 // this is thread safe, only if particle i is accessed by only one
81 // thread at a time. which is ensured, as particle i resides in a
82 // specific cell and each cell is only accessed by one thread at a time
83 // (ensured by traversals)
84 // also the list is not allowed to be resized!
85
86 // Depending on the targeted traversal neighbor lists are built differently
87 if constexpr (TraversalOptionEnum == TraversalOption::Value::vlc_c08) {
88 const auto &[cellIndexI, particleIndexI] = _particleToCellMap[&i];
89 const auto &[cellIndexJ, particleIndexJ] = _particleToCellMap[&j];
90
91 const auto cellIndex3DI = utils::ThreeDimensionalMapping::oneToThreeD(cellIndexI, _cellsPerDim);
92 const auto cellIndex3DJ = utils::ThreeDimensionalMapping::oneToThreeD(cellIndexJ, _cellsPerDim);
93
94 // WARNING: This is probably only valid for CSF==1
95 const std::array<size_t, 3> cellIndex3DBaseCell = utils::ArrayMath::min(cellIndex3DI, cellIndex3DJ);
96 const auto cellIndexBaseCell = utils::ThreeDimensionalMapping::threeToOneD(cellIndex3DBaseCell, _cellsPerDim);
97 // If the first cell is also the base cell insert as normal
98 if (cellIndexBaseCell == cellIndexI) {
99 _neighborLists[cellIndexI][particleIndexI].second.push_back(&j);
100 } else {
101 // In the following two cases the list has to be in a different cell than cellIndex1:
102 // 1. If the base cell is the cell of particle j
103 // To respect newton3 == disabled, we can't just do currentList[j].second.push_back(ptr1Ptr[i]).
104 // 2. If base cell is neither cellIndex1 or cellIndex2
105 auto &list = _neighborLists[cellIndexI];
106 auto iterIandList = std::find_if(list.begin(), list.end(),
107 [&](const std::pair<Particle_T *, std::vector<Particle_T *>> &pair) {
108 const auto &[particle, neighbors] = pair;
109 return particle == &i;
110 });
111 if (iterIandList != list.end()) {
112 auto &[_, neighbors] = *iterIandList;
113 neighbors.push_back(&j);
114 } else {
115 list.emplace_back(&i, std::vector<Particle_T *>{});
116 list.back().second.reserve(_newListAllocationSize);
117 list.back().second.push_back(&j);
118 }
119 }
120 } else if constexpr (TraversalOptionEnum == TraversalOption::Value::vlc_c01 or
121 TraversalOptionEnum == TraversalOption::Value::vlc_c18) {
122 const auto &[cellIndex, particleIndex] = _particleToCellMap[&i];
123 _neighborLists[cellIndex][particleIndex].second.push_back(&j);
124 } else {
126 "VLCAllCellsGeneratorFunctor::AoSFunctor(): Encountered incompatible Traversal Option {}.",
127 TraversalOptionEnum);
128 }
129 }
130 }
131
135 void SoAFunctorSingle(SoAView<SoAArraysType> soa, bool newton3) override {
136 if (soa.size() == 0) return;
137
138 auto **const __restrict__ ptrPtr = soa.template begin<Particle_T::AttributeNames::ptr>();
139 double *const __restrict__ xPtr = soa.template begin<Particle_T::AttributeNames::posX>();
140 double *const __restrict__ yPtr = soa.template begin<Particle_T::AttributeNames::posY>();
141 double *const __restrict__ zPtr = soa.template begin<Particle_T::AttributeNames::posZ>();
142
143 // index of cellIndex is particleToCellMap of ptrPtr, same for 2
144 const auto [cellIndex, _] = _particleToCellMap.at(ptrPtr[0]);
145
146 // iterating over particle indices and accessing currentList at index i works
147 // because the particles are iterated in the same order they are loaded in
148 // which is the same order they were initialized when building the aosNeighborList
149 const size_t numPart = soa.size();
150 for (unsigned int i = 0; i < numPart; ++i) {
151 for (unsigned int j = i + 1; j < numPart; ++j) {
152 const double drx = xPtr[i] - xPtr[j];
153 const double dry = yPtr[i] - yPtr[j];
154 const double drz = zPtr[i] - zPtr[j];
155
156 const double drx2 = drx * drx;
157 const double dry2 = dry * dry;
158 const double drz2 = drz * drz;
159
160 const double dr2 = drx2 + dry2 + drz2;
161
162 if (dr2 < _cutoffSkinSquared) {
163 auto &currentList = _neighborLists[cellIndex];
164 currentList[i].second.push_back(ptrPtr[j]);
165 if (not newton3) {
166 // we need this here, as SoAFunctorSingle will only be called once for both newton3=true and false.
167 currentList[j].second.push_back(ptrPtr[i]);
168 }
169 }
170 }
171 }
172 }
173
184 void SoAFunctorPair(SoAView<SoAArraysType> soa1, SoAView<SoAArraysType> soa2, bool /*newton3*/) override {
185 if (soa1.size() == 0 or soa2.size() == 0) return;
186
187 auto **const __restrict__ ptr1Ptr = soa1.template begin<Particle_T::AttributeNames::ptr>();
188 double *const __restrict__ x1Ptr = soa1.template begin<Particle_T::AttributeNames::posX>();
189 double *const __restrict__ y1Ptr = soa1.template begin<Particle_T::AttributeNames::posY>();
190 double *const __restrict__ z1Ptr = soa1.template begin<Particle_T::AttributeNames::posZ>();
191
192 auto **const __restrict__ ptr2Ptr = soa2.template begin<Particle_T::AttributeNames::ptr>();
193 double *const __restrict__ x2Ptr = soa2.template begin<Particle_T::AttributeNames::posX>();
194 double *const __restrict__ y2Ptr = soa2.template begin<Particle_T::AttributeNames::posY>();
195 double *const __restrict__ z2Ptr = soa2.template begin<Particle_T::AttributeNames::posZ>();
196
197 // index of cell1 is particleToCellMap of ptr1Ptr, same for 2
198 const size_t cellIndex1 = _particleToCellMap.at(ptr1Ptr[0]).first;
199 const size_t cellIndex2 = _particleToCellMap.at(ptr2Ptr[0]).first;
200
201 const auto cellIndexBaseCell = [&]() {
202 if constexpr (TraversalOptionEnum == TraversalOption::Value::vlc_c01 or
203 TraversalOptionEnum == TraversalOption::Value::vlc_c18) {
204 return cellIndex1;
205 } else if constexpr (TraversalOptionEnum == TraversalOption::Value::vlc_c08) {
206 const auto cellIndex3D1 = utils::ThreeDimensionalMapping::oneToThreeD(cellIndex1, _cellsPerDim);
207 const auto cellIndex3D2 = utils::ThreeDimensionalMapping::oneToThreeD(cellIndex2, _cellsPerDim);
208 const auto cellIndex3DBaseCell = utils::ArrayMath::min(cellIndex3D1, cellIndex3D2);
209 return utils::ThreeDimensionalMapping::threeToOneD(cellIndex3DBaseCell, _cellsPerDim);
210 } else {
212 "VLCAllCellsGeneratorFunctor::SoAFunctor(): Encountered incompatible Traversal Option {}.",
213 TraversalOptionEnum);
214 return 0ul;
215 }
216 }();
217
218 auto &currentList = _neighborLists[cellIndexBaseCell];
219
220 // iterating over particle indices and accessing currentList at index i works
221 // because the particles are iterated in the same order they are loaded in
222 // which is the same order they were initialized when building the aosNeighborList
223 const size_t numPart1 = soa1.size();
224 for (unsigned int i = 0; i < numPart1; ++i) {
225 const size_t numPart2 = soa2.size();
226 for (unsigned int j = 0; j < numPart2; ++j) {
227 const double drx = x1Ptr[i] - x2Ptr[j];
228 const double dry = y1Ptr[i] - y2Ptr[j];
229 const double drz = z1Ptr[i] - z2Ptr[j];
230
231 const double drx2 = drx * drx;
232 const double dry2 = dry * dry;
233 const double drz2 = drz * drz;
234
235 const double dr2 = drx2 + dry2 + drz2;
236
237 if (dr2 < _cutoffSkinSquared) {
238 if constexpr (TraversalOptionEnum == TraversalOption::Value::vlc_c01 or
239 TraversalOptionEnum == TraversalOption::Value::vlc_c18) {
240 currentList[i].second.push_back(ptr2Ptr[j]);
241 } else if constexpr (TraversalOptionEnum == TraversalOption::Value::vlc_c08) {
242 // depending on which cell is the base cell append the pointer to the respective list collection
243 if (cellIndex1 == cellIndexBaseCell) {
244 currentList[i].second.push_back(ptr2Ptr[j]);
245 } else {
246 // In the following two cases the list has to be in a different cell than cellIndex1:
247 // 1. If the base cell is the cell of particle j
248 // To respect newton3 == disabled, we can't just do currentList[j].second.push_back(ptr1Ptr[i]).
249 // 2. If base cell is neither cellIndex1 or cellIndex2
250 auto iter = std::find_if(currentList.begin(), currentList.end(), [&](const auto &pair) {
251 const auto &[particlePtr, list] = pair;
252 return particlePtr == ptr1Ptr[i];
253 });
254 if (iter != currentList.end()) {
255 iter->second.push_back(ptr2Ptr[j]);
256 } else {
257 currentList.emplace_back(ptr1Ptr[i], std::vector<Particle_T *>{});
258 currentList.back().second.reserve(_newListAllocationSize);
259 currentList.back().second.push_back(ptr2Ptr[j]);
260 }
261 }
262 }
263 }
264 }
265 }
266 }
267
271 constexpr static auto getNeededAttr() {
272 return std::array<typename Particle_T::AttributeNames, 4>{
273 Particle_T::AttributeNames::ptr, Particle_T::AttributeNames::posX, Particle_T::AttributeNames::posY,
274 Particle_T::AttributeNames::posZ};
275 }
276
280 constexpr static auto getNeededAttr(std::false_type) {
281 return std::array<typename Particle_T::AttributeNames, 4>{
282 Particle_T::AttributeNames::ptr, Particle_T::AttributeNames::posX, Particle_T::AttributeNames::posY,
283 Particle_T::AttributeNames::posZ};
284 }
285
289 constexpr static auto getComputedAttr() { return std::array<typename Particle_T::AttributeNames, 0>{}; }
290
291 private:
295 NeighborListsType &_neighborLists;
296 std::unordered_map<Particle_T *, std::pair<size_t, size_t>> &_particleToCellMap;
297 double _cutoffSkinSquared;
302 std::array<size_t, 3> _cellsPerDim;
303
304 std::vector<FullParticleCell<Particle_T>> *_cells = nullptr;
305
309 size_t _newListAllocationSize;
310};
311
312} // namespace autopas
This class handles the storage of particles in their full form.
Definition: FullParticleCell.h:26
PairwiseFunctor class.
Definition: PairwiseFunctor.h:31
View on a fixed part of a SoA between a start index and an end index.
Definition: SoAView.h:23
size_t size() const
Returns the number of particles in the view.
Definition: SoAView.h:83
This functor can generate verlet lists using the typical pairwise traversal.
Definition: VLCAllCellsGeneratorFunctor.h:22
static constexpr auto getNeededAttr(std::false_type)
Get attributes needed for computation without N3 optimization.
Definition: VLCAllCellsGeneratorFunctor.h:280
bool allowsNewton3() override
Specifies whether the functor is capable of Newton3-like functors.
Definition: VLCAllCellsGeneratorFunctor.h:50
void SoAFunctorPair(SoAView< SoAArraysType > soa1, SoAView< SoAArraysType > soa2, bool) override
Functor for structure of arrays (SoA)
Definition: VLCAllCellsGeneratorFunctor.h:184
void SoAFunctorSingle(SoAView< SoAArraysType > soa, bool newton3) override
PairwiseFunctor for structure of arrays (SoA)
Definition: VLCAllCellsGeneratorFunctor.h:135
static constexpr auto getComputedAttr()
Get attributes computed by this functor.
Definition: VLCAllCellsGeneratorFunctor.h:289
bool isRelevantForTuning() override
Specifies whether the functor should be considered for the auto-tuning process.
Definition: VLCAllCellsGeneratorFunctor.h:48
VLCAllCellsGeneratorFunctor(NeighborListsType &neighborLists, std::unordered_map< Particle_T *, std::pair< size_t, size_t > > &particleToCellMap, double cutoffSkin, size_t newListAllocationSize, const std::array< size_t, 3 > &cellsPerDim={})
Constructor.
Definition: VLCAllCellsGeneratorFunctor.h:35
void setCells(std::vector< FullParticleCell< Particle_T > > *cells)
Set the cells pointer.
Definition: VLCAllCellsGeneratorFunctor.h:66
std::string getName() override
Returns name of functor.
Definition: VLCAllCellsGeneratorFunctor.h:46
void AoSFunctor(Particle_T &i, Particle_T &j, bool newton3) override
PairwiseFunctor for arrays of structures (AoS).
Definition: VLCAllCellsGeneratorFunctor.h:71
static constexpr auto getNeededAttr()
Get attributes needed for computation.
Definition: VLCAllCellsGeneratorFunctor.h:271
bool allowsNonNewton3() override
Specifies whether the functor is capable of non-Newton3-like functors.
Definition: VLCAllCellsGeneratorFunctor.h:56
static void exception(const Exception e)
Handle an exception derived by std::exception.
Definition: ExceptionHandler.h:63
std::vector< std::vector< std::pair< Particle_T *, std::vector< Particle_T * > > > > AllCellsNeighborListsType
Cell wise verlet lists for neighbors from all adjacent cells: For every cell, a vector of pairs.
Definition: VerletListsCellsHelpers.h:27
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
constexpr std::array< T, SIZE > min(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Takes elementwise minimum, returns the result.
Definition: ArrayMath.h:62
constexpr std::array< T, 3 > oneToThreeD(T ind, const std::array< T, 3 > &dims)
Convert a 1d index to a 3d index.
Definition: ThreeDimensionalMapping.h:55
constexpr T threeToOneD(T x, T y, T z, const std::array< T, 3 > &dims)
Convert a 3d index to a 1d index.
Definition: ThreeDimensionalMapping.h:29
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:32