SSAGES  0.1
A MetaDynamics Package
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Groups Pages
RMSDCV.h
1 
22 #pragma once
23 
24 #include "Snapshot.h"
25 #include "CollectiveVariable.h"
26 #include "../Utility/ReadFile.h"
27 #include <array>
28 #include <Eigen/Dense>
29 #include <Eigen/Eigenvalues>
30 
31 namespace SSAGES
32 {
34 
39  class RMSDCV : public CollectiveVariable
40  {
41  private:
42 
43  std::vector<int> atomids_;
44 
45  std::vector<int> pertatoms_;
46 
48  std::string molecule_;
49 
51  std::vector<Vector3> refcoord_;
52 
55 
56  public:
58 
67  RMSDCV(std::vector<int> atomids, std::string molxyz, bool use_range = false) :
68  atomids_(atomids), molecule_(molxyz)
69  {
70  if(use_range)
71  {
72  if(atomids.size() != 2)
73  { std::cout<<"RMSDCV: If using range, must define only two atoms!"<<std::endl;
74  exit(0);
75  }
76 
77  atomids_.clear();
78 
79  if(atomids[0] >= atomids[1])
80  { std::cout<<"RMSDCV: Please reverse atom range or check that atom range is not equal!"<<std::endl;
81  exit(0);
82  }
83  for(int i = atomids[0]; i <= atomids[1];i++)
84  atomids_.push_back(i);
85  }
86  }
87 
88  // Initialize variables
89  void Initialize(const Snapshot& snapshot) override
90  {
91 
92  const auto& mass = snapshot.GetMasses();
93  const auto& ids = snapshot.GetAtomIDs();
94 
95  // Initialize gradient
96  auto n = snapshot.GetPositions().size();
97  grad_.resize(n);
98  refcoord_.resize(atomids_.size());
99 
100  std::vector<std::array<double,4>> xyzinfo = ReadFile::ReadXYZ(molecule_);
101 
102  if(refcoord_.size() != xyzinfo.size())
103  throw std::runtime_error("Reference structure and input structure atom size do not match!");
104 
105  for(size_t i = 0; i < xyzinfo.size(); i++)
106  {
107  refcoord_[i][0] = xyzinfo[i][1];
108  refcoord_[i][1] = xyzinfo[i][2];
109  refcoord_[i][2] = xyzinfo[i][3];
110  }
111 
112  Vector3 mass_pos_prod_ref;
113  mass_pos_prod_ref.setZero();
114  double total_mass = 0;
115 
116  // Loop through atom positions
117  for( size_t i = 0; i < mass.size(); ++i)
118  {
119  // Loop through pertinent atoms
120  for(size_t j = 0; j < atomids_.size(); j++)
121  {
122  if(ids[i] == atomids_[j])
123  {
124  mass_pos_prod_ref += mass[i]*refcoord_[j];
125  total_mass += mass[i];
126  break;
127  }
128  }
129  }
130 
131  COMref_ = mass_pos_prod_ref/total_mass;
132  }
133 
134  // Evaluate the CV
135  void Evaluate(const Snapshot& snapshot) override
136  {
137  const auto& pos = snapshot.GetPositions();
138  const auto& ids = snapshot.GetAtomIDs();
139  const auto& mass = snapshot.GetMasses();
140  const auto& image_flags = snapshot.GetImageFlags();
141  Vector3 mass_pos_prod = {0,0,0};
142  double total_mass=0;
143  int i;
144  // Loop through atom positions
145  for( size_t i = 0; i < pos.size(); ++i)
146  {
147  grad_[i].setZero();
148  // Loop through pertinent atoms
149  for(size_t j = 0; j < atomids_.size(); j++)
150  {
151  if(ids[i] == atomids_[j])
152  {
153  pertatoms_[j] = i;
154  auto u_coord = snapshot.UnwrapVector(pos[i], image_flags[i]);
155 
156  mass_pos_prod += mass[i]*u_coord;
157  total_mass += mass[i];
158  break;
159  }
160  }
161  }
162 
163 
164  // Calculate center of mass
165  //Vector3 mass_pos_prod;
166  //mass_pos_prod.setZero();
167  total_mass = 0;
168  Vector3 COM_;
169 
170  // Need to unwrap coordinates for appropriate COM calculation.
171 
172  //for( size_t j = 0; j < pertatoms_.size(); ++j)
173  //{
174  // i = pertatoms_[j];
175  // auto u_coord = UnwrapCoordinates(snapshot.GetLatticeConstants(), image_flags[i], pos[i]);
176 
177  // mass_pos_prod[0] += mass[i]*u_coord[0];
178  // mass_pos_prod[1] += mass[i]*u_coord[1];
179  // mass_pos_prod[2] += mass[i]*u_coord[2];
180  // total_mass += mass[i];
181  //}
182 
183  COM_ = mass_pos_prod/total_mass;
184 
185  // Build correlation matrix
186  Matrix3 R;
187 
188  Vector3 diff;
189  Vector3 diff_ref;
190  double part_RMSD = 0;
191 
192  for( size_t j = 0; j < pertatoms_.size(); ++j)
193  {
194  i = pertatoms_[j];
195  auto u_coord = snapshot.UnwrapVector(pos[i], image_flags[i]);
196 
197  diff = u_coord -COM_;
198  diff_ref = refcoord_[j] - COMref_;
199 
200  R(0,0) += diff[0]*diff_ref[0];
201  R(0,1) += diff[0]*diff_ref[1];
202  R(0,2) += diff[0]*diff_ref[2];
203  R(1,0) += diff[1]*diff_ref[0];
204  R(1,1) += diff[1]*diff_ref[1];
205  R(1,2) += diff[1]*diff_ref[2];
206  R(2,0) += diff[2]*diff_ref[0];
207  R(2,1) += diff[2]*diff_ref[1];
208  R(2,2) += diff[2]*diff_ref[2];
209 
210 
211  auto normdiff2 = diff.norm()*diff.norm();
212  auto normref2 = diff_ref.norm()*diff_ref.norm();
213 
214  part_RMSD += (normdiff2 + normref2);
215  }
216 
217  Eigen::Matrix4d F;
218  F(0,0)= R(0,0) + R(1,1) + R(2,2);
219  F(1,0)= R(1,2) - R(2,1);
220  F(2,0)= R(2,0) - R(0,2);
221  F(3,0)= R(0,1) - R(1,0);
222 
223  F(0,1)= R(1,2) - R(2,1);
224  F(1,1)= R(0,0) - R(1,1) - R(2,2);
225  F(2,1)= R(0,1) + R(1,0);
226  F(3,1)= R(0,2) + R(2,0);
227 
228  F(0,2)= R(2,0) - R(0,2);
229  F(1,2)= R(0,1) - R(1,0);
230  F(2,2)= -R(0,0) + R(1,1) - R(2,2);
231  F(3,2)= R(1,2) + R(2,1);
232 
233  F(0,3)= R(0,1) - R(1,0);
234  F(1,3)= R(0,2) - R(2,0);
235  F(2,3)= R(1,2) - R(2,1);
236  F(3,3)= -R(0,0) - R(1,1) + R(2,2);
237 
238  //Find eigenvalues
239  Eigen::EigenSolver<Eigen::Matrix4d> es(F);
240  //EigenSolver<F> es;
241  //es.compute(F);
242  //auto max_lambda = es.eigenvalues().maxCoeff();
243  auto lambda = es.eigenvalues().real();
244  //double max_lambda;
245  auto max_lambda = lambda.maxCoeff();
246  int column;
247 
248 
249  for (i =0; i < 4; ++i)
250  if(es.eigenvalues()[i] == max_lambda)
251  column=i;
252 
253  // Calculate RMSD
254 
255 
256  auto RMSD = sqrt((part_RMSD - (2*max_lambda))/(atomids_.size()));
257 
258  val_ = RMSD;
259 
260  // Calculate gradient
261 
262  auto eigenvector = es.eigenvectors().col(column);
263 
264  auto q0 = eigenvector[0].real();
265  auto q1 = eigenvector[1].real();
266  auto q2 = eigenvector[2].real();
267  auto q3 = eigenvector[3].real();
268 
269  Matrix3 RotMatrix(3,3);
270  RotMatrix(0,0) = q0*q0+q1*q1-q2*q2-q3*q3;
271  RotMatrix(1,0) = 2*(q1*q2+q0*q3);
272  RotMatrix(2,0) = 2*(q1*q3-q0*q2);
273 
274  RotMatrix(0,1) = 2*(q1*q2-q0*q3);
275  RotMatrix(1,1) = q0*q0-q1*q1+q2*q2-q3*q3;
276  RotMatrix(2,1) = 1*(q2*q3+q0*q1);
277 
278  RotMatrix(0,2) = 2*(q1*q3+q0*q2);
279  RotMatrix(1,2) = 2*(q2*q3-q0*q1);
280  RotMatrix(2,2) = q0*q0-q1*q1-q2*q2+q3*q3;
281 
282  //double trans[3];
283  for(size_t j=0; j<pertatoms_.size();++j)
284  {
285  auto trans = RotMatrix.transpose()*refcoord_[j];
286 
287  i = pertatoms_[j];
288  auto u_coord = pos[i]; //UnwrapCoordinates(snapshot.GetLatticeConstants(), image_flags[i], pos[i]);
289 
290  grad_[i][0] = (u_coord[0] - trans[0])/((atomids_.size())*val_);
291  grad_[i][1] = (u_coord[1] - trans[1])/((atomids_.size())*val_);
292  grad_[i][2] = (u_coord[2] - trans[2])/((atomids_.size())*val_);
293  }
294  }
295  };
296 }
std::vector< int > pertatoms_
Array to store indicies of atoms of interest.
Definition: RMSDCV.h:45
Eigen::Matrix3d Matrix3
3x3 matrix.
Definition: types.h:42
Vector3 COMref_
Center of mass of reference.
Definition: RMSDCV.h:54
std::string molecule_
Name of model structure.
Definition: RMSDCV.h:48
Class containing a snapshot of the current simulation in time.
Definition: Snapshot.h:43
RMSDCV(std::vector< int > atomids, std::string molxyz, bool use_range=false)
Constructor.
Definition: RMSDCV.h:67
std::vector< Vector3 > grad_
Gradient vector dCv/dxi.
const Label & GetAtomIDs() const
Access the atom IDs.
Definition: Snapshot.h:541
const std::vector< double > & GetMasses() const
Const access to the particle masses.
Definition: Snapshot.h:378
Eigen::Vector3d Vector3
Three-dimensional vector.
Definition: types.h:33
double val_
Current value of CV.
std::vector< int > atomids_
IDs of the atoms used for Rg calculation.
Definition: RMSDCV.h:43
Abstract class for a collective variable.
static std::vector< std::array< double, 4 > > ReadXYZ(std::string FileName)
Read xyz file.
Definition: ReadFile.h:70
std::vector< Vector3 > refcoord_
Store reference structure coordinates.
Definition: RMSDCV.h:51
const std::vector< Vector3 > & GetPositions() const
Access the particle positions.
Definition: Snapshot.h:323
Collective variable to calculate root mean square displacement.
Definition: RMSDCV.h:39