LCOV - code coverage report
Current view: top level - generic - Group.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 78 80 97.5 %
Date: 2018-12-19 07:49:13 Functions: 9 13 69.2 %

          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             : 

Generated by: LCOV version 1.13