35 RMSD::RMSD(
Log & log ):
36 alignmentMethod(SIMPLE),
37 myoptimalalignment(NULL),
55 alignmentMethod(oldrmsd.alignmentMethod),
56 reference(oldrmsd.reference),
58 displace(oldrmsd.align),
61 myoptimalalignment(NULL),
77 if (mytype==
"SIMPLE"){
79 log->
printf(
"RMSD IS DONE WITH SIMPLE METHOD(NO ROTATION)\n");
81 else if (mytype==
"OPTIMAL"){
83 log->
printf(
"RMSD IS DONE WITH OPTIMAL ALIGNMENT METHOD\n");
85 else if (mytype==
"OPTIMAL-FAST"){
87 log->
printf(
"RMSD IS DONE WITH OPTIMAL-FAST ALIGNMENT METHOD (fast version, numerically less stable, only valid with align==displace)\n");
89 else plumed_merror(
"unknown RMSD type" + mytype);
105 case SIMPLE: mystring.assign(
"SIMPLE");
break;
106 case OPTIMAL: mystring.assign(
"OPTIMAL");
break;
107 case OPTIMAL_FAST: mystring.assign(
"OPTIMAL-FAST");
break;
113 unsigned n=reference.size();
115 plumed_massert(
align.empty(),
"you should first clear() an RMSD object, then set a new referece");
116 plumed_massert(
displace.empty(),
"you should first clear() an RMSD object, then set a new referece");
122 plumed_massert(this->align.size()==align.size(),
"mismatch in dimension of align/displace arrays");
127 plumed_massert(this->displace.size()==displace.size(),
"mismatch in dimension of align/displace arrays");
131 double RMSD::calculate(
const std::vector<Vector> & positions,std::vector<Vector> &derivatives,
bool squared){
145 bool fastversion=
true;
147 if (align!=displace) fastversion=
false;
161 (*myoptimalalignment).assignP0(positions);
162 ret=(*myoptimalalignment).calculate(squared, derivatives);
173 const std::vector<double> & displace,
174 const std::vector<Vector> & positions,
175 const std::vector<Vector> & reference ,
177 std::vector<Vector> & derivatives,
bool squared) {
181 unsigned n=reference.size();
188 for(
unsigned i=0;i<
n;i++){
190 double dw=displace[i];
193 apositions+=positions[i]*aw;
194 areference+=reference[i]*aw;
195 dpositions+=positions[i]*dw;
196 dreference+=reference[i]*dw;
199 double invdnorm=1.0/dnorm;
200 double invanorm=1.0/anorm;
202 apositions*=invanorm;
203 areference*=invanorm;
204 dpositions*=invdnorm;
205 dreference*=invdnorm;
207 Vector shift=((apositions-areference)-(dpositions-dreference));
208 for(
unsigned i=0;i<
n;i++){
209 Vector d=(positions[i]-apositions)-(reference[i]-areference);
211 derivatives[i]=2*(invdnorm*displace[i]*d+invanorm*align[i]*shift);
219 for(
unsigned i=0;i<
n;i++){derivatives[i]*=(0.5/dist);}
226 const std::vector<double> & displace,
227 const std::vector<Vector> & positions,
228 const std::vector<Vector> & reference ,
229 std::vector<Vector> & derivatives,
bool squared) {
230 plumed_massert(displace==align,
"OPTIMAL_FAST version of RMSD can only be used when displace weights are same as align weights");
234 const unsigned n=reference.size();
240 derivatives.resize(n);
246 for(
unsigned iat=0;iat<
n;iat++){
249 cpositions+=positions[iat]*
w;
250 creference+=reference[iat]*
w;
252 double invnorm=1.0/
norm;
258 for(
unsigned iat=0;iat<
n;iat++){
260 sum00w+=(
dotProduct(positions[iat]-cpositions,positions[iat]-cpositions)
261 +
dotProduct(reference[iat]-creference,reference[iat]-creference))*w;
262 sum01w+=
Tensor(positions[iat]-cpositions,reference[iat]-creference)*
w;
265 double rr00=sum00w*invnorm;
266 Tensor rr01=sum01w*invnorm;
269 m[0][0]=rr00+2.0*(-rr01[0][0]-rr01[1][1]-rr01[2][2]);
270 m[1][1]=rr00+2.0*(-rr01[0][0]+rr01[1][1]+rr01[2][2]);
271 m[2][2]=rr00+2.0*(+rr01[0][0]-rr01[1][1]+rr01[2][2]);
272 m[3][3]=rr00+2.0*(+rr01[0][0]+rr01[1][1]-rr01[2][2]);
273 m[0][1]=2.0*(-rr01[1][2]+rr01[2][1]);
274 m[0][2]=2.0*(+rr01[0][2]-rr01[2][0]);
275 m[0][3]=2.0*(-rr01[0][1]+rr01[1][0]);
276 m[1][2]=2.0*(-rr01[0][1]-rr01[1][0]);
277 m[1][3]=2.0*(-rr01[0][2]-rr01[2][0]);
278 m[2][3]=2.0*(-rr01[1][2]-rr01[2][1]);
286 vector<double> eigenvals;
288 int diagerror=
diagMat(m, eigenvals, eigenvecs );
293 string msg=
"DIAGONALIZATION FAILED WITH ERROR CODE "+sdiagerror;
301 Vector4d q(eigenvecs[0][0],eigenvecs[0][1],eigenvecs[0][2],eigenvecs[0][3]);
307 rotation[0][0]=q[0]*q[0]+q[1]*q[1]-q[2]*q[2]-q[3]*q[3];
308 rotation[1][1]=q[0]*q[0]-q[1]*q[1]+q[2]*q[2]-q[3]*q[3];
309 rotation[2][2]=q[0]*q[0]-q[1]*q[1]-q[2]*q[2]+q[3]*q[3];
310 rotation[0][1]=2*(+q[0]*q[3]+q[1]*q[2]);
311 rotation[0][2]=2*(-q[0]*q[2]+q[1]*q[3]);
312 rotation[1][2]=2*(+q[0]*q[1]+q[2]*q[3]);
313 rotation[1][0]=2*(-q[0]*q[3]+q[1]*q[2]);
314 rotation[2][0]=2*(+q[0]*q[2]+q[1]*q[3]);
315 rotation[2][1]=2*(-q[0]*q[1]+q[2]*q[3]);
317 double prefactor=2.0*invnorm;
320 if(!squared) prefactor*=0.5/sqrt(dist);
330 for(
unsigned iat=0;iat<
n;iat++){
333 Vector d(positions[iat]-shift -
matmul(rotation,reference[iat]));
334 derivatives[iat]= prefactor*align[iat]*d;
335 if(safe) dist+=align[iat]*invnorm*
modulo2(d);
338 if(!squared) dist=sqrt(dist);
std::vector< Vector > reference
Class implementing fixed size matrices of doubles.
TensorGeneric< n, l > matmul(const TensorGeneric< n, m > &a, const TensorGeneric< m, l > &b)
void clear()
clear the structure
Class implementing fixed size vectors of doubles.
double optimalAlignment(const std::vector< double > &align, const std::vector< double > &displace, const std::vector< Vector > &positions, const std::vector< Vector > &reference, std::vector< Vector > &derivatives, bool squared=false)
A class that implements RMSD calculations This is a class that implements the various infrastructure ...
double calculate(const std::vector< Vector > &positions, std::vector< Vector > &derivatives, bool squared=false)
Compute rmsd.
Class containing the log stream.
void setAlign(const std::vector< double > &align)
set weights
RMSD(Log &log)
Constructor.
const std::vector< Vector > & getPositions() const
Access to the position array.
const std::vector< double > & getBeta() const
Access to the beta array.
A class that is intended to include or combine various optimal alignment algorithms.
int printf(const char *fmt,...)
Formatted output with explicit format - a la printf.
const std::vector< double > & getOccupancy() const
Access to the occupancy array.
OptimalAlignment * myoptimalalignment
T dotProduct(const std::vector< T > &A, const std::vector< T > &B)
Calculate the dot product between two vectors.
void setReference(const std::vector< Vector > &reference)
set reference coordinates
double modulo2() const
compute the squared modulo
void set(const PDB &, std::string mytype)
set reference, align and displace from input pdb structure
int diagMat(const Matrix< T > &A, std::vector< double > &eigenvals, Matrix< double > &eigenvecs)
~RMSD()
the destructor needs to delete the myalignment object eventually
double modulo2(const VectorGeneric< n > &v)
std::vector< double > displace
RMSD & operator=(const RMSD &)
assignment
void setDisplace(const std::vector< double > &displace)
set align
std::vector< double > align
double simpleAlignment(const std::vector< double > &align, const std::vector< double > &displace, const std::vector< Vector > &positions, const std::vector< Vector > &reference, Log *&log, std::vector< Vector > &derivatives, bool squared=false)
void setType(std::string mytype)
set the type of alignment we are doing
AlignmentMethod alignmentMethod
T norm(const std::vector< T > &A)
Calculate the dot product between a vector and itself.