|
Zoltan2
|
00001 // @HEADER 00002 // 00003 // *********************************************************************** 00004 // 00005 // Zoltan2: A package of combinatorial algorithms for scientific computing 00006 // Copyright 2012 Sandia Corporation 00007 // 00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00009 // the U.S. Government retains certain rights in this software. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact Karen Devine (kddevin@sandia.gov) 00039 // Erik Boman (egboman@sandia.gov) 00040 // Siva Rajamanickam (srajama@sandia.gov) 00041 // 00042 // *********************************************************************** 00043 // 00044 // @HEADER 00045 // 00046 // Test the IdentifierMap class. 00047 // 00048 // Test local IDs are implied, not supplied by app. 00049 00050 #include <Zoltan2_IdentifierMap.hpp> 00051 #include <Zoltan2_TestHelpers.hpp> 00052 00053 #if 0 00054 #include <string> 00055 #include <ostream> 00056 #include <iostream> 00057 #include <exception> 00058 #include <utility> 00059 #endif 00060 00061 #include <Teuchos_Comm.hpp> 00062 #include <Teuchos_DefaultComm.hpp> 00063 #include <Teuchos_RCP.hpp> 00064 #include <Teuchos_ArrayRCP.hpp> 00065 #include <Teuchos_Array.hpp> 00066 #include <Teuchos_ArrayView.hpp> 00067 00068 00069 using namespace std; 00070 using Teuchos::RCP; 00071 using Teuchos::rcp; 00072 using Teuchos::ArrayRCP; 00073 using Teuchos::Array; 00074 using Teuchos::ArrayView; 00075 using Teuchos::Comm; 00076 00077 template <typename T> 00078 struct UserIdTraits{ 00079 static std::string stringify(T val) {return std::string("INVALID");} 00080 }; 00081 00082 template<> 00083 struct UserIdTraits<std::pair<int, int> >{ 00084 static std::string stringify(std::pair<int, int> p) { 00085 ostringstream oss; 00086 oss << "pair(" << p.first << ", " << p.second << ")"; 00087 return oss.str(); 00088 } 00089 }; 00090 00091 template<> 00092 struct UserIdTraits<long>{ 00093 static std::string stringify(long val) { 00094 ostringstream oss; 00095 oss << val; 00096 return oss.str(); 00097 } 00098 }; 00099 00100 template<> 00101 struct UserIdTraits<int>{ 00102 static std::string stringify(int val) { 00103 ostringstream oss; 00104 oss << val; 00105 return oss.str(); 00106 } 00107 }; 00108 00109 template <typename IDMAP> 00110 void testIdMap( RCP<const Comm<int> > &comm, 00111 IDMAP *map, bool gnosAreGids, bool gnosAreConsecutive, 00112 ArrayRCP<typename IDMAP::zgid_t> &gids, 00113 ArrayRCP<typename IDMAP::zgid_t> &remoteGids, 00114 bool verbose) 00115 { 00116 typedef typename IDMAP::lno_t LNO; 00117 typedef typename IDMAP::gno_t GNO; 00118 typedef typename IDMAP::zgid_t GID; 00119 00120 int rank = comm->getRank(); 00121 int nprocs = comm->getSize(); 00122 00123 int fail = 0; 00124 00125 if (map->gnosAreGids() != gnosAreGids) 00126 fail = 1; 00127 00128 TEST_FAIL_AND_THROW(*comm, fail==0, "gnosAreGids") 00129 00130 if (map->gnosAreConsecutive() != gnosAreConsecutive) 00131 fail = 1; 00132 00133 TEST_FAIL_AND_THROW(*comm, fail==0, "consecutiveGids") 00134 00135 // Get Zoltan2's global numbers given user global Ids 00136 00137 size_t nLocalIds = gids.size(); 00138 Array<GNO> z2Ids(nLocalIds); 00139 00140 try { 00141 map->gidTranslate(gids(), z2Ids(), Zoltan2::TRANSLATE_APP_TO_LIB); 00142 } 00143 catch (std::exception &e){ 00144 fail = 2; 00145 } 00146 00147 TEST_FAIL_AND_THROW(*comm, fail==0, "gidTranslate") 00148 00149 if (verbose){ 00150 comm->barrier(); 00151 if (rank == 0) 00152 std::cout << "Zoltan2 GNOs = User GIDs: " << gnosAreGids << std::endl; 00153 for (int p=0; p < nprocs; p++){ 00154 if (p == rank){ 00155 std::cout << "Rank " << p << " gnos: "; 00156 for (size_t i=0; i < nLocalIds; i++){ 00157 std::cout << z2Ids[i] << " "; 00158 } 00159 std::cout << std::endl; 00160 std::cout.flush(); 00161 } 00162 comm->barrier(); 00163 } 00164 comm->barrier(); 00165 if (rank == 0){ 00166 std::cout << "MIN GNO " << map->getMinimumGlobalId(); 00167 std::cout << ", MAX GNO " << map->getMaximumGlobalId() << std::endl; 00168 std::cout.flush(); 00169 } 00170 comm->barrier(); 00171 } 00172 00173 // Get Zoltan2's global numbers given user local indices 00174 00175 Array<GNO> z2Ids2(nLocalIds); 00176 Array<LNO> indices(nLocalIds); 00177 00178 for (LNO i=nLocalIds-1,j=0; i >= 0; i--,j++){ 00179 indices[j] = i; 00180 } 00181 00182 00183 try { 00184 map->lnoTranslate(indices(), z2Ids2(), Zoltan2::TRANSLATE_APP_TO_LIB); 00185 } 00186 catch (std::exception &e){ 00187 fail = 3; 00188 } 00189 00190 TEST_FAIL_AND_THROW(*comm, fail==0, "lidTranslate") 00191 00192 for (LNO i=nLocalIds-1, j=0; i >= 0; i--, j++){ 00193 if (z2Ids2[j] != z2Ids[i]){ 00194 fail = 4; 00195 break; 00196 } 00197 } 00198 00199 TEST_FAIL_AND_THROW(*comm, fail==0, "lnoTranslate results") 00200 00201 // Get User's global Ids give Zoltan2's global numbers 00202 00203 Array<GID> userGids(nLocalIds); 00204 00205 try { 00206 map->gidTranslate(userGids(), z2Ids(), Zoltan2::TRANSLATE_LIB_TO_APP); 00207 } 00208 catch (std::exception &e){ 00209 fail = 5; 00210 } 00211 00212 TEST_FAIL_AND_THROW(*comm, fail==0, "gidTranslate 2") 00213 00214 for (size_t i=0; i < nLocalIds; i++){ 00215 if (userGids[i] != gids[i]){ 00216 fail = 6; 00217 break; 00218 } 00219 } 00220 00221 TEST_FAIL_AND_THROW(*comm, fail==0, "gidTranslate 2 results") 00222 00223 if (nprocs > 1){ 00224 // Get Zoltan2 global number and owner of some remote User global Ids 00225 size_t nRemoteIds = remoteGids.size(); 00226 Array<GNO> remoteGno(nRemoteIds); 00227 Array<int> remoteProc(nRemoteIds); 00228 00229 try { 00230 map->gidGlobalTranslate(remoteGids(), remoteGno(), remoteProc()); 00231 } 00232 catch (std::exception &e){ 00233 fail = 7; 00234 } 00235 00236 TEST_FAIL_AND_THROW(*comm, fail==0, "gidGLobalTranslate") 00237 00238 if (verbose){ 00239 comm->barrier(); 00240 for (int p=0; p < nprocs; p++){ 00241 if (rank == 0) 00242 std::cout << "Global info obtained from map:" << std::endl; 00243 if (p == rank){ 00244 std::cout << "Rank " << p << std::endl; 00245 for (size_t i=0; i < nRemoteIds; i++){ 00246 std::cout << " GID: "; 00247 std::cout << UserIdTraits<GID>::stringify(remoteGids[i]); 00248 std::cout << ", GNO " << remoteGno[i]; 00249 std::cout << ", Owner " << remoteProc[i] << std::endl; 00250 } 00251 std::cout << std::endl; 00252 std::cout.flush(); 00253 } 00254 comm->barrier(); 00255 } 00256 comm->barrier(); 00257 } 00258 } 00259 } 00260 00261 int main(int argc, char *argv[]) 00262 { 00263 Teuchos::GlobalMPISession session(&argc, &argv); 00264 RCP<const Comm<int> > comm = Teuchos::DefaultComm<int>::getComm(); 00265 int nprocs = comm->getSize(); 00266 int rank = comm->getRank(); 00267 RCP<const Zoltan2::Environment> env = rcp(new Zoltan2::Environment); 00268 00269 zlno_t numLocalObjects = 10; 00270 long numRemoteObjects = 3; // numRemoteObjects < numLocalObjects 00271 bool verbose = true; 00272 bool consecutiveGids=true; 00273 bool gnosAreGids=true; 00274 00275 // Test these cases: 00276 // 1. GIDs are non-consecutive ordinals 00277 // 2. GIDs are non-consecutive ordinals, but we ask IdentifierMap to 00278 // map them to consecutive IDs 00279 // 3. GIDs are consecutive ordinals 00280 // 4. GIDs are not Teuchos Ordinals 00281 00282 ArrayRCP<zzgid_t> gids(new zzgid_t [numLocalObjects], 0, numLocalObjects, true); 00283 ArrayRCP<zzgid_t> remoteGids(new zzgid_t [numRemoteObjects], 0, 00284 numRemoteObjects, true); 00285 00286 using Zoltan2::IdentifierMap; 00287 00288 typedef Zoltan2::BasicUserTypes<zscalar_t, zzgid_t, zlno_t, zgno_t> UserTypes; 00289 00291 // Ids are non-consecutive ordinals. 00292 00293 zgno_t base1 = 10000 * rank; 00294 zgno_t base2 = base1 + 5000; 00295 int fail = 0; 00296 zgno_t base = base1; 00297 00298 for (zlno_t i=0; i < numLocalObjects; i++){ 00299 gids[i] = base + i; 00300 if (i == numLocalObjects/2) base = base2; 00301 } 00302 00303 typedef IdentifierMap<UserTypes> idmap_t; 00304 00305 idmap_t *idMap = NULL; 00306 00307 try{ 00308 idMap = new idmap_t(env, comm, gids, false); 00309 } 00310 catch (std::exception &e){ 00311 std::cerr << rank << ") " << e.what() << std::endl; 00312 fail = 1; 00313 } 00314 TEST_FAIL_AND_EXIT(*comm, fail==0, "constructor first case", 1); 00315 00316 if (nprocs > 1){ 00317 int remoteProc = (rank ? rank-1 : nprocs-1); 00318 base = remoteProc * 10000; 00319 for (int i=0; i < numRemoteObjects; i++) 00320 remoteGids[i] = base + i; 00321 } 00322 00323 // We're not asking IdentifierMap to create consecutive 00324 // IDs, so Zoltan2 GNOs will be the User's GIDs, and 00325 // we will not have consecutive GNOs. 00326 00327 testIdMap<idmap_t>(comm, idMap, gnosAreGids, !consecutiveGids, 00328 gids, remoteGids, verbose); 00329 00330 delete idMap; 00331 00333 // Ids are non-consecutive ordinals. 00334 // IdentifierMap is asked to map them to consecutive. 00335 00336 try{ 00337 idMap = new idmap_t(env, comm, gids, true); 00338 } 00339 catch (std::exception &e){ 00340 std::cerr << rank << ") " << e.what() << std::endl; 00341 fail = 1; 00342 } 00343 TEST_FAIL_AND_EXIT(*comm, fail==0, "constructor second case", 1); 00344 00345 // Because we're asking IdentifierMap to make the Zoltan2 GNOs 00346 // consecutive, the GNOs will not be the same as the user GIDs. 00347 // And because we specifically asked for consecutive GNOs, we 00348 // will have consecutive global Ids. 00349 00350 testIdMap<idmap_t>(comm, idMap, !gnosAreGids, consecutiveGids, 00351 gids, remoteGids, verbose); 00352 00353 delete idMap; 00354 00356 // Ids are consecutive ordinals. 00357 00358 base = rank * numLocalObjects; 00359 for (zlno_t i=0; i < numLocalObjects; i++){ 00360 gids[i] = base + i; 00361 } 00362 00363 try{ 00364 idMap = new idmap_t(env, comm, gids, false); 00365 } 00366 catch (std::exception &e){ 00367 std::cerr << rank << ") " << e.what() << std::endl; 00368 fail = 1; 00369 } 00370 TEST_FAIL_AND_EXIT(*comm, fail==0, "constructor third case", 1); 00371 00372 if (nprocs > 1){ 00373 int remoteProc = (rank ? rank-1 : nprocs-1); 00374 base = remoteProc * numLocalObjects; 00375 for (int i=0; i < numRemoteObjects; i++) 00376 remoteGids[i] = base + i; 00377 } 00378 00379 // Because the User GIDs are ordinals, the Zoltan2 GNOs will be 00380 // the User GIDs. And since the User GIDs are already consecutive, 00381 // the Zoltan2 GNOs are consecutive. 00382 00383 testIdMap<idmap_t>(comm, idMap, gnosAreGids, consecutiveGids, 00384 gids, remoteGids, verbose); 00385 00386 delete idMap; 00387 00388 #if 0 00389 00390 ArrayRCP<std::pair<int,int> > remoteGidPairs( 00391 new std::pair<int,int> [numRemoteObjects], 0, numRemoteObjects, true); 00392 00393 // TODO - there is a bug in the IdentifierMap constructor 00394 // when GIDs are std::pair<int,int> 00396 // Ids are not ordinals. 00397 Zoltan2::BasicUserTypes<float, std::pair<int,int>, int, long> UserPairGids; 00398 00399 ArrayRCP<std::pair<int,int> > nonOrdinalGids( 00400 new std::pair<int,int> [numLocalObjects], 00401 0, numLocalObjects, true); 00402 00403 for (int i=0; i < numLocalObjects; i++){ 00404 nonOrdinalGids[i] = std::pair<int, int>(rank, i); 00405 } 00406 00407 typedef IdentifierMap<UserPairGids> mapPairGids_t; 00408 00409 mapPairGids_t *idMap2 = NULL; 00410 00411 try{ 00412 idMap2 = new mapPairGids_t(env, comm, nonOrdinalGids, false); 00413 } 00414 catch (std::exception &e){ 00415 std::cerr << rank << ") " << e.what() << std::endl; 00416 fail = 1; 00417 } 00418 TEST_FAIL_AND_EXIT(*comm, fail==0, "constructor fourth case", 1); 00419 00420 if (nprocs > 1){ 00421 int remoteProc = (rank ? rank-1 : nprocs-1); 00422 base = remoteProc * numLocalObjects; 00423 for (int i=0; i < numRemoteObjects; i++) 00424 remoteGidPairs[i] = std::pair<int,int>(remoteProc,i); 00425 } 00426 00427 // Because the User's GIDs are not Teuchos Ordinals, they 00428 // will not be used as Zoltan2 GNOs. When Zoltan2 creates 00429 // the global Ids for the problem, it creates consecutive 00430 // Ids that begin at 0. 00431 00432 testIdMap<idmap_t>(comm, idMap2, !gnosAreGids, consecutiveGids, 00433 nonOrdinalGids, remoteGidPairs, verbose); 00434 00435 delete idMap2; 00436 #endif 00437 00438 if (rank == 0) 00439 std::cout << "PASS" << std::endl; 00440 } 00441
1.7.6.1