2325 if (!indicesAreAllocated()) {
2326 allocateIndices(GlobalIndices, verbose_);
2328 const LO
lclRow = this->rowMap_->getLocalElement(
gblRow);
2329 if (
lclRow != Tpetra::Details::OrdinalTraits<LO>::invalid()) {
2331 if (this->hasColMap()) {
2333 const map_type&
colMap = *(this->colMap_);
2347 std::ostringstream os;
2348 os <<
"You attempted to insert entries in owned row " << gblRow
2349 <<
", at the following column indices: [";
2350 for (LO k = 0; k < numInputInds; ++k) {
2351 os << inputGblColInds[k];
2352 if (k +
static_cast<LO
>(1) < numInputInds) {
2357 <<
"Of those, the following indices are not in "
2358 "the column Map on this process: [";
2359 for (
size_t k = 0; k < badColInds.size(); ++k) {
2360 os << badColInds[k];
2361 if (k +
size_t(1) < badColInds.size()) {
2366 <<
"Since the matrix has a column Map already, "
2367 "it is invalid to insert entries at those locations.";
2368 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::invalid_argument, os.str());
2372 this->insertGlobalIndicesImpl(lclRow, inputGblColInds, numInputInds);
2374 this->insertGlobalIndicesIntoNonownedRows(gblRow, inputGblColInds,
2379template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2387template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2394 const char tfecfFuncName[] =
"insertGlobalIndicesFiltered: ";
2397 "Graph indices are local; use insertLocalIndices().");
2403 "You are not allowed to call this method if fill is not active. "
2404 "If fillComplete has been called, you must first call resumeFill "
2405 "before you may insert indices.");
2406 if (!indicesAreAllocated()) {
2407 allocateIndices(GlobalIndices, verbose_);
2412 if (!colMap_.is_null()) {
2423 if (
lclCol == Tpetra::Details::OrdinalTraits<LO>::invalid()) {
2446template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2463template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2468 !isFillActive(), std::runtime_error,
"requires that fill is active.");
2470 isStorageOptimized(), std::runtime_error,
2471 "cannot remove indices after optimizeStorage() has been called.");
2473 isGloballyIndexed(), std::runtime_error,
"graph indices are global.");
2475 !rowMap_->isNodeLocalElement(
lrow), std::runtime_error,
2476 "Local row " <<
lrow <<
" is not in the row Map on the calling process.");
2477 if (!indicesAreAllocated()) {
2478 allocateIndices(LocalIndices, verbose_);
2481 if (k_numRowEntries_.extent(0) != 0) {
2482 this->k_numRowEntries_(
lrow) = 0;
2487 !indicesAreAllocated() ||
2488 !isLocallyIndexed(),
2490 "Violated stated post-conditions. Please contact Tpetra team.");
2494template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2497 const typename local_graph_device_type::entries_type::non_const_type&
columnIndices) {
2499 ProfilingRegion
region(
"Tpetra::CrsGraph::setAllIndices");
2502 !hasColMap() || getColMap().
is_null(), std::runtime_error,
2503 "The graph must have a column Map before you may call this method.");
2510 std::runtime_error,
"Have 0 local rows, but rowPointers.size() is neither 0 nor 1.");
2514 std::runtime_error,
"rowPointers.size() = " <<
rowPtrLen <<
" != this->getLocalNumRows()+1 = " << (
numLocalRows + 1) <<
".");
2519 using exec_space =
typename local_graph_device_type::execution_space;
2522 Kokkos::parallel_reduce(
2523 Kokkos::RangePolicy<exec_space>(0,
columnIndices.extent(0)),
2530 auto comm = this->getComm();
2537 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not all within range [0, getLocalNumCols())!\n";
2540 throw std::invalid_argument(
"CrsGraph::setAllIndices(): columnIndices are out of the valid range on at least one process.");
2544 if (debug_ && this->isSorted()) {
2547 using exec_space =
typename local_graph_device_type::execution_space;
2548 using size_type =
typename local_graph_device_type::size_type;
2549 Kokkos::parallel_reduce(
2563 auto comm = this->getComm();
2564 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX,
notSorted,
2570 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not sorted!\n";
2573 throw std::invalid_argument(
"CrsGraph::setAllIndices(): provided columnIndices are not sorted within rows on at least one process.");
2577 indicesAreAllocated_ =
true;
2578 indicesAreLocal_ =
true;
2579 indicesAreSorted_ =
true;
2580 noRedundancies_ =
true;
2582 lclIndsUnpacked_wdv = lclIndsPacked_wdv;
2585 set_need_sync_host_uvm_access();
2589 storageStatus_ = Details::STORAGE_1D_PACKED;
2594 numAllocForAllRows_ = 0;
2595 k_numAllocPerRow_ =
decltype(k_numAllocPerRow_)();
2597 checkInternalState();
2600template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2605 typedef typename local_graph_device_type::row_map_type
row_map_type;
2606 typedef typename row_map_type::array_layout
layout_type;
2609 Kokkos::MemoryUnmanaged>
2614 constexpr bool same = std::is_same<size_t, row_offset_type>::value;
2619 if constexpr (
same) {
2627 std::is_same<
typename row_map_type::memory_space,
2628 Kokkos::HostSpace>::value;
2650 Kokkos::View<LocalOrdinal*, layout_type, device_type>
k_ind =
2651 Kokkos::Compat::getKokkosViewDeepCopy<device_type>(
columnIndices());
2655template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2659 using Teuchos::Comm;
2660 using Teuchos::outArg;
2663 using Teuchos::REDUCE_MAX;
2664 using Teuchos::REDUCE_MIN;
2665 using Teuchos::reduceAll;
2669 using size_type =
typename Teuchos::Array<GO>::size_type;
2672 std::unique_ptr<std::string>
prefix;
2674 prefix = this->createPrefix(
"CrsGraph",
"globalAssemble");
2675 std::ostringstream
os;
2677 std::cerr <<
os.str();
2682 "Fill must be active before "
2683 "you may call this method.");
2698 std::ostringstream
os;
2700 std::cerr <<
os.str();
2703 }
else if (verbose_) {
2704 std::ostringstream
os;
2705 os << *
prefix <<
"At least 1 process has nonlocal rows"
2707 std::cerr <<
os.str();
2726 for (
auto mapIter = this->nonlocals_.begin();
2727 mapIter != this->nonlocals_.end();
2757 const global_size_t INV = Teuchos::OrdinalTraits<global_size_t>::invalid();
2762 std::ostringstream
os;
2763 os << *
prefix <<
"nonlocalRowMap->getIndexBase()="
2765 std::cerr <<
os.str();
2777 for (
auto mapIter = this->nonlocals_.begin();
2778 mapIter != this->nonlocals_.end();
2787 std::ostringstream
os;
2789 std::cerr <<
os.str();
2805 std::ostringstream
os;
2807 std::cerr <<
os.str();
2814 std::ostringstream
os;
2815 os << *
prefix <<
"Original row Map is NOT 1-to-1" <<
endl;
2816 std::cerr <<
os.str();
2833 std::ostringstream
os;
2835 std::cerr <<
os.str();
2846 std::ostringstream
os;
2848 std::cerr <<
os.str();
2860 checkInternalState();
2862 std::ostringstream
os;
2864 std::cerr <<
os.str();
2868template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2871 clearGlobalConstants();
2872 if (
params != Teuchos::null) this->setParameterList(
params);
2874 indicesAreSorted_ =
true;
2875 noRedundancies_ =
true;
2876 fillComplete_ =
false;
2879template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2892 Teuchos::RCP<const map_type>
domMap = this->getDomainMap();
2894 domMap = this->getRowMap();
2896 Teuchos::RCP<const map_type>
ranMap = this->getRangeMap();
2898 ranMap = this->getRowMap();
2903template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2905 fillComplete(
const Teuchos::RCP<const map_type>& domainMap,
2906 const Teuchos::RCP<const map_type>&
rangeMap,
2907 const Teuchos::RCP<Teuchos::ParameterList>&
params) {
2910 const bool verbose = verbose_;
2912 std::unique_ptr<std::string>
prefix;
2914 prefix = this->createPrefix(
"CrsGraph",
"fillComplete");
2915 std::ostringstream
os;
2917 std::cerr <<
os.str();
2921 "Graph fill state must be active (isFillActive() "
2922 "must be true) before calling fillComplete().");
2924 const int numProcs = getComm()->getSize();
2933 if (
params->isParameter(
"sort column map ghost gids")) {
2934 sortGhostsAssociatedWithEachProcessor_ =
2935 params->get<
bool>(
"sort column map ghost gids",
2936 sortGhostsAssociatedWithEachProcessor_);
2937 }
else if (
params->isParameter(
"Sort column Map ghost GIDs")) {
2938 sortGhostsAssociatedWithEachProcessor_ =
2939 params->get<
bool>(
"Sort column Map ghost GIDs",
2940 sortGhostsAssociatedWithEachProcessor_);
2955 if (!indicesAreAllocated()) {
2958 allocateIndices(LocalIndices, verbose);
2961 allocateIndices(GlobalIndices, verbose);
2977 std::ostringstream
os;
2978 os << *
prefix <<
"Do not need to call globalAssemble; "
2979 "assertNoNonlocalInserts="
2983 std::cerr <<
os.str();
2988 std::ostringstream
os;
2990 Details::Impl::verbosePrintMap(
2991 os, nonlocals_.begin(), nonlocals_.end(),
2992 nonlocals_.size(),
"nonlocals_");
2993 std::cerr <<
os.str() <<
endl;
2997 auto map = this->getMap();
2998 auto comm =
map.is_null() ? Teuchos::null :
map->getComm();
3000 if (!comm.is_null()) {
3001 using Teuchos::REDUCE_MAX;
3002 using Teuchos::reduceAll;
3008 "least one process in the CrsGraph's communicator. This "
3009 "means either that you incorrectly set the "
3010 "\"No Nonlocal Changes\" fillComplete parameter to true, "
3011 "or that you inserted invalid entries. "
3012 "Rerun with the environment variable TPETRA_VERBOSE="
3013 "CrsGraph set to see the entries of nonlocals_ on every "
3014 "MPI process (WARNING: lots of output).");
3017 "nonlocals_.size()=" <<
numNonlocals <<
" != 0 on the "
3018 "calling process. This means either that you incorrectly "
3019 "set the \"No Nonlocal Changes\" fillComplete parameter "
3020 "to true, or that you inserted invalid entries. "
3021 "Rerun with the environment "
3022 "variable TPETRA_VERBOSE=CrsGraph set to see the entries "
3023 "of nonlocals_ on every MPI process (WARNING: lots of "
3036 Teuchos::Array<int> remotePIDs(0);
3039 this->makeColMap(remotePIDs);
3045 this->makeIndicesLocal(verbose);
3049 using Teuchos::outArg;
3051 using Teuchos::REDUCE_MIN;
3052 using Teuchos::reduceAll;
3056 if (!
map.is_null()) {
3057 comm =
map->getComm();
3059 if (comm.is_null()) {
3067 std::ostringstream
os;
3084 this->sortAndMergeAllIndices(this->isSorted(), this->isMerged());
3092 this->fillLocalGraph(
params);
3095 params->get(
"compute global constants",
true);
3097 this->computeGlobalConstants();
3099 this->computeLocalConstants();
3101 this->fillComplete_ =
true;
3102 this->checkInternalState();
3105 std::ostringstream
os;
3107 std::cerr <<
os.str();
3111template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3114 const Teuchos::RCP<const map_type>&
rangeMap,
3115 const Teuchos::RCP<const import_type>&
importer,
3116 const Teuchos::RCP<const export_type>&
exporter,
3117 const Teuchos::RCP<Teuchos::ParameterList>&
params) {
3119#ifdef HAVE_TPETRA_MMM_TIMINGS
3122 label =
params->get(
"Timer Label", label);
3123 std::string
prefix = std::string(
"Tpetra ") + label + std::string(
": ");
3124 using Teuchos::TimeMonitor;
3125 Teuchos::RCP<Teuchos::TimeMonitor>
MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
prefix + std::string(
"ESFC-G-Setup"))));
3130 std::runtime_error,
"The input domain Map and range Map must be nonnull.");
3132 isFillComplete() || !hasColMap(), std::runtime_error,
3134 "call this method unless the graph has a column Map.");
3138 std::runtime_error,
"The calling process has getLocalNumRows() = " << getLocalNumRows() <<
" > 0 rows, but the row offsets array has not "
3142 std::runtime_error,
"The row offsets array has length " <<
rowPtrsUnpackedLength <<
" != getLocalNumRows()+1 = " << (getLocalNumRows() + 1) <<
".");
3157 numAllocForAllRows_ = 0;
3158 k_numAllocPerRow_ =
decltype(k_numAllocPerRow_)();
3159 indicesAreAllocated_ =
true;
3164 indicesAreLocal_ =
true;
3165 indicesAreGlobal_ =
false;
3168#ifdef HAVE_TPETRA_MMM_TIMINGS
3170 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
prefix + std::string(
"ESFC-G-Maps"))));
3175 indicesAreSorted_ =
true;
3176 noRedundancies_ =
true;
3179#ifdef HAVE_TPETRA_MMM_TIMINGS
3181 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
prefix + std::string(
"ESFC-G-mIXcheckI"))));
3184 importer_ = Teuchos::null;
3185 exporter_ = Teuchos::null;
3188 !
importer->getSourceMap()->isSameAs(*getDomainMap()) ||
3189 !
importer->getTargetMap()->isSameAs(*getColMap()),
3190 std::invalid_argument,
": importer does not match matrix maps.");
3194#ifdef HAVE_TPETRA_MMM_TIMINGS
3196 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
prefix + std::string(
"ESFC-G-mIXcheckE"))));
3201 !
exporter->getSourceMap()->isSameAs(*getRowMap()) ||
3202 !
exporter->getTargetMap()->isSameAs(*getRangeMap()),
3203 std::invalid_argument,
": exporter does not match matrix maps.");
3207#ifdef HAVE_TPETRA_MMM_TIMINGS
3209 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
prefix + std::string(
"ESFC-G-mIXmake"))));
3211 Teuchos::Array<int> remotePIDs(0);
3212 this->makeImportExport(remotePIDs,
false);
3214#ifdef HAVE_TPETRA_MMM_TIMINGS
3216 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
prefix + std::string(
"ESFC-G-fLG"))));
3218 this->fillLocalGraph(
params);
3221 params->get(
"compute global constants",
true);
3224#ifdef HAVE_TPETRA_MMM_TIMINGS
3226 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
prefix + std::string(
"ESFC-G-cGC (const)"))));
3228 this->computeGlobalConstants();
3230#ifdef HAVE_TPETRA_MMM_TIMINGS
3232 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
prefix + std::string(
"ESFC-G-cGC (noconst)"))));
3234 this->computeLocalConstants();
3237 fillComplete_ =
true;
3239#ifdef HAVE_TPETRA_MMM_TIMINGS
3241 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
prefix + std::string(
"ESFC-G-cIS"))));
3243 checkInternalState();
3246template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3249 using ::Tpetra::Details::computeOffsetsFromCounts;
3250 typedef typename local_graph_device_type::row_map_type
row_map_type;
3252 typedef typename local_graph_device_type::entries_type::non_const_type
lclinds_1d_type;
3254 "fillLocalGraph (called from fillComplete or "
3255 "expertStaticFillComplete): ";
3256 const size_t lclNumRows = this->getLocalNumRows();
3262 if (!
params.is_null() && !
params->get(
"Optimize Storage",
true)) {
3271 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3273 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked.extent(0) == 0, std::logic_error,
3274 "rowPtrsUnpacked_host_ has size zero, but shouldn't");
3275 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked.extent(0) != lclNumRows + 1, std::logic_error,
3276 "rowPtrsUnpacked_host_.extent(0) = "
3277 << rowPtrsUnpacked.extent(0) <<
" != (lclNumRows + 1) = "
3278 << (lclNumRows + 1) <<
".");
3279 const size_t numOffsets = rowPtrsUnpacked.extent(0);
3280 const auto valToCheck = rowPtrsUnpacked(numOffsets - 1);
3281 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numOffsets != 0 &&
3282 lclIndsUnpacked_wdv.extent(0) != valToCheck,
3283 std::logic_error,
"numOffsets=" << numOffsets <<
" != 0 "
3284 " and lclIndsUnpacked_wdv.extent(0)="
3285 << lclIndsUnpacked_wdv.extent(0) <<
" != rowPtrsUnpacked_host_(" << numOffsets <<
")=" << valToCheck <<
".");
3288 size_t allocSize = 0;
3290 allocSize = this->getLocalAllocationSize();
3291 }
catch (std::logic_error& e) {
3292 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
3293 "getLocalAllocationSize threw "
3294 "std::logic_error: "
3296 }
catch (std::runtime_error& e) {
3297 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
3298 "getLocalAllocationSize threw "
3299 "std::runtime_error: "
3301 }
catch (std::exception& e) {
3302 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
3303 "getLocalAllocationSize threw "
3307 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
3308 "getLocalAllocationSize threw "
3309 "an exception not a subclass of std::exception.");
3312 if (this->getLocalNumEntries() != allocSize) {
3315 non_const_row_map_type ptr_d;
3316 row_map_type ptr_d_const;
3325 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3326 if (rowPtrsUnpacked.extent(0) != 0) {
3327 const size_t numOffsets =
3328 static_cast<size_t>(rowPtrsUnpacked.extent(0));
3329 const auto valToCheck = rowPtrsUnpacked(numOffsets - 1);
3330 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(valToCheck !=
size_t(lclIndsUnpacked_wdv.extent(0)),
3332 "(Unpacked branch) Before allocating "
3333 "or packing, k_rowPtrs_("
3334 << (numOffsets - 1) <<
")="
3335 << valToCheck <<
" != lclIndsUnpacked_wdv.extent(0)="
3336 << lclIndsUnpacked_wdv.extent(0) <<
".");
3346 size_t lclTotalNumEntries = 0;
3350 non_const_row_map_type(
"Tpetra::CrsGraph::ptr", lclNumRows + 1);
3351 ptr_d_const = ptr_d;
3355 typename num_row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
3357 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
size_t(numRowEnt_h.extent(0)) != lclNumRows,
3359 "(Unpacked branch) "
3360 "numRowEnt_h.extent(0)="
3361 << numRowEnt_h.extent(0)
3362 <<
" != getLocalNumRows()=" << lclNumRows <<
"");
3368 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(ptr_d.extent(0)) != lclNumRows + 1,
3370 "(Unpacked branch) After allocating "
3371 "ptr_d, ptr_d.extent(0) = "
3373 <<
" != lclNumRows+1 = " << (lclNumRows + 1) <<
".");
3374 const auto valToCheck =
3375 ::Tpetra::Details::getEntryOnHost(ptr_d, lclNumRows);
3376 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(valToCheck != lclTotalNumEntries, std::logic_error,
3377 "Tpetra::CrsGraph::fillLocalGraph: In unpacked branch, "
3378 "after filling ptr_d, ptr_d(lclNumRows="
3380 <<
") = " << valToCheck <<
" != total number of entries "
3381 "on the calling process = "
3382 << lclTotalNumEntries
3388 lclinds_1d_type ind_d =
3389 lclinds_1d_type(
"Tpetra::CrsGraph::lclInd", lclTotalNumEntries);
3401 typedef pack_functor<
3402 typename local_graph_device_type::entries_type::non_const_type,
3403 typename local_inds_dualv_type::t_dev::const_type,
3405 typename local_graph_device_type::row_map_type>
3407 inds_packer_type f(ind_d,
3408 lclIndsUnpacked_wdv.getDeviceView(Access::ReadOnly),
3409 ptr_d, this->getRowPtrsUnpackedDevice());
3411 typedef typename decltype(ind_d)::execution_space exec_space;
3412 typedef Kokkos::RangePolicy<exec_space, LocalOrdinal> range_type;
3413 Kokkos::parallel_for(range_type(0, lclNumRows), f);
3417 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(ptr_d.extent(0) == 0, std::logic_error,
3418 "(\"Optimize Storage\"=true branch) After packing, "
3419 "ptr_d.extent(0)=0.");
3420 if (ptr_d.extent(0) != 0) {
3421 const size_t numOffsets =
static_cast<size_t>(ptr_d.extent(0));
3422 const auto valToCheck =
3423 ::Tpetra::Details::getEntryOnHost(ptr_d, numOffsets - 1);
3424 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(valToCheck) != ind_d.extent(0),
3426 "(\"Optimize Storage\"=true branch) "
3427 "After packing, ptr_d("
3428 << (numOffsets - 1) <<
")="
3429 << valToCheck <<
" != ind_d.extent(0)="
3430 << ind_d.extent(0) <<
".");
3434 if (requestOptimizedStorage)
3435 setRowPtrs(ptr_d_const);
3437 setRowPtrsPacked(ptr_d_const);
3438 lclIndsPacked_wdv = local_inds_wdv_type(ind_d);
3441 this->setRowPtrs(rowPtrsUnpacked_dev_);
3442 lclIndsPacked_wdv = lclIndsUnpacked_wdv;
3445 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3446 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3447 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsPacked_dev.extent(0) == 0, std::logic_error,
3448 "(\"Optimize Storage\"=false branch) "
3449 "rowPtrsPacked_dev_.extent(0) = 0.");
3450 if (rowPtrsPacked_dev.extent(0) != 0) {
3451 const size_t numOffsets =
3452 static_cast<size_t>(rowPtrsPacked_dev.extent(0));
3453 const size_t valToCheck =
3454 rowPtrsPacked_host(numOffsets - 1);
3455 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(valToCheck !=
size_t(lclIndsPacked_wdv.extent(0)),
3457 "(\"Optimize Storage\"=false branch) "
3458 "rowPtrsPacked_dev_("
3459 << (numOffsets - 1) <<
")="
3461 <<
" != lclIndsPacked_wdv.extent(0)="
3462 << lclIndsPacked_wdv.extent(0) <<
".");
3468 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3469 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3470 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(rowPtrsPacked_dev.extent(0)) != lclNumRows + 1,
3471 std::logic_error,
"After packing, rowPtrsPacked_dev_.extent(0) = " << rowPtrsPacked_dev.extent(0) <<
" != lclNumRows+1 = " << (lclNumRows + 1) <<
".");
3472 if (rowPtrsPacked_dev.extent(0) != 0) {
3473 const size_t numOffsets =
static_cast<size_t>(rowPtrsPacked_dev.extent(0));
3474 const auto valToCheck = rowPtrsPacked_host(numOffsets - 1);
3475 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(valToCheck) != lclIndsPacked_wdv.extent(0),
3476 std::logic_error,
"After packing, rowPtrsPacked_dev_(" << (numOffsets - 1) <<
") = " << valToCheck <<
" != lclIndsPacked_wdv.extent(0) = " << lclIndsPacked_wdv.extent(0) <<
".");
3480 if (requestOptimizedStorage) {
3486 k_numRowEntries_ = num_row_entries_type();
3489 lclIndsUnpacked_wdv = lclIndsPacked_wdv;
3491 storageStatus_ = Details::STORAGE_1D_PACKED;
3494 set_need_sync_host_uvm_access();
3497template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3509 isLocallyIndexed() || isGloballyIndexed(), std::runtime_error,
3510 "Requires matching maps and non-static graph.");
3514template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3517 const Teuchos::RCP<const import_type>&
newImport,
3520 using Teuchos::REDUCE_MIN;
3521 using Teuchos::reduceAll;
3528 isFillComplete(), std::runtime_error,
3529 "The graph is fill complete "
3530 "(isFillComplete() returns true). You must call resumeFill() before "
3531 "you may call this method.");
3549 const LO
lclNumRows =
static_cast<LO
>(this->getLocalNumRows());
3583 if (indicesAreAllocated()) {
3584 if (isLocallyIndexed()) {
3589 const size_t allocSize = this->getLocalAllocationSize();
3590 auto oldLclInds1D = lclIndsUnpacked_wdv.getDeviceView(Access::ReadOnly);
3596 const auto LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
3597 const auto GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
3602 Kokkos::parallel_reduce(
3603 "Tpetra::CrsGraph::reindexColumns",
3604 Kokkos::RangePolicy<LocalOrdinal, execution_space>(0, allocSize),
3651 for (
size_t k = 0;
k <
rowInfo.numEntries; ++
k) {
3670 getRowMap().is_null() ? Teuchos::null : getRowMap()->getComm();
3671 if (!comm.is_null()) {
3677 "It is not possible to continue."
3678 " The most likely reason is that the graph is locally indexed, but the "
3679 "column Map is missing (null) on some processes, due to a previous call "
3680 "to replaceColMap().");
3684 "On some process, the graph "
3685 "contains column indices that are in the old column Map, but not in the "
3686 "new column Map (on that process). This method does NOT redistribute "
3687 "data; it does not claim to do the work of an Import or Export operation."
3688 " This means that for all processess, the calling process MUST own all "
3689 "column indices, in both the old column Map and the new column Map. In "
3690 "this case, you will need to do an Import or Export operation to "
3691 "redistribute data.");
3694 if (isLocallyIndexed()) {
3701 if (isLocallyIndexed()) {
3708 indicesAreSorted_ =
false;
3716 const bool sorted =
false;
3717 const bool merged =
true;
3731 if (!domainMap_.is_null()) {
3732 if (!domainMap_->isSameAs(*
newColMap)) {
3735 importer_ = Teuchos::null;
3744template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3747 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMap: ";
3749 colMap_.is_null(), std::invalid_argument,
prefix <<
"You may not call "
3750 "this method unless the graph already has a column Map.");
3753 prefix <<
"The new domain Map must be nonnull.");
3756 Teuchos::RCP<const import_type>
newImporter = Teuchos::null;
3763template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3766 const Teuchos::RCP<const import_type>&
newImporter) {
3767 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMapAndImporter: ";
3769 colMap_.is_null(), std::invalid_argument,
prefix <<
"You may not call "
3770 "this method unless the graph already has a column Map.");
3773 prefix <<
"The new domain Map must be nonnull.");
3783 "If the new Import is null, "
3784 "then the new domain Map must be the same as the current column Map.");
3787 colMap_->isSameAs(*(
newImporter->getTargetMap()));
3792 "new Import is nonnull, then the current column Map must be the same "
3793 "as the new Import's target Map, and the new domain Map must be the "
3794 "same as the new Import's source Map.");
3799 importer_ = Teuchos::rcp_const_cast<import_type>(
newImporter);
3802template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3805 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMap: ";
3807 rowMap_.is_null(), std::invalid_argument,
prefix <<
"You may not call "
3808 "this method unless the graph already has a row Map.");
3811 prefix <<
"The new range Map must be nonnull.");
3814 Teuchos::RCP<const export_type>
newExporter = Teuchos::null;
3821template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3824 const Teuchos::RCP<const export_type>&
newExporter) {
3825 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMapAndExporter: ";
3827 rowMap_.is_null(), std::invalid_argument,
prefix <<
"You may not call "
3828 "this method unless the graph already has a column Map.");
3831 prefix <<
"The new domain Map must be nonnull.");
3841 "If the new Export is null, "
3842 "then the new range Map must be the same as the current row Map.");
3847 rowMap_->isSameAs(*(
newExporter->getSourceMap()));
3850 "new Export is nonnull, then the current row Map must be the same "
3851 "as the new Export's source Map, and the new range Map must be the "
3852 "same as the new Export's target Map.");
3857 exporter_ = Teuchos::rcp_const_cast<export_type>(
newExporter);
3860template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3865 lclIndsPacked_wdv.getDeviceView(Access::ReadWrite),
3866 this->getRowPtrsPackedDevice());
3869template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3873 return local_graph_host_type(
3874 lclIndsPacked_wdv.getHostView(Access::ReadWrite),
3875 this->getRowPtrsPackedHost());
3878template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3881 using Teuchos::ArrayView;
3882 using Teuchos::outArg;
3883 using Teuchos::reduceAll;
3884 using ::Tpetra::Details::ProfilingRegion;
3887 ProfilingRegion
regionCGC(
"Tpetra::CrsGraph::computeGlobalConstants");
3889 this->computeLocalConstants();
3894 if (!this->haveGlobalConstants_) {
3895 const Teuchos::Comm<int>& comm = *(this->getComm());
3909 lcl =
static_cast<GST>(this->getLocalNumEntries());
3912 this->globalNumEntries_ =
gbl;
3916 outArg(this->globalMaxNumRowEntries_));
3917 this->haveGlobalConstants_ =
true;
3921template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3924 using ::Tpetra::Details::ProfilingRegion;
3926 ProfilingRegion
regionCLC(
"Tpetra::CrsGraph::computeLocalConstants");
3927 if (this->haveLocalConstants_) {
3932 this->nodeMaxNumRowEntries_ =
3933 Teuchos::OrdinalTraits<size_t>::invalid();
3937 auto ptr = this->getRowPtrsPackedDevice();
3938 const LO
lclNumRows =
ptr.extent(0) == 0 ?
static_cast<LO
>(0) : (
static_cast<LO
>(
ptr.extent(0)) -
static_cast<LO
>(1));
3941 ::Tpetra::Details::maxDifference(
"Tpetra::CrsGraph: nodeMaxNumRowEntries",
3944 this->haveLocalConstants_ =
true;
3947template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3948std::pair<size_t, std::string>
3953 using Teuchos::arcp;
3954 using Teuchos::Array;
3958 typedef typename local_graph_device_type::row_map_type::non_const_value_type offset_type;
3959 typedef typename num_row_entries_type::non_const_value_type
num_ent_type;
3963 std::unique_ptr<std::string>
prefix;
3965 prefix = this->createPrefix(
"CrsGraph",
"makeIndicesLocal");
3966 std::ostringstream
os;
3967 os << *
prefix <<
"lclNumRows: " << getLocalNumRows() <<
endl;
3968 std::cerr <<
os.str();
3974 "The graph does not have a "
3975 "column Map yet. This method should never be called in that case. "
3976 "Please report this bug to the Tpetra developers.");
3979 "that it has a column Map, because hasColMap() returns true. However, "
3980 "the result of getColMap() is null. This should never happen. Please "
3981 "report this bug to the Tpetra developers.");
3989 const LO
lclNumRows =
static_cast<LO
>(this->getLocalNumRows());
3992 if (this->isGloballyIndexed() &&
lclNumRows != 0) {
3994 typename num_row_entries_type::const_type
h_numRowEnt =
3995 this->k_numRowEntries_;
4001 errStrm <<
"Unpacked row pointers (rowPtrsUnpacked_dev_) has length 0. This should never "
4002 "happen here. Please report this bug to the Tpetra developers."
4005 return std::make_pair(Tpetra::Details::OrdinalTraits<size_t>::invalid(),
4017 using Kokkos::view_alloc;
4018 using Kokkos::WithoutInitializing;
4028 const std::string label(
"Tpetra::CrsGraph::lclInd");
4030 std::ostringstream
os;
4031 os << *
prefix <<
"(Re)allocate lclInd_wdv: old="
4032 << lclIndsUnpacked_wdv.extent(0) <<
", new=" <<
numEnt <<
endl;
4033 std::cerr <<
os.str();
4050 std::ostringstream
os;
4051 os << *
prefix <<
"Allocate device mirror k_numRowEnt: "
4053 std::cerr <<
os.str();
4058 using ::Tpetra::Details::convertColumnIndicesFromGlobalToLocal;
4061 lclIndsUnpacked_wdv.getDeviceView(Access::OverwriteAll),
4062 gblInds_wdv.getDeviceView(Access::ReadOnly),
4063 this->getRowPtrsUnpackedDevice(),
4067 const int myRank = [
this]() {
4068 auto map = this->getMap();
4069 if (
map.is_null()) {
4072 auto comm =
map->getComm();
4073 return comm.is_null() ? 0 : comm->getRank();
4077 errStrm <<
"(Process " <<
myRank <<
") When converting column "
4078 "indices from global to local, we encountered "
4082 <<
" not live in the column Map on this process." <<
endl;
4089 std::ostringstream
os;
4090 os << *
prefix <<
"Free gblInds_wdv: "
4091 << gblInds_wdv.extent(0) <<
endl;
4092 std::cerr <<
os.str();
4097 this->indicesAreLocal_ =
true;
4098 this->indicesAreGlobal_ =
false;
4099 this->checkInternalState();
4104template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4106 makeColMap(Teuchos::Array<int>& remotePIDs) {
4112 std::unique_ptr<std::string>
prefix;
4115 std::ostringstream
os;
4117 std::cerr <<
os.str();
4125 Teuchos::RCP<const map_type>
colMap = this->colMap_;
4127 this->sortGhostsAssociatedWithEachProcessor_;
4137 using Teuchos::outArg;
4138 using Teuchos::REDUCE_MIN;
4139 using Teuchos::reduceAll;
4145 auto comm = this->getComm();
4146 if (!comm.is_null()) {
4152 std::ostringstream
os;
4155 ": An error happened on at "
4156 "least one process in the CrsGraph's communicator. "
4157 "Here are all processes' error messages:"
4171 checkInternalState();
4173 std::ostringstream
os;
4175 std::cerr <<
os.str();
4179template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4184 using host_execution_space =
4185 typename Kokkos::View<LO*, device_type>::host_mirror_type::
4187 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
4191 std::unique_ptr<std::string>
prefix;
4194 std::ostringstream
os;
4196 <<
"sorted=" << (
sorted ?
"true" :
"false")
4197 <<
", merged=" << (
merged ?
"true" :
"false") <<
endl;
4198 std::cerr <<
os.str();
4200 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isGloballyIndexed(), std::logic_error,
4201 "This method may only be called after makeIndicesLocal.");
4202 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!merged && this->isStorageOptimized(), std::logic_error,
4203 "The graph is already storage optimized, so we shouldn't be "
4204 "merging any indices. "
4205 "Please report this bug to the Tpetra developers.");
4207 if (!sorted || !merged) {
4208 const LO lclNumRows(this->getLocalNumRows());
4209 auto range = range_type(0, lclNumRows);
4212 size_t totalNumDups = 0;
4214 lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
4216 Kokkos::parallel_reduce(
4218 [
this, sorted, merged](
const LO lclRow,
size_t& numDups) {
4219 const RowInfo rowInfo = this->getRowInfo(lclRow);
4220 numDups += this->sortAndMergeRowIndices(rowInfo, sorted, merged);
4224 std::ostringstream os;
4225 os << *prefix <<
"totalNumDups=" << totalNumDups << endl;
4226 std::cerr << os.str();
4229 (void)this->getRowPtrsUnpackedHost();
4231 lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
4233 Kokkos::parallel_for(range,
4234 [
this, sorted, merged](
const LO lclRow) {
4235 const RowInfo rowInfo = this->getRowInfo(lclRow);
4236 this->sortAndMergeRowIndices(rowInfo, sorted, merged);
4240 this->indicesAreSorted_ =
true;
4241 this->noRedundancies_ =
true;
4245 std::ostringstream os;
4246 os << *prefix <<
"Done" << endl;
4247 std::cerr << os.str();
4251template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4255 using Teuchos::ParameterList;
4258 using ::Tpetra::Details::ProfilingRegion;
4260 ProfilingRegion
regionMIE(
"Tpetra::CrsGraph::makeImportExport");
4263 "This method may not be called unless the graph has a column Map.");
4273 if (importer_.is_null()) {
4275 if (domainMap_ != colMap_ && (!domainMap_->isSameAs(*colMap_))) {
4276 if (
params.is_null() || !
params->isSublist(
"Import")) {
4278 importer_ =
rcp(
new import_type(domainMap_, colMap_, remotePIDs));
4298 if (exporter_.is_null()) {
4300 if (rangeMap_ != rowMap_ && !rangeMap_->isSameAs(*rowMap_)) {
4301 if (
params.is_null() || !
params->isSublist(
"Export")) {
4311template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4315 std::ostringstream
oss;
4316 oss << dist_object_type::description();
4317 if (isFillComplete()) {
4318 oss <<
"{status = fill complete"
4319 <<
", global rows = " << getGlobalNumRows()
4320 <<
", global cols = " << getGlobalNumCols()
4321 <<
", global num entries = " << getGlobalNumEntries()
4324 oss <<
"{status = fill not complete"
4325 <<
", global rows = " << getGlobalNumRows()
4331template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4334 const Teuchos::EVerbosityLevel
verbLevel)
const {
4337 using Teuchos::ArrayView;
4338 using Teuchos::Comm;
4340 using Teuchos::VERB_DEFAULT;
4341 using Teuchos::VERB_EXTREME;
4342 using Teuchos::VERB_HIGH;
4343 using Teuchos::VERB_LOW;
4344 using Teuchos::VERB_MEDIUM;
4345 using Teuchos::VERB_NONE;
4353 for (
size_t dec = 10;
dec < getGlobalNumRows();
dec *= 10) {
4356 width = std::max<size_t>(
width,
static_cast<size_t>(11)) + 2;
4366 if (
myImageID == 0)
out << this->description() << std::endl;
4368 if (isFillComplete() &&
myImageID == 0) {
4369 out <<
"Global max number of row entries = " << globalMaxNumRowEntries_ << std::endl;
4374 rowMap_->describe(
out,
vl);
4375 if (colMap_ != Teuchos::null) {
4376 if (
myImageID == 0)
out <<
"\nColumn map: " << std::endl;
4377 colMap_->describe(
out,
vl);
4379 if (domainMap_ != Teuchos::null) {
4380 if (
myImageID == 0)
out <<
"\nDomain map: " << std::endl;
4381 domainMap_->describe(
out,
vl);
4383 if (rangeMap_ != Teuchos::null) {
4384 if (
myImageID == 0)
out <<
"\nRange map: " << std::endl;
4385 rangeMap_->describe(
out,
vl);
4393 <<
"Node number of entries = " << this->getLocalNumEntries() << std::endl
4394 <<
"Node max number of entries = " << nodeMaxNumRowEntries_ << std::endl;
4395 if (!indicesAreAllocated()) {
4396 out <<
"Indices are not allocated." << std::endl;
4408 out << std::setw(
width) <<
"Node ID"
4409 << std::setw(
width) <<
"Global Row"
4410 << std::setw(
width) <<
"Num Entries";
4425 if (isGloballyIndexed()) {
4426 auto rowview = gblInds_wdv.getHostView(Access::ReadOnly);
4427 for (
size_t j = 0;
j <
rowinfo.numEntries; ++
j) {
4431 }
else if (isLocallyIndexed()) {
4432 auto rowview = lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
4433 for (
size_t j = 0;
j <
rowinfo.numEntries; ++
j) {
4435 out << colMap_->getGlobalElement(
collid) <<
" ";
4450template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4459template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4462 const size_t numSameIDs,
4473 const bool verbose = verbose_;
4475 std::unique_ptr<std::string>
prefix;
4477 prefix = this->createPrefix(
"CrsGraph",
"copyAndPermute");
4478 std::ostringstream
os;
4480 std::cerr <<
os.str();
4484 std::runtime_error,
"permuteToLIDs.extent(0) = " <<
permuteToLIDs.extent(0) <<
" != permuteFromLIDs.extent(0) = " <<
permuteFromLIDs.extent(0) <<
".");
4492 std::ostringstream
os;
4494 std::cerr <<
os.str();
4498 applyCrsPadding(*
padding, verbose);
4509 nonconst_global_inds_host_view_type
row_copy;
4517 std::ostringstream
os;
4518 os << *
prefix <<
"src_filled || srcCrsGraph == nullptr" <<
endl;
4519 std::cerr <<
os.str();
4526 for (
size_t i = 0;
i < numSameIDs; ++
i, ++
myid) {
4536 std::ostringstream
os;
4537 os << *
prefix <<
"! src_filled && srcCrsGraph != nullptr" <<
endl;
4538 std::cerr <<
os.str();
4540 for (
size_t i = 0;
i < numSameIDs; ++
i, ++
myid) {
4542 global_inds_host_view_type row;
4544 this->insertGlobalIndices(
gid, row.extent(0), row.data());
4568 global_inds_host_view_type row;
4570 this->insertGlobalIndices(
mygid, row.extent(0), row.data());
4575 std::ostringstream
os;
4577 std::cerr <<
os.str();
4581template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4584 const bool verbose) {
4588 using LO = local_ordinal_type;
4589 using row_ptrs_type =
4590 typename local_graph_device_type::row_map_type::non_const_type;
4592 Kokkos::RangePolicy<execution_space, Kokkos::IndexType<LO>>;
4594 ProfilingRegion
regionCAP(
"Tpetra::CrsGraph::applyCrsPadding");
4596 std::unique_ptr<std::string>
prefix;
4599 std::ostringstream
os;
4603 std::cerr <<
os.str();
4605 const int myRank = !verbose ? -1 : [&]() {
4606 auto map = this->getMap();
4607 if (map.is_null()) {
4610 auto comm = map->getComm();
4611 if (comm.is_null()) {
4614 return comm->getRank();
4623 if (!indicesAreAllocated()) {
4625 std::ostringstream os;
4626 os << *prefix <<
"Call allocateIndices" << endl;
4627 std::cerr << os.str();
4629 allocateIndices(GlobalIndices, verbose);
4631 TEUCHOS_ASSERT(indicesAreAllocated());
4636 auto rowPtrsUnpacked_dev = this->getRowPtrsUnpackedDevice();
4638 std::ostringstream os;
4639 os << *prefix <<
"Allocate row_ptrs_beg: "
4640 << rowPtrsUnpacked_dev.extent(0) << endl;
4641 std::cerr << os.str();
4643 using Kokkos::view_alloc;
4644 using Kokkos::WithoutInitializing;
4645 row_ptrs_type row_ptrs_beg(
4646 view_alloc(
"row_ptrs_beg", WithoutInitializing),
4647 rowPtrsUnpacked_dev.extent(0));
4649 Kokkos::deep_copy(execution_space(), row_ptrs_beg, rowPtrsUnpacked_dev);
4651 const size_t N = row_ptrs_beg.extent(0) == 0 ? size_t(0) : size_t(row_ptrs_beg.extent(0) - 1);
4653 std::ostringstream os;
4654 os << *prefix <<
"Allocate row_ptrs_end: " << N << endl;
4655 std::cerr << os.str();
4657 row_ptrs_type row_ptrs_end(
4658 view_alloc(
"row_ptrs_end", WithoutInitializing), N);
4659 row_ptrs_type num_row_entries;
4661 const bool refill_num_row_entries = k_numRowEntries_.extent(0) != 0;
4663 execution_space().fence();
4665 if (refill_num_row_entries) {
4669 row_ptrs_type(view_alloc(
"num_row_entries", WithoutInitializing), N);
4670 Kokkos::deep_copy(num_row_entries, this->k_numRowEntries_);
4671 Kokkos::parallel_for(
4672 "Fill end row pointers", range_policy(0, N),
4673 KOKKOS_LAMBDA(
const size_t i) {
4674 row_ptrs_end(i) = row_ptrs_beg(i) + num_row_entries(i);
4680 Kokkos::parallel_for(
4681 "Fill end row pointers", range_policy(0, N),
4682 KOKKOS_LAMBDA(
const size_t i) {
4683 row_ptrs_end(i) = row_ptrs_beg(i + 1);
4687 if (isGloballyIndexed()) {
4689 padding, myRank, verbose);
4691 padCrsArrays(row_ptrs_beg, row_ptrs_end, lclIndsUnpacked_wdv,
4692 padding, myRank, verbose);
4695 if (refill_num_row_entries) {
4696 Kokkos::parallel_for(
4697 "Fill num entries", range_policy(0, N),
4698 KOKKOS_LAMBDA(
const size_t i) {
4699 num_row_entries(i) = row_ptrs_end(i) - row_ptrs_beg(i);
4701 Kokkos::deep_copy(this->k_numRowEntries_, num_row_entries);
4704 std::ostringstream os;
4705 os << *prefix <<
"Reassign k_rowPtrs_; old size: "
4706 << rowPtrsUnpacked_dev.extent(0) <<
", new size: "
4707 << row_ptrs_beg.extent(0) << endl;
4708 std::cerr << os.str();
4709 TEUCHOS_ASSERT(rowPtrsUnpacked_dev.extent(0) == row_ptrs_beg.extent(0));
4712 setRowPtrsUnpacked(row_ptrs_beg);
4715template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4717 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
4718CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
4720 const RowGraph<LocalOrdinal, GlobalOrdinal, Node>& source,
4721 const size_t numSameIDs,
4722 const Kokkos::DualView<
const local_ordinal_type*,
4723 buffer_device_type>& permuteToLIDs,
4724 const Kokkos::DualView<
const local_ordinal_type*,
4725 buffer_device_type>& permuteFromLIDs,
4726 const bool verbose)
const {
4730 std::unique_ptr<std::string> prefix;
4733 "computeCrsPadding(same & permute)");
4734 std::ostringstream os;
4735 os << *prefix <<
"{numSameIDs: " << numSameIDs
4736 <<
", numPermutes: " << permuteFromLIDs.extent(0) <<
"}"
4738 std::cerr << os.str();
4741 const int myRank = [&]() {
4742 auto comm = rowMap_.is_null() ? Teuchos::null : rowMap_->getComm();
4743 return comm.is_null() ? -1 : comm->getRank();
4745 std::unique_ptr<padding_type> padding(
4746 new padding_type(myRank, numSameIDs,
4747 permuteFromLIDs.extent(0)));
4749 computeCrsPaddingForSameIDs(*padding, source,
4750 static_cast<LO
>(numSameIDs));
4751 computeCrsPaddingForPermutedIDs(*padding, source, permuteToLIDs,
4756template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4757void CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
4758 computeCrsPaddingForSameIDs(
4759 padding_type& padding,
4760 const RowGraph<local_ordinal_type, global_ordinal_type,
4762 const local_ordinal_type numSameIDs)
const {
4764 using GO = global_ordinal_type;
4765 using Details::Impl::getRowGraphGlobalRow;
4767 const char tfecfFuncName[] =
"computeCrsPaddingForSameIds";
4769 std::unique_ptr<std::string> prefix;
4770 const bool verbose = verbose_;
4772 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
4773 std::ostringstream os;
4774 os << *prefix <<
"numSameIDs: " << numSameIDs << endl;
4775 std::cerr << os.str();
4778 if (numSameIDs == 0) {
4782 const map_type& srcRowMap = *(source.getRowMap());
4783 const map_type& tgtRowMap = *rowMap_;
4784 using this_CRS_type = CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
4785 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
4786 const bool src_is_unique =
4787 srcCrs ==
nullptr ? false : srcCrs->isMerged();
4788 const bool tgt_is_unique = this->isMerged();
4790 std::vector<GO> srcGblColIndsScratch;
4791 std::vector<GO> tgtGblColIndsScratch;
4793 execute_sync_host_uvm_access();
4794 for (LO lclRowInd = 0; lclRowInd < numSameIDs; ++lclRowInd) {
4795 const GO srcGblRowInd = srcRowMap.getGlobalElement(lclRowInd);
4796 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(lclRowInd);
4797 auto srcGblColInds = getRowGraphGlobalRow(
4798 srcGblColIndsScratch, source, srcGblRowInd);
4799 auto tgtGblColInds = getRowGraphGlobalRow(
4800 tgtGblColIndsScratch, *
this, tgtGblRowInd);
4801 padding.update_same(lclRowInd, tgtGblColInds.getRawPtr(),
4802 tgtGblColInds.size(), tgt_is_unique,
4803 srcGblColInds.getRawPtr(),
4804 srcGblColInds.size(), src_is_unique);
4807 std::ostringstream os;
4808 os << *prefix <<
"Done" << endl;
4809 std::cerr << os.str();
4813template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4814void CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
4815 computeCrsPaddingForPermutedIDs(
4816 padding_type& padding,
4817 const RowGraph<local_ordinal_type, global_ordinal_type,
4819 const Kokkos::DualView<
const local_ordinal_type*,
4820 buffer_device_type>& permuteToLIDs,
4821 const Kokkos::DualView<
const local_ordinal_type*,
4822 buffer_device_type>& permuteFromLIDs)
const {
4824 using GO = global_ordinal_type;
4825 using Details::Impl::getRowGraphGlobalRow;
4827 const char tfecfFuncName[] =
"computeCrsPaddingForPermutedIds";
4829 std::unique_ptr<std::string> prefix;
4830 const bool verbose = verbose_;
4832 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
4833 std::ostringstream os;
4834 os << *prefix <<
"permuteToLIDs.extent(0): "
4835 << permuteToLIDs.extent(0)
4836 <<
", permuteFromLIDs.extent(0): "
4837 << permuteFromLIDs.extent(0) << endl;
4838 std::cerr << os.str();
4841 if (permuteToLIDs.extent(0) == 0) {
4845 const map_type& srcRowMap = *(source.getRowMap());
4846 const map_type& tgtRowMap = *rowMap_;
4847 using this_CRS_type = CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
4848 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
4849 const bool src_is_unique =
4850 srcCrs ==
nullptr ? false : srcCrs->isMerged();
4851 const bool tgt_is_unique = this->isMerged();
4853 TEUCHOS_ASSERT(!permuteToLIDs.need_sync_host());
4854 auto permuteToLIDs_h = permuteToLIDs.view_host();
4855 TEUCHOS_ASSERT(!permuteFromLIDs.need_sync_host());
4856 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
4858 std::vector<GO> srcGblColIndsScratch;
4859 std::vector<GO> tgtGblColIndsScratch;
4860 const LO numPermutes =
static_cast<LO
>(permuteToLIDs_h.extent(0));
4862 execute_sync_host_uvm_access();
4863 for (LO whichPermute = 0; whichPermute < numPermutes; ++whichPermute) {
4864 const LO srcLclRowInd = permuteFromLIDs_h[whichPermute];
4865 const GO srcGblRowInd = srcRowMap.getGlobalElement(srcLclRowInd);
4866 auto srcGblColInds = getRowGraphGlobalRow(
4867 srcGblColIndsScratch, source, srcGblRowInd);
4868 const LO tgtLclRowInd = permuteToLIDs_h[whichPermute];
4869 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(tgtLclRowInd);
4870 auto tgtGblColInds = getRowGraphGlobalRow(
4871 tgtGblColIndsScratch, *
this, tgtGblRowInd);
4872 padding.update_permute(whichPermute, tgtLclRowInd,
4873 tgtGblColInds.getRawPtr(),
4874 tgtGblColInds.size(), tgt_is_unique,
4875 srcGblColInds.getRawPtr(),
4876 srcGblColInds.size(), src_is_unique);
4880 std::ostringstream os;
4881 os << *prefix <<
"Done" << endl;
4882 std::cerr << os.str();
4886template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4888 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
4889CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
4890 computeCrsPaddingForImports(
4891 const Kokkos::DualView<
const local_ordinal_type*,
4892 buffer_device_type>& importLIDs,
4893 Kokkos::DualView<packet_type*, buffer_device_type> imports,
4894 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
4895 const bool verbose)
const {
4896 using Details::Impl::getRowGraphGlobalRow;
4899 using GO = global_ordinal_type;
4900 const char tfecfFuncName[] =
"computeCrsPaddingForImports";
4902 std::unique_ptr<std::string> prefix;
4904 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
4905 std::ostringstream os;
4906 os << *prefix <<
"importLIDs.extent(0): "
4907 << importLIDs.extent(0)
4908 <<
", imports.extent(0): "
4909 << imports.extent(0)
4910 <<
", numPacketsPerLID.extent(0): "
4911 << numPacketsPerLID.extent(0) << endl;
4912 std::cerr << os.str();
4915 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
4916 const int myRank = [&]() {
4917 auto comm = rowMap_.is_null() ? Teuchos::null : rowMap_->getComm();
4918 return comm.is_null() ? -1 : comm->getRank();
4920 std::unique_ptr<padding_type> padding(
4921 new padding_type(myRank, numImports));
4923 if (imports.need_sync_host()) {
4924 imports.sync_host();
4926 auto imports_h = imports.view_host();
4927 if (numPacketsPerLID.need_sync_host()) {
4928 numPacketsPerLID.sync_host();
4930 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
4932 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
4933 auto importLIDs_h = importLIDs.view_host();
4935 const map_type& tgtRowMap = *rowMap_;
4939 constexpr bool src_is_unique =
false;
4940 const bool tgt_is_unique = isMerged();
4942 std::vector<GO> tgtGblColIndsScratch;
4944 execute_sync_host_uvm_access();
4945 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
4950 const LO origSrcNumEnt =
4951 static_cast<LO
>(numPacketsPerLID_h[whichImport]);
4952 GO*
const srcGblColInds = imports_h.data() + offset;
4954 const LO tgtLclRowInd = importLIDs_h[whichImport];
4955 const GO tgtGblRowInd =
4956 tgtRowMap.getGlobalElement(tgtLclRowInd);
4957 auto tgtGblColInds = getRowGraphGlobalRow(
4958 tgtGblColIndsScratch, *
this, tgtGblRowInd);
4959 const size_t origTgtNumEnt(tgtGblColInds.size());
4961 padding->update_import(whichImport, tgtLclRowInd,
4962 tgtGblColInds.getRawPtr(),
4963 origTgtNumEnt, tgt_is_unique,
4965 origSrcNumEnt, src_is_unique);
4966 offset += origSrcNumEnt;
4970 std::ostringstream os;
4971 os << *prefix <<
"Done" << endl;
4972 std::cerr << os.str();
4977template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4979 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
4980CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
4981 computePaddingForCrsMatrixUnpack(
4982 const Kokkos::DualView<
const local_ordinal_type*,
4983 buffer_device_type>& importLIDs,
4984 Kokkos::DualView<char*, buffer_device_type> imports,
4985 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
4986 const bool verbose)
const {
4987 using Details::PackTraits;
4988 using Details::Impl::getRowGraphGlobalRow;
4991 using GO = global_ordinal_type;
4992 const char tfecfFuncName[] =
"computePaddingForCrsMatrixUnpack";
4994 std::unique_ptr<std::string> prefix;
4996 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
4997 std::ostringstream os;
4998 os << *prefix <<
"importLIDs.extent(0): "
4999 << importLIDs.extent(0)
5000 <<
", imports.extent(0): "
5001 << imports.extent(0)
5002 <<
", numPacketsPerLID.extent(0): "
5003 << numPacketsPerLID.extent(0) << endl;
5004 std::cerr << os.str();
5006 const bool extraVerbose =
5009 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5010 TEUCHOS_ASSERT(LO(numPacketsPerLID.extent(0)) >= numImports);
5011 const int myRank = [&]() {
5012 auto comm = rowMap_.is_null() ? Teuchos::null : rowMap_->getComm();
5013 return comm.is_null() ? -1 : comm->getRank();
5015 std::unique_ptr<padding_type> padding(
5016 new padding_type(myRank, numImports));
5018 if (imports.need_sync_host()) {
5019 imports.sync_host();
5021 auto imports_h = imports.view_host();
5022 if (numPacketsPerLID.need_sync_host()) {
5023 numPacketsPerLID.sync_host();
5025 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5027 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
5028 auto importLIDs_h = importLIDs.view_host();
5030 const map_type& tgtRowMap = *rowMap_;
5034 constexpr bool src_is_unique =
false;
5035 const bool tgt_is_unique = isMerged();
5037 std::vector<GO> srcGblColIndsScratch;
5038 std::vector<GO> tgtGblColIndsScratch;
5040 execute_sync_host_uvm_access();
5041 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5046 const size_t numBytes = numPacketsPerLID_h[whichImport];
5048 std::ostringstream os;
5049 os << *prefix <<
"whichImport=" << whichImport
5050 <<
", numImports=" << numImports
5051 <<
", numBytes=" << numBytes << endl;
5052 std::cerr << os.str();
5054 if (numBytes == 0) {
5057 LO origSrcNumEnt = 0;
5058 const size_t numEntBeg = offset;
5059 const size_t numEntLen =
5060 PackTraits<LO>::packValueCount(origSrcNumEnt);
5061 TEUCHOS_ASSERT(numBytes >= numEntLen);
5062 TEUCHOS_ASSERT(imports_h.extent(0) >= numEntBeg + numEntLen);
5063 PackTraits<LO>::unpackValue(origSrcNumEnt,
5064 imports_h.data() + numEntBeg);
5066 std::ostringstream os;
5067 os << *prefix <<
"whichImport=" << whichImport
5068 <<
", numImports=" << numImports
5069 <<
", origSrcNumEnt=" << origSrcNumEnt << endl;
5070 std::cerr << os.str();
5072 TEUCHOS_ASSERT(origSrcNumEnt >= LO(0));
5073 TEUCHOS_ASSERT(numBytes >=
size_t(numEntLen + origSrcNumEnt *
sizeof(GO)));
5074 const size_t gidsBeg = numEntBeg + numEntLen;
5075 if (srcGblColIndsScratch.size() <
size_t(origSrcNumEnt)) {
5076 srcGblColIndsScratch.resize(origSrcNumEnt);
5078 GO*
const srcGblColInds = srcGblColIndsScratch.data();
5079 PackTraits<GO>::unpackArray(srcGblColInds,
5080 imports_h.data() + gidsBeg,
5082 const LO tgtLclRowInd = importLIDs_h[whichImport];
5083 const GO tgtGblRowInd =
5084 tgtRowMap.getGlobalElement(tgtLclRowInd);
5085 auto tgtGblColInds = getRowGraphGlobalRow(
5086 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5087 const size_t origNumTgtEnt(tgtGblColInds.size());
5090 std::ostringstream os;
5091 os << *prefix <<
"whichImport=" << whichImport
5092 <<
", numImports=" << numImports
5093 <<
": Call padding->update_import" << endl;
5094 std::cerr << os.str();
5096 padding->update_import(whichImport, tgtLclRowInd,
5097 tgtGblColInds.getRawPtr(),
5098 origNumTgtEnt, tgt_is_unique,
5100 origSrcNumEnt, src_is_unique);
5105 std::ostringstream os;
5106 os << *prefix <<
"Done" << endl;
5107 std::cerr << os.str();
5112template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5113void CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5114 packAndPrepare(
const SrcDistObject& source,
5115 const Kokkos::DualView<
const local_ordinal_type*,
5116 buffer_device_type>& exportLIDs,
5117 Kokkos::DualView<packet_type*,
5118 buffer_device_type>& exports,
5119 Kokkos::DualView<
size_t*,
5122 size_t& constantNumPackets) {
5124 using GO = global_ordinal_type;
5126 using crs_graph_type =
5127 CrsGraph<local_ordinal_type, global_ordinal_type, node_type>;
5128 const char tfecfFuncName[] =
"packAndPrepare: ";
5129 ProfilingRegion region_papn(
"Tpetra::CrsGraph::packAndPrepare");
5131 const bool verbose = verbose_;
5132 std::unique_ptr<std::string> prefix;
5134 prefix = this->
createPrefix(
"CrsGraph",
"packAndPrepare");
5135 std::ostringstream os;
5136 os << *prefix <<
"Start" << endl;
5137 std::cerr << os.str();
5140 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(exportLIDs.extent(0) != numPacketsPerLID.extent(0),
5142 "exportLIDs.extent(0) = " << exportLIDs.extent(0)
5143 <<
" != numPacketsPerLID.extent(0) = " << numPacketsPerLID.extent(0)
5145 const row_graph_type* srcRowGraphPtr =
5146 dynamic_cast<const row_graph_type*
>(&source);
5147 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(srcRowGraphPtr ==
nullptr, std::invalid_argument,
5148 "Source of an Export "
5149 "or Import operation to a CrsGraph must be a RowGraph with the same "
5150 "template parameters.");
5154 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isFillComplete(), std::runtime_error,
5155 "The target graph of an Import or Export must not be fill complete.");
5157 const crs_graph_type* srcCrsGraphPtr =
5158 dynamic_cast<const crs_graph_type*
>(&source);
5160 if (srcCrsGraphPtr ==
nullptr) {
5161 using Teuchos::ArrayView;
5165 std::ostringstream os;
5166 os << *prefix <<
"Source is a RowGraph but not a CrsGraph"
5168 std::cerr << os.str();
5175 TEUCHOS_ASSERT(!exportLIDs.need_sync_host());
5176 auto exportLIDs_h = exportLIDs.view_host();
5177 ArrayView<const LO> exportLIDs_av(exportLIDs_h.data(),
5178 exportLIDs_h.extent(0));
5179 Teuchos::Array<GO> exports_a;
5181 numPacketsPerLID.clear_sync_state();
5182 numPacketsPerLID.modify_host();
5183 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5184 ArrayView<size_t> numPacketsPerLID_av(numPacketsPerLID_h.data(),
5185 numPacketsPerLID_h.extent(0));
5186 srcRowGraphPtr->pack(exportLIDs_av, exports_a, numPacketsPerLID_av,
5187 constantNumPackets);
5188 const size_t newSize =
static_cast<size_t>(exports_a.size());
5189 if (
static_cast<size_t>(exports.extent(0)) != newSize) {
5190 using exports_dv_type = Kokkos::DualView<packet_type*, buffer_device_type>;
5191 exports = exports_dv_type(
"exports", newSize);
5193 Kokkos::View<
const packet_type*, Kokkos::HostSpace,
5194 Kokkos::MemoryUnmanaged>
5195 exports_a_h(exports_a.getRawPtr(), newSize);
5196 exports.clear_sync_state();
5197 exports.modify_host();
5199 Kokkos::deep_copy(exports.view_host(), exports_a_h);
5202 else if (!getColMap().is_null() &&
5203 (this->getRowPtrsPackedDevice().extent(0) != 0 ||
5204 getRowMap()->getLocalNumElements() == 0)) {
5206 std::ostringstream os;
5207 os << *prefix <<
"packCrsGraphNew path" << endl;
5208 std::cerr << os.str();
5210 using export_pids_type =
5211 Kokkos::DualView<const int*, buffer_device_type>;
5212 export_pids_type exportPIDs;
5214 using NT = node_type;
5216 packCrsGraphNew<LO, GO, NT>(*srcCrsGraphPtr, exportLIDs, exportPIDs,
5217 exports, numPacketsPerLID,
5218 constantNumPackets,
false);
5220 srcCrsGraphPtr->packFillActiveNew(exportLIDs, exports, numPacketsPerLID,
5221 constantNumPackets);
5225 std::ostringstream os;
5226 os << *prefix <<
"Done" << endl;
5227 std::cerr << os.str();
5231template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5234 Teuchos::Array<GlobalOrdinal>& exports,
5237 auto col_map = this->getColMap();
5239 if (!
col_map.is_null() && (
this->getRowPtrsPackedDevice().extent(0) != 0 || getRowMap()->getLocalNumElements() == 0)) {
5249template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5252 Teuchos::Array<GlobalOrdinal>& exports,
5258 using host_execution_space =
5259 typename Kokkos::View<size_t*, device_type>::
5260 host_mirror_type::execution_space;
5262 const bool verbose = verbose_;
5265 std::unique_ptr<std::string>
prefix;
5267 prefix = this->createPrefix(
"CrsGraph",
"allocateIndices");
5268 std::ostringstream
os;
5270 std::cerr <<
os.str();
5272 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numExportLIDs != numPacketsPerLID.size(), std::runtime_error,
5273 "exportLIDs.size() = " << numExportLIDs <<
" != numPacketsPerLID.size()"
5275 << numPacketsPerLID.size() <<
".");
5277 const map_type&
rowMap = *(this->getRowMap());
5278 const map_type*
const colMapPtr = this->colMap_.getRawPtr();
5279 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isLocallyIndexed() && colMapPtr ==
nullptr, std::logic_error,
5280 "This graph claims to be locally indexed, but its column Map is nullptr. "
5281 "This should never happen. Please report this bug to the Tpetra "
5285 constantNumPackets = 0;
5289 size_t*
const numPacketsPerLID_raw = numPacketsPerLID.getRawPtr();
5290 const LO*
const exportLIDs_raw = exportLIDs.getRawPtr();
5297 Kokkos::RangePolicy<host_execution_space, LO> inputRange(0, numExportLIDs);
5298 size_t totalNumPackets = 0;
5299 size_t errCount = 0;
5302 typedef Kokkos::Device<host_execution_space, Kokkos::HostSpace>
5304 Kokkos::View<size_t, host_device_type> errCountView(&errCount);
5305 constexpr size_t ONE = 1;
5307 execute_sync_host_uvm_access();
5308 Kokkos::parallel_reduce(
5309 "Tpetra::CrsGraph::pack: totalNumPackets",
5311 [=, *
this](
const LO& i,
size_t& curTotalNumPackets) {
5312 const GO gblRow =
rowMap.getGlobalElement(exportLIDs_raw[i]);
5313 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid()) {
5314 Kokkos::atomic_add(&errCountView(), ONE);
5315 numPacketsPerLID_raw[i] = 0;
5317 const size_t numEnt = this->getNumEntriesInGlobalRow(gblRow);
5318 numPacketsPerLID_raw[i] = numEnt;
5319 curTotalNumPackets += numEnt;
5325 std::ostringstream os;
5326 os << *prefix <<
"totalNumPackets=" << totalNumPackets << endl;
5327 std::cerr << os.str();
5329 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(errCount != 0, std::logic_error,
5330 "totalNumPackets count encountered "
5331 "one or more errors! errCount = "
5333 <<
", totalNumPackets = " << totalNumPackets <<
".");
5337 exports.resize(totalNumPackets);
5339 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->supportsRowViews(), std::logic_error,
5340 "this->supportsRowViews() returns false; this should never happen. "
5341 "Please report this bug to the Tpetra developers.");
5347 std::ostringstream os;
5348 os << *prefix <<
"Pack into exports" << endl;
5349 std::cerr << os.str();
5354 GO*
const exports_raw = exports.getRawPtr();
5356 Kokkos::parallel_scan(
"Tpetra::CrsGraph::pack: pack from views",
5357 inputRange, [=, &prefix, *
this](
const LO i,
size_t& exportsOffset,
const bool final) {
5358 const size_t curOffset = exportsOffset;
5359 const GO gblRow =
rowMap.getGlobalElement(exportLIDs_raw[i]);
5360 const RowInfo rowInfo =
5361 this->getRowInfoFromGlobalRowIndex(gblRow);
5363 using TDO = Tpetra::Details::OrdinalTraits<size_t>;
5364 if (rowInfo.localRow == TDO::invalid()) {
5366 std::ostringstream os;
5367 os << *prefix <<
": INVALID rowInfo: i=" << i
5368 <<
", lclRow=" << exportLIDs_raw[i] << endl;
5369 std::cerr << os.str();
5371 Kokkos::atomic_add(&errCountView(), ONE);
5372 }
else if (curOffset + rowInfo.numEntries > totalNumPackets) {
5374 std::ostringstream os;
5375 os << *prefix <<
": UH OH! For i=" << i <<
", lclRow="
5376 << exportLIDs_raw[i] <<
", gblRow=" << gblRow <<
", curOffset "
5378 << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5379 <<
") > totalNumPackets (= " << totalNumPackets <<
")."
5381 std::cerr << os.str();
5383 Kokkos::atomic_add(&errCountView(), ONE);
5385 const LO numEnt =
static_cast<LO
>(rowInfo.numEntries);
5386 if (this->isLocallyIndexed()) {
5387 auto lclColInds = getLocalIndsViewHost(rowInfo);
5389 for (LO k = 0; k < numEnt; ++k) {
5390 const LO lclColInd = lclColInds(k);
5391 const GO gblColInd = colMapPtr->getGlobalElement(lclColInd);
5395 exports_raw[curOffset + k] = gblColInd;
5398 exportsOffset = curOffset + numEnt;
5399 }
else if (this->isGloballyIndexed()) {
5400 auto gblColInds = getGlobalIndsViewHost(rowInfo);
5402 for (LO k = 0; k < numEnt; ++k) {
5403 const GO gblColInd = gblColInds(k);
5407 exports_raw[curOffset + k] = gblColInd;
5410 exportsOffset = curOffset + numEnt;
5418 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(errCount != 0, std::logic_error,
5419 "Packing encountered "
5420 "one or more errors! errCount = "
5422 <<
", totalNumPackets = " << totalNumPackets <<
".");
5425 std::ostringstream os;
5426 os << *prefix <<
"Done" << endl;
5427 std::cerr << os.str();
5431template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5432void CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5433 packFillActiveNew(
const Kokkos::DualView<
const local_ordinal_type*,
5434 buffer_device_type>& exportLIDs,
5435 Kokkos::DualView<packet_type*,
5436 buffer_device_type>& exports,
5437 Kokkos::DualView<
size_t*,
5440 size_t& constantNumPackets)
const {
5443 using GO = global_ordinal_type;
5444 using host_execution_space =
typename Kokkos::View<
size_t*,
5445 device_type>::host_mirror_type::execution_space;
5446 using host_device_type =
5447 Kokkos::Device<host_execution_space, Kokkos::HostSpace>;
5448 using exports_dv_type =
5449 Kokkos::DualView<packet_type*, buffer_device_type>;
5450 const char tfecfFuncName[] =
"packFillActiveNew: ";
5451 const bool verbose = verbose_;
5453 const auto numExportLIDs = exportLIDs.extent(0);
5454 std::unique_ptr<std::string> prefix;
5456 prefix = this->
createPrefix(
"CrsGraph",
"packFillActiveNew");
5457 std::ostringstream os;
5458 os << *prefix <<
"numExportLIDs: " << numExportLIDs
5459 <<
", numPacketsPerLID.extent(0): "
5460 << numPacketsPerLID.extent(0) << endl;
5461 std::cerr << os.str();
5463 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numExportLIDs != numPacketsPerLID.extent(0), std::runtime_error,
5464 "exportLIDs.extent(0) = " << numExportLIDs
5465 <<
" != numPacketsPerLID.extent(0) = "
5466 << numPacketsPerLID.extent(0) <<
".");
5467 TEUCHOS_ASSERT(!exportLIDs.need_sync_host());
5468 auto exportLIDs_h = exportLIDs.view_host();
5470 const map_type&
rowMap = *(this->getRowMap());
5471 const map_type*
const colMapPtr = this->colMap_.getRawPtr();
5472 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isLocallyIndexed() && colMapPtr ==
nullptr, std::logic_error,
5473 "This graph claims to be locally indexed, but its column Map is nullptr. "
5474 "This should never happen. Please report this bug to the Tpetra "
5478 constantNumPackets = 0;
5480 numPacketsPerLID.clear_sync_state();
5481 numPacketsPerLID.modify_host();
5482 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5489 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
5490 range_type inputRange(0, numExportLIDs);
5491 size_t totalNumPackets = 0;
5492 size_t errCount = 0;
5495 Kokkos::View<size_t, host_device_type> errCountView(&errCount);
5496 constexpr size_t ONE = 1;
5499 std::ostringstream os;
5500 os << *prefix <<
"Compute totalNumPackets" << endl;
5501 std::cerr << os.str();
5504 execute_sync_host_uvm_access();
5505 totalNumPackets = 0;
5506 for (
size_t i = 0; i < numExportLIDs; ++i) {
5507 const LO lclRow = exportLIDs_h[i];
5508 const GO gblRow =
rowMap.getGlobalElement(lclRow);
5509 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid()) {
5511 std::ostringstream os;
5512 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5513 <<
" not in row Map on this process" << endl;
5514 std::cerr << os.str();
5516 Kokkos::atomic_add(&errCountView(), ONE);
5517 numPacketsPerLID_h(i) = 0;
5519 const size_t numEnt = this->getNumEntriesInGlobalRow(gblRow);
5520 numPacketsPerLID_h(i) = numEnt;
5521 totalNumPackets += numEnt;
5526 std::ostringstream os;
5527 os << *prefix <<
"totalNumPackets: " << totalNumPackets
5528 <<
", errCount: " << errCount << endl;
5529 std::cerr << os.str();
5531 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(errCount != 0, std::logic_error,
5532 "totalNumPackets count encountered "
5533 "one or more errors! totalNumPackets: "
5535 <<
", errCount: " << errCount <<
".");
5538 if (
size_t(exports.extent(0)) < totalNumPackets) {
5540 exports = exports_dv_type(
"exports", totalNumPackets);
5543 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->supportsRowViews(), std::logic_error,
5544 "this->supportsRowViews() returns false; this should never happen. "
5545 "Please report this bug to the Tpetra developers.");
5551 std::ostringstream os;
5552 os << *prefix <<
"Pack into exports buffer" << endl;
5553 std::cerr << os.str();
5556 exports.clear_sync_state();
5557 exports.modify_host();
5558 auto exports_h = exports.view_host();
5564 if (isLocallyIndexed())
5565 lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
5566 else if (isGloballyIndexed())
5567 gblInds_wdv.getHostView(Access::ReadOnly);
5570 Kokkos::parallel_scan(
"Tpetra::CrsGraph::packFillActiveNew: Pack exports",
5571 inputRange, [=, &prefix, *
this](
const LO i,
size_t& exportsOffset,
const bool final) {
5572 const size_t curOffset = exportsOffset;
5573 const LO lclRow = exportLIDs_h(i);
5574 const GO gblRow =
rowMap.getGlobalElement(lclRow);
5575 if (gblRow == Details::OrdinalTraits<GO>::invalid()) {
5577 std::ostringstream os;
5578 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5579 <<
" not in row Map on this process" << endl;
5580 std::cerr << os.str();
5582 Kokkos::atomic_add(&errCountView(), ONE);
5586 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex(gblRow);
5587 if (rowInfo.localRow == Details::OrdinalTraits<size_t>::invalid()) {
5589 std::ostringstream os;
5590 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5591 <<
", gblRow=" << gblRow <<
": invalid rowInfo"
5593 std::cerr << os.str();
5595 Kokkos::atomic_add(&errCountView(), ONE);
5599 if (curOffset + rowInfo.numEntries > totalNumPackets) {
5601 std::ostringstream os;
5602 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5603 <<
", gblRow=" << gblRow <<
", curOffset (= "
5604 << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5605 <<
") > totalNumPackets (= " << totalNumPackets
5607 std::cerr << os.str();
5609 Kokkos::atomic_add(&errCountView(), ONE);
5613 const LO numEnt =
static_cast<LO
>(rowInfo.numEntries);
5614 if (this->isLocallyIndexed()) {
5615 auto lclColInds = getLocalIndsViewHost(rowInfo);
5617 for (LO k = 0; k < numEnt; ++k) {
5618 const LO lclColInd = lclColInds(k);
5619 const GO gblColInd = colMapPtr->getGlobalElement(lclColInd);
5623 exports_h(curOffset + k) = gblColInd;
5626 exportsOffset = curOffset + numEnt;
5627 }
else if (this->isGloballyIndexed()) {
5628 auto gblColInds = getGlobalIndsViewHost(rowInfo);
5630 for (LO k = 0; k < numEnt; ++k) {
5631 const GO gblColInd = gblColInds(k);
5635 exports_h(curOffset + k) = gblColInd;
5638 exportsOffset = curOffset + numEnt;
5652 std::ostringstream os;
5653 os << *prefix <<
"errCount=" << errCount <<
"; Done" << endl;
5654 std::cerr << os.str();
5658template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5665 Kokkos::DualView<
size_t*,
5676 ProfilingRegion
regionCGC(
"Tpetra::CrsGraph::unpackAndCombine");
5677 const bool verbose = verbose_;
5679 std::unique_ptr<std::string>
prefix;
5682 std::ostringstream
os;
5684 std::cerr <<
os.str();
5687 auto padding = computeCrsPaddingForImports(
5689 applyCrsPadding(*
padding, verbose);
5691 std::ostringstream
os;
5692 os << *
prefix <<
"Done computing & applying padding" <<
endl;
5693 std::cerr <<
os.str();
5715 std::runtime_error,
": importLIDs.extent(0) = " <<
importLIDs.extent(0) <<
" != numPacketsPerLID.extent(0) = " <<
numPacketsPerLID.extent(0) <<
".");
5717 ": Import or Export operations are not allowed on a target "
5718 "CrsGraph that is fillComplete.");
5725 if (imports.need_sync_host()) {
5726 imports.sync_host();
5734 if (isLocallyIndexed()) {
5736 std::ostringstream
os;
5737 os << *
prefix <<
"Preallocate local indices scratch" <<
endl;
5738 std::cerr <<
os.str();
5745 std::ostringstream
os;
5746 os << *
prefix <<
"Local indices scratch size: "
5748 std::cerr <<
os.str();
5753 std::ostringstream
os;
5755 if (isGloballyIndexed()) {
5756 os <<
"Graph is globally indexed";
5758 os <<
"Graph is neither locally nor globally indexed";
5761 std::cerr <<
os.str();
5772 std::ostringstream
os;
5773 os << *
prefix <<
"i=" <<
i <<
", numImportLIDs="
5775 std::cerr <<
os.str();
5782 std::logic_error,
"importLIDs[i=" <<
i <<
"]=" <<
lclRow <<
" is not in the row Map on the calling "
5786 if (!isLocallyIndexed()) {
5798 }
catch (std::exception&
e) {
5800 "Tpetra::CrsGraph::unpackAndCombine: Insert loop threw an "
5807 std::ostringstream
os;
5809 std::cerr <<
os.str();
5813template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5816 using Teuchos::Comm;
5817 using Teuchos::null;
5818 using Teuchos::ParameterList;
5832 if (!domainMap_.is_null()) {
5833 if (domainMap_.getRawPtr() == rowMap_.getRawPtr()) {
5843 if (!rangeMap_.is_null()) {
5844 if (rangeMap_.getRawPtr() == rowMap_.getRawPtr()) {
5854 if (!colMap_.is_null()) {
5868 if (!rangeMap_.is_null() &&
5871 if (
params.is_null() || !
params->isSublist(
"Export")) {
5879 if (!domainMap_.is_null() &&
5882 if (
params.is_null() || !
params->isSublist(
"Import")) {
5908template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5910 getLocalDiagOffsets(
const Kokkos::View<size_t*, device_type, Kokkos::MemoryUnmanaged>& offsets)
const {
5915 const bool verbose = verbose_;
5917 std::unique_ptr<std::string>
prefix;
5919 prefix = this->createPrefix(
"CrsGraph",
"getLocalDiagOffsets");
5920 std::ostringstream
os;
5921 os << *
prefix <<
"offsets.extent(0)=" << offsets.extent(0)
5923 std::cerr <<
os.str();
5927 const LO
lclNumRows =
static_cast<LO
>(this->getLocalNumRows());
5929 std::invalid_argument,
"offsets.extent(0) = " << offsets.extent(0) <<
" < getLocalNumRows() = " <<
lclNumRows <<
".");
5954 const bool sorted = this->isSorted();
5955 if (isFillComplete()) {
5956 auto lclGraph = this->getLocalGraphDevice();
5964 auto offsets_h = Kokkos::create_mirror_view(offsets);
5974 if (
lclColInd == Tpetra::Details::OrdinalTraits<LO>::invalid()) {
5982 const size_t hint = 0;
5993 typename local_inds_dualv_type::t_host::const_type
lclColInds;
6028 std::ostringstream
os;
6029 os << *
prefix <<
"Wrong offsets: [";
6038 std::cerr <<
os.str();
6043 using Teuchos::reduceAll;
6044 Teuchos::RCP<const Teuchos::Comm<int>> comm = this->getComm();
6067 std::ostringstream
os;
6068 os <<
"Issue(s) that we noticed (on Process " <<
gblResults[4] <<
", "
6069 "possibly among others): "
6072 os <<
" - The column Map does not contain at least one diagonal entry "
6077 os <<
" - On one or more processes, some row does not contain a "
6082 os <<
" - On one or more processes, some offsets are incorrect."
6086 os <<
" - One or more processes had some other error."
6094template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6099 const bool verbose = verbose_;
6101 std::unique_ptr<std::string>
prefix;
6103 prefix = this->createPrefix(
"CrsGraph",
"getLocalOffRankOffsets");
6104 std::ostringstream
os;
6105 os << *
prefix <<
"offsets.extent(0)=" << offsets.extent(0)
6107 std::cerr <<
os.str();
6113 const size_t lclNumRows = this->getLocalNumRows();
6115 if (haveLocalOffRankOffsets_ && k_offRankOffsets_.extent(0) ==
lclNumRows + 1) {
6116 offsets = k_offRankOffsets_;
6119 haveLocalOffRankOffsets_ =
false;
6134 if (isFillComplete()) {
6135 k_offRankOffsets_ = offset_device_view_type(Kokkos::ViewAllocateWithoutInitializing(
"offRankOffset"),
lclNumRows + 1);
6136 auto lclGraph = this->getLocalGraphDevice();
6137 ::Tpetra::Details::getGraphOffRankOffsets(k_offRankOffsets_,
6140 offsets = k_offRankOffsets_;
6141 haveLocalOffRankOffsets_ =
true;
6165template <
class DeviceType,
6167 std::is_same<
typename DeviceType::memory_space,
6168 Kokkos::HostSpace>::value>
6169struct HelpGetLocalDiagOffsets {};
6171template <
class DeviceType>
6172struct HelpGetLocalDiagOffsets<DeviceType, true> {
6173 typedef DeviceType device_type;
6174 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6175 Kokkos::MemoryUnmanaged>
6176 device_offsets_type;
6177 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6178 Kokkos::MemoryUnmanaged>
6181 static device_offsets_type
6182 getDeviceOffsets(
const host_offsets_type& hostOffsets) {
6189 copyBackIfNeeded(
const host_offsets_type& ,
6190 const device_offsets_type& ) {
6194template <
class DeviceType>
6195struct HelpGetLocalDiagOffsets<DeviceType, false> {
6196 typedef DeviceType device_type;
6200 typedef Kokkos::View<size_t*, device_type> device_offsets_type;
6201 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6202 Kokkos::MemoryUnmanaged>
6205 static device_offsets_type
6206 getDeviceOffsets(
const host_offsets_type& hostOffsets) {
6209 return device_offsets_type(
"offsets", hostOffsets.extent(0));
6213 copyBackIfNeeded(
const host_offsets_type& hostOffsets,
6214 const device_offsets_type& deviceOffsets) {
6216 Kokkos::deep_copy(hostOffsets, deviceOffsets);
6221template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6227 "The graph does not yet have a column Map.");
6228 const LO
myNumRows =
static_cast<LO
>(this->getLocalNumRows());
6229 if (
static_cast<LO
>(offsets.size()) !=
myNumRows) {
6246 typedef typename helper_type::host_offsets_type host_offsets_type;
6256template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6262template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6265 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>&
rowTransfer,
6266 const Teuchos::RCP<const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>>&
domainTransfer,
6267 const Teuchos::RCP<const map_type>& domainMap,
6268 const Teuchos::RCP<const map_type>&
rangeMap,
6269 const Teuchos::RCP<Teuchos::ParameterList>&
params)
const {
6270 using Teuchos::ArrayRCP;
6271 using Teuchos::ArrayView;
6272 using Teuchos::Comm;
6273 using Teuchos::ParameterList;
6280#ifdef HAVE_TPETRA_MMM_TIMINGS
6282 using Teuchos::TimeMonitor;
6287 using NT = node_type;
6291 const char*
prefix =
"Tpetra::CrsGraph::transferAndFillComplete: ";
6293#ifdef HAVE_TPETRA_MMM_TIMINGS
6295 if (!
params.is_null()) label =
params->get(
"Timer Label", label);
6296 string prefix2 =
string(
"Tpetra ") + label + std::string(
": CrsGraph TAFC ");
6310 prefix <<
"The 'rowTransfer' input argument must be either an Import or "
6311 "an Export, and its template parameters must match the corresponding "
6312 "template parameters of the CrsGraph.");
6327 prefix <<
"The 'domainTransfer' input argument must be either an "
6328 "Import or an Export, and its template parameters must match the "
6329 "corresponding template parameters of the CrsGraph.");
6335 std::invalid_argument,
6336 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6337 "must be of the same type (either Import or Export).");
6343 std::invalid_argument,
6344 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6345 "must be of the same type (either Import or Export).");
6351 const bool communication_needed = rowTransfer.getSourceMap()->isDistributed();
6357 bool reverseMode =
false;
6358 bool restrictComm =
false;
6359 RCP<ParameterList> graphparams;
6360 if (!params.is_null()) {
6361 reverseMode = params->get(
"Reverse Mode", reverseMode);
6362 restrictComm = params->get(
"Restrict Communicator", restrictComm);
6363 graphparams = sublist(params,
"CrsGraph");
6368 RCP<const map_type> MyRowMap = reverseMode ? rowTransfer.getSourceMap() : rowTransfer.getTargetMap();
6369 RCP<const map_type> MyColMap;
6371 RCP<const map_type> MyRangeMap = !rangeMap.is_null() ? rangeMap : getRangeMap();
6372 RCP<const map_type> BaseRowMap = MyRowMap;
6373 RCP<const map_type> BaseDomainMap = MyDomainMap;
6381 if (!destGraph.is_null()) {
6392 const bool NewFlag =
6393 !destGraph->isLocallyIndexed() && !destGraph->isGloballyIndexed();
6394 TEUCHOS_TEST_FOR_EXCEPTION(!NewFlag, std::invalid_argument,
6395 prefix <<
"The input argument 'destGraph' is only allowed to be nonnull, "
6396 "if its graph is empty (neither locally nor globally indexed).");
6405 TEUCHOS_TEST_FOR_EXCEPTION(
6406 !destGraph->getRowMap()->isSameAs(*MyRowMap), std::invalid_argument,
6407 prefix <<
"The (row) Map of the input argument 'destGraph' is not the "
6408 "same as the (row) Map specified by the input argument 'rowTransfer'.");
6410 TEUCHOS_TEST_FOR_EXCEPTION(
6411 !destGraph->checkSizes(*
this), std::invalid_argument,
6412 prefix <<
"You provided a nonnull destination graph, but checkSizes() "
6413 "indicates that it is not a legal legal target for redistribution from "
6414 "the source graph (*this). This may mean that they do not have the "
6415 "same dimensions.");
6429 TEUCHOS_TEST_FOR_EXCEPTION(
6430 !(reverseMode || getRowMap()->isSameAs(*rowTransfer.getSourceMap())),
6431 std::invalid_argument, prefix <<
"rowTransfer->getSourceMap() must match this->getRowMap() in forward mode.");
6433 TEUCHOS_TEST_FOR_EXCEPTION(
6434 !(!reverseMode || getRowMap()->isSameAs(*rowTransfer.getTargetMap())),
6435 std::invalid_argument, prefix <<
"rowTransfer->getTargetMap() must match this->getRowMap() in reverse mode.");
6438 TEUCHOS_TEST_FOR_EXCEPTION(
6439 !xferDomainAsImport.is_null() && !xferDomainAsImport->getTargetMap()->isSameAs(*
domainMap),
6440 std::invalid_argument,
6441 prefix <<
"The target map of the 'domainTransfer' input argument must be "
6442 "the same as the rebalanced domain map 'domainMap'");
6444 TEUCHOS_TEST_FOR_EXCEPTION(
6445 !xferDomainAsExport.is_null() && !xferDomainAsExport->getSourceMap()->isSameAs(*
domainMap),
6446 std::invalid_argument,
6447 prefix <<
"The source map of the 'domainTransfer' input argument must be "
6448 "the same as the rebalanced domain map 'domainMap'");
6461 const size_t NumSameIDs = rowTransfer.getNumSameIDs();
6462 ArrayView<const LO> ExportLIDs = reverseMode ? rowTransfer.getRemoteLIDs() : rowTransfer.getExportLIDs();
6463 ArrayView<const LO> RemoteLIDs = reverseMode ? rowTransfer.getExportLIDs() : rowTransfer.getRemoteLIDs();
6464 ArrayView<const LO> PermuteToLIDs = reverseMode ? rowTransfer.getPermuteFromLIDs() : rowTransfer.getPermuteToLIDs();
6465 ArrayView<const LO> PermuteFromLIDs = reverseMode ? rowTransfer.getPermuteToLIDs() : rowTransfer.getPermuteFromLIDs();
6466 Distributor& Distor = rowTransfer.getDistributor();
6469 Teuchos::Array<int> SourcePids;
6470 Teuchos::Array<int> TargetPids;
6471 int MyPID = getComm()->getRank();
6474 RCP<const map_type> ReducedRowMap, ReducedColMap,
6475 ReducedDomainMap, ReducedRangeMap;
6476 RCP<const Comm<int>> ReducedComm;
6480 if (destGraph.is_null()) {
6481 destGraph = rcp(
new this_CRS_type(MyRowMap, 0, graphparams));
6488 ReducedRowMap = MyRowMap->removeEmptyProcesses();
6489 ReducedComm = ReducedRowMap.is_null() ? Teuchos::null : ReducedRowMap->getComm();
6490 destGraph->removeEmptyProcessesInPlace(ReducedRowMap);
6492 ReducedDomainMap = MyRowMap.getRawPtr() == MyDomainMap.getRawPtr() ? ReducedRowMap : MyDomainMap->replaceCommWithSubset(ReducedComm);
6493 ReducedRangeMap = MyRowMap.getRawPtr() == MyRangeMap.getRawPtr() ? ReducedRowMap : MyRangeMap->replaceCommWithSubset(ReducedComm);
6496 MyRowMap = ReducedRowMap;
6497 MyDomainMap = ReducedDomainMap;
6498 MyRangeMap = ReducedRangeMap;
6501 if (!ReducedComm.is_null()) {
6502 MyPID = ReducedComm->getRank();
6507 ReducedComm = MyRowMap->getComm();
6513#ifdef HAVE_TPETRA_MMM_TIMINGS
6515 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"ImportSetup"))));
6518 RCP<const import_type> MyImporter = getImporter();
6521 bool bSameDomainMap = BaseDomainMap->isSameAs(*getDomainMap());
6523 if (!restrictComm && !MyImporter.is_null() && bSameDomainMap) {
6530 Import_Util::getPids(*MyImporter, SourcePids,
false);
6531 }
else if (restrictComm && !MyImporter.is_null() && bSameDomainMap) {
6534 ivector_type SourceDomain_pids(getDomainMap(),
true);
6535 ivector_type SourceCol_pids(getColMap());
6537 SourceDomain_pids.putScalar(MyPID);
6539 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6540 SourcePids.resize(getColMap()->getLocalNumElements());
6541 SourceCol_pids.get1dCopy(SourcePids());
6542 }
else if (MyImporter.is_null() && bSameDomainMap) {
6544 SourcePids.resize(getColMap()->getLocalNumElements());
6545 SourcePids.assign(getColMap()->getLocalNumElements(), MyPID);
6546 }
else if (!MyImporter.is_null() &&
6547 !domainTransfer.is_null()) {
6554 ivector_type TargetDomain_pids(
domainMap);
6555 TargetDomain_pids.putScalar(MyPID);
6558 ivector_type SourceDomain_pids(getDomainMap());
6561 ivector_type SourceCol_pids(getColMap());
6563 if (!reverseMode && !xferDomainAsImport.is_null()) {
6564 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6565 }
else if (reverseMode && !xferDomainAsExport.is_null()) {
6566 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6567 }
else if (!reverseMode && !xferDomainAsExport.is_null()) {
6568 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6569 }
else if (reverseMode && !xferDomainAsImport.is_null()) {
6570 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6572 TEUCHOS_TEST_FOR_EXCEPTION(
6573 true, std::logic_error,
6574 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6576 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6577 SourcePids.resize(getColMap()->getLocalNumElements());
6578 SourceCol_pids.get1dCopy(SourcePids());
6579 }
else if (BaseDomainMap->isSameAs(*BaseRowMap) &&
6580 getDomainMap()->isSameAs(*getRowMap())) {
6583 ivector_type SourceRow_pids(getRowMap());
6584 ivector_type SourceCol_pids(getColMap());
6586 TargetRow_pids.putScalar(MyPID);
6587 if (!reverseMode && xferAsImport !=
nullptr) {
6588 SourceRow_pids.doExport(TargetRow_pids, *xferAsImport,
INSERT);
6589 }
else if (reverseMode && xferAsExport !=
nullptr) {
6590 SourceRow_pids.doExport(TargetRow_pids, *xferAsExport,
INSERT);
6591 }
else if (!reverseMode && xferAsExport !=
nullptr) {
6592 SourceRow_pids.doImport(TargetRow_pids, *xferAsExport,
INSERT);
6593 }
else if (reverseMode && xferAsImport !=
nullptr) {
6594 SourceRow_pids.doImport(TargetRow_pids, *xferAsImport,
INSERT);
6596 TEUCHOS_TEST_FOR_EXCEPTION(
6597 true, std::logic_error,
6598 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6600 SourceCol_pids.doImport(SourceRow_pids, *MyImporter,
INSERT);
6601 SourcePids.resize(getColMap()->getLocalNumElements());
6602 SourceCol_pids.get1dCopy(SourcePids());
6604 TEUCHOS_TEST_FOR_EXCEPTION(
6605 true, std::invalid_argument,
6606 prefix <<
"This method only allows either domainMap == getDomainMap(), "
6607 "or (domainMap == rowTransfer.getTargetMap() and getDomainMap() == getRowMap()).");
6611 size_t constantNumPackets = destGraph->constantNumberOfPackets();
6612 if (constantNumPackets == 0) {
6613 destGraph->reallocArraysForNumPacketsPerLid(ExportLIDs.size(),
6620 const size_t rbufLen = RemoteLIDs.size() * constantNumPackets;
6621 destGraph->reallocImportsIfNeeded(rbufLen,
false,
nullptr);
6626 destGraph->numExportPacketsPerLID_.modify_host();
6627 Teuchos::ArrayView<size_t> numExportPacketsPerLID =
6632 numExportPacketsPerLID, ExportLIDs,
6633 SourcePids, constantNumPackets);
6637#ifdef HAVE_TPETRA_MMM_TIMINGS
6639 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"Transfer"))));
6642 if (communication_needed) {
6644 if (constantNumPackets == 0) {
6648 destGraph->numExportPacketsPerLID_.sync_host();
6649 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
6651 destGraph->numImportPacketsPerLID_.sync_host();
6652 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
6655 Distor.doReversePostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
6656 destGraph->numImportPacketsPerLID_.view_host());
6657 size_t totalImportPackets = 0;
6659 totalImportPackets += numImportPacketsPerLID[i];
6664 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
6665 destGraph->imports_.modify_host();
6666 auto hostImports = destGraph->imports_.view_host();
6669 destGraph->exports_.sync_host();
6670 auto hostExports = destGraph->exports_.view_host();
6671 Distor.doReversePostsAndWaits(hostExports,
6672 numExportPacketsPerLID,
6674 numImportPacketsPerLID);
6676 destGraph->imports_.modify_host();
6677 auto hostImports = destGraph->imports_.view_host();
6680 destGraph->exports_.sync_host();
6681 auto hostExports = destGraph->exports_.view_host();
6682 Distor.doReversePostsAndWaits(hostExports,
6687 if (constantNumPackets == 0) {
6691 destGraph->numExportPacketsPerLID_.sync_host();
6692 destGraph->numImportPacketsPerLID_.sync_host();
6693 Distor.doPostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
6694 destGraph->numImportPacketsPerLID_.view_host());
6696 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
6698 size_t totalImportPackets = 0;
6700 totalImportPackets += numImportPacketsPerLID[i];
6705 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
6706 destGraph->imports_.modify_host();
6707 auto hostImports = destGraph->imports_.view_host();
6710 destGraph->exports_.sync_host();
6711 auto hostExports = destGraph->exports_.view_host();
6712 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
6714 Distor.doPostsAndWaits(hostExports, numExportPacketsPerLID, hostImports, numImportPacketsPerLID);
6716 destGraph->imports_.modify_host();
6717 auto hostImports = destGraph->imports_.view_host();
6720 destGraph->exports_.sync_host();
6721 auto hostExports = destGraph->exports_.view_host();
6722 Distor.doPostsAndWaits(hostExports, constantNumPackets, hostImports);
6731#ifdef HAVE_TPETRA_MMM_TIMINGS
6733 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"Unpack-1"))));
6737 destGraph->numImportPacketsPerLID_.sync_host();
6738 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
6740 destGraph->imports_.sync_host();
6741 Teuchos::ArrayView<const packet_type> hostImports =
6745 numImportPacketsPerLID,
6746 constantNumPackets,
INSERT,
6747 NumSameIDs, PermuteToLIDs, PermuteFromLIDs);
6748 size_t N = BaseRowMap->getLocalNumElements();
6751 ArrayRCP<size_t> CSR_rowptr(N + 1);
6752 ArrayRCP<GO> CSR_colind_GID;
6753 ArrayRCP<LO> CSR_colind_LID;
6754 CSR_colind_GID.resize(mynnz);
6758 if (
typeid(LO) ==
typeid(GO)) {
6759 CSR_colind_LID = Teuchos::arcp_reinterpret_cast<LO>(CSR_colind_GID);
6761 CSR_colind_LID.resize(mynnz);
6770 numImportPacketsPerLID, constantNumPackets,
6771 INSERT, NumSameIDs, PermuteToLIDs,
6772 PermuteFromLIDs, N, mynnz, MyPID,
6773 CSR_rowptr(), CSR_colind_GID(),
6774 SourcePids(), TargetPids);
6779#ifdef HAVE_TPETRA_MMM_TIMINGS
6781 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"Unpack-2"))));
6786 Teuchos::Array<int> RemotePids;
6787 Import_Util::lowCommunicationMakeColMapAndReindex(CSR_rowptr(),
6791 TargetPids, RemotePids,
6798 ReducedColMap = (MyRowMap.getRawPtr() == MyColMap.getRawPtr()) ? ReducedRowMap : MyColMap->replaceCommWithSubset(ReducedComm);
6799 MyColMap = ReducedColMap;
6803 destGraph->replaceColMap(MyColMap);
6810 if (ReducedComm.is_null()) {
6817 if ((!reverseMode && xferAsImport !=
nullptr) ||
6818 (reverseMode && xferAsExport !=
nullptr)) {
6819 Import_Util::sortCrsEntries(CSR_rowptr(),
6821 }
else if ((!reverseMode && xferAsExport !=
nullptr) ||
6822 (reverseMode && xferAsImport !=
nullptr)) {
6823 Import_Util::sortAndMergeCrsEntries(CSR_rowptr(),
6825 if (CSR_rowptr[N] != mynnz) {
6826 CSR_colind_LID.resize(CSR_rowptr[N]);
6829 TEUCHOS_TEST_FOR_EXCEPTION(
6830 true, std::logic_error,
6831 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6839 destGraph->setAllIndices(CSR_rowptr, CSR_colind_LID);
6845 Teuchos::ParameterList esfc_params;
6846#ifdef HAVE_TPETRA_MMM_TIMINGS
6848 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"CreateImporter"))));
6850 RCP<import_type> MyImport = rcp(
new import_type(MyDomainMap, MyColMap, RemotePids));
6851#ifdef HAVE_TPETRA_MMM_TIMINGS
6853 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"ESFC"))));
6855 esfc_params.set(
"Timer Label", prefix + std::string(
"TAFC"));
6857 if (!params.is_null())
6858 esfc_params.set(
"compute global constants", params->get(
"compute global constants",
true));
6860 destGraph->expertStaticFillComplete(MyDomainMap, MyRangeMap,
6861 MyImport, Teuchos::null, rcp(&esfc_params,
false));
6864template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6868 const Teuchos::RCP<const map_type>& domainMap,
6869 const Teuchos::RCP<const map_type>&
rangeMap,
6870 const Teuchos::RCP<Teuchos::ParameterList>&
params)
const {
6874template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6879 const Teuchos::RCP<const map_type>& domainMap,
6880 const Teuchos::RCP<const map_type>&
rangeMap,
6881 const Teuchos::RCP<Teuchos::ParameterList>&
params)
const {
6885template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6889 const Teuchos::RCP<const map_type>& domainMap,
6890 const Teuchos::RCP<const map_type>&
rangeMap,
6891 const Teuchos::RCP<Teuchos::ParameterList>&
params)
const {
6895template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6900 const Teuchos::RCP<const map_type>& domainMap,
6901 const Teuchos::RCP<const map_type>&
rangeMap,
6902 const Teuchos::RCP<Teuchos::ParameterList>&
params)
const {
6906template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6909 std::swap(
graph.need_sync_host_uvm_access,
this->need_sync_host_uvm_access);
6911 std::swap(
graph.rowMap_,
this->rowMap_);
6912 std::swap(
graph.colMap_,
this->colMap_);
6913 std::swap(
graph.rangeMap_,
this->rangeMap_);
6914 std::swap(
graph.domainMap_,
this->domainMap_);
6916 std::swap(
graph.importer_,
this->importer_);
6917 std::swap(
graph.exporter_,
this->exporter_);
6919 std::swap(
graph.nodeMaxNumRowEntries_,
this->nodeMaxNumRowEntries_);
6921 std::swap(
graph.globalNumEntries_,
this->globalNumEntries_);
6922 std::swap(
graph.globalMaxNumRowEntries_,
this->globalMaxNumRowEntries_);
6924 std::swap(
graph.numAllocForAllRows_,
this->numAllocForAllRows_);
6926 std::swap(
graph.rowPtrsPacked_dev_,
this->rowPtrsPacked_dev_);
6927 std::swap(
graph.rowPtrsPacked_host_,
this->rowPtrsPacked_host_);
6929 std::swap(
graph.rowPtrsUnpacked_dev_,
this->rowPtrsUnpacked_dev_);
6930 std::swap(
graph.rowPtrsUnpacked_host_,
this->rowPtrsUnpacked_host_);
6931 std::swap(
graph.packedUnpackedRowPtrsMatch_,
this->packedUnpackedRowPtrsMatch_);
6933 std::swap(
graph.k_offRankOffsets_,
this->k_offRankOffsets_);
6935 std::swap(
graph.lclIndsUnpacked_wdv,
this->lclIndsUnpacked_wdv);
6936 std::swap(
graph.gblInds_wdv,
this->gblInds_wdv);
6937 std::swap(
graph.lclIndsPacked_wdv,
this->lclIndsPacked_wdv);
6939 std::swap(
graph.storageStatus_,
this->storageStatus_);
6941 std::swap(
graph.indicesAreAllocated_,
this->indicesAreAllocated_);
6942 std::swap(
graph.indicesAreLocal_,
this->indicesAreLocal_);
6943 std::swap(
graph.indicesAreGlobal_,
this->indicesAreGlobal_);
6944 std::swap(
graph.fillComplete_,
this->fillComplete_);
6945 std::swap(
graph.indicesAreSorted_,
this->indicesAreSorted_);
6946 std::swap(
graph.noRedundancies_,
this->noRedundancies_);
6947 std::swap(
graph.haveLocalConstants_,
this->haveLocalConstants_);
6948 std::swap(
graph.haveGlobalConstants_,
this->haveGlobalConstants_);
6949 std::swap(
graph.haveLocalOffRankOffsets_,
this->haveLocalOffRankOffsets_);
6951 std::swap(
graph.sortGhostsAssociatedWithEachProcessor_,
this->sortGhostsAssociatedWithEachProcessor_);
6953 std::swap(
graph.k_numAllocPerRow_,
this->k_numAllocPerRow_);
6954 std::swap(
graph.k_numRowEntries_,
this->k_numRowEntries_);
6955 std::swap(
graph.nonlocals_,
this->nonlocals_);
6958template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6968 auto v1 =
m1.find(
key)->second;
6969 auto v2 =
m2.find(
key)->second;
6970 std::sort(
v1.begin(),
v1.end());
6971 std::sort(
v2.begin(),
v2.end());
6974 for (
size_t i = 0;
output &&
i <
v1.size();
i++) {
6989 output = this->nodeMaxNumRowEntries_ ==
graph.nodeMaxNumRowEntries_ ?
output :
false;
6992 output = this->globalMaxNumRowEntries_ ==
graph.globalMaxNumRowEntries_ ?
output :
false;
6994 output = this->numAllocForAllRows_ ==
graph.numAllocForAllRows_ ?
output :
false;
6998 output = this->indicesAreAllocated_ ==
graph.indicesAreAllocated_ ?
output :
false;
7004 output = this->haveLocalConstants_ ==
graph.haveLocalConstants_ ?
output :
false;
7005 output = this->haveGlobalConstants_ ==
graph.haveGlobalConstants_ ?
output :
false;
7006 output = this->haveLocalOffRankOffsets_ ==
graph.haveLocalOffRankOffsets_ ?
output :
false;
7007 output = this->sortGhostsAssociatedWithEachProcessor_ ==
graph.sortGhostsAssociatedWithEachProcessor_ ?
output :
false;
7015 output = this->k_numAllocPerRow_.extent(0) ==
graph.k_numAllocPerRow_.extent(0) ?
output :
false;
7016 if (
output && this->k_numAllocPerRow_.extent(0) > 0) {
7017 for (
size_t i = 0;
output &&
i < this->k_numAllocPerRow_.extent(0);
i++)
7023 output = this->k_numRowEntries_.extent(0) ==
graph.k_numRowEntries_.extent(0) ?
output :
false;
7024 if (
output && this->k_numRowEntries_.extent(0) > 0) {
7025 for (
size_t i = 0;
output &&
i < this->k_numRowEntries_.extent(0);
i++)
7031 auto rowPtrsThis = this->getRowPtrsUnpackedHost();
7039 output = this->lclIndsUnpacked_wdv.extent(0) ==
graph.lclIndsUnpacked_wdv.extent(0) ?
output :
false;
7040 if (
output && this->lclIndsUnpacked_wdv.extent(0) > 0) {
7041 auto indThis = this->lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
7042 auto indGraph =
graph.lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
7048 output = this->gblInds_wdv.extent(0) ==
graph.gblInds_wdv.extent(0) ?
output :
false;
7049 if (
output && this->gblInds_wdv.extent(0) > 0) {
7050 auto indtThis = this->gblInds_wdv.getHostView(Access::ReadOnly);
7051 auto indtGraph =
graph.gblInds_wdv.getHostView(Access::ReadOnly);
7126#define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7128 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7129 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7130 const Import<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7131 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7132 CrsGraph<LO, GO, NODE>::node_type>& importer, \
7133 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7134 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7135 CrsGraph<LO, GO, NODE>::node_type>>& domainMap, \
7136 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7137 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7138 CrsGraph<LO, GO, NODE>::node_type>>& rangeMap, \
7139 const Teuchos::RCP<Teuchos::ParameterList>& params);
7141#define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO, GO, NODE) \
7143 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7144 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7145 const Import<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7146 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7147 CrsGraph<LO, GO, NODE>::node_type>& rowImporter, \
7148 const Import<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7149 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7150 CrsGraph<LO, GO, NODE>::node_type>& domainImporter, \
7151 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7152 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7153 CrsGraph<LO, GO, NODE>::node_type>>& domainMap, \
7154 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7155 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7156 CrsGraph<LO, GO, NODE>::node_type>>& rangeMap, \
7157 const Teuchos::RCP<Teuchos::ParameterList>& params);
7159#define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7161 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7162 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7163 const Export<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7164 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7165 CrsGraph<LO, GO, NODE>::node_type>& exporter, \
7166 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7167 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7168 CrsGraph<LO, GO, NODE>::node_type>>& domainMap, \
7169 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7170 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7171 CrsGraph<LO, GO, NODE>::node_type>>& rangeMap, \
7172 const Teuchos::RCP<Teuchos::ParameterList>& params);
7174#define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO, GO, NODE) \
7176 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7177 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7178 const Export<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7179 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7180 CrsGraph<LO, GO, NODE>::node_type>& rowExporter, \
7181 const Export<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7182 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7183 CrsGraph<LO, GO, NODE>::node_type>& domainExporter, \
7184 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7185 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7186 CrsGraph<LO, GO, NODE>::node_type>>& domainMap, \
7187 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7188 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7189 CrsGraph<LO, GO, NODE>::node_type>>& rangeMap, \
7190 const Teuchos::RCP<Teuchos::ParameterList>& params);
7192#define TPETRA_CRSGRAPH_INSTANT(LO, GO, NODE) \
7193 template class CrsGraph<LO, GO, NODE>; \
7194 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7195 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7196 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO, GO, NODE) \
7197 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO, GO, NODE)