10 #ifndef TPETRA_CRSGRAPH_DEF_HPP
11 #define TPETRA_CRSGRAPH_DEF_HPP
20 #include "Tpetra_Details_getGraphDiagOffsets.hpp"
21 #include "Tpetra_Details_getGraphOffRankOffsets.hpp"
22 #include "Tpetra_Details_makeColMap.hpp"
26 #include "Tpetra_Distributor.hpp"
27 #include "Teuchos_SerialDenseMatrix.hpp"
28 #include "Tpetra_Vector.hpp"
31 #include "Tpetra_Details_packCrsGraph.hpp"
32 #include "Tpetra_Details_unpackCrsGraphAndCombine.hpp"
33 #include "Tpetra_Details_CrsPadding.hpp"
40 #include <type_traits>
48 template <
class MapIter>
49 void verbosePrintMap(std::ostream& out,
53 const char mapName[]) {
54 using ::Tpetra::Details::Behavior;
57 out << mapName <<
": {";
58 const size_t maxNumToPrint =
60 if (maxNumToPrint == 0) {
65 const size_t numToPrint = numEnt > maxNumToPrint ? maxNumToPrint : numEnt;
67 for (MapIter it = beg; it != end; ++it) {
68 out <<
"(" << (*it).first <<
", ";
72 if (count +
size_t(1) < numToPrint) {
84 template <
class LO,
class GO,
class Node>
85 Teuchos::ArrayView<GO>
87 std::vector<GO>& gblColIndsStorage,
88 const RowGraph<LO, GO, Node>& graph,
90 size_t origNumEnt = graph.getNumEntriesInGlobalRow(gblRowInd);
91 if (gblColIndsStorage.size() < origNumEnt) {
92 gblColIndsStorage.resize(origNumEnt);
94 typename CrsGraph<LO, GO, Node>::nonconst_global_inds_host_view_type gblColInds(gblColIndsStorage.data(),
96 graph.getGlobalRowCopy(gblRowInd, gblColInds, origNumEnt);
97 Teuchos::ArrayView<GO> retval(gblColIndsStorage.data(), origNumEnt);
101 template <
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
102 class ConvertColumnIndicesFromGlobalToLocal {
104 ConvertColumnIndicesFromGlobalToLocal(const ::Kokkos::View<LO*, DT>& lclColInds,
105 const ::Kokkos::View<const GO*, DT>& gblColInds,
106 const ::Kokkos::View<const OffsetType*, DT>& ptr,
107 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
108 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt)
109 : lclColInds_(lclColInds)
110 , gblColInds_(gblColInds)
112 , lclColMap_(lclColMap)
113 , numRowEnt_(numRowEnt) {}
116 operator()(
const LO& lclRow, OffsetType& curNumBad)
const {
117 const OffsetType offset = ptr_(lclRow);
121 const LO numEnt =
static_cast<LO
>(numRowEnt_(lclRow));
122 for (LO j = 0; j < numEnt; ++j) {
123 const GO gid = gblColInds_(offset + j);
124 const LO lid = lclColMap_.getLocalElement(gid);
125 lclColInds_(offset + j) = lid;
126 if (lid == ::Tpetra::Details::OrdinalTraits<LO>::invalid()) {
133 run(const ::Kokkos::View<LO*, DT>& lclColInds,
134 const ::Kokkos::View<const GO*, DT>& gblColInds,
135 const ::Kokkos::View<const OffsetType*, DT>& ptr,
136 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
137 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt) {
138 typedef ::Kokkos::RangePolicy<typename DT::execution_space, LO> range_type;
139 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> functor_type;
141 const LO lclNumRows = ptr.extent(0) == 0 ?
static_cast<LO
>(0) : static_cast<LO>(ptr.extent(0) - 1);
142 OffsetType numBad = 0;
144 ::Kokkos::parallel_reduce(range_type(0, lclNumRows),
145 functor_type(lclColInds, gblColInds, ptr,
146 lclColMap, numRowEnt),
152 ::Kokkos::View<LO*, DT> lclColInds_;
153 ::Kokkos::View<const GO*, DT> gblColInds_;
154 ::Kokkos::View<const OffsetType*, DT> ptr_;
156 ::Kokkos::View<const NumEntType*, DT> numRowEnt_;
175 template <
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
178 const Kokkos::View<const GO*, DT>& gblColInds,
179 const Kokkos::View<const OffsetType*, DT>& ptr,
181 const Kokkos::View<const NumEntType*, DT>& numRowEnt) {
182 using Impl::ConvertColumnIndicesFromGlobalToLocal;
183 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> impl_type;
184 return impl_type::run(lclColInds, gblColInds, ptr, lclColMap, numRowEnt);
187 template <
class ViewType,
class LO>
188 class MaxDifference {
190 MaxDifference(
const ViewType& ptr)
193 KOKKOS_INLINE_FUNCTION
void init(LO& dst)
const {
197 KOKKOS_INLINE_FUNCTION
void
198 join(LO& dst,
const LO& src)
const {
199 dst = (src > dst) ? src : dst;
202 KOKKOS_INLINE_FUNCTION
void
203 operator()(
const LO lclRow, LO& maxNumEnt)
const {
204 const LO numEnt =
static_cast<LO
>(ptr_(lclRow + 1) - ptr_(lclRow));
205 maxNumEnt = (numEnt > maxNumEnt) ? numEnt : maxNumEnt;
209 typename ViewType::const_type ptr_;
212 template <
class ViewType,
class LO>
213 typename ViewType::non_const_value_type
214 maxDifference(
const char kernelLabel[],
216 const LO lclNumRows) {
217 if (lclNumRows == 0) {
220 return static_cast<LO
>(0);
222 using execution_space =
typename ViewType::execution_space;
223 using range_type = Kokkos::RangePolicy<execution_space, LO>;
225 Kokkos::parallel_reduce(kernelLabel,
226 range_type(0, lclNumRows),
227 MaxDifference<ViewType, LO>(ptr),
235 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
236 bool CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
241 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
242 bool CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
247 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
248 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
249 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
250 const size_t maxNumEntriesPerRow,
251 const Teuchos::RCP<Teuchos::ParameterList>& params)
254 , numAllocForAllRows_(maxNumEntriesPerRow) {
255 const char tfecfFuncName[] =
256 "CrsGraph(rowMap,maxNumEntriesPerRow,params): ";
258 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid(),
259 std::invalid_argument,
260 "The allocation hint maxNumEntriesPerRow must be "
261 "a valid size_t value, which in this case means it must not be "
262 "Teuchos::OrdinalTraits<size_t>::invalid().");
267 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
269 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
270 const Teuchos::RCP<const map_type>& colMap,
271 const size_t maxNumEntriesPerRow,
272 const Teuchos::RCP<Teuchos::ParameterList>& params)
276 , numAllocForAllRows_(maxNumEntriesPerRow) {
277 const char tfecfFuncName[] =
278 "CrsGraph(rowMap,colMap,maxNumEntriesPerRow,params): ";
280 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
281 maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid(),
282 std::invalid_argument,
283 "The allocation hint maxNumEntriesPerRow must be "
284 "a valid size_t value, which in this case means it must not be "
285 "Teuchos::OrdinalTraits<size_t>::invalid().");
290 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
292 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
293 const Teuchos::ArrayView<const size_t>& numEntPerRow,
294 const Teuchos::RCP<Teuchos::ParameterList>& params)
297 , numAllocForAllRows_(0) {
298 const char tfecfFuncName[] =
299 "CrsGraph(rowMap,numEntPerRow,params): ";
302 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
303 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
304 static_cast<size_t>(numEntPerRow.size()) != lclNumRows,
305 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size() <<
" != the local number of rows " << lclNumRows <<
" as specified by "
306 "the input row Map.");
309 for (
size_t r = 0; r < lclNumRows; ++r) {
310 const size_t curRowCount = numEntPerRow[r];
311 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
312 std::invalid_argument,
"numEntPerRow(" << r <<
") "
313 "specifies an invalid number of entries "
314 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
322 typedef typename out_view_type::non_const_type nc_view_type;
323 typedef Kokkos::View<
const size_t*,
324 typename nc_view_type::array_layout,
326 Kokkos::MemoryUnmanaged>
328 in_view_type numAllocPerRowIn(numEntPerRow.getRawPtr(), lclNumRows);
329 nc_view_type numAllocPerRowOut(
"Tpetra::CrsGraph::numAllocPerRow",
332 using exec_space =
typename nc_view_type::execution_space;
340 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
342 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
343 const Kokkos::DualView<const size_t*, device_type>& numEntPerRow,
344 const Teuchos::RCP<Teuchos::ParameterList>& params)
347 , k_numAllocPerRow_(numEntPerRow.view_host())
348 , numAllocForAllRows_(0) {
349 const char tfecfFuncName[] =
350 "CrsGraph(rowMap,numEntPerRow,params): ";
353 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
354 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
355 static_cast<size_t>(numEntPerRow.extent(0)) != lclNumRows,
356 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.extent(0) <<
" != the local number of rows " << lclNumRows <<
" as specified by "
357 "the input row Map.");
360 for (
size_t r = 0; r < lclNumRows; ++r) {
361 const size_t curRowCount = numEntPerRow.view_host()(r);
362 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
363 std::invalid_argument,
"numEntPerRow(" << r <<
") "
364 "specifies an invalid number of entries "
365 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
373 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
375 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
376 const Teuchos::RCP<const map_type>& colMap,
377 const Kokkos::DualView<const size_t*, device_type>& numEntPerRow,
378 const Teuchos::RCP<Teuchos::ParameterList>& params)
382 , k_numAllocPerRow_(numEntPerRow.view_host())
383 , numAllocForAllRows_(0) {
384 const char tfecfFuncName[] =
385 "CrsGraph(rowMap,colMap,numEntPerRow,params): ";
388 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
389 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
390 static_cast<size_t>(numEntPerRow.extent(0)) != lclNumRows,
391 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.extent(0) <<
" != the local number of rows " << lclNumRows <<
" as specified by "
392 "the input row Map.");
395 for (
size_t r = 0; r < lclNumRows; ++r) {
396 const size_t curRowCount = numEntPerRow.view_host()(r);
397 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
398 std::invalid_argument,
"numEntPerRow(" << r <<
") "
399 "specifies an invalid number of entries "
400 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
408 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
410 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
411 const Teuchos::RCP<const map_type>& colMap,
412 const Teuchos::ArrayView<const size_t>& numEntPerRow,
413 const Teuchos::RCP<Teuchos::ParameterList>& params)
417 , numAllocForAllRows_(0) {
418 const char tfecfFuncName[] =
419 "CrsGraph(rowMap,colMap,numEntPerRow,params): ";
422 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
423 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
424 static_cast<size_t>(numEntPerRow.size()) != lclNumRows,
425 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size() <<
" != the local number of rows " << lclNumRows <<
" as specified by "
426 "the input row Map.");
429 for (
size_t r = 0; r < lclNumRows; ++r) {
430 const size_t curRowCount = numEntPerRow[r];
431 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
432 std::invalid_argument,
"numEntPerRow(" << r <<
") "
433 "specifies an invalid number of entries "
434 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
442 typedef typename out_view_type::non_const_type nc_view_type;
443 typedef Kokkos::View<
const size_t*,
444 typename nc_view_type::array_layout,
446 Kokkos::MemoryUnmanaged>
448 in_view_type numAllocPerRowIn(numEntPerRow.getRawPtr(), lclNumRows);
449 nc_view_type numAllocPerRowOut(
"Tpetra::CrsGraph::numAllocPerRow",
452 using exec_space =
typename nc_view_type::execution_space;
460 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
463 const Teuchos::RCP<const map_type>& rowMap,
464 const Teuchos::RCP<Teuchos::ParameterList>& params)
467 , colMap_(originalGraph.colMap_)
468 , numAllocForAllRows_(originalGraph.numAllocForAllRows_)
469 , storageStatus_(originalGraph.storageStatus_)
470 , indicesAreAllocated_(originalGraph.indicesAreAllocated_)
471 , indicesAreLocal_(originalGraph.indicesAreLocal_)
472 , indicesAreSorted_(originalGraph.indicesAreSorted_) {
475 int numRows = rowMap->getLocalNumElements();
477 auto rowsToUse = Kokkos::pair<size_t, size_t>(0, numRows + 1);
482 if (indicesAreLocal_) {
492 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
494 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
495 const Teuchos::RCP<const map_type>& colMap,
496 const typename local_graph_device_type::row_map_type& rowPointers,
497 const typename local_graph_device_type::entries_type::non_const_type& columnIndices,
498 const Teuchos::RCP<Teuchos::ParameterList>& params)
502 , numAllocForAllRows_(0)
503 , storageStatus_(Details::STORAGE_1D_PACKED)
504 , indicesAreAllocated_(true)
505 , indicesAreLocal_(true) {
507 if (!params.is_null() && params->isParameter(
"sorted") &&
508 !params->get<
bool>(
"sorted")) {
517 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
519 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
520 const Teuchos::RCP<const map_type>& colMap,
521 const Teuchos::ArrayRCP<size_t>& rowPointers,
522 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices,
523 const Teuchos::RCP<Teuchos::ParameterList>& params)
527 , numAllocForAllRows_(0)
528 , storageStatus_(Details::STORAGE_1D_PACKED)
529 , indicesAreAllocated_(true)
530 , indicesAreLocal_(true) {
532 if (!params.is_null() && params->isParameter(
"sorted") &&
533 !params->get<
bool>(
"sorted")) {
542 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
544 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
545 const Teuchos::RCP<const map_type>& colMap,
547 const Teuchos::RCP<Teuchos::ParameterList>& params)
555 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
558 const Teuchos::RCP<const map_type>& rowMap,
559 const Teuchos::RCP<const map_type>& colMap,
560 const Teuchos::RCP<const map_type>& domainMap,
561 const Teuchos::RCP<const map_type>& rangeMap,
562 const Teuchos::RCP<Teuchos::ParameterList>& params)
566 , numAllocForAllRows_(0)
567 , storageStatus_(Details::STORAGE_1D_PACKED)
568 , indicesAreAllocated_(true)
569 , indicesAreLocal_(true) {
571 const char tfecfFuncName[] =
"CrsGraph(Kokkos::LocalStaticCrsGraph,Map,Map,Map,Map)";
573 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
574 colMap.is_null(), std::runtime_error,
575 ": The input column Map must be nonnull.");
576 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
577 k_local_graph_.numRows() != rowMap->getLocalNumElements(),
579 ": The input row Map and the input local graph need to have the same "
580 "number of rows. The row Map claims "
581 << rowMap->getLocalNumElements()
582 <<
" row(s), but the local graph claims " << k_local_graph_.numRows()
592 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
594 ": cannot have 1D data structures allocated.");
596 if (!params.is_null() && params->isParameter(
"sorted") &&
597 !params->get<
bool>(
"sorted")) {
604 rangeMap.is_null() ?
rowMap_ : rangeMap);
605 Teuchos::Array<int> remotePIDs(0);
610 this->setRowPtrs(k_local_graph_.row_map);
612 set_need_sync_host_uvm_access();
614 const bool callComputeGlobalConstants = params.get() ==
nullptr ||
615 params->get(
"compute global constants",
true);
617 if (callComputeGlobalConstants) {
620 this->fillComplete_ =
true;
624 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
627 const Teuchos::RCP<const map_type>& rowMap,
628 const Teuchos::RCP<const map_type>& colMap,
629 const Teuchos::RCP<const map_type>& domainMap,
630 const Teuchos::RCP<const map_type>& rangeMap,
631 const Teuchos::RCP<const import_type>& importer,
632 const Teuchos::RCP<const export_type>& exporter,
633 const Teuchos::RCP<Teuchos::ParameterList>& params)
637 , rangeMap_(rangeMap.is_null() ? rowMap : rangeMap)
638 , domainMap_(domainMap.is_null() ? rowMap : domainMap)
639 , importer_(importer)
640 , exporter_(exporter)
641 , numAllocForAllRows_(0)
642 , storageStatus_(Details::STORAGE_1D_PACKED)
643 , indicesAreAllocated_(true)
644 , indicesAreLocal_(true) {
646 const char tfecfFuncName[] =
647 "Tpetra::CrsGraph(local_graph_device_type,"
648 "Map,Map,Map,Map,Import,Export,params): ";
650 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(colMap.is_null(), std::runtime_error,
651 "The input column Map must be nonnull.");
655 setRowPtrs(lclGraph.row_map);
657 set_need_sync_host_uvm_access();
659 if (!params.is_null() && params->isParameter(
"sorted") &&
660 !params->get<
bool>(
"sorted")) {
666 const bool callComputeGlobalConstants =
667 params.get() ==
nullptr ||
668 params->get(
"compute global constants",
true);
669 if (callComputeGlobalConstants) {
672 fillComplete_ =
true;
676 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
678 CrsGraph(
const row_ptrs_device_view_type& rowPointers,
680 const Teuchos::RCP<const map_type>& rowMap,
681 const Teuchos::RCP<const map_type>& colMap,
682 const Teuchos::RCP<const map_type>& domainMap,
683 const Teuchos::RCP<const map_type>& rangeMap,
684 const Teuchos::RCP<const import_type>& importer,
685 const Teuchos::RCP<const export_type>& exporter,
686 const Teuchos::RCP<Teuchos::ParameterList>& params)
690 , rangeMap_(rangeMap.is_null() ? rowMap : rangeMap)
691 , domainMap_(domainMap.is_null() ? rowMap : domainMap)
692 , importer_(importer)
693 , exporter_(exporter)
694 , numAllocForAllRows_(0)
695 , storageStatus_(Details::STORAGE_1D_PACKED)
696 , indicesAreAllocated_(true)
697 , indicesAreLocal_(true) {
699 const char tfecfFuncName[] =
700 "Tpetra::CrsGraph(row_ptrs_device_view_type,local_inds_wdv_type"
701 "Map,Map,Map,Map,Import,Export,params): ";
703 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(colMap.is_null(), std::runtime_error,
704 "The input column Map must be nonnull.");
708 setRowPtrs(rowPointers);
710 set_need_sync_host_uvm_access();
712 if (!params.is_null() && params->isParameter(
"sorted") &&
713 !params->get<
bool>(
"sorted")) {
719 const bool callComputeGlobalConstants =
720 params.get() ==
nullptr ||
721 params->get(
"compute global constants",
true);
722 if (callComputeGlobalConstants) {
725 fillComplete_ =
true;
729 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
730 Teuchos::RCP<const Teuchos::ParameterList>
733 using Teuchos::ParameterList;
734 using Teuchos::parameterList;
737 RCP<ParameterList> params = parameterList(
"Tpetra::CrsGraph");
740 RCP<ParameterList> importSublist = parameterList(
"Import");
752 Distributor distributor(rowMap_->getComm(), importSublist);
753 params->set(
"Import", *importSublist,
"How the Import performs communication.");
759 params->set(
"Export", *importSublist,
"How the Export performs communication.");
764 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
767 Teuchos::RCP<const Teuchos::ParameterList> validParams =
768 getValidParameters();
769 params->validateParametersAndSetDefaults(*validParams);
770 this->setMyParamList(params);
773 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
777 return rowMap_->getGlobalNumElements();
780 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
784 const char tfecfFuncName[] =
"getGlobalNumCols: ";
785 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
786 !isFillComplete() || getDomainMap().is_null(), std::runtime_error,
787 "The graph does not have a domain Map. You may not call this method in "
789 return getDomainMap()->getGlobalNumElements();
792 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
796 return this->rowMap_.is_null() ?
static_cast<size_t>(0) : this->rowMap_->getLocalNumElements();
799 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
803 const char tfecfFuncName[] =
"getLocalNumCols: ";
804 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
805 !hasColMap(), std::runtime_error,
806 "The graph does not have a column Map. You may not call this method "
807 "unless the graph has a column Map. This requires either that a custom "
808 "column Map was given to the constructor, or that fillComplete() has "
810 return colMap_.is_null() ?
static_cast<size_t>(0) : colMap_->getLocalNumElements();
813 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
814 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
820 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
821 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
827 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
828 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
834 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
835 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
841 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
842 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::import_type>
848 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
849 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::export_type>
855 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
858 return !colMap_.is_null();
861 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
867 const bool isOpt = indicesAreAllocated_ &&
868 k_numRowEntries_.extent(0) == 0 &&
869 getLocalNumRows() > 0;
874 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
878 const char tfecfFuncName[] =
"getGlobalNumEntries: ";
879 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->haveGlobalConstants_, std::logic_error,
880 "The graph does not have global constants computed, "
881 "but the user has requested them.");
883 return globalNumEntries_;
886 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
890 const char tfecfFuncName[] =
"getLocalNumEntries: ";
891 typedef LocalOrdinal LO;
893 if (this->indicesAreAllocated_) {
894 const LO lclNumRows = this->getLocalNumRows();
895 if (lclNumRows == 0) {
896 return static_cast<size_t>(0);
899 auto numEntPerRow = this->k_numRowEntries_;
900 const LO numNumEntPerRow = numEntPerRow.extent(0);
901 if (numNumEntPerRow == 0) {
902 if (static_cast<LO>(this->getRowPtrsPackedDevice().extent(0)) <
903 static_cast<LO>(lclNumRows + 1)) {
904 return static_cast<size_t>(0);
910 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->getRowPtrsPackedHost()(lclNumRows) != lclIndsPacked_wdv.extent(0), std::logic_error,
911 "Final entry of packed host rowptrs doesn't match the length of lclIndsPacked");
913 return lclIndsPacked_wdv.extent(0);
922 typedef typename num_row_entries_type::execution_space
924 typedef Kokkos::RangePolicy<host_exec_space, LO> range_type;
926 const LO upperLoopBound = lclNumRows < numNumEntPerRow ? lclNumRows : numNumEntPerRow;
927 size_t nodeNumEnt = 0;
928 Kokkos::parallel_reduce(
929 "Tpetra::CrsGraph::getNumNodeEntries",
930 range_type(0, upperLoopBound),
931 [=](
const LO& k,
size_t& lclSum) {
932 lclSum += numEntPerRow(k);
939 return static_cast<size_t>(0);
943 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
947 const char tfecfFuncName[] =
"getGlobalMaxNumRowEntries: ";
948 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->haveGlobalConstants_, std::logic_error,
949 "The graph does not have global constants computed, "
950 "but the user has requested them.");
952 return globalMaxNumRowEntries_;
955 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
959 return nodeMaxNumRowEntries_;
962 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
965 return fillComplete_;
968 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
971 return !fillComplete_;
974 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
977 return indicesAreLocal_;
980 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
983 return indicesAreGlobal_;
986 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
990 typedef LocalOrdinal LO;
992 if (this->indicesAreAllocated_) {
993 const LO lclNumRows = this->getLocalNumRows();
994 if (lclNumRows == 0) {
995 return static_cast<size_t>(0);
996 }
else if (storageStatus_ == Details::STORAGE_1D_PACKED) {
997 if (static_cast<LO>(this->getRowPtrsPackedDevice().extent(0)) <
998 static_cast<LO
>(lclNumRows + 1)) {
999 return static_cast<size_t>(0);
1001 if (this->isLocallyIndexed())
1002 return lclIndsPacked_wdv.extent(0);
1004 return gblInds_wdv.extent(0);
1006 }
else if (storageStatus_ == Details::STORAGE_1D_UNPACKED) {
1007 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
1008 if (rowPtrsUnpacked_host.extent(0) == 0) {
1009 return static_cast<size_t>(0);
1011 if (this->isLocallyIndexed())
1012 return lclIndsUnpacked_wdv.extent(0);
1014 return gblInds_wdv.extent(0);
1017 return static_cast<size_t>(0);
1020 return Tpetra::Details::OrdinalTraits<size_t>::invalid();
1024 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1025 Teuchos::RCP<const Teuchos::Comm<int>>
1028 return this->rowMap_.is_null() ? Teuchos::null : this->rowMap_->getComm();
1031 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1035 return rowMap_->getIndexBase();
1038 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1041 return indicesAreAllocated_;
1044 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1047 return indicesAreSorted_;
1050 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1053 return noRedundancies_;
1056 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1064 indicesAreSorted_ =
false;
1065 noRedundancies_ =
false;
1069 haveLocalConstants_ =
false;
1072 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1077 using Teuchos::arcp;
1078 using Teuchos::Array;
1079 using Teuchos::ArrayRCP;
1080 typedef Teuchos::ArrayRCP<size_t>::size_type size_type;
1081 typedef typename local_graph_device_type::row_map_type::non_const_type
1082 non_const_row_map_type;
1083 const char tfecfFuncName[] =
"allocateIndices: ";
1084 const char suffix[] =
1085 " Please report this bug to the Tpetra developers.";
1086 ProfilingRegion profRegion(
"Tpetra::CrsGraph::allocateIndices");
1088 std::unique_ptr<std::string> prefix;
1090 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
1091 std::ostringstream os;
1092 os << *prefix <<
"Start: lg="
1093 << (lg == GlobalIndices ?
"GlobalIndices" :
"LocalIndices")
1094 <<
", numRows: " << this->getLocalNumRows() << endl;
1095 std::cerr << os.str();
1101 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isLocallyIndexed() && lg == GlobalIndices, std::logic_error,
1102 ": The graph is locally indexed, but Tpetra code is calling "
1103 "this method with lg=GlobalIndices."
1105 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isGloballyIndexed() && lg == LocalIndices, std::logic_error,
1106 ": The graph is globally indexed, but Tpetra code is calling "
1107 "this method with lg=LocalIndices."
1109 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreAllocated(), std::logic_error,
1111 "indices are already allocated, but Tpetra is calling "
1112 "allocateIndices again."
1114 const size_t numRows = this->getLocalNumRows();
1119 size_type numInds = 0;
1122 std::ostringstream os;
1123 os << *prefix <<
"Allocate k_rowPtrs: " << (numRows + 1) << endl;
1124 std::cerr << os.str();
1126 non_const_row_map_type k_rowPtrs(
"Tpetra::CrsGraph::ptr", numRows + 1);
1128 if (this->k_numAllocPerRow_.extent(0) != 0) {
1133 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->k_numAllocPerRow_.extent(0) != numRows,
1134 std::invalid_argument,
1135 "k_numAllocPerRow_ is allocated, that is, "
1136 "has nonzero length "
1137 << this->k_numAllocPerRow_.extent(0)
1138 <<
", but its length != numRows = " << numRows <<
".");
1155 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->numAllocForAllRows_ ==
1156 Tpetra::Details::OrdinalTraits<size_t>::invalid(),
1157 std::invalid_argument,
1158 "numAllocForAllRows_ has an invalid value, "
1159 "namely Tpetra::Details::OrdinalTraits<size_t>::invalid() = "
1160 << Tpetra::Details::OrdinalTraits<size_t>::invalid() <<
".");
1166 setRowPtrsUnpacked(k_rowPtrs);
1169 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numInds != size_type(this->getRowPtrsUnpackedHost()(numRows)), std::logic_error,
1170 ": Number of indices produced by computeOffsetsFrom[Constant]Counts "
1171 "does not match final entry of rowptrs unpacked");
1174 if (lg == LocalIndices) {
1176 std::ostringstream os;
1177 os << *prefix <<
"Allocate local column indices "
1178 "lclIndsUnpacked_wdv: "
1180 std::cerr << os.str();
1182 lclIndsUnpacked_wdv = local_inds_wdv_type(
1183 local_inds_dualv_type(
"Tpetra::CrsGraph::lclInd", numInds));
1186 std::ostringstream os;
1187 os << *prefix <<
"Allocate global column indices "
1190 std::cerr << os.str();
1192 gblInds_wdv = global_inds_wdv_type(
1193 global_inds_dualv_type(
"Tpetra::CrsGraph::gblInd", numInds));
1195 storageStatus_ = Details::STORAGE_1D_UNPACKED;
1197 this->indicesAreLocal_ = (lg == LocalIndices);
1198 this->indicesAreGlobal_ = (lg == GlobalIndices);
1201 using Kokkos::ViewAllocateWithoutInitializing;
1202 const char label[] =
"Tpetra::CrsGraph::numRowEntries";
1204 std::ostringstream os;
1205 os << *prefix <<
"Allocate k_numRowEntries_: " << numRows
1207 std::cerr << os.str();
1209 num_row_entries_type numRowEnt(ViewAllocateWithoutInitializing(label), numRows);
1212 Kokkos::fence(
"CrsGraph::allocateIndices");
1213 this->k_numRowEntries_ = numRowEnt;
1217 this->numAllocForAllRows_ = 0;
1218 this->k_numAllocPerRow_ = decltype(k_numAllocPerRow_)();
1219 this->indicesAreAllocated_ =
true;
1222 this->checkInternalState();
1223 }
catch (std::logic_error& e) {
1224 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
1225 "At end of allocateIndices, "
1226 "checkInternalState threw std::logic_error: "
1228 }
catch (std::exception& e) {
1229 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1230 "At end of allocateIndices, "
1231 "checkInternalState threw std::exception: "
1234 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1235 "At end of allocateIndices, "
1236 "checkInternalState threw an exception "
1237 "not a subclass of std::exception.");
1241 std::ostringstream os;
1242 os << *prefix <<
"Done" << endl;
1243 std::cerr << os.str();
1247 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1248 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1249 local_inds_dualv_type::t_host::const_type
1252 if (rowinfo.allocSize == 0 || lclIndsUnpacked_wdv.extent(0) == 0)
1253 return typename local_inds_dualv_type::t_host::const_type();
1255 return lclIndsUnpacked_wdv.getHostSubview(rowinfo.offset1D,
1260 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1262 local_inds_dualv_type::t_host
1265 if (rowinfo.allocSize == 0 || lclIndsUnpacked_wdv.extent(0) == 0)
1266 return typename local_inds_dualv_type::t_host();
1268 return lclIndsUnpacked_wdv.getHostSubview(rowinfo.offset1D,
1273 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1275 global_inds_dualv_type::t_host::const_type
1278 if (rowinfo.allocSize == 0 || gblInds_wdv.extent(0) == 0)
1279 return typename global_inds_dualv_type::t_host::const_type();
1281 return gblInds_wdv.getHostSubview(rowinfo.offset1D,
1286 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1288 local_inds_dualv_type::t_dev::const_type
1291 if (rowinfo.allocSize == 0 || lclIndsUnpacked_wdv.extent(0) == 0)
1292 return typename local_inds_dualv_type::t_dev::const_type();
1294 return lclIndsUnpacked_wdv.getDeviceSubview(rowinfo.offset1D,
1299 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1301 global_inds_dualv_type::t_dev::const_type
1304 if (rowinfo.allocSize == 0 || gblInds_wdv.extent(0) == 0)
1305 return typename global_inds_dualv_type::t_dev::const_type();
1307 return gblInds_wdv.getDeviceSubview(rowinfo.offset1D,
1312 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1316 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid();
1318 if (this->rowMap_.is_null() || !this->rowMap_->isNodeLocalElement(myRow)) {
1319 ret.localRow = STINV;
1322 ret.offset1D = STINV;
1326 ret.localRow =
static_cast<size_t>(myRow);
1327 if (this->indicesAreAllocated()) {
1328 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
1330 if (rowPtrsUnpacked_host.extent(0) == 0) {
1334 ret.offset1D = rowPtrsUnpacked_host(myRow);
1335 ret.allocSize = rowPtrsUnpacked_host(myRow + 1) - rowPtrsUnpacked_host(myRow);
1338 ret.numEntries = (this->k_numRowEntries_.extent(0) == 0) ? ret.allocSize : this->k_numRowEntries_(myRow);
1343 ret.allocSize = (this->k_numAllocPerRow_.extent(0) != 0) ? this->k_numAllocPerRow_(myRow) :
1344 this->numAllocForAllRows_;
1346 ret.offset1D = STINV;
1352 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1356 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid();
1358 if (this->rowMap_.is_null()) {
1359 ret.localRow = STINV;
1362 ret.offset1D = STINV;
1365 const LocalOrdinal myRow = this->rowMap_->getLocalElement(gblRow);
1366 if (myRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid()) {
1367 ret.localRow = STINV;
1370 ret.offset1D = STINV;
1374 ret.localRow =
static_cast<size_t>(myRow);
1375 if (this->indicesAreAllocated()) {
1379 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
1380 if (rowPtrsUnpacked_host.extent(0) == 0) {
1384 ret.offset1D = rowPtrsUnpacked_host(myRow);
1385 ret.allocSize = rowPtrsUnpacked_host(myRow + 1) - rowPtrsUnpacked_host(myRow);
1388 ret.numEntries = (this->k_numRowEntries_.extent(0) == 0) ? ret.allocSize : this->k_numRowEntries_(myRow);
1393 ret.allocSize = (this->k_numAllocPerRow_.extent(0) != 0) ? this->k_numAllocPerRow_(myRow) :
1394 this->numAllocForAllRows_;
1396 ret.offset1D = STINV;
1402 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1405 using Teuchos::OrdinalTraits;
1406 typedef LocalOrdinal LO;
1407 typedef GlobalOrdinal GO;
1413 static_assert(
sizeof(GlobalOrdinal) >=
sizeof(LocalOrdinal),
1414 "Tpetra::CrsGraph: sizeof(GlobalOrdinal) must be >= sizeof(LocalOrdinal).");
1417 static_assert(
sizeof(
size_t) >=
sizeof(LocalOrdinal),
1418 "Tpetra::CrsGraph: sizeof(size_t) must be >= sizeof(LocalOrdinal).");
1419 static_assert(
sizeof(GST) >=
sizeof(
size_t),
1420 "Tpetra::CrsGraph: sizeof(Tpetra::global_size_t) must be >= sizeof(size_t).");
1429 "Tpetra::CrsGraph: Object cannot be created with the "
1430 "given template arguments: size assumptions are not valid.";
1431 TEUCHOS_TEST_FOR_EXCEPTION(
1432 static_cast<size_t>(Teuchos::OrdinalTraits<LO>::max()) > Teuchos::OrdinalTraits<size_t>::max(),
1433 std::runtime_error, msg);
1434 TEUCHOS_TEST_FOR_EXCEPTION(
1435 static_cast<GST>(Teuchos::OrdinalTraits<LO>::max()) > static_cast<GST>(Teuchos::OrdinalTraits<GO>::max()),
1436 std::runtime_error, msg);
1437 TEUCHOS_TEST_FOR_EXCEPTION(
1438 static_cast<size_t>(Teuchos::OrdinalTraits<GO>::max()) > Teuchos::OrdinalTraits<GST>::max(),
1439 std::runtime_error, msg);
1440 TEUCHOS_TEST_FOR_EXCEPTION(
1441 Teuchos::OrdinalTraits<size_t>::max() > Teuchos::OrdinalTraits<GST>::max(),
1442 std::runtime_error, msg);
1445 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1449 const SLocalGlobalViews& newInds,
1450 const ELocalGlobal lg,
1451 const ELocalGlobal I) {
1452 using Teuchos::ArrayView;
1453 typedef LocalOrdinal LO;
1454 typedef GlobalOrdinal GO;
1455 const char tfecfFuncName[] =
"insertIndices: ";
1457 size_t oldNumEnt = 0;
1459 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lg != GlobalIndices && lg != LocalIndices, std::invalid_argument,
1460 "lg must be either GlobalIndices or LocalIndices.");
1461 oldNumEnt = this->getNumEntriesInLocalRow(rowinfo.localRow);
1464 size_t numNewInds = 0;
1465 if (lg == GlobalIndices) {
1466 ArrayView<const GO> new_ginds = newInds.ginds;
1467 numNewInds = new_ginds.size();
1468 if (I == GlobalIndices) {
1469 auto gind_view = gblInds_wdv.getHostView(Access::ReadWrite);
1471 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(static_cast<size_t>(gind_view.size()) <
1472 rowinfo.numEntries + numNewInds,
1474 "gind_view.size() = " << gind_view.size()
1475 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1476 <<
") + numNewInds (= " << numNewInds <<
").");
1478 GO*
const gblColInds_out = gind_view.data() + rowinfo.offset1D + rowinfo.numEntries;
1479 for (
size_t k = 0; k < numNewInds; ++k) {
1480 gblColInds_out[k] = new_ginds[k];
1482 }
else if (I == LocalIndices) {
1483 auto lind_view = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1485 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(static_cast<size_t>(lind_view.size()) <
1486 rowinfo.numEntries + numNewInds,
1488 "lind_view.size() = " << lind_view.size()
1489 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1490 <<
") + numNewInds (= " << numNewInds <<
").");
1492 LO*
const lclColInds_out = lind_view.data() + rowinfo.offset1D + rowinfo.numEntries;
1493 for (
size_t k = 0; k < numNewInds; ++k) {
1494 lclColInds_out[k] = colMap_->getLocalElement(new_ginds[k]);
1497 }
else if (lg == LocalIndices) {
1498 ArrayView<const LO> new_linds = newInds.linds;
1499 numNewInds = new_linds.size();
1500 if (I == LocalIndices) {
1501 auto lind_view = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1503 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(static_cast<size_t>(lind_view.size()) <
1504 rowinfo.numEntries + numNewInds,
1506 "lind_view.size() = " << lind_view.size()
1507 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1508 <<
") + numNewInds (= " << numNewInds <<
").");
1510 LO*
const lclColInds_out = lind_view.data() + rowinfo.offset1D + rowinfo.numEntries;
1511 for (
size_t k = 0; k < numNewInds; ++k) {
1512 lclColInds_out[k] = new_linds[k];
1514 }
else if (I == GlobalIndices) {
1515 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
1516 "The case where the input indices are local "
1517 "and the indices to write are global (lg=LocalIndices, I="
1518 "GlobalIndices) is not implemented, because it does not make sense."
1520 <<
"If you have correct local column indices, that "
1521 "means the graph has a column Map. In that case, you should be "
1522 "storing local indices.");
1526 rowinfo.numEntries += numNewInds;
1527 this->k_numRowEntries_(rowinfo.localRow) += numNewInds;
1528 this->setLocallyModified();
1531 const size_t chkNewNumEnt =
1532 this->getNumEntriesInLocalRow(rowinfo.localRow);
1533 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(chkNewNumEnt != oldNumEnt + numNewInds, std::logic_error,
1534 "chkNewNumEnt = " << chkNewNumEnt
1535 <<
" != oldNumEnt (= " << oldNumEnt
1536 <<
") + numNewInds (= " << numNewInds <<
").");
1542 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1546 const GlobalOrdinal inputGblColInds[],
1547 const size_t numInputInds) {
1548 return this->insertGlobalIndicesImpl(this->getRowInfo(lclRow),
1549 inputGblColInds, numInputInds);
1552 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1556 const GlobalOrdinal inputGblColInds[],
1557 const size_t numInputInds,
1558 std::function<
void(
const size_t,
const size_t,
const size_t)> fun) {
1560 using Kokkos::MemoryUnmanaged;
1561 using Kokkos::subview;
1563 using Teuchos::ArrayView;
1564 using LO = LocalOrdinal;
1565 using GO = GlobalOrdinal;
1566 const char tfecfFuncName[] =
"insertGlobalIndicesImpl: ";
1567 const LO lclRow =
static_cast<LO
>(rowInfo.localRow);
1569 auto numEntries = rowInfo.numEntries;
1570 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1571 inp_view_type inputInds(inputGblColInds, numInputInds);
1574 auto gblIndsHostView = this->gblInds_wdv.getHostView(Access::ReadWrite);
1577 numEntries, inputInds, fun);
1580 const bool insertFailed =
1581 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1583 constexpr
size_t ONE(1);
1584 const int myRank = this->getComm()->getRank();
1585 std::ostringstream os;
1587 os <<
"Proc " << myRank <<
": Not enough capacity to insert "
1589 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1590 <<
" into local row " << lclRow <<
", which currently has "
1591 << rowInfo.numEntries
1592 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1593 <<
" and total allocation size " << rowInfo.allocSize
1595 const size_t maxNumToPrint =
1597 ArrayView<const GO> inputGblColIndsView(inputGblColInds,
1604 auto curGblColInds = getGlobalIndsViewHost(rowInfo);
1605 ArrayView<const GO> curGblColIndsView(curGblColInds.data(),
1606 rowInfo.numEntries);
1611 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
1614 this->k_numRowEntries_(lclRow) += numInserted;
1616 this->setLocallyModified();
1620 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1623 const Teuchos::ArrayView<const LocalOrdinal>& indices,
1624 std::function<
void(
const size_t,
const size_t,
const size_t)> fun) {
1625 using Kokkos::MemoryUnmanaged;
1626 using Kokkos::subview;
1628 using LO = LocalOrdinal;
1629 const char tfecfFuncName[] =
"insertLocallIndicesImpl: ";
1631 const RowInfo rowInfo = this->getRowInfo(myRow);
1633 size_t numNewInds = 0;
1634 size_t newNumEntries = 0;
1636 auto numEntries = rowInfo.numEntries;
1638 using inp_view_type = View<const LO*, Kokkos::HostSpace, MemoryUnmanaged>;
1639 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1640 size_t numInserted = 0;
1642 auto lclInds = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1644 numEntries, inputInds, fun);
1647 const bool insertFailed =
1648 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1650 constexpr
size_t ONE(1);
1651 const size_t numInputInds(indices.size());
1652 const int myRank = this->getComm()->getRank();
1653 std::ostringstream os;
1654 os <<
"On MPI Process " << myRank <<
": Not enough capacity to "
1657 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1658 <<
" into local row " << myRow <<
", which currently has "
1659 << rowInfo.numEntries
1660 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1661 <<
" and total allocation size " << rowInfo.allocSize <<
".";
1662 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
1664 numNewInds = numInserted;
1665 newNumEntries = rowInfo.numEntries + numNewInds;
1667 this->k_numRowEntries_(myRow) += numNewInds;
1668 this->setLocallyModified();
1671 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow(myRow);
1672 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(chkNewNumEntries != newNumEntries, std::logic_error,
1673 "getNumEntriesInLocalRow(" << myRow <<
") = " << chkNewNumEntries
1674 <<
" != newNumEntries = " << newNumEntries
1675 <<
". Please report this bug to the Tpetra developers.");
1679 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1683 const Teuchos::ArrayView<const GlobalOrdinal>& indices,
1684 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
const {
1685 using GO = GlobalOrdinal;
1686 using Kokkos::MemoryUnmanaged;
1688 auto invalidCount = Teuchos::OrdinalTraits<size_t>::invalid();
1690 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1691 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1693 size_t numFound = 0;
1694 LocalOrdinal lclRow = rowInfo.localRow;
1695 if (this->isLocallyIndexed()) {
1696 if (this->colMap_.is_null())
1697 return invalidCount;
1698 const auto& colMap = *(this->colMap_);
1699 auto map = [&](GO
const gblInd) {
return colMap.getLocalElement(gblInd); };
1702 lclIndsUnpacked_wdv.getHostView(Access::ReadOnly), inputInds, map, fun);
1703 }
else if (this->isGloballyIndexed()) {
1706 gblInds_wdv.getHostView(Access::ReadOnly), inputInds, fun);
1711 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1716 const bool merged) {
1717 const size_t origNumEnt = rowInfo.numEntries;
1718 if (origNumEnt != Tpetra::Details::OrdinalTraits<size_t>::invalid() &&
1720 auto lclColInds = this->getLocalIndsViewHostNonConst(rowInfo);
1722 LocalOrdinal*
const lclColIndsRaw = lclColInds.data();
1724 std::sort(lclColIndsRaw, lclColIndsRaw + origNumEnt);
1728 LocalOrdinal*
const beg = lclColIndsRaw;
1729 LocalOrdinal*
const end = beg + rowInfo.numEntries;
1730 LocalOrdinal*
const newend = std::unique(beg, end);
1731 const size_t newNumEnt = newend - beg;
1734 this->k_numRowEntries_(rowInfo.localRow) = newNumEnt;
1735 return origNumEnt - newNumEnt;
1737 return static_cast<size_t>(0);
1740 return static_cast<size_t>(0);
1744 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1747 const Teuchos::RCP<const map_type>& rangeMap) {
1749 if (domainMap_ != domainMap) {
1750 domainMap_ = domainMap;
1751 importer_ = Teuchos::null;
1753 if (rangeMap_ != rangeMap) {
1754 rangeMap_ = rangeMap;
1755 exporter_ = Teuchos::null;
1759 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1762 const auto INV = Teuchos::OrdinalTraits<global_size_t>::invalid();
1764 globalNumEntries_ = INV;
1765 globalMaxNumRowEntries_ = INV;
1766 haveGlobalConstants_ =
false;
1769 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1774 const char tfecfFuncName[] =
"checkInternalState: ";
1775 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1777 std::unique_ptr<std::string> prefix;
1779 prefix = this->createPrefix(
"CrsGraph",
"checkInternalState");
1780 std::ostringstream os;
1781 os << *prefix <<
"Start" << endl;
1782 std::cerr << os.str();
1785 const global_size_t GSTI = Teuchos::OrdinalTraits<global_size_t>::invalid();
1791 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->rowMap_.is_null(), std::logic_error,
1792 "Row Map is null." << suffix);
1795 const LocalOrdinal lclNumRows =
1796 static_cast<LocalOrdinal
>(this->getLocalNumRows());
1798 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isFillActive() == this->isFillComplete(), std::logic_error,
1799 "Graph cannot be both fill active and fill complete." << suffix);
1800 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isFillComplete() &&
1801 (this->colMap_.is_null() ||
1802 this->rangeMap_.is_null() ||
1803 this->domainMap_.is_null()),
1805 "Graph is full complete, but at least one of {column, range, domain} "
1808 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isStorageOptimized() && !this->indicesAreAllocated(),
1810 "Storage is optimized, but indices are not "
1811 "allocated, not even trivially."
1814 size_t nodeAllocSize = 0;
1816 nodeAllocSize = this->getLocalAllocationSize();
1817 }
catch (std::logic_error& e) {
1818 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1819 "getLocalAllocationSize threw "
1820 "std::logic_error: "
1822 }
catch (std::exception& e) {
1823 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1824 "getLocalAllocationSize threw an "
1828 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1829 "getLocalAllocationSize threw an exception "
1830 "not a subclass of std::exception.");
1833 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isStorageOptimized() &&
1834 nodeAllocSize != this->getLocalNumEntries(),
1836 "Storage is optimized, but "
1837 "this->getLocalAllocationSize() = "
1839 <<
" != this->getLocalNumEntries() = " << this->getLocalNumEntries()
1841 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->haveGlobalConstants_ &&
1842 (this->globalNumEntries_ != GSTI ||
1843 this->globalMaxNumRowEntries_ != GSTI),
1845 "Graph claims not to have global constants, but "
1846 "some of the global constants are not marked as invalid."
1848 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->haveGlobalConstants_ &&
1849 (this->globalNumEntries_ == GSTI ||
1850 this->globalMaxNumRowEntries_ == GSTI),
1852 "Graph claims to have global constants, but "
1853 "some of them are marked as invalid."
1855 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->haveGlobalConstants_ &&
1856 (this->globalNumEntries_ < this->getLocalNumEntries() ||
1857 this->globalMaxNumRowEntries_ < this->nodeMaxNumRowEntries_),
1859 "Graph claims to have global constants, and "
1860 "all of the values of the global constants are valid, but "
1861 "some of the local constants are greater than "
1862 "their corresponding global constants."
1864 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->indicesAreAllocated() &&
1865 (this->numAllocForAllRows_ != 0 ||
1866 this->k_numAllocPerRow_.extent(0) != 0),
1868 "The graph claims that its indices are allocated, but "
1869 "either numAllocForAllRows_ (= "
1870 << this->numAllocForAllRows_ <<
") is "
1871 "nonzero, or k_numAllocPerRow_ has nonzero dimension. In other words, "
1872 "the graph is supposed to release its \"allocation specifications\" "
1873 "when it allocates its indices."
1875 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
1876 auto rowPtrsUnpacked_dev = this->getRowPtrsUnpackedDevice();
1877 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked_host.extent(0) != rowPtrsUnpacked_dev.extent(0),
1879 "The host and device views of k_rowPtrs_ have "
1880 "different sizes; rowPtrsUnpacked_host_ has size "
1881 << rowPtrsUnpacked_host.extent(0)
1882 <<
", but rowPtrsUnpacked_dev_ has size "
1883 << rowPtrsUnpacked_dev.extent(0)
1885 if (isGloballyIndexed() && rowPtrsUnpacked_host.extent(0) != 0) {
1886 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
size_t(rowPtrsUnpacked_host.extent(0)) !=
size_t(lclNumRows + 1),
1888 "The graph is globally indexed and "
1889 "k_rowPtrs has nonzero size "
1890 << rowPtrsUnpacked_host.extent(0)
1891 <<
", but that size does not equal lclNumRows+1 = "
1892 << (lclNumRows + 1) <<
"." << suffix);
1893 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked_host(lclNumRows) !=
size_t(gblInds_wdv.extent(0)),
1895 "The graph is globally indexed and "
1896 "k_rowPtrs_ has nonzero size "
1897 << rowPtrsUnpacked_host.extent(0)
1898 <<
", but k_rowPtrs_(lclNumRows=" << lclNumRows <<
")="
1899 << rowPtrsUnpacked_host(lclNumRows)
1900 <<
" != gblInds_wdv.extent(0)="
1901 << gblInds_wdv.extent(0) <<
"." << suffix);
1903 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isLocallyIndexed() &&
1904 rowPtrsUnpacked_host.extent(0) != 0 &&
1905 (
static_cast<size_t>(rowPtrsUnpacked_host.extent(0)) !=
1906 static_cast<size_t>(lclNumRows + 1) ||
1907 rowPtrsUnpacked_host(lclNumRows) !=
1908 static_cast<size_t>(this->lclIndsUnpacked_wdv.extent(0))),
1910 "If k_rowPtrs_ has nonzero size and "
1911 "the graph is locally indexed, then "
1912 "k_rowPtrs_ must have N+1 rows, and "
1913 "k_rowPtrs_(N) must equal lclIndsUnpacked_wdv.extent(0)."
1916 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->indicesAreAllocated() &&
1917 nodeAllocSize > 0 &&
1918 this->lclIndsUnpacked_wdv.extent(0) == 0 &&
1919 this->gblInds_wdv.extent(0) == 0,
1921 "Graph is allocated nontrivially, but "
1922 "but 1-D allocations are not present."
1925 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->indicesAreAllocated() &&
1926 ((rowPtrsUnpacked_host.extent(0) != 0 ||
1927 this->k_numRowEntries_.extent(0) != 0) ||
1928 this->lclIndsUnpacked_wdv.extent(0) != 0 ||
1929 this->gblInds_wdv.extent(0) != 0),
1931 "If indices are not allocated, "
1932 "then none of the buffers should be."
1937 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC((this->indicesAreLocal_ || this->indicesAreGlobal_) &&
1938 !this->indicesAreAllocated_,
1940 "Indices may be local or global only if they are "
1943 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->indicesAreLocal_ && this->indicesAreGlobal_,
1944 std::logic_error,
"Indices may not be both local and global." << suffix);
1945 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreLocal_ && gblInds_wdv.extent(0) != 0,
1947 "Indices are local, but "
1948 "gblInds_wdv.extent(0) (= "
1949 << gblInds_wdv.extent(0)
1950 <<
") != 0. In other words, if indices are local, then "
1951 "allocations of global indices should not be present."
1953 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreGlobal_ && lclIndsUnpacked_wdv.extent(0) != 0,
1955 "Indices are global, but "
1956 "lclIndsUnpacked_wdv.extent(0) (= "
1957 << lclIndsUnpacked_wdv.extent(0)
1958 <<
") != 0. In other words, if indices are global, "
1959 "then allocations for local indices should not be present."
1961 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreLocal_ && nodeAllocSize > 0 &&
1962 lclIndsUnpacked_wdv.extent(0) == 0 && getLocalNumRows() > 0,
1964 "Indices are local and "
1965 "getLocalAllocationSize() = "
1966 << nodeAllocSize <<
" > 0, but "
1967 "lclIndsUnpacked_wdv.extent(0) = 0 and getLocalNumRows() = "
1968 << getLocalNumRows() <<
" > 0." << suffix);
1969 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreGlobal_ && nodeAllocSize > 0 &&
1970 gblInds_wdv.extent(0) == 0 && getLocalNumRows() > 0,
1972 "Indices are global and "
1973 "getLocalAllocationSize() = "
1974 << nodeAllocSize <<
" > 0, but "
1975 "gblInds_wdv.extent(0) = 0 and getLocalNumRows() = "
1976 << getLocalNumRows() <<
" > 0." << suffix);
1978 if (this->indicesAreAllocated() &&
1979 rowPtrsUnpacked_host.extent(0) != 0) {
1980 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(static_cast<size_t>(rowPtrsUnpacked_host.extent(0)) !=
1981 this->getLocalNumRows() + 1,
1983 "Indices are allocated and "
1984 "k_rowPtrs_ has nonzero length, but rowPtrsUnpacked_host_.extent(0) = "
1985 << rowPtrsUnpacked_host.extent(0) <<
" != getLocalNumRows()+1 = "
1986 << (this->getLocalNumRows() + 1) <<
"." << suffix);
1987 const size_t actualNumAllocated =
1988 rowPtrsUnpacked_host(this->getLocalNumRows());
1989 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isLocallyIndexed() &&
1990 static_cast<size_t>(this->lclIndsUnpacked_wdv.extent(0)) != actualNumAllocated,
1992 "Graph is locally indexed, indices are "
1993 "are allocated, and k_rowPtrs_ has nonzero length, but "
1994 "lclIndsUnpacked_wdv.extent(0) = "
1995 << this->lclIndsUnpacked_wdv.extent(0)
1996 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
1997 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isGloballyIndexed() &&
1998 static_cast<size_t>(this->gblInds_wdv.extent(0)) != actualNumAllocated,
2000 "Graph is globally indexed, indices "
2001 "are allocated, and k_rowPtrs_ has nonzero length, but "
2002 "gblInds_wdv.extent(0) = "
2003 << this->gblInds_wdv.extent(0)
2004 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2008 std::ostringstream os;
2009 os << *prefix <<
"Done" << endl;
2010 std::cerr << os.str();
2015 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2019 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex(globalRow);
2020 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2021 return Teuchos::OrdinalTraits<size_t>::invalid();
2023 return rowInfo.numEntries;
2027 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2031 const RowInfo rowInfo = this->getRowInfo(localRow);
2032 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2033 return Teuchos::OrdinalTraits<size_t>::invalid();
2035 return rowInfo.numEntries;
2039 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2043 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex(globalRow);
2044 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2045 return Teuchos::OrdinalTraits<size_t>::invalid();
2047 return rowInfo.allocSize;
2051 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2055 const RowInfo rowInfo = this->getRowInfo(localRow);
2056 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2057 return Teuchos::OrdinalTraits<size_t>::invalid();
2059 return rowInfo.allocSize;
2063 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2064 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_host_view_type
2067 return getRowPtrsPackedHost();
2070 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2071 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_device_view_type
2074 return getRowPtrsPackedDevice();
2077 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2078 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::local_inds_host_view_type
2081 return lclIndsPacked_wdv.getHostView(Access::ReadOnly);
2084 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2088 return lclIndsPacked_wdv.getDeviceView(Access::ReadOnly);
2091 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2094 nonconst_local_inds_host_view_type& indices,
2095 size_t& numEntries)
const {
2096 using Teuchos::ArrayView;
2097 const char tfecfFuncName[] =
"getLocalRowCopy: ";
2099 TEUCHOS_TEST_FOR_EXCEPTION(
2100 isGloballyIndexed() && !hasColMap(), std::runtime_error,
2101 "Tpetra::CrsGraph::getLocalRowCopy: The graph is globally indexed and "
2102 "does not have a column Map yet. That means we don't have local indices "
2103 "for columns yet, so it doesn't make sense to call this method. If the "
2104 "graph doesn't have a column Map yet, you should call fillComplete on "
2109 const RowInfo rowinfo = this->getRowInfo(localRow);
2111 const size_t theNumEntries = rowinfo.numEntries;
2112 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(static_cast<size_t>(indices.size()) < theNumEntries, std::runtime_error,
2113 "Specified storage (size==" << indices.size() <<
") does not suffice "
2115 << theNumEntries <<
" entry/ies for this row.");
2116 numEntries = theNumEntries;
2118 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid()) {
2119 if (isLocallyIndexed()) {
2120 auto lclInds = getLocalIndsViewHost(rowinfo);
2121 for (
size_t j = 0; j < theNumEntries; ++j) {
2122 indices[j] = lclInds(j);
2124 }
else if (isGloballyIndexed()) {
2125 auto gblInds = getGlobalIndsViewHost(rowinfo);
2126 for (
size_t j = 0; j < theNumEntries; ++j) {
2127 indices[j] = colMap_->getLocalElement(gblInds(j));
2133 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2136 nonconst_global_inds_host_view_type& indices,
2137 size_t& numEntries)
const {
2138 using Teuchos::ArrayView;
2139 const char tfecfFuncName[] =
"getGlobalRowCopy: ";
2143 const RowInfo rowinfo = getRowInfoFromGlobalRowIndex(globalRow);
2144 const size_t theNumEntries = rowinfo.numEntries;
2145 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2146 static_cast<size_t>(indices.size()) < theNumEntries, std::runtime_error,
2147 "Specified storage (size==" << indices.size() <<
") does not suffice "
2149 << theNumEntries <<
" entry/ies for this row.");
2150 numEntries = theNumEntries;
2152 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid()) {
2153 if (isLocallyIndexed()) {
2154 auto lclInds = getLocalIndsViewHost(rowinfo);
2155 for (
size_t j = 0; j < theNumEntries; ++j) {
2156 indices[j] = colMap_->getGlobalElement(lclInds(j));
2158 }
else if (isGloballyIndexed()) {
2159 auto gblInds = getGlobalIndsViewHost(rowinfo);
2160 for (
size_t j = 0; j < theNumEntries; ++j) {
2161 indices[j] = gblInds(j);
2167 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2170 const LocalOrdinal localRow,
2171 local_inds_host_view_type& indices)
const {
2172 const char tfecfFuncName[] =
"getLocalRowView: ";
2174 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isGloballyIndexed(), std::runtime_error,
2175 "The graph's indices are "
2176 "currently stored as global indices, so we cannot return a view with "
2177 "local column indices, whether or not the graph has a column Map. If "
2178 "the graph _does_ have a column Map, use getLocalRowCopy() instead.");
2180 const RowInfo rowInfo = getRowInfo(localRow);
2181 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid() &&
2182 rowInfo.numEntries > 0) {
2183 indices = lclIndsUnpacked_wdv.getHostSubview(rowInfo.offset1D,
2189 indices = local_inds_host_view_type();
2193 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(static_cast<size_t>(indices.size()) !=
2194 getNumEntriesInLocalRow(localRow),
2197 "= " << indices.extent(0)
2198 <<
" != getNumEntriesInLocalRow(localRow=" << localRow <<
") = " << getNumEntriesInLocalRow(localRow) <<
". Please report this bug to the Tpetra developers.");
2202 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2205 const GlobalOrdinal globalRow,
2206 global_inds_host_view_type& indices)
const {
2207 const char tfecfFuncName[] =
"getGlobalRowView: ";
2209 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isLocallyIndexed(), std::runtime_error,
2210 "The graph's indices are "
2211 "currently stored as local indices, so we cannot return a view with "
2212 "global column indices. Use getGlobalRowCopy() instead.");
2216 const RowInfo rowInfo = getRowInfoFromGlobalRowIndex(globalRow);
2217 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid() &&
2218 rowInfo.numEntries > 0) {
2219 indices = gblInds_wdv.getHostSubview(rowInfo.offset1D,
2223 indices =
typename global_inds_dualv_type::t_host::const_type();
2226 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(static_cast<size_t>(indices.size()) !=
2227 getNumEntriesInGlobalRow(globalRow),
2228 std::logic_error,
"indices.size() = " << indices.extent(0) <<
" != getNumEntriesInGlobalRow(globalRow=" << globalRow <<
") = " << getNumEntriesInGlobalRow(globalRow) <<
". Please report this bug to the Tpetra developers.");
2232 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2235 const Teuchos::ArrayView<const LocalOrdinal>& indices) {
2236 const char tfecfFuncName[] =
"insertLocalIndices: ";
2238 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!isFillActive(), std::runtime_error,
"Fill must be active.");
2239 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isGloballyIndexed(), std::runtime_error,
2240 "Graph indices are global; use insertGlobalIndices().");
2241 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!hasColMap(), std::runtime_error,
2242 "Cannot insert local indices without a column Map.");
2243 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!rowMap_->isNodeLocalElement(localRow), std::runtime_error,
2244 "Local row index " << localRow <<
" is not in the row Map "
2245 "on the calling process.");
2246 if (!indicesAreAllocated()) {
2247 allocateIndices(LocalIndices, verbose_);
2257 using Teuchos::Array;
2258 using Teuchos::toString;
2259 typedef typename Teuchos::ArrayView<const LocalOrdinal>::size_type size_type;
2262 Array<LocalOrdinal> badColInds;
2263 bool allInColMap =
true;
2264 for (size_type k = 0; k < indices.size(); ++k) {
2266 allInColMap =
false;
2267 badColInds.push_back(indices[k]);
2271 std::ostringstream os;
2272 os <<
"Tpetra::CrsGraph::insertLocalIndices: You attempted to insert "
2273 "entries in owned row "
2274 << localRow <<
", at the following column "
2276 << toString(indices) <<
"." << endl;
2277 os <<
"Of those, the following indices are not in the column Map on "
2279 << toString(badColInds) <<
"." << endl
2281 "the graph has a column Map already, it is invalid to insert entries "
2282 "at those locations.";
2283 TEUCHOS_TEST_FOR_EXCEPTION(!allInColMap, std::invalid_argument, os.str());
2288 insertLocalIndicesImpl(localRow, indices);
2291 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!indicesAreAllocated() || !isLocallyIndexed(), std::logic_error,
2292 "At the end of insertLocalIndices, ! indicesAreAllocated() || "
2293 "! isLocallyIndexed() is true. Please report this bug to the "
2294 "Tpetra developers.");
2298 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2301 const LocalOrdinal numEnt,
2302 const LocalOrdinal inds[]) {
2303 Teuchos::ArrayView<const LocalOrdinal> indsT(inds, numEnt);
2304 this->insertLocalIndices(localRow, indsT);
2307 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2310 const LocalOrdinal numInputInds,
2311 const GlobalOrdinal inputGblColInds[]) {
2312 typedef LocalOrdinal LO;
2313 const char tfecfFuncName[] =
"insertGlobalIndices: ";
2315 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isLocallyIndexed(), std::runtime_error,
2316 "graph indices are local; use insertLocalIndices().");
2321 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->isFillActive(), std::runtime_error,
2322 "You are not allowed to call this method if fill is not active. "
2323 "If fillComplete has been called, you must first call resumeFill "
2324 "before you may insert indices.");
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_);
2338 std::vector<GlobalOrdinal> badColInds;
2339 bool allInColMap =
true;
2340 for (LO k = 0; k < numInputInds; ++k) {
2342 allInColMap =
false;
2343 badColInds.push_back(inputGblColInds[k]);
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,
2379 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2382 const Teuchos::ArrayView<const GlobalOrdinal>& inputGblColInds) {
2383 this->insertGlobalIndices(gblRow, inputGblColInds.size(),
2384 inputGblColInds.getRawPtr());
2387 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2390 const GlobalOrdinal gblColInds[],
2391 const LocalOrdinal numGblColInds) {
2392 typedef LocalOrdinal LO;
2393 typedef GlobalOrdinal GO;
2394 const char tfecfFuncName[] =
"insertGlobalIndicesFiltered: ";
2396 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isLocallyIndexed(), std::runtime_error,
2397 "Graph indices are local; use insertLocalIndices().");
2402 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->isFillActive(), std::runtime_error,
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_);
2410 Teuchos::ArrayView<const GO> gblColInds_av(gblColInds, numGblColInds);
2412 if (!colMap_.is_null()) {
2413 const map_type& colMap = *(this->colMap_);
2416 while (curOffset < numGblColInds) {
2420 LO endOffset = curOffset;
2421 for (; endOffset < numGblColInds; ++endOffset) {
2423 if (lclCol == Tpetra::Details::OrdinalTraits<LO>::invalid()) {
2430 const LO numIndInSeq = (endOffset - curOffset);
2431 if (numIndInSeq != 0) {
2432 this->insertGlobalIndicesImpl(lclRow, gblColInds + curOffset,
2438 curOffset = endOffset + 1;
2441 this->insertGlobalIndicesImpl(lclRow, gblColInds_av.getRawPtr(),
2442 gblColInds_av.size());
2446 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2449 const GlobalOrdinal gblColInds[],
2450 const LocalOrdinal numGblColInds) {
2454 std::vector<GlobalOrdinal>& nonlocalRow = this->nonlocals_[gblRow];
2455 for (LocalOrdinal k = 0; k < numGblColInds; ++k) {
2459 nonlocalRow.push_back(gblColInds[k]);
2463 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2466 const char tfecfFuncName[] =
"removeLocalIndices: ";
2467 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2468 !isFillActive(), std::runtime_error,
"requires that fill is active.");
2469 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2470 isStorageOptimized(), std::runtime_error,
2471 "cannot remove indices after optimizeStorage() has been called.");
2472 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2473 isGloballyIndexed(), std::runtime_error,
"graph indices are global.");
2474 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
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;
2486 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(getNumEntriesInLocalRow(lrow) != 0 ||
2487 !indicesAreAllocated() ||
2488 !isLocallyIndexed(),
2490 "Violated stated post-conditions. Please contact Tpetra team.");
2494 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2496 setAllIndices(
const typename local_graph_device_type::row_map_type& rowPointers,
2497 const typename local_graph_device_type::entries_type::non_const_type& columnIndices) {
2499 ProfilingRegion region(
"Tpetra::CrsGraph::setAllIndices");
2500 const char tfecfFuncName[] =
"setAllIndices: ";
2501 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2502 !hasColMap() || getColMap().is_null(), std::runtime_error,
2503 "The graph must have a column Map before you may call this method.");
2504 LocalOrdinal numLocalRows = this->getLocalNumRows();
2506 LocalOrdinal rowPtrLen = rowPointers.size();
2507 if (numLocalRows == 0) {
2508 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2509 rowPtrLen != 0 && rowPtrLen != 1,
2510 std::runtime_error,
"Have 0 local rows, but rowPointers.size() is neither 0 nor 1.");
2512 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2513 rowPtrLen != numLocalRows + 1,
2514 std::runtime_error,
"rowPointers.size() = " << rowPtrLen <<
" != this->getLocalNumRows()+1 = " << (numLocalRows + 1) <<
".");
2519 using exec_space =
typename local_graph_device_type::execution_space;
2520 int columnsOutOfBounds = 0;
2522 Kokkos::parallel_reduce(
2523 Kokkos::RangePolicy<exec_space>(0, columnIndices.extent(0)),
2524 KOKKOS_LAMBDA(
const LocalOrdinal i,
int& lOutOfBounds) {
2525 if (columnIndices(i) < 0 || columnIndices(i) >= numLocalCols)
2528 columnsOutOfBounds);
2529 int globalColsOutOfBounds = 0;
2530 auto comm = this->getComm();
2531 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, columnsOutOfBounds,
2532 Teuchos::outArg(globalColsOutOfBounds));
2533 if (globalColsOutOfBounds) {
2534 std::string message;
2535 if (columnsOutOfBounds) {
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(
2550 Kokkos::RangePolicy<exec_space>(0, numLocalRows),
2551 KOKKOS_LAMBDA(
const LocalOrdinal i,
int& lNotSorted) {
2552 size_type rowBegin = rowPointers(i);
2553 size_type rowEnd = rowPointers(i + 1);
2554 for (size_type j = rowBegin + 1; j < rowEnd; j++) {
2555 if (columnIndices(j - 1) > columnIndices(j)) {
2562 int globalNotSorted = 0;
2563 auto comm = this->getComm();
2564 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, notSorted,
2565 Teuchos::outArg(globalNotSorted));
2566 if (globalNotSorted) {
2567 std::string message;
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;
2583 setRowPtrs(rowPointers);
2585 set_need_sync_host_uvm_access();
2589 storageStatus_ = Details::STORAGE_1D_PACKED;
2594 numAllocForAllRows_ = 0;
2595 k_numAllocPerRow_ = decltype(k_numAllocPerRow_)();
2597 checkInternalState();
2600 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2603 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices) {
2605 typedef typename local_graph_device_type::row_map_type row_map_type;
2606 typedef typename row_map_type::array_layout layout_type;
2607 typedef typename row_map_type::non_const_value_type row_offset_type;
2608 typedef View<
size_t*, layout_type, Kokkos::HostSpace,
2609 Kokkos::MemoryUnmanaged>
2611 typedef typename row_map_type::non_const_type nc_row_map_type;
2613 const size_t size =
static_cast<size_t>(rowPointers.size());
2614 constexpr
bool same = std::is_same<size_t, row_offset_type>::value;
2615 input_view_type ptr_in(rowPointers.getRawPtr(), size);
2617 nc_row_map_type ptr_rot(
"Tpetra::CrsGraph::ptr", size);
2619 if constexpr (same) {
2620 using lexecution_space =
typename device_type::execution_space;
2626 constexpr
bool inHostMemory =
2627 std::is_same<
typename row_map_type::memory_space,
2628 Kokkos::HostSpace>::value;
2638 View<size_t*, layout_type, device_type> ptr_st(
"Tpetra::CrsGraph::ptr", size);
2650 Kokkos::View<LocalOrdinal*, layout_type, device_type> k_ind =
2651 Kokkos::Compat::getKokkosViewDeepCopy<device_type>(columnIndices());
2652 setAllIndices(ptr_rot, k_ind);
2655 template <
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;
2670 const char tfecfFuncName[] =
"globalAssemble: ";
2672 std::unique_ptr<std::string> prefix;
2674 prefix = this->createPrefix(
"CrsGraph",
"globalAssemble");
2675 std::ostringstream os;
2676 os << *prefix <<
"Start" << endl;
2677 std::cerr << os.str();
2679 RCP<const Comm<int>> comm = getComm();
2681 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!isFillActive(), std::runtime_error,
2682 "Fill must be active before "
2683 "you may call this method.");
2685 const size_t myNumNonlocalRows = this->nonlocals_.size();
2692 const int iHaveNonlocalRows = (myNumNonlocalRows == 0) ? 0 : 1;
2693 int someoneHasNonlocalRows = 0;
2694 reduceAll<int, int>(*comm, REDUCE_MAX, iHaveNonlocalRows,
2695 outArg(someoneHasNonlocalRows));
2696 if (someoneHasNonlocalRows == 0) {
2698 std::ostringstream os;
2699 os << *prefix <<
"Done: No nonlocal rows" << endl;
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();
2720 RCP<const map_type> nonlocalRowMap;
2722 Teuchos::Array<size_t> numEntPerNonlocalRow(myNumNonlocalRows);
2724 Teuchos::Array<GO> myNonlocalGblRows(myNumNonlocalRows);
2725 size_type curPos = 0;
2726 for (
auto mapIter = this->nonlocals_.begin();
2727 mapIter != this->nonlocals_.end();
2728 ++mapIter, ++curPos) {
2729 myNonlocalGblRows[curPos] = mapIter->first;
2730 std::vector<GO>& gblCols = mapIter->second;
2731 std::sort(gblCols.begin(), gblCols.end());
2732 auto vecLast = std::unique(gblCols.begin(), gblCols.end());
2733 gblCols.erase(vecLast, gblCols.end());
2734 numEntPerNonlocalRow[curPos] = gblCols.size();
2745 GO myMinNonlocalGblRow = std::numeric_limits<GO>::max();
2747 auto iter = std::min_element(myNonlocalGblRows.begin(),
2748 myNonlocalGblRows.end());
2749 if (iter != myNonlocalGblRows.end()) {
2750 myMinNonlocalGblRow = *iter;
2753 GO gblMinNonlocalGblRow = 0;
2754 reduceAll<int, GO>(*comm, REDUCE_MIN, myMinNonlocalGblRow,
2755 outArg(gblMinNonlocalGblRow));
2756 const GO indexBase = gblMinNonlocalGblRow;
2757 const global_size_t INV = Teuchos::OrdinalTraits<global_size_t>::invalid();
2758 nonlocalRowMap = rcp(
new map_type(INV, myNonlocalGblRows(), indexBase, comm));
2762 std::ostringstream os;
2763 os << *prefix <<
"nonlocalRowMap->getIndexBase()="
2764 << nonlocalRowMap->getIndexBase() << endl;
2765 std::cerr << os.str();
2773 RCP<crs_graph_type> nonlocalGraph =
2774 rcp(
new crs_graph_type(nonlocalRowMap, numEntPerNonlocalRow()));
2776 size_type curPos = 0;
2777 for (
auto mapIter = this->nonlocals_.begin();
2778 mapIter != this->nonlocals_.end();
2779 ++mapIter, ++curPos) {
2780 const GO gblRow = mapIter->first;
2781 std::vector<GO>& gblCols = mapIter->second;
2782 const LO numEnt =
static_cast<LO
>(numEntPerNonlocalRow[curPos]);
2783 nonlocalGraph->insertGlobalIndices(gblRow, numEnt, gblCols.data());
2787 std::ostringstream os;
2788 os << *prefix <<
"Built nonlocal graph" << endl;
2789 std::cerr << os.str();
2800 auto origRowMap = this->getRowMap();
2801 const bool origRowMapIsOneToOne = origRowMap->isOneToOne();
2803 if (origRowMapIsOneToOne) {
2805 std::ostringstream os;
2806 os << *prefix <<
"Original row Map is 1-to-1" << endl;
2807 std::cerr << os.str();
2809 export_type exportToOrig(nonlocalRowMap, origRowMap);
2814 std::ostringstream os;
2815 os << *prefix <<
"Original row Map is NOT 1-to-1" << endl;
2816 std::cerr << os.str();
2823 export_type exportToOneToOne(nonlocalRowMap, oneToOneRowMap);
2829 crs_graph_type oneToOneGraph(oneToOneRowMap, 0);
2833 std::ostringstream os;
2834 os << *prefix <<
"Export nonlocal graph" << endl;
2835 std::cerr << os.str();
2837 oneToOneGraph.doExport(*nonlocalGraph, exportToOneToOne,
Tpetra::INSERT);
2841 nonlocalGraph = Teuchos::null;
2844 import_type importToOrig(oneToOneRowMap, origRowMap);
2846 std::ostringstream os;
2847 os << *prefix <<
"Import nonlocal graph" << endl;
2848 std::cerr << os.str();
2857 decltype(this->nonlocals_) newNonlocals;
2858 std::swap(this->nonlocals_, newNonlocals);
2860 checkInternalState();
2862 std::ostringstream os;
2863 os << *prefix <<
"Done" << endl;
2864 std::cerr << os.str();
2868 template <
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;
2879 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2892 Teuchos::RCP<const map_type> domMap = this->getDomainMap();
2893 if (domMap.is_null()) {
2894 domMap = this->getRowMap();
2896 Teuchos::RCP<const map_type> ranMap = this->getRangeMap();
2897 if (ranMap.is_null()) {
2898 ranMap = this->getRowMap();
2900 this->fillComplete(domMap, ranMap, params);
2903 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2906 const Teuchos::RCP<const map_type>& rangeMap,
2907 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2909 const char tfecfFuncName[] =
"fillComplete: ";
2910 const bool verbose = verbose_;
2912 std::unique_ptr<std::string> prefix;
2914 prefix = this->createPrefix(
"CrsGraph",
"fillComplete");
2915 std::ostringstream os;
2916 os << *prefix <<
"Start" << endl;
2917 std::cerr << os.str();
2920 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!isFillActive() || isFillComplete(), std::runtime_error,
2921 "Graph fill state must be active (isFillActive() "
2922 "must be true) before calling fillComplete().");
2924 const int numProcs = getComm()->getSize();
2932 if (!params.is_null()) {
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_);
2946 bool assertNoNonlocalInserts =
false;
2947 if (!params.is_null()) {
2948 assertNoNonlocalInserts =
2949 params->get<
bool>(
"No Nonlocal Changes", assertNoNonlocalInserts);
2955 if (!indicesAreAllocated()) {
2958 allocateIndices(LocalIndices, verbose);
2961 allocateIndices(GlobalIndices, verbose);
2969 const bool mayNeedGlobalAssemble = !assertNoNonlocalInserts && numProcs > 1;
2970 if (mayNeedGlobalAssemble) {
2975 const size_t numNonlocals = nonlocals_.size();
2977 std::ostringstream os;
2978 os << *prefix <<
"Do not need to call globalAssemble; "
2979 "assertNoNonlocalInserts="
2980 << (assertNoNonlocalInserts ?
"true" :
"false")
2981 <<
"numProcs=" << numProcs
2982 <<
", nonlocals_.size()=" << numNonlocals << endl;
2983 std::cerr << os.str();
2985 const int lclNeededGlobalAssemble =
2986 (numProcs > 1 && numNonlocals != 0) ? 1 : 0;
2987 if (lclNeededGlobalAssemble != 0 && verbose) {
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();
2999 int gblNeededGlobalAssemble = lclNeededGlobalAssemble;
3000 if (!comm.is_null()) {
3001 using Teuchos::REDUCE_MAX;
3002 using Teuchos::reduceAll;
3003 reduceAll(*comm, REDUCE_MAX, lclNeededGlobalAssemble,
3004 Teuchos::outArg(gblNeededGlobalAssemble));
3006 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(gblNeededGlobalAssemble != 0, std::runtime_error,
3007 "nonlocals_.size()=" << numNonlocals <<
" != 0 on at "
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).");
3016 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lclNeededGlobalAssemble != 0, std::runtime_error,
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 "
3030 setDomainRangeMaps(domainMap, rangeMap);
3036 Teuchos::Array<int> remotePIDs(0);
3037 const bool mustBuildColMap = !this->hasColMap();
3038 if (mustBuildColMap) {
3044 const std::pair<size_t, std::string> makeIndicesLocalResult =
3045 this->makeIndicesLocal(verbose);
3049 using Teuchos::outArg;
3051 using Teuchos::REDUCE_MIN;
3052 using Teuchos::reduceAll;
3054 RCP<const map_type> map = this->getMap();
3055 RCP<const Teuchos::Comm<int>> comm;
3056 if (!map.is_null()) {
3057 comm = map->getComm();
3059 if (comm.is_null()) {
3060 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(makeIndicesLocalResult.first != 0, std::runtime_error,
3061 makeIndicesLocalResult.second);
3063 const int lclSuccess = (makeIndicesLocalResult.first == 0);
3065 reduceAll(*comm, REDUCE_MIN, lclSuccess, outArg(gblSuccess));
3066 if (gblSuccess != 1) {
3067 std::ostringstream os;
3068 gathervPrint(os, makeIndicesLocalResult.second, *comm);
3069 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
3077 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(makeIndicesLocalResult.first != 0, std::runtime_error,
3078 makeIndicesLocalResult.second);
3084 this->sortAndMergeAllIndices(this->isSorted(), this->isMerged());
3089 this->makeImportExport(remotePIDs, mustBuildColMap);
3092 this->fillLocalGraph(params);
3094 const bool callComputeGlobalConstants = params.get() ==
nullptr ||
3095 params->get(
"compute global constants",
true);
3096 if (callComputeGlobalConstants) {
3097 this->computeGlobalConstants();
3099 this->computeLocalConstants();
3101 this->fillComplete_ =
true;
3102 this->checkInternalState();
3105 std::ostringstream os;
3106 os << *prefix <<
"Done" << endl;
3107 std::cerr << os.str();
3111 template <
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) {
3118 const char tfecfFuncName[] =
"expertStaticFillComplete: ";
3119 #ifdef HAVE_TPETRA_MMM_TIMINGS
3121 if (!params.is_null())
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"))));
3128 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3129 domainMap.is_null() || rangeMap.is_null(),
3130 std::runtime_error,
"The input domain Map and range Map must be nonnull.");
3131 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3132 isFillComplete() || !hasColMap(), std::runtime_error,
3134 "call this method unless the graph has a column Map.");
3135 auto rowPtrsUnpackedLength = this->getRowPtrsUnpackedDevice().extent(0);
3136 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3137 getLocalNumRows() > 0 && rowPtrsUnpackedLength == 0,
3138 std::runtime_error,
"The calling process has getLocalNumRows() = " << getLocalNumRows() <<
" > 0 rows, but the row offsets array has not "
3140 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3141 static_cast<size_t>(rowPtrsUnpackedLength) != getLocalNumRows() + 1,
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"))));
3172 setDomainRangeMaps(domainMap, rangeMap);
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;
3186 if (importer != Teuchos::null) {
3187 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3188 !importer->getSourceMap()->isSameAs(*getDomainMap()) ||
3189 !importer->getTargetMap()->isSameAs(*getColMap()),
3190 std::invalid_argument,
": importer does not match matrix maps.");
3191 importer_ = importer;
3194 #ifdef HAVE_TPETRA_MMM_TIMINGS
3196 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckE"))));
3199 if (exporter != Teuchos::null) {
3200 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3201 !exporter->getSourceMap()->isSameAs(*getRowMap()) ||
3202 !exporter->getTargetMap()->isSameAs(*getRangeMap()),
3203 std::invalid_argument,
": exporter does not match matrix maps.");
3204 exporter_ = exporter;
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);
3220 const bool callComputeGlobalConstants = params.get() ==
nullptr ||
3221 params->get(
"compute global constants",
true);
3223 if (callComputeGlobalConstants) {
3224 #ifdef HAVE_TPETRA_MMM_TIMINGS
3226 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (const)"))));
3227 #endif // HAVE_TPETRA_MMM_TIMINGS
3228 this->computeGlobalConstants();
3230 #ifdef HAVE_TPETRA_MMM_TIMINGS
3232 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (noconst)"))));
3233 #endif // HAVE_TPETRA_MMM_TIMINGS
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();
3246 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3248 fillLocalGraph(
const Teuchos::RCP<Teuchos::ParameterList>& params) {
3250 typedef typename local_graph_device_type::row_map_type row_map_type;
3251 typedef typename row_map_type::non_const_type non_const_row_map_type;
3252 typedef typename local_graph_device_type::entries_type::non_const_type lclinds_1d_type;
3253 const char tfecfFuncName[] =
3254 "fillLocalGraph (called from fillComplete or "
3255 "expertStaticFillComplete): ";
3256 const size_t lclNumRows = this->getLocalNumRows();
3261 bool requestOptimizedStorage =
true;
3262 if (!params.is_null() && !params->get(
"Optimize Storage",
true)) {
3263 requestOptimizedStorage =
false;
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();
3497 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3507 const char tfecfFuncName[] =
"replaceColMap: ";
3508 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3509 isLocallyIndexed() || isGloballyIndexed(), std::runtime_error,
3510 "Requires matching maps and non-static graph.");
3511 colMap_ = newColMap;
3514 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3517 const Teuchos::RCP<const import_type>& newImport,
3518 const bool sortIndicesInEachRow) {
3520 using Teuchos::REDUCE_MIN;
3521 using Teuchos::reduceAll;
3522 typedef GlobalOrdinal GO;
3523 typedef LocalOrdinal LO;
3524 using col_inds_type_dev =
typename local_inds_dualv_type::t_dev;
3525 const char tfecfFuncName[] =
"reindexColumns: ";
3527 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
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());
3564 bool allCurColIndsValid =
true;
3569 bool localSuffices =
true;
3578 col_inds_type_dev newLclInds1D_dev;
3583 if (indicesAreAllocated()) {
3584 if (isLocallyIndexed()) {
3586 const map_type& oldColMap = *(getColMap());
3589 const size_t allocSize = this->getLocalAllocationSize();
3590 auto oldLclInds1D = lclIndsUnpacked_wdv.getDeviceView(Access::ReadOnly);
3591 newLclInds1D_dev = col_inds_type_dev(
"Tpetra::CrsGraph::lclIndsReindexed",
3594 auto newLclColMap = newColMap->getLocalMap();
3596 const auto LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
3597 const auto GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
3599 const int NOT_ALL_LOCAL_INDICES_ARE_VALID = 1;
3600 const int LOCAL_DOES_NOT_SUFFICE = 2;
3601 int errorStatus = 0;
3602 Kokkos::parallel_reduce(
3603 "Tpetra::CrsGraph::reindexColumns",
3604 Kokkos::RangePolicy<LocalOrdinal, execution_space>(0, allocSize),
3605 KOKKOS_LAMBDA(
const LocalOrdinal k,
int& result) {
3606 const LocalOrdinal oldLclCol = oldLclInds1D(k);
3607 if (oldLclCol == LO_INVALID) {
3608 result &= NOT_ALL_LOCAL_INDICES_ARE_VALID;
3610 const GO gblCol = oldLclColMap.getGlobalElement(oldLclCol);
3611 if (gblCol == GO_INVALID) {
3612 result &= LOCAL_DOES_NOT_SUFFICE;
3614 const LocalOrdinal newLclCol = newLclColMap.getLocalElement(gblCol);
3615 if (newLclCol == LO_INVALID) {
3616 result &= NOT_ALL_LOCAL_INDICES_ARE_VALID;
3618 newLclInds1D_dev(k) = newLclCol;
3623 Kokkos::LOr<int>(errorStatus));
3624 allCurColIndsValid = !(errorStatus & NOT_ALL_LOCAL_INDICES_ARE_VALID);
3625 localSuffices = !(errorStatus & LOCAL_DOES_NOT_SUFFICE);
3632 allCurColIndsValid =
false;
3648 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
3649 const RowInfo rowInfo = this->getRowInfo(lclRow);
3650 auto oldGblRowView = this->getGlobalIndsViewHost(rowInfo);
3651 for (
size_t k = 0; k < rowInfo.numEntries; ++k) {
3652 const GO gblCol = oldGblRowView(k);
3653 if (!newColMap->isNodeGlobalElement(gblCol)) {
3654 localSuffices =
false;
3664 lclSuccess[0] = allCurColIndsValid ? 1 : 0;
3665 lclSuccess[1] = localSuffices ? 1 : 0;
3669 RCP<const Teuchos::Comm<int>> comm =
3670 getRowMap().is_null() ? Teuchos::null : getRowMap()->getComm();
3671 if (!comm.is_null()) {
3672 reduceAll<int, int>(*comm, REDUCE_MIN, 2, lclSuccess, gblSuccess);
3675 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3676 gblSuccess[0] == 0, std::runtime_error,
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().");
3682 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3683 gblSuccess[1] == 0, std::runtime_error,
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;
3709 if (sortIndicesInEachRow) {
3716 const bool sorted =
false;
3717 const bool merged =
true;
3718 this->sortAndMergeAllIndices(sorted, merged);
3721 colMap_ = newColMap;
3723 if (newImport.is_null()) {
3731 if (!domainMap_.is_null()) {
3732 if (!domainMap_->isSameAs(*newColMap)) {
3733 importer_ = Teuchos::rcp(
new import_type(domainMap_, newColMap));
3735 importer_ = Teuchos::null;
3740 importer_ = newImport;
3744 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3747 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMap: ";
3748 TEUCHOS_TEST_FOR_EXCEPTION(
3749 colMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3750 "this method unless the graph already has a column Map.");
3751 TEUCHOS_TEST_FOR_EXCEPTION(
3752 newDomainMap.is_null(), std::invalid_argument,
3753 prefix <<
"The new domain Map must be nonnull.");
3756 Teuchos::RCP<const import_type> newImporter = Teuchos::null;
3757 if (newDomainMap != colMap_ && (!newDomainMap->isSameAs(*colMap_))) {
3758 newImporter = rcp(
new import_type(newDomainMap, colMap_));
3760 this->replaceDomainMapAndImporter(newDomainMap, newImporter);
3763 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3766 const Teuchos::RCP<const import_type>& newImporter) {
3767 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMapAndImporter: ";
3768 TEUCHOS_TEST_FOR_EXCEPTION(
3769 colMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3770 "this method unless the graph already has a column Map.");
3771 TEUCHOS_TEST_FOR_EXCEPTION(
3772 newDomainMap.is_null(), std::invalid_argument,
3773 prefix <<
"The new domain Map must be nonnull.");
3776 if (newImporter.is_null()) {
3781 const bool colSameAsDom = colMap_->isSameAs(*newDomainMap);
3782 TEUCHOS_TEST_FOR_EXCEPTION(!colSameAsDom, std::invalid_argument,
3783 "If the new Import is null, "
3784 "then the new domain Map must be the same as the current column Map.");
3786 const bool colSameAsTgt =
3787 colMap_->isSameAs(*(newImporter->getTargetMap()));
3788 const bool newDomSameAsSrc =
3789 newDomainMap->isSameAs(*(newImporter->getSourceMap()));
3790 TEUCHOS_TEST_FOR_EXCEPTION(!colSameAsTgt || !newDomSameAsSrc, std::invalid_argument,
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.");
3798 domainMap_ = newDomainMap;
3799 importer_ = Teuchos::rcp_const_cast<
import_type>(newImporter);
3802 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3805 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMap: ";
3806 TEUCHOS_TEST_FOR_EXCEPTION(
3807 rowMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3808 "this method unless the graph already has a row Map.");
3809 TEUCHOS_TEST_FOR_EXCEPTION(
3810 newRangeMap.is_null(), std::invalid_argument,
3811 prefix <<
"The new range Map must be nonnull.");
3814 Teuchos::RCP<const export_type> newExporter = Teuchos::null;
3815 if (newRangeMap != rowMap_ && (!newRangeMap->isSameAs(*rowMap_))) {
3816 newExporter = rcp(
new export_type(rowMap_, newRangeMap));
3818 this->replaceRangeMapAndExporter(newRangeMap, newExporter);
3821 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3824 const Teuchos::RCP<const export_type>& newExporter) {
3825 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMapAndExporter: ";
3826 TEUCHOS_TEST_FOR_EXCEPTION(
3827 rowMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3828 "this method unless the graph already has a column Map.");
3829 TEUCHOS_TEST_FOR_EXCEPTION(
3830 newRangeMap.is_null(), std::invalid_argument,
3831 prefix <<
"The new domain Map must be nonnull.");
3834 if (newExporter.is_null()) {
3839 const bool rowSameAsRange = rowMap_->isSameAs(*newRangeMap);
3840 TEUCHOS_TEST_FOR_EXCEPTION(!rowSameAsRange, std::invalid_argument,
3841 "If the new Export is null, "
3842 "then the new range Map must be the same as the current row Map.");
3844 const bool newRangeSameAsTgt =
3845 newRangeMap->isSameAs(*(newExporter->getTargetMap()));
3846 const bool rowSameAsSrc =
3847 rowMap_->isSameAs(*(newExporter->getSourceMap()));
3848 TEUCHOS_TEST_FOR_EXCEPTION(!rowSameAsSrc || !newRangeSameAsTgt, std::invalid_argument,
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.");
3856 rangeMap_ = newRangeMap;
3857 exporter_ = Teuchos::rcp_const_cast<
export_type>(newExporter);
3860 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3865 lclIndsPacked_wdv.getDeviceView(Access::ReadWrite),
3866 this->getRowPtrsPackedDevice());
3869 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3873 return local_graph_host_type(
3874 lclIndsPacked_wdv.getHostView(Access::ReadWrite),
3875 this->getRowPtrsPackedHost());
3878 template <
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());
3911 reduceAll<int, GST>(comm, Teuchos::REDUCE_SUM, 1, &lcl, &gbl);
3912 this->globalNumEntries_ = gbl;
3914 const GST lclMaxNumRowEnt =
static_cast<GST
>(this->nodeMaxNumRowEntries_);
3915 reduceAll<int, GST>(comm, Teuchos::REDUCE_MAX, lclMaxNumRowEnt,
3916 outArg(this->globalMaxNumRowEntries_));
3917 this->haveGlobalConstants_ =
true;
3921 template <
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));
3940 const LO lclMaxNumRowEnt =
3941 ::Tpetra::Details::maxDifference(
"Tpetra::CrsGraph: nodeMaxNumRowEntries",
3943 this->nodeMaxNumRowEntries_ =
static_cast<size_t>(lclMaxNumRowEnt);
3944 this->haveLocalConstants_ =
true;
3947 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3948 std::pair<size_t, std::string>
3953 using Teuchos::arcp;
3954 using Teuchos::Array;
3955 typedef LocalOrdinal LO;
3956 typedef GlobalOrdinal GO;
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;
3960 const char tfecfFuncName[] =
"makeIndicesLocal: ";
3961 ProfilingRegion regionMakeIndicesLocal(
"Tpetra::CrsGraph::makeIndicesLocal");
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();
3973 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->hasColMap(), std::logic_error,
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.");
3977 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->getColMap().is_null(), std::logic_error,
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.");
3986 size_t lclNumErrs = 0;
3987 std::ostringstream errStrm;
3989 const LO lclNumRows =
static_cast<LO
>(this->getLocalNumRows());
3990 const map_type& colMap = *(this->getColMap());
3992 if (this->isGloballyIndexed() && lclNumRows != 0) {
3994 typename num_row_entries_type::const_type h_numRowEnt =
3995 this->k_numRowEntries_;
3997 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
4000 if (rowPtrsUnpacked_host.extent(0) == 0) {
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(),
4008 const auto numEnt = rowPtrsUnpacked_host(lclNumRows);
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();
4036 local_inds_dualv_type lclInds_dualv =
4037 local_inds_dualv_type(view_alloc(label, WithoutInitializing),
4050 std::ostringstream os;
4051 os << *prefix <<
"Allocate device mirror k_numRowEnt: "
4052 << h_numRowEnt.extent(0) << endl;
4053 std::cerr << os.str();
4056 Kokkos::create_mirror_view_and_copy(
device_type(), h_numRowEnt);
4060 convertColumnIndicesFromGlobalToLocal<LO, GO, DT, offset_type, num_ent_type>(
4061 lclIndsUnpacked_wdv.getDeviceView(Access::OverwriteAll),
4062 gblInds_wdv.getDeviceView(Access::ReadOnly),
4063 this->getRowPtrsUnpackedDevice(),
4066 if (lclNumErrs != 0) {
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();
4076 const bool pluralNumErrs = (lclNumErrs !=
static_cast<size_t>(1));
4077 errStrm <<
"(Process " << myRank <<
") When converting column "
4078 "indices from global to local, we encountered "
4080 <<
" ind" << (pluralNumErrs ?
"ices" :
"ex")
4081 <<
" that do" << (pluralNumErrs ?
"es" :
"")
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();
4101 return std::make_pair(lclNumErrs, errStrm.str());
4104 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4109 const char tfecfFuncName[] =
"makeColMap";
4111 ProfilingRegion regionSortAndMerge(
"Tpetra::CrsGraph::makeColMap");
4112 std::unique_ptr<std::string> prefix;
4114 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4115 std::ostringstream os;
4116 os << *prefix <<
"Start" << endl;
4117 std::cerr << os.str();
4125 Teuchos::RCP<const map_type> colMap = this->colMap_;
4126 const bool sortEachProcsGids =
4127 this->sortGhostsAssociatedWithEachProcessor_;
4137 using Teuchos::outArg;
4138 using Teuchos::REDUCE_MIN;
4139 using Teuchos::reduceAll;
4141 std::ostringstream errStrm;
4142 const int lclErrCode =
4144 getDomainMap(), *
this, sortEachProcsGids, &errStrm);
4145 auto comm = this->getComm();
4146 if (!comm.is_null()) {
4147 const int lclSuccess = (lclErrCode == 0) ? 1 : 0;
4149 reduceAll<int, int>(*comm, REDUCE_MIN, lclSuccess,
4150 outArg(gblSuccess));
4151 if (gblSuccess != 1) {
4152 std::ostringstream os;
4154 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
4155 ": An error happened on at "
4156 "least one process in the CrsGraph's communicator. "
4157 "Here are all processes' error messages:"
4164 getDomainMap(), *
this, sortEachProcsGids,
nullptr);
4169 this->colMap_ = colMap;
4171 checkInternalState();
4173 std::ostringstream os;
4174 os << *prefix <<
"Done" << endl;
4175 std::cerr << os.str();
4179 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4183 using LO = LocalOrdinal;
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>;
4188 const char tfecfFuncName[] =
"sortAndMergeAllIndices";
4191 std::unique_ptr<std::string> prefix;
4193 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4194 std::ostringstream os;
4195 os << *prefix <<
"Start: "
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();
4251 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4254 const bool useRemotePIDs) {
4255 using Teuchos::ParameterList;
4258 using ::Tpetra::Details::ProfilingRegion;
4259 const char tfecfFuncName[] =
"makeImportExport: ";
4260 ProfilingRegion regionMIE(
"Tpetra::CrsGraph::makeImportExport");
4262 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->hasColMap(), std::logic_error,
4263 "This method may not be called unless the graph has a column Map.");
4264 RCP<ParameterList> params = this->getNonconstParameterList();
4273 if (importer_.is_null()) {
4275 if (domainMap_ != colMap_ && (!domainMap_->isSameAs(*colMap_))) {
4276 if (params.is_null() || !params->isSublist(
"Import")) {
4277 if (useRemotePIDs) {
4278 importer_ = rcp(
new import_type(domainMap_, colMap_, remotePIDs));
4280 importer_ = rcp(
new import_type(domainMap_, colMap_));
4283 RCP<ParameterList> importSublist = sublist(params,
"Import",
true);
4284 if (useRemotePIDs) {
4285 RCP<import_type> newImp =
4286 rcp(
new import_type(domainMap_, colMap_, remotePIDs,
4290 importer_ = rcp(
new import_type(domainMap_, colMap_, importSublist));
4298 if (exporter_.is_null()) {
4300 if (rangeMap_ != rowMap_ && !rangeMap_->isSameAs(*rowMap_)) {
4301 if (params.is_null() || !params->isSublist(
"Export")) {
4302 exporter_ = rcp(
new export_type(rowMap_, rangeMap_));
4304 RCP<ParameterList> exportSublist = sublist(params,
"Export",
true);
4305 exporter_ = rcp(
new export_type(rowMap_, rangeMap_, exportSublist));
4311 template <
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()
4331 template <
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;
4347 Teuchos::EVerbosityLevel vl = verbLevel;
4348 if (vl == VERB_DEFAULT) vl = VERB_LOW;
4349 RCP<const Comm<int>> comm = this->getComm();
4350 const int myImageID = comm->getRank(),
4351 numImages = comm->getSize();
4353 for (
size_t dec = 10; dec < getGlobalNumRows(); dec *= 10) {
4356 width = std::max<size_t>(width,
static_cast<size_t>(11)) + 2;
4357 Teuchos::OSTab tab(out);
4365 if (vl != VERB_NONE) {
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;
4372 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4373 if (myImageID == 0) out <<
"\nRow map: " << 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);
4389 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4390 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4391 if (myImageID == imageCtr) {
4392 out <<
"Node ID = " << imageCtr << std::endl
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;
4405 if (vl == VERB_HIGH || vl == VERB_EXTREME) {
4406 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4407 if (myImageID == imageCtr) {
4408 out << std::setw(width) <<
"Node ID"
4409 << std::setw(width) <<
"Global Row"
4410 << std::setw(width) <<
"Num Entries";
4411 if (vl == VERB_EXTREME) {
4415 const LocalOrdinal lclNumRows =
4416 static_cast<LocalOrdinal
>(this->getLocalNumRows());
4417 for (LocalOrdinal r = 0; r < lclNumRows; ++r) {
4418 const RowInfo rowinfo = this->getRowInfo(r);
4419 GlobalOrdinal gid = rowMap_->getGlobalElement(r);
4420 out << std::setw(width) << myImageID
4421 << std::setw(width) << gid
4422 << std::setw(width) << rowinfo.numEntries;
4423 if (vl == VERB_EXTREME) {
4425 if (isGloballyIndexed()) {
4426 auto rowview = gblInds_wdv.getHostView(Access::ReadOnly);
4427 for (
size_t j = 0; j < rowinfo.numEntries; ++j) {
4428 GlobalOrdinal colgid = rowview[j + rowinfo.offset1D];
4429 out << colgid <<
" ";
4431 }
else if (isLocallyIndexed()) {
4432 auto rowview = lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
4433 for (
size_t j = 0; j < rowinfo.numEntries; ++j) {
4434 LocalOrdinal collid = rowview[j + rowinfo.offset1D];
4435 out << colMap_->getGlobalElement(collid) <<
" ";
4450 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4459 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4462 const size_t numSameIDs,
4472 const char tfecfFuncName[] =
"copyAndPermute: ";
4473 const bool verbose = verbose_;
4475 std::unique_ptr<std::string> prefix;
4477 prefix = this->createPrefix(
"CrsGraph",
"copyAndPermute");
4478 std::ostringstream os;
4479 os << *prefix << endl;
4480 std::cerr << os.str();
4483 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(permuteToLIDs.extent(0) != permuteFromLIDs.extent(0),
4484 std::runtime_error,
"permuteToLIDs.extent(0) = " << permuteToLIDs.extent(0) <<
" != permuteFromLIDs.extent(0) = " << permuteFromLIDs.extent(0) <<
".");
4492 std::ostringstream os;
4493 os << *prefix <<
"Compute padding" << endl;
4494 std::cerr << os.str();
4496 auto padding = computeCrsPadding(srcRowGraph, numSameIDs,
4497 permuteToLIDs, permuteFromLIDs, verbose);
4498 applyCrsPadding(*padding, verbose);
4503 const this_CRS_type* srcCrsGraph =
4504 dynamic_cast<const this_CRS_type*
>(&source);
4506 const map_type& srcRowMap = *(srcRowGraph.getRowMap());
4507 const map_type& tgtRowMap = *(getRowMap());
4508 const bool src_filled = srcRowGraph.isFillComplete();
4509 nonconst_global_inds_host_view_type row_copy;
4515 if (src_filled || srcCrsGraph ==
nullptr) {
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) {
4528 size_t row_length = srcRowGraph.getNumEntriesInGlobalRow(gid);
4529 Kokkos::resize(row_copy, row_length);
4530 size_t check_row_length = 0;
4531 srcRowGraph.getGlobalRowCopy(gid, row_copy, check_row_length);
4532 this->insertGlobalIndices(gid, row_length, row_copy.data());
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;
4543 srcCrsGraph->getGlobalRowView(gid, row);
4544 this->insertGlobalIndices(gid, row.extent(0), row.data());
4551 auto permuteToLIDs_h = permuteToLIDs.view_host();
4552 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
4554 if (src_filled || srcCrsGraph ==
nullptr) {
4555 for (LO i = 0; i < static_cast<LO>(permuteToLIDs_h.extent(0)); ++i) {
4558 size_t row_length = srcRowGraph.getNumEntriesInGlobalRow(srcgid);
4559 Kokkos::resize(row_copy, row_length);
4560 size_t check_row_length = 0;
4561 srcRowGraph.getGlobalRowCopy(srcgid, row_copy, check_row_length);
4562 this->insertGlobalIndices(mygid, row_length, row_copy.data());
4565 for (LO i = 0; i < static_cast<LO>(permuteToLIDs_h.extent(0)); ++i) {
4568 global_inds_host_view_type row;
4569 srcCrsGraph->getGlobalRowView(srcgid, row);
4570 this->insertGlobalIndices(mygid, row.extent(0), row.data());
4575 std::ostringstream os;
4576 os << *prefix <<
"Done" << endl;
4577 std::cerr << os.str();
4581 template <
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;
4591 using range_policy =
4592 Kokkos::RangePolicy<execution_space, Kokkos::IndexType<LO>>;
4593 const char tfecfFuncName[] =
"applyCrsPadding";
4594 ProfilingRegion regionCAP(
"Tpetra::CrsGraph::applyCrsPadding");
4596 std::unique_ptr<std::string> prefix;
4598 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4599 std::ostringstream os;
4600 os << *prefix <<
"padding: ";
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));
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);
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);
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);
4715 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4717 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
4718 CrsGraph<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,
4756 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4757 void 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();
4813 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4814 void 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();
4886 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4888 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
4889 CrsGraph<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();
4977 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4979 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
4980 CrsGraph<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 =
5061 TEUCHOS_ASSERT(numBytes >= numEntLen);
5062 TEUCHOS_ASSERT(imports_h.extent(0) >= numEntBeg + numEntLen);
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();
5112 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5113 void 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();
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();
5231 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5233 pack(
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5234 Teuchos::Array<GlobalOrdinal>& exports,
5235 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5236 size_t& constantNumPackets)
const {
5237 auto col_map = this->getColMap();
5239 if (!col_map.is_null() && (this->getRowPtrsPackedDevice().extent(0) != 0 || getRowMap()->getLocalNumElements() == 0)) {
5241 packCrsGraph<LocalOrdinal, GlobalOrdinal, Node>(*
this, exports, numPacketsPerLID,
5242 exportLIDs, constantNumPackets);
5244 this->packFillActive(exportLIDs, exports, numPacketsPerLID,
5245 constantNumPackets);
5249 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5251 packFillActive(
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5252 Teuchos::Array<GlobalOrdinal>& exports,
5253 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5254 size_t& constantNumPackets)
const {
5256 using LO = LocalOrdinal;
5257 using GO = GlobalOrdinal;
5258 using host_execution_space =
5259 typename Kokkos::View<size_t*, device_type>::
5260 host_mirror_type::execution_space;
5261 const char tfecfFuncName[] =
"packFillActive: ";
5262 const bool verbose = verbose_;
5264 const auto numExportLIDs = exportLIDs.size();
5265 std::unique_ptr<std::string> prefix;
5267 prefix = this->createPrefix(
"CrsGraph",
"allocateIndices");
5268 std::ostringstream os;
5269 os << *prefix <<
"numExportLIDs=" << numExportLIDs << endl;
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();
5431 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5432 void 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();
5658 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5662 Kokkos::DualView<packet_type*,
5665 Kokkos::DualView<
size_t*,
5674 const char tfecfFuncName[] =
"unpackAndCombine";
5676 ProfilingRegion regionCGC(
"Tpetra::CrsGraph::unpackAndCombine");
5677 const bool verbose = verbose_;
5679 std::unique_ptr<std::string> prefix;
5681 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
5682 std::ostringstream os;
5683 os << *prefix <<
"Start" << endl;
5684 std::cerr << os.str();
5687 auto padding = computeCrsPaddingForImports(
5688 importLIDs, imports, numPacketsPerLID, verbose);
5689 applyCrsPadding(*padding, verbose);
5691 std::ostringstream os;
5692 os << *prefix <<
"Done computing & applying padding" << endl;
5693 std::cerr << os.str();
5714 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(importLIDs.extent(0) != numPacketsPerLID.extent(0),
5715 std::runtime_error,
": importLIDs.extent(0) = " << importLIDs.extent(0) <<
" != numPacketsPerLID.extent(0) = " << numPacketsPerLID.extent(0) <<
".");
5716 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isFillComplete(), std::runtime_error,
5717 ": Import or Export operations are not allowed on a target "
5718 "CrsGraph that is fillComplete.");
5720 const size_t numImportLIDs(importLIDs.extent(0));
5721 if (numPacketsPerLID.need_sync_host()) {
5722 numPacketsPerLID.sync_host();
5724 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5725 if (imports.need_sync_host()) {
5726 imports.sync_host();
5728 auto imports_h = imports.view_host();
5729 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
5730 auto importLIDs_h = importLIDs.view_host();
5733 Teuchos::Array<LO> lclColInds;
5734 if (isLocallyIndexed()) {
5736 std::ostringstream os;
5737 os << *prefix <<
"Preallocate local indices scratch" << endl;
5738 std::cerr << os.str();
5740 size_t maxNumInserts = 0;
5741 for (
size_t i = 0; i < numImportLIDs; ++i) {
5742 maxNumInserts = std::max(maxNumInserts, numPacketsPerLID_h[i]);
5745 std::ostringstream os;
5746 os << *prefix <<
"Local indices scratch size: "
5747 << maxNumInserts << endl;
5748 std::cerr << os.str();
5750 lclColInds.resize(maxNumInserts);
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();
5765 TEUCHOS_ASSERT(!rowMap_.is_null());
5769 size_t importsOffset = 0;
5770 for (
size_t i = 0; i < numImportLIDs; ++i) {
5772 std::ostringstream os;
5773 os << *prefix <<
"i=" << i <<
", numImportLIDs="
5774 << numImportLIDs << endl;
5775 std::cerr << os.str();
5779 const LO lclRow = importLIDs_h[i];
5781 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(gblRow == Teuchos::OrdinalTraits<GO>::invalid(),
5782 std::logic_error,
"importLIDs[i=" << i <<
"]=" << lclRow <<
" is not in the row Map on the calling "
5784 const LO numEnt = numPacketsPerLID_h[i];
5785 const GO*
const gblColInds = (numEnt == 0) ?
nullptr : imports_h.data() + importsOffset;
5786 if (!isLocallyIndexed()) {
5787 insertGlobalIndicesFiltered(lclRow, gblColInds, numEnt);
5791 for (LO j = 0; j < numEnt; j++) {
5792 lclColInds[j] = colMap_->getLocalElement(gblColInds[j]);
5794 insertLocalIndices(lclRow, numEnt, lclColInds.data());
5796 importsOffset += numEnt;
5798 }
catch (std::exception& e) {
5799 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
5800 "Tpetra::CrsGraph::unpackAndCombine: Insert loop threw an "
5807 std::ostringstream os;
5808 os << *prefix <<
"Done" << endl;
5809 std::cerr << os.str();
5813 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5816 using Teuchos::Comm;
5817 using Teuchos::null;
5818 using Teuchos::ParameterList;
5824 RCP<const map_type> rowMap, domainMap, rangeMap, colMap;
5825 RCP<import_type> importer;
5826 RCP<export_type> exporter;
5829 RCP<const Comm<int>> newComm =
5830 (newMap.is_null()) ? null : newMap->getComm();
5832 if (!domainMap_.is_null()) {
5833 if (domainMap_.getRawPtr() == rowMap_.getRawPtr()) {
5840 domainMap = domainMap_->replaceCommWithSubset(newComm);
5843 if (!rangeMap_.is_null()) {
5844 if (rangeMap_.getRawPtr() == rowMap_.getRawPtr()) {
5851 rangeMap = rangeMap_->replaceCommWithSubset(newComm);
5854 if (!colMap_.is_null()) {
5855 colMap = colMap_->replaceCommWithSubset(newComm);
5859 if (!newComm.is_null()) {
5860 RCP<ParameterList> params = this->getNonconstParameterList();
5868 if (!rangeMap_.is_null() &&
5869 rangeMap != rowMap &&
5870 !rangeMap->isSameAs(*rowMap)) {
5871 if (params.is_null() || !params->isSublist(
"Export")) {
5872 exporter = rcp(
new export_type(rowMap, rangeMap));
5874 RCP<ParameterList> exportSublist = sublist(params,
"Export",
true);
5875 exporter = rcp(
new export_type(rowMap, rangeMap, exportSublist));
5879 if (!domainMap_.is_null() &&
5880 domainMap != colMap &&
5881 !domainMap->isSameAs(*colMap)) {
5882 if (params.is_null() || !params->isSublist(
"Import")) {
5883 importer = rcp(
new import_type(domainMap, colMap));
5885 RCP<ParameterList> importSublist = sublist(params,
"Import",
true);
5886 importer = rcp(
new import_type(domainMap, colMap, importSublist));
5894 exporter_ = exporter;
5895 importer_ = importer;
5902 this->map_ = rowMap;
5903 domainMap_ = domainMap;
5904 rangeMap_ = rangeMap;
5908 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5912 using LO = LocalOrdinal;
5913 using GO = GlobalOrdinal;
5914 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
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();
5926 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!hasColMap(), std::runtime_error,
"The graph must have a column Map.");
5927 const LO lclNumRows =
static_cast<LO
>(this->getLocalNumRows());
5928 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(static_cast<LO>(offsets.extent(0)) < lclNumRows,
5929 std::invalid_argument,
"offsets.extent(0) = " << offsets.extent(0) <<
" < getLocalNumRows() = " << lclNumRows <<
".");
5931 const map_type& rowMap = *(this->getRowMap());
5932 const map_type& colMap = *(this->getColMap());
5938 bool allRowMapDiagEntriesInColMap =
true;
5939 bool allDiagEntriesFound =
true;
5940 bool allOffsetsCorrect =
true;
5941 bool noOtherWeirdness =
true;
5942 using wrong_offsets_type = std::vector<std::pair<LO, size_t>>;
5943 wrong_offsets_type wrongOffsets(0);
5947 auto lclRowMap = rowMap.getLocalMap();
5954 const bool sorted = this->isSorted();
5955 if (isFillComplete()) {
5956 auto lclGraph = this->getLocalGraphDevice();
5957 ::Tpetra::Details::getGraphDiagOffsets(offsets, lclRowMap, lclColMap,
5959 lclGraph.entries, sorted);
5964 auto offsets_h = Kokkos::create_mirror_view(offsets);
5966 for (LO lclRowInd = 0; lclRowInd < lclNumRows; ++lclRowInd) {
5970 const GO gblRowInd = lclRowMap.getGlobalElement(lclRowInd);
5971 const GO gblColInd = gblRowInd;
5972 const LO lclColInd = lclColMap.getLocalElement(gblColInd);
5974 if (lclColInd == Tpetra::Details::OrdinalTraits<LO>::invalid()) {
5975 allRowMapDiagEntriesInColMap =
false;
5976 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid();
5978 const RowInfo rowInfo = this->getRowInfo(lclRowInd);
5979 if (static_cast<LO>(rowInfo.localRow) == lclRowInd &&
5980 rowInfo.numEntries > 0) {
5981 auto colInds = this->getLocalIndsViewHost(rowInfo);
5982 const size_t hint = 0;
5983 const size_t offset =
5984 KokkosSparse::findRelOffset(colInds, rowInfo.numEntries,
5985 lclColInd, hint, sorted);
5986 offsets_h(lclRowInd) = offset;
5993 typename local_inds_dualv_type::t_host::const_type lclColInds;
5995 lclColInds = this->getLocalIndsViewHost(rowInfo);
5997 noOtherWeirdness =
false;
6000 if (noOtherWeirdness) {
6001 const size_t numEnt = lclColInds.extent(0);
6002 if (offset >= numEnt) {
6005 allOffsetsCorrect =
false;
6006 wrongOffsets.push_back(std::make_pair(lclRowInd, offset));
6008 const LO actualLclColInd = lclColInds(offset);
6009 const GO actualGblColInd = lclColMap.getGlobalElement(actualLclColInd);
6010 if (actualGblColInd != gblColInd) {
6011 allOffsetsCorrect =
false;
6012 wrongOffsets.push_back(std::make_pair(lclRowInd, offset));
6018 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid();
6019 allDiagEntriesFound =
false;
6027 if (verbose && wrongOffsets.size() != 0) {
6028 std::ostringstream os;
6029 os << *prefix <<
"Wrong offsets: [";
6030 for (
size_t k = 0; k < wrongOffsets.size(); ++k) {
6031 os <<
"(" << wrongOffsets[k].first <<
","
6032 << wrongOffsets[k].second <<
")";
6033 if (k + 1 < wrongOffsets.size()) {
6038 std::cerr << os.str();
6043 using Teuchos::reduceAll;
6044 Teuchos::RCP<const Teuchos::Comm<int>> comm = this->getComm();
6045 const bool localSuccess =
6046 allRowMapDiagEntriesInColMap && allDiagEntriesFound && allOffsetsCorrect;
6047 const int numResults = 5;
6049 lclResults[0] = allRowMapDiagEntriesInColMap ? 1 : 0;
6050 lclResults[1] = allDiagEntriesFound ? 1 : 0;
6051 lclResults[2] = allOffsetsCorrect ? 1 : 0;
6052 lclResults[3] = noOtherWeirdness ? 1 : 0;
6055 lclResults[4] = !localSuccess ? comm->getRank() : comm->getSize();
6063 reduceAll<int, int>(*comm, Teuchos::REDUCE_MIN,
6064 numResults, lclResults, gblResults);
6066 if (gblResults[0] != 1 || gblResults[1] != 1 || gblResults[2] != 1 || gblResults[3] != 1) {
6067 std::ostringstream os;
6068 os <<
"Issue(s) that we noticed (on Process " << gblResults[4] <<
", "
6069 "possibly among others): "
6071 if (gblResults[0] == 0) {
6072 os <<
" - The column Map does not contain at least one diagonal entry "
6076 if (gblResults[1] == 0) {
6077 os <<
" - On one or more processes, some row does not contain a "
6081 if (gblResults[2] == 0) {
6082 os <<
" - On one or more processes, some offsets are incorrect."
6085 if (gblResults[3] == 0) {
6086 os <<
" - One or more processes had some other error."
6089 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
6094 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6098 const char tfecfFuncName[] =
"getLocalOffRankOffsets: ";
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();
6110 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!hasColMap(), std::runtime_error,
"The graph must have a column Map.");
6113 const size_t lclNumRows = this->getLocalNumRows();
6115 if (haveLocalOffRankOffsets_ && k_offRankOffsets_.extent(0) == lclNumRows + 1) {
6116 offsets = k_offRankOffsets_;
6119 haveLocalOffRankOffsets_ =
false;
6121 const map_type& colMap = *(this->getColMap());
6122 const map_type& domMap = *(this->getDomainMap());
6133 TEUCHOS_ASSERT(this->isSorted());
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_,
6138 lclColMap, lclDomMap,
6140 offsets = k_offRankOffsets_;
6141 haveLocalOffRankOffsets_ =
true;
6143 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
"Can't get off-rank offsets for non-fill-complete graph");
6165 template <
class DeviceType,
6166 const bool memSpaceIsHostSpace =
6167 std::is_same<
typename DeviceType::memory_space,
6168 Kokkos::HostSpace>::value>
6169 struct HelpGetLocalDiagOffsets {};
6171 template <
class DeviceType>
6172 struct 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& ) {
6194 template <
class DeviceType>
6195 struct 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) {
6221 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6224 typedef LocalOrdinal LO;
6225 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6226 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->hasColMap(), std::runtime_error,
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) {
6233 offsets.resize(myNumRows);
6245 typedef HelpGetLocalDiagOffsets<device_type> helper_type;
6246 typedef typename helper_type::host_offsets_type host_offsets_type;
6248 host_offsets_type hostOffsets(offsets.getRawPtr(), myNumRows);
6250 auto deviceOffsets = helper_type::getDeviceOffsets(hostOffsets);
6252 this->getLocalDiagOffsets(deviceOffsets);
6253 helper_type::copyBackIfNeeded(hostOffsets, deviceOffsets);
6256 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6262 template <
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;
6285 using LO = LocalOrdinal;
6286 using GO = GlobalOrdinal;
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 ");
6297 RCP<TimeMonitor> MM =
6298 rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"Pack-1"))));
6306 const import_type* xferAsImport =
dynamic_cast<const import_type*
>(&rowTransfer);
6307 const export_type* xferAsExport =
dynamic_cast<const export_type*
>(&rowTransfer);
6308 TEUCHOS_TEST_FOR_EXCEPTION(
6309 xferAsImport ==
nullptr && xferAsExport ==
nullptr, std::invalid_argument,
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.");
6319 Teuchos::RCP<const import_type> xferDomainAsImport =
6320 Teuchos::rcp_dynamic_cast<
const import_type>(domainTransfer);
6321 Teuchos::RCP<const export_type> xferDomainAsExport =
6322 Teuchos::rcp_dynamic_cast<
const export_type>(domainTransfer);
6324 if (!domainTransfer.is_null()) {
6325 TEUCHOS_TEST_FOR_EXCEPTION(
6326 (xferDomainAsImport.is_null() && xferDomainAsExport.is_null()), std::invalid_argument,
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.");
6331 TEUCHOS_TEST_FOR_EXCEPTION(
6332 (xferAsImport !=
nullptr || !xferDomainAsImport.is_null()) &&
6333 ((xferAsImport !=
nullptr && xferDomainAsImport.is_null()) ||
6334 (xferAsImport ==
nullptr && !xferDomainAsImport.is_null())),
6335 std::invalid_argument,
6336 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6337 "must be of the same type (either Import or Export).");
6339 TEUCHOS_TEST_FOR_EXCEPTION(
6340 (xferAsExport !=
nullptr || !xferDomainAsExport.is_null()) &&
6341 ((xferAsExport !=
nullptr && xferDomainAsExport.is_null()) ||
6342 (xferAsExport ==
nullptr && !xferDomainAsExport.is_null())),
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;
6370 RCP<const map_type> MyDomainMap = !domainMap.is_null() ? domainMap : getDomainMap();
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())) {
6582 ivector_type TargetRow_pids(domainMap);
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));
6864 template <
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 {
6871 transferAndFillComplete(destGraph, importer, Teuchos::null, domainMap, rangeMap, params);
6874 template <
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 {
6882 transferAndFillComplete(destGraph, rowImporter, Teuchos::rcpFromRef(domainImporter), domainMap, rangeMap, params);
6885 template <
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 {
6892 transferAndFillComplete(destGraph, exporter, Teuchos::null, domainMap, rangeMap, params);
6895 template <
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 {
6903 transferAndFillComplete(destGraph, rowExporter, Teuchos::rcpFromRef(domainExporter), domainMap, rangeMap, params);
6906 template <
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_);
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_);
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_);
6949 std::swap(graph.haveLocalOffRankOffsets_, this->haveLocalOffRankOffsets_);
6955 std::swap(graph.
nonlocals_, this->nonlocals_);
6958 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6961 auto compare_nonlocals = [&](
const nonlocals_type& m1,
const nonlocals_type& m2) {
6963 output = m1.size() == m2.size() ? output :
false;
6964 for (
auto& it_m : m1) {
6965 size_t key = it_m.first;
6966 output = m2.find(key) != m2.end() ? output :
false;
6968 auto v1 = m1.find(key)->second;
6969 auto v2 = m2.find(key)->second;
6973 output = v1.size() == v2.size() ? output :
false;
6974 for (
size_t i = 0; output && i < v1.size(); i++) {
6975 output = v1[i] == v2[i] ? output :
false;
6984 output = this->rowMap_->isSameAs(*(graph.
rowMap_)) ? output :
false;
6985 output = this->colMap_->isSameAs(*(graph.
colMap_)) ? output :
false;
6986 output = this->rangeMap_->isSameAs(*(graph.
rangeMap_)) ? output :
false;
6987 output = this->domainMap_->isSameAs(*(graph.
domainMap_)) ? output :
false;
6996 output = this->storageStatus_ == graph.
storageStatus_ ? output :
false;
6998 output = this->indicesAreAllocated_ == graph.indicesAreAllocated_ ? output :
false;
6999 output = this->indicesAreLocal_ == graph.indicesAreLocal_ ? output :
false;
7000 output = this->indicesAreGlobal_ == graph.indicesAreGlobal_ ? output :
false;
7001 output = this->fillComplete_ == graph.fillComplete_ ? output :
false;
7003 output = this->noRedundancies_ == graph.
noRedundancies_ ? output :
false;
7006 output = this->haveLocalOffRankOffsets_ == graph.haveLocalOffRankOffsets_ ? output :
false;
7011 output = compare_nonlocals(this->nonlocals_, graph.
nonlocals_) ? 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++)
7018 output = this->k_numAllocPerRow_(i) == graph.
k_numAllocPerRow_(i) ? output :
false;
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++)
7026 output = this->k_numRowEntries_(i) == graph.
k_numRowEntries_(i) ? output :
false;
7031 auto rowPtrsThis = this->getRowPtrsUnpackedHost();
7033 output = rowPtrsThis.extent(0) == rowPtrsGraph.extent(0) ? output :
false;
7034 for (
size_t i = 0; output && i < rowPtrsThis.extent(0); i++)
7035 output = rowPtrsThis(i) == rowPtrsGraph(i) ? output :
false;
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);
7043 for (
size_t i = 0; output && i < indThis.extent(0); i++)
7044 output = indThis(i) == indGraph(i) ? output :
false;
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);
7052 for (
size_t i = 0; output && i < indtThis.extent(0); i++)
7053 output = indtThis(i) == indtGraph(i) ? output :
false;
7072 output = thisLclGraph.row_map.extent(0) == graphLclGraph.row_map.extent(0)
7075 if (output && thisLclGraph.row_map.extent(0) > 0) {
7076 auto lclGraph_rowmap_host_this = thisLclGraph.row_map;
7077 auto lclGraph_rowmap_host_graph = graphLclGraph.row_map;
7078 for (
size_t i = 0; output && i < lclGraph_rowmap_host_this.extent(0); i++)
7079 output = lclGraph_rowmap_host_this(i) == lclGraph_rowmap_host_graph(i)
7084 output = thisLclGraph.entries.extent(0) == graphLclGraph.entries.extent(0)
7087 if (output && thisLclGraph.entries.extent(0) > 0) {
7088 auto lclGraph_entries_host_this = thisLclGraph.entries;
7089 auto lclGraph_entries_host_graph = graphLclGraph.entries;
7090 for (
size_t i = 0; output && i < lclGraph_entries_host_this.extent(0); i++)
7091 output = lclGraph_entries_host_this(i) == lclGraph_entries_host_graph(i)
7097 thisLclGraph.row_block_offsets.extent(0) ==
7098 graphLclGraph.row_block_offsets.extent(0)
7101 if (output && thisLclGraph.row_block_offsets.extent(0) > 0) {
7102 auto lclGraph_rbo_host_this = thisLclGraph.row_block_offsets;
7103 auto lclGraph_rbo_host_graph = graphLclGraph.row_block_offsets;
7104 for (
size_t i = 0; output && i < lclGraph_rbo_host_this.extent(0); i++)
7105 output = lclGraph_rbo_host_this(i) == lclGraph_rbo_host_graph(i)
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)
7199 #endif // TPETRA_CRSGRAPH_DEF_HPP
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
void setDomainRangeMaps(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap)
void setAllIndices(const typename local_graph_device_type::row_map_type &rowPointers, const typename local_graph_device_type::entries_type::non_const_type &columnIndices)
Set the graph's data directly, using 1-D storage.
Teuchos::RCP< const map_type > getRowMap() const override
Returns the Map that describes the row distribution in this graph.
offset_device_view_type k_offRankOffsets_
The offsets for off-rank entries.
size_t nodeMaxNumRowEntries_
Local maximum of the number of entries in each row.
bool indicesAreSorted_
Whether the graph's indices are sorted in each row, on this process.
KokkosSparse::StaticCrsGraph< local_ordinal_type, Kokkos::LayoutLeft, device_type, void, size_t > local_graph_device_type
The type of the part of the sparse graph on each MPI process.
void copyOffsets(const OutputViewType &dst, const InputViewType &src)
Copy row offsets (in a sparse graph or matrix) from src to dst. The offsets may have different types...
Teuchos::RCP< const map_type > rangeMap_
The Map describing the range of the (matrix corresponding to the) graph.
Teuchos::RCP< const map_type > getColMap() const override
Returns the Map that describes the column distribution in this graph.
local_inds_host_view_type getLocalIndicesHost() const
Get a host view of the packed column indicies.
GlobalOrdinal global_ordinal_type
The type of the graph's global indices.
local_inds_dualv_type::t_host::const_type getLocalIndsViewHost(const RowInfo &rowinfo) const
Get a const, locally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myRo...
An abstract interface for graphs accessed by rows.
void getLocalOffRankOffsets(offset_device_view_type &offsets) const
Get offsets of the off-rank entries in the graph.
void insertGlobalIndicesFiltered(const local_ordinal_type lclRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Like insertGlobalIndices(), but with column Map filtering.
local_inds_dualv_type::t_host getLocalIndsViewHostNonConst(const RowInfo &rowinfo)
Get a ReadWrite locally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(m...
bool sortGhostsAssociatedWithEachProcessor_
Whether to require makeColMap() (and therefore fillComplete()) to order column Map GIDs associated wi...
size_t insertGlobalIndicesImpl(const local_ordinal_type lclRow, const global_ordinal_type inputGblColInds[], const size_t numInputInds)
Insert global indices, using an input local row index.
static KOKKOS_INLINE_FUNCTION size_t unpackValue(LO &outVal, const char inBuf[])
Unpack the given value from the given output buffer.
void resumeFill(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Resume fill operations.
bool haveGlobalConstants_
Whether all processes have computed global constants.
size_t getLocalNumRows() const override
Returns the number of graph rows owned on the calling node.
void expertStaticFillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< const import_type > &importer=Teuchos::null, const Teuchos::RCP< const export_type > &exporter=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Perform a fillComplete on a graph that already has data, via setAllIndices().
Teuchos::RCP< const import_type > getImporter() const override
Returns the importer associated with this graph.
void getLocalDiagOffsets(const Kokkos::View< size_t *, device_type, Kokkos::MemoryUnmanaged > &offsets) const
Get offsets of the diagonal entries in the graph.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
void insertGlobalIndices(const global_ordinal_type globalRow, const Teuchos::ArrayView< const global_ordinal_type > &indices)
Insert global indices into the graph.
size_t getNumEntriesInLocalRow(local_ordinal_type localRow) const override
Get the number of entries in the given row (local index).
size_t getLocalAllocationSize() const
The local number of indices allocated for the graph, over all rows on the calling (MPI) process...
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Default parameter list suitable for validation.
Declaration of a function that prints strings from each process.
void computeLocalConstants()
Compute local constants, if they have not yet been computed.
void packCrsGraphWithOwningPIDs(const CrsGraph< LO, GO, NT > &sourceGraph, Kokkos::DualView< typename CrsGraph< LO, GO, NT >::packet_type *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exports_dv, const Teuchos::ArrayView< size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &exportLIDs, const Teuchos::ArrayView< const int > &sourcePIDs, size_t &constantNumPackets)
Pack specified entries of the given local sparse graph for communication.
typename row_graph_type::local_inds_device_view_type local_inds_device_view_type
The Kokkos::View type for views of local ordinals on device and host.
bool isIdenticalTo(const CrsGraph< LocalOrdinal, GlobalOrdinal, Node > &graph) const
Create a cloned CrsGraph for a different Node type.
bool isMerged() const
Whether duplicate column indices in each row have been merged.
virtual bool checkSizes(const SrcDistObject &source) override
Compare the source and target (this) objects for compatibility.
Teuchos::RCP< const map_type > getDomainMap() const override
Returns the Map associated with the domain of this graph.
size_t getGlobalMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, over all processes in the graph's communicator...
Declare and define Tpetra::Details::copyOffsets, an implementation detail of Tpetra (in particular...
bool noRedundancies_
Whether the graph's indices are non-redundant (merged) in each row, on this process.
global_inds_dualv_type::t_dev::const_type getGlobalIndsViewDevice(const RowInfo &rowinfo) const
Get a const, globally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myR...
void padCrsArrays(const RowPtr &rowPtrBeg, const RowPtr &rowPtrEnd, Indices &indices_wdv, const Padding &padding, const int my_rank, const bool verbose)
Determine if the row pointers and indices arrays need to be resized to accommodate new entries...
OffsetsViewType::non_const_value_type computeOffsetsFromConstantCount(const OffsetsViewType &ptr, const CountType count)
Compute offsets from a constant count.
void replaceRangeMap(const Teuchos::RCP< const map_type > &newRangeMap)
Replace the current Range Map with the given objects.
int makeColMap(Teuchos::RCP< const Tpetra::Map< LO, GO, NT >> &colMap, Teuchos::Array< int > &remotePIDs, const Teuchos::RCP< const Tpetra::Map< LO, GO, NT >> &domMap, const RowGraph< LO, GO, NT > &graph, const bool sortEachProcsGids=true, std::ostream *errStrm=NULL)
Make the graph's column Map.
void packCrsGraph(const CrsGraph< LO, GO, NT > &sourceGraph, Teuchos::Array< typename CrsGraph< LO, GO, NT >::packet_type > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &exportLIDs, size_t &constantNumPackets)
Pack specified entries of the given local sparse graph for communication.
row_ptrs_device_view_type getLocalRowPtrsDevice() const
Get a device view of the packed row offsets.
global_inds_dualv_type::t_host::const_type getGlobalIndsViewHost(const RowInfo &rowinfo) const
Get a const, globally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myR...
const row_ptrs_host_view_type & getRowPtrsPackedHost() const
Get the packed row pointers on host. Lazily make a copy from device.
static bool debug()
Whether Tpetra is in debug mode.
size_t getNumAllocatedEntriesInGlobalRow(global_ordinal_type globalRow) const
Current number of allocated entries in the given row on the calling (MPI) process, using a global row index.
Allocation information for a locally owned row in a CrsGraph or CrsMatrix.
local_inds_wdv_type lclIndsUnpacked_wdv
Local ordinals of column indices for all rows Valid when isLocallyIndexed is true If OptimizedStorage...
void replaceRangeMapAndExporter(const Teuchos::RCP< const map_type > &newRangeMap, const Teuchos::RCP< const export_type > &newExporter)
Replace the current Range Map and Export with the given parameters.
void verbosePrintArray(std::ostream &out, const ArrayType &x, const char name[], const size_t maxNumToPrint)
Print min(x.size(), maxNumToPrint) entries of x.
bool hasColMap() const override
Whether the graph has a column Map.
bool isGloballyIndexed() const override
Whether the graph's column indices are stored as global indices.
virtual void unpackAndCombine(const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &importLIDs, Kokkos::DualView< packet_type *, buffer_device_type > imports, Kokkos::DualView< size_t *, buffer_device_type > numPacketsPerLID, const size_t constantNumPackets, const CombineMode combineMode) override
void exportAndFillComplete(Teuchos::RCP< CrsGraph< local_ordinal_type, global_ordinal_type, Node >> &destGraph, const export_type &exporter, const Teuchos::RCP< const map_type > &domainMap=Teuchos::null, const Teuchos::RCP< const map_type > &rangeMap=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null) const
Export from this to the given destination graph, and make the result fill complete.
Teuchos_Ordinal Array_size_type
Size type for Teuchos Array objects.
int local_ordinal_type
Default value of Scalar template parameter.
bool isStorageOptimized() const
Returns true if storage has been optimized.
bool haveLocalConstants_
Whether this process has computed local constants.
size_t findGlobalIndices(const RowInfo &rowInfo, const Teuchos::ArrayView< const global_ordinal_type > &indices, std::function< void(const size_t, const size_t, const size_t)> fun) const
Finds indices in the given row.
std::string description() const override
Return a one-line human-readable description of this object.
void sort(View &view, const size_t &size)
Convenience wrapper for std::sort for host-accessible views.
void gathervPrint(std::ostream &out, const std::string &s, const Teuchos::Comm< int > &comm)
On Process 0 in the given communicator, print strings from each process in that communicator, in rank order.
void makeColMap(Teuchos::Array< int > &remotePIDs)
Make and set the graph's column Map.
Teuchos::RCP< const export_type > getExporter() const override
Returns the exporter associated with this graph.
std::pair< size_t, std::string > makeIndicesLocal(const bool verbose=false)
Convert column indices from global to local.
size_t global_size_t
Global size_t object.
virtual void removeEmptyProcessesInPlace(const Teuchos::RCP< const map_type > &newMap) override
Remove processes owning zero rows from the Maps and their communicator.
Node node_type
This class' Kokkos Node type.
void reindexColumns(const Teuchos::RCP< const map_type > &newColMap, const Teuchos::RCP< const import_type > &newImport=Teuchos::null, const bool sortIndicesInEachRow=true)
Reindex the column indices in place, and replace the column Map. Optionally, replace the Import objec...
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
void makeImportExport(Teuchos::Array< int > &remotePIDs, const bool useRemotePIDs)
Make the Import and Export objects, if needed.
size_t sortAndMergeRowIndices(const RowInfo &rowInfo, const bool sorted, const bool merged)
Sort and merge duplicate column indices in the given row.
void insertLocalIndices(const local_ordinal_type localRow, const Teuchos::ArrayView< const local_ordinal_type > &indices)
Insert local indices into the graph.
Insert new values that don't currently exist.
bool isSorted() const
Whether graph indices in all rows are known to be sorted.
void getLocalRowCopy(local_ordinal_type gblRow, nonconst_local_inds_host_view_type &gblColInds, size_t &numColInds) const override
Get a copy of the given row, using local indices.
Teuchos::RCP< const map_type > rowMap_
The Map describing the distribution of rows of the graph.
Teuchos::RCP< const import_type > importer_
The Import from the domain Map to the column Map.
size_t insertCrsIndices(typename Pointers::value_type const row, Pointers const &rowPtrs, InOutIndices &curIndices, size_t &numAssigned, InIndices const &newIndices, std::function< void(const size_t, const size_t, const size_t)> cb=std::function< void(const size_t, const size_t, const size_t)>())
Insert new indices in to current list of indices.
num_row_entries_type k_numRowEntries_
The number of local entries in each locally owned row.
local_inds_device_view_type getLocalIndicesDevice() const
Get a device view of the packed column indicies.
Teuchos::RCP< const map_type > domainMap_
The Map describing the domain of the (matrix corresponding to the) graph.
OffsetType convertColumnIndicesFromGlobalToLocal(const Kokkos::View< LO *, DT > &lclColInds, const Kokkos::View< const GO *, DT > &gblColInds, const Kokkos::View< const OffsetType *, DT > &ptr, const LocalMap< LO, GO, DT > &lclColMap, const Kokkos::View< const NumEntType *, DT > &numRowEnt)
Convert a CrsGraph's global column indices into local column indices.
global_size_t getGlobalNumRows() const override
Returns the number of global rows in the graph.
global_ordinal_type getGlobalElement(local_ordinal_type localIndex) const
The global index corresponding to the given local index.
bool isNodeLocalElement(local_ordinal_type localIndex) const
Whether the given local index is valid for this Map on the calling process.
Functions for manipulating CRS arrays.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
void setLocallyModified()
Report that we made a local modification to its structure.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
void unpackAndCombineIntoCrsArrays(const CrsGraph< LO, GO, NT > &sourceGraph, const Teuchos::ArrayView< const LO > &importLIDs, const Teuchos::ArrayView< const typename CrsGraph< LO, GO, NT >::packet_type > &imports, const Teuchos::ArrayView< const size_t > &numPacketsPerLID, const size_t constantNumPackets, const CombineMode combineMode, const size_t numSameIDs, const Teuchos::ArrayView< const LO > &permuteToLIDs, const Teuchos::ArrayView< const LO > &permuteFromLIDs, size_t TargetNumRows, size_t TargetNumNonzeros, const int MyTargetPID, const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< GO > &CRS_colind, const Teuchos::ArrayView< const int > &SourcePids, Teuchos::Array< int > &TargetPids)
unpackAndCombineIntoCrsArrays
void checkInternalState() const
Throw an exception if the internal state is not consistent.
void importAndFillComplete(Teuchos::RCP< CrsGraph< local_ordinal_type, global_ordinal_type, Node >> &destGraph, const import_type &importer, const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null) const
Import from this to the given destination graph, and make the result fill complete.
bool isNodeGlobalElement(global_ordinal_type globalIndex) const
Whether the given global index is owned by this Map on the calling process.
Sets up and executes a communication plan for a Tpetra DistObject.
size_t findCrsIndices(typename Pointers::value_type const row, Pointers const &rowPtrs, const size_t curNumEntries, Indices1 const &curIndices, Indices2 const &newIndices, Callback &&cb)
Finds offsets in to current list of indices.
static bool verbose()
Whether Tpetra is in verbose mode.
CombineMode
Rule for combining data in an Import or Export.
Teuchos::RCP< const export_type > exporter_
The Export from the row Map to the range Map.
void insertGlobalIndicesIntoNonownedRows(const global_ordinal_type gblRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Implementation of insertGlobalIndices for nonowned rows.
bool isFillComplete() const override
Whether fillComplete() has been called and the graph is in compute mode.
size_t getNumAllocatedEntriesInLocalRow(local_ordinal_type localRow) const
Current number of allocated entries in the given row on the calling (MPI) process, using a local row index.
void swap(CrsGraph< local_ordinal_type, global_ordinal_type, Node > &graph)
Swaps the data from *this with the data and maps from graph.
void globalAssemble()
Communicate nonlocal contributions to other processes.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createOneToOne(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node >> &M)
Nonmember constructor for a contiguous Map with user-defined weights and a user-specified, possibly nondefault Kokkos Node type.
RowInfo getRowInfoFromGlobalRowIndex(const global_ordinal_type gblRow) const
Get information about the locally owned row with global index gblRow.
Utility functions for packing and unpacking sparse matrix entries.
size_t getLocalNumCols() const override
Returns the number of columns connected to the locally owned rows of this graph.
size_t getLocalNumEntries() const override
The local number of entries in the graph.
Abstract base class for objects that can be the source of an Import or Export operation.
void removeLocalIndices(local_ordinal_type localRow)
Remove all graph indices from the specified local row.
LocalOrdinal local_ordinal_type
The type of the graph's local indices.
global_size_t globalNumEntries_
Global number of entries in the graph.
global_inds_wdv_type gblInds_wdv
Global ordinals of column indices for all rows.
local_inds_dualv_type::t_dev::const_type getLocalIndsViewDevice(const RowInfo &rowinfo) const
Get a const, locally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myRo...
Teuchos::RCP< const map_type > getRangeMap() const override
Returns the Map associated with the domain of this graph.
virtual void pack(const Teuchos::ArrayView< const local_ordinal_type > &exportLIDs, Teuchos::Array< global_ordinal_type > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, size_t &constantNumPackets) const override
void enableWDVTracking()
Enable WrappedDualView reference-count tracking and syncing. Call this after exiting a host-parallel ...
row_ptrs_host_view_type getLocalRowPtrsHost() const
Get a host view of the packed row offsets.
void packCrsGraphNew(const CrsGraph< LO, GO, NT > &sourceGraph, const Kokkos::DualView< const LO *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exportLIDs, const Kokkos::DualView< const int *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exportPIDs, Kokkos::DualView< typename CrsGraph< LO, GO, NT >::packet_type *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exports, Kokkos::DualView< size_t *, typename CrsGraph< LO, GO, NT >::buffer_device_type > numPacketsPerLID, size_t &constantNumPackets, const bool pack_pids)
Pack specified entries of the given local sparse graph for communication, for "new" DistObject interf...
const row_ptrs_host_view_type & getRowPtrsUnpackedHost() const
Get the unpacked row pointers on host. Lazily make a copy from device.
void replaceColMap(const Teuchos::RCP< const map_type > &newColMap)
Replace the graph's current column Map with the given Map.
global_size_t getGlobalNumCols() const override
Returns the number of global columns in the graph.
size_t getLocalMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, on this process.
RowInfo getRowInfo(const local_ordinal_type myRow) const
Get information about the locally owned row with local index myRow.
void replaceDomainMapAndImporter(const Teuchos::RCP< const map_type > &newDomainMap, const Teuchos::RCP< const import_type > &newImporter)
Replace the current domain Map and Import with the given parameters.
bool supportsRowViews() const override
Whether this class implements getLocalRowView() and getGlobalRowView() (it does). ...
typename dist_object_type::buffer_device_type buffer_device_type
Kokkos::Device specialization for communication buffers.
local_map_type getLocalMap() const
Get the LocalMap for Kokkos-Kernels.
local_inds_wdv_type lclIndsPacked_wdv
Local ordinals of column indices for all rows Valid when isLocallyIndexed is true Built during fillCo...
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
Details::EStorageStatus storageStatus_
Status of the graph's storage, when not in a fill-complete state.
size_t unpackAndCombineWithOwningPIDsCount(const CrsGraph< LO, GO, NT > &sourceGraph, const Teuchos::ArrayView< const LO > &importLIDs, const Teuchos::ArrayView< const typename CrsGraph< LO, GO, NT >::packet_type > &imports, const Teuchos::ArrayView< const size_t > &numPacketsPerLID, size_t constantNumPackets, CombineMode combineMode, size_t numSameIDs, const Teuchos::ArrayView< const LO > &permuteToLIDs, const Teuchos::ArrayView< const LO > &permuteFromLIDs)
Special version of Tpetra::Details::unpackCrsGraphAndCombine that also unpacks owning process ranks...
const row_ptrs_device_view_type & getRowPtrsPackedDevice() const
Get the packed row pointers on device.
A parallel distribution of indices over processes.
Teuchos::ArrayView< typename DualViewType::t_dev::value_type > getArrayViewFromDualView(const DualViewType &x)
Get a Teuchos::ArrayView which views the host Kokkos::View of the input 1-D Kokkos::DualView.
static KOKKOS_INLINE_FUNCTION size_t packValueCount(const LO &)
Number of bytes required to pack or unpack the given value of type value_type.
const row_ptrs_device_view_type & getRowPtrsUnpackedDevice() const
Get the unpacked row pointers on device.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects...
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > ¶ms) override
Set the given list of parameters (must be nonnull).
size_t getNumEntriesInGlobalRow(global_ordinal_type globalRow) const override
Returns the current number of entries on this node in the specified global row.
void fillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Tell the graph that you are done changing its structure.
void disableWDVTracking()
Disable WrappedDualView reference-count tracking and syncing. Call this before entering a host-parall...
local_ordinal_type getLocalElement(global_ordinal_type globalIndex) const
The local index corresponding to the given global index.
void getLocalRowView(const LocalOrdinal lclRow, local_inds_host_view_type &lclColInds) const override
Get a const view of the given local row's local column indices.
typename Node::device_type device_type
This class' Kokkos device type.
bool isLocallyIndexed() const override
Whether the graph's column indices are stored as local indices.
A distributed dense vector.
Stand-alone utility functions and macros.
bool isFillActive() const
Whether resumeFill() has been called and the graph is in edit mode.
virtual void copyAndPermute(const SrcDistObject &source, const size_t numSameIDs, const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &permuteToLIDs, const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &permuteFromLIDs, const CombineMode CM) override
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
Returns the communicator.
Kokkos::View< const size_t *, device_type >::host_mirror_type k_numAllocPerRow_
The maximum number of entries to allow in each locally owned row, per row.
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const ExecutionSpace &execSpace, const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
global_size_t globalMaxNumRowEntries_
Global maximum of the number of entries in each row.
static size_t verbosePrintCountThreshold()
Number of entries below which arrays, lists, etc. will be printed in debug mode.
size_t insertIndices(RowInfo &rowInfo, const SLocalGlobalViews &newInds, const ELocalGlobal lg, const ELocalGlobal I)
Insert indices into the given row.
global_size_t getGlobalNumEntries() const override
Returns the global number of entries in the graph.
Declaration and definition of Tpetra::Details::getEntryOnHost.
size_t numAllocForAllRows_
The maximum number of entries to allow in each locally owned row.
local_graph_device_type getLocalGraphDevice() const
Get the local graph.
void getGlobalRowView(const global_ordinal_type gblRow, global_inds_host_view_type &gblColInds) const override
Get a const view of the given global row's global column indices.
Teuchos::RCP< const map_type > colMap_
The Map describing the distribution of columns of the graph.
global_ordinal_type getIndexBase() const override
Returns the index base for global indices for this graph.
typename local_graph_device_type::HostMirror local_graph_host_type
The type of the part of the sparse graph on each MPI process.
void replaceDomainMap(const Teuchos::RCP< const map_type > &newDomainMap)
Replace the current domain Map with the given objects.
std::unique_ptr< std::string > createPrefix(const int myRank, const char prefix[])
Create string prefix for each line of verbose output.
nonlocals_type nonlocals_
Nonlocal data given to insertGlobalIndices.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const override
Print this object to the given output stream with the given verbosity level.
void computeGlobalConstants()
Compute global constants, if they have not yet been computed.
void getGlobalRowCopy(global_ordinal_type gblRow, nonconst_global_inds_host_view_type &gblColInds, size_t &numColInds) const override
Get a copy of the given row, using global indices.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.