40 #ifndef TPETRA_CRSGRAPH_DEF_HPP
41 #define TPETRA_CRSGRAPH_DEF_HPP
54 #include "Tpetra_Details_gathervPrint.hpp"
55 #include "Tpetra_Details_getGraphDiagOffsets.hpp"
56 #include "Tpetra_Details_makeColMap.hpp"
60 #include "Tpetra_Distributor.hpp"
61 #include "Teuchos_SerialDenseMatrix.hpp"
62 #include "Tpetra_Vector.hpp"
65 #include "Tpetra_Details_packCrsGraph.hpp"
66 #include "Tpetra_Details_unpackCrsGraphAndCombine.hpp"
73 #include <type_traits>
81 template<
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
82 class ConvertColumnIndicesFromGlobalToLocal {
84 ConvertColumnIndicesFromGlobalToLocal (const ::Kokkos::View<LO*, DT>& lclColInds,
85 const ::Kokkos::View<const GO*, DT>& gblColInds,
86 const ::Kokkos::View<const OffsetType*, DT>& ptr,
87 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
88 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt) :
89 lclColInds_ (lclColInds),
90 gblColInds_ (gblColInds),
92 lclColMap_ (lclColMap),
93 numRowEnt_ (numRowEnt)
97 operator () (
const LO& lclRow, OffsetType& curNumBad)
const
99 const OffsetType offset = ptr_(lclRow);
103 const LO numEnt =
static_cast<LO
> (numRowEnt_(lclRow));
104 for (LO j = 0; j < numEnt; ++j) {
105 const GO gid = gblColInds_(offset + j);
106 const LO lid = lclColMap_.getLocalElement (gid);
107 lclColInds_(offset + j) = lid;
108 if (lid == ::Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
115 run (const ::Kokkos::View<LO*, DT>& lclColInds,
116 const ::Kokkos::View<const GO*, DT>& gblColInds,
117 const ::Kokkos::View<const OffsetType*, DT>& ptr,
118 const ::Tpetra::Details::LocalMap<LO, GO, DT>& lclColMap,
119 const ::Kokkos::View<const NumEntType*, DT>& numRowEnt)
121 typedef ::Kokkos::RangePolicy<typename DT::execution_space, LO> range_type;
122 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> functor_type;
124 const LO lclNumRows = ptr.extent (0) == 0 ?
125 static_cast<LO
> (0) :
static_cast<LO
> (ptr.extent (0) - 1);
126 OffsetType numBad = 0;
128 ::Kokkos::parallel_reduce (range_type (0, lclNumRows),
129 functor_type (lclColInds, gblColInds, ptr,
130 lclColMap, numRowEnt),
136 ::Kokkos::View<LO*, DT> lclColInds_;
137 ::Kokkos::View<const GO*, DT> gblColInds_;
138 ::Kokkos::View<const OffsetType*, DT> ptr_;
140 ::Kokkos::View<const NumEntType*, DT> numRowEnt_;
159 template<
class LO,
class GO,
class DT,
class OffsetType,
class NumEntType>
162 const Kokkos::View<const GO*, DT>& gblColInds,
163 const Kokkos::View<const OffsetType*, DT>& ptr,
165 const Kokkos::View<const NumEntType*, DT>& numRowEnt)
167 using Impl::ConvertColumnIndicesFromGlobalToLocal;
168 typedef ConvertColumnIndicesFromGlobalToLocal<LO, GO, DT, OffsetType, NumEntType> impl_type;
169 return impl_type::run (lclColInds, gblColInds, ptr, lclColMap, numRowEnt);
172 template<
class ViewType,
class LO>
173 class MaxDifference {
175 MaxDifference (
const ViewType& ptr) : ptr_ (ptr) {}
177 KOKKOS_INLINE_FUNCTION
void init (LO& dst)
const {
181 KOKKOS_INLINE_FUNCTION
void
182 join (
volatile LO& dst,
const volatile LO& src)
const
184 dst = (src > dst) ? src : dst;
187 KOKKOS_INLINE_FUNCTION
void
188 operator () (
const LO lclRow, LO& maxNumEnt)
const
190 const LO numEnt =
static_cast<LO
> (ptr_(lclRow+1) - ptr_(lclRow));
191 maxNumEnt = (numEnt > maxNumEnt) ? numEnt : maxNumEnt;
194 typename ViewType::const_type ptr_;
197 template<
class ViewType,
class LO>
198 typename ViewType::non_const_value_type
199 maxDifference (
const char kernelLabel[],
203 if (lclNumRows == 0) {
206 return static_cast<LO
> (0);
209 using execution_space =
typename ViewType::execution_space;
210 using range_type = Kokkos::RangePolicy<execution_space, LO>;
212 Kokkos::parallel_reduce (kernelLabel,
213 range_type (0, lclNumRows),
214 MaxDifference<ViewType, LO> (ptr),
222 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
224 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
225 const size_t maxNumEntriesPerRow,
227 const Teuchos::RCP<Teuchos::ParameterList>& params) :
230 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
231 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
232 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
233 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
234 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
236 , numAllocForAllRows_ (maxNumEntriesPerRow)
237 , storageStatus_ (pftype == StaticProfile ?
240 , indicesAreAllocated_ (false)
241 , indicesAreLocal_ (false)
242 , indicesAreGlobal_ (false)
243 , fillComplete_ (false)
244 , lowerTriangular_ (false)
245 , upperTriangular_ (false)
246 , indicesAreSorted_ (true)
247 , noRedundancies_ (true)
248 , haveLocalConstants_ (false)
249 , haveGlobalConstants_ (false)
250 , sortGhostsAssociatedWithEachProcessor_ (true)
252 const char tfecfFuncName[] =
"CrsGraph(rowMap,maxNumEntriesPerRow,"
255 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
256 (maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid (),
257 std::invalid_argument,
"The allocation hint maxNumEntriesPerRow must be "
258 "a valid size_t value, which in this case means it must not be "
259 "Teuchos::OrdinalTraits<size_t>::invalid().");
264 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
266 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
267 const Teuchos::RCP<const map_type>& colMap,
268 const size_t maxNumEntriesPerRow,
270 const Teuchos::RCP<Teuchos::ParameterList>& params) :
274 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
275 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
276 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
277 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
278 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
280 , numAllocForAllRows_ (maxNumEntriesPerRow)
281 , storageStatus_ (pftype == StaticProfile ?
284 , indicesAreAllocated_ (false)
285 , indicesAreLocal_ (false)
286 , indicesAreGlobal_ (false)
287 , fillComplete_ (false)
288 , lowerTriangular_ (false)
289 , upperTriangular_ (false)
290 , indicesAreSorted_ (true)
291 , noRedundancies_ (true)
292 , haveLocalConstants_ (false)
293 , haveGlobalConstants_ (false)
294 , sortGhostsAssociatedWithEachProcessor_ (true)
296 const char tfecfFuncName[] =
"CrsGraph(rowMap,colMap,maxNumEntriesPerRow,"
299 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
300 maxNumEntriesPerRow == Teuchos::OrdinalTraits<size_t>::invalid (),
301 std::invalid_argument,
"The allocation hint maxNumEntriesPerRow must be "
302 "a valid size_t value, which in this case means it must not be "
303 "Teuchos::OrdinalTraits<size_t>::invalid().");
308 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
310 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
311 const Teuchos::ArrayView<const size_t>& numEntPerRow,
313 const Teuchos::RCP<Teuchos::ParameterList>& params) :
316 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
317 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
318 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
319 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
320 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
322 , numAllocForAllRows_ (0)
323 , storageStatus_ (pftype == StaticProfile ?
326 , indicesAreAllocated_ (false)
327 , indicesAreLocal_ (false)
328 , indicesAreGlobal_ (false)
329 , fillComplete_ (false)
330 , lowerTriangular_ (false)
331 , upperTriangular_ (false)
332 , indicesAreSorted_ (true)
333 , noRedundancies_ (true)
334 , haveLocalConstants_ (false)
335 , haveGlobalConstants_ (false)
336 , sortGhostsAssociatedWithEachProcessor_ (true)
338 const char tfecfFuncName[] =
"CrsGraph(rowMap,numEntPerRow,pftype,params): ";
341 const size_t lclNumRows = rowMap.is_null () ?
342 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
343 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
344 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
345 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
346 <<
" != the local number of rows " << lclNumRows <<
" as specified by "
347 "the input row Map.");
351 for (
size_t r = 0; r < lclNumRows; ++r) {
352 const size_t curRowCount = numEntPerRow[r];
353 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
354 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
355 std::invalid_argument,
"numEntPerRow(" << r <<
") "
356 "specifies an invalid number of entries "
357 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
365 typedef typename out_view_type::non_const_type nc_view_type;
366 typedef Kokkos::View<
const size_t*,
367 typename nc_view_type::array_layout,
369 Kokkos::MemoryUnmanaged> in_view_type;
370 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
371 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
380 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
381 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
383 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
384 const Teuchos::ArrayRCP<const size_t>& numEntPerRow,
386 const Teuchos::RCP<Teuchos::ParameterList>& params) :
387 dist_object_type (rowMap)
389 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
390 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
391 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
392 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
393 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
395 , numAllocForAllRows_ (0)
396 , storageStatus_ (pftype == StaticProfile ?
399 , indicesAreAllocated_ (false)
400 , indicesAreLocal_ (false)
401 , indicesAreGlobal_ (false)
402 , fillComplete_ (false)
403 , lowerTriangular_ (false)
404 , upperTriangular_ (false)
405 , indicesAreSorted_ (true)
406 , noRedundancies_ (true)
407 , haveLocalConstants_ (false)
408 , haveGlobalConstants_ (false)
409 , sortGhostsAssociatedWithEachProcessor_ (true)
411 const char tfecfFuncName[] =
"CrsGraph(RCP<const Map>,"
412 "ArrayRCP<const size_t>,ProfileType,RCP<ParameterList>): ";
415 const size_t lclNumRows = rowMap.is_null () ?
416 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
417 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
418 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
419 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
420 <<
" != the local number of rows " << lclNumRows <<
" as specified by "
421 "the input row Map.");
425 for (
size_t r = 0; r < lclNumRows; ++r) {
426 const size_t curRowCount = numEntPerRow[r];
427 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
428 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
429 std::invalid_argument,
"numEntPerRow(" << r <<
") "
430 "specifies an invalid number of entries "
431 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
438 typedef decltype (k_numAllocPerRow_) out_view_type;
439 typedef typename out_view_type::non_const_type nc_view_type;
440 typedef Kokkos::View<
const size_t*,
441 typename nc_view_type::array_layout,
443 Kokkos::MemoryUnmanaged> in_view_type;
444 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
445 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
448 k_numAllocPerRow_ = numAllocPerRowOut;
451 checkInternalState ();
453 #endif // TPETRA_ENABLE_DEPRECATED_CODE
456 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
458 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
459 const Kokkos::DualView<const size_t*, execution_space>& numEntPerRow,
461 const Teuchos::RCP<Teuchos::ParameterList>& params) :
464 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
465 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
466 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
467 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
468 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
470 , k_numAllocPerRow_ (numEntPerRow.h_view)
471 , numAllocForAllRows_ (0)
472 , storageStatus_ (pftype == StaticProfile ?
475 , indicesAreAllocated_ (false)
476 , indicesAreLocal_ (false)
477 , indicesAreGlobal_ (false)
478 , fillComplete_ (false)
479 , lowerTriangular_ (false)
480 , upperTriangular_ (false)
481 , indicesAreSorted_ (true)
482 , noRedundancies_ (true)
483 , haveLocalConstants_ (false)
484 , haveGlobalConstants_ (false)
485 , sortGhostsAssociatedWithEachProcessor_ (true)
487 const char tfecfFuncName[] =
"CrsGraph(rowMap,numEntPerRow,pftype,params): ";
490 const size_t lclNumRows = rowMap.is_null () ?
491 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
492 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
493 static_cast<size_t> (numEntPerRow.extent (0)) != lclNumRows,
494 std::invalid_argument,
"numEntPerRow has length " <<
495 numEntPerRow.extent (0) <<
" != the local number of rows " <<
496 lclNumRows <<
" as specified by " "the input row Map.");
500 for (
size_t r = 0; r < lclNumRows; ++r) {
501 const size_t curRowCount = numEntPerRow.h_view(r);
502 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
503 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
504 std::invalid_argument,
"numEntPerRow(" << r <<
") "
505 "specifies an invalid number of entries "
506 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
511 checkInternalState ();
515 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
517 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
518 const Teuchos::RCP<const map_type>& colMap,
519 const Kokkos::DualView<const size_t*, execution_space>& numEntPerRow,
521 const Teuchos::RCP<Teuchos::ParameterList>& params) :
525 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
526 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
527 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
528 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
529 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
531 , k_numAllocPerRow_ (numEntPerRow.h_view)
532 , numAllocForAllRows_ (0)
533 , storageStatus_ (pftype == StaticProfile ?
536 , indicesAreAllocated_ (false)
537 , indicesAreLocal_ (false)
538 , indicesAreGlobal_ (false)
539 , fillComplete_ (false)
540 , lowerTriangular_ (false)
541 , upperTriangular_ (false)
542 , indicesAreSorted_ (true)
543 , noRedundancies_ (true)
544 , haveLocalConstants_ (false)
545 , haveGlobalConstants_ (false)
546 , sortGhostsAssociatedWithEachProcessor_ (true)
548 const char tfecfFuncName[] =
"CrsGraph(rowMap,colMap,numEntPerRow,pftype,params): ";
551 const size_t lclNumRows = rowMap.is_null () ?
552 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
553 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
554 static_cast<size_t> (numEntPerRow.extent (0)) != lclNumRows,
555 std::invalid_argument,
"numEntPerRow has length " <<
556 numEntPerRow.extent (0) <<
" != the local number of rows " <<
557 lclNumRows <<
" as specified by " "the input row Map.");
561 for (
size_t r = 0; r < lclNumRows; ++r) {
562 const size_t curRowCount = numEntPerRow.h_view(r);
563 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
564 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
565 std::invalid_argument,
"numEntPerRow(" << r <<
") "
566 "specifies an invalid number of entries "
567 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
572 checkInternalState ();
576 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
578 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
579 const Teuchos::RCP<const map_type>& colMap,
580 const Teuchos::ArrayView<const size_t>& numEntPerRow,
582 const Teuchos::RCP<Teuchos::ParameterList>& params) :
586 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
587 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
588 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
589 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
590 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
592 , numAllocForAllRows_ (0)
593 , storageStatus_ (pftype == StaticProfile ?
596 , indicesAreAllocated_ (false)
597 , indicesAreLocal_ (false)
598 , indicesAreGlobal_ (false)
599 , fillComplete_ (false)
600 , lowerTriangular_ (false)
601 , upperTriangular_ (false)
602 , indicesAreSorted_ (true)
603 , noRedundancies_ (true)
604 , haveLocalConstants_ (false)
605 , haveGlobalConstants_ (false)
606 , sortGhostsAssociatedWithEachProcessor_ (true)
608 const char tfecfFuncName[] =
"CrsGraph(rowMap,colMap,numEntPerRow,pftype,"
612 const size_t lclNumRows = rowMap.is_null () ?
613 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
614 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
615 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
616 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
617 <<
" != the local number of rows " << lclNumRows <<
" as specified by "
618 "the input row Map.");
622 for (
size_t r = 0; r < lclNumRows; ++r) {
623 const size_t curRowCount = numEntPerRow[r];
624 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
625 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
626 std::invalid_argument,
"numEntPerRow(" << r <<
") "
627 "specifies an invalid number of entries "
628 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
635 typedef decltype (k_numAllocPerRow_) out_view_type;
636 typedef typename out_view_type::non_const_type nc_view_type;
637 typedef Kokkos::View<
const size_t*,
638 typename nc_view_type::array_layout,
640 Kokkos::MemoryUnmanaged> in_view_type;
641 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
642 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
645 k_numAllocPerRow_ = numAllocPerRowOut;
648 checkInternalState ();
651 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
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,
656 const Teuchos::ArrayRCP<const size_t>& numEntPerRow,
658 const Teuchos::RCP<Teuchos::ParameterList>& params) :
659 dist_object_type (rowMap)
662 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
663 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
664 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
665 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
666 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
668 , numAllocForAllRows_ (0)
669 , storageStatus_ (pftype == StaticProfile ?
672 , indicesAreAllocated_ (false)
673 , indicesAreLocal_ (false)
674 , indicesAreGlobal_ (false)
675 , fillComplete_ (false)
676 , lowerTriangular_ (false)
677 , upperTriangular_ (false)
678 , indicesAreSorted_ (true)
679 , noRedundancies_ (true)
680 , haveLocalConstants_ (false)
681 , haveGlobalConstants_ (false)
682 , sortGhostsAssociatedWithEachProcessor_ (true)
684 const char tfecfFuncName[] =
"CrsGraph(RCP<const Map>,RCP<const Map>,"
685 "ArrayRCP<const size_t>,ProfileType,RCP<ParameterList>): ";
688 const size_t lclNumRows = rowMap.is_null () ?
689 static_cast<size_t> (0) : rowMap->getNodeNumElements ();
690 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
691 static_cast<size_t> (numEntPerRow.size ()) != lclNumRows,
692 std::invalid_argument,
"numEntPerRow has length " << numEntPerRow.size ()
693 <<
" != the local number of rows " << lclNumRows <<
" as specified by "
694 "the input row Map.");
698 for (
size_t r = 0; r < lclNumRows; ++r) {
699 const size_t curRowCount = numEntPerRow[r];
700 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
701 (curRowCount == Teuchos::OrdinalTraits<size_t>::invalid (),
702 std::invalid_argument,
"numEntPerRow(" << r <<
") "
703 "specifies an invalid number of entries "
704 "(Teuchos::OrdinalTraits<size_t>::invalid()).");
711 typedef decltype (k_numAllocPerRow_) out_view_type;
712 typedef typename out_view_type::non_const_type nc_view_type;
713 typedef Kokkos::View<
const size_t*,
714 typename nc_view_type::array_layout,
716 Kokkos::MemoryUnmanaged> in_view_type;
717 in_view_type numAllocPerRowIn (numEntPerRow.getRawPtr (), lclNumRows);
718 nc_view_type numAllocPerRowOut (
"Tpetra::CrsGraph::numAllocPerRow",
721 k_numAllocPerRow_ = numAllocPerRowOut;
724 checkInternalState ();
726 #endif // TPETRA_ENABLE_DEPRECATED_CODE
728 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
730 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
731 const Teuchos::RCP<const map_type>& colMap,
732 const typename local_graph_type::row_map_type& rowPointers,
733 const typename local_graph_type::entries_type::non_const_type& columnIndices,
734 const Teuchos::RCP<Teuchos::ParameterList>& ) :
738 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
739 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
740 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
741 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
742 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
743 , pftype_(StaticProfile)
744 , numAllocForAllRows_(0)
746 , indicesAreAllocated_(true)
747 , indicesAreLocal_(true)
748 , indicesAreGlobal_(false)
749 , fillComplete_(false)
750 , lowerTriangular_ (false)
751 , upperTriangular_ (false)
752 , indicesAreSorted_(true)
753 , noRedundancies_(true)
754 , haveLocalConstants_ (false)
755 , haveGlobalConstants_ (false)
756 , sortGhostsAssociatedWithEachProcessor_(true)
759 setAllIndices (rowPointers, columnIndices);
760 checkInternalState ();
763 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
765 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
766 const Teuchos::RCP<const map_type>& colMap,
767 const Teuchos::ArrayRCP<size_t>& rowPointers,
768 const Teuchos::ArrayRCP<LocalOrdinal> & columnIndices,
769 const Teuchos::RCP<Teuchos::ParameterList>& ) :
773 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
774 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
775 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
776 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
777 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
778 , pftype_ (StaticProfile)
779 , numAllocForAllRows_ (0)
781 , indicesAreAllocated_ (true)
782 , indicesAreLocal_ (true)
783 , indicesAreGlobal_ (false)
784 , fillComplete_ (false)
785 , lowerTriangular_ (false)
786 , upperTriangular_ (false)
787 , indicesAreSorted_ (true)
788 , noRedundancies_ (true)
789 , haveLocalConstants_ (false)
790 , haveGlobalConstants_ (false)
791 , sortGhostsAssociatedWithEachProcessor_ (true)
794 setAllIndices (rowPointers, columnIndices);
795 checkInternalState ();
798 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
800 CrsGraph (
const Teuchos::RCP<const map_type>& rowMap,
801 const Teuchos::RCP<const map_type>& colMap,
803 const Teuchos::RCP<Teuchos::ParameterList>& params)
812 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
815 const Teuchos::RCP<const map_type>& rowMap,
816 const Teuchos::RCP<const map_type>& colMap,
817 const Teuchos::RCP<const map_type>& domainMap,
818 const Teuchos::RCP<const map_type>& rangeMap,
819 const Teuchos::RCP<Teuchos::ParameterList>& params)
823 , lclGraph_ (k_local_graph_)
824 , nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ())
825 , nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ())
826 , globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
827 , globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
828 , globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ())
829 , pftype_ (StaticProfile)
830 , numAllocForAllRows_ (0)
832 , indicesAreAllocated_ (true)
833 , indicesAreLocal_ (true)
834 , indicesAreGlobal_ (false)
835 , fillComplete_ (false)
836 , lowerTriangular_ (false)
837 , upperTriangular_ (false)
838 , indicesAreSorted_ (true)
839 , noRedundancies_ (true)
840 , haveLocalConstants_ (false)
841 , haveGlobalConstants_ (false)
842 , sortGhostsAssociatedWithEachProcessor_ (true)
845 const char tfecfFuncName[] =
"CrsGraph(Kokkos::LocalStaticCrsGraph,Map,Map,Map,Map)";
847 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
848 colMap.is_null (), std::runtime_error,
849 ": The input column Map must be nonnull.");
850 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
851 k_local_graph_.numRows () != rowMap->getNodeNumElements (),
853 ": The input row Map and the input local graph need to have the same "
854 "number of rows. The row Map claims " << rowMap->getNodeNumElements ()
855 <<
" row(s), but the local graph claims " << k_local_graph_.numRows ()
864 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
865 k_lclInds1D_.extent (0) != 0 || k_gblInds1D_.extent (0) != 0, std::logic_error,
866 ": cannot have 1D data structures allocated.");
867 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
868 ! lclInds2D_.is_null () || ! gblInds2D_.is_null (), std::logic_error,
869 ": cannot have 2D data structures allocated.");
871 setDomainRangeMaps (domainMap.is_null() ? rowMap_ : domainMap,
872 rangeMap .is_null() ? rowMap_ : rangeMap);
873 Teuchos::Array<int> remotePIDs (0);
874 this->makeImportExport (remotePIDs,
false);
876 k_lclInds1D_ = lclGraph_.entries;
877 k_rowPtrs_ = lclGraph_.row_map;
879 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
880 params->get (
"compute global constants",
true);
881 const bool computeLocalTriangularConstants = params.get () ==
nullptr ||
882 params->get (
"compute local triangular constants",
true);
884 if (callComputeGlobalConstants) {
885 this->computeGlobalConstants (computeLocalTriangularConstants);
887 this->fillComplete_ =
true;
888 this->checkInternalState ();
891 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
894 const Teuchos::RCP<const map_type>& rowMap,
895 const Teuchos::RCP<const map_type>& colMap,
896 const Teuchos::RCP<const map_type>& domainMap,
897 const Teuchos::RCP<const map_type>& rangeMap,
898 const Teuchos::RCP<const import_type>& importer,
899 const Teuchos::RCP<const export_type>& exporter,
900 const Teuchos::RCP<Teuchos::ParameterList>& params) :
904 rangeMap_ (rangeMap.is_null () ? rowMap : rangeMap),
905 domainMap_ (domainMap.is_null () ? rowMap : domainMap),
906 importer_ (importer),
907 exporter_ (exporter),
908 lclGraph_ (lclGraph),
909 nodeNumDiags_ (Teuchos::OrdinalTraits<size_t>::invalid ()),
910 nodeMaxNumRowEntries_ (Teuchos::OrdinalTraits<size_t>::invalid ()),
911 globalNumEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ()),
912 globalNumDiags_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ()),
913 globalMaxNumRowEntries_ (Teuchos::OrdinalTraits<
global_size_t>::invalid ()),
914 pftype_ (StaticProfile),
915 numAllocForAllRows_ (0),
917 indicesAreAllocated_ (true),
918 indicesAreLocal_ (true),
919 indicesAreGlobal_ (false),
920 fillComplete_ (false),
921 lowerTriangular_ (false),
922 upperTriangular_ (false),
923 indicesAreSorted_ (true),
924 noRedundancies_ (true),
925 haveLocalConstants_ (false),
926 haveGlobalConstants_ (false),
927 sortGhostsAssociatedWithEachProcessor_ (true)
930 const char tfecfFuncName[] =
"Tpetra::CrsGraph(local_graph_type,"
931 "Map,Map,Map,Map,Import,Export,params): ";
933 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
934 (colMap.is_null (), std::runtime_error,
935 "The input column Map must be nonnull.");
937 k_lclInds1D_ = lclGraph_.entries;
938 k_rowPtrs_ = lclGraph_.row_map;
939 const bool callComputeGlobalConstants =
940 params.get () ==
nullptr ||
941 params->get (
"compute global constants",
true);
942 const bool computeLocalTriangularConstants =
943 params.get () ==
nullptr ||
944 params->get (
"compute local triangular constants",
true);
945 if (callComputeGlobalConstants) {
946 this->computeGlobalConstants (computeLocalTriangularConstants);
948 fillComplete_ =
true;
949 checkInternalState ();
952 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
953 Teuchos::RCP<const Teuchos::ParameterList>
958 using Teuchos::ParameterList;
959 using Teuchos::parameterList;
961 RCP<ParameterList> params = parameterList (
"Tpetra::CrsGraph");
964 RCP<ParameterList> importSublist = parameterList (
"Import");
977 params->set (
"Import", *importSublist,
"How the Import performs communication.");
983 params->set (
"Export", *importSublist,
"How the Export performs communication.");
988 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
993 Teuchos::RCP<const Teuchos::ParameterList> validParams =
994 getValidParameters ();
995 params->validateParametersAndSetDefaults (*validParams);
996 this->setMyParamList (params);
999 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1004 return rowMap_->getGlobalNumElements ();
1007 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1012 const char tfecfFuncName[] =
"getGlobalNumCols: ";
1013 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
1014 ! isFillComplete () || getDomainMap ().is_null (), std::runtime_error,
1015 "The graph does not have a domain Map. You may not call this method in "
1017 return getDomainMap ()->getGlobalNumElements ();
1020 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1025 return this->rowMap_.is_null () ?
1026 static_cast<size_t> (0) :
1027 this->rowMap_->getNodeNumElements ();
1030 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1035 const char tfecfFuncName[] =
"getNodeNumCols: ";
1036 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
1037 ! hasColMap (), std::runtime_error,
1038 "The graph does not have a column Map. You may not call this method "
1039 "unless the graph has a column Map. This requires either that a custom "
1040 "column Map was given to the constructor, or that fillComplete() has "
1042 return colMap_.is_null () ?
static_cast<size_t> (0) :
1043 colMap_->getNodeNumElements ();
1046 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
1047 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1052 return this->getGlobalNumDiagsImpl ();
1055 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1056 size_t TPETRA_DEPRECATED
1060 return this->getNodeNumDiagsImpl ();
1063 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1068 const char tfecfFuncName[] =
"getGlobalNumDiags: ";
1069 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1070 (! this->haveGlobalConstants_, std::logic_error,
1071 "The graph does not have global constants computed, "
1072 "but the user has requested them.");
1074 return globalNumDiags_;
1077 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1082 return nodeNumDiags_;
1084 #endif // TPETRA_ENABLE_DEPRECATED_CODE
1086 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
1087 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1093 return Teuchos::null;
1095 #endif // TPETRA_ENABLE_DEPRECATED_CODE
1097 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1098 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
1105 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1106 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
1113 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1114 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
1121 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1122 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::map_type>
1129 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1130 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::import_type>
1137 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1138 Teuchos::RCP<const typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::export_type>
1145 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1150 return ! colMap_.is_null ();
1153 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1161 const bool isOpt = indicesAreAllocated_ &&
1162 k_numRowEntries_.extent (0) == 0 &&
1163 getNodeNumRows () > 0;
1165 const char tfecfFuncName[] =
"isStorageOptimized: ";
1166 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1167 (isOpt && getProfileType () != StaticProfile, std::logic_error,
1168 "The matrix claims to have optimized storage, but getProfileType() "
1169 "returns DynamicProfile. This should never happen. Please report this "
1170 "bug to the Tpetra developers.");
1175 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1183 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1188 const char tfecfFuncName[] =
"getGlobalNumEntries: ";
1189 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1190 (! this->haveGlobalConstants_, std::logic_error,
1191 "The graph does not have global constants computed, "
1192 "but the user has requested them.");
1194 return globalNumEntries_;
1197 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1202 typedef LocalOrdinal LO;
1204 if (this->indicesAreAllocated_) {
1205 const LO lclNumRows = this->getNodeNumRows ();
1206 if (lclNumRows == 0) {
1207 return static_cast<size_t> (0);
1211 auto numEntPerRow = this->k_numRowEntries_;
1212 const LO numNumEntPerRow = numEntPerRow.extent (0);
1213 if (numNumEntPerRow == 0) {
1214 if (
static_cast<LO
> (this->lclGraph_.row_map.extent (0)) <
1215 static_cast<LO
> (lclNumRows + 1)) {
1216 return static_cast<size_t> (0);
1219 return ::Tpetra::Details::getEntryOnHost (this->lclGraph_.row_map, lclNumRows);
1229 typedef typename num_row_entries_type::execution_space
1231 typedef Kokkos::RangePolicy<host_exec_space, LO> range_type;
1233 const LO upperLoopBound = lclNumRows < numNumEntPerRow ?
1236 size_t nodeNumEnt = 0;
1237 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::getNumNodeEntries",
1238 range_type (0, upperLoopBound),
1239 [=] (
const LO& k,
size_t& lclSum) {
1240 lclSum += numEntPerRow(k);
1247 return static_cast<size_t> (0);
1251 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1256 const char tfecfFuncName[] =
"getGlobalMaxNumRowEntries: ";
1257 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1258 (! this->haveGlobalConstants_, std::logic_error,
1259 "The graph does not have global constants computed, "
1260 "but the user has requested them.");
1262 return globalMaxNumRowEntries_;
1265 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1270 return nodeMaxNumRowEntries_;
1273 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1278 return fillComplete_;
1281 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1286 return ! fillComplete_;
1289 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
1290 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1291 bool TPETRA_DEPRECATED
1295 return this->isLowerTriangularImpl ();
1298 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1299 bool TPETRA_DEPRECATED
1303 return this->isUpperTriangularImpl ();
1306 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1308 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1309 isLowerTriangularImpl ()
const
1311 return this->lowerTriangular_;
1314 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1319 return this->upperTriangular_;
1321 #endif // TPETRA_ENABLE_DEPRECATED_CODE
1323 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1328 return indicesAreLocal_;
1331 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1336 return indicesAreGlobal_;
1339 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1344 typedef LocalOrdinal LO;
1346 if (this->indicesAreAllocated_) {
1347 const LO lclNumRows = this->getNodeNumRows ();
1348 if (lclNumRows == 0) {
1349 return static_cast<size_t> (0);
1351 else if (this->storageStatus_ == ::Tpetra::Details::STORAGE_1D_PACKED) {
1352 if (
static_cast<LO
> (this->lclGraph_.row_map.extent (0)) <
1353 static_cast<LO
> (lclNumRows + 1)) {
1354 return static_cast<size_t> (0);
1357 return ::Tpetra::Details::getEntryOnHost (this->lclGraph_.row_map, lclNumRows);
1360 else if (this->storageStatus_ == ::Tpetra::Details::STORAGE_1D_UNPACKED) {
1361 if (this->k_rowPtrs_.extent (0) == 0) {
1362 return static_cast<size_t> (0);
1365 return ::Tpetra::Details::getEntryOnHost (this->k_rowPtrs_, lclNumRows);
1368 else if (this->storageStatus_ == ::Tpetra::Details::STORAGE_2D) {
1369 size_t numAllocated = 0;
1370 if (this->isLocallyIndexed ()) {
1371 for (LocalOrdinal lclRow = 0; lclRow < lclNumRows; ++lclRow) {
1372 numAllocated += this->lclInds2D_[lclRow].size ();
1375 else if (this->isGloballyIndexed ()) {
1376 for (LocalOrdinal lclRow = 0; lclRow < lclNumRows; ++lclRow) {
1377 numAllocated += this->gblInds2D_[lclRow].size ();
1381 return numAllocated;
1384 return static_cast<size_t> (0);
1388 return Tpetra::Details::OrdinalTraits<size_t>::invalid ();
1392 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1393 Teuchos::RCP<const Teuchos::Comm<int> >
1397 return this->rowMap_.is_null () ? Teuchos::null : this->rowMap_->
getComm ();
1400 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1408 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1413 return indicesAreAllocated_;
1416 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1421 return indicesAreSorted_;
1424 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1429 return noRedundancies_;
1432 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1442 indicesAreSorted_ =
false;
1443 noRedundancies_ =
false;
1447 haveLocalConstants_ =
false;
1450 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1455 using Teuchos::arcp;
1456 using Teuchos::Array;
1457 using Teuchos::ArrayRCP;
1458 typedef Teuchos::ArrayRCP<size_t>::size_type size_type;
1459 typedef typename local_graph_type::row_map_type::non_const_type
1460 non_const_row_map_type;
1461 typedef typename local_graph_type::entries_type::non_const_type
1463 typedef Kokkos::View<GlobalOrdinal*,
1464 typename lcl_col_inds_type::array_layout,
1466 const char tfecfFuncName[] =
"allocateIndices: ";
1467 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1472 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1473 (this->isLocallyIndexed () && lg == GlobalIndices, std::logic_error,
1474 "The graph is locally indexed, but Tpetra code is calling this method "
1475 "with lg=GlobalIndices." << suffix);
1476 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1477 (this->isGloballyIndexed () && lg == LocalIndices, std::logic_error,
1478 "The graph is globally indexed, but Tpetra code is calling this method "
1479 "with lg=LocalIndices. " << suffix);
1480 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1481 (this->indicesAreAllocated (), std::logic_error,
"The graph's indices "
1482 "are already allocated, but Tpetra is calling allocateIndices again."
1484 const size_t numRows = this->getNodeNumRows ();
1486 if (this->getProfileType () == StaticProfile) {
1490 non_const_row_map_type k_rowPtrs (
"Tpetra::CrsGraph::ptr", numRows + 1);
1492 if (this->k_numAllocPerRow_.extent (0) != 0) {
1497 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1498 (this->k_numAllocPerRow_.extent (0) != numRows,
1499 std::invalid_argument,
"k_numAllocPerRow_ is allocated, that is, "
1500 "has nonzero length " << this->k_numAllocPerRow_.extent (0)
1501 <<
", but its length != numRows = " << numRows <<
".");
1519 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1520 (this->numAllocForAllRows_ ==
1521 Tpetra::Details::OrdinalTraits<size_t>::invalid (),
1522 std::invalid_argument,
"numAllocForAllRows_ has an invalid value, "
1523 "namely Tpetra::Details::OrdinalTraits<size_t>::invalid() = " <<
1524 Tpetra::Details::OrdinalTraits<size_t>::invalid () <<
".");
1531 this->k_rowPtrs_ = k_rowPtrs;
1533 const size_type numInds = ::Tpetra::Details::getEntryOnHost (this->k_rowPtrs_, numRows);
1535 if (lg == LocalIndices) {
1536 k_lclInds1D_ = lcl_col_inds_type (
"Tpetra::CrsGraph::ind", numInds);
1539 k_gblInds1D_ = gbl_col_inds_type (
"Tpetra::CrsGraph::ind", numInds);
1541 storageStatus_ = ::Tpetra::Details::STORAGE_1D_UNPACKED;
1547 const bool useNumAllocPerRow =
1548 (this->k_numAllocPerRow_.extent (0) != 0);
1550 if (lg == LocalIndices) {
1551 this->lclInds2D_ = arcp<Array<LocalOrdinal> > (numRows);
1552 for (
size_t i = 0; i < numRows; ++i) {
1553 const size_t howMany = useNumAllocPerRow ?
1554 this->k_numAllocPerRow_(i) :
1555 this->numAllocForAllRows_;
1557 this->lclInds2D_[i].resize (howMany);
1562 this->gblInds2D_ = arcp<Array<GlobalOrdinal> > (numRows);
1563 for (
size_t i = 0; i < numRows; ++i) {
1564 const size_t howMany = useNumAllocPerRow ?
1565 this->k_numAllocPerRow_(i) :
1566 this->numAllocForAllRows_;
1568 this->gblInds2D_[i].resize (howMany);
1572 this->storageStatus_ = ::Tpetra::Details::STORAGE_2D;
1575 this->indicesAreLocal_ = (lg == LocalIndices);
1576 this->indicesAreGlobal_ = (lg == GlobalIndices);
1579 using Kokkos::ViewAllocateWithoutInitializing;
1580 typedef decltype (k_numRowEntries_) row_ent_type;
1581 const char label[] =
"Tpetra::CrsGraph::numRowEntries";
1583 row_ent_type numRowEnt (ViewAllocateWithoutInitializing (label), numRows);
1585 this->k_numRowEntries_ = numRowEnt;
1589 this->numAllocForAllRows_ = 0;
1590 this->k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
1591 this->indicesAreAllocated_ =
true;
1594 this->checkInternalState ();
1596 catch (std::logic_error& e) {
1597 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1598 (
true, std::logic_error,
"At end of allocateIndices, "
1599 "checkInternalState threw std::logic_error: "
1602 catch (std::exception& e) {
1603 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1604 (
true, std::runtime_error,
"At end of allocateIndices, "
1605 "checkInternalState threw std::exception: "
1609 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1610 (
true, std::runtime_error,
"At end of allocateIndices, "
1611 "checkInternalState threw an exception "
1612 "not a subclass of std::exception.");
1616 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1617 Teuchos::ArrayView<const LocalOrdinal>
1621 using Kokkos::subview;
1622 typedef LocalOrdinal LO;
1624 Kokkos::MemoryUnmanaged> row_view_type;
1626 if (rowinfo.allocSize == 0) {
1627 return Teuchos::ArrayView<const LO> ();
1630 if (k_lclInds1D_.extent (0) != 0) {
1631 const size_t start = rowinfo.offset1D;
1632 const size_t len = rowinfo.allocSize;
1633 const std::pair<size_t, size_t> rng (start, start + len);
1639 row_view_type rowView = subview (row_view_type (k_lclInds1D_), rng);
1640 const LO*
const rowViewRaw = (len == 0) ?
nullptr : rowView.data ();
1641 return Teuchos::ArrayView<const LO> (rowViewRaw, len, Teuchos::RCP_DISABLE_NODE_LOOKUP);
1643 else if (! lclInds2D_[rowinfo.localRow].empty ()) {
1644 return lclInds2D_[rowinfo.localRow] ();
1647 return Teuchos::ArrayView<const LO> ();
1652 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1656 LocalOrdinal& capacity,
1661 #ifdef HAVE_TPETRA_DEBUG
1662 constexpr
bool debug =
true;
1664 constexpr
bool debug =
false;
1665 #endif // HAVE_TPETRA_DEBUG
1667 if (rowInfo.allocSize != 0) {
1668 if (k_lclInds1D_.extent (0) != 0) {
1670 if (rowInfo.offset1D + rowInfo.allocSize >
1671 static_cast<size_t> (k_lclInds1D_.extent (0))) {
1672 return static_cast<LocalOrdinal
> (-1);
1675 lclInds = &k_lclInds1D_[rowInfo.offset1D];
1676 capacity = rowInfo.allocSize;
1680 if (rowInfo.localRow >=
static_cast<size_t> (lclInds2D_.size ())) {
1681 return static_cast<LocalOrdinal
> (-1);
1686 const auto& curRow = lclInds2D_[rowInfo.localRow];
1687 if (! curRow.empty ()) {
1688 lclInds = curRow.getRawPtr ();
1689 capacity = curRow.size ();
1693 return static_cast<LocalOrdinal
> (0);
1696 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1697 Teuchos::ArrayView<LocalOrdinal>
1701 using Kokkos::subview;
1702 typedef LocalOrdinal LO;
1704 Kokkos::MemoryUnmanaged> row_view_type;
1706 if (rowinfo.allocSize == 0) {
1707 return Teuchos::ArrayView<LO> ();
1710 if (k_lclInds1D_.extent (0) != 0) {
1711 const size_t start = rowinfo.offset1D;
1712 const size_t len = rowinfo.allocSize;
1713 const std::pair<size_t, size_t> rng (start, start + len);
1719 row_view_type rowView = subview (row_view_type (k_lclInds1D_), rng);
1720 LO*
const rowViewRaw = (len == 0) ?
nullptr : rowView.data ();
1721 return Teuchos::ArrayView<LO> (rowViewRaw, len, Teuchos::RCP_DISABLE_NODE_LOOKUP);
1723 else if (! lclInds2D_[rowinfo.localRow].empty ()) {
1724 return lclInds2D_[rowinfo.localRow] ();
1727 return Teuchos::ArrayView<LO> ();
1733 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1734 Kokkos::View<
const LocalOrdinal*,
1736 Kokkos::MemoryUnmanaged>
1740 typedef LocalOrdinal LO;
1742 Kokkos::MemoryUnmanaged> row_view_type;
1744 if (rowInfo.allocSize == 0) {
1745 return row_view_type ();
1748 if (k_lclInds1D_.extent (0) != 0) {
1749 const size_t start = rowInfo.offset1D;
1750 const size_t len = rowInfo.allocSize;
1751 const std::pair<size_t, size_t> rng (start, start + len);
1757 return Kokkos::subview (row_view_type (k_lclInds1D_), rng);
1759 else if (! this->lclInds2D_[rowInfo.localRow].empty ()) {
1766 Teuchos::Array<LO>& lclInds = this->lclInds2D_[rowInfo.localRow];
1767 return row_view_type (lclInds.getRawPtr (), lclInds.size ());
1770 return row_view_type ();
1776 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1777 Kokkos::View<LocalOrdinal*,
1778 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::execution_space,
1779 Kokkos::MemoryUnmanaged>
1780 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1781 getLocalKokkosRowViewNonConst (
const RowInfo& rowInfo)
1783 typedef LocalOrdinal LO;
1785 Kokkos::MemoryUnmanaged> row_view_type;
1787 if (rowInfo.allocSize == 0) {
1788 return row_view_type ();
1791 if (k_lclInds1D_.extent (0) != 0) {
1792 const size_t start = rowInfo.offset1D;
1793 const size_t len = rowInfo.allocSize;
1794 const std::pair<size_t, size_t> rng (start, start + len);
1800 return Kokkos::subview (row_view_type (this->k_lclInds1D_), rng);
1802 else if (! this->lclInds2D_[rowInfo.localRow].empty ()) {
1809 Teuchos::Array<LO>& cols = this->lclInds2D_[rowInfo.localRow];
1810 LO*
const colsRaw = cols.getRawPtr ();
1811 return row_view_type (colsRaw, cols.size ());
1814 return row_view_type ();
1820 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1821 Kokkos::View<
const GlobalOrdinal*,
1822 typename CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::execution_space,
1823 Kokkos::MemoryUnmanaged>
1824 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1825 getGlobalKokkosRowView (
const RowInfo& rowinfo)
const
1827 typedef GlobalOrdinal GO;
1828 typedef Kokkos::View<
const GO*, execution_space,
1829 Kokkos::MemoryUnmanaged> row_view_type;
1831 if (rowinfo.allocSize == 0) {
1832 return row_view_type ();
1835 if (this->k_gblInds1D_.extent (0) != 0) {
1836 const size_t start = rowinfo.offset1D;
1837 const size_t len = rowinfo.allocSize;
1838 const std::pair<size_t, size_t> rng (start, start + len);
1844 return Kokkos::subview (row_view_type (this->k_gblInds1D_), rng);
1846 else if (! this->gblInds2D_[rowinfo.localRow].empty ()) {
1853 Teuchos::Array<GO>& cols = this->gblInds2D_[rowinfo.localRow];
1854 return row_view_type (cols.getRawPtr (), cols.size ());
1857 return row_view_type ();
1863 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1864 Teuchos::ArrayView<const GlobalOrdinal>
1868 Teuchos::ArrayView<const GlobalOrdinal> view;
1869 if (rowinfo.allocSize > 0) {
1870 if (k_gblInds1D_.extent (0) != 0) {
1871 auto rng = std::make_pair (rowinfo.offset1D,
1872 rowinfo.offset1D + rowinfo.allocSize);
1879 Kokkos::MemoryUnmanaged> k_gblInds1D_unmanaged = k_gblInds1D_;
1880 view = Kokkos::Compat::getConstArrayView (Kokkos::subview (k_gblInds1D_unmanaged, rng));
1882 else if (! gblInds2D_[rowinfo.localRow].empty()) {
1883 view = gblInds2D_[rowinfo.localRow] ();
1890 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1894 LocalOrdinal& capacity,
1899 #ifdef HAVE_TPETRA_DEBUG
1900 constexpr
bool debug =
true;
1902 constexpr
bool debug =
false;
1903 #endif // HAVE_TPETRA_DEBUG
1905 if (rowInfo.allocSize != 0) {
1906 if (k_gblInds1D_.extent (0) != 0) {
1908 if (rowInfo.offset1D + rowInfo.allocSize >
1909 static_cast<size_t> (k_gblInds1D_.extent (0))) {
1910 return static_cast<LocalOrdinal
> (-1);
1913 gblInds = &k_gblInds1D_[rowInfo.offset1D];
1914 capacity = rowInfo.allocSize;
1918 if (rowInfo.localRow >=
static_cast<size_t> (gblInds2D_.size ())) {
1919 return static_cast<LocalOrdinal
> (-1);
1922 const auto& curRow = gblInds2D_[rowInfo.localRow];
1923 if (! curRow.empty ()) {
1924 gblInds = curRow.getRawPtr ();
1925 capacity = curRow.size ();
1929 return static_cast<LocalOrdinal
> (0);
1933 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1934 Teuchos::ArrayView<GlobalOrdinal>
1938 Teuchos::ArrayView<GlobalOrdinal> view;
1939 if (rowinfo.allocSize > 0) {
1940 if (k_gblInds1D_.extent (0) != 0) {
1941 auto rng = std::make_pair (rowinfo.offset1D,
1942 rowinfo.offset1D + rowinfo.allocSize);
1949 Kokkos::MemoryUnmanaged> k_gblInds1D_unmanaged = k_gblInds1D_;
1950 view = Kokkos::Compat::getArrayView (Kokkos::subview (k_gblInds1D_unmanaged, rng));
1952 else if (! gblInds2D_[rowinfo.localRow].empty()) {
1953 view = gblInds2D_[rowinfo.localRow] ();
1960 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1965 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
1967 if (this->rowMap_.is_null () || ! this->rowMap_->isNodeLocalElement (myRow)) {
1968 ret.localRow = STINV;
1971 ret.offset1D = STINV;
1975 ret.localRow =
static_cast<size_t> (myRow);
1976 if (this->indicesAreAllocated ()) {
1977 if (this->getProfileType () == StaticProfile) {
1979 if (this->k_rowPtrs_.extent (0) == 0) {
1984 ret.offset1D = this->k_rowPtrs_(myRow);
1985 ret.allocSize = this->k_rowPtrs_(myRow+1) - this->k_rowPtrs_(myRow);
1988 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
1990 this->k_numRowEntries_(myRow);
1993 ret.offset1D = STINV;
1994 if (this->isLocallyIndexed ()) {
1995 ret.allocSize = (this->lclInds2D_.size () == 0) ?
1997 this->lclInds2D_[myRow].size ();
1999 else if (this->isGloballyIndexed ()) {
2000 ret.allocSize = (this->gblInds2D_.size () == 0) ?
2002 this->gblInds2D_[myRow].size ();
2008 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
2010 this->k_numRowEntries_(myRow);
2017 ret.allocSize = (this->k_numAllocPerRow_.extent (0) != 0) ?
2018 this->k_numAllocPerRow_(myRow) :
2019 this->numAllocForAllRows_;
2021 ret.offset1D = STINV;
2028 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2033 const size_t STINV = Teuchos::OrdinalTraits<size_t>::invalid ();
2035 if (this->rowMap_.is_null ()) {
2036 ret.localRow = STINV;
2039 ret.offset1D = STINV;
2042 const LocalOrdinal myRow = this->rowMap_->getLocalElement (gblRow);
2043 if (myRow == Teuchos::OrdinalTraits<LocalOrdinal>::invalid ()) {
2044 ret.localRow = STINV;
2047 ret.offset1D = STINV;
2051 ret.localRow =
static_cast<size_t> (myRow);
2052 if (this->indicesAreAllocated ()) {
2056 if (this->getProfileType() == StaticProfile) {
2057 if (this->k_rowPtrs_.extent (0) == 0) {
2062 ret.offset1D = this->k_rowPtrs_(myRow);
2063 ret.allocSize = this->k_rowPtrs_(myRow+1) - this->k_rowPtrs_(myRow);
2066 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
2068 this->k_numRowEntries_(myRow);
2071 ret.offset1D = STINV;
2072 if (this->isLocallyIndexed ()) {
2073 ret.allocSize = (this->lclInds2D_.size () == 0) ?
2075 this->lclInds2D_[myRow].size ();
2078 ret.allocSize = (this->gblInds2D_.size () == 0) ?
2080 this->gblInds2D_[myRow].size ();
2083 ret.numEntries = (this->k_numRowEntries_.extent (0) == 0) ?
2085 this->k_numRowEntries_(myRow);
2092 ret.allocSize = (this->k_numAllocPerRow_.extent (0) != 0) ?
2093 this->k_numAllocPerRow_(myRow) :
2094 this->numAllocForAllRows_;
2096 ret.offset1D = STINV;
2103 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2105 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
2106 staticAssertions ()
const
2108 using Teuchos::OrdinalTraits;
2109 typedef LocalOrdinal LO;
2110 typedef GlobalOrdinal GO;
2111 typedef global_size_t GST;
2116 static_assert (
sizeof (GlobalOrdinal) >=
sizeof (LocalOrdinal),
2117 "Tpetra::CrsGraph: sizeof(GlobalOrdinal) must be >= sizeof(LocalOrdinal).");
2120 static_assert (
sizeof (
size_t) >=
sizeof (LocalOrdinal),
2121 "Tpetra::CrsGraph: sizeof(size_t) must be >= sizeof(LocalOrdinal).");
2122 static_assert (
sizeof(GST) >=
sizeof(
size_t),
2123 "Tpetra::CrsGraph: sizeof(Tpetra::global_size_t) must be >= sizeof(size_t).");
2131 const char msg[] =
"Tpetra::CrsGraph: Object cannot be created with the "
2132 "given template arguments: size assumptions are not valid.";
2133 TEUCHOS_TEST_FOR_EXCEPTION(
2134 static_cast<size_t> (Teuchos::OrdinalTraits<LO>::max ()) > Teuchos::OrdinalTraits<size_t>::max (),
2135 std::runtime_error, msg);
2136 TEUCHOS_TEST_FOR_EXCEPTION(
2137 static_cast<GST
> (Teuchos::OrdinalTraits<LO>::max ()) >
static_cast<GST
> (Teuchos::OrdinalTraits<GO>::max ()),
2138 std::runtime_error, msg);
2139 TEUCHOS_TEST_FOR_EXCEPTION(
2140 static_cast<size_t> (Teuchos::OrdinalTraits<GO>::max ()) > Teuchos::OrdinalTraits<GST>::max(),
2141 std::runtime_error, msg);
2142 TEUCHOS_TEST_FOR_EXCEPTION(
2143 Teuchos::OrdinalTraits<size_t>::max () > Teuchos::OrdinalTraits<GST>::max (),
2144 std::runtime_error, msg);
2148 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2152 const SLocalGlobalViews &newInds,
2153 const ELocalGlobal lg,
2154 const ELocalGlobal I)
2156 using Teuchos::ArrayView;
2157 typedef LocalOrdinal LO;
2158 typedef GlobalOrdinal GO;
2159 const char tfecfFuncName[] =
"insertIndices: ";
2160 #ifdef HAVE_TPETRA_DEBUG
2161 constexpr
bool debug =
true;
2163 constexpr
bool debug =
false;
2164 #endif // HAVE_TPETRA_DEBUG
2166 size_t oldNumEnt = 0;
2168 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2169 (lg != GlobalIndices && lg != LocalIndices, std::invalid_argument,
2170 "lg must be either GlobalIndices or LocalIndices.");
2171 oldNumEnt = this->getNumEntriesInLocalRow (rowinfo.localRow);
2174 size_t numNewInds = 0;
2175 if (lg == GlobalIndices) {
2176 ArrayView<const GO> new_ginds = newInds.ginds;
2177 numNewInds = new_ginds.size();
2178 if (I == GlobalIndices) {
2179 ArrayView<GO> gind_view = this->getGlobalViewNonConst (rowinfo);
2181 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2182 (
static_cast<size_t> (gind_view.size ()) <
2183 rowinfo.numEntries + numNewInds, std::logic_error,
2184 "gind_view.size() = " << gind_view.size ()
2185 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
2186 <<
") + numNewInds (= " << numNewInds <<
").");
2188 GO*
const gblColInds_out = gind_view.getRawPtr () + rowinfo.numEntries;
2189 for (
size_t k = 0; k < numNewInds; ++k) {
2190 gblColInds_out[k] = new_ginds[k];
2193 else if (I == LocalIndices) {
2194 ArrayView<LO> lind_view = this->getLocalViewNonConst (rowinfo);
2196 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2197 (
static_cast<size_t> (lind_view.size ()) <
2198 rowinfo.numEntries + numNewInds, std::logic_error,
2199 "lind_view.size() = " << lind_view.size ()
2200 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
2201 <<
") + numNewInds (= " << numNewInds <<
").");
2203 LO*
const lclColInds_out = lind_view.getRawPtr () + rowinfo.numEntries;
2204 for (
size_t k = 0; k < numNewInds; ++k) {
2205 lclColInds_out[k] = colMap_->getLocalElement (new_ginds[k]);
2209 else if (lg == LocalIndices) {
2210 ArrayView<const LO> new_linds = newInds.linds;
2211 numNewInds = new_linds.size();
2212 if (I == LocalIndices) {
2213 ArrayView<LO> lind_view = this->getLocalViewNonConst (rowinfo);
2215 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2216 (
static_cast<size_t> (lind_view.size ()) <
2217 rowinfo.numEntries + numNewInds, std::logic_error,
2218 "lind_view.size() = " << lind_view.size ()
2219 <<
" < rowinfo.numEntries (= " << rowinfo.numEntries
2220 <<
") + numNewInds (= " << numNewInds <<
").");
2222 LO*
const lclColInds_out = lind_view.getRawPtr () + rowinfo.numEntries;
2223 for (
size_t k = 0; k < numNewInds; ++k) {
2224 lclColInds_out[k] = new_linds[k];
2227 else if (I == GlobalIndices) {
2228 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2229 (
true, std::logic_error,
"The case where the input indices are local "
2230 "and the indices to write are global (lg=LocalIndices, I="
2231 "GlobalIndices) is not implemented, because it does not make sense."
2232 << std::endl <<
"If you have correct local column indices, that "
2233 "means the graph has a column Map. In that case, you should be "
2234 "storing local indices.");
2238 rowinfo.numEntries += numNewInds;
2239 this->k_numRowEntries_(rowinfo.localRow) += numNewInds;
2240 this->setLocallyModified ();
2243 const size_t chkNewNumEnt =
2244 this->getNumEntriesInLocalRow (rowinfo.localRow);
2245 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2246 (chkNewNumEnt != oldNumEnt + numNewInds, std::logic_error,
2247 "chkNewNumEnt = " << chkNewNumEnt
2248 <<
" != oldNumEnt (= " << oldNumEnt
2249 <<
") + numNewInds (= " << numNewInds <<
").");
2255 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2259 const GlobalOrdinal inputGblColInds[],
2260 const size_t numInputInds)
2262 return this->insertGlobalIndicesImpl (this->getRowInfo (lclRow),
2263 inputGblColInds, numInputInds);
2266 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2270 const GlobalOrdinal inputGblColInds[],
2271 const size_t numInputInds,
2272 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
2275 using Kokkos::subview;
2276 using Kokkos::MemoryUnmanaged;
2277 using LO = LocalOrdinal;
2278 using GO = GlobalOrdinal;
2279 const char tfecfFuncName[] =
"insertGlobalIndicesImpl: ";
2280 #ifdef HAVE_TPETRA_DEBUG
2281 constexpr
bool debug =
true;
2283 constexpr
bool debug =
false;
2284 #endif // HAVE_TPETRA_DEBUG
2286 const LO lclRow =
static_cast<LO
> (rowInfo.localRow);
2288 if (this->getProfileType () == StaticProfile) {
2289 auto numEntries = rowInfo.numEntries;
2290 using inp_view_type = View<const GO*, execution_space, MemoryUnmanaged>;
2291 inp_view_type inputInds(inputGblColInds, numInputInds);
2293 this->k_gblInds1D_, numEntries, inputInds, fun);
2294 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2295 numInserted == Teuchos::OrdinalTraits<size_t>::invalid(),
2297 "There is not enough capacity to insert indices in to row " << lclRow <<
2298 ". The upper bound on the number of entries in this row must be increased to "
2299 "accommodate one or more of the new indices.");
2300 this->k_numRowEntries_(lclRow) += numInserted;
2301 this->setLocallyModified();
2306 size_t newNumEntries = rowInfo.numEntries + numInputInds;
2307 if (newNumEntries > rowInfo.allocSize) {
2309 size_t newAllocSize = 2*rowInfo.allocSize;
2310 if (newAllocSize < newNumEntries) {
2311 newAllocSize = newNumEntries;
2313 this->gblInds2D_[lclRow].resize (newAllocSize);
2317 GO*
const whereToPutGblColInds =
2318 this->gblInds2D_[lclRow].getRawPtr () + rowInfo.numEntries;
2319 for (
size_t k_new = 0; k_new < numInputInds; ++k_new) {
2320 whereToPutGblColInds[k_new] = inputGblColInds[k_new];
2322 this->k_numRowEntries_(lclRow) += numInputInds;
2323 this->setLocallyModified ();
2326 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow (lclRow);
2327 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2328 (chkNewNumEntries != newNumEntries, std::logic_error,
2329 "getNumEntriesInLocalRow(lclRow=" << lclRow <<
") = "
2330 << chkNewNumEntries <<
" != newNumEntries = " << newNumEntries
2331 <<
". Please report this bug to the Tpetra developers.");
2333 return numInputInds;
2338 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2340 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
2341 insertLocalIndicesImpl (
const LocalOrdinal myRow,
2342 const Teuchos::ArrayView<const LocalOrdinal>& indices,
2343 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
2345 using Kokkos::MemoryUnmanaged;
2346 using Kokkos::subview;
2348 using LO = LocalOrdinal;
2349 const char tfecfFuncName[] =
"insertLocallIndicesImpl: ";
2351 const RowInfo rowInfo = this->getRowInfo(myRow);
2353 size_t numNewInds = 0;
2354 size_t newNumEntries = 0;
2356 if (this->getProfileType () == StaticProfile) {
2357 auto numEntries = rowInfo.numEntries;
2359 using inp_view_type = View<const LO*, Kokkos::HostSpace, MemoryUnmanaged>;
2360 inp_view_type inputInds(indices.getRawPtr(), indices.size());
2362 this->k_lclInds1D_, numEntries, inputInds, fun);
2363 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2364 numInserted == Teuchos::OrdinalTraits<size_t>::invalid(),
2366 "There is not enough capacity to insert indices in to row " << myRow <<
2367 ". The upper bound on the number of entries in this row must be increased to "
2368 "accommodate one or more of the new indices.");
2369 numNewInds = numInserted;
2370 newNumEntries = rowInfo.numEntries + numNewInds;
2374 numNewInds = indices.size();
2375 newNumEntries = rowInfo.numEntries + numNewInds;
2376 if (newNumEntries > rowInfo.allocSize) {
2378 size_t newAllocSize = 2*rowInfo.allocSize;
2379 if (newAllocSize < newNumEntries) {
2380 newAllocSize = newNumEntries;
2382 this->lclInds2D_[myRow].resize(newAllocSize);
2384 std::copy (indices.begin (), indices.end (),
2385 this->lclInds2D_[myRow].begin () + rowInfo.numEntries);
2388 this->k_numRowEntries_(myRow) += numNewInds;
2389 this->setLocallyModified ();
2391 #ifdef HAVE_TPETRA_DEBUG
2392 constexpr
bool debug =
true;
2394 constexpr
bool debug =
false;
2395 #endif // HAVE_TPETRA_DEBUG
2398 const size_t chkNewNumEntries = this->getNumEntriesInLocalRow (myRow);
2399 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2400 (chkNewNumEntries != newNumEntries, std::logic_error,
2401 "getNumEntriesInLocalRow(" << myRow <<
") = " << chkNewNumEntries
2402 <<
" != newNumEntries = " << newNumEntries
2403 <<
". Please report this bug to the Tpetra developers.");
2408 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2412 const Teuchos::ArrayView<const LocalOrdinal>& indices,
2413 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
const
2415 #ifdef HAVE_TPETRA_DEBUG
2416 const char tfecfFuncName[] =
"findLocalIndices: ";
2417 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2418 (this->getProfileType() != StaticProfile, std::runtime_error,
2419 "findLocalIndices requires that the graph have StaticProfile.");
2420 #endif // HAVE_TPETRA_DEBUG
2421 using LO = LocalOrdinal;
2422 using inp_view_type = Kokkos::View<
const LO*, Kokkos::HostSpace,
2423 Kokkos::MemoryUnmanaged>;
2424 inp_view_type inputInds(indices.getRawPtr(), indices.size());
2426 size_t numFound = 0;
2427 LO lclRow = rowInfo.localRow;
2428 if (this->isLocallyIndexed())
2431 this->k_lclInds1D_, inputInds, fun);
2433 else if (this->isGloballyIndexed())
2435 if (this->colMap_.is_null())
2436 return Teuchos::OrdinalTraits<size_t>::invalid();
2437 const auto& colMap = *(this->colMap_);
2438 auto map = [&](LO
const lclInd){
return colMap.getGlobalElement(lclInd);};
2440 this->k_gblInds1D_, inputInds, map, fun);
2446 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2450 const Teuchos::ArrayView<const GlobalOrdinal>& indices,
2451 std::function<
void(
const size_t,
const size_t,
const size_t)> fun)
const
2453 const char tfecfFuncName[] =
"findGlobalIndices: ";
2454 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2455 this->getProfileType() != StaticProfile,
2457 "findLocalIndices requires the graph have StaticProfile");
2459 using GO = GlobalOrdinal;
2461 using Kokkos::MemoryUnmanaged;
2462 auto invalidCount = Teuchos::OrdinalTraits<size_t>::invalid();
2464 using inp_view_type = View<const GO*, execution_space, MemoryUnmanaged>;
2465 inp_view_type inputInds(indices.getRawPtr(), indices.size());
2467 size_t numFound = 0;
2468 LocalOrdinal lclRow = rowInfo.localRow;
2469 if (this->isLocallyIndexed())
2471 if (this->colMap_.is_null())
2472 return invalidCount;
2473 const auto& colMap = *(this->colMap_);
2474 auto map = [&](GO
const gblInd){
return colMap.getLocalElement(gblInd);};
2476 this->k_lclInds1D_, inputInds, map, fun);
2478 else if (this->isGloballyIndexed())
2481 this->k_gblInds1D_, inputInds, fun);
2487 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2494 const size_t origNumEnt = rowInfo.numEntries;
2495 if (origNumEnt != Tpetra::Details::OrdinalTraits<size_t>::invalid () &&
2497 auto lclColInds = this->getLocalKokkosRowViewNonConst (rowInfo);
2499 LocalOrdinal*
const lclColIndsRaw = lclColInds.data ();
2502 std::sort (lclColIndsRaw, lclColIndsRaw + origNumEnt);
2506 LocalOrdinal*
const beg = lclColIndsRaw;
2507 LocalOrdinal*
const end = beg + rowInfo.numEntries;
2509 LocalOrdinal*
const newend = std::unique (beg, end);
2510 const size_t newNumEnt = newend - beg;
2513 this->k_numRowEntries_(rowInfo.localRow) = newNumEnt;
2514 return origNumEnt - newNumEnt;
2517 return static_cast<size_t> (0);
2521 return static_cast<size_t> (0);
2526 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2530 const Teuchos::RCP<const map_type>& rangeMap)
2533 if (domainMap_ != domainMap) {
2534 domainMap_ = domainMap;
2535 importer_ = Teuchos::null;
2537 if (rangeMap_ != rangeMap) {
2538 rangeMap_ = rangeMap;
2539 exporter_ = Teuchos::null;
2544 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2549 globalNumEntries_ = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2550 globalNumDiags_ = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2551 globalMaxNumRowEntries_ = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2552 haveGlobalConstants_ =
false;
2556 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2563 const char tfecfFuncName[] =
"checkInternalState: ";
2564 const char suffix[] =
" Please report this bug to the Tpetra developers.";
2566 const global_size_t GSTI = Teuchos::OrdinalTraits<global_size_t>::invalid ();
2572 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2573 (this->rowMap_.is_null (), std::logic_error,
2574 "Row Map is null." << suffix);
2577 const LocalOrdinal lclNumRows =
2578 static_cast<LocalOrdinal
> (this->getNodeNumRows ());
2580 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2581 (this->isFillActive () == this->isFillComplete (), std::logic_error,
2582 "Graph cannot be both fill active and fill complete." << suffix);
2583 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2584 (this->isFillComplete () &&
2585 (this->colMap_.is_null () ||
2586 this->rangeMap_.is_null () ||
2587 this->domainMap_.is_null ()),
2589 "Graph is full complete, but at least one of {column, range, domain} "
2590 "Map is null." << suffix);
2591 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2592 (this->isStorageOptimized () && ! this->indicesAreAllocated (),
2593 std::logic_error,
"Storage is optimized, but indices are not "
2594 "allocated, not even trivially." << suffix);
2595 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2596 (this->indicesAreAllocated_ &&
2597 (this->storageStatus_ == ::Tpetra::Details::STORAGE_1D_PACKED ||
2598 this->storageStatus_ == ::Tpetra::Details::STORAGE_1D_UNPACKED) &&
2599 this->pftype_ != StaticProfile, std::logic_error,
2600 "Graph claims to have allocated indices and 1-D storage "
2601 "(either packed or unpacked), but also claims to be DynamicProfile.");
2602 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2603 (this->indicesAreAllocated_ &&
2604 this->storageStatus_ == ::Tpetra::Details::STORAGE_2D &&
2605 this->pftype_ == StaticProfile, std::logic_error,
2606 "Graph claims to have allocated indices and 2-D storage, "
2607 "but also claims to be StaticProfile.");
2608 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2609 (this->indicesAreAllocated_ &&
2610 this->storageStatus_ == ::Tpetra::Details::STORAGE_2D &&
2611 this->isLocallyIndexed () &&
2612 static_cast<LocalOrdinal
> (this->lclInds2D_.size ()) != lclNumRows,
2614 "Graph claims to have allocated indices, be locally indexed, and have "
2615 "2-D storage, but lclInds2D_.size() = " << this->lclInds2D_.size ()
2616 <<
" != getNodeNumRows() = " << lclNumRows <<
".");
2617 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2618 (this->indicesAreAllocated_ &&
2619 this->storageStatus_ == ::Tpetra::Details::STORAGE_2D &&
2620 this->isGloballyIndexed () &&
2621 static_cast<LocalOrdinal
> (this->gblInds2D_.size ()) != lclNumRows,
2623 "Graph claims to have allocated indices, be globally indexed, and have "
2624 "2-D storage, but gblInds2D_.size() = " << this->gblInds2D_.size ()
2625 <<
" != getNodeNumRows() = " << lclNumRows <<
".");
2627 size_t nodeAllocSize = 0;
2629 nodeAllocSize = this->getNodeAllocationSize ();
2631 catch (std::logic_error& e) {
2632 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2633 (
true, std::runtime_error,
"getNodeAllocationSize threw "
2634 "std::logic_error: " << e.what ());
2636 catch (std::exception& e) {
2637 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2638 (
true, std::runtime_error,
"getNodeAllocationSize threw an "
2639 "std::exception: " << e.what ());
2642 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2643 (
true, std::runtime_error,
"getNodeAllocationSize threw an exception "
2644 "not a subclass of std::exception.");
2647 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2648 (this->isStorageOptimized () &&
2649 nodeAllocSize != this->getNodeNumEntries (),
2650 std::logic_error,
"Storage is optimized, but "
2651 "this->getNodeAllocationSize() = " << nodeAllocSize
2652 <<
" != this->getNodeNumEntries() = " << this->getNodeNumEntries ()
2654 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2655 (! this->haveGlobalConstants_ &&
2656 (this->globalNumEntries_ != GSTI ||
2657 this->globalMaxNumRowEntries_ != GSTI),
2658 std::logic_error,
"Graph claims not to have global constants, but "
2659 "some of the global constants are not marked as invalid." << suffix);
2660 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2661 (this->haveGlobalConstants_ &&
2662 (this->globalNumEntries_ == GSTI ||
2663 this->globalMaxNumRowEntries_ == GSTI),
2664 std::logic_error,
"Graph claims to have global constants, but "
2665 "some of them are marked as invalid." << suffix);
2666 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2667 (this->haveGlobalConstants_ &&
2668 (this->globalNumEntries_ < this->getNodeNumEntries () ||
2669 this->globalMaxNumRowEntries_ < this->nodeMaxNumRowEntries_),
2670 std::logic_error,
"Graph claims to have global constants, and "
2671 "all of the values of the global constants are valid, but "
2672 "some of the local constants are greater than "
2673 "their corresponding global constants." << suffix);
2674 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2675 (this->indicesAreAllocated () &&
2676 (this->numAllocForAllRows_ != 0 ||
2677 this->k_numAllocPerRow_.extent (0) != 0),
2678 std::logic_error,
"The graph claims that its indices are allocated, but "
2679 "either numAllocForAllRows_ (= " << this->numAllocForAllRows_ <<
") is "
2680 "nonzero, or k_numAllocPerRow_ has nonzero dimension. In other words, "
2681 "the graph is supposed to release its \"allocation specifications\" "
2682 "when it allocates its indices." << suffix);
2683 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2684 (this->isStorageOptimized () && this->pftype_ != StaticProfile,
2686 "Storage is optimized, but graph is not StaticProfile." << suffix);
2687 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2688 (this->isGloballyIndexed () &&
2689 this->k_rowPtrs_.extent (0) != 0 &&
2690 (
static_cast<size_t> (this->k_rowPtrs_.extent (0)) !=
static_cast<size_t> (lclNumRows + 1) ||
2691 this->k_rowPtrs_(lclNumRows) !=
static_cast<size_t> (this->k_gblInds1D_.extent (0))),
2692 std::logic_error,
"If k_rowPtrs_ has nonzero size and "
2693 "the graph is globally indexed, then "
2694 "k_rowPtrs_ must have N+1 rows, and "
2695 "k_rowPtrs_(N) must equal k_gblInds1D_.extent(0)." << suffix);
2696 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2697 (this->isLocallyIndexed () &&
2698 this->k_rowPtrs_.extent (0) != 0 &&
2699 (
static_cast<size_t> (k_rowPtrs_.extent (0)) !=
static_cast<size_t> (lclNumRows + 1) ||
2700 this->k_rowPtrs_(lclNumRows) !=
static_cast<size_t> (this->k_lclInds1D_.extent (0))),
2701 std::logic_error,
"If k_rowPtrs_ has nonzero size and "
2702 "the graph is locally indexed, then "
2703 "k_rowPtrs_ must have N+1 rows, and "
2704 "k_rowPtrs_(N) must equal k_lclInds1D_.extent(0)." << suffix);
2706 if (this->pftype_ != StaticProfile) {
2707 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2708 (this->indicesAreAllocated () &&
2709 this->getNodeNumRows () > 0 &&
2710 this->lclInds2D_.is_null () &&
2711 this->gblInds2D_.is_null (),
2712 std::logic_error,
"Graph has DynamicProfile, indices are allocated, and "
2713 "the calling process has nonzero rows, but 2-D column index storage "
2714 "(whether local or global) is not present." << suffix);
2715 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2716 (this->indicesAreAllocated () &&
2717 this->getNodeNumRows () > 0 &&
2718 this->k_numRowEntries_.extent (0) == 0,
2719 std::logic_error,
"Graph has DynamicProfile, indices are allocated, and "
2720 "the calling process has nonzero rows, but k_numRowEntries_ is not "
2721 "present." << suffix);
2722 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2723 (this->k_lclInds1D_.extent (0) != 0 ||
2724 this->k_gblInds1D_.extent (0) != 0,
2725 std::logic_error,
"Graph has DynamicProfile, but "
2726 "1-D allocations are present." << suffix);
2727 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2728 (this->k_rowPtrs_.extent (0) != 0,
2729 std::logic_error,
"Graph has DynamicProfile, but "
2730 "row offsets are present." << suffix);
2732 else if (this->pftype_ == StaticProfile) {
2733 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2734 (this->indicesAreAllocated () &&
2735 nodeAllocSize > 0 &&
2736 this->k_lclInds1D_.extent (0) == 0 &&
2737 this->k_gblInds1D_.extent (0) == 0,
2738 std::logic_error,
"Graph has StaticProfile and is allocated "
2739 "nonnontrivally, but 1-D allocations are not present." << suffix);
2740 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2741 (this->lclInds2D_ != Teuchos::null || this->gblInds2D_ != Teuchos::null,
2742 std::logic_error,
"Graph has StaticProfile, but 2-D allocations are "
2743 "present." << suffix);
2746 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2747 (! this->indicesAreAllocated () &&
2748 ((this->k_rowPtrs_.extent (0) != 0 ||
2749 this->k_numRowEntries_.extent (0) != 0) ||
2750 this->k_lclInds1D_.extent (0) != 0 ||
2751 this->lclInds2D_ != Teuchos::null ||
2752 this->k_gblInds1D_.extent (0) != 0 ||
2753 this->gblInds2D_ != Teuchos::null),
2754 std::logic_error,
"If indices are not allocated, "
2755 "then none of the buffers should be." << suffix);
2759 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2760 ((this->indicesAreLocal_ || this->indicesAreGlobal_) &&
2761 ! this->indicesAreAllocated_,
2762 std::logic_error,
"Indices may be local or global only if they are "
2763 "allocated." << suffix);
2764 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2765 (this->indicesAreLocal_ && this->indicesAreGlobal_,
2766 std::logic_error,
"Indices may not be both local and global." << suffix);
2767 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2768 (this->indicesAreLocal_ &&
2769 (this->k_gblInds1D_.extent (0) != 0 || ! this->gblInds2D_.is_null ()),
2770 std::logic_error,
"Indices are local, but either "
2771 "k_gblInds1D_.extent(0) (= "
2772 << this->k_gblInds1D_.extent (0) <<
") != 0, or "
2773 "gblInds2D_ is not null. In other words, if indices are local, "
2774 "then global allocations should not be present." << suffix);
2775 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2776 (this->indicesAreGlobal_ &&
2777 (this->k_lclInds1D_.extent (0) != 0 ||
2778 ! this->lclInds2D_.is_null ()),
2779 std::logic_error,
"Indices are global, but either "
2780 "k_lclInds1D_.extent(0) (= "
2781 << this->k_lclInds1D_.extent (0) <<
") != 0, or "
2782 "lclInds2D_ is not null. In other words, if indices are global, "
2783 "then local allocations should not be present." << suffix);
2784 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2785 (this->indicesAreLocal_ &&
2786 nodeAllocSize > 0 &&
2787 this->k_lclInds1D_.extent (0) == 0 &&
2788 this->getNodeNumRows () > 0 &&
2789 this->lclInds2D_.is_null (),
2790 std::logic_error,
"Indices are local, getNodeAllocationSize() = "
2791 << nodeAllocSize <<
" > 0, k_lclInds1D_.extent(0) = 0, "
2792 "getNodeNumRows() = " << this->getNodeNumRows () <<
" > 0, and "
2793 "lclInds2D_ is null." << suffix);
2794 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2795 (this->indicesAreGlobal_ &&
2796 nodeAllocSize > 0 &&
2797 this->k_gblInds1D_.extent (0) == 0 &&
2798 this->getNodeNumRows () > 0 &&
2799 this->gblInds2D_.is_null (),
2800 std::logic_error,
"Indices are global, getNodeAllocationSize() = "
2801 << nodeAllocSize <<
" > 0, k_gblInds1D_.extent(0) = 0, "
2802 "getNodeNumRows() = " << this->getNodeNumRows () <<
" > 0, and "
2803 "gblInds2D_ is null." << suffix);
2805 if (this->indicesAreAllocated () &&
2806 this->pftype_ == StaticProfile &&
2807 this->k_rowPtrs_.extent (0) != 0) {
2808 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2809 (
static_cast<size_t> (this->k_rowPtrs_.extent (0)) !=
2810 this->getNodeNumRows () + 1,
2811 std::logic_error,
"Graph is StaticProfile, indices are allocated, and "
2812 "k_rowPtrs_ has nonzero length, but k_rowPtrs_.extent(0) = "
2813 << this->k_rowPtrs_.extent (0) <<
" != getNodeNumRows()+1 = "
2814 << (this->getNodeNumRows () + 1) <<
"." << suffix);
2815 const size_t actualNumAllocated =
2816 ::Tpetra::Details::getEntryOnHost (this->k_rowPtrs_, this->getNodeNumRows ());
2817 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2818 (this->isLocallyIndexed () &&
2819 static_cast<size_t> (this->k_lclInds1D_.extent (0)) != actualNumAllocated,
2820 std::logic_error,
"Graph is StaticProfile and locally indexed, "
2821 "indices are allocated, and k_rowPtrs_ has nonzero length, but "
2822 "k_lclInds1D_.extent(0) = " << this->k_lclInds1D_.extent (0)
2823 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2824 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2825 (this->isGloballyIndexed () &&
2826 static_cast<size_t> (this->k_gblInds1D_.extent (0)) != actualNumAllocated,
2827 std::logic_error,
"Graph is StaticProfile and globally indexed, "
2828 "indices are allocated, and k_rowPtrs_ has nonzero length, but "
2829 "k_gblInds1D_.extent(0) = " << this->k_gblInds1D_.extent (0)
2830 <<
" != actualNumAllocated = " << actualNumAllocated << suffix);
2836 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2841 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (globalRow);
2842 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2843 return Teuchos::OrdinalTraits<size_t>::invalid ();
2846 return rowInfo.numEntries;
2851 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2856 const RowInfo rowInfo = this->getRowInfo (localRow);
2857 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2858 return Teuchos::OrdinalTraits<size_t>::invalid ();
2861 return rowInfo.numEntries;
2866 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2871 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (globalRow);
2872 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2873 return Teuchos::OrdinalTraits<size_t>::invalid ();
2876 return rowInfo.allocSize;
2881 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2886 const RowInfo rowInfo = this->getRowInfo (localRow);
2887 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2888 return Teuchos::OrdinalTraits<size_t>::invalid ();
2891 return rowInfo.allocSize;
2896 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2897 Teuchos::ArrayRCP<const size_t>
2901 using Kokkos::ViewAllocateWithoutInitializing;
2902 using Kokkos::create_mirror_view;
2903 using Teuchos::ArrayRCP;
2904 typedef typename local_graph_type::row_map_type row_map_type;
2905 typedef typename row_map_type::non_const_value_type row_offset_type;
2906 const char prefix[] =
"Tpetra::CrsGraph::getNodeRowPtrs: ";
2907 const char suffix[] =
" Please report this bug to the Tpetra developers.";
2910 const size_t size = k_rowPtrs_.extent (0);
2911 constexpr
bool same = std::is_same<size_t, row_offset_type>::value;
2914 return ArrayRCP<const size_t> ();
2917 ArrayRCP<const row_offset_type> ptr_rot;
2918 ArrayRCP<const size_t> ptr_st;
2923 typename row_map_type::HostMirror ptr_h = create_mirror_view (k_rowPtrs_);
2926 TEUCHOS_TEST_FOR_EXCEPTION
2927 (ptr_h.extent (0) != k_rowPtrs_.extent (0), std::logic_error,
2928 prefix <<
"size_t == row_offset_type, but ptr_h.extent(0) = "
2929 << ptr_h.extent (0) <<
" != k_rowPtrs_.extent(0) = "
2930 << k_rowPtrs_.extent (0) <<
".");
2931 TEUCHOS_TEST_FOR_EXCEPTION
2932 (same && size != 0 && k_rowPtrs_.data () ==
nullptr, std::logic_error,
2933 prefix <<
"size_t == row_offset_type and k_rowPtrs_.extent(0) = "
2934 << size <<
" != 0, but k_rowPtrs_.data() == nullptr." << suffix);
2935 TEUCHOS_TEST_FOR_EXCEPTION
2936 (same && size != 0 && ptr_h.data () ==
nullptr, std::logic_error,
2937 prefix <<
"size_t == row_offset_type and k_rowPtrs_.extent(0) = "
2938 << size <<
" != 0, but create_mirror_view(k_rowPtrs_).data() "
2939 "== nullptr." << suffix);
2941 ptr_rot = Kokkos::Compat::persistingView (ptr_h);
2944 typedef Kokkos::View<size_t*, device_type> ret_view_type;
2945 ret_view_type ptr_d (ViewAllocateWithoutInitializing (
"ptr"), size);
2947 typename ret_view_type::HostMirror ptr_h = create_mirror_view (ptr_d);
2949 ptr_st = Kokkos::Compat::persistingView (ptr_h);
2952 TEUCHOS_TEST_FOR_EXCEPTION
2953 (same && size != 0 && ptr_rot.is_null (), std::logic_error,
2954 prefix <<
"size_t == row_offset_type and size = " << size
2955 <<
" != 0, but ptr_rot is null." << suffix);
2956 TEUCHOS_TEST_FOR_EXCEPTION
2957 (! same && size != 0 && ptr_st.is_null (), std::logic_error,
2958 prefix <<
"size_t != row_offset_type and size = " << size
2959 <<
" != 0, but ptr_st is null." << suffix);
2964 ArrayRCP<const size_t> retval =
2965 Kokkos::Impl::if_c<same,
2966 ArrayRCP<const row_offset_type>,
2967 ArrayRCP<const size_t> >::select (ptr_rot, ptr_st);
2969 TEUCHOS_TEST_FOR_EXCEPTION
2970 (size != 0 && retval.is_null (), std::logic_error,
2971 prefix <<
"size = " << size <<
" != 0, but retval is null." << suffix);
2977 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2978 Teuchos::ArrayRCP<const LocalOrdinal>
2982 return Kokkos::Compat::persistingView (k_lclInds1D_);
2986 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2990 const Teuchos::ArrayView<LocalOrdinal>&indices,
2991 size_t& numEntries)
const
2993 using Teuchos::ArrayView;
2994 typedef LocalOrdinal LO;
2995 typedef GlobalOrdinal GO;
2996 const char tfecfFuncName[] =
"getLocalRowCopy: ";
2998 TEUCHOS_TEST_FOR_EXCEPTION(
2999 isGloballyIndexed () && ! hasColMap (), std::runtime_error,
3000 "Tpetra::CrsGraph::getLocalRowCopy: The graph is globally indexed and "
3001 "does not have a column Map yet. That means we don't have local indices "
3002 "for columns yet, so it doesn't make sense to call this method. If the "
3003 "graph doesn't have a column Map yet, you should call fillComplete on "
3008 const RowInfo rowinfo = this->getRowInfo (localRow);
3010 const size_t theNumEntries = rowinfo.numEntries;
3011 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3012 (
static_cast<size_t> (indices.size ()) < theNumEntries, std::runtime_error,
3013 "Specified storage (size==" << indices.size () <<
") does not suffice "
3014 "to hold all " << theNumEntries <<
" entry/ies for this row.");
3015 numEntries = theNumEntries;
3017 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
3018 if (isLocallyIndexed ()) {
3019 ArrayView<const LO> lview = getLocalView (rowinfo);
3020 for (
size_t j = 0; j < theNumEntries; ++j) {
3021 indices[j] = lview[j];
3024 else if (isGloballyIndexed ()) {
3025 ArrayView<const GO> gview = getGlobalView (rowinfo);
3026 for (
size_t j = 0; j < theNumEntries; ++j) {
3027 indices[j] = colMap_->getLocalElement (gview[j]);
3034 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3038 const Teuchos::ArrayView<GlobalOrdinal>& indices,
3039 size_t& numEntries)
const
3041 using Teuchos::ArrayView;
3042 const char tfecfFuncName[] =
"getGlobalRowCopy: ";
3046 const RowInfo rowinfo = getRowInfoFromGlobalRowIndex (globalRow);
3047 const size_t theNumEntries = rowinfo.numEntries;
3048 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3049 static_cast<size_t> (indices.size ()) < theNumEntries, std::runtime_error,
3050 "Specified storage (size==" << indices.size () <<
") does not suffice "
3051 "to hold all " << theNumEntries <<
" entry/ies for this row.");
3052 numEntries = theNumEntries;
3054 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
3055 if (isLocallyIndexed ()) {
3056 ArrayView<const LocalOrdinal> lview = getLocalView (rowinfo);
3057 for (
size_t j = 0; j < theNumEntries; ++j) {
3058 indices[j] = colMap_->getGlobalElement (lview[j]);
3061 else if (isGloballyIndexed ()) {
3062 ArrayView<const GlobalOrdinal> gview = getGlobalView (rowinfo);
3063 for (
size_t j = 0; j < theNumEntries; ++j) {
3064 indices[j] = gview[j];
3071 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3075 Teuchos::ArrayView<const LocalOrdinal>& indices)
const
3077 const char tfecfFuncName[] =
"getLocalRowView: ";
3078 #ifdef HAVE_TPETRA_DEBUG
3079 constexpr
bool debug =
true;
3081 constexpr
bool debug =
false;
3082 #endif // HAVE_TPETRA_DEBUG
3084 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3085 (isGloballyIndexed (), std::runtime_error,
"The graph's indices are "
3086 "currently stored as global indices, so we cannot return a view with "
3087 "local column indices, whether or not the graph has a column Map. If "
3088 "the graph _does_ have a column Map, use getLocalRowCopy() instead.");
3092 const RowInfo rowInfo = getRowInfo (localRow);
3093 indices = Teuchos::null;
3094 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
3095 rowInfo.numEntries > 0) {
3096 indices = this->getLocalView (rowInfo);
3101 indices = indices (0, rowInfo.numEntries);
3105 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3106 (
static_cast<size_t> (indices.size ()) !=
3107 getNumEntriesInLocalRow (localRow), std::logic_error,
"indices.size() "
3108 "= " << indices.size () <<
" != getNumEntriesInLocalRow(localRow=" <<
3109 localRow <<
") = " << getNumEntriesInLocalRow (localRow) <<
3110 ". Please report this bug to the Tpetra developers.");
3115 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3119 Teuchos::ArrayView<const GlobalOrdinal>& indices)
const
3121 const char tfecfFuncName[] =
"getGlobalRowView: ";
3122 #ifdef HAVE_TPETRA_DEBUG
3123 constexpr
bool debug =
true;
3125 constexpr
bool debug =
false;
3126 #endif // HAVE_TPETRA_DEBUG
3128 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3129 (isLocallyIndexed (), std::runtime_error,
"The graph's indices are "
3130 "currently stored as local indices, so we cannot return a view with "
3131 "global column indices. Use getGlobalRowCopy() instead.");
3135 const RowInfo rowInfo = getRowInfoFromGlobalRowIndex (globalRow);
3136 indices = Teuchos::null;
3137 if (rowInfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
3138 rowInfo.numEntries > 0) {
3139 indices = (this->getGlobalView (rowInfo)) (0, rowInfo.numEntries);
3143 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3144 (
static_cast<size_t> (indices.size ()) !=
3145 getNumEntriesInGlobalRow (globalRow),
3146 std::logic_error,
"indices.size() = " << indices.size ()
3147 <<
" != getNumEntriesInGlobalRow(globalRow=" << globalRow <<
") = "
3148 << getNumEntriesInGlobalRow (globalRow)
3149 <<
". Please report this bug to the Tpetra developers.");
3154 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3158 const Teuchos::ArrayView<const LocalOrdinal>& indices)
3160 const char tfecfFuncName[] =
"insertLocalIndices: ";
3162 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3163 (! isFillActive (), std::runtime_error,
"Fill must be active.");
3164 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3165 (isGloballyIndexed (), std::runtime_error,
3166 "Graph indices are global; use insertGlobalIndices().");
3167 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3168 (! hasColMap (), std::runtime_error,
3169 "Cannot insert local indices without a column Map.");
3170 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3171 (! rowMap_->isNodeLocalElement (localRow), std::runtime_error,
3172 "Local row index " << localRow <<
" is not in the row Map "
3173 "on the calling process.");
3174 if (! indicesAreAllocated ()) {
3175 allocateIndices (LocalIndices);
3178 #ifdef HAVE_TPETRA_DEBUG
3179 constexpr
bool debug =
true;
3181 constexpr
bool debug =
false;
3182 #endif // HAVE_TPETRA_DEBUG
3190 using Teuchos::Array;
3191 using Teuchos::toString;
3193 typedef typename Teuchos::ArrayView<const LocalOrdinal>::size_type size_type;
3196 Array<LocalOrdinal> badColInds;
3197 bool allInColMap =
true;
3198 for (size_type k = 0; k < indices.size (); ++k) {
3200 allInColMap =
false;
3201 badColInds.push_back (indices[k]);
3204 if (! allInColMap) {
3205 std::ostringstream os;
3206 os <<
"Tpetra::CrsGraph::insertLocalIndices: You attempted to insert "
3207 "entries in owned row " << localRow <<
", at the following column "
3208 "indices: " << toString (indices) <<
"." << endl;
3209 os <<
"Of those, the following indices are not in the column Map on "
3210 "this process: " << toString (badColInds) <<
"." << endl <<
"Since "
3211 "the graph has a column Map already, it is invalid to insert entries "
3212 "at those locations.";
3213 TEUCHOS_TEST_FOR_EXCEPTION(! allInColMap, std::invalid_argument, os.str ());
3218 insertLocalIndicesImpl (localRow, indices);
3221 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3222 (! indicesAreAllocated () || ! isLocallyIndexed (), std::logic_error,
3223 "At the end of insertLocalIndices, ! indicesAreAllocated() || "
3224 "! isLocallyIndexed() is true. Please report this bug to the "
3225 "Tpetra developers.");
3229 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3233 const LocalOrdinal numEnt,
3234 const LocalOrdinal inds[])
3236 Teuchos::ArrayView<const LocalOrdinal> indsT (inds, numEnt);
3237 this->insertLocalIndices (localRow, indsT);
3241 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3245 const LocalOrdinal numInputInds,
3246 const GlobalOrdinal inputGblColInds[])
3248 typedef LocalOrdinal LO;
3249 const char tfecfFuncName[] =
"insertGlobalIndices: ";
3250 #ifdef HAVE_TPETRA_DEBUG
3251 constexpr
bool debug =
true;
3253 constexpr
bool debug =
false;
3254 #endif // HAVE_TPETRA_DEBUG
3256 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3257 (this->isLocallyIndexed (), std::runtime_error,
3258 "graph indices are local; use insertLocalIndices().");
3263 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3264 (! this->isFillActive (), std::runtime_error,
3265 "You are not allowed to call this method if fill is not active. "
3266 "If fillComplete has been called, you must first call resumeFill "
3267 "before you may insert indices.");
3268 if (! this->indicesAreAllocated ()) {
3269 this->allocateIndices (GlobalIndices);
3271 const LO lclRow = this->rowMap_->getLocalElement (gblRow);
3272 if (lclRow != Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
3274 if (this->hasColMap ()) {
3276 const map_type& colMap = * (this->colMap_);
3281 std::vector<GlobalOrdinal> badColInds;
3282 bool allInColMap =
true;
3283 for (LO k = 0; k < numInputInds; ++k) {
3285 allInColMap =
false;
3286 badColInds.push_back (inputGblColInds[k]);
3289 if (! allInColMap) {
3290 std::ostringstream os;
3291 os <<
"You attempted to insert entries in owned row " << gblRow
3292 <<
", at the following column indices: [";
3293 for (LO k = 0; k < numInputInds; ++k) {
3294 os << inputGblColInds[k];
3295 if (k +
static_cast<LO
> (1) < numInputInds) {
3299 os <<
"]." << endl <<
"Of those, the following indices are not in "
3300 "the column Map on this process: [";
3301 for (
size_t k = 0; k < badColInds.size (); ++k) {
3302 os << badColInds[k];
3303 if (k +
size_t (1) < badColInds.size ()) {
3307 os <<
"]." << endl <<
"Since the matrix has a column Map already, "
3308 "it is invalid to insert entries at those locations.";
3309 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3310 (
true, std::invalid_argument, os.str ());
3314 this->insertGlobalIndicesImpl (lclRow, inputGblColInds, numInputInds);
3317 this->insertGlobalIndicesIntoNonownedRows (gblRow, inputGblColInds,
3323 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3327 const Teuchos::ArrayView<const GlobalOrdinal>& inputGblColInds)
3329 this->insertGlobalIndices (gblRow, inputGblColInds.size (),
3330 inputGblColInds.getRawPtr ());
3334 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3338 const GlobalOrdinal gblColInds[],
3339 const LocalOrdinal numGblColInds)
3341 typedef LocalOrdinal LO;
3342 typedef GlobalOrdinal GO;
3343 const char tfecfFuncName[] =
"insertGlobalIndicesFiltered: ";
3345 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3346 (this->isLocallyIndexed (), std::runtime_error,
3347 "Graph indices are local; use insertLocalIndices().");
3352 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3353 (! this->isFillActive (), std::runtime_error,
3354 "You are not allowed to call this method if fill is not active. "
3355 "If fillComplete has been called, you must first call resumeFill "
3356 "before you may insert indices.");
3357 if (! this->indicesAreAllocated ()) {
3358 this->allocateIndices (GlobalIndices);
3361 Teuchos::ArrayView<const GO> gblColInds_av (gblColInds, numGblColInds);
3363 if (! this->colMap_.is_null ()) {
3364 const map_type& colMap = * (this->colMap_);
3367 while (curOffset < numGblColInds) {
3371 LO endOffset = curOffset;
3372 for ( ; endOffset < numGblColInds; ++endOffset) {
3374 if (lclCol == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
3381 const LO numIndInSeq = (endOffset - curOffset);
3382 if (numIndInSeq != 0) {
3383 this->insertGlobalIndicesImpl (lclRow, gblColInds + curOffset,
3389 curOffset = endOffset + 1;
3393 this->insertGlobalIndicesImpl (lclRow, gblColInds_av.getRawPtr (),
3394 gblColInds_av.size ());
3398 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3402 const GlobalOrdinal gblColInds[],
3403 const LocalOrdinal numGblColInds)
3408 std::vector<GlobalOrdinal>& nonlocalRow = this->nonlocals_[gblRow];
3409 for (LocalOrdinal k = 0; k < numGblColInds; ++k) {
3413 nonlocalRow.push_back (gblColInds[k]);
3417 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3422 const char tfecfFuncName[] =
"removeLocalIndices: ";
3423 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3424 ! isFillActive (), std::runtime_error,
"requires that fill is active.");
3425 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3426 isStorageOptimized (), std::runtime_error,
3427 "cannot remove indices after optimizeStorage() has been called.");
3428 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3429 isGloballyIndexed (), std::runtime_error,
"graph indices are global.");
3430 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3431 ! rowMap_->isNodeLocalElement (lrow), std::runtime_error,
3432 "Local row " << lrow <<
" is not in the row Map on the calling process.");
3433 if (! indicesAreAllocated ()) {
3434 allocateIndices (LocalIndices);
3439 clearGlobalConstants ();
3441 if (k_numRowEntries_.extent (0) != 0) {
3442 this->k_numRowEntries_(lrow) = 0;
3444 #ifdef HAVE_TPETRA_DEBUG
3445 constexpr
bool debug =
true;
3447 constexpr
bool debug =
false;
3448 #endif // HAVE_TPETRA_DEBUG
3451 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3452 (getNumEntriesInLocalRow (lrow) != 0 ||
3453 ! indicesAreAllocated () ||
3454 ! isLocallyIndexed (), std::logic_error,
3455 "Violated stated post-conditions. Please contact Tpetra team.");
3460 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3463 setAllIndices (
const typename local_graph_type::row_map_type& rowPointers,
3464 const typename local_graph_type::entries_type::non_const_type& columnIndices)
3466 const char tfecfFuncName[] =
"setAllIndices: ";
3467 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3468 ! hasColMap () || getColMap ().is_null (), std::runtime_error,
3469 "The graph must have a column Map before you may call this method.");
3470 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3471 static_cast<size_t> (rowPointers.size ()) != this->getNodeNumRows () + 1,
3472 std::runtime_error,
"rowPointers.size() = " << rowPointers.size () <<
3473 " != this->getNodeNumRows()+1 = " << (this->getNodeNumRows () + 1) <<
3479 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3480 ((this->k_lclInds1D_.extent (0) != 0 || this->k_gblInds1D_.extent (0) != 0),
3481 std::runtime_error,
"You may not call this method if 1-D data "
3482 "structures are already allocated.");
3484 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3485 (this->lclInds2D_ != Teuchos::null ||
3486 this->gblInds2D_ != Teuchos::null,
3487 std::runtime_error,
"You may not call this method if 2-D data "
3488 "structures are already allocated.");
3490 indicesAreAllocated_ =
true;
3491 indicesAreLocal_ =
true;
3492 pftype_ = StaticProfile;
3493 k_lclInds1D_ = columnIndices;
3494 k_rowPtrs_ = rowPointers;
3497 storageStatus_ = ::Tpetra::Details::STORAGE_1D_PACKED;
3505 numAllocForAllRows_ = 0;
3506 k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
3508 checkInternalState ();
3512 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3515 setAllIndices (
const Teuchos::ArrayRCP<size_t>& rowPointers,
3516 const Teuchos::ArrayRCP<LocalOrdinal>& columnIndices)
3519 typedef typename local_graph_type::row_map_type row_map_type;
3520 typedef typename row_map_type::array_layout layout_type;
3521 typedef typename row_map_type::non_const_value_type row_offset_type;
3522 typedef View<
size_t*, layout_type , Kokkos::HostSpace,
3523 Kokkos::MemoryUnmanaged> input_view_type;
3524 typedef typename row_map_type::non_const_type nc_row_map_type;
3526 const size_t size =
static_cast<size_t> (rowPointers.size ());
3527 constexpr
bool same = std::is_same<size_t, row_offset_type>::value;
3528 input_view_type ptr_in (rowPointers.getRawPtr (), size);
3530 nc_row_map_type ptr_rot (
"Tpetra::CrsGraph::ptr", size);
3536 input_view_type ptr_decoy (rowPointers.getRawPtr (), size);
3539 input_view_type>::select (ptr_rot, ptr_decoy),
3544 constexpr
bool inHostMemory =
3545 std::is_same<
typename row_map_type::memory_space,
3546 Kokkos::HostSpace>::value;
3557 View<size_t*, layout_type ,execution_space > ptr_st (
"Tpetra::CrsGraph::ptr", size);
3567 Kokkos::View<LocalOrdinal*, layout_type , execution_space > k_ind =
3568 Kokkos::Compat::getKokkosViewDeepCopy<device_type> (columnIndices ());
3569 setAllIndices (ptr_rot, k_ind);
3573 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3577 size_t& boundForAllLocalRows,
3578 bool& boundSameForAllLocalRows)
const
3580 const char tfecfFuncName[] =
"getNumEntriesPerLocalRowUpperBound: ";
3581 const char suffix[] =
" Please report this bug to the Tpetra developers.";
3586 Teuchos::ArrayRCP<const size_t> numEntriesPerRow;
3587 size_t numEntriesForAll = 0;
3588 bool allRowsSame =
true;
3590 const ptrdiff_t numRows =
static_cast<ptrdiff_t
> (this->getNodeNumRows ());
3592 if (this->indicesAreAllocated ()) {
3593 if (this->isStorageOptimized ()) {
3596 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3597 (this->getProfileType () != StaticProfile, std::logic_error,
3598 "The graph is not StaticProfile, but storage appears to be optimized."
3600 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3601 (numRows != 0 && k_rowPtrs_.extent (0) == 0, std::logic_error,
3602 "The graph has " << numRows <<
" (> 0) row" << (numRows != 1 ?
"s" :
"")
3603 <<
" on the calling process, but the k_rowPtrs_ array has zero entries."
3605 Teuchos::ArrayRCP<size_t> numEnt;
3607 numEnt = Teuchos::arcp<size_t> (numRows);
3612 bool allRowsReallySame =
false;
3613 for (ptrdiff_t i = 0; i < numRows; ++i) {
3614 numEnt[i] = this->k_rowPtrs_(i+1) - this->k_rowPtrs_(i);
3615 if (i != 0 && numEnt[i] != numEnt[i-1]) {
3616 allRowsReallySame =
false;
3619 if (allRowsReallySame) {
3621 numEntriesForAll = 0;
3623 numEntriesForAll = numEnt[1] - numEnt[0];
3628 numEntriesPerRow = numEnt;
3629 allRowsSame =
false;
3632 else if (k_numRowEntries_.extent (0) != 0) {
3637 numEntriesPerRow = Kokkos::Compat::persistingView (k_numRowEntries_);
3638 allRowsSame =
false;
3641 numEntriesForAll = 0;
3646 if (k_numAllocPerRow_.extent (0) != 0) {
3651 numEntriesPerRow = Kokkos::Compat::persistingView (k_numAllocPerRow_);
3652 allRowsSame =
false;
3655 numEntriesForAll = numAllocForAllRows_;
3660 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3661 (numEntriesForAll != 0 && numEntriesPerRow.size () != 0, std::logic_error,
3662 "numEntriesForAll and numEntriesPerRow are not consistent. The former "
3663 "is nonzero (" << numEntriesForAll <<
"), but the latter has nonzero "
3664 "size " << numEntriesPerRow.size () <<
"." << suffix);
3665 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3666 (numEntriesForAll != 0 && ! allRowsSame, std::logic_error,
3667 "numEntriesForAll and allRowsSame are not consistent. The former "
3668 "is nonzero (" << numEntriesForAll <<
"), but the latter is false."
3670 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3671 (numEntriesPerRow.size () != 0 && allRowsSame, std::logic_error,
3672 "numEntriesPerRow and allRowsSame are not consistent. The former has "
3673 "nonzero length " << numEntriesForAll <<
", but the latter is true."
3676 boundPerLocalRow = numEntriesPerRow;
3677 boundForAllLocalRows = numEntriesForAll;
3678 boundSameForAllLocalRows = allRowsSame;
3682 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3687 using Teuchos::Comm;
3688 using Teuchos::outArg;
3691 using Teuchos::REDUCE_MAX;
3692 using Teuchos::REDUCE_MIN;
3693 using Teuchos::reduceAll;
3695 typedef LocalOrdinal LO;
3696 typedef GlobalOrdinal GO;
3697 typedef typename Teuchos::Array<GO>::size_type size_type;
3698 const char tfecfFuncName[] =
"globalAssemble: ";
3700 RCP<const Comm<int> > comm = getComm ();
3702 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3703 (! isFillActive (), std::runtime_error,
"Fill must be active before "
3704 "you may call this method.");
3706 const size_t myNumNonlocalRows = this->nonlocals_.size ();
3713 const int iHaveNonlocalRows = (myNumNonlocalRows == 0) ? 0 : 1;
3714 int someoneHasNonlocalRows = 0;
3715 reduceAll<int, int> (*comm, REDUCE_MAX, iHaveNonlocalRows,
3716 outArg (someoneHasNonlocalRows));
3717 if (someoneHasNonlocalRows == 0) {
3731 RCP<const map_type> nonlocalRowMap;
3733 Teuchos::Array<size_t> numEntPerNonlocalRow (myNumNonlocalRows);
3735 Teuchos::Array<GO> myNonlocalGblRows (myNumNonlocalRows);
3736 size_type curPos = 0;
3737 for (
auto mapIter = this->nonlocals_.begin ();
3738 mapIter != this->nonlocals_.end ();
3739 ++mapIter, ++curPos) {
3740 myNonlocalGblRows[curPos] = mapIter->first;
3741 std::vector<GO>& gblCols = mapIter->second;
3742 std::sort (gblCols.begin (), gblCols.end ());
3743 auto vecLast = std::unique (gblCols.begin (), gblCols.end ());
3744 gblCols.erase (vecLast, gblCols.end ());
3745 numEntPerNonlocalRow[curPos] = gblCols.size ();
3756 GO myMinNonlocalGblRow = std::numeric_limits<GO>::max ();
3758 auto iter = std::min_element (myNonlocalGblRows.begin (),
3759 myNonlocalGblRows.end ());
3760 if (iter != myNonlocalGblRows.end ()) {
3761 myMinNonlocalGblRow = *iter;
3764 GO gblMinNonlocalGblRow = 0;
3765 reduceAll<int, GO> (*comm, REDUCE_MIN, myMinNonlocalGblRow,
3766 outArg (gblMinNonlocalGblRow));
3767 const GO indexBase = gblMinNonlocalGblRow;
3768 const global_size_t INV = Teuchos::OrdinalTraits<global_size_t>::invalid ();
3769 nonlocalRowMap = rcp (
new map_type (INV, myNonlocalGblRows (), indexBase, comm));
3777 RCP<crs_graph_type> nonlocalGraph =
3778 rcp (
new crs_graph_type (nonlocalRowMap, numEntPerNonlocalRow (),
3781 size_type curPos = 0;
3782 for (
auto mapIter = this->nonlocals_.begin ();
3783 mapIter != this->nonlocals_.end ();
3784 ++mapIter, ++curPos) {
3785 const GO gblRow = mapIter->first;
3786 std::vector<GO>& gblCols = mapIter->second;
3787 const LO numEnt =
static_cast<LO
> (numEntPerNonlocalRow[curPos]);
3788 nonlocalGraph->insertGlobalIndices (gblRow, numEnt, gblCols.data ());
3800 auto origRowMap = this->getRowMap ();
3801 const bool origRowMapIsOneToOne = origRowMap->isOneToOne ();
3803 if (origRowMapIsOneToOne) {
3804 export_type exportToOrig (nonlocalRowMap, origRowMap);
3814 export_type exportToOneToOne (nonlocalRowMap, oneToOneRowMap);
3820 crs_graph_type oneToOneGraph (oneToOneRowMap, 0);
3822 oneToOneGraph.doExport (*nonlocalGraph, exportToOneToOne,
Tpetra::INSERT);
3826 nonlocalGraph = Teuchos::null;
3829 import_type importToOrig (oneToOneRowMap, origRowMap);
3837 decltype (this->nonlocals_) newNonlocals;
3838 std::swap (this->nonlocals_, newNonlocals);
3840 checkInternalState ();
3844 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3847 resumeFill (
const Teuchos::RCP<Teuchos::ParameterList>& params)
3849 clearGlobalConstants();
3850 if (params != Teuchos::null) this->setParameterList (params);
3851 lowerTriangular_ =
false;
3852 upperTriangular_ =
false;
3854 indicesAreSorted_ =
true;
3855 noRedundancies_ =
true;
3856 fillComplete_ =
false;
3860 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3863 fillComplete (
const Teuchos::RCP<Teuchos::ParameterList>& params)
3875 Teuchos::RCP<const map_type> domMap = this->getDomainMap ();
3876 if (domMap.is_null ()) {
3877 domMap = this->getRowMap ();
3879 Teuchos::RCP<const map_type> ranMap = this->getRangeMap ();
3880 if (ranMap.is_null ()) {
3881 ranMap = this->getRowMap ();
3883 this->fillComplete (domMap, ranMap, params);
3887 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3890 fillComplete (
const Teuchos::RCP<const map_type>& domainMap,
3891 const Teuchos::RCP<const map_type>& rangeMap,
3892 const Teuchos::RCP<Teuchos::ParameterList>& params)
3894 const char tfecfFuncName[] =
"fillComplete: ";
3897 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3898 (! isFillActive () || isFillComplete (), std::runtime_error,
3899 "Graph fill state must be active (isFillActive() "
3900 "must be true) before calling fillComplete().");
3902 const int numProcs = getComm ()->getSize ();
3910 if (! params.is_null ()) {
3911 if (params->isParameter (
"sort column map ghost gids")) {
3912 sortGhostsAssociatedWithEachProcessor_ =
3913 params->get<
bool> (
"sort column map ghost gids",
3914 sortGhostsAssociatedWithEachProcessor_);
3916 else if (params->isParameter (
"Sort column Map ghost GIDs")) {
3917 sortGhostsAssociatedWithEachProcessor_ =
3918 params->get<
bool> (
"Sort column Map ghost GIDs",
3919 sortGhostsAssociatedWithEachProcessor_);
3925 bool assertNoNonlocalInserts =
false;
3926 if (! params.is_null ()) {
3927 assertNoNonlocalInserts =
3928 params->get<
bool> (
"No Nonlocal Changes", assertNoNonlocalInserts);
3934 if (! indicesAreAllocated ()) {
3937 allocateIndices (LocalIndices);
3940 allocateIndices (GlobalIndices);
3948 const bool mayNeedGlobalAssemble = ! assertNoNonlocalInserts && numProcs > 1;
3949 if (mayNeedGlobalAssemble) {
3955 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3956 (numProcs > 1 && this->nonlocals_.size() > 0, std::runtime_error,
3957 "The graph's communicator contains only one process, "
3958 "but there are nonlocal entries. "
3959 "This probably means that invalid entries were added to the graph.");
3964 setDomainRangeMaps (domainMap, rangeMap);
3970 Teuchos::Array<int> remotePIDs (0);
3971 const bool mustBuildColMap = ! this->hasColMap ();
3972 if (mustBuildColMap) {
3978 const std::pair<size_t, std::string> makeIndicesLocalResult =
3979 this->makeIndicesLocal ();
3981 using ::Tpetra::Details::gathervPrint;
3983 using Teuchos::REDUCE_MIN;
3984 using Teuchos::reduceAll;
3985 using Teuchos::outArg;
3987 RCP<const map_type> map = this->getMap ();
3988 RCP<const Teuchos::Comm<int> > comm;
3989 if (! map.is_null ()) {
3990 comm = map->getComm ();
3992 if (comm.is_null ()) {
3993 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3994 (makeIndicesLocalResult.first != 0, std::runtime_error,
3995 makeIndicesLocalResult.second);
3998 const int lclSuccess = (makeIndicesLocalResult.first == 0);
4000 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
4001 if (gblSuccess != 1) {
4002 std::ostringstream os;
4003 gathervPrint (os, makeIndicesLocalResult.second, *comm);
4004 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4005 (
true, std::runtime_error, os.str ());
4014 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4015 (makeIndicesLocalResult.first != 0, std::runtime_error,
4016 makeIndicesLocalResult.second);
4022 this->sortAndMergeAllIndices (this->isSorted (), this->isMerged ());
4027 this->makeImportExport (remotePIDs, mustBuildColMap);
4030 this->fillLocalGraph (params);
4032 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
4033 params->get (
"compute global constants",
true);
4034 const bool computeLocalTriangularConstants = params.get () ==
nullptr ||
4035 params->get (
"compute local triangular constants",
true);
4036 if (callComputeGlobalConstants) {
4037 this->computeGlobalConstants (computeLocalTriangularConstants);
4040 this->computeLocalConstants (computeLocalTriangularConstants);
4042 this->fillComplete_ =
true;
4043 this->checkInternalState ();
4047 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4051 const Teuchos::RCP<const map_type>& rangeMap,
4052 const Teuchos::RCP<const import_type>& importer,
4053 const Teuchos::RCP<const export_type>& exporter,
4054 const Teuchos::RCP<Teuchos::ParameterList>& params)
4056 const char tfecfFuncName[] =
"expertStaticFillComplete: ";
4057 #ifdef HAVE_TPETRA_MMM_TIMINGS
4059 if(!params.is_null())
4060 label = params->get(
"Timer Label",label);
4061 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
": ");
4062 using Teuchos::TimeMonitor;
4063 Teuchos::RCP<Teuchos::TimeMonitor> MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Setup"))));
4067 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4068 domainMap.is_null () || rangeMap.is_null (),
4069 std::runtime_error,
"The input domain Map and range Map must be nonnull.");
4070 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4071 pftype_ != StaticProfile, std::runtime_error,
"You may not call this "
4072 "method unless the graph is StaticProfile.");
4073 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4074 isFillComplete () || ! hasColMap (), std::runtime_error,
"You may not "
4075 "call this method unless the graph has a column Map.");
4076 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4077 getNodeNumRows () > 0 && k_rowPtrs_.extent (0) == 0,
4078 std::runtime_error,
"The calling process has getNodeNumRows() = "
4079 << getNodeNumRows () <<
" > 0 rows, but the row offsets array has not "
4081 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4082 static_cast<size_t> (k_rowPtrs_.extent (0)) != getNodeNumRows () + 1,
4083 std::runtime_error,
"The row offsets array has length " <<
4084 k_rowPtrs_.extent (0) <<
" != getNodeNumRows()+1 = " <<
4085 (getNodeNumRows () + 1) <<
".");
4100 numAllocForAllRows_ = 0;
4101 k_numAllocPerRow_ = decltype (k_numAllocPerRow_) ();
4102 indicesAreAllocated_ =
true;
4107 indicesAreLocal_ =
true;
4108 indicesAreGlobal_ =
false;
4111 #ifdef HAVE_TPETRA_MMM_TIMINGS
4113 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-Maps"))));
4115 setDomainRangeMaps (domainMap, rangeMap);
4118 indicesAreSorted_ =
true;
4119 noRedundancies_ =
true;
4122 #ifdef HAVE_TPETRA_MMM_TIMINGS
4124 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckI"))));
4127 importer_ = Teuchos::null;
4128 exporter_ = Teuchos::null;
4129 if (importer != Teuchos::null) {
4130 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4131 ! importer->getSourceMap ()->isSameAs (*getDomainMap ()) ||
4132 ! importer->getTargetMap ()->isSameAs (*getColMap ()),
4133 std::invalid_argument,
": importer does not match matrix maps.");
4134 importer_ = importer;
4138 #ifdef HAVE_TPETRA_MMM_TIMINGS
4140 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXcheckE"))));
4143 if (exporter != Teuchos::null) {
4144 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4145 ! exporter->getSourceMap ()->isSameAs (*getRowMap ()) ||
4146 ! exporter->getTargetMap ()->isSameAs (*getRangeMap ()),
4147 std::invalid_argument,
": exporter does not match matrix maps.");
4148 exporter_ = exporter;
4151 #ifdef HAVE_TPETRA_MMM_TIMINGS
4153 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-mIXmake"))));
4155 Teuchos::Array<int> remotePIDs (0);
4156 this->makeImportExport (remotePIDs,
false);
4159 #ifdef HAVE_TPETRA_MMM_TIMINGS
4161 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-fLG"))));
4163 this->fillLocalGraph (params);
4165 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
4166 params->get (
"compute global constants",
true);
4167 const bool computeLocalTriangularConstants = params.get () ==
nullptr ||
4168 params->get (
"compute local triangular constants",
true);
4170 if (callComputeGlobalConstants) {
4171 #ifdef HAVE_TPETRA_MMM_TIMINGS
4173 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (const)"))));
4174 #endif // HAVE_TPETRA_MMM_TIMINGS
4175 this->computeGlobalConstants (computeLocalTriangularConstants);
4178 #ifdef HAVE_TPETRA_MMM_TIMINGS
4180 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cGC (noconst)"))));
4181 #endif // HAVE_TPETRA_MMM_TIMINGS
4182 this->computeLocalConstants (computeLocalTriangularConstants);
4185 fillComplete_ =
true;
4187 #ifdef HAVE_TPETRA_MMM_TIMINGS
4189 MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-G-cIS"))));
4191 checkInternalState ();
4195 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4198 fillLocalGraph (
const Teuchos::RCP<Teuchos::ParameterList>& params)
4201 typedef decltype (k_numRowEntries_) row_entries_type;
4202 typedef typename local_graph_type::row_map_type row_map_type;
4203 typedef typename row_map_type::non_const_type non_const_row_map_type;
4204 typedef typename local_graph_type::entries_type::non_const_type lclinds_1d_type;
4205 const char tfecfFuncName[] =
"fillLocalGraph (called from fillComplete or "
4206 "expertStaticFillComplete): ";
4208 const size_t lclNumRows = this->getNodeNumRows ();
4215 non_const_row_map_type ptr_d;
4216 row_map_type ptr_d_const;
4217 lclinds_1d_type ind_d;
4219 bool requestOptimizedStorage =
true;
4220 if (! params.is_null () && ! params->get (
"Optimize Storage",
true)) {
4221 requestOptimizedStorage =
false;
4223 if (this->getProfileType () != StaticProfile) {
4232 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4233 (
static_cast<size_t> (this->k_numRowEntries_.extent (0)) !=
4234 lclNumRows, std::logic_error,
"(DynamicProfile branch) "
4235 "k_numRowEntries_.extent(0) = " << k_numRowEntries_.extent (0)
4236 <<
" != getNodeNumRows() = " << lclNumRows <<
"");
4246 size_t lclTotalNumEntries = 0;
4249 ptr_d = non_const_row_map_type (
"Tpetra::CrsGraph::ptr", lclNumRows+1);
4250 typename row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
4253 ptr_d_const = ptr_d;
4257 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4258 (
static_cast<size_t> (ptr_d.extent (0)) != lclNumRows + 1,
4259 std::logic_error,
"(DynamicProfile branch) After packing ptr_d, "
4260 "ptr_d.extent(0) = " << ptr_d.extent (0) <<
" != "
4261 "(lclNumRows+1) = " << (lclNumRows+1) <<
".");
4263 const auto valToCheck =
4264 ::Tpetra::Details::getEntryOnHost (ptr_d, lclNumRows);
4265 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4266 (valToCheck != lclTotalNumEntries, std::logic_error,
4267 "(DynamicProfile branch) After packing ptr_d, ptr_d(lclNumRows = "
4268 << lclNumRows <<
") = " << valToCheck <<
" != total number of "
4269 "entries on the calling process = " << lclTotalNumEntries <<
".");
4274 ind_d = lclinds_1d_type (
"Tpetra::CrsGraph::ind", lclTotalNumEntries);
4280 auto ptr_h = Kokkos::create_mirror_view (ptr_d);
4282 auto ind_h = Kokkos::create_mirror_view (ind_d);
4285 typename row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
4286 for (
size_t row = 0; row < lclNumRows; ++row) {
4287 const size_t numEnt = numRowEnt_h(row);
4288 std::copy (lclInds2D_[row].begin (),
4289 lclInds2D_[row].begin () + numEnt,
4290 ind_h.data () + ptr_h(row));
4297 if (ptr_d.extent (0) != 0) {
4298 const size_t numOffsets =
static_cast<size_t> (ptr_d.extent (0));
4299 const size_t valToCheck =
4300 ::Tpetra::Details::getEntryOnHost (ptr_d, numOffsets - 1);
4301 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4302 (valToCheck !=
static_cast<size_t> (ind_d.extent (0)),
4303 std::logic_error,
"(DynamicProfile branch) After packing column "
4304 "indices, ptr_d(" << (numOffsets-1) <<
") = " << valToCheck
4305 <<
" != ind_d.extent(0) = " << ind_d.extent (0) <<
".");
4309 else if (getProfileType () == StaticProfile) {
4317 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4318 (k_rowPtrs_.extent (0) == 0, std::logic_error,
4319 "(StaticProfile branch) k_rowPtrs_ has size zero, but shouldn't");
4320 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4321 (k_rowPtrs_.extent (0) != lclNumRows + 1, std::logic_error,
4322 "(StaticProfile branch) k_rowPtrs_.extent(0) = "
4323 << k_rowPtrs_.extent (0) <<
" != (lclNumRows + 1) = "
4324 << (lclNumRows + 1) <<
".");
4326 const size_t numOffsets = k_rowPtrs_.extent (0);
4327 const auto valToCheck =
4328 ::Tpetra::Details::getEntryOnHost (k_rowPtrs_, numOffsets - 1);
4329 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4331 k_lclInds1D_.extent (0) != valToCheck,
4332 std::logic_error,
"(StaticProfile branch) numOffsets = " <<
4333 numOffsets <<
" != 0 and k_lclInds1D_.extent(0) = " <<
4334 k_lclInds1D_.extent (0) <<
" != k_rowPtrs_(" << numOffsets <<
4335 ") = " << valToCheck <<
".");
4339 size_t allocSize = 0;
4341 allocSize = this->getNodeAllocationSize ();
4343 catch (std::logic_error& e) {
4344 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4345 (
true, std::logic_error,
"getNodeAllocationSize threw "
4346 "std::logic_error: " << e.what ());
4348 catch (std::runtime_error& e) {
4349 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4350 (
true, std::runtime_error,
"getNodeAllocationSize threw "
4351 "std::runtime_error: " << e.what ());
4353 catch (std::exception& e) {
4354 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4355 (
true, std::runtime_error,
"getNodeAllocationSize threw "
4356 "std::exception: " << e.what ());
4359 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4360 (
true, std::runtime_error,
"getNodeAllocationSize threw "
4361 "an exception not a subclass of std::exception.");
4364 if (this->getNodeNumEntries () != allocSize) {
4373 if (k_rowPtrs_.extent (0) != 0) {
4374 const size_t numOffsets =
4375 static_cast<size_t> (k_rowPtrs_.extent (0));
4376 const auto valToCheck =
4377 ::Tpetra::Details::getEntryOnHost (k_rowPtrs_, numOffsets - 1);
4378 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4379 (valToCheck !=
static_cast<size_t> (k_lclInds1D_.extent (0)),
4380 std::logic_error,
"(StaticProfile unpacked branch) Before "
4381 "allocating or packing, k_rowPtrs_(" << (numOffsets-1) <<
") = "
4382 << valToCheck <<
" != k_lclInds1D_.extent(0) = "
4383 << k_lclInds1D_.extent (0) <<
".");
4393 size_t lclTotalNumEntries = 0;
4396 ptr_d = non_const_row_map_type (
"Tpetra::CrsGraph::ptr", lclNumRows + 1);
4397 ptr_d_const = ptr_d;
4401 typename row_entries_type::const_type numRowEnt_h = k_numRowEntries_;
4403 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4404 (
static_cast<size_t> (numRowEnt_h.extent (0)) != lclNumRows,
4405 std::logic_error,
"(StaticProfile unpacked branch) "
4406 "numRowEnt_h.extent(0) = " << numRowEnt_h.extent (0)
4407 <<
" != getNodeNumRows() = " << lclNumRows <<
"");
4413 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4414 (
static_cast<size_t> (ptr_d.extent (0)) != lclNumRows + 1,
4415 std::logic_error,
"(StaticProfile unpacked branch) After "
4416 "allocating ptr_d, ptr_d.extent(0) = " << ptr_d.extent (0)
4417 <<
" != lclNumRows+1 = " << (lclNumRows+1) <<
".");
4419 const auto valToCheck =
4420 ::Tpetra::Details::getEntryOnHost (ptr_d, lclNumRows);
4421 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4422 (valToCheck != lclTotalNumEntries, std::logic_error,
4423 "Tpetra::CrsGraph::fillLocalGraph: In StaticProfile unpacked "
4424 "branch, after filling ptr_d, ptr_d(lclNumRows=" << lclNumRows
4425 <<
") = " << valToCheck <<
" != total number of entries on "
4426 "the calling process = " << lclTotalNumEntries <<
".");
4432 ind_d = lclinds_1d_type (
"Tpetra::CrsGraph::ind", lclTotalNumEntries);
4444 typedef pack_functor<
4445 typename local_graph_type::entries_type::non_const_type,
4446 row_map_type> inds_packer_type;
4447 inds_packer_type f (ind_d, k_lclInds1D_, ptr_d, k_rowPtrs_);
4449 typedef typename decltype (ind_d)::execution_space exec_space;
4450 typedef Kokkos::RangePolicy<exec_space, LocalOrdinal> range_type;
4451 Kokkos::parallel_for (range_type (0, lclNumRows), f);
4455 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4456 (ptr_d.extent (0) == 0, std::logic_error,
"(StaticProfile "
4457 "\"Optimize Storage\"=true branch) After packing, "
4458 "ptr_d.extent(0) = 0. This probably means k_rowPtrs_ was "
4459 "never allocated.");
4460 if (ptr_d.extent (0) != 0) {
4461 const size_t numOffsets =
static_cast<size_t> (ptr_d.extent (0));
4462 const auto valToCheck =
4463 ::Tpetra::Details::getEntryOnHost (ptr_d, numOffsets - 1);
4464 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4465 (
static_cast<size_t> (valToCheck) != ind_d.extent (0),
4466 std::logic_error,
"(StaticProfile \"Optimize Storage\"=true "
4467 "branch) After packing, ptr_d(" << (numOffsets-1) <<
") = "
4468 << valToCheck <<
" != ind_d.extent(0) = "
4469 << ind_d.extent (0) <<
".");
4474 ptr_d_const = k_rowPtrs_;
4475 ind_d = k_lclInds1D_;
4478 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4479 (ptr_d_const.extent (0) == 0, std::logic_error,
"(StaticProfile "
4480 "\"Optimize Storage\"=false branch) ptr_d_const.extent(0) = 0. "
4481 "This probably means that k_rowPtrs_ was never allocated.");
4482 if (ptr_d_const.extent (0) != 0) {
4483 const size_t numOffsets =
4484 static_cast<size_t> (ptr_d_const.extent (0));
4485 const size_t valToCheck =
4486 ::Tpetra::Details::getEntryOnHost (ptr_d_const, numOffsets - 1);
4487 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4488 (valToCheck !=
static_cast<size_t> (ind_d.extent (0)),
4489 std::logic_error,
"(StaticProfile \"Optimize Storage\"=false "
4490 "branch) ptr_d_const(" << (numOffsets-1) <<
") = " << valToCheck
4491 <<
" != ind_d.extent(0) = " << ind_d.extent (0) <<
".");
4498 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4499 (
static_cast<size_t> (ptr_d_const.extent (0)) != lclNumRows + 1,
4500 std::logic_error,
"After packing, ptr_d_const.extent(0) = " <<
4501 ptr_d_const.extent (0) <<
" != lclNumRows+1 = " << (lclNumRows+1)
4503 if (ptr_d_const.extent (0) != 0) {
4504 const size_t numOffsets =
static_cast<size_t> (ptr_d_const.extent (0));
4505 const auto valToCheck =
4506 ::Tpetra::Details::getEntryOnHost (ptr_d_const, numOffsets - 1);
4507 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4508 (
static_cast<size_t> (valToCheck) != ind_d.extent (0),
4509 std::logic_error,
"After packing, ptr_d_const(" << (numOffsets-1)
4510 <<
") = " << valToCheck <<
" != ind_d.extent(0) = "
4511 << ind_d.extent (0) <<
".");
4515 if (requestOptimizedStorage) {
4521 lclInds2D_ = Teuchos::null;
4522 k_numRowEntries_ = row_entries_type ();
4525 k_rowPtrs_ = ptr_d_const;
4526 k_lclInds1D_ = ind_d;
4530 pftype_ = StaticProfile;
4531 storageStatus_ = ::Tpetra::Details::STORAGE_1D_PACKED;
4537 lclGraph_ = local_graph_type (ind_d, ptr_d_const);
4540 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4543 replaceColMap (
const Teuchos::RCP<const map_type>& newColMap)
4552 const char tfecfFuncName[] =
"replaceColMap: ";
4553 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4554 isLocallyIndexed () || isGloballyIndexed (), std::runtime_error,
4555 "Requires matching maps and non-static graph.");
4556 colMap_ = newColMap;
4559 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4563 const Teuchos::RCP<const import_type>& newImport,
4564 const bool sortIndicesInEachRow)
4566 using Teuchos::REDUCE_MIN;
4567 using Teuchos::reduceAll;
4569 typedef GlobalOrdinal GO;
4570 typedef LocalOrdinal LO;
4571 typedef typename local_graph_type::entries_type::non_const_type col_inds_type;
4572 const char tfecfFuncName[] =
"reindexColumns: ";
4574 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4575 isFillComplete (), std::runtime_error,
"The graph is fill complete "
4576 "(isFillComplete() returns true). You must call resumeFill() before "
4577 "you may call this method.");
4595 const LO lclNumRows =
static_cast<LO
> (this->getNodeNumRows ());
4610 bool allCurColIndsValid =
true;
4615 bool localSuffices =
true;
4623 typename local_graph_type::entries_type::non_const_type newLclInds1D;
4624 Teuchos::ArrayRCP<Teuchos::Array<LO> > newLclInds2D;
4629 if (indicesAreAllocated ()) {
4630 if (isLocallyIndexed ()) {
4632 const map_type& oldColMap = * (getColMap ());
4633 if (pftype_ == StaticProfile) {
4635 const size_t allocSize = this->getNodeAllocationSize ();
4636 newLclInds1D = col_inds_type (
"Tpetra::CrsGraph::ind", allocSize);
4638 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
4639 const RowInfo rowInfo = this->getRowInfo (lclRow);
4640 const size_t beg = rowInfo.offset1D;
4641 const size_t end = beg + rowInfo.numEntries;
4642 for (
size_t k = beg; k < end; ++k) {
4645 const LO oldLclCol = k_lclInds1D_(k);
4646 if (oldLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
4647 allCurColIndsValid =
false;
4655 if (gblCol == Teuchos::OrdinalTraits<GO>::invalid ()) {
4656 allCurColIndsValid =
false;
4660 const LO newLclCol = newColMap->getLocalElement (gblCol);
4661 if (newLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
4662 localSuffices =
false;
4667 newLclInds1D(k) = newLclCol;
4676 newLclInds2D = Teuchos::arcp<Teuchos::Array<LO> > (lclNumRows);
4679 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
4680 const RowInfo rowInfo = this->getRowInfo (lclRow);
4681 newLclInds2D.resize (rowInfo.allocSize);
4683 Teuchos::ArrayView<const LO> oldLclRowView = getLocalView (rowInfo);
4684 Teuchos::ArrayView<LO> newLclRowView = (newLclInds2D[lclRow]) ();
4686 for (
size_t k = 0; k < rowInfo.numEntries; ++k) {
4687 const LO oldLclCol = oldLclRowView[k];
4688 if (oldLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
4689 allCurColIndsValid =
false;
4696 if (gblCol == Teuchos::OrdinalTraits<GO>::invalid ()) {
4697 allCurColIndsValid =
false;
4701 const LO newLclCol = newColMap->getLocalElement (gblCol);
4702 if (newLclCol == Teuchos::OrdinalTraits<LO>::invalid ()) {
4703 localSuffices =
false;
4706 newLclRowView[k] = newLclCol;
4718 allCurColIndsValid =
false;
4735 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
4736 const RowInfo rowInfo = this->getRowInfo (lclRow);
4737 Teuchos::ArrayView<const GO> oldGblRowView = getGlobalView (rowInfo);
4738 for (
size_t k = 0; k < rowInfo.numEntries; ++k) {
4739 const GO gblCol = oldGblRowView[k];
4740 if (! newColMap->isNodeGlobalElement (gblCol)) {
4741 localSuffices =
false;
4751 lclSuccess[0] = allCurColIndsValid ? 1 : 0;
4752 lclSuccess[1] = localSuffices ? 1 : 0;
4756 RCP<const Teuchos::Comm<int> > comm =
4757 getRowMap ().is_null () ? Teuchos::null : getRowMap ()->getComm ();
4758 if (! comm.is_null ()) {
4759 reduceAll<int, int> (*comm, REDUCE_MIN, 2, lclSuccess, gblSuccess);
4762 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4763 gblSuccess[0] == 0, std::runtime_error,
"It is not possible to continue."
4764 " The most likely reason is that the graph is locally indexed, but the "
4765 "column Map is missing (null) on some processes, due to a previous call "
4766 "to replaceColMap().");
4768 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4769 gblSuccess[1] == 0, std::runtime_error,
"On some process, the graph "
4770 "contains column indices that are in the old column Map, but not in the "
4771 "new column Map (on that process). This method does NOT redistribute "
4772 "data; it does not claim to do the work of an Import or Export operation."
4773 " This means that for all processess, the calling process MUST own all "
4774 "column indices, in both the old column Map and the new column Map. In "
4775 "this case, you will need to do an Import or Export operation to "
4776 "redistribute data.");
4779 if (isLocallyIndexed ()) {
4780 if (pftype_ == StaticProfile) {
4781 k_lclInds1D_ = newLclInds1D;
4783 lclInds2D_ = newLclInds2D;
4791 indicesAreSorted_ =
false;
4792 if (sortIndicesInEachRow) {
4799 const bool sorted =
false;
4800 const bool merged =
true;
4801 this->sortAndMergeAllIndices (sorted, merged);
4804 colMap_ = newColMap;
4806 if (newImport.is_null ()) {
4814 if (! domainMap_.is_null ()) {
4815 if (! domainMap_->isSameAs (* newColMap)) {
4816 importer_ = Teuchos::rcp (
new import_type (domainMap_, newColMap));
4818 importer_ = Teuchos::null;
4823 importer_ = newImport;
4828 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4832 const Teuchos::RCP<const import_type>& newImporter)
4834 const char prefix[] =
"Tpetra::CrsGraph::replaceDomainMapAndImporter: ";
4835 TEUCHOS_TEST_FOR_EXCEPTION(
4836 colMap_.is_null (), std::invalid_argument, prefix <<
"You may not call "
4837 "this method unless the graph already has a column Map.");
4838 TEUCHOS_TEST_FOR_EXCEPTION(
4839 newDomainMap.is_null (), std::invalid_argument,
4840 prefix <<
"The new domain Map must be nonnull.");
4844 if (newImporter.is_null ()) {
4849 const bool colSameAsDom = colMap_->isSameAs (*newDomainMap);
4850 TEUCHOS_TEST_FOR_EXCEPTION
4851 (colSameAsDom, std::invalid_argument,
"If the new Import is null, "
4852 "then the new domain Map must be the same as the current column Map.");
4855 const bool colSameAsTgt =
4856 colMap_->isSameAs (* (newImporter->getTargetMap ()));
4857 const bool newDomSameAsSrc =
4858 newDomainMap->isSameAs (* (newImporter->getSourceMap ()));
4859 TEUCHOS_TEST_FOR_EXCEPTION
4860 (! colSameAsTgt || ! newDomSameAsSrc, std::invalid_argument,
"If the "
4861 "new Import is nonnull, then the current column Map must be the same "
4862 "as the new Import's target Map, and the new domain Map must be the "
4863 "same as the new Import's source Map.");
4867 domainMap_ = newDomainMap;
4868 importer_ = Teuchos::rcp_const_cast<import_type> (newImporter);
4871 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4879 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4884 using ::Tpetra::Details::ProfilingRegion;
4885 using Teuchos::ArrayView;
4886 using Teuchos::outArg;
4887 using Teuchos::reduceAll;
4890 ProfilingRegion regionCGC (
"Tpetra::CrsGraph::computeGlobalConstants");
4892 this->computeLocalConstants (computeLocalTriangularConstants);
4897 if (! this->haveGlobalConstants_) {
4898 const Teuchos::Comm<int>& comm = * (this->getComm ());
4912 lcl[0] =
static_cast<GST
> (this->getNodeNumEntries ());
4921 lcl[1] = computeLocalTriangularConstants ?
4922 static_cast<GST
> (this->nodeNumDiags_) :
4923 static_cast<GST
> (0);
4925 reduceAll<int,GST> (comm, Teuchos::REDUCE_SUM, 2, lcl, gbl);
4926 this->globalNumEntries_ = gbl[0];
4931 this->globalNumDiags_ = computeLocalTriangularConstants ?
4933 Teuchos::OrdinalTraits<GST>::invalid ();
4935 const GST lclMaxNumRowEnt =
static_cast<GST
> (this->nodeMaxNumRowEntries_);
4936 reduceAll<int, GST> (comm, Teuchos::REDUCE_MAX, lclMaxNumRowEnt,
4937 outArg (this->globalMaxNumRowEntries_));
4938 this->haveGlobalConstants_ =
true;
4943 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4949 using ::Tpetra::Details::ProfilingRegion;
4951 ProfilingRegion regionCLC (
"Tpetra::CrsGraph::computeLocalConstants");
4952 if (this->haveLocalConstants_) {
4957 this->lowerTriangular_ =
false;
4958 this->upperTriangular_ =
false;
4959 this->nodeMaxNumRowEntries_ = Teuchos::OrdinalTraits<size_t>::invalid ();
4960 this->nodeNumDiags_ = Teuchos::OrdinalTraits<size_t>::invalid ();
4962 if (computeLocalTriangularConstants) {
4963 const bool hasRowAndColumnMaps =
4964 this->rowMap_.get () !=
nullptr && this->colMap_.get () !=
nullptr;
4965 if (hasRowAndColumnMaps) {
4966 auto lclRowMap = this->rowMap_->getLocalMap ();
4967 auto lclColMap = this->colMap_->getLocalMap ();
4975 constexpr
bool ignoreMapsForTriStruct =
true;
4978 lclColMap, ignoreMapsForTriStruct);
4979 this->lowerTriangular_ = result.couldBeLowerTriangular;
4980 this->upperTriangular_ = result.couldBeUpperTriangular;
4981 this->nodeMaxNumRowEntries_ = result.maxNumRowEnt;
4982 this->nodeNumDiags_ = result.diagCount;
4985 this->nodeMaxNumRowEntries_ = 0;
4986 this->nodeNumDiags_ = 0;
4996 auto ptr = this->lclGraph_.row_map;
4997 const LO lclNumRows = ptr.extent(0) == 0 ?
4998 static_cast<LO
> (0) :
4999 (
static_cast<LO
> (ptr.extent(0)) -
static_cast<LO
> (1));
5001 const LO lclMaxNumRowEnt =
5002 ::Tpetra::Details::maxDifference (
"Tpetra::CrsGraph: nodeMaxNumRowEntries",
5004 this->nodeMaxNumRowEntries_ =
static_cast<size_t> (lclMaxNumRowEnt);
5006 this->haveLocalConstants_ =
true;
5010 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5011 std::pair<size_t, std::string>
5015 using ::Tpetra::Details::ProfilingRegion;
5016 using Teuchos::arcp;
5017 using Teuchos::Array;
5019 typedef LocalOrdinal LO;
5020 typedef GlobalOrdinal GO;
5022 typedef typename local_graph_type::row_map_type::non_const_value_type offset_type;
5023 typedef decltype (k_numRowEntries_) row_entries_type;
5024 typedef typename row_entries_type::non_const_value_type num_ent_type;
5025 typedef typename local_graph_type::entries_type::non_const_type
5027 typedef Kokkos::View<GO*,
typename lcl_col_inds_type::array_layout,
5029 const char tfecfFuncName[] =
"makeIndicesLocal: ";
5030 ProfilingRegion regionMakeIndicesLocal (
"Tpetra::CrsGraph::makeIndicesLocal");
5034 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5035 (! this->hasColMap (), std::logic_error,
"The graph does not have a "
5036 "column Map yet. This method should never be called in that case. "
5037 "Please report this bug to the Tpetra developers.");
5038 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5039 (this->getColMap ().is_null (), std::logic_error,
"The graph claims "
5040 "that it has a column Map, because hasColMap() returns true. However, "
5041 "the result of getColMap() is null. This should never happen. Please "
5042 "report this bug to the Tpetra developers.");
5047 size_t lclNumErrs = 0;
5048 std::ostringstream errStrm;
5050 const LO lclNumRows =
static_cast<LO
> (this->getNodeNumRows ());
5051 const map_type& colMap = * (this->getColMap ());
5053 if (this->isGloballyIndexed () && lclNumRows != 0) {
5055 typename row_entries_type::const_type h_numRowEnt =
5056 this->k_numRowEntries_;
5059 if (this->getProfileType () == StaticProfile) {
5063 constexpr
bool LO_GO_same = std::is_same<LO, GO>::value;
5068 k_lclInds1D_ = Kokkos::Impl::if_c<LO_GO_same,
5070 lcl_col_inds_type>::select (k_gblInds1D_, k_lclInds1D_);
5073 if (k_rowPtrs_.extent (0) == 0) {
5074 errStrm <<
"k_rowPtrs_.extent(0) == 0. This should never "
5075 "happen here. Please report this bug to the Tpetra developers."
5078 return std::make_pair (Tpetra::Details::OrdinalTraits<size_t>::invalid (),
5081 const auto numEnt = ::Tpetra::Details::getEntryOnHost (k_rowPtrs_, lclNumRows);
5090 using Kokkos::view_alloc;
5091 using Kokkos::WithoutInitializing;
5101 const std::string label (
"Tpetra::CrsGraph::lclind");
5103 lcl_col_inds_type (view_alloc (label, WithoutInitializing), numEnt);
5114 auto k_numRowEnt = Kokkos::create_mirror_view (
device_type (), h_numRowEnt);
5118 convertColumnIndicesFromGlobalToLocal<LO, GO, DT, offset_type, num_ent_type> (k_lclInds1D_,
5123 if (lclNumErrs != 0) {
5124 const int myRank = [
this] () {
5125 auto map = this->getMap ();
5126 if (map.is_null ()) {
5130 auto comm = map->getComm ();
5131 return comm.is_null () ? 0 : comm->getRank ();
5134 const bool pluralNumErrs = (lclNumErrs !=
static_cast<size_t> (1));
5135 errStrm <<
"(Process " << myRank <<
") When converting column "
5136 "indices from global to local, we encountered " << lclNumErrs
5137 <<
" ind" << (pluralNumErrs ?
"ices" :
"ex")
5138 <<
" that do" << (pluralNumErrs ?
"es" :
"")
5139 <<
" not live in the column Map on this process." << endl;
5145 k_gblInds1D_ = gbl_col_inds_type ();
5151 Teuchos::ArrayRCP<Teuchos::Array<LO> > lclInds2D (lclNumRows);
5152 Teuchos::ArrayRCP<Teuchos::Array<GO> > gblInds2D = this->gblInds2D_;
5156 typedef typename Kokkos::View<LO*, device_type>::HostMirror::execution_space
5157 host_execution_space;
5158 typedef Kokkos::RangePolicy<host_execution_space, LO> range_type;
5159 Kokkos::parallel_reduce (
5160 "Tpetra::CrsGraph::makeIndicesLocal (DynamicProfile)",
5161 range_type (0, lclNumRows),
5162 [&gblInds2D, &h_numRowEnt, &lclInds2D, &colMap] (
const LO& lclRow,
size_t& numErrs) {
5163 const GO*
const curGblInds = gblInds2D[lclRow].getRawPtr ();
5167 const LO rna =
static_cast<LO
> (gblInds2D[lclRow].size ());
5168 const LO numEnt =
static_cast<LO
> (h_numRowEnt(lclRow));
5169 lclInds2D[lclRow].resize (rna);
5170 LO*
const curLclInds = lclInds2D[lclRow].getRawPtr ();
5171 for (LO j = 0; j < numEnt; ++j) {
5172 const GO gid = curGblInds[j];
5174 curLclInds[j] = lid;
5175 if (lid == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
5181 this->lclInds2D_ = lclInds2D;
5186 if (lclNumErrs != 0) {
5187 const int myRank = [
this] () {
5188 auto map = this->getMap ();
5189 if (map.is_null ()) {
5193 auto comm = map->getComm ();
5194 return comm.is_null () ? 0 : comm->getRank ();
5200 if (lclNumErrs > tooManyErrsToPrint) {
5201 errStrm <<
"(Process " << myRank <<
") When converting column "
5202 "indices from global to local, we encountered " << lclNumErrs
5203 <<
" indices that do not live in the column Map on this "
5204 "process. That's exceeds the allowable number to print."
5205 <<
"This limit is controllable by TPETRA_VERBOSE_PRINT_COUNT_THRESHOLD." << endl;
5210 std::map<LO, std::vector<GO> > badColInds;
5213 std::vector<LO> badLclRows;
5215 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
5216 const size_t numEnt =
static_cast<size_t> (h_numRowEnt[lclRow]);
5218 Teuchos::ArrayView<const GO> curGblInds = gblInds2D_[lclRow] ();
5219 if (numEnt >
static_cast<size_t> (curGblInds.size ())) {
5220 badLclRows.push_back (lclRow);
5223 for (
size_t j = 0; j < numEnt; ++j) {
5224 const GO gid = curGblInds[j];
5226 if (lid == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
5227 badColInds[lclRow].push_back (gid);
5233 const bool pluralNumErrs = (lclNumErrs !=
static_cast<size_t> (1));
5234 errStrm <<
"(Process " << myRank <<
") When converting column "
5235 "indices from global to local, we encountered " << lclNumErrs
5236 <<
" ind" << (pluralNumErrs ?
"ices" :
"ex") <<
" that "
5237 "do" << (pluralNumErrs ?
"es" :
"")
5238 <<
" not live in the column Map on this process." << endl
5239 <<
"(Process " << myRank <<
") Here are the bad global "
5240 "indices, listed by local row: " << endl;
5241 for (
auto && eachPair : badColInds) {
5242 const LO lclRow = eachPair.first;
5243 const GO gblRow = rowMap_->getGlobalElement (lclRow);
5244 errStrm <<
"(Process " << myRank <<
") Local row " << lclRow
5245 <<
" (global row " << gblRow <<
"): [";
5246 const size_t numBad = eachPair.second.size ();
5247 for (
size_t k = 0; k < numBad; ++k) {
5248 errStrm << eachPair.second[k];
5249 if (k +
size_t (1) < numBad) {
5253 errStrm <<
"]" << endl;
5256 if (badLclRows.size () != 0) {
5257 if (lclNumErrs == 0) {
5261 lclNumErrs = badLclRows.size ();
5264 errStrm <<
"(Process " << myRank <<
") When converting column "
5265 "indices from global to local, we (also) encountered the "
5266 "following local rows lclRow on this process for which "
5267 "h_numRowEnt[lclRow] > gblInds2D_[lclRow].size(). This "
5268 "likely indicates a bug in Tpetra." << endl
5269 <<
"(Process " << myRank <<
") [";
5270 const size_t numBad = badLclRows.size ();
5271 for (
size_t k = 0; k < numBad; ++k) {
5272 const LO lclRow = badLclRows[k];
5273 errStrm <<
"{lclRow: " << lclRow
5274 <<
"h_numRowEnt[lclRow]: " << h_numRowEnt[lclRow]
5275 <<
"gblInds2D_[lclRow].size(): "
5276 << gblInds2D_[lclRow].size () <<
"}";
5277 if (k +
size_t (1) < numBad) {
5281 errStrm <<
"]" << endl;
5286 this->gblInds2D_ = Teuchos::null;
5291 this->indicesAreLocal_ =
true;
5292 this->indicesAreGlobal_ =
false;
5293 this->checkInternalState ();
5295 return std::make_pair (lclNumErrs, errStrm.str ());
5299 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5304 using ::Tpetra::Details::ProfilingRegion;
5305 ProfilingRegion regionSortAndMerge (
"Tpetra::CrsGraph::makeColMap");
5313 Teuchos::RCP<const map_type> colMap = this->colMap_;
5314 const bool sortEachProcsGids =
5315 this->sortGhostsAssociatedWithEachProcessor_;
5325 using Teuchos::outArg;
5326 using Teuchos::REDUCE_MIN;
5327 using Teuchos::reduceAll;
5328 const char tfecfFuncName[] =
"makeColMap: ";
5330 std::ostringstream errStrm;
5331 const int lclErrCode =
5333 *
this, sortEachProcsGids, &errStrm);
5334 auto comm = this->getComm ();
5335 if (! comm.is_null ()) {
5336 const int lclSuccess = (lclErrCode == 0) ? 1 : 0;
5338 reduceAll<int, int> (*comm, REDUCE_MIN, lclSuccess,
5339 outArg (gblSuccess));
5340 if (gblSuccess != 1) {
5341 std::ostringstream os;
5343 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5344 (
true, std::runtime_error,
"An error happened on at least one "
5345 "(MPI) process in the CrsGraph's communicator. Here are all "
5346 "processes' error messages:" << std::endl << os.str ());
5352 *
this, sortEachProcsGids,
nullptr);
5357 this->colMap_ = colMap;
5359 checkInternalState ();
5363 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5368 using ::Tpetra::Details::ProfilingRegion;
5369 typedef LocalOrdinal LO;
5370 typedef typename Kokkos::View<LO*, device_type>::HostMirror::execution_space
5371 host_execution_space;
5372 typedef Kokkos::RangePolicy<host_execution_space, LO> range_type;
5373 const char tfecfFuncName[] =
"sortAndMergeAllIndices: ";
5374 ProfilingRegion regionSortAndMerge (
"Tpetra::CrsGraph::sortAndMergeAllIndices");
5376 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5377 (this->isGloballyIndexed (), std::logic_error,
5378 "This method may only be called after makeIndicesLocal." );
5380 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5381 (! merged && this->isStorageOptimized (), std::logic_error,
5382 "The graph is already storage optimized, so we shouldn't be merging any "
5383 "indices. Please report this bug to the Tpetra developers.");
5385 if (! sorted || ! merged) {
5386 const LO lclNumRows =
static_cast<LO
> (this->getNodeNumRows ());
5387 size_t totalNumDups = 0;
5389 Kokkos::parallel_reduce (range_type (0, lclNumRows),
5390 [
this, sorted, merged] (
const LO& lclRow,
size_t& numDups) {
5391 const RowInfo rowInfo = this->getRowInfo (lclRow);
5392 numDups += this->sortAndMergeRowIndices (rowInfo, sorted, merged);
5394 this->indicesAreSorted_ =
true;
5395 this->noRedundancies_ =
true;
5400 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5404 const bool useRemotePIDs)
5406 using ::Tpetra::Details::ProfilingRegion;
5407 using Teuchos::ParameterList;
5410 const char tfecfFuncName[] =
"makeImportExport: ";
5411 ProfilingRegion regionMIE (
"Tpetra::CrsGraph::makeImportExport");
5413 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5414 (! this->hasColMap (), std::logic_error,
5415 "This method may not be called unless the graph has a column Map.");
5416 RCP<ParameterList> params = this->getNonconstParameterList ();
5425 if (importer_.is_null ()) {
5427 if (domainMap_ != colMap_ && (! domainMap_->isSameAs (*colMap_))) {
5428 if (params.is_null () || ! params->isSublist (
"Import")) {
5429 if (useRemotePIDs) {
5430 importer_ = rcp (
new import_type (domainMap_, colMap_, remotePIDs));
5433 importer_ = rcp (
new import_type (domainMap_, colMap_));
5437 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
5438 if (useRemotePIDs) {
5439 RCP<import_type> newImp =
5440 rcp (
new import_type (domainMap_, colMap_, remotePIDs,
5445 importer_ = rcp (
new import_type (domainMap_, colMap_, importSublist));
5453 if (exporter_.is_null ()) {
5455 if (rangeMap_ != rowMap_ && ! rangeMap_->isSameAs (*rowMap_)) {
5456 if (params.is_null () || ! params->isSublist (
"Export")) {
5457 exporter_ = rcp (
new export_type (rowMap_, rangeMap_));
5460 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
5461 exporter_ = rcp (
new export_type (rowMap_, rangeMap_, exportSublist));
5468 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5473 std::ostringstream oss;
5474 oss << dist_object_type::description ();
5475 if (isFillComplete ()) {
5476 oss <<
"{status = fill complete"
5477 <<
", global rows = " << getGlobalNumRows()
5478 <<
", global cols = " << getGlobalNumCols()
5479 <<
", global num entries = " << getGlobalNumEntries()
5483 oss <<
"{status = fill not complete"
5484 <<
", global rows = " << getGlobalNumRows()
5491 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5494 describe (Teuchos::FancyOStream &out,
5495 const Teuchos::EVerbosityLevel verbLevel)
const
5497 using Teuchos::ArrayView;
5498 using Teuchos::Comm;
5500 using Teuchos::VERB_DEFAULT;
5501 using Teuchos::VERB_NONE;
5502 using Teuchos::VERB_LOW;
5503 using Teuchos::VERB_MEDIUM;
5504 using Teuchos::VERB_HIGH;
5505 using Teuchos::VERB_EXTREME;
5509 Teuchos::EVerbosityLevel vl = verbLevel;
5510 if (vl == VERB_DEFAULT) vl = VERB_LOW;
5511 RCP<const Comm<int> > comm = this->getComm();
5512 const int myImageID = comm->getRank(),
5513 numImages = comm->getSize();
5515 for (
size_t dec=10; dec<getGlobalNumRows(); dec *= 10) {
5518 width = std::max<size_t> (width,
static_cast<size_t> (11)) + 2;
5519 Teuchos::OSTab tab (out);
5527 if (vl != VERB_NONE) {
5528 if (myImageID == 0) out << this->description() << std::endl;
5530 if (isFillComplete() && myImageID == 0) {
5531 out <<
"Global number of diagonals = " << globalNumDiags_ << std::endl;
5532 out <<
"Global max number of row entries = " << globalMaxNumRowEntries_ << std::endl;
5535 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
5536 if (myImageID == 0) out <<
"\nRow map: " << std::endl;
5537 rowMap_->describe(out,vl);
5538 if (colMap_ != Teuchos::null) {
5539 if (myImageID == 0) out <<
"\nColumn map: " << std::endl;
5540 colMap_->describe(out,vl);
5542 if (domainMap_ != Teuchos::null) {
5543 if (myImageID == 0) out <<
"\nDomain map: " << std::endl;
5544 domainMap_->describe(out,vl);
5546 if (rangeMap_ != Teuchos::null) {
5547 if (myImageID == 0) out <<
"\nRange map: " << std::endl;
5548 rangeMap_->describe(out,vl);
5552 if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
5553 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
5554 if (myImageID == imageCtr) {
5555 out <<
"Node ID = " << imageCtr << std::endl
5556 <<
"Node number of entries = " << this->getNodeNumEntries () << std::endl
5557 <<
"Node number of diagonals = " << nodeNumDiags_ << std::endl
5558 <<
"Node max number of entries = " << nodeMaxNumRowEntries_ << std::endl;
5559 if (! indicesAreAllocated ()) {
5560 out <<
"Indices are not allocated." << std::endl;
5569 if (vl == VERB_HIGH || vl == VERB_EXTREME) {
5570 for (
int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
5571 if (myImageID == imageCtr) {
5572 out << std::setw(width) <<
"Node ID"
5573 << std::setw(width) <<
"Global Row"
5574 << std::setw(width) <<
"Num Entries";
5575 if (vl == VERB_EXTREME) {
5579 const LocalOrdinal lclNumRows =
5580 static_cast<LocalOrdinal
> (this->getNodeNumRows ());
5581 for (LocalOrdinal r=0; r < lclNumRows; ++r) {
5582 const RowInfo rowinfo = this->getRowInfo (r);
5583 GlobalOrdinal gid = rowMap_->getGlobalElement(r);
5584 out << std::setw(width) << myImageID
5585 << std::setw(width) << gid
5586 << std::setw(width) << rowinfo.numEntries;
5587 if (vl == VERB_EXTREME) {
5589 if (isGloballyIndexed()) {
5590 ArrayView<const GlobalOrdinal> rowview = getGlobalView(rowinfo);
5591 for (
size_t j=0; j < rowinfo.numEntries; ++j) out << rowview[j] <<
" ";
5593 else if (isLocallyIndexed()) {
5594 ArrayView<const LocalOrdinal> rowview = getLocalView(rowinfo);
5595 for (
size_t j=0; j < rowinfo.numEntries; ++j) out << colMap_->getGlobalElement(rowview[j]) <<
" ";
5610 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5621 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5624 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
5626 #else // TPETRA_ENABLE_DEPRECATED_CODE
5628 #endif // TPETRA_ENABLE_DEPRECATED_CODE
5630 const size_t numSameIDs,
5631 const Kokkos::DualView<
const local_ordinal_type*,
5632 buffer_device_type>& permuteToLIDs,
5633 const Kokkos::DualView<
const local_ordinal_type*,
5634 buffer_device_type>& permuteFromLIDs)
5637 using LO = local_ordinal_type;
5638 using GO = global_ordinal_type;
5641 const char tfecfFuncName[] =
"copyAndPermute: ";
5644 std::unique_ptr<std::string> prefix;
5646 std::ostringstream os;
5647 const int myRank = this->getMap ()->getComm ()->getRank ();
5648 os <<
"Proc " << myRank <<
": Tpetra::CrsGraph::copyAndPermute: ";
5649 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
5651 std::cerr << os.str ();
5654 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5655 (permuteToLIDs.extent (0) != permuteFromLIDs.extent (0),
5656 std::runtime_error,
"permuteToLIDs.extent(0) = "
5657 << permuteToLIDs.extent (0) <<
" != permuteFromLIDs.extent(0) = "
5658 << permuteFromLIDs.extent (0) <<
".");
5662 const row_graph_type& srcRowGraph =
5663 dynamic_cast<const row_graph_type&
> (source);
5665 if (this->getProfileType () == StaticProfile) {
5667 std::ostringstream os;
5668 os << *prefix <<
"Target is StaticProfile; do CRS padding" << endl;
5669 std::cerr << os.str ();
5672 computeCrsPadding (srcRowGraph, numSameIDs, permuteToLIDs, permuteFromLIDs);
5673 this->applyCrsPadding(padding);
5676 std::ostringstream os;
5677 os << *prefix <<
"Target is DynamicProfile" << endl;
5678 std::cerr << os.str ();
5684 const this_type* srcCrsGraph =
dynamic_cast<const this_type*
> (&source);
5686 const map_type& srcRowMap = * (srcRowGraph.getRowMap ());
5687 const map_type& tgtRowMap = * (this->getRowMap ());
5688 const bool src_filled = srcRowGraph.isFillComplete ();
5689 Teuchos::Array<GO> row_copy;
5695 if (src_filled || srcCrsGraph ==
nullptr) {
5697 std::ostringstream os;
5698 os << *prefix <<
"src_filled || srcCrsGraph == nullptr" << endl;
5699 std::cerr << os.str ();
5706 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
5707 const GO gid = srcRowMap.getGlobalElement (myid);
5708 size_t row_length = srcRowGraph.getNumEntriesInGlobalRow (gid);
5709 row_copy.resize (row_length);
5710 size_t check_row_length = 0;
5711 srcRowGraph.getGlobalRowCopy (gid, row_copy (), check_row_length);
5712 this->insertGlobalIndices (gid, row_copy ());
5716 std::ostringstream os;
5717 os << *prefix <<
"! src_filled && srcCrsGraph != nullptr" << endl;
5718 std::cerr << os.str ();
5720 for (
size_t i = 0; i < numSameIDs; ++i, ++myid) {
5721 const GO gid = srcRowMap.getGlobalElement (myid);
5722 Teuchos::ArrayView<const GO> row;
5723 srcCrsGraph->getGlobalRowView (gid, row);
5724 this->insertGlobalIndices (gid, row);
5731 auto permuteToLIDs_h = permuteToLIDs.view_host ();
5732 auto permuteFromLIDs_h = permuteFromLIDs.view_host ();
5734 if (src_filled || srcCrsGraph ==
nullptr) {
5735 for (LO i = 0; i < static_cast<LO> (permuteToLIDs_h.extent (0)); ++i) {
5736 const GO mygid = tgtRowMap.getGlobalElement (permuteToLIDs_h[i]);
5737 const GO srcgid = srcRowMap.getGlobalElement (permuteFromLIDs_h[i]);
5738 size_t row_length = srcRowGraph.getNumEntriesInGlobalRow (srcgid);
5739 row_copy.resize (row_length);
5740 size_t check_row_length = 0;
5741 srcRowGraph.getGlobalRowCopy (srcgid, row_copy (), check_row_length);
5742 this->insertGlobalIndices (mygid, row_copy ());
5745 for (LO i = 0; i < static_cast<LO> (permuteToLIDs_h.extent (0)); ++i) {
5746 const GO mygid = tgtRowMap.getGlobalElement (permuteToLIDs_h[i]);
5747 const GO srcgid = srcRowMap.getGlobalElement (permuteFromLIDs_h[i]);
5748 Teuchos::ArrayView<const GO> row;
5749 srcCrsGraph->getGlobalRowView (srcgid, row);
5750 this->insertGlobalIndices (mygid, row);
5755 std::ostringstream os;
5756 os << *prefix <<
"Done" << endl;
5757 std::cerr << os.str ();
5761 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5763 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5764 applyCrsPadding(
const Kokkos::UnorderedMap<LocalOrdinal, size_t, device_type>& padding)
5767 using execution_space =
typename device_type::execution_space;
5768 using row_ptrs_type =
typename local_graph_type::row_map_type::non_const_type;
5769 using indices_type = t_GlobalOrdinal_1D;
5770 using local_indices_type =
typename local_graph_type::entries_type::non_const_type;
5771 using range_policy = Kokkos::RangePolicy<execution_space, Kokkos::IndexType<LocalOrdinal>>;
5774 if (padding.size() == 0)
5778 if (! this->indicesAreAllocated()) {
5779 allocateIndices(GlobalIndices);
5785 row_ptrs_type row_ptrs_beg(
"row_ptrs_beg", this->k_rowPtrs_.extent(0));
5788 const size_t N = (row_ptrs_beg.extent(0) == 0 ? 0 : row_ptrs_beg.extent(0) - 1);
5789 row_ptrs_type row_ptrs_end(
"row_ptrs_end", N);
5791 bool refill_num_row_entries =
false;
5792 if (this->k_numRowEntries_.extent(0) > 0) {
5794 refill_num_row_entries =
true;
5795 auto num_row_entries = this->k_numRowEntries_;
5796 Kokkos::parallel_for(
"Fill end row pointers", range_policy(0, N),
5797 KOKKOS_LAMBDA(
const size_t i){
5798 row_ptrs_end(i) = row_ptrs_beg(i) + num_row_entries(i);
5806 Kokkos::parallel_for(
"Fill end row pointers", range_policy(0, N),
5807 KOKKOS_LAMBDA(
const size_t i){
5808 row_ptrs_end(i) = row_ptrs_beg(i+1);
5813 if(this->isGloballyIndexed()) {
5814 indices_type indices(
"indices", this->k_gblInds1D_.extent(0));
5816 using padding_type = Kokkos::UnorderedMap<LocalOrdinal, size_t, device_type>;
5817 padCrsArrays<row_ptrs_type,indices_type,padding_type>(row_ptrs_beg, row_ptrs_end, indices, padding);
5818 this->k_gblInds1D_ = indices;
5821 local_indices_type indices(
"indices", this->k_lclInds1D_.extent(0));
5823 using padding_type = Kokkos::UnorderedMap<LocalOrdinal, size_t, device_type>;
5824 padCrsArrays<row_ptrs_type,local_indices_type,padding_type>(row_ptrs_beg, row_ptrs_end, indices, padding);
5825 this->k_lclInds1D_ = indices;
5828 if (refill_num_row_entries) {
5829 auto num_row_entries = this->k_numRowEntries_;
5830 Kokkos::parallel_for(
"Fill num entries", range_policy(0, N),
5831 KOKKOS_LAMBDA(
const size_t i){
5832 num_row_entries(i) = row_ptrs_end(i) - row_ptrs_beg(i);
5836 this->k_rowPtrs_ = row_ptrs_beg;
5839 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5840 Kokkos::UnorderedMap<LocalOrdinal, size_t, typename Node::device_type>
5841 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5842 computeCrsPadding (
const RowGraph<LocalOrdinal,GlobalOrdinal,Node>& source,
5843 const size_t numSameIDs,
5844 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteToLIDs,
5845 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteFromLIDs)
const
5847 using LO = LocalOrdinal;
5848 using padding_type = Kokkos::UnorderedMap<LO, size_t, device_type>;
5849 padding_type padding (numSameIDs + permuteFromLIDs.extent (0));
5851 computeCrsPaddingForSameIDs(padding, source, numSameIDs,
false);
5852 computeCrsPaddingForPermutedIDs(padding, source, permuteToLIDs, permuteFromLIDs,
false);
5855 TEUCHOS_TEST_FOR_EXCEPTION
5856 (padding.failed_insert(), std::runtime_error,
5857 "failed to insert one or more indices in to padding map");
5862 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5864 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5865 computeCrsPaddingForSameIDs (Kokkos::UnorderedMap<LocalOrdinal, size_t, typename Node::device_type>& padding,
5866 const RowGraph<LocalOrdinal,GlobalOrdinal,Node>& source,
5867 const size_t numSameIDs,
5868 const bool padAll)
const
5870 using LO = LocalOrdinal;
5871 using GO = GlobalOrdinal;
5872 const char tfecfFuncName[] =
"computeCrsPaddingForSameIds: ";
5876 using insert_result =
5877 typename Kokkos::UnorderedMap<LocalOrdinal, size_t, typename Node::device_type>::insert_result;
5880 const map_type& src_row_map = * (source.getRowMap ());
5881 for (LO tgt_lid = 0; tgt_lid < static_cast<LO> (numSameIDs); ++tgt_lid) {
5882 const GO src_gid = src_row_map.getGlobalElement(tgt_lid);
5883 auto num_src_entries = source.getNumEntriesInGlobalRow(src_gid);
5885 if (num_src_entries == 0)
5888 insert_result result;
5889 const GO tgt_gid = rowMap_->getGlobalElement(tgt_lid);
5891 result = padding.insert(tgt_lid, num_src_entries);
5894 size_t check_row_length = 0;
5895 std::vector<GO> src_row_inds(num_src_entries);
5896 Teuchos::ArrayView<GO> src_row_inds_view(src_row_inds.data(), src_row_inds.size());
5897 source.getGlobalRowCopy(src_gid, src_row_inds_view, check_row_length);
5899 auto num_tgt_entries = this->getNumEntriesInGlobalRow(tgt_gid);
5900 std::vector<GO> tgt_row_inds(num_tgt_entries);
5901 Teuchos::ArrayView<GO> tgt_row_inds_view(tgt_row_inds.data(), tgt_row_inds.size());
5902 this->getGlobalRowCopy(tgt_gid, tgt_row_inds_view, check_row_length);
5904 size_t how_much_padding = 0;
5905 for (
auto src_row_ind : src_row_inds) {
5906 if (std::find(tgt_row_inds.begin(), tgt_row_inds.end(), src_row_ind) == tgt_row_inds.end()) {
5911 result = padding.insert (tgt_lid, how_much_padding);
5917 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5918 (result.failed(), std::runtime_error,
5919 "unable to insert padding for LID " << tgt_lid);
5923 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5925 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5926 computeCrsPaddingForPermutedIDs (Kokkos::UnorderedMap<LocalOrdinal, size_t, typename Node::device_type>& padding,
5927 const RowGraph<LocalOrdinal,GlobalOrdinal,Node>& source,
5928 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteToLIDs,
5929 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteFromLIDs,
5930 const bool padAll)
const
5932 using LO = LocalOrdinal;
5933 using GO = GlobalOrdinal;
5934 const char tfecfFuncName[] =
"computeCrsPaddingForPermutedIds: ";
5937 const map_type& src_row_map = * (source.getRowMap ());
5939 using insert_result =
5940 typename Kokkos::UnorderedMap<LocalOrdinal, size_t, typename Node::device_type>::insert_result;
5941 auto permuteToLIDs_h = permuteToLIDs.view_host ();
5942 auto permuteFromLIDs_h = permuteFromLIDs.view_host ();
5943 for (LO i = 0; i < static_cast<LO> (permuteToLIDs_h.extent (0)); ++i) {
5944 const GO src_gid = src_row_map.getGlobalElement(permuteFromLIDs_h[i]);
5945 auto num_src_entries = source.getNumEntriesInGlobalRow(src_gid);
5947 if (num_src_entries == 0)
5950 insert_result result;
5951 const LO tgt_lid = permuteToLIDs_h[i];
5954 result = padding.insert (tgt_lid, num_src_entries);
5957 size_t check_row_length = 0;
5958 std::vector<GO> src_row_inds(num_src_entries);
5959 Teuchos::ArrayView<GO> src_row_inds_view(src_row_inds.data(), src_row_inds.size());
5960 source.getGlobalRowCopy(src_gid, src_row_inds_view, check_row_length);
5962 const GO tgt_gid = rowMap_->getGlobalElement (tgt_lid);
5963 auto num_tgt_entries = this->getNumEntriesInGlobalRow(tgt_gid);
5964 std::vector<GO> tgt_row_inds(num_tgt_entries);
5965 Teuchos::ArrayView<GO> tgt_row_inds_view(tgt_row_inds.data(), tgt_row_inds.size());
5966 this->getGlobalRowCopy(tgt_gid, tgt_row_inds_view, check_row_length);
5968 size_t how_much_padding = 0;
5969 for (
auto src_row_ind : src_row_inds) {
5970 if (std::find(tgt_row_inds.begin(), tgt_row_inds.end(), src_row_ind) == tgt_row_inds.end()) {
5975 result = padding.insert (tgt_lid, how_much_padding);
5981 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5982 (result.failed(), std::runtime_error,
5983 "unable to insert padding for LID " << tgt_lid);
5988 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5989 Kokkos::UnorderedMap<LocalOrdinal, size_t, typename Node::device_type>
5990 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
5991 computeCrsPadding (
const Kokkos::DualView<
const local_ordinal_type*,
5992 buffer_device_type>& importLIDs,
5993 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID)
const
5995 const char tfecfFuncName[] =
"computeCrsPadding: ";
5999 using padding_type = Kokkos::UnorderedMap<local_ordinal_type, size_t, device_type>;
6000 padding_type padding (importLIDs.extent (0));
6001 auto numEnt =
static_cast<size_t> (importLIDs.extent (0));
6003 auto importLIDs_h = importLIDs.view_host ();
6004 if (numPacketsPerLID.need_sync_host ()) {
6005 numPacketsPerLID.sync_host ();
6007 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
6012 for (
size_t i = 0; i < numEnt; ++i) {
6013 auto result = padding.insert (importLIDs_h[i], numPacketsPerLID_h[i]);
6015 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6016 (result.failed(), std::runtime_error,
6017 "unable to insert padding for LID " << importLIDs_h[i]);
6020 TEUCHOS_TEST_FOR_EXCEPTION
6021 (padding.failed_insert(), std::runtime_error,
6022 "failed to insert one or more indices in to padding map");
6026 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6028 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
6029 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
6031 #else // TPETRA_ENABLE_DEPRECATED_CODE
6033 #endif // TPETRA_ENABLE_DEPRECATED_CODE
6034 (
const SrcDistObject& source,
6036 buffer_device_type>& exportLIDs,
6037 Kokkos::DualView<packet_type*,
6038 buffer_device_type>& exports,
6039 Kokkos::DualView<
size_t*,
6040 buffer_device_type> numPacketsPerLID,
6041 size_t& constantNumPackets,
6042 Distributor& distor)
6045 using GO = global_ordinal_type;
6047 using crs_graph_type =
6048 CrsGraph<local_ordinal_type, global_ordinal_type, node_type>;
6049 using row_graph_type =
6050 RowGraph<local_ordinal_type, global_ordinal_type, node_type>;
6051 const char tfecfFuncName[] =
"packAndPrepare: ";
6052 ProfilingRegion region_papn (
"Tpetra::CrsGraph::packAndPrepare");
6055 std::unique_ptr<std::string> prefix;
6057 std::ostringstream os;
6058 const int myRank = this->getMap ()->getComm ()->getRank ();
6059 os <<
"Proc " << myRank <<
": Tpetra::CrsGraph::packAndPrepare: ";
6060 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
6061 os <<
"Start" << endl;
6062 std::cerr << os.str ();
6065 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6066 (exportLIDs.extent (0) != numPacketsPerLID.extent (0),
6068 "exportLIDs.extent(0) = " << exportLIDs.extent (0)
6069 <<
" != numPacketsPerLID.extent(0) = " << numPacketsPerLID.extent (0)
6071 const row_graph_type* srcRowGraphPtr =
6072 dynamic_cast<const row_graph_type*
> (&source);
6073 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6074 (srcRowGraphPtr ==
nullptr, std::invalid_argument,
"Source of an Export "
6075 "or Import operation to a CrsGraph must be a RowGraph with the same "
6076 "template parameters.");
6080 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6081 (this->isFillComplete (), std::runtime_error,
6082 "The target graph of an Import or Export must not be fill complete.");
6084 const crs_graph_type* srcCrsGraphPtr =
6085 dynamic_cast<const crs_graph_type*
> (&source);
6087 if (srcCrsGraphPtr ==
nullptr) {
6088 using Teuchos::ArrayView;
6092 std::ostringstream os;
6093 os << *prefix <<
"Source is a RowGraph but not a CrsGraph" << endl;
6094 std::cerr << os.str ();
6101 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
6102 auto exportLIDs_h = exportLIDs.view_host ();
6103 ArrayView<const LO> exportLIDs_av (exportLIDs_h.data (),
6104 exportLIDs_h.extent (0));
6105 Teuchos::Array<GO> exports_a;
6107 numPacketsPerLID.clear_sync_state ();
6108 numPacketsPerLID.modify_host ();
6109 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
6110 ArrayView<size_t> numPacketsPerLID_av (numPacketsPerLID_h.data (),
6111 numPacketsPerLID_h.extent (0));
6112 srcRowGraphPtr->pack (exportLIDs_av, exports_a, numPacketsPerLID_av,
6113 constantNumPackets, distor);
6114 const size_t newSize =
static_cast<size_t> (exports_a.size ());
6115 if (
static_cast<size_t> (exports.extent (0)) != newSize) {
6116 using exports_dv_type = Kokkos::DualView<packet_type*, buffer_device_type>;
6117 exports = exports_dv_type (
"exports", newSize);
6119 Kokkos::View<
const packet_type*, Kokkos::HostSpace,
6120 Kokkos::MemoryUnmanaged> exports_a_h (exports_a.getRawPtr (), newSize);
6121 exports.clear_sync_state ();
6122 exports.modify_host ();
6126 else if (! getColMap ().is_null () &&
6127 (lclGraph_.row_map.extent (0) != 0 ||
6128 getRowMap ()->getNodeNumElements () == 0)) {
6130 std::ostringstream os;
6131 os << *prefix <<
"packCrsGraphNew path" << endl;
6132 std::cerr << os.str ();
6134 using export_pids_type =
6135 Kokkos::DualView<const int*, buffer_device_type>;
6136 export_pids_type exportPIDs;
6140 packCrsGraphNew<LO,GO,NT> (*srcCrsGraphPtr, exportLIDs, exportPIDs,
6141 exports, numPacketsPerLID,
6142 constantNumPackets,
false, distor);
6145 srcCrsGraphPtr->packFillActiveNew (exportLIDs, exports, numPacketsPerLID,
6146 constantNumPackets, distor);
6150 std::ostringstream os;
6151 os << *prefix <<
"Done" << endl;
6152 std::cerr << os.str ();
6156 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6159 pack (
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
6160 Teuchos::Array<GlobalOrdinal>& exports,
6161 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
6162 size_t& constantNumPackets,
6165 auto col_map = this->getColMap();
6167 if( !col_map.is_null() && (lclGraph_.row_map.extent(0) != 0 || getRowMap()->getNodeNumElements() ==0)) {
6169 packCrsGraph<LocalOrdinal,GlobalOrdinal,Node>(*
this, exports, numPacketsPerLID,
6170 exportLIDs, constantNumPackets, distor);
6173 this->packFillActive(exportLIDs, exports, numPacketsPerLID,
6174 constantNumPackets, distor);
6178 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6181 packFillActive (
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
6182 Teuchos::Array<GlobalOrdinal>& exports,
6183 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
6184 size_t& constantNumPackets,
6187 typedef LocalOrdinal LO;
6188 typedef GlobalOrdinal GO;
6189 typedef typename Kokkos::View<
size_t*,
6190 device_type>::HostMirror::execution_space host_execution_space;
6191 typedef typename device_type::execution_space device_execution_space;
6192 const char tfecfFuncName[] =
"packFillActive: ";
6194 const int myRank = debug ? this->getMap ()->getComm ()->getRank () : 0;
6196 const auto numExportLIDs = exportLIDs.size ();
6198 std::ostringstream os;
6199 os <<
"Proc " << myRank <<
": CrsGraph::pack: numExportLIDs = "
6200 << numExportLIDs << std::endl;
6201 std::cerr << os.str ();
6203 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6204 (numExportLIDs != numPacketsPerLID.size (), std::runtime_error,
6205 "exportLIDs.size() = " << numExportLIDs <<
" != numPacketsPerLID.size()"
6206 " = " << numPacketsPerLID.size () <<
".");
6210 device_execution_space().fence ();
6212 const map_type& rowMap = * (this->getRowMap ());
6213 const map_type*
const colMapPtr = this->colMap_.getRawPtr ();
6214 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6215 (this->isLocallyIndexed () && colMapPtr ==
nullptr, std::logic_error,
6216 "This graph claims to be locally indexed, but its column Map is nullptr. "
6217 "This should never happen. Please report this bug to the Tpetra "
6221 constantNumPackets = 0;
6225 size_t*
const numPacketsPerLID_raw = numPacketsPerLID.getRawPtr ();
6226 const LO*
const exportLIDs_raw = exportLIDs.getRawPtr ();
6233 Kokkos::RangePolicy<host_execution_space, LO> inputRange (0, numExportLIDs);
6234 size_t totalNumPackets = 0;
6235 size_t errCount = 0;
6238 typedef Kokkos::Device<host_execution_space, Kokkos::HostSpace>
6240 Kokkos::View<size_t, host_device_type> errCountView (&errCount);
6241 constexpr
size_t ONE = 1;
6243 Kokkos::parallel_reduce (
"Tpetra::CrsGraph::pack: totalNumPackets",
6245 [=] (
const LO& i,
size_t& curTotalNumPackets) {
6246 const GO gblRow = rowMap.getGlobalElement (exportLIDs_raw[i]);
6247 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
6248 Kokkos::atomic_add (&errCountView(), ONE);
6249 numPacketsPerLID_raw[i] = 0;
6252 const size_t numEnt = this->getNumEntriesInGlobalRow (gblRow);
6253 numPacketsPerLID_raw[i] = numEnt;
6254 curTotalNumPackets += numEnt;
6260 std::ostringstream os;
6261 os <<
"Proc " << myRank <<
": CrsGraph::pack: "
6262 <<
"totalNumPackets = " << totalNumPackets << std::endl;
6263 std::cerr << os.str ();
6265 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6266 (errCount != 0, std::logic_error,
"totalNumPackets count encountered "
6267 "one or more errors! errCount = " << errCount
6268 <<
", totalNumPackets = " << totalNumPackets <<
".");
6272 exports.resize (totalNumPackets);
6274 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6275 (! this->supportsRowViews (), std::logic_error,
6276 "this->supportsRowViews() returns false; this should never happen. "
6277 "Please report this bug to the Tpetra developers.");
6283 std::ostringstream os;
6284 os <<
"Proc " << myRank <<
": CrsGraph::pack: pack into exports" << std::endl;
6285 std::cerr << os.str ();
6290 GO*
const exports_raw = exports.getRawPtr ();
6292 Kokkos::parallel_scan (
"Tpetra::CrsGraph::pack: pack from views",
6294 [=] (
const LO& i,
size_t& exportsOffset,
const bool final) {
6295 const size_t curOffset = exportsOffset;
6296 const GO gblRow = rowMap.getGlobalElement (exportLIDs_raw[i]);
6297 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (gblRow);
6299 if (rowInfo.localRow == Tpetra::Details::OrdinalTraits<size_t>::invalid ()) {
6301 std::ostringstream os;
6302 os <<
"Proc " << myRank <<
": INVALID rowInfo: "
6303 <<
"i = " << i <<
", lclRow = " << exportLIDs_raw[i] << std::endl;
6304 std::cerr << os.str ();
6306 Kokkos::atomic_add (&errCountView(), ONE);
6308 else if (curOffset + rowInfo.numEntries > totalNumPackets) {
6310 std::ostringstream os;
6311 os <<
"Proc " << myRank <<
": UH OH! For i=" << i <<
", lclRow="
6312 << exportLIDs_raw[i] <<
", gblRow=" << gblRow <<
", curOffset "
6313 "(= " << curOffset <<
") + numEnt (= " << rowInfo.numEntries
6314 <<
") > totalNumPackets (= " << totalNumPackets <<
")."
6316 std::cerr << os.str ();
6318 Kokkos::atomic_add (&errCountView(), ONE);
6321 const LO numEnt =
static_cast<LO
> (rowInfo.numEntries);
6322 if (this->isLocallyIndexed ()) {
6323 const LO* lclColInds =
nullptr;
6326 this->getLocalViewRawConst (lclColInds, capacity, rowInfo);
6329 for (LO k = 0; k < numEnt; ++k) {
6330 const LO lclColInd = lclColInds[k];
6331 const GO gblColInd = colMapPtr->getGlobalElement (lclColInd);
6335 exports_raw[curOffset + k] = gblColInd;
6338 exportsOffset = curOffset + numEnt;
6341 Kokkos::atomic_add (&errCountView(), ONE);
6344 else if (this->isGloballyIndexed ()) {
6345 const GO* gblColInds =
nullptr;
6348 this->getGlobalViewRawConst (gblColInds, capacity, rowInfo);
6351 for (LO k = 0; k < numEnt; ++k) {
6352 const GO gblColInd = gblColInds[k];
6356 exports_raw[curOffset + k] = gblColInd;
6359 exportsOffset = curOffset + numEnt;
6362 Kokkos::atomic_add (&errCountView(), ONE);
6373 device_execution_space().fence ();
6375 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6376 (errCount != 0, std::logic_error,
"Packing encountered "
6377 "one or more errors! errCount = " << errCount
6378 <<
", totalNumPackets = " << totalNumPackets <<
".");
6381 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6383 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
6384 packFillActiveNew (
const Kokkos::DualView<
const local_ordinal_type*,
6385 buffer_device_type>& exportLIDs,
6386 Kokkos::DualView<packet_type*,
6387 buffer_device_type>& exports,
6388 Kokkos::DualView<
size_t*,
6389 buffer_device_type> numPacketsPerLID,
6390 size_t& constantNumPackets,
6391 Distributor& distor)
const
6395 using GO = global_ordinal_type;
6396 using host_execution_space =
typename Kokkos::View<
size_t*,
6397 device_type>::HostMirror::execution_space;
6398 using host_device_type =
6399 Kokkos::Device<host_execution_space, Kokkos::HostSpace>;
6400 using device_execution_space =
typename device_type::execution_space;
6401 using exports_dv_type =
6402 Kokkos::DualView<packet_type*, buffer_device_type>;
6403 const char tfecfFuncName[] =
"packFillActiveNew: ";
6405 const int myRank = debug ? this->getMap ()->getComm ()->getRank () : 0;
6407 std::unique_ptr<std::string> prefix;
6409 std::ostringstream os;
6410 os <<
"Proc " << myRank <<
": Tpetra::CrsGraph::packFillActiveNew: ";
6411 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
6412 os <<
"Start" << endl;
6413 std::cerr << os.str ();
6416 const auto numExportLIDs = exportLIDs.extent (0);
6418 std::ostringstream os;
6419 os << *prefix <<
"numExportLIDs: " << numExportLIDs
6420 <<
", numPacketsPerLID.extent(0): " << numPacketsPerLID.extent (0)
6422 std::cerr << os.str ();
6424 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6425 (numExportLIDs != numPacketsPerLID.extent (0), std::runtime_error,
6426 "exportLIDs.extent(0) = " << numExportLIDs
6427 <<
" != numPacketsPerLID.extent(0) = "
6428 << numPacketsPerLID.extent (0) <<
".");
6429 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
6430 auto exportLIDs_h = exportLIDs.view_host ();
6434 device_execution_space().fence ();
6436 const map_type& rowMap = * (this->getRowMap ());
6437 const map_type*
const colMapPtr = this->colMap_.getRawPtr ();
6438 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6439 (this->isLocallyIndexed () && colMapPtr ==
nullptr, std::logic_error,
6440 "This graph claims to be locally indexed, but its column Map is nullptr. "
6441 "This should never happen. Please report this bug to the Tpetra "
6445 constantNumPackets = 0;
6447 numPacketsPerLID.clear_sync_state ();
6448 numPacketsPerLID.modify_host ();
6449 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
6456 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
6457 range_type inputRange (0, numExportLIDs);
6458 size_t totalNumPackets = 0;
6459 size_t errCount = 0;
6462 Kokkos::View<size_t, host_device_type> errCountView (&errCount);
6463 constexpr
size_t ONE = 1;
6466 std::ostringstream os;
6467 os << *prefix <<
"Compute totalNumPackets" << endl;
6468 std::cerr << os.str ();
6471 Kokkos::parallel_reduce
6472 (
"Tpetra::CrsGraph::pack: totalNumPackets",
6474 [=] (
const LO i,
size_t& curTotalNumPackets) {
6475 const LO lclRow = exportLIDs_h[i];
6476 const GO gblRow = rowMap.getGlobalElement (lclRow);
6477 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
6479 std::ostringstream os;
6480 os <<
"Proc " << myRank <<
": For i=" << i <<
", lclRow="
6481 << lclRow <<
" not in row Map on this process" << endl;
6482 std::cerr << os.str ();
6484 Kokkos::atomic_add (&errCountView(), ONE);
6485 numPacketsPerLID_h(i) = 0;
6488 const size_t numEnt = this->getNumEntriesInGlobalRow (gblRow);
6489 numPacketsPerLID_h(i) = numEnt;
6490 curTotalNumPackets += numEnt;
6496 std::ostringstream os;
6497 os << *prefix <<
"totalNumPackets: " << totalNumPackets
6498 <<
", errCount: " << errCount << endl;
6499 std::cerr << os.str ();
6501 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6502 (errCount != 0, std::logic_error,
"totalNumPackets count encountered "
6503 "one or more errors! totalNumPackets: " << totalNumPackets
6504 <<
", errCount: " << errCount <<
".");
6507 if (
static_cast<size_t> (exports.extent (0)) < totalNumPackets) {
6509 exports = exports_dv_type (
"exports", totalNumPackets);
6512 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6513 (! this->supportsRowViews (), std::logic_error,
6514 "this->supportsRowViews() returns false; this should never happen. "
6515 "Please report this bug to the Tpetra developers.");
6521 std::ostringstream os;
6522 os << *prefix <<
"Pack into exports buffer" << endl;
6523 std::cerr << os.str ();
6526 exports.clear_sync_state ();
6527 exports.modify_host ();
6528 auto exports_h = exports.view_host ();
6533 device_execution_space().fence ();
6536 Kokkos::parallel_scan
6537 (
"Tpetra::CrsGraph::packFillActiveNew: Pack exports",
6539 [=] (
const LO i,
size_t& exportsOffset,
const bool final) {
6540 const size_t curOffset = exportsOffset;
6541 const LO lclRow = exportLIDs_h(i);
6542 const GO gblRow = rowMap.getGlobalElement (lclRow);
6543 if (gblRow == Details::OrdinalTraits<GO>::invalid ()) {
6545 std::ostringstream os;
6546 os <<
"Proc " << myRank <<
": For i=" << i <<
", lclRow="
6547 << lclRow <<
" not in row Map on this process" << endl;
6548 std::cerr << os.str ();
6550 Kokkos::atomic_add (&errCountView(), ONE);
6554 const RowInfo rowInfo = this->getRowInfoFromGlobalRowIndex (gblRow);
6555 if (rowInfo.localRow == Details::OrdinalTraits<size_t>::invalid ()) {
6557 std::ostringstream os;
6558 os <<
"Proc " << myRank <<
": For i=" << i <<
", lclRow="
6559 << lclRow <<
", gblRow=" << gblRow <<
": invalid rowInfo"
6561 std::cerr << os.str ();
6563 Kokkos::atomic_add (&errCountView(), ONE);
6567 if (curOffset + rowInfo.numEntries > totalNumPackets) {
6569 std::ostringstream os;
6570 os <<
"Proc " << myRank <<
": For i=" << i <<
", lclRow="
6571 << lclRow <<
", gblRow=" << gblRow <<
", curOffset "
6572 "(= " << curOffset <<
") + numEnt (= " << rowInfo.numEntries
6573 <<
") > totalNumPackets (= " << totalNumPackets <<
")."
6575 std::cerr << os.str ();
6577 Kokkos::atomic_add (&errCountView(), ONE);
6581 const LO numEnt =
static_cast<LO
> (rowInfo.numEntries);
6582 if (this->isLocallyIndexed ()) {
6583 const LO* lclColInds =
nullptr;
6586 this->getLocalViewRawConst (lclColInds, capacity, rowInfo);
6589 for (LO k = 0; k < numEnt; ++k) {
6590 const LO lclColInd = lclColInds[k];
6591 const GO gblColInd = colMapPtr->getGlobalElement (lclColInd);
6595 exports_h(curOffset + k) = gblColInd;
6598 exportsOffset = curOffset + numEnt;
6602 std::ostringstream os;
6603 os <<
"Proc " << myRank <<
": For i=" << i <<
", lclRow="
6604 << lclRow <<
", gblRow=" << gblRow <<
": "
6605 "getLocalViewRawConst returned nonzero error code "
6607 std::cerr << os.str ();
6609 Kokkos::atomic_add (&errCountView(), ONE);
6612 else if (this->isGloballyIndexed ()) {
6613 const GO* gblColInds =
nullptr;
6616 this->getGlobalViewRawConst (gblColInds, capacity, rowInfo);
6619 for (LO k = 0; k < numEnt; ++k) {
6620 const GO gblColInd = gblColInds[k];
6624 exports_h(curOffset + k) = gblColInd;
6627 exportsOffset = curOffset + numEnt;
6631 std::ostringstream os;
6632 os <<
"Proc " << myRank <<
": For i=" << i <<
", lclRow="
6633 << lclRow <<
", gblRow=" << gblRow <<
": "
6634 "getGlobalViewRawConst returned nonzero error code "
6636 std::cerr << os.str ();
6638 Kokkos::atomic_add (&errCountView(), ONE);
6652 std::ostringstream os;
6653 os << *prefix <<
"errCount = " << errCount <<
"; Done" << endl;
6654 std::cerr << os.str ();
6658 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6660 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
6661 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
6663 #else // TPETRA_ENABLE_DEPRECATED_CODE
6665 #endif // TPETRA_ENABLE_DEPRECATED_CODE
6667 buffer_device_type>& importLIDs,
6668 Kokkos::DualView<packet_type*,
6669 buffer_device_type> imports,
6670 Kokkos::DualView<
size_t*,
6671 buffer_device_type> numPacketsPerLID,
6678 using GO = global_ordinal_type;
6679 const char tfecfFuncName[] =
"unpackAndCombine: ";
6682 std::unique_ptr<std::string> prefix;
6684 std::ostringstream os;
6685 const int myRank = this->getMap ()->getComm ()->getRank ();
6686 os <<
"Proc " << myRank <<
": Tpetra::CrsGraph::unpackAndCombine: ";
6687 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
6689 std::cerr << os.str ();
6692 if (this->getProfileType () == StaticProfile) {
6693 auto padding = computeCrsPadding (importLIDs, numPacketsPerLID);
6694 applyCrsPadding(padding);
6713 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6714 (importLIDs.extent (0) != numPacketsPerLID.extent (0),
6715 std::runtime_error,
"importLIDs.extent(0) = "
6716 << importLIDs.extent (0) <<
" != numPacketsPerLID.extent(0) = "
6717 << numPacketsPerLID.extent (0) <<
".");
6718 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6719 (isFillComplete (), std::runtime_error,
6720 "Import or Export operations are not allowed on the destination "
6721 "CrsGraph if it is fill complete.");
6723 const size_t numImportLIDs =
static_cast<size_t> (importLIDs.extent (0));
6724 if (numPacketsPerLID.need_sync_host ()) {
6725 numPacketsPerLID.sync_host ();
6727 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
6730 Teuchos::Array<LO> lclColInds;
6731 if (this->isLocallyIndexed ()) {
6732 size_t maxNumInserts = 0;
6733 for (
size_t i = 0; i < numImportLIDs; ++i) {
6734 maxNumInserts = std::max (maxNumInserts, numPacketsPerLID_h[i]);
6736 lclColInds.resize (maxNumInserts);
6739 auto importLIDs_h = importLIDs.view_host ();
6740 if (imports.need_sync_host ()) {
6741 imports.sync_host ();
6743 auto imports_h = imports.view_host ();
6745 const map_type& rowMap = * (this->rowMap_);
6746 size_t importsOffset = 0;
6747 for (
size_t i = 0; i < numImportLIDs; ++i) {
6748 const LO lclRow = importLIDs_h[i];
6749 const GO gblRow = rowMap.getGlobalElement (lclRow);
6750 const LO numEnt = numPacketsPerLID_h[i];
6751 const GO*
const gblColInds = (numEnt == 0) ?
nullptr :
6752 &imports_h[importsOffset];
6753 if (! this->isLocallyIndexed ()) {
6754 if (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
6756 this->insertGlobalIndicesIntoNonownedRows (gblRow, gblColInds, numEnt);
6759 this->insertGlobalIndicesFiltered (lclRow, gblColInds, numEnt);
6763 for (LO j = 0; j < numEnt; j++) {
6764 lclColInds[j] = this->colMap_->getLocalElement (gblColInds[j]);
6766 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6767 (gblRow == Tpetra::Details::OrdinalTraits<GO>::invalid (),
6769 "cannot insert into unowned rows if isLocallyIndexed().");
6770 this->insertLocalIndices (lclRow, numEnt, lclColInds.data ());
6772 importsOffset += numEnt;
6777 std::ostringstream os;
6778 os << *prefix <<
"Done" << endl;
6779 std::cerr << os.str ();
6783 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6788 using Teuchos::Comm;
6789 using Teuchos::null;
6790 using Teuchos::ParameterList;
6796 RCP<const map_type> rowMap, domainMap, rangeMap, colMap;
6797 RCP<import_type> importer;
6798 RCP<export_type> exporter;
6801 RCP<const Comm<int> > newComm =
6802 (newMap.is_null ()) ?
null : newMap->getComm ();
6804 if (! domainMap_.is_null ()) {
6805 if (domainMap_.getRawPtr () == rowMap_.getRawPtr ()) {
6812 domainMap = domainMap_->replaceCommWithSubset (newComm);
6815 if (! rangeMap_.is_null ()) {
6816 if (rangeMap_.getRawPtr () == rowMap_.getRawPtr ()) {
6823 rangeMap = rangeMap_->replaceCommWithSubset (newComm);
6826 if (! colMap.is_null ()) {
6827 colMap = colMap_->replaceCommWithSubset (newComm);
6831 if (! newComm.is_null ()) {
6832 RCP<ParameterList> params = this->getNonconstParameterList ();
6840 if (! rangeMap_.is_null () &&
6841 rangeMap != rowMap &&
6842 ! rangeMap->isSameAs (*rowMap)) {
6843 if (params.is_null () || ! params->isSublist (
"Export")) {
6844 exporter = rcp (
new export_type (rowMap, rangeMap));
6847 RCP<ParameterList> exportSublist = sublist (params,
"Export",
true);
6848 exporter = rcp (
new export_type (rowMap, rangeMap, exportSublist));
6852 if (! domainMap_.is_null () &&
6853 domainMap != colMap &&
6854 ! domainMap->isSameAs (*colMap)) {
6855 if (params.is_null () || ! params->isSublist (
"Import")) {
6856 importer = rcp (
new import_type (domainMap, colMap));
6858 RCP<ParameterList> importSublist = sublist (params,
"Import",
true);
6859 importer = rcp (
new import_type (domainMap, colMap, importSublist));
6867 exporter_ = exporter;
6868 importer_ = importer;
6875 this->map_ = rowMap;
6876 domainMap_ = domainMap;
6877 rangeMap_ = rangeMap;
6881 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6884 getLocalDiagOffsets (
const Kokkos::View<size_t*, device_type, Kokkos::MemoryUnmanaged>& offsets)
const
6886 typedef LocalOrdinal LO;
6887 typedef GlobalOrdinal GO;
6888 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
6891 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6892 (! hasColMap (), std::runtime_error,
"The graph must have a column Map.");
6893 const LO lclNumRows =
static_cast<LO
> (this->getNodeNumRows ());
6894 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6895 (
static_cast<LO
> (offsets.extent (0)) < lclNumRows,
6896 std::invalid_argument,
"offsets.extent(0) = " <<
6897 offsets.extent (0) <<
" < getNodeNumRows() = " << lclNumRows <<
".");
6899 const map_type& rowMap = * (this->getRowMap ());
6900 const map_type& colMap = * (this->getColMap ());
6906 bool allRowMapDiagEntriesInColMap =
true;
6907 bool allDiagEntriesFound =
true;
6908 bool allOffsetsCorrect =
true;
6909 bool noOtherWeirdness =
true;
6910 using wrong_offsets_type = std::vector<std::pair<LO, size_t> >;
6911 wrong_offsets_type wrongOffsets (0);
6922 const bool sorted = this->isSorted ();
6923 if (isFillComplete ()) {
6924 auto lclGraph = this->getLocalGraph ();
6925 ::Tpetra::Details::getGraphDiagOffsets (offsets, lclRowMap, lclColMap,
6927 lclGraph.entries, sorted);
6933 auto offsets_h = Kokkos::create_mirror_view (offsets);
6935 for (LO lclRowInd = 0; lclRowInd < lclNumRows; ++lclRowInd) {
6939 const GO gblRowInd = lclRowMap.getGlobalElement (lclRowInd);
6940 const GO gblColInd = gblRowInd;
6941 const LO lclColInd = lclColMap.getLocalElement (gblColInd);
6943 if (lclColInd == Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
6944 allRowMapDiagEntriesInColMap =
false;
6945 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6948 const RowInfo rowInfo = this->getRowInfo (lclRowInd);
6949 if (
static_cast<LO
> (rowInfo.localRow) == lclRowInd &&
6950 rowInfo.numEntries > 0) {
6952 auto colInds = this->getLocalKokkosRowView (rowInfo);
6953 const size_t hint = 0;
6954 const size_t offset =
6955 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
6956 lclColInd, hint, sorted);
6957 offsets_h(lclRowInd) = offset;
6964 Teuchos::ArrayView<const LO> lclColInds;
6966 this->getLocalRowView (lclRowInd, lclColInds);
6969 noOtherWeirdness =
false;
6972 if (noOtherWeirdness) {
6973 const size_t numEnt = lclColInds.size ();
6974 if (offset >= numEnt) {
6977 allOffsetsCorrect =
false;
6978 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6980 const LO actualLclColInd = lclColInds[offset];
6981 const GO actualGblColInd = lclColMap.getGlobalElement (actualLclColInd);
6982 if (actualGblColInd != gblColInd) {
6983 allOffsetsCorrect =
false;
6984 wrongOffsets.push_back (std::make_pair (lclRowInd, offset));
6991 offsets_h(lclRowInd) = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
6992 allDiagEntriesFound =
false;
7001 if (wrongOffsets.size () != 0) {
7002 std::ostringstream os;
7003 os <<
"Proc " << this->getComm ()->getRank () <<
": Wrong offsets: [";
7004 for (
size_t k = 0; k < wrongOffsets.size (); ++k) {
7005 os <<
"(" << wrongOffsets[k].first <<
","
7006 << wrongOffsets[k].second <<
")";
7007 if (k + 1 < wrongOffsets.size ()) {
7011 os <<
"]" << std::endl;
7012 std::cerr << os.str ();
7017 using Teuchos::reduceAll;
7019 Teuchos::RCP<const Teuchos::Comm<int> > comm = this->getComm ();
7020 const bool localSuccess =
7021 allRowMapDiagEntriesInColMap && allDiagEntriesFound && allOffsetsCorrect;
7022 const int numResults = 5;
7024 lclResults[0] = allRowMapDiagEntriesInColMap ? 1 : 0;
7025 lclResults[1] = allDiagEntriesFound ? 1 : 0;
7026 lclResults[2] = allOffsetsCorrect ? 1 : 0;
7027 lclResults[3] = noOtherWeirdness ? 1 : 0;
7030 lclResults[4] = ! localSuccess ? comm->getRank () : comm->getSize ();
7038 reduceAll<int, int> (*comm, Teuchos::REDUCE_MIN,
7039 numResults, lclResults, gblResults);
7041 if (gblResults[0] != 1 || gblResults[1] != 1 || gblResults[2] != 1
7042 || gblResults[3] != 1) {
7043 std::ostringstream os;
7044 os <<
"Issue(s) that we noticed (on Process " << gblResults[4] <<
", "
7045 "possibly among others): " << endl;
7046 if (gblResults[0] == 0) {
7047 os <<
" - The column Map does not contain at least one diagonal entry "
7048 "of the graph." << endl;
7050 if (gblResults[1] == 0) {
7051 os <<
" - On one or more processes, some row does not contain a "
7052 "diagonal entry." << endl;
7054 if (gblResults[2] == 0) {
7055 os <<
" - On one or more processes, some offsets are incorrect."
7058 if (gblResults[3] == 0) {
7059 os <<
" - One or more processes had some other error."
7062 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
true, std::runtime_error, os.str());
7085 template<
class DeviceType,
7086 const bool memSpaceIsHostSpace =
7087 std::is_same<
typename DeviceType::memory_space,
7088 Kokkos::HostSpace>::value>
7089 struct HelpGetLocalDiagOffsets {};
7091 template<
class DeviceType>
7092 struct HelpGetLocalDiagOffsets<DeviceType, true> {
7093 typedef DeviceType device_type;
7094 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
7095 Kokkos::MemoryUnmanaged> device_offsets_type;
7096 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
7097 Kokkos::MemoryUnmanaged> host_offsets_type;
7099 static device_offsets_type
7100 getDeviceOffsets (
const host_offsets_type& hostOffsets)
7108 copyBackIfNeeded (
const host_offsets_type& ,
7109 const device_offsets_type& )
7113 template<
class DeviceType>
7114 struct HelpGetLocalDiagOffsets<DeviceType, false> {
7115 typedef DeviceType device_type;
7119 typedef Kokkos::View<size_t*, device_type> device_offsets_type;
7120 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
7121 Kokkos::MemoryUnmanaged> host_offsets_type;
7123 static device_offsets_type
7124 getDeviceOffsets (
const host_offsets_type& hostOffsets)
7128 return device_offsets_type (
"offsets", hostOffsets.extent (0));
7132 copyBackIfNeeded (
const host_offsets_type& hostOffsets,
7133 const device_offsets_type& deviceOffsets)
7141 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7146 typedef LocalOrdinal LO;
7147 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
7148 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
7149 (! this->hasColMap (), std::runtime_error,
7150 "The graph does not yet have a column Map.");
7151 const LO myNumRows =
static_cast<LO
> (this->getNodeNumRows ());
7152 if (
static_cast<LO
> (offsets.size ()) != myNumRows) {
7156 offsets.resize (myNumRows);
7168 typedef HelpGetLocalDiagOffsets<device_type> helper_type;
7169 typedef typename helper_type::host_offsets_type host_offsets_type;
7171 host_offsets_type hostOffsets (offsets.getRawPtr (), myNumRows);
7173 auto deviceOffsets = helper_type::getDeviceOffsets (hostOffsets);
7175 this->getLocalDiagOffsets (deviceOffsets);
7176 helper_type::copyBackIfNeeded (hostOffsets, deviceOffsets);
7179 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7186 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7190 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& rowTransfer,
7191 const Teuchos::RCP<const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node> > & domainTransfer,
7192 const Teuchos::RCP<const map_type>& domainMap,
7193 const Teuchos::RCP<const map_type>& rangeMap,
7194 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7200 using Teuchos::ArrayRCP;
7201 using Teuchos::ArrayView;
7202 using Teuchos::Comm;
7203 using Teuchos::ParameterList;
7206 #ifdef HAVE_TPETRA_MMM_TIMINGS
7208 using Teuchos::TimeMonitor;
7211 using LO = LocalOrdinal;
7212 using GO = GlobalOrdinal;
7213 using NT = node_type;
7216 using packet_type =
typename this_type::packet_type;
7218 const char* prefix =
"Tpetra::CrsGraph::transferAndFillComplete: ";
7220 #ifdef HAVE_TPETRA_MMM_TIMINGS
7222 if(!params.is_null()) label = params->get(
"Timer Label", label);
7223 string prefix2 = string(
"Tpetra ")+ label + std::string(
": CrsGraph TAFC ");
7224 RCP<TimeMonitor> MM =
7225 rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Pack-1"))));
7233 const import_type* xferAsImport =
dynamic_cast<const import_type*
>(&rowTransfer);
7234 const export_type* xferAsExport =
dynamic_cast<const export_type*
>(&rowTransfer);
7235 TEUCHOS_TEST_FOR_EXCEPTION(
7236 xferAsImport ==
nullptr && xferAsExport ==
nullptr, std::invalid_argument,
7237 prefix <<
"The 'rowTransfer' input argument must be either an Import or "
7238 "an Export, and its template parameters must match the corresponding "
7239 "template parameters of the CrsGraph.");
7246 Teuchos::RCP<const import_type> xferDomainAsImport =
7247 Teuchos::rcp_dynamic_cast<const import_type>(domainTransfer);
7248 Teuchos::RCP<const export_type> xferDomainAsExport =
7249 Teuchos::rcp_dynamic_cast<const export_type>(domainTransfer);
7251 if(! domainTransfer.is_null()) {
7253 TEUCHOS_TEST_FOR_EXCEPTION(
7254 (xferDomainAsImport.is_null() && xferDomainAsExport.is_null()), std::invalid_argument,
7255 prefix <<
"The 'domainTransfer' input argument must be either an "
7256 "Import or an Export, and its template parameters must match the "
7257 "corresponding template parameters of the CrsGraph.");
7259 TEUCHOS_TEST_FOR_EXCEPTION(
7260 ( xferAsImport !=
nullptr || ! xferDomainAsImport.is_null() ) &&
7261 (( xferAsImport !=
nullptr && xferDomainAsImport.is_null() ) ||
7262 ( xferAsImport ==
nullptr && ! xferDomainAsImport.is_null() )), std::invalid_argument,
7263 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
7264 "must be of the same type (either Import or Export).");
7266 TEUCHOS_TEST_FOR_EXCEPTION(
7267 ( xferAsExport !=
nullptr || ! xferDomainAsExport.is_null() ) &&
7268 (( xferAsExport !=
nullptr && xferDomainAsExport.is_null() ) ||
7269 ( xferAsExport ==
nullptr && ! xferDomainAsExport.is_null() )), std::invalid_argument,
7270 prefix <<
"The 'rowTransfer' and 'domainTransfer' input arguments "
7271 "must be of the same type (either Import or Export).");
7278 const bool communication_needed = rowTransfer.getSourceMap()->isDistributed();
7284 bool reverseMode =
false;
7285 bool restrictComm =
false;
7286 RCP<ParameterList> graphparams;
7287 if (! params.is_null()) {
7288 reverseMode = params->get(
"Reverse Mode", reverseMode);
7289 restrictComm = params->get(
"Restrict Communicator", restrictComm);
7290 graphparams = sublist(params,
"CrsGraph");
7295 RCP<const map_type> MyRowMap = reverseMode ?
7296 rowTransfer.getSourceMap() : rowTransfer.getTargetMap();
7297 RCP<const map_type> MyColMap;
7298 RCP<const map_type> MyDomainMap = ! domainMap.is_null() ? domainMap : getDomainMap();
7299 RCP<const map_type> MyRangeMap = ! rangeMap.is_null() ? rangeMap : getRangeMap();
7300 RCP<const map_type> BaseRowMap = MyRowMap;
7301 RCP<const map_type> BaseDomainMap = MyDomainMap;
7309 if (! destGraph.is_null()) {
7320 const bool NewFlag =
7321 ! destGraph->isLocallyIndexed() && ! destGraph->isGloballyIndexed();
7322 TEUCHOS_TEST_FOR_EXCEPTION(! NewFlag, std::invalid_argument,
7323 prefix <<
"The input argument 'destGraph' is only allowed to be nonnull, "
7324 "if its graph is empty (neither locally nor globally indexed).");
7333 TEUCHOS_TEST_FOR_EXCEPTION(
7334 ! destGraph->getRowMap()->isSameAs(*MyRowMap), std::invalid_argument,
7335 prefix <<
"The (row) Map of the input argument 'destGraph' is not the "
7336 "same as the (row) Map specified by the input argument 'rowTransfer'.");
7338 TEUCHOS_TEST_FOR_EXCEPTION(
7339 ! destGraph->checkSizes(*
this), std::invalid_argument,
7340 prefix <<
"You provided a nonnull destination graph, but checkSizes() "
7341 "indicates that it is not a legal legal target for redistribution from "
7342 "the source graph (*this). This may mean that they do not have the "
7343 "same dimensions.");
7357 TEUCHOS_TEST_FOR_EXCEPTION(
7358 ! (reverseMode || getRowMap()->isSameAs(*rowTransfer.getSourceMap())),
7359 std::invalid_argument, prefix <<
7360 "rowTransfer->getSourceMap() must match this->getRowMap() in forward mode.");
7362 TEUCHOS_TEST_FOR_EXCEPTION(
7363 ! (! reverseMode || getRowMap()->isSameAs(*rowTransfer.getTargetMap())),
7364 std::invalid_argument, prefix <<
7365 "rowTransfer->getTargetMap() must match this->getRowMap() in reverse mode.");
7368 TEUCHOS_TEST_FOR_EXCEPTION(
7369 ! xferDomainAsImport.is_null() && ! xferDomainAsImport->getTargetMap()->isSameAs(*domainMap),
7370 std::invalid_argument,
7371 prefix <<
"The target map of the 'domainTransfer' input argument must be "
7372 "the same as the rebalanced domain map 'domainMap'");
7374 TEUCHOS_TEST_FOR_EXCEPTION(
7375 ! xferDomainAsExport.is_null() && ! xferDomainAsExport->getSourceMap()->isSameAs(*domainMap),
7376 std::invalid_argument,
7377 prefix <<
"The source map of the 'domainTransfer' input argument must be "
7378 "the same as the rebalanced domain map 'domainMap'");
7391 const size_t NumSameIDs = rowTransfer.getNumSameIDs();
7392 ArrayView<const LO> ExportLIDs = reverseMode ?
7393 rowTransfer.getRemoteLIDs() : rowTransfer.getExportLIDs();
7394 ArrayView<const LO> RemoteLIDs = reverseMode ?
7395 rowTransfer.getExportLIDs() : rowTransfer.getRemoteLIDs();
7396 ArrayView<const LO> PermuteToLIDs = reverseMode ?
7397 rowTransfer.getPermuteFromLIDs() : rowTransfer.getPermuteToLIDs();
7398 ArrayView<const LO> PermuteFromLIDs = reverseMode ?
7399 rowTransfer.getPermuteToLIDs() : rowTransfer.getPermuteFromLIDs();
7400 Distributor& Distor = rowTransfer.getDistributor();
7403 Teuchos::Array<int> SourcePids;
7404 Teuchos::Array<int> TargetPids;
7405 int MyPID = getComm()->getRank();
7408 RCP<const map_type> ReducedRowMap, ReducedColMap,
7409 ReducedDomainMap, ReducedRangeMap;
7410 RCP<const Comm<int> > ReducedComm;
7414 if (destGraph.is_null()) {
7415 destGraph = rcp(
new this_type(MyRowMap, 0, StaticProfile, graphparams));
7422 ReducedRowMap = MyRowMap->removeEmptyProcesses();
7423 ReducedComm = ReducedRowMap.is_null() ?
7425 ReducedRowMap->getComm();
7426 destGraph->removeEmptyProcessesInPlace(ReducedRowMap);
7428 ReducedDomainMap = MyRowMap.getRawPtr() == MyDomainMap.getRawPtr() ?
7430 MyDomainMap->replaceCommWithSubset(ReducedComm);
7431 ReducedRangeMap = MyRowMap.getRawPtr() == MyRangeMap.getRawPtr() ?
7433 MyRangeMap->replaceCommWithSubset(ReducedComm);
7436 MyRowMap = ReducedRowMap;
7437 MyDomainMap = ReducedDomainMap;
7438 MyRangeMap = ReducedRangeMap;
7441 if (! ReducedComm.is_null()) {
7442 MyPID = ReducedComm->getRank();
7449 ReducedComm = MyRowMap->getComm();
7455 #ifdef HAVE_TPETRA_MMM_TIMINGS
7457 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ImportSetup"))));
7460 RCP<const import_type> MyImporter = getImporter();
7463 bool bSameDomainMap = BaseDomainMap->isSameAs(*getDomainMap());
7465 if (! restrictComm && ! MyImporter.is_null() && bSameDomainMap ) {
7472 Import_Util::getPids(*MyImporter, SourcePids,
false);
7474 else if (restrictComm && ! MyImporter.is_null() && bSameDomainMap) {
7477 ivector_type SourceDomain_pids(getDomainMap(),
true);
7478 ivector_type SourceCol_pids(getColMap());
7480 SourceDomain_pids.putScalar(MyPID);
7482 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
7483 SourcePids.resize(getColMap()->getNodeNumElements());
7484 SourceCol_pids.get1dCopy(SourcePids());
7486 else if (MyImporter.is_null() && bSameDomainMap) {
7488 SourcePids.resize(getColMap()->getNodeNumElements());
7489 SourcePids.assign(getColMap()->getNodeNumElements(), MyPID);
7491 else if ( ! MyImporter.is_null() &&
7492 ! domainTransfer.is_null() ) {
7499 ivector_type TargetDomain_pids(domainMap);
7500 TargetDomain_pids.putScalar(MyPID);
7503 ivector_type SourceDomain_pids(getDomainMap());
7506 ivector_type SourceCol_pids(getColMap());
7508 if (! reverseMode && ! xferDomainAsImport.is_null() ) {
7509 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
7511 else if (reverseMode && ! xferDomainAsExport.is_null() ) {
7512 SourceDomain_pids.doExport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
7514 else if (! reverseMode && ! xferDomainAsExport.is_null() ) {
7515 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsExport,
INSERT);
7517 else if (reverseMode && ! xferDomainAsImport.is_null() ) {
7518 SourceDomain_pids.doImport(TargetDomain_pids, *xferDomainAsImport,
INSERT);
7521 TEUCHOS_TEST_FOR_EXCEPTION(
7522 true, std::logic_error,
7523 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
7525 SourceCol_pids.doImport(SourceDomain_pids, *MyImporter,
INSERT);
7526 SourcePids.resize(getColMap()->getNodeNumElements());
7527 SourceCol_pids.get1dCopy(SourcePids());
7529 else if (BaseDomainMap->isSameAs(*BaseRowMap) &&
7530 getDomainMap()->isSameAs(*getRowMap())) {
7532 ivector_type TargetRow_pids(domainMap);
7533 ivector_type SourceRow_pids(getRowMap());
7534 ivector_type SourceCol_pids(getColMap());
7536 TargetRow_pids.putScalar(MyPID);
7537 if (! reverseMode && xferAsImport !=
nullptr) {
7538 SourceRow_pids.doExport(TargetRow_pids, *xferAsImport,
INSERT);
7540 else if (reverseMode && xferAsExport !=
nullptr) {
7541 SourceRow_pids.doExport(TargetRow_pids, *xferAsExport,
INSERT);
7543 else if (! reverseMode && xferAsExport !=
nullptr) {
7544 SourceRow_pids.doImport(TargetRow_pids, *xferAsExport,
INSERT);
7546 else if (reverseMode && xferAsImport !=
nullptr) {
7547 SourceRow_pids.doImport(TargetRow_pids, *xferAsImport,
INSERT);
7550 TEUCHOS_TEST_FOR_EXCEPTION(
7551 true, std::logic_error,
7552 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
7554 SourceCol_pids.doImport(SourceRow_pids, *MyImporter,
INSERT);
7555 SourcePids.resize(getColMap()->getNodeNumElements());
7556 SourceCol_pids.get1dCopy(SourcePids());
7559 TEUCHOS_TEST_FOR_EXCEPTION(
7560 true, std::invalid_argument,
7561 prefix <<
"This method only allows either domainMap == getDomainMap(), "
7562 "or (domainMap == rowTransfer.getTargetMap() and getDomainMap() == getRowMap()).");
7566 size_t constantNumPackets = destGraph->constantNumberOfPackets();
7567 if (constantNumPackets == 0) {
7568 destGraph->reallocArraysForNumPacketsPerLid(ExportLIDs.size(),
7576 const size_t rbufLen = RemoteLIDs.size() * constantNumPackets;
7577 destGraph->reallocImportsIfNeeded(rbufLen,
false,
nullptr);
7582 destGraph->numExportPacketsPerLID_.modify_host();
7583 Teuchos::ArrayView<size_t> numExportPacketsPerLID =
7588 numExportPacketsPerLID, ExportLIDs,
7589 SourcePids, constantNumPackets, Distor);
7593 #ifdef HAVE_TPETRA_MMM_TIMINGS
7595 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Transfer"))));
7598 if (communication_needed) {
7600 if (constantNumPackets == 0) {
7604 destGraph->numExportPacketsPerLID_.sync_host();
7605 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
7607 destGraph->numImportPacketsPerLID_.sync_host();
7608 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
7610 Distor.doReversePostsAndWaits(numExportPacketsPerLID, 1,
7611 numImportPacketsPerLID);
7612 size_t totalImportPackets = 0;
7613 for (Array_size_type i = 0; i < numImportPacketsPerLID.size(); ++i) {
7614 totalImportPackets += numImportPacketsPerLID[i];
7619 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
7620 destGraph->imports_.modify_host();
7621 Teuchos::ArrayView<packet_type> hostImports =
7625 destGraph->exports_.sync_host();
7626 Teuchos::ArrayView<const packet_type> hostExports =
7628 Distor.doReversePostsAndWaits(hostExports,
7629 numExportPacketsPerLID,
7631 numImportPacketsPerLID);
7634 destGraph->imports_.modify_host();
7635 Teuchos::ArrayView<packet_type> hostImports =
7639 destGraph->exports_.sync_host();
7640 Teuchos::ArrayView<const packet_type> hostExports =
7642 Distor.doReversePostsAndWaits(hostExports,
7648 if (constantNumPackets == 0) {
7652 destGraph->numExportPacketsPerLID_.sync_host();
7653 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
7655 destGraph->numImportPacketsPerLID_.sync_host();
7656 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
7658 Distor.doPostsAndWaits(numExportPacketsPerLID, 1,
7659 numImportPacketsPerLID);
7660 size_t totalImportPackets = 0;
7661 for (Array_size_type i = 0; i < numImportPacketsPerLID.size(); ++i) {
7662 totalImportPackets += numImportPacketsPerLID[i];
7667 destGraph->reallocImportsIfNeeded(totalImportPackets,
false,
nullptr);
7668 destGraph->imports_.modify_host();
7669 Teuchos::ArrayView<packet_type> hostImports =
7673 destGraph->exports_.sync_host();
7674 Teuchos::ArrayView<const packet_type> hostExports =
7676 Distor.doPostsAndWaits(hostExports,
7677 numExportPacketsPerLID,
7679 numImportPacketsPerLID);
7682 destGraph->imports_.modify_host();
7683 Teuchos::ArrayView<packet_type> hostImports =
7687 destGraph->exports_.sync_host();
7688 Teuchos::ArrayView<const packet_type> hostExports =
7690 Distor.doPostsAndWaits(hostExports,
7701 #ifdef HAVE_TPETRA_MMM_TIMINGS
7703 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-1"))));
7707 destGraph->numImportPacketsPerLID_.sync_host();
7708 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
7710 destGraph->imports_.sync_host();
7711 Teuchos::ArrayView<const packet_type> hostImports =
7715 numImportPacketsPerLID,
7716 constantNumPackets, Distor,
INSERT,
7717 NumSameIDs, PermuteToLIDs, PermuteFromLIDs);
7718 size_t N = BaseRowMap->getNodeNumElements();
7721 ArrayRCP<size_t> CSR_rowptr(N+1);
7722 ArrayRCP<GO> CSR_colind_GID;
7723 ArrayRCP<LO> CSR_colind_LID;
7724 CSR_colind_GID.resize(mynnz);
7728 if (
typeid(LO) ==
typeid(GO)) {
7729 CSR_colind_LID = Teuchos::arcp_reinterpret_cast<LO>(CSR_colind_GID);
7732 CSR_colind_LID.resize(mynnz);
7741 numImportPacketsPerLID, constantNumPackets,
7742 Distor,
INSERT, NumSameIDs, PermuteToLIDs,
7743 PermuteFromLIDs, N, mynnz, MyPID,
7744 CSR_rowptr(), CSR_colind_GID(),
7745 SourcePids(), TargetPids);
7750 #ifdef HAVE_TPETRA_MMM_TIMINGS
7752 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"Unpack-2"))));
7757 Teuchos::Array<int> RemotePids;
7758 Import_Util::lowCommunicationMakeColMapAndReindex(CSR_rowptr(),
7762 TargetPids, RemotePids,
7769 ReducedColMap = (MyRowMap.getRawPtr() == MyColMap.getRawPtr()) ?
7771 MyColMap->replaceCommWithSubset(ReducedComm);
7772 MyColMap = ReducedColMap;
7776 destGraph->replaceColMap(MyColMap);
7783 if (ReducedComm.is_null()) {
7790 if ((! reverseMode && xferAsImport !=
nullptr) ||
7791 (reverseMode && xferAsExport !=
nullptr)) {
7792 Import_Util::sortCrsEntries(CSR_rowptr(),
7795 else if ((! reverseMode && xferAsExport !=
nullptr) ||
7796 (reverseMode && xferAsImport !=
nullptr)) {
7797 Import_Util::sortAndMergeCrsEntries(CSR_rowptr(),
7799 if (CSR_rowptr[N] != mynnz) {
7800 CSR_colind_LID.resize(CSR_rowptr[N]);
7804 TEUCHOS_TEST_FOR_EXCEPTION(
7805 true, std::logic_error,
7806 prefix <<
"Should never get here! Please report this bug to a Tpetra developer.");
7814 destGraph->setAllIndices(CSR_rowptr, CSR_colind_LID);
7820 Teuchos::ParameterList esfc_params;
7821 #ifdef HAVE_TPETRA_MMM_TIMINGS
7823 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"CreateImporter"))));
7825 RCP<import_type> MyImport = rcp(
new import_type(MyDomainMap, MyColMap, RemotePids));
7826 #ifdef HAVE_TPETRA_MMM_TIMINGS
7828 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2+
string(
"ESFC"))));
7830 esfc_params.set(
"Timer Label",prefix + std::string(
"TAFC"));
7832 if(!params.is_null())
7833 esfc_params.set(
"compute global constants",params->get(
"compute global constants",
true));
7835 destGraph->expertStaticFillComplete(MyDomainMap, MyRangeMap,
7836 MyImport, Teuchos::null, rcp(&esfc_params,
false));
7840 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7845 const Teuchos::RCP<const map_type>& domainMap,
7846 const Teuchos::RCP<const map_type>& rangeMap,
7847 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7849 transferAndFillComplete(destGraph, importer, Teuchos::null, domainMap, rangeMap, params);
7852 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7858 const Teuchos::RCP<const map_type>& domainMap,
7859 const Teuchos::RCP<const map_type>& rangeMap,
7860 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7862 transferAndFillComplete(destGraph, rowImporter, Teuchos::rcpFromRef(domainImporter), domainMap, rangeMap, params);
7865 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7870 const Teuchos::RCP<const map_type>& domainMap,
7871 const Teuchos::RCP<const map_type>& rangeMap,
7872 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7874 transferAndFillComplete(destGraph, exporter, Teuchos::null, domainMap, rangeMap, params);
7877 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7883 const Teuchos::RCP<const map_type>& domainMap,
7884 const Teuchos::RCP<const map_type>& rangeMap,
7885 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
7887 transferAndFillComplete(destGraph, rowExporter, Teuchos::rcpFromRef(domainExporter), domainMap, rangeMap, params);
7891 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7896 std::swap(graph.
rowMap_, this->rowMap_);
7897 std::swap(graph.
colMap_, this->colMap_);
7898 std::swap(graph.
rangeMap_, this->rangeMap_);
7899 std::swap(graph.
domainMap_, this->domainMap_);
7901 std::swap(graph.
importer_, this->importer_);
7902 std::swap(graph.
exporter_, this->exporter_);
7904 std::swap(graph.
lclGraph_, this->lclGraph_);
7913 std::swap(graph.
pftype_, this->pftype_);
7917 std::swap(graph.
k_rowPtrs_, this->k_rowPtrs_);
7922 std::swap(graph.
lclInds2D_, this->lclInds2D_);
7923 std::swap(graph.
gblInds2D_, this->gblInds2D_);
7927 std::swap(graph.indicesAreAllocated_, this->indicesAreAllocated_);
7928 std::swap(graph.indicesAreLocal_, this->indicesAreLocal_);
7929 std::swap(graph.indicesAreGlobal_, this->indicesAreGlobal_);
7930 std::swap(graph.fillComplete_, this->fillComplete_);
7942 std::swap(graph.
nonlocals_, this->nonlocals_);
7946 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7951 auto compare_nonlocals = [&] (
const nonlocals_type & m1,
const nonlocals_type & m2) {
7953 output = m1.size() == m2.size() ? output :
false;
7954 for(
auto & it_m: m1)
7956 size_t key = it_m.first;
7957 output = m2.find(key) != m2.end() ? output :
false;
7960 auto v1 = m1.find(key)->second;
7961 auto v2 = m2.find(key)->second;
7962 std::sort(v1.begin(), v1.end());
7963 std::sort(v2.begin(), v2.end());
7965 output = v1.size() == v2.size() ? output :
false;
7966 for(
size_t i=0; output && i<v1.size(); i++)
7968 output = v1[i]==v2[i] ? output :
false;
7977 output = this->rowMap_->isSameAs( *(graph.
rowMap_) ) ? output :
false;
7978 output = this->colMap_->isSameAs( *(graph.
colMap_) ) ? output :
false;
7979 output = this->rangeMap_->isSameAs( *(graph.
rangeMap_) ) ? output :
false;
7980 output = this->domainMap_->isSameAs( *(graph.
domainMap_) ) ? output :
false;
7982 output = this->nodeNumDiags_ == graph.
nodeNumDiags_ ? output :
false;
7986 output = this->globalNumDiags_ == graph.
globalNumDiags_ ? output :
false;
7989 output = this->pftype_ == graph.
pftype_ ? output :
false;
7993 output = this->lclInds2D_ == graph.
lclInds2D_ ? output :
false;
7994 output = this->gblInds2D_ == graph.
gblInds2D_ ? output :
false;
7996 output = this->storageStatus_ == graph.
storageStatus_ ? output :
false;
7998 output = this->indicesAreAllocated_ == graph.indicesAreAllocated_ ? output :
false;
7999 output = this->indicesAreLocal_ == graph.indicesAreLocal_ ? output :
false;
8000 output = this->indicesAreGlobal_ == graph.indicesAreGlobal_ ? output :
false;
8001 output = this->fillComplete_ == graph.fillComplete_ ? output :
false;
8002 output = this->lowerTriangular_ == graph.
lowerTriangular_ ? output :
false;
8003 output = this->upperTriangular_ == graph.
upperTriangular_ ? output :
false;
8005 output = this->noRedundancies_ == graph.
noRedundancies_ ? output :
false;
8008 output = this->sortGhostsAssociatedWithEachProcessor_ == this->sortGhostsAssociatedWithEachProcessor_ ? output :
false;
8012 output = compare_nonlocals(this->nonlocals_, graph.
nonlocals_) ? output :
false;
8016 output = this->k_numAllocPerRow_.extent(0) == graph.
k_numAllocPerRow_.extent(0) ? output :
false;
8017 if(output && this->k_numAllocPerRow_.extent(0) > 0)
8019 for(
size_t i=0; output && i<this->k_numAllocPerRow_.extent(0); i++)
8020 output = this->k_numAllocPerRow_(i) == graph.
k_numAllocPerRow_(i) ? output :
false;
8025 output = this->k_numRowEntries_.extent(0) == graph.
k_numRowEntries_.extent(0) ? output :
false;
8026 if(output && this->k_numRowEntries_.extent(0) > 0)
8028 for(
size_t i = 0; output && i < this->k_numRowEntries_.extent(0); i++)
8029 output = this->k_numRowEntries_(i) == graph.
k_numRowEntries_(i) ? output :
false;
8033 output = this->k_rowPtrs_.extent(0) == graph.
k_rowPtrs_.extent(0) ? output :
false;
8034 if(output && this->k_rowPtrs_.extent(0) > 0)
8036 typename local_graph_type::row_map_type::const_type::HostMirror k_rowPtrs_host_this = Kokkos::create_mirror_view(this->k_rowPtrs_);
8037 typename local_graph_type::row_map_type::const_type::HostMirror k_rowPtrs_host_graph= Kokkos::create_mirror_view(graph.
k_rowPtrs_);
8040 for(
size_t i=0; output && i<k_rowPtrs_host_this.extent(0); i++)
8041 output = k_rowPtrs_host_this(i) == k_rowPtrs_host_graph(i) ? output :
false;
8045 output = this->k_lclInds1D_.extent(0) == graph.
k_lclInds1D_.extent(0) ? output :
false;
8046 if(output && this->k_lclInds1D_.extent(0) > 0)
8048 typename local_graph_type::entries_type::non_const_type::HostMirror k_lclInds1D_host_this = Kokkos::create_mirror_view(this->k_lclInds1D_);
8049 typename local_graph_type::entries_type::non_const_type::HostMirror k_lclInds1D_host_graph= Kokkos::create_mirror_view(graph.
k_lclInds1D_);
8052 for(
size_t i=0; output && i < k_lclInds1D_host_this.extent(0); i++)
8053 output = k_lclInds1D_host_this(i) == k_lclInds1D_host_graph(i) ? output :
false;
8057 output = this->k_gblInds1D_.extent(0) == graph.
k_gblInds1D_.extent(0) ? output :
false;
8058 if(output && this->k_gblInds1D_.extent(0) > 0)
8060 typename t_GlobalOrdinal_1D::HostMirror k_gblInds1D_host_this = Kokkos::create_mirror_view(this->k_gblInds1D_);
8061 typename t_GlobalOrdinal_1D::HostMirror k_gblInds1D_host_graph = Kokkos::create_mirror_view(graph.
k_gblInds1D_);
8064 for(
size_t i=0; output && i<k_gblInds1D_host_this.extent(0); i++)
8065 output = k_gblInds1D_host_this(i) == k_gblInds1D_host_graph(i) ? output :
false;
8075 output = this->lclGraph_.row_map.extent(0) == graph.
lclGraph_.row_map.extent(0) ? output :
false;
8076 if(output && this->lclGraph_.row_map.extent(0) > 0)
8078 typename local_graph_type::row_map_type::HostMirror lclGraph_rowmap_host_this = Kokkos::create_mirror_view(this->lclGraph_.row_map);
8079 typename local_graph_type::row_map_type::HostMirror lclGraph_rowmap_host_graph = Kokkos::create_mirror_view(graph.
lclGraph_.row_map);
8082 for(
size_t i=0; output && i<lclGraph_rowmap_host_this.extent(0); i++)
8083 output = lclGraph_rowmap_host_this(i) == lclGraph_rowmap_host_graph(i) ? output :
false;
8086 output = this->lclGraph_.entries.extent(0) == graph.
lclGraph_.entries.extent(0) ? output :
false;
8087 if(output && this->lclGraph_.entries.extent(0) > 0)
8089 typename local_graph_type::entries_type::HostMirror lclGraph_entries_host_this = Kokkos::create_mirror_view(this->lclGraph_.entries);
8090 typename local_graph_type::entries_type::HostMirror lclGraph_entries_host_graph = Kokkos::create_mirror_view(graph.
lclGraph_.entries);
8093 for(
size_t i=0; output && i<lclGraph_entries_host_this.extent(0); i++)
8094 output = lclGraph_entries_host_this(i) == lclGraph_entries_host_graph(i) ? output :
false;
8097 output = this->lclGraph_.row_block_offsets.extent(0) == graph.
lclGraph_.row_block_offsets.extent(0) ? output :
false;
8098 if(output && this->lclGraph_.row_block_offsets.extent(0) > 0)
8100 typename local_graph_type::row_block_type::HostMirror lclGraph_rbo_host_this = Kokkos::create_mirror_view(this->lclGraph_.row_block_offsets);
8101 typename local_graph_type::row_block_type::HostMirror lclGraph_rbo_host_graph = Kokkos::create_mirror_view(graph.
lclGraph_.row_block_offsets);
8104 for(
size_t i=0; output && i < lclGraph_rbo_host_this.extent(0); i++)
8105 output = lclGraph_rbo_host_this(i) == lclGraph_rbo_host_graph(i) ? output :
false;
8126 #define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
8128 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
8129 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
8130 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8131 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8132 CrsGraph<LO,GO,NODE>::node_type>& importer, \
8133 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8134 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8135 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
8136 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8137 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8138 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
8139 const Teuchos::RCP<Teuchos::ParameterList>& params);
8141 #define TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
8143 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
8144 importAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
8145 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8146 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8147 CrsGraph<LO,GO,NODE>::node_type>& rowImporter, \
8148 const Import<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8149 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8150 CrsGraph<LO,GO,NODE>::node_type>& domainImporter, \
8151 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8152 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8153 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
8154 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8155 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8156 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
8157 const Teuchos::RCP<Teuchos::ParameterList>& params);
8160 #define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
8162 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
8163 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
8164 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8165 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8166 CrsGraph<LO,GO,NODE>::node_type>& exporter, \
8167 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8168 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8169 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
8170 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8171 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8172 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
8173 const Teuchos::RCP<Teuchos::ParameterList>& params);
8175 #define TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
8177 Teuchos::RCP<CrsGraph<LO,GO,NODE> > \
8178 exportAndFillCompleteCrsGraph(const Teuchos::RCP<const CrsGraph<LO,GO,NODE> >& sourceGraph, \
8179 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8180 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8181 CrsGraph<LO,GO,NODE>::node_type>& rowExporter, \
8182 const Export<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8183 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8184 CrsGraph<LO,GO,NODE>::node_type>& domainExporter, \
8185 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8186 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8187 CrsGraph<LO,GO,NODE>::node_type> >& domainMap, \
8188 const Teuchos::RCP<const Map<CrsGraph<LO,GO,NODE>::local_ordinal_type, \
8189 CrsGraph<LO,GO,NODE>::global_ordinal_type, \
8190 CrsGraph<LO,GO,NODE>::node_type> >& rangeMap, \
8191 const Teuchos::RCP<Teuchos::ParameterList>& params);
8194 #define TPETRA_CRSGRAPH_INSTANT( LO, GO, NODE ) \
8195 template class CrsGraph<LO, GO, NODE>; \
8196 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
8197 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT(LO,GO,NODE) \
8198 TPETRA_CRSGRAPH_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE) \
8199 TPETRA_CRSGRAPH_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(LO,GO,NODE)
8202 #endif // TPETRA_CRSGRAPH_DEF_HPP