Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Zoltan2_TpetraCrsColorer.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Zoltan2: A package of combinatorial algorithms for scientific computing
4 //
5 // Copyright 2012 NTESS and the Zoltan2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #pragma once
11 
12 #include <stdexcept>
13 
14 #include "Teuchos_RCP.hpp"
15 #include "Teuchos_ParameterList.hpp"
16 #include "Teuchos_TestForException.hpp"
17 
18 #include "Tpetra_Map.hpp"
19 #include "Tpetra_MultiVector.hpp"
20 #include "Tpetra_CrsMatrix.hpp"
21 #include "Tpetra_CrsGraph.hpp"
22 #include "Tpetra_BlockMultiVector.hpp"
23 #include "Tpetra_BlockCrsMatrix.hpp"
24 
28 
29 namespace Zoltan2
30 {
31 
32 // Base class for coloring Tpetra::CrsMatrix for use in column compression
33 template <typename CrsMatrixType>
35 {
36 public:
37  typedef CrsMatrixType matrix_t;
38  typedef typename matrix_t::crs_graph_type graph_t;
39  typedef typename matrix_t::scalar_type scalar_t;
40  typedef typename matrix_t::local_ordinal_type lno_t;
41  typedef typename matrix_t::global_ordinal_type gno_t;
42  typedef typename matrix_t::node_type node_t;
43  typedef typename node_t::device_type device_t;
44  typedef typename device_t::execution_space execution_space;
45  typedef Kokkos::View<int *, device_t> list_of_colors_t;
46  typedef typename list_of_colors_t::HostMirror list_of_colors_host_t;
47 
48  // Constructor
49  TpetraCrsColorer(const Teuchos::RCP<matrix_t> &matrix_);
50 
51  // Destructor
53 
54  // Compute coloring data
55  void
56  computeColoring(Teuchos::ParameterList &coloring_params);
57 
58  // Compute seed matrix
59  template <typename MultiVectorType>
60  void
61  computeSeedMatrix(MultiVectorType &V, const int color_beg = 0) const;
62 
63  // Compute seed matrix with distribution fitted to the graph's column map
64  template <typename MultiVectorType>
65  void
66  computeSeedMatrixFitted(MultiVectorType &V, const int color_beg = 0) const;
67 
68  // Reconstruct matrix from supplied compressed vector
69  template <typename MultiVectorType>
70  void
71  reconstructMatrix(MultiVectorType &W, const int color_beg = 0) const;
72  template <typename MultiVectorType>
73  void
74  reconstructMatrix(MultiVectorType &W, matrix_t &mat, const int color_beg = 0) const;
75 
76  // Reconstruct matrix from supplied compressed vector fitted to the graph's
77  // row map
78  template <typename MultiVectorType>
79  void
80  reconstructMatrixFitted(MultiVectorType &W, const int color_beg = 0) const;
81  template <typename MultiVectorType>
82  void
83  reconstructMatrixFitted(MultiVectorType &W, matrix_t &mat, const int color_beg = 0) const;
84 
85  // Return number of colors
86  // KDD should num_colors be int or size_t?
87  int
88  getNumColors() const
89  {
90  return num_colors;
91  }
92 
93  // Get color given a column index
94  int
95  getColor(const size_t col) const
96  {
97  return list_of_colors_host(col) - 1;
98  }
99 
100  // Check coloring is valid, i.e., no row has two nonzero columns with
101  // same color
102  bool
104  {
106  }
107 
108 protected:
109  Teuchos::RCP<matrix_t> matrix;
110  Teuchos::RCP<const graph_t> graph;
114 };
115 
117 // Specialization of TpetraCrsColorer for BlockCrsMatrix
118 template <typename SC, typename LO, typename GO, typename NO>
119 class TpetraCrsColorer<Tpetra::BlockCrsMatrix<SC,LO,GO,NO> >
120 {
121 public:
122  typedef Tpetra::BlockCrsMatrix<SC, LO, GO, NO> matrix_t;
123  typedef Tpetra::BlockMultiVector<SC, LO, GO, NO> multivector_t;
124  typedef typename matrix_t::crs_graph_type graph_t;
125  typedef typename matrix_t::scalar_type scalar_t;
126  typedef typename matrix_t::local_ordinal_type lno_t;
127  typedef typename matrix_t::global_ordinal_type gno_t;
128  typedef typename matrix_t::node_type node_t;
129  typedef typename node_t::device_type device_t;
130  typedef typename device_t::execution_space execution_space;
131  typedef Kokkos::View<int *, device_t> list_of_colors_t;
132  typedef typename list_of_colors_t::HostMirror list_of_colors_host_t;
133 
134  // Constructor
135  TpetraCrsColorer(const Teuchos::RCP<matrix_t> &matrix_);
136 
137  // Destructor
139 
140  // Compute coloring data
141  void
142  computeColoring(Teuchos::ParameterList &coloring_params);
143 
144  // Compute seed matrix
145  void
146  computeSeedMatrix(multivector_t &V, const int color_beg = 0) const;
147 
148  // Compute seed matrix with distribution fitted to the graph's column map
149  void
150  computeSeedMatrixFitted(multivector_t &V, const int color_beg = 0) const;
151 
152  // Reconstruct matrix from supplied compressed vector
153  void
154  reconstructMatrix(multivector_t &W, const int color_beg = 0) const;
155  void
156  reconstructMatrix(multivector_t &W, matrix_t &mat, const int color_beg = 0) const;
157 
158  // Reconstruct matrix from supplied compressed vector fitted to the graph's
159  // row map
160  void
161  reconstructMatrixFitted(multivector_t &W, const int color_beg = 0) const;
162  void
163  reconstructMatrixFitted(multivector_t &W, matrix_t &mat, const int color_beg = 0) const;
164 
165  // Return number of colors
166  int
167  getNumColors() const
168  {
169  return num_colors * matrix->getBlockSize();
170  }
171 
172  // Get color given a column index
173  int
174  getColor(const size_t col) const
175  {
176  const int block_size = matrix->getBlockSize();
177  const size_t block_col = col / block_size;
178  const int offset = col - block_col * block_size;
179  return (list_of_colors_host(block_col) - 1) * block_size + offset;
180  }
181 
182  // Check coloring is valid, i.e., no row has two nonzero columns with
183  // same color
184  bool
186  {
188  }
189 
190 protected:
191  Teuchos::RCP<matrix_t> matrix;
192  Teuchos::RCP<const graph_t> graph;
196 };
197 
199 
200 template <typename CrsMatrixType>
202  const Teuchos::RCP<matrix_t> &matrix_
203 )
204  : matrix(matrix_),
205  graph(matrix->getCrsGraph()),
206  list_of_colors(),
207  list_of_colors_host(),
208  num_colors(0)
209 {
210 
211 }
212 
214 template <typename CrsMatrixType>
215 void
217  Teuchos::ParameterList &coloring_params
218 )
219 {
220  const std::string library = coloring_params.get("library", "zoltan");
221 
222  if (library == "zoltan") {
223  // Use Zoltan's coloring
224  ZoltanCrsColorer<matrix_t> zz(matrix);
225  zz.computeColoring(coloring_params,
226  num_colors, list_of_colors_host, list_of_colors);
227  }
228  else {
229  // Use Zoltan2's coloring
230  Zoltan2CrsColorer<matrix_t> zz2(matrix);
231  zz2.computeColoring(coloring_params,
232  num_colors, list_of_colors_host, list_of_colors);
233  }
234 }
235 
237 template <typename CrsMatrixType>
238 template <typename MultiVectorType>
239 void
241  MultiVectorType &V, const int color_beg) const
242 {
243  MultiVectorType V_fitted(graph->getColMap(), V.getNumVectors());
244 
245  computeSeedMatrixFitted(V_fitted, color_beg);
246 
247  Tpetra::Import<lno_t, gno_t, node_t>
248  importer(graph->getColMap(), V.getMap());
249 
250  V.doImport(V_fitted, importer, Tpetra::INSERT);
251 }
252 
254 template <typename CrsMatrixType>
255 template <typename MultiVectorType>
256 void
258  MultiVectorType &V, const int color_beg) const
259 {
260  // Check V's map is locally fitted to the graph's column map
261  TEUCHOS_TEST_FOR_EXCEPTION(
262  !(graph->getColMap()->isLocallyFitted(*(V.getMap()))), std::domain_error,
263  "Map for supplied vector is not locally fitted to the column map of the"
264  " Jacobian graph. "
265  "You must call the non-fitted version of this function.");
266 
267  auto V_view_dev = V.getLocalViewDevice(Tpetra::Access::OverwriteAll);
268  const size_t num_local_cols = graph->getLocalNumCols();
269  const int chunk_size = V.getNumVectors();
270  list_of_colors_t my_list_of_colors = list_of_colors;
271 
272  Kokkos::parallel_for(
273  "TpetraCrsColorer::computeSeedMatrixFitted()",
274  Kokkos::RangePolicy<execution_space>(0, num_local_cols),
275  KOKKOS_LAMBDA(const size_t i) {
276  const int color = my_list_of_colors[i] - 1 - color_beg;
277  if (color >= 0 && color < chunk_size)
278  V_view_dev(i, color) = scalar_t(1.0);
279  });
280 
281 }
282 
284 template <typename CrsMatrixType>
285 template <typename MultiVectorType>
286 void
288  MultiVectorType &W, const int color_beg) const
289 {
290  reconstructMatrix(W, *matrix, color_beg);
291 }
292 
294 template <typename CrsMatrixType>
295 template <typename MultiVectorType>
296 void
298  MultiVectorType &W,
299  matrix_t &mat,
300  const int color_beg) const
301 {
302  MultiVectorType W_fitted(graph->getRowMap(), W.getNumVectors());
303 
304  Tpetra::Import<lno_t, gno_t, node_t>
305  importer(W.getMap(), graph->getRowMap());
306 
307  W_fitted.doImport(W, importer, Tpetra::INSERT);
308 
309  reconstructMatrixFitted(W_fitted, mat, color_beg);
310 }
311 
313 template <typename CrsMatrixType>
314 template <typename MultiVectorType>
315 void
317  MultiVectorType &W, const int color_beg) const
318 {
319  reconstructMatrixFitted(W, *matrix, color_beg);
320 }
321 
323 template <typename CrsMatrixType>
324 template <typename MultiVectorType>
325 void
327  MultiVectorType &W,
328  matrix_t &mat,
329  const int color_beg) const
330 {
331  // Check the graph's row map is locally fitted to W's map
332  TEUCHOS_TEST_FOR_EXCEPTION(
333  !(W.getMap()->isLocallyFitted(*(graph->getRowMap()))), std::domain_error,
334  "Row map of the Jacobian graph is not locally fitted to the vector's map."
335  " You must call the non-fitted version of this function.");
336 
337  auto W_view_dev = W.getLocalViewDevice(Tpetra::Access::ReadOnly);
338  auto local_matrix = mat.getLocalMatrixDevice();
339  auto local_graph = local_matrix.graph;
340  const size_t num_local_rows = graph->getLocalNumRows();
341  const int chunk_size = W.getNumVectors();
342  list_of_colors_t my_list_of_colors = list_of_colors;
343 
344  Kokkos::parallel_for(
345  "TpetraCrsColorer::reconstructMatrixFitted()",
346  Kokkos::RangePolicy<execution_space>(0, num_local_rows),
347  KOKKOS_LAMBDA(const size_t row) {
348  const size_t entry_begin = local_graph.row_map(row);
349  const size_t entry_end = local_graph.row_map(row + 1);
350  for (size_t entry = entry_begin; entry < entry_end; entry++)
351  {
352  const size_t col = local_graph.entries(entry);
353  const int color = my_list_of_colors[col] - 1 - color_beg;
354  if (color >= 0 && color < chunk_size)
355  local_matrix.values(entry) = W_view_dev(row, color);
356  }
357  });
358 }
359 
361 template <typename SC, typename LO, typename GO, typename NO>
363  const Teuchos::RCP<matrix_t> &matrix_
364 )
365  : matrix(matrix_)
366  , graph(Teuchos::rcp(&(matrix->getCrsGraph()), false))
367  , list_of_colors()
368  , list_of_colors_host()
369  , num_colors(0)
370 {
371 }
372 
374 template <typename SC, typename LO, typename GO, typename NO>
375 void
377  Teuchos::ParameterList &coloring_params
378 )
379 {
380  const std::string library = coloring_params.get("library", "zoltan");
381 
382  if (library == "zoltan") {
383  // Use Zoltan's coloring
384  ZoltanCrsColorer<matrix_t> zz(matrix);
385  zz.computeColoring(coloring_params,
386  num_colors, list_of_colors_host, list_of_colors);
387  }
388  else {
389  // Use Zoltan2's coloring
390  Zoltan2CrsColorer<matrix_t> zz2(matrix);
391  zz2.computeColoring(coloring_params,
392  num_colors, list_of_colors_host, list_of_colors);
393  }
394 }
395 
397 template <typename SC, typename LO, typename GO, typename NO>
398 void
400  multivector_t &block_V, const int color_beg) const
401 {
402  multivector_t block_V_fitted(*(graph->getColMap()), matrix->getBlockSize(),
403  block_V.getNumVectors());
404 
405  computeSeedMatrixFitted(block_V_fitted, color_beg);
406 
407  const lno_t block_size = block_V.getBlockSize();
408  auto col_point_map = multivector_t::makePointMap(*graph->getColMap(),
409  block_size);
410  auto blockV_point_map = multivector_t::makePointMap(*block_V.getMap(),
411  block_size);
412  const auto col_point_map_rcp =
413  Teuchos::rcp(new Tpetra::Map<LO, GO, NO>(col_point_map));
414  const auto blockV_point_map_rcp =
415  Teuchos::rcp(new Tpetra::Map<LO, GO, NO>(blockV_point_map));
416 
417  Tpetra::Import<LO, GO, NO> importer_point(col_point_map_rcp,
418  blockV_point_map_rcp);
419 
420  block_V.getMultiVectorView().doImport(block_V_fitted.getMultiVectorView(),
421  importer_point, Tpetra::INSERT);
422 
423  // Tpetra::Import<LO,GO,NO> importer(graph->getColMap(), block_V.getMap());
424  // block_V.doImport(block_V_fitted, importer, Tpetra::INSERT);
425 }
426 
428 template <typename SC, typename LO, typename GO, typename NO>
429 void
431  multivector_t &blockV, const int color_beg) const
432 {
433  // Check blockV's map is locally fitted to the graph's column map
434  TEUCHOS_TEST_FOR_EXCEPTION(
435  !(graph->getColMap()->isLocallyFitted(*(blockV.getMap()))),
436  std::domain_error,
437  "Map for supplied vector is not locally fitted to the column map of the"
438  " Jacobian graph. "
439  "You must call the non-fitted version of this function.");
440 
441  const lno_t block_size = blockV.getBlockSize();
442  auto V = blockV.getMultiVectorView();
443  auto V_view_dev = V.getLocalViewDevice(Tpetra::Access::ReadWrite);
444  const size_t num_local_cols = V_view_dev.extent(0) / block_size;
445  const int chunk_size = V.getNumVectors() / block_size;
446  const int block_color_beg = color_beg / block_size;
447  list_of_colors_t my_list_of_colors = list_of_colors;
448 
449  Kokkos::parallel_for(
450  "TpetraCrsColorer::computeSeedMatrixFitted()",
451  Kokkos::RangePolicy<execution_space>(0, num_local_cols),
452  KOKKOS_LAMBDA(const size_t i) {
453  const int color = my_list_of_colors[i] - 1 - block_color_beg;
454  if (color >= 0 && color < chunk_size)
455  for (lno_t j = 0; j < block_size; ++j)
456  V_view_dev(i*block_size+j, color*block_size+j) = scalar_t(1.0);
457  });
458 
459 }
460 
462 template <typename SC, typename LO, typename GO, typename NO>
463 void
465  multivector_t &W, const int color_beg) const
466 {
467  reconstructMatrix(W, *matrix, color_beg);
468 }
469 
471 template <typename SC, typename LO, typename GO, typename NO>
472 void
474  multivector_t &block_W,
475  matrix_t &mat,
476  const int color_beg) const
477 {
478  multivector_t block_W_fitted(*(graph->getRowMap()), matrix->getBlockSize(),
479  block_W.getNumVectors());
480 
481  const lno_t block_size = block_W.getBlockSize();
482  auto row_point_map = multivector_t::makePointMap(*graph->getRowMap(),
483  block_size);
484  auto blockW_point_map = multivector_t::makePointMap(*block_W.getMap(),
485  block_size);
486  const auto row_point_map_rcp =
487  Teuchos::rcp(new Tpetra::Map<LO, GO, NO>(row_point_map));
488  const auto blockW_point_map_rcp =
489  Teuchos::rcp(new Tpetra::Map<LO, GO, NO>(blockW_point_map));
490 
491  Tpetra::Import<lno_t, gno_t, node_t>
492  importer_point(blockW_point_map_rcp, row_point_map_rcp);
493 
494  block_W_fitted.getMultiVectorView().doImport(block_W.getMultiVectorView(),
495  importer_point, Tpetra::INSERT);
496  reconstructMatrixFitted(block_W_fitted, mat, color_beg);
497 }
498 
500 template <typename SC, typename LO, typename GO, typename NO>
501 void
503  multivector_t &W, const int color_beg) const
504 {
505  reconstructMatrixFitted(W, *matrix, color_beg);
506 }
507 
509 template <typename SC, typename LO, typename GO, typename NO>
510 void
512  multivector_t &block_W,
513  matrix_t &mat,
514  const int color_beg) const
515 {
516  // Check the graph's row map is locally fitted to W's map
517  TEUCHOS_TEST_FOR_EXCEPTION(
518  !(block_W.getMap()->isLocallyFitted(*(graph->getRowMap()))),
519  std::domain_error,
520  "Row map of the Jacobian graph is not locally fitted to the vector's map."
521  " You must call the non-fitted version of this function.");
522 
523  // Blocks are block_size x block_size stored with LayoutRight
524  const lno_t block_size = block_W.getBlockSize();
525  const lno_t block_stride = block_size * block_size;
526  const lno_t block_row_stride = block_size;
527 
528  auto W = block_W.getMultiVectorView();
529  auto W_view_dev = W.getLocalViewDevice(Tpetra::Access::ReadOnly);
530  auto matrix_vals = mat.getValuesDeviceNonConst();
531  auto local_graph = graph->getLocalGraphDevice();
532  const size_t num_local_rows = graph->getLocalNumRows();
533  const int chunk_size = W.getNumVectors() / block_size;
534  const int block_color_beg = color_beg / block_size;
535  list_of_colors_t my_list_of_colors = list_of_colors;
536 
537  Kokkos::parallel_for(
538  "TpetraCrsColorer::reconstructMatrix()",
539  Kokkos::RangePolicy<execution_space>(0, num_local_rows),
540  KOKKOS_LAMBDA(const size_t block_row) {
541  const size_t entry_begin = local_graph.row_map(block_row);
542  const size_t entry_end = local_graph.row_map(block_row + 1);
543  for (size_t block_entry = entry_begin; block_entry < entry_end;
544  block_entry++)
545  {
546  const size_t block_col = local_graph.entries(block_entry);
547  const size_t block_offset = block_stride * block_entry;
548  const int block_color = my_list_of_colors[block_col] - 1 - block_color_beg;
549  if (block_color >= 0 && block_color < chunk_size)
550  {
551  for (lno_t i = 0; i < block_size; ++i)
552  {
553  const size_t row = block_row * block_size + i;
554  for (lno_t j = 0; j < block_size; ++j)
555  {
556  const size_t entry = block_offset + block_row_stride * i + j;
557  matrix_vals(entry) = W_view_dev(row, block_color*block_size+j);
558  }
559  }
560  }
561  }
562  });
563 }
564 } // namespace Tpetra
void computeColoring(Teuchos::ParameterList &coloring_params, int &num_colors, list_of_colors_host_t &list_of_colors_host, list_of_colors_t &list_of_colors) const
list_of_colors_host_t list_of_colors_host
void computeColoring(Teuchos::ParameterList &coloring_params)
void computeColoring(Teuchos::ParameterList &coloring_params, int &num_colors, list_of_colors_host_t &list_of_colors_host, list_of_colors_t &list_of_colors)
list_of_colors_t::HostMirror list_of_colors_host_t
matrix_t::local_ordinal_type lno_t
void computeSeedMatrix(MultiVectorType &V, const int color_beg=0) const
void reconstructMatrix(MultiVectorType &W, const int color_beg=0) const
void reconstructMatrixFitted(MultiVectorType &W, const int color_beg=0) const
bool check_coloring(const Tpetra::CrsGraph< LO, GO, NO > &graph, const list_of_colors_t &list_of_colors)
Kokkos::View< int *, device_t > list_of_colors_t
TpetraCrsColorer(const Teuchos::RCP< matrix_t > &matrix_)
matrix_t::global_ordinal_type gno_t
int getColor(const size_t col) const
Teuchos::RCP< const graph_t > graph
void computeSeedMatrixFitted(MultiVectorType &V, const int color_beg=0) const
device_t::execution_space execution_space
matrix_t::crs_graph_type graph_t