mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #4738 from akva2/blackoilmodelebos_domain_ordering
BlackoilModelEbos: improve domain ordering
This commit is contained in:
commit
cc0b994eca
@ -534,52 +534,7 @@ namespace Opm {
|
|||||||
auto locally_solved = initial_solution;
|
auto locally_solved = initial_solution;
|
||||||
|
|
||||||
// ----------- Decide on an ordering for the domains -----------
|
// ----------- Decide on an ordering for the domains -----------
|
||||||
std::vector<int> domain_order(domains_.size());
|
const auto domain_order = this->getSubdomainOrder();
|
||||||
if (param_.local_solve_approach_ == "gauss-seidel") {
|
|
||||||
// TODO: enable flexibility and choice in choosing domain ordering approach.
|
|
||||||
if (true) {
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
// 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 (size_t ii = 0; ii < domains_.size(); ++ii) {
|
|
||||||
domain_order[ii] = avgpress_per_domain[ii].second;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Use maximum residual to order domains.
|
|
||||||
const auto& residual = ebosSimulator_.model().linearizer().residual();
|
|
||||||
const int num_vars = residual[0].size();
|
|
||||||
std::vector<std::pair<double, int>> maxres_per_domain(domains_.size());
|
|
||||||
for (const auto& domain : domains_) {
|
|
||||||
double maxres = 0.0;
|
|
||||||
for (const int c : domain.cells) {
|
|
||||||
for (int ii = 0; ii < num_vars; ++ii) {
|
|
||||||
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 (size_t ii = 0; ii < domains_.size(); ++ii) {
|
|
||||||
domain_order[ii] = maxres_per_domain[ii].second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::iota(domain_order.begin(), domain_order.end(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------- Solve each domain separately -----------
|
// ----------- Solve each domain separately -----------
|
||||||
std::vector<SimulatorReportSingle> domain_reports(domains_.size());
|
std::vector<SimulatorReportSingle> domain_reports(domains_.size());
|
||||||
@ -1833,6 +1788,64 @@ namespace Opm {
|
|||||||
double maxResidualAllowed() const { return param_.max_residual_allowed_; }
|
double maxResidualAllowed() const { return param_.max_residual_allowed_; }
|
||||||
double linear_solve_setup_time_;
|
double linear_solve_setup_time_;
|
||||||
|
|
||||||
|
//! \brief Returns subdomain ordered according to method and ordering measure.
|
||||||
|
std::vector<int> getSubdomainOrder()
|
||||||
|
{
|
||||||
|
const auto& solution = ebosSimulator().model().solution(0);
|
||||||
|
|
||||||
|
std::vector<int> domain_order(domains_.size());
|
||||||
|
if (param_.local_solve_approach_ == "gauss-seidel") {
|
||||||
|
switch (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);
|
||||||
|
}
|
||||||
|
// 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 (size_t ii = 0; ii < domains_.size(); ++ii) {
|
||||||
|
domain_order[ii] = avgpress_per_domain[ii].second;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DomainOrderingMeasure::Residual: {
|
||||||
|
// Use maximum residual to order domains.
|
||||||
|
const auto& residual = ebosSimulator().model().linearizer().residual();
|
||||||
|
const int num_vars = residual[0].size();
|
||||||
|
std::vector<std::pair<double, int>> maxres_per_domain(domains_.size());
|
||||||
|
for (const auto& domain : domains_) {
|
||||||
|
double maxres = 0.0;
|
||||||
|
for (const int c : domain.cells) {
|
||||||
|
for (int ii = 0; ii < num_vars; ++ii) {
|
||||||
|
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 (size_t ii = 0; ii < domains_.size(); ++ii) {
|
||||||
|
domain_order[ii] = maxres_per_domain[ii].second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::iota(domain_order.begin(), domain_order.end(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain_order;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<bool> wasSwitched_;
|
std::vector<bool> wasSwitched_;
|
||||||
};
|
};
|
||||||
|
@ -20,9 +20,15 @@
|
|||||||
#ifndef OPM_BLACKOILMODELPARAMETERS_EBOS_HEADER_INCLUDED
|
#ifndef OPM_BLACKOILMODELPARAMETERS_EBOS_HEADER_INCLUDED
|
||||||
#define OPM_BLACKOILMODELPARAMETERS_EBOS_HEADER_INCLUDED
|
#define OPM_BLACKOILMODELPARAMETERS_EBOS_HEADER_INCLUDED
|
||||||
|
|
||||||
#include <opm/models/utils/propertysystem.hh>
|
#include <opm/models/discretization/common/fvbaseproperties.hh>
|
||||||
#include <opm/models/utils/parametersystem.hh>
|
|
||||||
|
|
||||||
|
#include <opm/models/utils/basicproperties.hh>
|
||||||
|
#include <opm/models/utils/parametersystem.hh>
|
||||||
|
#include <opm/models/utils/propertysystem.hh>
|
||||||
|
|
||||||
|
#include <opm/simulators/flow/SubDomain.hpp>
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace Opm::Properties {
|
namespace Opm::Properties {
|
||||||
@ -209,6 +215,10 @@ template<class TypeTag, class MyTypeTag>
|
|||||||
struct LocalDomainsPartitioningMethod {
|
struct LocalDomainsPartitioningMethod {
|
||||||
using type = UndefinedProperty;
|
using type = UndefinedProperty;
|
||||||
};
|
};
|
||||||
|
template<class TypeTag, class MyTypeTag>
|
||||||
|
struct LocalDomainsOrderingMeasure {
|
||||||
|
using type = UndefinedProperty;
|
||||||
|
};
|
||||||
template<class TypeTag>
|
template<class TypeTag>
|
||||||
struct DbhpMaxRel<TypeTag, TTag::FlowModelParameters> {
|
struct DbhpMaxRel<TypeTag, TTag::FlowModelParameters> {
|
||||||
using type = GetPropType<TypeTag, Scalar>;
|
using type = GetPropType<TypeTag, Scalar>;
|
||||||
@ -401,6 +411,10 @@ template<class TypeTag>
|
|||||||
struct LocalDomainsPartitioningMethod<TypeTag, TTag::FlowModelParameters> {
|
struct LocalDomainsPartitioningMethod<TypeTag, TTag::FlowModelParameters> {
|
||||||
static constexpr auto value = "zoltan";
|
static constexpr auto value = "zoltan";
|
||||||
};
|
};
|
||||||
|
template<class TypeTag>
|
||||||
|
struct LocalDomainsOrderingMeasure<TypeTag, TTag::FlowModelParameters> {
|
||||||
|
static constexpr auto value = "pressure";
|
||||||
|
};
|
||||||
// if openMP is available, determine the number threads per process automatically.
|
// if openMP is available, determine the number threads per process automatically.
|
||||||
#if _OPENMP
|
#if _OPENMP
|
||||||
template<class TypeTag>
|
template<class TypeTag>
|
||||||
@ -535,6 +549,7 @@ namespace Opm
|
|||||||
int num_local_domains_{0};
|
int num_local_domains_{0};
|
||||||
double local_domain_partition_imbalance_{1.03};
|
double local_domain_partition_imbalance_{1.03};
|
||||||
std::string local_domain_partition_method_;
|
std::string local_domain_partition_method_;
|
||||||
|
DomainOrderingMeasure local_domain_ordering_{DomainOrderingMeasure::AveragePressure};
|
||||||
|
|
||||||
/// Construct from user parameters or defaults.
|
/// Construct from user parameters or defaults.
|
||||||
BlackoilModelParametersEbos()
|
BlackoilModelParametersEbos()
|
||||||
@ -581,7 +596,15 @@ namespace Opm
|
|||||||
local_domain_partition_method_ = EWOMS_GET_PARAM(TypeTag, std::string, LocalDomainsPartitioningMethod);
|
local_domain_partition_method_ = EWOMS_GET_PARAM(TypeTag, std::string, LocalDomainsPartitioningMethod);
|
||||||
deck_file_name_ = EWOMS_GET_PARAM(TypeTag, std::string, EclDeckFileName);
|
deck_file_name_ = EWOMS_GET_PARAM(TypeTag, std::string, EclDeckFileName);
|
||||||
network_max_strict_iterations_ = EWOMS_GET_PARAM(TypeTag, int, NetworkMaxStrictIterations);
|
network_max_strict_iterations_ = EWOMS_GET_PARAM(TypeTag, int, NetworkMaxStrictIterations);
|
||||||
network_max_iterations_ = EWOMS_GET_PARAM(TypeTag, int, NetworkMaxIterations);
|
network_max_iterations_ = EWOMS_GET_PARAM(TypeTag, int, NetworkMaxIterations);
|
||||||
|
std::string measure = EWOMS_GET_PARAM(TypeTag, std::string, LocalDomainsOrderingMeasure);
|
||||||
|
if (measure == "residual") {
|
||||||
|
local_domain_ordering_ = DomainOrderingMeasure::Residual;
|
||||||
|
} else if (measure == "pressure") {
|
||||||
|
local_domain_ordering_ = DomainOrderingMeasure::AveragePressure;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Invalid domain ordering '" + measure + "' specified.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registerParameters()
|
static void registerParameters()
|
||||||
@ -631,6 +654,8 @@ namespace Opm
|
|||||||
EWOMS_REGISTER_PARAM(TypeTag, Scalar, LocalDomainsPartitioningImbalance, "Subdomain partitioning imbalance tolerance. 1.03 is 3 percent imbalance.");
|
EWOMS_REGISTER_PARAM(TypeTag, Scalar, LocalDomainsPartitioningImbalance, "Subdomain partitioning imbalance tolerance. 1.03 is 3 percent imbalance.");
|
||||||
EWOMS_REGISTER_PARAM(TypeTag, std::string, LocalDomainsPartitioningMethod, "Subdomain partitioning method. "
|
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'.");
|
"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'.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
@ -28,6 +28,12 @@
|
|||||||
namespace Opm
|
namespace Opm
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//! \brief Measure to use for domain ordering.
|
||||||
|
enum class DomainOrderingMeasure {
|
||||||
|
AveragePressure,
|
||||||
|
Residual
|
||||||
|
};
|
||||||
|
|
||||||
/// Representing a part of a grid, in a way suitable for performing
|
/// Representing a part of a grid, in a way suitable for performing
|
||||||
/// local solves.
|
/// local solves.
|
||||||
template <class Grid>
|
template <class Grid>
|
||||||
|
Loading…
Reference in New Issue
Block a user