42 #ifndef TPETRA_CRSGRAPH_DEF_HPP
43 #define TPETRA_CRSGRAPH_DEF_HPP
56 #include "Tpetra_Details_gathervPrint.hpp"
57 #include "Tpetra_Details_getGraphDiagOffsets.hpp"
58 #include "Tpetra_Details_makeColMap.hpp"
61 #include "Tpetra_Distributor.hpp"
62 #include "Teuchos_SerialDenseMatrix.hpp"
63 #include "Tpetra_Vector.hpp"
66 #include "Tpetra_Details_packCrsGraph.hpp"
67 #include "Tpetra_Details_unpackCrsGraphAndCombine.hpp"
74 #ifdef HAVE_TPETRA_DEBUG
77 #endif // HAVE_TPETRA_DEBUG
83 template<
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
84 class ConvertColumnIndicesFromGlobalToLocal {
86 ConvertColumnIndicesFromGlobalToLocal (const ::Kokkos::View<LO*, DT>& lclColInds,
87 const ::Kokkos::View<const GO*, DT>& gblColInds,
88 const ::Kokkos::View<const OffsetType*, DT>& ptr,
89 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
90 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt) :
91 lclColInds_ (lclColInds),
92 gblColInds_ (gblColInds),
94 lclColMap_ (lclColMap),
95 numRowEnt_ (numRowEnt)
99 operator () (
const LO& lclRow, OffsetType& curNumBad)
const
101 const OffsetType offset = ptr_(lclRow);
105 const LO numEnt = static_cast<LO> (numRowEnt_(lclRow));
106 for (LO j = 0; j < numEnt; ++j) {
107 const GO gid = gblColInds_(offset + j);
108 const LO lid = lclColMap_.getLocalElement (gid);
109 lclColInds_(offset + j) = lid;
110 if (lid == ::Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
117 run (const ::Kokkos::View<LO*, DT>& lclColInds,
118 const ::Kokkos::View<const GO*, DT>& gblColInds,
119 const ::Kokkos::View<const OffsetType*, DT>& ptr,
120 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
121 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt)
123 typedef ::Kokkos::RangePolicy<typename DT::execution_space, LO> range_type;
124 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> functor_type;
126 const LO lclNumRows = ptr.extent (0) == 0 ?
127 static_cast<LO> (0) : static_cast<LO> (ptr.extent (0) - 1);
128 OffsetType numBad = 0;
130 ::Kokkos::parallel_reduce (range_type (0, lclNumRows),
131 functor_type (lclColInds, gblColInds, ptr,
132 lclColMap, numRowEnt),
138 ::Kokkos::View<LO*, DT> lclColInds_;
139 ::Kokkos::View<const GO*, DT> gblColInds_;
140 ::Kokkos::View<const OffsetType*, DT> ptr_;
142 ::Kokkos::View<const NumEntType*, DT> numRowEnt_;
161 template<
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
164 const Kokkos::View<const GO*, DT>& gblColInds,
165 const Kokkos::View<const OffsetType*, DT>& ptr,
167 const Kokkos::View<const NumEntType*, DT>& numRowEnt)
169 using Impl::ConvertColumnIndicesFromGlobalToLocal;
170 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> impl_type;
171 return impl_type::run (lclColInds, gblColInds, ptr, lclColMap, numRowEnt);
174 template<
class ViewType,
class LO>
175 class MaxDifference {
177 MaxDifference (
const ViewType& ptr) : ptr_ (ptr) {}
179 KOKKOS_INLINE_FUNCTION
void init (LO& dst)
const {
183 KOKKOS_INLINE_FUNCTION
void
184 join (
volatile LO& dst,
const volatile LO& src)
const
186 dst = (src > dst) ? src : dst;
189 KOKKOS_INLINE_FUNCTION
void
190 operator () (
const LO lclRow, LO& maxNumEnt)
const
192 const LO numEnt = static_cast<LO> (ptr_(lclRow+1) - ptr_(lclRow));
193 maxNumEnt = (numEnt > maxNumEnt) ? numEnt : maxNumEnt;
196 typename ViewType::const_type ptr_;
199 template<
class ViewType,
class LO>
200 typename ViewType::non_const_value_type
201 maxDifference (
const char kernelLabel[],
205 if (lclNumRows == 0) {
208 return static_cast<LO> (0);
211 using execution_space =
typename ViewType::execution_space;
212 using range_type = Kokkos::RangePolicy<execution_space, LO>;
214 Kokkos::parallel_reduce (kernelLabel,
215 range_type (0, lclNumRows),
216 MaxDifference<ViewType, LO> (ptr),
226 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
228 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
229 size_t maxNumEntriesPerRow,
231 const Teuchos::RCP<Teuchos::ParameterList>& params) :
234 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
235 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
236 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
237 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
238 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
240 , numAllocForAllRows_ (maxNumEntriesPerRow)
244 , indicesAreAllocated_ (false)
245 , indicesAreLocal_ (false)
246 , indicesAreGlobal_ (false)
247 , fillComplete_ (false)
248 , lowerTriangular_ (false)
249 , upperTriangular_ (false)
250 , indicesAreSorted_ (true)
251 , noRedundancies_ (true)
252 , haveLocalConstants_ (false)
253 , haveGlobalConstants_ (false)
254 , sortGhostsAssociatedWithEachProcessor_ (true)
256 const char tfecfFuncName[] =
"CrsGraph(rowMap,maxNumEntriesPerRow,"
259 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
260 (maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid (),
261 std::invalid_argument,
"The allocation hint maxNumEntriesPerRow must be "
262 "a valid size_t value, which in this case means it must not be "
263 "Teuchos::OrdinalTraits<size_t>::invalid().");
265 checkInternalState ();
268 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
270 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
271 const Teuchos::RCP<const map_type>& colMap,
272 const size_t maxNumEntriesPerRow,
274 const Teuchos::RCP<Teuchos::ParameterList>& params) :
278 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
279 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
280 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
281 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
282 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
284 , numAllocForAllRows_ (maxNumEntriesPerRow)
288 , indicesAreAllocated_ (false)
289 , indicesAreLocal_ (false)
290 , indicesAreGlobal_ (false)
291 , fillComplete_ (false)
292 , lowerTriangular_ (false)
293 , upperTriangular_ (false)
294 , indicesAreSorted_ (true)
295 , noRedundancies_ (true)
296 , haveLocalConstants_ (false)
297 , haveGlobalConstants_ (false)
298 , sortGhostsAssociatedWithEachProcessor_ (true)
300 const char tfecfFuncName[] =
"CrsGraph(rowMap,colMap,maxNumEntriesPerRow,"
303 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
304 maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid (),
305 std::invalid_argument,
"The allocation hint maxNumEntriesPerRow must be "
306 "a valid size_t value, which in this case means it must not be "
307 "Teuchos::OrdinalTraits<size_t>::invalid().");
309 checkInternalState ();
312 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
314 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
315 const Teuchos::ArrayRCP<const size_t>& numEntPerRow,
317 const Teuchos::RCP<Teuchos::ParameterList>& params) :
320 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
321 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
322 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
323 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
324 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
326 , numAllocForAllRows_ (0)
330 , indicesAreAllocated_ (false)
331 , indicesAreLocal_ (false)
332 , indicesAreGlobal_ (false)
333 , fillComplete_ (false)
334 , lowerTriangular_ (false)
335 , upperTriangular_ (false)
336 , indicesAreSorted_ (true)
337 , noRedundancies_ (true)
338 , haveLocalConstants_ (false)
339 , haveGlobalConstants_ (false)
340 , sortGhostsAssociatedWithEachProcessor_ (true)
342 const char tfecfFuncName[] =
"CrsGraph(rowMap,numEntPerRow,pftype,params): ";
345 const size_t lclNumRows = rowMap.is_null () ?
346 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
347 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
348 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
349 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
350 <<
" != the local number of rows " << lclNumRows <<
" as specified by "
351 "the input row Map.");
355 for (
size_t r = 0; r < lclNumRows; ++r) {
356 const size_t curRowCount = numEntPerRow[r];
357 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
358 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
359 std::invalid_argument,
"numEntPerRow(" << r <<
") "
360 "specifies an invalid number of entries "
361 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
368 typedef decltype (k_numAllocPerRow_) out_view_type;
369 typedef typename out_view_type::non_const_type nc_view_type;
370 typedef Kokkos::View<
const size_t*,
371 typename nc_view_type::array_layout,
373 Kokkos::MemoryUnmanaged> in_view_type;
374 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
375 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
378 k_numAllocPerRow_ = numAllocPerRowOut;
381 checkInternalState ();
384 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
386 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
387 const Kokkos::DualView<const size_t*, execution_space>& numEntPerRow,
389 const Teuchos::RCP<Teuchos::ParameterList>& params) :
392 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
393 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
394 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
395 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
396 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
398 , k_numAllocPerRow_ (numEntPerRow.h_view)
399 , numAllocForAllRows_ (0)
403 , indicesAreAllocated_ (false)
404 , indicesAreLocal_ (false)
405 , indicesAreGlobal_ (false)
406 , fillComplete_ (false)
407 , lowerTriangular_ (false)
408 , upperTriangular_ (false)
409 , indicesAreSorted_ (true)
410 , noRedundancies_ (true)
411 , haveLocalConstants_ (false)
412 , haveGlobalConstants_ (false)
413 , sortGhostsAssociatedWithEachProcessor_ (true)
415 const char tfecfFuncName[] =
"CrsGraph(rowMap,numEntPerRow,pftype,params): ";
418 const size_t lclNumRows = rowMap.is_null () ?
419 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
420 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
421 static_cast<size_t> (numEntPerRow.extent (0)) != lclNumRows,
422 std::invalid_argument,
"numEntPerRow has length " <<
423 numEntPerRow.extent (0) <<
" != the local number of rows " <<
424 lclNumRows <<
" as specified by " "the input row Map.");
428 for (
size_t r = 0; r < lclNumRows; ++r) {
429 const size_t curRowCount = numEntPerRow.h_view(r);
430 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
431 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
432 std::invalid_argument,
"numEntPerRow(" << r <<
") "
433 "specifies an invalid number of entries "
434 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
439 checkInternalState ();
443 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
445 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
446 const Teuchos::RCP<const map_type>& colMap,
447 const Kokkos::DualView<const size_t*, execution_space>& numEntPerRow,
449 const Teuchos::RCP<Teuchos::ParameterList>& params) :
453 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
454 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
455 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
456 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
457 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
459 , k_numAllocPerRow_ (numEntPerRow.h_view)
460 , numAllocForAllRows_ (0)
464 , indicesAreAllocated_ (false)
465 , indicesAreLocal_ (false)
466 , indicesAreGlobal_ (false)
467 , fillComplete_ (false)
468 , lowerTriangular_ (false)
469 , upperTriangular_ (false)
470 , indicesAreSorted_ (true)
471 , noRedundancies_ (true)
472 , haveLocalConstants_ (false)
473 , haveGlobalConstants_ (false)
474 , sortGhostsAssociatedWithEachProcessor_ (true)
476 const char tfecfFuncName[] =
"CrsGraph(rowMap,colMap,numEntPerRow,pftype,params): ";
479 const size_t lclNumRows = rowMap.is_null () ?
480 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
481 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
482 static_cast<size_t> (numEntPerRow.extent (0)) != lclNumRows,
483 std::invalid_argument,
"numEntPerRow has length " <<
484 numEntPerRow.extent (0) <<
" != the local number of rows " <<
485 lclNumRows <<
" as specified by " "the input row Map.");
489 for (
size_t r = 0; r < lclNumRows; ++r) {
490 const size_t curRowCount = numEntPerRow.h_view(r);
491 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
492 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
493 std::invalid_argument,
"numEntPerRow(" << r <<
") "
494 "specifies an invalid number of entries "
495 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
500 checkInternalState ();
504 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
506 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
507 const Teuchos::RCP<const map_type>& colMap,
508 const Teuchos::ArrayRCP<const size_t>& numEntPerRow,
510 const Teuchos::RCP<Teuchos::ParameterList>& params) :
514 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
515 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
516 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
517 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
518 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
520 , numAllocForAllRows_ (0)
524 , indicesAreAllocated_ (false)
525 , indicesAreLocal_ (false)
526 , indicesAreGlobal_ (false)
527 , fillComplete_ (false)
528 , lowerTriangular_ (false)
529 , upperTriangular_ (false)
530 , indicesAreSorted_ (true)
531 , noRedundancies_ (true)
532 , haveLocalConstants_ (false)
533 , haveGlobalConstants_ (false)
534 , sortGhostsAssociatedWithEachProcessor_ (true)
536 const char tfecfFuncName[] =
"CrsGraph(rowMap,colMap,numEntPerRow,pftype,"
540 const size_t lclNumRows = rowMap.is_null () ?
541 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
542 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
543 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
544 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
545 <<
" != the local number of rows " << lclNumRows <<
" as specified by "
546 "the input row Map.");
550 for (
size_t r = 0; r < lclNumRows; ++r) {
551 const size_t curRowCount = numEntPerRow[r];
552 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
553 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
554 std::invalid_argument,
"numEntPerRow(" << r <<
") "
555 "specifies an invalid number of entries "
556 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
563 typedef decltype (k_numAllocPerRow_) out_view_type;
564 typedef typename out_view_type::non_const_type nc_view_type;
565 typedef Kokkos::View<
const size_t*,
566 typename nc_view_type::array_layout,
568 Kokkos::MemoryUnmanaged> in_view_type;
569 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
570 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
573 k_numAllocPerRow_ = numAllocPerRowOut;
576 checkInternalState ();
580 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
582 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
583 const Teuchos::RCP<const map_type>& colMap,
584 const typename local_graph_type::row_map_type& rowPointers,
585 const typename local_graph_type::entries_type::non_const_type& columnIndices,
586 const Teuchos::RCP<Teuchos::ParameterList>& params) :
590 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
591 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
592 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
593 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
594 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
596 , numAllocForAllRows_(0)
598 , indicesAreAllocated_(true)
599 , indicesAreLocal_(true)
600 , indicesAreGlobal_(false)
601 , fillComplete_(false)
602 , lowerTriangular_ (false)
603 , upperTriangular_ (false)
604 , indicesAreSorted_(true)
605 , noRedundancies_(true)
606 , haveLocalConstants_ (false)
607 , haveGlobalConstants_ (false)
608 , sortGhostsAssociatedWithEachProcessor_(true)
611 setAllIndices (rowPointers, columnIndices);
612 checkInternalState ();
616 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
618 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
619 const Teuchos::RCP<const map_type>& colMap,
620 const Teuchos::ArrayRCP<size_t>& rowPointers,
621 const Teuchos::ArrayRCP<LocalOrdinal> & columnIndices,
622 const Teuchos::RCP<Teuchos::ParameterList>& params) :
626 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
627 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
628 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
629 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
630 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
632 , numAllocForAllRows_ (0)
634 , indicesAreAllocated_ (true)
635 , indicesAreLocal_ (true)
636 , indicesAreGlobal_ (false)
637 , fillComplete_ (false)
638 , lowerTriangular_ (false)
639 , upperTriangular_ (false)
640 , indicesAreSorted_ (true)
641 , noRedundancies_ (true)
642 , haveLocalConstants_ (false)
643 , haveGlobalConstants_ (false)
644 , sortGhostsAssociatedWithEachProcessor_ (true)
647 setAllIndices (rowPointers, columnIndices);
648 checkInternalState ();
652 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
654 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
655 const Teuchos::RCP<const map_type>& colMap,
657 const Teuchos::RCP<Teuchos::ParameterList>& params)
666 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
669 const Teuchos::RCP<const map_type>& rowMap,
670 const Teuchos::RCP<const map_type>& colMap,
671 const Teuchos::RCP<const map_type>& domainMap,
672 const Teuchos::RCP<const map_type>& rangeMap,
673 const Teuchos::RCP<Teuchos::ParameterList>& params)
677 , lclGraph_ (k_local_graph_)
678 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
679 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
680 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
681 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
682 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
684 , numAllocForAllRows_ (0)
686 , indicesAreAllocated_ (true)
687 , indicesAreLocal_ (true)
688 , indicesAreGlobal_ (false)
689 , fillComplete_ (false)
690 , lowerTriangular_ (false)
691 , upperTriangular_ (false)
692 , indicesAreSorted_ (true)
693 , noRedundancies_ (true)
694 , haveLocalConstants_ (false)
695 , haveGlobalConstants_ (false)
696 , sortGhostsAssociatedWithEachProcessor_ (true)
699 const char tfecfFuncName[] =
"CrsGraph(Kokkos::LocalStaticCrsGraph,Map,Map,Map,Map)";
701 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
702 colMap.is_null (), std::runtime_error,
703 ": The input column Map must be nonnull.");
704 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
705 k_local_graph_.numRows () != rowMap->getNodeNumElements (),
707 ": The input row Map and the input local graph need to have the same "
708 "number of rows. The row Map claims " << rowMap->getNodeNumElements ()
709 <<
" row(s), but the local graph claims " << k_local_graph_.numRows ()
718 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
719 k_lclInds1D_.extent (0) != 0 || k_gblInds1D_.extent (0) != 0, std::logic_error,
720 ": cannot have 1D data structures allocated.");
721 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
722 ! lclInds2D_.is_null () || ! gblInds2D_.is_null (), std::logic_error,
723 ": cannot have 2D data structures allocated.");
725 setDomainRangeMaps (domainMap.is_null() ? rowMap_ : domainMap,
726 rangeMap .is_null() ? rowMap_ : rangeMap);
727 Teuchos::Array<int> remotePIDs (0);
728 this->makeImportExport (remotePIDs,
false);
730 k_lclInds1D_ = lclGraph_.entries;
731 k_rowPtrs_ = lclGraph_.row_map;
733 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
734 params->get (
"compute global constants",
true);
735 const bool computeLocalTriangularConstants = params.get () ==
nullptr ||
736 params->get (
"compute local triangular constants",
true);
738 if (callComputeGlobalConstants) {
739 this->computeGlobalConstants (computeLocalTriangularConstants);
741 this->fillComplete_ =
true;
742 this->checkInternalState ();
745 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
750 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
751 Teuchos::RCP<const Teuchos::ParameterList>
756 using Teuchos::ParameterList;
757 using Teuchos::parameterList;
759 RCP<ParameterList> params = parameterList (
"Tpetra::CrsGraph");
762 RCP<ParameterList> importSublist = parameterList (
"Import");
774 Distributor distributor (rowMap_->getComm (), importSublist);
775 params->set (
"Import", *importSublist,
"How the Import performs communication.");
781 params->set (
"Export", *importSublist,
"How the Export performs communication.");
787 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
792 Teuchos::RCP<const Teuchos::ParameterList> validParams =
793 getValidParameters ();
794 params->validateParametersAndSetDefaults (*validParams);
795 this->setMyParamList (params);
799 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
804 return rowMap_->getGlobalNumElements ();
808 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
813 const char tfecfFuncName[] =
"getGlobalNumCols: ";
814 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
815 ! isFillComplete () || getDomainMap ().is_null (), std::runtime_error,
816 "The graph does not have a domain Map. You may not call this method in "
818 return getDomainMap ()->getGlobalNumElements ();
822 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
827 return this->rowMap_.is_null () ?
828 static_cast<size_t> (0) :
829 this->rowMap_->getNodeNumElements ();
833 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
838 const char tfecfFuncName[] =
"getNodeNumCols: ";
839 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
840 ! hasColMap (), std::runtime_error,
841 "The graph does not have a column Map. You may not call this method "
842 "unless the graph has a column Map. This requires either that a custom "
843 "column Map was given to the constructor, or that fillComplete() has "
845 return colMap_.is_null () ? static_cast<size_t> (0) :
846 colMap_->getNodeNumElements ();
850 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
855 return nodeNumDiags_;
859 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
864 return this->getNodeNumDiagsImpl ();
868 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
873 const char tfecfFuncName[] =
"getGlobalNumDiags: ";
874 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
875 (! this->haveGlobalConstants_, std::logic_error,
876 "The graph does not have global constants computed, "
877 "but the user has requested them.");
879 return globalNumDiags_;
883 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
888 return this->getGlobalNumDiagsImpl ();
892 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
897 return rowMap_.is_null () ? Teuchos::null : rowMap_->
getNode ();
901 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
902 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
910 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
911 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
919 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
920 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
928 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
929 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
937 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
938 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::import_type>
946 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
947 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::export_type>
955 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
960 return ! colMap_.is_null ();
964 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
972 const bool isOpt = indicesAreAllocated_ &&
973 k_numRowEntries_.extent (0) == 0 &&
974 getNodeNumRows () > 0;
976 const char tfecfFuncName[] =
"isStorageOptimized: ";
977 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
979 "The matrix claims to have optimized storage, but getProfileType() "
980 "returns DynamicProfile. This should never happen. Please report this "
981 "bug to the Tpetra developers.");
987 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
996 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1001 const char tfecfFuncName[] =
"getGlobalNumEntries: ";
1002 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1003 (! this->haveGlobalConstants_, std::logic_error,
1004 "The graph does not have global constants computed, "
1005 "but the user has requested them.");
1007 return globalNumEntries_;
1011 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1016 typedef LocalOrdinal LO;
1018 if (this->indicesAreAllocated_) {
1019 const LO lclNumRows = this->getNodeNumRows ();
1020 if (lclNumRows == 0) {
1021 return static_cast<size_t> (0);
1025 auto numEntPerRow = this->k_numRowEntries_;
1026 const LO numNumEntPerRow = numEntPerRow.extent (0);
1027 if (numNumEntPerRow == 0) {
1028 if (static_cast<LO> (this->lclGraph_.row_map.extent (0)) <
1029 static_cast<LO> (lclNumRows + 1)) {
1030 return static_cast<size_t> (0);
1033 return ::Tpetra::Details::getEntryOnHost (this->lclGraph_.row_map, lclNumRows);
1043 typedef typename num_row_entries_type::execution_space
1045 typedef Kokkos::RangePolicy<host_exec_space, LO> range_type;
1047 const LO upperLoopBound = lclNumRows < numNumEntPerRow ?
1050 size_t nodeNumEnt = 0;
1051 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::getNumNodeEntries",
1052 range_type (0, upperLoopBound),
1053 [=] (
const LO& k,
size_t& lclSum) {
1054 lclSum += numEntPerRow(k);
1061 return static_cast<size_t> (0);
1066 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1071 const char tfecfFuncName[] =
"getGlobalMaxNumRowEntries: ";
1072 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1073 (! this->haveGlobalConstants_, std::logic_error,
1074 "The graph does not have global constants computed, "
1075 "but the user has requested them.");
1077 return globalMaxNumRowEntries_;
1081 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1086 return nodeMaxNumRowEntries_;
1090 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1095 return fillComplete_;
1099 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1104 return ! fillComplete_;
1108 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1113 return this->lowerTriangular_;
1117 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1122 return this->isLowerTriangularImpl ();
1126 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1131 return this->upperTriangular_;
1135 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1140 return this->isUpperTriangularImpl ();
1144 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1149 return indicesAreLocal_;
1153 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1158 return indicesAreGlobal_;
1162 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1167 typedef LocalOrdinal LO;
1169 if (this->indicesAreAllocated_) {
1170 const LO lclNumRows = this->getNodeNumRows ();
1171 if (lclNumRows == 0) {
1172 return static_cast<size_t> (0);
1174 else if (this->storageStatus_ == ::Tpetra::Details::STORAGE_1D_PACKED) {
1175 if (static_cast<LO> (this->lclGraph_.row_map.extent (0)) <
1176 static_cast<LO> (lclNumRows + 1)) {
1177 return static_cast<size_t> (0);
1180 return ::Tpetra::Details::getEntryOnHost (this->lclGraph_.row_map, lclNumRows);
1183 else if (this->storageStatus_ == ::Tpetra::Details::STORAGE_1D_UNPACKED) {
1184 if (this->k_rowPtrs_.extent (0) == 0) {
1185 return static_cast<size_t> (0);
1188 return ::Tpetra::Details::getEntryOnHost (this->k_rowPtrs_, lclNumRows);
1191 else if (this->storageStatus_ == ::Tpetra::Details::STORAGE_2D) {
1192 size_t numAllocated = 0;
1193 if (this->isLocallyIndexed ()) {
1194 for (LocalOrdinal lclRow = 0; lclRow < lclNumRows; ++lclRow) {
1195 numAllocated += this->lclInds2D_[lclRow].size ();
1198 else if (this->isGloballyIndexed ()) {
1199 for (LocalOrdinal lclRow = 0; lclRow < lclNumRows; ++lclRow) {
1200 numAllocated += this->gblInds2D_[lclRow].size ();
1204 return numAllocated;
1207 return static_cast<size_t> (0);
1211 return Tpetra::Details::OrdinalTraits<size_t>::invalid ();
1216 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1217 Teuchos::RCP<const Teuchos::Comm<int> >
1221 return this->rowMap_.is_null () ? Teuchos::null : this->rowMap_->
getComm ();
1225 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1234 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1239 return indicesAreAllocated_;
1243 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1248 return indicesAreSorted_;
1252 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1257 return noRedundancies_;
1261 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1271 indicesAreSorted_ =
false;
1272 noRedundancies_ =
false;
1276 haveLocalConstants_ =
false;
1280 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1285 using Teuchos::arcp;
1286 using Teuchos::Array;
1287 using Teuchos::ArrayRCP;
1288 typedef Teuchos::ArrayRCP<size_t>::size_type size_type;
1289 typedef typename local_graph_type::row_map_type::non_const_type
1290 non_const_row_map_type;
1291 typedef typename local_graph_type::entries_type::non_const_type
1293 typedef Kokkos::View<GlobalOrdinal*,
1294 typename lcl_col_inds_type::array_layout,
1295 device_type> gbl_col_inds_type;
1296 const char tfecfFuncName[] =
"allocateIndices: ";
1297 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1302 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1303 (this->isLocallyIndexed () && lg == GlobalIndices, std::logic_error,
1304 "The graph is locally indexed, but Tpetra code is calling this method "
1305 "with lg=GlobalIndices." << suffix);
1306 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1307 (this->isGloballyIndexed () && lg == LocalIndices, std::logic_error,
1308 "The graph is globally indexed, but Tpetra code is calling this method "
1309 "with lg=LocalIndices. " << suffix);
1310 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1311 (this->indicesAreAllocated (), std::logic_error,
"The graph's indices "
1312 "are already allocated, but Tpetra is calling allocateIndices again."
1314 const size_t numRows = this->getNodeNumRows ();
1316 if (this->getProfileType () == StaticProfile) {
1320 non_const_row_map_type k_rowPtrs (
"Tpetra::CrsGraph::ptr", numRows + 1);
1322 if (this->k_numAllocPerRow_.extent (0) != 0) {
1327 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1328 (this->k_numAllocPerRow_.extent (0) != numRows,
1329 std::invalid_argument,
"k_numAllocPerRow_ is allocated, that is, "
1330 "has nonzero length " << this->k_numAllocPerRow_.extent (0)
1331 <<
", but its length != numRows = " << numRows <<
".");
1349 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1350 (this->numAllocForAllRows_ ==
1351 Tpetra::Details::OrdinalTraits<size_t>::invalid (),
1352 std::invalid_argument,
"numAllocForAllRows_ has an invalid value, "
1353 "namely Tpetra::Details::OrdinalTraits<size_t>::invalid() = " <<
1354 Tpetra::Details::OrdinalTraits<size_t>::invalid () <<
".");
1361 this->k_rowPtrs_ = k_rowPtrs;
1363 const size_type numInds = ::Tpetra::Details::getEntryOnHost (this->k_rowPtrs_, numRows);
1365 if (lg == LocalIndices) {
1366 k_lclInds1D_ = lcl_col_inds_type (
"Tpetra::CrsGraph::ind", numInds);
1369 k_gblInds1D_ = gbl_col_inds_type (
"Tpetra::CrsGraph::ind", numInds);
1371 storageStatus_ = ::Tpetra::Details::STORAGE_1D_UNPACKED;
1377 const bool useNumAllocPerRow =
1378 (this->k_numAllocPerRow_.extent (0) != 0);
1380 if (lg == LocalIndices) {
1381 this->lclInds2D_ = arcp<Array<LocalOrdinal> > (numRows);
1382 for (
size_t i = 0; i < numRows; ++i) {
1383 const size_t howMany = useNumAllocPerRow ?
1384 this->k_numAllocPerRow_(i) :
1385 this->numAllocForAllRows_;
1387 this->lclInds2D_[i].resize (howMany);
1392 this->gblInds2D_ = arcp<Array<GlobalOrdinal> > (numRows);
1393 for (
size_t i = 0; i < numRows; ++i) {
1394 const size_t howMany = useNumAllocPerRow ?
1395 this->k_numAllocPerRow_(i) :
1396 this->numAllocForAllRows_;
1398 this->gblInds2D_[i].resize (howMany);
1402 this->storageStatus_ = ::Tpetra::Details::STORAGE_2D;
1405 this->indicesAreLocal_ = (lg == LocalIndices);
1406 this->indicesAreGlobal_ = (lg == GlobalIndices);
1409 using Kokkos::ViewAllocateWithoutInitializing;
1410 typedef decltype (k_numRowEntries_) row_ent_type;
1411 const char label[] =
"Tpetra::CrsGraph::numRowEntries";
1413 row_ent_type numRowEnt (ViewAllocateWithoutInitializing (label), numRows);
1415 this->k_numRowEntries_ = numRowEnt;
1419 this->numAllocForAllRows_ = 0;
1420 this->k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
1421 this->indicesAreAllocated_ =
true;
1424 this->checkInternalState ();
1426 catch (std::logic_error& e) {
1427 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1428 (
true, std::logic_error,
"At end of allocateIndices, "
1429 "checkInternalState threw std::logic_error: "
1432 catch (std::exception& e) {
1433 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1434 (
true, std::runtime_error,
"At end of allocateIndices, "
1435 "checkInternalState threw std::exception: "
1439 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1440 (
true, std::runtime_error,
"At end of allocateIndices, "
1441 "checkInternalState threw an exception "
1442 "not a subclass of std::exception.");
1447 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1448 Teuchos::ArrayView<const LocalOrdinal>
1449 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1452 using Kokkos::subview;
1453 typedef LocalOrdinal LO;
1455 Kokkos::MemoryUnmanaged> row_view_type;
1457 if (rowinfo.allocSize == 0) {
1458 return Teuchos::ArrayView<const LO> ();
1461 if (k_lclInds1D_.extent (0) != 0) {
1462 const size_t start = rowinfo.offset1D;
1463 const size_t len = rowinfo.allocSize;
1464 const std::pair<size_t, size_t> rng (start, start + len);
1470 row_view_type rowView = subview (row_view_type (k_lclInds1D_), rng);
1471 const LO*
const rowViewRaw = (len == 0) ? NULL : rowView.data ();
1472 return Teuchos::ArrayView<const LO> (rowViewRaw, len, Teuchos::RCP_DISABLE_NODE_LOOKUP);
1474 else if (! lclInds2D_[rowinfo.localRow].empty ()) {
1475 return lclInds2D_[rowinfo.localRow] ();
1478 return Teuchos::ArrayView<const LO> ();
1483 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1487 LocalOrdinal& capacity,
1493 if (rowInfo.allocSize != 0) {
1494 if (k_lclInds1D_.extent (0) != 0) {
1495 #ifdef HAVE_TPETRA_DEBUG
1496 if (rowInfo.offset1D + rowInfo.allocSize >
1497 static_cast<size_t> (k_lclInds1D_.extent (0))) {
1498 return static_cast<LocalOrdinal> (-1);
1500 #endif // HAVE_TPETRA_DEBUG
1501 lclInds = &k_lclInds1D_[rowInfo.offset1D];
1502 capacity = rowInfo.allocSize;
1505 #ifdef HAVE_TPETRA_DEBUG
1506 if (rowInfo.localRow >= static_cast<size_t> (lclInds2D_.size ())) {
1507 return static_cast<LocalOrdinal> (-1);
1509 #endif // HAVE_TPETRA_DEBUG
1512 const auto& curRow = lclInds2D_[rowInfo.localRow];
1513 if (! curRow.empty ()) {
1514 lclInds = curRow.getRawPtr ();
1515 capacity = curRow.size ();
1519 return static_cast<LocalOrdinal> (0);
1522 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1523 Teuchos::ArrayView<LocalOrdinal>
1527 using Kokkos::subview;
1528 typedef LocalOrdinal LO;
1530 Kokkos::MemoryUnmanaged> row_view_type;
1532 if (rowinfo.allocSize == 0) {
1533 return Teuchos::ArrayView<LO> ();
1536 if (k_lclInds1D_.extent (0) != 0) {
1537 const size_t start = rowinfo.offset1D;
1538 const size_t len = rowinfo.allocSize;
1539 const std::pair<size_t, size_t> rng (start, start + len);
1545 row_view_type rowView = subview (row_view_type (k_lclInds1D_), rng);
1546 LO*
const rowViewRaw = (len == 0) ? NULL : rowView.data ();
1547 return Teuchos::ArrayView<LO> (rowViewRaw, len, Teuchos::RCP_DISABLE_NODE_LOOKUP);
1549 else if (! lclInds2D_[rowinfo.localRow].empty ()) {
1550 return lclInds2D_[rowinfo.localRow] ();
1553 return Teuchos::ArrayView<LO> ();
1559 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1560 Kokkos::View<
const LocalOrdinal*,
1562 Kokkos::MemoryUnmanaged>
1566 typedef LocalOrdinal LO;
1567 typedef Kokkos::View<
const LO*, execution_space,
1568 Kokkos::MemoryUnmanaged> row_view_type;
1570 if (rowInfo.allocSize == 0) {
1571 return row_view_type ();
1574 if (k_lclInds1D_.extent (0) != 0) {
1575 const size_t start = rowInfo.offset1D;
1576 const size_t len = rowInfo.allocSize;
1577 const std::pair<size_t, size_t> rng (start, start + len);
1583 return Kokkos::subview (row_view_type (k_lclInds1D_), rng);
1585 else if (! this->lclInds2D_[rowInfo.localRow].empty ()) {
1592 Teuchos::Array<LO>& lclInds = this->lclInds2D_[rowInfo.localRow];
1593 return row_view_type (lclInds.getRawPtr (), lclInds.size ());
1596 return row_view_type ();
1602 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1603 Kokkos::View<LocalOrdinal*,
1604 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::execution_space,
1605 Kokkos::MemoryUnmanaged>
1606 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1607 getLocalKokkosRowViewNonConst (
const RowInfo& rowInfo)
1609 typedef LocalOrdinal LO;
1610 typedef Kokkos::View<LO*, execution_space,
1611 Kokkos::MemoryUnmanaged> row_view_type;
1613 if (rowInfo.allocSize == 0) {
1614 return row_view_type ();
1617 if (k_lclInds1D_.extent (0) != 0) {
1618 const size_t start = rowInfo.offset1D;
1619 const size_t len = rowInfo.allocSize;
1620 const std::pair<size_t, size_t> rng (start, start + len);
1626 return Kokkos::subview (row_view_type (this->k_lclInds1D_), rng);
1628 else if (! this->lclInds2D_[rowInfo.localRow].empty ()) {
1635 Teuchos::Array<LO>& cols = this->lclInds2D_[rowInfo.localRow];
1636 LO*
const colsRaw = cols.getRawPtr ();
1637 return row_view_type (colsRaw, cols.size ());
1640 return row_view_type ();
1646 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1647 Kokkos::View<
const GlobalOrdinal*,
1648 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::execution_space,
1649 Kokkos::MemoryUnmanaged>
1650 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1651 getGlobalKokkosRowView (
const RowInfo& rowinfo)
const
1653 typedef GlobalOrdinal GO;
1654 typedef Kokkos::View<
const GO*, execution_space,
1655 Kokkos::MemoryUnmanaged> row_view_type;
1657 if (rowinfo.allocSize == 0) {
1658 return row_view_type ();
1661 if (this->k_gblInds1D_.extent (0) != 0) {
1662 const size_t start = rowinfo.offset1D;
1663 const size_t len = rowinfo.allocSize;
1664 const std::pair<size_t, size_t> rng (start, start + len);
1670 return Kokkos::subview (row_view_type (this->k_gblInds1D_), rng);
1672 else if (! this->gblInds2D_[rowinfo.localRow].empty ()) {
1679 Teuchos::Array<GO>& cols = this->gblInds2D_[rowinfo.localRow];
1680 return row_view_type (cols.getRawPtr (), cols.size ());
1683 return row_view_type ();
1689 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1690 Teuchos::ArrayView<const GlobalOrdinal>
1691 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1694 Teuchos::ArrayView<const GlobalOrdinal> view;
1695 if (rowinfo.allocSize > 0) {
1696 if (k_gblInds1D_.extent (0) != 0) {
1697 auto rng = std::make_pair (rowinfo.offset1D,
1698 rowinfo.offset1D + rowinfo.allocSize);
1705 Kokkos::MemoryUnmanaged> k_gblInds1D_unmanaged = k_gblInds1D_;
1706 view = Kokkos::Compat::getConstArrayView (Kokkos::subview (k_gblInds1D_unmanaged, rng));
1708 else if (! gblInds2D_[rowinfo.localRow].empty()) {
1709 view = gblInds2D_[rowinfo.localRow] ();
1716 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1720 LocalOrdinal& capacity,
1726 if (rowInfo.allocSize != 0) {
1727 if (k_gblInds1D_.extent (0) != 0) {
1728 #ifdef HAVE_TPETRA_DEBUG
1729 if (rowInfo.offset1D + rowInfo.allocSize >
1730 static_cast<size_t> (k_gblInds1D_.extent (0))) {
1731 return static_cast<LocalOrdinal> (-1);
1733 #endif // HAVE_TPETRA_DEBUG
1734 gblInds = &k_gblInds1D_[rowInfo.offset1D];
1735 capacity = rowInfo.allocSize;
1738 #ifdef HAVE_TPETRA_DEBUG
1739 if (rowInfo.localRow >= static_cast<size_t> (gblInds2D_.size ())) {
1740 return static_cast<LocalOrdinal> (-1);
1742 #endif // HAVE_TPETRA_DEBUG
1743 const auto& curRow = gblInds2D_[rowInfo.localRow];
1744 if (! curRow.empty ()) {
1745 gblInds = curRow.getRawPtr ();
1746 capacity = curRow.size ();
1750 return static_cast<LocalOrdinal> (0);
1754 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1755 Teuchos::ArrayView<GlobalOrdinal>
1759 Teuchos::ArrayView<GlobalOrdinal> view;
1760 if (rowinfo.allocSize > 0) {
1761 if (k_gblInds1D_.extent (0) != 0) {
1762 auto rng = std::make_pair (rowinfo.offset1D,
1763 rowinfo.offset1D + rowinfo.allocSize);
1770 Kokkos::MemoryUnmanaged> k_gblInds1D_unmanaged = k_gblInds1D_;
1771 view = Kokkos::Compat::getArrayView (Kokkos::subview (k_gblInds1D_unmanaged, rng));
1773 else if (! gblInds2D_[rowinfo.localRow].empty()) {
1774 view = gblInds2D_[rowinfo.localRow] ();
1781 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1786 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1788 if (this->rowMap_.is_null () || ! this->rowMap_->isNodeLocalElement (myRow)) {
1789 ret.localRow = STINV;
1792 ret.offset1D = STINV;
1796 ret.localRow = static_cast<size_t> (myRow);
1797 if (this->indicesAreAllocated ()) {
1800 if (this->k_rowPtrs_.extent (0) == 0) {
1805 ret.offset1D = this->k_rowPtrs_(myRow);
1806 ret.allocSize = this->k_rowPtrs_(myRow+1) - this->k_rowPtrs_(myRow);
1809 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
1811 this->k_numRowEntries_(myRow);
1814 ret.offset1D = STINV;
1815 if (this->isLocallyIndexed ()) {
1816 ret.allocSize = (this->lclInds2D_.size () == 0) ?
1818 this->lclInds2D_[myRow].size ();
1820 else if (this->isGloballyIndexed ()) {
1821 ret.allocSize = (this->gblInds2D_.size () == 0) ?
1823 this->gblInds2D_[myRow].size ();
1829 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
1831 this->k_numRowEntries_(myRow);
1838 ret.allocSize = (this->k_numAllocPerRow_.extent (0) != 0) ?
1839 this->k_numAllocPerRow_(myRow) :
1840 this->numAllocForAllRows_;
1842 ret.offset1D = STINV;
1849 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1854 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1856 if (this->rowMap_.is_null ()) {
1857 ret.localRow = STINV;
1860 ret.offset1D = STINV;
1863 const LocalOrdinal myRow = this->rowMap_->getLocalElement (gblRow);
1864 if (myRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid ()) {
1865 ret.localRow = STINV;
1868 ret.offset1D = STINV;
1872 ret.localRow = static_cast<size_t> (myRow);
1873 if (this->indicesAreAllocated ()) {
1878 if (this->k_rowPtrs_.extent (0) == 0) {
1883 ret.offset1D = this->k_rowPtrs_(myRow);
1884 ret.allocSize = this->k_rowPtrs_(myRow+1) - this->k_rowPtrs_(myRow);
1887 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
1889 this->k_numRowEntries_(myRow);
1892 ret.offset1D = STINV;
1893 if (this->isLocallyIndexed ()) {
1894 ret.allocSize = (this->lclInds2D_.size () == 0) ?
1896 this->lclInds2D_[myRow].size ();
1899 ret.allocSize = (this->gblInds2D_.size () == 0) ?
1901 this->gblInds2D_[myRow].size ();
1904 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
1906 this->k_numRowEntries_(myRow);
1913 ret.allocSize = (this->k_numAllocPerRow_.extent (0) != 0) ?
1914 this->k_numAllocPerRow_(myRow) :
1915 this->numAllocForAllRows_;
1917 ret.offset1D = STINV;
1924 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1929 using Teuchos::OrdinalTraits;
1930 typedef LocalOrdinal LO;
1931 typedef GlobalOrdinal GO;
1937 static_assert (
sizeof (GlobalOrdinal) >=
sizeof (LocalOrdinal),
1938 "Tpetra::CrsGraph: sizeof(GlobalOrdinal) must be >= sizeof(LocalOrdinal).");
1941 static_assert (
sizeof (
size_t) >=
sizeof (LocalOrdinal),
1942 "Tpetra::CrsGraph: sizeof(size_t) must be >= sizeof(LocalOrdinal).");
1943 static_assert (
sizeof(GST) >=
sizeof(
size_t),
1944 "Tpetra::CrsGraph: sizeof(Tpetra::global_size_t) must be >= sizeof(size_t).");
1952 const char msg[] =
"Tpetra::CrsGraph: Object cannot be created with the "
1953 "given template arguments: size assumptions are not valid.";
1954 TEUCHOS_TEST_FOR_EXCEPTION(
1955 static_cast<size_t> (Teuchos::OrdinalTraits<LO>::max ()) > Teuchos::OrdinalTraits<size_t>::max (),
1956 std::runtime_error, msg);
1957 TEUCHOS_TEST_FOR_EXCEPTION(
1958 static_cast<GST> (Teuchos::OrdinalTraits<LO>::max ()) > static_cast<GST> (Teuchos::OrdinalTraits<GO>::max ()),
1959 std::runtime_error, msg);
1960 TEUCHOS_TEST_FOR_EXCEPTION(
1961 static_cast<size_t> (Teuchos::OrdinalTraits<GO>::max ()) > Teuchos::OrdinalTraits<GST>::max(),
1962 std::runtime_error, msg);
1963 TEUCHOS_TEST_FOR_EXCEPTION(
1964 Teuchos::OrdinalTraits<size_t>::max () > Teuchos::OrdinalTraits<GST>::max (),
1965 std::runtime_error, msg);
1969 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1973 const SLocalGlobalViews &newInds,
1974 const ELocalGlobal lg,
1975 const ELocalGlobal I)
1977 using Teuchos::ArrayView;
1978 typedef LocalOrdinal LO;
1979 typedef GlobalOrdinal GO;
1981 #ifdef HAVE_TPETRA_DEBUG
1982 const char tfecfFuncName[] =
"insertIndices: ";
1983 const size_t oldNumEnt = this->getNumEntriesInLocalRow (rowinfo.localRow);
1984 #endif // HAVE_TPETRA_DEBUG
1986 #ifdef HAVE_TPETRA_DEBUG
1987 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1988 (lg != GlobalIndices && lg != LocalIndices, std::invalid_argument,
1989 "lg must be either GlobalIndices or LocalIndices.");
1990 #endif // HAVE_TPETRA_DEBUG
1991 size_t numNewInds = 0;
1992 if (lg == GlobalIndices) {
1993 ArrayView<const GO> new_ginds = newInds.ginds;
1994 numNewInds = new_ginds.size();
1995 if (I == GlobalIndices) {
1996 ArrayView<GO> gind_view = this->getGlobalViewNonConst (rowinfo);
1997 #ifdef HAVE_TPETRA_DEBUG
1998 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1999 (static_cast<size_t> (gind_view.size ()) <
2000 rowinfo.numEntries + numNewInds, std::logic_error,
2001 "gind_view.size() = " << gind_view.size ()
2002 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
2003 <<
") + numNewInds (= " << numNewInds <<
").");
2004 #endif // HAVE_TPETRA_DEBUG
2005 GO*
const gblColInds_out = gind_view.getRawPtr () + rowinfo.numEntries;
2006 for (
size_t k = 0; k < numNewInds; ++k) {
2007 gblColInds_out[k] = new_ginds[k];
2010 else if (I == LocalIndices) {
2011 ArrayView<LO> lind_view = this->getLocalViewNonConst (rowinfo);
2012 #ifdef HAVE_TPETRA_DEBUG
2013 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2014 (static_cast<size_t> (lind_view.size ()) <
2015 rowinfo.numEntries + numNewInds, std::logic_error,
2016 "lind_view.size() = " << lind_view.size ()
2017 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
2018 <<
") + numNewInds (= " << numNewInds <<
").");
2019 #endif // HAVE_TPETRA_DEBUG
2020 LO*
const lclColInds_out = lind_view.getRawPtr () + rowinfo.numEntries;
2021 for (
size_t k = 0; k < numNewInds; ++k) {
2022 lclColInds_out[k] = colMap_->getLocalElement (new_ginds[k]);
2026 else if (lg == LocalIndices) {
2027 ArrayView<const LO> new_linds = newInds.linds;
2028 numNewInds = new_linds.size();
2029 if (I == LocalIndices) {
2030 ArrayView<LO> lind_view = this->getLocalViewNonConst (rowinfo);
2031 #ifdef HAVE_TPETRA_DEBUG
2032 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2033 (static_cast<size_t> (lind_view.size ()) <
2034 rowinfo.numEntries + numNewInds, std::logic_error,
2035 "lind_view.size() = " << lind_view.size ()
2036 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
2037 <<
") + numNewInds (= " << numNewInds <<
").");
2038 #endif // HAVE_TPETRA_DEBUG
2039 LO*
const lclColInds_out = lind_view.getRawPtr () + rowinfo.numEntries;
2040 for (
size_t k = 0; k < numNewInds; ++k) {
2041 lclColInds_out[k] = new_linds[k];
2044 else if (I == GlobalIndices) {
2045 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Tpetra::CrsGraph::"
2046 "insertIndices: the case where the input indices are local and the "
2047 "indices to write are global (lg=LocalIndices, I=GlobalIndices) is "
2048 "not implemented, because it does not make sense." << std::endl <<
2049 "If you have correct local column indices, that means the graph has "
2050 "a column Map. In that case, you should be storing local indices.");
2054 rowinfo.numEntries += numNewInds;
2055 this->k_numRowEntries_(rowinfo.localRow) += numNewInds;
2056 this->setLocallyModified ();
2058 #ifdef HAVE_TPETRA_DEBUG
2059 const size_t chkNewNumEnt =
2060 this->getNumEntriesInLocalRow (rowinfo.localRow);
2061 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2062 (chkNewNumEnt != oldNumEnt + numNewInds, std::logic_error,
2063 "chkNewNumEnt = " << chkNewNumEnt
2064 <<
" != oldNumEnt (= " << oldNumEnt
2065 <<
") + numNewInds (= " << numNewInds <<
").");
2066 #endif // HAVE_TPETRA_DEBUG
2071 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2075 const GlobalOrdinal inputGblColInds[],
2076 const size_t numInputInds)
2078 return this->insertGlobalIndicesImpl (this->getRowInfo (lclRow),
2079 inputGblColInds, numInputInds);
2082 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2086 const GlobalOrdinal inputGblColInds[],
2087 const size_t numInputInds)
2089 using Kokkos::subview;
2090 typedef LocalOrdinal LO;
2091 typedef GlobalOrdinal GO;
2092 typedef Kokkos::pair<size_t, size_t> range_type;
2093 const char tfecfFuncName[] =
"insertGlobalIndicesImpl: ";
2095 const LO lclRow = static_cast<LO> (rowInfo.localRow);
2096 size_t newNumEntries = rowInfo.numEntries + numInputInds;
2098 if (newNumEntries > rowInfo.allocSize) {
2107 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2108 (rowInfo.numEntries > rowInfo.allocSize, std::logic_error,
2109 "For local row " << lclRow <<
", rowInfo.numEntries = "
2110 << rowInfo.numEntries <<
" > rowInfo.allocSize = "
2111 << rowInfo.allocSize
2112 <<
". Please report this bug to the Tpetra developers.");
2114 size_t dupCount = 0;
2115 if (k_gblInds1D_.extent (0) != 0) {
2116 const size_t curOffset = rowInfo.offset1D;
2117 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2118 (static_cast<size_t> (k_gblInds1D_.extent (0)) < curOffset,
2119 std::logic_error,
"k_gblInds1D_.extent(0) = "
2120 << this->k_gblInds1D_.extent (0)
2121 <<
" < offset1D = " << curOffset <<
". "
2122 "Please report this bug to the Tpetra developers.");
2123 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2124 (static_cast<size_t> (k_gblInds1D_.extent (0)) <
2125 curOffset + rowInfo.numEntries,
2126 std::logic_error,
"k_gblInds1D_.extent(0) = "
2127 << this->k_gblInds1D_.extent (0)
2128 <<
" < offset1D (= " << curOffset <<
") + rowInfo.numEntries (= "
2129 << rowInfo.numEntries <<
"). "
2130 "Please report this bug to the Tpetra developers.");
2131 const Kokkos::pair<size_t, size_t>
2132 range (curOffset, curOffset + rowInfo.numEntries);
2134 auto gblIndsCur = subview (this->k_gblInds1D_, range);
2135 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2136 (static_cast<size_t> (gblIndsCur.extent (0)) !=
2137 rowInfo.numEntries, std::logic_error,
2138 "gblIndsCur.extent(0) = " << gblIndsCur.extent (0)
2139 <<
" != rowInfo.numEntries = " << rowInfo.numEntries
2140 <<
". Please report this bug to the Tpetra developers.");
2142 for (
size_t k_new = 0; k_new < numInputInds; ++k_new) {
2143 const GO gblIndToInsert = inputGblColInds[k_new];
2144 for (
size_t k_old = 0; k_old < rowInfo.numEntries; ++k_old) {
2145 if (gblIndsCur[k_old] == gblIndToInsert) {
2161 Teuchos::Array<GO>& gblInds_out = this->gblInds2D_[lclRow];
2162 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2163 (rowInfo.allocSize != static_cast<size_t> (gblInds_out.size ()),
2164 std::logic_error,
"rowInfo.allocSize = " << rowInfo.allocSize
2165 <<
" != gblInds_out.size() = " << gblInds_out.size ()
2166 <<
". Please report this bug to the Tpetra developers.");
2167 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2168 (rowInfo.numEntries > static_cast<size_t> (gblInds_out.size ()),
2169 std::logic_error,
"rowInfo.numEntries = " << rowInfo.numEntries
2170 <<
" > gblInds_out.size() = " << gblInds_out.size ()
2171 <<
". Please report this bug to the Tpetra developers.");
2177 for (
size_t k_new = 0; k_new < numInputInds; ++k_new) {
2178 const GO gblIndToInsert = inputGblColInds[k_new];
2179 for (
size_t k_old = 0; k_old < rowInfo.numEntries; ++k_old) {
2180 if (gblInds_out[k_old] == gblIndToInsert) {
2192 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2193 (numInputInds < dupCount, std::logic_error,
"numInputInds = "
2194 << numInputInds <<
" < dupCount = " << dupCount
2195 <<
". Please report this bug to the Tpetra developers.");
2196 const size_t numNewToInsert = numInputInds - dupCount;
2198 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2199 (rowInfo.numEntries + numNewToInsert > rowInfo.allocSize,
2200 std::runtime_error,
"For local row " << lclRow <<
" on Process " <<
2201 this->getComm ()->getRank () <<
", even after excluding " << dupCount
2202 <<
" duplicate(s) in input, the new number of entries " <<
2203 (rowInfo.numEntries + numNewToInsert) <<
" still exceeds this row's "
2204 "static allocation size " << rowInfo.allocSize <<
". You must "
2205 "either fix the upper bound on the number of entries in this row, "
2206 "or switch from StaticProfile to DynamicProfile.");
2208 if (k_gblInds1D_.extent (0) != 0) {
2209 const size_t curOffset = rowInfo.offset1D;
2211 subview (k_gblInds1D_, range_type (curOffset,
2212 curOffset + rowInfo.numEntries));
2214 subview (k_gblInds1D_, range_type (curOffset + rowInfo.numEntries,
2215 curOffset + rowInfo.allocSize));
2218 for (
size_t k_new = 0; k_new < numInputInds; ++k_new) {
2219 const GO gblIndToInsert = inputGblColInds[k_new];
2221 bool isAlreadyInOld =
false;
2222 for (
size_t k_old = 0; k_old < rowInfo.numEntries; ++k_old) {
2223 if (gblIndsCur[k_old] == gblIndToInsert) {
2224 isAlreadyInOld =
true;
2228 if (! isAlreadyInOld) {
2229 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2230 (curPos >= numNewToInsert, std::logic_error,
"curPos = " <<
2231 curPos <<
" >= numNewToInsert = " << numNewToInsert <<
". "
2232 "Please report this bug to the Tpetra developers.");
2233 gblIndsNew[curPos] = gblIndToInsert;
2244 Teuchos::ArrayView<GO> gblInds = (this->gblInds2D_[lclRow]) ();
2249 auto gblIndsCur = gblInds (0, rowInfo.numEntries);
2250 auto gblIndsNew = gblInds (rowInfo.numEntries,
2251 rowInfo.allocSize - rowInfo.numEntries);
2254 for (
size_t k_new = 0; k_new < numInputInds; ++k_new) {
2255 const GO gblIndToInsert = inputGblColInds[k_new];
2257 bool isAlreadyInOld =
false;
2258 for (
size_t k_old = 0; k_old < rowInfo.numEntries; ++k_old) {
2259 if (gblIndsCur[k_old] == gblIndToInsert) {
2260 isAlreadyInOld =
true;
2264 if (! isAlreadyInOld) {
2265 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2266 (curPos >= numNewToInsert, std::logic_error,
"curPos = " <<
2267 curPos <<
" >= numNewToInsert = " << numNewToInsert <<
". "
2268 "Please report this bug to the Tpetra developers.");
2269 gblIndsNew[curPos] = gblIndToInsert;
2275 this->k_numRowEntries_(lclRow) = rowInfo.numEntries + numNewToInsert;
2276 this->setLocallyModified ();
2278 #ifdef HAVE_TPETRA_DEBUG
2279 newNumEntries = rowInfo.numEntries + numNewToInsert;
2280 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow (lclRow);
2281 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2282 (chkNewNumEntries != newNumEntries, std::logic_error,
2283 "After inserting new entries, getNumEntriesInLocalRow(" << lclRow <<
2284 ") = " << chkNewNumEntries <<
" != newNumEntries = " << newNumEntries
2285 <<
". Please report this bug to the Tpetra developers.");
2286 #endif // HAVE_TPETRA_DEBUG
2288 return numNewToInsert;
2292 size_t newAllocSize = 2*rowInfo.allocSize;
2293 if (newAllocSize < newNumEntries) {
2294 newAllocSize = newNumEntries;
2296 this->gblInds2D_[lclRow].resize (newAllocSize);
2301 if (k_gblInds1D_.extent (0) != 0) {
2302 const size_t offset = rowInfo.offset1D + rowInfo.numEntries;
2303 for (
size_t k = 0; k < numInputInds; ++k) {
2304 this->k_gblInds1D_[offset + k] = inputGblColInds[k];
2308 GO*
const whereToPutGblColInds =
2309 this->gblInds2D_[lclRow].getRawPtr () + rowInfo.numEntries;
2310 for (
size_t k_new = 0; k_new < numInputInds; ++k_new) {
2311 whereToPutGblColInds[k_new] = inputGblColInds[k_new];
2315 this->k_numRowEntries_(lclRow) += numInputInds;
2316 this->setLocallyModified ();
2318 #ifdef HAVE_TPETRA_DEBUG
2320 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow (lclRow);
2321 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2322 (chkNewNumEntries != newNumEntries, std::logic_error,
2323 "getNumEntriesInLocalRow(lclRow=" << lclRow <<
") = "
2324 << chkNewNumEntries <<
" != newNumEntries = " << newNumEntries
2325 <<
". Please report this bug to the Tpetra developers.");
2327 #endif // HAVE_TPETRA_DEBUG
2329 return numInputInds;
2333 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2337 const Teuchos::ArrayView<const LocalOrdinal>& indices)
2339 using Kokkos::MemoryUnmanaged;
2340 using Kokkos::subview;
2342 typedef LocalOrdinal LO;
2343 const char* tfecfFuncName (
"insertLocallIndicesImpl: ");
2345 const RowInfo rowInfo = this->getRowInfo(myRow);
2346 const size_t numNewInds = indices.size();
2347 const size_t newNumEntries = rowInfo.numEntries + numNewInds;
2348 if (newNumEntries > rowInfo.allocSize) {
2349 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2350 getProfileType() == StaticProfile, std::runtime_error,
2351 "New indices exceed statically allocated graph structure.");
2354 size_t newAllocSize = 2*rowInfo.allocSize;
2355 if (newAllocSize < newNumEntries) {
2356 newAllocSize = newNumEntries;
2358 this->lclInds2D_[myRow].resize(newAllocSize);
2362 if (this->k_lclInds1D_.extent (0) != 0) {
2363 typedef View<const LO*, execution_space, MemoryUnmanaged> input_view_type;
2364 typedef View<LO*, execution_space, MemoryUnmanaged> row_view_type;
2366 input_view_type inputInds (indices.getRawPtr (), indices.size ());
2367 const size_t start = rowInfo.offset1D + rowInfo.numEntries;
2368 const std::pair<size_t, size_t> rng (start, start + newNumEntries);
2373 row_view_type myInds = subview (row_view_type (this->k_lclInds1D_), rng);
2377 std::copy (indices.begin (), indices.end (),
2378 this->lclInds2D_[myRow].begin () + rowInfo.numEntries);
2381 this->k_numRowEntries_(myRow) += numNewInds;
2382 this->setLocallyModified ();
2383 #ifdef HAVE_TPETRA_DEBUG
2385 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow (myRow);
2386 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2387 (chkNewNumEntries != newNumEntries, std::logic_error,
2388 "getNumEntriesInLocalRow(" << myRow <<
") = " << chkNewNumEntries
2389 <<
" != newNumEntries = " << newNumEntries
2390 <<
". Please report this bug to the Tpetra developers.");
2392 #endif // HAVE_TPETRA_DEBUG
2396 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2398 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
2403 const size_t origNumEnt = rowInfo.numEntries;
2404 if (origNumEnt != Tpetra::Details::OrdinalTraits<size_t>::invalid () &&
2406 auto lclColInds = this->getLocalKokkosRowViewNonConst (rowInfo);
2408 LocalOrdinal*
const lclColIndsRaw = lclColInds.data ();
2411 std::sort (lclColIndsRaw, lclColIndsRaw + origNumEnt);
2415 LocalOrdinal*
const beg = lclColIndsRaw;
2416 LocalOrdinal*
const end = beg + rowInfo.numEntries;
2418 LocalOrdinal*
const newend = std::unique (beg, end);
2419 const size_t newNumEnt = newend - beg;
2422 this->k_numRowEntries_(rowInfo.localRow) = newNumEnt;
2423 return origNumEnt - newNumEnt;
2426 return static_cast<size_t> (0);
2430 return static_cast<size_t> (0);
2435 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2439 const Teuchos::RCP<const map_type>& rangeMap)
2442 if (domainMap_ != domainMap) {
2443 domainMap_ = domainMap;
2444 importer_ = Teuchos::null;
2446 if (rangeMap_ != rangeMap) {
2447 rangeMap_ = rangeMap;
2448 exporter_ = Teuchos::null;
2453 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2458 globalNumEntries_ = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2459 globalNumDiags_ = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2460 globalMaxNumRowEntries_ = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2461 haveGlobalConstants_ =
false;
2465 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2472 const char tfecfFuncName[] =
"checkInternalState: ";
2473 const char suffix[] =
" Please report this bug to the Tpetra developers.";
2475 const global_size_t GSTI = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2481 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2482 (this->rowMap_.is_null (), std::logic_error,
2483 "Row Map is null." << suffix);
2486 const LocalOrdinal lclNumRows =
2487 static_cast<LocalOrdinal> (this->getNodeNumRows ());
2489 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2490 (this->isFillActive () == this->isFillComplete (), std::logic_error,
2491 "Graph cannot be both fill active and fill complete." << suffix);
2492 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2493 (this->isFillComplete () &&
2494 (this->colMap_.is_null () ||
2495 this->rangeMap_.is_null () ||
2496 this->domainMap_.is_null ()),
2498 "Graph is full complete, but at least one of {column, range, domain} "
2499 "Map is null." << suffix);
2500 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2501 (this->isStorageOptimized () && ! this->indicesAreAllocated (),
2502 std::logic_error,
"Storage is optimized, but indices are not "
2503 "allocated, not even trivially." << suffix);
2504 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2505 (this->indicesAreAllocated_ &&
2506 (this->storageStatus_ == ::Tpetra::Details::STORAGE_1D_PACKED ||
2507 this->storageStatus_ == ::Tpetra::Details::STORAGE_1D_UNPACKED) &&
2509 "Graph claims to have allocated indices and 1-D storage "
2510 "(either packed or unpacked), but also claims to be DynamicProfile.");
2511 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2512 (this->indicesAreAllocated_ &&
2513 this->storageStatus_ == ::Tpetra::Details::STORAGE_2D &&
2515 "Graph claims to have allocated indices and 2-D storage, "
2516 "but also claims to be StaticProfile.");
2517 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2518 (this->indicesAreAllocated_ &&
2519 this->storageStatus_ == ::Tpetra::Details::STORAGE_2D &&
2520 this->isLocallyIndexed () &&
2521 static_cast<LocalOrdinal> (this->lclInds2D_.size ()) != lclNumRows,
2523 "Graph claims to have allocated indices, be locally indexed, and have "
2524 "2-D storage, but lclInds2D_.size() = " << this->lclInds2D_.size ()
2525 <<
" != getNodeNumRows() = " << lclNumRows <<
".");
2526 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2527 (this->indicesAreAllocated_ &&
2528 this->storageStatus_ == ::Tpetra::Details::STORAGE_2D &&
2529 this->isGloballyIndexed () &&
2530 static_cast<LocalOrdinal> (this->gblInds2D_.size ()) != lclNumRows,
2532 "Graph claims to have allocated indices, be globally indexed, and have "
2533 "2-D storage, but gblInds2D_.size() = " << this->gblInds2D_.size ()
2534 <<
" != getNodeNumRows() = " << lclNumRows <<
".");
2536 size_t nodeAllocSize = 0;
2538 nodeAllocSize = this->getNodeAllocationSize ();
2540 catch (std::logic_error& e) {
2541 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2542 (
true, std::runtime_error,
"getNodeAllocationSize threw "
2543 "std::logic_error: " << e.what ());
2545 catch (std::exception& e) {
2546 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2547 (
true, std::runtime_error,
"getNodeAllocationSize threw an "
2548 "std::exception: " << e.what ());
2551 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2552 (
true, std::runtime_error,
"getNodeAllocationSize threw an exception "
2553 "not a subclass of std::exception.");
2556 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2557 (this->isStorageOptimized () &&
2558 nodeAllocSize != this->getNodeNumEntries (),
2559 std::logic_error,
"Storage is optimized, but "
2560 "this->getNodeAllocationSize() = " << nodeAllocSize
2561 <<
" != this->getNodeNumEntries() = " << this->getNodeNumEntries ()
2563 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2564 (! this->haveGlobalConstants_ &&
2565 (this->globalNumEntries_ != GSTI ||
2566 this->globalMaxNumRowEntries_ != GSTI),
2567 std::logic_error,
"Graph claims not to have global constants, but "
2568 "some of the global constants are not marked as invalid." << suffix);
2569 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2570 (this->haveGlobalConstants_ &&
2571 (this->globalNumEntries_ == GSTI ||
2572 this->globalMaxNumRowEntries_ == GSTI),
2573 std::logic_error,
"Graph claims to have global constants, but "
2574 "some of them are marked as invalid." << suffix);
2575 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2576 (this->haveGlobalConstants_ &&
2577 (this->globalNumEntries_ < this->getNodeNumEntries () ||
2578 this->globalMaxNumRowEntries_ < this->nodeMaxNumRowEntries_),
2579 std::logic_error,
"Graph claims to have global constants, and "
2580 "all of the values of the global constants are valid, but "
2581 "some of the local constants are greater than "
2582 "their corresponding global constants." << suffix);
2583 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2584 (this->indicesAreAllocated () &&
2585 (this->numAllocForAllRows_ != 0 ||
2586 this->k_numAllocPerRow_.extent (0) != 0),
2587 std::logic_error,
"The graph claims that its indices are allocated, but "
2588 "either numAllocForAllRows_ (= " << this->numAllocForAllRows_ <<
") is "
2589 "nonzero, or k_numAllocPerRow_ has nonzero dimension. In other words, "
2590 "the graph is supposed to release its \"allocation specifications\" "
2591 "when it allocates its indices." << suffix);
2592 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2593 (this->isStorageOptimized () && this->pftype_ !=
StaticProfile,
2595 "Storage is optimized, but graph is not StaticProfile." << suffix);
2596 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2597 (this->isGloballyIndexed () &&
2598 this->k_rowPtrs_.extent (0) != 0 &&
2599 (static_cast<size_t> (this->k_rowPtrs_.extent (0)) != static_cast<size_t> (lclNumRows + 1) ||
2600 this->k_rowPtrs_(lclNumRows) != static_cast<size_t> (this->k_gblInds1D_.extent (0))),
2601 std::logic_error,
"If k_rowPtrs_ has nonzero size and "
2602 "the graph is globally indexed, then "
2603 "k_rowPtrs_ must have N+1 rows, and "
2604 "k_rowPtrs_(N) must equal k_gblInds1D_.extent(0)." << suffix);
2605 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2606 (this->isLocallyIndexed () &&
2607 this->k_rowPtrs_.extent (0) != 0 &&
2608 (static_cast<size_t> (k_rowPtrs_.extent (0)) != static_cast<size_t> (lclNumRows + 1) ||
2609 this->k_rowPtrs_(lclNumRows) != static_cast<size_t> (this->k_lclInds1D_.extent (0))),
2610 std::logic_error,
"If k_rowPtrs_ has nonzero size and "
2611 "the graph is locally indexed, then "
2612 "k_rowPtrs_ must have N+1 rows, and "
2613 "k_rowPtrs_(N) must equal k_lclInds1D_.extent(0)." << suffix);
2616 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2617 (this->indicesAreAllocated () &&
2618 this->getNodeNumRows () > 0 &&
2619 this->lclInds2D_.is_null () &&
2620 this->gblInds2D_.is_null (),
2621 std::logic_error,
"Graph has DynamicProfile, indices are allocated, and "
2622 "the calling process has nonzero rows, but 2-D column index storage "
2623 "(whether local or global) is not present." << suffix);
2624 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2625 (this->indicesAreAllocated () &&
2626 this->getNodeNumRows () > 0 &&
2627 this->k_numRowEntries_.extent (0) == 0,
2628 std::logic_error,
"Graph has DynamicProfile, indices are allocated, and "
2629 "the calling process has nonzero rows, but k_numRowEntries_ is not "
2630 "present." << suffix);
2631 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2632 (this->k_lclInds1D_.extent (0) != 0 ||
2633 this->k_gblInds1D_.extent (0) != 0,
2634 std::logic_error,
"Graph has DynamicProfile, but "
2635 "1-D allocations are present." << suffix);
2636 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2637 (this->k_rowPtrs_.extent (0) != 0,
2638 std::logic_error,
"Graph has DynamicProfile, but "
2639 "row offsets are present." << suffix);
2642 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2643 (this->indicesAreAllocated () &&
2644 nodeAllocSize > 0 &&
2645 this->k_lclInds1D_.extent (0) == 0 &&
2646 this->k_gblInds1D_.extent (0) == 0,
2647 std::logic_error,
"Graph has StaticProfile and is allocated "
2648 "nonnontrivally, but 1-D allocations are not present." << suffix);
2649 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2650 (this->lclInds2D_ != Teuchos::null || this->gblInds2D_ != Teuchos::null,
2651 std::logic_error,
"Graph has StaticProfile, but 2-D allocations are "
2652 "present." << suffix);
2655 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2656 (! this->indicesAreAllocated () &&
2657 ((this->k_rowPtrs_.extent (0) != 0 ||
2658 this->k_numRowEntries_.extent (0) != 0) ||
2659 this->k_lclInds1D_.extent (0) != 0 ||
2660 this->lclInds2D_ != Teuchos::null ||
2661 this->k_gblInds1D_.extent (0) != 0 ||
2662 this->gblInds2D_ != Teuchos::null),
2663 std::logic_error,
"If indices are not allocated, "
2664 "then none of the buffers should be." << suffix);
2668 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2669 ((this->indicesAreLocal_ || this->indicesAreGlobal_) &&
2670 ! this->indicesAreAllocated_,
2671 std::logic_error,
"Indices may be local or global only if they are "
2672 "allocated." << suffix);
2673 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2674 (this->indicesAreLocal_ && this->indicesAreGlobal_,
2675 std::logic_error,
"Indices may not be both local and global." << suffix);
2676 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2677 (this->indicesAreLocal_ &&
2678 (this->k_gblInds1D_.extent (0) != 0 || ! this->gblInds2D_.is_null ()),
2679 std::logic_error,
"Indices are local, but either "
2680 "k_gblInds1D_.extent(0) (= "
2681 << this->k_gblInds1D_.extent (0) <<
") != 0, or "
2682 "gblInds2D_ is not null. In other words, if indices are local, "
2683 "then global allocations should not be present." << suffix);
2684 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2685 (this->indicesAreGlobal_ &&
2686 (this->k_lclInds1D_.extent (0) != 0 ||
2687 ! this->lclInds2D_.is_null ()),
2688 std::logic_error,
"Indices are global, but either "
2689 "k_lclInds1D_.extent(0) (= "
2690 << this->k_lclInds1D_.extent (0) <<
") != 0, or "
2691 "lclInds2D_ is not null. In other words, if indices are global, "
2692 "then local allocations should not be present." << suffix);
2693 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2694 (this->indicesAreLocal_ &&
2695 nodeAllocSize > 0 &&
2696 this->k_lclInds1D_.extent (0) == 0 &&
2697 this->getNodeNumRows () > 0 &&
2698 this->lclInds2D_.is_null (),
2699 std::logic_error,
"Indices are local, getNodeAllocationSize() = "
2700 << nodeAllocSize <<
" > 0, k_lclInds1D_.extent(0) = 0, "
2701 "getNodeNumRows() = " << this->getNodeNumRows () <<
" > 0, and "
2702 "lclInds2D_ is null." << suffix);
2703 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2704 (this->indicesAreGlobal_ &&
2705 nodeAllocSize > 0 &&
2706 this->k_gblInds1D_.extent (0) == 0 &&
2707 this->getNodeNumRows () > 0 &&
2708 this->gblInds2D_.is_null (),
2709 std::logic_error,
"Indices are global, getNodeAllocationSize() = "
2710 << nodeAllocSize <<
" > 0, k_gblInds1D_.extent(0) = 0, "
2711 "getNodeNumRows() = " << this->getNodeNumRows () <<
" > 0, and "
2712 "gblInds2D_ is null." << suffix);
2714 if (this->indicesAreAllocated () &&
2716 this->k_rowPtrs_.extent (0) != 0) {
2717 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2718 (static_cast<size_t> (this->k_rowPtrs_.extent (0)) !=
2719 this->getNodeNumRows () + 1,
2720 std::logic_error,
"Graph is StaticProfile, indices are allocated, and "
2721 "k_rowPtrs_ has nonzero length, but k_rowPtrs_.extent(0) = "
2722 << this->k_rowPtrs_.extent (0) <<
" != getNodeNumRows()+1 = "
2723 << (this->getNodeNumRows () + 1) <<
"." << suffix);
2724 const size_t actualNumAllocated =
2725 ::Tpetra::Details::getEntryOnHost (this->k_rowPtrs_, this->getNodeNumRows ());
2726 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2727 (this->isLocallyIndexed () &&
2728 static_cast<size_t> (this->k_lclInds1D_.extent (0)) != actualNumAllocated,
2729 std::logic_error,
"Graph is StaticProfile and locally indexed, "
2730 "indices are allocated, and k_rowPtrs_ has nonzero length, but "
2731 "k_lclInds1D_.extent(0) = " << this->k_lclInds1D_.extent (0)
2732 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2733 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2734 (this->isGloballyIndexed () &&
2735 static_cast<size_t> (this->k_gblInds1D_.extent (0)) != actualNumAllocated,
2736 std::logic_error,
"Graph is StaticProfile and globally indexed, "
2737 "indices are allocated, and k_rowPtrs_ has nonzero length, but "
2738 "k_gblInds1D_.extent(0) = " << this->k_gblInds1D_.extent (0)
2739 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2745 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2750 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (globalRow);
2751 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2752 return Teuchos::OrdinalTraits<size_t>::invalid ();
2755 return rowInfo.numEntries;
2760 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2765 const RowInfo rowInfo = this->getRowInfo (localRow);
2766 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2767 return Teuchos::OrdinalTraits<size_t>::invalid ();
2770 return rowInfo.numEntries;
2775 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2780 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (globalRow);
2781 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2782 return Teuchos::OrdinalTraits<size_t>::invalid ();
2785 return rowInfo.allocSize;
2790 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2795 const RowInfo rowInfo = this->getRowInfo (localRow);
2796 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2797 return Teuchos::OrdinalTraits<size_t>::invalid ();
2800 return rowInfo.allocSize;
2805 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2806 Teuchos::ArrayRCP<const size_t>
2810 using Kokkos::ViewAllocateWithoutInitializing;
2811 using Kokkos::create_mirror_view;
2812 using Teuchos::ArrayRCP;
2813 typedef typename local_graph_type::row_map_type row_map_type;
2814 typedef typename row_map_type::non_const_value_type row_offset_type;
2815 #ifdef HAVE_TPETRA_DEBUG
2816 const char prefix[] =
"Tpetra::CrsGraph::getNodeRowPtrs: ";
2817 const char suffix[] =
" Please report this bug to the Tpetra developers.";
2818 #endif // HAVE_TPETRA_DEBUG
2819 const size_t size = k_rowPtrs_.extent (0);
2820 const bool same = Kokkos::Impl::is_same<size_t, row_offset_type>::value;
2823 return ArrayRCP<const size_t> ();
2826 ArrayRCP<const row_offset_type> ptr_rot;
2827 ArrayRCP<const size_t> ptr_st;
2832 typename row_map_type::HostMirror ptr_h = create_mirror_view (k_rowPtrs_);
2834 #ifdef HAVE_TPETRA_DEBUG
2835 TEUCHOS_TEST_FOR_EXCEPTION(
2836 ptr_h.extent (0) != k_rowPtrs_.extent (0), std::logic_error,
2837 prefix <<
"size_t == row_offset_type, but ptr_h.extent(0) = "
2838 << ptr_h.extent (0) <<
" != k_rowPtrs_.extent(0) = "
2839 << k_rowPtrs_.extent (0) <<
".");
2840 TEUCHOS_TEST_FOR_EXCEPTION(
2841 same && size != 0 && k_rowPtrs_.data () == NULL, std::logic_error,
2842 prefix <<
"size_t == row_offset_type and k_rowPtrs_.extent(0) = "
2843 << size <<
" != 0, but k_rowPtrs_.data() == NULL." << suffix);
2844 TEUCHOS_TEST_FOR_EXCEPTION(
2845 same && size != 0 && ptr_h.data () == NULL, std::logic_error,
2846 prefix <<
"size_t == row_offset_type and k_rowPtrs_.extent(0) = "
2847 << size <<
" != 0, but create_mirror_view(k_rowPtrs_).data() "
2848 "== NULL." << suffix);
2849 #endif // HAVE_TPETRA_DEBUG
2850 ptr_rot = Kokkos::Compat::persistingView (ptr_h);
2853 typedef Kokkos::View<size_t*, device_type> ret_view_type;
2854 ret_view_type ptr_d (ViewAllocateWithoutInitializing (
"ptr"), size);
2856 typename ret_view_type::HostMirror ptr_h = create_mirror_view (ptr_d);
2858 ptr_st = Kokkos::Compat::persistingView (ptr_h);
2860 #ifdef HAVE_TPETRA_DEBUG
2861 TEUCHOS_TEST_FOR_EXCEPTION(
2862 same && size != 0 && ptr_rot.is_null (), std::logic_error,
2863 prefix <<
"size_t == row_offset_type and size = " << size
2864 <<
" != 0, but ptr_rot is null." << suffix);
2865 TEUCHOS_TEST_FOR_EXCEPTION(
2866 ! same && size != 0 && ptr_st.is_null (), std::logic_error,
2867 prefix <<
"size_t != row_offset_type and size = " << size
2868 <<
" != 0, but ptr_st is null." << suffix);
2869 #endif // HAVE_TPETRA_DEBUG
2873 #ifdef HAVE_TPETRA_DEBUG
2874 ArrayRCP<const size_t> retval =
2875 Kokkos::Impl::if_c<same,
2876 ArrayRCP<const row_offset_type>,
2877 ArrayRCP<const size_t> >::select (ptr_rot, ptr_st);
2878 TEUCHOS_TEST_FOR_EXCEPTION(
2879 size != 0 && retval.is_null (), std::logic_error,
2880 prefix <<
"size = " << size <<
" != 0, but retval is null." << suffix);
2883 return Kokkos::Impl::if_c<same,
2884 ArrayRCP<const row_offset_type>,
2885 ArrayRCP<const size_t> >::select (ptr_rot, ptr_st);
2886 #endif // HAVE_TPETRA_DEBUG
2890 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2891 Teuchos::ArrayRCP<const LocalOrdinal>
2895 return Kokkos::Compat::persistingView (k_lclInds1D_);
2899 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2903 const Teuchos::ArrayView<LocalOrdinal>&indices,
2904 size_t& numEntries)
const
2906 using Teuchos::ArrayView;
2907 typedef LocalOrdinal LO;
2908 typedef GlobalOrdinal GO;
2909 const char tfecfFuncName[] =
"getLocalRowCopy: ";
2911 TEUCHOS_TEST_FOR_EXCEPTION(
2912 isGloballyIndexed () && ! hasColMap (), std::runtime_error,
2913 "Tpetra::CrsGraph::getLocalRowCopy: The graph is globally indexed and "
2914 "does not have a column Map yet. That means we don't have local indices "
2915 "for columns yet, so it doesn't make sense to call this method. If the "
2916 "graph doesn't have a column Map yet, you should call fillComplete on "
2921 const RowInfo rowinfo = this->getRowInfo (localRow);
2923 const size_t theNumEntries = rowinfo.numEntries;
2924 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2925 (static_cast<size_t> (indices.size ()) < theNumEntries, std::runtime_error,
2926 "Specified storage (size==" << indices.size () <<
") does not suffice "
2927 "to hold all " << theNumEntries <<
" entry/ies for this row.");
2928 numEntries = theNumEntries;
2930 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
2931 if (isLocallyIndexed ()) {
2932 ArrayView<const LO> lview = getLocalView (rowinfo);
2933 for (
size_t j = 0; j < theNumEntries; ++j) {
2934 indices[j] = lview[j];
2937 else if (isGloballyIndexed ()) {
2938 ArrayView<const GO> gview = getGlobalView (rowinfo);
2939 for (
size_t j = 0; j < theNumEntries; ++j) {
2940 indices[j] = colMap_->getLocalElement (gview[j]);
2947 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2951 const Teuchos::ArrayView<GlobalOrdinal>& indices,
2952 size_t& numEntries)
const
2954 using Teuchos::ArrayView;
2955 const char tfecfFuncName[] =
"getGlobalRowCopy: ";
2959 const RowInfo rowinfo = getRowInfoFromGlobalRowIndex (globalRow);
2960 const size_t theNumEntries = rowinfo.numEntries;
2961 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2962 static_cast<size_t> (indices.size ()) < theNumEntries, std::runtime_error,
2963 "Specified storage (size==" << indices.size () <<
") does not suffice "
2964 "to hold all " << theNumEntries <<
" entry/ies for this row.");
2965 numEntries = theNumEntries;
2967 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
2968 if (isLocallyIndexed ()) {
2969 ArrayView<const LocalOrdinal> lview = getLocalView (rowinfo);
2970 for (
size_t j = 0; j < theNumEntries; ++j) {
2971 indices[j] = colMap_->getGlobalElement (lview[j]);
2974 else if (isGloballyIndexed ()) {
2975 ArrayView<const GlobalOrdinal> gview = getGlobalView (rowinfo);
2976 for (
size_t j = 0; j < theNumEntries; ++j) {
2977 indices[j] = gview[j];
2984 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2988 Teuchos::ArrayView<const LocalOrdinal>& indices)
const
2990 const char tfecfFuncName[] =
"getLocalRowView: ";
2991 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2992 isGloballyIndexed (), std::runtime_error,
"The graph's indices are "
2993 "currently stored as global indices, so we cannot return a view with "
2994 "local column indices, whether or not the graph has a column Map. If "
2995 "the graph _does_ have a column Map, use getLocalRowCopy() instead.");
2999 const RowInfo rowInfo = getRowInfo (localRow);
3000 indices = Teuchos::null;
3001 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
3002 rowInfo.numEntries > 0) {
3003 indices = this->getLocalView (rowInfo);
3008 indices = indices (0, rowInfo.numEntries);
3011 #ifdef HAVE_TPETRA_DEBUG
3012 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3013 (static_cast<size_t> (indices.size ()) !=
3014 getNumEntriesInLocalRow (localRow), std::logic_error,
"indices.size() "
3015 "= " << indices.size () <<
" != getNumEntriesInLocalRow(localRow=" <<
3016 localRow <<
") = " << getNumEntriesInLocalRow (localRow) <<
3017 ". Please report this bug to the Tpetra developers.");
3018 #endif // HAVE_TPETRA_DEBUG
3022 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3026 Teuchos::ArrayView<const GlobalOrdinal>& indices)
const
3028 const char tfecfFuncName[] =
"getGlobalRowView: ";
3029 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3030 isLocallyIndexed (), std::runtime_error,
"The graph's indices are "
3031 "currently stored as local indices, so we cannot return a view with "
3032 "global column indices. Use getGlobalRowCopy() instead.");
3036 const RowInfo rowInfo = getRowInfoFromGlobalRowIndex (globalRow);
3037 indices = Teuchos::null;
3038 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
3039 rowInfo.numEntries > 0) {
3040 indices = (this->getGlobalView (rowInfo)) (0, rowInfo.numEntries);
3043 #ifdef HAVE_TPETRA_DEBUG
3044 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3045 (static_cast<size_t> (indices.size ()) != getNumEntriesInGlobalRow (globalRow),
3046 std::logic_error,
"indices.size() = " << indices.size ()
3047 <<
" != getNumEntriesInGlobalRow(globalRow=" << globalRow <<
") = "
3048 << getNumEntriesInGlobalRow (globalRow)
3049 <<
". Please report this bug to the Tpetra developers.");
3050 #endif // HAVE_TPETRA_DEBUG
3054 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3058 const Teuchos::ArrayView<const LocalOrdinal>& indices)
3060 const char tfecfFuncName[] =
"insertLocalIndices";
3062 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3063 ! isFillActive (), std::runtime_error,
3064 ": requires that fill is active.");
3065 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3066 isGloballyIndexed (), std::runtime_error,
3067 ": graph indices are global; use insertGlobalIndices().");
3068 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3069 ! hasColMap (), std::runtime_error,
3070 ": cannot insert local indices without a column map.");
3071 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3072 ! rowMap_->isNodeLocalElement (localRow), std::runtime_error,
3073 ": row does not belong to this node.");
3074 if (! indicesAreAllocated ()) {
3075 allocateIndices (LocalIndices);
3078 #ifdef HAVE_TPETRA_DEBUG
3084 using Teuchos::Array;
3085 using Teuchos::toString;
3087 typedef typename Teuchos::ArrayView<const LocalOrdinal>::size_type size_type;
3089 const map_type& colMap = * (getColMap ());
3090 Array<LocalOrdinal> badColInds;
3091 bool allInColMap =
true;
3092 for (size_type k = 0; k < indices.size (); ++k) {
3094 allInColMap =
false;
3095 badColInds.push_back (indices[k]);
3098 if (! allInColMap) {
3099 std::ostringstream os;
3100 os <<
"Tpetra::CrsGraph::insertLocalIndices: You attempted to insert "
3101 "entries in owned row " << localRow <<
", at the following column "
3102 "indices: " << toString (indices) <<
"." << endl;
3103 os <<
"Of those, the following indices are not in the column Map on "
3104 "this process: " << toString (badColInds) <<
"." << endl <<
"Since "
3105 "the graph has a column Map already, it is invalid to insert entries "
3106 "at those locations.";
3107 TEUCHOS_TEST_FOR_EXCEPTION(! allInColMap, std::invalid_argument, os.str ());
3110 #endif // HAVE_TPETRA_DEBUG
3112 insertLocalIndicesImpl (localRow, indices);
3114 #ifdef HAVE_TPETRA_DEBUG
3115 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3116 indicesAreAllocated() ==
false || isLocallyIndexed() ==
false,
3118 ": Violated stated post-conditions. Please contact Tpetra team.");
3122 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3126 const LocalOrdinal numEnt,
3127 const LocalOrdinal inds[])
3129 Teuchos::ArrayView<const LocalOrdinal> indsT (inds, numEnt);
3130 this->insertLocalIndices (localRow, indsT);
3134 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3138 const LocalOrdinal numInputInds,
3139 const GlobalOrdinal inputGblColInds[])
3141 typedef LocalOrdinal LO;
3142 const char tfecfFuncName[] =
"insertGlobalIndices: ";
3144 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3145 (this->isLocallyIndexed (), std::runtime_error,
3146 "graph indices are local; use insertLocalIndices().");
3151 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3152 (! this->isFillActive (), std::runtime_error,
3153 "You are not allowed to call this method if fill is not active. "
3154 "If fillComplete has been called, you must first call resumeFill "
3155 "before you may insert indices.");
3156 if (! this->indicesAreAllocated ()) {
3157 this->allocateIndices (GlobalIndices);
3159 const LO lclRow = this->rowMap_->getLocalElement (gblRow);
3160 if (lclRow != Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
3161 #ifdef HAVE_TPETRA_DEBUG
3162 if (this->hasColMap ()) {
3164 const map_type& colMap = * (this->colMap_);
3169 std::vector<GlobalOrdinal> badColInds;
3170 bool allInColMap =
true;
3171 for (LO k = 0; k < numInputInds; ++k) {
3173 allInColMap =
false;
3174 badColInds.push_back (inputGblColInds[k]);
3177 if (! allInColMap) {
3178 std::ostringstream os;
3179 os <<
"You attempted to insert entries in owned row " << gblRow
3180 <<
", at the following column indices: [";
3181 for (LO k = 0; k < numInputInds; ++k) {
3182 os << inputGblColInds[k];
3183 if (k + static_cast<LO> (1) < numInputInds) {
3187 os <<
"]." << endl <<
"Of those, the following indices are not in "
3188 "the column Map on this process: [";
3189 for (
size_t k = 0; k < badColInds.size (); ++k) {
3190 os << badColInds[k];
3191 if (k +
size_t (1) < badColInds.size ()) {
3195 os <<
"]." << endl <<
"Since the matrix has a column Map already, "
3196 "it is invalid to insert entries at those locations.";
3197 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3198 (
true, std::invalid_argument, os.str ());
3201 #endif // HAVE_TPETRA_DEBUG
3202 this->insertGlobalIndicesImpl (lclRow, inputGblColInds, numInputInds);
3205 this->insertGlobalIndicesIntoNonownedRows (gblRow, inputGblColInds,
3211 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3215 const Teuchos::ArrayView<const GlobalOrdinal>& inputGblColInds)
3217 this->insertGlobalIndices (gblRow, inputGblColInds.size (),
3218 inputGblColInds.getRawPtr ());
3222 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3226 const GlobalOrdinal gblColInds[],
3227 const LocalOrdinal numGblColInds)
3229 typedef LocalOrdinal LO;
3230 typedef GlobalOrdinal GO;
3231 const char tfecfFuncName[] =
"insertGlobalIndicesFiltered: ";
3233 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3234 (this->isLocallyIndexed (), std::runtime_error,
3235 "Graph indices are local; use insertLocalIndices().");
3240 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3241 (! this->isFillActive (), std::runtime_error,
3242 "You are not allowed to call this method if fill is not active. "
3243 "If fillComplete has been called, you must first call resumeFill "
3244 "before you may insert indices.");
3245 if (! this->indicesAreAllocated ()) {
3246 this->allocateIndices (GlobalIndices);
3249 Teuchos::ArrayView<const GO> gblColInds_av (gblColInds, numGblColInds);
3251 if (! this->colMap_.is_null ()) {
3252 const map_type& colMap = * (this->colMap_);
3255 while (curOffset < numGblColInds) {
3259 LO endOffset = curOffset;
3260 for ( ; endOffset < numGblColInds; ++endOffset) {
3262 if (lclCol == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
3269 const LO numIndInSeq = (endOffset - curOffset);
3270 if (numIndInSeq != 0) {
3271 this->insertGlobalIndicesImpl (lclRow, gblColInds + curOffset,
3277 curOffset = endOffset + 1;
3281 this->insertGlobalIndicesImpl (lclRow, gblColInds_av.getRawPtr (),
3282 gblColInds_av.size ());
3286 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3290 const GlobalOrdinal gblColInds[],
3291 const LocalOrdinal numGblColInds)
3296 std::vector<GlobalOrdinal>& nonlocalRow = this->nonlocals_[gblRow];
3297 for (LocalOrdinal k = 0; k < numGblColInds; ++k) {
3301 nonlocalRow.push_back (gblColInds[k]);
3305 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3310 const char tfecfFuncName[] =
"removeLocalIndices: ";
3311 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3312 ! isFillActive (), std::runtime_error,
"requires that fill is active.");
3313 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3314 isStorageOptimized (), std::runtime_error,
3315 "cannot remove indices after optimizeStorage() has been called.");
3316 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3317 isGloballyIndexed (), std::runtime_error,
"graph indices are global.");
3318 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3319 ! rowMap_->isNodeLocalElement (lrow), std::runtime_error,
3320 "Local row " << lrow <<
" is not in the row Map on the calling process.");
3321 if (! indicesAreAllocated ()) {
3322 allocateIndices (LocalIndices);
3327 clearGlobalConstants ();
3329 if (k_numRowEntries_.extent (0) != 0) {
3330 this->k_numRowEntries_(lrow) = 0;
3332 #ifdef HAVE_TPETRA_DEBUG
3333 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3334 getNumEntriesInLocalRow (lrow) != 0 ||
3335 ! indicesAreAllocated () ||
3336 ! isLocallyIndexed (), std::logic_error,
3337 ": Violated stated post-conditions. Please contact Tpetra team.");
3338 #endif // HAVE_TPETRA_DEBUG
3342 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3346 const typename local_graph_type::entries_type::non_const_type& columnIndices)
3348 const char tfecfFuncName[] =
"setAllIndices: ";
3349 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3350 ! hasColMap () || getColMap ().is_null (), std::runtime_error,
3351 "The graph must have a column Map before you may call this method.");
3352 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3353 static_cast<size_t> (rowPointers.size ()) != this->getNodeNumRows () + 1,
3354 std::runtime_error,
"rowPointers.size() = " << rowPointers.size () <<
3355 " != this->getNodeNumRows()+1 = " << (this->getNodeNumRows () + 1) <<
3361 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3362 (this->k_lclInds1D_.extent (0) != 0 ||
3363 this->k_gblInds1D_.extent (0) != 0,
3364 std::runtime_error,
"You may not call this method if 1-D data "
3365 "structures are already allocated.");
3367 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3368 (this->lclInds2D_ != Teuchos::null ||
3369 this->gblInds2D_ != Teuchos::null,
3370 std::runtime_error,
"You may not call this method if 2-D data "
3371 "structures are already allocated.");
3373 indicesAreAllocated_ =
true;
3374 indicesAreLocal_ =
true;
3376 k_lclInds1D_ = columnIndices;
3377 k_rowPtrs_ = rowPointers;
3380 storageStatus_ = ::Tpetra::Details::STORAGE_1D_PACKED;
3388 numAllocForAllRows_ = 0;
3389 k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
3391 checkInternalState ();
3395 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3399 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices)
3402 typedef typename local_graph_type::row_map_type row_map_type;
3403 typedef typename row_map_type::array_layout layout_type;
3404 typedef typename row_map_type::non_const_value_type row_offset_type;
3405 typedef View<
size_t*, layout_type , Kokkos::HostSpace,
3406 Kokkos::MemoryUnmanaged> input_view_type;
3407 typedef typename row_map_type::non_const_type nc_row_map_type;
3409 const size_t size = static_cast<size_t> (rowPointers.size ());
3410 const bool same = Kokkos::Impl::is_same<size_t, row_offset_type>::value;
3411 input_view_type ptr_in (rowPointers.getRawPtr (), size);
3413 nc_row_map_type ptr_rot (
"Tpetra::CrsGraph::ptr", size);
3419 input_view_type ptr_decoy (rowPointers.getRawPtr (), size);
3422 input_view_type>::select (ptr_rot, ptr_decoy),
3427 const bool inHostMemory =
3428 Kokkos::Impl::is_same<
typename row_map_type::memory_space,
3429 Kokkos::HostSpace>::value;
3440 View<size_t*, layout_type ,execution_space > ptr_st (
"Tpetra::CrsGraph::ptr", size);
3450 Kokkos::View<LocalOrdinal*, layout_type , execution_space > k_ind =
3451 Kokkos::Compat::getKokkosViewDeepCopy<device_type> (columnIndices ());
3452 setAllIndices (ptr_rot, k_ind);
3456 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3460 size_t& boundForAllLocalRows,
3461 bool& boundSameForAllLocalRows)
const
3463 const char tfecfFuncName[] =
"getNumEntriesPerLocalRowUpperBound: ";
3464 const char suffix[] =
" Please report this bug to the Tpetra developers.";
3469 Teuchos::ArrayRCP<const size_t> numEntriesPerRow;
3470 size_t numEntriesForAll = 0;
3471 bool allRowsSame =
true;
3473 const ptrdiff_t numRows = static_cast<ptrdiff_t> (this->getNodeNumRows ());
3475 if (this->indicesAreAllocated ()) {
3476 if (this->isStorageOptimized ()) {
3479 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3480 (this->getProfileType () !=
StaticProfile, std::logic_error,
3481 "The graph is not StaticProfile, but storage appears to be optimized."
3483 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3484 (numRows != 0 && k_rowPtrs_.extent (0) == 0, std::logic_error,
3485 "The graph has " << numRows <<
" (> 0) row" << (numRows != 1 ?
"s" :
"")
3486 <<
" on the calling process, but the k_rowPtrs_ array has zero entries."
3488 Teuchos::ArrayRCP<size_t> numEnt;
3490 numEnt = Teuchos::arcp<size_t> (numRows);
3495 bool allRowsReallySame =
false;
3496 for (ptrdiff_t i = 0; i < numRows; ++i) {
3497 numEnt[i] = this->k_rowPtrs_(i+1) - this->k_rowPtrs_(i);
3498 if (i != 0 && numEnt[i] != numEnt[i-1]) {
3499 allRowsReallySame =
false;
3502 if (allRowsReallySame) {
3504 numEntriesForAll = 0;
3506 numEntriesForAll = numEnt[1] - numEnt[0];
3511 numEntriesPerRow = numEnt;
3512 allRowsSame =
false;
3515 else if (k_numRowEntries_.extent (0) != 0) {
3520 numEntriesPerRow = Kokkos::Compat::persistingView (k_numRowEntries_);
3521 allRowsSame =
false;
3524 numEntriesForAll = 0;
3529 if (k_numAllocPerRow_.extent (0) != 0) {
3534 numEntriesPerRow = Kokkos::Compat::persistingView (k_numAllocPerRow_);
3535 allRowsSame =
false;
3538 numEntriesForAll = numAllocForAllRows_;
3543 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3544 (numEntriesForAll != 0 && numEntriesPerRow.size () != 0, std::logic_error,
3545 "numEntriesForAll and numEntriesPerRow are not consistent. The former "
3546 "is nonzero (" << numEntriesForAll <<
"), but the latter has nonzero "
3547 "size " << numEntriesPerRow.size () <<
"." << suffix);
3548 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3549 (numEntriesForAll != 0 && ! allRowsSame, std::logic_error,
3550 "numEntriesForAll and allRowsSame are not consistent. The former "
3551 "is nonzero (" << numEntriesForAll <<
"), but the latter is false."
3553 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3554 (numEntriesPerRow.size () != 0 && allRowsSame, std::logic_error,
3555 "numEntriesPerRow and allRowsSame are not consistent. The former has "
3556 "nonzero length " << numEntriesForAll <<
", but the latter is true."
3559 boundPerLocalRow = numEntriesPerRow;
3560 boundForAllLocalRows = numEntriesForAll;
3561 boundSameForAllLocalRows = allRowsSame;
3565 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3570 using Teuchos::Comm;
3571 using Teuchos::outArg;
3574 using Teuchos::REDUCE_MAX;
3575 using Teuchos::REDUCE_MIN;
3576 using Teuchos::reduceAll;
3578 typedef LocalOrdinal LO;
3579 typedef GlobalOrdinal GO;
3580 typedef typename Teuchos::Array<GO>::size_type size_type;
3581 const char tfecfFuncName[] =
"globalAssemble: ";
3583 RCP<const Comm<int> > comm = getComm ();
3585 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3586 (! isFillActive (), std::runtime_error,
"Fill must be active before "
3587 "you may call this method.");
3589 const size_t myNumNonlocalRows = this->nonlocals_.size ();
3596 const int iHaveNonlocalRows = (myNumNonlocalRows == 0) ? 0 : 1;
3597 int someoneHasNonlocalRows = 0;
3598 reduceAll<int, int> (*comm, REDUCE_MAX, iHaveNonlocalRows,
3599 outArg (someoneHasNonlocalRows));
3600 if (someoneHasNonlocalRows == 0) {
3614 RCP<const map_type> nonlocalRowMap;
3616 Teuchos::ArrayRCP<size_t> numEntPerNonlocalRow (myNumNonlocalRows);
3618 Teuchos::Array<GO> myNonlocalGblRows (myNumNonlocalRows);
3619 size_type curPos = 0;
3620 for (
auto mapIter = this->nonlocals_.begin ();
3621 mapIter != this->nonlocals_.end ();
3622 ++mapIter, ++curPos) {
3623 myNonlocalGblRows[curPos] = mapIter->first;
3624 std::vector<GO>& gblCols = mapIter->second;
3625 std::sort (gblCols.begin (), gblCols.end ());
3626 auto vecLast = std::unique (gblCols.begin (), gblCols.end ());
3627 gblCols.erase (vecLast, gblCols.end ());
3628 numEntPerNonlocalRow[curPos] = gblCols.size ();
3639 GO myMinNonlocalGblRow = std::numeric_limits<GO>::max ();
3641 auto iter = std::min_element (myNonlocalGblRows.begin (),
3642 myNonlocalGblRows.end ());
3643 if (iter != myNonlocalGblRows.end ()) {
3644 myMinNonlocalGblRow = *iter;
3647 GO gblMinNonlocalGblRow = 0;
3648 reduceAll<int, GO> (*comm, REDUCE_MIN, myMinNonlocalGblRow,
3649 outArg (gblMinNonlocalGblRow));
3650 const GO indexBase = gblMinNonlocalGblRow;
3651 const global_size_t INV = Teuchos::OrdinalTraits<global_size_t>::invalid ();
3652 nonlocalRowMap = rcp (
new map_type (INV, myNonlocalGblRows (), indexBase, comm));
3660 RCP<crs_graph_type> nonlocalGraph =
3661 rcp (
new crs_graph_type (nonlocalRowMap, numEntPerNonlocalRow,
3664 size_type curPos = 0;
3665 for (
auto mapIter = this->nonlocals_.begin ();
3666 mapIter != this->nonlocals_.end ();
3667 ++mapIter, ++curPos) {
3668 const GO gblRow = mapIter->first;
3669 std::vector<GO>& gblCols = mapIter->second;
3670 const LO numEnt = static_cast<LO> (numEntPerNonlocalRow[curPos]);
3671 nonlocalGraph->insertGlobalIndices (gblRow, numEnt, gblCols.data ());
3683 auto origRowMap = this->getRowMap ();
3684 const bool origRowMapIsOneToOne = origRowMap->isOneToOne ();
3686 if (origRowMapIsOneToOne) {
3687 export_type exportToOrig (nonlocalRowMap, origRowMap);
3697 export_type exportToOneToOne (nonlocalRowMap, oneToOneRowMap);
3703 crs_graph_type oneToOneGraph (oneToOneRowMap, 0);
3705 oneToOneGraph.doExport (*nonlocalGraph, exportToOneToOne,
Tpetra::INSERT);
3709 nonlocalGraph = Teuchos::null;
3712 import_type importToOrig (oneToOneRowMap, origRowMap);
3720 decltype (this->nonlocals_) newNonlocals;
3721 std::swap (this->nonlocals_, newNonlocals);
3723 checkInternalState ();
3727 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3732 #ifdef HAVE_TPETRA_DEBUG
3733 const char tfecfFuncName[] =
"resumeFill";
3735 Teuchos::barrier( *rowMap_->getComm() );
3736 #endif // HAVE_TPETRA_DEBUG
3737 clearGlobalConstants();
3738 if (params != Teuchos::null) this->setParameterList (params);
3739 lowerTriangular_ =
false;
3740 upperTriangular_ =
false;
3742 indicesAreSorted_ =
true;
3743 noRedundancies_ =
true;
3744 fillComplete_ =
false;
3745 #ifdef HAVE_TPETRA_DEBUG
3746 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3747 ! isFillActive() || isFillComplete(), std::logic_error,
3748 "::resumeFill(): At end of method, either fill is not active or fill is "
3749 "complete. This violates stated post-conditions. Please report this bug "
3750 "to the Tpetra developers.");
3751 #endif // HAVE_TPETRA_DEBUG
3755 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3770 Teuchos::RCP<const map_type> domMap = this->getDomainMap ();
3771 if (domMap.is_null ()) {
3772 domMap = this->getRowMap ();
3774 Teuchos::RCP<const map_type> ranMap = this->getRangeMap ();
3775 if (ranMap.is_null ()) {
3776 ranMap = this->getRowMap ();
3778 this->fillComplete (domMap, ranMap, params);
3782 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3786 const Teuchos::RCP<const map_type>& rangeMap,
3787 const Teuchos::RCP<Teuchos::ParameterList>& params)
3789 const char tfecfFuncName[] =
"fillComplete: ";
3791 #ifdef HAVE_TPETRA_DEBUG
3792 rowMap_->
getComm ()->barrier ();
3793 #endif // HAVE_TPETRA_DEBUG
3795 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( ! isFillActive() || isFillComplete(),
3796 std::runtime_error,
"Graph fill state must be active (isFillActive() "
3797 "must be true) before calling fillComplete().");
3799 const int numProcs = getComm ()->getSize ();
3807 if (! params.is_null ()) {
3808 if (params->isParameter (
"sort column map ghost gids")) {
3809 sortGhostsAssociatedWithEachProcessor_ =
3810 params->get<
bool> (
"sort column map ghost gids",
3811 sortGhostsAssociatedWithEachProcessor_);
3813 else if (params->isParameter (
"Sort column Map ghost GIDs")) {
3814 sortGhostsAssociatedWithEachProcessor_ =
3815 params->get<
bool> (
"Sort column Map ghost GIDs",
3816 sortGhostsAssociatedWithEachProcessor_);
3822 bool assertNoNonlocalInserts =
false;
3823 if (! params.is_null ()) {
3824 assertNoNonlocalInserts =
3825 params->get<
bool> (
"No Nonlocal Changes", assertNoNonlocalInserts);
3831 if (! indicesAreAllocated ()) {
3834 allocateIndices (LocalIndices);
3837 allocateIndices (GlobalIndices);
3845 const bool mayNeedGlobalAssemble = ! assertNoNonlocalInserts && numProcs > 1;
3846 if (mayNeedGlobalAssemble) {
3852 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3853 (numProcs > 1 && this->nonlocals_.size() > 0, std::runtime_error,
3854 "The graph's communicator contains only one process, "
3855 "but there are nonlocal entries. "
3856 "This probably means that invalid entries were added to the graph.");
3861 setDomainRangeMaps (domainMap, rangeMap);
3867 Teuchos::Array<int> remotePIDs (0);
3868 const bool mustBuildColMap = ! this->hasColMap ();
3869 if (mustBuildColMap) {
3875 const std::pair<size_t, std::string> makeIndicesLocalResult =
3876 this->makeIndicesLocal ();
3879 using ::Tpetra::Details::gathervPrint;
3881 using Teuchos::REDUCE_MIN;
3882 using Teuchos::reduceAll;
3883 using Teuchos::outArg;
3885 RCP<const map_type> map = this->getMap ();
3886 RCP<const Teuchos::Comm<int> > comm;
3887 if (! map.is_null ()) {
3888 comm = map->getComm ();
3890 if (comm.is_null ()) {
3891 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3892 (makeIndicesLocalResult.first != 0, std::runtime_error,
3893 makeIndicesLocalResult.second);
3896 const int lclSuccess = (makeIndicesLocalResult.first == 0);
3898 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
3899 if (gblSuccess != 1) {
3900 std::ostringstream os;
3901 gathervPrint (os, makeIndicesLocalResult.second, *comm);
3902 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3903 (
true, std::runtime_error, os.str ());
3912 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3913 (makeIndicesLocalResult.first != 0, std::runtime_error,
3914 makeIndicesLocalResult.second);
3920 this->sortAndMergeAllIndices (this->isSorted (), this->isMerged ());
3925 this->makeImportExport (remotePIDs, mustBuildColMap);
3928 this->fillLocalGraph (params);
3930 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
3931 params->get (
"compute global constants",
true);
3932 const bool computeLocalTriangularConstants = params.get () ==
nullptr ||
3933 params->get (
"compute local triangular constants",
true);
3934 if (callComputeGlobalConstants) {
3935 this->computeGlobalConstants (computeLocalTriangularConstants);
3938 this->computeLocalConstants (computeLocalTriangularConstants);
3940 this->fillComplete_ =
true;
3941 this->checkInternalState ();
3945 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3949 const Teuchos::RCP<const map_type>& rangeMap,
3950 const Teuchos::RCP<const import_type>& importer,
3951 const Teuchos::RCP<const export_type>& exporter,
3952 const Teuchos::RCP<Teuchos::ParameterList>& params)
3954 const char tfecfFuncName[] =
"expertStaticFillComplete: ";
3955 #ifdef HAVE_TPETRA_MMM_TIMINGS
3957 if(!params.is_null())
3958 label = params->get(
"Timer Label",label);
3959 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
": ");
3960 using Teuchos::TimeMonitor;
3961 Teuchos::RCP<Teuchos::TimeMonitor> MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Setup"))));
3965 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3966 domainMap.is_null () || rangeMap.is_null (),
3967 std::runtime_error,
"The input domain Map and range Map must be nonnull.");
3968 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3969 pftype_ !=
StaticProfile, std::runtime_error,
"You may not call this "
3970 "method unless the graph is StaticProfile.");
3971 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3972 isFillComplete () || ! hasColMap (), std::runtime_error,
"You may not "
3973 "call this method unless the graph has a column Map.");
3974 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3975 getNodeNumRows () > 0 && k_rowPtrs_.extent (0) == 0,
3976 std::runtime_error,
"The calling process has getNodeNumRows() = "
3977 << getNodeNumRows () <<
" > 0 rows, but the row offsets array has not "
3979 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3980 static_cast<size_t> (k_rowPtrs_.extent (0)) != getNodeNumRows () + 1,
3981 std::runtime_error,
"The row offsets array has length " <<
3982 k_rowPtrs_.extent (0) <<
" != getNodeNumRows()+1 = " <<
3983 (getNodeNumRows () + 1) <<
".");
3998 numAllocForAllRows_ = 0;
3999 k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
4000 indicesAreAllocated_ =
true;
4005 indicesAreLocal_ =
true;
4006 indicesAreGlobal_ =
false;
4009 #ifdef HAVE_TPETRA_MMM_TIMINGS
4010 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Maps"))));
4012 setDomainRangeMaps (domainMap, rangeMap);
4015 indicesAreSorted_ =
true;
4016 noRedundancies_ =
true;
4019 #ifdef HAVE_TPETRA_MMM_TIMINGS
4020 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckI"))));
4023 importer_ = Teuchos::null;
4024 exporter_ = Teuchos::null;
4025 if (importer != Teuchos::null) {
4026 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4027 ! importer->getSourceMap ()->isSameAs (*getDomainMap ()) ||
4028 ! importer->getTargetMap ()->isSameAs (*getColMap ()),
4029 std::invalid_argument,
": importer does not match matrix maps.");
4030 importer_ = importer;
4034 #ifdef HAVE_TPETRA_MMM_TIMINGS
4035 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckE"))));
4038 if (exporter != Teuchos::null) {
4039 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4040 ! exporter->getSourceMap ()->isSameAs (*getRowMap ()) ||
4041 ! exporter->getTargetMap ()->isSameAs (*getRangeMap ()),
4042 std::invalid_argument,
": exporter does not match matrix maps.");
4043 exporter_ = exporter;
4046 #ifdef HAVE_TPETRA_MMM_TIMINGS
4047 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXmake"))));
4049 Teuchos::Array<int> remotePIDs (0);
4050 this->makeImportExport (remotePIDs,
false);
4053 #ifdef HAVE_TPETRA_MMM_TIMINGS
4054 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-fLG"))));
4056 this->fillLocalGraph (params);
4058 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
4059 params->get (
"compute global constants",
true);
4060 const bool computeLocalTriangularConstants = params.get () ==
nullptr ||
4061 params->get (
"compute local triangular constants",
true);
4063 if (callComputeGlobalConstants) {
4064 #ifdef HAVE_TPETRA_MMM_TIMINGS
4065 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (const)"))));
4066 #endif // HAVE_TPETRA_MMM_TIMINGS
4067 this->computeGlobalConstants (computeLocalTriangularConstants);
4070 #ifdef HAVE_TPETRA_MMM_TIMINGS
4071 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (noconst)"))));
4072 #endif // HAVE_TPETRA_MMM_TIMINGS
4073 this->computeLocalConstants (computeLocalTriangularConstants);
4076 fillComplete_ =
true;
4078 #ifdef HAVE_TPETRA_MMM_TIMINGS
4079 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cIS"))));
4081 checkInternalState ();
4085 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4088 fillLocalGraph (
const Teuchos::RCP<Teuchos::ParameterList>& params)
4091 typedef decltype (k_numRowEntries_) row_entries_type;
4092 typedef typename local_graph_type::row_map_type row_map_type;
4093 typedef typename row_map_type::non_const_type non_const_row_map_type;
4094 typedef typename local_graph_type::entries_type::non_const_type lclinds_1d_type;
4095 const char tfecfFuncName[] =
"fillLocalGraph (called from fillComplete or "
4096 "expertStaticFillComplete): ";
4097 const size_t lclNumRows = this->getNodeNumRows ();
4104 non_const_row_map_type ptr_d;
4105 row_map_type ptr_d_const;
4106 lclinds_1d_type ind_d;
4108 bool requestOptimizedStorage =
true;
4109 if (! params.is_null () && ! params->get (
"Optimize Storage",
true)) {
4110 requestOptimizedStorage =
false;
4120 #ifdef HAVE_TPETRA_DEBUG
4121 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4122 (static_cast<size_t> (this->k_numRowEntries_.extent (0)) !=
4123 lclNumRows, std::logic_error,
"(DynamicProfile branch) "
4124 "k_numRowEntries_.extent(0) = " << k_numRowEntries_.extent (0)
4125 <<
" != getNodeNumRows() = " << lclNumRows <<
"");
4126 #endif // HAVE_TPETRA_DEBUG
4135 size_t lclTotalNumEntries = 0;
4138 ptr_d = non_const_row_map_type (
"Tpetra::CrsGraph::ptr", lclNumRows+1);
4139 typename row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
4142 ptr_d_const = ptr_d;
4145 #ifdef HAVE_TPETRA_DEBUG
4146 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4147 (static_cast<size_t> (ptr_d.extent (0)) != lclNumRows + 1,
4148 std::logic_error,
"(DynamicProfile branch) After packing ptr_d, "
4149 "ptr_d.extent(0) = " << ptr_d.extent (0) <<
" != "
4150 "(lclNumRows+1) = " << (lclNumRows+1) <<
".");
4152 const auto valToCheck = ::Tpetra::Details::getEntryOnHost (ptr_d, lclNumRows);
4153 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4154 (valToCheck != lclTotalNumEntries, std::logic_error,
4155 "(DynamicProfile branch) After packing ptr_d, ptr_d(lclNumRows = "
4156 << lclNumRows <<
") = " << valToCheck <<
" != total number of "
4157 "entries on the calling process = " << lclTotalNumEntries <<
".");
4159 #endif // HAVE_TPETRA_DEBUG
4162 ind_d = lclinds_1d_type (
"Tpetra::CrsGraph::ind", lclTotalNumEntries);
4168 auto ptr_h = Kokkos::create_mirror_view (ptr_d);
4170 auto ind_h = Kokkos::create_mirror_view (ind_d);
4173 typename row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
4174 for (
size_t row = 0; row < lclNumRows; ++row) {
4175 const size_t numEnt = numRowEnt_h(row);
4176 std::copy (lclInds2D_[row].begin (),
4177 lclInds2D_[row].begin () + numEnt,
4178 ind_h.data () + ptr_h(row));
4183 #ifdef HAVE_TPETRA_DEBUG
4185 if (ptr_d.extent (0) != 0) {
4186 const size_t numOffsets = static_cast<size_t> (ptr_d.extent (0));
4187 const size_t valToCheck = ::Tpetra::Details::getEntryOnHost (ptr_d, numOffsets - 1);
4188 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4189 (valToCheck != static_cast<size_t> (ind_d.extent (0)),
4190 std::logic_error,
"(DynamicProfile branch) After packing column "
4191 "indices, ptr_d(" << (numOffsets-1) <<
") = " << valToCheck
4192 <<
" != ind_d.extent(0) = " << ind_d.extent (0) <<
".");
4194 #endif // HAVE_TPETRA_DEBUG
4201 #ifdef HAVE_TPETRA_DEBUG
4204 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4205 (k_rowPtrs_.extent (0) == 0, std::logic_error,
4206 "(StaticProfile branch) k_rowPtrs_ has size zero, but shouldn't");
4207 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4208 (k_rowPtrs_.extent (0) != lclNumRows + 1, std::logic_error,
4209 "(StaticProfile branch) k_rowPtrs_.extent(0) = "
4210 << k_rowPtrs_.extent (0) <<
" != (lclNumRows + 1) = "
4211 << (lclNumRows + 1) <<
".");
4213 const size_t numOffsets = k_rowPtrs_.extent (0);
4214 const auto valToCheck =
4215 ::Tpetra::Details::getEntryOnHost (k_rowPtrs_, numOffsets - 1);
4216 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4218 k_lclInds1D_.extent (0) != valToCheck,
4219 std::logic_error,
"(StaticProfile branch) numOffsets = " <<
4220 numOffsets <<
" != 0 and k_lclInds1D_.extent(0) = " <<
4221 k_lclInds1D_.extent (0) <<
" != k_rowPtrs_(" << numOffsets <<
4222 ") = " << valToCheck <<
".");
4224 #endif // HAVE_TPETRA_DEBUG
4226 size_t allocSize = 0;
4228 allocSize = this->getNodeAllocationSize ();
4230 catch (std::logic_error& e) {
4231 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4232 (
true, std::logic_error,
"In fillLocalGraph, getNodeAllocationSize "
4233 "threw std::logic_error: " << e.what ());
4235 catch (std::runtime_error& e) {
4236 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4237 (
true, std::runtime_error,
"In fillLocalGraph, getNodeAllocationSize "
4238 "threw std::runtime_error: " << e.what ());
4240 catch (std::exception& e) {
4241 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4242 (
true, std::runtime_error,
"In fillLocalGraph, getNodeAllocationSize "
4243 "threw std::exception: " << e.what ());
4246 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4247 (
true, std::runtime_error,
"In fillLocalGraph, getNodeAllocationSize "
4248 "threw an exception not a subclass of std::exception.");
4251 if (this->getNodeNumEntries () != allocSize) {
4259 #ifdef HAVE_TPETRA_DEBUG
4260 if (k_rowPtrs_.extent (0) != 0) {
4261 const size_t numOffsets =
4262 static_cast<size_t> (k_rowPtrs_.extent (0));
4263 const auto valToCheck =
4264 ::Tpetra::Details::getEntryOnHost (k_rowPtrs_, numOffsets - 1);
4265 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4266 (valToCheck != static_cast<size_t> (k_lclInds1D_.extent (0)),
4267 std::logic_error,
"(StaticProfile unpacked branch) Before "
4268 "allocating or packing, k_rowPtrs_(" << (numOffsets-1) <<
") = "
4269 << valToCheck <<
" != k_lclInds1D_.extent(0) = "
4270 << k_lclInds1D_.extent (0) <<
".");
4272 #endif // HAVE_TPETRA_DEBUG
4280 size_t lclTotalNumEntries = 0;
4283 ptr_d = non_const_row_map_type (
"Tpetra::CrsGraph::ptr", lclNumRows + 1);
4284 ptr_d_const = ptr_d;
4288 typename row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
4289 #ifdef HAVE_TPETRA_DEBUG
4290 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4291 (static_cast<size_t> (numRowEnt_h.extent (0)) != lclNumRows,
4292 std::logic_error,
"(StaticProfile unpacked branch) "
4293 "numRowEnt_h.extent(0) = " << numRowEnt_h.extent (0)
4294 <<
" != getNodeNumRows() = " << lclNumRows <<
"");
4295 #endif // HAVE_TPETRA_DEBUG
4299 #ifdef HAVE_TPETRA_DEBUG
4300 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4301 (static_cast<size_t> (ptr_d.extent (0)) != lclNumRows + 1,
4302 std::logic_error,
"(StaticProfile unpacked branch) After "
4303 "allocating ptr_d, ptr_d.extent(0) = " << ptr_d.extent (0)
4304 <<
" != lclNumRows+1 = " << (lclNumRows+1) <<
".");
4306 const auto valToCheck = ::Tpetra::Details::getEntryOnHost (ptr_d, lclNumRows);
4307 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4308 (valToCheck != lclTotalNumEntries, std::logic_error,
4309 "Tpetra::CrsGraph::fillLocalGraph: In StaticProfile unpacked "
4310 "branch, after filling ptr_d, ptr_d(lclNumRows=" << lclNumRows
4311 <<
") = " << valToCheck <<
" != total number of entries on "
4312 "the calling process = " << lclTotalNumEntries <<
".");
4314 #endif // HAVE_TPETRA_DEBUG
4318 ind_d = lclinds_1d_type (
"Tpetra::CrsGraph::ind", lclTotalNumEntries);
4330 typedef pack_functor<
4331 typename local_graph_type::entries_type::non_const_type,
4332 row_map_type> inds_packer_type;
4333 inds_packer_type f (ind_d, k_lclInds1D_, ptr_d, k_rowPtrs_);
4335 typedef typename decltype (ind_d)::execution_space exec_space;
4336 typedef Kokkos::RangePolicy<exec_space, LocalOrdinal> range_type;
4337 Kokkos::parallel_for (range_type (0, lclNumRows), f);
4340 #ifdef HAVE_TPETRA_DEBUG
4341 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4342 (ptr_d.extent (0) == 0, std::logic_error,
"(StaticProfile "
4343 "\"Optimize Storage\"=true branch) After packing, "
4344 "ptr_d.extent(0) = 0. This probably means k_rowPtrs_ was "
4345 "never allocated.");
4346 if (ptr_d.extent (0) != 0) {
4347 const size_t numOffsets = static_cast<size_t> (ptr_d.extent (0));
4348 const auto valToCheck = ::Tpetra::Details::getEntryOnHost (ptr_d, numOffsets - 1);
4349 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4350 (static_cast<size_t> (valToCheck) != ind_d.extent (0),
4351 std::logic_error,
"(StaticProfile \"Optimize Storage\"=true "
4352 "branch) After packing, ptr_d(" << (numOffsets-1) <<
") = "
4353 << valToCheck <<
" != ind_d.extent(0) = "
4354 << ind_d.extent (0) <<
".");
4356 #endif // HAVE_TPETRA_DEBUG
4359 ptr_d_const = k_rowPtrs_;
4360 ind_d = k_lclInds1D_;
4362 #ifdef HAVE_TPETRA_DEBUG
4363 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4364 (ptr_d_const.extent (0) == 0, std::logic_error,
"(StaticProfile "
4365 "\"Optimize Storage\"=false branch) ptr_d_const.extent(0) = 0. "
4366 "This probably means that k_rowPtrs_ was never allocated.");
4367 if (ptr_d_const.extent (0) != 0) {
4368 const size_t numOffsets =
4369 static_cast<size_t> (ptr_d_const.extent (0));
4370 const size_t valToCheck =
4371 ::Tpetra::Details::getEntryOnHost (ptr_d_const, numOffsets - 1);
4372 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4373 (valToCheck != static_cast<size_t> (ind_d.extent (0)),
4374 std::logic_error,
"(StaticProfile \"Optimize Storage\"=false "
4375 "branch) ptr_d_const(" << (numOffsets-1) <<
") = " << valToCheck
4376 <<
" != ind_d.extent(0) = " << ind_d.extent (0) <<
".");
4378 #endif // HAVE_TPETRA_DEBUG
4382 #ifdef HAVE_TPETRA_DEBUG
4384 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4385 (static_cast<size_t> (ptr_d_const.extent (0)) != lclNumRows + 1,
4386 std::logic_error,
"After packing, ptr_d_const.extent(0) = " <<
4387 ptr_d_const.extent (0) <<
" != lclNumRows+1 = " << (lclNumRows+1)
4389 if (ptr_d_const.extent (0) != 0) {
4390 const size_t numOffsets = static_cast<size_t> (ptr_d_const.extent (0));
4391 const auto valToCheck = ::Tpetra::Details::getEntryOnHost (ptr_d_const, numOffsets - 1);
4392 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4393 (static_cast<size_t> (valToCheck) != ind_d.extent (0),
4394 std::logic_error,
"After packing, ptr_d_const(" << (numOffsets-1)
4395 <<
") = " << valToCheck <<
" != ind_d.extent(0) = "
4396 << ind_d.extent (0) <<
".");
4398 #endif // HAVE_TPETRA_DEBUG
4400 if (requestOptimizedStorage) {
4406 lclInds2D_ = Teuchos::null;
4407 k_numRowEntries_ = row_entries_type ();
4410 k_rowPtrs_ = ptr_d_const;
4411 k_lclInds1D_ = ind_d;
4416 storageStatus_ = ::Tpetra::Details::STORAGE_1D_PACKED;
4422 lclGraph_ = local_graph_type (ind_d, ptr_d_const);
4432 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4434 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
4435 replaceColMap (
const Teuchos::RCP<const map_type>& newColMap)
4444 const char tfecfFuncName[] =
"replaceColMap: ";
4445 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4446 isLocallyIndexed () || isGloballyIndexed (), std::runtime_error,
4447 "Requires matching maps and non-static graph.");
4448 colMap_ = newColMap;
4451 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4455 const Teuchos::RCP<const import_type>& newImport,
4456 const bool sortIndicesInEachRow)
4458 using Teuchos::REDUCE_MIN;
4459 using Teuchos::reduceAll;
4461 typedef GlobalOrdinal GO;
4462 typedef LocalOrdinal LO;
4463 typedef typename local_graph_type::entries_type::non_const_type col_inds_type;
4464 const char tfecfFuncName[] =
"reindexColumns: ";
4466 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4467 isFillComplete (), std::runtime_error,
"The graph is fill complete "
4468 "(isFillComplete() returns true). You must call resumeFill() before "
4469 "you may call this method.");
4487 const LO lclNumRows = static_cast<LO> (this->getNodeNumRows ());
4502 bool allCurColIndsValid =
true;
4507 bool localSuffices =
true;
4515 typename local_graph_type::entries_type::non_const_type newLclInds1D;
4516 Teuchos::ArrayRCP<Teuchos::Array<LO> > newLclInds2D;
4521 if (indicesAreAllocated ()) {
4522 if (isLocallyIndexed ()) {
4524 const map_type& oldColMap = * (getColMap ());
4527 const size_t allocSize = this->getNodeAllocationSize ();
4528 newLclInds1D = col_inds_type (
"Tpetra::CrsGraph::ind", allocSize);
4530 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
4531 const RowInfo rowInfo = this->getRowInfo (lclRow);
4532 const size_t beg = rowInfo.offset1D;
4533 const size_t end = beg + rowInfo.numEntries;
4534 for (
size_t k = beg; k < end; ++k) {
4537 const LO oldLclCol = k_lclInds1D_(k);
4538 if (oldLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
4539 allCurColIndsValid =
false;
4547 if (gblCol == Teuchos::OrdinalTraits<GO>::invalid ()) {
4548 allCurColIndsValid =
false;
4552 const LO newLclCol = newColMap->getLocalElement (gblCol);
4553 if (newLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
4554 localSuffices =
false;
4559 newLclInds1D(k) = newLclCol;
4568 newLclInds2D = Teuchos::arcp<Teuchos::Array<LO> > (lclNumRows);
4571 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
4572 const RowInfo rowInfo = this->getRowInfo (lclRow);
4573 newLclInds2D.resize (rowInfo.allocSize);
4575 Teuchos::ArrayView<const LO> oldLclRowView = getLocalView (rowInfo);
4576 Teuchos::ArrayView<LO> newLclRowView = (newLclInds2D[lclRow]) ();
4578 for (
size_t k = 0; k < rowInfo.numEntries; ++k) {
4579 const LO oldLclCol = oldLclRowView[k];
4580 if (oldLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
4581 allCurColIndsValid =
false;
4588 if (gblCol == Teuchos::OrdinalTraits<GO>::invalid ()) {
4589 allCurColIndsValid =
false;
4593 const LO newLclCol = newColMap->getLocalElement (gblCol);
4594 if (newLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
4595 localSuffices =
false;
4598 newLclRowView[k] = newLclCol;
4610 allCurColIndsValid =
false;
4627 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
4628 const RowInfo rowInfo = this->getRowInfo (lclRow);
4629 Teuchos::ArrayView<const GO> oldGblRowView = getGlobalView (rowInfo);
4630 for (
size_t k = 0; k < rowInfo.numEntries; ++k) {
4631 const GO gblCol = oldGblRowView[k];
4632 if (! newColMap->isNodeGlobalElement (gblCol)) {
4633 localSuffices =
false;
4643 lclSuccess[0] = allCurColIndsValid ? 1 : 0;
4644 lclSuccess[1] = localSuffices ? 1 : 0;
4648 RCP<const Teuchos::Comm<int> > comm =
4649 getRowMap ().is_null () ? Teuchos::null : getRowMap ()->getComm ();
4650 if (! comm.is_null ()) {
4651 reduceAll<int, int> (*comm, REDUCE_MIN, 2, lclSuccess, gblSuccess);
4654 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4655 gblSuccess[0] == 0, std::runtime_error,
"It is not possible to continue."
4656 " The most likely reason is that the graph is locally indexed, but the "
4657 "column Map is missing (null) on some processes, due to a previous call "
4658 "to replaceColMap().");
4660 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4661 gblSuccess[1] == 0, std::runtime_error,
"On some process, the graph "
4662 "contains column indices that are in the old column Map, but not in the "
4663 "new column Map (on that process). This method does NOT redistribute "
4664 "data; it does not claim to do the work of an Import or Export operation."
4665 " This means that for all processess, the calling process MUST own all "
4666 "column indices, in both the old column Map and the new column Map. In "
4667 "this case, you will need to do an Import or Export operation to "
4668 "redistribute data.");
4671 if (isLocallyIndexed ()) {
4673 k_lclInds1D_ = newLclInds1D;
4675 lclInds2D_ = newLclInds2D;
4683 indicesAreSorted_ =
false;
4684 if (sortIndicesInEachRow) {
4691 const bool sorted =
false;
4692 const bool merged =
true;
4693 this->sortAndMergeAllIndices (sorted, merged);
4696 colMap_ = newColMap;
4698 if (newImport.is_null ()) {
4706 if (! domainMap_.is_null ()) {
4707 if (! domainMap_->isSameAs (* newColMap)) {
4708 importer_ = Teuchos::rcp (
new import_type (domainMap_, newColMap));
4710 importer_ = Teuchos::null;
4715 importer_ = newImport;
4720 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4724 const Teuchos::RCP<const import_type>& newImporter)
4726 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMapAndImporter: ";
4727 TEUCHOS_TEST_FOR_EXCEPTION(
4728 colMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4729 "this method unless the graph already has a column Map.");
4730 TEUCHOS_TEST_FOR_EXCEPTION(
4731 newDomainMap.is_null (), std::invalid_argument,
4732 prefix <<
"The new domain Map must be nonnull.");
4736 if (newImporter.is_null ()) {
4741 const bool colSameAsDom = colMap_->isSameAs (*newDomainMap);
4742 TEUCHOS_TEST_FOR_EXCEPTION
4743 (colSameAsDom, std::invalid_argument,
"If the new Import is null, "
4744 "then the new domain Map must be the same as the current column Map.");
4747 const bool colSameAsTgt =
4748 colMap_->isSameAs (* (newImporter->getTargetMap ()));
4749 const bool newDomSameAsSrc =
4750 newDomainMap->isSameAs (* (newImporter->getSourceMap ()));
4751 TEUCHOS_TEST_FOR_EXCEPTION
4752 (! colSameAsTgt || ! newDomSameAsSrc, std::invalid_argument,
"If the "
4753 "new Import is nonnull, then the current column Map must be the same "
4754 "as the new Import's target Map, and the new domain Map must be the "
4755 "same as the new Import's source Map.");
4759 domainMap_ = newDomainMap;
4760 importer_ = Teuchos::rcp_const_cast<import_type> (newImporter);
4763 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4771 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4776 using ::Tpetra::Details::ProfilingRegion;
4777 using Teuchos::ArrayView;
4778 using Teuchos::outArg;
4779 using Teuchos::reduceAll;
4782 ProfilingRegion regionCGC (
"Tpetra::CrsGraph::computeGlobalConstants");
4784 this->computeLocalConstants (computeLocalTriangularConstants);
4789 if (! this->haveGlobalConstants_) {
4790 const Teuchos::Comm<int>& comm = * (this->getComm ());
4804 lcl[0] = static_cast<GST> (this->getNodeNumEntries ());
4813 lcl[1] = computeLocalTriangularConstants ?
4814 static_cast<GST> (this->nodeNumDiags_) :
4815 static_cast<GST> (0);
4817 reduceAll<int,GST> (comm, Teuchos::REDUCE_SUM, 2, lcl, gbl);
4818 this->globalNumEntries_ = gbl[0];
4823 this->globalNumDiags_ = computeLocalTriangularConstants ?
4825 Teuchos::OrdinalTraits<GST>::invalid ();
4827 const GST lclMaxNumRowEnt = static_cast<GST> (this->nodeMaxNumRowEntries_);
4828 reduceAll<int, GST> (comm, Teuchos::REDUCE_MAX, lclMaxNumRowEnt,
4829 outArg (this->globalMaxNumRowEntries_));
4830 this->haveGlobalConstants_ =
true;
4835 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4841 using ::Tpetra::Details::ProfilingRegion;
4843 ProfilingRegion regionCLC (
"Tpetra::CrsGraph::computeLocalConstants");
4844 if (this->haveLocalConstants_) {
4849 this->lowerTriangular_ =
false;
4850 this->upperTriangular_ =
false;
4851 this->nodeMaxNumRowEntries_ = Teuchos::OrdinalTraits<size_t>::invalid ();
4852 this->nodeNumDiags_ = Teuchos::OrdinalTraits<size_t>::invalid ();
4854 if (computeLocalTriangularConstants) {
4855 const bool hasRowAndColumnMaps =
4856 this->rowMap_.get () !=
nullptr && this->colMap_.get () !=
nullptr;
4857 if (hasRowAndColumnMaps) {
4858 auto lclRowMap = this->rowMap_->getLocalMap ();
4859 auto lclColMap = this->colMap_->getLocalMap ();
4864 execution_space::fence ();
4867 constexpr
bool ignoreMapsForTriStruct =
true;
4870 lclColMap, ignoreMapsForTriStruct);
4871 this->lowerTriangular_ = result.couldBeLowerTriangular;
4872 this->upperTriangular_ = result.couldBeUpperTriangular;
4873 this->nodeMaxNumRowEntries_ = result.maxNumRowEnt;
4874 this->nodeNumDiags_ = result.diagCount;
4877 this->nodeMaxNumRowEntries_ = 0;
4878 this->nodeNumDiags_ = 0;
4886 execution_space::fence ();
4888 auto ptr = this->lclGraph_.row_map;
4889 const LO lclNumRows = ptr.extent(0) == 0 ?
4890 static_cast<LO> (0) :
4891 (static_cast<LO> (ptr.extent(0)) - static_cast<LO> (1));
4893 const LO lclMaxNumRowEnt =
4894 ::Tpetra::Details::maxDifference (
"Tpetra::CrsGraph: nodeMaxNumRowEntries",
4896 this->nodeMaxNumRowEntries_ = static_cast<size_t> (lclMaxNumRowEnt);
4898 this->haveLocalConstants_ =
true;
4902 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4903 std::pair<size_t, std::string>
4907 using ::Tpetra::Details::ProfilingRegion;
4908 using Teuchos::arcp;
4909 using Teuchos::Array;
4911 typedef LocalOrdinal LO;
4912 typedef GlobalOrdinal GO;
4914 typedef typename local_graph_type::row_map_type::non_const_value_type offset_type;
4915 typedef decltype (k_numRowEntries_) row_entries_type;
4916 typedef typename row_entries_type::non_const_value_type num_ent_type;
4917 typedef typename local_graph_type::entries_type::non_const_type
4919 typedef Kokkos::View<GO*,
typename lcl_col_inds_type::array_layout,
4921 const char tfecfFuncName[] =
"makeIndicesLocal: ";
4922 ProfilingRegion regionMakeIndicesLocal (
"Tpetra::CrsGraph::makeIndicesLocal");
4926 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4927 (! this->hasColMap (), std::logic_error,
"The graph does not have a "
4928 "column Map yet. This method should never be called in that case. "
4929 "Please report this bug to the Tpetra developers.");
4930 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4931 (this->getColMap ().is_null (), std::logic_error,
"The graph claims "
4932 "that it has a column Map, because hasColMap() returns true. However, "
4933 "the result of getColMap() is null. This should never happen. Please "
4934 "report this bug to the Tpetra developers.");
4939 size_t lclNumErrs = 0;
4940 std::ostringstream errStrm;
4942 const LO lclNumRows = static_cast<LO> (this->getNodeNumRows ());
4943 const map_type& colMap = * (this->getColMap ());
4945 if (this->isGloballyIndexed () && lclNumRows != 0) {
4947 typename row_entries_type::const_type h_numRowEnt =
4948 this->k_numRowEntries_;
4955 constexpr
bool LO_GO_same = std::is_same<LO, GO>::value;
4960 k_lclInds1D_ = Kokkos::Impl::if_c<LO_GO_same,
4962 lcl_col_inds_type>::select (k_gblInds1D_, k_lclInds1D_);
4965 if (k_rowPtrs_.extent (0) == 0) {
4966 errStrm <<
"k_rowPtrs_.extent(0) == 0. This should never "
4967 "happen here. Please report this bug to the Tpetra developers."
4970 return std::make_pair (Tpetra::Details::OrdinalTraits<size_t>::invalid (),
4973 const auto numEnt = ::Tpetra::Details::getEntryOnHost (k_rowPtrs_, lclNumRows);
4982 using Kokkos::view_alloc;
4983 using Kokkos::WithoutInitializing;
4993 const std::string label (
"Tpetra::CrsGraph::lclind");
4995 lcl_col_inds_type (view_alloc (label, WithoutInitializing), numEnt);
5006 auto k_numRowEnt = Kokkos::create_mirror_view (
device_type (), h_numRowEnt);
5010 convertColumnIndicesFromGlobalToLocal<LO, GO, DT, offset_type, num_ent_type> (k_lclInds1D_,
5015 if (lclNumErrs != 0) {
5016 const int myRank = [
this] () {
5017 auto map = this->getMap ();
5018 if (map.is_null ()) {
5022 auto comm = map->getComm ();
5023 return comm.is_null () ? 0 : comm->getRank ();
5026 const bool pluralNumErrs = (lclNumErrs != static_cast<size_t> (1));
5027 errStrm <<
"(Process " << myRank <<
") When converting column "
5028 "indices from global to local, we encountered " << lclNumErrs
5029 <<
" ind" << (pluralNumErrs ?
"ices" :
"ex")
5030 <<
" that do" << (pluralNumErrs ?
"es" :
"")
5031 <<
" not live in the column Map on this process." << endl;
5037 k_gblInds1D_ = gbl_col_inds_type ();
5043 Teuchos::ArrayRCP<Teuchos::Array<LO> > lclInds2D (lclNumRows);
5044 Teuchos::ArrayRCP<Teuchos::Array<GO> > gblInds2D = this->gblInds2D_;
5048 typedef typename Kokkos::View<LO*, device_type>::HostMirror::execution_space
5049 host_execution_space;
5050 typedef Kokkos::RangePolicy<host_execution_space, LO> range_type;
5051 Kokkos::parallel_reduce (
5052 "Tpetra::CrsGraph::makeIndicesLocal (DynamicProfile)",
5053 range_type (0, lclNumRows),
5054 [&gblInds2D, &h_numRowEnt, &lclInds2D, &colMap] (
const LO& lclRow,
size_t& numErrs) {
5055 const GO*
const curGblInds = gblInds2D[lclRow].getRawPtr ();
5059 const LO rna = static_cast<LO> (gblInds2D[lclRow].size ());
5060 const LO numEnt = static_cast<LO> (h_numRowEnt(lclRow));
5061 lclInds2D[lclRow].resize (rna);
5062 LO*
const curLclInds = lclInds2D[lclRow].getRawPtr ();
5063 for (LO j = 0; j < numEnt; ++j) {
5064 const GO gid = curGblInds[j];
5066 curLclInds[j] = lid;
5067 if (lid == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
5073 this->lclInds2D_ = lclInds2D;
5078 if (lclNumErrs != 0) {
5079 const int myRank = [
this] () {
5080 auto map = this->getMap ();
5081 if (map.is_null ()) {
5085 auto comm = map->getComm ();
5086 return comm.is_null () ? 0 : comm->getRank ();
5091 constexpr
size_t tooManyErrsToPrint = 200;
5092 if (lclNumErrs > tooManyErrsToPrint) {
5093 errStrm <<
"(Process " << myRank <<
") When converting column "
5094 "indices from global to local, we encountered " << lclNumErrs
5095 <<
" indices that do not live in the column Map on this "
5096 "process. That's too many to print." << endl;
5101 std::map<LO, std::vector<GO> > badColInds;
5104 std::vector<LO> badLclRows;
5106 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
5107 const size_t numEnt = static_cast<size_t> (h_numRowEnt[lclRow]);
5109 Teuchos::ArrayView<const GO> curGblInds = gblInds2D_[lclRow] ();
5110 if (numEnt > static_cast<size_t> (curGblInds.size ())) {
5111 badLclRows.push_back (lclRow);
5114 for (
size_t j = 0; j < numEnt; ++j) {
5115 const GO gid = curGblInds[j];
5117 if (lid == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
5118 badColInds[lclRow].push_back (gid);
5124 const bool pluralNumErrs = (lclNumErrs != static_cast<size_t> (1));
5125 errStrm <<
"(Process " << myRank <<
") When converting column "
5126 "indices from global to local, we encountered " << lclNumErrs
5127 <<
" ind" << (pluralNumErrs ?
"ices" :
"ex") <<
" that "
5128 "do" << (pluralNumErrs ?
"es" :
"")
5129 <<
" not live in the column Map on this process." << endl
5130 <<
"(Process " << myRank <<
") Here are the bad global "
5131 "indices, listed by local row: " << endl;
5132 for (
auto && eachPair : badColInds) {
5133 const LO lclRow = eachPair.first;
5134 const GO gblRow = rowMap_->getGlobalElement (lclRow);
5135 errStrm <<
"(Process " << myRank <<
") Local row " << lclRow
5136 <<
" (global row " << gblRow <<
"): [";
5137 const size_t numBad = eachPair.second.size ();
5138 for (
size_t k = 0; k < numBad; ++k) {
5139 errStrm << eachPair.second[k];
5140 if (k +
size_t (1) < numBad) {
5144 errStrm <<
"]" << endl;
5147 if (badLclRows.size () != 0) {
5148 if (lclNumErrs == 0) {
5152 lclNumErrs = badLclRows.size ();
5155 errStrm <<
"(Process " << myRank <<
") When converting column "
5156 "indices from global to local, we (also) encountered the "
5157 "following local rows lclRow on this process for which "
5158 "h_numRowEnt[lclRow] > gblInds2D_[lclRow].size(). This "
5159 "likely indicates a bug in Tpetra." << endl
5160 <<
"(Process " << myRank <<
") [";
5161 const size_t numBad = badLclRows.size ();
5162 for (
size_t k = 0; k < numBad; ++k) {
5163 const LO lclRow = badLclRows[k];
5164 errStrm <<
"{lclRow: " << lclRow
5165 <<
"h_numRowEnt[lclRow]: " << h_numRowEnt[lclRow]
5166 <<
"gblInds2D_[lclRow].size(): "
5167 << gblInds2D_[lclRow].size () <<
"}";
5168 if (k +
size_t (1) < numBad) {
5172 errStrm <<
"]" << endl;
5177 this->gblInds2D_ = Teuchos::null;
5182 this->indicesAreLocal_ =
true;
5183 this->indicesAreGlobal_ =
false;
5184 this->checkInternalState ();
5186 return std::make_pair (lclNumErrs, errStrm.str ());
5190 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5195 using ::Tpetra::Details::ProfilingRegion;
5196 ProfilingRegion regionSortAndMerge (
"Tpetra::CrsGraph::makeColMap");
5204 Teuchos::RCP<const map_type> colMap = this->colMap_;
5205 const bool sortEachProcsGids =
5206 this->sortGhostsAssociatedWithEachProcessor_;
5216 using Teuchos::outArg;
5217 using Teuchos::REDUCE_MIN;
5218 using Teuchos::reduceAll;
5219 const char tfecfFuncName[] =
"makeColMap: ";
5221 std::ostringstream errStrm;
5222 const int lclErrCode =
5224 *
this, sortEachProcsGids, &errStrm);
5225 auto comm = this->getComm ();
5226 if (! comm.is_null ()) {
5227 const int lclSuccess = (lclErrCode == 0) ? 1 : 0;
5229 reduceAll<int, int> (*comm, REDUCE_MIN, lclSuccess,
5230 outArg (gblSuccess));
5231 if (gblSuccess != 1) {
5232 std::ostringstream os;
5234 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5235 (
true, std::runtime_error,
"An error happened on at least one "
5236 "(MPI) process in the CrsGraph's communicator. Here are all "
5237 "processes' error messages:" << std::endl << os.str ());
5243 *
this, sortEachProcsGids, NULL);
5248 this->colMap_ = colMap;
5250 checkInternalState ();
5254 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5259 using ::Tpetra::Details::ProfilingRegion;
5260 typedef LocalOrdinal LO;
5261 typedef typename Kokkos::View<LO*, device_type>::HostMirror::execution_space
5262 host_execution_space;
5263 typedef Kokkos::RangePolicy<host_execution_space, LO> range_type;
5264 const char tfecfFuncName[] =
"sortAndMergeAllIndices: ";
5265 ProfilingRegion regionSortAndMerge (
"Tpetra::CrsGraph::sortAndMergeAllIndices");
5267 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5268 (this->isGloballyIndexed (), std::logic_error,
5269 "This method may only be called after makeIndicesLocal." );
5271 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5272 (! merged && this->isStorageOptimized (), std::logic_error,
5273 "The graph is already storage optimized, so we shouldn't be merging any "
5274 "indices. Please report this bug to the Tpetra developers.");
5276 if (! sorted || ! merged) {
5277 const LO lclNumRows = static_cast<LO> (this->getNodeNumRows ());
5278 size_t totalNumDups = 0;
5280 Kokkos::parallel_reduce (range_type (0, lclNumRows),
5281 [
this, sorted, merged] (
const LO& lclRow,
size_t& numDups) {
5282 const RowInfo rowInfo = this->getRowInfo (lclRow);
5283 numDups += this->sortAndMergeRowIndices (rowInfo, sorted, merged);
5285 this->indicesAreSorted_ =
true;
5286 this->noRedundancies_ =
true;
5291 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5293 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5294 makeImportExport (Teuchos::Array<int>& remotePIDs,
5295 const bool useRemotePIDs)
5297 using ::Tpetra::Details::ProfilingRegion;
5298 using Teuchos::ParameterList;
5301 const char tfecfFuncName[] =
"makeImportExport: ";
5302 ProfilingRegion regionMIE (
"Tpetra::CrsGraph::makeImportExport");
5304 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5305 (! this->hasColMap (), std::logic_error,
5306 "This method may not be called unless the graph has a column Map.");
5307 RCP<ParameterList> params = this->getNonconstParameterList ();
5316 if (importer_.is_null ()) {
5318 if (domainMap_ != colMap_ && (! domainMap_->isSameAs (*colMap_))) {
5319 if (params.is_null () || ! params->isSublist (
"Import")) {
5320 if (useRemotePIDs) {
5321 importer_ = rcp (
new import_type (domainMap_, colMap_, remotePIDs));
5324 importer_ = rcp (
new import_type (domainMap_, colMap_));
5328 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
5329 if (useRemotePIDs) {
5330 RCP<import_type> newImp =
5331 rcp (
new import_type (domainMap_, colMap_, remotePIDs));
5332 newImp->setParameterList (importSublist);
5336 importer_ = rcp (
new import_type (domainMap_, colMap_, importSublist));
5344 if (exporter_.is_null ()) {
5346 if (rangeMap_ != rowMap_ && ! rangeMap_->isSameAs (*rowMap_)) {
5347 if (params.is_null () || ! params->isSublist (
"Export")) {
5348 exporter_ = rcp (
new export_type (rowMap_, rangeMap_));
5351 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
5352 exporter_ = rcp (
new export_type (rowMap_, rangeMap_, exportSublist));
5359 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5364 std::ostringstream oss;
5365 oss << dist_object_type::description ();
5366 if (isFillComplete ()) {
5367 oss <<
"{status = fill complete"
5368 <<
", global rows = " << getGlobalNumRows()
5369 <<
", global cols = " << getGlobalNumCols()
5370 <<
", global num entries = " << getGlobalNumEntries()
5374 oss <<
"{status = fill not complete"
5375 <<
", global rows = " << getGlobalNumRows()
5382 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5386 const Teuchos::EVerbosityLevel verbLevel)
const
5388 using Teuchos::ArrayView;
5389 using Teuchos::Comm;
5391 using Teuchos::VERB_DEFAULT;
5392 using Teuchos::VERB_NONE;
5393 using Teuchos::VERB_LOW;
5394 using Teuchos::VERB_MEDIUM;
5395 using Teuchos::VERB_HIGH;
5396 using Teuchos::VERB_EXTREME;
5400 Teuchos::EVerbosityLevel vl = verbLevel;
5401 if (vl == VERB_DEFAULT) vl = VERB_LOW;
5402 RCP<const Comm<int> > comm = this->getComm();
5403 const int myImageID = comm->getRank(),
5404 numImages = comm->getSize();
5406 for (
size_t dec=10; dec<getGlobalNumRows(); dec *= 10) {
5409 width = std::max<size_t> (width, static_cast<size_t> (11)) + 2;
5410 Teuchos::OSTab tab (out);
5418 if (vl != VERB_NONE) {
5419 if (myImageID == 0) out << this->description() << std::endl;
5421 if (isFillComplete() && myImageID == 0) {
5422 out <<
"Global number of diagonals = " << globalNumDiags_ << std::endl;
5423 out <<
"Global max number of row entries = " << globalMaxNumRowEntries_ << std::endl;
5426 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
5427 if (myImageID == 0) out <<
"\nRow map: " << std::endl;
5428 rowMap_->describe(out,vl);
5429 if (colMap_ != Teuchos::null) {
5430 if (myImageID == 0) out <<
"\nColumn map: " << std::endl;
5431 colMap_->describe(out,vl);
5433 if (domainMap_ != Teuchos::null) {
5434 if (myImageID == 0) out <<
"\nDomain map: " << std::endl;
5435 domainMap_->describe(out,vl);
5437 if (rangeMap_ != Teuchos::null) {
5438 if (myImageID == 0) out <<
"\nRange map: " << std::endl;
5439 rangeMap_->describe(out,vl);
5443 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
5444 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
5445 if (myImageID == imageCtr) {
5446 out <<
"Node ID = " << imageCtr << std::endl
5447 <<
"Node number of entries = " << this->getNodeNumEntries () << std::endl
5448 <<
"Node number of diagonals = " << nodeNumDiags_ << std::endl
5449 <<
"Node max number of entries = " << nodeMaxNumRowEntries_ << std::endl;
5450 if (! indicesAreAllocated ()) {
5451 out <<
"Indices are not allocated." << std::endl;
5460 if (vl == VERB_HIGH || vl == VERB_EXTREME) {
5461 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
5462 if (myImageID == imageCtr) {
5463 out << std::setw(width) <<
"Node ID"
5464 << std::setw(width) <<
"Global Row"
5465 << std::setw(width) <<
"Num Entries";
5466 if (vl == VERB_EXTREME) {
5470 const LocalOrdinal lclNumRows =
5471 static_cast<LocalOrdinal> (this->getNodeNumRows ());
5472 for (LocalOrdinal r=0; r < lclNumRows; ++r) {
5473 const RowInfo rowinfo = this->getRowInfo (r);
5474 GlobalOrdinal gid = rowMap_->getGlobalElement(r);
5475 out << std::setw(width) << myImageID
5476 << std::setw(width) << gid
5477 << std::setw(width) << rowinfo.numEntries;
5478 if (vl == VERB_EXTREME) {
5480 if (isGloballyIndexed()) {
5481 ArrayView<const GlobalOrdinal> rowview = getGlobalView(rowinfo);
5482 for (
size_t j=0; j < rowinfo.numEntries; ++j) out << rowview[j] <<
" ";
5484 else if (isLocallyIndexed()) {
5485 ArrayView<const LocalOrdinal> rowview = getLocalView(rowinfo);
5486 for (
size_t j=0; j < rowinfo.numEntries; ++j) out << colMap_->getGlobalElement(rowview[j]) <<
" ";
5501 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5513 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5518 const Teuchos::ArrayView<const LocalOrdinal> &permuteToLIDs,
5519 const Teuchos::ArrayView<const LocalOrdinal> &permuteFromLIDs)
5521 using Teuchos::Array;
5522 using Teuchos::ArrayView;
5523 typedef LocalOrdinal LO;
5524 typedef GlobalOrdinal GO;
5525 const char tfecfFuncName[] =
"copyAndPermute";
5529 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
5530 permuteToLIDs.size() != permuteFromLIDs.size(), std::runtime_error,
5531 ": permuteToLIDs and permuteFromLIDs must have the same size.");
5545 const row_graph_type* srcRowGraph = dynamic_cast<const row_graph_type*> (&source);
5546 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
5547 srcRowGraph == NULL, std::invalid_argument,
5548 ": The source object must be a RowGraph with matching first three "
5549 "template parameters.");
5554 const this_type* srcCrsGraph = dynamic_cast<const this_type*> (&source);
5556 const map_type& srcRowMap = * (srcRowGraph->getRowMap ());
5557 const map_type& tgtRowMap = * (this->getRowMap ());
5558 const bool src_filled = srcRowGraph->isFillComplete ();
5565 if (src_filled || srcCrsGraph == NULL) {
5571 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
5573 size_t row_length = srcRowGraph->getNumEntriesInGlobalRow (gid);
5574 row_copy.resize (row_length);
5575 size_t check_row_length = 0;
5576 srcRowGraph->getGlobalRowCopy (gid, row_copy (), check_row_length);
5577 this->insertGlobalIndices (gid, row_copy ());
5580 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
5582 ArrayView<const GO> row;
5583 srcCrsGraph->getGlobalRowView (gid, row);
5584 this->insertGlobalIndices (gid, row);
5591 if (src_filled || srcCrsGraph == NULL) {
5592 for (LO i = 0; i < permuteToLIDs.size (); ++i) {
5595 size_t row_length = srcRowGraph->getNumEntriesInGlobalRow (srcgid);
5596 row_copy.resize (row_length);
5597 size_t check_row_length = 0;
5598 srcRowGraph->getGlobalRowCopy (srcgid, row_copy (), check_row_length);
5599 this->insertGlobalIndices (mygid, row_copy ());
5602 for (LO i = 0; i < permuteToLIDs.size (); ++i) {
5605 ArrayView<const GO> row;
5606 srcCrsGraph->getGlobalRowView (srcgid, row);
5607 this->insertGlobalIndices (mygid, row);
5613 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5617 const Teuchos::ArrayView<const LocalOrdinal> &exportLIDs,
5618 Teuchos::Array<GlobalOrdinal> &exports,
5619 const Teuchos::ArrayView<size_t> & numPacketsPerLID,
5620 size_t& constantNumPackets,
5625 const char tfecfFuncName[] =
"packAndPrepare: ";
5626 ProfilingRegion regionPackAndPrepare (
"Tpetra::CrsGraph::packAndPrepare");
5628 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5629 (exportLIDs.size () != numPacketsPerLID.size (), std::runtime_error,
5630 "exportLIDs.size() = " << exportLIDs.size ()
5631 <<
" != numPacketsPerLID.size() = " << numPacketsPerLID.size () <<
".");
5632 const row_graph_type& srcGraph = dynamic_cast<const row_graph_type&> (source);
5637 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5638 (this->isFillComplete (), std::runtime_error,
5639 "The target graph of an Import or Export must not be fill complete.");
5640 srcGraph.pack (exportLIDs, exports, numPacketsPerLID,
5641 constantNumPackets, distor);
5645 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5648 pack (
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
5649 Teuchos::Array<GlobalOrdinal>& exports,
5650 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
5651 size_t& constantNumPackets,
5654 typedef LocalOrdinal LO;
5655 typedef GlobalOrdinal GO;
5656 typedef typename Kokkos::View<
size_t*,
5657 device_type>::HostMirror::execution_space host_execution_space;
5658 typedef typename device_type::execution_space device_execution_space;
5659 const char tfecfFuncName[] =
"pack: ";
5660 constexpr
bool debug =
false;
5661 const int myRank = debug ? this->getMap ()->
getComm ()->getRank () : 0;
5663 const auto numExportLIDs = exportLIDs.size ();
5665 std::ostringstream os;
5666 os <<
"Proc " << myRank <<
": CrsGraph::pack: numExportLIDs = "
5667 << numExportLIDs << std::endl;
5668 std::cerr << os.str ();
5670 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5671 (numExportLIDs != numPacketsPerLID.size (), std::runtime_error,
5672 "exportLIDs.size() = " << numExportLIDs <<
" != numPacketsPerLID.size()"
5673 " = " << numPacketsPerLID.size () <<
".");
5677 device_execution_space::fence ();
5679 const map_type& rowMap = * (this->getRowMap ());
5680 const map_type*
const colMapPtr = this->colMap_.getRawPtr ();
5681 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5682 (this->isLocallyIndexed () && colMapPtr == NULL, std::logic_error,
5683 "This graph claims to be locally indexed, but its column Map is NULL. "
5684 "This should never happen. Please report this bug to the Tpetra "
5688 constantNumPackets = 0;
5692 size_t*
const numPacketsPerLID_raw = numPacketsPerLID.getRawPtr ();
5693 const LO*
const exportLIDs_raw = exportLIDs.getRawPtr ();
5700 Kokkos::RangePolicy<host_execution_space, LO> inputRange (0, numExportLIDs);
5701 size_t totalNumPackets = 0;
5702 size_t errCount = 0;
5705 typedef Kokkos::Device<host_execution_space, Kokkos::HostSpace>
5707 Kokkos::View<size_t, host_device_type> errCountView (&errCount);
5708 constexpr
size_t ONE = 1;
5710 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::pack: totalNumPackets",
5712 [=] (
const LO& i,
size_t& curTotalNumPackets) {
5714 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
5715 Kokkos::atomic_add (&errCountView(), ONE);
5716 numPacketsPerLID_raw[i] = 0;
5719 const size_t numEnt = this->getNumEntriesInGlobalRow (gblRow);
5720 numPacketsPerLID_raw[i] = numEnt;
5721 curTotalNumPackets += numEnt;
5727 std::ostringstream os;
5728 os <<
"Proc " << myRank <<
": CrsGraph::pack: "
5729 <<
"totalNumPackets = " << totalNumPackets << std::endl;
5730 std::cerr << os.str ();
5732 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5733 (errCount != 0, std::logic_error,
"totalNumPackets count encountered "
5734 "one or more errors! errCount = " << errCount
5735 <<
", totalNumPackets = " << totalNumPackets <<
".");
5739 exports.resize (totalNumPackets);
5741 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5742 (! this->supportsRowViews (), std::logic_error,
5743 "this->supportsRowViews() returns false; this should never happen. "
5744 "Please report this bug to the Tpetra developers.");
5750 std::ostringstream os;
5751 os <<
"Proc " << myRank <<
": CrsGraph::pack: pack into exports" << std::endl;
5752 std::cerr << os.str ();
5757 GO*
const exports_raw = exports.getRawPtr ();
5759 Kokkos::parallel_scan (
"Tpetra::CrsGraph::pack: pack from views",
5761 [=] (
const LO& i,
size_t& exportsOffset,
const bool final) {
5762 const size_t curOffset = exportsOffset;
5764 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (gblRow);
5766 if (rowInfo.localRow == Tpetra::Details::OrdinalTraits<size_t>::invalid ()) {
5768 std::ostringstream os;
5769 os <<
"Proc " << myRank <<
": INVALID rowInfo: "
5770 <<
"i = " << i <<
", lclRow = " << exportLIDs_raw[i] << std::endl;
5771 std::cerr << os.str ();
5773 Kokkos::atomic_add (&errCountView(), ONE);
5775 else if (curOffset + rowInfo.numEntries > totalNumPackets) {
5777 std::ostringstream os;
5778 os <<
"Proc " << myRank <<
": UH OH! For i=" << i <<
", lclRow="
5779 << exportLIDs_raw[i] <<
", gblRow=" << gblRow <<
", curOffset "
5780 "(= " << curOffset <<
") + numEnt (= " << rowInfo.numEntries
5781 <<
") > totalNumPackets (= " << totalNumPackets <<
")."
5783 std::cerr << os.str ();
5785 Kokkos::atomic_add (&errCountView(), ONE);
5788 const LO numEnt = static_cast<LO> (rowInfo.numEntries);
5789 if (this->isLocallyIndexed ()) {
5790 const LO* lclColInds = NULL;
5793 this->getLocalViewRawConst (lclColInds, capacity, rowInfo);
5796 for (LO k = 0; k < numEnt; ++k) {
5797 const LO lclColInd = lclColInds[k];
5802 exports_raw[curOffset + k] = gblColInd;
5805 exportsOffset = curOffset + numEnt;
5808 Kokkos::atomic_add (&errCountView(), ONE);
5811 else if (this->isGloballyIndexed ()) {
5812 const GO* gblColInds = NULL;
5815 this->getGlobalViewRawConst (gblColInds, capacity, rowInfo);
5818 for (LO k = 0; k < numEnt; ++k) {
5819 const GO gblColInd = gblColInds[k];
5823 exports_raw[curOffset + k] = gblColInd;
5826 exportsOffset = curOffset + numEnt;
5829 Kokkos::atomic_add (&errCountView(), ONE);
5840 device_execution_space::fence ();
5842 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5843 (errCount != 0, std::logic_error,
"Packing encountered "
5844 "one or more errors! errCount = " << errCount
5845 <<
", totalNumPackets = " << totalNumPackets <<
".");
5849 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5852 unpackAndCombine (
const Teuchos::ArrayView<const LocalOrdinal> &importLIDs,
5853 const Teuchos::ArrayView<const GlobalOrdinal> &imports,
5854 const Teuchos::ArrayView<size_t> &numPacketsPerLID,
5855 size_t constantNumPackets,
5859 typedef LocalOrdinal LO;
5860 typedef GlobalOrdinal GO;
5879 const char tfecfFuncName[] =
"unpackAndCombine: ";
5880 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
5881 importLIDs.size() != numPacketsPerLID.size(), std::runtime_error,
5882 "importLIDs and numPacketsPerLID must have the same size.");
5883 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
5884 isFillComplete (), std::runtime_error,
5885 "Import or Export operations are not allowed on the destination "
5886 "CrsGraph if it is fill complete.");
5888 const map_type& rowMap = * (this->rowMap_);
5889 const size_t numImportLIDs = static_cast<size_t> (importLIDs.size ());
5890 size_t importsOffset = 0;
5891 for (
size_t i = 0; i < numImportLIDs; ++i) {
5892 const LO lclRow = importLIDs[i];
5893 const GO gblRow = rowMap.getGlobalElement (lclRow);
5894 const LO numEnt = numPacketsPerLID[i];
5895 const GO*
const gblColInds = (numEnt == 0) ? NULL : &imports[importsOffset];
5896 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
5898 this->insertGlobalIndicesIntoNonownedRows (gblRow, gblColInds, numEnt);
5901 this->insertGlobalIndicesFiltered (lclRow, gblColInds, numEnt);
5903 importsOffset += numEnt;
5908 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5913 using Teuchos::Comm;
5914 using Teuchos::null;
5915 using Teuchos::ParameterList;
5921 RCP<const map_type> rowMap, domainMap, rangeMap, colMap;
5922 RCP<import_type> importer;
5923 RCP<export_type> exporter;
5926 RCP<const Comm<int> > newComm =
5927 (newMap.is_null ()) ?
null : newMap->getComm ();
5929 if (! domainMap_.is_null ()) {
5930 if (domainMap_.getRawPtr () == rowMap_.getRawPtr ()) {
5937 domainMap = domainMap_->replaceCommWithSubset (newComm);
5940 if (! rangeMap_.is_null ()) {
5941 if (rangeMap_.getRawPtr () == rowMap_.getRawPtr ()) {
5948 rangeMap = rangeMap_->replaceCommWithSubset (newComm);
5951 if (! colMap.is_null ()) {
5952 colMap = colMap_->replaceCommWithSubset (newComm);
5956 if (! newComm.is_null ()) {
5957 RCP<ParameterList> params = this->getNonconstParameterList ();
5965 if (! rangeMap_.is_null () &&
5966 rangeMap != rowMap &&
5967 ! rangeMap->isSameAs (*rowMap)) {
5968 if (params.is_null () || ! params->isSublist (
"Export")) {
5969 exporter = rcp (
new export_type (rowMap, rangeMap));
5972 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
5973 exporter = rcp (
new export_type (rowMap, rangeMap, exportSublist));
5977 if (! domainMap_.is_null () &&
5978 domainMap != colMap &&
5979 ! domainMap->isSameAs (*colMap)) {
5980 if (params.is_null () || ! params->isSublist (
"Import")) {
5981 importer = rcp (
new import_type (domainMap, colMap));
5983 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
5984 importer = rcp (
new import_type (domainMap, colMap, importSublist));
5992 exporter_ = exporter;
5993 importer_ = importer;
6000 this->map_ = rowMap;
6001 domainMap_ = domainMap;
6002 rangeMap_ = rangeMap;
6006 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6011 typedef LocalOrdinal LO;
6012 typedef GlobalOrdinal GO;
6013 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6015 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6016 (! hasColMap (), std::runtime_error,
"The graph must have a column Map.");
6017 const LO lclNumRows = static_cast<LO> (this->getNodeNumRows ());
6018 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6019 (static_cast<LO> (offsets.extent (0)) < lclNumRows,
6020 std::invalid_argument,
"offsets.extent(0) = " <<
6021 offsets.extent (0) <<
" < getNodeNumRows() = " << lclNumRows <<
".");
6023 const map_type& rowMap = * (this->getRowMap ());
6024 const map_type& colMap = * (this->getColMap ());
6026 #ifdef HAVE_TPETRA_DEBUG
6027 bool allRowMapDiagEntriesInColMap =
true;
6028 bool allDiagEntriesFound =
true;
6029 bool allOffsetsCorrect =
true;
6030 bool noOtherWeirdness =
true;
6031 std::vector<std::pair<LO, size_t> > wrongOffsets;
6032 #endif // HAVE_TPETRA_DEBUG
6043 const bool sorted = this->isSorted ();
6044 if (isFillComplete ()) {
6045 auto lclGraph = this->getLocalGraph ();
6046 ::Tpetra::Details::getGraphDiagOffsets (offsets, lclRowMap, lclColMap,
6048 lclGraph.entries, sorted);
6054 auto offsets_h = Kokkos::create_mirror_view (offsets);
6056 for (LO lclRowInd = 0; lclRowInd < lclNumRows; ++lclRowInd) {
6060 const GO gblRowInd = lclRowMap.getGlobalElement (lclRowInd);
6061 const GO gblColInd = gblRowInd;
6062 const LO lclColInd = lclColMap.getLocalElement (gblColInd);
6064 if (lclColInd == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
6065 #ifdef HAVE_TPETRA_DEBUG
6066 allRowMapDiagEntriesInColMap =
false;
6067 #endif // HAVE_TPETRA_DEBUG
6068 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6071 const RowInfo rowInfo = this->getRowInfo (lclRowInd);
6072 if (static_cast<LO> (rowInfo.localRow) == lclRowInd &&
6073 rowInfo.numEntries > 0) {
6075 auto colInds = this->getLocalKokkosRowView (rowInfo);
6076 const size_t hint = 0;
6077 const size_t offset =
6078 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
6079 lclColInd, hint, sorted);
6080 offsets_h(lclRowInd) = offset;
6082 #ifdef HAVE_TPETRA_DEBUG
6087 Teuchos::ArrayView<const LO> lclColInds;
6089 this->getLocalRowView (lclRowInd, lclColInds);
6092 noOtherWeirdness =
false;
6095 if (noOtherWeirdness) {
6096 const size_t numEnt = lclColInds.size ();
6097 if (offset >= numEnt) {
6100 allOffsetsCorrect =
false;
6101 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6103 const LO actualLclColInd = lclColInds[offset];
6104 const GO actualGblColInd = lclColMap.getGlobalElement (actualLclColInd);
6105 if (actualGblColInd != gblColInd) {
6106 allOffsetsCorrect =
false;
6107 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6111 #endif // HAVE_TPETRA_DEBUG
6114 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6115 #ifdef HAVE_TPETRA_DEBUG
6116 allDiagEntriesFound =
false;
6117 #endif // HAVE_TPETRA_DEBUG
6125 #ifdef HAVE_TPETRA_DEBUG
6126 if (wrongOffsets.size () != 0) {
6127 std::ostringstream os;
6128 os <<
"Proc " << this->getComm ()->getRank () <<
": Wrong offsets: [";
6129 for (
size_t k = 0; k < wrongOffsets.size (); ++k) {
6130 os <<
"(" << wrongOffsets[k].first <<
","
6131 << wrongOffsets[k].second <<
")";
6132 if (k + 1 < wrongOffsets.size ()) {
6136 os <<
"]" << std::endl;
6137 std::cerr << os.str ();
6139 #endif // HAVE_TPETRA_DEBUG
6141 #ifdef HAVE_TPETRA_DEBUG
6142 using Teuchos::reduceAll;
6144 Teuchos::RCP<const Teuchos::Comm<int> > comm = this->getComm ();
6145 const bool localSuccess =
6146 allRowMapDiagEntriesInColMap && allDiagEntriesFound && allOffsetsCorrect;
6147 const int numResults = 5;
6149 lclResults[0] = allRowMapDiagEntriesInColMap ? 1 : 0;
6150 lclResults[1] = allDiagEntriesFound ? 1 : 0;
6151 lclResults[2] = allOffsetsCorrect ? 1 : 0;
6152 lclResults[3] = noOtherWeirdness ? 1 : 0;
6155 lclResults[4] = ! localSuccess ? comm->getRank () : comm->getSize ();
6163 reduceAll<int, int> (*comm, Teuchos::REDUCE_MIN,
6164 numResults, lclResults, gblResults);
6166 if (gblResults[0] != 1 || gblResults[1] != 1 || gblResults[2] != 1
6167 || gblResults[3] != 1) {
6168 std::ostringstream os;
6169 os <<
"Issue(s) that we noticed (on Process " << gblResults[4] <<
", "
6170 "possibly among others): " << endl;
6171 if (gblResults[0] == 0) {
6172 os <<
" - The column Map does not contain at least one diagonal entry "
6173 "of the graph." << endl;
6175 if (gblResults[1] == 0) {
6176 os <<
" - On one or more processes, some row does not contain a "
6177 "diagonal entry." << endl;
6179 if (gblResults[2] == 0) {
6180 os <<
" - On one or more processes, some offsets are incorrect."
6183 if (gblResults[3] == 0) {
6184 os <<
" - One or more processes had some other error."
6187 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
6189 #endif // HAVE_TPETRA_DEBUG
6210 template<
class DeviceType,
6211 const bool memSpaceIsHostSpace =
6212 std::is_same<
typename DeviceType::memory_space,
6213 Kokkos::HostSpace>::value>
6214 struct HelpGetLocalDiagOffsets {};
6216 template<
class DeviceType>
6217 struct HelpGetLocalDiagOffsets<DeviceType, true> {
6218 typedef DeviceType device_type;
6219 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6220 Kokkos::MemoryUnmanaged> device_offsets_type;
6221 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6222 Kokkos::MemoryUnmanaged> host_offsets_type;
6224 static device_offsets_type
6225 getDeviceOffsets (
const host_offsets_type& hostOffsets)
6233 copyBackIfNeeded (
const host_offsets_type& ,
6234 const device_offsets_type& )
6238 template<
class DeviceType>
6239 struct HelpGetLocalDiagOffsets<DeviceType, false> {
6240 typedef DeviceType device_type;
6244 typedef Kokkos::View<size_t*, device_type> device_offsets_type;
6245 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
6246 Kokkos::MemoryUnmanaged> host_offsets_type;
6248 static device_offsets_type
6249 getDeviceOffsets (
const host_offsets_type& hostOffsets)
6253 return device_offsets_type (
"offsets", hostOffsets.extent (0));
6257 copyBackIfNeeded (
const host_offsets_type& hostOffsets,
6258 const device_offsets_type& deviceOffsets)
6266 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6268 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
6269 getLocalDiagOffsets (Teuchos::ArrayRCP<size_t>& offsets)
const
6271 typedef LocalOrdinal LO;
6272 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6273 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6274 (! this->hasColMap (), std::runtime_error,
6275 "The graph does not yet have a column Map.");
6276 const LO myNumRows = static_cast<LO> (this->getNodeNumRows ());
6277 if (static_cast<LO> (offsets.size ()) != myNumRows) {
6281 offsets.resize (myNumRows);
6293 typedef HelpGetLocalDiagOffsets<device_type> helper_type;
6294 typedef typename helper_type::host_offsets_type host_offsets_type;
6296 host_offsets_type hostOffsets (offsets.getRawPtr (), myNumRows);
6298 auto deviceOffsets = helper_type::getDeviceOffsets (hostOffsets);
6300 this->getLocalDiagOffsets (deviceOffsets);
6301 helper_type::copyBackIfNeeded (hostOffsets, deviceOffsets);
6304 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6311 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6315 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& rowTransfer,
6316 const Teuchos::RCP<const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node> > & domainTransfer,
6317 const Teuchos::RCP<const map_type>& domainMap,
6318 const Teuchos::RCP<const map_type>& rangeMap,
6319 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
6325 using Teuchos::ArrayRCP;
6326 using Teuchos::ArrayView;
6327 using Teuchos::Comm;
6328 using Teuchos::ParameterList;
6331 #ifdef HAVE_TPETRA_MMM_TIMINGS
6333 using Teuchos::TimeMonitor;
6336 using LO = LocalOrdinal;
6337 using GO = GlobalOrdinal;
6338 using NT = node_type;
6341 using packet_type =
typename this_type::packet_type;
6343 const char* prefix =
"Tpetra::CrsGraph::transferAndFillComplete: ";
6345 #ifdef HAVE_TPETRA_MMM_TIMINGS
6347 if(!params.is_null()) label = params->get(
"Timer Label", label);
6348 string prefix2 = string(
"Tpetra ")+ label + std::string(
": CrsGraph TAFC ");
6349 RCP<TimeMonitor> MM =
6350 rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Pack-1"))));
6358 const import_type* xferAsImport = dynamic_cast<const import_type*>(&rowTransfer);
6359 const export_type* xferAsExport = dynamic_cast<const export_type*>(&rowTransfer);
6360 TEUCHOS_TEST_FOR_EXCEPTION(
6361 xferAsImport == NULL && xferAsExport == NULL, std::invalid_argument,
6362 prefix <<
"The 'rowTransfer' input argument must be either an Import or "
6363 "an Export, and its template parameters must match the corresponding "
6364 "template parameters of the CrsGraph.");
6371 Teuchos::RCP<const import_type> xferDomainAsImport =
6372 Teuchos::rcp_dynamic_cast<const import_type>(domainTransfer);
6373 Teuchos::RCP<const export_type> xferDomainAsExport =
6374 Teuchos::rcp_dynamic_cast<const export_type>(domainTransfer);
6376 if(! domainTransfer.is_null()) {
6378 TEUCHOS_TEST_FOR_EXCEPTION(
6379 (xferDomainAsImport.is_null() && xferDomainAsExport.is_null()), std::invalid_argument,
6380 prefix <<
"The 'domainTransfer' input argument must be either an "
6381 "Import or an Export, and its template parameters must match the "
6382 "corresponding template parameters of the CrsGraph.");
6384 TEUCHOS_TEST_FOR_EXCEPTION(
6385 ( xferAsImport != NULL || ! xferDomainAsImport.is_null() ) &&
6386 (( xferAsImport != NULL && xferDomainAsImport.is_null() ) ||
6387 ( xferAsImport == NULL && ! xferDomainAsImport.is_null() )), std::invalid_argument,
6388 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6389 "must be of the same type (either Import or Export).");
6391 TEUCHOS_TEST_FOR_EXCEPTION(
6392 ( xferAsExport != NULL || ! xferDomainAsExport.is_null() ) &&
6393 (( xferAsExport != NULL && xferDomainAsExport.is_null() ) ||
6394 ( xferAsExport == NULL && ! xferDomainAsExport.is_null() )), std::invalid_argument,
6395 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
6396 "must be of the same type (either Import or Export).");
6403 const bool communication_needed = rowTransfer.getSourceMap()->isDistributed();
6409 bool reverseMode =
false;
6410 bool restrictComm =
false;
6411 RCP<ParameterList> graphparams;
6412 if (! params.is_null()) {
6413 reverseMode = params->get(
"Reverse Mode", reverseMode);
6414 restrictComm = params->get(
"Restrict Communicator", restrictComm);
6415 graphparams = sublist(params,
"CrsGraph");
6420 RCP<const map_type> MyRowMap = reverseMode ?
6421 rowTransfer.getSourceMap() : rowTransfer.getTargetMap();
6422 RCP<const map_type> MyColMap;
6423 RCP<const map_type> MyDomainMap = ! domainMap.is_null() ? domainMap : getDomainMap();
6424 RCP<const map_type> MyRangeMap = ! rangeMap.is_null() ? rangeMap : getRangeMap();
6425 RCP<const map_type> BaseRowMap = MyRowMap;
6426 RCP<const map_type> BaseDomainMap = MyDomainMap;
6434 if (! destGraph.is_null()) {
6445 const bool NewFlag =
6446 ! destGraph->isLocallyIndexed() && ! destGraph->isGloballyIndexed();
6447 TEUCHOS_TEST_FOR_EXCEPTION(! NewFlag, std::invalid_argument,
6448 prefix <<
"The input argument 'destGraph' is only allowed to be nonnull, "
6449 "if its graph is empty (neither locally nor globally indexed).");
6458 TEUCHOS_TEST_FOR_EXCEPTION(
6459 ! destGraph->getRowMap()->isSameAs(*MyRowMap), std::invalid_argument,
6460 prefix <<
"The (row) Map of the input argument 'destGraph' is not the "
6461 "same as the (row) Map specified by the input argument 'rowTransfer'.");
6463 TEUCHOS_TEST_FOR_EXCEPTION(
6464 ! destGraph->checkSizes(*
this), std::invalid_argument,
6465 prefix <<
"You provided a nonnull destination graph, but checkSizes() "
6466 "indicates that it is not a legal legal target for redistribution from "
6467 "the source graph (*this). This may mean that they do not have the "
6468 "same dimensions.");
6482 TEUCHOS_TEST_FOR_EXCEPTION(
6483 ! (reverseMode || getRowMap()->isSameAs(*rowTransfer.getSourceMap())),
6484 std::invalid_argument, prefix <<
6485 "rowTransfer->getSourceMap() must match this->getRowMap() in forward mode.");
6487 TEUCHOS_TEST_FOR_EXCEPTION(
6488 ! (! reverseMode || getRowMap()->isSameAs(*rowTransfer.getTargetMap())),
6489 std::invalid_argument, prefix <<
6490 "rowTransfer->getTargetMap() must match this->getRowMap() in reverse mode.");
6493 TEUCHOS_TEST_FOR_EXCEPTION(
6494 ! xferDomainAsImport.is_null() && ! xferDomainAsImport->getTargetMap()->isSameAs(*domainMap),
6495 std::invalid_argument,
6496 prefix <<
"The target map of the 'domainTransfer' input argument must be "
6497 "the same as the rebalanced domain map 'domainMap'");
6499 TEUCHOS_TEST_FOR_EXCEPTION(
6500 ! xferDomainAsExport.is_null() && ! xferDomainAsExport->getSourceMap()->isSameAs(*domainMap),
6501 std::invalid_argument,
6502 prefix <<
"The source map of the 'domainTransfer' input argument must be "
6503 "the same as the rebalanced domain map 'domainMap'");
6516 const size_t NumSameIDs = rowTransfer.getNumSameIDs();
6517 ArrayView<const LO> ExportLIDs = reverseMode ?
6518 rowTransfer.getRemoteLIDs() : rowTransfer.getExportLIDs();
6519 ArrayView<const LO> RemoteLIDs = reverseMode ?
6520 rowTransfer.getExportLIDs() : rowTransfer.getRemoteLIDs();
6521 ArrayView<const LO> PermuteToLIDs = reverseMode ?
6522 rowTransfer.getPermuteFromLIDs() : rowTransfer.getPermuteToLIDs();
6523 ArrayView<const LO> PermuteFromLIDs = reverseMode ?
6524 rowTransfer.getPermuteToLIDs() : rowTransfer.getPermuteFromLIDs();
6525 Distributor& Distor = rowTransfer.getDistributor();
6528 Teuchos::Array<int> SourcePids;
6529 Teuchos::Array<int> TargetPids;
6530 int MyPID = getComm()->getRank();
6533 RCP<const map_type> ReducedRowMap, ReducedColMap,
6534 ReducedDomainMap, ReducedRangeMap;
6535 RCP<const Comm<int> > ReducedComm;
6539 if (destGraph.is_null()) {
6540 destGraph = rcp(
new this_type(MyRowMap, 0, StaticProfile, graphparams));
6547 ReducedRowMap = MyRowMap->removeEmptyProcesses();
6548 ReducedComm = ReducedRowMap.is_null() ?
6550 ReducedRowMap->getComm();
6551 destGraph->removeEmptyProcessesInPlace(ReducedRowMap);
6553 ReducedDomainMap = MyRowMap.getRawPtr() == MyDomainMap.getRawPtr() ?
6555 MyDomainMap->replaceCommWithSubset(ReducedComm);
6556 ReducedRangeMap = MyRowMap.getRawPtr() == MyRangeMap.getRawPtr() ?
6558 MyRangeMap->replaceCommWithSubset(ReducedComm);
6561 MyRowMap = ReducedRowMap;
6562 MyDomainMap = ReducedDomainMap;
6563 MyRangeMap = ReducedRangeMap;
6566 if (! ReducedComm.is_null()) {
6567 MyPID = ReducedComm->getRank();
6574 ReducedComm = MyRowMap->getComm();
6580 #ifdef HAVE_TPETRA_MMM_TIMINGS
6581 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ImportSetup"))));
6584 RCP<const import_type> MyImporter = getImporter();
6587 bool bSameDomainMap = BaseDomainMap->isSameAs(*getDomainMap());
6589 if (! restrictComm && ! MyImporter.is_null() && bSameDomainMap ) {
6596 Import_Util::getPids(*MyImporter, SourcePids,
false);
6598 else if (restrictComm && ! MyImporter.is_null() && bSameDomainMap) {
6601 ivector_type SourceDomain_pids(getDomainMap(),
true);
6602 ivector_type SourceCol_pids(getColMap());
6604 SourceDomain_pids.putScalar(MyPID);
6606 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6607 SourcePids.resize(getColMap()->getNodeNumElements());
6608 SourceCol_pids.get1dCopy(SourcePids());
6610 else if (MyImporter.is_null() && bSameDomainMap) {
6612 SourcePids.resize(getColMap()->getNodeNumElements());
6613 SourcePids.assign(getColMap()->getNodeNumElements(), MyPID);
6615 else if ( ! MyImporter.is_null() &&
6616 ! domainTransfer.is_null() ) {
6623 ivector_type TargetDomain_pids(domainMap);
6624 TargetDomain_pids.putScalar(MyPID);
6627 ivector_type SourceDomain_pids(getDomainMap());
6630 ivector_type SourceCol_pids(getColMap());
6632 if (! reverseMode && ! xferDomainAsImport.is_null() ) {
6633 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6635 else if (reverseMode && ! xferDomainAsExport.is_null() ) {
6636 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6638 else if (! reverseMode && ! xferDomainAsExport.is_null() ) {
6639 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
6641 else if (reverseMode && ! xferDomainAsImport.is_null() ) {
6642 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
6645 TEUCHOS_TEST_FOR_EXCEPTION(
6646 true, std::logic_error,
6647 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6649 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
6650 SourcePids.resize(getColMap()->getNodeNumElements());
6651 SourceCol_pids.get1dCopy(SourcePids());
6653 else if (BaseDomainMap->isSameAs(*BaseRowMap) &&
6654 getDomainMap()->isSameAs(*getRowMap())) {
6656 ivector_type TargetRow_pids(domainMap);
6657 ivector_type SourceRow_pids(getRowMap());
6658 ivector_type SourceCol_pids(getColMap());
6660 TargetRow_pids.putScalar(MyPID);
6661 if (! reverseMode && xferAsImport != NULL) {
6662 SourceRow_pids.doExport(TargetRow_pids, *xferAsImport,
INSERT);
6664 else if (reverseMode && xferAsExport != NULL) {
6665 SourceRow_pids.doExport(TargetRow_pids, *xferAsExport,
INSERT);
6667 else if (! reverseMode && xferAsExport != NULL) {
6668 SourceRow_pids.doImport(TargetRow_pids, *xferAsExport,
INSERT);
6670 else if (reverseMode && xferAsImport != NULL) {
6671 SourceRow_pids.doImport(TargetRow_pids, *xferAsImport,
INSERT);
6674 TEUCHOS_TEST_FOR_EXCEPTION(
6675 true, std::logic_error,
6676 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6678 SourceCol_pids.doImport(SourceRow_pids, *MyImporter,
INSERT);
6679 SourcePids.resize(getColMap()->getNodeNumElements());
6680 SourceCol_pids.get1dCopy(SourcePids());
6683 TEUCHOS_TEST_FOR_EXCEPTION(
6684 true, std::invalid_argument,
6685 prefix <<
"This method only allows either domainMap == getDomainMap(), "
6686 "or (domainMap == rowTransfer.getTargetMap() and getDomainMap() == getRowMap()).");
6690 size_t constantNumPackets = destGraph->constantNumberOfPackets();
6691 if (constantNumPackets == 0) {
6692 destGraph->reallocArraysForNumPacketsPerLid(ExportLIDs.size(),
6700 const size_t rbufLen = RemoteLIDs.size() * constantNumPackets;
6701 destGraph->reallocImportsIfNeeded(rbufLen);
6706 destGraph->numExportPacketsPerLID_.template modify<Kokkos::HostSpace>();
6707 Teuchos::ArrayView<size_t> numExportPacketsPerLID =
6712 numExportPacketsPerLID, ExportLIDs,
6713 SourcePids, constantNumPackets, Distor);
6717 #ifdef HAVE_TPETRA_MMM_TIMINGS
6718 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Transfer"))));
6721 if (communication_needed) {
6723 if (constantNumPackets == 0) {
6727 destGraph->numExportPacketsPerLID_.template sync<Kokkos::HostSpace>();
6728 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
6730 destGraph->numImportPacketsPerLID_.template sync<Kokkos::HostSpace>();
6731 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
6733 Distor.doReversePostsAndWaits(numExportPacketsPerLID, 1,
6734 numImportPacketsPerLID);
6735 size_t totalImportPackets = 0;
6736 for (Array_size_type i = 0; i < numImportPacketsPerLID.size(); ++i) {
6737 totalImportPackets += numImportPacketsPerLID[i];
6742 destGraph->reallocImportsIfNeeded(totalImportPackets);
6743 destGraph->imports_.template modify<Kokkos::HostSpace>();
6744 Teuchos::ArrayView<packet_type> hostImports =
6748 destGraph->exports_.template sync<Kokkos::HostSpace>();
6749 Teuchos::ArrayView<const packet_type> hostExports =
6751 Distor.doReversePostsAndWaits(hostExports,
6752 numExportPacketsPerLID,
6754 numImportPacketsPerLID);
6757 destGraph->imports_.template modify<Kokkos::HostSpace>();
6758 Teuchos::ArrayView<packet_type> hostImports =
6762 destGraph->exports_.template sync<Kokkos::HostSpace>();
6763 Teuchos::ArrayView<const packet_type> hostExports =
6765 Distor.doReversePostsAndWaits(hostExports,
6771 if (constantNumPackets == 0) {
6775 destGraph->numExportPacketsPerLID_.template sync<Kokkos::HostSpace>();
6776 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
6778 destGraph->numImportPacketsPerLID_.template sync<Kokkos::HostSpace>();
6779 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
6781 Distor.doPostsAndWaits(numExportPacketsPerLID, 1,
6782 numImportPacketsPerLID);
6783 size_t totalImportPackets = 0;
6784 for (Array_size_type i = 0; i < numImportPacketsPerLID.size(); ++i) {
6785 totalImportPackets += numImportPacketsPerLID[i];
6790 destGraph->reallocImportsIfNeeded(totalImportPackets);
6791 destGraph->imports_.template modify<Kokkos::HostSpace>();
6792 Teuchos::ArrayView<packet_type> hostImports =
6796 destGraph->exports_.template sync<Kokkos::HostSpace>();
6797 Teuchos::ArrayView<const packet_type> hostExports =
6799 Distor.doPostsAndWaits(hostExports,
6800 numExportPacketsPerLID,
6802 numImportPacketsPerLID);
6805 destGraph->imports_.template modify<Kokkos::HostSpace>();
6806 Teuchos::ArrayView<packet_type> hostImports =
6810 destGraph->exports_.template sync<Kokkos::HostSpace>();
6811 Teuchos::ArrayView<const packet_type> hostExports =
6813 Distor.doPostsAndWaits(hostExports,
6824 #ifdef HAVE_TPETRA_MMM_TIMINGS
6825 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-1"))));
6829 destGraph->numImportPacketsPerLID_.template sync<Kokkos::HostSpace>();
6830 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
6832 destGraph->imports_.template sync<Kokkos::HostSpace>();
6833 Teuchos::ArrayView<const packet_type> hostImports =
6837 numImportPacketsPerLID,
6838 constantNumPackets, Distor,
INSERT,
6839 NumSameIDs, PermuteToLIDs, PermuteFromLIDs);
6840 size_t N = BaseRowMap->getNodeNumElements();
6843 ArrayRCP<size_t> CSR_rowptr(N+1);
6844 ArrayRCP<GO> CSR_colind_GID;
6845 ArrayRCP<LO> CSR_colind_LID;
6846 CSR_colind_GID.resize(mynnz);
6850 if (
typeid(LO) ==
typeid(GO)) {
6851 CSR_colind_LID = Teuchos::arcp_reinterpret_cast<LO>(CSR_colind_GID);
6854 CSR_colind_LID.resize(mynnz);
6863 numImportPacketsPerLID, constantNumPackets,
6864 Distor,
INSERT, NumSameIDs, PermuteToLIDs,
6865 PermuteFromLIDs, N, mynnz, MyPID,
6866 CSR_rowptr(), CSR_colind_GID(),
6867 SourcePids(), TargetPids);
6872 #ifdef HAVE_TPETRA_MMM_TIMINGS
6873 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-2"))));
6878 Teuchos::Array<int> RemotePids;
6879 Import_Util::lowCommunicationMakeColMapAndReindex(CSR_rowptr(),
6883 TargetPids, RemotePids,
6890 ReducedColMap = (MyRowMap.getRawPtr() == MyColMap.getRawPtr()) ?
6892 MyColMap->replaceCommWithSubset(ReducedComm);
6893 MyColMap = ReducedColMap;
6897 destGraph->replaceColMap(MyColMap);
6904 if (ReducedComm.is_null()) {
6911 if ((! reverseMode && xferAsImport != NULL) ||
6912 (reverseMode && xferAsExport != NULL)) {
6913 Import_Util::sortCrsEntries(CSR_rowptr(),
6916 else if ((! reverseMode && xferAsExport != NULL) ||
6917 (reverseMode && xferAsImport != NULL)) {
6918 Import_Util::sortAndMergeCrsEntries(CSR_rowptr(),
6920 if (CSR_rowptr[N] != mynnz) {
6921 CSR_colind_LID.resize(CSR_rowptr[N]);
6925 TEUCHOS_TEST_FOR_EXCEPTION(
6926 true, std::logic_error,
6927 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
6935 destGraph->setAllIndices(CSR_rowptr, CSR_colind_LID);
6941 Teuchos::ParameterList esfc_params;
6942 #ifdef HAVE_TPETRA_MMM_TIMINGS
6943 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"CreateImporter"))));
6945 RCP<import_type> MyImport = rcp(
new import_type(MyDomainMap, MyColMap, RemotePids));
6946 #ifdef HAVE_TPETRA_MMM_TIMINGS
6947 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ESFC"))));
6949 esfc_params.set(
"Timer Label",prefix + std::string(
"TAFC"));
6951 if(!params.is_null())
6952 esfc_params.set(
"compute global constants",params->get(
"compute global constants",
true));
6954 destGraph->expertStaticFillComplete(MyDomainMap, MyRangeMap,
6955 MyImport, Teuchos::null, rcp(&esfc_params,
false));
6959 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6961 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
6964 const Teuchos::RCP<const map_type>& domainMap,
6965 const Teuchos::RCP<const map_type>& rangeMap,
6966 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
6968 transferAndFillComplete(destGraph, importer, Teuchos::null, domainMap, rangeMap, params);
6971 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6977 const Teuchos::RCP<const map_type>& domainMap,
6978 const Teuchos::RCP<const map_type>& rangeMap,
6979 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
6981 transferAndFillComplete(destGraph, rowImporter, Teuchos::rcpFromRef(domainImporter), domainMap, rangeMap, params);
6984 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6989 const Teuchos::RCP<const map_type>& domainMap,
6990 const Teuchos::RCP<const map_type>& rangeMap,
6991 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
6993 transferAndFillComplete(destGraph, exporter, Teuchos::null, domainMap, rangeMap, params);
6996 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7002 const Teuchos::RCP<const map_type>& domainMap,
7003 const Teuchos::RCP<const map_type>& rangeMap,
7004 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7006 transferAndFillComplete(destGraph, rowExporter, Teuchos::rcpFromRef(domainExporter), domainMap, rangeMap, params);
7017 #define TPETRA_CRSGRAPH_GRAPH_INSTANT(LO,GO,NODE) \
7018 namespace Classes { template class CrsGraph< LO , GO , NODE >; }
7020 #define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7022 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7023 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7024 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7025 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7026 CrsGraph<LO,GO,NODE>::node_type>& importer, \
7027 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7028 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7029 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7030 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7031 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7032 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7033 const Teuchos::RCP<Teuchos::ParameterList>& params);
7035 #define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7037 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7038 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7039 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7040 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7041 CrsGraph<LO,GO,NODE>::node_type>& rowImporter, \
7042 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7043 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7044 CrsGraph<LO,GO,NODE>::node_type>& domainImporter, \
7045 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7046 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7047 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7048 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7049 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7050 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7051 const Teuchos::RCP<Teuchos::ParameterList>& params);
7054 #define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7056 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7057 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7058 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7059 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7060 CrsGraph<LO,GO,NODE>::node_type>& exporter, \
7061 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7062 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7063 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7064 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7065 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7066 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7067 const Teuchos::RCP<Teuchos::ParameterList>& params);
7069 #define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7071 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
7072 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
7073 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7074 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7075 CrsGraph<LO,GO,NODE>::node_type>& rowExporter, \
7076 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7077 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7078 CrsGraph<LO,GO,NODE>::node_type>& domainExporter, \
7079 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7080 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7081 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
7082 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
7083 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
7084 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
7085 const Teuchos::RCP<Teuchos::ParameterList>& params);
7090 #define TPETRA_CRSGRAPH_SORTROWINDICESANDVALUES_INSTANT(S,LO,GO,NODE)
7091 #define TPETRA_CRSGRAPH_MERGEROWINDICESANDVALUES_INSTANT(S,LO,GO,NODE)
7092 #define TPETRA_CRSGRAPH_ALLOCATEVALUES1D_INSTANT(S,LO,GO,NODE)
7093 #define TPETRA_CRSGRAPH_ALLOCATEVALUES2D_INSTANT(S,LO,GO,NODE)
7095 #define TPETRA_CRSGRAPH_INSTANT(S,LO,GO,NODE) \
7096 TPETRA_CRSGRAPH_SORTROWINDICESANDVALUES_INSTANT(S,LO,GO,NODE) \
7097 TPETRA_CRSGRAPH_MERGEROWINDICESANDVALUES_INSTANT(S,LO,GO,NODE) \
7098 TPETRA_CRSGRAPH_ALLOCATEVALUES1D_INSTANT(S,LO,GO,NODE) \
7099 TPETRA_CRSGRAPH_ALLOCATEVALUES2D_INSTANT(S,LO,GO,NODE) \
7100 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7101 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
7102 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
7103 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE)
7106 #endif // TPETRA_CRSGRAPH_DEF_HPP