TimeIO.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2016-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "Time.H"
30 #include "argList.H"
31 #include "Pstream.H"
32 #include "simpleObjectRegistry.H"
33 #include "dimensionedConstants.H"
34 #include "profiling.H"
35 #include "IOdictionary.H"
36 #include "fileOperation.H"
37 #include "fstreamPointer.H"
38 
39 #include <iomanip>
40 
41 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
42 
43 namespace Foam
44 {
45 
46 // Output seconds as day-hh:mm:ss
47 static std::ostream& printTimeHMS(std::ostream& os, double seconds)
48 {
49  const unsigned long ss = seconds;
50 
51  // days
52  const auto dd = (ss / 86400);
53 
54  if (dd) os << dd << '-';
55 
56  // hours
57  const int hh = ((ss / 3600) % 24);
58 
59  if (dd || hh)
60  {
61  os << std::setw(2) << std::setfill('0')
62  << hh << ':';
63  }
64 
65  // minutes
66  os << std::setw(2) << std::setfill('0')
67  << ((ss / 60) % 60) << ':';
68 
69  // seconds
70  os << std::setw(2) << std::setfill('0')
71  << (ss % 60);
72 
73 
74  // 1/100th seconds. As none or 2 decimal places
75  const int hundredths = int(100 * (seconds - ss)) % 100;
76 
77  if (hundredths)
78  {
79  os << '.' << std::setw(2) << std::setfill('0') << hundredths;
80  }
81 
82  return os;
83 }
84 
85 } // End namespace Foam
86 
87 
88 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
89 
91 {
92  word application;
93  if (controlDict_.readIfPresent("application", application))
94  {
95  // Do not override if already set so external application can override
96  setEnv("FOAM_APPLICATION", application, false);
97  }
98 
99  // Check for local switches and settings
100 
101  const dictionary* localDict = nullptr;
102 
103  // DebugSwitches
104  if
105  (
106  (localDict = controlDict_.findDict("DebugSwitches")) != nullptr
107  && localDict->size()
108  )
109  {
110  DetailInfo
111  << "Overriding DebugSwitches according to "
112  << controlDict_.name() << nl;
113 
114  debug::debugObjects().setValues(*localDict, true);
115  }
116 
117 
118  // InfoSwitches
119  if
120  (
121  (localDict = controlDict_.findDict("InfoSwitches")) != nullptr
122  && localDict->size()
123  )
124  {
125  DetailInfo
126  << "Overriding InfoSwitches according to "
127  << controlDict_.name() << nl;
128 
129  debug::infoObjects().setValues(*localDict, true);
130  }
131 
132  // OptimisationSwitches
133  if
134  (
135  (localDict = controlDict_.findDict("OptimisationSwitches")) != nullptr
136  && localDict->size()
137  )
138  {
139  DetailInfo
140  << "Overriding OptimisationSwitches according to "
141  << controlDict_.name() << nl;
142 
143  debug::optimisationObjects().setValues(*localDict, true);
144  }
145 
146 
147  // Handle fileHandler explicitly since it affects local dictionary
148  // monitoring.
149  word fileHandlerName;
150  if
151  (
152  localDict
153  && localDict->readIfPresent("fileHandler", fileHandlerName)
154  && fileHandler().type() != fileHandlerName
155  )
156  {
157  DetailInfo << "Overriding fileHandler to " << fileHandlerName << nl;
158 
159  // Remove old watches since destroying the file
160  fileNameList oldWatched(controlDict_.watchIndices().size());
161  forAllReverse(controlDict_.watchIndices(), i)
162  {
163  const label watchi = controlDict_.watchIndices()[i];
164  oldWatched[i] = fileHandler().getFile(watchi);
165  fileHandler().removeWatch(watchi);
166  }
167  controlDict_.watchIndices().clear();
168 
169  // The new handler, with verbosity
170  autoPtr<fileOperation> newHandler =
171  fileOperation::New(fileHandlerName, true);
172 
173  if (TimePaths::distributed() && newHandler)
174  {
175  newHandler->distributed(true);
176  }
177 
178  // Installing the new handler
179  Foam::fileHandler(std::move(newHandler));
180 
181  // Reinstall old watches
182  fileHandler().addWatches(controlDict_, oldWatched);
183  }
184 
185 
186  // DimensionedConstants.
187  // - special case since it may change both the 'unitSet' and the
188  // individual values
189  if
190  (
191 
192  (localDict = controlDict_.findDict("DimensionedConstants")) != nullptr
193  && localDict->size()
194  )
195  {
196  DetailInfo
197  << "Overriding DimensionedConstants according to "
198  << controlDict_.name() << nl;
199 
200  simpleObjectRegistry& objs = debug::dimensionedConstantObjects();
201 
202  // Change in-memory
203  dimensionedConstants().merge(*localDict);
204 
205  IStringStream dummyIs("");
206 
207  forAllConstIters(objs, iter)
208  {
209  const List<simpleRegIOobject*>& objects = *iter;
210 
211  for (simpleRegIOobject* obj : objects)
212  {
213  obj->readData(dummyIs);
214 
215  if (Foam::infoDetailLevel > 0)
216  {
217  Info<< " ";
218  obj->writeData(Info);
219  Info<< nl;
220  }
221  }
222  }
223  }
224 
225 
226  // DimensionSets
227  if
228  (
229  (localDict = controlDict_.findDict("DimensionSets")) != nullptr
230  && localDict->size()
231  )
232  {
233  DetailInfo
234  << "Overriding DimensionSets according to "
235  << controlDict_.name() << nl;
236 
237  simpleObjectRegistry& objs = debug::dimensionSetObjects();
238 
239  dictionary dict(Foam::dimensionSystems());
240  dict.merge(*localDict);
241 
242  simpleObjectRegistryEntry* objPtr = objs.find("DimensionSets");
243 
244  if (objPtr)
245  {
246  DetailInfo << *localDict << nl;
247 
248  const List<simpleRegIOobject*>& objects = *objPtr;
249 
250  for (simpleRegIOobject* obj : objects)
251  {
252  OStringStream os;
253  os << dict;
254  IStringStream is(os.str());
255  obj->readData(is);
256  }
257  }
258  }
259 
260 
261  if (!deltaTchanged_)
262  {
263  controlDict_.readEntry("deltaT", deltaT_);
264  }
265 
267  (
268  "writeControl",
269  controlDict_,
271  );
272 
273  scalar oldWriteInterval = writeInterval_;
274 
275  if (controlDict_.readIfPresent("writeInterval", writeInterval_))
276  {
277  if (writeControl_ == wcTimeStep && label(writeInterval_) < 1)
278  {
279  FatalIOErrorInFunction(controlDict_)
280  << "writeInterval < 1 for writeControl timeStep"
281  << exit(FatalIOError);
282  }
283  }
284  else
285  {
286  controlDict_.readEntry("writeFrequency", writeInterval_);
287  }
288 
289 
290  if (oldWriteInterval != writeInterval_)
291  {
292  switch (writeControl_)
293  {
294  case wcRunTime:
295  case wcAdjustableRunTime:
296  // Recalculate writeTimeIndex_ to be in units of current
297  // writeInterval.
298  writeTimeIndex_ = label
299  (
301  * oldWriteInterval
303  );
304  break;
305 
306  default:
307  break;
308  }
309  }
310 
311  if (controlDict_.readIfPresent("purgeWrite", purgeWrite_))
312  {
313  if (purgeWrite_ < 0)
314  {
316  << "invalid value for purgeWrite " << purgeWrite_
317  << ", should be >= 0, setting to 0"
318  << endl;
319 
320  purgeWrite_ = 0;
321  }
322  }
323 
324  if (controlDict_.found("timeFormat"))
325  {
326  const word formatName(controlDict_.get<word>("timeFormat"));
327 
328  if (formatName == "general")
329  {
330  format_ = general;
331  }
332  else if (formatName == "fixed")
333  {
334  format_ = fixed;
335  }
336  else if (formatName == "scientific")
337  {
339  }
340  else
341  {
343  << "unsupported time format " << formatName
344  << endl;
345  }
346  }
347 
348  controlDict_.readIfPresent("timePrecision", precision_);
349 
350  // stopAt at 'endTime' or a specified value
351  // if nothing is specified, the endTime is zero
352  if (stopAtControlNames.readIfPresent("stopAt", controlDict_, stopAt_))
353  {
354  if (stopAt_ == saEndTime)
355  {
356  controlDict_.readEntry("endTime", endTime_);
357  }
358  else
359  {
360  endTime_ = GREAT;
361  }
362  }
363  else if (!controlDict_.readIfPresent("endTime", endTime_))
364  {
365  endTime_ = 0;
366  }
367 
369 
370  if (controlDict_.found("writeVersion"))
371  {
372  writeStreamOption_.version(controlDict_.get<token>("writeVersion"));
373  }
374 
375  if (controlDict_.found("writeFormat"))
376  {
377  writeStreamOption_.format(controlDict_.get<word>("writeFormat"));
378  }
379 
380  if (controlDict_.found("writePrecision"))
381  {
383  (
384  controlDict_.get<unsigned int>("writePrecision")
385  );
386 
389 
392 
395  }
396 
397  if (controlDict_.found("writeCompression"))
398  {
399  writeStreamOption_.compression
400  (
401  controlDict_.get<word>("writeCompression")
402  );
403 
404  if (writeStreamOption_.compression() == IOstreamOption::COMPRESSED)
405  {
406  if (writeStreamOption_.format() == IOstreamOption::BINARY)
407  {
408  IOWarningInFunction(controlDict_)
409  << "Disabled binary format compression"
410  << " (inefficient/ineffective)"
411  << endl;
412 
413  writeStreamOption_.compression(IOstreamOption::UNCOMPRESSED);
414  }
415  else if (!ofstreamPointer::supports_gz())
416  {
417  IOWarningInFunction(controlDict_)
418  << "Disabled output compression"
419  << " (missing libz support)"
420  << endl;
421 
422  writeStreamOption_.compression(IOstreamOption::UNCOMPRESSED);
423  }
424  }
425  }
426 
427  controlDict_.readIfPresent("graphFormat", graphFormat_);
428  controlDict_.readIfPresent("runTimeModifiable", runTimeModifiable_);
429 
430 
431  if (!runTimeModifiable_ && controlDict_.watchIndices().size())
432  {
433  forAllReverse(controlDict_.watchIndices(), i)
434  {
435  fileHandler().removeWatch(controlDict_.watchIndices()[i]);
436  }
437  controlDict_.watchIndices().clear();
438  }
439 }
440 
441 
442 bool Foam::Time::read()
443 {
444  if (controlDict_.regIOobject::read())
445  {
446  // Read contents
447  readDict();
448  functionObjects_.read();
449 
450  if (runTimeModifiable_)
451  {
452  // For IOdictionary the call to regIOobject::read() would have
453  // already updated all the watchIndices via the addWatch but
454  // controlDict_ is an unwatchedIOdictionary so will only have
455  // stored the dependencies as files.
456  fileHandler().addWatches(controlDict_, controlDict_.files());
457  }
458  controlDict_.files().clear();
459 
460  return true;
461  }
462 
463  return false;
464 }
465 
466 
468 {
469  if (runTimeModifiable_)
470  {
471  // Get state of all monitored objects (=registered objects with a
472  // valid filePath).
473  // Note: requires same ordering in objectRegistries on different
474  // processors!
475  fileHandler().updateStates
476  (
477  (
480  ),
482  );
483  // Time handling is special since controlDict_ is the one dictionary
484  // that is not registered to any database.
485 
486  if (controlDict_.readIfModified())
487  {
488  readDict();
489  functionObjects_.read();
490 
491  if (runTimeModifiable_)
492  {
493  // For IOdictionary the call to regIOobject::read() would have
494  // already updated all the watchIndices via the addWatch but
495  // controlDict_ is an unwatchedIOdictionary so will only have
496  // stored the dependencies as files.
497 
498  fileHandler().addWatches(controlDict_, controlDict_.files());
499  }
500  controlDict_.files().clear();
501  }
502 
503  bool registryModified = objectRegistry::modified();
504 
505  if (registryModified)
506  {
508  }
509  }
510 }
511 
512 
513 bool Foam::Time::writeTimeDict() const
514 {
515  addProfiling(writing, "objectRegistry::writeObject");
516 
517  const word tmName(timeName());
518 
519  IOdictionary timeDict
520  (
521  IOobject
522  (
523  "time",
524  tmName,
525  "uniform",
526  *this,
529  false
530  )
531  );
532 
533  timeDict.add("value", timeName(timeToUserTime(value()), maxPrecision_));
534  timeDict.add("name", string(tmName));
535  timeDict.add("index", timeIndex_);
536  timeDict.add("deltaT", timeToUserTime(deltaT_));
537  timeDict.add("deltaT0", timeToUserTime(deltaT0_));
538 
539  return timeDict.regIOobject::writeObject
540  (
542  true
543  );
544 }
545 
546 
548 (
549  IOstreamOption streamOpt,
550  const bool valid
551 ) const
552 {
553  if (writeTime())
554  {
555  bool writeOK = writeTimeDict();
556 
557  if (writeOK)
558  {
559  writeOK = objectRegistry::writeObject(streamOpt, valid);
560  }
561 
562  if (writeOK)
563  {
564  // Does the writeTime trigger purging?
565  if (writeTime_ && purgeWrite_)
566  {
567  if
568  (
569  previousWriteTimes_.empty()
570  || previousWriteTimes_.top() != timeName()
571  )
572  {
573  previousWriteTimes_.push(timeName());
574  }
575 
576  while (previousWriteTimes_.size() > purgeWrite_)
577  {
578  fileHandler().rmDir
579  (
580  fileHandler().filePath
581  (
582  objectRegistry::path(previousWriteTimes_.pop()),
583  false // No .gz check (is directory)
584  )
585  );
586  }
587  }
588  }
589 
590  return writeOK;
591  }
592 
593  return false;
594 }
595 
596 
598 {
599  writeTime_ = true;
600  return write();
601 }
602 
603 
605 {
606  stopAt_ = saWriteNow;
607  endTime_ = value();
608 
609  return writeNow();
610 }
611 
614 {
615  writeOnce_ = true;
616 }
617 
618 
620 {
621  switch (printExecutionFormat_)
622  {
623  case 1:
624  {
625  os << "ExecutionTime = ";
626  printTimeHMS(os.stdStream(), elapsedCpuTime());
627 
628  os << " ClockTime = ";
629  printTimeHMS(os.stdStream(), elapsedClockTime());
630  }
631  break;
632 
633  default:
634  {
635  os << "ExecutionTime = " << elapsedCpuTime() << " s"
636  << " ClockTime = " << elapsedClockTime() << " s";
637  }
638  break;
639  }
640 
641  os << nl << endl;
642 
643  return os;
644 }
645 
646 
647 // ************************************************************************* //
Omanip< char > setfill(char fillch)
Definition: IOmanip.H:175
prefixOSstream Perr
OSstream wrapped stderr (std::cerr) with parallel prefix.
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:50
const Type & value() const noexcept
Return const reference to value.
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
#define addProfiling(name, descr)
Define profiling trigger with specified name and description string.
scalar deltaT_
Definition: TimeState.H:56
bool writeAndEnd()
Write the objects now (not at end of iteration) and end the run.
Definition: TimeIO.C:597
stopAtControls stopAt_
Definition: Time.H:171
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void readModifiedObjects()
Read the objects that have been modified.
virtual int precision() const
Get precision of output field.
Definition: OSstream.C:305
Dictionary reading and supplying the dimensioned constants used within OpenFOAM, particularly for the...
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
virtual bool writeObject(IOstreamOption streamOpt, const bool valid) const
Write the objects using stream options.
scalar writeInterval_
Definition: Time.H:175
int infoDetailLevel
Global for selective suppression of Info output.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
"ascii" (normal default)
static std::ostream & printTimeHMS(std::ostream &os, double seconds)
Definition: TimeIO.C:40
virtual bool modified() const
Return true if any of the object&#39;s files have been modified.
static fmtflags format_
Time directory name format.
Definition: Time.H:209
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:639
static bool supports_gz()
True if compiled with libz support.
static unsigned int defaultPrecision() noexcept
Return the default precision.
Definition: IOstream.H:416
autoPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler.
static const Enum< stopAtControls > stopAtControlNames
Names for stopAtControls.
Definition: Time.H:125
A simple container for options an IOstream can normally have.
virtual std::ostream & stdStream()
Access to underlying std::ostream.
Definition: OFstream.C:110
Ignore writing from objectRegistry::writeObject()
simpleObjectRegistry & debugObjects()
Access to registered DebugSwitch objects.
Definition: debug.C:288
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
writeControls writeControl_
Definition: Time.H:173
virtual word timeName() const
Return current time name.
Definition: Time.C:770
"runTime"
Definition: Time.H:86
label writeTimeIndex_
Definition: TimeState.H:54
simpleObjectRegistry & optimisationObjects()
Access to registered OptimisationSwitch objects.
Definition: debug.C:310
fileName path() const
The complete path.
Definition: IOobject.C:465
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:100
dictionary & dimensionedConstants()
virtual bool writeTimeDict() const
Write time dictionary to the <time>/uniform directory.
Definition: TimeIO.C:506
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, IOobjectOption::readOption readOpt=IOobjectOption::MUST_READ) const
Find entry and assign to T val. FatalIOError if it is found and the number of tokens is incorrect...
label purgeWrite_
Definition: Time.H:177
word timeName
Definition: getTimeIndex.H:3
bool merge(const dictionary &dict)
Merge entries from the given dictionary.
Definition: dictionary.C:811
"adjustable" / "adjustableRunTime"
Definition: Time.H:87
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
"timeStep"
Definition: Time.H:85
void setValues(const dictionary &dict, bool report=false)
Set values (invoke callbacks) from dictionary entries.
static int precision_
Time directory name precision.
Definition: Time.H:214
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:109
static const Enum< writeControls > writeControlNames
Names for writeControls.
Definition: Time.H:120
OSstream Sout
OSstream wrapped stdout (std::cout)
scalar endTime_
Definition: Time.H:169
const word & name() const
Name function is needed to disambiguate those inherited from regIOobject and dictionary.
#define DetailInfo
Definition: evalEntry.C:30
fixed-point notation
Definition: Time.H:112
scientific notation
Definition: Time.H:113
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:55
const labelList & watchIndices() const noexcept
Read access to file-monitoring handles.
Definition: regIOobjectI.H:195
bool distributed() const noexcept
True if case running with parallel distributed directories (ie. not NFS mounted)
Definition: TimePathsI.H:23
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
OBJstream os(runTime.globalPath()/outputName)
virtual void readDict()
Read the control dictionary and set the write controls etc.
Definition: TimeIO.C:83
simpleObjectRegistry & infoObjects()
Access to registered InfoSwitch objects.
Definition: debug.C:299
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:313
compressionType compression() const noexcept
Get the stream compression.
default float notation
Definition: Time.H:111
Ostream & printExecutionTime(OSstream &os) const
Print the elapsed ExecutionTime (cpu-time), ClockTime.
Definition: TimeIO.C:612
static autoPtr< fileOperation > New(const word &handlerType, bool verbose=false)
Select fileHandler-type. Uses defaultFileHandler if the handlerType is empty.
void readModifiedObjects()
Read the objects that have been modified.
Definition: TimeIO.C:460
simpleObjectRegistry & dimensionSetObjects()
Access to registered DimensionSets objects.
Definition: debug.C:321
bool deltaTchanged_
Definition: TimeState.H:60
const word & name() const noexcept
Return const reference to name.
void writeOnce()
Write the objects once (one shot) and continue the run.
Definition: TimeIO.C:606
dictionary & dimensionSystems()
Top level dictionary.
Definition: dimensionSets.C:86
virtual bool read()
Read control dictionary, update controls and time.
Definition: TimeIO.C:435
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
OSstream & stream()
Return OSstream for output operations.
Definition: error.C:300
Stop when Time reaches prescribed endTime.
Definition: Time.H:99
simpleObjectRegistry & dimensionedConstantObjects()
Access to registered DimensionedConstants objects.
Definition: debug.C:332
Nothing to be read.
versionNumber version() const noexcept
Get the stream version.
bool readIfPresent(const word &key, const dictionary &dict, EnumType &val) const
Find an entry if present, and assign to T val.
Definition: EnumI.H:125
OSstream Serr
OSstream wrapped stderr (std::cerr)
messageStream Info
Information stream (stdout output on master, null elsewhere)
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:429
List< fileName > fileNameList
A List of fileNames.
Definition: fileNameList.H:54
streamFormat format() const noexcept
Get the current stream format.
bool setEnv(const word &name, const std::string &value, const bool overwrite)
Set an environment variable, return true on success.
Definition: POSIX.C:309
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
bool writeNow()
Write the objects immediately (not at end of iteration) and continue the run.
Definition: TimeIO.C:590
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
virtual bool writeObject(IOstreamOption streamOpt, const bool valid) const
Write using stream options.
Definition: TimeIO.C:541
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and a sub-dictionary) otherwise return nullptr...
Definition: dictionaryI.H:120
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...