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