Zoltan2
Loading...
Searching...
No Matches
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"
14
15// Class to test the Colorer utility
16class ColorerTest {
17public:
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
218private:
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
253int 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}
common code used by tests
float zscalar_t
int main()
ColorerTest(Teuchos::RCP< const Teuchos::Comm< int > > &comm, int narg, char **arg)
bool run(const char *testname, Teuchos::ParameterList &params)
Tpetra::CrsMatrix< zscalar_t > matrix_t
Definition Bug9500.cpp:21
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::MultiVector< zscalar_t > multivector_t
Definition Bug9500.cpp:22
typename matrix_t::device_type::execution_space execution_space_t
Definition Bug9500.cpp:23
Tpetra::CrsGraph<> graph_t
Definition Bug9500.cpp:20
Tpetra::Map<> map_t
Definition Bug9500.cpp:18
RCP< tcrsMatrix_t > getUITpetraCrsMatrix()