12#ifndef DUMUX_TIME_LOOP_HH
13#define DUMUX_TIME_LOOP_HH
20#include <initializer_list>
23#include <dune/common/float_cmp.hh>
24#include <dune/common/timer.hh>
26#include <dune/common/parallel/communication.hh>
28#include <dune/common/parallel/mpihelper.hh>
29#include <dune/common/exceptions.hh>
41template<
typename Scalar,
typename R,
typename P>
42Scalar
toSeconds(std::chrono::duration<R, P> duration)
44 using Second = std::chrono::duration<Scalar, std::ratio<1>>;
45 return std::chrono::duration_cast<Second>(duration).count();
48template<
typename Scalar,
typename T, std::enable_if_t<std::is_
floating_po
int_v<T>,
bool> = true>
50{
return static_cast<Scalar
>(duration); }
53template<
typename Scalar,
typename T, std::enable_if_t<!std::is_
floating_po
int_v<T>,
bool> = true>
55{
static_assert(AlwaysFalse<T>::value,
"Given type not supported for representation of time values"); }
123 template<
class Rep,
class Period>
137template <
class Scalar>
147 template<
class Rep1,
class Period1,
148 class Rep2,
class Period2,
149 class Rep3,
class Period3>
150 TimeLoop(std::chrono::duration<Rep1, Period1> startTime,
151 std::chrono::duration<Rep2, Period2> dt,
152 std::chrono::duration<Rep3, Period3> tEnd,
194 template<
class Rep1,
class Period1,
195 class Rep2,
class Period2,
196 class Rep3,
class Period3>
197 void reset(std::chrono::duration<Rep1, Period1> startTime,
198 std::chrono::duration<Rep2, Period2> dt,
199 std::chrono::duration<Rep3, Period3> tEnd,
203 Detail::TimeLoop::toSeconds<Scalar>(startTime),
204 Detail::TimeLoop::toSeconds<Scalar>(dt),
205 Detail::TimeLoop::toSeconds<Scalar>(tEnd)
216 Dune::MPIHelper::getCommunication().rank() == 0;
260 template<
class ScalarOrDuration>
262 {
time_ = Detail::TimeLoop::toSeconds<Scalar>(t); }
270 template<
class ScalarOrDuration>
273 time_ = Detail::TimeLoop::toSeconds<Scalar>(t);
300 std::cout << Fmt::format(
"Set new end time to t = {:.5g} seconds.\n", t);
307 {
return timer_.elapsed(); }
331 std::cerr << Fmt::format(
"You have set a very small timestep size (dt = {:.5g}).",
timeStepSize_)
332 <<
" This might lead to numerical problems!\n";
341 template<
class ScalarOrDuration>
409 using std::min;
using std::max;
424 std::cout << Fmt::format(
"[{:3.0f}%] ", percent)
433 template<
class Communicator = Dune::Communication<
typename Dune::MPIHelper::MPICommunicator> >
434 void finalize(
const Communicator& comm = Dune::MPIHelper::getCommunication())
436 auto cpuTime =
timer_.stop();
439 std::cout << Fmt::format(
"Simulation took {:.5g} seconds on {} processes.\n", cpuTime, comm.size());
442 cpuTime = comm.sum(cpuTime);
445 std::cout << Fmt::format(
"The cumulative CPU time was {:.5g} seconds.\n", cpuTime);
478template<
class Rep1,
class Period1,
479 class Rep2,
class Period2,
480 class Rep3,
class Period3>
482 std::chrono::duration<Rep2, Period2>,
483 std::chrono::duration<Rep3, Period3>,
484 bool verbose =
true) ->
TimeLoop<std::conditional_t<
485 std::is_floating_point_v<std::common_type_t<Rep1, Rep2, Rep3>>,
486 std::common_type_t<Rep1, Rep2, Rep3>,
494template <
class Scalar>
497 class CheckPointType {
498 static constexpr std::size_t manualIdx = 0;
499 static constexpr std::size_t periodicIdx = 1;
502 bool isPeriodic()
const {
return set_[periodicIdx]; }
503 bool isManual()
const {
return set_[manualIdx]; }
504 bool isAny()
const {
return set_.any(); }
506 CheckPointType& withPeriodic(
bool value) { set_[periodicIdx] = value;
return *
this; }
507 CheckPointType& withManual(
bool value) { set_[manualIdx] = value;
return *
this; }
514 template<
class... Args>
518 periodicCheckPoints_ =
false;
519 deltaPeriodicCheckPoint_ = 0.0;
521 isCheckPoint_ =
false;
530 const auto newTime = this->
time()+dt;
533 const auto cpType = nextCheckPointType_(newTime);
534 if (cpType.isManual()) checkPoints_.pop();
535 if (cpType.isPeriodic()) lastPeriodicCheckPoint_ += deltaPeriodicCheckPoint_;
536 isCheckPoint_ = cpType.isAny();
555 const auto threshold = 0.2*nextDt;
556 const auto nextTime = this->
time() + nextDt;
558 const auto nextDtToCheckPoint = maxDtToCheckPoint_(nextTime);
559 if (nextDtToCheckPoint >
Scalar{0} && Dune::FloatCmp::le(nextDtToCheckPoint, threshold))
560 nextDt += nextDtToCheckPoint;
562 assert(nextDt > 0.0);
575 const auto maxCheckPointDt = computeStepSizeRespectingCheckPoints_();
577 return min(maxDtParent, maxCheckPointDt);
590 template<
class ScalarOrDuration1,
class ScalarOrDuration2 = Scalar>
593 setPeriodicCheckPoint_(
594 Detail::TimeLoop::toSeconds<Scalar>(interval),
595 Detail::TimeLoop::toSeconds<Scalar>(offset)
601 { periodicCheckPoints_ =
false; }
606 periodicCheckPoints_ =
false;
607 while (!checkPoints_.empty())
616 {
return isCheckPoint_; }
624 template<
class ScalarOrDuration>
628 setCheckPoint_(Detail::TimeLoop::toSeconds<Scalar>(t));
640 template<
class ScalarOrDuration>
641 void setCheckPoint(
const std::initializer_list<ScalarOrDuration>& checkPoints)
644 template<
class ScalarOrDuration>
645 [[deprecated(
"Use setCheckpoint(begin, end) instead. Will be removed after release 3.9.")]]
656 template<
class ForwardIterator>
660 for (; first != last; ++first)
661 setCheckPoint_(Detail::TimeLoop::toSeconds<Scalar>(*first));
668 bool fuzzyEqual_(
const Scalar t0,
const Scalar t1)
const
671 void setPeriodicCheckPoint_(
Scalar interval,
Scalar offset = 0.0)
674 if (signbit(interval))
675 DUNE_THROW(Dune::InvalidStateException,
"Interval has to be positive!");
677 periodicCheckPoints_ =
true;
678 deltaPeriodicCheckPoint_ = interval;
679 lastPeriodicCheckPoint_ = offset;
680 while (lastPeriodicCheckPoint_ + interval - this->
time() < 1e-14*interval)
681 lastPeriodicCheckPoint_ += interval;
684 std::cout << Fmt::format(
"Enabled periodic check points every {:.5g} seconds ", interval)
685 << Fmt::format(
"with the next check point at {:.5g} seconds.\n", lastPeriodicCheckPoint_ + interval);
688 if (nextCheckPointType_(this->
time() + deltaPeriodicCheckPoint_).isPeriodic())
689 isCheckPoint_ =
true;
696 void setCheckPoint_(
Scalar t)
701 std::cerr << Fmt::format(
"Couldn't insert checkpoint at t = {:.5g} ", t)
702 << Fmt::format(
"because that's not in the future! (current simulation time is {:.5g})\n", this->
time());
706 if (!checkPoints_.empty())
708 if (t <= checkPoints_.back())
711 std::cerr << Fmt::format(
"Couldn't insert checkpoint at t = {:.5g} ", t)
712 << Fmt::format(
"because it's earlier than or equal to the last check point (t = {:.5g}) in the queue.\n", checkPoints_.back())
713 <<
"Checkpoints can only be inserted in ascending order." << std::endl;
718 checkPoints_.push(t);
720 std::cout << Fmt::format(
"Set check point at t = {:.5g} seconds.\n", t);
726 CheckPointType nextCheckPointType_(
Scalar t)
728 return CheckPointType{}
729 .withPeriodic(periodicCheckPoints_ && fuzzyEqual_(t - lastPeriodicCheckPoint_, deltaPeriodicCheckPoint_))
730 .withManual(!checkPoints_.empty() && fuzzyEqual_(t - checkPoints_.front(), 0.0));
736 Scalar computeStepSizeRespectingCheckPoints_()
const
737 {
return maxDtToCheckPoint_(this->
time()); }
744 static constexpr auto unset = std::numeric_limits<Scalar>::max();
745 const auto dtToPeriodic = dtToNextPeriodicCheckPoint_(t);
746 const auto dtToManual = dtToNextManualCheckPoint_(t);
750 dtToPeriodic.value_or(unset),
751 dtToManual.value_or(unset)
758 std::optional<Scalar> dtToNextPeriodicCheckPoint_(
Scalar t)
const
760 if (periodicCheckPoints_)
761 return lastPeriodicCheckPoint_ + deltaPeriodicCheckPoint_ - t;
768 std::optional<Scalar> dtToNextManualCheckPoint_(
Scalar t)
const
770 if (!checkPoints_.empty())
771 return checkPoints_.front() - t;
775 bool periodicCheckPoints_;
776 Scalar deltaPeriodicCheckPoint_;
777 Scalar lastPeriodicCheckPoint_;
778 std::queue<Scalar> checkPoints_;
782template<
class... Args>
784 typename decltype(
TimeLoop{std::forward<Args>(args)...})::Scalar
A time loop with a check point mechanism.
Definition: common/timeloop.hh:496
bool isCheckPoint() const
Whether now is a time checkpoint.
Definition: common/timeloop.hh:615
CheckPointTimeLoop(Args &&... args)
Definition: common/timeloop.hh:515
void advanceTimeStep() override
Advance time step.
Definition: common/timeloop.hh:527
void removeAllCheckPoints()
remove all check points
Definition: common/timeloop.hh:604
void setPeriodicCheckPoint(ScalarOrDuration1 interval, ScalarOrDuration2 offset=0.0)
Set a periodic check point.
Definition: common/timeloop.hh:591
void setCheckPoint(const std::vector< ScalarOrDuration > &checkPoints)
Definition: common/timeloop.hh:646
void setCheckPoint(ScalarOrDuration t)
add a checkpoint to the queue
Definition: common/timeloop.hh:625
Scalar maxTimeStepSize() const override
The current maximum time step size.
Definition: common/timeloop.hh:572
void setCheckPoint(ForwardIterator first, ForwardIterator last)
add checkpoints to the queue from a container from the first iterator to the last iterator
Definition: common/timeloop.hh:657
void setCheckPoint(const std::initializer_list< ScalarOrDuration > &checkPoints)
add checkpoints to the queue from a list of time points
Definition: common/timeloop.hh:641
void disablePeriodicCheckPoints()
disable periodic check points
Definition: common/timeloop.hh:600
Manages the handling of time dependent problems.
Definition: common/timeloop.hh:84
virtual Scalar time() const =0
Return the time before the time integration. To get the time after the time integration you have to ...
virtual void setTimeStepSize(Scalar dt)=0
Set the current time step size to a given value.
virtual Scalar timeStepSize() const =0
Returns the suggested time step length .
S Scalar
Definition: common/timeloop.hh:86
virtual void advanceTimeStep()=0
Advance to the next time step.
void setTimeStepSize(std::chrono::duration< Rep, Period > dt)
Set the current time step size to a given value.
Definition: common/timeloop.hh:124
virtual bool finished() const =0
Returns true if the simulation is finished.
virtual Scalar maxTimeStepSize() const =0
Get the maximum possible time step size .
virtual ~TimeLoopBase()
Abstract base class needs virtual constructor.
Definition: common/timeloop.hh:89
The default time loop for instationary simulations.
Definition: common/timeloop.hh:139
void setMaxTimeStepSize(ScalarOrDuration maxDt)
Set the maximum time step size to a given value.
Definition: common/timeloop.hh:342
Scalar maxTimeStepSize() const override
The current maximum time step size.
Definition: common/timeloop.hh:404
void resetTimer()
Reset the timer.
Definition: common/timeloop.hh:186
TimeLoop(Scalar startTime, Scalar dt, Scalar tEnd, bool verbose=true)
Definition: common/timeloop.hh:141
void setVerbose(bool verbose=true)
Sets time loop verbosity.
Definition: common/timeloop.hh:453
Scalar time_
Definition: common/timeloop.hh:464
int timeStepIndex() const
Returns number of time steps which have been executed since the beginning of the simulation.
Definition: common/timeloop.hh:360
double stop()
Tells the time loop to stop tracking the time.
Definition: common/timeloop.hh:178
Scalar endTime_
Definition: common/timeloop.hh:465
TimeLoop(std::chrono::duration< Rep1, Period1 > startTime, std::chrono::duration< Rep2, Period2 > dt, std::chrono::duration< Rep3, Period3 > tEnd, bool verbose=true)
Definition: common/timeloop.hh:150
Scalar previousTimeStepSize_
Definition: common/timeloop.hh:469
void advanceTimeStep() override
Advance time step.
Definition: common/timeloop.hh:239
int timeStepIdx_
Definition: common/timeloop.hh:472
void start()
Tells the time loop to start tracking the time.
Definition: common/timeloop.hh:169
Scalar userSetMaxTimeStepSize_
Definition: common/timeloop.hh:470
void setFinished(bool finished=true)
Specify whether the simulation is finished.
Definition: common/timeloop.hh:376
bool verbose() const
If the time loop has verbose output.
Definition: common/timeloop.hh:449
void finalize(const Communicator &comm=Dune::MPIHelper::getCommunication())
Print final status and stops tracking the time.
Definition: common/timeloop.hh:434
bool verbose_
Definition: common/timeloop.hh:474
bool willBeFinished() const
Returns true if the simulation is finished after the time level is incremented by the current time st...
Definition: common/timeloop.hh:394
Scalar previousTimeStepSize() const
The previous time step size.
Definition: common/timeloop.hh:366
void reset(Scalar startTime, Scalar dt, Scalar tEnd, bool verbose=true)
Reset the time loop.
Definition: common/timeloop.hh:212
Scalar endTime() const
Returns the number of (simulated) seconds which the simulation runs.
Definition: common/timeloop.hh:288
void setTime(ScalarOrDuration t)
Set the current simulated time, don't change the current time step index.
Definition: common/timeloop.hh:261
void setTimeStepSize(Scalar dt) final
Set the current time step size to a given value.
Definition: common/timeloop.hh:320
bool finished() const override
Returns true if the simulation is finished.
Definition: common/timeloop.hh:385
Scalar timeStepSize_
Definition: common/timeloop.hh:468
void reportTimeStep() const
State info on cpu time.
Definition: common/timeloop.hh:417
void setTime(ScalarOrDuration t, int stepIdx)
Set the current simulated time and the time step index.
Definition: common/timeloop.hh:271
static constexpr Scalar baseEps_
Definition: common/timeloop.hh:461
Scalar timeStepSize() const final
Returns the suggested time step length so that we don't miss the beginning of the next episode or cr...
Definition: common/timeloop.hh:353
bool finished_
Definition: common/timeloop.hh:473
Dune::Timer timer_
Definition: common/timeloop.hh:463
void reset(std::chrono::duration< Rep1, Period1 > startTime, std::chrono::duration< Rep2, Period2 > dt, std::chrono::duration< Rep3, Period3 > tEnd, bool verbose=true)
Reset the time loop.
Definition: common/timeloop.hh:197
void setEndTime(Scalar t)
Set the time of simulated seconds at which the simulation runs.
Definition: common/timeloop.hh:296
Scalar startTime_
Definition: common/timeloop.hh:466
double wallClockTime() const
Returns the current wall clock time (cpu time) spend in this time loop.
Definition: common/timeloop.hh:306
Scalar timeAfterLastTimeStep_
Definition: common/timeloop.hh:471
Scalar time() const final
Return the time before the time integration. To get the time after the time integration you have to ...
Definition: common/timeloop.hh:282
Scalar timeStepWallClockTime_
Definition: common/timeloop.hh:471
std::chrono::duration< Rep > toSeconds(const std::string &s)
Try to construct an instance of std::chrono::seconds from a string including a unit suffix.
Definition: chrono.hh:63
TimeLoop(std::chrono::duration< Rep1, Period1 >, std::chrono::duration< Rep2, Period2 >, std::chrono::duration< Rep3, Period3 >, bool verbose=true) -> TimeLoop< std::conditional_t< std::is_floating_point_v< std::common_type_t< Rep1, Rep2, Rep3 > >, std::common_type_t< Rep1, Rep2, Rep3 >, double > >
CheckPointTimeLoop(Args &&... args) -> CheckPointTimeLoop< typename decltype(TimeLoop{std::forward< Args >(args)...})::Scalar >
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.