Facilitate using max time step from TUNING/NEXT[STEP] only when specified. Also corrects the persistent behaviour of NEXTSTEP.

This commit is contained in:
Vegard Kippe
2023-05-23 22:08:51 +02:00
parent 325ee7bbb3
commit 128ba83810
8 changed files with 47 additions and 22 deletions

View File

@@ -20,6 +20,8 @@
#ifndef OPM_TUNING_HPP
#define OPM_TUNING_HPP
#include <optional>
namespace Opm {
class NextStep {
@@ -49,7 +51,7 @@ namespace Opm {
static Tuning serializationTestObject();
// Record1
double TSINIT;
std::optional<double> TSINIT;
double TSMAXZ;
double TSMINZ;
double TSMCHP;

View File

@@ -1028,11 +1028,18 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
const auto& deck_item = rec.getItem(item_name);
return deck_item.defaultApplied(0) ? previous_value : rec.getItem(item_name).getSIDouble(0);
};
// \Note No TSTINIT value should not be used unless explicitly non-defaulted, hence removing value by default
// \Note (exception is the first time step, which is handled by the Tuning constructor)
tuning.TSINIT = std::nullopt;
if (numrecords > 0) {
const auto& record1 = handlerContext.keyword.getRecord(0);
tuning.TSINIT = nondefault_or_previous_sidouble(record1, "TSINIT", tuning.TSINIT);
// \Note A value indicates TSINIT was set in this record
if (const auto& deck_item = record1.getItem("TSINIT"); !deck_item.defaultApplied(0))
tuning.TSINIT = std::optional<double>{ record1.getItem("TSINIT").getSIDouble(0) };
tuning.TSMAXZ = nondefault_or_previous_sidouble(record1, "TSMAXZ", tuning.TSMAXZ);
tuning.TSMINZ = nondefault_or_previous_sidouble(record1, "TSMINZ", tuning.TSMINZ);
tuning.TSMCHP = nondefault_or_previous_sidouble(record1, "TSMCHP", tuning.TSMCHP);

View File

@@ -131,8 +131,9 @@ ScheduleState::ScheduleState(const ScheduleState& src, const time_point& start_t
if (this->next_tstep.has_value()) {
if (!this->next_tstep->every_report()) {
this->next_tstep = std::nullopt;
this->events().addEvent(ScheduleEvents::TUNING_CHANGE);
}
// Need to signal an event also for the persistance to take effect
this->events().addEvent(ScheduleEvents::TUNING_CHANGE);
}
}
@@ -347,12 +348,10 @@ Tuning& ScheduleState::tuning() {
return this->m_tuning;
}
// Returns -1 if there is no active limit on next step (from TUNING or NEXT[STEP])
double ScheduleState::max_next_tstep() const {
auto tuning_value = this->m_tuning.TSINIT;
if (!this->next_tstep.has_value())
return tuning_value;
auto next_value = this->next_tstep->value();
double tuning_value = this->m_tuning.TSINIT.has_value() ? this->m_tuning.TSINIT.value() : -1.0;
double next_value = this->next_tstep.has_value() ? this->next_tstep->value() : -1.0;
return std::max(next_value, tuning_value);
}

View File

@@ -53,7 +53,7 @@ Tuning::Tuning() {
using WsegIterKW = ParserKeywords::WSEGITER;
// Record1
TSINIT = TuningKw::TSINIT::defaultValue * Metric::Time;
TSINIT = std::nullopt; // Let simulator choose initial step if not specified
TSMAXZ = TuningKw::TSMAXZ::defaultValue * Metric::Time;
TSMINZ = TuningKw::TSMINZ::defaultValue * Metric::Time;
TSMCHP = TuningKw::TSMCHP::defaultValue * Metric::Time;
@@ -97,7 +97,7 @@ Tuning::Tuning() {
Tuning Tuning::serializationTestObject() {
Tuning result;
result.TSINIT = 1.0;
result.TSINIT = std::optional<double>{1.0};
result.TSMAXZ = 2.0;
result.TSMINZ = 3.0;
result.TSMCHP = 4.0;

View File

@@ -105,7 +105,8 @@ void RstState::load_tuning(const std::vector<int>& intehead,
this->tuning.MXWSIT = intehead[ VI::intehead::MXWSIT ];
this->tuning.MXWPIT = intehead[ VI::intehead::MXWPIT ];
tuning.TSINIT = this->unit_system.to_si(M::time, doubhead[VI::doubhead::TsInit]);
double tsinit = this->unit_system.to_si(M::time, doubhead[VI::doubhead::TsInit]);
tuning.TSINIT = tsinit > 0 ? std::optional<double>{ tsinit } : std::nullopt;
tuning.TSMAXZ = this->unit_system.to_si(M::time, doubhead[VI::doubhead::TsMaxz]);
tuning.TSMINZ = this->unit_system.to_si(M::time, doubhead[VI::doubhead::TsMinz]);
tuning.TSMCHP = this->unit_system.to_si(M::time, doubhead[VI::doubhead::TsMchp]);

View File

@@ -567,7 +567,7 @@ Opm::RestartIO::DoubHEAD::tuningParameters(const Tuning& tuning,
const double cnvT)
{
// Record 1
this->data_[Index::TsInit] = tuning.TSINIT / cnvT;
this->data_[Index::TsInit] = tuning.TSINIT.has_value() ? tuning.TSINIT.value() / cnvT : -1.0;
this->data_[Index::TsMaxz] = tuning.TSMAXZ / cnvT;
this->data_[Index::TsMinz] = tuning.TSMINZ / cnvT;
this->data_[Index::TsMchp] = tuning.TSMCHP / cnvT;

View File

@@ -687,9 +687,9 @@ namespace {
const auto TsInit = doubhead[VI::doubhead::TsInit];
if (TsInit < 0.0) {
throwIfMissingRequired({ "OPMEXTRA", M::identity, required });
}
// if (TsInit < 0.0) {
// throwIfMissingRequired({ "OPMEXTRA", M::identity, required });
// }
return { usys.to_si(M::time, TsInit) };
}

View File

@@ -20,6 +20,8 @@
#define BOOST_TEST_MODULE TuningTests
#include <optional>
#include <boost/test/unit_test.hpp>
#include <opm/input/eclipse/Python/Python.hpp>
@@ -99,11 +101,14 @@ BOOST_AUTO_TEST_CASE(TuningTest) {
{
size_t timestep = 4;
const auto& event = schedule[timestep].events();
BOOST_CHECK(!event.hasEvent(ScheduleEvents::TUNING_CHANGE));
// Because NEXTSTEP is persistent a tuning event is triggered at each report step
BOOST_CHECK(event.hasEvent(ScheduleEvents::TUNING_CHANGE));
const auto& tuning = schedule[timestep].tuning();
std::optional<double> TSINIT_default = tuning.TSINIT;
BOOST_CHECK(TSINIT_default == std::nullopt);
// BOOST_CHECK_CLOSE(TSINIT_default, 1 * Metric::Time, diff);
const auto& tuning = schedule[4].tuning();
double TSINIT_default = tuning.TSINIT;
BOOST_CHECK_CLOSE(TSINIT_default, 1 * Metric::Time, diff);
BOOST_CHECK_CLOSE(schedule[timestep].max_next_tstep(), 5*Metric::Time, diff);
double TSMAXZ_default = tuning.TSMAXZ;
@@ -223,8 +228,10 @@ BOOST_AUTO_TEST_CASE(TuningTest) {
const auto& tuning = schedule[timeStep].tuning();
BOOST_CHECK(event.hasEvent(ScheduleEvents::TUNING_CHANGE));
double TSINIT = tuning.TSINIT;
BOOST_CHECK_CLOSE(TSINIT, 2 * Metric::Time, diff);
std::optional<double> TSINIT = tuning.TSINIT;
BOOST_CHECK(TSINIT.has_value());
//BOOST_CHECK_CLOSE(TSINIT.value(), 2 * Metric::Time, diff);
BOOST_CHECK_CLOSE(schedule[timeStep].max_next_tstep(), 5*Metric::Time, diff);
double TSMAXZ = tuning.TSMAXZ;
@@ -330,7 +337,8 @@ BOOST_AUTO_TEST_CASE(TuningTest) {
{
std::size_t timestep = 7;
const auto& event = schedule[timestep].events();
BOOST_CHECK(!event.hasEvent(ScheduleEvents::TUNING_CHANGE));
// Because NEXTSTEP is persistent a tuning event is triggered at each report step
BOOST_CHECK(event.hasEvent(ScheduleEvents::TUNING_CHANGE));
}
/*** TIMESTEP 8 ***/
@@ -362,5 +370,13 @@ BOOST_AUTO_TEST_CASE(TuningTest) {
BOOST_CHECK_CLOSE(tuning.TMAXWC, 10.0 * Metric::Time, diff);
BOOST_CHECK_EQUAL(tuning.MXWSIT, ParserKeywords::WSEGITER::MAX_WELL_ITERATIONS::defaultValue);
/********* Record 2 [and 3] (should be unchanged) ***********/
double TRGTTE = tuning.TRGTTE;
BOOST_CHECK_CLOSE(TRGTTE, 0.2, diff);
int NEWTMX = tuning.NEWTMX;
BOOST_CHECK_EQUAL(NEWTMX, 13);
}
}