10 #ifndef PACKAGES_MUELU_SRC_REBALANCING_MUELU_REPARTITIONHEURISTICFACTORY_DEF_HPP_
11 #define PACKAGES_MUELU_SRC_REBALANCING_MUELU_REPARTITIONHEURISTICFACTORY_DEF_HPP_
19 #include <Teuchos_CommHelpers.hpp>
24 #include "MueLu_RAPFactory.hpp"
25 #include "MueLu_BlockedRAPFactory.hpp"
26 #include "MueLu_SubBlockAFactory.hpp"
35 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
38 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
41 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
45 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
54 #undef SET_VALID_ENTRY
58 validParamList->
set<
RCP<const FactoryBase> >(
"Node Comm", Teuchos::null,
"Generating factory of the node level communicator");
60 return validParamList;
63 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
67 const bool useMap = pL.
get<
bool>(
"repartition: use map");
69 Input(currentLevel,
"Map");
71 Input(currentLevel,
"A");
73 Input(currentLevel,
"A");
74 if (pL.
isParameter(
"repartition: node repartition level")) {
75 const int nodeRepartLevel = pL.
get<
int>(
"repartition: node repartition level");
76 if (currentLevel.
GetLevelID() == nodeRepartLevel) {
77 Input(currentLevel,
"Node Comm");
82 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
89 const int startLevel = pL.
get<
int>(
"repartition: start level");
90 const int nodeRepartLevel = pL.
get<
int>(
"repartition: node repartition level");
91 LO minRowsPerProcess = pL.
get<
LO>(
"repartition: min rows per proc");
92 LO targetRowsPerProcess = pL.
get<
LO>(
"repartition: target rows per proc");
93 LO minRowsPerThread = pL.
get<
LO>(
"repartition: min rows per thread");
94 LO targetRowsPerThread = pL.
get<
LO>(
"repartition: target rows per thread");
95 const double nonzeroImbalance = pL.
get<
double>(
"repartition: max imbalance");
96 const bool useMap = pL.
get<
bool>(
"repartition: use map");
98 int thread_per_mpi_rank = 1;
99 #if defined(KOKKOS_ENABLE_OPENMP)
100 using execution_space =
typename Node::device_type::execution_space;
101 if (std::is_same<execution_space, Kokkos::OpenMP>::value)
102 thread_per_mpi_rank = execution_space().concurrency();
105 if (minRowsPerThread > 0)
107 minRowsPerProcess = minRowsPerThread * thread_per_mpi_rank;
109 if (targetRowsPerThread == 0)
110 targetRowsPerThread = minRowsPerThread;
112 if (targetRowsPerThread > 0)
114 targetRowsPerProcess = targetRowsPerThread * thread_per_mpi_rank;
116 if (targetRowsPerProcess == 0)
117 targetRowsPerProcess = minRowsPerProcess;
120 Set<LO>(currentLevel,
"repartition: heuristic target rows per process", targetRowsPerProcess);
129 Afact = GetFactory(
"A");
130 if (!Afact.
is_null() && Teuchos::rcp_dynamic_cast<
const RAPFactory>(Afact) == Teuchos::null &&
131 Teuchos::rcp_dynamic_cast<const BlockedRAPFactory>(Afact) == Teuchos::null &&
132 Teuchos::rcp_dynamic_cast<
const SubBlockAFactory>(Afact) == Teuchos::null) {
133 GetOStream(
Warnings) <<
"MueLu::RepartitionHeuristicFactory::Build: The generation factory for A must "
134 "be a RAPFactory or a SubBlockAFactory providing the non-rebalanced matrix information! "
135 "It specifically must not be of type Rebalance(Blocked)AcFactory or similar. "
136 "Please check the input. Make also sure that \"number of partitions\" is provided to "
137 "the Interface class and the RepartitionFactory instance. Instead, we have a "
141 A = Get<RCP<Matrix> >(currentLevel,
"A");
142 map = A->getRowMap();
144 map = Get<RCP<const Map> >(currentLevel,
"Map");
154 if (currentLevel.GetLevelID() == nodeRepartLevel && map->getComm()->getSize() > 1) {
159 if (NodeComm()->getSize() != map->getComm()->getSize()) {
160 GetOStream(
Statistics1) <<
"Repartitioning? YES: \n Within node only" << std::endl;
161 int nodeRank = NodeComm->getRank();
164 int isZero = (nodeRank == 0);
166 Teuchos::reduceAll(*map->getComm(),
Teuchos::REDUCE_SUM, isZero, Teuchos::outArg(numNodes));
167 Set(currentLevel,
"number of partitions", numNodes);
173 if (currentLevel.GetLevelID() < startLevel) {
175 <<
"\n current level = " <<
Teuchos::toString(currentLevel.GetLevelID()) <<
", first level where repartitioning can happen is " +
Teuchos::toString(startLevel) << std::endl;
178 Set(currentLevel,
"number of partitions", -1);
192 if (comm->getSize() == 1 && Teuchos::rcp_dynamic_cast<
const RAPFactory>(Afact) != Teuchos::null) {
194 <<
"\n comm size = 1" << std::endl;
196 Set(currentLevel,
"number of partitions", -1);
200 int numActiveProcesses = 0;
201 MueLu_sumAll(comm, Teuchos::as<int>((map->getLocalNumElements() > 0) ? 1 : 0), numActiveProcesses);
203 if (numActiveProcesses == 1) {
205 <<
"\n # processes with rows = " <<
Teuchos::toString(numActiveProcesses) << std::endl;
207 Set(currentLevel,
"number of partitions", 1);
212 bool test3 =
false, test4 =
false;
213 std::string msg3, msg4;
217 if (minRowsPerProcess > 0) {
219 LO haveFewRows = (numMyRows < minRowsPerProcess ? 1 : 0), numWithFewRows = 0;
221 MueLu_minAll(comm, (numMyRows > 0 ? numMyRows : LOMAX), minNumRows);
226 if (numWithFewRows > 0)
237 GO minNnz, maxNnz, numMyNnz = Teuchos::as<GO>(A->getLocalNumEntries());
239 MueLu_minAll(comm, (numMyNnz > 0 ? numMyNnz : maxNnz), minNnz);
240 double imbalance = Teuchos::as<double>(maxNnz) / minNnz;
242 if (imbalance > nonzeroImbalance)
249 if (!test3 && !test4) {
250 GetOStream(
Statistics1) <<
"Repartitioning? NO:" << msg3 + msg4 << std::endl;
253 Set(currentLevel,
"number of partitions", -1);
257 GetOStream(
Statistics1) <<
"Repartitioning? YES:" << msg3 + msg4 << std::endl;
270 const auto globalNumRows = Teuchos::as<GO>(map->getGlobalNumElements());
271 int numPartitions = 1;
272 if (globalNumRows >= targetRowsPerProcess) {
274 numPartitions = std::max(Teuchos::as<int>(globalNumRows / targetRowsPerProcess), 1);
276 numPartitions = std::min(numPartitions, comm->getSize());
278 Set(currentLevel,
"number of partitions", numPartitions);
280 GetOStream(
Statistics1) <<
"Number of partitions to use = " << numPartitions << std::endl;
284 #endif // ifdef HAVE_MPI
#define MueLu_sumAll(rcpComm, in, out)
virtual ~RepartitionHeuristicFactory()
Destructor.
#define MueLu_maxAll(rcpComm, in, out)
void Build(Level ¤tLevel) const
Build an object with this factory.
T & get(const std::string &name, T def_value)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
#define SET_VALID_ENTRY(name)
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
#define MueLu_minAll(rcpComm, in, out)
bool isParameter(const std::string &name) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
Factory for building a thresholded operator.
void DeclareInput(Level ¤tLevel) const
Determines the data that RepartitionHeuristicFactory needs, and the factories that generate that data...
int GetLevelID() const
Return level number.
Exception throws to report errors in the internal logical of the program.
Print all warning messages.
Factory for building coarse matrices.
RepartitionHeuristicFactory()
Constructor.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
virtual std::string description() const
Return a simple one-line description of this object.
std::string toString(const T &t)