39template <
class Particle_T>
63 LinkedCells(
const std::array<double, 3> &boxMin,
const std::array<double, 3> &boxMax,
const double cutoff,
64 const double skin,
const unsigned int rebuildFrequency,
const double cellSizeFactor = 1.0,
70 [[nodiscard]] ContainerOption
getContainerType()
const override {
return ContainerOption::linkedCells; }
74 void reserve(
size_t numParticles,
size_t numParticlesHaloEstimate)
override {
75 _cellBlock.reserve(numParticles + numParticlesHaloEstimate);
89 auto cells =
_cellBlock.getNearbyHaloCells(haloParticle.getR(), this->getVerletSkin());
90 for (
auto cellptr : cells) {
96 AutoPasLog(TRACE,
"UpdateHaloParticle was not able to update particle: {}", haloParticle.toString());
114 return [&](
const std::array<unsigned long, 3> &cellsPerDimension,
115 const std::array<unsigned long, 3> &lowerCorner,
const std::array<unsigned long, 3> &upperCorner) {
123 [&](
const std::array<unsigned long, 3> &cellsPerDimension,
const std::array<unsigned long, 3> &lowerCorner,
124 const std::array<unsigned long, 3> &upperCorner) {
return 1; };
137 [[nodiscard]] std::vector<ParticleType>
updateContainer(
bool keepNeighborListsValid)
override {
138 if (keepNeighborListsValid) {
144 std::vector<ParticleType> invalidParticles;
147 std::vector<ParticleType> myInvalidParticles{}, myInvalidNotOwnedParticles{};
149 myInvalidParticles.reserve(128);
150 myInvalidNotOwnedParticles.reserve(128);
152 for (
size_t cellId = 0; cellId < this->
getCells().size(); ++cellId) {
154 this->
getCells()[cellId].deleteDummyParticles();
157 if (this->
getCells()[cellId].isEmpty())
continue;
159 const auto [cellLowerCorner, cellUpperCorner] = this->
getCellBlock().getCellBoundingBox(cellId);
161 auto &particleVec = this->
getCells()[cellId]._particles;
162 for (
auto pIter = particleVec.begin(); pIter < particleVec.end();) {
164 if (
utils::notInBox(pIter->getR(), cellLowerCorner, cellUpperCorner)) {
165 myInvalidParticles.push_back(*pIter);
167 *pIter = particleVec.back();
168 particleVec.pop_back();
178 for (
auto &&p : myInvalidParticles) {
180 if (
utils::inBox(p.getR(), this->getBoxMin(), this->getBoxMax())) {
181 this->
template addParticle<false>(p);
183 myInvalidNotOwnedParticles.push_back(p);
188 invalidParticles.insert(invalidParticles.end(), myInvalidNotOwnedParticles.begin(),
189 myInvalidNotOwnedParticles.end());
192 return invalidParticles;
200 std::tuple<const Particle_T *, size_t, size_t>
getParticle(
size_t cellIndex,
size_t particleIndex,
201 IteratorBehavior iteratorBehavior,
202 const std::array<double, 3> &boxMin,
203 const std::array<double, 3> &boxMax)
const override {
204 return getParticleImpl<true>(cellIndex, particleIndex, iteratorBehavior, boxMin, boxMax);
206 std::tuple<const Particle_T *, size_t, size_t>
getParticle(
size_t cellIndex,
size_t particleIndex,
207 IteratorBehavior iteratorBehavior)
const override {
209 constexpr std::array<double, 3> boxMin{std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(),
210 std::numeric_limits<double>::lowest()};
212 constexpr std::array<double, 3> boxMax{std::numeric_limits<double>::max(), std::numeric_limits<double>::max(),
213 std::numeric_limits<double>::max()};
214 return getParticleImpl<false>(cellIndex, particleIndex, iteratorBehavior, boxMin, boxMax);
228 template <
bool regionIter>
229 std::tuple<const Particle_T *, size_t, size_t>
getParticleImpl(
size_t cellIndex,
size_t particleIndex,
230 IteratorBehavior iteratorBehavior,
231 const std::array<double, 3> &boxMin,
232 const std::array<double, 3> &boxMax)
const {
233 using namespace autopas::utils::ArrayMath::literals;
235 std::array<double, 3> boxMinWithSafetyMargin = boxMin;
236 std::array<double, 3> boxMaxWithSafetyMargin = boxMax;
237 if constexpr (regionIter) {
244 const auto [startCellIndex, endCellIndex] = [&]() -> std::tuple<size_t, size_t> {
245 if constexpr (regionIter) {
247 return {
_cellBlock.get1DIndexOfPosition(boxMinWithSafetyMargin),
248 _cellBlock.get1DIndexOfPosition(boxMaxWithSafetyMargin)};
250 if (not(iteratorBehavior & IteratorBehavior::halo)) {
255 return {0, this->
_cells.size() - 1};
261 if (cellIndex == 0 and particleIndex == 0) {
266 if (cellIndex >= this->
_cells.size()) {
267 return {
nullptr, 0, 0};
270 if (particleIndex >= this->
_cells[cellIndex].
size() or
271 not containerIteratorUtils::particleFulfillsIteratorRequirements<regionIter>(
272 this->
_cells[cellIndex][particleIndex], iteratorBehavior, boxMin, boxMax)) {
274 std::tie(cellIndex, particleIndex) =
275 advanceIteratorIndices<regionIter>(cellIndex, particleIndex, iteratorBehavior, boxMin, boxMax,
276 boxMinWithSafetyMargin, boxMaxWithSafetyMargin, endCellIndex);
280 if (cellIndex > endCellIndex) {
281 return {
nullptr, 0, 0};
283 const Particle_T *retPtr = &this->
_cells[cellIndex][particleIndex];
285 return {retPtr, cellIndex, particleIndex};
290 auto &particleVec =
_cellBlock.getContainingCell(particle.getR())._particles;
291 const bool isRearParticle = &particle == &particleVec.back();
293 particle = particleVec.back();
294 particleVec.pop_back();
295 return not isRearParticle;
299 auto &particleVec = this->
_cells[cellIndex]._particles;
300 auto &particle = particleVec[particleIndex];
302 particle = particleVec.back();
303 particleVec.pop_back();
304 return particleIndex < particleVec.size();
308 IteratorBehavior behavior = autopas::IteratorBehavior::ownedOrHalo,
314 IteratorBehavior behavior = autopas::IteratorBehavior::ownedOrHalo,
316 nullptr)
const override {
326 template <
typename Lambda>
327 void forEach(Lambda forEachLambda, IteratorBehavior behavior = IteratorBehavior::ownedOrHalo) {
328 if (behavior == IteratorBehavior::ownedOrHaloOrDummy) {
330 cell.forEach(forEachLambda);
333 for (
size_t index = 0; index <
getCells().size(); index++) {
334 if (not
_cellBlock.ignoreCellForIteration(index, behavior)) {
335 getCells()[index].forEach(forEachLambda, behavior);
349 template <
typename Lambda,
typename A>
350 void reduce(Lambda reduceLambda, A &result, IteratorBehavior behavior = IteratorBehavior::ownedOrHalo) {
351 if (behavior == IteratorBehavior::ownedOrHaloOrDummy) {
353 cell.reduce(reduceLambda, result);
356 for (
size_t index = 0; index <
getCells().size(); index++) {
357 if (not
_cellBlock.ignoreCellForIteration(index, behavior)) {
358 getCells()[index].reduce(reduceLambda, result, behavior);
365 const std::array<double, 3> &lowerCorner,
const std::array<double, 3> &higherCorner, IteratorBehavior behavior,
371 const std::array<double, 3> &lowerCorner,
const std::array<double, 3> &higherCorner, IteratorBehavior behavior,
373 nullptr)
const override {
385 template <
typename Lambda>
387 const std::array<double, 3> &higherCorner, IteratorBehavior behavior) {
388 using namespace autopas::utils::ArrayMath::literals;
393 const size_t numCellsOfInterest = (stopIndex3D[0] - startIndex3D[0] + 1) * (stopIndex3D[1] - startIndex3D[1] + 1) *
394 (stopIndex3D[2] - startIndex3D[2] + 1);
395 std::vector<size_t> cellsOfInterest;
396 cellsOfInterest.reserve(numCellsOfInterest);
398 const auto &cellsPerDimensionWithHalo = this->
_cellBlock.getCellsPerDimensionWithHalo();
400 for (
size_t z = startIndex3D[2]; z <= stopIndex3D[2]; ++z) {
401 for (
size_t y = startIndex3D[1]; y <= stopIndex3D[1]; ++y) {
402 for (
size_t x = startIndex3D[0]; x <= stopIndex3D[0]; ++x) {
408 for (
auto cellIndex : cellsOfInterest) {
409 if (not
_cellBlock.ignoreCellForIteration(cellIndex, behavior)) {
410 getCells()[cellIndex].forEach(forEachLambda, lowerCorner, higherCorner, behavior);
425 template <
typename Lambda,
typename A>
426 void reduceInRegion(Lambda reduceLambda, A &result,
const std::array<double, 3> &lowerCorner,
427 const std::array<double, 3> &higherCorner, IteratorBehavior behavior) {
428 using namespace autopas::utils::ArrayMath::literals;
432 const size_t numCellsOfInterest = (stopIndex3D[0] - startIndex3D[0] + 1) * (stopIndex3D[1] - startIndex3D[1] + 1) *
433 (stopIndex3D[2] - startIndex3D[2] + 1);
434 std::vector<size_t> cellsOfInterest;
435 cellsOfInterest.reserve(numCellsOfInterest);
437 const auto &cellsPerDimensionWithHalo = this->
_cellBlock.getCellsPerDimensionWithHalo();
439 for (
size_t z = startIndex3D[2]; z <= stopIndex3D[2]; ++z) {
440 for (
size_t y = startIndex3D[1]; y <= stopIndex3D[1]; ++y) {
441 for (
size_t x = startIndex3D[0]; x <= stopIndex3D[0]; ++x) {
447 for (
auto cellIndex : cellsOfInterest) {
448 if (not
_cellBlock.ignoreCellForIteration(cellIndex, behavior)) {
449 getCells()[cellIndex].reduce(reduceLambda, result, lowerCorner, higherCorner, behavior);
487 template <
bool regionIter>
489 size_t cellIndex,
size_t particleIndex, IteratorBehavior iteratorBehavior,
const std::array<double, 3> &boxMin,
490 const std::array<double, 3> &boxMax, std::array<double, 3> boxMinWithSafetyMargin,
491 std::array<double, 3> boxMaxWithSafetyMargin,
size_t endCellIndex)
const {
496 auto cellIsRelevant = [&]() ->
bool {
499 (iteratorBehavior & IteratorBehavior::owned and
_cellBlock.cellCanContainOwnedParticles(cellIndex)) or
500 (iteratorBehavior & IteratorBehavior::halo and
_cellBlock.cellCanContainHaloParticles(cellIndex));
501 if constexpr (regionIter) {
505 const auto [cellLowCorner, cellHighCorner] =
_cellBlock.getCellBoundingBox(cellIndex);
507 utils::boxesOverlap(cellLowCorner, cellHighCorner, boxMinWithSafetyMargin, boxMaxWithSafetyMargin);
519 while (not cellIsRelevant() or particleIndex >= this->
_cells[cellIndex].
size()) {
527 if (cellIndex > endCellIndex) {
528 return {std::numeric_limits<
decltype(cellIndex)>::max(), std::numeric_limits<
decltype(particleIndex)>::max()};
531 }
while (not containerIteratorUtils::particleFulfillsIteratorRequirements<regionIter>(
532 this->
_cells[cellIndex][particleIndex], iteratorBehavior, boxMin, boxMax));
535 return {cellIndex, particleIndex};
543 template <
typename Traversal>
550 if (traversalInterface && cellTraversal) {
554 "The selected traversal is not compatible with the LinkedCells container. TraversalID: {}",
555 traversal->getTraversalType());
#define AutoPasLog(lvl, fmt,...)
Macro for logging providing common meta information without filename.
Definition: Logger.h:24
#define AUTOPAS_OPENMP(args)
Empty macro to throw away any arguments.
Definition: WrapOpenMP.h:126
Base class for traversals utilising load balancing.
Definition: BalancedTraversal.h:19
std::function< unsigned long(const std::array< unsigned long, 3 > &, const std::array< unsigned long, 3 > &, const std::array< unsigned long, 3 > &)> EstimatorFunction
Type signature for load estimators.
Definition: BalancedTraversal.h:26
The CellBasedParticleContainer class stores particles in some object and provides methods to iterate ...
Definition: CellBasedParticleContainer.h:25
double getVerletSkin() const final
Returns the verlet Skin length.
Definition: CellBasedParticleContainer.h:94
double getInteractionLength() const final
Return the interaction length (cutoff+skin) of the container.
Definition: CellBasedParticleContainer.h:89
std::vector< FullParticleCell< Particle_T > > _cells
Vector of particle cells.
Definition: CellBasedParticleContainer.h:157
size_t size() const override
Get the total number of particles saved in the container (owned + halo + dummy).
Definition: CellBasedParticleContainer.h:131
A cell pair traversal.
Definition: CellTraversal.h:23
virtual void setCellsToTraverse(std::vector< ParticleCell > &cells)
Sets the cells to iterate over.
Definition: CellTraversal.h:40
Public iterator class that iterates over a particle container and additional vectors (which are typic...
Definition: ContainerIterator.h:93
std::conditional_t< modifiable, std::vector< std::vector< Particle_T > * >, std::vector< std::vector< Particle_T > const * > > ParticleVecType
Type of the additional vector collection.
Definition: ContainerIterator.h:106
This class handles the storage of particles in their full form.
Definition: FullParticleCell.h:26
void addParticle(const Particle_T &p) override
Adds a Particle to the cell.
Definition: FullParticleCell.h:51
Interface for traversals used by the LinkedCell class.
Definition: LCTraversalInterface.h:18
LinkedCells class.
Definition: LinkedCells.h:40
ContainerIterator< ParticleType, false, true > getRegionIterator(const std::array< double, 3 > &lowerCorner, const std::array< double, 3 > &higherCorner, IteratorBehavior behavior, typename ContainerIterator< ParticleType, false, true >::ParticleVecType *additionalVectors=nullptr) const override
Iterate over all particles in a specified region for(auto iter = container.getRegionIterator(lowCorne...
Definition: LinkedCells.h:370
bool deleteParticle(size_t cellIndex, size_t particleIndex) override
Deletes the particle at the given index positions as long as this does not compromise the validity of...
Definition: LinkedCells.h:298
autopas::LoadEstimatorOption _loadEstimator
load estimation algorithm for balanced traversals.
Definition: LinkedCells.h:567
const internal::CellBlock3D< ParticleCell > & getCellBlock() const
Get the cell block, not supposed to be used except by verlet lists.
Definition: LinkedCells.h:464
std::tuple< const Particle_T *, size_t, size_t > getParticleImpl(size_t cellIndex, size_t particleIndex, IteratorBehavior iteratorBehavior, const std::array< double, 3 > &boxMin, const std::array< double, 3 > &boxMax) const
Container specific implementation for getParticle.
Definition: LinkedCells.h:229
LinkedCells(const std::array< double, 3 > &boxMin, const std::array< double, 3 > &boxMax, const double cutoff, const double skin, const unsigned int rebuildFrequency, const double cellSizeFactor=1.0, LoadEstimatorOption loadEstimator=LoadEstimatorOption::squaredParticlesPerCell)
Constructor of the LinkedCells class.
Definition: LinkedCells.h:63
BalancedTraversal::EstimatorFunction getLoadEstimatorFunction()
Generates the load estimation function depending on _loadEstimator.
Definition: LinkedCells.h:110
void forEachInRegion(Lambda forEachLambda, const std::array< double, 3 > &lowerCorner, const std::array< double, 3 > &higherCorner, IteratorBehavior behavior)
Execute code on all particles in this container in a certain region as defined by a lambda function.
Definition: LinkedCells.h:386
void deleteHaloParticles() override
Deletes all halo particles.
Definition: LinkedCells.h:100
void addHaloParticleImpl(const ParticleType &haloParticle) override
Adds a particle to the container that lies in the halo region of the container.
Definition: LinkedCells.h:83
internal::CellBlock3D< ParticleCell > & getCellBlock()
Get the cell block, not supposed to be used except by verlet lists.
Definition: LinkedCells.h:458
typename ParticleCell::ParticleType ParticleType
Type of the Particle.
Definition: LinkedCells.h:50
void prepareTraversal(Traversal &traversal)
Checks if a given traversal is allowed for LinkedCells and sets it up for the force interactions.
Definition: LinkedCells.h:544
void reduceInRegion(Lambda reduceLambda, A &result, const std::array< double, 3 > &lowerCorner, const std::array< double, 3 > &higherCorner, IteratorBehavior behavior)
Execute code on all particles in this container in a certain region as defined by a lambda function.
Definition: LinkedCells.h:426
CellType getParticleCellTypeEnum() const override
Get the ParticleCell type as an Enum.
Definition: LinkedCells.h:72
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 reduce(Lambda reduceLambda, A &result, IteratorBehavior behavior=IteratorBehavior::ownedOrHalo)
Reduce properties of particles as defined by a lambda function.
Definition: LinkedCells.h:350
std::vector< ParticleType > updateContainer(bool keepNeighborListsValid) override
Updates the container.
Definition: LinkedCells.h:137
ContainerIterator< ParticleType, true, true > getRegionIterator(const std::array< double, 3 > &lowerCorner, const std::array< double, 3 > &higherCorner, IteratorBehavior behavior, typename ContainerIterator< ParticleType, true, true >::ParticleVecType *additionalVectors=nullptr) override
Iterate over all particles in a specified region for(auto iter = container.getRegionIterator(lowCorne...
Definition: LinkedCells.h:364
bool deleteParticle(Particle_T &particle) override
Deletes the given particle as long as this does not compromise the validity of the container.
Definition: LinkedCells.h:288
TraversalSelectorInfo getTraversalSelectorInfo() const override
Generates a traversal selector info for this container.
Definition: LinkedCells.h:195
internal::CellBlock3D< ParticleCell > _cellBlock
object to manage the block of cells.
Definition: LinkedCells.h:562
void computeInteractions(TraversalInterface *traversal) override
Iterates over all particle multiples (e.g.
Definition: LinkedCells.h:129
void reserve(size_t numParticles, size_t numParticlesHaloEstimate) override
Reserve memory for a given number of particles in the container and logic layers.
Definition: LinkedCells.h:74
void rebuildNeighborLists(TraversalInterface *traversal) override
Rebuilds the neighbor lists for the next traversals.
Definition: LinkedCells.h:102
ContainerIterator< ParticleType, false, false > begin(IteratorBehavior behavior=autopas::IteratorBehavior::ownedOrHalo, typename ContainerIterator< ParticleType, false, false >::ParticleVecType *additionalVectors=nullptr) const override
Iterate over all particles using for(auto iter = container.begin(); iter.isValid(); ++iter) .
Definition: LinkedCells.h:313
std::tuple< size_t, size_t > advanceIteratorIndices(size_t cellIndex, size_t particleIndex, IteratorBehavior iteratorBehavior, const std::array< double, 3 > &boxMin, const std::array< double, 3 > &boxMax, std::array< double, 3 > boxMinWithSafetyMargin, std::array< double, 3 > boxMaxWithSafetyMargin, size_t endCellIndex) const
Given a pair of cell-/particleIndex and iterator restrictions either returns the next indices that ma...
Definition: LinkedCells.h:488
void forEach(Lambda forEachLambda, IteratorBehavior behavior=IteratorBehavior::ownedOrHalo)
Execute code on all particles in this container as defined by a lambda function.
Definition: LinkedCells.h:327
bool updateHaloParticle(const ParticleType &haloParticle) override
Update a halo particle of the container with the given haloParticle.
Definition: LinkedCells.h:88
std::tuple< const Particle_T *, size_t, size_t > getParticle(size_t cellIndex, size_t particleIndex, IteratorBehavior iteratorBehavior, const std::array< double, 3 > &boxMin, const std::array< double, 3 > &boxMax) const override
Fetch the pointer to a particle, identified via a cell and particle index.
Definition: LinkedCells.h:200
std::vector< ParticleCell > & getCells()
Returns a non-const reference to the cell data structure.
Definition: LinkedCells.h:470
ContainerOption getContainerType() const override
Get the ContainerType.
Definition: LinkedCells.h:70
std::tuple< const Particle_T *, size_t, size_t > getParticle(size_t cellIndex, size_t particleIndex, IteratorBehavior iteratorBehavior) const override
Fetch the pointer to a particle, identified via a cell and particle index.
Definition: LinkedCells.h:206
void addParticleImpl(const ParticleType &p) override
Adds a particle to the container.
Definition: LinkedCells.h:78
Class representing the load estimator choices.
Definition: LoadEstimatorOption.h:18
Value
Possible choices for the load estimation algorithm.
Definition: LoadEstimatorOption.h:23
@ squaredParticlesPerCell
Number of particles per cell squared.
Definition: LoadEstimatorOption.h:31
@ none
No load estimator.
Definition: LoadEstimatorOption.h:27
Particle_T ParticleType
The particle type for this cell.
Definition: ParticleCell.h:56
This interface serves as a common parent class for all traversals.
Definition: TraversalInterface.h:18
virtual void endTraversal()=0
Finalizes the traversal.
virtual void traverseParticles()=0
Traverse the particles by pairs, triplets etc.
virtual void initTraversal()=0
Initializes the traversal.
Info for traversals of a specific container.
Definition: TraversalSelectorInfo.h:14
Class that manages a block of ParticleCells.
Definition: CellBlock3D.h:30
static void exception(const Exception e)
Handle an exception derived by std::exception.
Definition: ExceptionHandler.h:63
std::vector< typename ContainerType::ParticleType > collectParticlesAndMarkNonOwnedAsDummy(ContainerType &container)
Collects leaving particles and marks halo particles as dummy.
Definition: LeavingParticleCollector.h:85
static bool checkParticleInCellAndUpdateByID(CellType &cell, const typename CellType::ParticleType &particle)
Updates a found particle within cellI to the values of particleI.
Definition: ParticleCellHelpers.h:21
unsigned long squaredParticlesPerCell(const std::vector< ParticleCell > &cells, const std::array< unsigned long, 3 > &cellsPerDimension, const std::array< unsigned long, 3 > &lowerCorner, const std::array< unsigned long, 3 > &upperCorner)
Sums up the squared number of particles for all cells within region.
Definition: LoadEstimators.h:31
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
bool boxesOverlap(const std::array< T, 3 > &boxALow, const std::array< T, 3 > &boxAHigh, const std::array< T, 3 > &boxBLow, const std::array< T, 3 > &boxBHigh)
Checks if two boxes have overlap.
Definition: inBox.h:67
bool notInBox(const std::array< T, 3 > &position, const std::array< T, 3 > &low, const std::array< T, 3 > &high)
Checks if position is not inside of a box defined by low and high.
Definition: inBox.h:50
bool inBox(const std::array< T, 3 > &position, const std::array< T, 3 > &low, const std::array< T, 3 > &high)
Checks if position is inside of a box defined by low and high.
Definition: inBox.h:26
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:32
CellType
The ParticleCell Type as an Enum.
Definition: ParticleCell.h:19
@ FullParticleCell
FullParticleCell : Default cell type for almost everything.
int autopas_get_num_threads()
Dummy for omp_get_num_threads() when no OpenMP is available.
Definition: WrapOpenMP.h:138
int autopas_get_thread_num()
Dummy for omp_set_lock() when no OpenMP is available.
Definition: WrapOpenMP.h:132