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().");
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().");
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()).");
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",
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()).");
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()).");
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()).");
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",
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")) {
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")) {
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(
637 ": cannot have 1D data structures allocated.");
639 if(! params.is_null() && params->isParameter(
"sorted") &&
640 ! params->get<
bool>(
"sorted")) {
648 rangeMap .is_null() ?
rowMap_ : rangeMap);
649 Teuchos::Array<int> remotePIDs (0);
655 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
656 params->get (
"compute global constants",
true);
658 if (callComputeGlobalConstants) {
661 this->fillComplete_ =
true;
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.");
699 if (! params.is_null() && params->isParameter(
"sorted") &&
700 ! params->get<
bool>(
"sorted")) {
707 const bool callComputeGlobalConstants =
708 params.get () ==
nullptr ||
709 params->get (
"compute global constants",
true);
710 if (callComputeGlobalConstants) {
713 fillComplete_ =
true;
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>
1066 return rowMap_->getIndexBase ();
1069 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1074 return indicesAreAllocated_;
1077 template <
class LocalOrdinal,
class GlobalOrdinal,
class 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>
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>
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*,
1491 execution_space, Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
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);
1542 using row_view_type = Kokkos::View<GO*, execution_space,
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>
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 =
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>
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>
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>
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";
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);
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>
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();
4386 execution_space().fence ();
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;
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>
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 =
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>
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>
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;
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;
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>
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...
void setDomainRangeMaps(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap)
Teuchos::RCP< const map_type > getRowMap() const override
Returns the Map that describes the row distribution in this graph.
void setAllIndices(const typename local_graph_type::row_map_type &rowPointers, const typename local_graph_type::entries_type::non_const_type &columnIndices)
Set the graph's data directly, using 1-D storage.
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...
Teuchos::RCP< const map_type > rangeMap_
The Map describing the range of the (matrix corresponding to the) graph.
Teuchos::RCP< const map_type > getColMap() const override
Returns the Map that describes the column distribution in this graph.
GlobalOrdinal 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.
size_t getNodeMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, on this process.
void insertGlobalIndicesFiltered(const local_ordinal_type lclRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Like insertGlobalIndices(), but with column Map filtering.
bool sortGhostsAssociatedWithEachProcessor_
Whether to require makeColMap() (and therefore fillComplete()) to order column Map GIDs associated wi...
size_t insertGlobalIndicesImpl(const local_ordinal_type lclRow, const global_ordinal_type inputGblColInds[], const size_t numInputInds)
Insert global indices, using an input local row index.
static KOKKOS_INLINE_FUNCTION size_t unpackValue(LO &outVal, const char inBuf[])
Unpack the given value from the given output buffer.
void resumeFill(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Resume fill operations.
bool haveGlobalConstants_
Whether all processes have computed global constants.
void expertStaticFillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< const import_type > &importer=Teuchos::null, const Teuchos::RCP< const export_type > &exporter=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Perform a fillComplete on a graph that already has data, via setAllIndices().
Teuchos::RCP< const import_type > getImporter() const override
Returns the importer associated with this graph.
void getLocalDiagOffsets(const Kokkos::View< size_t *, device_type, Kokkos::MemoryUnmanaged > &offsets) const
Get offsets of the diagonal entries in the graph.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
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.
void insertGlobalIndices(const global_ordinal_type globalRow, const Teuchos::ArrayView< const global_ordinal_type > &indices)
Insert global indices into the graph.
size_t getNumEntriesInLocalRow(local_ordinal_type localRow) const override
Get the number of entries in the given row (local index).
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Default parameter list suitable for validation.
Declaration of a function that prints strings from each process.
void computeLocalConstants()
Compute local constants, if they have not yet been computed.
bool isIdenticalTo(const CrsGraph< LocalOrdinal, GlobalOrdinal, Node > &graph) const
Create a cloned CrsGraph for a different Node type.
bool isMerged() const
Whether duplicate column indices in each row have been merged.
virtual bool checkSizes(const SrcDistObject &source) override
Compare the source and target (this) objects for compatibility.
Teuchos::RCP< const map_type > getDomainMap() const override
Returns the Map associated with the domain of this graph.
size_t getGlobalMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, over all processes in the graph's communicator...
void getLocalRowView(const local_ordinal_type lclRow, Teuchos::ArrayView< const local_ordinal_type > &lclColInds) const override
Get a const, non-persisting view of the given local row's local column indices, as a Teuchos::ArrayVi...
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.
static bool debug()
Whether Tpetra is in debug mode.
size_t findLocalIndices(const RowInfo &rowInfo, const Teuchos::ArrayView< const local_ordinal_type > &indices, std::function< void(const size_t, const size_t, const size_t)> fun) const
Finds indices in the given row.
size_t getNumAllocatedEntriesInGlobalRow(global_ordinal_type globalRow) const
Current number of allocated entries in the given row on the calling (MPI) process, using a global row index.
Allocation information for a locally owned row in a CrsGraph or CrsMatrix.
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.
bool hasColMap() const override
Whether the graph has a column Map.
bool isGloballyIndexed() const override
Whether the graph's column indices are stored as global indices.
void exportAndFillComplete(Teuchos::RCP< CrsGraph< local_ordinal_type, global_ordinal_type, Node > > &destGraph, const export_type &exporter, const Teuchos::RCP< const map_type > &domainMap=Teuchos::null, const Teuchos::RCP< const map_type > &rangeMap=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null) const
Export from this to the given destination graph, and make the result fill complete.
Teuchos_Ordinal Array_size_type
Size type for Teuchos Array objects.
int local_ordinal_type
Default value of Scalar template parameter.
bool isStorageOptimized() const
Returns true if storage has been optimized.
bool haveLocalConstants_
Whether this process has computed local constants.
std::string description() const override
Return a one-line human-readable description of this object.
local_ordinal_type getLocalViewRawConst(const local_ordinal_type *&lclInds, local_ordinal_type &capacity, const RowInfo &rowInfo) const
Get a pointer to the local column indices of a locally owned row, using the result of getRowInfo...
void gathervPrint(std::ostream &out, const std::string &s, const Teuchos::Comm< int > &comm)
On Process 0 in the given communicator, print strings from each process in that communicator, in rank order.
void makeColMap(Teuchos::Array< int > &remotePIDs)
Make and set the graph's column Map.
Teuchos::RCP< const export_type > getExporter() const override
Returns the exporter associated with this graph.
std::pair< size_t, std::string > makeIndicesLocal(const bool verbose=false)
Convert column indices from global to local.
void getNumEntriesPerLocalRowUpperBound(Teuchos::ArrayRCP< const size_t > &boundPerLocalRow, size_t &boundForAllLocalRows, bool &boundSameForAllLocalRows) const
Get an upper bound on the number of entries that can be stored in each row.
size_t global_size_t
Global size_t object.
size_t getNodeNumEntries() const override
The local number of entries in the graph.
virtual void removeEmptyProcessesInPlace(const Teuchos::RCP< const map_type > &newMap) override
Remove processes owning zero rows from the Maps and their communicator.
Node node_type
This class' Kokkos Node type.
void reindexColumns(const Teuchos::RCP< const map_type > &newColMap, const Teuchos::RCP< const import_type > &newImport=Teuchos::null, const bool sortIndicesInEachRow=true)
Reindex the column indices in place, and replace the column Map. Optionally, replace the Import objec...
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
void makeImportExport(Teuchos::Array< int > &remotePIDs, const bool useRemotePIDs)
Make the Import and Export objects, if needed.
size_t sortAndMergeRowIndices(const RowInfo &rowInfo, const bool sorted, const bool merged)
Sort and merge duplicate column indices in the given row.
void insertLocalIndices(const local_ordinal_type localRow, const Teuchos::ArrayView< const local_ordinal_type > &indices)
Insert local indices into the graph.
Insert new values that don't currently exist.
void getGlobalRowCopy(global_ordinal_type gblRow, const Teuchos::ArrayView< global_ordinal_type > &gblColInds, size_t &numColInds) const override
Get a copy of the given row, using global indices.
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...
bool isSorted() const
Whether graph indices in all rows are known to be sorted.
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.
global_size_t getGlobalNumRows() const override
Returns the number of global rows in the graph.
global_ordinal_type getGlobalElement(local_ordinal_type localIndex) const
The global index corresponding to the given local index.
Teuchos::ArrayView< const global_ordinal_type > getGlobalView(const RowInfo &rowinfo) const
Get a const, nonowned, globally indexed view of the locally owned row myRow, such that rowinfo = getR...
bool isNodeLocalElement(local_ordinal_type localIndex) const
Whether the given local index is valid for this Map on the calling process.
Functions for manipulating CRS arrays.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
void setLocallyModified()
Report that we made a local modification to its structure.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
local_graph_type::entries_type::non_const_type k_lclInds1D_
Local column indices for all rows.
Teuchos::ArrayView< local_ordinal_type > getLocalViewNonConst(const RowInfo &rowinfo)
Get a nonconst, nonowned, locally indexed view of the locally owned row myRow, such that rowinfo = ge...
size_t getNodeNumRows() const override
Returns the number of graph rows owned on the calling node.
ProfileType getProfileType() const
Returns true if the graph was allocated with static data structures.
void checkInternalState() const
Throw an exception if the internal state is not consistent.
bool isNodeGlobalElement(global_ordinal_type globalIndex) const
Whether the given global index is owned by this Map on the calling process.
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.
CombineMode
Rule for combining data in an Import or Export.
Kokkos::View< const size_t *, execution_space >::HostMirror k_numAllocPerRow_
The maximum number of entries to allow in each locally owned row, per row.
Teuchos::RCP< const export_type > exporter_
The Export from the row Map to the range Map.
void insertGlobalIndicesIntoNonownedRows(const global_ordinal_type gblRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Implementation of insertGlobalIndices for nonowned rows.
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
bool isFillComplete() const override
Whether fillComplete() has been called and the graph is in compute mode.
size_t getNumAllocatedEntriesInLocalRow(local_ordinal_type localRow) const
Current number of allocated entries in the given row on the calling (MPI) process, using a local row index.
Teuchos::ArrayRCP< const size_t > getNodeRowPtrs() const
Get a host view of the row offsets.
void swap(CrsGraph< local_ordinal_type, global_ordinal_type, Node > &graph)
Swaps the data from *this with the data and maps from graph.
void globalAssemble()
Communicate nonlocal contributions to other processes.
typename device_type::execution_space execution_space
This class' Kokkos execution space.
RowInfo getRowInfoFromGlobalRowIndex(const global_ordinal_type gblRow) const
Get information about the locally owned row with global index gblRow.
Utility functions for packing and unpacking sparse matrix entries.
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.
void removeLocalIndices(local_ordinal_type localRow)
Remove all graph indices from the specified local row.
size_t getNodeAllocationSize() const
The local number of indices allocated for the graph, over all rows on the calling (MPI) process...
LocalOrdinal local_ordinal_type
The type of the graph's local indices.
global_size_t globalNumEntries_
Global number of entries in the graph.
Teuchos::ArrayView< global_ordinal_type > getGlobalViewNonConst(const RowInfo &rowinfo)
Get a nonconst, nonowned, globally indexed view of the locally owned row myRow, such that rowinfo = g...
Teuchos::RCP< const map_type > getRangeMap() const override
Returns the Map associated with the domain of this graph.
void replaceColMap(const Teuchos::RCP< const map_type > &newColMap)
Replace the graph's current column Map with the given Map.
void getGlobalRowView(const global_ordinal_type gblRow, Teuchos::ArrayView< const global_ordinal_type > &gblColInds) const override
Get a const, non-persisting view of the given global row's global column indices, as a Teuchos::Array...
::Kokkos::Compat::KokkosDeviceWrapperNode< execution_space > node_type
Default value of Node template parameter.
global_size_t getGlobalNumCols() const override
Returns the number of global columns in the graph.
RowInfo getRowInfo(const local_ordinal_type myRow) const
Get information about the locally owned row with local index myRow.
size_t getNodeNumCols() const override
Returns the number of columns connected to the locally owned rows of this graph.
void replaceDomainMapAndImporter(const Teuchos::RCP< const map_type > &newDomainMap, const Teuchos::RCP< const import_type > &newImporter)
Replace the current domain Map and Import with the given parameters.
bool supportsRowViews() const override
Whether this class implements getLocalRowView() and getGlobalRowView() (it does). ...
local_map_type getLocalMap() const
Get the local Map for Kokkos kernels.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
Teuchos::ArrayView< const local_ordinal_type > getLocalView(const RowInfo &rowinfo) const
Get a const, nonowned, locally indexed view of the locally owned row myRow, such that rowinfo = getRo...
Details::EStorageStatus storageStatus_
Status of the graph's storage, when not in a fill-complete state.
A parallel distribution of indices over processes.
local_ordinal_type getGlobalViewRawConst(const global_ordinal_type *&gblInds, local_ordinal_type &capacity, const RowInfo &rowInfo) const
Get a pointer to the global column indices of a locally owned row, using the result of getRowInfoFrom...
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...
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > ¶ms) override
Set the given list of parameters (must be nonnull).
size_t getNumEntriesInGlobalRow(global_ordinal_type globalRow) const override
Returns the current number of entries on this node in the specified global row.
void fillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Tell the graph that you are done changing its structure.
local_ordinal_type getLocalElement(global_ordinal_type globalIndex) const
The local index corresponding to the given global index.
typename Node::device_type device_type
This class' Kokkos device type.
bool isLocallyIndexed() const override
Whether the graph's column indices are stored as local indices.
A distributed dense vector.
Stand-alone utility functions and macros.
Teuchos::ArrayRCP< const local_ordinal_type > getNodePackedIndices() const
Get an Teuchos::ArrayRCP of the packed column-indices.
bool isFillActive() const
Whether resumeFill() has been called and the graph is in edit mode.
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.
void importAndFillComplete(Teuchos::RCP< CrsGraph< local_ordinal_type, global_ordinal_type, Node > > &destGraph, const import_type &importer, const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null) const
Import from this to the given destination graph, and make the result fill complete.
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.
local_graph_type getLocalGraph() const
Get the local graph.
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...
size_t insertIndices(RowInfo &rowInfo, const SLocalGlobalViews &newInds, const ELocalGlobal lg, const ELocalGlobal I)
Insert indices into the given row.
global_size_t getGlobalNumEntries() const override
Returns the global number of entries in the graph.
Declaration and definition of Tpetra::Details::getEntryOnHost.
size_t numAllocForAllRows_
The maximum number of entries to allow in each locally owned row.
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.
virtual void pack(const Teuchos::ArrayView< const local_ordinal_type > &exportLIDs, Teuchos::Array< global_ordinal_type > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, size_t &constantNumPackets, Distributor &distor) const override
Pack this object's data for Import or Export.
void getLocalRowCopy(local_ordinal_type lclRow, const Teuchos::ArrayView< local_ordinal_type > &lclColInds, size_t &numColInds) const override
Get a copy of the given row, using local indices.
std::unique_ptr< std::string > createPrefix(const int myRank, const char prefix[])
Create string prefix for each line of verbose output.
nonlocals_type nonlocals_
Nonlocal data given to insertGlobalIndices.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const override
Print this object to the given output stream with the given verbosity level.
void computeGlobalConstants()
Compute global constants, if they have not yet been computed.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.