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

Generated by: LCOV version 1.14