uncollatedFileOperation.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
27 #include "Time.H"
28 #include "IFstream.H"
29 #include "OFstream.H"
32 #include "decomposedBlockData.H"
33 #include "dummyISstream.H"
34 
35 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
36 
37 namespace Foam
38 {
39 namespace fileOperations
40 {
41  defineTypeNameAndDebug(uncollatedFileOperation, 0);
42  addToRunTimeSelectionTable(fileOperation, uncollatedFileOperation, word);
43 }
44 }
45 
46 
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 
49 Foam::fileName Foam::fileOperations::uncollatedFileOperation::filePathInfo
50 (
51  const bool checkGlobal,
52  const bool isFile,
53  const IOobject& io
54 ) const
55 {
56  if (io.instance().isAbsolute())
57  {
58  fileName objectPath = io.instance()/io.name();
59 
60  if (isFileOrDir(isFile, objectPath))
61  {
62  return objectPath;
63  }
64  else
65  {
66  return fileName::null;
67  }
68  }
69  else
70  {
71  fileName path = io.path();
72  fileName objectPath = path/io.name();
73 
74  if (isFileOrDir(isFile, objectPath))
75  {
76  return objectPath;
77  }
78  else
79  {
80  if
81  (
82  checkGlobal
83  && io.time().processorCase()
84  && (
85  io.instance() == io.time().system()
86  || io.instance() == io.time().constant()
87  )
88  )
89  {
90  // Constant & system can come from global case
91 
92  fileName parentObjectPath =
93  io.rootPath()/io.time().globalCaseName()
94  /io.instance()/io.db().dbDir()/io.local()/io.name();
95 
96  if (isFileOrDir(isFile, parentObjectPath))
97  {
98  return parentObjectPath;
99  }
100  }
101 
102  // Check if parallel "procesors" directory
103  if (io.time().processorCase())
104  {
107  (
108  io,
109  io.instance()
110  );
111  fileName objectPath = path/io.name();
112 
113  if (isFileOrDir(isFile, objectPath))
114  {
115  return objectPath;
116  }
117  }
118 
119 
120  // Check for approximately same time. E.g. if time = 1e-2 and
121  // directory is 0.01 (due to different time formats)
122  if (!Foam::isDir(path))
123  {
124  word newInstancePath = io.time().findInstancePath
125  (
126  instant(io.instance())
127  );
128 
129  if (newInstancePath.size())
130  {
131  fileName fName
132  (
133  io.rootPath()/io.caseName()
134  /newInstancePath/io.db().dbDir()/io.local()/io.name()
135  );
136 
137  if (isFileOrDir(isFile, fName))
138  {
139  return fName;
140  }
141  }
142  }
143  }
144 
145  return fileName::null;
146  }
147 }
148 
149 
150 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
151 
153 (
154  const bool verbose
155 )
156 {
157  if (verbose)
158  {
159  Info<< "I/O : " << typeName << endl;
160  }
161 }
162 
163 
164 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
165 
167 {}
168 
169 
170 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
171 
173 (
174  const fileName& dir,
175  mode_t mode
176 ) const
177 {
178  return Foam::mkDir(dir, mode);
179 }
180 
181 
183 (
184  const fileName& fName,
185  mode_t mode
186 ) const
187 {
188  return Foam::chMod(fName, mode);
189 }
190 
191 
193 (
194  const fileName& fName,
195  const bool followLink
196 ) const
197 {
198  return Foam::mode(fName, followLink);
199 }
200 
201 
203 (
204  const fileName& fName,
205  const bool followLink
206 ) const
207 {
208  return Foam::type(fName, followLink);
209 }
210 
211 
213 (
214  const fileName& fName,
215  const bool checkGzip,
216  const bool followLink
217 ) const
218 {
219  return Foam::exists(fName, checkGzip, followLink);
220 }
221 
222 
224 (
225  const fileName& fName,
226  const bool followLink
227 ) const
228 {
229  return Foam::isDir(fName, followLink);
230 }
231 
232 
234 (
235  const fileName& fName,
236  const bool checkGzip,
237  const bool followLink
238 ) const
239 {
240  return Foam::isFile(fName, checkGzip, followLink);
241 }
242 
243 
245 (
246  const fileName& fName,
247  const bool followLink
248 ) const
249 {
250  return Foam::fileSize(fName, followLink);
251 }
252 
253 
255 (
256  const fileName& fName,
257  const bool followLink
258 ) const
259 {
260  return Foam::lastModified(fName, followLink);
261 }
262 
263 
265 (
266  const fileName& fName,
267  const bool followLink
268 ) const
269 {
270  return Foam::highResLastModified(fName, followLink);
271 }
272 
273 
275 (
276  const fileName& fName,
277  const std::string& ext
278 ) const
279 {
280  return Foam::mvBak(fName, ext);
281 }
282 
283 
285 (
286  const fileName& fName
287 ) const
288 {
289  return Foam::rm(fName);
290 }
291 
292 
294 (
295  const fileName& dir
296 ) const
297 {
298  return Foam::rmDir(dir);
299 }
300 
301 
303 (
304  const fileName& dir,
305  const fileName::Type type,
306  const bool filtergz,
307  const bool followLink
308 ) const
309 {
310  return Foam::readDir(dir, type, filtergz, followLink);
311 }
312 
313 
315 (
316  const fileName& src,
317  const fileName& dst,
318  const bool followLink
319 ) const
320 {
321  return Foam::cp(src, dst, followLink);
322 }
323 
324 
326 (
327  const fileName& src,
328  const fileName& dst
329 ) const
330 {
331  return Foam::ln(src, dst);
332 }
333 
334 
336 (
337  const fileName& src,
338  const fileName& dst,
339  const bool followLink
340 ) const
341 {
342  return Foam::mv(src, dst, followLink);
343 }
344 
345 
347 (
348  const bool checkGlobal,
349  const IOobject& io,
350  const word& typeName
351 ) const
352 {
353  if (debug)
354  {
355  Pout<< "uncollatedFileOperation::filePath :"
356  << " objectPath:" << io.objectPath()
357  << " checkGlobal:" << checkGlobal << endl;
358  }
359 
360  fileName objPath(filePathInfo(checkGlobal, true, io));
361 
362  if (debug)
363  {
364  Pout<< "uncollatedFileOperation::filePath :"
365  << " Returning from file searching:" << endl
366  << " objectPath:" << io.objectPath() << endl
367  << " filePath :" << objPath << endl << endl;
368  }
369  return objPath;
370 }
371 
372 
374 (
375  const bool checkGlobal,
376  const IOobject& io
377 ) const
378 {
379  if (debug)
380  {
381  Pout<< "uncollatedFileOperation::dirPath :"
382  << " objectPath:" << io.objectPath()
383  << " checkGlobal:" << checkGlobal << endl;
384  }
385 
386  fileName objPath(filePathInfo(checkGlobal, false, io));
387 
388  if (debug)
389  {
390  Pout<< "uncollatedFileOperation::dirPath :"
391  << " Returning from directory searching:" << endl
392  << " objectPath:" << io.objectPath() << endl
393  << " dirPath :" << objPath << endl << endl;
394  }
395  return objPath;
396 }
397 
398 
400 (
401  const objectRegistry& db,
402  const fileName& instance,
403  const fileName& local,
404  word& newInstance
405 ) const
406 {
407  if (debug)
408  {
409  Pout<< "uncollatedFileOperation::readObjects :"
410  << " db:" << db.objectPath()
411  << " instance:" << instance << endl;
412  }
413 
414  //- Use non-time searching version
415  fileNameList objectNames
416  (
417  fileOperation::readObjects(db, instance, local, newInstance)
418  );
419 
420  if (newInstance.empty())
421  {
422  // Find similar time
423  fileName newInst = db.time().findInstancePath(instant(instance));
424  if (!newInst.empty() && newInst != instance)
425  {
426  // Try with new time
427  objectNames = fileOperation::readObjects
428  (
429  db,
430  newInst,
431  local,
432  newInstance
433  );
434  }
435  }
436 
437  if (debug)
438  {
439  Pout<< "uncollatedFileOperation::readObjects :"
440  << " newInstance:" << newInstance
441  << " objectNames:" << objectNames << endl;
442  }
443 
444  return objectNames;
445 }
446 
447 
449 (
450  IOobject& io,
451  const fileName& fName,
452  const word& typeName
453 ) const
454 {
455  if (fName.empty())
456  {
457  if (IOobject::debug)
458  {
460  << "file " << io.objectPath() << " could not be opened"
461  << endl;
462  }
463 
464  return false;
465  }
466 
467  autoPtr<ISstream> isPtr(NewIFstream(fName));
468 
469  if (!isPtr.valid() || !isPtr->good())
470  {
471  return false;
472  }
473 
474  bool ok = io.readHeader(isPtr());
475 
476  if (io.headerClassName() == decomposedBlockData::typeName)
477  {
478  // Read the header inside the container (master data)
479  ok = decomposedBlockData::readMasterHeader(io, isPtr());
480  }
481 
482  return ok;
483 }
484 
485 
488 (
489  regIOobject& io,
490  const fileName& fName,
491  const word& typeName,
492  const bool valid
493 ) const
494 {
495  autoPtr<ISstream> isPtr;
496 
497  if (!valid)
498  {
499  isPtr = autoPtr<ISstream>(new dummyISstream());
500  return isPtr;
501  }
502 
503  if (fName.empty())
504  {
506  << "cannot find file " << io.objectPath()
507  << exit(FatalError);
508  }
509 
510  isPtr = NewIFstream(fName);
511 
512  if (!isPtr.valid() || !isPtr->good())
513  {
515  (
516  "uncollatedFileOperation::readStream()",
517  __FILE__,
518  __LINE__,
519  fName,
520  0
521  ) << "cannot open file"
522  << exit(FatalIOError);
523  }
524  else if (!io.readHeader(isPtr()))
525  {
526  FatalIOErrorInFunction(isPtr())
527  << "problem while reading header for object " << io.name()
528  << exit(FatalIOError);
529  }
530 
531  if (io.headerClassName() != decomposedBlockData::typeName)
532  {
533  return isPtr;
534  }
535  else
536  {
537  // Analyse the objectpath to find out the processor we're trying
538  // to access
539  fileName path;
540  fileName local;
543  (
544  io.objectPath(),
545  path,
546  local
547  );
548 
549  if (proci == -1)
550  {
551  FatalIOErrorInFunction(isPtr())
552  << "could not detect processor number"
553  << " from objectPath:" << io.objectPath()
554  << exit(FatalIOError);
555  }
556 
557  // Read data and return as stream
558  return decomposedBlockData::readBlock(proci, isPtr(), io);
559  }
560 }
561 
562 
564 (
565  regIOobject& io,
566  const bool masterOnly,
567  const IOstream::streamFormat format,
568  const word& typeName
569 ) const
570 {
571  bool ok = true;
572  if (Pstream::master() || !masterOnly)
573  {
574  if (debug)
575  {
576  Pout<< "uncollatedFileOperation::read() : "
577  << "reading object " << io.objectPath()
578  << " from file " << endl;
579  }
580 
581  // Set flag for e.g. codeStream
582  const bool oldGlobal = io.globalObject();
583  io.globalObject() = masterOnly;
584  // If codeStream originates from dictionary which is
585  // not IOdictionary we have a problem so use global
586  const bool oldFlag = regIOobject::masterOnlyReading;
587  regIOobject::masterOnlyReading = masterOnly;
588 
589  // Read file
590  ok = io.readData(io.readStream(typeName));
591  io.close();
592 
593  // Restore flags
594  io.globalObject() = oldGlobal;
596  }
597 
598  if (masterOnly && Pstream::parRun())
599  {
600  // Master reads headerclassname from file. Make sure this gets
601  // transfered as well as contents.
603  Pstream::scatter(io.note());
604 
605  // Get my communication order
606  const List<Pstream::commsStruct>& comms =
607  (
611  );
612  const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
613 
614  // Reveive from up
615  if (myComm.above() != -1)
616  {
617  IPstream fromAbove
618  (
620  myComm.above(),
621  0,
624  format
625  );
626  ok = io.readData(fromAbove);
627  }
628 
629  // Send to my downstairs neighbours
630  forAll(myComm.below(), belowI)
631  {
632  OPstream toBelow
633  (
635  myComm.below()[belowI],
636  0,
639  format
640  );
641  bool okWrite = io.writeData(toBelow);
642  ok = ok && okWrite;
643  }
644  }
645  return ok;
646 }
647 
648 
651 (
652  const fileName& filePath
653 ) const
654 {
655  return autoPtr<ISstream>(new IFstream(filePath));
656 }
657 
658 
661 (
662  const fileName& pathName,
666  const bool valid
667 ) const
668 {
669  return autoPtr<Ostream>(new OFstream(pathName, fmt, ver, cmp));
670 }
671 
672 
673 // ************************************************************************* //
time_t lastModified(const fileName &, const bool followLink=true)
Return time of last file modification.
Definition: POSIX.C:594
const labelList & below() const
Definition: UPstream.H:130
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
virtual bool exists(const fileName &, const bool checkGzip=true, const bool followLink=true) const
Does the name exist (as DIRECTORY or FILE) in the file system?
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
bool mv(const fileName &src, const fileName &dst, const bool followLink=false)
Rename src to dst.
Definition: POSIX.C:913
const word & name() const
Return name.
Definition: IOobject.H:291
A class for handling file names.
Definition: fileName.H:69
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
virtual bool mv(const fileName &src, const fileName &dst, const bool followLink=false) const
Rename src to dst.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
virtual bool chMod(const fileName &, const mode_t) const
Set the file mode.
off_t fileSize(const fileName &, const bool followLink=true)
Return size of file.
Definition: POSIX.C:572
Output to file stream.
Definition: OFstream.H:82
static const fileName null
An empty fileName.
Definition: fileName.H:97
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:418
virtual mode_t mode(const fileName &, const bool followLink=true) const
Return the file mode.
static int nProcsSimpleSum
Number of processors at which the sum algorithm changes from linear.
Definition: UPstream.H:266
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
bool cp(const fileName &src, const fileName &dst, const bool followLink=true)
Copy, recursively if necessary, the source to the destination.
Definition: POSIX.C:739
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:412
virtual bool readHeader(IOobject &, const fileName &, const word &typeName) const
Read object header from supplied file.
virtual double highResLastModified(const fileName &, const bool followLink=true) const
Return time of last file modification.
virtual bool read(regIOobject &, const bool masterOnly, const IOstream::streamFormat format, const word &typeName) const
Top-level read.
word format(conversionProperties.lookup("format"))
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:465
virtual bool mkDir(const fileName &, mode_t=0777) const
Make directory.
static label worldComm
Default communicator (all processors)
Definition: UPstream.H:275
virtual fileName filePath(const bool checkGlobal, const IOobject &, const word &typeName) const
Search for an object. checkGlobal : also check undecomposed case.
static const List< commsStruct > & linearCommunication(const label communicator=0)
Communication schedule for linear all-to-master (proc 0)
Definition: UPstream.H:448
bool mvBak(const fileName &, const std::string &ext="bak")
Rename to a corresponding backup file.
Definition: POSIX.C:942
Macros for easy insertion into run-time selection tables.
virtual bool isFile(const fileName &, const bool checkGzip=true, const bool followLink=true) const
Does the name exist as a FILE in the file system?
virtual bool rmDir(const fileName &) const
Remove a dirctory and its contents.
Input inter-processor communications stream.
Definition: IPstream.H:50
addToRunTimeSelectionTable(fileOperation, collatedFileOperation, word)
bool readHeader(Istream &)
Read header.
string & note()
Return non-constant access to the optional note.
Definition: IOobject.H:309
static label splitProcessorPath(const fileName &, fileName &path, fileName &local)
Split fileName into part before processor and part after.
virtual fileNameList readDir(const fileName &, const fileName::Type=fileName::FILE, const bool filtergz=true, const bool followLink=true) const
Read a directory and return the entries as a string list.
virtual bool isDir(const fileName &, const bool followLink=true) const
Does the name exist as a DIRECTORY in the file system?
virtual autoPtr< ISstream > NewIFstream(const fileName &) const
Generate an ISstream that reads a file.
virtual autoPtr< Ostream > NewOFstream(const fileName &pathname, IOstream::streamFormat format=IOstream::ASCII, IOstream::versionNumber version=IOstream::currentVersion, IOstream::compressionType compression=IOstream::UNCOMPRESSED, const bool valid=true) const
Generate an Ostream that writes a file.
void close()
Close Istream.
bool isDir(const fileName &, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:536
A class for handling words, derived from string.
Definition: word.H:59
bool & globalObject()
Is object same for all processors.
Definition: IOobject.H:339
virtual bool cp(const fileName &src, const fileName &dst, const bool followLink=true) const
Copy, recursively if necessary, the source to the destination.
mode_t mode(const fileName &, const bool followLink=true)
Return the file mode.
Definition: POSIX.C:467
word name() const
Return file name (part beyond last /)
Definition: fileName.C:180
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:86
virtual off_t fileSize(const fileName &, const bool followLink=true) const
Return size of file.
static const List< commsStruct > & treeCommunication(const label communicator=0)
Communication schedule for tree all-to-master (proc 0)
Definition: UPstream.H:457
virtual fileName dirPath(const bool checkGlobal, const IOobject &) const
Search for a directory. checkGlobal : also check undecomposed.
virtual time_t lastModified(const fileName &, const bool followLink=true) const
Return time of last file modification.
virtual bool rm(const fileName &) const
Remove a file, returning true if successful otherwise false.
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set)
Definition: autoPtrI.H:83
Structure for communicating between processors.
Definition: UPstream.H:76
bool ln(const fileName &src, const fileName &dst)
Create a softlink. dst should not exist. Returns true if successful.
Definition: POSIX.C:872
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:193
virtual bool ln(const fileName &src, const fileName &dst) const
Create a softlink. dst should not exist. Returns true if.
bool rmDir(const fileName &)
Remove a dirctory and its contents.
Definition: POSIX.C:1008
bool isFile(const fileName &, const bool checkGzip=true, const bool followLink=true)
Does the name exist as a FILE in the file system?
Definition: POSIX.C:551
const Time & time() const
Return time.
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Input from file stream.
Definition: IFstream.H:81
Output inter-processor communications stream.
Definition: OPstream.H:50
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:297
fileName::Type type(const fileName &, const bool followLink=true)
Return the file type: DIRECTORY or FILE.
Definition: POSIX.C:485
uncollatedFileOperation(const bool verbose)
Construct null.
static bool masterOnlyReading
To flag master-only reading of objects.
Definition: regIOobject.H:78
An instant of time. Contains the time value and name.
Definition: instant.H:66
virtual autoPtr< ISstream > readStream(regIOobject &, const fileName &, const word &typeName, const bool procValid=true) const
Reads header for regIOobject and returns an ISstream.
static autoPtr< ISstream > readBlock(const label blocki, Istream &is, IOobject &headerIO)
Read selected block (non-seeking) + header information.
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:394
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:400
static bool readMasterHeader(IOobject &, Istream &)
Read header. Call only on master.
virtual bool mvBak(const fileName &, const std::string &ext="bak") const
Rename to a corresponding backup file.
virtual bool readData(Istream &)
Virtual readData function.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:331
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
static fileName processorsPath(const IOobject &, const word &)
Like io.path with provided instance and any &#39;processorXXX&#39;.
bool chMod(const fileName &, const mode_t)
Set the file mode.
Definition: POSIX.C:453
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
Version number type.
Definition: IOstream.H:96
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:65
fileNameList readDir(const fileName &, const fileName::Type=fileName::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a string list.
Definition: POSIX.C:641
messageStream Info
fileName path() const
Return directory path name (part before last /)
Definition: fileName.C:250
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:52
defineTypeNameAndDebug(collatedFileOperation, 0)
bool rm(const fileName &)
Remove a file, returning true if successful otherwise false.
Definition: POSIX.C:984
Registry of regIOobjects.
virtual bool writeData(Ostream &) const =0
Pure virtual writaData function.
word findInstancePath(const fileName &path, const instant &) const
Search the case for the time directory path.
Definition: Time.C:667
Dummy stream for input. Aborts at any attempt to read from it.
Definition: dummyISstream.H:47
const word & headerClassName() const
Return name of the class name read from header.
Definition: IOobject.H:297
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:92
fileName objectPath() const
Return complete path + object name.
Definition: IOobject.H:412
virtual fileName::Type type(const fileName &, const bool followLink=true) const
Return the file type: DIRECTORY, FILE or LINK.
bool exists(const fileName &, const bool checkGzip=true, const bool followLink=true)
Does the name exist (as DIRECTORY or FILE) in the file system?
Definition: POSIX.C:517
Type
Enumerations to handle file types and modes.
Definition: fileName.H:82
Namespace for OpenFOAM.
double highResLastModified(const fileName &, const bool followLink=true)
Return time of last file modification.
Definition: POSIX.C:616
IOerror FatalIOError
#define InfoInFunction
Report an information message using Foam::Info.