Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2012-2023 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 "core/ActionShortcut.h"
23 : #include "core/ActionRegister.h"
24 : #include "MultiColvarShortcuts.h"
25 : #include <string>
26 : #include <cmath>
27 :
28 : //+PLUMEDOC MCOLVAR DISTANCES
29 : /*
30 : Calculate the distances between multiple piars of atoms
31 :
32 : \par Examples
33 :
34 : */
35 : //+ENDPLUMEDOC
36 :
37 : //+PLUMEDOC MCOLVAR XDISTANCES
38 : /*
39 : Calculate the x components of the vectors connecting one or many pairs of atoms.
40 : You can then calculate functions of the distribution of values such as the minimum, the number less than a certain quantity and so on.
41 :
42 : \par Examples
43 :
44 : The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and
45 : the x-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then
46 : printed
47 : \plumedfile
48 : d1: XDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1}
49 : PRINT ARG=d1.min
50 : \endplumedfile
51 : (See also \ref PRINT).
52 :
53 :
54 : The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and
55 : the x-component of the vector connecting atom 1 to atom 2. The number of values that are
56 : less than 0.1nm is then printed to a file.
57 : \plumedfile
58 : d1: XDISTANCES ATOMS1=3,5 ATOMS2=1,2 LESS_THAN={RATIONAL R_0=0.1}
59 : PRINT ARG=d1.lessthan
60 : \endplumedfile
61 : (See also \ref PRINT \ref switchingfunction).
62 :
63 : The following input tells plumed to calculate the x-components of all the distinct vectors that can be created
64 : between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3).
65 : The average of these quantities is then calculated.
66 : \plumedfile
67 : d1: XDISTANCES GROUP=1-3 MEAN
68 : PRINT ARG=d1.mean
69 : \endplumedfile
70 : (See also \ref PRINT)
71 :
72 : The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB.
73 : In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values
74 : more than 0.1 is then printed to a file.
75 : \plumedfile
76 : d1: XDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1}
77 : PRINT ARG=d1.morethan
78 : \endplumedfile
79 : (See also \ref PRINT \ref switchingfunction)
80 : */
81 : //+ENDPLUMEDOC
82 :
83 :
84 : //+PLUMEDOC MCOLVAR YDISTANCES
85 : /*
86 : Calculate the y components of the vectors connecting one or many pairs of atoms.
87 : You can then calculate functions of the distribution of values such as the minimum, the number less than a certain quantity and so on.
88 :
89 : \par Examples
90 :
91 : The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and
92 : the y-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then
93 : printed
94 : \plumedfile
95 : d1: YDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1}
96 : PRINT ARG=d1.min
97 : \endplumedfile
98 : (See also \ref PRINT).
99 :
100 :
101 : The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and
102 : the y-component of the vector connecting atom 1 to atom 2. The number of values that are
103 : less than 0.1nm is then printed to a file.
104 : \plumedfile
105 : d1: YDISTANCES ATOMS1=3,5 ATOMS2=1,2 LESS_THAN={RATIONAL R_0=0.1}
106 : PRINT ARG=d1.lessthan
107 : \endplumedfile
108 : (See also \ref PRINT \ref switchingfunction).
109 :
110 : The following input tells plumed to calculate the y-components of all the distinct vectors that can be created
111 : between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3).
112 : The average of these quantities is then calculated.
113 : \plumedfile
114 : d1: YDISTANCES GROUP=1-3 MEAN
115 : PRINT ARG=d1.mean
116 : \endplumedfile
117 : (See also \ref PRINT)
118 :
119 : The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB.
120 : In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values
121 : more than 0.1 is then printed to a file.
122 : \plumedfile
123 : d1: YDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1}
124 : PRINT ARG=d1.morethan
125 : \endplumedfile
126 : (See also \ref PRINT \ref switchingfunction)
127 :
128 : */
129 : //+ENDPLUMEDOC
130 :
131 : //+PLUMEDOC MCOLVAR ZDISTANCES
132 : /*
133 : Calculate the z components of the vectors connecting one or many pairs of atoms.
134 : You can then calculate functions of the distribution of values such as the minimum, the number less than a certain quantity and so on.
135 :
136 : \par Examples
137 :
138 : The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and
139 : the z-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then
140 : printed
141 : \plumedfile
142 : d1: ZDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1}
143 : PRINT ARG=d1.min
144 : \endplumedfile
145 : (See also \ref PRINT).
146 :
147 :
148 : The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and
149 : the z-component of the vector connecting atom 1 to atom 2. The number of values that are
150 : less than 0.1nm is then printed to a file.
151 : \plumedfile
152 : d1: ZDISTANCES ATOMS1=3,5 ATOMS2=1,2 LESS_THAN={RATIONAL R_0=0.1}
153 : PRINT ARG=d1.lessthan
154 : \endplumedfile
155 : (See also \ref PRINT \ref switchingfunction).
156 :
157 : The following input tells plumed to calculate the z-components of all the distinct vectors that can be created
158 : between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3).
159 : The average of these quantities is then calculated.
160 : \plumedfile
161 : d1: ZDISTANCES GROUP=1-3 MEAN
162 : PRINT ARG=d1.mean
163 : \endplumedfile
164 : (See also \ref PRINT)
165 :
166 : The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB.
167 : In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values
168 : more than 0.1 is then printed to a file.
169 : \plumedfile
170 : d1: ZDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1}
171 : PRINT ARG=d1.morethan
172 : \endplumedfile
173 : (See also \ref PRINT \ref switchingfunction)
174 :
175 : */
176 : //+ENDPLUMEDOC
177 :
178 :
179 : namespace PLMD {
180 : namespace multicolvar {
181 :
182 : class Distances : public ActionShortcut {
183 : public:
184 : static void registerKeywords(Keywords& keys);
185 : explicit Distances(const ActionOptions&);
186 : };
187 :
188 : PLUMED_REGISTER_ACTION(Distances,"DISTANCES")
189 : PLUMED_REGISTER_ACTION(Distances,"XDISTANCES")
190 : PLUMED_REGISTER_ACTION(Distances,"YDISTANCES")
191 : PLUMED_REGISTER_ACTION(Distances,"ZDISTANCES")
192 :
193 131 : void Distances::registerKeywords(Keywords& keys) {
194 131 : ActionShortcut::registerKeywords( keys );
195 262 : keys.add("atoms-1","GROUP","Calculate the distance between each distinct pair of atoms in the group");
196 262 : keys.add("atoms-2","GROUPA","Calculate the distances between all the atoms in GROUPA and all "
197 : "the atoms in GROUPB. This must be used in conjunction with GROUPB.");
198 262 : keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms "
199 : "in GROUPB. This must be used in conjunction with GROUPA.");
200 262 : keys.add("numbered","ATOMS","the pairs of atoms that you would like to calculate the angles for");
201 262 : keys.addFlag("NOPBC",false,"ignore the periodic boundary conditions when calculating distances");
202 262 : keys.addFlag("COMPONENTS",false,"calculate the x, y and z components of the distance separately and store them as label.x, label.y and label.z");
203 262 : keys.addFlag("SCALED_COMPONENTS",false,"calculate the a, b and c scaled components of the distance separately and store them as label.a, label.b and label.c");
204 262 : keys.addFlag("LOWMEM",false,"this flag does nothing and is present only to ensure back-compatibility");
205 262 : keys.reset_style("ATOMS","atoms"); MultiColvarShortcuts::shortcutKeywords( keys );
206 262 : keys.add("atoms","ORIGIN","calculate the distance of all the atoms specified using the ATOMS keyword from this point");
207 262 : keys.add("numbered","LOCATION","the location at which the CV is assumed to be in space");
208 262 : keys.reset_style("LOCATION","atoms");
209 262 : keys.setValueDescription("vector","the DISTANCES between the each pair of atoms that were specified");
210 262 : keys.addOutputComponent("x","COMPONENTS","vector","the x-components of the distance vectors");
211 262 : keys.addOutputComponent("y","COMPONENTS","vector","the y-components of the distance vectors");
212 262 : keys.addOutputComponent("z","COMPONENTS","vector","the z-components of the distance vectors");
213 393 : keys.needsAction("GROUP"); keys.needsAction("DISTANCE"); keys.needsAction("CENTER");
214 131 : }
215 :
216 58 : Distances::Distances(const ActionOptions& ao):
217 : Action(ao),
218 58 : ActionShortcut(ao)
219 : {
220 : // Create distances
221 58 : bool lowmem; parseFlag("LOWMEM",lowmem);
222 58 : if( lowmem ) warning("LOWMEM flag is deprecated and is no longer required for this action");
223 58 : std::string dline = getShortcutLabel() + ": DISTANCE";
224 116 : bool nopbc; parseFlag("NOPBC",nopbc); if( nopbc ) dline += " NOPBC";
225 58 : if( getName()=="DISTANCES" ) {
226 110 : bool comp; parseFlag("COMPONENTS",comp); if( comp ) dline += " COMPONENTS";
227 110 : bool scomp; parseFlag("SCALED_COMPONENTS",scomp); if( scomp ) dline += " SCALED_COMPONENTS";
228 : } else dline += " COMPONENTS";
229 : // Parse origin
230 116 : std::string num, ostr; parse("ORIGIN",ostr);
231 58 : if( ostr.length()>0 ) {
232 : // Parse atoms
233 23 : std::vector<std::string> afstr; MultiColvarShortcuts::parseAtomList("ATOMS",afstr,this);
234 17118 : for(unsigned i=0; i<afstr.size(); ++i) { Tools::convert( i+1, num ); dline += " ATOMS" + num + "=" + ostr + "," + afstr[i]; }
235 23 : } else {
236 70 : std::vector<std::string> grp; MultiColvarShortcuts::parseAtomList("GROUP",grp,this);
237 70 : std::vector<std::string> grpa; MultiColvarShortcuts::parseAtomList("GROUPA",grpa,this);
238 35 : if( grp.size()>0 ) {
239 3 : if( grpa.size()>0 ) error("should not be using GROUPA in tandem with GROUP");
240 : unsigned n=0;
241 203 : for(unsigned i=1; i<grp.size(); ++i) {
242 10103 : for(unsigned j=0; j<i; ++j) {
243 9903 : std::string num; Tools::convert( n+1, num ); n++;
244 19806 : dline += " ATOMS" + num + "=" + grp[i] + "," + grp[j];
245 : }
246 : }
247 32 : } else if( grpa.size()>0 ) {
248 2 : std::vector<std::string> grpb; MultiColvarShortcuts::parseAtomList("GROUPB",grpb,this);
249 1 : if( grpb.size()==0 ) error("found GROUPA but no corresponding GROUPB");
250 1 : std::string grpstr = getShortcutLabel() + "_grp: GROUP ATOMS="; bool printcomment=false;
251 4 : for(unsigned i=0; i<grpa.size(); ++i) {
252 294 : for(unsigned j=0; j<grpb.size(); ++j) {
253 291 : std::string num; Tools::convert( i*grpb.size() + j + 1, num );
254 582 : dline += " ATOMS" + num + "=" + grpa[i] + "," + grpb[j];
255 297 : if( i*grpb.size() + j<6 ) readInputLine( getShortcutLabel() + "_vatom" + num + ": CENTER ATOMS=" + grpa[i] + "," + grpb[j], true );
256 570 : else { readInputLine( getShortcutLabel() + "_vatom" + num + ": CENTER ATOMS=" + grpa[i] + "," + grpb[j], false ); printcomment=true; }
257 582 : if( i+j==0 ) grpstr += getShortcutLabel() + "_vatom" + num; else grpstr += "," + getShortcutLabel() + "_vatom" + num;
258 : }
259 : }
260 1 : std::string num; Tools::convert( grpa.size()*grpb.size(), num );
261 2 : if( printcomment ) addCommentToShortcutOutput("# A further " + num + " CENTER like the ones above were also created but are not shown");
262 1 : readInputLine( grpstr );
263 1 : } else {
264 31 : std::string grpstr = getShortcutLabel() + "_grp: GROUP ATOMS=";
265 31 : for(unsigned i=1;; ++i) {
266 1844 : std::string atstring; parseNumbered("ATOMS",i,atstring);
267 922 : if( atstring.length()==0 ) break;
268 1782 : std::string locstr; parseNumbered("LOCATION",i,locstr);
269 891 : if( locstr.length()==0 ) {
270 281 : std::string num; Tools::convert( i, num );
271 562 : readInputLine( getShortcutLabel() + "_vatom" + num + ": CENTER ATOMS=" + atstring );
272 562 : if( i==1 ) grpstr += getShortcutLabel() + "_vatom" + num; else grpstr += "," + getShortcutLabel() + "_vatom" + num;
273 : } else {
274 1216 : if( i==1 ) grpstr += locstr; else grpstr += "," + locstr;
275 : }
276 891 : std::string num; Tools::convert( i, num );
277 1782 : dline += " ATOMS" + num + "=" + atstring;
278 891 : }
279 31 : readInputLine( grpstr );
280 : }
281 35 : }
282 58 : readInputLine( dline );
283 : // Add shortcuts to label
284 113 : if( getName()=="DISTANCES" ) MultiColvarShortcuts::expandFunctions( getShortcutLabel(), getShortcutLabel(), "", this );
285 4 : else if( getName()=="XDISTANCES" ) MultiColvarShortcuts::expandFunctions( getShortcutLabel(), getShortcutLabel() + ".x", "", this );
286 3 : else if( getName()=="YDISTANCES" ) MultiColvarShortcuts::expandFunctions( getShortcutLabel(), getShortcutLabel() + ".y", "", this );
287 2 : else if( getName()=="ZDISTANCES" ) MultiColvarShortcuts::expandFunctions( getShortcutLabel(), getShortcutLabel() + ".z", "", this );
288 58 : }
289 :
290 : }
291 : }
|