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>
223 CrsGraph<LocalOrdinal, GlobalOrdinal, 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 ?
238 ::Tpetra::Details::STORAGE_1D_UNPACKED :
239 ::Tpetra::Details::STORAGE_2D)
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 ?
282 ::Tpetra::Details::STORAGE_1D_UNPACKED :
283 ::Tpetra::Details::STORAGE_2D)
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 ?
324 ::Tpetra::Details::STORAGE_1D_UNPACKED :
325 ::Tpetra::Details::STORAGE_2D)
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 ?
397 ::Tpetra::Details::STORAGE_1D_UNPACKED :
398 ::Tpetra::Details::STORAGE_2D)
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()).");
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",
447 Kokkos::
deep_copy (numAllocPerRowOut, numAllocPerRowIn);
453 #endif // TPETRA_ENABLE_DEPRECATED_CODE
456 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
457 CrsGraph<LocalOrdinal, GlobalOrdinal, 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) :
473 ::Tpetra::Details::STORAGE_1D_UNPACKED :
474 ::Tpetra::Details::STORAGE_2D)
475 , indicesAreAllocated_ (false)
476 , indicesAreLocal_ (false)
477 , indicesAreGlobal_ (false)
478 , fillComplete_ (false)
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()).");
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 ?
534 ::Tpetra::Details::STORAGE_1D_UNPACKED :
535 ::Tpetra::Details::STORAGE_2D)
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()).");
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 ?
594 ::Tpetra::Details::STORAGE_1D_UNPACKED :
595 ::Tpetra::Details::STORAGE_2D)
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()).");
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",
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 ?
670 ::Tpetra::Details::STORAGE_1D_UNPACKED :
671 ::Tpetra::Details::STORAGE_2D)
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()).");
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",
720 Kokkos::
deep_copy (numAllocPerRowOut, numAllocPerRowIn);
726 #endif // TPETRA_ENABLE_DEPRECATED_CODE
728 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
729 CrsGraph<LocalOrdinal, GlobalOrdinal, 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>& ) :
746 , indicesAreAllocated_(true)
747 , indicesAreLocal_(true)
748 , indicesAreGlobal_(false)
749 , fillComplete_(false)
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)
780 , storageStatus_ (::Tpetra::Details::STORAGE_1D_PACKED)
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)
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)
831 , storageStatus_ (::Tpetra::Details::STORAGE_1D_PACKED)
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(
866 ": cannot have 1D data structures allocated.");
867 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
869 ": cannot have 2D data structures allocated.");
872 rangeMap .is_null() ?
rowMap_ : rangeMap);
873 Teuchos::Array<int> remotePIDs (0);
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) {
887 this->fillComplete_ =
true;
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),
916 storageStatus_ (::Tpetra::Details::STORAGE_1D_PACKED),
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.");
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) {
948 fillComplete_ =
true;
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");
976 Distributor distributor (rowMap_->getComm (), importSublist);
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
1057 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1058 getNodeNumDiags ()
const
1060 return this->getNodeNumDiagsImpl ();
1063 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1065 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1066 getGlobalNumDiagsImpl ()
const
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>
1079 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1080 getNodeNumDiagsImpl ()
const
1082 return nodeNumDiags_;
1084 #endif // TPETRA_ENABLE_DEPRECATED_CODE
1086 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
1087 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1090 CrsGraph<LocalOrdinal, GlobalOrdinal, 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
1300 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1301 isUpperTriangular ()
const
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>
1316 CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::
1317 isUpperTriangularImpl ()
const
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>
1405 return rowMap_->getIndexBase ();
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,
1465 device_type> gbl_col_inds_type;
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);
1584 Kokkos::
deep_copy (numRowEnt, static_cast<
size_t> (0));
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;
1741 typedef Kokkos::View<
const LO*, execution_space,
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;
1784 typedef Kokkos::View<LO*, execution_space,
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);
1878 Kokkos::View<
const GlobalOrdinal*, execution_space,
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);
1948 Kokkos::View<GlobalOrdinal*, execution_space,
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>
2108 using Teuchos::OrdinalTraits;
2109 typedef LocalOrdinal LO;
2110 typedef GlobalOrdinal GO;
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>
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>
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>
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>
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>
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>
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): ";
4207 const
bool debug = ::Tpetra::Details::Behavior::debug ();
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>
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 ();
4972 execution_space().fence ();
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;
4994 execution_space().fence ();
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>
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,
6035 const Kokkos::DualView<
const local_ordinal_type*,
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;
6089 using LO = local_ordinal_type;
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;
6137 using LO = local_ordinal_type;
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
6394 using LO = local_ordinal_type;
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
6666 (
const Kokkos::DualView<
const local_ordinal_type*,
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,
6677 using LO = local_ordinal_type;
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>
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);
6915 auto lclRowMap = rowMap.getLocalMap ();
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;
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;
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
Teuchos::ArrayRCP< Teuchos::Array< local_ordinal_type > > lclInds2D_
Local column indices for all rows.
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
void setDomainRangeMaps(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap)
Teuchos::RCP< const map_type > getRowMap() const override
Returns the Map that describes the row distribution in this graph.
void setAllIndices(const typename local_graph_type::row_map_type &rowPointers, const typename local_graph_type::entries_type::non_const_type &columnIndices)
Set the graph's data directly, using 1-D storage.
size_t nodeMaxNumRowEntries_
Local maximum of the number of entries in each row.
bool indicesAreSorted_
Whether the graph's indices are sorted in each row, on this process.
void copyOffsets(const OutputViewType &dst, const InputViewType &src)
Copy row offsets (in a sparse graph or matrix) from src to dst. The offsets may have different types...
Teuchos::RCP< const map_type > rangeMap_
The Map describing the range of the (matrix corresponding to the) graph.
Teuchos::RCP< const map_type > getColMap() const override
Returns the Map that describes the column distribution in this graph.
size_t getNodeMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, on this process.
bool isNodeGlobalElement(GlobalOrdinal globalIndex) const
Whether the given global index is owned by this Map on the calling process.
void insertGlobalIndicesFiltered(const local_ordinal_type lclRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Like insertGlobalIndices(), but with column Map filtering.
bool lowerTriangular_
Whether the graph is locally lower triangular.
size_t nodeNumDiags_
Local number of (populated) diagonal entries.
bool sortGhostsAssociatedWithEachProcessor_
Whether to require makeColMap() (and therefore fillComplete()) to order column Map GIDs associated wi...
size_t insertGlobalIndicesImpl(const local_ordinal_type lclRow, const global_ordinal_type inputGblColInds[], const size_t numInputInds)
Insert global indices, using an input local row index.
void resumeFill(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Resume fill operations.
bool haveGlobalConstants_
Whether all processes have computed global constants.
void expertStaticFillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< const import_type > &importer=Teuchos::null, const Teuchos::RCP< const export_type > &exporter=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Perform a fillComplete on a graph that already has data, via setAllIndices().
Teuchos::RCP< const import_type > getImporter() const override
Returns the importer associated with this graph.
void getLocalDiagOffsets(const Kokkos::View< size_t *, device_type, Kokkos::MemoryUnmanaged > &offsets) const
Get offsets of the diagonal entries in the graph.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
Kokkos::View< global_ordinal_type *, execution_space > t_GlobalOrdinal_1D
Type of the k_gblInds1D_ array of global column indices.
t_GlobalOrdinal_1D k_gblInds1D_
Global column indices for all rows.
void insertGlobalIndices(const global_ordinal_type globalRow, const Teuchos::ArrayView< const global_ordinal_type > &indices)
Insert global indices into the graph.
size_t getNumEntriesInLocalRow(local_ordinal_type localRow) const override
Get the number of entries in the given row (local index).
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Default parameter list suitable for validation.
bool isIdenticalTo(const CrsGraph< LocalOrdinal, GlobalOrdinal, Node > &graph) const
Create a cloned CrsGraph for a different Node type.
bool isMerged() const
Whether duplicate column indices in each row have been merged.
virtual bool checkSizes(const SrcDistObject &source) override
Compare the source and target (this) objects for compatibility.
global_size_t globalNumDiags_
Global number of (populated) diagonal entries.
Teuchos::RCP< const map_type > getDomainMap() const override
Returns the Map associated with the domain of this graph.
size_t getGlobalMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, over all processes in the graph's communicator...
void getLocalRowView(const local_ordinal_type lclRow, Teuchos::ArrayView< const local_ordinal_type > &lclColInds) const override
Get a const, non-persisting view of the given local row's local column indices, as a Teuchos::ArrayVi...
Declare and define Tpetra::Details::copyOffsets, an implementation detail of Tpetra (in particular...
bool noRedundancies_
Whether the graph's indices are non-redundant (merged) in each row, on this process.
bool upperTriangular_
Whether the graph is locally upper triangular.
OffsetsViewType::non_const_value_type computeOffsetsFromConstantCount(const OffsetsViewType &ptr, const CountType count)
Compute offsets from a constant count.
static bool debug()
Whether Tpetra is in debug mode.
size_t findLocalIndices(const RowInfo &rowInfo, const Teuchos::ArrayView< const local_ordinal_type > &indices, std::function< void(const size_t, const size_t, const size_t)> fun) const
Finds indices in the given row.
size_t getNumAllocatedEntriesInGlobalRow(global_ordinal_type globalRow) const
Current number of allocated entries in the given row on the calling (MPI) process, using a global row index.
std::pair< size_t, std::string > makeIndicesLocal()
Convert column indices from global to local.
Allocation information for a locally owned row in a CrsGraph or CrsMatrix.
size_t unpackAndCombineWithOwningPIDsCount(const CrsGraph< LO, GO, NT > &sourceGraph, const Teuchos::ArrayView< const LO > &importLIDs, const Teuchos::ArrayView< const typename CrsGraph< LO, GO, NT >::packet_type > &imports, const Teuchos::ArrayView< const size_t > &numPacketsPerLID, size_t constantNumPackets, Distributor &distor, CombineMode combineMode, size_t numSameIDs, const Teuchos::ArrayView< const LO > &permuteToLIDs, const Teuchos::ArrayView< const LO > &permuteFromLIDs)
Special version of Tpetra::Details::unpackCrsGraphAndCombine that also unpacks owning process ranks...
bool hasColMap() const override
Whether the graph has a column Map.
bool isGloballyIndexed() const override
Whether the graph's column indices are stored as global indices.
void exportAndFillComplete(Teuchos::RCP< CrsGraph< local_ordinal_type, global_ordinal_type, Node > > &destGraph, const export_type &exporter, const Teuchos::RCP< const map_type > &domainMap=Teuchos::null, const Teuchos::RCP< const map_type > &rangeMap=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null) const
Export from this to the given destination graph, and make the result fill complete.
Teuchos_Ordinal Array_size_type
Size type for Teuchos Array objects.
bool isStorageOptimized() const
Returns true if storage has been optimized.
bool haveLocalConstants_
Whether this process has computed local constants.
bool isNodeLocalElement(LocalOrdinal localIndex) const
Whether the given local index is valid for this Map on the calling process.
::Tpetra::Details::EStorageStatus storageStatus_
Status of the graph's storage, when not in a fill-complete state.
std::string description() const override
Return a one-line human-readable description of this object.
local_ordinal_type getLocalViewRawConst(const local_ordinal_type *&lclInds, local_ordinal_type &capacity, const RowInfo &rowInfo) const
Get a pointer to the local column indices of a locally owned row, using the result of getRowInfo...
void gathervPrint(std::ostream &out, const std::string &s, const Teuchos::Comm< int > &comm)
On Process 0 in the given communicator, print strings from each process in that communicator, in rank order.
void makeColMap(Teuchos::Array< int > &remotePIDs)
Make and set the graph's column Map.
Teuchos::RCP< const export_type > getExporter() const override
Returns the exporter associated with this graph.
void getNumEntriesPerLocalRowUpperBound(Teuchos::ArrayRCP< const size_t > &boundPerLocalRow, size_t &boundForAllLocalRows, bool &boundSameForAllLocalRows) const
Get an upper bound on the number of entries that can be stored in each row.
size_t global_size_t
Global size_t object.
size_t getNodeNumEntries() const override
The local number of entries in the graph.
virtual void removeEmptyProcessesInPlace(const Teuchos::RCP< const map_type > &newMap) override
Remove processes owning zero rows from the Maps and their communicator.
Node node_type
This class' Kokkos Node type.
void reindexColumns(const Teuchos::RCP< const map_type > &newColMap, const Teuchos::RCP< const import_type > &newImport=Teuchos::null, const bool sortIndicesInEachRow=true)
Reindex the column indices in place, and replace the column Map. Optionally, replace the Import objec...
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
void makeImportExport(Teuchos::Array< int > &remotePIDs, const bool useRemotePIDs)
Make the Import and Export objects, if needed.
size_t sortAndMergeRowIndices(const RowInfo &rowInfo, const bool sorted, const bool merged)
Sort and merge duplicate column indices in the given row.
void insertLocalIndices(const local_ordinal_type localRow, const Teuchos::ArrayView< const local_ordinal_type > &indices)
Insert local indices into the graph.
Insert new values that don't currently exist.
void getGlobalRowCopy(global_ordinal_type gblRow, const Teuchos::ArrayView< global_ordinal_type > &gblColInds, size_t &numColInds) const override
Get a copy of the given row, using global indices.
bool isSorted() const
Whether graph indices in all rows are known to be sorted.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createOneToOne(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &M)
Nonmember constructor for a contiguous Map with user-defined weights and a user-specified, possibly nondefault Kokkos Node type.
Teuchos::RCP< const map_type > rowMap_
The Map describing the distribution of rows of the graph.
Teuchos::RCP< const import_type > importer_
The Import from the domain Map to the column Map.
size_t insertCrsIndices(typename Pointers::value_type const row, Pointers const &rowPtrs, InOutIndices &curIndices, size_t &numAssigned, InIndices const &newIndices, std::function< void(const size_t, const size_t, const size_t)> cb=std::function< void(const size_t, const size_t, const size_t)>())
Insert new indices in to current list of indices.
num_row_entries_type k_numRowEntries_
The number of local entries in each locally owned row.
Teuchos::RCP< const map_type > domainMap_
The Map describing the domain of the (matrix corresponding to the) graph.
OffsetType convertColumnIndicesFromGlobalToLocal(const Kokkos::View< LO *, DT > &lclColInds, const Kokkos::View< const GO *, DT > &gblColInds, const Kokkos::View< const OffsetType *, DT > &ptr, const LocalMap< LO, GO, DT > &lclColMap, const Kokkos::View< const NumEntType *, DT > &numRowEnt)
Convert a (StaticProfile) CrsGraph's global column indices into local column indices.
global_size_t getGlobalNumRows() const override
Returns the number of global rows in the graph.
Teuchos::ArrayView< const global_ordinal_type > getGlobalView(const RowInfo &rowinfo) const
Get a const, nonowned, globally indexed view of the locally owned row myRow, such that rowinfo = getR...
Functions for manipulating CRS arrays.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
void setLocallyModified()
Report that we made a local modification to its structure.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
local_graph_type::entries_type::non_const_type k_lclInds1D_
Local column indices for all rows.
Teuchos::ArrayView< local_ordinal_type > getLocalViewNonConst(const RowInfo &rowinfo)
Get a nonconst, nonowned, locally indexed view of the locally owned row myRow, such that rowinfo = ge...
size_t getNodeNumRows() const override
Returns the number of graph rows owned on the calling node.
ProfileType getProfileType() const
Returns true if the graph was allocated with static data structures.
void checkInternalState() const
Throw an exception if the internal state is not consistent.
Kokkos::StaticCrsGraph< local_ordinal_type, Kokkos::LayoutLeft, execution_space > local_graph_type
The type of the part of the sparse graph on each MPI process.
local_graph_type lclGraph_
Local graph; only initialized after first fillComplete() call.
Sets up and executes a communication plan for a Tpetra DistObject.
local_graph_type::row_map_type::const_type k_rowPtrs_
Row offsets for "1-D" storage.
size_t findCrsIndices(typename Pointers::value_type const row, Pointers const &rowPtrs, const size_t curNumEntries, Indices1 const &curIndices, Indices2 const &newIndices, Callback &&cb)
Finds offsets in to current list of indices.
GlobalOrdinal getGlobalElement(LocalOrdinal localIndex) const
The global index corresponding to the given local index.
CombineMode
Rule for combining data in an Import or Export.
Kokkos::View< const size_t *, execution_space >::HostMirror k_numAllocPerRow_
The maximum number of entries to allow in each locally owned row, per row.
Teuchos::RCP< const export_type > exporter_
The Export from the row Map to the range Map.
void insertGlobalIndicesIntoNonownedRows(const global_ordinal_type gblRow, const global_ordinal_type gblColInds[], const local_ordinal_type numGblColInds)
Implementation of insertGlobalIndices for nonowned rows.
LocalTriangularStructureResult< typename LocalMapType::local_ordinal_type > determineLocalTriangularStructure(const LocalGraphType &G, const LocalMapType &rowMap, const LocalMapType &colMap, const bool ignoreMapsForTriangularStructure)
Count the local number of diagonal entries in a local sparse graph, and determine whether the local p...
void unpackAndCombineIntoCrsArrays(const CrsGraph< LO, GO, NT > &sourceGraph, const Teuchos::ArrayView< const LO > &importLIDs, const Teuchos::ArrayView< const typename CrsGraph< LO, GO, NT >::packet_type > &imports, const Teuchos::ArrayView< const size_t > &numPacketsPerLID, const size_t constantNumPackets, Distributor &distor, const CombineMode combineMode, const size_t numSameIDs, const Teuchos::ArrayView< const LO > &permuteToLIDs, const Teuchos::ArrayView< const LO > &permuteFromLIDs, size_t TargetNumRows, size_t TargetNumNonzeros, const int MyTargetPID, const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< GO > &CRS_colind, const Teuchos::ArrayView< const int > &SourcePids, Teuchos::Array< int > &TargetPids)
unpackAndCombineIntoCrsArrays
Declaration and definition of Tpetra::Details::determineLocalTriangularStructure. ...
bool isFillComplete() const override
Whether fillComplete() has been called and the graph is in compute mode.
size_t getNumAllocatedEntriesInLocalRow(local_ordinal_type localRow) const
Current number of allocated entries in the given row on the calling (MPI) process, using a local row index.
void computeLocalConstants(const bool computeLocalTriangularConstants)
Compute local constants, if they have not yet been computed.
Teuchos::ArrayRCP< const size_t > getNodeRowPtrs() const
Get a host view of the row offsets.
void swap(CrsGraph< local_ordinal_type, global_ordinal_type, Node > &graph)
Swaps the data from *this with the data and maps from graph.
void globalAssemble()
Communicate nonlocal contributions to other processes.
CrsGraphType::global_ordinal_type getGlobalNumDiags(const CrsGraphType &G)
Number of populated diagonal entries in the given sparse graph, over all processes in the graph's (MP...
typename device_type::execution_space execution_space
This class' Kokkos execution space.
Teuchos::ArrayRCP< Teuchos::Array< global_ordinal_type > > gblInds2D_
Global column indices for all rows.
RowInfo getRowInfoFromGlobalRowIndex(const global_ordinal_type gblRow) const
Get information about the locally owned row with global index gblRow.
Utility functions for packing and unpacking sparse matrix entries.
void packCrsGraph(const CrsGraph< LO, GO, NT > &sourceGraph, Teuchos::Array< typename CrsGraph< LO, GO, NT >::packet_type > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &exportLIDs, size_t &constantNumPackets, Distributor &distor)
Pack specified entries of the given local sparse graph for communication.
Abstract base class for objects that can be the source of an Import or Export operation.
void removeLocalIndices(local_ordinal_type localRow)
Remove all graph indices from the specified local row.
size_t getNodeAllocationSize() const
The local number of indices allocated for the graph, over all rows on the calling (MPI) process...
LocalOrdinal local_ordinal_type
The type of the graph's local indices.
global_size_t globalNumEntries_
Global number of entries in the graph.
Teuchos::ArrayView< global_ordinal_type > getGlobalViewNonConst(const RowInfo &rowinfo)
Get a nonconst, nonowned, globally indexed view of the locally owned row myRow, such that rowinfo = g...
ProfileType pftype_
Whether the graph was allocated with static or dynamic profile.
Teuchos::RCP< const map_type > getRangeMap() const override
Returns the Map associated with the domain of this graph.
void replaceColMap(const Teuchos::RCP< const map_type > &newColMap)
Replace the graph's current column Map with the given Map.
void getGlobalRowView(const global_ordinal_type gblRow, Teuchos::ArrayView< const global_ordinal_type > &gblColInds) const override
Get a const, non-persisting view of the given global row's global column indices, as a Teuchos::Array...
::Kokkos::Compat::KokkosDeviceWrapperNode< execution_space > node_type
Default value of Node template parameter.
global_size_t getGlobalNumCols() const override
Returns the number of global columns in the graph.
RowInfo getRowInfo(const local_ordinal_type myRow) const
Get information about the locally owned row with local index myRow.
size_t getNodeNumCols() const override
Returns the number of columns connected to the locally owned rows of this graph.
void replaceDomainMapAndImporter(const Teuchos::RCP< const map_type > &newDomainMap, const Teuchos::RCP< const import_type > &newImporter)
Replace the current domain Map and Import with the given parameters.
bool supportsRowViews() const override
Whether this class implements getLocalRowView() and getGlobalRowView() (it does). ...
LocalOrdinal getLocalElement(GlobalOrdinal globalIndex) const
The local index corresponding to the given global index.
local_map_type getLocalMap() const
Get the local Map for Kokkos kernels.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
void computeGlobalConstants(const bool computeLocalTriangularConstants)
Compute global constants, if they have not yet been computed.
Teuchos::ArrayView< const local_ordinal_type > getLocalView(const RowInfo &rowinfo) const
Get a const, nonowned, locally indexed view of the locally owned row myRow, such that rowinfo = getRo...
A parallel distribution of indices over processes.
local_ordinal_type getGlobalViewRawConst(const global_ordinal_type *&gblInds, local_ordinal_type &capacity, const RowInfo &rowInfo) const
Get a pointer to the global column indices of a locally owned row, using the result of getRowInfoFrom...
int makeColMap(Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &colMap, Teuchos::Array< int > &remotePIDs, const Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &domMap, const RowGraph< LO, GO, NT > &graph, const bool sortEachProcsGids=true, std::ostream *errStrm=NULL)
Make the graph's column Map.
Teuchos::ArrayView< typename DualViewType::t_dev::value_type > getArrayViewFromDualView(const DualViewType &x)
Get a Teuchos::ArrayView which views the host Kokkos::View of the input 1-D Kokkos::DualView.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects...
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > ¶ms) override
Set the given list of parameters (must be nonnull).
size_t getNumEntriesInGlobalRow(global_ordinal_type globalRow) const override
Returns the current number of entries on this node in the specified global row.
void fillComplete(const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Tell the graph that you are done changing its structure.
typename Node::device_type device_type
This class' Kokkos device type.
bool isLocallyIndexed() const override
Whether the graph's column indices are stored as local indices.
A distributed dense vector.
Teuchos::ArrayRCP< const local_ordinal_type > getNodePackedIndices() const
Get an Teuchos::ArrayRCP of the packed column-indices.
bool isFillActive() const
Whether resumeFill() has been called and the graph is in edit mode.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
Returns the communicator.
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const ExecutionSpace &execSpace, const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
void importAndFillComplete(Teuchos::RCP< CrsGraph< local_ordinal_type, global_ordinal_type, Node > > &destGraph, const import_type &importer, const Teuchos::RCP< const map_type > &domainMap, const Teuchos::RCP< const map_type > &rangeMap, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null) const
Import from this to the given destination graph, and make the result fill complete.
global_size_t globalMaxNumRowEntries_
Global maximum of the number of entries in each row.
static size_t verbosePrintCountThreshold()
Threshold, below which arrays, lists, etc. will be printed in debug mode.
local_graph_type getLocalGraph() const
Get the local graph.
void packCrsGraphNew(const CrsGraph< LO, GO, NT > &sourceGraph, const Kokkos::DualView< const LO *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exportLIDs, const Kokkos::DualView< const int *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exportPIDs, Kokkos::DualView< typename CrsGraph< LO, GO, NT >::packet_type *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exports, Kokkos::DualView< size_t *, typename CrsGraph< LO, GO, NT >::buffer_device_type > numPacketsPerLID, size_t &constantNumPackets, const bool pack_pids, Distributor &distor)
Pack specified entries of the given local sparse graph for communication, for "new" DistObject interf...
void padCrsArrays(const RowPtr &rowPtrBeg, const RowPtr &rowPtrEnd, Indices &indices, const Padding &padding)
Determine if the row pointers and indices arrays need to be resized to accommodate new entries...
size_t insertIndices(RowInfo &rowInfo, const SLocalGlobalViews &newInds, const ELocalGlobal lg, const ELocalGlobal I)
Insert indices into the given row.
global_size_t getGlobalNumEntries() const override
Returns the global number of entries in the graph.
Declaration and definition of Tpetra::Details::getEntryOnHost.
size_t numAllocForAllRows_
The maximum number of entries to allow in each locally owned row.
Teuchos::RCP< const map_type > colMap_
The Map describing the distribution of columns of the graph.
global_ordinal_type getIndexBase() const override
Returns the index base for global indices for this graph.
void packCrsGraphWithOwningPIDs(const CrsGraph< LO, GO, NT > &sourceGraph, Kokkos::DualView< typename CrsGraph< LO, GO, NT >::packet_type *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exports_dv, const Teuchos::ArrayView< size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &exportLIDs, const Teuchos::ArrayView< const int > &sourcePIDs, size_t &constantNumPackets, Distributor &distor)
Pack specified entries of the given local sparse graph for communication.
virtual void pack(const Teuchos::ArrayView< const local_ordinal_type > &exportLIDs, Teuchos::Array< global_ordinal_type > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, size_t &constantNumPackets, Distributor &distor) const override
Pack this object's data for Import or Export.
void getLocalRowCopy(local_ordinal_type lclRow, const Teuchos::ArrayView< local_ordinal_type > &lclColInds, size_t &numColInds) const override
Get a copy of the given row, using local indices.
nonlocals_type nonlocals_
Nonlocal data given to insertGlobalIndices.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const override
Print this object to the given output stream with the given verbosity level.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.