Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2019 The plumed team
3 : (see the PEOPLE file at the root of the distribution for a list of names)
4 :
5 : See http://www.plumed.org for more information.
6 :
7 : This file is part of plumed, version 2.
8 :
9 : plumed is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : plumed is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 : #include "Colvar.h"
23 : #include "core/PlumedMain.h"
24 : #include "ActionRegister.h"
25 : #include "tools/PDB.h"
26 : #include "reference/RMSDBase.h"
27 : #include "reference/MetricRegister.h"
28 : #include "core/Atoms.h"
29 :
30 :
31 : using namespace std;
32 :
33 : namespace PLMD {
34 : namespace colvar {
35 :
36 : class RMSD : public Colvar {
37 :
38 : MultiValue myvals;
39 : ReferenceValuePack mypack;
40 : PLMD::RMSDBase* rmsd;
41 : bool squared;
42 :
43 : public:
44 : explicit RMSD(const ActionOptions&);
45 : ~RMSD();
46 : virtual void calculate();
47 : static void registerKeywords(Keywords& keys);
48 : };
49 :
50 :
51 : using namespace std;
52 :
53 : //+PLUMEDOC DCOLVAR RMSD
54 : /*
55 : Calculate the RMSD with respect to a reference structure.
56 :
57 : The aim with this colvar it to calculate something like:
58 :
59 : \f[
60 : d(X,X') = \vert X-X' \vert
61 : \f]
62 :
63 : where \f$ X \f$ is the instantaneous position of all the atoms in the system and
64 : \f$ X' \f$ is the positions of the atoms in some reference structure provided as input.
65 : \f$ d(X,X') \f$ thus measures the distance all the atoms have moved away from this reference configuration.
66 : Oftentimes, it is only the internal motions of the structure - i.e. not the translations of the center of
67 : mass or the rotations of the reference frame - that are interesting. Hence, when calculating the
68 : the root-mean-square deviation between the atoms in two configurations
69 : you must first superimpose the two structures in some way. At present PLUMED provides two distinct ways
70 : of performing this superposition. The first method is applied when you use TYPE=SIMPLE in the input
71 : line. This instruction tells PLUMED that the root mean square deviation is to be calculated after the
72 : positions of the geometric centers in the reference and instantaneous configurations are aligned. In
73 : other words \f$d(X,x')\f$ is to be calculated using:
74 :
75 : \f[
76 : d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z} \frac{w_i}{\sum_j w_j}( X_{i,\alpha}-com_\alpha(X)-{X'}_{i,\alpha}+com_\alpha(X') )^2 }
77 : \f]
78 : with
79 : \f[
80 : com_\alpha(X)= \sum_i \frac{w'_{i}}{\sum_j w'_j}X_{i,\alpha}
81 : \f]
82 : and
83 : \f[
84 : com_\alpha(X')= \sum_i \frac{w'_{i}}{\sum_j w'_j}X'_{i,\alpha}
85 : \f]
86 : Obviously, \f$ com_\alpha(X) \f$ and \f$ com_\alpha(X') \f$ represent the positions of the center of mass in the reference
87 : and instantaneous configurations if the weights $w'$ are set equal to the atomic masses. If the weights are all set equal to
88 : one, however, \f$com_\alpha(X) \f$ and \f$ com_\alpha(X') \f$ are the positions of the geometric centers.
89 : Notice that there are sets of weights: \f$ w' \f$ and \f$ w \f$. The first is used to calculate the position of the center of mass
90 : (so it determines how the atoms are \e aligned). Meanwhile, the second is used when calculating how far the atoms have actually been
91 : \e displaced. These weights are assigned in the reference configuration that you provide as input (i.e. the appear in the input file
92 : to this action that you set using REFERENCE=whatever.pdb). This input reference configuration consists of a simple pdb file
93 : containing the set of atoms for which you want to calculate the RMSD displacement and their positions in the reference configuration.
94 : It is important to note that the indices in this pdb need to be set correctly. The indices in this file determine the indices of the
95 : instantaneous atomic positions that are used by PLUMED when calculating this colvar. As such if you want to calculate the RMSD distance
96 : moved by the 1st, 4th, 6th and 28th atoms in the MD codes input file then the indices of the corresponding refernece positions in this pdb
97 : file should be set equal to 1, 4, 6 and 28.
98 :
99 : The pdb input file should also contain the values of \f$w\f$ and \f$w'\f$. In particular, the OCCUPANCY column (the first column after the coordinates)
100 : is used provides the values of \f$ w'\f$ that are used to calculate the position of the centre of mass. The BETA column (the second column
101 : after the Cartesian coordinates) is used to provide the \f$ w \f$ values which are used in the the calculation of the displacement.
102 : Please note that it is possible to use fractional values for beta and for the occupancy. However, we recommend you only do this when
103 : you really know what you are doing however as the results can be rather strange.
104 :
105 : In PDB files the atomic coordinates and box lengths should be in Angstroms unless
106 : you are working with natural units. If you are working with natural units then the coordinates
107 : should be in your natural length unit. For more details on the PDB file format visit http://www.wwpdb.org/docs.html.
108 : Make sure your PDB file is correclty formatted as explained \ref pdbreader "in this page".
109 :
110 : A different method is used to calculate the RMSD distance when you use TYPE=OPTIMAL on the input line. In this case the root mean square
111 : deviation is calculated after the positions of geometric centers in the reference and instantaneous configurations are aligned AND after
112 : an optimal alignment of the two frames is performed so that motion due to rotation of the reference frame between the two structures is
113 : removed. The equation for \f$d(X,X')\f$ in this case reads:
114 :
115 : \f[
116 : d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z} \frac{w_i}{\sum_j w_j}[ X_{i,\alpha}-com_\alpha(X)- \sum_\beta M(X,X',w')_{\alpha,\beta}({X'}_{i,\beta}-com_\beta(X')) ]^2 }
117 : \f]
118 :
119 : where \f$ M(X,X',w') \f$ is the optimal alignment matrix which is calculated using the Kearsley \cite kearsley algorithm. Again different sets of
120 : weights are used for the alignment (\f$w'\f$) and for the displacement calcuations (\f$w\f$).
121 : This gives a great deal of flexibility as it allows you to use a different sets of atoms (which may or may not overlap) for the alignment and displacement
122 : parts of the calculation. This may be very useful when you want to calculate how a ligand moves about in a protein cavity as you can use the protein as a reference
123 : system and do no alignment of the ligand.
124 :
125 : (Note: when this form of RMSD is used to calculate the secondary structure variables (\ref ALPHARMSD, \ref ANTIBETARMSD and \ref PARABETARMSD
126 : all the atoms in the segment are assumed to be part of both the alignment and displacement sets and all weights are set equal to one)
127 :
128 : Please note that there are a number of other methods for calculating the distance between the instantaneous configuration and a reference configuration
129 : that are available in plumed. More information on these various methods can be found in the section of the manual on \ref dists.
130 :
131 : \warning
132 : The molecule used for \ref RMSD calculation should be whole (both atoms used in alignment and in displacement calculation).
133 : In case it is broken by the host MD code, please use \ref WHOLEMOLECULES to reconstruct it before \ref RMSD calculation.
134 :
135 : \par Examples
136 :
137 : The following tells plumed to calculate the RMSD distance between
138 : the positions of the atoms in the reference file and their instantaneous
139 : position. The Kearseley algorithm is used so this is done optimally.
140 :
141 : \plumedfile
142 : RMSD REFERENCE=file.pdb TYPE=OPTIMAL
143 : \endplumedfile
144 :
145 : ...
146 :
147 : */
148 : //+ENDPLUMEDOC
149 :
150 6528 : PLUMED_REGISTER_ACTION(RMSD,"RMSD")
151 :
152 77 : void RMSD::registerKeywords(Keywords& keys) {
153 77 : Colvar::registerKeywords(keys);
154 308 : keys.add("compulsory","REFERENCE","a file in pdb format containing the reference structure and the atoms involved in the CV.");
155 385 : keys.add("compulsory","TYPE","SIMPLE","the manner in which RMSD alignment is performed. Should be OPTIMAL or SIMPLE.");
156 231 : keys.addFlag("SQUARED",false," This should be setted if you want MSD instead of RMSD ");
157 154 : keys.remove("NOPBC");
158 77 : }
159 :
160 76 : RMSD::RMSD(const ActionOptions&ao):
161 82 : PLUMED_COLVAR_INIT(ao),myvals(1,0), mypack(0,0,myvals),squared(false)
162 : {
163 : string reference;
164 152 : parse("REFERENCE",reference);
165 : string type;
166 76 : type.assign("SIMPLE");
167 152 : parse("TYPE",type);
168 152 : parseFlag("SQUARED",squared);
169 :
170 76 : checkRead();
171 :
172 :
173 76 : addValueWithDerivatives(); setNotPeriodic();
174 152 : PDB pdb;
175 :
176 : // read everything in ang and transform to nm if we are not in natural units
177 152 : if( !pdb.read(reference,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()) )
178 7 : error("missing input file " + reference );
179 :
180 75 : rmsd = metricRegister().create<RMSDBase>(type,pdb);
181 :
182 : std::vector<AtomNumber> atoms;
183 71 : rmsd->getAtomRequests( atoms );
184 : // rmsd->setNumberOfAtoms( atoms.size() );
185 71 : requestAtoms( atoms );
186 :
187 : // Setup the derivative pack
188 141 : myvals.resize( 1, 3*atoms.size()+9 ); mypack.resize( 0, atoms.size() );
189 9197 : for(unsigned i=0; i<atoms.size(); ++i) mypack.setAtomIndex( i, i );
190 :
191 140 : log.printf(" reference from file %s\n",reference.c_str());
192 140 : log.printf(" which contains %d atoms\n",getNumberOfAtoms());
193 140 : log.printf(" method for alignment : %s \n",type.c_str() );
194 70 : if(squared)log.printf(" chosen to use SQUARED option for MSD instead of RMSD\n");
195 70 : }
196 :
197 210 : RMSD::~RMSD() {
198 70 : delete rmsd;
199 140 : }
200 :
201 :
202 : // calculator
203 40484 : void RMSD::calculate() {
204 80968 : double r=rmsd->calculate( getPositions(), mypack, squared );
205 :
206 40484 : setValue(r);
207 29232478 : for(unsigned i=0; i<getNumberOfAtoms(); i++) setAtomsDerivatives( i, mypack.getAtomDerivative(i) );
208 :
209 40484 : Tensor virial; plumed_dbg_assert( !mypack.virialWasSet() );
210 40484 : setBoxDerivativesNoPbc();
211 40484 : }
212 :
213 : }
214 4839 : }
215 :
216 :
217 :
|