MueLu  Version of the Day
MueLu_ClassicalMapFactory_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 
47 #ifndef MUELU_CLASSICALMAPFACTORY_DEF_HPP_
48 #define MUELU_CLASSICALMAPFACTORY_DEF_HPP_
49 
50 
51 
52 #include <Teuchos_Array.hpp>
53 #include <Teuchos_ArrayRCP.hpp>
54 
55 
56 #ifdef HAVE_MPI
57 #include <Teuchos_DefaultMpiComm.hpp>
58 #endif
59 
60 #include <Xpetra_Vector.hpp>
61 #include <Xpetra_StridedMapFactory.hpp>
62 #include <Xpetra_VectorFactory.hpp>
63 #include <Xpetra_Import.hpp>
64 #include <Xpetra_IO.hpp>
65 
67 #include "MueLu_Level.hpp"
68 #include "MueLu_GraphBase.hpp"
69 #include "MueLu_MasterList.hpp"
70 #include "MueLu_Monitor.hpp"
71 #include "MueLu_GraphBase.hpp"
72 #include "MueLu_Graph.hpp"
73 #include "MueLu_LWGraph.hpp"
74 
75 #ifdef HAVE_MUELU_ZOLTAN2
77 #include <Zoltan2_XpetraCrsGraphAdapter.hpp>
78 #include <Zoltan2_ColoringProblem.hpp>
79 #include <Zoltan2_ColoringSolution.hpp>
80 
81 #endif
82 
83 #include "MueLu_LWGraph_kokkos.hpp"
84 #include <KokkosGraph_Distance1ColorHandle.hpp>
85 #include <KokkosGraph_Distance1Color.hpp>
86 
87 namespace MueLu {
88 
89  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
91  {
92  RCP<ParameterList> validParamList = rcp(new ParameterList());
93 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
94  SET_VALID_ENTRY("aggregation: deterministic");
95  SET_VALID_ENTRY("aggregation: coloring algorithm");
96  SET_VALID_ENTRY("aggregation: coloring: use color graph");
97 #undef SET_VALID_ENTRY
98  validParamList->set< RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the matrix A");
99  validParamList->set< RCP<const FactoryBase> >("UnAmalgamationInfo", Teuchos::null, "Generating factory of UnAmalgamationInfo");
100  validParamList->set< RCP<const FactoryBase> >("Graph", null, "Generating factory of the graph");
101  validParamList->set< RCP<const FactoryBase> >("Coloring Graph", null, "Generating factory of the graph");
102  validParamList->set< RCP<const FactoryBase> >("DofsPerNode", null, "Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
103 
104  return validParamList;
105  }
106 
107  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
109  {
110  Input(currentLevel, "A");
111  Input(currentLevel, "UnAmalgamationInfo");
112  Input(currentLevel, "Graph");
113 
114  const ParameterList& pL = GetParameterList();
115  bool use_color_graph = pL.get<bool>("aggregation: coloring: use color graph");
116  if(use_color_graph)
117  Input(currentLevel, "Coloring Graph");
118  }
119 
120  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
122  {
123  FactoryMonitor m(*this, "Build", currentLevel);
124  const ParameterList& pL = GetParameterList();
125  RCP<const Matrix> A = Get<RCP<Matrix> >(currentLevel,"A");
126 
127  RCP<const GraphBase> graph;
128  bool use_color_graph = pL.get<bool>("aggregation: coloring: use color graph");
129  if(use_color_graph) graph = Get<RCP<GraphBase> >(currentLevel,"Coloring Graph");
130  else graph = Get<RCP<GraphBase> >(currentLevel,"Graph");
131 
132 
133 
134  /* ============================================================= */
135  /* Phase 1 : Compute an initial MIS */
136  /* ============================================================= */
137  ArrayRCP<LO> myColors;
138  LO numColors=0;
139 
140  RCP<LocalOrdinalVector> fc_splitting;
141  std::string coloringAlgo = pL.get<std::string>("aggregation: coloring algorithm");
142 
143  // Switch to Zoltan2 if we're parallel and Tpetra (and not file)
144 #ifdef HAVE_MUELU_ZOLTAN2
145  int numProcs = A->getRowMap()->getComm()->getSize();
146  if(coloringAlgo!="file" && numProcs>1 && graph->GetDomainMap()->lib() == Xpetra::UseTpetra)
147  coloringAlgo="Zoltan2";
148 #endif
149 
150  //#define CMS_DUMP
151 #ifdef CMS_DUMP
152  {
153  int rank = graph->GetDomainMap()->getComm()->getRank();
154 
155  printf("[%d,%d] graph local size = %dx%d\n",rank,currentLevel.GetLevelID(),(int)graph->GetDomainMap()->getNodeNumElements(),(int)graph->GetImportMap()->getNodeNumElements());
156 
157  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);
158  RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(ofs));
159  graph->print(*fancy,Debug);
160  }
161  {
162  A->getRowMap()->getComm()->barrier();
163  }
164 
165 #endif
166 
167 
168 
169  // Switch to MIS if we're in Epetra (and not file)
170  if(coloringAlgo!="file" && graph->GetDomainMap()->lib() == Xpetra::UseEpetra)
171  coloringAlgo="MIS";
172 
173 
174  if(coloringAlgo == "file") {
175  // Read the CF splitting from disk
176  // NOTE: For interoperability reasons, this is dependent on the point_type enum not changing
177  std::string map_file = std::string("map_fcsplitting_") + std::to_string(currentLevel.GetLevelID()) + std::string(".m");
178  std::string color_file = std::string("fcsplitting_") + std::to_string(currentLevel.GetLevelID()) + std::string(".m");
179 
180  FILE * mapfile = fopen(map_file.c_str(),"r");
181  using real_type = typename Teuchos::ScalarTraits<SC>::magnitudeType;
182  using RealValuedMultiVector = typename Xpetra::MultiVector<real_type,LO,GO,NO>;
183  RCP<RealValuedMultiVector> mv;
184 
185 
186  GetOStream(Statistics1) << "Reading FC splitting from " << color_file << ", using map file " << map_file << ". On rank " << A->getRowMap()->getComm()->getRank() << " local size is " << A->getRowMap()->getNodeNumElements() << std::endl;
187  if(mapfile) {
188  fclose(mapfile);
189  RCP<const Map> colorMap = Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::ReadMap(map_file, A->getRowMap()->lib(), A->getRowMap()->getComm());
190  TEUCHOS_TEST_FOR_EXCEPTION(!colorMap->isCompatible(*A->getRowMap()),std::invalid_argument,"Coloring on disk has incompatible map with A");
191 
192  mv = Xpetra::IO<real_type, LocalOrdinal, GlobalOrdinal, Node>::ReadMultiVector(color_file,colorMap);
193  }
194  else {
195  // Use A's rowmap and hope it matches
196  mv = Xpetra::IO<real_type, LocalOrdinal, GlobalOrdinal, Node>::ReadMultiVector(color_file,A->getRowMap());
197  }
198  TEUCHOS_TEST_FOR_EXCEPTION(mv.is_null(),std::invalid_argument,"Coloring on disk cannot be read");
199  fc_splitting = LocalOrdinalVectorFactory::Build(A->getRowMap());
200  TEUCHOS_TEST_FOR_EXCEPTION(mv->getLocalLength() != fc_splitting->getLocalLength(),std::invalid_argument,"Coloring map mismatch");
201 
202  // Overlay the Dirichlet Points (and copy out the rest)
203  auto boundaryNodes = graph->GetBoundaryNodeMap();
204  ArrayRCP<const real_type> mv_data= mv->getData(0);
205  ArrayRCP<LO> fc_data= fc_splitting->getDataNonConst(0);
206  for(LO i=0; i<(LO)fc_data.size(); i++) {
207  if(boundaryNodes[i])
208  fc_data[i] = DIRICHLET_PT;
209  else
210  fc_data[i] = Teuchos::as<LO>(mv_data[i]);
211  }
212  }
213 #ifdef HAVE_MUELU_ZOLTAN2
214  else if(coloringAlgo.find("Zoltan2")!=std::string::npos && graph->GetDomainMap()->lib() == Xpetra::UseTpetra) {
215  SubFactoryMonitor sfm(*this,"DistributedGraphColoring",currentLevel);
216  DoDistributedGraphColoring(graph,myColors,numColors);
217  }
218 #endif
219  else if(coloringAlgo == "MIS" || graph->GetDomainMap()->lib() == Xpetra::UseTpetra) {
220  SubFactoryMonitor sfm(*this,"MIS",currentLevel)
221 ; TEUCHOS_TEST_FOR_EXCEPTION(A->getRowMap()->getComm()->getSize() != 1, std::invalid_argument,"MIS on more than 1 MPI rank is not supported");
222  DoMISNaive(*graph,myColors,numColors);
223  }
224  else {
225  SubFactoryMonitor sfm(*this,"GraphColoring",currentLevel);
226  TEUCHOS_TEST_FOR_EXCEPTION(A->getRowMap()->getComm()->getSize() != 1, std::invalid_argument,"KokkosKernels graph coloring on more than 1 MPI rank is not supported");
227  DoGraphColoring(*graph,myColors,numColors);
228  }
229 
230 #ifdef CMS_DUMP
231  {
232  int rank = graph->GetDomainMap()->getComm()->getRank();
233 
234  printf("[%d,%d] num colors %d\n",rank,currentLevel.GetLevelID(),numColors);
235 
236  std::ofstream ofs(std::string("m_colors_") + std::to_string(currentLevel.GetLevelID())+std::string("_") + std::to_string(rank) + std::string(".dat"),std::ofstream::out);
237  RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(ofs));
238  *fancy << myColors();
239  }
240  {
241  A->getRowMap()->getComm()->barrier();
242  }
243 
244 #endif
245 
246  /* ============================================================= */
247  /* Phase 2 : Mark the C-Points */
248  /* ============================================================= */
249  LO num_c_points = 0, num_d_points=0, num_f_points = 0;
250  if(fc_splitting.is_null()) {
251  // We just have a coloring, so we need to generate a splitting
252  auto boundaryNodes = graph->GetBoundaryNodeMap();
253  fc_splitting = LocalOrdinalVectorFactory::Build(A->getRowMap());
254  ArrayRCP<LO> myPointType = fc_splitting->getDataNonConst(0);
255  for(LO i=0; i<(LO)myColors.size(); i++) {
256  if(boundaryNodes[i]) {
257  myPointType[i] = DIRICHLET_PT;
258  num_d_points++;
259  }
260  else if ((LO)myColors[i] == 1) {
261  myPointType[i] = C_PT;
262  num_c_points++;
263  }
264  else
265  myPointType[i] = F_PT;
266  }
267  num_f_points = (LO)myColors.size() - num_d_points - num_c_points;
268  }
269  else {
270  // If we read the splitting off disk, we just need to count
271  ArrayRCP<LO> myPointType = fc_splitting->getDataNonConst(0);
272 
273  for(LO i=0; i<(LO)myPointType.size(); i++) {
274  if(myPointType[i] == DIRICHLET_PT)
275  num_d_points++;
276  else if (myPointType[i] == C_PT)
277  num_c_points++;
278  }
279  num_f_points = (LO)myPointType.size() - num_d_points - num_c_points;
280  }
281 
282  /* Output statistics on c/f/d points */
283  if (GetVerbLevel() & Statistics1) {
284  // NOTE: We batch the communication here
285  GO l_counts[] = {(GO)num_c_points, (GO) num_f_points, (GO) num_d_points};
286  GO g_counts[3];
287 
288  RCP<const Teuchos::Comm<int> > comm = A->getRowMap()->getComm();
289  Teuchos::reduceAll(*comm, Teuchos::REDUCE_SUM, 3, l_counts, g_counts);
290  GetOStream(Statistics1) << "ClassicalMapFactory("<<coloringAlgo<<"): C/F/D = "<<g_counts[0]<<"/"<<g_counts[1]<<"/"<<g_counts[2]<<std::endl;
291  }
292 
293 
294  /* Generate the Coarse map */
295  RCP<const Map> coarseMap;
296  {
297  SubFactoryMonitor sfm(*this,"Coarse Map",currentLevel);
298  GenerateCoarseMap(*A->getRowMap(),num_c_points,coarseMap);
299  }
300 
301  Set(currentLevel, "FC Splitting",fc_splitting);
302  Set(currentLevel, "CoarseMap", coarseMap);
303 
304  }
305 
306 /* ************************************************************************* */
307  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
309  GenerateCoarseMap(const Map & fineMap, LO num_c_points, RCP<const Map> & coarseMap) const {
310 
311  // FIXME: Assumes scalar PDE
312  std::vector<size_t> stridingInfo_(1);
313  stridingInfo_[0]=1;
314  GO domainGIDOffset = 0;
315 
316  coarseMap = StridedMapFactory::Build(fineMap.lib(),
317  Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
318  num_c_points,
319  fineMap.getIndexBase(),
320  stridingInfo_,
321  fineMap.getComm(),
322  domainGIDOffset);
323  }
324 
325 /* ************************************************************************* */
326  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
328  DoGraphColoring(const GraphBase & graph, ArrayRCP<LO> & myColors_out, LO & numColors) const {
329  const ParameterList& pL = GetParameterList();
330  using graph_t = typename LWGraph_kokkos::local_graph_type;
331  using KernelHandle = KokkosKernels::Experimental::
332  KokkosKernelsHandle<typename graph_t::row_map_type::value_type,
333  typename graph_t::entries_type::value_type,
334  typename graph_t::entries_type::value_type,
335  typename graph_t::device_type::execution_space,
336  typename graph_t::device_type::memory_space,
337  typename graph_t::device_type::memory_space>;
338  KernelHandle kh;
339 
340  // Leave gc algorithm choice as the default
341  kh.create_graph_coloring_handle();
342 
343  // Get the distance-1 graph coloring handle
344  auto coloringHandle = kh.get_graph_coloring_handle();
345 
346  // Set the distance-1 coloring algorithm to use
347  if(pL.get<bool>("aggregation: deterministic") == true) {
348  coloringHandle->set_algorithm( KokkosGraph::COLORING_SERIAL );
349  if(IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: serial" << std::endl;
350  } else if(pL.get<std::string>("aggregation: coloring algorithm") == "serial") {
351  coloringHandle->set_algorithm( KokkosGraph::COLORING_SERIAL );
352  if(IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: serial" << std::endl;
353  } else if(pL.get<std::string>("aggregation: coloring algorithm") == "vertex based") {
354  coloringHandle->set_algorithm( KokkosGraph::COLORING_VB );
355  if(IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: vertex based" << std::endl;
356  } else if(pL.get<std::string>("aggregation: coloring algorithm") == "vertex based bit array") {
357  coloringHandle->set_algorithm( KokkosGraph::COLORING_VBBIT );
358  if(IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: vertex based bit array" << std::endl;
359  } else if(pL.get<std::string>("aggregation: coloring algorithm") == "vertex based color set") {
360  coloringHandle->set_algorithm( KokkosGraph::COLORING_VBCS );
361  if(IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: vertex based color set" << std::endl;
362  } else if(pL.get<std::string>("aggregation: coloring algorithm") == "vertex based deterministic") {
363  coloringHandle->set_algorithm( KokkosGraph::COLORING_VBD );
364  if(IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: vertex based deterministic" << std::endl;
365  } else if(pL.get<std::string>("aggregation: coloring algorithm") == "vertex based deterministic bit array") {
366  coloringHandle->set_algorithm( KokkosGraph::COLORING_VBDBIT );
367  if(IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: vertex based deterministic bit array" << std::endl;
368  } else if(pL.get<std::string>("aggregation: coloring algorithm") == "edge based") {
369  coloringHandle->set_algorithm( KokkosGraph::COLORING_EB );
370  if(IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: edge based" << std::endl;
371  } else {
372  TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument,"Unrecognized distance 1 coloring algorithm");
373  }
374 
375  // Create device views for graph rowptrs/colinds
376  size_t numRows = graph.GetNodeNumVertices();
377  auto graphLWK = dynamic_cast<const LWGraph_kokkos*>(&graph);
378  auto graphLW = dynamic_cast<const LWGraph*>(&graph);
379  auto graphG = dynamic_cast<const Graph*>(&graph);
380  TEUCHOS_TEST_FOR_EXCEPTION(!graphLW && !graphLWK && !graphG,std::invalid_argument,"Graph is not a LWGraph or LWGraph_kokkos object");
381  // Run d1 graph coloring
382  // Assume that the graph is symmetric so row map/entries and col map/entries are the same
383 
384  if(graphLWK) {
385  KokkosGraph::Experimental::graph_color(&kh,
386  numRows,
387  numRows, // FIXME: This should be the number of columns
388  graphLWK->getRowPtrs(),
389  graphLWK->getEntries(),
390  true);
391  }
392  else if(graphLW) {
393  auto rowptrs = graphLW->getRowPtrs();
394  auto entries = graphLW->getEntries();
395  // Copy rowptrs to a size_t, because kokkos-kernels doesn't like rowptrs as LO's
396  Teuchos::Array<size_t> rowptrs_s(rowptrs.size());
397  std::copy(rowptrs.begin(),rowptrs.end(),rowptrs_s.begin());
398  Kokkos::View<const size_t*,Kokkos::LayoutLeft,Kokkos::HostSpace> rowptrs_v(rowptrs_s.data(),(size_t)rowptrs.size());
399  Kokkos::View<const LO*,Kokkos::LayoutLeft,Kokkos::HostSpace> entries_v(entries.getRawPtr(),(size_t)entries.size());
400  KokkosGraph::Experimental::graph_color(&kh,
401  numRows,
402  numRows, // FIXME: This should be the number of columns
403  rowptrs_v,
404  entries_v,
405  true);
406  }
407  else if(graphG) {
408  // FIXME: This is a terrible, terrible hack, based on 0-based local indexing.
409  RCP<const CrsGraph> graphC = graphG->GetGraph();
410  size_t numEntries = graphC->getNodeNumEntries();
411  ArrayView<const LO> indices;
412  graphC->getLocalRowView(0,indices);
413  Kokkos::View<size_t*,Kokkos::LayoutLeft,Kokkos::HostSpace> rowptrs_v("rowptrs_v",graphC->getNodeNumRows()+1);
414  rowptrs_v[0]=0;
415  for(LO i=0; i<(LO)graphC->getNodeNumRows()+1; i++)
416  rowptrs_v[i+1] = rowptrs_v[i] + graphC->getNumEntriesInLocalRow(i);
417  Kokkos::View<const LO*,Kokkos::LayoutLeft,Kokkos::HostSpace> entries_v(&indices[0],numEntries);
418  KokkosGraph::Experimental::graph_color(&kh,
419  numRows,
420  numRows, // FIXME: This should be the number of columns
421  rowptrs_v,
422  entries_v,
423  true);
424  }
425 
426 
427  // Extract the colors and store them in the aggregates
428  auto myColors_d = coloringHandle->get_vertex_colors();
429  numColors = static_cast<LO>(coloringHandle->get_num_colors());
430 
431  // Copy back to host
432  auto myColors_h = Kokkos::create_mirror_view(myColors_d);
433  myColors_out.resize(myColors_h.size());
434  Kokkos::View<LO*,Kokkos::LayoutLeft,Kokkos::HostSpace> myColors_v(&myColors_out[0],myColors_h.size());
435  Kokkos::deep_copy(myColors_v,myColors_h);
436 
437  //clean up coloring handle
438  kh.destroy_graph_coloring_handle();
439 
440  }// end DoGraphColoring
441 
442 
443 /* ************************************************************************* */
444  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
446  DoMISNaive(const GraphBase & graph, ArrayRCP<LO> & myColors, LO & numColors) const {
447  // This is a fall-back routine for when we don't have Kokkos or when it isn't initialized
448  // We just do greedy MIS because this is easy to write.
449 
450  LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
451  LO MIS = Teuchos::ScalarTraits<LO>::one();
452 
453  //FIXME: Not efficient
454  myColors.resize(0);
455  myColors.resize(graph.GetNodeNumVertices(),LO_INVALID);
456  auto boundaryNodes = graph.GetBoundaryNodeMap();
457  LO Nrows = (LO)graph.GetNodeNumVertices();
458 
459 
460  for(LO row=0; row < Nrows; row++) {
461  if(boundaryNodes[row])
462  continue;
463  ArrayView<const LO> indices = graph.getNeighborVertices(row);
464  bool has_colored_neighbor=false;
465  for(LO j=0; !has_colored_neighbor && j<(LO)indices.size(); j++) {
466  // FIXME: This does not handle ghosting correctly
467  if(myColors[indices[j]] == MIS)
468  has_colored_neighbor=true;
469  }
470  if(!has_colored_neighbor)
471  myColors[row] = MIS;
472  }
473  numColors=1;
474  }
475 
476 /* ************************************************************************* */
477  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
479  DoDistributedGraphColoring(RCP<const GraphBase> & graph, ArrayRCP<LO> & myColors_out, LO & numColors) const {
480 #ifdef HAVE_MUELU_ZOLTAN2
481  // const ParameterList& pL = GetParameterList();
482  Teuchos::ParameterList params;
483  params.set("color_choice","FirstFit");
484  params.set("color_method","D1");
485  // params.set("color_choice", colorMethod);
486  // params.set("color_method", colorAlg);
487  // params.set("verbose", verbose);
488  // params.set("serial_threshold",serialThreshold);
489  //params.set("recolor_degrees",recolorDegrees);
490 
491  // Do the coloring via Zoltan2
492  using GraphAdapter = MueLuGraphBaseAdapter<GraphBase>;
493  GraphAdapter z_adapter(graph);
494 
495  // We need to provide the MPI Comm, or else we wind up using the default (eep!)
496  Zoltan2::ColoringProblem<GraphAdapter> problem(&z_adapter,&params,graph->GetDomainMap()->getComm());
497  problem.solve();
498  Zoltan2::ColoringSolution<GraphAdapter> * soln = problem.getSolution();
499  ArrayRCP<int> colors = soln->getColorsRCP();
500  numColors = (LO)soln->getNumColors();
501 
502  // Assign the Array RCP or Copy Out
503  // FIXME: This probably won't work if LO!=int
504  if(std::is_same<LO,int>::value)
505  myColors_out = colors;
506  else {
507  myColors_out.resize(colors.size());
508  for(LO i=0; i<(LO)myColors_out.size(); i++)
509  myColors_out[i] = (LO) colors[i];
510  }
511 
512  /*
513 
514  printf("CMS: numColors = %d\ncolors = ",numColors);
515  for(int i=0;i<colors.size(); i++)
516  printf("%d ",colors[i]);
517  printf("\n");
518 
519  */
520 #endif //ifdef HAVE_MUELU_ZOLTAN2
521  }
522 
523 } //namespace MueLu
524 
525 #endif /* MUELU_CLASSICALMAPFACTORY_DEF_HPP_ */
void Build(Level &currentLevel) const override
Build an object with this factory.
#define SET_VALID_ENTRY(name)
virtual size_t GetNodeNumVertices() const =0
Return number of vertices owned by the calling node.
void DeclareInput(Level &currentLevel) const override
Specifies the data that this class needs, and the factories that generate that data.
MueLu representation of a compressed row storage graph.
Timer to be used in factories. Similar to Monitor but with additional timers.
virtual const ArrayRCP< const bool > GetBoundaryNodeMap() const =0
Print more statistics.
Print additional debugging information.
Namespace for MueLu classes and methods.
virtual void GenerateCoarseMap(const Map &fineMap, LO num_c_points, Teuchos::RCP< const Map > &coarseMap) const
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
virtual void DoDistributedGraphColoring(RCP< const GraphBase > &graph, Teuchos::ArrayRCP< LO > &myColors, LO &numColors) const
virtual void DoMISNaive(const GraphBase &graph, Teuchos::ArrayRCP< LO > &myColors, LO &numColors) const
MueLu representation of a graph.
Lightweight MueLu representation of a compressed row storage graph.
virtual void DoGraphColoring(const GraphBase &graph, Teuchos::ArrayRCP< LO > &myColors, LO &numColors) const
RCP< const ParameterList > GetValidParameterList() const override
Return a const parameter list of valid parameters that setParameterList() will accept.
virtual Teuchos::ArrayView< const LocalOrdinal > getNeighborVertices(LocalOrdinal v) const =0
Return the list of vertices adjacent to the vertex &#39;v&#39;.