LCOV - code coverage report
Current view: top level - generic - DumpAtoms.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 121 123 98.4 %
Date: 2020-11-18 11:20:57 Functions: 12 14 85.7 %

          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 "core/ActionAtomistic.h"
      23             : #include "core/ActionPilot.h"
      24             : #include "core/ActionRegister.h"
      25             : #include "tools/Pbc.h"
      26             : #include "tools/File.h"
      27             : #include "core/PlumedMain.h"
      28             : #include "core/Atoms.h"
      29             : #include "tools/Units.h"
      30             : #include <cstdio>
      31             : #include "core/SetupMolInfo.h"
      32             : #include "core/ActionSet.h"
      33             : 
      34             : #if defined(__PLUMED_HAS_XDRFILE)
      35             : #include <xdrfile/xdrfile_xtc.h>
      36             : #include <xdrfile/xdrfile_trr.h>
      37             : #endif
      38             : 
      39             : 
      40             : using namespace std;
      41             : 
      42             : namespace PLMD
      43             : {
      44             : namespace generic {
      45             : 
      46             : //+PLUMEDOC PRINTANALYSIS DUMPATOMS
      47             : /*
      48             : Dump selected atoms on a file.
      49             : 
      50             : This command can be used to output the positions of a particular set of atoms.
      51             : The atoms required are ouput in a xyz or gro formatted file.
      52             : If PLUMED has been compiled with xdrfile support, then also xtc and trr files can be written.
      53             : To this aim one should install xdrfile library (http://www.gromacs.org/Developer_Zone/Programming_Guide/XTC_Library).
      54             : If the xdrfile library is installed properly the PLUMED configure script should be able to
      55             : detect it and enable it.
      56             : The type of file is automatically detected from the file extension, but can be also
      57             : enforced with TYPE.
      58             : Importantly, if your
      59             : input file contains actions that edit the atoms position (e.g. \ref WHOLEMOLECULES)
      60             : and the DUMPATOMS command appears after this instruction, then the edited
      61             : atom positions are output.
      62             : You can control the buffering of output using the \ref FLUSH keyword on a separate line.
      63             : 
      64             : Units of the printed file can be controlled with the UNITS keyword. By default PLUMED units as
      65             : controlled in the \ref UNITS command are used, but one can override it e.g. with UNITS=A.
      66             : Notice that gro/xtc/trr files can only contain coordinates in nm.
      67             : 
      68             : \par Examples
      69             : 
      70             : The following input instructs plumed to print out the positions of atoms
      71             : 1-10 together with the position of the center of mass of atoms 11-20 every
      72             : 10 steps to a file called file.xyz.
      73             : \plumedfile
      74             : COM ATOMS=11-20 LABEL=c1
      75             : DUMPATOMS STRIDE=10 FILE=file.xyz ATOMS=1-10,c1
      76             : \endplumedfile
      77             : Notice that the coordinates in the xyz file will be expressed in nm, since these
      78             : are the defaults units in PLUMED. If you want the xyz file to be expressed in A, you should use the
      79             : following input
      80             : \plumedfile
      81             : COM ATOMS=11-20 LABEL=c1
      82             : DUMPATOMS STRIDE=10 FILE=file.xyz ATOMS=1-10,c1 UNITS=A
      83             : \endplumedfile
      84             : As an alternative, you might want to set all the lentght used by PLUMED to Angstrom using the \ref UNITS
      85             : action. However, this latter choice will affect all your input and output.
      86             : 
      87             : The following input is very similar but dumps a .gro (gromacs) file,
      88             : which also contains atom and residue names.
      89             : \plumedfile
      90             : # this is required to have proper atom names:
      91             : MOLINFO STRUCTURE=reference.pdb
      92             : # if omitted, atoms will have "X" name...
      93             : 
      94             : COM ATOMS=11-20 LABEL=c1
      95             : DUMPATOMS STRIDE=10 FILE=file.gro ATOMS=1-10,c1
      96             : # notice that last atom is a virtual one and will not have
      97             : # a correct name in the resulting gro file
      98             : \endplumedfile
      99             : 
     100             : The `file.gro` will contain coordinates expressed in nm, since this is the convention for gro files.
     101             : 
     102             : In case you have compiled PLUMED with `xdrfile` library, you might even write xtc or trr files as follows
     103             : \plumedfile
     104             : COM ATOMS=11-20 LABEL=c1
     105             : DUMPATOMS STRIDE=10 FILE=file.xtc ATOMS=1-10,c1
     106             : \endplumedfile
     107             : Notice that xtc files are significantly smaller than gro and xyz files.
     108             : 
     109             : Finally, consider that gro and xtc file store coordinates with limited precision set by the
     110             : `PRECISION` keyword. Default value is 3, which means "3 digits after dot" in nm (1/1000 of a nm).
     111             : The following will write a larger xtc file with high resolution coordinates:
     112             : \plumedfile
     113             : COM ATOMS=11-20 LABEL=c1
     114             : DUMPATOMS STRIDE=10 FILE=file.xtc ATOMS=1-10,c1 PRECISION=7
     115             : \endplumedfile
     116             : 
     117             : 
     118             : 
     119             : */
     120             : //+ENDPLUMEDOC
     121             : 
     122             : class DumpAtoms:
     123             :   public ActionAtomistic,
     124             :   public ActionPilot
     125             : {
     126             :   OFile of;
     127             :   double lenunit;
     128             :   int iprecision;
     129             :   std::vector<std::string> names;
     130             :   std::vector<unsigned>    residueNumbers;
     131             :   std::vector<std::string> residueNames;
     132             :   std::string type;
     133             :   std::string fmt_gro_pos;
     134             :   std::string fmt_gro_box;
     135             :   std::string fmt_xyz;
     136             : #if defined(__PLUMED_HAS_XDRFILE)
     137             :   XDRFILE* xd;
     138             : #endif
     139             : public:
     140             :   explicit DumpAtoms(const ActionOptions&);
     141             :   ~DumpAtoms();
     142             :   static void registerKeywords( Keywords& keys );
     143         483 :   void calculate() {}
     144         483 :   void apply() {}
     145             :   void update();
     146             : };
     147             : 
     148        6507 : PLUMED_REGISTER_ACTION(DumpAtoms,"DUMPATOMS")
     149             : 
     150          56 : void DumpAtoms::registerKeywords( Keywords& keys ) {
     151          56 :   Action::registerKeywords( keys );
     152          56 :   ActionPilot::registerKeywords( keys );
     153          56 :   ActionAtomistic::registerKeywords( keys );
     154         280 :   keys.add("compulsory","STRIDE","1","the frequency with which the atoms should be output");
     155         224 :   keys.add("atoms", "ATOMS", "the atom indices whose positions you would like to print out");
     156         224 :   keys.add("compulsory", "FILE", "file on which to output coordinates; extension is automatically detected");
     157         280 :   keys.add("compulsory", "UNITS","PLUMED","the units in which to print out the coordinates. PLUMED means internal PLUMED units");
     158         224 :   keys.add("optional", "PRECISION","The number of digits in trajectory file");
     159             : #if defined(__PLUMED_HAS_XDRFILE)
     160         224 :   keys.add("optional", "TYPE","file type, either xyz, gro, xtc, or trr, can override an automatically detected file extension");
     161             : #else
     162             :   keys.add("optional", "TYPE","file type, either xyz or gro, can override an automatically detected file extension");
     163             : #endif
     164         112 :   keys.use("RESTART");
     165         112 :   keys.use("UPDATE_FROM");
     166         112 :   keys.use("UPDATE_UNTIL");
     167          56 : }
     168             : 
     169          55 : DumpAtoms::DumpAtoms(const ActionOptions&ao):
     170             :   Action(ao),
     171             :   ActionAtomistic(ao),
     172             :   ActionPilot(ao),
     173         385 :   iprecision(3)
     174             : {
     175             :   vector<AtomNumber> atoms;
     176             :   string file;
     177         110 :   parse("FILE",file);
     178          55 :   if(file.length()==0) error("name out output file was not specified");
     179         110 :   type=Tools::extension(file);
     180          55 :   log<<"  file name "<<file<<"\n";
     181         133 :   if(type=="gro" || type=="xyz" || type=="xtc" || type=="trr") {
     182          80 :     log<<"  file extension indicates a "<<type<<" file\n";
     183             :   } else {
     184          15 :     log<<"  file extension not detected, assuming xyz\n";
     185             :     type="xyz";
     186             :   }
     187             :   string ntype;
     188         110 :   parse("TYPE",ntype);
     189          55 :   if(ntype.length()>0) {
     190           5 :     if(ntype!="xyz" && ntype!="gro" && ntype!="xtc" && ntype!="trr"
     191           0 :       ) error("TYPE cannot be understood");
     192           2 :     log<<"  file type enforced to be "<<ntype<<"\n";
     193             :     type=ntype;
     194             :   }
     195             : #ifndef __PLUMED_HAS_XDRFILE
     196             :   if(type=="xtc" || type=="trr") error("types xtc and trr require PLUMED to be linked with the xdrfile library. Please install it and recompile PLUMED.");
     197             : #endif
     198             : 
     199             :   fmt_gro_pos="%8.3f";
     200             :   fmt_gro_box="%12.7f";
     201             :   fmt_xyz="%f";
     202             : 
     203             :   string precision;
     204         110 :   parse("PRECISION",precision);
     205          55 :   if(precision.length()>0) {
     206           9 :     Tools::convert(precision,iprecision);
     207           9 :     log<<"  with precision "<<iprecision<<"\n";
     208             :     string a,b;
     209           9 :     Tools::convert(iprecision+5,a);
     210           9 :     Tools::convert(iprecision,b);
     211          45 :     fmt_gro_pos="%"+a+"."+b+"f";
     212             :     fmt_gro_box=fmt_gro_pos;
     213             :     fmt_xyz=fmt_gro_box;
     214             :   }
     215             : 
     216         110 :   parseAtomList("ATOMS",atoms);
     217             : 
     218         110 :   std::string unitname; parse("UNITS",unitname);
     219          55 :   if(unitname!="PLUMED") {
     220           8 :     Units myunit; myunit.setLength(unitname);
     221           6 :     if(myunit.getLength()!=1.0 && type=="gro") error("gro files should be in nm");
     222           6 :     if(myunit.getLength()!=1.0 && type=="xtc") error("xtc files should be in nm");
     223           6 :     if(myunit.getLength()!=1.0 && type=="trr") error("trr files should be in nm");
     224           8 :     lenunit=plumed.getAtoms().getUnits().getLength()/myunit.getLength();
     225         167 :   } else if(type=="gro" || type=="xtc" || type=="trr") lenunit=plumed.getAtoms().getUnits().getLength();
     226          21 :   else lenunit=1.0;
     227             : 
     228          55 :   checkRead();
     229          55 :   of.link(*this);
     230          55 :   of.open(file);
     231             :   std::string path=of.getPath();
     232          55 :   log<<"  Writing on file "<<path<<"\n";
     233             : #ifdef __PLUMED_HAS_XDRFILE
     234             :   std::string mode=of.getMode();
     235          55 :   if(type=="xtc") {
     236           6 :     of.close();
     237           6 :     xd=xdrfile_open(path.c_str(),mode.c_str());
     238          49 :   } else if(type=="trr") {
     239           4 :     of.close();
     240           4 :     xd=xdrfile_open(path.c_str(),mode.c_str());
     241             :   }
     242             : #endif
     243         110 :   log.printf("  printing the following atoms in %s :", unitname.c_str() );
     244       47051 :   for(unsigned i=0; i<atoms.size(); ++i) log.printf(" %d",atoms[i].serial() );
     245          55 :   log.printf("\n");
     246          55 :   requestAtoms(atoms);
     247         110 :   std::vector<SetupMolInfo*> moldat=plumed.getActionSet().select<SetupMolInfo*>();
     248          55 :   if( moldat.size()==1 ) {
     249          26 :     log<<"  MOLINFO DATA found, using proper atom names\n";
     250          26 :     names.resize(atoms.size());
     251       19756 :     for(unsigned i=0; i<atoms.size(); i++) names[i]=moldat[0]->getAtomName(atoms[i]);
     252          26 :     residueNumbers.resize(atoms.size());
     253       13188 :     for(unsigned i=0; i<residueNumbers.size(); ++i) residueNumbers[i]=moldat[0]->getResidueNumber(atoms[i]);
     254          26 :     residueNames.resize(atoms.size());
     255       19756 :     for(unsigned i=0; i<residueNames.size(); ++i) residueNames[i]=moldat[0]->getResidueName(atoms[i]);
     256             :   }
     257          55 : }
     258             : 
     259         483 : void DumpAtoms::update() {
     260         966 :   if(type=="xyz") {
     261         282 :     of.printf("%d\n",getNumberOfAtoms());
     262         141 :     const Tensor & t(getPbc().getBox());
     263         141 :     if(getPbc().isOrthorombic()) {
     264         944 :       of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2));
     265             :     } else {
     266         644 :       of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),
     267          69 :                 lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2),
     268          69 :                 lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2),
     269          69 :                 lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2)
     270             :                );
     271             :     }
     272       62017 :     for(unsigned i=0; i<getNumberOfAtoms(); ++i) {
     273             :       const char* defname="X";
     274             :       const char* name=defname;
     275       39014 :       if(names.size()>0) if(names[i].length()>0) name=names[i].c_str();
     276      278442 :       of.printf(("%s "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),name,lenunit*getPosition(i)(0),lenunit*getPosition(i)(1),lenunit*getPosition(i)(2));
     277             :     }
     278         342 :   } else if(type=="gro") {
     279         222 :     const Tensor & t(getPbc().getBox());
     280         444 :     of.printf("Made with PLUMED t=%f\n",getTime()/plumed.getAtoms().getUnits().getTime());
     281         222 :     of.printf("%d\n",getNumberOfAtoms());
     282       44292 :     for(unsigned i=0; i<getNumberOfAtoms(); ++i) {
     283             :       const char* defname="X";
     284             :       const char* name=defname;
     285             :       unsigned residueNumber=0;
     286       43269 :       if(names.size()>0) if(names[i].length()>0) name=names[i].c_str();
     287       43269 :       if(residueNumbers.size()>0) residueNumber=residueNumbers[i];
     288       22035 :       std::string resname="";
     289       22035 :       if(residueNames.size()>0) resname=residueNames[i];
     290      220350 :       of.printf(("%5u%-5s%5s%5d"+fmt_gro_pos+fmt_gro_pos+fmt_gro_pos+"\n").c_str(),
     291             :                 residueNumber%100000,resname.c_str(),name,getAbsoluteIndex(i).serial()%100000,
     292       88140 :                 lenunit*getPosition(i)(0),lenunit*getPosition(i)(1),lenunit*getPosition(i)(2));
     293             :     }
     294        5994 :     of.printf((fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+"\n").c_str(),
     295         666 :               lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2),
     296         666 :               lenunit*t(0,1),lenunit*t(0,2),lenunit*t(1,0),
     297         666 :               lenunit*t(1,2),lenunit*t(2,0),lenunit*t(2,1));
     298             : #if defined(__PLUMED_HAS_XDRFILE)
     299         168 :   } else if(type=="xtc" || type=="trr") {
     300             :     matrix box;
     301         120 :     const Tensor & t(getPbc().getBox());
     302         120 :     int natoms=getNumberOfAtoms();
     303         120 :     int step=getStep();
     304         240 :     float time=getTime()/plumed.getAtoms().getUnits().getTime();
     305         240 :     float precision=Tools::fastpow(10.0,iprecision);
     306         480 :     for(int i=0; i<3; i++) for(int j=0; j<3; j++) box[i][j]=lenunit*t(i,j);
     307         120 :     rvec* pos=new rvec [natoms];
     308             : // Notice that code below cannot throw any exception.
     309             : // Thus, this pointer is excepton safe
     310       25464 :     for(int i=0; i<natoms; i++) for(int j=0; j<3; j++) pos[i][j]=lenunit*getPosition(i)(j);
     311         120 :     if(type=="xtc") {
     312          72 :       write_xtc(xd,natoms,step,time,box,&pos[0],precision);
     313          48 :     } else if(type=="trr") {
     314          48 :       write_trr(xd,natoms,step,time,0.0,box,&pos[0],NULL,NULL);
     315             :     }
     316         120 :     delete [] pos;
     317             : #endif
     318           0 :   } else plumed_merror("unknown file type "+type);
     319         483 : }
     320             : 
     321         275 : DumpAtoms::~DumpAtoms() {
     322             : #ifdef __PLUMED_HAS_XDRFILE
     323         110 :   if(type=="xtc") {
     324           6 :     xdrfile_close(xd);
     325          49 :   } else if(type=="trr") {
     326           4 :     xdrfile_close(xd);
     327             :   }
     328             : #endif
     329         110 : }
     330             : 
     331             : 
     332             : }
     333        4839 : }

Generated by: LCOV version 1.13