24 #include "CVs/CollectiveVariable.h"
25 #include "Validator/ObjectRequirement.h"
26 #include "Drivers/DriverException.h"
29 #include "Utility/ReadFile.h"
31 #include <Eigen/Dense>
32 #include <Eigen/Eigenvalues>
68 RMSDCV(
const Label& atomids, std::string xyzfile,
bool use_range =
false) :
73 if(atomids.size() != 2)
76 "RMSDCV: With use_range, expected 2 atoms, but found " +
77 std::to_string(atomids.size()) +
"."
82 if(atomids[0] >= atomids[1])
85 "RMSDCV: Atom range must be strictly increasing."
88 for(
int i = atomids[0]; i <= atomids[1]; ++i)
101 const auto& masses = snapshot.
GetMasses();
105 std::vector<int> found(n, 0);
106 for(
size_t i = 0; i < n; ++i)
111 MPI_Allreduce(MPI_IN_PLACE, found.data(), n, MPI_INT, MPI_SUM, snapshot.
GetCommunicator());
112 unsigned ntot = std::accumulate(found.begin(), found.end(), 0, std::plus<int>());
116 "RMSDCV: Expected to find " + std::to_string(n) +
117 " atoms, but only found " + std::to_string(ntot) +
"."
129 for(
size_t i = 0; i < xyzinfo.size(); ++i)
132 if(
id == -1)
continue;
133 for(
size_t j = 0; j <
atomids_.size(); ++j)
144 Vector3 mass_pos_prod_ref = Vector3::Zero();
145 double total_mass = 0;
149 mass_pos_prod_ref += masses[i]*
refcoord_[i];
150 total_mass += masses[i];
152 MPI_Allreduce(MPI_IN_PLACE, mass_pos_prod_ref.data(), mass_pos_prod_ref.size(), MPI_DOUBLE, MPI_SUM, snapshot.
GetCommunicator());
153 MPI_Allreduce(MPI_IN_PLACE, &total_mass, 1, MPI_DOUBLE, MPI_SUM, snapshot.
GetCommunicator());
155 COMref_ = mass_pos_prod_ref/total_mass;
169 const auto& masses = snapshot.
GetMasses();
171 double masstot = snapshot.
TotalMass(idx);
184 double part_RMSD = 0;
191 R.noalias() += masses[i]*diff*diff_ref.transpose();
193 part_RMSD += masses[i]*(diff.squaredNorm() + diff_ref.squaredNorm());
195 MPI_Allreduce(MPI_IN_PLACE, R.data(), R.size(), MPI_DOUBLE, MPI_SUM, snapshot.
GetCommunicator());
196 MPI_Allreduce(MPI_IN_PLACE, &part_RMSD, 1, MPI_DOUBLE, MPI_SUM, snapshot.
GetCommunicator());
198 part_RMSD /= masstot;
201 F(0,0) = R(0,0) + R(1,1) + R(2,2);
202 F(1,0) = R(1,2) - R(2,1);
203 F(2,0) = R(2,0) - R(0,2);
204 F(3,0) = R(0,1) - R(1,0);
207 F(1,1) = R(0,0) - R(1,1) - R(2,2);
208 F(2,1) = R(0,1) + R(1,0);
209 F(3,1) = R(0,2) + R(2,0);
213 F(2,2) = -R(0,0) + R(1,1) - R(2,2);
214 F(3,2) = R(1,2) + R(2,1);
219 F(3,3) = -R(0,0) - R(1,1) + R(2,2);
222 Eigen::SelfAdjointEigenSolver<Eigen::Matrix4d> es(F);
223 auto max_lambda = es.eigenvalues().real()[3];
226 val_ = sqrt(part_RMSD - (2*max_lambda));
229 if(
val_ == 0)
return;
232 auto ev = es.eigenvectors().real().col(3);
233 auto q = Eigen::Quaterniond(ev(0),ev(1),ev(2),ev(3));
234 Matrix3 RotMatrix = q.toRotationMatrix();
244 static RMSDCV*
Build(
const Json::Value& json,
const std::string& path)
248 Json::CharReaderBuilder rbuilder;
249 Json::CharReader* reader = rbuilder.newCharReader();
251 reader->parse(JsonSchema::RMSDCV.c_str(),
252 JsonSchema::RMSDCV.c_str() + JsonSchema::RMSDCV.size(),
254 validator.
Parse(schema, path);
261 std::vector<int> atom_ids;
262 for(
auto& s : json[
"atom_ids"])
263 atom_ids.push_back(s.asInt());
264 auto reference = json[
"reference"].asString();
265 auto use_range = json.get(
"use_range",
false).asBool();
267 return new RMSDCV(atom_ids, reference, use_range);
Requirements on an object.
virtual void Parse(Value json, const std::string &path) override
Parse JSON value to generate Requirement(s).
virtual void Validate(const Value &json, const std::string &path) override
Validate JSON value.
std::vector< std::string > GetErrors()
Get list of error messages.
bool HasErrors()
Check if errors have occured.
Exception to be thrown when building the Driver fails.
Abstract class for a collective variable.
std::vector< Vector3 > grad_
Gradient vector dCv/dxi.
double val_
Current value of CV.
Collective variable to calculate root mean square displacement.
std::string xyzfile_
Name of model structure.
void Initialize(const Snapshot &snapshot) override
Initialize necessary variables.
Label atomids_
IDs of the atoms used for RMSD calculation.
RMSDCV(const Label &atomids, std::string xyzfile, bool use_range=false)
Constructor.
static RMSDCV * Build(const Json::Value &json, const std::string &path)
Set up collective variable.
std::vector< Vector3 > refcoord_
Store reference structure coordinates.
Vector3 COMref_
Center of mass of reference.
void Evaluate(const Snapshot &snapshot) override
Evaluate the CV.
static std::vector< std::array< double, 4 > > ReadXYZ(std::string FileName)
Read xyz file.
Class containing a snapshot of the current simulation in time.
unsigned GetNumAtoms() const
Get number of atoms in this snapshot.
void GetLocalIndices(const Label &ids, Label *indices) const
const mxx::comm & GetCommunicator() const
Get communicator for walker.
int GetLocalIndex(int id) const
Gets the local atom index corresponding to an atom ID.
double TotalMass(const Label &indices) const
Compute the total mass of a group of particles based on index.
const std::vector< Vector3 > & GetPositions() const
Access the particle positions.
const std::vector< double > & GetMasses() const
Const access to the particle masses.
Vector3 CenterOfMass(const Label &indices, bool mass_weight=true) const
Compute center of mass of a group of atoms based on index.
void ApplyMinimumImage(Vector3 *v) const
Apply minimum image to a vector.
Eigen::Matrix3d Matrix3
3x3 matrix.
Eigen::Vector3d Vector3
Three-dimensional vector.
std::vector< int > Label
List of integers.