From 012edac7cefe93b6b40cc004f3e1608c3ec3e530 Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Thu, 8 Sep 2016 21:18:53 +0200 Subject: [PATCH 1/5] Use provided set of deactivated wells in parallel. Before this commit we tried to compute whether a well is represented on the processor using the grid information. Due to the overlap region and possible completion on deactivated cells of the global grid this is not even possible. E.g. we cannot distinguish whether a completion is just not represented on the domain of a process or the corresponding cell is not active in the simulation. With this commit we refactor to passing the well manager an explicit list of name of wells that should be completely neglected. This information can easily by computed after the loadbalancer has computed partitions. --- opm/core/wells/WellsManager.cpp | 3 +- opm/core/wells/WellsManager.hpp | 11 ++++- opm/core/wells/WellsManager_impl.hpp | 71 ++++++++-------------------- 3 files changed, 31 insertions(+), 54 deletions(-) diff --git a/opm/core/wells/WellsManager.cpp b/opm/core/wells/WellsManager.cpp index 5a86c1139..67dbf29e7 100644 --- a/opm/core/wells/WellsManager.cpp +++ b/opm/core/wells/WellsManager.cpp @@ -340,7 +340,8 @@ namespace Opm UgGridHelpers::globalCell(grid), UgGridHelpers::cartDims(grid), UgGridHelpers::dimensions(grid), UgGridHelpers::cell2Faces(grid), UgGridHelpers::beginFaceCentroids(grid), - permeability, dummy_list_econ_limited, dummy_well_potentials); + permeability, dummy_list_econ_limited, dummy_well_potentials, + std::set()); } diff --git a/opm/core/wells/WellsManager.hpp b/opm/core/wells/WellsManager.hpp index 79d356bff..5eb42dcb5 100644 --- a/opm/core/wells/WellsManager.hpp +++ b/opm/core/wells/WellsManager.hpp @@ -77,6 +77,10 @@ namespace Opm /// The permeability argument may be zero if the input contain /// well productivity indices, otherwise it must be given in /// order to approximate these by the Peaceman formula. + /// + /// \param deactivated_wells A set of wells that should be treated + /// like shut wells. E.g. in a a parallel run these would be + /// the wells handeled by another process. Defaults to empty set. template WellsManager(const Opm::EclipseStateConstPtr eclipseState, const size_t timeStep, @@ -89,7 +93,8 @@ namespace Opm const double* permeability, const DynamicListEconLimited& list_econ_limited, bool is_parallel_run=false, - const std::vector& well_potentials={}); + const std::vector& well_potentials={}, + const std::set& deactivated_wells = {}); WellsManager(const Opm::EclipseStateConstPtr eclipseState, const size_t timeStep, @@ -158,7 +163,8 @@ namespace Opm FC begin_face_centroids, const double* permeability, const DynamicListEconLimited& list_econ_limited, - const std::vector& well_potentials); + const std::vector& well_potentials, + const std::set& deactivated_wells); // Disable copying and assignment. WellsManager(const WellsManager& other); WellsManager& operator=(const WellsManager& other); @@ -183,6 +189,7 @@ namespace Opm const double* permeability, const NTG& ntg, std::vector& wells_on_proc, + const std::set& deactivated_wells, const DynamicListEconLimited& list_econ_limited); void addChildGroups(GroupTreeNodeConstPtr parentNode, std::shared_ptr< const Schedule > schedule, size_t timeStep, const PhaseUsage& phaseUsage); diff --git a/opm/core/wells/WellsManager_impl.hpp b/opm/core/wells/WellsManager_impl.hpp index c637eeff4..440270b01 100644 --- a/opm/core/wells/WellsManager_impl.hpp +++ b/opm/core/wells/WellsManager_impl.hpp @@ -121,6 +121,7 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t const double* permeability, const NTG& ntg, std::vector& wells_on_proc, + const std::set& ignored_wells, const DynamicListEconLimited& list_econ_limited) { if (dimensions != 3) { @@ -137,10 +138,15 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t // Note that some wells are deactivated as they live on the interior // domain of another proccess. Therefore this might different from // the index of the well according to the eclipse state - int well_index_on_proc = 0; + int active_well_index = 0; for (auto wellIter= wells.begin(); wellIter != wells.end(); ++wellIter) { const auto* well = (*wellIter); + if ( ignored_wells.find(well->name()) != ignored_wells.end() ) { + wells_on_proc[ wellIter - wells.begin() ] = 0; + continue; + } + if (well->getStatus(timeStep) == WellCommon::SHUT) { continue; } @@ -157,8 +163,7 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t { // COMPDAT handling auto completionSet = well->getCompletions(timeStep); // shut completions and open ones stored in this process will have 1 others 0. - std::vector completion_on_proc(completionSet->size(), 1); - std::size_t shut_completions_number = 0; + for (size_t c=0; csize(); c++) { CompletionConstPtr completion = completionSet->get(c); if (completion->getState() == WellCompletion::OPEN) { @@ -170,17 +175,9 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t int cart_grid_indx = i + cpgdim[0]*(j + cpgdim[1]*k); std::map::const_iterator cgit = cartesian_to_compressed.find(cart_grid_indx); if (cgit == cartesian_to_compressed.end()) { - if ( is_parallel_run_ ) - { - completion_on_proc[c]=0; - continue; - } - else - { - OPM_MESSAGE("****Warning: Cell with i,j,k indices " << i << ' ' << j << ' ' - << k << " not found in grid. The completion will be igored (well = " - << well->name() << ')'); - } + OPM_MESSAGE("****Warning: Cell with i,j,k indices " << i << ' ' << j << ' ' + << k << " not found in grid. The completion will be igored (well = " + << well->name() << ')'); } else { @@ -226,47 +223,17 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t } pd.well_index *= wellPi; } - wellperf_data[well_index_on_proc].push_back(pd); + wellperf_data[active_well_index].push_back(pd); } } else { - ++shut_completions_number; if (completion->getState() != WellCompletion::SHUT) { OPM_THROW(std::runtime_error, "Completion state: " << WellCompletion::StateEnum2String( completion->getState() ) << " not handled"); } } } - if ( is_parallel_run_ ) - { - // sum_completions_on_proc includes completions - // that are shut - std::size_t sum_completions_on_proc = std::accumulate(completion_on_proc.begin(), - completion_on_proc.end(),0); - // Set wells that are not on this processor to SHUT. - // A well is not here if only shut completions are found. - if ( sum_completions_on_proc == shut_completions_number ) - { - // Mark well as not existent on this process - wells_on_proc[wellIter-wells.begin()] = 0; - continue; - } - else - { - // Check that the complete well is on this process - if ( sum_completions_on_proc < completionSet->size() ) - { - OpmLog::warning("Well " + well->name() + " does not seem to be" - + "completely in the disjoint partition of " - + "process. Therefore we deactivate it here."); - // Mark well as not existent on this process - wells_on_proc[wellIter-wells.begin()] = 0; - wellperf_data[well_index_on_proc].clear(); - continue; - } - } - } } { // WELSPECS handling - well_names_to_index[well->name()] = well_index_on_proc; + well_names_to_index[well->name()] = active_well_index; well_names.push_back(well->name()); { WellData wd; @@ -282,7 +249,7 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t } } - well_index_on_proc++; + active_well_index++; } // Set up reference depths that were defaulted. Count perfs. @@ -349,12 +316,13 @@ WellsManager(const Opm::EclipseStateConstPtr eclipseState, const double* permeability, const DynamicListEconLimited& list_econ_limited, bool is_parallel_run, - const std::vector& well_potentials) + const std::vector& well_potentials, + const std::set& deactivated_wells) : w_(0), is_parallel_run_(is_parallel_run) { init(eclipseState, timeStep, number_of_cells, global_cell, cart_dims, dimensions, - cell_to_faces, begin_face_centroids, permeability, list_econ_limited, well_potentials); + cell_to_faces, begin_face_centroids, permeability, list_econ_limited, well_potentials, deactivated_wells); } /// Construct wells from deck. @@ -370,7 +338,8 @@ WellsManager::init(const Opm::EclipseStateConstPtr eclipseState, FC begin_face_centroids, const double* permeability, const DynamicListEconLimited& list_econ_limited, - const std::vector& well_potentials) + const std::vector& well_potentials, + const std::set& deactivated_wells) { if (dimensions != 3) { OPM_THROW(std::runtime_error, @@ -432,7 +401,7 @@ WellsManager::init(const Opm::EclipseStateConstPtr eclipseState, dz, well_names, well_data, well_names_to_index, pu, cartesian_to_compressed, permeability, ntg, - wells_on_proc, list_econ_limited); + wells_on_proc, deactivated_wells, list_econ_limited); setupWellControls(wells, timeStep, well_names, pu, wells_on_proc, list_econ_limited); From 10bfa5dfa8b39f3217b64f1e5c6d65b138ee7391 Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Fri, 9 Sep 2016 14:58:14 +0200 Subject: [PATCH 2/5] Use index according to eclipse schedule to identify deactivated wells. --- opm/core/wells/WellsManager.cpp | 2 +- opm/core/wells/WellsManager.hpp | 9 +++++---- opm/core/wells/WellsManager_impl.hpp | 14 +++++++++----- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/opm/core/wells/WellsManager.cpp b/opm/core/wells/WellsManager.cpp index 67dbf29e7..32d763e73 100644 --- a/opm/core/wells/WellsManager.cpp +++ b/opm/core/wells/WellsManager.cpp @@ -341,7 +341,7 @@ namespace Opm UgGridHelpers::dimensions(grid), UgGridHelpers::cell2Faces(grid), UgGridHelpers::beginFaceCentroids(grid), permeability, dummy_list_econ_limited, dummy_well_potentials, - std::set()); + std::set()); } diff --git a/opm/core/wells/WellsManager.hpp b/opm/core/wells/WellsManager.hpp index 5eb42dcb5..4d1c60742 100644 --- a/opm/core/wells/WellsManager.hpp +++ b/opm/core/wells/WellsManager.hpp @@ -78,7 +78,8 @@ namespace Opm /// well productivity indices, otherwise it must be given in /// order to approximate these by the Peaceman formula. /// - /// \param deactivated_wells A set of wells that should be treated + /// \param deactivated_wells The indices (according to the + /// eclipse schedule) of wells that should be treated /// like shut wells. E.g. in a a parallel run these would be /// the wells handeled by another process. Defaults to empty set. template @@ -94,7 +95,7 @@ namespace Opm const DynamicListEconLimited& list_econ_limited, bool is_parallel_run=false, const std::vector& well_potentials={}, - const std::set& deactivated_wells = {}); + const std::set& deactivated_wells = {}); WellsManager(const Opm::EclipseStateConstPtr eclipseState, const size_t timeStep, @@ -164,7 +165,7 @@ namespace Opm const double* permeability, const DynamicListEconLimited& list_econ_limited, const std::vector& well_potentials, - const std::set& deactivated_wells); + const std::set& deactivated_wells); // Disable copying and assignment. WellsManager(const WellsManager& other); WellsManager& operator=(const WellsManager& other); @@ -189,7 +190,7 @@ namespace Opm const double* permeability, const NTG& ntg, std::vector& wells_on_proc, - const std::set& deactivated_wells, + const std::set& deactivated_wells, const DynamicListEconLimited& list_econ_limited); void addChildGroups(GroupTreeNodeConstPtr parentNode, std::shared_ptr< const Schedule > schedule, size_t timeStep, const PhaseUsage& phaseUsage); diff --git a/opm/core/wells/WellsManager_impl.hpp b/opm/core/wells/WellsManager_impl.hpp index 440270b01..57c617340 100644 --- a/opm/core/wells/WellsManager_impl.hpp +++ b/opm/core/wells/WellsManager_impl.hpp @@ -121,7 +121,7 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t const double* permeability, const NTG& ntg, std::vector& wells_on_proc, - const std::set& ignored_wells, + const std::set& ignored_wells, const DynamicListEconLimited& list_econ_limited) { if (dimensions != 3) { @@ -134,6 +134,8 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t wellperf_data.resize(wells.size()); wells_on_proc.resize(wells.size(), 1); + auto ignored_well = ignored_wells.begin(); + // The well index on the current process. // Note that some wells are deactivated as they live on the interior // domain of another proccess. Therefore this might different from @@ -141,9 +143,11 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t int active_well_index = 0; for (auto wellIter= wells.begin(); wellIter != wells.end(); ++wellIter) { const auto* well = (*wellIter); + const int well_index = wellIter - wells.begin(); - if ( ignored_wells.find(well->name()) != ignored_wells.end() ) { - wells_on_proc[ wellIter - wells.begin() ] = 0; + if ( ignored_well != ignored_wells.end() && *ignored_well == well_index ) { + wells_on_proc[ well_index ] = 0; + ++ignored_well; continue; } @@ -317,7 +321,7 @@ WellsManager(const Opm::EclipseStateConstPtr eclipseState, const DynamicListEconLimited& list_econ_limited, bool is_parallel_run, const std::vector& well_potentials, - const std::set& deactivated_wells) + const std::set& deactivated_wells) : w_(0), is_parallel_run_(is_parallel_run) { init(eclipseState, timeStep, number_of_cells, global_cell, @@ -339,7 +343,7 @@ WellsManager::init(const Opm::EclipseStateConstPtr eclipseState, const double* permeability, const DynamicListEconLimited& list_econ_limited, const std::vector& well_potentials, - const std::set& deactivated_wells) + const std::set& deactivated_wells) { if (dimensions != 3) { OPM_THROW(std::runtime_error, From 2875b64fafab883588561287660a23574ddd5e0e Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Mon, 12 Sep 2016 09:44:43 +0200 Subject: [PATCH 3/5] Revert "Use index according to eclipse schedule to identify deactivated wells." This reverts commit 09205dfa074af24b381595d02c15e799523ddb2b. We cannot use the index as it might change for a well between different report steps. Unfortunately the only persistent way to identify wells over all report steps in the schedule seems to be the well name. --- opm/core/wells/WellsManager.cpp | 2 +- opm/core/wells/WellsManager.hpp | 9 ++++----- opm/core/wells/WellsManager_impl.hpp | 14 +++++--------- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/opm/core/wells/WellsManager.cpp b/opm/core/wells/WellsManager.cpp index 32d763e73..67dbf29e7 100644 --- a/opm/core/wells/WellsManager.cpp +++ b/opm/core/wells/WellsManager.cpp @@ -341,7 +341,7 @@ namespace Opm UgGridHelpers::dimensions(grid), UgGridHelpers::cell2Faces(grid), UgGridHelpers::beginFaceCentroids(grid), permeability, dummy_list_econ_limited, dummy_well_potentials, - std::set()); + std::set()); } diff --git a/opm/core/wells/WellsManager.hpp b/opm/core/wells/WellsManager.hpp index 4d1c60742..5eb42dcb5 100644 --- a/opm/core/wells/WellsManager.hpp +++ b/opm/core/wells/WellsManager.hpp @@ -78,8 +78,7 @@ namespace Opm /// well productivity indices, otherwise it must be given in /// order to approximate these by the Peaceman formula. /// - /// \param deactivated_wells The indices (according to the - /// eclipse schedule) of wells that should be treated + /// \param deactivated_wells A set of wells that should be treated /// like shut wells. E.g. in a a parallel run these would be /// the wells handeled by another process. Defaults to empty set. template @@ -95,7 +94,7 @@ namespace Opm const DynamicListEconLimited& list_econ_limited, bool is_parallel_run=false, const std::vector& well_potentials={}, - const std::set& deactivated_wells = {}); + const std::set& deactivated_wells = {}); WellsManager(const Opm::EclipseStateConstPtr eclipseState, const size_t timeStep, @@ -165,7 +164,7 @@ namespace Opm const double* permeability, const DynamicListEconLimited& list_econ_limited, const std::vector& well_potentials, - const std::set& deactivated_wells); + const std::set& deactivated_wells); // Disable copying and assignment. WellsManager(const WellsManager& other); WellsManager& operator=(const WellsManager& other); @@ -190,7 +189,7 @@ namespace Opm const double* permeability, const NTG& ntg, std::vector& wells_on_proc, - const std::set& deactivated_wells, + const std::set& deactivated_wells, const DynamicListEconLimited& list_econ_limited); void addChildGroups(GroupTreeNodeConstPtr parentNode, std::shared_ptr< const Schedule > schedule, size_t timeStep, const PhaseUsage& phaseUsage); diff --git a/opm/core/wells/WellsManager_impl.hpp b/opm/core/wells/WellsManager_impl.hpp index 57c617340..440270b01 100644 --- a/opm/core/wells/WellsManager_impl.hpp +++ b/opm/core/wells/WellsManager_impl.hpp @@ -121,7 +121,7 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t const double* permeability, const NTG& ntg, std::vector& wells_on_proc, - const std::set& ignored_wells, + const std::set& ignored_wells, const DynamicListEconLimited& list_econ_limited) { if (dimensions != 3) { @@ -134,8 +134,6 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t wellperf_data.resize(wells.size()); wells_on_proc.resize(wells.size(), 1); - auto ignored_well = ignored_wells.begin(); - // The well index on the current process. // Note that some wells are deactivated as they live on the interior // domain of another proccess. Therefore this might different from @@ -143,11 +141,9 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t int active_well_index = 0; for (auto wellIter= wells.begin(); wellIter != wells.end(); ++wellIter) { const auto* well = (*wellIter); - const int well_index = wellIter - wells.begin(); - if ( ignored_well != ignored_wells.end() && *ignored_well == well_index ) { - wells_on_proc[ well_index ] = 0; - ++ignored_well; + if ( ignored_wells.find(well->name()) != ignored_wells.end() ) { + wells_on_proc[ wellIter - wells.begin() ] = 0; continue; } @@ -321,7 +317,7 @@ WellsManager(const Opm::EclipseStateConstPtr eclipseState, const DynamicListEconLimited& list_econ_limited, bool is_parallel_run, const std::vector& well_potentials, - const std::set& deactivated_wells) + const std::set& deactivated_wells) : w_(0), is_parallel_run_(is_parallel_run) { init(eclipseState, timeStep, number_of_cells, global_cell, @@ -343,7 +339,7 @@ WellsManager::init(const Opm::EclipseStateConstPtr eclipseState, const double* permeability, const DynamicListEconLimited& list_econ_limited, const std::vector& well_potentials, - const std::set& deactivated_wells) + const std::set& deactivated_wells) { if (dimensions != 3) { OPM_THROW(std::runtime_error, From 60ba51aea0bd44e522ca47ffa0d3ff904993ee20 Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Mon, 12 Sep 2016 12:02:20 +0200 Subject: [PATCH 4/5] Do exclude SHUT wells from lookup of deactivated wells. This should be prevent some unnecessary find calls in the set. --- opm/core/wells/WellsManager_impl.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opm/core/wells/WellsManager_impl.hpp b/opm/core/wells/WellsManager_impl.hpp index 440270b01..c19a885e0 100644 --- a/opm/core/wells/WellsManager_impl.hpp +++ b/opm/core/wells/WellsManager_impl.hpp @@ -142,12 +142,12 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t for (auto wellIter= wells.begin(); wellIter != wells.end(); ++wellIter) { const auto* well = (*wellIter); - if ( ignored_wells.find(well->name()) != ignored_wells.end() ) { - wells_on_proc[ wellIter - wells.begin() ] = 0; + if (well->getStatus(timeStep) == WellCommon::SHUT) { continue; } - if (well->getStatus(timeStep) == WellCommon::SHUT) { + if ( ignored_wells.find(well->name()) != ignored_wells.end() ) { + wells_on_proc[ wellIter - wells.begin() ] = 0; continue; } From 29dc9a1880963494f7bea1291980094096487661 Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Mon, 12 Sep 2016 12:03:39 +0200 Subject: [PATCH 5/5] Use an unordered_set of string to identify defunct wells. We do not rely on the order of the set and hope that the lookup might be faster as it prevents string comparisons. --- opm/core/wells/WellsManager.cpp | 2 +- opm/core/wells/WellsManager.hpp | 7 ++++--- opm/core/wells/WellsManager_impl.hpp | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/opm/core/wells/WellsManager.cpp b/opm/core/wells/WellsManager.cpp index 67dbf29e7..897d5301a 100644 --- a/opm/core/wells/WellsManager.cpp +++ b/opm/core/wells/WellsManager.cpp @@ -341,7 +341,7 @@ namespace Opm UgGridHelpers::dimensions(grid), UgGridHelpers::cell2Faces(grid), UgGridHelpers::beginFaceCentroids(grid), permeability, dummy_list_econ_limited, dummy_well_potentials, - std::set()); + std::unordered_set()); } diff --git a/opm/core/wells/WellsManager.hpp b/opm/core/wells/WellsManager.hpp index 5eb42dcb5..56e2526a4 100644 --- a/opm/core/wells/WellsManager.hpp +++ b/opm/core/wells/WellsManager.hpp @@ -20,6 +20,7 @@ #ifndef OPM_WELLSMANAGER_HEADER_INCLUDED #define OPM_WELLSMANAGER_HEADER_INCLUDED +#include #include @@ -94,7 +95,7 @@ namespace Opm const DynamicListEconLimited& list_econ_limited, bool is_parallel_run=false, const std::vector& well_potentials={}, - const std::set& deactivated_wells = {}); + const std::unordered_set& deactivated_wells = {}); WellsManager(const Opm::EclipseStateConstPtr eclipseState, const size_t timeStep, @@ -164,7 +165,7 @@ namespace Opm const double* permeability, const DynamicListEconLimited& list_econ_limited, const std::vector& well_potentials, - const std::set& deactivated_wells); + const std::unordered_set& deactivated_wells); // Disable copying and assignment. WellsManager(const WellsManager& other); WellsManager& operator=(const WellsManager& other); @@ -189,7 +190,7 @@ namespace Opm const double* permeability, const NTG& ntg, std::vector& wells_on_proc, - const std::set& deactivated_wells, + const std::unordered_set& deactivated_wells, const DynamicListEconLimited& list_econ_limited); void addChildGroups(GroupTreeNodeConstPtr parentNode, std::shared_ptr< const Schedule > schedule, size_t timeStep, const PhaseUsage& phaseUsage); diff --git a/opm/core/wells/WellsManager_impl.hpp b/opm/core/wells/WellsManager_impl.hpp index c19a885e0..48196744a 100644 --- a/opm/core/wells/WellsManager_impl.hpp +++ b/opm/core/wells/WellsManager_impl.hpp @@ -121,7 +121,7 @@ void WellsManager::createWellsFromSpecs(std::vector& wells, size_t const double* permeability, const NTG& ntg, std::vector& wells_on_proc, - const std::set& ignored_wells, + const std::unordered_set& ignored_wells, const DynamicListEconLimited& list_econ_limited) { if (dimensions != 3) { @@ -317,7 +317,7 @@ WellsManager(const Opm::EclipseStateConstPtr eclipseState, const DynamicListEconLimited& list_econ_limited, bool is_parallel_run, const std::vector& well_potentials, - const std::set& deactivated_wells) + const std::unordered_set& deactivated_wells) : w_(0), is_parallel_run_(is_parallel_run) { init(eclipseState, timeStep, number_of_cells, global_cell, @@ -339,7 +339,7 @@ WellsManager::init(const Opm::EclipseStateConstPtr eclipseState, const double* permeability, const DynamicListEconLimited& list_econ_limited, const std::vector& well_potentials, - const std::set& deactivated_wells) + const std::unordered_set& deactivated_wells) { if (dimensions != 3) { OPM_THROW(std::runtime_error,