10#ifndef TPETRA_CRSGRAPH_DEF_HPP
11#define TPETRA_CRSGRAPH_DEF_HPP
17#include "Teuchos_Assert.hpp"
19#ifdef KOKKOS_ENABLE_SYCL
20#include <sycl/sycl.hpp>
27#include "Tpetra_Details_getGraphDiagOffsets.hpp"
28#include "Tpetra_Details_getGraphOffRankOffsets.hpp"
29#include "Tpetra_Details_makeColMap.hpp"
33#include "Tpetra_Distributor.hpp"
34#include "Teuchos_SerialDenseMatrix.hpp"
35#include "Tpetra_Vector.hpp"
38#include "Tpetra_Details_packCrsGraph.hpp"
39#include "Tpetra_Details_unpackCrsGraphAndCombine.hpp"
40#include "Tpetra_Details_CrsPadding.hpp"
55template <
class MapIter>
56void verbosePrintMap(std::ostream& out,
60 const char mapName[]) {
61 using ::Tpetra::Details::Behavior;
64 out << mapName <<
": {";
65 const size_t maxNumToPrint =
67 if (maxNumToPrint == 0) {
72 const size_t numToPrint = numEnt > maxNumToPrint ? maxNumToPrint : numEnt;
74 for (MapIter it = beg; it != end; ++it) {
75 out <<
"(" << (*it).first <<
", ";
79 if (count +
size_t(1) < numToPrint) {
91template <
class LO,
class GO,
class Node>
94 std::vector<GO>& gblColIndsStorage,
95 const RowGraph<LO, GO, Node>& graph,
97 size_t origNumEnt = graph.getNumEntriesInGlobalRow(gblRowInd);
98 if (gblColIndsStorage.size() < origNumEnt) {
99 gblColIndsStorage.resize(origNumEnt);
101 typename CrsGraph<LO, GO, Node>::nonconst_global_inds_host_view_type gblColInds(gblColIndsStorage.data(),
103 graph.getGlobalRowCopy(gblRowInd, gblColInds, origNumEnt);
104 Teuchos::ArrayView<GO> retval(gblColIndsStorage.data(), origNumEnt);
108template <
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
109class ConvertColumnIndicesFromGlobalToLocal {
111 ConvertColumnIndicesFromGlobalToLocal(const ::Kokkos::View<LO*, DT>& lclColInds,
112 const ::Kokkos::View<const GO*, DT>& gblColInds,
113 const ::Kokkos::View<const OffsetType*, DT>& ptr,
114 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
115 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt)
116 : lclColInds_(lclColInds)
117 , gblColInds_(gblColInds)
119 , lclColMap_(lclColMap)
120 , numRowEnt_(numRowEnt) {}
123 operator()(
const LO& lclRow, OffsetType& curNumBad)
const {
124 const OffsetType offset = ptr_(lclRow);
128 const LO numEnt =
static_cast<LO
>(numRowEnt_(lclRow));
129 for (LO j = 0; j < numEnt; ++j) {
130 const GO gid = gblColInds_(offset + j);
131 const LO lid = lclColMap_.getLocalElement(gid);
132 lclColInds_(offset + j) = lid;
133 if (lid == ::Tpetra::Details::OrdinalTraits<LO>::invalid()) {
140 run(const ::Kokkos::View<LO*, DT>& lclColInds,
141 const ::Kokkos::View<const GO*, DT>& gblColInds,
142 const ::Kokkos::View<const OffsetType*, DT>& ptr,
143 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
144 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt) {
145 typedef ::Kokkos::RangePolicy<typename DT::execution_space, LO> range_type;
146 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> functor_type;
148 const LO lclNumRows = ptr.extent(0) == 0 ?
static_cast<LO
>(0) : static_cast<LO>(ptr.extent(0) - 1);
149 OffsetType numBad = 0;
151 ::Kokkos::parallel_reduce(range_type(0, lclNumRows),
152 functor_type(lclColInds, gblColInds, ptr,
153 lclColMap, numRowEnt),
159 ::Kokkos::View<LO*, DT> lclColInds_;
160 ::Kokkos::View<const GO*, DT> gblColInds_;
161 ::Kokkos::View<const OffsetType*, DT> ptr_;
162 ::Tpetra::Details::LocalMap<LO, GO, DT> lclColMap_;
163 ::Kokkos::View<const NumEntType*, DT> numRowEnt_;
182template <
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
185 const Kokkos::View<const GO*, DT>& gblColInds,
186 const Kokkos::View<const OffsetType*, DT>& ptr,
188 const Kokkos::View<const NumEntType*, DT>& numRowEnt) {
189 using Impl::ConvertColumnIndicesFromGlobalToLocal;
190 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> impl_type;
191 return impl_type::run(lclColInds, gblColInds, ptr, lclColMap, numRowEnt);
194template <
class ViewType,
class LO>
197 MaxDifference(
const ViewType& ptr)
200 KOKKOS_INLINE_FUNCTION
void init(LO& dst)
const {
204 KOKKOS_INLINE_FUNCTION
void
205 join(LO& dst,
const LO& src)
const {
206 dst = (src > dst) ? src : dst;
209 KOKKOS_INLINE_FUNCTION
void
210 operator()(
const LO lclRow, LO& maxNumEnt)
const {
211 const LO numEnt =
static_cast<LO
>(ptr_(lclRow + 1) - ptr_(lclRow));
212 maxNumEnt = (numEnt > maxNumEnt) ? numEnt : maxNumEnt;
216 typename ViewType::const_type ptr_;
219template <
class ViewType,
class LO>
220typename ViewType::non_const_value_type
221maxDifference(
const char kernelLabel[],
223 const LO lclNumRows) {
224 if (lclNumRows == 0) {
227 return static_cast<LO
>(0);
229 using execution_space =
typename ViewType::execution_space;
230 using range_type = Kokkos::RangePolicy<execution_space, LO>;
232 Kokkos::parallel_reduce(kernelLabel,
233 range_type(0, lclNumRows),
234 MaxDifference<ViewType, LO>(ptr),
242template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
248template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
254template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
255CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
256 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
257 const size_t maxNumEntriesPerRow,
258 const Teuchos::RCP<Teuchos::ParameterList>& params)
259 : dist_object_type(rowMap)
262 const char tfecfFuncName[] =
263 "CrsGraph(rowMap,maxNumEntriesPerRow,params): ";
265 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid(),
266 std::invalid_argument,
267 "The allocation hint maxNumEntriesPerRow must be "
268 "a valid size_t value, which in this case means it must not be "
269 "Teuchos::OrdinalTraits<size_t>::invalid().");
274template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
275CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
276 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
277 const Teuchos::RCP<const map_type>& colMap,
278 const size_t maxNumEntriesPerRow,
279 const Teuchos::RCP<Teuchos::ParameterList>& params)
280 : dist_object_type(rowMap)
284 const char tfecfFuncName[] =
285 "CrsGraph(rowMap,colMap,maxNumEntriesPerRow,params): ";
287 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
288 maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid(),
289 std::invalid_argument,
290 "The allocation hint maxNumEntriesPerRow must be "
291 "a valid size_t value, which in this case means it must not be "
292 "Teuchos::OrdinalTraits<size_t>::invalid().");
297template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
298CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
299 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
300 const Teuchos::ArrayView<const size_t>& numEntPerRow,
301 const Teuchos::RCP<Teuchos::ParameterList>& params)
302 : dist_object_type(rowMap)
305 const char tfecfFuncName[] =
306 "CrsGraph(rowMap,numEntPerRow,params): ";
309 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
310 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
311 static_cast<size_t>(numEntPerRow.size()) != lclNumRows,
312 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size() <<
" != the local number of rows " << lclNumRows <<
" as specified by "
313 "the input row Map.");
316 for (
size_t r = 0; r < lclNumRows; ++r) {
317 const size_t curRowCount = numEntPerRow[r];
318 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
319 std::invalid_argument,
"numEntPerRow(" << r <<
") "
320 "specifies an invalid number of entries "
321 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
329 typedef typename out_view_type::non_const_type nc_view_type;
330 typedef Kokkos::View<
const size_t*,
331 typename nc_view_type::array_layout,
333 Kokkos::MemoryUnmanaged>
335 in_view_type numAllocPerRowIn(numEntPerRow.getRawPtr(), lclNumRows);
336 nc_view_type numAllocPerRowOut(
"Tpetra::CrsGraph::numAllocPerRow",
339 using exec_space =
typename nc_view_type::execution_space;
340 Kokkos::deep_copy(exec_space(), numAllocPerRowOut, numAllocPerRowIn);
347template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
348CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
349 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
350 const Kokkos::DualView<const size_t*, device_type>& numEntPerRow,
351 const Teuchos::RCP<Teuchos::ParameterList>& params)
352 : dist_object_type(rowMap)
356 const char tfecfFuncName[] =
357 "CrsGraph(rowMap,numEntPerRow,params): ";
360 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
361 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
362 static_cast<size_t>(numEntPerRow.extent(0)) != lclNumRows,
363 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.extent(0) <<
" != the local number of rows " << lclNumRows <<
" as specified by "
364 "the input row Map.");
367 for (
size_t r = 0; r < lclNumRows; ++r) {
368 const size_t curRowCount = numEntPerRow.view_host()(r);
369 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
370 std::invalid_argument,
"numEntPerRow(" << r <<
") "
371 "specifies an invalid number of entries "
372 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
380template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
381CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
382 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
383 const Teuchos::RCP<const map_type>& colMap,
384 const Kokkos::DualView<const size_t*, device_type>& numEntPerRow,
385 const Teuchos::RCP<Teuchos::ParameterList>& params)
386 : dist_object_type(rowMap)
391 const char tfecfFuncName[] =
392 "CrsGraph(rowMap,colMap,numEntPerRow,params): ";
395 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
396 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
397 static_cast<size_t>(numEntPerRow.extent(0)) != lclNumRows,
398 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.extent(0) <<
" != the local number of rows " << lclNumRows <<
" as specified by "
399 "the input row Map.");
402 for (
size_t r = 0; r < lclNumRows; ++r) {
403 const size_t curRowCount = numEntPerRow.view_host()(r);
404 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
405 std::invalid_argument,
"numEntPerRow(" << r <<
") "
406 "specifies an invalid number of entries "
407 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
415template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
416CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
417 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
418 const Teuchos::RCP<const map_type>& colMap,
419 const Teuchos::ArrayView<const size_t>& numEntPerRow,
420 const Teuchos::RCP<Teuchos::ParameterList>& params)
421 : dist_object_type(rowMap)
425 const char tfecfFuncName[] =
426 "CrsGraph(rowMap,colMap,numEntPerRow,params): ";
429 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
430 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
431 static_cast<size_t>(numEntPerRow.size()) != lclNumRows,
432 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size() <<
" != the local number of rows " << lclNumRows <<
" as specified by "
433 "the input row Map.");
436 for (
size_t r = 0; r < lclNumRows; ++r) {
437 const size_t curRowCount = numEntPerRow[r];
438 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
439 std::invalid_argument,
"numEntPerRow(" << r <<
") "
440 "specifies an invalid number of entries "
441 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
449 typedef typename out_view_type::non_const_type nc_view_type;
450 typedef Kokkos::View<
const size_t*,
451 typename nc_view_type::array_layout,
453 Kokkos::MemoryUnmanaged>
455 in_view_type numAllocPerRowIn(numEntPerRow.getRawPtr(), lclNumRows);
456 nc_view_type numAllocPerRowOut(
"Tpetra::CrsGraph::numAllocPerRow",
459 using exec_space =
typename nc_view_type::execution_space;
460 Kokkos::deep_copy(exec_space(), numAllocPerRowOut, numAllocPerRowIn);
467template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
468CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
469 CrsGraph(CrsGraph<local_ordinal_type, global_ordinal_type, node_type>& originalGraph,
470 const Teuchos::RCP<const map_type>& rowMap,
471 const Teuchos::RCP<Teuchos::ParameterList>& params)
472 : dist_object_type(rowMap)
477 , indicesAreAllocated_(originalGraph.indicesAreAllocated_)
478 , indicesAreLocal_(originalGraph.indicesAreLocal_)
482 int numRows = rowMap->getLocalNumElements();
484 auto rowsToUse = Kokkos::pair<size_t, size_t>(0, numRows + 1);
489 if (indicesAreLocal_) {
499template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
500CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
501 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
502 const Teuchos::RCP<const map_type>& colMap,
503 const CrsGraph<local_ordinal_type, global_ordinal_type, node_type>& originalGraph,
504 const Teuchos::RCP<Teuchos::ParameterList>& params)
505 : CrsGraph(rowMap, colMap, Teuchos::null, Teuchos::null, originalGraph, params) {}
507template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
508CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
509 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
510 const Teuchos::RCP<const map_type>& colMap,
511 const Teuchos::RCP<const map_type>& domainMap,
512 const Teuchos::RCP<const map_type>& rangeMap,
513 const CrsGraph<local_ordinal_type, global_ordinal_type, node_type>& originalGraph,
514 const Teuchos::RCP<Teuchos::ParameterList>& params)
515 : dist_object_type(rowMap)
520 , indicesAreAllocated_(originalGraph.indicesAreAllocated_)
521 , indicesAreLocal_(originalGraph.indicesAreLocal_)
525 const char tfecfFuncName[] =
"CrsGraph(Map,Map,CrsGraph)";
526 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
527 originalGraph.
getRowMap()->getLocalNumElements() != rowMap->getLocalNumElements(),
529 ": The input row Map and the original graph need to have the same "
530 "number of elements.");
531 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
532 originalGraph.
getColMap()->getLocalNumElements() != colMap->getLocalNumElements(),
534 ": The input column Map and the original graph need to have the same "
535 "number of elements.");
536 if (!domainMap.is_null()) {
537 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
538 originalGraph.
getDomainMap()->getLocalNumElements() != domainMap->getLocalNumElements(),
540 ": The input domain Map and the original graph need to have the same "
541 "number of elements.");
543 if (!rangeMap.is_null()) {
544 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
545 originalGraph.
getRangeMap()->getLocalNumElements() != rangeMap->getLocalNumElements(),
547 ": The input range Map and the original graph need to have the same "
548 "number of elements.");
554 if (indicesAreLocal_) {
562 rangeMap.is_null() ? originalGraph.
getRangeMap() : rangeMap);
567template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
568CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
569 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
570 const Teuchos::RCP<const map_type>& colMap,
571 const typename local_graph_device_type::row_map_type& rowPointers,
572 const typename local_graph_device_type::entries_type::non_const_type& columnIndices,
573 const Teuchos::RCP<Teuchos::ParameterList>& params)
574 : dist_object_type(rowMap)
579 , indicesAreAllocated_(true)
580 , indicesAreLocal_(true) {
582 if (!params.is_null() && params->isParameter(
"sorted") &&
583 !params->get<
bool>(
"sorted")) {
592template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
593CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
594 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
595 const Teuchos::RCP<const map_type>& colMap,
596 const Teuchos::ArrayRCP<size_t>& rowPointers,
597 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices,
598 const Teuchos::RCP<Teuchos::ParameterList>& params)
599 : dist_object_type(rowMap)
604 , indicesAreAllocated_(true)
605 , indicesAreLocal_(true) {
607 if (!params.is_null() && params->isParameter(
"sorted") &&
608 !params->get<
bool>(
"sorted")) {
617template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
618CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
619 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
620 const Teuchos::RCP<const map_type>& colMap,
622 const Teuchos::RCP<Teuchos::ParameterList>& params)
623 : CrsGraph(k_local_graph_,
630template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
631CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
633 const Teuchos::RCP<const map_type>& rowMap,
634 const Teuchos::RCP<const map_type>& colMap,
635 const Teuchos::RCP<const map_type>& domainMap,
636 const Teuchos::RCP<const map_type>& rangeMap,
637 const Teuchos::RCP<Teuchos::ParameterList>& params)
643 , indicesAreAllocated_(true)
644 , indicesAreLocal_(true) {
646 const char tfecfFuncName[] =
"CrsGraph(Kokkos::LocalStaticCrsGraph,Map,Map,Map,Map)";
648 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
649 colMap.is_null(), std::runtime_error,
650 ": The input column Map must be nonnull.");
651 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
652 k_local_graph_.numRows() != rowMap->getLocalNumElements(),
654 ": The input row Map and the input local graph need to have the same "
655 "number of rows. The row Map claims "
656 << rowMap->getLocalNumElements()
657 <<
" row(s), but the local graph claims " << k_local_graph_.numRows()
667 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
669 ": cannot have 1D data structures allocated.");
671 if (!params.is_null() && params->isParameter(
"sorted") &&
672 !params->get<
bool>(
"sorted")) {
679 rangeMap.is_null() ?
rowMap_ : rangeMap);
680 Teuchos::Array<int> remotePIDs(0);
685 this->setRowPtrs(k_local_graph_.row_map);
687 set_need_sync_host_uvm_access();
689 const bool callComputeGlobalConstants = params.get() ==
nullptr ||
690 params->get(
"compute global constants",
true);
692 if (callComputeGlobalConstants) {
695 this->fillComplete_ =
true;
699template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
700CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
702 const Teuchos::RCP<const map_type>& rowMap,
703 const Teuchos::RCP<const map_type>& colMap,
704 const Teuchos::RCP<const map_type>& domainMap,
705 const Teuchos::RCP<const map_type>& rangeMap,
706 const Teuchos::RCP<const import_type>& importer,
707 const Teuchos::RCP<const export_type>& exporter,
708 const Teuchos::RCP<Teuchos::ParameterList>& params)
712 ,
rangeMap_(rangeMap.is_null() ? rowMap : rangeMap)
713 ,
domainMap_(domainMap.is_null() ? rowMap : domainMap)
718 , indicesAreAllocated_(true)
719 , indicesAreLocal_(true) {
721 const char tfecfFuncName[] =
722 "Tpetra::CrsGraph(local_graph_device_type,"
723 "Map,Map,Map,Map,Import,Export,params): ";
725 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(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")) {
741 const bool callComputeGlobalConstants =
742 params.get() ==
nullptr ||
743 params->get(
"compute global constants",
true);
744 if (callComputeGlobalConstants) {
747 fillComplete_ =
true;
751template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
752CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
753 CrsGraph(
const row_ptrs_device_view_type& rowPointers,
754 const local_inds_wdv_type& columnIndices,
755 const Teuchos::RCP<const map_type>& rowMap,
756 const Teuchos::RCP<const map_type>& colMap,
757 const Teuchos::RCP<const map_type>& domainMap,
758 const Teuchos::RCP<const map_type>& rangeMap,
759 const Teuchos::RCP<const import_type>& importer,
760 const Teuchos::RCP<const export_type>& exporter,
761 const Teuchos::RCP<Teuchos::ParameterList>& params)
765 ,
rangeMap_(rangeMap.is_null() ? rowMap : rangeMap)
766 ,
domainMap_(domainMap.is_null() ? rowMap : domainMap)
771 , indicesAreAllocated_(true)
772 , indicesAreLocal_(true) {
774 const char tfecfFuncName[] =
775 "Tpetra::CrsGraph(row_ptrs_device_view_type,local_inds_wdv_type"
776 "Map,Map,Map,Map,Import,Export,params): ";
778 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(colMap.is_null(), std::runtime_error,
779 "The input column Map must be nonnull.");
783 setRowPtrs(rowPointers);
785 set_need_sync_host_uvm_access();
787 if (!params.is_null() && params->isParameter(
"sorted") &&
788 !params->get<
bool>(
"sorted")) {
794 const bool callComputeGlobalConstants =
795 params.get() ==
nullptr ||
796 params->get(
"compute global constants",
true);
797 if (callComputeGlobalConstants) {
800 fillComplete_ =
true;
804template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
805Teuchos::RCP<const Teuchos::ParameterList>
808 using Teuchos::ParameterList;
809 using Teuchos::parameterList;
812 RCP<ParameterList> params = parameterList(
"Tpetra::CrsGraph");
815 RCP<ParameterList> importSublist = parameterList(
"Import");
828 params->set(
"Import", *importSublist,
"How the Import performs communication.");
834 params->set(
"Export", *importSublist,
"How the Export performs communication.");
839template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
842 Teuchos::RCP<const Teuchos::ParameterList> validParams =
844 params->validateParametersAndSetDefaults(*validParams);
845 this->setMyParamList(params);
848template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
852 return rowMap_->getGlobalNumElements();
855template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
859 const char tfecfFuncName[] =
"getGlobalNumCols: ";
860 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
862 "The graph does not have a domain Map. You may not call this method in "
867template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
871 return this->
rowMap_.is_null() ?
static_cast<size_t>(0) : this->
rowMap_->getLocalNumElements();
874template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
878 const char tfecfFuncName[] =
"getLocalNumCols: ";
879 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
881 "The graph does not have a column Map. You may not call this method "
882 "unless the graph has a column Map. This requires either that a custom "
883 "column Map was given to the constructor, or that fillComplete() has "
885 return colMap_.is_null() ?
static_cast<size_t>(0) :
colMap_->getLocalNumElements();
888template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
889Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
895template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
896Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
902template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
903Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
909template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
910Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
916template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
917Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::import_type>
923template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
924Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::export_type>
930template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
936template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
942 const bool isOpt = indicesAreAllocated_ &&
949template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
953 const char tfecfFuncName[] =
"getGlobalNumEntries: ";
955 "The graph does not have global constants computed, "
956 "but the user has requested them.");
961template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
965 const char tfecfFuncName[] =
"getLocalNumEntries: ";
966 typedef LocalOrdinal LO;
970 if (this->indicesAreAllocated_) {
972 if (lclNumRows == 0) {
973 return static_cast<size_t>(0);
977 const LO numNumEntPerRow = numEntPerRow.extent(0);
978 if (numNumEntPerRow == 0) {
980 static_cast<LO
>(lclNumRows + 1)) {
981 return static_cast<size_t>(0);
988 "Final entry of packed host rowptrs doesn't match the length of lclIndsPacked");
999 typedef typename num_row_entries_type::execution_space
1001 typedef Kokkos::RangePolicy<host_exec_space, LO> range_type;
1003 const LO upperLoopBound = lclNumRows < numNumEntPerRow ? lclNumRows : numNumEntPerRow;
1004 size_t nodeNumEnt = 0;
1005 Kokkos::parallel_reduce(
1006 "Tpetra::CrsGraph::getNumNodeEntries",
1007 range_type(0, upperLoopBound),
1008 [=](
const LO& k,
size_t& lclSum) {
1009 lclSum += numEntPerRow(k);
1016 return static_cast<size_t>(0);
1020template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1024 const char tfecfFuncName[] =
"getGlobalMaxNumRowEntries: ";
1026 "The graph does not have global constants computed, "
1027 "but the user has requested them.");
1032template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1039template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1042 return fillComplete_;
1045template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1048 return !fillComplete_;
1051template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1054 return indicesAreLocal_;
1057template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1060 return indicesAreGlobal_;
1063template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1067 typedef LocalOrdinal LO;
1069 if (this->indicesAreAllocated_) {
1071 if (lclNumRows == 0) {
1072 return static_cast<size_t>(0);
1075 static_cast<LO
>(lclNumRows + 1)) {
1076 return static_cast<size_t>(0);
1085 if (rowPtrsUnpacked_host.extent(0) == 0) {
1086 return static_cast<size_t>(0);
1094 return static_cast<size_t>(0);
1097 return Tpetra::Details::OrdinalTraits<size_t>::invalid();
1101template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1102Teuchos::RCP<const Teuchos::Comm<int>>
1105 return this->
rowMap_.is_null() ? Teuchos::null : this->
rowMap_->getComm();
1108template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1112 return rowMap_->getIndexBase();
1115template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1118 return indicesAreAllocated_;
1121template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1127template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1133template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1149template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1153 using Teuchos::arcp;
1154 using Teuchos::Array;
1155 using Teuchos::ArrayRCP;
1156 typedef Teuchos::ArrayRCP<size_t>::size_type size_type;
1157 typedef typename local_graph_device_type::row_map_type::non_const_type
1158 non_const_row_map_type;
1159 const char tfecfFuncName[] =
"allocateIndices: ";
1160 const char suffix[] =
1161 " Please report this bug to the Tpetra developers.";
1165 std::unique_ptr<std::string> prefix;
1167 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
1168 std::ostringstream os;
1169 os << *prefix <<
"Start: lg="
1170 << (lg == GlobalIndices ?
"GlobalIndices" :
"LocalIndices")
1171 <<
", numRows: " << this->getLocalNumRows() << endl;
1172 std::cerr << os.str();
1178 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isLocallyIndexed() && lg == GlobalIndices, std::logic_error,
1179 ": The graph is locally indexed, but Tpetra code is calling "
1180 "this method with lg=GlobalIndices."
1182 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isGloballyIndexed() && lg == LocalIndices, std::logic_error,
1183 ": The graph is globally indexed, but Tpetra code is calling "
1184 "this method with lg=LocalIndices."
1186 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreAllocated(), std::logic_error,
1188 "indices are already allocated, but Tpetra is calling "
1189 "allocateIndices again."
1191 const size_t numRows = this->getLocalNumRows();
1196 size_type numInds = 0;
1199 std::ostringstream os;
1200 os << *prefix <<
"Allocate k_rowPtrs: " << (numRows + 1) << endl;
1201 std::cerr << os.str();
1203 non_const_row_map_type k_rowPtrs(
"Tpetra::CrsGraph::ptr", numRows + 1);
1205 if (this->k_numAllocPerRow_.extent(0) != 0) {
1210 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->k_numAllocPerRow_.extent(0) != numRows,
1211 std::invalid_argument,
1212 "k_numAllocPerRow_ is allocated, that is, "
1213 "has nonzero length "
1214 << this->k_numAllocPerRow_.extent(0)
1215 <<
", but its length != numRows = " << numRows <<
".");
1232 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->numAllocForAllRows_ ==
1233 Tpetra::Details::OrdinalTraits<size_t>::invalid(),
1234 std::invalid_argument,
1235 "numAllocForAllRows_ has an invalid value, "
1236 "namely Tpetra::Details::OrdinalTraits<size_t>::invalid() = "
1237 << Tpetra::Details::OrdinalTraits<size_t>::invalid() <<
".");
1243 setRowPtrsUnpacked(k_rowPtrs);
1246 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numInds != size_type(this->getRowPtrsUnpackedHost()(numRows)), std::logic_error,
1247 ": Number of indices produced by computeOffsetsFrom[Constant]Counts "
1248 "does not match final entry of rowptrs unpacked");
1251 if (lg == LocalIndices) {
1253 std::ostringstream os;
1254 os << *prefix <<
"Allocate local column indices "
1255 "lclIndsUnpacked_wdv: "
1257 std::cerr << os.str();
1259 lclIndsUnpacked_wdv = local_inds_wdv_type(
1260 local_inds_dualv_type(
"Tpetra::CrsGraph::lclInd", numInds));
1263 std::ostringstream os;
1264 os << *prefix <<
"Allocate global column indices "
1267 std::cerr << os.str();
1269 gblInds_wdv = global_inds_wdv_type(
1270 global_inds_dualv_type(
"Tpetra::CrsGraph::gblInd", numInds));
1272 storageStatus_ = Details::STORAGE_1D_UNPACKED;
1274 this->indicesAreLocal_ = (lg == LocalIndices);
1275 this->indicesAreGlobal_ = (lg == GlobalIndices);
1278 using Kokkos::ViewAllocateWithoutInitializing;
1279 const char label[] =
"Tpetra::CrsGraph::numRowEntries";
1281 std::ostringstream os;
1282 os << *prefix <<
"Allocate k_numRowEntries_: " << numRows
1284 std::cerr << os.str();
1286 num_row_entries_type numRowEnt(ViewAllocateWithoutInitializing(label), numRows);
1288 Kokkos::deep_copy(
execution_space(), numRowEnt,
static_cast<size_t>(0));
1289 Kokkos::fence(
"CrsGraph::allocateIndices");
1290 this->k_numRowEntries_ = numRowEnt;
1294 this->numAllocForAllRows_ = 0;
1295 this->k_numAllocPerRow_ =
decltype(k_numAllocPerRow_)();
1296 this->indicesAreAllocated_ =
true;
1299 this->checkInternalState();
1300 }
catch (std::logic_error& e) {
1301 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
1302 "At end of allocateIndices, "
1303 "checkInternalState threw std::logic_error: "
1305 }
catch (std::exception& e) {
1306 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1307 "At end of allocateIndices, "
1308 "checkInternalState threw std::exception: "
1311 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1312 "At end of allocateIndices, "
1313 "checkInternalState threw an exception "
1314 "not a subclass of std::exception.");
1318 std::ostringstream os;
1319 os << *prefix <<
"Done" << endl;
1320 std::cerr << os.str();
1324template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1326 local_inds_dualv_type::t_host::const_type
1330 return typename local_inds_dualv_type::t_host::const_type();
1337template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1339 local_inds_dualv_type::t_host
1343 return typename local_inds_dualv_type::t_host();
1350template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1352 global_inds_dualv_type::t_host::const_type
1355 if (rowinfo.allocSize == 0 ||
gblInds_wdv.extent(0) == 0)
1356 return typename global_inds_dualv_type::t_host::const_type();
1358 return gblInds_wdv.getHostSubview(rowinfo.offset1D,
1363template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1365 local_inds_dualv_type::t_dev::const_type
1369 return typename local_inds_dualv_type::t_dev::const_type();
1376template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1378 global_inds_dualv_type::t_dev::const_type
1381 if (rowinfo.allocSize == 0 ||
gblInds_wdv.extent(0) == 0)
1382 return typename global_inds_dualv_type::t_dev::const_type();
1384 return gblInds_wdv.getDeviceSubview(rowinfo.offset1D,
1389template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1393 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid();
1395 if (this->
rowMap_.is_null() || !this->rowMap_->isNodeLocalElement(myRow)) {
1396 ret.localRow = STINV;
1399 ret.offset1D = STINV;
1403 ret.localRow =
static_cast<size_t>(myRow);
1404 if (this->indicesAreAllocated()) {
1407 if (rowPtrsUnpacked_host.extent(0) == 0) {
1411 ret.offset1D = rowPtrsUnpacked_host(myRow);
1412 ret.allocSize = rowPtrsUnpacked_host(myRow + 1) - rowPtrsUnpacked_host(myRow);
1423 ret.offset1D = STINV;
1429template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1433 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid();
1435 if (this->
rowMap_.is_null()) {
1436 ret.localRow = STINV;
1439 ret.offset1D = STINV;
1442 const LocalOrdinal myRow = this->
rowMap_->getLocalElement(gblRow);
1443 if (myRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid()) {
1444 ret.localRow = STINV;
1447 ret.offset1D = STINV;
1451 ret.localRow =
static_cast<size_t>(myRow);
1452 if (this->indicesAreAllocated()) {
1457 if (rowPtrsUnpacked_host.extent(0) == 0) {
1461 ret.offset1D = rowPtrsUnpacked_host(myRow);
1462 ret.allocSize = rowPtrsUnpacked_host(myRow + 1) - rowPtrsUnpacked_host(myRow);
1473 ret.offset1D = STINV;
1479template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1482 using Teuchos::OrdinalTraits;
1483 typedef LocalOrdinal LO;
1484 typedef GlobalOrdinal GO;
1490 static_assert(
sizeof(GlobalOrdinal) >=
sizeof(LocalOrdinal),
1491 "Tpetra::CrsGraph: sizeof(GlobalOrdinal) must be >= sizeof(LocalOrdinal).");
1494 static_assert(
sizeof(size_t) >=
sizeof(LocalOrdinal),
1495 "Tpetra::CrsGraph: sizeof(size_t) must be >= sizeof(LocalOrdinal).");
1496 static_assert(
sizeof(GST) >=
sizeof(size_t),
1497 "Tpetra::CrsGraph: sizeof(Tpetra::global_size_t) must be >= sizeof(size_t).");
1506 "Tpetra::CrsGraph: Object cannot be created with the "
1507 "given template arguments: size assumptions are not valid.";
1508 TEUCHOS_TEST_FOR_EXCEPTION(
1509 static_cast<size_t>(Teuchos::OrdinalTraits<LO>::max()) > Teuchos::OrdinalTraits<size_t>::max(),
1510 std::runtime_error, msg);
1511 TEUCHOS_TEST_FOR_EXCEPTION(
1512 static_cast<GST
>(Teuchos::OrdinalTraits<LO>::max()) >
static_cast<GST
>(Teuchos::OrdinalTraits<GO>::max()),
1513 std::runtime_error, msg);
1514 TEUCHOS_TEST_FOR_EXCEPTION(
1515 static_cast<size_t>(Teuchos::OrdinalTraits<GO>::max()) > Teuchos::OrdinalTraits<GST>::max(),
1516 std::runtime_error, msg);
1517 TEUCHOS_TEST_FOR_EXCEPTION(
1518 Teuchos::OrdinalTraits<size_t>::max() > Teuchos::OrdinalTraits<GST>::max(),
1519 std::runtime_error, msg);
1522template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1526 const SLocalGlobalViews& newInds,
1527 const ELocalGlobal lg,
1528 const ELocalGlobal I) {
1529 using Teuchos::ArrayView;
1530 typedef LocalOrdinal LO;
1531 typedef GlobalOrdinal GO;
1532 const char tfecfFuncName[] =
"insertIndices: ";
1534 size_t oldNumEnt = 0;
1536 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lg != GlobalIndices && lg != LocalIndices, std::invalid_argument,
1537 "lg must be either GlobalIndices or LocalIndices.");
1541 size_t numNewInds = 0;
1542 if (lg == GlobalIndices) {
1543 ArrayView<const GO> new_ginds = newInds.ginds;
1544 numNewInds = new_ginds.size();
1545 if (I == GlobalIndices) {
1546 auto gind_view =
gblInds_wdv.getHostView(Access::ReadWrite);
1548 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(gind_view.size()) <
1549 rowinfo.numEntries + numNewInds,
1551 "gind_view.size() = " << gind_view.size()
1552 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1553 <<
") + numNewInds (= " << numNewInds <<
").");
1555 GO*
const gblColInds_out = gind_view.data() + rowinfo.offset1D + rowinfo.numEntries;
1556 for (
size_t k = 0; k < numNewInds; ++k) {
1557 gblColInds_out[k] = new_ginds[k];
1559 }
else if (I == LocalIndices) {
1562 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(lind_view.size()) <
1563 rowinfo.numEntries + numNewInds,
1565 "lind_view.size() = " << lind_view.size()
1566 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1567 <<
") + numNewInds (= " << numNewInds <<
").");
1569 LO*
const lclColInds_out = lind_view.data() + rowinfo.offset1D + rowinfo.numEntries;
1570 for (
size_t k = 0; k < numNewInds; ++k) {
1571 lclColInds_out[k] =
colMap_->getLocalElement(new_ginds[k]);
1574 }
else if (lg == LocalIndices) {
1575 ArrayView<const LO> new_linds = newInds.linds;
1576 numNewInds = new_linds.size();
1577 if (I == LocalIndices) {
1580 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(lind_view.size()) <
1581 rowinfo.numEntries + numNewInds,
1583 "lind_view.size() = " << lind_view.size()
1584 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1585 <<
") + numNewInds (= " << numNewInds <<
").");
1587 LO*
const lclColInds_out = lind_view.data() + rowinfo.offset1D + rowinfo.numEntries;
1588 for (
size_t k = 0; k < numNewInds; ++k) {
1589 lclColInds_out[k] = new_linds[k];
1591 }
else if (I == GlobalIndices) {
1592 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
1593 "The case where the input indices are local "
1594 "and the indices to write are global (lg=LocalIndices, I="
1595 "GlobalIndices) is not implemented, because it does not make sense."
1597 <<
"If you have correct local column indices, that "
1598 "means the graph has a column Map. In that case, you should be "
1599 "storing local indices.");
1603 rowinfo.numEntries += numNewInds;
1608 const size_t chkNewNumEnt =
1610 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(chkNewNumEnt != oldNumEnt + numNewInds, std::logic_error,
1611 "chkNewNumEnt = " << chkNewNumEnt
1612 <<
" != oldNumEnt (= " << oldNumEnt
1613 <<
") + numNewInds (= " << numNewInds <<
").");
1619template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1623 const GlobalOrdinal inputGblColInds[],
1624 const size_t numInputInds) {
1626 inputGblColInds, numInputInds);
1629template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1633 const GlobalOrdinal inputGblColInds[],
1634 const size_t numInputInds,
1635 std::function<
void(
const size_t,
const size_t,
const size_t)> fun) {
1637 using Kokkos::MemoryUnmanaged;
1638 using Kokkos::subview;
1640 using Teuchos::ArrayView;
1641 using LO = LocalOrdinal;
1642 using GO = GlobalOrdinal;
1644 const char tfecfFuncName[] =
"insertGlobalIndicesImpl: ";
1645 const LO lclRow =
static_cast<LO
>(rowInfo.localRow);
1647 auto numEntries = rowInfo.numEntries;
1648 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1649 inp_view_type inputInds(inputGblColInds, numInputInds);
1652 auto gblIndsHostView = this->
gblInds_wdv.getHostView(Access::ReadWrite);
1655 numEntries, inputInds, fun);
1658 const bool insertFailed =
1659 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1661 constexpr size_t ONE(1);
1662 const int myRank = this->
getComm()->getRank();
1663 std::ostringstream os;
1665 os <<
"Proc " << myRank <<
": Not enough capacity to insert "
1667 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1668 <<
" into local row " << lclRow <<
", which currently has "
1669 << rowInfo.numEntries
1670 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1671 <<
" and total allocation size " << rowInfo.allocSize
1673 const size_t maxNumToPrint =
1675 ArrayView<const GO> inputGblColIndsView(inputGblColInds,
1677 verbosePrintArray(os, inputGblColIndsView,
1683 ArrayView<const GO> curGblColIndsView(curGblColInds.data(),
1684 rowInfo.numEntries);
1685 verbosePrintArray(os, curGblColIndsView,
1689 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
1698template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1701 const Teuchos::ArrayView<const LocalOrdinal>& indices,
1702 std::function<
void(
const size_t,
const size_t,
const size_t)> fun) {
1703 using Kokkos::MemoryUnmanaged;
1704 using Kokkos::subview;
1706 using LO = LocalOrdinal;
1708 const char tfecfFuncName[] =
"insertLocallIndicesImpl: ";
1710 const RowInfo rowInfo = this->getRowInfo(myRow);
1712 size_t numNewInds = 0;
1713 size_t newNumEntries = 0;
1715 auto numEntries = rowInfo.numEntries;
1717 using inp_view_type = View<const LO*, Kokkos::HostSpace, MemoryUnmanaged>;
1718 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1719 size_t numInserted = 0;
1721 auto lclInds = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1723 numEntries, inputInds, fun);
1726 const bool insertFailed =
1727 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1729 constexpr size_t ONE(1);
1730 const size_t numInputInds(indices.size());
1731 const int myRank = this->getComm()->getRank();
1732 std::ostringstream os;
1733 os <<
"On MPI Process " << myRank <<
": Not enough capacity to "
1736 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1737 <<
" into local row " << myRow <<
", which currently has "
1738 << rowInfo.numEntries
1739 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1740 <<
" and total allocation size " << rowInfo.allocSize <<
".";
1741 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
1743 numNewInds = numInserted;
1744 newNumEntries = rowInfo.numEntries + numNewInds;
1746 this->k_numRowEntries_(myRow) += numNewInds;
1747 this->setLocallyModified();
1750 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow(myRow);
1751 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(chkNewNumEntries != newNumEntries, std::logic_error,
1752 "getNumEntriesInLocalRow(" << myRow <<
") = " << chkNewNumEntries
1753 <<
" != newNumEntries = " << newNumEntries
1754 <<
". Please report this bug to the Tpetra developers.");
1758template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1762 const Teuchos::ArrayView<const GlobalOrdinal>& indices,
1763 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
const {
1764 using GO = GlobalOrdinal;
1765 using Kokkos::MemoryUnmanaged;
1768 auto invalidCount = Teuchos::OrdinalTraits<size_t>::invalid();
1770 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1771 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1773 size_t numFound = 0;
1774 LocalOrdinal lclRow = rowInfo.localRow;
1777 return invalidCount;
1778 const auto& colMap = *(this->
colMap_);
1779 auto map = [&](GO
const gblInd) {
return colMap.getLocalElement(gblInd); };
1781 numFound = Details::findCrsIndicesSorted(
1797 gblInds_wdv.getHostView(Access::ReadOnly), inputInds, fun);
1802template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1805 const Teuchos::RCP<const map_type>& rangeMap) {
1817template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1820 const auto INV = Teuchos::OrdinalTraits<global_size_t>::invalid();
1822 globalNumEntries_ = INV;
1823 globalMaxNumRowEntries_ = INV;
1824 haveGlobalConstants_ =
false;
1827template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1833 const char tfecfFuncName[] =
"checkInternalState: ";
1834 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1836 ProfilingRegion(
"Tpetra::CrsGraph::checkInternalState");
1838 std::unique_ptr<std::string> prefix;
1840 prefix = this->createPrefix(
"CrsGraph",
"checkInternalState");
1841 std::ostringstream os;
1842 os << *prefix <<
"Start" << endl;
1843 std::cerr << os.str();
1846 const global_size_t GSTI = Teuchos::OrdinalTraits<global_size_t>::invalid();
1852 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->
rowMap_.is_null(), std::logic_error,
1853 "Row Map is null." << suffix);
1856 const LocalOrdinal lclNumRows =
1860 "Graph cannot be both fill active and fill complete." << suffix);
1863 this->rangeMap_.is_null() ||
1864 this->domainMap_.is_null()),
1866 "Graph is full complete, but at least one of {column, range, domain} "
1869 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->
isStorageOptimized() && !this->indicesAreAllocated(),
1871 "Storage is optimized, but indices are not "
1872 "allocated, not even trivially."
1875 size_t nodeAllocSize = 0;
1878 }
catch (std::logic_error& e) {
1879 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1880 "getLocalAllocationSize threw "
1881 "std::logic_error: "
1883 }
catch (std::exception& e) {
1884 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1885 "getLocalAllocationSize threw an "
1889 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1890 "getLocalAllocationSize threw an exception "
1891 "not a subclass of std::exception.");
1897 "Storage is optimized, but "
1898 "this->getLocalAllocationSize() = "
1906 "Graph claims not to have global constants, but "
1907 "some of the global constants are not marked as invalid."
1913 "Graph claims to have global constants, but "
1914 "some of them are marked as invalid."
1920 "Graph claims to have global constants, and "
1921 "all of the values of the global constants are valid, but "
1922 "some of the local constants are greater than "
1923 "their corresponding global constants."
1925 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->indicesAreAllocated() &&
1929 "The graph claims that its indices are allocated, but "
1930 "either numAllocForAllRows_ (= "
1931 << this->numAllocForAllRows_ <<
") is "
1932 "nonzero, or k_numAllocPerRow_ has nonzero dimension. In other words, "
1933 "the graph is supposed to release its \"allocation specifications\" "
1934 "when it allocates its indices."
1938 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked_host.extent(0) != rowPtrsUnpacked_dev.extent(0),
1940 "The host and device views of k_rowPtrs_ have "
1941 "different sizes; rowPtrsUnpacked_host_ has size "
1942 << rowPtrsUnpacked_host.extent(0)
1943 <<
", but rowPtrsUnpacked_dev_ has size "
1944 << rowPtrsUnpacked_dev.extent(0)
1947 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
size_t(rowPtrsUnpacked_host.extent(0)) !=
size_t(lclNumRows + 1),
1949 "The graph is globally indexed and "
1950 "k_rowPtrs has nonzero size "
1951 << rowPtrsUnpacked_host.extent(0)
1952 <<
", but that size does not equal lclNumRows+1 = "
1953 << (lclNumRows + 1) <<
"." << suffix);
1954 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked_host(lclNumRows) !=
size_t(
gblInds_wdv.extent(0)),
1956 "The graph is globally indexed and "
1957 "k_rowPtrs_ has nonzero size "
1958 << rowPtrsUnpacked_host.extent(0)
1959 <<
", but k_rowPtrs_(lclNumRows=" << lclNumRows <<
")="
1960 << rowPtrsUnpacked_host(lclNumRows)
1961 <<
" != gblInds_wdv.extent(0)="
1965 rowPtrsUnpacked_host.extent(0) != 0 &&
1966 (
static_cast<size_t>(rowPtrsUnpacked_host.extent(0)) !=
1967 static_cast<size_t>(lclNumRows + 1) ||
1968 rowPtrsUnpacked_host(lclNumRows) !=
1971 "If k_rowPtrs_ has nonzero size and "
1972 "the graph is locally indexed, then "
1973 "k_rowPtrs_ must have N+1 rows, and "
1974 "k_rowPtrs_(N) must equal lclIndsUnpacked_wdv.extent(0)."
1977 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->indicesAreAllocated() &&
1978 nodeAllocSize > 0 &&
1980 this->gblInds_wdv.extent(0) == 0,
1982 "Graph is allocated nontrivially, but "
1983 "but 1-D allocations are not present."
1986 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->indicesAreAllocated() &&
1987 ((rowPtrsUnpacked_host.extent(0) != 0 ||
1988 this->k_numRowEntries_.extent(0) != 0) ||
1989 this->lclIndsUnpacked_wdv.extent(0) != 0 ||
1990 this->gblInds_wdv.extent(0) != 0),
1992 "If indices are not allocated, "
1993 "then none of the buffers should be."
1998 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC((this->indicesAreLocal_ || this->indicesAreGlobal_) &&
1999 !this->indicesAreAllocated_,
2001 "Indices may be local or global only if they are "
2004 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->indicesAreLocal_ && this->indicesAreGlobal_,
2005 std::logic_error,
"Indices may not be both local and global." << suffix);
2006 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreLocal_ &&
gblInds_wdv.extent(0) != 0,
2008 "Indices are local, but "
2009 "gblInds_wdv.extent(0) (= "
2011 <<
") != 0. In other words, if indices are local, then "
2012 "allocations of global indices should not be present."
2014 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreGlobal_ &&
lclIndsUnpacked_wdv.extent(0) != 0,
2016 "Indices are global, but "
2017 "lclIndsUnpacked_wdv.extent(0) (= "
2019 <<
") != 0. In other words, if indices are global, "
2020 "then allocations for local indices should not be present."
2022 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreLocal_ && nodeAllocSize > 0 &&
2025 "Indices are local and "
2026 "getLocalAllocationSize() = "
2027 << nodeAllocSize <<
" > 0, but "
2028 "lclIndsUnpacked_wdv.extent(0) = 0 and getLocalNumRows() = "
2030 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreGlobal_ && nodeAllocSize > 0 &&
2033 "Indices are global and "
2034 "getLocalAllocationSize() = "
2035 << nodeAllocSize <<
" > 0, but "
2036 "gblInds_wdv.extent(0) = 0 and getLocalNumRows() = "
2039 if (this->indicesAreAllocated() &&
2040 rowPtrsUnpacked_host.extent(0) != 0) {
2041 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(rowPtrsUnpacked_host.extent(0)) !=
2042 this->getLocalNumRows() + 1,
2044 "Indices are allocated and "
2045 "k_rowPtrs_ has nonzero length, but rowPtrsUnpacked_host_.extent(0) = "
2046 << rowPtrsUnpacked_host.extent(0) <<
" != getLocalNumRows()+1 = "
2047 << (this->getLocalNumRows() + 1) <<
"." << suffix);
2048 const size_t actualNumAllocated =
2053 "Graph is locally indexed, indices are "
2054 "are allocated, and k_rowPtrs_ has nonzero length, but "
2055 "lclIndsUnpacked_wdv.extent(0) = "
2056 << this->lclIndsUnpacked_wdv.extent(0)
2057 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2059 static_cast<size_t>(this->
gblInds_wdv.extent(0)) != actualNumAllocated,
2061 "Graph is globally indexed, indices "
2062 "are allocated, and k_rowPtrs_ has nonzero length, but "
2063 "gblInds_wdv.extent(0) = "
2064 << this->gblInds_wdv.extent(0)
2065 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2069 std::ostringstream os;
2070 os << *prefix <<
"Done" << endl;
2071 std::cerr << os.str();
2076template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2081 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2082 return Teuchos::OrdinalTraits<size_t>::invalid();
2084 return rowInfo.numEntries;
2088template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2093 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2094 return Teuchos::OrdinalTraits<size_t>::invalid();
2096 return rowInfo.numEntries;
2100template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2105 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2106 return Teuchos::OrdinalTraits<size_t>::invalid();
2108 return rowInfo.allocSize;
2112template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2117 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2118 return Teuchos::OrdinalTraits<size_t>::invalid();
2120 return rowInfo.allocSize;
2124template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2125typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_host_view_type
2131template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2132typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_device_view_type
2138template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2139typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::local_inds_host_view_type
2145template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2152template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2155 nonconst_local_inds_host_view_type& indices,
2156 size_t& numEntries)
const {
2157 using Teuchos::ArrayView;
2158 const char tfecfFuncName[] =
"getLocalRowCopy: ";
2160 TEUCHOS_TEST_FOR_EXCEPTION(
2162 "Tpetra::CrsGraph::getLocalRowCopy: The graph is globally indexed and "
2163 "does not have a column Map yet. That means we don't have local indices "
2164 "for columns yet, so it doesn't make sense to call this method. If the "
2165 "graph doesn't have a column Map yet, you should call fillComplete on "
2172 const size_t theNumEntries = rowinfo.numEntries;
2173 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(indices.size()) < theNumEntries, std::runtime_error,
2174 "Specified storage (size==" << indices.size() <<
") does not suffice "
2176 << theNumEntries <<
" entry/ies for this row.");
2177 numEntries = theNumEntries;
2179 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid()) {
2182 for (
size_t j = 0; j < theNumEntries; ++j) {
2183 indices[j] = lclInds(j);
2187 for (
size_t j = 0; j < theNumEntries; ++j) {
2188 indices[j] =
colMap_->getLocalElement(gblInds(j));
2194template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2197 nonconst_global_inds_host_view_type& indices,
2198 size_t& numEntries)
const {
2199 using Teuchos::ArrayView;
2200 const char tfecfFuncName[] =
"getGlobalRowCopy: ";
2205 const size_t theNumEntries = rowinfo.numEntries;
2206 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2207 static_cast<size_t>(indices.size()) < theNumEntries, std::runtime_error,
2208 "Specified storage (size==" << indices.size() <<
") does not suffice "
2210 << theNumEntries <<
" entry/ies for this row.");
2211 numEntries = theNumEntries;
2213 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid()) {
2216 bool err =
colMap_->getGlobalElements(lclInds.data(), theNumEntries, indices.data());
2217 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(err, std::runtime_error,
"getGlobalElements error");
2223 if (theNumEntries > 0) {
2225 (
void*)indices.data(),
2226 (
const void*)gblInds.data(),
2227 theNumEntries *
sizeof(*indices.data()));
2233template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2236 const LocalOrdinal localRow,
2237 local_inds_host_view_type& indices)
const {
2238 const char tfecfFuncName[] =
"getLocalRowView: ";
2241 "The graph's indices are "
2242 "currently stored as global indices, so we cannot return a view with "
2243 "local column indices, whether or not the graph has a column Map. If "
2244 "the graph _does_ have a column Map, use getLocalRowCopy() instead.");
2247 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid() &&
2248 rowInfo.numEntries > 0) {
2255 indices = local_inds_host_view_type();
2259 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(indices.size()) !=
2263 "= " << indices.extent(0)
2264 <<
" != getNumEntriesInLocalRow(localRow=" << localRow <<
") = " <<
getNumEntriesInLocalRow(localRow) <<
". Please report this bug to the Tpetra developers.");
2268template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2271 const GlobalOrdinal globalRow,
2272 global_inds_host_view_type& indices)
const {
2273 const char tfecfFuncName[] =
"getGlobalRowView: ";
2275 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
isLocallyIndexed(), std::runtime_error,
2276 "The graph's indices are "
2277 "currently stored as local indices, so we cannot return a view with "
2278 "global column indices. Use getGlobalRowCopy() instead.");
2283 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid() &&
2284 rowInfo.numEntries > 0) {
2285 indices =
gblInds_wdv.getHostSubview(rowInfo.offset1D,
2289 indices =
typename global_inds_dualv_type::t_host::const_type();
2292 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(indices.size()) !=
2294 std::logic_error,
"indices.size() = " << indices.extent(0) <<
" != getNumEntriesInGlobalRow(globalRow=" << globalRow <<
") = " <<
getNumEntriesInGlobalRow(globalRow) <<
". Please report this bug to the Tpetra developers.");
2298template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2301 const Teuchos::ArrayView<const LocalOrdinal>& indices) {
2302 const char tfecfFuncName[] =
"insertLocalIndices: ";
2304 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
isFillActive(), std::runtime_error,
"Fill must be active.");
2306 "Graph indices are global; use insertGlobalIndices().");
2307 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
hasColMap(), std::runtime_error,
2308 "Cannot insert local indices without a column Map.");
2309 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
rowMap_->isNodeLocalElement(localRow), std::runtime_error,
2310 "Local row index " << localRow <<
" is not in the row Map "
2311 "on the calling process.");
2312 if (!indicesAreAllocated()) {
2313 allocateIndices(LocalIndices, verbose_);
2323 using Teuchos::Array;
2324 using Teuchos::toString;
2325 typedef typename Teuchos::ArrayView<const LocalOrdinal>::size_type size_type;
2328 Array<LocalOrdinal> badColInds;
2329 bool allInColMap =
true;
2330 for (size_type k = 0; k < indices.size(); ++k) {
2332 allInColMap =
false;
2333 badColInds.push_back(indices[k]);
2337 std::ostringstream os;
2338 os <<
"Tpetra::CrsGraph::insertLocalIndices: You attempted to insert "
2339 "entries in owned row "
2340 << localRow <<
", at the following column "
2342 << toString(indices) <<
"." << endl;
2343 os <<
"Of those, the following indices are not in the column Map on "
2345 << toString(badColInds) <<
"." << endl
2347 "the graph has a column Map already, it is invalid to insert entries "
2348 "at those locations.";
2349 TEUCHOS_TEST_FOR_EXCEPTION(!allInColMap, std::invalid_argument, os.str());
2354 insertLocalIndicesImpl(localRow, indices);
2357 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!indicesAreAllocated() || !
isLocallyIndexed(), std::logic_error,
2358 "At the end of insertLocalIndices, ! indicesAreAllocated() || "
2359 "! isLocallyIndexed() is true. Please report this bug to the "
2360 "Tpetra developers.");
2364template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2367 const LocalOrdinal numEnt,
2368 const LocalOrdinal inds[]) {
2369 Teuchos::ArrayView<const LocalOrdinal> indsT(inds, numEnt);
2373template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2376 const LocalOrdinal numInputInds,
2377 const GlobalOrdinal inputGblColInds[]) {
2378 typedef LocalOrdinal LO;
2379 const char tfecfFuncName[] =
"insertGlobalIndices: ";
2381 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->
isLocallyIndexed(), std::runtime_error,
2382 "graph indices are local; use insertLocalIndices().");
2387 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->
isFillActive(), std::runtime_error,
2388 "You are not allowed to call this method if fill is not active. "
2389 "If fillComplete has been called, you must first call resumeFill "
2390 "before you may insert indices.");
2391 if (!indicesAreAllocated()) {
2392 allocateIndices(GlobalIndices, verbose_);
2394 const LO lclRow = this->
rowMap_->getLocalElement(gblRow);
2395 if (lclRow != Tpetra::Details::OrdinalTraits<LO>::invalid()) {
2404 std::vector<GlobalOrdinal> badColInds;
2405 bool allInColMap =
true;
2406 for (LO k = 0; k < numInputInds; ++k) {
2408 allInColMap =
false;
2409 badColInds.push_back(inputGblColInds[k]);
2413 std::ostringstream os;
2414 os <<
"You attempted to insert entries in owned row " << gblRow
2415 <<
", at the following column indices: [";
2416 for (LO k = 0; k < numInputInds; ++k) {
2417 os << inputGblColInds[k];
2418 if (k +
static_cast<LO
>(1) < numInputInds) {
2423 <<
"Of those, the following indices are not in "
2424 "the column Map on this process: [";
2425 for (
size_t k = 0; k < badColInds.size(); ++k) {
2426 os << badColInds[k];
2427 if (k +
size_t(1) < badColInds.size()) {
2432 <<
"Since the matrix has a column Map already, "
2433 "it is invalid to insert entries at those locations.";
2434 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::invalid_argument, os.str());
2445template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2448 const Teuchos::ArrayView<const GlobalOrdinal>& inputGblColInds) {
2450 inputGblColInds.getRawPtr());
2453template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2456 const GlobalOrdinal gblColInds[],
2457 const LocalOrdinal numGblColInds) {
2458 typedef LocalOrdinal LO;
2459 typedef GlobalOrdinal GO;
2460 const char tfecfFuncName[] =
"insertGlobalIndicesFiltered: ";
2462 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->
isLocallyIndexed(), std::runtime_error,
2463 "Graph indices are local; use insertLocalIndices().");
2468 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->
isFillActive(), std::runtime_error,
2469 "You are not allowed to call this method if fill is not active. "
2470 "If fillComplete has been called, you must first call resumeFill "
2471 "before you may insert indices.");
2472 if (!indicesAreAllocated()) {
2473 allocateIndices(GlobalIndices, verbose_);
2476 Teuchos::ArrayView<const GO> gblColInds_av(gblColInds, numGblColInds);
2482 while (curOffset < numGblColInds) {
2486 LO endOffset = curOffset;
2487 for (; endOffset < numGblColInds; ++endOffset) {
2489 if (lclCol == Tpetra::Details::OrdinalTraits<LO>::invalid()) {
2496 const LO numIndInSeq = (endOffset - curOffset);
2497 if (numIndInSeq != 0) {
2504 curOffset = endOffset + 1;
2508 gblColInds_av.size());
2512template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2515 const GlobalOrdinal gblColInds[],
2516 const LocalOrdinal numGblColInds) {
2520 std::vector<GlobalOrdinal>& nonlocalRow = this->
nonlocals_[gblRow];
2521 for (LocalOrdinal k = 0; k < numGblColInds; ++k) {
2525 nonlocalRow.push_back(gblColInds[k]);
2529template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2532 const char tfecfFuncName[] =
"removeLocalIndices: ";
2533 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2534 !
isFillActive(), std::runtime_error,
"requires that fill is active.");
2535 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2537 "cannot remove indices after optimizeStorage() has been called.");
2538 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2540 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2541 !
rowMap_->isNodeLocalElement(lrow), std::runtime_error,
2542 "Local row " << lrow <<
" is not in the row Map on the calling process.");
2543 if (!indicesAreAllocated()) {
2544 allocateIndices(LocalIndices, verbose_);
2553 !indicesAreAllocated() ||
2556 "Violated stated post-conditions. Please contact Tpetra team.");
2560template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2562 setAllIndices(
const typename local_graph_device_type::row_map_type& rowPointers,
2563 const typename local_graph_device_type::entries_type::non_const_type& columnIndices) {
2565 ProfilingRegion region(
"Tpetra::CrsGraph::setAllIndices");
2566 const char tfecfFuncName[] =
"setAllIndices: ";
2567 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2569 "The graph must have a column Map before you may call this method.");
2572 LocalOrdinal rowPtrLen = rowPointers.size();
2573 if (numLocalRows == 0) {
2574 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2575 rowPtrLen != 0 && rowPtrLen != 1,
2576 std::runtime_error,
"Have 0 local rows, but rowPointers.size() is neither 0 nor 1.");
2578 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2579 rowPtrLen != numLocalRows + 1,
2580 std::runtime_error,
"rowPointers.size() = " << rowPtrLen <<
" != this->getLocalNumRows()+1 = " << (numLocalRows + 1) <<
".");
2585 using exec_space =
typename local_graph_device_type::execution_space;
2586 int columnsOutOfBounds = 0;
2588 Kokkos::parallel_reduce(
2589 Kokkos::RangePolicy<exec_space>(0, columnIndices.extent(0)),
2590 KOKKOS_LAMBDA(
const LocalOrdinal i,
int& lOutOfBounds) {
2591 if (columnIndices(i) < 0 || columnIndices(i) >= numLocalCols)
2594 columnsOutOfBounds);
2595 int globalColsOutOfBounds = 0;
2597 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, columnsOutOfBounds,
2598 Teuchos::outArg(globalColsOutOfBounds));
2599 if (globalColsOutOfBounds) {
2600 std::string message;
2601 if (columnsOutOfBounds) {
2603 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not all within range [0, getLocalNumCols())!\n";
2606 throw std::invalid_argument(
"CrsGraph::setAllIndices(): columnIndices are out of the valid range on at least one process.");
2613 using exec_space =
typename local_graph_device_type::execution_space;
2614 using size_type =
typename local_graph_device_type::size_type;
2615 Kokkos::parallel_reduce(
2616 Kokkos::RangePolicy<exec_space>(0, numLocalRows),
2617 KOKKOS_LAMBDA(
const LocalOrdinal i,
int& lNotSorted) {
2618 size_type rowBegin = rowPointers(i);
2619 size_type rowEnd = rowPointers(i + 1);
2620 for (size_type j = rowBegin + 1; j < rowEnd; j++) {
2621 if (columnIndices(j - 1) > columnIndices(j)) {
2628 int globalNotSorted = 0;
2630 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, notSorted,
2631 Teuchos::outArg(globalNotSorted));
2632 if (globalNotSorted) {
2633 std::string message;
2636 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not sorted!\n";
2639 throw std::invalid_argument(
"CrsGraph::setAllIndices(): provided columnIndices are not sorted within rows on at least one process.");
2643 indicesAreAllocated_ =
true;
2644 indicesAreLocal_ =
true;
2647 setRowPtrs(rowPointers);
2649 set_need_sync_host_uvm_access();
2664template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2667 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices) {
2669 typedef typename local_graph_device_type::row_map_type row_map_type;
2670 typedef typename row_map_type::array_layout layout_type;
2671 typedef typename row_map_type::non_const_value_type row_offset_type;
2672 typedef View<
size_t*, layout_type, Kokkos::HostSpace,
2673 Kokkos::MemoryUnmanaged>
2675 typedef typename row_map_type::non_const_type nc_row_map_type;
2677 const size_t size =
static_cast<size_t>(rowPointers.size());
2678 constexpr bool same = std::is_same<size_t, row_offset_type>::value;
2679 input_view_type ptr_in(rowPointers.getRawPtr(), size);
2681 nc_row_map_type ptr_rot(
"Tpetra::CrsGraph::ptr", size);
2683 if constexpr (same) {
2684 using lexecution_space =
typename device_type::execution_space;
2685 Kokkos::deep_copy(lexecution_space(),
2690 constexpr bool inHostMemory =
2691 std::is_same<
typename row_map_type::memory_space,
2692 Kokkos::HostSpace>::value;
2702 View<size_t*, layout_type, device_type> ptr_st(
"Tpetra::CrsGraph::ptr", size);
2705 Kokkos::deep_copy(ptr_st, ptr_in);
2714 Kokkos::View<LocalOrdinal*, layout_type, device_type> k_ind =
2715 Kokkos::Compat::getKokkosViewDeepCopy<device_type>(columnIndices());
2719template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2723 using Teuchos::Comm;
2724 using Teuchos::outArg;
2727 using Teuchos::REDUCE_MAX;
2728 using Teuchos::REDUCE_MIN;
2729 using Teuchos::reduceAll;
2730 using crs_graph_type = CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
2733 using size_type =
typename Teuchos::Array<GO>::size_type;
2735 const char tfecfFuncName[] =
"globalAssemble: ";
2739 std::unique_ptr<std::string> prefix;
2741 prefix = this->createPrefix(
"CrsGraph",
"globalAssemble");
2742 std::ostringstream os;
2743 os << *prefix <<
"Start" << endl;
2744 std::cerr << os.str();
2746 RCP<const Comm<int>> comm =
getComm();
2748 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
isFillActive(), std::runtime_error,
2749 "Fill must be active before "
2750 "you may call this method.");
2752 const size_t myNumNonlocalRows = this->
nonlocals_.size();
2759 const int iHaveNonlocalRows = (myNumNonlocalRows == 0) ? 0 : 1;
2760 int someoneHasNonlocalRows = 0;
2761 reduceAll<int, int>(*comm, REDUCE_MAX, iHaveNonlocalRows,
2762 outArg(someoneHasNonlocalRows));
2763 if (someoneHasNonlocalRows == 0) {
2765 std::ostringstream os;
2766 os << *prefix <<
"Done: No nonlocal rows" << endl;
2767 std::cerr << os.str();
2770 }
else if (verbose_) {
2771 std::ostringstream os;
2772 os << *prefix <<
"At least 1 process has nonlocal rows"
2774 std::cerr << os.str();
2787 RCP<const map_type> nonlocalRowMap;
2789 Teuchos::Array<size_t> numEntPerNonlocalRow(myNumNonlocalRows);
2791 Teuchos::Array<GO> myNonlocalGblRows(myNumNonlocalRows);
2792 size_type curPos = 0;
2793 for (
auto mapIter = this->
nonlocals_.begin();
2794 mapIter != this->nonlocals_.end();
2795 ++mapIter, ++curPos) {
2796 myNonlocalGblRows[curPos] = mapIter->first;
2797 std::vector<GO>& gblCols = mapIter->second;
2798 std::sort(gblCols.begin(), gblCols.end());
2799 auto vecLast = std::unique(gblCols.begin(), gblCols.end());
2800 gblCols.erase(vecLast, gblCols.end());
2801 numEntPerNonlocalRow[curPos] = gblCols.size();
2812 GO myMinNonlocalGblRow = std::numeric_limits<GO>::max();
2814 auto iter = std::min_element(myNonlocalGblRows.begin(),
2815 myNonlocalGblRows.end());
2816 if (iter != myNonlocalGblRows.end()) {
2817 myMinNonlocalGblRow = *iter;
2820 GO gblMinNonlocalGblRow = 0;
2821 reduceAll<int, GO>(*comm, REDUCE_MIN, myMinNonlocalGblRow,
2822 outArg(gblMinNonlocalGblRow));
2823 const GO indexBase = gblMinNonlocalGblRow;
2824 const global_size_t INV = Teuchos::OrdinalTraits<global_size_t>::invalid();
2825 nonlocalRowMap = rcp(
new map_type(INV, myNonlocalGblRows(), indexBase, comm));
2829 std::ostringstream os;
2830 os << *prefix <<
"nonlocalRowMap->getIndexBase()="
2831 << nonlocalRowMap->getIndexBase() << endl;
2832 std::cerr << os.str();
2840 RCP<crs_graph_type> nonlocalGraph =
2843 size_type curPos = 0;
2844 for (
auto mapIter = this->
nonlocals_.begin();
2845 mapIter != this->nonlocals_.end();
2846 ++mapIter, ++curPos) {
2847 const GO gblRow = mapIter->first;
2848 std::vector<GO>& gblCols = mapIter->second;
2849 const LO numEnt =
static_cast<LO
>(numEntPerNonlocalRow[curPos]);
2850 nonlocalGraph->insertGlobalIndices(gblRow, numEnt, gblCols.data());
2854 std::ostringstream os;
2855 os << *prefix <<
"Built nonlocal graph" << endl;
2856 std::cerr << os.str();
2868 const bool origRowMapIsOneToOne = origRowMap->isOneToOne();
2870 if (origRowMapIsOneToOne) {
2872 std::ostringstream os;
2873 os << *prefix <<
"Original row Map is 1-to-1" << endl;
2874 std::cerr << os.str();
2876 export_type exportToOrig(nonlocalRowMap, origRowMap);
2881 std::ostringstream os;
2882 os << *prefix <<
"Original row Map is NOT 1-to-1" << endl;
2883 std::cerr << os.str();
2890 export_type exportToOneToOne(nonlocalRowMap, oneToOneRowMap);
2900 std::ostringstream os;
2901 os << *prefix <<
"Export nonlocal graph" << endl;
2902 std::cerr << os.str();
2908 nonlocalGraph = Teuchos::null;
2911 import_type importToOrig(oneToOneRowMap, origRowMap);
2913 std::ostringstream os;
2914 os << *prefix <<
"Import nonlocal graph" << endl;
2915 std::cerr << os.str();
2929 std::ostringstream os;
2930 os << *prefix <<
"Done" << endl;
2931 std::cerr << os.str();
2935template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2937 resumeFill(
const Teuchos::RCP<Teuchos::ParameterList>& params) {
2938 clearGlobalConstants();
2943 fillComplete_ =
false;
2946template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2948 fillComplete(
const Teuchos::RCP<Teuchos::ParameterList>& params) {
2959 Teuchos::RCP<const map_type> domMap = this->
getDomainMap();
2960 if (domMap.is_null()) {
2963 Teuchos::RCP<const map_type> ranMap = this->
getRangeMap();
2964 if (ranMap.is_null()) {
2970template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2972 fillComplete(
const Teuchos::RCP<const map_type>& domainMap,
2973 const Teuchos::RCP<const map_type>& rangeMap,
2974 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2977 const char tfecfFuncName[] =
"fillComplete: ";
2978 const bool verbose = verbose_;
2982 std::unique_ptr<std::string> prefix;
2984 prefix = this->createPrefix(
"CrsGraph",
"fillComplete");
2985 std::ostringstream os;
2986 os << *prefix <<
"Start" << endl;
2987 std::cerr << os.str();
2991 "Graph fill state must be active (isFillActive() "
2992 "must be true) before calling fillComplete().");
2994 const int numProcs =
getComm()->getSize();
3002 if (!params.is_null()) {
3003 if (params->isParameter(
"sort column map ghost gids")) {
3005 params->get<
bool>(
"sort column map ghost gids",
3007 }
else if (params->isParameter(
"Sort column Map ghost GIDs")) {
3009 params->get<
bool>(
"Sort column Map ghost GIDs",
3016 bool assertNoNonlocalInserts =
false;
3017 if (!params.is_null()) {
3018 assertNoNonlocalInserts =
3019 params->get<
bool>(
"No Nonlocal Changes", assertNoNonlocalInserts);
3025 if (!indicesAreAllocated()) {
3028 allocateIndices(LocalIndices, verbose);
3031 allocateIndices(GlobalIndices, verbose);
3039 const bool mayNeedGlobalAssemble = !assertNoNonlocalInserts && numProcs > 1;
3040 if (mayNeedGlobalAssemble) {
3045 const size_t numNonlocals =
nonlocals_.size();
3047 std::ostringstream os;
3048 os << *prefix <<
"Do not need to call globalAssemble; "
3049 "assertNoNonlocalInserts="
3050 << (assertNoNonlocalInserts ?
"true" :
"false")
3051 <<
"numProcs=" << numProcs
3052 <<
", nonlocals_.size()=" << numNonlocals << endl;
3053 std::cerr << os.str();
3055 const int lclNeededGlobalAssemble =
3056 (numProcs > 1 && numNonlocals != 0) ? 1 : 0;
3057 if (lclNeededGlobalAssemble != 0 && verbose) {
3058 std::ostringstream os;
3060 Details::Impl::verbosePrintMap(
3063 std::cerr << os.str() << endl;
3067 auto map = this->
getMap();
3068 auto comm = map.is_null() ? Teuchos::null : map->getComm();
3069 int gblNeededGlobalAssemble = lclNeededGlobalAssemble;
3070 if (!comm.is_null()) {
3071 using Teuchos::REDUCE_MAX;
3072 using Teuchos::reduceAll;
3073 reduceAll(*comm, REDUCE_MAX, lclNeededGlobalAssemble,
3074 Teuchos::outArg(gblNeededGlobalAssemble));
3076 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(gblNeededGlobalAssemble != 0, std::runtime_error,
3077 "nonlocals_.size()=" << numNonlocals <<
" != 0 on at "
3078 "least one process in the CrsGraph's communicator. This "
3079 "means either that you incorrectly set the "
3080 "\"No Nonlocal Changes\" fillComplete parameter to true, "
3081 "or that you inserted invalid entries. "
3082 "Rerun with the environment variable TPETRA_VERBOSE="
3083 "CrsGraph set to see the entries of nonlocals_ on every "
3084 "MPI process (WARNING: lots of output).");
3086 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lclNeededGlobalAssemble != 0, std::runtime_error,
3087 "nonlocals_.size()=" << numNonlocals <<
" != 0 on the "
3088 "calling process. This means either that you incorrectly "
3089 "set the \"No Nonlocal Changes\" fillComplete parameter "
3090 "to true, or that you inserted invalid entries. "
3091 "Rerun with the environment "
3092 "variable TPETRA_VERBOSE=CrsGraph set to see the entries "
3093 "of nonlocals_ on every MPI process (WARNING: lots of "
3106 Teuchos::Array<int> remotePIDs(0);
3107 const bool mustBuildColMap = !this->
hasColMap();
3108 if (mustBuildColMap) {
3109 this->makeColMap(remotePIDs);
3114 const std::pair<size_t, std::string> makeIndicesLocalResult =
3119 using Teuchos::outArg;
3121 using Teuchos::REDUCE_MIN;
3122 using Teuchos::reduceAll;
3124 RCP<const map_type> map = this->
getMap();
3125 RCP<const Teuchos::Comm<int>> comm;
3126 if (!map.is_null()) {
3127 comm = map->getComm();
3129 if (comm.is_null()) {
3130 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(makeIndicesLocalResult.first != 0, std::runtime_error,
3131 makeIndicesLocalResult.second);
3133 const int lclSuccess = (makeIndicesLocalResult.first == 0);
3135 reduceAll(*comm, REDUCE_MIN, lclSuccess, outArg(gblSuccess));
3136 if (gblSuccess != 1) {
3137 std::ostringstream os;
3138 gathervPrint(os, makeIndicesLocalResult.second, *comm);
3139 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
3147 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(makeIndicesLocalResult.first != 0, std::runtime_error,
3148 makeIndicesLocalResult.second);
3162 this->fillLocalGraph(params);
3164 const bool callComputeGlobalConstants = params.get() ==
nullptr ||
3165 params->get(
"compute global constants",
true);
3166 if (callComputeGlobalConstants) {
3171 this->fillComplete_ =
true;
3175 std::ostringstream os;
3176 os << *prefix <<
"Done" << endl;
3177 std::cerr << os.str();
3181template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3184 const Teuchos::RCP<const map_type>& rangeMap,
3185 const Teuchos::RCP<const import_type>& importer,
3186 const Teuchos::RCP<const export_type>& exporter,
3187 const Teuchos::RCP<Teuchos::ParameterList>& params) {
3188 const char tfecfFuncName[] =
"expertStaticFillComplete: ";
3191 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3192 domainMap.is_null() || rangeMap.is_null(),
3193 std::runtime_error,
"The input domain Map and range Map must be nonnull.");
3194 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3197 "call this method unless the graph has a column Map.");
3199 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3201 std::runtime_error,
"The calling process has getLocalNumRows() = " <<
getLocalNumRows() <<
" > 0 rows, but the row offsets array has not "
3203 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3205 std::runtime_error,
"The row offsets array has length " << rowPtrsUnpackedLength <<
" != getLocalNumRows()+1 = " << (
getLocalNumRows() + 1) <<
".");
3222 indicesAreAllocated_ =
true;
3227 indicesAreLocal_ =
true;
3228 indicesAreGlobal_ =
false;
3244 if (importer != Teuchos::null) {
3246 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3247 !importer->getSourceMap()->isSameAs(*
getDomainMap()) ||
3248 !importer->getTargetMap()->isSameAs(*
getColMap()),
3249 std::invalid_argument,
": importer does not match matrix maps.");
3253 if (exporter != Teuchos::null) {
3255 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3256 !exporter->getSourceMap()->isSameAs(*
getRowMap()) ||
3257 !exporter->getTargetMap()->isSameAs(*
getRangeMap()),
3258 std::invalid_argument,
": exporter does not match matrix maps.");
3264 Teuchos::Array<int> remotePIDs(0);
3270 this->fillLocalGraph(params);
3273 const bool callComputeGlobalConstants = params.get() ==
nullptr ||
3274 params->get(
"compute global constants",
true);
3276 if (callComputeGlobalConstants) {
3284 fillComplete_ =
true;
3289template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3291 fillLocalGraph(
const Teuchos::RCP<Teuchos::ParameterList>& params) {
3293 typedef typename local_graph_device_type::row_map_type row_map_type;
3294 typedef typename row_map_type::non_const_type non_const_row_map_type;
3295 typedef typename local_graph_device_type::entries_type::non_const_type lclinds_1d_type;
3296 const char tfecfFuncName[] =
3297 "fillLocalGraph (called from fillComplete or "
3298 "expertStaticFillComplete): ";
3299 const size_t lclNumRows = this->getLocalNumRows();
3306 bool requestOptimizedStorage =
true;
3307 if (!params.is_null() && !params->get(
"Optimize Storage",
true)) {
3308 requestOptimizedStorage =
false;
3316 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3318 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked.extent(0) == 0, std::logic_error,
3319 "rowPtrsUnpacked_host_ has size zero, but shouldn't");
3320 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked.extent(0) != lclNumRows + 1, std::logic_error,
3321 "rowPtrsUnpacked_host_.extent(0) = "
3322 << rowPtrsUnpacked.extent(0) <<
" != (lclNumRows + 1) = "
3323 << (lclNumRows + 1) <<
".");
3324 const size_t numOffsets = rowPtrsUnpacked.extent(0);
3325 const auto valToCheck = rowPtrsUnpacked(numOffsets - 1);
3326 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numOffsets != 0 &&
3327 lclIndsUnpacked_wdv.extent(0) != valToCheck,
3328 std::logic_error,
"numOffsets=" << numOffsets <<
" != 0 "
3329 " and lclIndsUnpacked_wdv.extent(0)="
3330 << lclIndsUnpacked_wdv.extent(0) <<
" != rowPtrsUnpacked_host_(" << numOffsets <<
")=" << valToCheck <<
".");
3333 size_t allocSize = 0;
3335 allocSize = this->getLocalAllocationSize();
3336 }
catch (std::logic_error& e) {
3337 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
3338 "getLocalAllocationSize threw "
3339 "std::logic_error: "
3341 }
catch (std::runtime_error& e) {
3342 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
3343 "getLocalAllocationSize threw "
3344 "std::runtime_error: "
3346 }
catch (std::exception& e) {
3347 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
3348 "getLocalAllocationSize threw "
3352 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
3353 "getLocalAllocationSize threw "
3354 "an exception not a subclass of std::exception.");
3357 if (this->getLocalNumEntries() != allocSize) {
3360 non_const_row_map_type ptr_d;
3361 row_map_type ptr_d_const;
3370 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3371 if (rowPtrsUnpacked.extent(0) != 0) {
3372 const size_t numOffsets =
3373 static_cast<size_t>(rowPtrsUnpacked.extent(0));
3374 const auto valToCheck = rowPtrsUnpacked(numOffsets - 1);
3375 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(valToCheck !=
size_t(lclIndsUnpacked_wdv.extent(0)),
3377 "(Unpacked branch) Before allocating "
3378 "or packing, k_rowPtrs_("
3379 << (numOffsets - 1) <<
")="
3380 << valToCheck <<
" != lclIndsUnpacked_wdv.extent(0)="
3381 << lclIndsUnpacked_wdv.extent(0) <<
".");
3391 size_t lclTotalNumEntries = 0;
3395 non_const_row_map_type(
"Tpetra::CrsGraph::ptr", lclNumRows + 1);
3396 ptr_d_const = ptr_d;
3400 typename num_row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
3402 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
size_t(numRowEnt_h.extent(0)) != lclNumRows,
3404 "(Unpacked branch) "
3405 "numRowEnt_h.extent(0)="
3406 << numRowEnt_h.extent(0)
3407 <<
" != getLocalNumRows()=" << lclNumRows <<
"");
3413 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(ptr_d.extent(0)) != lclNumRows + 1,
3415 "(Unpacked branch) After allocating "
3416 "ptr_d, ptr_d.extent(0) = "
3418 <<
" != lclNumRows+1 = " << (lclNumRows + 1) <<
".");
3419 const auto valToCheck =
3420 ::Tpetra::Details::getEntryOnHost(ptr_d, lclNumRows);
3421 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(valToCheck != lclTotalNumEntries, std::logic_error,
3422 "Tpetra::CrsGraph::fillLocalGraph: In unpacked branch, "
3423 "after filling ptr_d, ptr_d(lclNumRows="
3425 <<
") = " << valToCheck <<
" != total number of entries "
3426 "on the calling process = "
3427 << lclTotalNumEntries
3433 lclinds_1d_type ind_d =
3434 lclinds_1d_type(
"Tpetra::CrsGraph::lclInd", lclTotalNumEntries);
3446 typedef pack_functor<
3447 typename local_graph_device_type::entries_type::non_const_type,
3448 typename local_inds_dualv_type::t_dev::const_type,
3450 typename local_graph_device_type::row_map_type>
3452 inds_packer_type f(ind_d,
3453 lclIndsUnpacked_wdv.getDeviceView(Access::ReadOnly),
3454 ptr_d, this->getRowPtrsUnpackedDevice());
3456 typedef typename decltype(ind_d)::execution_space exec_space;
3457 typedef Kokkos::RangePolicy<exec_space, LocalOrdinal> range_type;
3458 Kokkos::parallel_for(range_type(0, lclNumRows), f);
3462 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(ptr_d.extent(0) == 0, std::logic_error,
3463 "(\"Optimize Storage\"=true branch) After packing, "
3464 "ptr_d.extent(0)=0.");
3465 if (ptr_d.extent(0) != 0) {
3466 const size_t numOffsets =
static_cast<size_t>(ptr_d.extent(0));
3467 const auto valToCheck =
3468 ::Tpetra::Details::getEntryOnHost(ptr_d, numOffsets - 1);
3469 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(valToCheck) != ind_d.extent(0),
3471 "(\"Optimize Storage\"=true branch) "
3472 "After packing, ptr_d("
3473 << (numOffsets - 1) <<
")="
3474 << valToCheck <<
" != ind_d.extent(0)="
3475 << ind_d.extent(0) <<
".");
3479 if (requestOptimizedStorage)
3480 setRowPtrs(ptr_d_const);
3482 setRowPtrsPacked(ptr_d_const);
3483 lclIndsPacked_wdv = local_inds_wdv_type(ind_d);
3486 this->setRowPtrs(rowPtrsUnpacked_dev_);
3487 lclIndsPacked_wdv = lclIndsUnpacked_wdv;
3490 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3491 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3492 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsPacked_dev.extent(0) == 0, std::logic_error,
3493 "(\"Optimize Storage\"=false branch) "
3494 "rowPtrsPacked_dev_.extent(0) = 0.");
3495 if (rowPtrsPacked_dev.extent(0) != 0) {
3496 const size_t numOffsets =
3497 static_cast<size_t>(rowPtrsPacked_dev.extent(0));
3498 const size_t valToCheck =
3499 rowPtrsPacked_host(numOffsets - 1);
3500 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(valToCheck !=
size_t(lclIndsPacked_wdv.extent(0)),
3502 "(\"Optimize Storage\"=false branch) "
3503 "rowPtrsPacked_dev_("
3504 << (numOffsets - 1) <<
")="
3506 <<
" != lclIndsPacked_wdv.extent(0)="
3507 << lclIndsPacked_wdv.extent(0) <<
".");
3513 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3514 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3515 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(rowPtrsPacked_dev.extent(0)) != lclNumRows + 1,
3516 std::logic_error,
"After packing, rowPtrsPacked_dev_.extent(0) = " << rowPtrsPacked_dev.extent(0) <<
" != lclNumRows+1 = " << (lclNumRows + 1) <<
".");
3517 if (rowPtrsPacked_dev.extent(0) != 0) {
3518 const size_t numOffsets =
static_cast<size_t>(rowPtrsPacked_dev.extent(0));
3519 const auto valToCheck = rowPtrsPacked_host(numOffsets - 1);
3520 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(valToCheck) != lclIndsPacked_wdv.extent(0),
3521 std::logic_error,
"After packing, rowPtrsPacked_dev_(" << (numOffsets - 1) <<
") = " << valToCheck <<
" != lclIndsPacked_wdv.extent(0) = " << lclIndsPacked_wdv.extent(0) <<
".");
3525 if (requestOptimizedStorage) {
3531 k_numRowEntries_ = num_row_entries_type();
3534 lclIndsUnpacked_wdv = lclIndsPacked_wdv;
3536 storageStatus_ = Details::STORAGE_1D_PACKED;
3539 set_need_sync_host_uvm_access();
3542template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3544 replaceColMap(
const Teuchos::RCP<const map_type>& newColMap) {
3552 const char tfecfFuncName[] =
"replaceColMap: ";
3553 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3555 "Requires matching maps and non-static graph.");
3559template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3562 const Teuchos::RCP<const import_type>& newImport,
3563 const bool sortIndicesInEachRow) {
3565 using Teuchos::REDUCE_MIN;
3566 using Teuchos::reduceAll;
3567 typedef GlobalOrdinal GO;
3568 typedef LocalOrdinal LO;
3569 using col_inds_type_dev =
typename local_inds_dualv_type::t_dev;
3570 const char tfecfFuncName[] =
"reindexColumns: ";
3572 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3574 "The graph is fill complete "
3575 "(isFillComplete() returns true). You must call resumeFill() before "
3576 "you may call this method.");
3609 bool allCurColIndsValid =
true;
3614 bool localSuffices =
true;
3623 col_inds_type_dev newLclInds1D_dev;
3628 if (indicesAreAllocated()) {
3636 newLclInds1D_dev = col_inds_type_dev(
"Tpetra::CrsGraph::lclIndsReindexed",
3639 auto newLclColMap = newColMap->getLocalMap();
3641 const auto LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
3642 const auto GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
3644 const int NOT_ALL_LOCAL_INDICES_ARE_VALID = 1;
3645 const int LOCAL_DOES_NOT_SUFFICE = 2;
3646 int errorStatus = 0;
3647 Kokkos::parallel_reduce(
3648 "Tpetra::CrsGraph::reindexColumns",
3649 Kokkos::RangePolicy<LocalOrdinal, execution_space>(0, allocSize),
3650 KOKKOS_LAMBDA(
const LocalOrdinal k,
int& result) {
3651 const LocalOrdinal oldLclCol = oldLclInds1D(k);
3652 if (oldLclCol == LO_INVALID) {
3653 result &= NOT_ALL_LOCAL_INDICES_ARE_VALID;
3655 const GO gblCol = oldLclColMap.getGlobalElement(oldLclCol);
3656 if (gblCol == GO_INVALID) {
3657 result &= LOCAL_DOES_NOT_SUFFICE;
3659 const LocalOrdinal newLclCol = newLclColMap.getLocalElement(gblCol);
3660 if (newLclCol == LO_INVALID) {
3661 result &= NOT_ALL_LOCAL_INDICES_ARE_VALID;
3663 newLclInds1D_dev(k) = newLclCol;
3668 Kokkos::LOr<int>(errorStatus));
3669 allCurColIndsValid = !(errorStatus & NOT_ALL_LOCAL_INDICES_ARE_VALID);
3670 localSuffices = !(errorStatus & LOCAL_DOES_NOT_SUFFICE);
3677 allCurColIndsValid =
false;
3693 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
3696 for (
size_t k = 0; k < rowInfo.numEntries; ++k) {
3697 const GO gblCol = oldGblRowView(k);
3698 if (!newColMap->isNodeGlobalElement(gblCol)) {
3699 localSuffices =
false;
3709 lclSuccess[0] = allCurColIndsValid ? 1 : 0;
3710 lclSuccess[1] = localSuffices ? 1 : 0;
3714 RCP<const Teuchos::Comm<int>> comm =
3716 if (!comm.is_null()) {
3717 reduceAll<int, int>(*comm, REDUCE_MIN, 2, lclSuccess, gblSuccess);
3720 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3721 gblSuccess[0] == 0, std::runtime_error,
3722 "It is not possible to continue."
3723 " The most likely reason is that the graph is locally indexed, but the "
3724 "column Map is missing (null) on some processes, due to a previous call "
3725 "to replaceColMap().");
3727 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3728 gblSuccess[1] == 0, std::runtime_error,
3729 "On some process, the graph "
3730 "contains column indices that are in the old column Map, but not in the "
3731 "new column Map (on that process). This method does NOT redistribute "
3732 "data; it does not claim to do the work of an Import or Export operation."
3733 " This means that for all processess, the calling process MUST own all "
3734 "column indices, in both the old column Map and the new column Map. In "
3735 "this case, you will need to do an Import or Export operation to "
3736 "redistribute data.");
3754 if (sortIndicesInEachRow) {
3761 const bool sorted =
false;
3762 const bool merged =
true;
3763 this->sortAndMergeAllIndices(sorted, merged);
3768 if (newImport.is_null()) {
3789template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3792 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMap: ";
3793 TEUCHOS_TEST_FOR_EXCEPTION(
3794 colMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3795 "this method unless the graph already has a column Map.");
3796 TEUCHOS_TEST_FOR_EXCEPTION(
3797 newDomainMap.is_null(), std::invalid_argument,
3798 prefix <<
"The new domain Map must be nonnull.");
3801 Teuchos::RCP<const import_type> newImporter = Teuchos::null;
3802 if (newDomainMap !=
colMap_ && (!newDomainMap->isSameAs(*
colMap_))) {
3808template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3811 const Teuchos::RCP<const import_type>& newImporter) {
3812 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMapAndImporter: ";
3813 TEUCHOS_TEST_FOR_EXCEPTION(
3814 colMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3815 "this method unless the graph already has a column Map.");
3816 TEUCHOS_TEST_FOR_EXCEPTION(
3817 newDomainMap.is_null(), std::invalid_argument,
3818 prefix <<
"The new domain Map must be nonnull.");
3821 if (newImporter.is_null()) {
3826 const bool colSameAsDom =
colMap_->isSameAs(*newDomainMap);
3827 TEUCHOS_TEST_FOR_EXCEPTION(!colSameAsDom, std::invalid_argument,
3828 "If the new Import is null, "
3829 "then the new domain Map must be the same as the current column Map.");
3831 const bool colSameAsTgt =
3832 colMap_->isSameAs(*(newImporter->getTargetMap()));
3833 const bool newDomSameAsSrc =
3834 newDomainMap->isSameAs(*(newImporter->getSourceMap()));
3835 TEUCHOS_TEST_FOR_EXCEPTION(!colSameAsTgt || !newDomSameAsSrc, std::invalid_argument,
3837 "new Import is nonnull, then the current column Map must be the same "
3838 "as the new Import's target Map, and the new domain Map must be the "
3839 "same as the new Import's source Map.");
3844 importer_ = Teuchos::rcp_const_cast<import_type>(newImporter);
3847template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3850 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMap: ";
3851 TEUCHOS_TEST_FOR_EXCEPTION(
3852 rowMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3853 "this method unless the graph already has a row Map.");
3854 TEUCHOS_TEST_FOR_EXCEPTION(
3855 newRangeMap.is_null(), std::invalid_argument,
3856 prefix <<
"The new range Map must be nonnull.");
3859 Teuchos::RCP<const export_type> newExporter = Teuchos::null;
3860 if (newRangeMap !=
rowMap_ && (!newRangeMap->isSameAs(*
rowMap_))) {
3866template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3869 const Teuchos::RCP<const export_type>& newExporter) {
3870 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMapAndExporter: ";
3871 TEUCHOS_TEST_FOR_EXCEPTION(
3872 rowMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3873 "this method unless the graph already has a column Map.");
3874 TEUCHOS_TEST_FOR_EXCEPTION(
3875 newRangeMap.is_null(), std::invalid_argument,
3876 prefix <<
"The new domain Map must be nonnull.");
3879 if (newExporter.is_null()) {
3884 const bool rowSameAsRange =
rowMap_->isSameAs(*newRangeMap);
3885 TEUCHOS_TEST_FOR_EXCEPTION(!rowSameAsRange, std::invalid_argument,
3886 "If the new Export is null, "
3887 "then the new range Map must be the same as the current row Map.");
3889 const bool newRangeSameAsTgt =
3890 newRangeMap->isSameAs(*(newExporter->getTargetMap()));
3891 const bool rowSameAsSrc =
3892 rowMap_->isSameAs(*(newExporter->getSourceMap()));
3893 TEUCHOS_TEST_FOR_EXCEPTION(!rowSameAsSrc || !newRangeSameAsTgt, std::invalid_argument,
3895 "new Export is nonnull, then the current row Map must be the same "
3896 "as the new Export's source Map, and the new range Map must be the "
3897 "same as the new Export's target Map.");
3902 exporter_ = Teuchos::rcp_const_cast<export_type>(newExporter);
3905template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3911 this->getRowPtrsPackedDevice());
3914template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3918 return local_graph_host_type(
3919 lclIndsPacked_wdv.getHostView(Access::ReadWrite),
3920 this->getRowPtrsPackedHost());
3923template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3926 using Teuchos::ArrayView;
3927 using Teuchos::outArg;
3928 using Teuchos::reduceAll;
3932 ProfilingRegion regionCGC(
"Tpetra::CrsGraph::computeGlobalConstants");
3935 std::shared_ptr<Details::CommRequest> req;
3938 req = Details::iallreduce(lcl, gbl, Teuchos::REDUCE_SUM, *this->
getComm());
3970template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3975 ProfilingRegion regionCLC(
"Tpetra::CrsGraph::computeLocalConstants");
3982 Teuchos::OrdinalTraits<size_t>::invalid();
3987 const LO lclNumRows = ptr.extent(0) == 0 ?
static_cast<LO
>(0) : (
static_cast<LO
>(ptr.extent(0)) -
static_cast<LO
>(1));
3989 const LO lclMaxNumRowEnt =
3990 ::Tpetra::Details::maxDifference(
"Tpetra::CrsGraph: nodeMaxNumRowEntries",
3996template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3997std::pair<size_t, std::string>
4002 using Teuchos::arcp;
4003 using Teuchos::Array;
4004 typedef LocalOrdinal LO;
4005 typedef GlobalOrdinal GO;
4007 typedef typename local_graph_device_type::row_map_type::non_const_value_type offset_type;
4008 typedef typename num_row_entries_type::non_const_value_type num_ent_type;
4009 const char tfecfFuncName[] =
"makeIndicesLocal: ";
4010 ProfilingRegion regionMakeIndicesLocal(
"Tpetra::CrsGraph::makeIndicesLocal");
4012 std::unique_ptr<std::string> prefix;
4014 prefix = this->createPrefix(
"CrsGraph",
"makeIndicesLocal");
4015 std::ostringstream os;
4017 std::cerr << os.str();
4022 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->
hasColMap(), std::logic_error,
4023 "The graph does not have a "
4024 "column Map yet. This method should never be called in that case. "
4025 "Please report this bug to the Tpetra developers.");
4026 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->
getColMap().is_null(), std::logic_error,
4028 "that it has a column Map, because hasColMap() returns true. However, "
4029 "the result of getColMap() is null. This should never happen. Please "
4030 "report this bug to the Tpetra developers.");
4035 size_t lclNumErrs = 0;
4036 std::ostringstream errStrm;
4043 typename num_row_entries_type::const_type h_numRowEnt =
4049 if (rowPtrsUnpacked_host.extent(0) == 0) {
4050 errStrm <<
"Unpacked row pointers (rowPtrsUnpacked_dev_) has length 0. This should never "
4051 "happen here. Please report this bug to the Tpetra developers."
4054 return std::make_pair(Tpetra::Details::OrdinalTraits<size_t>::invalid(),
4057 const auto numEnt = rowPtrsUnpacked_host(lclNumRows);
4066 using Kokkos::view_alloc;
4067 using Kokkos::WithoutInitializing;
4077 const std::string label(
"Tpetra::CrsGraph::lclInd");
4079 std::ostringstream os;
4080 os << *prefix <<
"(Re)allocate lclInd_wdv: old="
4082 std::cerr << os.str();
4085 local_inds_dualv_type lclInds_dualv =
4086 local_inds_dualv_type(view_alloc(label, WithoutInitializing),
4099 std::ostringstream os;
4100 os << *prefix <<
"Allocate device mirror k_numRowEnt: "
4101 << h_numRowEnt.extent(0) << endl;
4102 std::cerr << os.str();
4105 Kokkos::create_mirror_view_and_copy(
device_type(), h_numRowEnt);
4109 convertColumnIndicesFromGlobalToLocal<LO, GO, DT, offset_type, num_ent_type>(
4112 this->getRowPtrsUnpackedDevice(),
4115 if (lclNumErrs != 0) {
4116 const int myRank = [
this]() {
4117 auto map = this->
getMap();
4118 if (map.is_null()) {
4121 auto comm = map->getComm();
4122 return comm.is_null() ? 0 : comm->getRank();
4125 const bool pluralNumErrs = (lclNumErrs !=
static_cast<size_t>(1));
4126 errStrm <<
"(Process " << myRank <<
") When converting column "
4127 "indices from global to local, we encountered "
4129 <<
" ind" << (pluralNumErrs ?
"ices" :
"ex")
4130 <<
" that do" << (pluralNumErrs ?
"" :
"es")
4131 <<
" not live in the column Map on this process." << endl;
4138 std::ostringstream os;
4139 os << *prefix <<
"Free gblInds_wdv: "
4141 std::cerr << os.str();
4146 this->indicesAreLocal_ =
true;
4147 this->indicesAreGlobal_ =
false;
4150 return std::make_pair(lclNumErrs, errStrm.str());
4153template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4154void CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
4155 makeColMap(Teuchos::Array<int>& remotePIDs) {
4158 const char tfecfFuncName[] =
"makeColMap";
4160 ProfilingRegion regionSortAndMerge(
"Tpetra::CrsGraph::makeColMap");
4161 std::unique_ptr<std::string> prefix;
4163 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4164 std::ostringstream os;
4165 os << *prefix <<
"Start" << endl;
4166 std::cerr << os.str();
4174 Teuchos::RCP<const map_type> colMap = this->
colMap_;
4175 const bool sortEachProcsGids =
4186 using Teuchos::outArg;
4187 using Teuchos::REDUCE_MIN;
4188 using Teuchos::reduceAll;
4190 std::ostringstream errStrm;
4191 const int lclErrCode =
4195 if (!comm.is_null()) {
4196 const int lclSuccess = (lclErrCode == 0) ? 1 : 0;
4198 reduceAll<int, int>(*comm, REDUCE_MIN, lclSuccess,
4199 outArg(gblSuccess));
4200 if (gblSuccess != 1) {
4201 std::ostringstream os;
4203 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
4204 ": An error happened on at "
4205 "least one process in the CrsGraph's communicator. "
4206 "Here are all processes' error messages:"
4222 std::ostringstream os;
4223 os << *prefix <<
"Done" << endl;
4224 std::cerr << os.str();
4228template <
class execution_space,
class LO,
class rowptr_type,
class colinds_type,
class numRowEntries_type>
4229void prepareSortMergeUnpackedGraph(rowptr_type rowptr, colinds_type colinds, numRowEntries_type numRowEntries) {
4230 using ATS = KokkosKernels::ArithTraits<LO>;
4231 const auto unused = ATS::max();
4233 auto numRows = rowptr.extent(0) - 1;
4236 Kokkos::parallel_for(
4237 "flag_unused_entries", Kokkos::RangePolicy<execution_space, LO>(0, numRows), KOKKOS_LAMBDA(
const LO rlid) {
4238 for (
size_t jj = rowptr(rlid) + numRowEntries(rlid); jj < rowptr(rlid + 1); ++jj) {
4239 colinds(jj) = unused;
4244template <
class execution_space,
class LO,
class rowptr_type,
class colinds_type,
class numRowEntries_type>
4245void mergeUnpackedGraph(rowptr_type rowptr, colinds_type colinds, numRowEntries_type numRowEntries) {
4246 auto numRows = rowptr.extent(0) - 1;
4252 Kokkos::parallel_for(
4253 "merge_entries", Kokkos::RangePolicy<execution_space>(0, numRows), KOKKOS_LAMBDA(
const LO rlid) {
4254 auto rowNNZ = numRowEntries(rlid);
4258 auto rowBegin = rowptr(rlid);
4259 auto pos = rowBegin;
4260 for (
size_t offset = rowBegin + 1; offset < rowBegin + rowNNZ; ++offset) {
4261 if ((colinds(offset) != colinds(pos))) {
4262 colinds(++pos) = colinds(offset);
4265 numRowEntries(rlid) = pos + 1 - rowBegin;
4269template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4273 const char tfecfFuncName[] =
"sortAndMergeAllIndices";
4275 std::unique_ptr<std::string> prefix;
4277 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
4278 std::ostringstream os;
4279 os << *prefix <<
"Start: "
4280 <<
"sorted=" << (sorted ?
"true" :
"false")
4281 <<
", merged=" << (merged ?
"true" :
"false") << endl;
4282 std::cerr << os.str();
4284 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isGloballyIndexed(), std::logic_error,
4285 "This method may only be called after makeIndicesLocal.");
4286 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!merged && this->isStorageOptimized(), std::logic_error,
4287 "The graph is already storage optimized, so we shouldn't be "
4288 "merging any indices. "
4289 "Please report this bug to the Tpetra developers.");
4291 if (!sorted || !merged) {
4294 if (storageStatus_ == Details::STORAGE_1D_UNPACKED) {
4297 auto rowptr = rowPtrsUnpacked_dev_;
4298 auto colinds = lclIndsUnpacked_wdv.getDeviceView(Access::ReadWrite);
4301 auto k_numRowEntries_d = Kokkos::create_mirror_view_and_copy(
execution_space(), k_numRowEntries_);
4304 prepareSortMergeUnpackedGraph<execution_space, LocalOrdinal>(rowptr, colinds, k_numRowEntries_d);
4310 this->indicesAreSorted_ =
true;
4313 mergeUnpackedGraph<execution_space, LocalOrdinal>(rowptr, colinds, k_numRowEntries_d);
4314 Kokkos::deep_copy(k_numRowEntries_, k_numRowEntries_d);
4315 this->noRedundancies_ =
true;
4318 auto rowptr = rowPtrsPacked_dev_;
4319 auto colinds = lclIndsPacked_wdv.getDeviceView(Access::ReadWrite);
4320 if (!sorted && merged) {
4322 this->indicesAreSorted_ =
true;
4324 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
4325 "We should never get here."
4326 "Please report this bug to the Tpetra developers.");
4332 std::ostringstream os;
4333 os << *prefix <<
"Done" << endl;
4334 std::cerr << os.str();
4338template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4341 const bool useRemotePIDs) {
4342 using Teuchos::ParameterList;
4346 const char tfecfFuncName[] =
"makeImportExport: ";
4347 ProfilingRegion regionMIE(
"Tpetra::CrsGraph::makeImportExport");
4349 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->
hasColMap(), std::logic_error,
4350 "This method may not be called unless the graph has a column Map.");
4351 RCP<ParameterList> params = this->getNonconstParameterList();
4363 if (params.is_null() || !params->isSublist(
"Import")) {
4364 if (useRemotePIDs) {
4370 RCP<ParameterList> importSublist = sublist(params,
"Import",
true);
4371 if (useRemotePIDs) {
4372 RCP<import_type> newImp =
4388 if (params.is_null() || !params->isSublist(
"Export")) {
4391 RCP<ParameterList> exportSublist = sublist(params,
"Export",
true);
4398template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4402 std::ostringstream oss;
4405 oss <<
"{status = fill complete"
4411 oss <<
"{status = fill not complete"
4418template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4420 describe(Teuchos::FancyOStream& out,
4421 const Teuchos::EVerbosityLevel verbLevel)
const {
4424 using Teuchos::ArrayView;
4425 using Teuchos::Comm;
4427 using Teuchos::VERB_DEFAULT;
4428 using Teuchos::VERB_EXTREME;
4429 using Teuchos::VERB_HIGH;
4430 using Teuchos::VERB_LOW;
4431 using Teuchos::VERB_MEDIUM;
4432 using Teuchos::VERB_NONE;
4434 Teuchos::EVerbosityLevel vl = verbLevel;
4435 if (vl == VERB_DEFAULT) vl = VERB_LOW;
4436 RCP<const Comm<int>> comm = this->
getComm();
4437 const int myImageID = comm->getRank(),
4438 numImages = comm->getSize();
4443 width = std::max<size_t>(width,
static_cast<size_t>(11)) + 2;
4444 Teuchos::OSTab tab(out);
4452 if (vl != VERB_NONE) {
4453 if (myImageID == 0) out << this->
description() << std::endl;
4459 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4460 if (myImageID == 0) out <<
"\nRow map: " << std::endl;
4462 if (
colMap_ != Teuchos::null) {
4463 if (myImageID == 0) out <<
"\nColumn map: " << std::endl;
4467 if (myImageID == 0) out <<
"\nDomain map: " << std::endl;
4471 if (myImageID == 0) out <<
"\nRange map: " << std::endl;
4476 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4477 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4478 if (myImageID == imageCtr) {
4479 out <<
"Node ID = " << imageCtr << std::endl
4482 if (!indicesAreAllocated()) {
4483 out <<
"Indices are not allocated." << std::endl;
4492 if (vl == VERB_HIGH || vl == VERB_EXTREME) {
4493 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4494 if (myImageID == imageCtr) {
4495 out << std::setw(width) <<
"Node ID"
4496 << std::setw(width) <<
"Global Row"
4497 << std::setw(width) <<
"Num Entries";
4498 if (vl == VERB_EXTREME) {
4502 const LocalOrdinal lclNumRows =
4504 for (LocalOrdinal r = 0; r < lclNumRows; ++r) {
4506 GlobalOrdinal gid =
rowMap_->getGlobalElement(r);
4507 out << std::setw(width) << myImageID
4508 << std::setw(width) << gid
4509 << std::setw(width) << rowinfo.numEntries;
4510 if (vl == VERB_EXTREME) {
4513 auto rowview =
gblInds_wdv.getHostView(Access::ReadOnly);
4514 for (
size_t j = 0; j < rowinfo.numEntries; ++j) {
4515 GlobalOrdinal colgid = rowview[j + rowinfo.offset1D];
4516 out << colgid <<
" ";
4520 for (
size_t j = 0; j < rowinfo.numEntries; ++j) {
4521 LocalOrdinal collid = rowview[j + rowinfo.offset1D];
4522 out <<
colMap_->getGlobalElement(collid) <<
" ";
4537template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4546template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4549 const size_t numSameIDs,
4558 using this_CRS_type = CrsGraph<LO, GO, node_type>;
4559 const char tfecfFuncName[] =
"copyAndPermute: ";
4560 const bool verbose = verbose_;
4563 const row_graph_type& srcRowGraph =
dynamic_cast<const row_graph_type&
>(source);
4564 copyAndPermuteNew(srcRowGraph, *
this, numSameIDs, permuteToLIDs, permuteFromLIDs,
INSERT);
4570 std::unique_ptr<std::string> prefix;
4572 prefix = this->createPrefix(
"CrsGraph",
"copyAndPermute");
4573 std::ostringstream os;
4574 os << *prefix << endl;
4575 std::cerr << os.str();
4578 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(permuteToLIDs.extent(0) != permuteFromLIDs.extent(0),
4579 std::runtime_error,
"permuteToLIDs.extent(0) = " << permuteToLIDs.extent(0) <<
" != permuteFromLIDs.extent(0) = " << permuteFromLIDs.extent(0) <<
".");
4583 const row_graph_type& srcRowGraph =
4584 dynamic_cast<const row_graph_type&
>(source);
4587 std::ostringstream os;
4588 os << *prefix <<
"Compute padding" << endl;
4589 std::cerr << os.str();
4591 auto padding = computeCrsPadding(srcRowGraph, numSameIDs,
4592 permuteToLIDs, permuteFromLIDs, verbose);
4593 applyCrsPadding(*padding, verbose);
4598 const this_CRS_type* srcCrsGraph =
4599 dynamic_cast<const this_CRS_type*
>(&source);
4604 nonconst_global_inds_host_view_type row_copy;
4610 if (src_filled || srcCrsGraph ==
nullptr) {
4612 std::ostringstream os;
4613 os << *prefix <<
"src_filled || srcCrsGraph == nullptr" << endl;
4614 std::cerr << os.str();
4621 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
4624 Kokkos::resize(row_copy, row_length);
4625 size_t check_row_length = 0;
4631 std::ostringstream os;
4632 os << *prefix <<
"! src_filled && srcCrsGraph != nullptr" << endl;
4633 std::cerr << os.str();
4635 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
4637 global_inds_host_view_type row;
4646 auto permuteToLIDs_h = permuteToLIDs.view_host();
4647 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
4649 if (src_filled || srcCrsGraph ==
nullptr) {
4650 for (LO i = 0; i < static_cast<LO>(permuteToLIDs_h.extent(0)); ++i) {
4654 Kokkos::resize(row_copy, row_length);
4655 size_t check_row_length = 0;
4660 for (LO i = 0; i < static_cast<LO>(permuteToLIDs_h.extent(0)); ++i) {
4663 global_inds_host_view_type row;
4670 std::ostringstream os;
4671 os << *prefix <<
"Done" << endl;
4672 std::cerr << os.str();
4676template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4679 const bool verbose) {
4684 using row_ptrs_type =
4685 typename local_graph_device_type::row_map_type::non_const_type;
4686 using range_policy =
4687 Kokkos::RangePolicy<execution_space, Kokkos::IndexType<LO>>;
4688 const char tfecfFuncName[] =
"applyCrsPadding";
4689 ProfilingRegion regionCAP(
"Tpetra::CrsGraph::applyCrsPadding");
4691 std::unique_ptr<std::string> prefix;
4693 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4694 std::ostringstream os;
4695 os << *prefix <<
"padding: ";
4698 std::cerr << os.str();
4700 const int myRank = !verbose ? -1 : [&]() {
4701 auto map = this->getMap();
4702 if (map.is_null()) {
4705 auto comm = map->getComm();
4706 if (comm.is_null()) {
4709 return comm->getRank();
4718 if (!indicesAreAllocated()) {
4720 std::ostringstream os;
4721 os << *prefix <<
"Call allocateIndices" << endl;
4722 std::cerr << os.str();
4724 allocateIndices(GlobalIndices, verbose);
4726 TEUCHOS_ASSERT(indicesAreAllocated());
4731 auto rowPtrsUnpacked_dev = this->getRowPtrsUnpackedDevice();
4733 std::ostringstream os;
4734 os << *prefix <<
"Allocate row_ptrs_beg: "
4735 << rowPtrsUnpacked_dev.extent(0) << endl;
4736 std::cerr << os.str();
4738 using Kokkos::view_alloc;
4739 using Kokkos::WithoutInitializing;
4740 row_ptrs_type row_ptrs_beg(
4741 view_alloc(
"row_ptrs_beg", WithoutInitializing),
4742 rowPtrsUnpacked_dev.extent(0));
4744 Kokkos::deep_copy(
execution_space(), row_ptrs_beg, rowPtrsUnpacked_dev);
4746 const size_t N = row_ptrs_beg.extent(0) == 0 ? size_t(0) : size_t(row_ptrs_beg.extent(0) - 1);
4748 std::ostringstream os;
4749 os << *prefix <<
"Allocate row_ptrs_end: " << N << endl;
4750 std::cerr << os.str();
4752 row_ptrs_type row_ptrs_end(
4753 view_alloc(
"row_ptrs_end", WithoutInitializing), N);
4754 row_ptrs_type num_row_entries;
4756 const bool refill_num_row_entries = k_numRowEntries_.extent(0) != 0;
4760 if (refill_num_row_entries) {
4764 row_ptrs_type(view_alloc(
"num_row_entries", WithoutInitializing), N);
4765 Kokkos::deep_copy(num_row_entries, this->k_numRowEntries_);
4766 Kokkos::parallel_for(
4767 "Fill end row pointers", range_policy(0, N),
4768 KOKKOS_LAMBDA(
const size_t i) {
4769 row_ptrs_end(i) = row_ptrs_beg(i) + num_row_entries(i);
4775 Kokkos::parallel_for(
4776 "Fill end row pointers", range_policy(0, N),
4777 KOKKOS_LAMBDA(
const size_t i) {
4778 row_ptrs_end(i) = row_ptrs_beg(i + 1);
4782 if (isGloballyIndexed()) {
4784 padding, myRank, verbose);
4786 padCrsArrays(row_ptrs_beg, row_ptrs_end, lclIndsUnpacked_wdv,
4787 padding, myRank, verbose);
4790 if (refill_num_row_entries) {
4791 Kokkos::parallel_for(
4792 "Fill num entries", range_policy(0, N),
4793 KOKKOS_LAMBDA(
const size_t i) {
4794 num_row_entries(i) = row_ptrs_end(i) - row_ptrs_beg(i);
4796 Kokkos::deep_copy(this->k_numRowEntries_, num_row_entries);
4799 std::ostringstream os;
4800 os << *prefix <<
"Reassign k_rowPtrs_; old size: "
4801 << rowPtrsUnpacked_dev.extent(0) <<
", new size: "
4802 << row_ptrs_beg.extent(0) << endl;
4803 std::cerr << os.str();
4804 TEUCHOS_ASSERT(rowPtrsUnpacked_dev.extent(0) == row_ptrs_beg.extent(0));
4807 setRowPtrsUnpacked(row_ptrs_beg);
4810template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4812 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
4816 const size_t numSameIDs,
4821 const bool verbose)
const {
4825 std::unique_ptr<std::string> prefix;
4828 "computeCrsPadding(same & permute)");
4829 std::ostringstream os;
4830 os << *prefix <<
"{numSameIDs: " << numSameIDs
4831 <<
", numPermutes: " << permuteFromLIDs.extent(0) <<
"}"
4833 std::cerr << os.str();
4836 const int myRank = [&]() {
4837 auto comm = rowMap_.is_null() ? Teuchos::null : rowMap_->getComm();
4838 return comm.is_null() ? -1 : comm->getRank();
4840 std::unique_ptr<padding_type> padding(
4841 new padding_type(myRank, numSameIDs,
4842 permuteFromLIDs.extent(0)));
4844 computeCrsPaddingForSameIDs(*padding, source,
4845 static_cast<LO
>(numSameIDs));
4846 computeCrsPaddingForPermutedIDs(*padding, source, permuteToLIDs,
4851template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4854 padding_type& padding,
4860 using Details::Impl::getRowGraphGlobalRow;
4862 const char tfecfFuncName[] =
"computeCrsPaddingForSameIds";
4864 std::unique_ptr<std::string> prefix;
4865 const bool verbose = verbose_;
4867 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
4868 std::ostringstream os;
4869 os << *prefix <<
"numSameIDs: " << numSameIDs << endl;
4870 std::cerr << os.str();
4873 if (numSameIDs == 0) {
4877 const map_type& srcRowMap = *(source.getRowMap());
4878 const map_type& tgtRowMap = *rowMap_;
4880 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
4881 const bool src_is_unique =
4882 srcCrs ==
nullptr ? false : srcCrs->
isMerged();
4883 const bool tgt_is_unique = this->isMerged();
4885 std::vector<GO> srcGblColIndsScratch;
4886 std::vector<GO> tgtGblColIndsScratch;
4888 execute_sync_host_uvm_access();
4889 for (LO lclRowInd = 0; lclRowInd < numSameIDs; ++lclRowInd) {
4890 const GO srcGblRowInd = srcRowMap.getGlobalElement(lclRowInd);
4891 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(lclRowInd);
4892 auto srcGblColInds = getRowGraphGlobalRow(
4893 srcGblColIndsScratch, source, srcGblRowInd);
4894 auto tgtGblColInds = getRowGraphGlobalRow(
4895 tgtGblColIndsScratch, *
this, tgtGblRowInd);
4896 padding.update_same(lclRowInd, tgtGblColInds.getRawPtr(),
4897 tgtGblColInds.size(), tgt_is_unique,
4898 srcGblColInds.getRawPtr(),
4899 srcGblColInds.size(), src_is_unique);
4902 std::ostringstream os;
4903 os << *prefix <<
"Done" << endl;
4904 std::cerr << os.str();
4908template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4911 padding_type& padding,
4920 using Details::Impl::getRowGraphGlobalRow;
4922 const char tfecfFuncName[] =
"computeCrsPaddingForPermutedIds";
4924 std::unique_ptr<std::string> prefix;
4925 const bool verbose = verbose_;
4927 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
4928 std::ostringstream os;
4929 os << *prefix <<
"permuteToLIDs.extent(0): "
4930 << permuteToLIDs.extent(0)
4931 <<
", permuteFromLIDs.extent(0): "
4932 << permuteFromLIDs.extent(0) << endl;
4933 std::cerr << os.str();
4936 if (permuteToLIDs.extent(0) == 0) {
4940 const map_type& srcRowMap = *(source.getRowMap());
4941 const map_type& tgtRowMap = *rowMap_;
4943 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
4944 const bool src_is_unique =
4945 srcCrs ==
nullptr ? false : srcCrs->
isMerged();
4946 const bool tgt_is_unique = this->isMerged();
4948 TEUCHOS_ASSERT(!permuteToLIDs.need_sync_host());
4949 auto permuteToLIDs_h = permuteToLIDs.view_host();
4950 TEUCHOS_ASSERT(!permuteFromLIDs.need_sync_host());
4951 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
4953 std::vector<GO> srcGblColIndsScratch;
4954 std::vector<GO> tgtGblColIndsScratch;
4955 const LO numPermutes =
static_cast<LO
>(permuteToLIDs_h.extent(0));
4957 execute_sync_host_uvm_access();
4958 for (LO whichPermute = 0; whichPermute < numPermutes; ++whichPermute) {
4959 const LO srcLclRowInd = permuteFromLIDs_h[whichPermute];
4960 const GO srcGblRowInd = srcRowMap.getGlobalElement(srcLclRowInd);
4961 auto srcGblColInds = getRowGraphGlobalRow(
4962 srcGblColIndsScratch, source, srcGblRowInd);
4963 const LO tgtLclRowInd = permuteToLIDs_h[whichPermute];
4964 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(tgtLclRowInd);
4965 auto tgtGblColInds = getRowGraphGlobalRow(
4966 tgtGblColIndsScratch, *
this, tgtGblRowInd);
4967 padding.update_permute(whichPermute, tgtLclRowInd,
4968 tgtGblColInds.getRawPtr(),
4969 tgtGblColInds.size(), tgt_is_unique,
4970 srcGblColInds.getRawPtr(),
4971 srcGblColInds.size(), src_is_unique);
4975 std::ostringstream os;
4976 os << *prefix <<
"Done" << endl;
4977 std::cerr << os.str();
4981template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4983 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
4988 Kokkos::DualView<packet_type*, buffer_device_type> imports,
4989 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
4990 const bool verbose)
const {
4991 using Details::Impl::getRowGraphGlobalRow;
4995 const char tfecfFuncName[] =
"computeCrsPaddingForImports";
4997 std::unique_ptr<std::string> prefix;
4999 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5000 std::ostringstream os;
5001 os << *prefix <<
"importLIDs.extent(0): "
5002 << importLIDs.extent(0)
5003 <<
", imports.extent(0): "
5004 << imports.extent(0)
5005 <<
", numPacketsPerLID.extent(0): "
5006 << numPacketsPerLID.extent(0) << endl;
5007 std::cerr << os.str();
5010 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5011 const int myRank = [&]() {
5012 auto comm = rowMap_.is_null() ? Teuchos::null : rowMap_->getComm();
5013 return comm.is_null() ? -1 : comm->getRank();
5015 std::unique_ptr<padding_type> padding(
5016 new padding_type(myRank, numImports));
5018 if (imports.need_sync_host()) {
5019 imports.sync_host();
5021 auto imports_h = imports.view_host();
5022 if (numPacketsPerLID.need_sync_host()) {
5023 numPacketsPerLID.sync_host();
5025 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5027 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
5028 auto importLIDs_h = importLIDs.view_host();
5030 const map_type& tgtRowMap = *rowMap_;
5034 constexpr bool src_is_unique =
false;
5035 const bool tgt_is_unique = isMerged();
5037 std::vector<GO> tgtGblColIndsScratch;
5039 execute_sync_host_uvm_access();
5040 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5045 const LO origSrcNumEnt =
5046 static_cast<LO
>(numPacketsPerLID_h[whichImport]);
5047 GO*
const srcGblColInds = imports_h.data() + offset;
5049 const LO tgtLclRowInd = importLIDs_h[whichImport];
5050 const GO tgtGblRowInd =
5051 tgtRowMap.getGlobalElement(tgtLclRowInd);
5052 auto tgtGblColInds = getRowGraphGlobalRow(
5053 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5054 const size_t origTgtNumEnt(tgtGblColInds.size());
5056 padding->update_import(whichImport, tgtLclRowInd,
5057 tgtGblColInds.getRawPtr(),
5058 origTgtNumEnt, tgt_is_unique,
5060 origSrcNumEnt, src_is_unique);
5061 offset += origSrcNumEnt;
5065 std::ostringstream os;
5066 os << *prefix <<
"Done" << endl;
5067 std::cerr << os.str();
5072template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5074 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
5079 Kokkos::DualView<char*, buffer_device_type> imports,
5080 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
5081 const bool verbose)
const {
5083 using Details::Impl::getRowGraphGlobalRow;
5087 const char tfecfFuncName[] =
"computePaddingForCrsMatrixUnpack";
5089 std::unique_ptr<std::string> prefix;
5091 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5092 std::ostringstream os;
5093 os << *prefix <<
"importLIDs.extent(0): "
5094 << importLIDs.extent(0)
5095 <<
", imports.extent(0): "
5096 << imports.extent(0)
5097 <<
", numPacketsPerLID.extent(0): "
5098 << numPacketsPerLID.extent(0) << endl;
5099 std::cerr << os.str();
5101 const bool extraVerbose =
5104 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5105 TEUCHOS_ASSERT(LO(numPacketsPerLID.extent(0)) >= numImports);
5106 const int myRank = [&]() {
5107 auto comm = rowMap_.is_null() ? Teuchos::null : rowMap_->getComm();
5108 return comm.is_null() ? -1 : comm->getRank();
5110 std::unique_ptr<padding_type> padding(
5111 new padding_type(myRank, numImports));
5113 if (imports.need_sync_host()) {
5114 imports.sync_host();
5116 auto imports_h = imports.view_host();
5117 if (numPacketsPerLID.need_sync_host()) {
5118 numPacketsPerLID.sync_host();
5120 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5122 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
5123 auto importLIDs_h = importLIDs.view_host();
5125 const map_type& tgtRowMap = *rowMap_;
5129 constexpr bool src_is_unique =
false;
5130 const bool tgt_is_unique = isMerged();
5132 std::vector<GO> srcGblColIndsScratch;
5133 std::vector<GO> tgtGblColIndsScratch;
5135 execute_sync_host_uvm_access();
5136 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5141 const size_t numBytes = numPacketsPerLID_h[whichImport];
5143 std::ostringstream os;
5144 os << *prefix <<
"whichImport=" << whichImport
5145 <<
", numImports=" << numImports
5146 <<
", numBytes=" << numBytes << endl;
5147 std::cerr << os.str();
5149 if (numBytes == 0) {
5152 LO origSrcNumEnt = 0;
5153 const size_t numEntBeg = offset;
5154 const size_t numEntLen =
5155 PackTraits<LO>::packValueCount(origSrcNumEnt);
5156 TEUCHOS_ASSERT(numBytes >= numEntLen);
5157 TEUCHOS_ASSERT(imports_h.extent(0) >= numEntBeg + numEntLen);
5158 PackTraits<LO>::unpackValue(origSrcNumEnt,
5159 imports_h.data() + numEntBeg);
5161 std::ostringstream os;
5162 os << *prefix <<
"whichImport=" << whichImport
5163 <<
", numImports=" << numImports
5164 <<
", origSrcNumEnt=" << origSrcNumEnt << endl;
5165 std::cerr << os.str();
5167 TEUCHOS_ASSERT(origSrcNumEnt >= LO(0));
5168 TEUCHOS_ASSERT(numBytes >=
size_t(numEntLen + origSrcNumEnt *
sizeof(GO)));
5169 const size_t gidsBeg = numEntBeg + numEntLen;
5170 if (srcGblColIndsScratch.size() <
size_t(origSrcNumEnt)) {
5171 srcGblColIndsScratch.resize(origSrcNumEnt);
5173 GO*
const srcGblColInds = srcGblColIndsScratch.data();
5174 PackTraits<GO>::unpackArray(srcGblColInds,
5175 imports_h.data() + gidsBeg,
5177 const LO tgtLclRowInd = importLIDs_h[whichImport];
5178 const GO tgtGblRowInd =
5179 tgtRowMap.getGlobalElement(tgtLclRowInd);
5180 auto tgtGblColInds = getRowGraphGlobalRow(
5181 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5182 const size_t origNumTgtEnt(tgtGblColInds.size());
5185 std::ostringstream os;
5186 os << *prefix <<
"whichImport=" << whichImport
5187 <<
", numImports=" << numImports
5188 <<
": Call padding->update_import" << endl;
5189 std::cerr << os.str();
5191 padding->update_import(whichImport, tgtLclRowInd,
5192 tgtGblColInds.getRawPtr(),
5193 origNumTgtEnt, tgt_is_unique,
5195 origSrcNumEnt, src_is_unique);
5200 std::ostringstream os;
5201 os << *prefix <<
"Done" << endl;
5202 std::cerr << os.str();
5207template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5212 Kokkos::DualView<packet_type*,
5214 Kokkos::DualView<
size_t*,
5217 size_t& constantNumPackets) {
5218 using Tpetra::Details::ProfilingRegion;
5223 const char tfecfFuncName[] =
"packAndPrepare: ";
5224 ProfilingRegion region_papn(
"Tpetra::CrsGraph::packAndPrepare");
5226 const bool verbose = verbose_;
5227 std::unique_ptr<std::string> prefix;
5229 prefix = this->
createPrefix(
"CrsGraph",
"packAndPrepare");
5230 std::ostringstream os;
5231 os << *prefix <<
"Start" << endl;
5232 std::cerr << os.str();
5235 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(exportLIDs.extent(0) != numPacketsPerLID.extent(0),
5237 "exportLIDs.extent(0) = " << exportLIDs.extent(0)
5238 <<
" != numPacketsPerLID.extent(0) = " << numPacketsPerLID.extent(0)
5240 const row_graph_type* srcRowGraphPtr =
5241 dynamic_cast<const row_graph_type*
>(&source);
5242 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(srcRowGraphPtr ==
nullptr, std::invalid_argument,
5243 "Source of an Export "
5244 "or Import operation to a CrsGraph must be a RowGraph with the same "
5245 "template parameters.");
5249 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isFillComplete(), std::runtime_error,
5250 "The target graph of an Import or Export must not be fill complete.");
5255 if (srcCrsGraphPtr ==
nullptr) {
5256 using Teuchos::ArrayView;
5260 std::ostringstream os;
5261 os << *prefix <<
"Source is a RowGraph but not a CrsGraph"
5263 std::cerr << os.str();
5270 TEUCHOS_ASSERT(!exportLIDs.need_sync_host());
5271 auto exportLIDs_h = exportLIDs.view_host();
5272 ArrayView<const LO> exportLIDs_av(exportLIDs_h.data(),
5273 exportLIDs_h.extent(0));
5274 Teuchos::Array<GO> exports_a;
5276 numPacketsPerLID.clear_sync_state();
5277 numPacketsPerLID.modify_host();
5278 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5279 ArrayView<size_t> numPacketsPerLID_av(numPacketsPerLID_h.data(),
5280 numPacketsPerLID_h.extent(0));
5281 srcRowGraphPtr->pack(exportLIDs_av, exports_a, numPacketsPerLID_av,
5282 constantNumPackets);
5283 const size_t newSize =
static_cast<size_t>(exports_a.size());
5284 if (
static_cast<size_t>(exports.extent(0)) != newSize) {
5285 using exports_dv_type = Kokkos::DualView<packet_type*, buffer_device_type>;
5286 exports = exports_dv_type(
"exports", newSize);
5288 Kokkos::View<
const packet_type*, Kokkos::HostSpace,
5289 Kokkos::MemoryUnmanaged>
5290 exports_a_h(exports_a.getRawPtr(), newSize);
5291 exports.clear_sync_state();
5292 exports.modify_host();
5294 Kokkos::deep_copy(exports.view_host(), exports_a_h);
5297 else if (!getColMap().is_null() &&
5298 (this->getRowPtrsPackedDevice().extent(0) != 0 ||
5299 getRowMap()->getLocalNumElements() == 0)) {
5301 std::ostringstream os;
5302 os << *prefix <<
"packCrsGraphNew path" << endl;
5303 std::cerr << os.str();
5305 using export_pids_type =
5306 Kokkos::DualView<const int*, buffer_device_type>;
5307 export_pids_type exportPIDs;
5311 packCrsGraphNew<LO, GO, NT>(*srcCrsGraphPtr, exportLIDs, exportPIDs,
5312 exports, numPacketsPerLID,
5313 constantNumPackets,
false);
5315 srcCrsGraphPtr->packFillActiveNew(exportLIDs, exports, numPacketsPerLID,
5316 constantNumPackets);
5320 std::ostringstream os;
5321 os << *prefix <<
"Done" << endl;
5322 std::cerr << os.str();
5326template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5328 pack(
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5329 Teuchos::Array<GlobalOrdinal>& exports,
5330 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5331 size_t& constantNumPackets)
const {
5334 if (!col_map.is_null() && (this->getRowPtrsPackedDevice().extent(0) != 0 ||
getRowMap()->getLocalNumElements() == 0)) {
5336 packCrsGraph<LocalOrdinal, GlobalOrdinal, Node>(*
this, exports, numPacketsPerLID,
5337 exportLIDs, constantNumPackets);
5339 this->packFillActive(exportLIDs, exports, numPacketsPerLID,
5340 constantNumPackets);
5344template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5346 packFillActive(
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5347 Teuchos::Array<GlobalOrdinal>& exports,
5348 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5349 size_t& constantNumPackets)
const {
5351 using LO = LocalOrdinal;
5352 using GO = GlobalOrdinal;
5353 using host_execution_space =
5354 typename Kokkos::View<size_t*, device_type>::
5355 host_mirror_type::execution_space;
5356 const char tfecfFuncName[] =
"packFillActive: ";
5357 const bool verbose = verbose_;
5359 const auto numExportLIDs = exportLIDs.size();
5360 std::unique_ptr<std::string> prefix;
5362 prefix = this->createPrefix(
"CrsGraph",
"allocateIndices");
5363 std::ostringstream os;
5364 os << *prefix <<
"numExportLIDs=" << numExportLIDs << endl;
5365 std::cerr << os.str();
5367 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numExportLIDs != numPacketsPerLID.size(), std::runtime_error,
5368 "exportLIDs.size() = " << numExportLIDs <<
" != numPacketsPerLID.size()"
5370 << numPacketsPerLID.size() <<
".");
5372 const map_type& rowMap = *(this->getRowMap());
5373 const map_type*
const colMapPtr = this->colMap_.getRawPtr();
5374 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isLocallyIndexed() && colMapPtr ==
nullptr, std::logic_error,
5375 "This graph claims to be locally indexed, but its column Map is nullptr. "
5376 "This should never happen. Please report this bug to the Tpetra "
5380 constantNumPackets = 0;
5384 size_t*
const numPacketsPerLID_raw = numPacketsPerLID.getRawPtr();
5385 const LO*
const exportLIDs_raw = exportLIDs.getRawPtr();
5392 Kokkos::RangePolicy<host_execution_space, LO> inputRange(0, numExportLIDs);
5393 size_t totalNumPackets = 0;
5394 size_t errCount = 0;
5397 typedef Kokkos::Device<host_execution_space, Kokkos::HostSpace>
5399 Kokkos::View<size_t, host_device_type> errCountView(&errCount);
5400 constexpr size_t ONE = 1;
5402 execute_sync_host_uvm_access();
5403 Kokkos::parallel_reduce(
5404 "Tpetra::CrsGraph::pack: totalNumPackets",
5406 [=, *
this](
const LO& i,
size_t& curTotalNumPackets) {
5407 const GO gblRow = rowMap.getGlobalElement(exportLIDs_raw[i]);
5408 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid()) {
5409 Kokkos::atomic_add(&errCountView(), ONE);
5410 numPacketsPerLID_raw[i] = 0;
5412 const size_t numEnt = this->getNumEntriesInGlobalRow(gblRow);
5413 numPacketsPerLID_raw[i] = numEnt;
5414 curTotalNumPackets += numEnt;
5420 std::ostringstream os;
5421 os << *prefix <<
"totalNumPackets=" << totalNumPackets << endl;
5422 std::cerr << os.str();
5424 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(errCount != 0, std::logic_error,
5425 "totalNumPackets count encountered "
5426 "one or more errors! errCount = "
5428 <<
", totalNumPackets = " << totalNumPackets <<
".");
5432 exports.resize(totalNumPackets);
5434 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->supportsRowViews(), std::logic_error,
5435 "this->supportsRowViews() returns false; this should never happen. "
5436 "Please report this bug to the Tpetra developers.");
5442 std::ostringstream os;
5443 os << *prefix <<
"Pack into exports" << endl;
5444 std::cerr << os.str();
5449 GO*
const exports_raw = exports.getRawPtr();
5451 Kokkos::parallel_scan(
"Tpetra::CrsGraph::pack: pack from views",
5452 inputRange, [=, &prefix, *
this](
const LO i,
size_t& exportsOffset,
const bool final) {
5453 const size_t curOffset = exportsOffset;
5454 const GO gblRow = rowMap.getGlobalElement(exportLIDs_raw[i]);
5456 this->getRowInfoFromGlobalRowIndex(gblRow);
5458 using TDO = Tpetra::Details::OrdinalTraits<size_t>;
5459 if (rowInfo.localRow == TDO::invalid()) {
5461 std::ostringstream os;
5462 os << *prefix <<
": INVALID rowInfo: i=" << i
5463 <<
", lclRow=" << exportLIDs_raw[i] << endl;
5464 std::cerr << os.str();
5466 Kokkos::atomic_add(&errCountView(), ONE);
5467 }
else if (curOffset + rowInfo.numEntries > totalNumPackets) {
5469 std::ostringstream os;
5470 os << *prefix <<
": UH OH! For i=" << i <<
", lclRow="
5471 << exportLIDs_raw[i] <<
", gblRow=" << gblRow <<
", curOffset "
5473 << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5474 <<
") > totalNumPackets (= " << totalNumPackets <<
")."
5476 std::cerr << os.str();
5478 Kokkos::atomic_add(&errCountView(), ONE);
5480 const LO numEnt =
static_cast<LO
>(rowInfo.numEntries);
5481 if (this->isLocallyIndexed()) {
5482 auto lclColInds = getLocalIndsViewHost(rowInfo);
5484 for (LO k = 0; k < numEnt; ++k) {
5485 const LO lclColInd = lclColInds(k);
5486 const GO gblColInd = colMapPtr->getGlobalElement(lclColInd);
5490 exports_raw[curOffset + k] = gblColInd;
5493 exportsOffset = curOffset + numEnt;
5494 }
else if (this->isGloballyIndexed()) {
5495 auto gblColInds = getGlobalIndsViewHost(rowInfo);
5497 for (LO k = 0; k < numEnt; ++k) {
5498 const GO gblColInd = gblColInds(k);
5502 exports_raw[curOffset + k] = gblColInd;
5505 exportsOffset = curOffset + numEnt;
5513 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(errCount != 0, std::logic_error,
5514 "Packing encountered "
5515 "one or more errors! errCount = "
5517 <<
", totalNumPackets = " << totalNumPackets <<
".");
5520 std::ostringstream os;
5521 os << *prefix <<
"Done" << endl;
5522 std::cerr << os.str();
5526template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5530 Kokkos::DualView<packet_type*,
5532 Kokkos::DualView<
size_t*,
5535 size_t& constantNumPackets)
const {
5539 using host_execution_space =
typename Kokkos::View<
size_t*,
5541 using host_device_type =
5542 Kokkos::Device<host_execution_space, Kokkos::HostSpace>;
5543 using exports_dv_type =
5544 Kokkos::DualView<packet_type*, buffer_device_type>;
5545 const char tfecfFuncName[] =
"packFillActiveNew: ";
5546 const bool verbose = verbose_;
5548 const auto numExportLIDs = exportLIDs.extent(0);
5549 std::unique_ptr<std::string> prefix;
5551 prefix = this->
createPrefix(
"CrsGraph",
"packFillActiveNew");
5552 std::ostringstream os;
5553 os << *prefix <<
"numExportLIDs: " << numExportLIDs
5554 <<
", numPacketsPerLID.extent(0): "
5555 << numPacketsPerLID.extent(0) << endl;
5556 std::cerr << os.str();
5558 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numExportLIDs != numPacketsPerLID.extent(0), std::runtime_error,
5559 "exportLIDs.extent(0) = " << numExportLIDs
5560 <<
" != numPacketsPerLID.extent(0) = "
5561 << numPacketsPerLID.extent(0) <<
".");
5562 TEUCHOS_ASSERT(!exportLIDs.need_sync_host());
5563 auto exportLIDs_h = exportLIDs.view_host();
5565 const map_type& rowMap = *(this->getRowMap());
5566 const map_type*
const colMapPtr = this->colMap_.getRawPtr();
5567 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isLocallyIndexed() && colMapPtr ==
nullptr, std::logic_error,
5568 "This graph claims to be locally indexed, but its column Map is nullptr. "
5569 "This should never happen. Please report this bug to the Tpetra "
5573 constantNumPackets = 0;
5575 numPacketsPerLID.clear_sync_state();
5576 numPacketsPerLID.modify_host();
5577 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5584 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
5585 range_type inputRange(0, numExportLIDs);
5586 size_t totalNumPackets = 0;
5587 size_t errCount = 0;
5590 Kokkos::View<size_t, host_device_type> errCountView(&errCount);
5591 constexpr size_t ONE = 1;
5594 std::ostringstream os;
5595 os << *prefix <<
"Compute totalNumPackets" << endl;
5596 std::cerr << os.str();
5599 execute_sync_host_uvm_access();
5600 totalNumPackets = 0;
5601 for (
size_t i = 0; i < numExportLIDs; ++i) {
5602 const LO lclRow = exportLIDs_h[i];
5603 const GO gblRow = rowMap.getGlobalElement(lclRow);
5604 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid()) {
5606 std::ostringstream os;
5607 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5608 <<
" not in row Map on this process" << endl;
5609 std::cerr << os.str();
5611 Kokkos::atomic_add(&errCountView(), ONE);
5612 numPacketsPerLID_h(i) = 0;
5614 const size_t numEnt = this->getNumEntriesInGlobalRow(gblRow);
5615 numPacketsPerLID_h(i) = numEnt;
5616 totalNumPackets += numEnt;
5621 std::ostringstream os;
5622 os << *prefix <<
"totalNumPackets: " << totalNumPackets
5623 <<
", errCount: " << errCount << endl;
5624 std::cerr << os.str();
5626 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(errCount != 0, std::logic_error,
5627 "totalNumPackets count encountered "
5628 "one or more errors! totalNumPackets: "
5630 <<
", errCount: " << errCount <<
".");
5633 if (
size_t(exports.extent(0)) < totalNumPackets) {
5635 exports = exports_dv_type(
"exports", totalNumPackets);
5638 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->supportsRowViews(), std::logic_error,
5639 "this->supportsRowViews() returns false; this should never happen. "
5640 "Please report this bug to the Tpetra developers.");
5646 std::ostringstream os;
5647 os << *prefix <<
"Pack into exports buffer" << endl;
5648 std::cerr << os.str();
5651 exports.clear_sync_state();
5652 exports.modify_host();
5653 auto exports_h = exports.view_host();
5659 if (isLocallyIndexed())
5660 lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
5661 else if (isGloballyIndexed())
5662 gblInds_wdv.getHostView(Access::ReadOnly);
5665 Kokkos::parallel_scan(
"Tpetra::CrsGraph::packFillActiveNew: Pack exports",
5666 inputRange, [=, &prefix, *
this](
const LO i,
size_t& exportsOffset,
const bool final) {
5667 const size_t curOffset = exportsOffset;
5668 const LO lclRow = exportLIDs_h(i);
5669 const GO gblRow = rowMap.getGlobalElement(lclRow);
5670 if (gblRow == Details::OrdinalTraits<GO>::invalid()) {
5672 std::ostringstream os;
5673 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5674 <<
" not in row Map on this process" << endl;
5675 std::cerr << os.str();
5677 Kokkos::atomic_add(&errCountView(), ONE);
5681 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex(gblRow);
5682 if (rowInfo.localRow == Details::OrdinalTraits<size_t>::invalid()) {
5684 std::ostringstream os;
5685 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5686 <<
", gblRow=" << gblRow <<
": invalid rowInfo"
5688 std::cerr << os.str();
5690 Kokkos::atomic_add(&errCountView(), ONE);
5694 if (curOffset + rowInfo.numEntries > totalNumPackets) {
5696 std::ostringstream os;
5697 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5698 <<
", gblRow=" << gblRow <<
", curOffset (= "
5699 << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5700 <<
") > totalNumPackets (= " << totalNumPackets
5702 std::cerr << os.str();
5704 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_h(curOffset + k) = gblColInd;
5721 exportsOffset = curOffset + numEnt;
5722 }
else if (this->isGloballyIndexed()) {
5723 auto gblColInds = getGlobalIndsViewHost(rowInfo);
5725 for (LO k = 0; k < numEnt; ++k) {
5726 const GO gblColInd = gblColInds(k);
5730 exports_h(curOffset + k) = gblColInd;
5733 exportsOffset = curOffset + numEnt;
5747 std::ostringstream os;
5748 os << *prefix <<
"errCount=" << errCount <<
"; Done" << endl;
5749 std::cerr << os.str();
5753template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5760 Kokkos::DualView<
size_t*,
5769 const char tfecfFuncName[] =
"unpackAndCombine";
5771 ProfilingRegion regionCGC(
"Tpetra::CrsGraph::unpackAndCombine");
5772 const bool verbose = verbose_;
5774 std::unique_ptr<std::string> prefix;
5776 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
5777 std::ostringstream os;
5778 os << *prefix <<
"Start" << endl;
5779 std::cerr << os.str();
5782 auto padding = computeCrsPaddingForImports(
5783 importLIDs, imports, numPacketsPerLID, verbose);
5784 applyCrsPadding(*padding, verbose);
5786 std::ostringstream os;
5787 os << *prefix <<
"Done computing & applying padding" << endl;
5788 std::cerr << os.str();
5809 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(importLIDs.extent(0) != numPacketsPerLID.extent(0),
5810 std::runtime_error,
": importLIDs.extent(0) = " << importLIDs.extent(0) <<
" != numPacketsPerLID.extent(0) = " << numPacketsPerLID.extent(0) <<
".");
5811 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
isFillComplete(), std::runtime_error,
5812 ": Import or Export operations are not allowed on a target "
5813 "CrsGraph that is fillComplete.");
5815 const size_t numImportLIDs(importLIDs.extent(0));
5816 if (numPacketsPerLID.need_sync_host()) {
5817 numPacketsPerLID.sync_host();
5819 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5820 if (imports.need_sync_host()) {
5821 imports.sync_host();
5823 auto imports_h = imports.view_host();
5824 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
5825 auto importLIDs_h = importLIDs.view_host();
5828 Teuchos::Array<LO> lclColInds;
5831 std::ostringstream os;
5832 os << *prefix <<
"Preallocate local indices scratch" << endl;
5833 std::cerr << os.str();
5835 size_t maxNumInserts = 0;
5836 for (
size_t i = 0; i < numImportLIDs; ++i) {
5837 maxNumInserts = std::max(maxNumInserts, numPacketsPerLID_h[i]);
5840 std::ostringstream os;
5841 os << *prefix <<
"Local indices scratch size: "
5842 << maxNumInserts << endl;
5843 std::cerr << os.str();
5845 lclColInds.resize(maxNumInserts);
5848 std::ostringstream os;
5851 os <<
"Graph is globally indexed";
5853 os <<
"Graph is neither locally nor globally indexed";
5856 std::cerr << os.str();
5860 TEUCHOS_ASSERT(!
rowMap_.is_null());
5864 size_t importsOffset = 0;
5865 for (
size_t i = 0; i < numImportLIDs; ++i) {
5867 std::ostringstream os;
5868 os << *prefix <<
"i=" << i <<
", numImportLIDs="
5869 << numImportLIDs << endl;
5870 std::cerr << os.str();
5874 const LO lclRow = importLIDs_h[i];
5876 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(gblRow == Teuchos::OrdinalTraits<GO>::invalid(),
5877 std::logic_error,
"importLIDs[i=" << i <<
"]=" << lclRow <<
" is not in the row Map on the calling "
5879 const LO numEnt = numPacketsPerLID_h[i];
5880 const GO*
const gblColInds = (numEnt == 0) ?
nullptr : imports_h.data() + importsOffset;
5886 for (LO j = 0; j < numEnt; j++) {
5887 lclColInds[j] =
colMap_->getLocalElement(gblColInds[j]);
5891 importsOffset += numEnt;
5893 }
catch (std::exception& e) {
5894 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
5895 "Tpetra::CrsGraph::unpackAndCombine: Insert loop threw an "
5902 std::ostringstream os;
5903 os << *prefix <<
"Done" << endl;
5904 std::cerr << os.str();
5908template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5911 using Teuchos::Comm;
5912 using Teuchos::null;
5913 using Teuchos::ParameterList;
5919 RCP<const map_type> rowMap, domainMap, rangeMap, colMap;
5920 RCP<import_type> importer;
5921 RCP<export_type> exporter;
5924 RCP<const Comm<int>> newComm =
5925 (newMap.is_null()) ? null : newMap->getComm();
5935 domainMap =
domainMap_->replaceCommWithSubset(newComm);
5946 rangeMap =
rangeMap_->replaceCommWithSubset(newComm);
5950 colMap =
colMap_->replaceCommWithSubset(newComm);
5954 if (!newComm.is_null()) {
5955 RCP<ParameterList> params = this->getNonconstParameterList();
5964 rangeMap != rowMap &&
5965 !rangeMap->isSameAs(*rowMap)) {
5966 if (params.is_null() || !params->isSublist(
"Export")) {
5967 exporter = rcp(
new export_type(rowMap, rangeMap));
5969 RCP<ParameterList> exportSublist = sublist(params,
"Export",
true);
5970 exporter = rcp(
new export_type(rowMap, rangeMap, exportSublist));
5975 domainMap != colMap &&
5976 !domainMap->isSameAs(*colMap)) {
5977 if (params.is_null() || !params->isSublist(
"Import")) {
5978 importer = rcp(
new import_type(domainMap, colMap));
5980 RCP<ParameterList> importSublist = sublist(params,
"Import",
true);
5981 importer = rcp(
new import_type(domainMap, colMap, importSublist));
5997 this->
map_ = rowMap;
6003template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6005 getLocalDiagOffsets(
const Kokkos::View<size_t*, device_type, Kokkos::MemoryUnmanaged>& offsets)
const {
6007 using LO = LocalOrdinal;
6008 using GO = GlobalOrdinal;
6009 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6010 const bool verbose = verbose_;
6012 std::unique_ptr<std::string> prefix;
6014 prefix = this->createPrefix(
"CrsGraph",
"getLocalDiagOffsets");
6015 std::ostringstream os;
6016 os << *prefix <<
"offsets.extent(0)=" << offsets.extent(0)
6018 std::cerr << os.str();
6021 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
hasColMap(), std::runtime_error,
"The graph must have a column Map.");
6023 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<LO
>(offsets.extent(0)) < lclNumRows,
6024 std::invalid_argument,
"offsets.extent(0) = " << offsets.extent(0) <<
" < getLocalNumRows() = " << lclNumRows <<
".");
6033 bool allRowMapDiagEntriesInColMap =
true;
6034 bool allDiagEntriesFound =
true;
6035 bool allOffsetsCorrect =
true;
6036 bool noOtherWeirdness =
true;
6037 using wrong_offsets_type = std::vector<std::pair<LO, size_t>>;
6038 wrong_offsets_type wrongOffsets(0);
6049 const bool sorted = this->
isSorted();
6052 ::Tpetra::Details::getGraphDiagOffsets(offsets, lclRowMap, lclColMap,
6054 lclGraph.entries, sorted);
6059 auto offsets_h = Kokkos::create_mirror_view(offsets);
6061 for (LO lclRowInd = 0; lclRowInd < lclNumRows; ++lclRowInd) {
6065 const GO gblRowInd = lclRowMap.getGlobalElement(lclRowInd);
6066 const GO gblColInd = gblRowInd;
6067 const LO lclColInd = lclColMap.getLocalElement(gblColInd);
6069 if (lclColInd == Tpetra::Details::OrdinalTraits<LO>::invalid()) {
6070 allRowMapDiagEntriesInColMap =
false;
6071 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid();
6074 if (
static_cast<LO
>(rowInfo.localRow) == lclRowInd &&
6075 rowInfo.numEntries > 0) {
6077 const size_t hint = 0;
6078 const size_t offset =
6079 KokkosSparse::findRelOffset(colInds, rowInfo.numEntries,
6080 lclColInd, hint, sorted);
6081 offsets_h(lclRowInd) = offset;
6088 typename local_inds_dualv_type::t_host::const_type lclColInds;
6092 noOtherWeirdness =
false;
6095 if (noOtherWeirdness) {
6096 const size_t numEnt = lclColInds.extent(0);
6097 if (offset >= numEnt) {
6100 allOffsetsCorrect =
false;
6101 wrongOffsets.push_back(std::make_pair(lclRowInd, offset));
6103 const LO actualLclColInd = lclColInds(offset);
6104 const GO actualGblColInd = lclColMap.getGlobalElement(actualLclColInd);
6105 if (actualGblColInd != gblColInd) {
6106 allOffsetsCorrect =
false;
6107 wrongOffsets.push_back(std::make_pair(lclRowInd, offset));
6113 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid();
6114 allDiagEntriesFound =
false;
6119 Kokkos::deep_copy(offsets, offsets_h);
6122 if (verbose && wrongOffsets.size() != 0) {
6123 std::ostringstream os;
6124 os << *prefix <<
"Wrong offsets: [";
6125 for (
size_t k = 0; k < wrongOffsets.size(); ++k) {
6126 os <<
"(" << wrongOffsets[k].first <<
","
6127 << wrongOffsets[k].second <<
")";
6128 if (k + 1 < wrongOffsets.size()) {
6133 std::cerr << os.str();
6138 using Teuchos::reduceAll;
6139 Teuchos::RCP<const Teuchos::Comm<int>> comm = this->
getComm();
6140 const bool localSuccess =
6141 allRowMapDiagEntriesInColMap && allDiagEntriesFound && allOffsetsCorrect;
6142 const int numResults = 5;
6144 lclResults[0] = allRowMapDiagEntriesInColMap ? 1 : 0;
6145 lclResults[1] = allDiagEntriesFound ? 1 : 0;
6146 lclResults[2] = allOffsetsCorrect ? 1 : 0;
6147 lclResults[3] = noOtherWeirdness ? 1 : 0;
6150 lclResults[4] = !localSuccess ? comm->getRank() : comm->getSize();
6158 reduceAll<int, int>(*comm, Teuchos::REDUCE_MIN,
6159 numResults, lclResults, gblResults);
6161 if (gblResults[0] != 1 || gblResults[1] != 1 || gblResults[2] != 1 || gblResults[3] != 1) {
6162 std::ostringstream os;
6163 os <<
"Issue(s) that we noticed (on Process " << gblResults[4] <<
", "
6164 "possibly among others): "
6166 if (gblResults[0] == 0) {
6167 os <<
" - The column Map does not contain at least one diagonal entry "
6171 if (gblResults[1] == 0) {
6172 os <<
" - On one or more processes, some row does not contain a "
6176 if (gblResults[2] == 0) {
6177 os <<
" - On one or more processes, some offsets are incorrect."
6180 if (gblResults[3] == 0) {
6181 os <<
" - One or more processes had some other error."
6184 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
6189template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6193 const char tfecfFuncName[] =
"getLocalOffRankOffsets: ";
6194 const bool verbose = verbose_;
6196 std::unique_ptr<std::string> prefix;
6198 prefix = this->createPrefix(
"CrsGraph",
"getLocalOffRankOffsets");
6199 std::ostringstream os;
6200 os << *prefix <<
"offsets.extent(0)=" << offsets.extent(0)
6202 std::cerr << os.str();
6205 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
hasColMap(), std::runtime_error,
"The graph must have a column Map.");
6210 if (haveLocalOffRankOffsets_ &&
k_offRankOffsets_.extent(0) == lclNumRows + 1) {
6214 haveLocalOffRankOffsets_ =
false;
6230 k_offRankOffsets_ = offset_device_view_type(Kokkos::ViewAllocateWithoutInitializing(
"offRankOffset"), lclNumRows + 1);
6233 lclColMap, lclDomMap,
6236 haveLocalOffRankOffsets_ =
true;
6238 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
"Can't get off-rank offsets for non-fill-complete graph");
6260template <
class DeviceType,
6261 const bool memSpaceIsHostSpace =
6262 std::is_same<
typename DeviceType::memory_space,
6263 Kokkos::HostSpace>::value>
6264struct HelpGetLocalDiagOffsets {};
6266template <
class DeviceType>
6267struct HelpGetLocalDiagOffsets<DeviceType, true> {
6268 typedef DeviceType device_type;
6269 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6270 Kokkos::MemoryUnmanaged>
6271 device_offsets_type;
6272 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6273 Kokkos::MemoryUnmanaged>
6276 static device_offsets_type
6277 getDeviceOffsets(
const host_offsets_type& hostOffsets) {
6284 copyBackIfNeeded(
const host_offsets_type& ,
6285 const device_offsets_type& ) {
6289template <
class DeviceType>
6290struct HelpGetLocalDiagOffsets<DeviceType, false> {
6291 typedef DeviceType device_type;
6295 typedef Kokkos::View<size_t*, device_type> device_offsets_type;
6296 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6297 Kokkos::MemoryUnmanaged>
6300 static device_offsets_type
6301 getDeviceOffsets(
const host_offsets_type& hostOffsets) {
6304 return device_offsets_type(
"offsets", hostOffsets.extent(0));
6308 copyBackIfNeeded(
const host_offsets_type& hostOffsets,
6309 const device_offsets_type& deviceOffsets) {
6311 Kokkos::deep_copy(hostOffsets, deviceOffsets);
6316template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6319 typedef LocalOrdinal LO;
6320 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6321 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->
hasColMap(), std::runtime_error,
6322 "The graph does not yet have a column Map.");
6324 if (
static_cast<LO
>(offsets.size()) != myNumRows) {
6328 offsets.resize(myNumRows);
6340 typedef HelpGetLocalDiagOffsets<device_type> helper_type;
6341 typedef typename helper_type::host_offsets_type host_offsets_type;
6343 host_offsets_type hostOffsets(offsets.getRawPtr(), myNumRows);
6345 auto deviceOffsets = helper_type::getDeviceOffsets(hostOffsets);
6348 helper_type::copyBackIfNeeded(hostOffsets, deviceOffsets);
6351template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6357template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6360 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& rowTransfer,
6361 const Teuchos::RCP<const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>>& domainTransfer,
6362 const Teuchos::RCP<const map_type>& domainMap,
6363 const Teuchos::RCP<const map_type>& rangeMap,
6364 const Teuchos::RCP<Teuchos::ParameterList>& params)
const {
6366 using Teuchos::ArrayRCP;
6367 using Teuchos::ArrayView;
6368 using Teuchos::Comm;
6369 using Teuchos::ParameterList;
6377 using LO = LocalOrdinal;
6378 using GO = GlobalOrdinal;
6383 const char* prefix =
"Tpetra::CrsGraph::transferAndFillComplete: ";
6394 TEUCHOS_TEST_FOR_EXCEPTION(
6395 xferAsImport ==
nullptr && xferAsExport ==
nullptr, std::invalid_argument,
6396 prefix <<
"The 'rowTransfer' input argument must be either an Import or "
6397 "an Export, and its template parameters must match the corresponding "
6398 "template parameters of the CrsGraph.");
6405 Teuchos::RCP<const import_type> xferDomainAsImport =
6406 Teuchos::rcp_dynamic_cast<const import_type>(domainTransfer);
6407 Teuchos::RCP<const export_type> xferDomainAsExport =
6408 Teuchos::rcp_dynamic_cast<const export_type>(domainTransfer);
6410 if (!domainTransfer.is_null()) {
6411 TEUCHOS_TEST_FOR_EXCEPTION(
6412 (xferDomainAsImport.is_null() && xferDomainAsExport.is_null()), std::invalid_argument,
6413 prefix <<
"The 'domainTransfer' input argument must be either an "
6414 "Import or an Export, and its template parameters must match the "
6415 "corresponding template parameters of the CrsGraph.");
6417 TEUCHOS_TEST_FOR_EXCEPTION(
6418 (xferAsImport !=
nullptr || !xferDomainAsImport.is_null()) &&
6419 ((xferAsImport !=
nullptr && xferDomainAsImport.is_null()) ||
6420 (xferAsImport ==
nullptr && !xferDomainAsImport.is_null())),
6421 std::invalid_argument,
6422 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6423 "must be of the same type (either Import or Export).");
6425 TEUCHOS_TEST_FOR_EXCEPTION(
6426 (xferAsExport !=
nullptr || !xferDomainAsExport.is_null()) &&
6427 ((xferAsExport !=
nullptr && xferDomainAsExport.is_null()) ||
6428 (xferAsExport ==
nullptr && !xferDomainAsExport.is_null())),
6429 std::invalid_argument,
6430 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6431 "must be of the same type (either Import or Export).");
6437 const bool communication_needed = rowTransfer.getSourceMap()->isDistributed();
6443 bool reverseMode =
false;
6444 bool restrictComm =
false;
6445 RCP<ParameterList> graphparams;
6446 if (!params.is_null()) {
6447 reverseMode = params->get(
"Reverse Mode", reverseMode);
6448 restrictComm = params->get(
"Restrict Communicator", restrictComm);
6449 graphparams = sublist(params,
"CrsGraph");
6454 RCP<const map_type> MyRowMap = reverseMode ? rowTransfer.getSourceMap() : rowTransfer.getTargetMap();
6455 RCP<const map_type> MyColMap;
6456 RCP<const map_type> MyDomainMap = !domainMap.is_null() ? domainMap : getDomainMap();
6457 RCP<const map_type> MyRangeMap = !rangeMap.is_null() ? rangeMap : getRangeMap();
6458 RCP<const map_type> BaseRowMap = MyRowMap;
6459 RCP<const map_type> BaseDomainMap = MyDomainMap;
6467 if (!destGraph.is_null()) {
6478 const bool NewFlag =
6479 !destGraph->isLocallyIndexed() && !destGraph->isGloballyIndexed();
6480 TEUCHOS_TEST_FOR_EXCEPTION(!NewFlag, std::invalid_argument,
6481 prefix <<
"The input argument 'destGraph' is only allowed to be nonnull, "
6482 "if its graph is empty (neither locally nor globally indexed).");
6491 TEUCHOS_TEST_FOR_EXCEPTION(
6492 !destGraph->getRowMap()->isSameAs(*MyRowMap), std::invalid_argument,
6493 prefix <<
"The (row) Map of the input argument 'destGraph' is not the "
6494 "same as the (row) Map specified by the input argument 'rowTransfer'.");
6496 TEUCHOS_TEST_FOR_EXCEPTION(
6497 !destGraph->checkSizes(*
this), std::invalid_argument,
6498 prefix <<
"You provided a nonnull destination graph, but checkSizes() "
6499 "indicates that it is not a legal legal target for redistribution from "
6500 "the source graph (*this). This may mean that they do not have the "
6501 "same dimensions.");
6515 TEUCHOS_TEST_FOR_EXCEPTION(
6516 !(reverseMode || getRowMap()->isSameAs(*rowTransfer.getSourceMap())),
6517 std::invalid_argument, prefix <<
"rowTransfer->getSourceMap() must match this->getRowMap() in forward mode.");
6519 TEUCHOS_TEST_FOR_EXCEPTION(
6520 !(!reverseMode || getRowMap()->isSameAs(*rowTransfer.getTargetMap())),
6521 std::invalid_argument, prefix <<
"rowTransfer->getTargetMap() must match this->getRowMap() in reverse mode.");
6524 TEUCHOS_TEST_FOR_EXCEPTION(
6525 !xferDomainAsImport.is_null() && !xferDomainAsImport->getTargetMap()->isSameAs(*domainMap),
6526 std::invalid_argument,
6527 prefix <<
"The target map of the 'domainTransfer' input argument must be "
6528 "the same as the rebalanced domain map 'domainMap'");
6530 TEUCHOS_TEST_FOR_EXCEPTION(
6531 !xferDomainAsExport.is_null() && !xferDomainAsExport->getSourceMap()->isSameAs(*domainMap),
6532 std::invalid_argument,
6533 prefix <<
"The source map of the 'domainTransfer' input argument must be "
6534 "the same as the rebalanced domain map 'domainMap'");
6547 const size_t NumSameIDs = rowTransfer.getNumSameIDs();
6548 ArrayView<const LO> ExportLIDs = reverseMode ? rowTransfer.getRemoteLIDs() : rowTransfer.getExportLIDs();
6549 ArrayView<const LO> RemoteLIDs = reverseMode ? rowTransfer.getExportLIDs() : rowTransfer.getRemoteLIDs();
6550 ArrayView<const LO> PermuteToLIDs = reverseMode ? rowTransfer.getPermuteFromLIDs() : rowTransfer.getPermuteToLIDs();
6551 ArrayView<const LO> PermuteFromLIDs = reverseMode ? rowTransfer.getPermuteToLIDs() : rowTransfer.getPermuteFromLIDs();
6552 Distributor& Distor = rowTransfer.getDistributor();
6555 Teuchos::Array<int> SourcePids;
6556 Teuchos::Array<int> TargetPids;
6557 int MyPID = getComm()->getRank();
6560 RCP<const map_type> ReducedRowMap, ReducedColMap,
6561 ReducedDomainMap, ReducedRangeMap;
6562 RCP<const Comm<int>> ReducedComm;
6566 if (destGraph.is_null()) {
6567 destGraph = rcp(
new this_CRS_type(MyRowMap, 0, graphparams));
6574 ReducedRowMap = MyRowMap->removeEmptyProcesses();
6575 ReducedComm = ReducedRowMap.is_null() ? Teuchos::null : ReducedRowMap->getComm();
6576 destGraph->removeEmptyProcessesInPlace(ReducedRowMap);
6578 ReducedDomainMap = MyRowMap.getRawPtr() == MyDomainMap.getRawPtr() ? ReducedRowMap : MyDomainMap->replaceCommWithSubset(ReducedComm);
6579 ReducedRangeMap = MyRowMap.getRawPtr() == MyRangeMap.getRawPtr() ? ReducedRowMap : MyRangeMap->replaceCommWithSubset(ReducedComm);
6582 MyRowMap = ReducedRowMap;
6583 MyDomainMap = ReducedDomainMap;
6584 MyRangeMap = ReducedRangeMap;
6587 if (!ReducedComm.is_null()) {
6588 MyPID = ReducedComm->getRank();
6593 ReducedComm = MyRowMap->getComm();
6600 MM = Teuchos::rcp(
new Tpetra::Details::ProfilingRegion(
"Tpetra CrsGraph TAFC ImportSetup"));
6602 RCP<const import_type> MyImporter = getImporter();
6605 bool bSameDomainMap = BaseDomainMap->isSameAs(*getDomainMap());
6607 if (!restrictComm && !MyImporter.is_null() && bSameDomainMap) {
6615 }
else if (restrictComm && !MyImporter.is_null() && bSameDomainMap) {
6618 ivector_type SourceDomain_pids(getDomainMap(),
true);
6619 ivector_type SourceCol_pids(getColMap());
6621 SourceDomain_pids.putScalar(MyPID);
6623 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6624 SourcePids.resize(getColMap()->getLocalNumElements());
6625 SourceCol_pids.get1dCopy(SourcePids());
6626 }
else if (MyImporter.is_null() && bSameDomainMap) {
6628 SourcePids.resize(getColMap()->getLocalNumElements());
6629 SourcePids.assign(getColMap()->getLocalNumElements(), MyPID);
6630 }
else if (!MyImporter.is_null() &&
6631 !domainTransfer.is_null()) {
6638 ivector_type TargetDomain_pids(domainMap);
6639 TargetDomain_pids.putScalar(MyPID);
6642 ivector_type SourceDomain_pids(getDomainMap());
6645 ivector_type SourceCol_pids(getColMap());
6647 if (!reverseMode && !xferDomainAsImport.is_null()) {
6648 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6649 }
else if (reverseMode && !xferDomainAsExport.is_null()) {
6650 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6651 }
else if (!reverseMode && !xferDomainAsExport.is_null()) {
6652 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6653 }
else if (reverseMode && !xferDomainAsImport.is_null()) {
6654 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6656 TEUCHOS_TEST_FOR_EXCEPTION(
6657 true, std::logic_error,
6658 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6660 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6661 SourcePids.resize(getColMap()->getLocalNumElements());
6662 SourceCol_pids.get1dCopy(SourcePids());
6663 }
else if (BaseDomainMap->isSameAs(*BaseRowMap) &&
6664 getDomainMap()->isSameAs(*getRowMap())) {
6666 ivector_type TargetRow_pids(domainMap);
6667 ivector_type SourceRow_pids(getRowMap());
6668 ivector_type SourceCol_pids(getColMap());
6670 TargetRow_pids.putScalar(MyPID);
6671 if (!reverseMode && xferAsImport !=
nullptr) {
6672 SourceRow_pids.doExport(TargetRow_pids, *xferAsImport,
INSERT);
6673 }
else if (reverseMode && xferAsExport !=
nullptr) {
6674 SourceRow_pids.doExport(TargetRow_pids, *xferAsExport,
INSERT);
6675 }
else if (!reverseMode && xferAsExport !=
nullptr) {
6676 SourceRow_pids.doImport(TargetRow_pids, *xferAsExport,
INSERT);
6677 }
else if (reverseMode && xferAsImport !=
nullptr) {
6678 SourceRow_pids.doImport(TargetRow_pids, *xferAsImport,
INSERT);
6680 TEUCHOS_TEST_FOR_EXCEPTION(
6681 true, std::logic_error,
6682 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6684 SourceCol_pids.doImport(SourceRow_pids, *MyImporter,
INSERT);
6685 SourcePids.resize(getColMap()->getLocalNumElements());
6686 SourceCol_pids.get1dCopy(SourcePids());
6688 TEUCHOS_TEST_FOR_EXCEPTION(
6689 true, std::invalid_argument,
6690 prefix <<
"This method only allows either domainMap == getDomainMap(), "
6691 "or (domainMap == rowTransfer.getTargetMap() and getDomainMap() == getRowMap()).");
6695 size_t constantNumPackets = destGraph->constantNumberOfPackets();
6696 if (constantNumPackets == 0) {
6697 destGraph->reallocArraysForNumPacketsPerLid(ExportLIDs.size(),
6704 const size_t rbufLen = RemoteLIDs.size() * constantNumPackets;
6705 destGraph->reallocImportsIfNeeded(rbufLen,
false,
nullptr);
6710 destGraph->numExportPacketsPerLID_.modify_host();
6711 Teuchos::ArrayView<size_t> numExportPacketsPerLID =
6716 numExportPacketsPerLID, ExportLIDs,
6717 SourcePids, constantNumPackets);
6722 MM = Teuchos::rcp(
new Tpetra::Details::ProfilingRegion(
"Tpetra CrsGraph TAFC Transfer"));
6724 if (communication_needed) {
6726 if (constantNumPackets == 0) {
6730 destGraph->numExportPacketsPerLID_.sync_host();
6731 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
6733 destGraph->numImportPacketsPerLID_.sync_host();
6734 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
6737 Distor.doReversePostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
6738 destGraph->numImportPacketsPerLID_.view_host());
6739 size_t totalImportPackets = 0;
6741 totalImportPackets += numImportPacketsPerLID[i];
6746 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
6747 destGraph->imports_.modify_host();
6748 auto hostImports = destGraph->imports_.view_host();
6751 destGraph->exports_.sync_host();
6752 auto hostExports = destGraph->exports_.view_host();
6753 Distor.doReversePostsAndWaits(hostExports,
6754 numExportPacketsPerLID,
6756 numImportPacketsPerLID);
6758 destGraph->imports_.modify_host();
6759 auto hostImports = destGraph->imports_.view_host();
6762 destGraph->exports_.sync_host();
6763 auto hostExports = destGraph->exports_.view_host();
6764 Distor.doReversePostsAndWaits(hostExports,
6769 if (constantNumPackets == 0) {
6773 destGraph->numExportPacketsPerLID_.sync_host();
6774 destGraph->numImportPacketsPerLID_.sync_host();
6775 Distor.doPostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
6776 destGraph->numImportPacketsPerLID_.view_host());
6778 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
6780 size_t totalImportPackets = 0;
6782 totalImportPackets += numImportPacketsPerLID[i];
6787 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
6788 destGraph->imports_.modify_host();
6789 auto hostImports = destGraph->imports_.view_host();
6792 destGraph->exports_.sync_host();
6793 auto hostExports = destGraph->exports_.view_host();
6794 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
6796 Distor.doPostsAndWaits(hostExports, numExportPacketsPerLID, hostImports, numImportPacketsPerLID);
6798 destGraph->imports_.modify_host();
6799 auto hostImports = destGraph->imports_.view_host();
6802 destGraph->exports_.sync_host();
6803 auto hostExports = destGraph->exports_.view_host();
6804 Distor.doPostsAndWaits(hostExports, constantNumPackets, hostImports);
6814 MM = Teuchos::rcp(
new Tpetra::Details::ProfilingRegion(
"Tpetra CrsGraph TAFC Unpack-1"));
6817 destGraph->numImportPacketsPerLID_.sync_host();
6818 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
6820 destGraph->imports_.sync_host();
6821 Teuchos::ArrayView<const packet_type> hostImports =
6825 numImportPacketsPerLID,
6826 constantNumPackets,
INSERT,
6827 NumSameIDs, PermuteToLIDs, PermuteFromLIDs);
6828 size_t N = BaseRowMap->getLocalNumElements();
6831 ArrayRCP<size_t> CSR_rowptr(N + 1);
6832 ArrayRCP<GO> CSR_colind_GID;
6833 ArrayRCP<LO> CSR_colind_LID;
6834 CSR_colind_GID.resize(mynnz);
6838 if (
typeid(LO) ==
typeid(GO)) {
6839 CSR_colind_LID = Teuchos::arcp_reinterpret_cast<LO>(CSR_colind_GID);
6841 CSR_colind_LID.resize(mynnz);
6850 numImportPacketsPerLID, constantNumPackets,
6851 INSERT, NumSameIDs, PermuteToLIDs,
6852 PermuteFromLIDs, N, mynnz, MyPID,
6853 CSR_rowptr(), CSR_colind_GID(),
6854 SourcePids(), TargetPids);
6860 MM = Teuchos::rcp(
new Tpetra::Details::ProfilingRegion(
"Tpetra CrsGraph TAFC Unpack-2"));
6864 Teuchos::Array<int> RemotePids;
6869 TargetPids, RemotePids,
6877 ReducedColMap = (MyRowMap.getRawPtr() == MyColMap.getRawPtr()) ? ReducedRowMap : MyColMap->replaceCommWithSubset(ReducedComm);
6878 MyColMap = ReducedColMap;
6882 destGraph->replaceColMap(MyColMap);
6889 if (ReducedComm.is_null()) {
6896 if ((!reverseMode && xferAsImport !=
nullptr) ||
6897 (reverseMode && xferAsExport !=
nullptr)) {
6900 }
else if ((!reverseMode && xferAsExport !=
nullptr) ||
6901 (reverseMode && xferAsImport !=
nullptr)) {
6904 if (CSR_rowptr[N] != mynnz) {
6905 CSR_colind_LID.resize(CSR_rowptr[N]);
6908 TEUCHOS_TEST_FOR_EXCEPTION(
6909 true, std::logic_error,
6910 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6918 destGraph->setAllIndices(CSR_rowptr, CSR_colind_LID);
6924 Teuchos::ParameterList esfc_params;
6926 MM = Teuchos::rcp(
new Tpetra::Details::ProfilingRegion(
"Tpetra CrsGraph TAFC CreateImporter"));
6927 RCP<import_type> MyImport = rcp(
new import_type(MyDomainMap, MyColMap, RemotePids));
6929 MM = Teuchos::rcp(
new Tpetra::Details::ProfilingRegion(
"Tpetra CrsGraph TAFC ESFC"));
6931 if (!params.is_null())
6932 esfc_params.set(
"compute global constants", params->get(
"compute global constants",
true));
6934 destGraph->expertStaticFillComplete(MyDomainMap, MyRangeMap,
6935 MyImport, Teuchos::null, rcp(&esfc_params,
false));
6938template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6942 const Teuchos::RCP<const map_type>& domainMap,
6943 const Teuchos::RCP<const map_type>& rangeMap,
6944 const Teuchos::RCP<Teuchos::ParameterList>& params)
const {
6945 transferAndFillComplete(destGraph, importer, Teuchos::null, domainMap, rangeMap, params);
6948template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6953 const Teuchos::RCP<const map_type>& domainMap,
6954 const Teuchos::RCP<const map_type>& rangeMap,
6955 const Teuchos::RCP<Teuchos::ParameterList>& params)
const {
6956 transferAndFillComplete(destGraph, rowImporter, Teuchos::rcpFromRef(domainImporter), domainMap, rangeMap, params);
6959template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6963 const Teuchos::RCP<const map_type>& domainMap,
6964 const Teuchos::RCP<const map_type>& rangeMap,
6965 const Teuchos::RCP<Teuchos::ParameterList>& params)
const {
6966 transferAndFillComplete(destGraph, exporter, Teuchos::null, domainMap, rangeMap, params);
6969template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6974 const Teuchos::RCP<const map_type>& domainMap,
6975 const Teuchos::RCP<const map_type>& rangeMap,
6976 const Teuchos::RCP<Teuchos::ParameterList>& params)
const {
6977 transferAndFillComplete(destGraph, rowExporter, Teuchos::rcpFromRef(domainExporter), domainMap, rangeMap, params);
6980template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6982 swap(CrsGraph<LocalOrdinal, GlobalOrdinal, Node>& graph) {
6983 std::swap(graph.need_sync_host_uvm_access, this->need_sync_host_uvm_access);
6985 std::swap(graph.
rowMap_, this->rowMap_);
6986 std::swap(graph.
colMap_, this->colMap_);
6987 std::swap(graph.
rangeMap_, this->rangeMap_);
6988 std::swap(graph.
domainMap_, this->domainMap_);
6990 std::swap(graph.
importer_, this->importer_);
6991 std::swap(graph.
exporter_, this->exporter_);
7000 std::swap(graph.rowPtrsPacked_dev_, this->rowPtrsPacked_dev_);
7001 std::swap(graph.rowPtrsPacked_host_, this->rowPtrsPacked_host_);
7003 std::swap(graph.rowPtrsUnpacked_dev_, this->rowPtrsUnpacked_dev_);
7004 std::swap(graph.rowPtrsUnpacked_host_, this->rowPtrsUnpacked_host_);
7005 std::swap(graph.packedUnpackedRowPtrsMatch_, this->packedUnpackedRowPtrsMatch_);
7015 std::swap(graph.indicesAreAllocated_, this->indicesAreAllocated_);
7016 std::swap(graph.indicesAreLocal_, this->indicesAreLocal_);
7017 std::swap(graph.indicesAreGlobal_, this->indicesAreGlobal_);
7018 std::swap(graph.fillComplete_, this->fillComplete_);
7023 std::swap(graph.haveLocalOffRankOffsets_, this->haveLocalOffRankOffsets_);
7029 std::swap(graph.
nonlocals_, this->nonlocals_);
7032template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7034 isIdenticalTo(
const CrsGraph<LocalOrdinal, GlobalOrdinal, Node>& graph)
const {
7035 auto compare_nonlocals = [&](
const nonlocals_type& m1,
const nonlocals_type& m2) {
7037 output = m1.size() == m2.size() ? output :
false;
7038 for (
auto& it_m : m1) {
7039 size_t key = it_m.first;
7040 output = m2.find(key) != m2.end() ? output :
false;
7042 auto v1 = m1.find(key)->second;
7043 auto v2 = m2.find(key)->second;
7044 std::sort(v1.begin(), v1.end());
7045 std::sort(v2.begin(), v2.end());
7047 output = v1.size() == v2.size() ? output :
false;
7048 for (
size_t i = 0; output && i < v1.size(); i++) {
7049 output = v1[i] == v2[i] ? output :
false;
7058 output = this->
rowMap_->isSameAs(*(graph.
rowMap_)) ? output :
false;
7059 output = this->
colMap_->isSameAs(*(graph.
colMap_)) ? output :
false;
7072 output = this->indicesAreAllocated_ == graph.indicesAreAllocated_ ? output :
false;
7073 output = this->indicesAreLocal_ == graph.indicesAreLocal_ ? output :
false;
7074 output = this->indicesAreGlobal_ == graph.indicesAreGlobal_ ? output :
false;
7075 output = this->fillComplete_ == graph.fillComplete_ ? output :
false;
7080 output = this->haveLocalOffRankOffsets_ == graph.haveLocalOffRankOffsets_ ? output :
false;
7107 output = rowPtrsThis.extent(0) == rowPtrsGraph.extent(0) ? output :
false;
7108 for (
size_t i = 0; output && i < rowPtrsThis.extent(0); i++)
7109 output = rowPtrsThis(i) == rowPtrsGraph(i) ? output :
false;
7117 for (
size_t i = 0; output && i < indThis.extent(0); i++)
7118 output = indThis(i) == indGraph(i) ? output :
false;
7124 auto indtThis = this->
gblInds_wdv.getHostView(Access::ReadOnly);
7125 auto indtGraph = graph.
gblInds_wdv.getHostView(Access::ReadOnly);
7126 for (
size_t i = 0; output && i < indtThis.extent(0); i++)
7127 output = indtThis(i) == indtGraph(i) ? output :
false;
7146 output = thisLclGraph.row_map.extent(0) == graphLclGraph.row_map.extent(0)
7149 if (output && thisLclGraph.row_map.extent(0) > 0) {
7150 auto lclGraph_rowmap_host_this = thisLclGraph.row_map;
7151 auto lclGraph_rowmap_host_graph = graphLclGraph.row_map;
7152 for (
size_t i = 0; output && i < lclGraph_rowmap_host_this.extent(0); i++)
7153 output = lclGraph_rowmap_host_this(i) == lclGraph_rowmap_host_graph(i)
7158 output = thisLclGraph.entries.extent(0) == graphLclGraph.entries.extent(0)
7161 if (output && thisLclGraph.entries.extent(0) > 0) {
7162 auto lclGraph_entries_host_this = thisLclGraph.entries;
7163 auto lclGraph_entries_host_graph = graphLclGraph.entries;
7164 for (
size_t i = 0; output && i < lclGraph_entries_host_this.extent(0); i++)
7165 output = lclGraph_entries_host_this(i) == lclGraph_entries_host_graph(i)
7171 thisLclGraph.row_block_offsets.extent(0) ==
7172 graphLclGraph.row_block_offsets.extent(0)
7175 if (output && thisLclGraph.row_block_offsets.extent(0) > 0) {
7176 auto lclGraph_rbo_host_this = thisLclGraph.row_block_offsets;
7177 auto lclGraph_rbo_host_graph = graphLclGraph.row_block_offsets;
7178 for (
size_t i = 0; output && i < lclGraph_rbo_host_this.extent(0); i++)
7179 output = lclGraph_rbo_host_this(i) == lclGraph_rbo_host_graph(i)
7192template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7193void CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::insertGlobalIndicesDevice(
7196 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteToLIDs,
7197 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteFromLIDs,
7198 LocalOrdinal loopEnd) {
7200 using LO = LocalOrdinal;
7201 using GO = GlobalOrdinal;
7202 typedef typename crs_graph_type::global_inds_device_view_type::non_const_value_type global_inds_device_value_t;
7203 typedef typename Node::execution_space exec_space;
7204 typedef Kokkos::RangePolicy<exec_space, LO> range_type;
7206 const LocalOrdinal LINV = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
7207 const GlobalOrdinal GINV = Teuchos::OrdinalTraits<GlobalOrdinal>::invalid();
7209 using local_map_type =
typename crs_graph_type::map_type::local_map_type;
7210 local_map_type srcRowMapLocal = srcCrsGraph.
getRowMap()->getLocalMap();
7211 local_map_type srcColMapLocal = srcCrsGraph.
getColMap()->getLocalMap();
7212 local_map_type tgtRowMapLocal = tgtCrsGraph.
getRowMap()->getLocalMap();
7215 auto tgtGlobalColInds = tgtCrsGraph.
gblInds_wdv.getDeviceView(Access::ReadWrite);
7217 auto srcLocalColIndsDevice = srcCrsGraph.
lclIndsUnpacked_wdv.getDeviceView(Access::ReadOnly);
7219 typename crs_graph_type::num_row_entries_type::non_const_type h_numRowEnt = tgtCrsGraph.
k_numRowEntries_;
7221 auto k_numRowEnt = Kokkos::create_mirror_view_and_copy(
device_type(), h_numRowEnt);
7223 const bool sorted =
false;
7225 bool hasMap = permuteFromLIDs.extent(0) > 0;
7226 auto permuteToLIDs_d = permuteToLIDs.view_device();
7227 auto permuteFromLIDs_d = permuteFromLIDs.view_device();
7229#ifdef CRSGRAPH_INNER_ABORT
7230#undef CRSGRAPH_INNER_ABORT
7233#ifdef KOKKOS_ENABLE_SYCL
7234#define CRSGRAPH_INNER_ABORT(lin) \
7236 sycl::ext::oneapi::experimental::printf("ERROR: Tpetra_CrsGraph_def.hpp:%d", lin); \
7237 Kokkos::abort("error"); \
7240#define CRSGRAPH_INNER_ABORT(lin) \
7242 printf("ERROR: Tpetra_CrsGraph_def.hpp:%d", lin); \
7243 Kokkos::abort("error"); \
7247 Kokkos::parallel_for(
7248 "Tpetra_CrsGraph::copyAndPermuteNew",
7249 range_type(0, loopEnd),
7250 KOKKOS_LAMBDA(
const LO sourceLID) {
7251 auto srcLid = sourceLID;
7252 auto tgtLid = sourceLID;
7254 srcLid = permuteFromLIDs_d(srcLid);
7255 tgtLid = permuteToLIDs_d(tgtLid);
7257 auto srcGid = srcRowMapLocal.getGlobalElement(srcLid);
7258 if (srcGid == GINV) CRSGRAPH_INNER_ABORT(__LINE__);
7259 auto tgtGid = tgtRowMapLocal.getGlobalElement(tgtLid);
7260 auto tgtLocalRow = tgtRowMapLocal.getLocalElement(tgtGid);
7261 if (tgtLocalRow == LINV) CRSGRAPH_INNER_ABORT(__LINE__);
7262 if (tgtLocalRow != tgtLid) CRSGRAPH_INNER_ABORT(__LINE__);
7263 auto tgtNumEntries = k_numRowEnt(tgtLocalRow);
7266 auto start = srcLocalRowPtrsDevice(srcLid);
7267 auto end = srcLocalRowPtrsDevice(srcLid + 1);
7268 auto rowLength = (end - start);
7270 auto tstart = tgtLocalRowPtrsDevice(tgtLocalRow);
7271 auto tend = tstart + tgtNumEntries;
7272 auto tend1 = tgtLocalRowPtrsDevice(tgtLocalRow + 1);
7274 const size_t num_avail = (tend1 < tend) ?
size_t(0) : tend1 - tend;
7275 size_t num_inserted = 0;
7277 global_inds_device_value_t* tgtGlobalColIndsPtr = tgtGlobalColInds.data();
7280 for (
size_t j = 0; j < rowLength; j++) {
7281 auto ci = srcLocalColIndsDevice(start + j);
7282 GO gi = srcColMapLocal.getGlobalElement(ci);
7283 if (gi == GINV) CRSGRAPH_INNER_ABORT(__LINE__);
7284 auto numInTgtRow = (tend - tstart);
7286 const size_t offset = KokkosSparse::findRelOffset(
7287 tgtGlobalColIndsPtr + tstart, numInTgtRow, gi, hint, sorted);
7289 if (offset == numInTgtRow) {
7290 if (num_inserted >= num_avail) {
7291 Kokkos::abort(
"num_avail");
7293 tgtGlobalColIndsPtr[tstart + offset] = gi;
7299 k_numRowEnt(tgtLocalRow) += num_inserted;
7306template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7307void CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::copyAndPermuteNew(
7308 const row_graph_type& srcRowGraph,
7309 row_graph_type& tgtRowGraph,
7310 const size_t numSameIDs,
7319 const char tfecfFuncName[] =
"copyAndPermuteNew: ";
7320 const bool verbose = verbose_;
7323 std::unique_ptr<std::string> prefix;
7325 prefix = this->
createPrefix(
"CrsGraph",
"copyAndPermuteNew");
7326 std::ostringstream os;
7327 os << *prefix << endl;
7328 std::cerr << os.str();
7331 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
7332 permuteToLIDs.extent(0) != permuteFromLIDs.extent(0),
7334 "permuteToLIDs.extent(0) = " << permuteToLIDs.extent(0) <<
" != permuteFromLIDs.extent(0) = " << permuteFromLIDs.extent(0) <<
".");
7337 std::ostringstream os;
7338 os << *prefix <<
"Compute padding" << endl;
7339 std::cerr << os.str();
7344 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
7345 !srcCrsGraphPtr, std::runtime_error,
"error srcGraph type= " <<
typeid(srcRowGraph).name());
7349 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
7350 !tgtCrsGraphPtr, std::runtime_error,
"error tgtGraph type= " <<
typeid(tgtRowGraph).name());
7353 auto padding = tgtCrsGraph.computeCrsPadding(
7354 srcRowGraph, numSameIDs, permuteToLIDs, permuteFromLIDs, verbose);
7355 tgtCrsGraph.applyCrsPadding(*padding, verbose);
7357 const map_type& srcRowMap = *(srcRowGraph.getRowMap());
7358 const map_type& tgtRowMap = *(tgtRowGraph.getRowMap());
7360 nonconst_global_inds_host_view_type row_copy;
7366 LO numSameIDs_as_LID =
static_cast<LO
>(numSameIDs);
7368 if (src_filled || srcCrsGraphPtr ==
nullptr) {
7370 std::ostringstream os;
7371 os << *prefix <<
"src_filled || srcCrsGraph == nullptr" << endl;
7372 std::cerr << os.str();
7379 Kokkos::DualView<const local_ordinal_type*, buffer_device_type> noPermute;
7380 insertGlobalIndicesDevice(srcCrsGraph, tgtCrsGraph,
7381 noPermute, noPermute,
7385 std::ostringstream os;
7386 os << *prefix <<
"! src_filled && srcCrsGraph != nullptr" << endl;
7387 std::cerr << os.str();
7389 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
7390 const GO gid = srcRowMap.getGlobalElement(myid);
7391 global_inds_host_view_type row;
7392 srcCrsGraph.getGlobalRowView(gid, row);
7393 tgtCrsGraph.insertGlobalIndices(gid, row.extent(0), row.data());
7400 auto permuteToLIDs_h = permuteToLIDs.view_host();
7401 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
7402 auto permuteToLIDs_d = permuteToLIDs.view_device();
7403 auto permuteFromLIDs_d = permuteFromLIDs.view_device();
7405 if (src_filled || srcCrsGraphPtr ==
nullptr) {
7406 insertGlobalIndicesDevice(
7411 static_cast<LO
>(permuteToLIDs_h.extent(0)));
7413 for (LO i = 0; i < static_cast<LO>(permuteToLIDs_h.extent(0)); ++i) {
7414 const GO mygid = tgtRowMap.getGlobalElement(permuteToLIDs_h[i]);
7415 const GO srcgid = srcRowMap.getGlobalElement(permuteFromLIDs_h[i]);
7416 global_inds_host_view_type row;
7417 srcCrsGraph.getGlobalRowView(srcgid, row);
7418 tgtCrsGraph.insertGlobalIndices(mygid, row.extent(0), row.data());
7423 std::ostringstream os;
7424 os << *prefix <<
"Done" << endl;
7425 std::cerr << os.str();
7437#define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7439 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7440 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7441 const Import<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7442 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7443 CrsGraph<LO, GO, NODE>::node_type>& importer, \
7444 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7445 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7446 CrsGraph<LO, GO, NODE>::node_type>>& domainMap, \
7447 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7448 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7449 CrsGraph<LO, GO, NODE>::node_type>>& rangeMap, \
7450 const Teuchos::RCP<Teuchos::ParameterList>& params);
7452#define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO, GO, NODE) \
7454 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7455 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7456 const Import<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7457 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7458 CrsGraph<LO, GO, NODE>::node_type>& rowImporter, \
7459 const Import<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7460 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7461 CrsGraph<LO, GO, NODE>::node_type>& domainImporter, \
7462 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7463 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7464 CrsGraph<LO, GO, NODE>::node_type>>& domainMap, \
7465 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7466 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7467 CrsGraph<LO, GO, NODE>::node_type>>& rangeMap, \
7468 const Teuchos::RCP<Teuchos::ParameterList>& params);
7470#define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7472 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7473 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7474 const Export<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7475 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7476 CrsGraph<LO, GO, NODE>::node_type>& exporter, \
7477 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7478 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7479 CrsGraph<LO, GO, NODE>::node_type>>& domainMap, \
7480 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7481 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7482 CrsGraph<LO, GO, NODE>::node_type>>& rangeMap, \
7483 const Teuchos::RCP<Teuchos::ParameterList>& params);
7485#define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO, GO, NODE) \
7487 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7488 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7489 const Export<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7490 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7491 CrsGraph<LO, GO, NODE>::node_type>& rowExporter, \
7492 const Export<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7493 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7494 CrsGraph<LO, GO, NODE>::node_type>& domainExporter, \
7495 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7496 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7497 CrsGraph<LO, GO, NODE>::node_type>>& domainMap, \
7498 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7499 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7500 CrsGraph<LO, GO, NODE>::node_type>>& rangeMap, \
7501 const Teuchos::RCP<Teuchos::ParameterList>& params);
7503#define TPETRA_CRSGRAPH_INSTANT(LO, GO, NODE) \
7504 template class CrsGraph<LO, GO, NODE>; \
7505 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7506 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7507 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO, GO, NODE) \
7508 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.
Declaration of Tpetra::Details::iallreduce.
Utility functions for packing and unpacking sparse matrix entries.
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 lowCommunicationMakeColMapAndReindex(const Teuchos::ArrayView< const size_t > &rowptr, const Teuchos::ArrayView< LocalOrdinal > &colind_LID, const Teuchos::ArrayView< GlobalOrdinal > &colind_GID, const Teuchos::RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &domainMapRCP, const Teuchos::ArrayView< const int > &owningPIDs, Teuchos::Array< int > &remotePIDs, Teuchos::RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &colMap, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
lowCommunicationMakeColMapAndReindex
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.
KokkosSparse::StaticCrsGraph< local_ordinal_type, Kokkos::LayoutLeft, device_type, void, size_t > local_graph_device_type
The type of the part of the sparse graph on each MPI process.
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.
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.
typename local_graph_device_type::host_mirror_type local_graph_host_type
The type of the part of the sparse graph on each MPI process.
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...
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 getLocalRowCopy(local_ordinal_type lclRow, nonconst_local_inds_host_view_type &lclColInds, size_t &numColInds) const override
Get a copy of the given row, using local indices.
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.
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.
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.
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.
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.
Kokkos::View< constsize_t *, device_type >::host_mirror_type k_numAllocPerRow_
The maximum number of entries to allow in each locally owned row, per row.
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.
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,...
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.
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.
bool isFillComplete() const override
Whether the matrix is fill complete.
static bool useNewCopyAndPermute()
Use new implementation of copyAndPermute.
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 LocalMap 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(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 disableWDVTracking()
Disable WrappedDualView reference-count tracking and syncing. Call this before entering a host-parall...
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 enableWDVTracking()
Enable WrappedDualView reference-count tracking and syncing. Call this after exiting a host-parallel ...
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.
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 CrsGraph< LO, GO, NT > &graph, const bool sortEachProcsGids=true, std::ostream *errStrm=NULL)
Make the graph's column Map.
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.
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.