revising updateWellTargets to remove the dependency of WellState

avoiding template using here. It is possible we will need WellState
eventually, while only using the well_rates for the moment.
This commit is contained in:
Kai Bao 2016-10-10 14:47:19 +02:00
parent fec53a1af5
commit 32e9b26ce8
6 changed files with 118 additions and 169 deletions

View File

@ -218,7 +218,8 @@ namespace Opm
return (any_group_control_node && any_should_update_node); return (any_group_control_node && any_should_update_node);
} }
bool WellCollection::needUpdateProductionTargets() const { bool WellCollection::needUpdateProductionTargets() const
{
bool any_group_control_node = false; bool any_group_control_node = false;
bool any_should_update_node = false; bool any_should_update_node = false;
@ -251,12 +252,39 @@ namespace Opm
return leaf_nodes_[i]; return leaf_nodes_[i];
} }
bool WellCollection::justUpdateWellTargets() const { bool WellCollection::justUpdateWellTargets() const
{
return just_update_well_targets_; return just_update_well_targets_;
} }
void WellCollection::setJustUpdateWellTargets(const bool flag) { void WellCollection::setJustUpdateWellTargets(const bool flag)
{
just_update_well_targets_ = flag; just_update_well_targets_ = flag;
} }
void WellCollection::updateWellTargets(const std::vector<double> well_rates)
{
// TODO: currently, we only handle the level of the well groups for the moment, i.e. the level just above wells
// We believe the relations between groups are similar to the relations between different wells inside the same group.
// While there will be somre more complication invloved for sure.
for (size_t i = 0; i < leaf_nodes_.size(); ++i) {
// find a node needs to update targets, then update targets for all the wellls inside the group.
// if (leaf_nodes_[i]->shouldUpdateWellTargets() && !leaf_nodes_[i]->individualControl()) {
if (!leaf_nodes_[i]->individualControl()) {
// TODO: will remove dynamic_cast with interface revision.
WellsGroup* parent_node = dynamic_cast<Opm::WellsGroup *>(leaf_nodes_[i]->getParent());
// update the target within this group.
if (leaf_nodes_[i]->isProducer()) {
parent_node->updateWellProductionTargets(well_rates);
}
if (leaf_nodes_[i]->isInjector()) {
parent_node->updateWellInjectionTargets(well_rates);
}
}
}
setJustUpdateWellTargets(true);
}
} }

View File

@ -124,8 +124,7 @@ namespace Opm
WellNode* getNode(size_t i) const; WellNode* getNode(size_t i) const;
template <class WellState> void updateWellTargets(const std::vector<double> well_rates);
void updateWellTargets(const WellState& well_state);
bool justUpdateWellTargets() const; bool justUpdateWellTargets() const;
@ -145,6 +144,5 @@ namespace Opm
} // namespace Opm } // namespace Opm
#include "WellCollection_impl.hpp"
#endif /* OPM_WELLCOLLECTION_HPP */ #endif /* OPM_WELLCOLLECTION_HPP */

View File

