40 #ifndef TPETRA_CRSGRAPH_DEF_HPP
41 #define TPETRA_CRSGRAPH_DEF_HPP
50 #include "Tpetra_Details_getGraphDiagOffsets.hpp"
51 #include "Tpetra_Details_getGraphOffRankOffsets.hpp"
52 #include "Tpetra_Details_makeColMap.hpp"
56 #include "Tpetra_Distributor.hpp"
57 #include "Teuchos_SerialDenseMatrix.hpp"
58 #include "Tpetra_Vector.hpp"
61 #include "Tpetra_Details_packCrsGraph.hpp"
62 #include "Tpetra_Details_unpackCrsGraphAndCombine.hpp"
63 #include "Tpetra_Details_CrsPadding.hpp"
70 #include <type_traits>
78 template<
class MapIter>
80 verbosePrintMap(std::ostream& out,
86 using ::Tpetra::Details::Behavior;
89 out << mapName <<
": {";
90 const size_t maxNumToPrint =
92 if (maxNumToPrint == 0) {
98 const size_t numToPrint = numEnt > maxNumToPrint ?
99 maxNumToPrint : numEnt;
101 for (MapIter it = beg; it != end; ++it) {
102 out <<
"(" << (*it).first <<
", ";
106 if (count +
size_t(1) < numToPrint) {
111 if (count < numEnt) {
118 template<
class LO,
class GO,
class Node>
119 Teuchos::ArrayView<GO>
120 getRowGraphGlobalRow(
121 std::vector<GO>& gblColIndsStorage,
122 const RowGraph<LO, GO, Node>& graph,
125 size_t origNumEnt = graph.getNumEntriesInGlobalRow(gblRowInd);
126 if (gblColIndsStorage.size() < origNumEnt) {
127 gblColIndsStorage.resize(origNumEnt);
129 typename CrsGraph<LO,GO,Node>::nonconst_global_inds_host_view_type gblColInds(gblColIndsStorage.data(),
131 graph.getGlobalRowCopy(gblRowInd, gblColInds, origNumEnt);
132 Teuchos::ArrayView<GO> retval(gblColIndsStorage.data(),origNumEnt);
136 template<
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
137 class ConvertColumnIndicesFromGlobalToLocal {
139 ConvertColumnIndicesFromGlobalToLocal (const ::Kokkos::View<LO*, DT>& lclColInds,
140 const ::Kokkos::View<const GO*, DT>& gblColInds,
141 const ::Kokkos::View<const OffsetType*, DT>& ptr,
142 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
143 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt) :
144 lclColInds_ (lclColInds),
145 gblColInds_ (gblColInds),
147 lclColMap_ (lclColMap),
148 numRowEnt_ (numRowEnt)
152 operator () (
const LO& lclRow, OffsetType& curNumBad)
const
154 const OffsetType offset = ptr_(lclRow);
158 const LO numEnt =
static_cast<LO
> (numRowEnt_(lclRow));
159 for (LO j = 0; j < numEnt; ++j) {
160 const GO gid = gblColInds_(offset + j);
161 const LO lid = lclColMap_.getLocalElement (gid);
162 lclColInds_(offset + j) = lid;
163 if (lid == ::Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
170 run (const ::Kokkos::View<LO*, DT>& lclColInds,
171 const ::Kokkos::View<const GO*, DT>& gblColInds,
172 const ::Kokkos::View<const OffsetType*, DT>& ptr,
173 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
174 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt)
176 typedef ::Kokkos::RangePolicy<typename DT::execution_space, LO> range_type;
177 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> functor_type;
179 const LO lclNumRows = ptr.extent (0) == 0 ?
180 static_cast<LO
> (0) : static_cast<LO> (ptr.extent (0) - 1);
181 OffsetType numBad = 0;
183 ::Kokkos::parallel_reduce (range_type (0, lclNumRows),
184 functor_type (lclColInds, gblColInds, ptr,
185 lclColMap, numRowEnt),
191 ::Kokkos::View<LO*, DT> lclColInds_;
192 ::Kokkos::View<const GO*, DT> gblColInds_;
193 ::Kokkos::View<const OffsetType*, DT> ptr_;
195 ::Kokkos::View<const NumEntType*, DT> numRowEnt_;
214 template<
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
217 const Kokkos::View<const GO*, DT>& gblColInds,
218 const Kokkos::View<const OffsetType*, DT>& ptr,
220 const Kokkos::View<const NumEntType*, DT>& numRowEnt)
222 using Impl::ConvertColumnIndicesFromGlobalToLocal;
223 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> impl_type;
224 return impl_type::run (lclColInds, gblColInds, ptr, lclColMap, numRowEnt);
227 template<
class ViewType,
class LO>
228 class MaxDifference {
230 MaxDifference (
const ViewType& ptr) : ptr_ (ptr) {}
232 KOKKOS_INLINE_FUNCTION
void init (LO& dst)
const {
236 KOKKOS_INLINE_FUNCTION
void
237 join (LO& dst,
const LO& src)
const
239 dst = (src > dst) ? src : dst;
242 KOKKOS_INLINE_FUNCTION
void
243 operator () (
const LO lclRow, LO& maxNumEnt)
const
245 const LO numEnt =
static_cast<LO
> (ptr_(lclRow+1) - ptr_(lclRow));
246 maxNumEnt = (numEnt > maxNumEnt) ? numEnt : maxNumEnt;
249 typename ViewType::const_type ptr_;
252 template<
class ViewType,
class LO>
253 typename ViewType::non_const_value_type
254 maxDifference (
const char kernelLabel[],
258 if (lclNumRows == 0) {
261 return static_cast<LO
> (0);
264 using execution_space =
typename ViewType::execution_space;
265 using range_type = Kokkos::RangePolicy<execution_space, LO>;
267 Kokkos::parallel_reduce (kernelLabel,
268 range_type (0, lclNumRows),
269 MaxDifference<ViewType, LO> (ptr),
277 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
279 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
284 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
286 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
291 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
292 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
293 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
294 const size_t maxNumEntriesPerRow,
295 const Teuchos::RCP<Teuchos::ParameterList>& params) :
298 , numAllocForAllRows_ (maxNumEntriesPerRow)
300 const char tfecfFuncName[] =
301 "CrsGraph(rowMap,maxNumEntriesPerRow,params): ";
303 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
304 (maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid (),
305 std::invalid_argument,
"The allocation hint maxNumEntriesPerRow must be "
306 "a valid size_t value, which in this case means it must not be "
307 "Teuchos::OrdinalTraits<size_t>::invalid().");
312 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
314 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
315 const Teuchos::RCP<const map_type>& colMap,
316 const size_t maxNumEntriesPerRow,
317 const Teuchos::RCP<Teuchos::ParameterList>& params) :
321 , numAllocForAllRows_ (maxNumEntriesPerRow)
323 const char tfecfFuncName[] =
324 "CrsGraph(rowMap,colMap,maxNumEntriesPerRow,params): ";
326 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
327 maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid (),
328 std::invalid_argument,
"The allocation hint maxNumEntriesPerRow must be "
329 "a valid size_t value, which in this case means it must not be "
330 "Teuchos::OrdinalTraits<size_t>::invalid().");
336 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
338 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
339 const Teuchos::ArrayView<const size_t>& numEntPerRow,
340 const Teuchos::RCP<Teuchos::ParameterList>& params) :
343 , numAllocForAllRows_ (0)
345 const char tfecfFuncName[] =
346 "CrsGraph(rowMap,numEntPerRow,params): ";
349 const size_t lclNumRows = rowMap.is_null () ?
350 static_cast<size_t> (0) : rowMap->getLocalNumElements ();
351 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
352 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
353 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
354 <<
" != the local number of rows " << lclNumRows <<
" as specified by "
355 "the input row Map.");
358 for (
size_t r = 0; r < lclNumRows; ++r) {
359 const size_t curRowCount = numEntPerRow[r];
360 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
361 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
362 std::invalid_argument,
"numEntPerRow(" << r <<
") "
363 "specifies an invalid number of entries "
364 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
372 typedef typename out_view_type::non_const_type nc_view_type;
373 typedef Kokkos::View<
const size_t*,
374 typename nc_view_type::array_layout,
376 Kokkos::MemoryUnmanaged> in_view_type;
377 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
378 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
381 using exec_space =
typename nc_view_type::execution_space;
391 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
393 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
394 const Kokkos::DualView<const size_t*, device_type>& numEntPerRow,
395 const Teuchos::RCP<Teuchos::ParameterList>& params) :
398 , k_numAllocPerRow_ (numEntPerRow.h_view)
399 , numAllocForAllRows_ (0)
401 const char tfecfFuncName[] =
402 "CrsGraph(rowMap,numEntPerRow,params): ";
405 const size_t lclNumRows = rowMap.is_null () ?
406 static_cast<size_t> (0) : rowMap->getLocalNumElements ();
407 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
408 static_cast<size_t> (numEntPerRow.extent (0)) != lclNumRows,
409 std::invalid_argument,
"numEntPerRow has length " <<
410 numEntPerRow.extent (0) <<
" != the local number of rows " <<
411 lclNumRows <<
" as specified by " "the input row Map.");
414 for (
size_t r = 0; r < lclNumRows; ++r) {
415 const size_t curRowCount = numEntPerRow.h_view(r);
416 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
417 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
418 std::invalid_argument,
"numEntPerRow(" << r <<
") "
419 "specifies an invalid number of entries "
420 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
429 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
431 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
432 const Teuchos::RCP<const map_type>& colMap,
433 const Kokkos::DualView<const size_t*, device_type>& numEntPerRow,
434 const Teuchos::RCP<Teuchos::ParameterList>& params) :
438 , k_numAllocPerRow_ (numEntPerRow.h_view)
439 , numAllocForAllRows_ (0)
441 const char tfecfFuncName[] =
442 "CrsGraph(rowMap,colMap,numEntPerRow,params): ";
445 const size_t lclNumRows = rowMap.is_null () ?
446 static_cast<size_t> (0) : rowMap->getLocalNumElements ();
447 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
448 static_cast<size_t> (numEntPerRow.extent (0)) != lclNumRows,
449 std::invalid_argument,
"numEntPerRow has length " <<
450 numEntPerRow.extent (0) <<
" != the local number of rows " <<
451 lclNumRows <<
" as specified by " "the input row Map.");
454 for (
size_t r = 0; r < lclNumRows; ++r) {
455 const size_t curRowCount = numEntPerRow.h_view(r);
456 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
457 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
458 std::invalid_argument,
"numEntPerRow(" << r <<
") "
459 "specifies an invalid number of entries "
460 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
469 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
471 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
472 const Teuchos::RCP<const map_type>& colMap,
473 const Teuchos::ArrayView<const size_t>& numEntPerRow,
474 const Teuchos::RCP<Teuchos::ParameterList>& params) :
478 , numAllocForAllRows_ (0)
480 const char tfecfFuncName[] =
481 "CrsGraph(rowMap,colMap,numEntPerRow,params): ";
484 const size_t lclNumRows = rowMap.is_null () ?
485 static_cast<size_t> (0) : rowMap->getLocalNumElements ();
486 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
487 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
488 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
489 <<
" != the local number of rows " << lclNumRows <<
" as specified by "
490 "the input row Map.");
493 for (
size_t r = 0; r < lclNumRows; ++r) {
494 const size_t curRowCount = numEntPerRow[r];
495 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
496 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
497 std::invalid_argument,
"numEntPerRow(" << r <<
") "
498 "specifies an invalid number of entries "
499 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
507 typedef typename out_view_type::non_const_type nc_view_type;
508 typedef Kokkos::View<
const size_t*,
509 typename nc_view_type::array_layout,
511 Kokkos::MemoryUnmanaged> in_view_type;
512 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
513 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
516 using exec_space =
typename nc_view_type::execution_space;
525 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
528 const Teuchos::RCP<const map_type>& rowMap,
529 const Teuchos::RCP<Teuchos::ParameterList>& params) :
532 , colMap_(originalGraph.colMap_)
533 , numAllocForAllRows_(originalGraph.numAllocForAllRows_)
534 , storageStatus_(originalGraph.storageStatus_)
535 , indicesAreAllocated_(originalGraph.indicesAreAllocated_)
536 , indicesAreLocal_(originalGraph.indicesAreLocal_)
537 , indicesAreSorted_(originalGraph.indicesAreSorted_)
541 int numRows = rowMap->getLocalNumElements();
543 auto rowsToUse = Kokkos::pair<size_t, size_t>(0, numRows+1);
549 if (indicesAreLocal_) {
560 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
562 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
563 const Teuchos::RCP<const map_type>& colMap,
564 const typename local_graph_device_type::row_map_type& rowPointers,
565 const typename local_graph_device_type::entries_type::non_const_type& columnIndices,
566 const Teuchos::RCP<Teuchos::ParameterList>& params) :
570 , numAllocForAllRows_(0)
571 , storageStatus_(Details::STORAGE_1D_PACKED)
572 , indicesAreAllocated_(true)
573 , indicesAreLocal_(true)
576 if (! params.is_null() && params->isParameter(
"sorted") &&
577 ! params->get<
bool>(
"sorted")) {
587 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
589 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
590 const Teuchos::RCP<const map_type>& colMap,
591 const Teuchos::ArrayRCP<size_t>& rowPointers,
592 const Teuchos::ArrayRCP<LocalOrdinal> & columnIndices,
593 const Teuchos::RCP<Teuchos::ParameterList>& params) :
597 , numAllocForAllRows_ (0)
598 , storageStatus_ (Details::STORAGE_1D_PACKED)
599 , indicesAreAllocated_ (true)
600 , indicesAreLocal_ (true)
603 if (! params.is_null() && params->isParameter(
"sorted") &&
604 ! params->get<
bool>(
"sorted")) {
614 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
616 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
617 const Teuchos::RCP<const map_type>& colMap,
619 const Teuchos::RCP<Teuchos::ParameterList>& params)
628 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
631 const Teuchos::RCP<const map_type>& rowMap,
632 const Teuchos::RCP<const map_type>& colMap,
633 const Teuchos::RCP<const map_type>& domainMap,
634 const Teuchos::RCP<const map_type>& rangeMap,
635 const Teuchos::RCP<Teuchos::ParameterList>& params)
639 , numAllocForAllRows_ (0)
640 , storageStatus_ (Details::STORAGE_1D_PACKED)
641 , indicesAreAllocated_ (true)
642 , indicesAreLocal_ (true)
645 const char tfecfFuncName[] =
"CrsGraph(Kokkos::LocalStaticCrsGraph,Map,Map,Map,Map)";
647 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
648 colMap.is_null (), std::runtime_error,
649 ": The input column Map must be nonnull.");
650 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
651 k_local_graph_.numRows () != rowMap->getLocalNumElements (),
653 ": The input row Map and the input local graph need to have the same "
654 "number of rows. The row Map claims " << rowMap->getLocalNumElements ()
655 <<
" row(s), but the local graph claims " << k_local_graph_.numRows ()
665 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
667 ": cannot have 1D data structures allocated.");
669 if(! params.is_null() && params->isParameter(
"sorted") &&
670 ! params->get<
bool>(
"sorted")) {
678 rangeMap .is_null() ?
rowMap_ : rangeMap);
679 Teuchos::Array<int> remotePIDs (0);
684 this->setRowPtrs(k_local_graph_.row_map);
686 set_need_sync_host_uvm_access();
688 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
689 params->get (
"compute global constants",
true);
691 if (callComputeGlobalConstants) {
694 this->fillComplete_ =
true;
698 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
701 const Teuchos::RCP<const map_type>& rowMap,
702 const Teuchos::RCP<const map_type>& colMap,
703 const Teuchos::RCP<const map_type>& domainMap,
704 const Teuchos::RCP<const map_type>& rangeMap,
705 const Teuchos::RCP<const import_type>& importer,
706 const Teuchos::RCP<const export_type>& exporter,
707 const Teuchos::RCP<Teuchos::ParameterList>& params) :
711 rangeMap_ (rangeMap.is_null () ? rowMap : rangeMap),
712 domainMap_ (domainMap.is_null () ? rowMap : domainMap),
713 importer_ (importer),
714 exporter_ (exporter),
715 numAllocForAllRows_ (0),
716 storageStatus_ (Details::STORAGE_1D_PACKED),
717 indicesAreAllocated_ (true),
718 indicesAreLocal_ (true)
721 const char tfecfFuncName[] =
"Tpetra::CrsGraph(local_graph_device_type,"
722 "Map,Map,Map,Map,Import,Export,params): ";
724 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
725 (colMap.is_null (), std::runtime_error,
726 "The input column Map must be nonnull.");
730 setRowPtrs(lclGraph.row_map);
732 set_need_sync_host_uvm_access();
734 if (! params.is_null() && params->isParameter(
"sorted") &&
735 ! params->get<
bool>(
"sorted")) {
742 const bool callComputeGlobalConstants =
743 params.get () ==
nullptr ||
744 params->get (
"compute global constants",
true);
745 if (callComputeGlobalConstants) {
748 fillComplete_ =
true;
752 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
753 Teuchos::RCP<const Teuchos::ParameterList>
758 using Teuchos::ParameterList;
759 using Teuchos::parameterList;
761 RCP<ParameterList> params = parameterList (
"Tpetra::CrsGraph");
764 RCP<ParameterList> importSublist = parameterList (
"Import");
776 Distributor distributor (rowMap_->getComm (), importSublist);
777 params->set (
"Import", *importSublist,
"How the Import performs communication.");
783 params->set (
"Export", *importSublist,
"How the Export performs communication.");
788 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
793 Teuchos::RCP<const Teuchos::ParameterList> validParams =
794 getValidParameters ();
795 params->validateParametersAndSetDefaults (*validParams);
796 this->setMyParamList (params);
799 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
804 return rowMap_->getGlobalNumElements ();
807 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
812 const char tfecfFuncName[] =
"getGlobalNumCols: ";
813 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
814 ! isFillComplete () || getDomainMap ().is_null (), std::runtime_error,
815 "The graph does not have a domain Map. You may not call this method in "
817 return getDomainMap ()->getGlobalNumElements ();
821 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
826 return this->rowMap_.is_null () ?
827 static_cast<size_t> (0) :
828 this->rowMap_->getLocalNumElements ();
832 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
837 const char tfecfFuncName[] =
"getLocalNumCols: ";
838 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
839 ! hasColMap (), std::runtime_error,
840 "The graph does not have a column Map. You may not call this method "
841 "unless the graph has a column Map. This requires either that a custom "
842 "column Map was given to the constructor, or that fillComplete() has "
844 return colMap_.is_null () ?
static_cast<size_t> (0) :
845 colMap_->getLocalNumElements ();
850 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
851 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
858 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
859 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
866 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
867 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
874 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
875 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
882 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
883 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::import_type>
890 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
891 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::export_type>
898 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
903 return ! colMap_.is_null ();
906 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
914 const bool isOpt = indicesAreAllocated_ &&
915 k_numRowEntries_.extent (0) == 0 &&
916 getLocalNumRows () > 0;
922 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
927 const char tfecfFuncName[] =
"getGlobalNumEntries: ";
928 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
929 (! this->haveGlobalConstants_, std::logic_error,
930 "The graph does not have global constants computed, "
931 "but the user has requested them.");
933 return globalNumEntries_;
937 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
942 const char tfecfFuncName[] =
"getLocalNumEntries: ";
943 typedef LocalOrdinal LO;
945 if (this->indicesAreAllocated_) {
946 const LO lclNumRows = this->getLocalNumRows ();
947 if (lclNumRows == 0) {
948 return static_cast<size_t> (0);
952 auto numEntPerRow = this->k_numRowEntries_;
953 const LO numNumEntPerRow = numEntPerRow.extent (0);
954 if (numNumEntPerRow == 0) {
955 if (static_cast<LO> (this->getRowPtrsPackedDevice().extent (0)) <
956 static_cast<LO> (lclNumRows + 1)) {
957 return static_cast<size_t> (0);
964 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
965 (this->getRowPtrsPackedHost()(lclNumRows) != lclIndsPacked_wdv.extent(0), std::logic_error,
966 "Final entry of packed host rowptrs doesn't match the length of lclIndsPacked");
968 return lclIndsPacked_wdv.extent(0);
978 typedef typename num_row_entries_type::execution_space
980 typedef Kokkos::RangePolicy<host_exec_space, LO> range_type;
982 const LO upperLoopBound = lclNumRows < numNumEntPerRow ?
985 size_t nodeNumEnt = 0;
986 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::getNumNodeEntries",
987 range_type (0, upperLoopBound),
988 [=] (
const LO& k,
size_t& lclSum) {
989 lclSum += numEntPerRow(k);
996 return static_cast<size_t> (0);
1000 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1005 const char tfecfFuncName[] =
"getGlobalMaxNumRowEntries: ";
1006 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1007 (! this->haveGlobalConstants_, std::logic_error,
1008 "The graph does not have global constants computed, "
1009 "but the user has requested them.");
1011 return globalMaxNumRowEntries_;
1014 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1019 return nodeMaxNumRowEntries_;
1022 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1027 return fillComplete_;
1030 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1035 return ! fillComplete_;
1039 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1044 return indicesAreLocal_;
1047 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1052 return indicesAreGlobal_;
1055 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1060 typedef LocalOrdinal LO;
1062 if (this->indicesAreAllocated_) {
1063 const LO lclNumRows = this->getLocalNumRows ();
1064 if (lclNumRows == 0) {
1065 return static_cast<size_t> (0);
1067 else if (storageStatus_ == Details::STORAGE_1D_PACKED) {
1068 if (static_cast<LO> (this->getRowPtrsPackedDevice().extent (0)) <
1069 static_cast<LO
> (lclNumRows + 1)) {
1070 return static_cast<size_t> (0);
1073 if(this->isLocallyIndexed())
1074 return lclIndsPacked_wdv.extent(0);
1076 return gblInds_wdv.extent(0);
1079 else if (storageStatus_ == Details::STORAGE_1D_UNPACKED) {
1080 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
1081 if (rowPtrsUnpacked_host.extent (0) == 0) {
1082 return static_cast<size_t> (0);
1085 if(this->isLocallyIndexed())
1086 return lclIndsUnpacked_wdv.extent(0);
1088 return gblInds_wdv.extent(0);
1092 return static_cast<size_t> (0);
1096 return Tpetra::Details::OrdinalTraits<size_t>::invalid ();
1100 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1101 Teuchos::RCP<const Teuchos::Comm<int> >
1105 return this->rowMap_.is_null () ? Teuchos::null : this->rowMap_->getComm ();
1108 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1113 return rowMap_->getIndexBase ();
1116 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1121 return indicesAreAllocated_;
1124 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1129 return indicesAreSorted_;
1132 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1137 return noRedundancies_;
1140 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1150 indicesAreSorted_ =
false;
1151 noRedundancies_ =
false;
1155 haveLocalConstants_ =
false;
1158 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1164 using Teuchos::arcp;
1165 using Teuchos::Array;
1166 using Teuchos::ArrayRCP;
1168 typedef Teuchos::ArrayRCP<size_t>::size_type size_type;
1169 typedef typename local_graph_device_type::row_map_type::non_const_type
1170 non_const_row_map_type;
1171 const char tfecfFuncName[] =
"allocateIndices: ";
1172 const char suffix[] =
1173 " Please report this bug to the Tpetra developers.";
1174 ProfilingRegion profRegion(
"Tpetra::CrsGraph::allocateIndices");
1176 std::unique_ptr<std::string> prefix;
1178 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
1179 std::ostringstream os;
1180 os << *prefix <<
"Start: lg="
1181 << (lg == GlobalIndices ?
"GlobalIndices" :
"LocalIndices")
1182 <<
", numRows: " << this->getLocalNumRows() << endl;
1183 std::cerr << os.str();
1189 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1190 (isLocallyIndexed () && lg == GlobalIndices, std::logic_error,
1191 ": The graph is locally indexed, but Tpetra code is calling "
1192 "this method with lg=GlobalIndices." << suffix);
1193 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1194 (isGloballyIndexed () && lg == LocalIndices, std::logic_error,
1195 ": The graph is globally indexed, but Tpetra code is calling "
1196 "this method with lg=LocalIndices." << suffix);
1197 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1198 (indicesAreAllocated (), std::logic_error,
": The graph's "
1199 "indices are already allocated, but Tpetra is calling "
1200 "allocateIndices again." << suffix);
1201 const size_t numRows = this->getLocalNumRows ();
1206 size_type numInds = 0;
1209 std::ostringstream os;
1210 os << *prefix <<
"Allocate k_rowPtrs: " << (numRows+1) << endl;
1211 std::cerr << os.str();
1213 non_const_row_map_type k_rowPtrs (
"Tpetra::CrsGraph::ptr", numRows + 1);
1215 if (this->k_numAllocPerRow_.extent (0) != 0) {
1220 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1221 (this->k_numAllocPerRow_.extent (0) != numRows,
1222 std::invalid_argument,
"k_numAllocPerRow_ is allocated, that is, "
1223 "has nonzero length " << this->k_numAllocPerRow_.extent (0)
1224 <<
", but its length != numRows = " << numRows <<
".");
1242 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1243 (this->numAllocForAllRows_ ==
1244 Tpetra::Details::OrdinalTraits<size_t>::invalid (),
1245 std::invalid_argument,
"numAllocForAllRows_ has an invalid value, "
1246 "namely Tpetra::Details::OrdinalTraits<size_t>::invalid() = " <<
1247 Tpetra::Details::OrdinalTraits<size_t>::invalid () <<
".");
1253 setRowPtrsUnpacked(k_rowPtrs);
1256 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1257 (numInds != size_type(this->getRowPtrsUnpackedHost()(numRows)), std::logic_error,
1258 ": Number of indices produced by computeOffsetsFrom[Constant]Counts "
1259 "does not match final entry of rowptrs unpacked");
1263 if (lg == LocalIndices) {
1265 std::ostringstream os;
1266 os << *prefix <<
"Allocate local column indices "
1267 "lclIndsUnpacked_wdv: " << numInds << endl;
1268 std::cerr << os.str();
1270 lclIndsUnpacked_wdv = local_inds_wdv_type (
1271 local_inds_dualv_type(
"Tpetra::CrsGraph::lclInd",numInds));
1275 std::ostringstream os;
1276 os << *prefix <<
"Allocate global column indices "
1277 "gblInds_wdv: " << numInds << endl;
1278 std::cerr << os.str();
1280 gblInds_wdv = global_inds_wdv_type (
1281 global_inds_dualv_type(
"Tpetra::CrsGraph::gblInd",numInds));
1283 storageStatus_ = Details::STORAGE_1D_UNPACKED;
1285 this->indicesAreLocal_ = (lg == LocalIndices);
1286 this->indicesAreGlobal_ = (lg == GlobalIndices);
1289 using Kokkos::ViewAllocateWithoutInitializing;
1290 const char label[] =
"Tpetra::CrsGraph::numRowEntries";
1292 std::ostringstream os;
1293 os << *prefix <<
"Allocate k_numRowEntries_: " << numRows
1295 std::cerr << os.str();
1297 num_row_entries_type numRowEnt (ViewAllocateWithoutInitializing (label), numRows);
1300 Kokkos::fence(
"CrsGraph::allocateIndices");
1301 this->k_numRowEntries_ = numRowEnt;
1305 this->numAllocForAllRows_ = 0;
1306 this->k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
1307 this->indicesAreAllocated_ =
true;
1310 this->checkInternalState ();
1312 catch (std::logic_error& e) {
1313 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1314 (
true, std::logic_error,
"At end of allocateIndices, "
1315 "checkInternalState threw std::logic_error: "
1318 catch (std::exception& e) {
1319 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1320 (
true, std::runtime_error,
"At end of allocateIndices, "
1321 "checkInternalState threw std::exception: "
1325 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1326 (
true, std::runtime_error,
"At end of allocateIndices, "
1327 "checkInternalState threw an exception "
1328 "not a subclass of std::exception.");
1332 std::ostringstream os;
1333 os << *prefix <<
"Done" << endl;
1334 std::cerr << os.str();
1338 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1339 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1340 local_inds_dualv_type::t_host::const_type
1344 if (rowinfo.allocSize == 0 || lclIndsUnpacked_wdv.extent(0) == 0)
1345 return typename local_inds_dualv_type::t_host::const_type ();
1347 return lclIndsUnpacked_wdv.getHostSubview(rowinfo.offset1D,
1352 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1354 local_inds_dualv_type::t_host
1358 if (rowinfo.allocSize == 0 || lclIndsUnpacked_wdv.extent(0) == 0)
1359 return typename local_inds_dualv_type::t_host ();
1361 return lclIndsUnpacked_wdv.getHostSubview(rowinfo.offset1D,
1366 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1368 global_inds_dualv_type::t_host::const_type
1372 if (rowinfo.allocSize == 0 || gblInds_wdv.extent(0) == 0)
1373 return typename global_inds_dualv_type::t_host::const_type ();
1375 return gblInds_wdv.getHostSubview(rowinfo.offset1D,
1380 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1382 local_inds_dualv_type::t_dev::const_type
1386 if (rowinfo.allocSize == 0 || lclIndsUnpacked_wdv.extent(0) == 0)
1387 return typename local_inds_dualv_type::t_dev::const_type ();
1389 return lclIndsUnpacked_wdv.getDeviceSubview(rowinfo.offset1D,
1394 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1396 global_inds_dualv_type::t_dev::const_type
1400 if (rowinfo.allocSize == 0 || gblInds_wdv.extent(0) == 0)
1401 return typename global_inds_dualv_type::t_dev::const_type ();
1403 return gblInds_wdv.getDeviceSubview(rowinfo.offset1D,
1409 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1414 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1416 if (this->rowMap_.is_null () || ! this->rowMap_->isNodeLocalElement (myRow)) {
1417 ret.localRow = STINV;
1420 ret.offset1D = STINV;
1424 ret.localRow =
static_cast<size_t> (myRow);
1425 if (this->indicesAreAllocated ()) {
1426 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
1428 if (rowPtrsUnpacked_host.extent (0) == 0) {
1433 ret.offset1D = rowPtrsUnpacked_host(myRow);
1434 ret.allocSize = rowPtrsUnpacked_host(myRow+1) - rowPtrsUnpacked_host(myRow);
1437 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
1439 this->k_numRowEntries_(myRow);
1445 ret.allocSize = (this->k_numAllocPerRow_.extent (0) != 0) ?
1446 this->k_numAllocPerRow_(myRow) :
1447 this->numAllocForAllRows_;
1449 ret.offset1D = STINV;
1456 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1461 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1463 if (this->rowMap_.is_null ()) {
1464 ret.localRow = STINV;
1467 ret.offset1D = STINV;
1470 const LocalOrdinal myRow = this->rowMap_->getLocalElement (gblRow);
1471 if (myRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid ()) {
1472 ret.localRow = STINV;
1475 ret.offset1D = STINV;
1479 ret.localRow =
static_cast<size_t> (myRow);
1480 if (this->indicesAreAllocated ()) {
1484 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
1485 if (rowPtrsUnpacked_host.extent (0) == 0) {
1490 ret.offset1D = rowPtrsUnpacked_host(myRow);
1491 ret.allocSize = rowPtrsUnpacked_host(myRow+1) - rowPtrsUnpacked_host(myRow);
1494 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
1496 this->k_numRowEntries_(myRow);
1502 ret.allocSize = (this->k_numAllocPerRow_.extent (0) != 0) ?
1503 this->k_numAllocPerRow_(myRow) :
1504 this->numAllocForAllRows_;
1506 ret.offset1D = STINV;
1513 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1518 using Teuchos::OrdinalTraits;
1519 typedef LocalOrdinal LO;
1520 typedef GlobalOrdinal GO;
1526 static_assert (
sizeof (GlobalOrdinal) >=
sizeof (LocalOrdinal),
1527 "Tpetra::CrsGraph: sizeof(GlobalOrdinal) must be >= sizeof(LocalOrdinal).");
1530 static_assert (
sizeof (
size_t) >=
sizeof (LocalOrdinal),
1531 "Tpetra::CrsGraph: sizeof(size_t) must be >= sizeof(LocalOrdinal).");
1532 static_assert (
sizeof(GST) >=
sizeof(
size_t),
1533 "Tpetra::CrsGraph: sizeof(Tpetra::global_size_t) must be >= sizeof(size_t).");
1541 const char msg[] =
"Tpetra::CrsGraph: Object cannot be created with the "
1542 "given template arguments: size assumptions are not valid.";
1543 TEUCHOS_TEST_FOR_EXCEPTION(
1544 static_cast<size_t> (Teuchos::OrdinalTraits<LO>::max ()) > Teuchos::OrdinalTraits<size_t>::max (),
1545 std::runtime_error, msg);
1546 TEUCHOS_TEST_FOR_EXCEPTION(
1547 static_cast<GST> (Teuchos::OrdinalTraits<LO>::max ()) > static_cast<GST> (Teuchos::OrdinalTraits<GO>::max ()),
1548 std::runtime_error, msg);
1549 TEUCHOS_TEST_FOR_EXCEPTION(
1550 static_cast<size_t> (Teuchos::OrdinalTraits<GO>::max ()) > Teuchos::OrdinalTraits<GST>::max(),
1551 std::runtime_error, msg);
1552 TEUCHOS_TEST_FOR_EXCEPTION(
1553 Teuchos::OrdinalTraits<size_t>::max () > Teuchos::OrdinalTraits<GST>::max (),
1554 std::runtime_error, msg);
1558 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1562 const SLocalGlobalViews &newInds,
1563 const ELocalGlobal lg,
1564 const ELocalGlobal I)
1566 using Teuchos::ArrayView;
1567 typedef LocalOrdinal LO;
1568 typedef GlobalOrdinal GO;
1569 const char tfecfFuncName[] =
"insertIndices: ";
1571 size_t oldNumEnt = 0;
1573 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1574 (lg != GlobalIndices && lg != LocalIndices, std::invalid_argument,
1575 "lg must be either GlobalIndices or LocalIndices.");
1576 oldNumEnt = this->getNumEntriesInLocalRow (rowinfo.localRow);
1579 size_t numNewInds = 0;
1580 if (lg == GlobalIndices) {
1581 ArrayView<const GO> new_ginds = newInds.ginds;
1582 numNewInds = new_ginds.size();
1583 if (I == GlobalIndices) {
1584 auto gind_view = gblInds_wdv.getHostView(Access::ReadWrite);
1586 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1587 (static_cast<size_t> (gind_view.size ()) <
1588 rowinfo.numEntries + numNewInds, std::logic_error,
1589 "gind_view.size() = " << gind_view.size ()
1590 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1591 <<
") + numNewInds (= " << numNewInds <<
").");
1593 GO*
const gblColInds_out = gind_view.data () + rowinfo.offset1D
1594 + rowinfo.numEntries;
1595 for (
size_t k = 0; k < numNewInds; ++k) {
1596 gblColInds_out[k] = new_ginds[k];
1599 else if (I == LocalIndices) {
1600 auto lind_view = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1602 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1603 (static_cast<size_t> (lind_view.size ()) <
1604 rowinfo.numEntries + numNewInds, std::logic_error,
1605 "lind_view.size() = " << lind_view.size ()
1606 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1607 <<
") + numNewInds (= " << numNewInds <<
").");
1609 LO*
const lclColInds_out = lind_view.data () + rowinfo.offset1D
1610 + rowinfo.numEntries;
1611 for (
size_t k = 0; k < numNewInds; ++k) {
1612 lclColInds_out[k] = colMap_->getLocalElement (new_ginds[k]);
1616 else if (lg == LocalIndices) {
1617 ArrayView<const LO> new_linds = newInds.linds;
1618 numNewInds = new_linds.size();
1619 if (I == LocalIndices) {
1620 auto lind_view = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1622 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1623 (static_cast<size_t> (lind_view.size ()) <
1624 rowinfo.numEntries + numNewInds, std::logic_error,
1625 "lind_view.size() = " << lind_view.size ()
1626 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1627 <<
") + numNewInds (= " << numNewInds <<
").");
1629 LO*
const lclColInds_out = lind_view.data () + rowinfo.offset1D
1630 + rowinfo.numEntries;
1631 for (
size_t k = 0; k < numNewInds; ++k) {
1632 lclColInds_out[k] = new_linds[k];
1635 else if (I == GlobalIndices) {
1636 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1637 (
true, std::logic_error,
"The case where the input indices are local "
1638 "and the indices to write are global (lg=LocalIndices, I="
1639 "GlobalIndices) is not implemented, because it does not make sense."
1640 << std::endl <<
"If you have correct local column indices, that "
1641 "means the graph has a column Map. In that case, you should be "
1642 "storing local indices.");
1646 rowinfo.numEntries += numNewInds;
1647 this->k_numRowEntries_(rowinfo.localRow) += numNewInds;
1648 this->setLocallyModified ();
1651 const size_t chkNewNumEnt =
1652 this->getNumEntriesInLocalRow (rowinfo.localRow);
1653 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1654 (chkNewNumEnt != oldNumEnt + numNewInds, std::logic_error,
1655 "chkNewNumEnt = " << chkNewNumEnt
1656 <<
" != oldNumEnt (= " << oldNumEnt
1657 <<
") + numNewInds (= " << numNewInds <<
").");
1663 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1667 const GlobalOrdinal inputGblColInds[],
1668 const size_t numInputInds)
1670 return this->insertGlobalIndicesImpl (this->getRowInfo (lclRow),
1671 inputGblColInds, numInputInds);
1674 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1678 const GlobalOrdinal inputGblColInds[],
1679 const size_t numInputInds,
1680 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
1684 using Kokkos::subview;
1685 using Kokkos::MemoryUnmanaged;
1686 using Teuchos::ArrayView;
1687 using LO = LocalOrdinal;
1688 using GO = GlobalOrdinal;
1689 const char tfecfFuncName[] =
"insertGlobalIndicesImpl: ";
1690 const LO lclRow =
static_cast<LO
> (rowInfo.localRow);
1692 auto numEntries = rowInfo.numEntries;
1693 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1694 inp_view_type inputInds(inputGblColInds, numInputInds);
1697 auto gblIndsHostView = this->gblInds_wdv.getHostView(Access::ReadWrite);
1700 numEntries, inputInds, fun);
1703 const bool insertFailed =
1704 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1706 constexpr
size_t ONE (1);
1707 const int myRank = this->getComm()->getRank();
1708 std::ostringstream os;
1710 os <<
"Proc " << myRank <<
": Not enough capacity to insert "
1712 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1713 <<
" into local row " << lclRow <<
", which currently has "
1714 << rowInfo.numEntries
1715 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1716 <<
" and total allocation size " << rowInfo.allocSize
1718 const size_t maxNumToPrint =
1720 ArrayView<const GO> inputGblColIndsView(inputGblColInds,
1723 "column indices", maxNumToPrint);
1725 auto curGblColInds = getGlobalIndsViewHost(rowInfo);
1726 ArrayView<const GO> curGblColIndsView(curGblColInds.data(),
1727 rowInfo.numEntries);
1729 "column indices", maxNumToPrint);
1730 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1731 (
true, std::runtime_error, os.str());
1734 this->k_numRowEntries_(lclRow) += numInserted;
1736 this->setLocallyModified();
1741 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1745 const Teuchos::ArrayView<const LocalOrdinal>& indices,
1746 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
1748 using Kokkos::MemoryUnmanaged;
1749 using Kokkos::subview;
1751 using LO = LocalOrdinal;
1752 const char tfecfFuncName[] =
"insertLocallIndicesImpl: ";
1754 const RowInfo rowInfo = this->getRowInfo(myRow);
1756 size_t numNewInds = 0;
1757 size_t newNumEntries = 0;
1759 auto numEntries = rowInfo.numEntries;
1761 using inp_view_type = View<const LO*, Kokkos::HostSpace, MemoryUnmanaged>;
1762 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1763 size_t numInserted = 0;
1765 auto lclInds = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1767 numEntries, inputInds, fun);
1770 const bool insertFailed =
1771 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1773 constexpr
size_t ONE (1);
1774 const size_t numInputInds(indices.size());
1775 const int myRank = this->getComm()->getRank();
1776 std::ostringstream os;
1777 os <<
"On MPI Process " << myRank <<
": Not enough capacity to "
1778 "insert " << numInputInds
1779 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1780 <<
" into local row " << myRow <<
", which currently has "
1781 << rowInfo.numEntries
1782 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1783 <<
" and total allocation size " << rowInfo.allocSize <<
".";
1784 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1785 (
true, std::runtime_error, os.str());
1787 numNewInds = numInserted;
1788 newNumEntries = rowInfo.numEntries + numNewInds;
1790 this->k_numRowEntries_(myRow) += numNewInds;
1791 this->setLocallyModified ();
1794 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow (myRow);
1795 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1796 (chkNewNumEntries != newNumEntries, std::logic_error,
1797 "getNumEntriesInLocalRow(" << myRow <<
") = " << chkNewNumEntries
1798 <<
" != newNumEntries = " << newNumEntries
1799 <<
". Please report this bug to the Tpetra developers.");
1803 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1807 const Teuchos::ArrayView<const GlobalOrdinal>& indices,
1808 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
const
1810 using GO = GlobalOrdinal;
1812 using Kokkos::MemoryUnmanaged;
1813 auto invalidCount = Teuchos::OrdinalTraits<size_t>::invalid();
1815 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1816 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1818 size_t numFound = 0;
1819 LocalOrdinal lclRow = rowInfo.localRow;
1820 if (this->isLocallyIndexed())
1822 if (this->colMap_.is_null())
1823 return invalidCount;
1824 const auto& colMap = *(this->colMap_);
1825 auto map = [&](GO
const gblInd){
return colMap.getLocalElement(gblInd);};
1828 lclIndsUnpacked_wdv.getHostView(Access::ReadOnly), inputInds, map, fun);
1830 else if (this->isGloballyIndexed())
1834 gblInds_wdv.getHostView(Access::ReadOnly), inputInds, fun);
1840 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1847 const size_t origNumEnt = rowInfo.numEntries;
1848 if (origNumEnt != Tpetra::Details::OrdinalTraits<size_t>::invalid () &&
1850 auto lclColInds = this->getLocalIndsViewHostNonConst (rowInfo);
1852 LocalOrdinal*
const lclColIndsRaw = lclColInds.data ();
1854 std::sort (lclColIndsRaw, lclColIndsRaw + origNumEnt);
1858 LocalOrdinal*
const beg = lclColIndsRaw;
1859 LocalOrdinal*
const end = beg + rowInfo.numEntries;
1860 LocalOrdinal*
const newend = std::unique (beg, end);
1861 const size_t newNumEnt = newend - beg;
1864 this->k_numRowEntries_(rowInfo.localRow) = newNumEnt;
1865 return origNumEnt - newNumEnt;
1868 return static_cast<size_t> (0);
1872 return static_cast<size_t> (0);
1877 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1881 const Teuchos::RCP<const map_type>& rangeMap)
1884 if (domainMap_ != domainMap) {
1885 domainMap_ = domainMap;
1886 importer_ = Teuchos::null;
1888 if (rangeMap_ != rangeMap) {
1889 rangeMap_ = rangeMap;
1890 exporter_ = Teuchos::null;
1895 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1900 const auto INV = Teuchos::OrdinalTraits<global_size_t>::invalid();
1902 globalNumEntries_ = INV;
1903 globalMaxNumRowEntries_ = INV;
1904 haveGlobalConstants_ =
false;
1908 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1915 const char tfecfFuncName[] =
"checkInternalState: ";
1916 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1918 std::unique_ptr<std::string> prefix;
1920 prefix = this->createPrefix(
"CrsGraph",
"checkInternalState");
1921 std::ostringstream os;
1922 os << *prefix <<
"Start" << endl;
1923 std::cerr << os.str();
1926 const global_size_t GSTI = Teuchos::OrdinalTraits<global_size_t>::invalid ();
1932 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1933 (this->rowMap_.is_null (), std::logic_error,
1934 "Row Map is null." << suffix);
1937 const LocalOrdinal lclNumRows =
1938 static_cast<LocalOrdinal
> (this->getLocalNumRows ());
1940 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1941 (this->isFillActive () == this->isFillComplete (), std::logic_error,
1942 "Graph cannot be both fill active and fill complete." << suffix);
1943 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1944 (this->isFillComplete () &&
1945 (this->colMap_.is_null () ||
1946 this->rangeMap_.is_null () ||
1947 this->domainMap_.is_null ()),
1949 "Graph is full complete, but at least one of {column, range, domain} "
1950 "Map is null." << suffix);
1951 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1952 (this->isStorageOptimized () && ! this->indicesAreAllocated (),
1953 std::logic_error,
"Storage is optimized, but indices are not "
1954 "allocated, not even trivially." << suffix);
1956 size_t nodeAllocSize = 0;
1958 nodeAllocSize = this->getLocalAllocationSize ();
1960 catch (std::logic_error& e) {
1961 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1962 (
true, std::runtime_error,
"getLocalAllocationSize threw "
1963 "std::logic_error: " << e.what ());
1965 catch (std::exception& e) {
1966 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1967 (
true, std::runtime_error,
"getLocalAllocationSize threw an "
1968 "std::exception: " << e.what ());
1971 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1972 (
true, std::runtime_error,
"getLocalAllocationSize threw an exception "
1973 "not a subclass of std::exception.");
1976 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1977 (this->isStorageOptimized () &&
1978 nodeAllocSize != this->getLocalNumEntries (),
1979 std::logic_error,
"Storage is optimized, but "
1980 "this->getLocalAllocationSize() = " << nodeAllocSize
1981 <<
" != this->getLocalNumEntries() = " << this->getLocalNumEntries ()
1983 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1984 (! this->haveGlobalConstants_ &&
1985 (this->globalNumEntries_ != GSTI ||
1986 this->globalMaxNumRowEntries_ != GSTI),
1987 std::logic_error,
"Graph claims not to have global constants, but "
1988 "some of the global constants are not marked as invalid." << suffix);
1989 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1990 (this->haveGlobalConstants_ &&
1991 (this->globalNumEntries_ == GSTI ||
1992 this->globalMaxNumRowEntries_ == GSTI),
1993 std::logic_error,
"Graph claims to have global constants, but "
1994 "some of them are marked as invalid." << suffix);
1995 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1996 (this->haveGlobalConstants_ &&
1997 (this->globalNumEntries_ < this->getLocalNumEntries () ||
1998 this->globalMaxNumRowEntries_ < this->nodeMaxNumRowEntries_),
1999 std::logic_error,
"Graph claims to have global constants, and "
2000 "all of the values of the global constants are valid, but "
2001 "some of the local constants are greater than "
2002 "their corresponding global constants." << suffix);
2003 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2004 (this->indicesAreAllocated () &&
2005 (this->numAllocForAllRows_ != 0 ||
2006 this->k_numAllocPerRow_.extent (0) != 0),
2007 std::logic_error,
"The graph claims that its indices are allocated, but "
2008 "either numAllocForAllRows_ (= " << this->numAllocForAllRows_ <<
") is "
2009 "nonzero, or k_numAllocPerRow_ has nonzero dimension. In other words, "
2010 "the graph is supposed to release its \"allocation specifications\" "
2011 "when it allocates its indices." << suffix);
2012 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
2013 auto rowPtrsUnpacked_dev = this->getRowPtrsUnpackedDevice();
2014 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2015 (rowPtrsUnpacked_host.extent(0) != rowPtrsUnpacked_dev.extent(0),
2016 std::logic_error,
"The host and device views of k_rowPtrs_ have "
2017 "different sizes; rowPtrsUnpacked_host_ has size "
2018 << rowPtrsUnpacked_host.extent(0)
2019 <<
", but rowPtrsUnpacked_dev_ has size "
2020 << rowPtrsUnpacked_dev.extent(0)
2022 if (isGloballyIndexed() && rowPtrsUnpacked_host.extent(0) != 0) {
2023 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2024 (
size_t(rowPtrsUnpacked_host.extent(0)) !=
size_t(lclNumRows + 1),
2025 std::logic_error,
"The graph is globally indexed and "
2026 "k_rowPtrs has nonzero size " << rowPtrsUnpacked_host.extent(0)
2027 <<
", but that size does not equal lclNumRows+1 = "
2028 << (lclNumRows+1) <<
"." << suffix);
2029 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2030 (rowPtrsUnpacked_host(lclNumRows) !=
size_t(gblInds_wdv.extent(0)),
2031 std::logic_error,
"The graph is globally indexed and "
2032 "k_rowPtrs_ has nonzero size " << rowPtrsUnpacked_host.extent(0)
2033 <<
", but k_rowPtrs_(lclNumRows=" << lclNumRows <<
")="
2034 << rowPtrsUnpacked_host(lclNumRows)
2035 <<
" != gblInds_wdv.extent(0)="
2036 << gblInds_wdv.extent(0) <<
"." << suffix);
2038 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2039 (this->isLocallyIndexed () &&
2040 rowPtrsUnpacked_host.extent (0) != 0 &&
2041 (
static_cast<size_t> (rowPtrsUnpacked_host.extent (0)) !=
2042 static_cast<size_t> (lclNumRows + 1) ||
2043 rowPtrsUnpacked_host(lclNumRows) !=
2044 static_cast<size_t> (this->lclIndsUnpacked_wdv.extent (0))),
2045 std::logic_error,
"If k_rowPtrs_ has nonzero size and "
2046 "the graph is locally indexed, then "
2047 "k_rowPtrs_ must have N+1 rows, and "
2048 "k_rowPtrs_(N) must equal lclIndsUnpacked_wdv.extent(0)." << suffix);
2050 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2051 (this->indicesAreAllocated () &&
2052 nodeAllocSize > 0 &&
2053 this->lclIndsUnpacked_wdv.extent (0) == 0 &&
2054 this->gblInds_wdv.extent (0) == 0,
2055 std::logic_error,
"Graph is allocated nontrivially, but "
2056 "but 1-D allocations are not present." << suffix);
2058 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2059 (! this->indicesAreAllocated () &&
2060 ((rowPtrsUnpacked_host.extent (0) != 0 ||
2061 this->k_numRowEntries_.extent (0) != 0) ||
2062 this->lclIndsUnpacked_wdv.extent (0) != 0 ||
2063 this->gblInds_wdv.extent (0) != 0),
2064 std::logic_error,
"If indices are not allocated, "
2065 "then none of the buffers should be." << suffix);
2069 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2070 ((this->indicesAreLocal_ || this->indicesAreGlobal_) &&
2071 ! this->indicesAreAllocated_,
2072 std::logic_error,
"Indices may be local or global only if they are "
2073 "allocated." << suffix);
2074 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2075 (this->indicesAreLocal_ && this->indicesAreGlobal_,
2076 std::logic_error,
"Indices may not be both local and global." << suffix);
2077 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2078 (indicesAreLocal_ && gblInds_wdv.extent (0) != 0,
2079 std::logic_error,
"Indices are local, but "
2080 "gblInds_wdv.extent(0) (= " << gblInds_wdv.extent (0)
2081 <<
") != 0. In other words, if indices are local, then "
2082 "allocations of global indices should not be present."
2084 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2085 (indicesAreGlobal_ && lclIndsUnpacked_wdv.extent (0) != 0,
2086 std::logic_error,
"Indices are global, but "
2087 "lclIndsUnpacked_wdv.extent(0) (= " << lclIndsUnpacked_wdv.extent(0)
2088 <<
") != 0. In other words, if indices are global, "
2089 "then allocations for local indices should not be present."
2091 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2092 (indicesAreLocal_ && nodeAllocSize > 0 &&
2093 lclIndsUnpacked_wdv.extent (0) == 0 && getLocalNumRows () > 0,
2094 std::logic_error,
"Indices are local and "
2095 "getLocalAllocationSize() = " << nodeAllocSize <<
" > 0, but "
2096 "lclIndsUnpacked_wdv.extent(0) = 0 and getLocalNumRows() = "
2097 << getLocalNumRows () <<
" > 0." << suffix);
2098 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2099 (indicesAreGlobal_ && nodeAllocSize > 0 &&
2100 gblInds_wdv.extent (0) == 0 && getLocalNumRows () > 0,
2101 std::logic_error,
"Indices are global and "
2102 "getLocalAllocationSize() = " << nodeAllocSize <<
" > 0, but "
2103 "gblInds_wdv.extent(0) = 0 and getLocalNumRows() = "
2104 << getLocalNumRows () <<
" > 0." << suffix);
2106 if (this->indicesAreAllocated () &&
2107 rowPtrsUnpacked_host.extent (0) != 0) {
2108 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2109 (static_cast<size_t> (rowPtrsUnpacked_host.extent (0)) !=
2110 this->getLocalNumRows () + 1,
2111 std::logic_error,
"Indices are allocated and "
2112 "k_rowPtrs_ has nonzero length, but rowPtrsUnpacked_host_.extent(0) = "
2113 << rowPtrsUnpacked_host.extent (0) <<
" != getLocalNumRows()+1 = "
2114 << (this->getLocalNumRows () + 1) <<
"." << suffix);
2115 const size_t actualNumAllocated =
2116 rowPtrsUnpacked_host(this->getLocalNumRows());
2117 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2118 (this->isLocallyIndexed () &&
2119 static_cast<size_t> (this->lclIndsUnpacked_wdv.extent (0)) != actualNumAllocated,
2120 std::logic_error,
"Graph is locally indexed, indices are "
2121 "are allocated, and k_rowPtrs_ has nonzero length, but "
2122 "lclIndsUnpacked_wdv.extent(0) = " << this->lclIndsUnpacked_wdv.extent (0)
2123 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2124 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2125 (this->isGloballyIndexed () &&
2126 static_cast<size_t> (this->gblInds_wdv.extent (0)) != actualNumAllocated,
2127 std::logic_error,
"Graph is globally indexed, indices "
2128 "are allocated, and k_rowPtrs_ has nonzero length, but "
2129 "gblInds_wdv.extent(0) = " << this->gblInds_wdv.extent (0)
2130 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2134 std::ostringstream os;
2135 os << *prefix <<
"Done" << endl;
2136 std::cerr << os.str();
2142 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2147 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (globalRow);
2148 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2149 return Teuchos::OrdinalTraits<size_t>::invalid ();
2152 return rowInfo.numEntries;
2157 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2162 const RowInfo rowInfo = this->getRowInfo (localRow);
2163 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2164 return Teuchos::OrdinalTraits<size_t>::invalid ();
2167 return rowInfo.numEntries;
2172 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2177 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (globalRow);
2178 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2179 return Teuchos::OrdinalTraits<size_t>::invalid ();
2182 return rowInfo.allocSize;
2187 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2192 const RowInfo rowInfo = this->getRowInfo (localRow);
2193 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2194 return Teuchos::OrdinalTraits<size_t>::invalid ();
2197 return rowInfo.allocSize;
2202 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2203 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_host_view_type
2207 return getRowPtrsPackedHost();
2210 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2211 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_device_view_type
2215 return getRowPtrsPackedDevice();
2219 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2220 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::local_inds_host_view_type
2224 return lclIndsPacked_wdv.getHostView(Access::ReadOnly);
2227 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2232 return lclIndsPacked_wdv.getDeviceView(Access::ReadOnly);
2235 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2239 nonconst_local_inds_host_view_type & indices,
2240 size_t& numEntries)
const
2242 using Teuchos::ArrayView;
2243 const char tfecfFuncName[] =
"getLocalRowCopy: ";
2245 TEUCHOS_TEST_FOR_EXCEPTION(
2246 isGloballyIndexed () && ! hasColMap (), std::runtime_error,
2247 "Tpetra::CrsGraph::getLocalRowCopy: The graph is globally indexed and "
2248 "does not have a column Map yet. That means we don't have local indices "
2249 "for columns yet, so it doesn't make sense to call this method. If the "
2250 "graph doesn't have a column Map yet, you should call fillComplete on "
2255 const RowInfo rowinfo = this->getRowInfo (localRow);
2257 const size_t theNumEntries = rowinfo.numEntries;
2258 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2259 (static_cast<size_t> (indices.size ()) < theNumEntries,std::runtime_error,
2260 "Specified storage (size==" << indices.size () <<
") does not suffice "
2261 "to hold all " << theNumEntries <<
" entry/ies for this row.");
2262 numEntries = theNumEntries;
2264 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
2265 if (isLocallyIndexed ()) {
2266 auto lclInds = getLocalIndsViewHost(rowinfo);
2267 for (
size_t j = 0; j < theNumEntries; ++j) {
2268 indices[j] = lclInds(j);
2271 else if (isGloballyIndexed ()) {
2272 auto gblInds = getGlobalIndsViewHost(rowinfo);
2273 for (
size_t j = 0; j < theNumEntries; ++j) {
2274 indices[j] = colMap_->getLocalElement (gblInds(j));
2281 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2285 nonconst_global_inds_host_view_type &indices,
2286 size_t& numEntries)
const
2288 using Teuchos::ArrayView;
2289 const char tfecfFuncName[] =
"getGlobalRowCopy: ";
2293 const RowInfo rowinfo = getRowInfoFromGlobalRowIndex (globalRow);
2294 const size_t theNumEntries = rowinfo.numEntries;
2295 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2296 static_cast<size_t> (indices.size ()) < theNumEntries, std::runtime_error,
2297 "Specified storage (size==" << indices.size () <<
") does not suffice "
2298 "to hold all " << theNumEntries <<
" entry/ies for this row.");
2299 numEntries = theNumEntries;
2301 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
2302 if (isLocallyIndexed ()) {
2303 auto lclInds = getLocalIndsViewHost(rowinfo);
2304 for (
size_t j = 0; j < theNumEntries; ++j) {
2305 indices[j] = colMap_->getGlobalElement (lclInds(j));
2308 else if (isGloballyIndexed ()) {
2309 auto gblInds = getGlobalIndsViewHost(rowinfo);
2310 for (
size_t j = 0; j < theNumEntries; ++j) {
2311 indices[j] = gblInds(j);
2318 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2322 const LocalOrdinal localRow,
2323 local_inds_host_view_type &indices)
const
2325 const char tfecfFuncName[] =
"getLocalRowView: ";
2327 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2328 (isGloballyIndexed (), std::runtime_error,
"The graph's indices are "
2329 "currently stored as global indices, so we cannot return a view with "
2330 "local column indices, whether or not the graph has a column Map. If "
2331 "the graph _does_ have a column Map, use getLocalRowCopy() instead.");
2333 const RowInfo rowInfo = getRowInfo (localRow);
2334 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
2335 rowInfo.numEntries > 0) {
2336 indices = lclIndsUnpacked_wdv.getHostSubview(rowInfo.offset1D,
2343 indices = local_inds_host_view_type();
2347 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2348 (static_cast<size_t> (indices.size ()) !=
2349 getNumEntriesInLocalRow (localRow), std::logic_error,
"indices.size() "
2350 "= " << indices.extent(0) <<
" != getNumEntriesInLocalRow(localRow=" <<
2351 localRow <<
") = " << getNumEntriesInLocalRow(localRow) <<
2352 ". Please report this bug to the Tpetra developers.");
2357 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2361 const GlobalOrdinal globalRow,
2362 global_inds_host_view_type &indices)
const
2364 const char tfecfFuncName[] =
"getGlobalRowView: ";
2366 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2367 (isLocallyIndexed (), std::runtime_error,
"The graph's indices are "
2368 "currently stored as local indices, so we cannot return a view with "
2369 "global column indices. Use getGlobalRowCopy() instead.");
2373 const RowInfo rowInfo = getRowInfoFromGlobalRowIndex (globalRow);
2374 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
2375 rowInfo.numEntries > 0) {
2376 indices = gblInds_wdv.getHostSubview(rowInfo.offset1D,
2381 indices =
typename global_inds_dualv_type::t_host::const_type();
2384 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2385 (static_cast<size_t> (indices.size ()) !=
2386 getNumEntriesInGlobalRow (globalRow),
2387 std::logic_error,
"indices.size() = " << indices.extent(0)
2388 <<
" != getNumEntriesInGlobalRow(globalRow=" << globalRow <<
") = "
2389 << getNumEntriesInGlobalRow (globalRow)
2390 <<
". Please report this bug to the Tpetra developers.");
2395 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2399 const Teuchos::ArrayView<const LocalOrdinal>& indices)
2401 const char tfecfFuncName[] =
"insertLocalIndices: ";
2403 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2404 (! isFillActive (), std::runtime_error,
"Fill must be active.");
2405 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2406 (isGloballyIndexed (), std::runtime_error,
2407 "Graph indices are global; use insertGlobalIndices().");
2408 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2409 (! hasColMap (), std::runtime_error,
2410 "Cannot insert local indices without a column Map.");
2411 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2412 (! rowMap_->isNodeLocalElement (localRow), std::runtime_error,
2413 "Local row index " << localRow <<
" is not in the row Map "
2414 "on the calling process.");
2415 if (! indicesAreAllocated ()) {
2416 allocateIndices (LocalIndices, verbose_);
2425 using Teuchos::Array;
2426 using Teuchos::toString;
2428 typedef typename Teuchos::ArrayView<const LocalOrdinal>::size_type size_type;
2431 Array<LocalOrdinal> badColInds;
2432 bool allInColMap =
true;
2433 for (size_type k = 0; k < indices.size (); ++k) {
2435 allInColMap =
false;
2436 badColInds.push_back (indices[k]);
2439 if (! allInColMap) {
2440 std::ostringstream os;
2441 os <<
"Tpetra::CrsGraph::insertLocalIndices: You attempted to insert "
2442 "entries in owned row " << localRow <<
", at the following column "
2443 "indices: " << toString (indices) <<
"." << endl;
2444 os <<
"Of those, the following indices are not in the column Map on "
2445 "this process: " << toString (badColInds) <<
"." << endl <<
"Since "
2446 "the graph has a column Map already, it is invalid to insert entries "
2447 "at those locations.";
2448 TEUCHOS_TEST_FOR_EXCEPTION(! allInColMap, std::invalid_argument, os.str ());
2453 insertLocalIndicesImpl (localRow, indices);
2456 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2457 (! indicesAreAllocated () || ! isLocallyIndexed (), std::logic_error,
2458 "At the end of insertLocalIndices, ! indicesAreAllocated() || "
2459 "! isLocallyIndexed() is true. Please report this bug to the "
2460 "Tpetra developers.");
2464 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2468 const LocalOrdinal numEnt,
2469 const LocalOrdinal inds[])
2471 Teuchos::ArrayView<const LocalOrdinal> indsT (inds, numEnt);
2472 this->insertLocalIndices (localRow, indsT);
2476 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2480 const LocalOrdinal numInputInds,
2481 const GlobalOrdinal inputGblColInds[])
2483 typedef LocalOrdinal LO;
2484 const char tfecfFuncName[] =
"insertGlobalIndices: ";
2486 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2487 (this->isLocallyIndexed (), std::runtime_error,
2488 "graph indices are local; use insertLocalIndices().");
2493 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2494 (! this->isFillActive (), std::runtime_error,
2495 "You are not allowed to call this method if fill is not active. "
2496 "If fillComplete has been called, you must first call resumeFill "
2497 "before you may insert indices.");
2498 if (! indicesAreAllocated ()) {
2499 allocateIndices (GlobalIndices, verbose_);
2501 const LO lclRow = this->rowMap_->getLocalElement (gblRow);
2502 if (lclRow != Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
2504 if (this->hasColMap ()) {
2506 const map_type& colMap = * (this->colMap_);
2511 std::vector<GlobalOrdinal> badColInds;
2512 bool allInColMap =
true;
2513 for (LO k = 0; k < numInputInds; ++k) {
2515 allInColMap =
false;
2516 badColInds.push_back (inputGblColInds[k]);
2519 if (! allInColMap) {
2520 std::ostringstream os;
2521 os <<
"You attempted to insert entries in owned row " << gblRow
2522 <<
", at the following column indices: [";
2523 for (LO k = 0; k < numInputInds; ++k) {
2524 os << inputGblColInds[k];
2525 if (k + static_cast<LO> (1) < numInputInds) {
2529 os <<
"]." << endl <<
"Of those, the following indices are not in "
2530 "the column Map on this process: [";
2531 for (
size_t k = 0; k < badColInds.size (); ++k) {
2532 os << badColInds[k];
2533 if (k +
size_t (1) < badColInds.size ()) {
2537 os <<
"]." << endl <<
"Since the matrix has a column Map already, "
2538 "it is invalid to insert entries at those locations.";
2539 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2540 (
true, std::invalid_argument, os.str ());
2544 this->insertGlobalIndicesImpl (lclRow, inputGblColInds, numInputInds);
2547 this->insertGlobalIndicesIntoNonownedRows (gblRow, inputGblColInds,
2553 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2557 const Teuchos::ArrayView<const GlobalOrdinal>& inputGblColInds)
2559 this->insertGlobalIndices (gblRow, inputGblColInds.size (),
2560 inputGblColInds.getRawPtr ());
2564 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2568 const GlobalOrdinal gblColInds[],
2569 const LocalOrdinal numGblColInds)
2571 typedef LocalOrdinal LO;
2572 typedef GlobalOrdinal GO;
2573 const char tfecfFuncName[] =
"insertGlobalIndicesFiltered: ";
2575 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2576 (this->isLocallyIndexed (), std::runtime_error,
2577 "Graph indices are local; use insertLocalIndices().");
2582 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2583 (! this->isFillActive (), std::runtime_error,
2584 "You are not allowed to call this method if fill is not active. "
2585 "If fillComplete has been called, you must first call resumeFill "
2586 "before you may insert indices.");
2587 if (! indicesAreAllocated ()) {
2588 allocateIndices (GlobalIndices, verbose_);
2591 Teuchos::ArrayView<const GO> gblColInds_av (gblColInds, numGblColInds);
2593 if (! colMap_.is_null ()) {
2594 const map_type& colMap = * (this->colMap_);
2597 while (curOffset < numGblColInds) {
2601 LO endOffset = curOffset;
2602 for ( ; endOffset < numGblColInds; ++endOffset) {
2604 if (lclCol == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
2611 const LO numIndInSeq = (endOffset - curOffset);
2612 if (numIndInSeq != 0) {
2613 this->insertGlobalIndicesImpl (lclRow, gblColInds + curOffset,
2619 curOffset = endOffset + 1;
2623 this->insertGlobalIndicesImpl (lclRow, gblColInds_av.getRawPtr (),
2624 gblColInds_av.size ());
2628 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2632 const GlobalOrdinal gblColInds[],
2633 const LocalOrdinal numGblColInds)
2638 std::vector<GlobalOrdinal>& nonlocalRow = this->nonlocals_[gblRow];
2639 for (LocalOrdinal k = 0; k < numGblColInds; ++k) {
2643 nonlocalRow.push_back (gblColInds[k]);
2647 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2652 const char tfecfFuncName[] =
"removeLocalIndices: ";
2653 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2654 ! isFillActive (), std::runtime_error,
"requires that fill is active.");
2655 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2656 isStorageOptimized (), std::runtime_error,
2657 "cannot remove indices after optimizeStorage() has been called.");
2658 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2659 isGloballyIndexed (), std::runtime_error,
"graph indices are global.");
2660 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2661 ! rowMap_->isNodeLocalElement (lrow), std::runtime_error,
2662 "Local row " << lrow <<
" is not in the row Map on the calling process.");
2663 if (! indicesAreAllocated ()) {
2664 allocateIndices (LocalIndices, verbose_);
2667 if (k_numRowEntries_.extent (0) != 0) {
2668 this->k_numRowEntries_(lrow) = 0;
2672 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2673 (getNumEntriesInLocalRow (lrow) != 0 ||
2674 ! indicesAreAllocated () ||
2675 ! isLocallyIndexed (), std::logic_error,
2676 "Violated stated post-conditions. Please contact Tpetra team.");
2681 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2684 setAllIndices (
const typename local_graph_device_type::row_map_type& rowPointers,
2685 const typename local_graph_device_type::entries_type::non_const_type& columnIndices)
2688 ProfilingRegion region (
"Tpetra::CrsGraph::setAllIndices");
2689 const char tfecfFuncName[] =
"setAllIndices: ";
2690 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2691 ! hasColMap () || getColMap ().is_null (), std::runtime_error,
2692 "The graph must have a column Map before you may call this method.");
2693 LocalOrdinal numLocalRows = this->getLocalNumRows ();
2695 LocalOrdinal rowPtrLen = rowPointers.size();
2696 if(numLocalRows == 0) {
2697 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2698 rowPtrLen != 0 && rowPtrLen != 1,
2699 std::runtime_error,
"Have 0 local rows, but rowPointers.size() is neither 0 nor 1.");
2702 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2703 rowPtrLen != numLocalRows + 1,
2704 std::runtime_error,
"rowPointers.size() = " << rowPtrLen <<
2705 " != this->getLocalNumRows()+1 = " << (numLocalRows + 1) <<
".");
2710 using exec_space =
typename local_graph_device_type::execution_space;
2711 int columnsOutOfBounds = 0;
2713 Kokkos::parallel_reduce(Kokkos::RangePolicy<exec_space>(0, columnIndices.extent(0)),
2714 KOKKOS_LAMBDA (
const LocalOrdinal i,
int& lOutOfBounds)
2716 if(columnIndices(i) < 0 || columnIndices(i) >= numLocalCols)
2718 }, columnsOutOfBounds);
2719 int globalColsOutOfBounds= 0;
2720 auto comm = this->getComm();
2721 Teuchos::reduceAll<int, int> (*comm, Teuchos::REDUCE_MAX, columnsOutOfBounds,
2722 Teuchos::outArg (globalColsOutOfBounds));
2723 if (globalColsOutOfBounds)
2725 std::string message;
2726 if (columnsOutOfBounds)
2729 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not all within range [0, getLocalNumCols())!\n";
2732 throw std::invalid_argument(
"CrsGraph::setAllIndices(): columnIndices are out of the valid range on at least one process.");
2736 if (debug_ && this->isSorted()) {
2739 using exec_space =
typename local_graph_device_type::execution_space;
2740 using size_type =
typename local_graph_device_type::size_type;
2741 Kokkos::parallel_reduce(Kokkos::RangePolicy<exec_space>(0, numLocalRows),
2742 KOKKOS_LAMBDA (
const LocalOrdinal i,
int& lNotSorted)
2744 size_type rowBegin = rowPointers(i);
2745 size_type rowEnd = rowPointers(i + 1);
2746 for(size_type j = rowBegin + 1; j < rowEnd; j++)
2748 if(columnIndices(j - 1) > columnIndices(j))
2755 int globalNotSorted = 0;
2756 auto comm = this->getComm();
2757 Teuchos::reduceAll<int, int> (*comm, Teuchos::REDUCE_MAX, notSorted,
2758 Teuchos::outArg (globalNotSorted));
2759 if (globalNotSorted)
2761 std::string message;
2765 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not sorted!\n";
2768 throw std::invalid_argument(
"CrsGraph::setAllIndices(): provided columnIndices are not sorted within rows on at least one process.");
2772 indicesAreAllocated_ =
true;
2773 indicesAreLocal_ =
true;
2774 indicesAreSorted_ =
true;
2775 noRedundancies_ =
true;
2777 lclIndsUnpacked_wdv = lclIndsPacked_wdv;
2778 setRowPtrs(rowPointers);
2780 set_need_sync_host_uvm_access();
2784 storageStatus_ = Details::STORAGE_1D_PACKED;
2789 numAllocForAllRows_ = 0;
2790 k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
2792 checkInternalState ();
2796 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2800 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices)
2803 typedef typename local_graph_device_type::row_map_type row_map_type;
2804 typedef typename row_map_type::array_layout layout_type;
2805 typedef typename row_map_type::non_const_value_type row_offset_type;
2806 typedef View<
size_t*, layout_type , Kokkos::HostSpace,
2807 Kokkos::MemoryUnmanaged> input_view_type;
2808 typedef typename row_map_type::non_const_type nc_row_map_type;
2810 const size_t size =
static_cast<size_t> (rowPointers.size ());
2811 constexpr
bool same = std::is_same<size_t, row_offset_type>::value;
2812 input_view_type ptr_in (rowPointers.getRawPtr (), size);
2814 nc_row_map_type ptr_rot (
"Tpetra::CrsGraph::ptr", size);
2817 #ifdef KOKKOS_ENABLE_CXX17
2818 if constexpr (same) {
2819 using lexecution_space =
typename device_type::execution_space;
2829 input_view_type ptr_decoy (rowPointers.getRawPtr (), size);
2832 Kokkos::Impl::if_c<same,
2834 input_view_type>::select (ptr_rot, ptr_decoy),
2840 constexpr
bool inHostMemory =
2841 std::is_same<
typename row_map_type::memory_space,
2842 Kokkos::HostSpace>::value;
2853 View<size_t*, layout_type, device_type> ptr_st (
"Tpetra::CrsGraph::ptr", size);
2865 Kokkos::View<LocalOrdinal*, layout_type, device_type> k_ind =
2866 Kokkos::Compat::getKokkosViewDeepCopy<device_type> (columnIndices ());
2867 setAllIndices (ptr_rot, k_ind);
2871 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2876 using Teuchos::Comm;
2877 using Teuchos::outArg;
2880 using Teuchos::REDUCE_MAX;
2881 using Teuchos::REDUCE_MIN;
2882 using Teuchos::reduceAll;
2887 using size_type =
typename Teuchos::Array<GO>::size_type;
2888 const char tfecfFuncName[] =
"globalAssemble: ";
2890 std::unique_ptr<std::string> prefix;
2892 prefix = this->createPrefix(
"CrsGraph",
"globalAssemble");
2893 std::ostringstream os;
2894 os << *prefix <<
"Start" << endl;
2895 std::cerr << os.str();
2897 RCP<const Comm<int> > comm = getComm ();
2899 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2900 (! isFillActive (), std::runtime_error,
"Fill must be active before "
2901 "you may call this method.");
2903 const size_t myNumNonlocalRows = this->nonlocals_.size ();
2910 const int iHaveNonlocalRows = (myNumNonlocalRows == 0) ? 0 : 1;
2911 int someoneHasNonlocalRows = 0;
2912 reduceAll<int, int> (*comm, REDUCE_MAX, iHaveNonlocalRows,
2913 outArg (someoneHasNonlocalRows));
2914 if (someoneHasNonlocalRows == 0) {
2916 std::ostringstream os;
2917 os << *prefix <<
"Done: No nonlocal rows" << endl;
2918 std::cerr << os.str();
2922 else if (verbose_) {
2923 std::ostringstream os;
2924 os << *prefix <<
"At least 1 process has nonlocal rows"
2926 std::cerr << os.str();
2939 RCP<const map_type> nonlocalRowMap;
2941 Teuchos::Array<size_t> numEntPerNonlocalRow (myNumNonlocalRows);
2943 Teuchos::Array<GO> myNonlocalGblRows (myNumNonlocalRows);
2944 size_type curPos = 0;
2945 for (
auto mapIter = this->nonlocals_.begin ();
2946 mapIter != this->nonlocals_.end ();
2947 ++mapIter, ++curPos) {
2948 myNonlocalGblRows[curPos] = mapIter->first;
2949 std::vector<GO>& gblCols = mapIter->second;
2950 std::sort (gblCols.begin (), gblCols.end ());
2951 auto vecLast = std::unique (gblCols.begin (), gblCols.end ());
2952 gblCols.erase (vecLast, gblCols.end ());
2953 numEntPerNonlocalRow[curPos] = gblCols.size ();
2964 GO myMinNonlocalGblRow = std::numeric_limits<GO>::max ();
2966 auto iter = std::min_element (myNonlocalGblRows.begin (),
2967 myNonlocalGblRows.end ());
2968 if (iter != myNonlocalGblRows.end ()) {
2969 myMinNonlocalGblRow = *iter;
2972 GO gblMinNonlocalGblRow = 0;
2973 reduceAll<int, GO> (*comm, REDUCE_MIN, myMinNonlocalGblRow,
2974 outArg (gblMinNonlocalGblRow));
2975 const GO indexBase = gblMinNonlocalGblRow;
2976 const global_size_t INV = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2977 nonlocalRowMap = rcp (
new map_type (INV, myNonlocalGblRows (), indexBase, comm));
2981 std::ostringstream os;
2982 os << *prefix <<
"nonlocalRowMap->getIndexBase()="
2983 << nonlocalRowMap->getIndexBase() << endl;
2984 std::cerr << os.str();
2992 RCP<crs_graph_type> nonlocalGraph =
2993 rcp(
new crs_graph_type(nonlocalRowMap, numEntPerNonlocalRow()));
2995 size_type curPos = 0;
2996 for (
auto mapIter = this->nonlocals_.begin ();
2997 mapIter != this->nonlocals_.end ();
2998 ++mapIter, ++curPos) {
2999 const GO gblRow = mapIter->first;
3000 std::vector<GO>& gblCols = mapIter->second;
3001 const LO numEnt =
static_cast<LO
> (numEntPerNonlocalRow[curPos]);
3002 nonlocalGraph->insertGlobalIndices (gblRow, numEnt, gblCols.data ());
3006 std::ostringstream os;
3007 os << *prefix <<
"Built nonlocal graph" << endl;
3008 std::cerr << os.str();
3019 auto origRowMap = this->getRowMap ();
3020 const bool origRowMapIsOneToOne = origRowMap->isOneToOne ();
3022 if (origRowMapIsOneToOne) {
3024 std::ostringstream os;
3025 os << *prefix <<
"Original row Map is 1-to-1" << endl;
3026 std::cerr << os.str();
3028 export_type exportToOrig (nonlocalRowMap, origRowMap);
3034 std::ostringstream os;
3035 os << *prefix <<
"Original row Map is NOT 1-to-1" << endl;
3036 std::cerr << os.str();
3043 export_type exportToOneToOne (nonlocalRowMap, oneToOneRowMap);
3049 crs_graph_type oneToOneGraph (oneToOneRowMap, 0);
3053 std::ostringstream os;
3054 os << *prefix <<
"Export nonlocal graph" << endl;
3055 std::cerr << os.str();
3057 oneToOneGraph.doExport (*nonlocalGraph, exportToOneToOne,
Tpetra::INSERT);
3061 nonlocalGraph = Teuchos::null;
3064 import_type importToOrig (oneToOneRowMap, origRowMap);
3066 std::ostringstream os;
3067 os << *prefix <<
"Import nonlocal graph" << endl;
3068 std::cerr << os.str();
3077 decltype (this->nonlocals_) newNonlocals;
3078 std::swap (this->nonlocals_, newNonlocals);
3080 checkInternalState ();
3082 std::ostringstream os;
3083 os << *prefix <<
"Done" << endl;
3084 std::cerr << os.str();
3089 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3094 clearGlobalConstants();
3095 if (params != Teuchos::null) this->setParameterList (params);
3097 indicesAreSorted_ =
true;
3098 noRedundancies_ =
true;
3099 fillComplete_ =
false;
3103 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3118 Teuchos::RCP<const map_type> domMap = this->getDomainMap ();
3119 if (domMap.is_null ()) {
3120 domMap = this->getRowMap ();
3122 Teuchos::RCP<const map_type> ranMap = this->getRangeMap ();
3123 if (ranMap.is_null ()) {
3124 ranMap = this->getRowMap ();
3126 this->fillComplete (domMap, ranMap, params);
3130 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3134 const Teuchos::RCP<const map_type>& rangeMap,
3135 const Teuchos::RCP<Teuchos::ParameterList>& params)
3138 const char tfecfFuncName[] =
"fillComplete: ";
3139 const bool verbose = verbose_;
3141 std::unique_ptr<std::string> prefix;
3143 prefix = this->createPrefix(
"CrsGraph",
"fillComplete");
3144 std::ostringstream os;
3145 os << *prefix <<
"Start" << endl;
3146 std::cerr << os.str();
3149 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3150 (! isFillActive () || isFillComplete (), std::runtime_error,
3151 "Graph fill state must be active (isFillActive() "
3152 "must be true) before calling fillComplete().");
3154 const int numProcs = getComm ()->getSize ();
3162 if (! params.is_null ()) {
3163 if (params->isParameter (
"sort column map ghost gids")) {
3164 sortGhostsAssociatedWithEachProcessor_ =
3165 params->get<
bool> (
"sort column map ghost gids",
3166 sortGhostsAssociatedWithEachProcessor_);
3168 else if (params->isParameter (
"Sort column Map ghost GIDs")) {
3169 sortGhostsAssociatedWithEachProcessor_ =
3170 params->get<
bool> (
"Sort column Map ghost GIDs",
3171 sortGhostsAssociatedWithEachProcessor_);
3177 bool assertNoNonlocalInserts =
false;
3178 if (! params.is_null ()) {
3179 assertNoNonlocalInserts =
3180 params->get<
bool> (
"No Nonlocal Changes", assertNoNonlocalInserts);
3186 if (! indicesAreAllocated ()) {
3189 allocateIndices (LocalIndices, verbose);
3192 allocateIndices (GlobalIndices, verbose);
3200 const bool mayNeedGlobalAssemble = ! assertNoNonlocalInserts && numProcs > 1;
3201 if (mayNeedGlobalAssemble) {
3207 const size_t numNonlocals = nonlocals_.size();
3209 std::ostringstream os;
3210 os << *prefix <<
"Do not need to call globalAssemble; "
3211 "assertNoNonlocalInserts="
3212 << (assertNoNonlocalInserts ?
"true" :
"false")
3213 <<
"numProcs=" << numProcs
3214 <<
", nonlocals_.size()=" << numNonlocals << endl;
3215 std::cerr << os.str();
3217 const int lclNeededGlobalAssemble =
3218 (numProcs > 1 && numNonlocals != 0) ? 1 : 0;
3219 if (lclNeededGlobalAssemble != 0 && verbose) {
3220 std::ostringstream os;
3222 Details::Impl::verbosePrintMap(
3223 os, nonlocals_.begin(), nonlocals_.end(),
3224 nonlocals_.size(),
"nonlocals_");
3225 std::cerr << os.str() << endl;
3229 auto map = this->getMap();
3230 auto comm = map.is_null() ? Teuchos::null : map->getComm();
3231 int gblNeededGlobalAssemble = lclNeededGlobalAssemble;
3232 if (! comm.is_null()) {
3233 using Teuchos::REDUCE_MAX;
3234 using Teuchos::reduceAll;
3235 reduceAll(*comm, REDUCE_MAX, lclNeededGlobalAssemble,
3236 Teuchos::outArg(gblNeededGlobalAssemble));
3238 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3239 (gblNeededGlobalAssemble != 0, std::runtime_error,
3240 "nonlocals_.size()=" << numNonlocals <<
" != 0 on at "
3241 "least one process in the CrsGraph's communicator. This "
3242 "means either that you incorrectly set the "
3243 "\"No Nonlocal Changes\" fillComplete parameter to true, "
3244 "or that you inserted invalid entries. "
3245 "Rerun with the environment variable TPETRA_VERBOSE="
3246 "CrsGraph set to see the entries of nonlocals_ on every "
3247 "MPI process (WARNING: lots of output).");
3250 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3251 (lclNeededGlobalAssemble != 0, std::runtime_error,
3252 "nonlocals_.size()=" << numNonlocals <<
" != 0 on the "
3253 "calling process. This means either that you incorrectly "
3254 "set the \"No Nonlocal Changes\" fillComplete parameter "
3255 "to true, or that you inserted invalid entries. "
3256 "Rerun with the environment "
3257 "variable TPETRA_VERBOSE=CrsGraph set to see the entries "
3258 "of nonlocals_ on every MPI process (WARNING: lots of "
3265 setDomainRangeMaps (domainMap, rangeMap);
3271 Teuchos::Array<int> remotePIDs (0);
3272 const bool mustBuildColMap = ! this->hasColMap ();
3273 if (mustBuildColMap) {
3279 const std::pair<size_t, std::string> makeIndicesLocalResult =
3280 this->makeIndicesLocal(verbose);
3285 using Teuchos::REDUCE_MIN;
3286 using Teuchos::reduceAll;
3287 using Teuchos::outArg;
3289 RCP<const map_type> map = this->getMap ();
3290 RCP<const Teuchos::Comm<int> > comm;
3291 if (! map.is_null ()) {
3292 comm = map->getComm ();
3294 if (comm.is_null ()) {
3295 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3296 (makeIndicesLocalResult.first != 0, std::runtime_error,
3297 makeIndicesLocalResult.second);
3300 const int lclSuccess = (makeIndicesLocalResult.first == 0);
3302 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
3303 if (gblSuccess != 1) {
3304 std::ostringstream os;
3305 gathervPrint (os, makeIndicesLocalResult.second, *comm);
3306 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3307 (
true, std::runtime_error, os.str ());
3316 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3317 (makeIndicesLocalResult.first != 0, std::runtime_error,
3318 makeIndicesLocalResult.second);
3324 this->sortAndMergeAllIndices (this->isSorted (), this->isMerged ());
3329 this->makeImportExport (remotePIDs, mustBuildColMap);
3332 this->fillLocalGraph (params);
3334 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
3335 params->get (
"compute global constants",
true);
3336 if (callComputeGlobalConstants) {
3337 this->computeGlobalConstants ();
3340 this->computeLocalConstants ();
3342 this->fillComplete_ =
true;
3343 this->checkInternalState ();
3346 std::ostringstream os;
3347 os << *prefix <<
"Done" << endl;
3348 std::cerr << os.str();
3353 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3357 const Teuchos::RCP<const map_type>& rangeMap,
3358 const Teuchos::RCP<const import_type>& importer,
3359 const Teuchos::RCP<const export_type>& exporter,
3360 const Teuchos::RCP<Teuchos::ParameterList>& params)
3362 const char tfecfFuncName[] =
"expertStaticFillComplete: ";
3363 #ifdef HAVE_TPETRA_MMM_TIMINGS
3365 if(!params.is_null())
3366 label = params->get(
"Timer Label",label);
3367 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
": ");
3368 using Teuchos::TimeMonitor;
3369 Teuchos::RCP<Teuchos::TimeMonitor> MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Setup"))));
3373 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3374 domainMap.is_null () || rangeMap.is_null (),
3375 std::runtime_error,
"The input domain Map and range Map must be nonnull.");
3376 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3377 isFillComplete () || ! hasColMap (), std::runtime_error,
"You may not "
3378 "call this method unless the graph has a column Map.");
3379 auto rowPtrsUnpackedLength = this->getRowPtrsUnpackedHost().extent (0);
3380 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3381 getLocalNumRows () > 0 && rowPtrsUnpackedLength == 0,
3382 std::runtime_error,
"The calling process has getLocalNumRows() = "
3383 << getLocalNumRows () <<
" > 0 rows, but the row offsets array has not "
3385 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3386 static_cast<size_t> (rowPtrsUnpackedLength) != getLocalNumRows () + 1,
3387 std::runtime_error,
"The row offsets array has length " <<
3388 rowPtrsUnpackedLength <<
" != getLocalNumRows()+1 = " <<
3389 (getLocalNumRows () + 1) <<
".");
3404 numAllocForAllRows_ = 0;
3405 k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
3406 indicesAreAllocated_ =
true;
3411 indicesAreLocal_ =
true;
3412 indicesAreGlobal_ =
false;
3415 #ifdef HAVE_TPETRA_MMM_TIMINGS
3417 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Maps"))));
3419 setDomainRangeMaps (domainMap, rangeMap);
3422 indicesAreSorted_ =
true;
3423 noRedundancies_ =
true;
3426 #ifdef HAVE_TPETRA_MMM_TIMINGS
3428 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckI"))));
3431 importer_ = Teuchos::null;
3432 exporter_ = Teuchos::null;
3433 if (importer != Teuchos::null) {
3434 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3435 ! importer->getSourceMap ()->isSameAs (*getDomainMap ()) ||
3436 ! importer->getTargetMap ()->isSameAs (*getColMap ()),
3437 std::invalid_argument,
": importer does not match matrix maps.");
3438 importer_ = importer;
3442 #ifdef HAVE_TPETRA_MMM_TIMINGS
3444 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckE"))));
3447 if (exporter != Teuchos::null) {
3448 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3449 ! exporter->getSourceMap ()->isSameAs (*getRowMap ()) ||
3450 ! exporter->getTargetMap ()->isSameAs (*getRangeMap ()),
3451 std::invalid_argument,
": exporter does not match matrix maps.");
3452 exporter_ = exporter;
3455 #ifdef HAVE_TPETRA_MMM_TIMINGS
3457 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXmake"))));
3459 Teuchos::Array<int> remotePIDs (0);
3460 this->makeImportExport (remotePIDs,
false);
3462 #ifdef HAVE_TPETRA_MMM_TIMINGS
3464 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-fLG"))));
3466 this->fillLocalGraph (params);
3468 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
3469 params->get (
"compute global constants",
true);
3471 if (callComputeGlobalConstants) {
3472 #ifdef HAVE_TPETRA_MMM_TIMINGS
3474 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (const)"))));
3475 #endif // HAVE_TPETRA_MMM_TIMINGS
3476 this->computeGlobalConstants ();
3479 #ifdef HAVE_TPETRA_MMM_TIMINGS
3481 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (noconst)"))));
3482 #endif // HAVE_TPETRA_MMM_TIMINGS
3483 this->computeLocalConstants ();
3486 fillComplete_ =
true;
3488 #ifdef HAVE_TPETRA_MMM_TIMINGS
3490 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cIS"))));
3492 checkInternalState ();
3496 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3499 fillLocalGraph (
const Teuchos::RCP<Teuchos::ParameterList>& params)
3502 typedef typename local_graph_device_type::row_map_type row_map_type;
3503 typedef typename row_map_type::non_const_type non_const_row_map_type;
3504 typedef typename local_graph_device_type::entries_type::non_const_type lclinds_1d_type;
3505 const char tfecfFuncName[] =
"fillLocalGraph (called from fillComplete or "
3506 "expertStaticFillComplete): ";
3507 const size_t lclNumRows = this->getLocalNumRows ();
3512 bool requestOptimizedStorage =
true;
3513 if (! params.is_null () && ! params->get (
"Optimize Storage",
true)) {
3514 requestOptimizedStorage =
false;
3522 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3524 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3525 (rowPtrsUnpacked.extent (0) == 0, std::logic_error,
3526 "rowPtrsUnpacked_host_ has size zero, but shouldn't");
3527 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3528 (rowPtrsUnpacked.extent (0) != lclNumRows + 1, std::logic_error,
3529 "rowPtrsUnpacked_host_.extent(0) = "
3530 << rowPtrsUnpacked.extent (0) <<
" != (lclNumRows + 1) = "
3531 << (lclNumRows + 1) <<
".");
3532 const size_t numOffsets = rowPtrsUnpacked.extent (0);
3533 const auto valToCheck = rowPtrsUnpacked(numOffsets-1);
3534 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3536 lclIndsUnpacked_wdv.extent (0) != valToCheck,
3537 std::logic_error,
"numOffsets=" << numOffsets <<
" != 0 "
3538 " and lclIndsUnpacked_wdv.extent(0)=" << lclIndsUnpacked_wdv.extent(0)
3539 <<
" != rowPtrsUnpacked_host_(" << numOffsets <<
")=" << valToCheck
3543 size_t allocSize = 0;
3545 allocSize = this->getLocalAllocationSize ();
3547 catch (std::logic_error& e) {
3548 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3549 (
true, std::logic_error,
"getLocalAllocationSize threw "
3550 "std::logic_error: " << e.what ());
3552 catch (std::runtime_error& e) {
3553 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3554 (
true, std::runtime_error,
"getLocalAllocationSize threw "
3555 "std::runtime_error: " << e.what ());
3557 catch (std::exception& e) {
3558 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3559 (
true, std::runtime_error,
"getLocalAllocationSize threw "
3560 "std::exception: " << e.what ());
3563 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3564 (
true, std::runtime_error,
"getLocalAllocationSize threw "
3565 "an exception not a subclass of std::exception.");
3568 if (this->getLocalNumEntries () != allocSize) {
3571 non_const_row_map_type ptr_d;
3572 row_map_type ptr_d_const;
3581 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3582 if (rowPtrsUnpacked.extent (0) != 0) {
3583 const size_t numOffsets =
3584 static_cast<size_t> (rowPtrsUnpacked.extent (0));
3585 const auto valToCheck = rowPtrsUnpacked(numOffsets - 1);
3586 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3587 (valToCheck !=
size_t(lclIndsUnpacked_wdv.extent(0)),
3588 std::logic_error,
"(Unpacked branch) Before allocating "
3589 "or packing, k_rowPtrs_(" << (numOffsets-1) <<
")="
3590 << valToCheck <<
" != lclIndsUnpacked_wdv.extent(0)="
3591 << lclIndsUnpacked_wdv.extent (0) <<
".");
3601 size_t lclTotalNumEntries = 0;
3605 non_const_row_map_type (
"Tpetra::CrsGraph::ptr", lclNumRows + 1);
3606 ptr_d_const = ptr_d;
3610 typename num_row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
3612 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3613 (
size_t(numRowEnt_h.extent (0)) != lclNumRows,
3614 std::logic_error,
"(Unpacked branch) "
3615 "numRowEnt_h.extent(0)=" << numRowEnt_h.extent(0)
3616 <<
" != getLocalNumRows()=" << lclNumRows <<
"");
3622 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3623 (static_cast<size_t> (ptr_d.extent (0)) != lclNumRows + 1,
3624 std::logic_error,
"(Unpacked branch) After allocating "
3625 "ptr_d, ptr_d.extent(0) = " << ptr_d.extent(0)
3626 <<
" != lclNumRows+1 = " << (lclNumRows+1) <<
".");
3627 const auto valToCheck =
3628 ::Tpetra::Details::getEntryOnHost (ptr_d, lclNumRows);
3629 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3630 (valToCheck != lclTotalNumEntries, std::logic_error,
3631 "Tpetra::CrsGraph::fillLocalGraph: In unpacked branch, "
3632 "after filling ptr_d, ptr_d(lclNumRows=" << lclNumRows
3633 <<
") = " << valToCheck <<
" != total number of entries "
3634 "on the calling process = " << lclTotalNumEntries
3640 lclinds_1d_type ind_d =
3641 lclinds_1d_type (
"Tpetra::CrsGraph::lclInd", lclTotalNumEntries);
3653 typedef pack_functor<
3654 typename local_graph_device_type::entries_type::non_const_type,
3655 typename local_inds_dualv_type::t_dev::const_type,
3657 typename local_graph_device_type::row_map_type> inds_packer_type;
3658 inds_packer_type f (ind_d,
3659 lclIndsUnpacked_wdv.getDeviceView(Access::ReadOnly),
3660 ptr_d, this->getRowPtrsUnpackedDevice());
3662 typedef typename decltype (ind_d)::execution_space exec_space;
3663 typedef Kokkos::RangePolicy<exec_space, LocalOrdinal> range_type;
3664 Kokkos::parallel_for (range_type (0, lclNumRows), f);
3668 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3669 (ptr_d.extent (0) == 0, std::logic_error,
3670 "(\"Optimize Storage\"=true branch) After packing, "
3671 "ptr_d.extent(0)=0.");
3672 if (ptr_d.extent (0) != 0) {
3673 const size_t numOffsets =
static_cast<size_t> (ptr_d.extent (0));
3674 const auto valToCheck =
3675 ::Tpetra::Details::getEntryOnHost (ptr_d, numOffsets - 1);
3676 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3677 (static_cast<size_t> (valToCheck) != ind_d.extent (0),
3678 std::logic_error,
"(\"Optimize Storage\"=true branch) "
3679 "After packing, ptr_d(" << (numOffsets-1) <<
")="
3680 << valToCheck <<
" != ind_d.extent(0)="
3681 << ind_d.extent(0) <<
".");
3685 if (requestOptimizedStorage)
3686 setRowPtrs(ptr_d_const);
3688 setRowPtrsPacked(ptr_d_const);
3689 lclIndsPacked_wdv = local_inds_wdv_type(ind_d);
3693 this->setRowPtrs(rowPtrsUnpacked_dev_);
3694 lclIndsPacked_wdv = lclIndsUnpacked_wdv;
3697 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3698 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3699 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3700 (rowPtrsPacked_dev.extent (0) == 0, std::logic_error,
3701 "(\"Optimize Storage\"=false branch) "
3702 "rowPtrsPacked_dev_.extent(0) = 0.");
3703 if (rowPtrsPacked_dev.extent (0) != 0) {
3704 const size_t numOffsets =
3705 static_cast<size_t> (rowPtrsPacked_dev.extent (0));
3706 const size_t valToCheck =
3707 rowPtrsPacked_host(numOffsets - 1);
3708 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3709 (valToCheck !=
size_t(lclIndsPacked_wdv.extent (0)),
3710 std::logic_error,
"(\"Optimize Storage\"=false branch) "
3711 "rowPtrsPacked_dev_(" << (numOffsets-1) <<
")="
3713 <<
" != lclIndsPacked_wdv.extent(0)="
3714 << lclIndsPacked_wdv.extent (0) <<
".");
3720 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3721 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3722 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3723 (static_cast<size_t> (rowPtrsPacked_dev.extent (0)) != lclNumRows + 1,
3724 std::logic_error,
"After packing, rowPtrsPacked_dev_.extent(0) = " <<
3725 rowPtrsPacked_dev.extent (0) <<
" != lclNumRows+1 = " << (lclNumRows+1)
3727 if (rowPtrsPacked_dev.extent (0) != 0) {
3728 const size_t numOffsets =
static_cast<size_t> (rowPtrsPacked_dev.extent (0));
3729 const auto valToCheck = rowPtrsPacked_host(numOffsets - 1);
3730 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3731 (static_cast<size_t> (valToCheck) != lclIndsPacked_wdv.extent (0),
3732 std::logic_error,
"After packing, rowPtrsPacked_dev_(" << (numOffsets-1)
3733 <<
") = " << valToCheck <<
" != lclIndsPacked_wdv.extent(0) = "
3734 << lclIndsPacked_wdv.extent (0) <<
".");
3738 if (requestOptimizedStorage) {
3744 k_numRowEntries_ = num_row_entries_type ();
3747 lclIndsUnpacked_wdv = lclIndsPacked_wdv;
3749 storageStatus_ = Details::STORAGE_1D_PACKED;
3752 set_need_sync_host_uvm_access();
3755 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3767 const char tfecfFuncName[] =
"replaceColMap: ";
3768 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3769 isLocallyIndexed () || isGloballyIndexed (), std::runtime_error,
3770 "Requires matching maps and non-static graph.");
3771 colMap_ = newColMap;
3774 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3778 const Teuchos::RCP<const import_type>& newImport,
3779 const bool sortIndicesInEachRow)
3781 using Teuchos::REDUCE_MIN;
3782 using Teuchos::reduceAll;
3784 typedef GlobalOrdinal GO;
3785 typedef LocalOrdinal LO;
3786 typedef typename local_inds_dualv_type::t_host col_inds_type;
3787 const char tfecfFuncName[] =
"reindexColumns: ";
3789 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3790 isFillComplete (), std::runtime_error,
"The graph is fill complete "
3791 "(isFillComplete() returns true). You must call resumeFill() before "
3792 "you may call this method.");
3810 const LO lclNumRows =
static_cast<LO
> (this->getLocalNumRows ());
3825 bool allCurColIndsValid =
true;
3830 bool localSuffices =
true;
3838 col_inds_type newLclInds1D;
3839 auto oldLclInds1D = lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
3844 if (indicesAreAllocated ()) {
3845 if (isLocallyIndexed ()) {
3847 const map_type& oldColMap = * (getColMap ());
3849 const size_t allocSize = this->getLocalAllocationSize ();
3850 newLclInds1D = col_inds_type(
"Tpetra::CrsGraph::lclIndsReindexedHost",
3853 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
3854 const RowInfo rowInfo = this->getRowInfo (lclRow);
3855 const size_t beg = rowInfo.offset1D;
3856 const size_t end = beg + rowInfo.numEntries;
3857 for (
size_t k = beg; k < end; ++k) {
3858 const LO oldLclCol = oldLclInds1D(k);
3859 if (oldLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
3860 allCurColIndsValid =
false;
3868 if (gblCol == Teuchos::OrdinalTraits<GO>::invalid ()) {
3869 allCurColIndsValid =
false;
3873 const LO newLclCol = newColMap->getLocalElement (gblCol);
3874 if (newLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
3875 localSuffices =
false;
3878 newLclInds1D(k) = newLclCol;
3889 allCurColIndsValid =
false;
3906 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
3907 const RowInfo rowInfo = this->getRowInfo (lclRow);
3908 auto oldGblRowView = this->getGlobalIndsViewHost (rowInfo);
3909 for (
size_t k = 0; k < rowInfo.numEntries; ++k) {
3910 const GO gblCol = oldGblRowView(k);
3911 if (! newColMap->isNodeGlobalElement (gblCol)) {
3912 localSuffices =
false;
3922 lclSuccess[0] = allCurColIndsValid ? 1 : 0;
3923 lclSuccess[1] = localSuffices ? 1 : 0;
3927 RCP<const Teuchos::Comm<int> > comm =
3928 getRowMap ().is_null () ? Teuchos::null : getRowMap ()->getComm ();
3929 if (! comm.is_null ()) {
3930 reduceAll<int, int> (*comm, REDUCE_MIN, 2, lclSuccess, gblSuccess);
3933 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3934 gblSuccess[0] == 0, std::runtime_error,
"It is not possible to continue."
3935 " The most likely reason is that the graph is locally indexed, but the "
3936 "column Map is missing (null) on some processes, due to a previous call "
3937 "to replaceColMap().");
3939 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3940 gblSuccess[1] == 0, std::runtime_error,
"On some process, the graph "
3941 "contains column indices that are in the old column Map, but not in the "
3942 "new column Map (on that process). This method does NOT redistribute "
3943 "data; it does not claim to do the work of an Import or Export operation."
3944 " This means that for all processess, the calling process MUST own all "
3945 "column indices, in both the old column Map and the new column Map. In "
3946 "this case, you will need to do an Import or Export operation to "
3947 "redistribute data.");
3950 if (isLocallyIndexed ()) {
3952 typename local_inds_dualv_type::t_dev newLclInds1D_dev(
3953 Kokkos::view_alloc(
"Tpetra::CrsGraph::lclIndReindexed",
3954 Kokkos::WithoutInitializing),
3955 newLclInds1D.extent(0));
3966 indicesAreSorted_ =
false;
3967 if (sortIndicesInEachRow) {
3974 const bool sorted =
false;
3975 const bool merged =
true;
3976 this->sortAndMergeAllIndices (sorted, merged);
3979 colMap_ = newColMap;
3981 if (newImport.is_null ()) {
3989 if (! domainMap_.is_null ()) {
3990 if (! domainMap_->isSameAs (* newColMap)) {
3991 importer_ = Teuchos::rcp (
new import_type (domainMap_, newColMap));
3993 importer_ = Teuchos::null;
3998 importer_ = newImport;
4002 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4007 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMap: ";
4008 TEUCHOS_TEST_FOR_EXCEPTION(
4009 colMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4010 "this method unless the graph already has a column Map.");
4011 TEUCHOS_TEST_FOR_EXCEPTION(
4012 newDomainMap.is_null (), std::invalid_argument,
4013 prefix <<
"The new domain Map must be nonnull.");
4016 Teuchos::RCP<const import_type> newImporter = Teuchos::null;
4017 if (newDomainMap != colMap_ && (! newDomainMap->isSameAs (*colMap_))) {
4018 newImporter = rcp(
new import_type(newDomainMap, colMap_));
4020 this->replaceDomainMapAndImporter(newDomainMap, newImporter);
4023 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4027 const Teuchos::RCP<const import_type>& newImporter)
4029 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMapAndImporter: ";
4030 TEUCHOS_TEST_FOR_EXCEPTION(
4031 colMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4032 "this method unless the graph already has a column Map.");
4033 TEUCHOS_TEST_FOR_EXCEPTION(
4034 newDomainMap.is_null (), std::invalid_argument,
4035 prefix <<
"The new domain Map must be nonnull.");
4038 if (newImporter.is_null ()) {
4043 const bool colSameAsDom = colMap_->isSameAs (*newDomainMap);
4044 TEUCHOS_TEST_FOR_EXCEPTION
4045 (!colSameAsDom, std::invalid_argument,
"If the new Import is null, "
4046 "then the new domain Map must be the same as the current column Map.");
4049 const bool colSameAsTgt =
4050 colMap_->isSameAs (* (newImporter->getTargetMap ()));
4051 const bool newDomSameAsSrc =
4052 newDomainMap->isSameAs (* (newImporter->getSourceMap ()));
4053 TEUCHOS_TEST_FOR_EXCEPTION
4054 (! colSameAsTgt || ! newDomSameAsSrc, std::invalid_argument,
"If the "
4055 "new Import is nonnull, then the current column Map must be the same "
4056 "as the new Import's target Map, and the new domain Map must be the "
4057 "same as the new Import's source Map.");
4061 domainMap_ = newDomainMap;
4062 importer_ = Teuchos::rcp_const_cast<
import_type> (newImporter);
4065 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4070 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMap: ";
4071 TEUCHOS_TEST_FOR_EXCEPTION(
4072 rowMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4073 "this method unless the graph already has a row Map.");
4074 TEUCHOS_TEST_FOR_EXCEPTION(
4075 newRangeMap.is_null (), std::invalid_argument,
4076 prefix <<
"The new range Map must be nonnull.");
4079 Teuchos::RCP<const export_type> newExporter = Teuchos::null;
4080 if (newRangeMap != rowMap_ && (! newRangeMap->isSameAs (*rowMap_))) {
4081 newExporter = rcp(
new export_type(rowMap_, newRangeMap));
4083 this->replaceRangeMapAndExporter(newRangeMap, newExporter);
4086 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4090 const Teuchos::RCP<const export_type>& newExporter)
4092 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMapAndExporter: ";
4093 TEUCHOS_TEST_FOR_EXCEPTION(
4094 rowMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4095 "this method unless the graph already has a column Map.");
4096 TEUCHOS_TEST_FOR_EXCEPTION(
4097 newRangeMap.is_null (), std::invalid_argument,
4098 prefix <<
"The new domain Map must be nonnull.");
4101 if (newExporter.is_null ()) {
4106 const bool rowSameAsRange = rowMap_->isSameAs (*newRangeMap);
4107 TEUCHOS_TEST_FOR_EXCEPTION
4108 (!rowSameAsRange, std::invalid_argument,
"If the new Export is null, "
4109 "then the new range Map must be the same as the current row Map.");
4112 const bool newRangeSameAsTgt =
4113 newRangeMap->isSameAs (* (newExporter->getTargetMap ()));
4114 const bool rowSameAsSrc =
4115 rowMap_->isSameAs (* (newExporter->getSourceMap ()));
4116 TEUCHOS_TEST_FOR_EXCEPTION
4117 (! rowSameAsSrc || ! newRangeSameAsTgt, std::invalid_argument,
"If the "
4118 "new Export is nonnull, then the current row Map must be the same "
4119 "as the new Export's source Map, and the new range Map must be the "
4120 "same as the new Export's target Map.");
4124 rangeMap_ = newRangeMap;
4125 exporter_ = Teuchos::rcp_const_cast<
export_type> (newExporter);
4129 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4135 lclIndsPacked_wdv.getDeviceView(Access::ReadWrite),
4136 this->getRowPtrsPackedDevice());
4139 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4144 return local_graph_host_type(
4145 lclIndsPacked_wdv.getHostView(Access::ReadWrite),
4146 this->getRowPtrsPackedHost());
4149 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4154 using ::Tpetra::Details::ProfilingRegion;
4155 using Teuchos::ArrayView;
4156 using Teuchos::outArg;
4157 using Teuchos::reduceAll;
4160 ProfilingRegion regionCGC (
"Tpetra::CrsGraph::computeGlobalConstants");
4162 this->computeLocalConstants ();
4167 if (! this->haveGlobalConstants_) {
4168 const Teuchos::Comm<int>& comm = * (this->getComm ());
4182 lcl =
static_cast<GST
> (this->getLocalNumEntries ());
4184 reduceAll<int,GST> (comm, Teuchos::REDUCE_SUM, 1, &lcl, &gbl);
4185 this->globalNumEntries_ = gbl;
4187 const GST lclMaxNumRowEnt =
static_cast<GST
> (this->nodeMaxNumRowEntries_);
4188 reduceAll<int, GST> (comm, Teuchos::REDUCE_MAX, lclMaxNumRowEnt,
4189 outArg (this->globalMaxNumRowEntries_));
4190 this->haveGlobalConstants_ =
true;
4195 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4200 using ::Tpetra::Details::ProfilingRegion;
4202 ProfilingRegion regionCLC (
"Tpetra::CrsGraph::computeLocalConstants");
4203 if (this->haveLocalConstants_) {
4208 this->nodeMaxNumRowEntries_ =
4209 Teuchos::OrdinalTraits<size_t>::invalid();
4213 auto ptr = this->getRowPtrsPackedDevice();
4214 const LO lclNumRows = ptr.extent(0) == 0 ?
4215 static_cast<LO
> (0) :
4216 (static_cast<LO> (ptr.extent(0)) - static_cast<LO> (1));
4218 const LO lclMaxNumRowEnt =
4219 ::Tpetra::Details::maxDifference (
"Tpetra::CrsGraph: nodeMaxNumRowEntries",
4221 this->nodeMaxNumRowEntries_ =
static_cast<size_t> (lclMaxNumRowEnt);
4222 this->haveLocalConstants_ =
true;
4226 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4227 std::pair<size_t, std::string>
4232 using Teuchos::arcp;
4233 using Teuchos::Array;
4235 typedef LocalOrdinal LO;
4236 typedef GlobalOrdinal GO;
4238 typedef typename local_graph_device_type::row_map_type::non_const_value_type offset_type;
4239 typedef typename num_row_entries_type::non_const_value_type num_ent_type;
4240 const char tfecfFuncName[] =
"makeIndicesLocal: ";
4241 ProfilingRegion regionMakeIndicesLocal (
"Tpetra::CrsGraph::makeIndicesLocal");
4243 std::unique_ptr<std::string> prefix;
4245 prefix = this->createPrefix(
"CrsGraph",
"makeIndicesLocal");
4246 std::ostringstream os;
4247 os << *prefix <<
"lclNumRows: " << getLocalNumRows() << endl;
4248 std::cerr << os.str();
4253 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4254 (! this->hasColMap (), std::logic_error,
"The graph does not have a "
4255 "column Map yet. This method should never be called in that case. "
4256 "Please report this bug to the Tpetra developers.");
4257 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4258 (this->getColMap ().is_null (), std::logic_error,
"The graph claims "
4259 "that it has a column Map, because hasColMap() returns true. However, "
4260 "the result of getColMap() is null. This should never happen. Please "
4261 "report this bug to the Tpetra developers.");
4266 size_t lclNumErrs = 0;
4267 std::ostringstream errStrm;
4269 const LO lclNumRows =
static_cast<LO
> (this->getLocalNumRows ());
4270 const map_type& colMap = * (this->getColMap ());
4272 if (this->isGloballyIndexed () && lclNumRows != 0) {
4274 typename num_row_entries_type::const_type h_numRowEnt =
4275 this->k_numRowEntries_;
4277 auto rowPtrsUnpacked_host = this->getRowPtrsUnpackedHost();
4280 if (rowPtrsUnpacked_host.extent(0) == 0) {
4281 errStrm <<
"Unpacked row pointers (rowPtrsUnpacked_dev_) has length 0. This should never "
4282 "happen here. Please report this bug to the Tpetra developers."
4285 return std::make_pair(Tpetra::Details::OrdinalTraits<size_t>::invalid (),
4288 const auto numEnt = rowPtrsUnpacked_host(lclNumRows);
4297 using Kokkos::view_alloc;
4298 using Kokkos::WithoutInitializing;
4308 const std::string label (
"Tpetra::CrsGraph::lclInd");
4310 std::ostringstream os;
4311 os << *prefix <<
"(Re)allocate lclInd_wdv: old="
4312 << lclIndsUnpacked_wdv.extent(0) <<
", new=" << numEnt << endl;
4313 std::cerr << os.str();
4316 local_inds_dualv_type lclInds_dualv =
4317 local_inds_dualv_type(view_alloc(label, WithoutInitializing),
4330 std::ostringstream os;
4331 os << *prefix <<
"Allocate device mirror k_numRowEnt: "
4332 << h_numRowEnt.extent(0) << endl;
4333 std::cerr << os.str();
4336 Kokkos::create_mirror_view_and_copy (
device_type (), h_numRowEnt);
4340 convertColumnIndicesFromGlobalToLocal<LO, GO, DT, offset_type, num_ent_type> (
4341 lclIndsUnpacked_wdv.getDeviceView(Access::OverwriteAll),
4342 gblInds_wdv.getDeviceView(Access::ReadOnly),
4343 this->getRowPtrsUnpackedDevice(),
4346 if (lclNumErrs != 0) {
4347 const int myRank = [
this] () {
4348 auto map = this->getMap ();
4349 if (map.is_null ()) {
4353 auto comm = map->getComm ();
4354 return comm.is_null () ? 0 : comm->getRank ();
4357 const bool pluralNumErrs = (lclNumErrs !=
static_cast<size_t> (1));
4358 errStrm <<
"(Process " << myRank <<
") When converting column "
4359 "indices from global to local, we encountered " << lclNumErrs
4360 <<
" ind" << (pluralNumErrs ?
"ices" :
"ex")
4361 <<
" that do" << (pluralNumErrs ?
"es" :
"")
4362 <<
" not live in the column Map on this process." << endl;
4369 std::ostringstream os;
4370 os << *prefix <<
"Free gblInds_wdv: "
4371 << gblInds_wdv.extent(0) << endl;
4372 std::cerr << os.str();
4377 this->indicesAreLocal_ =
true;
4378 this->indicesAreGlobal_ =
false;
4379 this->checkInternalState ();
4381 return std::make_pair (lclNumErrs, errStrm.str ());
4384 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4391 const char tfecfFuncName[] =
"makeColMap";
4393 ProfilingRegion regionSortAndMerge (
"Tpetra::CrsGraph::makeColMap");
4394 std::unique_ptr<std::string> prefix;
4396 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4397 std::ostringstream os;
4398 os << *prefix <<
"Start" << endl;
4399 std::cerr << os.str();
4407 Teuchos::RCP<const map_type> colMap = this->colMap_;
4408 const bool sortEachProcsGids =
4409 this->sortGhostsAssociatedWithEachProcessor_;
4419 using Teuchos::outArg;
4420 using Teuchos::REDUCE_MIN;
4421 using Teuchos::reduceAll;
4423 std::ostringstream errStrm;
4424 const int lclErrCode =
4426 getDomainMap (), *
this, sortEachProcsGids, &errStrm);
4427 auto comm = this->getComm ();
4428 if (! comm.is_null ()) {
4429 const int lclSuccess = (lclErrCode == 0) ? 1 : 0;
4431 reduceAll<int, int> (*comm, REDUCE_MIN, lclSuccess,
4432 outArg (gblSuccess));
4433 if (gblSuccess != 1) {
4434 std::ostringstream os;
4436 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4437 (
true, std::runtime_error,
": An error happened on at "
4438 "least one process in the CrsGraph's communicator. "
4439 "Here are all processes' error messages:" << std::endl
4446 getDomainMap (), *
this, sortEachProcsGids,
nullptr);
4451 this->colMap_ = colMap;
4453 checkInternalState ();
4455 std::ostringstream os;
4456 os << *prefix <<
"Done" << endl;
4457 std::cerr << os.str();
4462 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4468 using LO = LocalOrdinal;
4469 using host_execution_space =
4470 typename Kokkos::View<LO*, device_type>::HostMirror::
4472 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
4473 const char tfecfFuncName[] =
"sortAndMergeAllIndices";
4475 (
"Tpetra::CrsGraph::sortAndMergeAllIndices");
4477 std::unique_ptr<std::string> prefix;
4479 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4480 std::ostringstream os;
4481 os << *prefix <<
"Start: "
4482 <<
"sorted=" << (sorted ?
"true" :
"false")
4483 <<
", merged=" << (merged ?
"true" :
"false") << endl;
4484 std::cerr << os.str();
4486 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4487 (this->isGloballyIndexed(), std::logic_error,
4488 "This method may only be called after makeIndicesLocal." );
4489 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4490 (! merged && this->isStorageOptimized(), std::logic_error,
4491 "The graph is already storage optimized, so we shouldn't be "
4492 "merging any indices. "
4493 "Please report this bug to the Tpetra developers.");
4495 if (! sorted || ! merged) {
4496 const LO lclNumRows(this->getLocalNumRows());
4497 auto range = range_type(0, lclNumRows);
4500 size_t totalNumDups = 0;
4502 lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
4504 Kokkos::parallel_reduce(range,
4505 [
this, sorted, merged] (
const LO lclRow,
size_t& numDups)
4507 const RowInfo rowInfo = this->getRowInfo(lclRow);
4508 numDups += this->sortAndMergeRowIndices(rowInfo, sorted, merged);
4512 std::ostringstream os;
4513 os << *prefix <<
"totalNumDups=" << totalNumDups << endl;
4514 std::cerr << os.str();
4518 lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
4520 Kokkos::parallel_for(range,
4521 [
this, sorted, merged] (
const LO lclRow)
4523 const RowInfo rowInfo = this->getRowInfo(lclRow);
4524 this->sortAndMergeRowIndices(rowInfo, sorted, merged);
4528 this->indicesAreSorted_ =
true;
4529 this->noRedundancies_ =
true;
4533 std::ostringstream os;
4534 os << *prefix <<
"Done" << endl;
4535 std::cerr << os.str();
4539 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4543 const bool useRemotePIDs)
4545 using ::Tpetra::Details::ProfilingRegion;
4546 using Teuchos::ParameterList;
4549 const char tfecfFuncName[] =
"makeImportExport: ";
4550 ProfilingRegion regionMIE (
"Tpetra::CrsGraph::makeImportExport");
4552 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4553 (! this->hasColMap (), std::logic_error,
4554 "This method may not be called unless the graph has a column Map.");
4555 RCP<ParameterList> params = this->getNonconstParameterList ();
4564 if (importer_.is_null ()) {
4566 if (domainMap_ != colMap_ && (! domainMap_->isSameAs (*colMap_))) {
4567 if (params.is_null () || ! params->isSublist (
"Import")) {
4568 if (useRemotePIDs) {
4569 importer_ = rcp (
new import_type (domainMap_, colMap_, remotePIDs));
4572 importer_ = rcp (
new import_type (domainMap_, colMap_));
4576 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
4577 if (useRemotePIDs) {
4578 RCP<import_type> newImp =
4579 rcp (
new import_type (domainMap_, colMap_, remotePIDs,
4584 importer_ = rcp (
new import_type (domainMap_, colMap_, importSublist));
4592 if (exporter_.is_null ()) {
4594 if (rangeMap_ != rowMap_ && ! rangeMap_->isSameAs (*rowMap_)) {
4595 if (params.is_null () || ! params->isSublist (
"Export")) {
4596 exporter_ = rcp (
new export_type (rowMap_, rangeMap_));
4599 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
4600 exporter_ = rcp (
new export_type (rowMap_, rangeMap_, exportSublist));
4607 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4612 std::ostringstream oss;
4613 oss << dist_object_type::description ();
4614 if (isFillComplete ()) {
4615 oss <<
"{status = fill complete"
4616 <<
", global rows = " << getGlobalNumRows()
4617 <<
", global cols = " << getGlobalNumCols()
4618 <<
", global num entries = " << getGlobalNumEntries()
4622 oss <<
"{status = fill not complete"
4623 <<
", global rows = " << getGlobalNumRows()
4630 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4634 const Teuchos::EVerbosityLevel verbLevel)
const
4636 using Teuchos::ArrayView;
4637 using Teuchos::Comm;
4639 using Teuchos::VERB_DEFAULT;
4640 using Teuchos::VERB_NONE;
4641 using Teuchos::VERB_LOW;
4642 using Teuchos::VERB_MEDIUM;
4643 using Teuchos::VERB_HIGH;
4644 using Teuchos::VERB_EXTREME;
4648 Teuchos::EVerbosityLevel vl = verbLevel;
4649 if (vl == VERB_DEFAULT) vl = VERB_LOW;
4650 RCP<const Comm<int> > comm = this->getComm();
4651 const int myImageID = comm->getRank(),
4652 numImages = comm->getSize();
4654 for (
size_t dec=10; dec<getGlobalNumRows(); dec *= 10) {
4657 width = std::max<size_t> (width,
static_cast<size_t> (11)) + 2;
4658 Teuchos::OSTab tab (out);
4666 if (vl != VERB_NONE) {
4667 if (myImageID == 0) out << this->description() << std::endl;
4669 if (isFillComplete() && myImageID == 0) {
4670 out <<
"Global max number of row entries = " << globalMaxNumRowEntries_ << std::endl;
4673 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4674 if (myImageID == 0) out <<
"\nRow map: " << std::endl;
4675 rowMap_->describe(out,vl);
4676 if (colMap_ != Teuchos::null) {
4677 if (myImageID == 0) out <<
"\nColumn map: " << std::endl;
4678 colMap_->describe(out,vl);
4680 if (domainMap_ != Teuchos::null) {
4681 if (myImageID == 0) out <<
"\nDomain map: " << std::endl;
4682 domainMap_->describe(out,vl);
4684 if (rangeMap_ != Teuchos::null) {
4685 if (myImageID == 0) out <<
"\nRange map: " << std::endl;
4686 rangeMap_->describe(out,vl);
4690 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4691 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4692 if (myImageID == imageCtr) {
4693 out <<
"Node ID = " << imageCtr << std::endl
4694 <<
"Node number of entries = " << this->getLocalNumEntries () << std::endl
4695 <<
"Node max number of entries = " << nodeMaxNumRowEntries_ << std::endl;
4696 if (! indicesAreAllocated ()) {
4697 out <<
"Indices are not allocated." << std::endl;
4706 if (vl == VERB_HIGH || vl == VERB_EXTREME) {
4707 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4708 if (myImageID == imageCtr) {
4709 out << std::setw(width) <<
"Node ID"
4710 << std::setw(width) <<
"Global Row"
4711 << std::setw(width) <<
"Num Entries";
4712 if (vl == VERB_EXTREME) {
4716 const LocalOrdinal lclNumRows =
4717 static_cast<LocalOrdinal
> (this->getLocalNumRows ());
4718 for (LocalOrdinal r=0; r < lclNumRows; ++r) {
4719 const RowInfo rowinfo = this->getRowInfo (r);
4720 GlobalOrdinal gid = rowMap_->getGlobalElement(r);
4721 out << std::setw(width) << myImageID
4722 << std::setw(width) << gid
4723 << std::setw(width) << rowinfo.numEntries;
4724 if (vl == VERB_EXTREME) {
4726 if (isGloballyIndexed()) {
4727 auto rowview = gblInds_wdv.getHostView(Access::ReadOnly);
4728 for (
size_t j=0; j < rowinfo.numEntries; ++j){
4729 GlobalOrdinal colgid = rowview[j + rowinfo.offset1D];
4730 out << colgid <<
" ";
4733 else if (isLocallyIndexed()) {
4734 auto rowview = lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
4735 for (
size_t j=0; j < rowinfo.numEntries; ++j) {
4736 LocalOrdinal collid = rowview[j + rowinfo.offset1D];
4737 out << colMap_->getGlobalElement(collid) <<
" ";
4753 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4764 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4769 const size_t numSameIDs,
4780 const char tfecfFuncName[] =
"copyAndPermute: ";
4781 const bool verbose = verbose_;
4783 std::unique_ptr<std::string> prefix;
4785 prefix = this->createPrefix(
"CrsGraph",
"copyAndPermute");
4786 std::ostringstream os;
4787 os << *prefix << endl;
4788 std::cerr << os.str ();
4791 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4792 (permuteToLIDs.extent (0) != permuteFromLIDs.extent (0),
4793 std::runtime_error,
"permuteToLIDs.extent(0) = "
4794 << permuteToLIDs.extent (0) <<
" != permuteFromLIDs.extent(0) = "
4795 << permuteFromLIDs.extent (0) <<
".");
4803 std::ostringstream os;
4804 os << *prefix <<
"Compute padding" << endl;
4805 std::cerr << os.str ();
4807 auto padding = computeCrsPadding(srcRowGraph, numSameIDs,
4808 permuteToLIDs, permuteFromLIDs, verbose);
4809 applyCrsPadding(*padding, verbose);
4814 const this_CRS_type* srcCrsGraph =
4815 dynamic_cast<const this_CRS_type*
> (&source);
4817 const map_type& srcRowMap = *(srcRowGraph.getRowMap());
4818 const map_type& tgtRowMap = *(getRowMap());
4819 const bool src_filled = srcRowGraph.isFillComplete();
4820 nonconst_global_inds_host_view_type row_copy;
4826 if (src_filled || srcCrsGraph ==
nullptr) {
4828 std::ostringstream os;
4829 os << *prefix <<
"src_filled || srcCrsGraph == nullptr" << endl;
4830 std::cerr << os.str ();
4837 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
4839 size_t row_length = srcRowGraph.getNumEntriesInGlobalRow (gid);
4840 Kokkos::resize(row_copy,row_length);
4841 size_t check_row_length = 0;
4842 srcRowGraph.getGlobalRowCopy (gid, row_copy, check_row_length);
4843 this->insertGlobalIndices (gid, row_length, row_copy.data());
4847 std::ostringstream os;
4848 os << *prefix <<
"! src_filled && srcCrsGraph != nullptr" << endl;
4849 std::cerr << os.str ();
4851 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
4853 global_inds_host_view_type row;
4854 srcCrsGraph->getGlobalRowView (gid, row);
4855 this->insertGlobalIndices (gid, row.extent(0), row.data());
4862 auto permuteToLIDs_h = permuteToLIDs.view_host ();
4863 auto permuteFromLIDs_h = permuteFromLIDs.view_host ();
4865 if (src_filled || srcCrsGraph ==
nullptr) {
4866 for (LO i = 0; i < static_cast<LO> (permuteToLIDs_h.extent (0)); ++i) {
4869 size_t row_length = srcRowGraph.getNumEntriesInGlobalRow (srcgid);
4870 Kokkos::resize(row_copy,row_length);
4871 size_t check_row_length = 0;
4872 srcRowGraph.getGlobalRowCopy (srcgid, row_copy, check_row_length);
4873 this->insertGlobalIndices (mygid, row_length, row_copy.data());
4876 for (LO i = 0; i < static_cast<LO> (permuteToLIDs_h.extent (0)); ++i) {
4879 global_inds_host_view_type row;
4880 srcCrsGraph->getGlobalRowView (srcgid, row);
4881 this->insertGlobalIndices (mygid, row.extent(0), row.data());
4886 std::ostringstream os;
4887 os << *prefix <<
"Done" << endl;
4888 std::cerr << os.str ();
4892 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4901 using LO = local_ordinal_type;
4902 using row_ptrs_type =
4903 typename local_graph_device_type::row_map_type::non_const_type;
4904 using range_policy =
4905 Kokkos::RangePolicy<execution_space, Kokkos::IndexType<LO>>;
4906 const char tfecfFuncName[] =
"applyCrsPadding";
4907 ProfilingRegion regionCAP(
"Tpetra::CrsGraph::applyCrsPadding");
4909 std::unique_ptr<std::string> prefix;
4911 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4912 std::ostringstream os;
4913 os << *prefix <<
"padding: ";
4916 std::cerr << os.str();
4918 const int myRank = ! verbose ? -1 : [&] () {
4919 auto map = this->getMap();
4920 if (map.is_null()) {
4923 auto comm = map->getComm();
4924 if (comm.is_null()) {
4927 return comm->getRank();
4936 if (! indicesAreAllocated()) {
4938 std::ostringstream os;
4939 os << *prefix <<
"Call allocateIndices" << endl;
4940 std::cerr << os.str();
4942 allocateIndices(GlobalIndices, verbose);
4944 TEUCHOS_ASSERT( indicesAreAllocated() );
4949 auto rowPtrsUnpacked_dev = this->getRowPtrsUnpackedDevice();
4951 std::ostringstream os;
4952 os << *prefix <<
"Allocate row_ptrs_beg: "
4953 << rowPtrsUnpacked_dev.extent(0) << endl;
4954 std::cerr << os.str();
4956 using Kokkos::view_alloc;
4957 using Kokkos::WithoutInitializing;
4958 row_ptrs_type row_ptrs_beg(
4959 view_alloc(
"row_ptrs_beg", WithoutInitializing),
4960 rowPtrsUnpacked_dev.extent(0));
4964 const size_t N = row_ptrs_beg.extent(0) == 0 ? size_t(0) :
4965 size_t(row_ptrs_beg.extent(0) - 1);
4967 std::ostringstream os;
4968 os << *prefix <<
"Allocate row_ptrs_end: " << N << endl;
4969 std::cerr << os.str();
4971 row_ptrs_type row_ptrs_end(
4972 view_alloc(
"row_ptrs_end", WithoutInitializing), N);
4973 row_ptrs_type num_row_entries;
4975 const bool refill_num_row_entries = k_numRowEntries_.extent(0) != 0;
4977 execution_space().fence();
4979 if (refill_num_row_entries) {
4983 row_ptrs_type(view_alloc(
"num_row_entries", WithoutInitializing), N);
4985 Kokkos::parallel_for
4986 (
"Fill end row pointers", range_policy(0, N),
4987 KOKKOS_LAMBDA (
const size_t i) {
4988 row_ptrs_end(i) = row_ptrs_beg(i) + num_row_entries(i);
4995 Kokkos::parallel_for
4996 (
"Fill end row pointers", range_policy(0, N),
4997 KOKKOS_LAMBDA (
const size_t i) {
4998 row_ptrs_end(i) = row_ptrs_beg(i+1);
5002 if (isGloballyIndexed()) {
5004 padding, myRank, verbose);
5007 padCrsArrays(row_ptrs_beg, row_ptrs_end, lclIndsUnpacked_wdv,
5008 padding, myRank, verbose);
5011 if (refill_num_row_entries) {
5012 Kokkos::parallel_for
5013 (
"Fill num entries", range_policy(0, N),
5014 KOKKOS_LAMBDA (
const size_t i) {
5015 num_row_entries(i) = row_ptrs_end(i) - row_ptrs_beg(i);
5020 std::ostringstream os;
5021 os << *prefix <<
"Reassign k_rowPtrs_; old size: "
5022 << rowPtrsUnpacked_dev.extent(0) <<
", new size: "
5023 << row_ptrs_beg.extent(0) << endl;
5024 std::cerr << os.str();
5025 TEUCHOS_ASSERT( rowPtrsUnpacked_dev.extent(0) == row_ptrs_beg.extent(0) );
5028 setRowPtrsUnpacked(row_ptrs_beg);
5031 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5033 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5035 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5037 const RowGraph<LocalOrdinal,GlobalOrdinal,Node>& source,
5038 const size_t numSameIDs,
5039 const Kokkos::DualView<
const local_ordinal_type*,
5040 buffer_device_type>& permuteToLIDs,
5041 const Kokkos::DualView<
const local_ordinal_type*,
5042 buffer_device_type>& permuteFromLIDs,
5043 const bool verbose)
const
5048 std::unique_ptr<std::string> prefix;
5051 "computeCrsPadding(same & permute)");
5052 std::ostringstream os;
5053 os << *prefix <<
"{numSameIDs: " << numSameIDs
5054 <<
", numPermutes: " << permuteFromLIDs.extent(0) <<
"}"
5056 std::cerr << os.str();
5059 const int myRank = [&] () {
5060 auto comm = rowMap_.is_null() ? Teuchos::null :
5062 return comm.is_null() ? -1 : comm->getRank();
5064 std::unique_ptr<padding_type> padding(
5065 new padding_type(myRank, numSameIDs,
5066 permuteFromLIDs.extent(0)));
5068 computeCrsPaddingForSameIDs(*padding, source,
5069 static_cast<LO>(numSameIDs));
5070 computeCrsPaddingForPermutedIDs(*padding, source, permuteToLIDs,
5075 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5077 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5078 computeCrsPaddingForSameIDs(
5079 padding_type& padding,
5080 const RowGraph<local_ordinal_type, global_ordinal_type,
5082 const local_ordinal_type numSameIDs)
const
5085 using GO = global_ordinal_type;
5086 using Details::Impl::getRowGraphGlobalRow;
5088 const char tfecfFuncName[] =
"computeCrsPaddingForSameIds";
5090 std::unique_ptr<std::string> prefix;
5091 const bool verbose = verbose_;
5093 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5094 std::ostringstream os;
5095 os << *prefix <<
"numSameIDs: " << numSameIDs << endl;
5096 std::cerr << os.str();
5099 if (numSameIDs == 0) {
5103 const map_type& srcRowMap = *(source.getRowMap());
5104 const map_type& tgtRowMap = *rowMap_;
5105 using this_CRS_type = CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
5106 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
5107 const bool src_is_unique =
5108 srcCrs ==
nullptr ?
false : srcCrs->isMerged();
5109 const bool tgt_is_unique = this->isMerged();
5111 std::vector<GO> srcGblColIndsScratch;
5112 std::vector<GO> tgtGblColIndsScratch;
5114 execute_sync_host_uvm_access();
5115 for (LO lclRowInd = 0; lclRowInd < numSameIDs; ++lclRowInd) {
5116 const GO srcGblRowInd = srcRowMap.getGlobalElement(lclRowInd);
5117 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(lclRowInd);
5118 auto srcGblColInds = getRowGraphGlobalRow(
5119 srcGblColIndsScratch, source, srcGblRowInd);
5120 auto tgtGblColInds = getRowGraphGlobalRow(
5121 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5122 padding.update_same(lclRowInd, tgtGblColInds.getRawPtr(),
5123 tgtGblColInds.size(), tgt_is_unique,
5124 srcGblColInds.getRawPtr(),
5125 srcGblColInds.size(), src_is_unique);
5128 std::ostringstream os;
5129 os << *prefix <<
"Done" << endl;
5130 std::cerr << os.str();
5134 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5136 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5137 computeCrsPaddingForPermutedIDs(
5138 padding_type& padding,
5139 const RowGraph<local_ordinal_type, global_ordinal_type,
5141 const Kokkos::DualView<
const local_ordinal_type*,
5142 buffer_device_type>& permuteToLIDs,
5143 const Kokkos::DualView<
const local_ordinal_type*,
5144 buffer_device_type>& permuteFromLIDs)
const
5147 using GO = global_ordinal_type;
5148 using Details::Impl::getRowGraphGlobalRow;
5150 const char tfecfFuncName[] =
"computeCrsPaddingForPermutedIds";
5152 std::unique_ptr<std::string> prefix;
5153 const bool verbose = verbose_;
5155 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5156 std::ostringstream os;
5157 os << *prefix <<
"permuteToLIDs.extent(0): "
5158 << permuteToLIDs.extent(0)
5159 <<
", permuteFromLIDs.extent(0): "
5160 << permuteFromLIDs.extent(0) << endl;
5161 std::cerr << os.str();
5164 if (permuteToLIDs.extent(0) == 0) {
5168 const map_type& srcRowMap = *(source.getRowMap());
5169 const map_type& tgtRowMap = *rowMap_;
5170 using this_CRS_type = CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
5171 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
5172 const bool src_is_unique =
5173 srcCrs ==
nullptr ?
false : srcCrs->isMerged();
5174 const bool tgt_is_unique = this->isMerged();
5176 TEUCHOS_ASSERT( ! permuteToLIDs.need_sync_host() );
5177 auto permuteToLIDs_h = permuteToLIDs.view_host();
5178 TEUCHOS_ASSERT( ! permuteFromLIDs.need_sync_host() );
5179 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
5181 std::vector<GO> srcGblColIndsScratch;
5182 std::vector<GO> tgtGblColIndsScratch;
5183 const LO numPermutes =
static_cast<LO
>(permuteToLIDs_h.extent(0));
5185 execute_sync_host_uvm_access();
5186 for (LO whichPermute = 0; whichPermute < numPermutes; ++whichPermute) {
5187 const LO srcLclRowInd = permuteFromLIDs_h[whichPermute];
5188 const GO srcGblRowInd = srcRowMap.getGlobalElement(srcLclRowInd);
5189 auto srcGblColInds = getRowGraphGlobalRow(
5190 srcGblColIndsScratch, source, srcGblRowInd);
5191 const LO tgtLclRowInd = permuteToLIDs_h[whichPermute];
5192 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(tgtLclRowInd);
5193 auto tgtGblColInds = getRowGraphGlobalRow(
5194 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5195 padding.update_permute(whichPermute, tgtLclRowInd,
5196 tgtGblColInds.getRawPtr(),
5197 tgtGblColInds.size(), tgt_is_unique,
5198 srcGblColInds.getRawPtr(),
5199 srcGblColInds.size(), src_is_unique);
5203 std::ostringstream os;
5204 os << *prefix <<
"Done" << endl;
5205 std::cerr << os.str();
5209 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5211 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5213 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5214 computeCrsPaddingForImports(
5215 const Kokkos::DualView<
const local_ordinal_type*,
5216 buffer_device_type>& importLIDs,
5217 Kokkos::DualView<packet_type*, buffer_device_type> imports,
5218 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
5219 const bool verbose)
const
5221 using Details::Impl::getRowGraphGlobalRow;
5224 using GO = global_ordinal_type;
5225 const char tfecfFuncName[] =
"computeCrsPaddingForImports";
5227 std::unique_ptr<std::string> prefix;
5229 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5230 std::ostringstream os;
5231 os << *prefix <<
"importLIDs.extent(0): "
5232 << importLIDs.extent(0)
5233 <<
", imports.extent(0): "
5234 << imports.extent(0)
5235 <<
", numPacketsPerLID.extent(0): "
5236 << numPacketsPerLID.extent(0) << endl;
5237 std::cerr << os.str();
5240 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5241 const int myRank = [&] () {
5242 auto comm = rowMap_.is_null() ? Teuchos::null :
5244 return comm.is_null() ? -1 : comm->getRank();
5246 std::unique_ptr<padding_type> padding(
5247 new padding_type(myRank, numImports));
5249 if (imports.need_sync_host()) {
5250 imports.sync_host();
5252 auto imports_h = imports.view_host();
5253 if (numPacketsPerLID.need_sync_host ()) {
5254 numPacketsPerLID.sync_host();
5256 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5258 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
5259 auto importLIDs_h = importLIDs.view_host();
5261 const map_type& tgtRowMap = *rowMap_;
5265 constexpr
bool src_is_unique =
false;
5266 const bool tgt_is_unique = isMerged();
5268 std::vector<GO> tgtGblColIndsScratch;
5270 execute_sync_host_uvm_access();
5271 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5276 const LO origSrcNumEnt =
5277 static_cast<LO
>(numPacketsPerLID_h[whichImport]);
5278 GO*
const srcGblColInds = imports_h.data() + offset;
5280 const LO tgtLclRowInd = importLIDs_h[whichImport];
5281 const GO tgtGblRowInd =
5282 tgtRowMap.getGlobalElement(tgtLclRowInd);
5283 auto tgtGblColInds = getRowGraphGlobalRow(
5284 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5285 const size_t origTgtNumEnt(tgtGblColInds.size());
5287 padding->update_import(whichImport, tgtLclRowInd,
5288 tgtGblColInds.getRawPtr(),
5289 origTgtNumEnt, tgt_is_unique,
5291 origSrcNumEnt, src_is_unique);
5292 offset += origSrcNumEnt;
5296 std::ostringstream os;
5297 os << *prefix <<
"Done" << endl;
5298 std::cerr << os.str();
5303 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5305 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5307 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5308 computePaddingForCrsMatrixUnpack(
5309 const Kokkos::DualView<
const local_ordinal_type*,
5310 buffer_device_type>& importLIDs,
5311 Kokkos::DualView<char*, buffer_device_type> imports,
5312 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
5313 const bool verbose)
const
5315 using Details::Impl::getRowGraphGlobalRow;
5316 using Details::PackTraits;
5319 using GO = global_ordinal_type;
5320 const char tfecfFuncName[] =
"computePaddingForCrsMatrixUnpack";
5322 std::unique_ptr<std::string> prefix;
5324 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5325 std::ostringstream os;
5326 os << *prefix <<
"importLIDs.extent(0): "
5327 << importLIDs.extent(0)
5328 <<
", imports.extent(0): "
5329 << imports.extent(0)
5330 <<
", numPacketsPerLID.extent(0): "
5331 << numPacketsPerLID.extent(0) << endl;
5332 std::cerr << os.str();
5334 const bool extraVerbose =
5337 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5338 TEUCHOS_ASSERT( LO(numPacketsPerLID.extent(0)) >= numImports );
5339 const int myRank = [&] () {
5340 auto comm = rowMap_.is_null() ? Teuchos::null :
5342 return comm.is_null() ? -1 : comm->getRank();
5344 std::unique_ptr<padding_type> padding(
5345 new padding_type(myRank, numImports));
5347 if (imports.need_sync_host()) {
5348 imports.sync_host();
5350 auto imports_h = imports.view_host();
5351 if (numPacketsPerLID.need_sync_host ()) {
5352 numPacketsPerLID.sync_host();
5354 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5356 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
5357 auto importLIDs_h = importLIDs.view_host();
5359 const map_type& tgtRowMap = *rowMap_;
5363 constexpr
bool src_is_unique =
false;
5364 const bool tgt_is_unique = isMerged();
5366 std::vector<GO> srcGblColIndsScratch;
5367 std::vector<GO> tgtGblColIndsScratch;
5369 execute_sync_host_uvm_access();
5370 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5375 const size_t numBytes = numPacketsPerLID_h[whichImport];
5377 std::ostringstream os;
5378 os << *prefix <<
"whichImport=" << whichImport
5379 <<
", numImports=" << numImports
5380 <<
", numBytes=" << numBytes << endl;
5381 std::cerr << os.str();
5383 if (numBytes == 0) {
5386 LO origSrcNumEnt = 0;
5387 const size_t numEntBeg = offset;
5388 const size_t numEntLen =
5390 TEUCHOS_ASSERT( numBytes >= numEntLen );
5391 TEUCHOS_ASSERT( imports_h.extent(0) >= numEntBeg + numEntLen );
5393 imports_h.data() + numEntBeg);
5395 std::ostringstream os;
5396 os << *prefix <<
"whichImport=" << whichImport
5397 <<
", numImports=" << numImports
5398 <<
", origSrcNumEnt=" << origSrcNumEnt << endl;
5399 std::cerr << os.str();
5401 TEUCHOS_ASSERT( origSrcNumEnt >= LO(0) );
5402 TEUCHOS_ASSERT( numBytes >=
size_t(numEntLen + origSrcNumEnt *
sizeof(GO)) );
5403 const size_t gidsBeg = numEntBeg + numEntLen;
5404 if (srcGblColIndsScratch.size() < size_t(origSrcNumEnt)) {
5405 srcGblColIndsScratch.resize(origSrcNumEnt);
5407 GO*
const srcGblColInds = srcGblColIndsScratch.data();
5408 PackTraits<GO>::unpackArray(srcGblColInds,
5409 imports_h.data() + gidsBeg,
5411 const LO tgtLclRowInd = importLIDs_h[whichImport];
5412 const GO tgtGblRowInd =
5413 tgtRowMap.getGlobalElement(tgtLclRowInd);
5414 auto tgtGblColInds = getRowGraphGlobalRow(
5415 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5416 const size_t origNumTgtEnt(tgtGblColInds.size());
5419 std::ostringstream os;
5420 os << *prefix <<
"whichImport=" << whichImport
5421 <<
", numImports=" << numImports
5422 <<
": Call padding->update_import" << endl;
5423 std::cerr << os.str();
5425 padding->update_import(whichImport, tgtLclRowInd,
5426 tgtGblColInds.getRawPtr(),
5427 origNumTgtEnt, tgt_is_unique,
5429 origSrcNumEnt, src_is_unique);
5434 std::ostringstream os;
5435 os << *prefix <<
"Done" << endl;
5436 std::cerr << os.str();
5441 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5443 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5445 (
const SrcDistObject& source,
5446 const Kokkos::DualView<
const local_ordinal_type*,
5447 buffer_device_type>& exportLIDs,
5448 Kokkos::DualView<packet_type*,
5449 buffer_device_type>& exports,
5450 Kokkos::DualView<
size_t*,
5451 buffer_device_type> numPacketsPerLID,
5452 size_t& constantNumPackets)
5455 using GO = global_ordinal_type;
5457 using crs_graph_type =
5458 CrsGraph<local_ordinal_type, global_ordinal_type, node_type>;
5459 const char tfecfFuncName[] =
"packAndPrepare: ";
5460 ProfilingRegion region_papn (
"Tpetra::CrsGraph::packAndPrepare");
5462 const bool verbose = verbose_;
5463 std::unique_ptr<std::string> prefix;
5465 prefix = this->
createPrefix(
"CrsGraph",
"packAndPrepare");
5466 std::ostringstream os;
5467 os << *prefix <<
"Start" << endl;
5468 std::cerr << os.str();
5471 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5472 (exportLIDs.extent (0) != numPacketsPerLID.extent (0),
5474 "exportLIDs.extent(0) = " << exportLIDs.extent (0)
5475 <<
" != numPacketsPerLID.extent(0) = " << numPacketsPerLID.extent (0)
5477 const row_graph_type* srcRowGraphPtr =
5478 dynamic_cast<const row_graph_type*
> (&source);
5479 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5480 (srcRowGraphPtr ==
nullptr, std::invalid_argument,
"Source of an Export "
5481 "or Import operation to a CrsGraph must be a RowGraph with the same "
5482 "template parameters.");
5486 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5487 (this->isFillComplete (), std::runtime_error,
5488 "The target graph of an Import or Export must not be fill complete.");
5490 const crs_graph_type* srcCrsGraphPtr =
5491 dynamic_cast<const crs_graph_type*
> (&source);
5493 if (srcCrsGraphPtr ==
nullptr) {
5494 using Teuchos::ArrayView;
5498 std::ostringstream os;
5499 os << *prefix <<
"Source is a RowGraph but not a CrsGraph"
5501 std::cerr << os.str();
5508 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
5509 auto exportLIDs_h = exportLIDs.view_host ();
5510 ArrayView<const LO> exportLIDs_av (exportLIDs_h.data (),
5511 exportLIDs_h.extent (0));
5512 Teuchos::Array<GO> exports_a;
5514 numPacketsPerLID.clear_sync_state ();
5515 numPacketsPerLID.modify_host ();
5516 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
5517 ArrayView<size_t> numPacketsPerLID_av (numPacketsPerLID_h.data (),
5518 numPacketsPerLID_h.extent (0));
5519 srcRowGraphPtr->pack (exportLIDs_av, exports_a, numPacketsPerLID_av,
5520 constantNumPackets);
5521 const size_t newSize =
static_cast<size_t> (exports_a.size ());
5522 if (static_cast<size_t> (exports.extent (0)) != newSize) {
5523 using exports_dv_type = Kokkos::DualView<packet_type*, buffer_device_type>;
5524 exports = exports_dv_type (
"exports", newSize);
5526 Kokkos::View<
const packet_type*, Kokkos::HostSpace,
5527 Kokkos::MemoryUnmanaged> exports_a_h (exports_a.getRawPtr (), newSize);
5528 exports.clear_sync_state ();
5529 exports.modify_host ();
5534 else if (! getColMap ().is_null () &&
5535 (this->getRowPtrsPackedDevice().extent (0) != 0 ||
5536 getRowMap ()->getLocalNumElements () == 0)) {
5538 std::ostringstream os;
5539 os << *prefix <<
"packCrsGraphNew path" << endl;
5540 std::cerr << os.str();
5542 using export_pids_type =
5543 Kokkos::DualView<const int*, buffer_device_type>;
5544 export_pids_type exportPIDs;
5546 using NT = node_type;
5548 packCrsGraphNew<LO,GO,NT> (*srcCrsGraphPtr, exportLIDs, exportPIDs,
5549 exports, numPacketsPerLID,
5550 constantNumPackets,
false);
5553 srcCrsGraphPtr->packFillActiveNew (exportLIDs, exports, numPacketsPerLID,
5554 constantNumPackets);
5558 std::ostringstream os;
5559 os << *prefix <<
"Done" << endl;
5560 std::cerr << os.str();
5564 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5567 pack (
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5568 Teuchos::Array<GlobalOrdinal>& exports,
5569 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5570 size_t& constantNumPackets)
const
5572 auto col_map = this->getColMap();
5574 if( !col_map.is_null() && (this->getRowPtrsPackedDevice().extent(0) != 0 || getRowMap()->getLocalNumElements() ==0)) {
5576 packCrsGraph<LocalOrdinal,GlobalOrdinal,Node>(*
this, exports, numPacketsPerLID,
5577 exportLIDs, constantNumPackets);
5580 this->packFillActive(exportLIDs, exports, numPacketsPerLID,
5581 constantNumPackets);
5585 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5588 packFillActive (
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5589 Teuchos::Array<GlobalOrdinal>& exports,
5590 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5591 size_t& constantNumPackets)
const
5594 using LO = LocalOrdinal;
5595 using GO = GlobalOrdinal;
5596 using host_execution_space =
5597 typename Kokkos::View<size_t*, device_type>::
5598 HostMirror::execution_space;
5599 const char tfecfFuncName[] =
"packFillActive: ";
5600 const bool verbose = verbose_;
5602 const auto numExportLIDs = exportLIDs.size ();
5603 std::unique_ptr<std::string> prefix;
5605 prefix = this->createPrefix(
"CrsGraph",
"allocateIndices");
5606 std::ostringstream os;
5607 os << *prefix <<
"numExportLIDs=" << numExportLIDs << endl;
5608 std::cerr << os.str();
5610 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5611 (numExportLIDs != numPacketsPerLID.size (), std::runtime_error,
5612 "exportLIDs.size() = " << numExportLIDs <<
" != numPacketsPerLID.size()"
5613 " = " << numPacketsPerLID.size () <<
".");
5615 const map_type& rowMap = * (this->getRowMap ());
5616 const map_type*
const colMapPtr = this->colMap_.getRawPtr ();
5617 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5618 (this->isLocallyIndexed () && colMapPtr ==
nullptr, std::logic_error,
5619 "This graph claims to be locally indexed, but its column Map is nullptr. "
5620 "This should never happen. Please report this bug to the Tpetra "
5624 constantNumPackets = 0;
5628 size_t*
const numPacketsPerLID_raw = numPacketsPerLID.getRawPtr ();
5629 const LO*
const exportLIDs_raw = exportLIDs.getRawPtr ();
5636 Kokkos::RangePolicy<host_execution_space, LO> inputRange (0, numExportLIDs);
5637 size_t totalNumPackets = 0;
5638 size_t errCount = 0;
5641 typedef Kokkos::Device<host_execution_space, Kokkos::HostSpace>
5643 Kokkos::View<size_t, host_device_type> errCountView (&errCount);
5644 constexpr
size_t ONE = 1;
5646 execute_sync_host_uvm_access();
5647 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::pack: totalNumPackets",
5649 [=] (
const LO& i,
size_t& curTotalNumPackets) {
5650 const GO gblRow = rowMap.getGlobalElement (exportLIDs_raw[i]);
5651 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
5652 Kokkos::atomic_add (&errCountView(), ONE);
5653 numPacketsPerLID_raw[i] = 0;
5656 const size_t numEnt = this->getNumEntriesInGlobalRow (gblRow);
5657 numPacketsPerLID_raw[i] = numEnt;
5658 curTotalNumPackets += numEnt;
5664 std::ostringstream os;
5665 os << *prefix <<
"totalNumPackets=" << totalNumPackets << endl;
5666 std::cerr << os.str();
5668 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5669 (errCount != 0, std::logic_error,
"totalNumPackets count encountered "
5670 "one or more errors! errCount = " << errCount
5671 <<
", totalNumPackets = " << totalNumPackets <<
".");
5675 exports.resize (totalNumPackets);
5677 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5678 (! this->supportsRowViews (), std::logic_error,
5679 "this->supportsRowViews() returns false; this should never happen. "
5680 "Please report this bug to the Tpetra developers.");
5686 std::ostringstream os;
5687 os << *prefix <<
"Pack into exports" << endl;
5688 std::cerr << os.str();
5693 GO*
const exports_raw = exports.getRawPtr ();
5695 Kokkos::parallel_scan (
"Tpetra::CrsGraph::pack: pack from views",
5696 inputRange, [=, &prefix]
5697 (
const LO i,
size_t& exportsOffset,
const bool final) {
5698 const size_t curOffset = exportsOffset;
5699 const GO gblRow = rowMap.getGlobalElement (exportLIDs_raw[i]);
5700 const RowInfo rowInfo =
5701 this->getRowInfoFromGlobalRowIndex (gblRow);
5703 using TDO = Tpetra::Details::OrdinalTraits<size_t>;
5704 if (rowInfo.localRow == TDO::invalid ()) {
5706 std::ostringstream os;
5707 os << *prefix <<
": INVALID rowInfo: i=" << i
5708 <<
", lclRow=" << exportLIDs_raw[i] << endl;
5709 std::cerr << os.str();
5711 Kokkos::atomic_add (&errCountView(), ONE);
5713 else if (curOffset + rowInfo.numEntries > totalNumPackets) {
5715 std::ostringstream os;
5716 os << *prefix <<
": UH OH! For i=" << i <<
", lclRow="
5717 << exportLIDs_raw[i] <<
", gblRow=" << gblRow <<
", curOffset "
5718 "(= " << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5719 <<
") > totalNumPackets (= " << totalNumPackets <<
")."
5721 std::cerr << os.str();
5723 Kokkos::atomic_add (&errCountView(), ONE);
5726 const LO numEnt =
static_cast<LO
> (rowInfo.numEntries);
5727 if (this->isLocallyIndexed ()) {
5728 auto lclColInds = getLocalIndsViewHost (rowInfo);
5730 for (LO k = 0; k < numEnt; ++k) {
5731 const LO lclColInd = lclColInds(k);
5732 const GO gblColInd = colMapPtr->getGlobalElement (lclColInd);
5736 exports_raw[curOffset + k] = gblColInd;
5739 exportsOffset = curOffset + numEnt;
5741 else if (this->isGloballyIndexed ()) {
5742 auto gblColInds = getGlobalIndsViewHost (rowInfo);
5744 for (LO k = 0; k < numEnt; ++k) {
5745 const GO gblColInd = gblColInds(k);
5749 exports_raw[curOffset + k] = gblColInd;
5752 exportsOffset = curOffset + numEnt;
5760 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5761 (errCount != 0, std::logic_error,
"Packing encountered "
5762 "one or more errors! errCount = " << errCount
5763 <<
", totalNumPackets = " << totalNumPackets <<
".");
5766 std::ostringstream os;
5767 os << *prefix <<
"Done" << endl;
5768 std::cerr << os.str();
5772 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5774 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5775 packFillActiveNew (
const Kokkos::DualView<
const local_ordinal_type*,
5776 buffer_device_type>& exportLIDs,
5777 Kokkos::DualView<packet_type*,
5778 buffer_device_type>& exports,
5779 Kokkos::DualView<
size_t*,
5780 buffer_device_type> numPacketsPerLID,
5781 size_t& constantNumPackets)
const
5785 using GO = global_ordinal_type;
5786 using host_execution_space =
typename Kokkos::View<
size_t*,
5787 device_type>::HostMirror::execution_space;
5788 using host_device_type =
5789 Kokkos::Device<host_execution_space, Kokkos::HostSpace>;
5790 using exports_dv_type =
5791 Kokkos::DualView<packet_type*, buffer_device_type>;
5792 const char tfecfFuncName[] =
"packFillActiveNew: ";
5793 const bool verbose = verbose_;
5795 const auto numExportLIDs = exportLIDs.extent (0);
5796 std::unique_ptr<std::string> prefix;
5798 prefix = this->
createPrefix(
"CrsGraph",
"packFillActiveNew");
5799 std::ostringstream os;
5800 os << *prefix <<
"numExportLIDs: " << numExportLIDs
5801 <<
", numPacketsPerLID.extent(0): "
5802 << numPacketsPerLID.extent(0) << endl;
5803 std::cerr << os.str();
5805 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5806 (numExportLIDs != numPacketsPerLID.extent (0), std::runtime_error,
5807 "exportLIDs.extent(0) = " << numExportLIDs
5808 <<
" != numPacketsPerLID.extent(0) = "
5809 << numPacketsPerLID.extent (0) <<
".");
5810 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
5811 auto exportLIDs_h = exportLIDs.view_host ();
5813 const map_type& rowMap = * (this->getRowMap ());
5814 const map_type*
const colMapPtr = this->colMap_.getRawPtr ();
5815 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5816 (this->isLocallyIndexed () && colMapPtr ==
nullptr, std::logic_error,
5817 "This graph claims to be locally indexed, but its column Map is nullptr. "
5818 "This should never happen. Please report this bug to the Tpetra "
5822 constantNumPackets = 0;
5824 numPacketsPerLID.clear_sync_state ();
5825 numPacketsPerLID.modify_host ();
5826 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
5833 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
5834 range_type inputRange (0, numExportLIDs);
5835 size_t totalNumPackets = 0;
5836 size_t errCount = 0;
5839 Kokkos::View<size_t, host_device_type> errCountView (&errCount);
5840 constexpr
size_t ONE = 1;
5843 std::ostringstream os;
5844 os << *prefix <<
"Compute totalNumPackets" << endl;
5845 std::cerr << os.str ();
5848 execute_sync_host_uvm_access();
5849 Kokkos::parallel_reduce
5850 (
"Tpetra::CrsGraph::pack: totalNumPackets",
5852 [=, &prefix] (
const LO i,
size_t& curTotalNumPackets) {
5853 const LO lclRow = exportLIDs_h[i];
5854 const GO gblRow = rowMap.getGlobalElement (lclRow);
5855 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
5857 std::ostringstream os;
5858 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5859 <<
" not in row Map on this process" << endl;
5860 std::cerr << os.str();
5862 Kokkos::atomic_add (&errCountView(), ONE);
5863 numPacketsPerLID_h(i) = 0;
5866 const size_t numEnt = this->getNumEntriesInGlobalRow (gblRow);
5867 numPacketsPerLID_h(i) = numEnt;
5868 curTotalNumPackets += numEnt;
5874 std::ostringstream os;
5875 os << *prefix <<
"totalNumPackets: " << totalNumPackets
5876 <<
", errCount: " << errCount << endl;
5877 std::cerr << os.str ();
5879 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5880 (errCount != 0, std::logic_error,
"totalNumPackets count encountered "
5881 "one or more errors! totalNumPackets: " << totalNumPackets
5882 <<
", errCount: " << errCount <<
".");
5885 if (
size_t(exports.extent (0)) < totalNumPackets) {
5887 exports = exports_dv_type (
"exports", totalNumPackets);
5890 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5891 (! this->supportsRowViews (), std::logic_error,
5892 "this->supportsRowViews() returns false; this should never happen. "
5893 "Please report this bug to the Tpetra developers.");
5899 std::ostringstream os;
5900 os << *prefix <<
"Pack into exports buffer" << endl;
5901 std::cerr << os.str();
5904 exports.clear_sync_state ();
5905 exports.modify_host ();
5906 auto exports_h = exports.view_host ();
5912 if(isLocallyIndexed())
5913 lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
5914 else if(isGloballyIndexed())
5915 gblInds_wdv.getHostView(Access::ReadOnly);
5918 Kokkos::parallel_scan
5919 (
"Tpetra::CrsGraph::packFillActiveNew: Pack exports",
5920 inputRange, [=, &prefix]
5921 (
const LO i,
size_t& exportsOffset,
const bool final) {
5922 const size_t curOffset = exportsOffset;
5923 const LO lclRow = exportLIDs_h(i);
5924 const GO gblRow = rowMap.getGlobalElement (lclRow);
5925 if (gblRow == Details::OrdinalTraits<GO>::invalid ()) {
5927 std::ostringstream os;
5928 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5929 <<
" not in row Map on this process" << endl;
5930 std::cerr << os.str();
5932 Kokkos::atomic_add (&errCountView(), ONE);
5936 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (gblRow);
5937 if (rowInfo.localRow == Details::OrdinalTraits<size_t>::invalid ()) {
5939 std::ostringstream os;
5940 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5941 <<
", gblRow=" << gblRow <<
": invalid rowInfo"
5943 std::cerr << os.str();
5945 Kokkos::atomic_add (&errCountView(), ONE);
5949 if (curOffset + rowInfo.numEntries > totalNumPackets) {
5951 std::ostringstream os;
5952 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5953 <<
", gblRow=" << gblRow <<
", curOffset (= "
5954 << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5955 <<
") > totalNumPackets (= " << totalNumPackets
5957 std::cerr << os.str();
5959 Kokkos::atomic_add (&errCountView(), ONE);
5963 const LO numEnt =
static_cast<LO
> (rowInfo.numEntries);
5964 if (this->isLocallyIndexed ()) {
5965 auto lclColInds = getLocalIndsViewHost(rowInfo);
5967 for (LO k = 0; k < numEnt; ++k) {
5968 const LO lclColInd = lclColInds(k);
5969 const GO gblColInd = colMapPtr->getGlobalElement (lclColInd);
5973 exports_h(curOffset + k) = gblColInd;
5976 exportsOffset = curOffset + numEnt;
5978 else if (this->isGloballyIndexed ()) {
5979 auto gblColInds = getGlobalIndsViewHost(rowInfo);
5981 for (LO k = 0; k < numEnt; ++k) {
5982 const GO gblColInd = gblColInds(k);
5986 exports_h(curOffset + k) = gblColInd;
5989 exportsOffset = curOffset + numEnt;
6003 std::ostringstream os;
6004 os << *prefix <<
"errCount=" << errCount <<
"; Done" << endl;
6005 std::cerr << os.str();
6009 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6015 Kokkos::DualView<packet_type*,
6017 Kokkos::DualView<
size_t*,
6026 const char tfecfFuncName[] =
"unpackAndCombine";
6028 ProfilingRegion regionCGC(
"Tpetra::CrsGraph::unpackAndCombine");
6029 const bool verbose = verbose_;
6031 std::unique_ptr<std::string> prefix;
6033 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
6034 std::ostringstream os;
6035 os << *prefix <<
"Start" << endl;
6036 std::cerr << os.str ();
6039 auto padding = computeCrsPaddingForImports(
6040 importLIDs, imports, numPacketsPerLID, verbose);
6041 applyCrsPadding(*padding, verbose);
6043 std::ostringstream os;
6044 os << *prefix <<
"Done computing & applying padding" << endl;
6045 std::cerr << os.str ();
6066 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6067 (importLIDs.extent (0) != numPacketsPerLID.extent (0),
6068 std::runtime_error,
": importLIDs.extent(0) = "
6069 << importLIDs.extent (0) <<
" != numPacketsPerLID.extent(0) = "
6070 << numPacketsPerLID.extent (0) <<
".");
6071 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6072 (isFillComplete (), std::runtime_error,
6073 ": Import or Export operations are not allowed on a target "
6074 "CrsGraph that is fillComplete.");
6076 const size_t numImportLIDs(importLIDs.extent(0));
6077 if (numPacketsPerLID.need_sync_host()) {
6078 numPacketsPerLID.sync_host();
6080 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
6081 if (imports.need_sync_host()) {
6082 imports.sync_host();
6084 auto imports_h = imports.view_host();
6085 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
6086 auto importLIDs_h = importLIDs.view_host();
6089 Teuchos::Array<LO> lclColInds;
6090 if (isLocallyIndexed()) {
6092 std::ostringstream os;
6093 os << *prefix <<
"Preallocate local indices scratch" << endl;
6094 std::cerr << os.str();
6096 size_t maxNumInserts = 0;
6097 for (
size_t i = 0; i < numImportLIDs; ++i) {
6098 maxNumInserts = std::max (maxNumInserts, numPacketsPerLID_h[i]);
6101 std::ostringstream os;
6102 os << *prefix <<
"Local indices scratch size: "
6103 << maxNumInserts << endl;
6104 std::cerr << os.str();
6106 lclColInds.resize (maxNumInserts);
6110 std::ostringstream os;
6112 if (isGloballyIndexed()) {
6113 os <<
"Graph is globally indexed";
6116 os <<
"Graph is neither locally nor globally indexed";
6119 std::cerr << os.str();
6123 TEUCHOS_ASSERT( ! rowMap_.is_null() );
6127 size_t importsOffset = 0;
6128 for (
size_t i = 0; i < numImportLIDs; ++i) {
6130 std::ostringstream os;
6131 os << *prefix <<
"i=" << i <<
", numImportLIDs="
6132 << numImportLIDs << endl;
6133 std::cerr << os.str();
6137 const LO lclRow = importLIDs_h[i];
6139 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6140 (gblRow == Teuchos::OrdinalTraits<GO>::invalid(),
6141 std::logic_error,
"importLIDs[i=" << i <<
"]="
6142 << lclRow <<
" is not in the row Map on the calling "
6144 const LO numEnt = numPacketsPerLID_h[i];
6145 const GO*
const gblColInds = (numEnt == 0) ?
nullptr :
6146 imports_h.data() + importsOffset;
6147 if (! isLocallyIndexed()) {
6148 insertGlobalIndicesFiltered(lclRow, gblColInds, numEnt);
6153 for (LO j = 0; j < numEnt; j++) {
6154 lclColInds[j] = colMap_->getLocalElement(gblColInds[j]);
6156 insertLocalIndices(lclRow, numEnt, lclColInds.data());
6158 importsOffset += numEnt;
6161 catch (std::exception& e) {
6162 TEUCHOS_TEST_FOR_EXCEPTION
6163 (
true, std::runtime_error,
6164 "Tpetra::CrsGraph::unpackAndCombine: Insert loop threw an "
6165 "exception: " << endl << e.what());
6169 std::ostringstream os;
6170 os << *prefix <<
"Done" << endl;
6171 std::cerr << os.str();
6175 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6180 using Teuchos::Comm;
6181 using Teuchos::null;
6182 using Teuchos::ParameterList;
6188 RCP<const map_type> rowMap, domainMap, rangeMap, colMap;
6189 RCP<import_type> importer;
6190 RCP<export_type> exporter;
6193 RCP<const Comm<int> > newComm =
6194 (newMap.is_null ()) ? null : newMap->getComm ();
6196 if (! domainMap_.is_null ()) {
6197 if (domainMap_.getRawPtr () == rowMap_.getRawPtr ()) {
6204 domainMap = domainMap_->replaceCommWithSubset (newComm);
6207 if (! rangeMap_.is_null ()) {
6208 if (rangeMap_.getRawPtr () == rowMap_.getRawPtr ()) {
6215 rangeMap = rangeMap_->replaceCommWithSubset (newComm);
6218 if (! colMap_.is_null ()) {
6219 colMap = colMap_->replaceCommWithSubset (newComm);
6223 if (! newComm.is_null ()) {
6224 RCP<ParameterList> params = this->getNonconstParameterList ();
6232 if (! rangeMap_.is_null () &&
6233 rangeMap != rowMap &&
6234 ! rangeMap->isSameAs (*rowMap)) {
6235 if (params.is_null () || ! params->isSublist (
"Export")) {
6236 exporter = rcp (
new export_type (rowMap, rangeMap));
6239 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
6240 exporter = rcp (
new export_type (rowMap, rangeMap, exportSublist));
6244 if (! domainMap_.is_null () &&
6245 domainMap != colMap &&
6246 ! domainMap->isSameAs (*colMap)) {
6247 if (params.is_null () || ! params->isSublist (
"Import")) {
6248 importer = rcp (
new import_type (domainMap, colMap));
6250 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
6251 importer = rcp (
new import_type (domainMap, colMap, importSublist));
6259 exporter_ = exporter;
6260 importer_ = importer;
6267 this->map_ = rowMap;
6268 domainMap_ = domainMap;
6269 rangeMap_ = rangeMap;
6273 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6279 using LO = LocalOrdinal;
6280 using GO = GlobalOrdinal;
6281 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6282 const bool verbose = verbose_;
6284 std::unique_ptr<std::string> prefix;
6286 prefix = this->createPrefix(
"CrsGraph",
"getLocalDiagOffsets");
6287 std::ostringstream os;
6288 os << *prefix <<
"offsets.extent(0)=" << offsets.extent(0)
6290 std::cerr << os.str();
6293 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6294 (! hasColMap (), std::runtime_error,
"The graph must have a column Map.");
6295 const LO lclNumRows =
static_cast<LO
> (this->getLocalNumRows ());
6296 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6297 (static_cast<LO> (offsets.extent (0)) < lclNumRows,
6298 std::invalid_argument,
"offsets.extent(0) = " <<
6299 offsets.extent (0) <<
" < getLocalNumRows() = " << lclNumRows <<
".");
6301 const map_type& rowMap = * (this->getRowMap ());
6302 const map_type& colMap = * (this->getColMap ());
6308 bool allRowMapDiagEntriesInColMap =
true;
6309 bool allDiagEntriesFound =
true;
6310 bool allOffsetsCorrect =
true;
6311 bool noOtherWeirdness =
true;
6312 using wrong_offsets_type = std::vector<std::pair<LO, size_t> >;
6313 wrong_offsets_type wrongOffsets(0);
6317 auto lclRowMap = rowMap.getLocalMap ();
6324 const bool sorted = this->isSorted ();
6325 if (isFillComplete ()) {
6326 auto lclGraph = this->getLocalGraphDevice ();
6327 ::Tpetra::Details::getGraphDiagOffsets (offsets, lclRowMap, lclColMap,
6329 lclGraph.entries, sorted);
6335 auto offsets_h = Kokkos::create_mirror_view (offsets);
6337 for (LO lclRowInd = 0; lclRowInd < lclNumRows; ++lclRowInd) {
6341 const GO gblRowInd = lclRowMap.getGlobalElement (lclRowInd);
6342 const GO gblColInd = gblRowInd;
6343 const LO lclColInd = lclColMap.getLocalElement (gblColInd);
6345 if (lclColInd == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
6346 allRowMapDiagEntriesInColMap =
false;
6347 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6350 const RowInfo rowInfo = this->getRowInfo (lclRowInd);
6351 if (static_cast<LO> (rowInfo.localRow) == lclRowInd &&
6352 rowInfo.numEntries > 0) {
6354 auto colInds = this->getLocalIndsViewHost (rowInfo);
6355 const size_t hint = 0;
6356 const size_t offset =
6357 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
6358 lclColInd, hint, sorted);
6359 offsets_h(lclRowInd) = offset;
6366 typename local_inds_dualv_type::t_host::const_type lclColInds;
6368 lclColInds = this->getLocalIndsViewHost (rowInfo);
6371 noOtherWeirdness =
false;
6374 if (noOtherWeirdness) {
6375 const size_t numEnt = lclColInds.extent (0);
6376 if (offset >= numEnt) {
6379 allOffsetsCorrect =
false;
6380 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6382 const LO actualLclColInd = lclColInds(offset);
6383 const GO actualGblColInd = lclColMap.getGlobalElement (actualLclColInd);
6384 if (actualGblColInd != gblColInd) {
6385 allOffsetsCorrect =
false;
6386 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6393 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6394 allDiagEntriesFound =
false;
6402 if (verbose && wrongOffsets.size () != 0) {
6403 std::ostringstream os;
6404 os << *prefix <<
"Wrong offsets: [";
6405 for (
size_t k = 0; k < wrongOffsets.size (); ++k) {
6406 os <<
"(" << wrongOffsets[k].first <<
","
6407 << wrongOffsets[k].second <<
")";
6408 if (k + 1 < wrongOffsets.size ()) {
6413 std::cerr << os.str();
6417 using Teuchos::reduceAll;
6419 Teuchos::RCP<const Teuchos::Comm<int> > comm = this->getComm ();
6420 const bool localSuccess =
6421 allRowMapDiagEntriesInColMap && allDiagEntriesFound && allOffsetsCorrect;
6422 const int numResults = 5;
6424 lclResults[0] = allRowMapDiagEntriesInColMap ? 1 : 0;
6425 lclResults[1] = allDiagEntriesFound ? 1 : 0;
6426 lclResults[2] = allOffsetsCorrect ? 1 : 0;
6427 lclResults[3] = noOtherWeirdness ? 1 : 0;
6430 lclResults[4] = ! localSuccess ? comm->getRank () : comm->getSize ();
6438 reduceAll<int, int> (*comm, Teuchos::REDUCE_MIN,
6439 numResults, lclResults, gblResults);
6441 if (gblResults[0] != 1 || gblResults[1] != 1 || gblResults[2] != 1
6442 || gblResults[3] != 1) {
6443 std::ostringstream os;
6444 os <<
"Issue(s) that we noticed (on Process " << gblResults[4] <<
", "
6445 "possibly among others): " << endl;
6446 if (gblResults[0] == 0) {
6447 os <<
" - The column Map does not contain at least one diagonal entry "
6448 "of the graph." << endl;
6450 if (gblResults[1] == 0) {
6451 os <<
" - On one or more processes, some row does not contain a "
6452 "diagonal entry." << endl;
6454 if (gblResults[2] == 0) {
6455 os <<
" - On one or more processes, some offsets are incorrect."
6458 if (gblResults[3] == 0) {
6459 os <<
" - One or more processes had some other error."
6462 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
6467 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6473 const char tfecfFuncName[] =
"getLocalOffRankOffsets: ";
6474 const bool verbose = verbose_;
6476 std::unique_ptr<std::string> prefix;
6478 prefix = this->createPrefix(
"CrsGraph",
"getLocalOffRankOffsets");
6479 std::ostringstream os;
6480 os << *prefix <<
"offsets.extent(0)=" << offsets.extent(0)
6482 std::cerr << os.str();
6485 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6486 (! hasColMap (), std::runtime_error,
"The graph must have a column Map.");
6489 const size_t lclNumRows = this->getLocalNumRows ();
6491 if (haveLocalOffRankOffsets_ && k_offRankOffsets_.extent(0) == lclNumRows+1) {
6492 offsets = k_offRankOffsets_;
6495 haveLocalOffRankOffsets_ =
false;
6497 const map_type& colMap = * (this->getColMap ());
6498 const map_type& domMap = * (this->getDomainMap ());
6509 TEUCHOS_ASSERT(this->isSorted ());
6510 if (isFillComplete ()) {
6511 k_offRankOffsets_ = offset_device_view_type(Kokkos::ViewAllocateWithoutInitializing(
"offRankOffset"), lclNumRows+1);
6512 auto lclGraph = this->getLocalGraphDevice ();
6513 ::Tpetra::Details::getGraphOffRankOffsets (k_offRankOffsets_,
6514 lclColMap, lclDomMap,
6516 offsets = k_offRankOffsets_;
6517 haveLocalOffRankOffsets_ =
true;
6519 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6520 (
true, std::logic_error,
"Can't get off-rank offsets for non-fill-complete graph");
6542 template<
class DeviceType,
6543 const bool memSpaceIsHostSpace =
6544 std::is_same<
typename DeviceType::memory_space,
6545 Kokkos::HostSpace>::value>
6546 struct HelpGetLocalDiagOffsets {};
6548 template<
class DeviceType>
6549 struct HelpGetLocalDiagOffsets<DeviceType, true> {
6550 typedef DeviceType device_type;
6551 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6552 Kokkos::MemoryUnmanaged> device_offsets_type;
6553 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6554 Kokkos::MemoryUnmanaged> host_offsets_type;
6556 static device_offsets_type
6557 getDeviceOffsets (
const host_offsets_type& hostOffsets)
6565 copyBackIfNeeded (
const host_offsets_type& ,
6566 const device_offsets_type& )
6570 template<
class DeviceType>
6571 struct HelpGetLocalDiagOffsets<DeviceType, false> {
6572 typedef DeviceType device_type;
6576 typedef Kokkos::View<size_t*, device_type> device_offsets_type;
6577 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6578 Kokkos::MemoryUnmanaged> host_offsets_type;
6580 static device_offsets_type
6581 getDeviceOffsets (
const host_offsets_type& hostOffsets)
6585 return device_offsets_type (
"offsets", hostOffsets.extent (0));
6589 copyBackIfNeeded (
const host_offsets_type& hostOffsets,
6590 const device_offsets_type& deviceOffsets)
6599 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6604 typedef LocalOrdinal LO;
6605 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6606 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6607 (! this->hasColMap (), std::runtime_error,
6608 "The graph does not yet have a column Map.");
6609 const LO myNumRows =
static_cast<LO
> (this->getLocalNumRows ());
6610 if (static_cast<LO> (offsets.size ()) != myNumRows) {
6614 offsets.resize (myNumRows);
6626 typedef HelpGetLocalDiagOffsets<device_type> helper_type;
6627 typedef typename helper_type::host_offsets_type host_offsets_type;
6629 host_offsets_type hostOffsets (offsets.getRawPtr (), myNumRows);
6631 auto deviceOffsets = helper_type::getDeviceOffsets (hostOffsets);
6633 this->getLocalDiagOffsets (deviceOffsets);
6634 helper_type::copyBackIfNeeded (hostOffsets, deviceOffsets);
6637 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6644 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6648 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& rowTransfer,
6649 const Teuchos::RCP<const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node> > & domainTransfer,
6650 const Teuchos::RCP<const map_type>& domainMap,
6651 const Teuchos::RCP<const map_type>& rangeMap,
6652 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
6658 using Teuchos::ArrayRCP;
6659 using Teuchos::ArrayView;
6660 using Teuchos::Comm;
6661 using Teuchos::ParameterList;
6664 #ifdef HAVE_TPETRA_MMM_TIMINGS
6666 using Teuchos::TimeMonitor;
6669 using LO = LocalOrdinal;
6670 using GO = GlobalOrdinal;
6671 using NT = node_type;
6675 const char* prefix =
"Tpetra::CrsGraph::transferAndFillComplete: ";
6677 #ifdef HAVE_TPETRA_MMM_TIMINGS
6679 if(!params.is_null()) label = params->get(
"Timer Label", label);
6680 string prefix2 = string(
"Tpetra ")+ label + std::string(
": CrsGraph TAFC ");
6681 RCP<TimeMonitor> MM =
6682 rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Pack-1"))));
6690 const import_type* xferAsImport =
dynamic_cast<const import_type*
>(&rowTransfer);
6691 const export_type* xferAsExport =
dynamic_cast<const export_type*
>(&rowTransfer);
6692 TEUCHOS_TEST_FOR_EXCEPTION(
6693 xferAsImport ==
nullptr && xferAsExport ==
nullptr, std::invalid_argument,
6694 prefix <<
"The 'rowTransfer' input argument must be either an Import or "
6695 "an Export, and its template parameters must match the corresponding "
6696 "template parameters of the CrsGraph.");
6703 Teuchos::RCP<const import_type> xferDomainAsImport =
6704 Teuchos::rcp_dynamic_cast<
const import_type>(domainTransfer);
6705 Teuchos::RCP<const export_type> xferDomainAsExport =
6706 Teuchos::rcp_dynamic_cast<
const export_type>(domainTransfer);
6708 if(! domainTransfer.is_null()) {
6710 TEUCHOS_TEST_FOR_EXCEPTION(
6711 (xferDomainAsImport.is_null() && xferDomainAsExport.is_null()), std::invalid_argument,
6712 prefix <<
"The 'domainTransfer' input argument must be either an "
6713 "Import or an Export, and its template parameters must match the "
6714 "corresponding template parameters of the CrsGraph.");
6716 TEUCHOS_TEST_FOR_EXCEPTION(
6717 ( xferAsImport !=
nullptr || ! xferDomainAsImport.is_null() ) &&
6718 (( xferAsImport !=
nullptr && xferDomainAsImport.is_null() ) ||
6719 ( xferAsImport ==
nullptr && ! xferDomainAsImport.is_null() )), std::invalid_argument,
6720 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6721 "must be of the same type (either Import or Export).");
6723 TEUCHOS_TEST_FOR_EXCEPTION(
6724 ( xferAsExport !=
nullptr || ! xferDomainAsExport.is_null() ) &&
6725 (( xferAsExport !=
nullptr && xferDomainAsExport.is_null() ) ||
6726 ( xferAsExport ==
nullptr && ! xferDomainAsExport.is_null() )), std::invalid_argument,
6727 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6728 "must be of the same type (either Import or Export).");
6735 const bool communication_needed = rowTransfer.getSourceMap()->isDistributed();
6741 bool reverseMode =
false;
6742 bool restrictComm =
false;
6743 RCP<ParameterList> graphparams;
6744 if (! params.is_null()) {
6745 reverseMode = params->get(
"Reverse Mode", reverseMode);
6746 restrictComm = params->get(
"Restrict Communicator", restrictComm);
6747 graphparams = sublist(params,
"CrsGraph");
6752 RCP<const map_type> MyRowMap = reverseMode ?
6753 rowTransfer.getSourceMap() : rowTransfer.getTargetMap();
6754 RCP<const map_type> MyColMap;
6755 RCP<const map_type> MyDomainMap = ! domainMap.is_null() ? domainMap : getDomainMap();
6756 RCP<const map_type> MyRangeMap = ! rangeMap.is_null() ? rangeMap : getRangeMap();
6757 RCP<const map_type> BaseRowMap = MyRowMap;
6758 RCP<const map_type> BaseDomainMap = MyDomainMap;
6766 if (! destGraph.is_null()) {
6777 const bool NewFlag =
6778 ! destGraph->isLocallyIndexed() && ! destGraph->isGloballyIndexed();
6779 TEUCHOS_TEST_FOR_EXCEPTION(! NewFlag, std::invalid_argument,
6780 prefix <<
"The input argument 'destGraph' is only allowed to be nonnull, "
6781 "if its graph is empty (neither locally nor globally indexed).");
6790 TEUCHOS_TEST_FOR_EXCEPTION(
6791 ! destGraph->getRowMap()->isSameAs(*MyRowMap), std::invalid_argument,
6792 prefix <<
"The (row) Map of the input argument 'destGraph' is not the "
6793 "same as the (row) Map specified by the input argument 'rowTransfer'.");
6795 TEUCHOS_TEST_FOR_EXCEPTION(
6796 ! destGraph->checkSizes(*
this), std::invalid_argument,
6797 prefix <<
"You provided a nonnull destination graph, but checkSizes() "
6798 "indicates that it is not a legal legal target for redistribution from "
6799 "the source graph (*this). This may mean that they do not have the "
6800 "same dimensions.");
6814 TEUCHOS_TEST_FOR_EXCEPTION(
6815 ! (reverseMode || getRowMap()->isSameAs(*rowTransfer.getSourceMap())),
6816 std::invalid_argument, prefix <<
6817 "rowTransfer->getSourceMap() must match this->getRowMap() in forward mode.");
6819 TEUCHOS_TEST_FOR_EXCEPTION(
6820 ! (! reverseMode || getRowMap()->isSameAs(*rowTransfer.getTargetMap())),
6821 std::invalid_argument, prefix <<
6822 "rowTransfer->getTargetMap() must match this->getRowMap() in reverse mode.");
6825 TEUCHOS_TEST_FOR_EXCEPTION(
6826 ! xferDomainAsImport.is_null() && ! xferDomainAsImport->getTargetMap()->isSameAs(*domainMap),
6827 std::invalid_argument,
6828 prefix <<
"The target map of the 'domainTransfer' input argument must be "
6829 "the same as the rebalanced domain map 'domainMap'");
6831 TEUCHOS_TEST_FOR_EXCEPTION(
6832 ! xferDomainAsExport.is_null() && ! xferDomainAsExport->getSourceMap()->isSameAs(*domainMap),
6833 std::invalid_argument,
6834 prefix <<
"The source map of the 'domainTransfer' input argument must be "
6835 "the same as the rebalanced domain map 'domainMap'");
6848 const size_t NumSameIDs = rowTransfer.getNumSameIDs();
6849 ArrayView<const LO> ExportLIDs = reverseMode ?
6850 rowTransfer.getRemoteLIDs() : rowTransfer.getExportLIDs();
6851 ArrayView<const LO> RemoteLIDs = reverseMode ?
6852 rowTransfer.getExportLIDs() : rowTransfer.getRemoteLIDs();
6853 ArrayView<const LO> PermuteToLIDs = reverseMode ?
6854 rowTransfer.getPermuteFromLIDs() : rowTransfer.getPermuteToLIDs();
6855 ArrayView<const LO> PermuteFromLIDs = reverseMode ?
6856 rowTransfer.getPermuteToLIDs() : rowTransfer.getPermuteFromLIDs();
6857 Distributor& Distor = rowTransfer.getDistributor();
6860 Teuchos::Array<int> SourcePids;
6861 Teuchos::Array<int> TargetPids;
6862 int MyPID = getComm()->getRank();
6865 RCP<const map_type> ReducedRowMap, ReducedColMap,
6866 ReducedDomainMap, ReducedRangeMap;
6867 RCP<const Comm<int> > ReducedComm;
6871 if (destGraph.is_null()) {
6872 destGraph = rcp(
new this_CRS_type(MyRowMap, 0, graphparams));
6879 ReducedRowMap = MyRowMap->removeEmptyProcesses();
6880 ReducedComm = ReducedRowMap.is_null() ?
6882 ReducedRowMap->getComm();
6883 destGraph->removeEmptyProcessesInPlace(ReducedRowMap);
6885 ReducedDomainMap = MyRowMap.getRawPtr() == MyDomainMap.getRawPtr() ?
6887 MyDomainMap->replaceCommWithSubset(ReducedComm);
6888 ReducedRangeMap = MyRowMap.getRawPtr() == MyRangeMap.getRawPtr() ?
6890 MyRangeMap->replaceCommWithSubset(ReducedComm);
6893 MyRowMap = ReducedRowMap;
6894 MyDomainMap = ReducedDomainMap;
6895 MyRangeMap = ReducedRangeMap;
6898 if (! ReducedComm.is_null()) {
6899 MyPID = ReducedComm->getRank();
6906 ReducedComm = MyRowMap->getComm();
6912 #ifdef HAVE_TPETRA_MMM_TIMINGS
6914 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ImportSetup"))));
6917 RCP<const import_type> MyImporter = getImporter();
6920 bool bSameDomainMap = BaseDomainMap->isSameAs(*getDomainMap());
6922 if (! restrictComm && ! MyImporter.is_null() && bSameDomainMap ) {
6929 Import_Util::getPids(*MyImporter, SourcePids,
false);
6931 else if (restrictComm && ! MyImporter.is_null() && bSameDomainMap) {
6934 ivector_type SourceDomain_pids(getDomainMap(),
true);
6935 ivector_type SourceCol_pids(getColMap());
6937 SourceDomain_pids.putScalar(MyPID);
6939 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6940 SourcePids.resize(getColMap()->getLocalNumElements());
6941 SourceCol_pids.get1dCopy(SourcePids());
6943 else if (MyImporter.is_null() && bSameDomainMap) {
6945 SourcePids.resize(getColMap()->getLocalNumElements());
6946 SourcePids.assign(getColMap()->getLocalNumElements(), MyPID);
6948 else if ( ! MyImporter.is_null() &&
6949 ! domainTransfer.is_null() ) {
6956 ivector_type TargetDomain_pids(domainMap);
6957 TargetDomain_pids.putScalar(MyPID);
6960 ivector_type SourceDomain_pids(getDomainMap());
6963 ivector_type SourceCol_pids(getColMap());
6965 if (! reverseMode && ! xferDomainAsImport.is_null() ) {
6966 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6968 else if (reverseMode && ! xferDomainAsExport.is_null() ) {
6969 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6971 else if (! reverseMode && ! xferDomainAsExport.is_null() ) {
6972 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6974 else if (reverseMode && ! xferDomainAsImport.is_null() ) {
6975 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6978 TEUCHOS_TEST_FOR_EXCEPTION(
6979 true, std::logic_error,
6980 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6982 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6983 SourcePids.resize(getColMap()->getLocalNumElements());
6984 SourceCol_pids.get1dCopy(SourcePids());
6986 else if (BaseDomainMap->isSameAs(*BaseRowMap) &&
6987 getDomainMap()->isSameAs(*getRowMap())) {
6989 ivector_type TargetRow_pids(domainMap);
6990 ivector_type SourceRow_pids(getRowMap());
6991 ivector_type SourceCol_pids(getColMap());
6993 TargetRow_pids.putScalar(MyPID);
6994 if (! reverseMode && xferAsImport !=
nullptr) {
6995 SourceRow_pids.doExport(TargetRow_pids, *xferAsImport,
INSERT);
6997 else if (reverseMode && xferAsExport !=
nullptr) {
6998 SourceRow_pids.doExport(TargetRow_pids, *xferAsExport,
INSERT);
7000 else if (! reverseMode && xferAsExport !=
nullptr) {
7001 SourceRow_pids.doImport(TargetRow_pids, *xferAsExport,
INSERT);
7003 else if (reverseMode && xferAsImport !=
nullptr) {
7004 SourceRow_pids.doImport(TargetRow_pids, *xferAsImport,
INSERT);
7007 TEUCHOS_TEST_FOR_EXCEPTION(
7008 true, std::logic_error,
7009 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
7011 SourceCol_pids.doImport(SourceRow_pids, *MyImporter,
INSERT);
7012 SourcePids.resize(getColMap()->getLocalNumElements());
7013 SourceCol_pids.get1dCopy(SourcePids());
7016 TEUCHOS_TEST_FOR_EXCEPTION(
7017 true, std::invalid_argument,
7018 prefix <<
"This method only allows either domainMap == getDomainMap(), "
7019 "or (domainMap == rowTransfer.getTargetMap() and getDomainMap() == getRowMap()).");
7023 size_t constantNumPackets = destGraph->constantNumberOfPackets();
7024 if (constantNumPackets == 0) {
7025 destGraph->reallocArraysForNumPacketsPerLid(ExportLIDs.size(),
7033 const size_t rbufLen = RemoteLIDs.size() * constantNumPackets;
7034 destGraph->reallocImportsIfNeeded(rbufLen,
false,
nullptr);
7039 destGraph->numExportPacketsPerLID_.modify_host();
7040 Teuchos::ArrayView<size_t> numExportPacketsPerLID =
7045 numExportPacketsPerLID, ExportLIDs,
7046 SourcePids, constantNumPackets);
7050 #ifdef HAVE_TPETRA_MMM_TIMINGS
7052 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Transfer"))));
7055 if (communication_needed) {
7057 if (constantNumPackets == 0) {
7061 destGraph->numExportPacketsPerLID_.sync_host();
7062 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
7064 destGraph->numImportPacketsPerLID_.sync_host();
7065 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
7068 Distor.doReversePostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
7069 destGraph->numImportPacketsPerLID_.view_host());
7070 size_t totalImportPackets = 0;
7072 totalImportPackets += numImportPacketsPerLID[i];
7077 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
7078 destGraph->imports_.modify_host();
7079 auto hostImports = destGraph->imports_.view_host();
7082 destGraph->exports_.sync_host();
7083 auto hostExports = destGraph->exports_.view_host();
7084 Distor.doReversePostsAndWaits(hostExports,
7085 numExportPacketsPerLID,
7087 numImportPacketsPerLID);
7090 destGraph->imports_.modify_host();
7091 auto hostImports = destGraph->imports_.view_host();
7094 destGraph->exports_.sync_host();
7095 auto hostExports = destGraph->exports_.view_host();
7096 Distor.doReversePostsAndWaits(hostExports,
7102 if (constantNumPackets == 0) {
7106 destGraph->numExportPacketsPerLID_.sync_host();
7107 destGraph->numImportPacketsPerLID_.sync_host();
7108 Distor.doPostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
7109 destGraph->numImportPacketsPerLID_.view_host());
7111 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
7113 size_t totalImportPackets = 0;
7115 totalImportPackets += numImportPacketsPerLID[i];
7120 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
7121 destGraph->imports_.modify_host();
7122 auto hostImports = destGraph->imports_.view_host();
7125 destGraph->exports_.sync_host();
7126 auto hostExports = destGraph->exports_.view_host();
7127 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
7129 Distor.doPostsAndWaits(hostExports, numExportPacketsPerLID, hostImports, numImportPacketsPerLID);
7132 destGraph->imports_.modify_host();
7133 auto hostImports = destGraph->imports_.view_host();
7136 destGraph->exports_.sync_host();
7137 auto hostExports = destGraph->exports_.view_host();
7138 Distor.doPostsAndWaits(hostExports, constantNumPackets, hostImports);
7147 #ifdef HAVE_TPETRA_MMM_TIMINGS
7149 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-1"))));
7153 destGraph->numImportPacketsPerLID_.sync_host();
7154 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
7156 destGraph->imports_.sync_host();
7157 Teuchos::ArrayView<const packet_type> hostImports =
7161 numImportPacketsPerLID,
7162 constantNumPackets,
INSERT,
7163 NumSameIDs, PermuteToLIDs, PermuteFromLIDs);
7164 size_t N = BaseRowMap->getLocalNumElements();
7167 ArrayRCP<size_t> CSR_rowptr(N+1);
7168 ArrayRCP<GO> CSR_colind_GID;
7169 ArrayRCP<LO> CSR_colind_LID;
7170 CSR_colind_GID.resize(mynnz);
7174 if (
typeid(LO) ==
typeid(GO)) {
7175 CSR_colind_LID = Teuchos::arcp_reinterpret_cast<LO>(CSR_colind_GID);
7178 CSR_colind_LID.resize(mynnz);
7187 numImportPacketsPerLID, constantNumPackets,
7188 INSERT, NumSameIDs, PermuteToLIDs,
7189 PermuteFromLIDs, N, mynnz, MyPID,
7190 CSR_rowptr(), CSR_colind_GID(),
7191 SourcePids(), TargetPids);
7196 #ifdef HAVE_TPETRA_MMM_TIMINGS
7198 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-2"))));
7203 Teuchos::Array<int> RemotePids;
7204 Import_Util::lowCommunicationMakeColMapAndReindex(CSR_rowptr(),
7208 TargetPids, RemotePids,
7215 ReducedColMap = (MyRowMap.getRawPtr() == MyColMap.getRawPtr()) ?
7217 MyColMap->replaceCommWithSubset(ReducedComm);
7218 MyColMap = ReducedColMap;
7222 destGraph->replaceColMap(MyColMap);
7229 if (ReducedComm.is_null()) {
7236 if ((! reverseMode && xferAsImport !=
nullptr) ||
7237 (reverseMode && xferAsExport !=
nullptr)) {
7238 Import_Util::sortCrsEntries(CSR_rowptr(),
7241 else if ((! reverseMode && xferAsExport !=
nullptr) ||
7242 (reverseMode && xferAsImport !=
nullptr)) {
7243 Import_Util::sortAndMergeCrsEntries(CSR_rowptr(),
7245 if (CSR_rowptr[N] != mynnz) {
7246 CSR_colind_LID.resize(CSR_rowptr[N]);
7250 TEUCHOS_TEST_FOR_EXCEPTION(
7251 true, std::logic_error,
7252 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
7260 destGraph->setAllIndices(CSR_rowptr, CSR_colind_LID);
7266 Teuchos::ParameterList esfc_params;
7267 #ifdef HAVE_TPETRA_MMM_TIMINGS
7269 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"CreateImporter"))));
7271 RCP<import_type> MyImport = rcp(
new import_type(MyDomainMap, MyColMap, RemotePids));
7272 #ifdef HAVE_TPETRA_MMM_TIMINGS
7274 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ESFC"))));
7276 esfc_params.set(
"Timer Label",prefix + std::string(
"TAFC"));
7278 if(!params.is_null())
7279 esfc_params.set(
"compute global constants",params->get(
"compute global constants",
true));
7281 destGraph->expertStaticFillComplete(MyDomainMap, MyRangeMap,
7282 MyImport, Teuchos::null, rcp(&esfc_params,
false));
7286 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7291 const Teuchos::RCP<const map_type>& domainMap,
7292 const Teuchos::RCP<const map_type>& rangeMap,
7293 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7295 transferAndFillComplete(destGraph, importer, Teuchos::null, domainMap, rangeMap, params);
7298 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7304 const Teuchos::RCP<const map_type>& domainMap,
7305 const Teuchos::RCP<const map_type>& rangeMap,
7306 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7308 transferAndFillComplete(destGraph, rowImporter, Teuchos::rcpFromRef(domainImporter), domainMap, rangeMap, params);
7311 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7316 const Teuchos::RCP<const map_type>& domainMap,
7317 const Teuchos::RCP<const map_type>& rangeMap,
7318 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7320 transferAndFillComplete(destGraph, exporter, Teuchos::null, domainMap, rangeMap, params);
7323 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7329 const Teuchos::RCP<const map_type>& domainMap,
7330 const Teuchos::RCP<const map_type>& rangeMap,
7331 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7333 transferAndFillComplete(destGraph, rowExporter, Teuchos::rcpFromRef(domainExporter), domainMap, rangeMap, params);
7337 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7342 std::swap(graph.need_sync_host_uvm_access, this->need_sync_host_uvm_access);
7344 std::swap(graph.
rowMap_, this->rowMap_);
7345 std::swap(graph.
colMap_, this->colMap_);
7346 std::swap(graph.
rangeMap_, this->rangeMap_);
7347 std::swap(graph.
domainMap_, this->domainMap_);
7349 std::swap(graph.
importer_, this->importer_);
7350 std::swap(graph.
exporter_, this->exporter_);
7359 std::swap(graph.rowPtrsPacked_dev_, this->rowPtrsPacked_dev_);
7360 std::swap(graph.rowPtrsPacked_host_, this->rowPtrsPacked_host_);
7362 std::swap(graph.rowPtrsUnpacked_dev_, this->rowPtrsUnpacked_dev_);
7363 std::swap(graph.rowPtrsUnpacked_host_, this->rowPtrsUnpacked_host_);
7364 std::swap(graph.packedUnpackedRowPtrsMatch_, this->packedUnpackedRowPtrsMatch_);
7374 std::swap(graph.indicesAreAllocated_, this->indicesAreAllocated_);
7375 std::swap(graph.indicesAreLocal_, this->indicesAreLocal_);
7376 std::swap(graph.indicesAreGlobal_, this->indicesAreGlobal_);
7377 std::swap(graph.fillComplete_, this->fillComplete_);
7382 std::swap(graph.haveLocalOffRankOffsets_, this->haveLocalOffRankOffsets_);
7388 std::swap(graph.
nonlocals_, this->nonlocals_);
7392 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7397 auto compare_nonlocals = [&] (
const nonlocals_type & m1,
const nonlocals_type & m2) {
7399 output = m1.size() == m2.size() ? output :
false;
7400 for(
auto & it_m: m1)
7402 size_t key = it_m.first;
7403 output = m2.find(key) != m2.end() ? output :
false;
7406 auto v1 = m1.find(key)->second;
7407 auto v2 = m2.find(key)->second;
7411 output = v1.size() == v2.size() ? output :
false;
7412 for(
size_t i=0; output && i<v1.size(); i++)
7414 output = v1[i]==v2[i] ? output :
false;
7423 output = this->rowMap_->isSameAs( *(graph.
rowMap_) ) ? output :
false;
7424 output = this->colMap_->isSameAs( *(graph.
colMap_) ) ? output :
false;
7425 output = this->rangeMap_->isSameAs( *(graph.
rangeMap_) ) ? output :
false;
7426 output = this->domainMap_->isSameAs( *(graph.
domainMap_) ) ? output :
false;
7435 output = this->storageStatus_ == graph.
storageStatus_ ? output :
false;
7437 output = this->indicesAreAllocated_ == graph.indicesAreAllocated_ ? output :
false;
7438 output = this->indicesAreLocal_ == graph.indicesAreLocal_ ? output :
false;
7439 output = this->indicesAreGlobal_ == graph.indicesAreGlobal_ ? output :
false;
7440 output = this->fillComplete_ == graph.fillComplete_ ? output :
false;
7442 output = this->noRedundancies_ == graph.
noRedundancies_ ? output :
false;
7445 output = this->haveLocalOffRankOffsets_ == graph.haveLocalOffRankOffsets_ ? output :
false;
7446 output = this->sortGhostsAssociatedWithEachProcessor_ == this->sortGhostsAssociatedWithEachProcessor_ ? output :
false;
7450 output = compare_nonlocals(this->nonlocals_, graph.
nonlocals_) ? output :
false;
7454 output = this->k_numAllocPerRow_.extent(0) == graph.
k_numAllocPerRow_.extent(0) ? output :
false;
7455 if(output && this->k_numAllocPerRow_.extent(0) > 0)
7457 for(
size_t i=0; output && i<this->k_numAllocPerRow_.extent(0); i++)
7458 output = this->k_numAllocPerRow_(i) == graph.
k_numAllocPerRow_(i) ? output :
false;
7463 output = this->k_numRowEntries_.extent(0) == graph.
k_numRowEntries_.extent(0) ? output :
false;
7464 if(output && this->k_numRowEntries_.extent(0) > 0)
7466 for(
size_t i = 0; output && i < this->k_numRowEntries_.extent(0); i++)
7467 output = this->k_numRowEntries_(i) == graph.
k_numRowEntries_(i) ? output :
false;
7472 auto rowPtrsThis = this->getRowPtrsUnpackedHost();
7474 output = rowPtrsThis .extent(0) == rowPtrsGraph.extent(0) ? output :
false;
7475 for(
size_t i=0; output && i< rowPtrsThis.extent(0); i++)
7476 output = rowPtrsThis(i) == rowPtrsGraph(i) ? output :
false;
7480 output = this->lclIndsUnpacked_wdv.extent(0) == graph.
lclIndsUnpacked_wdv.extent(0) ? output :
false;
7481 if(output && this->lclIndsUnpacked_wdv.extent(0) > 0)
7483 auto indThis = this->lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
7485 for(
size_t i=0; output && i < indThis.extent(0); i++)
7486 output = indThis(i) == indGraph(i) ? output :
false;
7490 output = this->gblInds_wdv.extent(0) == graph.
gblInds_wdv.extent(0) ? output :
false;
7491 if(output && this->gblInds_wdv.extent(0) > 0)
7493 auto indtThis = this->gblInds_wdv.getHostView(Access::ReadOnly);
7494 auto indtGraph = graph.
gblInds_wdv.getHostView(Access::ReadOnly);
7495 for(
size_t i=0; output && i<indtThis.extent(0); i++)
7496 output = indtThis(i) == indtGraph(i) ? output :
false;
7515 output = thisLclGraph.row_map.extent(0) == graphLclGraph.row_map.extent(0)
7517 if(output && thisLclGraph.row_map.extent(0) > 0)
7519 auto lclGraph_rowmap_host_this = thisLclGraph.row_map;
7520 auto lclGraph_rowmap_host_graph = graphLclGraph.row_map;
7521 for (
size_t i=0; output && i < lclGraph_rowmap_host_this.extent(0); i++)
7522 output = lclGraph_rowmap_host_this(i) == lclGraph_rowmap_host_graph(i)
7526 output = thisLclGraph.entries.extent(0) == graphLclGraph.entries.extent(0)
7528 if(output && thisLclGraph.entries.extent(0) > 0)
7530 auto lclGraph_entries_host_this = thisLclGraph.entries;
7531 auto lclGraph_entries_host_graph = graphLclGraph.entries;
7532 for (
size_t i=0; output && i < lclGraph_entries_host_this.extent(0); i++)
7533 output = lclGraph_entries_host_this(i) == lclGraph_entries_host_graph(i)
7538 thisLclGraph.row_block_offsets.extent(0) ==
7539 graphLclGraph.row_block_offsets.extent(0) ? output :
false;
7540 if(output && thisLclGraph.row_block_offsets.extent(0) > 0)
7542 auto lclGraph_rbo_host_this = thisLclGraph.row_block_offsets;
7543 auto lclGraph_rbo_host_graph = graphLclGraph.row_block_offsets;
7544 for (
size_t i=0; output && i < lclGraph_rbo_host_this.extent(0); i++)
7545 output = lclGraph_rbo_host_this(i) == lclGraph_rbo_host_graph(i)
7567 #define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7569 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7570 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7571 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7572 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7573 CrsGraph<LO,GO,NODE>::node_type>& importer, \
7574 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7575 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7576 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7577 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7578 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7579 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7580 const Teuchos::RCP<Teuchos::ParameterList>& params);
7582 #define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7584 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7585 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7586 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7587 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7588 CrsGraph<LO,GO,NODE>::node_type>& rowImporter, \
7589 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7590 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7591 CrsGraph<LO,GO,NODE>::node_type>& domainImporter, \
7592 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7593 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7594 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7595 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7596 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7597 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7598 const Teuchos::RCP<Teuchos::ParameterList>& params);
7601 #define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7603 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7604 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7605 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7606 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7607 CrsGraph<LO,GO,NODE>::node_type>& exporter, \
7608 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7609 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7610 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7611 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7612 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7613 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7614 const Teuchos::RCP<Teuchos::ParameterList>& params);
7616 #define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7618 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7619 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7620 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7621 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7622 CrsGraph<LO,GO,NODE>::node_type>& rowExporter, \
7623 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7624 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7625 CrsGraph<LO,GO,NODE>::node_type>& domainExporter, \
7626 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7627 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7628 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7629 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7630 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7631 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7632 const Teuchos::RCP<Teuchos::ParameterList>& params);
7635 #define TPETRA_CRSGRAPH_INSTANT( LO, GO, NODE ) \
7636 template class CrsGraph<LO, GO, NODE>; \
7637 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7638 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7639 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7640 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE)
7643 #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.
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.
Kokkos::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.
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.
typename device_type::execution_space execution_space
This class' Kokkos execution space.
RowInfo getRowInfoFromGlobalRowIndex(const global_ordinal_type gblRow) const
Get information about the locally owned row with global index gblRow.
Utility functions for packing and unpacking sparse matrix entries.
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 local Map 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.