Merge pull request #2866 from joakim-hove/schedule-dump

Implement schedule dump to deck functionality
This commit is contained in:
Joakim Hove 2021-11-25 11:10:11 +01:00 committed by GitHub
commit 2d0e92750d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 139 additions and 1 deletions

View File

@ -23,6 +23,7 @@
#include <map>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
@ -467,7 +468,8 @@ namespace Opm
}
}
friend std::ostream& operator<<(std::ostream& os, const Schedule& sched);
void dump_deck(std::ostream& os) const;
private:
ScheduleStatic m_static;

View File

@ -22,6 +22,7 @@
#include <chrono>
#include <cstddef>
#include <optional>
#include <ostream>
#include <vector>
#include <opm/common/OpmLog/KeywordLocation.hpp>
@ -42,6 +43,7 @@ namespace Opm {
class Deck;
class DeckOutput;
struct ScheduleDeckContext;
class Runspec;
@ -76,6 +78,8 @@ namespace Opm {
serializer.vector(m_keywords);
m_location.serializeOp(serializer);
}
void dump_deck(DeckOutput& output, time_point& current_time) const;
private:
ScheduleTimeType m_time_type;
time_point m_start_time;
@ -143,6 +147,8 @@ namespace Opm {
m_location.serializeOp(serializer);
}
void dump_deck(std::ostream& os) const;
private:
time_point m_restart_time;
std::size_t m_restart_offset;

View File

@ -2001,4 +2001,14 @@ void Schedule::create_next(const ScheduleBlock& block) {
this->create_next(start_time, end_time);
}
void Schedule::dump_deck(std::ostream& os) const {
this->m_sched_deck.dump_deck(os);
}
std::ostream& operator<<(std::ostream& os, const Schedule& sched)
{
sched.dump_deck(os);
return os;
}
}

View File

@ -22,6 +22,7 @@
#include <unordered_set>
#include <opm/common/utility/OpmInputError.hpp>
#include <opm/parser/eclipse/Deck/DeckOutput.hpp>
#include <opm/parser/eclipse/Deck/DeckSection.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleDeck.hpp>
#include <opm/common/OpmLog/OpmLog.hpp>
@ -111,6 +112,46 @@ bool ScheduleBlock::operator==(const ScheduleBlock& other) const {
this->m_keywords == other.m_keywords;
}
namespace {
void dump_time(time_point tp, ScheduleTimeType time_type, time_point current_time, DeckOutput& output) {
if (time_type == ScheduleTimeType::START)
return;
if (time_type == ScheduleTimeType::DATES) {
TimeStampUTC ts(TimeService::to_time_t(tp));
auto ecl_month = TimeService::eclipseMonthNames().at(ts.month());
std::string dates_string = fmt::format(R"(
DATES
{} '{}' {} /
/
)", ts.day(), ecl_month, ts.year());
output.write_string(dates_string);
} else {
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(tp - current_time);
double days = seconds.count() / 86400.0;
std::string tstep_string = fmt::format(R"(
TSTEP
{} /
)", days);
output.write_string(tstep_string);
}
}
}
void ScheduleBlock::dump_deck(DeckOutput& output, time_point& current_time) const {
dump_time(this->start_time(), this->m_time_type, current_time, output);
if (!this->end_time().has_value())
return;
for (const auto& keyword : this->m_keywords)
keyword.write(output);
current_time = this->end_time().value();
}
const KeywordLocation& ScheduleBlock::location() const {
return this->m_location;
@ -307,4 +348,14 @@ ScheduleDeck ScheduleDeck::serializeObject() {
return deck;
}
void ScheduleDeck::dump_deck(std::ostream& os) const {
DeckOutput output(os);
output.write_string("SCHEDULE\n");
auto current_time = this->m_blocks[0].start_time();
for (const auto& block : this->m_blocks)
block.dump_deck(output, current_time);
}
}

View File

@ -20,6 +20,7 @@
#include <algorithm>
#include <cstddef>
#include <iostream>
#include <fstream>
#include <memory>
#include <stdexcept>
#include <utility>
@ -70,6 +71,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/CompletedCells.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleGrid.hpp>
#include "tests/WorkArea.cpp"
using namespace Opm;
@ -4950,8 +4952,75 @@ END
BOOST_CHECK_MESSAGE(! sched[3].rptonly(),
R"("RPTONLY" must NOT be configured on report step 4)");
}
BOOST_AUTO_TEST_CASE(DUMP_DECK) {
const std::string part1 = R"(
DIMENS
10 10 10 /
START -- 0
10 MAI 2007 /
GRID
DXV
10*100.0 /
DYV
10*100.0 /
DZV
10*10.0 /
DEPTHZ
121*2000.0 /
SUMMARY
RPTONLY
)";
const std::string schedule_string = R"(
SCHEDULE
WELSPECS
'W_1' 'OP' 30 37 3.33 'OIL' 7* /
/
DATES -- 1, 2
10 'JUN' 2007 /
10 JLY 2007 /
/
WELSPECS
'WX2' 'OP' 30 37 3.33 'OIL' 7* /
'W_3' 'OP' 20 51 3.92 'OIL' 7* /
/
RPTONLYO
DATES -- 3, 4
10 AUG 2007 /
10 SEP 2007 /
/
END
)";
WorkArea wa;
{
std::ofstream stream{"CASE1.DATA"};
stream << part1 << std::endl << schedule_string;
}
const auto& deck1 = Parser{}.parseFile("CASE1.DATA");
const auto es1 = EclipseState { deck1 };
const auto sched1 = Schedule { deck1, es1, std::make_shared<const Python>() };
{
std::ofstream stream{"CASE2.DATA"};
stream << part1 << std::endl << sched1;
}
const auto& deck2 = Parser{}.parseFile("CASE2.DATA");
const auto es2 = EclipseState { deck2 };
const auto sched2 = Schedule { deck2, es2, std::make_shared<const Python>() };
// Can not do a full sched == sched2 because the Deck member will have embedded
// keyword location information.
for (std::size_t step = 0; step < sched1.size(); step++)
BOOST_CHECK(sched1[step] == sched2[step]);
}
BOOST_AUTO_TEST_CASE(TestScheduleGrid) {