@ -1,54 +0,0 @@
/*
Copyright 2016 SINTEF ICT, Applied Mathematics.
Copyright 2016 Statoil ASA.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <opm/core/wells/WellCollection.hpp>
namespace Opm
{
template <class WellState>
void WellCollection::updateWellTargets(const WellState& well_state)
{
// TODO: currently, we only handle the level of the well groups for the moment, i.e. the level just above wells
// We believe the relations between groups are similar to the relations between different wells inside the same group.
// While there will be somre more complication invloved for sure.
for (size_t i = 0; i < leaf_nodes_.size(); ++i) {
// find a node needs to update targets, then update targets for all the wellls inside the group.
// if (leaf_nodes_[i]->shouldUpdateWellTargets() && !leaf_nodes_[i]->individualControl()) {
if (!leaf_nodes_[i]->individualControl()) {
// TODO: will remove dynamic_cast with interface revision.
WellsGroup* parent_node = dynamic_cast<Opm::WellsGroup *>(leaf_nodes_[i]->getParent());
// update the target within this group.
if (leaf_nodes_[i]->isProducer()) {
parent_node->updateWellProductionTargets(well_state);
}
if (leaf_nodes_[i]->isInjector()) {
parent_node->updateWellInjectionTargets(well_state);
}
}
}
setJustUpdateWellTargets(true);
}
}

View File

@ -65,12 +65,12 @@ namespace Opm
const InjectionSpecification& inje_spec, const InjectionSpecification& inje_spec,
const PhaseUsage& phase_usage) const PhaseUsage& phase_usage)
: parent_(NULL), : parent_(NULL),
should_update_well_targets_(false),
individual_control_(true), // always begin with individual control
name_(myname), name_(myname),
production_specification_(prod_spec), production_specification_(prod_spec),
injection_specification_(inje_spec), injection_specification_(inje_spec),
phase_usage_(phase_usage), phase_usage_(phase_usage)
individual_control_(true), // always begin with individual control
should_update_well_targets_(false)
{ {
} }
@ -587,7 +587,7 @@ namespace Opm
/// \param[in] phase The phase for which to sum up. /// \param[in] phase The phase for which to sum up.
double WellsGroup::getTotalProductionFlow(const std::vector<double>& phase_flows, double WellsGroup::getTotalProductionFlow(const std::vector<double>& phase_flows,
const BlackoilPhases::PhaseIndex phase) const BlackoilPhases::PhaseIndex phase) const
{ {
double sum = 0.0; double sum = 0.0;
for (size_t i = 0; i < children_.size(); ++i) { for (size_t i = 0; i < children_.size(); ++i) {
@ -668,6 +668,57 @@ namespace Opm
} }
void WellsGroup::updateWellProductionTargets(const std::vector<double>& well_rates)
{
// TODO: currently, we only handle the level of the well groups for the moment, i.e. the level just above wells
// We believe the relations between groups are similar to the relations between different wells inside the same group.
// While there will be somre more complication invloved for sure.
// Basically, we need to update the target rates for the wells still under group control.
ProductionSpecification::ControlMode control_mode = prodSpec().control_mode_;
double target_rate = prodSpec().liquid_max_rate_;
if (ProductionSpecification::toString(control_mode) == "FLD") {
auto* parent_node = getParent();
control_mode = parent_node->prodSpec().control_mode_;
target_rate = parent_node->prodSpec().liquid_max_rate_;
}
double rate_individual_control = 0.;
for (size_t i = 0; i < children_.size(); ++i) {
const std::shared_ptr<Opm::WellNode> well_node = std::dynamic_pointer_cast<Opm::WellNode>(children_[i]);
if (well_node->individualControl() && well_node->isProducer()) {
rate_individual_control += std::abs(well_node->getLiquidProductionRate(well_rates));
}
}
const double rate_for_group_control = target_rate - rate_individual_control;
const double my_guide_rate = productionGuideRate(true);
for (size_t i = 0; i < children_.size(); ++i) {
const std::shared_ptr<Opm::WellNode> well_node = std::dynamic_pointer_cast<Opm::WellNode>(children_[i]);
if (!well_node->individualControl() && well_node->isProducer()) {
const double children_guide_rate = well_node->productionGuideRate(true);
well_node->applyProdGroupControl(control_mode, (children_guide_rate/my_guide_rate) * rate_for_group_control, true);
well_node->setShouldUpdateWellTargets(false);
}
}
}
void WellsGroup::updateWellInjectionTargets(const std::vector<double>& well_rates)
{
// NOT doing anything yet.
// Will finish it when having an examples with more than one injection wells within same injection group.
for (size_t i = 0; i < children_.size(); ++i) {
if (!children_[i]->individualControl() && std::dynamic_pointer_cast<Opm::WellNode>(children_[i])->isInjector()) {
children_[i]->setShouldUpdateWellTargets(false);
}
}
}
bool WellsGroupInterface::individualControl() const { bool WellsGroupInterface::individualControl() const {
return individual_control_; return individual_control_;
} }
@ -901,7 +952,7 @@ namespace Opm
/// \param[in] phase The phase for which to sum up. /// \param[in] phase The phase for which to sum up.
double WellNode::getTotalProductionFlow(const std::vector<double>& phase_flows, double WellNode::getTotalProductionFlow(const std::vector<double>& phase_flows,
const BlackoilPhases::PhaseIndex phase) const BlackoilPhases::PhaseIndex phase) const
{ {
if (isInjector()) { if (isInjector()) {
return 0.0; return 0.0;
@ -931,7 +982,6 @@ namespace Opm
const double target, const double target,
const bool only_group) const bool only_group)
{ {
// Not changing if we're not forced to change
/* if (only_group && (prodSpec().control_mode_ != ProductionSpecification::GRUP /* if (only_group && (prodSpec().control_mode_ != ProductionSpecification::GRUP
&& prodSpec().control_mode_ != ProductionSpecification::NONE)) { && prodSpec().control_mode_ != ProductionSpecification::NONE)) {
std::cout << "Returning" << std::endl; std::cout << "Returning" << std::endl;
@ -1068,6 +1118,25 @@ namespace Opm
} }
double WellNode::getLiquidProductionRate(const std::vector<double>& well_rates) const
{
return ( getTotalProductionFlow(well_rates, BlackoilPhases::Liquid) +
getTotalProductionFlow(well_rates, BlackoilPhases::Aqua) );
}
double WellNode::getOilProductionRate(const std::vector<double>& well_rates) const
{
return getTotalProductionFlow(well_rates, BlackoilPhases::Liquid);
}
double WellNode::getWaterProductionRate(const std::vector<double>& well_rates) const
{
return getTotalProductionFlow(well_rates, BlackoilPhases::Aqua);
}
namespace namespace
{ {

View File

@ -190,7 +190,7 @@ namespace Opm
/// with all phase rates of a single well adjacent in the array. /// with all phase rates of a single well adjacent in the array.
/// \param[in] phase The phase for which to sum up. /// \param[in] phase The phase for which to sum up.
virtual double getTotalProductionFlow(const std::vector<double>& phase_flows, virtual double getTotalProductionFlow(const std::vector<double>& phase_flows,
const BlackoilPhases::PhaseIndex phase) = 0; const BlackoilPhases::PhaseIndex phase) const = 0;
/// Applies explicit reinjection controls. This must be called at each timestep to be correct. /// Applies explicit reinjection controls. This must be called at each timestep to be correct.
/// \param[in] well_reservoirrates_phase /// \param[in] well_reservoirrates_phase
@ -311,7 +311,7 @@ namespace Opm
/// with all phase rates of a single well adjacent in the array. /// with all phase rates of a single well adjacent in the array.
/// \param[in] phase The phase for which to sum up. /// \param[in] phase The phase for which to sum up.
virtual double getTotalProductionFlow(const std::vector<double>& phase_flows, virtual double getTotalProductionFlow(const std::vector<double>& phase_flows,
const BlackoilPhases::PhaseIndex phase); const BlackoilPhases::PhaseIndex phase) const;
/// Applies explicit reinjection controls. This must be called at each timestep to be correct. /// Applies explicit reinjection controls. This must be called at each timestep to be correct.
/// \param[in] well_reservoirrates_phase /// \param[in] well_reservoirrates_phase
@ -325,11 +325,9 @@ namespace Opm
virtual void applyExplicitReinjectionControls(const std::vector<double>& well_reservoirrates_phase, virtual void applyExplicitReinjectionControls(const std::vector<double>& well_reservoirrates_phase,
const std::vector<double>& well_surfacerates_phase); const std::vector<double>& well_surfacerates_phase);
template <class WellState> void updateWellProductionTargets(const std::vector<double>& well_rates);
void updateWellProductionTargets(const WellState& well_state);
template <class WellState> void updateWellInjectionTargets(const std::vector<double>& well_rates);
void updateWellInjectionTargets(const WellState& well_state);
private: private:
std::vector<std::shared_ptr<WellsGroupInterface> > children_; std::vector<std::shared_ptr<WellsGroupInterface> > children_;
@ -406,7 +404,7 @@ namespace Opm
/// with all phase rates of a single well adjacent in the array. /// with all phase rates of a single well adjacent in the array.
/// \param[in] phase The phase for which to sum up. /// \param[in] phase The phase for which to sum up.
virtual double getTotalProductionFlow(const std::vector<double>& phase_flows, virtual double getTotalProductionFlow(const std::vector<double>& phase_flows,
const BlackoilPhases::PhaseIndex phase); const BlackoilPhases::PhaseIndex phase) const;
/// Returns the type of the well. /// Returns the type of the well.
WellType type() const; WellType type() const;
@ -428,6 +426,12 @@ namespace Opm
bool isInjector() const; bool isInjector() const;
double getLiquidProductionRate(const std::vector<double>& well_rates) const;
double getOilProductionRate(const std::vector<double>& well_rates) const;
double getWaterProductionRate(const std::vector<double>& well_rates) const;
private: private:
Wells* wells_; Wells* wells_;
int self_index_; int self_index_;
@ -450,6 +454,5 @@ namespace Opm
const PhaseUsage& phase_usage ); const PhaseUsage& phase_usage );
} }
#include "WellsGroup_impl.hpp"
#endif /* OPM_WELLSGROUP_HPP */ #endif /* OPM_WELLSGROUP_HPP */

