faunus
clustermove.h
1 #pragma once
2 
3 #include "move.h"
4 #include "aux/pairmatrix.h"
5 #include <map>
6 
7 namespace Faunus {
8 namespace move {
9 
14 {
15  private:
16  unsigned long int number_of_samples = 0;
17  bool save_pqr_files = false;
18  bool shape_anisotropy_use_com =
19  true;
20  std::unique_ptr<std::ostream> stream;
21  std::map<size_t, size_t> size_distribution;
22  std::map<size_t, AverageObj<Geometry::ShapeDescriptors>> shape_distribution;
23  std::map<size_t, std::ofstream> pqr_distribution;
24  decltype(pqr_distribution)::iterator
25  findPQRstream(size_t cluster_size);
26 
28  template <RequireGroups Range>
29  Tensor gyrationFromMassCenterPositions(
30  const Range& groups, const Point& mass_center_of_groups,
31  const Geometry::BoundaryFunction boundary = [](auto&) {})
32  {
33  using std::views::transform;
34  auto positions = groups | transform(&Group::mass_center);
35  auto masses = groups | transform(&Group::mass);
36  return Geometry::gyration(positions.begin(), positions.end(), masses.begin(),
37  mass_center_of_groups, boundary);
38  }
39 
41  template <RequireGroups Range>
42  Tensor gyrationFromParticlePositions(
43  const Range& groups, const Point& mass_center_of_groups,
44  const Geometry::BoundaryFunction boundary = [](auto&) {})
45  {
46  using namespace ranges::cpp20::views;
47  auto positions = groups | join | transform(&Particle::pos);
48  auto masses = groups | join | transform(&Particle::traits) | transform(&AtomData::mw);
49  return Geometry::gyration(positions.begin(), positions.end(), masses.begin(),
50  mass_center_of_groups, boundary);
51  }
52 
53  friend void to_json(json&, const ClusterShapeAnalysis&);
54 
55  public:
56  template <RequireGroups Range>
57  void sample(const Range& groups, const Point& mass_center_of_groups, const Space& spc)
58  {
59  const auto cluster_size = std::distance(groups.begin(), groups.end());
60  Tensor gyration_tensor;
61  if (shape_anisotropy_use_com) {
62  gyration_tensor = gyrationFromMassCenterPositions(groups, mass_center_of_groups,
64  }
65  else {
66  gyration_tensor = gyrationFromParticlePositions(groups, mass_center_of_groups,
68  }
69  const auto shape = Geometry::ShapeDescriptors(gyration_tensor);
70  size_distribution[cluster_size]++;
71  shape_distribution[cluster_size] += shape;
72  if (stream) {
73  const auto seed_index =
74  &(*groups.begin()) - &spc.groups.at(0); // index of first molecule in cluster
75  *stream << std::format("{} {} {:.3f}\n", cluster_size, seed_index,
76  shape.relative_shape_anisotropy);
77  }
78  if (save_pqr_files) {
79  auto it = findPQRstream(cluster_size);
80  it->second << std::format("REMARK 0 Sample number = {}\n", number_of_samples)
81  << std::format("REMARK 0 Relative shape anisotropy = {:.3f}\n",
82  shape.relative_shape_anisotropy);
83  PQRWriter pqr;
84  pqr.style = PQRWriter::Style::PQR;
85  pqr.save(it->second, groups, spc.geometry.getLength());
86  }
87  ++number_of_samples;
88  }
89 
90  ClusterShapeAnalysis(bool shape_anisotropy_use_com, const std::string& filename,
91  bool dump_pqr_files);
92  ClusterShapeAnalysis(const json& j);
93 };
94 
95 void to_json(json& j, const ClusterShapeAnalysis& shape);
96 
103 {
104  private:
105  const Space& spc;
106  bool use_mass_center_threshold =
107  true;
108  bool single_layer = false;
109  std::vector<std::string> molecule_names;
110  std::vector<int> molids;
111  std::set<int>
112  satellites;
113  PairMatrix<double, true> thresholds_squared;
114 
115  void parseThresholds(const json& j);
116  double clusterProbability(const Group& group1, const Group& group2) const;
117  void registerSatellites(const std::vector<std::string>&);
118  void updateMoleculeIndex();
119  friend void to_json(json& j, const FindCluster& cluster);
120 
121  public:
122  std::vector<size_t> molecule_index;
123  std::optional<size_t> findSeed(Random& random);
124  std::pair<std::vector<size_t>, bool> findCluster(size_t seed_index);
125  FindCluster(const Space& spc, const json& j);
126 };
127 
128 void to_json(json& j, const FindCluster& cluster);
129 
132 {
133  public:
135  const double displacement_factor;
136  const Point direction;
137  GroupMover(double displacement_factor, const Point& direction);
138 };
139 
142 {
143  public:
144  Point current_displacement = Point::Zero();
145  GroupTranslator(double displacement_factor, const Point& direction = Point::Ones());
146  std::function<void(Group&)> getLambda(Geometry::BoundaryFunction boundary, Random& slump);
147 };
148 
153 class GroupRotator : public GroupMover
154 {
155  private:
156  Eigen::Quaterniond setRandomRotation(Random& random);
157 
158  public:
159  double current_displacement = 0.0;
160  GroupRotator(double displacement_factor, const Point& rotation_axis = Point::Zero());
161  std::function<void(Group&)> getLambda(Geometry::BoundaryFunction boundary,
162  const Point& rotation_origin,
163  Random& random);
164 };
165 
169 class Cluster : public Move
170 {
171  private:
172  std::unique_ptr<FindCluster> find_cluster;
173  std::unique_ptr<ClusterShapeAnalysis> shape_analysis;
174  std::unique_ptr<GroupTranslator> translate;
175  std::unique_ptr<GroupRotator> rotate;
176 
177  std::function<Group&(size_t)> index_to_group;
178  Average<double> average_cluster_size;
179  double bias_energy = 0;
180  unsigned int bias_rejected = 0;
181  unsigned int shape_analysis_interval = 0;
182 
183  Point
184  clusterMassCenter(const std::vector<size_t>& indices) const;
185  void _move(Change& change) override;
186  double
187  bias(Change& change, double old_energy,
188  double new_energy) override;
189  void _reject(Change& change) override;
190  void _accept(Change& change) override;
191  void _to_json(json& j) const override;
192  void _from_json(const json& j) override;
193  void setChange(Change& change, const std::vector<size_t>& group_indices) const;
194  void calculateBias(size_t seed_index, const std::vector<size_t>& cluster_index);
195  void clearForMove();
196 
197  protected:
198  Cluster(Space& spc, std::string_view name, std::string_view cite);
199 
200  public:
201  explicit Cluster(Space& spc);
202 };
203 
204 } // namespace move
205 } // namespace Faunus
Helper class for Cluster move for finding clusters.
Definition: clustermove.h:102
nlohmann::json json
JSON object.
Definition: json_support.h:10
double mass() const
Sum of all active masses.
Definition: group.cpp:96
Point getLength() const override
A minimal containing cubic box.
Definition: geometry.cpp:900
Eigen::Vector3d Point
3D vector used for positions, velocities, forces etc.
Definition: coordinates.h:7
Definition: io.h:304
BoundaryFunction getBoundaryFunc() const
Lambda for applying boundary conditions on a point.
Definition: geometry.h:121
Tensor class Tensor class.
Definition: tensor.h:10
Point pos
Particle position vector.
Definition: particle.h:227
Random random
global instance of Random
Definition: random.cpp:62
Helper class to translate a group.
Definition: clustermove.h:141
Random number generator.
Definition: random.h:34
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
Base class for all moves (MC, Langevin, ...)
Definition: move.h:38
Helper base class for translating and rotating groups.
Definition: clustermove.h:131
Molecular cluster move.
Definition: clustermove.h:169
Helper class to translate a group.
Definition: clustermove.h:153
Helper class for Cluster move for analysing shape and size of found clusters.
Definition: clustermove.h:13
std::function< void(Point &)> BoundaryFunction
Function to apply PBC to a position.
Definition: core.h:30
GeometryType geometry
Container geometry (boundaries, shape, volume)
Definition: space.h:122
const AtomData & traits() const
get properties from AtomData
Definition: particle.cpp:183
Shape descriptors derived from gyration tensor.
Definition: geometry.h:744
Cell list class templates.
Definition: actions.cpp:11
End of Group class.
Definition: group.h:177
Specify changes made to a system.
Definition: space.h:29
Placeholder for atoms and molecules.
Definition: space.h:92
const double displacement_factor
Displacement to be scaled by a random number.
Definition: clustermove.h:135
GroupVector groups
All groups are stored here (i.e. molecules)
Definition: space.h:121
Point mass_center
Mass center.
Definition: group.h:185
Average< double > mean_square_displacement
Must be updated manually.
Definition: clustermove.h:134
const Point direction
Directions or axis of translation or rotation.
Definition: clustermove.h:136
std::vector< size_t > molecule_index
index of all possible molecules to be considered
Definition: clustermove.h:122