40 #ifndef TPETRA_CRSGRAPH_DEF_HPP 41 #define TPETRA_CRSGRAPH_DEF_HPP 55 #include "Tpetra_Details_getGraphDiagOffsets.hpp" 56 #include "Tpetra_Details_makeColMap.hpp" 60 #include "Tpetra_Distributor.hpp" 61 #include "Teuchos_SerialDenseMatrix.hpp" 62 #include "Tpetra_Vector.hpp" 65 #include "Tpetra_Details_packCrsGraph.hpp" 66 #include "Tpetra_Details_unpackCrsGraphAndCombine.hpp" 67 #include "Tpetra_Details_CrsPadding.hpp" 74 #include <type_traits> 82 template<
class MapIter>
84 verbosePrintMap(std::ostream& out,
90 using ::Tpetra::Details::Behavior;
93 out << mapName <<
": {";
94 const size_t maxNumToPrint =
96 if (maxNumToPrint == 0) {
102 const size_t numToPrint = numEnt > maxNumToPrint ?
103 maxNumToPrint : numEnt;
105 for (MapIter it = beg; it != end; ++it) {
106 out <<
"(" << (*it).first <<
", ";
110 if (count +
size_t(1) < numToPrint) {
115 if (count < numEnt) {
122 template<
class LO,
class GO,
class Node>
123 Teuchos::ArrayView<GO>
124 getRowGraphGlobalRow(
125 std::vector<GO>& gblColIndsStorage,
126 const RowGraph<LO, GO, Node>& graph,
129 size_t origNumEnt = graph.getNumEntriesInGlobalRow(gblRowInd);
130 if (gblColIndsStorage.size() < origNumEnt) {
131 gblColIndsStorage.resize(origNumEnt);
133 Teuchos::ArrayView<GO> gblColInds(gblColIndsStorage.data(),
135 graph.getGlobalRowCopy(gblRowInd, gblColInds, origNumEnt);
139 template<
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
140 class ConvertColumnIndicesFromGlobalToLocal {
142 ConvertColumnIndicesFromGlobalToLocal (const ::Kokkos::View<LO*, DT>& lclColInds,
143 const ::Kokkos::View<const GO*, DT>& gblColInds,
144 const ::Kokkos::View<const OffsetType*, DT>& ptr,
145 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
146 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt) :
147 lclColInds_ (lclColInds),
148 gblColInds_ (gblColInds),
150 lclColMap_ (lclColMap),
151 numRowEnt_ (numRowEnt)
155 operator () (
const LO& lclRow, OffsetType& curNumBad)
const 157 const OffsetType offset = ptr_(lclRow);
161 const LO numEnt =
static_cast<LO
> (numRowEnt_(lclRow));
162 for (LO j = 0; j < numEnt; ++j) {
163 const GO gid = gblColInds_(offset + j);
164 const LO lid = lclColMap_.getLocalElement (gid);
165 lclColInds_(offset + j) = lid;
166 if (lid == ::Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
173 run (const ::Kokkos::View<LO*, DT>& lclColInds,
174 const ::Kokkos::View<const GO*, DT>& gblColInds,
175 const ::Kokkos::View<const OffsetType*, DT>& ptr,
176 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
177 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt)
179 typedef ::Kokkos::RangePolicy<typename DT::execution_space, LO> range_type;
180 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> functor_type;
182 const LO lclNumRows = ptr.extent (0) == 0 ?
183 static_cast<LO
> (0) : static_cast<LO> (ptr.extent (0) - 1);
184 OffsetType numBad = 0;
186 ::Kokkos::parallel_reduce (range_type (0, lclNumRows),
187 functor_type (lclColInds, gblColInds, ptr,
188 lclColMap, numRowEnt),
194 ::Kokkos::View<LO*, DT> lclColInds_;
195 ::Kokkos::View<const GO*, DT> gblColInds_;
196 ::Kokkos::View<const OffsetType*, DT> ptr_;
198 ::Kokkos::View<const NumEntType*, DT> numRowEnt_;
217 template<
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
220 const Kokkos::View<const GO*, DT>& gblColInds,
221 const Kokkos::View<const OffsetType*, DT>& ptr,
223 const Kokkos::View<const NumEntType*, DT>& numRowEnt)
225 using Impl::ConvertColumnIndicesFromGlobalToLocal;
226 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> impl_type;
227 return impl_type::run (lclColInds, gblColInds, ptr, lclColMap, numRowEnt);
230 template<
class ViewType,
class LO>
231 class MaxDifference {
233 MaxDifference (
const ViewType& ptr) : ptr_ (ptr) {}
235 KOKKOS_INLINE_FUNCTION
void init (LO& dst)
const {
239 KOKKOS_INLINE_FUNCTION
void 240 join (
volatile LO& dst,
const volatile LO& src)
const 242 dst = (src > dst) ? src : dst;
245 KOKKOS_INLINE_FUNCTION
void 246 operator () (
const LO lclRow, LO& maxNumEnt)
const 248 const LO numEnt =
static_cast<LO
> (ptr_(lclRow+1) - ptr_(lclRow));
249 maxNumEnt = (numEnt > maxNumEnt) ? numEnt : maxNumEnt;
252 typename ViewType::const_type ptr_;
255 template<
class ViewType,
class LO>
256 typename ViewType::non_const_value_type
257 maxDifference (
const char kernelLabel[],
261 if (lclNumRows == 0) {
264 return static_cast<LO
> (0);
267 using execution_space =
typename ViewType::execution_space;
268 using range_type = Kokkos::RangePolicy<execution_space, LO>;
270 Kokkos::parallel_reduce (kernelLabel,
271 range_type (0, lclNumRows),
272 MaxDifference<ViewType, LO> (ptr),
280 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
282 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
287 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
289 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
294 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
295 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
296 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
297 const size_t maxNumEntriesPerRow,
299 const Teuchos::RCP<Teuchos::ParameterList>& params) :
302 , numAllocForAllRows_ (maxNumEntriesPerRow)
304 const char tfecfFuncName[] =
305 "CrsGraph(rowMap,maxNumEntriesPerRow,pftype,params): ";
307 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
308 (maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid (),
309 std::invalid_argument,
"The allocation hint maxNumEntriesPerRow must be " 310 "a valid size_t value, which in this case means it must not be " 311 "Teuchos::OrdinalTraits<size_t>::invalid().");
313 checkInternalState ();
316 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
318 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
319 const Teuchos::RCP<const map_type>& colMap,
320 const size_t maxNumEntriesPerRow,
322 const Teuchos::RCP<Teuchos::ParameterList>& params) :
326 , numAllocForAllRows_ (maxNumEntriesPerRow)
328 const char tfecfFuncName[] =
329 "CrsGraph(rowMap,colMap,maxNumEntriesPerRow,pftype,params): ";
331 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
332 maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid (),
333 std::invalid_argument,
"The allocation hint maxNumEntriesPerRow must be " 334 "a valid size_t value, which in this case means it must not be " 335 "Teuchos::OrdinalTraits<size_t>::invalid().");
337 checkInternalState ();
340 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
342 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
343 const Teuchos::ArrayView<const size_t>& numEntPerRow,
345 const Teuchos::RCP<Teuchos::ParameterList>& params) :
348 , numAllocForAllRows_ (0)
350 const char tfecfFuncName[] =
351 "CrsGraph(rowMap,numEntPerRow,pftype,params): ";
354 const size_t lclNumRows = rowMap.is_null () ?
355 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
356 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
357 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
358 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
359 <<
" != the local number of rows " << lclNumRows <<
" as specified by " 360 "the input row Map.");
363 for (
size_t r = 0; r < lclNumRows; ++r) {
364 const size_t curRowCount = numEntPerRow[r];
365 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
366 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
367 std::invalid_argument,
"numEntPerRow(" << r <<
") " 368 "specifies an invalid number of entries " 369 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
376 typedef decltype (k_numAllocPerRow_) out_view_type;
377 typedef typename out_view_type::non_const_type nc_view_type;
378 typedef Kokkos::View<
const size_t*,
379 typename nc_view_type::array_layout,
381 Kokkos::MemoryUnmanaged> in_view_type;
382 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
383 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
386 k_numAllocPerRow_ = numAllocPerRowOut;
389 checkInternalState ();
394 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
396 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
397 const Kokkos::DualView<const size_t*, execution_space>& numEntPerRow,
399 const Teuchos::RCP<Teuchos::ParameterList>& params) :
402 , k_numAllocPerRow_ (numEntPerRow.h_view)
403 , numAllocForAllRows_ (0)
405 const char tfecfFuncName[] =
406 "CrsGraph(rowMap,numEntPerRow,pftype,params): ";
409 const size_t lclNumRows = rowMap.is_null () ?
410 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
411 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
412 static_cast<size_t> (numEntPerRow.extent (0)) != lclNumRows,
413 std::invalid_argument,
"numEntPerRow has length " <<
414 numEntPerRow.extent (0) <<
" != the local number of rows " <<
415 lclNumRows <<
" as specified by " "the input row Map.");
418 for (
size_t r = 0; r < lclNumRows; ++r) {
419 const size_t curRowCount = numEntPerRow.h_view(r);
420 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
421 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
422 std::invalid_argument,
"numEntPerRow(" << r <<
") " 423 "specifies an invalid number of entries " 424 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
429 checkInternalState ();
433 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
435 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
436 const Teuchos::RCP<const map_type>& colMap,
437 const Kokkos::DualView<const size_t*, execution_space>& numEntPerRow,
439 const Teuchos::RCP<Teuchos::ParameterList>& params) :
443 , k_numAllocPerRow_ (numEntPerRow.h_view)
444 , numAllocForAllRows_ (0)
446 const char tfecfFuncName[] =
447 "CrsGraph(rowMap,colMap,numEntPerRow,pftype,params): ";
450 const size_t lclNumRows = rowMap.is_null () ?
451 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
452 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
453 static_cast<size_t> (numEntPerRow.extent (0)) != lclNumRows,
454 std::invalid_argument,
"numEntPerRow has length " <<
455 numEntPerRow.extent (0) <<
" != the local number of rows " <<
456 lclNumRows <<
" as specified by " "the input row Map.");
459 for (
size_t r = 0; r < lclNumRows; ++r) {
460 const size_t curRowCount = numEntPerRow.h_view(r);
461 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
462 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
463 std::invalid_argument,
"numEntPerRow(" << r <<
") " 464 "specifies an invalid number of entries " 465 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
470 checkInternalState ();
474 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
476 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
477 const Teuchos::RCP<const map_type>& colMap,
478 const Teuchos::ArrayView<const size_t>& numEntPerRow,
480 const Teuchos::RCP<Teuchos::ParameterList>& params) :
484 , numAllocForAllRows_ (0)
486 const char tfecfFuncName[] =
487 "CrsGraph(rowMap,colMap,numEntPerRow,pftype,params): ";
490 const size_t lclNumRows = rowMap.is_null () ?
491 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
492 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
493 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
494 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
495 <<
" != the local number of rows " << lclNumRows <<
" as specified by " 496 "the input row Map.");
499 for (
size_t r = 0; r < lclNumRows; ++r) {
500 const size_t curRowCount = numEntPerRow[r];
501 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
502 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
503 std::invalid_argument,
"numEntPerRow(" << r <<
") " 504 "specifies an invalid number of entries " 505 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
512 typedef decltype (k_numAllocPerRow_) out_view_type;
513 typedef typename out_view_type::non_const_type nc_view_type;
514 typedef Kokkos::View<
const size_t*,
515 typename nc_view_type::array_layout,
517 Kokkos::MemoryUnmanaged> in_view_type;
518 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
519 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
522 k_numAllocPerRow_ = numAllocPerRowOut;
525 checkInternalState ();
529 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
531 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
532 const Teuchos::RCP<const map_type>& colMap,
533 const typename local_graph_type::row_map_type& rowPointers,
534 const typename local_graph_type::entries_type::non_const_type& columnIndices,
535 const Teuchos::RCP<Teuchos::ParameterList>& params) :
539 , numAllocForAllRows_(0)
540 , storageStatus_(
Details::STORAGE_1D_PACKED)
541 , indicesAreAllocated_(true)
542 , indicesAreLocal_(true)
545 if (! params.is_null() && params->isParameter(
"sorted") &&
546 ! params->get<
bool>(
"sorted")) {
547 indicesAreSorted_ =
false;
550 indicesAreSorted_ =
true;
552 setAllIndices (rowPointers, columnIndices);
553 checkInternalState ();
556 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
558 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
559 const Teuchos::RCP<const map_type>& colMap,
560 const Teuchos::ArrayRCP<size_t>& rowPointers,
561 const Teuchos::ArrayRCP<LocalOrdinal> & columnIndices,
562 const Teuchos::RCP<Teuchos::ParameterList>& params) :
566 , numAllocForAllRows_ (0)
567 , storageStatus_ (
Details::STORAGE_1D_PACKED)
568 , indicesAreAllocated_ (true)
569 , indicesAreLocal_ (true)
572 if (! params.is_null() && params->isParameter(
"sorted") &&
573 ! params->get<
bool>(
"sorted")) {
574 indicesAreSorted_ =
false;
577 indicesAreSorted_ =
true;
579 setAllIndices (rowPointers, columnIndices);
580 checkInternalState ();
583 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
585 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
586 const Teuchos::RCP<const map_type>& colMap,
588 const Teuchos::RCP<Teuchos::ParameterList>& params)
597 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
600 const Teuchos::RCP<const map_type>& rowMap,
601 const Teuchos::RCP<const map_type>& colMap,
602 const Teuchos::RCP<const map_type>& domainMap,
603 const Teuchos::RCP<const map_type>& rangeMap,
604 const Teuchos::RCP<Teuchos::ParameterList>& params)
608 , lclGraph_ (k_local_graph_)
609 , numAllocForAllRows_ (0)
610 , storageStatus_ (
Details::STORAGE_1D_PACKED)
611 , indicesAreAllocated_ (true)
612 , indicesAreLocal_ (true)
615 const char tfecfFuncName[] =
"CrsGraph(Kokkos::LocalStaticCrsGraph,Map,Map,Map,Map)";
617 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
618 colMap.is_null (), std::runtime_error,
619 ": The input column Map must be nonnull.");
620 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
621 k_local_graph_.numRows () != rowMap->getNodeNumElements (),
623 ": The input row Map and the input local graph need to have the same " 624 "number of rows. The row Map claims " << rowMap->getNodeNumElements ()
625 <<
" row(s), but the local graph claims " << k_local_graph_.numRows ()
635 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
636 k_lclInds1D_.extent (0) != 0 || k_gblInds1D_.extent (0) != 0, std::logic_error,
637 ": cannot have 1D data structures allocated.");
639 if(! params.is_null() && params->isParameter(
"sorted") &&
640 ! params->get<
bool>(
"sorted")) {
641 indicesAreSorted_ =
false;
644 indicesAreSorted_ =
true;
647 setDomainRangeMaps (domainMap.is_null() ? rowMap_ : domainMap,
648 rangeMap .is_null() ? rowMap_ : rangeMap);
649 Teuchos::Array<int> remotePIDs (0);
650 this->makeImportExport (remotePIDs,
false);
652 k_lclInds1D_ = lclGraph_.entries;
653 k_rowPtrs_ = lclGraph_.row_map;
655 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
656 params->get (
"compute global constants",
true);
658 if (callComputeGlobalConstants) {
659 this->computeGlobalConstants ();
661 this->fillComplete_ =
true;
662 this->checkInternalState ();
665 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
668 const Teuchos::RCP<const map_type>& rowMap,
669 const Teuchos::RCP<const map_type>& colMap,
670 const Teuchos::RCP<const map_type>& domainMap,
671 const Teuchos::RCP<const map_type>& rangeMap,
672 const Teuchos::RCP<const import_type>& importer,
673 const Teuchos::RCP<const export_type>& exporter,
674 const Teuchos::RCP<Teuchos::ParameterList>& params) :
678 rangeMap_ (rangeMap.is_null () ? rowMap : rangeMap),
679 domainMap_ (domainMap.is_null () ? rowMap : domainMap),
680 importer_ (importer),
681 exporter_ (exporter),
682 lclGraph_ (lclGraph),
683 numAllocForAllRows_ (0),
684 storageStatus_ (
Details::STORAGE_1D_PACKED),
685 indicesAreAllocated_ (true),
686 indicesAreLocal_ (true)
689 const char tfecfFuncName[] =
"Tpetra::CrsGraph(local_graph_type," 690 "Map,Map,Map,Map,Import,Export,params): ";
692 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
693 (colMap.is_null (), std::runtime_error,
694 "The input column Map must be nonnull.");
696 k_lclInds1D_ = lclGraph_.entries;
697 k_rowPtrs_ = lclGraph_.row_map;
699 if (! params.is_null() && params->isParameter(
"sorted") &&
700 ! params->get<
bool>(
"sorted")) {
701 indicesAreSorted_ =
false;
704 indicesAreSorted_ =
true;
707 const bool callComputeGlobalConstants =
708 params.get () ==
nullptr ||
709 params->get (
"compute global constants",
true);
710 if (callComputeGlobalConstants) {
711 this->computeGlobalConstants ();
713 fillComplete_ =
true;
714 checkInternalState ();
717 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
718 Teuchos::RCP<const Teuchos::ParameterList>
723 using Teuchos::ParameterList;
724 using Teuchos::parameterList;
726 RCP<ParameterList> params = parameterList (
"Tpetra::CrsGraph");
729 RCP<ParameterList> importSublist = parameterList (
"Import");
741 Distributor distributor (rowMap_->getComm (), importSublist);
742 params->set (
"Import", *importSublist,
"How the Import performs communication.");
748 params->set (
"Export", *importSublist,
"How the Export performs communication.");
753 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
758 Teuchos::RCP<const Teuchos::ParameterList> validParams =
759 getValidParameters ();
760 params->validateParametersAndSetDefaults (*validParams);
761 this->setMyParamList (params);
764 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
769 return rowMap_->getGlobalNumElements ();
772 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
777 const char tfecfFuncName[] =
"getGlobalNumCols: ";
778 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
779 ! isFillComplete () || getDomainMap ().is_null (), std::runtime_error,
780 "The graph does not have a domain Map. You may not call this method in " 782 return getDomainMap ()->getGlobalNumElements ();
785 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
790 return this->rowMap_.is_null () ?
791 static_cast<size_t> (0) :
792 this->rowMap_->getNodeNumElements ();
795 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
800 const char tfecfFuncName[] =
"getNodeNumCols: ";
801 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
802 ! hasColMap (), std::runtime_error,
803 "The graph does not have a column Map. You may not call this method " 804 "unless the graph has a column Map. This requires either that a custom " 805 "column Map was given to the constructor, or that fillComplete() has " 807 return colMap_.is_null () ?
static_cast<size_t> (0) :
808 colMap_->getNodeNumElements ();
813 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
814 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
821 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
822 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
829 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
830 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
837 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
838 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
845 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
846 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::import_type>
853 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
854 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::export_type>
861 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
866 return ! colMap_.is_null ();
869 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
877 const bool isOpt = indicesAreAllocated_ &&
878 k_numRowEntries_.extent (0) == 0 &&
879 getNodeNumRows () > 0;
884 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
889 return StaticProfile;
892 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
897 const char tfecfFuncName[] =
"getGlobalNumEntries: ";
898 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
899 (! this->haveGlobalConstants_, std::logic_error,
900 "The graph does not have global constants computed, " 901 "but the user has requested them.");
903 return globalNumEntries_;
906 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
911 typedef LocalOrdinal LO;
913 if (this->indicesAreAllocated_) {
914 const LO lclNumRows = this->getNodeNumRows ();
915 if (lclNumRows == 0) {
916 return static_cast<size_t> (0);
920 auto numEntPerRow = this->k_numRowEntries_;
921 const LO numNumEntPerRow = numEntPerRow.extent (0);
922 if (numNumEntPerRow == 0) {
923 if (static_cast<LO> (this->lclGraph_.row_map.extent (0)) <
924 static_cast<LO> (lclNumRows + 1)) {
925 return static_cast<size_t> (0);
928 return ::Tpetra::Details::getEntryOnHost (this->lclGraph_.row_map, lclNumRows);
938 typedef typename num_row_entries_type::execution_space
940 typedef Kokkos::RangePolicy<host_exec_space, LO> range_type;
942 const LO upperLoopBound = lclNumRows < numNumEntPerRow ?
945 size_t nodeNumEnt = 0;
946 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::getNumNodeEntries",
947 range_type (0, upperLoopBound),
948 [=] (
const LO& k,
size_t& lclSum) {
949 lclSum += numEntPerRow(k);
956 return static_cast<size_t> (0);
960 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
965 const char tfecfFuncName[] =
"getGlobalMaxNumRowEntries: ";
966 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
967 (! this->haveGlobalConstants_, std::logic_error,
968 "The graph does not have global constants computed, " 969 "but the user has requested them.");
971 return globalMaxNumRowEntries_;
974 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
979 return nodeMaxNumRowEntries_;
982 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
987 return fillComplete_;
990 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
995 return ! fillComplete_;
999 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1004 return indicesAreLocal_;
1007 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1012 return indicesAreGlobal_;
1015 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1020 typedef LocalOrdinal LO;
1022 if (this->indicesAreAllocated_) {
1023 const LO lclNumRows = this->getNodeNumRows ();
1024 if (lclNumRows == 0) {
1025 return static_cast<size_t> (0);
1027 else if (storageStatus_ == Details::STORAGE_1D_PACKED) {
1028 if (static_cast<LO> (this->lclGraph_.row_map.extent (0)) <
1029 static_cast<LO> (lclNumRows + 1)) {
1030 return static_cast<size_t> (0);
1033 return ::Tpetra::Details::getEntryOnHost (this->lclGraph_.row_map, lclNumRows);
1036 else if (storageStatus_ == Details::STORAGE_1D_UNPACKED) {
1037 if (this->k_rowPtrs_.extent (0) == 0) {
1038 return static_cast<size_t> (0);
1041 return ::Tpetra::Details::getEntryOnHost (this->k_rowPtrs_, lclNumRows);
1045 return static_cast<size_t> (0);
1049 return Tpetra::Details::OrdinalTraits<size_t>::invalid ();
1053 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1054 Teuchos::RCP<const Teuchos::Comm<int> >
1058 return this->rowMap_.is_null () ? Teuchos::null : this->rowMap_->
getComm ();
1061 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1069 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1074 return indicesAreAllocated_;
1077 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1079 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1082 return indicesAreSorted_;
1085 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1090 return noRedundancies_;
1093 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1103 indicesAreSorted_ =
false;
1104 noRedundancies_ =
false;
1108 haveLocalConstants_ =
false;
1111 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1117 using Teuchos::arcp;
1118 using Teuchos::Array;
1119 using Teuchos::ArrayRCP;
1121 typedef Teuchos::ArrayRCP<size_t>::size_type size_type;
1122 typedef typename local_graph_type::row_map_type::non_const_type
1123 non_const_row_map_type;
1124 typedef typename local_graph_type::entries_type::non_const_type
1126 typedef Kokkos::View<GlobalOrdinal*,
1127 typename lcl_col_inds_type::array_layout,
1128 device_type> gbl_col_inds_type;
1129 const char tfecfFuncName[] =
"allocateIndices: ";
1130 const char suffix[] =
1131 " Please report this bug to the Tpetra developers.";
1132 ProfilingRegion profRegion(
"Tpetra::CrsGraph::allocateIndices");
1134 std::unique_ptr<std::string> prefix;
1136 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
1137 std::ostringstream os;
1138 os << *prefix <<
"Start: lg=" 1139 << (lg == GlobalIndices ?
"GlobalIndices" :
"LocalIndices")
1140 <<
", numRows: " << this->getNodeNumRows() << endl;
1141 std::cerr << os.str();
1147 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1148 (isLocallyIndexed () && lg == GlobalIndices, std::logic_error,
1149 ": The graph is locally indexed, but Tpetra code is calling " 1150 "this method with lg=GlobalIndices." << suffix);
1151 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1152 (isGloballyIndexed () && lg == LocalIndices, std::logic_error,
1153 ": The graph is globally indexed, but Tpetra code is calling " 1154 "this method with lg=LocalIndices." << suffix);
1155 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1156 (indicesAreAllocated (), std::logic_error,
": The graph's " 1157 "indices are already allocated, but Tpetra is calling " 1158 "allocateIndices again." << suffix);
1159 const size_t numRows = this->getNodeNumRows ();
1165 std::ostringstream os;
1166 os << *prefix <<
"Allocate k_rowPtrs: " << (numRows+1) << endl;
1167 std::cerr << os.str();
1169 non_const_row_map_type k_rowPtrs (
"Tpetra::CrsGraph::ptr", numRows + 1);
1171 if (this->k_numAllocPerRow_.extent (0) != 0) {
1176 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1177 (this->k_numAllocPerRow_.extent (0) != numRows,
1178 std::invalid_argument,
"k_numAllocPerRow_ is allocated, that is, " 1179 "has nonzero length " << this->k_numAllocPerRow_.extent (0)
1180 <<
", but its length != numRows = " << numRows <<
".");
1198 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1199 (this->numAllocForAllRows_ ==
1200 Tpetra::Details::OrdinalTraits<size_t>::invalid (),
1201 std::invalid_argument,
"numAllocForAllRows_ has an invalid value, " 1202 "namely Tpetra::Details::OrdinalTraits<size_t>::invalid() = " <<
1203 Tpetra::Details::OrdinalTraits<size_t>::invalid () <<
".");
1210 this->k_rowPtrs_ = k_rowPtrs;
1212 const size_type numInds =
1213 Details::getEntryOnHost(this->k_rowPtrs_, numRows);
1214 if (lg == LocalIndices) {
1216 std::ostringstream os;
1217 os << *prefix <<
"Allocate local column indices " 1218 "k_lclInds1D_: " << numInds << endl;
1219 std::cerr << os.str();
1221 k_lclInds1D_ = lcl_col_inds_type (
"Tpetra::CrsGraph::ind", numInds);
1225 std::ostringstream os;
1226 os << *prefix <<
"Allocate global column indices " 1227 "k_gblInds1D_: " << numInds << endl;
1228 std::cerr << os.str();
1230 k_gblInds1D_ = gbl_col_inds_type (
"Tpetra::CrsGraph::ind", numInds);
1232 storageStatus_ = Details::STORAGE_1D_UNPACKED;
1234 this->indicesAreLocal_ = (lg == LocalIndices);
1235 this->indicesAreGlobal_ = (lg == GlobalIndices);
1238 using Kokkos::ViewAllocateWithoutInitializing;
1239 typedef decltype (k_numRowEntries_) row_ent_type;
1240 const char label[] =
"Tpetra::CrsGraph::numRowEntries";
1242 std::ostringstream os;
1243 os << *prefix <<
"Allocate k_numRowEntries_: " << numRows
1245 std::cerr << os.str();
1247 row_ent_type numRowEnt (ViewAllocateWithoutInitializing (label), numRows);
1249 this->k_numRowEntries_ = numRowEnt;
1253 this->numAllocForAllRows_ = 0;
1254 this->k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
1255 this->indicesAreAllocated_ =
true;
1258 this->checkInternalState ();
1260 catch (std::logic_error& e) {
1261 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1262 (
true, std::logic_error,
"At end of allocateIndices, " 1263 "checkInternalState threw std::logic_error: " 1266 catch (std::exception& e) {
1267 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1268 (
true, std::runtime_error,
"At end of allocateIndices, " 1269 "checkInternalState threw std::exception: " 1273 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1274 (
true, std::runtime_error,
"At end of allocateIndices, " 1275 "checkInternalState threw an exception " 1276 "not a subclass of std::exception.");
1280 std::ostringstream os;
1281 os << *prefix <<
"Done" << endl;
1282 std::cerr << os.str();
1286 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1287 Teuchos::ArrayView<const LocalOrdinal>
1288 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1291 using Kokkos::subview;
1292 typedef LocalOrdinal LO;
1294 Kokkos::MemoryUnmanaged> row_view_type;
1296 if (rowinfo.allocSize == 0) {
1297 return Teuchos::ArrayView<const LO> ();
1300 if (k_lclInds1D_.extent (0) != 0) {
1301 const size_t start = rowinfo.offset1D;
1302 const size_t len = rowinfo.allocSize;
1303 const std::pair<size_t, size_t> rng (start, start + len);
1309 row_view_type rowView = subview (row_view_type (k_lclInds1D_), rng);
1310 const LO*
const rowViewRaw = (len == 0) ?
nullptr : rowView.data ();
1311 return Teuchos::ArrayView<const LO> (rowViewRaw, len, Teuchos::RCP_DISABLE_NODE_LOOKUP);
1314 return Teuchos::ArrayView<const LO> ();
1319 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1323 LocalOrdinal& capacity,
1329 if (rowInfo.allocSize != 0 && k_lclInds1D_.extent (0) != 0) {
1331 if (rowInfo.offset1D + rowInfo.allocSize >
1332 static_cast<size_t> (k_lclInds1D_.extent (0))) {
1333 return static_cast<LocalOrdinal
> (-1);
1336 lclInds = k_lclInds1D_.data () + rowInfo.offset1D;
1337 capacity = rowInfo.allocSize;
1339 return static_cast<LocalOrdinal
> (0);
1342 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1343 Teuchos::ArrayView<LocalOrdinal>
1347 using Kokkos::subview;
1348 typedef LocalOrdinal LO;
1350 Kokkos::MemoryUnmanaged> row_view_type;
1352 if (rowinfo.allocSize == 0) {
1353 return Teuchos::ArrayView<LO> ();
1356 if (k_lclInds1D_.extent (0) != 0) {
1357 const size_t start = rowinfo.offset1D;
1358 const size_t len = rowinfo.allocSize;
1359 const std::pair<size_t, size_t> rng (start, start + len);
1365 row_view_type rowView = subview (row_view_type (k_lclInds1D_), rng);
1366 LO*
const rowViewRaw = (len == 0) ?
nullptr : rowView.data ();
1367 return Teuchos::ArrayView<LO> (rowViewRaw, len, Teuchos::RCP_DISABLE_NODE_LOOKUP);
1370 return Teuchos::ArrayView<LO> ();
1376 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1377 Kokkos::View<
const LocalOrdinal*,
1379 Kokkos::MemoryUnmanaged>
1383 typedef LocalOrdinal LO;
1384 typedef Kokkos::View<
const LO*, execution_space,
1385 Kokkos::MemoryUnmanaged> row_view_type;
1387 if (rowInfo.allocSize == 0) {
1388 return row_view_type ();
1391 if (k_lclInds1D_.extent (0) != 0) {
1392 const size_t start = rowInfo.offset1D;
1393 const size_t len = rowInfo.allocSize;
1394 const std::pair<size_t, size_t> rng (start, start + len);
1400 return Kokkos::subview (row_view_type (k_lclInds1D_), rng);
1403 return row_view_type ();
1409 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1410 Kokkos::View<LocalOrdinal*,
1411 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::execution_space,
1412 Kokkos::MemoryUnmanaged>
1413 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1414 getLocalKokkosRowViewNonConst (
const RowInfo& rowInfo)
1416 using row_view_type = Kokkos::View<LocalOrdinal*,
1417 execution_space, Kokkos::MemoryUnmanaged>;
1419 if (rowInfo.allocSize == 0) {
1420 return row_view_type ();
1423 if (k_lclInds1D_.extent (0) != 0) {
1424 const size_t start = rowInfo.offset1D;
1425 const size_t len = rowInfo.allocSize;
1426 const std::pair<size_t, size_t> rng (start, start + len);
1432 return Kokkos::subview (row_view_type (this->k_lclInds1D_), rng);
1435 return row_view_type ();
1441 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1442 Kokkos::View<
const GlobalOrdinal*,
1443 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::execution_space,
1444 Kokkos::MemoryUnmanaged>
1445 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1446 getGlobalKokkosRowView (
const RowInfo& rowinfo)
const 1448 using row_view_type = Kokkos::View<
const GlobalOrdinal*,
1449 execution_space, Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
1451 if (rowinfo.allocSize == 0) {
1452 return row_view_type ();
1455 if (this->k_gblInds1D_.extent (0) != 0) {
1456 const size_t start = rowinfo.offset1D;
1457 const size_t len = rowinfo.allocSize;
1458 const std::pair<size_t, size_t> rng (start, start + len);
1464 return Kokkos::subview (row_view_type (this->k_gblInds1D_), rng);
1467 return row_view_type ();
1473 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1474 Teuchos::ArrayView<const GlobalOrdinal>
1475 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1480 Teuchos::ArrayView<const GO> view;
1481 if (rowinfo.allocSize > 0 && k_gblInds1D_.extent (0) != 0) {
1483 std::make_pair (rowinfo.offset1D,
1484 rowinfo.offset1D + rowinfo.allocSize);
1490 using row_view_type = Kokkos::View<
const GO*,
1492 row_view_type k_gblInds1D_unmanaged = k_gblInds1D_;
1493 using Kokkos::Compat::getConstArrayView;
1494 using Kokkos::subview;
1495 view = getConstArrayView (subview (k_gblInds1D_unmanaged, rng));
1501 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1505 LocalOrdinal& capacity,
1511 if (rowInfo.allocSize != 0 && k_gblInds1D_.extent (0) != 0) {
1513 if (rowInfo.offset1D + rowInfo.allocSize >
1514 static_cast<size_t> (k_gblInds1D_.extent (0))) {
1515 return static_cast<LocalOrdinal
> (-1);
1518 gblInds = k_gblInds1D_.data () + rowInfo.offset1D;
1519 capacity = rowInfo.allocSize;
1521 return static_cast<LocalOrdinal
> (0);
1525 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1526 Teuchos::ArrayView<GlobalOrdinal>
1532 Teuchos::ArrayView<GO> view;
1533 if (rowinfo.allocSize > 0 && k_gblInds1D_.extent (0) != 0) {
1535 std::make_pair (rowinfo.offset1D,
1536 rowinfo.offset1D + rowinfo.allocSize);
1543 Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
1544 row_view_type k_gblInds1D_unmanaged = k_gblInds1D_;
1545 using Kokkos::Compat::getArrayView;
1546 using Kokkos::subview;
1547 view = getArrayView (subview (k_gblInds1D_unmanaged, rng));
1553 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1558 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1560 if (this->rowMap_.is_null () || ! this->rowMap_->isNodeLocalElement (myRow)) {
1561 ret.localRow = STINV;
1564 ret.offset1D = STINV;
1568 ret.localRow =
static_cast<size_t> (myRow);
1569 if (this->indicesAreAllocated ()) {
1571 if (this->k_rowPtrs_.extent (0) == 0) {
1576 ret.offset1D = this->k_rowPtrs_(myRow);
1577 ret.allocSize = this->k_rowPtrs_(myRow+1) - this->k_rowPtrs_(myRow);
1580 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
1582 this->k_numRowEntries_(myRow);
1588 ret.allocSize = (this->k_numAllocPerRow_.extent (0) != 0) ?
1589 this->k_numAllocPerRow_(myRow) :
1590 this->numAllocForAllRows_;
1592 ret.offset1D = STINV;
1599 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1604 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1606 if (this->rowMap_.is_null ()) {
1607 ret.localRow = STINV;
1610 ret.offset1D = STINV;
1613 const LocalOrdinal myRow = this->rowMap_->getLocalElement (gblRow);
1614 if (myRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid ()) {
1615 ret.localRow = STINV;
1618 ret.offset1D = STINV;
1622 ret.localRow =
static_cast<size_t> (myRow);
1623 if (this->indicesAreAllocated ()) {
1627 if (this->k_rowPtrs_.extent (0) == 0) {
1632 ret.offset1D = this->k_rowPtrs_(myRow);
1633 ret.allocSize = this->k_rowPtrs_(myRow+1) - this->k_rowPtrs_(myRow);
1636 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
1638 this->k_numRowEntries_(myRow);
1644 ret.allocSize = (this->k_numAllocPerRow_.extent (0) != 0) ?
1645 this->k_numAllocPerRow_(myRow) :
1646 this->numAllocForAllRows_;
1648 ret.offset1D = STINV;
1655 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1660 using Teuchos::OrdinalTraits;
1661 typedef LocalOrdinal LO;
1662 typedef GlobalOrdinal GO;
1668 static_assert (
sizeof (GlobalOrdinal) >=
sizeof (LocalOrdinal),
1669 "Tpetra::CrsGraph: sizeof(GlobalOrdinal) must be >= sizeof(LocalOrdinal).");
1672 static_assert (
sizeof (
size_t) >=
sizeof (LocalOrdinal),
1673 "Tpetra::CrsGraph: sizeof(size_t) must be >= sizeof(LocalOrdinal).");
1674 static_assert (
sizeof(GST) >=
sizeof(
size_t),
1675 "Tpetra::CrsGraph: sizeof(Tpetra::global_size_t) must be >= sizeof(size_t).");
1683 const char msg[] =
"Tpetra::CrsGraph: Object cannot be created with the " 1684 "given template arguments: size assumptions are not valid.";
1685 TEUCHOS_TEST_FOR_EXCEPTION(
1686 static_cast<size_t> (Teuchos::OrdinalTraits<LO>::max ()) > Teuchos::OrdinalTraits<size_t>::max (),
1687 std::runtime_error, msg);
1688 TEUCHOS_TEST_FOR_EXCEPTION(
1689 static_cast<GST> (Teuchos::OrdinalTraits<LO>::max ()) > static_cast<GST> (Teuchos::OrdinalTraits<GO>::max ()),
1690 std::runtime_error, msg);
1691 TEUCHOS_TEST_FOR_EXCEPTION(
1692 static_cast<size_t> (Teuchos::OrdinalTraits<GO>::max ()) > Teuchos::OrdinalTraits<GST>::max(),
1693 std::runtime_error, msg);
1694 TEUCHOS_TEST_FOR_EXCEPTION(
1695 Teuchos::OrdinalTraits<size_t>::max () > Teuchos::OrdinalTraits<GST>::max (),
1696 std::runtime_error, msg);
1700 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1702 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1704 const SLocalGlobalViews &newInds,
1705 const ELocalGlobal lg,
1706 const ELocalGlobal I)
1708 using Teuchos::ArrayView;
1709 typedef LocalOrdinal LO;
1710 typedef GlobalOrdinal GO;
1711 const char tfecfFuncName[] =
"insertIndices: ";
1713 size_t oldNumEnt = 0;
1715 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1716 (lg != GlobalIndices && lg != LocalIndices, std::invalid_argument,
1717 "lg must be either GlobalIndices or LocalIndices.");
1718 oldNumEnt = this->getNumEntriesInLocalRow (rowinfo.localRow);
1721 size_t numNewInds = 0;
1722 if (lg == GlobalIndices) {
1723 ArrayView<const GO> new_ginds = newInds.ginds;
1724 numNewInds = new_ginds.size();
1725 if (I == GlobalIndices) {
1726 ArrayView<GO> gind_view = this->getGlobalViewNonConst (rowinfo);
1728 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1729 (static_cast<size_t> (gind_view.size ()) <
1730 rowinfo.numEntries + numNewInds, std::logic_error,
1731 "gind_view.size() = " << gind_view.size ()
1732 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1733 <<
") + numNewInds (= " << numNewInds <<
").");
1735 GO*
const gblColInds_out = gind_view.getRawPtr () + rowinfo.numEntries;
1736 for (
size_t k = 0; k < numNewInds; ++k) {
1737 gblColInds_out[k] = new_ginds[k];
1740 else if (I == LocalIndices) {
1741 ArrayView<LO> lind_view = this->getLocalViewNonConst (rowinfo);
1743 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1744 (static_cast<size_t> (lind_view.size ()) <
1745 rowinfo.numEntries + numNewInds, std::logic_error,
1746 "lind_view.size() = " << lind_view.size ()
1747 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1748 <<
") + numNewInds (= " << numNewInds <<
").");
1750 LO*
const lclColInds_out = lind_view.getRawPtr () + rowinfo.numEntries;
1751 for (
size_t k = 0; k < numNewInds; ++k) {
1752 lclColInds_out[k] = colMap_->getLocalElement (new_ginds[k]);
1756 else if (lg == LocalIndices) {
1757 ArrayView<const LO> new_linds = newInds.linds;
1758 numNewInds = new_linds.size();
1759 if (I == LocalIndices) {
1760 ArrayView<LO> lind_view = this->getLocalViewNonConst (rowinfo);
1762 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1763 (static_cast<size_t> (lind_view.size ()) <
1764 rowinfo.numEntries + numNewInds, std::logic_error,
1765 "lind_view.size() = " << lind_view.size ()
1766 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1767 <<
") + numNewInds (= " << numNewInds <<
").");
1769 LO*
const lclColInds_out = lind_view.getRawPtr () + rowinfo.numEntries;
1770 for (
size_t k = 0; k < numNewInds; ++k) {
1771 lclColInds_out[k] = new_linds[k];
1774 else if (I == GlobalIndices) {
1775 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1776 (
true, std::logic_error,
"The case where the input indices are local " 1777 "and the indices to write are global (lg=LocalIndices, I=" 1778 "GlobalIndices) is not implemented, because it does not make sense." 1779 << std::endl <<
"If you have correct local column indices, that " 1780 "means the graph has a column Map. In that case, you should be " 1781 "storing local indices.");
1785 rowinfo.numEntries += numNewInds;
1786 this->k_numRowEntries_(rowinfo.localRow) += numNewInds;
1787 this->setLocallyModified ();
1790 const size_t chkNewNumEnt =
1791 this->getNumEntriesInLocalRow (rowinfo.localRow);
1792 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1793 (chkNewNumEnt != oldNumEnt + numNewInds, std::logic_error,
1794 "chkNewNumEnt = " << chkNewNumEnt
1795 <<
" != oldNumEnt (= " << oldNumEnt
1796 <<
") + numNewInds (= " << numNewInds <<
").");
1802 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1806 const GlobalOrdinal inputGblColInds[],
1807 const size_t numInputInds)
1809 return this->insertGlobalIndicesImpl (this->getRowInfo (lclRow),
1810 inputGblColInds, numInputInds);
1813 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1817 const GlobalOrdinal inputGblColInds[],
1818 const size_t numInputInds,
1819 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
1823 using Kokkos::subview;
1824 using Kokkos::MemoryUnmanaged;
1825 using Teuchos::ArrayView;
1826 using LO = LocalOrdinal;
1827 using GO = GlobalOrdinal;
1828 const char tfecfFuncName[] =
"insertGlobalIndicesImpl: ";
1829 const LO lclRow =
static_cast<LO
> (rowInfo.localRow);
1831 auto numEntries = rowInfo.numEntries;
1832 using inp_view_type = View<const GO*, execution_space, MemoryUnmanaged>;
1833 inp_view_type inputInds(inputGblColInds, numInputInds);
1835 this->k_gblInds1D_, numEntries, inputInds, fun);
1837 const bool insertFailed =
1838 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1840 constexpr
size_t ONE (1);
1841 const int myRank = this->getComm()->getRank();
1842 std::ostringstream os;
1844 os <<
"Proc " << myRank <<
": Not enough capacity to insert " 1846 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1847 <<
" into local row " << lclRow <<
", which currently has " 1848 << rowInfo.numEntries
1849 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1850 <<
" and total allocation size " << rowInfo.allocSize
1852 const size_t maxNumToPrint =
1853 Details::Behavior::verbosePrintCountThreshold();
1854 ArrayView<const GO> inputGblColIndsView(inputGblColInds,
1857 "column indices", maxNumToPrint);
1859 const GO*
const curGblColInds =
1860 k_gblInds1D_.data() + rowInfo.offset1D;
1861 ArrayView<const GO> curGblColIndsView(curGblColInds,
1862 rowInfo.numEntries);
1864 "column indices", maxNumToPrint);
1865 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1866 (
true, std::runtime_error, os.str());
1869 this->k_numRowEntries_(lclRow) += numInserted;
1870 this->setLocallyModified();
1875 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1879 const Teuchos::ArrayView<const LocalOrdinal>& indices,
1880 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
1882 using Kokkos::MemoryUnmanaged;
1883 using Kokkos::subview;
1885 using LO = LocalOrdinal;
1886 const char tfecfFuncName[] =
"insertLocallIndicesImpl: ";
1888 const RowInfo rowInfo = this->getRowInfo(myRow);
1890 size_t numNewInds = 0;
1891 size_t newNumEntries = 0;
1893 auto numEntries = rowInfo.numEntries;
1895 using inp_view_type = View<const LO*, Kokkos::HostSpace, MemoryUnmanaged>;
1896 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1898 this->k_lclInds1D_, numEntries, inputInds, fun);
1900 const bool insertFailed =
1901 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1903 constexpr
size_t ONE (1);
1904 const size_t numInputInds(indices.size());
1905 const int myRank = this->getComm()->getRank();
1906 std::ostringstream os;
1907 os <<
"On MPI Process " << myRank <<
": Not enough capacity to " 1908 "insert " << numInputInds
1909 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1910 <<
" into local row " << myRow <<
", which currently has " 1911 << rowInfo.numEntries
1912 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1913 <<
" and total allocation size " << rowInfo.allocSize <<
".";
1914 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1915 (
true, std::runtime_error, os.str());
1917 numNewInds = numInserted;
1918 newNumEntries = rowInfo.numEntries + numNewInds;
1920 this->k_numRowEntries_(myRow) += numNewInds;
1921 this->setLocallyModified ();
1924 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow (myRow);
1925 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1926 (chkNewNumEntries != newNumEntries, std::logic_error,
1927 "getNumEntriesInLocalRow(" << myRow <<
") = " << chkNewNumEntries
1928 <<
" != newNumEntries = " << newNumEntries
1929 <<
". Please report this bug to the Tpetra developers.");
1934 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1936 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1938 const Teuchos::ArrayView<const LocalOrdinal>& indices,
1939 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
const 1941 using LO = LocalOrdinal;
1942 using inp_view_type = Kokkos::View<
const LO*, Kokkos::HostSpace,
1943 Kokkos::MemoryUnmanaged>;
1944 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1946 size_t numFound = 0;
1947 LO lclRow = rowInfo.localRow;
1948 if (this->isLocallyIndexed())
1951 this->k_lclInds1D_, inputInds, fun);
1953 else if (this->isGloballyIndexed())
1955 if (this->colMap_.is_null())
1956 return Teuchos::OrdinalTraits<size_t>::invalid();
1957 const auto& colMap = *(this->colMap_);
1958 auto map = [&](LO
const lclInd){
return colMap.getGlobalElement(lclInd);};
1960 this->k_gblInds1D_, inputInds, map, fun);
1966 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1970 const Teuchos::ArrayView<const GlobalOrdinal>& indices,
1971 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
const 1973 using GO = GlobalOrdinal;
1975 using Kokkos::MemoryUnmanaged;
1976 auto invalidCount = Teuchos::OrdinalTraits<size_t>::invalid();
1978 using inp_view_type = View<const GO*, execution_space, MemoryUnmanaged>;
1979 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1981 size_t numFound = 0;
1982 LocalOrdinal lclRow = rowInfo.localRow;
1983 if (this->isLocallyIndexed())
1985 if (this->colMap_.is_null())
1986 return invalidCount;
1987 const auto& colMap = *(this->colMap_);
1988 auto map = [&](GO
const gblInd){
return colMap.getLocalElement(gblInd);};
1990 this->k_lclInds1D_, inputInds, map, fun);
1992 else if (this->isGloballyIndexed())
1995 this->k_gblInds1D_, inputInds, fun);
2001 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2003 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
2008 const size_t origNumEnt = rowInfo.numEntries;
2009 if (origNumEnt != Tpetra::Details::OrdinalTraits<size_t>::invalid () &&
2011 auto lclColInds = this->getLocalKokkosRowViewNonConst (rowInfo);
2013 LocalOrdinal*
const lclColIndsRaw = lclColInds.data ();
2016 std::sort (lclColIndsRaw, lclColIndsRaw + origNumEnt);
2020 LocalOrdinal*
const beg = lclColIndsRaw;
2021 LocalOrdinal*
const end = beg + rowInfo.numEntries;
2023 LocalOrdinal*
const newend = std::unique (beg, end);
2024 const size_t newNumEnt = newend - beg;
2027 this->k_numRowEntries_(rowInfo.localRow) = newNumEnt;
2028 return origNumEnt - newNumEnt;
2031 return static_cast<size_t> (0);
2035 return static_cast<size_t> (0);
2040 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2044 const Teuchos::RCP<const map_type>& rangeMap)
2047 if (domainMap_ != domainMap) {
2048 domainMap_ = domainMap;
2049 importer_ = Teuchos::null;
2051 if (rangeMap_ != rangeMap) {
2052 rangeMap_ = rangeMap;
2053 exporter_ = Teuchos::null;
2058 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2063 const auto INV = Teuchos::OrdinalTraits<global_size_t>::invalid();
2065 globalNumEntries_ = INV;
2066 globalMaxNumRowEntries_ = INV;
2067 haveGlobalConstants_ =
false;
2071 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2073 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
2074 checkInternalState ()
const 2078 const char tfecfFuncName[] =
"checkInternalState: ";
2079 const char suffix[] =
" Please report this bug to the Tpetra developers.";
2081 std::unique_ptr<std::string> prefix;
2083 prefix = this->createPrefix(
"CrsGraph",
"checkInternalState");
2084 std::ostringstream os;
2085 os << *prefix <<
"Start" << endl;
2086 std::cerr << os.str();
2089 const global_size_t GSTI = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2095 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2096 (this->rowMap_.is_null (), std::logic_error,
2097 "Row Map is null." << suffix);
2100 const LocalOrdinal lclNumRows =
2101 static_cast<LocalOrdinal
> (this->getNodeNumRows ());
2103 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2104 (this->isFillActive () == this->isFillComplete (), std::logic_error,
2105 "Graph cannot be both fill active and fill complete." << suffix);
2106 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2107 (this->isFillComplete () &&
2108 (this->colMap_.is_null () ||
2109 this->rangeMap_.is_null () ||
2110 this->domainMap_.is_null ()),
2112 "Graph is full complete, but at least one of {column, range, domain} " 2113 "Map is null." << suffix);
2114 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2115 (this->isStorageOptimized () && ! this->indicesAreAllocated (),
2116 std::logic_error,
"Storage is optimized, but indices are not " 2117 "allocated, not even trivially." << suffix);
2119 size_t nodeAllocSize = 0;
2121 nodeAllocSize = this->getNodeAllocationSize ();
2123 catch (std::logic_error& e) {
2124 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2125 (
true, std::runtime_error,
"getNodeAllocationSize threw " 2126 "std::logic_error: " << e.what ());
2128 catch (std::exception& e) {
2129 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2130 (
true, std::runtime_error,
"getNodeAllocationSize threw an " 2131 "std::exception: " << e.what ());
2134 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2135 (
true, std::runtime_error,
"getNodeAllocationSize threw an exception " 2136 "not a subclass of std::exception.");
2139 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2140 (this->isStorageOptimized () &&
2141 nodeAllocSize != this->getNodeNumEntries (),
2142 std::logic_error,
"Storage is optimized, but " 2143 "this->getNodeAllocationSize() = " << nodeAllocSize
2144 <<
" != this->getNodeNumEntries() = " << this->getNodeNumEntries ()
2146 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2147 (! this->haveGlobalConstants_ &&
2148 (this->globalNumEntries_ != GSTI ||
2149 this->globalMaxNumRowEntries_ != GSTI),
2150 std::logic_error,
"Graph claims not to have global constants, but " 2151 "some of the global constants are not marked as invalid." << suffix);
2152 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2153 (this->haveGlobalConstants_ &&
2154 (this->globalNumEntries_ == GSTI ||
2155 this->globalMaxNumRowEntries_ == GSTI),
2156 std::logic_error,
"Graph claims to have global constants, but " 2157 "some of them are marked as invalid." << suffix);
2158 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2159 (this->haveGlobalConstants_ &&
2160 (this->globalNumEntries_ < this->getNodeNumEntries () ||
2161 this->globalMaxNumRowEntries_ < this->nodeMaxNumRowEntries_),
2162 std::logic_error,
"Graph claims to have global constants, and " 2163 "all of the values of the global constants are valid, but " 2164 "some of the local constants are greater than " 2165 "their corresponding global constants." << suffix);
2166 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2167 (this->indicesAreAllocated () &&
2168 (this->numAllocForAllRows_ != 0 ||
2169 this->k_numAllocPerRow_.extent (0) != 0),
2170 std::logic_error,
"The graph claims that its indices are allocated, but " 2171 "either numAllocForAllRows_ (= " << this->numAllocForAllRows_ <<
") is " 2172 "nonzero, or k_numAllocPerRow_ has nonzero dimension. In other words, " 2173 "the graph is supposed to release its \"allocation specifications\" " 2174 "when it allocates its indices." << suffix);
2175 if (isGloballyIndexed() && k_rowPtrs_.extent(0) != 0) {
2176 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2177 (
size_t(k_rowPtrs_.extent(0)) !=
size_t(lclNumRows + 1),
2178 std::logic_error,
"The graph is globally indexed and " 2179 "k_rowPtrs_ has nonzero size " << k_rowPtrs_.extent(0)
2180 <<
", but that size does not equal lclNumRows+1 = " 2181 << (lclNumRows+1) <<
"." << suffix);
2182 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2183 (k_rowPtrs_(lclNumRows) !=
size_t(k_gblInds1D_.extent(0)),
2184 std::logic_error,
"The graph is globally indexed and " 2185 "k_rowPtrs_ has nonzero size " << k_rowPtrs_.extent(0)
2186 <<
", but k_rowPtrs_(lclNumRows=" << lclNumRows <<
")=" 2187 << k_rowPtrs_(lclNumRows) <<
" != k_gblInds1D_.extent(0)=" 2188 << k_gblInds1D_.extent(0) <<
"." << suffix);
2190 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2191 (this->isLocallyIndexed () &&
2192 this->k_rowPtrs_.extent (0) != 0 &&
2193 (
static_cast<size_t> (k_rowPtrs_.extent (0)) != static_cast<size_t> (lclNumRows + 1) ||
2194 this->k_rowPtrs_(lclNumRows) !=
static_cast<size_t> (this->k_lclInds1D_.extent (0))),
2195 std::logic_error,
"If k_rowPtrs_ has nonzero size and " 2196 "the graph is locally indexed, then " 2197 "k_rowPtrs_ must have N+1 rows, and " 2198 "k_rowPtrs_(N) must equal k_lclInds1D_.extent(0)." << suffix);
2200 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2201 (this->indicesAreAllocated () &&
2202 nodeAllocSize > 0 &&
2203 this->k_lclInds1D_.extent (0) == 0 &&
2204 this->k_gblInds1D_.extent (0) == 0,
2205 std::logic_error,
"Graph is allocated nontrivially, but " 2206 "but 1-D allocations are not present." << suffix);
2208 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2209 (! this->indicesAreAllocated () &&
2210 ((this->k_rowPtrs_.extent (0) != 0 ||
2211 this->k_numRowEntries_.extent (0) != 0) ||
2212 this->k_lclInds1D_.extent (0) != 0 ||
2213 this->k_gblInds1D_.extent (0) != 0),
2214 std::logic_error,
"If indices are not allocated, " 2215 "then none of the buffers should be." << suffix);
2219 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2220 ((this->indicesAreLocal_ || this->indicesAreGlobal_) &&
2221 ! this->indicesAreAllocated_,
2222 std::logic_error,
"Indices may be local or global only if they are " 2223 "allocated." << suffix);
2224 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2225 (this->indicesAreLocal_ && this->indicesAreGlobal_,
2226 std::logic_error,
"Indices may not be both local and global." << suffix);
2227 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2228 (indicesAreLocal_ && k_gblInds1D_.extent (0) != 0,
2229 std::logic_error,
"Indices are local, but " 2230 "k_gblInds1D_.extent(0) (= " << k_gblInds1D_.extent (0)
2231 <<
") != 0. In other words, if indices are local, then " 2232 "allocations of global indices should not be present." 2234 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2235 (indicesAreGlobal_ && k_lclInds1D_.extent (0) != 0,
2236 std::logic_error,
"Indices are global, but " 2237 "k_lclInds1D_.extent(0) (= " << k_lclInds1D_.extent(0)
2238 <<
") != 0. In other words, if indices are global, " 2239 "then allocations for local indices should not be present." 2241 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2242 (indicesAreLocal_ && nodeAllocSize > 0 &&
2243 k_lclInds1D_.extent (0) == 0 && getNodeNumRows () > 0,
2244 std::logic_error,
"Indices are local and " 2245 "getNodeAllocationSize() = " << nodeAllocSize <<
" > 0, but " 2246 "k_lclInds1D_.extent(0) = 0 and getNodeNumRows() = " 2247 << getNodeNumRows () <<
" > 0." << suffix);
2248 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2249 (indicesAreGlobal_ && nodeAllocSize > 0 &&
2250 k_gblInds1D_.extent (0) == 0 && getNodeNumRows () > 0,
2251 std::logic_error,
"Indices are global and " 2252 "getNodeAllocationSize() = " << nodeAllocSize <<
" > 0, but " 2253 "k_gblInds1D_.extent(0) = 0 and getNodeNumRows() = " 2254 << getNodeNumRows () <<
" > 0." << suffix);
2256 if (this->indicesAreAllocated () &&
2257 this->k_rowPtrs_.extent (0) != 0) {
2258 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2259 (static_cast<size_t> (this->k_rowPtrs_.extent (0)) !=
2260 this->getNodeNumRows () + 1,
2261 std::logic_error,
"Indices are allocated and " 2262 "k_rowPtrs_ has nonzero length, but k_rowPtrs_.extent(0) = " 2263 << this->k_rowPtrs_.extent (0) <<
" != getNodeNumRows()+1 = " 2264 << (this->getNodeNumRows () + 1) <<
"." << suffix);
2265 const size_t actualNumAllocated =
2266 ::Tpetra::Details::getEntryOnHost (this->k_rowPtrs_, this->getNodeNumRows ());
2267 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2268 (this->isLocallyIndexed () &&
2269 static_cast<size_t> (this->k_lclInds1D_.extent (0)) != actualNumAllocated,
2270 std::logic_error,
"Graph is locally indexed, indices are " 2271 "are allocated, and k_rowPtrs_ has nonzero length, but " 2272 "k_lclInds1D_.extent(0) = " << this->k_lclInds1D_.extent (0)
2273 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2274 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2275 (this->isGloballyIndexed () &&
2276 static_cast<size_t> (this->k_gblInds1D_.extent (0)) != actualNumAllocated,
2277 std::logic_error,
"Graph is globally indexed, indices " 2278 "are allocated, and k_rowPtrs_ has nonzero length, but " 2279 "k_gblInds1D_.extent(0) = " << this->k_gblInds1D_.extent (0)
2280 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2284 std::ostringstream os;
2285 os << *prefix <<
"Done" << endl;
2286 std::cerr << os.str();
2292 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2297 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (globalRow);
2298 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2299 return Teuchos::OrdinalTraits<size_t>::invalid ();
2302 return rowInfo.numEntries;
2307 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2312 const RowInfo rowInfo = this->getRowInfo (localRow);
2313 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2314 return Teuchos::OrdinalTraits<size_t>::invalid ();
2317 return rowInfo.numEntries;
2322 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2327 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (globalRow);
2328 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2329 return Teuchos::OrdinalTraits<size_t>::invalid ();
2332 return rowInfo.allocSize;
2337 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2342 const RowInfo rowInfo = this->getRowInfo (localRow);
2343 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2344 return Teuchos::OrdinalTraits<size_t>::invalid ();
2347 return rowInfo.allocSize;
2352 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2353 Teuchos::ArrayRCP<const size_t>
2357 using Kokkos::ViewAllocateWithoutInitializing;
2358 using Kokkos::create_mirror_view;
2359 using Teuchos::ArrayRCP;
2360 typedef typename local_graph_type::row_map_type row_map_type;
2361 typedef typename row_map_type::non_const_value_type row_offset_type;
2362 const char prefix[] =
"Tpetra::CrsGraph::getNodeRowPtrs: ";
2363 const char suffix[] =
" Please report this bug to the Tpetra developers.";
2365 const size_t size = k_rowPtrs_.extent (0);
2366 constexpr
bool same = std::is_same<size_t, row_offset_type>::value;
2369 return ArrayRCP<const size_t> ();
2372 ArrayRCP<const row_offset_type> ptr_rot;
2373 ArrayRCP<const size_t> ptr_st;
2378 typename row_map_type::HostMirror ptr_h = create_mirror_view (k_rowPtrs_);
2381 TEUCHOS_TEST_FOR_EXCEPTION
2382 (ptr_h.extent (0) != k_rowPtrs_.extent (0), std::logic_error,
2383 prefix <<
"size_t == row_offset_type, but ptr_h.extent(0) = " 2384 << ptr_h.extent (0) <<
" != k_rowPtrs_.extent(0) = " 2385 << k_rowPtrs_.extent (0) <<
".");
2386 TEUCHOS_TEST_FOR_EXCEPTION
2387 (same && size != 0 && k_rowPtrs_.data () ==
nullptr, std::logic_error,
2388 prefix <<
"size_t == row_offset_type and k_rowPtrs_.extent(0) = " 2389 << size <<
" != 0, but k_rowPtrs_.data() == nullptr." << suffix);
2390 TEUCHOS_TEST_FOR_EXCEPTION
2391 (same && size != 0 && ptr_h.data () ==
nullptr, std::logic_error,
2392 prefix <<
"size_t == row_offset_type and k_rowPtrs_.extent(0) = " 2393 << size <<
" != 0, but create_mirror_view(k_rowPtrs_).data() " 2394 "== nullptr." << suffix);
2396 ptr_rot = Kokkos::Compat::persistingView (ptr_h);
2399 typedef Kokkos::View<size_t*, device_type> ret_view_type;
2400 ret_view_type ptr_d (ViewAllocateWithoutInitializing (
"ptr"), size);
2402 typename ret_view_type::HostMirror ptr_h = create_mirror_view (ptr_d);
2404 ptr_st = Kokkos::Compat::persistingView (ptr_h);
2407 TEUCHOS_TEST_FOR_EXCEPTION
2408 (same && size != 0 && ptr_rot.is_null (), std::logic_error,
2409 prefix <<
"size_t == row_offset_type and size = " << size
2410 <<
" != 0, but ptr_rot is null." << suffix);
2411 TEUCHOS_TEST_FOR_EXCEPTION
2412 (! same && size != 0 && ptr_st.is_null (), std::logic_error,
2413 prefix <<
"size_t != row_offset_type and size = " << size
2414 <<
" != 0, but ptr_st is null." << suffix);
2419 ArrayRCP<const size_t> retval =
2420 Kokkos::Impl::if_c<same,
2421 ArrayRCP<const row_offset_type>,
2422 ArrayRCP<const size_t> >::select (ptr_rot, ptr_st);
2424 TEUCHOS_TEST_FOR_EXCEPTION
2425 (size != 0 && retval.is_null (), std::logic_error,
2426 prefix <<
"size = " << size <<
" != 0, but retval is null." << suffix);
2432 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2433 Teuchos::ArrayRCP<const LocalOrdinal>
2437 return Kokkos::Compat::persistingView (k_lclInds1D_);
2441 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2445 const Teuchos::ArrayView<LocalOrdinal>&indices,
2446 size_t& numEntries)
const 2448 using Teuchos::ArrayView;
2449 typedef LocalOrdinal LO;
2450 typedef GlobalOrdinal GO;
2451 const char tfecfFuncName[] =
"getLocalRowCopy: ";
2453 TEUCHOS_TEST_FOR_EXCEPTION(
2454 isGloballyIndexed () && ! hasColMap (), std::runtime_error,
2455 "Tpetra::CrsGraph::getLocalRowCopy: The graph is globally indexed and " 2456 "does not have a column Map yet. That means we don't have local indices " 2457 "for columns yet, so it doesn't make sense to call this method. If the " 2458 "graph doesn't have a column Map yet, you should call fillComplete on " 2463 const RowInfo rowinfo = this->getRowInfo (localRow);
2465 const size_t theNumEntries = rowinfo.numEntries;
2466 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2467 (static_cast<size_t> (indices.size ()) < theNumEntries, std::runtime_error,
2468 "Specified storage (size==" << indices.size () <<
") does not suffice " 2469 "to hold all " << theNumEntries <<
" entry/ies for this row.");
2470 numEntries = theNumEntries;
2472 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
2473 if (isLocallyIndexed ()) {
2474 ArrayView<const LO> lview = getLocalView (rowinfo);
2475 for (
size_t j = 0; j < theNumEntries; ++j) {
2476 indices[j] = lview[j];
2479 else if (isGloballyIndexed ()) {
2480 ArrayView<const GO> gview = getGlobalView (rowinfo);
2481 for (
size_t j = 0; j < theNumEntries; ++j) {
2482 indices[j] = colMap_->getLocalElement (gview[j]);
2489 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2493 const Teuchos::ArrayView<GlobalOrdinal>& indices,
2494 size_t& numEntries)
const 2496 using Teuchos::ArrayView;
2497 const char tfecfFuncName[] =
"getGlobalRowCopy: ";
2501 const RowInfo rowinfo = getRowInfoFromGlobalRowIndex (globalRow);
2502 const size_t theNumEntries = rowinfo.numEntries;
2503 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2504 static_cast<size_t> (indices.size ()) < theNumEntries, std::runtime_error,
2505 "Specified storage (size==" << indices.size () <<
") does not suffice " 2506 "to hold all " << theNumEntries <<
" entry/ies for this row.");
2507 numEntries = theNumEntries;
2509 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
2510 if (isLocallyIndexed ()) {
2511 ArrayView<const LocalOrdinal> lview = getLocalView (rowinfo);
2512 for (
size_t j = 0; j < theNumEntries; ++j) {
2513 indices[j] = colMap_->getGlobalElement (lview[j]);
2516 else if (isGloballyIndexed ()) {
2517 ArrayView<const GlobalOrdinal> gview = getGlobalView (rowinfo);
2518 for (
size_t j = 0; j < theNumEntries; ++j) {
2519 indices[j] = gview[j];
2526 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2530 Teuchos::ArrayView<const LocalOrdinal>& indices)
const 2532 const char tfecfFuncName[] =
"getLocalRowView: ";
2534 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2535 (isGloballyIndexed (), std::runtime_error,
"The graph's indices are " 2536 "currently stored as global indices, so we cannot return a view with " 2537 "local column indices, whether or not the graph has a column Map. If " 2538 "the graph _does_ have a column Map, use getLocalRowCopy() instead.");
2542 const RowInfo rowInfo = getRowInfo (localRow);
2543 indices = Teuchos::null;
2544 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
2545 rowInfo.numEntries > 0) {
2546 indices = this->getLocalView (rowInfo);
2551 indices = indices (0, rowInfo.numEntries);
2555 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2556 (static_cast<size_t> (indices.size ()) !=
2557 getNumEntriesInLocalRow (localRow), std::logic_error,
"indices.size() " 2558 "= " << indices.size () <<
" != getNumEntriesInLocalRow(localRow=" <<
2559 localRow <<
") = " << getNumEntriesInLocalRow (localRow) <<
2560 ". Please report this bug to the Tpetra developers.");
2565 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2569 Teuchos::ArrayView<const GlobalOrdinal>& indices)
const 2571 const char tfecfFuncName[] =
"getGlobalRowView: ";
2573 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2574 (isLocallyIndexed (), std::runtime_error,
"The graph's indices are " 2575 "currently stored as local indices, so we cannot return a view with " 2576 "global column indices. Use getGlobalRowCopy() instead.");
2580 const RowInfo rowInfo = getRowInfoFromGlobalRowIndex (globalRow);
2581 indices = Teuchos::null;
2582 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
2583 rowInfo.numEntries > 0) {
2584 indices = (this->getGlobalView (rowInfo)) (0, rowInfo.numEntries);
2588 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2589 (static_cast<size_t> (indices.size ()) !=
2590 getNumEntriesInGlobalRow (globalRow),
2591 std::logic_error,
"indices.size() = " << indices.size ()
2592 <<
" != getNumEntriesInGlobalRow(globalRow=" << globalRow <<
") = " 2593 << getNumEntriesInGlobalRow (globalRow)
2594 <<
". Please report this bug to the Tpetra developers.");
2599 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2603 const Teuchos::ArrayView<const LocalOrdinal>& indices)
2605 const char tfecfFuncName[] =
"insertLocalIndices: ";
2607 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2608 (! isFillActive (), std::runtime_error,
"Fill must be active.");
2609 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2610 (isGloballyIndexed (), std::runtime_error,
2611 "Graph indices are global; use insertGlobalIndices().");
2612 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2613 (! hasColMap (), std::runtime_error,
2614 "Cannot insert local indices without a column Map.");
2615 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2616 (! rowMap_->isNodeLocalElement (localRow), std::runtime_error,
2617 "Local row index " << localRow <<
" is not in the row Map " 2618 "on the calling process.");
2619 if (! indicesAreAllocated ()) {
2620 allocateIndices (LocalIndices, verbose_);
2629 using Teuchos::Array;
2630 using Teuchos::toString;
2632 typedef typename Teuchos::ArrayView<const LocalOrdinal>::size_type size_type;
2635 Array<LocalOrdinal> badColInds;
2636 bool allInColMap =
true;
2637 for (size_type k = 0; k < indices.size (); ++k) {
2639 allInColMap =
false;
2640 badColInds.push_back (indices[k]);
2643 if (! allInColMap) {
2644 std::ostringstream os;
2645 os <<
"Tpetra::CrsGraph::insertLocalIndices: You attempted to insert " 2646 "entries in owned row " << localRow <<
", at the following column " 2647 "indices: " << toString (indices) <<
"." << endl;
2648 os <<
"Of those, the following indices are not in the column Map on " 2649 "this process: " << toString (badColInds) <<
"." << endl <<
"Since " 2650 "the graph has a column Map already, it is invalid to insert entries " 2651 "at those locations.";
2652 TEUCHOS_TEST_FOR_EXCEPTION(! allInColMap, std::invalid_argument, os.str ());
2657 insertLocalIndicesImpl (localRow, indices);
2660 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2661 (! indicesAreAllocated () || ! isLocallyIndexed (), std::logic_error,
2662 "At the end of insertLocalIndices, ! indicesAreAllocated() || " 2663 "! isLocallyIndexed() is true. Please report this bug to the " 2664 "Tpetra developers.");
2668 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2672 const LocalOrdinal numEnt,
2673 const LocalOrdinal inds[])
2675 Teuchos::ArrayView<const LocalOrdinal> indsT (inds, numEnt);
2676 this->insertLocalIndices (localRow, indsT);
2680 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2684 const LocalOrdinal numInputInds,
2685 const GlobalOrdinal inputGblColInds[])
2687 typedef LocalOrdinal LO;
2688 const char tfecfFuncName[] =
"insertGlobalIndices: ";
2690 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2691 (this->isLocallyIndexed (), std::runtime_error,
2692 "graph indices are local; use insertLocalIndices().");
2697 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2698 (! this->isFillActive (), std::runtime_error,
2699 "You are not allowed to call this method if fill is not active. " 2700 "If fillComplete has been called, you must first call resumeFill " 2701 "before you may insert indices.");
2702 if (! indicesAreAllocated ()) {
2703 allocateIndices (GlobalIndices, verbose_);
2705 const LO lclRow = this->rowMap_->getLocalElement (gblRow);
2706 if (lclRow != Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
2708 if (this->hasColMap ()) {
2710 const map_type& colMap = * (this->colMap_);
2715 std::vector<GlobalOrdinal> badColInds;
2716 bool allInColMap =
true;
2717 for (LO k = 0; k < numInputInds; ++k) {
2719 allInColMap =
false;
2720 badColInds.push_back (inputGblColInds[k]);
2723 if (! allInColMap) {
2724 std::ostringstream os;
2725 os <<
"You attempted to insert entries in owned row " << gblRow
2726 <<
", at the following column indices: [";
2727 for (LO k = 0; k < numInputInds; ++k) {
2728 os << inputGblColInds[k];
2729 if (k + static_cast<LO> (1) < numInputInds) {
2733 os <<
"]." << endl <<
"Of those, the following indices are not in " 2734 "the column Map on this process: [";
2735 for (
size_t k = 0; k < badColInds.size (); ++k) {
2736 os << badColInds[k];
2737 if (k +
size_t (1) < badColInds.size ()) {
2741 os <<
"]." << endl <<
"Since the matrix has a column Map already, " 2742 "it is invalid to insert entries at those locations.";
2743 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2744 (
true, std::invalid_argument, os.str ());
2748 this->insertGlobalIndicesImpl (lclRow, inputGblColInds, numInputInds);
2751 this->insertGlobalIndicesIntoNonownedRows (gblRow, inputGblColInds,
2757 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2761 const Teuchos::ArrayView<const GlobalOrdinal>& inputGblColInds)
2763 this->insertGlobalIndices (gblRow, inputGblColInds.size (),
2764 inputGblColInds.getRawPtr ());
2768 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2772 const GlobalOrdinal gblColInds[],
2773 const LocalOrdinal numGblColInds)
2775 typedef LocalOrdinal LO;
2776 typedef GlobalOrdinal GO;
2777 const char tfecfFuncName[] =
"insertGlobalIndicesFiltered: ";
2779 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2780 (this->isLocallyIndexed (), std::runtime_error,
2781 "Graph indices are local; use insertLocalIndices().");
2786 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2787 (! this->isFillActive (), std::runtime_error,
2788 "You are not allowed to call this method if fill is not active. " 2789 "If fillComplete has been called, you must first call resumeFill " 2790 "before you may insert indices.");
2791 if (! indicesAreAllocated ()) {
2792 allocateIndices (GlobalIndices, verbose_);
2795 Teuchos::ArrayView<const GO> gblColInds_av (gblColInds, numGblColInds);
2797 if (! colMap_.is_null ()) {
2798 const map_type& colMap = * (this->colMap_);
2801 while (curOffset < numGblColInds) {
2805 LO endOffset = curOffset;
2806 for ( ; endOffset < numGblColInds; ++endOffset) {
2808 if (lclCol == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
2815 const LO numIndInSeq = (endOffset - curOffset);
2816 if (numIndInSeq != 0) {
2817 this->insertGlobalIndicesImpl (lclRow, gblColInds + curOffset,
2823 curOffset = endOffset + 1;
2827 this->insertGlobalIndicesImpl (lclRow, gblColInds_av.getRawPtr (),
2828 gblColInds_av.size ());
2832 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2836 const GlobalOrdinal gblColInds[],
2837 const LocalOrdinal numGblColInds)
2842 std::vector<GlobalOrdinal>& nonlocalRow = this->nonlocals_[gblRow];
2843 for (LocalOrdinal k = 0; k < numGblColInds; ++k) {
2847 nonlocalRow.push_back (gblColInds[k]);
2851 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2856 const char tfecfFuncName[] =
"removeLocalIndices: ";
2857 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2858 ! isFillActive (), std::runtime_error,
"requires that fill is active.");
2859 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2860 isStorageOptimized (), std::runtime_error,
2861 "cannot remove indices after optimizeStorage() has been called.");
2862 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2863 isGloballyIndexed (), std::runtime_error,
"graph indices are global.");
2864 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2865 ! rowMap_->isNodeLocalElement (lrow), std::runtime_error,
2866 "Local row " << lrow <<
" is not in the row Map on the calling process.");
2867 if (! indicesAreAllocated ()) {
2868 allocateIndices (LocalIndices, verbose_);
2873 clearGlobalConstants ();
2875 if (k_numRowEntries_.extent (0) != 0) {
2876 this->k_numRowEntries_(lrow) = 0;
2880 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2881 (getNumEntriesInLocalRow (lrow) != 0 ||
2882 ! indicesAreAllocated () ||
2883 ! isLocallyIndexed (), std::logic_error,
2884 "Violated stated post-conditions. Please contact Tpetra team.");
2889 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2893 const typename local_graph_type::entries_type::non_const_type& columnIndices)
2895 const char tfecfFuncName[] =
"setAllIndices: ";
2896 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2897 ! hasColMap () || getColMap ().is_null (), std::runtime_error,
2898 "The graph must have a column Map before you may call this method.");
2899 LocalOrdinal numLocalRows = this->getNodeNumRows ();
2901 LocalOrdinal rowPtrLen = rowPointers.size();
2902 if(numLocalRows == 0) {
2903 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2904 rowPtrLen != 0 && rowPtrLen != 1,
2905 std::runtime_error,
"Have 0 local rows, but rowPointers.size() is neither 0 nor 1.");
2908 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2909 rowPtrLen != numLocalRows + 1,
2910 std::runtime_error,
"rowPointers.size() = " << rowPtrLen <<
2911 " != this->getNodeNumRows()+1 = " << (numLocalRows + 1) <<
".");
2915 if (debug_ && this->isSorted()) {
2918 using exec_space =
typename local_graph_type::execution_space;
2919 using size_type =
typename local_graph_type::size_type;
2920 Kokkos::parallel_reduce(Kokkos::RangePolicy<exec_space>(0, numLocalRows),
2921 KOKKOS_LAMBDA (
const LocalOrdinal i,
int& lNotSorted)
2923 size_type rowBegin = rowPointers(i);
2924 size_type rowEnd = rowPointers(i + 1);
2925 for(size_type j = rowBegin + 1; j < rowEnd; j++)
2927 if(columnIndices(j - 1) > columnIndices(j))
2934 int globalNotSorted = 0;
2935 auto comm = this->getComm();
2936 Teuchos::reduceAll<int, int> (*comm, Teuchos::REDUCE_MAX, notSorted,
2937 Teuchos::outArg (globalNotSorted));
2938 if (globalNotSorted)
2940 std::string message;
2944 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not sorted!\n";
2946 Details::gathervPrint(std::cout, message, *comm);
2947 throw std::invalid_argument(
"CrsGraph::setAllIndices(): provided columnIndices are not sorted within rows on at least one process.");
2954 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2955 ((this->k_lclInds1D_.extent (0) != 0 || this->k_gblInds1D_.extent (0) != 0),
2956 std::runtime_error,
"You may not call this method if 1-D data " 2957 "structures are already allocated.");
2959 indicesAreAllocated_ =
true;
2960 indicesAreLocal_ =
true;
2961 indicesAreSorted_ =
true;
2962 noRedundancies_ =
true;
2963 k_lclInds1D_ = columnIndices;
2964 k_rowPtrs_ = rowPointers;
2967 storageStatus_ = Details::STORAGE_1D_PACKED;
2975 numAllocForAllRows_ = 0;
2976 k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
2978 checkInternalState ();
2982 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2986 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices)
2989 typedef typename local_graph_type::row_map_type row_map_type;
2990 typedef typename row_map_type::array_layout layout_type;
2991 typedef typename row_map_type::non_const_value_type row_offset_type;
2992 typedef View<
size_t*, layout_type , Kokkos::HostSpace,
2993 Kokkos::MemoryUnmanaged> input_view_type;
2994 typedef typename row_map_type::non_const_type nc_row_map_type;
2996 const size_t size =
static_cast<size_t> (rowPointers.size ());
2997 constexpr
bool same = std::is_same<size_t, row_offset_type>::value;
2998 input_view_type ptr_in (rowPointers.getRawPtr (), size);
3000 nc_row_map_type ptr_rot (
"Tpetra::CrsGraph::ptr", size);
3006 input_view_type ptr_decoy (rowPointers.getRawPtr (), size);
3009 input_view_type>::select (ptr_rot, ptr_decoy),
3014 constexpr
bool inHostMemory =
3015 std::is_same<
typename row_map_type::memory_space,
3016 Kokkos::HostSpace>::value;
3027 View<size_t*, layout_type ,execution_space > ptr_st (
"Tpetra::CrsGraph::ptr", size);
3037 Kokkos::View<LocalOrdinal*, layout_type , execution_space > k_ind =
3038 Kokkos::Compat::getKokkosViewDeepCopy<device_type> (columnIndices ());
3039 setAllIndices (ptr_rot, k_ind);
3043 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3047 size_t& boundForAllLocalRows,
3048 bool& boundSameForAllLocalRows)
const 3050 const char tfecfFuncName[] =
"getNumEntriesPerLocalRowUpperBound: ";
3051 const char suffix[] =
" Please report this bug to the Tpetra developers.";
3056 Teuchos::ArrayRCP<const size_t> numEntriesPerRow;
3057 size_t numEntriesForAll = 0;
3058 bool allRowsSame =
true;
3060 const ptrdiff_t numRows =
static_cast<ptrdiff_t
> (this->getNodeNumRows ());
3062 if (this->indicesAreAllocated ()) {
3063 if (this->isStorageOptimized ()) {
3066 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3067 (numRows != 0 && k_rowPtrs_.extent (0) == 0, std::logic_error,
3068 "The graph has " << numRows <<
" (> 0) row" 3069 << (numRows != 1 ?
"s" :
"") <<
" on the calling process, " 3070 "but the k_rowPtrs_ array has zero entries." << suffix);
3071 Teuchos::ArrayRCP<size_t> numEnt;
3073 numEnt = Teuchos::arcp<size_t> (numRows);
3078 bool allRowsReallySame =
false;
3079 for (ptrdiff_t i = 0; i < numRows; ++i) {
3080 numEnt[i] = this->k_rowPtrs_(i+1) - this->k_rowPtrs_(i);
3081 if (i != 0 && numEnt[i] != numEnt[i-1]) {
3082 allRowsReallySame =
false;
3085 if (allRowsReallySame) {
3087 numEntriesForAll = 0;
3089 numEntriesForAll = numEnt[1] - numEnt[0];
3094 numEntriesPerRow = numEnt;
3095 allRowsSame =
false;
3098 else if (k_numRowEntries_.extent (0) != 0) {
3103 numEntriesPerRow = Kokkos::Compat::persistingView (k_numRowEntries_);
3104 allRowsSame =
false;
3107 numEntriesForAll = 0;
3112 if (k_numAllocPerRow_.extent (0) != 0) {
3117 numEntriesPerRow = Kokkos::Compat::persistingView (k_numAllocPerRow_);
3118 allRowsSame =
false;
3121 numEntriesForAll = numAllocForAllRows_;
3126 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3127 (numEntriesForAll != 0 && numEntriesPerRow.size () != 0, std::logic_error,
3128 "numEntriesForAll and numEntriesPerRow are not consistent. The former " 3129 "is nonzero (" << numEntriesForAll <<
"), but the latter has nonzero " 3130 "size " << numEntriesPerRow.size () <<
"." << suffix);
3131 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3132 (numEntriesForAll != 0 && ! allRowsSame, std::logic_error,
3133 "numEntriesForAll and allRowsSame are not consistent. The former " 3134 "is nonzero (" << numEntriesForAll <<
"), but the latter is false." 3136 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3137 (numEntriesPerRow.size () != 0 && allRowsSame, std::logic_error,
3138 "numEntriesPerRow and allRowsSame are not consistent. The former has " 3139 "nonzero length " << numEntriesForAll <<
", but the latter is true." 3142 boundPerLocalRow = numEntriesPerRow;
3143 boundForAllLocalRows = numEntriesForAll;
3144 boundSameForAllLocalRows = allRowsSame;
3148 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3153 using Teuchos::Comm;
3154 using Teuchos::outArg;
3157 using Teuchos::REDUCE_MAX;
3158 using Teuchos::REDUCE_MIN;
3159 using Teuchos::reduceAll;
3164 using size_type =
typename Teuchos::Array<GO>::size_type;
3165 const char tfecfFuncName[] =
"globalAssemble: ";
3167 std::unique_ptr<std::string> prefix;
3169 prefix = this->createPrefix(
"CrsGraph",
"globalAssemble");
3170 std::ostringstream os;
3171 os << *prefix <<
"Start" << endl;
3172 std::cerr << os.str();
3174 RCP<const Comm<int> > comm = getComm ();
3176 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3177 (! isFillActive (), std::runtime_error,
"Fill must be active before " 3178 "you may call this method.");
3180 const size_t myNumNonlocalRows = this->nonlocals_.size ();
3187 const int iHaveNonlocalRows = (myNumNonlocalRows == 0) ? 0 : 1;
3188 int someoneHasNonlocalRows = 0;
3189 reduceAll<int, int> (*comm, REDUCE_MAX, iHaveNonlocalRows,
3190 outArg (someoneHasNonlocalRows));
3191 if (someoneHasNonlocalRows == 0) {
3193 std::ostringstream os;
3194 os << *prefix <<
"Done: No nonlocal rows" << endl;
3195 std::cerr << os.str();
3199 else if (verbose_) {
3200 std::ostringstream os;
3201 os << *prefix <<
"At least 1 process has nonlocal rows" 3203 std::cerr << os.str();
3216 RCP<const map_type> nonlocalRowMap;
3218 Teuchos::Array<size_t> numEntPerNonlocalRow (myNumNonlocalRows);
3220 Teuchos::Array<GO> myNonlocalGblRows (myNumNonlocalRows);
3221 size_type curPos = 0;
3222 for (
auto mapIter = this->nonlocals_.begin ();
3223 mapIter != this->nonlocals_.end ();
3224 ++mapIter, ++curPos) {
3225 myNonlocalGblRows[curPos] = mapIter->first;
3226 std::vector<GO>& gblCols = mapIter->second;
3227 std::sort (gblCols.begin (), gblCols.end ());
3228 auto vecLast = std::unique (gblCols.begin (), gblCols.end ());
3229 gblCols.erase (vecLast, gblCols.end ());
3230 numEntPerNonlocalRow[curPos] = gblCols.size ();
3241 GO myMinNonlocalGblRow = std::numeric_limits<GO>::max ();
3243 auto iter = std::min_element (myNonlocalGblRows.begin (),
3244 myNonlocalGblRows.end ());
3245 if (iter != myNonlocalGblRows.end ()) {
3246 myMinNonlocalGblRow = *iter;
3249 GO gblMinNonlocalGblRow = 0;
3250 reduceAll<int, GO> (*comm, REDUCE_MIN, myMinNonlocalGblRow,
3251 outArg (gblMinNonlocalGblRow));
3252 const GO indexBase = gblMinNonlocalGblRow;
3253 const global_size_t INV = Teuchos::OrdinalTraits<global_size_t>::invalid ();
3254 nonlocalRowMap = rcp (
new map_type (INV, myNonlocalGblRows (), indexBase, comm));
3258 std::ostringstream os;
3259 os << *prefix <<
"nonlocalRowMap->getIndexBase()=" 3260 << nonlocalRowMap->getIndexBase() << endl;
3261 std::cerr << os.str();
3269 RCP<crs_graph_type> nonlocalGraph =
3270 rcp(
new crs_graph_type(nonlocalRowMap, numEntPerNonlocalRow(),
3273 size_type curPos = 0;
3274 for (
auto mapIter = this->nonlocals_.begin ();
3275 mapIter != this->nonlocals_.end ();
3276 ++mapIter, ++curPos) {
3277 const GO gblRow = mapIter->first;
3278 std::vector<GO>& gblCols = mapIter->second;
3279 const LO numEnt =
static_cast<LO
> (numEntPerNonlocalRow[curPos]);
3280 nonlocalGraph->insertGlobalIndices (gblRow, numEnt, gblCols.data ());
3284 std::ostringstream os;
3285 os << *prefix <<
"Built nonlocal graph" << endl;
3286 std::cerr << os.str();
3297 auto origRowMap = this->getRowMap ();
3298 const bool origRowMapIsOneToOne = origRowMap->isOneToOne ();
3300 if (origRowMapIsOneToOne) {
3302 std::ostringstream os;
3303 os << *prefix <<
"Original row Map is 1-to-1" << endl;
3304 std::cerr << os.str();
3306 export_type exportToOrig (nonlocalRowMap, origRowMap);
3312 std::ostringstream os;
3313 os << *prefix <<
"Original row Map is NOT 1-to-1" << endl;
3314 std::cerr << os.str();
3321 export_type exportToOneToOne (nonlocalRowMap, oneToOneRowMap);
3327 crs_graph_type oneToOneGraph (oneToOneRowMap, 0);
3331 std::ostringstream os;
3332 os << *prefix <<
"Export nonlocal graph" << endl;
3333 std::cerr << os.str();
3335 oneToOneGraph.doExport (*nonlocalGraph, exportToOneToOne,
Tpetra::INSERT);
3339 nonlocalGraph = Teuchos::null;
3342 import_type importToOrig (oneToOneRowMap, origRowMap);
3344 std::ostringstream os;
3345 os << *prefix <<
"Import nonlocal graph" << endl;
3346 std::cerr << os.str();
3355 decltype (this->nonlocals_) newNonlocals;
3356 std::swap (this->nonlocals_, newNonlocals);
3358 checkInternalState ();
3360 std::ostringstream os;
3361 os << *prefix <<
"Done" << endl;
3362 std::cerr << os.str();
3367 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3372 clearGlobalConstants();
3373 if (params != Teuchos::null) this->setParameterList (params);
3375 indicesAreSorted_ =
true;
3376 noRedundancies_ =
true;
3377 fillComplete_ =
false;
3381 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3396 Teuchos::RCP<const map_type> domMap = this->getDomainMap ();
3397 if (domMap.is_null ()) {
3398 domMap = this->getRowMap ();
3400 Teuchos::RCP<const map_type> ranMap = this->getRangeMap ();
3401 if (ranMap.is_null ()) {
3402 ranMap = this->getRowMap ();
3404 this->fillComplete (domMap, ranMap, params);
3408 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3412 const Teuchos::RCP<const map_type>& rangeMap,
3413 const Teuchos::RCP<Teuchos::ParameterList>& params)
3416 const char tfecfFuncName[] =
"fillComplete: ";
3417 const bool verbose = verbose_;
3419 std::unique_ptr<std::string> prefix;
3421 prefix = this->createPrefix(
"CrsGraph",
"fillComplete");
3422 std::ostringstream os;
3423 os << *prefix <<
"Start" << endl;
3424 std::cerr << os.str();
3427 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3428 (! isFillActive () || isFillComplete (), std::runtime_error,
3429 "Graph fill state must be active (isFillActive() " 3430 "must be true) before calling fillComplete().");
3432 const int numProcs = getComm ()->getSize ();
3440 if (! params.is_null ()) {
3441 if (params->isParameter (
"sort column map ghost gids")) {
3442 sortGhostsAssociatedWithEachProcessor_ =
3443 params->get<
bool> (
"sort column map ghost gids",
3444 sortGhostsAssociatedWithEachProcessor_);
3446 else if (params->isParameter (
"Sort column Map ghost GIDs")) {
3447 sortGhostsAssociatedWithEachProcessor_ =
3448 params->get<
bool> (
"Sort column Map ghost GIDs",
3449 sortGhostsAssociatedWithEachProcessor_);
3455 bool assertNoNonlocalInserts =
false;
3456 if (! params.is_null ()) {
3457 assertNoNonlocalInserts =
3458 params->get<
bool> (
"No Nonlocal Changes", assertNoNonlocalInserts);
3464 if (! indicesAreAllocated ()) {
3467 allocateIndices (LocalIndices, verbose);
3470 allocateIndices (GlobalIndices, verbose);
3478 const bool mayNeedGlobalAssemble = ! assertNoNonlocalInserts && numProcs > 1;
3479 if (mayNeedGlobalAssemble) {
3485 const size_t numNonlocals = nonlocals_.size();
3487 std::ostringstream os;
3488 os << *prefix <<
"Do not need to call globalAssemble; " 3489 "assertNoNonlocalInserts=" 3490 << (assertNoNonlocalInserts ?
"true" :
"false")
3491 <<
"numProcs=" << numProcs
3492 <<
", nonlocals_.size()=" << numNonlocals << endl;
3493 std::cerr << os.str();
3495 const int lclNeededGlobalAssemble =
3496 (numProcs > 1 && numNonlocals != 0) ? 1 : 0;
3497 if (lclNeededGlobalAssemble != 0 && verbose) {
3498 std::ostringstream os;
3500 Details::Impl::verbosePrintMap(
3501 os, nonlocals_.begin(), nonlocals_.end(),
3502 nonlocals_.size(),
"nonlocals_");
3503 std::cerr << os.str() << endl;
3507 auto map = this->getMap();
3508 auto comm = map.is_null() ? Teuchos::null : map->getComm();
3509 int gblNeededGlobalAssemble = lclNeededGlobalAssemble;
3510 if (! comm.is_null()) {
3511 using Teuchos::REDUCE_MAX;
3512 using Teuchos::reduceAll;
3513 reduceAll(*comm, REDUCE_MAX, lclNeededGlobalAssemble,
3514 Teuchos::outArg(gblNeededGlobalAssemble));
3516 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3517 (gblNeededGlobalAssemble != 0, std::runtime_error,
3518 "nonlocals_.size()=" << numNonlocals <<
" != 0 on at " 3519 "least one process in the CrsGraph's communicator. This " 3520 "means either that you incorrectly set the " 3521 "\"No Nonlocal Changes\" fillComplete parameter to true, " 3522 "or that you inserted invalid entries. " 3523 "Rerun with the environment variable TPETRA_VERBOSE=" 3524 "CrsGraph set to see the entries of nonlocals_ on every " 3525 "MPI process (WARNING: lots of output).");
3528 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3529 (lclNeededGlobalAssemble != 0, std::runtime_error,
3530 "nonlocals_.size()=" << numNonlocals <<
" != 0 on the " 3531 "calling process. This means either that you incorrectly " 3532 "set the \"No Nonlocal Changes\" fillComplete parameter " 3533 "to true, or that you inserted invalid entries. " 3534 "Rerun with the environment " 3535 "variable TPETRA_VERBOSE=CrsGraph set to see the entries " 3536 "of nonlocals_ on every MPI process (WARNING: lots of " 3543 setDomainRangeMaps (domainMap, rangeMap);
3549 Teuchos::Array<int> remotePIDs (0);
3550 const bool mustBuildColMap = ! this->hasColMap ();
3551 if (mustBuildColMap) {
3557 const std::pair<size_t, std::string> makeIndicesLocalResult =
3558 this->makeIndicesLocal(verbose);
3560 using Details::gathervPrint;
3562 using Teuchos::REDUCE_MIN;
3563 using Teuchos::reduceAll;
3564 using Teuchos::outArg;
3566 RCP<const map_type> map = this->getMap ();
3567 RCP<const Teuchos::Comm<int> > comm;
3568 if (! map.is_null ()) {
3569 comm = map->getComm ();
3571 if (comm.is_null ()) {
3572 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3573 (makeIndicesLocalResult.first != 0, std::runtime_error,
3574 makeIndicesLocalResult.second);
3577 const int lclSuccess = (makeIndicesLocalResult.first == 0);
3579 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
3580 if (gblSuccess != 1) {
3581 std::ostringstream os;
3582 gathervPrint (os, makeIndicesLocalResult.second, *comm);
3583 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3584 (
true, std::runtime_error, os.str ());
3593 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3594 (makeIndicesLocalResult.first != 0, std::runtime_error,
3595 makeIndicesLocalResult.second);
3601 this->sortAndMergeAllIndices (this->isSorted (), this->isMerged ());
3606 this->makeImportExport (remotePIDs, mustBuildColMap);
3609 this->fillLocalGraph (params);
3611 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
3612 params->get (
"compute global constants",
true);
3613 if (callComputeGlobalConstants) {
3614 this->computeGlobalConstants ();
3617 this->computeLocalConstants ();
3619 this->fillComplete_ =
true;
3620 this->checkInternalState ();
3623 std::ostringstream os;
3624 os << *prefix <<
"Done" << endl;
3625 std::cerr << os.str();
3630 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3634 const Teuchos::RCP<const map_type>& rangeMap,
3635 const Teuchos::RCP<const import_type>& importer,
3636 const Teuchos::RCP<const export_type>& exporter,
3637 const Teuchos::RCP<Teuchos::ParameterList>& params)
3639 const char tfecfFuncName[] =
"expertStaticFillComplete: ";
3640 #ifdef HAVE_TPETRA_MMM_TIMINGS 3642 if(!params.is_null())
3643 label = params->get(
"Timer Label",label);
3644 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
": ");
3645 using Teuchos::TimeMonitor;
3646 Teuchos::RCP<Teuchos::TimeMonitor> MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Setup"))));
3650 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3651 domainMap.is_null () || rangeMap.is_null (),
3652 std::runtime_error,
"The input domain Map and range Map must be nonnull.");
3653 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3654 isFillComplete () || ! hasColMap (), std::runtime_error,
"You may not " 3655 "call this method unless the graph has a column Map.");
3656 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3657 getNodeNumRows () > 0 && k_rowPtrs_.extent (0) == 0,
3658 std::runtime_error,
"The calling process has getNodeNumRows() = " 3659 << getNodeNumRows () <<
" > 0 rows, but the row offsets array has not " 3661 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3662 static_cast<size_t> (k_rowPtrs_.extent (0)) != getNodeNumRows () + 1,
3663 std::runtime_error,
"The row offsets array has length " <<
3664 k_rowPtrs_.extent (0) <<
" != getNodeNumRows()+1 = " <<
3665 (getNodeNumRows () + 1) <<
".");
3680 numAllocForAllRows_ = 0;
3681 k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
3682 indicesAreAllocated_ =
true;
3687 indicesAreLocal_ =
true;
3688 indicesAreGlobal_ =
false;
3691 #ifdef HAVE_TPETRA_MMM_TIMINGS 3693 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Maps"))));
3695 setDomainRangeMaps (domainMap, rangeMap);
3698 indicesAreSorted_ =
true;
3699 noRedundancies_ =
true;
3702 #ifdef HAVE_TPETRA_MMM_TIMINGS 3704 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckI"))));
3707 importer_ = Teuchos::null;
3708 exporter_ = Teuchos::null;
3709 if (importer != Teuchos::null) {
3710 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3711 ! importer->getSourceMap ()->isSameAs (*getDomainMap ()) ||
3712 ! importer->getTargetMap ()->isSameAs (*getColMap ()),
3713 std::invalid_argument,
": importer does not match matrix maps.");
3714 importer_ = importer;
3718 #ifdef HAVE_TPETRA_MMM_TIMINGS 3720 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckE"))));
3723 if (exporter != Teuchos::null) {
3724 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3725 ! exporter->getSourceMap ()->isSameAs (*getRowMap ()) ||
3726 ! exporter->getTargetMap ()->isSameAs (*getRangeMap ()),
3727 std::invalid_argument,
": exporter does not match matrix maps.");
3728 exporter_ = exporter;
3731 #ifdef HAVE_TPETRA_MMM_TIMINGS 3733 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXmake"))));
3735 Teuchos::Array<int> remotePIDs (0);
3736 this->makeImportExport (remotePIDs,
false);
3738 #ifdef HAVE_TPETRA_MMM_TIMINGS 3740 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-fLG"))));
3742 this->fillLocalGraph (params);
3744 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
3745 params->get (
"compute global constants",
true);
3747 if (callComputeGlobalConstants) {
3748 #ifdef HAVE_TPETRA_MMM_TIMINGS 3750 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (const)"))));
3751 #endif // HAVE_TPETRA_MMM_TIMINGS 3752 this->computeGlobalConstants ();
3755 #ifdef HAVE_TPETRA_MMM_TIMINGS 3757 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (noconst)"))));
3758 #endif // HAVE_TPETRA_MMM_TIMINGS 3759 this->computeLocalConstants ();
3762 fillComplete_ =
true;
3764 #ifdef HAVE_TPETRA_MMM_TIMINGS 3766 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cIS"))));
3768 checkInternalState ();
3772 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3775 fillLocalGraph (
const Teuchos::RCP<Teuchos::ParameterList>& params)
3778 typedef decltype (k_numRowEntries_) row_entries_type;
3779 typedef typename local_graph_type::row_map_type row_map_type;
3780 typedef typename row_map_type::non_const_type non_const_row_map_type;
3781 typedef typename local_graph_type::entries_type::non_const_type lclinds_1d_type;
3782 const char tfecfFuncName[] =
"fillLocalGraph (called from fillComplete or " 3783 "expertStaticFillComplete): ";
3784 const size_t lclNumRows = this->getNodeNumRows ();
3791 non_const_row_map_type ptr_d;
3792 row_map_type ptr_d_const;
3793 lclinds_1d_type ind_d;
3795 bool requestOptimizedStorage =
true;
3796 if (! params.is_null () && ! params->get (
"Optimize Storage",
true)) {
3797 requestOptimizedStorage =
false;
3806 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3807 (k_rowPtrs_.extent (0) == 0, std::logic_error,
3808 "k_rowPtrs_ has size zero, but shouldn't");
3809 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3810 (k_rowPtrs_.extent (0) != lclNumRows + 1, std::logic_error,
3811 "k_rowPtrs_.extent(0) = " 3812 << k_rowPtrs_.extent (0) <<
" != (lclNumRows + 1) = " 3813 << (lclNumRows + 1) <<
".");
3814 const size_t numOffsets = k_rowPtrs_.extent (0);
3815 const auto valToCheck =
3816 ::Tpetra::Details::getEntryOnHost (k_rowPtrs_, numOffsets - 1);
3817 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3819 k_lclInds1D_.extent (0) != valToCheck,
3820 std::logic_error,
"numOffsets=" << numOffsets <<
" != 0 " 3821 " and k_lclInds1D_.extent(0)=" << k_lclInds1D_.extent(0)
3822 <<
" != k_rowPtrs_(" << numOffsets <<
")=" << valToCheck
3826 size_t allocSize = 0;
3828 allocSize = this->getNodeAllocationSize ();
3830 catch (std::logic_error& e) {
3831 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3832 (
true, std::logic_error,
"getNodeAllocationSize threw " 3833 "std::logic_error: " << e.what ());
3835 catch (std::runtime_error& e) {
3836 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3837 (
true, std::runtime_error,
"getNodeAllocationSize threw " 3838 "std::runtime_error: " << e.what ());
3840 catch (std::exception& e) {
3841 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3842 (
true, std::runtime_error,
"getNodeAllocationSize threw " 3843 "std::exception: " << e.what ());
3846 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3847 (
true, std::runtime_error,
"getNodeAllocationSize threw " 3848 "an exception not a subclass of std::exception.");
3851 if (this->getNodeNumEntries () != allocSize) {
3859 if (k_rowPtrs_.extent (0) != 0) {
3860 const size_t numOffsets =
3861 static_cast<size_t> (k_rowPtrs_.extent (0));
3862 const auto valToCheck =
3863 ::Tpetra::Details::getEntryOnHost (k_rowPtrs_, numOffsets - 1);
3864 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3865 (valToCheck !=
size_t(k_lclInds1D_.extent(0)),
3866 std::logic_error,
"(Unpacked branch) Before allocating " 3867 "or packing, k_rowPtrs_(" << (numOffsets-1) <<
")=" 3868 << valToCheck <<
" != k_lclInds1D_.extent(0)=" 3869 << k_lclInds1D_.extent (0) <<
".");
3879 size_t lclTotalNumEntries = 0;
3882 ptr_d = non_const_row_map_type (
"Tpetra::CrsGraph::ptr", lclNumRows + 1);
3883 ptr_d_const = ptr_d;
3887 typename row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
3889 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3890 (
size_t(numRowEnt_h.extent (0)) != lclNumRows,
3891 std::logic_error,
"(Unpacked branch) " 3892 "numRowEnt_h.extent(0)=" << numRowEnt_h.extent(0)
3893 <<
" != getNodeNumRows()=" << lclNumRows <<
"");
3899 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3900 (static_cast<size_t> (ptr_d.extent (0)) != lclNumRows + 1,
3901 std::logic_error,
"(Unpacked branch) After allocating " 3902 "ptr_d, ptr_d.extent(0) = " << ptr_d.extent(0)
3903 <<
" != lclNumRows+1 = " << (lclNumRows+1) <<
".");
3904 const auto valToCheck =
3905 ::Tpetra::Details::getEntryOnHost (ptr_d, lclNumRows);
3906 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3907 (valToCheck != lclTotalNumEntries, std::logic_error,
3908 "Tpetra::CrsGraph::fillLocalGraph: In unpacked branch, " 3909 "after filling ptr_d, ptr_d(lclNumRows=" << lclNumRows
3910 <<
") = " << valToCheck <<
" != total number of entries " 3911 "on the calling process = " << lclTotalNumEntries
3917 ind_d = lclinds_1d_type (
"Tpetra::CrsGraph::ind", lclTotalNumEntries);
3929 typedef pack_functor<
3930 typename local_graph_type::entries_type::non_const_type,
3931 row_map_type> inds_packer_type;
3932 inds_packer_type f (ind_d, k_lclInds1D_, ptr_d, k_rowPtrs_);
3934 typedef typename decltype (ind_d)::execution_space exec_space;
3935 typedef Kokkos::RangePolicy<exec_space, LocalOrdinal> range_type;
3936 Kokkos::parallel_for (range_type (0, lclNumRows), f);
3940 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3941 (ptr_d.extent (0) == 0, std::logic_error,
3942 "(\"Optimize Storage\"=true branch) After packing, " 3943 "ptr_d.extent(0)=0. This probably means k_rowPtrs_ was " 3944 "never allocated.");
3945 if (ptr_d.extent (0) != 0) {
3946 const size_t numOffsets =
static_cast<size_t> (ptr_d.extent (0));
3947 const auto valToCheck =
3948 ::Tpetra::Details::getEntryOnHost (ptr_d, numOffsets - 1);
3949 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3950 (static_cast<size_t> (valToCheck) != ind_d.extent (0),
3951 std::logic_error,
"(\"Optimize Storage\"=true branch) " 3952 "After packing, ptr_d(" << (numOffsets-1) <<
")=" 3953 << valToCheck <<
" != ind_d.extent(0)=" 3954 << ind_d.extent(0) <<
".");
3959 ptr_d_const = k_rowPtrs_;
3960 ind_d = k_lclInds1D_;
3963 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3964 (ptr_d_const.extent (0) == 0, std::logic_error,
3965 "(\"Optimize Storage\"=false branch) " 3966 "ptr_d_const.extent(0) = 0. This probably means that " 3967 "k_rowPtrs_ was never allocated.");
3968 if (ptr_d_const.extent (0) != 0) {
3969 const size_t numOffsets =
3970 static_cast<size_t> (ptr_d_const.extent (0));
3971 const size_t valToCheck =
3972 ::Tpetra::Details::getEntryOnHost (ptr_d_const, numOffsets - 1);
3973 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3974 (valToCheck !=
size_t(ind_d.extent (0)),
3975 std::logic_error,
"(\"Optimize Storage\"=false branch) " 3976 "ptr_d_const(" << (numOffsets-1) <<
")=" << valToCheck
3977 <<
" != ind_d.extent(0)=" << ind_d.extent (0) <<
".");
3983 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3984 (static_cast<size_t> (ptr_d_const.extent (0)) != lclNumRows + 1,
3985 std::logic_error,
"After packing, ptr_d_const.extent(0) = " <<
3986 ptr_d_const.extent (0) <<
" != lclNumRows+1 = " << (lclNumRows+1)
3988 if (ptr_d_const.extent (0) != 0) {
3989 const size_t numOffsets =
static_cast<size_t> (ptr_d_const.extent (0));
3990 const auto valToCheck =
3991 ::Tpetra::Details::getEntryOnHost (ptr_d_const, numOffsets - 1);
3992 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3993 (static_cast<size_t> (valToCheck) != ind_d.extent (0),
3994 std::logic_error,
"After packing, ptr_d_const(" << (numOffsets-1)
3995 <<
") = " << valToCheck <<
" != ind_d.extent(0) = " 3996 << ind_d.extent (0) <<
".");
4000 if (requestOptimizedStorage) {
4006 k_numRowEntries_ = row_entries_type ();
4009 k_rowPtrs_ = ptr_d_const;
4010 k_lclInds1D_ = ind_d;
4012 storageStatus_ = Details::STORAGE_1D_PACKED;
4018 lclGraph_ = local_graph_type (ind_d, ptr_d_const);
4021 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4023 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
4024 replaceColMap (
const Teuchos::RCP<const map_type>& newColMap)
4033 const char tfecfFuncName[] =
"replaceColMap: ";
4034 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4035 isLocallyIndexed () || isGloballyIndexed (), std::runtime_error,
4036 "Requires matching maps and non-static graph.");
4037 colMap_ = newColMap;
4040 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4044 const Teuchos::RCP<const import_type>& newImport,
4045 const bool sortIndicesInEachRow)
4047 using Teuchos::REDUCE_MIN;
4048 using Teuchos::reduceAll;
4050 typedef GlobalOrdinal GO;
4051 typedef LocalOrdinal LO;
4052 typedef typename local_graph_type::entries_type::non_const_type col_inds_type;
4053 const char tfecfFuncName[] =
"reindexColumns: ";
4055 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4056 isFillComplete (), std::runtime_error,
"The graph is fill complete " 4057 "(isFillComplete() returns true). You must call resumeFill() before " 4058 "you may call this method.");
4076 const LO lclNumRows =
static_cast<LO
> (this->getNodeNumRows ());
4091 bool allCurColIndsValid =
true;
4096 bool localSuffices =
true;
4104 typename local_graph_type::entries_type::non_const_type newLclInds1D;
4105 Teuchos::ArrayRCP<Teuchos::Array<LO> > newLclInds2D;
4110 if (indicesAreAllocated ()) {
4111 if (isLocallyIndexed ()) {
4113 const map_type& oldColMap = * (getColMap ());
4115 const size_t allocSize = this->getNodeAllocationSize ();
4116 newLclInds1D = col_inds_type (
"Tpetra::CrsGraph::ind", allocSize);
4118 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
4119 const RowInfo rowInfo = this->getRowInfo (lclRow);
4120 const size_t beg = rowInfo.offset1D;
4121 const size_t end = beg + rowInfo.numEntries;
4122 for (
size_t k = beg; k < end; ++k) {
4125 const LO oldLclCol = k_lclInds1D_(k);
4126 if (oldLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
4127 allCurColIndsValid =
false;
4135 if (gblCol == Teuchos::OrdinalTraits<GO>::invalid ()) {
4136 allCurColIndsValid =
false;
4140 const LO newLclCol = newColMap->getLocalElement (gblCol);
4141 if (newLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
4142 localSuffices =
false;
4147 newLclInds1D(k) = newLclCol;
4158 allCurColIndsValid =
false;
4175 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
4176 const RowInfo rowInfo = this->getRowInfo (lclRow);
4177 Teuchos::ArrayView<const GO> oldGblRowView = getGlobalView (rowInfo);
4178 for (
size_t k = 0; k < rowInfo.numEntries; ++k) {
4179 const GO gblCol = oldGblRowView[k];
4180 if (! newColMap->isNodeGlobalElement (gblCol)) {
4181 localSuffices =
false;
4191 lclSuccess[0] = allCurColIndsValid ? 1 : 0;
4192 lclSuccess[1] = localSuffices ? 1 : 0;
4196 RCP<const Teuchos::Comm<int> > comm =
4197 getRowMap ().is_null () ? Teuchos::null : getRowMap ()->getComm ();
4198 if (! comm.is_null ()) {
4199 reduceAll<int, int> (*comm, REDUCE_MIN, 2, lclSuccess, gblSuccess);
4202 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4203 gblSuccess[0] == 0, std::runtime_error,
"It is not possible to continue." 4204 " The most likely reason is that the graph is locally indexed, but the " 4205 "column Map is missing (null) on some processes, due to a previous call " 4206 "to replaceColMap().");
4208 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4209 gblSuccess[1] == 0, std::runtime_error,
"On some process, the graph " 4210 "contains column indices that are in the old column Map, but not in the " 4211 "new column Map (on that process). This method does NOT redistribute " 4212 "data; it does not claim to do the work of an Import or Export operation." 4213 " This means that for all processess, the calling process MUST own all " 4214 "column indices, in both the old column Map and the new column Map. In " 4215 "this case, you will need to do an Import or Export operation to " 4216 "redistribute data.");
4219 if (isLocallyIndexed ()) {
4220 k_lclInds1D_ = newLclInds1D;
4227 indicesAreSorted_ =
false;
4228 if (sortIndicesInEachRow) {
4235 const bool sorted =
false;
4236 const bool merged =
true;
4237 this->sortAndMergeAllIndices (sorted, merged);
4240 colMap_ = newColMap;
4242 if (newImport.is_null ()) {
4250 if (! domainMap_.is_null ()) {
4251 if (! domainMap_->isSameAs (* newColMap)) {
4252 importer_ = Teuchos::rcp (
new import_type (domainMap_, newColMap));
4254 importer_ = Teuchos::null;
4259 importer_ = newImport;
4264 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4268 const Teuchos::RCP<const import_type>& newImporter)
4270 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMapAndImporter: ";
4271 TEUCHOS_TEST_FOR_EXCEPTION(
4272 colMap_.is_null (), std::invalid_argument, prefix <<
"You may not call " 4273 "this method unless the graph already has a column Map.");
4274 TEUCHOS_TEST_FOR_EXCEPTION(
4275 newDomainMap.is_null (), std::invalid_argument,
4276 prefix <<
"The new domain Map must be nonnull.");
4279 if (newImporter.is_null ()) {
4284 const bool colSameAsDom = colMap_->isSameAs (*newDomainMap);
4285 TEUCHOS_TEST_FOR_EXCEPTION
4286 (colSameAsDom, std::invalid_argument,
"If the new Import is null, " 4287 "then the new domain Map must be the same as the current column Map.");
4290 const bool colSameAsTgt =
4291 colMap_->isSameAs (* (newImporter->getTargetMap ()));
4292 const bool newDomSameAsSrc =
4293 newDomainMap->isSameAs (* (newImporter->getSourceMap ()));
4294 TEUCHOS_TEST_FOR_EXCEPTION
4295 (! colSameAsTgt || ! newDomSameAsSrc, std::invalid_argument,
"If the " 4296 "new Import is nonnull, then the current column Map must be the same " 4297 "as the new Import's target Map, and the new domain Map must be the " 4298 "same as the new Import's source Map.");
4302 domainMap_ = newDomainMap;
4303 importer_ = Teuchos::rcp_const_cast<
import_type> (newImporter);
4306 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4314 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4319 using ::Tpetra::Details::ProfilingRegion;
4320 using Teuchos::ArrayView;
4321 using Teuchos::outArg;
4322 using Teuchos::reduceAll;
4325 ProfilingRegion regionCGC (
"Tpetra::CrsGraph::computeGlobalConstants");
4327 this->computeLocalConstants ();
4332 if (! this->haveGlobalConstants_) {
4333 const Teuchos::Comm<int>& comm = * (this->getComm ());
4347 lcl =
static_cast<GST
> (this->getNodeNumEntries ());
4349 reduceAll<int,GST> (comm, Teuchos::REDUCE_SUM, 1, &lcl, &gbl);
4350 this->globalNumEntries_ = gbl;
4352 const GST lclMaxNumRowEnt =
static_cast<GST
> (this->nodeMaxNumRowEntries_);
4353 reduceAll<int, GST> (comm, Teuchos::REDUCE_MAX, lclMaxNumRowEnt,
4354 outArg (this->globalMaxNumRowEntries_));
4355 this->haveGlobalConstants_ =
true;
4360 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4365 using ::Tpetra::Details::ProfilingRegion;
4367 ProfilingRegion regionCLC (
"Tpetra::CrsGraph::computeLocalConstants");
4368 if (this->haveLocalConstants_) {
4373 this->nodeMaxNumRowEntries_ =
4374 Teuchos::OrdinalTraits<size_t>::invalid();
4388 auto ptr = this->lclGraph_.row_map;
4389 const LO lclNumRows = ptr.extent(0) == 0 ?
4390 static_cast<LO
> (0) :
4391 (static_cast<LO> (ptr.extent(0)) - static_cast<LO> (1));
4393 const LO lclMaxNumRowEnt =
4394 ::Tpetra::Details::maxDifference (
"Tpetra::CrsGraph: nodeMaxNumRowEntries",
4396 this->nodeMaxNumRowEntries_ =
static_cast<size_t> (lclMaxNumRowEnt);
4397 this->haveLocalConstants_ =
true;
4401 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4402 std::pair<size_t, std::string>
4407 using Teuchos::arcp;
4408 using Teuchos::Array;
4410 typedef LocalOrdinal LO;
4411 typedef GlobalOrdinal GO;
4413 typedef typename local_graph_type::row_map_type::non_const_value_type offset_type;
4414 typedef decltype (k_numRowEntries_) row_entries_type;
4415 typedef typename row_entries_type::non_const_value_type num_ent_type;
4416 typedef typename local_graph_type::entries_type::non_const_type
4418 typedef Kokkos::View<GO*,
typename lcl_col_inds_type::array_layout,
4420 const char tfecfFuncName[] =
"makeIndicesLocal: ";
4421 ProfilingRegion regionMakeIndicesLocal (
"Tpetra::CrsGraph::makeIndicesLocal");
4423 std::unique_ptr<std::string> prefix;
4425 prefix = this->createPrefix(
"CrsGraph",
"makeIndicesLocal");
4426 std::ostringstream os;
4427 os << *prefix <<
"lclNumRows: " << getNodeNumRows() << endl;
4428 std::cerr << os.str();
4433 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4434 (! this->hasColMap (), std::logic_error,
"The graph does not have a " 4435 "column Map yet. This method should never be called in that case. " 4436 "Please report this bug to the Tpetra developers.");
4437 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4438 (this->getColMap ().is_null (), std::logic_error,
"The graph claims " 4439 "that it has a column Map, because hasColMap() returns true. However, " 4440 "the result of getColMap() is null. This should never happen. Please " 4441 "report this bug to the Tpetra developers.");
4446 size_t lclNumErrs = 0;
4447 std::ostringstream errStrm;
4449 const LO lclNumRows =
static_cast<LO
> (this->getNodeNumRows ());
4450 const map_type& colMap = * (this->getColMap ());
4452 if (this->isGloballyIndexed () && lclNumRows != 0) {
4454 typename row_entries_type::const_type h_numRowEnt =
4455 this->k_numRowEntries_;
4461 constexpr
bool LO_GO_same = std::is_same<LO, GO>::value;
4466 k_lclInds1D_ = Kokkos::Impl::if_c<LO_GO_same,
4468 lcl_col_inds_type>::select (k_gblInds1D_, k_lclInds1D_);
4471 if (k_rowPtrs_.extent (0) == 0) {
4472 errStrm <<
"k_rowPtrs_.extent(0) == 0. This should never " 4473 "happen here. Please report this bug to the Tpetra developers." 4476 return std::make_pair (Tpetra::Details::OrdinalTraits<size_t>::invalid (),
4479 const auto numEnt = ::Tpetra::Details::getEntryOnHost (k_rowPtrs_, lclNumRows);
4488 using Kokkos::view_alloc;
4489 using Kokkos::WithoutInitializing;
4499 const std::string label (
"Tpetra::CrsGraph::lclind");
4501 std::ostringstream os;
4502 os << *prefix <<
"(Re)allocate k_lclInds1D_: old=" 4503 << k_lclInds1D_.extent(0) <<
", new=" << numEnt << endl;
4504 std::cerr << os.str();
4507 lcl_col_inds_type (view_alloc (label, WithoutInitializing), numEnt);
4519 std::ostringstream os;
4520 os << *prefix <<
"Allocate device mirror k_numRowEnt: " 4521 << h_numRowEnt.extent(0) << endl;
4522 std::cerr << os.str();
4524 auto k_numRowEnt = Kokkos::create_mirror_view (
device_type (), h_numRowEnt);
4528 convertColumnIndicesFromGlobalToLocal<LO, GO, DT, offset_type, num_ent_type> (k_lclInds1D_,
4533 if (lclNumErrs != 0) {
4534 const int myRank = [
this] () {
4535 auto map = this->getMap ();
4536 if (map.is_null ()) {
4540 auto comm = map->getComm ();
4541 return comm.is_null () ? 0 : comm->getRank ();
4544 const bool pluralNumErrs = (lclNumErrs !=
static_cast<size_t> (1));
4545 errStrm <<
"(Process " << myRank <<
") When converting column " 4546 "indices from global to local, we encountered " << lclNumErrs
4547 <<
" ind" << (pluralNumErrs ?
"ices" :
"ex")
4548 <<
" that do" << (pluralNumErrs ?
"es" :
"")
4549 <<
" not live in the column Map on this process." << endl;
4556 std::ostringstream os;
4557 os << *prefix <<
"Free k_gblInds1D_: " 4558 << k_gblInds1D_.extent(0) << endl;
4559 std::cerr << os.str();
4561 k_gblInds1D_ = gbl_col_inds_type ();
4565 this->indicesAreLocal_ =
true;
4566 this->indicesAreGlobal_ =
false;
4567 this->checkInternalState ();
4569 return std::make_pair (lclNumErrs, errStrm.str ());
4572 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4579 const char tfecfFuncName[] =
"makeColMap";
4581 ProfilingRegion regionSortAndMerge (
"Tpetra::CrsGraph::makeColMap");
4582 std::unique_ptr<std::string> prefix;
4584 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4585 std::ostringstream os;
4586 os << *prefix <<
"Start" << endl;
4587 std::cerr << os.str();
4595 Teuchos::RCP<const map_type> colMap = this->colMap_;
4596 const bool sortEachProcsGids =
4597 this->sortGhostsAssociatedWithEachProcessor_;
4607 using Teuchos::outArg;
4608 using Teuchos::REDUCE_MIN;
4609 using Teuchos::reduceAll;
4611 std::ostringstream errStrm;
4612 const int lclErrCode =
4614 getDomainMap (), *
this, sortEachProcsGids, &errStrm);
4615 auto comm = this->getComm ();
4616 if (! comm.is_null ()) {
4617 const int lclSuccess = (lclErrCode == 0) ? 1 : 0;
4619 reduceAll<int, int> (*comm, REDUCE_MIN, lclSuccess,
4620 outArg (gblSuccess));
4621 if (gblSuccess != 1) {
4622 std::ostringstream os;
4623 Details::gathervPrint (os, errStrm.str (), *comm);
4624 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4625 (
true, std::runtime_error,
": An error happened on at " 4626 "least one process in the CrsGraph's communicator. " 4627 "Here are all processes' error messages:" << std::endl
4634 getDomainMap (), *
this, sortEachProcsGids,
nullptr);
4639 this->colMap_ = colMap;
4641 checkInternalState ();
4643 std::ostringstream os;
4644 os << *prefix <<
"Done" << endl;
4645 std::cerr << os.str();
4650 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4656 using LO = LocalOrdinal;
4657 using host_execution_space =
4658 typename Kokkos::View<LO*, device_type>::HostMirror::
4660 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
4661 const char tfecfFuncName[] =
"sortAndMergeAllIndices";
4663 (
"Tpetra::CrsGraph::sortAndMergeAllIndices");
4665 std::unique_ptr<std::string> prefix;
4667 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4668 std::ostringstream os;
4669 os << *prefix <<
"Start: " 4670 <<
"sorted=" << (sorted ?
"true" :
"false")
4671 <<
", merged=" << (merged ?
"true" :
"false") << endl;
4672 std::cerr << os.str();
4674 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4675 (this->isGloballyIndexed(), std::logic_error,
4676 "This method may only be called after makeIndicesLocal." );
4677 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4678 (! merged && this->isStorageOptimized(), std::logic_error,
4679 "The graph is already storage optimized, so we shouldn't be " 4680 "merging any indices. " 4681 "Please report this bug to the Tpetra developers.");
4683 if (! sorted || ! merged) {
4684 const LO lclNumRows(this->getNodeNumRows());
4685 auto range = range_type(0, lclNumRows);
4689 size_t totalNumDups = 0;
4690 Kokkos::parallel_reduce(range,
4691 [
this, sorted, merged] (
const LO lclRow,
size_t& numDups)
4693 const RowInfo rowInfo = this->getRowInfo(lclRow);
4694 numDups += this->sortAndMergeRowIndices(rowInfo, sorted, merged);
4697 std::ostringstream os;
4698 os << *prefix <<
"totalNumDups=" << totalNumDups << endl;
4699 std::cerr << os.str();
4703 Kokkos::parallel_for(range,
4704 [
this, sorted, merged] (
const LO lclRow)
4706 const RowInfo rowInfo = this->getRowInfo(lclRow);
4707 this->sortAndMergeRowIndices(rowInfo, sorted, merged);
4710 this->indicesAreSorted_ =
true;
4711 this->noRedundancies_ =
true;
4715 std::ostringstream os;
4716 os << *prefix <<
"Done" << endl;
4717 std::cerr << os.str();
4721 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4723 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
4724 makeImportExport (Teuchos::Array<int>& remotePIDs,
4725 const bool useRemotePIDs)
4727 using ::Tpetra::Details::ProfilingRegion;
4728 using Teuchos::ParameterList;
4731 const char tfecfFuncName[] =
"makeImportExport: ";
4732 ProfilingRegion regionMIE (
"Tpetra::CrsGraph::makeImportExport");
4734 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4735 (! this->hasColMap (), std::logic_error,
4736 "This method may not be called unless the graph has a column Map.");
4737 RCP<ParameterList> params = this->getNonconstParameterList ();
4746 if (importer_.is_null ()) {
4748 if (domainMap_ != colMap_ && (! domainMap_->isSameAs (*colMap_))) {
4749 if (params.is_null () || ! params->isSublist (
"Import")) {
4750 if (useRemotePIDs) {
4751 importer_ = rcp (
new import_type (domainMap_, colMap_, remotePIDs));
4754 importer_ = rcp (
new import_type (domainMap_, colMap_));
4758 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
4759 if (useRemotePIDs) {
4760 RCP<import_type> newImp =
4761 rcp (
new import_type (domainMap_, colMap_, remotePIDs,
4766 importer_ = rcp (
new import_type (domainMap_, colMap_, importSublist));
4774 if (exporter_.is_null ()) {
4776 if (rangeMap_ != rowMap_ && ! rangeMap_->isSameAs (*rowMap_)) {
4777 if (params.is_null () || ! params->isSublist (
"Export")) {
4778 exporter_ = rcp (
new export_type (rowMap_, rangeMap_));
4781 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
4782 exporter_ = rcp (
new export_type (rowMap_, rangeMap_, exportSublist));
4789 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4794 std::ostringstream oss;
4795 oss << dist_object_type::description ();
4796 if (isFillComplete ()) {
4797 oss <<
"{status = fill complete" 4798 <<
", global rows = " << getGlobalNumRows()
4799 <<
", global cols = " << getGlobalNumCols()
4800 <<
", global num entries = " << getGlobalNumEntries()
4804 oss <<
"{status = fill not complete" 4805 <<
", global rows = " << getGlobalNumRows()
4812 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4816 const Teuchos::EVerbosityLevel verbLevel)
const 4818 using Teuchos::ArrayView;
4819 using Teuchos::Comm;
4821 using Teuchos::VERB_DEFAULT;
4822 using Teuchos::VERB_NONE;
4823 using Teuchos::VERB_LOW;
4824 using Teuchos::VERB_MEDIUM;
4825 using Teuchos::VERB_HIGH;
4826 using Teuchos::VERB_EXTREME;
4830 Teuchos::EVerbosityLevel vl = verbLevel;
4831 if (vl == VERB_DEFAULT) vl = VERB_LOW;
4832 RCP<const Comm<int> > comm = this->getComm();
4833 const int myImageID = comm->getRank(),
4834 numImages = comm->getSize();
4836 for (
size_t dec=10; dec<getGlobalNumRows(); dec *= 10) {
4839 width = std::max<size_t> (width,
static_cast<size_t> (11)) + 2;
4840 Teuchos::OSTab tab (out);
4848 if (vl != VERB_NONE) {
4849 if (myImageID == 0) out << this->description() << std::endl;
4851 if (isFillComplete() && myImageID == 0) {
4852 out <<
"Global max number of row entries = " << globalMaxNumRowEntries_ << std::endl;
4855 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4856 if (myImageID == 0) out <<
"\nRow map: " << std::endl;
4857 rowMap_->describe(out,vl);
4858 if (colMap_ != Teuchos::null) {
4859 if (myImageID == 0) out <<
"\nColumn map: " << std::endl;
4860 colMap_->describe(out,vl);
4862 if (domainMap_ != Teuchos::null) {
4863 if (myImageID == 0) out <<
"\nDomain map: " << std::endl;
4864 domainMap_->describe(out,vl);
4866 if (rangeMap_ != Teuchos::null) {
4867 if (myImageID == 0) out <<
"\nRange map: " << std::endl;
4868 rangeMap_->describe(out,vl);
4872 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4873 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4874 if (myImageID == imageCtr) {
4875 out <<
"Node ID = " << imageCtr << std::endl
4876 <<
"Node number of entries = " << this->getNodeNumEntries () << std::endl
4877 <<
"Node max number of entries = " << nodeMaxNumRowEntries_ << std::endl;
4878 if (! indicesAreAllocated ()) {
4879 out <<
"Indices are not allocated." << std::endl;
4888 if (vl == VERB_HIGH || vl == VERB_EXTREME) {
4889 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4890 if (myImageID == imageCtr) {
4891 out << std::setw(width) <<
"Node ID" 4892 << std::setw(width) <<
"Global Row" 4893 << std::setw(width) <<
"Num Entries";
4894 if (vl == VERB_EXTREME) {
4898 const LocalOrdinal lclNumRows =
4899 static_cast<LocalOrdinal
> (this->getNodeNumRows ());
4900 for (LocalOrdinal r=0; r < lclNumRows; ++r) {
4901 const RowInfo rowinfo = this->getRowInfo (r);
4902 GlobalOrdinal gid = rowMap_->getGlobalElement(r);
4903 out << std::setw(width) << myImageID
4904 << std::setw(width) << gid
4905 << std::setw(width) << rowinfo.numEntries;
4906 if (vl == VERB_EXTREME) {
4908 if (isGloballyIndexed()) {
4909 ArrayView<const GlobalOrdinal> rowview = getGlobalView(rowinfo);
4910 for (
size_t j=0; j < rowinfo.numEntries; ++j) out << rowview[j] <<
" ";
4912 else if (isLocallyIndexed()) {
4913 ArrayView<const LocalOrdinal> rowview = getLocalView(rowinfo);
4914 for (
size_t j=0; j < rowinfo.numEntries; ++j) out << colMap_->getGlobalElement(rowview[j]) <<
" ";
4929 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4940 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4945 const size_t numSameIDs,
4946 const Kokkos::DualView<
const local_ordinal_type*,
4947 buffer_device_type>& permuteToLIDs,
4948 const Kokkos::DualView<
const local_ordinal_type*,
4949 buffer_device_type>& permuteFromLIDs)
4952 using LO = local_ordinal_type;
4953 using GO = global_ordinal_type;
4956 const char tfecfFuncName[] =
"copyAndPermute: ";
4957 const bool verbose = verbose_;
4959 std::unique_ptr<std::string> prefix;
4961 prefix = this->createPrefix(
"CrsGraph",
"copyAndPermute");
4962 std::ostringstream os;
4963 os << *prefix << endl;
4964 std::cerr << os.str ();
4967 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4968 (permuteToLIDs.extent (0) != permuteFromLIDs.extent (0),
4969 std::runtime_error,
"permuteToLIDs.extent(0) = " 4970 << permuteToLIDs.extent (0) <<
" != permuteFromLIDs.extent(0) = " 4971 << permuteFromLIDs.extent (0) <<
".");
4975 const row_graph_type& srcRowGraph =
4976 dynamic_cast<const row_graph_type&
> (source);
4979 std::ostringstream os;
4980 os << *prefix <<
"Compute padding" << endl;
4981 std::cerr << os.str ();
4983 auto padding = computeCrsPadding(srcRowGraph, numSameIDs,
4984 permuteToLIDs, permuteFromLIDs, verbose);
4985 applyCrsPadding(*padding, verbose);
4990 const this_type* srcCrsGraph =
4991 dynamic_cast<const this_type*
> (&source);
4993 const map_type& srcRowMap = *(srcRowGraph.getRowMap());
4994 const map_type& tgtRowMap = *(getRowMap());
4995 const bool src_filled = srcRowGraph.isFillComplete();
4996 Teuchos::Array<GO> row_copy;
5002 if (src_filled || srcCrsGraph ==
nullptr) {
5004 std::ostringstream os;
5005 os << *prefix <<
"src_filled || srcCrsGraph == nullptr" << endl;
5006 std::cerr << os.str ();
5013 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
5014 const GO gid = srcRowMap.getGlobalElement (myid);
5015 size_t row_length = srcRowGraph.getNumEntriesInGlobalRow (gid);
5016 row_copy.resize (row_length);
5017 size_t check_row_length = 0;
5018 srcRowGraph.getGlobalRowCopy (gid, row_copy (), check_row_length);
5019 this->insertGlobalIndices (gid, row_copy ());
5023 std::ostringstream os;
5024 os << *prefix <<
"! src_filled && srcCrsGraph != nullptr" << endl;
5025 std::cerr << os.str ();
5027 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
5028 const GO gid = srcRowMap.getGlobalElement (myid);
5029 Teuchos::ArrayView<const GO> row;
5030 srcCrsGraph->getGlobalRowView (gid, row);
5031 this->insertGlobalIndices (gid, row);
5038 auto permuteToLIDs_h = permuteToLIDs.view_host ();
5039 auto permuteFromLIDs_h = permuteFromLIDs.view_host ();
5041 if (src_filled || srcCrsGraph ==
nullptr) {
5042 for (LO i = 0; i < static_cast<LO> (permuteToLIDs_h.extent (0)); ++i) {
5043 const GO mygid = tgtRowMap.getGlobalElement (permuteToLIDs_h[i]);
5044 const GO srcgid = srcRowMap.getGlobalElement (permuteFromLIDs_h[i]);
5045 size_t row_length = srcRowGraph.getNumEntriesInGlobalRow (srcgid);
5046 row_copy.resize (row_length);
5047 size_t check_row_length = 0;
5048 srcRowGraph.getGlobalRowCopy (srcgid, row_copy (), check_row_length);
5049 this->insertGlobalIndices (mygid, row_copy ());
5052 for (LO i = 0; i < static_cast<LO> (permuteToLIDs_h.extent (0)); ++i) {
5053 const GO mygid = tgtRowMap.getGlobalElement (permuteToLIDs_h[i]);
5054 const GO srcgid = srcRowMap.getGlobalElement (permuteFromLIDs_h[i]);
5055 Teuchos::ArrayView<const GO> row;
5056 srcCrsGraph->getGlobalRowView (srcgid, row);
5057 this->insertGlobalIndices (mygid, row);
5062 std::ostringstream os;
5063 os << *prefix <<
"Done" << endl;
5064 std::cerr << os.str ();
5068 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5070 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5071 applyCrsPadding(
const padding_type& padding,
5074 using Details::ProfilingRegion;
5078 using execution_space =
typename device_type::execution_space;
5079 using row_ptrs_type =
5080 typename local_graph_type::row_map_type::non_const_type;
5081 using range_policy =
5082 Kokkos::RangePolicy<execution_space, Kokkos::IndexType<LO>>;
5083 const char tfecfFuncName[] =
"applyCrsPadding";
5084 ProfilingRegion regionCAP(
"Tpetra::CrsGraph::applyCrsPadding");
5086 std::unique_ptr<std::string> prefix;
5088 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5089 std::ostringstream os;
5090 os << *prefix <<
"padding: ";
5093 std::cerr << os.str();
5095 const int myRank = ! verbose ? -1 : [&] () {
5096 auto map = this->getMap();
5097 if (map.is_null()) {
5100 auto comm = map->getComm();
5101 if (comm.is_null()) {
5104 return comm->getRank();
5113 if (! indicesAreAllocated()) {
5115 std::ostringstream os;
5116 os << *prefix <<
"Call allocateIndices" << endl;
5117 std::cerr << os.str();
5119 allocateIndices(GlobalIndices, verbose);
5121 TEUCHOS_ASSERT( indicesAreAllocated() );
5127 std::ostringstream os;
5128 os << *prefix <<
"Allocate row_ptrs_beg: " 5129 << k_rowPtrs_.extent(0) << endl;
5130 std::cerr << os.str();
5132 using Kokkos::view_alloc;
5133 using Kokkos::WithoutInitializing;
5134 row_ptrs_type row_ptrs_beg(
5135 view_alloc(
"row_ptrs_beg", WithoutInitializing),
5136 k_rowPtrs_.extent(0));
5139 const size_t N = row_ptrs_beg.extent(0) == 0 ? size_t(0) :
5140 size_t(row_ptrs_beg.extent(0) - 1);
5142 std::ostringstream os;
5143 os << *prefix <<
"Allocate row_ptrs_end: " << N << endl;
5144 std::cerr << os.str();
5146 row_ptrs_type row_ptrs_end(
5147 view_alloc(
"row_ptrs_end", WithoutInitializing), N);
5149 const bool refill_num_row_entries = k_numRowEntries_.extent(0) != 0;
5150 if (refill_num_row_entries) {
5153 auto num_row_entries = this->k_numRowEntries_;
5154 Kokkos::parallel_for
5155 (
"Fill end row pointers", range_policy(0, N),
5156 KOKKOS_LAMBDA (
const size_t i) {
5157 row_ptrs_end(i) = row_ptrs_beg(i) + num_row_entries(i);
5164 Kokkos::parallel_for
5165 (
"Fill end row pointers", range_policy(0, N),
5166 KOKKOS_LAMBDA (
const size_t i) {
5167 row_ptrs_end(i) = row_ptrs_beg(i+1);
5171 if (isGloballyIndexed()) {
5173 padding, myRank, verbose);
5177 padding, myRank, verbose);
5180 if (refill_num_row_entries) {
5181 auto num_row_entries = this->k_numRowEntries_;
5182 Kokkos::parallel_for
5183 (
"Fill num entries", range_policy(0, N),
5184 KOKKOS_LAMBDA (
const size_t i) {
5185 num_row_entries(i) = row_ptrs_end(i) - row_ptrs_beg(i);
5189 std::ostringstream os;
5190 os << *prefix <<
"Reassign k_rowPtrs_; old size: " 5191 << k_rowPtrs_.extent(0) <<
", new size: " 5192 << row_ptrs_beg.extent(0) << endl;
5193 std::cerr << os.str();
5194 TEUCHOS_ASSERT( k_rowPtrs_.extent(0) == row_ptrs_beg.extent(0) );
5196 this->k_rowPtrs_ = row_ptrs_beg;
5199 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5201 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5203 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5205 const RowGraph<LocalOrdinal,GlobalOrdinal,Node>& source,
5206 const size_t numSameIDs,
5207 const Kokkos::DualView<
const local_ordinal_type*,
5208 buffer_device_type>& permuteToLIDs,
5209 const Kokkos::DualView<
const local_ordinal_type*,
5210 buffer_device_type>& permuteFromLIDs,
5211 const bool verbose)
const 5216 std::unique_ptr<std::string> prefix;
5219 "computeCrsPadding(same & permute)");
5220 std::ostringstream os;
5221 os << *prefix <<
"{numSameIDs: " << numSameIDs
5222 <<
", numPermutes: " << permuteFromLIDs.extent(0) <<
"}" 5224 std::cerr << os.str();
5227 const int myRank = [&] () {
5228 auto comm = rowMap_.is_null() ? Teuchos::null :
5230 return comm.is_null() ? -1 : comm->getRank();
5232 std::unique_ptr<padding_type> padding(
5233 new padding_type(myRank, numSameIDs,
5234 permuteFromLIDs.extent(0)));
5244 computeCrsPaddingForSameIDs(*padding, source,
5245 static_cast<LO>(numSameIDs));
5246 computeCrsPaddingForPermutedIDs(*padding, source, permuteToLIDs,
5251 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5253 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5254 computeCrsPaddingForSameIDs(
5255 padding_type& padding,
5256 const RowGraph<local_ordinal_type, global_ordinal_type,
5258 const local_ordinal_type numSameIDs)
const 5261 using GO = global_ordinal_type;
5262 using Details::Impl::getRowGraphGlobalRow;
5264 const char tfecfFuncName[] =
"computeCrsPaddingForSameIds";
5266 std::unique_ptr<std::string> prefix;
5267 const bool verbose = verbose_;
5269 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5270 std::ostringstream os;
5271 os << *prefix <<
"numSameIDs: " << numSameIDs << endl;
5272 std::cerr << os.str();
5275 if (numSameIDs == 0) {
5279 const map_type& srcRowMap = *(source.getRowMap());
5280 const map_type& tgtRowMap = *rowMap_;
5281 using this_type = CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
5282 const this_type* srcCrs =
dynamic_cast<const this_type*
>(&source);
5283 const bool src_is_unique =
5284 srcCrs ==
nullptr ? false : srcCrs->isMerged();
5285 const bool tgt_is_unique = this->isMerged();
5287 std::vector<GO> srcGblColIndsScratch;
5288 std::vector<GO> tgtGblColIndsScratch;
5289 for (LO lclRowInd = 0; lclRowInd < numSameIDs; ++lclRowInd) {
5290 const GO srcGblRowInd = srcRowMap.getGlobalElement(lclRowInd);
5291 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(lclRowInd);
5292 auto srcGblColInds = getRowGraphGlobalRow(
5293 srcGblColIndsScratch, source, srcGblRowInd);
5294 auto tgtGblColInds = getRowGraphGlobalRow(
5295 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5296 padding.update_same(lclRowInd, tgtGblColInds.getRawPtr(),
5297 tgtGblColInds.size(), tgt_is_unique,
5298 srcGblColInds.getRawPtr(),
5299 srcGblColInds.size(), src_is_unique);
5302 std::ostringstream os;
5303 os << *prefix <<
"Done" << endl;
5304 std::cerr << os.str();
5308 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5310 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5311 computeCrsPaddingForPermutedIDs(
5312 padding_type& padding,
5313 const RowGraph<local_ordinal_type, global_ordinal_type,
5315 const Kokkos::DualView<
const local_ordinal_type*,
5316 buffer_device_type>& permuteToLIDs,
5317 const Kokkos::DualView<
const local_ordinal_type*,
5318 buffer_device_type>& permuteFromLIDs)
const 5321 using GO = global_ordinal_type;
5322 using Details::Impl::getRowGraphGlobalRow;
5324 const char tfecfFuncName[] =
"computeCrsPaddingForPermutedIds";
5326 std::unique_ptr<std::string> prefix;
5327 const bool verbose = verbose_;
5329 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5330 std::ostringstream os;
5331 os << *prefix <<
"permuteToLIDs.extent(0): " 5332 << permuteToLIDs.extent(0)
5333 <<
", permuteFromLIDs.extent(0): " 5334 << permuteFromLIDs.extent(0) << endl;
5335 std::cerr << os.str();
5338 if (permuteToLIDs.extent(0) == 0) {
5342 const map_type& srcRowMap = *(source.getRowMap());
5343 const map_type& tgtRowMap = *rowMap_;
5344 using this_type = CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
5345 const this_type* srcCrs =
dynamic_cast<const this_type*
>(&source);
5346 const bool src_is_unique =
5347 srcCrs ==
nullptr ? false : srcCrs->isMerged();
5348 const bool tgt_is_unique = this->isMerged();
5350 TEUCHOS_ASSERT( ! permuteToLIDs.need_sync_host() );
5351 auto permuteToLIDs_h = permuteToLIDs.view_host();
5352 TEUCHOS_ASSERT( ! permuteFromLIDs.need_sync_host() );
5353 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
5355 std::vector<GO> srcGblColIndsScratch;
5356 std::vector<GO> tgtGblColIndsScratch;
5357 const LO numPermutes =
static_cast<LO
>(permuteToLIDs_h.extent(0));
5358 for (LO whichPermute = 0; whichPermute < numPermutes; ++whichPermute) {
5359 const LO srcLclRowInd = permuteFromLIDs_h[whichPermute];
5360 const GO srcGblRowInd = srcRowMap.getGlobalElement(srcLclRowInd);
5361 auto srcGblColInds = getRowGraphGlobalRow(
5362 srcGblColIndsScratch, source, srcGblRowInd);
5363 const LO tgtLclRowInd = permuteToLIDs_h[whichPermute];
5364 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(tgtLclRowInd);
5365 auto tgtGblColInds = getRowGraphGlobalRow(
5366 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5367 padding.update_permute(whichPermute, tgtLclRowInd,
5368 tgtGblColInds.getRawPtr(),
5369 tgtGblColInds.size(), tgt_is_unique,
5370 srcGblColInds.getRawPtr(),
5371 srcGblColInds.size(), src_is_unique);
5375 std::ostringstream os;
5376 os << *prefix <<
"Done" << endl;
5377 std::cerr << os.str();
5381 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5383 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5385 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5386 computeCrsPaddingForImports(
5387 const Kokkos::DualView<
const local_ordinal_type*,
5388 buffer_device_type>& importLIDs,
5389 Kokkos::DualView<packet_type*, buffer_device_type> imports,
5390 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
5391 const bool verbose)
const 5393 using Details::Impl::getRowGraphGlobalRow;
5396 using GO = global_ordinal_type;
5397 const char tfecfFuncName[] =
"computeCrsPaddingForImports";
5399 std::unique_ptr<std::string> prefix;
5401 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5402 std::ostringstream os;
5403 os << *prefix <<
"importLIDs.extent(0): " 5404 << importLIDs.extent(0)
5405 <<
", imports.extent(0): " 5406 << imports.extent(0)
5407 <<
", numPacketsPerLID.extent(0): " 5408 << numPacketsPerLID.extent(0) << endl;
5409 std::cerr << os.str();
5412 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5413 const int myRank = [&] () {
5414 auto comm = rowMap_.is_null() ? Teuchos::null :
5416 return comm.is_null() ? -1 : comm->getRank();
5418 std::unique_ptr<padding_type> padding(
5419 new padding_type(myRank, numImports));
5421 if (imports.need_sync_host()) {
5422 imports.sync_host();
5424 auto imports_h = imports.view_host();
5425 if (numPacketsPerLID.need_sync_host ()) {
5426 numPacketsPerLID.sync_host();
5428 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5430 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
5431 auto importLIDs_h = importLIDs.view_host();
5433 const map_type& tgtRowMap = *rowMap_;
5437 constexpr
bool src_is_unique =
false;
5438 const bool tgt_is_unique = isMerged();
5440 std::vector<GO> tgtGblColIndsScratch;
5442 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5447 const LO origSrcNumEnt =
5448 static_cast<LO
>(numPacketsPerLID_h[whichImport]);
5449 GO*
const srcGblColInds = imports_h.data() + offset;
5451 const LO tgtLclRowInd = importLIDs_h[whichImport];
5452 const GO tgtGblRowInd =
5453 tgtRowMap.getGlobalElement(tgtLclRowInd);
5454 auto tgtGblColInds = getRowGraphGlobalRow(
5455 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5456 const size_t origTgtNumEnt(tgtGblColInds.size());
5458 padding->update_import(whichImport, tgtLclRowInd,
5459 tgtGblColInds.getRawPtr(),
5460 origTgtNumEnt, tgt_is_unique,
5462 origSrcNumEnt, src_is_unique);
5463 offset += origSrcNumEnt;
5467 std::ostringstream os;
5468 os << *prefix <<
"Done" << endl;
5469 std::cerr << os.str();
5474 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5476 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5478 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5479 computePaddingForCrsMatrixUnpack(
5480 const Kokkos::DualView<
const local_ordinal_type*,
5481 buffer_device_type>& importLIDs,
5482 Kokkos::DualView<char*, buffer_device_type> imports,
5483 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
5484 const bool verbose)
const 5486 using Details::Impl::getRowGraphGlobalRow;
5487 using Details::PackTraits;
5490 using GO = global_ordinal_type;
5491 const char tfecfFuncName[] =
"computePaddingForCrsMatrixUnpack";
5493 std::unique_ptr<std::string> prefix;
5495 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5496 std::ostringstream os;
5497 os << *prefix <<
"importLIDs.extent(0): " 5498 << importLIDs.extent(0)
5499 <<
", imports.extent(0): " 5500 << imports.extent(0)
5501 <<
", numPacketsPerLID.extent(0): " 5502 << numPacketsPerLID.extent(0) << endl;
5503 std::cerr << os.str();
5505 const bool extraVerbose =
5506 verbose && Details::Behavior::verbose(
"CrsPadding");
5508 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5509 TEUCHOS_ASSERT( LO(numPacketsPerLID.extent(0)) >= numImports );
5510 const int myRank = [&] () {
5511 auto comm = rowMap_.is_null() ? Teuchos::null :
5513 return comm.is_null() ? -1 : comm->getRank();
5515 std::unique_ptr<padding_type> padding(
5516 new padding_type(myRank, numImports));
5518 if (imports.need_sync_host()) {
5519 imports.sync_host();
5521 auto imports_h = imports.view_host();
5522 if (numPacketsPerLID.need_sync_host ()) {
5523 numPacketsPerLID.sync_host();
5525 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5527 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
5528 auto importLIDs_h = importLIDs.view_host();
5530 const map_type& tgtRowMap = *rowMap_;
5534 constexpr
bool src_is_unique =
false;
5535 const bool tgt_is_unique = isMerged();
5537 std::vector<GO> srcGblColIndsScratch;
5538 std::vector<GO> tgtGblColIndsScratch;
5540 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5545 const size_t numBytes = numPacketsPerLID_h[whichImport];
5547 std::ostringstream os;
5548 os << *prefix <<
"whichImport=" << whichImport
5549 <<
", numImports=" << numImports
5550 <<
", numBytes=" << numBytes << endl;
5551 std::cerr << os.str();
5553 if (numBytes == 0) {
5556 LO origSrcNumEnt = 0;
5557 const size_t numEntBeg = offset;
5558 const size_t numEntLen =
5560 TEUCHOS_ASSERT( numBytes >= numEntLen );
5561 TEUCHOS_ASSERT( imports_h.extent(0) >= numEntBeg + numEntLen );
5563 imports_h.data() + numEntBeg);
5565 std::ostringstream os;
5566 os << *prefix <<
"whichImport=" << whichImport
5567 <<
", numImports=" << numImports
5568 <<
", origSrcNumEnt=" << origSrcNumEnt << endl;
5569 std::cerr << os.str();
5571 TEUCHOS_ASSERT( origSrcNumEnt >= LO(0) );
5572 TEUCHOS_ASSERT( numBytes >=
size_t(numEntLen + origSrcNumEnt *
sizeof(GO)) );
5573 const size_t gidsBeg = numEntBeg + numEntLen;
5574 if (srcGblColIndsScratch.size() < size_t(origSrcNumEnt)) {
5575 srcGblColIndsScratch.resize(origSrcNumEnt);
5577 GO*
const srcGblColInds = srcGblColIndsScratch.data();
5578 PackTraits<GO>::unpackArray(srcGblColInds,
5579 imports_h.data() + gidsBeg,
5581 const LO tgtLclRowInd = importLIDs_h[whichImport];
5582 const GO tgtGblRowInd =
5583 tgtRowMap.getGlobalElement(tgtLclRowInd);
5584 auto tgtGblColInds = getRowGraphGlobalRow(
5585 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5586 const size_t origNumTgtEnt(tgtGblColInds.size());
5589 std::ostringstream os;
5590 os << *prefix <<
"whichImport=" << whichImport
5591 <<
", numImports=" << numImports
5592 <<
": Call padding->update_import" << endl;
5593 std::cerr << os.str();
5595 padding->update_import(whichImport, tgtLclRowInd,
5596 tgtGblColInds.getRawPtr(),
5597 origNumTgtEnt, tgt_is_unique,
5599 origSrcNumEnt, src_is_unique);
5604 std::ostringstream os;
5605 os << *prefix <<
"Done" << endl;
5606 std::cerr << os.str();
5611 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5613 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5615 (
const SrcDistObject& source,
5616 const Kokkos::DualView<
const local_ordinal_type*,
5617 buffer_device_type>& exportLIDs,
5618 Kokkos::DualView<packet_type*,
5619 buffer_device_type>& exports,
5620 Kokkos::DualView<
size_t*,
5621 buffer_device_type> numPacketsPerLID,
5622 size_t& constantNumPackets,
5623 Distributor& distor)
5626 using GO = global_ordinal_type;
5628 using crs_graph_type =
5629 CrsGraph<local_ordinal_type, global_ordinal_type, node_type>;
5630 using row_graph_type =
5631 RowGraph<local_ordinal_type, global_ordinal_type, node_type>;
5632 const char tfecfFuncName[] =
"packAndPrepare: ";
5633 ProfilingRegion region_papn (
"Tpetra::CrsGraph::packAndPrepare");
5635 const bool verbose = verbose_;
5636 std::unique_ptr<std::string> prefix;
5638 prefix = this->
createPrefix(
"CrsGraph",
"packAndPrepare");
5639 std::ostringstream os;
5640 os << *prefix <<
"Start" << endl;
5641 std::cerr << os.str();
5644 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5645 (exportLIDs.extent (0) != numPacketsPerLID.extent (0),
5647 "exportLIDs.extent(0) = " << exportLIDs.extent (0)
5648 <<
" != numPacketsPerLID.extent(0) = " << numPacketsPerLID.extent (0)
5650 const row_graph_type* srcRowGraphPtr =
5651 dynamic_cast<const row_graph_type*
> (&source);
5652 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5653 (srcRowGraphPtr ==
nullptr, std::invalid_argument,
"Source of an Export " 5654 "or Import operation to a CrsGraph must be a RowGraph with the same " 5655 "template parameters.");
5659 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5660 (this->isFillComplete (), std::runtime_error,
5661 "The target graph of an Import or Export must not be fill complete.");
5663 const crs_graph_type* srcCrsGraphPtr =
5664 dynamic_cast<const crs_graph_type*
> (&source);
5666 if (srcCrsGraphPtr ==
nullptr) {
5667 using Teuchos::ArrayView;
5671 std::ostringstream os;
5672 os << *prefix <<
"Source is a RowGraph but not a CrsGraph" 5674 std::cerr << os.str();
5681 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
5682 auto exportLIDs_h = exportLIDs.view_host ();
5683 ArrayView<const LO> exportLIDs_av (exportLIDs_h.data (),
5684 exportLIDs_h.extent (0));
5685 Teuchos::Array<GO> exports_a;
5687 numPacketsPerLID.clear_sync_state ();
5688 numPacketsPerLID.modify_host ();
5689 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
5690 ArrayView<size_t> numPacketsPerLID_av (numPacketsPerLID_h.data (),
5691 numPacketsPerLID_h.extent (0));
5692 srcRowGraphPtr->pack (exportLIDs_av, exports_a, numPacketsPerLID_av,
5693 constantNumPackets, distor);
5694 const size_t newSize =
static_cast<size_t> (exports_a.size ());
5695 if (static_cast<size_t> (exports.extent (0)) != newSize) {
5696 using exports_dv_type = Kokkos::DualView<packet_type*, buffer_device_type>;
5697 exports = exports_dv_type (
"exports", newSize);
5699 Kokkos::View<
const packet_type*, Kokkos::HostSpace,
5700 Kokkos::MemoryUnmanaged> exports_a_h (exports_a.getRawPtr (), newSize);
5701 exports.clear_sync_state ();
5702 exports.modify_host ();
5706 else if (! getColMap ().is_null () &&
5707 (lclGraph_.row_map.extent (0) != 0 ||
5708 getRowMap ()->getNodeNumElements () == 0)) {
5710 std::ostringstream os;
5711 os << *prefix <<
"packCrsGraphNew path" << endl;
5712 std::cerr << os.str();
5714 using export_pids_type =
5715 Kokkos::DualView<const int*, buffer_device_type>;
5716 export_pids_type exportPIDs;
5720 packCrsGraphNew<LO,GO,NT> (*srcCrsGraphPtr, exportLIDs, exportPIDs,
5721 exports, numPacketsPerLID,
5722 constantNumPackets,
false, distor);
5725 srcCrsGraphPtr->packFillActiveNew (exportLIDs, exports, numPacketsPerLID,
5726 constantNumPackets, distor);
5730 std::ostringstream os;
5731 os << *prefix <<
"Done" << endl;
5732 std::cerr << os.str();
5736 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5738 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5739 pack (
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5740 Teuchos::Array<GlobalOrdinal>& exports,
5741 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5742 size_t& constantNumPackets,
5745 auto col_map = this->getColMap();
5747 if( !col_map.is_null() && (lclGraph_.row_map.extent(0) != 0 || getRowMap()->getNodeNumElements() ==0)) {
5749 packCrsGraph<LocalOrdinal,GlobalOrdinal,Node>(*
this, exports, numPacketsPerLID,
5750 exportLIDs, constantNumPackets, distor);
5753 this->packFillActive(exportLIDs, exports, numPacketsPerLID,
5754 constantNumPackets, distor);
5758 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5761 packFillActive (
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5762 Teuchos::Array<GlobalOrdinal>& exports,
5763 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5764 size_t& constantNumPackets,
5768 using LO = LocalOrdinal;
5769 using GO = GlobalOrdinal;
5770 using host_execution_space =
5771 typename Kokkos::View<size_t*, device_type>::
5772 HostMirror::execution_space;
5773 using device_execution_space =
5774 typename device_type::execution_space;
5775 const char tfecfFuncName[] =
"packFillActive: ";
5776 const bool verbose = verbose_;
5778 const auto numExportLIDs = exportLIDs.size ();
5779 std::unique_ptr<std::string> prefix;
5781 prefix = this->createPrefix(
"CrsGraph",
"allocateIndices");
5782 std::ostringstream os;
5783 os << *prefix <<
"numExportLIDs=" << numExportLIDs << endl;
5784 std::cerr << os.str();
5786 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5787 (numExportLIDs != numPacketsPerLID.size (), std::runtime_error,
5788 "exportLIDs.size() = " << numExportLIDs <<
" != numPacketsPerLID.size()" 5789 " = " << numPacketsPerLID.size () <<
".");
5793 device_execution_space().fence ();
5795 const map_type& rowMap = * (this->getRowMap ());
5796 const map_type*
const colMapPtr = this->colMap_.getRawPtr ();
5797 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5798 (this->isLocallyIndexed () && colMapPtr ==
nullptr, std::logic_error,
5799 "This graph claims to be locally indexed, but its column Map is nullptr. " 5800 "This should never happen. Please report this bug to the Tpetra " 5804 constantNumPackets = 0;
5808 size_t*
const numPacketsPerLID_raw = numPacketsPerLID.getRawPtr ();
5809 const LO*
const exportLIDs_raw = exportLIDs.getRawPtr ();
5816 Kokkos::RangePolicy<host_execution_space, LO> inputRange (0, numExportLIDs);
5817 size_t totalNumPackets = 0;
5818 size_t errCount = 0;
5821 typedef Kokkos::Device<host_execution_space, Kokkos::HostSpace>
5823 Kokkos::View<size_t, host_device_type> errCountView (&errCount);
5824 constexpr
size_t ONE = 1;
5826 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::pack: totalNumPackets",
5828 [=] (
const LO& i,
size_t& curTotalNumPackets) {
5829 const GO gblRow = rowMap.getGlobalElement (exportLIDs_raw[i]);
5830 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
5831 Kokkos::atomic_add (&errCountView(), ONE);
5832 numPacketsPerLID_raw[i] = 0;
5835 const size_t numEnt = this->getNumEntriesInGlobalRow (gblRow);
5836 numPacketsPerLID_raw[i] = numEnt;
5837 curTotalNumPackets += numEnt;
5843 std::ostringstream os;
5844 os << *prefix <<
"totalNumPackets=" << totalNumPackets << endl;
5845 std::cerr << os.str();
5847 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5848 (errCount != 0, std::logic_error,
"totalNumPackets count encountered " 5849 "one or more errors! errCount = " << errCount
5850 <<
", totalNumPackets = " << totalNumPackets <<
".");
5854 exports.resize (totalNumPackets);
5856 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5857 (! this->supportsRowViews (), std::logic_error,
5858 "this->supportsRowViews() returns false; this should never happen. " 5859 "Please report this bug to the Tpetra developers.");
5865 std::ostringstream os;
5866 os << *prefix <<
"Pack into exports" << endl;
5867 std::cerr << os.str();
5872 GO*
const exports_raw = exports.getRawPtr ();
5874 Kokkos::parallel_scan (
"Tpetra::CrsGraph::pack: pack from views",
5875 inputRange, [=, &prefix]
5876 (
const LO i,
size_t& exportsOffset,
const bool final) {
5877 const size_t curOffset = exportsOffset;
5878 const GO gblRow = rowMap.getGlobalElement (exportLIDs_raw[i]);
5879 const RowInfo rowInfo =
5880 this->getRowInfoFromGlobalRowIndex (gblRow);
5882 using TDO = Tpetra::Details::OrdinalTraits<size_t>;
5883 if (rowInfo.localRow == TDO::invalid ()) {
5885 std::ostringstream os;
5886 os << *prefix <<
": INVALID rowInfo: i=" << i
5887 <<
", lclRow=" << exportLIDs_raw[i] << endl;
5888 std::cerr << os.str();
5890 Kokkos::atomic_add (&errCountView(), ONE);
5892 else if (curOffset + rowInfo.numEntries > totalNumPackets) {
5894 std::ostringstream os;
5895 os << *prefix <<
": UH OH! For i=" << i <<
", lclRow=" 5896 << exportLIDs_raw[i] <<
", gblRow=" << gblRow <<
", curOffset " 5897 "(= " << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5898 <<
") > totalNumPackets (= " << totalNumPackets <<
")." 5900 std::cerr << os.str();
5902 Kokkos::atomic_add (&errCountView(), ONE);
5905 const LO numEnt =
static_cast<LO
> (rowInfo.numEntries);
5906 if (this->isLocallyIndexed ()) {
5907 const LO* lclColInds =
nullptr;
5910 this->getLocalViewRawConst (lclColInds, capacity, rowInfo);
5913 for (LO k = 0; k < numEnt; ++k) {
5914 const LO lclColInd = lclColInds[k];
5915 const GO gblColInd = colMapPtr->getGlobalElement (lclColInd);
5919 exports_raw[curOffset + k] = gblColInd;
5922 exportsOffset = curOffset + numEnt;
5925 Kokkos::atomic_add (&errCountView(), ONE);
5928 else if (this->isGloballyIndexed ()) {
5929 const GO* gblColInds =
nullptr;
5932 this->getGlobalViewRawConst (gblColInds, capacity, rowInfo);
5935 for (LO k = 0; k < numEnt; ++k) {
5936 const GO gblColInd = gblColInds[k];
5940 exports_raw[curOffset + k] = gblColInd;
5943 exportsOffset = curOffset + numEnt;
5946 Kokkos::atomic_add (&errCountView(), ONE);
5957 device_execution_space().fence ();
5959 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5960 (errCount != 0, std::logic_error,
"Packing encountered " 5961 "one or more errors! errCount = " << errCount
5962 <<
", totalNumPackets = " << totalNumPackets <<
".");
5965 std::ostringstream os;
5966 os << *prefix <<
"Done" << endl;
5967 std::cerr << os.str();
5971 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5973 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5974 packFillActiveNew (
const Kokkos::DualView<
const local_ordinal_type*,
5975 buffer_device_type>& exportLIDs,
5976 Kokkos::DualView<packet_type*,
5977 buffer_device_type>& exports,
5978 Kokkos::DualView<
size_t*,
5979 buffer_device_type> numPacketsPerLID,
5980 size_t& constantNumPackets,
5981 Distributor& distor)
const 5985 using GO = global_ordinal_type;
5986 using host_execution_space =
typename Kokkos::View<
size_t*,
5987 device_type>::HostMirror::execution_space;
5988 using host_device_type =
5989 Kokkos::Device<host_execution_space, Kokkos::HostSpace>;
5990 using device_execution_space =
typename device_type::execution_space;
5991 using exports_dv_type =
5992 Kokkos::DualView<packet_type*, buffer_device_type>;
5993 const char tfecfFuncName[] =
"packFillActiveNew: ";
5994 const bool verbose = verbose_;
5996 const auto numExportLIDs = exportLIDs.extent (0);
5997 std::unique_ptr<std::string> prefix;
5999 prefix = this->
createPrefix(
"CrsGraph",
"packFillActiveNew");
6000 std::ostringstream os;
6001 os << *prefix <<
"numExportLIDs: " << numExportLIDs
6002 <<
", numPacketsPerLID.extent(0): " 6003 << numPacketsPerLID.extent(0) << endl;
6004 std::cerr << os.str();
6006 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6007 (numExportLIDs != numPacketsPerLID.extent (0), std::runtime_error,
6008 "exportLIDs.extent(0) = " << numExportLIDs
6009 <<
" != numPacketsPerLID.extent(0) = " 6010 << numPacketsPerLID.extent (0) <<
".");
6011 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
6012 auto exportLIDs_h = exportLIDs.view_host ();
6016 device_execution_space().fence ();
6018 const map_type& rowMap = * (this->getRowMap ());
6019 const map_type*
const colMapPtr = this->colMap_.getRawPtr ();
6020 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6021 (this->isLocallyIndexed () && colMapPtr ==
nullptr, std::logic_error,
6022 "This graph claims to be locally indexed, but its column Map is nullptr. " 6023 "This should never happen. Please report this bug to the Tpetra " 6027 constantNumPackets = 0;
6029 numPacketsPerLID.clear_sync_state ();
6030 numPacketsPerLID.modify_host ();
6031 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
6038 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
6039 range_type inputRange (0, numExportLIDs);
6040 size_t totalNumPackets = 0;
6041 size_t errCount = 0;
6044 Kokkos::View<size_t, host_device_type> errCountView (&errCount);
6045 constexpr
size_t ONE = 1;
6048 std::ostringstream os;
6049 os << *prefix <<
"Compute totalNumPackets" << endl;
6050 std::cerr << os.str ();
6053 Kokkos::parallel_reduce
6054 (
"Tpetra::CrsGraph::pack: totalNumPackets",
6056 [=, &prefix] (
const LO i,
size_t& curTotalNumPackets) {
6057 const LO lclRow = exportLIDs_h[i];
6058 const GO gblRow = rowMap.getGlobalElement (lclRow);
6059 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
6061 std::ostringstream os;
6062 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
6063 <<
" not in row Map on this process" << endl;
6064 std::cerr << os.str();
6066 Kokkos::atomic_add (&errCountView(), ONE);
6067 numPacketsPerLID_h(i) = 0;
6070 const size_t numEnt = this->getNumEntriesInGlobalRow (gblRow);
6071 numPacketsPerLID_h(i) = numEnt;
6072 curTotalNumPackets += numEnt;
6078 std::ostringstream os;
6079 os << *prefix <<
"totalNumPackets: " << totalNumPackets
6080 <<
", errCount: " << errCount << endl;
6081 std::cerr << os.str ();
6083 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6084 (errCount != 0, std::logic_error,
"totalNumPackets count encountered " 6085 "one or more errors! totalNumPackets: " << totalNumPackets
6086 <<
", errCount: " << errCount <<
".");
6089 if (
size_t(exports.extent (0)) < totalNumPackets) {
6091 exports = exports_dv_type (
"exports", totalNumPackets);
6094 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6095 (! this->supportsRowViews (), std::logic_error,
6096 "this->supportsRowViews() returns false; this should never happen. " 6097 "Please report this bug to the Tpetra developers.");
6103 std::ostringstream os;
6104 os << *prefix <<
"Pack into exports buffer" << endl;
6105 std::cerr << os.str();
6108 exports.clear_sync_state ();
6109 exports.modify_host ();
6110 auto exports_h = exports.view_host ();
6115 device_execution_space().fence ();
6118 Kokkos::parallel_scan
6119 (
"Tpetra::CrsGraph::packFillActiveNew: Pack exports",
6120 inputRange, [=, &prefix]
6121 (
const LO i,
size_t& exportsOffset,
const bool final) {
6122 const size_t curOffset = exportsOffset;
6123 const LO lclRow = exportLIDs_h(i);
6124 const GO gblRow = rowMap.getGlobalElement (lclRow);
6125 if (gblRow == Details::OrdinalTraits<GO>::invalid ()) {
6127 std::ostringstream os;
6128 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
6129 <<
" not in row Map on this process" << endl;
6130 std::cerr << os.str();
6132 Kokkos::atomic_add (&errCountView(), ONE);
6136 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (gblRow);
6137 if (rowInfo.localRow == Details::OrdinalTraits<size_t>::invalid ()) {
6139 std::ostringstream os;
6140 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
6141 <<
", gblRow=" << gblRow <<
": invalid rowInfo" 6143 std::cerr << os.str();
6145 Kokkos::atomic_add (&errCountView(), ONE);
6149 if (curOffset + rowInfo.numEntries > totalNumPackets) {
6151 std::ostringstream os;
6152 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
6153 <<
", gblRow=" << gblRow <<
", curOffset (= " 6154 << curOffset <<
") + numEnt (= " << rowInfo.numEntries
6155 <<
") > totalNumPackets (= " << totalNumPackets
6157 std::cerr << os.str();
6159 Kokkos::atomic_add (&errCountView(), ONE);
6163 const LO numEnt =
static_cast<LO
> (rowInfo.numEntries);
6164 if (this->isLocallyIndexed ()) {
6165 const LO* lclColInds =
nullptr;
6168 this->getLocalViewRawConst (lclColInds, capacity, rowInfo);
6171 for (LO k = 0; k < numEnt; ++k) {
6172 const LO lclColInd = lclColInds[k];
6173 const GO gblColInd = colMapPtr->getGlobalElement (lclColInd);
6177 exports_h(curOffset + k) = gblColInd;
6180 exportsOffset = curOffset + numEnt;
6184 std::ostringstream os;
6185 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
6186 <<
", gblRow=" << gblRow <<
": getLocalViewRawConst" 6187 "returned nonzero error code " << errCode << endl;
6188 std::cerr << os.str();
6190 Kokkos::atomic_add (&errCountView(), ONE);
6193 else if (this->isGloballyIndexed ()) {
6194 const GO* gblColInds =
nullptr;
6197 this->getGlobalViewRawConst (gblColInds, capacity, rowInfo);
6200 for (LO k = 0; k < numEnt; ++k) {
6201 const GO gblColInd = gblColInds[k];
6205 exports_h(curOffset + k) = gblColInd;
6208 exportsOffset = curOffset + numEnt;
6212 std::ostringstream os;
6213 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
6214 <<
", gblRow=" << gblRow <<
": " 6215 "getGlobalViewRawConst returned nonzero error code " 6217 std::cerr << os.str();
6219 Kokkos::atomic_add (&errCountView(), ONE);
6233 std::ostringstream os;
6234 os << *prefix <<
"errCount=" << errCount <<
"; Done" << endl;
6235 std::cerr << os.str();
6239 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6241 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
6243 (
const Kokkos::DualView<
const local_ordinal_type*,
6244 buffer_device_type>& importLIDs,
6245 Kokkos::DualView<packet_type*,
6246 buffer_device_type> imports,
6247 Kokkos::DualView<
size_t*,
6248 buffer_device_type> numPacketsPerLID,
6253 using Details::ProfilingRegion;
6256 using GO = global_ordinal_type;
6257 const char tfecfFuncName[] =
"unpackAndCombine";
6259 ProfilingRegion regionCGC(
"Tpetra::CrsGraph::unpackAndCombine");
6260 const bool verbose = verbose_;
6262 std::unique_ptr<std::string> prefix;
6264 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
6265 std::ostringstream os;
6266 os << *prefix <<
"Start" << endl;
6267 std::cerr << os.str ();
6270 auto padding = computeCrsPaddingForImports(
6271 importLIDs, imports, numPacketsPerLID, verbose);
6272 applyCrsPadding(*padding, verbose);
6274 std::ostringstream os;
6275 os << *prefix <<
"Done computing & applying padding" << endl;
6276 std::cerr << os.str ();
6297 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6298 (importLIDs.extent (0) != numPacketsPerLID.extent (0),
6299 std::runtime_error,
": importLIDs.extent(0) = " 6300 << importLIDs.extent (0) <<
" != numPacketsPerLID.extent(0) = " 6301 << numPacketsPerLID.extent (0) <<
".");
6302 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6303 (isFillComplete (), std::runtime_error,
6304 ": Import or Export operations are not allowed on a target " 6305 "CrsGraph that is fillComplete.");
6307 const size_t numImportLIDs(importLIDs.extent(0));
6308 if (numPacketsPerLID.need_sync_host()) {
6309 numPacketsPerLID.sync_host();
6311 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
6312 if (imports.need_sync_host()) {
6313 imports.sync_host();
6315 auto imports_h = imports.view_host();
6316 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
6317 auto importLIDs_h = importLIDs.view_host();
6320 Teuchos::Array<LO> lclColInds;
6321 if (isLocallyIndexed()) {
6323 std::ostringstream os;
6324 os << *prefix <<
"Preallocate local indices scratch" << endl;
6325 std::cerr << os.str();
6327 size_t maxNumInserts = 0;
6328 for (
size_t i = 0; i < numImportLIDs; ++i) {
6329 maxNumInserts = std::max (maxNumInserts, numPacketsPerLID_h[i]);
6332 std::ostringstream os;
6333 os << *prefix <<
"Local indices scratch size: " 6334 << maxNumInserts << endl;
6335 std::cerr << os.str();
6337 lclColInds.resize (maxNumInserts);
6341 std::ostringstream os;
6343 if (isGloballyIndexed()) {
6344 os <<
"Graph is globally indexed";
6347 os <<
"Graph is neither locally nor globally indexed";
6350 std::cerr << os.str();
6354 TEUCHOS_ASSERT( ! rowMap_.is_null() );
6355 const map_type& rowMap = *rowMap_;
6358 size_t importsOffset = 0;
6359 for (
size_t i = 0; i < numImportLIDs; ++i) {
6361 std::ostringstream os;
6362 os << *prefix <<
"i=" << i <<
", numImportLIDs=" 6363 << numImportLIDs << endl;
6364 std::cerr << os.str();
6368 const LO lclRow = importLIDs_h[i];
6369 const GO gblRow = rowMap.getGlobalElement(lclRow);
6370 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6371 (gblRow == Teuchos::OrdinalTraits<GO>::invalid(),
6372 std::logic_error,
"importLIDs[i=" << i <<
"]=" 6373 << lclRow <<
" is not in the row Map on the calling " 6375 const LO numEnt = numPacketsPerLID_h[i];
6376 const GO*
const gblColInds = (numEnt == 0) ?
nullptr :
6377 imports_h.data() + importsOffset;
6378 if (! isLocallyIndexed()) {
6379 insertGlobalIndicesFiltered(lclRow, gblColInds, numEnt);
6384 for (LO j = 0; j < numEnt; j++) {
6385 lclColInds[j] = colMap_->getLocalElement(gblColInds[j]);
6387 insertLocalIndices(lclRow, numEnt, lclColInds.data());
6389 importsOffset += numEnt;
6392 catch (std::exception& e) {
6393 TEUCHOS_TEST_FOR_EXCEPTION
6394 (
true, std::runtime_error,
6395 "Tpetra::CrsGraph::unpackAndCombine: Insert loop threw an " 6396 "exception: " << endl << e.what());
6400 std::ostringstream os;
6401 os << *prefix <<
"Done" << endl;
6402 std::cerr << os.str();
6406 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6411 using Teuchos::Comm;
6412 using Teuchos::null;
6413 using Teuchos::ParameterList;
6419 RCP<const map_type> rowMap, domainMap, rangeMap, colMap;
6420 RCP<import_type> importer;
6421 RCP<export_type> exporter;
6424 RCP<const Comm<int> > newComm =
6425 (newMap.is_null ()) ? null : newMap->getComm ();
6427 if (! domainMap_.is_null ()) {
6428 if (domainMap_.getRawPtr () == rowMap_.getRawPtr ()) {
6435 domainMap = domainMap_->replaceCommWithSubset (newComm);
6438 if (! rangeMap_.is_null ()) {
6439 if (rangeMap_.getRawPtr () == rowMap_.getRawPtr ()) {
6446 rangeMap = rangeMap_->replaceCommWithSubset (newComm);
6449 if (! colMap.is_null ()) {
6450 colMap = colMap_->replaceCommWithSubset (newComm);
6454 if (! newComm.is_null ()) {
6455 RCP<ParameterList> params = this->getNonconstParameterList ();
6463 if (! rangeMap_.is_null () &&
6464 rangeMap != rowMap &&
6465 ! rangeMap->isSameAs (*rowMap)) {
6466 if (params.is_null () || ! params->isSublist (
"Export")) {
6467 exporter = rcp (
new export_type (rowMap, rangeMap));
6470 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
6471 exporter = rcp (
new export_type (rowMap, rangeMap, exportSublist));
6475 if (! domainMap_.is_null () &&
6476 domainMap != colMap &&
6477 ! domainMap->isSameAs (*colMap)) {
6478 if (params.is_null () || ! params->isSublist (
"Import")) {
6479 importer = rcp (
new import_type (domainMap, colMap));
6481 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
6482 importer = rcp (
new import_type (domainMap, colMap, importSublist));
6490 exporter_ = exporter;
6491 importer_ = importer;
6498 this->map_ = rowMap;
6499 domainMap_ = domainMap;
6500 rangeMap_ = rangeMap;
6504 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6510 using LO = LocalOrdinal;
6511 using GO = GlobalOrdinal;
6512 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6513 const bool verbose = verbose_;
6515 std::unique_ptr<std::string> prefix;
6517 prefix = this->createPrefix(
"CrsGraph",
"getLocalDiagOffsets");
6518 std::ostringstream os;
6519 os << *prefix <<
"offsets.extent(0)=" << offsets.extent(0)
6521 std::cerr << os.str();
6524 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6525 (! hasColMap (), std::runtime_error,
"The graph must have a column Map.");
6526 const LO lclNumRows =
static_cast<LO
> (this->getNodeNumRows ());
6527 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6528 (static_cast<LO> (offsets.extent (0)) < lclNumRows,
6529 std::invalid_argument,
"offsets.extent(0) = " <<
6530 offsets.extent (0) <<
" < getNodeNumRows() = " << lclNumRows <<
".");
6532 const map_type& rowMap = * (this->getRowMap ());
6533 const map_type& colMap = * (this->getColMap ());
6539 bool allRowMapDiagEntriesInColMap =
true;
6540 bool allDiagEntriesFound =
true;
6541 bool allOffsetsCorrect =
true;
6542 bool noOtherWeirdness =
true;
6543 using wrong_offsets_type = std::vector<std::pair<LO, size_t> >;
6544 wrong_offsets_type wrongOffsets(0);
6548 auto lclRowMap = rowMap.getLocalMap ();
6555 const bool sorted = this->isSorted ();
6556 if (isFillComplete ()) {
6557 auto lclGraph = this->getLocalGraph ();
6558 ::Tpetra::Details::getGraphDiagOffsets (offsets, lclRowMap, lclColMap,
6560 lclGraph.entries, sorted);
6566 auto offsets_h = Kokkos::create_mirror_view (offsets);
6568 for (LO lclRowInd = 0; lclRowInd < lclNumRows; ++lclRowInd) {
6572 const GO gblRowInd = lclRowMap.getGlobalElement (lclRowInd);
6573 const GO gblColInd = gblRowInd;
6574 const LO lclColInd = lclColMap.getLocalElement (gblColInd);
6576 if (lclColInd == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
6577 allRowMapDiagEntriesInColMap =
false;
6578 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6581 const RowInfo rowInfo = this->getRowInfo (lclRowInd);
6582 if (static_cast<LO> (rowInfo.localRow) == lclRowInd &&
6583 rowInfo.numEntries > 0) {
6585 auto colInds = this->getLocalKokkosRowView (rowInfo);
6586 const size_t hint = 0;
6587 const size_t offset =
6588 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
6589 lclColInd, hint, sorted);
6590 offsets_h(lclRowInd) = offset;
6597 Teuchos::ArrayView<const LO> lclColInds;
6599 this->getLocalRowView (lclRowInd, lclColInds);
6602 noOtherWeirdness =
false;
6605 if (noOtherWeirdness) {
6606 const size_t numEnt = lclColInds.size ();
6607 if (offset >= numEnt) {
6610 allOffsetsCorrect =
false;
6611 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6613 const LO actualLclColInd = lclColInds[offset];
6614 const GO actualGblColInd = lclColMap.getGlobalElement (actualLclColInd);
6615 if (actualGblColInd != gblColInd) {
6616 allOffsetsCorrect =
false;
6617 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6624 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6625 allDiagEntriesFound =
false;
6633 if (verbose && wrongOffsets.size () != 0) {
6634 std::ostringstream os;
6635 os << *prefix <<
"Wrong offsets: [";
6636 for (
size_t k = 0; k < wrongOffsets.size (); ++k) {
6637 os <<
"(" << wrongOffsets[k].first <<
"," 6638 << wrongOffsets[k].second <<
")";
6639 if (k + 1 < wrongOffsets.size ()) {
6644 std::cerr << os.str();
6648 using Teuchos::reduceAll;
6650 Teuchos::RCP<const Teuchos::Comm<int> > comm = this->getComm ();
6651 const bool localSuccess =
6652 allRowMapDiagEntriesInColMap && allDiagEntriesFound && allOffsetsCorrect;
6653 const int numResults = 5;
6655 lclResults[0] = allRowMapDiagEntriesInColMap ? 1 : 0;
6656 lclResults[1] = allDiagEntriesFound ? 1 : 0;
6657 lclResults[2] = allOffsetsCorrect ? 1 : 0;
6658 lclResults[3] = noOtherWeirdness ? 1 : 0;
6661 lclResults[4] = ! localSuccess ? comm->getRank () : comm->getSize ();
6669 reduceAll<int, int> (*comm, Teuchos::REDUCE_MIN,
6670 numResults, lclResults, gblResults);
6672 if (gblResults[0] != 1 || gblResults[1] != 1 || gblResults[2] != 1
6673 || gblResults[3] != 1) {
6674 std::ostringstream os;
6675 os <<
"Issue(s) that we noticed (on Process " << gblResults[4] <<
", " 6676 "possibly among others): " << endl;
6677 if (gblResults[0] == 0) {
6678 os <<
" - The column Map does not contain at least one diagonal entry " 6679 "of the graph." << endl;
6681 if (gblResults[1] == 0) {
6682 os <<
" - On one or more processes, some row does not contain a " 6683 "diagonal entry." << endl;
6685 if (gblResults[2] == 0) {
6686 os <<
" - On one or more processes, some offsets are incorrect." 6689 if (gblResults[3] == 0) {
6690 os <<
" - One or more processes had some other error." 6693 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
6716 template<
class DeviceType,
6717 const bool memSpaceIsHostSpace =
6718 std::is_same<
typename DeviceType::memory_space,
6719 Kokkos::HostSpace>::value>
6720 struct HelpGetLocalDiagOffsets {};
6722 template<
class DeviceType>
6723 struct HelpGetLocalDiagOffsets<DeviceType, true> {
6724 typedef DeviceType device_type;
6725 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6726 Kokkos::MemoryUnmanaged> device_offsets_type;
6727 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6728 Kokkos::MemoryUnmanaged> host_offsets_type;
6730 static device_offsets_type
6731 getDeviceOffsets (
const host_offsets_type& hostOffsets)
6739 copyBackIfNeeded (
const host_offsets_type& ,
6740 const device_offsets_type& )
6744 template<
class DeviceType>
6745 struct HelpGetLocalDiagOffsets<DeviceType, false> {
6746 typedef DeviceType device_type;
6750 typedef Kokkos::View<size_t*, device_type> device_offsets_type;
6751 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6752 Kokkos::MemoryUnmanaged> host_offsets_type;
6754 static device_offsets_type
6755 getDeviceOffsets (
const host_offsets_type& hostOffsets)
6759 return device_offsets_type (
"offsets", hostOffsets.extent (0));
6763 copyBackIfNeeded (
const host_offsets_type& hostOffsets,
6764 const device_offsets_type& deviceOffsets)
6772 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6774 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
6775 getLocalDiagOffsets (Teuchos::ArrayRCP<size_t>& offsets)
const 6777 typedef LocalOrdinal LO;
6778 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6779 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6780 (! this->hasColMap (), std::runtime_error,
6781 "The graph does not yet have a column Map.");
6782 const LO myNumRows =
static_cast<LO
> (this->getNodeNumRows ());
6783 if (static_cast<LO> (offsets.size ()) != myNumRows) {
6787 offsets.resize (myNumRows);
6799 typedef HelpGetLocalDiagOffsets<device_type> helper_type;
6800 typedef typename helper_type::host_offsets_type host_offsets_type;
6802 host_offsets_type hostOffsets (offsets.getRawPtr (), myNumRows);
6804 auto deviceOffsets = helper_type::getDeviceOffsets (hostOffsets);
6806 this->getLocalDiagOffsets (deviceOffsets);
6807 helper_type::copyBackIfNeeded (hostOffsets, deviceOffsets);
6810 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6817 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6821 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& rowTransfer,
6822 const Teuchos::RCP<const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node> > & domainTransfer,
6823 const Teuchos::RCP<const map_type>& domainMap,
6824 const Teuchos::RCP<const map_type>& rangeMap,
6825 const Teuchos::RCP<Teuchos::ParameterList>& params)
const 6831 using Teuchos::ArrayRCP;
6832 using Teuchos::ArrayView;
6833 using Teuchos::Comm;
6834 using Teuchos::ParameterList;
6837 #ifdef HAVE_TPETRA_MMM_TIMINGS 6839 using Teuchos::TimeMonitor;
6842 using LO = LocalOrdinal;
6843 using GO = GlobalOrdinal;
6844 using NT = node_type;
6847 using packet_type =
typename this_type::packet_type;
6849 const char* prefix =
"Tpetra::CrsGraph::transferAndFillComplete: ";
6851 #ifdef HAVE_TPETRA_MMM_TIMINGS 6853 if(!params.is_null()) label = params->get(
"Timer Label", label);
6854 string prefix2 = string(
"Tpetra ")+ label + std::string(
": CrsGraph TAFC ");
6855 RCP<TimeMonitor> MM =
6856 rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Pack-1"))));
6864 const import_type* xferAsImport =
dynamic_cast<const import_type*
>(&rowTransfer);
6865 const export_type* xferAsExport =
dynamic_cast<const export_type*
>(&rowTransfer);
6866 TEUCHOS_TEST_FOR_EXCEPTION(
6867 xferAsImport ==
nullptr && xferAsExport ==
nullptr, std::invalid_argument,
6868 prefix <<
"The 'rowTransfer' input argument must be either an Import or " 6869 "an Export, and its template parameters must match the corresponding " 6870 "template parameters of the CrsGraph.");
6877 Teuchos::RCP<const import_type> xferDomainAsImport =
6878 Teuchos::rcp_dynamic_cast<
const import_type>(domainTransfer);
6879 Teuchos::RCP<const export_type> xferDomainAsExport =
6880 Teuchos::rcp_dynamic_cast<
const export_type>(domainTransfer);
6882 if(! domainTransfer.is_null()) {
6884 TEUCHOS_TEST_FOR_EXCEPTION(
6885 (xferDomainAsImport.is_null() && xferDomainAsExport.is_null()), std::invalid_argument,
6886 prefix <<
"The 'domainTransfer' input argument must be either an " 6887 "Import or an Export, and its template parameters must match the " 6888 "corresponding template parameters of the CrsGraph.");
6890 TEUCHOS_TEST_FOR_EXCEPTION(
6891 ( xferAsImport !=
nullptr || ! xferDomainAsImport.is_null() ) &&
6892 (( xferAsImport !=
nullptr && xferDomainAsImport.is_null() ) ||
6893 ( xferAsImport ==
nullptr && ! xferDomainAsImport.is_null() )), std::invalid_argument,
6894 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments " 6895 "must be of the same type (either Import or Export).");
6897 TEUCHOS_TEST_FOR_EXCEPTION(
6898 ( xferAsExport !=
nullptr || ! xferDomainAsExport.is_null() ) &&
6899 (( xferAsExport !=
nullptr && xferDomainAsExport.is_null() ) ||
6900 ( xferAsExport ==
nullptr && ! xferDomainAsExport.is_null() )), std::invalid_argument,
6901 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments " 6902 "must be of the same type (either Import or Export).");
6909 const bool communication_needed = rowTransfer.getSourceMap()->isDistributed();
6915 bool reverseMode =
false;
6916 bool restrictComm =
false;
6917 RCP<ParameterList> graphparams;
6918 if (! params.is_null()) {
6919 reverseMode = params->get(
"Reverse Mode", reverseMode);
6920 restrictComm = params->get(
"Restrict Communicator", restrictComm);
6921 graphparams = sublist(params,
"CrsGraph");
6926 RCP<const map_type> MyRowMap = reverseMode ?
6927 rowTransfer.getSourceMap() : rowTransfer.getTargetMap();
6928 RCP<const map_type> MyColMap;
6929 RCP<const map_type> MyDomainMap = ! domainMap.is_null() ? domainMap : getDomainMap();
6930 RCP<const map_type> MyRangeMap = ! rangeMap.is_null() ? rangeMap : getRangeMap();
6931 RCP<const map_type> BaseRowMap = MyRowMap;
6932 RCP<const map_type> BaseDomainMap = MyDomainMap;
6940 if (! destGraph.is_null()) {
6951 const bool NewFlag =
6952 ! destGraph->isLocallyIndexed() && ! destGraph->isGloballyIndexed();
6953 TEUCHOS_TEST_FOR_EXCEPTION(! NewFlag, std::invalid_argument,
6954 prefix <<
"The input argument 'destGraph' is only allowed to be nonnull, " 6955 "if its graph is empty (neither locally nor globally indexed).");
6964 TEUCHOS_TEST_FOR_EXCEPTION(
6965 ! destGraph->getRowMap()->isSameAs(*MyRowMap), std::invalid_argument,
6966 prefix <<
"The (row) Map of the input argument 'destGraph' is not the " 6967 "same as the (row) Map specified by the input argument 'rowTransfer'.");
6969 TEUCHOS_TEST_FOR_EXCEPTION(
6970 ! destGraph->checkSizes(*
this), std::invalid_argument,
6971 prefix <<
"You provided a nonnull destination graph, but checkSizes() " 6972 "indicates that it is not a legal legal target for redistribution from " 6973 "the source graph (*this). This may mean that they do not have the " 6974 "same dimensions.");
6988 TEUCHOS_TEST_FOR_EXCEPTION(
6989 ! (reverseMode || getRowMap()->isSameAs(*rowTransfer.getSourceMap())),
6990 std::invalid_argument, prefix <<
6991 "rowTransfer->getSourceMap() must match this->getRowMap() in forward mode.");
6993 TEUCHOS_TEST_FOR_EXCEPTION(
6994 ! (! reverseMode || getRowMap()->isSameAs(*rowTransfer.getTargetMap())),
6995 std::invalid_argument, prefix <<
6996 "rowTransfer->getTargetMap() must match this->getRowMap() in reverse mode.");
6999 TEUCHOS_TEST_FOR_EXCEPTION(
7000 ! xferDomainAsImport.is_null() && ! xferDomainAsImport->getTargetMap()->isSameAs(*domainMap),
7001 std::invalid_argument,
7002 prefix <<
"The target map of the 'domainTransfer' input argument must be " 7003 "the same as the rebalanced domain map 'domainMap'");
7005 TEUCHOS_TEST_FOR_EXCEPTION(
7006 ! xferDomainAsExport.is_null() && ! xferDomainAsExport->getSourceMap()->isSameAs(*domainMap),
7007 std::invalid_argument,
7008 prefix <<
"The source map of the 'domainTransfer' input argument must be " 7009 "the same as the rebalanced domain map 'domainMap'");
7022 const size_t NumSameIDs = rowTransfer.getNumSameIDs();
7023 ArrayView<const LO> ExportLIDs = reverseMode ?
7024 rowTransfer.getRemoteLIDs() : rowTransfer.getExportLIDs();
7025 ArrayView<const LO> RemoteLIDs = reverseMode ?
7026 rowTransfer.getExportLIDs() : rowTransfer.getRemoteLIDs();
7027 ArrayView<const LO> PermuteToLIDs = reverseMode ?
7028 rowTransfer.getPermuteFromLIDs() : rowTransfer.getPermuteToLIDs();
7029 ArrayView<const LO> PermuteFromLIDs = reverseMode ?
7030 rowTransfer.getPermuteToLIDs() : rowTransfer.getPermuteFromLIDs();
7031 Distributor& Distor = rowTransfer.getDistributor();
7034 Teuchos::Array<int> SourcePids;
7035 Teuchos::Array<int> TargetPids;
7036 int MyPID = getComm()->getRank();
7039 RCP<const map_type> ReducedRowMap, ReducedColMap,
7040 ReducedDomainMap, ReducedRangeMap;
7041 RCP<const Comm<int> > ReducedComm;
7045 if (destGraph.is_null()) {
7046 destGraph = rcp(
new this_type(MyRowMap, 0, StaticProfile, graphparams));
7053 ReducedRowMap = MyRowMap->removeEmptyProcesses();
7054 ReducedComm = ReducedRowMap.is_null() ?
7056 ReducedRowMap->getComm();
7057 destGraph->removeEmptyProcessesInPlace(ReducedRowMap);
7059 ReducedDomainMap = MyRowMap.getRawPtr() == MyDomainMap.getRawPtr() ?
7061 MyDomainMap->replaceCommWithSubset(ReducedComm);
7062 ReducedRangeMap = MyRowMap.getRawPtr() == MyRangeMap.getRawPtr() ?
7064 MyRangeMap->replaceCommWithSubset(ReducedComm);
7067 MyRowMap = ReducedRowMap;
7068 MyDomainMap = ReducedDomainMap;
7069 MyRangeMap = ReducedRangeMap;
7072 if (! ReducedComm.is_null()) {
7073 MyPID = ReducedComm->getRank();
7080 ReducedComm = MyRowMap->getComm();
7086 #ifdef HAVE_TPETRA_MMM_TIMINGS 7088 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ImportSetup"))));
7091 RCP<const import_type> MyImporter = getImporter();
7094 bool bSameDomainMap = BaseDomainMap->isSameAs(*getDomainMap());
7096 if (! restrictComm && ! MyImporter.is_null() && bSameDomainMap ) {
7103 Import_Util::getPids(*MyImporter, SourcePids,
false);
7105 else if (restrictComm && ! MyImporter.is_null() && bSameDomainMap) {
7108 ivector_type SourceDomain_pids(getDomainMap(),
true);
7109 ivector_type SourceCol_pids(getColMap());
7111 SourceDomain_pids.putScalar(MyPID);
7113 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
7114 SourcePids.resize(getColMap()->getNodeNumElements());
7115 SourceCol_pids.get1dCopy(SourcePids());
7117 else if (MyImporter.is_null() && bSameDomainMap) {
7119 SourcePids.resize(getColMap()->getNodeNumElements());
7120 SourcePids.assign(getColMap()->getNodeNumElements(), MyPID);
7122 else if ( ! MyImporter.is_null() &&
7123 ! domainTransfer.is_null() ) {
7130 ivector_type TargetDomain_pids(domainMap);
7131 TargetDomain_pids.putScalar(MyPID);
7134 ivector_type SourceDomain_pids(getDomainMap());
7137 ivector_type SourceCol_pids(getColMap());
7139 if (! reverseMode && ! xferDomainAsImport.is_null() ) {
7140 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
7142 else if (reverseMode && ! xferDomainAsExport.is_null() ) {
7143 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
7145 else if (! reverseMode && ! xferDomainAsExport.is_null() ) {
7146 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
7148 else if (reverseMode && ! xferDomainAsImport.is_null() ) {
7149 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
7152 TEUCHOS_TEST_FOR_EXCEPTION(
7153 true, std::logic_error,
7154 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
7156 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
7157 SourcePids.resize(getColMap()->getNodeNumElements());
7158 SourceCol_pids.get1dCopy(SourcePids());
7160 else if (BaseDomainMap->isSameAs(*BaseRowMap) &&
7161 getDomainMap()->isSameAs(*getRowMap())) {
7163 ivector_type TargetRow_pids(domainMap);
7164 ivector_type SourceRow_pids(getRowMap());
7165 ivector_type SourceCol_pids(getColMap());
7167 TargetRow_pids.putScalar(MyPID);
7168 if (! reverseMode && xferAsImport !=
nullptr) {
7169 SourceRow_pids.doExport(TargetRow_pids, *xferAsImport,
INSERT);
7171 else if (reverseMode && xferAsExport !=
nullptr) {
7172 SourceRow_pids.doExport(TargetRow_pids, *xferAsExport,
INSERT);
7174 else if (! reverseMode && xferAsExport !=
nullptr) {
7175 SourceRow_pids.doImport(TargetRow_pids, *xferAsExport,
INSERT);
7177 else if (reverseMode && xferAsImport !=
nullptr) {
7178 SourceRow_pids.doImport(TargetRow_pids, *xferAsImport,
INSERT);
7181 TEUCHOS_TEST_FOR_EXCEPTION(
7182 true, std::logic_error,
7183 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
7185 SourceCol_pids.doImport(SourceRow_pids, *MyImporter,
INSERT);
7186 SourcePids.resize(getColMap()->getNodeNumElements());
7187 SourceCol_pids.get1dCopy(SourcePids());
7190 TEUCHOS_TEST_FOR_EXCEPTION(
7191 true, std::invalid_argument,
7192 prefix <<
"This method only allows either domainMap == getDomainMap(), " 7193 "or (domainMap == rowTransfer.getTargetMap() and getDomainMap() == getRowMap()).");
7197 size_t constantNumPackets = destGraph->constantNumberOfPackets();
7198 if (constantNumPackets == 0) {
7199 destGraph->reallocArraysForNumPacketsPerLid(ExportLIDs.size(),
7207 const size_t rbufLen = RemoteLIDs.size() * constantNumPackets;
7208 destGraph->reallocImportsIfNeeded(rbufLen,
false,
nullptr);
7213 destGraph->numExportPacketsPerLID_.modify_host();
7214 Teuchos::ArrayView<size_t> numExportPacketsPerLID =
7219 numExportPacketsPerLID, ExportLIDs,
7220 SourcePids, constantNumPackets, Distor);
7224 #ifdef HAVE_TPETRA_MMM_TIMINGS 7226 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Transfer"))));
7229 if (communication_needed) {
7231 if (constantNumPackets == 0) {
7235 destGraph->numExportPacketsPerLID_.sync_host();
7236 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
7238 destGraph->numImportPacketsPerLID_.sync_host();
7239 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
7241 Distor.doReversePostsAndWaits(numExportPacketsPerLID, 1,
7242 numImportPacketsPerLID);
7243 size_t totalImportPackets = 0;
7244 for (Array_size_type i = 0; i < numImportPacketsPerLID.size(); ++i) {
7245 totalImportPackets += numImportPacketsPerLID[i];
7250 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
7251 destGraph->imports_.modify_host();
7252 Teuchos::ArrayView<packet_type> hostImports =
7256 destGraph->exports_.sync_host();
7257 Teuchos::ArrayView<const packet_type> hostExports =
7259 Distor.doReversePostsAndWaits(hostExports,
7260 numExportPacketsPerLID,
7262 numImportPacketsPerLID);
7265 destGraph->imports_.modify_host();
7266 Teuchos::ArrayView<packet_type> hostImports =
7270 destGraph->exports_.sync_host();
7271 Teuchos::ArrayView<const packet_type> hostExports =
7273 Distor.doReversePostsAndWaits(hostExports,
7279 if (constantNumPackets == 0) {
7283 destGraph->numExportPacketsPerLID_.sync_host();
7284 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
7286 destGraph->numImportPacketsPerLID_.sync_host();
7287 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
7289 Distor.doPostsAndWaits(numExportPacketsPerLID, 1,
7290 numImportPacketsPerLID);
7291 size_t totalImportPackets = 0;
7292 for (Array_size_type i = 0; i < numImportPacketsPerLID.size(); ++i) {
7293 totalImportPackets += numImportPacketsPerLID[i];
7298 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
7299 destGraph->imports_.modify_host();
7300 Teuchos::ArrayView<packet_type> hostImports =
7304 destGraph->exports_.sync_host();
7305 Teuchos::ArrayView<const packet_type> hostExports =
7307 Distor.doPostsAndWaits(hostExports,
7308 numExportPacketsPerLID,
7310 numImportPacketsPerLID);
7313 destGraph->imports_.modify_host();
7314 Teuchos::ArrayView<packet_type> hostImports =
7318 destGraph->exports_.sync_host();
7319 Teuchos::ArrayView<const packet_type> hostExports =
7321 Distor.doPostsAndWaits(hostExports,
7332 #ifdef HAVE_TPETRA_MMM_TIMINGS 7334 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-1"))));
7338 destGraph->numImportPacketsPerLID_.sync_host();
7339 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
7341 destGraph->imports_.sync_host();
7342 Teuchos::ArrayView<const packet_type> hostImports =
7346 numImportPacketsPerLID,
7347 constantNumPackets, Distor,
INSERT,
7348 NumSameIDs, PermuteToLIDs, PermuteFromLIDs);
7349 size_t N = BaseRowMap->getNodeNumElements();
7352 ArrayRCP<size_t> CSR_rowptr(N+1);
7353 ArrayRCP<GO> CSR_colind_GID;
7354 ArrayRCP<LO> CSR_colind_LID;
7355 CSR_colind_GID.resize(mynnz);
7359 if (
typeid(LO) ==
typeid(GO)) {
7360 CSR_colind_LID = Teuchos::arcp_reinterpret_cast<LO>(CSR_colind_GID);
7363 CSR_colind_LID.resize(mynnz);
7372 numImportPacketsPerLID, constantNumPackets,
7373 Distor,
INSERT, NumSameIDs, PermuteToLIDs,
7374 PermuteFromLIDs, N, mynnz, MyPID,
7375 CSR_rowptr(), CSR_colind_GID(),
7376 SourcePids(), TargetPids);
7381 #ifdef HAVE_TPETRA_MMM_TIMINGS 7383 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-2"))));
7388 Teuchos::Array<int> RemotePids;
7389 Import_Util::lowCommunicationMakeColMapAndReindex(CSR_rowptr(),
7393 TargetPids, RemotePids,
7400 ReducedColMap = (MyRowMap.getRawPtr() == MyColMap.getRawPtr()) ?
7402 MyColMap->replaceCommWithSubset(ReducedComm);
7403 MyColMap = ReducedColMap;
7407 destGraph->replaceColMap(MyColMap);
7414 if (ReducedComm.is_null()) {
7421 if ((! reverseMode && xferAsImport !=
nullptr) ||
7422 (reverseMode && xferAsExport !=
nullptr)) {
7423 Import_Util::sortCrsEntries(CSR_rowptr(),
7426 else if ((! reverseMode && xferAsExport !=
nullptr) ||
7427 (reverseMode && xferAsImport !=
nullptr)) {
7428 Import_Util::sortAndMergeCrsEntries(CSR_rowptr(),
7430 if (CSR_rowptr[N] != mynnz) {
7431 CSR_colind_LID.resize(CSR_rowptr[N]);
7435 TEUCHOS_TEST_FOR_EXCEPTION(
7436 true, std::logic_error,
7437 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
7445 destGraph->setAllIndices(CSR_rowptr, CSR_colind_LID);
7451 Teuchos::ParameterList esfc_params;
7452 #ifdef HAVE_TPETRA_MMM_TIMINGS 7454 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"CreateImporter"))));
7456 RCP<import_type> MyImport = rcp(
new import_type(MyDomainMap, MyColMap, RemotePids));
7457 #ifdef HAVE_TPETRA_MMM_TIMINGS 7459 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ESFC"))));
7461 esfc_params.set(
"Timer Label",prefix + std::string(
"TAFC"));
7463 if(!params.is_null())
7464 esfc_params.set(
"compute global constants",params->get(
"compute global constants",
true));
7466 destGraph->expertStaticFillComplete(MyDomainMap, MyRangeMap,
7467 MyImport, Teuchos::null, rcp(&esfc_params,
false));
7471 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7473 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
7476 const Teuchos::RCP<const map_type>& domainMap,
7477 const Teuchos::RCP<const map_type>& rangeMap,
7478 const Teuchos::RCP<Teuchos::ParameterList>& params)
const 7480 transferAndFillComplete(destGraph, importer, Teuchos::null, domainMap, rangeMap, params);
7483 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7489 const Teuchos::RCP<const map_type>& domainMap,
7490 const Teuchos::RCP<const map_type>& rangeMap,
7491 const Teuchos::RCP<Teuchos::ParameterList>& params)
const 7493 transferAndFillComplete(destGraph, rowImporter, Teuchos::rcpFromRef(domainImporter), domainMap, rangeMap, params);
7496 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7501 const Teuchos::RCP<const map_type>& domainMap,
7502 const Teuchos::RCP<const map_type>& rangeMap,
7503 const Teuchos::RCP<Teuchos::ParameterList>& params)
const 7505 transferAndFillComplete(destGraph, exporter, Teuchos::null, domainMap, rangeMap, params);
7508 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7514 const Teuchos::RCP<const map_type>& domainMap,
7515 const Teuchos::RCP<const map_type>& rangeMap,
7516 const Teuchos::RCP<Teuchos::ParameterList>& params)
const 7518 transferAndFillComplete(destGraph, rowExporter, Teuchos::rcpFromRef(domainExporter), domainMap, rangeMap, params);
7522 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7527 std::swap(graph.
rowMap_, this->rowMap_);
7528 std::swap(graph.
colMap_, this->colMap_);
7529 std::swap(graph.
rangeMap_, this->rangeMap_);
7530 std::swap(graph.
domainMap_, this->domainMap_);
7532 std::swap(graph.
importer_, this->importer_);
7533 std::swap(graph.
exporter_, this->exporter_);
7535 std::swap(graph.
lclGraph_, this->lclGraph_);
7544 std::swap(graph.
k_rowPtrs_, this->k_rowPtrs_);
7551 std::swap(graph.indicesAreAllocated_, this->indicesAreAllocated_);
7552 std::swap(graph.indicesAreLocal_, this->indicesAreLocal_);
7553 std::swap(graph.indicesAreGlobal_, this->indicesAreGlobal_);
7554 std::swap(graph.fillComplete_, this->fillComplete_);
7564 std::swap(graph.
nonlocals_, this->nonlocals_);
7568 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7573 auto compare_nonlocals = [&] (
const nonlocals_type & m1,
const nonlocals_type & m2) {
7575 output = m1.size() == m2.size() ? output :
false;
7576 for(
auto & it_m: m1)
7578 size_t key = it_m.first;
7579 output = m2.find(key) != m2.end() ? output :
false;
7582 auto v1 = m1.find(key)->second;
7583 auto v2 = m2.find(key)->second;
7584 std::sort(v1.begin(), v1.end());
7585 std::sort(v2.begin(), v2.end());
7587 output = v1.size() == v2.size() ? output :
false;
7588 for(
size_t i=0; output && i<v1.size(); i++)
7590 output = v1[i]==v2[i] ? output :
false;
7599 output = this->rowMap_->isSameAs( *(graph.
rowMap_) ) ? output :
false;
7600 output = this->colMap_->isSameAs( *(graph.
colMap_) ) ? output :
false;
7601 output = this->rangeMap_->isSameAs( *(graph.
rangeMap_) ) ? output :
false;
7602 output = this->domainMap_->isSameAs( *(graph.
domainMap_) ) ? output :
false;
7611 output = this->storageStatus_ == graph.
storageStatus_ ? output :
false;
7613 output = this->indicesAreAllocated_ == graph.indicesAreAllocated_ ? output :
false;
7614 output = this->indicesAreLocal_ == graph.indicesAreLocal_ ? output :
false;
7615 output = this->indicesAreGlobal_ == graph.indicesAreGlobal_ ? output :
false;
7616 output = this->fillComplete_ == graph.fillComplete_ ? output :
false;
7618 output = this->noRedundancies_ == graph.
noRedundancies_ ? output :
false;
7621 output = this->sortGhostsAssociatedWithEachProcessor_ == this->sortGhostsAssociatedWithEachProcessor_ ? output :
false;
7625 output = compare_nonlocals(this->nonlocals_, graph.
nonlocals_) ? output :
false;
7629 output = this->k_numAllocPerRow_.extent(0) == graph.
k_numAllocPerRow_.extent(0) ? output :
false;
7630 if(output && this->k_numAllocPerRow_.extent(0) > 0)
7632 for(
size_t i=0; output && i<this->k_numAllocPerRow_.extent(0); i++)
7633 output = this->k_numAllocPerRow_(i) == graph.
k_numAllocPerRow_(i) ? output :
false;
7638 output = this->k_numRowEntries_.extent(0) == graph.
k_numRowEntries_.extent(0) ? output :
false;
7639 if(output && this->k_numRowEntries_.extent(0) > 0)
7641 for(
size_t i = 0; output && i < this->k_numRowEntries_.extent(0); i++)
7642 output = this->k_numRowEntries_(i) == graph.
k_numRowEntries_(i) ? output :
false;
7646 output = this->k_rowPtrs_.extent(0) == graph.
k_rowPtrs_.extent(0) ? output :
false;
7647 if(output && this->k_rowPtrs_.extent(0) > 0)
7649 typename local_graph_type::row_map_type::const_type::HostMirror k_rowPtrs_host_this = Kokkos::create_mirror_view(this->k_rowPtrs_);
7650 typename local_graph_type::row_map_type::const_type::HostMirror k_rowPtrs_host_graph= Kokkos::create_mirror_view(graph.
k_rowPtrs_);
7653 for(
size_t i=0; output && i<k_rowPtrs_host_this.extent(0); i++)
7654 output = k_rowPtrs_host_this(i) == k_rowPtrs_host_graph(i) ? output :
false;
7658 output = this->k_lclInds1D_.extent(0) == graph.
k_lclInds1D_.extent(0) ? output :
false;
7659 if(output && this->k_lclInds1D_.extent(0) > 0)
7661 typename local_graph_type::entries_type::non_const_type::HostMirror k_lclInds1D_host_this = Kokkos::create_mirror_view(this->k_lclInds1D_);
7662 typename local_graph_type::entries_type::non_const_type::HostMirror k_lclInds1D_host_graph= Kokkos::create_mirror_view(graph.
k_lclInds1D_);
7665 for(
size_t i=0; output && i < k_lclInds1D_host_this.extent(0); i++)
7666 output = k_lclInds1D_host_this(i) == k_lclInds1D_host_graph(i) ? output :
false;
7670 output = this->k_gblInds1D_.extent(0) == graph.
k_gblInds1D_.extent(0) ? output :
false;
7671 if(output && this->k_gblInds1D_.extent(0) > 0)
7673 typename t_GlobalOrdinal_1D::HostMirror k_gblInds1D_host_this = Kokkos::create_mirror_view(this->k_gblInds1D_);
7674 typename t_GlobalOrdinal_1D::HostMirror k_gblInds1D_host_graph = Kokkos::create_mirror_view(graph.
k_gblInds1D_);
7677 for(
size_t i=0; output && i<k_gblInds1D_host_this.extent(0); i++)
7678 output = k_gblInds1D_host_this(i) == k_gblInds1D_host_graph(i) ? output :
false;
7688 output = this->lclGraph_.row_map.extent(0) == graph.
lclGraph_.row_map.extent(0) ? output :
false;
7689 if(output && this->lclGraph_.row_map.extent(0) > 0)
7691 typename local_graph_type::row_map_type::HostMirror lclGraph_rowmap_host_this = Kokkos::create_mirror_view(this->lclGraph_.row_map);
7692 typename local_graph_type::row_map_type::HostMirror lclGraph_rowmap_host_graph = Kokkos::create_mirror_view(graph.
lclGraph_.row_map);
7695 for(
size_t i=0; output && i<lclGraph_rowmap_host_this.extent(0); i++)
7696 output = lclGraph_rowmap_host_this(i) == lclGraph_rowmap_host_graph(i) ? output :
false;
7699 output = this->lclGraph_.entries.extent(0) == graph.
lclGraph_.entries.extent(0) ? output :
false;
7700 if(output && this->lclGraph_.entries.extent(0) > 0)
7702 typename local_graph_type::entries_type::HostMirror lclGraph_entries_host_this = Kokkos::create_mirror_view(this->lclGraph_.entries);
7703 typename local_graph_type::entries_type::HostMirror lclGraph_entries_host_graph = Kokkos::create_mirror_view(graph.
lclGraph_.entries);
7706 for(
size_t i=0; output && i<lclGraph_entries_host_this.extent(0); i++)
7707 output = lclGraph_entries_host_this(i) == lclGraph_entries_host_graph(i) ? output :
false;
7710 output = this->lclGraph_.row_block_offsets.extent(0) == graph.
lclGraph_.row_block_offsets.extent(0) ? output :
false;
7711 if(output && this->lclGraph_.row_block_offsets.extent(0) > 0)
7713 typename local_graph_type::row_block_type::HostMirror lclGraph_rbo_host_this = Kokkos::create_mirror_view(this->lclGraph_.row_block_offsets);
7714 typename local_graph_type::row_block_type::HostMirror lclGraph_rbo_host_graph = Kokkos::create_mirror_view(graph.
lclGraph_.row_block_offsets);
7717 for(
size_t i=0; output && i < lclGraph_rbo_host_this.extent(0); i++)
7718 output = lclGraph_rbo_host_this(i) == lclGraph_rbo_host_graph(i) ? output :
false;
7739 #define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \ 7741 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \ 7742 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \ 7743 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7744 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7745 CrsGraph<LO,GO,NODE>::node_type>& importer, \ 7746 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7747 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7748 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \ 7749 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7750 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7751 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \ 7752 const Teuchos::RCP<Teuchos::ParameterList>& params); 7754 #define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \ 7756 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \ 7757 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \ 7758 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7759 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7760 CrsGraph<LO,GO,NODE>::node_type>& rowImporter, \ 7761 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7762 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7763 CrsGraph<LO,GO,NODE>::node_type>& domainImporter, \ 7764 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7765 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7766 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \ 7767 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7768 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7769 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \ 7770 const Teuchos::RCP<Teuchos::ParameterList>& params); 7773 #define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \ 7775 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \ 7776 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \ 7777 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7778 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7779 CrsGraph<LO,GO,NODE>::node_type>& exporter, \ 7780 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7781 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7782 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \ 7783 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7784 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7785 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \ 7786 const Teuchos::RCP<Teuchos::ParameterList>& params); 7788 #define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \ 7790 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \ 7791 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \ 7792 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7793 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7794 CrsGraph<LO,GO,NODE>::node_type>& rowExporter, \ 7795 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7796 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7797 CrsGraph<LO,GO,NODE>::node_type>& domainExporter, \ 7798 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7799 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7800 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \ 7801 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \ 7802 CrsGraph<LO,GO,NODE>::global_ordinal_type, \ 7803 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \ 7804 const Teuchos::RCP<Teuchos::ParameterList>& params); 7807 #define TPETRA_CRSGRAPH_INSTANT( LO, GO, NODE ) \ 7808 template class CrsGraph<LO, GO, NODE>; \ 7809 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \ 7810 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \ 7811 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \ 7812 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) 7815 #endif // TPETRA_CRSGRAPH_DEF_HPP Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
Namespace Tpetra contains the class and methods constituting the Tpetra library.
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.
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...
bool isNodeGlobalElement(global_ordinal_type globalIndex) const
Whether the given global index is owned by this Map on the calling process.
Teuchos::RCP< const map_type > rangeMap_
The Map describing the range of the (matrix corresponding to the) graph.
GO global_ordinal_type
The type of the graph's global indices.
Kokkos::StaticCrsGraph< local_ordinal_type, Kokkos::LayoutLeft, device_type > local_graph_type
The type of the part of the sparse graph on each MPI process.
bool sortGhostsAssociatedWithEachProcessor_
Whether to require makeColMap() (and therefore fillComplete()) to order column Map GIDs associated wi...
static KOKKOS_INLINE_FUNCTION size_t unpackValue(LO &outVal, const char inBuf[])
Unpack the given value from the given output buffer.
bool haveGlobalConstants_
Whether all processes have computed global constants.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
Kokkos::View< global_ordinal_type *, execution_space > t_GlobalOrdinal_1D
Type of the k_gblInds1D_ array of global column indices.
t_GlobalOrdinal_1D k_gblInds1D_
Global column indices for all rows.
Declaration of a function that prints strings from each process.
local_ordinal_type getLocalElement(global_ordinal_type globalIndex) const
The local index corresponding to the given global index.
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.
OffsetsViewType::non_const_value_type computeOffsetsFromConstantCount(const OffsetsViewType &ptr, const CountType count)
Compute offsets from a constant count.
void removeEmptyProcessesInPlace(Teuchos::RCP< DistObjectType > &input, const Teuchos::RCP< const Map< typename DistObjectType::local_ordinal_type, typename DistObjectType::global_ordinal_type, typename DistObjectType::node_type > > &newMap)
Remove processes which contain no elements in this object's Map.
local_map_type getLocalMap() const
Get the local Map for Kokkos kernels.
static bool debug()
Whether Tpetra is in debug mode.
bool isNodeLocalElement(local_ordinal_type localIndex) const
Whether the given local index is valid for this Map on the calling process.
Allocation information for a locally owned row in a CrsGraph or CrsMatrix.
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, Distributor &distor, 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...
void verbosePrintArray(std::ostream &out, const ArrayType &x, const char name[], const size_t maxNumToPrint)
Print min(x.size(), maxNumToPrint) entries of x.
int local_ordinal_type
Default value of Scalar template parameter.
bool haveLocalConstants_
Whether this process has computed local constants.
Implementation details of Tpetra.
size_t global_size_t
Global size_t object.
node_type node_type
This class' Kokkos Node type.
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.
Insert new values that don't currently exist.
void padCrsArrays(const RowPtr &rowPtrBeg, const RowPtr &rowPtrEnd, Indices &indices, 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...
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.
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.
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.
Functions for manipulating CRS arrays.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
local_graph_type::entries_type::non_const_type k_lclInds1D_
Local column indices for all rows.
local_graph_type lclGraph_
Local graph; only initialized after first fillComplete() call.
Sets up and executes a communication plan for a Tpetra DistObject.
local_graph_type::row_map_type::const_type k_rowPtrs_
Row offsets for "1-D" storage.
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.
Kokkos::View< const size_t *, execution_space >::HostMirror k_numAllocPerRow_
The maximum number of entries to allow in each locally owned row, per row.
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 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, Distributor &distor, 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
typename device_type::execution_space execution_space
This class' Kokkos execution space.
Utility functions for packing and unpacking sparse matrix entries.
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, Distributor &distor)
Pack specified entries of the given local sparse graph for communication.
Abstract base class for objects that can be the source of an Import or Export operation.
LO local_ordinal_type
The type of the graph's local indices.
global_size_t globalNumEntries_
Global number of entries in the graph.
::Kokkos::Compat::KokkosDeviceWrapperNode< execution_space > node_type
Default value of Node template parameter.
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.
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.
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.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects...
typename node_type ::device_type device_type
This class' Kokkos device type.
A distributed dense vector.
Stand-alone utility functions and macros.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
Returns the communicator.
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const ExecutionSpace &execSpace, const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
global_ordinal_type getGlobalElement(local_ordinal_type localIndex) const
The global index corresponding to the given local index.
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.
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, Distributor &distor)
Pack specified entries of the given local sparse graph for communication, for "new" DistObject interf...
Declaration and definition of Tpetra::Details::getEntryOnHost.
size_t numAllocForAllRows_
The maximum number of entries to allow in each locally owned row.
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.
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, Distributor &distor)
Pack specified entries of the given local sparse graph for communication.
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.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.