diff --git a/opm/simulators/timestepping/AdaptiveTimeSteppingEbos.hpp b/opm/simulators/timestepping/AdaptiveTimeSteppingEbos.hpp index acb1707cf..929d8660d 100644 --- a/opm/simulators/timestepping/AdaptiveTimeSteppingEbos.hpp +++ b/opm/simulators/timestepping/AdaptiveTimeSteppingEbos.hpp @@ -286,6 +286,8 @@ namespace Opm { } public: + AdaptiveTimeSteppingEbos() = default; + //! \brief contructor taking parameter object AdaptiveTimeSteppingEbos(const UnitSystem& unitSystem, const bool terminalOutput = true) @@ -676,6 +678,140 @@ namespace Opm { timestepAfterEvent_ = tuning.TMAXWC; } + template + void serializeOp(Serializer& serializer) + { + serializer(timeStepControlType_); + switch (timeStepControlType_) { + case TimeStepControlType::HardCodedTimeStep: + allocAndSerialize(serializer); + break; + case TimeStepControlType::PIDAndIterationCount: + allocAndSerialize(serializer); + break; + case TimeStepControlType::SimpleIterationCount: + allocAndSerialize(serializer); + break; + case TimeStepControlType::PID: + allocAndSerialize(serializer); + break; + } + serializer(restartFactor_); + serializer(growthFactor_); + serializer(maxGrowth_); + serializer(maxTimeStep_); + serializer(minTimeStep_); + serializer(ignoreConvergenceFailure_); + serializer(solverRestartMax_); + serializer(solverVerbose_); + serializer(timestepVerbose_); + serializer(suggestedNextTimestep_); + serializer(fullTimestepInitially_); + serializer(timestepAfterEvent_); + serializer(useNewtonIteration_); + serializer(minTimeStepBeforeShuttingProblematicWells_); + } + + static AdaptiveTimeSteppingEbos serializationTestObjectHardcoded() + { + return serializationTestObject_(); + } + + static AdaptiveTimeSteppingEbos serializationTestObjectPID() + { + return serializationTestObject_(); + } + + static AdaptiveTimeSteppingEbos serializationTestObjectPIDIt() + { + return serializationTestObject_(); + } + + static AdaptiveTimeSteppingEbos serializationTestObjectSimple() + { + return serializationTestObject_(); + } + + bool operator==(const AdaptiveTimeSteppingEbos& rhs) + { + if (timeStepControlType_ != rhs.timeStepControlType_ || + (timeStepControl_ && !rhs.timeStepControl_) || + (!timeStepControl_ && rhs.timeStepControl_)) { + return false; + } + + bool result = false; + switch (timeStepControlType_) { + case TimeStepControlType::HardCodedTimeStep: + result = castAndComp(rhs); + break; + case TimeStepControlType::PIDAndIterationCount: + result = castAndComp(rhs); + break; + case TimeStepControlType::SimpleIterationCount: + result = castAndComp(rhs); + break; + case TimeStepControlType::PID: + result = castAndComp(rhs); + break; + } + + return result && + this->restartFactor_ == rhs.restartFactor_ && + this->growthFactor_ == rhs.growthFactor_ && + this->maxGrowth_ == rhs.maxGrowth_ && + this->maxTimeStep_ == rhs.maxTimeStep_ && + this->minTimeStep_ == rhs.minTimeStep_ && + this->ignoreConvergenceFailure_ == rhs.ignoreConvergenceFailure_ && + this->solverRestartMax_== rhs.solverRestartMax_ && + this->solverVerbose_ == rhs.solverVerbose_ && + this->fullTimestepInitially_ == rhs.fullTimestepInitially_ && + this->timestepAfterEvent_ == rhs.timestepAfterEvent_ && + this->useNewtonIteration_ == rhs.useNewtonIteration_ && + this->minTimeStepBeforeShuttingProblematicWells_ == + rhs.minTimeStepBeforeShuttingProblematicWells_; + } + + private: + template + static AdaptiveTimeSteppingEbos serializationTestObject_() + { + AdaptiveTimeSteppingEbos result; + + result.restartFactor_ = 1.0; + result.growthFactor_ = 2.0; + result.maxGrowth_ = 3.0; + result.maxTimeStep_ = 4.0; + result.minTimeStep_ = 5.0; + result.ignoreConvergenceFailure_ = true; + result.solverRestartMax_ = 6; + result.solverVerbose_ = true; + result.timestepVerbose_ = true; + result.suggestedNextTimestep_ = 7.0; + result.fullTimestepInitially_ = 8.0; + result.useNewtonIteration_ = true; + result.minTimeStepBeforeShuttingProblematicWells_ = 9.0; + result.timeStepControlType_ = Controller::Type; + result.timeStepControl_ = std::make_unique(Controller::serializationTestObject()); + + return result; + } + template + void allocAndSerialize(Serializer& serializer) + { + if (!serializer.isSerializing()) { + timeStepControl_ = std::make_unique(); + } + serializer(*static_cast(timeStepControl_.get())); + } + + template + bool castAndComp(const AdaptiveTimeSteppingEbos& Rhs) const + { + const T* lhs = static_cast(timeStepControl_.get()); + const T* rhs = static_cast(Rhs.timeStepControl_.get()); + return *lhs == *rhs; + } protected: void init_(const UnitSystem& unitSystem) @@ -685,13 +821,15 @@ namespace Opm { const double tol = EWOMS_GET_PARAM(TypeTag, double, TimeStepControlTolerance); // 1e-1 if (control == "pid") { - timeStepControl_ = TimeStepControlType(new PIDTimeStepControl(tol)); + timeStepControl_ = std::make_unique(tol); + timeStepControlType_ = TimeStepControlType::PID; } else if (control == "pid+iteration") { const int iterations = EWOMS_GET_PARAM(TypeTag, int, TimeStepControlTargetIterations); // 30 const double decayDampingFactor = EWOMS_GET_PARAM(TypeTag, double, TimeStepControlDecayDampingFactor); // 1.0 const double growthDampingFactor = EWOMS_GET_PARAM(TypeTag, double, TimeStepControlGrowthDampingFactor); // 3.2 - timeStepControl_ = TimeStepControlType(new PIDAndIterationCountTimeStepControl(iterations, decayDampingFactor, growthDampingFactor, tol)); + timeStepControl_ = std::make_unique(iterations, decayDampingFactor, growthDampingFactor, tol); + timeStepControlType_ = TimeStepControlType::PIDAndIterationCount; } else if (control == "pid+newtoniteration") { const int iterations = EWOMS_GET_PARAM(TypeTag, int, TimeStepControlTargetNewtonIterations); // 8 @@ -700,27 +838,30 @@ namespace Opm { const double nonDimensionalMinTimeStepIterations = EWOMS_GET_PARAM(TypeTag, double, MinTimeStepBasedOnNewtonIterations); // 0.0 by default // the min time step can be reduced by the newton iteration numbers double minTimeStepReducedByIterations = unitSystem.to_si(UnitSystem::measure::time, nonDimensionalMinTimeStepIterations); - timeStepControl_ = TimeStepControlType(new PIDAndIterationCountTimeStepControl(iterations, decayDampingFactor, - growthDampingFactor, tol, minTimeStepReducedByIterations)); + timeStepControl_ = std::make_unique(iterations, decayDampingFactor, + growthDampingFactor, tol, minTimeStepReducedByIterations); + timeStepControlType_ = TimeStepControlType::PIDAndIterationCount; useNewtonIteration_ = true; } else if (control == "iterationcount") { const int iterations = EWOMS_GET_PARAM(TypeTag, int, TimeStepControlTargetIterations); // 30 const double decayrate = EWOMS_GET_PARAM(TypeTag, double, TimeStepControlDecayRate); // 0.75 const double growthrate = EWOMS_GET_PARAM(TypeTag, double, TimeStepControlGrowthRate); // 1.25 - timeStepControl_ = TimeStepControlType(new SimpleIterationCountTimeStepControl(iterations, decayrate, growthrate)); + timeStepControl_ = std::make_unique(iterations, decayrate, growthrate); + timeStepControlType_ = TimeStepControlType::SimpleIterationCount; } else if (control == "newtoniterationcount") { const int iterations = EWOMS_GET_PARAM(TypeTag, int, TimeStepControlTargetNewtonIterations); // 8 const double decayrate = EWOMS_GET_PARAM(TypeTag, double, TimeStepControlDecayRate); // 0.75 const double growthrate = EWOMS_GET_PARAM(TypeTag, double, TimeStepControlGrowthRate); // 1.25 - timeStepControl_ = TimeStepControlType(new SimpleIterationCountTimeStepControl(iterations, decayrate, growthrate)); + timeStepControl_ = std::make_unique(iterations, decayrate, growthrate); useNewtonIteration_ = true; + timeStepControlType_ = TimeStepControlType::SimpleIterationCount; } else if (control == "hardcoded") { const std::string filename = EWOMS_GET_PARAM(TypeTag, std::string, TimeStepControlFileName); // "timesteps" - timeStepControl_ = TimeStepControlType(new HardcodedTimeStepControl(filename)); - + timeStepControl_ = std::make_unique(filename); + timeStepControlType_ = TimeStepControlType::HardCodedTimeStep; } else OPM_THROW(std::runtime_error, @@ -782,9 +923,10 @@ namespace Opm { return failing_wells; } - using TimeStepControlType = std::unique_ptr; + using TimeStepController = std::unique_ptr; - TimeStepControlType timeStepControl_; //!< time step control object + TimeStepControlType timeStepControlType_; //!< type of time step control object + TimeStepController timeStepControl_; //!< time step control object double restartFactor_; //!< factor to multiply time step with when solver fails to converge double growthFactor_; //!< factor to multiply time step when solver recovered from failed convergence double maxGrowth_; //!< factor that limits the maximum growth of a time step diff --git a/opm/simulators/timestepping/TimeStepControl.hpp b/opm/simulators/timestepping/TimeStepControl.hpp index 11c5fa574..78e9e82b5 100644 --- a/opm/simulators/timestepping/TimeStepControl.hpp +++ b/opm/simulators/timestepping/TimeStepControl.hpp @@ -21,12 +21,20 @@ #ifndef OPM_TIMESTEPCONTROL_HEADER_INCLUDED #define OPM_TIMESTEPCONTROL_HEADER_INCLUDED -#include - #include +#include +#include + namespace Opm { + enum class TimeStepControlType { + SimpleIterationCount, + PID, + PIDAndIterationCount, + HardCodedTimeStep + }; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// A simple iteration count based adaptive time step control. @@ -35,6 +43,7 @@ namespace Opm class SimpleIterationCountTimeStepControl : public TimeStepControlInterface { public: + static constexpr TimeStepControlType Type = TimeStepControlType::SimpleIterationCount; SimpleIterationCountTimeStepControl() = default; /// \brief constructor @@ -87,6 +96,7 @@ namespace Opm class PIDTimeStepControl : public TimeStepControlInterface { public: + static constexpr TimeStepControlType Type = TimeStepControlType::PID; /// \brief constructor /// \param tol tolerance for the relative changes of the numerical solution to be accepted /// in one time step (default is 1e-3) @@ -126,6 +136,8 @@ namespace Opm { typedef PIDTimeStepControl BaseType; public: + static constexpr TimeStepControlType Type = TimeStepControlType::PIDAndIterationCount; + /// \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 @@ -174,6 +186,7 @@ namespace Opm class HardcodedTimeStepControl : public TimeStepControlInterface { public: + static constexpr TimeStepControlType Type = TimeStepControlType::HardCodedTimeStep; HardcodedTimeStepControl() = default; /// \brief constructor diff --git a/tests/test_RestartSerialization.cpp b/tests/test_RestartSerialization.cpp index 3983000c6..f075d0fc0 100644 --- a/tests/test_RestartSerialization.cpp +++ b/tests/test_RestartSerialization.cpp @@ -19,8 +19,11 @@ #include +#include + #include +#include #include #include #include @@ -42,7 +45,7 @@ std::tuple PackUnpack(T& in) ser.unpack(out); size_t pos2 = ser.position(); - return std::make_tuple(out, pos1, pos2); + return std::make_tuple(std::move(out), pos1, pos2); } #define TEST_FOR_TYPE_NAMED_OBJ(TYPE, NAME, OBJ) \ @@ -66,6 +69,12 @@ TEST_FOR_TYPE(PIDTimeStepControl) TEST_FOR_TYPE(SimpleIterationCountTimeStepControl) TEST_FOR_TYPE(SimulatorTimer) +namespace Opm { using ATE = AdaptiveTimeSteppingEbos; } +TEST_FOR_TYPE_NAMED_OBJ(ATE, AdaptiveTimeSteppingEbosHardcoded, serializationTestObjectHardcoded) +TEST_FOR_TYPE_NAMED_OBJ(ATE, AdaptiveTimeSteppingEbosPID, serializationTestObjectPID) +TEST_FOR_TYPE_NAMED_OBJ(ATE, AdaptiveTimeSteppingEbosPIDIt, serializationTestObjectPIDIt) +TEST_FOR_TYPE_NAMED_OBJ(ATE, AdaptiveTimeSteppingEbosSimple, serializationTestObjectSimple) + bool init_unit_test_func() { return true;