Epetra Package Browser (Single Doxygen Collection) Development
test/BlockMap/cxx_main.cpp
Go to the documentation of this file.
00001 //@HEADER
00002 // ************************************************************************
00003 //
00004 //               Epetra: Linear Algebra Services Package
00005 //                 Copyright 2011 Sandia Corporation
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ************************************************************************
00040 //@HEADER
00041 
00042 
00043 // Epetra_BlockMap Test routine
00044 
00045 #include "Epetra_Time.h"
00046 #include "Epetra_BlockMap.h"
00047 #ifdef EPETRA_MPI
00048 #include "Epetra_MpiComm.h"
00049 #include <mpi.h>
00050 #endif
00051 #include "Epetra_SerialComm.h"
00052 #include "checkmap.h"
00053 #include "../epetra_test_err.h"
00054 #include "Epetra_Version.h"
00055 
00056 int main(int argc, char *argv[]) {
00057   bool verbose = false;
00058   // Check if we should print results to standard out
00059   if (argc > 1)
00060     if ((argv[1][0] == '-') && (argv[1][1] == 'v'))
00061       verbose = true;
00062 
00063   int i;
00064   int ierr = 0;
00065   int returnierr = 0;
00066 
00067 #ifdef EPETRA_MPI
00068 
00069   // Initialize MPI
00070   MPI_Init(&argc,&argv);
00071   Epetra_MpiComm Comm(MPI_COMM_WORLD);
00072 #else
00073   Epetra_SerialComm Comm;
00074 #endif
00075 
00076   if (!verbose) {
00077     Comm.SetTracebackMode(0); // This should shut down any error traceback reporting
00078   }
00079   int MyPID = Comm.MyPID();
00080   int NumProc = Comm.NumProc();
00081 
00082   int verbose_int = verbose ? 1 : 0;
00083   Comm.Broadcast(&verbose_int, 1, 0);
00084   verbose = verbose_int==1 ? true : false;
00085 
00086   if (verbose && MyPID==0)
00087     cout << Epetra_Version() << endl << endl;
00088 
00089   if (verbose) cout << Comm << endl << flush;
00090   Comm.Barrier();
00091   bool verbose1 = verbose;
00092   if (verbose) verbose = (MyPID==0);
00093 
00094   int NumMyElements = 10000;
00095   int NumGlobalElements = NumMyElements*NumProc+EPETRA_MIN(NumProc,3);
00096   if (MyPID < 3) NumMyElements++;
00097   int IndexBase = 0;
00098   int ElementSize = 7;
00099   bool DistributedGlobal = (NumGlobalElements>NumMyElements);
00100   bool IsOneToOne = true;
00101   Epetra_BlockMap * Map;
00102 
00103   // Test exceptions
00104 
00105   if (verbose)
00106     cout << "*******************************************************************************************" << endl
00107    << "        Testing Exceptions (Expect error messages if EPETRA_NO_ERROR_REPORTS is not defined" << endl
00108    << "*******************************************************************************************" << endl
00109    << endl << endl;
00110 
00111   try {
00112     if (verbose) cout << "Checking Epetra_BlockMap(-2, ElementSize, IndexBase, Comm)" << endl;
00113     Epetra_BlockMap TestMap(-2, ElementSize, IndexBase, Comm);
00114   }
00115   catch (int Error) {
00116     if (Error != -1) {
00117       if (Error != 0) {
00118         EPETRA_TEST_ERR(Error,returnierr);
00119         if (verbose) cout << "Error code should be -1" << endl;
00120       }
00121       else { // Error == 0
00122         cout << "Error code = " << Error << "Should be -1" << endl;
00123         returnierr += 1;
00124       }
00125     }
00126     else if (verbose) cout << "Checked OK\n\n" << endl;
00127   }
00128 
00129   try {
00130     if (verbose) cout << "Checking Epetra_BlockMap(2, 3, ElementSize, IndexBase, Comm)" << endl;
00131     Epetra_BlockMap TestMap(2, 3, ElementSize, IndexBase, Comm);
00132   }
00133   catch (int Error) {
00134     if (Error != -4) {
00135       if (Error != 0) {
00136         EPETRA_TEST_ERR(Error,returnierr);
00137         if (verbose) cout << "Error code should be -4" << endl;
00138       }
00139       else { // Error == 0
00140         cout << "Error code = " << Error << "Should be -4" << endl;
00141         returnierr += 1;
00142       }
00143     }
00144     else if (verbose) cout << "Checked OK\n\n" << endl;
00145   }
00146 
00147   if (verbose) cerr << flush;
00148   if (verbose) cout << flush;
00149   Comm.Barrier();
00150   if (verbose)
00151     cout << endl << endl
00152          << "*******************************************************************************************" << endl
00153          << "        Testing valid constructor now......................................................" << endl
00154          << "*******************************************************************************************" << endl
00155          << endl << endl;
00156   // Test Epetra-defined uniform linear distribution constructor
00157   Map = new Epetra_BlockMap(NumGlobalElements, ElementSize, IndexBase, Comm);
00158   if (verbose) cout << "Checking Epetra_BlockMap(NumGlobalElements, ElementSize, IndexBase, Comm)" << endl;
00159   ierr = checkmap(*Map, NumGlobalElements, NumMyElements, 0, ElementSize, 0,
00160       NumGlobalElements*ElementSize, NumMyElements*ElementSize,
00161       IndexBase, Comm, DistributedGlobal,IsOneToOne);
00162 
00163   EPETRA_TEST_ERR(ierr,returnierr);
00164   if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
00165 
00166   delete Map;
00167 
00168   // Test User-defined linear distribution constructor
00169   Map = new Epetra_BlockMap(NumGlobalElements, NumMyElements, ElementSize, IndexBase, Comm);
00170 
00171   if (verbose) cout << "Checking Epetra_BlockMap(NumGlobalElements, NumMyElements, ElementSize, IndexBase, Comm)" << endl;
00172   ierr = checkmap(*Map, NumGlobalElements, NumMyElements, 0, ElementSize, 0,
00173                    NumGlobalElements*ElementSize, NumMyElements*ElementSize,
00174       IndexBase, Comm, DistributedGlobal,IsOneToOne);
00175 
00176   EPETRA_TEST_ERR(ierr,returnierr);
00177   if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
00178 
00179   delete Map;
00180 
00181   // Test User-defined arbitrary distribution constructor and fill MyGlobalElements
00182   // such that the map is not one-to-one.
00183   int NumMyElems = 5;
00184   int NumGlobalElems = (Comm.NumProc()+1)*NumMyElems;
00185   int myFirstElem = Comm.MyPID()*NumMyElems;
00186   if (Comm.MyPID() == 0) NumMyElems *= 2;
00187 
00188   int* myElems = new int[NumMyElems];
00189   for(int ii=0; ii<NumMyElems; ++ii) {
00190     myElems[ii] = myFirstElem + ii;
00191   }
00192 
00193   Map = new Epetra_BlockMap(NumGlobalElems, NumMyElems, myElems, 1, 0, Comm);
00194 
00195   if (verbose) cout << "Checking non-oneToOne Epetra_BlockMap(...)"<<endl;
00196   ierr = Map->IsOneToOne() == false ? 0 : -1;
00197 
00198   //this Map is 1-to-1 if we're running on 1 processor, otherwise it
00199   //should not be 1-to-1.
00200   if (Comm.NumProc() > 1) {
00201     EPETRA_TEST_ERR(ierr,returnierr);
00202   }
00203   if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
00204 
00205   delete [] myElems;
00206   delete Map;
00207 
00208   // Test User-defined arbitrary distribution constructor
00209   // Generate Global Element List.  Do in reverse for fun!
00210 
00211   int * MyGlobalElements = new int[NumMyElements];
00212   int MaxMyGID = (Comm.MyPID()+1)*NumMyElements-1+IndexBase;
00213   if (Comm.MyPID()>2)
00214     MaxMyGID+=3;
00215   for (i = 0; i<NumMyElements; i++)
00216     MyGlobalElements[i] = MaxMyGID-i;
00217 
00218   Map = new Epetra_BlockMap(NumGlobalElements, NumMyElements, MyGlobalElements, ElementSize,
00219                             IndexBase, Comm);
00220 
00221   if (verbose) cout << "Checking Epetra_BlockMap(NumGlobalElements, NumMyElements, MyGlobalElements,  ElementSize, IndexBase, Comm)" << endl;
00222   ierr = checkmap(*Map, NumGlobalElements, NumMyElements, MyGlobalElements, ElementSize, 0,
00223                   NumGlobalElements*ElementSize, NumMyElements*ElementSize,
00224                   IndexBase, Comm, DistributedGlobal,IsOneToOne);
00225 
00226   EPETRA_TEST_ERR(ierr,returnierr);
00227   if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
00228 
00229   Epetra_BlockMap * Map3 = new Epetra_BlockMap(*Map);// A map to test the SameAs method later
00230 
00231   delete Map;
00232 
00233   int * ElementSizeList = new int[NumMyElements];
00234   int NumMyEquations = 0;
00235   int NumGlobalEquations = 0;
00236   for (i = 0; i<NumMyElements; i++) {
00237     ElementSizeList[i] = i%6 + 2; // elementsizes go from 2 to 7
00238     NumMyEquations += ElementSizeList[i];
00239   }
00240   ElementSize = 7; // Set to maximum for use in checkmap
00241   NumGlobalEquations = Comm.NumProc()*NumMyEquations;
00242   
00243   // Adjust NumGlobalEquations based on processor ID
00244   if (Comm.NumProc() > 3) {
00245     if (Comm.MyPID()>2)
00246       NumGlobalEquations += 3*((NumMyElements)%6+2);
00247     else
00248       NumGlobalEquations -= (Comm.NumProc()-3)*((NumMyElements-1)%6+2);
00249   }
00250   Map = new Epetra_BlockMap(NumGlobalElements, NumMyElements, MyGlobalElements, ElementSizeList,
00251                             IndexBase, Comm);
00252   if (verbose) cout << "Checking Epetra_BlockMap(NumGlobalElements, NumMyElements, MyGlobalElements,  ElementSizeList, IndexBase, Comm)" << endl;
00253   ierr = checkmap(*Map, NumGlobalElements, NumMyElements, MyGlobalElements, ElementSize, ElementSizeList,
00254       NumGlobalEquations, NumMyEquations,
00255       IndexBase, Comm, DistributedGlobal,IsOneToOne);
00256   
00257   EPETRA_TEST_ERR(ierr,returnierr);
00258   if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
00259 
00260   // Test Copy constructor
00261   Epetra_BlockMap * Map1 = new Epetra_BlockMap(*Map);
00262 
00263   // Test SameAs() method
00264   bool same = Map1->SameAs(*Map);
00265   EPETRA_TEST_ERR(!(same==true),returnierr);// should return true since Map1 is a copy of Map
00266 
00267   Epetra_BlockMap * Map2 = new Epetra_BlockMap(NumGlobalElements,NumMyElements,MyGlobalElements,ElementSizeList,IndexBase,Comm);
00268   same = Map2->SameAs(*Map);
00269   EPETRA_TEST_ERR(!(same==true),returnierr); // Map and Map2 were created with the same sets of parameters
00270   delete Map2;
00271 
00272   // now test SameAs() on some maps that are different
00273 
00274   Map2 = new Epetra_BlockMap(NumGlobalElements,NumMyElements,MyGlobalElements,ElementSizeList,IndexBase-1,Comm);
00275   same = Map2->SameAs(*Map);
00276   EPETRA_TEST_ERR(!(same==false),returnierr); // IndexBases are different
00277   delete Map2;
00278   
00279   int *ElementSizeList1 = new int[NumMyElements];
00280   for (i=0; i<NumMyElements; i++)
00281     ElementSizeList1[i] = i%5 + 2; // element sizes go from 2 to 6
00282   Map2 = new Epetra_BlockMap(NumGlobalElements,NumMyElements,MyGlobalElements,ElementSizeList1,IndexBase,Comm);
00283   same = Map2->SameAs(*Map);
00284   EPETRA_TEST_ERR(!(same==false),returnierr); // ElementSizes are different
00285   delete [] ElementSizeList1;
00286   delete Map2;
00287 
00288   same = Map3->SameAs(*Map);
00289   EPETRA_TEST_ERR(!(same==false),returnierr); // Map3 saved from an earlier test
00290   delete Map3;
00291 
00292   // Back to testing copy constructor
00293   if (verbose) cout << "Checking Epetra_BlockMap(*Map)" << endl;
00294   ierr = checkmap(*Map1, NumGlobalElements, NumMyElements, MyGlobalElements, ElementSize, ElementSizeList,
00295       NumGlobalEquations, NumMyEquations,
00296       IndexBase, Comm, DistributedGlobal,IsOneToOne);
00297 
00298   EPETRA_TEST_ERR(ierr,returnierr);
00299   if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
00300 
00301   if (verbose1) {
00302     if (verbose) cout << "Test ostream << operator" << endl << flush;
00303   }
00304     // Build a small map for test cout.  Use 10 elements from current map
00305     int * MyEls = Map->MyGlobalElements();
00306     int * MySz  = Map->ElementSizeList();
00307     int IndBase = Map->IndexBase();
00308     int MyLen = EPETRA_MIN(10+Comm.MyPID(),Map->NumMyElements());
00309     Epetra_BlockMap * SmallMap = new Epetra_BlockMap(-1, MyLen, MyEls, MySz, IndBase, Comm);
00310     if (verbose1) {
00311     cout << *SmallMap;
00312     }
00313     delete SmallMap;
00314 
00315   delete Map;
00316   delete Map1;
00317   
00318 
00319   //create a map where proc 1 has no local elements, then check to make sure that
00320   //if NumMyElements == 0, then MaxMyGID < MinMyGID.
00321 
00322   if (MyPID == 1) {
00323     Map1 = new Epetra_BlockMap(-1, 0, (int*)0, (int*)0, IndexBase, Comm);
00324   }
00325   else {
00326     Map1 = new Epetra_BlockMap(-1, NumMyElements, MyGlobalElements, ElementSizeList, IndexBase, Comm);
00327   }
00328 
00329   int numMyElems = Map1->NumMyElements();
00330   if (MyPID == 1) {
00331     EPETRA_TEST_ERR(!(numMyElems == 0), returnierr);
00332     int maxgid = Map1->MaxMyGID();
00333     int mingid = Map1->MinMyGID();
00334     EPETRA_TEST_ERR( !(maxgid<mingid), returnierr);
00335   }
00336 
00337   delete[] ElementSizeList;
00338   delete[] MyGlobalElements;
00339   delete Map1;
00340 
00341   // test reference counting
00342   ierr = 0;
00343 
00344   if (verbose)
00345     cout << endl << endl
00346    << "*******************************************************************************************" << endl
00347    << "        Testing reference counting now....................................................." << endl
00348    << "*******************************************************************************************" << endl << endl;
00349 
00350   Epetra_BlockMap b1(NumGlobalElements, NumMyElements, ElementSize, IndexBase, Comm);
00351   int b1count = b1.ReferenceCount();
00352   const Epetra_BlockMapData* b1addr = b1.DataPtr();
00353   EPETRA_TEST_ERR(!(b1count==1),ierr); // count should be 1
00354   if(verbose) cout << "Default constructor. \nb1= " << b1count << "  " << b1addr << endl;
00355   
00356   Epetra_BlockMap* b2 = new Epetra_BlockMap(b1);
00357   int b2count = b2->ReferenceCount();
00358   const Epetra_BlockMapData* b2addr = b2->DataPtr();
00359   int b1countold = b1count;
00360   b1count = b1.ReferenceCount();
00361   EPETRA_TEST_ERR(!(b2count==b1count && b1count==(b1countold+1)),ierr); // both counts should be 2
00362   EPETRA_TEST_ERR(!(b1addr==b2addr),ierr); // addresses should be same
00363   if(verbose) cout << "Copy constructor. \nb1= " << b1count << "  " << b1addr << "\nb2= " << b2count << "  " << b2addr << endl;
00364 
00365   delete b2;
00366   b1countold = b1count;
00367   b1count = b1.ReferenceCount();
00368   EPETRA_TEST_ERR(!(b1count==b1countold-1), ierr); // count should have decremented (to 1)
00369   EPETRA_TEST_ERR(!(b1addr==b1.DataPtr()), ierr); // b1addr should be unchanged
00370   if(verbose) cout << "b2 destroyed. \nb1= " << b1count << "  " << b1addr << endl;
00371 
00372   { // inside of braces to test stack deallocation.
00373     if(verbose) cout << "Assignment operator, post construction" << endl;
00374     Epetra_BlockMap b3(NumGlobalElements, NumMyElements, ElementSize, IndexBase-1, Comm);
00375     int b3count = b3.ReferenceCount();
00376     const Epetra_BlockMapData* b3addr = b3.DataPtr();
00377     EPETRA_TEST_ERR(!(b3count==1),ierr); // b3count should be 1 initially
00378     EPETRA_TEST_ERR(!(b1addr!=b3addr),ierr); // b1 and b3 should have different ptr addresses
00379     if(verbose) cout << "Prior to assignment: \nb1= " << b1count << "  " << b1addr << "\nb3= " << b3count << "  " << b3addr << endl;
00380     b3 = b1;
00381     b3count = b3.ReferenceCount();
00382     b3addr = b3.DataPtr();
00383     b1countold = b1count;
00384     b1count = b1.ReferenceCount();
00385     EPETRA_TEST_ERR(!(b3count==b1count && b1count==b1countold+1),ierr); // both counts should be 2
00386     EPETRA_TEST_ERR(!(b1addr==b3addr),ierr); // addresses should be same
00387     if(verbose) cout << "After assignment: \nb1= " << b1count << "  " << b1addr << "\nb3= " << b3count << "  " << b3addr << endl;
00388   }
00389   b1countold = b1count;
00390   b1count = b1.ReferenceCount();
00391   EPETRA_TEST_ERR(!(b1count==b1countold-1), ierr); // count should have decremented (to 1)
00392   EPETRA_TEST_ERR(!(b1addr==b1.DataPtr()), ierr); // b1addr should be unchanged
00393   if (verbose) cout << "b3 destroyed. \nb1= " << b1count << "  " << b1addr << endl;
00394 
00395   EPETRA_TEST_ERR(ierr,returnierr);
00396   if (verbose && (ierr == 0)) cout << "Checked OK\n\n" <<endl;
00397   // done with reference counting testing
00398 
00399   // test subcommunicators
00400   ierr=0;
00401   if (verbose)
00402     cout << endl << endl
00403    << "*******************************************************************************************" << endl
00404    << "        Testing subcommunicators now......................................................." << endl
00405    << "*******************************************************************************************" << endl << endl;
00406 
00407   // Create a map where everything is on proc 0
00408   if (MyPID != 0) {
00409     Map1 = new Epetra_BlockMap(-1, 0,  1, IndexBase, Comm);
00410   }
00411   else {
00412     Map1 = new Epetra_BlockMap(-1, NumMyElements, 1, IndexBase, Comm);
00413   }
00414 
00415   // Remove empty processes ...
00416   Map2=0; Map2 = Map1->RemoveEmptyProcesses();
00417   if(MyPID==0) {EPETRA_TEST_ERR(Map2 == 0,ierr);}
00418   else {EPETRA_TEST_ERR(Map2 != 0,ierr);}
00419 
00420   // Replace comm
00421   const Epetra_Comm * TempComm = Map2 ? &Map2->Comm() : 0;
00422   Map3=0; Map3 = Map1->ReplaceCommWithSubset(TempComm);
00423   if(MyPID==0) {EPETRA_TEST_ERR(Map3 == 0,ierr);}
00424   else {EPETRA_TEST_ERR(Map3 != 0,ierr);}
00425 
00426   delete Map1;  delete Map2;  delete Map3;
00427 
00428   EPETRA_TEST_ERR(ierr,returnierr);
00429   if (verbose && (ierr == 0)) cout << "Checked OK\n\n" <<endl;
00430  // done with testing subcommunicators
00431 
00432 #ifdef EPETRA_MPI
00433   MPI_Finalize();
00434 #endif
00435 
00436   return returnierr;
00437 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines