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> 
   39namespace Detail::TimeLoop {
 
   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);
 
 
  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)
 
 
  651    template<
class ForwardIterator>
 
  655        for (; first != last; ++first)
 
  656            setCheckPoint_(Detail::TimeLoop::toSeconds<Scalar>(*first));
 
 
  667    { 
return maxDtToCheckPoint_(this->
time()); }
 
 
  670    bool fuzzyEqual_(
const Scalar t0, 
const Scalar t1)
 const 
  671    { 
return Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(t0, t1, this->
baseEps_*this->
timeStepSize()); }
 
  673    void setPeriodicCheckPoint_(
Scalar interval, 
Scalar offset = 0.0)
 
  676        if (signbit(interval))
 
  677            DUNE_THROW(Dune::InvalidStateException, 
"Interval has to be positive!");
 
  679        periodicCheckPoints_ = 
true;
 
  680        deltaPeriodicCheckPoint_ = interval;
 
  681        lastPeriodicCheckPoint_ = offset;
 
  682        while (lastPeriodicCheckPoint_ + interval - this->
time() < 1e-14*interval)
 
  683            lastPeriodicCheckPoint_ += interval;
 
  686            std::cout << Fmt::format(
"Enabled periodic check points every {:.5g} seconds ", interval)
 
  687                      << Fmt::format(
"with the next check point at {:.5g} seconds.\n", lastPeriodicCheckPoint_ + interval);
 
  690        if (nextCheckPointType_(this->
time() + deltaPeriodicCheckPoint_).isPeriodic())
 
  691            isCheckPoint_ = 
true;
 
  698    void setCheckPoint_(
Scalar t)
 
  700        if (Dune::FloatCmp::le<Scalar, Dune::FloatCmp::absolute>(t - this->
time(), 0.0, this->
timeStepSize()*this->
baseEps_))
 
  703                std::cerr << Fmt::format(
"Couldn't insert checkpoint at t = {:.5g} ", t)
 
  704                          << Fmt::format(
"because that's not in the future! (current simulation time is {:.5g})\n", this->
time());
 
  708        if (!checkPoints_.empty())
 
  710            if (t <= checkPoints_.back())
 
  713                    std::cerr << Fmt::format(
"Couldn't insert checkpoint at t = {:.5g} ", t)
 
  714                              << Fmt::format(
"because it's earlier than or equal to the last check point (t = {:.5g}) in the queue.\n", checkPoints_.back())
 
  715                              << 
"Checkpoints can only be inserted in ascending order." << std::endl;
 
  720        checkPoints_.push(t);
 
  722            std::cout << Fmt::format(
"Set check point at t = {:.5g} seconds.\n", t);
 
  728    CheckPointType nextCheckPointType_(
Scalar t)
 
  730        return CheckPointType{}
 
  731            .withPeriodic(periodicCheckPoints_ && fuzzyEqual_(t - lastPeriodicCheckPoint_, deltaPeriodicCheckPoint_))
 
  732            .withManual(!checkPoints_.empty() && fuzzyEqual_(t - checkPoints_.front(), 0.0));
 
  740        static constexpr auto unset = std::numeric_limits<Scalar>::max();
 
  741        const auto dtToPeriodic = dtToNextPeriodicCheckPoint_(t);
 
  742        const auto dtToManual = dtToNextManualCheckPoint_(t);
 
  746            dtToPeriodic.value_or(unset),
 
  747            dtToManual.value_or(unset)
 
  754    std::optional<Scalar> dtToNextPeriodicCheckPoint_(
Scalar t)
 const 
  756        if (periodicCheckPoints_)
 
  757            return lastPeriodicCheckPoint_ + deltaPeriodicCheckPoint_ - t;
 
  764    std::optional<Scalar> dtToNextManualCheckPoint_(
Scalar t)
 const 
  766        if (!checkPoints_.empty())
 
  767            return checkPoints_.front() - t;
 
  771    bool periodicCheckPoints_;
 
  772    Scalar deltaPeriodicCheckPoint_;
 
  773    Scalar lastPeriodicCheckPoint_;
 
  774    std::queue<Scalar> checkPoints_;
 
 
  778template<
class... Args>
 
  780    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
Scalar timeStepSizeToNextCheckPoint() const
Return the time step size to exactly reach the next check point In case there is no check point in th...
Definition common/timeloop.hh:666
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:652
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 .
GetPropType< TypeTag, Properties::Scalar > 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
Distance implementation details.
Definition cvfelocalresidual.hh:25
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.