From 6e9bb4cf0bbf5cc617b4b599dcf32b6fb94e5b0f Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Thu, 15 Sep 2016 12:21:59 +0200 Subject: [PATCH 1/3] Timestepper based on userInput A new timestepper that reads timesteps from a file generated using ecl_summary "DECK" TIME and applies it to the simulator Also a parameter timestep.initial_step_length (default 1 day) is added to controll the frist timestep. --- .../simulator/AdaptiveTimeStepping_impl.hpp | 8 +++- opm/core/simulator/TimeStepControl.cpp | 43 +++++++++++++++++-- opm/core/simulator/TimeStepControl.hpp | 27 ++++++++++-- .../simulator/TimeStepControlInterface.hpp | 2 +- 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/opm/core/simulator/AdaptiveTimeStepping_impl.hpp b/opm/core/simulator/AdaptiveTimeStepping_impl.hpp index 56a11dec..0ac481ac 100644 --- a/opm/core/simulator/AdaptiveTimeStepping_impl.hpp +++ b/opm/core/simulator/AdaptiveTimeStepping_impl.hpp @@ -72,7 +72,7 @@ namespace Opm { , solver_restart_max_( param.getDefault("solver.restart", int(10) ) ) , solver_verbose_( param.getDefault("solver.verbose", bool(true) ) && terminal_output ) , timestep_verbose_( param.getDefault("timestep.verbose", bool(true) ) && terminal_output ) - , suggested_next_timestep_( -1.0 ) + , suggested_next_timestep_( unit::convert::from(param.getDefault("timestep.initial_step_length", double(1.0) ), unit::day) ) , full_timestep_initially_( param.getDefault("full_timestep_initially", bool(false) ) ) { // valid are "pid" and "pid+iteration" @@ -95,6 +95,10 @@ namespace Opm { const double decayrate = param.getDefault("timestep.control.decayrate", double(0.75) ); const double growthrate = param.getDefault("timestep.control.growthrate", double(1.25) ); timeStepControl_ = TimeStepControlType( new SimpleIterationCountTimeStepControl( iterations, decayrate, growthrate ) ); + } else if ( control == "hardcoded") { + const std::string filename = param.getDefault("timestep.control.filename", std::string("timesteps")); + timeStepControl_ = TimeStepControlType( new HardcodedTimeStepControl( filename ) ); + } else OPM_THROW(std::runtime_error,"Unsupported time step control selected "<< control ); @@ -202,7 +206,7 @@ namespace Opm { // compute new time step estimate double dtEstimate = - timeStepControl_->computeTimeStepSize( dt, linearIterations, relativeChange ); + timeStepControl_->computeTimeStepSize( dt, linearIterations, relativeChange, substepTimer.simulationTimeElapsed()); // limit the growth of the timestep size by the growth factor dtEstimate = std::min( dtEstimate, double(max_growth_ * dt) ); diff --git a/opm/core/simulator/TimeStepControl.cpp b/opm/core/simulator/TimeStepControl.cpp index e7d11043..0c01b24e 100644 --- a/opm/core/simulator/TimeStepControl.cpp +++ b/opm/core/simulator/TimeStepControl.cpp @@ -23,6 +23,9 @@ #include #include #include +#include +#include +#include #include #include @@ -55,7 +58,7 @@ namespace Opm } double SimpleIterationCountTimeStepControl:: - computeTimeStepSize( const double dt, const int iterations, const RelativeChangeInterface& /* relativeChange */ ) const + computeTimeStepSize( const double dt, const int iterations, const RelativeChangeInterface& /* relativeChange */, const double /*simulationTimeElapsed */) const { double dtEstimate = dt ; @@ -74,6 +77,38 @@ namespace Opm return dtEstimate; } + //////////////////////////////////////////////////////// + // + // HardcodedTimeStepControl Implementation + // + //////////////////////////////////////////////////////// + + HardcodedTimeStepControl:: + HardcodedTimeStepControl( const std::string filename) + { + std::ifstream infile (filename); + double time; + std::string line; + std::getline(infile, line); //assumes two lines before the timing starts. + std::getline(infile, line); + + while (!infile.eof() ) { + infile >> time; // read the time in days + std::string line; + std::getline(infile, line); // skip the rest of the line + timesteps_.push_back( time * unit::day ); + } + + } + + double HardcodedTimeStepControl:: + computeTimeStepSize( const double /*dt */, const int /*iterations */, const RelativeChangeInterface& /* relativeChange */ , const double simulationTimeElapsed) const + { + auto nextTime = std::upper_bound(timesteps_.begin(), timesteps_.end(), simulationTimeElapsed); + double dtEstimate = (*nextTime - simulationTimeElapsed); + return dtEstimate; + } + //////////////////////////////////////////////////////// @@ -90,7 +125,7 @@ namespace Opm {} double PIDTimeStepControl:: - computeTimeStepSize( const double dt, const int /* iterations */, const RelativeChangeInterface& relChange ) const + computeTimeStepSize( const double dt, const int /* iterations */, const RelativeChangeInterface& relChange, const double /*simulationTimeElapsed */) const { // shift errors for( int i=0; i<2; ++i ) { @@ -141,9 +176,9 @@ namespace Opm {} double PIDAndIterationCountTimeStepControl:: - computeTimeStepSize( const double dt, const int iterations, const RelativeChangeInterface& relChange ) const + computeTimeStepSize( const double dt, const int iterations, const RelativeChangeInterface& relChange, const double simulationTimeElapsed ) const { - double dtEstimate = BaseType :: computeTimeStepSize( dt, iterations, relChange ); + double dtEstimate = BaseType :: computeTimeStepSize( dt, iterations, relChange, simulationTimeElapsed); // further reduce step size if to many iterations were used if( iterations > target_iterations_ ) diff --git a/opm/core/simulator/TimeStepControl.hpp b/opm/core/simulator/TimeStepControl.hpp index ec14ddbe..40f5db6e 100644 --- a/opm/core/simulator/TimeStepControl.hpp +++ b/opm/core/simulator/TimeStepControl.hpp @@ -48,7 +48,7 @@ namespace Opm const bool verbose = false); /// \brief \copydoc TimeStepControlInterface::computeTimeStepSize - double computeTimeStepSize( const double dt, const int iterations, const RelativeChangeInterface& /* relativeChange */ ) const; + double computeTimeStepSize( const double dt, const int iterations, const RelativeChangeInterface& /* relativeChange */, const double /*simulationTimeElapsed */ ) const; protected: const int target_iterations_; @@ -82,7 +82,7 @@ namespace Opm const bool verbose = false ); /// \brief \copydoc TimeStepControlInterface::computeTimeStepSize - double computeTimeStepSize( const double dt, const int /* iterations */, const RelativeChangeInterface& relativeChange ) const; + double computeTimeStepSize( const double dt, const int /* iterations */, const RelativeChangeInterface& relativeChange, const double /*simulationTimeElapsed */ ) const; protected: const double tol_; @@ -111,12 +111,33 @@ namespace Opm const bool verbose = false); /// \brief \copydoc TimeStepControlInterface::computeTimeStepSize - double computeTimeStepSize( const double dt, const int iterations, const RelativeChangeInterface& relativeChange ) const; + double computeTimeStepSize( const double dt, const int iterations, const RelativeChangeInterface& relativeChange, const double /*simulationTimeElapsed */ ) const; protected: const int target_iterations_; }; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// HardcodedTimeStepControl + /// Input generated from summary file using the ert application: + /// ecl_summary DECK TIME > filename + // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + class HardcodedTimeStepControl : public TimeStepControlInterface + { + public: + /// \brief constructor + /// \param filename filename contaning the timesteps + HardcodedTimeStepControl( const std::string filename); + + /// \brief \copydoc TimeStepControlInterface::computeTimeStepSize + double computeTimeStepSize( const double dt, const int /* iterations */, const RelativeChangeInterface& /*relativeChange */, const double simulationTimeElapsed) const; + + protected: + std::vector timesteps_; + }; + } // end namespace Opm #endif diff --git a/opm/core/simulator/TimeStepControlInterface.hpp b/opm/core/simulator/TimeStepControlInterface.hpp index 2aee5aeb..bdab5e3a 100644 --- a/opm/core/simulator/TimeStepControlInterface.hpp +++ b/opm/core/simulator/TimeStepControlInterface.hpp @@ -56,7 +56,7 @@ namespace Opm /// \param timeError object to compute || u^n+1 - u^n || / || u^n+1 || /// /// \return suggested time step size for the next step - virtual double computeTimeStepSize( const double dt, const int iterations, const RelativeChangeInterface& relativeChange ) const = 0; + virtual double computeTimeStepSize( const double dt, const int iterations, const RelativeChangeInterface& relativeChange , const double simulationTimeElapsed) const = 0; /// virtual destructor (empty) virtual ~TimeStepControlInterface () {} From f1bdd67438631a3f028adc5cd44aa3c6b1b27bca Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Fri, 16 Sep 2016 10:01:19 +0200 Subject: [PATCH 2/3] Small fixes hardcodedTimestepControl -- avoid using eof() -- add comments -- no longer assumes two lines of comments. -- revert change to default value for timestep.initial_step_length -- make contructer explicit -- pass reference --- .../simulator/AdaptiveTimeStepping_impl.hpp | 2 +- opm/core/simulator/TimeStepControl.cpp | 22 ++++++++----------- opm/core/simulator/TimeStepControl.hpp | 9 +++++--- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/opm/core/simulator/AdaptiveTimeStepping_impl.hpp b/opm/core/simulator/AdaptiveTimeStepping_impl.hpp index 0ac481ac..33d92d90 100644 --- a/opm/core/simulator/AdaptiveTimeStepping_impl.hpp +++ b/opm/core/simulator/AdaptiveTimeStepping_impl.hpp @@ -72,7 +72,7 @@ namespace Opm { , solver_restart_max_( param.getDefault("solver.restart", int(10) ) ) , solver_verbose_( param.getDefault("solver.verbose", bool(true) ) && terminal_output ) , timestep_verbose_( param.getDefault("timestep.verbose", bool(true) ) && terminal_output ) - , suggested_next_timestep_( unit::convert::from(param.getDefault("timestep.initial_step_length", double(1.0) ), unit::day) ) + , suggested_next_timestep_( -1.0 ) , full_timestep_initially_( param.getDefault("full_timestep_initially", bool(false) ) ) { // valid are "pid" and "pid+iteration" diff --git a/opm/core/simulator/TimeStepControl.cpp b/opm/core/simulator/TimeStepControl.cpp index 0c01b24e..91cb478c 100644 --- a/opm/core/simulator/TimeStepControl.cpp +++ b/opm/core/simulator/TimeStepControl.cpp @@ -84,29 +84,25 @@ namespace Opm //////////////////////////////////////////////////////// HardcodedTimeStepControl:: - HardcodedTimeStepControl( const std::string filename) + HardcodedTimeStepControl( const std::string& filename) { std::ifstream infile (filename); - double time; + std::string::size_type sz; std::string line; - std::getline(infile, line); //assumes two lines before the timing starts. - std::getline(infile, line); + while ( std::getline(infile, line)) { + if( line[0] != '-') { // ignore lines starting with '-' + const double time = std::stod(line,&sz); // read the first number i.e. the actual substep time + subStepTime_.push_back( time * unit::day ); + } - while (!infile.eof() ) { - infile >> time; // read the time in days - std::string line; - std::getline(infile, line); // skip the rest of the line - timesteps_.push_back( time * unit::day ); } - } double HardcodedTimeStepControl:: computeTimeStepSize( const double /*dt */, const int /*iterations */, const RelativeChangeInterface& /* relativeChange */ , const double simulationTimeElapsed) const { - auto nextTime = std::upper_bound(timesteps_.begin(), timesteps_.end(), simulationTimeElapsed); - double dtEstimate = (*nextTime - simulationTimeElapsed); - return dtEstimate; + auto nextTime = std::upper_bound(subStepTime_.begin(), subStepTime_.end(), simulationTimeElapsed); + return (*nextTime - simulationTimeElapsed); } diff --git a/opm/core/simulator/TimeStepControl.hpp b/opm/core/simulator/TimeStepControl.hpp index 40f5db6e..00a82d74 100644 --- a/opm/core/simulator/TimeStepControl.hpp +++ b/opm/core/simulator/TimeStepControl.hpp @@ -121,21 +121,24 @@ namespace Opm /// /// HardcodedTimeStepControl /// Input generated from summary file using the ert application: + /// /// ecl_summary DECK TIME > filename - // + /// + /// Assumes time is given in days /////////////////////////////////////////////////////////////////////////////////////////////////////////////// class HardcodedTimeStepControl : public TimeStepControlInterface { public: /// \brief constructor /// \param filename filename contaning the timesteps - HardcodedTimeStepControl( const std::string filename); + explicit HardcodedTimeStepControl( const std::string& filename); /// \brief \copydoc TimeStepControlInterface::computeTimeStepSize double computeTimeStepSize( const double dt, const int /* iterations */, const RelativeChangeInterface& /*relativeChange */, const double simulationTimeElapsed) const; protected: - std::vector timesteps_; + // store the time (in days) of the substeps the simulator should use + std::vector subStepTime_; }; From ff81d4855135a791cf9cd3e21702e96198824190 Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Wed, 21 Sep 2016 09:38:51 +0200 Subject: [PATCH 3/3] Guard against non-existing file --- opm/core/simulator/TimeStepControl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/opm/core/simulator/TimeStepControl.cpp b/opm/core/simulator/TimeStepControl.cpp index 91cb478c..a6787191 100644 --- a/opm/core/simulator/TimeStepControl.cpp +++ b/opm/core/simulator/TimeStepControl.cpp @@ -87,6 +87,9 @@ namespace Opm HardcodedTimeStepControl( const std::string& filename) { std::ifstream infile (filename); + if (!infile.is_open()) { + OPM_THROW(std::runtime_error,"Incorrect or no filename is provided to the hardcodedTimeStep. Use timestep.control.filename=your_file_name"); + } std::string::size_type sz; std::string line; while ( std::getline(infile, line)) {