Enable rerun of iteration over Schedule keywords
This commit is contained in:
@@ -348,11 +348,13 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
unit_system.serializeOp(serializer);
|
unit_system.serializeOp(serializer);
|
||||||
serializer.vector(snapshots);
|
serializer.vector(snapshots);
|
||||||
|
serializer(this->m_input_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<class Key, class Value> using Map2 = std::map<Key,Value>;
|
template<class Key, class Value> using Map2 = std::map<Key,Value>;
|
||||||
std::shared_ptr<const Python> python_handle;
|
std::shared_ptr<const Python> python_handle;
|
||||||
|
std::string m_input_path;
|
||||||
ScheduleDeck m_sched_deck;
|
ScheduleDeck m_sched_deck;
|
||||||
TimeMap m_timeMap;
|
TimeMap m_timeMap;
|
||||||
WellMap wells_static;
|
WellMap wells_static;
|
||||||
@@ -411,7 +413,10 @@ namespace Opm
|
|||||||
void updateUDQActive( std::size_t timeStep, std::shared_ptr<UDQActive> udq );
|
void updateUDQActive( std::size_t timeStep, std::shared_ptr<UDQActive> udq );
|
||||||
bool updateWellStatus( const std::string& well, std::size_t reportStep, bool runtime, Well::Status status, std::optional<KeywordLocation> = {});
|
bool updateWellStatus( const std::string& well, std::size_t reportStep, bool runtime, Well::Status status, std::optional<KeywordLocation> = {});
|
||||||
void addWellToGroup( const std::string& group_name, const std::string& well_name , std::size_t timeStep);
|
void addWellToGroup( const std::string& group_name, const std::string& well_name , std::size_t timeStep);
|
||||||
void iterateScheduleSection(std::shared_ptr<const Python> python, const std::string& input_path, const ParseContext& parseContext , ErrorGuard& errors, const EclipseGrid& grid,
|
void iterateScheduleSection(std::optional<std::size_t> load_offset,
|
||||||
|
const ParseContext& parseContext,
|
||||||
|
ErrorGuard& errors,
|
||||||
|
const EclipseGrid& grid,
|
||||||
const FieldPropsManager& fp);
|
const FieldPropsManager& fp);
|
||||||
void addACTIONX(const Action::ActionX& action, std::size_t currentStep);
|
void addACTIONX(const Action::ActionX& action, std::size_t currentStep);
|
||||||
void addGroupToGroup( const std::string& parent_group, const std::string& child_group, std::size_t timeStep);
|
void addGroupToGroup( const std::string& parent_group, const std::string& child_group, std::size_t timeStep);
|
||||||
@@ -421,9 +426,7 @@ namespace Opm
|
|||||||
void addWell(const std::string& wellName, const DeckRecord& record, std::size_t timeStep, Connection::Order connection_order);
|
void addWell(const std::string& wellName, const DeckRecord& record, std::size_t timeStep, Connection::Order connection_order);
|
||||||
void checkIfAllConnectionsIsShut(std::size_t currentStep);
|
void checkIfAllConnectionsIsShut(std::size_t currentStep);
|
||||||
void updateUDQ(const DeckKeyword& keyword, std::size_t current_step);
|
void updateUDQ(const DeckKeyword& keyword, std::size_t current_step);
|
||||||
void handleKeyword(std::shared_ptr<const Python> python,
|
void handleKeyword(std::size_t currentStep,
|
||||||
const std::string& input_path,
|
|
||||||
std::size_t currentStep,
|
|
||||||
const ScheduleBlock& block,
|
const ScheduleBlock& block,
|
||||||
const DeckKeyword& keyword,
|
const DeckKeyword& keyword,
|
||||||
const ParseContext& parseContext, ErrorGuard& errors,
|
const ParseContext& parseContext, ErrorGuard& errors,
|
||||||
@@ -507,7 +510,7 @@ namespace Opm
|
|||||||
bool handleNormalKeyword(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors);
|
bool handleNormalKeyword(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors);
|
||||||
|
|
||||||
// Keyword Handlers
|
// Keyword Handlers
|
||||||
void handlePYACTION (std::shared_ptr<const Python> python, const std::string& input_path, const DeckKeyword&, std::size_t currentStep);
|
void handlePYACTION(const DeckKeyword&, std::size_t currentStep);
|
||||||
void handleGCONPROD(const DeckKeyword& keyword, std::size_t current_step, const ParseContext& parseContext, ErrorGuard& errors);
|
void handleGCONPROD(const DeckKeyword& keyword, std::size_t current_step, const ParseContext& parseContext, ErrorGuard& errors);
|
||||||
void handleGCONINJE(const DeckKeyword& keyword, std::size_t current_step, const ParseContext& parseContext, ErrorGuard& errors);
|
void handleGCONINJE(const DeckKeyword& keyword, std::size_t current_step, const ParseContext& parseContext, ErrorGuard& errors);
|
||||||
void handleGLIFTOPT(const DeckKeyword& keyword, std::size_t report_step, const ParseContext& parseContext, ErrorGuard& errors);
|
void handleGLIFTOPT(const DeckKeyword& keyword, std::size_t report_step, const ParseContext& parseContext, ErrorGuard& errors);
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ namespace Opm {
|
|||||||
std::vector<ScheduleBlock>::const_iterator begin() const;
|
std::vector<ScheduleBlock>::const_iterator begin() const;
|
||||||
std::vector<ScheduleBlock>::const_iterator end() const;
|
std::vector<ScheduleBlock>::const_iterator end() const;
|
||||||
std::size_t size() const;
|
std::size_t size() const;
|
||||||
|
std::size_t restart_offset() const;
|
||||||
const KeywordLocation& location() const;
|
const KeywordLocation& location() const;
|
||||||
|
|
||||||
bool operator==(const ScheduleDeck& other) const;
|
bool operator==(const ScheduleDeck& other) const;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ namespace Opm {
|
|||||||
const PAvg& pavg() const;
|
const PAvg& pavg() const;
|
||||||
|
|
||||||
void tuning(Tuning tuning);
|
void tuning(Tuning tuning);
|
||||||
|
Tuning& tuning();
|
||||||
const Tuning& tuning() const;
|
const Tuning& tuning() const;
|
||||||
|
|
||||||
void nupcol(int nupcol);
|
void nupcol(int nupcol);
|
||||||
|
|||||||
@@ -1615,15 +1615,14 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Schedule::handleWSEGITER(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) {
|
void Schedule::handleWSEGITER(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) {
|
||||||
auto tuning = this->snapshots.back().tuning();
|
|
||||||
const auto& record = handlerContext.keyword.getRecord(0);
|
const auto& record = handlerContext.keyword.getRecord(0);
|
||||||
|
auto& tuning = this->snapshots.back().tuning();
|
||||||
|
|
||||||
tuning.MXWSIT = record.getItem<ParserKeywords::WSEGITER::MAX_WELL_ITERATIONS>().get<int>(0);
|
tuning.MXWSIT = record.getItem<ParserKeywords::WSEGITER::MAX_WELL_ITERATIONS>().get<int>(0);
|
||||||
tuning.WSEG_MAX_RESTART = record.getItem<ParserKeywords::WSEGITER::MAX_TIMES_REDUCED>().get<int>(0);
|
tuning.WSEG_MAX_RESTART = record.getItem<ParserKeywords::WSEGITER::MAX_TIMES_REDUCED>().get<int>(0);
|
||||||
tuning.WSEG_REDUCTION_FACTOR = record.getItem<ParserKeywords::WSEGITER::REDUCTION_FACTOR>().get<double>(0);
|
tuning.WSEG_REDUCTION_FACTOR = record.getItem<ParserKeywords::WSEGITER::REDUCTION_FACTOR>().get<double>(0);
|
||||||
tuning.WSEG_INCREASE_FACTOR = record.getItem<ParserKeywords::WSEGITER::INCREASING_FACTOR>().get<double>(0);
|
tuning.WSEG_INCREASE_FACTOR = record.getItem<ParserKeywords::WSEGITER::INCREASING_FACTOR>().get<double>(0);
|
||||||
|
|
||||||
this->snapshots.back().tuning(tuning);
|
|
||||||
m_events.addEvent(ScheduleEvents::TUNING_CHANGE, handlerContext.currentStep);
|
m_events.addEvent(ScheduleEvents::TUNING_CHANGE, handlerContext.currentStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ namespace {
|
|||||||
const RestartIO::RstState * rst)
|
const RestartIO::RstState * rst)
|
||||||
try :
|
try :
|
||||||
python_handle(python),
|
python_handle(python),
|
||||||
|
m_input_path(deck.getInputPath()),
|
||||||
m_sched_deck(deck, restart_info(rst) ),
|
m_sched_deck(deck, restart_info(rst) ),
|
||||||
m_timeMap( deck , restart_info( rst )),
|
m_timeMap( deck , restart_info( rst )),
|
||||||
m_events( this->m_timeMap ),
|
m_events( this->m_timeMap ),
|
||||||
@@ -149,12 +150,28 @@ namespace {
|
|||||||
applyMESSAGES(keyword, 0);
|
applyMESSAGES(keyword, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->iterateScheduleSection( python, deck.getInputPath(), parseContext, errors, grid, fp);
|
this->iterateScheduleSection( {}, parseContext, errors, grid, fp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is temporary "integration test" for the time arguments in the
|
The code in the if (integration_test) { ... } is an enforced
|
||||||
Schedule class.
|
integration test to assert the sanity of the ongoing Schedule
|
||||||
|
refactoring. At the very latest this should be removed when the
|
||||||
|
Schedule refactoring is complete.
|
||||||
*/
|
*/
|
||||||
if (this->size() > 0) {
|
const bool integration_test = true;
|
||||||
|
if (integration_test) {
|
||||||
|
if (this->size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Verify that we can safely re-iterate over the Schedule section
|
||||||
|
if (!rst)
|
||||||
|
this->iterateScheduleSection( 0, parseContext, errors, grid, fp);
|
||||||
|
else {
|
||||||
|
auto restart_offset = this->m_sched_deck.restart_offset();
|
||||||
|
this->iterateScheduleSection( restart_offset, parseContext, errors, grid, fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the time schedule is correct.
|
||||||
for (std::size_t report_step = 0; report_step < this->size() - 1; report_step++) {
|
for (std::size_t report_step = 0; report_step < this->size() - 1; report_step++) {
|
||||||
const auto& this_block = this->m_sched_deck[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])) {
|
if (this_block.start_time() != std::chrono::system_clock::from_time_t(this->m_timeMap[report_step])) {
|
||||||
@@ -285,6 +302,7 @@ namespace {
|
|||||||
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() };
|
result.snapshots = { ScheduleState::serializeObject() };
|
||||||
|
result.m_input_path = "Some/funny/path";
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -302,9 +320,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Schedule::handleKeyword(std::shared_ptr<const Python> python,
|
void Schedule::handleKeyword(std::size_t currentStep,
|
||||||
const std::string& input_path,
|
|
||||||
std::size_t currentStep,
|
|
||||||
const ScheduleBlock& block,
|
const ScheduleBlock& block,
|
||||||
const DeckKeyword& keyword,
|
const DeckKeyword& keyword,
|
||||||
const ParseContext& parseContext,
|
const ParseContext& parseContext,
|
||||||
@@ -325,7 +341,7 @@ namespace {
|
|||||||
rftProperties.push_back( std::make_pair( &keyword , currentStep ));
|
rftProperties.push_back( std::make_pair( &keyword , currentStep ));
|
||||||
|
|
||||||
else if (keyword.name() == "PYACTION")
|
else if (keyword.name() == "PYACTION")
|
||||||
handlePYACTION(python, input_path, keyword, currentStep);
|
handlePYACTION(keyword, currentStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -372,18 +388,89 @@ private:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Schedule::iterateScheduleSection(std::shared_ptr<const Opm::Python> python,
|
void Schedule::iterateScheduleSection(std::optional<std::size_t> load_offset,
|
||||||
const std::string& input_path,
|
const ParseContext& parseContext ,
|
||||||
const ParseContext& parseContext ,
|
ErrorGuard& errors,
|
||||||
ErrorGuard& errors,
|
const EclipseGrid& grid,
|
||||||
const EclipseGrid& grid,
|
const FieldPropsManager& fp) {
|
||||||
const FieldPropsManager& fp) {
|
|
||||||
|
|
||||||
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 deck_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;
|
||||||
|
/*
|
||||||
|
The process of transitioning to Schedule model based on ScheduleState
|
||||||
|
instances is a gradual one. For the keywords which have been converted
|
||||||
|
to the ScheduleState implementation the iterateScheduleSection()
|
||||||
|
function can be called repeatedly, whereas for the keywords which have
|
||||||
|
not yet been converted that is not safe. The old_style_keywords is a
|
||||||
|
list of keywords which should be ignored when iterateScheduleSection()
|
||||||
|
is called repeatedly.
|
||||||
|
*/
|
||||||
|
std::unordered_set<std::string> old_style_keywords = {
|
||||||
|
"PYACTION",
|
||||||
|
"GCONPROD",
|
||||||
|
"GCONINJE",
|
||||||
|
"GLIFTOPT",
|
||||||
|
"WELPI",
|
||||||
|
"BRANPROP",
|
||||||
|
"COMPDAT",
|
||||||
|
"COMPLUMP",
|
||||||
|
"COMPORD",
|
||||||
|
"COMPSEGS",
|
||||||
|
"GCONINJE",
|
||||||
|
"GCONPROD",
|
||||||
|
"GCONSALE",
|
||||||
|
"GCONSUMP",
|
||||||
|
"GEFAC",
|
||||||
|
"GLIFTOPT",
|
||||||
|
"GPMAINT",
|
||||||
|
"GRUPNET",
|
||||||
|
"GRUPTREE",
|
||||||
|
"GUIDERAT",
|
||||||
|
"LIFTOPT",
|
||||||
|
"LINCOM",
|
||||||
|
"MESSAGES",
|
||||||
|
"MULTFLT",
|
||||||
|
"MXUNSUPP",
|
||||||
|
"NODEPROP",
|
||||||
|
"RPTSCHED",
|
||||||
|
"UDQ",
|
||||||
|
"VFPINJ",
|
||||||
|
"VFPPROD",
|
||||||
|
"WCONHIST",
|
||||||
|
"WCONINJE",
|
||||||
|
"WCONINJH",
|
||||||
|
"WCONPROD",
|
||||||
|
"WECON",
|
||||||
|
"WEFAC",
|
||||||
|
"WELOPEN",
|
||||||
|
"WELPI",
|
||||||
|
"WELSEGS",
|
||||||
|
"WELSPECS",
|
||||||
|
"WELTARG",
|
||||||
|
"WFOAM",
|
||||||
|
"WGRUPCON",
|
||||||
|
"WHISTCTL",
|
||||||
|
"WINJTEMP",
|
||||||
|
"WLIFTOPT",
|
||||||
|
"WLIST",
|
||||||
|
"WPAVEDEP",
|
||||||
|
"WPIMULT",
|
||||||
|
"WPMITAB",
|
||||||
|
"WPOLYMER",
|
||||||
|
"WSALT",
|
||||||
|
"WSEGSICD",
|
||||||
|
"WSEGAICD",
|
||||||
|
"WSEGVALV",
|
||||||
|
"WSKPTAB",
|
||||||
|
"WSOLVENT",
|
||||||
|
"WTEMP",
|
||||||
|
"WTEST",
|
||||||
|
"WTRACER"
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The keywords in the skiprest_whitelist set are loaded from the
|
The keywords in the skiprest_whitelist set are loaded from the
|
||||||
SCHEDULE section even though the SKIPREST keyword is in action. The
|
SCHEDULE section even though the SKIPREST keyword is in action. The
|
||||||
@@ -426,6 +513,12 @@ private:
|
|||||||
location.lineno));
|
location.lineno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (load_offset.has_value()) {
|
||||||
|
if (load_offset.value() < this->m_sched_deck.restart_offset())
|
||||||
|
throw std::logic_error("BUG: Tried to replay schedule keywords from historical section in restarted run");
|
||||||
|
this->snapshots.resize( load_offset.value() );
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& block : this->m_sched_deck) {
|
for (const auto& block : this->m_sched_deck) {
|
||||||
std::size_t keyword_index = 0;
|
std::size_t keyword_index = 0;
|
||||||
auto time_type = block.time_type();
|
auto time_type = block.time_type();
|
||||||
@@ -462,6 +555,11 @@ private:
|
|||||||
current_file = location.filename;
|
current_file = location.filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (load_offset.has_value() && old_style_keywords.count(keyword.name()) == 1) {
|
||||||
|
keyword_index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (keyword.name() == "ACTIONX") {
|
if (keyword.name() == "ACTIONX") {
|
||||||
Action::ActionX action(keyword, this->m_timeMap.getStartTime(currentStep));
|
Action::ActionX action(keyword, this->m_timeMap.getStartTime(currentStep));
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -487,9 +585,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger(fmt::format("Processing keyword {} at line {}", location.keyword, location.lineno));
|
logger(fmt::format("Processing keyword {} at line {}", location.keyword, location.lineno));
|
||||||
this->handleKeyword(python,
|
this->handleKeyword(currentStep,
|
||||||
input_path,
|
|
||||||
currentStep,
|
|
||||||
block,
|
block,
|
||||||
keyword,
|
keyword,
|
||||||
parseContext,
|
parseContext,
|
||||||
@@ -522,8 +618,8 @@ private:
|
|||||||
this->m_actions.update(currentStep, new_actions);
|
this->m_actions.update(currentStep, new_actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Schedule::handlePYACTION(std::shared_ptr<const Python> python, const std::string& input_path, const DeckKeyword& keyword, std::size_t currentStep) {
|
void Schedule::handlePYACTION(const DeckKeyword& keyword, std::size_t currentStep) {
|
||||||
if (!python->enabled()) {
|
if (!this->python_handle->enabled()) {
|
||||||
//Must have a real Python instance here - to ensure that IMPORT works
|
//Must have a real Python instance here - to ensure that IMPORT works
|
||||||
const auto& loc = keyword.location();
|
const auto& loc = keyword.location();
|
||||||
OpmLog::warning("This version of flow is built without support for Python. Keyword PYACTION in file: " + loc.filename + " line: " + std::to_string(loc.lineno) + " is ignored.");
|
OpmLog::warning("This version of flow is built without support for Python. Keyword PYACTION in file: " + loc.filename + " line: " + std::to_string(loc.lineno) + " is ignored.");
|
||||||
@@ -534,12 +630,12 @@ private:
|
|||||||
const auto& run_count = Action::PyAction::from_string( keyword.getRecord(0).getItem<ParserKeywords::PYACTION::RUN_COUNT>().get<std::string>(0) );
|
const auto& run_count = Action::PyAction::from_string( keyword.getRecord(0).getItem<ParserKeywords::PYACTION::RUN_COUNT>().get<std::string>(0) );
|
||||||
const auto& module_arg = keyword.getRecord(1).getItem<ParserKeywords::PYACTION::FILENAME>().get<std::string>(0);
|
const auto& module_arg = keyword.getRecord(1).getItem<ParserKeywords::PYACTION::FILENAME>().get<std::string>(0);
|
||||||
std::string module;
|
std::string module;
|
||||||
if (input_path.empty())
|
if (this->m_input_path.empty())
|
||||||
module = module_arg;
|
module = module_arg;
|
||||||
else
|
else
|
||||||
module = input_path + "/" + module_arg;
|
module = this->m_input_path + "/" + module_arg;
|
||||||
|
|
||||||
Action::PyAction pyaction(python, name, run_count, module);
|
Action::PyAction pyaction(this->python_handle, name, run_count, module);
|
||||||
auto new_actions = std::make_shared<Action::Actions>( this->actions(currentStep) );
|
auto new_actions = std::make_shared<Action::Actions>( this->actions(currentStep) );
|
||||||
new_actions->add(pyaction);
|
new_actions->add(pyaction);
|
||||||
this->m_actions.update(currentStep, new_actions);
|
this->m_actions.update(currentStep, new_actions);
|
||||||
@@ -1631,6 +1727,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
return this->m_timeMap == data.m_timeMap &&
|
return this->m_timeMap == data.m_timeMap &&
|
||||||
|
this->m_input_path == data.m_input_path &&
|
||||||
compareMap(this->wells_static, data.wells_static) &&
|
compareMap(this->wells_static, data.wells_static) &&
|
||||||
compareMap(this->groups, data.groups) &&
|
compareMap(this->groups, data.groups) &&
|
||||||
this->m_events == data.m_events &&
|
this->m_events == data.m_events &&
|
||||||
|
|||||||
@@ -121,6 +121,11 @@ const KeywordLocation& ScheduleDeck::location() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::size_t ScheduleDeck::restart_offset() const {
|
||||||
|
return this->m_restart_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ScheduleDeck::ScheduleDeck(const Deck& deck, const std::pair<std::time_t, std::size_t>& restart) {
|
ScheduleDeck::ScheduleDeck(const Deck& deck, const std::pair<std::time_t, std::size_t>& restart) {
|
||||||
const std::unordered_set<std::string> skiprest_include = {"VFPPROD", "VFPINJ", "RPTSCHED", "RPTRST", "TUNING", "MESSAGES"};
|
const std::unordered_set<std::string> skiprest_include = {"VFPPROD", "VFPINJ", "RPTSCHED", "RPTRST", "TUNING", "MESSAGES"};
|
||||||
std::chrono::system_clock::time_point start_time;
|
std::chrono::system_clock::time_point start_time;
|
||||||
|
|||||||
@@ -110,4 +110,8 @@ const Tuning& ScheduleState::tuning() const {
|
|||||||
return this->m_tuning;
|
return this->m_tuning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tuning& ScheduleState::tuning() {
|
||||||
|
return this->m_tuning;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user