Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2012-2019 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 :
29 : namespace PLMD {
30 :
31 : class Value;
32 :
33 : /**
34 : \ingroup TOOLBOX
35 : Class for output files
36 :
37 : This class provides features similar to those in the standard C "FILE*" type,
38 : but only for sequential output. See IFile for sequential input.
39 :
40 : See the example here for a possible use:
41 : \verbatim
42 : #include "File.h"
43 :
44 : int main(){
45 : PLMD::OFile pof;
46 : pof.open("ciao");
47 : pof.printf("%s\n","test1");
48 : pof.setLinePrefix("plumed: ");
49 : pof.printf("%s\n","test2");
50 : pof.setLinePrefix("");
51 : pof.addConstantField("x2").printField("x2",67.0);
52 : pof.printField("x1",10.0).printField("x3",20.12345678901234567890).printField();
53 : pof.printField("x1",10.0).printField("x3",-1e70*20.12345678901234567890).printField();
54 : pof.printField("x3",10.0).printField("x2",777.0).printField("x1",-1e70*20.12345678901234567890).printField();
55 : pof.printField("x3",67.0).printField("x1",18.0).printField();
56 : pof.close();
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 : snp.close();
141 : grw.close();
142 : }
143 :
144 : \endverbatim
145 : */
146 :
147 : class OFile:
148 : public virtual FileBase {
149 : /// Pointer to a linked OFile.
150 : /// see link(OFile&)
151 : OFile* linked;
152 : /// Internal buffer for printf
153 : char* buffer_string;
154 : /// Internal buffer (generic use)
155 : char* buffer;
156 : /// Internal buffer length
157 : int buflen;
158 : /// This variables stores the actual buffer length
159 : int actual_buffer_length;
160 : /// Class identifying a single field for fielded output
161 42112237 : class Field:
162 : public FieldBase {
163 : };
164 : /// Low-level write
165 : size_t llwrite(const char*,size_t);
166 : /// True if fields has changed.
167 : /// This could be due to a change in the list of fields or a reset
168 : /// of a nominally constant field
169 : bool fieldChanged;
170 : /// Format for fields writing
171 : std::string fieldFmt;
172 : /// All the previously defined variable fields
173 : std::vector<Field> previous_fields;
174 : /// All the defined variable fields
175 : std::vector<Field> fields;
176 : /// All the defined constant fields
177 : std::vector<Field> const_fields;
178 : /// Prefix for line (e.g. "PLUMED: ")
179 : std::string linePrefix;
180 : /// Temporary ostringstream for << output
181 : std::ostringstream oss;
182 : /// The string used for backing up files
183 : std::string backstring;
184 : /// Find field index given name
185 : unsigned findField(const std::string&name)const;
186 : /// check if we are restarting
187 : bool checkRestart()const;
188 : /// True if restart behavior should be forced
189 : bool enforceRestart_;
190 : /// True if backup behavior (i.e. non restart) should be forced
191 : bool enforceBackup_;
192 : public:
193 : /// Constructor
194 : OFile();
195 : /// Destructor
196 : ~OFile();
197 : /// Allows overloading of link
198 : using FileBase::link;
199 : /// Allows overloading of open
200 : using FileBase::open;
201 : /// Allows linking this OFile to another one.
202 : /// In this way, everything written to this OFile will be immediately
203 : /// written on the linked OFile. Notice that a OFile should
204 : /// be either opened explicitly, linked to a FILE or linked to a OFile
205 : OFile& link(OFile&);
206 : /// Set the string name to be used for automatic backup
207 : void setBackupString( const std::string& );
208 : /// Backup a file by giving it a different name
209 : void backupFile( const std::string& bstring, const std::string& fname );
210 : /// This backs up all the files that would have been created with the
211 : /// name str. It is used in analysis when you are not restarting. Analysis
212 : /// output files at different times, which are names analysis.0.<filename>,
213 : /// analysis.1.<filename> and <filename>, are backed up to bck.0.analysis.0.<filename>,
214 : /// bck.0.analysis.1.<filename> and bck.0.<filename>
215 : void backupAllFiles( const std::string& str );
216 : /// Opens the file using automatic append/backup
217 0 : OFile& open(const std::string&name);
218 : /// Set the prefix for output.
219 : /// Typically "PLUMED: ". Notice that lines with a prefix cannot
220 : /// be parsed using fields in a IFile.
221 : OFile& setLinePrefix(const std::string&);
222 : /// Set the format for writing double precision fields
223 : OFile& fmtField(const std::string&);
224 : /// Reset the format for writing double precision fields to its default
225 : OFile& fmtField();
226 : /// Set the value of a double precision field
227 : OFile& printField(const std::string&,double);
228 : /// Set the value of a int field
229 : OFile& printField(const std::string&,int);
230 : /// Set the value of a string field
231 : OFile& printField(const std::string&,const std::string&);
232 : ///
233 : OFile& addConstantField(const std::string&);
234 : /// Used to setup printing of values
235 : OFile& setupPrintValue( Value *val );
236 : /// Print a value
237 : OFile& printField( Value* val, const double& v );
238 : /** Close a line.
239 : Typically used as
240 : \verbatim
241 : of.printField("a",a).printField("b",b).printField();
242 : \endverbatim
243 : */
244 : OFile& printField();
245 : /**
246 : Resets the list of fields.
247 : As it is only possible to add new constant fields (addConstantField()),
248 : this method can be used to clean the field list.
249 : */
250 : OFile& clearFields();
251 : /// Formatted output with explicit format - a la printf
252 : int printf(const char*fmt,...);
253 : /// Formatted output with << operator
254 : template <class T>
255 : friend OFile& operator<<(OFile&,const T &);
256 : /// Rewind a file
257 : OFile&rewind();
258 : /// Flush a file
259 : virtual FileBase&flush();
260 : /// Enforce restart, also if the attached plumed object is not restarting.
261 : /// Useful for tests
262 : OFile&enforceRestart();
263 : /// Enforce backup, even if the attached plumed object is restarting.
264 : OFile&enforceBackup();
265 : };
266 :
267 : /// Write using << syntax
268 : template <class T>
269 67205 : OFile& operator<<(OFile&of,const T &t) {
270 67205 : of.oss<<t;
271 134410 : of.printf("%s",of.oss.str().c_str());
272 134410 : of.oss.str("");
273 67205 : return of;
274 : }
275 :
276 :
277 : }
278 :
279 : #endif
|