Add class ScheduleTStep

This commit is contained in:
Joakim Hove
2021-01-06 19:08:00 +01:00
parent 22ac814056
commit aaacdd6c57
9 changed files with 278 additions and 18 deletions
+2
View File
@@ -127,6 +127,7 @@ if(ENABLE_ECL_INPUT)
src/opm/parser/eclipse/EclipseState/Schedule/RPTConfig.cpp src/opm/parser/eclipse/EclipseState/Schedule/RPTConfig.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp
src/opm/parser/eclipse/EclipseState/Schedule/ScheduleDeck.cpp src/opm/parser/eclipse/EclipseState/Schedule/ScheduleDeck.cpp
src/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.cpp
src/opm/parser/eclipse/EclipseState/Schedule/ScheduleTypes.cpp src/opm/parser/eclipse/EclipseState/Schedule/ScheduleTypes.cpp
src/opm/parser/eclipse/EclipseState/Schedule/SummaryState.cpp src/opm/parser/eclipse/EclipseState/Schedule/SummaryState.cpp
src/opm/parser/eclipse/EclipseState/Schedule/TimeMap.cpp src/opm/parser/eclipse/EclipseState/Schedule/TimeMap.cpp
@@ -743,6 +744,7 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/EclipseState/Schedule/RPTConfig.hpp opm/parser/eclipse/EclipseState/Schedule/RPTConfig.hpp
opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp
opm/parser/eclipse/EclipseState/Schedule/ScheduleDeck.hpp opm/parser/eclipse/EclipseState/Schedule/ScheduleDeck.hpp
opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp
opm/parser/eclipse/EclipseState/Schedule/ScheduleTypes.hpp opm/parser/eclipse/EclipseState/Schedule/ScheduleTypes.hpp
opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp
opm/parser/eclipse/EclipseState/Schedule/Group/GPMaint.hpp opm/parser/eclipse/EclipseState/Schedule/Group/GPMaint.hpp
@@ -51,6 +51,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellMatcher.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Well/WellMatcher.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Action/Actions.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Action/Actions.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleDeck.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/ScheduleDeck.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp>
#include <opm/common/utility/ActiveGridCells.hpp> #include <opm/common/utility/ActiveGridCells.hpp>
#include <opm/io/eclipse/rst/state.hpp> #include <opm/io/eclipse/rst/state.hpp>
@@ -293,6 +294,13 @@ namespace Opm
bool operator==(const Schedule& data) const; bool operator==(const Schedule& data) const;
std::shared_ptr<const Python> python() const; std::shared_ptr<const Python> python() const;
const ScheduleState& operator[](std::size_t index) const;
std::vector<ScheduleState>::const_iterator begin() const;
std::vector<ScheduleState>::const_iterator end() const;
ScheduleState& create_next(const ScheduleBlock& block);
/* /*
The cmp() function compares two schedule instances in a context aware The cmp() function compares two schedule instances in a context aware
manner. Floating point numbers are compared with a tolerance. The manner. Floating point numbers are compared with a tolerance. The
@@ -335,7 +343,6 @@ namespace Opm
m_actions.serializeOp(serializer); m_actions.serializeOp(serializer);
m_network.serializeOp(serializer); m_network.serializeOp(serializer);
m_glo.serializeOp(serializer); m_glo.serializeOp(serializer);
m_pavg.serializeOp(serializer);
rft_config.serializeOp(serializer); rft_config.serializeOp(serializer);
m_nupcol.template serializeOp<Serializer, false>(serializer); m_nupcol.template serializeOp<Serializer, false>(serializer);
restart_config.serializeOp(serializer); restart_config.serializeOp(serializer);
@@ -347,6 +354,7 @@ namespace Opm
reconstructDynMap<Map2>(splitvfpinj.first, splitvfpinj.second, vfpinj_tables); reconstructDynMap<Map2>(splitvfpinj.first, splitvfpinj.second, vfpinj_tables);
} }
unit_system.serializeOp(serializer); unit_system.serializeOp(serializer);
serializer.vector(snapshots);
} }
private: private:
@@ -375,14 +383,16 @@ namespace Opm
DynamicState<std::shared_ptr<Action::Actions>> m_actions; DynamicState<std::shared_ptr<Action::Actions>> m_actions;
DynamicState<std::shared_ptr<Network::ExtNetwork>> m_network; DynamicState<std::shared_ptr<Network::ExtNetwork>> m_network;
DynamicState<std::shared_ptr<GasLiftOpt>> m_glo; DynamicState<std::shared_ptr<GasLiftOpt>> m_glo;
DynamicState<std::shared_ptr<PAvg>> m_pavg;
RFTConfig rft_config; RFTConfig rft_config;
DynamicState<int> m_nupcol; DynamicState<int> m_nupcol;
RestartConfig restart_config; RestartConfig restart_config;
UnitSystem unit_system; UnitSystem unit_system;
std::optional<int> exit_status; std::optional<int> exit_status;
std::map<std::string,Events> wellgroup_events; std::map<std::string,Events> wellgroup_events;
DynamicState<std::shared_ptr<RPTConfig>> rpt_config;
std::vector<ScheduleState> snapshots;
void load_rst(const RestartIO::RstState& rst, void load_rst(const RestartIO::RstState& rst,
const EclipseGrid& grid, const EclipseGrid& grid,
const FieldPropsManager& fp); const FieldPropsManager& fp);
@@ -402,7 +412,6 @@ namespace Opm
Connection::Order wellConnectionOrder); Connection::Order wellConnectionOrder);
bool updateWPAVE(const std::string& wname, std::size_t report_step, const PAvg& pavg); bool updateWPAVE(const std::string& wname, std::size_t report_step, const PAvg& pavg);
DynamicState<std::shared_ptr<RPTConfig>> rpt_config;
void updateNetwork(std::shared_ptr<Network::ExtNetwork> network, std::size_t report_step); void updateNetwork(std::shared_ptr<Network::ExtNetwork> network, std::size_t report_step);
void updateGuideRateModel(const GuideRateModel& new_model, std::size_t report_step); void updateGuideRateModel(const GuideRateModel& new_model, std::size_t report_step);
@@ -54,7 +54,7 @@ namespace Opm {
void push_back(const DeckKeyword& keyword); void push_back(const DeckKeyword& keyword);
std::optional<DeckKeyword> get(const std::string& kw) const; std::optional<DeckKeyword> get(const std::string& kw) const;
const std::chrono::system_clock::time_point& start_time() const; const std::chrono::system_clock::time_point& start_time() const;
const std::chrono::system_clock::time_point& end_time() const; const std::optional<std::chrono::system_clock::time_point>& end_time() const;
void end_time(const std::chrono::system_clock::time_point& t); void end_time(const std::chrono::system_clock::time_point& t);
ScheduleTimeType time_type() const; ScheduleTimeType time_type() const;
const KeywordLocation& location() const; const KeywordLocation& location() const;
@@ -0,0 +1,74 @@
/*
Copyright 2021 Equinor ASA.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SCHEDULE_TSTEP_HPP
#define SCHEDULE_TSTEP_HPP
#include <chrono>
#include <memory>
#include <optional>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.hpp>
namespace Opm {
/*
The purpose of the ScheduleState class is to hold the entire Schedule
information, i.e. wells and groups and so on, at exactly one point in
time. The ScheduleState class itself has no dynamic behavior, the dynamics
is handled by the Schedule instance owning the ScheduleState instance.
*/
class ScheduleState {
public:
ScheduleState() = default;
explicit ScheduleState(const std::chrono::system_clock::time_point& start_time);
ScheduleState(const std::chrono::system_clock::time_point& start_time, const std::chrono::system_clock::time_point& end_time);
ScheduleState(const ScheduleState& src, const std::chrono::system_clock::time_point& start_time);
ScheduleState(const ScheduleState& src, const std::chrono::system_clock::time_point& start_time, const std::chrono::system_clock::time_point& end_time);
std::chrono::system_clock::time_point start_time() const;
std::chrono::system_clock::time_point end_time() const;
ScheduleState next(const std::chrono::system_clock::time_point& next_start);
bool operator==(const ScheduleState& other) const;
static ScheduleState serializeObject();
void pavg(PAvg pavg);
const PAvg& pavg() const;
template<class Serializer>
void serializeOp(Serializer& serializer) {
serializer(m_start_time);
serializer(m_end_time);
serializer(m_pavg);
}
private:
std::chrono::system_clock::time_point m_start_time;
std::optional<std::chrono::system_clock::time_point> m_end_time;
std::shared_ptr<PAvg> m_pavg;
};
}
#endif
@@ -1821,11 +1821,12 @@ namespace {
} }
void Schedule::handleWPAVE(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { void Schedule::handleWPAVE(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) {
auto wpave = std::make_shared<PAvg>( handlerContext.keyword.getRecord(0) ); auto wpave = PAvg( handlerContext.keyword.getRecord(0) );
for (const auto& wname : this->wellNames(handlerContext.currentStep)) for (const auto& wname : this->wellNames(handlerContext.currentStep))
this->updateWPAVE(wname, handlerContext.currentStep, *wpave ); this->updateWPAVE(wname, handlerContext.currentStep, wpave );
this->m_pavg.update( handlerContext.currentStep, std::move(wpave) ); auto& sched_state = this->snapshots.back();
sched_state.pavg(std::move(wpave));
} }
void Schedule::handleWWPAVE(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) { void Schedule::handleWWPAVE(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
@@ -128,7 +128,6 @@ namespace {
m_actions(this->m_timeMap, std::make_shared<Action::Actions>()), m_actions(this->m_timeMap, std::make_shared<Action::Actions>()),
m_network(this->m_timeMap, std::make_shared<Network::ExtNetwork>()), m_network(this->m_timeMap, std::make_shared<Network::ExtNetwork>()),
m_glo(this->m_timeMap, std::make_shared<GasLiftOpt>()), m_glo(this->m_timeMap, std::make_shared<GasLiftOpt>()),
m_pavg(this->m_timeMap, std::make_shared<PAvg>()),
rft_config(this->m_timeMap), rft_config(this->m_timeMap),
m_nupcol(this->m_timeMap, runspec.nupcol()), m_nupcol(this->m_timeMap, runspec.nupcol()),
restart_config(m_timeMap, deck, parseContext, errors), restart_config(m_timeMap, deck, parseContext, errors),
@@ -154,6 +153,33 @@ namespace {
} }
this->iterateScheduleSection( python, deck.getInputPath(), parseContext, errors, grid, fp); this->iterateScheduleSection( python, deck.getInputPath(), parseContext, errors, grid, fp);
/*
This is temporary "integration test" for the time arguments in the
Schedule class.
*/
if (this->size() > 0) {
for (std::size_t report_step = 0; report_step < this->size() - 1; report_step++) {
const auto& this_block = this->m_sched_deck[report_step];
if (this_block.start_time() != std::chrono::system_clock::from_time_t(this->m_timeMap[report_step])) {
auto msg = fmt::format("Block: Bug in start_time for report_step: {} ", report_step);
throw std::logic_error(msg);
}
const auto& next_block = this->m_sched_deck[report_step + 1];
if (this_block.end_time() != next_block.start_time())
throw std::logic_error("Block: Internal bug in sched_block start / end inconsistent");
const auto& this_step = this->operator[](report_step);
if (this_step.start_time() != std::chrono::system_clock::from_time_t(this->m_timeMap[report_step])) {
auto msg = fmt::format("Bug in start_time for report_step: {} ", report_step);
throw std::logic_error(msg);
}
const auto& next_step = this->operator[](report_step + 1);
if (this_step.end_time() != next_step.start_time())
throw std::logic_error("Internal bug in sched_step start / end inconsistent");
}
}
} }
catch (const OpmInputError& opm_error) { catch (const OpmInputError& opm_error) {
throw; throw;
@@ -264,6 +290,7 @@ namespace {
result.restart_config = RestartConfig::serializeObject(); result.restart_config = RestartConfig::serializeObject();
result.wellgroup_events = {{"test", Events::serializeObject()}}; result.wellgroup_events = {{"test", Events::serializeObject()}};
result.unit_system = UnitSystem::newFIELD(); result.unit_system = UnitSystem::newFIELD();
result.snapshots = { ScheduleState::serializeObject() };
return result; return result;
} }
@@ -360,7 +387,7 @@ private:
std::vector<std::pair< const DeckKeyword* , std::size_t> > rftProperties; std::vector<std::pair< const DeckKeyword* , std::size_t> > rftProperties;
std::string time_unit = this->unit_system.name(UnitSystem::measure::time); std::string time_unit = this->unit_system.name(UnitSystem::measure::time);
auto convert_time = [this](double seconds) { return this->unit_system.from_si(UnitSystem::measure::time, seconds); }; auto deck_time = [this](double seconds) { return this->unit_system.from_si(UnitSystem::measure::time, seconds); };
std::string current_file; std::string current_file;
const auto& time_map = this->m_timeMap; const auto& time_map = this->m_timeMap;
/* /*
@@ -400,7 +427,7 @@ private:
currentStep + 1, currentStep + 1,
this->size(), this->size(),
Schedule::formatDate(this->getStartTime()), Schedule::formatDate(this->getStartTime()),
convert_time(time_map.getTimePassedUntil(currentStep)), deck_time(time_map.getTimePassedUntil(currentStep)),
time_unit, time_unit,
location.lineno)); location.lineno));
} }
@@ -410,8 +437,8 @@ private:
auto time_type = block.time_type(); auto time_type = block.time_type();
if (time_type == ScheduleTimeType::DATES || time_type == ScheduleTimeType::TSTEP) { if (time_type == ScheduleTimeType::DATES || time_type == ScheduleTimeType::TSTEP) {
const auto& start_date = Schedule::formatDate(std::chrono::system_clock::to_time_t(block.start_time())); const auto& start_date = Schedule::formatDate(std::chrono::system_clock::to_time_t(block.start_time()));
const auto& days = convert_time(this->stepLength(currentStep - 1)); const auto& days = deck_time(this->stepLength(currentStep - 1));
const auto& days_total = convert_time(time_map.getTimePassedUntil(currentStep)); const auto& days_total = deck_time(time_map.getTimePassedUntil(currentStep));
logger.complete_step(fmt::format("Complete report step {0} ({1} {2}) at {3} ({4} {2})", logger.complete_step(fmt::format("Complete report step {0} ({1} {2}) at {3} ({4} {2})",
currentStep, currentStep,
days, days,
@@ -427,7 +454,7 @@ private:
time_unit, time_unit,
block.location().lineno)); block.location().lineno));
} }
this->create_next(block);
while (true) { while (true) {
if (keyword_index == block.size()) if (keyword_index == block.size())
@@ -477,6 +504,7 @@ private:
rftProperties); rftProperties);
keyword_index++; keyword_index++;
} }
checkIfAllConnectionsIsShut(currentStep); checkIfAllConnectionsIsShut(currentStep);
currentStep += 1; currentStep += 1;
} }
@@ -902,8 +930,8 @@ private:
this->addWell( std::move(well), timeStep ); this->addWell( std::move(well), timeStep );
const auto& pavg_ptr = this->m_pavg.get(timeStep); const auto& ts = this->operator[](timeStep);
this->updateWPAVE( wellName, timeStep, *pavg_ptr ); this->updateWPAVE( wellName, timeStep, ts.pavg() );
} }
@@ -2032,5 +2060,35 @@ bool Schedule::cmp(const Schedule& sched1, const Schedule& sched2, std::size_t r
return (count == 0); return (count == 0);
} }
const ScheduleState& Schedule::operator[](std::size_t index) const {
return this->snapshots.at(index);
}
std::vector<ScheduleState>::const_iterator Schedule::begin() const {
return this->snapshots.begin();
}
std::vector<ScheduleState>::const_iterator Schedule::end() const {
return this->snapshots.end();
}
ScheduleState& Schedule::create_next(const ScheduleBlock& block) {
const auto& start_time = block.start_time();
const auto& end_time = block.end_time();
if (this->snapshots.empty()) {
if (end_time.has_value())
this->snapshots.emplace_back( start_time, end_time.value() );
else
this->snapshots.emplace_back(start_time);
} else {
const auto& last = this->snapshots.back();
if (end_time.has_value())
this->snapshots.emplace_back( last, start_time, end_time.value() );
else
this->snapshots.emplace_back( last, start_time );
}
return this->snapshots.back();
}
} }
@@ -61,8 +61,8 @@ const std::chrono::system_clock::time_point& ScheduleBlock::start_time() const {
return this->m_start_time; return this->m_start_time;
} }
const std::chrono::system_clock::time_point& ScheduleBlock::end_time() const { const std::optional<std::chrono::system_clock::time_point>& ScheduleBlock::end_time() const {
return this->m_end_time.value(); return this->m_end_time;
} }
ScheduleTimeType ScheduleBlock::time_type() const { ScheduleTimeType ScheduleBlock::time_type() const {
@@ -0,0 +1,80 @@
/*
Copyright 2021 Equinor ASA.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp>
namespace Opm {
ScheduleState::ScheduleState(const std::chrono::system_clock::time_point& t1):
m_start_time(t1),
m_pavg( std::make_shared<PAvg>())
{
}
ScheduleState::ScheduleState(const std::chrono::system_clock::time_point& start_time, const std::chrono::system_clock::time_point& end_time) :
ScheduleState(start_time)
{
this->m_end_time = end_time;
}
ScheduleState::ScheduleState(const ScheduleState& src, const std::chrono::system_clock::time_point& start_time) :
ScheduleState(src)
{
this->m_start_time = start_time;
this->m_end_time = std::nullopt;
}
ScheduleState::ScheduleState(const ScheduleState& src, const std::chrono::system_clock::time_point& start_time, const std::chrono::system_clock::time_point& end_time) :
ScheduleState(src)
{
this->m_start_time = start_time;
this->m_end_time = end_time;
}
std::chrono::system_clock::time_point ScheduleState::start_time() const {
return this->m_start_time;
}
std::chrono::system_clock::time_point ScheduleState::end_time() const {
return this->m_end_time.value();
}
void ScheduleState::pavg(PAvg arg) {
this->m_pavg = std::make_shared<PAvg>( std::move(arg) );
}
const PAvg& ScheduleState::pavg() const {
return *this->m_pavg;
}
bool ScheduleState::operator==(const ScheduleState& other) const {
return this->m_start_time == other.m_start_time &&
this->m_end_time == other.m_end_time;
}
ScheduleState ScheduleState::serializeObject() {
auto t1 = std::chrono::system_clock::now();
auto t2 = t1 + std::chrono::hours(48);
ScheduleState ts(t1, t2);
return ts;
}
}
+36
View File
@@ -4489,6 +4489,42 @@ std::string dates_msg(const std::chrono::system_clock::time_point& t, std::array
} }
BOOST_AUTO_TEST_CASE(ScheduleStateDatesTest) {
const auto& sched = make_schedule(createDeckWTEST());
BOOST_CHECK_EQUAL(sched.size(), 6);
BOOST_CHECK( compare_dates(sched[0].start_time(), 2007, 5, 10 ));
BOOST_CHECK( compare_dates(sched[0].end_time(), 2007, 6, 10 ));
BOOST_CHECK( compare_dates(sched[1].start_time(), 2007, 6, 10));
BOOST_CHECK( compare_dates(sched[1].end_time(), 2007, 7, 10 ));
BOOST_CHECK( compare_dates(sched[2].start_time(), 2007, 7, 10));
BOOST_CHECK( compare_dates(sched[2].end_time(), 2007, 8, 10 ));
BOOST_CHECK( compare_dates(sched[3].start_time(), 2007, 8, 10));
BOOST_CHECK( compare_dates(sched[3].end_time(), 2007, 9, 10 ));
BOOST_CHECK( compare_dates(sched[4].start_time(), 2007, 9, 10));
BOOST_CHECK( compare_dates(sched[4].end_time(), 2007, 11, 10 ));
BOOST_CHECK( compare_dates(sched[5].start_time(), 2007, 11, 10));
BOOST_CHECK_THROW( sched[5].end_time(), std::exception );
}
BOOST_AUTO_TEST_CASE(ScheduleStateTest) {
auto t1 = std::chrono::system_clock::now();
auto t2 = t1 + std::chrono::hours(48);
ScheduleState ts1(t1);
BOOST_CHECK( t1 == ts1.start_time() );
BOOST_CHECK_THROW( ts1.end_time(), std::exception );
ScheduleState ts2(t1, t2);
BOOST_CHECK( t1 == ts2.start_time() );
BOOST_CHECK( t2 == ts2.end_time() );
}
BOOST_AUTO_TEST_CASE(ScheduleDeckTest) { BOOST_AUTO_TEST_CASE(ScheduleDeckTest) {
{ {
ScheduleDeck sched_deck; ScheduleDeck sched_deck;