Time.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 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 
26 #include "Time.H"
27 #include "timeIOdictionary.H"
28 #include "PstreamReduceOps.H"
29 #include "argList.H"
30 
31 // * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
36 }
37 
40 {
41  "endTime",
42  "noWriteNow",
43  "writeNow",
44  "nextWrite"
45 };
46 
49 {
50  "timeStep",
51  "runTime",
52  "adjustableRunTime",
53  "clockTime",
54  "cpuTime"
55 };
56 
58 
60 
62 
63 const int Foam::Time::maxPrecision_(3 - log10(small));
64 
66 
67 
68 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
69 
71 {
72  const scalar timeToNextAction = min
73  (
74  max
75  (
76  0,
77  (writeTimeIndex_ + 1)*writeInterval_ - (value() - beginTime_)
78  ),
79  functionObjects_.timeToNextAction()
80  );
81 
82  const scalar nSteps = timeToNextAction/deltaT_;
83 
84  if (nSteps < labelMax)
85  {
86  // Allow the time-step to increase by up to 1%
87  // to accommodate the next write time before splitting
88  const label nStepsToNextAction = label(nSteps + 0.99);
89 
90  // Adjust deltaT if nStepsToNextWrite > 0
91  if (nStepsToNextAction > 0)
92  {
93  deltaT_ = timeToNextAction/nStepsToNextAction;
94  }
95  }
96 }
97 
98 
100 {
101  // default is to resume calculation from "latestTime"
102  const word startFrom = controlDict_.lookupOrDefault<word>
103  (
104  "startFrom",
105  "latestTime"
106  );
107 
108  if (startFrom == "startTime")
109  {
110  startTime_ = controlDict_.lookup<scalar>("startTime", userUnits());
111  }
112  else
113  {
114  // Search directory for valid time directories
115  const instantList timeDirs = findTimes(path(), constant());
116 
117  if (startFrom == "firstTime")
118  {
119  if (timeDirs.size())
120  {
121  if (timeDirs[0].name() == constant() && timeDirs.size() >= 2)
122  {
123  startTime_ = userTimeToTime(timeDirs[1].value());
124  }
125  else
126  {
127  startTime_ = userTimeToTime(timeDirs[0].value());
128  }
129  }
130  }
131  else if (startFrom == "latestTime")
132  {
133  if (timeDirs.size())
134  {
135  startTime_ = userTimeToTime(timeDirs.last().value());
136  }
137  }
138  else
139  {
140  FatalIOErrorInFunction(controlDict_)
141  << "expected startTime, firstTime or latestTime"
142  << " found '" << startFrom << "'"
143  << exit(FatalIOError);
144  }
145  }
146 
147  setTime(startTime_, 0);
148  readDict();
149  deltaTSave_ = deltaT_;
150  deltaT0_ = deltaT_;
151 
152  // Check if time directory exists
153  // If not increase time precision to see if it is formatted differently.
154  if (!fileHandler().exists(timePath(), false, true))
155  {
156  int oldPrecision = curPrecision_;
157  int requiredPrecision = -1;
158 
159  for
160  (
161  curPrecision_ = maxPrecision_;
162  curPrecision_ > oldPrecision;
163  curPrecision_--
164  )
165  {
166  // Update the time formatting
167  setTime(startTime_, 0);
168 
169  // Check the existence of the time directory with the new format
170  if (fileHandler().exists(timePath(), false, true))
171  {
172  requiredPrecision = curPrecision_;
173  }
174  }
175 
176  if (requiredPrecision > 0)
177  {
178  // Update the time precision
179  curPrecision_ = requiredPrecision;
180 
181  // Update the time formatting
182  setTime(startTime_, 0);
183 
185  << "Increasing the timePrecision from " << oldPrecision
186  << " to " << curPrecision_
187  << " to support the formatting of the current time directory "
188  << name() << nl << endl;
189  }
190  else
191  {
192  // Could not find time directory so assume it is not present
193  curPrecision_ = oldPrecision;
194 
195  // Revert the time formatting
196  setTime(startTime_, 0);
197  }
198  }
199 
200  if (Pstream::parRun())
201  {
202  scalar sumStartTime = startTime_;
203  reduce(sumStartTime, sumOp<scalar>());
204  if
205  (
206  mag(Pstream::nProcs()*startTime_ - sumStartTime)
207  > Pstream::nProcs()*deltaT_/10.0
208  )
209  {
210  FatalIOErrorInFunction(controlDict_)
211  << "Start time is not the same for all processors" << nl
212  << "processor " << Pstream::myProcNo() << " has startTime "
213  << startTime_ << exit(FatalIOError);
214  }
215  }
216 
217  timeIOdictionary timeDict
218  (
219  IOobject
220  (
221  "time",
222  name(),
223  "uniform",
224  *this,
227  false
228  )
229  );
230 
231  if (controlDict_.found("beginTime"))
232  {
233  beginTime_ = controlDict_.lookup<scalar>("beginTime", userUnits());
234  }
235  else if (timeDict.found("beginTime"))
236  {
237  beginTime_ = timeDict.lookup<scalar>("beginTime", userUnits());
238  }
239  else
240  {
241  beginTime_ = startTime_;
242  }
243 
244  // Read and set the deltaT only if time-step adjustment is active
245  // otherwise use the deltaT from the controlDict
246  if (controlDict_.lookupOrDefault<Switch>("adjustTimeStep", false))
247  {
248  if (timeDict.found("deltaT"))
249  {
250  deltaT_ = timeDict.lookup<scalar>("deltaT", userUnits());
251  deltaTSave_ = deltaT_;
252  deltaT0_ = deltaT_;
253  }
254  }
255 
256  if (timeDict.found("deltaT0"))
257  {
258  deltaT0_ = timeDict.lookup<scalar>("deltaT0", userUnits());
259  }
260 
261  if (timeDict.readIfPresent("index", startTimeIndex_))
262  {
263  timeIndex_ = startTimeIndex_;
264  }
265 
266  // Set writeTimeIndex_ to correspond to beginTime_
267  if
268  (
269  (
270  writeControl_ == writeControl::runTime
271  || writeControl_ == writeControl::adjustableRunTime
272  )
273  )
274  {
275  writeTimeIndex_ = label
276  (
277  ((value() - beginTime_) + 0.5*deltaT_)/writeInterval_
278  );
279  }
280 
281 
282  // Check if values stored in time dictionary are consistent
283 
284  // 1. Based on time name
285  bool checkValue = true;
286 
287  string storedTimeName;
288  if (timeDict.readIfPresent("name", storedTimeName))
289  {
290  if (storedTimeName == name())
291  {
292  // Same time. No need to check stored value
293  checkValue = false;
294  }
295  }
296 
297  // 2. Based on time value
298  // (consistent up to the current time writing precision so it won't
299  // trigger if we just change the write precision)
300  if (checkValue)
301  {
302  scalar storedTimeValue;
303  if (timeDict.readIfPresent("value", storedTimeValue))
304  {
305  word storedTimeName(timeName(storedTimeValue));
306 
307  if (storedTimeName != name())
308  {
309  IOWarningInFunction(timeDict)
310  << "Time read from time dictionary " << storedTimeName
311  << " differs from actual time " << name() << '.' << nl
312  << " This may cause unexpected database behaviour."
313  << " If you are not interested" << nl
314  << " in preserving time state delete"
315  << " the time dictionary."
316  << endl;
317  }
318  }
319  }
320 }
321 
322 
323 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
324 
326 (
327  const word& controlDictName,
328  const argList& args,
329  const bool enableFunctionObjects
330 )
331 :
332  TimePaths
333  (
334  args.parRunControl().parRun(),
335  args.rootPath(),
336  args.globalCaseName(),
337  args.caseName()
338  ),
339 
340  objectRegistry(*this),
341 
342  runTimeModifiable_(false),
343 
344  controlDict_
345  (
346  IOobject
347  (
348  controlDictName,
349  system(),
350  *this,
351  IOobject::MUST_READ_IF_MODIFIED,
352  IOobject::NO_WRITE
353  ),
354  *this
355  ),
356 
357  startTimeIndex_(0),
358  startTime_(0),
359  endTime_(0),
360  beginTime_(startTime_),
361 
362  userTime_(userTimes::userTime::New(controlDict_)),
363 
364  stopAt_(stopAtControl::endTime),
365  writeControl_(writeControl::timeStep),
366  writeInterval_(great),
367  purgeWrite_(0),
368  writeOnce_(false),
369 
370  subCycling_(false),
371 
372  sigWriteNow_(writeInfoHeader, *this),
373  sigStopAtWriteNow_(writeInfoHeader, *this),
374 
375  writeFormat_(IOstream::ASCII),
376  writeVersion_(IOstream::currentVersion),
377  writeCompression_(IOstream::UNCOMPRESSED),
378  cacheTemporaryObjects_(true),
379 
380  functionObjects_
381  (
382  *this,
383  enableFunctionObjects
384  ? (
385  argList::validOptions.found("functionObjects")
386  ? args.optionFound("functionObjects")
387  : argList::validOptions.found("noFunctionObjects")
388  ? !args.optionFound("noFunctionObjects")
389  : true
390  )
391  : false
392  )
393 {
394  libs.open(controlDict_, "libs");
395 
396  // Explicitly set read flags on objectRegistry so anything constructed
397  // from it reads as well (e.g. fvSolution).
399 
400  if (args.options().found("case"))
401  {
402  const wordList switchSets
403  (
404  {
405  "InfoSwitches",
406  "OptimisationSwitches",
407  "DebugSwitches",
408  "DimensionSets",
409  "UnitSets",
410  "units",
411  "DimensionedConstants",
412  "dimensionedConstants"
413  }
414  );
415 
416  forAll(switchSets, i)
417  {
418  if (controlDict_.found(switchSets[i]))
419  {
420  IOWarningInFunction(controlDict_)
421  << switchSets[i]
422  << " in system/controlDict are only processed if "
423  << args.executable() << " is run in the "
424  << args.path() << " directory" << endl;
425  }
426  }
427  }
428 
429  setControls();
430 
431  // Add a watch on the controlDict and functions files
432  // after runTimeModifiable_ is set
433  controlDict_.addWatch();
434  functionObjects_.addWatch();
435 }
436 
437 
439 (
440  const word& controlDictName,
441  const fileName& rootPath,
442  const fileName& caseName,
443  const bool enableFunctionObjects
444 )
445 :
446  TimePaths(rootPath, caseName),
447 
448  objectRegistry(*this),
449 
450  runTimeModifiable_(false),
451 
452  controlDict_
453  (
454  IOobject
455  (
456  controlDictName,
457  system(),
458  *this,
459  IOobject::MUST_READ_IF_MODIFIED,
460  IOobject::NO_WRITE
461  ),
462  *this
463  ),
464 
465  startTimeIndex_(0),
466  startTime_(0),
467  endTime_(0),
468  beginTime_(startTime_),
469 
470  userTime_(userTimes::userTime::New(controlDict_)),
471 
472  stopAt_(stopAtControl::endTime),
473  writeControl_(writeControl::timeStep),
474  writeInterval_(great),
475  purgeWrite_(0),
476  writeOnce_(false),
477 
478  subCycling_(false),
479 
480  sigWriteNow_(writeInfoHeader, *this),
481  sigStopAtWriteNow_(writeInfoHeader, *this),
482 
483  writeFormat_(IOstream::ASCII),
484  writeVersion_(IOstream::currentVersion),
485  writeCompression_(IOstream::UNCOMPRESSED),
486  cacheTemporaryObjects_(true),
487 
488  functionObjects_(*this, enableFunctionObjects)
489 {
490  libs.open(controlDict_, "libs");
491 
492  // Explicitly set read flags on objectRegistry so anything constructed
493  // from it reads as well (e.g. fvSolution).
495 
496  setControls();
497 
498  // Add a watch on the controlDict and functions files
499  // after runTimeModifiable_ is set
500  controlDict_.addWatch();
501  functionObjects_.addWatch();
502 }
503 
504 
506 (
507  const dictionary& dict,
508  const fileName& rootPath,
509  const fileName& caseName,
510  const bool enableFunctionObjects
511 )
512 :
513  TimePaths(rootPath, caseName),
514 
515  objectRegistry(*this),
516 
517  runTimeModifiable_(false),
518 
519  controlDict_
520  (
521  IOobject
522  (
523  controlDictName,
524  system(),
525  *this,
526  IOobject::MUST_READ_IF_MODIFIED,
527  IOobject::NO_WRITE
528  ),
529  dict,
530  *this
531  ),
532 
533  startTimeIndex_(0),
534  startTime_(0),
535  endTime_(0),
536  beginTime_(startTime_),
537 
538  userTime_(userTimes::userTime::New(controlDict_)),
539 
540  stopAt_(stopAtControl::endTime),
541  writeControl_(writeControl::timeStep),
542  writeInterval_(great),
543  purgeWrite_(0),
544  writeOnce_(false),
545 
546  subCycling_(false),
547 
548  sigWriteNow_(writeInfoHeader, *this),
549  sigStopAtWriteNow_(writeInfoHeader, *this),
550 
551  writeFormat_(IOstream::ASCII),
552  writeVersion_(IOstream::currentVersion),
553  writeCompression_(IOstream::UNCOMPRESSED),
554  cacheTemporaryObjects_(true),
555 
556  functionObjects_(*this, enableFunctionObjects)
557 {
558  libs.open(controlDict_, "libs");
559 
560  // Explicitly set read flags on objectRegistry so anything constructed
561  // from it reads as well (e.g. fvSolution).
563 
564  setControls();
565 
566  // Add a watch on the controlDict and functions files
567  // after runTimeModifiable_ is set
568  controlDict_.addWatch();
569  functionObjects_.addWatch();
570 }
571 
572 
574 (
575  const fileName& rootPath,
576  const fileName& caseName,
577  const bool enableFunctionObjects
578 )
579 :
580  TimePaths(rootPath, caseName),
581 
582  objectRegistry(*this),
583 
584  runTimeModifiable_(false),
585 
586  controlDict_
587  (
588  IOobject
589  (
590  controlDictName,
591  system(),
592  *this,
593  IOobject::NO_READ,
594  IOobject::NO_WRITE
595  ),
596  *this
597  ),
598 
599  startTimeIndex_(0),
600  startTime_(0),
601  endTime_(0),
602  beginTime_(startTime_),
603 
604  userTime_(userTimes::userTime::New(controlDict_)),
605 
606  stopAt_(stopAtControl::endTime),
607  writeControl_(writeControl::timeStep),
608  writeInterval_(great),
609  purgeWrite_(0),
610  writeOnce_(false),
611 
612  subCycling_(false),
613 
614  writeFormat_(IOstream::ASCII),
615  writeVersion_(IOstream::currentVersion),
616  writeCompression_(IOstream::UNCOMPRESSED),
617  cacheTemporaryObjects_(true),
618 
619  functionObjects_(*this, enableFunctionObjects)
620 {
621  libs.open(controlDict_, "libs");
622 }
623 
624 
625 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
626 
628 {
629  // Destroy function objects first
630  functionObjects_.clear();
631 }
632 
633 
634 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
635 
637 {
638  if (controlDict_.found("regionSolvers"))
639  {
640  return controlDict_.subDict("regionSolvers").toc();
641  }
642  else
643  {
644  return wordList::null();
645  }
646 }
647 
648 
649 Foam::word Foam::Time::timeName(const scalar t, const int precision)
650 {
651  std::ostringstream buf;
652  buf.setf(ios_base::fmtflags(format_), ios_base::floatfield);
653  buf.precision(precision);
654  buf << t;
655  return buf.str();
656 }
657 
658 
660 {
661  return findTimes(path(), constant());
662 }
663 
664 
666 (
667  const fileName& dir,
668  const word& name,
669  const IOobject::readOption rOpt,
670  const word& stopInstance
671 ) const
672 {
673  IOobject startIO
674  (
675  name, // name might be empty!
677  dir,
678  *this,
679  rOpt
680  );
681 
682  IOobject io
683  (
684  fileHandler().findInstance
685  (
686  startIO,
687  userTimeValue(),
688  stopInstance
689  )
690  );
691 
692  return io.instance();
693 }
694 
695 
697 (
698  const fileName& directory,
699  const instant& t
700 ) const
701 {
702  // Simplified version: use findTimes (readDir + sort). The expensive
703  // bit is the readDir, not the sorting. Tbd: avoid calling findInstancePath
704  // from filePath.
705 
706  const instantList timeDirs = findTimes(path(), constant());
707  // Note:
708  // - times will include constant (with value 0) as first element.
709  // For backwards compatibility make sure to find 0 in preference
710  // to constant.
711  // - list is sorted so could use binary search
712 
714  {
715  if (t.equal(timeDirs[i].value()))
716  {
717  return timeDirs[i].name();
718  }
719  }
720 
721  return word::null;
722 }
723 
724 
726 {
727  return findInstancePath(path(), t);
728 }
729 
730 
732 {
733  const instantList timeDirs = findTimes(path(), constant());
734 
735  // There is only one time (likely "constant") so return it
736  if (timeDirs.size() == 1)
737  {
738  return timeDirs[0];
739  }
740 
741  if (t < timeDirs[1].value())
742  {
743  return timeDirs[1];
744  }
745  else if (t > timeDirs.last().value())
746  {
747  return timeDirs.last();
748  }
749 
750  label nearestIndex = -1;
751  scalar deltaT = great;
752 
753  for (label timei=1; timei < timeDirs.size(); ++timei)
754  {
755  scalar diff = mag(timeDirs[timei].value() - t);
756  if (diff < deltaT)
757  {
758  deltaT = diff;
759  nearestIndex = timei;
760  }
761  }
762 
763  return timeDirs[nearestIndex];
764 }
765 
766 
768 (
769  const instantList& timeDirs,
770  const scalar t,
771  const word& constantName
772 )
773 {
774  label nearestIndex = -1;
775  scalar deltaT = great;
776 
777  forAll(timeDirs, timei)
778  {
779  if (timeDirs[timei].name() == constantName) continue;
780 
781  scalar diff = mag(timeDirs[timei].value() - t);
782  if (diff < deltaT)
783  {
784  deltaT = diff;
785  nearestIndex = timei;
786  }
787  }
788 
789  return nearestIndex;
790 }
791 
792 
794 {
795  return startTimeIndex_;
796 }
797 
798 
800 {
801  return dimensionedScalar
802  (
803  timeName(timeToUserTime(beginTime_)),
804  dimTime,
805  beginTime_
806  );
807 }
808 
809 
811 {
812  return dimensionedScalar
813  (
814  timeName(timeToUserTime(startTime_)),
815  dimTime,
816  startTime_
817  );
818 }
819 
820 
822 {
823  return dimensionedScalar
824  (
825  timeName(timeToUserTime(endTime_)),
826  dimTime,
827  endTime_
828  );
829 }
830 
831 
833 {
834  return *userTime_;
835 }
836 
837 
838 Foam::scalar Foam::Time::userTimeValue() const
839 {
840  return userTime_->timeToUserTime(value());
841 }
842 
843 
844 Foam::scalar Foam::Time::userDeltaTValue() const
845 {
846  return
847  userTime_->timeToUserTime(value())
848  - userTime_->timeToUserTime(value() - deltaT_);
849 }
850 
851 
852 Foam::scalar Foam::Time::userTimeToTime(const scalar tau) const
853 {
854  return userTime_->userTimeToTime(tau);
855 }
856 
857 
858 Foam::scalar Foam::Time::timeToUserTime(const scalar t) const
859 {
860  return userTime_->timeToUserTime(t);
861 }
862 
863 
865 {
866  if (name() == constant())
867  {
868  return constant();
869  }
870  else
871  {
872  return timeName(userTimeValue()) + userTime_->unitName();
873  }
874 }
875 
876 
878 {
879  return userTime_->units();
880 }
881 
882 
884 {
885  static const unitSet unitSeconds(dimTime);
886 
887  switch (writeControl_)
888  {
889  case writeControl::timeStep:
890  return units::unitless;
891  case writeControl::runTime:
892  case writeControl::adjustableRunTime:
893  return userUnits();
894  case writeControl::cpuTime:
895  case writeControl::clockTime:
896  return unitSeconds;
897  }
898 
899  return units::none;
900 }
901 
902 
904 {
905  return value() < (endTime_ - 0.5*deltaT_);
906 }
907 
908 
909 bool Foam::Time::run() const
910 {
911  bool running = this->running();
912 
913  if (!subCycling_)
914  {
915  if (!running && timeIndex_ != startTimeIndex_)
916  {
917  functionObjects_.execute();
918  functionObjects_.end();
919 
920  if (cacheTemporaryObjects_)
921  {
922  cacheTemporaryObjects_ = checkCacheTemporaryObjects();
923  }
924  }
925  }
926 
927  if (running)
928  {
929  if (!subCycling_)
930  {
931  const_cast<Time&>(*this).readModifiedObjects();
932 
933  if (timeIndex_ == startTimeIndex_)
934  {
935  functionObjects_.start();
936  }
937  else
938  {
939  functionObjects_.execute();
940 
941  if (cacheTemporaryObjects_)
942  {
943  cacheTemporaryObjects_ = checkCacheTemporaryObjects();
944  }
945  }
946  }
947 
948  // Re-evaluate if running in case a function object has changed things
949  running = this->running();
950  }
951 
952  return running;
953 }
954 
955 
957 {
958  bool running = run();
959 
960  if (running)
961  {
962  operator++();
963  }
964 
965  return running;
966 }
967 
968 
969 bool Foam::Time::end() const
970 {
971  return value() > (endTime_ + 0.5*deltaT_);
972 }
973 
974 
975 bool Foam::Time::stopAt(const stopAtControl sa) const
976 {
977  const bool changed = (stopAt_ != sa);
978  stopAt_ = sa;
979 
980  // adjust endTime
981  if (sa == stopAtControl::endTime)
982  {
983  controlDict_.lookup("endTime") >> endTime_;
984  }
985  else
986  {
987  endTime_ = great;
988  }
989  return changed;
990 }
991 
992 
993 void Foam::Time::setTime(const Time& t)
994 {
995  value() = t.value();
996  dimensionedScalar::name() = t.dimensionedScalar::name();
997  timeIndex_ = t.timeIndex_;
998  fileHandler().setTime(*this);
999 }
1000 
1001 
1002 void Foam::Time::setTime(const instant& inst, const label newIndex)
1003 {
1004  value() = userTimeToTime(inst.value());
1005  dimensionedScalar::name() = inst.name();
1006  timeIndex_ = newIndex;
1007 
1008  timeIOdictionary timeDict
1009  (
1010  IOobject
1011  (
1012  "time",
1013  name(),
1014  "uniform",
1015  *this,
1018  false
1019  )
1020  );
1021 
1022  if (timeDict.found("deltaT"))
1023  {
1024  deltaT_ = timeDict.lookup<scalar>("deltaT", userUnits());
1025  }
1026 
1027  if (timeDict.found("deltaT0"))
1028  {
1029  deltaT0_ = timeDict.lookup<scalar>("deltaT0", userUnits());
1030  }
1031 
1032  timeDict.readIfPresent("index", timeIndex_);
1033 
1034  fileHandler().setTime(*this);
1035 }
1036 
1037 
1038 void Foam::Time::setTime(const dimensionedScalar& newTime, const label newIndex)
1039 {
1040  setTime(newTime.value(), newIndex);
1041 }
1042 
1043 
1044 void Foam::Time::setTime(const scalar newTime, const label newIndex)
1045 {
1046  value() = newTime;
1047  dimensionedScalar::name() = timeName(timeToUserTime(newTime));
1048  timeIndex_ = newIndex;
1049  fileHandler().setTime(*this);
1050 }
1051 
1052 
1054 {
1055  setEndTime(endTime.value());
1056 }
1057 
1058 
1059 void Foam::Time::setEndTime(const scalar endTime)
1060 {
1061  endTime_ = endTime;
1062 }
1063 
1064 
1066 {
1067  setDeltaT(deltaT.value());
1068 }
1069 
1070 
1071 void Foam::Time::setDeltaT(const scalar deltaT)
1072 {
1073  setDeltaTNoAdjust(deltaT);
1074 
1075  if (writeControl_ == writeControl::adjustableRunTime)
1076  {
1077  adjustDeltaT();
1078  }
1079 }
1080 
1081 
1082 void Foam::Time::setDeltaTNoAdjust(const scalar deltaT)
1083 {
1084  deltaT_ = deltaT;
1085  deltaTchanged_ = true;
1086 }
1087 
1088 
1089 void Foam::Time::setWriteInterval(const scalar writeInterval)
1090 {
1091  if (writeInterval_ == great || !equal(writeInterval, writeInterval_))
1092  {
1093  writeInterval_ = writeInterval;
1094 
1095  if
1096  (
1097  writeControl_ == writeControl::runTime
1098  || writeControl_ == writeControl::adjustableRunTime
1099  )
1100  {
1101  // Recalculate writeTimeIndex_ for consistency with the new
1102  // writeInterval
1103  writeTimeIndex_ = label
1104  (
1105  ((value() - beginTime_) + 0.5*deltaT_)/writeInterval_
1106  );
1107  }
1108  else if (writeControl_ == writeControl::timeStep)
1109  {
1110  // Set to the nearest integer
1111  writeInterval_ = label(writeInterval + 0.5);
1112  }
1113  }
1114 }
1115 
1116 
1118 {
1119  subCycling_ = true;
1120  prevTimeState_.set(new TimeState(*this));
1121 
1122  setTime(*this - deltaT(), (timeIndex() - 1)*nSubCycles);
1123  deltaT_ /= nSubCycles;
1124  deltaT0_ /= nSubCycles;
1125  deltaTSave_ = deltaT0_;
1126 
1127  return prevTimeState();
1128 }
1129 
1130 
1132 {
1133  if (subCycling_)
1134  {
1135  subCycling_ = false;
1136  TimeState::operator=(prevTimeState());
1137  prevTimeState_.clear();
1138  }
1139 }
1140 
1141 
1142 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1143 
1145 {
1146  return operator+=(deltaT.value());
1147 }
1148 
1149 
1150 Foam::Time& Foam::Time::operator+=(const scalar deltaT)
1151 {
1152  setDeltaT(deltaT);
1153  return operator++();
1154 }
1155 
1156 
1158 {
1159  deltaT0_ = deltaTSave_;
1160  deltaTSave_ = deltaT_;
1161 
1162  // Save old time value and name
1163  const scalar oldTimeValue = timeToUserTime(value());
1164  const word oldTimeName = dimensionedScalar::name();
1165 
1166  // Increment time
1167  setTime(value() + deltaT_, timeIndex_ + 1);
1168 
1169  if (!subCycling_)
1170  {
1171  // If the time is very close to zero reset to zero
1172  if (mag(value()) < 10*small*deltaT_)
1173  {
1174  setTime(0, timeIndex_);
1175  }
1176 
1177  if (sigStopAtWriteNow_.active() || sigWriteNow_.active())
1178  {
1179  // A signal might have been sent on one processor only
1180  // Reduce so all decide the same.
1181 
1182  label flag = 0;
1183  if
1184  (
1185  sigStopAtWriteNow_.active()
1186  && stopAt_ == stopAtControl::writeNow
1187  )
1188  {
1189  flag += 1;
1190  }
1191  if (sigWriteNow_.active() && writeOnce_)
1192  {
1193  flag += 2;
1194  }
1195  reduce(flag, maxOp<label>());
1196 
1197  if (flag & 1)
1198  {
1199  stopAt_ = stopAtControl::writeNow;
1200  }
1201  if (flag & 2)
1202  {
1203  writeOnce_ = true;
1204  }
1205  }
1206 
1207  writeTime_ = false;
1208 
1209  switch (writeControl_)
1210  {
1211  case writeControl::timeStep:
1212  writeTime_ = !(timeIndex_ % label(writeInterval_));
1213  break;
1214 
1215  case writeControl::runTime:
1216  case writeControl::adjustableRunTime:
1217  {
1218  label writeIndex = label
1219  (
1220  ((value() - beginTime_) + 0.5*deltaT_)
1221  / writeInterval_
1222  );
1223 
1224  if (writeIndex > writeTimeIndex_)
1225  {
1226  writeTime_ = true;
1227  writeTimeIndex_ = writeIndex;
1228  }
1229  }
1230  break;
1231 
1232  case writeControl::cpuTime:
1233  {
1234  label writeIndex = label
1235  (
1236  returnReduce(elapsedCpuTime(), maxOp<double>())
1237  / writeInterval_
1238  );
1239  if (writeIndex > writeTimeIndex_)
1240  {
1241  writeTime_ = true;
1242  writeTimeIndex_ = writeIndex;
1243  }
1244  }
1245  break;
1246 
1247  case writeControl::clockTime:
1248  {
1249  label writeIndex = label
1250  (
1251  returnReduce(label(elapsedClockTime()), maxOp<label>())
1252  / writeInterval_
1253  );
1254  if (writeIndex > writeTimeIndex_)
1255  {
1256  writeTime_ = true;
1257  writeTimeIndex_ = writeIndex;
1258  }
1259  }
1260  break;
1261  }
1262 
1263 
1264  // Check if endTime needs adjustment to stop at the next run()/end()
1265  if (!end())
1266  {
1267  if (stopAt_ == stopAtControl::noWriteNow)
1268  {
1269  endTime_ = value();
1270  }
1271  else if (stopAt_ == stopAtControl::writeNow)
1272  {
1273  endTime_ = value();
1274  writeTime_ = true;
1275  }
1276  else if (stopAt_ == stopAtControl::nextWrite && writeTime_ == true)
1277  {
1278  endTime_ = value();
1279  }
1280  }
1281 
1282  // Override writeTime if one-shot writing
1283  if (writeOnce_)
1284  {
1285  writeTime_ = true;
1286  writeOnce_ = false;
1287  }
1288 
1289  // Adjust the precision of the time name if necessary
1290  {
1291  // User-time equivalent of deltaT
1292  const scalar userDeltaT = userDeltaTValue();
1293 
1294  // Tolerance used when testing time equivalence
1295  const scalar timeTol =
1296  max(min(pow(10.0, -precision_), 0.1*userDeltaT), small);
1297 
1298  // Time value obtained by reading timeName
1299  scalar timeNameValue = -vGreat;
1300 
1301  // Check that new time representation differs from old one
1302  // reinterpretation of the word
1303  if
1304  (
1305  readScalar(dimensionedScalar::name().c_str(), timeNameValue)
1306  && (mag(timeNameValue - oldTimeValue - userDeltaT) > timeTol)
1307  )
1308  {
1309  int oldPrecision = curPrecision_;
1310  while
1311  (
1312  curPrecision_ < maxPrecision_
1313  && readScalar(dimensionedScalar::name().c_str(), timeNameValue)
1314  && (mag(timeNameValue - oldTimeValue - userDeltaT) > timeTol)
1315  )
1316  {
1317  curPrecision_++;
1318  setTime(value(), timeIndex());
1319  }
1320 
1321  if (curPrecision_ != oldPrecision)
1322  {
1324  << "Increased the timePrecision from " << oldPrecision
1325  << " to " << curPrecision_
1326  << " to distinguish between timeNames at time "
1328  << endl;
1329 
1330  if (curPrecision_ == maxPrecision_)
1331  {
1332  // Reached maxPrecision limit
1334  << "Current time name " << dimensionedScalar::name()
1335  << nl
1336  << " The maximum time precision has been reached"
1337  " which might result in overwriting previous"
1338  " results."
1339  << exit(FatalError);
1340  }
1341 
1342  // Check if round-off error caused time-reversal
1343  scalar oldTimeNameValue = -vGreat;
1344  if
1345  (
1346  readScalar(oldTimeName.c_str(), oldTimeNameValue)
1347  && (
1348  sign(timeNameValue - oldTimeNameValue)
1349  != sign(deltaT_)
1350  )
1351  )
1352  {
1354  << "Current time name " << dimensionedScalar::name()
1355  << " is set to an instance prior to the "
1356  "previous one "
1357  << oldTimeName << nl
1358  << " This might result in temporal "
1359  "discontinuities."
1360  << endl;
1361  }
1362  }
1363  }
1364  }
1365  }
1366 
1367  return *this;
1368 }
1369 
1370 
1372 {
1373  return operator++();
1374 }
1375 
1376 
1377 // ************************************************************************* //
Inter-processor communication reduction functions.
bool found
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: UList.H:461
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
readOption
Enumeration defining the read options.
Definition: IOobject.H:117
@ MUST_READ_IF_MODIFIED
Definition: IOobject.H:119
fileName & instance() const
Return the instance directory, constant, system, <time> etc.
Definition: IOobject.C:352
readOption readOpt() const
Definition: IOobject.H:357
An IOstream is an abstract base class for all input/output systems; be they streams,...
Definition: IOstream.H:72
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
static const List< word > & null()
Return a null List.
Definition: ListI.H:118
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:55
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:61
A class for addressing time paths without using the Time class.
Definition: TimePaths.H:49
The time value with time-stepping information, user-defined remapping, etc.
Definition: TimeState.H:55
friend class Time
Declare friendship with the Time class.
Definition: TimeState.H:70
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:76
virtual bool run() const
Return true if run should continue,.
Definition: Time.C:909
static int precision_
Time directory name precision.
Definition: Time.H:165
scalar timeToUserTime(const scalar t) const
Convert the real-time (s) into user-time (e.g. CA deg)
Definition: Time.C:858
instantList times() const
Search the case for valid time directories.
Definition: Time.C:659
virtual void setTime(const Time &)
Reset the time and time-index to those of the given time.
Definition: Time.C:993
virtual dimensionedScalar startTime() const
Return start time.
Definition: Time.C:810
static const NamedEnum< stopAtControl, 4 > stopAtControlNames
Definition: Time.H:117
static int curPrecision_
Current time directory name precision adjusted as necessary.
Definition: Time.H:170
void adjustDeltaT()
Adjust the time step so that writing occurs at the specified time.
Definition: Time.C:70
format
Supported time directory name formats.
Definition: Time.H:111
scalar userTimeToTime(const scalar tau) const
Convert the user-time (e.g. CA deg) to real-time (s).
Definition: Time.C:852
scalar writeInterval_
Definition: Time.H:138
virtual dimensionedScalar beginTime() const
Return begin time (initial start time)
Definition: Time.C:799
scalar userTimeValue() const
Return current user time value.
Definition: Time.C:838
scalar userDeltaTValue() const
Return user time step value.
Definition: Time.C:844
static const int maxPrecision_
Maximum time directory name precision.
Definition: Time.H:173
word findInstance(const fileName &dir, const word &name=word::null, const IOobject::readOption rOpt=IOobject::MUST_READ, const word &stopInstance=word::null) const
Return the location of "dir" containing the file "name".
Definition: Time.C:666
const unitSet & userUnits() const
Return the user-time unit conversion.
Definition: Time.C:877
virtual void setWriteInterval(const scalar writeInterval)
Reset the write interval.
Definition: Time.C:1089
virtual void setEndTime(const dimensionedScalar &)
Reset end time.
Definition: Time.C:1053
word userTimeName() const
Return current user time name with units.
Definition: Time.C:864
virtual bool running() const
Return true if run should continue without any side effects.
Definition: Time.C:903
void setControls()
Set the controls from the current controlDict.
Definition: Time.C:99
word findInstancePath(const fileName &path, const instant &) const
Search the case for the time directory path.
Definition: Time.C:697
virtual void setDeltaT(const dimensionedScalar &)
Reset time step.
Definition: Time.C:1065
static word controlDictName
The default control dictionary name (normally "controlDict")
Definition: Time.H:208
static word timeName(const scalar, const int precision=curPrecision_)
Return time name of given scalar time.
Definition: Time.C:649
wordList regionNames() const
Return the list of region names.
Definition: Time.C:636
stopAtControl
Stop-run control options.
Definition: Time.H:102
static format format_
Time directory name format.
Definition: Time.H:162
virtual bool stopAt(const stopAtControl) const
Adjust the current stopAtControl. Note that this value.
Definition: Time.C:975
const userTimes::userTime & userTime() const
Return the userTime.
Definition: Time.C:832
const unitSet & writeIntervalUnits() const
Return the write interval units.
Definition: Time.C:883
virtual label startTimeIndex() const
Return start time index.
Definition: Time.C:793
virtual void endSubCycle()
Reset time after sub-cycling back to previous TimeState.
Definition: Time.C:1131
virtual void setDeltaTNoAdjust(const scalar)
Reset time step without additional adjustment or modification.
Definition: Time.C:1082
virtual Time & operator++()
Prefix increment,.
Definition: Time.C:1157
static const NamedEnum< writeControl, 5 > writeControlNames
Definition: Time.H:119
void readModifiedObjects()
Read the objects that have been modified.
Definition: TimeIO.C:200
scalar beginTime_
Definition: Time.H:129
virtual TimeState subCycle(const label nSubCycles)
Set time to sub-cycle for the given number of steps.
Definition: Time.C:1117
writeControl
Write control options.
Definition: Time.H:92
virtual bool loop()
Return true if run should continue and if so increment time.
Definition: Time.C:956
virtual dimensionedScalar endTime() const
Return end time.
Definition: Time.C:821
virtual ~Time()
Destructor.
Definition: Time.C:627
static label findClosestTimeIndex(const instantList &, const scalar, const word &constantName="constant")
Search instantList for the time index closest to the given time.
Definition: Time.C:768
virtual Time & operator+=(const dimensionedScalar &)
Set deltaT to that specified and increment time via operator++()
Definition: Time.C:1144
virtual bool end() const
Return true if end of run,.
Definition: Time.C:969
instant findClosestTime(const scalar) const
Search the case for the time closest to the given time.
Definition: Time.C:731
T & last()
Return the last element of the list.
Definition: UListI.H:128
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:411
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:103
const word & executable() const
Name of executable without the path.
Definition: argListI.H:36
const Foam::HashTable< string > & options() const
Return options.
Definition: argListI.H:96
fileName path() const
Return the path to the caseName.
Definition: argListI.H:66
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:669
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:468
const scalar & value() const
Return const reference to value.
const word & name() const
Return const reference to name.
bool open(const fileName &libName, const bool verbose=true)
Open the named library, optionally with warnings if problems occur.
A class for handling file names.
Definition: fileName.H:82
virtual void setTime(const Time &) const
Callback for time change.
scalar timeToNextAction()
Return the time to the next write.
An instant of time. Contains the time value and name.
Definition: instant.H:67
scalar value() const
Value (const access)
Definition: instant.H:114
const word & name() const
Name (const access)
Definition: instant.H:126
bool equal(const scalar) const
Comparison used for instants to be equal.
Definition: instant.C:59
Registry of regIOobjects.
void addWatch()
Add file watch on object (if registered and READ_IF_MODIFIED)
Definition: regIOobject.C:235
timeIOdictionary derived from IOdictionary with globalFile set false to enable writing to processor t...
Unit conversion structure. Contains the associated dimensions and the multiplier with which to conver...
Definition: unitSet.H:68
An abstract class for the user time description.
A class for handling words, derived from string.
Definition: word.H:63
static const word null
An empty word.
Definition: word.H:78
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
const vector tau
static instantList timeDirs
Definition: globalFoam.H:44
runTimeSource setTime(sourceTimes[sourceTimeIndex], sourceTimeIndex)
word timeName
Definition: getTimeIndex.H:3
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
#define WarningInFunction
Report a warning using Foam::Warning.
const unitSet unitless
const unitSet none
Namespace for OpenFOAM.
const fileOperation & fileHandler()
Get current file handler.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
dlLibraryTable libs
Table of loaded dynamic libraries.
void adjustDeltaT(Time &runTime, const PtrList< solver > &solvers)
Adjust the time-step according to the solver maxDeltaT.
int system(const std::string &command)
Execute the specified command.
Definition: POSIX.C:1230
bool equal(const T &s1, const T &s2)
Definition: doubleFloat.H:62
void setDeltaT(Time &runTime, const PtrList< solver > &solvers)
Set the initial time-step according to the solver maxDeltaT.
dimensionedScalar sign(const dimensionedScalar &ds)
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
bool writeInfoHeader
bool exists(const fileName &, const bool checkVariants=true, const bool followLink=true)
Does the name exist (as directory or file) in the file system?
Definition: POSIX.C:520
dimensionedScalar log10(const dimensionedScalar &ds)
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if successful.
Definition: doubleScalar.H:75
const dimensionSet & dimTime
Definition: dimensions.C:142
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
scalar diff(const triad &A, const triad &B)
Return a quantity of the difference between two triads.
Definition: triad.C:409
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
IOerror FatalIOError
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
tmp< DimensionedField< typename powProduct< Type, r >::type, GeoMesh, Field > > pow(const DimensionedField< Type, GeoMesh, PrimitiveField > &df, typename powProduct< Type, r >::type)
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
error FatalError
static const label labelMax
Definition: label.H:62
void operator+=(fvMatrix< Type > &fvEqn, const CarrierEqn< Type > &cEqn)
Add to a finite-volume equation.
Definition: CarrierEqn.C:271
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
static const char nl
Definition: Ostream.H:297
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
label timeIndex
Definition: getTimeIndex.H:4
dictionary dict
Foam::argList args(argc, argv)