LCOV - code coverage report
Current view: top level - tools - OFile.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 6 6 100.0 %
Date: 2024-10-18 14:00:25 Functions: 96 108 88.9 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-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             : #ifndef __PLUMED_tools_OFile_h
      23             : #define __PLUMED_tools_OFile_h
      24             : 
      25             : #include "FileBase.h"
      26             : #include <vector>
      27             : #include <sstream>
      28             : #include <memory>
      29             : #include <cstddef>
      30             : 
      31             : namespace PLMD {
      32             : 
      33             : class Value;
      34             : 
      35             : /**
      36             : \ingroup TOOLBOX
      37             : Class for output files
      38             : 
      39             : This class provides features similar to those in the standard C "FILE*" type,
      40             : but only for sequential output. See IFile for sequential input.
      41             : 
      42             : See the example here for a possible use:
      43             : \verbatim
      44             : #include "File.h"
      45             : 
      46             : int main(){
      47             :   PLMD::OFile pof;
      48             :   pof.open("ciao");
      49             :   pof.printf("%s\n","test1");
      50             :   pof.setLinePrefix("plumed: ");
      51             :   pof.printf("%s\n","test2");
      52             :   pof.setLinePrefix("");
      53             :   pof.addConstantField("x2").printField("x2",67.0);
      54             :   pof.printField("x1",10.0).printField("x3",20.12345678901234567890).printField();
      55             :   pof.printField("x1",10.0).printField("x3",-1e70*20.12345678901234567890).printField();
      56             :   pof.printField("x3",10.0).printField("x2",777.0).printField("x1",-1e70*20.12345678901234567890).printField();
      57             :   pof.printField("x3",67.0).printField("x1",18.0).printField();
      58             :   return 0;
      59             : }
      60             : \endverbatim
      61             : 
      62             : This program is expected to produce a file "ciao" which reads
      63             : \verbatim
      64             : test1
      65             : plumed: test2
      66             : #! FIELDS x1 x3
      67             : #! SET x2                      67
      68             :                      10      20.12345678901234
      69             :                      10 -2.012345678901235e+71
      70             : #! FIELDS x1 x3
      71             : #! SET x2                     777
      72             :  -2.012345678901235e+71                     10
      73             :                      18                     67
      74             : \endverbatim
      75             : 
      76             : Notes
      77             : - "x2" is declared as "constant", which means that it is written using the "SET"
      78             : keyword. Thus, everytime it is modified, all the headers are repeated in the output file.
      79             : - printField() without arguments is used as a "newline".
      80             : - most methods return a reference to the OFile itself, to allow chaining many calls on the same line
      81             : (this is similar to << operator in std::ostream)
      82             : 
      83             : \section using-correctly-ofile Using correctly OFile in PLUMED
      84             : 
      85             : When a OFile object is used in PLUMED it can be convenient to link() it
      86             : to the Action object where it is defined, or to the PlumedMain object.
      87             : This will save in the OFile a pointer to the linked object and will
      88             : allow to have some extra information. E.g., if PLUMED is restarting,
      89             : files will be appended. Notice that one can enforce this behavior using
      90             : the enforceRestart() method before opening a file.
      91             : 
      92             : To have all files managed consistently, it is important to use OFile in the proper way.
      93             : This should allow multi-replica plumed, restart and backups to work in
      94             : the expected way. For this reason all the operations in OFile and IFile
      95             : are synchronizing all the processors of the group, so call to OFile functions
      96             : should always be performed by all processes; for this reason is also not useful
      97             : to use Log for debugging because only master threads will actually write.
      98             : For debugging is better to use the standard stderr.
      99             : 
     100             : \verbatim
     101             : int main(){
     102             : // this is a growing file, containing a full history
     103             : // (frames are appended, as in traditional HILLS and COLVAR)
     104             :   OFile grw;
     105             : // this is a single-snapshopt file used e.g. for checkpointing
     106             : // (rewritten every time)
     107             :   OFile snp;
     108             : 
     109             : // open both files at the beginning
     110             : // (will go in \ref Action constructor)
     111             :   grw.open("growing");
     112             :   snp.open("snapshot");
     113             : 
     114             : // trajectory loop
     115             :   for(int i=0;i<nsteps;i++){
     116             : 
     117             : // files should be written in the update() method of an \ref Action
     118             : 
     119             : // write on growing file
     120             :     grw<<"data at step "<<i<<\n";
     121             : 
     122             : // flushing
     123             : // it takes time, so do it only if data is critical
     124             : // better to leave this choice to the user with the FLUSH keyword
     125             : //    grw.flush();
     126             : 
     127             : // write on snapshot file
     128             :     snp.rewind();
     129             :     snp<<"snapshot at step "<<i<<"\n";
     130             :     snp.flush();
     131             : // the only difference is that snp is rewound
     132             : // notice that it should be rewound just before writing
     133             : // because rewind is going to move the file out of the way
     134             : // to have a safe copy of the file ("bck.last.filename")
     135             : // Also notice that snapshots should be flushed
     136             : // for this reason, it is better to write them only
     137             : // rarely to avoid excessive slow down
     138             : 
     139             :   }
     140             : }
     141             : 
     142             : \notice
     143             : Notice that it is not necessary to explicitely close files, since they are closed implicitly
     144             : when the object goes out of scope. In case you need to explicitly close the file before it is
     145             : destroyed, please check it the procedure is exception safe and, if necessary, add some `try/catch`
     146             : statement.
     147             : 
     148             : \endverbatim
     149             : */
     150             : 
     151             : class OFile:
     152             :   public virtual FileBase {
     153             : /// Pointer to a linked OFile.
     154             : /// see link(OFile&)
     155             :   OFile* linked;
     156             : /// Internal buffer for printf
     157             :   std::vector<char> buffer_string;
     158             : /// Internal buffer (generic use)
     159             :   std::vector<char> buffer;
     160             : /// Internal buffer length
     161             :   int buflen;
     162             : /// This variables stores the actual buffer length
     163             :   int actual_buffer_length;
     164             : /// Class identifying a single field for fielded output
     165    51805100 :   class Field:
     166             :     public FieldBase {
     167             :   };
     168             : /// Low-level write
     169             :   std::size_t llwrite(const char*,std::size_t);
     170             : /// True if fields has changed.
     171             : /// This could be due to a change in the list of fields or a reset
     172             : /// of a nominally constant field
     173             :   bool fieldChanged;
     174             : /// Format for fields writing
     175             :   std::string fieldFmt;
     176             : /// All the previously defined variable fields
     177             :   std::vector<Field> previous_fields;
     178             : /// All the defined variable fields
     179             :   std::vector<Field> fields;
     180             : /// All the defined constant fields
     181             :   std::vector<Field> const_fields;
     182             : /// Prefix for line (e.g. "PLUMED: ")
     183             :   std::string linePrefix;
     184             : /// Temporary ostringstream for << output
     185             :   std::ostringstream oss;
     186             : /// The string used for backing up files
     187             :   std::string backstring;
     188             : /// Find field index given name
     189             :   unsigned findField(const std::string&name)const;
     190             : /// check if we are restarting
     191             :   bool checkRestart()const;
     192             : /// True if restart behavior should be forced
     193             :   bool enforceRestart_;
     194             : /// True if backup behavior (i.e. non restart) should be forced
     195             :   bool enforceBackup_;
     196             : public:
     197             : /// Constructor
     198             :   OFile();
     199             : /// Allows overloading of link
     200             :   using FileBase::link;
     201             : /// Allows overloading of open
     202             :   using FileBase::open;
     203             : /// Allows linking this OFile to another one.
     204             : /// In this way, everything written to this OFile will be immediately
     205             : /// written on the linked OFile. Notice that a OFile should
     206             : /// be either opened explicitly, linked to a FILE or linked to a OFile
     207             :   OFile& link(OFile&);
     208             : /// Set the string name to be used for automatic backup
     209             :   void setBackupString( const std::string& );
     210             : /// Backup a file by giving it a different name
     211             :   void backupFile( const std::string& bstring, const std::string& fname );
     212             : /// This backs up all the files that would have been created with the
     213             : /// name str.  It is used in analysis when you are not restarting.  Analysis
     214             : /// output files at different times, which are names analysis.0.<filename>,
     215             : /// analysis.1.<filename> and <filename>, are backed up to bck.0.analysis.0.<filename>,
     216             : /// bck.0.analysis.1.<filename> and bck.0.<filename>
     217             :   void backupAllFiles( const std::string& str );
     218             : /// Opens the file using automatic append/backup
     219             :   OFile& open(const std::string&name) override;
     220             : /// Set the prefix for output.
     221             : /// Typically "PLUMED: ". Notice that lines with a prefix cannot
     222             : /// be parsed using fields in a IFile.
     223             :   OFile& setLinePrefix(const std::string&);
     224             : /// Set the format for writing double precision fields
     225             :   OFile& fmtField(const std::string&);
     226             : /// Reset the format for writing double precision fields to its default
     227             :   OFile& fmtField();
     228             : /// Set the value of a double precision field
     229             :   OFile& printField(const std::string&,double);
     230             : /// Set the value of a int type field
     231             :   OFile& printField(const std::string&,int);
     232             :   OFile& printField(const std::string&,long int);
     233             :   OFile& printField(const std::string&,long long int);
     234             :   OFile& printField(const std::string&,unsigned);
     235             :   OFile& printField(const std::string&,long unsigned);
     236             :   OFile& printField(const std::string&,long long unsigned);
     237             : /// Set the value of a string field
     238             :   OFile& printField(const std::string&,const std::string&);
     239             : ///
     240             :   OFile& addConstantField(const std::string&);
     241             : /// Used to setup printing of values
     242             :   OFile& setupPrintValue( Value *val );
     243             : /// Print a value
     244             :   OFile& printField( Value* val, const double& v );
     245             :   /** Close a line.
     246             :   Typically used as
     247             :   \verbatim
     248             :     of.printField("a",a).printField("b",b).printField();
     249             :   \endverbatim
     250             :   */
     251             :   OFile& printField();
     252             :   /**
     253             :   Resets the list of fields.
     254             :   As it is only possible to add new constant fields (addConstantField()),
     255             :   this method can be used to clean the field list.
     256             :   */
     257             :   OFile& clearFields();
     258             : /// Formatted output with explicit format - a la printf
     259             :   int printf(const char*fmt,...);
     260             : /// Formatted output with << operator
     261             :   template <class T>
     262             :   friend OFile& operator<<(OFile&,const T &);
     263             : /// Rewind a file
     264             :   OFile&rewind();
     265             : /// Flush a file
     266             :   FileBase&flush() override;
     267             : /// Enforce restart, also if the attached plumed object is not restarting.
     268             : /// Useful for tests
     269             :   OFile&enforceRestart();
     270             : /// Enforce backup, even if the attached plumed object is restarting.
     271             :   OFile&enforceBackup();
     272             : };
     273             : 
     274             : /// Write using << syntax
     275             : template <class T>
     276     1772496 : OFile& operator<<(OFile&of,const T &t) {
     277     1772496 :   of.oss<<t;
     278     1772496 :   of.printf("%s",of.oss.str().c_str());
     279     1772496 :   of.oss.str("");
     280     1772496 :   return of;
     281             : }
     282             : 
     283             : 
     284             : }
     285             : 
     286             : #endif

Generated by: LCOV version 1.16