AutoPas  3.0.0
Loading...
Searching...
No Matches
VLCAllCellsNeighborList.h
Go to the documentation of this file.
1
12#pragma once
13
18
19namespace autopas {
20
26template <class ParticleCell>
27class TraversalSelector;
28
29template <class Particle_T, class NeighborList>
30class VLCTraversalInterface;
31
37template <class Particle_T>
39 public:
44
48 using SoAPairOfParticleAndList = std::pair<size_t, std::vector<size_t, autopas::AlignedAllocator<size_t>>>;
49
54 using SoAListType = typename std::vector<std::vector<SoAPairOfParticleAndList>>;
55
59 [[nodiscard]] ContainerOption getContainerType() const override { return ContainerOption::verletListsCells; }
60
64 void buildAoSNeighborList(LinkedCells<Particle_T> &linkedCells, bool useNewton3, double cutoff, double skin,
65 double interactionLength, const TraversalOption vlcTraversalOpt,
66 typename VerletListsCellsHelpers::VLCBuildType buildType) override {
67 using namespace utils::ArrayMath::literals;
68 this->_internalLinkedCells = &linkedCells;
69 auto &cells = linkedCells.getCells();
70 const auto cellsPerDim = this->_internalLinkedCells->getCellBlock().getCellsPerDimensionWithHalo();
71
72 const auto boxSizeWithHalo = this->_internalLinkedCells->getBoxMax() - this->_internalLinkedCells->getBoxMin() +
73 std::array<double, 3>{interactionLength, interactionLength, interactionLength} * 2.;
74 const auto listLengthEstimate = VerletListsCellsHelpers::estimateListLength(
75 this->_internalLinkedCells->getNumberOfParticles(IteratorBehavior::ownedOrHalo), boxSizeWithHalo,
76 interactionLength, 1.3);
77
78 const auto offsetsC08 = VerletListsCellsHelpers::buildC08BaseStep(utils::ArrayUtils::static_cast_copy_array<int>(
79 this->_internalLinkedCells->getCellBlock().getCellsPerDimensionWithHalo()));
80
81 // Helper function to estimate the number of neighbor lists for one base step
82 // TODO: This is a generous and rough estimate and can probably be improved!
83 const auto estimateNumLists = [&](size_t baseCellIndex) {
84 // If the cell is near the end of any dimension we can reduce the estimate to the particles in the base cell,
85 // because all other cells' interactions would be from halos.
86 const auto cellIndex3D = utils::ThreeDimensionalMapping::oneToThreeD(baseCellIndex, cellsPerDim);
87 const auto numTouchedBoundaries = [&]() {
88 int acc = 0;
89 for (size_t i = 0; i < 3; ++i) {
90 // false == 0 ; true == 1
91 acc += static_cast<int>(cellIndex3D[i] == (cellsPerDim[i] - 1));
92 }
93 return acc;
94 }();
95 if (numTouchedBoundaries > 0) {
96 if (useNewton3) {
97 return cells[baseCellIndex].size();
98 } else {
99 // In this case we have to accommodate the lists for the reverse interactions from all non-halo neighbors.
100 // 1x for lists from the cell itself and once more per untouched border.
101 return cells[baseCellIndex].size() * (4 - numTouchedBoundaries);
102 }
103 }
104 size_t estimate = 0;
105 std::map<int, double> offsetFactors{};
106 std::map<int, double> offsetFactorsNoN3{};
107 for (const auto [offsetA, offsetB, factor] : offsetsC08) {
108 offsetFactors[offsetA] = std::max(offsetFactors[offsetA], factor);
109 offsetFactorsNoN3[offsetB] = std::max(offsetFactors[offsetB], factor);
110 }
111 for (const auto &[offset, factor] : offsetFactors) {
112 estimate += cells[baseCellIndex + offset].size() * factor;
113 }
114 if (not useNewton3) {
115 for (const auto &[offset, factor] : offsetFactorsNoN3) {
116 estimate += cells[baseCellIndex + offset].size() * factor;
117 }
118 }
119 return estimate;
120 };
121
122 // Initialize a map of neighbor lists for each cell.
123 _aosNeighborList.clear();
124 const size_t numCells = cells.size();
125 _aosNeighborList.resize(numCells);
126 for (size_t cellIndex = 0; cellIndex < numCells; ++cellIndex) {
127 const auto estimateForNumberOfLists = [&]() {
128 // Usually each cell holds one list per particle, except vlc_c08, which holds all lists of a base step,
129 // which involves also lists from other cells' particles.
130 if (vlcTraversalOpt == TraversalOption::vlc_c08) {
131 return estimateNumLists(cellIndex);
132 } else {
133 return cells[cellIndex].size();
134 }
135 }();
136 auto &cell = cells[cellIndex];
137 _aosNeighborList[cellIndex].reserve(estimateForNumberOfLists);
138 size_t particleIndexWithinCell = 0;
139 for (auto iter = cell.begin(); iter != cell.end(); ++iter, ++particleIndexWithinCell) {
140 Particle_T *particle = &*iter;
141 _aosNeighborList[cellIndex].emplace_back(particle, std::vector<Particle_T *>());
142 _aosNeighborList[cellIndex].back().second.reserve(listLengthEstimate);
143 _particleToCellMap[particle] = std::make_pair(cellIndex, particleIndexWithinCell);
144 }
145 }
146
147 applyBuildFunctor(linkedCells, useNewton3, cutoff, skin, interactionLength, vlcTraversalOpt, buildType);
148 }
149
153 size_t getNumberOfPartners(const Particle_T *particle) const override {
154 const auto &[cellIndex, particleIndexInCell] = _particleToCellMap.at(const_cast<Particle_T *>(particle));
155 return _aosNeighborList.at(cellIndex).at(particleIndexInCell).second.size();
156 }
157
163 return _aosNeighborList;
164 }
165
170 auto &getSoANeighborList() { return _soaNeighborList; }
171
175 void generateSoAFromAoS(LinkedCells<Particle_T> &linkedCells) override {
176 _soaNeighborList.clear();
177
178 // particle pointer to global index of particle
179 std::unordered_map<Particle_T *, size_t> particlePtrToIndex;
180 particlePtrToIndex.reserve(linkedCells.size());
181 size_t i = 0;
182 for (auto iter = linkedCells.begin(IteratorBehavior::ownedOrHaloOrDummy); iter.isValid(); ++iter, ++i) {
183 particlePtrToIndex[&(*iter)] = i;
184 }
185
186 _soaNeighborList.resize(linkedCells.getCells().size());
187
188 // iterate over cells and for each create the soa lists from the aos lists
189 for (size_t firstCellIndex = 0; firstCellIndex < _aosNeighborList.size(); ++firstCellIndex) {
190 const auto &aosLists = _aosNeighborList[firstCellIndex];
191 auto &soaLists = _soaNeighborList[firstCellIndex];
192 soaLists.reserve(aosLists.size());
193
194 // iterate over pairs of particle and neighbor list
195 for (const auto &[particlePtr, neighbors] : aosLists) {
196 // global index of current particle
197 size_t currentParticleGlobalIndex = particlePtrToIndex.at(particlePtr);
198
199 // create SoA neighbor list for current particle
200 std::vector<size_t, autopas::AlignedAllocator<size_t>> currentSoANeighborList{};
201 currentSoANeighborList.reserve(neighbors.size());
202
203 // fill the SoA neighbor list with the indices of the particles from the corresponding AoS neighbor list
204 for (const auto &neighborOfCurrentParticle : neighbors) {
205 currentSoANeighborList.emplace_back(particlePtrToIndex.at(neighborOfCurrentParticle));
206 }
207
208 // add the newly constructed pair of particle index and SoA neighbor list to cell
209 soaLists.emplace_back(currentParticleGlobalIndex, currentSoANeighborList);
210 }
211 }
212 }
213
214 void setUpTraversal(TraversalInterface *traversal) override {
215 auto vTraversal = dynamic_cast<VLCTraversalInterface<Particle_T, VLCAllCellsNeighborList<Particle_T>> *>(traversal);
216
217 if (vTraversal) {
218 vTraversal->setVerletList(*this);
219 } else {
221 "Trying to use a traversal of wrong type in VerletListCells.h. TraversalID: {}",
222 traversal->getTraversalType());
223 }
224 }
225
226 private:
230 void applyBuildFunctor(LinkedCells<Particle_T> &linkedCells, bool useNewton3, double cutoff, double skin,
231 double interactionLength, const TraversalOption &vlcTraversalOpt,
232 typename VerletListsCellsHelpers::VLCBuildType buildType) override {
233 // Generate the build traversal with the traversal selector and apply the build functor with it.
235 // Argument "cluster size" does not matter here.
236 TraversalSelectorInfo traversalSelectorInfo(linkedCells.getCellBlock().getCellsPerDimensionWithHalo(),
237 interactionLength, linkedCells.getCellBlock().getCellLength(), 0);
238
239 const auto dataLayout =
240 buildType == VerletListsCellsHelpers::VLCBuildType::aosBuild ? DataLayoutOption::aos : DataLayoutOption::soa;
241
242 // LC traversal that will be used to build the List
243 const TraversalOption lcBuildTraversalOpt =
244 vlcTraversalOpt == TraversalOption::vlc_c08 ? TraversalOption::lc_c08 : TraversalOption::lc_c18;
245
246 using namespace utils::ArrayMath::literals;
247 const auto boxSizeWithHalo = linkedCells.getBoxMax() - linkedCells.getBoxMin() +
248 std::array<double, 3>{interactionLength, interactionLength, interactionLength} * 2.;
249 const auto listLengthEstimate = VerletListsCellsHelpers::estimateListLength(
250 linkedCells.getNumberOfParticles(IteratorBehavior::ownedOrHalo), boxSizeWithHalo, interactionLength, 1.3);
251
252 if (vlcTraversalOpt == TraversalOption::vlc_c08) {
253 VLCAllCellsGeneratorFunctor<Particle_T, TraversalOption::vlc_c08> f(
254 _aosNeighborList, _particleToCellMap, cutoff + skin, listLengthEstimate,
255 linkedCells.getCellBlock().getCellsPerDimensionWithHalo());
256 f.setCells(&this->_internalLinkedCells->getCells());
257 // Build the AoS list using the AoS or SoA functor depending on buildType
258 auto buildTraversal = traversalSelector.template generateTraversal<std::remove_reference_t<decltype(f)>>(
259 lcBuildTraversalOpt, f, traversalSelectorInfo, dataLayout, useNewton3);
260 linkedCells.computeInteractions(buildTraversal.get());
261 } else {
262 VLCAllCellsGeneratorFunctor<Particle_T, TraversalOption::vlc_c18> f(
263 _aosNeighborList, _particleToCellMap, cutoff + skin, listLengthEstimate,
264 linkedCells.getCellBlock().getCellsPerDimensionWithHalo());
265 // Build the AoS list using the AoS or SoA functor depending on buildType
266 auto buildTraversal = traversalSelector.template generateTraversal<std::remove_reference_t<decltype(f)>>(
267 lcBuildTraversalOpt, f, traversalSelectorInfo, dataLayout, useNewton3);
268 linkedCells.computeInteractions(buildTraversal.get());
269 }
270 }
271
275 typename VerletListsCellsHelpers::AllCellsNeighborListsType<Particle_T> _aosNeighborList{};
276
280 std::unordered_map<Particle_T *, std::pair<size_t, size_t>> _particleToCellMap{};
281
286 SoAListType _soaNeighborList{};
287};
288} // namespace autopas
size_t getNumberOfParticles(IteratorBehavior behavior) const override
Get the number of particles with respect to the specified IteratorBehavior.
Definition: CellBasedParticleContainer.h:113
size_t size() const override
Get the total number of particles saved in the container (owned + halo + dummy).
Definition: CellBasedParticleContainer.h:131
const std::array< double, 3 > & getBoxMin() const final
Get the lower corner of the container without halo.
Definition: CellBasedParticleContainer.h:74
const std::array< double, 3 > & getBoxMax() const final
Get the upper corner of the container without halo.
Definition: CellBasedParticleContainer.h:69
LinkedCells class.
Definition: LinkedCells.h:40
internal::CellBlock3D< ParticleCell > & getCellBlock()
Get the cell block, not supposed to be used except by verlet lists.
Definition: LinkedCells.h:458
ContainerIterator< ParticleType, true, false > begin(IteratorBehavior behavior=autopas::IteratorBehavior::ownedOrHalo, typename ContainerIterator< ParticleType, true, false >::ParticleVecType *additionalVectors=nullptr) override
Iterate over all particles using for(auto iter = container.begin(); iter.isValid(); ++iter) .
Definition: LinkedCells.h:307
void computeInteractions(TraversalInterface *traversal) override
Iterates over all particle multiples (e.g.
Definition: LinkedCells.h:129
std::vector< ParticleCell > & getCells()
Returns a non-const reference to the cell data structure.
Definition: LinkedCells.h:470
This interface serves as a common parent class for all traversals.
Definition: TraversalInterface.h:18
virtual TraversalOption getTraversalType() const =0
Return a enum representing the name of the traversal class.
Info for traversals of a specific container.
Definition: TraversalSelectorInfo.h:14
TraversalSelector is used for the construction of the list in the applyBuildFunctor method.
Definition: TraversalSelector.h:62
Neighbor list to be used with VerletListsCells container.
Definition: VLCAllCellsNeighborList.h:38
void generateSoAFromAoS(LinkedCells< Particle_T > &linkedCells) override
Generates neighbor list in SoA layout from available neighbor list in AoS layout.
Definition: VLCAllCellsNeighborList.h:175
size_t getNumberOfPartners(const Particle_T *particle) const override
Gets the number of neighbors over all neighbor lists that belong to this particle.
Definition: VLCAllCellsNeighborList.h:153
ContainerOption getContainerType() const override
Returns the container type of this neighbor list and the container it belongs to.
Definition: VLCAllCellsNeighborList.h:59
void buildAoSNeighborList(LinkedCells< Particle_T > &linkedCells, bool useNewton3, double cutoff, double skin, double interactionLength, const TraversalOption vlcTraversalOpt, typename VerletListsCellsHelpers::VLCBuildType buildType) override
Builds AoS neighbor list from underlying linked cells object.
Definition: VLCAllCellsNeighborList.h:64
void setUpTraversal(TraversalInterface *traversal) override
Assigns the current traversal to the correct traversal interface.
Definition: VLCAllCellsNeighborList.h:214
VerletListsCellsHelpers::AllCellsNeighborListsType< Particle_T > & getAoSNeighborList()
Returns the neighbor list in AoS layout.
Definition: VLCAllCellsNeighborList.h:162
std::pair< size_t, std::vector< size_t, autopas::AlignedAllocator< size_t > > > SoAPairOfParticleAndList
Helper type definition.
Definition: VLCAllCellsNeighborList.h:48
typename VerletListsCellsHelpers::AllCellsNeighborListsType< Particle_T > ListType
Type of the data structure used to save the neighbor lists.
Definition: VLCAllCellsNeighborList.h:43
typename std::vector< std::vector< SoAPairOfParticleAndList > > SoAListType
Helper type definition.
Definition: VLCAllCellsNeighborList.h:54
auto & getSoANeighborList()
Returns the neighbor list in SoA layout.
Definition: VLCAllCellsNeighborList.h:170
Interface of neighbor lists to be used with VerletListsCells container.
Definition: VLCNeighborListInterface.h:19
LinkedCells< Particle_T > * _internalLinkedCells
Internal linked cells structure.
Definition: VLCNeighborListInterface.h:121
This class provides the Traversal Interface for the verlet lists cells container.
Definition: VLCTraversalInterface.h:27
virtual void setVerletList(NeighborList &verlet)
Sets the verlet list for the traversal to iterate over.
Definition: VLCTraversalInterface.h:41
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
std::vector< BaseStepOffsets > buildC08BaseStep(const std::array< int, 3 > &cellsPerDim)
Builds the list of offsets from the base cell for the c08 base step.
Definition: VerletListsCellsHelpers.cpp:26
VLCBuildType
Indicates which build functor should be used for the generation of the neighbor list.
Definition: VerletListsCellsHelpers.h:44
size_t estimateListLength(size_t numParticles, const std::array< double, 3 > &boxSize, double interactionLength, double correctionFactor)
Simple heuristic to calculate the average number of particles per verlet list assuming particles are ...
Definition: VerletListsCellsHelpers.cpp:16
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
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:32