From 1d943575584e6a8a66a7e4156e78840f0d2f928a Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Tue, 22 Sep 2020 14:12:15 +0200 Subject: [PATCH] Refactored how well information is exported after load balancing. Previously, we exported an unordered map containing all names of wells that are not present in the local part of the grid. As we envision to have wells that are distributed across multiple processors, this information does not seem to be enough. We need to be able to set up communication for each well. To do this we need to find out who handles perforations of each well. We now export a full list of well name together with a boolean indicating whether it perforates local cells (vector of pair of string and bool). --- ebos/eclbasevanguard.hh | 18 ++++++++----- ebos/eclcpgridvanguard.hh | 6 +---- ebos/ecloutputblackoilmodule.hh | 26 ++++++++++++------- opm/simulators/wells/BlackoilWellModel.hpp | 2 ++ .../wells/BlackoilWellModel_impl.hpp | 25 +++++++++++------- 5 files changed, 46 insertions(+), 31 deletions(-) diff --git a/ebos/eclbasevanguard.hh b/ebos/eclbasevanguard.hh index dbb9875c9..5b46f3f69 100644 --- a/ebos/eclbasevanguard.hh +++ b/ebos/eclbasevanguard.hh @@ -579,15 +579,15 @@ public: void equilCartesianCoordinate(unsigned cellIdx, std::array& ijk) const { return asImp_().equilCartesianIndexMapper().cartesianCoordinate(cellIdx, ijk); } + /*! - * \brief Return the names of the wells which do not penetrate any cells on the local - * process. + * \brief Returns vector with name and whether the has local perforated cells + * for all wells. * - * This is a kludge around the fact that for distributed grids, not all wells are - * seen by all proccesses. + * Will only have usable values for CpGrid. */ - std::unordered_set defunctWellNames() const - { return std::unordered_set(); } + const std::vector>& parallelWells() const + { return parallelWells_; } /*! * \brief Get the cell centroids for a distributed grid. @@ -683,6 +683,12 @@ protected: * Empty otherwise. Used by EclTransmissibilty. */ std::vector centroids_; + /*! \brief information about wells in parallel + * + * For each well in the model there is an entry with its name + * and a boolean indicating whether it perforates local cells. + */ + std::vector> parallelWells_; }; template diff --git a/ebos/eclcpgridvanguard.hh b/ebos/eclcpgridvanguard.hh index 6dbc3a520..c3bd407b0 100644 --- a/ebos/eclcpgridvanguard.hh +++ b/ebos/eclcpgridvanguard.hh @@ -218,7 +218,7 @@ public: PropsCentroidsDataHandle handle(*grid_, eclState, eclGrid, this->centroids_, cartesianIndexMapper()); - defunctWellNames_ = std::get<1>(grid_->loadBalance(handle, edgeWeightsMethod, &wells, faceTrans.data(), ownersFirst)); + this->parallelWells_ = std::get<1>(grid_->loadBalance(handle, edgeWeightsMethod, &wells, faceTrans.data(), ownersFirst)); } catch(const std::bad_cast& e) { @@ -295,9 +295,6 @@ public: return *equilCartesianIndexMapper_; } - std::unordered_set defunctWellNames() const - { return defunctWellNames_; } - const EclTransmissibility& globalTransmissibility() const { assert( globalTrans_ != nullptr ); @@ -361,7 +358,6 @@ protected: std::unique_ptr equilCartesianIndexMapper_; std::unique_ptr > globalTrans_; - std::unordered_set defunctWellNames_; int mpiRank; }; diff --git a/ebos/ecloutputblackoilmodule.hh b/ebos/ecloutputblackoilmodule.hh index 399b62a2f..1088f649b 100644 --- a/ebos/ecloutputblackoilmodule.hh +++ b/ebos/ecloutputblackoilmodule.hh @@ -322,8 +322,7 @@ public: for (const auto& well: schedule.getWells(reportStepNum)) { // don't bother with wells not on this process - const auto& defunctWellNames = simulator_.vanguard().defunctWellNames(); - if (defunctWellNames.find(well.name()) != defunctWellNames.end()) { + if (isDefunctParallelWell(well.name())) { continue; } @@ -903,8 +902,7 @@ public: for (const auto& well: schedule.getWells(reportStepNum)) { // don't bother with wells not on this process - const auto& defunctWellNames = simulator_.vanguard().defunctWellNames(); - if (defunctWellNames.find(well.name()) != defunctWellNames.end()) { + if (isDefunctParallelWell(well.name())) { continue; } @@ -1332,8 +1330,7 @@ public: for (const auto& wname: schedule.wellNames(reportStepNum)) { // don't bother with wells not on this process - const auto& defunctWellNames = simulator_.vanguard().defunctWellNames(); - if (defunctWellNames.find(wname) != defunctWellNames.end()) { + if (isDefunctParallelWell(wname)) { continue; } @@ -1432,8 +1429,7 @@ public: for (const auto& wname: schedule.wellNames(reportStepNum)) { // don't bother with wells not on this process - const auto& defunctWellNames = simulator_.vanguard().defunctWellNames(); - if (defunctWellNames.find(wname) != defunctWellNames.end()) { + if (isDefunctParallelWell(wname)) { continue; } @@ -1561,8 +1557,7 @@ public: for (const auto& wname : schedule.wellNames(reportStepNum)) { // don't bother with wells not on this process - const auto& defunctWellNames = simulator_.vanguard().defunctWellNames(); - if (defunctWellNames.find(wname) != defunctWellNames.end()) { + if (isDefunctParallelWell(wname)) { continue; } @@ -1830,6 +1825,17 @@ public: private: + bool isDefunctParallelWell(std::string wname) const + { + if (simulator_.gridView().comm().size()==1) + return false; + const auto& parallelWells = simulator_.vanguard().parallelWells(); + std::pair value{wname, true}; + auto candidate = std::lower_bound(parallelWells.begin(), parallelWells.end(), + value); + return candidate == parallelWells.end() || *candidate != value; + } + bool isIORank_() const { const auto& comm = simulator_.gridView().comm(); diff --git a/opm/simulators/wells/BlackoilWellModel.hpp b/opm/simulators/wells/BlackoilWellModel.hpp index 7fec28672..d029b9d3a 100644 --- a/opm/simulators/wells/BlackoilWellModel.hpp +++ b/opm/simulators/wells/BlackoilWellModel.hpp @@ -280,6 +280,8 @@ namespace Opm { std::vector is_cell_perforated_; + std::function is_shut_or_defunct_; + void initializeWellPerfData(); // create the well container diff --git a/opm/simulators/wells/BlackoilWellModel_impl.hpp b/opm/simulators/wells/BlackoilWellModel_impl.hpp index 3e067ac56..d8df47787 100644 --- a/opm/simulators/wells/BlackoilWellModel_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModel_impl.hpp @@ -25,6 +25,7 @@ #include #include +#include namespace Opm { template @@ -53,6 +54,18 @@ namespace Opm { const auto& cartDims = Opm::UgGridHelpers::cartDims(grid); setupCartesianToCompressed_(Opm::UgGridHelpers::globalCell(grid), cartDims[0]*cartDims[1]*cartDims[2]); + + is_shut_or_defunct_ = [&ebosSimulator](const Well& well) { + if (well.getStatus() == Well::Status::SHUT) + return true; + if (ebosSimulator.gridView().comm().size() == 1) + return false; + std::pair value{well.name(), true}; // false indicate not active! + const auto& parallel_wells = ebosSimulator.vanguard().parallelWells(); + auto candidate = std::lower_bound(parallel_wells.begin(), parallel_wells.end(), + value); + return candidate == parallel_wells.end() || *candidate != value; + }; } template @@ -215,13 +228,9 @@ namespace Opm { int globalNumWells = 0; // Make wells_ecl_ contain only this partition's non-shut wells. { - const auto& defunct_well_names = ebosSimulator_.vanguard().defunctWellNames(); - auto is_shut_or_defunct = [&defunct_well_names](const Well& well) { - return (well.getStatus() == Well::Status::SHUT) || (defunct_well_names.find(well.name()) != defunct_well_names.end()); - }; auto w = schedule().getWells(timeStepIdx); globalNumWells = w.size(); - w.erase(std::remove_if(w.begin(), w.end(), is_shut_or_defunct), w.end()); + w.erase(std::remove_if(w.begin(), w.end(), is_shut_or_defunct_), w.end()); wells_ecl_.swap(w); } initializeWellPerfData(); @@ -529,13 +538,9 @@ namespace Opm { int globalNumWells = 0; // Make wells_ecl_ contain only this partition's non-shut wells. { - const auto& defunct_well_names = ebosSimulator_.vanguard().defunctWellNames(); - auto is_shut_or_defunct = [&defunct_well_names](const Well& well) { - return (well.getStatus() == Well::Status::SHUT) || (defunct_well_names.find(well.name()) != defunct_well_names.end()); - }; auto w = schedule().getWells(report_step); globalNumWells = w.size(); - w.erase(std::remove_if(w.begin(), w.end(), is_shut_or_defunct), w.end()); + w.erase(std::remove_if(w.begin(), w.end(), is_shut_or_defunct_), w.end()); wells_ecl_.swap(w); }