Zoltan2
componentMetrics.cpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Zoltan2: A package of combinatorial algorithms for scientific computing
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Karen Devine (kddevin@sandia.gov)
39 // Erik Boman (egboman@sandia.gov)
40 // Siva Rajamanickam (srajama@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
48 #include <Zoltan2_TestHelpers.hpp>
49 #include <iostream>
50 #include <Teuchos_RCP.hpp>
51 #include <Tpetra_CrsMatrix.hpp>
52 #include <Tpetra_DefaultPlatform.hpp>
53 #include <MatrixMarket_Tpetra.hpp>
54 
55 
57 // Test program for componentMetrics code.
58 // Usage:
59 // a.out
60 // Karen Devine, 2017
62 
63 typedef Tpetra::Map<zlno_t, zgno_t> zmap_t;
64 typedef Tpetra::CrsMatrix<zscalar_t, zlno_t, zgno_t> zmatrix_t;
65 typedef Tpetra::CrsGraph<zlno_t, zgno_t> zgraph_t;
66 
69 
71 template <typename CC_T>
73  std::string &name, // test name (including rank)
74  CC_T cc, // the perProcessorComponentMetrics object for the test
75  size_t nccAnswer, // Expected answers for the test
76  size_t maxAnswer,
77  size_t minAnswer,
78  double avgAnswer
79 )
80 {
81  int ierr = 0;
82 
83  if (cc.getNumComponents() != nccAnswer) {
84  std::cout << name << "Invalid number of components "
85  << cc.getNumComponents() << " should be " << nccAnswer
86  << std::endl;
87  ierr++;
88  }
89 
90  if (cc.getMaxComponentSize() != maxAnswer) {
91  std::cout << name << "Maximum component size "
92  << cc.getMaxComponentSize() << " should be " << maxAnswer
93  << std::endl;
94  ierr++;
95  }
96 
97  if (cc.getMinComponentSize() != minAnswer) {
98  std::cout << name << "Minimum component size "
99  << cc.getMinComponentSize() << " should be " << minAnswer
100  << std::endl;
101  ierr++;
102  }
103 
104  if (cc.getAvgComponentSize() != avgAnswer) {
105  std::cout << name << "Average component size "
106  << cc.getAvgComponentSize() << " should be " << avgAnswer
107  << std::endl;
108  ierr++;
109  }
110 
111  return ierr;
112 }
113 
115 int test_every_third(Teuchos::RCP<const Teuchos::Comm<int> > &comm)
116 {
117  // Testing a graph with every third vertex in the same component
118  // Test using a GraphAdapter.
119 
120  std::ostringstream namestream;
121  namestream << comm->getRank() << " every_third ";
122  std::string name = namestream.str();
123 
124  int ierr = 0;
125 
126  // Create a default map
127  const size_t gNvtx = 27;
128 
129  Teuchos::RCP<const zmap_t> map = rcp(new zmap_t(gNvtx, 0, comm));
130  size_t nVtx = map->getNodeNumElements();
131 
132  // Create a Tpetra::Matrix with every third local row in the same component
133  size_t maxRowLen = 1;
134  Teuchos::RCP<zmatrix_t> matrix = rcp(new zmatrix_t(map, maxRowLen));
135 
136  Teuchos::Array<zgno_t> col(3);
137  Teuchos::Array<zscalar_t> val(3); val[0] = 1.; val[1] = 1.; val[2] = 1.;
138 
139  for (size_t i = 0; i < nVtx; i++) {
140  zgno_t id = map->getGlobalElement(i);
141  col[0] = (id+3)%gNvtx;
142  col[1] = (id+6)%gNvtx;
143  col[2] = (id+9)%gNvtx;
144  matrix->insertGlobalValues(id, col(), val());
145  }
146 
147  matrix->fillComplete(map, map);
148 
149  // Create a Zoltan2 XpetraGraphAdapter
150  graphAdapter_t ia(matrix->getCrsGraph(), 0);
151 
152  // Call connected components utility
154  cc_t cc(ia, *comm);
155 
156  // Check result:
157  size_t nccAnswer = std::min<size_t>(3, nVtx);
158  size_t maxAnswer = nVtx/3 + ((nVtx%3)!=0);
159  size_t minAnswer = (nVtx ? std::max<size_t>(nVtx/3, 1) : 0);
160  double avgAnswer = (nVtx ? double(nVtx) / double(std::min<size_t>(nVtx,3))
161  : 0.);
162 
163  ierr = checkResult<cc_t>(name, cc,
164  nccAnswer, maxAnswer, minAnswer, avgAnswer);
165 
166  return ierr;
167 }
168 
170 int test_dist_component(Teuchos::RCP<const Teuchos::Comm<int> > &comm)
171 {
172  // Testing a graph with single component, distributed among procs
173  // Test using a GraphAdapter.
174 
175  std::ostringstream namestream;
176  namestream << comm->getRank() << " dist_component ";
177  std::string name = namestream.str();
178 
179  int ierr = 0;
180 
181  // Create a default map
182  const size_t gNvtx = 25;
183 
184  Teuchos::RCP<const zmap_t> map = rcp(new zmap_t(gNvtx, 0, comm));
185  size_t nVtx = map->getNodeNumElements();
186 
187  // Create a Tpetra::Matrix with a single component
188  size_t maxRowLen = 1;
189  Teuchos::RCP<zmatrix_t> matrix = rcp(new zmatrix_t(map, maxRowLen));
190 
191  Teuchos::Array<zgno_t> col(3);
192  Teuchos::Array<zscalar_t> val(3); val[0] = 1.; val[1] = 1.; val[2] = 1.;
193 
194  for (size_t i = 0; i < nVtx; i++) {
195  zgno_t id = map->getGlobalElement(i);
196  col[0] = (id+4)%gNvtx;
197  col[1] = (id+1)%gNvtx;
198  col[2] = (id+3)%gNvtx;
199  matrix->insertGlobalValues(id, col(), val());
200  }
201 
202  matrix->fillComplete(map, map);
203 
204  // Create a Zoltan2 XpetraGraphAdapter
205  graphAdapter_t ia(matrix->getCrsGraph(), 0);
206 
207  // Call connected components utility
209  cc_t cc(ia, *comm);
210 
211  // Check result:
212  // one component with all local vertices
213  size_t nccAnswer = size_t(nVtx > 0);
214  size_t maxAnswer = nVtx;
215  size_t minAnswer = nVtx;
216  double avgAnswer = nVtx;
217 
218  ierr = checkResult<cc_t>(name, cc,
219  nccAnswer, maxAnswer, minAnswer, avgAnswer);
220 
221  return ierr;
222 }
223 
225 int test_one_proc(Teuchos::RCP<const Teuchos::Comm<int> > &comm)
226 {
227  // Testing a graph with all vertices and edges on a single proc
228  // Test using a MatrixAdapter.
229 
230  std::ostringstream namestream;
231  namestream << comm->getRank() << " one_proc ";
232  std::string name = namestream.str();
233 
234  int ierr = 0;
235 
236  int me = comm->getRank();
237  int np = comm->getSize();
238  bool allOnThisProc = (me == np-1);
239 
240  // Create a map with all data on a single proc
241  const size_t gNvtx = 25;
242  size_t nVtx;
243 
244  if (allOnThisProc) nVtx = gNvtx;
245  else nVtx = 0;
246 
247  Teuchos::RCP<const zmap_t> map = rcp(new zmap_t(gNvtx, nVtx, 0, comm));
248 
249  // Create a Tpetra::Matrix with one component
250  size_t maxRowLen = 1;
251  Teuchos::RCP<zmatrix_t> matrix = rcp(new zmatrix_t(map, maxRowLen));
252  if (allOnThisProc) {
253  Teuchos::Array<zgno_t> col(2);
254  Teuchos::Array<zscalar_t> val(2); val[0] = 1.; val[1] = 1.;
255  for (size_t i = 0; i < nVtx; i++) {
256  zgno_t id = map->getGlobalElement(i);
257  col[0] = id;
258  col[1] = (id+1)%gNvtx;
259  matrix->insertGlobalValues(id, col(), val());
260  }
261  }
262  matrix->fillComplete(map, map);
263 
264  // Create a Zoltan2 XpetraMatrixAdapter
265  matrixAdapter_t ia(matrix, 0);
266 
267  // Call connected components utility
269  cc_t cc(ia, *comm);
270 
271  // Check result:
272  if (allOnThisProc) {
273  // one component with all global vertices
274  size_t nccAnswer = 1;
275  size_t maxAnswer = gNvtx;
276  size_t minAnswer = gNvtx;
277  double avgAnswer = double(gNvtx);
278 
279  ierr = checkResult<cc_t>(name, cc,
280  nccAnswer, maxAnswer, minAnswer, avgAnswer);
281  }
282  else {
283  // one component with all global vertices
284  size_t nccAnswer = 0;
285  size_t maxAnswer = 0;
286  size_t minAnswer = 0;
287  double avgAnswer = 0.;
288 
289  ierr = checkResult<cc_t>(name, cc,
290  nccAnswer, maxAnswer, minAnswer, avgAnswer);
291  }
292 
293  return ierr;
294 }
295 
297 int test_no_graph(Teuchos::RCP<const Teuchos::Comm<int> > &comm)
298 {
299  // Testing a graph with no edges
300  // Test using a MatrixAdapter.
301  // Test using an MPI communicator rather than Teuchos::Comm, if appropriate.
302 
303  std::ostringstream namestream;
304  namestream << comm->getRank() << " no_graph ";
305  std::string name = namestream.str();
306 
307  int ierr = 0;
308 
309  // Create a default map
310  const size_t gNvtx = 25;
311 
312  Teuchos::RCP<const zmap_t> map = rcp(new zmap_t(gNvtx, 0, comm));
313  size_t nVtx = map->getNodeNumElements();
314 
315  // Create a Tpetra::Matrix with no edges
316  size_t maxRowLen = 1;
317  Teuchos::RCP<zmatrix_t> matrix = rcp(new zmatrix_t(map, maxRowLen));
318  matrix->fillComplete(map, map);
319 
320  // Create a Zoltan2 XpetraMatrixAdapter
321  matrixAdapter_t ia(matrix, 0);
322 
323 #ifdef HAVE_ZOLTAN2_MPI
324  // For testing only, extract MPI communicator from Teuchos::Comm
325  // There's no need to do this in real life; use Teuchos::Comm if you have it.
326  // We just want to exercise the MPI_Comm interface here.
327  if (comm->getRank() == 0) std::cout << " using MPI_Comm " << std::endl;
328  MPI_Comm useThisComm = Teuchos::getRawMpiComm(*comm);
329 #else
330  const Teuchos::Comm<int> &useThisComm = *comm;
331 #endif
332 
333  // Call connected components utility
335  cc_t cc(ia, useThisComm);
336 
337  // Check result:
338  // With no edges, every vertex should be a component
339  size_t nccAnswer = nVtx;
340  size_t maxAnswer = size_t(nVtx > 0);
341  size_t minAnswer = size_t(nVtx > 0);
342  double avgAnswer = double(nVtx > 0);
343 
344  ierr = checkResult<cc_t>(name, cc,
345  nccAnswer, maxAnswer, minAnswer, avgAnswer);
346 
347  return ierr;
348 }
349 
351 int main(int narg, char** arg)
352 {
353  // Establish session.
354  Teuchos::GlobalMPISession mpiSession(&narg, &arg, NULL);
355  Teuchos::RCP<const Teuchos::Comm<int> > comm =
356  Tpetra::DefaultPlatform::getDefaultPlatform().getComm();
357  int me = comm->getRank();
358 
359  int testReturn = 0;
360  if (me == 0) std::cout << "test_one_proc..." << std::endl;
361  testReturn += test_one_proc(comm); // all data on a single proc
362  if (me == 0) std::cout << "test_no_graph..." << std::endl;
363  testReturn += test_no_graph(comm); // no edges in graph
364  if (me == 0) std::cout << "test_dist_component..." << std::endl;
365  testReturn += test_dist_component(comm); // one component per rank
366  if (me == 0) std::cout << "test_every_third..." << std::endl;
367  testReturn += test_every_third(comm); // every 3rd vtx in same component
368 
369  int gtestReturn = 0;
370  Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, 1,
371  &testReturn, &gtestReturn);
372  if (me == 0) {
373  if (gtestReturn) std::cout << "FAIL" << std::endl;
374  else std::cout << "PASS" << std::endl;
375  }
376 
377  return gtestReturn;
378 }
Tpetra::CrsGraph< zlno_t, zgno_t > zgraph_t
Provides access for Zoltan2 to Xpetra::CrsMatrix data.
int test_dist_component(Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Zoltan2::XpetraCrsMatrixAdapter< zmatrix_t > matrixAdapter_t
int checkResult(std::string &name, CC_T cc, size_t nccAnswer, size_t maxAnswer, size_t minAnswer, double avgAnswer)
Provides access for Zoltan2 to Xpetra::CrsGraph data.
Zoltan2::XpetraCrsGraphAdapter< zgraph_t > graphAdapter_t
int test_every_third(Teuchos::RCP< const Teuchos::Comm< int > > &comm)
common code used by tests
int test_one_proc(Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Tpetra::CrsMatrix< zscalar_t, zlno_t, zgno_t > zmatrix_t
Defines XpetraCrsGraphAdapter class.
Defines the XpetraCrsMatrixAdapter class.
int test_no_graph(Teuchos::RCP< const Teuchos::Comm< int > > &comm)
int zgno_t
int main(int narg, char **arg)
Identify and compute the number of connected components in a processor&#39;s input Note that this routine...
Tpetra::Map< zlno_t, zgno_t > zmap_t