Version: SMASH-2.0
lattice.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2015-2020
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #ifndef SRC_INCLUDE_SMASH_LATTICE_H_
11 #define SRC_INCLUDE_SMASH_LATTICE_H_
12 
13 #include <array>
14 #include <cstring>
15 #include <functional>
16 #include <utility>
17 #include <vector>
18 
19 #include "forwarddeclarations.h"
20 #include "fourvector.h"
21 #include "logging.h"
22 #include "numerics.h"
23 
24 namespace smash {
25 static constexpr int LLattice = LogArea::Lattice::id;
26 
36 enum class LatticeUpdate {
37  AtOutput = 0,
38  EveryTimestep = 1,
40 };
41 
46 template <typename T>
48  public:
66  RectangularLattice(const std::array<double, 3>& l,
67  const std::array<int, 3>& n,
68  const std::array<double, 3>& orig, bool per,
69  const LatticeUpdate upd)
70  : lattice_sizes_(l),
71  n_cells_(n),
72  cell_sizes_{l[0] / n[0], l[1] / n[1], l[2] / n[2]},
73  origin_(orig),
74  periodic_(per),
75  when_update_(upd) {
76  lattice_.resize(n_cells_[0] * n_cells_[1] * n_cells_[2]);
77  logg[LLattice].debug(
78  "Rectangular lattice created: sizes[fm] = (", lattice_sizes_[0], ",",
79  lattice_sizes_[1], ",", lattice_sizes_[2], "), dims = (", n_cells_[0],
80  ",", n_cells_[1], ",", n_cells_[2], "), origin = (", origin_[0], ",",
81  origin_[1], ",", origin_[2], "), periodic: ", periodic_);
82  if (n_cells_[0] < 1 || n_cells_[1] < 1 || n_cells_[2] < 1 ||
83  lattice_sizes_[0] < 0.0 || lattice_sizes_[1] < 0.0 ||
84  lattice_sizes_[2] < 0.0) {
85  throw std::invalid_argument(
86  "Lattice sizes should be positive, "
87  "lattice dimensions should be > 0.");
88  }
89  }
90 
93  : lattice_(rl.lattice_),
95  n_cells_(rl.n_cells_),
97  origin_(rl.origin_),
98  periodic_(rl.periodic_),
100 
102  void reset() { std::fill(lattice_.begin(), lattice_.end(), T()); }
103 
112  inline bool out_of_bounds(int ix, int iy, int iz) const {
113  // clang-format off
114  return !periodic_ &&
115  (ix < 0 || ix >= n_cells_[0] ||
116  iy < 0 || iy >= n_cells_[1] ||
117  iz < 0 || iz >= n_cells_[2]);
118  // clang-format on
119  }
120 
129  inline ThreeVector cell_center(int ix, int iy, int iz) const {
130  return ThreeVector(origin_[0] + cell_sizes_[0] * (ix + 0.5),
131  origin_[1] + cell_sizes_[1] * (iy + 0.5),
132  origin_[2] + cell_sizes_[2] * (iz + 0.5));
133  }
134 
143  inline ThreeVector cell_center(int index) const {
144  const int ix = index % n_cells_[0];
145  index = index / n_cells_[0];
146  const int iy = index % n_cells_[1];
147  const int iz = index / n_cells_[1];
148  return cell_center(ix, iy, iz);
149  }
150 
152  const std::array<double, 3>& lattice_sizes() const { return lattice_sizes_; }
153 
155  const std::array<int, 3>& dimensions() const { return n_cells_; }
156 
158  const std::array<double, 3>& cell_sizes() const { return cell_sizes_; }
159 
161  const std::array<double, 3>& origin() const { return origin_; }
162 
164  bool periodic() const { return periodic_; }
165 
168 
170  using iterator = typename std::vector<T>::iterator;
172  using const_iterator = typename std::vector<T>::const_iterator;
174  iterator begin() { return lattice_.begin(); }
176  const_iterator begin() const { return lattice_.begin(); }
178  iterator end() { return lattice_.end(); }
180  const_iterator end() const { return lattice_.end(); }
182  T& operator[](std::size_t i) { return lattice_[i]; }
184  const T& operator[](std::size_t i) const { return lattice_[i]; }
186  std::size_t size() const { return lattice_.size(); }
187 
196  T& node(int ix, int iy, int iz) {
197  return periodic_
198  ? lattice_[positive_modulo(ix, n_cells_[0]) +
199  n_cells_[0] *
200  (positive_modulo(iy, n_cells_[1]) +
201  n_cells_[1] * positive_modulo(iz, n_cells_[2]))]
202  : lattice_[ix + n_cells_[0] * (iy + n_cells_[1] * iz)];
203  }
204 
219  bool value_at(const ThreeVector& r, T& value) {
220  const int ix = std::floor((r.x1() - origin_[0]) / cell_sizes_[0]);
221  const int iy = std::floor((r.x2() - origin_[1]) / cell_sizes_[1]);
222  const int iz = std::floor((r.x3() - origin_[2]) / cell_sizes_[2]);
223  if (out_of_bounds(ix, iy, iz)) {
224  value = T();
225  return false;
226  } else {
227  value = node(ix, iy, iz);
228  return true;
229  }
230  }
231 
242  template <typename F>
243  void iterate_sublattice(const std::array<int, 3>& lower_bounds,
244  const std::array<int, 3>& upper_bounds, F&& func) {
245  logg[LLattice].debug(
246  "Iterating sublattice with lower bound index (", lower_bounds[0], ",",
247  lower_bounds[1], ",", lower_bounds[2], "), upper bound index (",
248  upper_bounds[0], ",", upper_bounds[1], ",", upper_bounds[2], ")");
249 
250  if (periodic_) {
251  for (int iz = lower_bounds[2]; iz < upper_bounds[2]; iz++) {
252  const int z_offset = positive_modulo(iz, n_cells_[2]) * n_cells_[1];
253  for (int iy = lower_bounds[1]; iy < upper_bounds[1]; iy++) {
254  const int y_offset =
255  n_cells_[0] * (positive_modulo(iy, n_cells_[1]) + z_offset);
256  for (int ix = lower_bounds[0]; ix < upper_bounds[0]; ix++) {
257  const int index = positive_modulo(ix, n_cells_[0]) + y_offset;
258  func(lattice_[index], ix, iy, iz);
259  }
260  }
261  }
262  } else {
263  for (int iz = lower_bounds[2]; iz < upper_bounds[2]; iz++) {
264  const int z_offset = iz * n_cells_[1];
265  for (int iy = lower_bounds[1]; iy < upper_bounds[1]; iy++) {
266  const int y_offset = n_cells_[0] * (iy + z_offset);
267  for (int ix = lower_bounds[0]; ix < upper_bounds[0]; ix++) {
268  func(lattice_[ix + y_offset], ix, iy, iz);
269  }
270  }
271  }
272  }
273  }
274 
287  template <typename F>
288  void iterate_in_radius(const ThreeVector& point, const double r_cut,
289  F&& func) {
290  std::array<int, 3> l_bounds, u_bounds;
291 
292  /* Array holds value at the cell center: r_center = r_0 + (i+0.5)cell_size,
293  * where i is index in any direction. Therefore we want cells with condition
294  * (r-r_cut)*csize - 0.5 < i < (r+r_cut)*csize - 0.5, r = r_center - r_0 */
295  for (int i = 0; i < 3; i++) {
296  l_bounds[i] =
297  std::ceil((point[i] - origin_[i] - r_cut) / cell_sizes_[i] - 0.5);
298  u_bounds[i] =
299  std::ceil((point[i] - origin_[i] + r_cut) / cell_sizes_[i] - 0.5);
300  }
301 
302  if (!periodic_) {
303  for (int i = 0; i < 3; i++) {
304  if (l_bounds[i] < 0) {
305  l_bounds[i] = 0;
306  }
307  if (u_bounds[i] > n_cells_[i]) {
308  u_bounds[i] = n_cells_[i];
309  }
310  if (l_bounds[i] > n_cells_[i] || u_bounds[i] < 0) {
311  return;
312  }
313  }
314  }
315  iterate_sublattice(l_bounds, u_bounds, std::forward<F>(func));
316  }
317 
326  template <typename L>
327  bool identical_to_lattice(const L* lat) const {
328  return n_cells_[0] == lat->dimensions()[0] &&
329  n_cells_[1] == lat->dimensions()[1] &&
330  n_cells_[2] == lat->dimensions()[2] &&
331  std::abs(lattice_sizes_[0] - lat->lattice_sizes()[0]) <
332  really_small &&
333  std::abs(lattice_sizes_[1] - lat->lattice_sizes()[1]) <
334  really_small &&
335  std::abs(lattice_sizes_[2] - lat->lattice_sizes()[2]) <
336  really_small &&
337  std::abs(origin_[0] - lat->origin()[0]) < really_small &&
338  std::abs(origin_[1] - lat->origin()[1]) < really_small &&
339  std::abs(origin_[2] - lat->origin()[2]) < really_small &&
340  periodic_ == lat->periodic();
341  }
342 
343  protected:
345  std::vector<T> lattice_;
347  const std::array<double, 3> lattice_sizes_;
349  const std::array<int, 3> n_cells_;
351  const std::array<double, 3> cell_sizes_;
353  const std::array<double, 3> origin_;
355  const bool periodic_;
358 
359  private:
368  inline int positive_modulo(int i, int n) const {
369  /* (i % n + n) % n would be correct, but slow.
370  * Instead I rely on the fact that i should never go too far
371  * in negative region and replace i%n + n by i + 256 * n = i + (n << 8) */
372  // FIXME: This should use asserts, also checking for under- or overflows.
373  return (i + (n << 8)) % n;
374  }
375 };
376 
377 } // namespace smash
378 
379 #endif // SRC_INCLUDE_SMASH_LATTICE_H_
smash::LatticeUpdate
LatticeUpdate
Enumerator option for lattice updates.
Definition: lattice.h:36
smash
Definition: action.h:24
smash::RectangularLattice::RectangularLattice
RectangularLattice(const std::array< double, 3 > &l, const std::array< int, 3 > &n, const std::array< double, 3 > &orig, bool per, const LatticeUpdate upd)
Rectangular lattice constructor.
Definition: lattice.h:66
smash::RectangularLattice::out_of_bounds
bool out_of_bounds(int ix, int iy, int iz) const
Checks if 3D index is out of lattice bounds.
Definition: lattice.h:112
smash::LatticeUpdate::AtOutput
smash::ThreeVector::x3
double x3() const
Definition: threevector.h:173
smash::RectangularLattice< smash::EnergyMomentumTensor >::const_iterator
typename std::vector< smash::EnergyMomentumTensor >::const_iterator const_iterator
Const interator of lattice.
Definition: lattice.h:172
smash::RectangularLattice::iterate_in_radius
void iterate_in_radius(const ThreeVector &point, const double r_cut, F &&func)
Iterates only nodes, whose cell centers lie not further than r_cut in x, y, z directions from the giv...
Definition: lattice.h:288
smash::RectangularLattice::n_cells_
const std::array< int, 3 > n_cells_
Number of cells in x,y,z directions.
Definition: lattice.h:349
smash::RectangularLattice::identical_to_lattice
bool identical_to_lattice(const L *lat) const
Checks if lattices of possibly different types have identical structure.
Definition: lattice.h:327
smash::RectangularLattice::positive_modulo
int positive_modulo(int i, int n) const
Returns division modulo, which is always between 0 and n-1 in is not suitable, because it returns res...
Definition: lattice.h:368
smash::RectangularLattice::lattice_sizes_
const std::array< double, 3 > lattice_sizes_
Lattice sizes in x, y, z directions.
Definition: lattice.h:347
smash::LatticeUpdate::EveryTimestep
fourvector.h
smash::logg
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
smash::RectangularLattice::end
const_iterator end() const
Definition: lattice.h:180
smash::really_small
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
smash::RectangularLattice::operator[]
const T & operator[](std::size_t i) const
Definition: lattice.h:184
forwarddeclarations.h
smash::ThreeVector
Definition: threevector.h:31
smash::RectangularLattice::cell_center
ThreeVector cell_center(int ix, int iy, int iz) const
Find the coordinates of a given cell.
Definition: lattice.h:129
smash::LatticeUpdate::EveryFixedInterval
smash::RectangularLattice::periodic
bool periodic() const
Definition: lattice.h:164
smash::RectangularLattice
A container class to hold all the arrays on the lattice and access them.
Definition: lattice.h:47
smash::RectangularLattice::cell_sizes_
const std::array< double, 3 > cell_sizes_
Cell sizes in x, y, z directions.
Definition: lattice.h:351
smash::RectangularLattice::begin
iterator begin()
Definition: lattice.h:174
smash::RectangularLattice::when_update_
const LatticeUpdate when_update_
When the lattice should be recalculated.
Definition: lattice.h:357
smash::RectangularLattice::cell_center
ThreeVector cell_center(int index) const
Find the coordinate of cell center given the 1d index of the cell.
Definition: lattice.h:143
smash::RectangularLattice::lattice_
std::vector< T > lattice_
The lattice itself, array containing physical quantities.
Definition: lattice.h:345
smash::RectangularLattice::begin
const_iterator begin() const
Definition: lattice.h:176
smash::RectangularLattice::RectangularLattice
RectangularLattice(RectangularLattice< T > const &rl)
Copy-constructor.
Definition: lattice.h:92
smash::ThreeVector::x1
double x1() const
Definition: threevector.h:165
smash::RectangularLattice::node
T & node(int ix, int iy, int iz)
Take the value of a cell given its 3-D indices.
Definition: lattice.h:196
smash::RectangularLattice::lattice_sizes
const std::array< double, 3 > & lattice_sizes() const
Definition: lattice.h:152
smash::RectangularLattice::value_at
bool value_at(const ThreeVector &r, T &value)
Interpolates lattice quantity to coordinate r.
Definition: lattice.h:219
smash::RectangularLattice::cell_sizes
const std::array< double, 3 > & cell_sizes() const
Definition: lattice.h:158
numerics.h
smash::RectangularLattice::operator[]
T & operator[](std::size_t i)
Definition: lattice.h:182
logging.h
smash::RectangularLattice::dimensions
const std::array< int, 3 > & dimensions() const
Definition: lattice.h:155
smash::RectangularLattice::end
iterator end()
Definition: lattice.h:178
smash::RectangularLattice::size
std::size_t size() const
Definition: lattice.h:186
smash::RectangularLattice::when_update
LatticeUpdate when_update() const
Definition: lattice.h:167
smash::pdg::n
constexpr int n
Neutron.
Definition: pdgcode_constants.h:30
smash::RectangularLattice::periodic_
const bool periodic_
Whether the lattice is periodic.
Definition: lattice.h:355
smash::RectangularLattice< smash::EnergyMomentumTensor >::iterator
typename std::vector< smash::EnergyMomentumTensor >::iterator iterator
Iterator of lattice.
Definition: lattice.h:170
smash::LLattice
static constexpr int LLattice
Definition: lattice.h:25
smash::RectangularLattice::origin_
const std::array< double, 3 > origin_
Coordinates of the left down nearer corner.
Definition: lattice.h:353
smash::RectangularLattice::origin
const std::array< double, 3 > & origin() const
Definition: lattice.h:161
smash::RectangularLattice::reset
void reset()
Sets all values on lattice to zeros.
Definition: lattice.h:102
smash::RectangularLattice::iterate_sublattice
void iterate_sublattice(const std::array< int, 3 > &lower_bounds, const std::array< int, 3 > &upper_bounds, F &&func)
A sub-lattice iterator, which iterates in a 3D-structured manner and calls a function on every cell.
Definition: lattice.h:243
smash::ThreeVector::x2
double x2() const
Definition: threevector.h:169