View File

@ -1,95 +0,0 @@
/*
Copyright 2016 SINTEF ICT, Applied Mathematics.
Copyright 2016 Statoil ASA.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <opm/core/wells/WellsGroup.hpp>
#include <iostream>
namespace Opm
{
template <class WellState>
void WellsGroup::updateWellProductionTargets(const WellState& well_state)
{
// TODO: currently, we only handle the level of the well groups for the moment, i.e. the level just above wells
// We believe the relations between groups are similar to the relations between different wells inside the same group.
// While there will be somre more complication invloved for sure.
// Basically, we need to update the target rates for the wells still under group control.
ProductionSpecification::ControlMode control_mode = prodSpec().control_mode_;
double target_rate = prodSpec().liquid_max_rate_;
if (ProductionSpecification::toString(control_mode) == "FLD") {
auto* parent_node = getParent();
control_mode = parent_node->prodSpec().control_mode_;
target_rate = parent_node->prodSpec().liquid_max_rate_;
}
double rate_individual_control = 0;
for (size_t i = 0; i < children_.size(); ++i) {
if (children_[i]->individualControl() && std::dynamic_pointer_cast<Opm::WellNode>(children_[i])->isProducer()) {
// get the rate here.
const std::string well_name = children_[i]->name();
typedef typename WellState::WellMapType::const_iterator const_iterator;
const_iterator it = well_state.wellMap().find(well_name);
const int well_index = (*it).second[0];
const int np = well_state.numPhases();
const double oil_rate = well_state.wellRates()[np * well_index + 1];
const double water_rate = well_state.wellRates()[np * well_index];
rate_individual_control += std::abs(oil_rate + water_rate);
}
}
const double rate_for_group_control = target_rate - rate_individual_control;
const double my_guide_rate = productionGuideRate(true);
for (size_t i = 0; i < children_.size(); ++i) {
// if (children_[i]->shouldUpdateWellTargets() && !children_[i]->individualControl()) {
if (!children_[i]->individualControl() && std::dynamic_pointer_cast<Opm::WellNode>(children_[i])->isProducer()) {
const double children_guide_rate = children_[i]->productionGuideRate(true);
// children_[i]->applyProdGroupControl(control_mode, (children_guide_rate/my_guide_rate) * rate_for_group_control, false);
children_[i]->applyProdGroupControl(control_mode, (children_guide_rate/my_guide_rate) * rate_for_group_control, true);
children_[i]->setShouldUpdateWellTargets(false);
}
}
}
template <class WellState>
void WellsGroup::updateWellInjectionTargets(const WellState&) {
// NOT doing anything yet.
// Will finish it when having an examples with more than one injection wells within same injection group.
for (size_t i = 0; i < children_.size(); ++i) {
if (!children_[i]->individualControl() && std::dynamic_pointer_cast<Opm::WellNode>(children_[i])->isInjector()) {
children_[i]->setShouldUpdateWellTargets(false);
}
}
}
}