diff --git a/dumux/common/timeloop.hh b/dumux/common/timeloop.hh index deae729407e5248fa1813b57bbc6f9bcb9cf8dd8..b3fd5ce7393248ea9c87a5e56dc0b18ad8b9fdd3 100644 --- a/dumux/common/timeloop.hh +++ b/dumux/common/timeloop.hh @@ -421,18 +421,18 @@ public: void advanceTimeStep() override { const auto dt = this->timeStepSize(); - const auto nextTime = this->time()+dt; + const auto newTime = this->time()+dt; //! Check point management, TimeLoop::isCheckPoint() has to be called after this! // if we reached a periodic check point - if (periodicCheckPoints_ && Dune::FloatCmp::eq(nextTime - lastPeriodicCheckPoint_, deltaPeriodicCheckPoint_, 1e-7)) + if (periodicCheckPoints_ && Dune::FloatCmp::eq(newTime - lastPeriodicCheckPoint_, deltaPeriodicCheckPoint_, 1e-7)) { lastPeriodicCheckPoint_ += deltaPeriodicCheckPoint_; isCheckPoint_ = true; } // or a manually set check point - else if (!checkPoints_.empty() && Dune::FloatCmp::eq(nextTime - checkPoints_.front(), 0.0, 1e-7)) + else if (!checkPoints_.empty() && Dune::FloatCmp::eq(newTime - checkPoints_.front(), 0.0, 1e-7)) { checkPoints_.pop(); isCheckPoint_ = true; @@ -454,6 +454,21 @@ public: using std::max; if (isCheckPoint_) this->setTimeStepSize(max(dt, previousTimeStepSize)); + + // if there is a check point soon check if the time step after the next time step would be smaller + // than 20% of the next time step, if yes increase the suggested next time step to exactly reach the check point + // (in the limits of the maximum time step size) + auto nextDt = this->timeStepSize(); + const auto threshold = 0.2*nextDt; + const auto nextTime = this->time() + nextDt; + + if (periodicCheckPoints_ && Dune::FloatCmp::le(lastPeriodicCheckPoint_ + deltaPeriodicCheckPoint_ - nextTime, threshold)) + nextDt = lastPeriodicCheckPoint_ + deltaPeriodicCheckPoint_ - this->time(); + + if (!checkPoints_.empty() && Dune::FloatCmp::le(checkPoints_.front() - nextTime, threshold)) + nextDt = checkPoints_.front() - this->time(); + + this->setTimeStepSize(nextDt); } /*!