mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-10-31 09:44:07 -05:00
Don't Copy Well Objects When Well Names are Sufficient
In particular, favour calling member functions on ScheduleState::wells to retrieve references to individual well objects given a name instead of using Schedule::getWells() or Schedule::getWellsAtEnd(). While convenient, these functions introduce needless copies of all well objects stored in the Schedule object. This commit instead, where possible, uses the somewhat less convenient ScheduleState::well_order() accessor and then accesses individual wells by name. To this end, change BlackoilWellModelGeneric::not_on_process_ from a function taking a well and returning a bool into a function taking a well name and returning a bool.
This commit is contained in:
1 parent
9020fed6b1
commit
fa45c41dd3
6 files changed
+92
-55
No files matched your search
@@ -41,6 +41,7 @@
|
||||
#include <opm/input/eclipse/Schedule/RPTConfig.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/NameOrder.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||
|
||||
@@ -1182,7 +1183,10 @@ void GenericOutputBlackoilModule<FluidSystem>::
|
||||
setupExtraBlockData(const std::size_t reportStepNum,
|
||||
std::function<bool(int)> isCartIdxOnThisRank)
|
||||
{
|
||||
for (const auto& well : schedule_.getWells(reportStepNum - 1)) {
|
||||
const auto& sched = this->schedule_[reportStepNum - 1];
|
||||
|
||||
for (const auto& wname : sched.well_order()) {
|
||||
const auto& well = sched.wells.get(wname);
|
||||
for (const auto& connection : well.getConnections()) {
|
||||
if (isCartIdxOnThisRank(connection.global_index())) {
|
||||
this->extraBlockData_.emplace(std::piecewise_construct,
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/NameOrder.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellEnums.hpp>
|
||||
@@ -41,6 +42,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
@@ -202,8 +204,8 @@ cumulative(const std::size_t reportStepNum,
|
||||
this->outputCumulativeReportRecord_(values, names, {});
|
||||
}
|
||||
|
||||
for (const auto& wname : this->schedule_.wellNames(reportStepNum)) {
|
||||
const auto& well = this->schedule_.getWell(wname, reportStepNum);
|
||||
for (const auto& wname : this->schedule_[reportStepNum].well_order()) {
|
||||
const auto& well = this->schedule_[reportStepNum].wells.get(wname);
|
||||
|
||||
std::vector<Scalar> values(WellCumDataType::numWCValues);
|
||||
std::vector<std::string> names(WellCumDataType::numWCNames);
|
||||
@@ -435,8 +437,8 @@ injection(const std::size_t reportStepNum,
|
||||
this->outputInjectionReportRecord_(values, names, {});
|
||||
}
|
||||
|
||||
for (const auto& wname : this->schedule_.wellNames(reportStepNum)) {
|
||||
const auto& well = this->schedule_.getWell(wname, reportStepNum);
|
||||
for (const auto& wname : this->schedule_[reportStepNum].well_order()) {
|
||||
const auto& well = this->schedule_[reportStepNum].wells.get(wname);
|
||||
|
||||
// Ignore production wells for the injection report.
|
||||
if (well.isProducer()) {
|
||||
@@ -513,20 +515,26 @@ template<class Scalar>
|
||||
void LogOutputHelper<Scalar>::
|
||||
msw(const std::size_t reportStepNum) const
|
||||
{
|
||||
const auto& wells = this->schedule_.getWells(reportStepNum);
|
||||
if (std::any_of(wells.begin(), wells.end(),
|
||||
[](const auto& well) { return well.isMultiSegment(); }))
|
||||
{
|
||||
this->beginMSWReport_();
|
||||
std::for_each(wells.begin(), wells.end(),
|
||||
[this](const auto& well)
|
||||
{
|
||||
if (well.isMultiSegment()) {
|
||||
this->outputMSWReportRecord_(well);
|
||||
}
|
||||
});
|
||||
this->endMSWReport_();
|
||||
const auto& sched = this->schedule_[reportStepNum];
|
||||
|
||||
auto msWells = std::vector<std::reference_wrapper<const Well>>{};
|
||||
for (const auto& wname : sched.well_order()) {
|
||||
if (const auto& well = sched.wells.get(wname); well.isMultiSegment()) {
|
||||
msWells.push_back(std::cref(well));
|
||||
}
|
||||
}
|
||||
|
||||
if (msWells.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->beginMSWReport_();
|
||||
|
||||
std::for_each(msWells.begin(), msWells.end(),
|
||||
[this](const Well& well)
|
||||
{ this->outputMSWReportRecord_(well); });
|
||||
|
||||
this->endMSWReport_();
|
||||
}
|
||||
|
||||
|
||||
@@ -567,8 +575,8 @@ production(const std::size_t reportStepNum,
|
||||
this->outputProductionReportRecord_(values, names, {});
|
||||
}
|
||||
|
||||
for (const auto& wname : this->schedule_.wellNames(reportStepNum)) {
|
||||
const auto& well = this->schedule_.getWell(wname, reportStepNum);
|
||||
for (const auto& wname : this->schedule_[reportStepNum].well_order()) {
|
||||
const auto& well = this->schedule_[reportStepNum].wells.get(wname);
|
||||
|
||||
// Ignore injection wells for the production report.
|
||||
if (well.isInjector()) {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/input/eclipse/Schedule/RFTConfig.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/NameOrder.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||
|
||||
#include <opm/material/fluidsystems/BlackOilDefaultFluidSystemIndices.hpp>
|
||||
@@ -85,7 +86,7 @@ addToWells(data::Wells& wellDatas,
|
||||
gatherAndUpdateMap(gasConnectionSaturations_, comm);
|
||||
}
|
||||
|
||||
for (const auto& wname : this->schedule_.wellNames(reportStepNum)) {
|
||||
for (const auto& wname : this->schedule_[reportStepNum].well_order()) {
|
||||
// Don't bother with wells not on this process.
|
||||
if (!wellQuery_(wname)) {
|
||||
continue;
|
||||
@@ -144,13 +145,15 @@ allocate(const std::size_t reportStepNum)
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& well: schedule_.getWells(reportStepNum)) {
|
||||
for (const auto& wname : schedule_[reportStepNum].well_order()) {
|
||||
|
||||
// don't bother with wells not on this process
|
||||
if (!wellQuery_(well.name())) {
|
||||
if (!wellQuery_(wname)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& well = schedule_[reportStepNum].wells.get(wname);
|
||||
|
||||
for (const auto& connection: well.getConnections()) {
|
||||
const std::size_t index = connection.global_index();
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <opm/input/eclipse/Schedule/Network/ExtNetwork.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/Schedule/ScheduleTypes.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/NameOrder.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellTestConfig.hpp>
|
||||
|
||||
@@ -72,8 +73,9 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
@@ -108,18 +110,19 @@ BlackoilWellModelGeneric(Schedule& schedule,
|
||||
{
|
||||
|
||||
const auto numProcs = comm_.size();
|
||||
this->not_on_process_ = [this, numProcs](const Well& well) {
|
||||
if (numProcs == decltype(numProcs){1})
|
||||
this->not_on_process_ = [this, numProcs](const std::string& well) {
|
||||
if (numProcs == decltype(numProcs){1}) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Recall: false indicates NOT active!
|
||||
const auto value = std::make_pair(well.name(), true);
|
||||
const auto value = std::make_pair(well, true);
|
||||
auto candidate = std::lower_bound(this->parallel_well_info_.begin(),
|
||||
this->parallel_well_info_.end(),
|
||||
value);
|
||||
|
||||
return (candidate == this->parallel_well_info_.end())
|
||||
|| (*candidate != value);
|
||||
|| (*candidate != value);
|
||||
};
|
||||
|
||||
const auto& node_pressures = eclState.getRestartNetworkPressures();
|
||||
@@ -295,8 +298,21 @@ template<class Scalar>
|
||||
std::vector<Well> BlackoilWellModelGeneric<Scalar>::
|
||||
getLocalWells(const int timeStepIdx) const
|
||||
{
|
||||
auto w = schedule().getWells(timeStepIdx);
|
||||
w.erase(std::remove_if(w.begin(), w.end(), not_on_process_), w.end());
|
||||
auto w = std::vector<Well>{};
|
||||
|
||||
auto wnames = this->schedule().wellNames(timeStepIdx);
|
||||
wnames.erase(std::remove_if(wnames.begin(), wnames.end(),
|
||||
this->not_on_process_),
|
||||
wnames.end());
|
||||
|
||||
w.reserve(wnames.size());
|
||||
|
||||
std::transform(wnames.begin(), wnames.end(),
|
||||
std::back_inserter(w),
|
||||
[&st = this->schedule()[timeStepIdx]]
|
||||
(const std::string& wname)
|
||||
{ return st.wells(wname); });
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
@@ -2002,50 +2018,55 @@ template<class Scalar>
|
||||
std::vector<std::vector<int>> BlackoilWellModelGeneric<Scalar>::
|
||||
getMaxWellConnections() const
|
||||
{
|
||||
std::vector<std::vector<int>> wells;
|
||||
auto wellConnections = std::vector<std::vector<int>>{};
|
||||
|
||||
auto schedule_wells = schedule().getWellsatEnd();
|
||||
schedule_wells.erase(std::remove_if(schedule_wells.begin(), schedule_wells.end(), not_on_process_), schedule_wells.end());
|
||||
wells.reserve(schedule_wells.size());
|
||||
auto schedule_wells = this->schedule().wellNames();
|
||||
schedule_wells.erase(std::remove_if(schedule_wells.begin(),
|
||||
schedule_wells.end(),
|
||||
this->not_on_process_),
|
||||
schedule_wells.end());
|
||||
|
||||
wellConnections.reserve(schedule_wells.size());
|
||||
|
||||
const auto possibleFutureConnections = schedule().getPossibleFutureConnections();
|
||||
|
||||
auto possibleFutureConnections = schedule().getPossibleFutureConnections();
|
||||
#if HAVE_MPI
|
||||
// Communicate Map to other processes, since it is only available on rank 0
|
||||
Parallel::MpiSerializer ser(comm_);
|
||||
ser.broadcast(Parallel::RootRank{0}, possibleFutureConnections);
|
||||
#endif
|
||||
// initialize the additional cell connections introduced by wells.
|
||||
for (const auto& well : schedule_wells)
|
||||
{
|
||||
std::vector<int> compressed_well_perforations = this->getCellsForConnections(well);
|
||||
|
||||
const auto possibleFutureConnectionSetIt = possibleFutureConnections.find(well.name());
|
||||
// initialize the additional cell connections introduced by wells.
|
||||
for (const auto& well : schedule_wells) {
|
||||
auto& compressed_well_perforations = wellConnections.emplace_back
|
||||
(this->getCellsForConnections(this->schedule().back().wells(well)));
|
||||
|
||||
const auto possibleFutureConnectionSetIt = possibleFutureConnections.find(well);
|
||||
if (possibleFutureConnectionSetIt != possibleFutureConnections.end()) {
|
||||
for (const auto& global_index : possibleFutureConnectionSetIt->second) {
|
||||
// THIS NEEDS TO BE UPDATED TO USE LGR
|
||||
|
||||
int compressed_idx = compressedIndexForInterior(global_index);
|
||||
|
||||
const int compressed_idx = compressedIndexForInterior(global_index);
|
||||
if (compressed_idx >= 0) { // Ignore connections in inactive/remote cells.
|
||||
compressed_well_perforations.push_back(compressed_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// also include wells with no perforations in case
|
||||
std::sort(compressed_well_perforations.begin(),
|
||||
compressed_well_perforations.end());
|
||||
|
||||
wells.push_back(compressed_well_perforations);
|
||||
}
|
||||
return wells;
|
||||
|
||||
return wellConnections;
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
int BlackoilWellModelGeneric<Scalar>::numLocalWellsEnd() const
|
||||
{
|
||||
auto w = schedule().getWellsatEnd();
|
||||
w.erase(std::remove_if(w.begin(), w.end(), not_on_process_), w.end());
|
||||
return w.size();
|
||||
const auto& wnames = schedule().back().well_order().names();
|
||||
|
||||
return std::count_if(wnames.begin(), wnames.end(),
|
||||
[this](const std::string& wname)
|
||||
{ return ! this->not_on_process_(wname); });
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
|
||||
@@ -536,7 +536,7 @@ protected:
|
||||
std::map<std::string, double> well_close_times_;
|
||||
|
||||
std::vector<ConnectionIndexMap> conn_idx_map_{};
|
||||
std::function<bool(const Well&)> not_on_process_{};
|
||||
std::function<bool(const std::string&)> not_on_process_{};
|
||||
|
||||
// a vector of all the wells.
|
||||
std::vector<WellInterfaceGeneric<Scalar>*> well_container_generic_{};
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <opm/input/eclipse/Schedule/Group/Group.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Network/ExtNetwork.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/NameOrder.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||
|
||||
#include <opm/material/fluidsystems/BlackOilFluidSystem.hpp>
|
||||
@@ -2289,12 +2290,12 @@ updateGuideRatesForWells(const Schedule& schedule,
|
||||
GuideRate* guideRate)
|
||||
{
|
||||
OPM_TIMEFUNCTION();
|
||||
for (const auto& well : schedule.getWells(reportStepIdx)) {
|
||||
for (const auto& wname : schedule[reportStepIdx].well_order()) {
|
||||
std::array<Scalar,3> potentials{};
|
||||
auto& [oilpot, gaspot, waterpot] = potentials;
|
||||
|
||||
const auto& well_index = wellState.index(well.name());
|
||||
if (well_index.has_value() && wellState.wellIsOwned(well_index.value(), well.name()))
|
||||
const auto& well_index = wellState.index(wname);
|
||||
if (well_index.has_value() && wellState.wellIsOwned(well_index.value(), wname))
|
||||
{
|
||||
// the well is found and owned
|
||||
const auto& ws = wellState.well(well_index.value());
|
||||
@@ -2313,7 +2314,7 @@ updateGuideRatesForWells(const Schedule& schedule,
|
||||
oilpot = unit_system.from_si(UnitSystem::measure::liquid_surface_rate, oilpot);
|
||||
waterpot = unit_system.from_si(UnitSystem::measure::liquid_surface_rate, waterpot);
|
||||
gaspot = unit_system.from_si(UnitSystem::measure::gas_surface_rate, gaspot);
|
||||
guideRate->compute(well.name(), reportStepIdx, simTime, oilpot, gaspot, waterpot);
|
||||
guideRate->compute(wname, reportStepIdx, simTime, oilpot, gaspot, waterpot);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user