Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Bug9500.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 
28  ColorerTest(const Teuchos::RCP<const Teuchos::Comm<int> > &comm, int multiple)
29  {
30  int me = comm->getRank();
31  int np = comm->getSize();
32 
33  // Create non-symmetrix matrix with non-contiguous row map -- only even GIDs
34  size_t myNrows = 4;
35  Teuchos::Array<gno_t> myRows(myNrows);
36  for (size_t i = 0; i < myNrows; i++) {
37  myRows[i] = multiple * (me * myNrows + i);
38  }
39 
40  Tpetra::global_size_t dummy =
41  Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid();
42  Teuchos::RCP<const map_t> map = rcp(new map_t(dummy, myRows, 0, comm));
43 
44  size_t nnz = 2;
45  JBlock = rcp(new matrix_t(map, nnz));
46  Teuchos::Array<gno_t> myCols(nnz);
47  Teuchos::Array<zscalar_t> myVals(nnz);
48 
49  for (size_t i = 0; i < myNrows; i++) {
50  auto gid = map->getGlobalElement(i);
51  size_t cnt = 0;
52  myCols[cnt++] = gid;
53  if (gid+multiple <= map->getMaxAllGlobalIndex())
54  myCols[cnt++] = gid+multiple;
55  JBlock->insertGlobalValues(gid, myCols(0,cnt), myVals(0, cnt));
56  }
57  JBlock->fillComplete();
58 
59  // Fill JBlock with random numbers for a better test.
60 #if KOKKOS_VERSION >= 40799
61  using IST = typename KokkosKernels::ArithTraits<zscalar_t>::val_type;
62 #else
63  using IST = typename Kokkos::ArithTraits<zscalar_t>::val_type;
64 #endif
65  using pool_type =
66  Kokkos::Random_XorShift64_Pool<execution_space_t>;
67  pool_type rand_pool(static_cast<uint64_t>(me));
68 
69  Kokkos::fill_random(JBlock->getLocalMatrixDevice().values, rand_pool,
70  static_cast<IST>(1.), static_cast<IST>(9999.));
71 
72  Teuchos::FancyOStream foo(Teuchos::rcp(&std::cout,false));
73  JBlock->describe(foo, Teuchos::VERB_EXTREME);
74 
75  // Build same matrix with cyclic domain and range maps
76  // To make range and domain maps differ for square matrices,
77  // keep some processors empty in the cyclic maps
78 
79  size_t nIndices = std::max(JBlock->getGlobalNumCols(),
80  JBlock->getGlobalNumRows());
81  Teuchos::Array<gno_t> indices(nIndices);
82 
83  Teuchos::RCP<const map_t> vMapCyclic =
84  getCyclicMap(JBlock->getGlobalNumCols(), indices, np-1,
85  multiple, comm);
86  Teuchos::RCP<const map_t> wMapCyclic =
87  getCyclicMap(JBlock->getGlobalNumRows(), indices, np-2,
88  multiple, comm);
89 
90  // Make JCyclic: same matrix with different Domain and Range maps
91  RCP<const graph_t> block_graph = JBlock->getCrsGraph();
92  RCP<graph_t> cyclic_graph = rcp(new graph_t(*block_graph));
93  cyclic_graph->resumeFill();
94  cyclic_graph->fillComplete(vMapCyclic, wMapCyclic);
95  JCyclic = rcp(new matrix_t(cyclic_graph));
96  JCyclic->resumeFill();
97  TEUCHOS_ASSERT(block_graph->getLocalNumRows() ==
98  cyclic_graph->getLocalNumRows());
99  {
100  auto val_s = JBlock->getLocalMatrixHost().values;
101  auto val_d = JCyclic->getLocalMatrixHost().values;
102  TEUCHOS_ASSERT(val_s.extent(0) == val_d.extent(0));
103  Kokkos::deep_copy(val_d, val_s);
104  }
105  JCyclic->fillComplete();
106  JCyclic->describe(foo, Teuchos::VERB_EXTREME);
107  }
108 
110  bool run(const char* testname, Teuchos::ParameterList &params) {
111 
112  bool ok = true;
113 
114  params.set("symmetric", false);
115 
116  // test with default maps
117  ok = buildAndCheckSeedMatrix(testname, params, true);
118 
119  // test with cyclic maps
120  ok &= buildAndCheckSeedMatrix(testname, params, false);
121 
122  return ok;
123  }
124 
127  const char *testname,
128  Teuchos::ParameterList &params,
129  const bool useBlock
130  )
131  {
132  int ierr = 0;
133 
134  // Pick matrix depending on useBlock flag
135  Teuchos::RCP<matrix_t> J = (useBlock ? JBlock : JCyclic);
136  int me = J->getRowMap()->getComm()->getRank();
137 
138  std::cout << "Running " << testname << " with "
139  << (useBlock ? "Block maps" : "Cyclic maps")
140  << std::endl;
141 
142  // Create a colorer
144  colorer.computeColoring(params);
145 
146  // Check coloring
147  if (!colorer.checkColoring()) {
148  std::cout << testname << " with "
149  << (useBlock ? "Block maps" : "Cyclic maps")
150  << " FAILED: invalid coloring returned"
151  << std::endl;
152  return false;
153  }
154 
155  // Compute seed matrix V -- the application wants this matrix
156  // Dense matrix of 0/1 indicating the compression via coloring
157 
158  const int numColors = colorer.getNumColors();
159 
160  // Compute the seed matrix; applications want this seed matrix
161 
162  multivector_t V(J->getDomainMap(), numColors);
163  colorer.computeSeedMatrix(V);
164 
165  // To test the result...
166  // Compute the compressed matrix W
167  multivector_t W(J->getRangeMap(), numColors);
168 
169  J->apply(V, W);
170 
171  // Reconstruct matrix from compression vector
172  Teuchos::RCP<matrix_t> Jp = rcp(new matrix_t(*J, Teuchos::Copy));
173  Jp->setAllToScalar(static_cast<zscalar_t>(-1.));
174 
175  colorer.reconstructMatrix(W, *Jp);
176 
177  // Check that values of J = values of Jp
178  auto J_local_matrix = J->getLocalMatrixDevice();
179  auto Jp_local_matrix = Jp->getLocalMatrixDevice();
180  const size_t num_local_nz = J->getLocalNumEntries();
181 
182  Kokkos::parallel_reduce(
183  "TpetraCrsColorer::testReconstructedMatrix()",
184  Kokkos::RangePolicy<execution_space_t>(0, num_local_nz),
185  KOKKOS_LAMBDA(const size_t nz, int &errorcnt) {
186  if (J_local_matrix.values(nz) != Jp_local_matrix.values(nz)) {
187  Kokkos::printf("Error in nonzero comparison %zu: %g != %g",
188  nz, J_local_matrix.values(nz), Jp_local_matrix.values(nz));
189  errorcnt++;
190  }
191  },
192  ierr);
193 
194 
195  if (ierr > 0) {
196  std::cout << testname << " FAILED on rank " << me << " with "
197  << (useBlock ? "Block maps" : "Cyclic maps")
198  << std::endl;
199  params.print();
200  }
201 
202  return (ierr == 0);
203  }
204 
205 private:
206 
208  // Return a map that is cyclic (like dealing rows to processors)
209  Teuchos::RCP<const map_t> getCyclicMap(
210  size_t nIndices,
211  Teuchos::Array<gno_t> &indices,
212  int mapNumProc,
213  int multiple,
214  const Teuchos::RCP<const Teuchos::Comm<int> > &comm)
215  {
216  size_t cnt = 0;
217  int me = comm->getRank();
218  int np = comm->getSize();
219  if (mapNumProc > np) mapNumProc = np; // corner case: bad input
220  if (mapNumProc <= 0) mapNumProc = 1; // corner case: np is too small
221 
222  for (size_t i = 0; i < nIndices; i++)
223  if (me == int(i % np)) indices[cnt++] = multiple*i;
224 
225  Tpetra::global_size_t dummy =
226  Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid();
227 
228  return rcp(new map_t(dummy, indices(0,cnt), 0, comm));
229  }
230 
232  // Input matrix -- built in Constructor
233  bool symmetric; // User can specify whether matrix is symmetric
234  Teuchos::RCP<matrix_t> JBlock; // has Trilinos default domain and range maps
235  Teuchos::RCP<matrix_t> JCyclic; // has cyclic domain and range maps
236 };
237 
238 
240 int doTheTest(const Teuchos::RCP<const Teuchos::Comm<int> > &comm, int multiple)
241 {
242  bool ok = true;
243  int ierr = 0;
244 
245  ColorerTest testColorer(comm, multiple);
246 
247  // Set parameters and compute coloring
248  {
249  Teuchos::ParameterList coloring_params;
250  std::string matrixType = "Jacobian";
251  bool symmetrize = true; // Zoltan's TRANSPOSE symmetrization, if needed
252 
253  coloring_params.set("MatrixType", matrixType);
254  coloring_params.set("symmetrize", symmetrize);
255 
256  ok = testColorer.run("Test One", coloring_params);
257  if (!ok) ierr++;
258  }
259 
260  {
261  Teuchos::ParameterList coloring_params;
262  std::string matrixType = "Jacobian";
263  bool symmetrize = false; // colorer's BIPARTITE symmetrization, if needed
264 
265  coloring_params.set("MatrixType", matrixType);
266  coloring_params.set("symmetrize", symmetrize);
267 
268  ok = testColorer.run("Test Two", coloring_params);
269  if (!ok) ierr++;
270  }
271 
272  {
273  Teuchos::ParameterList coloring_params;
274  std::string matrixType = "Jacobian";
275 
276  coloring_params.set("MatrixType", matrixType);
277 
278  ok = testColorer.run("Test Three", coloring_params);
279  if (!ok) ierr++;
280  }
281  return ierr;
282 }
283 
285 int main(int narg, char **arg)
286 {
287  Tpetra::ScopeGuard scope(&narg, &arg);
288  Teuchos::RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
289  int ierr = 0;
290 
291  ierr += doTheTest(comm, 1); // Contiguous row map
292  ierr += doTheTest(comm, 2); // Non-contiguous row map --
293  // only even-numbered indices
294  ierr += doTheTest(comm, 5); // Indices spaced wider than rows/proc
295 
296  int gerr;
297  Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_SUM, 1, &ierr, &gerr);
298  if (comm->getRank() == 0) {
299  if (gerr == 0)
300  std::cout << "TEST PASSED" << std::endl;
301  else
302  std::cout << "TEST FAILED" << std::endl;
303  }
304 }
Tpetra::CrsMatrix< zscalar_t > matrix_t
Definition: Bug9500.cpp:21
int doTheTest(const Teuchos::RCP< const Teuchos::Comm< int > > &comm, int multiple)
Definition: Bug9500.cpp:240
typename matrix_t::device_type::execution_space execution_space_t
Definition: Bug9500.cpp:23
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
ColorerTest(const Teuchos::RCP< const Teuchos::Comm< int > > &comm, int multiple)
Definition: Bug9500.cpp:28
bool run(const char *testname, Teuchos::ParameterList &params)
Definition: Bug9500.cpp:110
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:126
Tpetra::global_size_t global_size_t
Tpetra::CrsGraph<> graph_t
Definition: Bug9500.cpp:20
Tpetra::Map<> map_t
Definition: Bug9500.cpp:18