faunus
geometry.h
1 #pragma once
2 
3 #include "units.h"
4 #include "core.h"
5 #include "particle.h"
6 #include "tensor.h"
7 #include <concepts>
8 #include <Eigen/Geometry>
9 #include <spdlog/spdlog.h>
10 #include <range/v3/view/cartesian_product.hpp>
11 #include <range/v3/view/zip.hpp>
12 #include <utility>
13 
15 namespace Faunus {
16 
17 class Random;
18 
35 namespace Geometry {
36 
37 // Note: BoundaryFunction and DistanceFunction are defined in core.h
38 
40 enum class Variant
41 {
42  CUBOID = 0,
43  SPHERE,
44  CYLINDER,
45  SLIT,
46  HEXAGONAL,
47  OCTAHEDRON,
48  HYPERSPHERE2D
49 };
50 
52 enum class VolumeMethod
53 {
54  ISOTROPIC,
55  ISOCHORIC,
56  XY,
57  Z,
58  INVALID
59 };
60 
61 NLOHMANN_JSON_SERIALIZE_ENUM(VolumeMethod, {{VolumeMethod::INVALID, nullptr},
62  {VolumeMethod::ISOTROPIC, "isotropic"},
63  {VolumeMethod::ISOCHORIC, "isochoric"},
64  {VolumeMethod::XY, "xy"},
65  {VolumeMethod::Z, "z"}})
66 
67 enum class Coordinates
68 {
69  ORTHOGONAL,
70  ORTHOHEXAGONAL,
71  TRUNC_OCTAHEDRAL,
72  NON3D
73 };
74 enum class Boundary : int
75 {
76  FIXED = 0,
77  PERIODIC = 1
78 };
79 
86 {
87  public:
88  using BoundaryXYZ = Eigen::Matrix<Boundary, 3, 1>;
89  // typedef std::pair<std::string, BoundaryXYZ> BoundaryName;
90  // static const std::map<std::string, BoundaryXYZ> names; //!< boundary names
91 
92  Coordinates coordinates;
93  BoundaryXYZ direction;
94 
95  [[nodiscard]] Eigen::Matrix<bool, 3, 1> isPeriodic() const;
96 
97  explicit BoundaryCondition(Coordinates coordinates = Coordinates::ORTHOGONAL,
98  BoundaryXYZ boundary = {Boundary::FIXED, Boundary::FIXED,
99  Boundary::FIXED})
100  : coordinates(coordinates)
101  , direction(std::move(boundary)) {};
102 };
103 
108 {
109  virtual Point setVolume(double, VolumeMethod = VolumeMethod::ISOTROPIC) = 0;
110  [[nodiscard]] virtual double getVolume(int = 3) const = 0;
111  virtual void boundary(Point&) const = 0;
112  [[nodiscard]] virtual bool collision(const Point&) const = 0;
113  virtual void randompos(Point&, Random&) const = 0;
114  [[nodiscard]] virtual Point vdist(const Point& a,
115  const Point& b) const = 0;
116  [[nodiscard]] virtual Point getLength() const = 0;
117  virtual ~GeometryBase();
118  virtual void to_json(json& j) const = 0;
119  virtual void from_json(const json& j) = 0;
120 
121  [[nodiscard]] inline BoundaryFunction getBoundaryFunc() const
122  {
123  return [this](Point& i) { boundary(i); };
124  }
125 
126  [[nodiscard]] inline DistanceFunction getDistanceFunc() const
127  {
128  return [this](const Point& i, const Point& j) { return vdist(i, j); };
129  }
130 
131  protected:
132  template <typename T = double> [[nodiscard]] inline int anint(T x) const
133  {
134  return int(x > 0.0 ? x + 0.5 : x - 0.5);
135  }
136 
137 };
138 
143 {
144  public:
145  BoundaryCondition boundary_conditions;
146 
147  ~GeometryImplementation() override;
148 
150  [[nodiscard]] virtual std::unique_ptr<GeometryImplementation> clone() const = 0;
151 };
152 
158 {
159  protected:
160  Point box, box_half, box_inv;
161 
162  public:
163  Point getLength() const override;
164  double getVolume(int dim = 3) const final; // finalized to help the compiler with inlining
165  void setLength(const Point& len); // todo shall be protected
166  Point setVolume(double volume, VolumeMethod method = VolumeMethod::ISOTROPIC) override;
167  Point vdist(const Point& a, const Point& b) const override;
168  void boundary(Point& a) const override;
169  bool collision(const Point& a) const override;
170  void randompos(Point& m, Random& rand) const override;
171  void from_json(const json& j) override;
172  void to_json(json& j) const override;
173  explicit Cuboid(const Point& side_length);
174  Cuboid();
175 
176  [[nodiscard]] std::unique_ptr<GeometryImplementation>
177  clone() const override;
178 };
179 
186 class Slit : public Cuboid
187 {
188  using Tbase = Cuboid;
189 
190  public:
191  explicit Slit(const Point& p);
192  Slit(double x, double y, double z);
193  explicit Slit(double x = 0.0);
194 
195  [[nodiscard]] std::unique_ptr<GeometryImplementation>
196  clone() const override;
197 };
198 
203 {
204  protected:
205  double radius;
206 
207  public:
208  Point getLength() const override;
209  double getVolume(int dim = 3) const override;
210  Point setVolume(double volume, VolumeMethod method = VolumeMethod::ISOTROPIC) override;
211  Point vdist(const Point& a, const Point& b) const override;
212 
213  inline static double sqdist(const Point& a, const Point& b) { return (a - b).squaredNorm(); };
214 
215  void boundary(Point& a) const override;
216  bool collision(const Point& point) const override;
217  void randompos(Point& m, Random& rand) const override;
218  void from_json(const json& j) override;
219  void to_json(json& j) const override;
220  explicit Sphere(double radius = 0.0);
221  double getRadius() const;
222 
223  std::unique_ptr<GeometryImplementation>
224  clone() const override;
225 };
226 
227 class Hypersphere2d : public Sphere
228 {
229  public:
230  Point vdist(const Point& a, const Point& b) const override;
231  bool collision(const Point& a) const override;
232  void randompos(Point& m, Random& rand) const override;
233  explicit Hypersphere2d(double radius = 0.0);
234 
235  std::unique_ptr<GeometryImplementation>
236  clone() const override;
237 };
238 
244 {
245  protected:
246  double radius, height;
247 
248  public:
249  Point getLength() const override;
250  double getVolume(int dim = 3) const override;
251  Point setVolume(double volume, VolumeMethod method = VolumeMethod::ISOTROPIC) override;
252  Point vdist(const Point& a, const Point& b) const override;
253  void boundary(Point& a) const override;
254  bool collision(const Point& a) const override;
255  void randompos(Point& m, Random& rand) const override;
256  void from_json(const json& j) override;
257  void to_json(json& j) const override;
258  explicit Cylinder(double radius = 0.0, double height = 0.0);
259 
260  [[nodiscard]] std::unique_ptr<GeometryImplementation>
261  clone() const override;
262 };
263 
272 {
276  static const Eigen::Matrix3d rhombic2cartesian;
277  static const Eigen::Matrix3d cartesian2rhombic;
278 
279  Point box;
280  void set_box(double side, double height);
281 
282  public:
283  Point getLength() const override;
284  double getVolume(int dim = 3) const override;
285  Point setVolume(double volume, VolumeMethod method = VolumeMethod::ISOTROPIC) override;
286  Point vdist(const Point& a, const Point& b) const override;
287  void boundary(Point& a) const override;
288  bool collision(const Point& a) const override;
289  void randompos(Point& m, Random& rand) const override;
290  void from_json(const json& j) override;
291  void to_json(json& j) const override;
292  explicit HexagonalPrism(double side = 0.0, double height = 0.0);
293 
294  [[nodiscard]] std::unique_ptr<GeometryImplementation>
295  clone() const override;
296 
297  [[nodiscard]] double innerRadius() const;
298  [[nodiscard]] double outerRadius() const;
299  [[nodiscard]] double height() const;
300 };
301 
306 {
307  double side;
308 
309  public:
310  Point getLength() const override;
311  double getVolume(int dim = 3) const override;
312  Point setVolume(double volume, VolumeMethod method = VolumeMethod::ISOTROPIC) override;
313  Point vdist(const Point& a, const Point& b) const override;
314  void boundary(Point& a) const override;
315  bool collision(const Point& a) const override;
316  void randompos(Point& pos, Random& rand) const override;
317  void from_json(const json& j) override;
318  void to_json(json& j) const override;
319  explicit TruncatedOctahedron(double side = 0.0);
320 
321  [[nodiscard]] std::unique_ptr<GeometryImplementation>
322  clone() const override;
323 };
324 
342 class Chameleon : public GeometryBase
343 {
344  private:
345  Point len_or_zero = {0, 0, 0};
346  Point len, len_half,
347  len_inv;
348  std::unique_ptr<GeometryImplementation> geometry =
349  nullptr;
350  Variant _type;
351  std::string _name;
352  void
353  makeGeometry(const Variant type =
354  Variant::CUBOID);
355  void _setLength(const Point& l);
356 
357  public:
358  const Variant& type = _type;
359  const std::string& name = _name;
360  double getVolume(int dim = 3) const override;
361  Point setVolume(double, VolumeMethod = VolumeMethod::ISOTROPIC) override;
362  Point getLength() const override;
363  // setLength() needed only for Move::ReplayMove (stems from IO::XTCReader).
364  void setLength(const Point&);
365  void boundary(Point&) const override;
366  Point vdist(const Point&, const Point&) const override;
367  double sqdist(const Point&,
368  const Point&) const;
369  void randompos(Point&, Random&) const override;
370  bool collision(const Point&) const override;
371  void from_json(const json&) override;
372  void to_json(json& j) const override;
373 
374  const BoundaryCondition& boundaryConditions() const;
375 
376  static const std::map<std::string, Variant> names;
377  typedef std::pair<std::string, Variant> VariantName;
378 
379  static VariantName variantName(const std::string& name);
380 
381  static VariantName variantName(const json& j);
382 
383  explicit Chameleon(const Variant type = Variant::CUBOID);
384  Chameleon(const GeometryImplementation& geo, Variant type);
385 
387  Chameleon(const Chameleon& geo);
388 
390  Chameleon& operator=(const Chameleon& geo);
391 
392  [[nodiscard]] std::shared_ptr<GeometryImplementation> asSimpleGeometry() const;
393 };
394 
395 inline void Chameleon::randompos(Point& m, Random& rand) const
396 {
397  assert(geometry);
398  geometry->randompos(m, rand);
399 }
400 
401 inline bool Chameleon::collision(const Point& a) const
402 {
403  assert(geometry);
404  return geometry->collision(a);
405 }
406 
407 inline void Chameleon::boundary(Point& a) const
408 {
409  const auto& boundary_conditions = geometry->boundary_conditions;
410  if (boundary_conditions.coordinates == Coordinates::ORTHOGONAL) {
411  if (boundary_conditions.direction.x() == Boundary::PERIODIC) {
412  if (std::fabs(a.x()) > len_half.x())
413  a.x() -= len.x() * anint(a.x() * len_inv.x());
414  }
415  if (boundary_conditions.direction.y() == Boundary::PERIODIC) {
416  if (std::fabs(a.y()) > len_half.y())
417  a.y() -= len.y() * anint(a.y() * len_inv.y());
418  }
419  if (boundary_conditions.direction.z() == Boundary::PERIODIC) {
420  if (std::fabs(a.z()) > len_half.z())
421  a.z() -= len.z() * anint(a.z() * len_inv.z());
422  }
423  }
424  else {
425  geometry->boundary(a);
426  }
427 }
428 
429 inline Point Chameleon::vdist(const Point& a, const Point& b) const
430 {
431  Point distance;
432  const auto& boundary_conditions = geometry->boundary_conditions;
433  if (boundary_conditions.coordinates == Coordinates::ORTHOGONAL) {
434  distance = a - b;
435  if (boundary_conditions.direction.x() == Boundary::PERIODIC) {
436  if (distance.x() > len_half.x())
437  distance.x() -= len.x();
438  else if (distance.x() < -len_half.x())
439  distance.x() += len.x();
440  }
441  if (boundary_conditions.direction.y() == Boundary::PERIODIC) {
442  if (distance.y() > len_half.y())
443  distance.y() -= len.y();
444  else if (distance.y() < -len_half.y())
445  distance.y() += len.y();
446  }
447  if (boundary_conditions.direction.z() == Boundary::PERIODIC) {
448  if (distance.z() > len_half.z())
449  distance.z() -= len.z();
450  else if (distance.z() < -len_half.z())
451  distance.z() += len.z();
452  }
453  }
454  else {
455  distance = geometry->vdist(a, b);
456  }
457  return distance;
458 }
459 
460 inline double Chameleon::sqdist(const Point& a, const Point& b) const
461 {
462  if (geometry->boundary_conditions.coordinates == Coordinates::ORTHOGONAL) {
463  if constexpr (true) {
464  Point d((a - b).cwiseAbs());
465  return (d - (d.array() > len_half.array())
466  .cast<double>()
467  .matrix()
468  .cwiseProduct(len_or_zero))
469  .squaredNorm();
470  }
471  else { // more readable alternative(?), nearly same speed
472  Point d(a - b);
473  for (int i = 0; i < 3; ++i) {
474  d[i] = std::fabs(d[i]);
475  d[i] = d[i] -
476  len_or_zero[i] *
477  static_cast<double>(d[i] > len_half[i]); // casting faster than branching
478  }
479  return d[0] * d[0] + d[1] * d[1] + d[2] * d[2];
480  }
481  }
482  else {
483  return geometry->vdist(a, b).squaredNorm();
484  }
485 }
486 
487 void to_json(json&, const Chameleon&);
488 void from_json(const json&, Chameleon&);
489 
490 enum class weight
491 {
492  MASS,
493  CHARGE,
494  GEOMETRIC
495 };
496 
504 template <std::ranges::range Positions, std::ranges::range Weights>
506  const Positions& positions, const Weights& weights,
507  Geometry::BoundaryFunction boundary = [](auto&) {}, const Point& shift = Point::Zero())
508 {
509  double weight_sum = 0.0;
510  Point center(0.0, 0.0, 0.0);
511  for (const auto& [position, weight] : ranges::views::zip(positions, weights)) {
512  Point shifted_position = position + shift;
513  boundary(shifted_position);
514  center += weight * shifted_position;
515  weight_sum += weight;
516  }
517  if (std::fabs(weight_sum) > pc::epsilon_dbl) {
518  center = center / weight_sum - shift; // translate back
519  boundary(center);
520  return center;
521  }
522  else {
523  faunus_logger->warn("warning: sum of weights is zero! setting center to (0,0,0)");
524  return Point::Zero();
525  }
526 }
527 
540 template <RequireParticleIterator iterator> //, typename weightFunc>
541 Point weightedCenter(iterator begin, iterator end, BoundaryFunction boundary,
542  std::function<double(const Particle&)> weight_function,
543  const Point& shift = Point::Zero())
544 {
545  namespace rv = std::views;
546  auto particles = std::ranges::subrange(begin, end);
547  auto positions = particles | rv::transform(&Particle::pos);
548  auto weights = particles | rv::transform(weight_function);
549  return weightedCenter(positions, weights, boundary, shift);
550 }
551 
562 template <RequireParticleIterator iterator>
564  iterator begin, iterator end, BoundaryFunction apply_boundary = [](Point&) {},
565  const Point& shift = {0.0, 0.0, 0.0})
566 {
567  auto particle_mass = [](const auto& particle) -> double { return particle.traits().mw; };
568  return weightedCenter(begin, end, apply_boundary, particle_mass, shift);
569 }
570 
577 template <RequireParticleIterator iterator>
579  iterator begin, iterator end, const Point& displacement,
580  BoundaryFunction apply_boundary = [](auto&) {})
581 {
582  std::for_each(begin, end, [&](auto& particle) {
583  particle.pos += displacement;
584  apply_boundary(particle.pos);
585  });
586 }
587 
594 template <RequireParticleIterator iterator>
595 void translateToOrigin(iterator begin, iterator end, BoundaryFunction apply_boundary = [](auto&) {})
596 {
597  Point cm = massCenter(begin, end, apply_boundary);
598  translate(begin, end, -cm, apply_boundary);
599 }
600 
613 template <RequireParticleIterator iterator>
614 void rotate(
615  iterator begin, iterator end, const Eigen::Quaterniond& quaternion,
616  BoundaryFunction apply_boundary = [](auto&) {}, const Point& shift = Point::Zero())
617 {
618  const auto rotation_matrix = quaternion.toRotationMatrix(); // rotation matrix
619  std::for_each(begin, end, [&](auto& particle) {
620  particle.rotate(quaternion, rotation_matrix); // rotate internal coordinates
621  particle.pos += shift;
622  apply_boundary(particle.pos);
623  particle.pos = (quaternion * particle.pos) - shift; // rotate positions
624  apply_boundary(particle.pos);
625  });
626 }
627 
633 template <class Tspace, class GroupIndex>
634 Point trigoCom(const Tspace& spc, const GroupIndex& indices,
635  const std::vector<int>& dir = {0, 1, 2})
636 {
637  if (dir.empty() || dir.size() > 3) {
638  throw std::out_of_range("invalid directions");
639  }
640  namespace rv = std::views;
641  using std::views::join;
642  auto positions = indices | rv::transform([&](auto i) { return spc.groups.at(i); }) | join |
643  rv::transform(&Particle::pos);
644  Point xhi(0, 0, 0);
645  Point zeta(0, 0, 0);
646  Point theta(0, 0, 0);
647  Point com(0, 0, 0);
648  for (auto k : dir) {
649  const auto q = 2.0 * pc::pi / spc.geometry.getLength()[k];
650  int cnt = 0;
651  std::for_each(positions.begin(), positions.end(), [&](auto& position) {
652  theta[k] = position[k] * q;
653  zeta[k] += std::sin(theta[k]);
654  xhi[k] += std::cos(theta[k]);
655  cnt++;
656  });
657  theta[k] =
658  std::atan2(-zeta[k] / static_cast<double>(cnt), -xhi[k] / static_cast<double>(cnt)) +
659  pc::pi;
660  com[k] = spc.geometry.getLength()[k] * theta[k] / (2.0 * pc::pi);
661  }
662  spc.geometry.boundary(com); // is this really needed?
663  return com;
664 }
665 
688 template <RequirePointIterator position_iterator, std::forward_iterator mass_iterator>
690  position_iterator begin, position_iterator end, mass_iterator mass, const Point& mass_center,
691  const BoundaryFunction boundary = [](auto&) {})
692 {
693  Tensor S = Tensor::Zero();
694  double total_mass = 0.0;
695  std::for_each(begin, end, [&](const Point& position) {
696  Point r = position - mass_center; // get rid...
697  boundary(r); // ...of PBC (if any)
698  S += (*mass) * r * r.transpose();
699  total_mass += (*mass);
700  std::advance(mass, 1);
701  });
702  if (total_mass > pc::epsilon_dbl) {
703  return S / total_mass;
704  }
705  throw std::runtime_error("gyration tensor: total mass must be positive");
706 }
707 
726 template <RequireParticleIterator iterator>
728  iterator begin, iterator end, const Point& mass_center,
729  const BoundaryFunction boundary = [](auto&) {})
730 {
731  namespace rv = std::views;
732  auto particles = std::ranges::subrange(begin, end);
733  auto positions = particles | rv::transform(&Particle::pos);
734  auto masses = particles | rv::transform(&Particle::traits) | rv::transform(&AtomData::mw);
735  return gyration(positions.begin(), positions.end(), masses.begin(), mass_center, boundary);
736 }
737 
745 {
746  double gyration_radius_squared = 0.0;
747  double asphericity = 0.0;
748  double acylindricity = 0.0;
749  double relative_shape_anisotropy =
750  0.0;
751  ShapeDescriptors() = default;
752  ShapeDescriptors(const Tensor& gyration_tensor);
754  operator+=(const ShapeDescriptors& other);
755  ShapeDescriptors operator*(const double scale) const;
756 };
757 
758 void to_json(json& j, const ShapeDescriptors& shape);
759 
770 template <RequireParticleIterator iterator>
772  iterator begin, iterator end, const Point origin = Point::Zero(),
773  const BoundaryFunction boundary = [](auto&) {})
774 {
775  Tensor I = Tensor::Zero();
776  std::for_each(begin, end, [&](const Particle& particle) {
777  Point t = particle.pos - origin;
778  boundary(t);
779  I += particle.traits().mw * (t.squaredNorm() * Tensor::Identity() - t * t.transpose());
780  });
781  return I;
782 }
783 
790 template <std::forward_iterator InputIt1, std::forward_iterator InputIt2, typename BinaryOperation>
791 double rootMeanSquareDeviation(InputIt1 begin, InputIt1 end, InputIt2 d_begin,
792  BinaryOperation diff_squared_func)
793 {
794  assert(std::distance(begin, end) > 0);
795  double sq_sum = 0;
796  for (InputIt1 i = begin; i != end; ++i) {
797  sq_sum += diff_squared_func(*i, *d_begin);
798  ++d_begin;
799  }
800  return std::sqrt(sq_sum / std::distance(begin, end));
801 }
802 
817 
828 std::pair<Cuboid, ParticleVector> hexagonalPrismToCuboid(const HexagonalPrism& hexagon,
829  const RequireParticles auto& particles)
830 {
831  Cuboid cuboid({2.0 * hexagon.innerRadius(), 3.0 * hexagon.outerRadius(), hexagon.height()});
832  ParticleVector cuboid_particles;
833  cuboid_particles.reserve(2 * std::distance(particles.begin(), particles.end()));
834  std::copy(particles.begin(), particles.end(),
835  std::back_inserter(cuboid_particles)); // add central hexagon
836 
837  std::transform(particles.begin(), particles.end(), std::back_inserter(cuboid_particles),
838  [&](auto particle) {
839  particle.pos.x() +=
840  hexagon.innerRadius() * (particle.pos.x() > 0.0 ? -1.0 : 1.0);
841  particle.pos.y() +=
842  hexagon.outerRadius() * (particle.pos.y() > 0.0 ? -1.5 : 1.5);
843  assert(cuboid.collision(particle.pos) == false);
844  return particle;
845  }); // add the four corners; i.e. one extra, split hexagon
846  assert(std::fabs(cuboid.getVolume() - 2.0 * hexagon.getVolume()) <= pc::epsilon_dbl);
847  return {cuboid, cuboid_particles};
848 }
849 
876 {
877  static std::vector<Point> fibonacciSphere(size_t);
878 
879  public:
880  std::vector<Eigen::Quaterniond> quaternions_1;
881  std::vector<Eigen::Quaterniond> quaternions_2;
882  std::vector<Eigen::Quaterniond> dihedrals;
883 
884  TwobodyAngles() = default;
885  TwobodyAngles(double angle_resolution);
886 
894  auto quaternionPairs() const
895  {
896  namespace rv = ranges::views;
897  auto product = [](const auto& pair) -> Eigen::Quaterniond {
898  const auto& [q2, q_dihedral] = pair;
899  return q_dihedral * q2; // noncommutative
900  };
901  auto second_body_quaternions =
902  rv::cartesian_product(quaternions_2, dihedrals) | std::views::transform(product);
903  return rv::cartesian_product(quaternions_1, second_body_quaternions);
904  }
905 
906  size_t
907  size() const;
908 };
909 
929 {
930  private:
931  using QuaternionIter = std::vector<Eigen::Quaterniond>::const_iterator;
932  QuaternionIter q_euler1;
933  QuaternionIter q_euler2;
934  QuaternionIter q_dihedral;
935 
936  public:
937  TwobodyAnglesState() = default;
938  TwobodyAnglesState(double angle_resolution);
939  TwobodyAnglesState& advance();
940  std::optional<std::pair<Eigen::Quaterniond, Eigen::Quaterniond>>
941  get();
942 };
943 
944 } // namespace Geometry
945 } // namespace Faunus
nlohmann::json json
JSON object.
Definition: json_support.h:10
void translateToOrigin(iterator begin, iterator end, BoundaryFunction apply_boundary=[](auto &) {})
Move the mass center of the particle range to origin (0,0,0) and wrap to PBC.
Definition: geometry.h:595
Eigen::Vector3d Point
3D vector used for positions, velocities, forces etc.
Definition: coordinates.h:7
std::vector< Eigen::Quaterniond > quaternions_1
Quaternions to explore all Euler angles.
Definition: geometry.h:880
Definition: geometry.h:227
BoundaryFunction getBoundaryFunc() const
Lambda for applying boundary conditions on a point.
Definition: geometry.h:121
Tensor class Tensor class.
Definition: tensor.h:10
std::function< Point(const Point &, const Point &)> DistanceFunction
Function to calculate the (minimum) distance between two points.
Definition: core.h:32
Point pos
Particle position vector.
Definition: particle.h:227
Random number generator.
Definition: random.h:34
double getVolume(int dim=3) const override
Get volume.
Definition: geometry.cpp:345
A base class for various geometries implementations.
Definition: geometry.h:142
Geometry class for spheres, cylinders, cuboids, hexagonal prism, truncated octahedron, slits.
Definition: geometry.h:342
Point weightedCenter(const Positions &positions, const Weights &weights, Geometry::BoundaryFunction boundary=[](auto &) {}, const Point &shift=Point::Zero())
Calculates the (weighted) center for a set of positions.
Definition: geometry.h:505
Tensor gyration(position_iterator begin, position_iterator end, mass_iterator mass, const Point &mass_center, const BoundaryFunction boundary=[](auto &) {})
Calculates a gyration tensor of a range of particles.
Definition: geometry.h:689
The spherical geometry where no periodic boundary condition could be applied.
Definition: geometry.h:202
void rotate(iterator begin, iterator end, const Eigen::Quaterniond &quaternion, BoundaryFunction apply_boundary=[](auto &) {}, const Point &shift=Point::Zero())
Rotate range of particles using a Quaternion.
Definition: geometry.h:614
double T
floating point size
Definition: units.h:73
concept RequireParticles
Concept for a range of particles.
Definition: particle.h:257
DistanceFunction getDistanceFunc() const
Lambda for calculating the (minimum) distance vector between two positions.
Definition: geometry.h:126
Tensor inertia(iterator begin, iterator end, const Point origin=Point::Zero(), const BoundaryFunction boundary=[](auto &) {})
Calculates an inertia tensor of a molecular group.
Definition: geometry.h:771
void randompos(Point &, Random &) const override
Generate random position.
Definition: geometry.h:395
double innerRadius() const
Inner hexagonal radius.
Definition: geometry.cpp:465
The cuboid geometry with periodic boundary conditions possibly applied in all three directions...
Definition: geometry.h:157
double sqdist(const Point &, const Point &) const
(Minimum) squared distance between two points
Definition: geometry.h:460
The hexagonal prism geometry with periodic boundary conditions.
Definition: geometry.h:271
An interface for all geometries.Base class for all geometries.
Definition: geometry.h:107
A legacy class for the cuboid geometry with periodic boundary conditions only in xy directions...
Definition: geometry.h:186
std::vector< Particle > ParticleVector
Storage type for collections of particles.
Definition: particle.h:253
std::function< void(Point &)> BoundaryFunction
Function to apply PBC to a position.
Definition: core.h:30
void boundary(Point &) const override
Apply boundary conditions.
Definition: geometry.h:407
A structure containing a type of boundary condition in each direction.
Definition: geometry.h:85
std::vector< Eigen::Quaterniond > dihedrals
Quaternions to explore all dihedral angles.
Definition: geometry.h:882
double outerRadius() const
Outer radius / side-length.
Definition: geometry.cpp:470
Variant
Geometry variant used for Chameleon.
Definition: geometry.h:40
Particle class for storing positions, id, and other properties.
Definition: particle.h:220
Structure for exploring a discrete, uniform angular space between two rigid bodies.
Definition: geometry.h:875
static const std::map< std::string, Variant > names
Geometry names.
Definition: geometry.h:376
const AtomData & traits() const
get properties from AtomData
Definition: particle.cpp:183
double rootMeanSquareDeviation(InputIt1 begin, InputIt1 end, InputIt2 d_begin, BinaryOperation diff_squared_func)
Root-mean-square deviation of two data sets represented by iterators.
Definition: geometry.h:791
int anint(T x) const
Round to int.
Definition: geometry.h:132
Shape descriptors derived from gyration tensor.
Definition: geometry.h:744
Cell list class templates.
Definition: actions.cpp:11
auto distance(T1 first, T2 last)
Distance between two arbitrary contiguous iterators.
Definition: iteratorsupport.h:7
The cylindrical geometry with periodic boundary conditions in z-axis (the height of the cylinder)...
Definition: geometry.h:243
bool collision(const Point &) const override
Overlap with boundaries.
Definition: geometry.h:401
double height() const
Prism height.
Definition: geometry.cpp:475
The truncated octahedron geoemtry with periodic boundary conditions in all directions.
Definition: geometry.h:305
Structure for exploring a discrete, uniform angular space between two rigid bodies.
Definition: geometry.h:928
Point massCenter(iterator begin, iterator end, BoundaryFunction apply_boundary=[](Point &) {}, const Point &shift={0.0, 0.0, 0.0})
Calculates mass center of range of particles.
Definition: geometry.h:563
Point vdist(const Point &, const Point &) const override
Minimum distance vector b->a.
Definition: geometry.h:429
auto quaternionPairs() const
Iterator to loop over pairs of quaternions to rotate two rigid bodies against each other...
Definition: geometry.h:894
std::vector< Eigen::Quaterniond > quaternions_2
Quaternions to explore all Euler angles.
Definition: geometry.h:881
Point trigoCom(const Tspace &spc, const GroupIndex &indices, const std::vector< int > &dir={0, 1, 2})
Calculate mass center of cluster of particles in unbounded environment.
Definition: geometry.h:634
std::pair< Cuboid, ParticleVector > hexagonalPrismToCuboid(const HexagonalPrism &hexagon, const RequireParticles auto &particles)
Convert particles in hexagonal prism to space-filled cuboid.
Definition: geometry.h:828
void translate(iterator begin, iterator end, const Point &displacement, BoundaryFunction apply_boundary=[](auto &) {})
Definition: geometry.h:578
VolumeMethod
Various methods of volume scaling,.
Definition: geometry.h:52
ParticleVector mapParticlesOnSphere(const ParticleVector &source)
Scale particles to the surface of a sphere.
Definition: geometry.cpp:766