Zoltan2
Loading...
Searching...
No Matches
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"
14
15// Class to test the Colorer utility
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
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 KokkosKernels::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
201private:
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
236int 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
281int 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}
int doTheTest(const Teuchos::RCP< const Teuchos::Comm< int > > &comm, int multiple)
Definition Bug9500.cpp:236
common code used by tests
float zscalar_t
int main()
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
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