Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2020 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 "ActionRegister.h"
24 : #include "tools/Torsion.h"
25 :
26 : #include <string>
27 : #include <cmath>
28 :
29 : using namespace std;
30 :
31 : namespace PLMD {
32 : namespace colvar {
33 :
34 : //+PLUMEDOC COLVAR TORSION
35 : /*
36 : Calculate a torsional angle.
37 :
38 : This command can be used to compute the torsion between four atoms or alternatively
39 : to calculate the angle between two vectors projected on the plane
40 : orthogonal to an axis.
41 :
42 : \par Examples
43 :
44 : This input tells plumed to print the torsional angle between atoms 1, 2, 3 and 4
45 : on file COLVAR.
46 : \plumedfile
47 : t: TORSION ATOMS=1,2,3,4
48 : # this is an alternative, equivalent, definition:
49 : # t: TORSION VECTOR1=2,1 AXIS=2,3 VECTOR2=3,4
50 : PRINT ARG=t FILE=COLVAR
51 : \endplumedfile
52 :
53 : If you are working with a protein you can specify the special named torsion angles \f$\phi\f$, \f$\psi\f$, \f$\omega\f$ and \f$\chi_1\f$
54 : by using TORSION in combination with the \ref MOLINFO command. This can be done by using the following
55 : syntax.
56 :
57 : \plumedfile
58 : #SETTINGS MOLFILE=regtest/basic/rt32/helix.pdb
59 : MOLINFO MOLTYPE=protein STRUCTURE=myprotein.pdb
60 : t1: TORSION ATOMS=@phi-3
61 : t2: TORSION ATOMS=@psi-4
62 : PRINT ARG=t1,t2 FILE=colvar STRIDE=10
63 : \endplumedfile
64 :
65 : Here, \@phi-3 tells plumed that you would like to calculate the \f$\phi\f$ angle in the third residue of the protein.
66 : Similarly \@psi-4 tells plumed that you want to calculate the \f$\psi\f$ angle of the fourth residue of the protein.
67 :
68 : Both of the previous examples specify that the torsion angle should be calculated based on the position of four atoms.
69 : For the first example in particular the assumption when the torsion is specified in this way is that there are chemical
70 : bonds between atoms 1 and 2, atoms 2 and 3 and atoms 3 and 4. In general, however, a torsional angle measures the angle
71 : between two planes, which have at least one vector in common. As shown below, there is thus an alternate, more general, way
72 : through which we can define a torsional angle:
73 :
74 : \plumedfile
75 : t1: TORSION VECTOR1=1,2 AXIS=3,4 VECTOR2=5,6
76 : PRINT ARG=t1 FILE=colvar STRIDE=20
77 : \endplumedfile
78 :
79 : This input instructs PLUMED to calculate the angle between the plane containing the vector connecting atoms 1 and 2 and the vector
80 : connecting atoms 3 and 4 and the plane containing this second vector and the vector connecting atoms 5 and 6. We can even use
81 : PLUMED to calculate the torsional angle between two bond vectors around the z-axis as shown below:
82 :
83 : \plumedfile
84 : a0: FIXEDATOM AT=0,0,0
85 : az: FIXEDATOM AT=0,0,1
86 : t1: TORSION VECTOR1=1,2 AXIS=a0,az VECTOR2=5,6
87 : PRINT ARG=t1 FILE=colvar STRIDE=20
88 : \endplumedfile
89 :
90 :
91 : */
92 : //+ENDPLUMEDOC
93 :
94 1052 : class Torsion : public Colvar {
95 : bool pbc;
96 : bool do_cosine;
97 :
98 : public:
99 : explicit Torsion(const ActionOptions&);
100 : // active methods:
101 : virtual void calculate();
102 : static void registerKeywords(Keywords& keys);
103 : };
104 :
105 8410 : PLUMED_REGISTER_ACTION(Torsion,"TORSION")
106 :
107 529 : void Torsion::registerKeywords(Keywords& keys) {
108 529 : Colvar::registerKeywords( keys );
109 2116 : keys.add("atoms-1","ATOMS","the four atoms involved in the torsional angle");
110 2116 : keys.add("atoms-2","AXIS","two atoms that define an axis. You can use this to find the angle in the plane perpendicular to the axis between the vectors specified using the VECTOR1 and VECTOR2 keywords.");
111 2116 : keys.add("atoms-2","VECTOR1","two atoms that define a vector. You can use this in combination with VECTOR2 and AXIS");
112 2116 : keys.add("atoms-2","VECTOR2","two atoms that define a vector. You can use this in combination with VECTOR1 and AXIS");
113 1587 : keys.addFlag("COSINE",false,"calculate cosine instead of dihedral");
114 529 : }
115 :
116 528 : Torsion::Torsion(const ActionOptions&ao):
117 : PLUMED_COLVAR_INIT(ao),
118 : pbc(true),
119 530 : do_cosine(false)
120 : {
121 : vector<AtomNumber> atoms,v1,v2,axis;
122 1056 : parseAtomList("ATOMS",atoms);
123 1056 : parseAtomList("VECTOR1",v1);
124 1056 : parseAtomList("VECTOR2",v2);
125 1056 : parseAtomList("AXIS",axis);
126 :
127 1056 : parseFlag("COSINE",do_cosine);
128 :
129 528 : bool nopbc=!pbc;
130 1056 : parseFlag("NOPBC",nopbc);
131 528 : pbc=!nopbc;
132 528 : checkRead();
133 :
134 528 : if(atoms.size()==4) {
135 1567 : if(!(v1.empty() && v2.empty() && axis.empty()))
136 2 : error("ATOMS keyword is not compatible with VECTOR1, VECTOR2 and AXIS keywords");
137 1044 : log.printf(" between atoms %d %d %d %d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial(),atoms[3].serial());
138 522 : atoms.resize(6);
139 522 : atoms[5]=atoms[3];
140 522 : atoms[4]=atoms[2];
141 522 : atoms[3]=atoms[2];
142 522 : atoms[2]=atoms[1];
143 5 : } else if(atoms.empty()) {
144 12 : if(!(v1.size()==2 && v2.size()==2 && axis.size()==2))
145 0 : error("VECTOR1, VECTOR2 and AXIS should specify 2 atoms each");
146 8 : log.printf(" between lines %d-%d and %d-%d, projected on the plane orthogonal to line %d-%d\n",
147 : v1[0].serial(),v1[1].serial(),v2[0].serial(),v2[1].serial(),axis[0].serial(),axis[1].serial());
148 4 : atoms.resize(6);
149 4 : atoms[0]=v1[1];
150 4 : atoms[1]=v1[0];
151 4 : atoms[2]=axis[0];
152 4 : atoms[3]=axis[1];
153 4 : atoms[4]=v2[0];
154 4 : atoms[5]=v2[1];
155 2 : } else error("ATOMS should specify 4 atoms");
156 :
157 526 : if(pbc) log.printf(" using periodic boundary conditions\n");
158 108 : else log.printf(" without periodic boundary conditions\n");
159 :
160 526 : if(do_cosine) log.printf(" calculating cosine instead of torsion\n");
161 :
162 526 : addValueWithDerivatives();
163 1578 : if(!do_cosine) setPeriodic("-pi","pi");
164 0 : else setNotPeriodic();
165 526 : requestAtoms(atoms);
166 526 : }
167 :
168 : // calculator
169 28989 : void Torsion::calculate() {
170 :
171 28989 : Vector d0,d1,d2;
172 28989 : if(pbc) makeWhole();
173 28989 : d0=delta(getPosition(1),getPosition(0));
174 28989 : d1=delta(getPosition(3),getPosition(2));
175 28989 : d2=delta(getPosition(5),getPosition(4));
176 28989 : Vector dd0,dd1,dd2;
177 : PLMD::Torsion t;
178 28989 : double torsion=t.compute(d0,d1,d2,dd0,dd1,dd2);
179 28989 : if(do_cosine) {
180 0 : dd0 *= -sin(torsion);
181 0 : dd1 *= -sin(torsion);
182 0 : dd2 *= -sin(torsion);
183 0 : torsion = cos(torsion);
184 : }
185 28989 : setAtomsDerivatives(0,dd0);
186 57978 : setAtomsDerivatives(1,-dd0);
187 : setAtomsDerivatives(2,dd1);
188 57978 : setAtomsDerivatives(3,-dd1);
189 : setAtomsDerivatives(4,dd2);
190 57978 : setAtomsDerivatives(5,-dd2);
191 :
192 28989 : setValue (torsion);
193 : setBoxDerivativesNoPbc();
194 28989 : }
195 :
196 : }
197 5517 : }
198 :
199 :
200 :
|