Merge pull request #1134 from GitPaean/group_ebos

updating the group control limit for individual control wells
This commit is contained in:
Atgeirr Flø Rasmussen 2017-01-18 14:08:33 +01:00 committed by GitHub
commit 674d97c660
4 changed files with 143 additions and 10 deletions

View File

@ -282,7 +282,7 @@ namespace Opm
void WellCollection::updateWellTargets(const std::vector<double>& well_rates)
{
if ( !needUpdateWellTargets() ) {
if ( !needUpdateWellTargets() && groupTargetConverged(well_rates)) {
return;
}
@ -323,4 +323,17 @@ namespace Opm
return group_control_active_;
}
bool WellCollection::groupTargetConverged(const std::vector<double>& well_rates) const
{
// TODO: eventually, there should be only one root node
// TODO: we also need to check the injection target, while we have not done that.
for (const std::shared_ptr<WellsGroupInterface>& root_node : roots_) {
if ( !root_node->groupProdTargetConverged(well_rates) ) {
return false;
}
}
return true;
}
}

View File

@ -139,6 +139,13 @@ namespace Opm
/// Whether we have active group control
bool groupControlActive() const;
/// Whether the group target is converged
// It is considered converged if eitehr the group targets are matched or the group targets are not matched while the wells are
// running under their own limits so that they can not produce more
// It is considered not converged if the group targets are not matched while some of the wells are still running under group control
// The strategy may need to be adjusted when more complicated multi-layered group control situation applied, not sure about thatyet.
bool groupTargetConverged(const std::vector<double>& well_rates) const;
private:
// To account for the possibility of a forest
std::vector<std::shared_ptr<WellsGroupInterface> > roots_;

View File

