10#ifndef TPETRA_CRSGRAPH_DEF_HPP
11#define TPETRA_CRSGRAPH_DEF_HPP
16#ifdef KOKKOS_ENABLE_SYCL
17#include <sycl/sycl.hpp>
24#include "Tpetra_Details_getGraphDiagOffsets.hpp"
25#include "Tpetra_Details_getGraphOffRankOffsets.hpp"
26#include "Tpetra_Details_makeColMap.hpp"
30#include "Tpetra_Distributor.hpp"
31#include "Teuchos_SerialDenseMatrix.hpp"
32#include "Tpetra_Vector.hpp"
35#include "Tpetra_Details_packCrsGraph.hpp"
36#include "Tpetra_Details_unpackCrsGraphAndCombine.hpp"
37#include "Tpetra_Details_CrsPadding.hpp"
52template <
class MapIter>
53void verbosePrintMap(std::ostream& out,
57 const char mapName[]) {
58 using ::Tpetra::Details::Behavior;
61 out << mapName <<
": {";
62 const size_t maxNumToPrint =
64 if (maxNumToPrint == 0) {
69 const size_t numToPrint = numEnt > maxNumToPrint ? maxNumToPrint : numEnt;
71 for (MapIter it = beg; it != end; ++it) {
72 out <<
"(" << (*it).first <<
", ";
76 if (count +
size_t(1) < numToPrint) {
88template <
class LO,
class GO,
class Node>
91 std::vector<GO>& gblColIndsStorage,
92 const RowGraph<LO, GO, Node>& graph,
94 size_t origNumEnt = graph.getNumEntriesInGlobalRow(gblRowInd);
95 if (gblColIndsStorage.size() < origNumEnt) {
96 gblColIndsStorage.resize(origNumEnt);
98 typename CrsGraph<LO, GO, Node>::nonconst_global_inds_host_view_type gblColInds(gblColIndsStorage.data(),
100 graph.getGlobalRowCopy(gblRowInd, gblColInds, origNumEnt);
101 Teuchos::ArrayView<GO> retval(gblColIndsStorage.data(), origNumEnt);
105template <
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
106class ConvertColumnIndicesFromGlobalToLocal {
108 ConvertColumnIndicesFromGlobalToLocal(const ::Kokkos::View<LO*, DT>& lclColInds,
109 const ::Kokkos::View<const GO*, DT>& gblColInds,
110 const ::Kokkos::View<const OffsetType*, DT>& ptr,
111 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
112 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt)
113 : lclColInds_(lclColInds)
114 , gblColInds_(gblColInds)
116 , lclColMap_(lclColMap)
117 , numRowEnt_(numRowEnt) {}
120 operator()(
const LO& lclRow, OffsetType& curNumBad)
const {
121 const OffsetType offset = ptr_(lclRow);
125 const LO numEnt =
static_cast<LO
>(numRowEnt_(lclRow));
126 for (LO j = 0; j < numEnt; ++j) {
127 const GO gid = gblColInds_(offset + j);
128 const LO lid = lclColMap_.getLocalElement(gid);
129 lclColInds_(offset + j) = lid;
130 if (lid == ::Tpetra::Details::OrdinalTraits<LO>::invalid()) {
137 run(const ::Kokkos::View<LO*, DT>& lclColInds,
138 const ::Kokkos::View<const GO*, DT>& gblColInds,
139 const ::Kokkos::View<const OffsetType*, DT>& ptr,
140 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
141 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt) {
142 typedef ::Kokkos::RangePolicy<typename DT::execution_space, LO> range_type;
143 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> functor_type;
145 const LO lclNumRows = ptr.extent(0) == 0 ?
static_cast<LO
>(0) : static_cast<LO>(ptr.extent(0) - 1);
146 OffsetType numBad = 0;
148 ::Kokkos::parallel_reduce(range_type(0, lclNumRows),
149 functor_type(lclColInds, gblColInds, ptr,
150 lclColMap, numRowEnt),
156 ::Kokkos::View<LO*, DT> lclColInds_;
157 ::Kokkos::View<const GO*, DT> gblColInds_;
158 ::Kokkos::View<const OffsetType*, DT> ptr_;
159 ::Tpetra::Details::LocalMap<LO, GO, DT> lclColMap_;
160 ::Kokkos::View<const NumEntType*, DT> numRowEnt_;
179template <
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
182 const Kokkos::View<const GO*, DT>& gblColInds,
183 const Kokkos::View<const OffsetType*, DT>& ptr,
185 const Kokkos::View<const NumEntType*, DT>& numRowEnt) {
186 using Impl::ConvertColumnIndicesFromGlobalToLocal;
187 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> impl_type;
188 return impl_type::run(lclColInds, gblColInds, ptr, lclColMap, numRowEnt);
191template <
class ViewType,
class LO>
194 MaxDifference(
const ViewType& ptr)
197 KOKKOS_INLINE_FUNCTION
void init(LO& dst)
const {
201 KOKKOS_INLINE_FUNCTION
void
202 join(LO& dst,
const LO& src)
const {
203 dst = (src > dst) ? src : dst;
206 KOKKOS_INLINE_FUNCTION
void
207 operator()(
const LO lclRow, LO& maxNumEnt)
const {
208 const LO numEnt =
static_cast<LO
>(ptr_(lclRow + 1) - ptr_(lclRow));
209 maxNumEnt = (numEnt > maxNumEnt) ? numEnt : maxNumEnt;
213 typename ViewType::const_type ptr_;
216template <
class ViewType,
class LO>
217typename ViewType::non_const_value_type
218maxDifference(
const char kernelLabel[],
220 const LO lclNumRows) {
221 if (lclNumRows == 0) {
224 return static_cast<LO
>(0);
226 using execution_space =
typename ViewType::execution_space;
227 using range_type = Kokkos::RangePolicy<execution_space, LO>;
229 Kokkos::parallel_reduce(kernelLabel,
230 range_type(0, lclNumRows),
231 MaxDifference<ViewType, LO>(ptr),
239template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
245template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
251template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
252CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
253 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
254 const size_t maxNumEntriesPerRow,
255 const Teuchos::RCP<Teuchos::ParameterList>& params)
256 : dist_object_type(rowMap)
259 const char tfecfFuncName[] =
260 "CrsGraph(rowMap,maxNumEntriesPerRow,params): ";
262 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid(),
263 std::invalid_argument,
264 "The allocation hint maxNumEntriesPerRow must be "
265 "a valid size_t value, which in this case means it must not be "
266 "Teuchos::OrdinalTraits<size_t>::invalid().");
271template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
272CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
273 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
274 const Teuchos::RCP<const map_type>& colMap,
275 const size_t maxNumEntriesPerRow,
276 const Teuchos::RCP<Teuchos::ParameterList>& params)
277 : dist_object_type(rowMap)
281 const char tfecfFuncName[] =
282 "CrsGraph(rowMap,colMap,maxNumEntriesPerRow,params): ";
284 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
285 maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid(),
286 std::invalid_argument,
287 "The allocation hint maxNumEntriesPerRow must be "
288 "a valid size_t value, which in this case means it must not be "
289 "Teuchos::OrdinalTraits<size_t>::invalid().");
294template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
295CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
296 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
297 const Teuchos::ArrayView<const size_t>& numEntPerRow,
298 const Teuchos::RCP<Teuchos::ParameterList>& params)
299 : dist_object_type(rowMap)
302 const char tfecfFuncName[] =
303 "CrsGraph(rowMap,numEntPerRow,params): ";
306 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
307 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
308 static_cast<size_t>(numEntPerRow.size()) != lclNumRows,
309 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size() <<
" != the local number of rows " << lclNumRows <<
" as specified by "
310 "the input row Map.");
313 for (
size_t r = 0; r < lclNumRows; ++r) {
314 const size_t curRowCount = numEntPerRow[r];
315 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
316 std::invalid_argument,
"numEntPerRow(" << r <<
") "
317 "specifies an invalid number of entries "
318 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
326 typedef typename out_view_type::non_const_type nc_view_type;
327 typedef Kokkos::View<
const size_t*,
328 typename nc_view_type::array_layout,
330 Kokkos::MemoryUnmanaged>
332 in_view_type numAllocPerRowIn(numEntPerRow.getRawPtr(), lclNumRows);
333 nc_view_type numAllocPerRowOut(
"Tpetra::CrsGraph::numAllocPerRow",
336 using exec_space =
typename nc_view_type::execution_space;
337 Kokkos::deep_copy(exec_space(), numAllocPerRowOut, numAllocPerRowIn);
344template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
345CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
346 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
347 const Kokkos::DualView<const size_t*, device_type>& numEntPerRow,
348 const Teuchos::RCP<Teuchos::ParameterList>& params)
349 : dist_object_type(rowMap)
353 const char tfecfFuncName[] =
354 "CrsGraph(rowMap,numEntPerRow,params): ";
357 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
358 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
359 static_cast<size_t>(numEntPerRow.extent(0)) != lclNumRows,
360 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.extent(0) <<
" != the local number of rows " << lclNumRows <<
" as specified by "
361 "the input row Map.");
364 for (
size_t r = 0; r < lclNumRows; ++r) {
365 const size_t curRowCount = numEntPerRow.view_host()(r);
366 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
367 std::invalid_argument,
"numEntPerRow(" << r <<
") "
368 "specifies an invalid number of entries "
369 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
377template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
378CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
379 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
380 const Teuchos::RCP<const map_type>& colMap,
381 const Kokkos::DualView<const size_t*, device_type>& numEntPerRow,
382 const Teuchos::RCP<Teuchos::ParameterList>& params)
383 : dist_object_type(rowMap)
388 const char tfecfFuncName[] =
389 "CrsGraph(rowMap,colMap,numEntPerRow,params): ";
392 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
393 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
394 static_cast<size_t>(numEntPerRow.extent(0)) != lclNumRows,
395 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.extent(0) <<
" != the local number of rows " << lclNumRows <<
" as specified by "
396 "the input row Map.");
399 for (
size_t r = 0; r < lclNumRows; ++r) {
400 const size_t curRowCount = numEntPerRow.view_host()(r);
401 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
402 std::invalid_argument,
"numEntPerRow(" << r <<
") "
403 "specifies an invalid number of entries "
404 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
412template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
413CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
414 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
415 const Teuchos::RCP<const map_type>& colMap,
416 const Teuchos::ArrayView<const size_t>& numEntPerRow,
417 const Teuchos::RCP<Teuchos::ParameterList>& params)
418 : dist_object_type(rowMap)
422 const char tfecfFuncName[] =
423 "CrsGraph(rowMap,colMap,numEntPerRow,params): ";
426 const size_t lclNumRows = rowMap.is_null() ?
static_cast<size_t>(0) : rowMap->getLocalNumElements();
427 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
428 static_cast<size_t>(numEntPerRow.size()) != lclNumRows,
429 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size() <<
" != the local number of rows " << lclNumRows <<
" as specified by "
430 "the input row Map.");
433 for (
size_t r = 0; r < lclNumRows; ++r) {
434 const size_t curRowCount = numEntPerRow[r];
435 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(curRowCount == Teuchos::OrdinalTraits<size_t>::invalid(),
436 std::invalid_argument,
"numEntPerRow(" << r <<
") "
437 "specifies an invalid number of entries "
438 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
446 typedef typename out_view_type::non_const_type nc_view_type;
447 typedef Kokkos::View<
const size_t*,
448 typename nc_view_type::array_layout,
450 Kokkos::MemoryUnmanaged>
452 in_view_type numAllocPerRowIn(numEntPerRow.getRawPtr(), lclNumRows);
453 nc_view_type numAllocPerRowOut(
"Tpetra::CrsGraph::numAllocPerRow",
456 using exec_space =
typename nc_view_type::execution_space;
457 Kokkos::deep_copy(exec_space(), numAllocPerRowOut, numAllocPerRowIn);
464template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
465CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
466 CrsGraph(CrsGraph<local_ordinal_type, global_ordinal_type, node_type>& originalGraph,
467 const Teuchos::RCP<const map_type>& rowMap,
468 const Teuchos::RCP<Teuchos::ParameterList>& params)
469 : dist_object_type(rowMap)
474 , indicesAreAllocated_(originalGraph.indicesAreAllocated_)
475 , indicesAreLocal_(originalGraph.indicesAreLocal_)
479 int numRows = rowMap->getLocalNumElements();
481 auto rowsToUse = Kokkos::pair<size_t, size_t>(0, numRows + 1);
486 if (indicesAreLocal_) {
496template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
497CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
498 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
499 const Teuchos::RCP<const map_type>& colMap,
500 const typename local_graph_device_type::row_map_type& rowPointers,
501 const typename local_graph_device_type::entries_type::non_const_type& columnIndices,
502 const Teuchos::RCP<Teuchos::ParameterList>& params)
503 : dist_object_type(rowMap)
508 , indicesAreAllocated_(true)
509 , indicesAreLocal_(true) {
511 if (!params.is_null() && params->isParameter(
"sorted") &&
512 !params->get<
bool>(
"sorted")) {
521template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
522CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
523 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
524 const Teuchos::RCP<const map_type>& colMap,
525 const Teuchos::ArrayRCP<size_t>& rowPointers,
526 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices,
527 const Teuchos::RCP<Teuchos::ParameterList>& params)
528 : dist_object_type(rowMap)
533 , indicesAreAllocated_(true)
534 , indicesAreLocal_(true) {
536 if (!params.is_null() && params->isParameter(
"sorted") &&
537 !params->get<
bool>(
"sorted")) {
546template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
547CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
548 CrsGraph(
const Teuchos::RCP<const map_type>& rowMap,
549 const Teuchos::RCP<const map_type>& colMap,
551 const Teuchos::RCP<Teuchos::ParameterList>& params)
552 : CrsGraph(k_local_graph_,
559template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
560CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
562 const Teuchos::RCP<const map_type>& rowMap,
563 const Teuchos::RCP<const map_type>& colMap,
564 const Teuchos::RCP<const map_type>& domainMap,
565 const Teuchos::RCP<const map_type>& rangeMap,
566 const Teuchos::RCP<Teuchos::ParameterList>& params)
572 , indicesAreAllocated_(true)
573 , indicesAreLocal_(true) {
575 const char tfecfFuncName[] =
"CrsGraph(Kokkos::LocalStaticCrsGraph,Map,Map,Map,Map)";
577 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
578 colMap.is_null(), std::runtime_error,
579 ": The input column Map must be nonnull.");
580 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
581 k_local_graph_.numRows() != rowMap->getLocalNumElements(),
583 ": The input row Map and the input local graph need to have the same "
584 "number of rows. The row Map claims "
585 << rowMap->getLocalNumElements()
586 <<
" row(s), but the local graph claims " << k_local_graph_.numRows()
596 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
598 ": cannot have 1D data structures allocated.");
600 if (!params.is_null() && params->isParameter(
"sorted") &&
601 !params->get<
bool>(
"sorted")) {
608 rangeMap.is_null() ?
rowMap_ : rangeMap);
609 Teuchos::Array<int> remotePIDs(0);
614 this->setRowPtrs(k_local_graph_.row_map);
616 set_need_sync_host_uvm_access();
618 const bool callComputeGlobalConstants = params.get() ==
nullptr ||
619 params->get(
"compute global constants",
true);
621 if (callComputeGlobalConstants) {
624 this->fillComplete_ =
true;
628template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
629CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
631 const Teuchos::RCP<const map_type>& rowMap,
632 const Teuchos::RCP<const map_type>& colMap,
633 const Teuchos::RCP<const map_type>& domainMap,
634 const Teuchos::RCP<const map_type>& rangeMap,
635 const Teuchos::RCP<const import_type>& importer,
636 const Teuchos::RCP<const export_type>& exporter,
637 const Teuchos::RCP<Teuchos::ParameterList>& params)
641 ,
rangeMap_(rangeMap.is_null() ? rowMap : rangeMap)
642 ,
domainMap_(domainMap.is_null() ? rowMap : domainMap)
647 , indicesAreAllocated_(true)
648 , indicesAreLocal_(true) {
650 const char tfecfFuncName[] =
651 "Tpetra::CrsGraph(local_graph_device_type,"
652 "Map,Map,Map,Map,Import,Export,params): ";
654 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(colMap.is_null(), std::runtime_error,
655 "The input column Map must be nonnull.");
659 setRowPtrs(lclGraph.row_map);
661 set_need_sync_host_uvm_access();
663 if (!params.is_null() && params->isParameter(
"sorted") &&
664 !params->get<
bool>(
"sorted")) {
670 const bool callComputeGlobalConstants =
671 params.get() ==
nullptr ||
672 params->get(
"compute global constants",
true);
673 if (callComputeGlobalConstants) {
676 fillComplete_ =
true;
680template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
681CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
682 CrsGraph(
const row_ptrs_device_view_type& rowPointers,
683 const local_inds_wdv_type& columnIndices,
684 const Teuchos::RCP<const map_type>& rowMap,
685 const Teuchos::RCP<const map_type>& colMap,
686 const Teuchos::RCP<const map_type>& domainMap,
687 const Teuchos::RCP<const map_type>& rangeMap,
688 const Teuchos::RCP<const import_type>& importer,
689 const Teuchos::RCP<const export_type>& exporter,
690 const Teuchos::RCP<Teuchos::ParameterList>& params)
694 ,
rangeMap_(rangeMap.is_null() ? rowMap : rangeMap)
695 ,
domainMap_(domainMap.is_null() ? rowMap : domainMap)
700 , indicesAreAllocated_(true)
701 , indicesAreLocal_(true) {
703 const char tfecfFuncName[] =
704 "Tpetra::CrsGraph(row_ptrs_device_view_type,local_inds_wdv_type"
705 "Map,Map,Map,Map,Import,Export,params): ";
707 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(colMap.is_null(), std::runtime_error,
708 "The input column Map must be nonnull.");
712 setRowPtrs(rowPointers);
714 set_need_sync_host_uvm_access();
716 if (!params.is_null() && params->isParameter(
"sorted") &&
717 !params->get<
bool>(
"sorted")) {
723 const bool callComputeGlobalConstants =
724 params.get() ==
nullptr ||
725 params->get(
"compute global constants",
true);
726 if (callComputeGlobalConstants) {
729 fillComplete_ =
true;
733template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
734Teuchos::RCP<const Teuchos::ParameterList>
737 using Teuchos::ParameterList;
738 using Teuchos::parameterList;
741 RCP<ParameterList> params = parameterList(
"Tpetra::CrsGraph");
744 RCP<ParameterList> importSublist = parameterList(
"Import");
757 params->set(
"Import", *importSublist,
"How the Import performs communication.");
763 params->set(
"Export", *importSublist,
"How the Export performs communication.");
768template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
771 Teuchos::RCP<const Teuchos::ParameterList> validParams =
773 params->validateParametersAndSetDefaults(*validParams);
774 this->setMyParamList(params);
777template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
781 return rowMap_->getGlobalNumElements();
784template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
788 const char tfecfFuncName[] =
"getGlobalNumCols: ";
789 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
791 "The graph does not have a domain Map. You may not call this method in "
796template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
800 return this->
rowMap_.is_null() ?
static_cast<size_t>(0) : this->
rowMap_->getLocalNumElements();
803template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
807 const char tfecfFuncName[] =
"getLocalNumCols: ";
808 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
810 "The graph does not have a column Map. You may not call this method "
811 "unless the graph has a column Map. This requires either that a custom "
812 "column Map was given to the constructor, or that fillComplete() has "
814 return colMap_.is_null() ?
static_cast<size_t>(0) :
colMap_->getLocalNumElements();
817template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
818Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
824template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
825Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
831template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
832Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
838template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
839Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
845template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
846Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::import_type>
852template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
853Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::export_type>
859template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
865template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
871 const bool isOpt = indicesAreAllocated_ &&
878template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
882 const char tfecfFuncName[] =
"getGlobalNumEntries: ";
884 "The graph does not have global constants computed, "
885 "but the user has requested them.");
890template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
894 const char tfecfFuncName[] =
"getLocalNumEntries: ";
895 typedef LocalOrdinal LO;
899 if (this->indicesAreAllocated_) {
901 if (lclNumRows == 0) {
902 return static_cast<size_t>(0);
906 const LO numNumEntPerRow = numEntPerRow.extent(0);
907 if (numNumEntPerRow == 0) {
909 static_cast<LO
>(lclNumRows + 1)) {
910 return static_cast<size_t>(0);
917 "Final entry of packed host rowptrs doesn't match the length of lclIndsPacked");
928 typedef typename num_row_entries_type::execution_space
930 typedef Kokkos::RangePolicy<host_exec_space, LO> range_type;
932 const LO upperLoopBound = lclNumRows < numNumEntPerRow ? lclNumRows : numNumEntPerRow;
933 size_t nodeNumEnt = 0;
934 Kokkos::parallel_reduce(
935 "Tpetra::CrsGraph::getNumNodeEntries",
936 range_type(0, upperLoopBound),
937 [=](
const LO& k,
size_t& lclSum) {
938 lclSum += numEntPerRow(k);
945 return static_cast<size_t>(0);
949template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
953 const char tfecfFuncName[] =
"getGlobalMaxNumRowEntries: ";
955 "The graph does not have global constants computed, "
956 "but the user has requested them.");
961template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
968template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
971 return fillComplete_;
974template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
977 return !fillComplete_;
980template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
983 return indicesAreLocal_;
986template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
989 return indicesAreGlobal_;
992template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
996 typedef LocalOrdinal LO;
998 if (this->indicesAreAllocated_) {
1000 if (lclNumRows == 0) {
1001 return static_cast<size_t>(0);
1004 static_cast<LO
>(lclNumRows + 1)) {
1005 return static_cast<size_t>(0);
1014 if (rowPtrsUnpacked_host.extent(0) == 0) {
1015 return static_cast<size_t>(0);
1023 return static_cast<size_t>(0);
1026 return Tpetra::Details::OrdinalTraits<size_t>::invalid();
1030template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1031Teuchos::RCP<const Teuchos::Comm<int>>
1034 return this->
rowMap_.is_null() ? Teuchos::null : this->
rowMap_->getComm();
1037template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1041 return rowMap_->getIndexBase();
1044template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1047 return indicesAreAllocated_;
1050template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1056template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1062template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1078template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1082 using Teuchos::arcp;
1083 using Teuchos::Array;
1084 using Teuchos::ArrayRCP;
1085 typedef Teuchos::ArrayRCP<size_t>::size_type size_type;
1086 typedef typename local_graph_device_type::row_map_type::non_const_type
1087 non_const_row_map_type;
1088 const char tfecfFuncName[] =
"allocateIndices: ";
1089 const char suffix[] =
1090 " Please report this bug to the Tpetra developers.";
1094 std::unique_ptr<std::string> prefix;
1096 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
1097 std::ostringstream os;
1098 os << *prefix <<
"Start: lg="
1099 << (lg == GlobalIndices ?
"GlobalIndices" :
"LocalIndices")
1100 <<
", numRows: " << this->getLocalNumRows() << endl;
1101 std::cerr << os.str();
1107 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isLocallyIndexed() && lg == GlobalIndices, std::logic_error,
1108 ": The graph is locally indexed, but Tpetra code is calling "
1109 "this method with lg=GlobalIndices."
1111 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isGloballyIndexed() && lg == LocalIndices, std::logic_error,
1112 ": The graph is globally indexed, but Tpetra code is calling "
1113 "this method with lg=LocalIndices."
1115 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreAllocated(), std::logic_error,
1117 "indices are already allocated, but Tpetra is calling "
1118 "allocateIndices again."
1120 const size_t numRows = this->getLocalNumRows();
1125 size_type numInds = 0;
1128 std::ostringstream os;
1129 os << *prefix <<
"Allocate k_rowPtrs: " << (numRows + 1) << endl;
1130 std::cerr << os.str();
1132 non_const_row_map_type k_rowPtrs(
"Tpetra::CrsGraph::ptr", numRows + 1);
1134 if (this->k_numAllocPerRow_.extent(0) != 0) {
1139 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->k_numAllocPerRow_.extent(0) != numRows,
1140 std::invalid_argument,
1141 "k_numAllocPerRow_ is allocated, that is, "
1142 "has nonzero length "
1143 << this->k_numAllocPerRow_.extent(0)
1144 <<
", but its length != numRows = " << numRows <<
".");
1161 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->numAllocForAllRows_ ==
1162 Tpetra::Details::OrdinalTraits<size_t>::invalid(),
1163 std::invalid_argument,
1164 "numAllocForAllRows_ has an invalid value, "
1165 "namely Tpetra::Details::OrdinalTraits<size_t>::invalid() = "
1166 << Tpetra::Details::OrdinalTraits<size_t>::invalid() <<
".");
1172 setRowPtrsUnpacked(k_rowPtrs);
1175 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numInds != size_type(this->getRowPtrsUnpackedHost()(numRows)), std::logic_error,
1176 ": Number of indices produced by computeOffsetsFrom[Constant]Counts "
1177 "does not match final entry of rowptrs unpacked");
1180 if (lg == LocalIndices) {
1182 std::ostringstream os;
1183 os << *prefix <<
"Allocate local column indices "
1184 "lclIndsUnpacked_wdv: "
1186 std::cerr << os.str();
1188 lclIndsUnpacked_wdv = local_inds_wdv_type(
1189 local_inds_dualv_type(
"Tpetra::CrsGraph::lclInd", numInds));
1192 std::ostringstream os;
1193 os << *prefix <<
"Allocate global column indices "
1196 std::cerr << os.str();
1198 gblInds_wdv = global_inds_wdv_type(
1199 global_inds_dualv_type(
"Tpetra::CrsGraph::gblInd", numInds));
1201 storageStatus_ = Details::STORAGE_1D_UNPACKED;
1203 this->indicesAreLocal_ = (lg == LocalIndices);
1204 this->indicesAreGlobal_ = (lg == GlobalIndices);
1207 using Kokkos::ViewAllocateWithoutInitializing;
1208 const char label[] =
"Tpetra::CrsGraph::numRowEntries";
1210 std::ostringstream os;
1211 os << *prefix <<
"Allocate k_numRowEntries_: " << numRows
1213 std::cerr << os.str();
1215 num_row_entries_type numRowEnt(ViewAllocateWithoutInitializing(label), numRows);
1217 Kokkos::deep_copy(
execution_space(), numRowEnt,
static_cast<size_t>(0));
1218 Kokkos::fence(
"CrsGraph::allocateIndices");
1219 this->k_numRowEntries_ = numRowEnt;
1223 this->numAllocForAllRows_ = 0;
1224 this->k_numAllocPerRow_ =
decltype(k_numAllocPerRow_)();
1225 this->indicesAreAllocated_ =
true;
1228 this->checkInternalState();
1229 }
catch (std::logic_error& e) {
1230 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
1231 "At end of allocateIndices, "
1232 "checkInternalState threw std::logic_error: "
1234 }
catch (std::exception& e) {
1235 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1236 "At end of allocateIndices, "
1237 "checkInternalState threw std::exception: "
1240 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1241 "At end of allocateIndices, "
1242 "checkInternalState threw an exception "
1243 "not a subclass of std::exception.");
1247 std::ostringstream os;
1248 os << *prefix <<
"Done" << endl;
1249 std::cerr << os.str();
1253template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1255 local_inds_dualv_type::t_host::const_type
1259 return typename local_inds_dualv_type::t_host::const_type();
1266template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1268 local_inds_dualv_type::t_host
1272 return typename local_inds_dualv_type::t_host();
1279template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1281 global_inds_dualv_type::t_host::const_type
1284 if (rowinfo.allocSize == 0 ||
gblInds_wdv.extent(0) == 0)
1285 return typename global_inds_dualv_type::t_host::const_type();
1287 return gblInds_wdv.getHostSubview(rowinfo.offset1D,
1292template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1294 local_inds_dualv_type::t_dev::const_type
1298 return typename local_inds_dualv_type::t_dev::const_type();
1305template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1307 global_inds_dualv_type::t_dev::const_type
1310 if (rowinfo.allocSize == 0 ||
gblInds_wdv.extent(0) == 0)
1311 return typename global_inds_dualv_type::t_dev::const_type();
1313 return gblInds_wdv.getDeviceSubview(rowinfo.offset1D,
1318template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1322 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid();
1324 if (this->
rowMap_.is_null() || !this->rowMap_->isNodeLocalElement(myRow)) {
1325 ret.localRow = STINV;
1328 ret.offset1D = STINV;
1332 ret.localRow =
static_cast<size_t>(myRow);
1333 if (this->indicesAreAllocated()) {
1336 if (rowPtrsUnpacked_host.extent(0) == 0) {
1340 ret.offset1D = rowPtrsUnpacked_host(myRow);
1341 ret.allocSize = rowPtrsUnpacked_host(myRow + 1) - rowPtrsUnpacked_host(myRow);
1352 ret.offset1D = STINV;
1358template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1362 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid();
1364 if (this->
rowMap_.is_null()) {
1365 ret.localRow = STINV;
1368 ret.offset1D = STINV;
1371 const LocalOrdinal myRow = this->
rowMap_->getLocalElement(gblRow);
1372 if (myRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid()) {
1373 ret.localRow = STINV;
1376 ret.offset1D = STINV;
1380 ret.localRow =
static_cast<size_t>(myRow);
1381 if (this->indicesAreAllocated()) {
1386 if (rowPtrsUnpacked_host.extent(0) == 0) {
1390 ret.offset1D = rowPtrsUnpacked_host(myRow);
1391 ret.allocSize = rowPtrsUnpacked_host(myRow + 1) - rowPtrsUnpacked_host(myRow);
1402 ret.offset1D = STINV;
1408template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1411 using Teuchos::OrdinalTraits;
1412 typedef LocalOrdinal LO;
1413 typedef GlobalOrdinal GO;
1419 static_assert(
sizeof(GlobalOrdinal) >=
sizeof(LocalOrdinal),
1420 "Tpetra::CrsGraph: sizeof(GlobalOrdinal) must be >= sizeof(LocalOrdinal).");
1423 static_assert(
sizeof(size_t) >=
sizeof(LocalOrdinal),
1424 "Tpetra::CrsGraph: sizeof(size_t) must be >= sizeof(LocalOrdinal).");
1425 static_assert(
sizeof(GST) >=
sizeof(size_t),
1426 "Tpetra::CrsGraph: sizeof(Tpetra::global_size_t) must be >= sizeof(size_t).");
1435 "Tpetra::CrsGraph: Object cannot be created with the "
1436 "given template arguments: size assumptions are not valid.";
1437 TEUCHOS_TEST_FOR_EXCEPTION(
1438 static_cast<size_t>(Teuchos::OrdinalTraits<LO>::max()) > Teuchos::OrdinalTraits<size_t>::max(),
1439 std::runtime_error, msg);
1440 TEUCHOS_TEST_FOR_EXCEPTION(
1441 static_cast<GST
>(Teuchos::OrdinalTraits<LO>::max()) >
static_cast<GST
>(Teuchos::OrdinalTraits<GO>::max()),
1442 std::runtime_error, msg);
1443 TEUCHOS_TEST_FOR_EXCEPTION(
1444 static_cast<size_t>(Teuchos::OrdinalTraits<GO>::max()) > Teuchos::OrdinalTraits<GST>::max(),
1445 std::runtime_error, msg);
1446 TEUCHOS_TEST_FOR_EXCEPTION(
1447 Teuchos::OrdinalTraits<size_t>::max() > Teuchos::OrdinalTraits<GST>::max(),
1448 std::runtime_error, msg);
1451template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1455 const SLocalGlobalViews& newInds,
1456 const ELocalGlobal lg,
1457 const ELocalGlobal I) {
1458 using Teuchos::ArrayView;
1459 typedef LocalOrdinal LO;
1460 typedef GlobalOrdinal GO;
1461 const char tfecfFuncName[] =
"insertIndices: ";
1463 size_t oldNumEnt = 0;
1465 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lg != GlobalIndices && lg != LocalIndices, std::invalid_argument,
1466 "lg must be either GlobalIndices or LocalIndices.");
1470 size_t numNewInds = 0;
1471 if (lg == GlobalIndices) {
1472 ArrayView<const GO> new_ginds = newInds.ginds;
1473 numNewInds = new_ginds.size();
1474 if (I == GlobalIndices) {
1475 auto gind_view =
gblInds_wdv.getHostView(Access::ReadWrite);
1477 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(gind_view.size()) <
1478 rowinfo.numEntries + numNewInds,
1480 "gind_view.size() = " << gind_view.size()
1481 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1482 <<
") + numNewInds (= " << numNewInds <<
").");
1484 GO*
const gblColInds_out = gind_view.data() + rowinfo.offset1D + rowinfo.numEntries;
1485 for (
size_t k = 0; k < numNewInds; ++k) {
1486 gblColInds_out[k] = new_ginds[k];
1488 }
else if (I == LocalIndices) {
1491 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(lind_view.size()) <
1492 rowinfo.numEntries + numNewInds,
1494 "lind_view.size() = " << lind_view.size()
1495 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1496 <<
") + numNewInds (= " << numNewInds <<
").");
1498 LO*
const lclColInds_out = lind_view.data() + rowinfo.offset1D + rowinfo.numEntries;
1499 for (
size_t k = 0; k < numNewInds; ++k) {
1500 lclColInds_out[k] =
colMap_->getLocalElement(new_ginds[k]);
1503 }
else if (lg == LocalIndices) {
1504 ArrayView<const LO> new_linds = newInds.linds;
1505 numNewInds = new_linds.size();
1506 if (I == LocalIndices) {
1509 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(lind_view.size()) <
1510 rowinfo.numEntries + numNewInds,
1512 "lind_view.size() = " << lind_view.size()
1513 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
1514 <<
") + numNewInds (= " << numNewInds <<
").");
1516 LO*
const lclColInds_out = lind_view.data() + rowinfo.offset1D + rowinfo.numEntries;
1517 for (
size_t k = 0; k < numNewInds; ++k) {
1518 lclColInds_out[k] = new_linds[k];
1520 }
else if (I == GlobalIndices) {
1521 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
1522 "The case where the input indices are local "
1523 "and the indices to write are global (lg=LocalIndices, I="
1524 "GlobalIndices) is not implemented, because it does not make sense."
1526 <<
"If you have correct local column indices, that "
1527 "means the graph has a column Map. In that case, you should be "
1528 "storing local indices.");
1532 rowinfo.numEntries += numNewInds;
1537 const size_t chkNewNumEnt =
1539 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(chkNewNumEnt != oldNumEnt + numNewInds, std::logic_error,
1540 "chkNewNumEnt = " << chkNewNumEnt
1541 <<
" != oldNumEnt (= " << oldNumEnt
1542 <<
") + numNewInds (= " << numNewInds <<
").");
1548template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1552 const GlobalOrdinal inputGblColInds[],
1553 const size_t numInputInds) {
1555 inputGblColInds, numInputInds);
1558template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1562 const GlobalOrdinal inputGblColInds[],
1563 const size_t numInputInds,
1564 std::function<
void(
const size_t,
const size_t,
const size_t)> fun) {
1566 using Kokkos::MemoryUnmanaged;
1567 using Kokkos::subview;
1569 using Teuchos::ArrayView;
1570 using LO = LocalOrdinal;
1571 using GO = GlobalOrdinal;
1573 const char tfecfFuncName[] =
"insertGlobalIndicesImpl: ";
1574 const LO lclRow =
static_cast<LO
>(rowInfo.localRow);
1576 auto numEntries = rowInfo.numEntries;
1577 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1578 inp_view_type inputInds(inputGblColInds, numInputInds);
1581 auto gblIndsHostView = this->
gblInds_wdv.getHostView(Access::ReadWrite);
1584 numEntries, inputInds, fun);
1587 const bool insertFailed =
1588 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1590 constexpr size_t ONE(1);
1591 const int myRank = this->
getComm()->getRank();
1592 std::ostringstream os;
1594 os <<
"Proc " << myRank <<
": Not enough capacity to insert "
1596 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1597 <<
" into local row " << lclRow <<
", which currently has "
1598 << rowInfo.numEntries
1599 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1600 <<
" and total allocation size " << rowInfo.allocSize
1602 const size_t maxNumToPrint =
1604 ArrayView<const GO> inputGblColIndsView(inputGblColInds,
1606 verbosePrintArray(os, inputGblColIndsView,
1612 ArrayView<const GO> curGblColIndsView(curGblColInds.data(),
1613 rowInfo.numEntries);
1614 verbosePrintArray(os, curGblColIndsView,
1618 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
1627template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1630 const Teuchos::ArrayView<const LocalOrdinal>& indices,
1631 std::function<
void(
const size_t,
const size_t,
const size_t)> fun) {
1632 using Kokkos::MemoryUnmanaged;
1633 using Kokkos::subview;
1635 using LO = LocalOrdinal;
1637 const char tfecfFuncName[] =
"insertLocallIndicesImpl: ";
1639 const RowInfo rowInfo = this->getRowInfo(myRow);
1641 size_t numNewInds = 0;
1642 size_t newNumEntries = 0;
1644 auto numEntries = rowInfo.numEntries;
1646 using inp_view_type = View<const LO*, Kokkos::HostSpace, MemoryUnmanaged>;
1647 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1648 size_t numInserted = 0;
1650 auto lclInds = lclIndsUnpacked_wdv.getHostView(Access::ReadWrite);
1652 numEntries, inputInds, fun);
1655 const bool insertFailed =
1656 numInserted == Teuchos::OrdinalTraits<size_t>::invalid();
1658 constexpr size_t ONE(1);
1659 const size_t numInputInds(indices.size());
1660 const int myRank = this->getComm()->getRank();
1661 std::ostringstream os;
1662 os <<
"On MPI Process " << myRank <<
": Not enough capacity to "
1665 <<
" ind" << (numInputInds != ONE ?
"ices" :
"ex")
1666 <<
" into local row " << myRow <<
", which currently has "
1667 << rowInfo.numEntries
1668 <<
" entr" << (rowInfo.numEntries != ONE ?
"ies" :
"y")
1669 <<
" and total allocation size " << rowInfo.allocSize <<
".";
1670 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
1672 numNewInds = numInserted;
1673 newNumEntries = rowInfo.numEntries + numNewInds;
1675 this->k_numRowEntries_(myRow) += numNewInds;
1676 this->setLocallyModified();
1679 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow(myRow);
1680 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(chkNewNumEntries != newNumEntries, std::logic_error,
1681 "getNumEntriesInLocalRow(" << myRow <<
") = " << chkNewNumEntries
1682 <<
" != newNumEntries = " << newNumEntries
1683 <<
". Please report this bug to the Tpetra developers.");
1687template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1691 const Teuchos::ArrayView<const GlobalOrdinal>& indices,
1692 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
const {
1693 using GO = GlobalOrdinal;
1694 using Kokkos::MemoryUnmanaged;
1697 auto invalidCount = Teuchos::OrdinalTraits<size_t>::invalid();
1699 using inp_view_type = View<const GO*, Kokkos::HostSpace, MemoryUnmanaged>;
1700 inp_view_type inputInds(indices.getRawPtr(), indices.size());
1702 size_t numFound = 0;
1703 LocalOrdinal lclRow = rowInfo.localRow;
1706 return invalidCount;
1707 const auto& colMap = *(this->
colMap_);
1708 auto map = [&](GO
const gblInd) {
return colMap.getLocalElement(gblInd); };
1710 numFound = Details::findCrsIndicesSorted(
1726 gblInds_wdv.getHostView(Access::ReadOnly), inputInds, fun);
1731template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1734 const Teuchos::RCP<const map_type>& rangeMap) {
1746template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1749 const auto INV = Teuchos::OrdinalTraits<global_size_t>::invalid();
1751 globalNumEntries_ = INV;
1752 globalMaxNumRowEntries_ = INV;
1753 haveGlobalConstants_ =
false;
1756template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1761 const char tfecfFuncName[] =
"checkInternalState: ";
1762 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1764 std::unique_ptr<std::string> prefix;
1766 prefix = this->createPrefix(
"CrsGraph",
"checkInternalState");
1767 std::ostringstream os;
1768 os << *prefix <<
"Start" << endl;
1769 std::cerr << os.str();
1772 const global_size_t GSTI = Teuchos::OrdinalTraits<global_size_t>::invalid();
1778 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->
rowMap_.is_null(), std::logic_error,
1779 "Row Map is null." << suffix);
1782 const LocalOrdinal lclNumRows =
1786 "Graph cannot be both fill active and fill complete." << suffix);
1789 this->rangeMap_.is_null() ||
1790 this->domainMap_.is_null()),
1792 "Graph is full complete, but at least one of {column, range, domain} "
1795 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->
isStorageOptimized() && !this->indicesAreAllocated(),
1797 "Storage is optimized, but indices are not "
1798 "allocated, not even trivially."
1801 size_t nodeAllocSize = 0;
1804 }
catch (std::logic_error& e) {
1805 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1806 "getLocalAllocationSize threw "
1807 "std::logic_error: "
1809 }
catch (std::exception& e) {
1810 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1811 "getLocalAllocationSize threw an "
1815 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
1816 "getLocalAllocationSize threw an exception "
1817 "not a subclass of std::exception.");
1823 "Storage is optimized, but "
1824 "this->getLocalAllocationSize() = "
1832 "Graph claims not to have global constants, but "
1833 "some of the global constants are not marked as invalid."
1839 "Graph claims to have global constants, but "
1840 "some of them are marked as invalid."
1846 "Graph claims to have global constants, and "
1847 "all of the values of the global constants are valid, but "
1848 "some of the local constants are greater than "
1849 "their corresponding global constants."
1851 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->indicesAreAllocated() &&
1855 "The graph claims that its indices are allocated, but "
1856 "either numAllocForAllRows_ (= "
1857 << this->numAllocForAllRows_ <<
") is "
1858 "nonzero, or k_numAllocPerRow_ has nonzero dimension. In other words, "
1859 "the graph is supposed to release its \"allocation specifications\" "
1860 "when it allocates its indices."
1864 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked_host.extent(0) != rowPtrsUnpacked_dev.extent(0),
1866 "The host and device views of k_rowPtrs_ have "
1867 "different sizes; rowPtrsUnpacked_host_ has size "
1868 << rowPtrsUnpacked_host.extent(0)
1869 <<
", but rowPtrsUnpacked_dev_ has size "
1870 << rowPtrsUnpacked_dev.extent(0)
1873 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
size_t(rowPtrsUnpacked_host.extent(0)) !=
size_t(lclNumRows + 1),
1875 "The graph is globally indexed and "
1876 "k_rowPtrs has nonzero size "
1877 << rowPtrsUnpacked_host.extent(0)
1878 <<
", but that size does not equal lclNumRows+1 = "
1879 << (lclNumRows + 1) <<
"." << suffix);
1880 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked_host(lclNumRows) !=
size_t(
gblInds_wdv.extent(0)),
1882 "The graph is globally indexed and "
1883 "k_rowPtrs_ has nonzero size "
1884 << rowPtrsUnpacked_host.extent(0)
1885 <<
", but k_rowPtrs_(lclNumRows=" << lclNumRows <<
")="
1886 << rowPtrsUnpacked_host(lclNumRows)
1887 <<
" != gblInds_wdv.extent(0)="
1891 rowPtrsUnpacked_host.extent(0) != 0 &&
1892 (
static_cast<size_t>(rowPtrsUnpacked_host.extent(0)) !=
1893 static_cast<size_t>(lclNumRows + 1) ||
1894 rowPtrsUnpacked_host(lclNumRows) !=
1897 "If k_rowPtrs_ has nonzero size and "
1898 "the graph is locally indexed, then "
1899 "k_rowPtrs_ must have N+1 rows, and "
1900 "k_rowPtrs_(N) must equal lclIndsUnpacked_wdv.extent(0)."
1903 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->indicesAreAllocated() &&
1904 nodeAllocSize > 0 &&
1906 this->gblInds_wdv.extent(0) == 0,
1908 "Graph is allocated nontrivially, but "
1909 "but 1-D allocations are not present."
1912 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->indicesAreAllocated() &&
1913 ((rowPtrsUnpacked_host.extent(0) != 0 ||
1914 this->k_numRowEntries_.extent(0) != 0) ||
1915 this->lclIndsUnpacked_wdv.extent(0) != 0 ||
1916 this->gblInds_wdv.extent(0) != 0),
1918 "If indices are not allocated, "
1919 "then none of the buffers should be."
1924 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC((this->indicesAreLocal_ || this->indicesAreGlobal_) &&
1925 !this->indicesAreAllocated_,
1927 "Indices may be local or global only if they are "
1930 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->indicesAreLocal_ && this->indicesAreGlobal_,
1931 std::logic_error,
"Indices may not be both local and global." << suffix);
1932 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreLocal_ &&
gblInds_wdv.extent(0) != 0,
1934 "Indices are local, but "
1935 "gblInds_wdv.extent(0) (= "
1937 <<
") != 0. In other words, if indices are local, then "
1938 "allocations of global indices should not be present."
1940 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreGlobal_ &&
lclIndsUnpacked_wdv.extent(0) != 0,
1942 "Indices are global, but "
1943 "lclIndsUnpacked_wdv.extent(0) (= "
1945 <<
") != 0. In other words, if indices are global, "
1946 "then allocations for local indices should not be present."
1948 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreLocal_ && nodeAllocSize > 0 &&
1951 "Indices are local and "
1952 "getLocalAllocationSize() = "
1953 << nodeAllocSize <<
" > 0, but "
1954 "lclIndsUnpacked_wdv.extent(0) = 0 and getLocalNumRows() = "
1956 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(indicesAreGlobal_ && nodeAllocSize > 0 &&
1959 "Indices are global and "
1960 "getLocalAllocationSize() = "
1961 << nodeAllocSize <<
" > 0, but "
1962 "gblInds_wdv.extent(0) = 0 and getLocalNumRows() = "
1965 if (this->indicesAreAllocated() &&
1966 rowPtrsUnpacked_host.extent(0) != 0) {
1967 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(rowPtrsUnpacked_host.extent(0)) !=
1968 this->getLocalNumRows() + 1,
1970 "Indices are allocated and "
1971 "k_rowPtrs_ has nonzero length, but rowPtrsUnpacked_host_.extent(0) = "
1972 << rowPtrsUnpacked_host.extent(0) <<
" != getLocalNumRows()+1 = "
1973 << (this->getLocalNumRows() + 1) <<
"." << suffix);
1974 const size_t actualNumAllocated =
1979 "Graph is locally indexed, indices are "
1980 "are allocated, and k_rowPtrs_ has nonzero length, but "
1981 "lclIndsUnpacked_wdv.extent(0) = "
1982 << this->lclIndsUnpacked_wdv.extent(0)
1983 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
1985 static_cast<size_t>(this->
gblInds_wdv.extent(0)) != actualNumAllocated,
1987 "Graph is globally indexed, indices "
1988 "are allocated, and k_rowPtrs_ has nonzero length, but "
1989 "gblInds_wdv.extent(0) = "
1990 << this->gblInds_wdv.extent(0)
1991 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
1995 std::ostringstream os;
1996 os << *prefix <<
"Done" << endl;
1997 std::cerr << os.str();
2002template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2007 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2008 return Teuchos::OrdinalTraits<size_t>::invalid();
2010 return rowInfo.numEntries;
2014template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2019 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2020 return Teuchos::OrdinalTraits<size_t>::invalid();
2022 return rowInfo.numEntries;
2026template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2031 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2032 return Teuchos::OrdinalTraits<size_t>::invalid();
2034 return rowInfo.allocSize;
2038template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2043 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid()) {
2044 return Teuchos::OrdinalTraits<size_t>::invalid();
2046 return rowInfo.allocSize;
2050template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2051typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_host_view_type
2057template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2058typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_device_view_type
2064template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2065typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::local_inds_host_view_type
2071template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2078template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2081 nonconst_local_inds_host_view_type& indices,
2082 size_t& numEntries)
const {
2083 using Teuchos::ArrayView;
2084 const char tfecfFuncName[] =
"getLocalRowCopy: ";
2086 TEUCHOS_TEST_FOR_EXCEPTION(
2088 "Tpetra::CrsGraph::getLocalRowCopy: The graph is globally indexed and "
2089 "does not have a column Map yet. That means we don't have local indices "
2090 "for columns yet, so it doesn't make sense to call this method. If the "
2091 "graph doesn't have a column Map yet, you should call fillComplete on "
2098 const size_t theNumEntries = rowinfo.numEntries;
2099 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(indices.size()) < theNumEntries, std::runtime_error,
2100 "Specified storage (size==" << indices.size() <<
") does not suffice "
2102 << theNumEntries <<
" entry/ies for this row.");
2103 numEntries = theNumEntries;
2105 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid()) {
2108 for (
size_t j = 0; j < theNumEntries; ++j) {
2109 indices[j] = lclInds(j);
2113 for (
size_t j = 0; j < theNumEntries; ++j) {
2114 indices[j] =
colMap_->getLocalElement(gblInds(j));
2120template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2123 nonconst_global_inds_host_view_type& indices,
2124 size_t& numEntries)
const {
2125 using Teuchos::ArrayView;
2126 const char tfecfFuncName[] =
"getGlobalRowCopy: ";
2131 const size_t theNumEntries = rowinfo.numEntries;
2132 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2133 static_cast<size_t>(indices.size()) < theNumEntries, std::runtime_error,
2134 "Specified storage (size==" << indices.size() <<
") does not suffice "
2136 << theNumEntries <<
" entry/ies for this row.");
2137 numEntries = theNumEntries;
2139 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid()) {
2142 bool err =
colMap_->getGlobalElements(lclInds.data(), theNumEntries, indices.data());
2143 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(err, std::runtime_error,
"getGlobalElements error");
2147 (
void*)indices.data(),
2148 (
const void*)gblInds.data(),
2149 theNumEntries *
sizeof(*indices.data()));
2154template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2157 const LocalOrdinal localRow,
2158 local_inds_host_view_type& indices)
const {
2159 const char tfecfFuncName[] =
"getLocalRowView: ";
2162 "The graph's indices are "
2163 "currently stored as global indices, so we cannot return a view with "
2164 "local column indices, whether or not the graph has a column Map. If "
2165 "the graph _does_ have a column Map, use getLocalRowCopy() instead.");
2168 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid() &&
2169 rowInfo.numEntries > 0) {
2176 indices = local_inds_host_view_type();
2180 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(indices.size()) !=
2184 "= " << indices.extent(0)
2185 <<
" != getNumEntriesInLocalRow(localRow=" << localRow <<
") = " <<
getNumEntriesInLocalRow(localRow) <<
". Please report this bug to the Tpetra developers.");
2189template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2192 const GlobalOrdinal globalRow,
2193 global_inds_host_view_type& indices)
const {
2194 const char tfecfFuncName[] =
"getGlobalRowView: ";
2196 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
isLocallyIndexed(), std::runtime_error,
2197 "The graph's indices are "
2198 "currently stored as local indices, so we cannot return a view with "
2199 "global column indices. Use getGlobalRowCopy() instead.");
2204 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid() &&
2205 rowInfo.numEntries > 0) {
2206 indices =
gblInds_wdv.getHostSubview(rowInfo.offset1D,
2210 indices =
typename global_inds_dualv_type::t_host::const_type();
2213 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(indices.size()) !=
2215 std::logic_error,
"indices.size() = " << indices.extent(0) <<
" != getNumEntriesInGlobalRow(globalRow=" << globalRow <<
") = " <<
getNumEntriesInGlobalRow(globalRow) <<
". Please report this bug to the Tpetra developers.");
2219template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2222 const Teuchos::ArrayView<const LocalOrdinal>& indices) {
2223 const char tfecfFuncName[] =
"insertLocalIndices: ";
2225 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
isFillActive(), std::runtime_error,
"Fill must be active.");
2227 "Graph indices are global; use insertGlobalIndices().");
2228 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
hasColMap(), std::runtime_error,
2229 "Cannot insert local indices without a column Map.");
2230 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
rowMap_->isNodeLocalElement(localRow), std::runtime_error,
2231 "Local row index " << localRow <<
" is not in the row Map "
2232 "on the calling process.");
2233 if (!indicesAreAllocated()) {
2234 allocateIndices(LocalIndices, verbose_);
2244 using Teuchos::Array;
2245 using Teuchos::toString;
2246 typedef typename Teuchos::ArrayView<const LocalOrdinal>::size_type size_type;
2249 Array<LocalOrdinal> badColInds;
2250 bool allInColMap =
true;
2251 for (size_type k = 0; k < indices.size(); ++k) {
2253 allInColMap =
false;
2254 badColInds.push_back(indices[k]);
2258 std::ostringstream os;
2259 os <<
"Tpetra::CrsGraph::insertLocalIndices: You attempted to insert "
2260 "entries in owned row "
2261 << localRow <<
", at the following column "
2263 << toString(indices) <<
"." << endl;
2264 os <<
"Of those, the following indices are not in the column Map on "
2266 << toString(badColInds) <<
"." << endl
2268 "the graph has a column Map already, it is invalid to insert entries "
2269 "at those locations.";
2270 TEUCHOS_TEST_FOR_EXCEPTION(!allInColMap, std::invalid_argument, os.str());
2275 insertLocalIndicesImpl(localRow, indices);
2278 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!indicesAreAllocated() || !
isLocallyIndexed(), std::logic_error,
2279 "At the end of insertLocalIndices, ! indicesAreAllocated() || "
2280 "! isLocallyIndexed() is true. Please report this bug to the "
2281 "Tpetra developers.");
2285template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2288 const LocalOrdinal numEnt,
2289 const LocalOrdinal inds[]) {
2290 Teuchos::ArrayView<const LocalOrdinal> indsT(inds, numEnt);
2294template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2297 const LocalOrdinal numInputInds,
2298 const GlobalOrdinal inputGblColInds[]) {
2299 typedef LocalOrdinal LO;
2300 const char tfecfFuncName[] =
"insertGlobalIndices: ";
2302 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->
isLocallyIndexed(), std::runtime_error,
2303 "graph indices are local; use insertLocalIndices().");
2308 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->
isFillActive(), std::runtime_error,
2309 "You are not allowed to call this method if fill is not active. "
2310 "If fillComplete has been called, you must first call resumeFill "
2311 "before you may insert indices.");
2312 if (!indicesAreAllocated()) {
2313 allocateIndices(GlobalIndices, verbose_);
2315 const LO lclRow = this->
rowMap_->getLocalElement(gblRow);
2316 if (lclRow != Tpetra::Details::OrdinalTraits<LO>::invalid()) {
2325 std::vector<GlobalOrdinal> badColInds;
2326 bool allInColMap =
true;
2327 for (LO k = 0; k < numInputInds; ++k) {
2329 allInColMap =
false;
2330 badColInds.push_back(inputGblColInds[k]);
2334 std::ostringstream os;
2335 os <<
"You attempted to insert entries in owned row " << gblRow
2336 <<
", at the following column indices: [";
2337 for (LO k = 0; k < numInputInds; ++k) {
2338 os << inputGblColInds[k];
2339 if (k +
static_cast<LO
>(1) < numInputInds) {
2344 <<
"Of those, the following indices are not in "
2345 "the column Map on this process: [";
2346 for (
size_t k = 0; k < badColInds.size(); ++k) {
2347 os << badColInds[k];
2348 if (k +
size_t(1) < badColInds.size()) {
2353 <<
"Since the matrix has a column Map already, "
2354 "it is invalid to insert entries at those locations.";
2355 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::invalid_argument, os.str());
2366template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2369 const Teuchos::ArrayView<const GlobalOrdinal>& inputGblColInds) {
2371 inputGblColInds.getRawPtr());
2374template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2377 const GlobalOrdinal gblColInds[],
2378 const LocalOrdinal numGblColInds) {
2379 typedef LocalOrdinal LO;
2380 typedef GlobalOrdinal GO;
2381 const char tfecfFuncName[] =
"insertGlobalIndicesFiltered: ";
2383 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->
isLocallyIndexed(), std::runtime_error,
2384 "Graph indices are local; use insertLocalIndices().");
2389 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->
isFillActive(), std::runtime_error,
2390 "You are not allowed to call this method if fill is not active. "
2391 "If fillComplete has been called, you must first call resumeFill "
2392 "before you may insert indices.");
2393 if (!indicesAreAllocated()) {
2394 allocateIndices(GlobalIndices, verbose_);
2397 Teuchos::ArrayView<const GO> gblColInds_av(gblColInds, numGblColInds);
2403 while (curOffset < numGblColInds) {
2407 LO endOffset = curOffset;
2408 for (; endOffset < numGblColInds; ++endOffset) {
2410 if (lclCol == Tpetra::Details::OrdinalTraits<LO>::invalid()) {
2417 const LO numIndInSeq = (endOffset - curOffset);
2418 if (numIndInSeq != 0) {
2425 curOffset = endOffset + 1;
2429 gblColInds_av.size());
2433template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2436 const GlobalOrdinal gblColInds[],
2437 const LocalOrdinal numGblColInds) {
2441 std::vector<GlobalOrdinal>& nonlocalRow = this->
nonlocals_[gblRow];
2442 for (LocalOrdinal k = 0; k < numGblColInds; ++k) {
2446 nonlocalRow.push_back(gblColInds[k]);
2450template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2453 const char tfecfFuncName[] =
"removeLocalIndices: ";
2454 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2455 !
isFillActive(), std::runtime_error,
"requires that fill is active.");
2456 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2458 "cannot remove indices after optimizeStorage() has been called.");
2459 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2461 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2462 !
rowMap_->isNodeLocalElement(lrow), std::runtime_error,
2463 "Local row " << lrow <<
" is not in the row Map on the calling process.");
2464 if (!indicesAreAllocated()) {
2465 allocateIndices(LocalIndices, verbose_);
2474 !indicesAreAllocated() ||
2477 "Violated stated post-conditions. Please contact Tpetra team.");
2481template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2483 setAllIndices(
const typename local_graph_device_type::row_map_type& rowPointers,
2484 const typename local_graph_device_type::entries_type::non_const_type& columnIndices) {
2486 ProfilingRegion region(
"Tpetra::CrsGraph::setAllIndices");
2487 const char tfecfFuncName[] =
"setAllIndices: ";
2488 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2490 "The graph must have a column Map before you may call this method.");
2493 LocalOrdinal rowPtrLen = rowPointers.size();
2494 if (numLocalRows == 0) {
2495 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2496 rowPtrLen != 0 && rowPtrLen != 1,
2497 std::runtime_error,
"Have 0 local rows, but rowPointers.size() is neither 0 nor 1.");
2499 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2500 rowPtrLen != numLocalRows + 1,
2501 std::runtime_error,
"rowPointers.size() = " << rowPtrLen <<
" != this->getLocalNumRows()+1 = " << (numLocalRows + 1) <<
".");
2506 using exec_space =
typename local_graph_device_type::execution_space;
2507 int columnsOutOfBounds = 0;
2509 Kokkos::parallel_reduce(
2510 Kokkos::RangePolicy<exec_space>(0, columnIndices.extent(0)),
2511 KOKKOS_LAMBDA(
const LocalOrdinal i,
int& lOutOfBounds) {
2512 if (columnIndices(i) < 0 || columnIndices(i) >= numLocalCols)
2515 columnsOutOfBounds);
2516 int globalColsOutOfBounds = 0;
2518 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, columnsOutOfBounds,
2519 Teuchos::outArg(globalColsOutOfBounds));
2520 if (globalColsOutOfBounds) {
2521 std::string message;
2522 if (columnsOutOfBounds) {
2524 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not all within range [0, getLocalNumCols())!\n";
2527 throw std::invalid_argument(
"CrsGraph::setAllIndices(): columnIndices are out of the valid range on at least one process.");
2534 using exec_space =
typename local_graph_device_type::execution_space;
2535 using size_type =
typename local_graph_device_type::size_type;
2536 Kokkos::parallel_reduce(
2537 Kokkos::RangePolicy<exec_space>(0, numLocalRows),
2538 KOKKOS_LAMBDA(
const LocalOrdinal i,
int& lNotSorted) {
2539 size_type rowBegin = rowPointers(i);
2540 size_type rowEnd = rowPointers(i + 1);
2541 for (size_type j = rowBegin + 1; j < rowEnd; j++) {
2542 if (columnIndices(j - 1) > columnIndices(j)) {
2549 int globalNotSorted = 0;
2551 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, notSorted,
2552 Teuchos::outArg(globalNotSorted));
2553 if (globalNotSorted) {
2554 std::string message;
2557 message = std::string(
"ERROR, rank ") + std::to_string(comm->getRank()) +
", CrsGraph::setAllIndices(): provided columnIndices are not sorted!\n";
2560 throw std::invalid_argument(
"CrsGraph::setAllIndices(): provided columnIndices are not sorted within rows on at least one process.");
2564 indicesAreAllocated_ =
true;
2565 indicesAreLocal_ =
true;
2570 setRowPtrs(rowPointers);
2572 set_need_sync_host_uvm_access();
2587template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2590 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices) {
2592 typedef typename local_graph_device_type::row_map_type row_map_type;
2593 typedef typename row_map_type::array_layout layout_type;
2594 typedef typename row_map_type::non_const_value_type row_offset_type;
2595 typedef View<
size_t*, layout_type, Kokkos::HostSpace,
2596 Kokkos::MemoryUnmanaged>
2598 typedef typename row_map_type::non_const_type nc_row_map_type;
2600 const size_t size =
static_cast<size_t>(rowPointers.size());
2601 constexpr bool same = std::is_same<size_t, row_offset_type>::value;
2602 input_view_type ptr_in(rowPointers.getRawPtr(), size);
2604 nc_row_map_type ptr_rot(
"Tpetra::CrsGraph::ptr", size);
2606 if constexpr (same) {
2607 using lexecution_space =
typename device_type::execution_space;
2608 Kokkos::deep_copy(lexecution_space(),
2613 constexpr bool inHostMemory =
2614 std::is_same<
typename row_map_type::memory_space,
2615 Kokkos::HostSpace>::value;
2625 View<size_t*, layout_type, device_type> ptr_st(
"Tpetra::CrsGraph::ptr", size);
2628 Kokkos::deep_copy(ptr_st, ptr_in);
2637 Kokkos::View<LocalOrdinal*, layout_type, device_type> k_ind =
2638 Kokkos::Compat::getKokkosViewDeepCopy<device_type>(columnIndices());
2642template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2646 using Teuchos::Comm;
2647 using Teuchos::outArg;
2650 using Teuchos::REDUCE_MAX;
2651 using Teuchos::REDUCE_MIN;
2652 using Teuchos::reduceAll;
2653 using crs_graph_type = CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
2656 using size_type =
typename Teuchos::Array<GO>::size_type;
2658 const char tfecfFuncName[] =
"globalAssemble: ";
2662 std::unique_ptr<std::string> prefix;
2664 prefix = this->createPrefix(
"CrsGraph",
"globalAssemble");
2665 std::ostringstream os;
2666 os << *prefix <<
"Start" << endl;
2667 std::cerr << os.str();
2669 RCP<const Comm<int>> comm =
getComm();
2671 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
isFillActive(), std::runtime_error,
2672 "Fill must be active before "
2673 "you may call this method.");
2675 const size_t myNumNonlocalRows = this->
nonlocals_.size();
2682 const int iHaveNonlocalRows = (myNumNonlocalRows == 0) ? 0 : 1;
2683 int someoneHasNonlocalRows = 0;
2684 reduceAll<int, int>(*comm, REDUCE_MAX, iHaveNonlocalRows,
2685 outArg(someoneHasNonlocalRows));
2686 if (someoneHasNonlocalRows == 0) {
2688 std::ostringstream os;
2689 os << *prefix <<
"Done: No nonlocal rows" << endl;
2690 std::cerr << os.str();
2693 }
else if (verbose_) {
2694 std::ostringstream os;
2695 os << *prefix <<
"At least 1 process has nonlocal rows"
2697 std::cerr << os.str();
2710 RCP<const map_type> nonlocalRowMap;
2712 Teuchos::Array<size_t> numEntPerNonlocalRow(myNumNonlocalRows);
2714 Teuchos::Array<GO> myNonlocalGblRows(myNumNonlocalRows);
2715 size_type curPos = 0;
2716 for (
auto mapIter = this->
nonlocals_.begin();
2717 mapIter != this->nonlocals_.end();
2718 ++mapIter, ++curPos) {
2719 myNonlocalGblRows[curPos] = mapIter->first;
2720 std::vector<GO>& gblCols = mapIter->second;
2721 std::sort(gblCols.begin(), gblCols.end());
2722 auto vecLast = std::unique(gblCols.begin(), gblCols.end());
2723 gblCols.erase(vecLast, gblCols.end());
2724 numEntPerNonlocalRow[curPos] = gblCols.size();
2735 GO myMinNonlocalGblRow = std::numeric_limits<GO>::max();
2737 auto iter = std::min_element(myNonlocalGblRows.begin(),
2738 myNonlocalGblRows.end());
2739 if (iter != myNonlocalGblRows.end()) {
2740 myMinNonlocalGblRow = *iter;
2743 GO gblMinNonlocalGblRow = 0;
2744 reduceAll<int, GO>(*comm, REDUCE_MIN, myMinNonlocalGblRow,
2745 outArg(gblMinNonlocalGblRow));
2746 const GO indexBase = gblMinNonlocalGblRow;
2747 const global_size_t INV = Teuchos::OrdinalTraits<global_size_t>::invalid();
2748 nonlocalRowMap = rcp(
new map_type(INV, myNonlocalGblRows(), indexBase, comm));
2752 std::ostringstream os;
2753 os << *prefix <<
"nonlocalRowMap->getIndexBase()="
2754 << nonlocalRowMap->getIndexBase() << endl;
2755 std::cerr << os.str();
2763 RCP<crs_graph_type> nonlocalGraph =
2766 size_type curPos = 0;
2767 for (
auto mapIter = this->
nonlocals_.begin();
2768 mapIter != this->nonlocals_.end();
2769 ++mapIter, ++curPos) {
2770 const GO gblRow = mapIter->first;
2771 std::vector<GO>& gblCols = mapIter->second;
2772 const LO numEnt =
static_cast<LO
>(numEntPerNonlocalRow[curPos]);
2773 nonlocalGraph->insertGlobalIndices(gblRow, numEnt, gblCols.data());
2777 std::ostringstream os;
2778 os << *prefix <<
"Built nonlocal graph" << endl;
2779 std::cerr << os.str();
2791 const bool origRowMapIsOneToOne = origRowMap->isOneToOne();
2793 if (origRowMapIsOneToOne) {
2795 std::ostringstream os;
2796 os << *prefix <<
"Original row Map is 1-to-1" << endl;
2797 std::cerr << os.str();
2799 export_type exportToOrig(nonlocalRowMap, origRowMap);
2804 std::ostringstream os;
2805 os << *prefix <<
"Original row Map is NOT 1-to-1" << endl;
2806 std::cerr << os.str();
2813 export_type exportToOneToOne(nonlocalRowMap, oneToOneRowMap);
2823 std::ostringstream os;
2824 os << *prefix <<
"Export nonlocal graph" << endl;
2825 std::cerr << os.str();
2831 nonlocalGraph = Teuchos::null;
2834 import_type importToOrig(oneToOneRowMap, origRowMap);
2836 std::ostringstream os;
2837 os << *prefix <<
"Import nonlocal graph" << endl;
2838 std::cerr << os.str();
2852 std::ostringstream os;
2853 os << *prefix <<
"Done" << endl;
2854 std::cerr << os.str();
2858template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2860 resumeFill(
const Teuchos::RCP<Teuchos::ParameterList>& params) {
2861 clearGlobalConstants();
2866 fillComplete_ =
false;
2869template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2871 fillComplete(
const Teuchos::RCP<Teuchos::ParameterList>& params) {
2882 Teuchos::RCP<const map_type> domMap = this->
getDomainMap();
2883 if (domMap.is_null()) {
2886 Teuchos::RCP<const map_type> ranMap = this->
getRangeMap();
2887 if (ranMap.is_null()) {
2893template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2895 fillComplete(
const Teuchos::RCP<const map_type>& domainMap,
2896 const Teuchos::RCP<const map_type>& rangeMap,
2897 const Teuchos::RCP<Teuchos::ParameterList>& params) {
2900 const char tfecfFuncName[] =
"fillComplete: ";
2901 const bool verbose = verbose_;
2905 std::unique_ptr<std::string> prefix;
2907 prefix = this->createPrefix(
"CrsGraph",
"fillComplete");
2908 std::ostringstream os;
2909 os << *prefix <<
"Start" << endl;
2910 std::cerr << os.str();
2914 "Graph fill state must be active (isFillActive() "
2915 "must be true) before calling fillComplete().");
2917 const int numProcs =
getComm()->getSize();
2925 if (!params.is_null()) {
2926 if (params->isParameter(
"sort column map ghost gids")) {
2928 params->get<
bool>(
"sort column map ghost gids",
2930 }
else if (params->isParameter(
"Sort column Map ghost GIDs")) {
2932 params->get<
bool>(
"Sort column Map ghost GIDs",
2939 bool assertNoNonlocalInserts =
false;
2940 if (!params.is_null()) {
2941 assertNoNonlocalInserts =
2942 params->get<
bool>(
"No Nonlocal Changes", assertNoNonlocalInserts);
2948 if (!indicesAreAllocated()) {
2951 allocateIndices(LocalIndices, verbose);
2954 allocateIndices(GlobalIndices, verbose);
2962 const bool mayNeedGlobalAssemble = !assertNoNonlocalInserts && numProcs > 1;
2963 if (mayNeedGlobalAssemble) {
2968 const size_t numNonlocals =
nonlocals_.size();
2970 std::ostringstream os;
2971 os << *prefix <<
"Do not need to call globalAssemble; "
2972 "assertNoNonlocalInserts="
2973 << (assertNoNonlocalInserts ?
"true" :
"false")
2974 <<
"numProcs=" << numProcs
2975 <<
", nonlocals_.size()=" << numNonlocals << endl;
2976 std::cerr << os.str();
2978 const int lclNeededGlobalAssemble =
2979 (numProcs > 1 && numNonlocals != 0) ? 1 : 0;
2980 if (lclNeededGlobalAssemble != 0 && verbose) {
2981 std::ostringstream os;
2983 Details::Impl::verbosePrintMap(
2986 std::cerr << os.str() << endl;
2990 auto map = this->
getMap();
2991 auto comm = map.is_null() ? Teuchos::null : map->getComm();
2992 int gblNeededGlobalAssemble = lclNeededGlobalAssemble;
2993 if (!comm.is_null()) {
2994 using Teuchos::REDUCE_MAX;
2995 using Teuchos::reduceAll;
2996 reduceAll(*comm, REDUCE_MAX, lclNeededGlobalAssemble,
2997 Teuchos::outArg(gblNeededGlobalAssemble));
2999 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(gblNeededGlobalAssemble != 0, std::runtime_error,
3000 "nonlocals_.size()=" << numNonlocals <<
" != 0 on at "
3001 "least one process in the CrsGraph's communicator. This "
3002 "means either that you incorrectly set the "
3003 "\"No Nonlocal Changes\" fillComplete parameter to true, "
3004 "or that you inserted invalid entries. "
3005 "Rerun with the environment variable TPETRA_VERBOSE="
3006 "CrsGraph set to see the entries of nonlocals_ on every "
3007 "MPI process (WARNING: lots of output).");
3009 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(lclNeededGlobalAssemble != 0, std::runtime_error,
3010 "nonlocals_.size()=" << numNonlocals <<
" != 0 on the "
3011 "calling process. This means either that you incorrectly "
3012 "set the \"No Nonlocal Changes\" fillComplete parameter "
3013 "to true, or that you inserted invalid entries. "
3014 "Rerun with the environment "
3015 "variable TPETRA_VERBOSE=CrsGraph set to see the entries "
3016 "of nonlocals_ on every MPI process (WARNING: lots of "
3029 Teuchos::Array<int> remotePIDs(0);
3030 const bool mustBuildColMap = !this->
hasColMap();
3031 if (mustBuildColMap) {
3037 const std::pair<size_t, std::string> makeIndicesLocalResult =
3042 using Teuchos::outArg;
3044 using Teuchos::REDUCE_MIN;
3045 using Teuchos::reduceAll;
3047 RCP<const map_type> map = this->
getMap();
3048 RCP<const Teuchos::Comm<int>> comm;
3049 if (!map.is_null()) {
3050 comm = map->getComm();
3052 if (comm.is_null()) {
3053 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(makeIndicesLocalResult.first != 0, std::runtime_error,
3054 makeIndicesLocalResult.second);
3056 const int lclSuccess = (makeIndicesLocalResult.first == 0);
3058 reduceAll(*comm, REDUCE_MIN, lclSuccess, outArg(gblSuccess));
3059 if (gblSuccess != 1) {
3060 std::ostringstream os;
3061 gathervPrint(os, makeIndicesLocalResult.second, *comm);
3062 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
3070 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(makeIndicesLocalResult.first != 0, std::runtime_error,
3071 makeIndicesLocalResult.second);
3085 this->fillLocalGraph(params);
3087 const bool callComputeGlobalConstants = params.get() ==
nullptr ||
3088 params->get(
"compute global constants",
true);
3089 if (callComputeGlobalConstants) {
3094 this->fillComplete_ =
true;
3098 std::ostringstream os;
3099 os << *prefix <<
"Done" << endl;
3100 std::cerr << os.str();
3104template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3107 const Teuchos::RCP<const map_type>& rangeMap,
3108 const Teuchos::RCP<const import_type>& importer,
3109 const Teuchos::RCP<const export_type>& exporter,
3110 const Teuchos::RCP<Teuchos::ParameterList>& params) {
3111 const char tfecfFuncName[] =
"expertStaticFillComplete: ";
3112#ifdef HAVE_TPETRA_MMM_TIMINGS
3114 if (!params.is_null())
3115 label = params->get(
"Timer Label", label);
3116 std::string prefix = std::string(
"Tpetra ") + label + std::string(
": ");
3117 using Teuchos::TimeMonitor;
3118 Teuchos::RCP<Teuchos::TimeMonitor> MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Setup"))));
3121 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3122 domainMap.is_null() || rangeMap.is_null(),
3123 std::runtime_error,
"The input domain Map and range Map must be nonnull.");
3124 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3127 "call this method unless the graph has a column Map.");
3129 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3131 std::runtime_error,
"The calling process has getLocalNumRows() = " <<
getLocalNumRows() <<
" > 0 rows, but the row offsets array has not "
3133 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3135 std::runtime_error,
"The row offsets array has length " << rowPtrsUnpackedLength <<
" != getLocalNumRows()+1 = " << (
getLocalNumRows() + 1) <<
".");
3152 indicesAreAllocated_ =
true;
3157 indicesAreLocal_ =
true;
3158 indicesAreGlobal_ =
false;
3161#ifdef HAVE_TPETRA_MMM_TIMINGS
3163 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Maps"))));
3172#ifdef HAVE_TPETRA_MMM_TIMINGS
3174 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckI"))));
3179 if (importer != Teuchos::null) {
3180 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3181 !importer->getSourceMap()->isSameAs(*
getDomainMap()) ||
3182 !importer->getTargetMap()->isSameAs(*
getColMap()),
3183 std::invalid_argument,
": importer does not match matrix maps.");
3187#ifdef HAVE_TPETRA_MMM_TIMINGS
3189 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckE"))));
3192 if (exporter != Teuchos::null) {
3193 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3194 !exporter->getSourceMap()->isSameAs(*
getRowMap()) ||
3195 !exporter->getTargetMap()->isSameAs(*
getRangeMap()),
3196 std::invalid_argument,
": exporter does not match matrix maps.");
3200#ifdef HAVE_TPETRA_MMM_TIMINGS
3202 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXmake"))));
3204 Teuchos::Array<int> remotePIDs(0);
3207#ifdef HAVE_TPETRA_MMM_TIMINGS
3209 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-fLG"))));
3211 this->fillLocalGraph(params);
3213 const bool callComputeGlobalConstants = params.get() ==
nullptr ||
3214 params->get(
"compute global constants",
true);
3216 if (callComputeGlobalConstants) {
3217#ifdef HAVE_TPETRA_MMM_TIMINGS
3219 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (const)"))));
3223#ifdef HAVE_TPETRA_MMM_TIMINGS
3225 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (noconst)"))));
3230 fillComplete_ =
true;
3232#ifdef HAVE_TPETRA_MMM_TIMINGS
3234 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cIS"))));
3239template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3241 fillLocalGraph(
const Teuchos::RCP<Teuchos::ParameterList>& params) {
3243 typedef typename local_graph_device_type::row_map_type row_map_type;
3244 typedef typename row_map_type::non_const_type non_const_row_map_type;
3245 typedef typename local_graph_device_type::entries_type::non_const_type lclinds_1d_type;
3246 const char tfecfFuncName[] =
3247 "fillLocalGraph (called from fillComplete or "
3248 "expertStaticFillComplete): ";
3249 const size_t lclNumRows = this->getLocalNumRows();
3256 bool requestOptimizedStorage =
true;
3257 if (!params.is_null() && !params->get(
"Optimize Storage",
true)) {
3258 requestOptimizedStorage =
false;
3266 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3268 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked.extent(0) == 0, std::logic_error,
3269 "rowPtrsUnpacked_host_ has size zero, but shouldn't");
3270 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsUnpacked.extent(0) != lclNumRows + 1, std::logic_error,
3271 "rowPtrsUnpacked_host_.extent(0) = "
3272 << rowPtrsUnpacked.extent(0) <<
" != (lclNumRows + 1) = "
3273 << (lclNumRows + 1) <<
".");
3274 const size_t numOffsets = rowPtrsUnpacked.extent(0);
3275 const auto valToCheck = rowPtrsUnpacked(numOffsets - 1);
3276 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numOffsets != 0 &&
3277 lclIndsUnpacked_wdv.extent(0) != valToCheck,
3278 std::logic_error,
"numOffsets=" << numOffsets <<
" != 0 "
3279 " and lclIndsUnpacked_wdv.extent(0)="
3280 << lclIndsUnpacked_wdv.extent(0) <<
" != rowPtrsUnpacked_host_(" << numOffsets <<
")=" << valToCheck <<
".");
3283 size_t allocSize = 0;
3285 allocSize = this->getLocalAllocationSize();
3286 }
catch (std::logic_error& e) {
3287 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
3288 "getLocalAllocationSize threw "
3289 "std::logic_error: "
3291 }
catch (std::runtime_error& e) {
3292 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
3293 "getLocalAllocationSize threw "
3294 "std::runtime_error: "
3296 }
catch (std::exception& e) {
3297 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
3298 "getLocalAllocationSize threw "
3302 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
3303 "getLocalAllocationSize threw "
3304 "an exception not a subclass of std::exception.");
3307 if (this->getLocalNumEntries() != allocSize) {
3310 non_const_row_map_type ptr_d;
3311 row_map_type ptr_d_const;
3320 auto rowPtrsUnpacked = this->getRowPtrsUnpackedHost();
3321 if (rowPtrsUnpacked.extent(0) != 0) {
3322 const size_t numOffsets =
3323 static_cast<size_t>(rowPtrsUnpacked.extent(0));
3324 const auto valToCheck = rowPtrsUnpacked(numOffsets - 1);
3325 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(valToCheck !=
size_t(lclIndsUnpacked_wdv.extent(0)),
3327 "(Unpacked branch) Before allocating "
3328 "or packing, k_rowPtrs_("
3329 << (numOffsets - 1) <<
")="
3330 << valToCheck <<
" != lclIndsUnpacked_wdv.extent(0)="
3331 << lclIndsUnpacked_wdv.extent(0) <<
".");
3341 size_t lclTotalNumEntries = 0;
3345 non_const_row_map_type(
"Tpetra::CrsGraph::ptr", lclNumRows + 1);
3346 ptr_d_const = ptr_d;
3350 typename num_row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
3352 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
size_t(numRowEnt_h.extent(0)) != lclNumRows,
3354 "(Unpacked branch) "
3355 "numRowEnt_h.extent(0)="
3356 << numRowEnt_h.extent(0)
3357 <<
" != getLocalNumRows()=" << lclNumRows <<
"");
3363 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(ptr_d.extent(0)) != lclNumRows + 1,
3365 "(Unpacked branch) After allocating "
3366 "ptr_d, ptr_d.extent(0) = "
3368 <<
" != lclNumRows+1 = " << (lclNumRows + 1) <<
".");
3369 const auto valToCheck =
3370 ::Tpetra::Details::getEntryOnHost(ptr_d, lclNumRows);
3371 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(valToCheck != lclTotalNumEntries, std::logic_error,
3372 "Tpetra::CrsGraph::fillLocalGraph: In unpacked branch, "
3373 "after filling ptr_d, ptr_d(lclNumRows="
3375 <<
") = " << valToCheck <<
" != total number of entries "
3376 "on the calling process = "
3377 << lclTotalNumEntries
3383 lclinds_1d_type ind_d =
3384 lclinds_1d_type(
"Tpetra::CrsGraph::lclInd", lclTotalNumEntries);
3396 typedef pack_functor<
3397 typename local_graph_device_type::entries_type::non_const_type,
3398 typename local_inds_dualv_type::t_dev::const_type,
3400 typename local_graph_device_type::row_map_type>
3402 inds_packer_type f(ind_d,
3403 lclIndsUnpacked_wdv.getDeviceView(Access::ReadOnly),
3404 ptr_d, this->getRowPtrsUnpackedDevice());
3406 typedef typename decltype(ind_d)::execution_space exec_space;
3407 typedef Kokkos::RangePolicy<exec_space, LocalOrdinal> range_type;
3408 Kokkos::parallel_for(range_type(0, lclNumRows), f);
3412 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(ptr_d.extent(0) == 0, std::logic_error,
3413 "(\"Optimize Storage\"=true branch) After packing, "
3414 "ptr_d.extent(0)=0.");
3415 if (ptr_d.extent(0) != 0) {
3416 const size_t numOffsets =
static_cast<size_t>(ptr_d.extent(0));
3417 const auto valToCheck =
3418 ::Tpetra::Details::getEntryOnHost(ptr_d, numOffsets - 1);
3419 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(valToCheck) != ind_d.extent(0),
3421 "(\"Optimize Storage\"=true branch) "
3422 "After packing, ptr_d("
3423 << (numOffsets - 1) <<
")="
3424 << valToCheck <<
" != ind_d.extent(0)="
3425 << ind_d.extent(0) <<
".");
3429 if (requestOptimizedStorage)
3430 setRowPtrs(ptr_d_const);
3432 setRowPtrsPacked(ptr_d_const);
3433 lclIndsPacked_wdv = local_inds_wdv_type(ind_d);
3436 this->setRowPtrs(rowPtrsUnpacked_dev_);
3437 lclIndsPacked_wdv = lclIndsUnpacked_wdv;
3440 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3441 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3442 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowPtrsPacked_dev.extent(0) == 0, std::logic_error,
3443 "(\"Optimize Storage\"=false branch) "
3444 "rowPtrsPacked_dev_.extent(0) = 0.");
3445 if (rowPtrsPacked_dev.extent(0) != 0) {
3446 const size_t numOffsets =
3447 static_cast<size_t>(rowPtrsPacked_dev.extent(0));
3448 const size_t valToCheck =
3449 rowPtrsPacked_host(numOffsets - 1);
3450 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(valToCheck !=
size_t(lclIndsPacked_wdv.extent(0)),
3452 "(\"Optimize Storage\"=false branch) "
3453 "rowPtrsPacked_dev_("
3454 << (numOffsets - 1) <<
")="
3456 <<
" != lclIndsPacked_wdv.extent(0)="
3457 << lclIndsPacked_wdv.extent(0) <<
".");
3463 auto rowPtrsPacked_dev = this->getRowPtrsPackedDevice();
3464 auto rowPtrsPacked_host = this->getRowPtrsPackedHost();
3465 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(rowPtrsPacked_dev.extent(0)) != lclNumRows + 1,
3466 std::logic_error,
"After packing, rowPtrsPacked_dev_.extent(0) = " << rowPtrsPacked_dev.extent(0) <<
" != lclNumRows+1 = " << (lclNumRows + 1) <<
".");
3467 if (rowPtrsPacked_dev.extent(0) != 0) {
3468 const size_t numOffsets =
static_cast<size_t>(rowPtrsPacked_dev.extent(0));
3469 const auto valToCheck = rowPtrsPacked_host(numOffsets - 1);
3470 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<size_t>(valToCheck) != lclIndsPacked_wdv.extent(0),
3471 std::logic_error,
"After packing, rowPtrsPacked_dev_(" << (numOffsets - 1) <<
") = " << valToCheck <<
" != lclIndsPacked_wdv.extent(0) = " << lclIndsPacked_wdv.extent(0) <<
".");
3475 if (requestOptimizedStorage) {
3481 k_numRowEntries_ = num_row_entries_type();
3484 lclIndsUnpacked_wdv = lclIndsPacked_wdv;
3486 storageStatus_ = Details::STORAGE_1D_PACKED;
3489 set_need_sync_host_uvm_access();
3492template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3494 replaceColMap(
const Teuchos::RCP<const map_type>& newColMap) {
3502 const char tfecfFuncName[] =
"replaceColMap: ";
3503 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3505 "Requires matching maps and non-static graph.");
3509template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3512 const Teuchos::RCP<const import_type>& newImport,
3513 const bool sortIndicesInEachRow) {
3515 using Teuchos::REDUCE_MIN;
3516 using Teuchos::reduceAll;
3517 typedef GlobalOrdinal GO;
3518 typedef LocalOrdinal LO;
3519 using col_inds_type_dev =
typename local_inds_dualv_type::t_dev;
3520 const char tfecfFuncName[] =
"reindexColumns: ";
3522 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3524 "The graph is fill complete "
3525 "(isFillComplete() returns true). You must call resumeFill() before "
3526 "you may call this method.");
3559 bool allCurColIndsValid =
true;
3564 bool localSuffices =
true;
3573 col_inds_type_dev newLclInds1D_dev;
3578 if (indicesAreAllocated()) {
3586 newLclInds1D_dev = col_inds_type_dev(
"Tpetra::CrsGraph::lclIndsReindexed",
3589 auto newLclColMap = newColMap->getLocalMap();
3591 const auto LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
3592 const auto GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
3594 const int NOT_ALL_LOCAL_INDICES_ARE_VALID = 1;
3595 const int LOCAL_DOES_NOT_SUFFICE = 2;
3596 int errorStatus = 0;
3597 Kokkos::parallel_reduce(
3598 "Tpetra::CrsGraph::reindexColumns",
3599 Kokkos::RangePolicy<LocalOrdinal, execution_space>(0, allocSize),
3600 KOKKOS_LAMBDA(
const LocalOrdinal k,
int& result) {
3601 const LocalOrdinal oldLclCol = oldLclInds1D(k);
3602 if (oldLclCol == LO_INVALID) {
3603 result &= NOT_ALL_LOCAL_INDICES_ARE_VALID;
3605 const GO gblCol = oldLclColMap.getGlobalElement(oldLclCol);
3606 if (gblCol == GO_INVALID) {
3607 result &= LOCAL_DOES_NOT_SUFFICE;
3609 const LocalOrdinal newLclCol = newLclColMap.getLocalElement(gblCol);
3610 if (newLclCol == LO_INVALID) {
3611 result &= NOT_ALL_LOCAL_INDICES_ARE_VALID;
3613 newLclInds1D_dev(k) = newLclCol;
3618 Kokkos::LOr<int>(errorStatus));
3619 allCurColIndsValid = !(errorStatus & NOT_ALL_LOCAL_INDICES_ARE_VALID);
3620 localSuffices = !(errorStatus & LOCAL_DOES_NOT_SUFFICE);
3627 allCurColIndsValid =
false;
3643 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
3646 for (
size_t k = 0; k < rowInfo.numEntries; ++k) {
3647 const GO gblCol = oldGblRowView(k);
3648 if (!newColMap->isNodeGlobalElement(gblCol)) {
3649 localSuffices =
false;
3659 lclSuccess[0] = allCurColIndsValid ? 1 : 0;
3660 lclSuccess[1] = localSuffices ? 1 : 0;
3664 RCP<const Teuchos::Comm<int>> comm =
3666 if (!comm.is_null()) {
3667 reduceAll<int, int>(*comm, REDUCE_MIN, 2, lclSuccess, gblSuccess);
3670 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3671 gblSuccess[0] == 0, std::runtime_error,
3672 "It is not possible to continue."
3673 " The most likely reason is that the graph is locally indexed, but the "
3674 "column Map is missing (null) on some processes, due to a previous call "
3675 "to replaceColMap().");
3677 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3678 gblSuccess[1] == 0, std::runtime_error,
3679 "On some process, the graph "
3680 "contains column indices that are in the old column Map, but not in the "
3681 "new column Map (on that process). This method does NOT redistribute "
3682 "data; it does not claim to do the work of an Import or Export operation."
3683 " This means that for all processess, the calling process MUST own all "
3684 "column indices, in both the old column Map and the new column Map. In "
3685 "this case, you will need to do an Import or Export operation to "
3686 "redistribute data.");
3704 if (sortIndicesInEachRow) {
3711 const bool sorted =
false;
3712 const bool merged =
true;
3713 this->sortAndMergeAllIndices(sorted, merged);
3718 if (newImport.is_null()) {
3739template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3742 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMap: ";
3743 TEUCHOS_TEST_FOR_EXCEPTION(
3744 colMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3745 "this method unless the graph already has a column Map.");
3746 TEUCHOS_TEST_FOR_EXCEPTION(
3747 newDomainMap.is_null(), std::invalid_argument,
3748 prefix <<
"The new domain Map must be nonnull.");
3751 Teuchos::RCP<const import_type> newImporter = Teuchos::null;
3752 if (newDomainMap !=
colMap_ && (!newDomainMap->isSameAs(*
colMap_))) {
3758template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3761 const Teuchos::RCP<const import_type>& newImporter) {
3762 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMapAndImporter: ";
3763 TEUCHOS_TEST_FOR_EXCEPTION(
3764 colMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3765 "this method unless the graph already has a column Map.");
3766 TEUCHOS_TEST_FOR_EXCEPTION(
3767 newDomainMap.is_null(), std::invalid_argument,
3768 prefix <<
"The new domain Map must be nonnull.");
3771 if (newImporter.is_null()) {
3776 const bool colSameAsDom =
colMap_->isSameAs(*newDomainMap);
3777 TEUCHOS_TEST_FOR_EXCEPTION(!colSameAsDom, std::invalid_argument,
3778 "If the new Import is null, "
3779 "then the new domain Map must be the same as the current column Map.");
3781 const bool colSameAsTgt =
3782 colMap_->isSameAs(*(newImporter->getTargetMap()));
3783 const bool newDomSameAsSrc =
3784 newDomainMap->isSameAs(*(newImporter->getSourceMap()));
3785 TEUCHOS_TEST_FOR_EXCEPTION(!colSameAsTgt || !newDomSameAsSrc, std::invalid_argument,
3787 "new Import is nonnull, then the current column Map must be the same "
3788 "as the new Import's target Map, and the new domain Map must be the "
3789 "same as the new Import's source Map.");
3794 importer_ = Teuchos::rcp_const_cast<import_type>(newImporter);
3797template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3800 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMap: ";
3801 TEUCHOS_TEST_FOR_EXCEPTION(
3802 rowMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3803 "this method unless the graph already has a row Map.");
3804 TEUCHOS_TEST_FOR_EXCEPTION(
3805 newRangeMap.is_null(), std::invalid_argument,
3806 prefix <<
"The new range Map must be nonnull.");
3809 Teuchos::RCP<const export_type> newExporter = Teuchos::null;
3810 if (newRangeMap !=
rowMap_ && (!newRangeMap->isSameAs(*
rowMap_))) {
3816template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3819 const Teuchos::RCP<const export_type>& newExporter) {
3820 const char prefix[] =
"Tpetra::CrsGraph::replaceRangeMapAndExporter: ";
3821 TEUCHOS_TEST_FOR_EXCEPTION(
3822 rowMap_.is_null(), std::invalid_argument, prefix <<
"You may not call "
3823 "this method unless the graph already has a column Map.");
3824 TEUCHOS_TEST_FOR_EXCEPTION(
3825 newRangeMap.is_null(), std::invalid_argument,
3826 prefix <<
"The new domain Map must be nonnull.");
3829 if (newExporter.is_null()) {
3834 const bool rowSameAsRange =
rowMap_->isSameAs(*newRangeMap);
3835 TEUCHOS_TEST_FOR_EXCEPTION(!rowSameAsRange, std::invalid_argument,
3836 "If the new Export is null, "
3837 "then the new range Map must be the same as the current row Map.");
3839 const bool newRangeSameAsTgt =
3840 newRangeMap->isSameAs(*(newExporter->getTargetMap()));
3841 const bool rowSameAsSrc =
3842 rowMap_->isSameAs(*(newExporter->getSourceMap()));
3843 TEUCHOS_TEST_FOR_EXCEPTION(!rowSameAsSrc || !newRangeSameAsTgt, std::invalid_argument,
3845 "new Export is nonnull, then the current row Map must be the same "
3846 "as the new Export's source Map, and the new range Map must be the "
3847 "same as the new Export's target Map.");
3852 exporter_ = Teuchos::rcp_const_cast<export_type>(newExporter);
3855template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3861 this->getRowPtrsPackedDevice());
3864template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3868 return local_graph_host_type(
3869 lclIndsPacked_wdv.getHostView(Access::ReadWrite),
3870 this->getRowPtrsPackedHost());
3873template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3876 using Teuchos::ArrayView;
3877 using Teuchos::outArg;
3878 using Teuchos::reduceAll;
3882 ProfilingRegion regionCGC(
"Tpetra::CrsGraph::computeGlobalConstants");
3890 const Teuchos::Comm<int>& comm = *(this->
getComm());
3906 reduceAll<int, GST>(comm, Teuchos::REDUCE_SUM, 1, &lcl, &gbl);
3910 reduceAll<int, GST>(comm, Teuchos::REDUCE_MAX, lclMaxNumRowEnt,
3916template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3921 ProfilingRegion regionCLC(
"Tpetra::CrsGraph::computeLocalConstants");
3928 Teuchos::OrdinalTraits<size_t>::invalid();
3933 const LO lclNumRows = ptr.extent(0) == 0 ?
static_cast<LO
>(0) : (
static_cast<LO
>(ptr.extent(0)) -
static_cast<LO
>(1));
3935 const LO lclMaxNumRowEnt =
3936 ::Tpetra::Details::maxDifference(
"Tpetra::CrsGraph: nodeMaxNumRowEntries",
3942template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3943std::pair<size_t, std::string>
3948 using Teuchos::arcp;
3949 using Teuchos::Array;
3950 typedef LocalOrdinal LO;
3951 typedef GlobalOrdinal GO;
3953 typedef typename local_graph_device_type::row_map_type::non_const_value_type offset_type;
3954 typedef typename num_row_entries_type::non_const_value_type num_ent_type;
3955 const char tfecfFuncName[] =
"makeIndicesLocal: ";
3956 ProfilingRegion regionMakeIndicesLocal(
"Tpetra::CrsGraph::makeIndicesLocal");
3958 std::unique_ptr<std::string> prefix;
3960 prefix = this->createPrefix(
"CrsGraph",
"makeIndicesLocal");
3961 std::ostringstream os;
3963 std::cerr << os.str();
3968 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->
hasColMap(), std::logic_error,
3969 "The graph does not have a "
3970 "column Map yet. This method should never be called in that case. "
3971 "Please report this bug to the Tpetra developers.");
3972 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->
getColMap().is_null(), std::logic_error,
3974 "that it has a column Map, because hasColMap() returns true. However, "
3975 "the result of getColMap() is null. This should never happen. Please "
3976 "report this bug to the Tpetra developers.");
3981 size_t lclNumErrs = 0;
3982 std::ostringstream errStrm;
3989 typename num_row_entries_type::const_type h_numRowEnt =
3995 if (rowPtrsUnpacked_host.extent(0) == 0) {
3996 errStrm <<
"Unpacked row pointers (rowPtrsUnpacked_dev_) has length 0. This should never "
3997 "happen here. Please report this bug to the Tpetra developers."
4000 return std::make_pair(Tpetra::Details::OrdinalTraits<size_t>::invalid(),
4003 const auto numEnt = rowPtrsUnpacked_host(lclNumRows);
4012 using Kokkos::view_alloc;
4013 using Kokkos::WithoutInitializing;
4023 const std::string label(
"Tpetra::CrsGraph::lclInd");
4025 std::ostringstream os;
4026 os << *prefix <<
"(Re)allocate lclInd_wdv: old="
4028 std::cerr << os.str();
4031 local_inds_dualv_type lclInds_dualv =
4032 local_inds_dualv_type(view_alloc(label, WithoutInitializing),
4045 std::ostringstream os;
4046 os << *prefix <<
"Allocate device mirror k_numRowEnt: "
4047 << h_numRowEnt.extent(0) << endl;
4048 std::cerr << os.str();
4051 Kokkos::create_mirror_view_and_copy(
device_type(), h_numRowEnt);
4055 convertColumnIndicesFromGlobalToLocal<LO, GO, DT, offset_type, num_ent_type>(
4058 this->getRowPtrsUnpackedDevice(),
4061 if (lclNumErrs != 0) {
4062 const int myRank = [
this]() {
4063 auto map = this->
getMap();
4064 if (map.is_null()) {
4067 auto comm = map->getComm();
4068 return comm.is_null() ? 0 : comm->getRank();
4071 const bool pluralNumErrs = (lclNumErrs !=
static_cast<size_t>(1));
4072 errStrm <<
"(Process " << myRank <<
") When converting column "
4073 "indices from global to local, we encountered "
4075 <<
" ind" << (pluralNumErrs ?
"ices" :
"ex")
4076 <<
" that do" << (pluralNumErrs ?
"es" :
"")
4077 <<
" not live in the column Map on this process." << endl;
4084 std::ostringstream os;
4085 os << *prefix <<
"Free gblInds_wdv: "
4087 std::cerr << os.str();
4092 this->indicesAreLocal_ =
true;
4093 this->indicesAreGlobal_ =
false;
4096 return std::make_pair(lclNumErrs, errStrm.str());
4099template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4101 makeColMap(Teuchos::Array<int>& remotePIDs) {
4104 const char tfecfFuncName[] =
"makeColMap";
4106 ProfilingRegion regionSortAndMerge(
"Tpetra::CrsGraph::makeColMap");
4107 std::unique_ptr<std::string> prefix;
4109 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4110 std::ostringstream os;
4111 os << *prefix <<
"Start" << endl;
4112 std::cerr << os.str();
4120 Teuchos::RCP<const map_type> colMap = this->
colMap_;
4121 const bool sortEachProcsGids =
4132 using Teuchos::outArg;
4133 using Teuchos::REDUCE_MIN;
4134 using Teuchos::reduceAll;
4136 std::ostringstream errStrm;
4137 const int lclErrCode =
4141 if (!comm.is_null()) {
4142 const int lclSuccess = (lclErrCode == 0) ? 1 : 0;
4144 reduceAll<int, int>(*comm, REDUCE_MIN, lclSuccess,
4145 outArg(gblSuccess));
4146 if (gblSuccess != 1) {
4147 std::ostringstream os;
4149 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error,
4150 ": An error happened on at "
4151 "least one process in the CrsGraph's communicator. "
4152 "Here are all processes' error messages:"
4168 std::ostringstream os;
4169 os << *prefix <<
"Done" << endl;
4170 std::cerr << os.str();
4174template <
class execution_space,
class LO,
class rowptr_type,
class colinds_type,
class numRowEntries_type>
4175void prepareSortMergeUnpackedGraph(rowptr_type rowptr, colinds_type colinds, numRowEntries_type numRowEntries) {
4176 using ATS = KokkosKernels::ArithTraits<LO>;
4177 const auto unused = ATS::max();
4179 auto numRows = rowptr.extent(0) - 1;
4182 Kokkos::parallel_for(
4183 "flag_unused_entries", Kokkos::RangePolicy<execution_space, LO>(0, numRows), KOKKOS_LAMBDA(
const LO rlid) {
4184 for (
size_t jj = rowptr(rlid) + numRowEntries(rlid); jj < rowptr(rlid + 1); ++jj) {
4185 colinds(jj) = unused;
4190template <
class execution_space,
class LO,
class rowptr_type,
class colinds_type,
class numRowEntries_type>
4191void mergeUnpackedGraph(rowptr_type rowptr, colinds_type colinds, numRowEntries_type numRowEntries) {
4195 auto numRows = rowptr.extent(0) - 1;
4201 Kokkos::parallel_for(
4202 "merge_entries", Kokkos::RangePolicy<execution_space>(0, numRows), KOKKOS_LAMBDA(
const LO rlid) {
4203 auto rowNNZ = numRowEntries(rlid);
4207 auto rowBegin = rowptr(rlid);
4208 auto pos = rowBegin;
4209 for (
size_t offset = rowBegin + 1; offset < rowBegin + rowNNZ; ++offset) {
4210 if ((colinds(offset) != colinds(pos))) {
4211 colinds(++pos) = colinds(offset);
4214 numRowEntries(rlid) = pos + 1 - rowBegin;
4218template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4222 const char tfecfFuncName[] =
"sortAndMergeAllIndices";
4225 std::unique_ptr<std::string> prefix;
4227 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
4228 std::ostringstream os;
4229 os << *prefix <<
"Start: "
4230 <<
"sorted=" << (sorted ?
"true" :
"false")
4231 <<
", merged=" << (merged ?
"true" :
"false") << endl;
4232 std::cerr << os.str();
4234 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isGloballyIndexed(), std::logic_error,
4235 "This method may only be called after makeIndicesLocal.");
4236 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!merged && this->isStorageOptimized(), std::logic_error,
4237 "The graph is already storage optimized, so we shouldn't be "
4238 "merging any indices. "
4239 "Please report this bug to the Tpetra developers.");
4241 if (!sorted || !merged) {
4242 if (storageStatus_ == Details::STORAGE_1D_UNPACKED) {
4245 auto rowptr = rowPtrsUnpacked_dev_;
4246 auto colinds = lclIndsUnpacked_wdv.getDeviceView(Access::ReadWrite);
4249 auto k_numRowEntries_d = Kokkos::create_mirror_view_and_copy(
execution_space(), k_numRowEntries_);
4252 prepareSortMergeUnpackedGraph<execution_space, LocalOrdinal>(rowptr, colinds, k_numRowEntries_d);
4255 KokkosSparse::sort_crs_graph(rowptr, colinds);
4256 this->indicesAreSorted_ =
true;
4259 mergeUnpackedGraph<execution_space, LocalOrdinal>(rowptr, colinds, k_numRowEntries_d);
4260 Kokkos::deep_copy(k_numRowEntries_, k_numRowEntries_d);
4261 this->noRedundancies_ =
true;
4264 auto rowptr = rowPtrsPacked_dev_;
4265 auto colinds = lclIndsPacked_wdv.getDeviceView(Access::ReadWrite);
4266 if (!sorted && merged) {
4267 KokkosSparse::sort_crs_graph(rowptr, colinds);
4268 this->indicesAreSorted_ =
true;
4270 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
4271 "We should never get here."
4272 "Please report this bug to the Tpetra developers.");
4278 std::ostringstream os;
4279 os << *prefix <<
"Done" << endl;
4280 std::cerr << os.str();
4284template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4287 const bool useRemotePIDs) {
4288 using Teuchos::ParameterList;
4292 const char tfecfFuncName[] =
"makeImportExport: ";
4293 ProfilingRegion regionMIE(
"Tpetra::CrsGraph::makeImportExport");
4295 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->
hasColMap(), std::logic_error,
4296 "This method may not be called unless the graph has a column Map.");
4297 RCP<ParameterList> params = this->getNonconstParameterList();
4309 if (params.is_null() || !params->isSublist(
"Import")) {
4310 if (useRemotePIDs) {
4316 RCP<ParameterList> importSublist = sublist(params,
"Import",
true);
4317 if (useRemotePIDs) {
4318 RCP<import_type> newImp =
4334 if (params.is_null() || !params->isSublist(
"Export")) {
4337 RCP<ParameterList> exportSublist = sublist(params,
"Export",
true);
4344template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4348 std::ostringstream oss;
4351 oss <<
"{status = fill complete"
4357 oss <<
"{status = fill not complete"
4364template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4366 describe(Teuchos::FancyOStream& out,
4367 const Teuchos::EVerbosityLevel verbLevel)
const {
4370 using Teuchos::ArrayView;
4371 using Teuchos::Comm;
4373 using Teuchos::VERB_DEFAULT;
4374 using Teuchos::VERB_EXTREME;
4375 using Teuchos::VERB_HIGH;
4376 using Teuchos::VERB_LOW;
4377 using Teuchos::VERB_MEDIUM;
4378 using Teuchos::VERB_NONE;
4380 Teuchos::EVerbosityLevel vl = verbLevel;
4381 if (vl == VERB_DEFAULT) vl = VERB_LOW;
4382 RCP<const Comm<int>> comm = this->
getComm();
4383 const int myImageID = comm->getRank(),
4384 numImages = comm->getSize();
4389 width = std::max<size_t>(width,
static_cast<size_t>(11)) + 2;
4390 Teuchos::OSTab tab(out);
4398 if (vl != VERB_NONE) {
4399 if (myImageID == 0) out << this->
description() << std::endl;
4405 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4406 if (myImageID == 0) out <<
"\nRow map: " << std::endl;
4408 if (
colMap_ != Teuchos::null) {
4409 if (myImageID == 0) out <<
"\nColumn map: " << std::endl;
4413 if (myImageID == 0) out <<
"\nDomain map: " << std::endl;
4417 if (myImageID == 0) out <<
"\nRange map: " << std::endl;
4422 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
4423 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4424 if (myImageID == imageCtr) {
4425 out <<
"Node ID = " << imageCtr << std::endl
4428 if (!indicesAreAllocated()) {
4429 out <<
"Indices are not allocated." << std::endl;
4438 if (vl == VERB_HIGH || vl == VERB_EXTREME) {
4439 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
4440 if (myImageID == imageCtr) {
4441 out << std::setw(width) <<
"Node ID"
4442 << std::setw(width) <<
"Global Row"
4443 << std::setw(width) <<
"Num Entries";
4444 if (vl == VERB_EXTREME) {
4448 const LocalOrdinal lclNumRows =
4450 for (LocalOrdinal r = 0; r < lclNumRows; ++r) {
4452 GlobalOrdinal gid =
rowMap_->getGlobalElement(r);
4453 out << std::setw(width) << myImageID
4454 << std::setw(width) << gid
4455 << std::setw(width) << rowinfo.numEntries;
4456 if (vl == VERB_EXTREME) {
4459 auto rowview =
gblInds_wdv.getHostView(Access::ReadOnly);
4460 for (
size_t j = 0; j < rowinfo.numEntries; ++j) {
4461 GlobalOrdinal colgid = rowview[j + rowinfo.offset1D];
4462 out << colgid <<
" ";
4466 for (
size_t j = 0; j < rowinfo.numEntries; ++j) {
4467 LocalOrdinal collid = rowview[j + rowinfo.offset1D];
4468 out <<
colMap_->getGlobalElement(collid) <<
" ";
4483template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4492template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4495 const size_t numSameIDs,
4504 using this_CRS_type = CrsGraph<LO, GO, node_type>;
4505 const char tfecfFuncName[] =
"copyAndPermute: ";
4506 const bool verbose = verbose_;
4509 const row_graph_type& srcRowGraph =
dynamic_cast<const row_graph_type&
>(source);
4510 copyAndPermuteNew(srcRowGraph, *
this, numSameIDs, permuteToLIDs, permuteFromLIDs,
INSERT);
4516 std::unique_ptr<std::string> prefix;
4518 prefix = this->createPrefix(
"CrsGraph",
"copyAndPermute");
4519 std::ostringstream os;
4520 os << *prefix << endl;
4521 std::cerr << os.str();
4524 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(permuteToLIDs.extent(0) != permuteFromLIDs.extent(0),
4525 std::runtime_error,
"permuteToLIDs.extent(0) = " << permuteToLIDs.extent(0) <<
" != permuteFromLIDs.extent(0) = " << permuteFromLIDs.extent(0) <<
".");
4529 const row_graph_type& srcRowGraph =
4530 dynamic_cast<const row_graph_type&
>(source);
4533 std::ostringstream os;
4534 os << *prefix <<
"Compute padding" << endl;
4535 std::cerr << os.str();
4537 auto padding = computeCrsPadding(srcRowGraph, numSameIDs,
4538 permuteToLIDs, permuteFromLIDs, verbose);
4539 applyCrsPadding(*padding, verbose);
4544 const this_CRS_type* srcCrsGraph =
4545 dynamic_cast<const this_CRS_type*
>(&source);
4550 nonconst_global_inds_host_view_type row_copy;
4556 if (src_filled || srcCrsGraph ==
nullptr) {
4558 std::ostringstream os;
4559 os << *prefix <<
"src_filled || srcCrsGraph == nullptr" << endl;
4560 std::cerr << os.str();
4567 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
4570 Kokkos::resize(row_copy, row_length);
4571 size_t check_row_length = 0;
4577 std::ostringstream os;
4578 os << *prefix <<
"! src_filled && srcCrsGraph != nullptr" << endl;
4579 std::cerr << os.str();
4581 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
4583 global_inds_host_view_type row;
4592 auto permuteToLIDs_h = permuteToLIDs.view_host();
4593 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
4595 if (src_filled || srcCrsGraph ==
nullptr) {
4596 for (LO i = 0; i < static_cast<LO>(permuteToLIDs_h.extent(0)); ++i) {
4600 Kokkos::resize(row_copy, row_length);
4601 size_t check_row_length = 0;
4606 for (LO i = 0; i < static_cast<LO>(permuteToLIDs_h.extent(0)); ++i) {
4609 global_inds_host_view_type row;
4616 std::ostringstream os;
4617 os << *prefix <<
"Done" << endl;
4618 std::cerr << os.str();
4622template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4625 const bool verbose) {
4630 using row_ptrs_type =
4631 typename local_graph_device_type::row_map_type::non_const_type;
4632 using range_policy =
4633 Kokkos::RangePolicy<execution_space, Kokkos::IndexType<LO>>;
4634 const char tfecfFuncName[] =
"applyCrsPadding";
4635 ProfilingRegion regionCAP(
"Tpetra::CrsGraph::applyCrsPadding");
4637 std::unique_ptr<std::string> prefix;
4639 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
4640 std::ostringstream os;
4641 os << *prefix <<
"padding: ";
4644 std::cerr << os.str();
4646 const int myRank = !verbose ? -1 : [&]() {
4647 auto map = this->getMap();
4648 if (map.is_null()) {
4651 auto comm = map->getComm();
4652 if (comm.is_null()) {
4655 return comm->getRank();
4664 if (!indicesAreAllocated()) {
4666 std::ostringstream os;
4667 os << *prefix <<
"Call allocateIndices" << endl;
4668 std::cerr << os.str();
4670 allocateIndices(GlobalIndices, verbose);
4672 TEUCHOS_ASSERT(indicesAreAllocated());
4677 auto rowPtrsUnpacked_dev = this->getRowPtrsUnpackedDevice();
4679 std::ostringstream os;
4680 os << *prefix <<
"Allocate row_ptrs_beg: "
4681 << rowPtrsUnpacked_dev.extent(0) << endl;
4682 std::cerr << os.str();
4684 using Kokkos::view_alloc;
4685 using Kokkos::WithoutInitializing;
4686 row_ptrs_type row_ptrs_beg(
4687 view_alloc(
"row_ptrs_beg", WithoutInitializing),
4688 rowPtrsUnpacked_dev.extent(0));
4690 Kokkos::deep_copy(
execution_space(), row_ptrs_beg, rowPtrsUnpacked_dev);
4692 const size_t N = row_ptrs_beg.extent(0) == 0 ? size_t(0) : size_t(row_ptrs_beg.extent(0) - 1);
4694 std::ostringstream os;
4695 os << *prefix <<
"Allocate row_ptrs_end: " << N << endl;
4696 std::cerr << os.str();
4698 row_ptrs_type row_ptrs_end(
4699 view_alloc(
"row_ptrs_end", WithoutInitializing), N);
4700 row_ptrs_type num_row_entries;
4702 const bool refill_num_row_entries = k_numRowEntries_.extent(0) != 0;
4706 if (refill_num_row_entries) {
4710 row_ptrs_type(view_alloc(
"num_row_entries", WithoutInitializing), N);
4711 Kokkos::deep_copy(num_row_entries, this->k_numRowEntries_);
4712 Kokkos::parallel_for(
4713 "Fill end row pointers", range_policy(0, N),
4714 KOKKOS_LAMBDA(
const size_t i) {
4715 row_ptrs_end(i) = row_ptrs_beg(i) + num_row_entries(i);
4721 Kokkos::parallel_for(
4722 "Fill end row pointers", range_policy(0, N),
4723 KOKKOS_LAMBDA(
const size_t i) {
4724 row_ptrs_end(i) = row_ptrs_beg(i + 1);
4728 if (isGloballyIndexed()) {
4730 padding, myRank, verbose);
4732 padCrsArrays(row_ptrs_beg, row_ptrs_end, lclIndsUnpacked_wdv,
4733 padding, myRank, verbose);
4736 if (refill_num_row_entries) {
4737 Kokkos::parallel_for(
4738 "Fill num entries", range_policy(0, N),
4739 KOKKOS_LAMBDA(
const size_t i) {
4740 num_row_entries(i) = row_ptrs_end(i) - row_ptrs_beg(i);
4742 Kokkos::deep_copy(this->k_numRowEntries_, num_row_entries);
4745 std::ostringstream os;
4746 os << *prefix <<
"Reassign k_rowPtrs_; old size: "
4747 << rowPtrsUnpacked_dev.extent(0) <<
", new size: "
4748 << row_ptrs_beg.extent(0) << endl;
4749 std::cerr << os.str();
4750 TEUCHOS_ASSERT(rowPtrsUnpacked_dev.extent(0) == row_ptrs_beg.extent(0));
4753 setRowPtrsUnpacked(row_ptrs_beg);
4756template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4758 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
4762 const size_t numSameIDs,
4767 const bool verbose)
const {
4771 std::unique_ptr<std::string> prefix;
4774 "computeCrsPadding(same & permute)");
4775 std::ostringstream os;
4776 os << *prefix <<
"{numSameIDs: " << numSameIDs
4777 <<
", numPermutes: " << permuteFromLIDs.extent(0) <<
"}"
4779 std::cerr << os.str();
4782 const int myRank = [&]() {
4783 auto comm = rowMap_.is_null() ? Teuchos::null : rowMap_->getComm();
4784 return comm.is_null() ? -1 : comm->getRank();
4786 std::unique_ptr<padding_type> padding(
4787 new padding_type(myRank, numSameIDs,
4788 permuteFromLIDs.extent(0)));
4790 computeCrsPaddingForSameIDs(*padding, source,
4791 static_cast<LO
>(numSameIDs));
4792 computeCrsPaddingForPermutedIDs(*padding, source, permuteToLIDs,
4797template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4800 padding_type& padding,
4806 using Details::Impl::getRowGraphGlobalRow;
4808 const char tfecfFuncName[] =
"computeCrsPaddingForSameIds";
4810 std::unique_ptr<std::string> prefix;
4811 const bool verbose = verbose_;
4813 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
4814 std::ostringstream os;
4815 os << *prefix <<
"numSameIDs: " << numSameIDs << endl;
4816 std::cerr << os.str();
4819 if (numSameIDs == 0) {
4823 const map_type& srcRowMap = *(source.getRowMap());
4824 const map_type& tgtRowMap = *rowMap_;
4826 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
4827 const bool src_is_unique =
4828 srcCrs ==
nullptr ? false : srcCrs->
isMerged();
4829 const bool tgt_is_unique = this->isMerged();
4831 std::vector<GO> srcGblColIndsScratch;
4832 std::vector<GO> tgtGblColIndsScratch;
4834 execute_sync_host_uvm_access();
4835 for (LO lclRowInd = 0; lclRowInd < numSameIDs; ++lclRowInd) {
4836 const GO srcGblRowInd = srcRowMap.getGlobalElement(lclRowInd);
4837 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(lclRowInd);
4838 auto srcGblColInds = getRowGraphGlobalRow(
4839 srcGblColIndsScratch, source, srcGblRowInd);
4840 auto tgtGblColInds = getRowGraphGlobalRow(
4841 tgtGblColIndsScratch, *
this, tgtGblRowInd);
4842 padding.update_same(lclRowInd, tgtGblColInds.getRawPtr(),
4843 tgtGblColInds.size(), tgt_is_unique,
4844 srcGblColInds.getRawPtr(),
4845 srcGblColInds.size(), src_is_unique);
4848 std::ostringstream os;
4849 os << *prefix <<
"Done" << endl;
4850 std::cerr << os.str();
4854template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4857 padding_type& padding,
4866 using Details::Impl::getRowGraphGlobalRow;
4868 const char tfecfFuncName[] =
"computeCrsPaddingForPermutedIds";
4870 std::unique_ptr<std::string> prefix;
4871 const bool verbose = verbose_;
4873 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
4874 std::ostringstream os;
4875 os << *prefix <<
"permuteToLIDs.extent(0): "
4876 << permuteToLIDs.extent(0)
4877 <<
", permuteFromLIDs.extent(0): "
4878 << permuteFromLIDs.extent(0) << endl;
4879 std::cerr << os.str();
4882 if (permuteToLIDs.extent(0) == 0) {
4886 const map_type& srcRowMap = *(source.getRowMap());
4887 const map_type& tgtRowMap = *rowMap_;
4889 const this_CRS_type* srcCrs =
dynamic_cast<const this_CRS_type*
>(&source);
4890 const bool src_is_unique =
4891 srcCrs ==
nullptr ? false : srcCrs->
isMerged();
4892 const bool tgt_is_unique = this->isMerged();
4894 TEUCHOS_ASSERT(!permuteToLIDs.need_sync_host());
4895 auto permuteToLIDs_h = permuteToLIDs.view_host();
4896 TEUCHOS_ASSERT(!permuteFromLIDs.need_sync_host());
4897 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
4899 std::vector<GO> srcGblColIndsScratch;
4900 std::vector<GO> tgtGblColIndsScratch;
4901 const LO numPermutes =
static_cast<LO
>(permuteToLIDs_h.extent(0));
4903 execute_sync_host_uvm_access();
4904 for (LO whichPermute = 0; whichPermute < numPermutes; ++whichPermute) {
4905 const LO srcLclRowInd = permuteFromLIDs_h[whichPermute];
4906 const GO srcGblRowInd = srcRowMap.getGlobalElement(srcLclRowInd);
4907 auto srcGblColInds = getRowGraphGlobalRow(
4908 srcGblColIndsScratch, source, srcGblRowInd);
4909 const LO tgtLclRowInd = permuteToLIDs_h[whichPermute];
4910 const GO tgtGblRowInd = tgtRowMap.getGlobalElement(tgtLclRowInd);
4911 auto tgtGblColInds = getRowGraphGlobalRow(
4912 tgtGblColIndsScratch, *
this, tgtGblRowInd);
4913 padding.update_permute(whichPermute, tgtLclRowInd,
4914 tgtGblColInds.getRawPtr(),
4915 tgtGblColInds.size(), tgt_is_unique,
4916 srcGblColInds.getRawPtr(),
4917 srcGblColInds.size(), src_is_unique);
4921 std::ostringstream os;
4922 os << *prefix <<
"Done" << endl;
4923 std::cerr << os.str();
4927template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4929 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
4934 Kokkos::DualView<packet_type*, buffer_device_type> imports,
4935 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
4936 const bool verbose)
const {
4937 using Details::Impl::getRowGraphGlobalRow;
4941 const char tfecfFuncName[] =
"computeCrsPaddingForImports";
4943 std::unique_ptr<std::string> prefix;
4945 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
4946 std::ostringstream os;
4947 os << *prefix <<
"importLIDs.extent(0): "
4948 << importLIDs.extent(0)
4949 <<
", imports.extent(0): "
4950 << imports.extent(0)
4951 <<
", numPacketsPerLID.extent(0): "
4952 << numPacketsPerLID.extent(0) << endl;
4953 std::cerr << os.str();
4956 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
4957 const int myRank = [&]() {
4958 auto comm = rowMap_.is_null() ? Teuchos::null : rowMap_->getComm();
4959 return comm.is_null() ? -1 : comm->getRank();
4961 std::unique_ptr<padding_type> padding(
4962 new padding_type(myRank, numImports));
4964 if (imports.need_sync_host()) {
4965 imports.sync_host();
4967 auto imports_h = imports.view_host();
4968 if (numPacketsPerLID.need_sync_host()) {
4969 numPacketsPerLID.sync_host();
4971 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
4973 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
4974 auto importLIDs_h = importLIDs.view_host();
4976 const map_type& tgtRowMap = *rowMap_;
4980 constexpr bool src_is_unique =
false;
4981 const bool tgt_is_unique = isMerged();
4983 std::vector<GO> tgtGblColIndsScratch;
4985 execute_sync_host_uvm_access();
4986 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
4991 const LO origSrcNumEnt =
4992 static_cast<LO
>(numPacketsPerLID_h[whichImport]);
4993 GO*
const srcGblColInds = imports_h.data() + offset;
4995 const LO tgtLclRowInd = importLIDs_h[whichImport];
4996 const GO tgtGblRowInd =
4997 tgtRowMap.getGlobalElement(tgtLclRowInd);
4998 auto tgtGblColInds = getRowGraphGlobalRow(
4999 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5000 const size_t origTgtNumEnt(tgtGblColInds.size());
5002 padding->update_import(whichImport, tgtLclRowInd,
5003 tgtGblColInds.getRawPtr(),
5004 origTgtNumEnt, tgt_is_unique,
5006 origSrcNumEnt, src_is_unique);
5007 offset += origSrcNumEnt;
5011 std::ostringstream os;
5012 os << *prefix <<
"Done" << endl;
5013 std::cerr << os.str();
5018template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5020 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::padding_type>
5025 Kokkos::DualView<char*, buffer_device_type> imports,
5026 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
5027 const bool verbose)
const {
5029 using Details::Impl::getRowGraphGlobalRow;
5033 const char tfecfFuncName[] =
"computePaddingForCrsMatrixUnpack";
5035 std::unique_ptr<std::string> prefix;
5037 prefix = this->
createPrefix(
"CrsGraph", tfecfFuncName);
5038 std::ostringstream os;
5039 os << *prefix <<
"importLIDs.extent(0): "
5040 << importLIDs.extent(0)
5041 <<
", imports.extent(0): "
5042 << imports.extent(0)
5043 <<
", numPacketsPerLID.extent(0): "
5044 << numPacketsPerLID.extent(0) << endl;
5045 std::cerr << os.str();
5047 const bool extraVerbose =
5050 const LO numImports =
static_cast<LO
>(importLIDs.extent(0));
5051 TEUCHOS_ASSERT(LO(numPacketsPerLID.extent(0)) >= numImports);
5052 const int myRank = [&]() {
5053 auto comm = rowMap_.is_null() ? Teuchos::null : rowMap_->getComm();
5054 return comm.is_null() ? -1 : comm->getRank();
5056 std::unique_ptr<padding_type> padding(
5057 new padding_type(myRank, numImports));
5059 if (imports.need_sync_host()) {
5060 imports.sync_host();
5062 auto imports_h = imports.view_host();
5063 if (numPacketsPerLID.need_sync_host()) {
5064 numPacketsPerLID.sync_host();
5066 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5068 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
5069 auto importLIDs_h = importLIDs.view_host();
5071 const map_type& tgtRowMap = *rowMap_;
5075 constexpr bool src_is_unique =
false;
5076 const bool tgt_is_unique = isMerged();
5078 std::vector<GO> srcGblColIndsScratch;
5079 std::vector<GO> tgtGblColIndsScratch;
5081 execute_sync_host_uvm_access();
5082 for (LO whichImport = 0; whichImport < numImports; ++whichImport) {
5087 const size_t numBytes = numPacketsPerLID_h[whichImport];
5089 std::ostringstream os;
5090 os << *prefix <<
"whichImport=" << whichImport
5091 <<
", numImports=" << numImports
5092 <<
", numBytes=" << numBytes << endl;
5093 std::cerr << os.str();
5095 if (numBytes == 0) {
5098 LO origSrcNumEnt = 0;
5099 const size_t numEntBeg = offset;
5100 const size_t numEntLen =
5101 PackTraits<LO>::packValueCount(origSrcNumEnt);
5102 TEUCHOS_ASSERT(numBytes >= numEntLen);
5103 TEUCHOS_ASSERT(imports_h.extent(0) >= numEntBeg + numEntLen);
5104 PackTraits<LO>::unpackValue(origSrcNumEnt,
5105 imports_h.data() + numEntBeg);
5107 std::ostringstream os;
5108 os << *prefix <<
"whichImport=" << whichImport
5109 <<
", numImports=" << numImports
5110 <<
", origSrcNumEnt=" << origSrcNumEnt << endl;
5111 std::cerr << os.str();
5113 TEUCHOS_ASSERT(origSrcNumEnt >= LO(0));
5114 TEUCHOS_ASSERT(numBytes >=
size_t(numEntLen + origSrcNumEnt *
sizeof(GO)));
5115 const size_t gidsBeg = numEntBeg + numEntLen;
5116 if (srcGblColIndsScratch.size() <
size_t(origSrcNumEnt)) {
5117 srcGblColIndsScratch.resize(origSrcNumEnt);
5119 GO*
const srcGblColInds = srcGblColIndsScratch.data();
5120 PackTraits<GO>::unpackArray(srcGblColInds,
5121 imports_h.data() + gidsBeg,
5123 const LO tgtLclRowInd = importLIDs_h[whichImport];
5124 const GO tgtGblRowInd =
5125 tgtRowMap.getGlobalElement(tgtLclRowInd);
5126 auto tgtGblColInds = getRowGraphGlobalRow(
5127 tgtGblColIndsScratch, *
this, tgtGblRowInd);
5128 const size_t origNumTgtEnt(tgtGblColInds.size());
5131 std::ostringstream os;
5132 os << *prefix <<
"whichImport=" << whichImport
5133 <<
", numImports=" << numImports
5134 <<
": Call padding->update_import" << endl;
5135 std::cerr << os.str();
5137 padding->update_import(whichImport, tgtLclRowInd,
5138 tgtGblColInds.getRawPtr(),
5139 origNumTgtEnt, tgt_is_unique,
5141 origSrcNumEnt, src_is_unique);
5146 std::ostringstream os;
5147 os << *prefix <<
"Done" << endl;
5148 std::cerr << os.str();
5153template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5158 Kokkos::DualView<packet_type*,
5160 Kokkos::DualView<
size_t*,
5163 size_t& constantNumPackets) {
5164 using Tpetra::Details::ProfilingRegion;
5169 const char tfecfFuncName[] =
"packAndPrepare: ";
5170 ProfilingRegion region_papn(
"Tpetra::CrsGraph::packAndPrepare");
5172 const bool verbose = verbose_;
5173 std::unique_ptr<std::string> prefix;
5175 prefix = this->
createPrefix(
"CrsGraph",
"packAndPrepare");
5176 std::ostringstream os;
5177 os << *prefix <<
"Start" << endl;
5178 std::cerr << os.str();
5181 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(exportLIDs.extent(0) != numPacketsPerLID.extent(0),
5183 "exportLIDs.extent(0) = " << exportLIDs.extent(0)
5184 <<
" != numPacketsPerLID.extent(0) = " << numPacketsPerLID.extent(0)
5186 const row_graph_type* srcRowGraphPtr =
5187 dynamic_cast<const row_graph_type*
>(&source);
5188 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(srcRowGraphPtr ==
nullptr, std::invalid_argument,
5189 "Source of an Export "
5190 "or Import operation to a CrsGraph must be a RowGraph with the same "
5191 "template parameters.");
5195 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isFillComplete(), std::runtime_error,
5196 "The target graph of an Import or Export must not be fill complete.");
5201 if (srcCrsGraphPtr ==
nullptr) {
5202 using Teuchos::ArrayView;
5206 std::ostringstream os;
5207 os << *prefix <<
"Source is a RowGraph but not a CrsGraph"
5209 std::cerr << os.str();
5216 TEUCHOS_ASSERT(!exportLIDs.need_sync_host());
5217 auto exportLIDs_h = exportLIDs.view_host();
5218 ArrayView<const LO> exportLIDs_av(exportLIDs_h.data(),
5219 exportLIDs_h.extent(0));
5220 Teuchos::Array<GO> exports_a;
5222 numPacketsPerLID.clear_sync_state();
5223 numPacketsPerLID.modify_host();
5224 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5225 ArrayView<size_t> numPacketsPerLID_av(numPacketsPerLID_h.data(),
5226 numPacketsPerLID_h.extent(0));
5227 srcRowGraphPtr->pack(exportLIDs_av, exports_a, numPacketsPerLID_av,
5228 constantNumPackets);
5229 const size_t newSize =
static_cast<size_t>(exports_a.size());
5230 if (
static_cast<size_t>(exports.extent(0)) != newSize) {
5231 using exports_dv_type = Kokkos::DualView<packet_type*, buffer_device_type>;
5232 exports = exports_dv_type(
"exports", newSize);
5234 Kokkos::View<
const packet_type*, Kokkos::HostSpace,
5235 Kokkos::MemoryUnmanaged>
5236 exports_a_h(exports_a.getRawPtr(), newSize);
5237 exports.clear_sync_state();
5238 exports.modify_host();
5240 Kokkos::deep_copy(exports.view_host(), exports_a_h);
5243 else if (!getColMap().is_null() &&
5244 (this->getRowPtrsPackedDevice().extent(0) != 0 ||
5245 getRowMap()->getLocalNumElements() == 0)) {
5247 std::ostringstream os;
5248 os << *prefix <<
"packCrsGraphNew path" << endl;
5249 std::cerr << os.str();
5251 using export_pids_type =
5252 Kokkos::DualView<const int*, buffer_device_type>;
5253 export_pids_type exportPIDs;
5257 packCrsGraphNew<LO, GO, NT>(*srcCrsGraphPtr, exportLIDs, exportPIDs,
5258 exports, numPacketsPerLID,
5259 constantNumPackets,
false);
5261 srcCrsGraphPtr->packFillActiveNew(exportLIDs, exports, numPacketsPerLID,
5262 constantNumPackets);
5266 std::ostringstream os;
5267 os << *prefix <<
"Done" << endl;
5268 std::cerr << os.str();
5272template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5274 pack(
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5275 Teuchos::Array<GlobalOrdinal>& exports,
5276 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5277 size_t& constantNumPackets)
const {
5280 if (!col_map.is_null() && (this->getRowPtrsPackedDevice().extent(0) != 0 ||
getRowMap()->getLocalNumElements() == 0)) {
5282 packCrsGraph<LocalOrdinal, GlobalOrdinal, Node>(*
this, exports, numPacketsPerLID,
5283 exportLIDs, constantNumPackets);
5285 this->packFillActive(exportLIDs, exports, numPacketsPerLID,
5286 constantNumPackets);
5290template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5292 packFillActive(
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5293 Teuchos::Array<GlobalOrdinal>& exports,
5294 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5295 size_t& constantNumPackets)
const {
5297 using LO = LocalOrdinal;
5298 using GO = GlobalOrdinal;
5299 using host_execution_space =
5300 typename Kokkos::View<size_t*, device_type>::
5301 host_mirror_type::execution_space;
5302 const char tfecfFuncName[] =
"packFillActive: ";
5303 const bool verbose = verbose_;
5305 const auto numExportLIDs = exportLIDs.size();
5306 std::unique_ptr<std::string> prefix;
5308 prefix = this->createPrefix(
"CrsGraph",
"allocateIndices");
5309 std::ostringstream os;
5310 os << *prefix <<
"numExportLIDs=" << numExportLIDs << endl;
5311 std::cerr << os.str();
5313 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numExportLIDs != numPacketsPerLID.size(), std::runtime_error,
5314 "exportLIDs.size() = " << numExportLIDs <<
" != numPacketsPerLID.size()"
5316 << numPacketsPerLID.size() <<
".");
5318 const map_type& rowMap = *(this->getRowMap());
5319 const map_type*
const colMapPtr = this->colMap_.getRawPtr();
5320 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isLocallyIndexed() && colMapPtr ==
nullptr, std::logic_error,
5321 "This graph claims to be locally indexed, but its column Map is nullptr. "
5322 "This should never happen. Please report this bug to the Tpetra "
5326 constantNumPackets = 0;
5330 size_t*
const numPacketsPerLID_raw = numPacketsPerLID.getRawPtr();
5331 const LO*
const exportLIDs_raw = exportLIDs.getRawPtr();
5338 Kokkos::RangePolicy<host_execution_space, LO> inputRange(0, numExportLIDs);
5339 size_t totalNumPackets = 0;
5340 size_t errCount = 0;
5343 typedef Kokkos::Device<host_execution_space, Kokkos::HostSpace>
5345 Kokkos::View<size_t, host_device_type> errCountView(&errCount);
5346 constexpr size_t ONE = 1;
5348 execute_sync_host_uvm_access();
5349 Kokkos::parallel_reduce(
5350 "Tpetra::CrsGraph::pack: totalNumPackets",
5352 [=, *
this](
const LO& i,
size_t& curTotalNumPackets) {
5353 const GO gblRow = rowMap.getGlobalElement(exportLIDs_raw[i]);
5354 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid()) {
5355 Kokkos::atomic_add(&errCountView(), ONE);
5356 numPacketsPerLID_raw[i] = 0;
5358 const size_t numEnt = this->getNumEntriesInGlobalRow(gblRow);
5359 numPacketsPerLID_raw[i] = numEnt;
5360 curTotalNumPackets += numEnt;
5366 std::ostringstream os;
5367 os << *prefix <<
"totalNumPackets=" << totalNumPackets << endl;
5368 std::cerr << os.str();
5370 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(errCount != 0, std::logic_error,
5371 "totalNumPackets count encountered "
5372 "one or more errors! errCount = "
5374 <<
", totalNumPackets = " << totalNumPackets <<
".");
5378 exports.resize(totalNumPackets);
5380 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->supportsRowViews(), std::logic_error,
5381 "this->supportsRowViews() returns false; this should never happen. "
5382 "Please report this bug to the Tpetra developers.");
5388 std::ostringstream os;
5389 os << *prefix <<
"Pack into exports" << endl;
5390 std::cerr << os.str();
5395 GO*
const exports_raw = exports.getRawPtr();
5397 Kokkos::parallel_scan(
"Tpetra::CrsGraph::pack: pack from views",
5398 inputRange, [=, &prefix, *
this](
const LO i,
size_t& exportsOffset,
const bool final) {
5399 const size_t curOffset = exportsOffset;
5400 const GO gblRow = rowMap.getGlobalElement(exportLIDs_raw[i]);
5402 this->getRowInfoFromGlobalRowIndex(gblRow);
5404 using TDO = Tpetra::Details::OrdinalTraits<size_t>;
5405 if (rowInfo.localRow == TDO::invalid()) {
5407 std::ostringstream os;
5408 os << *prefix <<
": INVALID rowInfo: i=" << i
5409 <<
", lclRow=" << exportLIDs_raw[i] << endl;
5410 std::cerr << os.str();
5412 Kokkos::atomic_add(&errCountView(), ONE);
5413 }
else if (curOffset + rowInfo.numEntries > totalNumPackets) {
5415 std::ostringstream os;
5416 os << *prefix <<
": UH OH! For i=" << i <<
", lclRow="
5417 << exportLIDs_raw[i] <<
", gblRow=" << gblRow <<
", curOffset "
5419 << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5420 <<
") > totalNumPackets (= " << totalNumPackets <<
")."
5422 std::cerr << os.str();
5424 Kokkos::atomic_add(&errCountView(), ONE);
5426 const LO numEnt =
static_cast<LO
>(rowInfo.numEntries);
5427 if (this->isLocallyIndexed()) {
5428 auto lclColInds = getLocalIndsViewHost(rowInfo);
5430 for (LO k = 0; k < numEnt; ++k) {
5431 const LO lclColInd = lclColInds(k);
5432 const GO gblColInd = colMapPtr->getGlobalElement(lclColInd);
5436 exports_raw[curOffset + k] = gblColInd;
5439 exportsOffset = curOffset + numEnt;
5440 }
else if (this->isGloballyIndexed()) {
5441 auto gblColInds = getGlobalIndsViewHost(rowInfo);
5443 for (LO k = 0; k < numEnt; ++k) {
5444 const GO gblColInd = gblColInds(k);
5448 exports_raw[curOffset + k] = gblColInd;
5451 exportsOffset = curOffset + numEnt;
5459 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(errCount != 0, std::logic_error,
5460 "Packing encountered "
5461 "one or more errors! errCount = "
5463 <<
", totalNumPackets = " << totalNumPackets <<
".");
5466 std::ostringstream os;
5467 os << *prefix <<
"Done" << endl;
5468 std::cerr << os.str();
5472template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5476 Kokkos::DualView<packet_type*,
5478 Kokkos::DualView<
size_t*,
5481 size_t& constantNumPackets)
const {
5485 using host_execution_space =
typename Kokkos::View<
size_t*,
5487 using host_device_type =
5488 Kokkos::Device<host_execution_space, Kokkos::HostSpace>;
5489 using exports_dv_type =
5490 Kokkos::DualView<packet_type*, buffer_device_type>;
5491 const char tfecfFuncName[] =
"packFillActiveNew: ";
5492 const bool verbose = verbose_;
5494 const auto numExportLIDs = exportLIDs.extent(0);
5495 std::unique_ptr<std::string> prefix;
5497 prefix = this->
createPrefix(
"CrsGraph",
"packFillActiveNew");
5498 std::ostringstream os;
5499 os << *prefix <<
"numExportLIDs: " << numExportLIDs
5500 <<
", numPacketsPerLID.extent(0): "
5501 << numPacketsPerLID.extent(0) << endl;
5502 std::cerr << os.str();
5504 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numExportLIDs != numPacketsPerLID.extent(0), std::runtime_error,
5505 "exportLIDs.extent(0) = " << numExportLIDs
5506 <<
" != numPacketsPerLID.extent(0) = "
5507 << numPacketsPerLID.extent(0) <<
".");
5508 TEUCHOS_ASSERT(!exportLIDs.need_sync_host());
5509 auto exportLIDs_h = exportLIDs.view_host();
5511 const map_type& rowMap = *(this->getRowMap());
5512 const map_type*
const colMapPtr = this->colMap_.getRawPtr();
5513 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->isLocallyIndexed() && colMapPtr ==
nullptr, std::logic_error,
5514 "This graph claims to be locally indexed, but its column Map is nullptr. "
5515 "This should never happen. Please report this bug to the Tpetra "
5519 constantNumPackets = 0;
5521 numPacketsPerLID.clear_sync_state();
5522 numPacketsPerLID.modify_host();
5523 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5530 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
5531 range_type inputRange(0, numExportLIDs);
5532 size_t totalNumPackets = 0;
5533 size_t errCount = 0;
5536 Kokkos::View<size_t, host_device_type> errCountView(&errCount);
5537 constexpr size_t ONE = 1;
5540 std::ostringstream os;
5541 os << *prefix <<
"Compute totalNumPackets" << endl;
5542 std::cerr << os.str();
5545 execute_sync_host_uvm_access();
5546 totalNumPackets = 0;
5547 for (
size_t i = 0; i < numExportLIDs; ++i) {
5548 const LO lclRow = exportLIDs_h[i];
5549 const GO gblRow = rowMap.getGlobalElement(lclRow);
5550 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid()) {
5552 std::ostringstream os;
5553 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5554 <<
" not in row Map on this process" << endl;
5555 std::cerr << os.str();
5557 Kokkos::atomic_add(&errCountView(), ONE);
5558 numPacketsPerLID_h(i) = 0;
5560 const size_t numEnt = this->getNumEntriesInGlobalRow(gblRow);
5561 numPacketsPerLID_h(i) = numEnt;
5562 totalNumPackets += numEnt;
5567 std::ostringstream os;
5568 os << *prefix <<
"totalNumPackets: " << totalNumPackets
5569 <<
", errCount: " << errCount << endl;
5570 std::cerr << os.str();
5572 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(errCount != 0, std::logic_error,
5573 "totalNumPackets count encountered "
5574 "one or more errors! totalNumPackets: "
5576 <<
", errCount: " << errCount <<
".");
5579 if (
size_t(exports.extent(0)) < totalNumPackets) {
5581 exports = exports_dv_type(
"exports", totalNumPackets);
5584 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->supportsRowViews(), std::logic_error,
5585 "this->supportsRowViews() returns false; this should never happen. "
5586 "Please report this bug to the Tpetra developers.");
5592 std::ostringstream os;
5593 os << *prefix <<
"Pack into exports buffer" << endl;
5594 std::cerr << os.str();
5597 exports.clear_sync_state();
5598 exports.modify_host();
5599 auto exports_h = exports.view_host();
5605 if (isLocallyIndexed())
5606 lclIndsUnpacked_wdv.getHostView(Access::ReadOnly);
5607 else if (isGloballyIndexed())
5608 gblInds_wdv.getHostView(Access::ReadOnly);
5611 Kokkos::parallel_scan(
"Tpetra::CrsGraph::packFillActiveNew: Pack exports",
5612 inputRange, [=, &prefix, *
this](
const LO i,
size_t& exportsOffset,
const bool final) {
5613 const size_t curOffset = exportsOffset;
5614 const LO lclRow = exportLIDs_h(i);
5615 const GO gblRow = rowMap.getGlobalElement(lclRow);
5616 if (gblRow == Details::OrdinalTraits<GO>::invalid()) {
5618 std::ostringstream os;
5619 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5620 <<
" not in row Map on this process" << endl;
5621 std::cerr << os.str();
5623 Kokkos::atomic_add(&errCountView(), ONE);
5627 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex(gblRow);
5628 if (rowInfo.localRow == Details::OrdinalTraits<size_t>::invalid()) {
5630 std::ostringstream os;
5631 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5632 <<
", gblRow=" << gblRow <<
": invalid rowInfo"
5634 std::cerr << os.str();
5636 Kokkos::atomic_add(&errCountView(), ONE);
5640 if (curOffset + rowInfo.numEntries > totalNumPackets) {
5642 std::ostringstream os;
5643 os << *prefix <<
"For i=" << i <<
", lclRow=" << lclRow
5644 <<
", gblRow=" << gblRow <<
", curOffset (= "
5645 << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5646 <<
") > totalNumPackets (= " << totalNumPackets
5648 std::cerr << os.str();
5650 Kokkos::atomic_add(&errCountView(), ONE);
5654 const LO numEnt =
static_cast<LO
>(rowInfo.numEntries);
5655 if (this->isLocallyIndexed()) {
5656 auto lclColInds = getLocalIndsViewHost(rowInfo);
5658 for (LO k = 0; k < numEnt; ++k) {
5659 const LO lclColInd = lclColInds(k);
5660 const GO gblColInd = colMapPtr->getGlobalElement(lclColInd);
5664 exports_h(curOffset + k) = gblColInd;
5667 exportsOffset = curOffset + numEnt;
5668 }
else if (this->isGloballyIndexed()) {
5669 auto gblColInds = getGlobalIndsViewHost(rowInfo);
5671 for (LO k = 0; k < numEnt; ++k) {
5672 const GO gblColInd = gblColInds(k);
5676 exports_h(curOffset + k) = gblColInd;
5679 exportsOffset = curOffset + numEnt;
5693 std::ostringstream os;
5694 os << *prefix <<
"errCount=" << errCount <<
"; Done" << endl;
5695 std::cerr << os.str();
5699template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5706 Kokkos::DualView<
size_t*,
5715 const char tfecfFuncName[] =
"unpackAndCombine";
5717 ProfilingRegion regionCGC(
"Tpetra::CrsGraph::unpackAndCombine");
5718 const bool verbose = verbose_;
5720 std::unique_ptr<std::string> prefix;
5722 prefix = this->createPrefix(
"CrsGraph", tfecfFuncName);
5723 std::ostringstream os;
5724 os << *prefix <<
"Start" << endl;
5725 std::cerr << os.str();
5728 auto padding = computeCrsPaddingForImports(
5729 importLIDs, imports, numPacketsPerLID, verbose);
5730 applyCrsPadding(*padding, verbose);
5732 std::ostringstream os;
5733 os << *prefix <<
"Done computing & applying padding" << endl;
5734 std::cerr << os.str();
5755 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(importLIDs.extent(0) != numPacketsPerLID.extent(0),
5756 std::runtime_error,
": importLIDs.extent(0) = " << importLIDs.extent(0) <<
" != numPacketsPerLID.extent(0) = " << numPacketsPerLID.extent(0) <<
".");
5757 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
isFillComplete(), std::runtime_error,
5758 ": Import or Export operations are not allowed on a target "
5759 "CrsGraph that is fillComplete.");
5761 const size_t numImportLIDs(importLIDs.extent(0));
5762 if (numPacketsPerLID.need_sync_host()) {
5763 numPacketsPerLID.sync_host();
5765 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
5766 if (imports.need_sync_host()) {
5767 imports.sync_host();
5769 auto imports_h = imports.view_host();
5770 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
5771 auto importLIDs_h = importLIDs.view_host();
5774 Teuchos::Array<LO> lclColInds;
5777 std::ostringstream os;
5778 os << *prefix <<
"Preallocate local indices scratch" << endl;
5779 std::cerr << os.str();
5781 size_t maxNumInserts = 0;
5782 for (
size_t i = 0; i < numImportLIDs; ++i) {
5783 maxNumInserts = std::max(maxNumInserts, numPacketsPerLID_h[i]);
5786 std::ostringstream os;
5787 os << *prefix <<
"Local indices scratch size: "
5788 << maxNumInserts << endl;
5789 std::cerr << os.str();
5791 lclColInds.resize(maxNumInserts);
5794 std::ostringstream os;
5797 os <<
"Graph is globally indexed";
5799 os <<
"Graph is neither locally nor globally indexed";
5802 std::cerr << os.str();
5806 TEUCHOS_ASSERT(!
rowMap_.is_null());
5810 size_t importsOffset = 0;
5811 for (
size_t i = 0; i < numImportLIDs; ++i) {
5813 std::ostringstream os;
5814 os << *prefix <<
"i=" << i <<
", numImportLIDs="
5815 << numImportLIDs << endl;
5816 std::cerr << os.str();
5820 const LO lclRow = importLIDs_h[i];
5822 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(gblRow == Teuchos::OrdinalTraits<GO>::invalid(),
5823 std::logic_error,
"importLIDs[i=" << i <<
"]=" << lclRow <<
" is not in the row Map on the calling "
5825 const LO numEnt = numPacketsPerLID_h[i];
5826 const GO*
const gblColInds = (numEnt == 0) ?
nullptr : imports_h.data() + importsOffset;
5832 for (LO j = 0; j < numEnt; j++) {
5833 lclColInds[j] =
colMap_->getLocalElement(gblColInds[j]);
5837 importsOffset += numEnt;
5839 }
catch (std::exception& e) {
5840 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
5841 "Tpetra::CrsGraph::unpackAndCombine: Insert loop threw an "
5848 std::ostringstream os;
5849 os << *prefix <<
"Done" << endl;
5850 std::cerr << os.str();
5854template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5857 using Teuchos::Comm;
5858 using Teuchos::null;
5859 using Teuchos::ParameterList;
5865 RCP<const map_type> rowMap, domainMap, rangeMap, colMap;
5866 RCP<import_type> importer;
5867 RCP<export_type> exporter;
5870 RCP<const Comm<int>> newComm =
5871 (newMap.is_null()) ? null : newMap->getComm();
5881 domainMap =
domainMap_->replaceCommWithSubset(newComm);
5892 rangeMap =
rangeMap_->replaceCommWithSubset(newComm);
5896 colMap =
colMap_->replaceCommWithSubset(newComm);
5900 if (!newComm.is_null()) {
5901 RCP<ParameterList> params = this->getNonconstParameterList();
5910 rangeMap != rowMap &&
5911 !rangeMap->isSameAs(*rowMap)) {
5912 if (params.is_null() || !params->isSublist(
"Export")) {
5913 exporter = rcp(
new export_type(rowMap, rangeMap));
5915 RCP<ParameterList> exportSublist = sublist(params,
"Export",
true);
5916 exporter = rcp(
new export_type(rowMap, rangeMap, exportSublist));
5921 domainMap != colMap &&
5922 !domainMap->isSameAs(*colMap)) {
5923 if (params.is_null() || !params->isSublist(
"Import")) {
5924 importer = rcp(
new import_type(domainMap, colMap));
5926 RCP<ParameterList> importSublist = sublist(params,
"Import",
true);
5927 importer = rcp(
new import_type(domainMap, colMap, importSublist));
5943 this->
map_ = rowMap;
5949template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5951 getLocalDiagOffsets(
const Kokkos::View<size_t*, device_type, Kokkos::MemoryUnmanaged>& offsets)
const {
5953 using LO = LocalOrdinal;
5954 using GO = GlobalOrdinal;
5955 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
5956 const bool verbose = verbose_;
5958 std::unique_ptr<std::string> prefix;
5960 prefix = this->createPrefix(
"CrsGraph",
"getLocalDiagOffsets");
5961 std::ostringstream os;
5962 os << *prefix <<
"offsets.extent(0)=" << offsets.extent(0)
5964 std::cerr << os.str();
5967 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
hasColMap(), std::runtime_error,
"The graph must have a column Map.");
5969 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
static_cast<LO
>(offsets.extent(0)) < lclNumRows,
5970 std::invalid_argument,
"offsets.extent(0) = " << offsets.extent(0) <<
" < getLocalNumRows() = " << lclNumRows <<
".");
5979 bool allRowMapDiagEntriesInColMap =
true;
5980 bool allDiagEntriesFound =
true;
5981 bool allOffsetsCorrect =
true;
5982 bool noOtherWeirdness =
true;
5983 using wrong_offsets_type = std::vector<std::pair<LO, size_t>>;
5984 wrong_offsets_type wrongOffsets(0);
5995 const bool sorted = this->
isSorted();
5998 ::Tpetra::Details::getGraphDiagOffsets(offsets, lclRowMap, lclColMap,
6000 lclGraph.entries, sorted);
6005 auto offsets_h = Kokkos::create_mirror_view(offsets);
6007 for (LO lclRowInd = 0; lclRowInd < lclNumRows; ++lclRowInd) {
6011 const GO gblRowInd = lclRowMap.getGlobalElement(lclRowInd);
6012 const GO gblColInd = gblRowInd;
6013 const LO lclColInd = lclColMap.getLocalElement(gblColInd);
6015 if (lclColInd == Tpetra::Details::OrdinalTraits<LO>::invalid()) {
6016 allRowMapDiagEntriesInColMap =
false;
6017 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid();
6020 if (
static_cast<LO
>(rowInfo.localRow) == lclRowInd &&
6021 rowInfo.numEntries > 0) {
6023 const size_t hint = 0;
6024 const size_t offset =
6025 KokkosSparse::findRelOffset(colInds, rowInfo.numEntries,
6026 lclColInd, hint, sorted);
6027 offsets_h(lclRowInd) = offset;
6034 typename local_inds_dualv_type::t_host::const_type lclColInds;
6038 noOtherWeirdness =
false;
6041 if (noOtherWeirdness) {
6042 const size_t numEnt = lclColInds.extent(0);
6043 if (offset >= numEnt) {
6046 allOffsetsCorrect =
false;
6047 wrongOffsets.push_back(std::make_pair(lclRowInd, offset));
6049 const LO actualLclColInd = lclColInds(offset);
6050 const GO actualGblColInd = lclColMap.getGlobalElement(actualLclColInd);
6051 if (actualGblColInd != gblColInd) {
6052 allOffsetsCorrect =
false;
6053 wrongOffsets.push_back(std::make_pair(lclRowInd, offset));
6059 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid();
6060 allDiagEntriesFound =
false;
6065 Kokkos::deep_copy(offsets, offsets_h);
6068 if (verbose && wrongOffsets.size() != 0) {
6069 std::ostringstream os;
6070 os << *prefix <<
"Wrong offsets: [";
6071 for (
size_t k = 0; k < wrongOffsets.size(); ++k) {
6072 os <<
"(" << wrongOffsets[k].first <<
","
6073 << wrongOffsets[k].second <<
")";
6074 if (k + 1 < wrongOffsets.size()) {
6079 std::cerr << os.str();
6084 using Teuchos::reduceAll;
6085 Teuchos::RCP<const Teuchos::Comm<int>> comm = this->
getComm();
6086 const bool localSuccess =
6087 allRowMapDiagEntriesInColMap && allDiagEntriesFound && allOffsetsCorrect;
6088 const int numResults = 5;
6090 lclResults[0] = allRowMapDiagEntriesInColMap ? 1 : 0;
6091 lclResults[1] = allDiagEntriesFound ? 1 : 0;
6092 lclResults[2] = allOffsetsCorrect ? 1 : 0;
6093 lclResults[3] = noOtherWeirdness ? 1 : 0;
6096 lclResults[4] = !localSuccess ? comm->getRank() : comm->getSize();
6104 reduceAll<int, int>(*comm, Teuchos::REDUCE_MIN,
6105 numResults, lclResults, gblResults);
6107 if (gblResults[0] != 1 || gblResults[1] != 1 || gblResults[2] != 1 || gblResults[3] != 1) {
6108 std::ostringstream os;
6109 os <<
"Issue(s) that we noticed (on Process " << gblResults[4] <<
", "
6110 "possibly among others): "
6112 if (gblResults[0] == 0) {
6113 os <<
" - The column Map does not contain at least one diagonal entry "
6117 if (gblResults[1] == 0) {
6118 os <<
" - On one or more processes, some row does not contain a "
6122 if (gblResults[2] == 0) {
6123 os <<
" - On one or more processes, some offsets are incorrect."
6126 if (gblResults[3] == 0) {
6127 os <<
" - One or more processes had some other error."
6130 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
6135template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6139 const char tfecfFuncName[] =
"getLocalOffRankOffsets: ";
6140 const bool verbose = verbose_;
6142 std::unique_ptr<std::string> prefix;
6144 prefix = this->createPrefix(
"CrsGraph",
"getLocalOffRankOffsets");
6145 std::ostringstream os;
6146 os << *prefix <<
"offsets.extent(0)=" << offsets.extent(0)
6148 std::cerr << os.str();
6151 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
hasColMap(), std::runtime_error,
"The graph must have a column Map.");
6156 if (haveLocalOffRankOffsets_ &&
k_offRankOffsets_.extent(0) == lclNumRows + 1) {
6160 haveLocalOffRankOffsets_ =
false;
6176 k_offRankOffsets_ = offset_device_view_type(Kokkos::ViewAllocateWithoutInitializing(
"offRankOffset"), lclNumRows + 1);
6179 lclColMap, lclDomMap,
6182 haveLocalOffRankOffsets_ =
true;
6184 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::logic_error,
"Can't get off-rank offsets for non-fill-complete graph");
6206template <
class DeviceType,
6207 const bool memSpaceIsHostSpace =
6208 std::is_same<
typename DeviceType::memory_space,
6209 Kokkos::HostSpace>::value>
6210struct HelpGetLocalDiagOffsets {};
6212template <
class DeviceType>
6213struct HelpGetLocalDiagOffsets<DeviceType, true> {
6214 typedef DeviceType device_type;
6215 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6216 Kokkos::MemoryUnmanaged>
6217 device_offsets_type;
6218 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6219 Kokkos::MemoryUnmanaged>
6222 static device_offsets_type
6223 getDeviceOffsets(
const host_offsets_type& hostOffsets) {
6230 copyBackIfNeeded(
const host_offsets_type& ,
6231 const device_offsets_type& ) {
6235template <
class DeviceType>
6236struct HelpGetLocalDiagOffsets<DeviceType, false> {
6237 typedef DeviceType device_type;
6241 typedef Kokkos::View<size_t*, device_type> device_offsets_type;
6242 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6243 Kokkos::MemoryUnmanaged>
6246 static device_offsets_type
6247 getDeviceOffsets(
const host_offsets_type& hostOffsets) {
6250 return device_offsets_type(
"offsets", hostOffsets.extent(0));
6254 copyBackIfNeeded(
const host_offsets_type& hostOffsets,
6255 const device_offsets_type& deviceOffsets) {
6257 Kokkos::deep_copy(hostOffsets, deviceOffsets);
6262template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6265 typedef LocalOrdinal LO;
6266 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6267 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!this->
hasColMap(), std::runtime_error,
6268 "The graph does not yet have a column Map.");
6270 if (
static_cast<LO
>(offsets.size()) != myNumRows) {
6274 offsets.resize(myNumRows);
6286 typedef HelpGetLocalDiagOffsets<device_type> helper_type;
6287 typedef typename helper_type::host_offsets_type host_offsets_type;
6289 host_offsets_type hostOffsets(offsets.getRawPtr(), myNumRows);
6291 auto deviceOffsets = helper_type::getDeviceOffsets(hostOffsets);
6294 helper_type::copyBackIfNeeded(hostOffsets, deviceOffsets);
6297template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6303template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6306 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& rowTransfer,
6307 const Teuchos::RCP<const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>>& domainTransfer,
6308 const Teuchos::RCP<const map_type>& domainMap,
6309 const Teuchos::RCP<const map_type>& rangeMap,
6310 const Teuchos::RCP<Teuchos::ParameterList>& params)
const {
6311 using Teuchos::ArrayRCP;
6312 using Teuchos::ArrayView;
6313 using Teuchos::Comm;
6314 using Teuchos::ParameterList;
6321#ifdef HAVE_TPETRA_MMM_TIMINGS
6323 using Teuchos::TimeMonitor;
6326 using LO = LocalOrdinal;
6327 using GO = GlobalOrdinal;
6332 const char* prefix =
"Tpetra::CrsGraph::transferAndFillComplete: ";
6334#ifdef HAVE_TPETRA_MMM_TIMINGS
6336 if (!params.is_null()) label = params->get(
"Timer Label", label);
6337 string prefix2 = string(
"Tpetra ") + label + std::string(
": CrsGraph TAFC ");
6338 RCP<TimeMonitor> MM =
6339 rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"Pack-1"))));
6349 TEUCHOS_TEST_FOR_EXCEPTION(
6350 xferAsImport ==
nullptr && xferAsExport ==
nullptr, std::invalid_argument,
6351 prefix <<
"The 'rowTransfer' input argument must be either an Import or "
6352 "an Export, and its template parameters must match the corresponding "
6353 "template parameters of the CrsGraph.");
6360 Teuchos::RCP<const import_type> xferDomainAsImport =
6361 Teuchos::rcp_dynamic_cast<const import_type>(domainTransfer);
6362 Teuchos::RCP<const export_type> xferDomainAsExport =
6363 Teuchos::rcp_dynamic_cast<const export_type>(domainTransfer);
6365 if (!domainTransfer.is_null()) {
6366 TEUCHOS_TEST_FOR_EXCEPTION(
6367 (xferDomainAsImport.is_null() && xferDomainAsExport.is_null()), std::invalid_argument,
6368 prefix <<
"The 'domainTransfer' input argument must be either an "
6369 "Import or an Export, and its template parameters must match the "
6370 "corresponding template parameters of the CrsGraph.");
6372 TEUCHOS_TEST_FOR_EXCEPTION(
6373 (xferAsImport !=
nullptr || !xferDomainAsImport.is_null()) &&
6374 ((xferAsImport !=
nullptr && xferDomainAsImport.is_null()) ||
6375 (xferAsImport ==
nullptr && !xferDomainAsImport.is_null())),
6376 std::invalid_argument,
6377 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6378 "must be of the same type (either Import or Export).");
6380 TEUCHOS_TEST_FOR_EXCEPTION(
6381 (xferAsExport !=
nullptr || !xferDomainAsExport.is_null()) &&
6382 ((xferAsExport !=
nullptr && xferDomainAsExport.is_null()) ||
6383 (xferAsExport ==
nullptr && !xferDomainAsExport.is_null())),
6384 std::invalid_argument,
6385 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6386 "must be of the same type (either Import or Export).");
6392 const bool communication_needed = rowTransfer.getSourceMap()->isDistributed();
6398 bool reverseMode =
false;
6399 bool restrictComm =
false;
6400 RCP<ParameterList> graphparams;
6401 if (!params.is_null()) {
6402 reverseMode = params->get(
"Reverse Mode", reverseMode);
6403 restrictComm = params->get(
"Restrict Communicator", restrictComm);
6404 graphparams = sublist(params,
"CrsGraph");
6409 RCP<const map_type> MyRowMap = reverseMode ? rowTransfer.getSourceMap() : rowTransfer.getTargetMap();
6410 RCP<const map_type> MyColMap;
6411 RCP<const map_type> MyDomainMap = !domainMap.is_null() ? domainMap : getDomainMap();
6412 RCP<const map_type> MyRangeMap = !rangeMap.is_null() ? rangeMap : getRangeMap();
6413 RCP<const map_type> BaseRowMap = MyRowMap;
6414 RCP<const map_type> BaseDomainMap = MyDomainMap;
6422 if (!destGraph.is_null()) {
6433 const bool NewFlag =
6434 !destGraph->isLocallyIndexed() && !destGraph->isGloballyIndexed();
6435 TEUCHOS_TEST_FOR_EXCEPTION(!NewFlag, std::invalid_argument,
6436 prefix <<
"The input argument 'destGraph' is only allowed to be nonnull, "
6437 "if its graph is empty (neither locally nor globally indexed).");
6446 TEUCHOS_TEST_FOR_EXCEPTION(
6447 !destGraph->getRowMap()->isSameAs(*MyRowMap), std::invalid_argument,
6448 prefix <<
"The (row) Map of the input argument 'destGraph' is not the "
6449 "same as the (row) Map specified by the input argument 'rowTransfer'.");
6451 TEUCHOS_TEST_FOR_EXCEPTION(
6452 !destGraph->checkSizes(*
this), std::invalid_argument,
6453 prefix <<
"You provided a nonnull destination graph, but checkSizes() "
6454 "indicates that it is not a legal legal target for redistribution from "
6455 "the source graph (*this). This may mean that they do not have the "
6456 "same dimensions.");
6470 TEUCHOS_TEST_FOR_EXCEPTION(
6471 !(reverseMode || getRowMap()->isSameAs(*rowTransfer.getSourceMap())),
6472 std::invalid_argument, prefix <<
"rowTransfer->getSourceMap() must match this->getRowMap() in forward mode.");
6474 TEUCHOS_TEST_FOR_EXCEPTION(
6475 !(!reverseMode || getRowMap()->isSameAs(*rowTransfer.getTargetMap())),
6476 std::invalid_argument, prefix <<
"rowTransfer->getTargetMap() must match this->getRowMap() in reverse mode.");
6479 TEUCHOS_TEST_FOR_EXCEPTION(
6480 !xferDomainAsImport.is_null() && !xferDomainAsImport->getTargetMap()->isSameAs(*domainMap),
6481 std::invalid_argument,
6482 prefix <<
"The target map of the 'domainTransfer' input argument must be "
6483 "the same as the rebalanced domain map 'domainMap'");
6485 TEUCHOS_TEST_FOR_EXCEPTION(
6486 !xferDomainAsExport.is_null() && !xferDomainAsExport->getSourceMap()->isSameAs(*domainMap),
6487 std::invalid_argument,
6488 prefix <<
"The source map of the 'domainTransfer' input argument must be "
6489 "the same as the rebalanced domain map 'domainMap'");
6502 const size_t NumSameIDs = rowTransfer.getNumSameIDs();
6503 ArrayView<const LO> ExportLIDs = reverseMode ? rowTransfer.getRemoteLIDs() : rowTransfer.getExportLIDs();
6504 ArrayView<const LO> RemoteLIDs = reverseMode ? rowTransfer.getExportLIDs() : rowTransfer.getRemoteLIDs();
6505 ArrayView<const LO> PermuteToLIDs = reverseMode ? rowTransfer.getPermuteFromLIDs() : rowTransfer.getPermuteToLIDs();
6506 ArrayView<const LO> PermuteFromLIDs = reverseMode ? rowTransfer.getPermuteToLIDs() : rowTransfer.getPermuteFromLIDs();
6507 Distributor& Distor = rowTransfer.getDistributor();
6510 Teuchos::Array<int> SourcePids;
6511 Teuchos::Array<int> TargetPids;
6512 int MyPID = getComm()->getRank();
6515 RCP<const map_type> ReducedRowMap, ReducedColMap,
6516 ReducedDomainMap, ReducedRangeMap;
6517 RCP<const Comm<int>> ReducedComm;
6521 if (destGraph.is_null()) {
6522 destGraph = rcp(
new this_CRS_type(MyRowMap, 0, graphparams));
6529 ReducedRowMap = MyRowMap->removeEmptyProcesses();
6530 ReducedComm = ReducedRowMap.is_null() ? Teuchos::null : ReducedRowMap->getComm();
6531 destGraph->removeEmptyProcessesInPlace(ReducedRowMap);
6533 ReducedDomainMap = MyRowMap.getRawPtr() == MyDomainMap.getRawPtr() ? ReducedRowMap : MyDomainMap->replaceCommWithSubset(ReducedComm);
6534 ReducedRangeMap = MyRowMap.getRawPtr() == MyRangeMap.getRawPtr() ? ReducedRowMap : MyRangeMap->replaceCommWithSubset(ReducedComm);
6537 MyRowMap = ReducedRowMap;
6538 MyDomainMap = ReducedDomainMap;
6539 MyRangeMap = ReducedRangeMap;
6542 if (!ReducedComm.is_null()) {
6543 MyPID = ReducedComm->getRank();
6548 ReducedComm = MyRowMap->getComm();
6554#ifdef HAVE_TPETRA_MMM_TIMINGS
6556 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"ImportSetup"))));
6559 RCP<const import_type> MyImporter = getImporter();
6562 bool bSameDomainMap = BaseDomainMap->isSameAs(*getDomainMap());
6564 if (!restrictComm && !MyImporter.is_null() && bSameDomainMap) {
6572 }
else if (restrictComm && !MyImporter.is_null() && bSameDomainMap) {
6575 ivector_type SourceDomain_pids(getDomainMap(),
true);
6576 ivector_type SourceCol_pids(getColMap());
6578 SourceDomain_pids.putScalar(MyPID);
6580 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6581 SourcePids.resize(getColMap()->getLocalNumElements());
6582 SourceCol_pids.get1dCopy(SourcePids());
6583 }
else if (MyImporter.is_null() && bSameDomainMap) {
6585 SourcePids.resize(getColMap()->getLocalNumElements());
6586 SourcePids.assign(getColMap()->getLocalNumElements(), MyPID);
6587 }
else if (!MyImporter.is_null() &&
6588 !domainTransfer.is_null()) {
6595 ivector_type TargetDomain_pids(domainMap);
6596 TargetDomain_pids.putScalar(MyPID);
6599 ivector_type SourceDomain_pids(getDomainMap());
6602 ivector_type SourceCol_pids(getColMap());
6604 if (!reverseMode && !xferDomainAsImport.is_null()) {
6605 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6606 }
else if (reverseMode && !xferDomainAsExport.is_null()) {
6607 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6608 }
else if (!reverseMode && !xferDomainAsExport.is_null()) {
6609 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6610 }
else if (reverseMode && !xferDomainAsImport.is_null()) {
6611 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6613 TEUCHOS_TEST_FOR_EXCEPTION(
6614 true, std::logic_error,
6615 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6617 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6618 SourcePids.resize(getColMap()->getLocalNumElements());
6619 SourceCol_pids.get1dCopy(SourcePids());
6620 }
else if (BaseDomainMap->isSameAs(*BaseRowMap) &&
6621 getDomainMap()->isSameAs(*getRowMap())) {
6623 ivector_type TargetRow_pids(domainMap);
6624 ivector_type SourceRow_pids(getRowMap());
6625 ivector_type SourceCol_pids(getColMap());
6627 TargetRow_pids.putScalar(MyPID);
6628 if (!reverseMode && xferAsImport !=
nullptr) {
6629 SourceRow_pids.doExport(TargetRow_pids, *xferAsImport,
INSERT);
6630 }
else if (reverseMode && xferAsExport !=
nullptr) {
6631 SourceRow_pids.doExport(TargetRow_pids, *xferAsExport,
INSERT);
6632 }
else if (!reverseMode && xferAsExport !=
nullptr) {
6633 SourceRow_pids.doImport(TargetRow_pids, *xferAsExport,
INSERT);
6634 }
else if (reverseMode && xferAsImport !=
nullptr) {
6635 SourceRow_pids.doImport(TargetRow_pids, *xferAsImport,
INSERT);
6637 TEUCHOS_TEST_FOR_EXCEPTION(
6638 true, std::logic_error,
6639 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6641 SourceCol_pids.doImport(SourceRow_pids, *MyImporter,
INSERT);
6642 SourcePids.resize(getColMap()->getLocalNumElements());
6643 SourceCol_pids.get1dCopy(SourcePids());
6645 TEUCHOS_TEST_FOR_EXCEPTION(
6646 true, std::invalid_argument,
6647 prefix <<
"This method only allows either domainMap == getDomainMap(), "
6648 "or (domainMap == rowTransfer.getTargetMap() and getDomainMap() == getRowMap()).");
6652 size_t constantNumPackets = destGraph->constantNumberOfPackets();
6653 if (constantNumPackets == 0) {
6654 destGraph->reallocArraysForNumPacketsPerLid(ExportLIDs.size(),
6661 const size_t rbufLen = RemoteLIDs.size() * constantNumPackets;
6662 destGraph->reallocImportsIfNeeded(rbufLen,
false,
nullptr);
6667 destGraph->numExportPacketsPerLID_.modify_host();
6668 Teuchos::ArrayView<size_t> numExportPacketsPerLID =
6673 numExportPacketsPerLID, ExportLIDs,
6674 SourcePids, constantNumPackets);
6678#ifdef HAVE_TPETRA_MMM_TIMINGS
6680 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"Transfer"))));
6683 if (communication_needed) {
6685 if (constantNumPackets == 0) {
6689 destGraph->numExportPacketsPerLID_.sync_host();
6690 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
6692 destGraph->numImportPacketsPerLID_.sync_host();
6693 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
6696 Distor.doReversePostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
6697 destGraph->numImportPacketsPerLID_.view_host());
6698 size_t totalImportPackets = 0;
6700 totalImportPackets += numImportPacketsPerLID[i];
6705 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
6706 destGraph->imports_.modify_host();
6707 auto hostImports = destGraph->imports_.view_host();
6710 destGraph->exports_.sync_host();
6711 auto hostExports = destGraph->exports_.view_host();
6712 Distor.doReversePostsAndWaits(hostExports,
6713 numExportPacketsPerLID,
6715 numImportPacketsPerLID);
6717 destGraph->imports_.modify_host();
6718 auto hostImports = destGraph->imports_.view_host();
6721 destGraph->exports_.sync_host();
6722 auto hostExports = destGraph->exports_.view_host();
6723 Distor.doReversePostsAndWaits(hostExports,
6728 if (constantNumPackets == 0) {
6732 destGraph->numExportPacketsPerLID_.sync_host();
6733 destGraph->numImportPacketsPerLID_.sync_host();
6734 Distor.doPostsAndWaits(destGraph->numExportPacketsPerLID_.view_host(), 1,
6735 destGraph->numImportPacketsPerLID_.view_host());
6737 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
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 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
6755 Distor.doPostsAndWaits(hostExports, numExportPacketsPerLID, hostImports, numImportPacketsPerLID);
6757 destGraph->imports_.modify_host();
6758 auto hostImports = destGraph->imports_.view_host();
6761 destGraph->exports_.sync_host();
6762 auto hostExports = destGraph->exports_.view_host();
6763 Distor.doPostsAndWaits(hostExports, constantNumPackets, hostImports);
6772#ifdef HAVE_TPETRA_MMM_TIMINGS
6774 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"Unpack-1"))));
6778 destGraph->numImportPacketsPerLID_.sync_host();
6779 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
6781 destGraph->imports_.sync_host();
6782 Teuchos::ArrayView<const packet_type> hostImports =
6786 numImportPacketsPerLID,
6787 constantNumPackets,
INSERT,
6788 NumSameIDs, PermuteToLIDs, PermuteFromLIDs);
6789 size_t N = BaseRowMap->getLocalNumElements();
6792 ArrayRCP<size_t> CSR_rowptr(N + 1);
6793 ArrayRCP<GO> CSR_colind_GID;
6794 ArrayRCP<LO> CSR_colind_LID;
6795 CSR_colind_GID.resize(mynnz);
6799 if (
typeid(LO) ==
typeid(GO)) {
6800 CSR_colind_LID = Teuchos::arcp_reinterpret_cast<LO>(CSR_colind_GID);
6802 CSR_colind_LID.resize(mynnz);
6811 numImportPacketsPerLID, constantNumPackets,
6812 INSERT, NumSameIDs, PermuteToLIDs,
6813 PermuteFromLIDs, N, mynnz, MyPID,
6814 CSR_rowptr(), CSR_colind_GID(),
6815 SourcePids(), TargetPids);
6820#ifdef HAVE_TPETRA_MMM_TIMINGS
6822 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"Unpack-2"))));
6827 Teuchos::Array<int> RemotePids;
6832 TargetPids, RemotePids,
6839 ReducedColMap = (MyRowMap.getRawPtr() == MyColMap.getRawPtr()) ? ReducedRowMap : MyColMap->replaceCommWithSubset(ReducedComm);
6840 MyColMap = ReducedColMap;
6844 destGraph->replaceColMap(MyColMap);
6851 if (ReducedComm.is_null()) {
6858 if ((!reverseMode && xferAsImport !=
nullptr) ||
6859 (reverseMode && xferAsExport !=
nullptr)) {
6862 }
else if ((!reverseMode && xferAsExport !=
nullptr) ||
6863 (reverseMode && xferAsImport !=
nullptr)) {
6866 if (CSR_rowptr[N] != mynnz) {
6867 CSR_colind_LID.resize(CSR_rowptr[N]);
6870 TEUCHOS_TEST_FOR_EXCEPTION(
6871 true, std::logic_error,
6872 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6880 destGraph->setAllIndices(CSR_rowptr, CSR_colind_LID);
6886 Teuchos::ParameterList esfc_params;
6887#ifdef HAVE_TPETRA_MMM_TIMINGS
6889 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"CreateImporter"))));
6891 RCP<import_type> MyImport = rcp(
new import_type(MyDomainMap, MyColMap, RemotePids));
6892#ifdef HAVE_TPETRA_MMM_TIMINGS
6894 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2 +
string(
"ESFC"))));
6896 esfc_params.set(
"Timer Label", prefix + std::string(
"TAFC"));
6898 if (!params.is_null())
6899 esfc_params.set(
"compute global constants", params->get(
"compute global constants",
true));
6901 destGraph->expertStaticFillComplete(MyDomainMap, MyRangeMap,
6902 MyImport, Teuchos::null, rcp(&esfc_params,
false));
6905template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6909 const Teuchos::RCP<const map_type>& domainMap,
6910 const Teuchos::RCP<const map_type>& rangeMap,
6911 const Teuchos::RCP<Teuchos::ParameterList>& params)
const {
6912 transferAndFillComplete(destGraph, importer, Teuchos::null, domainMap, rangeMap, params);
6915template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6920 const Teuchos::RCP<const map_type>& domainMap,
6921 const Teuchos::RCP<const map_type>& rangeMap,
6922 const Teuchos::RCP<Teuchos::ParameterList>& params)
const {
6923 transferAndFillComplete(destGraph, rowImporter, Teuchos::rcpFromRef(domainImporter), domainMap, rangeMap, params);
6926template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6930 const Teuchos::RCP<const map_type>& domainMap,
6931 const Teuchos::RCP<const map_type>& rangeMap,
6932 const Teuchos::RCP<Teuchos::ParameterList>& params)
const {
6933 transferAndFillComplete(destGraph, exporter, Teuchos::null, domainMap, rangeMap, params);
6936template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6941 const Teuchos::RCP<const map_type>& domainMap,
6942 const Teuchos::RCP<const map_type>& rangeMap,
6943 const Teuchos::RCP<Teuchos::ParameterList>& params)
const {
6944 transferAndFillComplete(destGraph, rowExporter, Teuchos::rcpFromRef(domainExporter), domainMap, rangeMap, params);
6947template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6949 swap(CrsGraph<LocalOrdinal, GlobalOrdinal, Node>& graph) {
6950 std::swap(graph.need_sync_host_uvm_access, this->need_sync_host_uvm_access);
6952 std::swap(graph.
rowMap_, this->rowMap_);
6953 std::swap(graph.
colMap_, this->colMap_);
6954 std::swap(graph.
rangeMap_, this->rangeMap_);
6955 std::swap(graph.
domainMap_, this->domainMap_);
6957 std::swap(graph.
importer_, this->importer_);
6958 std::swap(graph.
exporter_, this->exporter_);
6967 std::swap(graph.rowPtrsPacked_dev_, this->rowPtrsPacked_dev_);
6968 std::swap(graph.rowPtrsPacked_host_, this->rowPtrsPacked_host_);
6970 std::swap(graph.rowPtrsUnpacked_dev_, this->rowPtrsUnpacked_dev_);
6971 std::swap(graph.rowPtrsUnpacked_host_, this->rowPtrsUnpacked_host_);
6972 std::swap(graph.packedUnpackedRowPtrsMatch_, this->packedUnpackedRowPtrsMatch_);
6982 std::swap(graph.indicesAreAllocated_, this->indicesAreAllocated_);
6983 std::swap(graph.indicesAreLocal_, this->indicesAreLocal_);
6984 std::swap(graph.indicesAreGlobal_, this->indicesAreGlobal_);
6985 std::swap(graph.fillComplete_, this->fillComplete_);
6990 std::swap(graph.haveLocalOffRankOffsets_, this->haveLocalOffRankOffsets_);
6996 std::swap(graph.
nonlocals_, this->nonlocals_);
6999template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7001 isIdenticalTo(
const CrsGraph<LocalOrdinal, GlobalOrdinal, Node>& graph)
const {
7002 auto compare_nonlocals = [&](
const nonlocals_type& m1,
const nonlocals_type& m2) {
7004 output = m1.size() == m2.size() ? output :
false;
7005 for (
auto& it_m : m1) {
7006 size_t key = it_m.first;
7007 output = m2.find(key) != m2.end() ? output :
false;
7009 auto v1 = m1.find(key)->second;
7010 auto v2 = m2.find(key)->second;
7011 std::sort(v1.begin(), v1.end());
7012 std::sort(v2.begin(), v2.end());
7014 output = v1.size() == v2.size() ? output :
false;
7015 for (
size_t i = 0; output && i < v1.size(); i++) {
7016 output = v1[i] == v2[i] ? output :
false;
7025 output = this->
rowMap_->isSameAs(*(graph.
rowMap_)) ? output :
false;
7026 output = this->
colMap_->isSameAs(*(graph.
colMap_)) ? output :
false;
7039 output = this->indicesAreAllocated_ == graph.indicesAreAllocated_ ? output :
false;
7040 output = this->indicesAreLocal_ == graph.indicesAreLocal_ ? output :
false;
7041 output = this->indicesAreGlobal_ == graph.indicesAreGlobal_ ? output :
false;
7042 output = this->fillComplete_ == graph.fillComplete_ ? output :
false;
7047 output = this->haveLocalOffRankOffsets_ == graph.haveLocalOffRankOffsets_ ? output :
false;
7074 output = rowPtrsThis.extent(0) == rowPtrsGraph.extent(0) ? output :
false;
7075 for (
size_t i = 0; output && i < rowPtrsThis.extent(0); i++)
7076 output = rowPtrsThis(i) == rowPtrsGraph(i) ? output :
false;
7084 for (
size_t i = 0; output && i < indThis.extent(0); i++)
7085 output = indThis(i) == indGraph(i) ? output :
false;
7091 auto indtThis = this->
gblInds_wdv.getHostView(Access::ReadOnly);
7092 auto indtGraph = graph.
gblInds_wdv.getHostView(Access::ReadOnly);
7093 for (
size_t i = 0; output && i < indtThis.extent(0); i++)
7094 output = indtThis(i) == indtGraph(i) ? output :
false;
7113 output = thisLclGraph.row_map.extent(0) == graphLclGraph.row_map.extent(0)
7116 if (output && thisLclGraph.row_map.extent(0) > 0) {
7117 auto lclGraph_rowmap_host_this = thisLclGraph.row_map;
7118 auto lclGraph_rowmap_host_graph = graphLclGraph.row_map;
7119 for (
size_t i = 0; output && i < lclGraph_rowmap_host_this.extent(0); i++)
7120 output = lclGraph_rowmap_host_this(i) == lclGraph_rowmap_host_graph(i)
7125 output = thisLclGraph.entries.extent(0) == graphLclGraph.entries.extent(0)
7128 if (output && thisLclGraph.entries.extent(0) > 0) {
7129 auto lclGraph_entries_host_this = thisLclGraph.entries;
7130 auto lclGraph_entries_host_graph = graphLclGraph.entries;
7131 for (
size_t i = 0; output && i < lclGraph_entries_host_this.extent(0); i++)
7132 output = lclGraph_entries_host_this(i) == lclGraph_entries_host_graph(i)
7138 thisLclGraph.row_block_offsets.extent(0) ==
7139 graphLclGraph.row_block_offsets.extent(0)
7142 if (output && thisLclGraph.row_block_offsets.extent(0) > 0) {
7143 auto lclGraph_rbo_host_this = thisLclGraph.row_block_offsets;
7144 auto lclGraph_rbo_host_graph = graphLclGraph.row_block_offsets;
7145 for (
size_t i = 0; output && i < lclGraph_rbo_host_this.extent(0); i++)
7146 output = lclGraph_rbo_host_this(i) == lclGraph_rbo_host_graph(i)
7159template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7160void CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::insertGlobalIndicesDevice(
7163 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteToLIDs,
7164 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteFromLIDs,
7165 LocalOrdinal loopEnd) {
7167 using LO = LocalOrdinal;
7168 using GO = GlobalOrdinal;
7169 typedef typename crs_graph_type::global_inds_device_view_type::non_const_value_type global_inds_device_value_t;
7170 typedef typename Node::execution_space exec_space;
7171 typedef Kokkos::RangePolicy<exec_space, LO> range_type;
7173 const LocalOrdinal LINV = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
7174 const GlobalOrdinal GINV = Teuchos::OrdinalTraits<GlobalOrdinal>::invalid();
7176 using local_map_type =
typename crs_graph_type::map_type::local_map_type;
7177 local_map_type srcRowMapLocal = srcCrsGraph.
getRowMap()->getLocalMap();
7178 local_map_type srcColMapLocal = srcCrsGraph.
getColMap()->getLocalMap();
7179 local_map_type tgtRowMapLocal = tgtCrsGraph.
getRowMap()->getLocalMap();
7182 auto tgtGlobalColInds = tgtCrsGraph.
gblInds_wdv.getDeviceView(Access::ReadWrite);
7184 auto srcLocalColIndsDevice = srcCrsGraph.
lclIndsUnpacked_wdv.getDeviceView(Access::ReadOnly);
7186 typename crs_graph_type::num_row_entries_type::non_const_type h_numRowEnt = tgtCrsGraph.
k_numRowEntries_;
7188 auto k_numRowEnt = Kokkos::create_mirror_view_and_copy(
device_type(), h_numRowEnt);
7190 const bool sorted =
false;
7192 bool hasMap = permuteFromLIDs.extent(0) > 0;
7193 auto permuteToLIDs_d = permuteToLIDs.view_device();
7194 auto permuteFromLIDs_d = permuteFromLIDs.view_device();
7196#ifdef CRSGRAPH_INNER_ABORT
7197#undef CRSGRAPH_INNER_ABORT
7200#ifdef KOKKOS_ENABLE_SYCL
7201#define CRSGRAPH_INNER_ABORT(lin) \
7203 sycl::ext::oneapi::experimental::printf("ERROR: Tpetra_CrsGraph_def.hpp:%d", lin); \
7204 Kokkos::abort("error"); \
7207#define CRSGRAPH_INNER_ABORT(lin) \
7209 printf("ERROR: Tpetra_CrsGraph_def.hpp:%d", lin); \
7210 Kokkos::abort("error"); \
7214 Kokkos::parallel_for(
7215 "Tpetra_CrsGraph::copyAndPermuteNew",
7216 range_type(0, loopEnd),
7217 KOKKOS_LAMBDA(
const LO sourceLID) {
7218 auto srcLid = sourceLID;
7219 auto tgtLid = sourceLID;
7221 srcLid = permuteFromLIDs_d(srcLid);
7222 tgtLid = permuteToLIDs_d(tgtLid);
7224 auto srcGid = srcRowMapLocal.getGlobalElement(srcLid);
7225 if (srcGid == GINV) CRSGRAPH_INNER_ABORT(__LINE__);
7226 auto tgtGid = tgtRowMapLocal.getGlobalElement(tgtLid);
7227 auto tgtLocalRow = tgtRowMapLocal.getLocalElement(tgtGid);
7228 if (tgtLocalRow == LINV) CRSGRAPH_INNER_ABORT(__LINE__);
7229 if (tgtLocalRow != tgtLid) CRSGRAPH_INNER_ABORT(__LINE__);
7230 auto tgtNumEntries = k_numRowEnt(tgtLocalRow);
7233 auto start = srcLocalRowPtrsDevice(srcLid);
7234 auto end = srcLocalRowPtrsDevice(srcLid + 1);
7235 auto rowLength = (end - start);
7237 auto tstart = tgtLocalRowPtrsDevice(tgtLocalRow);
7238 auto tend = tstart + tgtNumEntries;
7239 auto tend1 = tgtLocalRowPtrsDevice(tgtLocalRow + 1);
7241 const size_t num_avail = (tend1 < tend) ?
size_t(0) : tend1 - tend;
7242 size_t num_inserted = 0;
7244 global_inds_device_value_t* tgtGlobalColIndsPtr = tgtGlobalColInds.data();
7247 for (
size_t j = 0; j < rowLength; j++) {
7248 auto ci = srcLocalColIndsDevice(start + j);
7249 GO gi = srcColMapLocal.getGlobalElement(ci);
7250 if (gi == GINV) CRSGRAPH_INNER_ABORT(__LINE__);
7251 auto numInTgtRow = (tend - tstart);
7253 const size_t offset = KokkosSparse::findRelOffset(
7254 tgtGlobalColIndsPtr + tstart, numInTgtRow, gi, hint, sorted);
7256 if (offset == numInTgtRow) {
7257 if (num_inserted >= num_avail) {
7258 Kokkos::abort(
"num_avail");
7260 tgtGlobalColIndsPtr[tstart + offset] = gi;
7266 k_numRowEnt(tgtLocalRow) += num_inserted;
7273template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7274void CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::copyAndPermuteNew(
7275 const row_graph_type& srcRowGraph,
7276 row_graph_type& tgtRowGraph,
7277 const size_t numSameIDs,
7286 const char tfecfFuncName[] =
"copyAndPermuteNew: ";
7287 const bool verbose = verbose_;
7290 std::unique_ptr<std::string> prefix;
7292 prefix = this->
createPrefix(
"CrsGraph",
"copyAndPermuteNew");
7293 std::ostringstream os;
7294 os << *prefix << endl;
7295 std::cerr << os.str();
7298 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
7299 permuteToLIDs.extent(0) != permuteFromLIDs.extent(0),
7301 "permuteToLIDs.extent(0) = " << permuteToLIDs.extent(0) <<
" != permuteFromLIDs.extent(0) = " << permuteFromLIDs.extent(0) <<
".");
7304 std::ostringstream os;
7305 os << *prefix <<
"Compute padding" << endl;
7306 std::cerr << os.str();
7311 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
7312 !srcCrsGraphPtr, std::runtime_error,
"error srcGraph type= " <<
typeid(srcRowGraph).name());
7316 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
7317 !tgtCrsGraphPtr, std::runtime_error,
"error tgtGraph type= " <<
typeid(tgtRowGraph).name());
7320 auto padding = tgtCrsGraph.computeCrsPadding(
7321 srcRowGraph, numSameIDs, permuteToLIDs, permuteFromLIDs, verbose);
7322 tgtCrsGraph.applyCrsPadding(*padding, verbose);
7324 const map_type& srcRowMap = *(srcRowGraph.getRowMap());
7325 const map_type& tgtRowMap = *(tgtRowGraph.getRowMap());
7327 nonconst_global_inds_host_view_type row_copy;
7333 LO numSameIDs_as_LID =
static_cast<LO
>(numSameIDs);
7335 if (src_filled || srcCrsGraphPtr ==
nullptr) {
7337 std::ostringstream os;
7338 os << *prefix <<
"src_filled || srcCrsGraph == nullptr" << endl;
7339 std::cerr << os.str();
7346 Kokkos::DualView<const local_ordinal_type*, buffer_device_type> noPermute;
7347 insertGlobalIndicesDevice(srcCrsGraph, tgtCrsGraph,
7348 noPermute, noPermute,
7352 std::ostringstream os;
7353 os << *prefix <<
"! src_filled && srcCrsGraph != nullptr" << endl;
7354 std::cerr << os.str();
7356 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
7357 const GO gid = srcRowMap.getGlobalElement(myid);
7358 global_inds_host_view_type row;
7359 srcCrsGraph.getGlobalRowView(gid, row);
7360 tgtCrsGraph.insertGlobalIndices(gid, row.extent(0), row.data());
7367 auto permuteToLIDs_h = permuteToLIDs.view_host();
7368 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
7369 auto permuteToLIDs_d = permuteToLIDs.view_device();
7370 auto permuteFromLIDs_d = permuteFromLIDs.view_device();
7372 if (src_filled || srcCrsGraphPtr ==
nullptr) {
7373 insertGlobalIndicesDevice(
7378 static_cast<LO
>(permuteToLIDs_h.extent(0)));
7380 for (LO i = 0; i < static_cast<LO>(permuteToLIDs_h.extent(0)); ++i) {
7381 const GO mygid = tgtRowMap.getGlobalElement(permuteToLIDs_h[i]);
7382 const GO srcgid = srcRowMap.getGlobalElement(permuteFromLIDs_h[i]);
7383 global_inds_host_view_type row;
7384 srcCrsGraph.getGlobalRowView(srcgid, row);
7385 tgtCrsGraph.insertGlobalIndices(mygid, row.extent(0), row.data());
7390 std::ostringstream os;
7391 os << *prefix <<
"Done" << endl;
7392 std::cerr << os.str();
7404#define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7406 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7407 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7408 const Import<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7409 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7410 CrsGraph<LO, GO, NODE>::node_type>& importer, \
7411 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7412 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7413 CrsGraph<LO, GO, NODE>::node_type>>& domainMap, \
7414 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7415 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7416 CrsGraph<LO, GO, NODE>::node_type>>& rangeMap, \
7417 const Teuchos::RCP<Teuchos::ParameterList>& params);
7419#define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO, GO, NODE) \
7421 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7422 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7423 const Import<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7424 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7425 CrsGraph<LO, GO, NODE>::node_type>& rowImporter, \
7426 const Import<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7427 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7428 CrsGraph<LO, GO, NODE>::node_type>& domainImporter, \
7429 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7430 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7431 CrsGraph<LO, GO, NODE>::node_type>>& domainMap, \
7432 const Teuchos::RCP<const Map<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7433 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7434 CrsGraph<LO, GO, NODE>::node_type>>& rangeMap, \
7435 const Teuchos::RCP<Teuchos::ParameterList>& params);
7437#define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7439 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7440 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7441 const Export<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7442 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7443 CrsGraph<LO, GO, NODE>::node_type>& exporter, \
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_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO, GO, NODE) \
7454 Teuchos::RCP<CrsGraph<LO, GO, NODE>> \
7455 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO, GO, NODE>>& sourceGraph, \
7456 const Export<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7457 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7458 CrsGraph<LO, GO, NODE>::node_type>& rowExporter, \
7459 const Export<CrsGraph<LO, GO, NODE>::local_ordinal_type, \
7460 CrsGraph<LO, GO, NODE>::global_ordinal_type, \
7461 CrsGraph<LO, GO, NODE>::node_type>& domainExporter, \
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_INSTANT(LO, GO, NODE) \
7471 template class CrsGraph<LO, GO, NODE>; \
7472 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7473 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO, GO, NODE) \
7474 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO, GO, NODE) \
7475 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO, GO, NODE)
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
Declare and define Tpetra::Details::copyOffsets, an implementation detail of Tpetra (in particular,...
Functions for manipulating CRS arrays.
Declaration of a function that prints strings from each process.
Declaration and definition of Tpetra::Details::getEntryOnHost.
Utility functions for packing and unpacking sparse matrix entries.
void lowCommunicationMakeColMapAndReindex(const Teuchos::ArrayView< const size_t > &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)
lowCommunicationMakeColMapAndReindex
void sortAndMergeCrsEntries(const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< Ordinal > &CRS_colind, const Teuchos::ArrayView< Scalar > &CRS_vals)
Sort and merge the entries of the (raw CSR) matrix by column index within each row.
void sortCrsEntries(const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< Ordinal > &CRS_colind, const Teuchos::ArrayView< Scalar > &CRS_vals)
Sort the entries of the (raw CSR) matrix by column index within each row.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects.
void getPids(const Tpetra::Import< LocalOrdinal, GlobalOrdinal, Node > &Importer, Teuchos::Array< int > &pids, bool use_minus_one_for_local)
Like getPidGidPairs, but just gets the PIDs, ordered by the column Map.
Stand-alone utility functions and macros.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
bool isMerged() const
Whether duplicate column indices in each row have been merged.
virtual void unpackAndCombine(const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &importLIDs, Kokkos::DualView< packet_type *, buffer_device_type > imports, Kokkos::DualView< size_t *, buffer_device_type > numPacketsPerLID, const size_t constantNumPackets, const CombineMode combineMode) override
local_inds_dualv_type::t_dev::const_type getLocalIndsViewDevice(const RowInfo &rowinfo) const
Get a const, locally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myRo...
global_size_t globalMaxNumRowEntries_
Global maximum of the number of entries in each row.
void reindexColumns(const Teuchos::RCP< const map_type > &newColMap, const Teuchos::RCP< const import_type > &newImport=Teuchos::null, const bool sortIndicesInEachRow=true)
Reindex the column indices in place, and replace the column Map. Optionally, replace the Import objec...
global_inds_dualv_type::t_host::const_type getGlobalIndsViewHost(const RowInfo &rowinfo) const
Get a const, globally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myR...
size_t getNumEntriesInLocalRow(local_ordinal_type localRow) const override
Get the number of entries in the given row (local index).
Teuchos::RCP< const map_type > getColMap() const override
Returns the Map that describes the column distribution in this graph.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Default parameter list suitable for validation.
Details::EStorageStatus storageStatus_
Status of the graph's storage, when not in a fill-complete state.
::Tpetra::Import< LocalOrdinal, GlobalOrdinal, Node > import_type
The Import specialization used by this class.
global_ordinal_type packet_type
Type of each entry of the DistObject communication buffer.
GlobalOrdinal global_ordinal_type
The type of the graph's global indices.
void insertGlobalIndicesIntoNonownedRows(const global_ordinal_type gblRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Implementation of insertGlobalIndices for nonowned rows.
Teuchos::RCP< const map_type > rangeMap_
The Map describing the range of the (matrix corresponding to the) graph.
std::pair< size_t, std::string > makeIndicesLocal(const bool verbose=false)
Convert column indices from global to local.
local_inds_device_view_type getLocalIndicesDevice() const
Get a device view of the packed column indicies.
global_size_t getGlobalNumEntries() const override
Returns the global number of entries in the graph.
bool isIdenticalTo(const CrsGraph< LocalOrdinal, GlobalOrdinal, Node > &graph) const
Create a cloned CrsGraph for a different Node type.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
Returns the communicator.
local_inds_wdv_type lclIndsUnpacked_wdv
Local ordinals of column indices for all rows Valid when isLocallyIndexed is true If OptimizedStorage...
void globalAssemble()
Communicate nonlocal contributions to other processes.
RowInfo getRowInfoFromGlobalRowIndex(const global_ordinal_type gblRow) const
Get information about the locally owned row with global index gblRow.
void getLocalDiagOffsets(const Kokkos::View< size_t *, device_type, Kokkos::MemoryUnmanaged > &offsets) const
Get offsets of the diagonal entries in the graph.
size_t findGlobalIndices(const RowInfo &rowInfo, const Teuchos::ArrayView< const global_ordinal_type > &indices, std::function< void(const size_t, const size_t, const size_t)> fun) const
Finds indices in the given row.
void fillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Tell the graph that you are done changing its structure.
global_inds_wdv_type gblInds_wdv
Global ordinals of column indices for all rows.
size_t nodeMaxNumRowEntries_
Local maximum of the number of entries in each row.
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.
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > ¶ms) override
Set the given list of parameters (must be nonnull).
void resumeFill(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Resume fill operations.
size_t insertIndices(RowInfo &rowInfo, const SLocalGlobalViews &newInds, const ELocalGlobal lg, const ELocalGlobal I)
Insert indices into the given row.
typename Node::device_type device_type
This class' Kokkos device type.
void insertGlobalIndicesFiltered(const local_ordinal_type lclRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Like insertGlobalIndices(), but with column Map filtering.
virtual void copyAndPermute(const SrcDistObject &source, const size_t numSameIDs, const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &permuteToLIDs, const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &permuteFromLIDs, const CombineMode CM) override
RowInfo getRowInfo(const local_ordinal_type myRow) const
Get information about the locally owned row with local index myRow.
global_inds_dualv_type::t_dev::const_type getGlobalIndsViewDevice(const RowInfo &rowinfo) const
Get a const, globally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myR...
typename local_graph_device_type::HostMirror local_graph_host_type
The type of the part of the sparse graph on each MPI process.
Teuchos::RCP< const map_type > colMap_
The Map describing the distribution of columns of the graph.
bool noRedundancies_
Whether the graph's indices are non-redundant (merged) in each row, on this process.
row_ptrs_host_view_type getLocalRowPtrsHost() const
Get a host view of the packed row offsets.
bool isSorted() const
Whether graph indices in all rows are known to be sorted.
typename dist_object_type::buffer_device_type buffer_device_type
Kokkos::Device specialization for communication buffers.
void setAllIndices(const typename local_graph_device_type::row_map_type &rowPointers, const typename local_graph_device_type::entries_type::non_const_type &columnIndices)
Set the graph's data directly, using 1-D storage.
void insertLocalIndices(const local_ordinal_type localRow, const Teuchos::ArrayView< const local_ordinal_type > &indices)
Insert local indices into the graph.
local_inds_host_view_type getLocalIndicesHost() const
Get a host view of the packed column indicies.
bool supportsRowViews() const override
Whether this class implements getLocalRowView() and getGlobalRowView() (it does).
size_t getNumEntriesInGlobalRow(global_ordinal_type globalRow) const override
Returns the current number of entries on this node in the specified global row.
bool isFillComplete() const override
Whether fillComplete() has been called and the graph is in compute mode.
void setDomainRangeMaps(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap)
void swap(CrsGraph< local_ordinal_type, global_ordinal_type, Node > &graph)
Swaps the data from *this with the data and maps from graph.
::Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > map_type
The Map specialization used by this class.
void getGlobalRowView(const global_ordinal_type gblRow, global_inds_host_view_type &gblColInds) const override
Get a const view of the given global row's global column indices.
const row_ptrs_host_view_type & getRowPtrsUnpackedHost() const
Get the unpacked row pointers on host. Lazily make a copy from device.
void exportAndFillComplete(Teuchos::RCP< CrsGraph< local_ordinal_type, global_ordinal_type, Node > > &destGraph, const export_type &exporter, const Teuchos::RCP< const map_type > &domainMap=Teuchos::null, const Teuchos::RCP< const map_type > &rangeMap=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null) const
Export from this to the given destination graph, and make the result fill complete.
void makeColMap(Teuchos::Array< int > &remotePIDs)
Make and set the graph's column Map.
bool haveGlobalConstants_
Whether all processes have computed global constants.
size_t getGlobalMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, over all processes in the graph's communicator.
void checkInternalState() const
Throw an exception if the internal state is not consistent.
Teuchos::RCP< const map_type > getRangeMap() const override
Returns the Map associated with the domain of this graph.
void expertStaticFillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< const import_type > &importer=Teuchos::null, const Teuchos::RCP< const export_type > &exporter=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Perform a fillComplete on a graph that already has data, via setAllIndices().
bool sortGhostsAssociatedWithEachProcessor_
Whether to require makeColMap() (and therefore fillComplete()) to order column Map GIDs associated wi...
size_t getNumAllocatedEntriesInGlobalRow(global_ordinal_type globalRow) const
Current number of allocated entries in the given row on the calling (MPI) process,...
Teuchos::RCP< const export_type > getExporter() const override
Returns the exporter associated with this graph.
void makeImportExport(Teuchos::Array< int > &remotePIDs, const bool useRemotePIDs)
Make the Import and Export objects, if needed.
global_ordinal_type getIndexBase() const override
Returns the index base for global indices for this graph.
row_ptrs_device_view_type getLocalRowPtrsDevice() const
Get a device view of the packed row offsets.
void getLocalRowCopy(local_ordinal_type gblRow, nonconst_local_inds_host_view_type &gblColInds, size_t &numColInds) const override
Get a copy of the given row, using local indices.
local_inds_dualv_type::t_host::const_type getLocalIndsViewHost(const RowInfo &rowinfo) const
Get a const, locally indexed view of the locally owned row myRow, such that rowinfo = getRowInfo(myRo...
bool isFillActive() const
Whether resumeFill() has been called and the graph is in edit mode.
Teuchos::RCP< const map_type > getRowMap() const override
Returns the Map that describes the row distribution in this graph.
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(const GlobalOrdinal gblRow, nonconst_global_inds_host_view_type &gblColInds, size_t &numColInds) const =0
Get a copy of the global column indices in a given row of the graph.
virtual size_t getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const =0
Returns the current number of entries on this node in the specified global row.
Abstract base class for objects that can be the source of an Import or Export operation.
A distributed dense vector.
Implementation details of Tpetra.
Nonmember function that computes a residual Computes R = B - A * X.
void padCrsArrays(const RowPtr &rowPtrBeg, const RowPtr &rowPtrEnd, Indices &indices_wdv, const Padding &padding, const int my_rank, const bool verbose)
Determine if the row pointers and indices arrays need to be resized to accommodate new entries....
void verbosePrintArray(std::ostream &out, const ArrayType &x, const char name[], const size_t maxNumToPrint)
Print min(x.size(), maxNumToPrint) entries of x.
void copyOffsets(const OutputViewType &dst, const InputViewType &src)
Copy row offsets (in a sparse graph or matrix) from src to dst. The offsets may have different types.
void unpackAndCombineIntoCrsArrays(const CrsGraph< LO, GO, NT > &sourceGraph, const Teuchos::ArrayView< const LO > &importLIDs, const Teuchos::ArrayView< const typename CrsGraph< LO, GO, NT >::packet_type > &imports, const Teuchos::ArrayView< const size_t > &numPacketsPerLID, const size_t constantNumPackets, const CombineMode combineMode, const size_t numSameIDs, const Teuchos::ArrayView< const LO > &permuteToLIDs, const Teuchos::ArrayView< const LO > &permuteFromLIDs, size_t TargetNumRows, size_t TargetNumNonzeros, const int MyTargetPID, const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< GO > &CRS_colind, const Teuchos::ArrayView< const int > &SourcePids, Teuchos::Array< int > &TargetPids)
unpackAndCombineIntoCrsArrays
void disableWDVTracking()
Disable WrappedDualView reference-count tracking and syncing. Call this before entering a host-parall...
void packCrsGraph(const CrsGraph< LO, GO, NT > &sourceGraph, Teuchos::Array< typename CrsGraph< LO, GO, NT >::packet_type > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &exportLIDs, size_t &constantNumPackets)
Pack specified entries of the given local sparse graph for communication.
size_t unpackAndCombineWithOwningPIDsCount(const CrsGraph< LO, GO, NT > &sourceGraph, const Teuchos::ArrayView< const LO > &importLIDs, const Teuchos::ArrayView< const typename CrsGraph< LO, GO, NT >::packet_type > &imports, const Teuchos::ArrayView< const size_t > &numPacketsPerLID, size_t constantNumPackets, CombineMode combineMode, size_t numSameIDs, const Teuchos::ArrayView< const LO > &permuteToLIDs, const Teuchos::ArrayView< const LO > &permuteFromLIDs)
Special version of Tpetra::Details::unpackCrsGraphAndCombine that also unpacks owning process ranks.
Teuchos::ArrayView< typename DualViewType::t_dev::value_type > getArrayViewFromDualView(const DualViewType &x)
Get a Teuchos::ArrayView which views the host Kokkos::View of the input 1-D Kokkos::DualView.
size_t insertCrsIndices(typename Pointers::value_type const row, Pointers const &rowPtrs, InOutIndices &curIndices, size_t &numAssigned, InIndices const &newIndices, std::function< void(const size_t, const size_t, const size_t)> cb=std::function< void(const size_t, const size_t, const size_t)>())
Insert new indices in to current list of indices.
void packCrsGraphNew(const CrsGraph< LO, GO, NT > &sourceGraph, const Kokkos::DualView< const LO *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exportLIDs, const Kokkos::DualView< const int *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exportPIDs, Kokkos::DualView< typename CrsGraph< LO, GO, NT >::packet_type *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exports, Kokkos::DualView< size_t *, typename CrsGraph< LO, GO, NT >::buffer_device_type > numPacketsPerLID, size_t &constantNumPackets, const bool pack_pids)
Pack specified entries of the given local sparse graph for communication, for "new" DistObject interf...
OffsetType convertColumnIndicesFromGlobalToLocal(const Kokkos::View< LO *, DT > &lclColInds, const Kokkos::View< const GO *, DT > &gblColInds, const Kokkos::View< const OffsetType *, DT > &ptr, const LocalMap< LO, GO, DT > &lclColMap, const Kokkos::View< const NumEntType *, DT > &numRowEnt)
Convert a CrsGraph's global column indices into local column indices.
std::unique_ptr< std::string > createPrefix(const int myRank, const char prefix[])
Create string prefix for each line of verbose output.
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const ExecutionSpace &execSpace, const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
OffsetsViewType::non_const_value_type computeOffsetsFromConstantCount(const OffsetsViewType &ptr, const CountType count)
Compute offsets from a constant count.
size_t findCrsIndices(typename Pointers::value_type const row, Pointers const &rowPtrs, const size_t curNumEntries, Indices1 const &curIndices, Indices2 const &newIndices, Callback &&cb)
Finds offsets in to current list of indices.
int makeColMap(Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &colMap, Teuchos::Array< int > &remotePIDs, const Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &domMap, const RowGraph< LO, GO, NT > &graph, const bool sortEachProcsGids=true, std::ostream *errStrm=NULL)
Make the graph's column Map.
void enableWDVTracking()
Enable WrappedDualView reference-count tracking and syncing. Call this after exiting a host-parallel ...
void packCrsGraphWithOwningPIDs(const CrsGraph< LO, GO, NT > &sourceGraph, Kokkos::DualView< typename CrsGraph< LO, GO, NT >::packet_type *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exports_dv, const Teuchos::ArrayView< size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &exportLIDs, const Teuchos::ArrayView< const int > &sourcePIDs, size_t &constantNumPackets)
Pack specified entries of the given local sparse graph for communication.
void gathervPrint(std::ostream &out, const std::string &s, const Teuchos::Comm< int > &comm)
On Process 0 in the given communicator, print strings from each process in that communicator,...
Namespace Tpetra contains the class and methods constituting the Tpetra library.
Teuchos_Ordinal Array_size_type
Size type for Teuchos Array objects.
size_t global_size_t
Global size_t object.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createOneToOne(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &M)
Nonmember constructor for a contiguous Map with user-defined weights and a user-specified,...
CombineMode
Rule for combining data in an Import or Export.
@ INSERT
Insert new values that don't currently exist.
Traits class for packing / unpacking data of type T.
Allocation information for a locally owned row in a CrsGraph or CrsMatrix.