10 #ifndef TPETRA_EXPORT_DEF_HPP
11 #define TPETRA_EXPORT_DEF_HPP
13 #include "Tpetra_Distributor.hpp"
14 #include "Tpetra_Map.hpp"
15 #include "Tpetra_ImportExportData.hpp"
17 #include "Tpetra_Import.hpp"
18 #include "Tpetra_Details_DualViewUtil.hpp"
20 #include "Teuchos_as.hpp"
21 #include "Teuchos_Array.hpp"
22 #include "Teuchos_FancyOStream.hpp"
23 #include "Teuchos_ParameterList.hpp"
28 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
30 Export(
const Teuchos::RCP<const map_type>& source,
31 const Teuchos::RCP<const map_type>& target,
32 const Teuchos::RCP<Teuchos::FancyOStream>& out,
33 const Teuchos::RCP<Teuchos::ParameterList>& plist)
34 :
base_type(source, target, out, plist,
"Export") {
37 using ::Tpetra::Details::ProfilingRegion;
38 ProfilingRegion regionExport(
"Tpetra::Export::Export");
41 std::ostringstream os;
42 const int myRank = source->getComm()->getRank();
43 os << myRank <<
": Export ctor" << endl;
46 Teuchos::Array<GlobalOrdinal> exportGIDs;
47 setupSamePermuteExport(exportGIDs);
48 if (source->isDistributed()) {
49 setupRemote(exportGIDs);
52 TEUCHOS_ASSERT(!this->
TransferData_->permuteFromLIDs_.need_sync_device());
53 TEUCHOS_ASSERT(!this->
TransferData_->permuteFromLIDs_.need_sync_host());
54 TEUCHOS_ASSERT(!this->
TransferData_->permuteToLIDs_.need_sync_device());
55 TEUCHOS_ASSERT(!this->
TransferData_->permuteToLIDs_.need_sync_host());
56 TEUCHOS_ASSERT(!this->
TransferData_->remoteLIDs_.need_sync_device());
57 TEUCHOS_ASSERT(!this->
TransferData_->remoteLIDs_.need_sync_host());
58 TEUCHOS_ASSERT(!this->
TransferData_->exportLIDs_.need_sync_device());
59 TEUCHOS_ASSERT(!this->
TransferData_->exportLIDs_.need_sync_host());
61 this->detectRemoteExportLIDsContiguous();
64 std::ostringstream os;
65 const int myRank = source->getComm()->getRank();
66 os << myRank <<
": Export ctor: done" << endl;
71 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
73 Export(
const Teuchos::RCP<const map_type>& source,
74 const Teuchos::RCP<const map_type>& target)
75 :
Export(source, target, Teuchos::null, Teuchos::null) {}
77 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
79 Export(
const Teuchos::RCP<const map_type>& source,
80 const Teuchos::RCP<const map_type>& target,
81 const Teuchos::RCP<Teuchos::FancyOStream>& out)
82 :
Export(source, target, out, Teuchos::null) {}
84 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
86 Export(
const Teuchos::RCP<const map_type>& source,
87 const Teuchos::RCP<const map_type>& target,
88 const Teuchos::RCP<Teuchos::ParameterList>& plist)
89 :
Export(source, target, Teuchos::null, plist) {}
91 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
96 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
101 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
104 const Teuchos::EVerbosityLevel verbLevel)
const {
106 this->describeImpl(out,
"Tpetra::Export", verbLevel);
109 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
112 auto out = Teuchos::getFancyOStream(Teuchos::rcpFromRef(os));
114 this->describe(*out, Teuchos::VERB_EXTREME);
117 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
122 using Teuchos::Array;
123 using Teuchos::ArrayRCP;
124 using Teuchos::ArrayView;
127 using ::Tpetra::Details::makeDualViewFromOwningHostView;
128 using ::Tpetra::Details::ProfilingRegion;
129 using ::Tpetra::Details::view_alloc_no_init;
130 using LO = LocalOrdinal;
131 using GO = GlobalOrdinal;
132 using size_type =
typename ArrayView<const GO>::size_type;
133 const char tfecfFuncName[] =
"setupSamePermuteExport: ";
134 ProfilingRegion regionExport(
"Tpetra::Export::setupSamePermuteExport");
136 std::unique_ptr<std::string> prefix;
137 if (this->verbose()) {
138 auto srcMap = this->getSourceMap();
139 auto comm = srcMap.is_null() ? Teuchos::null : srcMap->getComm();
140 const int myRank = comm.is_null() ? -1 : comm->getRank();
142 std::ostringstream os;
143 os <<
"Proc " << myRank <<
": Tpetra::Export::setupSamePermuteExport: ";
144 prefix = std::unique_ptr<std::string>(
new std::string(os.str()));
146 std::ostringstream os2;
147 os2 << *prefix <<
"Start" << std::endl;
148 this->verboseOutputStream() << os2.str();
151 const map_type& source = *(this->getSourceMap());
152 const map_type& target = *(this->getTargetMap());
153 ArrayView<const GO> sourceGIDs = source.getLocalElementList();
154 ArrayView<const GO> targetGIDs = target.getLocalElementList();
156 #ifdef HAVE_TPETRA_DEBUG
157 ArrayView<const GO> rawSrcGids = sourceGIDs;
158 ArrayView<const GO> rawTgtGids = targetGIDs;
160 const GO*
const rawSrcGids = sourceGIDs.getRawPtr();
161 const GO*
const rawTgtGids = targetGIDs.getRawPtr();
162 #endif // HAVE_TPETRA_DEBUG
163 const size_type numSrcGids = sourceGIDs.size();
164 const size_type numTgtGids = targetGIDs.size();
165 const size_type numGids = std::min(numSrcGids, numTgtGids);
173 size_type numSameGids = 0;
174 for (; numSameGids < numGids &&
175 rawSrcGids[numSameGids] == rawTgtGids[numSameGids];
178 this->TransferData_->numSameIDs_ = numSameGids;
180 if (this->verbose()) {
181 std::ostringstream os;
182 os << *prefix <<
"numIDs: " << numGids
183 <<
", numSameIDs: " << numSameGids << endl;
184 this->verboseOutputStream() << os.str();
199 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid();
200 const LO numSrcLids =
static_cast<LO
>(numSrcGids);
204 for (LO srcLid = numSameGids; srcLid < numSrcLids; ++srcLid) {
205 const GO curSrcGid = rawSrcGids[srcLid];
209 const LO tgtLid = target.getLocalElement(curSrcGid);
210 if (tgtLid != LINVALID) {
216 if (this->verbose()) {
217 std::ostringstream os;
218 os << *prefix <<
"numPermutes: " << numPermutes
219 <<
", numExports: " << numExports << endl;
220 this->verboseOutputStream() << os.str();
222 TEUCHOS_ASSERT(numPermutes + numExports ==
223 numSrcLids - numSameGids);
225 typename decltype(this->TransferData_->permuteToLIDs_)::t_host
227 typename decltype(this->TransferData_->permuteToLIDs_)::t_host
229 typename decltype(this->TransferData_->permuteToLIDs_)::t_host
234 exportGIDs.resize(numExports);
239 for (LO srcLid = numSameGids; srcLid < numSrcLids; ++srcLid) {
240 const GO curSrcGid = rawSrcGids[srcLid];
241 const LO tgtLid = target.getLocalElement(curSrcGid);
242 if (tgtLid != LINVALID) {
243 permuteToLIDs[numPermutes2] = tgtLid;
244 permuteFromLIDs[numPermutes2] = srcLid;
247 exportGIDs[numExports2] = curSrcGid;
248 exportLIDs[numExports2] = srcLid;
252 TEUCHOS_ASSERT(numPermutes == numPermutes2);
253 TEUCHOS_ASSERT(numExports == numExports2);
254 TEUCHOS_ASSERT(
size_t(numExports) ==
size_t(exportGIDs.size()));
267 if (numExports != 0 && !source.isDistributed()) {
273 this->TransferData_->isLocallyComplete_ =
false;
274 if (this->verbose()) {
275 std::ostringstream os;
276 os << *prefix <<
"Export is not locally complete" << endl;
277 this->verboseOutputStream() << os.str();
282 "::setupSamePermuteExport(): Source has "
283 "export LIDs but Source is not distributed globally. Exporting to "
284 "a submap of the target map.");
298 if (source.isDistributed()) {
299 if (this->verbose()) {
300 std::ostringstream os;
301 os << *prefix <<
"Source Map is distributed; "
302 "call targetMap.getRemoteiNdexList"
304 this->verboseOutputStream() << os.str();
306 this->TransferData_->exportPIDs_.resize(exportGIDs.size());
311 target.getRemoteIndexList(exportGIDs(),
312 this->TransferData_->exportPIDs_());
316 "::setupSamePermuteExport(): The source Map has GIDs not found "
317 "in the target Map.");
326 this->TransferData_->isLocallyComplete_ =
false;
328 Teuchos::Array<int>& exportPIDs = this->TransferData_->exportPIDs_;
330 const size_type totalNumExports = exportPIDs.size();
331 const size_type numInvalidExports =
332 std::count_if(exportPIDs.begin(), exportPIDs.end(),
333 [](
const int procId) {
return procId == -1; });
334 if (this->verbose()) {
335 std::ostringstream os;
336 os << *prefix <<
"totalNumExports: " << totalNumExports
337 <<
", numInvalidExports: " << numInvalidExports << endl;
338 this->verboseOutputStream() << os.str();
340 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numInvalidExports == 0, std::logic_error,
341 "targetMap.getRemoteIndexList returned IDNotPresent, but no export "
342 "PIDs are -1. Please report this bug to the Tpetra developers.");
350 if (numInvalidExports == totalNumExports) {
351 exportGIDs.resize(0);
352 exportLIDs = decltype(exportLIDs)();
353 exportPIDs.resize(0);
355 size_type numValidExports = 0;
356 for (size_type e = 0; e < totalNumExports; ++e) {
357 if (this->TransferData_->exportPIDs_[e] != -1) {
358 exportGIDs[numValidExports] = exportGIDs[e];
359 exportLIDs[numValidExports] = exportLIDs[e];
360 exportPIDs[numValidExports] = exportPIDs[e];
364 exportGIDs.resize(numValidExports);
365 Kokkos::resize(exportLIDs, numValidExports);
366 exportPIDs.resize(numValidExports);
378 if (this->verbose()) {
379 std::ostringstream os;
380 os << *prefix <<
"Done!" << std::endl;
381 this->verboseOutputStream() << os.str();
385 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
386 void Export<LocalOrdinal, GlobalOrdinal, Node>::
387 setupRemote(Teuchos::Array<GlobalOrdinal>& exportGIDs) {
389 using Teuchos::Array;
390 using ::Tpetra::Details::makeDualViewFromOwningHostView;
391 using ::Tpetra::Details::view_alloc_no_init;
392 using LO = LocalOrdinal;
393 using GO = GlobalOrdinal;
395 std::unique_ptr<std::string> prefix;
396 if (this->verbose()) {
397 auto srcMap = this->getSourceMap();
398 auto comm = srcMap.is_null() ? Teuchos::null : srcMap->getComm();
399 const int myRank = comm.is_null() ? -1 : comm->getRank();
401 std::ostringstream os;
402 os <<
"Proc " << myRank <<
": Tpetra::Export::setupRemote: ";
403 prefix = std::unique_ptr<std::string>(
new std::string(os.str()));
405 std::ostringstream os2;
406 os2 << *prefix <<
"Start" << std::endl;
407 this->verboseOutputStream() << os2.str();
410 TEUCHOS_ASSERT(!this->getTargetMap().is_null());
411 const map_type& tgtMap = *(this->getTargetMap());
418 TEUCHOS_ASSERT(
size_t(this->TransferData_->exportLIDs_.extent(0)) ==
419 size_t(this->TransferData_->exportPIDs_.size()));
420 this->TransferData_->exportLIDs_.modify_host();
421 auto exportLIDs = this->TransferData_->exportLIDs_.view_host();
422 sort3(this->TransferData_->exportPIDs_.begin(),
423 this->TransferData_->exportPIDs_.end(),
424 exportGIDs.getRawPtr(),
426 this->TransferData_->exportLIDs_.sync_device();
432 if (this->verbose()) {
433 std::ostringstream os;
434 os << *prefix <<
"Call createFromSends" << endl;
435 this->verboseOutputStream() << os.str();
444 Teuchos::Array<int>& exportPIDs = this->TransferData_->exportPIDs_;
445 Distributor& distributor = this->TransferData_->distributor_;
446 const size_t numRemoteIDs = distributor.createFromSends(exportPIDs());
448 if (this->verbose()) {
449 std::ostringstream os;
450 os << *prefix <<
"numRemoteIDs: " << numRemoteIDs
451 <<
"; call doPostsAndWaits" << endl;
452 this->verboseOutputStream() << os.str();
459 Kokkos::View<const GO*, Kokkos::HostSpace> exportGIDsConst(exportGIDs.data(), exportGIDs.size());
460 Kokkos::View<GO*, Kokkos::HostSpace> remoteGIDs(
"remoteGIDs", numRemoteIDs);
461 distributor.doPostsAndWaits(exportGIDsConst, 1, remoteGIDs);
465 using host_remote_lids_type =
466 typename decltype(this->TransferData_->remoteLIDs_)::t_host;
469 for (LO j = 0; j < LO(numRemoteIDs); ++j) {
470 remoteLIDs[j] = tgtMap.getLocalElement(remoteGIDs[j]);
474 if (this->verbose()) {
475 std::ostringstream os;
476 os << *prefix <<
"Done!" << endl;
477 this->verboseOutputStream() << os.str();
490 #define TPETRA_EXPORT_INSTANT(LO, GO, NODE) \
491 template class Export<LO, GO, NODE>;
493 #endif // TPETRA_EXPORT_DEF_HPP
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
Teuchos::FancyOStream & verboseOutputStream() const
Valid (nonnull) output stream for verbose output.
virtual void print(std::ostream &os) const
Print the Export's data to the given output stream.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
LookupStatus
Return status of Map remote index lookup (getRemoteIndexList()).
void sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT3 &first3, const bool stableSort=false)
Sort the first array, and apply the same permutation to the second and third arrays.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Describe this object in a human-readable way to the given output stream.
Export(const Teuchos::RCP< const map_type > &source, const Teuchos::RCP< const map_type > &target)
Construct a Export object from the source and target Map.
auto view_alloc_no_init(const std::string &label) -> decltype(Kokkos::view_alloc(label, Kokkos::WithoutInitializing))
Use in place of the string label as the first argument of Kokkos::View's constructor, in case you want to allocate without initializing.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
#define TPETRA_ABUSE_WARNING(throw_exception_test, Exception, msg)
Handle an abuse warning, according to HAVE_TPETRA_THROW_ABUSE_WARNINGS and HAVE_TPETRA_PRINT_ABUSE_WA...
Teuchos::RCP< ImportExportData< LocalOrdinal, GlobalOrdinal, Node > > TransferData_
All the data needed for executing the Export communication plan.
Stand-alone utility functions and macros.
void makeDualViewFromOwningHostView(Kokkos::DualView< ElementType *, DeviceType > &dv, const typename Kokkos::DualView< ElementType *, DeviceType >::t_host &hostView)
Initialize dv such that its host View is hostView.
bool verbose() const
Whether to print verbose debugging output.