Zoltan2
mj_backwardcompat.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 
53 #include <Zoltan2_InputTraits.hpp>
54 #include <Tpetra_Map.hpp>
55 #include <vector>
56 #include <cstdlib>
57 
59 // Simple adapter with contiguous coordinates
60 template <typename User>
62 {
63 public:
66 
68  const size_t nids_,
69  const gno_t *gids_,
70  const int dim_,
71  const scalar_t *coords_,
72  const scalar_t *weights_ = NULL)
73  : nids(nids_), gids(gids_), dim(dim_), coords(coords_), weights(weights_)
74  { }
75 
76  size_t getLocalNumIDs() const { return nids; }
77 
78  void getIDsView(const gno_t *&ids) const { ids = gids; }
79 
80  int getNumWeightsPerID() const { return (weights != NULL); }
81 
82  void getWeightsView(const scalar_t *&wgt, int &stride, int idx = 0) const
83  { wgt = weights; stride = 1; }
84 
85  int getNumEntriesPerID() const { return dim; }
86 
87  void getEntriesView(const scalar_t *&coo, int &stride, int idx = 0) const
88  {
89  coo = &(coords[idx*nids]);
90  stride = 1;
91  }
92 
93 private:
94  const size_t nids;
95  const gno_t *gids;
96  const int dim;
97  const scalar_t *coords;
98  const scalar_t *weights;
99 };
100 
102 // Simple adapter with strided coordinates
103 template <typename User>
105 {
106 public:
109 
111  const size_t nids_,
112  const gno_t *gids_,
113  const int dim_,
114  const scalar_t *coords_,
115  const scalar_t *weights_ = NULL)
116  : nids(nids_), gids(gids_), dim(dim_), coords(coords_), weights(weights_)
117  { }
118 
119  size_t getLocalNumIDs() const { return nids; }
120 
121  void getIDsView(const gno_t *&ids) const { ids = gids; }
122 
123  int getNumWeightsPerID() const { return (weights != NULL); }
124 
125  void getWeightsView(const scalar_t *&wgt, int &stride, int idx = 0) const
126  { wgt = weights; stride = 1; }
127 
128  int getNumEntriesPerID() const { return dim; }
129 
130  void getEntriesView(const scalar_t *&coo, int &stride, int idx = 0) const
131  {
132  coo = &(coords[idx]);
133  stride = dim;
134  }
135 
136 private:
137  const size_t nids;
138  const gno_t *gids;
139  const int dim;
140  const scalar_t *coords;
141  const scalar_t *weights;
142 };
143 
145 int main(int narg, char *arg[])
146 {
147  Tpetra::ScopeGuard scope(&narg, &arg);
148  const Teuchos::RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
149  int rank = comm->getRank();
150  int nprocs = comm->getSize();
151  int nFail = 0;
152 
153  typedef Tpetra::Map<> Map_t;
154  typedef Map_t::local_ordinal_type localId_t;
155  typedef Map_t::global_ordinal_type globalId_t;
156  typedef double scalar_t;
157 
159  typedef OldSchoolVectorAdapterStrided<myTypes> stridedAdapter_t;
160  typedef OldSchoolVectorAdapterContig<myTypes> contigAdapter_t;
162 
164  // Create input data.
165 
166  size_t localCount = 40;
167  int dim = 5;
168 
169  // Create coordinates strided
170  scalar_t *cStrided = new scalar_t [dim * localCount];
171  size_t cnt = 0;
172  for (size_t i = 0; i < localCount; i++)
173  for (int d = 0; d < dim; d++)
174  cStrided[cnt++] = d*1000 + rank*100 + i;
175 
176  // Create same coords, stored contiguously
177  scalar_t *cContig = new scalar_t [dim * localCount];
178  cnt = 0;
179  for (int d = 0; d < dim; d++)
180  for (size_t i = 0; i < localCount; i++)
181  cContig[cnt++] = d*1000 + rank*100 + i;
182 
183  // Create global ids for the coordinates.
184  globalId_t *globalIds = new globalId_t [localCount];
185  globalId_t offset = rank * localCount;
186  for (size_t i=0; i < localCount; i++) globalIds[i] = offset++;
187 
189  // Create parameters for an MJ problem
190 
191  Teuchos::ParameterList params("test params");
192  params.set("debug_level", "basic_status");
193  params.set("error_check_level", "debug_mode_assertions");
194 
195  params.set("algorithm", "multijagged");
196  params.set("num_global_parts", nprocs+1);
197 
199  // Test one: No weights
200 
201  // Partition using strided coords
202  stridedAdapter_t *ia1 =
203  new stridedAdapter_t(localCount,globalIds,dim,cStrided);
204 
207 
208  problem1->solve();
209 
210  quality_t *metricObject1 = new quality_t(ia1, &params, comm,
211  &problem1->getSolution());
212  if (rank == 0){
213 
214  metricObject1->printMetrics(std::cout);
215 
216  double imb = metricObject1->getObjectCountImbalance();
217  if (imb <= 1.03) // Should get perfect balance
218  std::cout << "no weights -- balance satisfied: " << imb << std::endl;
219  else {
220  std::cout << "no weights -- balance failure: " << imb << std::endl;
221  nFail++;
222  }
223  std::cout << std::endl;
224  }
225 
226  // Partition using contiguous coords
227  contigAdapter_t *ia2 = new contigAdapter_t(localCount,globalIds,dim,cContig);
228 
231 
232  problem2->solve();
233 
234  // compare strided vs contiguous
235  size_t ndiff = 0;
236  for (size_t i = 0; i < localCount; i++) {
237  if (problem1->getSolution().getPartListView()[i] !=
238  problem2->getSolution().getPartListView()[i]) {
239  std::cout << rank << " Error: differing parts for index " << i
240  << problem1->getSolution().getPartListView()[i] << " "
241  << problem2->getSolution().getPartListView()[i] << std::endl;
242 
243  ndiff++;
244  }
245  }
246  if (ndiff > 0) nFail++;
247  else if (rank == 0) std::cout << "no weights -- comparisons OK " << std::endl;
248 
249  delete metricObject1;
250  delete problem1;
251  delete problem2;
252  delete ia1;
253  delete ia2;
254 
256  // Test two: weighted
257  // Create a Zoltan2 input adapter that includes weights.
258 
259  scalar_t *weights = new scalar_t [localCount];
260  for (size_t i=0; i < localCount; i++) weights[i] = 1 + scalar_t(rank);
261 
262  // Test with strided coords
263  ia1 = new stridedAdapter_t(localCount, globalIds, dim, cStrided, weights);
264 
265  problem1 = new Zoltan2::PartitioningProblem<stridedAdapter_t>(ia1, &params);
266 
267  problem1->solve();
268 
269  metricObject1 = new quality_t(ia1, &params, comm, &problem1->getSolution());
270 
271  if (rank == 0){
272 
273  metricObject1->printMetrics(std::cout);
274 
275  double imb = metricObject1->getWeightImbalance(0);
276  if (imb <= 1.03)
277  std::cout << "weighted -- balance satisfied " << imb << std::endl;
278  else {
279  std::cout << "weighted -- balance failed " << imb << std::endl;
280  nFail++;
281  }
282  std::cout << std::endl;
283  }
284 
285  // Partition using contiguous coords
286  ia2 = new contigAdapter_t(localCount, globalIds, dim, cContig, weights);
287 
288  problem2 = new Zoltan2::PartitioningProblem<contigAdapter_t>(ia2, &params);
289 
290  problem2->solve();
291 
292  // compare strided vs contiguous
293  ndiff = 0;
294  for (size_t i = 0; i < localCount; i++) {
295  if (problem1->getSolution().getPartListView()[i] !=
296  problem2->getSolution().getPartListView()[i]) {
297  std::cout << rank << " Error: differing parts for index " << i
298  << problem1->getSolution().getPartListView()[i] << " "
299  << problem2->getSolution().getPartListView()[i] << std::endl;
300 
301  ndiff++;
302  }
303  }
304  if (ndiff > 0) nFail++;
305  else if (rank == 0) std::cout << "weighted -- comparisons OK " << std::endl;
306 
307  delete metricObject1;
308  delete problem1;
309  delete problem2;
310  delete ia1;
311  delete ia2;
312 
313  // Test with strided coords
314  if (weights) delete [] weights;
315  if (cStrided) delete [] cStrided;
316  if (cContig) delete [] cContig;
317  if (globalIds) delete [] globalIds;
318 
319  // check result
320 
321  int gnFail;
322  Teuchos::reduceAll(*comm, Teuchos::REDUCE_SUM, 1, &nFail, &gnFail);
323 
324  if (rank == 0) {
325  if (gnFail == 0) std::cout << "PASS" << std::endl;
326  else std::cout << "FAIL: " << gnFail << " tests failed" << std::endl;
327  }
328 
329  return 0;
330 }
331 
Traits for application input objects.
Defines the PartitioningProblem class.
Defines the PartitioningSolution class.
Defines the VectorAdapter interface.
Zoltan2::InputTraits< User >::scalar_t scalar_t
int getNumEntriesPerID() const
Return the number of vectors.
int getNumWeightsPerID() const
Returns the number of weights per object. Number of weights per object should be zero or greater....
OldSchoolVectorAdapterContig(const size_t nids_, const gno_t *gids_, const int dim_, const scalar_t *coords_, const scalar_t *weights_=NULL)
void getIDsView(const gno_t *&ids) const
size_t getLocalNumIDs() const
Returns the number of objects on this process.
Zoltan2::InputTraits< User >::gno_t gno_t
void getWeightsView(const scalar_t *&wgt, int &stride, int idx=0) const
void getEntriesView(const scalar_t *&coo, int &stride, int idx=0) const
Zoltan2::InputTraits< User >::scalar_t scalar_t
int getNumWeightsPerID() const
Returns the number of weights per object. Number of weights per object should be zero or greater....
size_t getLocalNumIDs() const
Returns the number of objects on this process.
int getNumEntriesPerID() const
Return the number of vectors.
void getIDsView(const gno_t *&ids) const
void getEntriesView(const scalar_t *&coo, int &stride, int idx=0) const
void getWeightsView(const scalar_t *&wgt, int &stride, int idx=0) const
OldSchoolVectorAdapterStrided(const size_t nids_, const gno_t *gids_, const int dim_, const scalar_t *coords_, const scalar_t *weights_=NULL)
Zoltan2::InputTraits< User >::gno_t gno_t
A simple class that can be the User template argument for an InputAdapter.
A class that computes and returns quality metrics.
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.
VectorAdapter defines the interface for vector input.
int main(int narg, char *arg[])
static ArrayRCP< ArrayRCP< zscalar_t > > weights
default_gno_t gno_t
The ordinal type (e.g., int, long, int64_t) that can represent global counts and identifiers.
default_scalar_t scalar_t
The data type for weights and coordinates.