Merge pull request #6320 from erikhide/update-time-step-control-verbosity

Cleaned up and fixed verbosity for time step controllers
This commit is contained in:
Markus Blatt authored and GitHub committed 2025-07-21 16:16:55 +02:00
commit 816f3fe97b
3 files changed
+149 -97

No files matched your search

@@ -163,38 +163,42 @@ void registerAdaptiveParameters()
std::tuple<TimeStepControlType, std::unique_ptr<TimeStepControlInterface>, bool>
createController(const UnitSystem& unitSystem)
{
const double tol = Parameters::Get<Parameters::TimeStepControlTolerance>(); // 1e-1
const double tol = Parameters::Get<Parameters::TimeStepControlTolerance>();
const bool verbose = Parameters::Get<Parameters::TimeStepVerbosity>();
using RetVal = std::tuple<TimeStepControlType, std::unique_ptr<TimeStepControlInterface>, bool>;
using Func = std::function<RetVal()>;
const auto creators = std::unordered_map<std::string, Func> {
{"pid",
[tol]() {
[tol, verbose]() {
return RetVal{
TimeStepControlType::PID,
std::make_unique<PIDTimeStepControl>(tol),
std::make_unique<PIDTimeStepControl>(tol,
verbose),
false
};
}},
{"pid+iteration",
[tol]() {
const int iterations = Parameters::Get<Parameters::TimeStepControlTargetIterations>(); // 30
const double decayDampingFactor = Parameters::Get<Parameters::TimeStepControlDecayDampingFactor>(); // 1.0
const double growthDampingFactor = Parameters::Get<Parameters::TimeStepControlGrowthDampingFactor>(); // 3.2
[tol, verbose]() {
const int iterations = Parameters::Get<Parameters::TimeStepControlTargetIterations>();
const double decayDampingFactor = Parameters::Get<Parameters::TimeStepControlDecayDampingFactor>();
const double growthDampingFactor = Parameters::Get<Parameters::TimeStepControlGrowthDampingFactor>();
return RetVal{
TimeStepControlType::PIDAndIterationCount,
std::make_unique<PIDAndIterationCountTimeStepControl>(iterations,
decayDampingFactor,
growthDampingFactor,
tol),
tol,
0.0, // should be zero for target *linear* iterations
verbose),
false
};
}},
{"pid+newtoniteration",
[tol, &unitSystem]() {
const int iterations = Parameters::Get<Parameters::TimeStepControlTargetNewtonIterations>(); // 8
const double decayDampingFactor = Parameters::Get<Parameters::TimeStepControlDecayDampingFactor>(); // 1.0
const double growthDampingFactor = Parameters::Get<Parameters::TimeStepControlGrowthDampingFactor>(); // 3.2
const double nonDimensionalMinTimeStepIterations = Parameters::Get<Parameters::MinTimeStepBasedOnNewtonIterations>(); // 0.0 by default
[tol, verbose, &unitSystem]() {
const int iterations = Parameters::Get<Parameters::TimeStepControlTargetNewtonIterations>();
const double decayDampingFactor = Parameters::Get<Parameters::TimeStepControlDecayDampingFactor>();
const double growthDampingFactor = Parameters::Get<Parameters::TimeStepControlGrowthDampingFactor>();
const double nonDimensionalMinTimeStepIterations = Parameters::Get<Parameters::MinTimeStepBasedOnNewtonIterations>();
// the min time step can be reduced by the newton iteration numbers
double minTimeStepReducedByIterations = unitSystem.to_si(UnitSystem::measure::time,
nonDimensionalMinTimeStepIterations);
@@ -204,44 +208,46 @@ createController(const UnitSystem& unitSystem)
decayDampingFactor,
growthDampingFactor,
tol,
minTimeStepReducedByIterations),
minTimeStepReducedByIterations,
verbose),
true
};
}},
{"iterationcount",
[]() {
const int iterations = Parameters::Get<Parameters::TimeStepControlTargetIterations>(); // 30
const double decayrate = Parameters::Get<Parameters::TimeStepControlDecayRate>(); // 0.75
const double growthrate = Parameters::Get<Parameters::TimeStepControlGrowthRate>(); // 1.25
[verbose]() {
const int iterations = Parameters::Get<Parameters::TimeStepControlTargetIterations>();
const double decayrate = Parameters::Get<Parameters::TimeStepControlDecayRate>();
const double growthrate = Parameters::Get<Parameters::TimeStepControlGrowthRate>();
return RetVal{
TimeStepControlType::SimpleIterationCount,
std::make_unique<SimpleIterationCountTimeStepControl>(iterations,
decayrate,
growthrate),
growthrate,
verbose),
false
};
}},
{"newtoniterationcount",
[]() {
const int iterations = Parameters::Get<Parameters::TimeStepControlTargetNewtonIterations>(); // 8
const double decayrate = Parameters::Get<Parameters::TimeStepControlDecayRate>(); // 0.75
const double growthrate = Parameters::Get<Parameters::TimeStepControlGrowthRate>(); // 1.25
[verbose]() {
const int iterations = Parameters::Get<Parameters::TimeStepControlTargetNewtonIterations>();
const double decayrate = Parameters::Get<Parameters::TimeStepControlDecayRate>();
const double growthrate = Parameters::Get<Parameters::TimeStepControlGrowthRate>();
return RetVal{
TimeStepControlType::SimpleIterationCount,
std::make_unique<SimpleIterationCountTimeStepControl>(iterations,
decayrate,
growthrate),
growthrate,
verbose),
true
};
}},
{"general3rdorder",
[tol]() {
[tol, verbose]() {
const double safetyFactor = Parameters::Get<Parameters::TimeStepControlSafetyFactor>();
const bool rejectCompletedStep = Parameters::Get<Parameters::TimeStepControlRejectCompletedStep>();
const std::string toleranceTestVersion = Parameters::Get<Parameters::TimeStepControlToleranceTestVersion>();
const double maxReductionTimeStep = Parameters::Get<Parameters::TimeStepControlMaxReductionTimeStep>();
const std::string parameters = Parameters::Get<Parameters::TimeStepControlParameters>();
const bool verbose = Parameters::Get<Parameters::TimeStepVerbosity>();
return RetVal{
TimeStepControlType::General3rdOrder,
std::make_unique<General3rdOrderController>(tol,
@@ -256,7 +262,7 @@ createController(const UnitSystem& unitSystem)
}},
{"hardcoded",
[]() {
const std::string filename = Parameters::Get<Parameters::TimeStepControlFileName>(); // "timesteps"
const std::string filename = Parameters::Get<Parameters::TimeStepControlFileName>();
return RetVal{
TimeStepControlType::HardCodedTimeStep,
std::make_unique<HardcodedTimeStepControl>(filename),
@@ -265,7 +271,7 @@ createController(const UnitSystem& unitSystem)
}},
};
const std::string control = Parameters::Get<Parameters::TimeStepControl>(); // "pid"
const std::string control = Parameters::Get<Parameters::TimeStepControl>();
const auto it = creators.find(control);
if (it == creators.end()) {
OPM_THROW(std::runtime_error,
+48 -28
View File
@@ -92,6 +92,9 @@ namespace Opm
dtEstimate *= growthrate_;
}
if( verbose_ )
OpmLog::info(fmt::format("Suggested next time step size (from controller): {} days", unit::convert::to( dtEstimate, unit::day )));
return dtEstimate;
}
@@ -192,7 +195,7 @@ namespace Opm
// adjust dt by given tolerance
const double newDt = dt * tol_ / error;
if ( verbose_ )
OpmLog::info(fmt::format("Computed step size (tol): {} days", unit::convert::to( newDt, unit::day )));
OpmLog::info(fmt::format("Suggested next time step size (from PID controller): {} days", unit::convert::to( newDt, unit::day )));
return newDt;
}
else if (errors_[0] == 0 || errors_[1] == 0 || errors_[2] == 0.)
@@ -211,7 +214,7 @@ namespace Opm
std::pow( tol_ / errors_[ 2 ], kI ) *
std::pow( errors_[1]*errors_[1]/errors_[ 0 ]/errors_[ 2 ], kD ));
if( verbose_ )
OpmLog::info(fmt::format("Computed step size (pow): {} days", unit::convert::to( newDt, unit::day )));
OpmLog::info(fmt::format("Suggested next time step size (from PID controller): {} days", unit::convert::to( newDt, unit::day )));
return newDt;
}
}
@@ -243,6 +246,7 @@ namespace Opm
, decayDampingFactor_( decayDampingFactor )
, growthDampingFactor_( growthDampingFactor )
, minTimeStepBasedOnIterations_(minTimeStepBasedOnIterations)
, verbose_(verbose)
{}
PIDAndIterationCountTimeStepControl
@@ -270,6 +274,9 @@ namespace Opm
dtEstimateIter = dt * (1.0 + off_target_fraction * growthDampingFactor_);
}
if( verbose_ )
OpmLog::info(fmt::format("Suggested next time step size (from iteration target): {} days", unit::convert::to( dtEstimateIter, unit::day )));
return std::min(dtEstimatePID, dtEstimateIter);
}
@@ -279,7 +286,8 @@ namespace Opm
this->target_iterations_ == ctrl.target_iterations_ &&
this->decayDampingFactor_ == ctrl.decayDampingFactor_ &&
this->growthDampingFactor_ == ctrl.growthDampingFactor_ &&
this->minTimeStepBasedOnIterations_ == ctrl.minTimeStepBasedOnIterations_;
this->minTimeStepBasedOnIterations_ == ctrl.minTimeStepBasedOnIterations_ &&
this->verbose_ == ctrl.verbose_;
}
@@ -345,7 +353,38 @@ namespace Opm
double General3rdOrderController::
computeTimeStepSize(const double dt, const int /* iterations */, const RelativeChangeInterface& /* relChange */, const AdaptiveSimulatorTimer& substepTimer) const
{
if (errors_[0] == 0 || errors_[1] == 0 || errors_[2] == 0)
for( int i = 0; i < 2; ++i )
{
assert(std::isfinite(errors_[i]));
}
if (substepTimer.currentStepNum() < 3) // Use an I controller after report time steps
{
controllerVersion_ = InternalControlVersions::IController;
}
else // Use the general third order controller for all other time steps
{
controllerVersion_ = InternalControlVersions::General3rdOrder;
}
bool noTimeStepConstraint = false;
if (controllerVersion_ == InternalControlVersions::IController)
{
if (errors_[2] == 0)
{
noTimeStepConstraint = true;
}
}
else
{
if (errors_[0] == 0 || errors_[1] == 0 || errors_[2] == 0)
{
noTimeStepConstraint = true;
}
}
if (noTimeStepConstraint)
{
if ( verbose_ )
{
@@ -354,33 +393,14 @@ namespace Opm
return std::numeric_limits<double>::max();
}
for( int i = 0; i < 2; ++i )
{
assert(std::isfinite(errors_[i]));
}
const double newDt = dt * timeStepFactor(errors_, timeSteps_);
// Use an I controller after report time steps
if (substepTimer.currentStepNum() < 3)
if (verbose_)
{
controllerVersion_ = InternalControlVersions::IController;
const double newDt = dt * timeStepFactor(errors_, timeSteps_);
if (verbose_)
{
OpmLog::info(fmt::format("Computed step size (pow): {} days", unit::convert::to( newDt, unit::day )));
}
return newDt;
}
// Use the general third order controller for all other time steps
else
{
controllerVersion_ = InternalControlVersions::General3rdOrder;
const double newDt = dt * timeStepFactor(errors_, timeSteps_);
if (verbose_)
{
OpmLog::info(fmt::format("Computed step size (pow): {} days", unit::convert::to( newDt, unit::day )));
}
return newDt;
OpmLog::info(fmt::format("Suggested next time step size (from controller): {} days", unit::convert::to( newDt, unit::day )));
OpmLog::info(fmt::format("Most recent relative change: {}", errors_[2]));
}
return newDt;
}
double General3rdOrderController::
+67 -41
View File
@@ -56,17 +56,18 @@ namespace Opm
{
public:
static constexpr TimeStepControlType Type = TimeStepControlType::SimpleIterationCount;
SimpleIterationCountTimeStepControl() = default;
/// \brief constructor
/// \param target_iterations number of desired iterations (e.g. Newton iterations) per time step in one time step
// \param decayrate decayrate of time step when target iterations are not met (should be <= 1)
// \param growthrate growthrate of time step when target iterations are not met (should be >= 1)
/// \param verbose if true get some output (default = false)
SimpleIterationCountTimeStepControl( const int target_iterations,
const double decayrate,
const double growthrate,
const bool verbose = false);
/// \param decayrate decayrate of time step when target iterations are not met (should be <= 1)
/// \param growthrate growthrate of time step when target iterations are not met (should be >= 1)
/// \param verbose if true, get some output
SimpleIterationCountTimeStepControl(const int target_iterations,
const double decayrate,
const double growthrate,
const bool verbose);
static SimpleIterationCountTimeStepControl serializationTestObject();
@@ -76,7 +77,8 @@ namespace Opm
const RelativeChangeInterface& /* relativeChange */,
const AdaptiveSimulatorTimer& /* substepTimer */ ) const override;
bool timeStepAccepted(const double /* error */, const double /* timeStepJustCompleted */) const override { return true; }
bool timeStepAccepted(const double /* error */,
const double /* timeStepJustCompleted */) const override { return true; }
template<class Serializer>
void serializeOp(Serializer& serializer)
@@ -114,12 +116,15 @@ namespace Opm
{
public:
static constexpr TimeStepControlType Type = TimeStepControlType::PID;
PIDTimeStepControl() = default;
/// \brief constructor
/// \param tol tolerance for the relative changes of the numerical solution to be accepted
/// in one time step (default is 1e-3)
/// \param verbose if true get some output (default = false)
explicit PIDTimeStepControl(const double tol = 1e-3,
const bool verbose = false);
/// in one time step
/// \param verbose if true, get some output
PIDTimeStepControl(const double tol,
const bool verbose);
static PIDTimeStepControl serializationTestObject();
@@ -129,7 +134,8 @@ namespace Opm
const RelativeChangeInterface& relativeChange,
const AdaptiveSimulatorTimer& /* substepTimer */ ) const override;
bool timeStepAccepted(const double /* error */, const double /* timeStepJustCompleted */) const override { return true; }
bool timeStepAccepted(const double /* error */,
const double /* timeStepJustCompleted */) const override { return true; }
template<class Serializer>
void serializeOp(Serializer& serializer)
@@ -142,16 +148,15 @@ namespace Opm
bool operator==(const PIDTimeStepControl&) const;
protected:
const double tol_ = 1e-3;
const double tol_ = 0.1;
mutable std::vector< double > errors_{};
const bool verbose_ = false;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// PID controller based adaptive time step control as above that also takes
/// an target iteration into account.
/// target iterations into account.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
class PIDAndIterationCountTimeStepControl : public PIDTimeStepControl
@@ -160,17 +165,22 @@ namespace Opm
public:
static constexpr TimeStepControlType Type = TimeStepControlType::PIDAndIterationCount;
PIDAndIterationCountTimeStepControl() = default;
/// \brief constructor
/// \param target_iterations number of desired iterations per time step
/// \param tol tolerance for the relative changes of the numerical solution to be accepted
/// in one time step (default is 1e-3)
/// \param verbose if true get some output (default = false)
explicit PIDAndIterationCountTimeStepControl(const int target_iterations = 20,
const double decayDampingFactor = 1.0,
const double growthDampingFactor = 1.0/1.2,
const double tol = 1e-3,
const double minTimeStepBasedOnIterations = 0.,
const bool verbose = false);
/// \param target_iterations number of desired iterations per time step
/// \param decayDampingFactor limiting the decrease in time step if iteration count was high
/// \param growthDampingFactor limiting the increase in time step if iteration count was low
/// \param tol tolerance for the relative changes of the numerical solution to be
/// accepted in one time step
/// \param minTimeStepBasedOnIterations time step suggestion from target iterations should not be below this
/// \param verbose if true, get some output
PIDAndIterationCountTimeStepControl(const int target_iterations,
const double decayDampingFactor,
const double growthDampingFactor,
const double tol,
const double minTimeStepBasedOnIterations,
const bool verbose);
static PIDAndIterationCountTimeStepControl serializationTestObject();
@@ -180,7 +190,8 @@ namespace Opm
const RelativeChangeInterface& relativeChange,
const AdaptiveSimulatorTimer& /* substepTimer */ ) const override;
bool timeStepAccepted(const double /* error */, const double /* timeStepJustCompleted */) const override { return true; }
bool timeStepAccepted(const double /* error */,
const double /* timeStepJustCompleted */) const override { return true; }
template<class Serializer>
void serializeOp(Serializer& serializer)
@@ -190,15 +201,17 @@ namespace Opm
serializer(decayDampingFactor_);
serializer(growthDampingFactor_);
serializer(minTimeStepBasedOnIterations_);
serializer(verbose_);
}
bool operator==(const PIDAndIterationCountTimeStepControl&) const;
protected:
const int target_iterations_;
const double decayDampingFactor_;
const double growthDampingFactor_;
const double minTimeStepBasedOnIterations_;
const int target_iterations_ = 8;
const double decayDampingFactor_ = 1.0;
const double growthDampingFactor_ = 3.2;
const double minTimeStepBasedOnIterations_ = 0.0;
const bool verbose_ = false;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -212,14 +225,24 @@ namespace Opm
static constexpr TimeStepControlType Type = TimeStepControlType::General3rdOrder;
General3rdOrderController() = default;
General3rdOrderController( const double tolerance,
const double safetyFactor,
const bool rejectCompletedStep,
const std::string& toleranceTestVersion,
const double maxReductionTimeStep,
const std::string& parameters,
const bool verbose);
/// \brief constructor
/// \param tolerance tolerance for the relative changes of the numerical solution to be
/// accepted in one time step
/// \param safetyFactor multiplied with tolerance to ensure that target relative change is
/// lower than tolerance
/// \param rejectCompletedStep if true, discard the recently completed time step and try again
/// \param toleranceTestVersion the test used to decide if a time step should be rejected
/// \param maxReductionTimeStep limits the reduction in time step size for control error filtering
/// \param parameters parameter values for the controller formula
/// \param verbose if true, get some output
General3rdOrderController(const double tolerance,
const double safetyFactor,
const bool rejectCompletedStep,
const std::string& toleranceTestVersion,
const double maxReductionTimeStep,
const std::string& parameters,
const bool verbose);
static General3rdOrderController serializationTestObject();
@@ -230,7 +253,8 @@ namespace Opm
double timeStepFactor(const std::array<double, 3>& errors, const std::array<double, 3>& timeSteps) const;
bool timeStepAccepted(const double error, const double timeStepJustCompleted) const override;
bool timeStepAccepted(const double error,
const double timeStepJustCompleted) const override;
template<class Serializer>
void serializeOp(Serializer& serializer)
@@ -278,6 +302,7 @@ namespace Opm
{
public:
static constexpr TimeStepControlType Type = TimeStepControlType::HardCodedTimeStep;
HardcodedTimeStepControl() = default;
/// \brief constructor
@@ -292,7 +317,8 @@ namespace Opm
const RelativeChangeInterface& /*relativeChange */,
const AdaptiveSimulatorTimer& substepTimer) const override;
bool timeStepAccepted(const double /* error */, const double /* timeStepJustCompleted */) const override { return true; }
bool timeStepAccepted(const double /* error */,
const double /* timeStepJustCompleted */) const override { return true; }
template<class Serializer>
void serializeOp(Serializer& serializer)