24template <
class Particle_T>
37 double interactionLength)
38 : _interactionLength(interactionLength),
41 _haloBoxMin{utils::ArrayMath::subScalar(boxMin, interactionLength)},
42 _haloBoxMax{utils::ArrayMath::addScalar(boxMax, interactionLength)} {}
47 typename std::vector<ClusterTower<Particle_T>>::iterator
begin() {
return _towers.begin(); }
52 typename std::vector<ClusterTower<Particle_T>>::const_iterator
begin()
const {
return _towers.begin(); }
57 typename std::vector<ClusterTower<Particle_T>>::iterator
end() {
return _towers.end(); }
62 typename std::vector<ClusterTower<Particle_T>>::const_iterator
end()
const {
return _towers.end(); }
82 size_t size()
const {
return _towers.size(); }
89 void resize(
const std::array<double, 2> &towerSideLength,
const std::array<size_t, 2> &towersPerDim) {
90 using namespace autopas::utils::ArrayMath::literals;
93 _towerSideLength = towerSideLength;
94 _towerSideLengthReciprocal = 1. / towerSideLength;
95 const auto numTowersPerInteractionLength2D =
96 static_cast_copy_array<int>(ceil(_interactionLength / _towerSideLength));
98 if (numTowersPerInteractionLength2D[0] != numTowersPerInteractionLength2D[1]) {
100 "Number of towers per interaction length differs in X vs Y direction! "
101 "The container is built on the assumption that they are the same, "
102 "so from here on the behavior might be undefined. Values: {}",
105 _numTowersPerInteractionLength =
106 *std::max_element(numTowersPerInteractionLength2D.begin(), numTowersPerInteractionLength2D.end());
107 _towersPerDim = towersPerDim;
108 _towers.resize(_towersPerDim[0] * _towersPerDim[1]);
111 _firstOwnedTowerIndex =
towerIndex2DTo1D(_numTowersPerInteractionLength, _numTowersPerInteractionLength);
112 _lastOwnedTowerIndex =
towerIndex2DTo1D(_towersPerDim[0] - _numTowersPerInteractionLength,
113 _towersPerDim[1] - _numTowersPerInteractionLength);
120 bool empty()
const {
return _towers.empty(); }
126 void addTower(
size_t clusterSize) { _towers.emplace_back(clusterSize); }
141 size_t numParticles,
size_t clusterSize)
const {
142 using namespace autopas::utils::ArrayMath::literals;
147 const std::array<double, 3> boxSize = _boxMax - _boxMin;
148 const std::array<double, 2> boxSize2D{boxSize[0], boxSize[1]};
149 if (numParticles == 0) {
150 return {boxSize2D, {1, 1}};
153 const double volume = boxSize[0] * boxSize[1] * boxSize[2];
156 const double density =
static_cast<double>(numParticles) / volume;
157 const auto optimalSideLength = std::cbrt(
static_cast<double>(clusterSize) / density);
159 const auto numTowersOwned(ceil(boxSize2D / optimalSideLength));
160 const auto towerSideLengthNew = boxSize2D / numTowersOwned;
162 const auto numTowers = numTowersOwned + (ceil(_interactionLength / towerSideLengthNew) * 2.);
165 return {towerSideLengthNew, static_cast_copy_array<size_t>(numTowers)};
176 [[nodiscard]] std::tuple<std::array<double, 3>, std::array<double, 3>>
getTowerBoundingBox(
size_t index1D)
const {
178 if (_towersPerDim[0] == 0) {
179 return {_boxMin, _boxMax};
191 const std::array<size_t, 2> &index2D)
const {
193 if (_towersPerDim[0] == 0) {
194 return {_boxMin, _boxMax};
197 const std::array<double, 3> towerBoxMin{
198 _boxMin[0] - _towerSideLength[0] * _numTowersPerInteractionLength +
199 _towerSideLength[0] *
static_cast<double>(index2D[0]),
200 _boxMin[1] - _towerSideLength[1] * _numTowersPerInteractionLength +
201 _towerSideLength[1] *
static_cast<double>(index2D[1]),
204 const std::array<double, 3> towerBoxMax{
205 towerBoxMin[0] + _towerSideLength[0],
206 towerBoxMin[1] + _towerSideLength[1],
209 return {towerBoxMin, towerBoxMax};
220 if (_towers.size() == 1) {
224 std::array<size_t, 2> towerIndex2D{};
226 for (
int dim = 0; dim < 2; dim++) {
227 const auto towerDimIndex =
228 static_cast<long int>(std::floor((pos[dim] - _boxMin[dim]) * _towerSideLengthReciprocal[dim])) +
229 _numTowersPerInteractionLength;
230 const auto towerDimIndexNonNegative =
static_cast<size_t>(std::max(towerDimIndex, 0l));
231 const auto towerDimIndexNonLargerValue = std::min(towerDimIndexNonNegative, _towersPerDim[dim] - 1);
232 towerIndex2D[dim] = towerDimIndexNonLargerValue;
235 if (pos[dim] >= _haloBoxMax[dim]) {
236 towerIndex2D[dim] = _towersPerDim[dim] - 1;
237 }
else if (pos[dim] < _haloBoxMin[dim]) {
238 towerIndex2D[dim] = 0;
282 [[nodiscard]]
size_t towerIndex2DTo1D(
const size_t x,
const size_t y)
const {
return x + y * _towersPerDim[0]; }
291 if (_towersPerDim[0] == 0) {
294 return {index % _towersPerDim[0], index / _towersPerDim[0]};
322 const std::array<double, 3> &
getBoxMin()
const {
return _boxMin; }
327 const std::array<double, 3> &
getBoxMax()
const {
return _boxMax; }
342 const std::vector<ClusterTower<Particle_T>> &
getTowers()
const {
return _towers; }
347 std::vector<ClusterTower<Particle_T>> &
getTowersRef() {
return _towers; }
371 if (index1d < _firstOwnedTowerIndex or index1d > _lastOwnedTowerIndex) {
375 bool isHaloTower =
false;
376 for (
size_t i = 0; i < index2D.size(); ++i) {
377 if (index2D[i] < _numTowersPerInteractionLength or
378 index2D[i] >= _towersPerDim[i] - _numTowersPerInteractionLength) {
383 return not isHaloTower;
390 size_t _firstOwnedTowerIndex{};
394 size_t _lastOwnedTowerIndex{};
398 double _interactionLength;
403 int _numTowersPerInteractionLength{};
408 std::array<double, 3> _boxMin;
413 std::array<double, 3> _boxMax;
418 std::array<double, 3> _haloBoxMin;
423 std::array<double, 3> _haloBoxMax;
428 std::vector<ClusterTower<Particle_T>> _towers;
433 std::array<size_t, 2> _towersPerDim{};
438 std::array<double, 2> _towerSideLength{0.};
443 std::array<double, 2> _towerSideLengthReciprocal{0.};
#define AutoPasLog(lvl, fmt,...)
Macro for logging providing common meta information without filename.
Definition: Logger.h:24
Interface class to handle cell borders and cell types of cells.
Definition: CellBorderAndFlagManager.h:17
std::size_t index_t
The index type to access the particle cells.
Definition: CellBorderAndFlagManager.h:22
Class to manage the grid of towers for the Verlet Cluster Lists container.
Definition: ClusterTowerBlock2D.h:25
std::vector< ClusterTower< Particle_T > >::const_iterator end() const
End iterator over towers.
Definition: ClusterTowerBlock2D.h:62
size_t getTowerIndex1DAtPosition(const std::array< double, 3 > &pos) const
Return the 1D index of the tower at a given position.
Definition: ClusterTowerBlock2D.h:250
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 > & getBoxMax() const
Getter.
Definition: ClusterTowerBlock2D.h:327
bool empty() const
Indicator if the block contains any towers.
Definition: ClusterTowerBlock2D.h:120
const std::array< double, 3 > & getHaloBoxMin() const
Getter.
Definition: ClusterTowerBlock2D.h:332
std::vector< ClusterTower< Particle_T > > & getTowersRef()
Getter for a mutable reference.
Definition: ClusterTowerBlock2D.h:347
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
size_t getFirstOwnedTowerIndex() const
Getter.
Definition: ClusterTowerBlock2D.h:302
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
const std::array< double, 3 > & getBoxMin() const
Getter.
Definition: ClusterTowerBlock2D.h:322
std::vector< ClusterTower< Particle_T > >::iterator end()
End iterator over towers.
Definition: ClusterTowerBlock2D.h:57
bool cellCanContainOwnedParticles(index_t index1d) const override
Checks if the cell with the one-dimensional index index1d can contain owned particles.
Definition: ClusterTowerBlock2D.h:369
std::vector< ClusterTower< Particle_T > >::const_iterator begin() const
Start iterator over towers.
Definition: ClusterTowerBlock2D.h:52
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::array< size_t, 2 > getTowerIndex2DAtPosition(const std::array< double, 3 > &pos) const
Returns the 2D index of the tower in the tower grid the given 3D coordinates are in.
Definition: ClusterTowerBlock2D.h:218
const ClusterTower< Particle_T > & operator[](size_t i) const
Access operator for towers.
Definition: ClusterTowerBlock2D.h:76
std::tuple< std::array< double, 3 >, std::array< double, 3 > > getTowerBoundingBox(const std::array< size_t, 2 > &index2D) const
Calculates the low and high corner of a tower given by its 2D grid index.
Definition: ClusterTowerBlock2D.h:190
size_t getLastOwnedTowerIndex() const
Getter.
Definition: ClusterTowerBlock2D.h:307
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
void addTower(size_t clusterSize)
Construct a new tower at the end of the storage.
Definition: ClusterTowerBlock2D.h:126
const std::array< size_t, 2 > & getTowersPerDim() const
Getter.
Definition: ClusterTowerBlock2D.h:352
const std::vector< ClusterTower< Particle_T > > & getTowers() const
Getter.
Definition: ClusterTowerBlock2D.h:342
const std::array< double, 2 > & getTowerSideLengthReciprocal() const
Getter.
Definition: ClusterTowerBlock2D.h:362
bool cellCanContainHaloParticles(index_t index1d) const override
Checks if the cell with the one-dimensional index index1d can contain halo particles.
Definition: ClusterTowerBlock2D.h:364
double getInteractionLength() const
Getter.
Definition: ClusterTowerBlock2D.h:312
ClusterTowerBlock2D(const std::array< double, 3 > &boxMin, const std::array< double, 3 > &boxMax, double interactionLength)
Constructor.
Definition: ClusterTowerBlock2D.h:36
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 > & operator[](size_t i)
Access operator for towers.
Definition: ClusterTowerBlock2D.h:69
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
std::array< size_t, 2 > towerIndex1DTo2D(size_t index) const
Returns the 2D index for the given 1D index of a tower.
Definition: ClusterTowerBlock2D.h:290
This class represents one tower for clusters in the VerletClusterLists container.
Definition: ClusterTower.h:43
This namespace is used for implementation specifics.
Definition: CellFunctor.h:14
constexpr std::array< T, SIZE > ceil(const std::array< T, SIZE > &a)
For each element in a, computes the smallest integer value not less than the element.
Definition: ArrayMath.h:316
constexpr std::array< output_t, SIZE > static_cast_copy_array(const std::array< input_t, SIZE > &a)
Creates a new array by performing an element-wise static_cast<>.
Definition: ArrayUtils.h:81
void to_string(std::ostream &os, const Container &container, const std::string &delimiter, const std::array< std::string, 2 > &surround, Fun elemToString)
Generates a string representation of a container which fulfills the Container requirement (provide cb...
Definition: ArrayUtils.h:102