Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 
OldSchoolVectorAdapterStrided(const size_t nids_, const gno_t *gids_, const int dim_, const scalar_t *coords_, const scalar_t *weights_=NULL)
size_t getLocalNumIDs() const
Returns the number of objects on this process.
Zoltan2::InputTraits< User >::gno_t gno_t
void getEntriesView(const scalar_t *&coo, int &stride, int idx=0) const
int getNumEntriesPerID() const
Return the number of vectors.
int main(int narg, char *arg[])
Zoltan2::InputTraits< User >::scalar_t scalar_t
A simple class that can be the User template argument for an InputAdapter.
Defines the VectorAdapter interface.
static ArrayRCP< ArrayRCP< zscalar_t > > weights
Defines the PartitioningSolution class.
int getNumWeightsPerID() const
Returns the number of weights per object. Number of weights per object should be zero or greater...
void getIDsView(const gno_t *&ids) const
void getWeightsView(const scalar_t *&wgt, int &stride, int idx=0) const
void getEntriesView(const scalar_t *&coo, int &stride, int idx=0) const
void getIDsView(const gno_t *&ids) const
VectorAdapter defines the interface for vector input.
Traits for application input objects.
default_gno_t gno_t
The ordinal type (e.g., int, long, int64_t) that can represent global counts and identifiers.
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
PartitioningProblem sets up partitioning problems for the user.
void getWeightsView(const scalar_t *&wgt, int &stride, int idx=0) const
Defines the PartitioningProblem class.
Zoltan2::InputTraits< User >::gno_t gno_t
A class that computes and returns quality metrics.
size_t getLocalNumIDs() const
Returns the number of objects on this process.
void solve(bool updateInputData=true)
Direct the problem to create a solution.
default_scalar_t scalar_t
The data type for weights and coordinates.
int getNumEntriesPerID() const
Return the number of vectors.
OldSchoolVectorAdapterContig(const size_t nids_, const gno_t *gids_, const int dim_, const scalar_t *coords_, const scalar_t *weights_=NULL)
int getNumWeightsPerID() const
Returns the number of weights per object. Number of weights per object should be zero or greater...
Zoltan2::InputTraits< User >::scalar_t scalar_t