Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2018 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 :
23 : #include "core/ActionRegister.h"
24 : #include "core/ActionAtomistic.h"
25 : #include "core/Atoms.h"
26 : #include "tools/IFile.h"
27 : #include "tools/Tools.h"
28 : #include <string>
29 : #include <vector>
30 : #include <algorithm>
31 :
32 : using namespace std;
33 :
34 : namespace PLMD {
35 : namespace generic {
36 :
37 : //+PLUMEDOC GENERIC GROUP
38 : /*
39 : Define a group of atoms so that a particular list of atoms can be referenced with a single label
40 : in definitions of CVs or virtual atoms.
41 :
42 : Atoms can be listed as comma separated numbers (i.e. 1,2,3,10,45,7,9,..) , simple positive ranges
43 : (i.e. 20-40), ranges with a stride either positive or negative (i.e. 20-40:2 or 80-50:-2) or as
44 : combinations of all the former methods (1,2,4,5,10-20,21-40:2,80-50:-2).
45 :
46 : Moreover, lists can be imported from ndx files (GROMACS format). Use NDX_FILE to set the name of
47 : the index file and NDX_GROUP to set the name of the group to be imported (default is first one).
48 :
49 : It is also possible to remove atoms from a list and or sort them using keywords REMOVE, SORT, and UNIQUE.
50 : The flow is the following:
51 : - If ATOMS is present take the ordered list of atoms from the ATOMS keyword.
52 : - If NDX_FILE is present append the list from the the gromacs group.
53 : - If REMOVE is present remove the first occurence of each of these atoms from the list.
54 : If one tries to remove an atom that was not listed plumed adds a notice in the output.
55 : - If SORT is present resulting list is sorted.
56 : - If UNIQUE is present the resuling list is sorted and duplicate elements are removed.
57 :
58 : Notice that this command just creates a shortcut, and does not imply any real calculation.
59 : So, having a huge group defined does not slow down your calculation in any way.
60 : It is just convenient to better organize input files. Might be used in combination with
61 : the \ref INCLUDE command so as to store long group definitions in a separate file.
62 :
63 :
64 : \par Examples
65 :
66 : This command create a group of atoms containing atoms 1,4,7,11 and 14 (labeled 'o'), and another containing
67 : atoms 2,3,5,6,8,9,12,13 (labeled 'h'):
68 : \verbatim
69 : o: GROUP ATOMS=1,4,7,11,14
70 : h: GROUP ATOMS=2,3,5,6,8,9,12,13
71 : # compute the coordination among the two groups
72 : c: COORDINATION GROUPA=o GROUPB=h R_0=0.3
73 : # same could have been obtained without GROUP, just writing:
74 : # c: COORDINATION GROUPA=1,4,7,11,14 GROUPB=2,3,5,6,8,9,12,13
75 :
76 : # print the coordination on file 'colvar'
77 : PRINT ARG=c FILE=colvar
78 : \endverbatim
79 : (see also \ref COORDINATION and \ref PRINT)
80 :
81 : Groups can be conveniently stored in a separate file.
82 : E.g. one could create a file named 'groups.dat' which reads
83 : \verbatim
84 : o: GROUP ATOMS=1,4,7,11,14
85 : h: GROUP ATOMS=2,3,5,6,8,9,12,13
86 : \endverbatim
87 : and then include it in the main 'plumed.dat' file
88 : \verbatim
89 : INCLUDE FILE=groups.dat
90 : # compute the coordination among the two groups
91 : c: COORDINATION GROUPA=o GROUPB=h R_0=0.3
92 : # print the coordination on file 'colvar'
93 : PRINT ARG=c FILE=colvar
94 : \endverbatim
95 : (see also \ref INCLUDE, \ref COORDINATION, and \ref PRINT).
96 : The groups.dat file could be very long and include lists of thousand atoms without cluttering the main plumed.dat file.
97 :
98 : A GROMACS index file can also be imported
99 : \verbatim
100 : # import group named 'protein' from file index.ndx
101 : pro: GROUP NDX_FILE=index.ndx NDX_GROUP=protein
102 : # dump all the atoms of the protein on a trajectory file
103 : DUMPATOMS ATOMS=pro FILE=traj.gro
104 : \endverbatim
105 : (see also \ref DUMPATOMS)
106 :
107 : A list can be edited with REMOVE
108 : \verbatim
109 : # take one atom every three
110 : ox: GROUP ATOMS=1-90:3
111 : # take the remaining atoms
112 : hy: GROUP ATOMS=1-90 REMOVE=ox
113 : DUMPATOMS ATOMS=ox FILE=ox.gro
114 : DUMPATOMS ATOMS=hy FILE=hy.gro
115 : \endverbatim
116 : (see also \ref DUMPATOMS)
117 :
118 :
119 : */
120 : //+ENDPLUMEDOC
121 :
122 : class Group:
123 : public ActionAtomistic
124 : {
125 :
126 : public:
127 : explicit Group(const ActionOptions&ao);
128 : ~Group();
129 : static void registerKeywords( Keywords& keys );
130 0 : void calculate() {}
131 0 : void apply() {}
132 : };
133 :
134 2586 : PLUMED_REGISTER_ACTION(Group,"GROUP")
135 :
136 63 : Group::Group(const ActionOptions&ao):
137 : Action(ao),
138 63 : ActionAtomistic(ao)
139 : {
140 63 : vector<AtomNumber> atoms;
141 63 : parseAtomList("ATOMS",atoms);
142 126 : std::string ndxfile,ndxgroup;
143 63 : parse("NDX_FILE",ndxfile);
144 63 : parse("NDX_GROUP",ndxgroup);
145 63 : if(ndxfile.length()>0 && atoms.size()>0) error("either use explicit atom list or import from index file");
146 63 : if(ndxfile.length()==0 && ndxgroup.size()>0) error("NDX_GROUP can be only used is NDX_FILE is also used");
147 :
148 63 : if(ndxfile.length()>0) {
149 2 : if(ndxgroup.size()>0) log<<" importing group '"+ndxgroup+"'";
150 1 : else log<<" importing first group";
151 2 : log<<" from index file "<<ndxfile<<"\n";
152 :
153 2 : IFile ifile;
154 2 : ifile.open(ndxfile);
155 4 : std::string line;
156 4 : std::string groupname;
157 2 : bool firstgroup=true;
158 2 : bool groupfound=false;
159 16 : while(ifile.getline(line)) {
160 12 : std::vector<std::string> words=Tools::getWords(line);
161 12 : if(words.size()>=3 && words[0]=="[" && words[2]=="]") {
162 4 : if(groupname.length()>0) firstgroup=false;
163 4 : groupname=words[1];
164 4 : if(groupname==ndxgroup || ndxgroup.length()==0) groupfound=true;
165 8 : } else if(groupname==ndxgroup || (firstgroup && ndxgroup.length()==0)) {
166 26 : for(unsigned i=0; i<words.size(); i++) {
167 22 : AtomNumber at; Tools::convert(words[i],at);
168 22 : atoms.push_back(at);
169 : }
170 : }
171 12 : }
172 4 : if(!groupfound) error("group has not been found in index file");
173 : }
174 :
175 126 : std::vector<AtomNumber> remove;
176 63 : parseAtomList("REMOVE",remove);
177 63 : if(remove.size()>0) {
178 1 : std::vector<AtomNumber> notfound;
179 1 : log<<" removing these atoms from the list:";
180 5 : for(unsigned i=0; i<remove.size(); i++) {
181 4 : std::vector<AtomNumber>::iterator it = find(atoms.begin(),atoms.end(),remove[i]);
182 4 : if(it!=atoms.end()) {
183 3 : log<<" "<<(*it).serial();
184 3 : atoms.erase(it);
185 1 : } else notfound.push_back(remove[i]);
186 : }
187 1 : log<<"\n";
188 1 : if(notfound.size()>0) {
189 1 : log<<" the following atoms were not found:";
190 1 : for(unsigned i=0; i<notfound.size(); i++) log<<" "<<notfound[i].serial();
191 1 : log<<"\n";
192 1 : }
193 : }
194 :
195 63 : bool sortme=false;
196 63 : parseFlag("SORT",sortme);
197 63 : if(sortme) {
198 1 : log<<" atoms are sorted\n";
199 1 : sort(atoms.begin(),atoms.end());
200 : }
201 63 : bool unique=false;
202 63 : parseFlag("UNIQUE",unique);
203 63 : if(unique) {
204 1 : log<<" sorting atoms and removing duplicates\n";
205 1 : Tools::removeDuplicates(atoms);
206 : }
207 :
208 63 : this->atoms.insertGroup(getLabel(),atoms);
209 63 : log.printf(" list of atoms ");
210 63 : for(unsigned i=0; i<atoms.size(); i++) log<<" "<<atoms[i].serial();
211 126 : log.printf("\n");
212 63 : }
213 :
214 64 : void Group::registerKeywords( Keywords& keys ) {
215 64 : Action::registerKeywords( keys );
216 64 : ActionAtomistic::registerKeywords( keys );
217 64 : keys.add("atoms", "ATOMS", "the numerical indexes for the set of atoms in the group");
218 64 : keys.add("atoms", "REMOVE","remove these atoms from the list");
219 64 : keys.addFlag("SORT",false,"sort the resulting list");
220 64 : keys.addFlag("UNIQUE",false,"sort atoms and remove duplicated ones");
221 64 : keys.add("optional", "NDX_FILE", "the name of index file (gromacs syntax)");
222 64 : keys.add("optional", "NDX_GROUP", "the name of the group to be imported (gromacs syntax) - first group found is used by default");
223 64 : }
224 :
225 252 : Group::~Group() {
226 63 : atoms.removeGroup(getLabel());
227 189 : }
228 :
229 : }
230 2523 : }
231 :
|