Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
directoryTest_findUniqueGids.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 // Program to testing Zoltan2::findUniqueGids capability
47 // Input: Vector of keys: each key is an array with N entries
48 // Result vector to be filled by findUniqueGids
49 // Output: Filled result vector
50 
51 
52 #include <iostream>
53 #include <vector>
54 #include <array>
55 #include <unordered_set>
56 #include <string>
57 #include <typeinfo>
58 
59 #include <Zoltan2_Standards.hpp>
61 
62 namespace Zoltan2
63 {
64 
65 template <typename key_t, typename gno_t>
67  const std::vector<key_t> &keys,
68  std::vector<gno_t> &gids,
69  Teuchos::RCP<const Teuchos::Comm<int> > &comm
70 )
71 {
72  // Compute the new GIDs
73  const bool bUseLocalIDs = false; // Local IDs not needed
74  int debug_level = 0;
75 
76  typedef int lno_t; // unused
77 
79 
80  directory_t directory(comm, bUseLocalIDs, debug_level);
81 
82  directory.update(keys.size(), &keys[0], NULL, &gids[0], NULL,
84 
85  directory.remap_user_data_as_unique_gids();
86 
87  // Retrieve the global numbers and put in the result gids vector
88  directory.find(keys.size(), &keys[0], NULL, &gids[0], NULL, NULL, false);
89 
90  // using ssize_t can be long* on clang and I get warnings here or in the original
91  // findUniqueGids - using long long specifically is ok. Can we do an MPI type
92  // as size_t safely or is a conversion necessary? TODO but this gives a clean
93  // build result.
94  typedef long long mpi_t;
95  mpi_t nDDEntries = static_cast<mpi_t>(directory.node_map_size());
96  mpi_t nUnique = 0;
97 
98  // TODO use Teuchos
99 #ifdef HAVE_MPI
100  MPI_Allreduce(&nDDEntries, &nUnique, 1, MPI_LONG_LONG, MPI_SUM,
101  Teuchos::getRawMpiComm(*comm));
102 #else
103  MPI_Allreduce(&nDDEntries, &nUnique, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD);
104 #endif
105 
106  return size_t(nUnique);
107 }
108 
109 template<typename T>
110 struct type_name
111 {
112  static const char* name() {
113  std::cout << "You are missing a DECL_TYPE_NAME" << std::endl;
114  return(NULL);
115  }
116 };
117 
118 #define DECL_TYPE_NAME(x) \
119  template<> struct type_name<x> { static const char* name() {return #x;} }
120 
121 DECL_TYPE_NAME(int);
122 DECL_TYPE_NAME(long long);
123 
125 // Tests for correctness
126 static const std::string fail = "FAIL ";
127 static const std::string pass = " ";
128 
129 // Test for correct number of unique Gids
130 void checkNUnique(std::string &name, size_t nUniqueGids, size_t nExpected)
131 {
132  if (nUniqueGids != nExpected)
133  std::cout << fail << name
134  << "nUniqueGids " << nUniqueGids << " != " << nExpected
135  << std::endl;
136 }
137 
138 // Test for correct maximum Gid
139 template <typename gno_t>
141  std::string &name,
142  std::vector<gno_t> &gids,
143  gno_t maxExpected,
144  Teuchos::RCP<const Teuchos::Comm<int> > &comm
145 )
146 {
147  gno_t maxGid = 0, gmaxGid = 0;
148  size_t len = gids.size();
149  for (size_t i = 0; i < len; i++)
150  if (gids[i] > maxGid) maxGid = gids[i];
151 
152  Teuchos::reduceAll<int, gno_t>(*comm, Teuchos::REDUCE_MAX, 1,
153  &maxGid, &gmaxGid);
154  if (gmaxGid != maxExpected)
155  std::cout << fail << name
156  << "max Gid " << gmaxGid << " != " << maxExpected
157  << std::endl;
158 }
159 
160 // Test for correct minimum Gid
161 template <typename gno_t>
163  std::string &name,
164  std::vector<gno_t> &gids,
165  gno_t minExpected,
166  Teuchos::RCP<const Teuchos::Comm<int> > &comm
167 )
168 {
169  gno_t minGid = std::numeric_limits<gno_t>::max(), gminGid;
170  size_t len = gids.size();
171  for (size_t i = 0; i < len; i++)
172  if (gids[i] < minGid) minGid = gids[i];
173 
174  Teuchos::reduceAll<int, gno_t>(*comm, Teuchos::REDUCE_MIN, 1,
175  &minGid, &gminGid);
176  if (gminGid != minExpected)
177  std::cout << fail << name
178  << "min Gid " << gminGid << " != " << minExpected
179  << std::endl;
180 }
181 
182 // Test for number of locally unique Gids
183 template <typename gno_t>
185  std::string &name,
186  std::vector<gno_t> &gids,
187  size_t nExpected)
188 {
189  size_t gidsLen = gids.size();
190  std::unordered_set<gno_t> gidsSet(gidsLen);
191 
192  size_t nDups = 0;
193  for (size_t i = 0; i < gidsLen; i++) {
194  if (gidsSet.find(gids[i]) != gidsSet.end()) {
195  // Gid is already found locally
196  nDups++;
197  }
198  else
199  gidsSet.insert(gids[i]);
200  }
201  size_t nUnique = gidsLen - nDups;
202  if (nUnique != nExpected)
203  std::cout << fail << name
204  << "num locally unique Gids " << nUnique << " != " << nExpected
205  << std::endl;
206 }
207 
209 
210 template <typename gno_t>
211 void test1(Teuchos::RCP<const Teuchos::Comm<int> > &comm)
212 {
213  // Test 1:
214  // Key has only one entry
215  // Each proc has me+1 keys
216  // Keys are in range [1,np]
217  int me = comm->getRank();
218  int np = comm->getSize();
219 
220  std::string name = std::string(" test1: ")
221  + std::string(type_name<gno_t>::name());
222  if (me == 0) std::cout << "--------\n Starting " << name << std::endl;
223 
224  typedef std::array<gno_t, 1> zkey_t;
225  typedef std::vector<zkey_t> keyvec_t;
226  typedef std::vector<gno_t> gidvec_t;
227 
228  const size_t nKeys = me+1;
229  keyvec_t keys(nKeys);
230  gidvec_t gids(nKeys);
231 
232  for (size_t i = 0; i < nKeys; i++) {
233  zkey_t k;
234  k[0] = i+1;
235  keys[i] = k;
236  }
237 
238  size_t nUniqueGids = findUniqueGids<zkey_t, gno_t>(keys,gids,comm);
239 
240  // Test for correctness
241  if (me == 0)
242  std::cout << " " << name << " nUniqueGids " << nUniqueGids << std::endl;
243 
244  checkNUnique(name, nUniqueGids, size_t(np));
245 
246  checkMaxGid(name, gids, gno_t(np-1), comm);
247 
248  checkMinGid(name, gids, gno_t(0), comm);
249 
250  checkNLocallyUnique(name, gids, nKeys);
251 }
252 
254 
255 template <typename gno_t>
256 void test2(Teuchos::RCP<const Teuchos::Comm<int> > &comm)
257 {
258  // Test 2:
259  // Key has two entries
260  // Each proc has six keys
261  // Three Keys are {rank, x} for x in {1, 2, 3}
262  // Three Keys are {(rank+x)%np, x} for x in {1, 2, 3}
263  // Each rank has three unique and three non-unique keys
264  int me = comm->getRank();
265  int np = comm->getSize();
266 
267  std::string name = std::string(" test2: ")
268  + std::string(type_name<gno_t>::name());
269  if (me == 0) std::cout << "--------\n Starting " << name << std::endl;
270 
271  typedef std::array<gno_t, 2> zkey_t;
272  typedef std::vector<zkey_t> keyvec_t;
273  typedef std::vector<gno_t> gidvec_t;
274 
275  const size_t nKeys = 6;
276  const size_t nKeysHalf = 3;
277  keyvec_t keys(nKeys);
278  gidvec_t gids(nKeys);
279 
280  for (size_t i = 0; i < nKeysHalf; i++) {
281  zkey_t k;
282  k[0] = gno_t(me);
283  k[1] = gno_t(i+1);
284  keys[i] = k;
285  }
286  for (size_t i = 0; i < nKeysHalf; i++) {
287  zkey_t k;
288  k[0] = gno_t((me+i+1)%np);
289  k[1] = gno_t(i+1);
290  keys[i+nKeysHalf] = k;
291  }
292 
293  size_t nUniqueGids = findUniqueGids<zkey_t,gno_t>(keys,gids,comm);
294 
295  // Test for correctness
296  if (me == 0)
297  std::cout << " " << name << " nUniqueGids " << nUniqueGids << std::endl;
298 
299  checkNUnique(name, nUniqueGids, size_t(nKeysHalf*np));
300 
301  checkMaxGid(name, gids, gno_t(nKeysHalf*np-1), comm);
302 
303  checkMinGid(name, gids, gno_t(0), comm);
304 }
305 
307 template <typename gno_t>
308 void test3(Teuchos::RCP<const Teuchos::Comm<int> > &comm)
309 {
310  // Test 3:
311  // Key has three entries
312  // Each proc has 2*np keys
313  // np Keys are {x, x, x} for x in {0, 1, ..., np-1}
314  // np Keys are {rank, rank, x} for x in {0, 1, ..., np-1}
315  // Each proc has one locally duplicated key
316  // Each proc contributes np unique keys
317  int me = comm->getRank();
318  int np = comm->getSize();
319 
320  std::string name = std::string(" test3: ")
321  + std::string(type_name<gno_t>::name());
322  if (me == 0) std::cout << "--------\n Starting " << name << std::endl;
323 
324  typedef std::array<gno_t, 3> zkey_t;
325  typedef std::vector<zkey_t> keyvec_t;
326  typedef std::vector<gno_t> gidvec_t;
327 
328  const size_t nKeys = 2*np;
329  const size_t nKeysHalf = np;
330  keyvec_t keys(nKeys);
331  gidvec_t gids(nKeys);
332 
333  for (size_t i = 0; i < nKeysHalf; i++) {
334  zkey_t k;
335  k[0] = gno_t(me);
336  k[1] = gno_t(me);
337  k[2] = gno_t(i);
338  keys[i+nKeysHalf] = k;
339  }
340  for (size_t i = 0; i < nKeysHalf; i++) {
341  zkey_t k;
342  k[0] = gno_t(i);
343  k[1] = gno_t(i);
344  k[2] = gno_t(i);
345  keys[i] = k;
346  }
347 
348  size_t nUniqueGids = findUniqueGids<zkey_t,gno_t>(keys,gids,comm);
349 
350  // for (size_t i = 0; i < nKeys; i++)
351  // std::cout << me << " Key " << i << ": "
352  // << keys[i][0] << " " << keys[i][1] << " " << keys[i][2]
353  // << " GID " << gids[i]
354  // << std::endl;
355 
356  // Test for correctness
357  if (me == 0)
358  std::cout << " " << name << " nUniqueGids " << nUniqueGids << std::endl;
359 
360  checkNUnique(name, nUniqueGids, size_t(np*np));
361 
362  checkMaxGid(name, gids, gno_t(np*np-1), comm);
363 
364  checkMinGid(name, gids, gno_t(0), comm);
365 
366  checkNLocallyUnique(name, gids, size_t(nKeys-1));
367 }
368 
370 
371 template <typename gno_t>
372 void test4(Teuchos::RCP<const Teuchos::Comm<int> > &comm)
373 {
374  // Test 4:
375  // Key has four entries
376  // Each proc has (rank+1)%2 keys; odd-numbered ranks are empty
377  // Keys are all identical {0, 1, 2, 3}
378  int me = comm->getRank();
379 
380  std::string name = std::string(" test4: ")
381  + std::string(type_name<gno_t>::name());
382  if (me == 0) std::cout << "--------\n Starting " << name << std::endl;
383 
384  typedef std::array<gno_t, 4> zkey_t;
385  typedef std::vector<zkey_t> keyvec_t;
386  typedef std::vector<gno_t> gidvec_t;
387 
388  const size_t nKeys = (me+1)%2;
389  keyvec_t keys(nKeys);
390  gidvec_t gids(nKeys);
391 
392  for (size_t i = 0; i < nKeys; i++) {
393  zkey_t k;
394  k[0] = gno_t(0);
395  k[1] = gno_t(1);
396  k[2] = gno_t(2);
397  k[3] = gno_t(3);
398  keys[i] = k;
399  }
400 
401  size_t nUniqueGids = findUniqueGids<zkey_t,gno_t>(keys,gids,comm);
402 
403  // Test for correctness
404  if (me == 0)
405  std::cout << " " << name << " nUniqueGids " << nUniqueGids << std::endl;
406 
407  checkNUnique(name, nUniqueGids, size_t(1));
408 
409  checkMaxGid(name, gids, gno_t(0), comm);
410 
411  checkMinGid(name, gids, gno_t(0), comm);
412 
413  checkNLocallyUnique(name, gids, (nKeys ? size_t(1): size_t(0)));
414 }
415 
416 } // namespace Zoltan2
417 
418 int main(int argc, char *argv[])
419 {
420  Tpetra::ScopeGuard tscope(&argc, &argv);
421  Teuchos::RCP<const Teuchos::Comm<int> > comm =
422  Teuchos::DefaultComm<int>::getComm();
423 
424  Zoltan2::test1<int>(comm);
425  Zoltan2::test2<int>(comm);
426  Zoltan2::test3<int>(comm);
427  Zoltan2::test4<int>(comm);
428 
429  Zoltan2::test1<long long>(comm);
430  Zoltan2::test2<long long>(comm);
431  Zoltan2::test3<long long>(comm);
432  Zoltan2::test4<long long>(comm);
433 
434  return 0;
435 }
void test1(Teuchos::RCP< const Teuchos::Comm< int > > &comm)
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:18
int main(int narg, char **arg)
Definition: coloring1.cpp:199
void test4(Teuchos::RCP< const Teuchos::Comm< int > > &comm)
static const std::string pass
void checkNUnique(std::string &name, size_t nUniqueGids, size_t nExpected)
map_t::local_ordinal_type lno_t
Definition: mapRemotes.cpp:17
size_t findUniqueGids(Tpetra::MultiVector< gno_t, lno_t, gno_t > &keys, Tpetra::Vector< gno_t, lno_t, gno_t > &gids)
void test2(Teuchos::RCP< const Teuchos::Comm< int > > &comm)
static const std::string fail
DECL_TYPE_NAME(int)
void checkNLocallyUnique(std::string &name, std::vector< gno_t > &gids, size_t nExpected)
Gathering definitions used in software development.
void test3(Teuchos::RCP< const Teuchos::Comm< int > > &comm)
void checkMinGid(std::string &name, std::vector< gno_t > &gids, gno_t minExpected, Teuchos::RCP< const Teuchos::Comm< int > > &comm)
void checkMaxGid(std::string &name, std::vector< gno_t > &gids, gno_t maxExpected, Teuchos::RCP< const Teuchos::Comm< int > > &comm)