Zoltan2 Version of the Day
PartitioningSolution.cpp
Go to the documentation of this file.
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_BasicIdentifierInput.hpp>
00055 #include <Zoltan2_TestHelpers.hpp>
00056 
00057 typedef Zoltan2::BasicUserTypes<scalar_t, gno_t, lno_t, gno_t> user_t;
00058 typedef Zoltan2::BasicIdentifierInput<user_t> idInput_t;
00059 
00060 using Teuchos::ArrayRCP;
00061 using Teuchos::Array;
00062 using Teuchos::RCP;
00063 using Teuchos::rcp;
00064 using Teuchos::arcp;
00065 
00066 
00067 typedef zoltan2_partId_t partId_t;
00068 
00069 void makeArrays(int wdim, int *lens, partId_t **ids, scalar_t **sizes,
00070   ArrayRCP<ArrayRCP<partId_t> > &idList, ArrayRCP<ArrayRCP<scalar_t> > &sizeList)
00071 {
00072   ArrayRCP<partId_t> *idArrays = new ArrayRCP<partId_t> [wdim];
00073   ArrayRCP<scalar_t> *sizeArrays = new ArrayRCP<scalar_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 dimension.
00095 
00096   int numIdsPerProc = 10;
00097   int maxWeightDim = 3;
00098   int maxNumPartSizes = nprocs;
00099   int *lengths = new int [maxWeightDim];
00100   partId_t **idLists = new partId_t * [maxWeightDim];
00101   scalar_t **sizeLists = new scalar_t * [maxWeightDim];
00102 
00103   for (int w=0; w < maxWeightDim; w++){
00104     idLists[w] = new partId_t [maxNumPartSizes];
00105     sizeLists[w] = new scalar_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   gno_t *myGids = new gno_t [numIdsPerProc];
00116   for (int i=0, x=rank*numIdsPerProc; i < numIdsPerProc; i++){
00117     myGids[i] = x++;
00118   }
00119 
00120   ArrayRCP<const gno_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 dimension, one part per proc.
00128   // Some part sizes are 2 and some are 1.
00129 
00130   int numGlobalParts = nprocs;
00131   int weightDim = 1;
00132 
00133   ArrayRCP<ArrayRCP<partId_t> > ids;
00134   ArrayRCP<ArrayRCP<scalar_t> > sizes;
00135 
00136   memset(lengths, 0, sizeof(int) * maxWeightDim);
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   scalar_t *normalizedPartSizes = new scalar_t [numGlobalParts];
00147   scalar_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       weightDim,                  // weight dimension
00167       ids.view(0,weightDim),      // part ids
00168       sizes.view(0,weightDim))); // 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       scalar_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   partId_t *partAssignments = new partId_t [numIdsPerProc];
00218   for (int i=0; i < numIdsPerProc; i++){
00219     partAssignments[i] = myGids[i] % numGlobalParts;  // round robin
00220   }
00221   ArrayRCP<partId_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 gno_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 partId_t *parts = solution->getPartList();
00251     for (int i=0; !fail && i < numIdsPerProc; i++){
00252       if (parts[i] != 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 < maxWeightDim; w++){
00278     delete [] idLists[w];
00279     delete [] sizeLists[w];
00280   }
00281   delete [] idLists;
00282   delete [] sizeLists;
00283 }