|
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_EXPORT_DEF_HPP 00043 #define TPETRA_EXPORT_DEF_HPP 00044 00045 #ifdef DOXYGEN_USE_ONLY 00046 # include <Tpetra_Export_decl.hpp> 00047 #endif // DOXYGEN_USE_ONLY 00048 00049 #include <Tpetra_Distributor.hpp> 00050 #include <Tpetra_Map.hpp> 00051 #include <Tpetra_ImportExportData.hpp> 00052 #include <Tpetra_Util.hpp> 00053 #include <Tpetra_Import.hpp> 00054 #include <Teuchos_as.hpp> 00055 00056 namespace { 00057 // Default value of Export's "Debug" parameter. 00058 const bool tpetraExportDebugDefault = false; 00059 } // namespace (anonymous) 00060 00061 namespace Tpetra { 00062 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00063 void 00064 Export<LocalOrdinal,GlobalOrdinal,Node>:: 00065 setParameterList (const Teuchos::RCP<Teuchos::ParameterList>& plist) 00066 { 00067 bool debug = tpetraExportDebugDefault; 00068 if (! plist.is_null ()) { 00069 try { 00070 debug = plist->get<bool> ("Debug"); 00071 } catch (Teuchos::Exceptions::InvalidParameter&) {} 00072 } 00073 debug_ = debug; 00074 ExportData_->distributor_.setParameterList (plist); 00075 } 00076 00077 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00078 Export<LocalOrdinal,GlobalOrdinal,Node>:: 00079 Export (const Teuchos::RCP<const map_type >& source, 00080 const Teuchos::RCP<const map_type >& target) : 00081 out_ (Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr))), 00082 debug_ (tpetraExportDebugDefault) 00083 { 00084 using Teuchos::rcp; 00085 using std::endl; 00086 typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type; 00087 00088 if (! out_.is_null ()) { 00089 out_->pushTab (); 00090 } 00091 if (debug_) { 00092 std::ostringstream os; 00093 const int myRank = source->getComm ()->getRank (); 00094 os << myRank << ": Export ctor" << endl; 00095 *out_ << os.str (); 00096 } 00097 ExportData_ = rcp (new data_type (source, target, out_)); 00098 Teuchos::Array<GlobalOrdinal> exportGIDs; 00099 setupSamePermuteExport (exportGIDs); 00100 if (debug_) { 00101 std::ostringstream os; 00102 const int myRank = source->getComm ()->getRank (); 00103 os << myRank << ": Export ctor: " 00104 << "setupSamePermuteExport done" << endl; 00105 *out_ << os.str (); 00106 } 00107 if (source->isDistributed ()) { 00108 setupRemote (exportGIDs); 00109 } 00110 if (debug_) { 00111 std::ostringstream os; 00112 const int myRank = source->getComm ()->getRank (); 00113 os << myRank << ": Export ctor: done" << endl; 00114 *out_ << os.str (); 00115 } 00116 if (! out_.is_null ()) { 00117 out_->popTab (); 00118 } 00119 } 00120 00121 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00122 Export<LocalOrdinal,GlobalOrdinal,Node>:: 00123 Export (const Teuchos::RCP<const map_type >& source, 00124 const Teuchos::RCP<const map_type >& target, 00125 const RCP<Teuchos::FancyOStream>& out) : 00126 out_ (out), 00127 debug_ (tpetraExportDebugDefault) 00128 { 00129 using Teuchos::rcp; 00130 using std::endl; 00131 typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type; 00132 00133 if (! out_.is_null ()) { 00134 out_->pushTab (); 00135 } 00136 if (debug_) { 00137 std::ostringstream os; 00138 const int myRank = source->getComm ()->getRank (); 00139 os << myRank << ": Export ctor" << endl; 00140 *out_ << os.str (); 00141 } 00142 ExportData_ = rcp (new data_type (source, target, out)); 00143 Teuchos::Array<GlobalOrdinal> exportGIDs; 00144 setupSamePermuteExport (exportGIDs); 00145 if (debug_) { 00146 std::ostringstream os; 00147 const int myRank = source->getComm ()->getRank (); 00148 os << myRank << ": Export ctor: " 00149 << "setupSamePermuteExport done" << endl; 00150 *out_ << os.str (); 00151 } 00152 if (source->isDistributed ()) { 00153 setupRemote (exportGIDs); 00154 } 00155 if (debug_) { 00156 std::ostringstream os; 00157 const int myRank = source->getComm ()->getRank (); 00158 os << myRank << ": Export ctor: done" << endl; 00159 *out_ << os.str (); 00160 } 00161 if (! out_.is_null ()) { 00162 out_->popTab (); 00163 } 00164 } 00165 00166 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00167 Export<LocalOrdinal,GlobalOrdinal,Node>:: 00168 Export (const Teuchos::RCP<const map_type >& source, 00169 const Teuchos::RCP<const map_type >& target, 00170 const Teuchos::RCP<Teuchos::ParameterList>& plist) : 00171 out_ (Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr))), 00172 debug_ (tpetraExportDebugDefault) 00173 { 00174 using Teuchos::rcp; 00175 using std::endl; 00176 typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type; 00177 00178 // Read "Debug" parameter from the input ParameterList. 00179 bool debug = tpetraExportDebugDefault; 00180 if (! plist.is_null ()) { 00181 try { 00182 debug = plist->get<bool> ("Debug"); 00183 } catch (Teuchos::Exceptions::InvalidParameter&) {} 00184 } 00185 debug_ = debug; 00186 00187 if (! out_.is_null ()) { 00188 out_->pushTab (); 00189 } 00190 if (debug_) { 00191 std::ostringstream os; 00192 const int myRank = source->getComm ()->getRank (); 00193 os << myRank << ": Export ctor" << endl; 00194 *out_ << os.str (); 00195 } 00196 ExportData_ = rcp (new data_type (source, target, out_, plist)); 00197 Teuchos::Array<GlobalOrdinal> exportGIDs; 00198 setupSamePermuteExport (exportGIDs); 00199 if (debug_) { 00200 std::ostringstream os; 00201 const int myRank = source->getComm ()->getRank (); 00202 os << myRank << ": Export ctor: " 00203 << "setupSamePermuteExport done" << endl; 00204 *out_ << os.str (); 00205 } 00206 if (source->isDistributed ()) { 00207 setupRemote (exportGIDs); 00208 } 00209 if (debug_) { 00210 std::ostringstream os; 00211 const int myRank = source->getComm ()->getRank (); 00212 os << myRank << ": Export ctor: done" << endl; 00213 *out_ << os.str (); 00214 } 00215 if (! out_.is_null ()) { 00216 out_->popTab (); 00217 } 00218 } 00219 00220 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00221 Export<LocalOrdinal,GlobalOrdinal,Node>:: 00222 Export (const Teuchos::RCP<const map_type >& source, 00223 const Teuchos::RCP<const map_type >& target, 00224 const RCP<Teuchos::FancyOStream>& out, 00225 const Teuchos::RCP<Teuchos::ParameterList>& plist) : 00226 out_ (Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr))), 00227 debug_ (tpetraExportDebugDefault) 00228 { 00229 using Teuchos::rcp; 00230 using std::endl; 00231 typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type; 00232 00233 // Read "Debug" parameter from the input ParameterList. 00234 bool debug = tpetraExportDebugDefault; 00235 if (! plist.is_null ()) { 00236 try { 00237 debug = plist->get<bool> ("Debug"); 00238 } catch (Teuchos::Exceptions::InvalidParameter&) {} 00239 } 00240 debug_ = debug; 00241 00242 if (! out_.is_null ()) { 00243 out_->pushTab (); 00244 } 00245 if (debug_) { 00246 std::ostringstream os; 00247 const int myRank = source->getComm ()->getRank (); 00248 os << myRank << ": Export ctor" << endl; 00249 *out_ << os.str (); 00250 } 00251 ExportData_ = rcp (new data_type (source, target, out, plist)); 00252 Teuchos::Array<GlobalOrdinal> exportGIDs; 00253 setupSamePermuteExport (exportGIDs); 00254 if (debug_) { 00255 std::ostringstream os; 00256 const int myRank = source->getComm ()->getRank (); 00257 os << myRank << ": Export ctor: " 00258 << "setupSamePermuteExport done" << endl; 00259 *out_ << os.str (); 00260 } 00261 if (source->isDistributed ()) { 00262 setupRemote (exportGIDs); 00263 } 00264 if (debug_) { 00265 std::ostringstream os; 00266 const int myRank = source->getComm ()->getRank (); 00267 os << myRank << ": Export ctor: done" << endl; 00268 *out_ << os.str (); 00269 } 00270 if (! out_.is_null ()) { 00271 out_->popTab (); 00272 } 00273 } 00274 00275 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00276 Export<LocalOrdinal,GlobalOrdinal,Node>:: 00277 Export (const Export<LocalOrdinal,GlobalOrdinal,Node>& rhs) 00278 : ExportData_ (rhs.ExportData_), 00279 out_ (rhs.out_), 00280 debug_ (rhs.debug_) 00281 { 00282 using std::endl; 00283 00284 if (! out_.is_null ()) { 00285 out_->pushTab (); 00286 } 00287 if (debug_) { 00288 std::ostringstream os; 00289 const int myRank = getSourceMap ()->getComm ()->getRank (); 00290 os << myRank << ": Export copy ctor (done)" << endl; 00291 *out_ << os.str (); 00292 } 00293 if (! out_.is_null ()) { 00294 out_->popTab (); 00295 } 00296 } 00297 00298 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00299 Export<LocalOrdinal,GlobalOrdinal,Node>:: 00300 Export (const Import<LocalOrdinal,GlobalOrdinal,Node>& importer) 00301 : out_ (importer.out_) 00302 , debug_ (importer.debug_) 00303 { 00304 if(!importer.ImportData_.is_null()) ExportData_ = importer.ImportData_->reverseClone(); 00305 } 00306 00307 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00308 Export<LocalOrdinal,GlobalOrdinal,Node>::~Export() 00309 {} 00310 00311 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00312 size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumSameIDs() const { 00313 return ExportData_->numSameIDs_; 00314 } 00315 00316 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00317 size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumPermuteIDs() const { 00318 return ExportData_->permuteFromLIDs_.size(); 00319 } 00320 00321 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00322 ArrayView<const LocalOrdinal> 00323 Export<LocalOrdinal,GlobalOrdinal,Node>::getPermuteFromLIDs() const { 00324 return ExportData_->permuteFromLIDs_(); 00325 } 00326 00327 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00328 ArrayView<const LocalOrdinal> 00329 Export<LocalOrdinal,GlobalOrdinal,Node>::getPermuteToLIDs() const { 00330 return ExportData_->permuteToLIDs_(); 00331 } 00332 00333 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00334 size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumRemoteIDs() const { 00335 return ExportData_->remoteLIDs_.size(); 00336 } 00337 00338 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00339 ArrayView<const LocalOrdinal> 00340 Export<LocalOrdinal,GlobalOrdinal,Node>::getRemoteLIDs() const { 00341 return ExportData_->remoteLIDs_(); 00342 } 00343 00344 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00345 size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumExportIDs() const { 00346 return ExportData_->exportLIDs_.size(); 00347 } 00348 00349 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00350 ArrayView<const LocalOrdinal> 00351 Export<LocalOrdinal,GlobalOrdinal,Node>::getExportLIDs() const { 00352 return ExportData_->exportLIDs_(); 00353 } 00354 00355 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00356 ArrayView<const int> 00357 Export<LocalOrdinal,GlobalOrdinal,Node>::getExportPIDs() const { 00358 return ExportData_->exportPIDs_(); 00359 } 00360 00361 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00362 Teuchos::RCP<const typename Export<LocalOrdinal,GlobalOrdinal,Node>::map_type> 00363 Export<LocalOrdinal,GlobalOrdinal,Node>::getSourceMap() const { 00364 return ExportData_->source_; 00365 } 00366 00367 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00368 Teuchos::RCP<const typename Export<LocalOrdinal,GlobalOrdinal,Node>::map_type> 00369 Export<LocalOrdinal,GlobalOrdinal,Node>::getTargetMap() const { 00370 return ExportData_->target_; 00371 } 00372 00373 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00374 Distributor & 00375 Export<LocalOrdinal,GlobalOrdinal,Node>::getDistributor() const { 00376 return ExportData_->distributor_; 00377 } 00378 00379 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00380 Export<LocalOrdinal,GlobalOrdinal,Node>& 00381 Export<LocalOrdinal,GlobalOrdinal,Node>:: 00382 operator= (const Export<LocalOrdinal,GlobalOrdinal,Node>& rhs) { 00383 if (&rhs != this) { 00384 ExportData_ = rhs.ExportData_; 00385 } 00386 return *this; 00387 } 00388 00389 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00390 void Export<LocalOrdinal,GlobalOrdinal,Node>:: 00391 print (std::ostream& os) const 00392 { 00393 using Teuchos::Comm; 00394 using Teuchos::getFancyOStream; 00395 using Teuchos::RCP; 00396 using Teuchos::rcpFromRef; 00397 using Teuchos::toString; 00398 using std::endl; 00399 00400 RCP<const Comm<int> > comm = getSourceMap ()->getComm (); 00401 const int myImageID = comm->getRank (); 00402 const int numImages = comm->getSize (); 00403 for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) { 00404 if (myImageID == imageCtr) { 00405 os << endl; 00406 if (myImageID == 0) { // I'm the root node (only output this info once) 00407 os << "Export Data Members:" << endl; 00408 } 00409 os << "Image ID : " << myImageID << endl; 00410 00411 os << "permuteFromLIDs: " << toString (getPermuteFromLIDs ()) << endl; 00412 os << "permuteToLIDs : " << toString (getPermuteToLIDs ()) << endl; 00413 os << "remoteLIDs : " << toString (getRemoteLIDs ()) << endl; 00414 os << "exportLIDs : " << toString (getExportLIDs ()) << endl; 00415 os << "exportPIDs : " << toString (getExportPIDs ()) << endl; 00416 00417 os << "numSameIDs : " << getNumSameIDs () << endl; 00418 os << "numPermuteIDs : " << getNumPermuteIDs () << endl; 00419 os << "numRemoteIDs : " << getNumRemoteIDs () << endl; 00420 os << "numExportIDs : " << getNumExportIDs () << endl; 00421 } 00422 // A few global barriers give output a chance to complete. 00423 comm->barrier(); 00424 comm->barrier(); 00425 comm->barrier(); 00426 } 00427 if (myImageID == 0) { 00428 os << endl << endl << "Source Map:" << endl << std::flush; 00429 } 00430 comm->barrier(); 00431 os << *getSourceMap(); 00432 comm->barrier(); 00433 00434 if (myImageID == 0) { 00435 os << endl << endl << "Target Map:" << endl << std::flush; 00436 } 00437 comm->barrier(); 00438 os << *getTargetMap(); 00439 comm->barrier(); 00440 00441 // It's also helpful for debugging to print the Distributor 00442 // object. Epetra_Export::Print() does this, so we can do a 00443 // side-by-side comparison. 00444 if (myImageID == 0) { 00445 os << endl << endl << "Distributor:" << endl << std::flush; 00446 } 00447 comm->barrier(); 00448 getDistributor().describe (*(getFancyOStream (rcpFromRef (os))), 00449 Teuchos::VERB_EXTREME); 00450 } 00451 00452 00453 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00454 void 00455 Export<LocalOrdinal,GlobalOrdinal,Node>:: 00456 setupSamePermuteExport (Teuchos::Array<GlobalOrdinal>& exportGIDs) 00457 { 00458 using Teuchos::arcp; 00459 using Teuchos::Array; 00460 using Teuchos::ArrayRCP; 00461 using Teuchos::ArrayView; 00462 using Teuchos::as; 00463 using Teuchos::null; 00464 typedef LocalOrdinal LO; 00465 typedef GlobalOrdinal GO; 00466 typedef typename ArrayView<const GO>::size_type size_type; 00467 const map_type& source = * (getSourceMap ()); 00468 const map_type& target = * (getTargetMap ()); 00469 ArrayView<const GO> sourceGIDs = source.getNodeElementList (); 00470 ArrayView<const GO> targetGIDs = target.getNodeElementList (); 00471 00472 #ifdef HAVE_TPETRA_DEBUG 00473 ArrayView<const GO> rawSrcGids = sourceGIDs; 00474 ArrayView<const GO> rawTgtGids = targetGIDs; 00475 #else 00476 const GO* const rawSrcGids = sourceGIDs.getRawPtr (); 00477 const GO* const rawTgtGids = targetGIDs.getRawPtr (); 00478 #endif // HAVE_TPETRA_DEBUG 00479 const size_type numSrcGids = sourceGIDs.size (); 00480 const size_type numTgtGids = targetGIDs.size (); 00481 const size_type numGids = std::min (numSrcGids, numTgtGids); 00482 00483 // Compute numSameIDs_: the number of initial GIDs that are the 00484 // same (and occur in the same order) in both Maps. The point of 00485 // numSameIDs_ is for the common case of an Export where all the 00486 // overlapping GIDs are at the end of the source Map, but 00487 // otherwise the source and target Maps are the same. This allows 00488 // a fast contiguous copy for the initial "same IDs." 00489 size_type numSameGids = 0; 00490 for ( ; numSameGids < numGids && rawSrcGids[numSameGids] == rawTgtGids[numSameGids]; ++numSameGids) 00491 {} // third clause of 'for' does everything 00492 ExportData_->numSameIDs_ = numSameGids; 00493 00494 // Compute permuteToLIDs_, permuteFromLIDs_, exportGIDs, and 00495 // exportLIDs_. The first two arrays are IDs to be permuted, and 00496 // the latter two arrays are IDs to sent out ("exported"), called 00497 // "export" IDs. 00498 // 00499 // IDs to permute are in both the source and target Maps, which 00500 // means we don't have to send or receive them, but we do have to 00501 // rearrange (permute) them in general. IDs to send are in the 00502 // source Map, but not in the target Map. 00503 00504 exportGIDs.resize (0); 00505 Array<LO>& permuteToLIDs = ExportData_->permuteToLIDs_; 00506 Array<LO>& permuteFromLIDs = ExportData_->permuteFromLIDs_; 00507 Array<LO>& exportLIDs = ExportData_->exportLIDs_; 00508 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid (); 00509 const LO numSrcLids = as<LO> (numSrcGids); 00510 // Iterate over the source Map's LIDs, since we only need to do 00511 // GID -> LID lookups for the target Map. 00512 for (LO srcLid = numSameGids; srcLid < numSrcLids; ++srcLid) { 00513 const GO curSrcGid = rawSrcGids[srcLid]; 00514 // getLocalElement() returns LINVALID if the GID isn't in the target Map. 00515 // This saves us a lookup (which isNodeGlobalElement() would do). 00516 const LO tgtLid = target.getLocalElement (curSrcGid); 00517 if (tgtLid != LINVALID) { // if target.isNodeGlobalElement (curSrcGid) 00518 permuteToLIDs.push_back (tgtLid); 00519 permuteFromLIDs.push_back (srcLid); 00520 } else { 00521 exportGIDs.push_back (curSrcGid); 00522 exportLIDs.push_back (srcLid); 00523 } 00524 } 00525 00526 // exportLIDs_ is the list of this process' LIDs that it has to 00527 // send out. Since this is an Export, and therefore the target 00528 // Map is nonoverlapping, we know that each export LID only needs 00529 // to be sent to one process. However, the source Map may be 00530 // overlapping, so multiple processes might send to the same LID 00531 // on a receiving process. 00532 00533 TPETRA_ABUSE_WARNING( 00534 getNumExportIDs() > 0 && ! source.isDistributed(), 00535 std::runtime_error, 00536 "::setupSamePermuteExport(): Source has export LIDs but Source is not " 00537 "distributed globally." << std::endl 00538 << "Exporting to a submap of the target map."); 00539 00540 // Compute exportPIDs_ ("outgoing" process IDs). 00541 // 00542 // For each GID in exportGIDs (GIDs to which this process must 00543 // send), find its corresponding owning process (a.k.a. "image") 00544 // ID in the target Map. Store these process IDs in 00545 // exportPIDs_. These are the process IDs to which the Export 00546 // needs to send data. 00547 // 00548 // We only need to do this if the source Map is distributed; 00549 // otherwise, the Export doesn't have to perform any 00550 // communication. 00551 if (source.isDistributed ()) { 00552 ExportData_->exportPIDs_.resize(exportGIDs.size ()); 00553 // This call will assign any GID in the target Map with no 00554 // corresponding process ID a fake process ID of -1. We'll use 00555 // this below to remove exports for processses that don't exist. 00556 const LookupStatus lookup = 00557 target.getRemoteIndexList (exportGIDs(), 00558 ExportData_->exportPIDs_ ()); 00559 TPETRA_ABUSE_WARNING( lookup == IDNotPresent, std::runtime_error, 00560 "::setupSamePermuteExport(): The source Map has GIDs not found " 00561 "in the target Map."); 00562 00563 // Get rid of process IDs not in the target Map. This prevents 00564 // exporting to GIDs which don't belong to any process in the 00565 // target Map. 00566 if (lookup == IDNotPresent) { 00567 const size_type numInvalidExports = 00568 std::count_if (ExportData_->exportPIDs_().begin(), 00569 ExportData_->exportPIDs_().end(), 00570 std::bind1st (std::equal_to<int>(), -1)); 00571 00572 // count number of valid and total number of exports 00573 const size_type totalNumExports = ExportData_->exportPIDs_.size(); 00574 if (numInvalidExports == totalNumExports) { 00575 // all exports are invalid; we have no exports; we can delete all exports 00576 exportGIDs.resize(0); 00577 ExportData_->exportLIDs_.resize(0); 00578 ExportData_->exportPIDs_.resize(0); 00579 } 00580 else { 00581 // some exports are valid; we need to keep the valid exports 00582 // pack and resize 00583 size_type numValidExports = 0; 00584 for (size_type e = 0; e < totalNumExports; ++e) { 00585 if (ExportData_->exportPIDs_[e] != -1) { 00586 exportGIDs[numValidExports] = exportGIDs[e]; 00587 ExportData_->exportLIDs_[numValidExports] = ExportData_->exportLIDs_[e]; 00588 ExportData_->exportPIDs_[numValidExports] = ExportData_->exportPIDs_[e]; 00589 ++numValidExports; 00590 } 00591 } 00592 exportGIDs.resize (numValidExports); 00593 ExportData_->exportLIDs_.resize (numValidExports); 00594 ExportData_->exportPIDs_.resize (numValidExports); 00595 } 00596 } 00597 } 00598 } // setupSamePermuteExport() 00599 00600 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00601 void 00602 Export<LocalOrdinal,GlobalOrdinal,Node>::setupRemote(Teuchos::Array<GlobalOrdinal> & exportGIDs) 00603 { 00604 using std::endl; 00605 const map_type& target = * (getTargetMap ()); 00606 const int myRank = target.getComm ()->getRank (); 00607 00608 if (! out_.is_null ()) { 00609 out_->pushTab (); 00610 } 00611 if (debug_) { 00612 std::ostringstream os; 00613 os << myRank << ": Export::setupRemote" << endl; 00614 *out_ << os.str (); 00615 } 00616 if (! out_.is_null ()) { 00617 out_->pushTab (); 00618 } 00619 00620 // Sort exportPIDs_ in ascending order, and apply the same 00621 // permutation to exportGIDs_ and exportLIDs_. This ensures that 00622 // exportPIDs_[i], exportGIDs_[i], and exportLIDs_[i] all 00623 // refer to the same thing. 00624 sort3 (ExportData_->exportPIDs_.begin(), 00625 ExportData_->exportPIDs_.end(), 00626 exportGIDs.begin(), 00627 ExportData_->exportLIDs_.begin()); 00628 00629 if (debug_) { 00630 std::ostringstream os; 00631 os << myRank << ": Export::setupRemote: Calling createFromSends" << endl; 00632 *out_ << os.str (); 00633 } 00634 00635 // Construct the list of entries that calling image needs to send 00636 // as a result of everyone asking for what it needs to receive. 00637 // 00638 // mfh 05 Jan 2012: I understand the above comment as follows: 00639 // Construct the communication plan from the list of image IDs to 00640 // which we need to send. 00641 size_t numRemoteIDs; 00642 numRemoteIDs = ExportData_->distributor_.createFromSends (ExportData_->exportPIDs_ ()); 00643 00644 if (debug_) { 00645 std::ostringstream os; 00646 os << myRank << ": Export::setupRemote: Calling doPostsAndWaits" << endl; 00647 *out_ << os.str (); 00648 } 00649 00650 // Use the communication plan with ExportGIDs to find out who is 00651 // sending to us and get the proper ordering of GIDs for incoming 00652 // remote entries (these will be converted to LIDs when done). 00653 Array<GlobalOrdinal> remoteGIDs (numRemoteIDs); 00654 ExportData_->distributor_.doPostsAndWaits (exportGIDs().getConst (), 1, remoteGIDs()); 00655 00656 // Remote (incoming) IDs come in as GIDs; convert to LIDs. LIDs 00657 // tell this process where to store the incoming remote data. 00658 ExportData_->remoteLIDs_.resize (numRemoteIDs); 00659 { 00660 typename Array<GlobalOrdinal>::const_iterator i = remoteGIDs.begin(); 00661 typename Array<LocalOrdinal>::iterator j = ExportData_->remoteLIDs_.begin(); 00662 while (i != remoteGIDs.end()) { 00663 *j++ = target.getLocalElement(*i++); 00664 } 00665 } 00666 00667 if (! out_.is_null ()) { 00668 out_->popTab (); 00669 } 00670 if (debug_) { 00671 std::ostringstream os; 00672 os << myRank << ": Export::setupRemote: done" << endl; 00673 *out_ << os.str (); 00674 } 00675 if (! out_.is_null ()) { 00676 out_->popTab (); 00677 } 00678 } 00679 00680 } // namespace Tpetra 00681 00682 // Explicit instantiation macro. 00683 // Only invoke this when in the Tpetra namespace. 00684 // Most users do not need to use this. 00685 // 00686 // LO: The local ordinal type. 00687 // GO: The global ordinal type. 00688 // NODE: The Kokkos Node type. 00689 #define TPETRA_EXPORT_INSTANT(LO, GO, NODE) \ 00690 \ 00691 template class Export< LO , GO , NODE >; 00692 00693 #endif // TPETRA_EXPORT_DEF_HPP
1.7.6.1