Pass restart info to TimeMap constructor
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
@@ -38,7 +39,7 @@ namespace Opm {
|
||||
class TimeMap {
|
||||
public:
|
||||
TimeMap() = default;
|
||||
explicit TimeMap(const Deck& deck);
|
||||
explicit TimeMap(const Deck& deck, const std::pair<std::time_t, std::size_t>& restart = std::make_pair(std::time_t{0}, std::size_t{0}));
|
||||
explicit TimeMap(const std::vector<std::time_t>& time_points);
|
||||
|
||||
size_t size() const;
|
||||
@@ -83,17 +84,17 @@ namespace Opm {
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::time_t> m_timeList;
|
||||
|
||||
bool isTimestepInFreqSequence (size_t timestep, size_t start_timestep, size_t frequency, bool years) const;
|
||||
size_t closest(const std::vector<size_t> & vec, size_t value) const;
|
||||
void addTStep(int64_t step);
|
||||
void addTime(std::time_t newTime);
|
||||
void addFromDATESKeyword( const DeckKeyword& DATESKeyword );
|
||||
void addFromTSTEPKeyword( const DeckKeyword& TSTEPKeyword );
|
||||
void init_start(std::time_t start_time);
|
||||
|
||||
std::vector<std::time_t> m_timeList;
|
||||
std::vector<StepData> m_first_timestep_years; // A list of the first timestep of every year
|
||||
std::vector<StepData> m_first_timestep_months; // A list of the first timestep of every month
|
||||
std::size_t restart_offset = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -22,12 +22,17 @@
|
||||
|
||||
#include <opm/common/utility/TimeService.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/S.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp>
|
||||
|
||||
|
||||
constexpr const std::time_t invalid_time = -1;
|
||||
|
||||
namespace Opm {
|
||||
|
||||
namespace {
|
||||
@@ -49,52 +54,108 @@ namespace {
|
||||
{"DES", 12}};
|
||||
}
|
||||
|
||||
void TimeMap::init_start(std::time_t start_time) {
|
||||
auto timestamp = TimeStampUTC{start_time};
|
||||
|
||||
this->m_timeList.push_back(start_time);
|
||||
this->m_first_timestep_months.push_back({0, timestamp});
|
||||
this->m_first_timestep_years.push_back({0, timestamp});
|
||||
}
|
||||
|
||||
|
||||
TimeMap::TimeMap(const std::vector<std::time_t>& time_points) {
|
||||
if (time_points.empty())
|
||||
throw std::invalid_argument("Can not initialize with empty list of time points");
|
||||
|
||||
this->m_timeList.push_back(time_points[0]);
|
||||
m_first_timestep_months.push_back({0, TimeStampUTC{time_points[0]}});
|
||||
m_first_timestep_years.push_back({0, TimeStampUTC{time_points[0]}});
|
||||
for (std::size_t ti = 1; ti < time_points.size(); ti++)
|
||||
this->addTime( time_points[ti] );
|
||||
this->init_start(time_points[0]);
|
||||
for (std::size_t ti = 1; ti < time_points.size(); ti++) {
|
||||
if (time_points[ti] == invalid_time) {
|
||||
this->m_timeList.push_back(invalid_time);
|
||||
this->restart_offset += 1;
|
||||
}
|
||||
else
|
||||
this->addTime( time_points[ti] );
|
||||
}
|
||||
if (this->restart_offset > 0)
|
||||
this->restart_offset += 1;
|
||||
}
|
||||
|
||||
TimeMap::TimeMap( const Deck& deck) {
|
||||
|
||||
std::time_t time;
|
||||
if (deck.hasKeyword("START")) {
|
||||
// Use the 'START' keyword to find out the start date (if the
|
||||
// keyword was specified)
|
||||
const auto& keyword = deck.getKeyword("START");
|
||||
time = timeFromEclipse(keyword.getRecord(0));
|
||||
} else {
|
||||
// The default start date is not specified in the Eclipse
|
||||
// reference manual. We hence just assume it is same as for
|
||||
// the START keyword for Eclipse R100, i.e., January 1st,
|
||||
// 1983...
|
||||
time = mkdate(1983, 1, 1);
|
||||
TimeMap::TimeMap( const Deck& deck, const std::pair<std::time_t, std::size_t>& restart) {
|
||||
bool skiprest = deck.hasKeyword<ParserKeywords::SKIPREST>();
|
||||
{
|
||||
std::time_t start_time;
|
||||
if (deck.hasKeyword("START")) {
|
||||
// Use the 'START' keyword to find out the start date (if the
|
||||
// keyword was specified)
|
||||
const auto& keyword = deck.getKeyword("START");
|
||||
start_time = timeFromEclipse(keyword.getRecord(0));
|
||||
} else {
|
||||
// The default start date is not specified in the Eclipse
|
||||
// reference manual. We hence just assume it is same as for
|
||||
// the START keyword for Eclipse R100, i.e., January 1st,
|
||||
// 1983...
|
||||
start_time = mkdate(1983, 1, 1);
|
||||
}
|
||||
this->init_start(start_time);
|
||||
}
|
||||
|
||||
auto restart_time = restart.first;
|
||||
this->restart_offset = restart.second;
|
||||
bool skip = false;
|
||||
|
||||
for (std::size_t it = 1; it < this->restart_offset; it++)
|
||||
this->m_timeList.push_back(invalid_time);
|
||||
|
||||
if (this->restart_offset > 0) {
|
||||
if (skiprest)
|
||||
skip = true;
|
||||
else {
|
||||
this->m_timeList.push_back(restart_time);
|
||||
skip = false;
|
||||
}
|
||||
}
|
||||
m_timeList.push_back(time);
|
||||
auto timestamp = TimeStampUTC{time};
|
||||
m_first_timestep_months.push_back({0, timestamp});
|
||||
m_first_timestep_years.push_back({0, timestamp});
|
||||
|
||||
// find all "TSTEP" and "DATES" keywords in the deck and deal
|
||||
// with them one after another
|
||||
for( const auto& keyword : deck ) {
|
||||
// We're only interested in "TSTEP" and "DATES" keywords,
|
||||
// so we ignore everything else here...
|
||||
if (keyword.name() != "TSTEP" &&
|
||||
keyword.name() != "DATES")
|
||||
{
|
||||
if (keyword.name() != "TSTEP" && keyword.name() != "DATES")
|
||||
continue;
|
||||
|
||||
if (keyword.name() == "DATES") {
|
||||
for (size_t recordIndex = 0; recordIndex < keyword.size(); recordIndex++) {
|
||||
const auto &record = keyword.getRecord(recordIndex);
|
||||
const std::time_t nextTime = TimeMap::timeFromEclipse(record);
|
||||
if (nextTime == restart_time)
|
||||
skip = false;
|
||||
|
||||
if (!skip)
|
||||
addTime(nextTime);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keyword.name() == "TSTEP")
|
||||
addFromTSTEPKeyword(keyword);
|
||||
else if (keyword.name() == "DATES")
|
||||
addFromDATESKeyword(keyword);
|
||||
if (skip)
|
||||
continue;
|
||||
|
||||
addFromTSTEPKeyword(keyword);
|
||||
}
|
||||
|
||||
/*
|
||||
There is a coupling between the presence of the SKIPREST keyword and
|
||||
the restart argument: The restart argument indicates whether this is
|
||||
deck should be parsed as restarted deck. If restart_offset == 0 we do
|
||||
not interpret this as restart situation and the presence of SKIPREST
|
||||
is ignored. In the opposite case we verify - post loading - that we
|
||||
have actually located the restart date - otherwise "something is
|
||||
broken".
|
||||
*/
|
||||
if (this->restart_offset != 0) {
|
||||
if (skiprest) {
|
||||
const auto iter = std::find(this->m_timeList.begin(), this->m_timeList.end(), restart_time);
|
||||
if (iter == this->m_timeList.end())
|
||||
throw std::invalid_argument("Could not find restart date");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +166,7 @@ namespace {
|
||||
|
||||
|
||||
std::time_t TimeMap::getStartTime(size_t tStepIdx) const {
|
||||
return this->operator[]( tStepIdx );
|
||||
return this->operator[](tStepIdx);
|
||||
}
|
||||
|
||||
std::time_t TimeMap::getEndTime() const {
|
||||
@@ -189,16 +250,6 @@ namespace {
|
||||
return date;
|
||||
}
|
||||
|
||||
void TimeMap::addFromDATESKeyword(const DeckKeyword &DATESKeyword) {
|
||||
if (DATESKeyword.name() != "DATES")
|
||||
throw std::invalid_argument("Method requires DATES keyword input.");
|
||||
|
||||
for (size_t recordIndex = 0; recordIndex < DATESKeyword.size(); recordIndex++) {
|
||||
const auto &record = DATESKeyword.getRecord(recordIndex);
|
||||
const std::time_t nextTime = TimeMap::timeFromEclipse(record);
|
||||
addTime(nextTime);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeMap::addFromTSTEPKeyword(const DeckKeyword &TSTEPKeyword) {
|
||||
if (TSTEPKeyword.name() != "TSTEP")
|
||||
@@ -239,7 +290,8 @@ namespace {
|
||||
{
|
||||
return this->m_timeList == data.m_timeList &&
|
||||
this->m_first_timestep_months == data.m_first_timestep_months &&
|
||||
this->m_first_timestep_years == data.m_first_timestep_years;
|
||||
this->m_first_timestep_years == data.m_first_timestep_years &&
|
||||
this->restart_offset == data.restart_offset;
|
||||
}
|
||||
|
||||
bool TimeMap::isTimestepInFirstOfMonthsYearsSequence(size_t timestep, bool years, size_t start_timestep, size_t frequency) const {
|
||||
@@ -329,12 +381,14 @@ namespace {
|
||||
|
||||
|
||||
std::time_t TimeMap::operator[] (size_t index) const {
|
||||
if (index < m_timeList.size()) {
|
||||
return m_timeList[index];
|
||||
} else
|
||||
if (index >= m_timeList.size())
|
||||
throw std::invalid_argument("Index out of range");
|
||||
}
|
||||
|
||||
if (index > 0 && index < this->restart_offset)
|
||||
throw std::invalid_argument("Tried to get time information from the base case in restarted run");
|
||||
|
||||
return m_timeList[index];
|
||||
}
|
||||
|
||||
std::time_t TimeMap::mkdate(int in_year, int in_month, int in_day) {
|
||||
return mkdatetime(in_year , in_month , in_day, 0,0,0);
|
||||
|
||||
@@ -594,3 +594,108 @@ BOOST_AUTO_TEST_CASE(TimeServiceOperatorPlus) {
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(RESTART) {
|
||||
std::string deck_string1 = R"(
|
||||
START
|
||||
1 JAN 2000 /
|
||||
|
||||
RESTART
|
||||
'CASE' 5 /
|
||||
|
||||
SCHEDULE
|
||||
|
||||
SKIPREST
|
||||
|
||||
DATES
|
||||
1 JAN 2001 /
|
||||
1 JAN 2002 /
|
||||
1 JAN 2003 /
|
||||
1 JAN 2004 /
|
||||
/
|
||||
|
||||
DATES
|
||||
1 JAN 2005 /
|
||||
/
|
||||
|
||||
DATES
|
||||
1 JAN 2006 /
|
||||
1 JAN 2007 /
|
||||
1 JAN 2008 /
|
||||
1 JAN 2009 /
|
||||
1 JAN 2010 /
|
||||
/
|
||||
)";
|
||||
|
||||
std::string deck_string2 = R"(
|
||||
START
|
||||
1 JAN 2000 /
|
||||
|
||||
RESTART
|
||||
'CASE' 5 /
|
||||
|
||||
SCHEDULE
|
||||
|
||||
-- The period before the restart dates has been removed - the restart date
|
||||
-- should still be picked up as report step 5.
|
||||
--DATES
|
||||
-- 1 JAN 2001 /
|
||||
-- 1 JAN 2002 /
|
||||
-- 1 JAN 2003 /
|
||||
-- 1 JAN 2004 /
|
||||
--/
|
||||
|
||||
DATES
|
||||
1 JUL 2005 /
|
||||
/
|
||||
|
||||
DATES
|
||||
1 JAN 2006 /
|
||||
1 JAN 2007 /
|
||||
1 JAN 2008 /
|
||||
1 JAN 2009 /
|
||||
1 JAN 2010 /
|
||||
/
|
||||
)";
|
||||
|
||||
std::string deck_string3 = R"(
|
||||
START
|
||||
1 JAN 2000 /
|
||||
|
||||
RESTART
|
||||
'CASE' 5 /
|
||||
|
||||
SCHEDULE
|
||||
|
||||
-- This test does not have SKIPREST
|
||||
|
||||
TSTEP
|
||||
1 1 1 /
|
||||
)";
|
||||
|
||||
Opm::Parser parser;
|
||||
const auto deck1 = parser.parseString(deck_string1);
|
||||
const auto deck2 = parser.parseString(deck_string2);
|
||||
const auto deck3 = parser.parseString(deck_string3);
|
||||
|
||||
// The date 2005-01-02 is not present as a DATES in the deck; invalid input.
|
||||
auto invalid_restart = std::make_pair(Opm::asTimeT(Opm::TimeStampUTC({2005, 1, 2})), 5);
|
||||
auto valid_restart = std::make_pair(Opm::asTimeT(Opm::TimeStampUTC({2005, 1, 1})), 5);
|
||||
|
||||
BOOST_CHECK_THROW( Opm::TimeMap(deck1, invalid_restart) , std::invalid_argument);
|
||||
Opm::TimeMap tm1(deck1, valid_restart);
|
||||
BOOST_CHECK_THROW( tm1[1], std::invalid_argument );
|
||||
BOOST_CHECK_THROW( tm1[4], std::invalid_argument );
|
||||
auto start = tm1[0];
|
||||
BOOST_CHECK_EQUAL(start , Opm::asTimeT(Opm::TimeStampUTC({2000,1,1})));
|
||||
BOOST_CHECK_EQUAL(tm1[5] , Opm::asTimeT(Opm::TimeStampUTC({2005,1,1})));
|
||||
|
||||
Opm::TimeMap tm2(deck2, valid_restart);
|
||||
BOOST_CHECK_EQUAL(tm2[5], Opm::asTimeT(Opm::TimeStampUTC({2005,1,1})));
|
||||
BOOST_CHECK_EQUAL(tm2[6], Opm::asTimeT(Opm::TimeStampUTC({2005,7,1})));
|
||||
|
||||
Opm::TimeMap tm3(deck3, valid_restart);
|
||||
BOOST_CHECK_EQUAL(tm3[5], Opm::asTimeT(Opm::TimeStampUTC({2005,1,1})));
|
||||
BOOST_CHECK_EQUAL(tm3[6], Opm::asTimeT(Opm::TimeStampUTC({2005,1,2})));
|
||||
BOOST_CHECK_EQUAL(tm3[7], Opm::asTimeT(Opm::TimeStampUTC({2005,1,3})));
|
||||
BOOST_CHECK_EQUAL(tm3[8], Opm::asTimeT(Opm::TimeStampUTC({2005,1,4})));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user