|
Tpetra Matrix/Vector Services
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Tpetra: Templated Linear Algebra Services Package 00005 // Copyright (2008) 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 #ifndef TPETRA_DIRECTORY_HPP 00043 #define TPETRA_DIRECTORY_HPP 00044 00045 #include <Teuchos_as.hpp> 00046 #include <Tpetra_ConfigDefs.hpp> 00047 #include <Tpetra_Distributor.hpp> 00048 #include <Tpetra_Map.hpp> 00049 #include <Tpetra_DirectoryImpl.hpp> 00050 #include <Tpetra_DirectoryImpl_def.hpp> 00051 00052 #ifdef DOXYGEN_USE_ONLY 00053 # include "Tpetra_Directory_decl.hpp" 00054 #endif 00055 00056 namespace Tpetra { 00057 00058 template<class LO, class GO, class NT> 00059 Directory<LO, GO, NT>::Directory () : 00060 impl_ (NULL) 00061 {} 00062 00063 template<class LO, class GO, class NT> 00064 TEUCHOS_DEPRECATED 00065 Directory<LO, GO, NT>::Directory (const Map<LO, GO, NT>& /* map */) : 00066 impl_ (NULL) 00067 { 00068 TEUCHOS_TEST_FOR_EXCEPTION( 00069 true, std::logic_error, "Tpetra::Directory: All constructors other than " 00070 "the default (zero-argument) constructor have been deprecated. All " 00071 "initialization takes place in initialize."); 00072 } 00073 00074 template<class LO, class GO, class NT> 00075 TEUCHOS_DEPRECATED 00076 Directory<LO, GO, NT>:: 00077 Directory (const Teuchos::RCP<const Map<LO, GO, NT> >& /* mapPtr */) : 00078 impl_ (NULL) 00079 { 00080 TEUCHOS_TEST_FOR_EXCEPTION( 00081 true, std::logic_error, "Tpetra::Directory: All constructors other than " 00082 "the default (zero-argument) constructor have been deprecated. All " 00083 "initialization takes place in initialize."); 00084 } 00085 00086 template<class LO, class GO, class NT> 00087 TEUCHOS_DEPRECATED 00088 Directory<LO, GO, NT>:: 00089 Directory (const Map<LO, GO, NT>& /* map */, 00090 const Tpetra::Details::TieBreak<LO,GO>& /* tieBreak */) : 00091 impl_ (NULL) 00092 { 00093 TEUCHOS_TEST_FOR_EXCEPTION( 00094 true, std::logic_error, "Tpetra::Directory: All constructors other than " 00095 "the default (zero-argument) constructor have been deprecated. All " 00096 "initialization takes place in initialize. You may provide an optional " 00097 "TieBreak object there if you like."); 00098 } 00099 00100 template<class LO, class GO, class NT> 00101 Directory<LO, GO, NT>::~Directory () { 00102 if (impl_ != NULL) { 00103 delete impl_; 00104 impl_ = NULL; 00105 } 00106 } 00107 00108 template<class LO, class GO, class NT> 00109 bool 00110 Directory<LO, GO, NT>::initialized () const { 00111 return impl_ != NULL; 00112 } 00113 00114 00115 template<class LO, class GO, class NT> 00116 void 00117 Directory<LO, GO, NT>:: 00118 initialize (const Map<LO, GO, NT>& map, 00119 const Tpetra::Details::TieBreak<LO,GO>& tieBreak) 00120 { 00121 if (initialized ()) { 00122 TEUCHOS_TEST_FOR_EXCEPTION( 00123 impl_ == NULL, std::logic_error, "Tpetra::Directory::initialize: " 00124 "The Directory claims that it has been initialized, " 00125 "but its implementation object has not yet been created. " 00126 "Please report this bug to the Tpetra developers."); 00127 } 00128 else { 00129 TEUCHOS_TEST_FOR_EXCEPTION( 00130 impl_ != NULL, std::logic_error, "Tpetra::Directory::initialize: " 00131 "Directory implementation has already been initialized, " 00132 "but initialized() returns false. " 00133 "Please report this bug to the Tpetra developers."); 00134 00135 // Create an implementation object of the appropriate type, 00136 // depending on whether the Map is distributed or replicated, 00137 // and contiguous or noncontiguous. 00138 // 00139 // mfh 06 Apr 2014: When a distributed noncontiguous Directory 00140 // takes a TieBreak, all the entries (local indices and process 00141 // ranks) owned by the Directory on the calling process pass 00142 // through the TieBreak object. This may have side effects, 00143 // such as the TieBreak object remembering whether there were 00144 // any duplicates on the calling process. We want to extend use 00145 // of a TieBreak object to other kinds of Directories. For a 00146 // distributed contiguous Directory, the calling process owns 00147 // all of the (PID,LID) pairs in the input Map. For a locally 00148 // replicated contiguous Directory, Process 0 owns all of the 00149 // (PID,LID) pairs in the input Map. 00150 // 00151 // It may seem silly to pass in a TieBreak when there are no 00152 // ties to break. However, the TieBreak object gets to see all 00153 // (PID,LID) pairs that the Directory owns on the calling 00154 // process, and interface of TieBreak allows side effects. 00155 // Users may wish to exploit them regardless of the kind of Map 00156 // they pass in. 00157 const Details::Directory<LO, GO, NT>* dir = NULL; 00158 bool usedTieBreak = false; 00159 if (map.isDistributed ()) { 00160 if (map.isUniform ()) { 00161 dir = new Details::ContiguousUniformDirectory<LO, GO, NT> (map); 00162 } 00163 else if (map.isContiguous ()) { 00164 dir = new Details::DistributedContiguousDirectory<LO, GO, NT> (map); 00165 } 00166 else { 00167 dir = new Details::DistributedNoncontiguousDirectory<LO, GO, NT> (map, tieBreak); 00168 usedTieBreak = true; 00169 } 00170 } 00171 else { 00172 dir = new Details::ReplicatedDirectory<LO, GO, NT> (map); 00173 00174 if (tieBreak.mayHaveSideEffects () && map.getNodeNumElements () != 0) { 00175 // We need the second clause in the above test because Map's 00176 // interface provides an inclusive range of local indices. 00177 const int myRank = map.getComm ()->getRank (); 00178 // In a replicated Directory, Process 0 owns all the 00179 // Directory's entries. This is an arbitrary assignment; any 00180 // one process would do. 00181 if (myRank == 0) { 00182 std::vector<std::pair<int, LO> > pidLidList (1); 00183 const LO minLocInd = map.getMinLocalIndex (); 00184 const LO maxLocInd = map.getMaxLocalIndex (); 00185 for (LO locInd = minLocInd; locInd <= maxLocInd; ++locInd) { 00186 pidLidList[0] = std::make_pair (myRank, locInd); 00187 const GO globInd = map.getGlobalElement (locInd); 00188 // We don't care about the return value; we just want to 00189 // invoke the side effects. 00190 (void) tieBreak.selectedIndex (globInd, pidLidList); 00191 } 00192 } 00193 } 00194 usedTieBreak = true; 00195 } // done with all different Map cases 00196 00197 // If we haven't already used the TieBreak object, use it now. 00198 // This code appears twice because ReplicatedDirectory is a 00199 // special case: we already know what gets replicated. 00200 if (! usedTieBreak && tieBreak.mayHaveSideEffects () && 00201 map.getNodeNumElements () != 0) { 00202 // We need the third clause in the above test because Map's 00203 // interface provides an inclusive range of local indices. 00204 std::vector<std::pair<int, LO> > pidLidList (1); 00205 const LO minLocInd = map.getMinLocalIndex (); 00206 const LO maxLocInd = map.getMaxLocalIndex (); 00207 const int myRank = map.getComm ()->getRank (); 00208 for (LO locInd = minLocInd; locInd <= maxLocInd; ++locInd) { 00209 pidLidList[0] = std::make_pair (myRank, locInd); 00210 const GO globInd = map.getGlobalElement (locInd); 00211 // We don't care about the return value; we just want to 00212 // invoke the side effects. 00213 (void) tieBreak.selectedIndex (globInd, pidLidList); 00214 } 00215 } 00216 00217 impl_ = dir; 00218 } 00219 } 00220 00221 template<class LO, class GO, class NT> 00222 void 00223 Directory<LO, GO, NT>::initialize (const Map<LO, GO, NT>& map) 00224 { 00225 if (initialized ()) { 00226 TEUCHOS_TEST_FOR_EXCEPTION( 00227 impl_ == NULL, std::logic_error, "Tpetra::Directory::initialize: " 00228 "The Directory claims that it has been initialized, " 00229 "but its implementation object has not yet been created. " 00230 "Please report this bug to the Tpetra developers."); 00231 } 00232 else { 00233 TEUCHOS_TEST_FOR_EXCEPTION( 00234 impl_ != NULL, std::logic_error, "Tpetra::Directory::initialize: " 00235 "Directory implementation has already been initialized, " 00236 "but initialized() returns false. " 00237 "Please report this bug to the Tpetra developers."); 00238 00239 // Create an implementation object of the appropriate type, 00240 // depending on whether the Map is distributed or replicated, 00241 // and contiguous or noncontiguous. 00242 const Details::Directory<LO, GO, NT>* dir = NULL; 00243 if (map.isDistributed ()) { 00244 if (map.isUniform ()) { 00245 dir = new Details::ContiguousUniformDirectory<LO, GO, NT> (map); 00246 } 00247 else if (map.isContiguous ()) { 00248 dir = new Details::DistributedContiguousDirectory<LO, GO, NT> (map); 00249 } 00250 else { 00251 dir = new Details::DistributedNoncontiguousDirectory<LO, GO, NT> (map); 00252 } 00253 } 00254 else { 00255 dir = new Details::ReplicatedDirectory<LO, GO, NT> (map); 00256 } 00257 TEUCHOS_TEST_FOR_EXCEPTION( 00258 dir == NULL, std::logic_error, "Tpetra::Directory::initialize: " 00259 "Failed to create Directory implementation. " 00260 "Please report this bug to the Tpetra developers."); 00261 impl_ = dir; 00262 } 00263 } 00264 00265 template<class LO, class GO, class NT> 00266 LookupStatus 00267 Directory<LO, GO, NT>:: 00268 getDirectoryEntries (const Map<LO, GO, NT>& map, 00269 const Teuchos::ArrayView<const GO>& globalIDs, 00270 const Teuchos::ArrayView<int>& nodeIDs) const 00271 { 00272 if (! initialized ()) { 00273 // This const_cast is super wrong, but "mutable" is also a lie, 00274 // and Map's interface needs this method to be marked const for 00275 // some reason. 00276 const_cast<Directory<LO, GO, NT>* > (this)->initialize (map); 00277 } 00278 const bool computeLIDs = false; 00279 return impl_->getEntries (map, globalIDs, nodeIDs, Teuchos::null, computeLIDs); 00280 } 00281 00282 00283 template<class LO, class GO, class NT> 00284 LookupStatus TEUCHOS_DEPRECATED 00285 Directory<LO, GO, NT>:: 00286 getDirectoryEntries (const Teuchos::ArrayView<const GO>& globalIDs, 00287 const Teuchos::ArrayView<int>& nodeIDs) const 00288 { 00289 TEUCHOS_TEST_FOR_EXCEPTION( 00290 true, std::logic_error, "This method is DEPRECATED. Please call the " 00291 "three-argument version of getDirectoryEntries that takes a Map, an " 00292 "ArrayView<const GO>, and an ArrayView<int>."); 00293 } 00294 00295 template<class LO, class GO, class NT> 00296 LookupStatus 00297 Directory<LO, GO, NT>:: 00298 getDirectoryEntries (const Map<LO, GO, NT>& map, 00299 const Teuchos::ArrayView<const GO>& globalIDs, 00300 const Teuchos::ArrayView<int>& nodeIDs, 00301 const Teuchos::ArrayView<LO>& localIDs) const 00302 { 00303 if (! initialized ()) { 00304 // This const_cast is super wrong, but "mutable" is also a lie, 00305 // and Map's interface needs this method to be marked const for 00306 // some reason. 00307 const_cast<Directory<LO, GO, NT>* > (this)->initialize (map); 00308 } 00309 const bool computeLIDs = true; 00310 return impl_->getEntries (map, globalIDs, nodeIDs, localIDs, computeLIDs); 00311 } 00312 00313 template<class LO, class GO, class NT> 00314 LookupStatus TEUCHOS_DEPRECATED 00315 Directory<LO, GO, NT>:: 00316 getDirectoryEntries (const Teuchos::ArrayView<const GO>& globalIDs, 00317 const Teuchos::ArrayView<int>& nodeIDs, 00318 const Teuchos::ArrayView<LO>& localIDs) const 00319 { 00320 TEUCHOS_TEST_FOR_EXCEPTION( 00321 true, std::logic_error, "This method is DEPRECATED. Please call the " 00322 "four-argument version of getDirectoryEntries that takes a Map, an " 00323 "ArrayView<const GO>, an ArrayView<int>, and an ArrayView<LO>."); 00324 } 00325 00326 template<class LO, class GO, class NT> 00327 bool Directory<LO, GO, NT>::isOneToOne (const Map<LO, GO, NT>& map) const { 00328 if (! initialized ()) { 00329 // This const_cast is super wrong, but "mutable" is also a lie, 00330 // and Map's interface needs this method to be marked const for 00331 // some reason. 00332 const_cast<Directory<LO, GO, NT>* > (this)->initialize (map); 00333 } 00334 return impl_->isOneToOne (* (map.getComm ())); 00335 } 00336 00337 template<class LO, class GO, class NT> 00338 std::string 00339 Directory<LO, GO, NT>::description () const 00340 { 00341 using Teuchos::TypeNameTraits; 00342 00343 std::ostringstream os; 00344 os << "Directory" 00345 << "<" << TypeNameTraits<LO>::name () 00346 << ", " << TypeNameTraits<GO>::name () 00347 << ", " << TypeNameTraits<NT>::name () << ">"; 00348 return os.str (); 00349 } 00350 00351 } // namespace Tpetra 00352 00353 // 00354 // Explicit instantiation macro 00355 // 00356 // Must be expanded from within the Tpetra namespace! 00357 // 00358 00359 #define TPETRA_DIRECTORY_INSTANT(LO,GO,NODE) \ 00360 \ 00361 template class Directory< LO , GO , NODE >; \ 00362 00363 #endif // TPETRA_DIRECTORY_HPP
1.7.6.1