LCOV - code coverage report
Current view: top level - generic - DumpAtoms.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 175 187 93.6 %
Date: 2025-12-04 11:19:34 Functions: 10 13 76.9 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-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/ActionAtomistic.h"
      23             : #include "core/ActionWithArguments.h"
      24             : #include "core/ActionPilot.h"
      25             : #include "core/ActionRegister.h"
      26             : #include "tools/Pbc.h"
      27             : #include "tools/File.h"
      28             : #include "core/PlumedMain.h"
      29             : #include "tools/Units.h"
      30             : #include "tools/CheckInRange.h"
      31             : #include "core/GenericMolInfo.h"
      32             : #include "core/ActionSet.h"
      33             : #include "xdrfile/xdrfile_xtc.h"
      34             : #include "xdrfile/xdrfile_trr.h"
      35             : 
      36             : 
      37             : namespace PLMD {
      38             : namespace generic {
      39             : 
      40             : //+PLUMEDOC PRINTANALYSIS DUMPATOMS
      41             : /*
      42             : Dump selected atoms on a file.
      43             : 
      44             : This command can be used to output the positions of a particular set of atoms.
      45             : For example, the following input instructs PLUMED to print out the positions
      46             : of atoms 1-10 together with the position of the center of mass of atoms 11-20 every
      47             : 10 steps to a file called file.xyz.
      48             : 
      49             : ```plumed
      50             : c1: COM ATOMS=11-20
      51             : DUMPATOMS STRIDE=10 FILE=file.xyz ATOMS=1-10,c1
      52             : ```
      53             : 
      54             : By default, the coordinates in the output xyz file are in nm but you can change these units
      55             : by using the `UNITS` keyword as shown below:
      56             : 
      57             : ```plumed
      58             : c1: COM ATOMS=11-20
      59             : DUMPATOMS STRIDE=10 FILE=file.xyz ATOMS=1-10,c1 UNITS=A
      60             : ```
      61             : 
      62             : or by using the [UNITS](UNITS.md) action as shown below:
      63             : 
      64             : ```plumed
      65             : UNITS LENGTH=A
      66             : c1: COM ATOMS=11-20
      67             : DUMPATOMS STRIDE=10 FILE=file.xyz ATOMS=1-10,c1
      68             : ```
      69             : 
      70             : Notice, however, that if you use the second option here all the quantitities with units of length in your input
      71             : file must be provided in Angstrom and not nm.
      72             : 
      73             : ## DUMPATOMS and WHOLEMOLECULES
      74             : 
      75             : The commands [WHOLEMOLECULES](WHOLEMOLECULES.md), [WRAPAROUND](WRAPAROUND.md), [FIT_TO_TEMPLATE](FIT_TO_TEMPLATE.md)
      76             : and [RESET_CELL](RESET_CELL.md) all edit the global positions of the atoms.  If you use an input like this one:
      77             : 
      78             : ```plumed
      79             : DUMPATOMS ATOMS=1-10 FILE=file.xyz
      80             : WHOLEMOLECULES ENTITY0=1-10
      81             : ```
      82             : 
      83             : then the positions of the atoms that were passed to PLUMED by the MD code are output.  However, if you use an input
      84             : like this one:
      85             : 
      86             : ```plumed
      87             : WHOLEMOLECULES ENTITY0=1-10
      88             : DUMPATOMS ATOMS=1-10 FILE=file.xyz
      89             : ```
      90             : 
      91             : the positions outputted by the DUMPATOMS command will have been editted by the [WHOLEMOLECULES](WHOLEMOLECULES.md) command.
      92             : 
      93             : ## Outputting other file types
      94             : 
      95             : The extension that is given to the file specified using the `FILE` keyword determines the output file type. Hence,
      96             : the following example will output a gro file rather than an xyz file:
      97             : 
      98             : ```plumed
      99             : c1: COM ATOMS=11-20
     100             : DUMPATOMS STRIDE=10 FILE=file.gro ATOMS=1-10,c1
     101             : ```
     102             : 
     103             : You can also enforce the output file type by using the `TYPE` keyword as shown below:
     104             : 
     105             : ```plumed
     106             : c1: COM ATOMS=11-20
     107             : DUMPATOMS STRIDE=10 FILE=file.xyz ATOMS=1-10,c1 TYPE=gro
     108             : FLUSH STRIDE=1
     109             : ```
     110             : 
     111             : Notice that DUMPATOMS command here outputs the atoms in the gro-file format even though the author of this input has used the xyz extension.
     112             : Further note that by using the [FLUSH](FLUSH.md) we force PLUMED to output flush all the open files every step and not to store output
     113             : data in a buffer before printing it to the output files.
     114             : 
     115             : Outputting the atomic positions using the gro file format is particularly advantageous if you also have a [MOLINFO](MOLINFO.md) command in
     116             : your input file as shown below:
     117             : 
     118             : ```plumed
     119             : #SETTINGS MOLFILE=regtest/basic/rt32/helix.pdb
     120             : # this is required to have proper atom names:
     121             : MOLINFO STRUCTURE=regtest/basic/rt32/helix.pdb
     122             : # if omitted, atoms will have "X" name...
     123             : 
     124             : c1: COM ATOMS=11-20
     125             : DUMPATOMS STRIDE=10 FILE=file.gro ATOMS=1-10,c1
     126             : # notice that last atom is a virtual one and will not have
     127             : # a correct name in the resulting gro file
     128             : ```
     129             : 
     130             : The reason that using the gro file format is advantageous in this case is that PLUMED will also output the atom and residue names
     131             : for the non-virtual atoms.  PLUMED is able to do this in this case as it is able to use the information that was read in from the
     132             : pdb file that was provided to the [MOLINFO](MOLINFO.md) command.
     133             : 
     134             : If PLUMED has been compiled with xdrfile support, then PLUMED
     135             : can output xtc and trr files as well as xyz and gro files.  If you want to use these output types you should install the xdrfile
     136             : library by following the instructions [here](http://www.gromacs.org/Developer_Zone/Programming_Guide/XTC_Library).
     137             : If the xdrfile library is installed properly the PLUMED configure script should be able to
     138             : detect it and enable it.  The following example shows how you can use DUMPATOMS to output an xtc file:
     139             : 
     140             : ```plumed
     141             : c1: COM ATOMS=11-20
     142             : DUMPATOMS STRIDE=10 FILE=file.xtc ATOMS=1-10,c1
     143             : ```
     144             : 
     145             : The xtc file that is output by this command will be significantly smaller than a gro and xyz file.
     146             : 
     147             : Finally, notice that gro and xtc file store coordinates with limited precision set by the
     148             : `PRECISION` keyword. The default value is 3, which means "3 digits after dot" in nm (1/1000 of a nm).
     149             : The following will write a larger xtc file with high resolution coordinates:
     150             : 
     151             : ```plumed
     152             : COM ATOMS=11-20 LABEL=c1
     153             : DUMPATOMS STRIDE=10 FILE=file.xtc ATOMS=1-10,c1 PRECISION=7
     154             : ```
     155             : 
     156             : ## Outputting atomic positions and vectors
     157             : 
     158             : The atoms section of an xyz file normally contains four columns of data - a symbol that tells you the atom type
     159             : and then three columns containing the atom's $x$, $y$ and $z$ coordinates.  PLUMED allows you to output more columns
     160             : of data in this file.  For example, the following input outputs five columns of data.  The first four columns of data
     161             : are the usual ones you would expect in an xyz file, while the fifth contains the coordination numbers for each of the
     162             : atom that have been calculated using PLUMED
     163             : 
     164             : ```plumed
     165             : # These three lines calculate the coordination numbers of 100 atoms
     166             : c1: CONTACT_MATRIX GROUP=1-100 SWITCH={RATIONAL R_0=0.1 NN=6 MM=12}
     167             : ones: ONES SIZE=100
     168             : cc: MATRIX_VECTOR_PRODUCT ARG=c1,ones
     169             : DUMPATOMS ATOMS=1-100 ARG=cc FILE=file.xyz
     170             : ```
     171             : 
     172             : This command is used in the shortcut that recovered the old [DUMPMULTICOLVAR](DUMPMULTICOLVAR.md) command. This new version of
     173             : the command is better, however, as you can output more than one vector of symmetry functions at once as is demonstrated by the following
     174             : input that outputs the coordination numbers and the values that were obtained when the coordination numbers were all transformed by a
     175             : switching function:
     176             : 
     177             : ```plumed
     178             : # These three lines calculate the coordination numbers of 100 atoms
     179             : c1: CONTACT_MATRIX GROUP=1-100 SWITCH={RATIONAL R_0=0.1 NN=6 MM=12}
     180             : ones: ONES SIZE=100
     181             : cc: MATRIX_VECTOR_PRODUCT ARG=c1,ones
     182             : fcc: LESS_THAN ARG=cc SWITCH={RATIONAL R_0=4}
     183             : DUMPATOMS ATOMS=1-100 ARG=cc,fcc FILE=file.xyz
     184             : ```
     185             : 
     186             : Notice that when we use an `ARG` keyword we can also use DUMPATOMS to only print those atoms whose corresponding element in the
     187             : the input vector satisfies a certain criteria.  For example the input file below only prints the positions (and coordination numbers) of atoms that
     188             : have a coordination number that is greater than or equal to 4.
     189             : 
     190             : ```plumed
     191             : # These three lines calculate the coordination numbers of 100 atoms
     192             : c1: CONTACT_MATRIX GROUP=1-100 SWITCH={RATIONAL R_0=0.1 NN=6 MM=12}
     193             : ones: ONES SIZE=100
     194             : cc: MATRIX_VECTOR_PRODUCT ARG=c1,ones
     195             : DUMPATOMS ATOMS=1-100 ARG=cc GREATER_THAN_OR_EQUAL=4 FILE=file.xyz
     196             : ```
     197             : 
     198             : Alternatively, the following input allows us to output those atoms that have a coordination number that is between 4 and 6:
     199             : 
     200             : ```plumed
     201             : # These three lines calculate the coordination numbers of 100 atoms
     202             : c1: CONTACT_MATRIX GROUP=1-100 SWITCH={RATIONAL R_0=0.1 NN=6 MM=12}
     203             : ones: ONES SIZE=100
     204             : cc: MATRIX_VECTOR_PRODUCT ARG=c1,ones
     205             : DUMPATOMS ...
     206             :   ATOMS=1-100 ARG=cc
     207             :   GREATER_THAN_OR_EQUAL=4
     208             :   LESS_THAN_OR_EQUAL=6
     209             :   FILE=file.xyz
     210             : ...
     211             : ```
     212             : 
     213             : Commands like these are useful if you want to print the coordinates of the atom that are in a paricular cluster that has been identified using
     214             : the [DFSCLUSTERING](DFSCLUSTERING.md) command.
     215             : 
     216             : __You can only use the ARG keyword if you are outputting an xyz file__
     217             : 
     218             : ## PRINT and RESTART
     219             : 
     220             : If you run a calculation with the following input:
     221             : 
     222             : ```plumed
     223             : DUMPATOMS ATOMS=1-100 FILE=file.xyz
     224             : ```
     225             : 
     226             : and a file called `file.xyz` is already present in the directory where the calculation is running, the existing file is backed up
     227             : and renamed to `bck.0.file.xyz` so that new data can be output to a new file called `file.xyz`.  If you would like to append to the
     228             : existing file you can use the RESTART command as shown below:
     229             : 
     230             : ```plumed
     231             : DUMPATOMS ATOMS=1-100 FILE=file.xyz RESTART=YES
     232             : ```
     233             : 
     234             : You can achieve the same result by using the [RESTART](RESTART.md) action as shown below:
     235             : 
     236             : ```plumed
     237             : RESTART
     238             : DUMPATOMS ATOMS=1-100 FILE=file.xyz
     239             : ```
     240             : 
     241             : However, the advantage of using the RESTART keyword is that you can apped to some files and back up others as illustrated below:
     242             : 
     243             : ```plumed
     244             : DUMPATOMS ATOMS=1-100 FILE=file1.xyz
     245             : DUMPATOMS ATOMS=1-100 FILE=file2.xyz RESTART=YES
     246             : ```
     247             : 
     248             : If you use the input above the file `file1.xyz` is backed up, while new data will be appended to the file `file2.xyz`.  If you use the
     249             : [RESTART](RESTART.md) action instead data will be appended to both colvar files.
     250             : 
     251             : ## Switching printing on and off
     252             : 
     253             : You can use the UPDATE_FROM and UPDATE_UNTIL flags to make the DUMPATOMS command only output data at certain points during the trajectory.
     254             : To see how this works consider the following example:
     255             : 
     256             : ```plumed
     257             : DUMPATOMS ATOMS=1-100 FILE=file.xyz UPDATE_FROM=100 UPDATE_UNTIL=500 STRIDE=1
     258             : ```
     259             : 
     260             : During the first 100 ps of a simulation with this input the atomic positions are not output to the file called file.xyz.
     261             : The positions are instead only output after the first 100 ps of trajectory have elapsed.  Furthermore, output of the positions stops
     262             : once the trajectory is longer than 500 ps. In other words, the positions are only output during the 400 ps time interval after the first
     263             : 100 ps of the simulation.
     264             : 
     265             : */
     266             : //+ENDPLUMEDOC
     267             : 
     268             : class DumpAtoms:
     269             :   public ActionAtomistic,
     270             :   public ActionWithArguments,
     271             :   public ActionPilot {
     272             :   OFile of;
     273             :   double lenunit;
     274             :   int iprecision;
     275             :   CheckInRange bounds;
     276             :   std::vector<std::string> names;
     277             :   std::vector<unsigned>    residueNumbers;
     278             :   std::vector<std::string> residueNames;
     279             :   std::string type;
     280             :   std::string fmt_gro_pos;
     281             :   std::string fmt_gro_box;
     282             :   std::string fmt_xyz;
     283             :   xdrfile::XDRFILE* xd;
     284             : public:
     285             :   explicit DumpAtoms(const ActionOptions&);
     286             :   ~DumpAtoms();
     287             :   static void registerKeywords( Keywords& keys );
     288             :   void calculateNumericalDerivatives( ActionWithValue* a=NULL ) override;
     289         194 :   bool actionHasForces() override {
     290         194 :     return false;
     291             :   }
     292             :   void lockRequests() override;
     293             :   void unlockRequests() override;
     294        9095 :   void calculate() override {}
     295        9095 :   void apply() override {}
     296             :   void update() override ;
     297             : };
     298             : 
     299             : PLUMED_REGISTER_ACTION(DumpAtoms,"DUMPATOMS")
     300             : 
     301         224 : void DumpAtoms::registerKeywords( Keywords& keys ) {
     302         224 :   Action::registerKeywords( keys );
     303         224 :   ActionPilot::registerKeywords( keys );
     304         224 :   ActionAtomistic::registerKeywords( keys );
     305         224 :   ActionWithArguments::registerKeywords( keys );
     306         448 :   keys.addInputKeyword("optional","ARG","vector","the labels of vectors that should be output in the xyz file. The number of elements in the vector should equal the number of atoms output");
     307         224 :   keys.add("compulsory","STRIDE","1","the frequency with which the atoms should be output");
     308         224 :   keys.add("atoms", "ATOMS", "the atom indices whose positions you would like to print out");
     309         224 :   keys.add("compulsory", "FILE", "file on which to output coordinates; extension is automatically detected");
     310         224 :   keys.add("compulsory", "UNITS","PLUMED","the units in which to print out the coordinates. PLUMED means internal PLUMED units");
     311         224 :   keys.add("optional", "PRECISION","The number of digits in trajectory file");
     312         224 :   keys.add("optional", "TYPE","file type, either xyz, gro, xtc, or trr, can override an automatically detected file extension");
     313         224 :   keys.add("optional","LESS_THAN_OR_EQUAL","when printing with arguments that are vectors only print components of vectors have a value less than or equal to this value");
     314         224 :   keys.add("optional","GREATER_THAN_OR_EQUAL","when printing with arguments that are vectors only print components of vectors have a value greater than or equal to this value");
     315         224 :   keys.use("RESTART");
     316         224 :   keys.use("UPDATE_FROM");
     317         224 :   keys.use("UPDATE_UNTIL");
     318         224 : }
     319             : 
     320         222 : DumpAtoms::DumpAtoms(const ActionOptions&ao):
     321             :   Action(ao),
     322             :   ActionAtomistic(ao),
     323             :   ActionWithArguments(ao),
     324             :   ActionPilot(ao),
     325         222 :   iprecision(3) {
     326             :   std::vector<AtomNumber> atoms;
     327             :   std::string file;
     328         444 :   parse("FILE",file);
     329         222 :   if(file.length()==0) {
     330           0 :     error("name out output file was not specified");
     331             :   }
     332         222 :   type=Tools::extension(file);
     333         222 :   log<<"  file name "<<file<<"\n";
     334         461 :   if(type=="gro" || type=="xyz" || type=="xtc" || type=="trr") {
     335         197 :     log<<"  file extension indicates a "<<type<<" file\n";
     336             :   } else {
     337          25 :     log<<"  file extension not detected, assuming xyz\n";
     338             :     type="xyz";
     339             :   }
     340             :   std::string ntype;
     341         444 :   parse("TYPE",ntype);
     342         222 :   if(ntype.length()>0) {
     343           5 :     if(ntype!="xyz" && ntype!="gro" && ntype!="xtc" && ntype!="trr"
     344             :       ) {
     345           0 :       error("TYPE cannot be understood");
     346             :     }
     347           2 :     log<<"  file type enforced to be "<<ntype<<"\n";
     348             :     type=ntype;
     349             :   }
     350             : 
     351             :   fmt_gro_pos="%8.3f";
     352             :   fmt_gro_box="%12.7f";
     353             :   fmt_xyz="%f";
     354             : 
     355             :   std::string precision;
     356         444 :   parse("PRECISION",precision);
     357         222 :   if(precision.length()>0) {
     358         136 :     Tools::convert(precision,iprecision);
     359         136 :     log<<"  with precision "<<iprecision<<"\n";
     360             :     std::string a,b;
     361         136 :     Tools::convert(iprecision+5,a);
     362         136 :     Tools::convert(iprecision,b);
     363         272 :     fmt_gro_pos="%"+a+"."+b+"f";
     364             :     fmt_gro_box=fmt_gro_pos;
     365             :     fmt_xyz=fmt_gro_box;
     366             :   }
     367             : 
     368         444 :   parseAtomList("ATOMS",atoms);
     369             : 
     370             :   std::string unitname;
     371         444 :   parse("UNITS",unitname);
     372         222 :   if(unitname!="PLUMED") {
     373          17 :     Units myunit;
     374          17 :     myunit.setLength(unitname);
     375          32 :     if(myunit.getLength()!=1.0 && type=="gro") {
     376           0 :       error("gro files should be in nm");
     377             :     }
     378          32 :     if(myunit.getLength()!=1.0 && type=="xtc") {
     379           0 :       error("xtc files should be in nm");
     380             :     }
     381          32 :     if(myunit.getLength()!=1.0 && type=="trr") {
     382           0 :       error("trr files should be in nm");
     383             :     }
     384          17 :     lenunit=getUnits().getLength()/myunit.getLength();
     385         534 :   } else if(type=="gro" || type=="xtc" || type=="trr") {
     386          56 :     lenunit=getUnits().getLength();
     387             :   } else {
     388         149 :     lenunit=1.0;
     389             :   }
     390             : 
     391         222 :   of.link(*this);
     392         222 :   of.open(file);
     393             :   std::string path=of.getPath();
     394         222 :   log<<"  Writing on file "<<path<<"\n";
     395             :   std::string mode=of.getMode();
     396         222 :   if(type=="xtc") {
     397           6 :     of.close();
     398           6 :     xd=xdrfile::xdrfile_open(path.c_str(),mode.c_str());
     399         216 :   } else if(type=="trr") {
     400           4 :     of.close();
     401           4 :     xd=xdrfile::xdrfile_open(path.c_str(),mode.c_str());
     402             :   }
     403         222 :   log.printf("  printing the following atoms in %s :", unitname.c_str() );
     404       30874 :   for(unsigned i=0; i<atoms.size(); ++i) {
     405       30652 :     log.printf(" %d",atoms[i].serial() );
     406             :   }
     407         222 :   log.printf("\n");
     408             : 
     409         222 :   if( getNumberOfArguments()>0 ) {
     410          39 :     if( type!="xyz" ) {
     411           0 :       error("can only print atomic properties when outputting xyz files");
     412             :     }
     413             : 
     414             :     std::vector<std::string> argnames;
     415         119 :     for(unsigned i=0; i<getNumberOfArguments(); ++i) {
     416          80 :       if( getPntrToArgument(i)->getRank()!=1 ) {
     417           0 :         error("arguments for xyz output should be vectors");
     418             :       }
     419          80 :       if( getPntrToArgument(i)->getNumberOfValues()!=atoms.size() ) {
     420           0 :         error("number of elements in vector " + getPntrToArgument(i)->getName() + " is not equal to number of atoms output");
     421             :       }
     422          80 :       argnames.push_back( getPntrToArgument(i)->getName() );
     423             :     }
     424             :     std::vector<std::string> str_upper, str_lower;
     425             :     std::string errors;
     426          39 :     parseVector("LESS_THAN_OR_EQUAL",str_upper);
     427          78 :     parseVector("GREATER_THAN_OR_EQUAL",str_lower);
     428          39 :     if( !bounds.setBounds( getNumberOfArguments(), str_lower, str_upper, errors ) ) {
     429           0 :       error( errors );
     430             :     }
     431          39 :     if( bounds.wereSet() ) {
     432          26 :       log.printf("  %s \n", bounds.report( argnames ).c_str() );
     433             :     }
     434          39 :   }
     435             : 
     436         222 :   requestAtoms(atoms, false);
     437         222 :   auto* infomoldat=plumed.getActionSet().selectLatest<GenericMolInfo*>(this);
     438         222 :   if( infomoldat ) {
     439          56 :     log<<"  MOLINFO DATA found with label " <<infomoldat->getLabel()<<", using proper atom names\n";
     440          56 :     names.resize(atoms.size());
     441        5835 :     for(unsigned i=0; i<atoms.size(); i++)
     442        5779 :       if(atoms[i].index()<infomoldat->getPDBsize()) {
     443       11554 :         names[i]=infomoldat->getAtomName(atoms[i]);
     444             :       }
     445          56 :     residueNumbers.resize(atoms.size());
     446        5835 :     for(unsigned i=0; i<residueNumbers.size(); ++i)
     447        5779 :       if(atoms[i].index()<infomoldat->getPDBsize()) {
     448        5777 :         residueNumbers[i]=infomoldat->getResidueNumber(atoms[i]);
     449             :       }
     450          56 :     residueNames.resize(atoms.size());
     451        5835 :     for(unsigned i=0; i<residueNames.size(); ++i)
     452        5779 :       if(atoms[i].index()<infomoldat->getPDBsize()) {
     453       11554 :         residueNames[i]=infomoldat->getResidueName(atoms[i]);
     454             :       }
     455             :   }
     456         222 : }
     457             : 
     458           0 : void DumpAtoms::calculateNumericalDerivatives( ActionWithValue* a ) {
     459           0 :   plumed_merror("this should never be called");
     460             : }
     461             : 
     462        9095 : void DumpAtoms::lockRequests() {
     463             :   ActionWithArguments::lockRequests();
     464             :   ActionAtomistic::lockRequests();
     465        9095 : }
     466             : 
     467        9095 : void DumpAtoms::unlockRequests() {
     468             :   ActionWithArguments::unlockRequests();
     469             :   ActionAtomistic::unlockRequests();
     470        9095 : }
     471             : 
     472        9000 : void DumpAtoms::update() {
     473        9000 :   if(type=="xyz") {
     474             :     unsigned nat=0;
     475        8414 :     std::vector<double> args( getNumberOfArguments() );
     476       74007 :     for(unsigned i=0; i<getNumberOfAtoms(); ++i)  {
     477       95495 :       for(unsigned j=0; j<getNumberOfArguments(); ++j) {
     478       29902 :         args[j] = getPntrToArgument(j)->get(i);
     479             :       }
     480       65593 :       if( bounds.check( args ) ) {
     481       61787 :         nat++;
     482             :       }
     483             :     }
     484        8414 :     of.printf("%d\n",nat);
     485        8414 :     const Tensor & t(getPbc().getBox());
     486        8414 :     if(getPbc().isOrthorombic()) {
     487         612 :       of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2));
     488             :     } else {
     489       16216 :       of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),
     490        8108 :                 lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2),
     491        8108 :                 lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2),
     492        8108 :                 lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2)
     493             :                );
     494             :     }
     495       16828 :     const std::string posFormatString="%s "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz;
     496        8414 :     const std::string extraFormatString=" "+fmt_xyz;
     497       74007 :     for(unsigned i=0; i<getNumberOfAtoms(); ++i) {
     498       95495 :       for(unsigned j=0; j<getNumberOfArguments(); ++j) {
     499       29902 :         args[j] = getPntrToArgument(j)->get(i);
     500             :       }
     501       65593 :       if( !bounds.check(args) ) {
     502        3806 :         continue;
     503             :       }
     504             :       const char* defname="X";
     505             :       const char* atomName=defname;
     506       61787 :       if(names.size()>0) {
     507       10802 :         if(names[i].length()>0) {
     508             :           atomName=names[i].c_str();
     509             :         }
     510             :       }
     511       61787 :       of.printf(posFormatString.c_str(),
     512             :                 atomName,
     513       61787 :                 lenunit*getPosition(i)(0),
     514       61787 :                 lenunit*getPosition(i)(1),
     515       61787 :                 lenunit*getPosition(i)(2));
     516       87883 :       for(unsigned j=0; j<getNumberOfArguments(); ++j) {
     517       26096 :         of.printf(extraFormatString.c_str(), getPntrToArgument(j)->get(i) );
     518             :       }
     519       61787 :       of.printf("\n");
     520             :     }
     521         586 :   } else if(type=="gro") {
     522         932 :     const std::string posFormatString="%5u%-5s%5s%5d"+fmt_gro_pos+fmt_gro_pos+fmt_gro_pos+"\n";
     523         466 :     std::string extraFormatString=" "+fmt_xyz;
     524         466 :     const Tensor & t(getPbc().getBox());
     525         466 :     of.printf("Made with PLUMED t=%f\n",getTime()/getUnits().getTime());
     526         466 :     of.printf("%d\n",getNumberOfAtoms());
     527       38404 :     for(unsigned i=0; i<getNumberOfAtoms(); ++i) {
     528             :       const char* defname="X";
     529             :       const char* atomName=defname;
     530             :       unsigned residueNumber=0;
     531       37938 :       if(names.size()>0)
     532       37137 :         if(names[i].length()>0) {
     533             :           atomName=names[i].c_str();
     534             :         }
     535       37938 :       if(residueNumbers.size()>0) {
     536       37137 :         residueNumber=residueNumbers[i];
     537             :       }
     538       37938 :       std::string resname="";
     539       37938 :       if(residueNames.size()>0) {
     540       37137 :         resname=residueNames[i];
     541             :       }
     542       37938 :       of.printf(posFormatString.c_str(),
     543             :                 residueNumber%100000,resname.c_str(),atomName,getAbsoluteIndex(i).serial()%100000,
     544       37938 :                 lenunit*getPosition(i)(0),lenunit*getPosition(i)(1),lenunit*getPosition(i)(2));
     545             :     }
     546         932 :     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(),
     547         466 :               lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2),
     548         466 :               lenunit*t(0,1),lenunit*t(0,2),lenunit*t(1,0),
     549         466 :               lenunit*t(1,2),lenunit*t(2,0),lenunit*t(2,1));
     550         168 :   } else if(type=="xtc" || type=="trr") {
     551             :     xdrfile::matrix box;
     552         120 :     const Tensor & t(getPbc().getBox());
     553         120 :     int natoms=getNumberOfAtoms();
     554         120 :     int step=getStep();
     555         120 :     float time=getTime()/getUnits().getTime();
     556         120 :     float precision=Tools::fastpow(10.0,iprecision);
     557         480 :     for(int i=0; i<3; i++)
     558        1440 :       for(int j=0; j<3; j++) {
     559        1080 :         box[i][j]=lenunit*t(i,j);
     560             :       }
     561             : // here we cannot use a std::vector<rvec> since it does not compile.
     562             : // we thus use a std::unique_ptr<rvec[]>
     563             :     auto pos = Tools::make_unique<xdrfile::rvec[]>(natoms);
     564        6456 :     for(int i=0; i<natoms; i++)
     565       25344 :       for(int j=0; j<3; j++) {
     566       19008 :         pos[i][j]=lenunit*getPosition(i)(j);
     567             :       }
     568         120 :     if(type=="xtc") {
     569          72 :       write_xtc(xd,natoms,step,time,box,&pos[0],precision);
     570          48 :     } else if(type=="trr") {
     571          48 :       write_trr(xd,natoms,step,time,0.0,box,&pos[0],NULL,NULL);
     572             :     }
     573             :   } else {
     574           0 :     plumed_merror("unknown file type "+type);
     575             :   }
     576        9000 : }
     577             : 
     578         444 : DumpAtoms::~DumpAtoms() {
     579         222 :   if(type=="xtc") {
     580           6 :     xdrfile_close(xd);
     581         216 :   } else if(type=="trr") {
     582           4 :     xdrfile_close(xd);
     583             :   }
     584        1110 : }
     585             : 
     586             : 
     587             : }
     588             : }

Generated by: LCOV version 1.16