29template <
class ParticleCell>
44 CellBlock3D(std::vector<ParticleCell> &vec,
const std::array<double, 3> &bMin,
const std::array<double, 3> &bMax,
45 double interactionLength,
double cellSizeFactor = 1.0)
46 : _cells(&vec), _boxMin(bMin), _boxMax(bMax), _interactionLength(interactionLength) {
47 rebuild(vec, bMin, bMax, interactionLength, cellSizeFactor);
49 for (
int i = 0; i < 3; ++i) {
50 if (bMax[i] < bMin[i] + interactionLength) {
51 AutoPasLog(ERROR,
"Interaction length too large is {}, bmin {}, bmax {}", interactionLength, bMin[i], bMax[i]);
69 if (index1d < _firstOwnedCellIndex or index1d > _lastOwnedCellIndex) {
72 const auto index3d = oneToThreeD(index1d);
73 bool isHaloCell =
false;
74 for (
size_t i = 0; i < index3d.size(); ++i) {
75 if (index3d[i] < _cellsPerInteractionLength or
76 index3d[i] >= _cellsPerDimensionWithHalo[i] - _cellsPerInteractionLength) {
116 void rebuild(std::vector<ParticleCell> &vec,
const std::array<double, 3> &bMin,
const std::array<double, 3> &bMax,
117 double interactionLength,
double cellSizeFactor);
141 const std::array<index_t, 3> &index3d)
const;
164 return _cellsPerDimensionWithHalo;
172 [[nodiscard]]
bool checkInHalo(
const std::array<double, 3> &position)
const;
189 std::vector<ParticleCell *>
getNearbyHaloCells(
const std::array<double, 3> &position,
double allowedDistance)
const {
190 using namespace autopas::utils::ArrayMath::literals;
193 const auto index1D = threeToOneD(index3D);
199 std::vector<ParticleCell *> closeHaloCells;
203 const auto blockLength = highIndex3D - lowIndex3D;
204 const auto numInterestingCells = std::max(1ul, blockLength[0] * blockLength[1] * blockLength[2]);
205 closeHaloCells.reserve(numInterestingCells);
209 closeHaloCells.push_back(&
getCell(index3D));
212 auto currentIndex3D = lowIndex3D;
213 for (currentIndex3D[0] = lowIndex3D[0]; currentIndex3D[0] <= highIndex3D[0]; ++currentIndex3D[0]) {
214 for (currentIndex3D[1] = lowIndex3D[1]; currentIndex3D[1] <= highIndex3D[1]; ++currentIndex3D[1]) {
215 for (currentIndex3D[2] = lowIndex3D[2]; currentIndex3D[2] <= highIndex3D[2]; ++currentIndex3D[2]) {
217 if (currentIndex3D == index3D) {
221 const auto currentIndex1D = threeToOneD(currentIndex3D);
223 closeHaloCells.push_back(&
getCell(currentIndex3D));
229 return closeHaloCells;
236 [[nodiscard]]
const std::array<double, 3> &
getHaloBoxMin()
const {
return _haloBoxMin; }
242 [[nodiscard]]
const std::array<double, 3> &
getHaloBoxMax()
const {
return _haloBoxMax; }
254 [[nodiscard]]
const std::array<double, 3> &
getCellLength()
const {
return _cellLength; }
280 [[nodiscard]] std::array<index_t, 3> oneToThreeD(
index_t index1D)
const;
287 [[nodiscard]]
index_t threeToOneD(
const std::array<index_t, 3> &index3D)
const;
293 std::array<index_t, 3> _cellsPerDimensionWithHalo{};
294 index_t _firstOwnedCellIndex{};
296 std::vector<ParticleCell> *_cells;
298 std::array<double, 3> _boxMin, _boxMax;
299 std::array<double, 3> _haloBoxMin{}, _haloBoxMax{};
301 double _interactionLength{};
303 unsigned long _cellsPerInteractionLength{};
305 std::array<double, 3> _cellLength{};
311 std::array<double, 3> _cellLengthReciprocal{};
314template <
class ParticleCell>
316 const std::array<double, 3> &pos)
const {
317 return threeToOneD(get3DIndexOfPosition(pos));
320template <
class ParticleCell>
322 const std::array<double, 3> &pos)
const {
323 std::array<typename CellBlock3D<ParticleCell>::index_t, 3> cellIndex{};
325 for (
size_t dim = 0; dim < 3; dim++) {
327 const long int value = (
static_cast<long int>(std::floor((pos[dim] - _boxMin[dim]) * _cellLengthReciprocal[dim]))) +
328 _cellsPerInteractionLength;
329 const index_t nonNegativeValue =
static_cast<index_t>(std::max(value, 0l));
330 const index_t nonLargerValue = std::min(nonNegativeValue, _cellsPerDimensionWithHalo[dim] - 1);
331 cellIndex[dim] = nonLargerValue;
335 if (pos[dim] >= _boxMax[dim]) {
337 cellIndex[dim] = std::max(cellIndex[dim], _cellsPerDimensionWithHalo[dim] - _cellsPerInteractionLength);
338 }
else if (pos[dim] < _boxMin[dim] and cellIndex[dim] == _cellsPerInteractionLength) {
341 }
else if (pos[dim] < _boxMax[dim] and
342 cellIndex[dim] == _cellsPerDimensionWithHalo[dim] - _cellsPerInteractionLength) {
351template <
class ParticleCell>
353 const auto particlesPerCell = numParticles / _cells->size();
354 for (
auto &cell : *_cells) {
355 cell.reserve(particlesPerCell);
359template <
class ParticleCell>
361 const std::array<double, 3> &bMax,
double interactionLength,
362 double cellSizeFactor) {
363 using namespace autopas::utils::ArrayMath::literals;
368 _interactionLength = interactionLength;
370 if (cellSizeFactor >= 1.0) {
371 _cellsPerInteractionLength = 1;
373 _cellsPerInteractionLength = ceil(1.0 / cellSizeFactor);
377 for (
int d = 0; d < 3; ++d) {
378 const double boxLength = _boxMax[d] - _boxMin[d];
381 const auto cellsPerDim =
382 std::max(
static_cast<index_t>(std::floor(boxLength / (_interactionLength * cellSizeFactor))), 1ul);
384 _cellsPerDimensionWithHalo[d] = cellsPerDim + 2 * _cellsPerInteractionLength;
386 _cellLength[d] = boxLength /
static_cast<double>(cellsPerDim);
388 _cellLengthReciprocal[d] =
static_cast<double>(cellsPerDim) / boxLength;
390 _haloBoxMin[d] = _boxMin[d] - _cellsPerInteractionLength * _cellLength[d];
391 _haloBoxMax[d] = _boxMax[d] + _cellsPerInteractionLength * _cellLength[d];
393 numCells *= _cellsPerDimensionWithHalo[d];
398 AutoPasLog(TRACE,
"Interaction Length : {}", interactionLength);
399 AutoPasLog(TRACE,
"Cell Size Factor : {}", cellSizeFactor);
401 _firstOwnedCellIndex = _cellsPerDimensionWithHalo[0] * _cellsPerDimensionWithHalo[1] * _cellsPerInteractionLength +
402 _cellsPerDimensionWithHalo[0] * _cellsPerInteractionLength + _cellsPerInteractionLength;
403 _lastOwnedCellIndex = numCells - 1 - _firstOwnedCellIndex;
406 _cells->resize(numCells);
408 for (
auto &cell : *_cells) {
409 cell.setCellLength(_cellLength);
413 for (
int i = 0; i < numCells; i++) {
414 const bool canHaveHalos = cellCanContainHaloParticles(i);
415 const bool canHaveOwned = cellCanContainOwnedParticles(i);
416 if (canHaveHalos and canHaveOwned) {
418 }
else if (canHaveHalos) {
420 }
else if (canHaveOwned) {
428template <
class ParticleCell>
430 return _cells->size();
433template <
class ParticleCell>
435 return _firstOwnedCellIndex;
438template <
class ParticleCell>
440 return _lastOwnedCellIndex;
443template <
class ParticleCell>
446 return this->getCellBoundingBox(this->oneToThreeD(index1d));
449template <
class ParticleCell>
451 const std::array<index_t, 3> &index3d)
const {
452 std::array<double, 3> boxmin{}, boxmax{};
453 for (
int d = 0; d < 3; d++) {
455 boxmin[d] = index3d[d] * this->_cellLength[d] + _haloBoxMin[d];
458 if (index3d[d] == 0) {
459 boxmin[d] = _haloBoxMin[d];
460 }
else if (index3d[d] == _cellsPerInteractionLength) {
462 boxmin[d] = _boxMin[d];
465 boxmax[d] = boxmin[d] + this->_cellLength[d];
469 if (index3d[d] == this->_cellsPerDimensionWithHalo[d] - _cellsPerInteractionLength - 1) {
470 boxmax[d] = _boxMax[d];
471 }
else if (index3d[d] == this->_cellsPerDimensionWithHalo[d] - 1) {
472 boxmin[d] = _haloBoxMax[d] - this->_cellLength[d];
473 boxmax[d] = _haloBoxMax[d];
476 return {boxmin, boxmax};
479template <
class ParticleCell>
481 auto ind = get1DIndexOfPosition(pos);
485template <
class ParticleCell>
487 return (*_cells)[index1d];
490template <
class ParticleCell>
492 return (*_cells)[threeToOneD(index3d)];
495template <
class ParticleCell>
497 index_t index1D)
const {
501template <
class ParticleCell>
503 const std::array<index_t, 3> &index3D)
const {
507template <
class ParticleCell>
513template <
class ParticleCell>
515 std::vector<index_t> haloSlices(2 * _cellsPerInteractionLength);
516 auto mid = haloSlices.begin() + _cellsPerInteractionLength;
517 std::iota(haloSlices.begin(), mid, 0);
520 std::iota(mid, haloSlices.end(), _cellsPerDimensionWithHalo[0] - _cellsPerInteractionLength);
522 for (
index_t j = 0; j < _cellsPerDimensionWithHalo[1]; j++) {
523 for (
index_t k = 0; k < _cellsPerDimensionWithHalo[2]; k++) {
524 index_t index = threeToOneD({i, j, k});
525 (*_cells)[index].clear();
530 std::iota(mid, haloSlices.end(), _cellsPerDimensionWithHalo[1] - _cellsPerInteractionLength);
531 for (
index_t i = 1; i < _cellsPerDimensionWithHalo[0] - 1; i++) {
533 for (
index_t k = 0; k < _cellsPerDimensionWithHalo[2]; k++) {
534 index_t index = threeToOneD({i, j, k});
535 (*_cells)[index].clear();
540 std::iota(mid, haloSlices.end(), _cellsPerDimensionWithHalo[2] - _cellsPerInteractionLength);
541 for (
index_t i = 1; i < _cellsPerDimensionWithHalo[0] - 1; i++) {
542 for (
index_t j = 1; j < _cellsPerDimensionWithHalo[1] - 1; j++) {
544 index_t index = threeToOneD({i, j, k});
545 (*_cells)[index].clear();
#define AutoPasLog(lvl, fmt,...)
Macro for logging providing common meta information without filename.
Definition: Logger.h:24
Class for Cells of Particles.
Definition: ParticleCell.h:51
Class that manages a block of ParticleCells.
Definition: CellBlock3D.h:30
const std::array< double, 3 > & getHaloBoxMin() const
Get the lower corner of the halo region.
Definition: CellBlock3D.h:236
unsigned long getCellsPerInteractionLength() const
Get the number of cells per interaction length.
Definition: CellBlock3D.h:248
ParticleCell & getContainingCell(const std::array< double, 3 > &pos) const
Get the containing cell of a specified position.
Definition: CellBlock3D.h:480
const std::array< double, 3 > & getHaloBoxMax() const
Get the upper corner of the halo region.
Definition: CellBlock3D.h:242
const std::array< index_t, 3 > & getCellsPerDimensionWithHalo() const
Get the dimension of the cell block including the halo boxes.
Definition: CellBlock3D.h:163
bool cellCanContainHaloParticles(index_t index1d) const override
Checks if the cell with the one-dimensional index index1d can contain halo particles.
Definition: CellBlock3D.h:68
index_t getFirstOwnedCellIndex() const
1D id of the first cell that is not in the halo.
Definition: CellBlock3D.h:434
std::vector< ParticleCell * > getNearbyHaloCells(const std::array< double, 3 > &position, double allowedDistance) const
Get the halo cells around a given point.
Definition: CellBlock3D.h:189
index_t get1DIndexOfPosition(const std::array< double, 3 > &pos) const
Get the 1d index of the cell block for a given position.
Definition: CellBlock3D.h:315
bool cellCanContainOwnedParticles(index_t index1d) const override
Checks if the cell with the one-dimensional index index1d can contain owned particles.
Definition: CellBlock3D.h:84
index_t getNumCells() const
Get the number of cells in this block.
Definition: CellBlock3D.h:429
void reserve(size_t numParticles)
Reserve memory for a given number of particles.
Definition: CellBlock3D.h:352
void rebuild(std::vector< ParticleCell > &vec, const std::array< double, 3 > &bMin, const std::array< double, 3 > &bMax, double interactionLength, double cellSizeFactor)
Rebuild the cell block.
Definition: CellBlock3D.h:360
bool checkInHalo(const std::array< double, 3 > &position) const
Checks whether a given position is inside the halo region of the managed cell block.
Definition: CellBlock3D.h:508
void clearHaloCells()
Deletes all particles in the halo cells of the managed cell block.
Definition: CellBlock3D.h:514
ParticleCell & getCell(index_t index1d) const
get the ParticleCell of a specified 1d index.
Definition: CellBlock3D.h:486
CellBlock3D & operator=(const CellBlock3D)=delete
Deleted assignment operator.
CellBlock3D(const CellBlock3D &)=delete
Deleted copy constructor.
CellBlock3D(std::vector< ParticleCell > &vec, const std::array< double, 3 > &bMin, const std::array< double, 3 > &bMax, double interactionLength, double cellSizeFactor=1.0)
Constructor of CellBlock3D.
Definition: CellBlock3D.h:44
std::size_t index_t
The index type to access the particle cells.
Definition: CellBlock3D.h:35
ParticleCell & getCell(const std::array< index_t, 3 > &index3d) const
Get the ParticleCell of a specified 3d index.
Definition: CellBlock3D.h:491
std::pair< std::array< double, 3 >, std::array< double, 3 > > getCellBoundingBox(index_t index1d) const
Get the lower and upper corner of the cell at the 1d index index1d.
Definition: CellBlock3D.h:444
const std::array< double, 3 > & getCellLength() const
Get the cell lengths.
Definition: CellBlock3D.h:254
index_t getLastOwnedCellIndex() const
1D id of the last cell before there are only halo cells left.
Definition: CellBlock3D.h:439
std::pair< std::array< double, 3 >, std::array< double, 3 > > getCellBoundingBox(const std::array< index_t, 3 > &index3d) const
Get the lower and upper corner of the cell at the 3d index index3d.
Definition: CellBlock3D.h:450
std::array< index_t, 3 > get3DIndexOfPosition(const std::array< double, 3 > &pos) const
Get the 3d index of the cell block for a given position.
Definition: CellBlock3D.h:321
Interface class to handle cell borders and cell types of cells.
Definition: CellBorderAndFlagManager.h:17
static void exception(const Exception e)
Handle an exception derived by std::exception.
Definition: ExceptionHandler.h:63
This namespace is used for implementation specifics.
Definition: CellFunctor.h:14
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
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
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 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
@ dummy
Dummy or deleted state, a particle with this state is not an actual particle!
@ halo
Halo state, a particle with this state is an actual particle, but not owned by the current AutoPas ob...
@ owned
Owned state, a particle with this state is an actual particle and owned by the current AutoPas object...