Zoltan2
graph.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 #include <iostream>
46 #include <limits>
50 #include <Teuchos_ParameterList.hpp>
51 #include <Teuchos_RCP.hpp>
52 #include <Teuchos_CommandLineProcessor.hpp>
53 #include <Tpetra_DefaultPlatform.hpp>
54 #include <Tpetra_CrsMatrix.hpp>
55 #include <Tpetra_Vector.hpp>
56 #include <Galeri_XpetraMaps.hpp>
57 #include <Galeri_XpetraProblemFactory.hpp>
58 
59 using Teuchos::RCP;
60 using namespace std;
61 
63 // Program to demonstrate use of Zoltan2 to partition a TPetra matrix
64 // using graph partitioning via Scotch or ParMETIS.
66 
67 int main(int narg, char** arg)
68 {
69  // Establish session; works both for MPI and non-MPI builds
70  Teuchos::GlobalMPISession mpiSession(&narg, &arg, NULL);
71  RCP<const Teuchos::Comm<int> > comm =
72  Tpetra::DefaultPlatform::getDefaultPlatform().getComm();
73  int me = comm->getRank();
74 
75  // Useful typedefs: basic types
76  typedef int zlno_t;
77  typedef int zgno_t;
78  typedef double zscalar_t;
79 
80  // Useful typedefs: Tpetra types
81  typedef Tpetra::Map<zlno_t, zgno_t> Map_t;
82  typedef Tpetra::CrsMatrix<zscalar_t, zlno_t, zgno_t> Matrix_t;
83  typedef Tpetra::MultiVector<zscalar_t, zlno_t, zgno_t> MultiVector_t;
84  typedef Tpetra::Vector<zscalar_t, zlno_t, zgno_t> Vector_t;
85 
86  // Useful typedefs: Zoltan2 types
87  typedef Zoltan2::XpetraCrsMatrixAdapter<Matrix_t> MatrixAdapter_t;
88  typedef Zoltan2::XpetraMultiVectorAdapter<Vector_t> MultiVectorAdapter_t;
89 
90  // Input parameters with default values
91  std::string method = "scotch"; // Partitioning method
92  zgno_t nx = 50, ny = 40, nz = 30; // Dimensions of mesh corresponding to
93  // the matrix to be partitioned
94 
95  // Read run-time options.
96  Teuchos::CommandLineProcessor cmdp (false, false);
97  cmdp.setOption("method", &method,
98  "Partitioning method to use: scotch or parmetis.");
99  cmdp.setOption("nx", &nx,
100  "number of gridpoints in X dimension for "
101  "mesh used to generate matrix; must be >= 1.");
102  cmdp.setOption("ny", &ny,
103  "number of gridpoints in Y dimension for "
104  "mesh used to generate matrix; must be >= 1.");
105  cmdp.setOption("nz", &nz,
106  "number of gridpoints in Z dimension for "
107  "mesh used to generate matrix; must be >= 1.");
108  cmdp.parse(narg, arg);
109 
110  if ((nx < 1) || (ny < 1) || (nz < 1)) {
111  cout << "Input error: nx, ny and nz must be >= 1" << endl;
112  return -1;
113  }
114 
115  // For this example, generate a matrix using Galeri with the
116  // default Tpetra distribution:
117  // Laplace3D matrix corresponding to mesh with dimensions (nx X ny X nz)
118  // with block row-based distribution
119  Teuchos::ParameterList galeriList;
120  galeriList.set("nx", nx);
121  galeriList.set("ny", ny);
122  galeriList.set("nz", nz);
123  Tpetra::global_size_t nGlobalElements = nx * ny * nz;
124 
125  RCP<Matrix_t> origMatrix;
126 
127  try {
128  RCP<const Map_t> map = rcp(new Map_t(nGlobalElements, 0, comm));
129 
130  typedef Galeri::Xpetra::Problem<Map_t,Matrix_t,MultiVector_t> Galeri_t;
131  RCP<Galeri_t> galeriProblem =
132  Galeri::Xpetra::BuildProblem<zscalar_t, zlno_t, zgno_t,
133  Map_t, Matrix_t, MultiVector_t>
134  ("Laplace3D", map, galeriList);
135  origMatrix = galeriProblem->BuildMatrix();
136  }
137  catch (std::exception &e) {
138  cout << "Exception in Galeri matrix generation. " << e.what() << endl;
139  return -1;
140  }
141 
142  if (me == 0)
143  cout << "NumRows = " << origMatrix->getGlobalNumRows() << endl
144  << "NumNonzeros = " << origMatrix->getGlobalNumEntries() << endl
145  << "NumProcs = " << comm->getSize() << endl;
146 
147  // Create vectors to use with the matrix for sparse matvec.
148  RCP<Vector_t> origVector, origProd;
149  origProd = Tpetra::createVector<zscalar_t,zlno_t,zgno_t>(
150  origMatrix->getRangeMap());
151  origVector = Tpetra::createVector<zscalar_t,zlno_t,zgno_t>(
152  origMatrix->getDomainMap());
153  origVector->randomize();
154 
155  // Specify partitioning parameters
156  Teuchos::ParameterList param;
157  param.set("partitioning_approach", "partition");
158  param.set("algorithm", method);
159 
160  // Create an input adapter for the Tpetra matrix.
161  MatrixAdapter_t adapter(origMatrix);
162 
163  // Create and solve partitioning problem
164  Zoltan2::PartitioningProblem<MatrixAdapter_t> problem(&adapter, &param);
165 
166  try {
167  problem.solve();
168  }
169  catch (std::exception &e) {
170  cout << "Exception returned from solve(). " << e.what() << endl;
171  return -1;
172  }
173 
174  // Redistribute matrix and vector into new matrix and vector.
175  // Can use PartitioningSolution from matrix to redistribute the vectors, too.
176 
177  if (me == 0) cout << "Redistributing matrix..." << endl;
178  RCP<Matrix_t> redistribMatrix;
179  adapter.applyPartitioningSolution(*origMatrix, redistribMatrix,
180  problem.getSolution());
181 
182  if (me == 0) cout << "Redistributing vectors..." << endl;
183  RCP<Vector_t> redistribVector;
184  MultiVectorAdapter_t adapterVector(origVector);
185  adapterVector.applyPartitioningSolution(*origVector, redistribVector,
186  problem.getSolution());
187 
188  // Create a new product vector for sparse matvec
189  RCP<Vector_t> redistribProd;
190  redistribProd = Tpetra::createVector<zscalar_t,zlno_t,zgno_t>(
191  redistribMatrix->getRangeMap());
192 
193  // SANITY CHECK
194  // A little output for small problems
195  if (origMatrix->getGlobalNumRows() <= 50) {
196  cout << me << " ORIGINAL: ";
197  for (size_t i = 0; i < origVector->getLocalLength(); i++)
198  cout << origVector->getMap()->getGlobalElement(i) << " ";
199  cout << endl;
200  cout << me << " REDISTRIB: ";
201  for (size_t i = 0; i < redistribVector->getLocalLength(); i++)
202  cout << redistribVector->getMap()->getGlobalElement(i) << " ";
203  cout << endl;
204  }
205 
206  // SANITY CHECK
207  // check that redistribution is "correct"; perform matvec with
208  // original and redistributed matrices/vectors and compare norms.
209 
210  if (me == 0) cout << "Matvec original..." << endl;
211  origMatrix->apply(*origVector, *origProd);
212  zscalar_t origNorm = origProd->norm2();
213  if (me == 0)
214  cout << "Norm of Original matvec prod: " << origNorm << endl;
215 
216  if (me == 0) cout << "Matvec redistributed..." << endl;
217  redistribMatrix->apply(*redistribVector, *redistribProd);
218  zscalar_t redistribNorm = redistribProd->norm2();
219  if (me == 0)
220  cout << "Norm of Redistributed matvec prod: " << redistribNorm << endl;
221 
222  if (me == 0) {
223  const double epsilon = 0.00000001;
224  if (redistribNorm > origNorm+epsilon || redistribNorm < origNorm-epsilon)
225  cout << "Mat-Vec product changed; FAIL" << std::endl;
226  else
227  cout << "PASS" << endl;
228  }
229 
230  return 0;
231 }
Provides access for Zoltan2 to Xpetra::CrsMatrix data.
size_t global_size_t
double zscalar_t
int zlno_t
Defines the XpetraMultiVectorAdapter.
Defines the XpetraCrsMatrixAdapter class.
int main(int narg, char **arg)
Definition: graph.cpp:67
An adapter for Xpetra::MultiVector.
int zgno_t
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
PartitioningProblem sets up partitioning problems for the user.
Defines the PartitioningProblem class.
#define epsilon
void solve(bool updateInputData=true)
Direct the problem to create a solution.