correction for lift quantity well-data

corrections to IUAD and IUAP

various improvements of E100 compatible restart file

add debug output

additonal debug print

corrected loop placement for active prod/inj wells

remove debug print and clean up code
This commit is contained in:
Jostein Alvestad 2020-05-15 08:43:32 +02:00
parent 985cb279ff
commit ec976db684
9 changed files with 101 additions and 79 deletions

View File

@ -55,6 +55,8 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
GasFlowFract = 10, // Normalised Gas flow rate fraction GasFlowFract = 10, // Normalised Gas flow rate fraction
Pressure = 11, // Segment pressure Pressure = 11, // Segment pressure
item31 = 30, // Very close to Normalised Water flow rate fraction - value used pr today
item40 = 39, // Unknown item40 = 39, // Unknown
ValveLength = 40, // Length of valve ValveLength = 40, // Length of valve

View File

@ -113,6 +113,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
BHPTarget = 6, // Well's bottom hole pressure target BHPTarget = 6, // Well's bottom hole pressure target
DatumDepth = 9, // Well's reference depth for BHP DatumDepth = 9, // Well's reference depth for BHP
Alq_value = 10, // Well's artificial lift quantity
DrainageRadius = 17, // Well's drainage radius - item 7 from WELSPECS DrainageRadius = 17, // Well's drainage radius - item 7 from WELSPECS
EfficiencyFactor1 = 24, // Item2 from WEFAC; this value is repeated at two locations. EfficiencyFactor1 = 24, // Item2 from WEFAC; this value is repeated at two locations.

View File

@ -87,6 +87,7 @@ public:
std::size_t use_index = 0; std::size_t use_index = 0;
UDAControl control; UDAControl control;
int uad_code; int uad_code;
std::string wg_name() const;
std::size_t use_count; std::size_t use_count;
private: private:
// The wgname is need in the update process, but it should // The wgname is need in the update process, but it should

View File

