Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
TpetraCrsColorer.cpp
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 #include "Tpetra_Core.hpp"
11 #include "Kokkos_Random.hpp"
12 #include "Zoltan2_TestHelpers.hpp"
14 
15 // Class to test the Colorer utility
16 class ColorerTest {
17 public:
18  using map_t = Tpetra::Map<>;
19  using gno_t = typename map_t::global_ordinal_type;
20  using graph_t = Tpetra::CrsGraph<>;
21  using matrix_t = Tpetra::CrsMatrix<zscalar_t>;
22  using multivector_t = Tpetra::MultiVector<zscalar_t>;
23  using execution_space_t = typename matrix_t::device_type::execution_space;
24 
26  // Construct the test:
27  // Read or generate a matrix (JBlock) with default range and domain maps
28  // Construct identical matrix (JCyclic) with cyclic range and domain maps
29 
30  ColorerTest(Teuchos::RCP<const Teuchos::Comm<int> > &comm,
31  int narg, char**arg)
32  : symmetric(false)
33  {
34  int me = comm->getRank();
35  int np = comm->getSize();
36 
37  // Process command line arguments
38  bool distributeInput = true;
39  size_t xdim = 10, ydim = 11, zdim = 12;
40 
41  Teuchos::CommandLineProcessor cmdp(false, false);
42  cmdp.setOption("file", &matrixFileName,
43  "Name of the Matrix Market file to use");
44  cmdp.setOption("xdim", &xdim,
45  "Number of nodes in x-direction for generated matrix");
46  cmdp.setOption("ydim", &ydim,
47  "Number of nodes in y-direction for generated matrix");
48  cmdp.setOption("zdim", &zdim,
49  "Number of nodes in z-direction for generated matrix");
50  cmdp.setOption("distribute", "no-distribute", &distributeInput,
51  "Should Zoltan2 distribute the matrix as it is read?");
52  cmdp.setOption("symmetric", "non-symmetric", &symmetric,
53  "Is the matrix symmetric?");
54  cmdp.parse(narg, arg);
55 
56  // Get and store a matrix
57  if (matrixFileName != "") {
58  // Read from a file
59  UserInputForTests uinput(".", matrixFileName, comm, true, distributeInput);
60  JBlock = uinput.getUITpetraCrsMatrix();
61  }
62  else {
63  // Generate a matrix
64  UserInputForTests uinput(xdim, ydim, zdim, string("Laplace3D"), comm,
65  true, distributeInput);
66  JBlock = uinput.getUITpetraCrsMatrix();
67  }
68 
69  // Build same matrix with cyclic domain and range maps
70  // To make range and domain maps differ for square matrices,
71  // keep some processors empty in the cyclic maps
72 
73  size_t nIndices = std::max(JBlock->getGlobalNumCols(),
74  JBlock->getGlobalNumRows());
75  Teuchos::Array<gno_t> indices(nIndices);
76 
77  Teuchos::RCP<const map_t> vMapCyclic =
78  getCyclicMap(JBlock->getGlobalNumCols(), indices, np-1, comm);
79  Teuchos::RCP<const map_t> wMapCyclic =
80  getCyclicMap(JBlock->getGlobalNumRows(), indices, np-2, comm);
81 
82  // Fill JBlock with random numbers for a better test.
83  JBlock->resumeFill();
84 
85  using IST = typename Kokkos::ArithTraits<zscalar_t>::val_type;
86  using pool_type =
87  Kokkos::Random_XorShift64_Pool<execution_space_t>;
88  pool_type rand_pool(static_cast<uint64_t>(me));
89 
90  Kokkos::fill_random(JBlock->getLocalMatrixDevice().values, rand_pool,
91  static_cast<IST>(1.), static_cast<IST>(9999.));
92  JBlock->fillComplete();
93 
94 
95  // Make JCyclic: same matrix with different Domain and Range maps
96  RCP<const graph_t> block_graph = JBlock->getCrsGraph();
97  RCP<graph_t> cyclic_graph = rcp(new graph_t(*block_graph));
98  cyclic_graph->resumeFill();
99  cyclic_graph->fillComplete(vMapCyclic, wMapCyclic);
100  JCyclic = rcp(new matrix_t(cyclic_graph));
101  JCyclic->resumeFill();
102  TEUCHOS_ASSERT(block_graph->getLocalNumRows() == cyclic_graph->getLocalNumRows());
103  {
104  auto val_s = JBlock->getLocalMatrixHost().values;
105  auto val_d = JCyclic->getLocalMatrixHost().values;
106  TEUCHOS_ASSERT(val_s.extent(0) == val_d.extent(0));
107  Kokkos::deep_copy(val_d, val_s);
108  }
109  JCyclic->fillComplete();
110  }
111 
113  bool run(const char *testname, Teuchos::ParameterList &params) {
114 
115  bool ok = true;
116 
117  params.set("symmetric", symmetric);
118  params.set("library", "zoltan");
119 
120  // test with default maps
121  ok = buildAndCheckSeedMatrix(testname, params, true);
122 
123  // test with cyclic maps
124  ok &= buildAndCheckSeedMatrix(testname, params, false);
125  // if (matrixFileName != "west0067") {
126 
127  params.set("library", "zoltan2");
128  // test with default maps
129  ok = buildAndCheckSeedMatrix(testname, params, true);
130 
131  // test with cyclic maps
132  ok &= buildAndCheckSeedMatrix(testname, params, false);
133  // }
134 
135  return ok;
136  }
137 
140  const char *testname,
141  Teuchos::ParameterList &params,
142  const bool useBlock
143  )
144  {
145  int ierr = 0;
146 
147  // Pick matrix depending on useBlock flag
148  Teuchos::RCP<matrix_t> J = (useBlock ? JBlock : JCyclic);
149  int me = J->getRowMap()->getComm()->getRank();
150 
151  std::cout << params.get("library", "zoltan2") << " Running " << testname << " with "
152  << (useBlock ? "Block maps" : "Cyclic maps")
153  << std::endl;
154 
155  // Create a colorer
157  colorer.computeColoring(params);
158 
159  // Check coloring
160  if (!colorer.checkColoring()) {
161  std::cout << testname << " with "
162  << (useBlock ? "Block maps" : "Cyclic maps")
163  << " FAILED: invalid coloring returned"
164  << std::endl;
165  return false;
166  }
167 
168  // Compute seed matrix V -- the application wants this matrix
169  // Dense matrix of 0/1 indicating the compression via coloring
170 
171  const int numColors = colorer.getNumColors();
172 
173  // Compute the seed matrix; applications want this seed matrix
174 
175  multivector_t V(J->getDomainMap(), numColors);
176  colorer.computeSeedMatrix(V);
177 
178  // To test the result...
179  // Compute the compressed matrix W
180  multivector_t W(J->getRangeMap(), numColors);
181 
182  J->apply(V, W);
183 
184  // Reconstruct matrix from compression vector
185  Teuchos::RCP<matrix_t> Jp = rcp(new matrix_t(*J, Teuchos::Copy));
186  Jp->setAllToScalar(static_cast<zscalar_t>(-1.));
187 
188  colorer.reconstructMatrix(W, *Jp);
189 
190  // Check that values of J = values of Jp
191  auto J_local_matrix = J->getLocalMatrixDevice();
192  auto Jp_local_matrix = Jp->getLocalMatrixDevice();
193  const size_t num_local_nz = J->getLocalNumEntries();
194 
195  Kokkos::parallel_reduce(
196  "TpetraCrsColorer::testReconstructedMatrix()",
197  Kokkos::RangePolicy<execution_space_t>(0, num_local_nz),
198  KOKKOS_LAMBDA(const size_t nz, int &errorcnt) {
199  if (J_local_matrix.values(nz) != Jp_local_matrix.values(nz)) {
200  Kokkos::printf("Error in nonzero comparison %zu: %g != %g",
201  nz, J_local_matrix.values(nz), Jp_local_matrix.values(nz));
202  errorcnt++;
203  }
204  },
205  ierr);
206 
207 
208  if (ierr > 0) {
209  std::cout << testname << " FAILED on rank " << me << " with "
210  << (useBlock ? "Block maps" : "Cyclic maps")
211  << std::endl;
212  params.print();
213  }
214 
215  return (ierr == 0);
216  }
217 
218 private:
219 
221  // Return a map that is cyclic (like dealing rows to processors)
222  Teuchos::RCP<const map_t> getCyclicMap(
223  size_t nIndices,
224  Teuchos::Array<gno_t> &indices,
225  int mapNumProc,
226  const Teuchos::RCP<const Teuchos::Comm<int> > &comm)
227  {
228  size_t cnt = 0;
229  int me = comm->getRank();
230  int np = comm->getSize();
231  if (mapNumProc > np) mapNumProc = np; // corner case: bad input
232  if (mapNumProc <= 0) mapNumProc = 1; // corner case: np is too small
233 
234  for (size_t i = 0; i < nIndices; i++)
235  if (me == int(i % np)) indices[cnt++] = i;
236 
237  Tpetra::global_size_t dummy =
238  Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid();
239 
240  return rcp(new map_t(dummy, indices(0,cnt), 0, comm));
241  }
242 
244  // Input matrix -- built in Constructor
245  bool symmetric; // User can specify whether matrix is symmetric
246  Teuchos::RCP<matrix_t> JBlock; // has Trilinos default domain and range maps
247  Teuchos::RCP<matrix_t> JCyclic; // has cyclic domain and range maps
248  std::string matrixFileName;
249 };
250 
251 
253 int main(int narg, char **arg)
254 {
255  Tpetra::ScopeGuard scope(&narg, &arg);
256  Teuchos::RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
257  bool ok = true;
258  int ierr = 0;
259 
260  ColorerTest testColorer(comm, narg, arg);
261 
262  // Set parameters and compute coloring
263  {
264  Teuchos::ParameterList coloring_params;
265  std::string matrixType = "Jacobian";
266  bool symmetrize = true; // Zoltan's TRANSPOSE symmetrization, if needed
267 
268  coloring_params.set("MatrixType", matrixType);
269  coloring_params.set("symmetrize", symmetrize);
270 
271  ok = testColorer.run("Test One", coloring_params);
272  if (!ok) ierr++;
273  }
274 
275  {
276  Teuchos::ParameterList coloring_params;
277  std::string matrixType = "Jacobian";
278  bool symmetrize = false; // colorer's BIPARTITE symmetrization, if needed
279 
280  coloring_params.set("MatrixType", matrixType);
281  coloring_params.set("symmetrize", symmetrize);
282 
283  ok = testColorer.run("Test Two", coloring_params);
284  if (!ok) ierr++;
285  }
286 
287  {
288  Teuchos::ParameterList coloring_params;
289  std::string matrixType = "Jacobian";
290 
291  coloring_params.set("MatrixType", matrixType);
292 
293  ok = testColorer.run("Test Three", coloring_params);
294  if (!ok) ierr++;
295  }
296 
297  int gerr;
298  Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_SUM, 1, &ierr, &gerr);
299  if (comm->getRank() == 0) {
300  if (gerr == 0)
301  std::cout << "TEST PASSED" << std::endl;
302  else
303  std::cout << "TEST FAILED" << std::endl;
304  }
305 
306 //Through cmake...
307 //Test cases -- UserInputForTests can generate Galeri or read files:
308 //- tri-diagonal matrix -- can check the number of colors
309 //- galeri matrix
310 //- read from file: symmetric matrix and non-symmetric matrix
311 
312 //Through code ...
313 //Test with fitted and non-fitted maps
314 //Call regular and fitted versions of functions
315 
316 //Through code ...
317 //Test both with and without Symmetrize --
318 //test both to exercise both sets of callbacks in Zoltan
319 // --matrixType = Jacobian/Hessian
320 // --symmetric, --no-symmetric
321 // --symmetrize, --no-symmetrize
322 
323 //Through cmake
324 //Test both with and without distributeInput
325 // --distribute, --no-distribute
326 
327 }
Tpetra::CrsMatrix< zscalar_t > matrix_t
Definition: Bug9500.cpp:21
typename matrix_t::device_type::execution_space execution_space_t
Definition: Bug9500.cpp:23
RCP< tcrsMatrix_t > getUITpetraCrsMatrix()
ColorerTest(Teuchos::RCP< const Teuchos::Comm< int > > &comm, int narg, char **arg)
int main(int narg, char **arg)
Definition: coloring1.cpp:164
common code used by tests
Tpetra::MultiVector< zscalar_t > multivector_t
Definition: Bug9500.cpp:22
bool run(const char *testname, Teuchos::ParameterList &params)
typename map_t::global_ordinal_type gno_t
Definition: Bug9500.cpp:19
bool buildAndCheckSeedMatrix(const char *testname, Teuchos::ParameterList &params, const bool useBlock)
Definition: Bug9500.cpp:122
Tpetra::global_size_t global_size_t
Tpetra::CrsGraph<> graph_t
Definition: Bug9500.cpp:20
Tpetra::Map<> map_t
Definition: Bug9500.cpp:18