mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
move calculateAllGroupGuideRates into BlackoilWellModelGuideRates
This commit is contained in:
parent
01dfe23a50
commit
5e157cd23b
@ -58,185 +58,6 @@
|
|||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
namespace {
|
|
||||||
class GroupTreeWalker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using GroupOp = std::function<void(const Opm::Group&)>;
|
|
||||||
using WellOp = std::function<void(const Opm::Well&)>;
|
|
||||||
|
|
||||||
explicit GroupTreeWalker(const Opm::Schedule& sched,
|
|
||||||
const int reportStepIdx)
|
|
||||||
: sched_ (sched)
|
|
||||||
, reportStepIdx_(reportStepIdx)
|
|
||||||
{}
|
|
||||||
|
|
||||||
GroupTreeWalker& groupOp(GroupOp visit)
|
|
||||||
{
|
|
||||||
this->visitGroup_ = std::move(visit);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
GroupTreeWalker& wellOp(WellOp visit)
|
|
||||||
{
|
|
||||||
this->visitWell_ = std::move(visit);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
this->visitGroup_ = GroupOp{};
|
|
||||||
this->visitWell_ = WellOp{};
|
|
||||||
}
|
|
||||||
|
|
||||||
void traversePostOrder();
|
|
||||||
|
|
||||||
private:
|
|
||||||
using NodeOp = void (GroupTreeWalker::*)(std::string_view) const;
|
|
||||||
|
|
||||||
std::reference_wrapper<const Opm::Schedule> sched_;
|
|
||||||
int reportStepIdx_;
|
|
||||||
|
|
||||||
GroupOp visitGroup_{};
|
|
||||||
WellOp visitWell_{};
|
|
||||||
|
|
||||||
std::stack<std::string_view, std::vector<std::string_view>> dfsGroupStack_{};
|
|
||||||
std::unordered_set<std::size_t> dfsGroupDiscovered_{};
|
|
||||||
|
|
||||||
NodeOp postDiscover_{nullptr};
|
|
||||||
NodeOp preFinish_{nullptr};
|
|
||||||
|
|
||||||
void traverse();
|
|
||||||
|
|
||||||
void startWalk();
|
|
||||||
void discover(std::string_view group);
|
|
||||||
void finish(std::string_view group);
|
|
||||||
|
|
||||||
bool isSeen(std::string_view group) const;
|
|
||||||
std::size_t insertIndex(std::string_view group) const;
|
|
||||||
|
|
||||||
void visitGroup(std::string_view group) const;
|
|
||||||
void visitWell(std::string_view well) const;
|
|
||||||
|
|
||||||
const Opm::Group& getGroup(std::string_view group) const;
|
|
||||||
const Opm::Well& getWell(std::string_view well) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
void GroupTreeWalker::traversePostOrder()
|
|
||||||
{
|
|
||||||
this->preFinish_ = &GroupTreeWalker::visitGroup;
|
|
||||||
this->postDiscover_ = nullptr;
|
|
||||||
|
|
||||||
this->traverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GroupTreeWalker::traverse()
|
|
||||||
{
|
|
||||||
this->startWalk();
|
|
||||||
|
|
||||||
while (! this->dfsGroupStack_.empty()) {
|
|
||||||
const auto gname = this->dfsGroupStack_.top();
|
|
||||||
|
|
||||||
if (this->isSeen(gname)) {
|
|
||||||
if (this->preFinish_ != nullptr) {
|
|
||||||
(this->*preFinish_)(gname);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->finish(gname);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->discover(gname);
|
|
||||||
|
|
||||||
if (this->postDiscover_ != nullptr) {
|
|
||||||
(this->*postDiscover_)(gname);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& group = this->getGroup(gname);
|
|
||||||
|
|
||||||
if (! group.wellgroup()) { // Node group. Register child groups.
|
|
||||||
for (const auto& child : group.groups()) {
|
|
||||||
if (! this->isSeen(child)) {
|
|
||||||
this->dfsGroupStack_.push(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { // Group is a well group--visit its wells.
|
|
||||||
for (const auto& well : group.wells()) {
|
|
||||||
this->visitWell(well);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GroupTreeWalker::startWalk()
|
|
||||||
{
|
|
||||||
this->dfsGroupDiscovered_.clear();
|
|
||||||
|
|
||||||
while (! this->dfsGroupStack_.empty()) {
|
|
||||||
this->dfsGroupStack_.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->dfsGroupStack_.push("FIELD");
|
|
||||||
}
|
|
||||||
|
|
||||||
void GroupTreeWalker::discover(std::string_view group)
|
|
||||||
{
|
|
||||||
this->dfsGroupDiscovered_.insert(this->insertIndex(group));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GroupTreeWalker::finish(std::string_view group)
|
|
||||||
{
|
|
||||||
if (this->dfsGroupStack_.top() != group) {
|
|
||||||
throw std::invalid_argument {
|
|
||||||
fmt::format("Internal Error: Expected group '{}', but got '{}'",
|
|
||||||
group, this->dfsGroupStack_.top())
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
this->dfsGroupStack_.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GroupTreeWalker::isSeen(std::string_view group) const
|
|
||||||
{
|
|
||||||
return this->dfsGroupDiscovered_.find(this->insertIndex(group))
|
|
||||||
!= this->dfsGroupDiscovered_.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t GroupTreeWalker::insertIndex(std::string_view group) const
|
|
||||||
{
|
|
||||||
return this->getGroup(group).insert_index();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GroupTreeWalker::visitGroup(std::string_view group) const
|
|
||||||
{
|
|
||||||
if (! this->visitGroup_) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->visitGroup_(this->getGroup(group));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GroupTreeWalker::visitWell(std::string_view well) const
|
|
||||||
{
|
|
||||||
if (! this->visitWell_) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->visitWell_(this->getWell(well));
|
|
||||||
}
|
|
||||||
|
|
||||||
const Opm::Group& GroupTreeWalker::getGroup(std::string_view group) const
|
|
||||||
{
|
|
||||||
return this->sched_.get().getGroup({group.data(), group.size()}, this->reportStepIdx_);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Opm::Well& GroupTreeWalker::getWell(std::string_view well) const
|
|
||||||
{
|
|
||||||
return this->sched_.get().getWell({well.data(), well.size()}, this->reportStepIdx_);
|
|
||||||
}
|
|
||||||
} // Anonymous
|
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
BlackoilWellModelGeneric::
|
BlackoilWellModelGeneric::
|
||||||
@ -918,67 +739,6 @@ assignShutConnections(data::Wells& wsrpt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string, data::GroupGuideRates>
|
|
||||||
BlackoilWellModelGeneric::
|
|
||||||
calculateAllGroupGuiderates(const int reportStepIdx) const
|
|
||||||
{
|
|
||||||
auto gr = std::unordered_map<std::string, data::GroupGuideRates>{};
|
|
||||||
|
|
||||||
auto walker = GroupTreeWalker{ this->schedule(), reportStepIdx };
|
|
||||||
|
|
||||||
// Populates 'gr'.
|
|
||||||
walker.groupOp([this, &gr](const Group& group)
|
|
||||||
{
|
|
||||||
const auto& gname = group.name();
|
|
||||||
|
|
||||||
if (gname == "FIELD") { return; }
|
|
||||||
|
|
||||||
if (this->guideRate_.has(gname)) {
|
|
||||||
gr[gname].production = BlackoilWellModelGuideRates(*this).getGuideRateValues(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->guideRate_.has(gname, Phase::WATER) ||
|
|
||||||
this->guideRate_.has(gname, Phase::GAS))
|
|
||||||
{
|
|
||||||
gr[gname].injection =
|
|
||||||
BlackoilWellModelGuideRates(*this).getGuideRateInjectionGroupValues(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto parent = group.parent();
|
|
||||||
if (parent == "FIELD") { return; }
|
|
||||||
|
|
||||||
gr[parent].injection += gr[gname].injection;
|
|
||||||
gr[parent].production += gr[gname].production;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Populates 'gr'.
|
|
||||||
walker.wellOp([this, &gr](const Well& well)
|
|
||||||
{
|
|
||||||
if (! (this->guideRate_.has(well.name()) ||
|
|
||||||
this->guideRate_.hasPotentials(well.name())))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& gname = well.groupName();
|
|
||||||
|
|
||||||
auto& grval = well.isInjector()
|
|
||||||
? gr[gname].injection
|
|
||||||
: gr[gname].production;
|
|
||||||
|
|
||||||
grval += BlackoilWellModelGuideRates(*this).getGuideRateValues(well);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Visit wells and groups before their parents, meaning no group is
|
|
||||||
// visited until all of its children down to the leaves of the group
|
|
||||||
// tree have been visited. Upon completion, 'gr' contains guide rate
|
|
||||||
// values for all groups reachable from 'FIELD' at this time/report
|
|
||||||
// step.
|
|
||||||
walker.traversePostOrder();
|
|
||||||
|
|
||||||
return gr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BlackoilWellModelGeneric::
|
BlackoilWellModelGeneric::
|
||||||
assignGroupControl(const Group& group,
|
assignGroupControl(const Group& group,
|
||||||
@ -1044,7 +804,7 @@ assignGroupValues(const int reportStepIdx,
|
|||||||
std::map<std::string, data::GroupData>& gvalues) const
|
std::map<std::string, data::GroupData>& gvalues) const
|
||||||
{
|
{
|
||||||
const auto groupGuideRates =
|
const auto groupGuideRates =
|
||||||
this->calculateAllGroupGuiderates(reportStepIdx);
|
BlackoilWellModelGuideRates(*this).calculateAllGroupGuideRates(reportStepIdx);
|
||||||
|
|
||||||
for (const auto& gname : schedule_.groupNames(reportStepIdx)) {
|
for (const auto& gname : schedule_.groupNames(reportStepIdx)) {
|
||||||
const auto& grup = schedule_.getGroup(gname, reportStepIdx);
|
const auto& grup = schedule_.getGroup(gname, reportStepIdx);
|
||||||
|
@ -282,9 +282,6 @@ protected:
|
|||||||
std::map<std::string, data::GroupData>& gvalues) const;
|
std::map<std::string, data::GroupData>& gvalues) const;
|
||||||
void assignNodeValues(std::map<std::string, data::NodeData>& nodevalues) const;
|
void assignNodeValues(std::map<std::string, data::NodeData>& nodevalues) const;
|
||||||
|
|
||||||
std::unordered_map<std::string, data::GroupGuideRates>
|
|
||||||
calculateAllGroupGuiderates(const int reportStepIdx) const;
|
|
||||||
|
|
||||||
void calculateEfficiencyFactors(const int reportStepIdx);
|
void calculateEfficiencyFactors(const int reportStepIdx);
|
||||||
|
|
||||||
void checkGconsaleLimits(const Group& group,
|
void checkGconsaleLimits(const Group& group,
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Group/Group.hpp>
|
#include <opm/input/eclipse/Schedule/Group/Group.hpp>
|
||||||
|
|
||||||
|
#include <opm/output/data/Groups.hpp>
|
||||||
#include <opm/output/data/GuideRateValue.hpp>
|
#include <opm/output/data/GuideRateValue.hpp>
|
||||||
|
|
||||||
#include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
|
#include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
|
||||||
@ -123,6 +124,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void traversePreOrder();
|
void traversePreOrder();
|
||||||
|
void traversePostOrder();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using NodeOp = void (GroupTreeWalker::*)(std::string_view) const;
|
using NodeOp = void (GroupTreeWalker::*)(std::string_view) const;
|
||||||
@ -163,6 +165,14 @@ void GroupTreeWalker::traversePreOrder()
|
|||||||
this->traverse();
|
this->traverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupTreeWalker::traversePostOrder()
|
||||||
|
{
|
||||||
|
this->preFinish_ = &GroupTreeWalker::visitGroup;
|
||||||
|
this->postDiscover_ = nullptr;
|
||||||
|
|
||||||
|
this->traverse();
|
||||||
|
}
|
||||||
|
|
||||||
void GroupTreeWalker::traverse()
|
void GroupTreeWalker::traverse()
|
||||||
{
|
{
|
||||||
this->startWalk();
|
this->startWalk();
|
||||||
@ -472,4 +482,64 @@ assignWellGuideRates(data::Wells& wsrpt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unordered_map<std::string, data::GroupGuideRates>
|
||||||
|
BlackoilWellModelGuideRates::
|
||||||
|
calculateAllGroupGuideRates(const int reportStepIdx) const
|
||||||
|
{
|
||||||
|
auto gr = std::unordered_map<std::string, data::GroupGuideRates>{};
|
||||||
|
|
||||||
|
auto walker = GroupTreeWalker{wellModel_.schedule(), reportStepIdx};
|
||||||
|
|
||||||
|
// Populates 'gr'.
|
||||||
|
walker.groupOp([this, &gr](const Group& group)
|
||||||
|
{
|
||||||
|
const auto& gname = group.name();
|
||||||
|
|
||||||
|
if (gname == "FIELD") { return; }
|
||||||
|
|
||||||
|
if (wellModel_.guideRate().has(gname)) {
|
||||||
|
gr[gname].production = this->getGuideRateValues(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wellModel_.guideRate().has(gname, Phase::WATER) ||
|
||||||
|
wellModel_.guideRate().has(gname, Phase::GAS))
|
||||||
|
{
|
||||||
|
gr[gname].injection = this->getGuideRateInjectionGroupValues(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto parent = group.parent();
|
||||||
|
if (parent == "FIELD") { return; }
|
||||||
|
|
||||||
|
gr[parent].injection += gr[gname].injection;
|
||||||
|
gr[parent].production += gr[gname].production;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Populates 'gr'.
|
||||||
|
walker.wellOp([this, &gr](const Well& well)
|
||||||
|
{
|
||||||
|
if (! (wellModel_.guideRate().has(well.name()) ||
|
||||||
|
wellModel_.guideRate().hasPotentials(well.name())))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& gname = well.groupName();
|
||||||
|
|
||||||
|
auto& grval = well.isInjector()
|
||||||
|
? gr[gname].injection
|
||||||
|
: gr[gname].production;
|
||||||
|
|
||||||
|
grval += this->getGuideRateValues(well);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Visit wells and groups before their parents, meaning no group is
|
||||||
|
// visited until all of its children down to the leaves of the group
|
||||||
|
// tree have been visited. Upon completion, 'gr' contains guide rate
|
||||||
|
// values for all groups reachable from 'FIELD' at this time/report
|
||||||
|
// step.
|
||||||
|
walker.traversePostOrder();
|
||||||
|
|
||||||
|
return gr;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
@ -26,11 +26,13 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
|
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
class BlackoilWellModelGeneric;
|
class BlackoilWellModelGeneric;
|
||||||
namespace data {
|
namespace data {
|
||||||
|
class GroupGuideRates;
|
||||||
class GuideRateValue;
|
class GuideRateValue;
|
||||||
class Wells;
|
class Wells;
|
||||||
}
|
}
|
||||||
@ -46,6 +48,15 @@ public:
|
|||||||
: wellModel_(wellModel)
|
: wellModel_(wellModel)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
//! \brief Assign well guide rates.
|
||||||
|
void assignWellGuideRates(data::Wells& wsrpt,
|
||||||
|
const int reportStepIdx) const;
|
||||||
|
|
||||||
|
//! \brief Calculates guide rate for all groups.
|
||||||
|
std::unordered_map<std::string, data::GroupGuideRates>
|
||||||
|
calculateAllGroupGuideRates(const int reportStepIdx) const;
|
||||||
|
|
||||||
|
private:
|
||||||
//! \brief Obtain guide rate values.
|
//! \brief Obtain guide rate values.
|
||||||
void getGuideRateValues(const GuideRate::RateVector& qs,
|
void getGuideRateValues(const GuideRate::RateVector& qs,
|
||||||
const bool is_inj,
|
const bool is_inj,
|
||||||
@ -61,11 +72,6 @@ public:
|
|||||||
//! \brief Obtain guide rate values for injection group.
|
//! \brief Obtain guide rate values for injection group.
|
||||||
data::GuideRateValue getGuideRateInjectionGroupValues(const Group& group) const;
|
data::GuideRateValue getGuideRateInjectionGroupValues(const Group& group) const;
|
||||||
|
|
||||||
//! \brief Assign guide rates for a well.
|
|
||||||
void assignWellGuideRates(data::Wells& wsrpt,
|
|
||||||
const int reportStepIdx) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const BlackoilWellModelGeneric& wellModel_; //!< Reference to well model
|
const BlackoilWellModelGeneric& wellModel_; //!< Reference to well model
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user