23template <
class Particle_T>
35 std::vector<Particle_T> &_particlesToAdd;
37 double _interactionLengthSqr;
53 double interactionLengthSqr,
bool newton3)
54 : _clusterSize(clusterSize),
55 _neighborListsBuffer(neighborListsBuffer),
56 _particlesToAdd(particlesToAdd),
57 _towerBlock(towerBlock),
58 _interactionLengthSqr(interactionLengthSqr),
68 using namespace autopas::utils::ArrayMath::literals;
70 for (
auto &tower : _towerBlock) {
71 tower.deleteDummyParticles();
75 const size_t numParticles = std::accumulate(_towerBlock.
begin(), _towerBlock.
end(), _particlesToAdd.size(),
76 [](
auto acc,
const auto &tower) {
79 return acc + tower.getNumActualParticles();
84 const auto numTowersOld = _towerBlock.
size();
85 const auto [towerSideLength, numTowersPerDim] =
87 const auto numTowersNew = numTowersPerDim[0] * numTowersPerDim[1];
90 std::vector<std::vector<Particle_T>> invalidParticles{};
95 invalidParticles.reserve(1 + std::max(0,
static_cast<int>(numTowersNew) -
static_cast<int>(numTowersOld)) +
98 invalidParticles.push_back(std::move(_particlesToAdd));
99 _particlesToAdd.clear();
101 for (
size_t i = numTowersNew; i < numTowersOld; ++i) {
102 invalidParticles.push_back(std::move(_towerBlock[i].particleVector()));
107 _towerBlock.
resize(towerSideLength, numTowersPerDim);
111 invalidParticles.insert(invalidParticles.end(), collectedParticlesFromTowers.begin(),
112 collectedParticlesFromTowers.end());
117 const auto sizeEstimation =
118 static_cast<size_t>((
static_cast<double>(numParticles) /
static_cast<double>(numTowersNew)) * 1.2);
119 for (
auto &tower : _towerBlock) {
121 tower.setClusterSize(_clusterSize);
122 tower.reserve(sizeEstimation);
130 size_t numClusters = 0;
131 for (
auto &tower : _towerBlock) {
132 numClusters += tower.generateClusters();
133 for (
auto clusterIter = _newton3 ? tower.getClusters().begin() : tower.getFirstOwnedCluster();
134 clusterIter < (_newton3 ? tower.getClusters().end() : tower.getFirstTailHaloCluster()); ++clusterIter) {
138 clusterIter->setNeighborList(&(_neighborListsBuffer.template getNeighborListRef<false>(listID)));
158 double startDummiesX = 1000 * _towerBlock.
getHaloBoxMax()[0];
159 for (
size_t index = 0; index < _towerBlock.
size(); index++) {
160 _towerBlock[index].setDummyValues(startDummiesX +
static_cast<double>(index) * dummyParticleDistance,
161 dummyParticleDistance);
170 for (
auto &tower : _towerBlock) {
171 tower.setDummyParticlesToLastActualParticle();
172 for (
auto clusterIter = tower.getFirstOwnedCluster(); clusterIter < tower.getFirstTailHaloCluster();
174 clusterIter->clearNeighbors();
184 std::vector<std::vector<Particle_T>> invalidParticles;
185 invalidParticles.resize(_towerBlock.
size());
186 for (
size_t towerIndex = 0; towerIndex < _towerBlock.
size(); towerIndex++) {
187 invalidParticles[towerIndex] = _towerBlock[towerIndex].collectAllActualParticles();
188 _towerBlock[towerIndex].clear();
190 return invalidParticles;
200 std::vector<std::vector<Particle_T>> outOfBoundsParticles;
201 outOfBoundsParticles.resize(_towerBlock.
size());
202 for (
size_t towerIndex = 0; towerIndex < _towerBlock.
size(); towerIndex++) {
204 outOfBoundsParticles[towerIndex] = _towerBlock[towerIndex].collectOutOfBoundsParticles(towerBoxMin, towerBoxMax);
206 return outOfBoundsParticles;
218 const auto numVectors = particles2D.size();
220 for (
size_t index = 0; index < numVectors; index++) {
221 const std::vector<Particle_T> &vector = particles2D[index];
222 for (
const auto &particle : vector) {
225 tower.addParticle(particle);
227 AutoPasLog(TRACE,
"Not adding particle to VerletClusterLists container, because it is outside the halo:\n{}",
228 particle.toString());
244 for (
int towerIndexY = 0; towerIndexY <= maxTowerIndexY; towerIndexY++) {
245 for (
int towerIndexX = 0; towerIndexX <= maxTowerIndexX; towerIndexX++) {
247 const int minX = std::max(towerIndexX - numTowersPerInteractionLength, 0);
248 const int minY = std::max(towerIndexY - numTowersPerInteractionLength, 0);
249 const int maxX = std::min(towerIndexX + numTowersPerInteractionLength, maxTowerIndexX);
250 const int maxY = std::min(towerIndexY + numTowersPerInteractionLength, maxTowerIndexY);
278 template <
class FunType>
280 const int maxNeighborIndexX,
const int minNeighborIndexY,
const int maxNeighborIndexY,
284 for (
int neighborIndexY = minNeighborIndexY; neighborIndexY <= maxNeighborIndexY; neighborIndexY++) {
285 double distBetweenTowersY =
286 std::max(0, std::abs(towerIndexY - neighborIndexY) - 1) * _towerBlock.
getTowerSideLength()[1];
288 for (
int neighborIndexX = minNeighborIndexX; neighborIndexX <= maxNeighborIndexX; neighborIndexX++) {
289 if (_newton3 and not
isForwardNeighbor(towerIndexX, towerIndexY, neighborIndexX, neighborIndexY)) {
293 double distBetweenTowersX =
294 std::max(0, std::abs(towerIndexX - neighborIndexX) - 1) * _towerBlock.
getTowerSideLength()[0];
297 auto distBetweenTowersXYsqr = distBetweenTowersX * distBetweenTowersX + distBetweenTowersY * distBetweenTowersY;
299 if (distBetweenTowersXYsqr <= _interactionLengthSqr) {
300 auto &neighborTower = _towerBlock.
getTowerByIndex2D(neighborIndexX, neighborIndexY);
302 function(tower, neighborTower);
317 const int interactionCellTowerX = towerIndexX / numTowersPerInteractionLength;
318 const int interactionCellTowerY = towerIndexY / numTowersPerInteractionLength;
320 const int numInteractionCellsX =
static_cast<int>(
321 std::ceil(_towerBlock.
getTowersPerDim()[0] /
static_cast<double>(numTowersPerInteractionLength)));
323 return interactionCellTowerX + numInteractionCellsX * interactionCellTowerY;
340 const int neighborIndexY) {
344 if (interactionCellNeighborIndex1D > interactionCellTowerIndex1D) {
346 }
else if (interactionCellNeighborIndex1D < interactionCellTowerIndex1D) {
350 const auto towerIndex1D = _towerBlock.
towerIndex2DTo1D(towerIndexX, towerIndexY);
351 const auto neighborIndex1D = _towerBlock.
towerIndex2DTo1D(neighborIndexX, neighborIndexY);
353 return neighborIndex1D >= towerIndex1D;
370 const auto interactionLengthFracOfDomainZ =
372 const bool isSameTower = (&towerA == &towerB);
375 const auto neighborListReserveHeuristicFactor = (interactionLengthFracOfDomainZ * 2.1) / _clusterSize;
376 const auto isHaloCluster = [](
const auto &clusterIter,
const auto &tower) {
377 return clusterIter < tower.getFirstOwnedCluster() or clusterIter >= tower.getFirstTailHaloCluster();
382 if (not clusterIterA->empty()) {
384 neighborListReserveHeuristicFactor);
388 for (
auto clusterIterB = isSameTower and _newton3 ? clusterIterA + 1 : towerB.
getClusters().begin();
389 clusterIterB < towerB.
getClusters().end(); ++clusterIterB) {
391 if (&*clusterIterA == &*clusterIterB) {
395 if (isHaloCluster(clusterIterA, towerA) and isHaloCluster(clusterIterB, towerB)) {
398 if (not clusterIterB->empty()) {
399 const auto [aMin, aMax] = clusterIterA->getBoundingBox();
400 const auto [bMin, bMax] = clusterIterB->getBoundingBox();
401 const auto boxDistSquared = boxDistanceSquared(aMin, aMax, bMin, bMax);
402 if (boxDistSquared <= _interactionLengthSqr) {
403 clusterIterA->addNeighbor(*clusterIterB);
#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
Class for manual memory management of neighbor lists.
Definition: NeighborListsBuffer.h:31
void reserveNeighborLists(size_t n)
Resize the internal buffer so that there are new spare lists.
Definition: NeighborListsBuffer.h:115
size_t getNewNeighborList()
Reserves a neighbor list for use.
Definition: NeighborListsBuffer.h:74
Class to manage the grid of towers for the Verlet Cluster Lists container.
Definition: ClusterTowerBlock2D.h:25
size_t towerIndex2DTo1D(const size_t x, const size_t y) const
Returns the 1D index for the given 2D-coordinates of a tower.
Definition: ClusterTowerBlock2D.h:282
const std::array< double, 3 > & getHaloBoxMin() const
Getter.
Definition: ClusterTowerBlock2D.h:332
const std::array< double, 3 > & getHaloBoxMax() const
Getter.
Definition: ClusterTowerBlock2D.h:337
size_t size() const
Return the number of towers.
Definition: ClusterTowerBlock2D.h:82
const std::array< double, 2 > & getTowerSideLength() const
Getter.
Definition: ClusterTowerBlock2D.h:357
std::vector< ClusterTower< Particle_T > >::iterator begin()
Start iterator over towers.
Definition: ClusterTowerBlock2D.h:47
std::vector< ClusterTower< Particle_T > >::iterator end()
End iterator over towers.
Definition: ClusterTowerBlock2D.h:57
void resize(const std::array< double, 2 > &towerSideLength, const std::array< size_t, 2 > &towersPerDim)
Resize the internal grid and storage.
Definition: ClusterTowerBlock2D.h:89
std::tuple< std::array< double, 3 >, std::array< double, 3 > > getTowerBoundingBox(size_t index1D) const
Calculates the low and high corner of a tower given by its index.
Definition: ClusterTowerBlock2D.h:176
const std::array< size_t, 2 > & getTowersPerDim() const
Getter.
Definition: ClusterTowerBlock2D.h:352
double getInteractionLength() const
Getter.
Definition: ClusterTowerBlock2D.h:312
std::tuple< std::array< double, 2 >, std::array< size_t, 2 > > estimateOptimalGridSideLength(size_t numParticles, size_t clusterSize) const
Estimates the optimal 2D tower grid side length.
Definition: ClusterTowerBlock2D.h:140
ClusterTower< Particle_T > & getTowerByIndex2D(const size_t x, const size_t y)
Returns a reference to the tower for the given tower grid coordinates.
Definition: ClusterTowerBlock2D.h:271
int getNumTowersPerInteractionLength() const
Getter.
Definition: ClusterTowerBlock2D.h:317
ClusterTower< Particle_T > & getTowerAtPosition(const std::array< double, 3 > &pos)
Return a reference to the tower at a given position in the simulation coordinate system (e....
Definition: ClusterTowerBlock2D.h:260
This class represents one tower for clusters in the VerletClusterLists container.
Definition: ClusterTower.h:43
const std::vector< autopas::internal::Cluster< Particle_T > >::iterator & getFirstTailHaloCluster() const
Returns an iterator to the first particle after the owned clusters, that contains no owned particles ...
Definition: ClusterTower.h:297
const std::vector< autopas::internal::Cluster< Particle_T > >::iterator & getFirstOwnedCluster() const
Returns an iterator to the first cluster that contains at least one owned particle.
Definition: ClusterTower.h:280
unsigned long getNumActualParticles() const
Get the number of all particles saved in the tower without tailing dummies that are used to fill up c...
Definition: ClusterTower.h:260
auto & getClusters()
Returns a reference to the std::vector holding the clusters of this container.
Definition: ClusterTower.h:274
This class represents a cluster in the VerletClusterLists container.
Definition: Cluster.h:26
Helper class for rebuilding the VerletClusterLists container.
Definition: VerletClusterListsRebuilder.h:24
void updateNeighborLists()
Updates the neighbor lists for all clusters.
Definition: VerletClusterListsRebuilder.h:237
void calculateNeighborsBetweenTowers(internal::ClusterTower< Particle_T > &towerA, internal::ClusterTower< Particle_T > &towerB)
Calculates for all clusters in the given tower:
Definition: VerletClusterListsRebuilder.h:366
std::vector< std::vector< Particle_T > > collectAllParticlesFromTowers()
Takes all particles from all towers and returns them.
Definition: VerletClusterListsRebuilder.h:183
void iterateNeighborTowers(const int towerIndexX, const int towerIndexY, const int minNeighborIndexX, const int maxNeighborIndexX, const int minNeighborIndexY, const int maxNeighborIndexY, FunType function)
For all clusters in a tower, given by it's x/y indices, find all neighbors in towers that are given b...
Definition: VerletClusterListsRebuilder.h:279
int get1DInteractionCellIndexForTower(const int towerIndexX, const int towerIndexY)
Returns the index of a imagined interaction cell with side length equal the interaction length that c...
Definition: VerletClusterListsRebuilder.h:315
bool isForwardNeighbor(const int towerIndexX, const int towerIndexY, const int neighborIndexX, const int neighborIndexY)
Decides if a given neighbor tower is a forward neighbor to a given tower.
Definition: VerletClusterListsRebuilder.h:339
std::vector< std::vector< Particle_T > > collectOutOfBoundsParticlesFromTowers()
Collect all particles that are stored in the wrong towers.
Definition: VerletClusterListsRebuilder.h:199
void rebuildNeighborListsAndFillClusters()
Rebuilds the neighbor lists and fills Clusters with dummies as described in ClusterTower::setDummyVal...
Definition: VerletClusterListsRebuilder.h:153
size_t rebuildTowersAndClusters()
Rebuilds the towers, sorts the particles into them and creates the clusters with a reference to an un...
Definition: VerletClusterListsRebuilder.h:67
void clearNeighborListsAndMoveDummiesIntoClusters()
Clears previously saved neighbors from clusters and sets the 3D positions of the dummy particles to i...
Definition: VerletClusterListsRebuilder.h:169
bool getNewton3() const
Getter.
Definition: VerletClusterListsRebuilder.h:414
void sortParticlesIntoTowers(const std::vector< std::vector< Particle_T > > &particles2D)
Sorts all passed particles in the appropriate clusters.
Definition: VerletClusterListsRebuilder.h:217
VerletClusterListsRebuilder(ClusterTowerBlock2D< Particle_T > &towerBlock, std::vector< Particle_T > &particlesToAdd, NeighborListsBuffer_T &neighborListsBuffer, size_t clusterSize, double interactionLengthSqr, bool newton3)
Constructs the builder from the cluster list.
Definition: VerletClusterListsRebuilder.h:51
This namespace is used for implementation specifics.
Definition: CellFunctor.h:14
double boxDistanceSquared(const std::array< T, SIZE > &aMin, const std::array< T, SIZE > &aMax, const std::array< T, SIZE > &bMin, const std::array< T, SIZE > &bMax)
Calculate the squared minimum distance between two boxes, which are aligned to the Cartesian grid.
Definition: ArrayMath.h:663
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