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
Pressure = 11, // Segment pressure
item31 = 30, // Very close to Normalised Water flow rate fraction - value used pr today
item40 = 39, // Unknown
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
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
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;
UDAControl control;
int uad_code;
std::string wg_name() const;
std::size_t use_count;
private:
// 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);
}
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;
cur_prod_ctrl = 0.;
}
@ -269,9 +266,6 @@ int higherLevelProdControlMode(const Opm::Schedule& sched,
cur_prod_ctrl = sumState.get(group_key);
}
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;
cur_prod_ctrl = 0.;
}
@ -313,9 +307,6 @@ int higherLevelInjControlGroupSeqIndex(const Opm::Schedule& sched,
cur_inj_ctrl = sumState.get(group_key);
}
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;
cur_inj_ctrl = 0.;
}
@ -353,9 +344,6 @@ int higherLevelInjControlMode(const Opm::Schedule& sched,
cur_inj_ctrl = sumState.get(group_key);
}
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;
cur_inj_ctrl = 0.;
}
@ -519,6 +507,33 @@ void staticContrib(const Opm::Schedule& sched,
// location nwgmax
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
if ((group.getGroupType() == Opm::Group::GroupType::NONE) || (group.getGroupType() == Opm::Group::GroupType::PRODUCTION)
|| (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& p_exceed_act = group.productionControls(sumState).exceed_action;
// Find production control mode for group
std::string group_key_1;
group_key_1 = gf_key("GMCTP", group.name());
double cur_prod_ctrl = -1.;
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());
}
// 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]
- 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)
@ -762,15 +748,6 @@ void staticContrib(const Opm::Schedule& sched,
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 -
iGrp[nwgmax + 17] = -1;
@ -800,9 +777,6 @@ void staticContrib(const Opm::Schedule& sched,
}
}
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;
}
if (group.name() != "FIELD") {
@ -900,9 +874,6 @@ void staticContrib(const Opm::Schedule& sched,
}
}
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;
}
@ -1109,12 +1080,10 @@ void staticContrib(const Opm::Group& group,
if (prod_cntl.oil_target > 0.) {
sGrp[Isp::OilRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.oil_target);
//sGrp[37] = sGrp[Isp::OilRateLimit];
sGrp[52] = sGrp[Isp::OilRateLimit]; // "ORAT" control
}
if (prod_cntl.water_target > 0.) {
sGrp[Isp::WatRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.water_target);
//sGrp[38] = sGrp[Isp::WatRateLimit];
sGrp[53] = sGrp[Isp::WatRateLimit]; //"WRAT" control
}
if (prod_cntl.gas_target > 0.) {
@ -1123,7 +1092,6 @@ void staticContrib(const Opm::Group& group,
}
if (prod_cntl.liquid_target > 0.) {
sGrp[Isp::LiqRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.liquid_target);
//sGrp[40] = sGrp[Isp::LiqRateLimit];
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::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
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::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::item106] = 1.0;

View File

@ -64,11 +64,10 @@ namespace {
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 type = -4;
std::vector <Opm::UDQTokenType> type_1 = {
std::vector <Opm::UDQTokenType> type_1 = {
Opm::UDQTokenType::elemental_func_sorta,
Opm::UDQTokenType::elemental_func_sortd,
Opm::UDQTokenType::elemental_func_undef,
@ -77,18 +76,17 @@ namespace {
Opm::UDQTokenType::scalar_func_aveg,
Opm::UDQTokenType::scalar_func_aveh,
Opm::UDQTokenType::scalar_func_max,
Opm::UDQTokenType::scalar_func_min,
Opm::UDQTokenType::scalar_func_min,
Opm::UDQTokenType::binary_op_div
};
int num_type_1 = 0;
for (const auto& tok_type : type_1) {
num_type_1 += tokens.count(tok_type);
}
}
type = (num_type_1 > 0) ? -1 : -4;
return type;
}
namespace iUdq {
@ -134,7 +132,7 @@ namespace {
}
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[1] = udq_record.input_index + 1;
@ -143,7 +141,7 @@ namespace {
iUad[2] = 1;
iUad[3] = udq_record.use_count;
iUad[4] = udq_record.use_index + 1;
iUad[4] = udq_record.use_index + 1 - use_cnt_diff;
}
} // 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)) {
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 {
std::cout << "Invalid Control keyword: " << static_cast<int>(ctrl) << std::endl;
@ -511,9 +511,14 @@ captureDeclaredUDQData(const Opm::Schedule& sched,
int cnt_iuad = 0;
for (std::size_t index = 0; index < udq_records.size(); index++) {
const auto& record = udq_records[index];
auto i_uad = this->iUAD_[index];
iUad::staticContrib(record, i_uad);
cnt_iuad += 1;
auto i_uad = this->iUAD_[cnt_iuad];
const auto& ctrl = record.control;
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]) {
std::stringstream str;

View File

@ -29,6 +29,7 @@
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.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/Units/UnitSystem.hpp>
#include <opm/parser/eclipse/Units/Units.hpp>
@ -496,6 +497,11 @@ namespace {
: swprop(M::pressure, 1.0*::Opm::unit::atm);
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 (well.getStatus() == Opm::Well::Status::OPEN) {
sWell[Ix::OilRateTarget] = getRateLimit(units, M::liquid_surface_rate, pc.oil_rate);
@ -903,7 +909,7 @@ captureDeclaredWellData(const Schedule& sched,
void
Opm::RestartIO::Helpers::AggregateWellData::
captureDynamicWellData(const Schedule& sched,
captureDynamicWellData(const Opm::Schedule& sched,
const std::size_t sim_step,
const Opm::data::WellRates& xw,
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); });
}
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,
const std::size_t rptStep,
const std::size_t simStep)
@ -288,8 +321,8 @@ namespace {
const auto no_wudq = noWellUdqs(sched, rptStep, simStep);
const auto no_gudq = noGroupUdqs(sched, rptStep, simStep);
const auto no_fudq = noFieldUdqs(sched, rptStep, simStep);
const auto no_iuads = udqActive.IUAD_size();
const auto no_iuaps = udqActive.IUAP_size();
const auto no_iuads = noIuads(sched, rptStep, simStep);
const auto no_iuaps = noIuaps(sched, rptStep, simStep);
return {
r_seed,

View File

@ -50,6 +50,11 @@ UDQActive::operator bool() const {
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) {
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);
}
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()) {
for (std::size_t index = 1; index < output_data.size(); index++) {
const auto& prev_record = this->output_data[index - 1];