@ -230,9 +230,6 @@ int higherLevelProdControlGroupSeqIndex(const Opm::Schedule& sched,
cur_prod_ctrl = sumState.get(group_key); cur_prod_ctrl = sumState.get(group_key);
} }
else { else {
//std::stringstream str;
//str << "Current group control is not defined for group: " << current.name() << " at timestep: " << simStep;
//throw std::invalid_argument(str.str());
std::cout << "Current group control is not defined for group: " << current.name() << " at timestep: " << simStep << std::endl; std::cout << "Current group control is not defined for group: " << current.name() << " at timestep: " << simStep << std::endl;
cur_prod_ctrl = 0.; cur_prod_ctrl = 0.;
} }
@ -269,9 +266,6 @@ int higherLevelProdControlMode(const Opm::Schedule& sched,
cur_prod_ctrl = sumState.get(group_key); cur_prod_ctrl = sumState.get(group_key);
} }
else { else {
//std::stringstream str;
//str << "Current group control is not defined for group: " << current.name() << " at timestep: " << simStep;
//throw std::invalid_argument(str.str());
std::cout << "Current group control is not defined for group: " << current.name() << " at timestep: " << simStep << std::endl; std::cout << "Current group control is not defined for group: " << current.name() << " at timestep: " << simStep << std::endl;
cur_prod_ctrl = 0.; cur_prod_ctrl = 0.;
} }
@ -313,9 +307,6 @@ int higherLevelInjControlGroupSeqIndex(const Opm::Schedule& sched,
cur_inj_ctrl = sumState.get(group_key); cur_inj_ctrl = sumState.get(group_key);
} }
else { else {
//std::stringstream str;
//str << "Current injection group control: " << curInjCtrlKey << " is not defined for group: " << current.name() << " at timestep: " << simStep;
//throw std::invalid_argument(str.str());
std::cout << "Current injection group control: " << curInjCtrlKey << " is not defined for group: " << current.name() << " at timestep: " << simStep << std::endl; std::cout << "Current injection group control: " << curInjCtrlKey << " is not defined for group: " << current.name() << " at timestep: " << simStep << std::endl;
cur_inj_ctrl = 0.; cur_inj_ctrl = 0.;
} }
@ -353,9 +344,6 @@ int higherLevelInjControlMode(const Opm::Schedule& sched,
cur_inj_ctrl = sumState.get(group_key); cur_inj_ctrl = sumState.get(group_key);
} }
else { else {
//std::stringstream str;
//str << "Current injection group control: " << curInjCtrlKey << " is not defined for group: " << current.name() << " at timestep: " << simStep;
//throw std::invalid_argument(str.str());
std::cout << "Current injection group control: " << curInjCtrlKey << " is not defined for group: " << current.name() << " at timestep: " << simStep << std::endl; std::cout << "Current injection group control: " << curInjCtrlKey << " is not defined for group: " << current.name() << " at timestep: " << simStep << std::endl;
cur_inj_ctrl = 0.; cur_inj_ctrl = 0.;
} }
@ -519,6 +507,33 @@ void staticContrib(const Opm::Schedule& sched,
// location nwgmax // location nwgmax
iGrp[nwgmax] = groupSize(group); iGrp[nwgmax] = groupSize(group);
// Find number of active production wells and injection wells for group
std::string group_key_1;
group_key_1 = gf_key("GMWPR", group.name());
double g_act_pwells = -1.;
if (sumState.has(group_key_1)) {
g_act_pwells = sumState.get(group_key_1);
}
else {
g_act_pwells = 0.;
}
group_key_1 = gf_key("GMWIN", group.name());
double g_act_iwells = -1.;
if (sumState.has(group_key_1)) {
g_act_iwells = sumState.get(group_key_1);
}
else {
g_act_iwells = 0.;
}
// set the number of active wells for a group
if (g_act_pwells >= 0 && g_act_iwells >= 0) {
iGrp[nwgmax + 33] = g_act_pwells + g_act_iwells;
}
else {
iGrp[nwgmax + 33] = 0;
}
//Treat groups that have production //Treat groups that have production
if ((group.getGroupType() == Opm::Group::GroupType::NONE) || (group.getGroupType() == Opm::Group::GroupType::PRODUCTION) if ((group.getGroupType() == Opm::Group::GroupType::NONE) || (group.getGroupType() == Opm::Group::GroupType::PRODUCTION)
|| (group.getGroupType() == Opm::Group::GroupType::MIXED)) { || (group.getGroupType() == Opm::Group::GroupType::MIXED)) {
@ -527,7 +542,6 @@ void staticContrib(const Opm::Schedule& sched,
const auto& prod_guide_rate_def = group.productionControls(sumState).guide_rate_def; const auto& prod_guide_rate_def = group.productionControls(sumState).guide_rate_def;
const auto& p_exceed_act = group.productionControls(sumState).exceed_action; const auto& p_exceed_act = group.productionControls(sumState).exceed_action;
// Find production control mode for group // Find production control mode for group
std::string group_key_1;
group_key_1 = gf_key("GMCTP", group.name()); group_key_1 = gf_key("GMCTP", group.name());
double cur_prod_ctrl = -1.; double cur_prod_ctrl = -1.;
Opm::Group::ProductionCMode pctl_mode = Opm::Group::ProductionCMode::NONE; Opm::Group::ProductionCMode pctl_mode = Opm::Group::ProductionCMode::NONE;
@ -545,34 +559,6 @@ void staticContrib(const Opm::Schedule& sched,
//throw std::invalid_argument(str.str()); //throw std::invalid_argument(str.str());
} }
// Find number of active production wells and injection wells for group
group_key_1 = gf_key("GMWPR", group.name());
double g_act_pwells = -1.;
if (sumState.has(group_key_1)) {
g_act_pwells = sumState.get(group_key_1);
}
else {
//std::stringstream str;
//str << "Number of flowing production wells is not defined for group: " << group.name() << " at timestep: " << simStep;
//throw std::invalid_argument(str.str());
std::cout << "Number of flowing production wells is not defined for group: " << group.name() << " at timestep: " << simStep << std::endl;
g_act_pwells = 0.;
}
group_key_1 = gf_key("GMWIN", group.name());
double g_act_iwells = -1.;
if (sumState.has(group_key_1)) {
g_act_iwells = sumState.get(group_key_1);
}
else {
//std::stringstream str;
//str << "Number of flowing injection wells is not defined for group: " << group.name() << " at timestep: " << simStep;
//throw std::invalid_argument(str.str());
std::cout << "Number of flowing injection wells is not defined for group: " << group.name() << " at timestep: " << simStep << std::endl;
g_act_iwells = 0.;
}
/*IGRP[NWGMAX + 5] /*IGRP[NWGMAX + 5]
- the value is determined by a relatively complex logic, a pseudo code scetch follows: - the value is determined by a relatively complex logic, a pseudo code scetch follows:
if (group is free to respond to higher level production rate target_reinj_fraction) if (group is free to respond to higher level production rate target_reinj_fraction)
@ -762,15 +748,6 @@ void staticContrib(const Opm::Schedule& sched,
iGrp[nwgmax + 10] = 0; iGrp[nwgmax + 10] = 0;
} }
} }
// set the number of active wells for a group
if (g_act_pwells >= 0 && g_act_iwells >= 0) {
iGrp[nwgmax + 33] = g_act_pwells + g_act_iwells;
}
else {
iGrp[nwgmax + 33] = 0;
}
} }
//default value - //default value -
iGrp[nwgmax + 17] = -1; iGrp[nwgmax + 17] = -1;
@ -800,9 +777,6 @@ void staticContrib(const Opm::Schedule& sched,
} }
} }
else { else {
//std::stringstream str;
//str << "Current group water injection control is not defined for group: " << group.name() << " at timestep: " << simStep;
//throw std::invalid_argument(str.str());
std::cout << "Current group water injection control is not defined for group: " << group.name() << " at timestep: " << simStep << std::endl; std::cout << "Current group water injection control is not defined for group: " << group.name() << " at timestep: " << simStep << std::endl;
} }
if (group.name() != "FIELD") { if (group.name() != "FIELD") {
@ -900,9 +874,6 @@ void staticContrib(const Opm::Schedule& sched,
} }
} }
else { else {
//std::stringstream str;
//str << "Current group gas injection control is not defined for group: " << group.name() << " at timestep: " << simStep;
//throw std::invalid_argument(str.str());
std::cout << "Current group gas injection control is not defined for group: " << group.name() << " at timestep: " << simStep << std::endl; std::cout << "Current group gas injection control is not defined for group: " << group.name() << " at timestep: " << simStep << std::endl;
} }
@ -1109,12 +1080,10 @@ void staticContrib(const Opm::Group& group,
if (prod_cntl.oil_target > 0.) { if (prod_cntl.oil_target > 0.) {
sGrp[Isp::OilRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.oil_target); sGrp[Isp::OilRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.oil_target);
//sGrp[37] = sGrp[Isp::OilRateLimit];
sGrp[52] = sGrp[Isp::OilRateLimit]; // "ORAT" control sGrp[52] = sGrp[Isp::OilRateLimit]; // "ORAT" control
} }
if (prod_cntl.water_target > 0.) { if (prod_cntl.water_target > 0.) {
sGrp[Isp::WatRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.water_target); sGrp[Isp::WatRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.water_target);
//sGrp[38] = sGrp[Isp::WatRateLimit];
sGrp[53] = sGrp[Isp::WatRateLimit]; //"WRAT" control sGrp[53] = sGrp[Isp::WatRateLimit]; //"WRAT" control
} }
if (prod_cntl.gas_target > 0.) { if (prod_cntl.gas_target > 0.) {
@ -1123,7 +1092,6 @@ void staticContrib(const Opm::Group& group,
} }
if (prod_cntl.liquid_target > 0.) { if (prod_cntl.liquid_target > 0.) {
sGrp[Isp::LiqRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.liquid_target); sGrp[Isp::LiqRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.liquid_target);
//sGrp[40] = sGrp[Isp::LiqRateLimit];
sGrp[54] = sGrp[Isp::LiqRateLimit]; //"LRAT" control sGrp[54] = sGrp[Isp::LiqRateLimit]; //"LRAT" control
} }
} }

View File

@ -698,6 +698,9 @@ namespace {
rSeg[iS + Ix::WatFlowFract] = (std::abs(temp_w) > 0) ? temp_w / rSeg[8] : 0.; rSeg[iS + Ix::WatFlowFract] = (std::abs(temp_w) > 0) ? temp_w / rSeg[8] : 0.;
rSeg[iS + Ix::GasFlowFract] = (std::abs(temp_g) > 0) ? temp_g / rSeg[8] : 0.; rSeg[iS + Ix::GasFlowFract] = (std::abs(temp_g) > 0) ? temp_g / rSeg[8] : 0.;
rSeg[iS + Ix::item31] = rSeg[iS + Ix::WatFlowFract];
// value is 1. based on tests on several data sets // value is 1. based on tests on several data sets
rSeg[iS + Ix::item40] = 1.; rSeg[iS + Ix::item40] = 1.;
@ -751,6 +754,8 @@ namespace {
rSeg[iS + Ix::WatFlowFract] = (std::abs(temp_w) > 0) ? temp_w / rSeg[iS + 8] : 0.; rSeg[iS + Ix::WatFlowFract] = (std::abs(temp_w) > 0) ? temp_w / rSeg[iS + 8] : 0.;
rSeg[iS + Ix::GasFlowFract] = (std::abs(temp_g) > 0) ? temp_g / rSeg[iS + 8] : 0.; rSeg[iS + Ix::GasFlowFract] = (std::abs(temp_g) > 0) ? temp_g / rSeg[iS + 8] : 0.;
rSeg[iS + Ix::item31] = rSeg[iS + Ix::WatFlowFract];
rSeg[iS + Ix::item40] = 1.; rSeg[iS + Ix::item40] = 1.;
rSeg[iS + Ix::item106] = 1.0; rSeg[iS + Ix::item106] = 1.0;

View File

@ -64,8 +64,7 @@ namespace {
return inteHead[163]; return inteHead[163];
} }
// Categorize function in terms of which token-types are used in formula
// Categorize function in terms of which token-types are used in formula
int define_type(const std::set<Opm::UDQTokenType> tokens) { int define_type(const std::set<Opm::UDQTokenType> tokens) {
int type = -4; int type = -4;
std::vector <Opm::UDQTokenType> type_1 = { std::vector <Opm::UDQTokenType> type_1 = {
@ -89,7 +88,6 @@ namespace {
return type; return type;
} }
namespace iUdq { namespace iUdq {
Opm::RestartIO::Helpers::WindowedArray<int> Opm::RestartIO::Helpers::WindowedArray<int>
@ -134,7 +132,7 @@ namespace {
} }
template <class IUADArray> template <class IUADArray>
void staticContrib(const Opm::UDQActive::Record& udq_record, IUADArray& iUad) void staticContrib(const Opm::UDQActive::Record& udq_record, IUADArray& iUad, int use_cnt_diff)
{ {
iUad[0] = udq_record.uad_code; iUad[0] = udq_record.uad_code;
iUad[1] = udq_record.input_index + 1; iUad[1] = udq_record.input_index + 1;
@ -143,7 +141,7 @@ namespace {
iUad[2] = 1; iUad[2] = 1;
iUad[3] = udq_record.use_count; iUad[3] = udq_record.use_count;
iUad[4] = udq_record.use_index + 1; iUad[4] = udq_record.use_index + 1 - use_cnt_diff;
} }
} // iUad } // iUad
@ -445,7 +443,9 @@ const std::vector<int> iuap_data(const Opm::Schedule& sched,
} }
else if ((wg_key == Opm::UDAKeyword::GCONPROD) || (wg_key == Opm::UDAKeyword::GCONINJE)) { else if ((wg_key == Opm::UDAKeyword::GCONPROD) || (wg_key == Opm::UDAKeyword::GCONINJE)) {
const auto& group = sched.getGroup(iuap[ind].wgname, simStep); const auto& group = sched.getGroup(iuap[ind].wgname, simStep);
wg_no.push_back(group.insert_index() - 1); if (iuap[ind].wgname != "FIELD") {
wg_no.push_back(group.insert_index() - 1);
}
} }
else { else {
std::cout << "Invalid Control keyword: " << static_cast<int>(ctrl) << std::endl; std::cout << "Invalid Control keyword: " << static_cast<int>(ctrl) << std::endl;
@ -511,9 +511,14 @@ captureDeclaredUDQData(const Opm::Schedule& sched,
int cnt_iuad = 0; int cnt_iuad = 0;
for (std::size_t index = 0; index < udq_records.size(); index++) { for (std::size_t index = 0; index < udq_records.size(); index++) {
const auto& record = udq_records[index]; const auto& record = udq_records[index];
auto i_uad = this->iUAD_[index]; auto i_uad = this->iUAD_[cnt_iuad];
iUad::staticContrib(record, i_uad); const auto& ctrl = record.control;
cnt_iuad += 1; const auto wg_key = Opm::UDQ::keyword(ctrl);
if (!(((wg_key == Opm::UDAKeyword::GCONPROD) || (wg_key == Opm::UDAKeyword::GCONINJE)) && (record.wg_name() == "FIELD"))) {
int use_count_diff = static_cast<int>(index) - cnt_iuad;
iUad::staticContrib(record, i_uad, use_count_diff);
cnt_iuad += 1;
}
} }
if (cnt_iuad != inteHead[VI::intehead::NO_IUADS]) { if (cnt_iuad != inteHead[VI::intehead::NO_IUADS]) {
std::stringstream str; std::stringstream str;

View File

@ -29,6 +29,7 @@
#include <opm/parser/eclipse/EclipseState/Runspec.hpp> #include <opm/parser/eclipse/EclipseState/Runspec.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp> #include <opm/parser/eclipse/Units/UnitSystem.hpp>
#include <opm/parser/eclipse/Units/Units.hpp> #include <opm/parser/eclipse/Units/Units.hpp>
@ -496,6 +497,11 @@ namespace {
: swprop(M::pressure, 1.0*::Opm::unit::atm); : swprop(M::pressure, 1.0*::Opm::unit::atm);
sWell[Ix::HistBHPTarget] = sWell[Ix::BHPTarget]; sWell[Ix::HistBHPTarget] = sWell[Ix::BHPTarget];
//alq_value - has no unit conversion according to parser code
if (pc.alq_value != 0.0) {
sWell[Ix::Alq_value] = pc.alq_value;
}
if (predMode) { if (predMode) {
//if (well.getStatus() == Opm::Well::Status::OPEN) { //if (well.getStatus() == Opm::Well::Status::OPEN) {
sWell[Ix::OilRateTarget] = getRateLimit(units, M::liquid_surface_rate, pc.oil_rate); sWell[Ix::OilRateTarget] = getRateLimit(units, M::liquid_surface_rate, pc.oil_rate);
@ -903,7 +909,7 @@ captureDeclaredWellData(const Schedule& sched,
void void
Opm::RestartIO::Helpers::AggregateWellData:: Opm::RestartIO::Helpers::AggregateWellData::
captureDynamicWellData(const Schedule& sched, captureDynamicWellData(const Opm::Schedule& sched,
const std::size_t sim_step, const std::size_t sim_step,
const Opm::data::WellRates& xw, const Opm::data::WellRates& xw,
const ::Opm::SummaryState& smry) const ::Opm::SummaryState& smry)

View File

@ -154,6 +154,39 @@ namespace {
return std::count_if(input.begin(), input.end(), [](const Opm::UDQInput inp) { return (inp.var_type() == Opm::UDQVarType::GROUP_VAR); }); return std::count_if(input.begin(), input.end(), [](const Opm::UDQInput inp) { return (inp.var_type() == Opm::UDQVarType::GROUP_VAR); });
} }
int noIuads(const Opm::Schedule& sched,
const std::size_t rptStep,
const std::size_t simStep)
{
if (rptStep == std::size_t{0}) {
return 0;
}
const auto& udqAct = sched.udqActive(simStep);
const auto& iuad = udqAct.get_iuad();
return std::count_if(iuad.begin(), iuad.end(), [](const Opm::UDQActive::Record rec) {
return (!(((Opm::UDQ::keyword(rec.control) == Opm::UDAKeyword::GCONPROD) || (Opm::UDQ::keyword(rec.control) == Opm::UDAKeyword::GCONINJE))
&& (rec.wg_name() == "FIELD"))); });
}
int noIuaps(const Opm::Schedule& sched,
const std::size_t rptStep,
const std::size_t simStep)
{
if (rptStep == std::size_t{0}) {
return 0;
}
const auto& udqAct = sched.udqActive(simStep);
const auto& iuap = udqAct.get_iuap();
return std::count_if(iuap.begin(), iuap.end(), [](const Opm::UDQActive::InputRecord rec) {
return (!(((Opm::UDQ::keyword(rec.control) == Opm::UDAKeyword::GCONPROD) || (Opm::UDQ::keyword(rec.control) == Opm::UDAKeyword::GCONINJE))
&& (rec.wgname == "FIELD"))); });
}
int noFieldUdqs(const Opm::Schedule& sched, int noFieldUdqs(const Opm::Schedule& sched,
const std::size_t rptStep, const std::size_t rptStep,
const std::size_t simStep) const std::size_t simStep)
@ -288,8 +321,8 @@ namespace {
const auto no_wudq = noWellUdqs(sched, rptStep, simStep); const auto no_wudq = noWellUdqs(sched, rptStep, simStep);
const auto no_gudq = noGroupUdqs(sched, rptStep, simStep); const auto no_gudq = noGroupUdqs(sched, rptStep, simStep);
const auto no_fudq = noFieldUdqs(sched, rptStep, simStep); const auto no_fudq = noFieldUdqs(sched, rptStep, simStep);
const auto no_iuads = udqActive.IUAD_size(); const auto no_iuads = noIuads(sched, rptStep, simStep);
const auto no_iuaps = udqActive.IUAP_size(); const auto no_iuaps = noIuaps(sched, rptStep, simStep);
return { return {
r_seed, r_seed,

View File

@ -50,6 +50,11 @@ UDQActive::operator bool() const {
return this->input_data.size() > 0; return this->input_data.size() > 0;
} }
std::string UDQActive::Record::wg_name() const {
return this->wgname;
}
std::string UDQActive::udq_hash(const std::string& udq, UDAControl control) { std::string UDQActive::udq_hash(const std::string& udq, UDAControl control) {
return udq + std::to_string(static_cast<int64_t>(control)); return udq + std::to_string(static_cast<int64_t>(control));
} }
@ -144,10 +149,6 @@ const std::vector<UDQActive::Record>& UDQActive::get_iuad() const {
this->output_data.emplace_back(input_record.udq, input_record.input_index, 0, input_record.wgname, input_record.control); this->output_data.emplace_back(input_record.udq, input_record.input_index, 0, input_record.wgname, input_record.control);
} }
std::sort(this->output_data.begin(), this->output_data.end(),
[](const UDQActive::Record& rec1, const UDQActive::Record& rec2) { return rec1.input_index < rec2.input_index;});
if (!output_data.empty()) { if (!output_data.empty()) {
for (std::size_t index = 1; index < output_data.size(); index++) { for (std::size_t index = 1; index < output_data.size(); index++) {
const auto& prev_record = this->output_data[index - 1]; const auto& prev_record = this->output_data[index - 1];