Zoltan2
Loading...
Searching...
No Matches
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
23using Teuchos::RCP;
24
26// Program to demonstrate use of Zoltan2 to partition a TPetra matrix
27// using graph partitioning via Scotch or ParMETIS.
29
30int 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}
Defines the PartitioningProblem class.
Defines the XpetraCrsMatrixAdapter class.
Defines the XpetraMultiVectorAdapter.
int main()
PartitioningProblem sets up partitioning problems for the user.
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
void solve(bool updateInputData=true)
Direct the problem to create a solution.
Provides access for Zoltan2 to Xpetra::CrsMatrix data.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
#define epsilon
Definition nd.cpp:47
Zoltan2::XpetraMultiVectorAdapter< tMVector_t > MultiVectorAdapter_t
Definition nd.cpp:45