All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
Xpetra_EpetraMap.cpp
Go to the documentation of this file.
00001 // @HEADER
00002 //
00003 // ***********************************************************************
00004 //
00005 //             Xpetra: A linear algebra interface package
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
00039 //                    Jeremie Gaidamour (jngaida@sandia.gov)
00040 //                    Jonathan Hu       (jhu@sandia.gov)
00041 //                    Ray Tuminaro      (rstumin@sandia.gov)
00042 //
00043 // ***********************************************************************
00044 //
00045 // @HEADER
00046 #include "Xpetra_ConfigDefs.hpp"
00047 
00048 #ifdef HAVE_XPETRA_EPETRA
00049 
00050 #include "Xpetra_EpetraMap.hpp"
00051 #include "Xpetra_EpetraUtils.hpp"
00052 
00053 #include "Xpetra_EpetraExceptions.hpp"
00054 
00055 namespace Xpetra {
00056 
00057   // Implementation note for constructors: the Epetra_Comm is cloned in the constructor of Epetra_BlockMap. We don't need to keep a reference on it.
00058   // TODO: use toEpetra() function here.
00059   EpetraMap::EpetraMap(global_size_t numGlobalElements, int indexBase, const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
00060                        LocalGlobal lg, const Teuchos::RCP<Node> &node)
00061   {
00062     // This test come from Tpetra (Epetra doesn't check if numGlobalElements,indexBase are equivalent across images).
00063     // In addition, for the test TEST_THROW(M map((myImageID == 0 ? GSTI : 0),0,comm), std::invalid_argument), only one node throw an exception and there is a dead lock.
00064     std::string errPrefix;
00065     errPrefix = Teuchos::typeName(*this) + "::constructor(numGlobal,indexBase,comm,lOrG): ";
00066      
00067     if (lg == GloballyDistributed) {
00068       const int myImageID = comm->getRank();
00069        
00070       // check that numGlobalElements,indexBase is equivalent across images
00071       global_size_t rootNGE = numGlobalElements;
00072       int rootIB  = indexBase;
00073       Teuchos::broadcast<int,global_size_t>(*comm,0,&rootNGE);
00074       Teuchos::broadcast<int,int>(*comm,0,&rootIB);
00075       int localChecks[2], globalChecks[2];
00076       localChecks[0] = -1;   // fail or pass
00077       localChecks[1] = 0;    // fail reason
00078       if (numGlobalElements != rootNGE) {
00079         localChecks[0] = myImageID;
00080         localChecks[1] = 1;
00081       }
00082       else if (indexBase != rootIB) {
00083         localChecks[0] = myImageID;
00084         localChecks[1] = 2;
00085       }
00086       // REDUCE_MAX will give us the image ID of the highest rank proc that DID NOT pass, as well as the reason
00087       // these will be -1 and 0 if all procs passed
00088       Teuchos::reduceAll<int,int>(*comm,Teuchos::REDUCE_MAX,2,localChecks,globalChecks);
00089       if (globalChecks[0] != -1) {
00090         if (globalChecks[1] == 1) {
00091           TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument,
00092                              errPrefix << "numGlobal must be the same on all nodes (examine node " << globalChecks[0] << ").");
00093         }
00094         else if (globalChecks[1] == 2) {
00095           TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument,
00096                              errPrefix << "indexBase must be the same on all nodes (examine node " << globalChecks[0] << ").");
00097         }
00098         else {
00099           // logic error on our part
00100           TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
00101                              errPrefix << "logic error. Please contact the Tpetra team.");
00102         }
00103       }
00104     }
00105      
00106     // Note: validity of numGlobalElements checked by Epetra.
00107 
00108     IF_EPETRA_EXCEPTION_THEN_THROW_GLOBAL_INVALID_ARG((map_ = (rcp(new Epetra_BlockMap(static_cast<int>(numGlobalElements), 1, indexBase, *toEpetra(comm))))));
00109   }
00110 
00111   EpetraMap::EpetraMap(global_size_t numGlobalElements, size_t numLocalElements, int indexBase,
00112                        const Teuchos::RCP<const Teuchos::Comm<int> > &comm, const Teuchos::RCP<Node> &node)
00113   {
00114     // This test come from Tpetra
00115     using Teuchos::outArg;
00116 
00117     const size_t  L0 = Teuchos::OrdinalTraits<size_t>::zero();
00118     const size_t  L1 = Teuchos::OrdinalTraits<size_t>::one();
00119     const global_size_t GST0 = Teuchos::OrdinalTraits<global_size_t>::zero();
00120     const global_size_t GST1 = Teuchos::OrdinalTraits<global_size_t>::one();
00121     const global_size_t GSTI = Teuchos::OrdinalTraits<global_size_t>::invalid();
00122 
00123     std::string errPrefix;
00124     errPrefix = Teuchos::typeName(*this) + "::constructor(numGlobal,numLocal,indexBase,platform): ";
00125      
00126     // get a internodal communicator from the Platform
00127     const int myImageID = comm->getRank();
00128      
00129     global_size_t global_sum;
00130     { // begin scoping block
00131       // for communicating failures
00132       int localChecks[2], globalChecks[2];
00133       /* compute the global size
00134          we are computing the number of global elements because exactly ONE of the following is true:
00135          - the user didn't specify it, and we need it
00136          - the user did specify it, but we need to
00137          + validate it against the sum of the local sizes, and
00138          + ensure that it is the same on all nodes
00139       */
00140       Teuchos::reduceAll<int,global_size_t>(*comm,Teuchos::REDUCE_SUM,
00141                                             Teuchos::as<global_size_t>(numLocalElements),outArg(global_sum));
00142       /* there are three errors we should be detecting:
00143          - numGlobalElements != invalid() and it is incorrect/invalid
00144          - numLocalElements invalid (<0)
00145       */
00146       localChecks[0] = -1;
00147       localChecks[1] = 0;
00148       if (numLocalElements < L1 && numLocalElements != L0) {
00149         // invalid
00150         localChecks[0] = myImageID;
00151         localChecks[1] = 1;
00152       }
00153       else if (numGlobalElements < GST1 && numGlobalElements != GST0 && numGlobalElements != GSTI) {
00154         // invalid
00155         localChecks[0] = myImageID;
00156         localChecks[1] = 2;
00157       }
00158       else if (numGlobalElements != GSTI && numGlobalElements != global_sum) {
00159         // incorrect
00160         localChecks[0] = myImageID;
00161         localChecks[1] = 3;
00162       }
00163       // now check that indexBase is equivalent across images
00164       int rootIB = indexBase;
00165       Teuchos::broadcast<int,int>(*comm,0,&rootIB);   // broadcast one ordinal from node 0
00166       if (indexBase != rootIB) {
00167         localChecks[0] = myImageID;
00168         localChecks[1] = 4;
00169       }
00170       // REDUCE_MAX will give us the image ID of the highest rank proc that DID NOT pass
00171       // this will be -1 if all procs passed
00172       Teuchos::reduceAll<int,int>(*comm,Teuchos::REDUCE_MAX,2,localChecks,globalChecks);
00173       if (globalChecks[0] != -1) {
00174         if (globalChecks[1] == 1) {
00175           TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument,
00176                              errPrefix << "numLocal is not valid on at least one node (possibly node "
00177                              << globalChecks[0] << ").");
00178         }
00179         else if (globalChecks[1] == 2) {
00180           TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument,
00181                              errPrefix << "numGlobal is not valid on at least one node (possibly node "
00182                              << globalChecks[0] << ").");
00183         }
00184         else if (globalChecks[1] == 3) {
00185           TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument,
00186                              errPrefix << "numGlobal doesn't match sum of numLocal (== "
00187                              << global_sum << ") on at least one node (possibly node "
00188                              << globalChecks[0] << ").");
00189         }
00190         else if (globalChecks[1] == 4) {
00191           TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument,
00192                              errPrefix << "indexBase is not the same on all nodes (examine node "
00193                              << globalChecks[0] << ").");
00194         }
00195         else {
00196           // logic error on my part
00197           TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
00198                              errPrefix << "logic error. Please contact the Tpetra team.");
00199         }
00200       }
00201        
00202     }
00203 
00204     // set numGlobalElements
00205     if (numGlobalElements == GSTI) {
00206       numGlobalElements = global_sum;}
00207 
00208     IF_EPETRA_EXCEPTION_THEN_THROW_GLOBAL_INVALID_ARG((map_ = (rcp(new Epetra_BlockMap(static_cast<int>(numGlobalElements), numLocalElements, 1, indexBase, *toEpetra(comm))))));
00209   }
00210        
00211   // TODO: UnitTest FAILED
00212   EpetraMap::EpetraMap(global_size_t numGlobalElements, const Teuchos::ArrayView<const int> &elementList, int indexBase,
00213                        const Teuchos::RCP<const Teuchos::Comm<int> > &comm, const Teuchos::RCP<Node> &node)
00214   {
00215     if (numGlobalElements == Teuchos::OrdinalTraits<global_size_t>::invalid()) {
00216       IF_EPETRA_EXCEPTION_THEN_THROW_GLOBAL_INVALID_ARG((map_ = (rcp(new Epetra_BlockMap(-1, elementList.size(), elementList.getRawPtr(), 1, indexBase, *toEpetra(comm))))));
00217     } else {
00218       IF_EPETRA_EXCEPTION_THEN_THROW_GLOBAL_INVALID_ARG((map_ = (rcp(new Epetra_BlockMap(numGlobalElements, elementList.size(), elementList.getRawPtr(), 1, indexBase, *toEpetra(comm))))));
00219     }
00220   }
00221    
00222 
00223 
00224 
00225 
00226 
00227 
00228   LookupStatus EpetraMap::getRemoteIndexList(const Teuchos::ArrayView< const GlobalOrdinal > &GIDList, const Teuchos::ArrayView< int > &nodeIDList, const Teuchos::ArrayView< int > &LIDList) const { XPETRA_MONITOR("EpetraMap::getRemoteIndexList"); return toXpetra(map_->RemoteIDList(GIDList.size(), GIDList.getRawPtr(), nodeIDList.getRawPtr(), LIDList.getRawPtr())); }
00229     
00230   LookupStatus EpetraMap::getRemoteIndexList(const Teuchos::ArrayView< const int > &GIDList, const Teuchos::ArrayView< int > &nodeIDList) const { XPETRA_MONITOR("EpetraMap::getRemoteIndexList"); return toXpetra(map_->RemoteIDList(GIDList.size(), GIDList.getRawPtr(), nodeIDList.getRawPtr(), 0)); }
00231     
00232   Teuchos::ArrayView< const int > EpetraMap::getNodeElementList() const { XPETRA_MONITOR("EpetraMap::getNodeElementList"); return ArrayView< const int >(map_->MyGlobalElements(), map_->NumMyElements()); /* Note: this method return a const array, so it is safe to use directly the internal array. */ }
00233 
00234   //typedef Kokkos::DefaultNode::DefaultNodeType Node;
00235   const Teuchos::RCP<Kokkos::DefaultNode::DefaultNodeType> EpetraMap::getNode() const { XPETRA_MONITOR("EpetraMap::getNode"); return Kokkos::DefaultNode::getDefaultNode(); } //removed &
00236 
00237 
00238 
00239 
00240 
00241 
00242   std::string EpetraMap::description() const {
00243     XPETRA_MONITOR("EpetraMap::description"); 
00244 
00245     // This implementation come from Tpetra_Map_def.hpp (without modification)
00246     std::ostringstream oss;
00247     oss << Teuchos::Describable::description();
00248     oss << "{getGlobalNumElements() = " << getGlobalNumElements()
00249         << ", getNodeNumElements() = " << getNodeNumElements()
00250         << ", isContiguous() = " << isContiguous()
00251         << ", isDistributed() = " << isDistributed()
00252         << "}";
00253     return oss.str();
00254   }
00255 
00256   void EpetraMap::describe( Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const {
00257     XPETRA_MONITOR("EpetraMap::describe"); 
00258           
00259     const Teuchos::RCP<const Teuchos::Comm<int> > comm_ = getComm();
00260 
00261     // This implementation come from Tpetra_Map_def.hpp (without modification)
00262     using std::endl;
00263     using std::setw;
00264     using Teuchos::VERB_DEFAULT;
00265     using Teuchos::VERB_NONE;
00266     using Teuchos::VERB_LOW;
00267     using Teuchos::VERB_MEDIUM;
00268     using Teuchos::VERB_HIGH;
00269     using Teuchos::VERB_EXTREME;
00270      
00271     const size_t nME = getNodeNumElements();
00272     Teuchos::ArrayView<const int> myEntries = getNodeElementList();
00273     int myImageID = comm_->getRank();
00274     int numImages = comm_->getSize();
00275      
00276     Teuchos::EVerbosityLevel vl = verbLevel;
00277     if (vl == VERB_DEFAULT) vl = VERB_LOW;
00278      
00279     size_t width = 1;
00280     for (size_t dec=10; dec<getGlobalNumElements(); dec *= 10) {
00281       ++width;
00282     }
00283     width = std::max<size_t>(width,12) + 2;
00284      
00285     Teuchos::OSTab tab(out);
00286      
00287     if (vl == VERB_NONE) {
00288       // do nothing
00289     }
00290     else if (vl == VERB_LOW) {
00291       out << this->description() << endl;
00292     }
00293     else {  // MEDIUM, HIGH or EXTREME
00294       for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
00295         if (myImageID == imageCtr) {
00296           if (myImageID == 0) { // this is the root node (only output this info once)
00297             out << endl
00298                 << "Number of Global Entries = " << getGlobalNumElements()  << endl
00299                 << "Maximum of all GIDs      = " << getMaxAllGlobalIndex() << endl
00300                 << "Minimum of all GIDs      = " << getMinAllGlobalIndex() << endl
00301                 << "Index Base               = " << getIndexBase()         << endl;
00302           }
00303           out << endl;
00304           if (vl == VERB_HIGH || vl == VERB_EXTREME) {
00305             out << "Number of Local Elements   = " << nME           << endl
00306                 << "Maximum of my GIDs         = " << getMaxGlobalIndex() << endl
00307                 << "Minimum of my GIDs         = " << getMinGlobalIndex() << endl;
00308             out << endl;
00309           }
00310           if (vl == VERB_EXTREME) {
00311             out << std::setw(width) << "Node ID"
00312                 << std::setw(width) << "Local Index"
00313                 << std::setw(width) << "Global Index"
00314                 << endl;
00315             for (size_t i=0; i < nME; i++) {
00316               out << std::setw(width) << myImageID
00317                   << std::setw(width) << i
00318                   << std::setw(width) << myEntries[i]
00319                   << endl;
00320             }
00321             out << std::flush;
00322           }
00323         }
00324         // Do a few global ops to give I/O a chance to complete
00325         comm_->barrier();
00326         comm_->barrier();
00327         comm_->barrier();
00328       }
00329     }
00330   }
00331 
00332 
00333 
00334 
00335 
00336   const Epetra_Map & toEpetra(const Map<int,int> &map) {
00337     // TODO: throw exception
00338     const EpetraMap & epetraMap = dynamic_cast<const EpetraMap &>(map);
00339     return epetraMap.getEpetra_Map();
00340   }
00341 
00342   const Epetra_Map & toEpetra(const RCP< const Map<int, int> > &map) {
00343     XPETRA_RCP_DYNAMIC_CAST(const EpetraMap, map, epetraMap, "toEpetra");
00344     return epetraMap->getEpetra_Map();
00345   }
00346 
00347 //   const RCP< const Map<int, int> > toXpetra(const RCP< const Epetra_Map > &map) {
00348 //     return rcp( new EpetraMap(map) );
00349 //   }
00350 
00351   const RCP< const Map<int, int> > toXpetra(const Epetra_BlockMap &map) {
00352     RCP<const Epetra_BlockMap> m = rcp(new Epetra_BlockMap(map));
00353     return rcp( new EpetraMap(m) );
00354   }
00355   //
00356 
00357 }
00358 
00359 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines