Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
graph.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 <iostream>
11 #include <limits>
15 #include <Teuchos_ParameterList.hpp>
16 #include <Teuchos_RCP.hpp>
17 #include <Teuchos_CommandLineProcessor.hpp>
18 #include <Tpetra_CrsMatrix.hpp>
19 #include <Tpetra_Vector.hpp>
20 #include <Galeri_XpetraMaps.hpp>
21 #include <Galeri_XpetraProblemFactory.hpp>
22 
23 using Teuchos::RCP;
24 
26 // Program to demonstrate use of Zoltan2 to partition a TPetra matrix
27 // using graph partitioning via Scotch or ParMETIS.
29 
30 int main(int narg, char** arg)
31 {
32  // Establish session; works both for MPI and non-MPI builds
33  Tpetra::ScopeGuard tscope(&narg, &arg);
34  Teuchos::RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
35  int me = comm->getRank();
36 
37  // Useful typedefs: Tpetra types
38  // In this example, we'll use Tpetra defaults for local/global ID type
39  typedef Tpetra::Map<> Map_t;
40  typedef Map_t::local_ordinal_type localId_t;
41  typedef Map_t::global_ordinal_type globalId_t;
42  typedef Tpetra::Details::DefaultTypes::scalar_type scalar_t;
43  typedef Tpetra::CrsMatrix<scalar_t, localId_t, globalId_t> Matrix_t;
44  typedef Tpetra::MultiVector<scalar_t, localId_t, globalId_t> MultiVector_t;
45  typedef Tpetra::Vector<scalar_t, localId_t, globalId_t> Vector_t;
46 
47  // Useful typedefs: Zoltan2 types
48  typedef Zoltan2::XpetraCrsMatrixAdapter<Matrix_t> MatrixAdapter_t;
50 
51  // Input parameters with default values
52  std::string method = "scotch"; // Partitioning method
53  globalId_t nx = 50, ny = 40, nz = 30; // Dimensions of mesh corresponding to
54  // the matrix to be partitioned
55 
56  // Read run-time options.
57  Teuchos::CommandLineProcessor cmdp (false, false);
58  cmdp.setOption("method", &method,
59  "Partitioning method to use: scotch or parmetis.");
60  cmdp.setOption("nx", &nx,
61  "number of gridpoints in X dimension for "
62  "mesh used to generate matrix; must be >= 1.");
63  cmdp.setOption("ny", &ny,
64  "number of gridpoints in Y dimension for "
65  "mesh used to generate matrix; must be >= 1.");
66  cmdp.setOption("nz", &nz,
67  "number of gridpoints in Z dimension for "
68  "mesh used to generate matrix; must be >= 1.");
69  cmdp.parse(narg, arg);
70 
71  if ((nx < 1) || (ny < 1) || (nz < 1)) {
72  std::cout << "Input error: nx, ny and nz must be >= 1" << std::endl;
73  return -1;
74  }
75 
76  // For this example, generate a matrix using Galeri with the
77  // default Tpetra distribution:
78  // Laplace3D matrix corresponding to mesh with dimensions (nx X ny X nz)
79  // with block row-based distribution
80  Teuchos::ParameterList galeriList;
81  galeriList.set("nx", nx);
82  galeriList.set("ny", ny);
83  galeriList.set("nz", nz);
84  Tpetra::global_size_t nGlobalElements = nx * ny * nz;
85 
86  RCP<Matrix_t> origMatrix;
87 
88  try {
89  RCP<const Map_t> map = rcp(new Map_t(nGlobalElements, 0, comm));
90 
91  typedef Galeri::Xpetra::Problem<Map_t,Matrix_t,MultiVector_t> Galeri_t;
92  RCP<Galeri_t> galeriProblem =
93  Galeri::Xpetra::BuildProblem<scalar_t, localId_t, globalId_t,
94  Map_t, Matrix_t, MultiVector_t>
95  ("Laplace3D", map, galeriList);
96  origMatrix = galeriProblem->BuildMatrix();
97  }
98  catch (std::exception &e) {
99  std::cout << "Exception in Galeri matrix generation. " << e.what() << std::endl;
100  return -1;
101  }
102 
103  if (me == 0)
104  std::cout << "NumRows = " << origMatrix->getGlobalNumRows() << std::endl
105  << "NumNonzeros = " << origMatrix->getGlobalNumEntries() << std::endl
106  << "NumProcs = " << comm->getSize() << std::endl;
107 
108  // Create vectors to use with the matrix for sparse matvec.
109  RCP<Vector_t> origVector, origProd;
110  origProd = Tpetra::createVector<scalar_t,localId_t,globalId_t>(
111  origMatrix->getRangeMap());
112  origVector = Tpetra::createVector<scalar_t,localId_t,globalId_t>(
113  origMatrix->getDomainMap());
114  origVector->randomize();
115 
116  // Specify partitioning parameters
117  Teuchos::ParameterList param;
118  param.set("partitioning_approach", "partition");
119  param.set("algorithm", method);
120 
121  // Create an input adapter for the Tpetra matrix.
122  MatrixAdapter_t adapter(origMatrix);
123 
124  // Create and solve partitioning problem
125  Zoltan2::PartitioningProblem<MatrixAdapter_t> problem(&adapter, &param);
126 
127  try {
128  problem.solve();
129  }
130  catch (std::exception &e) {
131  std::cout << "Exception returned from solve(). " << e.what() << std::endl;
132  return -1;
133  }
134 
135  // Redistribute matrix and vector into new matrix and vector.
136  // Can use PartitioningSolution from matrix to redistribute the vectors, too.
137 
138  if (me == 0) std::cout << "Redistributing matrix..." << std::endl;
139  RCP<Matrix_t> redistribMatrix;
140  adapter.applyPartitioningSolution(*origMatrix, redistribMatrix,
141  problem.getSolution());
142 
143  if (me == 0) std::cout << "Redistributing vectors..." << std::endl;
144  RCP<Vector_t> redistribVector;
145  MultiVectorAdapter_t adapterVector(origVector);
146  adapterVector.applyPartitioningSolution(*origVector, redistribVector,
147  problem.getSolution());
148 
149  // Create a new product vector for sparse matvec
150  RCP<Vector_t> redistribProd;
151  redistribProd = Tpetra::createVector<scalar_t,localId_t,globalId_t>(
152  redistribMatrix->getRangeMap());
153 
154  // SANITY CHECK
155  // A little output for small problems
156  if (origMatrix->getGlobalNumRows() <= 50) {
157  std::cout << me << " ORIGINAL: ";
158  for (size_t i = 0; i < origVector->getLocalLength(); i++)
159  std::cout << origVector->getMap()->getGlobalElement(i) << " ";
160  std::cout << std::endl;
161  std::cout << me << " REDISTRIB: ";
162  for (size_t i = 0; i < redistribVector->getLocalLength(); i++)
163  std::cout << redistribVector->getMap()->getGlobalElement(i) << " ";
164  std::cout << std::endl;
165  }
166 
167  // SANITY CHECK
168  // check that redistribution is "correct"; perform matvec with
169  // original and redistributed matrices/vectors and compare norms.
170 
171  if (me == 0) std::cout << "Matvec original..." << std::endl;
172  origMatrix->apply(*origVector, *origProd);
173  scalar_t origNorm = origProd->norm2();
174  if (me == 0)
175  std::cout << "Norm of Original matvec prod: " << origNorm << std::endl;
176 
177  if (me == 0) std::cout << "Matvec redistributed..." << std::endl;
178  redistribMatrix->apply(*redistribVector, *redistribProd);
179  scalar_t redistribNorm = redistribProd->norm2();
180  if (me == 0)
181  std::cout << "Norm of Redistributed matvec prod: " << redistribNorm << std::endl;
182 
183  if (me == 0) {
184  const scalar_t epsilon = 0.001;
185  if (redistribNorm > origNorm+epsilon || redistribNorm < origNorm-epsilon)
186  std::cout << "Mat-Vec product changed; FAIL" << std::endl;
187  else
188  std::cout << "PASS" << std::endl;
189  }
190 
191  return 0;
192 }
Provides access for Zoltan2 to Xpetra::CrsMatrix data.
int main(int narg, char **arg)
Definition: coloring1.cpp:164
Defines the XpetraMultiVectorAdapter.
#define epsilon
Definition: nd.cpp:47
Defines the XpetraCrsMatrixAdapter class.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
Zoltan2::XpetraMultiVectorAdapter< tMVector_t > MultiVectorAdapter_t
Definition: nd.cpp:45
An adapter for Xpetra::MultiVector.
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
PartitioningProblem sets up partitioning problems for the user.
Tpetra::global_size_t global_size_t
Defines the PartitioningProblem class.
void solve(bool updateInputData=true)
Direct the problem to create a solution.