Initial work to add Actionx data to Eclipse compatible restart file

further changes to Actionx - restart

further changes for Actionx data to Restart file

additional changes to output Actionx data to Restart file

add test data for UDQ-ACTIONX

changes to add unit tests for InteHead - Actionx

Added changes to allow for output of IACT, SACT and ZACT to the E100 compatible restart file

changes to add ZLACT to restart output

Further changes - add ZACN - prelim

further changes to add ZACN to restart file

Additional changes to output IACN and SACN to restart

further changes to add IACN and SACN to the restart file

further changes to make unit tests for Actionx data / keywords

further changes to actionx restart and unit tests therefore

Added code for unit tests - not finished

some changes to correct for changes in upstream/master

changes correct errors in IACN and SACN

Initial work to add Actionx data to Eclipse compatible restart file

further changes to Actionx - restart

further changes for Actionx data to Restart file

additional changes to output Actionx data to Restart file

add test data for UDQ-ACTIONX

changes to add unit tests for InteHead - Actionx

Added changes to allow for output of IACT, SACT and ZACT to the E100 compatible restart file

changes to add ZLACT to restart output

Further changes - add ZACN - prelim

further changes to add ZACN to restart file

Additional changes to output IACN and SACN to restart

further changes to add IACN and SACN to the restart file

further changes to make unit tests for Actionx data / keywords

further changes to actionx restart and unit tests therefore

Added code for unit tests - not finished

some changes to correct for changes in upstream/master

changes correct errors in IACN and SACN

changes to avoid change in output data for restart file

further changes to avoid change in RESTART data

minor change to avoid data change in Restart file
This commit is contained in:
Jostein Alvestad
2019-08-27 15:31:49 +02:00
committed by Joakim Hove
parent 1db06277ce
commit 7973585db0
18 changed files with 2652 additions and 13 deletions

View File

