Info message, cmdline option and avoid splitting wells on restart (for now)

This commit is contained in:
Vegard Kippe
2024-10-22 20:29:24 +02:00
parent 729d3c2a59
commit 7f6c7aec01
7 changed files with 55 additions and 33 deletions

View File

@@ -228,7 +228,9 @@ public:
this->doLoadBalance_(this->edgeWeightsMethod(), this->ownersFirst(),
this->partitionMethod(), this->serialPartitioning(),
this->enableDistributedWells(), this->imbalanceTol(),
this->enableDistributedWells(),
this->allow_splitting_inactive_wells_,
this->imbalanceTol(),
this->gridView(), this->schedule(),
this->eclState(), this->parallelWells_,
this->numJacobiBlocks());

View File

@@ -139,6 +139,7 @@ public:
externalPartitionFile_ = Parameters::Get<Parameters::ExternalPartition>();
#endif
enableDistributedWells_ = Parameters::Get<Parameters::AllowDistributedWells>();
allow_splitting_inactive_wells_ = Parameters::Get<Parameters::AllowSplittingInactiveWells>();
ignoredKeywords_ = Parameters::Get<Parameters::IgnoreKeywords>();
int output_param = Parameters::Get<Parameters::EclOutputInterval>();
if (output_param >= 0)

View File

@@ -457,6 +457,8 @@ void FlowGenericVanguard::registerParameters_()
#endif
Parameters::Register<Parameters::AllowDistributedWells>
("Allow the perforations of a well to be distributed to interior of multiple processes");
Parameters::Register<Parameters::AllowSplittingInactiveWells>
("Allow inactive (never non-shut) wells to be split across multiple domains");
// register here for the use in the tests without BlackoilModelParameters
Parameters::Register<Parameters::UseMultisegmentWell>
("Use the well model for multi-segment wells instead of the one for single-segment wells");

View File

