Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2012-2020 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 usefull
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 writen 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 implicitely
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 26042 : 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 43444757 : 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 0 : OFile& open(const std::string&name);
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 field
230 : OFile& printField(const std::string&,int);
231 : /// Set the value of a string field
232 : OFile& printField(const std::string&,const std::string&);
233 : ///
234 : OFile& addConstantField(const std::string&);
235 : /// Used to setup printing of values
236 : OFile& setupPrintValue( Value *val );
237 : /// Print a value
238 : OFile& printField( Value* val, const double& v );
239 : /** Close a line.
240 : Typically used as
241 : \verbatim
242 : of.printField("a",a).printField("b",b).printField();
243 : \endverbatim
244 : */
245 : OFile& printField();
246 : /**
247 : Resets the list of fields.
248 : As it is only possible to add new constant fields (addConstantField()),
249 : this method can be used to clean the field list.
250 : */
251 : OFile& clearFields();
252 : /// Formatted output with explicit format - a la printf
253 : int printf(const char*fmt,...);
254 : /// Formatted output with << operator
255 : template <class T>
256 : friend OFile& operator<<(OFile&,const T &);
257 : /// Rewind a file
258 : OFile&rewind();
259 : /// Flush a file
260 : virtual FileBase&flush();
261 : /// Enforce restart, also if the attached plumed object is not restarting.
262 : /// Useful for tests
263 : OFile&enforceRestart();
264 : /// Enforce backup, even if the attached plumed object is restarting.
265 : OFile&enforceBackup();
266 : };
267 :
268 : /// Write using << syntax
269 : template <class T>
270 1069996 : OFile& operator<<(OFile&of,const T &t) {
271 1069996 : of.oss<<t;
272 2139992 : of.printf("%s",of.oss.str().c_str());
273 2139992 : of.oss.str("");
274 1069996 : return of;
275 : }
276 :
277 :
278 : }
279 :
280 : #endif
|