|
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 PartitioningSolution class. 00047 // 00048 // Normally a Solution is created by a Problem. 00049 // We create a few Solutions in this unit test. 00050 00051 // TODO test ::convertSolutionToImportList 00052 00053 #include <Zoltan2_PartitioningSolution.hpp> 00054 #include <Zoltan2_BasicIdentifierAdapter.hpp> 00055 #include <Zoltan2_TestHelpers.hpp> 00056 00057 typedef Zoltan2::BasicUserTypes<zscalar_t, zgno_t, zlno_t, zgno_t> user_t; 00058 typedef Zoltan2::BasicIdentifierAdapter<user_t> idInput_t; 00059 typedef idInput_t::part_t part_t; 00060 00061 using Teuchos::ArrayRCP; 00062 using Teuchos::Array; 00063 using Teuchos::RCP; 00064 using Teuchos::rcp; 00065 using Teuchos::arcp; 00066 00067 00068 00069 void makeArrays(int wdim, int *lens, part_t **ids, zscalar_t **sizes, 00070 ArrayRCP<ArrayRCP<part_t> > &idList, ArrayRCP<ArrayRCP<zscalar_t> > &sizeList) 00071 { 00072 ArrayRCP<part_t> *idArrays = new ArrayRCP<part_t> [wdim]; 00073 ArrayRCP<zscalar_t> *sizeArrays = new ArrayRCP<zscalar_t> [wdim]; 00074 00075 for (int w=0; w < wdim; w++){ 00076 idArrays[w] = arcp(ids[w], 0, lens[w], false); 00077 sizeArrays[w] = arcp(sizes[w], 0, lens[w], false); 00078 } 00079 00080 idList = arcp(idArrays, 0, wdim, true); 00081 sizeList = arcp(sizeArrays, 0, wdim, true); 00082 } 00083 00084 int main(int argc, char *argv[]) 00085 { 00086 Teuchos::GlobalMPISession session(&argc, &argv); 00087 RCP<const Comm<int> > comm = Teuchos::DefaultComm<int>::getComm(); 00088 int nprocs = comm->getSize(); 00089 int rank = comm->getRank(); 00090 int fail=0, gfail=0; 00091 double epsilon = 10e-6; 00092 00094 // Arrays to hold part Ids and part Sizes for each weight 00095 00096 int numIdsPerProc = 10; 00097 int maxNumWeights = 3; 00098 int maxNumPartSizes = nprocs; 00099 int *lengths = new int [maxNumWeights]; 00100 part_t **idLists = new part_t * [maxNumWeights]; 00101 zscalar_t **sizeLists = new zscalar_t * [maxNumWeights]; 00102 00103 for (int w=0; w < maxNumWeights; w++){ 00104 idLists[w] = new part_t [maxNumPartSizes]; 00105 sizeLists[w] = new zscalar_t [maxNumPartSizes]; 00106 } 00107 00109 // A default environment 00110 RCP<const Zoltan2::Environment> env = rcp(new Zoltan2::Environment); 00111 00113 // A simple identifier map. 00114 00115 zgno_t *myGids = new zgno_t [numIdsPerProc]; 00116 for (int i=0, x=rank*numIdsPerProc; i < numIdsPerProc; i++){ 00117 myGids[i] = x++; 00118 } 00119 00120 ArrayRCP<const zgno_t> gidArray(myGids, 0, numIdsPerProc, true); 00121 00122 RCP<const Zoltan2::IdentifierMap<user_t> > idMap = 00123 rcp(new Zoltan2::IdentifierMap<user_t>(env, comm, gidArray)); 00124 00126 // TEST: 00127 // One weight, one part per proc. 00128 // Some part sizes are 2 and some are 1. 00129 00130 int numGlobalParts = nprocs; 00131 int nWeights = 1; 00132 00133 ArrayRCP<ArrayRCP<part_t> > ids; 00134 ArrayRCP<ArrayRCP<zscalar_t> > sizes; 00135 00136 memset(lengths, 0, sizeof(int) * maxNumWeights); 00137 00138 lengths[0] = 1; // We give a size for 1 part. 00139 idLists[0][0] = rank; // The part is my part. 00140 sizeLists[0][0] = rank%2 + 1.0; // The size is 1.0 or 2.0 00141 00142 makeArrays(1, lengths, idLists, sizeLists, ids, sizes); 00143 00144 // Normalized part size for every part, for checking later on 00145 00146 zscalar_t *normalizedPartSizes = new zscalar_t [numGlobalParts]; 00147 zscalar_t sumSizes=0; 00148 for (int i=0; i < numGlobalParts; i++){ 00149 normalizedPartSizes[i] = 1.0; 00150 if (i % 2) normalizedPartSizes[i] = 2.0; 00151 sumSizes += normalizedPartSizes[i]; 00152 } 00153 for (int i=0; i < numGlobalParts; i++) 00154 normalizedPartSizes[i] /= sumSizes; 00155 00157 // Create a solution object with part size information, and check it. 00158 00159 RCP<Zoltan2::PartitioningSolution<idInput_t> > solution; 00160 00161 try{ 00162 solution = rcp(new Zoltan2::PartitioningSolution<idInput_t>( 00163 env, // application environment info 00164 comm, // problem communicator 00165 idMap, // problem identifiers (global Ids, local Ids) 00166 nWeights, // number of weights 00167 ids.view(0,nWeights), // part ids 00168 sizes.view(0,nWeights))); // part sizes 00169 } 00170 catch (std::exception &e){ 00171 fail=1; 00172 } 00173 00174 TEST_FAIL_AND_EXIT(*comm, fail==0, "constructor call 1", 1); 00175 00176 // Test the Solution queries that are used by algorithms 00177 00178 if (solution->getTargetGlobalNumberOfParts() != size_t(numGlobalParts)) 00179 fail=2; 00180 00181 if (!fail && solution->getLocalNumberOfParts() != 1) 00182 fail=3; 00183 00184 if (!fail && !solution->oneToOnePartDistribution()) 00185 fail=4; 00186 00187 if (!fail && solution->getPartDistribution() != NULL) 00188 fail=5; 00189 00190 if (!fail && solution->getProcDistribution() != NULL) 00191 fail=6; 00192 00193 if (!fail && 00194 ((nprocs>1 && solution->criteriaHasUniformPartSizes(0)) || 00195 (nprocs==1 && !solution->criteriaHasUniformPartSizes(0))) ) 00196 fail=8; 00197 00198 if (!fail){ 00199 for (int partId=0; !fail && partId < numGlobalParts; partId++){ 00200 zscalar_t psize = solution->getCriteriaPartSize(0, partId); 00201 00202 if ( psize < normalizedPartSizes[partId] - epsilon || 00203 psize > normalizedPartSizes[partId] + epsilon ) 00204 fail=9; 00205 } 00206 } 00207 00208 delete [] normalizedPartSizes; 00209 00210 gfail = globalFail(comm, fail); 00211 if (gfail){ 00212 printFailureCode(comm, fail); // exits after printing "FAIL" 00213 } 00214 00215 // Test the Solution set method that is called by algorithms 00216 00217 part_t *partAssignments = new part_t [numIdsPerProc]; 00218 for (int i=0; i < numIdsPerProc; i++){ 00219 partAssignments[i] = myGids[i] % numGlobalParts; // round robin 00220 } 00221 ArrayRCP<part_t> partList = arcp(partAssignments, 0, numIdsPerProc); 00222 00223 try{ 00224 solution->setParts(gidArray, partList, true); 00225 } 00226 catch (std::exception &e){ 00227 fail=10; 00228 } 00229 00230 gfail = globalFail(comm, fail); 00231 if (gfail){ 00232 printFailureCode(comm, fail); // exits after printing "FAIL" 00233 } 00234 00235 // Test the Solution get methods that may be called by users 00236 // or migration functions. 00237 00238 if (solution->getLocalNumberOfIds() != size_t(numIdsPerProc)) 00239 fail = 11; 00240 00241 if (!fail){ 00242 const zgno_t *gids = solution->getIdList(); 00243 for (int i=0; !fail && i < numIdsPerProc; i++){ 00244 if (gids[i] != myGids[i]) 00245 fail = 12; 00246 } 00247 } 00248 00249 if (!fail){ 00250 const part_t *parts = solution->getPartList(); 00251 for (int i=0; !fail && i < numIdsPerProc; i++){ 00252 if (parts[i] != part_t(myGids[i] % numGlobalParts)) 00253 fail = 13; 00254 } 00255 } 00256 00257 gfail = globalFail(comm, fail); 00258 if (gfail){ 00259 printFailureCode(comm, fail); // exits after printing "FAIL" 00260 } 00261 00262 if (rank==0) 00263 std::cout << "PASS" << std::endl; 00264 00266 // TODO: 00268 // Create a solution object without part size information, and check it. 00270 // Test multiple weights. 00272 // Test multiple parts per process. 00274 // Specify a list of parts of size 0. (The rest should be uniform.) 00275 00276 delete [] lengths; 00277 for (int w=0; w < maxNumWeights; w++){ 00278 delete [] idLists[w]; 00279 delete [] sizeLists[w]; 00280 } 00281 delete [] idLists; 00282 delete [] sizeLists; 00283 }
1.7.6.1