@@ -48,6 +48,8 @@
namespace Opm::Parameters {
struct AllowDistributedWells { static constexpr bool value = false; };
struct AllowSplittingInactiveWells { static constexpr bool value = true; };
struct EclOutputInterval { static constexpr int value = -1; };
struct EdgeWeightsMethod { static constexpr int value = 1; };
struct EnableDryRun { static constexpr auto value = "auto"; };
@@ -360,6 +362,8 @@ protected:
std::string externalPartitionFile_{};
#endif
bool enableDistributedWells_;
bool allow_splitting_inactive_wells_;
std::string ignoredKeywords_;
std::optional<int> outputInterval_;
bool useMultisegmentWell_;

View File

@@ -150,6 +150,7 @@ doLoadBalance_(const Dune::EdgeWeightMethod edgeWeightsMethod,
const Dune::PartitionMethod partitionMethod,
const bool serialPartitioning,
const bool enableDistributedWells,
const bool allowSplittingInactiveWells,
const double imbalanceTol,
const GridView& gridView,
const Schedule& schedule,
@@ -194,9 +195,15 @@ doLoadBalance_(const Dune::EdgeWeightMethod edgeWeightsMethod,
}
}
// Skipping inactive wells in partitioning currently does not play nice with restart..
const bool restart = eclState1.getInitConfig().restartRequested();
const bool split_inactive = (!restart && allowSplittingInactiveWells);
const auto wells = ((mpiSize > 1) || partitionJacobiBlocks)
? schedule.getActiveWellsAtEnd()
? split_inactive
? schedule.getActiveWellsAtEnd()
: schedule.getWellsatEnd()
: std::vector<Well>{};
const auto& possibleFutureConnections = schedule.getPossibleFutureConnections();
// Distribute the grid and switch to the distributed view.
if (mpiSize > 1) {
@@ -209,36 +216,44 @@ doLoadBalance_(const Dune::EdgeWeightMethod edgeWeightsMethod,
}
// Add inactive wells to all ranks with connections (not solved, so OK even without distributed wells)
std::unordered_set<unsigned> cellOnRank;
const auto& global_cells = this->grid_->globalCell();
for (const auto cell : global_cells) cellOnRank.insert(cell);
const auto& comm = this->grid_->comm();
const auto nranks = comm.size();
const auto inactive_well_names = schedule.getInactiveWellNamesAtEnd();
std::size_t num_wells = inactive_well_names.size();
std::vector<int> well_on_rank(num_wells, 0);
std::size_t well_idx = 0;
for (const auto& well_name : inactive_well_names) {
const auto& well = schedule.getWell(well_name, schedule.size()-1);
for (const auto& conn: well.getConnections()) {
if (cellOnRank.count(conn.global_index()) > 0) {
well_on_rank[well_idx] = 1;
break;
if (split_inactive) {
std::unordered_set<unsigned> cellOnRank;
const auto& global_cells = this->grid_->globalCell();
for (const auto cell : global_cells) cellOnRank.insert(cell);
const auto inactive_well_names = schedule.getInactiveWellNamesAtEnd();
std::size_t num_wells = inactive_well_names.size();
std::vector<int> well_on_rank(num_wells, 0);
std::size_t well_idx = 0;
for (const auto& well_name : inactive_well_names) {
const auto& well = schedule.getWell(well_name, schedule.size()-1);
for (const auto& conn: well.getConnections()) {
if (cellOnRank.count(conn.global_index()) > 0) {
well_on_rank[well_idx] = 1;
parallelWells.emplace_back(well_name, true);
break;
}
}
if (!well_on_rank[well_idx]) parallelWells.emplace_back(well_name, false);
++well_idx;
}
// Provide information message
const auto& comm = this->grid_->comm();
const auto nranks = comm.size();
// // values from rank i will be at indices i*num_wells, i*num_wells + 1, ..., (i+1) * num_wells -1
std::vector<int> well_on_rank_global(num_wells * nranks, 0);
comm.allgather(well_on_rank.data(), static_cast<int>(num_wells), well_on_rank_global.data());
if (comm.rank() == 0) {
well_idx = 0;
for (const auto& well_name : inactive_well_names) {
std::string msg = fmt::format("Well {} is inactive, with perforations on ranks: ", well_name);
for (int i=0; i<nranks; ++i) {
if (well_on_rank_global[i*num_wells + well_idx]) msg += fmt::format("{} ", i);
}
OpmLog::info(msg);
++well_idx;
}
}
++well_idx;
}
// values from rank i will be at indices i*num_wells, i*num_wells + 1, ..., (i+1) * num_wells -1
std::vector<int> well_on_rank_global(num_wells * nranks, 0);
comm.allgather(well_on_rank.data(), static_cast<int>(num_wells), well_on_rank_global.data());
well_idx = 0;
for (const auto& well_name : inactive_well_names) {
for (int i=0; i<nranks; ++i) {
if (well_on_rank_global[i*num_wells + well_idx]) {
parallelWells.emplace_back(well_name, true);
}
}
++well_idx;
}
std::sort(parallelWells.begin(), parallelWells.end());

View File

@@ -153,6 +153,7 @@ protected:
const Dune::PartitionMethod partitionMethod,
const bool serialPartitioning,
const bool enableDistributedWells,
const bool allowSplittingInactiveWells,
const double imbalanceTol,
const GridView& gridView,
const Schedule& schedule,

View File

@@ -695,9 +695,6 @@ void WellState<Scalar>::initWellStateMSWell(const std::vector<Well>& wells_ecl,
for (int w = 0; w < nw; ++w) {
const auto& well_ecl = wells_ecl[w];
auto& ws = this->well(w);
// If the phase_rates has zero size this is an inactive well that will never be solved
if (ws.perf_data.phase_rates.size() == 0)
continue;
if (well_ecl.isMultiSegment()) {
const WellSegments& segment_set = well_ecl.getSegments();