Final fixes for new well structure (to make it compile)
This commit is contained in:
parent
06fdc66370
commit
e6df79e341
@ -77,6 +77,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
computeFlowRatePerWell(*wells.c_wells(), well_rate_per_cell, well_rate);
|
||||
|
||||
#if 0
|
||||
while (!wells.conditionsMet(well_bhp, well_rate)) {
|
||||
std::cout << "Conditions not met for well, trying again" << std::endl;
|
||||
pressure_solver.solve(totmob, omega, src, wdp, bcs.c_bcs(), pressure, face_flux, well_bhp, well_rate_per_cell);
|
||||
@ -88,7 +89,7 @@ int main(int argc, char** argv) {
|
||||
computeFlowRatePerWell(*wells.c_wells(), well_rate_per_cell, well_rate);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
std::vector<double> porevol;
|
||||
computePorevolume(*grid->c_grid(), incomp_properties, porevol);
|
||||
|
||||
|
@ -94,12 +94,15 @@ namespace Opm
|
||||
}
|
||||
|
||||
bool WellCollection::conditionsMet(const std::vector<double>& well_bhp,
|
||||
const std::vector<double>& well_rate,
|
||||
double epsilon)
|
||||
const std::vector<double>& well_reservoirrates_phase,
|
||||
const std::vector<double>& well_surfacerates_phase)
|
||||
{
|
||||
for (size_t i = 0; i < roots_.size(); i++) {
|
||||
WellPhasesSummed phases;
|
||||
if(!roots_[i]->conditionsMet(well_bhp, well_rate, phases, epsilon)) {
|
||||
if (!roots_[i]->conditionsMet(well_bhp,
|
||||
well_reservoirrates_phase,
|
||||
well_surfacerates_phase,
|
||||
phases)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -118,4 +121,12 @@ namespace Opm
|
||||
leaf_nodes_[i]->setWellsPointer(wells, i);
|
||||
}
|
||||
}
|
||||
|
||||
void WellCollection::applyGroupControls()
|
||||
{
|
||||
for (size_t i = 0; i < roots_.size(); ++i) {
|
||||
roots_[i]->applyProdGroupControls();
|
||||
roots_[i]->applyInjGroupControls();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,14 +56,18 @@ namespace Opm
|
||||
/// \note It's highly recommended to use the conditionsMet found in WellsManager.
|
||||
/// \param[in] well_bhp A vector containing the bhp for each well. Is assumed
|
||||
/// to be ordered the same way as the related Wells-struct.
|
||||
/// \param[in] well_rate A vector containing the rate for each well. Is assumed
|
||||
/// to be ordered the same way as the related Wells-struct.
|
||||
/// \param[in] epsilon The error tolerated for each inequality. Formally, it will accept
|
||||
/// (a - b <= epsilon) as (a <= b).
|
||||
/// \param[in] well_reservoirrates_phase
|
||||
/// A vector containing reservoir rates by phase for each well.
|
||||
/// Is assumed to be ordered the same way as the related Wells-struct,
|
||||
/// with all phase rates of a single well adjacent in the array.
|
||||
/// \param[in] well_surfacerates_phase
|
||||
/// A vector containing surface rates by phase for each well.
|
||||
/// Is assumed to be ordered the same way as the related Wells-struct,
|
||||
/// with all phase rates of a single well adjacent in the array.
|
||||
/// \return true if no violations were found, false otherwise (false also implies a change).
|
||||
bool conditionsMet(const std::vector<double>& well_bhp,
|
||||
const std::vector<double>& well_rate,
|
||||
const double epsilon=1e-8);
|
||||
const std::vector<double>& well_reservoirrates_phase,
|
||||
const std::vector<double>& well_surfacerates_phase);
|
||||
|
||||
/// Adds the well pointer to each leaf node (does not take ownership).
|
||||
void setWellsPointer(Wells* wells);
|
||||
@ -86,6 +90,9 @@ namespace Opm
|
||||
/// \return the pointer to the group if found, NULL otherwise
|
||||
const WellsGroupInterface* findNode(const std::string& name) const;
|
||||
|
||||
/// Applies all group controls (injection and production)
|
||||
void applyGroupControls();
|
||||
|
||||
private:
|
||||
// To account for the possibility of a forest
|
||||
std::vector<std::tr1::shared_ptr<WellsGroupInterface> > roots_;
|
||||
|
@ -74,6 +74,11 @@ namespace Opm
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
const PhaseUsage& WellsGroupInterface::phaseUsage() const
|
||||
{
|
||||
return phase_usage_;
|
||||
}
|
||||
|
||||
bool WellsGroupInterface::isLeafNode() const
|
||||
{
|
||||
@ -161,7 +166,56 @@ namespace Opm
|
||||
}
|
||||
return tot_rate;
|
||||
}
|
||||
|
||||
|
||||
double WellsGroupInterface::getTarget(ProductionSpecification::ControlMode mode)
|
||||
{
|
||||
double target = -1.0;
|
||||
switch (mode) {
|
||||
case ProductionSpecification::GRAT:
|
||||
target = prodSpec().gas_max_rate_;
|
||||
break;
|
||||
case ProductionSpecification::ORAT:
|
||||
target = prodSpec().oil_max_rate_;
|
||||
break;
|
||||
case ProductionSpecification::RESV:
|
||||
target = prodSpec().reservoir_flow_max_rate_;
|
||||
break;
|
||||
case ProductionSpecification::LRAT:
|
||||
target = prodSpec().liquid_max_rate_;
|
||||
break;
|
||||
case ProductionSpecification::GRUP:
|
||||
THROW("Can't query target production rate for GRUP control keyword");
|
||||
break;
|
||||
default:
|
||||
THROW("Unsupported control mode to query target " << mode);
|
||||
break;
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
double WellsGroupInterface::getTarget(InjectionSpecification::ControlMode mode)
|
||||
{
|
||||
double target = -1.0;
|
||||
switch (mode) {
|
||||
case InjectionSpecification::RATE:
|
||||
target = injSpec().surface_flow_max_rate_;
|
||||
break;
|
||||
case InjectionSpecification::RESV:
|
||||
target = injSpec().reservoir_flow_max_rate_;
|
||||
break;
|
||||
case InjectionSpecification::GRUP:
|
||||
THROW("Can't query target production rate for GRUP control keyword");
|
||||
break;
|
||||
default:
|
||||
THROW("Unsupported control mode to query target " << mode);
|
||||
break;
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -212,27 +266,38 @@ namespace Opm
|
||||
/// Sets the current active control to the provided one for all injectors within the group.
|
||||
/// After this call, the combined rate (which rate depending on control_mode) of the group
|
||||
/// shall be equal to target.
|
||||
/// \param[in] forced if true, all children will be set under group control, otherwise
|
||||
/// only children that are under group control will be changed.
|
||||
void WellsGroup::applyInjGroupControl(const InjectionSpecification::ControlMode control_mode,
|
||||
const double target)
|
||||
const double target,
|
||||
const bool forced)
|
||||
{
|
||||
for (size_t i = 0; i < children_.size(); ++i) {
|
||||
const double child_target = target * children_[i]->injSpec().guide_rate_/injSpec().guide_rate_;
|
||||
children_[i]->applyInjGroupControl(control_mode, child_target);
|
||||
if (forced || injSpec().control_mode_ == InjectionSpecification::FLD) {
|
||||
for (size_t i = 0; i < children_.size(); ++i) {
|
||||
const double child_target = target * children_[i]->injSpec().guide_rate_ / injSpec().guide_rate_;
|
||||
children_[i]->applyInjGroupControl(control_mode, child_target, true);
|
||||
}
|
||||
injSpec().control_mode_ = InjectionSpecification::FLD;
|
||||
}
|
||||
injSpec().control_mode_ = InjectionSpecification::FLD;
|
||||
}
|
||||
|
||||
/// Sets the current active control to the provided one for all producers within the group.
|
||||
/// After this call, the combined rate (which rate depending on control_mode) of the group
|
||||
/// shall be equal to target.
|
||||
/// \param[in] forced if true, all children will be set under group control, otherwise
|
||||
/// only children that are under group control will be changed.
|
||||
void WellsGroup::applyProdGroupControl(const ProductionSpecification::ControlMode control_mode,
|
||||
const double target)
|
||||
const double target,
|
||||
const bool forced)
|
||||
{
|
||||
for (size_t i = 0; i < children_.size(); ++i) {
|
||||
const double child_target = target * children_[i]->prodSpec().guide_rate_/prodSpec().guide_rate_;
|
||||
children_[i]->applyProdGroupControl(control_mode, child_target);
|
||||
if (forced
|
||||
|| (prodSpec().control_mode_ == ProductionSpecification::FLD || prodSpec().control_mode_ == ProductionSpecification::NONE)) {
|
||||
for (size_t i = 0; i < children_.size(); ++i) {
|
||||
const double child_target = target * children_[i]->prodSpec().guide_rate_ / prodSpec().guide_rate_;
|
||||
children_[i]->applyProdGroupControl(control_mode, child_target, true);
|
||||
}
|
||||
prodSpec().control_mode_ = ProductionSpecification::FLD;
|
||||
}
|
||||
prodSpec().control_mode_ = ProductionSpecification::FLD;
|
||||
}
|
||||
|
||||
|
||||
@ -254,171 +319,83 @@ namespace Opm
|
||||
child_phases_summed += current_child_phases_summed;
|
||||
}
|
||||
|
||||
const int np = phaseUsage().num_phases;
|
||||
|
||||
// Injection constraints.
|
||||
InjectionSpecification::ControlMode injection_modes[] = {InjectionSpecification::RATE,
|
||||
InjectionSpecification::RESV};
|
||||
// RATE
|
||||
if (injSpec().control_mode_ != InjectionSpecification::RATE) {
|
||||
const double target_rate = injSpec().surface_flow_max_rate_;
|
||||
for (int mode_index = 0; mode_index < 2; ++mode_index) {
|
||||
InjectionSpecification::ControlMode mode = injection_modes[mode_index];
|
||||
if(injSpec().control_mode_ == mode) {
|
||||
continue;
|
||||
}
|
||||
const double target_rate = getTarget(mode);
|
||||
if (target_rate >= 0.0) {
|
||||
double my_rate = 0.0;
|
||||
for (int phase = 0; phase < np; ++phase) {
|
||||
my_rate += child_phases_summed.surf_inj_rates[phase];
|
||||
}
|
||||
double my_rate = rateByMode(child_phases_summed.res_inj_rates,
|
||||
child_phases_summed.surf_inj_rates,
|
||||
mode);
|
||||
|
||||
if (my_rate > target_rate) {
|
||||
std::cout << "Group RATE target not met for group " << name() << std::endl;
|
||||
std::cout << "Group " << mode<<" target not met for group " << name() << std::endl;
|
||||
std::cout << "target = " << target_rate << '\n'
|
||||
<< "rate = " << my_rate << std::endl;
|
||||
applyInjGroupControl(InjectionSpecification::RATE, target_rate);
|
||||
injSpec().control_mode_ = InjectionSpecification::RATE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// RESV
|
||||
if (injSpec().control_mode_ != InjectionSpecification::RESV) {
|
||||
const double target_rate = injSpec().reservoir_flow_max_rate_;
|
||||
if (target_rate >= 0.0) {
|
||||
double my_rate = 0.0;
|
||||
for (int phase = 0; phase < np; ++phase) {
|
||||
my_rate += child_phases_summed.res_inj_rates[phase];
|
||||
}
|
||||
if (my_rate > target_rate) {
|
||||
std::cout << "Group RESV target not met for group " << name() << std::endl;
|
||||
std::cout << "target = " << target_rate << '\n'
|
||||
<< "rate = " << my_rate << std::endl;
|
||||
applyInjGroupControl(InjectionSpecification::RESV, target_rate);
|
||||
injSpec().control_mode_ = InjectionSpecification::RESV;
|
||||
applyInjGroupControl(mode, target_rate, true);
|
||||
injSpec().control_mode_ = mode;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// REIN
|
||||
// \TODO: Add support for REIN controls.
|
||||
|
||||
// Production constraints.
|
||||
bool prod_restrictions_violated = false;
|
||||
ProductionSpecification::ControlMode violated_prod_mode = ProductionSpecification::NONE;
|
||||
|
||||
rateByMode(child_phases_summed.res_prod_rates,
|
||||
child_phases_summed.surf_prod_rates,
|
||||
mode);
|
||||
|
||||
// ORAT
|
||||
if (prodSpec().control_mode_ != ProductionSpecification::ORAT) {
|
||||
const double target_rate = prodSpec().oil_max_rate_;
|
||||
ProductionSpecification::ControlMode production_modes[] = {ProductionSpecification::ORAT,
|
||||
ProductionSpecification::WRAT,
|
||||
ProductionSpecification::GRAT,
|
||||
ProductionSpecification::LRAT,
|
||||
ProductionSpecification::RESV};
|
||||
bool production_violated = false;
|
||||
ProductionSpecification::ControlMode production_mode_violated;
|
||||
for (int mode_index = 0; mode_index < 5; ++mode_index) {
|
||||
const ProductionSpecification::ControlMode mode = production_modes[mode_index];
|
||||
if (prodSpec().control_mode_ == mode) {
|
||||
continue;
|
||||
}
|
||||
const double target_rate = getTarget(mode);
|
||||
if (target_rate >= 0.0) {
|
||||
const double my_rate
|
||||
= child_phases_summed.surf_prod_rates[phaseUsage().phase_pos[BlackoilPhases::Liquid]];
|
||||
const double my_rate = rateByMode(child_phases_summed.res_prod_rates,
|
||||
child_phases_summed.surf_prod_rates,
|
||||
mode);
|
||||
if (std::fabs(my_rate) > target_rate) {
|
||||
std::cout << "Group ORAT target not met for group " << name() << std::endl;
|
||||
std::cout << "Group" << mode << " target not met for group " << name() << std::endl;
|
||||
std::cout << "target = " << target_rate << '\n'
|
||||
<< "rate = " << my_rate << std::endl;
|
||||
applyProdGroupControl(ProductionSpecification::ORAT, target_rate);
|
||||
prodSpec().control_mode_ = ProductionSpecification::ORAT;
|
||||
return false;
|
||||
production_violated = true;
|
||||
production_mode_violated = mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WRAT
|
||||
if (prodSpec().control_mode_ != ProductionSpecification::WRAT) {
|
||||
const double target_rate = prodSpec().water_max_rate_;
|
||||
if (target_rate >= 0.0) {
|
||||
const double my_rate
|
||||
= child_phases_summed.surf_prod_rates[phaseUsage().phase_pos[BlackoilPhases::Aqua]];
|
||||
if (std::fabs(my_rate) > target_rate) {
|
||||
std::cout << "Group WRAT target not met for group " << name() << std::endl;
|
||||
std::cout << "target = " << target_rate << '\n'
|
||||
<< "rate = " << my_rate << std::endl;
|
||||
applyProdGroupControl(ProductionSpecification::WRAT, target_rate);
|
||||
prodSpec().control_mode_ = ProductionSpecification::WRAT;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GRAT
|
||||
if (prodSpec().control_mode_ != ProductionSpecification::GRAT) {
|
||||
const double target_rate = prodSpec().gas_max_rate_;
|
||||
if (target_rate >= 0.0) {
|
||||
const double my_rate
|
||||
= child_phases_summed.surf_prod_rates[phaseUsage().phase_pos[BlackoilPhases::Vapour]];
|
||||
if (std::fabs(my_rate) > target_rate) {
|
||||
std::cout << "Group GRAT target not met for group " << name() << std::endl;
|
||||
std::cout << "target = " << target_rate << '\n'
|
||||
<< "rate = " << my_rate << std::endl;
|
||||
applyProdGroupControl(ProductionSpecification::GRAT, target_rate);
|
||||
prodSpec().control_mode_ = ProductionSpecification::GRAT;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LRAT
|
||||
if (prodSpec().control_mode_ != ProductionSpecification::LRAT) {
|
||||
const double target_rate = prodSpec().liquid_max_rate_;
|
||||
if (target_rate >= 0.0) {
|
||||
const double my_rate =
|
||||
= child_phases_summed.surf_prod_rates[phaseUsage().phase_pos[BlackoilPhases::Aqua]]
|
||||
+ child_phases_summed.surf_prod_rates[phaseUsage().phase_pos[BlackoilPhases::Liquid]];
|
||||
if (std::fabs(my_rate) > target_rate) {
|
||||
std::cout << "Group LRAT target not met for group " << name() << std::endl;
|
||||
std::cout << "target = " << target_rate << '\n'
|
||||
<< "rate = " << my_rate << std::endl;
|
||||
applyProdGroupControl(ProductionSpecification::LRAT, target_rate);
|
||||
prodSpec().control_mode_ = ProductionSpecification::LRAT;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RESV
|
||||
if (prodSpec().control_mode_ != ProductionSpecification::RESV) {
|
||||
const double target_rate = prodSpec().reservoir_flow_max_rate_;
|
||||
if (target_rate >= 0.0) {
|
||||
double my_rate = 0.0;
|
||||
for (int phase = 0; phase < np; ++phase) {
|
||||
my_rate += child_phases_summed.res_prod_rates[phase];
|
||||
}
|
||||
if (std::fabs(my_rate) > target_rate) {
|
||||
std::cout << "Group RESV target not met for group " << name() << std::endl;
|
||||
std::cout << "target = " << target_rate << '\n'
|
||||
<< "rate = " << my_rate << std::endl;
|
||||
applyProdGroupControl(ProductionSpecification::RESV, target_rate);
|
||||
prodSpec().control_mode_ = ProductionSpecification::RESV;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double rate_target = std::min(std::abs(injSpec().fluid_volume_max_rate_),
|
||||
prodSpec().fluid_volume_max_rate_);
|
||||
|
||||
double rate_sum = child_phases_summed.rate_sum;
|
||||
if (std::abs(rate_sum) - std::abs(rate_target) > epsilon) {
|
||||
std::cout << "well_rate not met" << std::endl;
|
||||
std::cout << "target = " << rate_target
|
||||
<< ", well_rate[index_of_well] = "
|
||||
<< rate_sum << std::endl;
|
||||
std::cout << "Group name = " << name() << std::endl;
|
||||
|
||||
|
||||
if (production_violated) {
|
||||
switch (prodSpec().procedure_) {
|
||||
case ProductionSpecification::WELL:
|
||||
getWorstOffending(well_rate).first->shutWell();
|
||||
getWorstOffending(well_reservoirrates_phase,
|
||||
well_surfacerates_phase,
|
||||
production_mode_violated).first->shutWell();
|
||||
return false;
|
||||
break;
|
||||
case ProductionSpecification::RATE:
|
||||
applyControl(SURFACE_RATE);
|
||||
applyProdGroupControl(production_mode_violated,
|
||||
getTarget(production_mode_violated),
|
||||
true);
|
||||
return false;
|
||||
case ProductionSpecification::NONE_P:
|
||||
// Do nothing
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
// Nothing do to;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
summed_phases += child_phases_summed;
|
||||
return true;
|
||||
}
|
||||
@ -441,17 +418,85 @@ namespace Opm
|
||||
return sum;
|
||||
}
|
||||
|
||||
std::pair<WellNode*, double> WellsGroup::getWorstOffending(const std::vector<double>& values)
|
||||
std::pair<WellNode*, double> WellsGroup::getWorstOffending(const std::vector<double>& well_reservoirrates_phase,
|
||||
const std::vector<double>& well_surfacerates_phase,
|
||||
ProductionSpecification::ControlMode mode)
|
||||
{
|
||||
std::pair<WellNode*, double> max;
|
||||
for (size_t i = 0; i < children_.size(); i++) {
|
||||
std::pair<WellNode*, double> child_max = children_[i]->getWorstOffending(values);
|
||||
std::pair<WellNode*, double> child_max = children_[i]->getWorstOffending(well_reservoirrates_phase,
|
||||
well_surfacerates_phase,
|
||||
mode);
|
||||
if (i == 0 || max.second < child_max.second) {
|
||||
max = child_max;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
void WellsGroup::applyProdGroupControls()
|
||||
{
|
||||
ProductionSpecification::ControlMode prod_mode = prodSpec().control_mode_;
|
||||
switch (prod_mode) {
|
||||
case ProductionSpecification::ORAT:
|
||||
case ProductionSpecification::WRAT:
|
||||
case ProductionSpecification::LRAT:
|
||||
case ProductionSpecification::RESV:
|
||||
{
|
||||
const double my_guide_rate = prodSpec().guide_rate_;
|
||||
for (size_t i = 0; i < children_.size(); ++i ) {
|
||||
// Apply for all children.
|
||||
// Note, we do _not_ want to call the applyProdGroupControl in this object,
|
||||
// as that would check if we're under group control, something we're not.
|
||||
const double children_guide_rate = children_[i]->prodSpec().guide_rate_;
|
||||
children_[i]->applyProdGroupControl(prod_mode,
|
||||
(my_guide_rate / children_guide_rate) * getTarget(prod_mode),
|
||||
false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ProductionSpecification::FLD:
|
||||
case ProductionSpecification::NONE:
|
||||
// Call all children
|
||||
for (size_t i = 0; i < children_.size(); ++i ) {
|
||||
children_[i]->applyProdGroupControls();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
THROW("Unhandled group production control type " << prod_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void WellsGroup::applyInjGroupControls()
|
||||
{
|
||||
InjectionSpecification::ControlMode inj_mode = injSpec().control_mode_;
|
||||
switch (inj_mode) {
|
||||
case InjectionSpecification::RATE:
|
||||
case InjectionSpecification::RESV:
|
||||
{
|
||||
const double my_guide_rate = injSpec().guide_rate_;
|
||||
for (size_t i = 0; i < children_.size(); ++i ) {
|
||||
// Apply for all children.
|
||||
// Note, we do _not_ want to call the applyProdGroupControl in this object,
|
||||
// as that would check if we're under group control, something we're not.
|
||||
const double children_guide_rate = children_[i]->injSpec().guide_rate_;
|
||||
children_[i]->applyInjGroupControl(inj_mode,
|
||||
(my_guide_rate / children_guide_rate) * getTarget(inj_mode),
|
||||
false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case InjectionSpecification::FLD:
|
||||
case InjectionSpecification::NONE:
|
||||
// Call all children
|
||||
for (size_t i = 0; i < children_.size(); ++i ) {
|
||||
children_[i]->applyInjGroupControls();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
THROW("Unhandled group injection control mode " << inj_mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -466,7 +511,8 @@ namespace Opm
|
||||
: WellsGroupInterface(myname, prod_spec, inj_spec, phase_usage),
|
||||
wells_(0),
|
||||
self_index_(-1),
|
||||
group_control_index_(-1)
|
||||
group_control_index_(-1),
|
||||
shut_well_(true) // This is default for now
|
||||
{
|
||||
}
|
||||
|
||||
@ -566,12 +612,6 @@ namespace Opm
|
||||
{
|
||||
wells_ = wells;
|
||||
self_index_ = self_index;
|
||||
bool already_has_group_control =
|
||||
((wells_->type[self_index_] == INJECTOR) && (injSpec().control_mode_ == InjectionSpecification::GRUP))
|
||||
|| ((wells_->type[self_index_] == PRODUCER) && (prodSpec().control_mode_ == ProductionSpecification::GRUP));
|
||||
if (already_has_group_control) {
|
||||
group_control_index_ = wells_->ctrls[self_index_]->num - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void WellNode::calculateGuideRates()
|
||||
@ -586,16 +626,49 @@ namespace Opm
|
||||
|
||||
void WellNode::shutWell()
|
||||
{
|
||||
wells_->ctrls[self_index_]->target[0] = 0.0;
|
||||
if (shut_well_) {
|
||||
set_current_control(self_index_, -1, wells_);
|
||||
}
|
||||
else {
|
||||
const double target = 0.0;
|
||||
const double distr[3] = {1.0, 1.0, 1.0};
|
||||
|
||||
if (group_control_index_ < 0) {
|
||||
// The well only had its own controls, no group controls.
|
||||
append_well_controls(SURFACE_RATE, target, distr, self_index_, wells_);
|
||||
group_control_index_ = wells_->ctrls[self_index_]->num - 1;
|
||||
} else {
|
||||
// We will now modify the last control, that
|
||||
// "belongs to" the group control.
|
||||
const int np = wells_->number_of_phases;
|
||||
wells_->ctrls[self_index_]->type[group_control_index_] = SURFACE_RATE;
|
||||
wells_->ctrls[self_index_]->target[group_control_index_] = target;
|
||||
std::copy(distr, distr + np, wells_->ctrls[self_index_]->distr + np * group_control_index_);
|
||||
}
|
||||
set_current_control(self_index_, -1, wells_);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<WellNode*, double> WellNode::getWorstOffending(const std::vector<double>& values) {
|
||||
return std::make_pair<WellNode*, double>(this, values[self_index_]);
|
||||
std::pair<WellNode*, double> WellNode::getWorstOffending(const std::vector<double>& well_reservoirrates_phase,
|
||||
const std::vector<double>& well_surfacerates_phase,
|
||||
ProductionSpecification::ControlMode mode)
|
||||
{
|
||||
const int np = phaseUsage().num_phases;
|
||||
const int index = self_index_*np;
|
||||
return std::make_pair<WellNode*, double>(this, rateByMode(&well_reservoirrates_phase[index],
|
||||
&well_surfacerates_phase[index],
|
||||
mode));
|
||||
}
|
||||
|
||||
void WellNode::applyInjGroupControl(const InjectionSpecification::ControlMode control_mode,
|
||||
const double target)
|
||||
const double target,
|
||||
const bool forced)
|
||||
{
|
||||
// Not changing if we're not forced to change
|
||||
if (!forced
|
||||
&& (injSpec().control_mode_ != InjectionSpecification::GRUP || injSpec().control_mode_ != InjectionSpecification::NONE)) {
|
||||
return;
|
||||
}
|
||||
if (!wells_->type[self_index_] == INJECTOR) {
|
||||
ASSERT(target == 0.0);
|
||||
return;
|
||||
@ -631,8 +704,14 @@ namespace Opm
|
||||
|
||||
|
||||
void WellNode::applyProdGroupControl(const ProductionSpecification::ControlMode control_mode,
|
||||
const double target)
|
||||
const double target,
|
||||
const bool forced)
|
||||
{
|
||||
// Not changing if we're not forced to change
|
||||
if (!forced && (prodSpec().control_mode_ != ProductionSpecification::GRUP
|
||||
|| prodSpec().control_mode_ != ProductionSpecification::NONE)) {
|
||||
return;
|
||||
}
|
||||
if (!wells_->type[self_index_] == PRODUCER) {
|
||||
ASSERT(target == 0.0);
|
||||
return;
|
||||
@ -698,6 +777,17 @@ namespace Opm
|
||||
set_current_control(self_index_, group_control_index_, wells_);
|
||||
}
|
||||
|
||||
|
||||
void WellNode::applyProdGroupControls()
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
void WellNode::applyInjGroupControls()
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
@ -124,24 +124,54 @@ namespace Opm
|
||||
virtual bool conditionsMet(const std::vector<double>& well_bhp,
|
||||
const std::vector<double>& well_reservoirrates_phase,
|
||||
const std::vector<double>& well_surfacerates_phase,
|
||||
WellPhasesSummed& summed_phases);
|
||||
WellPhasesSummed& summed_phases) = 0;
|
||||
|
||||
/// Sets the current active control to the provided one for all injectors within the group.
|
||||
/// After this call, the combined rate (which rate depending on control_mode) of the group
|
||||
/// shall be equal to target.
|
||||
/// \param[in] forced if true, all children will be set under group control, otherwise
|
||||
/// only children that are under group control will be changed.
|
||||
virtual void applyInjGroupControl(const InjectionSpecification::ControlMode control_mode,
|
||||
const double target) = 0;
|
||||
const double target,
|
||||
const bool forced) = 0;
|
||||
/// Sets the current active control to the provided one for all producers within the group.
|
||||
/// After this call, the combined rate (which rate depending on control_mode) of the group
|
||||
/// shall be equal to target.
|
||||
/// \param[in] forced if true, all children will be set under group control, otherwise
|
||||
/// only children that are under group control will be changed.
|
||||
virtual void applyProdGroupControl(const ProductionSpecification::ControlMode control_mode,
|
||||
const double target) = 0;
|
||||
const double target,
|
||||
const bool forced) = 0;
|
||||
|
||||
/// Gets the worst offending well based on the input
|
||||
/// \param values A vector of a values for each well. This is assumed to be ordered the same way as the
|
||||
/// relevant Wells struct.
|
||||
/// \param[in] well_reservoirrates_phase
|
||||
/// A vector containing reservoir rates by phase for each well.
|
||||
/// Is assumed to be ordered the same way as the related Wells-struct,
|
||||
/// with all phase rates of a single well adjacent in the array.
|
||||
/// \param[in] well_surfacerates_phase
|
||||
/// A vector containing surface rates by phase for each well.
|
||||
/// Is assumed to be ordered the same way as the related Wells-struct,
|
||||
/// with all phase rates of a single well adjacent in the array.
|
||||
/// \param[in] mode
|
||||
/// The relevant control mode to find the maximum over.
|
||||
/// \return first will be a pointer to the worst offending well, second will be the obtained value at that well.
|
||||
virtual std::pair<WellNode*, double> getWorstOffending(const std::vector<double>& values) = 0;
|
||||
virtual std::pair<WellNode*, double> getWorstOffending(const std::vector<double>& well_reservoirrates_phase,
|
||||
const std::vector<double>& well_surfacerates_phase,
|
||||
ProductionSpecification::ControlMode mode) = 0;
|
||||
|
||||
/// Gets the target rate for the given mode.
|
||||
double getTarget(ProductionSpecification::ControlMode mode);
|
||||
|
||||
/// Gets the target rate for the given mode.
|
||||
double getTarget(InjectionSpecification::ControlMode mode);
|
||||
|
||||
/// Applies any production group control relevant to all children nodes.
|
||||
/// If no group control is set, this is called recursively to the children.
|
||||
virtual void applyProdGroupControls() = 0;
|
||||
|
||||
/// Applies any injection group control relevant to all children nodes.
|
||||
/// If no group control is set, this is called recursively to the children.
|
||||
virtual void applyInjGroupControls() = 0;
|
||||
|
||||
protected:
|
||||
/// Calculates the correct rate for the given ProductionSpecification::ControlMode
|
||||
@ -186,19 +216,35 @@ namespace Opm
|
||||
virtual void calculateGuideRates();
|
||||
|
||||
virtual int numberOfLeafNodes();
|
||||
virtual std::pair<WellNode*, double> getWorstOffending(const std::vector<double>& values);
|
||||
virtual std::pair<WellNode*, double> getWorstOffending(const std::vector<double>& well_reservoirrates_phase,
|
||||
const std::vector<double>& well_surfacerates_phase,
|
||||
ProductionSpecification::ControlMode mode);
|
||||
|
||||
/// Sets the current active control to the provided one for all injectors within the group.
|
||||
/// After this call, the combined rate (which rate depending on control_mode) of the group
|
||||
/// shall be equal to target.
|
||||
/// \param[in] forced if true, all children will be set under group control, otherwise
|
||||
/// only children that are under group control will be changed.
|
||||
virtual void applyInjGroupControl(const InjectionSpecification::ControlMode control_mode,
|
||||
const double target);
|
||||
const double target,
|
||||
bool forced);
|
||||
|
||||
/// Sets the current active control to the provided one for all producers within the group.
|
||||
/// After this call, the combined rate (which rate depending on control_mode) of the group
|
||||
/// shall be equal to target.
|
||||
/// \param[in] forced if true, all children will be set under group control, otherwise
|
||||
/// only children that are under group control will be changed.
|
||||
virtual void applyProdGroupControl(const ProductionSpecification::ControlMode control_mode,
|
||||
const double target);
|
||||
const double target,
|
||||
bool forced);
|
||||
|
||||
/// Applies any production group control relevant to all children nodes.
|
||||
/// If no group control is set, this is called recursively to the children.
|
||||
virtual void applyProdGroupControls();
|
||||
|
||||
/// Applies any injection group control relevant to all children nodes.
|
||||
/// If no group control is set, this is called recursively to the children.
|
||||
virtual void applyInjGroupControls();
|
||||
|
||||
private:
|
||||
std::vector<std::tr1::shared_ptr<WellsGroupInterface> > children_;
|
||||
@ -230,24 +276,42 @@ namespace Opm
|
||||
// Shuts the well (in the well struct)
|
||||
void shutWell();
|
||||
|
||||
virtual std::pair<WellNode*, double> getWorstOffending(const std::vector<double>& values);
|
||||
virtual std::pair<WellNode*, double> getWorstOffending(const std::vector<double>& well_reservoirrates_phase,
|
||||
const std::vector<double>& well_surfacerates_phase,
|
||||
ProductionSpecification::ControlMode mode);
|
||||
|
||||
/// Sets the current active control to the provided one for all injectors within the group.
|
||||
/// After this call, the combined rate (which rate depending on control_mode) of the group
|
||||
/// shall be equal to target.
|
||||
/// \param[in] forced if true, all children will be set under group control, otherwise
|
||||
/// only children that are under group control will be changed.
|
||||
virtual void applyInjGroupControl(const InjectionSpecification::ControlMode control_mode,
|
||||
const double target);
|
||||
const double target,
|
||||
bool forced);
|
||||
|
||||
/// Sets the current active control to the provided one for all producers within the group.
|
||||
/// After this call, the combined rate (which rate depending on control_mode) of the group
|
||||
/// shall be equal to target.
|
||||
/// \param[in] forced if true, all children will be set under group control, otherwise
|
||||
/// only children that are under group control will be changed.
|
||||
virtual void applyProdGroupControl(const ProductionSpecification::ControlMode control_mode,
|
||||
const double target);
|
||||
const double target,
|
||||
bool forced);
|
||||
|
||||
/// Applies any production group control relevant to all children nodes.
|
||||
/// If no group control is set, this is called recursively to the children.
|
||||
virtual void applyProdGroupControls();
|
||||
|
||||
/// Applies any injection group control relevant to all children nodes.
|
||||
/// If no group control is set, this is called recursively to the children.
|
||||
virtual void applyInjGroupControls();
|
||||
|
||||
|
||||
private:
|
||||
Wells* wells_;
|
||||
int self_index_;
|
||||
int group_control_index_;
|
||||
bool shut_well_;
|
||||
};
|
||||
|
||||
/// Creates the WellsGroupInterface for the given name
|
||||
|
@ -621,68 +621,8 @@ namespace Opm
|
||||
}
|
||||
}
|
||||
well_collection_.calculateGuideRates();
|
||||
|
||||
// Apply guide rates:
|
||||
for (size_t wix = 0; wix < well_data.size(); wix++) {
|
||||
const WellNode& wellnode = *well_collection_.getLeafNodes()[wix];
|
||||
if (well_data[wix].type == PRODUCER && (wellnode.prodSpec().control_mode_ == ProductionSpecification::GRUP)) {
|
||||
ASSERT(w_->ctrls[wix]->current == -1);
|
||||
switch (wellnode.prodSpec().guide_rate_type_ ) {
|
||||
case ProductionSpecification::OIL:
|
||||
{
|
||||
const ProductionSpecification& parent_prod_spec =
|
||||
wellnode.getParent()->prodSpec();
|
||||
const double guide_rate = wellnode.prodSpec().guide_rate_;
|
||||
const double oil_target = guide_rate * parent_prod_spec.oil_max_rate_;
|
||||
double distr[3] = { 0.0, 0.0, 0.0 };
|
||||
distr[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0;
|
||||
const int control_index = w_->ctrls[wix]->num;
|
||||
append_well_controls(SURFACE_RATE, oil_target, distr, wix, w_);
|
||||
set_current_control(wix, control_index, w_);
|
||||
}
|
||||
case ProductionSpecification::NONE_GRT:
|
||||
{
|
||||
// Will use the group control type:
|
||||
const ProductionSpecification& parent_prod_spec =
|
||||
wellnode.getParent()->prodSpec();
|
||||
const double guide_rate = wellnode.prodSpec().guide_rate_;
|
||||
switch(parent_prod_spec.control_mode_) {
|
||||
case ProductionSpecification::LRAT:
|
||||
{
|
||||
const double liq_target = guide_rate * parent_prod_spec.liquid_max_rate_;
|
||||
double distr[3] = { 0.0, 0.0, 0.0 };
|
||||
distr[pu.phase_pos[BlackoilPhases::Aqua]] = 1.0;
|
||||
distr[pu.phase_pos[BlackoilPhases::Liquid]] = 1.0;
|
||||
append_well_controls(SURFACE_RATE, liq_target, distr, wix, w_);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
THROW("Unhandled parent production specification control mode " << parent_prod_spec.control_mode_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
THROW("Unhandled production specification guide rate type "
|
||||
<< wellnode.prodSpec().guide_rate_type_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (well_data[wix].type == INJECTOR && (wellnode.injSpec().control_mode_ == InjectionSpecification::GRUP)) {
|
||||
ASSERT(w_->ctrls[wix]->current == -1);
|
||||
if (wellnode.injSpec().guide_rate_type_ == InjectionSpecification::RAT) {
|
||||
const double parent_surface_rate = wellnode.getParent()->injSpec().surface_flow_max_rate_;
|
||||
const double guide_rate = wellnode.prodSpec().guide_rate_;
|
||||
const double target = guide_rate * parent_surface_rate;
|
||||
const double distr[3] = { 1.0, 1.0, 1.0 };
|
||||
append_well_controls(SURFACE_RATE, target, distr, wix, w_);
|
||||
} else {
|
||||
THROW("Unhandled injection specification guide rate type "
|
||||
<< wellnode.injSpec().guide_rate_type_);
|
||||
}
|
||||
}
|
||||
}
|
||||
well_collection_.setWellsPointer(w_);
|
||||
well_collection_.applyGroupControls();
|
||||
}
|
||||
|
||||
|
||||
@ -710,9 +650,12 @@ namespace Opm
|
||||
}
|
||||
|
||||
bool WellsManager::conditionsMet(const std::vector<double>& well_bhp,
|
||||
const std::vector<double>& well_rate)
|
||||
const std::vector<double>& well_reservoirrates_phase,
|
||||
const std::vector<double>& well_surfacerates_phase)
|
||||
{
|
||||
return well_collection_.conditionsMet(well_bhp, well_rate);
|
||||
return well_collection_.conditionsMet(well_bhp,
|
||||
well_reservoirrates_phase,
|
||||
well_surfacerates_phase);
|
||||
}
|
||||
|
||||
} // namespace Opm
|
||||
|
@ -68,18 +68,24 @@ namespace Opm
|
||||
/// down wells). Only one change is applied per invocation. Typical use will be
|
||||
/// \code
|
||||
/// solve_pressure();
|
||||
/// while(!wells.conditionsMet(well_bhp, well_rate)) {
|
||||
/// while(!wells.conditionsMet(...)) {
|
||||
/// solve_pressure();
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \param[in] well_bhp A vector containing the bhp for each well. Is assumed
|
||||
/// to be ordered the same way as the related Wells-struct.
|
||||
/// \param[in] well_rate A vector containing the rate for each well. Is assumed
|
||||
/// to be ordered the same way as the related Wells-struct.
|
||||
/// \param[in] well_reservoirrates_phase
|
||||
/// A vector containing reservoir rates by phase for each well.
|
||||
/// Is assumed to be ordered the same way as the related Wells-struct,
|
||||
/// with all phase rates of a single well adjacent in the array.
|
||||
/// \param[in] well_surfacerates_phase
|
||||
/// A vector containing surface rates by phase for each well.
|
||||
/// Is assumed to be ordered the same way as the related Wells-struct,
|
||||
/// with all phase rates of a single well adjacent in the array.
|
||||
/// \return true if no violations were found, false otherwise (false also implies a change).
|
||||
bool conditionsMet(const std::vector<double>& well_bhp,
|
||||
const std::vector<double>& well_rate);
|
||||
bool conditionsMet(const std::vector<double>& well_bhp,
|
||||
const std::vector<double>& well_reservoirrates_phase,
|
||||
const std::vector<double>& well_surfacerates_phase);
|
||||
|
||||
private:
|
||||
// Disable copying and assignment.
|
||||
|
Loading…
Reference in New Issue
Block a user