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