17 #include <range/v3/range/conversion.hpp> 18 #include <spdlog/spdlog.h> 60 template <
typename TGr
idType>
struct AbstractGrid :
private TGridType
62 using GridType = TGridType;
68 virtual CellCoord coordinates(CellIndex index)
const = 0;
69 virtual CellIndex index(
const CellCoord& coordinates)
const = 0;
70 virtual CellCoord coordinatesAt(
const Point& position)
const = 0;
71 virtual CellIndex indexAt(
const Point& position)
const = 0;
72 virtual bool isCell(
const CellCoord& coordinates)
const = 0;
73 virtual bool isCellAt(
const Point& point)
const = 0;
74 virtual CellIndex size()
const = 0;
80 using GridType = TGridType;
81 using typename TGridType::CellCoord;
83 virtual bool isNeighborCell(
const CellCoord& coordinates,
const CellCoord& offset)
const = 0;
98 using GridType =
typename AbstractGrid<TGridType>::GridType;
114 assert(index < size());
115 return cell_index_to_coordinates.unaryExpr([index](
const auto modulo) {
116 return index % modulo;
117 }) / cell_coordinates_to_index;
125 CellIndex
index(
const CellCoord& coordinates)
const override 127 assert(isCell(coordinates));
128 return (coordinates * cell_coordinates_to_index).sum();
141 assert(isCellAt(position));
142 return (position / cell).floor().template cast<CellIndex>();
152 return index(coordinatesAt(position));
163 bool isCell(
const CellCoord& coordinates)
const override 165 return (coordinates < this->getCellListEnd()).all() &&
166 (coordinates >= CellCoord::Zero()).all();
179 return (point < this->getBox()).all() && (point >= Point::Zero()).all();
185 CellIndex
size()
const override {
return cell_list_end.prod(); };
192 : minimal_cell_dimension(minimal_cell_dimension)
198 const CellCoord& getCellListEnd()
const {
return cell_list_end; }
200 const Point& getBox()
const {
return box; }
202 const Point& getCell()
const {
return cell; }
205 CellCoord cell_list_end;
206 SpaceAxis minimal_cell_dimension;
213 CellCoord cell_coordinates_to_index;
216 CellCoord cell_index_to_coordinates;
223 void updateCellGrid(
const Point& new_box)
226 cell_list_end = (box / box.min(minimal_cell_dimension)).floor().template cast<CellIndex>();
227 cell = box / cell_list_end.template cast<SpaceAxis>();
230 cell_coordinates_to_index[0] = 1;
231 cell_index_to_coordinates[0] = cell_list_end[0];
232 for (
int i = 1; i < TGridType::Dimension; ++i) {
233 cell_coordinates_to_index[i] = cell_list_end[i - 1] * cell_coordinates_to_index[i - 1];
234 cell_index_to_coordinates[i] = cell_list_end[i] * cell_index_to_coordinates[i - 1];
244 template <
typename TGr
idType>
250 using typename AbstractNeighborGrid<TGridType>::GridType;
264 return Base::isCell(coordinates + offset);
282 template <
typename TGr
idType>
289 using GridType =
typename AbstractNeighborGrid<TGridType>::GridType;
303 CellCoord
coordinates(
const CellIndex index)
const override {
return Base::coordinates(index); }
313 CellIndex
index(
const CellCoord& coordinates)
const override 315 auto pbc_coordinates = coordinates;
316 auto& boundary_coords = this->getCellListEnd();
317 for (
auto i = 0; i < pbc_coordinates.size(); ++i) {
318 if (coordinates[i] < 0) {
319 pbc_coordinates[i] +=
320 boundary_coords[i] * (std::abs(coordinates[i]) / boundary_coords[i] + 1);
322 else if (coordinates[i] >= boundary_coords[i]) {
323 pbc_coordinates[i] -= boundary_coords[i] * (coordinates[i] / boundary_coords[i]);
326 return Base::index(pbc_coordinates);
339 assert(isCellAt(position));
340 return (position / this->getCell()).floor().template cast<CellIndex>();
350 return this->index(this->coordinatesAt(position));
361 bool isCell(
const CellCoord&)
const override {
return true; }
386 const CellCoord& offset)
const override 388 return (offset >= neighbours_cell_offset_min).all() &&
389 (offset <= neighbours_cell_offset_max).all();
393 :
Base(box, cell_dimension)
399 CellCoord neighbours_cell_offset_min;
400 CellCoord neighbours_cell_offset_max;
409 void updateCellGrid()
411 const auto cell_list_middle = (this->getCellListEnd() - 1).
template cast<double>() * 0.5;
412 neighbours_cell_offset_min = -cell_list_middle.floor().template cast<CellIndex>();
413 neighbours_cell_offset_max = cell_list_middle.ceil().template cast<CellIndex>();
421 template <
bool PBC,
class TGr
idType>
422 using GridBoundary =
typename std::conditional<PBC, PeriodicBoundaryGrid<TGridType>,
428 template <
bool PBC>
using Grid3DBoundary = GridBoundary<PBC, Grid3DType>;
429 using Grid3DFixed = Grid3DBoundary<false>;
430 using Grid3DPeriodic = Grid3DBoundary<true>;
449 template <
typename TMember,
typename TIndex>
459 assert(index >= 0 && index < indexEnd());
460 return container[index];
465 assert(index >= 0 && index < indexEnd());
466 return container[index];
481 std::vector<Index> indices;
482 indices.reserve(std::distance(container.begin(), container.end()));
483 auto iterator = container.begin();
484 while ((iterator = std::find_if(iterator, container.end(), [](
const auto& members) {
485 return !members.empty();
486 })) != container.end()) {
487 indices.push_back(std::distance(iterator, container.begin()));
488 std::advance(iterator, 1);
495 if (size >= max_container_size) {
496 faunus_logger->error(
"Size of the cell list container is too large! \n" 497 "Try using a sparse version (i.e. dense: false)");
498 throw std::runtime_error(
"cell list `container` size too large");
500 container.resize(size);
504 Index indexEnd()
const {
return container.size(); }
507 const std::size_t max_container_size = 1000000000;
509 std::vector<Members> container;
520 template <
typename TMember,
typename TIndex>
530 assert(index >= 0 && index < indexEnd());
532 return container.at(index);
534 catch (std::out_of_range& e) {
541 assert(index >= 0 && index < indexEnd());
543 return container.at(index);
545 catch (std::out_of_range& e) {
546 [[maybe_unused]]
auto [iterator, flag] = container.emplace(index,
Members{});
547 return iterator->second;
562 std::vector<Index> indices;
563 indices.reserve(std::distance(container.begin(), container.end()));
564 std::transform(container.begin(), container.end(), back_inserter(indices),
565 [](
const auto& pair) {
return pair.first; });
575 Index indexEnd()
const {
return index_end; }
580 std::unordered_map<Index, Members> container;
589 template <
class TContainer>
class Container :
public TContainer
592 using ContainerType = ContainerTypeOf<TContainer>;
593 using Member = MemberOf<ContainerType>;
594 using Index = IndexOf<ContainerType>;
596 void insert(
const Member& member,
const Index index_new)
598 assert(index_new < this->indexEnd());
599 this->
get(index_new).push_back(member);
602 void erase(
const Member& member,
const Index index_old)
604 assert(index_old < this->indexEnd());
605 auto& members = this->
get(index_old);
607 auto remove_it = std::remove(members.begin(), members.end(), member);
608 members.erase(remove_it, members.end());
612 void move(
const Member& member,
const Index index_old,
const Index index_new)
614 erase(member, index_old);
615 insert(member, index_new);
618 using TContainer::TContainer;
631 template <
class TContainer,
class TGr
id>
634 protected TContainer,
655 return this->
get(this->index(cell_coordinates));
667 if (this->isNeighborCell(cell_coordinates, cell_offset)) {
668 return getMembers(cell_coordinates + cell_offset);
680 const auto indices = this->indices();
681 return std::views::all(indices) |
682 std::views::transform([
this](
auto index) {
return this->coordinates(index); }) |
715 CellListBase(
const typename TGrid::Point& box,
const typename TGrid::SpaceAxis cell_dimension)
716 :
Grid(box, cell_dimension)
726 using Container::erase;
727 using Container::get;
728 using Container::getEmpty;
729 using Container::insert;
730 using Container::move;
736 template <
typename TMember,
class TGrid,
737 template <
typename,
typename>
class TCellList =
CellListBase,
740 TCellList<Container::Container<TContainer<TMember, Grid::IndexOf<TGrid>>>, TGrid>;
750 template <
class TContainer,
class TGr
id>
774 return getSorted(this->index(cell_coordinates));
786 if (this->isNeighborCell(cell_coordinates, cell_offset)) {
787 return getSortedMembers(cell_coordinates + cell_offset);
790 return this->getEmpty();
801 is_sorted.resize(this->size(),
false);
810 const typename GridOf<TBase>::SpaceAxis cell_dimension)
811 :
TBase(box, cell_dimension)
813 is_sorted.resize(this->size(),
false);
819 TBase::insert(member, new_cell_index);
820 if (is_sorted[new_cell_index]) {
821 is_sorted[new_cell_index] =
false;
827 TBase::remove(member, old_cell_index);
828 if (is_sorted[old_cell_index]) {
829 is_sorted[old_cell_index] =
false;
840 auto& members = this->
get(cell_index);
841 if (!is_sorted[cell_index]) {
842 std::sort(members.begin(), members.end());
843 is_sorted[cell_index] =
true;
845 assert(std::is_sorted(members.begin(), members.end()));
851 std::vector<bool> is_sorted;
863 using typename TBase::AbstractCellList;
864 using typename AbstractCellList::CellCoord;
865 using typename AbstractCellList::CellIndex;
866 using typename AbstractCellList::Member;
867 using typename TBase::Container;
868 using typename TBase::Grid;
870 void addMember(
const Member& member,
const CellCoord& new_cell_coordinates)
872 this->insert(member, this->index(new_cell_coordinates));
875 void removeMember(
const Member& member)
877 const auto old_cell_index = member2cell.at(member);
878 this->erase(member, old_cell_index);
879 member2cell.erase(member);
882 void updateMember(
const Member& member,
const CellCoord& new_cell_coordinates)
884 this->update(member, this->index(new_cell_coordinates));
891 bool containsMember(
const Member& member) {
return member2cell.count(member) != 0; }
902 for (
const auto& member : members) {
903 insert(member, source.member2cell[member]);
910 void insert(
const Member& member,
const CellIndex& new_cell_index)
912 assert(member2cell.count(member) == 0);
913 TBase::insert(member, new_cell_index);
914 member2cell.insert({member, new_cell_index});
917 void update(
const Member& member,
const CellIndex& new_cell_index)
919 const auto old_cell_index = member2cell.at(member);
920 if (new_cell_index != old_cell_index) {
921 TBase::move(member, old_cell_index, new_cell_index);
922 member2cell.at(member) = new_cell_index;
928 std::map<Member, CellIndex> member2cell;
944 using typename AbstractCellList::Member;
945 using typename AbstractCellList::GridType::Point;
949 const auto new_cell_index = this->indexAt(new_position);
950 this->insert(member, new_cell_index);
953 void updateMemberAt(
const Member& member,
const Point& new_position)
955 const auto new_cell_index = this->indexAt(new_position);
956 this->update(member, new_cell_index);
971 template <
typename TCellListMinuend,
typename TCellListSubtrahend>
974 GridTypeOf<GridOf<TCellListMinuend>>>
976 using CellListMinuend = TCellListMinuend;
977 using CellListSubtrahend = TCellListSubtrahend;
980 using AbstractCellList =
typename CellListMinuend::AbstractCellList;
981 using Grid =
typename CellListMinuend::Grid;
982 using Container =
typename CellListMinuend::Container;
983 using typename AbstractCellList::CellCoord;
984 using typename AbstractCellList::CellIndex;
985 using typename AbstractCellList::Member;
986 using typename AbstractCellList::Members;
990 const auto subtrahend_cell = subtrahend->getSortedMembers(cell_coordinates);
991 if (std::size(subtrahend_cell) == 0) {
993 return minuend->getSortedMembers(cell_coordinates);
996 const auto cell_index = minuend->getGrid().index(cell_coordinates);
997 auto difference_cell_it = difference_cache.find(cell_index);
998 if (difference_cell_it == difference_cache.end()) {
1000 auto minuend_cell = minuend->getSortedMembers(cell_coordinates);
1001 std::tie(difference_cell_it, std::ignore) =
1002 difference_cache.emplace(cell_index,
Members{});
1003 std::set_difference(minuend_cell.begin(), minuend_cell.end(),
1004 subtrahend_cell.begin(), subtrahend_cell.end(),
1005 std::back_inserter(difference_cell_it->second));
1007 return difference_cell_it->second;
1013 if (subtrahend->getMembers(cell_coordinates).empty()) {
1015 return minuend->getMembers(cell_coordinates);
1018 return getSortedMembers(cell_coordinates);
1025 if (minuend->getGrid().isNeighborCell(cell_coordinates, cell_offset)) {
1027 return getSortedMembers(cell_coordinates + cell_offset);
1030 return minuend->getNeighborMembers(cell_coordinates, cell_offset);
1037 if (minuend->getGrid().isNeighborCell(cell_coordinates, cell_offset)) {
1038 return getMembers(cell_coordinates + cell_offset);
1041 return minuend->getNeighborMembers(cell_coordinates, cell_offset);
1047 auto& getGrid() {
return minuend->getGrid(); }
1049 std::vector<CellCoord>
getCells()
const override {
return minuend->getCells(); }
1052 std::shared_ptr<TCellListSubtrahend> subtrahend)
1054 , subtrahend(subtrahend)
1059 std::shared_ptr<CellListMinuend> minuend;
1060 std::shared_ptr<CellListSubtrahend> subtrahend;
1061 std::map<CellIndex, Members> difference_cache;
CellIndex index(const CellCoord &coordinates) const override
Compute the cell index from the cell coordinates.
Definition: celllistimpl.h:125
Container based on a map suitable for system with a non-uniform or low member density.
Definition: celllistimpl.h:521
Eigen::Vector3d Point
3D vector used for positions, velocities, forces etc.
Definition: coordinates.h:7
std::vector< CellCoord > getCells() const override
Definition: celllistimpl.h:678
const Members & getSorted(const CellIndex cell_index)
Get members in a sorted order.
Definition: celllistimpl.h:838
A mixing returning members in a cell in sorted order, e.g., for lookup or filtering.
Definition: celllistimpl.h:751
CellCoord coordinates(const CellIndex index) const override
Compute the cell coordinates from the cell index.
Definition: celllistimpl.h:112
TIndex Index
the cell index (key) type
Definition: celllist.h:96
const Members & getMembers(const CellCoord &cell_coordinates) override
Gets cell members at given cell coordinates.
Definition: celllistimpl.h:1011
double T
floating point size
Definition: units.h:73
CellIndex size() const override
Definition: celllistimpl.h:185
A basic class for a cell list allowing to keep members organized into a grid.
Definition: celllistimpl.h:632
const Members & getEmpty() const override
Gets cell members of an empty cell. Allows non-existing cells.
Definition: celllistimpl.h:551
CellIndex gridSize() const override
Definition: celllistimpl.h:689
A mixin using spatial coordinates instead of cell coordinates when inserting or removing a member...
Definition: celllistimpl.h:937
CellIndex indexAt(const Point &position) const override
Compute the cell index from the spatial position.
Definition: celllistimpl.h:150
An interface of a container.
Definition: celllist.h:93
Definition: celllistimpl.h:78
const Members & getNeighborMembers(const CellCoord &cell_coordinates, const CellCoord &cell_offset) override
Gets cell members at given cell coordinates.
Definition: celllistimpl.h:1034
A cell grid core class assuming fixed boundary conditions.
Definition: celllistimpl.h:95
std::vector< Index > indices() const override
Return all cell indicis that may contain members.
Definition: celllistimpl.h:560
void insertMember(const Member &member, const Point &new_position)
< point
Definition: celllistimpl.h:947
Containers store members in individual cells with a common minimalistic interface.
Eigen::Array< SpaceAxis, Dimension, 1 > Point
a point in the VDimensional space
Definition: celllist.h:43
CellListBase(const TGrid &cell_grid)
Construct an empty cell list from a grid.
Definition: celllistimpl.h:704
const Members & getMembers(const CellCoord &cell_coordinates) override
< members type
Definition: celllistimpl.h:653
CellIndex index(const CellCoord &coordinates) const override
Compute the cell index from the cell coordinates.
Definition: celllistimpl.h:313
TCellIndex CellIndex
a single coordinate in cell space, e.g., int; also an absolute cell index
Definition: celllist.h:42
typename Grid::CoordOf< GridType > CellCoord
grid (cell) coordinates type
Definition: celllist.h:145
bool isCell(const CellCoord &coordinates) const override
Verifies if coordinates are valid in the grid.
Definition: celllistimpl.h:163
GridBase(const Point &box, SpaceAxis minimal_cell_dimension)
Definition: celllistimpl.h:191
Fixed boundary conditions.
Definition: celllistimpl.h:245
bool isCellAt(const Point &point) const override
Verifies if spatial coordinates are in the box.
Definition: celllistimpl.h:177
const Members & getSortedMembers(const CellCoord &cell_coordinates) override
< members type
Definition: celllistimpl.h:772
Eigen::Array< CellIndex, Dimension, 1 > CellCoord
VDimensional cell coordinates.
Definition: celllist.h:44
TSpaceAxis SpaceAxis
a single coordinate in physical space, e.g., double
Definition: celllist.h:40
const TGrid & getGrid()
Static cast itself to a grid.
Definition: celllistimpl.h:698
Definition: celllist.h:15
typename Container::MemberOf< ContainerType > Member
member type
Definition: celllist.h:143
std::vector< Member > Members
the cell members type
Definition: celllist.h:98
TIndex Index
the cell index (key) type
Definition: celllist.h:96
const Members & getEmpty() const override
Gets cell members of an empty cell. Allows non-existing cells.
Definition: celllistimpl.h:469
const Members & getNeighborSortedMembers(const CellCoord &cell_coordinates, const CellCoord &cell_offset) override
Get members of a neighbor cell in a sorted order.
Definition: celllistimpl.h:783
CellListBase(const typename TGrid::Point &box, const typename TGrid::SpaceAxis cell_dimension)
Construct an empty cell list knowing a box dimension and minimal cell dimension.
Definition: celllistimpl.h:715
std::vector< CellCoord > getCells() const override
Gets indicies of non-empty cells.
Definition: celllistimpl.h:1049
Wrapper of two cell list to efficiently provide difference of members, i.e., members presented in the...
Definition: celllistimpl.h:972
CellCoord coordinatesAt(const Point &position) const override
Compute cell coordinates from a spatial position.
Definition: celllistimpl.h:337
GridTypeOf< TGrid > GridType
abstract grid type
Definition: celllist.h:141
SortableCellList(const typename GridOf< TBase >::Point &box, const typename GridOf< TBase >::SpaceAxis cell_dimension)
Construct an empty cell list knowing a box dimension and minimal cell dimension.
Definition: celllistimpl.h:809
void importMembers(CellListReverseMap &source, const T &members)
Imports members from other list without computing cell coordinates from member positions.
Definition: celllistimpl.h:900
CellCoord coordinatesAt(const Point &position) const override
Compute cell coordinates from a spatial position.
Definition: celllistimpl.h:139
typename Container::MembersOf< ContainerType > Members
members type
Definition: celllist.h:142
typename Container::MembersOf< ContainerType > Members
members type
Definition: celllist.h:142
typename Grid::IndexOf< GridType > CellIndex
grid (cell) index type
Definition: celllist.h:144
bool isCell(const CellCoord &) const override
Verifies if coordinates are valid in the grid.
Definition: celllistimpl.h:361
Periodic boundary conditions.
Definition: celllistimpl.h:283
typename Grid::CoordOf< GridType > CellCoord
grid (cell) coordinates type
Definition: celllist.h:145
std::vector< Member > Members
the cell members type
Definition: celllist.h:98
bool isNeighborCell([[maybe_unused]] const CellCoord &coordinates, const CellCoord &offset) const override
Verifies if offseted coordinates are valid taking into account periodic boundary conditions.
Definition: celllistimpl.h:385
std::vector< Member > Members
the cell members type
Definition: celllist.h:98
Eigen::Array< CellIndex, Dimension, 1 > CellCoord
VDimensional cell coordinates.
Definition: celllist.h:44
Container based on a vector suitable for system with a uniform and high member density.
Definition: celllistimpl.h:450
const Members & getNeighborMembers(const CellCoord &cell_coordinates, const CellCoord &cell_offset) override
Get cell members at given offseted cell coordinates, or empty if offseted dcoordinates do not exist...
Definition: celllistimpl.h:664
const Members & getSortedMembers(const CellCoord &cell_coordinates) override
< members type
Definition: celllistimpl.h:988
CellIndex indexAt(const Point &position) const override
Compute the cell index from the spatial position.
Definition: celllistimpl.h:348
typename Grid::IndexOf< GridType > CellIndex
grid (cell) index type
Definition: celllist.h:144
CellIndex gridSize() const override
Get cells count. Valid cell indices are in the range [0, gridSize).
Definition: celllistimpl.h:1045
bool isNeighborCell(const CellCoord &coordinates, const CellCoord &offset) const
Verifies if offseted coordinates are valid.
Definition: celllistimpl.h:262
Interface of a grid.
Definition: celllistimpl.h:60
Reverse mapping (from particle to its cell) is stored.
Definition: celllistimpl.h:860
std::vector< Index > indices() const override
Return all cell indices that may contain members.
Definition: celllistimpl.h:479
typename Container::MemberOf< ContainerType > Member
member type
Definition: celllist.h:143
An interface of a immutable cell list.
Definition: celllist.h:137
CellCoord coordinates(const CellIndex index) const override
Compute the cell coordinates from the cell index.
Definition: celllistimpl.h:303
bool containsMember(const Member &member)
returns true if member is present in the cell list false if not
Definition: celllistimpl.h:891
An interface to a cell list that can return cell's members in sorted order.
Definition: celllist.h:168
SortableCellList(const GridOf< TBase > &cell_grid)
Construct an empty cell list from a grid.
Definition: celllistimpl.h:798
bool isCellAt(const Point &) const override
Verifies if spatial coordinates are in the box.
Definition: celllistimpl.h:371