1 #ifndef UTOPIA_CORE_GRIDS_HEXAGONAL_HH
2 #define UTOPIA_CORE_GRIDS_HEXAGONAL_HH
91 static_assert(
dim == 2,
"Hexagonal grid is only implemented for 2D "
102 > get_as<double>(
"aspect_ratio_tolerance", cfg, 0.02))
105 required_space[0] = this->
_space->extent[0];
107 std::stringstream required_space_ss;
108 required_space_ss << required_space;
110 throw std::invalid_argument(fmt::format(
111 "Given the extent of the physical space and the specified "
112 "resolution, a mapping with hexagonal cells could not be "
113 "found! Either adjust the the extent of physical space or the "
114 "resolution of the grid. Alternatively increase the tolerance "
115 "to distorted hexagons or choose another grid. \n"
116 "The required aspect ratio of sqrt(3) / 2 is violated by {} "
117 "(> `aspect_ratio_tolerance` = {})! \n"
118 "With the given resolution, set the space extent to : \n"
119 "{} or increase the resolution.",
121 get_as<double>(
"aspect_ratio_tolerance", cfg, 0.02),
122 required_space_ss.str()
169 if (mid[1] % 2 == 0) {
252 ridx = this->
_space->map_into_space(pos);
254 else if (not this->
_space->contains(pos)) {
255 throw std::invalid_argument(
"The given position is outside "
256 "the non-periodic space associated with this grid!");
262 arma::Col<int>::fixed<
dim> midx = {
263 static_cast<int>(std::round(ridx[0] + 2. / 3. * ridx[1])),
264 static_cast<int>(std::round(4. / 3. * ridx[1]))
268 midx[0] -= std::floor(midx[1] / 2.);
282 if (midx[0] ==
static_cast<int>(
_shape[0])) {
310 and select !=
"left" and select !=
"right"
311 and select !=
"bottom" and select !=
"top")
313 throw std::invalid_argument(
"Invalid value for argument "
314 "`select` in call to method SquareGrid::boundary_cells! "
315 "Available arguments (for currently selected "
316 "dimensionality) are: "
317 "'all', 'left', 'right', 'bottom', 'top'. Given value: '"
322 std::set<IndexType> bc_ids;
335 auto hint = bc_ids.begin();
338 if (select ==
"all" or select ==
"bottom") {
341 bc_ids.emplace_hint(hint,
id);
347 if (select ==
"left") {
350 bc_ids.emplace_hint(hint, row *
_shape[0]);
356 if (select ==
"right") {
358 const auto offset =
_shape[0] - 1;
361 bc_ids.emplace_hint(hint, offset + row *
_shape[0]);
367 if (select ==
"all") {
369 const auto offset =
_shape[0] - 1;
373 bc_ids.emplace_hint(hint, row *
_shape[0]);
376 bc_ids.emplace_hint(bc_ids.end(),
377 offset + row *
_shape[0]);
384 if (select ==
"all" or select ==
"top") {
389 bc_ids.emplace_hint(hint,
id);
418 double s = sqrt(2. / (3 * sqrt(3)));
419 double width = sqrt(3) * s;
420 double height = 2 * s;
422 shape[0] = std::round( this->
_space->extent[0] / width
423 * this->_resolution);
424 shape[1] = std::round( this->
_space->extent[1] / (0.75 * height)
425 * this->_resolution);
450 +
"' neighborhood available for HexagonalGrid! "
451 "Available modes: empty, hexagonal.");
457 const Config&)
const override
467 +
"' neighborhood available for HexagonalGrid! "
468 "Available modes: empty, hexagonal.");
494 constexpr
bool check_shape =
true;
495 const auto distance = get_nb_param_distance<check_shape>(
nb_params);
513 throw std::invalid_argument(fmt::format(
514 "Hexagonal neighborhood is not implemented for a "
515 "distance larger than 1. Requested distance was {}.",
530 neighbor_ids.reserve(3 *
dim);
534 add_neighbors_in_<0, true>(root_id, neighbor_ids);
535 add_neighbors_in_<1, true>(root_id, neighbor_ids);
536 add_neighbors_in_<2, true>(root_id, neighbor_ids);
552 neighbor_ids.reserve(2 *
dim);
556 add_neighbors_in_<0, false>(root_id, neighbor_ids);
557 add_neighbors_in_<1, false>(root_id, neighbor_ids);
558 add_neighbors_in_<2, false>(root_id, neighbor_ids);
584 template<DimType axis,
bool periodic>
589 static_assert(axis < 3);
592 if constexpr (axis == 0) {
599 if constexpr (periodic) {
600 neighbor_ids.push_back(root_id - 1 +
_shape[0]);
606 neighbor_ids.push_back(root_id - 1);
610 if (nrm_id ==
_shape[0] - 1) {
612 if constexpr (periodic) {
613 neighbor_ids.push_back(root_id + 1 -
_shape[0]);
619 neighbor_ids.push_back(root_id + 1);
623 else if constexpr (axis == 1) {
632 if constexpr (periodic) {
633 if (nrm_id_0 <
_shape[0] - 1) {
634 neighbor_ids.push_back( root_id -
_shape[0] + 1
639 neighbor_ids.push_back( root_id - 2*
_shape[0] + 1
645 else if (nrm_id_0 ==
_shape[0] - 1 and nrm_id_1 % 2 == 0) {
647 if constexpr (periodic) {
648 neighbor_ids.push_back(root_id - 2*
_shape[0] + 1);
652 else if (nrm_id_1 % 2 == 0) {
655 neighbor_ids.push_back(root_id -
_shape[0] + 1);
659 neighbor_ids.push_back(root_id -
_shape[0]);
663 if (nrm_id_1 ==
_shape[1] - 1) {
665 if constexpr (periodic) {
668 neighbor_ids.push_back( root_id +
_shape[0] - 1
673 neighbor_ids.push_back( root_id + 2*
_shape[0] - 1
679 else if (nrm_id_0 == 0 and nrm_id_1 % 2 == 1){
681 if constexpr (periodic) {
682 neighbor_ids.push_back(root_id + 2*
_shape[0] - 1);
685 else if (nrm_id_1 % 2 == 0) {
687 neighbor_ids.push_back(root_id +
_shape[0]);
691 neighbor_ids.push_back(root_id +
_shape[0] - 1);
703 if constexpr (periodic) {
704 neighbor_ids.push_back( root_id -
_shape[0]
709 else if (nrm_id_0 == 0 and nrm_id_1 % 2 == 1) {
711 if constexpr (periodic) {
712 neighbor_ids.push_back(root_id - 1);
716 else if (nrm_id_1 % 2 == 1) {
717 neighbor_ids.push_back(root_id -
_shape[0] - 1);
720 neighbor_ids.push_back(root_id -
_shape[0]);
723 if (nrm_id_1 ==
_shape[1] - 1) {
725 if constexpr (periodic) {
726 neighbor_ids.push_back( root_id +
_shape[0]
731 else if (nrm_id_0 ==
_shape[0] - 1 and nrm_id_1 % 2 == 0) {
733 if constexpr (periodic) {
734 neighbor_ids.push_back(root_id + 1);
738 else if (nrm_id_1 % 2 == 0) {
739 neighbor_ids.push_back(root_id +
_shape[0] + 1);
742 neighbor_ids.push_back(root_id +
_shape[0]);
763 template<
bool check_shape=false>
765 const auto distance = get_as<DistType>(
"distance", params, 1);
771 if constexpr (check_shape) {
773 and (distance * 2 + 1 > this->
shape().min()))
777 std::stringstream shape_ss;
778 this->
shape().print(shape_ss,
"Grid Shape:");
780 throw std::invalid_argument(
"The grid shape is too small to "
781 "accomodate a neighborhood with 'distance' parameter set "
782 "to " + get_as<std::string>(
"distance", params,
"1")
783 +
" in a periodic space!\n" + shape_ss.str());
The base class for all grid discretizations used by the CellManager.
Definition: base.hh:99
bool is_periodic() const
Whether the space this grid maps to is periodic.
Definition: base.hh:304
const NBMode & nb_mode() const
Const reference to the currently selected neighborhood mode.
Definition: base.hh:198
const std::shared_ptr< Space > _space
The space that is to be discretized.
Definition: base.hh:120
const Config & nb_params() const
The neighborhood parameters of the currently selected neighborhood.
Definition: base.hh:203
NBFuncID< Self > _nb_empty
A neighborhood function for empty neighborhood.
Definition: base.hh:323
const std::shared_ptr< Space > & space() const
Const reference to the space this grid maps to.
Definition: base.hh:299
DataIO::Config Config
The configuration type.
Definition: base.hh:114
A grid discretization using hexagonal cells.
Definition: hexagonal.hh:50
typename Space::SpaceVec SpaceVec
The type of vectors that have a relation to physical space.
Definition: hexagonal.hh:59
HexagonalGrid(std::shared_ptr< Space > space, const Config &cfg)
Construct a hexagonal grid discretization.
Definition: hexagonal.hh:84
MultiIndex shape() const override
Get shape of the hexagonal grid.
Definition: hexagonal.hh:146
NBFuncID< Base > get_nb_func(NBMode nb_mode, const Config &nb_params) override
Retrieve the neighborhood function depending on the mode.
Definition: hexagonal.hh:439
SpaceVec extent_of(const IndexType) const override
Returns the extent of the cell with the given ID.
Definition: hexagonal.hh:186
NBFuncID< Base > _nb_hexagonal_nonperiodic
The Von-Neumann neighborhood for non-periodic grids.
Definition: hexagonal.hh:544
const SpaceVec _cell_extent
The extent of each cell of this discretization (same for all)
Definition: hexagonal.hh:76
MultiIndex determine_shape() const
Get shape of the hexagonal grid.
Definition: hexagonal.hh:413
void add_neighbors_in_(const IndexType root_id, IndexContainer &neighbor_ids) const
Add both direct neighbors to a container of indices.
Definition: hexagonal.hh:585
GridStructure structure() const override
Structure of the grid.
Definition: hexagonal.hh:151
NBFuncID< Base > get_nb_func_hexagonal(const Config &nb_params)
Returns a standalone hexagonal neighborhood function.
Definition: hexagonal.hh:492
IndexType num_cells() const override
Number of hexagonal cells required to fill the physical space.
Definition: hexagonal.hh:135
std::set< IndexType > boundary_cells(std::string select="all") const override
Retrieve a set of cell indices that are at a specified boundary.
Definition: hexagonal.hh:307
SpaceVec effective_resolution() const override
The effective cell resolution into each physical space dimension.
Definition: hexagonal.hh:140
static constexpr DimType dim
The dimensionality of the space to be discretized (for easier access)
Definition: hexagonal.hh:56
const MultiIndex _shape
The (multi-index) shape of the grid, resulting from resolution.
Definition: hexagonal.hh:71
DistType expected_num_neighbors(const NBMode &nb_mode, const Config &) const override
Computes the expected number of neighbors for a neighborhood mode.
Definition: hexagonal.hh:456
SpaceVec barycenter_of(const IndexType id) const override
Returns the barycenter of the cell with the given ID.
Definition: hexagonal.hh:167
std::vector< SpaceVec > vertices_of(const IndexType id) const override
Returns the vertices of the cell with the given ID.
Definition: hexagonal.hh:197
DistType get_nb_param_distance(const Config ¶ms) const
Extract the distance neighborhood parameter from the given config.
Definition: hexagonal.hh:764
MultiIndexType< dim > MultiIndex
The type of multi-index like arrays, e.g. the grid shape.
Definition: hexagonal.hh:62
NBFuncID< Base > _nb_hexagonal_periodic
The Von-Neumann neighborhood for periodic grids.
Definition: hexagonal.hh:522
IndexType cell_at(const SpaceVec &pos) const override
Return the ID of the cell covering the given point in physical space.
Definition: hexagonal.hh:248
MultiIndex midx_of(const IndexType id) const override
Returns the multi-index of the cell with the given ID.
Definition: hexagonal.hh:160
NBMode
Possible neighborhood types; availability depends on choice of grid.
Definition: base.hh:52
std::string nb_mode_to_string(const NBMode &nb_mode)
Given an NBMode enum value, return the corresponding string key.
Definition: base.hh:78
GridStructure
Available grid implementations.
Definition: base.hh:13
std::function< IndexContainer(const IndexType)> NBFuncID
Type of the neighborhood calculating function.
Definition: base.hh:92
@ hexagonal
The hexagonal neighbourhood, i.e. the neighbourhood on a hexagonal grid.
@ empty
Every entity is utterly alone in the world.
@ hexagonal
A hexagonal lattice grid.
YAML::Node Config
Type of a variadic dictionary-like data structure used throughout Utopia.
Definition: types.hh:71
@ vertices
Iterate over vertices.
arma::Col< IndexType >::fixed< dim > MultiIndexType
Type for index type vectors that are associated with a physical space.
Definition: types.hh:53
std::vector< IndexType > IndexContainer
Type for container of indices.
Definition: types.hh:43
unsigned short DimType
Type for dimensions, i.e. very small unsigned integers.
Definition: types.hh:34
unsigned int DistType
Type for distancens, i.e. intermediately long unsigned integers.
Definition: types.hh:37
std::size_t IndexType
Type for indices, i.e. values used for container indexing, agent IDs, ...
Definition: types.hh:40
SpaceVecType< dim > SpaceVec
The type for vectors relating to physical space.
Definition: space.hh:33
static constexpr std::size_t dim
The dimensionality of the space.
Definition: space.hh:30