Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
PartitioningSolution.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 //
46 // Test the PartitioningSolution class.
47 //
48 // Normally a Solution is created by a Problem.
49 // We create a few Solutions in this unit test.
50 
51 // TODO test ::convertSolutionToImportList
52 
55 #include <Zoltan2_TestHelpers.hpp>
56 
60 
61 using Teuchos::ArrayRCP;
62 using Teuchos::Array;
63 using Teuchos::RCP;
64 using Teuchos::rcp;
65 using Teuchos::arcp;
66 
67 
68 
69 void makeArrays(int wdim, int *lens, zzpart_t **ids, zscalar_t **sizes,
70  ArrayRCP<ArrayRCP<zzpart_t> > &idList, ArrayRCP<ArrayRCP<zscalar_t> > &sizeList)
71 {
72  ArrayRCP<zzpart_t> *idArrays = new ArrayRCP<zzpart_t> [wdim];
73  ArrayRCP<zscalar_t> *sizeArrays = new ArrayRCP<zscalar_t> [wdim];
74 
75  for (int w=0; w < wdim; w++){
76  idArrays[w] = arcp(ids[w], 0, lens[w], false);
77  sizeArrays[w] = arcp(sizes[w], 0, lens[w], false);
78  }
79 
80  idList = arcp(idArrays, 0, wdim, true);
81  sizeList = arcp(sizeArrays, 0, wdim, true);
82 }
83 
84 int main(int narg, char *arg[])
85 {
86  Tpetra::ScopeGuard tscope(&narg, &arg);
87  Teuchos::RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
88 
89  int nprocs = comm->getSize();
90  int rank = comm->getRank();
91  int fail=0, gfail=0;
92  double epsilon = 10e-6;
93 
95  // Arrays to hold part Ids and part Sizes for each weight
96 
97  int numIdsPerProc = 10;
98  int maxNumWeights = 3;
99  int maxNumPartSizes = nprocs;
100  int *lengths = new int [maxNumWeights];
101  zzpart_t **idLists = new zzpart_t * [maxNumWeights];
102  zscalar_t **sizeLists = new zscalar_t * [maxNumWeights];
103 
104  for (int w=0; w < maxNumWeights; w++){
105  idLists[w] = new zzpart_t [maxNumPartSizes];
106  sizeLists[w] = new zscalar_t [maxNumPartSizes];
107  }
108 
110  // A default environment
111  RCP<const Zoltan2::Environment> env = rcp(new Zoltan2::Environment(comm));
112 
114  // A simple identifier map.
115 
116  zgno_t *myGids = new zgno_t [numIdsPerProc];
117  for (int i=0, x=rank*numIdsPerProc; i < numIdsPerProc; i++)
118  myGids[i] = x++;
119 
121  // TEST:
122  // One weight, one part per proc.
123  // Some part sizes are 2 and some are 1.
124 
125  int numGlobalParts = nprocs;
126  int nWeights = 1;
127 
128  ArrayRCP<ArrayRCP<zzpart_t> > ids;
129  ArrayRCP<ArrayRCP<zscalar_t> > sizes;
130 
131  memset(lengths, 0, sizeof(int) * maxNumWeights);
132 
133  lengths[0] = 1; // We give a size for 1 part.
134  idLists[0][0] = rank; // The part is my part.
135  sizeLists[0][0] = rank%2 + 1.0; // The size is 1.0 or 2.0
136 
137  makeArrays(1, lengths, idLists, sizeLists, ids, sizes);
138 
139  // Normalized part size for every part, for checking later on
140 
141  zscalar_t *normalizedPartSizes = new zscalar_t [numGlobalParts];
142  zscalar_t sumSizes=0;
143  for (int i=0; i < numGlobalParts; i++){
144  normalizedPartSizes[i] = 1.0;
145  if (i % 2) normalizedPartSizes[i] = 2.0;
146  sumSizes += normalizedPartSizes[i];
147  }
148  for (int i=0; i < numGlobalParts; i++)
149  normalizedPartSizes[i] /= sumSizes;
150 
152  // Create a solution object with part size information, and check it.
153 
154  RCP<Zoltan2::PartitioningSolution<idInput_t> > solution;
155 
156  try{
157  solution = rcp(new Zoltan2::PartitioningSolution<idInput_t>(
158  env, // application environment info
159  comm, // problem communicator
160  nWeights, // number of weights
161  ids.view(0,nWeights), // part ids
162  sizes.view(0,nWeights))); // part sizes
163  }
164  catch (std::exception &e){
165  fail=1;
166  }
167 
168  TEST_FAIL_AND_EXIT(*comm, fail==0, "constructor call 1", 1);
169 
170  // Test the Solution queries that are used by algorithms
171 
172  if (solution->getTargetGlobalNumberOfParts() != size_t(numGlobalParts))
173  fail=2;
174 
175  if (!fail && solution->getLocalNumberOfParts() != 1)
176  fail=3;
177 
178  if (!fail && !solution->oneToOnePartDistribution())
179  fail=4;
180 
181  if (!fail && solution->getPartDistribution() != NULL)
182  fail=5;
183 
184  if (!fail && solution->getProcDistribution() != NULL)
185  fail=6;
186 
187  if (!fail &&
188  ((nprocs>1 && solution->criteriaHasUniformPartSizes(0)) ||
189  (nprocs==1 && !solution->criteriaHasUniformPartSizes(0))) )
190  fail=8;
191 
192  if (!fail){
193  for (int partId=0; !fail && partId < numGlobalParts; partId++){
194  zscalar_t psize = solution->getCriteriaPartSize(0, partId);
195 
196  if ( psize < normalizedPartSizes[partId] - epsilon ||
197  psize > normalizedPartSizes[partId] + epsilon )
198  fail=9;
199  }
200  }
201 
202  delete [] normalizedPartSizes;
203 
204  gfail = globalFail(*comm, fail);
205  if (gfail){
206  printFailureCode(*comm, fail); // exits after printing "FAIL"
207  }
208 
209  // Test the Solution set method that is called by algorithms
210 
211  zzpart_t *partAssignments = new zzpart_t [numIdsPerProc];
212  for (int i=0; i < numIdsPerProc; i++){
213  partAssignments[i] = myGids[i] % numGlobalParts; // round robin
214  }
215  ArrayRCP<zzpart_t> partList = arcp(partAssignments, 0, numIdsPerProc);
216 
217  try{
218  solution->setParts(partList);
219  }
220  catch (std::exception &e){
221  fail=10;
222  }
223 
224  gfail = globalFail(*comm, fail);
225  if (gfail){
226  printFailureCode(*comm, fail); // exits after printing "FAIL"
227  }
228 
229  // Test the Solution get methods that may be called by users
230  // or migration functions.
231 
232  if (!fail){
233  const zzpart_t *parts = solution->getPartListView();
234  for (int i=0; !fail && i < numIdsPerProc; i++){
235  if (parts[i] != zzpart_t(myGids[i] % numGlobalParts))
236  fail = 13;
237  }
238  }
239 
240  gfail = globalFail(*comm, fail);
241  if (gfail){
242  printFailureCode(*comm, fail); // exits after printing "FAIL"
243  }
244 
245  if (rank==0)
246  std::cout << "PASS" << std::endl;
247 
249  // TODO:
251  // Create a solution object without part size information, and check it.
253  // Test multiple weights.
255  // Test multiple parts per process.
257  // Specify a list of parts of size 0. (The rest should be uniform.)
258 
259  delete [] lengths;
260  for (int w=0; w < maxNumWeights; w++){
261  delete [] idLists[w];
262  delete [] sizeLists[w];
263  }
264  delete [] idLists;
265  delete [] sizeLists;
266  delete [] myGids;
267 }
void printFailureCode(const Comm< int > &comm, int fail)
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > zzuser_t
Definition: Mapping.cpp:58
#define TEST_FAIL_AND_EXIT(comm, ok, s, code)
int main(int narg, char **arg)
Definition: coloring1.cpp:199
Defines the PartitioningSolution class.
idInput_t::part_t zzpart_t
common code used by tests
This class represents a collection of global Identifiers and their associated weights, if any.
#define epsilon
Definition: nd.cpp:82
void makeArrays(int wdim, int *lens, zzpart_t **ids, zscalar_t **sizes, ArrayRCP< ArrayRCP< zzpart_t > > &idList, ArrayRCP< ArrayRCP< zscalar_t > > &sizeList)
A PartitioningSolution is a solution to a partitioning problem.
The user parameters, debug, timing and memory profiling output objects, and error checking methods...
static const std::string fail
Defines the BasicIdentifierAdapter class.
int globalFail(const Comm< int > &comm, int fail)
Zoltan2::BasicIdentifierAdapter< zzuser_t > idInput_t
float zscalar_t
Tpetra::Map::global_ordinal_type zgno_t