1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "objectRegistry.H"
28 #include "PstreamReduceOps.H"
30 #include "profilingPool.H"
31 #include "profiling.H"
35 // * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
37 defineTypeNameAndDebug(Foam::Time, 0);
40 const char* Foam::NamedEnum<Foam::Time::stopAtControls, 4>::names[] =
48 const Foam::NamedEnum<Foam::Time::stopAtControls, 4>
49 Foam::Time::stopAtControlNames_;
52 const char* Foam::NamedEnum<Foam::Time::writeControls, 5>::names[] =
61 const Foam::NamedEnum<Foam::Time::writeControls, 5>
62 Foam::Time::writeControlNames_;
64 Foam::Time::fmtflags Foam::Time::format_(Foam::Time::general);
65 int Foam::Time::precision_(6);
67 Foam::word Foam::Time::controlDictName("controlDict");
70 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
72 void Foam::Time::adjustDeltaT()
74 if (writeControl_ == wcAdjustableRunTime)
76 scalar timeToNextWrite = max
79 (outputTimeIndex_ + 1)*writeInterval_ - (value() - startTime_)
82 label nStepsToNextWrite = label(timeToNextWrite/deltaT_ - SMALL) + 1;
83 scalar newDeltaT = timeToNextWrite/nStepsToNextWrite;
85 // Control the increase of the time step to within a factor of 2
86 // and the decrease within a factor of 5.
87 if (newDeltaT >= deltaT_)
89 deltaT_ = min(newDeltaT, 2.0*deltaT_);
93 deltaT_ = max(newDeltaT, 0.2*deltaT_);
99 void Foam::Time::setControls()
101 // default is to resume calculation from "latestTime"
102 word startFrom = controlDict_.lookupOrDefault<word>
108 if (startFrom == "startTime")
110 controlDict_.lookup("startTime") >> startTime_;
114 // Search directory for valid time directories
115 instantList timeDirs = findTimes(path());
117 if (startFrom == "firstTime")
121 startTime_ = timeDirs[0].value();
124 else if (startFrom == "latestTime")
128 startTime_ = timeDirs[timeDirs.size()-1].value();
133 FatalIOErrorIn("Time::setControls()", controlDict_)
134 << "expected startTime, firstTime or latestTime"
135 << " found '" << startFrom << "'"
136 << exit(FatalIOError);
140 setTime(startTime_, 0);
143 deltaTSave_ = deltaT_;
144 deltaT0_ = deltaTSave_;
146 if (Pstream::parRun())
148 scalar sumStartTime = startTime_;
149 reduce(sumStartTime, sumOp<scalar>());
152 mag(Pstream::nProcs()*startTime_ - sumStartTime)
153 > Pstream::nProcs()*deltaT_/10.0
156 FatalIOErrorIn("Time::setControls()", controlDict_)
157 << "Start time is not the same for all processors" << nl
158 << "processor " << Pstream::myProcNo() << " has startTime "
159 << startTime_ << exit(FatalIOError);
163 IOdictionary timeDict
171 IOobject::READ_IF_PRESENT,
177 if (timeDict.readIfPresent("deltaT", deltaTSave_))
179 deltaT0_ = deltaTSave_;
182 if (timeDict.readIfPresent("index", startTimeIndex_))
184 timeIndex_ = startTimeIndex_;
189 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
193 const word& controlDictName,
194 const fileName& rootPath,
195 const fileName& caseName,
196 const word& systemName,
197 const word& constantName,
198 const bool enableFunctionObjects
209 objectRegistry(*this),
229 writeControl_(wcTimeStep),
230 writeInterval_(GREAT),
234 writeFormat_(IOstream::ASCII),
235 writeVersion_(IOstream::currentVersion),
236 writeCompression_(IOstream::UNCOMPRESSED),
238 runTimeModifiable_(true),
240 readLibs_(controlDict_, "libs"),
241 functionObjects_(*this, enableFunctionObjects)
245 profilingPool::initProfiling
263 const dictionary& dict,
264 const fileName& rootPath,
265 const fileName& caseName,
266 const word& systemName,
267 const word& constantName,
268 const bool enableFunctionObjects
279 objectRegistry(*this),
300 writeControl_(wcTimeStep),
301 writeInterval_(GREAT),
305 writeFormat_(IOstream::ASCII),
306 writeVersion_(IOstream::currentVersion),
307 writeCompression_(IOstream::UNCOMPRESSED),
309 runTimeModifiable_(true),
311 readLibs_(controlDict_, "libs"),
312 functionObjects_(*this, enableFunctionObjects)
316 profilingPool::initProfiling
334 const fileName& rootPath,
335 const fileName& caseName,
336 const word& systemName,
337 const word& constantName,
338 const bool enableFunctionObjects
349 objectRegistry(*this),
369 writeControl_(wcTimeStep),
370 writeInterval_(GREAT),
374 writeFormat_(IOstream::ASCII),
375 writeVersion_(IOstream::currentVersion),
376 writeCompression_(IOstream::UNCOMPRESSED),
378 runTimeModifiable_(true),
380 readLibs_(controlDict_, "libs"),
381 functionObjects_(*this, enableFunctionObjects)
383 profilingPool::initProfiling
399 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
403 // destroy function objects first
404 functionObjects_.clear();
406 profilingPool::stopProfiling(*this);
410 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
412 Foam::word Foam::Time::timeName(const scalar t)
414 std::ostringstream buf;
415 buf.setf(ios_base::fmtflags(format_), ios_base::floatfield);
416 buf.precision(precision_);
422 Foam::word Foam::Time::timeName() const
424 return dimensionedScalar::name();
428 // Search the construction path for times
429 Foam::instantList Foam::Time::times() const
431 return findTimes(path());
435 Foam::word Foam::Time::findInstancePath(const instant& t) const
437 instantList timeDirs = findTimes(path());
439 forAllReverse(timeDirs, timeI)
441 if (timeDirs[timeI] == t)
443 return timeDirs[timeI].name();
451 Foam::instant Foam::Time::findClosestTime(const scalar t) const
453 instantList timeDirs = findTimes(path());
455 // there is only one time (likely "constant") so return it
456 if (timeDirs.size() == 1)
461 if (t < timeDirs[1].value())
465 else if (t > timeDirs[timeDirs.size()-1].value())
467 return timeDirs[timeDirs.size()-1];
470 label nearestIndex = -1;
471 scalar deltaT = GREAT;
473 for (label timeI=1; timeI < timeDirs.size(); ++timeI)
475 scalar diff = mag(timeDirs[timeI].value() - t);
479 nearestIndex = timeI;
483 return timeDirs[nearestIndex];
487 // This should work too,
488 // if we don't worry about checking "constant" explicitly
490 // Foam::instant Foam::Time::findClosestTime(const scalar t) const
492 // instantList timeDirs = findTimes(path());
493 // label timeIndex = min(findClosestTimeIndex(timeDirs, t), 0);
494 // return timeDirs[timeIndex];
497 Foam::label Foam::Time::findClosestTimeIndex
499 const instantList& timeDirs,
503 label nearestIndex = -1;
504 scalar deltaT = GREAT;
506 forAll(timeDirs, timeI)
508 if (timeDirs[timeI].name() == "constant") continue;
510 scalar diff = mag(timeDirs[timeI].value() - t);
514 nearestIndex = timeI;
522 Foam::label Foam::Time::startTimeIndex() const
524 return startTimeIndex_;
528 Foam::dimensionedScalar Foam::Time::startTime() const
530 return dimensionedScalar("startTime", dimTime, startTime_);
534 Foam::dimensionedScalar Foam::Time::endTime() const
536 return dimensionedScalar("endTime", dimTime, endTime_);
540 bool Foam::Time::run() const
542 bool running = value() < (endTime_ - 0.5*deltaT_);
546 // only execute when the condition is no longer true
547 // ie, when exiting the control loop
548 if (!running && timeIndex_ != startTimeIndex_)
550 addProfile2(fo,"functionObjects_.end()");
552 // Note, end() also calls an indirect start() as required
553 functionObjects_.end();
561 bool Foam::Time::loop()
563 bool running = run();
574 bool Foam::Time::end() const
576 return value() > (endTime_ + 0.5*deltaT_);
580 void Foam::Time::setTime(const Time& t)
583 dimensionedScalar::name() = t.dimensionedScalar::name();
584 timeIndex_ = t.timeIndex_;
588 void Foam::Time::setTime(const instant& inst, const label newIndex)
590 value() = inst.value();
591 dimensionedScalar::name() = inst.name();
592 timeIndex_ = newIndex;
594 IOdictionary timeDict
602 IOobject::READ_IF_PRESENT,
608 timeDict.readIfPresent("deltaT", deltaT_);
609 timeDict.readIfPresent("deltaT0", deltaT0_);
610 timeDict.readIfPresent("index", timeIndex_);
614 void Foam::Time::setTime
616 const dimensionedScalar& newTime,
620 setTime(newTime.value(), newIndex);
624 void Foam::Time::setTime(const scalar newTime, const label newIndex)
627 dimensionedScalar::name() = timeName(timeToUserTime(newTime));
628 timeIndex_ = newIndex;
632 void Foam::Time::setStopAt(const stopAtControls& sa)
638 void Foam::Time::setEndTime(const dimensionedScalar& endTime)
640 setEndTime(endTime.value());
644 void Foam::Time::setEndTime(const scalar endTime)
650 void Foam::Time::setDeltaT
652 const dimensionedScalar& deltaT,
653 const bool bAdjustDeltaT
656 setDeltaT(deltaT.value(), bAdjustDeltaT);
660 void Foam::Time::setDeltaT(const scalar deltaT, const bool bAdjustDeltaT)
663 deltaTchanged_ = true;
672 void Foam::Time::setWriteControl(const writeControls& wc)
678 void Foam::Time::setWriteInterval(const scalar writeInterval)
680 writeInterval_ = writeInterval;
684 Foam::TimeState Foam::Time::subCycle(const label nSubCycles)
687 prevTimeState_.set(new TimeState(*this));
689 setTime(*this - deltaT(), (timeIndex() - 1)*nSubCycles);
690 deltaT_ /= nSubCycles;
691 deltaT0_ /= nSubCycles;
692 deltaTSave_ = deltaT0_;
694 return prevTimeState();
698 void Foam::Time::endSubCycle()
703 TimeState::operator=(prevTimeState());
704 prevTimeState_.clear();
709 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
711 Foam::Time& Foam::Time::operator+=(const dimensionedScalar& deltaT)
713 return operator+=(deltaT.value());
717 Foam::Time& Foam::Time::operator+=(const scalar deltaT)
724 Foam::Time& Foam::Time::operator++()
726 readModifiedObjects();
730 if (timeIndex_ == startTimeIndex_)
732 addProfile2(fo,"functionObjects_.start()");
734 functionObjects_.start();
738 addProfile2(fo,"functionObjects_.execute()");
740 functionObjects_.execute();
744 deltaT0_ = deltaTSave_;
745 deltaTSave_ = deltaT_;
747 const word oldTimeName = dimensionedScalar::name();
749 setTime(value() + deltaT_, timeIndex_ + 1);
751 // If the time is very close to zero reset to zero
752 if (mag(value()) < 10*SMALL*deltaT_)
754 setTime(0.0, timeIndex_);
757 // Check that new time representation differs from old one
758 if (dimensionedScalar::name() == oldTimeName)
760 int oldPrecision = precision_;
764 setTime(value(), timeIndex());
766 while (precision_ < 100 && dimensionedScalar::name() == oldTimeName);
768 WarningIn("Time::operator++()")
769 << "Increased the timePrecision from " << oldPrecision
770 << " to " << precision_
771 << " to distinguish between timeNames at time " << value()
775 switch (writeControl_)
778 outputTime_ = !(timeIndex_ % label(writeInterval_));
782 case wcAdjustableRunTime:
785 label(((value() - startTime_) + 0.5*deltaT_)/writeInterval_);
787 if (outputIndex > outputTimeIndex_)
790 outputTimeIndex_ = outputIndex;
801 label outputIndex = label(elapsedCpuTime()/writeInterval_);
802 if (outputIndex > outputTimeIndex_)
805 outputTimeIndex_ = outputIndex;
816 label outputIndex = label(elapsedClockTime()/writeInterval_);
817 if (outputIndex > outputTimeIndex_)
820 outputTimeIndex_ = outputIndex;
830 // see if endTime needs adjustment to stop at the next run()/end() check
833 if (stopAt_ == saNoWriteNow)
837 else if (stopAt_ == saWriteNow)
842 else if (stopAt_ == saNextWrite && outputTime_ == true)
852 Foam::Time& Foam::Time::operator++(int)
858 // ************************************************************************* //