@ -186,7 +186,7 @@ namespace Opm
return tot_rate;
}
double WellsGroupInterface::getTarget(ProductionSpecification::ControlMode mode)
double WellsGroupInterface::getTarget(ProductionSpecification::ControlMode mode) const
{
double target = -1.0;
switch (mode) {
@ -216,7 +216,7 @@ namespace Opm
return target;
}
double WellsGroupInterface::getTarget(InjectionSpecification::ControlMode mode)
double WellsGroupInterface::getTarget(InjectionSpecification::ControlMode mode) const
{
double target = -1.0;
switch (mode) {
@ -793,6 +793,18 @@ namespace Opm
const double children_guide_rate = children_[i]->productionGuideRate(true);
children_[i]->applyProdGroupControl(prod_mode, (children_guide_rate / my_guide_rate) * rate_for_group_control, true);
children_[i]->setTargetUpdated(true);
} else {
// for the well not under group control, we need to update their group control limit
// to provide a mechanism for the well to return to group control
// putting its own rate back to the rate_for_group_control for redistribution
const double rate = std::abs(children_[i]->getProductionRate(well_rates, prod_mode) * children_[i]->efficiencyFactor());
const double temp_rate_for_group_control = rate_for_group_control + rate;
// TODO: the following might not be the correct thing to do for mutliple-layer group
const double children_guide_rate = children_[i]->productionGuideRate(false);
const double temp_my_guide_rate = my_guide_rate + children_guide_rate;
children_[i]->applyProdGroupControl(prod_mode, (children_guide_rate / temp_my_guide_rate) * temp_rate_for_group_control, false);
children_[i]->setTargetUpdated(true);
}
}
}
@ -808,12 +820,76 @@ namespace Opm
// do nothing
}
bool WellsGroup::canProduceMore() const
{
for (const std::shared_ptr<const WellsGroupInterface>& child_node : children_) {
if (child_node->canProduceMore()) {
return true;
}
}
return false;
}
bool WellsGroup::groupProdTargetConverged(const std::vector<double>& well_rates) const
{
// TODO: should consider the efficiency factor in getProductionRate()
for (const std::shared_ptr<const WellsGroupInterface>& child_node : children_) {
if ( ! child_node->groupProdTargetConverged(well_rates) ) {
return false;
}
}
// We need to check whether the current group target is satisfied
// we need to decide the modes we want to support here.
const ProductionSpecification::ControlMode prod_mode = prodSpec().control_mode_;
switch(prod_mode) {
case ProductionSpecification::LRAT :
case ProductionSpecification::ORAT :
case ProductionSpecification::WRAT :
case ProductionSpecification::GRAT :
{
const double production_rate = std::abs(getProductionRate(well_rates, prod_mode));
const double production_target = std::abs(getTarget(prod_mode));
// 0.01 is a hard-coded relative tolerance
const double relative_tolerance = 0.01;
// the bigger one of the two values
const double bigger_of_two = std::max(production_rate, production_target);
if (std::abs(production_target - production_rate) > relative_tolerance * bigger_of_two) {
// underproducing the target while potentially can produce more
// then we should not consider the effort to match the group target is done yet
if (canProduceMore()) {
return false;
} else {
// can not produce more to meet the target
OpmLog::info("group " + name() + " can not meet its target!");
}
}
}
case ProductionSpecification::FLD :
case ProductionSpecification::NONE :
case ProductionSpecification::GRUP :
break;
default:
{
const std::string msg = "Not handling target checking for control type " + ProductionSpecification::toString(prod_mode);
OPM_THROW(std::runtime_error, msg);
}
}
return true;
}
double WellsGroup::getProductionRate(const std::vector<double>& well_rates,
const ProductionSpecification::ControlMode prod_mode) const
{
double total_production_rate = 0.0;
for (const std::shared_ptr<const WellsGroupInterface>& child_node : children_) {
total_production_rate += child_node->getProductionRate(well_rates, prod_mode);
total_production_rate += child_node->getProductionRate(well_rates, prod_mode) * child_node->efficiencyFactor();
}
return total_production_rate;
}
@ -1214,6 +1290,7 @@ namespace Opm
if (!phase_used[BlackoilPhases::Aqua]) {
OPM_THROW(std::runtime_error, "Water phase not active and LRAT control specified.");
}
distr[phase_pos[BlackoilPhases::Liquid]] = 1.0;
distr[phase_pos[BlackoilPhases::Aqua]] = 1.0;
break;
@ -1492,7 +1569,8 @@ namespace Opm
double WellNode::getAccumulativeEfficiencyFactor() const {
double WellNode::getAccumulativeEfficiencyFactor() const
{
// TODO: not sure whether a well can be exempted from repsponding to the efficiency factor
// for the parent group.
double efficiency_factor = efficiencyFactor();
@ -1506,18 +1584,33 @@ namespace Opm
}
int WellNode::selfIndex() const {
int WellNode::selfIndex() const
{
return self_index_;
}
bool WellNode::targetUpdated() const {
bool WellNode::targetUpdated() const
{
return target_updated_;
}
void WellNode::setTargetUpdated(const bool flag) {
void WellNode::setTargetUpdated(const bool flag)
{
target_updated_ = flag;
}
bool WellNode::canProduceMore() const
{
return (isProducer() && !individualControl());
}
bool WellNode::groupProdTargetConverged(const std::vector<double>& /* well_rates */) const
{
return true;
}
}

View File

@ -163,10 +163,10 @@ namespace Opm
ProductionSpecification::ControlMode mode) = 0;
/// Gets the target rate for the given mode.
double getTarget(ProductionSpecification::ControlMode mode);
double getTarget(ProductionSpecification::ControlMode mode) const;
/// Gets the target rate for the given mode.
double getTarget(InjectionSpecification::ControlMode mode);
double getTarget(InjectionSpecification::ControlMode mode) const;
/// Applies any production group control relevant to all children nodes.
/// If no group control is set, this is called recursively to the children.
@ -235,6 +235,18 @@ namespace Opm
virtual void setTargetUpdated(const bool flag) = 0;
// bascially, for the group or wells under group control
// they have the potential to adjust their targets to produce more to match the higher level target
virtual bool canProduceMore() const = 0;
// checking wether group production target converged
// if the group is producing following the target, then it should be considered okay
// if the group is not producing following the target, then we should check wether the group
// should be able to produce more to match the target.
// if the group can not produce more, we also consider the effort to match the group target is
// also done and the group target converged while we should give a message
virtual bool groupProdTargetConverged(const std::vector<double>& well_rates) const = 0;
double efficiencyFactor() const;
void setEfficiencyFactor(const double efficiency_factor);
@ -369,6 +381,10 @@ namespace Opm
virtual double getProductionRate(const std::vector<double>& well_rates,
const ProductionSpecification::ControlMode prod_mode) const;
virtual bool canProduceMore() const;
virtual bool groupProdTargetConverged(const std::vector<double>& well_rates) const;
private:
std::vector<std::shared_ptr<WellsGroupInterface> > children_;
};
@ -497,6 +513,10 @@ namespace Opm
virtual void setTargetUpdated(const bool flag);
virtual bool canProduceMore() const;
virtual bool groupProdTargetConverged(const std::vector<double>& well_rates) const;
private:
Wells* wells_;
int self_index_;