Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
GraphModel.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
45 //
46 // Testing of GraphModel built from Xpetra matrix input adapters.
47 //
48 
58 #include <Zoltan2_GraphModel.hpp>
62 #include <Zoltan2_TestHelpers.hpp>
63 #include <Zoltan2_InputTraits.hpp>
64 
65 #include <string>
66 #include <vector>
67 #include <iostream>
68 #include <bitset>
69 
70 #include <Teuchos_Comm.hpp>
71 #include <Teuchos_DefaultComm.hpp>
72 #include <Teuchos_ArrayView.hpp>
73 
74 const int SMALL_NUMBER_OF_ROWS = 5;
75 using Teuchos::RCP;
76 using Teuchos::rcp;
77 using Teuchos::Comm;
78 using Teuchos::ArrayView;
79 
81 
82 typedef Tpetra::CrsMatrix<zscalar_t, zlno_t, zgno_t, znode_t> tcrsMatrix_t;
83 typedef Tpetra::CrsGraph<zlno_t, zgno_t, znode_t> tcrsGraph_t;
84 typedef Tpetra::Map<zlno_t, zgno_t, znode_t> tmap_t;
85 
87 
90 
93 
94 using std::string;
95 using std::vector;
96 
98 template<typename offset_t>
99 void printGraph(zlno_t nrows, const zgno_t *v,
100  const zgno_t *elid, const zgno_t *egid,
101  const offset_t *idx,
102  const RCP<const Comm<int> > &comm)
103 {
104  int rank = comm->getRank();
105  int nprocs = comm->getSize();
106  comm->barrier();
107 
108  for (int p=0; p < nprocs; p++){
109  if (p == rank){
110  std::cout << "Rank " << p << std::endl;
111  for (zlno_t i=0; i < nrows; i++){
112  std::cout << " Vtx " << i << ": ";
113  if (elid)
114  for (offset_t j=idx[i]; j < idx[i+1]; j++)
115  std::cout << *elid++ << " ";
116  else
117  for (offset_t j=idx[i]; j < idx[i+1]; j++)
118  std::cout << *egid++ << " ";
119  std::cout << std::endl;
120  }
121  std::cout.flush();
122  }
123  comm->barrier();
124  }
125  comm->barrier();
126 }
127 
129 
130 template <typename MatrixOrGraph>
132  RCP<const MatrixOrGraph> &M,
133  size_t &numLocalDiags,
134  size_t &numGlobalDiags
135 )
136 {
137  // See specializations below
138 }
139 
140 template <>
142  RCP<const tcrsGraph_t> &M,
143  size_t &numLocalDiags,
144  size_t &numGlobalDiags
145 )
146 {
147  typedef typename tcrsGraph_t::global_ordinal_type gno_t;
148 
149  size_t maxnnz = M->getLocalMaxNumRowEntries();
150  typename tcrsGraph_t::nonconst_global_inds_host_view_type colGids("colGIds", maxnnz);
151  numLocalDiags = 0;
152  numGlobalDiags = 0;
153 
154  int nLocalRows = M->getLocalNumRows();
155  for (int i = 0; i < nLocalRows; i++) {
156 
157  gno_t rowGid = M->getRowMap()->getGlobalElement(i);
158  size_t nnz;
159  M->getGlobalRowCopy(rowGid, colGids, nnz);
160 
161  for (size_t j = 0; j < nnz; j++) {
162  if (rowGid == colGids[j]) {
163  numLocalDiags++;
164  break;
165  }
166  }
167  }
168  Teuchos::reduceAll<int, size_t>(*(M->getComm()), Teuchos::REDUCE_SUM, 1,
169  &numLocalDiags, &numGlobalDiags);
170 }
171 
172 template <>
174  RCP<const tcrsMatrix_t> &M,
175  size_t &numLocalDiags,
176  size_t &numGlobalDiags
177 )
178 {
179  RCP<const tcrsGraph_t> graph = M->getCrsGraph();
180  computeNumDiags<tcrsGraph_t>(graph, numLocalDiags, numGlobalDiags);
181 }
182 
183 
185 template <typename BaseAdapter, typename Adapter, typename MatrixOrGraph>
187  RCP<const MatrixOrGraph> &M,
188  RCP<const Tpetra::CrsGraph<zlno_t, zgno_t> > &Mgraph,
189  const RCP<const Comm<int> > &comm,
190  bool idsAreConsecutive,
191  int nVtxWeights, int nEdgeWeights, int nnzWgtIdx, int coordDim,
192  bool consecutiveIdsRequested, bool removeSelfEdges, bool buildLocalGraph)
193 {
195  typedef typename
197 
198  int fail=0;
199  int rank = comm->getRank();
200  int nprocs = comm->getSize();
201  RCP<const Zoltan2::Environment> env = rcp(new Zoltan2::Environment(comm));
202 
203  zlno_t nLocalRows = M->getLocalNumRows();
204  zlno_t nLocalNZ = M->getLocalNumEntries();
205  zgno_t nGlobalRows = M->getGlobalNumRows();
206  zgno_t nGlobalNZ = M->getGlobalNumEntries();
207 
208  std::bitset<Zoltan2::NUM_MODEL_FLAGS> modelFlags;
209  if (consecutiveIdsRequested)
210  modelFlags.set(Zoltan2::GENERATE_CONSECUTIVE_IDS);
211  if (removeSelfEdges)
212  modelFlags.set(Zoltan2::REMOVE_SELF_EDGES);
213  if (buildLocalGraph)
214  modelFlags.set(Zoltan2::BUILD_LOCAL_GRAPH);
215 
216  // Set up some fake input
217  zscalar_t **coords=NULL;
218  zscalar_t **rowWeights=NULL;
219 
220  if (coordDim > 0){
221  coords = new zscalar_t * [coordDim];
222  for (int i=0; i < coordDim; i++){
223  coords[i] = new zscalar_t [nLocalRows];
224  for (zlno_t j=0; j < nLocalRows; j++){
225  coords[i][j] = 100000*i + j;
226  }
227  }
228  }
229 
230  if (nVtxWeights > 0){
231  rowWeights = new zscalar_t * [nVtxWeights];
232  for (int i=0; i < nVtxWeights; i++){
233  if (nnzWgtIdx == i)
234  rowWeights[i] = NULL;
235  else{
236  rowWeights[i] = new zscalar_t [nLocalRows];
237  for (zlno_t j=0; j < nLocalRows; j++){
238  rowWeights[i][j] = 200000*i + j;
239  }
240  }
241  }
242  }
243 
244  if (nEdgeWeights > 0 && rank == 0){
245  std::cout << "TODO: STILL NEED TO TEST EDGE WEIGHTS!" << std::endl;
246  }
247 
248  // Create a matrix or graph input adapter.
249 
250  Adapter tmi(M, nVtxWeights);
251 
252  for (int i=0; i < nVtxWeights; i++){
253  if (nnzWgtIdx == i)
254  tmi.setWeightIsDegree(i);
255  else
256  tmi.setWeights(rowWeights[i], 1, i);
257  }
258 
259  zgno_t *gids = NULL;
260 
261  simpleVAdapter_t *via = NULL;
262 
263  if (coordDim > 0) {
264  gids = new zgno_t[nLocalRows];
265  for (zlno_t i = 0; i < nLocalRows; i++)
266  gids[i] = M->getRowMap()->getGlobalElement(i);
267  via = new simpleVAdapter_t(nLocalRows, gids, coords[0],
268  (coordDim > 1 ? coords[1] : NULL),
269  (coordDim > 2 ? coords[2] : NULL),
270  1,1,1);
271  tmi.setCoordinateInput(via);
272  }
273 
274  size_t numLocalDiags = 0;
275  size_t numGlobalDiags = 0;
276  if (removeSelfEdges) {
277  computeNumDiags<MatrixOrGraph>(M, numLocalDiags, numGlobalDiags);
278  }
279 
280  const RCP<const tmap_t> rowMap = M->getRowMap();
281  const RCP<const tmap_t> colMap = M->getColMap();
282 
283  // How many neighbor vertices are not on my process.
284 
285  int *numNbors = new int [nLocalRows];
286  int *numLocalNbors = new int [nLocalRows];
287  bool *haveDiag = new bool [nLocalRows];
288  size_t totalLocalNbors = 0;
289 
290  for (zlno_t i=0; i < nLocalRows; i++){
291  numLocalNbors[i] = 0;
292  haveDiag[i] = false;
293 
294  typename Tpetra::CrsGraph<zlno_t, zgno_t>::local_inds_host_view_type idx;
295  Mgraph->getLocalRowView(i, idx);
296  numNbors[i] = idx.extent(0);
297 
298  for (std::size_t j=0; j < idx.size(); j++){
299  if (idx[j] == i){
300  haveDiag[i] = true;
301  numLocalNbors[i]++;
302  totalLocalNbors++;
303  }
304  else{
305  zgno_t gidVal = colMap->getGlobalElement(idx[j]);
306  if (rowMap->getLocalElement(gidVal) !=
307  Teuchos::OrdinalTraits<zlno_t>::invalid()) {
308  // nbor is local to this process
309  numLocalNbors[i]++;
310  totalLocalNbors++;
311  }
312  }
313  }
314  }
315 
316  // Create a GraphModel based on this input data.
317 
318  if (rank == 0) std::cout << " Creating GraphModel" << std::endl;
319  Zoltan2::GraphModel<BaseAdapter> *model = NULL;
320  RCP<const BaseAdapter> baseTmi = rcp(dynamic_cast<BaseAdapter *>(&tmi),false);
321 
322  try{
323  model = new Zoltan2::GraphModel<BaseAdapter>(baseTmi, env,
324  comm, modelFlags);
325  }
326  catch (std::exception &e){
327  std::cerr << rank << ") " << e.what() << std::endl;
328  fail = 1;
329  }
330  TEST_FAIL_AND_EXIT(*comm, !fail, "Creating graph model", 1)
331 
332  // Test the GraphModel interface
333 
334  if (rank == 0) std::cout << " Checking counts" << std::endl;
335  if (model->getLocalNumVertices() != size_t(nLocalRows)) fail = 1;
336  TEST_FAIL_AND_EXIT(*comm, !fail, "getLocalNumVertices", 1)
337 
338  if (buildLocalGraph) {
339  if (model->getLocalNumVertices() != size_t(nLocalRows)) fail = 1;
340  TEST_FAIL_AND_EXIT(*comm, !fail, "getGlobalNumVertices", 1)
341 
342  size_t num = (removeSelfEdges ? totalLocalNbors - numLocalDiags
343  : totalLocalNbors);
344  if (model->getLocalNumEdges() != num) fail = 1;
345  TEST_FAIL_AND_EXIT(*comm, !fail, "getLocalNumEdges", 1)
346 
347  if (model->getGlobalNumEdges() != num) fail = 1;
348  TEST_FAIL_AND_EXIT(*comm, !fail, "getGlobalNumEdges", 1)
349  }
350  else {
351  if (model->getGlobalNumVertices() != size_t(nGlobalRows)) fail = 1;
352  TEST_FAIL_AND_EXIT(*comm, !fail, "getGlobalNumVertices", 1)
353 
354  size_t num = (removeSelfEdges ? nLocalNZ-numLocalDiags : nLocalNZ);
355  if (model->getLocalNumEdges() != num) fail = 1;
356  TEST_FAIL_AND_EXIT(*comm, !fail, "getLocalNumEdges", 1)
357 
358  num = (removeSelfEdges ? (nGlobalNZ-numGlobalDiags) : nGlobalNZ);
359  if (model->getGlobalNumEdges() != num) fail = 1;
360  TEST_FAIL_AND_EXIT(*comm, !fail, "getGlobalNumEdges", 1)
361  }
362 
363  if (model->getNumWeightsPerVertex() != nVtxWeights) fail = 1;
364  TEST_FAIL_AND_EXIT(*comm, !fail, "getNumWeightsPerVertex", 1)
365 
366  if (model->getNumWeightsPerEdge() != 0) fail = 1;
367  TEST_FAIL_AND_EXIT(*comm, !fail, "getNumWeightsPerEdge", 1)
368 
369  if (model->getCoordinateDim() != coordDim) fail = 1;
370  TEST_FAIL_AND_EXIT(*comm, !fail, "getCoordinateDim", 1)
371 
372 
373  if (rank == 0) std::cout << " Checking vertices" << std::endl;
374  ArrayView<const zgno_t> vertexGids;
375  ArrayView<input_t> crds;
376  ArrayView<input_t> wgts;
377 
378  try{
379  model->getVertexList(vertexGids, wgts);
380  if (coordDim) model->getVertexCoords(crds);
381  }
382  catch (std::exception &e){
383  std::cerr << rank << ") Error " << e.what() << std::endl;
384  fail = 1;
385  }
386  TEST_FAIL_AND_EXIT(*comm, !fail, "getVertexList", 1)
387 
388  if (vertexGids.size() != nLocalRows) fail = 1;
389  TEST_FAIL_AND_EXIT(*comm, !fail, "getVertexList size", 1)
390 
391  if (buildLocalGraph) {
392  // For local graph, vertexGIDs are 0 to n-1, where n = nLocalRows
393  for (zlno_t i = 0; i < nLocalRows; i++) {
394  if (vertexGids[i] != i) {
395  fail = 1;
396  break;
397  }
398  }
399  }
400  else {
401  // We know model stores things in same order we gave it.
402  if (idsAreConsecutive){
403  zgno_t minLocalGID = rowMap->getMinGlobalIndex();
404  for (zlno_t i=0; i < nLocalRows; i++){
405  if (vertexGids[i] != minLocalGID + i) {
406  fail = 1;
407  break;
408  }
409  }
410  }
411  else{ // round robin ids
412  if (consecutiveIdsRequested) {
413  zgno_t myFirstRow;
414  zgno_t tnLocalRows = nLocalRows;
415  scan(*comm, Teuchos::REDUCE_SUM, 1, &tnLocalRows, &myFirstRow);
416  myFirstRow -= nLocalRows;
417  for (zlno_t i=0; i < nLocalRows; i++){
418  if (vertexGids[i] != myFirstRow+i){
419  std::cout << rank << " Row " << i << " of " << nLocalRows
420  << " myFirstRow+i " << myFirstRow+i
421  << " vertexGids " << vertexGids[i]
422  << std::endl;
423  fail = 1;
424  break;
425  }
426  }
427  }
428  else {
429  zgno_t myGid = rank;
430  for (zlno_t i=0; i < nLocalRows; i++, myGid += nprocs){
431  if (vertexGids[i] != myGid){
432  std::cout << rank << " Row " << i << " of " << nLocalRows
433  << " myGid " << myGid << " vertexGids " << vertexGids[i]
434  << std::endl;
435  fail = 1;
436  break;
437  }
438  }
439  }
440  }
441  }
442  TEST_FAIL_AND_EXIT(*comm, !fail, "vertex gids", 1)
443 
444 
445  if ((crds.size() != coordDim) || (wgts.size() != nVtxWeights)) fail = 1;
446  TEST_FAIL_AND_EXIT(*comm, !fail, "coord or weight array size", 1)
447 
448  for (int i=0; !fail && i < coordDim; i++){
449  for (zlno_t j=0; j < nLocalRows; j++){
450  if (crds[i][j] != 100000*i + j){
451  fail = 1;
452  break;
453  }
454  }
455  }
456  TEST_FAIL_AND_EXIT(*comm, !fail, "coord values", 1)
457 
458  for (int i=0; !fail && i < nVtxWeights; i++){
459  if (nnzWgtIdx == i){
460  for (zlno_t j=0; j < nLocalRows; j++){
461  zscalar_t val = (buildLocalGraph ? numLocalNbors[j] : numNbors[j]);
462  if (removeSelfEdges && haveDiag[j])
463  val -= 1;
464  if (wgts[i][j] != val){
465  fail = 1;
466  break;
467  }
468  }
469  }
470  else{
471  for (zlno_t j=0; j < nLocalRows; j++){
472  if (wgts[i][j] != 200000*i + j){
473  fail = 1;
474  break;
475  }
476  }
477  }
478  }
479 
480  TEST_FAIL_AND_EXIT(*comm, !fail, "row weight values", 1)
481 
482 
483  if (rank == 0) std::cout << " Checking edges" << std::endl;
484 
485  if (!buildLocalGraph) {
486  ArrayView<const zgno_t> edgeGids;
487  ArrayView<const offset_t> offsets;
488  size_t numEdges=0;
489 
490  try{
491  numEdges = model->getEdgeList(edgeGids, offsets, wgts);
492  }
493  catch(std::exception &e){
494  std::cerr << rank << ") Error " << e.what() << std::endl;
495  fail = 1;
496  }
497  TEST_FAIL_AND_EXIT(*comm, !fail, "getEdgeList", 1)
498 
499  TEST_FAIL_AND_EXIT(*comm, wgts.size() == 0, "edge weights present", 1)
500 
501  size_t num = 0;
502  for (typename ArrayView<const offset_t>::size_type i=0;
503  i < offsets.size()-1; i++){
504  offset_t edgeListSize = offsets[i+1] - offsets[i];
505  num += edgeListSize;
506  size_t val = numNbors[i];
507  if (removeSelfEdges && haveDiag[i])
508  val--;
509  if (edgeListSize != val){
510  fail = 1;
511  break;
512  }
513  }
514 
515  TEST_FAIL_AND_EXIT(*comm, numEdges==num, "getEdgeList size", 1)
516  if (nGlobalRows < SMALL_NUMBER_OF_ROWS){
517  if (rank == 0)
518  std::cout << "Printing graph now " << nGlobalRows << std::endl;
519  printGraph<offset_t>(nLocalRows, vertexGids.getRawPtr(), NULL,
520  edgeGids.getRawPtr(), offsets.getRawPtr(), comm);
521  }
522  else{
523  if (rank==0)
524  std::cout << " " << nGlobalRows << " total rows" << std::endl;
525  }
526  }
527 
528  else { // buildLocalGraph
529  // Get graph restricted to this process
530 
531  if (rank == 0) std::cout << " Checking local edges" << std::endl;
532  ArrayView<const zgno_t> localEdges;
533  ArrayView<const offset_t> localOffsets;
534  size_t numLocalNeighbors=0;
535 
536  try{
537  numLocalNeighbors= model->getEdgeList(localEdges, localOffsets, wgts);
538  }
539  catch(std::exception &e){
540  std::cout << rank << ") Error " << e.what() << std::endl;
541  std::cerr << rank << ") Error " << e.what() << std::endl;
542  fail = 1;
543  }
544  TEST_FAIL_AND_EXIT(*comm, !fail, "getLocalEdgeList", 1)
545  TEST_FAIL_AND_EXIT(*comm, ((localOffsets.size()-1) == nLocalRows),
546  "getLocalEdgeList localOffsets.size", 1)
547 
548  size_t num = 0;
549  for (zlno_t i=0; i < nLocalRows; i++){
550  offset_t edgeListSize = localOffsets[i+1] - localOffsets[i];
551  num += edgeListSize;
552  size_t val = numLocalNbors[i];
553  if (removeSelfEdges && haveDiag[i])
554  val--;
555  if (edgeListSize != val){
556  std::cout << rank << "vtx " << i << " of " << localOffsets.size()
557  << " Number of local edges in model " << edgeListSize
558  << " not equal to expected number of edges " << val
559  << std::endl;
560  fail = 1;
561  break;
562  }
563  }
564  TEST_FAIL_AND_EXIT(*comm, !fail, "getLocalEdgeList list sizes", 1)
565 
566  TEST_FAIL_AND_EXIT(*comm, numLocalNeighbors==num,
567  "getLocalEdgeList sum size", 1)
568 
569  fail = ((removeSelfEdges ? totalLocalNbors-numLocalDiags
570  : totalLocalNbors)
571  != numLocalNeighbors);
572  TEST_FAIL_AND_EXIT(*comm, !fail, "getLocalEdgeList total size", 1)
573 
574  if (nGlobalRows < SMALL_NUMBER_OF_ROWS){
575  if (totalLocalNbors == 0){
576  if (rank == 0)
577  std::cout << " Graph of local edges is empty" << std::endl;
578  }
579  else{
580  printGraph<offset_t>(nLocalRows, vertexGids.getRawPtr(),
581  localEdges.getRawPtr(), NULL, localOffsets.getRawPtr(), comm);
582  }
583  }
584  }
585 
586  if (rank == 0) std::cout << " Cleaning up" << std::endl;
587  delete model;
588 
589  if (nLocalRows){
590  delete [] numNbors;
591  delete [] numLocalNbors;
592  delete [] haveDiag;
593 
594  if (nVtxWeights > 0){
595  for (int i=0; i < nVtxWeights; i++){
596  if (rowWeights[i])
597  delete [] rowWeights[i];
598  }
599  delete [] rowWeights;
600  }
601 
602  if (coordDim > 0){
603  delete via;
604  delete [] gids;
605  for (int i=0; i < coordDim; i++){
606  if (coords[i])
607  delete [] coords[i];
608  }
609  delete [] coords;
610  }
611  }
612 
613  if (rank==0) std::cout << " OK" << std::endl;
614 }
615 
617 void testGraphModel(string fname, zgno_t xdim, zgno_t ydim, zgno_t zdim,
618  const RCP<const Comm<int> > &comm,
619  int nVtxWeights, int nnzWgtIdx, int coordDim,
620  bool consecutiveIdsRequested, bool removeSelfEdges, bool buildLocalGraph)
621 {
622  int rank = comm->getRank();
623 
624  if (rank==0){
625  std::cout << std::endl << "=======================" << std::endl;
626  if (fname.size() > 0)
627  std::cout << std::endl << "Test parameters: file name " << fname << std::endl;
628  else{
629  std::cout << std::endl << "Test parameters: dimension ";
630  std::cout << xdim << "x" << ydim << "x" << zdim << std::endl;
631  }
632 
633  std::cout << "Num Vertex Weights: " << nVtxWeights << std::endl;
634  if (nnzWgtIdx >= 0)
635  std::cout << " Dimension " << nnzWgtIdx << " is number of neighbors" << std::endl;
636 
637  std::cout << "Coordinate dim: " << coordDim << std::endl;
638  std::cout << "Request consecutive vertex gids: ";
639  std::cout << (consecutiveIdsRequested ? "yes" : "no") << std::endl;
640  std::cout << "Request to remove self edges: ";
641  std::cout << (removeSelfEdges ? "yes" : "no") << std::endl;
642  }
643 
644  // Input generator
645  UserInputForTests *uinput;
646 
647  if (fname.size() > 0)
648  uinput = new UserInputForTests(testDataFilePath, fname, comm, true);
649  else
650  uinput = new UserInputForTests(xdim,ydim,zdim,string(""), comm, true, true);
651 
652  RCP<tcrsMatrix_t> M = uinput->getUITpetraCrsMatrix();
653 
654  // Row Ids of test input are already consecutive
655 
656  RCP<const tcrsMatrix_t> Mconsec = rcp_const_cast<const tcrsMatrix_t>(M);
657 
658  RCP<const Tpetra::CrsGraph<zlno_t, zgno_t> > graph = Mconsec->getCrsGraph();
659 
660 // printTpetraGraph<zlno_t, zgno_t>(comm, *graph, std::cout, 100,
661 // "Graph having consecutive IDs");
662 
663  if (rank == 0)
664  std::cout << " TEST MatrixAdapter for graph having Consecutive IDs"
665  << std::endl;
666  bool idsAreConsecutive = true;
667 
668  testAdapter<baseMAdapter_t,xMAdapter_t,tcrsMatrix_t>(Mconsec, graph, comm,
669  idsAreConsecutive,
670  nVtxWeights, 0,
671  nnzWgtIdx, coordDim,
672  consecutiveIdsRequested,
673  removeSelfEdges,
674  buildLocalGraph);
675 
676  if (rank == 0)
677  std::cout << " TEST GraphAdapter for graph having Consecutive IDs"
678  << std::endl;
679  testAdapter<baseGAdapter_t,xGAdapter_t,tcrsGraph_t>(graph, graph, comm,
680  idsAreConsecutive,
681  nVtxWeights, 1,
682  nnzWgtIdx, coordDim,
683  consecutiveIdsRequested,
684  removeSelfEdges,
685  buildLocalGraph);
686 
687  // Do a round robin migration so that global IDs are not consecutive.
688 
689  Array<zgno_t> myNewRows;
690  int nprocs = comm->getSize();
691  for (size_t i=rank; i < Mconsec->getGlobalNumRows(); i+=nprocs)
692  myNewRows.push_back(i);
693 
694  RCP<const tcrsMatrix_t> Mnonconsec = rcp_const_cast<const tcrsMatrix_t>(
696  *Mconsec, myNewRows.size(), myNewRows.getRawPtr()));
697 
698  graph = Mnonconsec->getCrsGraph();
699 
700 // printTpetraGraph<zlno_t, zgno_t>(comm, *graph, std::cout, 100,
701 // "Graph having non-consecutive (Round-Robin) IDs");
702 
703  if (rank == 0)
704  std::cout << " TEST MatrixAdapter graph having Round-Robin IDs"
705  << std::endl;
706  idsAreConsecutive = false;
707 
708  testAdapter<baseMAdapter_t,xMAdapter_t,tcrsMatrix_t>(Mnonconsec, graph, comm,
709  idsAreConsecutive,
710  nVtxWeights, 0,
711  nnzWgtIdx, coordDim,
712  consecutiveIdsRequested,
713  removeSelfEdges,
714  buildLocalGraph);
715 
716  if (rank == 0)
717  std::cout << " TEST GraphAdapter graph having Round-Robin IDs"
718  << std::endl;
719  testAdapter<baseGAdapter_t,xGAdapter_t,tcrsGraph_t>(graph, graph, comm,
720  idsAreConsecutive,
721  nVtxWeights, 0,
722  nnzWgtIdx, coordDim,
723  consecutiveIdsRequested,
724  removeSelfEdges,
725  buildLocalGraph);
726 
727  delete uinput;
728 }
729 
731 int main(int narg, char *arg[])
732 {
733  Tpetra::ScopeGuard tscope(&narg, &arg);
734  Teuchos::RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
735 
736  int rank = comm->getRank();
737 
738  int nVtxWeights=0;
739  int nnzWgtIdx = -1;
740  int coordDim=0;
741  bool consecutiveIdsRequested = false;
742  bool removeSelfEdges = false;
743  bool buildLocalGraph = false;
744  string fname("simple");
745 
746  if (rank == 0)
747  std::cout << "TESTING base case (global)" << std::endl;
748  testGraphModel(fname, 0, 0, 0, comm,
749  nVtxWeights, nnzWgtIdx, coordDim,
750  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
751 
752  if (rank == 0)
753  std::cout << "TESTING with row weights (global)" << std::endl;
754  nVtxWeights = 1;
755  testGraphModel(fname, 0, 0, 0, comm,
756  nVtxWeights, nnzWgtIdx, coordDim,
757  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
758 
759  if (rank == 0)
760  std::cout << "TESTING with weights = nnz (global)" << std::endl;
761  nnzWgtIdx = 1;
762  testGraphModel(fname, 0, 0, 0, comm,
763  nVtxWeights, nnzWgtIdx, coordDim,
764  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
765 
766  if (rank == 0)
767  std::cout << "TESTING with multiple row weights and coords (global)"
768  << std::endl;
769  nVtxWeights = 2;
770  coordDim = 3;
771  testGraphModel(fname, 0, 0, 0, comm,
772  nVtxWeights, nnzWgtIdx, coordDim,
773  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
774 
775  if (rank == 0)
776  std::cout << "TESTING with consecutiveIdsRequested (global)" << std::endl;
777  consecutiveIdsRequested = true;
778  testGraphModel(fname, 0, 0, 0, comm,
779  nVtxWeights, nnzWgtIdx, coordDim,
780  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
781 
782  if (rank == 0)
783  std::cout << "TESTING with consecutiveIdsRequested and removeSelfEdges "
784  << "(global)" << std::endl;
785  removeSelfEdges = true;
786  testGraphModel(fname, 0, 0, 0, comm,
787  nVtxWeights, nnzWgtIdx, coordDim,
788  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
789 
790  if (rank == 0)
791  std::cout << "TESTING with removeSelfEdges (global)" << std::endl;
792  consecutiveIdsRequested = false;
793  testGraphModel(fname, 0, 0, 0, comm,
794  nVtxWeights, nnzWgtIdx, coordDim,
795  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
796 
797  if (rank == 0)
798  std::cout << "TESTING base case (local)" << std::endl;
799  buildLocalGraph = true;
800  consecutiveIdsRequested = false;
801  removeSelfEdges = false;
802  testGraphModel(fname, 0, 0, 0, comm,
803  nVtxWeights, nnzWgtIdx, coordDim,
804  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
805 
806  if (rank == 0)
807  std::cout << "TESTING with row weights (local)" << std::endl;
808  nVtxWeights = 1;
809  testGraphModel(fname, 0, 0, 0, comm,
810  nVtxWeights, nnzWgtIdx, coordDim,
811  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
812 
813  if (rank == 0)
814  std::cout << "TESTING with weights = nnz (local)" << std::endl;
815  nnzWgtIdx = 1;
816  testGraphModel(fname, 0, 0, 0, comm,
817  nVtxWeights, nnzWgtIdx, coordDim,
818  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
819 
820  if (rank == 0)
821  std::cout << "TESTING with multiple row weights and coords (local)"
822  << std::endl;
823  nVtxWeights = 2;
824  coordDim = 3;
825  testGraphModel(fname, 0, 0, 0, comm,
826  nVtxWeights, nnzWgtIdx, coordDim,
827  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
828 
829  if (rank == 0)
830  std::cout << "TESTING with consecutiveIdsRequested (local)" << std::endl;
831  consecutiveIdsRequested = true;
832  testGraphModel(fname, 0, 0, 0, comm,
833  nVtxWeights, nnzWgtIdx, coordDim,
834  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
835 
836  if (rank == 0)
837  std::cout << "TESTING with consecutiveIdsRequested and removeSelfEdges"
838  << "(local)"
839  << std::endl;
840  removeSelfEdges = true;
841  testGraphModel(fname, 0, 0, 0, comm,
842  nVtxWeights, nnzWgtIdx, coordDim,
843  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
844 
845  if (rank == 0)
846  std::cout << "TESTING with removeSelfEdges (local)" << std::endl;
847  consecutiveIdsRequested = false;
848  testGraphModel(fname, 0, 0, 0, comm,
849  nVtxWeights, nnzWgtIdx, coordDim,
850  consecutiveIdsRequested, removeSelfEdges, buildLocalGraph);
851  if (rank==0)
852  std::cout << "PASS" << std::endl;
853 
854  return 0;
855 }
856 
size_t getLocalNumEdges() const
Returns the number of edges on this process. In global or subset graphs, includes off-process edges...
Zoltan2::GraphAdapter< tcrsGraph_t, simpleUser_t > baseGAdapter_t
Definition: GraphModel.cpp:89
size_t getVertexList(ArrayView< const gno_t > &Ids, ArrayView< input_t > &wgts) const
Sets pointers to this process&#39; vertex Ids and their weights.
int getNumWeightsPerVertex() const
Returns the number (0 or greater) of weights per vertex.
void testAdapter(RCP< const MatrixOrGraph > &M, RCP< const Tpetra::CrsGraph< zlno_t, zgno_t > > &Mgraph, const RCP< const Comm< int > > &comm, bool idsAreConsecutive, int nVtxWeights, int nEdgeWeights, int nnzWgtIdx, int coordDim, bool consecutiveIdsRequested, bool removeSelfEdges, bool buildLocalGraph)
Definition: GraphModel.cpp:186
MatrixAdapter defines the adapter interface for matrices.
RCP< tcrsMatrix_t > getUITpetraCrsMatrix()
void computeNumDiags< tcrsMatrix_t >(RCP< const tcrsMatrix_t > &M, size_t &numLocalDiags, size_t &numGlobalDiags)
Definition: GraphModel.cpp:173
Provides access for Zoltan2 to Xpetra::CrsMatrix data.
GraphAdapter defines the interface for graph-based user data.
algorithm requires consecutive ids
void computeNumDiags< tcrsGraph_t >(RCP< const tcrsGraph_t > &M, size_t &numLocalDiags, size_t &numGlobalDiags)
Definition: GraphModel.cpp:141
default_offset_t offset_t
The data type to represent offsets.
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:18
#define TEST_FAIL_AND_EXIT(comm, ok, s, code)
static RCP< User > doMigration(const User &from, size_t numLocalRows, const gno_t *myNewRows)
Migrate the object Given a user object and a new row distribution, create and return a new user objec...
Provides access for Zoltan2 to Xpetra::CrsGraph data.
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > simpleUser_t
int main(int narg, char **arg)
Definition: coloring1.cpp:199
common code used by tests
size_t getGlobalNumVertices() const
Returns the global number vertices.
void printGraph(RCP< const Comm< int > > &comm, zlno_t nvtx, const zgno_t *vtxIds, const offset_t *offsets, const zgno_t *edgeIds)
void computeNumDiags(RCP< const MatrixOrGraph > &M, size_t &numLocalDiags, size_t &numGlobalDiags)
Definition: GraphModel.cpp:131
Zoltan2::XpetraCrsGraphAdapter< tcrsGraph_t, simpleUser_t > xGAdapter_t
Definition: GraphModel.cpp:92
Defines XpetraCrsGraphAdapter class.
void testGraphModel(string fname, zgno_t xdim, zgno_t ydim, zgno_t zdim, const RCP< const Comm< int > > &comm, int nVtxWeights, int nnzWgtIdx, int coordDim, bool consecutiveIdsRequested, bool removeSelfEdges, bool buildLocalGraph)
Definition: GraphModel.cpp:617
list fname
Begin.
Definition: validXML.py:19
algorithm requires no self edges
Defines the XpetraCrsMatrixAdapter class.
int getCoordinateDim() const
Returns the dimension (0 to 3) of vertex coordinates.
Zoltan2::BasicVectorAdapter< simpleUser_t > simpleVAdapter_t
size_t getVertexCoords(ArrayView< input_t > &xyz) const
Sets pointers to this process&#39; vertex coordinates, if available. Order of coordinate info matches tha...
size_t getEdgeList(ArrayView< const gno_t > &edgeIds, ArrayView< const offset_t > &offsets, ArrayView< input_t > &wgts) const
Sets pointers to this process&#39; edge (neighbor) global Ids, including off-process edges.
size_t getGlobalNumEdges() const
Returns the global number edges. For local graphs, the number of global edges is the number of local ...
The StridedData class manages lists of weights or coordinates.
Zoltan2::MatrixAdapter< tcrsMatrix_t, simpleUser_t > baseMAdapter_t
BasicVectorAdapter represents a vector (plus optional weights) supplied by the user as pointers to st...
Traits for application input objects.
The user parameters, debug, timing and memory profiling output objects, and error checking methods...
const int SMALL_NUMBER_OF_ROWS
Test of GraphModel interface.
Definition: GraphModel.cpp:74
size_t getLocalNumVertices() const
Returns the number vertices on this process.
Tpetra::Map::local_ordinal_type zlno_t
static const std::string fail
Tpetra::CrsMatrix< zscalar_t, zlno_t, zgno_t, znode_t > tcrsMatrix_t
Tpetra::Map< zlno_t, zgno_t, znode_t > tmap_t
Tpetra::CrsGraph< zlno_t, zgno_t, znode_t > tcrsGraph_t
GraphModel defines the interface required for graph models.
int getNumWeightsPerEdge() const
Returns the number (0 or greater) of weights per edge.
Defines the GraphModel interface.
Zoltan2::XpetraCrsMatrixAdapter< tcrsMatrix_t, simpleUser_t > xMAdapter_t
Definition: GraphModel.cpp:91
float zscalar_t
Defines the BasicVectorAdapter class.
model represents graph within only one rank
Tpetra::Map::global_ordinal_type zgno_t
std::string testDataFilePath(".")