10 #ifndef TPETRA_CRSGRAPH_DEF_HPP
11 #define TPETRA_CRSGRAPH_DEF_HPP
20 #include "Tpetra_Details_getGraphDiagOffsets.hpp"
21 #include "Tpetra_Details_getGraphOffRankOffsets.hpp"
22 #include "Tpetra_Details_makeColMap.hpp"
26 #include "Tpetra_Distributor.hpp"
27 #include "Teuchos_SerialDenseMatrix.hpp"
28 #include "Tpetra_Vector.hpp"
31 #include "Tpetra_Details_packCrsGraph.hpp"
32 #include "Tpetra_Details_unpackCrsGraphAndCombine.hpp"
33 #include "Tpetra_Details_CrsPadding.hpp"
40 #include <type_traits>
48 template<
class MapIter>
50 verbosePrintMap(std::ostream& out,
56 using ::Tpetra::Details::Behavior;
59 out << mapName <<
": {";
60 const size_t maxNumToPrint =
62 if (maxNumToPrint == 0) {
68 const size_t numToPrint = numEnt > maxNumToPrint ?
69 maxNumToPrint : numEnt;
71 for (MapIter it = beg; it != end; ++it) {
72 out <<
"(" << (*it).first <<
", ";
76 if (count +
size_t(1) < numToPrint) {
88 template<
class LO,
class GO,
class Node>
89 Teuchos::ArrayView<GO>
91 std::vector<GO>& gblColIndsStorage,
92 const RowGraph<LO, GO, Node>& graph,
95 size_t origNumEnt = graph.getNumEntriesInGlobalRow(gblRowInd);
96 if (gblColIndsStorage.size() < origNumEnt) {
97 gblColIndsStorage.resize(origNumEnt);
99 typename CrsGraph<LO,GO,Node>::nonconst_global_inds_host_view_type gblColInds(gblColIndsStorage.data(),
101 graph.getGlobalRowCopy(gblRowInd, gblColInds, origNumEnt);
102 Teuchos::ArrayView<GO> retval(gblColIndsStorage.data(),origNumEnt);
106 template<
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
107 class ConvertColumnIndicesFromGlobalToLocal {
109 ConvertColumnIndicesFromGlobalToLocal (const ::Kokkos::View<LO*, DT>& lclColInds,
110 const ::Kokkos::View<const GO*, DT>& gblColInds,
111 const ::Kokkos::View<const OffsetType*, DT>& ptr,
112 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
113 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt) :
114 lclColInds_ (lclColInds),
115 gblColInds_ (gblColInds),
117 lclColMap_ (lclColMap),
118 numRowEnt_ (numRowEnt)
122 operator () (
const LO& lclRow, OffsetType& curNumBad)
const
124 const OffsetType offset = ptr_(lclRow);
128 const LO numEnt =
static_cast<LO
> (numRowEnt_(lclRow));
129 for (LO j = 0; j < numEnt; ++j) {
130 const GO gid = gblColInds_(offset + j);
131 const LO lid = lclColMap_.getLocalElement (gid);
132 lclColInds_(offset + j) = lid;
133 if (lid == ::Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
140 run (const ::Kokkos::View<LO*, DT>& lclColInds,
141 const ::Kokkos::View<const GO*, DT>& gblColInds,
142 const ::Kokkos::View<const OffsetType*, DT>& ptr,
143 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
144 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt)
146 typedef ::Kokkos::RangePolicy<typename DT::execution_space, LO> range_type;
147 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> functor_type;
149 const LO lclNumRows = ptr.extent (0) == 0 ?
150 static_cast<LO
> (0) : static_cast<LO> (ptr.extent (0) - 1);
151 OffsetType numBad = 0;
153 ::Kokkos::parallel_reduce (range_type (0, lclNumRows),
154 functor_type (lclColInds, gblColInds, ptr,
155 lclColMap, numRowEnt),
161 ::Kokkos::View<LO*, DT> lclColInds_;
162 ::Kokkos::View<const GO*, DT> gblColInds_;
163 ::Kokkos::View<const OffsetType*, DT> ptr_;
165 ::Kokkos::View<const NumEntType*, DT> numRowEnt_;
184 template<
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
187 const Kokkos::View<const GO*, DT>& gblColInds,
188 const Kokkos::View<const OffsetType*, DT>& ptr,
190 const Kokkos::View<const NumEntType*, DT>& numRowEnt)
192 using Impl::ConvertColumnIndicesFromGlobalToLocal;
193 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> impl_type;
194 return impl_type::run (lclColInds, gblColInds, ptr, lclColMap, numRowEnt);
197 template<
class ViewType,
class LO>
198 class MaxDifference {
200 MaxDifference (
const ViewType& ptr) : ptr_ (ptr) {}
202 KOKKOS_INLINE_FUNCTION
void init (LO& dst)
const {
206 KOKKOS_INLINE_FUNCTION
void
207 join (LO& dst,
const LO& src)
const
209 dst = (src > dst) ? src : dst;
212 KOKKOS_INLINE_FUNCTION
void
213 operator () (
const LO lclRow, LO& maxNumEnt)
const
215 const LO numEnt =
static_cast<LO
> (ptr_(lclRow+1) - ptr_(lclRow));
216 maxNumEnt = (numEnt > maxNumEnt) ? numEnt : maxNumEnt;
219 typename ViewType::const_type ptr_;
222 template<
class ViewType,
class LO>
223 typename ViewType::non_const_value_type
224 maxDifference (
const char kernelLabel[],
228 if (lclNumRows == 0) {
231 return static_cast<LO
> (0);
234 using execution_space =
typename ViewType::execution_space;
235 using range_type = Kokkos::RangePolicy<execution_space, LO>;
237 Kokkos::parallel_reduce (kernelLabel,
238 range_type (0, lclNumRows),
239 MaxDifference<ViewType, LO> (ptr),
247 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
249 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
254 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
256 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
261 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
262 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
263 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
264 const size_t maxNumEntriesPerRow,
265 const Teuchos::RCP<Teuchos::ParameterList>& params) :
268 , numAllocForAllRows_ (maxNumEntriesPerRow)
270 const char tfecfFuncName[] =
271 "CrsGraph(rowMap,maxNumEntriesPerRow,params): ";
273 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
274 (maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid (),
275 std::invalid_argument,
"The allocation hint maxNumEntriesPerRow must be "
276 "a valid size_t value, which in this case means it must not be "
277 "Teuchos::OrdinalTraits<size_t>::invalid().");
282 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
284 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
285 const Teuchos::RCP<const map_type>& colMap,
286 const size_t maxNumEntriesPerRow,
287 const Teuchos::RCP<Teuchos::ParameterList>& params) :
291 , numAllocForAllRows_ (maxNumEntriesPerRow)
293 const char tfecfFuncName[] =
294 "CrsGraph(rowMap,colMap,maxNumEntriesPerRow,params): ";
296 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
297 maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid (),
298 std::invalid_argument,
"The allocation hint maxNumEntriesPerRow must be "
299 "a valid size_t value, which in this case means it must not be "
300 "Teuchos::OrdinalTraits<size_t>::invalid().");
306 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
308 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
309 const Teuchos::ArrayView<const size_t>& numEntPerRow,
310 const Teuchos::RCP<Teuchos::ParameterList>& params) :
313 , numAllocForAllRows_ (0)
315 const char tfecfFuncName[] =
316 "CrsGraph(rowMap,numEntPerRow,params): ";
319 const size_t lclNumRows = rowMap.is_null () ?
320 static_cast<size_t> (0) : rowMap->getLocalNumElements ();
321 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
322 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
323 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
324 <<
" != the local number of rows " << lclNumRows <<
" as specified by "
325 "the input row Map.");
328 for (
size_t r = 0; r < lclNumRows; ++r) {
329 const size_t curRowCount = numEntPerRow[r];
330 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
331 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
332 std::invalid_argument,
"numEntPerRow(" << r <<
") "
333 "specifies an invalid number of entries "
334 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
342 typedef typename out_view_type::non_const_type nc_view_type;
343 typedef Kokkos::View<
const size_t*,
344 typename nc_view_type::array_layout,
346 Kokkos::MemoryUnmanaged> in_view_type;
347 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
348 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
351 using exec_space =
typename nc_view_type::execution_space;
361 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
363 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
364 const Kokkos::DualView<const size_t*, device_type>& numEntPerRow,
365 const Teuchos::RCP<Teuchos::ParameterList>& params) :
368 , k_numAllocPerRow_ (numEntPerRow.view_host())
369 , numAllocForAllRows_ (0)
371 const char tfecfFuncName[] =
372 "CrsGraph(rowMap,numEntPerRow,params): ";
375 const size_t lclNumRows = rowMap.is_null () ?
376 static_cast<size_t> (0) : rowMap->getLocalNumElements ();
377 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
378 static_cast<size_t> (numEntPerRow.extent (0)) != lclNumRows,
379 std::invalid_argument,
"numEntPerRow has length " <<
380 numEntPerRow.extent (0) <<
" != the local number of rows " <<
381 lclNumRows <<
" as specified by " "the input row Map.");
384 for (
size_t r = 0; r < lclNumRows; ++r) {
385 const size_t curRowCount = numEntPerRow.view_host()(r);
386 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
387 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
388 std::invalid_argument,
"numEntPerRow(" << r <<
") "
389 "specifies an invalid number of entries "
390 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
399 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
401 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
402 const Teuchos::RCP<const map_type>& colMap,
403 const Kokkos::DualView<const size_t*, device_type>& numEntPerRow,
404 const Teuchos::RCP<Teuchos::ParameterList>& params) :
408 , k_numAllocPerRow_ (numEntPerRow.view_host())
409 , numAllocForAllRows_ (0)
411 const char tfecfFuncName[] =
412 "CrsGraph(rowMap,colMap,numEntPerRow,params): ";
415 const size_t lclNumRows = rowMap.is_null () ?
416 static_cast<size_t> (0) : rowMap->getLocalNumElements ();
417 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
418 static_cast<size_t> (numEntPerRow.extent (0)) != lclNumRows,
419 std::invalid_argument,
"numEntPerRow has length " <<
420 numEntPerRow.extent (0) <<
" != the local number of rows " <<
421 lclNumRows <<
" as specified by " "the input row Map.");
424 for (
size_t r = 0; r < lclNumRows; ++r) {
425 const size_t curRowCount = numEntPerRow.view_host()(r);
426 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
427 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
428 std::invalid_argument,
"numEntPerRow(" << r <<
") "
429 "specifies an invalid number of entries "
430 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
439 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
441 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
442 const Teuchos::RCP<const map_type>& colMap,
443 const Teuchos::ArrayView<const size_t>& numEntPerRow,
444 const Teuchos::RCP<Teuchos::ParameterList>& params) :
448 , numAllocForAllRows_ (0)
450 const char tfecfFuncName[] =
451 "CrsGraph(rowMap,colMap,numEntPerRow,params): ";
454 const size_t lclNumRows = rowMap.is_null () ?
455 static_cast<size_t> (0) : rowMap->getLocalNumElements ();
456 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
457 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
458 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
459 <<
" != the local number of rows " << lclNumRows <<
" as specified by "
460 "the input row Map.");
463 for (
size_t r = 0; r < lclNumRows; ++r) {
464 const size_t curRowCount = numEntPerRow[r];
465 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
466 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
467 std::invalid_argument,
"numEntPerRow(" << r <<
") "
468 "specifies an invalid number of entries "
469 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
477 typedef typename out_view_type::non_const_type nc_view_type;
478 typedef Kokkos::View<
const size_t*,
479 typename nc_view_type::array_layout,
481 Kokkos::MemoryUnmanaged> in_view_type;
482 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
483 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
486 using exec_space =
typename nc_view_type::execution_space;
495 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
498 const Teuchos::RCP<const map_type>& rowMap,
499 const Teuchos::RCP<Teuchos::ParameterList>& params) :
502 , colMap_(originalGraph.colMap_)
503 , numAllocForAllRows_(originalGraph.numAllocForAllRows_)
504 , storageStatus_(originalGraph.storageStatus_)
505 , indicesAreAllocated_(originalGraph.indicesAreAllocated_)
506 , indicesAreLocal_(originalGraph.indicesAreLocal_)
507 , indicesAreSorted_(originalGraph.indicesAreSorted_)
511 int numRows = rowMap->getLocalNumElements();
513 auto rowsToUse = Kokkos::pair<size_t, size_t>(0, numRows+1);
519 if (indicesAreLocal_) {
530 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
532 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
533 const Teuchos::RCP<const map_type>& colMap,
534 const typename local_graph_device_type::row_map_type& rowPointers,
535 const typename local_graph_device_type::entries_type::non_const_type& columnIndices,
536 const Teuchos::RCP<Teuchos::ParameterList>& params) :
540 , numAllocForAllRows_(0)
541 , storageStatus_(Details::STORAGE_1D_PACKED)
542 , indicesAreAllocated_(true)
543 , indicesAreLocal_(true)
546 if (! params.is_null() && params->isParameter(
"sorted") &&
547 ! params->get<
bool>(
"sorted")) {
557 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
559 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
560 const Teuchos::RCP<const map_type>& colMap,
561 const Teuchos::ArrayRCP<size_t>& rowPointers,
562 const Teuchos::ArrayRCP<LocalOrdinal> & columnIndices,
563 const Teuchos::RCP<Teuchos::ParameterList>& params) :
567 , numAllocForAllRows_ (0)
568 , storageStatus_ (Details::STORAGE_1D_PACKED)
569 , indicesAreAllocated_ (true)
570 , indicesAreLocal_ (true)
573 if (! params.is_null() && params->isParameter(
"sorted") &&
574 ! params->get<
bool>(
"sorted")) {
584 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
586 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
587 const Teuchos::RCP<const map_type>& colMap,
589 const Teuchos::RCP<Teuchos::ParameterList>& params)
598 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
601 const Teuchos::RCP<const map_type>& rowMap,
602 const Teuchos::RCP<const map_type>& colMap,
603 const Teuchos::RCP<const map_type>& domainMap,
604 const Teuchos::RCP<const map_type>& rangeMap,
605 const Teuchos::RCP<Teuchos::ParameterList>& params)
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->getLocalNumElements (),
623 ": The input row Map and the input local graph need to have the same "
624 "number of rows. The row Map claims " << rowMap->getLocalNumElements ()
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);
654 this->setRowPtrs(k_local_graph_.row_map);
656 set_need_sync_host_uvm_access();
658 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
659 params->get (
"compute global constants",
true);
661 if (callComputeGlobalConstants) {
664 this->fillComplete_ =
true;
668 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
671 const Teuchos::RCP<const map_type>& rowMap,
672 const Teuchos::RCP<const map_type>& colMap,
673 const Teuchos::RCP<const map_type>& domainMap,
674 const Teuchos::RCP<const map_type>& rangeMap,
675 const Teuchos::RCP<const import_type>& importer,
676 const Teuchos::RCP<const export_type>& exporter,
677 const Teuchos::RCP<Teuchos::ParameterList>& params) :
681 rangeMap_ (rangeMap.is_null () ? rowMap : rangeMap),
682 domainMap_ (domainMap.is_null () ? rowMap : domainMap),
683 importer_ (importer),
684 exporter_ (exporter),
685 numAllocForAllRows_ (0),
686 storageStatus_ (Details::STORAGE_1D_PACKED),
687 indicesAreAllocated_ (true),
688 indicesAreLocal_ (true)
691 const char tfecfFuncName[] =
"Tpetra::CrsGraph(local_graph_device_type,"
692 "Map,Map,Map,Map,Import,Export,params): ";
694 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
695 (colMap.is_null (), std::runtime_error,
696 "The input column Map must be nonnull.");
700 setRowPtrs(lclGraph.row_map);
702 set_need_sync_host_uvm_access();
704 if (! params.is_null() && params->isParameter(
"sorted") &&
705 ! params->get<
bool>(
"sorted")) {
712 const bool callComputeGlobalConstants =
713 params.get () ==
nullptr ||
714 params->get (
"compute global constants",
true);
715 if (callComputeGlobalConstants) {
718 fillComplete_ =
true;
722 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
724 CrsGraph (
const row_ptrs_device_view_type& rowPointers,
726 const Teuchos::RCP<const map_type>& rowMap,
727 const Teuchos::RCP<const map_type>& colMap,
728 const Teuchos::RCP<const map_type>& domainMap,
729 const Teuchos::RCP<const map_type>& rangeMap,
730 const Teuchos::RCP<const import_type>& importer,
731 const Teuchos::RCP<const export_type>& exporter,
732 const Teuchos::RCP<Teuchos::ParameterList>& params) :
736 rangeMap_ (rangeMap.is_null () ? rowMap : rangeMap),
737 domainMap_ (domainMap.is_null () ? rowMap : domainMap),
738 importer_ (importer),
739 exporter_ (exporter),
740 numAllocForAllRows_ (0),
741 storageStatus_ (Details::STORAGE_1D_PACKED),
742 indicesAreAllocated_ (true),
743 indicesAreLocal_ (true)
746 const char tfecfFuncName[] =
"Tpetra::CrsGraph(row_ptrs_device_view_type,local_inds_wdv_type"
747 "Map,Map,Map,Map,Import,Export,params): ";
749 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
750 (colMap.is_null (), std::runtime_error,
751 "The input column Map must be nonnull.");
755 setRowPtrs(rowPointers);
757 set_need_sync_host_uvm_access();
759 if (! params.is_null() && params->isParameter(
"sorted") &&
760 ! params->get<
bool>(
"sorted")) {
767 const bool callComputeGlobalConstants =
768 params.get () ==
nullptr ||
769 params->get (
"compute global constants",
true);
770 if (callComputeGlobalConstants) {
773 fillComplete_ =
true;
777 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
778 Teuchos::RCP<const Teuchos::ParameterList>
783 using Teuchos::ParameterList;
784 using Teuchos::parameterList;
786 RCP<ParameterList> params = parameterList (
"Tpetra::CrsGraph");
789 RCP<ParameterList> importSublist = parameterList (
"Import");
801 Distributor distributor (rowMap_->getComm (), importSublist);
802 params->set (
"Import", *importSublist,
"How the Import performs communication.");
808 params->set (
"Export", *importSublist,
"How the Export performs communication.");
813 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
818 Teuchos::RCP<const Teuchos::ParameterList> validParams =
819 getValidParameters ();
820 params->validateParametersAndSetDefaults (*validParams);
821 this->setMyParamList (params);
824 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
829 return rowMap_->getGlobalNumElements ();
832 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
837 const char tfecfFuncName[] =
"getGlobalNumCols: ";
838 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
839 ! isFillComplete () || getDomainMap ().is_null (), std::runtime_error,
840 "The graph does not have a domain Map. You may not call this method in "
842 return getDomainMap ()->getGlobalNumElements ();
846 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
851 return this->rowMap_.is_null () ?
852 static_cast<size_t> (0) :
853 this->rowMap_->getLocalNumElements ();
857 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
862 const char tfecfFuncName[] =
"getLocalNumCols: ";
863 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
864 ! hasColMap (), std::runtime_error,
865 "The graph does not have a column Map. You may not call this method "
866 "unless the graph has a column Map. This requires either that a custom "
867 "column Map was given to the constructor, or that fillComplete() has "
869 return colMap_.is_null () ?
static_cast<size_t> (0) :
870 colMap_->getLocalNumElements ();
875 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
876 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
883 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
884 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
891 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
892 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
899 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
900 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
907 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
908 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::import_type>
915 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
916 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::export_type>
923 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
928 return ! colMap_.is_null ();
931 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
939 const bool isOpt = indicesAreAllocated_ &&
940 k_numRowEntries_.extent (0) == 0 &&
941 getLocalNumRows () > 0;
947 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
952 const char tfecfFuncName[] =
"getGlobalNumEntries: ";
953 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
954 (! this->haveGlobalConstants_, std::logic_error,
955 "The graph does not have global constants computed, "
956 "but the user has requested them.");
958 return globalNumEntries_;
962 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
967 const char tfecfFuncName[] =
"getLocalNumEntries: ";
968 typedef LocalOrdinal LO;
970 if (this->indicesAreAllocated_) {
971 const LO lclNumRows = this->getLocalNumRows ();
972 if (lclNumRows == 0) {
973 return static_cast<size_t> (0);
977 auto numEntPerRow = this->k_numRowEntries_;
978 const LO numNumEntPerRow = numEntPerRow.extent (0);
979 if (numNumEntPerRow == 0) {
980 if (static_cast<LO> (this->getRowPtrsPackedDevice().extent (0)) <
981 static_cast<LO> (lclNumRows + 1)) {
982 return static_cast<size_t> (0);
989 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
990 (this->getRowPtrsPackedHost()(lclNumRows) != lclIndsPacked_wdv.extent(0), std::logic_error,
991 "Final entry of packed host rowptrs doesn't match the length of lclIndsPacked");
993 return lclIndsPacked_wdv.extent(0);
1003 typedef typename num_row_entries_type::execution_space
1005 typedef Kokkos::RangePolicy<host_exec_space, LO> range_type;
1007 const LO upperLoopBound = lclNumRows < numNumEntPerRow ?
1010 size_t nodeNumEnt = 0;
1011 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::getNumNodeEntries",
1012 range_type (0, upperLoopBound),
1013 [=] (
const LO& k,
size_t& lclSum) {
1014 lclSum += numEntPerRow(k);
1021 return static_cast<size_t> (0);
1025 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1030 const char tfecfFuncName[] =
"getGlobalMaxNumRowEntries: ";
1031 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1032 (! this->haveGlobalConstants_, std::logic_error,
1033 "The graph does not have global constants computed, "
1034 "but the user has requested them.");
1036 return globalMaxNumRowEntries_;
1039 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1044 return nodeMaxNumRowEntries_;
1047 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1052 return fillComplete_;
1055 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1060 return ! fillComplete_;
1064 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1069 return indicesAreLocal_;
1072 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1077 return indicesAreGlobal_;
1080 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1085 typedef LocalOrdinal LO;
1087 if (this->indicesAreAllocated_) {
1088 const LO lclNumRows = this->getLocalNumRows ();
1089 if (lclNumRows == 0) {
1090 return static_cast<size_t> (0);
1092 else if (storageStatus_ == Details::STORAGE_1D_PACKED) {
1093 if (static_cast<LO> (this->getRowPtrsPackedDevice().extent (0)) <
1094 static_cast<LO
> (lclNumRows + 1)) {
1095 return static_cast<size_t> (0);
1098 if(this->isLocallyIndexed())
1099 return lclIndsPacked_wdv.extent(0);
1101 return gblInds_wdv.extent(0);
1104 else if (storageStatus_ == Details::STORAGE_1D_UNPACKED) {
1105 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
1106 if (rowPtrsUnpacked_host.extent (0) == 0) {
1107 return static_cast<size_t> (0);
1110 if(this->isLocallyIndexed())
1111 return lclIndsUnpacked_wdv.extent(0);
1113 return gblInds_wdv.extent(0);
1117 return static_cast<size_t> (0);
1121 return Tpetra::Details::OrdinalTraits<size_t>::invalid ();
1125 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1126 Teuchos::RCP<const Teuchos::Comm<int> >
1130 return this->rowMap_.is_null () ? Teuchos::null : this->rowMap_->getComm ();
1133 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1138 return rowMap_->getIndexBase ();
1141 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1146 return indicesAreAllocated_;
1149 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1154 return indicesAreSorted_;
1157 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1162 return noRedundancies_;
1165 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1175 indicesAreSorted_ =
false;
1176 noRedundancies_ =
false;
1180 haveLocalConstants_ =
false;
1183 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1189 using Teuchos::arcp;
1190 using Teuchos::Array;
1191 using Teuchos::ArrayRCP;
1193 typedef Teuchos::ArrayRCP<size_t>::size_type size_type;
1194 typedef typename local_graph_device_type::row_map_type::non_const_type
1195 non_const_row_map_type;
1196 const char tfecfFuncName[] =
"allocateIndices: ";
1197 const char suffix[] =
1198 " Please report this bug to the Tpetra developers.";
1199 ProfilingRegion profRegion(
"Tpetra::CrsGraph::allocateIndices");
1201 std::unique_ptr<std::string> prefix;
1203 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
1204 std::ostringstream os;
1205 os << *prefix <<
"Start: lg="
1206 << (lg == GlobalIndices ?
"GlobalIndices" :
"LocalIndices")
1207 <<
", numRows: " << this->getLocalNumRows() << endl;
1208 std::cerr << os.str();
1214 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1215 (isLocallyIndexed () && lg == GlobalIndices, std::logic_error,
1216 ": The graph is locally indexed, but Tpetra code is calling "
1217 "this method with lg=GlobalIndices." << suffix);
1218 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1219 (isGloballyIndexed () && lg == LocalIndices, std::logic_error,
1220 ": The graph is globally indexed, but Tpetra code is calling "
1221 "this method with lg=LocalIndices." << suffix);
1222 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1223 (indicesAreAllocated (), std::logic_error,
": The graph's "
1224 "indices are already allocated, but Tpetra is calling "
1225 "allocateIndices again." << suffix);
1226 const size_t numRows = this->getLocalNumRows ();
1231 size_type numInds = 0;
1234 std::ostringstream os;
1235 os << *prefix <<
"Allocate k_rowPtrs: " << (numRows+1) << endl;
1236 std::cerr << os.str();
1238 non_const_row_map_type k_rowPtrs (
"Tpetra::CrsGraph::ptr", numRows + 1);
1240 if (this->k_numAllocPerRow_.extent (0) != 0) {
1245 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1246 (this->k_numAllocPerRow_.extent (0) != numRows,
1247 std::invalid_argument,
"k_numAllocPerRow_ is allocated, that is, "
1248 "has nonzero length " << this->k_numAllocPerRow_.extent (0)
1249 <<
", but its length != numRows = " << numRows <<
".");
1267 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1268 (this->numAllocForAllRows_ ==
1269 Tpetra::Details::OrdinalTraits<size_t>::invalid (),
1270 std::invalid_argument,
"numAllocForAllRows_ has an invalid value, "
1271 "namely Tpetra::Details::OrdinalTraits<size_t>::invalid() = " <<
1272 Tpetra::Details::OrdinalTraits<size_t>::invalid () <<
".");
1278 setRowPtrsUnpacked(k_rowPtrs);
1281 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1282 (numInds != size_type(this->getRowPtrsUnpackedHost()(numRows)), std::logic_error,
1283 ": Number of indices produced by computeOffsetsFrom[Constant]Counts "
1284 "does not match final entry of rowptrs unpacked");
1288 if (lg == LocalIndices) {
1290 std::ostringstream os;
1291 os << *prefix <<
"Allocate local column indices "
1292 "lclIndsUnpacked_wdv: " << numInds << endl;
1293 std::cerr << os.str();
1295 lclIndsUnpacked_wdv = local_inds_wdv_type (
1296 local_inds_dualv_type(
"Tpetra::CrsGraph::lclInd",numInds));
1300 std::ostringstream os;
1301 os << *prefix <<
"Allocate global column indices "
1302 "gblInds_wdv: " << numInds << endl;
1303 std::cerr << os.str();
1305 gblInds_wdv = global_inds_wdv_type (
1306 global_inds_dualv_type(
"Tpetra::CrsGraph::gblInd",numInds));
1308 storageStatus_ = Details::STORAGE_1D_UNPACKED;
1310 this->indicesAreLocal_ = (lg == LocalIndices);
1311 this->indicesAreGlobal_ = (lg == GlobalIndices);
1314 using Kokkos::ViewAllocateWithoutInitializing;
1315 const char label[] =
"Tpetra::CrsGraph::numRowEntries";
1317 std::ostringstream os;
1318 os << *prefix <<
"Allocate k_numRowEntries_: " << numRows
1320 std::cerr << os.str();
1322 num_row_entries_type numRowEnt (ViewAllocateWithoutInitializing (label), numRows);
1325 Kokkos::fence(
"CrsGraph::allocateIndices");
1326 this->k_numRowEntries_ = numRowEnt;
1330 this->numAllocForAllRows_ = 0;
1331 this->k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
1332 this->indicesAreAllocated_ =
true;
1335 this->checkInternalState ();
1337 catch (std::logic_error& e) {
1338 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1339 (
true, std::logic_error,
"At end of allocateIndices, "
1340 "checkInternalState threw std::logic_error: "
1343 catch (std::exception& e) {
1344 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1345 (
true, std::runtime_error,
"At end of allocateIndices, "
1346 "checkInternalState threw std::exception: "
1350 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1351 (
true, std::runtime_error,
"At end of allocateIndices, "
1352 "checkInternalState threw an exception "
1353 "not a subclass of std::exception.");
1357 std::ostringstream os;
1358 os << *prefix <<
"Done" << endl;
1359 std::cerr << os.str();
1363 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1364 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1365 local_inds_dualv_type::t_host::const_type
1369 if (rowinfo.allocSize == 0 || lclIndsUnpacked_wdv.extent(0) == 0)
1370 return typename local_inds_dualv_type::t_host::const_type ();
1372 return lclIndsUnpacked_wdv.getHostSubview(rowinfo.offset1D,
1377 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1379 local_inds_dualv_type::t_host
1383 if (rowinfo.allocSize == 0 || lclIndsUnpacked_wdv.extent(0) == 0)
1384 return typename local_inds_dualv_type::t_host ();
1386 return lclIndsUnpacked_wdv.getHostSubview(rowinfo.offset1D,
1391 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1393 global_inds_dualv_type::t_host::const_type
1397 if (rowinfo.allocSize == 0 || gblInds_wdv.extent(0) == 0)
1398 return typename global_inds_dualv_type::t_host::const_type ();
1400 return gblInds_wdv.getHostSubview(rowinfo.offset1D,
1405 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1407 local_inds_dualv_type::t_dev::const_type
1411 if (rowinfo.allocSize == 0 || lclIndsUnpacked_wdv.extent(0) == 0)
1412 return typename local_inds_dualv_type::t_dev::const_type ();
1414 return lclIndsUnpacked_wdv.getDeviceSubview(rowinfo.offset1D,
1419 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1421 global_inds_dualv_type::t_dev::const_type
1425 if (rowinfo.allocSize == 0 || gblInds_wdv.extent(0) == 0)
1426 return typename global_inds_dualv_type::t_dev::const_type ();
1428 return gblInds_wdv.getDeviceSubview(rowinfo.offset1D,
1434 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1439 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1441 if (this->rowMap_.is_null () || ! this->rowMap_->isNodeLocalElement (myRow)) {
1442 ret.localRow = STINV;
1445 ret.offset1D = STINV;
1449 ret.localRow =
static_cast<size_t> (myRow);
1450 if (this->indicesAreAllocated ()) {
1451 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
1453 if (rowPtrsUnpacked_host.extent (0) == 0) {
1458 ret.offset1D = rowPtrsUnpacked_host(myRow);
1459 ret.allocSize = rowPtrsUnpacked_host(myRow+1) - rowPtrsUnpacked_host(myRow);
1462 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
1464 this->k_numRowEntries_(myRow);
1470 ret.allocSize = (this->k_numAllocPerRow_.extent (0) != 0) ?
1471 this->k_numAllocPerRow_(myRow) :
1472 this->numAllocForAllRows_;
1474 ret.offset1D = STINV;
1481 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1486 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1488 if (this->rowMap_.is_null ()) {
1489 ret.localRow = STINV;
1492 ret.offset1D = STINV;
1495 const LocalOrdinal myRow = this->rowMap_->getLocalElement (gblRow);
1496 if (myRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid ()) {
1497 ret.localRow = STINV;
1500 ret.offset1D = STINV;
1504 ret.localRow =
static_cast<size_t> (myRow);
1505 if (this->indicesAreAllocated ()) {
1509 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
1510 if (rowPtrsUnpacked_host.extent (0) == 0) {
1515 ret.offset1D = rowPtrsUnpacked_host(myRow);
1516 ret.allocSize = rowPtrsUnpacked_host(myRow+1) - rowPtrsUnpacked_host(myRow);
1519 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
1521 this->k_numRowEntries_(myRow);
1527 ret.allocSize = (this->k_numAllocPerRow_.extent (0) != 0) ?
1528 this->k_numAllocPerRow_(myRow) :
1529 this->numAllocForAllRows_;
1531 ret.offset1D = STINV;
1538 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1543 using Teuchos::OrdinalTraits;
1544 typedef LocalOrdinal LO;
1545 typedef GlobalOrdinal GO;
1551 static_assert (
sizeof (GlobalOrdinal) >=
sizeof (LocalOrdinal),
1552 "Tpetra::CrsGraph: sizeof(GlobalOrdinal) must be >= sizeof(LocalOrdinal).");
1555 static_assert (
sizeof (
size_t) >=
sizeof (LocalOrdinal),
1556 "Tpetra::CrsGraph: sizeof(size_t) must be >= sizeof(LocalOrdinal).");
1557 static_assert (
sizeof(GST) >=
sizeof(
size_t),
1558 "Tpetra::CrsGraph: sizeof(Tpetra::global_size_t) must be >= sizeof(size_t).");
1566 const char msg[] =
"Tpetra::CrsGraph: Object cannot be created with the "
1567 "given template arguments: size assumptions are not valid.";
1568 TEUCHOS_TEST_FOR_EXCEPTION(
1569 static_cast<size_t> (Teuchos::OrdinalTraits<LO>::max ()) > Teuchos::OrdinalTraits<size_t>::max (),
1570 std::runtime_error, msg);
1571 TEUCHOS_TEST_FOR_EXCEPTION(
1572 static_cast<GST> (Teuchos::OrdinalTraits<LO>::max ()) > static_cast<GST> (Teuchos::OrdinalTraits<GO>::max ()),
1573 std::runtime_error, msg);
1574 TEUCHOS_TEST_FOR_EXCEPTION(
1575 static_cast<size_t> (Teuchos::OrdinalTraits<GO>::max ()) > Teuchos::OrdinalTraits<GST>::max(),
1576 std::runtime_error, msg);
1577 TEUCHOS_TEST_FOR_EXCEPTION(
1578 Teuchos::OrdinalTraits<size_t>::max () > Teuchos::OrdinalTraits<GST>::max (),
1579 std::runtime_error, msg);
1583 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1587 const SLocalGlobalViews &newInds,
1588 const ELocalGlobal lg,
1589 const ELocalGlobal I)
1591 using Teuchos::ArrayView;
1592 typedef LocalOrdinal LO;
1593 typedef GlobalOrdinal GO;
1594 const char tfecfFuncName[] =
"insertIndices: ";
1596 size_t oldNumEnt = 0;
1598 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1599 (lg != GlobalIndices && lg != LocalIndices, std::invalid_argument,
1600 "lg must be either GlobalIndices or LocalIndices.");
1601 oldNumEnt = this->getNumEntriesInLocalRow (rowinfo.localRow);
1604 size_t numNewInds = 0;
1605 if (lg == GlobalIndices) {
1606 ArrayView<const GO> new_ginds = newInds.ginds;
1607 numNewInds = new_ginds.size();
1608 if (I == GlobalIndices) {
1609 auto gind_view = gblInds_wdv.getHostView(Access::ReadWrite);
1611 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1612 (static_cast<size_t> (gind_view.size ()) <
1613 rowinfo.numEntries + numNewInds, std::logic_error,
1614 "gind_view.size() = " << gind_view.size ()
1615 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1616 <<
") + numNewInds (= " << numNewInds <<
").");
1618 GO*
const gblColInds_out = gind_view.data () + rowinfo.offset1D
1619 + rowinfo.numEntries;
1620 for (
size_t k = 0; k < numNewInds; ++k) {
1621 gblColInds_out[k] = new_ginds[k];
1624 else if (I == LocalIndices) {
1625 auto lind_view = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1627 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1628 (static_cast<size_t> (lind_view.size ()) <
1629 rowinfo.numEntries + numNewInds, std::logic_error,
1630 "lind_view.size() = " << lind_view.size ()
1631 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1632 <<
") + numNewInds (= " << numNewInds <<
").");
1634 LO*
const lclColInds_out = lind_view.data () + rowinfo.offset1D
1635 + rowinfo.numEntries;
1636 for (
size_t k = 0; k < numNewInds; ++k) {
1637 lclColInds_out[k] = colMap_->getLocalElement (new_ginds[k]);
1641 else if (lg == LocalIndices) {
1642 ArrayView<const LO> new_linds = newInds.linds;
1643 numNewInds = new_linds.size();
1644 if (I == LocalIndices) {
1645 auto lind_view = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1647 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1648 (static_cast<size_t> (lind_view.size ()) <
1649 rowinfo.numEntries + numNewInds, std::logic_error,
1650 "lind_view.size() = " << lind_view.size ()
1651 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1652 <<
") + numNewInds (= " << numNewInds <<
").");
1654 LO*
const lclColInds_out = lind_view.data () + rowinfo.offset1D
1655 + rowinfo.numEntries;
1656 for (
size_t k = 0; k < numNewInds; ++k) {
1657 lclColInds_out[k] = new_linds[k];
1660 else if (I == GlobalIndices) {
1661 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1662 (
true, std::logic_error,
"The case where the input indices are local "
1663 "and the indices to write are global (lg=LocalIndices, I="
1664 "GlobalIndices) is not implemented, because it does not make sense."
1665 << std::endl <<
"If you have correct local column indices, that "
1666 "means the graph has a column Map. In that case, you should be "
1667 "storing local indices.");
1671 rowinfo.numEntries += numNewInds;
1672 this->k_numRowEntries_(rowinfo.localRow) += numNewInds;
1673 this->setLocallyModified ();
1676 const size_t chkNewNumEnt =
1677 this->getNumEntriesInLocalRow (rowinfo.localRow);
1678 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1679 (chkNewNumEnt != oldNumEnt + numNewInds, std::logic_error,
1680 "chkNewNumEnt = " << chkNewNumEnt
1681 <<
" != oldNumEnt (= " << oldNumEnt
1682 <<
") + numNewInds (= " << numNewInds <<
").");
1688 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1692 const GlobalOrdinal inputGblColInds[],
1693 const size_t numInputInds)
1695 return this->insertGlobalIndicesImpl (this->getRowInfo (lclRow),
1696 inputGblColInds, numInputInds);
1699 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1703 const GlobalOrdinal inputGblColInds[],
1704 const size_t numInputInds,
1705 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
1709 using Kokkos::subview;
1710 using Kokkos::MemoryUnmanaged;
1711 using Teuchos::ArrayView;
1712 using LO = LocalOrdinal;
1713 using GO = GlobalOrdinal;
1714 const char tfecfFuncName[] =
"insertGlobalIndicesImpl: ";
1715 const LO lclRow =
static_cast<LO
> (rowInfo.localRow);
1717 auto numEntries = rowInfo.numEntries;
1718 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1719 inp_view_type inputInds(inputGblColInds, numInputInds);
1722 auto gblIndsHostView = this->gblInds_wdv.getHostView(Access::ReadWrite);
1725 numEntries, inputInds, fun);
1728 const bool insertFailed =
1729 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1731 constexpr
size_t ONE (1);
1732 const int myRank = this->getComm()->getRank();
1733 std::ostringstream os;
1735 os <<
"Proc " << myRank <<
": Not enough capacity to insert "
1737 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1738 <<
" into local row " << lclRow <<
", which currently has "
1739 << rowInfo.numEntries
1740 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1741 <<
" and total allocation size " << rowInfo.allocSize
1743 const size_t maxNumToPrint =
1745 ArrayView<const GO> inputGblColIndsView(inputGblColInds,
1748 "column indices", maxNumToPrint);
1750 auto curGblColInds = getGlobalIndsViewHost(rowInfo);
1751 ArrayView<const GO> curGblColIndsView(curGblColInds.data(),
1752 rowInfo.numEntries);
1754 "column indices", maxNumToPrint);
1755 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1756 (
true, std::runtime_error, os.str());
1759 this->k_numRowEntries_(lclRow) += numInserted;
1761 this->setLocallyModified();
1766 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1770 const Teuchos::ArrayView<const LocalOrdinal>& indices,
1771 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
1773 using Kokkos::MemoryUnmanaged;
1774 using Kokkos::subview;
1776 using LO = LocalOrdinal;
1777 const char tfecfFuncName[] =
"insertLocallIndicesImpl: ";
1779 const RowInfo rowInfo = this->getRowInfo(myRow);
1781 size_t numNewInds = 0;
1782 size_t newNumEntries = 0;
1784 auto numEntries = rowInfo.numEntries;
1786 using inp_view_type = View<const LO*, Kokkos::HostSpace, MemoryUnmanaged>;
1787 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1788 size_t numInserted = 0;
1790 auto lclInds = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1792 numEntries, inputInds, fun);
1795 const bool insertFailed =
1796 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1798 constexpr
size_t ONE (1);
1799 const size_t numInputInds(indices.size());
1800 const int myRank = this->getComm()->getRank();
1801 std::ostringstream os;
1802 os <<
"On MPI Process " << myRank <<
": Not enough capacity to "
1803 "insert " << numInputInds
1804 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1805 <<
" into local row " << myRow <<
", which currently has "
1806 << rowInfo.numEntries
1807 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1808 <<
" and total allocation size " << rowInfo.allocSize <<
".";
1809 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1810 (
true, std::runtime_error, os.str());
1812 numNewInds = numInserted;
1813 newNumEntries = rowInfo.numEntries + numNewInds;
1815 this->k_numRowEntries_(myRow) += numNewInds;
1816 this->setLocallyModified ();
1819 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow (myRow);
1820 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1821 (chkNewNumEntries != newNumEntries, std::logic_error,
1822 "getNumEntriesInLocalRow(" << myRow <<
") = " << chkNewNumEntries
1823 <<
" != newNumEntries = " << newNumEntries
1824 <<
". Please report this bug to the Tpetra developers.");
1828 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1832 const Teuchos::ArrayView<const GlobalOrdinal>& indices,
1833 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
const
1835 using GO = GlobalOrdinal;
1837 using Kokkos::MemoryUnmanaged;
1838 auto invalidCount = Teuchos::OrdinalTraits<size_t>::invalid();
1840 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1841 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1843 size_t numFound = 0;
1844 LocalOrdinal lclRow = rowInfo.localRow;
1845 if (this->isLocallyIndexed())
1847 if (this->colMap_.is_null())
1848 return invalidCount;
1849 const auto& colMap = *(this->colMap_);
1850 auto map = [&](GO
const gblInd){
return colMap.getLocalElement(gblInd);};
1853 lclIndsUnpacked_wdv.getHostView(Access::ReadOnly), inputInds, map, fun);
1855 else if (this->isGloballyIndexed())
1859 gblInds_wdv.getHostView(Access::ReadOnly), inputInds, fun);
1865 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1872 const size_t origNumEnt = rowInfo.numEntries;
1873 if (origNumEnt != Tpetra::Details::OrdinalTraits<size_t>::invalid () &&
1875 auto lclColInds = this->getLocalIndsViewHostNonConst (rowInfo);
1877 LocalOrdinal*
const lclColIndsRaw = lclColInds.data ();
1879 std::sort (lclColIndsRaw, lclColIndsRaw + origNumEnt);
1883 LocalOrdinal*
const beg = lclColIndsRaw;
1884 LocalOrdinal*
const end = beg + rowInfo.numEntries;
1885 LocalOrdinal*
const newend = std::unique (beg, end);
1886 const size_t newNumEnt = newend - beg;
1889 this->k_numRowEntries_(rowInfo.localRow) = newNumEnt;
1890 return origNumEnt - newNumEnt;
1893 return static_cast<size_t> (0);
1897 return static_cast<size_t> (0);
1902 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1906 const Teuchos::RCP<const map_type>& rangeMap)
1909 if (domainMap_ != domainMap) {
1910 domainMap_ = domainMap;
1911 importer_ = Teuchos::null;
1913 if (rangeMap_ != rangeMap) {
1914 rangeMap_ = rangeMap;
1915 exporter_ = Teuchos::null;
1920 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1925 const auto INV = Teuchos::OrdinalTraits<global_size_t>::invalid();
1927 globalNumEntries_ = INV;
1928 globalMaxNumRowEntries_ = INV;
1929 haveGlobalConstants_ =
false;
1933 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1940 const char tfecfFuncName[] =
"checkInternalState: ";
1941 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1943 std::unique_ptr<std::string> prefix;
1945 prefix = this->createPrefix(
"CrsGraph",
"checkInternalState");
1946 std::ostringstream os;
1947 os << *prefix <<
"Start" << endl;
1948 std::cerr << os.str();
1951 const global_size_t GSTI = Teuchos::OrdinalTraits<global_size_t>::invalid ();
1957 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1958 (this->rowMap_.is_null (), std::logic_error,
1959 "Row Map is null." << suffix);
1962 const LocalOrdinal lclNumRows =
1963 static_cast<LocalOrdinal
> (this->getLocalNumRows ());
1965 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1966 (this->isFillActive () == this->isFillComplete (), std::logic_error,
1967 "Graph cannot be both fill active and fill complete." << suffix);
1968 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1969 (this->isFillComplete () &&
1970 (this->colMap_.is_null () ||
1971 this->rangeMap_.is_null () ||
1972 this->domainMap_.is_null ()),
1974 "Graph is full complete, but at least one of {column, range, domain} "
1975 "Map is null." << suffix);
1976 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1977 (this->isStorageOptimized () && ! this->indicesAreAllocated (),
1978 std::logic_error,
"Storage is optimized, but indices are not "
1979 "allocated, not even trivially." << suffix);
1981 size_t nodeAllocSize = 0;
1983 nodeAllocSize = this->getLocalAllocationSize ();
1985 catch (std::logic_error& e) {
1986 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1987 (
true, std::runtime_error,
"getLocalAllocationSize threw "
1988 "std::logic_error: " << e.what ());
1990 catch (std::exception& e) {
1991 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1992 (
true, std::runtime_error,
"getLocalAllocationSize threw an "
1993 "std::exception: " << e.what ());
1996 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1997 (
true, std::runtime_error,
"getLocalAllocationSize threw an exception "
1998 "not a subclass of std::exception.");
2001 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2002 (this->isStorageOptimized () &&
2003 nodeAllocSize != this->getLocalNumEntries (),
2004 std::logic_error,
"Storage is optimized, but "
2005 "this->getLocalAllocationSize() = " << nodeAllocSize
2006 <<
" != this->getLocalNumEntries() = " << this->getLocalNumEntries ()
2008 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2009 (! this->haveGlobalConstants_ &&
2010 (this->globalNumEntries_ != GSTI ||
2011 this->globalMaxNumRowEntries_ != GSTI),
2012 std::logic_error,
"Graph claims not to have global constants, but "
2013 "some of the global constants are not marked as invalid." << suffix);
2014 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2015 (this->haveGlobalConstants_ &&
2016 (this->globalNumEntries_ == GSTI ||
2017 this->globalMaxNumRowEntries_ == GSTI),
2018 std::logic_error,
"Graph claims to have global constants, but "
2019 "some of them are marked as invalid." << suffix);
2020 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2021 (this->haveGlobalConstants_ &&
2022 (this->globalNumEntries_ < this->getLocalNumEntries () ||
2023 this->globalMaxNumRowEntries_ < this->nodeMaxNumRowEntries_),
2024 std::logic_error,
"Graph claims to have global constants, and "
2025 "all of the values of the global constants are valid, but "
2026 "some of the local constants are greater than "
2027 "their corresponding global constants." << suffix);
2028 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2029 (this->indicesAreAllocated () &&
2030 (this->numAllocForAllRows_ != 0 ||
2031 this->k_numAllocPerRow_.extent (0) != 0),
2032 std::logic_error,
"The graph claims that its indices are allocated, but "
2033 "either numAllocForAllRows_ (= " << this->numAllocForAllRows_ <<
") is "
2034 "nonzero, or k_numAllocPerRow_ has nonzero dimension. In other words, "
2035 "the graph is supposed to release its \"allocation specifications\" "
2036 "when it allocates its indices." << suffix);
2037 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
2038 auto rowPtrsUnpacked_dev = this->getRowPtrsUnpackedDevice();
2039 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2040 (rowPtrsUnpacked_host.extent(0) != rowPtrsUnpacked_dev.extent(0),
2041 std::logic_error,
"The host and device views of k_rowPtrs_ have "
2042 "different sizes; rowPtrsUnpacked_host_ has size "
2043 << rowPtrsUnpacked_host.extent(0)
2044 <<
", but rowPtrsUnpacked_dev_ has size "
2045 << rowPtrsUnpacked_dev.extent(0)
2047 if (isGloballyIndexed() && rowPtrsUnpacked_host.extent(0) != 0) {
2048 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2049 (
size_t(rowPtrsUnpacked_host.extent(0)) !=
size_t(lclNumRows + 1),
2050 std::logic_error,
"The graph is globally indexed and "
2051 "k_rowPtrs has nonzero size " << rowPtrsUnpacked_host.extent(0)
2052 <<
", but that size does not equal lclNumRows+1 = "
2053 << (lclNumRows+1) <<
"." << suffix);
2054 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2055 (rowPtrsUnpacked_host(lclNumRows) !=
size_t(gblInds_wdv.extent(0)),
2056 std::logic_error,
"The graph is globally indexed and "
2057 "k_rowPtrs_ has nonzero size " << rowPtrsUnpacked_host.extent(0)
2058 <<
", but k_rowPtrs_(lclNumRows=" << lclNumRows <<
")="
2059 << rowPtrsUnpacked_host(lclNumRows)
2060 <<
" != gblInds_wdv.extent(0)="
2061 << gblInds_wdv.extent(0) <<
"." << suffix);
2063 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2064 (this->isLocallyIndexed () &&
2065 rowPtrsUnpacked_host.extent (0) != 0 &&
2066 (
static_cast<size_t> (rowPtrsUnpacked_host.extent (0)) !=
2067 static_cast<size_t> (lclNumRows + 1) ||
2068 rowPtrsUnpacked_host(lclNumRows) !=
2069 static_cast<size_t> (this->lclIndsUnpacked_wdv.extent (0))),
2070 std::logic_error,
"If k_rowPtrs_ has nonzero size and "
2071 "the graph is locally indexed, then "
2072 "k_rowPtrs_ must have N+1 rows, and "
2073 "k_rowPtrs_(N) must equal lclIndsUnpacked_wdv.extent(0)." << suffix);
2075 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2076 (this->indicesAreAllocated () &&
2077 nodeAllocSize > 0 &&
2078 this->lclIndsUnpacked_wdv.extent (0) == 0 &&
2079 this->gblInds_wdv.extent (0) == 0,
2080 std::logic_error,
"Graph is allocated nontrivially, but "
2081 "but 1-D allocations are not present." << suffix);
2083 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2084 (! this->indicesAreAllocated () &&
2085 ((rowPtrsUnpacked_host.extent (0) != 0 ||
2086 this->k_numRowEntries_.extent (0) != 0) ||
2087 this->lclIndsUnpacked_wdv.extent (0) != 0 ||
2088 this->gblInds_wdv.extent (0) != 0),
2089 std::logic_error,
"If indices are not allocated, "
2090 "then none of the buffers should be." << suffix);
2094 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2095 ((this->indicesAreLocal_ || this->indicesAreGlobal_) &&
2096 ! this->indicesAreAllocated_,
2097 std::logic_error,
"Indices may be local or global only if they are "
2098 "allocated." << suffix);
2099 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2100 (this->indicesAreLocal_ && this->indicesAreGlobal_,
2101 std::logic_error,
"Indices may not be both local and global." << suffix);
2102 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2103 (indicesAreLocal_ && gblInds_wdv.extent (0) != 0,
2104 std::logic_error,
"Indices are local, but "
2105 "gblInds_wdv.extent(0) (= " << gblInds_wdv.extent (0)
2106 <<
") != 0. In other words, if indices are local, then "
2107 "allocations of global indices should not be present."
2109 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2110 (indicesAreGlobal_ && lclIndsUnpacked_wdv.extent (0) != 0,
2111 std::logic_error,
"Indices are global, but "
2112 "lclIndsUnpacked_wdv.extent(0) (= " << lclIndsUnpacked_wdv.extent(0)
2113 <<
") != 0. In other words, if indices are global, "
2114 "then allocations for local indices should not be present."
2116 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2117 (indicesAreLocal_ && nodeAllocSize > 0 &&
2118 lclIndsUnpacked_wdv.extent (0) == 0 && getLocalNumRows () > 0,
2119 std::logic_error,
"Indices are local and "
2120 "getLocalAllocationSize() = " << nodeAllocSize <<
" > 0, but "
2121 "lclIndsUnpacked_wdv.extent(0) = 0 and getLocalNumRows() = "
2122 << getLocalNumRows () <<
" > 0." << suffix);
2123 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2124 (indicesAreGlobal_ && nodeAllocSize > 0 &&
2125 gblInds_wdv.extent (0) == 0 && getLocalNumRows () > 0,
2126 std::logic_error,
"Indices are global and "
2127 "getLocalAllocationSize() = " << nodeAllocSize <<
" > 0, but "
2128 "gblInds_wdv.extent(0) = 0 and getLocalNumRows() = "
2129 << getLocalNumRows () <<
" > 0." << suffix);
2131 if (this->indicesAreAllocated () &&
2132 rowPtrsUnpacked_host.extent (0) != 0) {
2133 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2134 (static_cast<size_t> (rowPtrsUnpacked_host.extent (0)) !=
2135 this->getLocalNumRows () + 1,
2136 std::logic_error,
"Indices are allocated and "
2137 "k_rowPtrs_ has nonzero length, but rowPtrsUnpacked_host_.extent(0) = "
2138 << rowPtrsUnpacked_host.extent (0) <<
" != getLocalNumRows()+1 = "
2139 << (this->getLocalNumRows () + 1) <<
"." << suffix);
2140 const size_t actualNumAllocated =
2141 rowPtrsUnpacked_host(this->getLocalNumRows());
2142 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2143 (this->isLocallyIndexed () &&
2144 static_cast<size_t> (this->lclIndsUnpacked_wdv.extent (0)) != actualNumAllocated,
2145 std::logic_error,
"Graph is locally indexed, indices are "
2146 "are allocated, and k_rowPtrs_ has nonzero length, but "
2147 "lclIndsUnpacked_wdv.extent(0) = " << this->lclIndsUnpacked_wdv.extent (0)
2148 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2149 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2150 (this->isGloballyIndexed () &&
2151 static_cast<size_t> (this->gblInds_wdv.extent (0)) != actualNumAllocated,
2152 std::logic_error,
"Graph is globally indexed, indices "
2153 "are allocated, and k_rowPtrs_ has nonzero length, but "
2154 "gblInds_wdv.extent(0) = " << this->gblInds_wdv.extent (0)
2155 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2159 std::ostringstream os;
2160 os << *prefix <<
"Done" << endl;
2161 std::cerr << os.str();
2167 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2172 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (globalRow);
2173 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2174 return Teuchos::OrdinalTraits<size_t>::invalid ();
2177 return rowInfo.numEntries;
2182 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2187 const RowInfo rowInfo = this->getRowInfo (localRow);
2188 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2189 return Teuchos::OrdinalTraits<size_t>::invalid ();
2192 return rowInfo.numEntries;
2197 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2202 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (globalRow);
2203 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2204 return Teuchos::OrdinalTraits<size_t>::invalid ();
2207 return rowInfo.allocSize;
2212 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2217 const RowInfo rowInfo = this->getRowInfo (localRow);
2218 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2219 return Teuchos::OrdinalTraits<size_t>::invalid ();
2222 return rowInfo.allocSize;
2227 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2228 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_host_view_type
2232 return getRowPtrsPackedHost();
2235 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2236 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_device_view_type
2240 return getRowPtrsPackedDevice();
2244 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2245 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::local_inds_host_view_type
2249 return lclIndsPacked_wdv.getHostView(Access::ReadOnly);
2252 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2257 return lclIndsPacked_wdv.getDeviceView(Access::ReadOnly);
2260 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2264 nonconst_local_inds_host_view_type & indices,
2265 size_t& numEntries)
const
2267 using Teuchos::ArrayView;
2268 const char tfecfFuncName[] =
"getLocalRowCopy: ";
2270 TEUCHOS_TEST_FOR_EXCEPTION(
2271 isGloballyIndexed () && ! hasColMap (), std::runtime_error,
2272 "Tpetra::CrsGraph::getLocalRowCopy: The graph is globally indexed and "
2273 "does not have a column Map yet. That means we don't have local indices "
2274 "for columns yet, so it doesn't make sense to call this method. If the "
2275 "graph doesn't have a column Map yet, you should call fillComplete on "
2280 const RowInfo rowinfo = this->getRowInfo (localRow);
2282 const size_t theNumEntries = rowinfo.numEntries;
2283 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2284 (static_cast<size_t> (indices.size ()) < theNumEntries,std::runtime_error,
2285 "Specified storage (size==" << indices.size () <<
") does not suffice "
2286 "to hold all " << theNumEntries <<
" entry/ies for this row.");
2287 numEntries = theNumEntries;
2289 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
2290 if (isLocallyIndexed ()) {
2291 auto lclInds = getLocalIndsViewHost(rowinfo);
2292 for (
size_t j = 0; j < theNumEntries; ++j) {
2293 indices[j] = lclInds(j);
2296 else if (isGloballyIndexed ()) {
2297 auto gblInds = getGlobalIndsViewHost(rowinfo);
2298 for (
size_t j = 0; j < theNumEntries; ++j) {
2299 indices[j] = colMap_->getLocalElement (gblInds(j));
2306 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2310 nonconst_global_inds_host_view_type &indices,
2311 size_t& numEntries)
const
2313 using Teuchos::ArrayView;
2314 const char tfecfFuncName[] =
"getGlobalRowCopy: ";
2318 const RowInfo rowinfo = getRowInfoFromGlobalRowIndex (globalRow);
2319 const size_t theNumEntries = rowinfo.numEntries;
2320 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2321 static_cast<size_t> (indices.size ()) < theNumEntries, std::runtime_error,
2322 "Specified storage (size==" << indices.size () <<
") does not suffice "
2323 "to hold all " << theNumEntries <<
" entry/ies for this row.");
2324 numEntries = theNumEntries;
2326 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
2327 if (isLocallyIndexed ()) {
2328 auto lclInds = getLocalIndsViewHost(rowinfo);
2329 for (
size_t j = 0; j < theNumEntries; ++j) {
2330 indices[j] = colMap_->getGlobalElement (lclInds(j));
2333 else if (isGloballyIndexed ()) {
2334 auto gblInds = getGlobalIndsViewHost(rowinfo);
2335 for (
size_t j = 0; j < theNumEntries; ++j) {
2336 indices[j] = gblInds(j);
2343 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2347 const LocalOrdinal localRow,
2348 local_inds_host_view_type &indices)
const
2350 const char tfecfFuncName[] =
"getLocalRowView: ";
2352 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2353 (isGloballyIndexed (), std::runtime_error,
"The graph's indices are "
2354 "currently stored as global indices, so we cannot return a view with "
2355 "local column indices, whether or not the graph has a column Map. If "
2356 "the graph _does_ have a column Map, use getLocalRowCopy() instead.");
2358 const RowInfo rowInfo = getRowInfo (localRow);
2359 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
2360 rowInfo.numEntries > 0) {
2361 indices = lclIndsUnpacked_wdv.getHostSubview(rowInfo.offset1D,
2368 indices = local_inds_host_view_type();
2372 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2373 (static_cast<size_t> (indices.size ()) !=
2374 getNumEntriesInLocalRow (localRow), std::logic_error,
"indices.size() "
2375 "= " << indices.extent(0) <<
" != getNumEntriesInLocalRow(localRow=" <<
2376 localRow <<
") = " << getNumEntriesInLocalRow(localRow) <<
2377 ". Please report this bug to the Tpetra developers.");
2382 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2386 const GlobalOrdinal globalRow,
2387 global_inds_host_view_type &indices)
const
2389 const char tfecfFuncName[] =
"getGlobalRowView: ";
2391 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2392 (isLocallyIndexed (), std::runtime_error,
"The graph's indices are "
2393 "currently stored as local indices, so we cannot return a view with "
2394 "global column indices. Use getGlobalRowCopy() instead.");
2398 const RowInfo rowInfo = getRowInfoFromGlobalRowIndex (globalRow);
2399 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
2400 rowInfo.numEntries > 0) {
2401 indices = gblInds_wdv.getHostSubview(rowInfo.offset1D,
2406 indices =
typename global_inds_dualv_type::t_host::const_type();
2409 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2410 (static_cast<size_t> (indices.size ()) !=
2411 getNumEntriesInGlobalRow (globalRow),
2412 std::logic_error,
"indices.size() = " << indices.extent(0)
2413 <<
" != getNumEntriesInGlobalRow(globalRow=" << globalRow <<
") = "
2414 << getNumEntriesInGlobalRow (globalRow)
2415 <<
". Please report this bug to the Tpetra developers.");
2420 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2424 const Teuchos::ArrayView<const LocalOrdinal>& indices)
2426 const char tfecfFuncName[] =
"insertLocalIndices: ";
2428 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2429 (! isFillActive (), std::runtime_error,
"Fill must be active.");
2430 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2431 (isGloballyIndexed (), std::runtime_error,
2432 "Graph indices are global; use insertGlobalIndices().");
2433 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2434 (! hasColMap (), std::runtime_error,
2435 "Cannot insert local indices without a column Map.");
2436 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2437 (! rowMap_->isNodeLocalElement (localRow), std::runtime_error,
2438 "Local row index " << localRow <<
" is not in the row Map "
2439 "on the calling process.");
2440 if (! indicesAreAllocated ()) {
2441 allocateIndices (LocalIndices, verbose_);
2450 using Teuchos::Array;
2451 using Teuchos::toString;
2453 typedef typename Teuchos::ArrayView<const LocalOrdinal>::size_type size_type;
2456 Array<LocalOrdinal> badColInds;
2457 bool allInColMap =
true;
2458 for (size_type k = 0; k < indices.size (); ++k) {
2460 allInColMap =
false;
2461 badColInds.push_back (indices[k]);
2464 if (! allInColMap) {
2465 std::ostringstream os;
2466 os <<
"Tpetra::CrsGraph::insertLocalIndices: You attempted to insert "
2467 "entries in owned row " << localRow <<
", at the following column "
2468 "indices: " << toString (indices) <<
"." << endl;
2469 os <<
"Of those, the following indices are not in the column Map on "
2470 "this process: " << toString (badColInds) <<
"." << endl <<
"Since "
2471 "the graph has a column Map already, it is invalid to insert entries "
2472 "at those locations.";
2473 TEUCHOS_TEST_FOR_EXCEPTION(! allInColMap, std::invalid_argument, os.str ());
2478 insertLocalIndicesImpl (localRow, indices);
2481 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2482 (! indicesAreAllocated () || ! isLocallyIndexed (), std::logic_error,
2483 "At the end of insertLocalIndices, ! indicesAreAllocated() || "
2484 "! isLocallyIndexed() is true. Please report this bug to the "
2485 "Tpetra developers.");
2489 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2493 const LocalOrdinal numEnt,
2494 const LocalOrdinal inds[])
2496 Teuchos::ArrayView<const LocalOrdinal> indsT (inds, numEnt);
2497 this->insertLocalIndices (localRow, indsT);
2501 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2505 const LocalOrdinal numInputInds,
2506 const GlobalOrdinal inputGblColInds[])
2508 typedef LocalOrdinal LO;
2509 const char tfecfFuncName[] =
"insertGlobalIndices: ";
2511 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2512 (this->isLocallyIndexed (), std::runtime_error,
2513 "graph indices are local; use insertLocalIndices().");
2518 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2519 (! this->isFillActive (), std::runtime_error,
2520 "You are not allowed to call this method if fill is not active. "
2521 "If fillComplete has been called, you must first call resumeFill "
2522 "before you may insert indices.");
2523 if (! indicesAreAllocated ()) {
2524 allocateIndices (GlobalIndices, verbose_);
2526 const LO lclRow = this->rowMap_->getLocalElement (gblRow);
2527 if (lclRow != Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
2529 if (this->hasColMap ()) {
2531 const map_type& colMap = * (this->colMap_);
2536 std::vector<GlobalOrdinal> badColInds;
2537 bool allInColMap =
true;
2538 for (LO k = 0; k < numInputInds; ++k) {
2540 allInColMap =
false;
2541 badColInds.push_back (inputGblColInds[k]);
2544 if (! allInColMap) {
2545 std::ostringstream os;
2546 os <<
"You attempted to insert entries in owned row " << gblRow
2547 <<
", at the following column indices: [";
2548 for (LO k = 0; k < numInputInds; ++k) {
2549 os << inputGblColInds[k];
2550 if (k + static_cast<LO> (1) < numInputInds) {
2554 os <<
"]." << endl <<
"Of those, the following indices are not in "
2555 "the column Map on this process: [";
2556 for (
size_t k = 0; k < badColInds.size (); ++k) {
2557 os << badColInds[k];
2558 if (k +
size_t (1) < badColInds.size ()) {
2562 os <<
"]." << endl <<
"Since the matrix has a column Map already, "
2563 "it is invalid to insert entries at those locations.";
2564 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2565 (
true, std::invalid_argument, os.str ());
2569 this->insertGlobalIndicesImpl (lclRow, inputGblColInds, numInputInds);
2572 this->insertGlobalIndicesIntoNonownedRows (gblRow, inputGblColInds,
2578 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2582 const Teuchos::ArrayView<const GlobalOrdinal>& inputGblColInds)
2584 this->insertGlobalIndices (gblRow, inputGblColInds.size (),
2585 inputGblColInds.getRawPtr ());
2589 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2593 const GlobalOrdinal gblColInds[],
2594 const LocalOrdinal numGblColInds)
2596 typedef LocalOrdinal LO;
2597 typedef GlobalOrdinal GO;
2598 const char tfecfFuncName[] =
"insertGlobalIndicesFiltered: ";
2600 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2601 (this->isLocallyIndexed (), std::runtime_error,
2602 "Graph indices are local; use insertLocalIndices().");
2607 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2608 (! this->isFillActive (), std::runtime_error,
2609 "You are not allowed to call this method if fill is not active. "
2610 "If fillComplete has been called, you must first call resumeFill "
2611 "before you may insert indices.");
2612 if (! indicesAreAllocated ()) {
2613 allocateIndices (GlobalIndices, verbose_);
2616 Teuchos::ArrayView<const GO> gblColInds_av (gblColInds, numGblColInds);
2618 if (! colMap_.is_null ()) {
2619 const map_type& colMap = * (this->colMap_);
2622 while (curOffset < numGblColInds) {
2626 LO endOffset = curOffset;
2627 for ( ; endOffset < numGblColInds; ++endOffset) {
2629 if (lclCol == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
2636 const LO numIndInSeq = (endOffset - curOffset);
2637 if (numIndInSeq != 0) {
2638 this->insertGlobalIndicesImpl (lclRow, gblColInds + curOffset,
2644 curOffset = endOffset + 1;
2648 this->insertGlobalIndicesImpl (lclRow, gblColInds_av.getRawPtr (),
2649 gblColInds_av.size ());
2653 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2657 const GlobalOrdinal gblColInds[],
2658 const LocalOrdinal numGblColInds)
2663 std::vector<GlobalOrdinal>& nonlocalRow = this->nonlocals_[gblRow];
2664 for (LocalOrdinal k = 0; k < numGblColInds; ++k) {
2668 nonlocalRow.push_back (gblColInds[k]);
2672 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2677 const char tfecfFuncName[] =
"removeLocalIndices: ";
2678 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2679 ! isFillActive (), std::runtime_error,
"requires that fill is active.");
2680 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2681 isStorageOptimized (), std::runtime_error,
2682 "cannot remove indices after optimizeStorage() has been called.");
2683 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2684 isGloballyIndexed (), std::runtime_error,
"graph indices are global.");
2685 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2686 ! rowMap_->isNodeLocalElement (lrow), std::runtime_error,
2687 "Local row " << lrow <<
" is not in the row Map on the calling process.");
2688 if (! indicesAreAllocated ()) {
2689 allocateIndices (LocalIndices, verbose_);
2692 if (k_numRowEntries_.extent (0) != 0) {
2693 this->k_numRowEntries_(lrow) = 0;
2697 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2698 (getNumEntriesInLocalRow (lrow) != 0 ||
2699 ! indicesAreAllocated () ||
2700 ! isLocallyIndexed (), std::logic_error,
2701 "Violated stated post-conditions. Please contact Tpetra team.");
2706 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2709 setAllIndices (
const typename local_graph_device_type::row_map_type& rowPointers,
2710 const typename local_graph_device_type::entries_type::non_const_type& columnIndices)
2713 ProfilingRegion region (
"Tpetra::CrsGraph::setAllIndices");
2714 const char tfecfFuncName[] =
"setAllIndices: ";
2715 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2716 ! hasColMap () || getColMap ().is_null (), std::runtime_error,
2717 "The graph must have a column Map before you may call this method.");
2718 LocalOrdinal numLocalRows = this->getLocalNumRows ();
2720 LocalOrdinal rowPtrLen = rowPointers.size();
2721 if(numLocalRows == 0) {
2722 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2723 rowPtrLen != 0 && rowPtrLen != 1,
2724 std::runtime_error,
"Have 0 local rows, but rowPointers.size() is neither 0 nor 1.");
2727 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2728 rowPtrLen != numLocalRows + 1,
2729 std::runtime_error,
"rowPointers.size() = " << rowPtrLen <<
2730 " != this->getLocalNumRows()+1 = " << (numLocalRows + 1) <<
".");
2735 using exec_space =
typename local_graph_device_type::execution_space;
2736 int columnsOutOfBounds = 0;
2738 Kokkos::parallel_reduce(Kokkos::RangePolicy<exec_space>(0, columnIndices.extent(0)),
2739 KOKKOS_LAMBDA (
const LocalOrdinal i,
int& lOutOfBounds)
2741 if(columnIndices(i) < 0 || columnIndices(i) >= numLocalCols)
2743 }, columnsOutOfBounds);
2744 int globalColsOutOfBounds= 0;
2745 auto comm = this->getComm();
2746 Teuchos::reduceAll<int, int> (*comm, Teuchos::REDUCE_MAX, columnsOutOfBounds,
2747 Teuchos::outArg (globalColsOutOfBounds));
2748 if (globalColsOutOfBounds)
2750 std::string message;
2751 if (columnsOutOfBounds)
2754 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not all within range [0, getLocalNumCols())!\n";
2757 throw std::invalid_argument(
"CrsGraph::setAllIndices(): columnIndices are out of the valid range on at least one process.");
2761 if (debug_ && this->isSorted()) {
2764 using exec_space =
typename local_graph_device_type::execution_space;
2765 using size_type =
typename local_graph_device_type::size_type;
2766 Kokkos::parallel_reduce(Kokkos::RangePolicy<exec_space>(0, numLocalRows),
2767 KOKKOS_LAMBDA (
const LocalOrdinal i,
int& lNotSorted)
2769 size_type rowBegin = rowPointers(i);
2770 size_type rowEnd = rowPointers(i + 1);
2771 for(size_type j = rowBegin + 1; j < rowEnd; j++)
2773 if(columnIndices(j - 1) > columnIndices(j))
2780 int globalNotSorted = 0;
2781 auto comm = this->getComm();
2782 Teuchos::reduceAll<int, int> (*comm, Teuchos::REDUCE_MAX, notSorted,
2783 Teuchos::outArg (globalNotSorted));
2784 if (globalNotSorted)
2786 std::string message;
2790 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not sorted!\n";
2793 throw std::invalid_argument(
"CrsGraph::setAllIndices(): provided columnIndices are not sorted within rows on at least one process.");
2797 indicesAreAllocated_ =
true;
2798 indicesAreLocal_ =
true;
2799 indicesAreSorted_ =
true;
2800 noRedundancies_ =
true;
2802 lclIndsUnpacked_wdv = lclIndsPacked_wdv;
2803 setRowPtrs(rowPointers);
2805 set_need_sync_host_uvm_access();
2809 storageStatus_ = Details::STORAGE_1D_PACKED;
2814 numAllocForAllRows_ = 0;
2815 k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
2817 checkInternalState ();
2821 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2825 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices)
2828 typedef typename local_graph_device_type::row_map_type row_map_type;
2829 typedef typename row_map_type::array_layout layout_type;
2830 typedef typename row_map_type::non_const_value_type row_offset_type;
2831 typedef View<
size_t*, layout_type , Kokkos::HostSpace,
2832 Kokkos::MemoryUnmanaged> input_view_type;
2833 typedef typename row_map_type::non_const_type nc_row_map_type;
2835 const size_t size =
static_cast<size_t> (rowPointers.size ());
2836 constexpr
bool same = std::is_same<size_t, row_offset_type>::value;
2837 input_view_type ptr_in (rowPointers.getRawPtr (), size);
2839 nc_row_map_type ptr_rot (
"Tpetra::CrsGraph::ptr", size);
2841 if constexpr (same) {
2842 using lexecution_space =
typename device_type::execution_space;
2849 constexpr
bool inHostMemory =
2850 std::is_same<
typename row_map_type::memory_space,
2851 Kokkos::HostSpace>::value;
2862 View<size_t*, layout_type, device_type> ptr_st (
"Tpetra::CrsGraph::ptr", size);
2874 Kokkos::View<LocalOrdinal*, layout_type, device_type> k_ind =
2875 Kokkos::Compat::getKokkosViewDeepCopy<device_type> (columnIndices ());
2876 setAllIndices (ptr_rot, k_ind);
2880 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2885 using Teuchos::Comm;
2886 using Teuchos::outArg;
2889 using Teuchos::REDUCE_MAX;
2890 using Teuchos::REDUCE_MIN;
2891 using Teuchos::reduceAll;
2896 using size_type =
typename Teuchos::Array<GO>::size_type;
2897 const char tfecfFuncName[] =
"globalAssemble: ";
2899 std::unique_ptr<std::string> prefix;
2901 prefix = this->createPrefix(
"CrsGraph",
"globalAssemble");
2902 std::ostringstream os;
2903 os << *prefix <<
"Start" << endl;
2904 std::cerr << os.str();
2906 RCP<const Comm<int> > comm = getComm ();
2908 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2909 (! isFillActive (), std::runtime_error,
"Fill must be active before "
2910 "you may call this method.");
2912 const size_t myNumNonlocalRows = this->nonlocals_.size ();
2919 const int iHaveNonlocalRows = (myNumNonlocalRows == 0) ? 0 : 1;
2920 int someoneHasNonlocalRows = 0;
2921 reduceAll<int, int> (*comm, REDUCE_MAX, iHaveNonlocalRows,
2922 outArg (someoneHasNonlocalRows));
2923 if (someoneHasNonlocalRows == 0) {
2925 std::ostringstream os;
2926 os << *prefix <<
"Done: No nonlocal rows" << endl;
2927 std::cerr << os.str();
2931 else if (verbose_) {
2932 std::ostringstream os;
2933 os << *prefix <<
"At least 1 process has nonlocal rows"
2935 std::cerr << os.str();
2948 RCP<const map_type> nonlocalRowMap;
2950 Teuchos::Array<size_t> numEntPerNonlocalRow (myNumNonlocalRows);
2952 Teuchos::Array<GO> myNonlocalGblRows (myNumNonlocalRows);
2953 size_type curPos = 0;
2954 for (
auto mapIter = this->nonlocals_.begin ();
2955 mapIter != this->nonlocals_.end ();
2956 ++mapIter, ++curPos) {
2957 myNonlocalGblRows[curPos] = mapIter->first;
2958 std::vector<GO>& gblCols = mapIter->second;
2959 std::sort (gblCols.begin (), gblCols.end ());
2960 auto vecLast = std::unique (gblCols.begin (), gblCols.end ());
2961 gblCols.erase (vecLast, gblCols.end ());
2962 numEntPerNonlocalRow[curPos] = gblCols.size ();
2973 GO myMinNonlocalGblRow = std::numeric_limits<GO>::max ();
2975 auto iter = std::min_element (myNonlocalGblRows.begin (),
2976 myNonlocalGblRows.end ());
2977 if (iter != myNonlocalGblRows.end ()) {
2978 myMinNonlocalGblRow = *iter;
2981 GO gblMinNonlocalGblRow = 0;
2982 reduceAll<int, GO> (*comm, REDUCE_MIN, myMinNonlocalGblRow,
2983 outArg (gblMinNonlocalGblRow));
2984 const GO indexBase = gblMinNonlocalGblRow;
2985 const global_size_t INV = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2986 nonlocalRowMap = rcp (
new map_type (INV, myNonlocalGblRows (), indexBase, comm));
2990 std::ostringstream os;
2991 os << *prefix <<
"nonlocalRowMap->getIndexBase()="
2992 << nonlocalRowMap->getIndexBase() << endl;
2993 std::cerr << os.str();
3001 RCP<crs_graph_type> nonlocalGraph =
3002 rcp(
new crs_graph_type(nonlocalRowMap, numEntPerNonlocalRow()));
3004 size_type curPos = 0;
3005 for (
auto mapIter = this->nonlocals_.begin ();
3006 mapIter != this->nonlocals_.end ();
3007 ++mapIter, ++curPos) {
3008 const GO gblRow = mapIter->first;
3009 std::vector<GO>& gblCols = mapIter->second;
3010 const LO numEnt =
static_cast<LO
> (numEntPerNonlocalRow[curPos]);
3011 nonlocalGraph->insertGlobalIndices (gblRow, numEnt, gblCols.data ());
3015 std::ostringstream os;
3016 os << *prefix <<
"Built nonlocal graph" << endl;
3017 std::cerr << os.str();
3028 auto origRowMap = this->getRowMap ();
3029 const bool origRowMapIsOneToOne = origRowMap->isOneToOne ();
3031 if (origRowMapIsOneToOne) {
3033 std::ostringstream os;
3034 os << *prefix <<
"Original row Map is 1-to-1" << endl;
3035 std::cerr << os.str();
3037 export_type exportToOrig (nonlocalRowMap, origRowMap);
3043 std::ostringstream os;
3044 os << *prefix <<
"Original row Map is NOT 1-to-1" << endl;
3045 std::cerr << os.str();
3052 export_type exportToOneToOne (nonlocalRowMap, oneToOneRowMap);
3058 crs_graph_type oneToOneGraph (oneToOneRowMap, 0);
3062 std::ostringstream os;
3063 os << *prefix <<
"Export nonlocal graph" << endl;
3064 std::cerr << os.str();
3066 oneToOneGraph.doExport (*nonlocalGraph, exportToOneToOne,
Tpetra::INSERT);
3070 nonlocalGraph = Teuchos::null;
3073 import_type importToOrig (oneToOneRowMap, origRowMap);
3075 std::ostringstream os;
3076 os << *prefix <<
"Import nonlocal graph" << endl;
3077 std::cerr << os.str();
3086 decltype (this->nonlocals_) newNonlocals;
3087 std::swap (this->nonlocals_, newNonlocals);
3089 checkInternalState ();
3091 std::ostringstream os;
3092 os << *prefix <<
"Done" << endl;
3093 std::cerr << os.str();
3098 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3103 clearGlobalConstants();
3104 if (params != Teuchos::null) this->setParameterList (params);
3106 indicesAreSorted_ =
true;
3107 noRedundancies_ =
true;
3108 fillComplete_ =
false;
3112 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3127 Teuchos::RCP<const map_type> domMap = this->getDomainMap ();
3128 if (domMap.is_null ()) {
3129 domMap = this->getRowMap ();
3131 Teuchos::RCP<const map_type> ranMap = this->getRangeMap ();
3132 if (ranMap.is_null ()) {
3133 ranMap = this->getRowMap ();
3135 this->fillComplete (domMap, ranMap, params);
3139 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3143 const Teuchos::RCP<const map_type>& rangeMap,
3144 const Teuchos::RCP<Teuchos::ParameterList>& params)
3147 const char tfecfFuncName[] =
"fillComplete: ";
3148 const bool verbose = verbose_;
3150 std::unique_ptr<std::string> prefix;
3152 prefix = this->createPrefix(
"CrsGraph",
"fillComplete");
3153 std::ostringstream os;
3154 os << *prefix <<
"Start" << endl;
3155 std::cerr << os.str();
3158 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3159 (! isFillActive () || isFillComplete (), std::runtime_error,
3160 "Graph fill state must be active (isFillActive() "
3161 "must be true) before calling fillComplete().");
3163 const int numProcs = getComm ()->getSize ();
3171 if (! params.is_null ()) {
3172 if (params->isParameter (
"sort column map ghost gids")) {
3173 sortGhostsAssociatedWithEachProcessor_ =
3174 params->get<
bool> (
"sort column map ghost gids",
3175 sortGhostsAssociatedWithEachProcessor_);
3177 else if (params->isParameter (
"Sort column Map ghost GIDs")) {
3178 sortGhostsAssociatedWithEachProcessor_ =
3179 params->get<
bool> (
"Sort column Map ghost GIDs",
3180 sortGhostsAssociatedWithEachProcessor_);
3186 bool assertNoNonlocalInserts =
false;
3187 if (! params.is_null ()) {
3188 assertNoNonlocalInserts =
3189 params->get<
bool> (
"No Nonlocal Changes", assertNoNonlocalInserts);
3195 if (! indicesAreAllocated ()) {
3198 allocateIndices (LocalIndices, verbose);
3201 allocateIndices (GlobalIndices, verbose);
3209 const bool mayNeedGlobalAssemble = ! assertNoNonlocalInserts && numProcs > 1;
3210 if (mayNeedGlobalAssemble) {
3216 const size_t numNonlocals = nonlocals_.size();
3218 std::ostringstream os;
3219 os << *prefix <<
"Do not need to call globalAssemble; "
3220 "assertNoNonlocalInserts="
3221 << (assertNoNonlocalInserts ?
"true" :
"false")
3222 <<
"numProcs=" << numProcs
3223 <<
", nonlocals_.size()=" << numNonlocals << endl;
3224 std::cerr << os.str();
3226 const int lclNeededGlobalAssemble =
3227 (numProcs > 1 && numNonlocals != 0) ? 1 : 0;
3228 if (lclNeededGlobalAssemble != 0 && verbose) {
3229 std::ostringstream os;
3231 Details::Impl::verbosePrintMap(
3232 os, nonlocals_.begin(), nonlocals_.end(),
3233 nonlocals_.size(),
"nonlocals_");
3234 std::cerr << os.str() << endl;
3238 auto map = this->getMap();
3239 auto comm = map.is_null() ? Teuchos::null : map->getComm();
3240 int gblNeededGlobalAssemble = lclNeededGlobalAssemble;
3241 if (! comm.is_null()) {
3242 using Teuchos::REDUCE_MAX;
3243 using Teuchos::reduceAll;
3244 reduceAll(*comm, REDUCE_MAX, lclNeededGlobalAssemble,
3245 Teuchos::outArg(gblNeededGlobalAssemble));
3247 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3248 (gblNeededGlobalAssemble != 0, std::runtime_error,
3249 "nonlocals_.size()=" << numNonlocals <<
" != 0 on at "
3250 "least one process in the CrsGraph's communicator. This "
3251 "means either that you incorrectly set the "
3252 "\"No Nonlocal Changes\" fillComplete parameter to true, "
3253 "or that you inserted invalid entries. "
3254 "Rerun with the environment variable TPETRA_VERBOSE="
3255 "CrsGraph set to see the entries of nonlocals_ on every "
3256 "MPI process (WARNING: lots of output).");
3259 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3260 (lclNeededGlobalAssemble != 0, std::runtime_error,
3261 "nonlocals_.size()=" << numNonlocals <<
" != 0 on the "
3262 "calling process. This means either that you incorrectly "
3263 "set the \"No Nonlocal Changes\" fillComplete parameter "
3264 "to true, or that you inserted invalid entries. "
3265 "Rerun with the environment "
3266 "variable TPETRA_VERBOSE=CrsGraph set to see the entries "
3267 "of nonlocals_ on every MPI process (WARNING: lots of "
3274 setDomainRangeMaps (domainMap, rangeMap);
3280 Teuchos::Array<int> remotePIDs (0);
3281 const bool mustBuildColMap = ! this->hasColMap ();
3282 if (mustBuildColMap) {
3288 const std::pair<size_t, std::string> makeIndicesLocalResult =
3289 this->makeIndicesLocal(verbose);
3294 using Teuchos::REDUCE_MIN;
3295 using Teuchos::reduceAll;
3296 using Teuchos::outArg;
3298 RCP<const map_type> map = this->getMap ();
3299 RCP<const Teuchos::Comm<int> > comm;
3300 if (! map.is_null ()) {
3301 comm = map->getComm ();
3303 if (comm.is_null ()) {
3304 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3305 (makeIndicesLocalResult.first != 0, std::runtime_error,
3306 makeIndicesLocalResult.second);
3309 const int lclSuccess = (makeIndicesLocalResult.first == 0);
3311 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
3312 if (gblSuccess != 1) {
3313 std::ostringstream os;
3314 gathervPrint (os, makeIndicesLocalResult.second, *comm);
3315 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3316 (
true, std::runtime_error, os.str ());
3325 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3326 (makeIndicesLocalResult.first != 0, std::runtime_error,
3327 makeIndicesLocalResult.second);
3333 this->sortAndMergeAllIndices (this->isSorted (), this->isMerged ());
3338 this->makeImportExport (remotePIDs, mustBuildColMap);
3341 this->fillLocalGraph (params);
3343 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
3344 params->get (
"compute global constants",
true);
3345 if (callComputeGlobalConstants) {
3346 this->computeGlobalConstants ();
3349 this->computeLocalConstants ();
3351 this->fillComplete_ =
true;
3352 this->checkInternalState ();
3355 std::ostringstream os;
3356 os << *prefix <<
"Done" << endl;
3357 std::cerr << os.str();
3362 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3366 const Teuchos::RCP<const map_type>& rangeMap,
3367 const Teuchos::RCP<const import_type>& importer,
3368 const Teuchos::RCP<const export_type>& exporter,
3369 const Teuchos::RCP<Teuchos::ParameterList>& params)
3371 const char tfecfFuncName[] =
"expertStaticFillComplete: ";
3372 #ifdef HAVE_TPETRA_MMM_TIMINGS
3374 if(!params.is_null())
3375 label = params->get(
"Timer Label",label);
3376 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
": ");
3377 using Teuchos::TimeMonitor;
3378 Teuchos::RCP<Teuchos::TimeMonitor> MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Setup"))));
3382 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3383 domainMap.is_null () || rangeMap.is_null (),
3384 std::runtime_error,
"The input domain Map and range Map must be nonnull.");
3385 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3386 isFillComplete () || ! hasColMap (), std::runtime_error,
"You may not "
3387 "call this method unless the graph has a column Map.");
3388 auto rowPtrsUnpackedLength = this->getRowPtrsUnpackedHost().extent (0);
3389 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3390 getLocalNumRows () > 0 && rowPtrsUnpackedLength == 0,
3391 std::runtime_error,
"The calling process has getLocalNumRows() = "
3392 << getLocalNumRows () <<
" > 0 rows, but the row offsets array has not "
3394 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3395 static_cast<size_t> (rowPtrsUnpackedLength) != getLocalNumRows () + 1,
3396 std::runtime_error,
"The row offsets array has length " <<
3397 rowPtrsUnpackedLength <<
" != getLocalNumRows()+1 = " <<
3398 (getLocalNumRows () + 1) <<
".");
3413 numAllocForAllRows_ = 0;
3414 k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
3415 indicesAreAllocated_ =
true;
3420 indicesAreLocal_ =
true;
3421 indicesAreGlobal_ =
false;
3424 #ifdef HAVE_TPETRA_MMM_TIMINGS
3426 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Maps"))));
3428 setDomainRangeMaps (domainMap, rangeMap);
3431 indicesAreSorted_ =
true;
3432 noRedundancies_ =
true;
3435 #ifdef HAVE_TPETRA_MMM_TIMINGS
3437 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckI"))));
3440 importer_ = Teuchos::null;
3441 exporter_ = Teuchos::null;
3442 if (importer != Teuchos::null) {
3443 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3444 ! importer->getSourceMap ()->isSameAs (*getDomainMap ()) ||
3445 ! importer->getTargetMap ()->isSameAs (*getColMap ()),
3446 std::invalid_argument,
": importer does not match matrix maps.");
3447 importer_ = importer;
3451 #ifdef HAVE_TPETRA_MMM_TIMINGS
3453 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckE"))));
3456 if (exporter != Teuchos::null) {
3457 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3458 ! exporter->getSourceMap ()->isSameAs (*getRowMap ()) ||
3459 ! exporter->getTargetMap ()->isSameAs (*getRangeMap ()),
3460 std::invalid_argument,
": exporter does not match matrix maps.");
3461 exporter_ = exporter;
3464 #ifdef HAVE_TPETRA_MMM_TIMINGS
3466 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXmake"))));
3468 Teuchos::Array<int> remotePIDs (0);
3469 this->makeImportExport (remotePIDs,
false);
3471 #ifdef HAVE_TPETRA_MMM_TIMINGS
3473 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-fLG"))));
3475 this->fillLocalGraph (params);
3477 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
3478 params->get (
"compute global constants",
true);
3480 if (callComputeGlobalConstants) {
3481 #ifdef HAVE_TPETRA_MMM_TIMINGS
3483 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (const)"))));
3484 #endif // HAVE_TPETRA_MMM_TIMINGS
3485 this->computeGlobalConstants ();
3488 #ifdef HAVE_TPETRA_MMM_TIMINGS
3490 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (noconst)"))));
3491 #endif // HAVE_TPETRA_MMM_TIMINGS
3492 this->computeLocalConstants ();
3495 fillComplete_ =
true;
3497 #ifdef HAVE_TPETRA_MMM_TIMINGS
3499 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cIS"))));
3501 checkInternalState ();
3505 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3508 fillLocalGraph (
const Teuchos::RCP<Teuchos::ParameterList>& params)
3511 typedef typename local_graph_device_type::row_map_type row_map_type;
3512 typedef typename row_map_type::non_const_type non_const_row_map_type;
3513 typedef typename local_graph_device_type::entries_type::non_const_type lclinds_1d_type;
3514 const char tfecfFuncName[] =
"fillLocalGraph (called from fillComplete or "
3515 "expertStaticFillComplete): ";
3516 const size_t lclNumRows = this->getLocalNumRows ();
3521 bool requestOptimizedStorage =
true;
3522 if (! params.is_null () && ! params->get (
"Optimize Storage",
true)) {
3523 requestOptimizedStorage =
false;
3531 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3533 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3534 (rowPtrsUnpacked.extent (0) == 0, std::logic_error,
3535 "rowPtrsUnpacked_host_ has size zero, but shouldn't");
3536 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3537 (rowPtrsUnpacked.extent (0) != lclNumRows + 1, std::logic_error,
3538 "rowPtrsUnpacked_host_.extent(0) = "
3539 << rowPtrsUnpacked.extent (0) <<
" != (lclNumRows + 1) = "
3540 << (lclNumRows + 1) <<
".");
3541 const size_t numOffsets = rowPtrsUnpacked.extent (0);
3542 const auto valToCheck = rowPtrsUnpacked(numOffsets-1);
3543 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3545 lclIndsUnpacked_wdv.extent (0) != valToCheck,
3546 std::logic_error,
"numOffsets=" << numOffsets <<
" != 0 "
3547 " and lclIndsUnpacked_wdv.extent(0)=" << lclIndsUnpacked_wdv.extent(0)
3548 <<
" != rowPtrsUnpacked_host_(" << numOffsets <<
")=" << valToCheck
3552 size_t allocSize = 0;
3554 allocSize = this->getLocalAllocationSize ();
3556 catch (std::logic_error& e) {
3557 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3558 (
true, std::logic_error,
"getLocalAllocationSize threw "
3559 "std::logic_error: " << e.what ());
3561 catch (std::runtime_error& e) {
3562 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3563 (
true, std::runtime_error,
"getLocalAllocationSize threw "
3564 "std::runtime_error: " << e.what ());
3566 catch (std::exception& e) {
3567 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3568 (
true, std::runtime_error,
"getLocalAllocationSize threw "
3569 "std::exception: " << e.what ());
3572 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3573 (
true, std::runtime_error,
"getLocalAllocationSize threw "
3574 "an exception not a subclass of std::exception.");
3577 if (this->getLocalNumEntries () != allocSize) {
3580 non_const_row_map_type ptr_d;
3581 row_map_type ptr_d_const;
3590 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3591 if (rowPtrsUnpacked.extent (0) != 0) {
3592 const size_t numOffsets =
3593 static_cast<size_t> (rowPtrsUnpacked.extent (0));
3594 const auto valToCheck = rowPtrsUnpacked(numOffsets - 1);
3595 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3596 (valToCheck !=
size_t(lclIndsUnpacked_wdv.extent(0)),
3597 std::logic_error,
"(Unpacked branch) Before allocating "
3598 "or packing, k_rowPtrs_(" << (numOffsets-1) <<
")="
3599 << valToCheck <<
" != lclIndsUnpacked_wdv.extent(0)="
3600 << lclIndsUnpacked_wdv.extent (0) <<
".");
3610 size_t lclTotalNumEntries = 0;
3614 non_const_row_map_type (
"Tpetra::CrsGraph::ptr", lclNumRows + 1);
3615 ptr_d_const = ptr_d;
3619 typename num_row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
3621 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3622 (
size_t(numRowEnt_h.extent (0)) != lclNumRows,
3623 std::logic_error,
"(Unpacked branch) "
3624 "numRowEnt_h.extent(0)=" << numRowEnt_h.extent(0)
3625 <<
" != getLocalNumRows()=" << lclNumRows <<
"");
3631 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3632 (static_cast<size_t> (ptr_d.extent (0)) != lclNumRows + 1,
3633 std::logic_error,
"(Unpacked branch) After allocating "
3634 "ptr_d, ptr_d.extent(0) = " << ptr_d.extent(0)
3635 <<
" != lclNumRows+1 = " << (lclNumRows+1) <<
".");
3636 const auto valToCheck =
3637 ::Tpetra::Details::getEntryOnHost (ptr_d, lclNumRows);
3638 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3639 (valToCheck != lclTotalNumEntries, std::logic_error,
3640 "Tpetra::CrsGraph::fillLocalGraph: In unpacked branch, "
3641 "after filling ptr_d, ptr_d(lclNumRows=" << lclNumRows
3642 <<
") = " << valToCheck <<
" != total number of entries "
3643 "on the calling process = " << lclTotalNumEntries
3649 lclinds_1d_type ind_d =
3650 lclinds_1d_type (
"Tpetra::CrsGraph::lclInd", lclTotalNumEntries);
3662 typedef pack_functor<
3663 typename local_graph_device_type::entries_type::non_const_type,
3664 typename local_inds_dualv_type::t_dev::const_type,
3666 typename local_graph_device_type::row_map_type> inds_packer_type;
3667 inds_packer_type f (ind_d,
3668 lclIndsUnpacked_wdv.getDeviceView(Access::ReadOnly),
3669 ptr_d, this->getRowPtrsUnpackedDevice());
3671 typedef typename decltype (ind_d)::execution_space exec_space;
3672 typedef Kokkos::RangePolicy<exec_space, LocalOrdinal> range_type;
3673 Kokkos::parallel_for (range_type (0, lclNumRows), f);
3677 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3678 (ptr_d.extent (0) == 0, std::logic_error,
3679 "(\"Optimize Storage\"=true branch) After packing, "
3680 "ptr_d.extent(0)=0.");
3681 if (ptr_d.extent (0) != 0) {
3682 const size_t numOffsets =
static_cast<size_t> (ptr_d.extent (0));
3683 const auto valToCheck =
3684 ::Tpetra::Details::getEntryOnHost (ptr_d, numOffsets - 1);
3685 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3686 (static_cast<size_t> (valToCheck) != ind_d.extent (0),
3687 std::logic_error,
"(\"Optimize Storage\"=true branch) "
3688 "After packing, ptr_d(" << (numOffsets-1) <<
")="
3689 << valToCheck <<
" != ind_d.extent(0)="
3690 << ind_d.extent(0) <<
".");
3694 if (requestOptimizedStorage)
3695 setRowPtrs(ptr_d_const);
3697 setRowPtrsPacked(ptr_d_const);
3698 lclIndsPacked_wdv = local_inds_wdv_type(ind_d);
3702 this->setRowPtrs(rowPtrsUnpacked_dev_);
3703 lclIndsPacked_wdv = lclIndsUnpacked_wdv;
3706 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3707 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3708 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3709 (rowPtrsPacked_dev.extent (0) == 0, std::logic_error,
3710 "(\"Optimize Storage\"=false branch) "
3711 "rowPtrsPacked_dev_.extent(0) = 0.");
3712 if (rowPtrsPacked_dev.extent (0) != 0) {
3713 const size_t numOffsets =
3714 static_cast<size_t> (rowPtrsPacked_dev.extent (0));
3715 const size_t valToCheck =
3716 rowPtrsPacked_host(numOffsets - 1);
3717 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3718 (valToCheck !=
size_t(lclIndsPacked_wdv.extent (0)),
3719 std::logic_error,
"(\"Optimize Storage\"=false branch) "
3720 "rowPtrsPacked_dev_(" << (numOffsets-1) <<
")="
3722 <<
" != lclIndsPacked_wdv.extent(0)="
3723 << lclIndsPacked_wdv.extent (0) <<
".");
3729 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3730 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3731 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3732 (static_cast<size_t> (rowPtrsPacked_dev.extent (0)) != lclNumRows + 1,
3733 std::logic_error,
"After packing, rowPtrsPacked_dev_.extent(0) = " <<
3734 rowPtrsPacked_dev.extent (0) <<
" != lclNumRows+1 = " << (lclNumRows+1)
3736 if (rowPtrsPacked_dev.extent (0) != 0) {
3737 const size_t numOffsets =
static_cast<size_t> (rowPtrsPacked_dev.extent (0));
3738 const auto valToCheck = rowPtrsPacked_host(numOffsets - 1);
3739 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3740 (static_cast<size_t> (valToCheck) != lclIndsPacked_wdv.extent (0),
3741 std::logic_error,
"After packing, rowPtrsPacked_dev_(" << (numOffsets-1)
3742 <<
") = " << valToCheck <<
" != lclIndsPacked_wdv.extent(0) = "
3743 << lclIndsPacked_wdv.extent (0) <<
".");
3747 if (requestOptimizedStorage) {
3753 k_numRowEntries_ = num_row_entries_type ();
3756 lclIndsUnpacked_wdv = lclIndsPacked_wdv;
3758 storageStatus_ = Details::STORAGE_1D_PACKED;
3761 set_need_sync_host_uvm_access();
3764 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3776 const char tfecfFuncName[] =
"replaceColMap: ";
3777 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3778 isLocallyIndexed () || isGloballyIndexed (), std::runtime_error,
3779 "Requires matching maps and non-static graph.");
3780 colMap_ = newColMap;
3783 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3787 const Teuchos::RCP<const import_type>& newImport,
3788 const bool sortIndicesInEachRow)
3790 using Teuchos::REDUCE_MIN;
3791 using Teuchos::reduceAll;
3793 typedef GlobalOrdinal GO;
3794 typedef LocalOrdinal LO;
3795 typedef typename local_inds_dualv_type::t_host col_inds_type;
3796 const char tfecfFuncName[] =
"reindexColumns: ";
3798 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3799 isFillComplete (), std::runtime_error,
"The graph is fill complete "
3800 "(isFillComplete() returns true). You must call resumeFill() before "
3801 "you may call this method.");
3819 const LO lclNumRows =
static_cast<LO
> (this->getLocalNumRows ());
3834 bool allCurColIndsValid =
true;
3839 bool localSuffices =
true;
3847 col_inds_type newLclInds1D;
3848 auto oldLclInds1D = lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
3853 if (indicesAreAllocated ()) {
3854 if (isLocallyIndexed ()) {
3856 const map_type& oldColMap = * (getColMap ());
3858 const size_t allocSize = this->getLocalAllocationSize ();
3859 newLclInds1D = col_inds_type(
"Tpetra::CrsGraph::lclIndsReindexedHost",
3862 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
3863 const RowInfo rowInfo = this->getRowInfo (lclRow);
3864 const size_t beg = rowInfo.offset1D;
3865 const size_t end = beg + rowInfo.numEntries;
3866 for (
size_t k = beg; k < end; ++k) {
3867 const LO oldLclCol = oldLclInds1D(k);
3868 if (oldLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
3869 allCurColIndsValid =
false;
3877 if (gblCol == Teuchos::OrdinalTraits<GO>::invalid ()) {
3878 allCurColIndsValid =
false;
3882 const LO newLclCol = newColMap->getLocalElement (gblCol);
3883 if (newLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
3884 localSuffices =
false;
3887 newLclInds1D(k) = newLclCol;
3898 allCurColIndsValid =
false;
3915 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
3916 const RowInfo rowInfo = this->getRowInfo (lclRow);
3917 auto oldGblRowView = this->getGlobalIndsViewHost (rowInfo);
3918 for (
size_t k = 0; k < rowInfo.numEntries; ++k) {
3919 const GO gblCol = oldGblRowView(k);
3920 if (! newColMap->isNodeGlobalElement (gblCol)) {
3921 localSuffices =
false;
3931 lclSuccess[0] = allCurColIndsValid ? 1 : 0;
3932 lclSuccess[1] = localSuffices ? 1 : 0;
3936 RCP<const Teuchos::Comm<int> > comm =
3937 getRowMap ().is_null () ? Teuchos::null : getRowMap ()->getComm ();
3938 if (! comm.is_null ()) {
3939 reduceAll<int, int> (*comm, REDUCE_MIN, 2, lclSuccess, gblSuccess);
3942 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3943 gblSuccess[0] == 0, std::runtime_error,
"It is not possible to continue."
3944 " The most likely reason is that the graph is locally indexed, but the "
3945 "column Map is missing (null) on some processes, due to a previous call "
3946 "to replaceColMap().");
3948 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3949 gblSuccess[1] == 0, std::runtime_error,
"On some process, the graph "
3950 "contains column indices that are in the old column Map, but not in the "
3951 "new column Map (on that process). This method does NOT redistribute "
3952 "data; it does not claim to do the work of an Import or Export operation."
3953 " This means that for all processess, the calling process MUST own all "
3954 "column indices, in both the old column Map and the new column Map. In "
3955 "this case, you will need to do an Import or Export operation to "
3956 "redistribute data.");
3959 if (isLocallyIndexed ()) {
3961 typename local_inds_dualv_type::t_dev newLclInds1D_dev(
3962 Kokkos::view_alloc(
"Tpetra::CrsGraph::lclIndReindexed",
3963 Kokkos::WithoutInitializing),
3964 newLclInds1D.extent(0));
3975 indicesAreSorted_ =
false;
3976 if (sortIndicesInEachRow) {
3983 const bool sorted =
false;
3984 const bool merged =
true;
3985 this->sortAndMergeAllIndices (sorted, merged);
3988 colMap_ = newColMap;
3990 if (newImport.is_null ()) {
3998 if (! domainMap_.is_null ()) {
3999 if (! domainMap_->isSameAs (* newColMap)) {
4000 importer_ = Teuchos::rcp (
new import_type (domainMap_, newColMap));
4002 importer_ = Teuchos::null;
4007 importer_ = newImport;
4011 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4016 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMap: ";
4017 TEUCHOS_TEST_FOR_EXCEPTION(
4018 colMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4019 "this method unless the graph already has a column Map.");
4020 TEUCHOS_TEST_FOR_EXCEPTION(
4021 newDomainMap.is_null (), std::invalid_argument,
4022 prefix <<
"The new domain Map must be nonnull.");
4025 Teuchos::RCP<const import_type> newImporter = Teuchos::null;
4026 if (newDomainMap != colMap_ && (! newDomainMap->isSameAs (*colMap_))) {
4027 newImporter = rcp(
new import_type(newDomainMap, colMap_));
4029 this->replaceDomainMapAndImporter(newDomainMap, newImporter);
4032 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4036 const Teuchos::RCP<const import_type>& newImporter)
4038 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMapAndImporter: ";
4039 TEUCHOS_TEST_FOR_EXCEPTION(
4040 colMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4041 "this method unless the graph already has a column Map.");
4042 TEUCHOS_TEST_FOR_EXCEPTION(
4043 newDomainMap.is_null (), std::invalid_argument,
4044 prefix <<
"The new domain Map must be nonnull.");
4047 if (newImporter.is_null ()) {
4052 const bool colSameAsDom = colMap_->isSameAs (*newDomainMap);
4053 TEUCHOS_TEST_FOR_EXCEPTION
4054 (!colSameAsDom, std::invalid_argument,
"If the new Import is null, "
4055 "then the new domain Map must be the same as the current column Map.");
4058 const bool colSameAsTgt =
4059 colMap_->isSameAs (* (newImporter->getTargetMap ()));
4060 const bool newDomSameAsSrc =
4061 newDomainMap->isSameAs (* (newImporter->getSourceMap ()));
4062 TEUCHOS_TEST_FOR_EXCEPTION
4063 (! colSameAsTgt || ! newDomSameAsSrc, std::invalid_argument,
"If the "
4064 "new Import is nonnull, then the current column Map must be the same "
4065 "as the new Import's target Map, and the new domain Map must be the "
4066 "same as the new Import's source Map.");
4070 domainMap_ = newDomainMap;
4071 importer_ = Teuchos::rcp_const_cast<
import_type> (newImporter);
4074 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4079 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMap: ";
4080 TEUCHOS_TEST_FOR_EXCEPTION(
4081 rowMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4082 "this method unless the graph already has a row Map.");
4083 TEUCHOS_TEST_FOR_EXCEPTION(
4084 newRangeMap.is_null (), std::invalid_argument,
4085 prefix <<
"The new range Map must be nonnull.");
4088 Teuchos::RCP<const export_type> newExporter = Teuchos::null;
4089 if (newRangeMap != rowMap_ && (! newRangeMap->isSameAs (*rowMap_))) {
4090 newExporter = rcp(
new export_type(rowMap_, newRangeMap));
4092 this->replaceRangeMapAndExporter(newRangeMap, newExporter);
4095 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4099 const Teuchos::RCP<const export_type>& newExporter)
4101 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMapAndExporter: ";
4102 TEUCHOS_TEST_FOR_EXCEPTION(
4103 rowMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4104 "this method unless the graph already has a column Map.");
4105 TEUCHOS_TEST_FOR_EXCEPTION(
4106 newRangeMap.is_null (), std::invalid_argument,
4107 prefix <<
"The new domain Map must be nonnull.");
4110 if (newExporter.is_null ()) {
4115 const bool rowSameAsRange = rowMap_->isSameAs (*newRangeMap);
4116 TEUCHOS_TEST_FOR_EXCEPTION
4117 (!rowSameAsRange, std::invalid_argument,
"If the new Export is null, "
4118 "then the new range Map must be the same as the current row Map.");
4121 const bool newRangeSameAsTgt =
4122 newRangeMap->isSameAs (* (newExporter->getTargetMap ()));
4123 const bool rowSameAsSrc =
4124 rowMap_->isSameAs (* (newExporter->getSourceMap ()));
4125 TEUCHOS_TEST_FOR_EXCEPTION
4126 (! rowSameAsSrc || ! newRangeSameAsTgt, std::invalid_argument,
"If the "
4127 "new Export is nonnull, then the current row Map must be the same "
4128 "as the new Export's source Map, and the new range Map must be the "
4129 "same as the new Export's target Map.");
4133 rangeMap_ = newRangeMap;
4134 exporter_ = Teuchos::rcp_const_cast<
export_type> (newExporter);
4138 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4144 lclIndsPacked_wdv.getDeviceView(Access::ReadWrite),
4145 this->getRowPtrsPackedDevice());
4148 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4153 return local_graph_host_type(
4154 lclIndsPacked_wdv.getHostView(Access::ReadWrite),
4155 this->getRowPtrsPackedHost());
4158 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4163 using ::Tpetra::Details::ProfilingRegion;
4164 using Teuchos::ArrayView;
4165 using Teuchos::outArg;
4166 using Teuchos::reduceAll;
4169 ProfilingRegion regionCGC (
"Tpetra::CrsGraph::computeGlobalConstants");
4171 this->computeLocalConstants ();
4176 if (! this->haveGlobalConstants_) {
4177 const Teuchos::Comm<int>& comm = * (this->getComm ());
4191 lcl =
static_cast<GST
> (this->getLocalNumEntries ());
4193 reduceAll<int,GST> (comm, Teuchos::REDUCE_SUM, 1, &lcl, &gbl);
4194 this->globalNumEntries_ = gbl;
4196 const GST lclMaxNumRowEnt =
static_cast<GST
> (this->nodeMaxNumRowEntries_);
4197 reduceAll<int, GST> (comm, Teuchos::REDUCE_MAX, lclMaxNumRowEnt,
4198 outArg (this->globalMaxNumRowEntries_));
4199 this->haveGlobalConstants_ =
true;
4204 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4209 using ::Tpetra::Details::ProfilingRegion;
4211 ProfilingRegion regionCLC (
"Tpetra::CrsGraph::computeLocalConstants");
4212 if (this->haveLocalConstants_) {
4217 this->nodeMaxNumRowEntries_ =
4218 Teuchos::OrdinalTraits<size_t>::invalid();
4222 auto ptr = this->getRowPtrsPackedDevice();
4223 const LO lclNumRows = ptr.extent(0) == 0 ?
4224 static_cast<LO
> (0) :
4225 (static_cast<LO> (ptr.extent(0)) - static_cast<LO> (1));
4227 const LO lclMaxNumRowEnt =
4228 ::Tpetra::Details::maxDifference (
"Tpetra::CrsGraph: nodeMaxNumRowEntries",
4230 this->nodeMaxNumRowEntries_ =
static_cast<size_t> (lclMaxNumRowEnt);
4231 this->haveLocalConstants_ =
true;
4235 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4236 std::pair<size_t, std::string>
4241 using Teuchos::arcp;
4242 using Teuchos::Array;
4244 typedef LocalOrdinal LO;
4245 typedef GlobalOrdinal GO;
4247 typedef typename local_graph_device_type::row_map_type::non_const_value_type offset_type;
4248 typedef typename num_row_entries_type::non_const_value_type num_ent_type;
4249 const char tfecfFuncName[] =
"makeIndicesLocal: ";
4250 ProfilingRegion regionMakeIndicesLocal (
"Tpetra::CrsGraph::makeIndicesLocal");
4252 std::unique_ptr<std::string> prefix;
4254 prefix = this->createPrefix(
"CrsGraph",
"makeIndicesLocal");
4255 std::ostringstream os;
4256 os << *prefix <<
"lclNumRows: " << getLocalNumRows() << endl;
4257 std::cerr << os.str();
4262 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4263 (! this->hasColMap (), std::logic_error,
"The graph does not have a "
4264 "column Map yet. This method should never be called in that case. "
4265 "Please report this bug to the Tpetra developers.");
4266 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4267 (this->getColMap ().is_null (), std::logic_error,
"The graph claims "
4268 "that it has a column Map, because hasColMap() returns true. However, "
4269 "the result of getColMap() is null. This should never happen. Please "
4270 "report this bug to the Tpetra developers.");
4275 size_t lclNumErrs = 0;
4276 std::ostringstream errStrm;
4278 const LO lclNumRows =
static_cast<LO
> (this->getLocalNumRows ());
4279 const map_type& colMap = * (this->getColMap ());
4281 if (this->isGloballyIndexed () && lclNumRows != 0) {
4283 typename num_row_entries_type::const_type h_numRowEnt =
4284 this->k_numRowEntries_;
4286 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
4289 if (rowPtrsUnpacked_host.extent(0) == 0) {
4290 errStrm <<
"Unpacked row pointers (rowPtrsUnpacked_dev_) has length 0. This should never "
4291 "happen here. Please report this bug to the Tpetra developers."
4294 return std::make_pair(Tpetra::Details::OrdinalTraits<size_t>::invalid (),
4297 const auto numEnt = rowPtrsUnpacked_host(lclNumRows);
4306 using Kokkos::view_alloc;
4307 using Kokkos::WithoutInitializing;
4317 const std::string label (
"Tpetra::CrsGraph::lclInd");
4319 std::ostringstream os;
4320 os << *prefix <<
"(Re)allocate lclInd_wdv: old="
4321 << lclIndsUnpacked_wdv.extent(0) <<
", new=" << numEnt << endl;
4322 std::cerr << os.str();
4325 local_inds_dualv_type lclInds_dualv =
4326 local_inds_dualv_type(view_alloc(label, WithoutInitializing),
4339 std::ostringstream os;
4340 os << *prefix <<
"Allocate device mirror k_numRowEnt: "
4341 << h_numRowEnt.extent(0) << endl;
4342 std::cerr << os.str();
4345 Kokkos::create_mirror_view_and_copy (
device_type (), h_numRowEnt);
4349 convertColumnIndicesFromGlobalToLocal<LO, GO, DT, offset_type, num_ent_type> (
4350 lclIndsUnpacked_wdv.getDeviceView(Access::OverwriteAll),
4351 gblInds_wdv.getDeviceView(Access::ReadOnly),
4352 this->getRowPtrsUnpackedDevice(),
4355 if (lclNumErrs != 0) {
4356 const int myRank = [
this] () {
4357 auto map = this->getMap ();
4358 if (map.is_null ()) {
4362 auto comm = map->getComm ();
4363 return comm.is_null () ? 0 : comm->getRank ();
4366 const bool pluralNumErrs = (lclNumErrs !=
static_cast<size_t> (1));
4367 errStrm <<
"(Process " << myRank <<
") When converting column "
4368 "indices from global to local, we encountered " << lclNumErrs
4369 <<
" ind" << (pluralNumErrs ?
"ices" :
"ex")
4370 <<
" that do" << (pluralNumErrs ?
"es" :
"")
4371 <<
" not live in the column Map on this process." << endl;
4378 std::ostringstream os;
4379 os << *prefix <<
"Free gblInds_wdv: "
4380 << gblInds_wdv.extent(0) << endl;
4381 std::cerr << os.str();
4386 this->indicesAreLocal_ =
true;
4387 this->indicesAreGlobal_ =
false;
4388 this->checkInternalState ();
4390 return std::make_pair (lclNumErrs, errStrm.str ());
4393 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4400 const char tfecfFuncName[] =
"makeColMap";
4402 ProfilingRegion regionSortAndMerge (
"Tpetra::CrsGraph::makeColMap");
4403 std::unique_ptr<std::string> prefix;
4405 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4406 std::ostringstream os;
4407 os << *prefix <<
"Start" << endl;
4408 std::cerr << os.str();
4416 Teuchos::RCP<const map_type> colMap = this->colMap_;
4417 const bool sortEachProcsGids =
4418 this->sortGhostsAssociatedWithEachProcessor_;
4428 using Teuchos::outArg;
4429 using Teuchos::REDUCE_MIN;
4430 using Teuchos::reduceAll;
4432 std::ostringstream errStrm;
4433 const int lclErrCode =
4435 getDomainMap (), *
this, sortEachProcsGids, &errStrm);
4436 auto comm = this->getComm ();
4437 if (! comm.is_null ()) {
4438 const int lclSuccess = (lclErrCode == 0) ? 1 : 0;
4440 reduceAll<int, int> (*comm, REDUCE_MIN, lclSuccess,
4441 outArg (gblSuccess));
4442 if (gblSuccess != 1) {
4443 std::ostringstream os;
4445 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4446 (
true, std::runtime_error,
": An error happened on at "
4447 "least one process in the CrsGraph's communicator. "
4448 "Here are all processes' error messages:" << std::endl
4455 getDomainMap (), *
this, sortEachProcsGids,
nullptr);
4460 this->colMap_ = colMap;
4462 checkInternalState ();
4464 std::ostringstream os;
4465 os << *prefix <<
"Done" << endl;
4466 std::cerr << os.str();
4471 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4477 using LO = LocalOrdinal;
4478 using host_execution_space =
4479 typename Kokkos::View<LO*, device_type>::HostMirror::
4481 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
4482 const char tfecfFuncName[] =
"sortAndMergeAllIndices";
4484 (
"Tpetra::CrsGraph::sortAndMergeAllIndices");
4486 std::unique_ptr<std::string> prefix;
4488 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4489 std::ostringstream os;
4490 os << *prefix <<
"Start: "
4491 <<
"sorted=" << (sorted ?
"true" :
"false")
4492 <<
", merged=" << (merged ?
"true" :
"false") << endl;
4493 std::cerr << os.str();
4495 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4496 (this->isGloballyIndexed(), std::logic_error,
4497 "This method may only be called after makeIndicesLocal." );
4498 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4499 (! merged && this->isStorageOptimized(), std::logic_error,
4500 "The graph is already storage optimized, so we shouldn't be "
4501 "merging any indices. "
4502 "Please report this bug to the Tpetra developers.");
4504 if (! sorted || ! merged) {
4505 const LO lclNumRows(this->getLocalNumRows());
4506 auto range = range_type(0, lclNumRows);
4509 size_t totalNumDups = 0;
4511 lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
4513 Kokkos::parallel_reduce(range,
4514 [
this, sorted, merged] (
const LO lclRow,
size_t& numDups)
4516 const RowInfo rowInfo = this->getRowInfo(lclRow);
4517 numDups += this->sortAndMergeRowIndices(rowInfo, sorted, merged);
4521 std::ostringstream os;
4522 os << *prefix <<
"totalNumDups=" << totalNumDups << endl;
4523 std::cerr << os.str();
4527 lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
4529 Kokkos::parallel_for(range,
4530 [
this, sorted, merged] (
const LO lclRow)
4532 const RowInfo rowInfo = this->getRowInfo(lclRow);
4533 this->sortAndMergeRowIndices(rowInfo, sorted, merged);
4537 this->indicesAreSorted_ =
true;
4538 this->noRedundancies_ =
true;
4542 std::ostringstream os;
4543 os << *prefix <<
"Done" << endl;
4544 std::cerr << os.str();
4548 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4552 const bool useRemotePIDs)
4554 using ::Tpetra::Details::ProfilingRegion;
4555 using Teuchos::ParameterList;
4558 const char tfecfFuncName[] =
"makeImportExport: ";
4559 ProfilingRegion regionMIE (
"Tpetra::CrsGraph::makeImportExport");
4561 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4562 (! this->hasColMap (), std::logic_error,
4563 "This method may not be called unless the graph has a column Map.");
4564 RCP<ParameterList> params = this->getNonconstParameterList ();
4573 if (importer_.is_null ()) {
4575 if (domainMap_ != colMap_ && (! domainMap_->isSameAs (*colMap_))) {
4576 if (params.is_null () || ! params->isSublist (
"Import")) {
4577 if (useRemotePIDs) {
4578 importer_ = rcp (
new import_type (domainMap_, colMap_, remotePIDs));
4581 importer_ = rcp (
new import_type (domainMap_, colMap_));
4585 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
4586 if (useRemotePIDs) {
4587 RCP<import_type> newImp =
4588 rcp (
new import_type (domainMap_, colMap_, remotePIDs,
4593 importer_ = rcp (
new import_type (domainMap_, colMap_, importSublist));
4601 if (exporter_.is_null ()) {
4603 if (rangeMap_ != rowMap_ && ! rangeMap_->isSameAs (*rowMap_)) {
4604 if (params.is_null () || ! params->isSublist (
"Export")) {
4605 exporter_ = rcp (
new export_type (rowMap_, rangeMap_));
4608 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
4609 exporter_ = rcp (
new export_type (rowMap_, rangeMap_, exportSublist));
4616 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4621 std::ostringstream oss;
4622 oss << dist_object_type::description ();
4623 if (isFillComplete ()) {
4624 oss <<
"{status = fill complete"
4625 <<
", global rows = " << getGlobalNumRows()
4626 <<
", global cols = " << getGlobalNumCols()
4627 <<
", global num entries = " << getGlobalNumEntries()
4631 oss <<
"{status = fill not complete"
4632 <<
", global rows = " << getGlobalNumRows()
4639 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4643 const Teuchos::EVerbosityLevel verbLevel)
const
4645 using Teuchos::ArrayView;
4646 using Teuchos::Comm;
4648 using Teuchos::VERB_DEFAULT;
4649 using Teuchos::VERB_NONE;
4650 using Teuchos::VERB_LOW;
4651 using Teuchos::VERB_MEDIUM;
4652 using Teuchos::VERB_HIGH;
4653 using Teuchos::VERB_EXTREME;
4657 Teuchos::EVerbosityLevel vl = verbLevel;
4658 if (vl == VERB_DEFAULT) vl = VERB_LOW;
4659 RCP<const Comm<int> > comm = this->getComm();
4660 const int myImageID = comm->getRank(),
4661 numImages = comm->getSize();
4663 for (
size_t dec=10; dec<getGlobalNumRows(); dec *= 10) {
4666 width = std::max<size_t> (width,
static_cast<size_t> (11)) + 2;
4667 Teuchos::OSTab tab (out);
4675 if (vl != VERB_NONE) {
4676 if (myImageID == 0) out << this->description() << std::endl;
4678 if (isFillComplete() && myImageID == 0) {
4679 out <<
"Global max number of row entries = " << globalMaxNumRowEntries_ << std::endl;
4682 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4683 if (myImageID == 0) out <<
"\nRow map: " << std::endl;
4684 rowMap_->describe(out,vl);
4685 if (colMap_ != Teuchos::null) {
4686 if (myImageID == 0) out <<
"\nColumn map: " << std::endl;
4687 colMap_->describe(out,vl);
4689 if (domainMap_ != Teuchos::null) {
4690 if (myImageID == 0) out <<
"\nDomain map: " << std::endl;
4691 domainMap_->describe(out,vl);
4693 if (rangeMap_ != Teuchos::null) {
4694 if (myImageID == 0) out <<
"\nRange map: " << std::endl;
4695 rangeMap_->describe(out,vl);
4699 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4700 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4701 if (myImageID == imageCtr) {
4702 out <<
"Node ID = " << imageCtr << std::endl
4703 <<
"Node number of entries = " << this->getLocalNumEntries () << std::endl
4704 <<
"Node max number of entries = " << nodeMaxNumRowEntries_ << std::endl;
4705 if (! indicesAreAllocated ()) {
4706 out <<
"Indices are not allocated." << std::endl;
4715 if (vl == VERB_HIGH || vl == VERB_EXTREME) {
4716 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4717 if (myImageID == imageCtr) {
4718 out << std::setw(width) <<
"Node ID"
4719 << std::setw(width) <<
"Global Row"
4720 << std::setw(width) <<
"Num Entries";
4721 if (vl == VERB_EXTREME) {
4725 const LocalOrdinal lclNumRows =
4726 static_cast<LocalOrdinal
> (this->getLocalNumRows ());
4727 for (LocalOrdinal r=0; r < lclNumRows; ++r) {
4728 const RowInfo rowinfo = this->getRowInfo (r);
4729 GlobalOrdinal gid = rowMap_->getGlobalElement(r);
4730 out << std::setw(width) << myImageID
4731 << std::setw(width) << gid
4732 << std::setw(width) << rowinfo.numEntries;
4733 if (vl == VERB_EXTREME) {
4735 if (isGloballyIndexed()) {
4736 auto rowview = gblInds_wdv.getHostView(Access::ReadOnly);
4737 for (
size_t j=0; j < rowinfo.numEntries; ++j){
4738 GlobalOrdinal colgid = rowview[j + rowinfo.offset1D];
4739 out << colgid <<
" ";
4742 else if (isLocallyIndexed()) {
4743 auto rowview = lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
4744 for (
size_t j=0; j < rowinfo.numEntries; ++j) {
4745 LocalOrdinal collid = rowview[j + rowinfo.offset1D];
4746 out << colMap_->getGlobalElement(collid) <<
" ";
4762 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4773 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4778 const size_t numSameIDs,
4789 const char tfecfFuncName[] =
"copyAndPermute: ";
4790 const bool verbose = verbose_;
4792 std::unique_ptr<std::string> prefix;
4794 prefix = this->createPrefix(
"CrsGraph",
"copyAndPermute");
4795 std::ostringstream os;
4796 os << *prefix << endl;
4797 std::cerr << os.str ();
4800 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4801 (permuteToLIDs.extent (0) != permuteFromLIDs.extent (0),
4802 std::runtime_error,
"permuteToLIDs.extent(0) = "
4803 << permuteToLIDs.extent (0) <<
" != permuteFromLIDs.extent(0) = "
4804 << permuteFromLIDs.extent (0) <<
".");
4812 std::ostringstream os;
4813 os << *prefix <<
"Compute padding" << endl;
4814 std::cerr << os.str ();
4816 auto padding = computeCrsPadding(srcRowGraph, numSameIDs,
4817 permuteToLIDs, permuteFromLIDs, verbose);
4818 applyCrsPadding(*padding, verbose);
4823 const this_CRS_type* srcCrsGraph =
4824 dynamic_cast<const this_CRS_type*
> (&source);
4826 const map_type& srcRowMap = *(srcRowGraph.getRowMap());
4827 const map_type& tgtRowMap = *(getRowMap());
4828 const bool src_filled = srcRowGraph.isFillComplete();
4829 nonconst_global_inds_host_view_type row_copy;
4835 if (src_filled || srcCrsGraph ==
nullptr) {
4837 std::ostringstream os;
4838 os << *prefix <<
"src_filled || srcCrsGraph == nullptr" << endl;
4839 std::cerr << os.str ();
4846 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
4848 size_t row_length = srcRowGraph.getNumEntriesInGlobalRow (gid);
4849 Kokkos::resize(row_copy,row_length);
4850 size_t check_row_length = 0;
4851 srcRowGraph.getGlobalRowCopy (gid, row_copy, check_row_length);
4852 this->insertGlobalIndices (gid, row_length, row_copy.data());
4856 std::ostringstream os;
4857 os << *prefix <<
"! src_filled && srcCrsGraph != nullptr" << endl;
4858 std::cerr << os.str ();
4860 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
4862 global_inds_host_view_type row;
4863 srcCrsGraph->getGlobalRowView (gid, row);
4864 this->insertGlobalIndices (gid, row.extent(0), row.data());
4871 auto permuteToLIDs_h = permuteToLIDs.view_host ();
4872 auto permuteFromLIDs_h = permuteFromLIDs.view_host ();
4874 if (src_filled || srcCrsGraph ==
nullptr) {
4875 for (LO i = 0; i < static_cast<LO> (permuteToLIDs_h.extent (0)); ++i) {
4878 size_t row_length = srcRowGraph.getNumEntriesInGlobalRow (srcgid);
4879 Kokkos::resize(row_copy,row_length);
4880 size_t check_row_length = 0;
4881 srcRowGraph.getGlobalRowCopy (srcgid, row_copy, check_row_length);
4882 this->insertGlobalIndices (mygid, row_length, row_copy.data());
4885 for (LO i = 0; i < static_cast<LO> (permuteToLIDs_h.extent (0)); ++i) {
4888 global_inds_host_view_type row;
4889 srcCrsGraph->getGlobalRowView (srcgid, row);
4890 this->insertGlobalIndices (mygid, row.extent(0), row.data());
4895 std::ostringstream os;
4896 os << *prefix <<
"Done" << endl;
4897 std::cerr << os.str ();
4901 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4910 using LO = local_ordinal_type;
4911 using row_ptrs_type =
4912 typename local_graph_device_type::row_map_type::non_const_type;
4913 using range_policy =
4914 Kokkos::RangePolicy<execution_space, Kokkos::IndexType<LO>>;
4915 const char tfecfFuncName[] =
"applyCrsPadding";
4916 ProfilingRegion regionCAP(
"Tpetra::CrsGraph::applyCrsPadding");
4918 std::unique_ptr<std::string> prefix;
4920 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4921 std::ostringstream os;
4922 os << *prefix <<
"padding: ";
4925 std::cerr << os.str();
4927 const int myRank = ! verbose ? -1 : [&] () {
4928 auto map = this->getMap();
4929 if (map.is_null()) {
4932 auto comm = map->getComm();
4933 if (comm.is_null()) {
4936 return comm->getRank();
4945 if (! indicesAreAllocated()) {
4947 std::ostringstream os;
4948 os << *prefix <<
"Call allocateIndices" << endl;
4949 std::cerr << os.str();
4951 allocateIndices(GlobalIndices, verbose);
4953 TEUCHOS_ASSERT( indicesAreAllocated() );
4958 auto rowPtrsUnpacked_dev = this->getRowPtrsUnpackedDevice();
4960 std::ostringstream os;
4961 os << *prefix <<
"Allocate row_ptrs_beg: "
4962 << rowPtrsUnpacked_dev.extent(0) << endl;
4963 std::cerr << os.str();
4965 using Kokkos::view_alloc;
4966 using Kokkos::WithoutInitializing;
4967 row_ptrs_type row_ptrs_beg(
4968 view_alloc(
"row_ptrs_beg", WithoutInitializing),
4969 rowPtrsUnpacked_dev.extent(0));
4973 const size_t N = row_ptrs_beg.extent(0) == 0 ? size_t(0) :
4974 size_t(row_ptrs_beg.extent(0) - 1);
4976 std::ostringstream os;
4977 os << *prefix <<
"Allocate row_ptrs_end: " << N << endl;
4978 std::cerr << os.str();
4980 row_ptrs_type row_ptrs_end(
4981 view_alloc(
"row_ptrs_end", WithoutInitializing), N);
4982 row_ptrs_type num_row_entries;
4984 const bool refill_num_row_entries = k_numRowEntries_.extent(0) != 0;
4986 execution_space().fence();
4988 if (refill_num_row_entries) {
4992 row_ptrs_type(view_alloc(
"num_row_entries", WithoutInitializing), N);
4994 Kokkos::parallel_for
4995 (
"Fill end row pointers", range_policy(0, N),
4996 KOKKOS_LAMBDA (
const size_t i) {
4997 row_ptrs_end(i) = row_ptrs_beg(i) + num_row_entries(i);
5004 Kokkos::parallel_for
5005 (
"Fill end row pointers", range_policy(0, N),
5006 KOKKOS_LAMBDA (
const size_t i) {
5007 row_ptrs_end(i) = row_ptrs_beg(i+1);
5011 if (isGloballyIndexed()) {
5013 padding, myRank, verbose);
5016 padCrsArrays(row_ptrs_beg, row_ptrs_end, lclIndsUnpacked_wdv,
5017 padding, myRank, verbose);
5020 if (refill_num_row_entries) {
5021 Kokkos::parallel_for
5022 (
"Fill num entries", range_policy(0, N),
5023 KOKKOS_LAMBDA (
const size_t i) {
5024 num_row_entries(i) = row_ptrs_end(i) - row_ptrs_beg(i);
5029 std::ostringstream os;
5030 os << *prefix <<
"Reassign k_rowPtrs_; old size: "
5031 << rowPtrsUnpacked_dev.extent(0) <<
", new size: "
5032 << row_ptrs_beg.extent(0) << endl;
5033 std::cerr << os.str();
5034 TEUCHOS_ASSERT( rowPtrsUnpacked_dev.extent(0) == row_ptrs_beg.extent(0) );
5037 setRowPtrsUnpacked(row_ptrs_beg);
5040 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5042 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5044 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5046 const RowGraph<LocalOrdinal,GlobalOrdinal,Node>& source,
5047 const size_t numSameIDs,
5048 const Kokkos::DualView<
const local_ordinal_type*,
5049 buffer_device_type>& permuteToLIDs,
5050 const Kokkos::DualView<
const local_ordinal_type*,
5051 buffer_device_type>& permuteFromLIDs,
5052 const bool verbose)
const
5057 std::unique_ptr<std::string> prefix;
5060 "computeCrsPadding(same & permute)");
5061 std::ostringstream os;
5062 os << *prefix <<
"{numSameIDs: " << numSameIDs
5063 <<
", numPermutes: " << permuteFromLIDs.extent(0) <<
"}"
5065 std::cerr << os.str();
5068 const int myRank = [&] () {
5069 auto comm = rowMap_.is_null() ? Teuchos::null :
5071 return comm.is_null() ? -1 : comm->getRank();
5073 std::unique_ptr<padding_type> padding(
5074 new padding_type(myRank, numSameIDs,
5075 permuteFromLIDs.extent(0)));
5077 computeCrsPaddingForSameIDs(*padding, source,
5078 static_cast<LO>(numSameIDs));
5079 computeCrsPaddingForPermutedIDs(*padding, source, permuteToLIDs,
5084 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5086 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5087 computeCrsPaddingForSameIDs(
5088 padding_type& padding,
5089 const RowGraph<local_ordinal_type, global_ordinal_type,
5091 const local_ordinal_type numSameIDs)
const
5094 using GO = global_ordinal_type;
5095 using Details::Impl::getRowGraphGlobalRow;
5097 const char tfecfFuncName[] =
"computeCrsPaddingForSameIds";
5099 std::unique_ptr<std::string> prefix;
5100 const bool verbose = verbose_;
5102 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5103 std::ostringstream os;
5104 os << *prefix <<
"numSameIDs: " << numSameIDs << endl;
5105 std::cerr << os.str();
5108 if (numSameIDs == 0) {
5112 const map_type& srcRowMap = *(source.getRowMap());
5113 const map_type& tgtRowMap = *rowMap_;
5114 using this_CRS_type = CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
5115 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
5116 const bool src_is_unique =
5117 srcCrs ==
nullptr ?
false : srcCrs->isMerged();
5118 const bool tgt_is_unique = this->isMerged();
5120 std::vector<GO> srcGblColIndsScratch;
5121 std::vector<GO> tgtGblColIndsScratch;
5123 execute_sync_host_uvm_access();
5124 for (LO lclRowInd = 0; lclRowInd < numSameIDs; ++lclRowInd) {
5125 const GO srcGblRowInd = srcRowMap.getGlobalElement(lclRowInd);
5126 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(lclRowInd);
5127 auto srcGblColInds = getRowGraphGlobalRow(
5128 srcGblColIndsScratch, source, srcGblRowInd);
5129 auto tgtGblColInds = getRowGraphGlobalRow(
5130 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5131 padding.update_same(lclRowInd, tgtGblColInds.getRawPtr(),
5132 tgtGblColInds.size(), tgt_is_unique,
5133 srcGblColInds.getRawPtr(),
5134 srcGblColInds.size(), src_is_unique);
5137 std::ostringstream os;
5138 os << *prefix <<
"Done" << endl;
5139 std::cerr << os.str();
5143 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5145 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5146 computeCrsPaddingForPermutedIDs(
5147 padding_type& padding,
5148 const RowGraph<local_ordinal_type, global_ordinal_type,
5150 const Kokkos::DualView<
const local_ordinal_type*,
5151 buffer_device_type>& permuteToLIDs,
5152 const Kokkos::DualView<
const local_ordinal_type*,
5153 buffer_device_type>& permuteFromLIDs)
const
5156 using GO = global_ordinal_type;
5157 using Details::Impl::getRowGraphGlobalRow;
5159 const char tfecfFuncName[] =
"computeCrsPaddingForPermutedIds";
5161 std::unique_ptr<std::string> prefix;
5162 const bool verbose = verbose_;
5164 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5165 std::ostringstream os;
5166 os << *prefix <<
"permuteToLIDs.extent(0): "
5167 << permuteToLIDs.extent(0)
5168 <<
", permuteFromLIDs.extent(0): "
5169 << permuteFromLIDs.extent(0) << endl;
5170 std::cerr << os.str();
5173 if (permuteToLIDs.extent(0) == 0) {
5177 const map_type& srcRowMap = *(source.getRowMap());
5178 const map_type& tgtRowMap = *rowMap_;
5179 using this_CRS_type = CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
5180 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
5181 const bool src_is_unique =
5182 srcCrs ==
nullptr ?
false : srcCrs->isMerged();
5183 const bool tgt_is_unique = this->isMerged();
5185 TEUCHOS_ASSERT( ! permuteToLIDs.need_sync_host() );
5186 auto permuteToLIDs_h = permuteToLIDs.view_host();
5187 TEUCHOS_ASSERT( ! permuteFromLIDs.need_sync_host() );
5188 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
5190 std::vector<GO> srcGblColIndsScratch;
5191 std::vector<GO> tgtGblColIndsScratch;
5192 const LO numPermutes =
static_cast<LO
>(permuteToLIDs_h.extent(0));
5194 execute_sync_host_uvm_access();
5195 for (LO whichPermute = 0; whichPermute < numPermutes; ++whichPermute) {
5196 const LO srcLclRowInd = permuteFromLIDs_h[whichPermute];
5197 const GO srcGblRowInd = srcRowMap.getGlobalElement(srcLclRowInd);
5198 auto srcGblColInds = getRowGraphGlobalRow(
5199 srcGblColIndsScratch, source, srcGblRowInd);
5200 const LO tgtLclRowInd = permuteToLIDs_h[whichPermute];
5201 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(tgtLclRowInd);
5202 auto tgtGblColInds = getRowGraphGlobalRow(
5203 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5204 padding.update_permute(whichPermute, tgtLclRowInd,
5205 tgtGblColInds.getRawPtr(),
5206 tgtGblColInds.size(), tgt_is_unique,
5207 srcGblColInds.getRawPtr(),
5208 srcGblColInds.size(), src_is_unique);
5212 std::ostringstream os;
5213 os << *prefix <<
"Done" << endl;
5214 std::cerr << os.str();
5218 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5220 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5222 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5223 computeCrsPaddingForImports(
5224 const Kokkos::DualView<
const local_ordinal_type*,
5225 buffer_device_type>& importLIDs,
5226 Kokkos::DualView<packet_type*, buffer_device_type> imports,
5227 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
5228 const bool verbose)
const
5230 using Details::Impl::getRowGraphGlobalRow;
5233 using GO = global_ordinal_type;
5234 const char tfecfFuncName[] =
"computeCrsPaddingForImports";
5236 std::unique_ptr<std::string> prefix;
5238 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5239 std::ostringstream os;
5240 os << *prefix <<
"importLIDs.extent(0): "
5241 << importLIDs.extent(0)
5242 <<
", imports.extent(0): "
5243 << imports.extent(0)
5244 <<
", numPacketsPerLID.extent(0): "
5245 << numPacketsPerLID.extent(0) << endl;
5246 std::cerr << os.str();
5249 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5250 const int myRank = [&] () {
5251 auto comm = rowMap_.is_null() ? Teuchos::null :
5253 return comm.is_null() ? -1 : comm->getRank();
5255 std::unique_ptr<padding_type> padding(
5256 new padding_type(myRank, numImports));
5258 if (imports.need_sync_host()) {
5259 imports.sync_host();
5261 auto imports_h = imports.view_host();
5262 if (numPacketsPerLID.need_sync_host ()) {
5263 numPacketsPerLID.sync_host();
5265 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5267 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
5268 auto importLIDs_h = importLIDs.view_host();
5270 const map_type& tgtRowMap = *rowMap_;
5274 constexpr
bool src_is_unique =
false;
5275 const bool tgt_is_unique = isMerged();
5277 std::vector<GO> tgtGblColIndsScratch;
5279 execute_sync_host_uvm_access();
5280 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5285 const LO origSrcNumEnt =
5286 static_cast<LO
>(numPacketsPerLID_h[whichImport]);
5287 GO*
const srcGblColInds = imports_h.data() + offset;
5289 const LO tgtLclRowInd = importLIDs_h[whichImport];
5290 const GO tgtGblRowInd =
5291 tgtRowMap.getGlobalElement(tgtLclRowInd);
5292 auto tgtGblColInds = getRowGraphGlobalRow(
5293 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5294 const size_t origTgtNumEnt(tgtGblColInds.size());
5296 padding->update_import(whichImport, tgtLclRowInd,
5297 tgtGblColInds.getRawPtr(),
5298 origTgtNumEnt, tgt_is_unique,
5300 origSrcNumEnt, src_is_unique);
5301 offset += origSrcNumEnt;
5305 std::ostringstream os;
5306 os << *prefix <<
"Done" << endl;
5307 std::cerr << os.str();
5312 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5314 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5316 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5317 computePaddingForCrsMatrixUnpack(
5318 const Kokkos::DualView<
const local_ordinal_type*,
5319 buffer_device_type>& importLIDs,
5320 Kokkos::DualView<char*, buffer_device_type> imports,
5321 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
5322 const bool verbose)
const
5324 using Details::Impl::getRowGraphGlobalRow;
5325 using Details::PackTraits;
5328 using GO = global_ordinal_type;
5329 const char tfecfFuncName[] =
"computePaddingForCrsMatrixUnpack";
5331 std::unique_ptr<std::string> prefix;
5333 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5334 std::ostringstream os;
5335 os << *prefix <<
"importLIDs.extent(0): "
5336 << importLIDs.extent(0)
5337 <<
", imports.extent(0): "
5338 << imports.extent(0)
5339 <<
", numPacketsPerLID.extent(0): "
5340 << numPacketsPerLID.extent(0) << endl;
5341 std::cerr << os.str();
5343 const bool extraVerbose =
5346 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5347 TEUCHOS_ASSERT( LO(numPacketsPerLID.extent(0)) >= numImports );
5348 const int myRank = [&] () {
5349 auto comm = rowMap_.is_null() ? Teuchos::null :
5351 return comm.is_null() ? -1 : comm->getRank();
5353 std::unique_ptr<padding_type> padding(
5354 new padding_type(myRank, numImports));
5356 if (imports.need_sync_host()) {
5357 imports.sync_host();
5359 auto imports_h = imports.view_host();
5360 if (numPacketsPerLID.need_sync_host ()) {
5361 numPacketsPerLID.sync_host();
5363 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5365 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
5366 auto importLIDs_h = importLIDs.view_host();
5368 const map_type& tgtRowMap = *rowMap_;
5372 constexpr
bool src_is_unique =
false;
5373 const bool tgt_is_unique = isMerged();
5375 std::vector<GO> srcGblColIndsScratch;
5376 std::vector<GO> tgtGblColIndsScratch;
5378 execute_sync_host_uvm_access();
5379 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5384 const size_t numBytes = numPacketsPerLID_h[whichImport];
5386 std::ostringstream os;
5387 os << *prefix <<
"whichImport=" << whichImport
5388 <<
", numImports=" << numImports
5389 <<
", numBytes=" << numBytes << endl;
5390 std::cerr << os.str();
5392 if (numBytes == 0) {
5395 LO origSrcNumEnt = 0;
5396 const size_t numEntBeg = offset;
5397 const size_t numEntLen =
5399 TEUCHOS_ASSERT( numBytes >= numEntLen );
5400 TEUCHOS_ASSERT( imports_h.extent(0) >= numEntBeg + numEntLen );
5402 imports_h.data() + numEntBeg);
5404 std::ostringstream os;
5405 os << *prefix <<
"whichImport=" << whichImport
5406 <<
", numImports=" << numImports
5407 <<
", origSrcNumEnt=" << origSrcNumEnt << endl;
5408 std::cerr << os.str();
5410 TEUCHOS_ASSERT( origSrcNumEnt >= LO(0) );
5411 TEUCHOS_ASSERT( numBytes >=
size_t(numEntLen + origSrcNumEnt *
sizeof(GO)) );
5412 const size_t gidsBeg = numEntBeg + numEntLen;
5413 if (srcGblColIndsScratch.size() < size_t(origSrcNumEnt)) {
5414 srcGblColIndsScratch.resize(origSrcNumEnt);
5416 GO*
const srcGblColInds = srcGblColIndsScratch.data();
5417 PackTraits<GO>::unpackArray(srcGblColInds,
5418 imports_h.data() + gidsBeg,
5420 const LO tgtLclRowInd = importLIDs_h[whichImport];
5421 const GO tgtGblRowInd =
5422 tgtRowMap.getGlobalElement(tgtLclRowInd);
5423 auto tgtGblColInds = getRowGraphGlobalRow(
5424 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5425 const size_t origNumTgtEnt(tgtGblColInds.size());
5428 std::ostringstream os;
5429 os << *prefix <<
"whichImport=" << whichImport
5430 <<
", numImports=" << numImports
5431 <<
": Call padding->update_import" << endl;
5432 std::cerr << os.str();
5434 padding->update_import(whichImport, tgtLclRowInd,
5435 tgtGblColInds.getRawPtr(),
5436 origNumTgtEnt, tgt_is_unique,
5438 origSrcNumEnt, src_is_unique);
5443 std::ostringstream os;
5444 os << *prefix <<
"Done" << endl;
5445 std::cerr << os.str();
5450 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5452 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5454 (
const SrcDistObject& source,
5455 const Kokkos::DualView<
const local_ordinal_type*,
5456 buffer_device_type>& exportLIDs,
5457 Kokkos::DualView<packet_type*,
5458 buffer_device_type>& exports,
5459 Kokkos::DualView<
size_t*,
5460 buffer_device_type> numPacketsPerLID,
5461 size_t& constantNumPackets)
5464 using GO = global_ordinal_type;
5466 using crs_graph_type =
5467 CrsGraph<local_ordinal_type, global_ordinal_type, node_type>;
5468 const char tfecfFuncName[] =
"packAndPrepare: ";
5469 ProfilingRegion region_papn (
"Tpetra::CrsGraph::packAndPrepare");
5471 const bool verbose = verbose_;
5472 std::unique_ptr<std::string> prefix;
5474 prefix = this->
createPrefix(
"CrsGraph",
"packAndPrepare");
5475 std::ostringstream os;
5476 os << *prefix <<
"Start" << endl;
5477 std::cerr << os.str();
5480 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5481 (exportLIDs.extent (0) != numPacketsPerLID.extent (0),
5483 "exportLIDs.extent(0) = " << exportLIDs.extent (0)
5484 <<
" != numPacketsPerLID.extent(0) = " << numPacketsPerLID.extent (0)
5486 const row_graph_type* srcRowGraphPtr =
5487 dynamic_cast<const row_graph_type*
> (&source);
5488 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5489 (srcRowGraphPtr ==
nullptr, std::invalid_argument,
"Source of an Export "
5490 "or Import operation to a CrsGraph must be a RowGraph with the same "
5491 "template parameters.");
5495 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5496 (this->isFillComplete (), std::runtime_error,
5497 "The target graph of an Import or Export must not be fill complete.");
5499 const crs_graph_type* srcCrsGraphPtr =
5500 dynamic_cast<const crs_graph_type*
> (&source);
5502 if (srcCrsGraphPtr ==
nullptr) {
5503 using Teuchos::ArrayView;
5507 std::ostringstream os;
5508 os << *prefix <<
"Source is a RowGraph but not a CrsGraph"
5510 std::cerr << os.str();
5517 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
5518 auto exportLIDs_h = exportLIDs.view_host ();
5519 ArrayView<const LO> exportLIDs_av (exportLIDs_h.data (),
5520 exportLIDs_h.extent (0));
5521 Teuchos::Array<GO> exports_a;
5523 numPacketsPerLID.clear_sync_state ();
5524 numPacketsPerLID.modify_host ();
5525 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
5526 ArrayView<size_t> numPacketsPerLID_av (numPacketsPerLID_h.data (),
5527 numPacketsPerLID_h.extent (0));
5528 srcRowGraphPtr->pack (exportLIDs_av, exports_a, numPacketsPerLID_av,
5529 constantNumPackets);
5530 const size_t newSize =
static_cast<size_t> (exports_a.size ());
5531 if (static_cast<size_t> (exports.extent (0)) != newSize) {
5532 using exports_dv_type = Kokkos::DualView<packet_type*, buffer_device_type>;
5533 exports = exports_dv_type (
"exports", newSize);
5535 Kokkos::View<
const packet_type*, Kokkos::HostSpace,
5536 Kokkos::MemoryUnmanaged> exports_a_h (exports_a.getRawPtr (), newSize);
5537 exports.clear_sync_state ();
5538 exports.modify_host ();
5543 else if (! getColMap ().is_null () &&
5544 (this->getRowPtrsPackedDevice().extent (0) != 0 ||
5545 getRowMap ()->getLocalNumElements () == 0)) {
5547 std::ostringstream os;
5548 os << *prefix <<
"packCrsGraphNew path" << endl;
5549 std::cerr << os.str();
5551 using export_pids_type =
5552 Kokkos::DualView<const int*, buffer_device_type>;
5553 export_pids_type exportPIDs;
5555 using NT = node_type;
5557 packCrsGraphNew<LO,GO,NT> (*srcCrsGraphPtr, exportLIDs, exportPIDs,
5558 exports, numPacketsPerLID,
5559 constantNumPackets,
false);
5562 srcCrsGraphPtr->packFillActiveNew (exportLIDs, exports, numPacketsPerLID,
5563 constantNumPackets);
5567 std::ostringstream os;
5568 os << *prefix <<
"Done" << endl;
5569 std::cerr << os.str();
5573 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5576 pack (
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5577 Teuchos::Array<GlobalOrdinal>& exports,
5578 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5579 size_t& constantNumPackets)
const
5581 auto col_map = this->getColMap();
5583 if( !col_map.is_null() && (this->getRowPtrsPackedDevice().extent(0) != 0 || getRowMap()->getLocalNumElements() ==0)) {
5585 packCrsGraph<LocalOrdinal,GlobalOrdinal,Node>(*
this, exports, numPacketsPerLID,
5586 exportLIDs, constantNumPackets);
5589 this->packFillActive(exportLIDs, exports, numPacketsPerLID,
5590 constantNumPackets);
5594 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5597 packFillActive (
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5598 Teuchos::Array<GlobalOrdinal>& exports,
5599 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5600 size_t& constantNumPackets)
const
5603 using LO = LocalOrdinal;
5604 using GO = GlobalOrdinal;
5605 using host_execution_space =
5606 typename Kokkos::View<size_t*, device_type>::
5607 HostMirror::execution_space;
5608 const char tfecfFuncName[] =
"packFillActive: ";
5609 const bool verbose = verbose_;
5611 const auto numExportLIDs = exportLIDs.size ();
5612 std::unique_ptr<std::string> prefix;
5614 prefix = this->createPrefix(
"CrsGraph",
"allocateIndices");
5615 std::ostringstream os;
5616 os << *prefix <<
"numExportLIDs=" << numExportLIDs << endl;
5617 std::cerr << os.str();
5619 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5620 (numExportLIDs != numPacketsPerLID.size (), std::runtime_error,
5621 "exportLIDs.size() = " << numExportLIDs <<
" != numPacketsPerLID.size()"
5622 " = " << numPacketsPerLID.size () <<
".");
5624 const map_type& rowMap = * (this->getRowMap ());
5625 const map_type*
const colMapPtr = this->colMap_.getRawPtr ();
5626 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5627 (this->isLocallyIndexed () && colMapPtr ==
nullptr, std::logic_error,
5628 "This graph claims to be locally indexed, but its column Map is nullptr. "
5629 "This should never happen. Please report this bug to the Tpetra "
5633 constantNumPackets = 0;
5637 size_t*
const numPacketsPerLID_raw = numPacketsPerLID.getRawPtr ();
5638 const LO*
const exportLIDs_raw = exportLIDs.getRawPtr ();
5645 Kokkos::RangePolicy<host_execution_space, LO> inputRange (0, numExportLIDs);
5646 size_t totalNumPackets = 0;
5647 size_t errCount = 0;
5650 typedef Kokkos::Device<host_execution_space, Kokkos::HostSpace>
5652 Kokkos::View<size_t, host_device_type> errCountView (&errCount);
5653 constexpr
size_t ONE = 1;
5655 execute_sync_host_uvm_access();
5656 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::pack: totalNumPackets",
5658 [=] (
const LO& i,
size_t& curTotalNumPackets) {
5659 const GO gblRow = rowMap.getGlobalElement (exportLIDs_raw[i]);
5660 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
5661 Kokkos::atomic_add (&errCountView(), ONE);
5662 numPacketsPerLID_raw[i] = 0;
5665 const size_t numEnt = this->getNumEntriesInGlobalRow (gblRow);
5666 numPacketsPerLID_raw[i] = numEnt;
5667 curTotalNumPackets += numEnt;
5673 std::ostringstream os;
5674 os << *prefix <<
"totalNumPackets=" << totalNumPackets << endl;
5675 std::cerr << os.str();
5677 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5678 (errCount != 0, std::logic_error,
"totalNumPackets count encountered "
5679 "one or more errors! errCount = " << errCount
5680 <<
", totalNumPackets = " << totalNumPackets <<
".");
5684 exports.resize (totalNumPackets);
5686 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5687 (! this->supportsRowViews (), std::logic_error,
5688 "this->supportsRowViews() returns false; this should never happen. "
5689 "Please report this bug to the Tpetra developers.");
5695 std::ostringstream os;
5696 os << *prefix <<
"Pack into exports" << endl;
5697 std::cerr << os.str();
5702 GO*
const exports_raw = exports.getRawPtr ();
5704 Kokkos::parallel_scan (
"Tpetra::CrsGraph::pack: pack from views",
5705 inputRange, [=, &prefix]
5706 (
const LO i,
size_t& exportsOffset,
const bool final) {
5707 const size_t curOffset = exportsOffset;
5708 const GO gblRow = rowMap.getGlobalElement (exportLIDs_raw[i]);
5709 const RowInfo rowInfo =
5710 this->getRowInfoFromGlobalRowIndex (gblRow);
5712 using TDO = Tpetra::Details::OrdinalTraits<size_t>;
5713 if (rowInfo.localRow == TDO::invalid ()) {
5715 std::ostringstream os;
5716 os << *prefix <<
": INVALID rowInfo: i=" << i
5717 <<
", lclRow=" << exportLIDs_raw[i] << endl;
5718 std::cerr << os.str();
5720 Kokkos::atomic_add (&errCountView(), ONE);
5722 else if (curOffset + rowInfo.numEntries > totalNumPackets) {
5724 std::ostringstream os;
5725 os << *prefix <<
": UH OH! For i=" << i <<
", lclRow="
5726 << exportLIDs_raw[i] <<
", gblRow=" << gblRow <<
", curOffset "
5727 "(= " << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5728 <<
") > totalNumPackets (= " << totalNumPackets <<
")."
5730 std::cerr << os.str();
5732 Kokkos::atomic_add (&errCountView(), ONE);
5735 const LO numEnt =
static_cast<LO
> (rowInfo.numEntries);
5736 if (this->isLocallyIndexed ()) {
5737 auto lclColInds = getLocalIndsViewHost (rowInfo);
5739 for (LO k = 0; k < numEnt; ++k) {
5740 const LO lclColInd = lclColInds(k);
5741 const GO gblColInd = colMapPtr->getGlobalElement (lclColInd);
5745 exports_raw[curOffset + k] = gblColInd;
5748 exportsOffset = curOffset + numEnt;
5750 else if (this->isGloballyIndexed ()) {
5751 auto gblColInds = getGlobalIndsViewHost (rowInfo);
5753 for (LO k = 0; k < numEnt; ++k) {
5754 const GO gblColInd = gblColInds(k);
5758 exports_raw[curOffset + k] = gblColInd;
5761 exportsOffset = curOffset + numEnt;
5769 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5770 (errCount != 0, std::logic_error,
"Packing encountered "
5771 "one or more errors! errCount = " << errCount
5772 <<
", totalNumPackets = " << totalNumPackets <<
".");
5775 std::ostringstream os;
5776 os << *prefix <<
"Done" << endl;
5777 std::cerr << os.str();
5781 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5783 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5784 packFillActiveNew (
const Kokkos::DualView<
const local_ordinal_type*,
5785 buffer_device_type>& exportLIDs,
5786 Kokkos::DualView<packet_type*,
5787 buffer_device_type>& exports,
5788 Kokkos::DualView<
size_t*,
5789 buffer_device_type> numPacketsPerLID,
5790 size_t& constantNumPackets)
const
5794 using GO = global_ordinal_type;
5795 using host_execution_space =
typename Kokkos::View<
size_t*,
5796 device_type>::HostMirror::execution_space;
5797 using host_device_type =
5798 Kokkos::Device<host_execution_space, Kokkos::HostSpace>;
5799 using exports_dv_type =
5800 Kokkos::DualView<packet_type*, buffer_device_type>;
5801 const char tfecfFuncName[] =
"packFillActiveNew: ";
5802 const bool verbose = verbose_;
5804 const auto numExportLIDs = exportLIDs.extent (0);
5805 std::unique_ptr<std::string> prefix;
5807 prefix = this->
createPrefix(
"CrsGraph",
"packFillActiveNew");
5808 std::ostringstream os;
5809 os << *prefix <<
"numExportLIDs: " << numExportLIDs
5810 <<
", numPacketsPerLID.extent(0): "
5811 << numPacketsPerLID.extent(0) << endl;
5812 std::cerr << os.str();
5814 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5815 (numExportLIDs != numPacketsPerLID.extent (0), std::runtime_error,
5816 "exportLIDs.extent(0) = " << numExportLIDs
5817 <<
" != numPacketsPerLID.extent(0) = "
5818 << numPacketsPerLID.extent (0) <<
".");
5819 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
5820 auto exportLIDs_h = exportLIDs.view_host ();
5822 const map_type& rowMap = * (this->getRowMap ());
5823 const map_type*
const colMapPtr = this->colMap_.getRawPtr ();
5824 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5825 (this->isLocallyIndexed () && colMapPtr ==
nullptr, std::logic_error,
5826 "This graph claims to be locally indexed, but its column Map is nullptr. "
5827 "This should never happen. Please report this bug to the Tpetra "
5831 constantNumPackets = 0;
5833 numPacketsPerLID.clear_sync_state ();
5834 numPacketsPerLID.modify_host ();
5835 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
5842 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
5843 range_type inputRange (0, numExportLIDs);
5844 size_t totalNumPackets = 0;
5845 size_t errCount = 0;
5848 Kokkos::View<size_t, host_device_type> errCountView (&errCount);
5849 constexpr
size_t ONE = 1;
5852 std::ostringstream os;
5853 os << *prefix <<
"Compute totalNumPackets" << endl;
5854 std::cerr << os.str ();
5857 execute_sync_host_uvm_access();
5858 totalNumPackets = 0;
5859 for (
size_t i=0; i<numExportLIDs; ++i) {
5860 const LO lclRow = exportLIDs_h[i];
5861 const GO gblRow = rowMap.getGlobalElement (lclRow);
5862 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
5864 std::ostringstream os;
5865 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5866 <<
" not in row Map on this process" << endl;
5867 std::cerr << os.str();
5869 Kokkos::atomic_add (&errCountView(), ONE);
5870 numPacketsPerLID_h(i) = 0;
5873 const size_t numEnt = this->getNumEntriesInGlobalRow (gblRow);
5874 numPacketsPerLID_h(i) = numEnt;
5875 totalNumPackets += numEnt;
5880 std::ostringstream os;
5881 os << *prefix <<
"totalNumPackets: " << totalNumPackets
5882 <<
", errCount: " << errCount << endl;
5883 std::cerr << os.str ();
5885 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5886 (errCount != 0, std::logic_error,
"totalNumPackets count encountered "
5887 "one or more errors! totalNumPackets: " << totalNumPackets
5888 <<
", errCount: " << errCount <<
".");
5891 if (
size_t(exports.extent (0)) < totalNumPackets) {
5893 exports = exports_dv_type (
"exports", totalNumPackets);
5896 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5897 (! this->supportsRowViews (), std::logic_error,
5898 "this->supportsRowViews() returns false; this should never happen. "
5899 "Please report this bug to the Tpetra developers.");
5905 std::ostringstream os;
5906 os << *prefix <<
"Pack into exports buffer" << endl;
5907 std::cerr << os.str();
5910 exports.clear_sync_state ();
5911 exports.modify_host ();
5912 auto exports_h = exports.view_host ();
5918 if(isLocallyIndexed())
5919 lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
5920 else if(isGloballyIndexed())
5921 gblInds_wdv.getHostView(Access::ReadOnly);
5924 Kokkos::parallel_scan
5925 (
"Tpetra::CrsGraph::packFillActiveNew: Pack exports",
5926 inputRange, [=, &prefix]
5927 (
const LO i,
size_t& exportsOffset,
const bool final) {
5928 const size_t curOffset = exportsOffset;
5929 const LO lclRow = exportLIDs_h(i);
5930 const GO gblRow = rowMap.getGlobalElement (lclRow);
5931 if (gblRow == Details::OrdinalTraits<GO>::invalid ()) {
5933 std::ostringstream os;
5934 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5935 <<
" not in row Map on this process" << endl;
5936 std::cerr << os.str();
5938 Kokkos::atomic_add (&errCountView(), ONE);
5942 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (gblRow);
5943 if (rowInfo.localRow == Details::OrdinalTraits<size_t>::invalid ()) {
5945 std::ostringstream os;
5946 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5947 <<
", gblRow=" << gblRow <<
": invalid rowInfo"
5949 std::cerr << os.str();
5951 Kokkos::atomic_add (&errCountView(), ONE);
5955 if (curOffset + rowInfo.numEntries > totalNumPackets) {
5957 std::ostringstream os;
5958 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5959 <<
", gblRow=" << gblRow <<
", curOffset (= "
5960 << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5961 <<
") > totalNumPackets (= " << totalNumPackets
5963 std::cerr << os.str();
5965 Kokkos::atomic_add (&errCountView(), ONE);
5969 const LO numEnt =
static_cast<LO
> (rowInfo.numEntries);
5970 if (this->isLocallyIndexed ()) {
5971 auto lclColInds = getLocalIndsViewHost(rowInfo);
5973 for (LO k = 0; k < numEnt; ++k) {
5974 const LO lclColInd = lclColInds(k);
5975 const GO gblColInd = colMapPtr->getGlobalElement (lclColInd);
5979 exports_h(curOffset + k) = gblColInd;
5982 exportsOffset = curOffset + numEnt;
5984 else if (this->isGloballyIndexed ()) {
5985 auto gblColInds = getGlobalIndsViewHost(rowInfo);
5987 for (LO k = 0; k < numEnt; ++k) {
5988 const GO gblColInd = gblColInds(k);
5992 exports_h(curOffset + k) = gblColInd;
5995 exportsOffset = curOffset + numEnt;
6009 std::ostringstream os;
6010 os << *prefix <<
"errCount=" << errCount <<
"; Done" << endl;
6011 std::cerr << os.str();
6015 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6021 Kokkos::DualView<packet_type*,
6023 Kokkos::DualView<
size_t*,
6032 const char tfecfFuncName[] =
"unpackAndCombine";
6034 ProfilingRegion regionCGC(
"Tpetra::CrsGraph::unpackAndCombine");
6035 const bool verbose = verbose_;
6037 std::unique_ptr<std::string> prefix;
6039 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
6040 std::ostringstream os;
6041 os << *prefix <<
"Start" << endl;
6042 std::cerr << os.str ();
6045 auto padding = computeCrsPaddingForImports(
6046 importLIDs, imports, numPacketsPerLID, verbose);
6047 applyCrsPadding(*padding, verbose);
6049 std::ostringstream os;
6050 os << *prefix <<
"Done computing & applying padding" << endl;
6051 std::cerr << os.str ();
6072 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6073 (importLIDs.extent (0) != numPacketsPerLID.extent (0),
6074 std::runtime_error,
": importLIDs.extent(0) = "
6075 << importLIDs.extent (0) <<
" != numPacketsPerLID.extent(0) = "
6076 << numPacketsPerLID.extent (0) <<
".");
6077 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6078 (isFillComplete (), std::runtime_error,
6079 ": Import or Export operations are not allowed on a target "
6080 "CrsGraph that is fillComplete.");
6082 const size_t numImportLIDs(importLIDs.extent(0));
6083 if (numPacketsPerLID.need_sync_host()) {
6084 numPacketsPerLID.sync_host();
6086 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
6087 if (imports.need_sync_host()) {
6088 imports.sync_host();
6090 auto imports_h = imports.view_host();
6091 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
6092 auto importLIDs_h = importLIDs.view_host();
6095 Teuchos::Array<LO> lclColInds;
6096 if (isLocallyIndexed()) {
6098 std::ostringstream os;
6099 os << *prefix <<
"Preallocate local indices scratch" << endl;
6100 std::cerr << os.str();
6102 size_t maxNumInserts = 0;
6103 for (
size_t i = 0; i < numImportLIDs; ++i) {
6104 maxNumInserts = std::max (maxNumInserts, numPacketsPerLID_h[i]);
6107 std::ostringstream os;
6108 os << *prefix <<
"Local indices scratch size: "
6109 << maxNumInserts << endl;
6110 std::cerr << os.str();
6112 lclColInds.resize (maxNumInserts);
6116 std::ostringstream os;
6118 if (isGloballyIndexed()) {
6119 os <<
"Graph is globally indexed";
6122 os <<
"Graph is neither locally nor globally indexed";
6125 std::cerr << os.str();
6129 TEUCHOS_ASSERT( ! rowMap_.is_null() );
6133 size_t importsOffset = 0;
6134 for (
size_t i = 0; i < numImportLIDs; ++i) {
6136 std::ostringstream os;
6137 os << *prefix <<
"i=" << i <<
", numImportLIDs="
6138 << numImportLIDs << endl;
6139 std::cerr << os.str();
6143 const LO lclRow = importLIDs_h[i];
6145 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6146 (gblRow == Teuchos::OrdinalTraits<GO>::invalid(),
6147 std::logic_error,
"importLIDs[i=" << i <<
"]="
6148 << lclRow <<
" is not in the row Map on the calling "
6150 const LO numEnt = numPacketsPerLID_h[i];
6151 const GO*
const gblColInds = (numEnt == 0) ?
nullptr :
6152 imports_h.data() + importsOffset;
6153 if (! isLocallyIndexed()) {
6154 insertGlobalIndicesFiltered(lclRow, gblColInds, numEnt);
6159 for (LO j = 0; j < numEnt; j++) {
6160 lclColInds[j] = colMap_->getLocalElement(gblColInds[j]);
6162 insertLocalIndices(lclRow, numEnt, lclColInds.data());
6164 importsOffset += numEnt;
6167 catch (std::exception& e) {
6168 TEUCHOS_TEST_FOR_EXCEPTION
6169 (
true, std::runtime_error,
6170 "Tpetra::CrsGraph::unpackAndCombine: Insert loop threw an "
6171 "exception: " << endl << e.what());
6175 std::ostringstream os;
6176 os << *prefix <<
"Done" << endl;
6177 std::cerr << os.str();
6181 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6186 using Teuchos::Comm;
6187 using Teuchos::null;
6188 using Teuchos::ParameterList;
6194 RCP<const map_type> rowMap, domainMap, rangeMap, colMap;
6195 RCP<import_type> importer;
6196 RCP<export_type> exporter;
6199 RCP<const Comm<int> > newComm =
6200 (newMap.is_null ()) ? null : newMap->getComm ();
6202 if (! domainMap_.is_null ()) {
6203 if (domainMap_.getRawPtr () == rowMap_.getRawPtr ()) {
6210 domainMap = domainMap_->replaceCommWithSubset (newComm);
6213 if (! rangeMap_.is_null ()) {
6214 if (rangeMap_.getRawPtr () == rowMap_.getRawPtr ()) {
6221 rangeMap = rangeMap_->replaceCommWithSubset (newComm);
6224 if (! colMap_.is_null ()) {
6225 colMap = colMap_->replaceCommWithSubset (newComm);
6229 if (! newComm.is_null ()) {
6230 RCP<ParameterList> params = this->getNonconstParameterList ();
6238 if (! rangeMap_.is_null () &&
6239 rangeMap != rowMap &&
6240 ! rangeMap->isSameAs (*rowMap)) {
6241 if (params.is_null () || ! params->isSublist (
"Export")) {
6242 exporter = rcp (
new export_type (rowMap, rangeMap));
6245 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
6246 exporter = rcp (
new export_type (rowMap, rangeMap, exportSublist));
6250 if (! domainMap_.is_null () &&
6251 domainMap != colMap &&
6252 ! domainMap->isSameAs (*colMap)) {
6253 if (params.is_null () || ! params->isSublist (
"Import")) {
6254 importer = rcp (
new import_type (domainMap, colMap));
6256 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
6257 importer = rcp (
new import_type (domainMap, colMap, importSublist));
6265 exporter_ = exporter;
6266 importer_ = importer;
6273 this->map_ = rowMap;
6274 domainMap_ = domainMap;
6275 rangeMap_ = rangeMap;
6279 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6285 using LO = LocalOrdinal;
6286 using GO = GlobalOrdinal;
6287 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6288 const bool verbose = verbose_;
6290 std::unique_ptr<std::string> prefix;
6292 prefix = this->createPrefix(
"CrsGraph",
"getLocalDiagOffsets");
6293 std::ostringstream os;
6294 os << *prefix <<
"offsets.extent(0)=" << offsets.extent(0)
6296 std::cerr << os.str();
6299 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6300 (! hasColMap (), std::runtime_error,
"The graph must have a column Map.");
6301 const LO lclNumRows =
static_cast<LO
> (this->getLocalNumRows ());
6302 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6303 (static_cast<LO> (offsets.extent (0)) < lclNumRows,
6304 std::invalid_argument,
"offsets.extent(0) = " <<
6305 offsets.extent (0) <<
" < getLocalNumRows() = " << lclNumRows <<
".");
6307 const map_type& rowMap = * (this->getRowMap ());
6308 const map_type& colMap = * (this->getColMap ());
6314 bool allRowMapDiagEntriesInColMap =
true;
6315 bool allDiagEntriesFound =
true;
6316 bool allOffsetsCorrect =
true;
6317 bool noOtherWeirdness =
true;
6318 using wrong_offsets_type = std::vector<std::pair<LO, size_t> >;
6319 wrong_offsets_type wrongOffsets(0);
6323 auto lclRowMap = rowMap.getLocalMap ();
6330 const bool sorted = this->isSorted ();
6331 if (isFillComplete ()) {
6332 auto lclGraph = this->getLocalGraphDevice ();
6333 ::Tpetra::Details::getGraphDiagOffsets (offsets, lclRowMap, lclColMap,
6335 lclGraph.entries, sorted);
6341 auto offsets_h = Kokkos::create_mirror_view (offsets);
6343 for (LO lclRowInd = 0; lclRowInd < lclNumRows; ++lclRowInd) {
6347 const GO gblRowInd = lclRowMap.getGlobalElement (lclRowInd);
6348 const GO gblColInd = gblRowInd;
6349 const LO lclColInd = lclColMap.getLocalElement (gblColInd);
6351 if (lclColInd == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
6352 allRowMapDiagEntriesInColMap =
false;
6353 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6356 const RowInfo rowInfo = this->getRowInfo (lclRowInd);
6357 if (static_cast<LO> (rowInfo.localRow) == lclRowInd &&
6358 rowInfo.numEntries > 0) {
6360 auto colInds = this->getLocalIndsViewHost (rowInfo);
6361 const size_t hint = 0;
6362 const size_t offset =
6363 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
6364 lclColInd, hint, sorted);
6365 offsets_h(lclRowInd) = offset;
6372 typename local_inds_dualv_type::t_host::const_type lclColInds;
6374 lclColInds = this->getLocalIndsViewHost (rowInfo);
6377 noOtherWeirdness =
false;
6380 if (noOtherWeirdness) {
6381 const size_t numEnt = lclColInds.extent (0);
6382 if (offset >= numEnt) {
6385 allOffsetsCorrect =
false;
6386 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6388 const LO actualLclColInd = lclColInds(offset);
6389 const GO actualGblColInd = lclColMap.getGlobalElement (actualLclColInd);
6390 if (actualGblColInd != gblColInd) {
6391 allOffsetsCorrect =
false;
6392 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6399 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6400 allDiagEntriesFound =
false;
6408 if (verbose && wrongOffsets.size () != 0) {
6409 std::ostringstream os;
6410 os << *prefix <<
"Wrong offsets: [";
6411 for (
size_t k = 0; k < wrongOffsets.size (); ++k) {
6412 os <<
"(" << wrongOffsets[k].first <<
","
6413 << wrongOffsets[k].second <<
")";
6414 if (k + 1 < wrongOffsets.size ()) {
6419 std::cerr << os.str();
6423 using Teuchos::reduceAll;
6425 Teuchos::RCP<const Teuchos::Comm<int> > comm = this->getComm ();
6426 const bool localSuccess =
6427 allRowMapDiagEntriesInColMap && allDiagEntriesFound && allOffsetsCorrect;
6428 const int numResults = 5;
6430 lclResults[0] = allRowMapDiagEntriesInColMap ? 1 : 0;
6431 lclResults[1] = allDiagEntriesFound ? 1 : 0;
6432 lclResults[2] = allOffsetsCorrect ? 1 : 0;
6433 lclResults[3] = noOtherWeirdness ? 1 : 0;
6436 lclResults[4] = ! localSuccess ? comm->getRank () : comm->getSize ();
6444 reduceAll<int, int> (*comm, Teuchos::REDUCE_MIN,
6445 numResults, lclResults, gblResults);
6447 if (gblResults[0] != 1 || gblResults[1] != 1 || gblResults[2] != 1
6448 || gblResults[3] != 1) {
6449 std::ostringstream os;
6450 os <<
"Issue(s) that we noticed (on Process " << gblResults[4] <<
", "
6451 "possibly among others): " << endl;
6452 if (gblResults[0] == 0) {
6453 os <<
" - The column Map does not contain at least one diagonal entry "
6454 "of the graph." << endl;
6456 if (gblResults[1] == 0) {
6457 os <<
" - On one or more processes, some row does not contain a "
6458 "diagonal entry." << endl;
6460 if (gblResults[2] == 0) {
6461 os <<
" - On one or more processes, some offsets are incorrect."
6464 if (gblResults[3] == 0) {
6465 os <<
" - One or more processes had some other error."
6468 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
6473 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6479 const char tfecfFuncName[] =
"getLocalOffRankOffsets: ";
6480 const bool verbose = verbose_;
6482 std::unique_ptr<std::string> prefix;
6484 prefix = this->createPrefix(
"CrsGraph",
"getLocalOffRankOffsets");
6485 std::ostringstream os;
6486 os << *prefix <<
"offsets.extent(0)=" << offsets.extent(0)
6488 std::cerr << os.str();
6491 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6492 (! hasColMap (), std::runtime_error,
"The graph must have a column Map.");
6495 const size_t lclNumRows = this->getLocalNumRows ();
6497 if (haveLocalOffRankOffsets_ && k_offRankOffsets_.extent(0) == lclNumRows+1) {
6498 offsets = k_offRankOffsets_;
6501 haveLocalOffRankOffsets_ =
false;
6503 const map_type& colMap = * (this->getColMap ());
6504 const map_type& domMap = * (this->getDomainMap ());
6515 TEUCHOS_ASSERT(this->isSorted ());
6516 if (isFillComplete ()) {
6517 k_offRankOffsets_ = offset_device_view_type(Kokkos::ViewAllocateWithoutInitializing(
"offRankOffset"), lclNumRows+1);
6518 auto lclGraph = this->getLocalGraphDevice ();
6519 ::Tpetra::Details::getGraphOffRankOffsets (k_offRankOffsets_,
6520 lclColMap, lclDomMap,
6522 offsets = k_offRankOffsets_;
6523 haveLocalOffRankOffsets_ =
true;
6525 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6526 (
true, std::logic_error,
"Can't get off-rank offsets for non-fill-complete graph");
6548 template<
class DeviceType,
6549 const bool memSpaceIsHostSpace =
6550 std::is_same<
typename DeviceType::memory_space,
6551 Kokkos::HostSpace>::value>
6552 struct HelpGetLocalDiagOffsets {};
6554 template<
class DeviceType>
6555 struct HelpGetLocalDiagOffsets<DeviceType, true> {
6556 typedef DeviceType device_type;
6557 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6558 Kokkos::MemoryUnmanaged> device_offsets_type;
6559 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6560 Kokkos::MemoryUnmanaged> host_offsets_type;
6562 static device_offsets_type
6563 getDeviceOffsets (
const host_offsets_type& hostOffsets)
6571 copyBackIfNeeded (
const host_offsets_type& ,
6572 const device_offsets_type& )
6576 template<
class DeviceType>
6577 struct HelpGetLocalDiagOffsets<DeviceType, false> {
6578 typedef DeviceType device_type;
6582 typedef Kokkos::View<size_t*, device_type> device_offsets_type;
6583 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6584 Kokkos::MemoryUnmanaged> host_offsets_type;
6586 static device_offsets_type
6587 getDeviceOffsets (
const host_offsets_type& hostOffsets)
6591 return device_offsets_type (
"offsets", hostOffsets.extent (0));
6595 copyBackIfNeeded (
const host_offsets_type& hostOffsets,
6596 const device_offsets_type& deviceOffsets)
6605 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6610 typedef LocalOrdinal LO;
6611 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6612 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6613 (! this->hasColMap (), std::runtime_error,
6614 "The graph does not yet have a column Map.");
6615 const LO myNumRows =
static_cast<LO
> (this->getLocalNumRows ());
6616 if (static_cast<LO> (offsets.size ()) != myNumRows) {
6620 offsets.resize (myNumRows);
6632 typedef HelpGetLocalDiagOffsets<device_type> helper_type;
6633 typedef typename helper_type::host_offsets_type host_offsets_type;
6635 host_offsets_type hostOffsets (offsets.getRawPtr (), myNumRows);
6637 auto deviceOffsets = helper_type::getDeviceOffsets (hostOffsets);
6639 this->getLocalDiagOffsets (deviceOffsets);
6640 helper_type::copyBackIfNeeded (hostOffsets, deviceOffsets);
6643 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6650 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6654 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& rowTransfer,
6655 const Teuchos::RCP<const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node> > & domainTransfer,
6656 const Teuchos::RCP<const map_type>& domainMap,
6657 const Teuchos::RCP<const map_type>& rangeMap,
6658 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
6664 using Teuchos::ArrayRCP;
6665 using Teuchos::ArrayView;
6666 using Teuchos::Comm;
6667 using Teuchos::ParameterList;
6670 #ifdef HAVE_TPETRA_MMM_TIMINGS
6672 using Teuchos::TimeMonitor;
6675 using LO = LocalOrdinal;
6676 using GO = GlobalOrdinal;
6677 using NT = node_type;
6681 const char* prefix =
"Tpetra::CrsGraph::transferAndFillComplete: ";
6683 #ifdef HAVE_TPETRA_MMM_TIMINGS
6685 if(!params.is_null()) label = params->get(
"Timer Label", label);
6686 string prefix2 = string(
"Tpetra ")+ label + std::string(
": CrsGraph TAFC ");
6687 RCP<TimeMonitor> MM =
6688 rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Pack-1"))));
6696 const import_type* xferAsImport =
dynamic_cast<const import_type*
>(&rowTransfer);
6697 const export_type* xferAsExport =
dynamic_cast<const export_type*
>(&rowTransfer);
6698 TEUCHOS_TEST_FOR_EXCEPTION(
6699 xferAsImport ==
nullptr && xferAsExport ==
nullptr, std::invalid_argument,
6700 prefix <<
"The 'rowTransfer' input argument must be either an Import or "
6701 "an Export, and its template parameters must match the corresponding "
6702 "template parameters of the CrsGraph.");
6709 Teuchos::RCP<const import_type> xferDomainAsImport =
6710 Teuchos::rcp_dynamic_cast<
const import_type>(domainTransfer);
6711 Teuchos::RCP<const export_type> xferDomainAsExport =
6712 Teuchos::rcp_dynamic_cast<
const export_type>(domainTransfer);
6714 if(! domainTransfer.is_null()) {
6716 TEUCHOS_TEST_FOR_EXCEPTION(
6717 (xferDomainAsImport.is_null() && xferDomainAsExport.is_null()), std::invalid_argument,
6718 prefix <<
"The 'domainTransfer' input argument must be either an "
6719 "Import or an Export, and its template parameters must match the "
6720 "corresponding template parameters of the CrsGraph.");
6722 TEUCHOS_TEST_FOR_EXCEPTION(
6723 ( xferAsImport !=
nullptr || ! xferDomainAsImport.is_null() ) &&
6724 (( xferAsImport !=
nullptr && xferDomainAsImport.is_null() ) ||
6725 ( xferAsImport ==
nullptr && ! xferDomainAsImport.is_null() )), std::invalid_argument,
6726 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6727 "must be of the same type (either Import or Export).");
6729 TEUCHOS_TEST_FOR_EXCEPTION(
6730 ( xferAsExport !=
nullptr || ! xferDomainAsExport.is_null() ) &&
6731 (( xferAsExport !=
nullptr && xferDomainAsExport.is_null() ) ||
6732 ( xferAsExport ==
nullptr && ! xferDomainAsExport.is_null() )), std::invalid_argument,
6733 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6734 "must be of the same type (either Import or Export).");
6741 const bool communication_needed = rowTransfer.getSourceMap()->isDistributed();
6747 bool reverseMode =
false;
6748 bool restrictComm =
false;
6749 RCP<ParameterList> graphparams;
6750 if (! params.is_null()) {
6751 reverseMode = params->get(
"Reverse Mode", reverseMode);
6752 restrictComm = params->get(
"Restrict Communicator", restrictComm);
6753 graphparams = sublist(params,
"CrsGraph");
6758 RCP<const map_type> MyRowMap = reverseMode ?
6759 rowTransfer.getSourceMap() : rowTransfer.getTargetMap();
6760 RCP<const map_type> MyColMap;
6761 RCP<const map_type> MyDomainMap = ! domainMap.is_null() ? domainMap : getDomainMap();
6762 RCP<const map_type> MyRangeMap = ! rangeMap.is_null() ? rangeMap : getRangeMap();
6763 RCP<const map_type> BaseRowMap = MyRowMap;
6764 RCP<const map_type> BaseDomainMap = MyDomainMap;
6772 if (! destGraph.is_null()) {
6783 const bool NewFlag =
6784 ! destGraph->isLocallyIndexed() && ! destGraph->isGloballyIndexed();
6785 TEUCHOS_TEST_FOR_EXCEPTION(! NewFlag, std::invalid_argument,
6786 prefix <<
"The input argument 'destGraph' is only allowed to be nonnull, "
6787 "if its graph is empty (neither locally nor globally indexed).");
6796 TEUCHOS_TEST_FOR_EXCEPTION(
6797 ! destGraph->getRowMap()->isSameAs(*MyRowMap), std::invalid_argument,
6798 prefix <<
"The (row) Map of the input argument 'destGraph' is not the "
6799 "same as the (row) Map specified by the input argument 'rowTransfer'.");
6801 TEUCHOS_TEST_FOR_EXCEPTION(
6802 ! destGraph->checkSizes(*
this), std::invalid_argument,
6803 prefix <<
"You provided a nonnull destination graph, but checkSizes() "
6804 "indicates that it is not a legal legal target for redistribution from "
6805 "the source graph (*this). This may mean that they do not have the "
6806 "same dimensions.");
6820 TEUCHOS_TEST_FOR_EXCEPTION(
6821 ! (reverseMode || getRowMap()->isSameAs(*rowTransfer.getSourceMap())),
6822 std::invalid_argument, prefix <<
6823 "rowTransfer->getSourceMap() must match this->getRowMap() in forward mode.");
6825 TEUCHOS_TEST_FOR_EXCEPTION(
6826 ! (! reverseMode || getRowMap()->isSameAs(*rowTransfer.getTargetMap())),
6827 std::invalid_argument, prefix <<
6828 "rowTransfer->getTargetMap() must match this->getRowMap() in reverse mode.");
6831 TEUCHOS_TEST_FOR_EXCEPTION(
6832 ! xferDomainAsImport.is_null() && ! xferDomainAsImport->getTargetMap()->isSameAs(*domainMap),
6833 std::invalid_argument,
6834 prefix <<
"The target map of the 'domainTransfer' input argument must be "
6835 "the same as the rebalanced domain map 'domainMap'");
6837 TEUCHOS_TEST_FOR_EXCEPTION(
6838 ! xferDomainAsExport.is_null() && ! xferDomainAsExport->getSourceMap()->isSameAs(*domainMap),
6839 std::invalid_argument,
6840 prefix <<
"The source map of the 'domainTransfer' input argument must be "
6841 "the same as the rebalanced domain map 'domainMap'");
6854 const size_t NumSameIDs = rowTransfer.getNumSameIDs();
6855 ArrayView<const LO> ExportLIDs = reverseMode ?
6856 rowTransfer.getRemoteLIDs() : rowTransfer.getExportLIDs();
6857 ArrayView<const LO> RemoteLIDs = reverseMode ?
6858 rowTransfer.getExportLIDs() : rowTransfer.getRemoteLIDs();
6859 ArrayView<const LO> PermuteToLIDs = reverseMode ?
6860 rowTransfer.getPermuteFromLIDs() : rowTransfer.getPermuteToLIDs();
6861 ArrayView<const LO> PermuteFromLIDs = reverseMode ?
6862 rowTransfer.getPermuteToLIDs() : rowTransfer.getPermuteFromLIDs();
6863 Distributor& Distor = rowTransfer.getDistributor();
6866 Teuchos::Array<int> SourcePids;
6867 Teuchos::Array<int> TargetPids;
6868 int MyPID = getComm()->getRank();
6871 RCP<const map_type> ReducedRowMap, ReducedColMap,
6872 ReducedDomainMap, ReducedRangeMap;
6873 RCP<const Comm<int> > ReducedComm;
6877 if (destGraph.is_null()) {
6878 destGraph = rcp(
new this_CRS_type(MyRowMap, 0, graphparams));
6885 ReducedRowMap = MyRowMap->removeEmptyProcesses();
6886 ReducedComm = ReducedRowMap.is_null() ?
6888 ReducedRowMap->getComm();
6889 destGraph->removeEmptyProcessesInPlace(ReducedRowMap);
6891 ReducedDomainMap = MyRowMap.getRawPtr() == MyDomainMap.getRawPtr() ?
6893 MyDomainMap->replaceCommWithSubset(ReducedComm);
6894 ReducedRangeMap = MyRowMap.getRawPtr() == MyRangeMap.getRawPtr() ?
6896 MyRangeMap->replaceCommWithSubset(ReducedComm);
6899 MyRowMap = ReducedRowMap;
6900 MyDomainMap = ReducedDomainMap;
6901 MyRangeMap = ReducedRangeMap;
6904 if (! ReducedComm.is_null()) {
6905 MyPID = ReducedComm->getRank();
6912 ReducedComm = MyRowMap->getComm();
6918 #ifdef HAVE_TPETRA_MMM_TIMINGS
6920 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ImportSetup"))));
6923 RCP<const import_type> MyImporter = getImporter();
6926 bool bSameDomainMap = BaseDomainMap->isSameAs(*getDomainMap());
6928 if (! restrictComm && ! MyImporter.is_null() && bSameDomainMap ) {
6935 Import_Util::getPids(*MyImporter, SourcePids,
false);
6937 else if (restrictComm && ! MyImporter.is_null() && bSameDomainMap) {
6940 ivector_type SourceDomain_pids(getDomainMap(),
true);
6941 ivector_type SourceCol_pids(getColMap());
6943 SourceDomain_pids.putScalar(MyPID);
6945 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6946 SourcePids.resize(getColMap()->getLocalNumElements());
6947 SourceCol_pids.get1dCopy(SourcePids());
6949 else if (MyImporter.is_null() && bSameDomainMap) {
6951 SourcePids.resize(getColMap()->getLocalNumElements());
6952 SourcePids.assign(getColMap()->getLocalNumElements(), MyPID);
6954 else if ( ! MyImporter.is_null() &&
6955 ! domainTransfer.is_null() ) {
6962 ivector_type TargetDomain_pids(domainMap);
6963 TargetDomain_pids.putScalar(MyPID);
6966 ivector_type SourceDomain_pids(getDomainMap());
6969 ivector_type SourceCol_pids(getColMap());
6971 if (! reverseMode && ! xferDomainAsImport.is_null() ) {
6972 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6974 else if (reverseMode && ! xferDomainAsExport.is_null() ) {
6975 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6977 else if (! reverseMode && ! xferDomainAsExport.is_null() ) {
6978 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6980 else if (reverseMode && ! xferDomainAsImport.is_null() ) {
6981 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6984 TEUCHOS_TEST_FOR_EXCEPTION(
6985 true, std::logic_error,
6986 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6988 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6989 SourcePids.resize(getColMap()->getLocalNumElements());
6990 SourceCol_pids.get1dCopy(SourcePids());
6992 else if (BaseDomainMap->isSameAs(*BaseRowMap) &&
6993 getDomainMap()->isSameAs(*getRowMap())) {
6995 ivector_type TargetRow_pids(domainMap);
6996 ivector_type SourceRow_pids(getRowMap());
6997 ivector_type SourceCol_pids(getColMap());
6999 TargetRow_pids.putScalar(MyPID);
7000 if (! reverseMode && xferAsImport !=
nullptr) {
7001 SourceRow_pids.doExport(TargetRow_pids, *xferAsImport,
INSERT);
7003 else if (reverseMode && xferAsExport !=
nullptr) {
7004 SourceRow_pids.doExport(TargetRow_pids, *xferAsExport,
INSERT);
7006 else if (! reverseMode && xferAsExport !=
nullptr) {
7007 SourceRow_pids.doImport(TargetRow_pids, *xferAsExport,
INSERT);
7009 else if (reverseMode && xferAsImport !=
nullptr) {
7010 SourceRow_pids.doImport(TargetRow_pids, *xferAsImport,
INSERT);
7013 TEUCHOS_TEST_FOR_EXCEPTION(
7014 true, std::logic_error,
7015 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
7017 SourceCol_pids.doImport(SourceRow_pids, *MyImporter,
INSERT);
7018 SourcePids.resize(getColMap()->getLocalNumElements());
7019 SourceCol_pids.get1dCopy(SourcePids());
7022 TEUCHOS_TEST_FOR_EXCEPTION(
7023 true, std::invalid_argument,
7024 prefix <<
"This method only allows either domainMap == getDomainMap(), "
7025 "or (domainMap == rowTransfer.getTargetMap() and getDomainMap() == getRowMap()).");
7029 size_t constantNumPackets = destGraph->constantNumberOfPackets();
7030 if (constantNumPackets == 0) {
7031 destGraph->reallocArraysForNumPacketsPerLid(ExportLIDs.size(),
7039 const size_t rbufLen = RemoteLIDs.size() * constantNumPackets;
7040 destGraph->reallocImportsIfNeeded(rbufLen,
false,
nullptr);
7045 destGraph->numExportPacketsPerLID_.modify_host();
7046 Teuchos::ArrayView<size_t> numExportPacketsPerLID =
7051 numExportPacketsPerLID, ExportLIDs,
7052 SourcePids, constantNumPackets);
7056 #ifdef HAVE_TPETRA_MMM_TIMINGS
7058 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Transfer"))));
7061 if (communication_needed) {
7063 if (constantNumPackets == 0) {
7067 destGraph->numExportPacketsPerLID_.sync_host();
7068 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
7070 destGraph->numImportPacketsPerLID_.sync_host();
7071 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
7074 Distor.doReversePostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
7075 destGraph->numImportPacketsPerLID_.view_host());
7076 size_t totalImportPackets = 0;
7078 totalImportPackets += numImportPacketsPerLID[i];
7083 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
7084 destGraph->imports_.modify_host();
7085 auto hostImports = destGraph->imports_.view_host();
7088 destGraph->exports_.sync_host();
7089 auto hostExports = destGraph->exports_.view_host();
7090 Distor.doReversePostsAndWaits(hostExports,
7091 numExportPacketsPerLID,
7093 numImportPacketsPerLID);
7096 destGraph->imports_.modify_host();
7097 auto hostImports = destGraph->imports_.view_host();
7100 destGraph->exports_.sync_host();
7101 auto hostExports = destGraph->exports_.view_host();
7102 Distor.doReversePostsAndWaits(hostExports,
7108 if (constantNumPackets == 0) {
7112 destGraph->numExportPacketsPerLID_.sync_host();
7113 destGraph->numImportPacketsPerLID_.sync_host();
7114 Distor.doPostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
7115 destGraph->numImportPacketsPerLID_.view_host());
7117 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
7119 size_t totalImportPackets = 0;
7121 totalImportPackets += numImportPacketsPerLID[i];
7126 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
7127 destGraph->imports_.modify_host();
7128 auto hostImports = destGraph->imports_.view_host();
7131 destGraph->exports_.sync_host();
7132 auto hostExports = destGraph->exports_.view_host();
7133 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
7135 Distor.doPostsAndWaits(hostExports, numExportPacketsPerLID, hostImports, numImportPacketsPerLID);
7138 destGraph->imports_.modify_host();
7139 auto hostImports = destGraph->imports_.view_host();
7142 destGraph->exports_.sync_host();
7143 auto hostExports = destGraph->exports_.view_host();
7144 Distor.doPostsAndWaits(hostExports, constantNumPackets, hostImports);
7153 #ifdef HAVE_TPETRA_MMM_TIMINGS
7155 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-1"))));
7159 destGraph->numImportPacketsPerLID_.sync_host();
7160 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
7162 destGraph->imports_.sync_host();
7163 Teuchos::ArrayView<const packet_type> hostImports =
7167 numImportPacketsPerLID,
7168 constantNumPackets,
INSERT,
7169 NumSameIDs, PermuteToLIDs, PermuteFromLIDs);
7170 size_t N = BaseRowMap->getLocalNumElements();
7173 ArrayRCP<size_t> CSR_rowptr(N+1);
7174 ArrayRCP<GO> CSR_colind_GID;
7175 ArrayRCP<LO> CSR_colind_LID;
7176 CSR_colind_GID.resize(mynnz);
7180 if (
typeid(LO) ==
typeid(GO)) {
7181 CSR_colind_LID = Teuchos::arcp_reinterpret_cast<LO>(CSR_colind_GID);
7184 CSR_colind_LID.resize(mynnz);
7193 numImportPacketsPerLID, constantNumPackets,
7194 INSERT, NumSameIDs, PermuteToLIDs,
7195 PermuteFromLIDs, N, mynnz, MyPID,
7196 CSR_rowptr(), CSR_colind_GID(),
7197 SourcePids(), TargetPids);
7202 #ifdef HAVE_TPETRA_MMM_TIMINGS
7204 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-2"))));
7209 Teuchos::Array<int> RemotePids;
7210 Import_Util::lowCommunicationMakeColMapAndReindex(CSR_rowptr(),
7214 TargetPids, RemotePids,
7221 ReducedColMap = (MyRowMap.getRawPtr() == MyColMap.getRawPtr()) ?
7223 MyColMap->replaceCommWithSubset(ReducedComm);
7224 MyColMap = ReducedColMap;
7228 destGraph->replaceColMap(MyColMap);
7235 if (ReducedComm.is_null()) {
7242 if ((! reverseMode && xferAsImport !=
nullptr) ||
7243 (reverseMode && xferAsExport !=
nullptr)) {
7244 Import_Util::sortCrsEntries(CSR_rowptr(),
7247 else if ((! reverseMode && xferAsExport !=
nullptr) ||
7248 (reverseMode && xferAsImport !=
nullptr)) {
7249 Import_Util::sortAndMergeCrsEntries(CSR_rowptr(),
7251 if (CSR_rowptr[N] != mynnz) {
7252 CSR_colind_LID.resize(CSR_rowptr[N]);
7256 TEUCHOS_TEST_FOR_EXCEPTION(
7257 true, std::logic_error,
7258 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
7266 destGraph->setAllIndices(CSR_rowptr, CSR_colind_LID);
7272 Teuchos::ParameterList esfc_params;
7273 #ifdef HAVE_TPETRA_MMM_TIMINGS
7275 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"CreateImporter"))));
7277 RCP<import_type> MyImport = rcp(
new import_type(MyDomainMap, MyColMap, RemotePids));
7278 #ifdef HAVE_TPETRA_MMM_TIMINGS
7280 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ESFC"))));
7282 esfc_params.set(
"Timer Label",prefix + std::string(
"TAFC"));
7284 if(!params.is_null())
7285 esfc_params.set(
"compute global constants",params->get(
"compute global constants",
true));
7287 destGraph->expertStaticFillComplete(MyDomainMap, MyRangeMap,
7288 MyImport, Teuchos::null, rcp(&esfc_params,
false));
7292 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7297 const Teuchos::RCP<const map_type>& domainMap,
7298 const Teuchos::RCP<const map_type>& rangeMap,
7299 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7301 transferAndFillComplete(destGraph, importer, Teuchos::null, domainMap, rangeMap, params);
7304 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7310 const Teuchos::RCP<const map_type>& domainMap,
7311 const Teuchos::RCP<const map_type>& rangeMap,
7312 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7314 transferAndFillComplete(destGraph, rowImporter, Teuchos::rcpFromRef(domainImporter), domainMap, rangeMap, params);
7317 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7322 const Teuchos::RCP<const map_type>& domainMap,
7323 const Teuchos::RCP<const map_type>& rangeMap,
7324 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7326 transferAndFillComplete(destGraph, exporter, Teuchos::null, domainMap, rangeMap, params);
7329 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7335 const Teuchos::RCP<const map_type>& domainMap,
7336 const Teuchos::RCP<const map_type>& rangeMap,
7337 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7339 transferAndFillComplete(destGraph, rowExporter, Teuchos::rcpFromRef(domainExporter), domainMap, rangeMap, params);
7343 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7348 std::swap(graph.need_sync_host_uvm_access, this->need_sync_host_uvm_access);
7350 std::swap(graph.
rowMap_, this->rowMap_);
7351 std::swap(graph.
colMap_, this->colMap_);
7352 std::swap(graph.
rangeMap_, this->rangeMap_);
7353 std::swap(graph.
domainMap_, this->domainMap_);
7355 std::swap(graph.
importer_, this->importer_);
7356 std::swap(graph.
exporter_, this->exporter_);
7365 std::swap(graph.rowPtrsPacked_dev_, this->rowPtrsPacked_dev_);
7366 std::swap(graph.rowPtrsPacked_host_, this->rowPtrsPacked_host_);
7368 std::swap(graph.rowPtrsUnpacked_dev_, this->rowPtrsUnpacked_dev_);
7369 std::swap(graph.rowPtrsUnpacked_host_, this->rowPtrsUnpacked_host_);
7370 std::swap(graph.packedUnpackedRowPtrsMatch_, this->packedUnpackedRowPtrsMatch_);
7380 std::swap(graph.indicesAreAllocated_, this->indicesAreAllocated_);
7381 std::swap(graph.indicesAreLocal_, this->indicesAreLocal_);
7382 std::swap(graph.indicesAreGlobal_, this->indicesAreGlobal_);
7383 std::swap(graph.fillComplete_, this->fillComplete_);
7388 std::swap(graph.haveLocalOffRankOffsets_, this->haveLocalOffRankOffsets_);
7394 std::swap(graph.
nonlocals_, this->nonlocals_);
7398 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7403 auto compare_nonlocals = [&] (
const nonlocals_type & m1,
const nonlocals_type & m2) {
7405 output = m1.size() == m2.size() ? output :
false;
7406 for(
auto & it_m: m1)
7408 size_t key = it_m.first;
7409 output = m2.find(key) != m2.end() ? output :
false;
7412 auto v1 = m1.find(key)->second;
7413 auto v2 = m2.find(key)->second;
7417 output = v1.size() == v2.size() ? output :
false;
7418 for(
size_t i=0; output && i<v1.size(); i++)
7420 output = v1[i]==v2[i] ? output :
false;
7429 output = this->rowMap_->isSameAs( *(graph.
rowMap_) ) ? output :
false;
7430 output = this->colMap_->isSameAs( *(graph.
colMap_) ) ? output :
false;
7431 output = this->rangeMap_->isSameAs( *(graph.
rangeMap_) ) ? output :
false;
7432 output = this->domainMap_->isSameAs( *(graph.
domainMap_) ) ? output :
false;
7441 output = this->storageStatus_ == graph.
storageStatus_ ? output :
false;
7443 output = this->indicesAreAllocated_ == graph.indicesAreAllocated_ ? output :
false;
7444 output = this->indicesAreLocal_ == graph.indicesAreLocal_ ? output :
false;
7445 output = this->indicesAreGlobal_ == graph.indicesAreGlobal_ ? output :
false;
7446 output = this->fillComplete_ == graph.fillComplete_ ? output :
false;
7448 output = this->noRedundancies_ == graph.
noRedundancies_ ? output :
false;
7451 output = this->haveLocalOffRankOffsets_ == graph.haveLocalOffRankOffsets_ ? output :
false;
7456 output = compare_nonlocals(this->nonlocals_, graph.
nonlocals_) ? output :
false;
7460 output = this->k_numAllocPerRow_.extent(0) == graph.
k_numAllocPerRow_.extent(0) ? output :
false;
7461 if(output && this->k_numAllocPerRow_.extent(0) > 0)
7463 for(
size_t i=0; output && i<this->k_numAllocPerRow_.extent(0); i++)
7464 output = this->k_numAllocPerRow_(i) == graph.
k_numAllocPerRow_(i) ? output :
false;
7469 output = this->k_numRowEntries_.extent(0) == graph.
k_numRowEntries_.extent(0) ? output :
false;
7470 if(output && this->k_numRowEntries_.extent(0) > 0)
7472 for(
size_t i = 0; output && i < this->k_numRowEntries_.extent(0); i++)
7473 output = this->k_numRowEntries_(i) == graph.
k_numRowEntries_(i) ? output :
false;
7478 auto rowPtrsThis = this->getRowPtrsUnpackedHost();
7480 output = rowPtrsThis .extent(0) == rowPtrsGraph.extent(0) ? output :
false;
7481 for(
size_t i=0; output && i< rowPtrsThis.extent(0); i++)
7482 output = rowPtrsThis(i) == rowPtrsGraph(i) ? output :
false;
7486 output = this->lclIndsUnpacked_wdv.extent(0) == graph.
lclIndsUnpacked_wdv.extent(0) ? output :
false;
7487 if(output && this->lclIndsUnpacked_wdv.extent(0) > 0)
7489 auto indThis = this->lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
7491 for(
size_t i=0; output && i < indThis.extent(0); i++)
7492 output = indThis(i) == indGraph(i) ? output :
false;
7496 output = this->gblInds_wdv.extent(0) == graph.
gblInds_wdv.extent(0) ? output :
false;
7497 if(output && this->gblInds_wdv.extent(0) > 0)
7499 auto indtThis = this->gblInds_wdv.getHostView(Access::ReadOnly);
7500 auto indtGraph = graph.
gblInds_wdv.getHostView(Access::ReadOnly);
7501 for(
size_t i=0; output && i<indtThis.extent(0); i++)
7502 output = indtThis(i) == indtGraph(i) ? output :
false;
7521 output = thisLclGraph.row_map.extent(0) == graphLclGraph.row_map.extent(0)
7523 if(output && thisLclGraph.row_map.extent(0) > 0)
7525 auto lclGraph_rowmap_host_this = thisLclGraph.row_map;
7526 auto lclGraph_rowmap_host_graph = graphLclGraph.row_map;
7527 for (
size_t i=0; output && i < lclGraph_rowmap_host_this.extent(0); i++)
7528 output = lclGraph_rowmap_host_this(i) == lclGraph_rowmap_host_graph(i)
7532 output = thisLclGraph.entries.extent(0) == graphLclGraph.entries.extent(0)
7534 if(output && thisLclGraph.entries.extent(0) > 0)
7536 auto lclGraph_entries_host_this = thisLclGraph.entries;
7537 auto lclGraph_entries_host_graph = graphLclGraph.entries;
7538 for (
size_t i=0; output && i < lclGraph_entries_host_this.extent(0); i++)
7539 output = lclGraph_entries_host_this(i) == lclGraph_entries_host_graph(i)
7544 thisLclGraph.row_block_offsets.extent(0) ==
7545 graphLclGraph.row_block_offsets.extent(0) ? output :
false;
7546 if(output && thisLclGraph.row_block_offsets.extent(0) > 0)
7548 auto lclGraph_rbo_host_this = thisLclGraph.row_block_offsets;
7549 auto lclGraph_rbo_host_graph = graphLclGraph.row_block_offsets;
7550 for (
size_t i=0; output && i < lclGraph_rbo_host_this.extent(0); i++)
7551 output = lclGraph_rbo_host_this(i) == lclGraph_rbo_host_graph(i)
7573 #define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7575 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7576 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7577 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7578 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7579 CrsGraph<LO,GO,NODE>::node_type>& importer, \
7580 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7581 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7582 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7583 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7584 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7585 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7586 const Teuchos::RCP<Teuchos::ParameterList>& params);
7588 #define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7590 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7591 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7592 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7593 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7594 CrsGraph<LO,GO,NODE>::node_type>& rowImporter, \
7595 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7596 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7597 CrsGraph<LO,GO,NODE>::node_type>& domainImporter, \
7598 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7599 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7600 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7601 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7602 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7603 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7604 const Teuchos::RCP<Teuchos::ParameterList>& params);
7607 #define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7609 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7610 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7611 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7612 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7613 CrsGraph<LO,GO,NODE>::node_type>& exporter, \
7614 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7615 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7616 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7617 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7618 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7619 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7620 const Teuchos::RCP<Teuchos::ParameterList>& params);
7622 #define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7624 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7625 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7626 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7627 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7628 CrsGraph<LO,GO,NODE>::node_type>& rowExporter, \
7629 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7630 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7631 CrsGraph<LO,GO,NODE>::node_type>& domainExporter, \
7632 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7633 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7634 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7635 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7636 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7637 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7638 const Teuchos::RCP<Teuchos::ParameterList>& params);
7641 #define TPETRA_CRSGRAPH_INSTANT( LO, GO, NODE ) \
7642 template class CrsGraph<LO, GO, NODE>; \
7643 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7644 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7645 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7646 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE)
7649 #endif // TPETRA_CRSGRAPH_DEF_HPP
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
void setDomainRangeMaps(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap)
void setAllIndices(const typename local_graph_device_type::row_map_type &rowPointers, const typename local_graph_device_type::entries_type::non_const_type &columnIndices)
Set the graph's data directly, using 1-D storage.
Teuchos::RCP< const map_type > getRowMap() const override
Returns the Map that describes the row distribution in this graph.
offset_device_view_type k_offRankOffsets_
The offsets for off-rank entries.
size_t nodeMaxNumRowEntries_
Local maximum of the number of entries in each row.
bool indicesAreSorted_
Whether the graph's indices are sorted in each row, on this process.
KokkosSparse::StaticCrsGraph< local_ordinal_type, Kokkos::LayoutLeft, device_type, void, size_t > local_graph_device_type
The type of the part of the sparse graph on each MPI process.
void copyOffsets(const OutputViewType &dst, const InputViewType &src)
Copy row offsets (in a sparse graph or matrix) from src to dst. The offsets may have different types...
Teuchos::RCP< const map_type > rangeMap_
The Map describing the range of the (matrix corresponding to the) graph.
Teuchos::RCP< const map_type > getColMap() const override
Returns the Map that describes the column distribution in this graph.
local_inds_host_view_type getLocalIndicesHost() const
Get a host view of the packed column indicies.
GlobalOrdinal global_ordinal_type
The type of the graph's global indices.
local_inds_dualv_type::t_host::const_type getLocalIndsViewHost(const RowInfo &rowinfo) const
Get a const, locally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myRo...
An abstract interface for graphs accessed by rows.
Kokkos::View< const size_t *, device_type >::HostMirror k_numAllocPerRow_
The maximum number of entries to allow in each locally owned row, per row.
void getLocalOffRankOffsets(offset_device_view_type &offsets) const
Get offsets of the off-rank entries in the graph.
void insertGlobalIndicesFiltered(const local_ordinal_type lclRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Like insertGlobalIndices(), but with column Map filtering.
local_inds_dualv_type::t_host getLocalIndsViewHostNonConst(const RowInfo &rowinfo)
Get a ReadWrite locally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(m...
bool sortGhostsAssociatedWithEachProcessor_
Whether to require makeColMap() (and therefore fillComplete()) to order column Map GIDs associated wi...
size_t insertGlobalIndicesImpl(const local_ordinal_type lclRow, const global_ordinal_type inputGblColInds[], const size_t numInputInds)
Insert global indices, using an input local row index.
static KOKKOS_INLINE_FUNCTION size_t unpackValue(LO &outVal, const char inBuf[])
Unpack the given value from the given output buffer.
void resumeFill(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Resume fill operations.
bool haveGlobalConstants_
Whether all processes have computed global constants.
size_t getLocalNumRows() const override
Returns the number of graph rows owned on the calling node.
void expertStaticFillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< const import_type > &importer=Teuchos::null, const Teuchos::RCP< const export_type > &exporter=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Perform a fillComplete on a graph that already has data, via setAllIndices().
Teuchos::RCP< const import_type > getImporter() const override
Returns the importer associated with this graph.
void getLocalDiagOffsets(const Kokkos::View< size_t *, device_type, Kokkos::MemoryUnmanaged > &offsets) const
Get offsets of the diagonal entries in the graph.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
void insertGlobalIndices(const global_ordinal_type globalRow, const Teuchos::ArrayView< const global_ordinal_type > &indices)
Insert global indices into the graph.
size_t getNumEntriesInLocalRow(local_ordinal_type localRow) const override
Get the number of entries in the given row (local index).
size_t getLocalAllocationSize() const
The local number of indices allocated for the graph, over all rows on the calling (MPI) process...
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Default parameter list suitable for validation.
Declaration of a function that prints strings from each process.
void computeLocalConstants()
Compute local constants, if they have not yet been computed.
void packCrsGraphWithOwningPIDs(const CrsGraph< LO, GO, NT > &sourceGraph, Kokkos::DualView< typename CrsGraph< LO, GO, NT >::packet_type *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exports_dv, const Teuchos::ArrayView< size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &exportLIDs, const Teuchos::ArrayView< const int > &sourcePIDs, size_t &constantNumPackets)
Pack specified entries of the given local sparse graph for communication.
typename row_graph_type::local_inds_device_view_type local_inds_device_view_type
The Kokkos::View type for views of local ordinals on device and host.
bool isIdenticalTo(const CrsGraph< LocalOrdinal, GlobalOrdinal, Node > &graph) const
Create a cloned CrsGraph for a different Node type.
bool isMerged() const
Whether duplicate column indices in each row have been merged.
virtual bool checkSizes(const SrcDistObject &source) override
Compare the source and target (this) objects for compatibility.
Teuchos::RCP< const map_type > getDomainMap() const override
Returns the Map associated with the domain of this graph.
size_t getGlobalMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, over all processes in the graph's communicator...
Declare and define Tpetra::Details::copyOffsets, an implementation detail of Tpetra (in particular...
bool noRedundancies_
Whether the graph's indices are non-redundant (merged) in each row, on this process.
global_inds_dualv_type::t_dev::const_type getGlobalIndsViewDevice(const RowInfo &rowinfo) const
Get a const, globally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myR...
void padCrsArrays(const RowPtr &rowPtrBeg, const RowPtr &rowPtrEnd, Indices &indices_wdv, const Padding &padding, const int my_rank, const bool verbose)
Determine if the row pointers and indices arrays need to be resized to accommodate new entries...
OffsetsViewType::non_const_value_type computeOffsetsFromConstantCount(const OffsetsViewType &ptr, const CountType count)
Compute offsets from a constant count.
void replaceRangeMap(const Teuchos::RCP< const map_type > &newRangeMap)
Replace the current Range Map with the given objects.
void packCrsGraph(const CrsGraph< LO, GO, NT > &sourceGraph, Teuchos::Array< typename CrsGraph< LO, GO, NT >::packet_type > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &exportLIDs, size_t &constantNumPackets)
Pack specified entries of the given local sparse graph for communication.
row_ptrs_device_view_type getLocalRowPtrsDevice() const
Get a device view of the packed row offsets.
global_inds_dualv_type::t_host::const_type getGlobalIndsViewHost(const RowInfo &rowinfo) const
Get a const, globally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myR...
const row_ptrs_host_view_type & getRowPtrsPackedHost() const
Get the packed row pointers on host. Lazily make a copy from device.
static bool debug()
Whether Tpetra is in debug mode.
size_t getNumAllocatedEntriesInGlobalRow(global_ordinal_type globalRow) const
Current number of allocated entries in the given row on the calling (MPI) process, using a global row index.
Allocation information for a locally owned row in a CrsGraph or CrsMatrix.
local_inds_wdv_type lclIndsUnpacked_wdv
Local ordinals of column indices for all rows Valid when isLocallyIndexed is true If OptimizedStorage...
void replaceRangeMapAndExporter(const Teuchos::RCP< const map_type > &newRangeMap, const Teuchos::RCP< const export_type > &newExporter)
Replace the current Range Map and Export with the given parameters.
void verbosePrintArray(std::ostream &out, const ArrayType &x, const char name[], const size_t maxNumToPrint)
Print min(x.size(), maxNumToPrint) entries of x.
bool hasColMap() const override
Whether the graph has a column Map.
bool isGloballyIndexed() const override
Whether the graph's column indices are stored as global indices.
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.
virtual void unpackAndCombine(const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &importLIDs, Kokkos::DualView< packet_type *, buffer_device_type > imports, Kokkos::DualView< size_t *, buffer_device_type > numPacketsPerLID, const size_t constantNumPackets, const CombineMode combineMode) override
Teuchos_Ordinal Array_size_type
Size type for Teuchos Array objects.
int local_ordinal_type
Default value of Scalar template parameter.
bool isStorageOptimized() const
Returns true if storage has been optimized.
bool haveLocalConstants_
Whether this process has computed local constants.
size_t findGlobalIndices(const RowInfo &rowInfo, const Teuchos::ArrayView< const global_ordinal_type > &indices, std::function< void(const size_t, const size_t, const size_t)> fun) const
Finds indices in the given row.
std::string description() const override
Return a one-line human-readable description of this object.
void sort(View &view, const size_t &size)
Convenience wrapper for std::sort for host-accessible views.
void gathervPrint(std::ostream &out, const std::string &s, const Teuchos::Comm< int > &comm)
On Process 0 in the given communicator, print strings from each process in that communicator, in rank order.
void makeColMap(Teuchos::Array< int > &remotePIDs)
Make and set the graph's column Map.
Teuchos::RCP< const export_type > getExporter() const override
Returns the exporter associated with this graph.
std::pair< size_t, std::string > makeIndicesLocal(const bool verbose=false)
Convert column indices from global to local.
size_t global_size_t
Global size_t object.
virtual void removeEmptyProcessesInPlace(const Teuchos::RCP< const map_type > &newMap) override
Remove processes owning zero rows from the Maps and their communicator.
Node node_type
This class' Kokkos Node type.
void reindexColumns(const Teuchos::RCP< const map_type > &newColMap, const Teuchos::RCP< const import_type > &newImport=Teuchos::null, const bool sortIndicesInEachRow=true)
Reindex the column indices in place, and replace the column Map. Optionally, replace the Import objec...
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
void makeImportExport(Teuchos::Array< int > &remotePIDs, const bool useRemotePIDs)
Make the Import and Export objects, if needed.
size_t sortAndMergeRowIndices(const RowInfo &rowInfo, const bool sorted, const bool merged)
Sort and merge duplicate column indices in the given row.
void insertLocalIndices(const local_ordinal_type localRow, const Teuchos::ArrayView< const local_ordinal_type > &indices)
Insert local indices into the graph.
Insert new values that don't currently exist.
bool isSorted() const
Whether graph indices in all rows are known to be sorted.
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.
void getLocalRowCopy(local_ordinal_type gblRow, nonconst_local_inds_host_view_type &gblColInds, size_t &numColInds) const override
Get a copy of the given row, using local indices.
Teuchos::RCP< const map_type > rowMap_
The Map describing the distribution of rows of the graph.
Teuchos::RCP< const import_type > importer_
The Import from the domain Map to the column Map.
size_t insertCrsIndices(typename Pointers::value_type const row, Pointers const &rowPtrs, InOutIndices &curIndices, size_t &numAssigned, InIndices const &newIndices, std::function< void(const size_t, const size_t, const size_t)> cb=std::function< void(const size_t, const size_t, const size_t)>())
Insert new indices in to current list of indices.
num_row_entries_type k_numRowEntries_
The number of local entries in each locally owned row.
local_inds_device_view_type getLocalIndicesDevice() const
Get a device view of the packed column indicies.
Teuchos::RCP< const map_type > domainMap_
The Map describing the domain of the (matrix corresponding to the) graph.
OffsetType convertColumnIndicesFromGlobalToLocal(const Kokkos::View< LO *, DT > &lclColInds, const Kokkos::View< const GO *, DT > &gblColInds, const Kokkos::View< const OffsetType *, DT > &ptr, const LocalMap< LO, GO, DT > &lclColMap, const Kokkos::View< const NumEntType *, DT > &numRowEnt)
Convert a CrsGraph's global column indices into local column indices.
global_size_t getGlobalNumRows() const override
Returns the number of global rows in the graph.
global_ordinal_type getGlobalElement(local_ordinal_type localIndex) const
The global index corresponding to the given local index.
bool isNodeLocalElement(local_ordinal_type localIndex) const
Whether the given local index is valid for this Map on the calling process.
Functions for manipulating CRS arrays.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
void setLocallyModified()
Report that we made a local modification to its structure.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
void unpackAndCombineIntoCrsArrays(const CrsGraph< LO, GO, NT > &sourceGraph, const Teuchos::ArrayView< const LO > &importLIDs, const Teuchos::ArrayView< const typename CrsGraph< LO, GO, NT >::packet_type > &imports, const Teuchos::ArrayView< const size_t > &numPacketsPerLID, const size_t constantNumPackets, const CombineMode combineMode, const size_t numSameIDs, const Teuchos::ArrayView< const LO > &permuteToLIDs, const Teuchos::ArrayView< const LO > &permuteFromLIDs, size_t TargetNumRows, size_t TargetNumNonzeros, const int MyTargetPID, const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< GO > &CRS_colind, const Teuchos::ArrayView< const int > &SourcePids, Teuchos::Array< int > &TargetPids)
unpackAndCombineIntoCrsArrays
void checkInternalState() const
Throw an exception if the internal state is not consistent.
bool isNodeGlobalElement(global_ordinal_type globalIndex) const
Whether the given global index is owned by this Map on the calling process.
Sets up and executes a communication plan for a Tpetra DistObject.
size_t findCrsIndices(typename Pointers::value_type const row, Pointers const &rowPtrs, const size_t curNumEntries, Indices1 const &curIndices, Indices2 const &newIndices, Callback &&cb)
Finds offsets in to current list of indices.
static bool verbose()
Whether Tpetra is in verbose mode.
CombineMode
Rule for combining data in an Import or Export.
Teuchos::RCP< const export_type > exporter_
The Export from the row Map to the range Map.
void insertGlobalIndicesIntoNonownedRows(const global_ordinal_type gblRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Implementation of insertGlobalIndices for nonowned rows.
bool isFillComplete() const override
Whether fillComplete() has been called and the graph is in compute mode.
size_t getNumAllocatedEntriesInLocalRow(local_ordinal_type localRow) const
Current number of allocated entries in the given row on the calling (MPI) process, using a local row index.
void swap(CrsGraph< local_ordinal_type, global_ordinal_type, Node > &graph)
Swaps the data from *this with the data and maps from graph.
void globalAssemble()
Communicate nonlocal contributions to other processes.
RowInfo getRowInfoFromGlobalRowIndex(const global_ordinal_type gblRow) const
Get information about the locally owned row with global index gblRow.
Utility functions for packing and unpacking sparse matrix entries.
size_t getLocalNumCols() const override
Returns the number of columns connected to the locally owned rows of this graph.
size_t getLocalNumEntries() const override
The local number of entries in the graph.
Abstract base class for objects that can be the source of an Import or Export operation.
void removeLocalIndices(local_ordinal_type localRow)
Remove all graph indices from the specified local row.
LocalOrdinal local_ordinal_type
The type of the graph's local indices.
global_size_t globalNumEntries_
Global number of entries in the graph.
global_inds_wdv_type gblInds_wdv
Global ordinals of column indices for all rows.
local_inds_dualv_type::t_dev::const_type getLocalIndsViewDevice(const RowInfo &rowinfo) const
Get a const, locally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myRo...
Teuchos::RCP< const map_type > getRangeMap() const override
Returns the Map associated with the domain of this graph.
virtual void pack(const Teuchos::ArrayView< const local_ordinal_type > &exportLIDs, Teuchos::Array< global_ordinal_type > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, size_t &constantNumPackets) const override
void enableWDVTracking()
Enable WrappedDualView reference-count tracking and syncing. Call this after exiting a host-parallel ...
row_ptrs_host_view_type getLocalRowPtrsHost() const
Get a host view of the packed row offsets.
void packCrsGraphNew(const CrsGraph< LO, GO, NT > &sourceGraph, const Kokkos::DualView< const LO *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exportLIDs, const Kokkos::DualView< const int *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exportPIDs, Kokkos::DualView< typename CrsGraph< LO, GO, NT >::packet_type *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exports, Kokkos::DualView< size_t *, typename CrsGraph< LO, GO, NT >::buffer_device_type > numPacketsPerLID, size_t &constantNumPackets, const bool pack_pids)
Pack specified entries of the given local sparse graph for communication, for "new" DistObject interf...
const row_ptrs_host_view_type & getRowPtrsUnpackedHost() const
Get the unpacked row pointers on host. Lazily make a copy from device.
void replaceColMap(const Teuchos::RCP< const map_type > &newColMap)
Replace the graph's current column Map with the given Map.
global_size_t getGlobalNumCols() const override
Returns the number of global columns in the graph.
size_t getLocalMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, on this process.
RowInfo getRowInfo(const local_ordinal_type myRow) const
Get information about the locally owned row with local index myRow.
void replaceDomainMapAndImporter(const Teuchos::RCP< const map_type > &newDomainMap, const Teuchos::RCP< const import_type > &newImporter)
Replace the current domain Map and Import with the given parameters.
bool supportsRowViews() const override
Whether this class implements getLocalRowView() and getGlobalRowView() (it does). ...
typename dist_object_type::buffer_device_type buffer_device_type
Kokkos::Device specialization for communication buffers.
local_map_type getLocalMap() const
Get the LocalMap for Kokkos-Kernels.
local_inds_wdv_type lclIndsPacked_wdv
Local ordinals of column indices for all rows Valid when isLocallyIndexed is true Built during fillCo...
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
Details::EStorageStatus storageStatus_
Status of the graph's storage, when not in a fill-complete state.
size_t unpackAndCombineWithOwningPIDsCount(const CrsGraph< LO, GO, NT > &sourceGraph, const Teuchos::ArrayView< const LO > &importLIDs, const Teuchos::ArrayView< const typename CrsGraph< LO, GO, NT >::packet_type > &imports, const Teuchos::ArrayView< const size_t > &numPacketsPerLID, size_t constantNumPackets, CombineMode combineMode, size_t numSameIDs, const Teuchos::ArrayView< const LO > &permuteToLIDs, const Teuchos::ArrayView< const LO > &permuteFromLIDs)
Special version of Tpetra::Details::unpackCrsGraphAndCombine that also unpacks owning process ranks...
const row_ptrs_device_view_type & getRowPtrsPackedDevice() const
Get the packed row pointers on device.
A parallel distribution of indices over processes.
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.
const row_ptrs_device_view_type & getRowPtrsUnpackedDevice() const
Get the unpacked row pointers on device.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects...
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > ¶ms) override
Set the given list of parameters (must be nonnull).
size_t getNumEntriesInGlobalRow(global_ordinal_type globalRow) const override
Returns the current number of entries on this node in the specified global row.
void fillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Tell the graph that you are done changing its structure.
void disableWDVTracking()
Disable WrappedDualView reference-count tracking and syncing. Call this before entering a host-parall...
local_ordinal_type getLocalElement(global_ordinal_type globalIndex) const
The local index corresponding to the given global index.
void getLocalRowView(const LocalOrdinal lclRow, local_inds_host_view_type &lclColInds) const override
Get a const view of the given local row's local column indices.
typename Node::device_type device_type
This class' Kokkos device type.
bool isLocallyIndexed() const override
Whether the graph's column indices are stored as local indices.
A distributed dense vector.
Stand-alone utility functions and macros.
bool isFillActive() const
Whether resumeFill() has been called and the graph is in edit mode.
virtual void copyAndPermute(const SrcDistObject &source, const size_t numSameIDs, const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &permuteToLIDs, const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &permuteFromLIDs, const CombineMode CM) override
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
Returns the communicator.
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.
size_t insertIndices(RowInfo &rowInfo, const SLocalGlobalViews &newInds, const ELocalGlobal lg, const ELocalGlobal I)
Insert indices into the given row.
global_size_t getGlobalNumEntries() const override
Returns the global number of entries in the graph.
Declaration and definition of Tpetra::Details::getEntryOnHost.
size_t numAllocForAllRows_
The maximum number of entries to allow in each locally owned row.
local_graph_device_type getLocalGraphDevice() const
Get the local graph.
void getGlobalRowView(const global_ordinal_type gblRow, global_inds_host_view_type &gblColInds) const override
Get a const view of the given global row's global column indices.
Teuchos::RCP< const map_type > colMap_
The Map describing the distribution of columns of the graph.
global_ordinal_type getIndexBase() const override
Returns the index base for global indices for this graph.
typename local_graph_device_type::HostMirror local_graph_host_type
The type of the part of the sparse graph on each MPI process.
void replaceDomainMap(const Teuchos::RCP< const map_type > &newDomainMap)
Replace the current domain Map with the given objects.
std::unique_ptr< std::string > createPrefix(const int myRank, const char prefix[])
Create string prefix for each line of verbose output.
nonlocals_type nonlocals_
Nonlocal data given to insertGlobalIndices.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const override
Print this object to the given output stream with the given verbosity level.
void computeGlobalConstants()
Compute global constants, if they have not yet been computed.
void getGlobalRowCopy(global_ordinal_type gblRow, nonconst_global_inds_host_view_type &gblColInds, size_t &numColInds) const override
Get a copy of the given row, using global indices.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.