LCOV - code coverage report
Current view: top level - generic - Print.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 58 60 96.7 %
Date: 2026-11-05 10:19:04 Functions: 9 11 81.8 %

          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/ActionPilot.h"
      23             : #include "core/ActionWithArguments.h"
      24             : #include "core/ActionRegister.h"
      25             : 
      26             : namespace PLMD {
      27             : namespace generic {
      28             : 
      29             : //+PLUMEDOC PRINTANALYSIS PRINT
      30             : /*
      31             : Print quantities to a file.
      32             : 
      33             : This command can be used to output quantities to a file. The following demonstrates a very
      34             : simple example:
      35             : 
      36             : ```plumed
      37             : d: DISTANCE ATOMS=1,2
      38             : PRINT ARG=d FILE=colvar
      39             : ```
      40             : 
      41             : This command outputs the distance between atom 1 and 2 to a file called colvar every step of
      42             : trajectory. If you want to output the distance less frequently you can use the STRIDE keyword
      43             : as illustrated below:
      44             : 
      45             : ```plumed
      46             : d: DISTANCE ATOMS=1,2
      47             : PRINT ARG=d FILE=colvar STRIDE=10
      48             : ```
      49             : 
      50             : With the input above the distance is only output on every 10th step. Notice this distance will only
      51             : be calculated on every step as this quantity is not used on every other step.
      52             : 
      53             : You can also control the format of the numbers that are output by using the FMT keyword as shown below:
      54             : 
      55             : ```plumed
      56             : d: DISTANCE ATOMS=1,2
      57             : PRINT ARG=d FILE=colvar FMT=%10.6f
      58             : ```
      59             : 
      60             : The FMT key takes a [C format specifiers](https://www.simplilearn.com/tutorials/c-tutorial/format-specifiers-in-c)
      61             : in input, which is what determines the appearance of the numbers output.
      62             : 
      63             : You can also use the PRINT command to output objects that have a rank that is greater than zero.
      64             : For example, the following input calculates a vector of three distances. These three distances
      65             : are then output to the output colvar file every step.
      66             : 
      67             : ```plumed
      68             : d: DISTANCE ATOMS1=1,2 ATOMS2=3,4 ATOMS3=5,6
      69             : PRINT ARG=d FILE=colvar
      70             : ```
      71             : 
      72             : Alterantively, we can output a matrix by using an input like the one shown below:
      73             : 
      74             : ```plumed
      75             : d: DISTANCE_MATRIX GROUP=1-4
      76             : PRINT ARG=d FILE=colvar
      77             : ```
      78             : 
      79             : The output `colvar` file here will contain the 16 elements of the matrix on each line output. You can
      80             : also use PRINT to output functions on grids. However, you are probably better using [DUMPGRID](DUMPGRID.md) or
      81             : [DUMPCUBE](DUMPCUBE.md) to output functions on grids.
      82             : 
      83             : The PRINT directive can be used multiple times in the input so you can print files with different strides or print different quantities
      84             : to different files as illustrated in the example input below:
      85             : 
      86             : ```plumed
      87             : # compute distance:
      88             : distance: DISTANCE ATOMS=2,5
      89             : # compute total energy (potential)
      90             : energy: ENERGY
      91             : # print distance on a file
      92             : PRINT ARG=distance          STRIDE=10   FILE=COLVAR
      93             : # print both variables on another file
      94             : PRINT ARG=distance,energy   STRIDE=1000 FILE=COLVAR_ALL
      95             : ```
      96             : 
      97             : The input above instructs plumed to print the distance between atoms 3 and 5 on a file
      98             : called COLVAR every 10 steps, and the distance and total energy on a file called COLVAR_ALL
      99             : every 1000 steps.
     100             : 
     101             : You can control the buffering of output using the [FLUSH](FLUSH.md) keyword. Furthermore, whether the output file is
     102             : appended or backed up depends on whetehr or not the [RESTART](RESTART.md) action is present on the file. If you add `RESTART=yes` on the
     103             : line containing the PRINT directive the file will be appended also.
     104             : 
     105             : Printing happens in the so-called "update" phase. This implies that printing
     106             : is affected by the presence of [UPDATE_IF](UPDATE_IF.md) actions. One can thus decide to start
     107             : and stop printing at preassigned values of time using the `UPDATE_FROM` and `UPDATE_UNTIL` keywords.
     108             : Keep into account that even on steps when the action is not updated (and thus the file is not printed)
     109             : the argument will be activated. In other words, if you use `UPDATE_FROM` to start printing at a given time,
     110             : the collective variables this PRINT statement depends on will be computed also before that time.
     111             : 
     112             : ## PRINT and RESTART
     113             : 
     114             : If you run a calculation with the following input:
     115             : 
     116             : ```plumed
     117             : d: DISTANCE ATOMS=1,2
     118             : PRINT ARG=d FILE=colvar
     119             : ```
     120             : 
     121             : and a file called colvar is already present in the directory where the calculation is running, the existing file is backed up
     122             : and renamed to `bck.0.colvar` so that new data can be output to a new file called `colvar`.  If you would like to append to the
     123             : existing file you can use the RESTART command as shown below:
     124             : 
     125             : ```plumed
     126             : d: DISTANCE ATOMS=1,2
     127             : PRINT ARG=d FILE=colvar RESTART=YES
     128             : ```
     129             : 
     130             : You can achieve the same result by using the [RESTART](RESTART.md) action as shown below:
     131             : 
     132             : ```plumed
     133             : RESTART
     134             : d: DISTANCE ATOMS=1,2
     135             : PRINT ARG=d FILE=colvar
     136             : ```
     137             : 
     138             : However, the advantage of using the RESTART keyword is that you can apped to some files and back up others as illustrated below:
     139             : 
     140             : ```plumed
     141             : d1: DISTANCE ATOMS=1,2
     142             : PRINT ARG=d1 FILE=colvar1
     143             : d2: DISTANCE ATOMS=3,4
     144             : PRINT ARG=d2 FILE=colvar2 RESTART=YES
     145             : ```
     146             : 
     147             : If you use the input above the file `colvar1` is backed up, while new data will be appended to the file `colvar2`.  If you use the
     148             : [RESTART](RESTART.md) action instead data will be appended to both colvar files.
     149             : 
     150             : ## Switching printing on and off
     151             : 
     152             : You can use the UPDATE_FROM and UPDATE_UNTIL flags to make the PRINT command only output data at certain points during the trajectory.
     153             : To see how this works consider the following example:
     154             : 
     155             : ```plumed
     156             : d: DISTANCE ATOMS=1,2
     157             : PRINT ARG=d FILE=colvar UPDATE_FROM=100 UPDATE_UNTIL=500 STRIDE=1
     158             : ```
     159             : 
     160             : During the first 100 ps of the simulation with this input the distance between atoms 1 and 2 is not output to the file called colvar.
     161             : The distance is instead first output after the first 100 ps of trajectory have elapsed.  Furthermore, output of the distance stops
     162             : once the trajectory is longer than 500 ps. In other words, the distance is only output during the 400 ps time interval after the first
     163             : 100 ps of the simulation.
     164             : 
     165             : */
     166             : //+ENDPLUMEDOC
     167             : 
     168             : class Print :
     169             :   public ActionPilot,
     170             :   public ActionWithArguments {
     171             :   std::string file;
     172             :   OFile ofile;
     173             :   std::string fmt;
     174             : // small internal utility
     175             : /////////////////////////////////////////
     176             : // these are crazy things just for debug:
     177             : // they allow to change regularly the
     178             : // printed argument
     179             :   int rotate;
     180             :   int rotateCountdown;
     181             :   int rotateLast;
     182             :   std::vector<Value*> rotateArguments;
     183             : /////////////////////////////////////////
     184             : public:
     185      247078 :   void calculate() override {}
     186             :   void prepare() override;
     187             :   std::string writeInGraph() const override;
     188             :   explicit Print(const ActionOptions&);
     189             :   static void registerKeywords(Keywords& keys);
     190      246956 :   void apply() override {}
     191             :   void update() override;
     192             :   ~Print();
     193             : };
     194             : 
     195             : PLUMED_REGISTER_ACTION(Print,"PRINT")
     196             : 
     197        1572 : void Print::registerKeywords(Keywords& keys) {
     198        1572 :   Action::registerKeywords(keys);
     199        1572 :   ActionPilot::registerKeywords(keys);
     200        1572 :   ActionWithArguments::registerKeywords(keys);
     201        3144 :   keys.addInputKeyword("compulsory","ARG","scalar/vector/matrix","the labels of the values that you would like to print to the file");
     202        1572 :   keys.add("compulsory","STRIDE","1","the frequency with which the quantities of interest should be output");
     203        1572 :   keys.add("optional","FILE","the name of the file on which to output these quantities");
     204        1572 :   keys.add("compulsory","FMT","%f","the format that should be used to output real numbers");
     205        1572 :   keys.add("hidden","_ROTATE","some funky thing implemented by GBussi");
     206        1572 :   keys.use("RESTART");
     207        1572 :   keys.use("UPDATE_FROM");
     208        1572 :   keys.use("UPDATE_UNTIL");
     209        1572 : }
     210             : 
     211        1562 : Print::Print(const ActionOptions&ao):
     212             :   Action(ao),
     213             :   ActionPilot(ao),
     214             :   ActionWithArguments(ao),
     215        1562 :   rotate(0) {
     216        1562 :   ofile.link(*this);
     217        3124 :   parse("FILE",file);
     218        1562 :   if(file.length()>0) {
     219        1562 :     ofile.open(file);
     220        1552 :     log.printf("  on file %s\n",file.c_str());
     221             :   } else {
     222           0 :     log.printf("  on plumed log file\n");
     223           0 :     ofile.link(log);
     224             :   }
     225        1552 :   parse("FMT",fmt);
     226        1552 :   fmt=" "+fmt;
     227        1552 :   log.printf("  with format %s\n",fmt.c_str());
     228        9572 :   for(unsigned i=0; i<getNumberOfArguments(); ++i) {
     229        8020 :     ofile.setupPrintValue( getPntrToArgument(i) );
     230             :   }
     231             : /////////////////////////////////////////
     232             : // these are crazy things just for debug:
     233             : // they allow to change regularly the
     234             : // printed argument
     235        1552 :   parse("_ROTATE",rotate);
     236        1552 :   if(rotate>0) {
     237           1 :     rotateCountdown=rotate;
     238           4 :     for(unsigned i=0; i<getNumberOfArguments(); ++i) {
     239           3 :       rotateArguments.push_back( getPntrToArgument(i) );
     240             :     }
     241          11 :     std::vector<Value*> a(1,rotateArguments[0]);
     242           1 :     requestArguments(std::vector<Value*>(1,rotateArguments[0]));
     243           1 :     rotateLast=0;
     244             :   }
     245             : /////////////////////////////////////////
     246        1552 :   checkRead();
     247        1602 : }
     248             : 
     249           8 : std::string Print::writeInGraph() const {
     250          24 :   return getName() + "\n" + "FILE=" + file;
     251             : }
     252             : 
     253      247239 : void Print::prepare() {
     254             : /////////////////////////////////////////
     255             : // these are crazy things just for debug:
     256             : // they allow to change regularly the
     257             : // printed argument
     258      247239 :   if(rotate>0) {
     259           5 :     rotateCountdown--;
     260           5 :     if(rotateCountdown==0) {
     261           2 :       rotateCountdown=rotate;
     262           2 :       rotateLast++;
     263           2 :       rotateLast%=rotateArguments.size();
     264           4 :       requestArguments(std::vector<Value*>(1,rotateArguments[rotateLast]));
     265             :     }
     266             :   }
     267             : /////////////////////////////////////////
     268      247239 : }
     269             : 
     270      235442 : void Print::update() {
     271      235442 :   ofile.fmtField(" %f");
     272      235442 :   ofile.printField("time",getTime());
     273      869929 :   for(unsigned i=0; i<getNumberOfArguments(); i++) {
     274      634487 :     ofile.fmtField(fmt);
     275      634487 :     getPntrToArgument(i)->print( ofile );
     276             :   }
     277      235442 :   ofile.printField();
     278      235442 : }
     279             : 
     280        3104 : Print::~Print() {
     281        3104 : }
     282             : 
     283             : }
     284             : 
     285             : 
     286             : }

Generated by: LCOV version 1.16