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