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