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"
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_;
194 ::Tpetra::Details::LocalMap<LO, GO, DT> lclColMap_;
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>
284 template <
class LocalOrdinal,
class GlobalOrdinal,
class 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) :
296 dist_object_type (rowMap)
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>
313 CrsGraph<LocalOrdinal, GlobalOrdinal, 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) :
318 dist_object_type (rowMap)
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>
337 CrsGraph<LocalOrdinal, GlobalOrdinal, 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) :
341 dist_object_type (rowMap)
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;
382 Kokkos::deep_copy (exec_space(), numAllocPerRowOut, numAllocPerRowIn);
391 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
392 CrsGraph<LocalOrdinal, GlobalOrdinal, 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) :
396 dist_object_type (rowMap)
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>
430 CrsGraph<LocalOrdinal, GlobalOrdinal, 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) :
435 dist_object_type (rowMap)
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>
470 CrsGraph<LocalOrdinal, GlobalOrdinal, 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) :
475 dist_object_type (rowMap)
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;
517 Kokkos::deep_copy (exec_space(), numAllocPerRowOut, numAllocPerRowIn);
525 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
526 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
527 CrsGraph (CrsGraph<local_ordinal_type, global_ordinal_type, node_type>& originalGraph,
528 const Teuchos::RCP<const map_type>& rowMap,
529 const Teuchos::RCP<Teuchos::ParameterList>& params) :
530 dist_object_type (rowMap)
535 , indicesAreAllocated_(originalGraph.indicesAreAllocated_)
536 , indicesAreLocal_(originalGraph.indicesAreLocal_)
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>
561 CrsGraph<LocalOrdinal, GlobalOrdinal, 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) :
567 dist_object_type (rowMap)
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>
588 CrsGraph<LocalOrdinal, GlobalOrdinal, 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) :
594 dist_object_type (rowMap)
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>
615 CrsGraph<LocalOrdinal, GlobalOrdinal, 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)
620 : CrsGraph (k_local_graph_,
628 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
629 CrsGraph<LocalOrdinal, GlobalOrdinal, 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)
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>
699 CrsGraph<LocalOrdinal, GlobalOrdinal, 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),
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");
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 =
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(
815 "The graph does not have a domain Map. You may not call this method in "
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(
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>
906 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
914 const bool isOpt = indicesAreAllocated_ &&
922 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
927 const char tfecfFuncName[] =
"getGlobalNumEntries: ";
928 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
930 "The graph does not have global constants computed, "
931 "but the user has requested them.");
937 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
942 typedef LocalOrdinal LO;
944 if (this->indicesAreAllocated_) {
946 if (lclNumRows == 0) {
947 return static_cast<size_t> (0);
952 const LO numNumEntPerRow = numEntPerRow.extent (0);
953 if (numNumEntPerRow == 0) {
955 static_cast<LO
> (lclNumRows + 1)) {
956 return static_cast<size_t> (0);
969 typedef typename num_row_entries_type::execution_space
971 typedef Kokkos::RangePolicy<host_exec_space, LO> range_type;
973 const LO upperLoopBound = lclNumRows < numNumEntPerRow ?
976 size_t nodeNumEnt = 0;
977 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::getNumNodeEntries",
978 range_type (0, upperLoopBound),
979 [=] (
const LO& k,
size_t& lclSum) {
980 lclSum += numEntPerRow(k);
987 return static_cast<size_t> (0);
991 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
996 const char tfecfFuncName[] =
"getGlobalMaxNumRowEntries: ";
997 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
999 "The graph does not have global constants computed, "
1000 "but the user has requested them.");
1005 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1013 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1018 return fillComplete_;
1021 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1026 return ! fillComplete_;
1030 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1035 return indicesAreLocal_;
1038 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1043 return indicesAreGlobal_;
1046 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1051 typedef LocalOrdinal LO;
1053 if (this->indicesAreAllocated_) {
1055 if (lclNumRows == 0) {
1056 return static_cast<size_t> (0);
1060 static_cast<LO
> (lclNumRows + 1)) {
1061 return static_cast<size_t> (0);
1069 if (rowPtrsUnpacked_host.extent (0) == 0) {
1070 return static_cast<size_t> (0);
1073 return rowPtrsUnpacked_host(lclNumRows);
1077 return static_cast<size_t> (0);
1081 return Tpetra::Details::OrdinalTraits<size_t>::invalid ();
1085 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1086 Teuchos::RCP<const Teuchos::Comm<int> >
1090 return this->
rowMap_.is_null () ? Teuchos::null : this->
rowMap_->getComm ();
1093 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1098 return rowMap_->getIndexBase ();
1101 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1106 return indicesAreAllocated_;
1109 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1117 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1125 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1143 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1149 using Teuchos::arcp;
1150 using Teuchos::Array;
1151 using Teuchos::ArrayRCP;
1153 typedef Teuchos::ArrayRCP<size_t>::size_type size_type;
1154 typedef typename local_graph_device_type::row_map_type::non_const_type
1155 non_const_row_map_type;
1156 const char tfecfFuncName[] =
"allocateIndices: ";
1157 const char suffix[] =
1158 " Please report this bug to the Tpetra developers.";
1159 ProfilingRegion profRegion(
"Tpetra::CrsGraph::allocateIndices");
1161 std::unique_ptr<std::string> prefix;
1163 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
1164 std::ostringstream os;
1165 os << *prefix <<
"Start: lg="
1166 << (lg == GlobalIndices ?
"GlobalIndices" :
"LocalIndices")
1167 <<
", numRows: " << this->getLocalNumRows() << endl;
1168 std::cerr << os.str();
1174 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1175 (isLocallyIndexed () && lg == GlobalIndices, std::logic_error,
1176 ": The graph is locally indexed, but Tpetra code is calling "
1177 "this method with lg=GlobalIndices." << suffix);
1178 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1179 (isGloballyIndexed () && lg == LocalIndices, std::logic_error,
1180 ": The graph is globally indexed, but Tpetra code is calling "
1181 "this method with lg=LocalIndices." << suffix);
1182 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1183 (indicesAreAllocated (), std::logic_error,
": The graph's "
1184 "indices are already allocated, but Tpetra is calling "
1185 "allocateIndices again." << suffix);
1186 const size_t numRows = this->getLocalNumRows ();
1193 std::ostringstream os;
1194 os << *prefix <<
"Allocate k_rowPtrs: " << (numRows+1) << endl;
1195 std::cerr << os.str();
1197 non_const_row_map_type k_rowPtrs (
"Tpetra::CrsGraph::ptr", numRows + 1);
1199 if (this->k_numAllocPerRow_.extent (0) != 0) {
1204 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1205 (this->k_numAllocPerRow_.extent (0) != numRows,
1206 std::invalid_argument,
"k_numAllocPerRow_ is allocated, that is, "
1207 "has nonzero length " << this->k_numAllocPerRow_.extent (0)
1208 <<
", but its length != numRows = " << numRows <<
".");
1226 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1227 (this->numAllocForAllRows_ ==
1228 Tpetra::Details::OrdinalTraits<size_t>::invalid (),
1229 std::invalid_argument,
"numAllocForAllRows_ has an invalid value, "
1230 "namely Tpetra::Details::OrdinalTraits<size_t>::invalid() = " <<
1231 Tpetra::Details::OrdinalTraits<size_t>::invalid () <<
".");
1238 setRowPtrsUnpacked(k_rowPtrs);
1241 const size_type numInds = this->getRowPtrsUnpackedHost()(numRows);
1242 if (lg == LocalIndices) {
1244 std::ostringstream os;
1245 os << *prefix <<
"Allocate local column indices "
1246 "lclIndsUnpacked_wdv: " << numInds << endl;
1247 std::cerr << os.str();
1249 lclIndsUnpacked_wdv = local_inds_wdv_type (
1250 local_inds_dualv_type(
"Tpetra::CrsGraph::lclInd",numInds));
1254 std::ostringstream os;
1255 os << *prefix <<
"Allocate global column indices "
1256 "gblInds_wdv: " << numInds << endl;
1257 std::cerr << os.str();
1259 gblInds_wdv = global_inds_wdv_type (
1260 global_inds_dualv_type(
"Tpetra::CrsGraph::gblInd",numInds));
1262 storageStatus_ = Details::STORAGE_1D_UNPACKED;
1264 this->indicesAreLocal_ = (lg == LocalIndices);
1265 this->indicesAreGlobal_ = (lg == GlobalIndices);
1268 using Kokkos::ViewAllocateWithoutInitializing;
1269 typedef decltype (k_numRowEntries_) row_ent_type;
1270 const char label[] =
"Tpetra::CrsGraph::numRowEntries";
1272 std::ostringstream os;
1273 os << *prefix <<
"Allocate k_numRowEntries_: " << numRows
1275 std::cerr << os.str();
1277 row_ent_type numRowEnt (ViewAllocateWithoutInitializing (label), numRows);
1279 Kokkos::deep_copy (
execution_space(), numRowEnt,
static_cast<size_t> (0));
1281 this->k_numRowEntries_ = numRowEnt;
1285 this->numAllocForAllRows_ = 0;
1286 this->k_numAllocPerRow_ =
decltype (k_numAllocPerRow_) ();
1287 this->indicesAreAllocated_ =
true;
1290 this->checkInternalState ();
1292 catch (std::logic_error& e) {
1293 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1294 (
true, std::logic_error,
"At end of allocateIndices, "
1295 "checkInternalState threw std::logic_error: "
1298 catch (std::exception& e) {
1299 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1300 (
true, std::runtime_error,
"At end of allocateIndices, "
1301 "checkInternalState threw std::exception: "
1305 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1306 (
true, std::runtime_error,
"At end of allocateIndices, "
1307 "checkInternalState threw an exception "
1308 "not a subclass of std::exception.");
1312 std::ostringstream os;
1313 os << *prefix <<
"Done" << endl;
1314 std::cerr << os.str();
1318 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1320 local_inds_dualv_type::t_host::const_type
1325 return typename local_inds_dualv_type::t_host::const_type ();
1332 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1334 local_inds_dualv_type::t_host
1339 return typename local_inds_dualv_type::t_host ();
1346 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1348 global_inds_dualv_type::t_host::const_type
1352 if (rowinfo.allocSize == 0 ||
gblInds_wdv.extent(0) == 0)
1353 return typename global_inds_dualv_type::t_host::const_type ();
1355 return gblInds_wdv.getHostSubview(rowinfo.offset1D,
1360 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1362 local_inds_dualv_type::t_dev::const_type
1367 return typename local_inds_dualv_type::t_dev::const_type ();
1374 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1376 global_inds_dualv_type::t_dev::const_type
1380 if (rowinfo.allocSize == 0 ||
gblInds_wdv.extent(0) == 0)
1381 return typename global_inds_dualv_type::t_dev::const_type ();
1383 return gblInds_wdv.getDeviceSubview(rowinfo.offset1D,
1389 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1394 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1396 if (this->
rowMap_.is_null () || ! this->rowMap_->isNodeLocalElement (myRow)) {
1397 ret.localRow = STINV;
1400 ret.offset1D = STINV;
1404 ret.localRow =
static_cast<size_t> (myRow);
1405 if (this->indicesAreAllocated ()) {
1408 if (rowPtrsUnpacked_host.extent (0) == 0) {
1413 ret.offset1D = rowPtrsUnpacked_host(myRow);
1414 ret.allocSize = rowPtrsUnpacked_host(myRow+1) - rowPtrsUnpacked_host(myRow);
1429 ret.offset1D = STINV;
1436 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1441 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1443 if (this->
rowMap_.is_null ()) {
1444 ret.localRow = STINV;
1447 ret.offset1D = STINV;
1450 const LocalOrdinal myRow = this->
rowMap_->getLocalElement (gblRow);
1451 if (myRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid ()) {
1452 ret.localRow = STINV;
1455 ret.offset1D = STINV;
1459 ret.localRow =
static_cast<size_t> (myRow);
1460 if (this->indicesAreAllocated ()) {
1465 if (rowPtrsUnpacked_host.extent (0) == 0) {
1470 ret.offset1D = rowPtrsUnpacked_host(myRow);
1471 ret.allocSize = rowPtrsUnpacked_host(myRow+1) - rowPtrsUnpacked_host(myRow);
1486 ret.offset1D = STINV;
1493 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1498 using Teuchos::OrdinalTraits;
1499 typedef LocalOrdinal LO;
1500 typedef GlobalOrdinal GO;
1506 static_assert (
sizeof (GlobalOrdinal) >=
sizeof (LocalOrdinal),
1507 "Tpetra::CrsGraph: sizeof(GlobalOrdinal) must be >= sizeof(LocalOrdinal).");
1510 static_assert (
sizeof (size_t) >=
sizeof (LocalOrdinal),
1511 "Tpetra::CrsGraph: sizeof(size_t) must be >= sizeof(LocalOrdinal).");
1512 static_assert (
sizeof(GST) >=
sizeof(size_t),
1513 "Tpetra::CrsGraph: sizeof(Tpetra::global_size_t) must be >= sizeof(size_t).");
1521 const char msg[] =
"Tpetra::CrsGraph: Object cannot be created with the "
1522 "given template arguments: size assumptions are not valid.";
1523 TEUCHOS_TEST_FOR_EXCEPTION(
1524 static_cast<size_t> (Teuchos::OrdinalTraits<LO>::max ()) > Teuchos::OrdinalTraits<size_t>::max (),
1525 std::runtime_error, msg);
1526 TEUCHOS_TEST_FOR_EXCEPTION(
1527 static_cast<GST
> (Teuchos::OrdinalTraits<LO>::max ()) >
static_cast<GST
> (Teuchos::OrdinalTraits<GO>::max ()),
1528 std::runtime_error, msg);
1529 TEUCHOS_TEST_FOR_EXCEPTION(
1530 static_cast<size_t> (Teuchos::OrdinalTraits<GO>::max ()) > Teuchos::OrdinalTraits<GST>::max(),
1531 std::runtime_error, msg);
1532 TEUCHOS_TEST_FOR_EXCEPTION(
1533 Teuchos::OrdinalTraits<size_t>::max () > Teuchos::OrdinalTraits<GST>::max (),
1534 std::runtime_error, msg);
1538 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1542 const SLocalGlobalViews &newInds,
1543 const ELocalGlobal lg,
1544 const ELocalGlobal I)
1546 using Teuchos::ArrayView;
1547 typedef LocalOrdinal LO;
1548 typedef GlobalOrdinal GO;
1549 const char tfecfFuncName[] =
"insertIndices: ";
1551 size_t oldNumEnt = 0;
1553 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1554 (lg != GlobalIndices && lg != LocalIndices, std::invalid_argument,
1555 "lg must be either GlobalIndices or LocalIndices.");
1559 size_t numNewInds = 0;
1560 if (lg == GlobalIndices) {
1561 ArrayView<const GO> new_ginds = newInds.ginds;
1562 numNewInds = new_ginds.size();
1563 if (I == GlobalIndices) {
1564 auto gind_view =
gblInds_wdv.getHostView(Access::ReadWrite);
1566 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1567 (
static_cast<size_t> (gind_view.size ()) <
1568 rowinfo.numEntries + numNewInds, std::logic_error,
1569 "gind_view.size() = " << gind_view.size ()
1570 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1571 <<
") + numNewInds (= " << numNewInds <<
").");
1573 GO*
const gblColInds_out = gind_view.data () + rowinfo.offset1D
1574 + rowinfo.numEntries;
1575 for (
size_t k = 0; k < numNewInds; ++k) {
1576 gblColInds_out[k] = new_ginds[k];
1579 else if (I == LocalIndices) {
1582 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1583 (
static_cast<size_t> (lind_view.size ()) <
1584 rowinfo.numEntries + numNewInds, std::logic_error,
1585 "lind_view.size() = " << lind_view.size ()
1586 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1587 <<
") + numNewInds (= " << numNewInds <<
").");
1589 LO*
const lclColInds_out = lind_view.data () + rowinfo.offset1D
1590 + rowinfo.numEntries;
1591 for (
size_t k = 0; k < numNewInds; ++k) {
1592 lclColInds_out[k] =
colMap_->getLocalElement (new_ginds[k]);
1596 else if (lg == LocalIndices) {
1597 ArrayView<const LO> new_linds = newInds.linds;
1598 numNewInds = new_linds.size();
1599 if (I == LocalIndices) {
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] = new_linds[k];
1615 else if (I == GlobalIndices) {
1616 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1617 (
true, std::logic_error,
"The case where the input indices are local "
1618 "and the indices to write are global (lg=LocalIndices, I="
1619 "GlobalIndices) is not implemented, because it does not make sense."
1620 << std::endl <<
"If you have correct local column indices, that "
1621 "means the graph has a column Map. In that case, you should be "
1622 "storing local indices.");
1626 rowinfo.numEntries += numNewInds;
1631 const size_t chkNewNumEnt =
1633 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1634 (chkNewNumEnt != oldNumEnt + numNewInds, std::logic_error,
1635 "chkNewNumEnt = " << chkNewNumEnt
1636 <<
" != oldNumEnt (= " << oldNumEnt
1637 <<
") + numNewInds (= " << numNewInds <<
").");
1643 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1647 const GlobalOrdinal inputGblColInds[],
1648 const size_t numInputInds)
1651 inputGblColInds, numInputInds);
1654 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1658 const GlobalOrdinal inputGblColInds[],
1659 const size_t numInputInds,
1660 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
1664 using Kokkos::subview;
1665 using Kokkos::MemoryUnmanaged;
1666 using Teuchos::ArrayView;
1667 using LO = LocalOrdinal;
1668 using GO = GlobalOrdinal;
1669 const char tfecfFuncName[] =
"insertGlobalIndicesImpl: ";
1670 const LO lclRow =
static_cast<LO
> (rowInfo.localRow);
1672 auto numEntries = rowInfo.numEntries;
1673 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1674 inp_view_type inputInds(inputGblColInds, numInputInds);
1677 auto gblIndsHostView = this->
gblInds_wdv.getHostView(Access::ReadWrite);
1680 numEntries, inputInds, fun);
1683 const bool insertFailed =
1684 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1686 constexpr size_t ONE (1);
1687 const int myRank = this->
getComm()->getRank();
1688 std::ostringstream os;
1690 os <<
"Proc " << myRank <<
": Not enough capacity to insert "
1692 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1693 <<
" into local row " << lclRow <<
", which currently has "
1694 << rowInfo.numEntries
1695 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1696 <<
" and total allocation size " << rowInfo.allocSize
1698 const size_t maxNumToPrint =
1700 ArrayView<const GO> inputGblColIndsView(inputGblColInds,
1702 verbosePrintArray(os, inputGblColIndsView,
"Input global "
1703 "column indices", maxNumToPrint);
1706 ArrayView<const GO> curGblColIndsView(curGblColInds.data(),
1707 rowInfo.numEntries);
1708 verbosePrintArray(os, curGblColIndsView,
"Current global "
1709 "column indices", maxNumToPrint);
1710 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1711 (
true, std::runtime_error, os.str());
1721 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1725 const Teuchos::ArrayView<const LocalOrdinal>& indices,
1726 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
1728 using Kokkos::MemoryUnmanaged;
1729 using Kokkos::subview;
1731 using LO = LocalOrdinal;
1732 const char tfecfFuncName[] =
"insertLocallIndicesImpl: ";
1734 const RowInfo rowInfo = this->getRowInfo(myRow);
1736 size_t numNewInds = 0;
1737 size_t newNumEntries = 0;
1739 auto numEntries = rowInfo.numEntries;
1741 using inp_view_type = View<const LO*, Kokkos::HostSpace, MemoryUnmanaged>;
1742 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1743 size_t numInserted = 0;
1745 auto lclInds = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1747 numEntries, inputInds, fun);
1750 const bool insertFailed =
1751 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1753 constexpr size_t ONE (1);
1754 const size_t numInputInds(indices.size());
1755 const int myRank = this->getComm()->getRank();
1756 std::ostringstream os;
1757 os <<
"On MPI Process " << myRank <<
": Not enough capacity to "
1758 "insert " << numInputInds
1759 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1760 <<
" into local row " << myRow <<
", which currently has "
1761 << rowInfo.numEntries
1762 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1763 <<
" and total allocation size " << rowInfo.allocSize <<
".";
1764 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1765 (
true, std::runtime_error, os.str());
1767 numNewInds = numInserted;
1768 newNumEntries = rowInfo.numEntries + numNewInds;
1770 this->k_numRowEntries_(myRow) += numNewInds;
1771 this->setLocallyModified ();
1774 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow (myRow);
1775 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1776 (chkNewNumEntries != newNumEntries, std::logic_error,
1777 "getNumEntriesInLocalRow(" << myRow <<
") = " << chkNewNumEntries
1778 <<
" != newNumEntries = " << newNumEntries
1779 <<
". Please report this bug to the Tpetra developers.");
1783 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1787 const Teuchos::ArrayView<const GlobalOrdinal>& indices,
1788 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
const
1790 using GO = GlobalOrdinal;
1792 using Kokkos::MemoryUnmanaged;
1793 auto invalidCount = Teuchos::OrdinalTraits<size_t>::invalid();
1795 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1796 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1798 size_t numFound = 0;
1799 LocalOrdinal lclRow = rowInfo.localRow;
1803 return invalidCount;
1804 const auto& colMap = *(this->
colMap_);
1805 auto map = [&](GO
const gblInd){
return colMap.getLocalElement(gblInd);};
1814 gblInds_wdv.getHostView(Access::ReadOnly), inputInds, fun);
1820 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1827 const size_t origNumEnt = rowInfo.numEntries;
1828 if (origNumEnt != Tpetra::Details::OrdinalTraits<size_t>::invalid () &&
1832 LocalOrdinal*
const lclColIndsRaw = lclColInds.data ();
1834 std::sort (lclColIndsRaw, lclColIndsRaw + origNumEnt);
1838 LocalOrdinal*
const beg = lclColIndsRaw;
1839 LocalOrdinal*
const end = beg + rowInfo.numEntries;
1840 LocalOrdinal*
const newend = std::unique (beg, end);
1841 const size_t newNumEnt = newend - beg;
1845 return origNumEnt - newNumEnt;
1848 return static_cast<size_t> (0);
1852 return static_cast<size_t> (0);
1857 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1861 const Teuchos::RCP<const map_type>& rangeMap)
1875 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1880 const auto INV = Teuchos::OrdinalTraits<global_size_t>::invalid();
1882 globalNumEntries_ = INV;
1883 globalMaxNumRowEntries_ = INV;
1884 haveGlobalConstants_ =
false;
1888 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1895 const char tfecfFuncName[] =
"checkInternalState: ";
1896 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1898 std::unique_ptr<std::string> prefix;
1900 prefix = this->createPrefix(
"CrsGraph",
"checkInternalState");
1901 std::ostringstream os;
1902 os << *prefix <<
"Start" << endl;
1903 std::cerr << os.str();
1906 const global_size_t GSTI = Teuchos::OrdinalTraits<global_size_t>::invalid ();
1912 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1913 (this->
rowMap_.is_null (), std::logic_error,
1914 "Row Map is null." << suffix);
1917 const LocalOrdinal lclNumRows =
1920 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1922 "Graph cannot be both fill active and fill complete." << suffix);
1923 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1926 this->rangeMap_.is_null () ||
1927 this->domainMap_.is_null ()),
1929 "Graph is full complete, but at least one of {column, range, domain} "
1930 "Map is null." << suffix);
1931 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1933 std::logic_error,
"Storage is optimized, but indices are not "
1934 "allocated, not even trivially." << suffix);
1936 size_t nodeAllocSize = 0;
1940 catch (std::logic_error& e) {
1941 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1942 (
true, std::runtime_error,
"getLocalAllocationSize threw "
1943 "std::logic_error: " << e.what ());
1945 catch (std::exception& e) {
1946 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1947 (
true, std::runtime_error,
"getLocalAllocationSize threw an "
1948 "std::exception: " << e.what ());
1951 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1952 (
true, std::runtime_error,
"getLocalAllocationSize threw an exception "
1953 "not a subclass of std::exception.");
1956 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1959 std::logic_error,
"Storage is optimized, but "
1960 "this->getLocalAllocationSize() = " << nodeAllocSize
1963 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1967 std::logic_error,
"Graph claims not to have global constants, but "
1968 "some of the global constants are not marked as invalid." << suffix);
1969 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1973 std::logic_error,
"Graph claims to have global constants, but "
1974 "some of them are marked as invalid." << suffix);
1975 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1979 std::logic_error,
"Graph claims to have global constants, and "
1980 "all of the values of the global constants are valid, but "
1981 "some of the local constants are greater than "
1982 "their corresponding global constants." << suffix);
1983 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1984 (this->indicesAreAllocated () &&
1987 std::logic_error,
"The graph claims that its indices are allocated, but "
1988 "either numAllocForAllRows_ (= " << this->numAllocForAllRows_ <<
") is "
1989 "nonzero, or k_numAllocPerRow_ has nonzero dimension. In other words, "
1990 "the graph is supposed to release its \"allocation specifications\" "
1991 "when it allocates its indices." << suffix);
1994 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1995 (rowPtrsUnpacked_host.extent(0) != rowPtrsUnpacked_dev.extent(0),
1996 std::logic_error,
"The host and device views of k_rowPtrs_ have "
1997 "different sizes; rowPtrsUnpacked_host_ has size "
1998 << rowPtrsUnpacked_host.extent(0)
1999 <<
", but rowPtrsUnpacked_dev_ has size "
2000 << rowPtrsUnpacked_dev.extent(0)
2003 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2004 (
size_t(rowPtrsUnpacked_host.extent(0)) !=
size_t(lclNumRows + 1),
2005 std::logic_error,
"The graph is globally indexed and "
2006 "k_rowPtrs has nonzero size " << rowPtrsUnpacked_host.extent(0)
2007 <<
", but that size does not equal lclNumRows+1 = "
2008 << (lclNumRows+1) <<
"." << suffix);
2009 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2010 (rowPtrsUnpacked_host(lclNumRows) !=
size_t(
gblInds_wdv.extent(0)),
2011 std::logic_error,
"The graph is globally indexed and "
2012 "k_rowPtrs_ has nonzero size " << rowPtrsUnpacked_host.extent(0)
2013 <<
", but k_rowPtrs_(lclNumRows=" << lclNumRows <<
")="
2014 << rowPtrsUnpacked_host(lclNumRows)
2015 <<
" != gblInds_wdv.extent(0)="
2018 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2020 rowPtrsUnpacked_host.extent (0) != 0 &&
2021 (
static_cast<size_t> (rowPtrsUnpacked_host.extent (0)) !=
2022 static_cast<size_t> (lclNumRows + 1) ||
2023 rowPtrsUnpacked_host(lclNumRows) !=
2025 std::logic_error,
"If k_rowPtrs_ has nonzero size and "
2026 "the graph is locally indexed, then "
2027 "k_rowPtrs_ must have N+1 rows, and "
2028 "k_rowPtrs_(N) must equal lclIndsUnpacked_wdv.extent(0)." << suffix);
2030 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2031 (this->indicesAreAllocated () &&
2032 nodeAllocSize > 0 &&
2034 this->gblInds_wdv.extent (0) == 0,
2035 std::logic_error,
"Graph is allocated nontrivially, but "
2036 "but 1-D allocations are not present." << suffix);
2038 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2039 (! this->indicesAreAllocated () &&
2040 ((rowPtrsUnpacked_host.extent (0) != 0 ||
2041 this->k_numRowEntries_.extent (0) != 0) ||
2042 this->lclIndsUnpacked_wdv.extent (0) != 0 ||
2043 this->gblInds_wdv.extent (0) != 0),
2044 std::logic_error,
"If indices are not allocated, "
2045 "then none of the buffers should be." << suffix);
2049 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2050 ((this->indicesAreLocal_ || this->indicesAreGlobal_) &&
2051 ! this->indicesAreAllocated_,
2052 std::logic_error,
"Indices may be local or global only if they are "
2053 "allocated." << suffix);
2054 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2055 (this->indicesAreLocal_ && this->indicesAreGlobal_,
2056 std::logic_error,
"Indices may not be both local and global." << suffix);
2057 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2059 std::logic_error,
"Indices are local, but "
2060 "gblInds_wdv.extent(0) (= " <<
gblInds_wdv.extent (0)
2061 <<
") != 0. In other words, if indices are local, then "
2062 "allocations of global indices should not be present."
2064 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2066 std::logic_error,
"Indices are global, but "
2068 <<
") != 0. In other words, if indices are global, "
2069 "then allocations for local indices should not be present."
2071 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2072 (indicesAreLocal_ && nodeAllocSize > 0 &&
2074 std::logic_error,
"Indices are local and "
2075 "getLocalAllocationSize() = " << nodeAllocSize <<
" > 0, but "
2076 "lclIndsUnpacked_wdv.extent(0) = 0 and getLocalNumRows() = "
2078 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2079 (indicesAreGlobal_ && nodeAllocSize > 0 &&
2081 std::logic_error,
"Indices are global and "
2082 "getLocalAllocationSize() = " << nodeAllocSize <<
" > 0, but "
2083 "gblInds_wdv.extent(0) = 0 and getLocalNumRows() = "
2086 if (this->indicesAreAllocated () &&
2087 rowPtrsUnpacked_host.extent (0) != 0) {
2088 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2089 (
static_cast<size_t> (rowPtrsUnpacked_host.extent (0)) !=
2090 this->getLocalNumRows () + 1,
2091 std::logic_error,
"Indices are allocated and "
2092 "k_rowPtrs_ has nonzero length, but rowPtrsUnpacked_host_.extent(0) = "
2093 << rowPtrsUnpacked_host.extent (0) <<
" != getLocalNumRows()+1 = "
2094 << (this->getLocalNumRows () + 1) <<
"." << suffix);
2095 const size_t actualNumAllocated =
2097 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2100 std::logic_error,
"Graph is locally indexed, indices are "
2101 "are allocated, and k_rowPtrs_ has nonzero length, but "
2102 "lclIndsUnpacked_wdv.extent(0) = " << this->lclIndsUnpacked_wdv.extent (0)
2103 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2104 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2106 static_cast<size_t> (this->
gblInds_wdv.extent (0)) != actualNumAllocated,
2107 std::logic_error,
"Graph is globally indexed, indices "
2108 "are allocated, and k_rowPtrs_ has nonzero length, but "
2109 "gblInds_wdv.extent(0) = " << this->gblInds_wdv.extent (0)
2110 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2114 std::ostringstream os;
2115 os << *prefix <<
"Done" << endl;
2116 std::cerr << os.str();
2122 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2128 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2129 return Teuchos::OrdinalTraits<size_t>::invalid ();
2132 return rowInfo.numEntries;
2137 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2143 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2144 return Teuchos::OrdinalTraits<size_t>::invalid ();
2147 return rowInfo.numEntries;
2152 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2158 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2159 return Teuchos::OrdinalTraits<size_t>::invalid ();
2162 return rowInfo.allocSize;
2167 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2173 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2174 return Teuchos::OrdinalTraits<size_t>::invalid ();
2177 return rowInfo.allocSize;
2182 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2183 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_host_view_type
2190 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2191 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_device_view_type
2199 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2200 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::local_inds_host_view_type
2207 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2215 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2219 nonconst_local_inds_host_view_type & indices,
2220 size_t& numEntries)
const
2222 using Teuchos::ArrayView;
2223 const char tfecfFuncName[] =
"getLocalRowCopy: ";
2225 TEUCHOS_TEST_FOR_EXCEPTION(
2227 "Tpetra::CrsGraph::getLocalRowCopy: The graph is globally indexed and "
2228 "does not have a column Map yet. That means we don't have local indices "
2229 "for columns yet, so it doesn't make sense to call this method. If the "
2230 "graph doesn't have a column Map yet, you should call fillComplete on "
2237 const size_t theNumEntries = rowinfo.numEntries;
2238 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2239 (
static_cast<size_t> (indices.size ()) < theNumEntries,std::runtime_error,
2240 "Specified storage (size==" << indices.size () <<
") does not suffice "
2241 "to hold all " << theNumEntries <<
" entry/ies for this row.");
2242 numEntries = theNumEntries;
2244 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
2247 for (
size_t j = 0; j < theNumEntries; ++j) {
2248 indices[j] = lclInds(j);
2253 for (
size_t j = 0; j < theNumEntries; ++j) {
2254 indices[j] =
colMap_->getLocalElement (gblInds(j));
2261 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2265 nonconst_global_inds_host_view_type &indices,
2266 size_t& numEntries)
const
2268 using Teuchos::ArrayView;
2269 const char tfecfFuncName[] =
"getGlobalRowCopy: ";
2274 const size_t theNumEntries = rowinfo.numEntries;
2275 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2276 static_cast<size_t> (indices.size ()) < theNumEntries, std::runtime_error,
2277 "Specified storage (size==" << indices.size () <<
") does not suffice "
2278 "to hold all " << theNumEntries <<
" entry/ies for this row.");
2279 numEntries = theNumEntries;
2281 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
2284 for (
size_t j = 0; j < theNumEntries; ++j) {
2285 indices[j] =
colMap_->getGlobalElement (lclInds(j));
2290 for (
size_t j = 0; j < theNumEntries; ++j) {
2291 indices[j] = gblInds(j);
2298 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2302 const LocalOrdinal localRow,
2303 local_inds_host_view_type &indices)
const
2305 const char tfecfFuncName[] =
"getLocalRowView: ";
2307 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2309 "currently stored as global indices, so we cannot return a view with "
2310 "local column indices, whether or not the graph has a column Map. If "
2311 "the graph _does_ have a column Map, use getLocalRowCopy() instead.");
2314 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
2315 rowInfo.numEntries > 0) {
2323 indices = local_inds_host_view_type();
2327 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2328 (
static_cast<size_t> (indices.size ()) !=
2330 "= " << indices.extent(0) <<
" != getNumEntriesInLocalRow(localRow=" <<
2332 ". Please report this bug to the Tpetra developers.");
2337 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2341 const GlobalOrdinal globalRow,
2342 global_inds_host_view_type &indices)
const
2344 const char tfecfFuncName[] =
"getGlobalRowView: ";
2346 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2348 "currently stored as local indices, so we cannot return a view with "
2349 "global column indices. Use getGlobalRowCopy() instead.");
2354 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
2355 rowInfo.numEntries > 0) {
2356 indices =
gblInds_wdv.getHostSubview(rowInfo.offset1D,
2361 indices =
typename global_inds_dualv_type::t_host::const_type();
2364 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2365 (
static_cast<size_t> (indices.size ()) !=
2367 std::logic_error,
"indices.size() = " << indices.extent(0)
2368 <<
" != getNumEntriesInGlobalRow(globalRow=" << globalRow <<
") = "
2370 <<
". Please report this bug to the Tpetra developers.");
2375 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2379 const Teuchos::ArrayView<const LocalOrdinal>& indices)
2381 const char tfecfFuncName[] =
"insertLocalIndices: ";
2383 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2384 (!
isFillActive (), std::runtime_error,
"Fill must be active.");
2385 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2387 "Graph indices are global; use insertGlobalIndices().");
2388 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2390 "Cannot insert local indices without a column Map.");
2391 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2392 (!
rowMap_->isNodeLocalElement (localRow), std::runtime_error,
2393 "Local row index " << localRow <<
" is not in the row Map "
2394 "on the calling process.");
2395 if (! indicesAreAllocated ()) {
2396 allocateIndices (LocalIndices, verbose_);
2405 using Teuchos::Array;
2406 using Teuchos::toString;
2408 typedef typename Teuchos::ArrayView<const LocalOrdinal>::size_type size_type;
2411 Array<LocalOrdinal> badColInds;
2412 bool allInColMap =
true;
2413 for (size_type k = 0; k < indices.size (); ++k) {
2415 allInColMap =
false;
2416 badColInds.push_back (indices[k]);
2419 if (! allInColMap) {
2420 std::ostringstream os;
2421 os <<
"Tpetra::CrsGraph::insertLocalIndices: You attempted to insert "
2422 "entries in owned row " << localRow <<
", at the following column "
2423 "indices: " << toString (indices) <<
"." << endl;
2424 os <<
"Of those, the following indices are not in the column Map on "
2425 "this process: " << toString (badColInds) <<
"." << endl <<
"Since "
2426 "the graph has a column Map already, it is invalid to insert entries "
2427 "at those locations.";
2428 TEUCHOS_TEST_FOR_EXCEPTION(! allInColMap, std::invalid_argument, os.str ());
2433 insertLocalIndicesImpl (localRow, indices);
2436 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2438 "At the end of insertLocalIndices, ! indicesAreAllocated() || "
2439 "! isLocallyIndexed() is true. Please report this bug to the "
2440 "Tpetra developers.");
2444 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2448 const LocalOrdinal numEnt,
2449 const LocalOrdinal inds[])
2451 Teuchos::ArrayView<const LocalOrdinal> indsT (inds, numEnt);
2456 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2460 const LocalOrdinal numInputInds,
2461 const GlobalOrdinal inputGblColInds[])
2463 typedef LocalOrdinal LO;
2464 const char tfecfFuncName[] =
"insertGlobalIndices: ";
2466 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2468 "graph indices are local; use insertLocalIndices().");
2473 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2475 "You are not allowed to call this method if fill is not active. "
2476 "If fillComplete has been called, you must first call resumeFill "
2477 "before you may insert indices.");
2478 if (! indicesAreAllocated ()) {
2479 allocateIndices (GlobalIndices, verbose_);
2481 const LO lclRow = this->
rowMap_->getLocalElement (gblRow);
2482 if (lclRow != Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
2491 std::vector<GlobalOrdinal> badColInds;
2492 bool allInColMap =
true;
2493 for (LO k = 0; k < numInputInds; ++k) {
2495 allInColMap =
false;
2496 badColInds.push_back (inputGblColInds[k]);
2499 if (! allInColMap) {
2500 std::ostringstream os;
2501 os <<
"You attempted to insert entries in owned row " << gblRow
2502 <<
", at the following column indices: [";
2503 for (LO k = 0; k < numInputInds; ++k) {
2504 os << inputGblColInds[k];
2505 if (k +
static_cast<LO
> (1) < numInputInds) {
2509 os <<
"]." << endl <<
"Of those, the following indices are not in "
2510 "the column Map on this process: [";
2511 for (
size_t k = 0; k < badColInds.size (); ++k) {
2512 os << badColInds[k];
2513 if (k +
size_t (1) < badColInds.size ()) {
2517 os <<
"]." << endl <<
"Since the matrix has a column Map already, "
2518 "it is invalid to insert entries at those locations.";
2519 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2520 (
true, std::invalid_argument, os.str ());
2533 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2537 const Teuchos::ArrayView<const GlobalOrdinal>& inputGblColInds)
2540 inputGblColInds.getRawPtr ());
2544 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2548 const GlobalOrdinal gblColInds[],
2549 const LocalOrdinal numGblColInds)
2551 typedef LocalOrdinal LO;
2552 typedef GlobalOrdinal GO;
2553 const char tfecfFuncName[] =
"insertGlobalIndicesFiltered: ";
2555 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2557 "Graph indices are local; use insertLocalIndices().");
2562 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2564 "You are not allowed to call this method if fill is not active. "
2565 "If fillComplete has been called, you must first call resumeFill "
2566 "before you may insert indices.");
2567 if (! indicesAreAllocated ()) {
2568 allocateIndices (GlobalIndices, verbose_);
2571 Teuchos::ArrayView<const GO> gblColInds_av (gblColInds, numGblColInds);
2577 while (curOffset < numGblColInds) {
2581 LO endOffset = curOffset;
2582 for ( ; endOffset < numGblColInds; ++endOffset) {
2584 if (lclCol == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
2591 const LO numIndInSeq = (endOffset - curOffset);
2592 if (numIndInSeq != 0) {
2599 curOffset = endOffset + 1;
2604 gblColInds_av.size ());
2608 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2612 const GlobalOrdinal gblColInds[],
2613 const LocalOrdinal numGblColInds)
2618 std::vector<GlobalOrdinal>& nonlocalRow = this->
nonlocals_[gblRow];
2619 for (LocalOrdinal k = 0; k < numGblColInds; ++k) {
2623 nonlocalRow.push_back (gblColInds[k]);
2627 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2632 const char tfecfFuncName[] =
"removeLocalIndices: ";
2633 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2634 !
isFillActive (), std::runtime_error,
"requires that fill is active.");
2635 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2637 "cannot remove indices after optimizeStorage() has been called.");
2638 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2640 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2641 !
rowMap_->isNodeLocalElement (lrow), std::runtime_error,
2642 "Local row " << lrow <<
" is not in the row Map on the calling process.");
2643 if (! indicesAreAllocated ()) {
2644 allocateIndices (LocalIndices, verbose_);
2652 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2654 ! indicesAreAllocated () ||
2656 "Violated stated post-conditions. Please contact Tpetra team.");
2661 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2664 setAllIndices (
const typename local_graph_device_type::row_map_type& rowPointers,
2665 const typename local_graph_device_type::entries_type::non_const_type& columnIndices)
2668 ProfilingRegion region (
"Tpetra::CrsGraph::setAllIndices");
2669 const char tfecfFuncName[] =
"setAllIndices: ";
2670 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2672 "The graph must have a column Map before you may call this method.");
2675 LocalOrdinal rowPtrLen = rowPointers.size();
2676 if(numLocalRows == 0) {
2677 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2678 rowPtrLen != 0 && rowPtrLen != 1,
2679 std::runtime_error,
"Have 0 local rows, but rowPointers.size() is neither 0 nor 1.");
2682 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2683 rowPtrLen != numLocalRows + 1,
2684 std::runtime_error,
"rowPointers.size() = " << rowPtrLen <<
2685 " != this->getLocalNumRows()+1 = " << (numLocalRows + 1) <<
".");
2690 using exec_space =
typename local_graph_device_type::execution_space;
2691 int columnsOutOfBounds = 0;
2693 Kokkos::parallel_reduce(Kokkos::RangePolicy<exec_space>(0, columnIndices.extent(0)),
2694 KOKKOS_LAMBDA (
const LocalOrdinal i,
int& lOutOfBounds)
2696 if(columnIndices(i) < 0 || columnIndices(i) >= numLocalCols)
2698 }, columnsOutOfBounds);
2699 int globalColsOutOfBounds= 0;
2701 Teuchos::reduceAll<int, int> (*comm, Teuchos::REDUCE_MAX, columnsOutOfBounds,
2702 Teuchos::outArg (globalColsOutOfBounds));
2703 if (globalColsOutOfBounds)
2705 std::string message;
2706 if (columnsOutOfBounds)
2709 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not all within range [0, getLocalNumCols())!\n";
2712 throw std::invalid_argument(
"CrsGraph::setAllIndices(): columnIndices are out of the valid range on at least one process.");
2719 using exec_space =
typename local_graph_device_type::execution_space;
2720 using size_type =
typename local_graph_device_type::size_type;
2721 Kokkos::parallel_reduce(Kokkos::RangePolicy<exec_space>(0, numLocalRows),
2722 KOKKOS_LAMBDA (
const LocalOrdinal i,
int& lNotSorted)
2724 size_type rowBegin = rowPointers(i);
2725 size_type rowEnd = rowPointers(i + 1);
2726 for(size_type j = rowBegin + 1; j < rowEnd; j++)
2728 if(columnIndices(j - 1) > columnIndices(j))
2735 int globalNotSorted = 0;
2737 Teuchos::reduceAll<int, int> (*comm, Teuchos::REDUCE_MAX, notSorted,
2738 Teuchos::outArg (globalNotSorted));
2739 if (globalNotSorted)
2741 std::string message;
2745 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not sorted!\n";
2748 throw std::invalid_argument(
"CrsGraph::setAllIndices(): provided columnIndices are not sorted within rows on at least one process.");
2752 indicesAreAllocated_ =
true;
2753 indicesAreLocal_ =
true;
2758 setRowPtrs(rowPointers);
2760 set_need_sync_host_uvm_access();
2776 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2779 setAllIndices (
const Teuchos::ArrayRCP<size_t>& rowPointers,
2780 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices)
2783 typedef typename local_graph_device_type::row_map_type row_map_type;
2784 typedef typename row_map_type::array_layout layout_type;
2785 typedef typename row_map_type::non_const_value_type row_offset_type;
2786 typedef View<
size_t*, layout_type , Kokkos::HostSpace,
2787 Kokkos::MemoryUnmanaged> input_view_type;
2788 typedef typename row_map_type::non_const_type nc_row_map_type;
2790 const size_t size =
static_cast<size_t> (rowPointers.size ());
2791 constexpr bool same = std::is_same<size_t, row_offset_type>::value;
2792 input_view_type ptr_in (rowPointers.getRawPtr (), size);
2794 nc_row_map_type ptr_rot (
"Tpetra::CrsGraph::ptr", size);
2797#ifdef KOKKOS_ENABLE_CXX17
2798 if constexpr (same) {
2799 using lexecution_space =
typename device_type::execution_space;
2800 Kokkos::deep_copy (lexecution_space(),
2809 input_view_type ptr_decoy (rowPointers.getRawPtr (), size);
2812 Kokkos::Impl::if_c<same,
2814 input_view_type>::select (ptr_rot, ptr_decoy),
2820 constexpr bool inHostMemory =
2821 std::is_same<
typename row_map_type::memory_space,
2822 Kokkos::HostSpace>::value;
2833 View<size_t*, layout_type, device_type> ptr_st (
"Tpetra::CrsGraph::ptr", size);
2836 Kokkos::deep_copy (ptr_st, ptr_in);
2845 Kokkos::View<LocalOrdinal*, layout_type, device_type> k_ind =
2846 Kokkos::Compat::getKokkosViewDeepCopy<device_type> (columnIndices ());
2851 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2856 using Teuchos::Comm;
2857 using Teuchos::outArg;
2860 using Teuchos::REDUCE_MAX;
2861 using Teuchos::REDUCE_MIN;
2862 using Teuchos::reduceAll;
2864 using crs_graph_type = CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
2867 using size_type =
typename Teuchos::Array<GO>::size_type;
2868 const char tfecfFuncName[] =
"globalAssemble: ";
2870 std::unique_ptr<std::string> prefix;
2872 prefix = this->createPrefix(
"CrsGraph",
"globalAssemble");
2873 std::ostringstream os;
2874 os << *prefix <<
"Start" << endl;
2875 std::cerr << os.str();
2877 RCP<const Comm<int> > comm =
getComm ();
2879 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2880 (!
isFillActive (), std::runtime_error,
"Fill must be active before "
2881 "you may call this method.");
2883 const size_t myNumNonlocalRows = this->
nonlocals_.size ();
2890 const int iHaveNonlocalRows = (myNumNonlocalRows == 0) ? 0 : 1;
2891 int someoneHasNonlocalRows = 0;
2892 reduceAll<int, int> (*comm, REDUCE_MAX, iHaveNonlocalRows,
2893 outArg (someoneHasNonlocalRows));
2894 if (someoneHasNonlocalRows == 0) {
2896 std::ostringstream os;
2897 os << *prefix <<
"Done: No nonlocal rows" << endl;
2898 std::cerr << os.str();
2902 else if (verbose_) {
2903 std::ostringstream os;
2904 os << *prefix <<
"At least 1 process has nonlocal rows"
2906 std::cerr << os.str();
2919 RCP<const map_type> nonlocalRowMap;
2921 Teuchos::Array<size_t> numEntPerNonlocalRow (myNumNonlocalRows);
2923 Teuchos::Array<GO> myNonlocalGblRows (myNumNonlocalRows);
2924 size_type curPos = 0;
2925 for (
auto mapIter = this->
nonlocals_.begin ();
2926 mapIter != this->nonlocals_.end ();
2927 ++mapIter, ++curPos) {
2928 myNonlocalGblRows[curPos] = mapIter->first;
2929 std::vector<GO>& gblCols = mapIter->second;
2930 std::sort (gblCols.begin (), gblCols.end ());
2931 auto vecLast = std::unique (gblCols.begin (), gblCols.end ());
2932 gblCols.erase (vecLast, gblCols.end ());
2933 numEntPerNonlocalRow[curPos] = gblCols.size ();
2944 GO myMinNonlocalGblRow = std::numeric_limits<GO>::max ();
2946 auto iter = std::min_element (myNonlocalGblRows.begin (),
2947 myNonlocalGblRows.end ());
2948 if (iter != myNonlocalGblRows.end ()) {
2949 myMinNonlocalGblRow = *iter;
2952 GO gblMinNonlocalGblRow = 0;
2953 reduceAll<int, GO> (*comm, REDUCE_MIN, myMinNonlocalGblRow,
2954 outArg (gblMinNonlocalGblRow));
2955 const GO indexBase = gblMinNonlocalGblRow;
2956 const global_size_t INV = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2957 nonlocalRowMap = rcp (
new map_type (INV, myNonlocalGblRows (), indexBase, comm));
2961 std::ostringstream os;
2962 os << *prefix <<
"nonlocalRowMap->getIndexBase()="
2963 << nonlocalRowMap->getIndexBase() << endl;
2964 std::cerr << os.str();
2972 RCP<crs_graph_type> nonlocalGraph =
2975 size_type curPos = 0;
2976 for (
auto mapIter = this->
nonlocals_.begin ();
2977 mapIter != this->nonlocals_.end ();
2978 ++mapIter, ++curPos) {
2979 const GO gblRow = mapIter->first;
2980 std::vector<GO>& gblCols = mapIter->second;
2981 const LO numEnt =
static_cast<LO
> (numEntPerNonlocalRow[curPos]);
2982 nonlocalGraph->insertGlobalIndices (gblRow, numEnt, gblCols.data ());
2986 std::ostringstream os;
2987 os << *prefix <<
"Built nonlocal graph" << endl;
2988 std::cerr << os.str();
3000 const bool origRowMapIsOneToOne = origRowMap->isOneToOne ();
3002 if (origRowMapIsOneToOne) {
3004 std::ostringstream os;
3005 os << *prefix <<
"Original row Map is 1-to-1" << endl;
3006 std::cerr << os.str();
3008 export_type exportToOrig (nonlocalRowMap, origRowMap);
3014 std::ostringstream os;
3015 os << *prefix <<
"Original row Map is NOT 1-to-1" << endl;
3016 std::cerr << os.str();
3023 export_type exportToOneToOne (nonlocalRowMap, oneToOneRowMap);
3033 std::ostringstream os;
3034 os << *prefix <<
"Export nonlocal graph" << endl;
3035 std::cerr << os.str();
3041 nonlocalGraph = Teuchos::null;
3044 import_type importToOrig (oneToOneRowMap, origRowMap);
3046 std::ostringstream os;
3047 os << *prefix <<
"Import nonlocal graph" << endl;
3048 std::cerr << os.str();
3062 std::ostringstream os;
3063 os << *prefix <<
"Done" << endl;
3064 std::cerr << os.str();
3069 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3072 resumeFill (
const Teuchos::RCP<Teuchos::ParameterList>& params)
3074 clearGlobalConstants();
3079 fillComplete_ =
false;
3083 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3086 fillComplete (
const Teuchos::RCP<Teuchos::ParameterList>& params)
3098 Teuchos::RCP<const map_type> domMap = this->
getDomainMap ();
3099 if (domMap.is_null ()) {
3102 Teuchos::RCP<const map_type> ranMap = this->
getRangeMap ();
3103 if (ranMap.is_null ()) {
3110 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3113 fillComplete (
const Teuchos::RCP<const map_type>& domainMap,
3114 const Teuchos::RCP<const map_type>& rangeMap,
3115 const Teuchos::RCP<Teuchos::ParameterList>& params)
3118 const char tfecfFuncName[] =
"fillComplete: ";
3119 const bool verbose = verbose_;
3121 std::unique_ptr<std::string> prefix;
3123 prefix = this->createPrefix(
"CrsGraph",
"fillComplete");
3124 std::ostringstream os;
3125 os << *prefix <<
"Start" << endl;
3126 std::cerr << os.str();
3129 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3131 "Graph fill state must be active (isFillActive() "
3132 "must be true) before calling fillComplete().");
3134 const int numProcs =
getComm ()->getSize ();
3142 if (! params.is_null ()) {
3143 if (params->isParameter (
"sort column map ghost gids")) {
3145 params->get<
bool> (
"sort column map ghost gids",
3148 else if (params->isParameter (
"Sort column Map ghost GIDs")) {
3150 params->get<
bool> (
"Sort column Map ghost GIDs",
3157 bool assertNoNonlocalInserts =
false;
3158 if (! params.is_null ()) {
3159 assertNoNonlocalInserts =
3160 params->get<
bool> (
"No Nonlocal Changes", assertNoNonlocalInserts);
3166 if (! indicesAreAllocated ()) {
3169 allocateIndices (LocalIndices, verbose);
3172 allocateIndices (GlobalIndices, verbose);
3180 const bool mayNeedGlobalAssemble = ! assertNoNonlocalInserts && numProcs > 1;
3181 if (mayNeedGlobalAssemble) {
3187 const size_t numNonlocals =
nonlocals_.size();
3189 std::ostringstream os;
3190 os << *prefix <<
"Do not need to call globalAssemble; "
3191 "assertNoNonlocalInserts="
3192 << (assertNoNonlocalInserts ?
"true" :
"false")
3193 <<
"numProcs=" << numProcs
3194 <<
", nonlocals_.size()=" << numNonlocals << endl;
3195 std::cerr << os.str();
3197 const int lclNeededGlobalAssemble =
3198 (numProcs > 1 && numNonlocals != 0) ? 1 : 0;
3199 if (lclNeededGlobalAssemble != 0 && verbose) {
3200 std::ostringstream os;
3202 Details::Impl::verbosePrintMap(
3205 std::cerr << os.str() << endl;
3209 auto map = this->
getMap();
3210 auto comm = map.is_null() ? Teuchos::null : map->getComm();
3211 int gblNeededGlobalAssemble = lclNeededGlobalAssemble;
3212 if (! comm.is_null()) {
3213 using Teuchos::REDUCE_MAX;
3214 using Teuchos::reduceAll;
3215 reduceAll(*comm, REDUCE_MAX, lclNeededGlobalAssemble,
3216 Teuchos::outArg(gblNeededGlobalAssemble));
3218 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3219 (gblNeededGlobalAssemble != 0, std::runtime_error,
3220 "nonlocals_.size()=" << numNonlocals <<
" != 0 on at "
3221 "least one process in the CrsGraph's communicator. This "
3222 "means either that you incorrectly set the "
3223 "\"No Nonlocal Changes\" fillComplete parameter to true, "
3224 "or that you inserted invalid entries. "
3225 "Rerun with the environment variable TPETRA_VERBOSE="
3226 "CrsGraph set to see the entries of nonlocals_ on every "
3227 "MPI process (WARNING: lots of output).");
3230 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3231 (lclNeededGlobalAssemble != 0, std::runtime_error,
3232 "nonlocals_.size()=" << numNonlocals <<
" != 0 on the "
3233 "calling process. This means either that you incorrectly "
3234 "set the \"No Nonlocal Changes\" fillComplete parameter "
3235 "to true, or that you inserted invalid entries. "
3236 "Rerun with the environment "
3237 "variable TPETRA_VERBOSE=CrsGraph set to see the entries "
3238 "of nonlocals_ on every MPI process (WARNING: lots of "
3251 Teuchos::Array<int> remotePIDs (0);
3252 const bool mustBuildColMap = ! this->
hasColMap ();
3253 if (mustBuildColMap) {
3259 const std::pair<size_t, std::string> makeIndicesLocalResult =
3265 using Teuchos::REDUCE_MIN;
3266 using Teuchos::reduceAll;
3267 using Teuchos::outArg;
3269 RCP<const map_type> map = this->
getMap ();
3270 RCP<const Teuchos::Comm<int> > comm;
3271 if (! map.is_null ()) {
3272 comm = map->getComm ();
3274 if (comm.is_null ()) {
3275 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3276 (makeIndicesLocalResult.first != 0, std::runtime_error,
3277 makeIndicesLocalResult.second);
3280 const int lclSuccess = (makeIndicesLocalResult.first == 0);
3282 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
3283 if (gblSuccess != 1) {
3284 std::ostringstream os;
3285 gathervPrint (os, makeIndicesLocalResult.second, *comm);
3286 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3287 (
true, std::runtime_error, os.str ());
3296 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3297 (makeIndicesLocalResult.first != 0, std::runtime_error,
3298 makeIndicesLocalResult.second);
3312 this->fillLocalGraph (params);
3314 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
3315 params->get (
"compute global constants",
true);
3316 if (callComputeGlobalConstants) {
3322 this->fillComplete_ =
true;
3326 std::ostringstream os;
3327 os << *prefix <<
"Done" << endl;
3328 std::cerr << os.str();
3333 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3337 const Teuchos::RCP<const map_type>& rangeMap,
3338 const Teuchos::RCP<const import_type>& importer,
3339 const Teuchos::RCP<const export_type>& exporter,
3340 const Teuchos::RCP<Teuchos::ParameterList>& params)
3342 const char tfecfFuncName[] =
"expertStaticFillComplete: ";
3343#ifdef HAVE_TPETRA_MMM_TIMINGS
3345 if(!params.is_null())
3346 label = params->get(
"Timer Label",label);
3347 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
": ");
3348 using Teuchos::TimeMonitor;
3349 Teuchos::RCP<Teuchos::TimeMonitor> MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Setup"))));
3353 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3354 domainMap.is_null () || rangeMap.is_null (),
3355 std::runtime_error,
"The input domain Map and range Map must be nonnull.");
3356 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3358 "call this method unless the graph has a column Map.");
3360 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3362 std::runtime_error,
"The calling process has getLocalNumRows() = "
3363 <<
getLocalNumRows () <<
" > 0 rows, but the row offsets array has not "
3365 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3366 static_cast<size_t> (rowPtrsUnpackedLength) !=
getLocalNumRows () + 1,
3367 std::runtime_error,
"The row offsets array has length " <<
3368 rowPtrsUnpackedLength <<
" != getLocalNumRows()+1 = " <<
3386 indicesAreAllocated_ =
true;
3391 indicesAreLocal_ =
true;
3392 indicesAreGlobal_ =
false;
3395#ifdef HAVE_TPETRA_MMM_TIMINGS
3397 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Maps"))));
3406#ifdef HAVE_TPETRA_MMM_TIMINGS
3408 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckI"))));
3413 if (importer != Teuchos::null) {
3414 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3415 ! importer->getSourceMap ()->isSameAs (*
getDomainMap ()) ||
3416 ! importer->getTargetMap ()->isSameAs (*
getColMap ()),
3417 std::invalid_argument,
": importer does not match matrix maps.");
3422#ifdef HAVE_TPETRA_MMM_TIMINGS
3424 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckE"))));
3427 if (exporter != Teuchos::null) {
3428 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3429 ! exporter->getSourceMap ()->isSameAs (*
getRowMap ()) ||
3430 ! exporter->getTargetMap ()->isSameAs (*
getRangeMap ()),
3431 std::invalid_argument,
": exporter does not match matrix maps.");
3435#ifdef HAVE_TPETRA_MMM_TIMINGS
3437 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXmake"))));
3439 Teuchos::Array<int> remotePIDs (0);
3442#ifdef HAVE_TPETRA_MMM_TIMINGS
3444 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-fLG"))));
3446 this->fillLocalGraph (params);
3448 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
3449 params->get (
"compute global constants",
true);
3451 if (callComputeGlobalConstants) {
3452#ifdef HAVE_TPETRA_MMM_TIMINGS
3454 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (const)"))));
3459#ifdef HAVE_TPETRA_MMM_TIMINGS
3461 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (noconst)"))));
3466 fillComplete_ =
true;
3468#ifdef HAVE_TPETRA_MMM_TIMINGS
3470 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cIS"))));
3476 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3479 fillLocalGraph (
const Teuchos::RCP<Teuchos::ParameterList>& params)
3482 typedef decltype (k_numRowEntries_) row_entries_type;
3483 typedef typename local_graph_device_type::row_map_type row_map_type;
3484 typedef typename row_map_type::non_const_type non_const_row_map_type;
3485 typedef typename local_graph_device_type::entries_type::non_const_type lclinds_1d_type;
3486 const char tfecfFuncName[] =
"fillLocalGraph (called from fillComplete or "
3487 "expertStaticFillComplete): ";
3488 const size_t lclNumRows = this->getLocalNumRows ();
3493 bool requestOptimizedStorage =
true;
3494 if (! params.is_null () && ! params->get (
"Optimize Storage",
true)) {
3495 requestOptimizedStorage =
false;
3503 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3505 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3506 (rowPtrsUnpacked.extent (0) == 0, std::logic_error,
3507 "rowPtrsUnpacked_host_ has size zero, but shouldn't");
3508 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3509 (rowPtrsUnpacked.extent (0) != lclNumRows + 1, std::logic_error,
3510 "rowPtrsUnpacked_host_.extent(0) = "
3511 << rowPtrsUnpacked.extent (0) <<
" != (lclNumRows + 1) = "
3512 << (lclNumRows + 1) <<
".");
3513 const size_t numOffsets = rowPtrsUnpacked.extent (0);
3514 const auto valToCheck = rowPtrsUnpacked(numOffsets-1);
3515 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3517 lclIndsUnpacked_wdv.extent (0) != valToCheck,
3518 std::logic_error,
"numOffsets=" << numOffsets <<
" != 0 "
3519 " and lclIndsUnpacked_wdv.extent(0)=" << lclIndsUnpacked_wdv.extent(0)
3520 <<
" != rowPtrsUnpacked_host_(" << numOffsets <<
")=" << valToCheck
3524 size_t allocSize = 0;
3526 allocSize = this->getLocalAllocationSize ();
3528 catch (std::logic_error& e) {
3529 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3530 (
true, std::logic_error,
"getLocalAllocationSize threw "
3531 "std::logic_error: " << e.what ());
3533 catch (std::runtime_error& e) {
3534 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3535 (
true, std::runtime_error,
"getLocalAllocationSize threw "
3536 "std::runtime_error: " << e.what ());
3538 catch (std::exception& e) {
3539 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3540 (
true, std::runtime_error,
"getLocalAllocationSize threw "
3541 "std::exception: " << e.what ());
3544 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3545 (
true, std::runtime_error,
"getLocalAllocationSize threw "
3546 "an exception not a subclass of std::exception.");
3549 if (this->getLocalNumEntries () != allocSize) {
3552 non_const_row_map_type ptr_d;
3553 row_map_type ptr_d_const;
3562 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3563 if (rowPtrsUnpacked.extent (0) != 0) {
3564 const size_t numOffsets =
3565 static_cast<size_t> (rowPtrsUnpacked.extent (0));
3566 const auto valToCheck = rowPtrsUnpacked(numOffsets - 1);
3567 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3568 (valToCheck !=
size_t(lclIndsUnpacked_wdv.extent(0)),
3569 std::logic_error,
"(Unpacked branch) Before allocating "
3570 "or packing, k_rowPtrs_(" << (numOffsets-1) <<
")="
3571 << valToCheck <<
" != lclIndsUnpacked_wdv.extent(0)="
3572 << lclIndsUnpacked_wdv.extent (0) <<
".");
3582 size_t lclTotalNumEntries = 0;
3586 non_const_row_map_type (
"Tpetra::CrsGraph::ptr", lclNumRows + 1);
3587 ptr_d_const = ptr_d;
3591 typename row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
3593 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3594 (
size_t(numRowEnt_h.extent (0)) != lclNumRows,
3595 std::logic_error,
"(Unpacked branch) "
3596 "numRowEnt_h.extent(0)=" << numRowEnt_h.extent(0)
3597 <<
" != getLocalNumRows()=" << lclNumRows <<
"");
3603 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3604 (
static_cast<size_t> (ptr_d.extent (0)) != lclNumRows + 1,
3605 std::logic_error,
"(Unpacked branch) After allocating "
3606 "ptr_d, ptr_d.extent(0) = " << ptr_d.extent(0)
3607 <<
" != lclNumRows+1 = " << (lclNumRows+1) <<
".");
3608 const auto valToCheck =
3609 ::Tpetra::Details::getEntryOnHost (ptr_d, lclNumRows);
3610 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3611 (valToCheck != lclTotalNumEntries, std::logic_error,
3612 "Tpetra::CrsGraph::fillLocalGraph: In unpacked branch, "
3613 "after filling ptr_d, ptr_d(lclNumRows=" << lclNumRows
3614 <<
") = " << valToCheck <<
" != total number of entries "
3615 "on the calling process = " << lclTotalNumEntries
3621 lclinds_1d_type ind_d =
3622 lclinds_1d_type (
"Tpetra::CrsGraph::lclInd", lclTotalNumEntries);
3634 typedef pack_functor<
3635 typename local_graph_device_type::entries_type::non_const_type,
3636 typename local_inds_dualv_type::t_dev::const_type,
3638 typename local_graph_device_type::row_map_type> inds_packer_type;
3639 inds_packer_type f (ind_d,
3640 lclIndsUnpacked_wdv.getDeviceView(Access::ReadOnly),
3641 ptr_d, this->getRowPtrsUnpackedDevice());
3643 typedef typename decltype (ind_d)::execution_space exec_space;
3644 typedef Kokkos::RangePolicy<exec_space, LocalOrdinal> range_type;
3645 Kokkos::parallel_for (range_type (0, lclNumRows), f);
3649 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3650 (ptr_d.extent (0) == 0, std::logic_error,
3651 "(\"Optimize Storage\"=true branch) After packing, "
3652 "ptr_d.extent(0)=0.");
3653 if (ptr_d.extent (0) != 0) {
3654 const size_t numOffsets =
static_cast<size_t> (ptr_d.extent (0));
3655 const auto valToCheck =
3656 ::Tpetra::Details::getEntryOnHost (ptr_d, numOffsets - 1);
3657 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3658 (
static_cast<size_t> (valToCheck) != ind_d.extent (0),
3659 std::logic_error,
"(\"Optimize Storage\"=true branch) "
3660 "After packing, ptr_d(" << (numOffsets-1) <<
")="
3661 << valToCheck <<
" != ind_d.extent(0)="
3662 << ind_d.extent(0) <<
".");
3666 if (requestOptimizedStorage)
3667 setRowPtrs(ptr_d_const);
3669 setRowPtrsPacked(ptr_d_const);
3670 lclIndsPacked_wdv = local_inds_wdv_type(ind_d);
3674 this->setRowPtrs(rowPtrsUnpacked_dev_);
3675 lclIndsPacked_wdv = lclIndsUnpacked_wdv;
3678 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3679 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3680 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3681 (rowPtrsPacked_dev.extent (0) == 0, std::logic_error,
3682 "(\"Optimize Storage\"=false branch) "
3683 "rowPtrsPacked_dev_.extent(0) = 0.");
3684 if (rowPtrsPacked_dev.extent (0) != 0) {
3685 const size_t numOffsets =
3686 static_cast<size_t> (rowPtrsPacked_dev.extent (0));
3687 const size_t valToCheck =
3688 rowPtrsPacked_host(numOffsets - 1);
3689 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3690 (valToCheck !=
size_t(lclIndsPacked_wdv.extent (0)),
3691 std::logic_error,
"(\"Optimize Storage\"=false branch) "
3692 "rowPtrsPacked_dev_(" << (numOffsets-1) <<
")="
3694 <<
" != lclIndsPacked_wdv.extent(0)="
3695 << lclIndsPacked_wdv.extent (0) <<
".");
3701 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3702 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3703 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3704 (
static_cast<size_t> (rowPtrsPacked_dev.extent (0)) != lclNumRows + 1,
3705 std::logic_error,
"After packing, rowPtrsPacked_dev_.extent(0) = " <<
3706 rowPtrsPacked_dev.extent (0) <<
" != lclNumRows+1 = " << (lclNumRows+1)
3708 if (rowPtrsPacked_dev.extent (0) != 0) {
3709 const size_t numOffsets =
static_cast<size_t> (rowPtrsPacked_dev.extent (0));
3710 const auto valToCheck = rowPtrsPacked_host(numOffsets - 1);
3711 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3712 (
static_cast<size_t> (valToCheck) != lclIndsPacked_wdv.extent (0),
3713 std::logic_error,
"After packing, rowPtrsPacked_dev_(" << (numOffsets-1)
3714 <<
") = " << valToCheck <<
" != lclIndsPacked_wdv.extent(0) = "
3715 << lclIndsPacked_wdv.extent (0) <<
".");
3719 if (requestOptimizedStorage) {
3725 k_numRowEntries_ = row_entries_type ();
3728 lclIndsUnpacked_wdv = lclIndsPacked_wdv;
3730 storageStatus_ = Details::STORAGE_1D_PACKED;
3733 set_need_sync_host_uvm_access();
3736 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3739 replaceColMap (
const Teuchos::RCP<const map_type>& newColMap)
3748 const char tfecfFuncName[] =
"replaceColMap: ";
3749 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3751 "Requires matching maps and non-static graph.");
3755 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3759 const Teuchos::RCP<const import_type>& newImport,
3760 const bool sortIndicesInEachRow)
3762 using Teuchos::REDUCE_MIN;
3763 using Teuchos::reduceAll;
3765 typedef GlobalOrdinal GO;
3766 typedef LocalOrdinal LO;
3767 typedef typename local_inds_dualv_type::t_host col_inds_type;
3768 const char tfecfFuncName[] =
"reindexColumns: ";
3770 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3771 isFillComplete (), std::runtime_error,
"The graph is fill complete "
3772 "(isFillComplete() returns true). You must call resumeFill() before "
3773 "you may call this method.");
3806 bool allCurColIndsValid =
true;
3811 bool localSuffices =
true;
3819 col_inds_type newLclInds1D;
3825 if (indicesAreAllocated ()) {
3831 newLclInds1D = col_inds_type(
"Tpetra::CrsGraph::lclIndsReindexedHost",
3834 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
3836 const size_t beg = rowInfo.offset1D;
3837 const size_t end = beg + rowInfo.numEntries;
3838 for (
size_t k = beg; k < end; ++k) {
3839 const LO oldLclCol = oldLclInds1D(k);
3840 if (oldLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
3841 allCurColIndsValid =
false;
3849 if (gblCol == Teuchos::OrdinalTraits<GO>::invalid ()) {
3850 allCurColIndsValid =
false;
3854 const LO newLclCol = newColMap->getLocalElement (gblCol);
3855 if (newLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
3856 localSuffices =
false;
3859 newLclInds1D(k) = newLclCol;
3870 allCurColIndsValid =
false;
3887 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
3890 for (
size_t k = 0; k < rowInfo.numEntries; ++k) {
3891 const GO gblCol = oldGblRowView(k);
3892 if (! newColMap->isNodeGlobalElement (gblCol)) {
3893 localSuffices =
false;
3903 lclSuccess[0] = allCurColIndsValid ? 1 : 0;
3904 lclSuccess[1] = localSuffices ? 1 : 0;
3908 RCP<const Teuchos::Comm<int> > comm =
3910 if (! comm.is_null ()) {
3911 reduceAll<int, int> (*comm, REDUCE_MIN, 2, lclSuccess, gblSuccess);
3914 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3915 gblSuccess[0] == 0, std::runtime_error,
"It is not possible to continue."
3916 " The most likely reason is that the graph is locally indexed, but the "
3917 "column Map is missing (null) on some processes, due to a previous call "
3918 "to replaceColMap().");
3920 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3921 gblSuccess[1] == 0, std::runtime_error,
"On some process, the graph "
3922 "contains column indices that are in the old column Map, but not in the "
3923 "new column Map (on that process). This method does NOT redistribute "
3924 "data; it does not claim to do the work of an Import or Export operation."
3925 " This means that for all processess, the calling process MUST own all "
3926 "column indices, in both the old column Map and the new column Map. In "
3927 "this case, you will need to do an Import or Export operation to "
3928 "redistribute data.");
3933 typename local_inds_dualv_type::t_dev newLclInds1D_dev(
3934 Kokkos::view_alloc(
"Tpetra::CrsGraph::lclIndReindexed",
3935 Kokkos::WithoutInitializing),
3936 newLclInds1D.extent(0));
3937 Kokkos::deep_copy(newLclInds1D_dev, newLclInds1D);
3948 if (sortIndicesInEachRow) {
3955 const bool sorted =
false;
3956 const bool merged =
true;
3957 this->sortAndMergeAllIndices (sorted, merged);
3962 if (newImport.is_null ()) {
3983 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3988 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMap: ";
3989 TEUCHOS_TEST_FOR_EXCEPTION(
3990 colMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
3991 "this method unless the graph already has a column Map.");
3992 TEUCHOS_TEST_FOR_EXCEPTION(
3993 newDomainMap.is_null (), std::invalid_argument,
3994 prefix <<
"The new domain Map must be nonnull.");
3997 Teuchos::RCP<const import_type> newImporter = Teuchos::null;
3998 if (newDomainMap !=
colMap_ && (! newDomainMap->isSameAs (*
colMap_))) {
4004 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4008 const Teuchos::RCP<const import_type>& newImporter)
4010 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMapAndImporter: ";
4011 TEUCHOS_TEST_FOR_EXCEPTION(
4012 colMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4013 "this method unless the graph already has a column Map.");
4014 TEUCHOS_TEST_FOR_EXCEPTION(
4015 newDomainMap.is_null (), std::invalid_argument,
4016 prefix <<
"The new domain Map must be nonnull.");
4019 if (newImporter.is_null ()) {
4024 const bool colSameAsDom =
colMap_->isSameAs (*newDomainMap);
4025 TEUCHOS_TEST_FOR_EXCEPTION
4026 (!colSameAsDom, std::invalid_argument,
"If the new Import is null, "
4027 "then the new domain Map must be the same as the current column Map.");
4030 const bool colSameAsTgt =
4031 colMap_->isSameAs (* (newImporter->getTargetMap ()));
4032 const bool newDomSameAsSrc =
4033 newDomainMap->isSameAs (* (newImporter->getSourceMap ()));
4034 TEUCHOS_TEST_FOR_EXCEPTION
4035 (! colSameAsTgt || ! newDomSameAsSrc, std::invalid_argument,
"If the "
4036 "new Import is nonnull, then the current column Map must be the same "
4037 "as the new Import's target Map, and the new domain Map must be the "
4038 "same as the new Import's source Map.");
4043 importer_ = Teuchos::rcp_const_cast<import_type> (newImporter);
4046 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4051 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMap: ";
4052 TEUCHOS_TEST_FOR_EXCEPTION(
4053 rowMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4054 "this method unless the graph already has a row Map.");
4055 TEUCHOS_TEST_FOR_EXCEPTION(
4056 newRangeMap.is_null (), std::invalid_argument,
4057 prefix <<
"The new range Map must be nonnull.");
4060 Teuchos::RCP<const export_type> newExporter = Teuchos::null;
4061 if (newRangeMap !=
rowMap_ && (! newRangeMap->isSameAs (*
rowMap_))) {
4067 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4071 const Teuchos::RCP<const export_type>& newExporter)
4073 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMapAndExporter: ";
4074 TEUCHOS_TEST_FOR_EXCEPTION(
4075 rowMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4076 "this method unless the graph already has a column Map.");
4077 TEUCHOS_TEST_FOR_EXCEPTION(
4078 newRangeMap.is_null (), std::invalid_argument,
4079 prefix <<
"The new domain Map must be nonnull.");
4082 if (newExporter.is_null ()) {
4087 const bool rowSameAsRange =
rowMap_->isSameAs (*newRangeMap);
4088 TEUCHOS_TEST_FOR_EXCEPTION
4089 (!rowSameAsRange, std::invalid_argument,
"If the new Export is null, "
4090 "then the new range Map must be the same as the current row Map.");
4093 const bool newRangeSameAsTgt =
4094 newRangeMap->isSameAs (* (newExporter->getTargetMap ()));
4095 const bool rowSameAsSrc =
4096 rowMap_->isSameAs (* (newExporter->getSourceMap ()));
4097 TEUCHOS_TEST_FOR_EXCEPTION
4098 (! rowSameAsSrc || ! newRangeSameAsTgt, std::invalid_argument,
"If the "
4099 "new Export is nonnull, then the current row Map must be the same "
4100 "as the new Export's source Map, and the new range Map must be the "
4101 "same as the new Export's target Map.");
4106 exporter_ = Teuchos::rcp_const_cast<export_type> (newExporter);
4110 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4117 this->getRowPtrsPackedDevice());
4120 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4125 return local_graph_host_type(
4126 lclIndsPacked_wdv.getHostView(Access::ReadWrite),
4127 this->getRowPtrsPackedHost());
4130 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4136 using Teuchos::ArrayView;
4137 using Teuchos::outArg;
4138 using Teuchos::reduceAll;
4141 ProfilingRegion regionCGC (
"Tpetra::CrsGraph::computeGlobalConstants");
4149 const Teuchos::Comm<int>& comm = * (this->
getComm ());
4165 reduceAll<int,GST> (comm, Teuchos::REDUCE_SUM, 1, &lcl, &gbl);
4169 reduceAll<int, GST> (comm, Teuchos::REDUCE_MAX, lclMaxNumRowEnt,
4176 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4183 ProfilingRegion regionCLC (
"Tpetra::CrsGraph::computeLocalConstants");
4190 Teuchos::OrdinalTraits<size_t>::invalid();
4195 const LO lclNumRows = ptr.extent(0) == 0 ?
4196 static_cast<LO
> (0) :
4197 (
static_cast<LO
> (ptr.extent(0)) -
static_cast<LO
> (1));
4199 const LO lclMaxNumRowEnt =
4200 ::Tpetra::Details::maxDifference (
"Tpetra::CrsGraph: nodeMaxNumRowEntries",
4207 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4208 std::pair<size_t, std::string>
4213 using Teuchos::arcp;
4214 using Teuchos::Array;
4216 typedef LocalOrdinal LO;
4217 typedef GlobalOrdinal GO;
4219 typedef typename local_graph_device_type::row_map_type::non_const_value_type offset_type;
4221 typedef typename row_entries_type::non_const_value_type num_ent_type;
4222 const char tfecfFuncName[] =
"makeIndicesLocal: ";
4223 ProfilingRegion regionMakeIndicesLocal (
"Tpetra::CrsGraph::makeIndicesLocal");
4225 std::unique_ptr<std::string> prefix;
4227 prefix = this->createPrefix(
"CrsGraph",
"makeIndicesLocal");
4228 std::ostringstream os;
4230 std::cerr << os.str();
4235 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4236 (! this->
hasColMap (), std::logic_error,
"The graph does not have a "
4237 "column Map yet. This method should never be called in that case. "
4238 "Please report this bug to the Tpetra developers.");
4239 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4240 (this->
getColMap ().is_null (), std::logic_error,
"The graph claims "
4241 "that it has a column Map, because hasColMap() returns true. However, "
4242 "the result of getColMap() is null. This should never happen. Please "
4243 "report this bug to the Tpetra developers.");
4248 size_t lclNumErrs = 0;
4249 std::ostringstream errStrm;
4256 typename row_entries_type::const_type h_numRowEnt =
4262 if (rowPtrsUnpacked_host.extent(0) == 0) {
4263 errStrm <<
"Unpacked row pointers (rowPtrsUnpacked_dev_) has length 0. This should never "
4264 "happen here. Please report this bug to the Tpetra developers."
4267 return std::make_pair(Tpetra::Details::OrdinalTraits<size_t>::invalid (),
4270 const auto numEnt = rowPtrsUnpacked_host(lclNumRows);
4279 using Kokkos::view_alloc;
4280 using Kokkos::WithoutInitializing;
4290 const std::string label (
"Tpetra::CrsGraph::lclInd");
4292 std::ostringstream os;
4293 os << *prefix <<
"(Re)allocate lclInd_wdv: old="
4295 std::cerr << os.str();
4298 local_inds_dualv_type lclInds_dualv =
4299 local_inds_dualv_type(view_alloc(label, WithoutInitializing),
4312 std::ostringstream os;
4313 os << *prefix <<
"Allocate device mirror k_numRowEnt: "
4314 << h_numRowEnt.extent(0) << endl;
4315 std::cerr << os.str();
4318 Kokkos::create_mirror_view_and_copy (
device_type (), h_numRowEnt);
4322 convertColumnIndicesFromGlobalToLocal<LO, GO, DT, offset_type, num_ent_type> (
4325 this->getRowPtrsUnpackedDevice(),
4328 if (lclNumErrs != 0) {
4329 const int myRank = [
this] () {
4330 auto map = this->
getMap ();
4331 if (map.is_null ()) {
4335 auto comm = map->getComm ();
4336 return comm.is_null () ? 0 : comm->getRank ();
4339 const bool pluralNumErrs = (lclNumErrs !=
static_cast<size_t> (1));
4340 errStrm <<
"(Process " << myRank <<
") When converting column "
4341 "indices from global to local, we encountered " << lclNumErrs
4342 <<
" ind" << (pluralNumErrs ?
"ices" :
"ex")
4343 <<
" that do" << (pluralNumErrs ?
"es" :
"")
4344 <<
" not live in the column Map on this process." << endl;
4351 std::ostringstream os;
4352 os << *prefix <<
"Free gblInds_wdv: "
4354 std::cerr << os.str();
4359 this->indicesAreLocal_ =
true;
4360 this->indicesAreGlobal_ =
false;
4363 return std::make_pair (lclNumErrs, errStrm.str ());
4366 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4373 const char tfecfFuncName[] =
"makeColMap";
4375 ProfilingRegion regionSortAndMerge (
"Tpetra::CrsGraph::makeColMap");
4376 std::unique_ptr<std::string> prefix;
4378 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4379 std::ostringstream os;
4380 os << *prefix <<
"Start" << endl;
4381 std::cerr << os.str();
4389 Teuchos::RCP<const map_type> colMap = this->
colMap_;
4390 const bool sortEachProcsGids =
4401 using Teuchos::outArg;
4402 using Teuchos::REDUCE_MIN;
4403 using Teuchos::reduceAll;
4405 std::ostringstream errStrm;
4406 const int lclErrCode =
4410 if (! comm.is_null ()) {
4411 const int lclSuccess = (lclErrCode == 0) ? 1 : 0;
4413 reduceAll<int, int> (*comm, REDUCE_MIN, lclSuccess,
4414 outArg (gblSuccess));
4415 if (gblSuccess != 1) {
4416 std::ostringstream os;
4418 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4419 (
true, std::runtime_error,
": An error happened on at "
4420 "least one process in the CrsGraph's communicator. "
4421 "Here are all processes' error messages:" << std::endl
4437 std::ostringstream os;
4438 os << *prefix <<
"Done" << endl;
4439 std::cerr << os.str();
4444 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4450 using LO = LocalOrdinal;
4451 using host_execution_space =
4452 typename Kokkos::View<LO*, device_type>::HostMirror::
4454 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
4455 const char tfecfFuncName[] =
"sortAndMergeAllIndices";
4457 (
"Tpetra::CrsGraph::sortAndMergeAllIndices");
4459 std::unique_ptr<std::string> prefix;
4461 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4462 std::ostringstream os;
4463 os << *prefix <<
"Start: "
4464 <<
"sorted=" << (sorted ?
"true" :
"false")
4465 <<
", merged=" << (merged ?
"true" :
"false") << endl;
4466 std::cerr << os.str();
4468 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4469 (this->isGloballyIndexed(), std::logic_error,
4470 "This method may only be called after makeIndicesLocal." );
4471 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4472 (! merged && this->isStorageOptimized(), std::logic_error,
4473 "The graph is already storage optimized, so we shouldn't be "
4474 "merging any indices. "
4475 "Please report this bug to the Tpetra developers.");
4477 if (! sorted || ! merged) {
4478 const LO lclNumRows(this->getLocalNumRows());
4479 auto range = range_type(0, lclNumRows);
4482 size_t totalNumDups = 0;
4484 lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
4486 Kokkos::parallel_reduce(range,
4487 [
this, sorted, merged] (
const LO lclRow,
size_t& numDups)
4489 const RowInfo rowInfo = this->getRowInfo(lclRow);
4490 numDups += this->sortAndMergeRowIndices(rowInfo, sorted, merged);
4494 std::ostringstream os;
4495 os << *prefix <<
"totalNumDups=" << totalNumDups << endl;
4496 std::cerr << os.str();
4500 lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
4502 Kokkos::parallel_for(range,
4503 [
this, sorted, merged] (
const LO lclRow)
4505 const RowInfo rowInfo = this->getRowInfo(lclRow);
4506 this->sortAndMergeRowIndices(rowInfo, sorted, merged);
4510 this->indicesAreSorted_ =
true;
4511 this->noRedundancies_ =
true;
4515 std::ostringstream os;
4516 os << *prefix <<
"Done" << endl;
4517 std::cerr << os.str();
4521 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4525 const bool useRemotePIDs)
4528 using Teuchos::ParameterList;
4531 const char tfecfFuncName[] =
"makeImportExport: ";
4532 ProfilingRegion regionMIE (
"Tpetra::CrsGraph::makeImportExport");
4534 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4535 (! this->
hasColMap (), std::logic_error,
4536 "This method may not be called unless the graph has a column Map.");
4537 RCP<ParameterList> params = this->getNonconstParameterList ();
4549 if (params.is_null () || ! params->isSublist (
"Import")) {
4550 if (useRemotePIDs) {
4558 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
4559 if (useRemotePIDs) {
4560 RCP<import_type> newImp =
4577 if (params.is_null () || ! params->isSublist (
"Export")) {
4581 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
4589 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4594 std::ostringstream oss;
4597 oss <<
"{status = fill complete"
4604 oss <<
"{status = fill not complete"
4612 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4615 describe (Teuchos::FancyOStream &out,
4616 const Teuchos::EVerbosityLevel verbLevel)
const
4618 using Teuchos::ArrayView;
4619 using Teuchos::Comm;
4621 using Teuchos::VERB_DEFAULT;
4622 using Teuchos::VERB_NONE;
4623 using Teuchos::VERB_LOW;
4624 using Teuchos::VERB_MEDIUM;
4625 using Teuchos::VERB_HIGH;
4626 using Teuchos::VERB_EXTREME;
4630 Teuchos::EVerbosityLevel vl = verbLevel;
4631 if (vl == VERB_DEFAULT) vl = VERB_LOW;
4632 RCP<const Comm<int> > comm = this->
getComm();
4633 const int myImageID = comm->getRank(),
4634 numImages = comm->getSize();
4639 width = std::max<size_t> (width,
static_cast<size_t> (11)) + 2;
4640 Teuchos::OSTab tab (out);
4648 if (vl != VERB_NONE) {
4649 if (myImageID == 0) out << this->
description() << std::endl;
4655 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4656 if (myImageID == 0) out <<
"\nRow map: " << std::endl;
4658 if (
colMap_ != Teuchos::null) {
4659 if (myImageID == 0) out <<
"\nColumn map: " << std::endl;
4663 if (myImageID == 0) out <<
"\nDomain map: " << std::endl;
4667 if (myImageID == 0) out <<
"\nRange map: " << std::endl;
4672 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4673 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4674 if (myImageID == imageCtr) {
4675 out <<
"Node ID = " << imageCtr << std::endl
4678 if (! indicesAreAllocated ()) {
4679 out <<
"Indices are not allocated." << std::endl;
4688 if (vl == VERB_HIGH || vl == VERB_EXTREME) {
4689 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4690 if (myImageID == imageCtr) {
4691 out << std::setw(width) <<
"Node ID"
4692 << std::setw(width) <<
"Global Row"
4693 << std::setw(width) <<
"Num Entries";
4694 if (vl == VERB_EXTREME) {
4698 const LocalOrdinal lclNumRows =
4700 for (LocalOrdinal r=0; r < lclNumRows; ++r) {
4702 GlobalOrdinal gid =
rowMap_->getGlobalElement(r);
4703 out << std::setw(width) << myImageID
4704 << std::setw(width) << gid
4705 << std::setw(width) << rowinfo.numEntries;
4706 if (vl == VERB_EXTREME) {
4709 auto rowview =
gblInds_wdv.getHostView(Access::ReadOnly);
4710 for (
size_t j=0; j < rowinfo.numEntries; ++j){
4711 GlobalOrdinal colgid = rowview[j + rowinfo.offset1D];
4712 out << colgid <<
" ";
4717 for (
size_t j=0; j < rowinfo.numEntries; ++j) {
4718 LocalOrdinal collid = rowview[j + rowinfo.offset1D];
4719 out <<
colMap_->getGlobalElement(collid) <<
" ";
4735 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4746 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4751 const size_t numSameIDs,
4761 using this_CRS_type = CrsGraph<LO, GO, node_type>;
4762 const char tfecfFuncName[] =
"copyAndPermute: ";
4763 const bool verbose = verbose_;
4765 std::unique_ptr<std::string> prefix;
4767 prefix = this->createPrefix(
"CrsGraph",
"copyAndPermute");
4768 std::ostringstream os;
4769 os << *prefix << endl;
4770 std::cerr << os.str ();
4773 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4774 (permuteToLIDs.extent (0) != permuteFromLIDs.extent (0),
4775 std::runtime_error,
"permuteToLIDs.extent(0) = "
4776 << permuteToLIDs.extent (0) <<
" != permuteFromLIDs.extent(0) = "
4777 << permuteFromLIDs.extent (0) <<
".");
4781 const row_graph_type& srcRowGraph =
4782 dynamic_cast<const row_graph_type&
> (source);
4785 std::ostringstream os;
4786 os << *prefix <<
"Compute padding" << endl;
4787 std::cerr << os.str ();
4789 auto padding = computeCrsPadding(srcRowGraph, numSameIDs,
4790 permuteToLIDs, permuteFromLIDs, verbose);
4791 applyCrsPadding(*padding, verbose);
4796 const this_CRS_type* srcCrsGraph =
4797 dynamic_cast<const this_CRS_type*
> (&source);
4802 nonconst_global_inds_host_view_type row_copy;
4808 if (src_filled || srcCrsGraph ==
nullptr) {
4810 std::ostringstream os;
4811 os << *prefix <<
"src_filled || srcCrsGraph == nullptr" << endl;
4812 std::cerr << os.str ();
4819 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
4822 Kokkos::resize(row_copy,row_length);
4823 size_t check_row_length = 0;
4829 std::ostringstream os;
4830 os << *prefix <<
"! src_filled && srcCrsGraph != nullptr" << endl;
4831 std::cerr << os.str ();
4833 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
4835 global_inds_host_view_type row;
4844 auto permuteToLIDs_h = permuteToLIDs.view_host ();
4845 auto permuteFromLIDs_h = permuteFromLIDs.view_host ();
4847 if (src_filled || srcCrsGraph ==
nullptr) {
4848 for (LO i = 0; i < static_cast<LO> (permuteToLIDs_h.extent (0)); ++i) {
4852 Kokkos::resize(row_copy,row_length);
4853 size_t check_row_length = 0;
4858 for (LO i = 0; i < static_cast<LO> (permuteToLIDs_h.extent (0)); ++i) {
4861 global_inds_host_view_type row;
4868 std::ostringstream os;
4869 os << *prefix <<
"Done" << endl;
4870 std::cerr << os.str ();
4874 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4884 using row_ptrs_type =
4885 typename local_graph_device_type::row_map_type::non_const_type;
4886 using range_policy =
4887 Kokkos::RangePolicy<execution_space, Kokkos::IndexType<LO>>;
4888 const char tfecfFuncName[] =
"applyCrsPadding";
4889 ProfilingRegion regionCAP(
"Tpetra::CrsGraph::applyCrsPadding");
4891 std::unique_ptr<std::string> prefix;
4893 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4894 std::ostringstream os;
4895 os << *prefix <<
"padding: ";
4898 std::cerr << os.str();
4900 const int myRank = ! verbose ? -1 : [&] () {
4901 auto map = this->getMap();
4902 if (map.is_null()) {
4905 auto comm = map->getComm();
4906 if (comm.is_null()) {
4909 return comm->getRank();
4918 if (! indicesAreAllocated()) {
4920 std::ostringstream os;
4921 os << *prefix <<
"Call allocateIndices" << endl;
4922 std::cerr << os.str();
4924 allocateIndices(GlobalIndices, verbose);
4926 TEUCHOS_ASSERT( indicesAreAllocated() );
4931 auto rowPtrsUnpacked_dev = this->getRowPtrsUnpackedDevice();
4933 std::ostringstream os;
4934 os << *prefix <<
"Allocate row_ptrs_beg: "
4935 << rowPtrsUnpacked_dev.extent(0) << endl;
4936 std::cerr << os.str();
4938 using Kokkos::view_alloc;
4939 using Kokkos::WithoutInitializing;
4940 row_ptrs_type row_ptrs_beg(
4941 view_alloc(
"row_ptrs_beg", WithoutInitializing),
4942 rowPtrsUnpacked_dev.extent(0));
4944 Kokkos::deep_copy(
execution_space(),row_ptrs_beg, rowPtrsUnpacked_dev);
4946 const size_t N = row_ptrs_beg.extent(0) == 0 ? size_t(0) :
4947 size_t(row_ptrs_beg.extent(0) - 1);
4949 std::ostringstream os;
4950 os << *prefix <<
"Allocate row_ptrs_end: " << N << endl;
4951 std::cerr << os.str();
4953 row_ptrs_type row_ptrs_end(
4954 view_alloc(
"row_ptrs_end", WithoutInitializing), N);
4955 row_ptrs_type num_row_entries;
4957 const bool refill_num_row_entries = k_numRowEntries_.extent(0) != 0;
4961 if (refill_num_row_entries) {
4965 row_ptrs_type(view_alloc(
"num_row_entries", WithoutInitializing), N);
4966 Kokkos::deep_copy(num_row_entries, this->k_numRowEntries_);
4967 Kokkos::parallel_for
4968 (
"Fill end row pointers", range_policy(0, N),
4969 KOKKOS_LAMBDA (
const size_t i) {
4970 row_ptrs_end(i) = row_ptrs_beg(i) + num_row_entries(i);
4977 Kokkos::parallel_for
4978 (
"Fill end row pointers", range_policy(0, N),
4979 KOKKOS_LAMBDA (
const size_t i) {
4980 row_ptrs_end(i) = row_ptrs_beg(i+1);
4984 if (isGloballyIndexed()) {
4986 padding, myRank, verbose);
4989 padCrsArrays(row_ptrs_beg, row_ptrs_end, lclIndsUnpacked_wdv,
4990 padding, myRank, verbose);
4993 if (refill_num_row_entries) {
4994 Kokkos::parallel_for
4995 (
"Fill num entries", range_policy(0, N),
4996 KOKKOS_LAMBDA (
const size_t i) {
4997 num_row_entries(i) = row_ptrs_end(i) - row_ptrs_beg(i);
4999 Kokkos::deep_copy(this->k_numRowEntries_, num_row_entries);
5002 std::ostringstream os;
5003 os << *prefix <<
"Reassign k_rowPtrs_; old size: "
5004 << rowPtrsUnpacked_dev.extent(0) <<
", new size: "
5005 << row_ptrs_beg.extent(0) << endl;
5006 std::cerr << os.str();
5007 TEUCHOS_ASSERT( rowPtrsUnpacked_dev.extent(0) == row_ptrs_beg.extent(0) );
5010 setRowPtrsUnpacked(row_ptrs_beg);
5013 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5015 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5020 const size_t numSameIDs,
5025 const bool verbose)
const
5030 std::unique_ptr<std::string> prefix;
5033 "computeCrsPadding(same & permute)");
5034 std::ostringstream os;
5035 os << *prefix <<
"{numSameIDs: " << numSameIDs
5036 <<
", numPermutes: " << permuteFromLIDs.extent(0) <<
"}"
5038 std::cerr << os.str();
5041 const int myRank = [&] () {
5042 auto comm = rowMap_.is_null() ? Teuchos::null :
5044 return comm.is_null() ? -1 : comm->getRank();
5046 std::unique_ptr<padding_type> padding(
5047 new padding_type(myRank, numSameIDs,
5048 permuteFromLIDs.extent(0)));
5050 computeCrsPaddingForSameIDs(*padding, source,
5051 static_cast<LO
>(numSameIDs));
5052 computeCrsPaddingForPermutedIDs(*padding, source, permuteToLIDs,
5057 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5061 padding_type& padding,
5068 using Details::Impl::getRowGraphGlobalRow;
5070 const char tfecfFuncName[] =
"computeCrsPaddingForSameIds";
5072 std::unique_ptr<std::string> prefix;
5073 const bool verbose = verbose_;
5075 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5076 std::ostringstream os;
5077 os << *prefix <<
"numSameIDs: " << numSameIDs << endl;
5078 std::cerr << os.str();
5081 if (numSameIDs == 0) {
5085 const map_type& srcRowMap = *(source.getRowMap());
5086 const map_type& tgtRowMap = *rowMap_;
5088 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
5089 const bool src_is_unique =
5090 srcCrs ==
nullptr ? false : srcCrs->
isMerged();
5091 const bool tgt_is_unique = this->isMerged();
5093 std::vector<GO> srcGblColIndsScratch;
5094 std::vector<GO> tgtGblColIndsScratch;
5096 execute_sync_host_uvm_access();
5097 for (LO lclRowInd = 0; lclRowInd < numSameIDs; ++lclRowInd) {
5098 const GO srcGblRowInd = srcRowMap.getGlobalElement(lclRowInd);
5099 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(lclRowInd);
5100 auto srcGblColInds = getRowGraphGlobalRow(
5101 srcGblColIndsScratch, source, srcGblRowInd);
5102 auto tgtGblColInds = getRowGraphGlobalRow(
5103 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5104 padding.update_same(lclRowInd, tgtGblColInds.getRawPtr(),
5105 tgtGblColInds.size(), tgt_is_unique,
5106 srcGblColInds.getRawPtr(),
5107 srcGblColInds.size(), src_is_unique);
5110 std::ostringstream os;
5111 os << *prefix <<
"Done" << endl;
5112 std::cerr << os.str();
5116 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5120 padding_type& padding,
5130 using Details::Impl::getRowGraphGlobalRow;
5132 const char tfecfFuncName[] =
"computeCrsPaddingForPermutedIds";
5134 std::unique_ptr<std::string> prefix;
5135 const bool verbose = verbose_;
5137 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5138 std::ostringstream os;
5139 os << *prefix <<
"permuteToLIDs.extent(0): "
5140 << permuteToLIDs.extent(0)
5141 <<
", permuteFromLIDs.extent(0): "
5142 << permuteFromLIDs.extent(0) << endl;
5143 std::cerr << os.str();
5146 if (permuteToLIDs.extent(0) == 0) {
5150 const map_type& srcRowMap = *(source.getRowMap());
5151 const map_type& tgtRowMap = *rowMap_;
5153 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
5154 const bool src_is_unique =
5155 srcCrs ==
nullptr ? false : srcCrs->
isMerged();
5156 const bool tgt_is_unique = this->isMerged();
5158 TEUCHOS_ASSERT( ! permuteToLIDs.need_sync_host() );
5159 auto permuteToLIDs_h = permuteToLIDs.view_host();
5160 TEUCHOS_ASSERT( ! permuteFromLIDs.need_sync_host() );
5161 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
5163 std::vector<GO> srcGblColIndsScratch;
5164 std::vector<GO> tgtGblColIndsScratch;
5165 const LO numPermutes =
static_cast<LO
>(permuteToLIDs_h.extent(0));
5167 execute_sync_host_uvm_access();
5168 for (LO whichPermute = 0; whichPermute < numPermutes; ++whichPermute) {
5169 const LO srcLclRowInd = permuteFromLIDs_h[whichPermute];
5170 const GO srcGblRowInd = srcRowMap.getGlobalElement(srcLclRowInd);
5171 auto srcGblColInds = getRowGraphGlobalRow(
5172 srcGblColIndsScratch, source, srcGblRowInd);
5173 const LO tgtLclRowInd = permuteToLIDs_h[whichPermute];
5174 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(tgtLclRowInd);
5175 auto tgtGblColInds = getRowGraphGlobalRow(
5176 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5177 padding.update_permute(whichPermute, tgtLclRowInd,
5178 tgtGblColInds.getRawPtr(),
5179 tgtGblColInds.size(), tgt_is_unique,
5180 srcGblColInds.getRawPtr(),
5181 srcGblColInds.size(), src_is_unique);
5185 std::ostringstream os;
5186 os << *prefix <<
"Done" << endl;
5187 std::cerr << os.str();
5191 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5193 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5199 Kokkos::DualView<packet_type*, buffer_device_type> imports,
5200 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
5201 const bool verbose)
const
5203 using Details::Impl::getRowGraphGlobalRow;
5207 const char tfecfFuncName[] =
"computeCrsPaddingForImports";
5209 std::unique_ptr<std::string> prefix;
5211 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5212 std::ostringstream os;
5213 os << *prefix <<
"importLIDs.extent(0): "
5214 << importLIDs.extent(0)
5215 <<
", imports.extent(0): "
5216 << imports.extent(0)
5217 <<
", numPacketsPerLID.extent(0): "
5218 << numPacketsPerLID.extent(0) << endl;
5219 std::cerr << os.str();
5222 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5223 const int myRank = [&] () {
5224 auto comm = rowMap_.is_null() ? Teuchos::null :
5226 return comm.is_null() ? -1 : comm->getRank();
5228 std::unique_ptr<padding_type> padding(
5229 new padding_type(myRank, numImports));
5231 if (imports.need_sync_host()) {
5232 imports.sync_host();
5234 auto imports_h = imports.view_host();
5235 if (numPacketsPerLID.need_sync_host ()) {
5236 numPacketsPerLID.sync_host();
5238 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5240 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
5241 auto importLIDs_h = importLIDs.view_host();
5243 const map_type& tgtRowMap = *rowMap_;
5247 constexpr bool src_is_unique =
false;
5248 const bool tgt_is_unique = isMerged();
5250 std::vector<GO> tgtGblColIndsScratch;
5252 execute_sync_host_uvm_access();
5253 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5258 const LO origSrcNumEnt =
5259 static_cast<LO
>(numPacketsPerLID_h[whichImport]);
5260 GO*
const srcGblColInds = imports_h.data() + offset;
5262 const LO tgtLclRowInd = importLIDs_h[whichImport];
5263 const GO tgtGblRowInd =
5264 tgtRowMap.getGlobalElement(tgtLclRowInd);
5265 auto tgtGblColInds = getRowGraphGlobalRow(
5266 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5267 const size_t origTgtNumEnt(tgtGblColInds.size());
5269 padding->update_import(whichImport, tgtLclRowInd,
5270 tgtGblColInds.getRawPtr(),
5271 origTgtNumEnt, tgt_is_unique,
5273 origSrcNumEnt, src_is_unique);
5274 offset += origSrcNumEnt;
5278 std::ostringstream os;
5279 os << *prefix <<
"Done" << endl;
5280 std::cerr << os.str();
5285 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5287 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type
5293 Kokkos::DualView<char*, buffer_device_type> imports,
5294 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
5295 const bool verbose)
const
5297 using Details::Impl::getRowGraphGlobalRow;
5302 const char tfecfFuncName[] =
"computePaddingForCrsMatrixUnpack";
5304 std::unique_ptr<std::string> prefix;
5306 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5307 std::ostringstream os;
5308 os << *prefix <<
"importLIDs.extent(0): "
5309 << importLIDs.extent(0)
5310 <<
", imports.extent(0): "
5311 << imports.extent(0)
5312 <<
", numPacketsPerLID.extent(0): "
5313 << numPacketsPerLID.extent(0) << endl;
5314 std::cerr << os.str();
5316 const bool extraVerbose =
5319 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5320 TEUCHOS_ASSERT( LO(numPacketsPerLID.extent(0)) >= numImports );
5321 const int myRank = [&] () {
5322 auto comm = rowMap_.is_null() ? Teuchos::null :
5324 return comm.is_null() ? -1 : comm->getRank();
5326 std::unique_ptr<padding_type> padding(
5327 new padding_type(myRank, numImports));
5329 if (imports.need_sync_host()) {
5330 imports.sync_host();
5332 auto imports_h = imports.view_host();
5333 if (numPacketsPerLID.need_sync_host ()) {
5334 numPacketsPerLID.sync_host();
5336 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5338 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
5339 auto importLIDs_h = importLIDs.view_host();
5341 const map_type& tgtRowMap = *rowMap_;
5345 constexpr bool src_is_unique =
false;
5346 const bool tgt_is_unique = isMerged();
5348 std::vector<GO> srcGblColIndsScratch;
5349 std::vector<GO> tgtGblColIndsScratch;
5351 execute_sync_host_uvm_access();
5352 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5357 const size_t numBytes = numPacketsPerLID_h[whichImport];
5359 std::ostringstream os;
5360 os << *prefix <<
"whichImport=" << whichImport
5361 <<
", numImports=" << numImports
5362 <<
", numBytes=" << numBytes << endl;
5363 std::cerr << os.str();
5365 if (numBytes == 0) {
5368 LO origSrcNumEnt = 0;
5369 const size_t numEntBeg = offset;
5370 const size_t numEntLen =
5371 PackTraits<LO>::packValueCount(origSrcNumEnt);
5372 TEUCHOS_ASSERT( numBytes >= numEntLen );
5373 TEUCHOS_ASSERT( imports_h.extent(0) >= numEntBeg + numEntLen );
5374 PackTraits<LO>::unpackValue(origSrcNumEnt,
5375 imports_h.data() + numEntBeg);
5377 std::ostringstream os;
5378 os << *prefix <<
"whichImport=" << whichImport
5379 <<
", numImports=" << numImports
5380 <<
", origSrcNumEnt=" << origSrcNumEnt << endl;
5381 std::cerr << os.str();
5383 TEUCHOS_ASSERT( origSrcNumEnt >= LO(0) );
5384 TEUCHOS_ASSERT( numBytes >=
size_t(numEntLen + origSrcNumEnt *
sizeof(GO)) );
5385 const size_t gidsBeg = numEntBeg + numEntLen;
5386 if (srcGblColIndsScratch.size() <
size_t(origSrcNumEnt)) {
5387 srcGblColIndsScratch.resize(origSrcNumEnt);
5389 GO*
const srcGblColInds = srcGblColIndsScratch.data();
5390 PackTraits<GO>::unpackArray(srcGblColInds,
5391 imports_h.data() + gidsBeg,
5393 const LO tgtLclRowInd = importLIDs_h[whichImport];
5394 const GO tgtGblRowInd =
5395 tgtRowMap.getGlobalElement(tgtLclRowInd);
5396 auto tgtGblColInds = getRowGraphGlobalRow(
5397 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5398 const size_t origNumTgtEnt(tgtGblColInds.size());
5401 std::ostringstream os;
5402 os << *prefix <<
"whichImport=" << whichImport
5403 <<
", numImports=" << numImports
5404 <<
": Call padding->update_import" << endl;
5405 std::cerr << os.str();
5407 padding->update_import(whichImport, tgtLclRowInd,
5408 tgtGblColInds.getRawPtr(),
5409 origNumTgtEnt, tgt_is_unique,
5411 origSrcNumEnt, src_is_unique);
5416 std::ostringstream os;
5417 os << *prefix <<
"Done" << endl;
5418 std::cerr << os.str();
5423 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5430 Kokkos::DualView<packet_type*,
5432 Kokkos::DualView<
size_t*,
5434 size_t& constantNumPackets)
5436 using Tpetra::Details::ProfilingRegion;
5441 const char tfecfFuncName[] =
"packAndPrepare: ";
5442 ProfilingRegion region_papn (
"Tpetra::CrsGraph::packAndPrepare");
5444 const bool verbose = verbose_;
5445 std::unique_ptr<std::string> prefix;
5447 prefix = this->
createPrefix(
"CrsGraph",
"packAndPrepare");
5448 std::ostringstream os;
5449 os << *prefix <<
"Start" << endl;
5450 std::cerr << os.str();
5453 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5454 (exportLIDs.extent (0) != numPacketsPerLID.extent (0),
5456 "exportLIDs.extent(0) = " << exportLIDs.extent (0)
5457 <<
" != numPacketsPerLID.extent(0) = " << numPacketsPerLID.extent (0)
5459 const row_graph_type* srcRowGraphPtr =
5460 dynamic_cast<const row_graph_type*
> (&source);
5461 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5462 (srcRowGraphPtr ==
nullptr, std::invalid_argument,
"Source of an Export "
5463 "or Import operation to a CrsGraph must be a RowGraph with the same "
5464 "template parameters.");
5468 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5469 (this->isFillComplete (), std::runtime_error,
5470 "The target graph of an Import or Export must not be fill complete.");
5475 if (srcCrsGraphPtr ==
nullptr) {
5476 using Teuchos::ArrayView;
5480 std::ostringstream os;
5481 os << *prefix <<
"Source is a RowGraph but not a CrsGraph"
5483 std::cerr << os.str();
5490 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
5491 auto exportLIDs_h = exportLIDs.view_host ();
5492 ArrayView<const LO> exportLIDs_av (exportLIDs_h.data (),
5493 exportLIDs_h.extent (0));
5494 Teuchos::Array<GO> exports_a;
5496 numPacketsPerLID.clear_sync_state ();
5497 numPacketsPerLID.modify_host ();
5498 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
5499 ArrayView<size_t> numPacketsPerLID_av (numPacketsPerLID_h.data (),
5500 numPacketsPerLID_h.extent (0));
5501 srcRowGraphPtr->pack (exportLIDs_av, exports_a, numPacketsPerLID_av,
5502 constantNumPackets);
5503 const size_t newSize =
static_cast<size_t> (exports_a.size ());
5504 if (
static_cast<size_t> (exports.extent (0)) != newSize) {
5505 using exports_dv_type = Kokkos::DualView<packet_type*, buffer_device_type>;
5506 exports = exports_dv_type (
"exports", newSize);
5508 Kokkos::View<
const packet_type*, Kokkos::HostSpace,
5509 Kokkos::MemoryUnmanaged> exports_a_h (exports_a.getRawPtr (), newSize);
5510 exports.clear_sync_state ();
5511 exports.modify_host ();
5513 Kokkos::deep_copy (exports.view_host (), exports_a_h);
5516 else if (! getColMap ().is_null () &&
5517 (this->getRowPtrsPackedDevice().extent (0) != 0 ||
5518 getRowMap ()->getLocalNumElements () == 0)) {
5520 std::ostringstream os;
5521 os << *prefix <<
"packCrsGraphNew path" << endl;
5522 std::cerr << os.str();
5524 using export_pids_type =
5525 Kokkos::DualView<const int*, buffer_device_type>;
5526 export_pids_type exportPIDs;
5530 packCrsGraphNew<LO,GO,NT> (*srcCrsGraphPtr, exportLIDs, exportPIDs,
5531 exports, numPacketsPerLID,
5532 constantNumPackets,
false);
5535 srcCrsGraphPtr->packFillActiveNew (exportLIDs, exports, numPacketsPerLID,
5536 constantNumPackets);
5540 std::ostringstream os;
5541 os << *prefix <<
"Done" << endl;
5542 std::cerr << os.str();
5546 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5549 pack (
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5550 Teuchos::Array<GlobalOrdinal>& exports,
5551 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5552 size_t& constantNumPackets)
const
5556 if( !col_map.is_null() && (this->getRowPtrsPackedDevice().extent(0) != 0 ||
getRowMap()->getLocalNumElements() ==0)) {
5558 packCrsGraph<LocalOrdinal,GlobalOrdinal,Node>(*
this, exports, numPacketsPerLID,
5559 exportLIDs, constantNumPackets);
5562 this->packFillActive(exportLIDs, exports, numPacketsPerLID,
5563 constantNumPackets);
5567 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5570 packFillActive (
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5571 Teuchos::Array<GlobalOrdinal>& exports,
5572 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5573 size_t& constantNumPackets)
const
5576 using LO = LocalOrdinal;
5577 using GO = GlobalOrdinal;
5578 using host_execution_space =
5579 typename Kokkos::View<size_t*, device_type>::
5580 HostMirror::execution_space;
5581 const char tfecfFuncName[] =
"packFillActive: ";
5582 const bool verbose = verbose_;
5584 const auto numExportLIDs = exportLIDs.size ();
5585 std::unique_ptr<std::string> prefix;
5587 prefix = this->createPrefix(
"CrsGraph",
"allocateIndices");
5588 std::ostringstream os;
5589 os << *prefix <<
"numExportLIDs=" << numExportLIDs << endl;
5590 std::cerr << os.str();
5592 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5593 (numExportLIDs != numPacketsPerLID.size (), std::runtime_error,
5594 "exportLIDs.size() = " << numExportLIDs <<
" != numPacketsPerLID.size()"
5595 " = " << numPacketsPerLID.size () <<
".");
5597 const map_type& rowMap = * (this->getRowMap ());
5598 const map_type*
const colMapPtr = this->colMap_.getRawPtr ();
5599 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5600 (this->isLocallyIndexed () && colMapPtr ==
nullptr, std::logic_error,
5601 "This graph claims to be locally indexed, but its column Map is nullptr. "
5602 "This should never happen. Please report this bug to the Tpetra "
5606 constantNumPackets = 0;
5610 size_t*
const numPacketsPerLID_raw = numPacketsPerLID.getRawPtr ();
5611 const LO*
const exportLIDs_raw = exportLIDs.getRawPtr ();
5618 Kokkos::RangePolicy<host_execution_space, LO> inputRange (0, numExportLIDs);
5619 size_t totalNumPackets = 0;
5620 size_t errCount = 0;
5623 typedef Kokkos::Device<host_execution_space, Kokkos::HostSpace>
5625 Kokkos::View<size_t, host_device_type> errCountView (&errCount);
5626 constexpr size_t ONE = 1;
5628 execute_sync_host_uvm_access();
5629 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::pack: totalNumPackets",
5631 [=] (
const LO& i,
size_t& curTotalNumPackets) {
5632 const GO gblRow = rowMap.getGlobalElement (exportLIDs_raw[i]);
5633 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
5634 Kokkos::atomic_add (&errCountView(), ONE);
5635 numPacketsPerLID_raw[i] = 0;
5638 const size_t numEnt = this->getNumEntriesInGlobalRow (gblRow);
5639 numPacketsPerLID_raw[i] = numEnt;
5640 curTotalNumPackets += numEnt;
5646 std::ostringstream os;
5647 os << *prefix <<
"totalNumPackets=" << totalNumPackets << endl;
5648 std::cerr << os.str();
5650 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5651 (errCount != 0, std::logic_error,
"totalNumPackets count encountered "
5652 "one or more errors! errCount = " << errCount
5653 <<
", totalNumPackets = " << totalNumPackets <<
".");
5657 exports.resize (totalNumPackets);
5659 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5660 (! this->supportsRowViews (), std::logic_error,
5661 "this->supportsRowViews() returns false; this should never happen. "
5662 "Please report this bug to the Tpetra developers.");
5668 std::ostringstream os;
5669 os << *prefix <<
"Pack into exports" << endl;
5670 std::cerr << os.str();
5675 GO*
const exports_raw = exports.getRawPtr ();
5677 Kokkos::parallel_scan (
"Tpetra::CrsGraph::pack: pack from views",
5678 inputRange, [=, &prefix]
5679 (
const LO i,
size_t& exportsOffset,
const bool final) {
5680 const size_t curOffset = exportsOffset;
5681 const GO gblRow = rowMap.getGlobalElement (exportLIDs_raw[i]);
5683 this->getRowInfoFromGlobalRowIndex (gblRow);
5685 using TDO = Tpetra::Details::OrdinalTraits<size_t>;
5686 if (rowInfo.localRow == TDO::invalid ()) {
5688 std::ostringstream os;
5689 os << *prefix <<
": INVALID rowInfo: i=" << i
5690 <<
", lclRow=" << exportLIDs_raw[i] << endl;
5691 std::cerr << os.str();
5693 Kokkos::atomic_add (&errCountView(), ONE);
5695 else if (curOffset + rowInfo.numEntries > totalNumPackets) {
5697 std::ostringstream os;
5698 os << *prefix <<
": UH OH! For i=" << i <<
", lclRow="
5699 << exportLIDs_raw[i] <<
", gblRow=" << gblRow <<
", curOffset "
5700 "(= " << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5701 <<
") > totalNumPackets (= " << totalNumPackets <<
")."
5703 std::cerr << os.str();
5705 Kokkos::atomic_add (&errCountView(), ONE);
5708 const LO numEnt =
static_cast<LO
> (rowInfo.numEntries);
5709 if (this->isLocallyIndexed ()) {
5710 auto lclColInds = getLocalIndsViewHost (rowInfo);
5712 for (LO k = 0; k < numEnt; ++k) {
5713 const LO lclColInd = lclColInds(k);
5714 const GO gblColInd = colMapPtr->getGlobalElement (lclColInd);
5718 exports_raw[curOffset + k] = gblColInd;
5721 exportsOffset = curOffset + numEnt;
5723 else if (this->isGloballyIndexed ()) {
5724 auto gblColInds = getGlobalIndsViewHost (rowInfo);
5726 for (LO k = 0; k < numEnt; ++k) {
5727 const GO gblColInd = gblColInds(k);
5731 exports_raw[curOffset + k] = gblColInd;
5734 exportsOffset = curOffset + numEnt;
5742 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5743 (errCount != 0, std::logic_error,
"Packing encountered "
5744 "one or more errors! errCount = " << errCount
5745 <<
", totalNumPackets = " << totalNumPackets <<
".");
5748 std::ostringstream os;
5749 os << *prefix <<
"Done" << endl;
5750 std::cerr << os.str();
5754 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5759 Kokkos::DualView<packet_type*,
5761 Kokkos::DualView<
size_t*,
5763 size_t& constantNumPackets)
const
5768 using host_execution_space =
typename Kokkos::View<
size_t*,
5770 using host_device_type =
5771 Kokkos::Device<host_execution_space, Kokkos::HostSpace>;
5772 using exports_dv_type =
5773 Kokkos::DualView<packet_type*, buffer_device_type>;
5774 const char tfecfFuncName[] =
"packFillActiveNew: ";
5775 const bool verbose = verbose_;
5777 const auto numExportLIDs = exportLIDs.extent (0);
5778 std::unique_ptr<std::string> prefix;
5780 prefix = this->
createPrefix(
"CrsGraph",
"packFillActiveNew");
5781 std::ostringstream os;
5782 os << *prefix <<
"numExportLIDs: " << numExportLIDs
5783 <<
", numPacketsPerLID.extent(0): "
5784 << numPacketsPerLID.extent(0) << endl;
5785 std::cerr << os.str();
5787 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5788 (numExportLIDs != numPacketsPerLID.extent (0), std::runtime_error,
5789 "exportLIDs.extent(0) = " << numExportLIDs
5790 <<
" != numPacketsPerLID.extent(0) = "
5791 << numPacketsPerLID.extent (0) <<
".");
5792 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
5793 auto exportLIDs_h = exportLIDs.view_host ();
5795 const map_type& rowMap = * (this->getRowMap ());
5796 const map_type*
const colMapPtr = this->colMap_.getRawPtr ();
5797 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5798 (this->isLocallyIndexed () && colMapPtr ==
nullptr, std::logic_error,
5799 "This graph claims to be locally indexed, but its column Map is nullptr. "
5800 "This should never happen. Please report this bug to the Tpetra "
5804 constantNumPackets = 0;
5806 numPacketsPerLID.clear_sync_state ();
5807 numPacketsPerLID.modify_host ();
5808 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
5815 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
5816 range_type inputRange (0, numExportLIDs);
5817 size_t totalNumPackets = 0;
5818 size_t errCount = 0;
5821 Kokkos::View<size_t, host_device_type> errCountView (&errCount);
5822 constexpr size_t ONE = 1;
5825 std::ostringstream os;
5826 os << *prefix <<
"Compute totalNumPackets" << endl;
5827 std::cerr << os.str ();
5830 execute_sync_host_uvm_access();
5831 Kokkos::parallel_reduce
5832 (
"Tpetra::CrsGraph::pack: totalNumPackets",
5834 [=, &prefix] (
const LO i,
size_t& curTotalNumPackets) {
5835 const LO lclRow = exportLIDs_h[i];
5836 const GO gblRow = rowMap.getGlobalElement (lclRow);
5837 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
5839 std::ostringstream os;
5840 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5841 <<
" not in row Map on this process" << endl;
5842 std::cerr << os.str();
5844 Kokkos::atomic_add (&errCountView(), ONE);
5845 numPacketsPerLID_h(i) = 0;
5848 const size_t numEnt = this->getNumEntriesInGlobalRow (gblRow);
5849 numPacketsPerLID_h(i) = numEnt;
5850 curTotalNumPackets += numEnt;
5856 std::ostringstream os;
5857 os << *prefix <<
"totalNumPackets: " << totalNumPackets
5858 <<
", errCount: " << errCount << endl;
5859 std::cerr << os.str ();
5861 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5862 (errCount != 0, std::logic_error,
"totalNumPackets count encountered "
5863 "one or more errors! totalNumPackets: " << totalNumPackets
5864 <<
", errCount: " << errCount <<
".");
5867 if (
size_t(exports.extent (0)) < totalNumPackets) {
5869 exports = exports_dv_type (
"exports", totalNumPackets);
5872 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5873 (! this->supportsRowViews (), std::logic_error,
5874 "this->supportsRowViews() returns false; this should never happen. "
5875 "Please report this bug to the Tpetra developers.");
5881 std::ostringstream os;
5882 os << *prefix <<
"Pack into exports buffer" << endl;
5883 std::cerr << os.str();
5886 exports.clear_sync_state ();
5887 exports.modify_host ();
5888 auto exports_h = exports.view_host ();
5894 if(isLocallyIndexed())
5895 lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
5896 else if(isGloballyIndexed())
5897 gblInds_wdv.getHostView(Access::ReadOnly);
5900 Kokkos::parallel_scan
5901 (
"Tpetra::CrsGraph::packFillActiveNew: Pack exports",
5902 inputRange, [=, &prefix]
5903 (
const LO i,
size_t& exportsOffset,
const bool final) {
5904 const size_t curOffset = exportsOffset;
5905 const LO lclRow = exportLIDs_h(i);
5906 const GO gblRow = rowMap.getGlobalElement (lclRow);
5907 if (gblRow == Details::OrdinalTraits<GO>::invalid ()) {
5909 std::ostringstream os;
5910 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5911 <<
" not in row Map on this process" << endl;
5912 std::cerr << os.str();
5914 Kokkos::atomic_add (&errCountView(), ONE);
5918 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (gblRow);
5919 if (rowInfo.localRow == Details::OrdinalTraits<size_t>::invalid ()) {
5921 std::ostringstream os;
5922 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5923 <<
", gblRow=" << gblRow <<
": invalid rowInfo"
5925 std::cerr << os.str();
5927 Kokkos::atomic_add (&errCountView(), ONE);
5931 if (curOffset + rowInfo.numEntries > totalNumPackets) {
5933 std::ostringstream os;
5934 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5935 <<
", gblRow=" << gblRow <<
", curOffset (= "
5936 << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5937 <<
") > totalNumPackets (= " << totalNumPackets
5939 std::cerr << os.str();
5941 Kokkos::atomic_add (&errCountView(), ONE);
5945 const LO numEnt =
static_cast<LO
> (rowInfo.numEntries);
5946 if (this->isLocallyIndexed ()) {
5947 auto lclColInds = getLocalIndsViewHost(rowInfo);
5949 for (LO k = 0; k < numEnt; ++k) {
5950 const LO lclColInd = lclColInds(k);
5951 const GO gblColInd = colMapPtr->getGlobalElement (lclColInd);
5955 exports_h(curOffset + k) = gblColInd;
5958 exportsOffset = curOffset + numEnt;
5960 else if (this->isGloballyIndexed ()) {
5961 auto gblColInds = getGlobalIndsViewHost(rowInfo);
5963 for (LO k = 0; k < numEnt; ++k) {
5964 const GO gblColInd = gblColInds(k);
5968 exports_h(curOffset + k) = gblColInd;
5971 exportsOffset = curOffset + numEnt;
5985 std::ostringstream os;
5986 os << *prefix <<
"errCount=" << errCount <<
"; Done" << endl;
5987 std::cerr << os.str();
5991 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5999 Kokkos::DualView<
size_t*,
6008 const char tfecfFuncName[] =
"unpackAndCombine";
6010 ProfilingRegion regionCGC(
"Tpetra::CrsGraph::unpackAndCombine");
6011 const bool verbose = verbose_;
6013 std::unique_ptr<std::string> prefix;
6015 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
6016 std::ostringstream os;
6017 os << *prefix <<
"Start" << endl;
6018 std::cerr << os.str ();
6021 auto padding = computeCrsPaddingForImports(
6022 importLIDs, imports, numPacketsPerLID, verbose);
6023 applyCrsPadding(*padding, verbose);
6025 std::ostringstream os;
6026 os << *prefix <<
"Done computing & applying padding" << endl;
6027 std::cerr << os.str ();
6048 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6049 (importLIDs.extent (0) != numPacketsPerLID.extent (0),
6050 std::runtime_error,
": importLIDs.extent(0) = "
6051 << importLIDs.extent (0) <<
" != numPacketsPerLID.extent(0) = "
6052 << numPacketsPerLID.extent (0) <<
".");
6053 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6055 ": Import or Export operations are not allowed on a target "
6056 "CrsGraph that is fillComplete.");
6058 const size_t numImportLIDs(importLIDs.extent(0));
6059 if (numPacketsPerLID.need_sync_host()) {
6060 numPacketsPerLID.sync_host();
6062 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
6063 if (imports.need_sync_host()) {
6064 imports.sync_host();
6066 auto imports_h = imports.view_host();
6067 TEUCHOS_ASSERT( ! importLIDs.need_sync_host() );
6068 auto importLIDs_h = importLIDs.view_host();
6071 Teuchos::Array<LO> lclColInds;
6074 std::ostringstream os;
6075 os << *prefix <<
"Preallocate local indices scratch" << endl;
6076 std::cerr << os.str();
6078 size_t maxNumInserts = 0;
6079 for (
size_t i = 0; i < numImportLIDs; ++i) {
6080 maxNumInserts = std::max (maxNumInserts, numPacketsPerLID_h[i]);
6083 std::ostringstream os;
6084 os << *prefix <<
"Local indices scratch size: "
6085 << maxNumInserts << endl;
6086 std::cerr << os.str();
6088 lclColInds.resize (maxNumInserts);
6092 std::ostringstream os;
6095 os <<
"Graph is globally indexed";
6098 os <<
"Graph is neither locally nor globally indexed";
6101 std::cerr << os.str();
6105 TEUCHOS_ASSERT( !
rowMap_.is_null() );
6109 size_t importsOffset = 0;
6110 for (
size_t i = 0; i < numImportLIDs; ++i) {
6112 std::ostringstream os;
6113 os << *prefix <<
"i=" << i <<
", numImportLIDs="
6114 << numImportLIDs << endl;
6115 std::cerr << os.str();
6119 const LO lclRow = importLIDs_h[i];
6121 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6122 (gblRow == Teuchos::OrdinalTraits<GO>::invalid(),
6123 std::logic_error,
"importLIDs[i=" << i <<
"]="
6124 << lclRow <<
" is not in the row Map on the calling "
6126 const LO numEnt = numPacketsPerLID_h[i];
6127 const GO*
const gblColInds = (numEnt == 0) ?
nullptr :
6128 imports_h.data() + importsOffset;
6135 for (LO j = 0; j < numEnt; j++) {
6136 lclColInds[j] =
colMap_->getLocalElement(gblColInds[j]);
6140 importsOffset += numEnt;
6143 catch (std::exception& e) {
6144 TEUCHOS_TEST_FOR_EXCEPTION
6145 (
true, std::runtime_error,
6146 "Tpetra::CrsGraph::unpackAndCombine: Insert loop threw an "
6147 "exception: " << endl << e.what());
6151 std::ostringstream os;
6152 os << *prefix <<
"Done" << endl;
6153 std::cerr << os.str();
6157 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6162 using Teuchos::Comm;
6163 using Teuchos::null;
6164 using Teuchos::ParameterList;
6170 RCP<const map_type> rowMap, domainMap, rangeMap, colMap;
6171 RCP<import_type> importer;
6172 RCP<export_type> exporter;
6175 RCP<const Comm<int> > newComm =
6176 (newMap.is_null ()) ? null : newMap->getComm ();
6186 domainMap =
domainMap_->replaceCommWithSubset (newComm);
6197 rangeMap =
rangeMap_->replaceCommWithSubset (newComm);
6201 colMap =
colMap_->replaceCommWithSubset (newComm);
6205 if (! newComm.is_null ()) {
6206 RCP<ParameterList> params = this->getNonconstParameterList ();
6215 rangeMap != rowMap &&
6216 ! rangeMap->isSameAs (*rowMap)) {
6217 if (params.is_null () || ! params->isSublist (
"Export")) {
6218 exporter = rcp (
new export_type (rowMap, rangeMap));
6221 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
6222 exporter = rcp (
new export_type (rowMap, rangeMap, exportSublist));
6227 domainMap != colMap &&
6228 ! domainMap->isSameAs (*colMap)) {
6229 if (params.is_null () || ! params->isSublist (
"Import")) {
6230 importer = rcp (
new import_type (domainMap, colMap));
6232 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
6233 importer = rcp (
new import_type (domainMap, colMap, importSublist));
6249 this->
map_ = rowMap;
6255 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6258 getLocalDiagOffsets (
const Kokkos::View<size_t*, device_type, Kokkos::MemoryUnmanaged>& offsets)
const
6261 using LO = LocalOrdinal;
6262 using GO = GlobalOrdinal;
6263 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6264 const bool verbose = verbose_;
6266 std::unique_ptr<std::string> prefix;
6268 prefix = this->createPrefix(
"CrsGraph",
"getLocalDiagOffsets");
6269 std::ostringstream os;
6270 os << *prefix <<
"offsets.extent(0)=" << offsets.extent(0)
6272 std::cerr << os.str();
6275 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6276 (!
hasColMap (), std::runtime_error,
"The graph must have a column Map.");
6278 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6279 (
static_cast<LO
> (offsets.extent (0)) < lclNumRows,
6280 std::invalid_argument,
"offsets.extent(0) = " <<
6281 offsets.extent (0) <<
" < getLocalNumRows() = " << lclNumRows <<
".");
6290 bool allRowMapDiagEntriesInColMap =
true;
6291 bool allDiagEntriesFound =
true;
6292 bool allOffsetsCorrect =
true;
6293 bool noOtherWeirdness =
true;
6294 using wrong_offsets_type = std::vector<std::pair<LO, size_t> >;
6295 wrong_offsets_type wrongOffsets(0);
6306 const bool sorted = this->
isSorted ();
6309 ::Tpetra::Details::getGraphDiagOffsets (offsets, lclRowMap, lclColMap,
6311 lclGraph.entries, sorted);
6317 auto offsets_h = Kokkos::create_mirror_view (offsets);
6319 for (LO lclRowInd = 0; lclRowInd < lclNumRows; ++lclRowInd) {
6323 const GO gblRowInd = lclRowMap.getGlobalElement (lclRowInd);
6324 const GO gblColInd = gblRowInd;
6325 const LO lclColInd = lclColMap.getLocalElement (gblColInd);
6327 if (lclColInd == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
6328 allRowMapDiagEntriesInColMap =
false;
6329 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6333 if (
static_cast<LO
> (rowInfo.localRow) == lclRowInd &&
6334 rowInfo.numEntries > 0) {
6337 const size_t hint = 0;
6338 const size_t offset =
6339 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
6340 lclColInd, hint, sorted);
6341 offsets_h(lclRowInd) = offset;
6348 typename local_inds_dualv_type::t_host::const_type lclColInds;
6353 noOtherWeirdness =
false;
6356 if (noOtherWeirdness) {
6357 const size_t numEnt = lclColInds.extent (0);
6358 if (offset >= numEnt) {
6361 allOffsetsCorrect =
false;
6362 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6364 const LO actualLclColInd = lclColInds(offset);
6365 const GO actualGblColInd = lclColMap.getGlobalElement (actualLclColInd);
6366 if (actualGblColInd != gblColInd) {
6367 allOffsetsCorrect =
false;
6368 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6375 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6376 allDiagEntriesFound =
false;
6381 Kokkos::deep_copy (offsets, offsets_h);
6384 if (verbose && wrongOffsets.size () != 0) {
6385 std::ostringstream os;
6386 os << *prefix <<
"Wrong offsets: [";
6387 for (
size_t k = 0; k < wrongOffsets.size (); ++k) {
6388 os <<
"(" << wrongOffsets[k].first <<
","
6389 << wrongOffsets[k].second <<
")";
6390 if (k + 1 < wrongOffsets.size ()) {
6395 std::cerr << os.str();
6399 using Teuchos::reduceAll;
6401 Teuchos::RCP<const Teuchos::Comm<int> > comm = this->
getComm ();
6402 const bool localSuccess =
6403 allRowMapDiagEntriesInColMap && allDiagEntriesFound && allOffsetsCorrect;
6404 const int numResults = 5;
6406 lclResults[0] = allRowMapDiagEntriesInColMap ? 1 : 0;
6407 lclResults[1] = allDiagEntriesFound ? 1 : 0;
6408 lclResults[2] = allOffsetsCorrect ? 1 : 0;
6409 lclResults[3] = noOtherWeirdness ? 1 : 0;
6412 lclResults[4] = ! localSuccess ? comm->getRank () : comm->getSize ();
6420 reduceAll<int, int> (*comm, Teuchos::REDUCE_MIN,
6421 numResults, lclResults, gblResults);
6423 if (gblResults[0] != 1 || gblResults[1] != 1 || gblResults[2] != 1
6424 || gblResults[3] != 1) {
6425 std::ostringstream os;
6426 os <<
"Issue(s) that we noticed (on Process " << gblResults[4] <<
", "
6427 "possibly among others): " << endl;
6428 if (gblResults[0] == 0) {
6429 os <<
" - The column Map does not contain at least one diagonal entry "
6430 "of the graph." << endl;
6432 if (gblResults[1] == 0) {
6433 os <<
" - On one or more processes, some row does not contain a "
6434 "diagonal entry." << endl;
6436 if (gblResults[2] == 0) {
6437 os <<
" - On one or more processes, some offsets are incorrect."
6440 if (gblResults[3] == 0) {
6441 os <<
" - One or more processes had some other error."
6444 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
6449 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6455 const char tfecfFuncName[] =
"getLocalOffRankOffsets: ";
6456 const bool verbose = verbose_;
6458 std::unique_ptr<std::string> prefix;
6460 prefix = this->createPrefix(
"CrsGraph",
"getLocalOffRankOffsets");
6461 std::ostringstream os;
6462 os << *prefix <<
"offsets.extent(0)=" << offsets.extent(0)
6464 std::cerr << os.str();
6467 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6468 (!
hasColMap (), std::runtime_error,
"The graph must have a column Map.");
6477 haveLocalOffRankOffsets_ =
false;
6478 k_offRankOffsets_ = offset_device_view_type(Kokkos::ViewAllocateWithoutInitializing(
"offRankOffset"), lclNumRows+1);
6497 lclColMap, lclDomMap,
6499 haveLocalOffRankOffsets_ =
true;
6521 template<
class DeviceType,
6522 const bool memSpaceIsHostSpace =
6523 std::is_same<
typename DeviceType::memory_space,
6524 Kokkos::HostSpace>::value>
6525 struct HelpGetLocalDiagOffsets {};
6527 template<
class DeviceType>
6528 struct HelpGetLocalDiagOffsets<DeviceType, true> {
6529 typedef DeviceType device_type;
6530 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6531 Kokkos::MemoryUnmanaged> device_offsets_type;
6532 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6533 Kokkos::MemoryUnmanaged> host_offsets_type;
6535 static device_offsets_type
6536 getDeviceOffsets (
const host_offsets_type& hostOffsets)
6544 copyBackIfNeeded (
const host_offsets_type& ,
6545 const device_offsets_type& )
6549 template<
class DeviceType>
6550 struct HelpGetLocalDiagOffsets<DeviceType, false> {
6551 typedef DeviceType device_type;
6555 typedef Kokkos::View<size_t*, device_type> device_offsets_type;
6556 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6557 Kokkos::MemoryUnmanaged> host_offsets_type;
6559 static device_offsets_type
6560 getDeviceOffsets (
const host_offsets_type& hostOffsets)
6564 return device_offsets_type (
"offsets", hostOffsets.extent (0));
6568 copyBackIfNeeded (
const host_offsets_type& hostOffsets,
6569 const device_offsets_type& deviceOffsets)
6572 Kokkos::deep_copy (hostOffsets, deviceOffsets);
6578 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6583 typedef LocalOrdinal LO;
6584 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6585 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6586 (! this->
hasColMap (), std::runtime_error,
6587 "The graph does not yet have a column Map.");
6589 if (
static_cast<LO
> (offsets.size ()) != myNumRows) {
6593 offsets.resize (myNumRows);
6605 typedef HelpGetLocalDiagOffsets<device_type> helper_type;
6606 typedef typename helper_type::host_offsets_type host_offsets_type;
6608 host_offsets_type hostOffsets (offsets.getRawPtr (), myNumRows);
6610 auto deviceOffsets = helper_type::getDeviceOffsets (hostOffsets);
6613 helper_type::copyBackIfNeeded (hostOffsets, deviceOffsets);
6616 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6623 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6627 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& rowTransfer,
6628 const Teuchos::RCP<const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node> > & domainTransfer,
6629 const Teuchos::RCP<const map_type>& domainMap,
6630 const Teuchos::RCP<const map_type>& rangeMap,
6631 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
6637 using Teuchos::ArrayRCP;
6638 using Teuchos::ArrayView;
6639 using Teuchos::Comm;
6640 using Teuchos::ParameterList;
6643#ifdef HAVE_TPETRA_MMM_TIMINGS
6645 using Teuchos::TimeMonitor;
6648 using LO = LocalOrdinal;
6649 using GO = GlobalOrdinal;
6654 const char* prefix =
"Tpetra::CrsGraph::transferAndFillComplete: ";
6656#ifdef HAVE_TPETRA_MMM_TIMINGS
6658 if(!params.is_null()) label = params->get(
"Timer Label", label);
6659 string prefix2 = string(
"Tpetra ")+ label + std::string(
": CrsGraph TAFC ");
6660 RCP<TimeMonitor> MM =
6661 rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Pack-1"))));
6671 TEUCHOS_TEST_FOR_EXCEPTION(
6672 xferAsImport ==
nullptr && xferAsExport ==
nullptr, std::invalid_argument,
6673 prefix <<
"The 'rowTransfer' input argument must be either an Import or "
6674 "an Export, and its template parameters must match the corresponding "
6675 "template parameters of the CrsGraph.");
6682 Teuchos::RCP<const import_type> xferDomainAsImport =
6683 Teuchos::rcp_dynamic_cast<const import_type>(domainTransfer);
6684 Teuchos::RCP<const export_type> xferDomainAsExport =
6685 Teuchos::rcp_dynamic_cast<const export_type>(domainTransfer);
6687 if(! domainTransfer.is_null()) {
6689 TEUCHOS_TEST_FOR_EXCEPTION(
6690 (xferDomainAsImport.is_null() && xferDomainAsExport.is_null()), std::invalid_argument,
6691 prefix <<
"The 'domainTransfer' input argument must be either an "
6692 "Import or an Export, and its template parameters must match the "
6693 "corresponding template parameters of the CrsGraph.");
6695 TEUCHOS_TEST_FOR_EXCEPTION(
6696 ( xferAsImport !=
nullptr || ! xferDomainAsImport.is_null() ) &&
6697 (( xferAsImport !=
nullptr && xferDomainAsImport.is_null() ) ||
6698 ( xferAsImport ==
nullptr && ! xferDomainAsImport.is_null() )), std::invalid_argument,
6699 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6700 "must be of the same type (either Import or Export).");
6702 TEUCHOS_TEST_FOR_EXCEPTION(
6703 ( xferAsExport !=
nullptr || ! xferDomainAsExport.is_null() ) &&
6704 (( xferAsExport !=
nullptr && xferDomainAsExport.is_null() ) ||
6705 ( xferAsExport ==
nullptr && ! xferDomainAsExport.is_null() )), std::invalid_argument,
6706 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6707 "must be of the same type (either Import or Export).");
6714 const bool communication_needed = rowTransfer.getSourceMap()->isDistributed();
6720 bool reverseMode =
false;
6721 bool restrictComm =
false;
6722 RCP<ParameterList> graphparams;
6723 if (! params.is_null()) {
6724 reverseMode = params->get(
"Reverse Mode", reverseMode);
6725 restrictComm = params->get(
"Restrict Communicator", restrictComm);
6726 graphparams = sublist(params,
"CrsGraph");
6731 RCP<const map_type> MyRowMap = reverseMode ?
6732 rowTransfer.getSourceMap() : rowTransfer.getTargetMap();
6733 RCP<const map_type> MyColMap;
6734 RCP<const map_type> MyDomainMap = ! domainMap.is_null() ? domainMap : getDomainMap();
6735 RCP<const map_type> MyRangeMap = ! rangeMap.is_null() ? rangeMap : getRangeMap();
6736 RCP<const map_type> BaseRowMap = MyRowMap;
6737 RCP<const map_type> BaseDomainMap = MyDomainMap;
6745 if (! destGraph.is_null()) {
6756 const bool NewFlag =
6757 ! destGraph->isLocallyIndexed() && ! destGraph->isGloballyIndexed();
6758 TEUCHOS_TEST_FOR_EXCEPTION(! NewFlag, std::invalid_argument,
6759 prefix <<
"The input argument 'destGraph' is only allowed to be nonnull, "
6760 "if its graph is empty (neither locally nor globally indexed).");
6769 TEUCHOS_TEST_FOR_EXCEPTION(
6770 ! destGraph->getRowMap()->isSameAs(*MyRowMap), std::invalid_argument,
6771 prefix <<
"The (row) Map of the input argument 'destGraph' is not the "
6772 "same as the (row) Map specified by the input argument 'rowTransfer'.");
6774 TEUCHOS_TEST_FOR_EXCEPTION(
6775 ! destGraph->checkSizes(*
this), std::invalid_argument,
6776 prefix <<
"You provided a nonnull destination graph, but checkSizes() "
6777 "indicates that it is not a legal legal target for redistribution from "
6778 "the source graph (*this). This may mean that they do not have the "
6779 "same dimensions.");
6793 TEUCHOS_TEST_FOR_EXCEPTION(
6794 ! (reverseMode || getRowMap()->isSameAs(*rowTransfer.getSourceMap())),
6795 std::invalid_argument, prefix <<
6796 "rowTransfer->getSourceMap() must match this->getRowMap() in forward mode.");
6798 TEUCHOS_TEST_FOR_EXCEPTION(
6799 ! (! reverseMode || getRowMap()->isSameAs(*rowTransfer.getTargetMap())),
6800 std::invalid_argument, prefix <<
6801 "rowTransfer->getTargetMap() must match this->getRowMap() in reverse mode.");
6804 TEUCHOS_TEST_FOR_EXCEPTION(
6805 ! xferDomainAsImport.is_null() && ! xferDomainAsImport->getTargetMap()->isSameAs(*domainMap),
6806 std::invalid_argument,
6807 prefix <<
"The target map of the 'domainTransfer' input argument must be "
6808 "the same as the rebalanced domain map 'domainMap'");
6810 TEUCHOS_TEST_FOR_EXCEPTION(
6811 ! xferDomainAsExport.is_null() && ! xferDomainAsExport->getSourceMap()->isSameAs(*domainMap),
6812 std::invalid_argument,
6813 prefix <<
"The source map of the 'domainTransfer' input argument must be "
6814 "the same as the rebalanced domain map 'domainMap'");
6827 const size_t NumSameIDs = rowTransfer.getNumSameIDs();
6828 ArrayView<const LO> ExportLIDs = reverseMode ?
6829 rowTransfer.getRemoteLIDs() : rowTransfer.getExportLIDs();
6830 ArrayView<const LO> RemoteLIDs = reverseMode ?
6831 rowTransfer.getExportLIDs() : rowTransfer.getRemoteLIDs();
6832 ArrayView<const LO> PermuteToLIDs = reverseMode ?
6833 rowTransfer.getPermuteFromLIDs() : rowTransfer.getPermuteToLIDs();
6834 ArrayView<const LO> PermuteFromLIDs = reverseMode ?
6835 rowTransfer.getPermuteToLIDs() : rowTransfer.getPermuteFromLIDs();
6836 Distributor& Distor = rowTransfer.getDistributor();
6839 Teuchos::Array<int> SourcePids;
6840 Teuchos::Array<int> TargetPids;
6841 int MyPID = getComm()->getRank();
6844 RCP<const map_type> ReducedRowMap, ReducedColMap,
6845 ReducedDomainMap, ReducedRangeMap;
6846 RCP<const Comm<int> > ReducedComm;
6850 if (destGraph.is_null()) {
6851 destGraph = rcp(
new this_CRS_type(MyRowMap, 0, graphparams));
6858 ReducedRowMap = MyRowMap->removeEmptyProcesses();
6859 ReducedComm = ReducedRowMap.is_null() ?
6861 ReducedRowMap->getComm();
6862 destGraph->removeEmptyProcessesInPlace(ReducedRowMap);
6864 ReducedDomainMap = MyRowMap.getRawPtr() == MyDomainMap.getRawPtr() ?
6866 MyDomainMap->replaceCommWithSubset(ReducedComm);
6867 ReducedRangeMap = MyRowMap.getRawPtr() == MyRangeMap.getRawPtr() ?
6869 MyRangeMap->replaceCommWithSubset(ReducedComm);
6872 MyRowMap = ReducedRowMap;
6873 MyDomainMap = ReducedDomainMap;
6874 MyRangeMap = ReducedRangeMap;
6877 if (! ReducedComm.is_null()) {
6878 MyPID = ReducedComm->getRank();
6885 ReducedComm = MyRowMap->getComm();
6891#ifdef HAVE_TPETRA_MMM_TIMINGS
6893 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ImportSetup"))));
6896 RCP<const import_type> MyImporter = getImporter();
6899 bool bSameDomainMap = BaseDomainMap->isSameAs(*getDomainMap());
6901 if (! restrictComm && ! MyImporter.is_null() && bSameDomainMap ) {
6910 else if (restrictComm && ! MyImporter.is_null() && bSameDomainMap) {
6913 ivector_type SourceDomain_pids(getDomainMap(),
true);
6914 ivector_type SourceCol_pids(getColMap());
6916 SourceDomain_pids.putScalar(MyPID);
6918 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6919 SourcePids.resize(getColMap()->getLocalNumElements());
6920 SourceCol_pids.get1dCopy(SourcePids());
6922 else if (MyImporter.is_null() && bSameDomainMap) {
6924 SourcePids.resize(getColMap()->getLocalNumElements());
6925 SourcePids.assign(getColMap()->getLocalNumElements(), MyPID);
6927 else if ( ! MyImporter.is_null() &&
6928 ! domainTransfer.is_null() ) {
6935 ivector_type TargetDomain_pids(domainMap);
6936 TargetDomain_pids.putScalar(MyPID);
6939 ivector_type SourceDomain_pids(getDomainMap());
6942 ivector_type SourceCol_pids(getColMap());
6944 if (! reverseMode && ! xferDomainAsImport.is_null() ) {
6945 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6947 else if (reverseMode && ! xferDomainAsExport.is_null() ) {
6948 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6950 else if (! reverseMode && ! xferDomainAsExport.is_null() ) {
6951 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6953 else if (reverseMode && ! xferDomainAsImport.is_null() ) {
6954 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6957 TEUCHOS_TEST_FOR_EXCEPTION(
6958 true, std::logic_error,
6959 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6961 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6962 SourcePids.resize(getColMap()->getLocalNumElements());
6963 SourceCol_pids.get1dCopy(SourcePids());
6965 else if (BaseDomainMap->isSameAs(*BaseRowMap) &&
6966 getDomainMap()->isSameAs(*getRowMap())) {
6968 ivector_type TargetRow_pids(domainMap);
6969 ivector_type SourceRow_pids(getRowMap());
6970 ivector_type SourceCol_pids(getColMap());
6972 TargetRow_pids.putScalar(MyPID);
6973 if (! reverseMode && xferAsImport !=
nullptr) {
6974 SourceRow_pids.doExport(TargetRow_pids, *xferAsImport,
INSERT);
6976 else if (reverseMode && xferAsExport !=
nullptr) {
6977 SourceRow_pids.doExport(TargetRow_pids, *xferAsExport,
INSERT);
6979 else if (! reverseMode && xferAsExport !=
nullptr) {
6980 SourceRow_pids.doImport(TargetRow_pids, *xferAsExport,
INSERT);
6982 else if (reverseMode && xferAsImport !=
nullptr) {
6983 SourceRow_pids.doImport(TargetRow_pids, *xferAsImport,
INSERT);
6986 TEUCHOS_TEST_FOR_EXCEPTION(
6987 true, std::logic_error,
6988 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6990 SourceCol_pids.doImport(SourceRow_pids, *MyImporter,
INSERT);
6991 SourcePids.resize(getColMap()->getLocalNumElements());
6992 SourceCol_pids.get1dCopy(SourcePids());
6995 TEUCHOS_TEST_FOR_EXCEPTION(
6996 true, std::invalid_argument,
6997 prefix <<
"This method only allows either domainMap == getDomainMap(), "
6998 "or (domainMap == rowTransfer.getTargetMap() and getDomainMap() == getRowMap()).");
7002 size_t constantNumPackets = destGraph->constantNumberOfPackets();
7003 if (constantNumPackets == 0) {
7004 destGraph->reallocArraysForNumPacketsPerLid(ExportLIDs.size(),
7012 const size_t rbufLen = RemoteLIDs.size() * constantNumPackets;
7013 destGraph->reallocImportsIfNeeded(rbufLen,
false,
nullptr);
7018 destGraph->numExportPacketsPerLID_.modify_host();
7019 Teuchos::ArrayView<size_t> numExportPacketsPerLID =
7024 numExportPacketsPerLID, ExportLIDs,
7025 SourcePids, constantNumPackets);
7029#ifdef HAVE_TPETRA_MMM_TIMINGS
7031 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Transfer"))));
7034 if (communication_needed) {
7036 if (constantNumPackets == 0) {
7040 destGraph->numExportPacketsPerLID_.sync_host();
7041 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
7043 destGraph->numImportPacketsPerLID_.sync_host();
7044 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
7047 Distor.doReversePostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
7048 destGraph->numImportPacketsPerLID_.view_host());
7049 size_t totalImportPackets = 0;
7051 totalImportPackets += numImportPacketsPerLID[i];
7056 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
7057 destGraph->imports_.modify_host();
7058 auto hostImports = destGraph->imports_.view_host();
7061 destGraph->exports_.sync_host();
7062 auto hostExports = destGraph->exports_.view_host();
7063 Distor.doReversePostsAndWaits(hostExports,
7064 numExportPacketsPerLID,
7066 numImportPacketsPerLID);
7069 destGraph->imports_.modify_host();
7070 auto hostImports = destGraph->imports_.view_host();
7073 destGraph->exports_.sync_host();
7074 auto hostExports = destGraph->exports_.view_host();
7075 Distor.doReversePostsAndWaits(hostExports,
7081 if (constantNumPackets == 0) {
7085 destGraph->numExportPacketsPerLID_.sync_host();
7086 destGraph->numImportPacketsPerLID_.sync_host();
7087 Distor.doPostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
7088 destGraph->numImportPacketsPerLID_.view_host());
7090 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
7092 size_t totalImportPackets = 0;
7094 totalImportPackets += numImportPacketsPerLID[i];
7099 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
7100 destGraph->imports_.modify_host();
7101 auto hostImports = destGraph->imports_.view_host();
7104 destGraph->exports_.sync_host();
7105 auto hostExports = destGraph->exports_.view_host();
7106 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
7108 Distor.doPostsAndWaits(hostExports, numExportPacketsPerLID, hostImports, numImportPacketsPerLID);
7111 destGraph->imports_.modify_host();
7112 auto hostImports = destGraph->imports_.view_host();
7115 destGraph->exports_.sync_host();
7116 auto hostExports = destGraph->exports_.view_host();
7117 Distor.doPostsAndWaits(hostExports, constantNumPackets, hostImports);
7126#ifdef HAVE_TPETRA_MMM_TIMINGS
7128 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-1"))));
7132 destGraph->numImportPacketsPerLID_.sync_host();
7133 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
7135 destGraph->imports_.sync_host();
7136 Teuchos::ArrayView<const packet_type> hostImports =
7140 numImportPacketsPerLID,
7141 constantNumPackets,
INSERT,
7142 NumSameIDs, PermuteToLIDs, PermuteFromLIDs);
7143 size_t N = BaseRowMap->getLocalNumElements();
7146 ArrayRCP<size_t> CSR_rowptr(N+1);
7147 ArrayRCP<GO> CSR_colind_GID;
7148 ArrayRCP<LO> CSR_colind_LID;
7149 CSR_colind_GID.resize(mynnz);
7153 if (
typeid(LO) ==
typeid(GO)) {
7154 CSR_colind_LID = Teuchos::arcp_reinterpret_cast<LO>(CSR_colind_GID);
7157 CSR_colind_LID.resize(mynnz);
7166 numImportPacketsPerLID, constantNumPackets,
7167 INSERT, NumSameIDs, PermuteToLIDs,
7168 PermuteFromLIDs, N, mynnz, MyPID,
7169 CSR_rowptr(), CSR_colind_GID(),
7170 SourcePids(), TargetPids);
7175#ifdef HAVE_TPETRA_MMM_TIMINGS
7177 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-2"))));
7182 Teuchos::Array<int> RemotePids;
7187 TargetPids, RemotePids,
7194 ReducedColMap = (MyRowMap.getRawPtr() == MyColMap.getRawPtr()) ?
7196 MyColMap->replaceCommWithSubset(ReducedComm);
7197 MyColMap = ReducedColMap;
7201 destGraph->replaceColMap(MyColMap);
7208 if (ReducedComm.is_null()) {
7215 if ((! reverseMode && xferAsImport !=
nullptr) ||
7216 (reverseMode && xferAsExport !=
nullptr)) {
7220 else if ((! reverseMode && xferAsExport !=
nullptr) ||
7221 (reverseMode && xferAsImport !=
nullptr)) {
7224 if (CSR_rowptr[N] != mynnz) {
7225 CSR_colind_LID.resize(CSR_rowptr[N]);
7229 TEUCHOS_TEST_FOR_EXCEPTION(
7230 true, std::logic_error,
7231 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
7239 destGraph->setAllIndices(CSR_rowptr, CSR_colind_LID);
7245 Teuchos::ParameterList esfc_params;
7246#ifdef HAVE_TPETRA_MMM_TIMINGS
7248 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"CreateImporter"))));
7250 RCP<import_type> MyImport = rcp(
new import_type(MyDomainMap, MyColMap, RemotePids));
7251#ifdef HAVE_TPETRA_MMM_TIMINGS
7253 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ESFC"))));
7255 esfc_params.set(
"Timer Label",prefix + std::string(
"TAFC"));
7257 if(!params.is_null())
7258 esfc_params.set(
"compute global constants",params->get(
"compute global constants",
true));
7260 destGraph->expertStaticFillComplete(MyDomainMap, MyRangeMap,
7261 MyImport, Teuchos::null, rcp(&esfc_params,
false));
7265 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7270 const Teuchos::RCP<const map_type>& domainMap,
7271 const Teuchos::RCP<const map_type>& rangeMap,
7272 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7274 transferAndFillComplete(destGraph, importer, Teuchos::null, domainMap, rangeMap, params);
7277 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7283 const Teuchos::RCP<const map_type>& domainMap,
7284 const Teuchos::RCP<const map_type>& rangeMap,
7285 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7287 transferAndFillComplete(destGraph, rowImporter, Teuchos::rcpFromRef(domainImporter), domainMap, rangeMap, params);
7290 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7295 const Teuchos::RCP<const map_type>& domainMap,
7296 const Teuchos::RCP<const map_type>& rangeMap,
7297 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7299 transferAndFillComplete(destGraph, exporter, Teuchos::null, domainMap, rangeMap, params);
7302 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7308 const Teuchos::RCP<const map_type>& domainMap,
7309 const Teuchos::RCP<const map_type>& rangeMap,
7310 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7312 transferAndFillComplete(destGraph, rowExporter, Teuchos::rcpFromRef(domainExporter), domainMap, rangeMap, params);
7316 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7319 swap(CrsGraph<LocalOrdinal, GlobalOrdinal, Node>& graph)
7321 std::swap(graph.need_sync_host_uvm_access, this->need_sync_host_uvm_access);
7323 std::swap(graph.
rowMap_, this->rowMap_);
7324 std::swap(graph.
colMap_, this->colMap_);
7325 std::swap(graph.
rangeMap_, this->rangeMap_);
7326 std::swap(graph.
domainMap_, this->domainMap_);
7328 std::swap(graph.
importer_, this->importer_);
7329 std::swap(graph.
exporter_, this->exporter_);
7338 std::swap(graph.rowPtrsPacked_dev_, this->rowPtrsPacked_dev_);
7339 std::swap(graph.rowPtrsPacked_host_, this->rowPtrsPacked_host_);
7341 std::swap(graph.rowPtrsUnpacked_dev_, this->rowPtrsUnpacked_dev_);
7342 std::swap(graph.rowPtrsUnpacked_host_, this->rowPtrsUnpacked_host_);
7343 std::swap(graph.packedUnpackedRowPtrsMatch_, this->packedUnpackedRowPtrsMatch_);
7353 std::swap(graph.indicesAreAllocated_, this->indicesAreAllocated_);
7354 std::swap(graph.indicesAreLocal_, this->indicesAreLocal_);
7355 std::swap(graph.indicesAreGlobal_, this->indicesAreGlobal_);
7356 std::swap(graph.fillComplete_, this->fillComplete_);
7361 std::swap(graph.haveLocalOffRankOffsets_, this->haveLocalOffRankOffsets_);
7367 std::swap(graph.
nonlocals_, this->nonlocals_);
7371 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7374 isIdenticalTo(
const CrsGraph<LocalOrdinal, GlobalOrdinal, Node> & graph)
const
7376 auto compare_nonlocals = [&] (
const nonlocals_type & m1,
const nonlocals_type & m2) {
7378 output = m1.size() == m2.size() ? output :
false;
7379 for(
auto & it_m: m1)
7381 size_t key = it_m.first;
7382 output = m2.find(key) != m2.end() ? output :
false;
7385 auto v1 = m1.find(key)->second;
7386 auto v2 = m2.find(key)->second;
7387 std::sort(v1.begin(), v1.end());
7388 std::sort(v2.begin(), v2.end());
7390 output = v1.size() == v2.size() ? output :
false;
7391 for(
size_t i=0; output && i<v1.size(); i++)
7393 output = v1[i]==v2[i] ? output :
false;
7402 output = this->
rowMap_->isSameAs( *(graph.
rowMap_) ) ? output :
false;
7403 output = this->
colMap_->isSameAs( *(graph.
colMap_) ) ? output :
false;
7416 output = this->indicesAreAllocated_ == graph.indicesAreAllocated_ ? output :
false;
7417 output = this->indicesAreLocal_ == graph.indicesAreLocal_ ? output :
false;
7418 output = this->indicesAreGlobal_ == graph.indicesAreGlobal_ ? output :
false;
7419 output = this->fillComplete_ == graph.fillComplete_ ? output :
false;
7424 output = this->haveLocalOffRankOffsets_ == graph.haveLocalOffRankOffsets_ ? output :
false;
7453 output = rowPtrsThis .extent(0) == rowPtrsGraph.extent(0) ? output :
false;
7454 for(
size_t i=0; output && i< rowPtrsThis.extent(0); i++)
7455 output = rowPtrsThis(i) == rowPtrsGraph(i) ? output :
false;
7464 for(
size_t i=0; output && i < indThis.extent(0); i++)
7465 output = indThis(i) == indGraph(i) ? output :
false;
7472 auto indtThis = this->
gblInds_wdv.getHostView(Access::ReadOnly);
7473 auto indtGraph = graph.
gblInds_wdv.getHostView(Access::ReadOnly);
7474 for(
size_t i=0; output && i<indtThis.extent(0); i++)
7475 output = indtThis(i) == indtGraph(i) ? output :
false;
7494 output = thisLclGraph.row_map.extent(0) == graphLclGraph.row_map.extent(0)
7496 if(output && thisLclGraph.row_map.extent(0) > 0)
7498 auto lclGraph_rowmap_host_this = thisLclGraph.row_map;
7499 auto lclGraph_rowmap_host_graph = graphLclGraph.row_map;
7500 for (
size_t i=0; output && i < lclGraph_rowmap_host_this.extent(0); i++)
7501 output = lclGraph_rowmap_host_this(i) == lclGraph_rowmap_host_graph(i)
7505 output = thisLclGraph.entries.extent(0) == graphLclGraph.entries.extent(0)
7507 if(output && thisLclGraph.entries.extent(0) > 0)
7509 auto lclGraph_entries_host_this = thisLclGraph.entries;
7510 auto lclGraph_entries_host_graph = graphLclGraph.entries;
7511 for (
size_t i=0; output && i < lclGraph_entries_host_this.extent(0); i++)
7512 output = lclGraph_entries_host_this(i) == lclGraph_entries_host_graph(i)
7517 thisLclGraph.row_block_offsets.extent(0) ==
7518 graphLclGraph.row_block_offsets.extent(0) ? output :
false;
7519 if(output && thisLclGraph.row_block_offsets.extent(0) > 0)
7521 auto lclGraph_rbo_host_this = thisLclGraph.row_block_offsets;
7522 auto lclGraph_rbo_host_graph = graphLclGraph.row_block_offsets;
7523 for (
size_t i=0; output && i < lclGraph_rbo_host_this.extent(0); i++)
7524 output = lclGraph_rbo_host_this(i) == lclGraph_rbo_host_graph(i)
7546#define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7548 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7549 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7550 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7551 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7552 CrsGraph<LO,GO,NODE>::node_type>& importer, \
7553 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7554 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7555 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7556 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7557 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7558 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7559 const Teuchos::RCP<Teuchos::ParameterList>& params);
7561#define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7563 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7564 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7565 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7566 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7567 CrsGraph<LO,GO,NODE>::node_type>& rowImporter, \
7568 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7569 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7570 CrsGraph<LO,GO,NODE>::node_type>& domainImporter, \
7571 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7572 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7573 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
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> >& rangeMap, \
7577 const Teuchos::RCP<Teuchos::ParameterList>& params);
7580#define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7582 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7583 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7584 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7585 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7586 CrsGraph<LO,GO,NODE>::node_type>& exporter, \
7587 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7588 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7589 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7590 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7591 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7592 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7593 const Teuchos::RCP<Teuchos::ParameterList>& params);
7595#define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7597 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7598 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7599 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7600 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7601 CrsGraph<LO,GO,NODE>::node_type>& rowExporter, \
7602 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7603 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7604 CrsGraph<LO,GO,NODE>::node_type>& domainExporter, \
7605 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7606 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7607 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
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> >& rangeMap, \
7611 const Teuchos::RCP<Teuchos::ParameterList>& params);
7614#define TPETRA_CRSGRAPH_INSTANT( LO, GO, NODE ) \
7615 template class CrsGraph<LO, GO, NODE>; \
7616 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7617 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7618 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7619 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE)
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
Declare and define Tpetra::Details::copyOffsets, an implementation detail of Tpetra (in particular,...
Functions for manipulating CRS arrays.
Declaration of a function that prints strings from each process.
Declaration and definition of Tpetra::Details::getEntryOnHost.
Utility functions for packing and unpacking sparse matrix entries.
void lowCommunicationMakeColMapAndReindex(const Teuchos::ArrayView< const size_t > &rowPointers, const Teuchos::ArrayView< LocalOrdinal > &columnIndices_LID, const Teuchos::ArrayView< GlobalOrdinal > &columnIndices_GID, const Teuchos::RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &domainMap, const Teuchos::ArrayView< const int > &owningPids, Teuchos::Array< int > &remotePids, Teuchos::RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &colMap)
lowCommunicationMakeColMapAndReindex
void sortAndMergeCrsEntries(const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< Ordinal > &CRS_colind, const Teuchos::ArrayView< Scalar > &CRS_vals)
Sort and merge the entries of the (raw CSR) matrix by column index within each row.
void sortCrsEntries(const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< Ordinal > &CRS_colind, const Teuchos::ArrayView< Scalar > &CRS_vals)
Sort the entries of the (raw CSR) matrix by column index within each row.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects.
void getPids(const Tpetra::Import< LocalOrdinal, GlobalOrdinal, Node > &Importer, Teuchos::Array< int > &pids, bool use_minus_one_for_local)
Like getPidGidPairs, but just gets the PIDs, ordered by the column Map.
Stand-alone utility functions and macros.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
bool isMerged() const
Whether duplicate column indices in each row have been merged.
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
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...
global_size_t globalMaxNumRowEntries_
Global maximum of the number of entries in each row.
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...
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...
size_t getNumEntriesInLocalRow(local_ordinal_type localRow) const override
Get the number of entries in the given row (local index).
Teuchos::RCP< const map_type > getColMap() const override
Returns the Map that describes the column distribution in this graph.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Default parameter list suitable for validation.
Details::EStorageStatus storageStatus_
Status of the graph's storage, when not in a fill-complete state.
::Tpetra::Import< LocalOrdinal, GlobalOrdinal, Node > import_type
The Import specialization used by this class.
global_ordinal_type packet_type
Type of each entry of the DistObject communication buffer.
GlobalOrdinal global_ordinal_type
The type of the graph's global indices.
void insertGlobalIndicesIntoNonownedRows(const global_ordinal_type gblRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Implementation of insertGlobalIndices for nonowned rows.
Teuchos::RCP< const map_type > rangeMap_
The Map describing the range of the (matrix corresponding to the) graph.
std::pair< size_t, std::string > makeIndicesLocal(const bool verbose=false)
Convert column indices from global to local.
local_inds_device_view_type getLocalIndicesDevice() const
Get a device view of the packed column indicies.
global_size_t getGlobalNumEntries() const override
Returns the global number of entries in the graph.
bool isIdenticalTo(const CrsGraph< LocalOrdinal, GlobalOrdinal, Node > &graph) const
Create a cloned CrsGraph for a different Node type.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
Returns the communicator.
local_inds_wdv_type lclIndsUnpacked_wdv
Local ordinals of column indices for all rows Valid when isLocallyIndexed is true If OptimizedStorage...
void globalAssemble()
Communicate nonlocal contributions to other processes.
RowInfo getRowInfoFromGlobalRowIndex(const global_ordinal_type gblRow) const
Get information about the locally owned row with global index gblRow.
void getLocalDiagOffsets(const Kokkos::View< size_t *, device_type, Kokkos::MemoryUnmanaged > &offsets) const
Get offsets of the diagonal entries in the graph.
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.
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.
global_inds_wdv_type gblInds_wdv
Global ordinals of column indices for all rows.
size_t nodeMaxNumRowEntries_
Local maximum of the number of entries in each row.
size_t sortAndMergeRowIndices(const RowInfo &rowInfo, const bool sorted, const bool merged)
Sort and merge duplicate column indices in the given row.
Teuchos::RCP< const import_type > importer_
The Import from the domain Map to the column Map.
num_row_entries_type k_numRowEntries_
The number of local entries in each locally owned row.
const row_ptrs_device_view_type & getRowPtrsUnpackedDevice() const
Get the unpacked row pointers on device.
size_t numAllocForAllRows_
The maximum number of entries to allow in each locally owned row.
bool hasColMap() const override
Whether the graph has a column Map.
LocalOrdinal local_ordinal_type
The type of the graph's local indices.
std::string description() const override
Return a one-line human-readable description of this object.
bool isStorageOptimized() const
Returns true if storage has been optimized.
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.
void removeLocalIndices(local_ordinal_type localRow)
Remove all graph indices from the specified local row.
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 getGlobalNumRows() const override
Returns the number of global rows in the graph.
Teuchos::RCP< const map_type > getDomainMap() const override
Returns the Map associated with the domain of this graph.
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 computeLocalConstants()
Compute local constants, if they have not yet been computed.
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.
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 setParameterList(const Teuchos::RCP< Teuchos::ParameterList > ¶ms) override
Set the given list of parameters (must be nonnull).
void resumeFill(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Resume fill operations.
size_t insertIndices(RowInfo &rowInfo, const SLocalGlobalViews &newInds, const ELocalGlobal lg, const ELocalGlobal I)
Insert indices into the given row.
typename Node::device_type device_type
This class' Kokkos device type.
void insertGlobalIndicesFiltered(const local_ordinal_type lclRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Like insertGlobalIndices(), but with column Map filtering.
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
RowInfo getRowInfo(const local_ordinal_type myRow) const
Get information about the locally owned row with local index myRow.
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...
typename local_graph_device_type::HostMirror local_graph_host_type
The type of the part of the sparse graph on each MPI process.
Teuchos::RCP< const map_type > colMap_
The Map describing the distribution of columns of the graph.
bool noRedundancies_
Whether the graph's indices are non-redundant (merged) in each row, on this process.
row_ptrs_host_view_type getLocalRowPtrsHost() const
Get a host view of the packed row offsets.
bool isSorted() const
Whether graph indices in all rows are known to be sorted.
typename dist_object_type::buffer_device_type buffer_device_type
Kokkos::Device specialization for communication buffers.
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.
void insertLocalIndices(const local_ordinal_type localRow, const Teuchos::ArrayView< const local_ordinal_type > &indices)
Insert local indices into the graph.
local_inds_host_view_type getLocalIndicesHost() const
Get a host view of the packed column indicies.
bool supportsRowViews() const override
Whether this class implements getLocalRowView() and getGlobalRowView() (it does).
size_t getNumEntriesInGlobalRow(global_ordinal_type globalRow) const override
Returns the current number of entries on this node in the specified global row.
bool isFillComplete() const override
Whether fillComplete() has been called and the graph is in compute mode.
void setDomainRangeMaps(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap)
void swap(CrsGraph< local_ordinal_type, global_ordinal_type, Node > &graph)
Swaps the data from *this with the data and maps from graph.
::Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > map_type
The Map specialization used by this class.
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.
const row_ptrs_host_view_type & getRowPtrsUnpackedHost() const
Get the unpacked row pointers on host. Lazily make a copy from device.
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.
void makeColMap(Teuchos::Array< int > &remotePIDs)
Make and set the graph's column Map.
bool haveGlobalConstants_
Whether all processes have computed global constants.
size_t getGlobalMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, over all processes in the graph's communicator.
void checkInternalState() const
Throw an exception if the internal state is not consistent.
Teuchos::RCP< const map_type > getRangeMap() const override
Returns the Map associated with the domain of this graph.
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().
bool sortGhostsAssociatedWithEachProcessor_
Whether to require makeColMap() (and therefore fillComplete()) to order column Map GIDs associated wi...
size_t getNumAllocatedEntriesInGlobalRow(global_ordinal_type globalRow) const
Current number of allocated entries in the given row on the calling (MPI) process,...
Teuchos::RCP< const export_type > getExporter() const override
Returns the exporter associated with this graph.
typename device_type::execution_space execution_space
This class' Kokkos execution space.
void makeImportExport(Teuchos::Array< int > &remotePIDs, const bool useRemotePIDs)
Make the Import and Export objects, if needed.
global_ordinal_type getIndexBase() const override
Returns the index base for global indices for this graph.
row_ptrs_device_view_type getLocalRowPtrsDevice() const
Get a device view of the packed row offsets.
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.
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...
bool isFillActive() const
Whether resumeFill() has been called and the graph is in edit mode.
Teuchos::RCP< const map_type > getRowMap() const override
Returns the Map that describes the row distribution in this graph.
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.
global_size_t globalNumEntries_
Global number of entries in the graph.
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.
::Tpetra::Export< LocalOrdinal, GlobalOrdinal, Node > export_type
The Export specialization used by this class.
size_t getLocalNumEntries() const override
The local number of entries in the graph.
Teuchos::RCP< const import_type > getImporter() const override
Returns the importer associated with this graph.
local_inds_wdv_type lclIndsPacked_wdv
Local ordinals of column indices for all rows Valid when isLocallyIndexed is true Built during fillCo...
Teuchos::RCP< const map_type > domainMap_
The Map describing the domain of the (matrix corresponding to the) graph.
const row_ptrs_host_view_type & getRowPtrsPackedHost() const
Get the packed row pointers on host. Lazily make a copy from device.
size_t getLocalNumCols() const override
Returns the number of columns connected to the locally owned rows of this graph.
nonlocals_type nonlocals_
Nonlocal data given to insertGlobalIndices.
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 getLocalOffRankOffsets(offset_device_view_type &offsets) const
Get offsets of the off-rank entries in the graph.
global_size_t getGlobalNumCols() const override
Returns the number of global columns in the graph.
bool indicesAreSorted_
Whether the graph's indices are sorted in each row, on this process.
Node node_type
This class' Kokkos Node type.
Teuchos::RCP< const export_type > exporter_
The Export from the row Map to the range Map.
void insertGlobalIndices(const global_ordinal_type globalRow, const Teuchos::ArrayView< const global_ordinal_type > &indices)
Insert global indices into the graph.
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...
void replaceDomainMap(const Teuchos::RCP< const map_type > &newDomainMap)
Replace the current domain Map with the given objects.
Kokkos::View< constsize_t *, device_type >::HostMirror k_numAllocPerRow_
The maximum number of entries to allow in each locally owned row, per row.
void computeGlobalConstants()
Compute global constants, if they have not yet been computed.
size_t getNumAllocatedEntriesInLocalRow(local_ordinal_type localRow) const
Current number of allocated entries in the given row on the calling (MPI) process,...
offset_device_view_type k_offRankOffsets_
The offsets for off-rank entries.
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.
void setLocallyModified()
Report that we made a local modification to its structure.
size_t getLocalAllocationSize() const
The local number of indices allocated for the graph, over all rows on the calling (MPI) process.
void replaceRangeMap(const Teuchos::RCP< const map_type > &newRangeMap)
Replace the current Range Map with the given objects.
Teuchos::RCP< const map_type > rowMap_
The Map describing the distribution of rows of the graph.
const row_ptrs_device_view_type & getRowPtrsPackedDevice() const
Get the packed row pointers on device.
virtual void removeEmptyProcessesInPlace(const Teuchos::RCP< const map_type > &newMap) override
Remove processes owning zero rows from the Maps and their communicator.
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.
bool isGloballyIndexed() const override
Whether the graph's column indices are stored as global indices.
bool isLocallyIndexed() const override
Whether the graph's column indices are stored as local indices.
size_t getLocalMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, on this process.
virtual bool checkSizes(const SrcDistObject &source) override
Compare the source and target (this) objects for compatibility.
local_graph_device_type getLocalGraphDevice() const
Get the local graph.
size_t getLocalNumRows() const override
Returns the number of graph rows owned on the calling node.
void replaceColMap(const Teuchos::RCP< const map_type > &newColMap)
Replace the graph's current column Map with the given Map.
bool haveLocalConstants_
Whether this process has computed local constants.
void getGlobalRowView(GlobalOrdinal GlobalRow, global_inds_host_view_type &indices, values_host_view_type &values) const override
Get a constant, nonpersisting view of a row of this matrix, using global row and column indices.
static bool debug()
Whether Tpetra is in debug mode.
static bool verbose()
Whether Tpetra is in verbose mode.
static size_t verbosePrintCountThreshold()
Number of entries below which arrays, lists, etc. will be printed in debug mode.
"Local" part of Map suitable for Kokkos kernels.
void doImport(const SrcDistObject &source, const Import< LocalOrdinal, GlobalOrdinal, Node > &importer, const CombineMode CM, const bool restrictedMode=false)
DistObject(const Teuchos::RCP< const map_type > &map)
Teuchos::RCP< const map_type > map_
void doExport(const SrcDistObject &source, const Export< LocalOrdinal, GlobalOrdinal, Node > &exporter, const CombineMode CM, const bool restrictedMode=false)
virtual std::string description() const
virtual Teuchos::RCP< const map_type > getMap() const
Sets up and executes a communication plan for a Tpetra DistObject.
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.
local_ordinal_type getLocalElement(global_ordinal_type globalIndex) const
The local index corresponding to the given global index.
bool isNodeGlobalElement(global_ordinal_type globalIndex) const
Whether the given global index is owned by this Map on the calling process.
local_map_type getLocalMap() const
Get the local Map for Kokkos kernels.
An abstract interface for graphs accessed by rows.
virtual bool isFillComplete() const =0
Whether fillComplete() has been called (without an intervening resumeFill()).
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRowMap() const =0
The Map that describes this graph's distribution of rows over processes.
virtual void getGlobalRowCopy(const GlobalOrdinal gblRow, nonconst_global_inds_host_view_type &gblColInds, size_t &numColInds) const =0
Get a copy of the global column indices in a given row of the graph.
virtual size_t getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const =0
Returns the current number of entries on this node in the specified global row.
Abstract base class for objects that can be the source of an Import or Export operation.
A distributed dense vector.
Implementation details of Tpetra.
Nonmember function that computes a residual Computes R = B - A * X.
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....
void verbosePrintArray(std::ostream &out, const ArrayType &x, const char name[], const size_t maxNumToPrint)
Print min(x.size(), maxNumToPrint) entries of x.
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.
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 disableWDVTracking()
Disable WrappedDualView reference-count tracking and syncing. Call this before entering a host-parall...
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.
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.
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.
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.
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...
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.
std::unique_ptr< std::string > createPrefix(const int myRank, const char prefix[])
Create string prefix for each line of verbose output.
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const ExecutionSpace &execSpace, const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
OffsetsViewType::non_const_value_type computeOffsetsFromConstantCount(const OffsetsViewType &ptr, const CountType count)
Compute offsets from a constant count.
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.
int makeColMap(Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &colMap, Teuchos::Array< int > &remotePIDs, const Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &domMap, const RowGraph< LO, GO, NT > &graph, const bool sortEachProcsGids=true, std::ostream *errStrm=NULL)
Make the graph's column Map.
void enableWDVTracking()
Enable WrappedDualView reference-count tracking and syncing. Call this after exiting a host-parallel ...
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.
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,...
Namespace Tpetra contains the class and methods constituting the Tpetra library.
Teuchos_Ordinal Array_size_type
Size type for Teuchos Array objects.
size_t global_size_t
Global size_t object.
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,...
CombineMode
Rule for combining data in an Import or Export.
@ INSERT
Insert new values that don't currently exist.
Traits class for packing / unpacking data of type T.
Allocation information for a locally owned row in a CrsGraph or CrsMatrix.