Merge pull request #1134 from GitPaean/group_ebos
updating the group control limit for individual control wells
This commit is contained in:
commit
674d97c660
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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_;
|
||||
|
Loading…
Reference in New Issue
Block a user