Utopia  2
Framework for studying models of complex & adaptive systems.
space.hh
Go to the documentation of this file.
1 #ifndef UTOPIA_CORE_SPACE_HH
2 #define UTOPIA_CORE_SPACE_HH
3 
4 #include <cmath>
5 
6 #include <armadillo>
7 #include <spdlog/spdlog.h> // for fmt
8 
9 #include "../data_io/cfg_utils.hh"
10 #include "types.hh"
11 
12 
13 namespace Utopia {
20 
26 template<std::size_t num_dims>
27 struct Space {
28  // -- Members -------------------------------------------------------------
30  static constexpr std::size_t dim = num_dims;
31 
34 
36  const bool periodic;
37 
40 
41 
42  // -- Constructors --------------------------------------------------------
44 
47  Space(const Config& cfg)
48  :
50  extent(setup_extent(cfg))
51  {
52  static_assert(dim > 0, "Space::dim needs to be >= 1");
53  }
54 
56 
60  :
61  periodic(false),
63  {
64  static_assert(dim > 0, "Space::dim needs to be >= 1");
65  }
66 
67 
68  // -- Public interface ----------------------------------------------------
70 
81  template<bool include_high_value_boundary=true>
82  bool contains(const SpaceVec& pos) const {
83  // Calculate the relative position within the space
84  const auto rel_pos = pos / extent; // element-wise division
85 
86  // Check that all relative positions are in the respective interval
87  if constexpr (include_high_value_boundary) {
88  return arma::all(rel_pos >= 0. and rel_pos <= 1.); // [0, 1]
89  }
90  else {
91  return arma::all(rel_pos >= 0. and rel_pos < 1.); // [0, 1)
92  }
93  }
94 
96 
103  SpaceVec map_into_space(const SpaceVec& pos) const {
104  // If it is already within space, nothing to map
105  // Check whether it is contained (_excluding_ high value boundary)
106  if (contains<false>(pos)) {
107  return pos;
108  }
109  // else: Need to transform back into space
110 
111  return pos - arma::floor(pos / extent) % extent;
112  }
113 
114 
116 
124  SpaceVec displacement(const SpaceVec& pos_0, const SpaceVec& pos_1) const {
125  SpaceVec dx = pos_1 - pos_0;
126 
127  if (not periodic) {
128  return dx;
129  }
130  // else: Need to get shortest distance
131 
132  return dx - arma::round(dx / extent) % extent;
133  }
134 
136 
149  template<class NormType=std::size_t>
150  auto distance(const SpaceVec& pos_0, const SpaceVec& pos_1,
151  const NormType p=2) const
152  {
153  return arma::norm(displacement(pos_0, pos_1), p);
154  }
155 
156 
157 private:
158  // -- Setup functions -----------------------------------------------------
160  bool setup_periodic(const Config& cfg) const {
161  if (not cfg["periodic"]) {
162  throw std::invalid_argument("Missing config entry `periodic` to "
163  "set up a Space object!");
164  }
165  return get_as<bool>("periodic", cfg);
166  }
167 
170  SpaceVec ext;
171  ext.fill(1.);
172  return ext;
173  }
174 
176 
182  SpaceVec setup_extent(const Config& cfg) const {
183  if (cfg["extent"]) {
184  SpaceVec ext;
185 
186  if (cfg["extent"].IsScalar()) {
187  ext.fill(get_as<double>("extent", cfg));
188  }
189  else {
190  if (dim != cfg["extent"].size()) {
191  throw std::invalid_argument(fmt::format(
192  "Invalid size of `space.extent` sequence ({}) for "
193  "selected space dimensionality ({})!",
194  cfg["extent"].size(), dim
195  ));
196  }
197  ext = get_as_SpaceVec<dim>("extent", cfg);
198  }
199 
200  if (ext.min() <= 0.) {
201  ext.print("Invalid `space.extent`:");
202  throw std::invalid_argument(
203  "The space extent needs to be strictly positive in "
204  "all entries, but it contained at least one element <= 0! "
205  "Check the `space.extent` config node to address this."
206  );
207  }
208 
209  return ext;
210  }
211  else {
212  // Return the default extent, needs no check
213  return setup_extent();
214  }
215  }
216 };
217 
218 
221 
222 // end group Model
227 } // namespace Utopia
228 
229 #endif // UTOPIA_CORE_SPACE_HH
Definition: agent.hh:11
DataIO::Config Config
Type of a variadic dictionary-like data structure used throughout Utopia.
Definition: types.hh:80
arma::Col< double >::fixed< dim > SpaceVecType
Type for vector-like data that is associated with a physical space.
Definition: types.hh:61
The Space bundles properties about the physical space a model resides in.
Definition: space.hh:27
SpaceVec map_into_space(const SpaceVec &pos) const
Map a position (potentially outside space's extent) back into space.
Definition: space.hh:103
SpaceVecType< dim > SpaceVec
The type for vectors relating to physical space.
Definition: space.hh:33
Space()
Default constructor i.e. constructing a space with default parameters.
Definition: space.hh:59
SpaceVec setup_extent(const Config &cfg) const
Construct a space extent vector from a config node.
Definition: space.hh:182
auto distance(const SpaceVec &pos_0, const SpaceVec &pos_1, const NormType p=2) const
The distance of two coordinates in space.
Definition: space.hh:150
SpaceVec displacement(const SpaceVec &pos_0, const SpaceVec &pos_1) const
Compute the displacement vector between two coordinates.
Definition: space.hh:124
SpaceVec setup_extent() const
Construct a default space extent vector (valued 1 in each dimension)
Definition: space.hh:169
bool setup_periodic(const Config &cfg) const
Setup the member periodic from a config node.
Definition: space.hh:160
bool contains(const SpaceVec &pos) const
Whether this space contains the given coordinate (without mapping it)
Definition: space.hh:82
const SpaceVec extent
The physical (euclidean) extent of the space.
Definition: space.hh:39
Space(const Config &cfg)
Construct a Space using information from a config node.
Definition: space.hh:47
const bool periodic
Whether the space is to be assumed periodic.
Definition: space.hh:36
static constexpr std::size_t dim
The dimensionality of the space.
Definition: space.hh:30