@@ -0,0 +1,587 @@
/*
Copyright 2018 Statoil 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/output/eclipse/AggregateActionxData.hpp>
#include <opm/output/eclipse/AggregateGroupData.hpp>
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQAssign.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Action/ActionX.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunctionTable.hpp>
#include <algorithm>
#include <cstddef>
#include <cstring>
#include <string>
#include <iostream>
// #####################################################################
// Class Opm::RestartIO::Helpers::AggregateGroupData
// ---------------------------------------------------------------------
namespace {
const std::map<std::string, int> lhsQuantityToIndex = {
{"F", 1},
{"W", 2},
{"G", 3},
{"D", 10},
{"M", 11},
{"Y", 12},
};
const std::map<std::string, double> monthToNo = {
{"JAN", 1.},
{"FEB", 2.},
{"MAR", 3.},
{"APR", 4.},
{"MAY", 5.},
{"JUN", 6.},
{"JUL", 7.},
{"AUG", 8.},
{"SEP", 9.},
{"OCT", 10.},
{"NOV", 11.},
{"DEC", 12.},
};
const std::map<std::string, int> rhsQuantityToIndex = {
{"F", 1},
{"W", 2},
{"G", 3},
};
using logic_enum = Opm::Action::Condition::Logical;
const std::map<logic_enum, int> logicalToIndex_13 = {
{logic_enum::AND, 1},
{logic_enum::OR, 2},
{logic_enum::END, 0},
};
const std::map<logic_enum, int> logicalToIndex_17 = {
{logic_enum::AND, 1},
{logic_enum::OR, 0},
{logic_enum::END, 0},
};
using cmp_enum = Opm::Action::Condition::Comparator;
const std::map<cmp_enum, int> cmpToIndex = {
{cmp_enum::GREATER, 1},
{cmp_enum::LESS, 2},
{cmp_enum::GREATER_EQUAL, 3},
{cmp_enum::LESS_EQUAL, 4},
{cmp_enum::EQUAL, 5},
{cmp_enum::INVALID, 0},
};
namespace iACT {
Opm::RestartIO::Helpers::WindowedArray<int>
allocate(const std::vector<int>& actDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<int>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(actDims[0]) },
WV::WindowSize{ static_cast<std::size_t>(actDims[1]) }
};
}
template <class IACTArray>
void staticContrib(const Opm::Action::ActionX& actx, IACTArray& iAct)
{
//item [0]: is unknown, (=0)
iAct[0] = 0;
//item [1]: The number of lines of schedule data including ENDACTIO
iAct[1] = actx.keyword_strings().size();
//item [2]: is unknown, (=1)
iAct[2] = 1;
//item [3]: is unknown, (=7)
iAct[3] = 7;
//item [4]: is unknown, (=0)
iAct[4] = 0;
//item [5]: The number of times the action is triggered
iAct[5] = actx.max_run();
//item [6]: is unknown, (=0)
iAct[6] = 0;
//item [7]: is unknown, (=0)
iAct[7] = 0;
//item [8]: The number of times the action is triggered
iAct[8] = actx.conditions().size();
}
} // iAct
namespace sACT {
Opm::RestartIO::Helpers::WindowedArray<float>
allocate(const std::vector<int>& actDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<float>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(actDims[0]) },
WV::WindowSize{ static_cast<std::size_t>(actDims[2]) }
};
}
template <class SACTArray>
void staticContrib(SACTArray& sAct)
{
//item [0 - 4]: is unknown, (=0)
for (std::size_t ind = 0; ind < 5 ; ind++) {
sAct[ind] = 0;
}
}
} // sAct
namespace zACT {
Opm::RestartIO::Helpers::WindowedArray<
Opm::EclIO::PaddedOutputString<8>
>
allocate(const std::vector<int>& actDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<
Opm::EclIO::PaddedOutputString<8>
>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(actDims[0]) },
WV::WindowSize{ static_cast<std::size_t>(actDims[3]) }
};
}
template <class ZACTArray>
void staticContrib(const Opm::Action::ActionX& actx, ZACTArray& zAct)
{
// entry 1 is udq keyword
zAct[0] = actx.name();
}
} // zAct
namespace zLACT {
Opm::RestartIO::Helpers::WindowedArray<
Opm::EclIO::PaddedOutputString<8>
>
allocate(const std::vector<int>& actDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<
Opm::EclIO::PaddedOutputString<8>
>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(actDims[0]) },
WV::WindowSize{ static_cast<std::size_t>(actDims[4]) }
};
}
template <class ZLACTArray>
void staticContrib(const Opm::Action::ActionX& actx, int noEPrZlact, ZLACTArray& zLact)
{
std::size_t ind = 0;
int l_sstr = 8;
int max_l_str = 128;
// write out the schedule input lines
const auto& schedule_data = actx.keyword_strings();
for (auto z_data : schedule_data) {
int n_sstr = z_data.size()/l_sstr;
if (static_cast<int>(z_data.size()) > max_l_str) {
std::cout << "Too long input data string (max 128 characters): " << z_data << std::endl;
throw std::invalid_argument("Actionx: " + actx.name());
}
else {
for (int i = 0; i < n_sstr; i++) {
zLact[ind + i] = z_data.substr(i*l_sstr, l_sstr);
}
//add remainder of last non-zero string
if ((z_data.size() % l_sstr) > 0)
zLact[ind + n_sstr] = z_data.substr(n_sstr*l_sstr);
}
ind += static_cast<std::size_t>(noEPrZlact);
}
}
} // zLact
namespace zACN {
Opm::RestartIO::Helpers::WindowedArray<
Opm::EclIO::PaddedOutputString<8>
>
allocate(const std::vector<int>& actDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<
Opm::EclIO::PaddedOutputString<8>
>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(actDims[0]) },
WV::WindowSize{ static_cast<std::size_t>(actDims[5]) }
};
}
template <class ZACNArray>
void staticContrib(const Opm::Action::ActionX& actx, ZACNArray& zAcn)
{
std::size_t ind = 0;
int noEPZacn = 13;
// write out the schedule Actionx conditions
const auto& actx_cond = actx.conditions();
for (auto z_data : actx_cond) {
// left hand quantity
if ((z_data.lhs.quantity.substr(0,1) != "D") &&
(z_data.lhs.quantity.substr(0,1) != "M") &&
(z_data.lhs.quantity.substr(0,1) != "Y"))
zAcn[ind + 0] = z_data.lhs.quantity;
// right hand quantity
if ((z_data.rhs.quantity.substr(0,1) == "W") ||
(z_data.rhs.quantity.substr(0,1) == "G"))
zAcn[ind + 1] = z_data.rhs.quantity;
// operator (comparator)
zAcn[ind + 2] = z_data.cmp_string;
// well-name if left hand quantity is a well quantity
if (z_data.lhs.quantity.substr(0,1) == "W") {
zAcn[ind + 3] = z_data.lhs.args[0];
}
// well-name if right hand quantity is a well quantity
if (z_data.rhs.quantity.substr(0,1) == "W") {
zAcn[ind + 4] = z_data.rhs.args[0];
}
// group-name if left hand quantity is a group quantity
if (z_data.lhs.quantity.substr(0,1) == "G") {
zAcn[ind + 5] = z_data.lhs.args[0];
}
// group-name if right hand quantity is a group quantity
if (z_data.rhs.quantity.substr(0,1) == "G") {
zAcn[ind + 6] = z_data.rhs.args[0];
}
//increment index according to no of items pr condition
ind += static_cast<std::size_t>(noEPZacn);
}
}
} // zAcn
}
namespace iACN {
Opm::RestartIO::Helpers::WindowedArray<int>
allocate(const std::vector<int>& actDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<int>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(actDims[0]) },
WV::WindowSize{ static_cast<std::size_t>(actDims[6]) }
};
}
template <class IACNArray>
void staticContrib(const Opm::Action::ActionX& actx, IACNArray& iAcn)
{
//item [0 - 9]: are unknown, (=0)
/*item [10] type of quantity for condition
1 for a field quantity (number of flowing producing wells)
2 for a well quantity
3 for a (node) group quantity
//9 for a well group quantity
10 for DAY
11 for MNTH
12 for YEAR
*/
std::size_t ind = 0;
int noEPZacn = 26;
// write out the schedule Actionx conditions
const auto& actx_cond = actx.conditions();
for (auto cond_it = actx_cond.begin(); cond_it < actx_cond.end(); cond_it++) {
auto z_data = *cond_it;
// left hand quantity
std::string lhsQtype = z_data.lhs.quantity.substr(0,1);
const auto it_lhsq = lhsQuantityToIndex.find(lhsQtype);
if (it_lhsq != lhsQuantityToIndex.end()) {
iAcn[ind + 10] = it_lhsq->second;
}
else {
std::cout << "Unknown condition type: " << z_data.lhs.quantity << std::endl;
throw std::invalid_argument("Actionx: " + actx.name());
}
/*item[11] - quantity type for rhs quantity
1 - for field variables
2 - for well variables?
3 - for group variables
8 - for constant values
*/
iAcn[ind + 11] = 8;
std::string rhsQtype = z_data.rhs.quantity.substr(0,1);
const auto it_rhsq = rhsQuantityToIndex.find(rhsQtype);
if (it_rhsq != rhsQuantityToIndex.end()) {
iAcn[ind + 11] = it_rhsq->second;
}
/*item[12] - index for lhs type
1 - for MNTH
0 - for all other types
*/
std::string lhsQ = z_data.lhs.quantity;
if ( lhsQ == "MNTH") {
iAcn[ind + 12] = 1;
}
/*item [13] - relates to operator
OR is 2
AND is 1
*/
const auto it_logic_13 = logicalToIndex_13.find(z_data.logic);
if (it_logic_13 != logicalToIndex_13.end()) {
iAcn[ind + 13] = it_logic_13->second;
}
else {
std::cout << "Unknown Boolean operator type for condition: " << z_data.lhs.quantity << std::endl;
throw std::invalid_argument("Actionx: " + actx.name());
}
/*item [16] - related to the operater used in ACTIONX for defined quantities
> is 1
< is 2
>= is 3
<= is 4
= is 5
*/
const auto it_cmp = cmpToIndex.find(z_data.cmp);
if (it_cmp != cmpToIndex.end()) {
iAcn[ind + 16] = it_cmp->second;
}
else {
std::cout << "Unknown operator type for condition: " << z_data.lhs.quantity << std::endl;
throw std::invalid_argument("Actionx: " + actx.name());
}
/*item [17] - relates to operator and if the right hand condition is a constant or not
* First condition => [17] = 0
* Second+ conditions
*If the previous condition has a constant rhs => [17] = 0
*If rhs is {W,G, F} and
*If previous condition is AND => [17] = 1
*If previous condition is OR => [17] = 0
*/
if (cond_it > actx_cond.begin()) {
const std::string prev_rhs_quant = (cond_it-1)->rhs.quantity.substr(0,1);
const auto it_prev_rhs = rhsQuantityToIndex.find(prev_rhs_quant);
if (it_prev_rhs != rhsQuantityToIndex.end()) {
const auto it_logic_17 = logicalToIndex_17.find((cond_it-1)->logic);
if (it_logic_17 != logicalToIndex_17.end()) {
iAcn[ind + 17] = it_logic_17->second;
}
else {
std::cout << "Unknown Boolean operator type for condition: " << z_data.lhs.quantity << std::endl;
throw std::invalid_argument("Actionx: " + actx.name());
}
}
}
//increment index according to no of items pr condition
ind += static_cast<std::size_t>(noEPZacn);
}
}
} // iAcn
namespace sACN {
Opm::RestartIO::Helpers::WindowedArray<double>
allocate(const std::vector<int>& actDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<double>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(actDims[0]) },
WV::WindowSize{ static_cast<std::size_t>(actDims[7]) }
};
}
template <class SACNArray>
void staticContrib(const Opm::Action::ActionX& actx,
const Opm::SummaryState& st,
SACNArray& sAcn)
{
std::size_t ind = 0;
int noEPZacn = 16;
double undef_high_val = 1.0E+20;
// write out the schedule Actionx conditions
const auto& actx_cond = actx.conditions();
for (const auto& z_data : actx_cond) {
// item [0 - 1] = 0 (unknown)
sAcn[ind + 0] = 0.;
sAcn[ind + 1] = 0.;
//item [2, 5, 7, 9]: value of condition 1 (zero if well, group or field variable
const std::string& rhsQtype = z_data.rhs.quantity.substr(0,1);
const auto& it_rhsq = rhsQuantityToIndex.find(rhsQtype);
if (it_rhsq == rhsQuantityToIndex.end()) {
//come here if constant value condition
double t_val = 0.;
if (rhsQtype == "M") {
const auto& it_mnth = monthToNo.find(z_data.rhs.quantity);
if (it_mnth != monthToNo.end()) {
t_val = it_mnth->second;
}
else {
std::cout << "Unknown Month: " << z_data.rhs.quantity << std::endl;
throw std::invalid_argument("Actionx: " + actx.name() + " Condition: " + z_data.lhs.quantity );
}
}
else {
t_val = std::stod(z_data.rhs.quantity);
}
sAcn[ind + 2] = t_val;
sAcn[ind + 5] = sAcn[ind + 2];
sAcn[ind + 7] = sAcn[ind + 2];
sAcn[ind + 9] = sAcn[ind + 2];
}
//Treat well, group and field right hand side conditions
if (it_rhsq != rhsQuantityToIndex.end()) {
//Well variable
if (it_rhsq->first == "W") {
sAcn[ind + 4] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity);
sAcn[ind + 5] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity);
sAcn[ind + 6] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity);
sAcn[ind + 7] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity);
sAcn[ind + 8] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity);
sAcn[ind + 9] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity);
}
//group variable
if (it_rhsq->first == "G") {
sAcn[ind + 4] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity);
sAcn[ind + 5] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity);
sAcn[ind + 6] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity);
sAcn[ind + 7] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity);
sAcn[ind + 8] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity);
sAcn[ind + 9] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity);
}
//field variable
if (it_rhsq->first == "F") {
sAcn[ind + 4] = st.get(z_data.rhs.quantity);
sAcn[ind + 5] = st.get(z_data.rhs.quantity);
sAcn[ind + 6] = st.get(z_data.rhs.quantity);
sAcn[ind + 7] = st.get(z_data.rhs.quantity);
sAcn[ind + 8] = st.get(z_data.rhs.quantity);
sAcn[ind + 9] = st.get(z_data.rhs.quantity);
}
}
//treat cases with left hand side condition being: DAY, MNTH og YEAR variable
const std::string& lhsQtype = z_data.lhs.quantity.substr(0,1);
const auto& it_lhsq = lhsQuantityToIndex.find(lhsQtype);
if ((it_lhsq->first == "D") || (it_lhsq->first == "M") || (it_lhsq->first == "Y")) {
sAcn[ind + 4] = undef_high_val;
sAcn[ind + 5] = undef_high_val;
sAcn[ind + 6] = undef_high_val;
sAcn[ind + 7] = undef_high_val;
sAcn[ind + 8] = undef_high_val;
sAcn[ind + 9] = undef_high_val;
}
//increment index according to no of items pr condition
ind += static_cast<std::size_t>(noEPZacn);
}
}
} // sAcn
// =====================================================================
Opm::RestartIO::Helpers::AggregateActionxData::
AggregateActionxData(const std::vector<int>& actDims)
: iACT_ (iACT::allocate(actDims)),
sACT_ (sACT::allocate(actDims)),
zACT_ (zACT::allocate(actDims)),
zLACT_(zLACT::allocate(actDims)),
zACN_ (zACN::allocate(actDims)),
iACN_ (iACN::allocate(actDims)),
sACN_ (sACN::allocate(actDims))
{}
// ---------------------------------------------------------------------
void
Opm::RestartIO::Helpers::AggregateActionxData::
captureDeclaredActionxData( const Opm::Schedule& sched,
const Opm::SummaryState& st,
const std::vector<int>& actDims,
const std::size_t simStep)
{
auto acts = sched.actions(simStep);
std::size_t act_ind = 0;
for (auto actx_it = acts.begin(); actx_it < acts.end(); actx_it++) {
{
auto i_act = this->iACT_[act_ind];
iACT::staticContrib(*actx_it, i_act);
}
{
auto s_act = this->sACT_[act_ind];
sACT::staticContrib(s_act);
}
{
auto z_act = this->zACT_[act_ind];
zACT::staticContrib(*actx_it, z_act);
}
{
auto z_lact = this->zLACT_[act_ind];
zLACT::staticContrib(*actx_it, actDims[8], z_lact);
}
{
auto z_acn = this->zACN_[act_ind];
zACN::staticContrib(*actx_it, z_acn);
}
{
auto i_acn = this->iACN_[act_ind];
iACN::staticContrib(*actx_it, i_acn);
}
{
auto s_acn = this->sACN_[act_ind];
sACN::staticContrib(*actx_it, st, s_acn);
}
act_ind +=1;
}
}

