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) {
152 return {boxSize2D, {3, 3}};
155 const double volume = boxSize[0] * boxSize[1] * boxSize[2];
158 const double density =
static_cast<double>(numParticles) / volume;
159 const auto optimalSideLength = std::cbrt(
static_cast<double>(clusterSize) / density);
161 const auto numTowersOwned(ceil(boxSize2D / optimalSideLength));
162 const auto towerSideLengthNew = boxSize2D / numTowersOwned;
164 const auto numTowers = numTowersOwned + (ceil(_interactionLength / towerSideLengthNew) * 2.);
167 return {towerSideLengthNew, static_cast_copy_array<size_t>(numTowers)};
178 [[nodiscard]] std::tuple<std::array<double, 3>, std::array<double, 3>>
getTowerBoundingBox(
size_t index1D)
const {
180 if (_towersPerDim[0] == 0) {
181 return {_boxMin, _boxMax};
193 const std::array<size_t, 2> &index2D)
const {
195 if (_towersPerDim[0] == 0) {
196 return {_boxMin, _boxMax};
199 const std::array<double, 3> towerBoxMin{
200 _boxMin[0] - _towerSideLength[0] * _numTowersPerInteractionLength +
201 _towerSideLength[0] *
static_cast<double>(index2D[0]),
202 _boxMin[1] - _towerSideLength[1] * _numTowersPerInteractionLength +
203 _towerSideLength[1] *
static_cast<double>(index2D[1]),
206 const std::array<double, 3> towerBoxMax{
207 towerBoxMin[0] + _towerSideLength[0],
208 towerBoxMin[1] + _towerSideLength[1],
211 return {towerBoxMin, towerBoxMax};
222 if (_towers.size() == 1) {
226 std::array<size_t, 2> towerIndex2D{};
228 for (
int dim = 0; dim < 2; dim++) {
229 const auto towerDimIndex =
230 static_cast<long int>(std::floor((pos[dim] - _boxMin[dim]) * _towerSideLengthReciprocal[dim])) +
231 _numTowersPerInteractionLength;
232 const auto towerDimIndexNonNegative =
static_cast<size_t>(std::max(towerDimIndex, 0l));
233 const auto towerDimIndexNonLargerValue = std::min(towerDimIndexNonNegative, _towersPerDim[dim] - 1);
234 towerIndex2D[dim] = towerDimIndexNonLargerValue;
237 if (pos[dim] >= _haloBoxMax[dim]) {
238 towerIndex2D[dim] = _towersPerDim[dim] - 1;
239 }
else if (pos[dim] < _haloBoxMin[dim]) {
240 towerIndex2D[dim] = 0;
284 [[nodiscard]]
size_t towerIndex2DTo1D(
const size_t x,
const size_t y)
const {
return x + y * _towersPerDim[0]; }
293 if (_towersPerDim[0] == 0) {
296 return {index % _towersPerDim[0], index / _towersPerDim[0]};
324 const std::array<double, 3> &
getBoxMin()
const {
return _boxMin; }
329 const std::array<double, 3> &
getBoxMax()
const {
return _boxMax; }
344 const std::vector<ClusterTower<Particle_T>> &
getTowers()
const {
return _towers; }
349 std::vector<ClusterTower<Particle_T>> &
getTowersRef() {
return _towers; }
373 if (index1d < _firstOwnedTowerIndex or index1d > _lastOwnedTowerIndex) {
377 bool isHaloTower =
false;
378 for (
size_t i = 0; i < index2D.size(); ++i) {
379 if (index2D[i] < _numTowersPerInteractionLength or
380 index2D[i] >= _towersPerDim[i] - _numTowersPerInteractionLength) {
385 return not isHaloTower;
392 size_t _firstOwnedTowerIndex{};
396 size_t _lastOwnedTowerIndex{};
400 double _interactionLength;
405 int _numTowersPerInteractionLength{};
410 std::array<double, 3> _boxMin;
415 std::array<double, 3> _boxMax;
420 std::array<double, 3> _haloBoxMin;
425 std::array<double, 3> _haloBoxMax;
430 std::vector<ClusterTower<Particle_T>> _towers;
435 std::array<size_t, 2> _towersPerDim{};
440 std::array<double, 2> _towerSideLength{0.};
445 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:252
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:284
const std::array< double, 3 > & getBoxMax() const
Getter.
Definition: ClusterTowerBlock2D.h:329
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:334
std::vector< ClusterTower< Particle_T > > & getTowersRef()
Getter for a mutable reference.
Definition: ClusterTowerBlock2D.h:349
const std::array< double, 3 > & getHaloBoxMax() const
Getter.
Definition: ClusterTowerBlock2D.h:339
size_t size() const
Return the number of towers.
Definition: ClusterTowerBlock2D.h:82
size_t getFirstOwnedTowerIndex() const
Getter.
Definition: ClusterTowerBlock2D.h:304
const std::array< double, 2 > & getTowerSideLength() const
Getter.
Definition: ClusterTowerBlock2D.h:359
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:324
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:371
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:220
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:192
size_t getLastOwnedTowerIndex() const
Getter.
Definition: ClusterTowerBlock2D.h:309
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:178
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:354
const std::vector< ClusterTower< Particle_T > > & getTowers() const
Getter.
Definition: ClusterTowerBlock2D.h:344
const std::array< double, 2 > & getTowerSideLengthReciprocal() const
Getter.
Definition: ClusterTowerBlock2D.h:364
bool cellCanContainHaloParticles(index_t index1d) const override
Checks if the cell with the one-dimensional index index1d can contain halo particles.
Definition: ClusterTowerBlock2D.h:366
double getInteractionLength() const
Getter.
Definition: ClusterTowerBlock2D.h:314
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:273
int getNumTowersPerInteractionLength() const
Getter.
Definition: ClusterTowerBlock2D.h:319
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:262
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:292
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