Add MaxPressure NLDD domain ordering option, make it default.

This commit is contained in:
Atgeirr Flø Rasmussen
2023-11-15 09:36:01 +01:00
parent 9c9fae26a8
commit 8acc8af2a4
3 changed files with 36 additions and 22 deletions

View File

@@ -695,26 +695,33 @@ private:
const auto& solution = ebosSimulator.model().solution(0);
std::vector<int> domain_order(domains_.size());
switch (model_.param().local_solve_approach_) {
case DomainSolveApproach::GaussSeidel: {
// Calculate the measure used to order the domains.
std::vector<std::pair<double, int>> measure_per_domain(domains_.size());
switch (model_.param().local_domain_ordering_) {
case DomainOrderingMeasure::AveragePressure: {
// Use average pressures to order domains.
std::vector<std::pair<double, int>> avgpress_per_domain(domains_.size());
for (const auto& domain : domains_) {
double press_sum = 0.0;
for (const int c : domain.cells) {
press_sum += solution[c][Indices::pressureSwitchIdx];
}
const double avgpress = press_sum / domain.cells.size();
avgpress_per_domain[domain.index] = std::make_pair(avgpress, domain.index);
measure_per_domain[domain.index] = std::make_pair(avgpress, domain.index);
}
// Lexicographical sort by pressure, then index.
std::sort(avgpress_per_domain.begin(), avgpress_per_domain.end());
// Reverse since we want high-pressure regions solved first.
std::reverse(avgpress_per_domain.begin(), avgpress_per_domain.end());
for (std::size_t ii = 0; ii < domains_.size(); ++ii) {
domain_order[ii] = avgpress_per_domain[ii].second;
break;
}
case DomainOrderingMeasure::MaxPressure: {
// Use max pressures to order domains.
std::vector<std::pair<double, int>> maxpress_per_domain(domains_.size());
for (const auto& domain : domains_) {
double maxpress = 0.0;
for (const int c : domain.cells) {
maxpress = std::max(maxpress, solution[c][Indices::pressureSwitchIdx]);
}
measure_per_domain[domain.index] = std::make_pair(maxpress, domain.index);
}
break;
}
@@ -730,20 +737,24 @@ private:
maxres = std::max(maxres, std::fabs(residual[c][ii]));
}
}
maxres_per_domain[domain.index] = std::make_pair(maxres, domain.index);
}
// Lexicographical sort by pressure, then index.
std::sort(maxres_per_domain.begin(), maxres_per_domain.end());
// Reverse since we want high-pressure regions solved first.
std::reverse(maxres_per_domain.begin(), maxres_per_domain.end());
for (std::size_t ii = 0; ii < domains_.size(); ++ii) {
domain_order[ii] = maxres_per_domain[ii].second;
measure_per_domain[domain.index] = std::make_pair(maxres, domain.index);
}
break;
}
break;
} // end of switch (model_.param().local_domain_ordering_)
// Sort by largest measure, keeping index order if equal.
std::stable_sort(measure_per_domain.begin(), measure_per_domain.end(),
[](const auto& m1, const auto& m2){ return m1.first > m2.first; });
// Assign domain order.
for (std::size_t ii = 0; ii < domains_.size(); ++ii) {
domain_order[ii] = measure_per_domain[ii].second;
}
break;
}
} // end of case DomainSolveApproach::GaussSeidel
case DomainSolveApproach::Jacobi:
default:

View File

@@ -439,7 +439,7 @@ struct LocalDomainsPartitioningMethod<TypeTag, TTag::FlowModelParameters> {
};
template<class TypeTag>
struct LocalDomainsOrderingMeasure<TypeTag, TTag::FlowModelParameters> {
static constexpr auto value = "pressure";
static constexpr auto value = "maxpressure";
};
// if openMP is available, determine the number threads per process automatically.
#if _OPENMP
@@ -579,7 +579,7 @@ namespace Opm
int num_local_domains_{0};
double local_domain_partition_imbalance_{1.03};
std::string local_domain_partition_method_;
DomainOrderingMeasure local_domain_ordering_{DomainOrderingMeasure::AveragePressure};
DomainOrderingMeasure local_domain_ordering_{DomainOrderingMeasure::MaxPressure};
bool write_partitions_{false};
@@ -642,7 +642,9 @@ namespace Opm
std::string measure = EWOMS_GET_PARAM(TypeTag, std::string, LocalDomainsOrderingMeasure);
if (measure == "residual") {
local_domain_ordering_ = DomainOrderingMeasure::Residual;
} else if (measure == "pressure") {
} else if (measure == "maxpressure") {
local_domain_ordering_ = DomainOrderingMeasure::MaxPressure;
} else if (measure == "averagepressure") {
local_domain_ordering_ = DomainOrderingMeasure::AveragePressure;
} else {
throw std::runtime_error("Invalid domain ordering '" + measure + "' specified.");
@@ -701,7 +703,7 @@ namespace Opm
EWOMS_REGISTER_PARAM(TypeTag, std::string, LocalDomainsPartitioningMethod, "Subdomain partitioning method. "
"Allowed values are 'zoltan', 'simple', and the name of a partition file ending with '.partition'.");
EWOMS_REGISTER_PARAM(TypeTag, std::string, LocalDomainsOrderingMeasure, "Subdomain ordering measure. "
"Allowed values are 'pressure' and 'residual'.");
"Allowed values are 'maxpressure', 'averagepressure' and 'residual'.");
EWOMS_REGISTER_PARAM(TypeTag, bool, DebugEmitCellPartition, "Whether or not to emit cell partitions as a debugging aid.");

View File

@@ -36,6 +36,7 @@ namespace Opm
//! \brief Measure to use for domain ordering.
enum class DomainOrderingMeasure {
AveragePressure,
MaxPressure,
Residual
};