View File

@@ -0,0 +1,139 @@
/*
Copyright (c) 2018 Equinor ASA
Copyright (c) 2018 Statoil 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/output/eclipse/AggregateUDQData.hpp>
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
#include <opm/output/eclipse/InteHEAD.hpp>
#include <opm/output/eclipse/DoubHEAD.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Action/ActionX.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
#include <opm/parser/eclipse/Units/Units.hpp>
#include <chrono>
#include <cstddef>
#include <vector>
namespace {
// The number of actions (no of Actionx)
std::size_t noOfActions(const Opm::Action::Actions& acts)
{
std::size_t no_entries = acts.size();
return no_entries;
}
std::size_t entriesPerIACT()
{
std::size_t no_entries = 9;
return no_entries;
}
std::size_t entriesPerSACT()
{
std::size_t no_entries = 5;
return no_entries;
}
std::size_t entriesPerZACT()
{
std::size_t no_entries = 4;
return no_entries;
}
// (The max number of characters in an action statement / (8 - chars pr string)) * (max over actions of number of lines pr ACTIONX)
std::size_t entriesPerZLACT(const Opm::Runspec& rspec, const Opm::Action::Actions& acts)
{
int max_char_pr_line = rspec.actdims().max_characters();
std::size_t no_entries_pr_line = ((max_char_pr_line % 8) == 0) ? max_char_pr_line / 8 : (max_char_pr_line / 8) + 1;
std::size_t no_entries = no_entries_pr_line * acts.max_input_lines();
return no_entries;
}
// The max number of characters in an action statement * (max over actions of number of lines pr ACTIONX) / (8 - chars pr string)
std::size_t entriesPerLine(const Opm::Runspec& rspec)
{
int max_char_pr_line = rspec.actdims().max_characters();
std::size_t no_entries_pr_line = ((max_char_pr_line % 8) == 0) ? max_char_pr_line / 8 : (max_char_pr_line / 8) + 1;
return no_entries_pr_line;
}
std::size_t entriesPerZACN(const Opm::Runspec& rspec)
{
//(Max number of conditions pr ACTIONX) * ((max no characters pr line = 104) / (8 - characters pr string)(104/8 = 13)
std::size_t no_entries = rspec.actdims().max_conditions() * 13;
return no_entries;
}
std::size_t entriesPerIACN(const Opm::Runspec& rspec)
{
//26*Max number of conditions pr ACTIONX
std::size_t no_entries = 26 * rspec.actdims().max_conditions();
return no_entries;
}
std::size_t entriesPerSACN(const Opm::Runspec& rspec)
{
//16
std::size_t no_entries = 16 * rspec.actdims().max_conditions();
return no_entries;
}
} // Anonymous
// #####################################################################
// Public Interface (createUdqDims()) Below Separator
// ---------------------------------------------------------------------
std::vector<int>
Opm::RestartIO::Helpers::
createActionxDims( const Runspec& rspec,
const Schedule& sched,
const std::size_t simStep)
{
const auto& acts = sched.actions(simStep);
std::vector<int> actDims(9);
//No of Actionx keywords
actDims[0] = noOfActions(acts);
actDims[1] = entriesPerIACT();
actDims[2] = entriesPerSACT();
actDims[3] = entriesPerZACT();
actDims[4] = entriesPerZLACT(rspec, acts);
actDims[5] = entriesPerZACN(rspec);
actDims[6] = entriesPerIACN(rspec);
actDims[7] = entriesPerSACN(rspec);
actDims[8] = entriesPerLine(rspec);
return actDims;
}

View File

@@ -27,6 +27,9 @@
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ArrayDimChecker.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Action/Actions.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Action/ActionX.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/Regdims.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
@@ -186,14 +189,27 @@ namespace {
};
}
/*Opm::RestartIO::InteHEAD::UdqParam
getRandSeedPar(const ::Opm::Runspec& rspec)
Opm::RestartIO::InteHEAD::UdqParam
getUdqParam(const ::Opm::Runspec& rspec, const ::Opm::UDQConfig& udqcfg )
{
const auto& udq_par = rspec.udqParams();
const auto r_seed = udq_par.rand_seed();
const auto no_udq = udqcfg.size();
return { r_seed};
}*/
return { r_seed, static_cast<int>(no_udq)};
}
Opm::RestartIO::InteHEAD::ActionParam
getActionParam(const ::Opm::Runspec& rspec, const ::Opm::Action::Actions& acts )
{
const auto& no_act = acts.size();
const auto max_lines_pr_action = acts.max_input_lines();
const auto max_cond_per_action = rspec.actdims().max_conditions();
const auto max_characters_per_line = rspec.actdims().max_characters();
return { static_cast<int>(no_act), max_lines_pr_action, static_cast<int>(max_cond_per_action), static_cast<int>(max_characters_per_line)};
}
Opm::RestartIO::InteHEAD::WellSegDims
getWellSegDims(const ::Opm::Runspec& rspec,
@@ -264,6 +280,8 @@ createInteHead(const EclipseState& es,
{
const auto nwgmax = maxGroupSize(sched, lookup_step);
const auto ngmax = numGroupsInField(sched, lookup_step);
const auto& udqCfg = sched.getUDQConfig(lookup_step);
const auto& acts = sched.actions(lookup_step);
const auto& rspec = es.runspec();
const auto& tdim = es.getTableManager();
const auto& rdim = tdim.getRegdims();
@@ -292,7 +310,8 @@ createInteHead(const EclipseState& es,
.regionDimensions (getRegDims(tdim, rdim))
.ngroups ({ ngmax })
.variousParam (201702, 100) // Output should be compatible with Eclipse 100, 2017.02 version.
//.udqParam_1 (getRandSeedPar(rspec))
//.udqParam_1 (getUdqParam(rspec, udqCfg))
//.actionParam (getActionParam(rspec, acts))
;
return ih.data();

View File

@@ -175,9 +175,9 @@ enum index : std::vector<int>::size_type {
ih_153 = 153 , // 0 0
ih_154 = 154 , // 0 0
ih_155 = 155 , // 0 0
ih_156 = 156 , // 0 0
ih_157 = 157 , // 0 0
ih_158 = 158 , // 0 0
NO_ACT = VI::intehead::NOOFACTIONS, // 0 0
MAX_LINES = VI::intehead::MAXNOLINES, // 0 0
MAXSPRLINE = VI::intehead::MAXNOSTRPRLINE, // 0 0
ih_159 = 159 , // 0 0
ih_160 = 160 , // 0 0
ih_161 = 161 , // 0 0
@@ -264,7 +264,7 @@ enum index : std::vector<int>::size_type {
ih_242 = 242 , // 0
ih_243 = 243 , // 0
ih_244 = 244 , // 0
ih_245 = 245 , // 0
MXACTC = VI::intehead::MAX_ACT_COND, // Max no of conditions pr action
ih_246 = 246 , // 0
ih_247 = 247 , // 0
ih_248 = 248 , // 0
@@ -285,8 +285,8 @@ enum index : std::vector<int>::size_type {
ih_263 = 263 , // 0
ih_264 = 264 , // 0
ih_265 = 265 , // 0
ih_266 = 266 , // 0
UDQPAR_1 = VI::intehead::UDQPAR_1, // 0
NOUDQS = VI::intehead::NO_UDQS, // 0
UDQPAR_1 = VI::intehead::UDQPAR_1, // 0
ih_268 = 268 , // 0
ih_269 = 269 , // 0
ih_270 = 270 , // 0
@@ -315,7 +315,7 @@ enum index : std::vector<int>::size_type {
ih_293 = 293 , // 0
ih_294 = 294 , // 0
ih_295 = 295 , // 0
ih_296 = 296 , // 0
R_SEED = VI::intehead::RSEED, // 0
ih_297 = 297 , // 0
ih_298 = 298 , // 0
ih_299 = 299 , // 0
@@ -683,6 +683,21 @@ Opm::RestartIO::InteHEAD::
udqParam_1(const UdqParam& udq_par)
{
this -> data_[UDQPAR_1] = - udq_par.udqParam_1;
this -> data_[R_SEED] = - udq_par.udqParam_1;
this -> data_[NOUDQS] = udq_par.no_udqs;
return *this;
}
Opm::RestartIO::InteHEAD&
Opm::RestartIO::InteHEAD::
actionParam(const ActionParam& act_par)
{
this -> data_[NO_ACT] = act_par.no_actions;
this -> data_[MAX_LINES] = act_par.max_no_sched_lines_per_action;
this -> data_[MXACTC] = act_par.max_no_conditions_per_action;
this -> data_[MAXSPRLINE] = ((act_par.max_no_characters_per_line % 8) == 0) ? act_par.max_no_characters_per_line / 8 :
(act_par.max_no_characters_per_line / 8) + 1;
return *this;
}

View File

@@ -55,6 +55,14 @@ const ActionX& Actions::get(std::size_t index) const {
return this->actions[index];
}
int Actions::max_input_lines() const {
std::size_t max_il = 0;
for (const auto& act : this-> actions) {
if (act.keyword_strings().size() > max_il) max_il = act.keyword_strings().size() ;
}
return static_cast<int>(max_il);
}
bool Actions::ready(std::time_t sim_time) const {
for (const auto& action : this->actions) {