47 #ifndef MUELU_CLASSICALMAPFACTORY_DEF_HPP_
48 #define MUELU_CLASSICALMAPFACTORY_DEF_HPP_
51 #include <Teuchos_ArrayRCP.hpp>
58 #include <Xpetra_StridedMapFactory.hpp>
65 #include "MueLu_LWGraph.hpp"
69 #include "MueLu_LWGraph.hpp"
71 #ifdef HAVE_MUELU_ZOLTAN2
73 #include <Zoltan2_XpetraCrsGraphAdapter.hpp>
74 #include <Zoltan2_ColoringProblem.hpp>
75 #include <Zoltan2_ColoringSolution.hpp>
79 #include "MueLu_LWGraph_kokkos.hpp"
80 #include <KokkosGraph_Distance1ColorHandle.hpp>
81 #include <KokkosGraph_Distance1Color.hpp>
85 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
88 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
92 #undef SET_VALID_ENTRY
94 validParamList->
set<
RCP<const FactoryBase> >(
"UnAmalgamationInfo", Teuchos::null,
"Generating factory of UnAmalgamationInfo");
97 validParamList->
set<
RCP<const FactoryBase> >(
"DofsPerNode", null,
"Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
99 return validParamList;
102 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
104 Input(currentLevel,
"A");
105 Input(currentLevel,
"UnAmalgamationInfo");
106 Input(currentLevel,
"Graph");
109 bool use_color_graph = pL.
get<
bool>(
"aggregation: coloring: use color graph");
111 Input(currentLevel,
"Coloring Graph");
114 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
121 bool use_color_graph = pL.
get<
bool>(
"aggregation: coloring: use color graph");
123 graph = Get<RCP<LWGraph> >(currentLevel,
"Coloring Graph");
125 graph = Get<RCP<LWGraph> >(currentLevel,
"Graph");
134 std::string coloringAlgo = pL.
get<std::string>(
"aggregation: coloring algorithm");
137 #ifdef HAVE_MUELU_ZOLTAN2
138 int numProcs = A->getRowMap()->getComm()->getSize();
139 if (coloringAlgo !=
"file" && numProcs > 1 && graph->GetDomainMap()->lib() ==
Xpetra::UseTpetra)
140 coloringAlgo =
"Zoltan2";
146 int rank = graph->GetDomainMap()->getComm()->getRank();
148 printf(
"[%d,%d] graph local size = %dx%d\n", rank, currentLevel.GetLevelID(), (int)graph->GetDomainMap()->getLocalNumElements(), (int)graph->GetImportMap()->getLocalNumElements());
150 std::ofstream ofs(std::string(
"m_dropped_graph_") + std::to_string(currentLevel.GetLevelID()) + std::string(
"_") + std::to_string(rank) + std::string(
".dat"), std::ofstream::out);
152 graph->print(*fancy,
Debug);
155 A->getRowMap()->getComm()->barrier();
162 coloringAlgo =
"MIS";
164 if (coloringAlgo ==
"file") {
167 std::string map_file = std::string(
"map_fcsplitting_") + std::to_string(currentLevel.GetLevelID()) + std::string(
".m");
168 std::string color_file = std::string(
"fcsplitting_") + std::to_string(currentLevel.GetLevelID()) + std::string(
".m");
170 FILE* mapfile = fopen(map_file.c_str(),
"r");
175 GetOStream(
Statistics1) <<
"Reading FC splitting from " << color_file <<
", using map file " << map_file <<
". On rank " << A->getRowMap()->getComm()->getRank() <<
" local size is " << A->getRowMap()->getLocalNumElements() << std::endl;
179 TEUCHOS_TEST_FOR_EXCEPTION(!colorMap->isCompatible(*A->getRowMap()), std::invalid_argument,
"Coloring on disk has incompatible map with A");
187 fc_splitting = LocalOrdinalVectorFactory::Build(A->getRowMap());
188 TEUCHOS_TEST_FOR_EXCEPTION(mv->getLocalLength() != fc_splitting->getLocalLength(), std::invalid_argument,
"Coloring map mismatch");
191 auto boundaryNodes = graph->GetBoundaryNodeMap();
193 ArrayRCP<LO> fc_data = fc_splitting->getDataNonConst(0);
194 for (
LO i = 0; i < (
LO)fc_data.
size(); i++) {
195 if (boundaryNodes[i])
196 fc_data[i] = DIRICHLET_PT;
198 fc_data[i] = Teuchos::as<LO>(mv_data[i]);
201 #ifdef HAVE_MUELU_ZOLTAN2
202 else if (coloringAlgo.find(
"Zoltan2") != std::string::npos && graph->GetDomainMap()->lib() ==
Xpetra::UseTpetra) {
204 DoDistributedGraphColoring(graph, myColors, numColors);
207 else if (coloringAlgo ==
"MIS" || graph->GetDomainMap()->lib() ==
Xpetra::UseTpetra) {
209 TEUCHOS_TEST_FOR_EXCEPTION(A->getRowMap()->getComm()->getSize() != 1, std::invalid_argument,
"MIS on more than 1 MPI rank is not supported");
210 DoMISNaive(*graph, myColors, numColors);
213 TEUCHOS_TEST_FOR_EXCEPTION(A->getRowMap()->getComm()->getSize() != 1, std::invalid_argument,
"KokkosKernels graph coloring on more than 1 MPI rank is not supported");
214 DoGraphColoring(*graph, myColors, numColors);
219 int rank = graph->GetDomainMap()->getComm()->getRank();
221 printf(
"[%d,%d] num colors %d\n", rank, currentLevel.GetLevelID(), numColors);
223 std::ofstream ofs(std::string(
"m_colors_") + std::to_string(currentLevel.GetLevelID()) + std::string(
"_") + std::to_string(rank) + std::string(
".dat"), std::ofstream::out);
225 *fancy << myColors();
228 A->getRowMap()->getComm()->barrier();
236 LO num_c_points = 0, num_d_points = 0, num_f_points = 0;
239 auto boundaryNodes = graph->GetBoundaryNodeMap();
240 fc_splitting = LocalOrdinalVectorFactory::Build(A->getRowMap());
241 ArrayRCP<LO> myPointType = fc_splitting->getDataNonConst(0);
242 for (
LO i = 0; i < (
LO)myColors.size(); i++) {
243 if (boundaryNodes[i]) {
244 myPointType[i] = DIRICHLET_PT;
246 }
else if ((
LO)myColors[i] == 1) {
247 myPointType[i] = C_PT;
250 myPointType[i] = F_PT;
252 num_f_points = (
LO)myColors.size() - num_d_points - num_c_points;
255 ArrayRCP<LO> myPointType = fc_splitting->getDataNonConst(0);
257 for (
LO i = 0; i < (
LO)myPointType.
size(); i++) {
258 if (myPointType[i] == DIRICHLET_PT)
260 else if (myPointType[i] == C_PT)
263 num_f_points = (
LO)myPointType.
size() - num_d_points - num_c_points;
269 GO l_counts[] = {(
GO)num_c_points, (
GO)num_f_points, (
GO)num_d_points};
274 GetOStream(
Statistics1) <<
"ClassicalMapFactory(" << coloringAlgo <<
"): C/F/D = " << g_counts[0] <<
"/" << g_counts[1] <<
"/" << g_counts[2] << std::endl;
281 GenerateCoarseMap(*A->getRowMap(), num_c_points, coarseMap);
284 Set(currentLevel,
"FC Splitting", fc_splitting);
285 Set(currentLevel,
"CoarseMap", coarseMap);
289 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
293 std::vector<size_t> stridingInfo_(1);
294 stridingInfo_[0] = 1;
295 GO domainGIDOffset = 0;
297 coarseMap = StridedMapFactory::Build(fineMap.lib(),
300 fineMap.getIndexBase(),
307 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
312 using KernelHandle = KokkosKernels::Experimental::
313 KokkosKernelsHandle<
typename graph_t::row_map_type::value_type,
314 typename graph_t::entries_type::value_type,
315 typename graph_t::entries_type::value_type,
316 typename graph_t::device_type::execution_space,
317 typename graph_t::device_type::memory_space,
318 typename graph_t::device_type::memory_space>;
322 kh.create_graph_coloring_handle();
325 auto coloringHandle = kh.get_graph_coloring_handle();
328 if (pL.
get<
bool>(
"aggregation: deterministic") ==
true) {
329 coloringHandle->set_algorithm(KokkosGraph::COLORING_SERIAL);
331 }
else if (pL.
get<std::string>(
"aggregation: coloring algorithm") ==
"serial") {
332 coloringHandle->set_algorithm(KokkosGraph::COLORING_SERIAL);
334 }
else if (pL.
get<std::string>(
"aggregation: coloring algorithm") ==
"vertex based") {
335 coloringHandle->set_algorithm(KokkosGraph::COLORING_VB);
337 }
else if (pL.
get<std::string>(
"aggregation: coloring algorithm") ==
"vertex based bit array") {
338 coloringHandle->set_algorithm(KokkosGraph::COLORING_VBBIT);
340 }
else if (pL.
get<std::string>(
"aggregation: coloring algorithm") ==
"vertex based color set") {
341 coloringHandle->set_algorithm(KokkosGraph::COLORING_VBCS);
343 }
else if (pL.
get<std::string>(
"aggregation: coloring algorithm") ==
"vertex based deterministic") {
344 coloringHandle->set_algorithm(KokkosGraph::COLORING_VBD);
345 if (IsPrint(
Statistics1)) GetOStream(
Statistics1) <<
" algorithm: vertex based deterministic" << std::endl;
346 }
else if (pL.
get<std::string>(
"aggregation: coloring algorithm") ==
"vertex based deterministic bit array") {
347 coloringHandle->set_algorithm(KokkosGraph::COLORING_VBDBIT);
348 if (IsPrint(
Statistics1)) GetOStream(
Statistics1) <<
" algorithm: vertex based deterministic bit array" << std::endl;
349 }
else if (pL.
get<std::string>(
"aggregation: coloring algorithm") ==
"edge based") {
350 coloringHandle->set_algorithm(KokkosGraph::COLORING_EB);
359 auto graphLW =
dynamic_cast<const LWGraph*
>(&graph);
373 auto rowptrs = graphLW->getRowPtrs();
374 auto entries = graphLW->getEntries();
375 KokkosGraph::Experimental::graph_color(&kh,
384 auto myColors_d = coloringHandle->get_vertex_colors();
385 numColors =
static_cast<LO>(coloringHandle->get_num_colors());
388 auto myColors_h = Kokkos::create_mirror_view(myColors_d);
389 myColors_out.
resize(myColors_h.size());
390 Kokkos::View<LO*, Kokkos::LayoutLeft, Kokkos::HostSpace> myColors_v(&myColors_out[0], myColors_h.
size());
391 Kokkos::deep_copy(myColors_v, myColors_h);
394 kh.destroy_graph_coloring_handle();
399 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
414 for (
LO row = 0; row < Nrows; row++) {
415 if (boundaryNodes[row])
418 bool has_colored_neighbor =
false;
419 for (
LO j = 0; !has_colored_neighbor && j < (
LO)indices.length; j++) {
421 if (myColors[indices(j)] == MIS)
422 has_colored_neighbor =
true;
424 if (!has_colored_neighbor)
431 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
434 #ifdef HAVE_MUELU_ZOLTAN2
437 params.
set(
"color_choice",
"FirstFit");
438 params.
set(
"color_method",
"D1");
447 GraphAdapter z_adapter(graph);
450 Zoltan2::ColoringProblem<GraphAdapter> problem(&z_adapter, ¶ms, graph->
GetDomainMap()->getComm());
452 Zoltan2::ColoringSolution<GraphAdapter>* soln = problem.getSolution();
454 numColors = (
LO)soln->getNumColors();
458 if (std::is_same<LO, int>::value)
459 myColors_out = colors;
462 for (
LO i = 0; i < (
LO)myColors_out.
size(); i++)
463 myColors_out[i] = (
LO)colors[i];
474 #endif // ifdef HAVE_MUELU_ZOLTAN2
void Build(Level ¤tLevel) const override
Build an object with this factory.
#define SET_VALID_ENTRY(name)
typename std::conditional< OnHost, typename local_graph_device_type::HostMirror, local_graph_device_type >::type local_graph_type
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
void DeclareInput(Level ¤tLevel) const override
Specifies the data that this class needs, and the factories that generate that data.
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual void DoDistributedGraphColoring(RCP< const LWGraph > &graph, Teuchos::ArrayRCP< LO > &myColors, LO &numColors) const
Print additional debugging information.
virtual void DoMISNaive(const LWGraph &graph, Teuchos::ArrayRCP< LO > &myColors, LO &numColors) const
KOKKOS_INLINE_FUNCTION size_type GetNodeNumVertices() const
Return number of graph vertices.
KOKKOS_INLINE_FUNCTION const boundary_nodes_type GetBoundaryNodeMap() const
Returns map with global ids of boundary nodes.
void resize(const size_type n, const T &val=T())
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
static RCP< const Map > ReadMap(const std::string &fileName, Xpetra::UnderlyingLib lib, const RCP< const Teuchos::Comm< int > > &comm)
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
static RCP< MultiVector > ReadMultiVector(const std::string &fileName, const RCP< const Map > &map)
KOKKOS_INLINE_FUNCTION neighbor_vertices_type getNeighborVertices(LO i) const
Return the list of vertices adjacent to the vertex 'v'.
virtual void DoGraphColoring(const LWGraph &graph, Teuchos::ArrayRCP< LO > &myColors, LO &numColors) const
virtual void GenerateCoarseMap(const Map &fineMap, LO num_c_points, Teuchos::RCP< const Map > &coarseMap) const
const RCP< const Map > GetDomainMap() const
Lightweight MueLu representation of a compressed row storage graph.
RCP< const ParameterList > GetValidParameterList() const override
Return a const parameter list of valid parameters that setParameterList() will accept.