Version: SMASH-3.1
lattice.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2015-2021
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]},
74  origin_(orig),
75  periodic_(per),
76  when_update_(upd) {
77  lattice_.resize(n_cells_[0] * n_cells_[1] * n_cells_[2]);
78  logg[LLattice].debug(
79  "Rectangular lattice created: sizes[fm] = (", lattice_sizes_[0], ",",
80  lattice_sizes_[1], ",", lattice_sizes_[2], "), dims = (", n_cells_[0],
81  ",", n_cells_[1], ",", n_cells_[2], "), origin = (", origin_[0], ",",
82  origin_[1], ",", origin_[2], "), periodic: ", periodic_);
83  if (n_cells_[0] < 1 || n_cells_[1] < 1 || n_cells_[2] < 1 ||
84  lattice_sizes_[0] < 0.0 || lattice_sizes_[1] < 0.0 ||
85  lattice_sizes_[2] < 0.0) {
86  throw std::invalid_argument(
87  "Lattice sizes should be positive, "
88  "number of lattice cells should be > 0.");
89  }
90  }
91 
94  : lattice_(rl.lattice_),
96  n_cells_(rl.n_cells_),
99  origin_(rl.origin_),
100  periodic_(rl.periodic_),
102 
104  void reset() { std::fill(lattice_.begin(), lattice_.end(), T()); }
105 
114  inline bool out_of_bounds(int ix, int iy, int iz) const {
115  // clang-format off
116  return !periodic_ &&
117  (ix < 0 || ix >= n_cells_[0] ||
118  iy < 0 || iy >= n_cells_[1] ||
119  iz < 0 || iz >= n_cells_[2]);
120  // clang-format on
121  }
122 
131  inline ThreeVector cell_center(int ix, int iy, int iz) const {
132  return ThreeVector(origin_[0] + cell_sizes_[0] * (ix + 0.5),
133  origin_[1] + cell_sizes_[1] * (iy + 0.5),
134  origin_[2] + cell_sizes_[2] * (iz + 0.5));
135  }
136 
145  inline ThreeVector cell_center(int index) const {
146  const int ix = index % n_cells_[0];
147  index = index / n_cells_[0];
148  const int iy = index % n_cells_[1];
149  const int iz = index / n_cells_[1];
150  return cell_center(ix, iy, iz);
151  }
152 
154  const std::array<double, 3>& lattice_sizes() const { return lattice_sizes_; }
155 
157  const std::array<int, 3>& n_cells() const { return n_cells_; }
158 
160  const std::array<double, 3>& cell_sizes() const { return cell_sizes_; }
161 
163  const std::array<double, 3>& origin() const { return origin_; }
164 
166  bool periodic() const { return periodic_; }
167 
170 
172  using iterator = typename std::vector<T>::iterator;
174  using const_iterator = typename std::vector<T>::const_iterator;
176  iterator begin() { return lattice_.begin(); }
178  const_iterator begin() const { return lattice_.begin(); }
180  iterator end() { return lattice_.end(); }
182  const_iterator end() const { return lattice_.end(); }
184  T& operator[](std::size_t i) { return lattice_[i]; }
186  const T& operator[](std::size_t i) const { return lattice_[i]; }
188  std::size_t size() const { return lattice_.size(); }
189 
193  void assign_value(int lattice_index, T value) {
194  lattice_[lattice_index] = value;
195  }
196 
205  int index1d(int ix, int iy, int iz) {
206  assert(ix < n_cells_[0]);
207  assert(iy < n_cells_[1]);
208  assert(iz < n_cells_[2]);
209  return (ix + n_cells_[0] * (iy + iz * n_cells_[1]));
210  }
221  int index_left(int ix, int iy, int iz) {
222  if (unlikely(ix == 0)) {
223  return periodic_ ? index1d(n_cells_[0] - 1, iy, iz) : index1d(ix, iy, iz);
224  } else {
225  return index1d(ix - 1, iy, iz);
226  }
227  }
238  int index_right(int ix, int iy, int iz) {
239  if (unlikely(ix == (n_cells_[0] - 1))) {
240  return periodic_ ? index1d(0, iy, iz) : index1d(ix, iy, iz);
241  } else {
242  return index1d(ix + 1, iy, iz);
243  }
244  }
255  int index_down(int ix, int iy, int iz) {
256  if (unlikely(iy == 0)) {
257  return periodic_ ? index1d(ix, n_cells_[1] - 1, iz) : index1d(ix, iy, iz);
258  } else {
259  return index1d(ix, iy - 1, iz);
260  }
261  }
272  int index_up(int ix, int iy, int iz) {
273  if (unlikely(iy == (n_cells_[1] - 1))) {
274  return periodic_ ? index1d(ix, 0, iz) : index1d(ix, iy, iz);
275  } else {
276  return index1d(ix, iy + 1, iz);
277  }
278  }
289  int index_backward(int ix, int iy, int iz) {
290  if (unlikely(iz == 0)) {
291  return periodic_ ? index1d(ix, iy, n_cells_[2] - 1) : index1d(ix, iy, iz);
292  } else {
293  return index1d(ix, iy, iz - 1);
294  }
295  }
306  int index_forward(int ix, int iy, int iz) {
307  if (unlikely(iz == (n_cells_[2] - 1))) {
308  return periodic_ ? index1d(ix, iy, 0) : index1d(ix, iy, iz);
309  } else {
310  return index1d(ix, iy, iz + 1);
311  }
312  }
313 
321  RectangularLattice<ThreeVector>& grad_lat) const {
322  if (n_cells_[0] < 2 || n_cells_[1] < 2 || n_cells_[2] < 2) {
323  // Gradient calculation is impossible
324  throw std::runtime_error(
325  "Lattice is too small for gradient calculation"
326  " (should be at least 2x2x2)");
327  }
328  if (!identical_to_lattice(&grad_lat)) {
329  // Lattice for gradient should have identical origin/dims/periodicity
330  throw std::invalid_argument(
331  "Lattice for gradient should have the"
332  " same origin/dims/periodicity as the original one.");
333  }
334  const double inv_2dx = 0.5 / cell_sizes_[0];
335  const double inv_2dy = 0.5 / cell_sizes_[1];
336  const double inv_2dz = 0.5 / cell_sizes_[2];
337  const int dix = 1;
338  const int diy = n_cells_[0];
339  const int diz = n_cells_[0] * n_cells_[1];
340  const int d = diz * n_cells_[2];
341 
342  for (int iz = 0; iz < n_cells_[2]; iz++) {
343  const int z_offset = diz * iz;
344  for (int iy = 0; iy < n_cells_[1]; iy++) {
345  const int y_offset = diy * iy + z_offset;
346  for (int ix = 0; ix < n_cells_[0]; ix++) {
347  const int index = ix + y_offset;
348  if (unlikely(ix == 0)) {
349  (grad_lat)[index].set_x1(
350  periodic_
351  ? (lattice_[index + dix] - lattice_[index + diy - dix]) *
352  inv_2dx
353  : (lattice_[index + dix] - lattice_[index]) * 2.0 *
354  inv_2dx);
355  } else if (unlikely(ix == n_cells_[0] - 1)) {
356  (grad_lat)[index].set_x1(
357  periodic_
358  ? (lattice_[index - diy + dix] - lattice_[index - dix]) *
359  inv_2dx
360  : (lattice_[index] - lattice_[index - dix]) * 2.0 *
361  inv_2dx);
362  } else {
363  (grad_lat)[index].set_x1(
364  (lattice_[index + dix] - lattice_[index - dix]) * inv_2dx);
365  }
366 
367  if (unlikely(iy == 0)) {
368  (grad_lat)[index].set_x2(
369  periodic_
370  ? (lattice_[index + diy] - lattice_[index + diz - diy]) *
371  inv_2dy
372  : (lattice_[index + diy] - lattice_[index]) * 2.0 *
373  inv_2dy);
374  } else if (unlikely(iy == n_cells_[1] - 1)) {
375  (grad_lat)[index].set_x2(
376  periodic_
377  ? (lattice_[index - diz + diy] - lattice_[index - diy]) *
378  inv_2dy
379  : (lattice_[index] - lattice_[index - diy]) * 2.0 *
380  inv_2dy);
381  } else {
382  (grad_lat)[index].set_x2(
383  (lattice_[index + diy] - lattice_[index - diy]) * inv_2dy);
384  }
385 
386  if (unlikely(iz == 0)) {
387  (grad_lat)[index].set_x3(
388  periodic_
389  ? (lattice_[index + diz] - lattice_[index + d - diz]) *
390  inv_2dz
391  : (lattice_[index + diz] - lattice_[index]) * 2.0 *
392  inv_2dz);
393  } else if (unlikely(iz == n_cells_[2] - 1)) {
394  (grad_lat)[index].set_x3(
395  periodic_
396  ? (lattice_[index - d + diz] - lattice_[index - diz]) *
397  inv_2dz
398  : (lattice_[index] - lattice_[index - diz]) * 2.0 *
399  inv_2dz);
400  } else {
401  (grad_lat)[index].set_x3(
402  (lattice_[index + diz] - lattice_[index - diz]) * inv_2dz);
403  }
404  }
405  }
406  }
407  }
408 
419  RectangularLattice<FourVector>& old_lat, double time_step,
420  RectangularLattice<std::array<FourVector, 4>>& grad_lat) const {
421  if (n_cells_[0] < 2 || n_cells_[1] < 2 || n_cells_[2] < 2) {
422  // Gradient calculation is impossible
423  throw std::runtime_error(
424  "Lattice is too small for gradient calculation"
425  " (should be at least 2x2x2)");
426  }
427  if (!identical_to_lattice(&grad_lat)) {
428  // Lattice for gradient should have identical origin/dims/periodicity
429  throw std::invalid_argument(
430  "Lattice for gradient should have the"
431  " same origin/dims/periodicity as the original one.");
432  }
433  const double inv_2dx = 0.5 / cell_sizes_[0];
434  const double inv_2dy = 0.5 / cell_sizes_[1];
435  const double inv_2dz = 0.5 / cell_sizes_[2];
436  const int dix = 1;
437  const int diy = n_cells_[0];
438  const int diz = n_cells_[0] * n_cells_[1];
439  const int d = diz * n_cells_[2];
440 
441  for (int iz = 0; iz < n_cells_[2]; iz++) {
442  const int z_offset = diz * iz;
443  for (int iy = 0; iy < n_cells_[1]; iy++) {
444  const int y_offset = diy * iy + z_offset;
445  for (int ix = 0; ix < n_cells_[0]; ix++) {
446  const int index = ix + y_offset;
447 
448  // auxiliary vectors used for the calculation of gradients
449  FourVector grad_t_jmu(0.0, 0.0, 0.0, 0.0);
450  FourVector grad_x_jmu(0.0, 0.0, 0.0, 0.0);
451  FourVector grad_y_jmu(0.0, 0.0, 0.0, 0.0);
452  FourVector grad_z_jmu(0.0, 0.0, 0.0, 0.0);
453  // t direction
454  grad_t_jmu = (lattice_[index] - (old_lat)[index]) * (1.0 / time_step);
455  // x direction
456  if (unlikely(ix == 0)) {
457  grad_x_jmu =
458  periodic_
459  ? (lattice_[index + dix] - lattice_[index + diy - dix]) *
460  inv_2dx
461  : (lattice_[index + dix] - lattice_[index]) * 2.0 * inv_2dx;
462  } else if (unlikely(ix == n_cells_[0] - 1)) {
463  grad_x_jmu =
464  periodic_
465  ? (lattice_[index - diy + dix] - lattice_[index - dix]) *
466  inv_2dx
467  : (lattice_[index] - lattice_[index - dix]) * 2.0 * inv_2dx;
468  } else {
469  grad_x_jmu =
470  (lattice_[index + dix] - lattice_[index - dix]) * inv_2dx;
471  }
472  // y direction
473  if (unlikely(iy == 0)) {
474  grad_y_jmu =
475  periodic_
476  ? (lattice_[index + diy] - lattice_[index + diz - diy]) *
477  inv_2dy
478  : (lattice_[index + diy] - lattice_[index]) * 2.0 * inv_2dy;
479  } else if (unlikely(iy == n_cells_[1] - 1)) {
480  grad_y_jmu =
481  periodic_
482  ? (lattice_[index - diz + diy] - lattice_[index - diy]) *
483  inv_2dy
484  : (lattice_[index] - lattice_[index - diy]) * 2.0 * inv_2dy;
485  } else {
486  grad_y_jmu =
487  (lattice_[index + diy] - lattice_[index - diy]) * inv_2dy;
488  }
489  // z direction
490  if (unlikely(iz == 0)) {
491  grad_z_jmu =
492  periodic_
493  ? (lattice_[index + diz] - lattice_[index + d - diz]) *
494  inv_2dz
495  : (lattice_[index + diz] - lattice_[index]) * 2.0 * inv_2dz;
496  } else if (unlikely(iz == n_cells_[2] - 1)) {
497  grad_z_jmu =
498  periodic_
499  ? (lattice_[index - d + diz] - lattice_[index - diz]) *
500  inv_2dz
501  : (lattice_[index] - lattice_[index - diz]) * 2.0 * inv_2dz;
502  } else {
503  grad_z_jmu =
504  (lattice_[index + diz] - lattice_[index - diz]) * inv_2dz;
505  }
506  // fill
507  (grad_lat)[index][0] = grad_t_jmu;
508  (grad_lat)[index][1] = grad_x_jmu;
509  (grad_lat)[index][2] = grad_y_jmu;
510  (grad_lat)[index][3] = grad_z_jmu;
511  }
512  }
513  }
514  }
515 
524  T& node(int ix, int iy, int iz) {
525  return periodic_
526  ? lattice_[positive_modulo(ix, n_cells_[0]) +
527  n_cells_[0] *
528  (positive_modulo(iy, n_cells_[1]) +
529  n_cells_[1] * positive_modulo(iz, n_cells_[2]))]
530  : lattice_[ix + n_cells_[0] * (iy + n_cells_[1] * iz)];
531  }
532 
547  bool value_at(const ThreeVector& r, T& value) {
548  const int ix = std::floor((r.x1() - origin_[0]) / cell_sizes_[0]);
549  const int iy = std::floor((r.x2() - origin_[1]) / cell_sizes_[1]);
550  const int iz = std::floor((r.x3() - origin_[2]) / cell_sizes_[2]);
551  if (out_of_bounds(ix, iy, iz)) {
552  value = T();
553  return false;
554  } else {
555  value = node(ix, iy, iz);
556  return true;
557  }
558  }
559 
570  template <typename F>
571  void iterate_sublattice(const std::array<int, 3>& lower_bounds,
572  const std::array<int, 3>& upper_bounds, F&& func) {
573  logg[LLattice].debug(
574  "Iterating sublattice with lower bound index (", lower_bounds[0], ",",
575  lower_bounds[1], ",", lower_bounds[2], "), upper bound index (",
576  upper_bounds[0], ",", upper_bounds[1], ",", upper_bounds[2], ")");
577 
578  if (periodic_) {
579  for (int iz = lower_bounds[2]; iz < upper_bounds[2]; iz++) {
580  const int z_offset = positive_modulo(iz, n_cells_[2]) * n_cells_[1];
581  for (int iy = lower_bounds[1]; iy < upper_bounds[1]; iy++) {
582  const int y_offset =
583  n_cells_[0] * (positive_modulo(iy, n_cells_[1]) + z_offset);
584  for (int ix = lower_bounds[0]; ix < upper_bounds[0]; ix++) {
585  const int index = positive_modulo(ix, n_cells_[0]) + y_offset;
586  func(lattice_[index], ix, iy, iz);
587  }
588  }
589  }
590  } else {
591  for (int iz = lower_bounds[2]; iz < upper_bounds[2]; iz++) {
592  const int z_offset = iz * n_cells_[1];
593  for (int iy = lower_bounds[1]; iy < upper_bounds[1]; iy++) {
594  const int y_offset = n_cells_[0] * (iy + z_offset);
595  for (int ix = lower_bounds[0]; ix < upper_bounds[0]; ix++) {
596  func(lattice_[ix + y_offset], ix, iy, iz);
597  }
598  }
599  }
600  }
601  }
602 
616  template <typename F>
617  void iterate_in_cube(const ThreeVector& point, const double r_cut, F&& func) {
618  std::array<int, 3> l_bounds, u_bounds;
619 
620  /* Array holds value at the cell center: r_center = r_0 + (i+0.5)cell_size,
621  * where i is index in any direction. Therefore we want cells with condition
622  * (r-r_cut)/csize - 0.5 < i < (r+r_cut)/csize - 0.5, r = r_center - r_0 */
623  for (int i = 0; i < 3; i++) {
624  l_bounds[i] =
625  std::ceil((point[i] - origin_[i] - r_cut) / cell_sizes_[i] - 0.5);
626  u_bounds[i] =
627  std::ceil((point[i] - origin_[i] + r_cut) / cell_sizes_[i] - 0.5);
628  }
629 
630  if (!periodic_) {
631  for (int i = 0; i < 3; i++) {
632  if (l_bounds[i] < 0) {
633  l_bounds[i] = 0;
634  }
635  if (u_bounds[i] > n_cells_[i]) {
636  u_bounds[i] = n_cells_[i];
637  }
638  if (l_bounds[i] > n_cells_[i] || u_bounds[i] < 0) {
639  return;
640  }
641  }
642  }
643  iterate_sublattice(l_bounds, u_bounds, std::forward<F>(func));
644  }
645 
657  template <typename F>
658  void integrate_volume(F& integral,
659  F (*integrand)(ThreeVector, T&, ThreeVector),
660  const double rcut, const ThreeVector& point) {
662  point, {rcut, rcut, rcut},
663  [&point, &integral, &integrand, this](T value, int ix, int iy, int iz) {
664  ThreeVector pos = this->cell_center(ix, iy, iz);
665  integral += integrand(pos, value, point) * this->cell_volume_;
666  });
667  }
682  template <typename F>
684  const std::array<double, 3>& rectangle, F&& func) {
685  std::array<int, 3> l_bounds, u_bounds;
686 
687  /* Array holds value at the cell center: r_center = r_0 + (i+0.5)cell_size,
688  * where i is index in any direction. Therefore we want cells with condition
689  * (r[i]-rectangle[i])/csize - 0.5 < i < (r[i]+rectangle[i])/csize - 0.5,
690  * r[i] = r_center[i] - r_0[i]
691  */
692  for (int i = 0; i < 3; i++) {
693  l_bounds[i] = std::ceil(
694  (point[i] - origin_[i] - rectangle[i]) / cell_sizes_[i] - 0.5);
695  u_bounds[i] = std::ceil(
696  (point[i] - origin_[i] + rectangle[i]) / cell_sizes_[i] - 0.5);
697  }
698 
699  if (!periodic_) {
700  for (int i = 0; i < 3; i++) {
701  if (l_bounds[i] < 0) {
702  l_bounds[i] = 0;
703  }
704  if (u_bounds[i] > n_cells_[i]) {
705  u_bounds[i] = n_cells_[i];
706  }
707  if (l_bounds[i] > n_cells_[i] || u_bounds[i] < 0) {
708  return;
709  }
710  }
711  }
712  iterate_sublattice(l_bounds, u_bounds, std::forward<F>(func));
713  }
714 
726  template <typename F>
727  void iterate_nearest_neighbors(const ThreeVector& point, F&& func) {
728  // get the 3D indeces of the cell containing the given point
729  const int ix = std::floor((point.x1() - origin_[0]) / cell_sizes_[0]);
730  const int iy = std::floor((point.x2() - origin_[1]) / cell_sizes_[1]);
731  const int iz = std::floor((point.x3() - origin_[2]) / cell_sizes_[2]);
732 
733  logg[LLattice].debug(
734  "Iterating over nearest neighbors of the cell at ix = ", ix,
735  ", iy = ", iy, ", iz = ", iz);
736 
737  // determine the 1D index of the center cell
738  const int i = index1d(ix, iy, iz);
739  func(lattice_[i], i, i);
740 
741  // determine the indeces of nearby cells, perform function on them
742  int ileft = index_left(ix, iy, iz);
743  func(lattice_[ileft], ileft, i);
744 
745  int iright = index_right(ix, iy, iz);
746  func(lattice_[iright], iright, i);
747 
748  int idown = index_down(ix, iy, iz);
749  func(lattice_[idown], idown, i);
750 
751  int iup = index_up(ix, iy, iz);
752  func(lattice_[iup], iup, i);
753 
754  int ibackward = index_backward(ix, iy, iz);
755  func(lattice_[ibackward], ibackward, i);
756 
757  int iforward = index_forward(ix, iy, iz);
758  func(lattice_[iforward], iforward, i);
759  }
760 
769  template <typename L>
770  bool identical_to_lattice(const L* lat) const {
771  return n_cells_[0] == lat->n_cells()[0] &&
772  n_cells_[1] == lat->n_cells()[1] &&
773  n_cells_[2] == lat->n_cells()[2] &&
774  std::abs(lattice_sizes_[0] - lat->lattice_sizes()[0]) <
775  really_small &&
776  std::abs(lattice_sizes_[1] - lat->lattice_sizes()[1]) <
777  really_small &&
778  std::abs(lattice_sizes_[2] - lat->lattice_sizes()[2]) <
779  really_small &&
780  std::abs(origin_[0] - lat->origin()[0]) < really_small &&
781  std::abs(origin_[1] - lat->origin()[1]) < really_small &&
782  std::abs(origin_[2] - lat->origin()[2]) < really_small &&
783  periodic_ == lat->periodic();
784  }
785 
786  protected:
788  std::vector<T> lattice_;
790  const std::array<double, 3> lattice_sizes_;
792  const std::array<int, 3> n_cells_;
794  const std::array<double, 3> cell_sizes_;
796  const double cell_volume_;
798  const std::array<double, 3> origin_;
800  const bool periodic_;
803 
804  private:
813  inline int positive_modulo(int i, int n) const {
814  /* (i % n + n) % n would be correct, but slow.
815  * Instead I rely on the fact that i should never go too far
816  * in negative region and replace i%n + n by i + 256 * n = i + (n << 8) */
817  // FIXME: This should use asserts, also checking for under- or overflows.
818  return (i + (n << 8)) % n;
819  }
820 };
821 
822 } // namespace smash
823 
824 #endif // SRC_INCLUDE_SMASH_LATTICE_H_
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
A container class to hold all the arrays on the lattice and access them.
Definition: lattice.h:47
const double cell_volume_
Volume of a cell.
Definition: lattice.h:796
bool out_of_bounds(int ix, int iy, int iz) const
Checks if 3D index is out of lattice bounds.
Definition: lattice.h:114
const std::array< double, 3 > & origin() const
Definition: lattice.h:163
const_iterator end() const
Definition: lattice.h:182
const std::array< int, 3 > n_cells_
Number of cells in x,y,z directions.
Definition: lattice.h:792
int index_right(int ix, int iy, int iz)
Given the indices of a cell in the x, y, and z directions, return index of the nearest cell in the +x...
Definition: lattice.h:238
int index_left(int ix, int iy, int iz)
Given the indices of a cell in the x, y, and z directions, return index of the nearest cell in the -x...
Definition: lattice.h:221
const bool periodic_
Whether the lattice is periodic.
Definition: lattice.h:800
int index1d(int ix, int iy, int iz)
Return the index of a given cell.
Definition: lattice.h:205
const std::array< double, 3 > & lattice_sizes() const
Definition: lattice.h:154
T & operator[](std::size_t i)
Definition: lattice.h:184
const T & operator[](std::size_t i) const
Definition: lattice.h:186
bool periodic() const
Definition: lattice.h:166
int index_up(int ix, int iy, int iz)
Given the indices of a cell in the x, y, and z directions, return index of the nearest cell in the +y...
Definition: lattice.h:272
bool identical_to_lattice(const L *lat) const
Checks if lattices of possibly different types have identical structure.
Definition: lattice.h:770
const std::array< double, 3 > origin_
Coordinates of the left down nearer corner.
Definition: lattice.h:798
int index_backward(int ix, int iy, int iz)
Given the indices of a cell in the x, y, and z directions, return index of the nearest cell in the -z...
Definition: lattice.h:289
void reset()
Sets all values on lattice to zeros.
Definition: lattice.h:104
LatticeUpdate when_update() const
Definition: lattice.h:169
void compute_four_gradient_lattice(RectangularLattice< FourVector > &old_lat, double time_step, RectangularLattice< std::array< FourVector, 4 >> &grad_lat) const
Compute a fourgradient on a lattice of FourVectors jmu via the finite difference method.
Definition: lattice.h:418
const LatticeUpdate when_update_
When the lattice should be recalculated.
Definition: lattice.h:802
const std::array< int, 3 > & n_cells() const
Definition: lattice.h:157
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
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:571
void compute_gradient_lattice(RectangularLattice< ThreeVector > &grad_lat) const
Compute a gradient on a lattice of doubles via the finite difference method.
Definition: lattice.h:320
ThreeVector cell_center(int ix, int iy, int iz) const
Find the coordinates of a given cell.
Definition: lattice.h:131
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:813
int index_forward(int ix, int iy, int iz)
Given the indices of a cell in the x, y, and z directions, return index of the nearest cell in the +z...
Definition: lattice.h:306
typename std::vector< T >::const_iterator const_iterator
Const interator of lattice.
Definition: lattice.h:174
void assign_value(int lattice_index, T value)
Overwrite with a template value T at a given node.
Definition: lattice.h:193
void iterate_in_cube(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 give...
Definition: lattice.h:617
RectangularLattice(RectangularLattice< T > const &rl)
Copy-constructor.
Definition: lattice.h:93
const_iterator begin() const
Definition: lattice.h:178
void integrate_volume(F &integral, F(*integrand)(ThreeVector, T &, ThreeVector), const double rcut, const ThreeVector &point)
Calculate a volume integral with given integrand.
Definition: lattice.h:658
void iterate_nearest_neighbors(const ThreeVector &point, F &&func)
Iterates only over nodes corresponding to the center cell (the cell containing the given point) and i...
Definition: lattice.h:727
typename std::vector< T >::iterator iterator
Iterator of lattice.
Definition: lattice.h:172
void iterate_in_rectangle(const ThreeVector &point, const std::array< double, 3 > &rectangle, F &&func)
Iterates only nodes whose cell centers lie not further than d_x in x-, d_y in y-, and d_z in z-direct...
Definition: lattice.h:683
const std::array< double, 3 > lattice_sizes_
Lattice sizes in x, y, z directions.
Definition: lattice.h:790
T & node(int ix, int iy, int iz)
Take the value of a cell given its 3-D indices.
Definition: lattice.h:524
const std::array< double, 3 > cell_sizes_
Cell sizes in x, y, z directions.
Definition: lattice.h:794
bool value_at(const ThreeVector &r, T &value)
Interpolates lattice quantity to coordinate r.
Definition: lattice.h:547
std::vector< T > lattice_
The lattice itself, array containing physical quantities.
Definition: lattice.h:788
ThreeVector cell_center(int index) const
Find the coordinate of cell center given the 1d index of the cell.
Definition: lattice.h:145
std::size_t size() const
Definition: lattice.h:188
int index_down(int ix, int iy, int iz)
Given the indices of a cell in the x, y, and z directions, return index of the nearest cell in the -y...
Definition: lattice.h:255
const std::array< double, 3 > & cell_sizes() const
Definition: lattice.h:160
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:31
double x3() const
Definition: threevector.h:185
double x2() const
Definition: threevector.h:181
double x1() const
Definition: threevector.h:177
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
#define unlikely(x)
Tell the branch predictor that this expression is likely false.
Definition: macros.h:16
constexpr int n
Neutron.
Definition: action.h:24
LatticeUpdate
Enumerator option for lattice updates.
Definition: lattice.h:36
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
static constexpr int LLattice
Definition: lattice.h:25
Generic numerical functions.