partitionCells: drop indent for namespace

This commit is contained in:
Arne Morten Kvarving 2023-06-29 12:41:56 +02:00
parent e8f04eec68
commit b95b342517
2 changed files with 129 additions and 131 deletions

View File

@ -44,140 +44,139 @@
namespace { namespace {
std::pair<std::vector<int>, int> std::pair<std::vector<int>, int>
countDomains(std::vector<int> partition_vector) countDomains(std::vector<int> partition_vector)
{ {
auto maxPos = std::max_element(partition_vector.begin(), auto maxPos = std::max_element(partition_vector.begin(),
partition_vector.end()); partition_vector.end());
const auto num_domains = (maxPos == partition_vector.end()) const auto num_domains = (maxPos == partition_vector.end())
? 0 : *maxPos + 1; ? 0 : *maxPos + 1;
return { std::move(partition_vector), num_domains }; return { std::move(partition_vector), num_domains };
} }
template <typename, class = void> template <typename, class = void>
struct HasZoltanPartitioning : public std::false_type {}; struct HasZoltanPartitioning : public std::false_type {};
template <typename GridType> template <typename GridType>
struct HasZoltanPartitioning< struct HasZoltanPartitioning<
GridType, GridType,
std::void_t<decltype(std::declval<const GridType&>().zoltanPartitionWithoutScatter std::void_t<decltype(std::declval<const GridType&>().zoltanPartitionWithoutScatter
(std::declval<const std::vector<Opm::Well>*>(), (std::declval<const std::vector<Opm::Well>*>(),
std::declval<const double*>(), std::declval<const double*>(),
std::declval<const int>(), std::declval<const int>(),
std::declval<const double>()))> std::declval<const double>()))>
> : public std::true_type {}; > : public std::true_type {};
} // anonymous namespace } // anonymous namespace
namespace Opm { namespace Opm {
template<class Grid> template<class Grid>
std::pair<std::vector<int>, int> partitionCells(const Grid& grid, std::pair<std::vector<int>, int> partitionCells(const Grid& grid,
const std::vector<Well>& wells, const std::vector<Well>& wells,
const std::string& method, const std::string& method,
const int num_local_domains, const int num_local_domains,
const double partition_imbalance) const double partition_imbalance)
{ {
if (method == "zoltan") { if (method == "zoltan") {
if constexpr (HasZoltanPartitioning<Grid>::value) { if constexpr (HasZoltanPartitioning<Grid>::value) {
return partitionCellsZoltan(grid, wells, num_local_domains, partition_imbalance); return partitionCellsZoltan(grid, wells, num_local_domains, partition_imbalance);
} else {
OPM_THROW(std::runtime_error, "Zoltan requested for local domain partitioning, "
"but is not available for the current grid type.");
}
} else if (method == "simple") {
const int num_cells = detail::countLocalInteriorCells(grid);
return partitionCellsSimple(num_cells, num_local_domains);
} else if (method.size() > 10 && method.substr(method.size() - 10, 10) == ".partition") {
// Method string ends with ".partition", interpret as filename for partitioning.
const int num_cells = detail::countLocalInteriorCells(grid);
return partitionCellsFromFile(method, num_cells);
} else { } else {
OPM_THROW(std::runtime_error, "Unknown local domain partitioning method requested: " + method); OPM_THROW(std::runtime_error, "Zoltan requested for local domain partitioning, "
"but is not available for the current grid type.");
} }
} else if (method == "simple") {
const int num_cells = detail::countLocalInteriorCells(grid);
return partitionCellsSimple(num_cells, num_local_domains);
} else if (method.size() > 10 && method.substr(method.size() - 10, 10) == ".partition") {
// Method string ends with ".partition", interpret as filename for partitioning.
const int num_cells = detail::countLocalInteriorCells(grid);
return partitionCellsFromFile(method, num_cells);
} else {
OPM_THROW(std::runtime_error, "Unknown local domain partitioning method requested: " + method);
}
}
// Read from file, containing one number per cell.
std::pair<std::vector<int>, int> partitionCellsFromFile(const std::string& filename, const int num_cells)
{
// Read file into single vector.
std::ifstream is(filename);
const std::vector<int> cellpart{std::istream_iterator<int>(is), std::istream_iterator<int>()};
if (cellpart.size() != size_t(num_cells)) {
auto msg = fmt::format("Partition file contains {} entries, but there are {} cells.",
cellpart.size(), num_cells);
throw std::runtime_error(msg);
} }
// Create and return the output domain vector.
const int num_domains = (*std::max_element(cellpart.begin(), cellpart.end())) + 1;
return { cellpart, num_domains };
}
// Read from file, containing one number per cell.
std::pair<std::vector<int>, int> partitionCellsFromFile(const std::string& filename, const int num_cells)
{
// Read file into single vector.
std::ifstream is(filename);
const std::vector<int> cellpart{std::istream_iterator<int>(is), std::istream_iterator<int>()};
if (cellpart.size() != size_t(num_cells)) {
auto msg = fmt::format("Partition file contains {} entries, but there are {} cells.",
cellpart.size(), num_cells);
throw std::runtime_error(msg);
}
// Create and return the output domain vector. // Trivially simple partitioner
const int num_domains = (*std::max_element(cellpart.begin(), cellpart.end())) + 1; std::pair<std::vector<int>, int> partitionCellsSimple(const int num_cells, const int num_domains)
return { cellpart, num_domains }; {
// Build the partitions.
const int dom_sz = num_cells / num_domains;
std::vector<int> bounds(num_domains + 1, dom_sz);
bounds[0] = 0;
for (int i = 0; i < num_cells % num_domains; ++i) {
++bounds[i + 1];
} }
std::partial_sum(bounds.begin(), bounds.end(), bounds.begin());
assert(bounds[num_domains] == num_cells);
// Trivially simple partitioner std::vector<int> part(num_cells);
std::pair<std::vector<int>, int> partitionCellsSimple(const int num_cells, const int num_domains) for (int i = 0; i < num_domains; ++i) {
{ std::fill(part.begin() + bounds[i], part.begin() + bounds[i + 1], i);
// Build the partitions.
const int dom_sz = num_cells / num_domains;
std::vector<int> bounds(num_domains + 1, dom_sz);
bounds[0] = 0;
for (int i = 0; i < num_cells % num_domains; ++i) {
++bounds[i + 1];
}
std::partial_sum(bounds.begin(), bounds.end(), bounds.begin());
assert(bounds[num_domains] == num_cells);
std::vector<int> part(num_cells);
for (int i = 0; i < num_domains; ++i) {
std::fill(part.begin() + bounds[i], part.begin() + bounds[i + 1], i);
}
return { part, num_domains };
} }
return { part, num_domains };
}
template<class Grid> template<class Grid>
std::pair<std::vector<int>, int> partitionCellsZoltan(const Grid& grid, std::pair<std::vector<int>, int> partitionCellsZoltan(const Grid& grid,
const std::vector<Well>& wells, const std::vector<Well>& wells,
const int num_domains, const int num_domains,
const double domain_imbalance) const double domain_imbalance)
{ {
auto partition_vector = grid.zoltanPartitionWithoutScatter auto partition_vector = grid.zoltanPartitionWithoutScatter
(&wells, nullptr, num_domains, domain_imbalance); (&wells, nullptr, num_domains, domain_imbalance);
return countDomains(std::move(partition_vector)); return countDomains(std::move(partition_vector));
} }
template std::pair<std::vector<int>,int> template std::pair<std::vector<int>,int>
partitionCells<Dune::CpGrid>(const Dune::CpGrid&, partitionCells<Dune::CpGrid>(const Dune::CpGrid&,
const std::vector<Well>&, const std::vector<Well>&,
const std::string&, const std::string&,
const int, const int,
const double); const double);
template std::pair<std::vector<int>,int> template std::pair<std::vector<int>,int>
partitionCells<Dune::PolyhedralGrid<3,3,double>>(const Dune::PolyhedralGrid<3,3,double>&, partitionCells<Dune::PolyhedralGrid<3,3,double>>(const Dune::PolyhedralGrid<3,3,double>&,
const std::vector<Well>&, const std::vector<Well>&,
const std::string&, const std::string&,
const int, const int,
const double); const double);
#if HAVE_DUNE_ALUGRID #if HAVE_DUNE_ALUGRID
#if HAVE_MPI #if HAVE_MPI
using ALUGrid3CN = Dune::ALUGrid<3, 3, Dune::cube, Dune::nonconforming, Dune::ALUGridMPIComm>; using ALUGrid3CN = Dune::ALUGrid<3, 3, Dune::cube, Dune::nonconforming, Dune::ALUGridMPIComm>;
#else #else
using ALUGrid3CN = Dune::ALUGrid<3, 3, Dune::cube, Dune::nonconforming, Dune::ALUGridNoComm>; using ALUGrid3CN = Dune::ALUGrid<3, 3, Dune::cube, Dune::nonconforming, Dune::ALUGridNoComm>;
#endif //HAVE_MPI #endif //HAVE_MPI
template std::pair<std::vector<int>,int> template std::pair<std::vector<int>,int>
partitionCells<ALUGrid3CN>(const ALUGrid3CN&, partitionCells<ALUGrid3CN>(const ALUGrid3CN&,
const std::vector<Well>&, const std::vector<Well>&,
const std::string&, const std::string&,
const int, const int,
const double); const double);
#endif #endif
} // namespace Opm } // namespace Opm

View File

@ -24,35 +24,34 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
namespace Opm namespace Opm {
{
class Well;
/// Partitions the grid using the specified method. class Well;
/// \return pair containing a partition vector (partition number for each cell), and the number of partitions.
template<class Grid>
std::pair<std::vector<int>, int> partitionCells(const Grid& grid,
const std::vector<Well>& wells,
const std::string& method,
const int num_local_domains,
const double partition_imbalance);
/// Read a partitioning from file, assumed to contain one number per cell, its partition number. /// Partitions the grid using the specified method.
/// \return pair containing a partition vector (partition number for each cell), and the number of partitions. /// \return pair containing a partition vector (partition number for each cell), and the number of partitions.
std::pair<std::vector<int>, int> partitionCellsFromFile(const std::string& filename, const int num_cells); template<class Grid>
std::pair<std::vector<int>, int> partitionCells(const Grid& grid,
const std::vector<Well>& wells,
const std::string& method,
const int num_local_domains,
const double partition_imbalance);
/// Trivially simple partitioner assigning partitions en bloc, consecutively by cell index. /// Read a partitioning from file, assumed to contain one number per cell, its partition number.
/// \return pair containing a partition vector (partition number for each cell), and the number of partitions. /// \return pair containing a partition vector (partition number for each cell), and the number of partitions.
std::pair<std::vector<int>, int> partitionCellsSimple(const int num_cells, const int num_domains); std::pair<std::vector<int>, int> partitionCellsFromFile(const std::string& filename, const int num_cells);
/// Partitions the grid using the Zoltan graph partitioner. /// Trivially simple partitioner assigning partitions en bloc, consecutively by cell index.
/// \return pair containing a partition vector (partition number for each cell), and the number of partitions. /// \return pair containing a partition vector (partition number for each cell), and the number of partitions.
template<class Grid> std::pair<std::vector<int>, int> partitionCellsSimple(const int num_cells, const int num_domains);
std::pair<std::vector<int>, int> partitionCellsZoltan(const Grid& grid,
const std::vector<Well>& wells, /// Partitions the grid using the Zoltan graph partitioner.
const int num_domains, /// \return pair containing a partition vector (partition number for each cell), and the number of partitions.
const double domain_imbalance); template<class Grid>
std::pair<std::vector<int>, int> partitionCellsZoltan(const Grid& grid,
const std::vector<Well>& wells,
const int num_domains,
const double domain_imbalance);
} // namespace Opm } // namespace Opm
#endif // OPM_ASPINPARTITION_HEADER_INCLUDED #endif // OPM_ASPINPARTITION_HEADER_INCLUDED