Time.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) 2015-2022 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 "PstreamReduceOps.H"
31 #include "argList.H"
32 #include "HashSet.H"
33 #include "profiling.H"
34 #include "IOdictionary.H"
35 #include "registerSwitch.H"
36 #include <sstream>
37 
38 // * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(Time, 0);
43 }
44 
45 const Foam::Enum
46 <
48 >
50 ({
51  { stopAtControls::saEndTime, "endTime" },
52  { stopAtControls::saNoWriteNow, "noWriteNow" },
53  { stopAtControls::saWriteNow, "writeNow" },
54  { stopAtControls::saNextWrite, "nextWrite" },
55  // Leave saUnknown untabulated - fallback to flag unknown settings
56 });
57 
58 
59 const Foam::Enum
60 <
62 >
64 ({
65  { writeControls::wcNone, "none" },
66  { writeControls::wcTimeStep, "timeStep" },
67  { writeControls::wcRunTime, "runTime" },
68  { writeControls::wcAdjustableRunTime, "adjustable" },
69  { writeControls::wcAdjustableRunTime, "adjustableRunTime" },
70  { writeControls::wcClockTime, "clockTime" },
71  { writeControls::wcCpuTime, "cpuTime" },
72  // Leave wcUnknown untabulated - fallback to flag unknown settings
73 });
74 
75 
77 
79 
80 const int Foam::Time::maxPrecision_(3 - log10(SMALL));
81 
83 
85 (
86  Foam::debug::infoSwitch("printExecutionFormat", 0)
87 );
88 
90 (
91  "printExecutionFormat",
92  int,
94 );
95 
96 
97 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
98 
100 {
101  bool adjustTime = false;
102  scalar timeToNextWrite = VGREAT;
103 
105  {
106  adjustTime = true;
107  timeToNextWrite = max
108  (
109  0.0,
111  );
112  }
113 
114  if (adjustTime)
115  {
116  scalar nSteps = timeToNextWrite/deltaT_;
117 
118  // For tiny deltaT the label can overflow!
119  if (nSteps < scalar(labelMax))
120  {
121  // nSteps can be < 1 so make sure at least 1
122  label nStepsToNextWrite = max(1, round(nSteps));
123 
124  scalar newDeltaT = timeToNextWrite/nStepsToNextWrite;
125 
126  // Control the increase of the time step to within a factor of 2
127  // and the decrease within a factor of 5.
128  if (newDeltaT >= deltaT_)
129  {
130  deltaT_ = min(newDeltaT, 2.0*deltaT_);
131  }
132  else
133  {
134  deltaT_ = max(newDeltaT, 0.2*deltaT_);
135  }
136  }
137  }
138 
139  functionObjects_.adjustTimeStep();
140 }
141 
142 
144 {
145  // default is to resume calculation from "latestTime"
146  const word startFrom = controlDict_.getOrDefault<word>
147  (
148  "startFrom",
149  "latestTime"
150  );
151 
152  if (startFrom == "startTime")
153  {
154  controlDict_.readEntry("startTime", startTime_);
155  }
156  else
157  {
158  // Search directory for valid time directories
159  instantList timeDirs = findTimes(path(), constant());
160 
161  const label nTimes = timeDirs.size();
162 
163  if (startFrom == "firstTime")
164  {
165  if (nTimes > 1 && timeDirs.first().name() == constant())
166  {
167  startTime_ = timeDirs[1].value();
168  }
169  else if (nTimes)
170  {
171  startTime_ = timeDirs.first().value();
172  }
173  }
174  else if (startFrom == "latestTime")
175  {
176  if (nTimes)
177  {
178  startTime_ = timeDirs.last().value();
179  }
180  }
181  else
182  {
183  FatalIOErrorInFunction(controlDict_)
184  << "expected startTime, firstTime or latestTime"
185  << " found '" << startFrom << "'"
186  << exit(FatalIOError);
187  }
188  }
189 
190  setTime(startTime_, 0);
191 
192  readDict();
193  deltaTSave_ = deltaT_;
194  deltaT0_ = deltaT_;
195 
196  // Check if time directory exists
197  // If not increase time precision to see if it is formatted differently.
198  // Note: - do not use raw fileHandler().exists(...) since does not check
199  // alternative processorsDDD directories naming
200  // - do not look for compressed (is directory)
201 
202  if (fileHandler().filePath(timePath(), false).empty())
203  {
204  const int oldPrecision = precision_;
205  int requiredPrecision = -1;
206  word oldTime(timeName());
207  for
208  (
209  precision_ = maxPrecision_;
210  precision_ > oldPrecision;
211  --precision_
212  )
213  {
214  // Update the time formatting
215  setTime(startTime_, 0);
216 
217  word newTime(timeName());
218  if (newTime == oldTime)
219  {
220  break;
221  }
222  oldTime = std::move(newTime);
223 
224  // Does a time directory exist with the new format?
225  if (!fileHandler().filePath(timePath(), false).empty())
226  {
227  requiredPrecision = precision_;
228  }
229  }
230 
231  if (requiredPrecision > 0)
232  {
233  // Update the time precision
234  precision_ = requiredPrecision;
235 
236  // Update the time formatting
237  setTime(startTime_, 0);
238 
240  << "Increasing the timePrecision from " << oldPrecision
241  << " to " << precision_
242  << " to support the formatting of the current time directory "
243  << timeName() << nl << endl;
244  }
245  else
246  {
247  // Could not find time directory so assume it is not present
248  precision_ = oldPrecision;
249 
250  // Revert the time formatting
251  setTime(startTime_, 0);
252  }
253  }
254 
255  if (Pstream::parRun())
256  {
257  scalar sumStartTime = startTime_;
258  reduce(sumStartTime, sumOp<scalar>());
259  if
260  (
261  mag(Pstream::nProcs()*startTime_ - sumStartTime)
262  > Pstream::nProcs()*deltaT_/10.0
263  )
264  {
265  FatalIOErrorInFunction(controlDict_)
266  << "Start time is not the same for all processors" << nl
267  << "processor " << Pstream::myProcNo() << " has startTime "
268  << startTime_ << exit(FatalIOError);
269  }
270  }
271 
272  IOdictionary timeDict
273  (
274  IOobject
275  (
276  "time",
277  timeName(),
278  "uniform",
279  *this,
283  )
284  );
285 
286  // Read and set the deltaT only if time-step adjustment is active
287  // otherwise use the deltaT from the controlDict
288  if (controlDict_.getOrDefault("adjustTimeStep", false))
289  {
290  if (timeDict.readIfPresent("deltaT", deltaT_))
291  {
292  deltaTSave_ = deltaT_;
293  deltaT0_ = deltaT_;
294  }
295  }
296 
297  timeDict.readIfPresent("deltaT0", deltaT0_);
298 
299  if (timeDict.readIfPresent("index", startTimeIndex_))
300  {
301  timeIndex_ = startTimeIndex_;
302  }
303 
304 
305  // Check if values stored in time dictionary are consistent
306 
307  // 1. Based on time name
308  bool checkValue = true;
309 
310  string storedTimeName;
311  if (timeDict.readIfPresent("name", storedTimeName))
312  {
313  if (storedTimeName == timeName())
314  {
315  // Same time. No need to check stored value
316  checkValue = false;
317  }
318  }
319 
320  // 2. Based on time value
321  // (consistent up to the current time writing precision so it won't
322  // trigger if we just change the write precision)
323  if (checkValue)
324  {
325  scalar storedTimeValue;
326  if (timeDict.readIfPresent("value", storedTimeValue))
327  {
328  word storedTimeName(timeName(storedTimeValue));
329 
330  if (storedTimeName != timeName())
331  {
332  IOWarningInFunction(timeDict)
333  << "Time read from time dictionary " << storedTimeName
334  << " differs from actual time " << timeName() << '.' << nl
335  << " This may cause unexpected database behaviour."
336  << " If you are not interested" << nl
337  << " in preserving time state delete"
338  << " the time dictionary."
339  << endl;
340  }
341  }
342  }
343 }
344 
345 
346 void Foam::Time::setMonitoring(const bool forceProfiling)
347 {
348  const dictionary* profilingDict = controlDict_.findDict("profiling");
349  if (!profilingDict)
350  {
351  // ... or from etc/controlDict
352  profilingDict = debug::controlDict().findDict("profiling");
353  }
354 
355  // initialize profiling on request
356  // otherwise rely on profiling entry within controlDict
357  // and skip if 'active' keyword is explicitly set to false
358  if (forceProfiling)
359  {
361  (
362  IOobject
363  (
364  "profiling",
365  timeName(),
366  "uniform",
367  *this,
370  ),
371  *this
372  );
373  }
374  else if
375  (
376  profilingDict
377  && profilingDict->getOrDefault("active", true)
378  )
379  {
381  (
382  *profilingDict,
383  IOobject
384  (
385  "profiling",
386  timeName(),
387  "uniform",
388  *this,
391  ),
392  *this
393  );
394  }
395 
396  // Time objects not registered so do like objectRegistry::checkIn ourselves.
397  if (runTimeModifiable_)
398  {
399  // Monitor all files that controlDict depends on
400  // Files might have been set during token reading so only on master
401  // processor. Broadcast names to all processors
402  // (even although they are only checked on master)
403  // so that the watched states are synchronised
404 
405  Pstream::broadcast(controlDict_.files(), UPstream::worldComm);
406  fileHandler().addWatches(controlDict_, controlDict_.files());
407  }
408 
409  // Clear dependent files - not needed now
410  controlDict_.files().clear();
411 }
412 
413 
414 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
415 
417 (
418  const word& ctrlDictName,
419  const fileName& rootPath,
420  const fileName& caseName,
421  const word& systemName,
422  const word& constantName,
423  const bool enableFunctionObjects,
424  const bool enableLibs
425 )
426 :
427  TimePaths
428  (
429  rootPath,
430  caseName,
431  systemName,
432  constantName
433  ),
434 
435  objectRegistry(*this),
436 
437  loopProfiling_(nullptr),
438  libs_(),
439 
440  controlDict_
441  (
442  IOobject
443  (
444  ctrlDictName,
445  system(),
446  *this,
447  IOobject::MUST_READ_IF_MODIFIED,
448  IOobject::NO_WRITE,
449  IOobject::NO_REGISTER
450  )
451  ),
452 
453  startTimeIndex_(0),
454  startTime_(0),
455  endTime_(0),
456 
457  stopAt_(saEndTime),
458  writeControl_(wcTimeStep),
459  writeInterval_(GREAT),
460  purgeWrite_(0),
461  subCycling_(0),
462  writeOnce_(false),
463  sigWriteNow_(*this, true),
464  sigStopAtWriteNow_(*this, true),
465  writeStreamOption_(IOstreamOption::ASCII),
466  graphFormat_("raw"),
467  runTimeModifiable_(false),
468  cacheTemporaryObjects_(true),
469  functionObjects_(*this, false)
470 {
471  if (enableFunctionObjects)
472  {
473  functionObjects_.on();
474  }
475 
476  if (enableLibs)
477  {
478  libs_.open("libs", controlDict_);
479  }
480 
481  // Explicitly set read flags on objectRegistry so anything constructed
482  // from it reads as well (e.g. fvSolution).
485  setControls();
486  setMonitoring();
487 }
488 
489 
491 (
492  const word& ctrlDictName,
493  const argList& args,
494  const word& systemName,
495  const word& constantName,
496  const bool enableFunctionObjects,
497  const bool enableLibs
498 )
499 :
500  TimePaths(args, systemName, constantName),
501 
502  objectRegistry(*this),
503 
504  loopProfiling_(nullptr),
505  libs_(),
506 
507  controlDict_
508  (
509  IOobject
510  (
511  ctrlDictName,
512  system(),
513  *this,
514  IOobject::MUST_READ_IF_MODIFIED,
515  IOobject::NO_WRITE,
516  IOobject::NO_REGISTER
517  )
518  ),
519 
520  startTimeIndex_(0),
521  startTime_(0),
522  endTime_(0),
523 
524  stopAt_(saEndTime),
525  writeControl_(wcTimeStep),
526  writeInterval_(GREAT),
527  purgeWrite_(0),
528  subCycling_(0),
529  writeOnce_(false),
530  sigWriteNow_(*this, true),
531  sigStopAtWriteNow_(*this, true),
532  writeStreamOption_(IOstreamOption::ASCII),
533  graphFormat_("raw"),
534  runTimeModifiable_(false),
535  cacheTemporaryObjects_(true),
536  functionObjects_(*this, false)
537 {
538  // Functions
539  //
540  // * '-withFunctionObjects' exists and used = enable
541  // * '-noFunctionObjects' exists and used = disable
542  // * default: no functions if there is no way to enable/disable them
543  if (enableFunctionObjects && args.allowFunctionObjects())
544  {
545  functionObjects_.on();
546  }
547 
548  // Libraries
549  //
550  // * enable by default unless '-no-libs' option was used
551  if (enableLibs && args.allowLibs())
552  {
553  libs_.open("libs", controlDict_);
554  }
555 
556  // Explicitly set read flags on objectRegistry so anything constructed
557  // from it reads as well (e.g. fvSolution).
559 
560  setControls();
562  // '-profiling' = force profiling, ignore controlDict entry
563  setMonitoring(args.found("profiling"));
564 }
565 
566 
568 (
569  const dictionary& dict,
570  const fileName& rootPath,
571  const fileName& caseName,
572  const word& systemName,
573  const word& constantName,
574  const bool enableFunctionObjects,
575  const bool enableLibs
576 )
577 :
578  TimePaths
579  (
580  rootPath,
581  caseName,
582  systemName,
583  constantName
584  ),
585 
586  objectRegistry(*this),
587 
588  loopProfiling_(nullptr),
589  libs_(),
590 
591  controlDict_
592  (
593  IOobject
594  (
595  controlDictName,
596  system(),
597  *this,
598  IOobject::NO_READ,
599  IOobject::NO_WRITE,
600  IOobject::NO_REGISTER
601  ),
602  dict
603  ),
604 
605  startTimeIndex_(0),
606  startTime_(0),
607  endTime_(0),
608 
609  stopAt_(saEndTime),
610  writeControl_(wcTimeStep),
611  writeInterval_(GREAT),
612  purgeWrite_(0),
613  subCycling_(0),
614  writeOnce_(false),
615  sigWriteNow_(*this, true),
616  sigStopAtWriteNow_(*this, true),
617  writeStreamOption_(IOstreamOption::ASCII),
618  graphFormat_("raw"),
619  runTimeModifiable_(false),
620  cacheTemporaryObjects_(true),
621  functionObjects_(*this, false)
622 {
623  if (enableFunctionObjects)
624  {
625  functionObjects_.on();
626  }
627 
628  if (enableLibs)
629  {
630  libs_.open("libs", controlDict_);
631  }
632 
633 
634  // Explicitly set read flags on objectRegistry so anything constructed
635  // from it reads as well (e.g. fvSolution).
637 
638  // Since could not construct regIOobject with setting:
641  setControls();
642  setMonitoring();
643 }
644 
645 
647 (
648  const fileName& rootPath,
649  const fileName& caseName,
650  const word& systemName,
651  const word& constantName,
652  const bool enableFunctionObjects,
653  const bool enableLibs
654 )
655 :
656  TimePaths
657  (
658  rootPath,
659  caseName,
660  systemName,
661  constantName
662  ),
663 
664  objectRegistry(*this),
665 
666  loopProfiling_(nullptr),
667  libs_(),
668 
669  controlDict_
670  (
671  IOobject
672  (
673  controlDictName,
674  system(),
675  *this,
676  IOobject::NO_READ,
677  IOobject::NO_WRITE,
678  IOobject::NO_REGISTER
679  )
680  ),
681 
682  startTimeIndex_(0),
683  startTime_(0),
684  endTime_(0),
685 
686  stopAt_(saEndTime),
687  writeControl_(wcTimeStep),
688  writeInterval_(GREAT),
689  purgeWrite_(0),
690  subCycling_(0),
691  writeOnce_(false),
692  writeStreamOption_(IOstreamOption::ASCII),
693  graphFormat_("raw"),
694  runTimeModifiable_(false),
695  cacheTemporaryObjects_(true),
696  functionObjects_(*this, false)
697 {
698  if (enableFunctionObjects)
699  {
700  functionObjects_.on();
701  }
702 
703  if (enableLibs)
704  {
705  libs_.open("libs", controlDict_);
706  }
708  setMonitoring(); // for profiling etc
709 }
710 
711 
712 // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
713 
715 {
716  return
718  (
719  fileName("."), // root-path
720  fileName("."), // case-name
721  false, // No enableFunctionObjects
722  false // No enableLibs
723  );
724 }
725 
726 
728 {
729  return
731  (
732  caseDir.path(), // root-path
733  caseDir.name(), // case-name
734  false, // No enableFunctionObjects
735  false // No enableLibs
736  );
737 }
738 
739 
741 {
742  return
744  (
746  args,
747  false, // No enableFunctionObjects
748  false // No enableLibs
749  );
750 }
751 
752 
753 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
754 
756 {
757  loopProfiling_.reset(nullptr);
758 
759  forAllReverse(controlDict_.watchIndices(), i)
760  {
761  fileHandler().removeWatch(controlDict_.watchIndices()[i]);
762  }
763 
764  // Destroy function objects first
765  functionObjects_.clear();
766 
767  // Clean up profiling
768  profiling::stop(*this);
769 
770  // Ensure all owned objects are also cleaned up now
772 }
773 
774 
775 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
776 
777 Foam::word Foam::Time::timeName(const scalar t, const int precision)
778 {
779  std::ostringstream buf;
780  buf.setf(ios_base::fmtflags(format_), ios_base::floatfield);
781  buf.precision(precision);
782  buf << t;
783  return buf.str();
784 }
785 
786 
788 {
789  return dimensionedScalar::name();
790 }
791 
792 
794 (
795  const fileName& dir,
796  const word& name,
798  const word& stopInstance
799 ) const
800 {
801  // Note: name might be empty!
802  IOobject startIO(name, timeName(), dir, *this, rOpt);
803 
804  IOobject io
805  (
806  fileHandler().findInstance
807  (
808  startIO,
809  timeOutputValue(),
810  stopInstance
811  )
812  );
813  return io.instance();
814 }
815 
816 
818 (
819  const fileName& directory,
820  const instant& t
821 ) const
822 {
823  // Simplified version: use findTimes (readDir + sort). The expensive
824  // bit is the readDir, not the sorting. Tbd: avoid calling findInstancePath
825  // from filePath.
826 
827  instantList timeDirs = findTimes(path(), constant());
828  // Note:
829  // - times will include constant (with value 0) as first element.
830  // For backwards compatibility make sure to find 0 in preference
831  // to constant.
832  // - list is sorted so could use binary search
833 
834  forAllReverse(timeDirs, i)
835  {
836  if (t.equal(timeDirs[i].value()))
837  {
838  return timeDirs[i].name();
839  }
840  }
841 
842  return word::null;
843 }
844 
847 {
848  return findInstancePath(path(), t);
849 }
850 
852 Foam::label Foam::Time::startTimeIndex() const
853 {
854  return startTimeIndex_;
855 }
856 
859 {
860  return dimensionedScalar("startTime", dimTime, startTime_);
861 }
862 
865 {
866  return dimensionedScalar("endTime", dimTime, endTime_);
867 }
868 
871 {
872  return stopAt_;
873 }
874 
875 
876 bool Foam::Time::run() const
877 {
878  loopProfiling_.reset(nullptr);
879 
880  bool isRunning = value() < (endTime_ - 0.5*deltaT_);
881 
882  if (!subCycling_)
883  {
884  // Only execute when the condition is no longer true
885  // ie, when exiting the control loop
886  if (!isRunning && timeIndex_ != startTimeIndex_)
887  {
888  // Ensure functionObjects execute on last time step
889  // (and hence write uptodate functionObjectProperties)
890  {
891  addProfiling(fo, "functionObjects.execute()");
892  functionObjects_.execute();
893  }
894  {
895  addProfiling(fo, "functionObjects.end()");
896  functionObjects_.end();
897  }
898 
899  if (cacheTemporaryObjects_)
900  {
901  cacheTemporaryObjects_ = checkCacheTemporaryObjects();
902  }
903  }
904  }
905 
906  if (isRunning)
907  {
908  if (!subCycling_)
909  {
910  const_cast<Time&>(*this).readModifiedObjects();
911 
912  if (timeIndex_ == startTimeIndex_)
913  {
914  addProfiling(functionObjects, "functionObjects.start()");
915  functionObjects_.start();
916  }
917  else
918  {
919  addProfiling(functionObjects, "functionObjects.execute()");
920  functionObjects_.execute();
921  }
922 
923  // Check if the execution of functionObjects require re-reading
924  // any files. This moves effect of e.g. 'timeActivatedFileUpdate'
925  // one time step forward. Note that we cannot call
926  // readModifiedObjects from within timeActivatedFileUpdate since
927  // it might re-read the functionObjects themselves (and delete
928  // the timeActivatedFileUpdate one)
929  if (functionObjects_.filesModified())
930  {
931  const_cast<Time&>(*this).readModifiedObjects();
932  }
933 
934  if (cacheTemporaryObjects_)
935  {
936  cacheTemporaryObjects_ = checkCacheTemporaryObjects();
937  }
938  }
939 
940  // Update the "is-running" status following the
941  // possible side-effects from functionObjects
942  isRunning = value() < (endTime_ - 0.5*deltaT_);
943 
944  // (re)trigger profiling
945  if (profiling::active())
946  {
947  loopProfiling_.reset
948  (
949  new profilingTrigger("time.run() " + objectRegistry::name())
950  );
951  }
952  }
953 
954  return isRunning;
955 }
956 
957 
958 bool Foam::Time::loop()
959 {
960  const bool isRunning = run();
961 
962  if (isRunning)
963  {
964  operator++();
965  }
966 
967  return isRunning;
968 }
969 
971 bool Foam::Time::end() const
972 {
973  return value() > (endTime_ + 0.5*deltaT_);
974 }
975 
976 
977 bool Foam::Time::stopAt(const stopAtControls stopCtrl) const
978 {
979  if (stopCtrl == stopAtControls::saUnknown)
980  {
981  return false;
982  }
983 
984  const bool changed = (stopAt_ != stopCtrl);
985  stopAt_ = stopCtrl;
986  endTime_ = GREAT;
987 
988  // Adjust endTime
989  if (stopCtrl == stopAtControls::saEndTime)
990  {
991  controlDict_.readEntry("endTime", endTime_);
992  }
993 
994  return changed;
995 }
996 
998 bool Foam::Time::isAdjustTimeStep() const
999 {
1000  return controlDict_.getOrDefault("adjustTimeStep", false);
1001 }
1002 
1003 
1004 void Foam::Time::setTime(const Time& t)
1005 {
1006  value() = t.value();
1007  dimensionedScalar::name() = t.dimensionedScalar::name();
1008  timeIndex_ = t.timeIndex_;
1009  fileHandler().setTime(*this);
1010 }
1011 
1012 
1013 void Foam::Time::setTime(const instant& inst, const label newIndex)
1014 {
1015  value() = inst.value();
1016  dimensionedScalar::name() = inst.name();
1017  timeIndex_ = newIndex;
1018 
1019  IOdictionary timeDict
1020  (
1021  IOobject
1022  (
1023  "time",
1024  timeName(),
1025  "uniform",
1026  *this,
1030  )
1031  );
1032 
1033  timeDict.readIfPresent("deltaT", deltaT_);
1034  timeDict.readIfPresent("deltaT0", deltaT0_);
1035  timeDict.readIfPresent("index", timeIndex_);
1036  fileHandler().setTime(*this);
1037 }
1038 
1040 void Foam::Time::setTime(const dimensionedScalar& newTime, const label newIndex)
1041 {
1042  setTime(newTime.value(), newIndex);
1043 }
1044 
1045 
1046 void Foam::Time::setTime(const scalar newTime, const label newIndex)
1047 {
1048  value() = newTime;
1049  dimensionedScalar::name() = timeName(timeToUserTime(newTime));
1050  timeIndex_ = newIndex;
1051  fileHandler().setTime(*this);
1052 }
1053 
1055 void Foam::Time::setEndTime(const dimensionedScalar& endTime)
1056 {
1057  setEndTime(endTime.value());
1058 }
1059 
1060 
1061 void Foam::Time::setEndTime(const scalar endTime)
1062 {
1063  endTime_ = endTime;
1064 }
1065 
1066 
1068 (
1069  const dimensionedScalar& deltaT,
1070  const bool adjust
1071 )
1072 {
1073  setDeltaT(deltaT.value(), adjust);
1074 }
1075 
1076 
1077 void Foam::Time::setDeltaT(const scalar deltaT, const bool adjust)
1078 {
1079  deltaT_ = deltaT;
1080  deltaTchanged_ = true;
1081 
1082  if (adjust)
1083  {
1084  adjustDeltaT();
1085  }
1086 }
1087 
1088 
1089 Foam::TimeState Foam::Time::subCycle(const label nSubCycles)
1090 {
1091  #ifdef FULLDEBUG
1092  if (prevTimeState_)
1093  {
1095  << "previous time state already set" << nl
1096  << exit(FatalError);
1097  }
1098  #endif
1099 
1100  prevTimeState_.reset(new TimeState(*this));
1101 
1102  setTime(*this - deltaT(), (timeIndex() - 1)*nSubCycles);
1103  deltaT_ /= nSubCycles;
1104  deltaT0_ /= nSubCycles;
1105  deltaTSave_ = deltaT0_;
1107  subCycling_ = nSubCycles;
1108 
1109  return prevTimeState();
1110 }
1111 
1112 
1113 void Foam::Time::subCycleIndex(const label index)
1114 {
1115  // Only permit adjustment if sub-cycling was already active
1116  // and if the index is valid (positive, non-zero).
1117  // This avoids potential mixups for deleting.
1118 
1119  if (subCycling_ && index > 0)
1120  {
1121  subCycling_ = index;
1122  }
1123 }
1124 
1125 
1127 {
1128  if (subCycling_)
1129  {
1130  TimeState::operator=(prevTimeState());
1131  prevTimeState_.reset(nullptr);
1132  }
1134  subCycling_ = 0;
1135 }
1136 
1137 
1138 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1141 {
1142  return operator+=(deltaT.value());
1143 }
1144 
1145 
1146 Foam::Time& Foam::Time::operator+=(const scalar deltaT)
1147 {
1148  setDeltaT(deltaT);
1149  return operator++();
1150 }
1151 
1152 
1154 {
1155  deltaT0_ = deltaTSave_;
1156  deltaTSave_ = deltaT_;
1157 
1158  // Save old time value and name
1159  const scalar oldTimeValue = timeToUserTime(value());
1160  const word oldTimeName = dimensionedScalar::name();
1161 
1162  // Increment time
1163  setTime(value() + deltaT_, timeIndex_ + 1);
1164 
1165  if (!subCycling_)
1166  {
1167  // If the time is very close to zero reset to zero
1168  if (mag(value()) < 10*SMALL*deltaT_)
1169  {
1170  setTime(0.0, timeIndex_);
1171  }
1172 
1173  if (sigStopAtWriteNow_.active() || sigWriteNow_.active())
1174  {
1175  // A signal might have been sent on one processor only
1176  // Reduce so all decide the same.
1177 
1178  label flag = 0;
1179  if (sigStopAtWriteNow_.active() && stopAt_ == saWriteNow)
1180  {
1181  flag += 1;
1182  }
1183  if (sigWriteNow_.active() && writeOnce_)
1184  {
1185  flag += 2;
1186  }
1187  reduce(flag, maxOp<label>());
1188 
1189  if (flag & 1)
1190  {
1191  stopAt_ = saWriteNow;
1192  }
1193  if (flag & 2)
1194  {
1195  writeOnce_ = true;
1196  }
1197  }
1198 
1199  writeTime_ = false;
1200 
1201  switch (writeControl_)
1202  {
1203  case wcNone:
1204  case wcUnknown:
1205  break;
1206 
1207  case wcTimeStep:
1208  writeTime_ = !(timeIndex_ % label(writeInterval_));
1209  break;
1210 
1211  case wcRunTime:
1212  case wcAdjustableRunTime:
1213  {
1214  const label writeIndex = label
1215  (
1216  ((value() - startTime_) + 0.5*deltaT_)
1217  / writeInterval_
1218  );
1219 
1220  if (writeIndex > writeTimeIndex_)
1221  {
1222  writeTime_ = true;
1223  writeTimeIndex_ = writeIndex;
1224  }
1225  }
1226  break;
1227 
1228  case wcCpuTime:
1229  {
1230  const label writeIndex = label
1231  (
1232  returnReduce(elapsedCpuTime(), maxOp<double>())
1233  / writeInterval_
1234  );
1235  if (writeIndex > writeTimeIndex_)
1236  {
1237  writeTime_ = true;
1238  writeTimeIndex_ = writeIndex;
1239  }
1240  }
1241  break;
1242 
1243  case wcClockTime:
1244  {
1245  const label writeIndex = label
1246  (
1247  returnReduce(elapsedClockTime(), maxOp<double>())
1248  / writeInterval_
1249  );
1250  if (writeIndex > writeTimeIndex_)
1251  {
1252  writeTime_ = true;
1253  writeTimeIndex_ = writeIndex;
1254  }
1255  }
1256  break;
1257  }
1258 
1259 
1260  // Check if endTime needs adjustment to stop at the next run()/end()
1261  if (!end())
1262  {
1263  if (stopAt_ == saNoWriteNow)
1264  {
1265  endTime_ = value();
1266  }
1267  else if (stopAt_ == saWriteNow)
1268  {
1269  endTime_ = value();
1270  writeTime_ = true;
1271  }
1272  else if (stopAt_ == saNextWrite && writeTime_ == true)
1273  {
1274  endTime_ = value();
1275  }
1276  }
1277 
1278  // Override writeTime if one-shot writing
1279  if (writeOnce_)
1280  {
1281  writeTime_ = true;
1282  writeOnce_ = false;
1283  }
1284 
1285  // Adjust the precision of the time directory name if necessary
1286  if (writeTime_)
1287  {
1288  // User-time equivalent of deltaT
1289  const scalar userDeltaT =
1290  timeToUserTime(value()) - timeToUserTime(value() - deltaT_);
1291 
1292  // Tolerance used when testing time equivalence
1293  const scalar timeTol =
1294  max(min(pow(scalar(10), -precision_), 0.1*userDeltaT), SMALL);
1295 
1296  // Time value obtained by reading timeName
1297  scalar timeNameValue = -VGREAT;
1298 
1299  // Check that new time representation differs from old one
1300  // reinterpretation of the word
1301  if
1302  (
1303  readScalar(dimensionedScalar::name(), timeNameValue)
1304  && (mag(timeNameValue - oldTimeValue - userDeltaT) > timeTol)
1305  )
1306  {
1307  int oldPrecision = precision_;
1308  while
1309  (
1310  precision_ < maxPrecision_
1311  && readScalar(dimensionedScalar::name(), timeNameValue)
1312  && (mag(timeNameValue - oldTimeValue - userDeltaT) > timeTol)
1313  )
1314  {
1315  precision_++;
1316  setTime(value(), timeIndex());
1317  }
1318 
1319  if (precision_ != oldPrecision)
1320  {
1322  << "Increased the timePrecision from " << oldPrecision
1323  << " to " << precision_
1324  << " to distinguish between timeNames at time "
1326  << endl;
1327 
1328  if (precision_ == maxPrecision_)
1329  {
1330  // Reached maxPrecision limit
1332  << "Current time name " << dimensionedScalar::name()
1333  << nl
1334  << " The maximum time precision has been reached"
1335  " which might result in overwriting previous"
1336  " results."
1337  << endl;
1338  }
1339 
1340  // Check if round-off error caused time-reversal
1341  scalar oldTimeNameValue = -VGREAT;
1342  if
1343  (
1344  readScalar(oldTimeName, oldTimeNameValue)
1345  && (
1346  sign(timeNameValue - oldTimeNameValue)
1347  != sign(deltaT_)
1348  )
1349  )
1350  {
1352  << "Current time name " << dimensionedScalar::name()
1353  << " is set to an instance prior to the "
1354  "previous one "
1355  << oldTimeName << nl
1356  << " This might result in temporal "
1357  "discontinuities."
1358  << endl;
1359  }
1360  }
1361  }
1362  }
1363  }
1364 
1365  return *this;
1366 }
1367 
1368 
1370 {
1371  return operator++();
1372 }
1373 
1374 
1375 // ************************************************************************* //
virtual Time & operator++()
Prefix increment,.
Definition: Time.C:1146
dimensionedScalar sign(const dimensionedScalar &ds)
List< instant > instantList
List of instants.
Definition: instantList.H:41
const Type & value() const noexcept
Return const reference to value.
dictionary dict
#define addProfiling(name, descr)
Define profiling trigger with specified name and description string.
registerInfoSwitch("printExecutionFormat", int, Foam::Time::printExecutionFormat_)
Info<< "Creating field kinetic energy K\"<< endl;volScalarField K("K", 0.5 *magSqr(U));if(U.nOldTimes()){ volVectorField *Uold=&U.oldTime();volScalarField *Kold=&K.oldTime();*Kold==0.5 *magSqr(*Uold);while(Uold->nOldTimes()) { Uold=&Uold-> oldTime()
Definition: createK.H:12
Address the time paths without using the Time class.
Definition: TimePaths.H:52
scalar deltaT_
Definition: TimeState.H:56
A class for handling file names.
Definition: fileName.H:71
readOption readOpt() const noexcept
Get the read option.
Inter-processor communication reduction functions.
static int printExecutionFormat_
Style for "ExecutionTime = " output.
Definition: Time.H:136
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
The time value with time-stepping information, user-defined remapping, etc.
Definition: TimeState.H:47
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
word findInstance(const fileName &dir, const word &name=word::null, IOobjectOption::readOption rOpt=IOobjectOption::MUST_READ, const word &stopInstance=word::null) const
Return time instance (location) of dir that contains the file name (eg, used in reading mesh data)...
Definition: Time.C:787
void adjustDeltaT()
Adjust the time step so that writing occurs at the specified time.
Definition: Time.C:92
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
virtual ~Time()
Destructor.
Definition: Time.C:748
virtual bool isAdjustTimeStep() const
Return true if adjustTimeStep is true.
Definition: Time.C:991
scalar writeInterval_
Definition: Time.H:175
virtual stopAtControls stopAt() const
Return the stop control information.
Definition: Time.C:863
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:162
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
virtual void setEndTime(const dimensionedScalar &endTime)
Reset end time.
Definition: Time.C:1048
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
writeControls
Write control options.
Definition: Time.H:82
virtual bool loop()
Return true if run should continue and if so increment time.
Definition: Time.C:951
virtual dimensionedScalar startTime() const
Return start time.
Definition: Time.C:851
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:1004
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:707
runTimeSource setTime(sourceTimes[sourceTimeIndex], sourceTimeIndex)
void on()
Switch the function objects on.
refPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler - forwards to fileOperation::handler()
static const Enum< stopAtControls > stopAtControlNames
Names for stopAtControls.
Definition: Time.H:125
A simple container for options an IOstream can normally have.
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:169
bool adjustTimeStep()
Called at the end of Time::adjustDeltaT() if adjustTime is true.
virtual dimensionedScalar endTime() const
Return end time.
Definition: Time.C:857
Ignore writing from objectRegistry::writeObject()
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1029
scalar startTime_
Definition: Time.H:167
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:411
writeControls writeControl_
Definition: Time.H:173
void setMonitoring(const bool forceProfiling=false)
Set file monitoring, profiling, etc.
Definition: Time.C:339
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
int infoSwitch(const char *name, const int deflt=0)
Lookup info switch or add default value.
Definition: debug.C:228
virtual word timeName() const
Return current time name.
Definition: Time.C:780
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
label writeTimeIndex_
Definition: TimeState.H:54
bool allowFunctionObjects() const
The controlDict &#39;functions&#39; entry is allowed to be used.
Definition: argList.C:1941
virtual bool run() const
Return true if run should continue,.
Definition: Time.C:869
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all processes in communicator.
static const int maxPrecision_
Maximum time directory name precision.
Definition: Time.H:219
scalar value() const noexcept
The value (const access)
Definition: Instant.H:134
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
word timeName
Definition: getTimeIndex.H:3
virtual TimeState subCycle(const label nSubCycles)
Set time to sub-cycle for the given number of steps.
Definition: Time.C:1082
"adjustable" / "adjustableRunTime"
Definition: Time.H:87
bool allowLibs() const
The controlDict &#39;libs&#39; entry is allowed to be used. (eg, has not been disabled by the -no-libs option...
Definition: argList.C:1959
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1020
const T & name() const noexcept
The name/key (const access)
Definition: Instant.H:144
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
static int precision_
Time directory name precision.
Definition: Time.H:214
A class for handling words, derived from Foam::string.
Definition: word.H:63
Extract command arguments and options from the supplied argc and argv parameters. ...
Definition: argList.H:118
static void initialize(const IOobject &ioObj, const Time &owner)
Singleton to initialize profiling pool, everything enabled.
Definition: profiling.C:141
Reading is optional [identical to LAZY_READ].
static const word null
An empty word.
Definition: word.H:84
static const Enum< writeControls > writeControlNames
Names for writeControls.
Definition: Time.H:120
virtual void setTime(const Time &t)
Reset the time and time-index to those of the given time.
Definition: Time.C:997
Time(const word &ctrlDictName, const argList &args, const bool enableFunctionObjects=true, const bool enableLibs=true)
Construct from dictionary name to read and argument list.
Definition: TimeI.H:24
static word controlDictName
The default control dictionary name (normally "controlDict")
Definition: Time.H:280
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
static void stop(const Time &owner)
Stop profiling, cleanup pool if possible.
Definition: profiling.C:167
virtual void subCycleIndex(const label index)
Adjust the reported sub-cycle index.
Definition: Time.C:1106
static bool active()
True if profiling is allowed and is active.
Definition: profiling.C:106
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:192
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...
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:194
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
defineTypeNameAndDebug(combustionModel, 0)
default float notation
Definition: Time.H:111
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:233
const word & name() const noexcept
Return const reference to name.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
word findInstancePath(const fileName &directory, const instant &t) const
Search the case for the time directory path corresponding to the given instance.
Definition: Time.C:811
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name...
Definition: instant.H:53
virtual bool end() const
Return true if end of run,.
Definition: Time.C:964
#define WarningInFunction
Report a warning using Foam::Warning.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
virtual Time & operator+=(const dimensionedScalar &deltaT)
Set deltaT to that specified and increment time via operator++()
Definition: Time.C:1133
virtual void setDeltaT(const dimensionedScalar &deltaT, const bool adjust=true)
Reset time step, normally also calling adjustDeltaT()
Definition: Time.C:1061
Nothing to be read.
Automatically write from objectRegistry::writeObject()
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:51
void clear()
Clear all entries from the registry.
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
constexpr label labelMax
Definition: label.H:55
virtual void endSubCycle()
Reset time after sub-cycling back to previous TimeState.
Definition: Time.C:1119
fmtflags
Supported time directory name formats.
Definition: Time.H:109
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:430
int system(const std::string &command, const bool bg=false)
Execute the specified command via the shell.
Definition: POSIX.C:1702
stopAtControls
Stop-run control options, which are primarily used when altering the stopAt condition.
Definition: Time.H:97
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
Registry of regIOobjects.
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition: autoPtr.H:178
bool equal(scalar val) const noexcept
True if values are equal (includes SMALL for rounding)
Definition: Instant.H:155
bool open(bool verbose=true)
Open named, but unopened libraries. These names will normally have been added with the append() metho...
Foam::argList args(argc, argv)
dictionary & controlDict()
The central control dictionary, the contents of which are either taken directly from the FOAM_CONTROL...
Definition: debug.C:142
virtual label startTimeIndex() const
Return start time index.
Definition: Time.C:845
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:171
dimensionedScalar log10(const dimensionedScalar &ds)
Do not request registration (bool: false)
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:171
void setControls()
Set the controls from the current controlDict.
Definition: Time.C:136
Namespace for OpenFOAM.
label timeIndex
Definition: getTimeIndex.H:24
label timeIndex_
Definition: TimeState.H:53
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 ...
readOption
Enumeration defining read preferences.