42 #ifndef TPETRA_CRSMATRIX_DEF_HPP
43 #define TPETRA_CRSMATRIX_DEF_HPP
53 #include "Tpetra_LocalCrsMatrixOperator.hpp"
56 #include "Tpetra_RowMatrix.hpp"
63 #include "Tpetra_Details_gathervPrint.hpp"
64 #include "Tpetra_Details_getDiagCopyWithoutOffsets.hpp"
65 #include "Tpetra_Details_leftScaleLocalCrsMatrix.hpp"
67 #include "Tpetra_Details_rightScaleLocalCrsMatrix.hpp"
68 #include "KokkosSparse_getDiagCopy.hpp"
69 #include "Tpetra_Details_copyConvert.hpp"
72 #include "Tpetra_Details_packCrsMatrix.hpp"
73 #include "Tpetra_Details_unpackCrsMatrixAndCombine.hpp"
75 #include "Teuchos_FancyOStream.hpp"
76 #include "Teuchos_RCP.hpp"
77 #include "Teuchos_DataAccess.hpp"
78 #include "Teuchos_SerialDenseMatrix.hpp"
86 using Teuchos::rcpFromRef;
92 template<
class T,
class BinaryFunction>
93 T atomic_binary_function_update (
volatile T*
const dest,
107 T newVal = f (assume, inputVal);
108 oldVal = Kokkos::atomic_compare_exchange (dest, assume, newVal);
109 }
while (assume != oldVal);
129 template<
class Scalar>
133 typedef Teuchos::ScalarTraits<Scalar> STS;
134 return std::max (STS::magnitude (x), STS::magnitude (y));
143 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
144 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
145 CrsMatrix (
const Teuchos::RCP<const map_type>& rowMap,
146 size_t maxNumEntriesPerRow,
148 const Teuchos::RCP<Teuchos::ParameterList>& params) :
150 storageStatus_ (pftype == StaticProfile ?
151 ::Tpetra::Details::STORAGE_1D_UNPACKED :
152 ::Tpetra::Details::STORAGE_2D),
153 fillComplete_ (false),
154 frobNorm_ (-STM::one ())
156 const char tfecfFuncName[] =
"CrsMatrix(RCP<const Map>, size_t, "
157 "ProfileType[, RCP<ParameterList>]): ";
158 Teuchos::RCP<crs_graph_type> graph;
160 graph = Teuchos::rcp (
new crs_graph_type (rowMap, maxNumEntriesPerRow,
163 catch (std::exception& e) {
164 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
165 (
true, std::runtime_error,
"CrsGraph constructor (RCP<const Map>, "
166 "size_t, ProfileType[, RCP<ParameterList>]) threw an exception: "
173 staticGraph_ = myGraph_;
178 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
181 const Teuchos::ArrayView<const size_t>& numEntPerRowToAlloc,
183 const Teuchos::RCP<Teuchos::ParameterList>& params) :
185 storageStatus_ (pftype == StaticProfile ?
186 ::Tpetra::Details::STORAGE_1D_UNPACKED :
187 ::Tpetra::Details::STORAGE_2D),
188 fillComplete_ (false),
189 frobNorm_ (-STM::one ())
191 const char tfecfFuncName[] =
"CrsMatrix(RCP<const Map>, "
192 "ArrayView<const size_t>, ProfileType[, RCP<ParameterList>]): ";
193 Teuchos::RCP<crs_graph_type> graph;
195 graph = Teuchos::rcp (
new crs_graph_type (rowMap, numEntPerRowToAlloc,
198 catch (std::exception &e) {
199 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
200 (
true, std::runtime_error,
"CrsGraph constructor (RCP<const Map>, "
201 "ArrayView<const size_t>, ProfileType[, RCP<ParameterList>]) threw "
202 "an exception: " << e.what ());
208 staticGraph_ = graph;
213 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
214 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
216 CrsMatrix (
const Teuchos::RCP<const map_type>& rowMap,
217 const Teuchos::ArrayRCP<const size_t>& numEntPerRowToAlloc,
219 const Teuchos::RCP<Teuchos::ParameterList>& params) :
220 dist_object_type (rowMap),
221 storageStatus_ (pftype == StaticProfile ?
222 ::Tpetra::Details::STORAGE_1D_UNPACKED :
223 ::Tpetra::Details::STORAGE_2D),
224 fillComplete_ (false),
225 frobNorm_ (-STM::one ())
227 const char tfecfFuncName[] =
"CrsMatrix(RCP<const Map>, "
228 "ArrayRCP<const size_t>, ProfileType[, RCP<ParameterList>]): ";
229 Teuchos::RCP<crs_graph_type> graph;
231 graph = Teuchos::rcp (
new crs_graph_type (rowMap, numEntPerRowToAlloc (),
234 catch (std::exception &e) {
235 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
236 (
true, std::runtime_error,
"CrsGraph constructor (RCP<const Map>, "
237 "ArrayView<const size_t>, ProfileType[, RCP<ParameterList>]) threw "
238 "an exception: " << e.what ());
244 staticGraph_ = graph;
248 #endif // TPETRA_ENABLE_DEPRECATED_CODE
250 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
251 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
252 CrsMatrix (
const Teuchos::RCP<const map_type>& rowMap,
253 const Teuchos::RCP<const map_type>& colMap,
254 const size_t maxNumEntPerRow,
256 const Teuchos::RCP<Teuchos::ParameterList>& params) :
258 storageStatus_ (pftype == StaticProfile ?
259 ::Tpetra::Details::STORAGE_1D_UNPACKED :
260 ::Tpetra::Details::STORAGE_2D),
261 fillComplete_ (false),
262 frobNorm_ (-STM::one ())
264 const char tfecfFuncName[] =
"CrsMatrix(RCP<const Map>, RCP<const Map>, "
265 "size_t, ProfileType[, RCP<ParameterList>]): ";
267 #ifdef HAVE_TPETRA_DEBUG
269 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
270 (! staticGraph_.is_null (), std::logic_error,
271 "staticGraph_ is not null at the beginning of the constructor. "
272 "Please report this bug to the Tpetra developers.");
273 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
274 (! myGraph_.is_null (), std::logic_error,
275 "myGraph_ is not null at the beginning of the constructor. "
276 "Please report this bug to the Tpetra developers.");
277 #endif // HAVE_TPETRA_DEBUG
279 Teuchos::RCP<crs_graph_type> graph;
285 catch (std::exception &e) {
286 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
287 (
true, std::runtime_error,
"CrsGraph constructor (RCP<const Map>, "
288 "RCP<const Map>, size_t, ProfileType[, RCP<ParameterList>]) threw an "
289 "exception: " << e.what ());
295 staticGraph_ = myGraph_;
300 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
303 const Teuchos::RCP<const map_type>& colMap,
304 const Teuchos::ArrayView<const size_t>& numEntPerRowToAlloc,
306 const Teuchos::RCP<Teuchos::ParameterList>& params) :
308 storageStatus_ (pftype == StaticProfile ?
309 ::Tpetra::Details::STORAGE_1D_UNPACKED :
310 ::Tpetra::Details::STORAGE_2D),
311 fillComplete_ (false),
312 frobNorm_ (-STM::one ())
314 const char tfecfFuncName[] =
"CrsMatrix(RCP<const Map>, RCP<const Map>, "
315 "ArrayView<const size_t>, ProfileType[, RCP<ParameterList>]): ";
316 Teuchos::RCP<crs_graph_type> graph;
322 catch (std::exception &e) {
323 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
324 (
true, std::runtime_error,
"CrsGraph constructor (RCP<const Map>, "
325 "RCP<const Map>, ArrayView<const size_t>, ProfileType[, "
326 "RCP<ParameterList>]) threw an exception: " << e.what ());
332 staticGraph_ = graph;
337 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
338 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
340 CrsMatrix (
const Teuchos::RCP<const map_type>& rowMap,
341 const Teuchos::RCP<const map_type>& colMap,
342 const Teuchos::ArrayRCP<const size_t>& numEntPerRowToAlloc,
344 const Teuchos::RCP<Teuchos::ParameterList>& params) :
345 dist_object_type (rowMap),
346 storageStatus_ (pftype == StaticProfile ?
347 ::Tpetra::Details::STORAGE_1D_UNPACKED :
348 ::Tpetra::Details::STORAGE_2D),
349 fillComplete_ (false),
350 frobNorm_ (-STM::one ())
352 const char tfecfFuncName[] =
"CrsMatrix(RCP<const Map>, RCP<const Map>, "
353 "ArrayRCP<const size_t>, ProfileType[, RCP<ParameterList>]): ";
354 Teuchos::RCP<crs_graph_type> graph;
357 numEntPerRowToAlloc (),
360 catch (std::exception &e) {
361 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
362 (
true, std::runtime_error,
"CrsGraph constructor (RCP<const Map>, "
363 "RCP<const Map>, ArrayView<const size_t>, ProfileType[, "
364 "RCP<ParameterList>]) threw an exception: " << e.what ());
370 staticGraph_ = graph;
374 #endif // TPETRA_ENABLE_DEPRECATED_CODE
376 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
377 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
378 CrsMatrix (
const Teuchos::RCP<const crs_graph_type>& graph,
379 const Teuchos::RCP<Teuchos::ParameterList>& ) :
381 staticGraph_ (graph),
382 storageStatus_ (::Tpetra::Details::STORAGE_1D_PACKED),
383 fillComplete_ (false),
384 frobNorm_ (-STM::one ())
386 typedef typename local_matrix_type::values_type values_type;
387 const char tfecfFuncName[] =
"CrsMatrix(RCP<const CrsGraph>[, "
388 "RCP<ParameterList>]): ";
389 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
390 (graph.is_null (), std::runtime_error,
"Input graph is null.");
391 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
392 (! graph->isFillComplete (), std::runtime_error,
"Input graph is not "
393 "fill complete. You must call fillComplete on the graph before using "
394 "it to construct a CrsMatrix. Note that calling resumeFill on the "
395 "graph makes it not fill complete, even if you had previously called "
396 "fillComplete. In that case, you must call fillComplete on the graph "
405 const size_t numCols = graph->getColMap ()->getNodeNumElements ();
406 auto lclGraph = graph->getLocalGraph ();
407 const size_t numEnt = lclGraph.entries.extent (0);
408 values_type val (
"Tpetra::CrsMatrix::val", numEnt);
410 auto lclMat = std::make_shared<local_matrix_type>
411 (
"Tpetra::CrsMatrix::lclMatrix_", numCols, val, lclGraph);
412 lclMatrix_ = std::make_shared<local_multiply_op_type> (lclMat);
417 k_values1D_ = lclMat->values;
422 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
424 CrsMatrix (
const Teuchos::RCP<const crs_graph_type>& graph,
425 const typename local_matrix_type::values_type& values,
426 const Teuchos::RCP<Teuchos::ParameterList>& ) :
428 staticGraph_ (graph),
429 storageStatus_ (::Tpetra::Details::STORAGE_1D_PACKED),
430 fillComplete_ (false),
431 frobNorm_ (-STM::one ())
433 const char tfecfFuncName[] =
"CrsMatrix(RCP<const CrsGraph>,local_matrix_type::values_type,[, "
434 "RCP<ParameterList>]): ";
435 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
436 (graph.is_null (), std::runtime_error,
"Input graph is null.");
437 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
438 (! graph->isFillComplete (), std::runtime_error,
"Input graph is not "
439 "fill complete. You must call fillComplete on the graph before using "
440 "it to construct a CrsMatrix. Note that calling resumeFill on the "
441 "graph makes it not fill complete, even if you had previously called "
442 "fillComplete. In that case, you must call fillComplete on the graph "
451 const size_t numCols = graph->getColMap ()->getNodeNumElements ();
452 auto lclGraph = graph->getLocalGraph ();
454 auto lclMat = std::make_shared<local_matrix_type>
455 (
"Tpetra::CrsMatrix::lclMatrix_", numCols, values, lclGraph);
456 lclMatrix_ = std::make_shared<local_multiply_op_type> (lclMat);
461 k_values1D_ = lclMat->values;
468 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
471 const Teuchos::RCP<const map_type>& colMap,
472 const typename local_matrix_type::row_map_type& rowPointers,
473 const typename local_graph_type::entries_type::non_const_type& columnIndices,
474 const typename local_matrix_type::values_type& values,
475 const Teuchos::RCP<Teuchos::ParameterList>& params) :
477 storageStatus_ (::Tpetra::Details::STORAGE_1D_PACKED),
478 fillComplete_ (false),
479 frobNorm_ (-STM::one ())
482 const char tfecfFuncName[] =
"Tpetra::CrsMatrix(RCP<const Map>, "
483 "RCP<const Map>, ptr, ind, val[, params]): ";
484 const char suffix[] =
". Please report this bug to the Tpetra developers.";
490 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
491 (values.extent (0) != columnIndices.extent (0),
492 std::invalid_argument,
"Input arrays don't have matching dimensions. "
493 "values.extent(0) = " << values.extent (0) <<
" != "
494 "columnIndices.extent(0) = " << columnIndices.extent (0) <<
".");
495 #ifdef HAVE_TPETRA_DEBUG
496 if (rowPointers.extent (0) != 0) {
497 const size_t numEnt =
498 ::Tpetra::Details::getEntryOnHost (rowPointers, rowPointers.extent (0) - 1);
499 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
500 (numEnt != static_cast<size_t> (columnIndices.extent (0)) ||
501 numEnt != static_cast<size_t> (values.extent (0)),
502 std::invalid_argument,
"Last entry of rowPointers says that the matrix"
503 " has " << numEnt <<
" entr" << (numEnt != 1 ?
"ies" :
"y") <<
", but "
504 "the dimensions of columnIndices and values don't match this. "
505 "columnIndices.extent(0) = " << columnIndices.extent (0) <<
506 " and values.extent(0) = " << values.extent (0) <<
".");
508 #endif // HAVE_TPETRA_DEBUG
510 RCP<crs_graph_type> graph;
512 graph = Teuchos::rcp (
new crs_graph_type (rowMap, colMap, rowPointers,
513 columnIndices, params));
515 catch (std::exception& e) {
516 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
517 (
true, std::runtime_error,
"CrsGraph constructor (RCP<const Map>, "
518 "RCP<const Map>, ptr, ind[, params]) threw an exception: "
526 auto lclGraph = graph->getLocalGraph ();
527 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
528 (lclGraph.row_map.extent (0) != rowPointers.extent (0) ||
529 lclGraph.entries.extent (0) != columnIndices.extent (0),
530 std::logic_error,
"CrsGraph's constructor (rowMap, colMap, ptr, "
531 "ind[, params]) did not set the local graph correctly." << suffix);
532 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
533 (lclGraph.entries.extent (0) != values.extent (0),
534 std::logic_error,
"CrsGraph's constructor (rowMap, colMap, ptr, ind[, "
535 "params]) did not set the local graph correctly. "
536 "lclGraph.entries.extent(0) = " << lclGraph.entries.extent (0)
537 <<
" != values.extent(0) = " << values.extent (0) << suffix);
543 staticGraph_ = graph;
552 const size_t numCols = graph->getColMap ()->getNodeNumElements ();
554 auto lclMat = std::make_shared<local_matrix_type>
555 (
"Tpetra::CrsMatrix::lclMatrix_", numCols, values, lclGraph);
556 lclMatrix_ = std::make_shared<local_multiply_op_type> (lclMat);
558 auto newValues = lclMat->values;
559 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
560 (newValues.extent (0) != values.extent (0),
561 std::logic_error,
"Local matrix's constructor did not set the "
562 "values correctly. newValues.extent(0) = " <<
563 newValues.extent (0) <<
" != values.extent(0) = " <<
564 values.extent (0) << suffix);
569 this->k_values1D_ = newValues;
574 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
577 const Teuchos::RCP<const map_type>& colMap,
578 const Teuchos::ArrayRCP<size_t>& ptr,
579 const Teuchos::ArrayRCP<LocalOrdinal>& ind,
580 const Teuchos::ArrayRCP<Scalar>& val,
581 const Teuchos::RCP<Teuchos::ParameterList>& params) :
583 storageStatus_ (::Tpetra::Details::STORAGE_1D_PACKED),
584 fillComplete_ (false),
585 frobNorm_ (-STM::one ())
587 using Kokkos::Compat::getKokkosViewDeepCopy;
588 using Teuchos::av_reinterpret_cast;
590 typedef typename local_matrix_type::values_type values_type;
592 const char tfecfFuncName[] =
"Tpetra::CrsMatrix(RCP<const Map>, "
593 "RCP<const Map>, ptr, ind, val[, params]): ";
595 RCP<crs_graph_type> graph;
600 catch (std::exception& e) {
601 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
602 (
true, std::runtime_error,
"CrsGraph constructor (RCP<const Map>, "
603 "RCP<const Map>, ArrayRCP<size_t>, ArrayRCP<LocalOrdinal>[, "
604 "RCP<ParameterList>]) threw an exception: " << e.what ());
610 staticGraph_ = graph;
623 auto lclGraph = staticGraph_->getLocalGraph ();
624 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
625 (
size_t (lclGraph.row_map.extent (0)) !=
size_t (ptr.size ()) ||
626 size_t (lclGraph.entries.extent (0)) !=
size_t (ind.size ()),
627 std::logic_error,
"CrsGraph's constructor (rowMap, colMap, "
628 "ptr, ind[, params]) did not set the local graph correctly. "
629 "Please report this bug to the Tpetra developers.");
631 const size_t numCols =
632 staticGraph_->getColMap ()->getNodeNumElements ();
634 getKokkosViewDeepCopy<device_type> (av_reinterpret_cast<IST> (val ()));
636 auto lclMat = std::make_shared<local_matrix_type>
637 (
"Tpetra::CrsMatrix::lclMatrix_", numCols, valIn, lclGraph);
638 lclMatrix_ = std::make_shared<local_multiply_op_type> (lclMat);
643 this->k_values1D_ = lclMat->values;
648 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
651 const Teuchos::RCP<const map_type>& colMap,
653 const Teuchos::RCP<Teuchos::ParameterList>& params) :
657 k_values1D_ (lclMatrix.values),
658 storageStatus_ (::Tpetra::Details::STORAGE_1D_PACKED),
659 fillComplete_ (true),
660 frobNorm_ (-STM::one ())
662 const char tfecfFuncName[] =
"Tpetra::CrsMatrix(RCP<const Map>, "
663 "RCP<const Map>, local_matrix_type[, RCP<ParameterList>]): ";
664 Teuchos::RCP<crs_graph_type> graph;
667 lclMatrix.graph, params));
669 catch (std::exception& e) {
670 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
671 (
true, std::runtime_error,
"CrsGraph constructor (RCP<const Map>, "
672 "RCP<const Map>, local_graph_type[, RCP<ParameterList>]) threw an "
673 "exception: " << e.what ());
675 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
676 (!graph->isFillComplete (), std::logic_error,
"CrsGraph constructor (RCP"
677 "<const Map>, RCP<const Map>, local_graph_type[, RCP<ParameterList>]) "
678 "did not produce a fill-complete graph. Please report this bug to the "
679 "Tpetra developers.");
684 staticGraph_ = graph;
686 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
687 params->get (
"compute global constants",
true);
688 if (callComputeGlobalConstants) {
693 #ifdef HAVE_TPETRA_DEBUG
694 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
isFillActive (), std::logic_error,
695 "We're at the end of fillComplete(), but isFillActive() is true. "
696 "Please report this bug to the Tpetra developers.");
697 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
isFillComplete (), std::logic_error,
698 "We're at the end of fillComplete(), but isFillComplete() is false. "
699 "Please report this bug to the Tpetra developers.");
700 #endif // HAVE_TPETRA_DEBUG
704 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
707 const Teuchos::RCP<const map_type>& rowMap,
708 const Teuchos::RCP<const map_type>& colMap,
709 const Teuchos::RCP<const map_type>& domainMap,
710 const Teuchos::RCP<const map_type>& rangeMap,
711 const Teuchos::RCP<Teuchos::ParameterList>& params) :
715 k_values1D_ (lclMatrix.values),
716 storageStatus_ (::Tpetra::Details::STORAGE_1D_PACKED),
717 fillComplete_ (true),
718 frobNorm_ (-STM::one ())
720 const char tfecfFuncName[] =
"Tpetra::CrsMatrix(RCP<const Map>, "
721 "RCP<const Map>, RCP<const Map>, RCP<const Map>, local_matrix_type[, "
722 "RCP<ParameterList>]): ";
723 Teuchos::RCP<crs_graph_type> graph;
725 graph = Teuchos::rcp (
new crs_graph_type (lclMatrix.graph, rowMap, colMap,
726 domainMap, rangeMap, params));
728 catch (std::exception& e) {
729 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
730 (
true, std::runtime_error,
"CrsGraph constructor (RCP<const Map>, "
731 "RCP<const Map>, RCP<const Map>, RCP<const Map>, local_graph_type[, "
732 "RCP<ParameterList>]) threw an exception: " << e.what ());
734 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
735 (!graph->isFillComplete (), std::logic_error,
"CrsGraph constructor (RCP"
736 "<const Map>, RCP<const Map>, RCP<const Map>, RCP<const Map>, local_graph_type[, "
737 "RCP<ParameterList>]) did not produce a fill-complete graph. Please report this "
738 "bug to the Tpetra developers.");
743 staticGraph_ = graph;
745 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
746 params->get (
"compute global constants",
true);
747 if (callComputeGlobalConstants) {
752 #ifdef HAVE_TPETRA_DEBUG
753 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
isFillActive (), std::logic_error,
754 "We're at the end of fillComplete(), but isFillActive() is true. "
755 "Please report this bug to the Tpetra developers.");
756 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
isFillComplete (), std::logic_error,
757 "We're at the end of fillComplete(), but isFillComplete() is false. "
758 "Please report this bug to the Tpetra developers.");
759 #endif // HAVE_TPETRA_DEBUG
763 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
766 const Teuchos::RCP<const map_type>& rowMap,
767 const Teuchos::RCP<const map_type>& colMap,
768 const Teuchos::RCP<const map_type>& domainMap,
769 const Teuchos::RCP<const map_type>& rangeMap,
770 const Teuchos::RCP<const import_type>& importer,
771 const Teuchos::RCP<const export_type>& exporter,
772 const Teuchos::RCP<Teuchos::ParameterList>& params) :
776 k_values1D_ (lclMatrix.values),
777 storageStatus_ (::Tpetra::Details::STORAGE_1D_PACKED),
778 fillComplete_ (true),
779 frobNorm_ (-STM::one ())
782 const char tfecfFuncName[] =
"Tpetra::CrsMatrix"
783 "(lclMat,Map,Map,Map,Map,Import,Export,params): ";
785 Teuchos::RCP<crs_graph_type> graph;
788 domainMap, rangeMap, importer,
791 catch (std::exception& e) {
792 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
793 (
true, std::runtime_error,
"CrsGraph constructor "
794 "(local_graph_type, Map, Map, Map, Map, Import, Export, "
795 "params) threw: " << e.what ());
797 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
798 (!graph->isFillComplete (), std::logic_error,
"CrsGraph "
799 "constructor (local_graph_type, Map, Map, Map, Map, Import, "
800 "Export, params) did not produce a fill-complete graph. "
801 "Please report this bug to the Tpetra developers.");
806 staticGraph_ = graph;
808 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
809 params->get (
"compute global constants",
true);
810 if (callComputeGlobalConstants) {
815 #ifdef HAVE_TPETRA_DEBUG
816 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
isFillActive (), std::logic_error,
817 "We're at the end of fillComplete(), but isFillActive() is true. "
818 "Please report this bug to the Tpetra developers.");
819 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!
isFillComplete (), std::logic_error,
820 "We're at the end of fillComplete(), but isFillComplete() is false. "
821 "Please report this bug to the Tpetra developers.");
822 #endif // HAVE_TPETRA_DEBUG
826 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
829 const Teuchos::DataAccess copyOrView)
830 :
CrsMatrix (source.getCrsGraph (), source.getLocalValuesView ())
832 const char tfecfFuncName[] =
"Tpetra::CrsMatrix("
833 "const CrsMatrix&, const Teuchos::DataAccess): ";
834 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
836 "Source graph must be fillComplete().");
838 if (copyOrView == Teuchos::Copy) {
839 using values_type =
typename local_matrix_type::values_type;
841 using Kokkos::view_alloc;
842 using Kokkos::WithoutInitializing;
843 values_type newvals (view_alloc (
"val", WithoutInitializing),
846 k_values1D_ = newvals;
851 else if (copyOrView == Teuchos::View) {
855 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
856 (
true, std::invalid_argument,
"Second argument 'copyOrView' "
857 "has an invalid value " << copyOrView <<
". Valid values "
858 "include Teuchos::Copy = " << Teuchos::Copy <<
" and "
859 "Teuchos::View = " << Teuchos::View <<
".");
865 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
870 std::swap(crs_matrix.
importMV_, this->importMV_);
871 std::swap(crs_matrix.
exportMV_, this->exportMV_);
872 std::swap(crs_matrix.staticGraph_, this->staticGraph_);
873 std::swap(crs_matrix.myGraph_, this->myGraph_);
874 std::swap(crs_matrix.
lclMatrix_, this->lclMatrix_);
875 std::swap(crs_matrix.k_values1D_, this->k_values1D_);
876 std::swap(crs_matrix.values2D_, this->values2D_);
879 std::swap(crs_matrix.
nonlocals_, this->nonlocals_);
880 std::swap(crs_matrix.
frobNorm_, this->frobNorm_);
884 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
885 Teuchos::RCP<const Teuchos::Comm<int> >
888 return getCrsGraphRef ().getComm ();
891 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
892 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
897 return Teuchos::null;
899 #endif // TPETRA_ENABLE_DEPRECATED_CODE
901 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
905 return this->getCrsGraphRef ().getProfileType ();
908 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
912 return fillComplete_;
915 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
919 return ! fillComplete_;
922 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
926 return this->getCrsGraphRef ().isStorageOptimized ();
929 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
933 return getCrsGraphRef ().isLocallyIndexed ();
936 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
940 return getCrsGraphRef ().isGloballyIndexed ();
943 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
947 return getCrsGraphRef ().hasColMap ();
950 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
954 return getCrsGraphRef ().getGlobalNumEntries ();
957 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
961 return getCrsGraphRef ().getNodeNumEntries ();
964 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
968 return getCrsGraphRef ().getGlobalNumRows ();
971 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
975 return getCrsGraphRef ().getGlobalNumCols ();
978 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
982 return getCrsGraphRef ().getNodeNumRows ();
985 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
989 return getCrsGraphRef ().getNodeNumCols ();
992 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
993 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
997 return this->getGlobalNumDiagsImpl ();
1000 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1001 size_t TPETRA_DEPRECATED
1002 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1003 getNodeNumDiags ()
const {
1004 return this->getNodeNumDiagsImpl ();
1007 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1009 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1010 getGlobalNumDiagsImpl ()
const {
1011 const crs_graph_type& G = this->getCrsGraphRef ();
1012 using HDM = ::Tpetra::Details::HasDeprecatedMethods2630_WarningThisClassIsNotForUsers;
1013 return dynamic_cast<const HDM&
> (G).getGlobalNumDiagsImpl ();
1016 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1018 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1019 getNodeNumDiagsImpl ()
const {
1020 const crs_graph_type& G = this->getCrsGraphRef ();
1021 using HDM = ::Tpetra::Details::HasDeprecatedMethods2630_WarningThisClassIsNotForUsers;
1022 return dynamic_cast<const HDM&
> (G).getNodeNumDiagsImpl ();
1024 #endif // TPETRA_ENABLE_DEPRECATED_CODE
1026 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1030 return getCrsGraphRef ().getNumEntriesInGlobalRow (globalRow);
1033 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1037 return getCrsGraphRef ().getNumEntriesInLocalRow (localRow);
1040 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1044 return getCrsGraphRef ().getGlobalMaxNumRowEntries ();
1047 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1051 return getCrsGraphRef ().getNodeMaxNumRowEntries ();
1054 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1058 return getRowMap ()->getIndexBase ();
1061 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1062 Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >
1065 return getCrsGraphRef ().getRowMap ();
1068 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1069 Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >
1072 return getCrsGraphRef ().getColMap ();
1075 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1076 Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >
1079 return getCrsGraphRef ().getDomainMap ();
1082 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1083 Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >
1086 return getCrsGraphRef ().getRangeMap ();
1089 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1090 Teuchos::RCP<const RowGraph<LocalOrdinal, GlobalOrdinal, Node> >
1093 if (staticGraph_ != Teuchos::null) {
1094 return staticGraph_;
1099 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1100 Teuchos::RCP<const CrsGraph<LocalOrdinal, GlobalOrdinal, Node> >
1103 if (staticGraph_ != Teuchos::null) {
1104 return staticGraph_;
1109 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1113 if (! this->staticGraph_.is_null ()) {
1114 return * (this->staticGraph_);
1117 #ifdef HAVE_TPETRA_DEBUG
1118 const char tfecfFuncName[] =
"getCrsGraphRef: ";
1119 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1120 (this->myGraph_.is_null (), std::logic_error,
1121 "Both staticGraph_ and myGraph_ are null. "
1122 "Please report this bug to the Tpetra developers.");
1123 #endif // HAVE_TPETRA_DEBUG
1124 return * (this->myGraph_);
1128 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1129 typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_type
1133 return lclMatrix_.get () ==
nullptr ?
1135 lclMatrix_->getLocalMatrix ();
1138 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
1139 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1140 bool TPETRA_DEPRECATED
1143 return this->isLowerTriangularImpl ();
1146 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1147 bool TPETRA_DEPRECATED
1148 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1149 isUpperTriangular ()
const {
1150 return this->isUpperTriangularImpl ();
1153 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1155 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1156 isLowerTriangularImpl ()
const {
1157 const crs_graph_type& G = this->getCrsGraphRef ();
1158 using HDM = ::Tpetra::Details::HasDeprecatedMethods2630_WarningThisClassIsNotForUsers;
1159 return dynamic_cast<const HDM&
> (G).isLowerTriangularImpl ();
1162 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1164 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1165 isUpperTriangularImpl ()
const {
1166 const crs_graph_type& G = this->getCrsGraphRef ();
1167 using HDM = ::Tpetra::Details::HasDeprecatedMethods2630_WarningThisClassIsNotForUsers;
1168 return dynamic_cast<const HDM&
> (G).isUpperTriangularImpl ();
1170 #endif // TPETRA_ENABLE_DEPRECATED_CODE
1172 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1176 return myGraph_.is_null ();
1179 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1186 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1193 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1194 Teuchos::ArrayRCP<Teuchos::Array<typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::impl_scalar_type> >
1198 using Teuchos::arcp;
1199 using Teuchos::Array;
1200 using Teuchos::ArrayRCP;
1201 typedef impl_scalar_type IST;
1202 typedef LocalOrdinal LO;
1203 const char tfecfFuncName[] =
"allocateValues2D: ";
1205 const crs_graph_type& graph = this->getCrsGraphRef ();
1206 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1207 (! graph.indicesAreAllocated (), std::runtime_error,
1208 "Graph indices must be allocated before values.");
1209 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1210 (graph.getProfileType () == StaticProfile, std::runtime_error,
1211 "Graph indices must be allocated in a dynamic profile.");
1213 const LO lclNumRows = graph.getNodeNumRows ();
1214 Teuchos::ArrayRCP<Teuchos::Array<IST> > values2D (lclNumRows);
1215 if (! graph.lclInds2D_.is_null ()) {
1216 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
1217 values2D[lclRow].resize (graph.lclInds2D_[lclRow].size ());
1220 else if (! graph.gblInds2D_.is_null ()) {
1221 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
1222 values2D[lclRow].resize (graph.gblInds2D_[lclRow].size ());
1228 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1233 using ::Tpetra::Details::ProfilingRegion;
1234 const char tfecfFuncName[] =
"allocateValues: ";
1235 ProfilingRegion regionAllocateValues (
"Tpetra::CrsMatrix::allocateValues");
1237 #ifdef HAVE_TPETRA_DEBUG
1238 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1240 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1241 (this->staticGraph_.is_null (), std::logic_error,
1242 "staticGraph_ is null." << suffix);
1247 if ((gas == GraphAlreadyAllocated) != this->staticGraph_->indicesAreAllocated ()) {
1248 const char err1[] =
"The caller has asserted that the graph is ";
1249 const char err2[] =
"already allocated, but the static graph says "
1250 "that its indices are ";
1251 const char err3[] =
"already allocated. Please report this bug to "
1252 "the Tpetra developers.";
1253 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1254 (gas == GraphAlreadyAllocated && ! this->staticGraph_->indicesAreAllocated (),
1255 std::logic_error, err1 << err2 <<
"not " << err3);
1256 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1257 (gas != GraphAlreadyAllocated && this->staticGraph_->indicesAreAllocated (),
1258 std::logic_error, err1 <<
"not " << err2 << err3);
1266 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1267 (! this->staticGraph_->indicesAreAllocated () &&
1268 this->myGraph_.is_null (), std::logic_error,
1269 "The static graph says that its indices are not allocated, "
1270 "but the graph is not owned by the matrix." << suffix);
1271 #endif // HAVE_TPETRA_DEBUG
1273 if (gas == GraphNotYetAllocated) {
1274 #ifdef HAVE_TPETRA_DEBUG
1275 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1276 (this->myGraph_.is_null (), std::logic_error,
1277 "gas = GraphNotYetAllocated, but myGraph_ is null." << suffix);
1278 #endif // HAVE_TPETRA_DEBUG
1280 this->myGraph_->allocateIndices (lg);
1282 catch (std::exception& e) {
1283 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1284 (
true, std::runtime_error,
"CrsGraph::allocateIndices "
1285 "threw an exception: " << e.what ());
1288 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1289 (
true, std::runtime_error,
"CrsGraph::allocateIndices "
1290 "threw an exception not a subclass of std::exception.");
1295 if (this->getProfileType () == StaticProfile) {
1302 #ifdef HAVE_TPETRA_DEBUG
1303 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1304 (this->staticGraph_.is_null (), std::logic_error,
1305 "this->getProfileType() == StaticProfile, but staticGraph_ is null."
1307 #endif // HAVE_TPETRA_DEBUG
1309 const size_t lclNumRows = this->staticGraph_->getNodeNumRows ();
1310 typename Graph::local_graph_type::row_map_type k_ptrs =
1311 this->staticGraph_->k_rowPtrs_;
1312 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1313 (k_ptrs.extent (0) != lclNumRows+1, std::logic_error,
1314 "With StaticProfile, row offsets array has length "
1315 << k_ptrs.extent (0) <<
" != (lclNumRows+1) = "
1316 << (lclNumRows+1) <<
".");
1318 const size_t lclTotalNumEntries =
1319 ::Tpetra::Details::getEntryOnHost (k_ptrs, lclNumRows);
1322 typedef typename local_matrix_type::values_type values_type;
1324 values_type (
"Tpetra::CrsMatrix::val", lclTotalNumEntries);
1332 this->values2D_ = this->allocateValues2D ();
1336 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1339 getAllValues (Teuchos::ArrayRCP<const size_t>& rowPointers,
1340 Teuchos::ArrayRCP<const LocalOrdinal>& columnIndices,
1341 Teuchos::ArrayRCP<const Scalar>& values)
const
1344 const char tfecfFuncName[] =
"getAllValues: ";
1345 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
1346 columnIndices.size () != values.size (), std::runtime_error,
1347 "Requires that columnIndices and values are the same size.");
1349 RCP<const crs_graph_type> relevantGraph = getCrsGraph ();
1350 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
1351 relevantGraph.is_null (), std::runtime_error,
1352 "Requires that getCrsGraph() is not null.");
1354 rowPointers = relevantGraph->getNodeRowPtrs ();
1356 catch (std::exception &e) {
1357 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
1358 true, std::runtime_error,
1359 "Caught exception while calling graph->getNodeRowPtrs(): "
1363 columnIndices = relevantGraph->getNodePackedIndices ();
1365 catch (std::exception &e) {
1366 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
1367 true, std::runtime_error,
1368 "Caught exception while calling graph->getNodePackedIndices(): "
1371 Teuchos::ArrayRCP<const impl_scalar_type> vals =
1372 Kokkos::Compat::persistingView (k_values1D_);
1373 values = Teuchos::arcp_reinterpret_cast<
const Scalar> (vals);
1376 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1382 using ::Tpetra::Details::ProfilingRegion;
1383 using Kokkos::create_mirror_view;
1384 using Teuchos::arcp_const_cast;
1385 using Teuchos::Array;
1386 using Teuchos::ArrayRCP;
1387 using Teuchos::null;
1390 typedef typename local_matrix_type::row_map_type row_map_type;
1391 typedef typename Graph::local_graph_type::entries_type::non_const_type lclinds_1d_type;
1392 typedef typename local_matrix_type::values_type values_type;
1393 ProfilingRegion regionFLGAM (
"Tpetra::CrsGraph::fillLocalGraphAndMatrix");
1395 #ifdef HAVE_TPETRA_DEBUG
1396 const char tfecfFuncName[] =
"fillLocalGraphAndMatrix (called from "
1397 "fillComplete or expertStaticFillComplete): ";
1398 #endif // HAVE_TPETRA_DEBUG
1400 #ifdef HAVE_TPETRA_DEBUG
1403 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1404 (myGraph_.is_null (), std::logic_error,
"The nonconst graph (myGraph_) "
1405 "is null. This means that the matrix has a const (a.k.a. \"static\") "
1406 "graph. fillComplete or expertStaticFillComplete should never call "
1407 "fillLocalGraphAndMatrix in that case. "
1408 "Please report this bug to the Tpetra developers.");
1409 #endif // HAVE_TPETRA_DEBUG
1411 const size_t lclNumRows = this->getNodeNumRows ();
1419 typename row_map_type::non_const_type k_ptrs;
1420 row_map_type k_ptrs_const;
1421 lclinds_1d_type k_inds;
1427 lclinds_1d_type k_lclInds1D_ = myGraph_->k_lclInds1D_;
1429 typedef decltype (myGraph_->k_numRowEntries_) row_entries_type;
1431 if (getProfileType () != StaticProfile) {
1450 typename row_entries_type::const_type numRowEnt_h =
1451 myGraph_->k_numRowEntries_;
1452 #ifdef HAVE_TPETRA_DEBUG
1453 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1454 (static_cast<size_t> (numRowEnt_h.extent (0)) != lclNumRows,
1455 std::logic_error,
"(DynamicProfile branch) numRowEnt_h has the "
1456 "wrong length. numRowEnt_h.extent(0) = "
1457 << numRowEnt_h.extent (0) <<
" != getNodeNumRows() = "
1458 << lclNumRows <<
".");
1459 #endif // HAVE_TPETRA_DEBUG
1464 k_ptrs =
typename row_map_type::non_const_type (
"Tpetra::CrsGraph::ptr",
1466 typename row_map_type::non_const_type::HostMirror h_ptrs =
1467 create_mirror_view (k_ptrs);
1475 const size_t lclTotalNumEntries =
1477 #ifdef HAVE_TPETRA_DEBUG
1478 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1479 (static_cast<size_t> (h_ptrs.extent (0)) != lclNumRows + 1,
1480 std::logic_error,
"(DynamicProfile branch) After packing h_ptrs, "
1481 "h_ptrs.extent(0) = " << h_ptrs.extent (0) <<
" != "
1482 "(lclNumRows+1) = " << (lclNumRows+1) <<
".");
1484 const size_t h_ptrs_lastEnt = h_ptrs(lclNumRows);
1485 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1486 (h_ptrs_lastEnt != lclTotalNumEntries, std::logic_error,
1487 "(DynamicProfile branch) After packing h_ptrs, h_ptrs(lclNumRows="
1488 << lclNumRows <<
") = " << h_ptrs_lastEnt <<
" != total number "
1489 "of entries on the calling process = " << lclTotalNumEntries <<
".");
1491 #endif // HAVE_TPETRA_DEBUG
1494 k_inds = lclinds_1d_type (
"Tpetra::CrsGraph::ind", lclTotalNumEntries);
1495 k_vals = values_type (
"Tpetra::CrsMatrix::val", lclTotalNumEntries);
1498 typename lclinds_1d_type::HostMirror h_inds = create_mirror_view (k_inds);
1499 typename values_type::HostMirror h_vals = create_mirror_view (k_vals);
1502 ArrayRCP<Array<LocalOrdinal> > lclInds2D = myGraph_->lclInds2D_;
1503 for (
size_t row = 0; row < lclNumRows; ++row) {
1504 const size_t numEnt = numRowEnt_h(row);
1505 std::copy (lclInds2D[row].begin(),
1506 lclInds2D[row].begin() + numEnt,
1507 h_inds.data() + h_ptrs(row));
1508 std::copy (values2D_[row].begin(),
1509 values2D_[row].begin() + numEnt,
1510 h_vals.data() + h_ptrs(row));
1519 k_ptrs_const = k_ptrs;
1521 #ifdef HAVE_TPETRA_DEBUG
1523 if (k_ptrs.extent (0) != 0) {
1524 const size_t numOffsets =
static_cast<size_t> (k_ptrs.extent (0));
1525 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1526 (numOffsets != lclNumRows + 1, std::logic_error,
"(DynamicProfile "
1527 "branch) After copying into k_ptrs, k_ptrs.extent(0) = " <<
1528 numOffsets <<
" != (lclNumRows+1) = " << (lclNumRows+1) <<
".");
1530 const auto valToCheck = ::Tpetra::Details::getEntryOnHost (k_ptrs, numOffsets-1);
1531 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1532 (static_cast<size_t> (valToCheck) != k_vals.extent (0),
1533 std::logic_error,
"(DynamicProfile branch) After packing, k_ptrs("
1534 << (numOffsets-1) <<
") = " << valToCheck <<
" != "
1535 "k_vals.extent(0) = " << k_vals.extent (0) <<
".");
1536 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1537 (static_cast<size_t> (valToCheck) != k_inds.extent (0),
1538 std::logic_error,
"(DynamicProfile branch) After packing, k_ptrs("
1539 << (numOffsets-1) <<
") = " << valToCheck <<
" != "
1540 "k_inds.extent(0) = " << k_inds.extent (0) <<
".");
1542 #endif // HAVE_TPETRA_DEBUG
1544 else if (getProfileType () == StaticProfile) {
1551 typename Graph::local_graph_type::row_map_type curRowOffsets =
1552 myGraph_->k_rowPtrs_;
1554 #ifdef HAVE_TPETRA_DEBUG
1555 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1556 (curRowOffsets.extent (0) == 0, std::logic_error,
1557 "(StaticProfile branch) curRowOffsets.extent(0) == 0.");
1558 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1559 (curRowOffsets.extent (0) != lclNumRows + 1, std::logic_error,
1560 "(StaticProfile branch) curRowOffsets.extent(0) = "
1561 << curRowOffsets.extent (0) <<
" != lclNumRows + 1 = "
1562 << (lclNumRows + 1) <<
".")
1564 const size_t numOffsets = curRowOffsets.extent (0);
1565 const auto valToCheck =
1566 ::Tpetra::Details::getEntryOnHost (curRowOffsets, numOffsets - 1);
1567 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1569 myGraph_->k_lclInds1D_.extent (0) != valToCheck,
1570 std::logic_error,
"(StaticProfile branch) numOffsets = " <<
1571 numOffsets <<
" != 0 and myGraph_->k_lclInds1D_.extent(0) = "
1572 << myGraph_->k_lclInds1D_.extent (0) <<
" != curRowOffsets("
1573 << numOffsets <<
") = " << valToCheck <<
".");
1575 #endif // HAVE_TPETRA_DEBUG
1577 if (myGraph_->getNodeNumEntries () != myGraph_->getNodeAllocationSize ()) {
1584 #ifdef HAVE_TPETRA_DEBUG
1585 if (curRowOffsets.extent (0) != 0) {
1586 const size_t numOffsets =
1587 static_cast<size_t> (curRowOffsets.extent (0));
1588 const auto valToCheck =
1589 ::Tpetra::Details::getEntryOnHost (curRowOffsets, numOffsets-1);
1590 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1591 (static_cast<size_t> (valToCheck) !=
1592 static_cast<size_t> (k_values1D_.extent (0)),
1593 std::logic_error,
"(StaticProfile unpacked branch) Before "
1594 "allocating or packing, curRowOffsets(" << (numOffsets-1) <<
") = "
1595 << valToCheck <<
" != k_values1D_.extent(0)"
1596 " = " << k_values1D_.extent (0) <<
".");
1597 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1598 (static_cast<size_t> (valToCheck) !=
1599 static_cast<size_t> (myGraph_->k_lclInds1D_.extent (0)),
1600 std::logic_error,
"(StaticProfile unpacked branch) Before "
1601 "allocating or packing, curRowOffsets(" << (numOffsets-1) <<
") = "
1603 <<
" != myGraph_->k_lclInds1D_.extent(0) = "
1604 << myGraph_->k_lclInds1D_.extent (0) <<
".");
1606 #endif // HAVE_TPETRA_DEBUG
1614 size_t lclTotalNumEntries = 0;
1616 typename row_map_type::non_const_type::HostMirror h_ptrs;
1621 typename row_map_type::non_const_type
1622 packedRowOffsets (
"Tpetra::CrsGraph::ptr", lclNumRows + 1);
1623 typename row_entries_type::const_type numRowEnt_h =
1624 myGraph_->k_numRowEntries_;
1627 lclTotalNumEntries =
1631 k_ptrs = packedRowOffsets;
1632 k_ptrs_const = k_ptrs;
1635 #ifdef HAVE_TPETRA_DEBUG
1636 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1637 (static_cast<size_t> (k_ptrs.extent (0)) != lclNumRows + 1,
1639 "(StaticProfile unpacked branch) After packing k_ptrs, "
1640 "k_ptrs.extent(0) = " << k_ptrs.extent (0) <<
" != "
1641 "lclNumRows+1 = " << (lclNumRows+1) <<
".");
1643 const auto valToCheck = ::Tpetra::Details::getEntryOnHost (k_ptrs, lclNumRows);
1644 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1645 (valToCheck != lclTotalNumEntries, std::logic_error,
1646 "(StaticProfile unpacked branch) After filling k_ptrs, "
1647 "k_ptrs(lclNumRows=" << lclNumRows <<
") = " << valToCheck
1648 <<
" != total number of entries on the calling process = "
1649 << lclTotalNumEntries <<
".");
1651 #endif // HAVE_TPETRA_DEBUG
1654 k_inds = lclinds_1d_type (
"Tpetra::CrsGraph::ind", lclTotalNumEntries);
1655 k_vals = values_type (
"Tpetra::CrsMatrix::val", lclTotalNumEntries);
1667 typedef pack_functor<
typename Graph::local_graph_type::entries_type::non_const_type,
1668 typename Graph::local_graph_type::row_map_type>
1670 inds_packer_type indsPacker (k_inds, myGraph_->k_lclInds1D_,
1671 k_ptrs, curRowOffsets);
1673 typedef Kokkos::RangePolicy<exec_space, LocalOrdinal> range_type;
1674 Kokkos::parallel_for (range_type (0, lclNumRows), indsPacker);
1678 typedef pack_functor<values_type, row_map_type> vals_packer_type;
1679 vals_packer_type valsPacker (k_vals, this->k_values1D_,
1680 k_ptrs, curRowOffsets);
1681 Kokkos::parallel_for (range_type (0, lclNumRows), valsPacker);
1683 #ifdef HAVE_TPETRA_DEBUG
1684 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1685 (k_ptrs.extent (0) == 0, std::logic_error,
1686 "(StaticProfile \"Optimize Storage\" = "
1687 "true branch) After packing, k_ptrs.extent(0) = 0. This "
1688 "probably means that k_rowPtrs_ was never allocated.");
1689 if (k_ptrs.extent (0) != 0) {
1690 const size_t numOffsets =
static_cast<size_t> (k_ptrs.extent (0));
1691 const auto valToCheck = ::Tpetra::Details::getEntryOnHost (k_ptrs, numOffsets - 1);
1692 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1693 (static_cast<size_t> (valToCheck) != k_vals.extent (0),
1695 "(StaticProfile \"Optimize Storage\"=true branch) After packing, "
1696 "k_ptrs(" << (numOffsets-1) <<
") = " << valToCheck <<
1697 " != k_vals.extent(0) = " << k_vals.extent (0) <<
".");
1698 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1699 (static_cast<size_t> (valToCheck) != k_inds.extent (0),
1701 "(StaticProfile \"Optimize Storage\"=true branch) After packing, "
1702 "k_ptrs(" << (numOffsets-1) <<
") = " << valToCheck <<
1703 " != k_inds.extent(0) = " << k_inds.extent (0) <<
".");
1705 #endif // HAVE_TPETRA_DEBUG
1708 k_ptrs_const = myGraph_->k_rowPtrs_;
1709 k_inds = myGraph_->k_lclInds1D_;
1710 k_vals = this->k_values1D_;
1712 #ifdef HAVE_TPETRA_DEBUG
1713 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1714 (k_ptrs_const.extent (0) == 0, std::logic_error,
1715 "(StaticProfile \"Optimize Storage\"=false branch) "
1716 "k_ptrs_const.extent(0) = 0. This probably means that "
1717 "k_rowPtrs_ was never allocated.");
1718 if (k_ptrs_const.extent (0) != 0) {
1719 const size_t numOffsets =
static_cast<size_t> (k_ptrs_const.extent (0));
1720 const auto valToCheck = ::Tpetra::Details::getEntryOnHost (k_ptrs_const, numOffsets - 1);
1721 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1722 (static_cast<size_t> (valToCheck) != k_vals.extent (0),
1724 "(StaticProfile \"Optimize Storage\"=false branch) "
1725 "k_ptrs_const(" << (numOffsets-1) <<
") = " << valToCheck
1726 <<
" != k_vals.extent(0) = " << k_vals.extent (0) <<
".");
1727 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1728 (static_cast<size_t> (valToCheck) != k_inds.extent (0),
1730 "(StaticProfile \"Optimize Storage\" = false branch) "
1731 "k_ptrs_const(" << (numOffsets-1) <<
") = " << valToCheck
1732 <<
" != k_inds.extent(0) = " << k_inds.extent (0) <<
".");
1734 #endif // HAVE_TPETRA_DEBUG
1738 #ifdef HAVE_TPETRA_DEBUG
1740 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1741 (static_cast<size_t> (k_ptrs_const.extent (0)) != lclNumRows + 1,
1742 std::logic_error,
"After packing, k_ptrs_const.extent(0) = " <<
1743 k_ptrs_const.extent (0) <<
" != lclNumRows+1 = " << (lclNumRows+1)
1745 if (k_ptrs_const.extent (0) != 0) {
1746 const size_t numOffsets =
static_cast<size_t> (k_ptrs_const.extent (0));
1747 const size_t k_ptrs_const_numOffsetsMinus1 =
1748 ::Tpetra::Details::getEntryOnHost (k_ptrs_const, numOffsets - 1);
1749 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1750 (k_ptrs_const_numOffsetsMinus1 != k_vals.extent (0),
1751 std::logic_error,
"After packing, k_ptrs_const(" << (numOffsets-1) <<
1752 ") = " << k_ptrs_const_numOffsetsMinus1 <<
" != k_vals.extent(0)"
1753 " = " << k_vals.extent (0) <<
".");
1754 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1755 (k_ptrs_const_numOffsetsMinus1 != k_inds.extent (0),
1756 std::logic_error,
"After packing, k_ptrs_const(" << (numOffsets-1) <<
1757 ") = " << k_ptrs_const_numOffsetsMinus1 <<
" != k_inds.extent(0)"
1758 " = " << k_inds.extent (0) <<
".");
1760 #endif // HAVE_TPETRA_DEBUG
1766 const bool defaultOptStorage =
1767 ! isStaticGraph () || staticGraph_->isStorageOptimized ();
1768 const bool requestOptimizedStorage =
1769 (! params.is_null () && params->get (
"Optimize Storage", defaultOptStorage)) ||
1770 (params.is_null () && defaultOptStorage);
1777 if (requestOptimizedStorage) {
1783 myGraph_->lclInds2D_ = null;
1784 myGraph_->k_numRowEntries_ = row_entries_type ();
1787 this->values2D_ = null;
1790 myGraph_->k_rowPtrs_ = k_ptrs_const;
1791 myGraph_->k_lclInds1D_ = k_inds;
1792 this->k_values1D_ = k_vals;
1795 myGraph_->pftype_ = StaticProfile;
1796 myGraph_->storageStatus_ = ::Tpetra::Details::STORAGE_1D_PACKED;
1797 this->storageStatus_ = ::Tpetra::Details::STORAGE_1D_PACKED;
1808 myGraph_->lclGraph_ =
1812 auto lclMat = std::make_shared<local_matrix_type>
1813 (
"Tpetra::CrsMatrix::lclMatrix_", getNodeNumCols (),
1814 k_vals, myGraph_->lclGraph_);
1815 lclMatrix_ = std::make_shared<local_multiply_op_type> (lclMat);
1818 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1823 using ::Tpetra::Details::ProfilingRegion;
1824 using Kokkos::create_mirror_view;
1825 using Teuchos::ArrayRCP;
1826 using Teuchos::Array;
1827 using Teuchos::null;
1830 typedef LocalOrdinal LO;
1831 typedef typename Graph::local_graph_type::row_map_type row_map_type;
1832 typedef typename row_map_type::non_const_type non_const_row_map_type;
1833 typedef typename local_matrix_type::values_type values_type;
1834 #ifdef HAVE_TPETRA_DEBUG
1835 const char tfecfFuncName[] =
"fillLocalMatrix (called from fillComplete): ";
1836 #endif // HAVE_TPETRA_DEBUG
1837 ProfilingRegion regionFLM (
"Tpetra::CrsMatrix::fillLocalMatrix");
1839 const size_t lclNumRows = getNodeNumRows();
1850 ArrayRCP<Array<LO> > lclInds2D = staticGraph_->lclInds2D_;
1851 size_t nodeNumEntries = staticGraph_->getNodeNumEntries ();
1852 size_t nodeNumAllocated = staticGraph_->getNodeAllocationSize ();
1853 row_map_type k_rowPtrs_ = staticGraph_->lclGraph_.row_map;
1855 row_map_type k_ptrs;
1861 bool requestOptimizedStorage =
true;
1862 const bool default_OptimizeStorage =
1863 ! isStaticGraph () || staticGraph_->isStorageOptimized ();
1864 if (! params.is_null () && ! params->get (
"Optimize Storage", default_OptimizeStorage)) {
1865 requestOptimizedStorage =
false;
1872 if (! staticGraph_->isStorageOptimized () && requestOptimizedStorage) {
1874 "You requested optimized storage by setting the"
1875 "\"Optimize Storage\" flag to \"true\" in the parameter list, or by virtue"
1876 "of default behavior. However, the associated CrsGraph was filled separately"
1877 "and requested not to optimize storage. Therefore, the CrsMatrix cannot"
1878 "optimize storage.");
1879 requestOptimizedStorage =
false;
1882 typedef decltype (staticGraph_->k_numRowEntries_) row_entries_type;
1884 if (getProfileType() != StaticProfile) {
1907 size_t lclTotalNumEntries = 0;
1909 typename non_const_row_map_type::HostMirror h_ptrs;
1911 typename row_entries_type::const_type numRowEnt_h =
1912 staticGraph_->k_numRowEntries_;
1914 non_const_row_map_type packedRowOffsets (
"Tpetra::CrsGraph::ptr",
1918 h_ptrs = create_mirror_view (packedRowOffsets);
1922 k_ptrs = packedRowOffsets;
1925 #ifdef HAVE_TPETRA_DEBUG
1926 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1927 (static_cast<size_t> (k_ptrs.extent (0)) != lclNumRows + 1,
1928 std::logic_error,
"In DynamicProfile branch, after packing k_ptrs, "
1929 "k_ptrs.extent(0) = " << k_ptrs.extent (0) <<
" != "
1930 "(lclNumRows+1) = " << (lclNumRows+1) <<
".");
1931 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1932 (static_cast<size_t> (h_ptrs.extent (0)) != lclNumRows + 1,
1933 std::logic_error,
"In DynamicProfile branch, after packing h_ptrs, "
1934 "h_ptrs.extent(0) = " << h_ptrs.extent (0) <<
" != "
1935 "(lclNumRows+1) = " << (lclNumRows+1) <<
".");
1937 const auto valToCheck = ::Tpetra::Details::getEntryOnHost (k_ptrs, lclNumRows);
1938 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1939 (static_cast<size_t> (valToCheck) != lclTotalNumEntries,
1940 std::logic_error,
"(DynamicProfile branch) After packing k_ptrs, "
1941 "k_ptrs(lclNumRows = " << lclNumRows <<
") = " << valToCheck
1942 <<
" != total number of entries on the calling process = "
1943 << lclTotalNumEntries <<
".");
1945 #endif // HAVE_TPETRA_DEBUG
1948 k_vals = values_type (
"Tpetra::CrsMatrix::val", lclTotalNumEntries);
1950 typename values_type::HostMirror h_vals = create_mirror_view (k_vals);
1952 for (
size_t lclRow = 0; lclRow < lclNumRows; ++lclRow) {
1953 const size_t numEnt = numRowEnt_h(lclRow);
1954 std::copy (values2D_[lclRow].begin(),
1955 values2D_[lclRow].begin() + numEnt,
1956 h_vals.data() + h_ptrs(lclRow));
1961 #ifdef HAVE_TPETRA_DEBUG
1963 if (k_ptrs.extent (0) != 0) {
1964 const size_t numOffsets =
static_cast<size_t> (k_ptrs.extent (0));
1965 const auto valToCheck =
1966 ::Tpetra::Details::getEntryOnHost (k_ptrs, numOffsets - 1);
1967 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1968 (static_cast<size_t> (valToCheck) != k_vals.extent (0),
1969 std::logic_error,
"(DynamicProfile branch) After packing, k_ptrs("
1970 << (numOffsets-1) <<
") = " << valToCheck <<
" != "
1971 "k_vals.extent(0) = " << k_vals.extent (0) <<
".");
1973 #endif // HAVE_TPETRA_DEBUG
1975 else if (getProfileType () == StaticProfile) {
1993 if (nodeNumEntries != nodeNumAllocated) {
1996 non_const_row_map_type tmpk_ptrs (
"Tpetra::CrsGraph::ptr",
2001 size_t lclTotalNumEntries = 0;
2004 typename row_entries_type::const_type numRowEnt_d =
2005 staticGraph_->k_numRowEntries_;
2013 k_vals = values_type (
"Tpetra::CrsMatrix::val", lclTotalNumEntries);
2016 typedef pack_functor<values_type, row_map_type> packer_type;
2017 packer_type valsPacker (k_vals, k_values1D_, tmpk_ptrs, k_rowPtrs_);
2020 typedef Kokkos::RangePolicy<exec_space, LocalOrdinal> range_type;
2021 Kokkos::parallel_for (range_type (0, lclNumRows), valsPacker);
2024 k_vals = k_values1D_;
2029 if (requestOptimizedStorage) {
2033 k_values1D_ = k_vals;
2034 this->storageStatus_ = ::Tpetra::Details::STORAGE_1D_PACKED;
2041 auto lclMat = std::make_shared<local_matrix_type>
2042 (
"Tpetra::CrsMatrix::lclMatrix_",
2043 getColMap ()->getNodeNumElements (),
2044 k_vals, staticGraph_->getLocalGraph ());
2045 lclMatrix_ = std::make_shared<local_multiply_op_type> (lclMat);
2048 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2053 const typename crs_graph_type::SLocalGlobalViews& newInds,
2054 const Teuchos::ArrayView<impl_scalar_type>& oldRowVals,
2055 const Teuchos::ArrayView<const impl_scalar_type>& newRowVals,
2056 const ELocalGlobal lg,
2057 const ELocalGlobal I)
2059 const size_t oldNumEnt = rowInfo.numEntries;
2060 const size_t numInserted = graph.insertIndices (rowInfo, newInds, lg, I);
2066 if (numInserted > 0) {
2067 const size_t startOffset = oldNumEnt;
2068 memcpy (&oldRowVals[startOffset], &newRowVals[0],
2069 numInserted *
sizeof (impl_scalar_type));
2073 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2077 const Teuchos::ArrayView<const LocalOrdinal>& indices,
2078 const Teuchos::ArrayView<const Scalar>& values)
2082 const char tfecfFuncName[] =
"insertLocalValues: ";
2084 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2085 (! this->isFillActive (), std::runtime_error,
2086 "Fill is not active. After calling fillComplete, you must call "
2087 "resumeFill before you may insert entries into the matrix again.");
2088 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2089 (this->isStaticGraph (), std::runtime_error,
2090 "Cannot insert indices with static graph; use replaceLocalValues() "
2094 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2095 (graph.
colMap_.is_null (), std::runtime_error,
2096 "Cannot insert local indices without a column map.");
2097 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2099 std::runtime_error,
"Graph indices are global; use "
2100 "insertGlobalValues().");
2101 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2102 (values.size () != indices.size (), std::runtime_error,
2103 "values.size() = " << values.size ()
2104 <<
" != indices.size() = " << indices.size () <<
".");
2105 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
2106 ! graph.
rowMap_->isNodeLocalElement (lclRow), std::runtime_error,
2107 "Local row index " << lclRow <<
" does not belong to this process.");
2109 if (! graph.indicesAreAllocated ()) {
2110 this->allocateValues (LocalIndices, GraphNotYetAllocated);
2113 const size_t numEntriesToAdd =
static_cast<size_t> (indices.size ());
2114 #ifdef HAVE_TPETRA_DEBUG
2119 using Teuchos::toString;
2122 Teuchos::Array<LocalOrdinal> badColInds;
2123 bool allInColMap =
true;
2124 for (
size_t k = 0; k < numEntriesToAdd; ++k) {
2126 allInColMap =
false;
2127 badColInds.push_back (indices[k]);
2130 if (! allInColMap) {
2131 std::ostringstream os;
2132 os <<
"You attempted to insert entries in owned row " << lclRow
2133 <<
", at the following column indices: " << toString (indices)
2135 os <<
"Of those, the following indices are not in the column Map on "
2136 "this process: " << toString (badColInds) <<
"." << endl <<
"Since "
2137 "the matrix has a column Map already, it is invalid to insert "
2138 "entries at those locations.";
2139 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2140 (
true, std::invalid_argument, os.str ());
2143 #endif // HAVE_TPETRA_DEBUG
2147 if (this->getProfileType() == StaticProfile)
2149 Teuchos::ArrayView<IST> valsView = this->getViewNonConst(rowInfo);
2150 auto fun = [&](
size_t const k,
size_t const ,
size_t const offset) {
2151 valsView[offset] += values[k]; };
2152 std::function<void(size_t const, size_t const, size_t const)> cb(std::ref(fun));
2153 graph.insertLocalIndicesImpl(lclRow, indices, cb);
2158 const size_t curNumEnt = rowInfo.numEntries;
2159 const size_t newNumEnt = curNumEnt + numEntriesToAdd;
2160 if (newNumEnt > rowInfo.allocSize) {
2162 Teuchos::Array<IST>& curVals = this->values2D_[lclRow];
2166 graph.
lclInds2D_[rowInfo.localRow].resize (newNumEnt);
2167 curVals.resize (newNumEnt);
2168 rowInfo.allocSize = newNumEnt;
2170 typename crs_graph_type::SLocalGlobalViews indsView;
2171 indsView.linds = indices;
2173 Teuchos::ArrayView<IST> valsView = this->getViewNonConst (rowInfo);
2174 Teuchos::ArrayView<const IST> valsIn =
2175 Teuchos::av_reinterpret_cast<
const IST> (values);
2176 this->insertIndicesAndValues (graph, rowInfo, indsView, valsView,
2177 valsIn, LocalIndices, LocalIndices);
2178 #ifdef HAVE_TPETRA_DEBUG
2180 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2181 (chkNewNumEnt != newNumEnt, std::logic_error,
2182 "The row should have " << newNumEnt <<
" entries after insert, but "
2183 "instead has " << chkNewNumEnt <<
". Please report this bug to "
2184 "the Tpetra developers.");
2185 #endif // HAVE_TPETRA_DEBUG
2189 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2193 const LocalOrdinal numEnt,
2194 const Scalar vals[],
2195 const LocalOrdinal cols[])
2197 Teuchos::ArrayView<const LocalOrdinal> colsT (cols, numEnt);
2198 Teuchos::ArrayView<const Scalar> valsT (vals, numEnt);
2199 this->insertLocalValues (localRow, colsT, valsT);
2202 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2207 const GlobalOrdinal gblColInds[],
2208 const impl_scalar_type vals[],
2209 const size_t numInputEnt)
2211 typedef impl_scalar_type IST;
2212 typedef GlobalOrdinal GO;
2213 #ifdef HAVE_TPETRA_DEBUG
2214 const char tfecfFuncName[] =
"insertGlobalValuesImpl: ";
2216 #endif // HAVE_TPETRA_DEBUG
2218 size_t newNumEnt = 0;
2219 const size_t curNumEnt = rowInfo.numEntries;
2221 if (! graph.indicesAreAllocated ()) {
2222 this->allocateValues (GlobalIndices, GraphNotYetAllocated);
2227 rowInfo = graph.getRowInfo (rowInfo.localRow);
2230 if (this->getProfileType () == StaticProfile) {
2231 Teuchos::ArrayView<IST> valsView = this->getViewNonConst(rowInfo);
2232 auto fun = [&](
size_t const k,
size_t const ,
size_t const offset) {
2233 valsView[offset] += vals[k];
2235 std::function<void(size_t const, size_t const, size_t const)> cb(std::ref(fun));
2237 graph.insertGlobalIndicesImpl(rowInfo, gblColInds, numInputEnt, cb);
2238 newNumEnt = curNumEnt + numInserted;
2242 newNumEnt = curNumEnt + numInputEnt;
2243 if (newNumEnt > rowInfo.allocSize) {
2246 Teuchos::Array<IST>& curVals = this->values2D_[rowInfo.localRow];
2249 graph.gblInds2D_[rowInfo.localRow].resize (newNumEnt);
2250 curVals.resize (newNumEnt);
2251 rowInfo.allocSize = newNumEnt;
2254 using Teuchos::ArrayView;
2255 typename crs_graph_type::SLocalGlobalViews inputIndsAV;
2256 inputIndsAV.ginds = ArrayView<const GO> (gblColInds, numInputEnt);
2257 ArrayView<IST> curValsAV = this->getViewNonConst (rowInfo);
2258 ArrayView<const IST> inputValsAV (vals, numInputEnt);
2260 const ELocalGlobal curIndexingStatus =
2261 this->isGloballyIndexed () ? GlobalIndices : LocalIndices;
2267 this->insertIndicesAndValues (graph, rowInfo, inputIndsAV, curValsAV,
2268 inputValsAV, GlobalIndices,
2272 #ifdef HAVE_TPETRA_DEBUG
2273 const size_t chkNewNumEnt =
2274 graph.getNumEntriesInLocalRow (rowInfo.localRow);
2275 if (chkNewNumEnt != newNumEnt) {
2276 std::ostringstream os;
2277 os << std::endl <<
"newNumEnt = " << newNumEnt
2278 <<
" != graph.getNumEntriesInLocalRow(" << rowInfo.localRow
2279 <<
") = " << chkNewNumEnt <<
"." << std::endl
2280 <<
"\torigNumEnt: " << origNumEnt << std::endl
2281 <<
"\tnumInputEnt: " << numInputEnt << std::endl
2282 <<
"\tgblColInds: [";
2283 for (
size_t k = 0; k < numInputEnt; ++k) {
2284 os << gblColInds[k];
2285 if (k +
size_t (1) < numInputEnt) {
2289 os <<
"]" << std::endl
2291 for (
size_t k = 0; k < numInputEnt; ++k) {
2293 if (k +
size_t (1) < numInputEnt) {
2297 os <<
"]" << std::endl;
2299 if (this->supportsRowViews ()) {
2300 Teuchos::ArrayView<const Scalar> vals2;
2301 if (this->isGloballyIndexed ()) {
2302 Teuchos::ArrayView<const GlobalOrdinal> gblColInds2;
2303 const GlobalOrdinal gblRow =
2304 graph.rowMap_->getGlobalElement (rowInfo.localRow);
2305 if (gblRow == Tpetra::Details::OrdinalTraits<GlobalOrdinal>::invalid ()) {
2306 os <<
"Local row index " << rowInfo.localRow <<
" is invalid!" << std::endl;
2309 bool getViewThrew =
false;
2311 this->getGlobalRowView (gblRow, gblColInds2, vals2);
2313 catch (std::exception& e) {
2314 getViewThrew =
true;
2315 os <<
"getGlobalRowView threw exception:" << std::endl
2316 << e.what () << std::endl;
2318 if (! getViewThrew) {
2319 os <<
"\tNew global column indices: "
2320 << Teuchos::toString (gblColInds2) << std::endl
2321 <<
"\tNew values: " << Teuchos::toString (vals2) << std::endl;
2325 else if (this->isLocallyIndexed ()) {
2326 Teuchos::ArrayView<const LocalOrdinal> lclColInds2;
2327 this->getLocalRowView (rowInfo.localRow, lclColInds2, vals2);
2328 os <<
"\tNew local column indices: " << Teuchos::toString (lclColInds2)
2330 os <<
"\tNew values: " << Teuchos::toString (vals2) << std::endl;
2334 os <<
"Please report this bug to the Tpetra developers.";
2335 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2336 (
true, std::logic_error, os.str ());
2338 #endif // HAVE_TPETRA_DEBUG
2341 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2345 const Teuchos::ArrayView<const GlobalOrdinal>& indices,
2346 const Teuchos::ArrayView<const Scalar>& values)
2348 using Teuchos::toString;
2351 typedef LocalOrdinal LO;
2352 typedef GlobalOrdinal GO;
2353 typedef Tpetra::Details::OrdinalTraits<LO> OTLO;
2354 typedef typename Teuchos::ArrayView<const GO>::size_type size_type;
2355 const char tfecfFuncName[] =
"insertGlobalValues: ";
2357 #ifdef HAVE_TPETRA_DEBUG
2358 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2359 (values.size () != indices.size (), std::runtime_error,
2360 "values.size() = " << values.size () <<
" != indices.size() = "
2361 << indices.size () <<
".");
2362 #endif // HAVE_TPETRA_DEBUG
2366 const map_type& rowMap = * (this->getCrsGraphRef ().rowMap_);
2369 if (lclRow == OTLO::invalid ()) {
2376 this->insertNonownedGlobalValues (gblRow, indices, values);
2379 if (this->isStaticGraph ()) {
2381 const int myRank = rowMap.getComm ()->getRank ();
2382 const int numProcs = rowMap.getComm ()->getSize ();
2383 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2384 (
true, std::runtime_error,
2385 "The matrix was constructed with a constant (\"static\") graph, "
2386 "yet the given global row index " << gblRow <<
" is in the row "
2387 "Map on the calling process (with rank " << myRank <<
", of " <<
2388 numProcs <<
" process(es)). In this case, you may not insert "
2389 "new entries into rows owned by the calling process.");
2393 const IST*
const inputVals =
2394 reinterpret_cast<const IST*
> (values.getRawPtr ());
2395 const GO*
const inputGblColInds = indices.getRawPtr ();
2396 const size_t numInputEnt = indices.size ();
2405 if (! graph.
colMap_.is_null ()) {
2411 #ifdef HAVE_TPETRA_DEBUG
2412 Teuchos::Array<GO> badColInds;
2413 #endif // HAVE_TPETRA_DEBUG
2414 const size_type numEntriesToInsert = indices.size ();
2415 bool allInColMap =
true;
2416 for (size_type k = 0; k < numEntriesToInsert; ++k) {
2418 allInColMap =
false;
2419 #ifdef HAVE_TPETRA_DEBUG
2420 badColInds.push_back (indices[k]);
2423 #endif // HAVE_TPETRA_DEBUG
2426 if (! allInColMap) {
2427 std::ostringstream os;
2428 os <<
"You attempted to insert entries in owned row " << gblRow
2429 <<
", at the following column indices: " << toString (indices)
2431 #ifdef HAVE_TPETRA_DEBUG
2432 os <<
"Of those, the following indices are not in the column Map "
2433 "on this process: " << toString (badColInds) <<
"." << endl
2434 <<
"Since the matrix has a column Map already, it is invalid "
2435 "to insert entries at those locations.";
2437 os <<
"At least one of those indices is not in the column Map "
2438 "on this process." << endl <<
"It is invalid to insert into "
2439 "columns not in the column Map on the process that owns the "
2441 #endif // HAVE_TPETRA_DEBUG
2442 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2443 (
true, std::invalid_argument, os.str ());
2447 this->insertGlobalValuesImpl (graph, rowInfo, inputGblColInds,
2448 inputVals, numInputEnt);
2453 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2457 const LocalOrdinal numEnt,
2458 const Scalar vals[],
2459 const GlobalOrdinal inds[])
2461 Teuchos::ArrayView<const GlobalOrdinal> indsT (inds, numEnt);
2462 Teuchos::ArrayView<const Scalar> valsT (vals, numEnt);
2463 this->insertGlobalValues (globalRow, indsT, valsT);
2467 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2471 const Teuchos::ArrayView<const GlobalOrdinal>& indices,
2472 const Teuchos::ArrayView<const Scalar>& values)
2474 typedef impl_scalar_type IST;
2475 typedef LocalOrdinal LO;
2476 typedef GlobalOrdinal GO;
2477 typedef Tpetra::Details::OrdinalTraits<LO> OTLO;
2478 const char tfecfFuncName[] =
"insertGlobalValuesFiltered: ";
2480 #ifdef HAVE_TPETRA_DEBUG
2481 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2482 (values.size () != indices.size (), std::runtime_error,
2483 "values.size() = " << values.size () <<
" != indices.size() = "
2484 << indices.size () <<
".");
2485 #endif // HAVE_TPETRA_DEBUG
2489 const map_type& rowMap = * (this->getCrsGraphRef ().rowMap_);
2490 const LO lclRow = rowMap.getLocalElement (gblRow);
2491 if (lclRow == OTLO::invalid ()) {
2498 this->insertNonownedGlobalValues (gblRow, indices, values);
2501 if (this->isStaticGraph ()) {
2503 const int myRank = rowMap.getComm ()->getRank ();
2504 const int numProcs = rowMap.getComm ()->getSize ();
2505 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2506 (
true, std::runtime_error,
2507 "The matrix was constructed with a constant (\"static\") graph, "
2508 "yet the given global row index " << gblRow <<
" is in the row "
2509 "Map on the calling process (with rank " << myRank <<
", of " <<
2510 numProcs <<
" process(es)). In this case, you may not insert "
2511 "new entries into rows owned by the calling process.");
2514 crs_graph_type& graph = * (this->myGraph_);
2515 const IST*
const inputVals =
2516 reinterpret_cast<const IST*
> (values.getRawPtr ());
2517 const GO*
const inputGblColInds = indices.getRawPtr ();
2518 const size_t numInputEnt = indices.size ();
2519 RowInfo rowInfo = graph.getRowInfo (lclRow);
2521 if (!graph.colMap_.is_null() &&
2522 graph.isLocallyIndexed() &&
2523 this->getProfileType() == StaticProfile) {
2530 const map_type& colMap = * (graph.colMap_);
2531 size_t curOffset = 0;
2532 while (curOffset < numInputEnt) {
2536 Teuchos::Array<LO> lclIndices;
2537 size_t endOffset = curOffset;
2538 for ( ; endOffset < numInputEnt; ++endOffset) {
2539 auto lclIndex = colMap.getLocalElement(inputGblColInds[endOffset]);
2540 if (lclIndex != OTLO::invalid())
2541 lclIndices.push_back(lclIndex);
2548 const LO numIndInSeq = (endOffset - curOffset);
2549 if (numIndInSeq != 0) {
2550 this->insertLocalValues(lclRow, lclIndices(), values(curOffset, numIndInSeq));
2555 #ifdef HAVE_TPETRA_DEBUG
2556 const bool invariant = endOffset == numInputEnt ||
2557 colMap.getLocalElement (inputGblColInds[endOffset]) == OTLO::invalid ();
2558 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2559 (! invariant, std::logic_error, std::endl <<
"Invariant failed!");
2560 #endif // HAVE_TPETRA_DEBUG
2561 curOffset = endOffset + 1;
2564 else if (! graph.colMap_.is_null ()) {
2565 const map_type& colMap = * (graph.colMap_);
2566 size_t curOffset = 0;
2567 while (curOffset < numInputEnt) {
2571 size_t endOffset = curOffset;
2572 for ( ; endOffset < numInputEnt &&
2573 colMap.getLocalElement (inputGblColInds[endOffset]) != OTLO::invalid ();
2579 const LO numIndInSeq = (endOffset - curOffset);
2580 if (numIndInSeq != 0) {
2581 rowInfo = graph.getRowInfo(lclRow);
2582 this->insertGlobalValuesImpl (graph, rowInfo,
2583 inputGblColInds + curOffset,
2584 inputVals + curOffset,
2590 #ifdef HAVE_TPETRA_DEBUG
2591 const bool invariant = endOffset == numInputEnt ||
2592 colMap.getLocalElement (inputGblColInds[endOffset]) == OTLO::invalid ();
2593 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
2594 (! invariant, std::logic_error, std::endl <<
"Invariant failed!");
2595 #endif // HAVE_TPETRA_DEBUG
2596 curOffset = endOffset + 1;
2600 this->insertGlobalValuesImpl (graph, rowInfo, inputGblColInds,
2601 inputVals, numInputEnt);
2606 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2608 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
2609 replaceLocalValuesImpl (impl_scalar_type rowVals[],
2610 const crs_graph_type& graph,
2611 const RowInfo& rowInfo,
2612 const LocalOrdinal inds[],
2613 const impl_scalar_type newVals[],
2614 const LocalOrdinal numElts)
const
2616 typedef LocalOrdinal LO;
2617 typedef GlobalOrdinal GO;
2618 const bool sorted = graph.isSorted ();
2627 if (graph.isLocallyIndexed ()) {
2630 auto colInds = graph.getLocalKokkosRowView (rowInfo);
2632 for (LO j = 0; j < numElts; ++j) {
2633 const LO lclColInd = inds[j];
2634 const size_t offset =
2635 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2636 lclColInd, hint, sorted);
2637 if (offset != rowInfo.numEntries) {
2638 rowVals[offset] = newVals[j];
2644 else if (graph.isGloballyIndexed ()) {
2645 if (graph.colMap_.is_null ()) {
2646 return Teuchos::OrdinalTraits<LO>::invalid ();
2648 const map_type colMap = * (graph.colMap_);
2652 auto colInds = graph.getGlobalKokkosRowView (rowInfo);
2654 for (LO j = 0; j < numElts; ++j) {
2655 const GO gblColInd = colMap.getGlobalElement (inds[j]);
2656 if (gblColInd != Teuchos::OrdinalTraits<GO>::invalid ()) {
2657 const size_t offset =
2658 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2659 gblColInd, hint, sorted);
2660 if (offset != rowInfo.numEntries) {
2661 rowVals[offset] = newVals[j];
2680 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2684 const Teuchos::ArrayView<const LocalOrdinal>& lclCols,
2685 const Teuchos::ArrayView<const Scalar>& vals)
const
2687 typedef LocalOrdinal LO;
2689 const LO numInputEnt =
static_cast<LO
> (lclCols.size ());
2690 if (static_cast<LO> (vals.size ()) != numInputEnt) {
2691 return Teuchos::OrdinalTraits<LO>::invalid ();
2693 const LO*
const inputInds = lclCols.getRawPtr ();
2694 const Scalar*
const inputVals = vals.getRawPtr ();
2695 return this->replaceLocalValues (localRow, numInputEnt,
2696 inputVals, inputInds);
2699 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2703 const LocalOrdinal numEnt,
2704 const Scalar inputVals[],
2705 const LocalOrdinal inputCols[])
const
2708 typedef LocalOrdinal LO;
2710 if (! this->isFillActive () || this->staticGraph_.is_null ()) {
2712 return Teuchos::OrdinalTraits<LO>::invalid ();
2717 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2720 return static_cast<LO
> (0);
2722 auto curRowVals = this->getRowViewNonConst (rowInfo);
2723 const IST*
const inVals =
reinterpret_cast<const IST*
> (inputVals);
2724 return this->replaceLocalValuesImpl (curRowVals.data (), graph, rowInfo,
2725 inputCols, inVals, numEnt);
2728 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2732 const crs_graph_type& graph,
2734 const GlobalOrdinal inds[],
2735 const impl_scalar_type newVals[],
2736 const LocalOrdinal numElts)
const
2738 if (graph.getProfileType() == StaticProfile)
2740 Teuchos::ArrayView<const GlobalOrdinal> indsT(inds, numElts);
2742 [&](
size_t const k,
size_t const ,
size_t const offset) {
2743 rowVals[offset] = newVals[k];
2745 std::function<void(size_t const, size_t const, size_t const)> cb(std::ref(fun));
2746 return graph.findGlobalIndices(rowInfo, indsT, cb);
2751 typedef LocalOrdinal LO;
2752 typedef GlobalOrdinal GO;
2754 const bool sorted = graph.isSorted ();
2763 if (graph.isLocallyIndexed ()) {
2767 if (graph.colMap_.is_null ()) {
2773 const map_type& colMap = * (graph.colMap_);
2777 auto colInds = graph.getLocalKokkosRowView (rowInfo);
2778 const LO LINV = Teuchos::OrdinalTraits<LO>::invalid ();
2779 for (LO j = 0; j < numElts; ++j) {
2780 const LO lclColInd = colMap.getLocalElement (inds[j]);
2781 if (lclColInd != LINV) {
2782 const size_t offset =
2783 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2784 lclColInd, hint, sorted);
2785 if (offset != rowInfo.numEntries) {
2786 rowVals[offset] = newVals[j];
2793 else if (graph.isGloballyIndexed ()) {
2796 auto colInds = graph.getGlobalKokkosRowView (rowInfo);
2798 for (LO j = 0; j < numElts; ++j) {
2799 const GO gblColInd = inds[j];
2800 const size_t offset =
2801 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2802 gblColInd, hint, sorted);
2803 if (offset != rowInfo.numEntries) {
2804 rowVals[offset] = newVals[j];
2817 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2821 const Teuchos::ArrayView<const GlobalOrdinal>& inputGblColInds,
2822 const Teuchos::ArrayView<const Scalar>& inputVals)
const
2824 typedef LocalOrdinal LO;
2826 const LO numInputEnt =
static_cast<LO
> (inputGblColInds.size ());
2827 if (static_cast<LO> (inputVals.size ()) != numInputEnt) {
2828 return Teuchos::OrdinalTraits<LO>::invalid ();
2830 return this->replaceGlobalValues (globalRow, numInputEnt,
2831 inputVals.getRawPtr (),
2832 inputGblColInds.getRawPtr ());
2835 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2839 const LocalOrdinal numEnt,
2840 const Scalar inputVals[],
2841 const GlobalOrdinal inputGblColInds[])
const
2844 typedef LocalOrdinal LO;
2846 if (! this->isFillActive () || this->staticGraph_.is_null ()) {
2848 return Teuchos::OrdinalTraits<LO>::invalid ();
2853 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2856 return static_cast<LO
> (0);
2859 auto curRowVals = this->getRowViewNonConst (rowInfo);
2860 const IST*
const inVals =
reinterpret_cast<const IST*
> (inputVals);
2861 return this->replaceGlobalValuesImpl (curRowVals.data (), graph, rowInfo,
2862 inputGblColInds, inVals, numEnt);
2865 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2869 const crs_graph_type& graph,
2871 const GlobalOrdinal inds[],
2872 const impl_scalar_type newVals[],
2873 const LocalOrdinal numElts,
2874 const bool atomic)
const
2876 typedef LocalOrdinal LO;
2877 typedef GlobalOrdinal GO;
2879 const bool sorted = graph.isSorted ();
2888 if (graph.isLocallyIndexed ()) {
2892 if (graph.colMap_.is_null ()) {
2898 const map_type& colMap = * (graph.colMap_);
2902 auto colInds = graph.getLocalKokkosRowView (rowInfo);
2903 const LO LINV = Teuchos::OrdinalTraits<LO>::invalid ();
2905 for (LO j = 0; j < numElts; ++j) {
2906 const LO lclColInd = colMap.getLocalElement (inds[j]);
2907 if (lclColInd != LINV) {
2908 const size_t offset =
2909 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2910 lclColInd, hint, sorted);
2911 if (offset != rowInfo.numEntries) {
2913 Kokkos::atomic_add (&rowVals[offset], newVals[j]);
2916 rowVals[offset] += newVals[j];
2924 else if (graph.isGloballyIndexed ()) {
2927 auto colInds = graph.getGlobalKokkosRowView (rowInfo);
2929 for (LO j = 0; j < numElts; ++j) {
2930 const GO gblColInd = inds[j];
2931 const size_t offset =
2932 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
2933 gblColInd, hint, sorted);
2934 if (offset != rowInfo.numEntries) {
2936 Kokkos::atomic_add (&rowVals[offset], newVals[j]);
2939 rowVals[offset] += newVals[j];
2953 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2957 const Teuchos::ArrayView<const GlobalOrdinal>& inputGblColInds,
2958 const Teuchos::ArrayView<const Scalar>& inputVals,
2961 typedef LocalOrdinal LO;
2963 const LO numInputEnt =
static_cast<LO
> (inputGblColInds.size ());
2964 if (static_cast<LO> (inputVals.size ()) != numInputEnt) {
2965 return Teuchos::OrdinalTraits<LO>::invalid ();
2967 return this->sumIntoGlobalValues (gblRow, numInputEnt,
2968 inputVals.getRawPtr (),
2969 inputGblColInds.getRawPtr (),
2973 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2977 const LocalOrdinal numInputEnt,
2978 const Scalar inputVals[],
2979 const GlobalOrdinal inputGblColInds[],
2983 typedef LocalOrdinal LO;
2984 typedef GlobalOrdinal GO;
2986 if (! this->isFillActive () || this->staticGraph_.is_null ()) {
2988 return Teuchos::OrdinalTraits<LO>::invalid ();
2993 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
2998 using Teuchos::ArrayView;
2999 ArrayView<const GO> inputGblColInds_av (numInputEnt == 0 ? NULL :
3000 inputGblColInds, numInputEnt);
3001 ArrayView<const Scalar> inputVals_av (numInputEnt == 0 ? NULL :
3002 inputVals, numInputEnt);
3007 this->insertNonownedGlobalValues (gblRow, inputGblColInds_av,
3018 auto curRowVals = this->getRowViewNonConst (rowInfo);
3019 const IST*
const inVals =
reinterpret_cast<const IST*
> (inputVals);
3020 return this->sumIntoGlobalValuesImpl (curRowVals.data (), graph, rowInfo,
3021 inputGblColInds, inVals,
3022 numInputEnt, atomic);
3026 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3030 const LocalOrdinal numInputEnt,
3031 const impl_scalar_type inputVals[],
3032 const LocalOrdinal inputCols[],
3033 std::function<impl_scalar_type (
const impl_scalar_type&,
const impl_scalar_type&) > f,
3034 const bool atomic)
const
3036 using Tpetra::Details::OrdinalTraits;
3037 typedef LocalOrdinal LO;
3039 if (! this->isFillActive () || this->staticGraph_.is_null ()) {
3041 return Teuchos::OrdinalTraits<LO>::invalid ();
3043 const crs_graph_type& graph = * (this->staticGraph_);
3044 const RowInfo rowInfo = graph.getRowInfo (lclRow);
3046 if (rowInfo.localRow == OrdinalTraits<size_t>::invalid ()) {
3049 return static_cast<LO
> (0);
3051 auto curRowVals = this->getRowViewNonConst (rowInfo);
3052 return this->transformLocalValues (curRowVals.data (), graph,
3053 rowInfo, inputCols, inputVals,
3054 numInputEnt, f, atomic);
3057 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3059 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
3060 transformGlobalValues (
const GlobalOrdinal gblRow,
3061 const LocalOrdinal numInputEnt,
3062 const impl_scalar_type inputVals[],
3063 const GlobalOrdinal inputCols[],
3064 std::function<impl_scalar_type (
const impl_scalar_type&,
const impl_scalar_type&) > f,
3065 const bool atomic)
const
3067 using Tpetra::Details::OrdinalTraits;
3068 typedef LocalOrdinal LO;
3070 if (! this->isFillActive () || this->staticGraph_.is_null ()) {
3072 return OrdinalTraits<LO>::invalid ();
3074 const crs_graph_type& graph = * (this->staticGraph_);
3075 const RowInfo rowInfo = graph.getRowInfoFromGlobalRowIndex (gblRow);
3077 if (rowInfo.localRow == OrdinalTraits<size_t>::invalid ()) {
3080 return static_cast<LO
> (0);
3082 auto curRowVals = this->getRowViewNonConst (rowInfo);
3083 return this->transformGlobalValues (curRowVals.data (), graph,
3084 rowInfo, inputCols, inputVals,
3085 numInputEnt, f, atomic);
3088 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3090 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
3091 transformLocalValues (impl_scalar_type rowVals[],
3092 const crs_graph_type& graph,
3093 const RowInfo& rowInfo,
3094 const LocalOrdinal inds[],
3095 const impl_scalar_type newVals[],
3096 const LocalOrdinal numElts,
3097 std::function<impl_scalar_type (
const impl_scalar_type&,
const impl_scalar_type&) > f,
3098 const bool atomic)
const
3100 typedef impl_scalar_type ST;
3101 typedef LocalOrdinal LO;
3102 typedef GlobalOrdinal GO;
3109 const bool sorted = graph.isSorted ();
3114 if (graph.isLocallyIndexed ()) {
3117 auto colInds = graph.getLocalKokkosRowView (rowInfo);
3119 for (LO j = 0; j < numElts; ++j) {
3120 const LO lclColInd = inds[j];
3121 const size_t offset =
3122 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
3123 lclColInd, hint, sorted);
3124 if (offset != rowInfo.numEntries) {
3133 volatile ST*
const dest = &rowVals[offset];
3134 (void) atomic_binary_function_update (dest, newVals[j], f);
3138 rowVals[offset] = f (rowVals[offset], newVals[j]);
3145 else if (graph.isGloballyIndexed ()) {
3149 if (graph.colMap_.is_null ()) {
3156 const map_type& colMap = * (graph.colMap_);
3159 auto colInds = graph.getGlobalKokkosRowView (rowInfo);
3161 const GO GINV = Teuchos::OrdinalTraits<GO>::invalid ();
3162 for (LO j = 0; j < numElts; ++j) {
3163 const GO gblColInd = colMap.getGlobalElement (inds[j]);
3164 if (gblColInd != GINV) {
3165 const size_t offset =
3166 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
3167 gblColInd, hint, sorted);
3168 if (offset != rowInfo.numEntries) {
3177 volatile ST*
const dest = &rowVals[offset];
3178 (void) atomic_binary_function_update (dest, newVals[j], f);
3182 rowVals[offset] = f (rowVals[offset], newVals[j]);
3197 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3199 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
3200 transformGlobalValues (impl_scalar_type rowVals[],
3201 const crs_graph_type& graph,
3202 const RowInfo& rowInfo,
3203 const GlobalOrdinal inds[],
3204 const impl_scalar_type newVals[],
3205 const LocalOrdinal numElts,
3206 std::function<impl_scalar_type (
const impl_scalar_type&,
const impl_scalar_type&) > f,
3207 const bool atomic)
const
3209 typedef impl_scalar_type ST;
3210 typedef LocalOrdinal LO;
3211 typedef GlobalOrdinal GO;
3218 const bool sorted = graph.isSorted ();
3223 if (graph.isGloballyIndexed ()) {
3226 auto colInds = graph.getGlobalKokkosRowView (rowInfo);
3228 for (LO j = 0; j < numElts; ++j) {
3229 const GO gblColInd = inds[j];
3230 const size_t offset =
3231 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
3232 gblColInd, hint, sorted);
3233 if (offset != rowInfo.numEntries) {
3242 volatile ST*
const dest = &rowVals[offset];
3243 (void) atomic_binary_function_update (dest, newVals[j], f);
3247 rowVals[offset] = f (rowVals[offset], newVals[j]);
3254 else if (graph.isLocallyIndexed ()) {
3258 if (graph.colMap_.is_null ()) {
3264 const map_type& colMap = * (graph.colMap_);
3267 auto colInds = graph.getLocalKokkosRowView (rowInfo);
3269 const LO LINV = Teuchos::OrdinalTraits<LO>::invalid ();
3270 for (LO j = 0; j < numElts; ++j) {
3271 const LO lclColInd = colMap.getLocalElement (inds[j]);
3272 if (lclColInd != LINV) {
3273 const size_t offset =
3274 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
3275 lclColInd, hint, sorted);
3276 if (offset != rowInfo.numEntries) {
3285 volatile ST*
const dest = &rowVals[offset];
3286 (void) atomic_binary_function_update (dest, newVals[j], f);
3290 rowVals[offset] = f (rowVals[offset], newVals[j]);
3305 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3307 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
3308 sumIntoLocalValuesImpl (impl_scalar_type rowVals[],
3309 const crs_graph_type& graph,
3310 const RowInfo& rowInfo,
3311 const LocalOrdinal inds[],
3312 const impl_scalar_type newVals[],
3313 const LocalOrdinal numElts,
3314 const bool atomic)
const
3316 typedef LocalOrdinal LO;
3317 typedef GlobalOrdinal GO;
3319 const bool sorted = graph.isSorted ();
3328 if (graph.isLocallyIndexed ()) {
3331 auto colInds = graph.getLocalKokkosRowView (rowInfo);
3333 for (LO j = 0; j < numElts; ++j) {
3334 const LO lclColInd = inds[j];
3335 const size_t offset =
3336 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
3337 lclColInd, hint, sorted);
3338 if (offset != rowInfo.numEntries) {
3340 Kokkos::atomic_add (&rowVals[offset], newVals[j]);
3343 rowVals[offset] += newVals[j];
3350 else if (graph.isGloballyIndexed ()) {
3351 if (graph.colMap_.is_null ()) {
3352 return Teuchos::OrdinalTraits<LO>::invalid ();
3354 const map_type colMap = * (graph.colMap_);
3358 auto colInds = graph.getGlobalKokkosRowView (rowInfo);
3360 for (LO j = 0; j < numElts; ++j) {
3361 const GO gblColInd = colMap.getGlobalElement (inds[j]);
3362 if (gblColInd != Teuchos::OrdinalTraits<GO>::invalid ()) {
3363 const size_t offset =
3364 KokkosSparse::findRelOffset (colInds, rowInfo.numEntries,
3365 gblColInd, hint, sorted);
3366 if (offset != rowInfo.numEntries) {
3368 Kokkos::atomic_add (&rowVals[offset], newVals[j]);
3371 rowVals[offset] += newVals[j];
3391 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3395 const Teuchos::ArrayView<const LocalOrdinal>& indices,
3396 const Teuchos::ArrayView<const Scalar>& values,
3397 const bool atomic)
const
3399 typedef LocalOrdinal LO;
3401 const LO numInputEnt =
static_cast<LO
> (indices.size ());
3402 if (static_cast<LO> (values.size ()) != numInputEnt) {
3403 return Teuchos::OrdinalTraits<LO>::invalid ();
3405 const LO*
const inputInds = indices.getRawPtr ();
3406 const Scalar*
const inputVals = values.getRawPtr ();
3407 return this->sumIntoLocalValues (localRow, numInputEnt,
3408 inputVals, inputInds, atomic);
3411 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3415 const LocalOrdinal numEnt,
3416 const Scalar vals[],
3417 const LocalOrdinal cols[],
3418 const bool atomic)
const
3421 typedef LocalOrdinal LO;
3423 if (! this->isFillActive () || this->staticGraph_.is_null ()) {
3425 return Teuchos::OrdinalTraits<LO>::invalid ();
3430 if (rowInfo.localRow == Teuchos::OrdinalTraits<size_t>::invalid ()) {
3433 return static_cast<LO
> (0);
3435 auto curRowVals = this->getRowViewNonConst (rowInfo);
3436 const IST*
const inputVals =
reinterpret_cast<const IST*
> (vals);
3437 return this->sumIntoLocalValuesImpl (curRowVals.data (), graph, rowInfo,
3438 cols, inputVals, numEnt, atomic);
3441 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3442 Teuchos::ArrayView<const typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::impl_scalar_type>
3446 using Kokkos::MemoryUnmanaged;
3448 using Teuchos::ArrayView;
3450 typedef std::pair<size_t, size_t> range_type;
3452 if (k_values1D_.extent (0) != 0 && rowinfo.allocSize > 0) {
3453 #ifdef HAVE_TPETRA_DEBUG
3454 TEUCHOS_TEST_FOR_EXCEPTION(
3455 rowinfo.offset1D + rowinfo.allocSize > k_values1D_.extent (0),
3456 std::range_error,
"Tpetra::CrsMatrix::getView: Invalid access "
3457 "to 1-D storage of values." << std::endl <<
"rowinfo.offset1D (" <<
3458 rowinfo.offset1D <<
") + rowinfo.allocSize (" << rowinfo.allocSize <<
3459 ") > k_values1D_.extent(0) (" << k_values1D_.extent (0) <<
").");
3460 #endif // HAVE_TPETRA_DEBUG
3461 range_type range (rowinfo.offset1D, rowinfo.offset1D + rowinfo.allocSize);
3462 typedef View<const ST*, execution_space, MemoryUnmanaged> subview_type;
3469 subview_type sv = Kokkos::subview (subview_type (k_values1D_), range);
3470 const ST*
const sv_raw = (rowinfo.allocSize == 0) ? NULL : sv.data ();
3471 return ArrayView<const ST> (sv_raw, rowinfo.allocSize);
3473 else if (values2D_ != Teuchos::null) {
3474 return values2D_[rowinfo.localRow] ();
3477 return ArrayView<impl_scalar_type> ();
3482 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3486 LocalOrdinal& numEnt,
3489 if (k_values1D_.extent (0) != 0 && rowinfo.allocSize > 0) {
3490 #ifdef HAVE_TPETRA_DEBUG
3491 if (rowinfo.offset1D + rowinfo.allocSize > k_values1D_.extent (0)) {
3494 return Teuchos::OrdinalTraits<LocalOrdinal>::invalid ();
3496 #endif // HAVE_TPETRA_DEBUG
3497 vals = k_values1D_.data () + rowinfo.offset1D;
3498 numEnt = rowinfo.allocSize;
3500 else if (! values2D_.is_null ()) {
3501 #ifdef HAVE_TPETRA_DEBUG
3502 if (rowinfo.localRow >= static_cast<size_t> (values2D_.size ())) {
3505 return Teuchos::OrdinalTraits<LocalOrdinal>::invalid ();
3507 #endif // HAVE_TPETRA_DEBUG
3510 const auto& curRow = values2D_[rowinfo.localRow];
3511 vals = curRow.getRawPtr ();
3512 numEnt = curRow.size ();
3519 return static_cast<LocalOrdinal
> (0);
3522 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3526 LocalOrdinal& numEnt,
3530 const LocalOrdinal err = this->getViewRawConst (valsConst, numEnt, rowinfo);
3535 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3536 Kokkos::View<const typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::impl_scalar_type*,
3538 Kokkos::MemoryUnmanaged>
3542 using Kokkos::MemoryUnmanaged;
3544 typedef impl_scalar_type ST;
3545 typedef View<const ST*, execution_space, MemoryUnmanaged> subview_type;
3546 typedef std::pair<size_t, size_t> range_type;
3548 if (k_values1D_.extent (0) != 0 && rowInfo.allocSize > 0) {
3549 #ifdef HAVE_TPETRA_DEBUG
3550 TEUCHOS_TEST_FOR_EXCEPTION
3551 (rowInfo.offset1D + rowInfo.allocSize > this->k_values1D_.extent (0),
3552 std::range_error,
"Tpetra::CrsMatrix::getRowView: Invalid access "
3553 "to 1-D storage of values. rowInfo.offset1D ("
3554 << rowInfo.offset1D <<
") + rowInfo.allocSize (" << rowInfo.allocSize
3555 <<
") > this->k_values1D_.extent(0) ("
3556 << this->k_values1D_.extent (0) <<
").");
3557 #endif // HAVE_TPETRA_DEBUG
3558 range_type range (rowInfo.offset1D, rowInfo.offset1D + rowInfo.allocSize);
3565 return Kokkos::subview (subview_type (this->k_values1D_), range);
3567 else if (this->values2D_ != Teuchos::null) {
3571 auto& rowView = this->values2D_[rowInfo.localRow];
3572 return subview_type (rowView.getRawPtr (), rowView.size ());
3575 return subview_type ();
3579 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3580 Kokkos::View<typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::impl_scalar_type*,
3581 typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::execution_space,
3582 Kokkos::MemoryUnmanaged>
3583 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
3584 getRowViewNonConst (
const RowInfo& rowInfo)
const
3586 using Kokkos::MemoryUnmanaged;
3588 typedef impl_scalar_type ST;
3589 typedef View<ST*, execution_space, MemoryUnmanaged> subview_type;
3590 typedef std::pair<size_t, size_t> range_type;
3592 if (k_values1D_.extent (0) != 0 && rowInfo.allocSize > 0) {
3593 #ifdef HAVE_TPETRA_DEBUG
3594 TEUCHOS_TEST_FOR_EXCEPTION
3595 (rowInfo.offset1D + rowInfo.allocSize > this->k_values1D_.extent (0),
3596 std::range_error,
"Tpetra::CrsMatrix::getRowViewNonConst: Invalid "
3597 "access to 1-D storage of values. rowInfo.offset1D ("
3598 << rowInfo.offset1D <<
") + rowInfo.allocSize (" << rowInfo.allocSize
3599 <<
") > this->k_values1D_.extent(0) ("
3600 << this->k_values1D_.extent (0) <<
").");
3601 #endif // HAVE_TPETRA_DEBUG
3602 range_type range (rowInfo.offset1D, rowInfo.offset1D + rowInfo.allocSize);
3609 return Kokkos::subview (subview_type (this->k_values1D_), range);
3611 else if (this->values2D_ != Teuchos::null) {
3615 auto& rowView = this->values2D_[rowInfo.localRow];
3616 return subview_type (rowView.getRawPtr (), rowView.size ());
3619 return subview_type ();
3623 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3624 Teuchos::ArrayView<typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::impl_scalar_type>
3631 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3635 const Teuchos::ArrayView<LocalOrdinal>& indices,
3636 const Teuchos::ArrayView<Scalar>& values,
3637 size_t& numEntries)
const
3639 using Teuchos::ArrayView;
3640 using Teuchos::av_reinterpret_cast;
3641 const char tfecfFuncName[] =
"getLocalRowCopy: ";
3643 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3644 (! this->hasColMap (), std::runtime_error,
3645 "The matrix does not have a column Map yet. This means we don't have "
3646 "local indices for columns yet, so it doesn't make sense to call this "
3647 "method. If the matrix doesn't have a column Map yet, you should call "
3648 "fillComplete on it first.");
3650 const RowInfo rowinfo = staticGraph_->getRowInfo (localRow);
3651 const size_t theNumEntries = rowinfo.numEntries;
3652 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3653 (static_cast<size_t> (indices.size ()) < theNumEntries ||
3654 static_cast<size_t> (values.size ()) < theNumEntries,
3655 std::runtime_error,
"Row with local index " << localRow <<
" has " <<
3656 theNumEntries <<
" entry/ies, but indices.size() = " <<
3657 indices.size () <<
" and values.size() = " << values.size () <<
".");
3658 numEntries = theNumEntries;
3660 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
3661 if (staticGraph_->isLocallyIndexed ()) {
3662 const LocalOrdinal* curLclInds;
3664 LocalOrdinal numSpots;
3669 #ifdef HAVE_TPETRA_DEBUG
3671 staticGraph_->getLocalViewRawConst (curLclInds, numSpots, rowinfo);
3672 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3673 (err != static_cast<LocalOrdinal> (0), std::logic_error,
3674 "staticGraph_->getLocalViewRawConst returned nonzero error code "
3676 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3677 (static_cast<size_t> (numSpots) < theNumEntries, std::logic_error,
3678 "numSpots = " << numSpots <<
" < theNumEntries = " << theNumEntries
3680 const LocalOrdinal numSpotsBefore = numSpots;
3681 err = getViewRawConst (curVals, numSpots, rowinfo);
3682 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3683 (err != static_cast<LocalOrdinal> (0), std::logic_error,
3684 "getViewRaw returned nonzero error code " << err <<
".");
3685 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3686 (numSpotsBefore != numSpots, std::logic_error,
3687 "numSpotsBefore = " << numSpotsBefore <<
" != numSpots = "
3688 << numSpots <<
".");
3690 (void) staticGraph_->getLocalViewRawConst (curLclInds, numSpots, rowinfo);
3691 (void) getViewRawConst (curVals, numSpots, rowinfo);
3692 #endif // HAVE_TPETRA_DEBUG
3694 for (
size_t j = 0; j < theNumEntries; ++j) {
3695 values[j] = curVals[j];
3696 indices[j] = curLclInds[j];
3699 else if (staticGraph_->isGloballyIndexed ()) {
3701 const map_type& colMap = * (staticGraph_->colMap_);
3702 const GlobalOrdinal* curGblInds;
3704 LocalOrdinal numSpots;
3709 #ifdef HAVE_TPETRA_DEBUG
3711 staticGraph_->getGlobalViewRawConst (curGblInds, numSpots, rowinfo);
3712 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3713 (err != static_cast<LocalOrdinal> (0), std::logic_error,
3714 "staticGraph_->getGlobalViewRawConst returned nonzero error code "
3716 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3717 (static_cast<size_t> (numSpots) < theNumEntries, std::logic_error,
3718 "numSpots = " << numSpots <<
" < theNumEntries = " << theNumEntries
3720 const LocalOrdinal numSpotsBefore = numSpots;
3721 err = getViewRawConst (curVals, numSpots, rowinfo);
3722 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3723 (err != static_cast<LocalOrdinal> (0), std::logic_error,
3724 "getViewRawConst returned nonzero error code " << err <<
".");
3725 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3726 (numSpotsBefore != numSpots, std::logic_error,
3727 "numSpotsBefore = " << numSpotsBefore <<
" != numSpots = "
3728 << numSpots <<
".");
3730 (void) staticGraph_->getGlobalViewRawConst (curGblInds, numSpots, rowinfo);
3731 (void) getViewRawConst (curVals, numSpots, rowinfo);
3732 #endif //HAVE_TPETRA_DEBUG
3734 for (
size_t j = 0; j < theNumEntries; ++j) {
3735 values[j] = curVals[j];
3742 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3746 const Teuchos::ArrayView<GlobalOrdinal>& indices,
3747 const Teuchos::ArrayView<Scalar>& values,
3748 size_t& numEntries)
const
3750 using Teuchos::ArrayView;
3751 using Teuchos::av_reinterpret_cast;
3752 const char tfecfFuncName[] =
"getGlobalRowCopy: ";
3755 staticGraph_->getRowInfoFromGlobalRowIndex (globalRow);
3756 const size_t theNumEntries = rowinfo.numEntries;
3757 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3758 static_cast<size_t> (indices.size ()) < theNumEntries ||
3759 static_cast<size_t> (values.size ()) < theNumEntries,
3760 std::runtime_error,
"Row with global index " << globalRow <<
" has "
3761 << theNumEntries <<
" entry/ies, but indices.size() = " <<
3762 indices.size () <<
" and values.size() = " << values.size () <<
".");
3763 numEntries = theNumEntries;
3765 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid ()) {
3766 if (staticGraph_->isLocallyIndexed ()) {
3767 const map_type& colMap = * (staticGraph_->colMap_);
3768 const LocalOrdinal* curLclInds;
3770 LocalOrdinal numSpots;
3775 #ifdef HAVE_TPETRA_DEBUG
3777 staticGraph_->getLocalViewRawConst (curLclInds, numSpots, rowinfo);
3778 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3779 (err != static_cast<LocalOrdinal> (0), std::logic_error,
3780 "staticGraph_->getLocalViewRawConst returned nonzero error code "
3782 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3783 (static_cast<size_t> (numSpots) < theNumEntries, std::logic_error,
3784 "numSpots = " << numSpots <<
" < theNumEntries = " << theNumEntries
3786 const LocalOrdinal numSpotsBefore = numSpots;
3787 err = getViewRawConst (curVals, numSpots, rowinfo);
3788 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3789 (err != static_cast<LocalOrdinal> (0), std::logic_error,
3790 "getViewRaw returned nonzero error code " << err <<
".");
3791 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3792 (numSpotsBefore != numSpots, std::logic_error,
3793 "numSpotsBefore = " << numSpotsBefore <<
" != numSpots = "
3794 << numSpots <<
".");
3796 (void) staticGraph_->getLocalViewRawConst (curLclInds, numSpots, rowinfo);
3797 (void) getViewRawConst (curVals, numSpots, rowinfo);
3798 #endif //HAVE_TPETRA_DEBUG
3800 for (
size_t j = 0; j < theNumEntries; ++j) {
3801 values[j] = curVals[j];
3805 else if (staticGraph_->isGloballyIndexed ()) {
3806 const GlobalOrdinal* curGblInds;
3808 LocalOrdinal numSpots;
3813 #ifdef HAVE_TPETRA_DEBUG
3815 staticGraph_->getGlobalViewRawConst (curGblInds, numSpots, rowinfo);
3816 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3817 (err != static_cast<LocalOrdinal> (0), std::logic_error,
3818 "staticGraph_->getGlobalViewRawConst returned nonzero error code "
3820 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3821 (static_cast<size_t> (numSpots) < theNumEntries, std::logic_error,
3822 "numSpots = " << numSpots <<
" < theNumEntries = " << theNumEntries
3824 const LocalOrdinal numSpotsBefore = numSpots;
3825 err = getViewRawConst (curVals, numSpots, rowinfo);
3826 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3827 (err != static_cast<LocalOrdinal> (0), std::logic_error,
3828 "getViewRawConst returned nonzero error code " << err <<
".");
3829 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3830 (numSpotsBefore != numSpots, std::logic_error,
3831 "numSpotsBefore = " << numSpotsBefore <<
" != numSpots = "
3832 << numSpots <<
".");
3834 (void) staticGraph_->getGlobalViewRawConst (curGblInds, numSpots, rowinfo);
3835 (void) getViewRawConst (curVals, numSpots, rowinfo);
3836 #endif //HAVE_TPETRA_DEBUG
3838 for (
size_t j = 0; j < theNumEntries; ++j) {
3839 values[j] = curVals[j];
3840 indices[j] = curGblInds[j];
3846 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3850 Teuchos::ArrayView<const LocalOrdinal>& indices,
3851 Teuchos::ArrayView<const Scalar>& values)
const
3853 using Teuchos::ArrayView;
3854 using Teuchos::av_reinterpret_cast;
3855 typedef LocalOrdinal LO;
3856 const char tfecfFuncName[] =
"getLocalRowView: ";
3858 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3859 isGloballyIndexed (), std::runtime_error,
"The matrix currently stores "
3860 "its indices as global indices, so you cannot get a view with local "
3861 "column indices. If the matrix has a column Map, you may call "
3862 "getLocalRowCopy() to get local column indices; otherwise, you may get "
3863 "a view with global column indices by calling getGlobalRowCopy().");
3864 indices = Teuchos::null;
3865 values = Teuchos::null;
3866 const RowInfo rowinfo = staticGraph_->getRowInfo (localRow);
3867 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
3868 rowinfo.numEntries > 0) {
3869 ArrayView<const LO> indTmp = staticGraph_->getLocalView (rowinfo);
3870 ArrayView<const Scalar> valTmp =
3871 av_reinterpret_cast<
const Scalar> (this->getView (rowinfo));
3872 indices = indTmp (0, rowinfo.numEntries);
3873 values = valTmp (0, rowinfo.numEntries);
3876 #ifdef HAVE_TPETRA_DEBUG
3877 const char suffix[] =
". This should never happen. Please report this "
3878 "bug to the Tpetra developers.";
3879 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3880 (static_cast<size_t> (indices.size ()) !=
3881 static_cast<size_t> (values.size ()), std::logic_error,
3882 "At the end of this method, for local row " << localRow <<
", "
3883 "indices.size() = " << indices.size () <<
" != values.size () = "
3884 << values.size () << suffix);
3885 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3886 (static_cast<size_t> (indices.size ()) !=
3887 static_cast<size_t> (rowinfo.numEntries), std::logic_error,
3888 "At the end of this method, for local row " << localRow <<
", "
3889 "indices.size() = " << indices.size () <<
" != rowinfo.numEntries = "
3890 << rowinfo.numEntries << suffix);
3891 const size_t expectedNumEntries = getNumEntriesInLocalRow (localRow);
3892 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3893 (rowinfo.numEntries != expectedNumEntries, std::logic_error,
"At the end "
3894 "of this method, for local row " << localRow <<
", rowinfo.numEntries = "
3895 << rowinfo.numEntries <<
" != getNumEntriesInLocalRow(localRow) = " <<
3896 expectedNumEntries << suffix);
3897 #endif // HAVE_TPETRA_DEBUG
3900 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3904 LocalOrdinal& numEnt,
3906 const LocalOrdinal*& ind)
const
3908 typedef LocalOrdinal LO;
3915 if (staticGraph_.is_null () || staticGraph_->isGloballyIndexed ()) {
3916 return Tpetra::Details::OrdinalTraits<LO>::invalid ();
3919 const RowInfo rowInfo = staticGraph_->getRowInfo (lclRow);
3920 if (rowInfo.localRow == Tpetra::Details::OrdinalTraits<size_t>::invalid ()) {
3925 return static_cast<LO
> (1);
3928 numEnt =
static_cast<LO
> (rowInfo.numEntries);
3929 auto lclColInds = staticGraph_->getLocalKokkosRowView (rowInfo);
3930 ind = lclColInds.data ();
3931 const LO err = this->getViewRawConst (val, numEnt, rowInfo);
3937 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3941 LocalOrdinal& numEnt,
3942 const LocalOrdinal*& lclColInds,
3943 const Scalar*& vals)
const
3946 const LocalOrdinal errCode =
3947 this->getLocalRowView (lclRow, numEnt, vals_ist, lclColInds);
3948 vals =
reinterpret_cast<const Scalar*
> (vals_ist);
3952 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
3956 Teuchos::ArrayView<const GlobalOrdinal>& indices,
3957 Teuchos::ArrayView<const Scalar>& values)
const
3959 using Teuchos::ArrayView;
3960 using Teuchos::av_reinterpret_cast;
3961 typedef GlobalOrdinal GO;
3962 const char tfecfFuncName[] =
"getGlobalRowView: ";
3964 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
3965 isLocallyIndexed (), std::runtime_error,
3966 "The matrix is locally indexed, so we cannot return a view of the row "
3967 "with global column indices. Use getGlobalRowCopy() instead.");
3968 indices = Teuchos::null;
3969 values = Teuchos::null;
3971 staticGraph_->getRowInfoFromGlobalRowIndex (globalRow);
3972 if (rowinfo.localRow != Teuchos::OrdinalTraits<size_t>::invalid () &&
3973 rowinfo.numEntries > 0) {
3974 ArrayView<const GO> indTmp = staticGraph_->getGlobalView (rowinfo);
3975 ArrayView<const Scalar> valTmp =
3976 av_reinterpret_cast<
const Scalar> (this->getView (rowinfo));
3977 #ifdef HAVE_TPETRA_DEBUG
3978 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3979 (static_cast<size_t> (indTmp.size ()) < rowinfo.numEntries ||
3980 static_cast<size_t> (valTmp.size ()) < rowinfo.numEntries,
3981 std::logic_error, std::endl <<
"rowinfo.numEntries not accurate. "
3982 << std::endl <<
"indTmp.size() = " << indTmp.size ()
3983 <<
", valTmp.size() = " << valTmp.size ()
3984 <<
", rowinfo.numEntries = " << rowinfo.numEntries <<
".");
3985 #endif // HAVE_TPETRA_DEBUG
3986 indices = indTmp (0, rowinfo.numEntries);
3987 values = valTmp (0, rowinfo.numEntries);
3990 #ifdef HAVE_TPETRA_DEBUG
3991 const char suffix[] =
". This should never happen. Please report this "
3992 "bug to the Tpetra developers.";
3993 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
3994 (static_cast<size_t> (indices.size ()) !=
3995 static_cast<size_t> (values.size ()), std::logic_error,
3996 "At the end of this method, for global row " << globalRow <<
", "
3997 "indices.size() = " << indices.size () <<
" != values.size () = "
3998 << values.size () << suffix);
3999 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4000 (static_cast<size_t> (indices.size ()) !=
4001 static_cast<size_t> (rowinfo.numEntries), std::logic_error,
4002 "At the end of this method, for global row " << globalRow <<
", "
4003 "indices.size() = " << indices.size () <<
" != rowinfo.numEntries = "
4004 << rowinfo.numEntries << suffix);
4005 const size_t expectedNumEntries = getNumEntriesInGlobalRow (globalRow);
4006 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4007 (rowinfo.numEntries != expectedNumEntries, std::logic_error,
"At the end "
4008 "of this method, for global row " << globalRow <<
", rowinfo.numEntries "
4009 "= " << rowinfo.numEntries <<
" != getNumEntriesInGlobalRow(globalRow) ="
4010 " " << expectedNumEntries << suffix);
4011 #endif // HAVE_TPETRA_DEBUG
4014 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4019 typedef LocalOrdinal LO;
4020 typedef typename Teuchos::Array<Scalar>::size_type size_type;
4021 const char tfecfFuncName[] =
"scale: ";
4024 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4025 ! isFillActive (), std::runtime_error,
4026 "Fill must be active before you may call this method. "
4027 "Please call resumeFill() to make fill active.");
4029 const size_t nlrs = staticGraph_->getNodeNumRows ();
4030 const size_t numEntries = staticGraph_->getNodeNumEntries ();
4031 if (! staticGraph_->indicesAreAllocated () ||
4032 nlrs == 0 || numEntries == 0) {
4036 auto lclMat = this->getLocalMatrix ();
4038 if (staticGraph_->getProfileType () == StaticProfile) {
4039 const LO lclNumRows = lclMat.numRows ();
4040 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
4041 auto row_i = lclMat.row (lclRow);
4042 for (LO k = 0; k < row_i.length; ++k) {
4044 row_i.value (k) *= theAlpha;
4048 else if (staticGraph_->getProfileType () != StaticProfile) {
4049 for (
size_t row = 0; row < nlrs; ++row) {
4050 const size_type numEnt = getNumEntriesInLocalRow (row);
4051 Teuchos::ArrayView<impl_scalar_type> rowVals = values2D_[row] ();
4052 for (size_type k = 0; k < numEnt; ++k) {
4053 rowVals[k] *= theAlpha;
4060 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4065 const char tfecfFuncName[] =
"setAllToScalar: ";
4067 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4068 ! isFillActive (), std::runtime_error,
4069 "Fill must be active before you may call this method. "
4070 "Please call resumeFill() to make fill active.");
4076 const size_t nlrs = staticGraph_->getNodeNumRows();
4077 const size_t numEntries = staticGraph_->getNodeNumEntries();
4078 if (! staticGraph_->indicesAreAllocated () || numEntries == 0) {
4082 const ProfileType profType = staticGraph_->getProfileType ();
4083 if (profType == StaticProfile) {
4089 else if (profType != StaticProfile) {
4090 for (
size_t row = 0; row < nlrs; ++row) {
4091 std::fill (values2D_[row].begin (), values2D_[row].end (), theAlpha);
4097 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4101 const typename local_graph_type::entries_type::non_const_type& columnIndices,
4102 const typename local_matrix_type::values_type& values)
4104 const char tfecfFuncName[] =
"setAllValues: ";
4105 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4106 (columnIndices.size () != values.size (), std::invalid_argument,
4107 "columnIndices.size() = " << columnIndices.size () <<
" != values.size()"
4108 " = " << values.size () <<
".");
4109 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4110 (myGraph_.is_null (), std::runtime_error,
"myGraph_ must not be null.");
4113 myGraph_->setAllIndices (rowPointers, columnIndices);
4115 catch (std::exception &e) {
4116 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4117 (
true, std::runtime_error,
"myGraph_->setAllIndices() threw an "
4118 "exception: " << e.what ());
4124 auto lclGraph = myGraph_->getLocalGraph ();
4125 const size_t numEnt = lclGraph.entries.extent (0);
4126 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4127 (lclGraph.row_map.extent (0) != rowPointers.extent (0) ||
4128 numEnt !=
static_cast<size_t> (columnIndices.extent (0)),
4129 std::logic_error,
"myGraph_->setAllIndices() did not correctly create "
4130 "local graph. Please report this bug to the Tpetra developers.");
4132 const size_t numCols = myGraph_->getColMap ()->getNodeNumElements ();
4134 auto lclMat = std::make_shared<local_matrix_type>
4135 (
"Tpetra::CrsMatrix::lclMatrix_", numCols, values, lclGraph);
4136 lclMatrix_ = std::make_shared<local_multiply_op_type> (lclMat);
4141 k_values1D_ = lclMat->values;
4145 this->storageStatus_ = ::Tpetra::Details::STORAGE_1D_PACKED;
4147 checkInternalState ();
4150 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4154 const Teuchos::ArrayRCP<LocalOrdinal>& ind,
4155 const Teuchos::ArrayRCP<Scalar>& val)
4157 using Kokkos::Compat::getKokkosViewDeepCopy;
4158 using Teuchos::ArrayRCP;
4159 using Teuchos::av_reinterpret_cast;
4162 typedef typename local_matrix_type::row_map_type row_map_type;
4164 const char tfecfFuncName[] =
"setAllValues(ArrayRCP<size_t>, ArrayRCP<LO>, ArrayRCP<Scalar>): ";
4170 typename row_map_type::non_const_type ptrNative (
"ptr", ptr.size ());
4171 Kokkos::View<
const size_t*,
4172 typename row_map_type::array_layout,
4174 Kokkos::MemoryUnmanaged> ptrSizeT (ptr.getRawPtr (), ptr.size ());
4177 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4178 (ptrNative.extent (0) != ptrSizeT.extent (0),
4179 std::logic_error,
"ptrNative.extent(0) = " <<
4180 ptrNative.extent (0) <<
" != ptrSizeT.extent(0) = "
4181 << ptrSizeT.extent (0) <<
". Please report this bug to the "
4182 "Tpetra developers.");
4184 auto indIn = getKokkosViewDeepCopy<DT> (ind ());
4185 auto valIn = getKokkosViewDeepCopy<DT> (av_reinterpret_cast<IST> (val ()));
4186 this->setAllValues (ptrNative, indIn, valIn);
4189 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4194 const char tfecfFuncName[] =
"getLocalDiagOffsets: ";
4195 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4196 (staticGraph_.is_null (), std::runtime_error,
"The matrix has no graph.");
4203 const size_t lclNumRows = staticGraph_->getNodeNumRows ();
4204 if (static_cast<size_t> (offsets.size ()) < lclNumRows) {
4205 offsets.resize (lclNumRows);
4211 typedef typename device_type::memory_space memory_space;
4212 if (std::is_same<memory_space, Kokkos::HostSpace>::value) {
4217 Kokkos::MemoryUnmanaged> output_type;
4218 output_type offsetsOut (offsets.getRawPtr (), lclNumRows);
4219 staticGraph_->getLocalDiagOffsets (offsetsOut);
4222 Kokkos::View<size_t*, device_type> offsetsTmp (
"diagOffsets", lclNumRows);
4223 staticGraph_->getLocalDiagOffsets (offsetsTmp);
4224 typedef Kokkos::View<
size_t*, Kokkos::HostSpace,
4225 Kokkos::MemoryUnmanaged> output_type;
4226 output_type offsetsOut (offsets.getRawPtr (), lclNumRows);
4231 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4236 using Teuchos::ArrayRCP;
4237 using Teuchos::ArrayView;
4238 using Teuchos::av_reinterpret_cast;
4239 const char tfecfFuncName[] =
"getLocalDiagCopy (1-arg): ";
4243 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4244 staticGraph_.is_null (), std::runtime_error,
4245 "This method requires that the matrix have a graph.");
4246 auto rowMapPtr = this->getRowMap ();
4247 if (rowMapPtr.is_null () || rowMapPtr->getComm ().is_null ()) {
4253 auto colMapPtr = this->getColMap ();
4254 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4255 (! this->hasColMap () || colMapPtr.is_null (), std::runtime_error,
4256 "This method requires that the matrix have a column Map.");
4257 const map_type& rowMap = * rowMapPtr;
4258 const map_type& colMap = * colMapPtr;
4259 const LO myNumRows =
static_cast<LO
> (this->getNodeNumRows ());
4261 #ifdef HAVE_TPETRA_DEBUG
4264 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4265 ! diag.
getMap ()->isCompatible (rowMap), std::runtime_error,
4266 "The input Vector's Map must be compatible with the CrsMatrix's row "
4267 "Map. You may check this by using Map's isCompatible method: "
4268 "diag.getMap ()->isCompatible (A.getRowMap ());");
4269 #endif // HAVE_TPETRA_DEBUG
4271 if (this->isFillComplete ()) {
4272 diag.template modify<device_type> ();
4273 const auto D_lcl = diag.template getLocalView<device_type> ();
4275 const auto D_lcl_1d =
4276 Kokkos::subview (D_lcl, Kokkos::make_pair (LO (0), myNumRows), 0);
4278 const auto lclRowMap = rowMap.getLocalMap ();
4283 lclMatrix_->getLocalMatrix ());
4291 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4296 Kokkos::MemoryUnmanaged>& offsets)
const
4298 typedef LocalOrdinal LO;
4300 #ifdef HAVE_TPETRA_DEBUG
4301 const char tfecfFuncName[] =
"getLocalDiagCopy: ";
4302 const map_type& rowMap = * (this->getRowMap ());
4305 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4306 ! diag.
getMap ()->isCompatible (rowMap), std::runtime_error,
4307 "The input Vector's Map must be compatible with (in the sense of Map::"
4308 "isCompatible) the CrsMatrix's row Map.");
4309 #endif // HAVE_TPETRA_DEBUG
4318 diag.template modify<device_type> ();
4319 auto D_lcl = diag.template getLocalView<device_type> ();
4320 const LO myNumRows =
static_cast<LO
> (this->getNodeNumRows ());
4323 Kokkos::subview (D_lcl, Kokkos::make_pair (LO (0), myNumRows), 0);
4325 KokkosSparse::getDiagCopy (D_lcl_1d, offsets,
4326 lclMatrix_->getLocalMatrix ());
4329 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4333 const Teuchos::ArrayView<const size_t>& offsets)
const
4335 using LO = LocalOrdinal;
4336 using host_execution_space = Kokkos::DefaultHostExecutionSpace;
4339 #ifdef HAVE_TPETRA_DEBUG
4340 const char tfecfFuncName[] =
"getLocalDiagCopy: ";
4341 const map_type& rowMap = * (this->getRowMap ());
4344 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4345 ! diag.
getMap ()->isCompatible (rowMap), std::runtime_error,
4346 "The input Vector's Map must be compatible with (in the sense of Map::"
4347 "isCompatible) the CrsMatrix's row Map.");
4348 #endif // HAVE_TPETRA_DEBUG
4361 auto lclVecHost1d = Kokkos::subview (lclVecHost, Kokkos::ALL (), 0);
4363 using host_offsets_view_type =
4364 Kokkos::View<
const size_t*, Kokkos::HostSpace,
4365 Kokkos::MemoryTraits<Kokkos::Unmanaged> >;
4366 host_offsets_view_type h_offsets (offsets.getRawPtr (), offsets.size ());
4368 using range_type = Kokkos::RangePolicy<host_execution_space, LO>;
4369 const LO myNumRows =
static_cast<LO
> (this->getNodeNumRows ());
4370 const size_t INV = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
4373 Kokkos::parallel_for
4374 (
"Tpetra::CrsMatrix::getLocalDiagCopy",
4375 range_type (0, myNumRows),
4376 [&] (
const LO lclRow) {
4377 lclVecHost1d(lclRow) = STS::zero ();
4378 if (h_offsets[lclRow] != INV) {
4379 auto curRow = lclMat.rowConst (lclRow);
4380 lclVecHost1d(lclRow) =
static_cast<IST
> (curRow.value(h_offsets[lclRow]));
4387 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4392 using ::Tpetra::Details::ProfilingRegion;
4393 using Teuchos::ArrayRCP;
4394 using Teuchos::ArrayView;
4395 using Teuchos::null;
4398 using Teuchos::rcpFromRef;
4401 const char tfecfFuncName[] =
"leftScale: ";
4403 ProfilingRegion region (
"Tpetra::CrsMatrix::leftScale");
4405 RCP<const vec_type> xp;
4406 if (this->getRangeMap ()->isSameAs (* (x.
getMap ()))) {
4409 auto exporter = this->getCrsGraphRef ().getExporter ();
4410 if (exporter.get () !=
nullptr) {
4411 RCP<vec_type> tempVec (
new vec_type (this->getRowMap ()));
4412 tempVec->doImport (x, *exporter,
REPLACE);
4416 xp = rcpFromRef (x);
4419 else if (this->getRowMap ()->isSameAs (* (x.
getMap ()))) {
4420 xp = rcpFromRef (x);
4423 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4424 (
true, std::invalid_argument,
"x's Map must be the same as "
4425 "either the row Map or the range Map of the CrsMatrix.");
4433 const LO lclNumRows =
4434 static_cast<LO
> (this->getRowMap ()->getNodeNumElements ());
4435 const bool validLocalMatrix = lclMatrix_.get () !=
nullptr &&
4436 lclMatrix_->getLocalMatrix ().numRows () == lclNumRows;
4438 if (validLocalMatrix) {
4439 using dev_memory_space =
typename device_type::memory_space;
4440 if (xp->template need_sync<dev_memory_space> ()) {
4441 using Teuchos::rcp_const_cast;
4442 rcp_const_cast<vec_type> (xp)->
template sync<dev_memory_space> ();
4444 auto x_lcl = xp->template getLocalView<dev_memory_space> ();
4445 auto x_lcl_1d = Kokkos::subview (x_lcl, Kokkos::ALL (), 0);
4446 using ::Tpetra::Details::leftScaleLocalCrsMatrix;
4447 leftScaleLocalCrsMatrix (lclMatrix_->getLocalMatrix (),
4448 x_lcl_1d,
false,
false);
4453 ArrayRCP<const Scalar> vectorVals = xp->getData (0);
4454 ArrayView<impl_scalar_type> rowValues = Teuchos::null;
4455 for (LocalOrdinal i = 0; i < lclNumRows; ++i) {
4456 const RowInfo rowinfo = this->staticGraph_->getRowInfo (i);
4457 rowValues = this->getViewNonConst (rowinfo);
4459 for (
size_t j = 0; j < rowinfo.numEntries; ++j) {
4460 rowValues[j] *= scaleValue;
4467 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4472 using ::Tpetra::Details::ProfilingRegion;
4473 using Teuchos::ArrayRCP;
4474 using Teuchos::ArrayView;
4475 using Teuchos::null;
4478 using Teuchos::rcpFromRef;
4481 const char tfecfFuncName[] =
"rightScale: ";
4483 ProfilingRegion region (
"Tpetra::CrsMatrix::rightScale");
4485 RCP<const vec_type> xp;
4486 if (this->getDomainMap ()->isSameAs (* (x.
getMap ()))) {
4489 auto importer = this->getCrsGraphRef ().getImporter ();
4490 if (importer.get () !=
nullptr) {
4491 RCP<vec_type> tempVec (
new vec_type (this->getColMap ()));
4492 tempVec->doImport (x, *importer,
REPLACE);
4496 xp = rcpFromRef (x);
4499 else if (this->getColMap ()->isSameAs (* (x.
getMap ()))) {
4500 xp = rcpFromRef (x);
4502 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4503 (
true, std::runtime_error,
"x's Map must be the same as "
4504 "either the domain Map or the column Map of the CrsMatrix.");
4512 const LO lclNumRows =
4513 static_cast<LO
> (this->getRowMap ()->getNodeNumElements ());
4514 const bool validLocalMatrix = lclMatrix_.get () !=
nullptr &&
4515 lclMatrix_->getLocalMatrix ().numRows () == lclNumRows;
4517 if (validLocalMatrix) {
4518 using dev_memory_space =
typename device_type::memory_space;
4519 if (xp->template need_sync<dev_memory_space> ()) {
4520 using Teuchos::rcp_const_cast;
4521 rcp_const_cast<vec_type> (xp)->
template sync<dev_memory_space> ();
4523 auto x_lcl = xp->template getLocalView<dev_memory_space> ();
4524 auto x_lcl_1d = Kokkos::subview (x_lcl, Kokkos::ALL (), 0);
4525 using ::Tpetra::Details::rightScaleLocalCrsMatrix;
4526 rightScaleLocalCrsMatrix (lclMatrix_->getLocalMatrix (),
4527 x_lcl_1d,
false,
false);
4532 ArrayRCP<const Scalar> vectorVals = xp->getData (0);
4533 ArrayView<impl_scalar_type> rowValues = null;
4534 for (LO i = 0; i < lclNumRows; ++i) {
4535 const RowInfo rowinfo = this->staticGraph_->getRowInfo (i);
4536 rowValues = this->getViewNonConst (rowinfo);
4537 ArrayView<const LO> colInds;
4538 this->getCrsGraphRef ().getLocalRowView (i, colInds);
4539 for (
size_t j = 0; j < rowinfo.numEntries; ++j) {
4547 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4552 using Teuchos::ArrayView;
4553 using Teuchos::outArg;
4554 using Teuchos::REDUCE_SUM;
4555 using Teuchos::reduceAll;
4556 typedef typename Teuchos::ArrayRCP<const impl_scalar_type>::size_type size_type;
4564 if (frobNorm == -STM::one ()) {
4566 if (getNodeNumEntries() > 0) {
4567 if (isStorageOptimized ()) {
4570 const size_type numEntries =
4571 static_cast<size_type
> (getNodeNumEntries ());
4572 for (size_type k = 0; k < numEntries; ++k) {
4578 const mag_type val_abs = STS::abs (val);
4579 mySum += val_abs * val_abs;
4583 const LocalOrdinal numRows =
4584 static_cast<LocalOrdinal
> (this->getNodeNumRows ());
4585 for (LocalOrdinal r = 0; r < numRows; ++r) {
4586 const RowInfo rowInfo = myGraph_->getRowInfo (r);
4587 const size_type numEntries =
4588 static_cast<size_type
> (rowInfo.numEntries);
4589 ArrayView<const impl_scalar_type> A_r =
4590 this->getView (rowInfo).view (0, numEntries);
4591 for (size_type k = 0; k < numEntries; ++k) {
4593 const mag_type val_abs = STS::abs (val);
4594 mySum += val_abs * val_abs;
4600 reduceAll<int, mag_type> (* (getComm ()), REDUCE_SUM,
4601 mySum, outArg (totalSum));
4602 frobNorm = STM::sqrt (totalSum);
4604 if (isFillComplete ()) {
4608 frobNorm_ = frobNorm;
4613 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4618 const char tfecfFuncName[] =
"replaceColMap: ";
4622 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4623 myGraph_.is_null (), std::runtime_error,
4624 "This method does not work if the matrix has a const graph. The whole "
4625 "idea of a const graph is that you are not allowed to change it, but "
4626 "this method necessarily must modify the graph, since the graph owns "
4627 "the matrix's column Map.");
4628 myGraph_->replaceColMap (newColMap);
4631 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4635 const Teuchos::RCP<const map_type>& newColMap,
4636 const Teuchos::RCP<const import_type>& newImport,
4637 const bool sortEachRow)
4639 const char tfecfFuncName[] =
"reindexColumns: ";
4640 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4641 graph == NULL && myGraph_.is_null (), std::invalid_argument,
4642 "The input graph is NULL, but the matrix does not own its graph.");
4645 const bool sortGraph =
false;
4647 if (sortEachRow && theGraph.isLocallyIndexed () && ! theGraph.isSorted ()) {
4648 const LocalOrdinal lclNumRows =
4649 static_cast<LocalOrdinal
> (theGraph.getNodeNumRows ());
4650 for (LocalOrdinal row = 0; row < lclNumRows; ++row) {
4651 const RowInfo rowInfo = theGraph.getRowInfo (row);
4652 auto lclColInds = theGraph.getLocalKokkosRowViewNonConst (rowInfo);
4653 auto vals = this->getRowViewNonConst (rowInfo);
4656 sort2 (lclColInds.data (),
4657 lclColInds.data () + rowInfo.numEntries,
4660 theGraph.indicesAreSorted_ =
true;
4664 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4668 Teuchos::RCP<const import_type>& newImporter)
4670 const char tfecfFuncName[] =
"replaceDomainMapAndImporter: ";
4671 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
4672 myGraph_.is_null (), std::runtime_error,
4673 "This method does not work if the matrix has a const graph. The whole "
4674 "idea of a const graph is that you are not allowed to change it, but this"
4675 " method necessarily must modify the graph, since the graph owns the "
4676 "matrix's domain Map and Import objects.");
4677 myGraph_->replaceDomainMapAndImporter (newDomainMap, newImporter);
4680 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4684 const Teuchos::ArrayView<const GlobalOrdinal>& indices,
4685 const Teuchos::ArrayView<const Scalar>& values)
4687 using Teuchos::Array;
4688 typedef GlobalOrdinal GO;
4689 typedef typename Array<GO>::size_type size_type;
4691 const size_type numToInsert = indices.size ();
4694 std::pair<Array<GO>, Array<Scalar> >& curRow = nonlocals_[globalRow];
4695 Array<GO>& curRowInds = curRow.first;
4696 Array<Scalar>& curRowVals = curRow.second;
4697 const size_type newCapacity = curRowInds.size () + numToInsert;
4698 curRowInds.reserve (newCapacity);
4699 curRowVals.reserve (newCapacity);
4700 for (size_type k = 0; k < numToInsert; ++k) {
4701 curRowInds.push_back (indices[k]);
4702 curRowVals.push_back (values[k]);
4706 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4711 using ::Tpetra::Details::ProfilingRegion;
4712 using Teuchos::Comm;
4713 using Teuchos::outArg;
4716 using Teuchos::REDUCE_MAX;
4717 using Teuchos::REDUCE_MIN;
4718 using Teuchos::reduceAll;
4721 typedef GlobalOrdinal GO;
4722 typedef typename Teuchos::Array<GO>::size_type size_type;
4723 const char tfecfFuncName[] =
"globalAssemble: ";
4724 ProfilingRegion regionGlobalAssemble (
"Tpetra::CrsMatrix::globalAssemble");
4726 RCP<const Comm<int> > comm = getComm ();
4728 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4729 (! isFillActive (), std::runtime_error,
"Fill must be active before "
4730 "you may call this method.");
4732 const size_t myNumNonlocalRows = nonlocals_.size ();
4739 const int iHaveNonlocalRows = (myNumNonlocalRows == 0) ? 0 : 1;
4740 int someoneHasNonlocalRows = 0;
4741 reduceAll<int, int> (*comm, REDUCE_MAX, iHaveNonlocalRows,
4742 outArg (someoneHasNonlocalRows));
4743 if (someoneHasNonlocalRows == 0) {
4757 RCP<const map_type> nonlocalRowMap;
4759 Teuchos::Array<size_t> numEntPerNonlocalRow (myNumNonlocalRows);
4761 Teuchos::Array<GO> myNonlocalGblRows (myNumNonlocalRows);
4762 size_type curPos = 0;
4763 for (
auto mapIter = nonlocals_.begin (); mapIter != nonlocals_.end ();
4764 ++mapIter, ++curPos) {
4765 myNonlocalGblRows[curPos] = mapIter->first;
4768 Teuchos::Array<GO>& gblCols = (mapIter->second).first;
4769 Teuchos::Array<Scalar>& vals = (mapIter->second).second;
4776 sort2 (gblCols.begin (), gblCols.end (), vals.begin ());
4777 typename Teuchos::Array<GO>::iterator gblCols_newEnd;
4778 typename Teuchos::Array<Scalar>::iterator vals_newEnd;
4779 merge2 (gblCols_newEnd, vals_newEnd,
4780 gblCols.begin (), gblCols.end (),
4781 vals.begin (), vals.end ());
4782 gblCols.erase (gblCols_newEnd, gblCols.end ());
4783 vals.erase (vals_newEnd, vals.end ());
4784 numEntPerNonlocalRow[curPos] = gblCols.size ();
4795 GO myMinNonlocalGblRow = std::numeric_limits<GO>::max ();
4797 auto iter = std::min_element (myNonlocalGblRows.begin (),
4798 myNonlocalGblRows.end ());
4799 if (iter != myNonlocalGblRows.end ()) {
4800 myMinNonlocalGblRow = *iter;
4803 GO gblMinNonlocalGblRow = 0;
4804 reduceAll<int, GO> (*comm, REDUCE_MIN, myMinNonlocalGblRow,
4805 outArg (gblMinNonlocalGblRow));
4806 const GO indexBase = gblMinNonlocalGblRow;
4807 const global_size_t INV = Teuchos::OrdinalTraits<global_size_t>::invalid ();
4808 nonlocalRowMap = rcp (
new map_type (INV, myNonlocalGblRows (), indexBase, comm));
4816 RCP<crs_matrix_type> nonlocalMatrix =
4817 rcp (
new crs_matrix_type (nonlocalRowMap, numEntPerNonlocalRow (),
4820 size_type curPos = 0;
4821 for (
auto mapIter = nonlocals_.begin (); mapIter != nonlocals_.end ();
4822 ++mapIter, ++curPos) {
4823 const GO gblRow = mapIter->first;
4825 Teuchos::Array<GO>& gblCols = (mapIter->second).first;
4826 Teuchos::Array<Scalar>& vals = (mapIter->second).second;
4828 nonlocalMatrix->insertGlobalValues (gblRow, gblCols (), vals ());
4840 auto origRowMap = this->getRowMap ();
4841 const bool origRowMapIsOneToOne = origRowMap->isOneToOne ();
4843 int isLocallyComplete = 1;
4845 if (origRowMapIsOneToOne) {
4846 export_type exportToOrig (nonlocalRowMap, origRowMap);
4848 isLocallyComplete = 0;
4850 this->doExport (*nonlocalMatrix, exportToOrig,
Tpetra::ADD);
4859 export_type exportToOneToOne (nonlocalRowMap, oneToOneRowMap);
4861 isLocallyComplete = 0;
4868 crs_matrix_type oneToOneMatrix (oneToOneRowMap, 0);
4870 oneToOneMatrix.doExport (*nonlocalMatrix, exportToOneToOne,
Tpetra::ADD);
4874 nonlocalMatrix = Teuchos::null;
4877 import_type importToOrig (oneToOneRowMap, origRowMap);
4878 this->doImport (oneToOneMatrix, importToOrig,
Tpetra::ADD);
4885 decltype (nonlocals_) newNonlocals;
4886 std::swap (nonlocals_, newNonlocals);
4895 int isGloballyComplete = 0;
4896 reduceAll<int, int> (*comm, REDUCE_MIN, isLocallyComplete,
4897 outArg (isGloballyComplete));
4898 TEUCHOS_TEST_FOR_EXCEPTION
4899 (isGloballyComplete != 1, std::runtime_error,
"On at least one process, "
4900 "you called insertGlobalValues with a global row index which is not in "
4901 "the matrix's row Map on any process in its communicator.");
4904 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4909 if (! isStaticGraph ()) {
4910 myGraph_->resumeFill (params);
4912 clearGlobalConstants ();
4913 fillComplete_ =
false;
4916 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4930 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4934 return getCrsGraphRef ().haveGlobalConstants ();
4937 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4949 frobNorm_ = -STM::one ();
4952 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4957 const char tfecfFuncName[] =
"fillComplete(params): ";
4959 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4960 (this->getCrsGraph ().is_null (), std::logic_error,
4961 "getCrsGraph() returns null. This should not happen at this point. "
4962 "Please report this bug to the Tpetra developers.");
4972 Teuchos::RCP<const map_type> rangeMap = graph.
getRowMap ();
4973 Teuchos::RCP<const map_type> domainMap = rangeMap;
4974 this->fillComplete (domainMap, rangeMap, params);
4978 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
4982 const Teuchos::RCP<const map_type>& rangeMap,
4983 const Teuchos::RCP<Teuchos::ParameterList>& params)
4985 using ::Tpetra::Details::ProfilingRegion;
4986 using Teuchos::ArrayRCP;
4989 const char tfecfFuncName[] =
"fillComplete: ";
4990 ProfilingRegion regionFillComplete (
"Tpetra::CrsMatrix::fillComplete");
4992 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
4993 (! this->isFillActive () || this->isFillComplete (), std::runtime_error,
4994 "Matrix fill state must be active (isFillActive() "
4995 "must be true) before you may call fillComplete().");
4996 const int numProcs = this->getComm ()->getSize ();
5004 bool assertNoNonlocalInserts =
false;
5007 bool sortGhosts =
true;
5009 if (! params.is_null ()) {
5010 assertNoNonlocalInserts = params->get (
"No Nonlocal Changes",
5011 assertNoNonlocalInserts);
5012 if (params->isParameter (
"sort column map ghost gids")) {
5013 sortGhosts = params->get (
"sort column map ghost gids", sortGhosts);
5015 else if (params->isParameter (
"Sort column Map ghost GIDs")) {
5016 sortGhosts = params->get (
"Sort column Map ghost GIDs", sortGhosts);
5021 const bool needGlobalAssemble = ! assertNoNonlocalInserts && numProcs > 1;
5023 if (! this->myGraph_.is_null ()) {
5024 this->myGraph_->sortGhostsAssociatedWithEachProcessor_ = sortGhosts;
5027 if (! this->getCrsGraphRef ().indicesAreAllocated ()) {
5028 if (this->hasColMap ()) {
5030 this->allocateValues (LocalIndices, GraphNotYetAllocated);
5033 this->allocateValues (GlobalIndices, GraphNotYetAllocated);
5038 if (needGlobalAssemble) {
5039 this->globalAssemble ();
5042 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5043 (numProcs == 1 && nonlocals_.size() > 0,
5044 std::runtime_error,
"Cannot have nonlocal entries on a serial run. "
5045 "An invalid entry (i.e., with row index not in the row Map) must have "
5046 "been submitted to the CrsMatrix.");
5049 if (this->isStaticGraph ()) {
5056 #ifdef HAVE_TPETRA_DEBUG
5074 const bool domainMapsMatch =
5075 this->staticGraph_->getDomainMap ()->isSameAs (*domainMap);
5076 const bool rangeMapsMatch =
5077 this->staticGraph_->getRangeMap ()->isSameAs (*rangeMap);
5079 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5080 (! domainMapsMatch, std::runtime_error,
5081 "The CrsMatrix's domain Map does not match the graph's domain Map. "
5082 "The graph cannot be changed because it was given to the CrsMatrix "
5083 "constructor as const. You can fix this by passing in the graph's "
5084 "domain Map and range Map to the matrix's fillComplete call.");
5086 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5087 (! rangeMapsMatch, std::runtime_error,
5088 "The CrsMatrix's range Map does not match the graph's range Map. "
5089 "The graph cannot be changed because it was given to the CrsMatrix "
5090 "constructor as const. You can fix this by passing in the graph's "
5091 "domain Map and range Map to the matrix's fillComplete call.");
5092 #endif // HAVE_TPETRA_DEBUG
5096 this->fillLocalMatrix (params);
5103 this->myGraph_->setDomainRangeMaps (domainMap, rangeMap);
5106 Teuchos::Array<int> remotePIDs (0);
5107 const bool mustBuildColMap = ! this->hasColMap ();
5108 if (mustBuildColMap) {
5109 this->myGraph_->makeColMap (remotePIDs);
5114 const std::pair<size_t, std::string> makeIndicesLocalResult =
5115 this->myGraph_->makeIndicesLocal ();
5120 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5121 (makeIndicesLocalResult.first != 0, std::runtime_error,
5122 makeIndicesLocalResult.second);
5124 const bool sorted = this->myGraph_->isSorted ();
5125 const bool merged = this->myGraph_->isMerged ();
5126 this->sortAndMergeIndicesAndValues (sorted, merged);
5131 this->myGraph_->makeImportExport (remotePIDs, mustBuildColMap);
5135 this->fillLocalGraphAndMatrix (params);
5137 const bool callGraphComputeGlobalConstants = params.get () ==
nullptr ||
5138 params->get (
"compute global constants",
true);
5139 const bool computeLocalTriangularConstants = params.get () ==
nullptr ||
5140 params->get (
"compute local triangular constants",
true);
5141 if (callGraphComputeGlobalConstants) {
5142 this->myGraph_->computeGlobalConstants (computeLocalTriangularConstants);
5145 this->myGraph_->computeLocalConstants (computeLocalTriangularConstants);
5147 this->myGraph_->fillComplete_ =
true;
5148 this->myGraph_->checkInternalState ();
5151 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
5152 params->get (
"compute global constants",
true);
5153 if (callComputeGlobalConstants) {
5154 this->computeGlobalConstants ();
5159 this->fillComplete_ =
true;
5160 this->checkInternalState ();
5163 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5167 const Teuchos::RCP<const map_type> & rangeMap,
5168 const Teuchos::RCP<const import_type>& importer,
5169 const Teuchos::RCP<const export_type>& exporter,
5170 const Teuchos::RCP<Teuchos::ParameterList> ¶ms)
5172 #ifdef HAVE_TPETRA_MMM_TIMINGS
5174 if(!params.is_null())
5175 label = params->get(
"Timer Label",label);
5176 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
": ");
5177 using Teuchos::TimeMonitor;
5179 Teuchos::TimeMonitor all(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-all")));
5182 const char tfecfFuncName[] =
"expertStaticFillComplete: ";
5183 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC( ! isFillActive() || isFillComplete(),
5184 std::runtime_error,
"Matrix fill state must be active (isFillActive() "
5185 "must be true) before calling fillComplete().");
5186 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
5187 myGraph_.is_null (), std::logic_error,
"myGraph_ is null. This is not allowed.");
5190 #ifdef HAVE_TPETRA_MMM_TIMINGS
5191 Teuchos::TimeMonitor graph(*TimeMonitor::getNewTimer(prefix + std::string(
"eSFC-M-Graph")));
5194 myGraph_->expertStaticFillComplete (domainMap, rangeMap, importer, exporter,params);
5197 const bool callComputeGlobalConstants = params.get () ==
nullptr ||
5198 params->get (
"compute global constants",
true);
5199 if (callComputeGlobalConstants) {
5200 this->computeGlobalConstants ();
5204 #ifdef HAVE_TPETRA_MMM_TIMINGS
5205 TimeMonitor fLGAM(*TimeMonitor::getNewTimer(prefix + std::string(
"eSFC-M-fLGAM")));
5208 fillLocalGraphAndMatrix (params);
5213 fillComplete_ =
true;
5216 #ifdef HAVE_TPETRA_DEBUG
5217 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(isFillActive(), std::logic_error,
5218 ": We're at the end of fillComplete(), but isFillActive() is true. "
5219 "Please report this bug to the Tpetra developers.");
5220 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(! isFillComplete(), std::logic_error,
5221 ": We're at the end of fillComplete(), but isFillActive() is true. "
5222 "Please report this bug to the Tpetra developers.");
5223 #endif // HAVE_TPETRA_DEBUG
5225 #ifdef HAVE_TPETRA_MMM_TIMINGS
5226 Teuchos::TimeMonitor cIS(*TimeMonitor::getNewTimer(prefix + std::string(
"ESFC-M-cIS")));
5229 checkInternalState();
5233 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5239 #ifdef HAVE_TPETRA_DEBUG
5240 const char tfecfFuncName[] =
"mergeRowIndicesAndValues: ";
5241 #endif // HAVE_TPETRA_DEBUG
5243 auto rowValues = this->getRowViewNonConst (rowInfo);
5244 typedef typename std::decay<decltype (rowValues[0]) >::type value_type;
5245 value_type* rowValueIter = rowValues.data ();
5246 auto inds_view = graph.getLocalKokkosRowViewNonConst (rowInfo);
5249 LocalOrdinal* beg = inds_view.data ();
5250 LocalOrdinal* end = inds_view.data () + rowInfo.numEntries;
5252 #ifdef HAVE_TPETRA_DEBUG
5253 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5254 (rowInfo.allocSize != static_cast<size_t> (inds_view.extent (0)) ||
5255 rowInfo.allocSize != static_cast<size_t> (rowValues.extent (0)),
5256 std::runtime_error,
"rowInfo.allocSize = " << rowInfo.allocSize
5257 <<
" != inds_view.extent(0) = " << inds_view.extent (0)
5258 <<
" || rowInfo.allocSize = " << rowInfo.allocSize
5259 <<
" != rowValues.extent(0) = " << rowValues.extent (0) <<
".");
5260 #endif // HAVE_TPETRA_DEBUG
5262 LocalOrdinal* newend = beg;
5264 LocalOrdinal* cur = beg + 1;
5265 value_type* vcur = rowValueIter + 1;
5266 value_type* vend = rowValueIter;
5268 while (cur != end) {
5269 if (*cur != *newend) {
5286 const size_t mergedEntries = newend - beg;
5288 const size_t numDups = rowInfo.numEntries - mergedEntries;
5292 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5297 using ::Tpetra::Details::ProfilingRegion;
5298 typedef LocalOrdinal LO;
5299 typedef typename Kokkos::View<LO*, device_type>::HostMirror::execution_space
5300 host_execution_space;
5301 typedef Kokkos::RangePolicy<host_execution_space, LO> range_type;
5303 const char tfecfFuncName[] =
"sortAndMergeIndicesAndValues: ";
5304 ProfilingRegion regionSAM (
"Tpetra::CrsMatrix::sortAndMergeIndicesAndValues");
5306 if (! sorted || ! merged) {
5307 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5308 (this->isStaticGraph (), std::runtime_error,
"Cannot sort or merge with "
5309 "\"static\" (const) graph, since the matrix does not own the graph.");
5310 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5311 (this->myGraph_.is_null (), std::logic_error,
"myGraph_ is null, but "
5312 "this matrix claims ! isStaticGraph(). "
5313 "Please report this bug to the Tpetra developers.");
5314 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5315 (this->isStorageOptimized (), std::logic_error,
"It is invalid to call "
5316 "this method if the graph's storage has already been optimized. "
5317 "Please report this bug to the Tpetra developers.");
5320 const LO lclNumRows =
static_cast<LO
> (this->getNodeNumRows ());
5321 size_t totalNumDups = 0;
5323 Kokkos::parallel_reduce (range_type (0, lclNumRows),
5324 [
this, &graph, sorted, merged] (
const LO& lclRow,
size_t& numDups) {
5327 auto lclColInds = graph.getLocalKokkosRowViewNonConst (rowInfo);
5328 auto vals = this->getRowViewNonConst (rowInfo);
5331 sort2 (lclColInds.data (),
5332 lclColInds.data () + rowInfo.numEntries,
5336 numDups += this->mergeRowIndicesAndValues (graph, rowInfo);
5348 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5359 using Teuchos::rcp_const_cast;
5360 using Teuchos::rcpFromRef;
5361 const Scalar
ZERO = Teuchos::ScalarTraits<Scalar>::zero ();
5362 const Scalar ONE = Teuchos::ScalarTraits<Scalar>::one ();
5368 if (alpha == ZERO) {
5371 }
else if (beta != ONE) {
5385 RCP<const import_type> importer = this->getGraph ()->getImporter ();
5386 RCP<const export_type> exporter = this->getGraph ()->getExporter ();
5392 const bool Y_is_overwritten = (beta ==
ZERO);
5395 const bool Y_is_replicated =
5396 (! Y_in.
isDistributed () && this->getComm ()->getSize () != 1);
5404 if (Y_is_replicated && this->getComm ()->getRank () > 0) {
5411 RCP<const MV> X_colMap;
5412 if (importer.is_null ()) {
5420 RCP<MV> X_colMapNonConst = getColumnMapMultiVector (X_in,
true);
5422 X_colMap = rcp_const_cast<
const MV> (X_colMapNonConst);
5427 X_colMap = rcpFromRef (X_in);
5431 ProfilingRegion regionImport (
"Tpetra::CrsMatrix::apply: Import");
5437 RCP<MV> X_colMapNonConst = getColumnMapMultiVector (X_in);
5440 X_colMapNonConst->doImport (X_in, *importer,
INSERT);
5441 X_colMap = rcp_const_cast<
const MV> (X_colMapNonConst);
5448 RCP<MV> Y_rowMap = getRowMapMultiVector (Y_in);
5455 if (! exporter.is_null ()) {
5456 this->localApply (*X_colMap, *Y_rowMap, Teuchos::NO_TRANS, alpha, ZERO);
5458 ProfilingRegion regionExport (
"Tpetra::CrsMatrix::apply: Export");
5464 if (Y_is_overwritten) {
5490 Y_rowMap = getRowMapMultiVector (Y_in,
true);
5497 this->localApply (*X_colMap, *Y_rowMap, Teuchos::NO_TRANS, alpha, beta);
5501 this->localApply (*X_colMap, Y_in, Teuchos::NO_TRANS, alpha, beta);
5509 if (Y_is_replicated) {
5510 ProfilingRegion regionReduce (
"Tpetra::CrsMatrix::apply: Reduce Y");
5515 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5520 const Teuchos::ETransp mode,
5525 using Teuchos::null;
5528 using Teuchos::rcp_const_cast;
5529 using Teuchos::rcpFromRef;
5530 const Scalar
ZERO = Teuchos::ScalarTraits<Scalar>::zero ();
5533 if (alpha == ZERO) {
5556 RCP<const import_type> importer = this->getGraph ()->getImporter ();
5557 RCP<const export_type> exporter = this->getGraph ()->getExporter ();
5563 const bool Y_is_overwritten = (beta ==
ZERO);
5564 if (Y_is_replicated && this->getComm ()->getRank () > 0) {
5570 X = rcp (
new MV (X_in, Teuchos::Copy));
5572 X = rcpFromRef (X_in);
5576 if (importer != Teuchos::null) {
5577 if (importMV_ != Teuchos::null && importMV_->getNumVectors() != numVectors) {
5580 if (importMV_ == null) {
5581 importMV_ = rcp (
new MV (this->getColMap (), numVectors));
5584 if (exporter != Teuchos::null) {
5585 if (exportMV_ != Teuchos::null && exportMV_->getNumVectors() != numVectors) {
5588 if (exportMV_ == null) {
5589 exportMV_ = rcp (
new MV (this->getRowMap (), numVectors));
5595 if (! exporter.is_null ()) {
5596 ProfilingRegion regionImport (
"Tpetra::CrsMatrix::apply (transpose): Import");
5597 exportMV_->doImport (X_in, *exporter,
INSERT);
5604 if (importer != Teuchos::null) {
5605 ProfilingRegion regionExport (
"Tpetra::CrsMatrix::apply (transpose): Export");
5612 importMV_->putScalar (ZERO);
5614 this->localApply (*X, *importMV_, mode, alpha, ZERO);
5615 if (Y_is_overwritten) {
5632 MV Y (Y_in, Teuchos::Copy);
5633 this->localApply (*X, Y, mode, alpha, beta);
5636 this->localApply (*X, Y_in, mode, alpha, beta);
5643 if (Y_is_replicated) {
5644 ProfilingRegion regionReduce (
"Tpetra::CrsMatrix::apply (transpose): Reduce Y");
5649 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5654 const Teuchos::ETransp mode,
5655 const Scalar& alpha,
5656 const Scalar& beta)
const
5659 using Teuchos::NO_TRANS;
5660 ProfilingRegion regionLocalApply (
"Tpetra::CrsMatrix::localApply");
5671 const char tfecfFuncName[] =
"localApply: ";
5672 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5673 (lclMatrix_.get () ==
nullptr, std::logic_error,
5674 "lclMatrix_ not created yet.");
5675 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5679 const bool transpose = (mode != Teuchos::NO_TRANS);
5680 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5682 getColMap ()->getNodeNumElements (), std::runtime_error,
5683 "NO_TRANS case: X has the wrong number of local rows. "
5685 "getColMap()->getNodeNumElements() = " <<
5686 getColMap ()->getNodeNumElements () <<
".");
5687 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5689 getRowMap ()->getNodeNumElements (), std::runtime_error,
5690 "NO_TRANS case: Y has the wrong number of local rows. "
5692 "getRowMap()->getNodeNumElements() = " <<
5693 getRowMap ()->getNodeNumElements () <<
".");
5694 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5696 getRowMap ()->getNodeNumElements (), std::runtime_error,
5697 "TRANS or CONJ_TRANS case: X has the wrong number of local "
5699 <<
" != getRowMap()->getNodeNumElements() = "
5700 << getRowMap ()->getNodeNumElements () <<
".");
5701 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5703 getColMap ()->getNodeNumElements (), std::runtime_error,
5704 "TRANS or CONJ_TRANS case: X has the wrong number of local "
5706 <<
" != getColMap()->getNodeNumElements() = "
5707 << getColMap ()->getNodeNumElements () <<
".");
5708 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5709 (! isFillComplete (), std::runtime_error,
"The matrix is not "
5710 "fill complete. You must call fillComplete() (possibly with "
5711 "domain and range Map arguments) without an intervening "
5712 "resumeFill() call before you may call this method.");
5713 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5715 std::runtime_error,
"X and Y must be constant stride.");
5718 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
5719 (X_lcl.data () == Y_lcl.data () && X_lcl.data () !=
nullptr,
5720 std::runtime_error,
"X and Y may not alias one another.");
5723 lclMatrix_->apply (X_lcl, Y_lcl, mode, alpha, beta);
5726 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5731 Teuchos::ETransp mode,
5736 const char fnName[] =
"Tpetra::CrsMatrix::apply";
5738 TEUCHOS_TEST_FOR_EXCEPTION
5739 (! isFillComplete (), std::runtime_error,
5740 fnName <<
": Cannot call apply() until fillComplete() "
5741 "has been called.");
5743 if (mode == Teuchos::NO_TRANS) {
5744 ProfilingRegion regionNonTranspose (fnName);
5745 this->applyNonTranspose (X, Y, alpha, beta);
5748 ProfilingRegion regionTranspose (
"Tpetra::CrsMatrix::apply (transpose)");
5755 const Scalar
ZERO = Teuchos::ScalarTraits<Scalar>::zero ();
5759 this->applyTranspose (X, Y, mode, alpha, beta);
5763 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5769 const Scalar& dampingFactor,
5771 const int numSweeps)
const
5773 reorderedGaussSeidel (B, X, D, Teuchos::null, dampingFactor, direction, numSweeps);
5776 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
5782 const Teuchos::ArrayView<LocalOrdinal>& rowIndices,
5783 const Scalar& dampingFactor,
5785 const int numSweeps)
const
5787 using Teuchos::null;
5790 using Teuchos::rcp_const_cast;
5791 using Teuchos::rcpFromRef;
5794 TEUCHOS_TEST_FOR_EXCEPTION(
5795 isFillComplete() ==
false, std::runtime_error,
5796 "Tpetra::CrsMatrix::gaussSeidel: cannot call this method until "
5797 "fillComplete() has been called.");
5798 TEUCHOS_TEST_FOR_EXCEPTION(
5800 std::invalid_argument,
5801 "Tpetra::CrsMatrix::gaussSeidel: The number of sweeps must be , "
5802 "nonnegative but you provided numSweeps = " << numSweeps <<
" < 0.");
5807 if (direction == Forward) {
5808 localDirection = Forward;
5810 else if (direction == Backward) {
5811 localDirection = Backward;
5813 else if (direction == Symmetric) {
5815 localDirection = Forward;
5818 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
5819 "Tpetra::CrsMatrix::gaussSeidel: The 'direction' enum does not have "
5820 "any of its valid values: Forward, Backward, or Symmetric.");
5823 if (numSweeps == 0) {
5830 RCP<const import_type> importer = this->getGraph()->getImporter();
5831 RCP<const export_type> exporter = this->getGraph()->getExporter();
5832 TEUCHOS_TEST_FOR_EXCEPTION(
5833 ! exporter.is_null (), std::runtime_error,
5834 "Tpetra's gaussSeidel implementation requires that the row, domain, "
5835 "and range Maps be the same. This cannot be the case, because the "
5836 "matrix has a nontrivial Export object.");
5838 RCP<const map_type> domainMap = this->getDomainMap ();
5839 RCP<const map_type> rangeMap = this->getRangeMap ();
5840 RCP<const map_type> rowMap = this->getGraph ()->getRowMap ();
5841 RCP<const map_type> colMap = this->getGraph ()->getColMap ();
5843 #ifdef HAVE_TEUCHOS_DEBUG
5848 TEUCHOS_TEST_FOR_EXCEPTION(
5849 ! X.
getMap ()->isSameAs (*domainMap),
5851 "Tpetra::CrsMatrix::gaussSeidel requires that the input "
5852 "multivector X be in the domain Map of the matrix.");
5853 TEUCHOS_TEST_FOR_EXCEPTION(
5854 ! B.
getMap ()->isSameAs (*rangeMap),
5856 "Tpetra::CrsMatrix::gaussSeidel requires that the input "
5857 "B be in the range Map of the matrix.");
5858 TEUCHOS_TEST_FOR_EXCEPTION(
5859 ! D.
getMap ()->isSameAs (*rowMap),
5861 "Tpetra::CrsMatrix::gaussSeidel requires that the input "
5862 "D be in the row Map of the matrix.");
5863 TEUCHOS_TEST_FOR_EXCEPTION(
5864 ! rowMap->isSameAs (*rangeMap),
5866 "Tpetra::CrsMatrix::gaussSeidel requires that the row Map and the "
5867 "range Map be the same (in the sense of Tpetra::Map::isSameAs).");
5868 TEUCHOS_TEST_FOR_EXCEPTION(
5869 ! domainMap->isSameAs (*rangeMap),
5871 "Tpetra::CrsMatrix::gaussSeidel requires that the domain Map and "
5872 "the range Map of the matrix be the same.");
5878 #endif // HAVE_TEUCHOS_DEBUG
5888 B_in = rcpFromRef (B);
5895 RCP<MV> B_in_nonconst = getRowMapMultiVector (B,
true);
5897 B_in = rcp_const_cast<
const MV> (B_in_nonconst);
5902 "gaussSeidel: The current implementation of the Gauss-Seidel kernel "
5903 "requires that X and B both have constant stride. Since B does not "
5904 "have constant stride, we had to make a copy. This is a limitation of "
5905 "the current implementation and not your fault, but we still report it "
5906 "as an efficiency warning for your information.");
5915 RCP<MV> X_domainMap;
5917 bool copiedInput =
false;
5919 if (importer.is_null ()) {
5921 X_domainMap = rcpFromRef (X);
5922 X_colMap = X_domainMap;
5923 copiedInput =
false;
5929 X_colMap = getColumnMapMultiVector (X,
true);
5930 X_domainMap = X_colMap;
5935 "Tpetra::CrsMatrix::gaussSeidel: The current implementation of the "
5936 "Gauss-Seidel kernel requires that X and B both have constant "
5937 "stride. Since X does not have constant stride, we had to make a "
5938 "copy. This is a limitation of the current implementation and not "
5939 "your fault, but we still report it as an efficiency warning for "
5940 "your information.");
5945 X_domainMap = rcpFromRef (X);
5949 X_colMap = X_domainMap->offsetViewNonConst (colMap, 0);
5959 X_colMap->doImport (X, *importer,
INSERT);
5960 copiedInput =
false;
5967 X_colMap = getColumnMapMultiVector (X,
true);
5968 X_domainMap = X_colMap->offsetViewNonConst (domainMap, 0);
5969 X_colMap->doImport (X, *importer,
INSERT);
5973 "Tpetra::CrsMatrix::gaussSeidel: The current implementation of the "
5974 "Gauss-Seidel kernel requires that X and B both have constant stride. "
5975 "Since X does not have constant stride, we had to make a copy. "
5976 "This is a limitation of the current implementation and not your fault, "
5977 "but we still report it as an efficiency warning for your information.");
5981 for (
int sweep = 0; sweep < numSweeps; ++sweep) {
5982 if (! importer.is_null () && sweep > 0) {
5984 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
5988 if (direction != Symmetric) {
5989 if (rowIndices.is_null ()) {
5990 this->
template localGaussSeidel<ST, ST> (*B_in, *X_colMap, D,
5995 this->
template reorderedLocalGaussSeidel<ST, ST> (*B_in, *X_colMap,
6002 const bool doImportBetweenDirections =
false;
6003 if (rowIndices.is_null ()) {
6004 this->
template localGaussSeidel<ST, ST> (*B_in, *X_colMap, D,
6011 if (doImportBetweenDirections) {
6013 if (! importer.is_null ()) {
6014 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
6017 this->
template localGaussSeidel<ST, ST> (*B_in, *X_colMap, D,
6022 this->
template reorderedLocalGaussSeidel<ST, ST> (*B_in, *X_colMap,
6026 if (doImportBetweenDirections) {
6028 if (! importer.is_null ()) {
6029 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
6032 this->
template reorderedLocalGaussSeidel<ST, ST> (*B_in, *X_colMap,
6045 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6051 const Scalar& dampingFactor,
6053 const int numSweeps,
6054 const bool zeroInitialGuess)
const
6056 reorderedGaussSeidelCopy (X, B, D, Teuchos::null, dampingFactor, direction,
6057 numSweeps, zeroInitialGuess);
6060 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6066 const Teuchos::ArrayView<LocalOrdinal>& rowIndices,
6067 const Scalar& dampingFactor,
6069 const int numSweeps,
6070 const bool zeroInitialGuess)
const
6072 using Teuchos::null;
6075 using Teuchos::rcpFromRef;
6076 using Teuchos::rcp_const_cast;
6078 const char prefix[] =
"Tpetra::CrsMatrix::(reordered)gaussSeidelCopy: ";
6079 const Scalar
ZERO = Teuchos::ScalarTraits<Scalar>::zero ();
6081 TEUCHOS_TEST_FOR_EXCEPTION(
6082 ! isFillComplete (), std::runtime_error,
6083 prefix <<
"The matrix is not fill complete.");
6084 TEUCHOS_TEST_FOR_EXCEPTION(
6085 numSweeps < 0, std::invalid_argument,
6086 prefix <<
"The number of sweeps must be nonnegative, "
6087 "but you provided numSweeps = " << numSweeps <<
" < 0.");
6092 if (direction == Forward) {
6093 localDirection = Forward;
6095 else if (direction == Backward) {
6096 localDirection = Backward;
6098 else if (direction == Symmetric) {
6100 localDirection = Forward;
6103 TEUCHOS_TEST_FOR_EXCEPTION(
6104 true, std::invalid_argument,
6105 prefix <<
"The 'direction' enum does not have any of its valid "
6106 "values: Forward, Backward, or Symmetric.");
6109 if (numSweeps == 0) {
6113 RCP<const import_type> importer = this->getGraph ()->getImporter ();
6114 RCP<const export_type> exporter = this->getGraph ()->getExporter ();
6115 TEUCHOS_TEST_FOR_EXCEPTION(
6116 ! exporter.is_null (), std::runtime_error,
6117 "This method's implementation currently requires that the matrix's row, "
6118 "domain, and range Maps be the same. This cannot be the case, because "
6119 "the matrix has a nontrivial Export object.");
6121 RCP<const map_type> domainMap = this->getDomainMap ();
6122 RCP<const map_type> rangeMap = this->getRangeMap ();
6123 RCP<const map_type> rowMap = this->getGraph ()->getRowMap ();
6124 RCP<const map_type> colMap = this->getGraph ()->getColMap ();
6126 #ifdef HAVE_TEUCHOS_DEBUG
6131 TEUCHOS_TEST_FOR_EXCEPTION(
6132 ! X.
getMap ()->isSameAs (*domainMap), std::runtime_error,
6133 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
6134 "multivector X be in the domain Map of the matrix.");
6135 TEUCHOS_TEST_FOR_EXCEPTION(
6136 ! B.
getMap ()->isSameAs (*rangeMap), std::runtime_error,
6137 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
6138 "B be in the range Map of the matrix.");
6139 TEUCHOS_TEST_FOR_EXCEPTION(
6140 ! D.
getMap ()->isSameAs (*rowMap), std::runtime_error,
6141 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
6142 "D be in the row Map of the matrix.");
6143 TEUCHOS_TEST_FOR_EXCEPTION(
6144 ! rowMap->isSameAs (*rangeMap), std::runtime_error,
6145 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the row Map and the "
6146 "range Map be the same (in the sense of Tpetra::Map::isSameAs).");
6147 TEUCHOS_TEST_FOR_EXCEPTION(
6148 ! domainMap->isSameAs (*rangeMap), std::runtime_error,
6149 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the domain Map and "
6150 "the range Map of the matrix be the same.");
6156 #endif // HAVE_TEUCHOS_DEBUG
6167 RCP<MV> X_domainMap;
6168 bool copyBackOutput =
false;
6169 if (importer.is_null ()) {
6171 X_colMap = rcpFromRef (X);
6172 X_domainMap = rcpFromRef (X);
6178 if (zeroInitialGuess) {
6179 X_colMap->putScalar (ZERO);
6187 X_colMap = getColumnMapMultiVector (X,
true);
6191 X_domainMap = X_colMap;
6192 if (! zeroInitialGuess) {
6195 }
catch (std::exception& e) {
6196 std::ostringstream os;
6197 os <<
"Tpetra::CrsMatrix::reorderedGaussSeidelCopy: "
6198 "deep_copy(*X_domainMap, X) threw an exception: "
6199 << e.what () <<
".";
6200 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error, e.what ());
6203 copyBackOutput =
true;
6207 "gaussSeidelCopy: The current implementation of the Gauss-Seidel "
6208 "kernel requires that X and B both have constant stride. Since X "
6209 "does not have constant stride, we had to make a copy. This is a "
6210 "limitation of the current implementation and not your fault, but we "
6211 "still report it as an efficiency warning for your information.");
6215 X_colMap = getColumnMapMultiVector (X);
6216 X_domainMap = X_colMap->offsetViewNonConst (domainMap, 0);
6218 #ifdef HAVE_TPETRA_DEBUG
6219 auto X_colMap_host_view = X_colMap->getLocalViewHost ();
6220 auto X_domainMap_host_view = X_domainMap->getLocalViewHost ();
6222 if (X_colMap->getLocalLength () != 0 && X_domainMap->getLocalLength ()) {
6223 TEUCHOS_TEST_FOR_EXCEPTION
6224 (X_colMap_host_view.data () != X_domainMap_host_view.data (),
6225 std::logic_error,
"Tpetra::CrsMatrix::gaussSeidelCopy: Pointer to "
6226 "start of column Map view of X is not equal to pointer to start of "
6227 "(domain Map view of) X. This may mean that Tpetra::MultiVector::"
6228 "offsetViewNonConst is broken. "
6229 "Please report this bug to the Tpetra developers.");
6232 TEUCHOS_TEST_FOR_EXCEPTION(
6233 X_colMap_host_view.extent (0) < X_domainMap_host_view.extent (0) ||
6234 X_colMap->getLocalLength () < X_domainMap->getLocalLength (),
6235 std::logic_error,
"Tpetra::CrsMatrix::gaussSeidelCopy: "
6236 "X_colMap has fewer local rows than X_domainMap. "
6237 "X_colMap_host_view.extent(0) = " << X_colMap_host_view.extent (0)
6238 <<
", X_domainMap_host_view.extent(0) = "
6239 << X_domainMap_host_view.extent (0)
6240 <<
", X_colMap->getLocalLength() = " << X_colMap->getLocalLength ()
6241 <<
", and X_domainMap->getLocalLength() = "
6242 << X_domainMap->getLocalLength ()
6243 <<
". This means that Tpetra::MultiVector::offsetViewNonConst "
6244 "is broken. Please report this bug to the Tpetra developers.");
6246 TEUCHOS_TEST_FOR_EXCEPTION(
6247 X_colMap->getNumVectors () != X_domainMap->getNumVectors (),
6248 std::logic_error,
"Tpetra::CrsMatrix::gaussSeidelCopy: "
6249 "X_colMap has a different number of columns than X_domainMap. "
6250 "X_colMap->getNumVectors() = " << X_colMap->getNumVectors ()
6251 <<
" != X_domainMap->getNumVectors() = "
6252 << X_domainMap->getNumVectors ()
6253 <<
". This means that Tpetra::MultiVector::offsetViewNonConst "
6254 "is broken. Please report this bug to the Tpetra developers.");
6255 #endif // HAVE_TPETRA_DEBUG
6257 if (zeroInitialGuess) {
6259 X_colMap->putScalar (ZERO);
6269 X_colMap->doImport (X, *importer,
INSERT);
6271 copyBackOutput =
true;
6279 B_in = rcpFromRef (B);
6285 RCP<MV> B_in_nonconst = getRowMapMultiVector (B,
true);
6288 }
catch (std::exception& e) {
6289 std::ostringstream os;
6290 os <<
"Tpetra::CrsMatrix::reorderedGaussSeidelCopy: "
6291 "deep_copy(*B_in_nonconst, B) threw an exception: "
6292 << e.what () <<
".";
6293 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error, e.what ());
6295 B_in = rcp_const_cast<
const MV> (B_in_nonconst);
6300 "gaussSeidelCopy: The current implementation requires that B have "
6301 "constant stride. Since B does not have constant stride, we had to "
6302 "copy it into a separate constant-stride multivector. This is a "
6303 "limitation of the current implementation and not your fault, but we "
6304 "still report it as an efficiency warning for your information.");
6307 for (
int sweep = 0; sweep < numSweeps; ++sweep) {
6308 if (! importer.is_null () && sweep > 0) {
6311 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
6315 if (direction != Symmetric) {
6316 if (rowIndices.is_null ()) {
6317 this->
template localGaussSeidel<ST, ST> (*B_in, *X_colMap, D,
6322 this->
template reorderedLocalGaussSeidel<ST, ST> (*B_in, *X_colMap,
6329 if (rowIndices.is_null ()) {
6330 this->
template localGaussSeidel<ST, ST> (*B_in, *X_colMap, D,
6338 this->
template localGaussSeidel<ST, ST> (*B_in, *X_colMap, D,
6343 this->
template reorderedLocalGaussSeidel<ST, ST> (*B_in, *X_colMap,
6347 this->
template reorderedLocalGaussSeidel<ST, ST> (*B_in, *X_colMap,
6356 if (copyBackOutput) {
6359 }
catch (std::exception& e) {
6360 TEUCHOS_TEST_FOR_EXCEPTION(
6361 true, std::runtime_error, prefix <<
"deep_copy(X, *X_domainMap) "
6362 "threw an exception: " << e.what ());
6367 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6369 Teuchos::RCP<CrsMatrix<T, LocalOrdinal, GlobalOrdinal, Node> >
6375 const char tfecfFuncName[] =
"convert: ";
6377 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6378 (! this->isFillComplete (), std::runtime_error,
"This matrix (the source "
6379 "of the conversion) is not fill complete. You must first call "
6380 "fillComplete() (possibly with the domain and range Map) without an "
6381 "intervening call to resumeFill(), before you may call this method.");
6382 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
6383 (! this->isStaticGraph (), std::logic_error,
"This matrix (the source "
6384 "of the conversion) claims to be fill complete, but does not have a "
6385 "static (i.e., constant) graph. Please report this bug to the Tpetra "
6388 RCP<output_matrix_type> newMatrix
6389 (
new output_matrix_type (this->getCrsGraph ()));
6392 using ::Tpetra::Details::copyConvert;
6393 copyConvert (newMatrix->lclMatrix_->getLocalMatrix ().values,
6394 this->lclMatrix_->getLocalMatrix ().values);
6398 newMatrix->fillComplete (this->getDomainMap (), this->getRangeMap ());
6404 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6409 #ifdef HAVE_TPETRA_DEBUG
6410 const char tfecfFuncName[] =
"checkInternalState: ";
6411 const char err[] =
"Internal state is not consistent. "
6412 "Please report this bug to the Tpetra developers.";
6416 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
6417 staticGraph_.is_null (),
6418 std::logic_error, err);
6422 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
6423 ! myGraph_.is_null () && myGraph_ != staticGraph_,
6424 std::logic_error, err);
6426 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
6427 isFillComplete () && ! staticGraph_->isFillComplete (),
6428 std::logic_error, err <<
" Specifically, the matrix is fill complete, "
6429 "but its graph is NOT fill complete.");
6431 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
6432 isStorageOptimized () && ! values2D_.is_null (),
6433 std::logic_error, err);
6435 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
6436 getProfileType() == StaticProfile && values2D_ != Teuchos::null,
6437 std::logic_error, err);
6439 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
6440 getProfileType() != StaticProfile && k_values1D_.extent (0) > 0,
6441 std::logic_error, err);
6444 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
6445 staticGraph_->indicesAreAllocated () &&
6446 staticGraph_->getNodeAllocationSize() > 0 &&
6447 staticGraph_->getNodeNumRows() > 0
6448 && values2D_.is_null () &&
6449 k_values1D_.extent (0) == 0,
6450 std::logic_error, err);
6452 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
6453 k_values1D_.extent (0) > 0 && values2D_ != Teuchos::null,
6454 std::logic_error, err <<
" Specifically, k_values1D_ is allocated (has "
6455 "size " << k_values1D_.extent (0) <<
" > 0) and values2D_ is also "
6456 "allocated. CrsMatrix is not suppose to have both a 1-D and a 2-D "
6457 "allocation at the same time.");
6461 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6466 std::ostringstream os;
6468 os <<
"Tpetra::CrsMatrix (Kokkos refactor): {";
6469 if (this->getObjectLabel () !=
"") {
6470 os <<
"Label: \"" << this->getObjectLabel () <<
"\", ";
6472 if (isFillComplete ()) {
6473 os <<
"isFillComplete: true"
6474 <<
", global dimensions: [" << getGlobalNumRows () <<
", "
6475 << getGlobalNumCols () <<
"]"
6476 <<
", global number of entries: " << getGlobalNumEntries ()
6480 os <<
"isFillComplete: false"
6481 <<
", global dimensions: [" << getGlobalNumRows () <<
", "
6482 << getGlobalNumCols () <<
"]}";
6487 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6491 const Teuchos::EVerbosityLevel verbLevel)
const
6495 using Teuchos::ArrayView;
6496 using Teuchos::Comm;
6498 using Teuchos::TypeNameTraits;
6499 using Teuchos::VERB_DEFAULT;
6500 using Teuchos::VERB_NONE;
6501 using Teuchos::VERB_LOW;
6502 using Teuchos::VERB_MEDIUM;
6503 using Teuchos::VERB_HIGH;
6504 using Teuchos::VERB_EXTREME;
6506 const Teuchos::EVerbosityLevel vl = (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
6508 if (vl == VERB_NONE) {
6513 Teuchos::OSTab tab0 (out);
6515 RCP<const Comm<int> > comm = this->getComm();
6516 const int myRank = comm->getRank();
6517 const int numProcs = comm->getSize();
6519 for (
size_t dec=10; dec<getGlobalNumRows(); dec *= 10) {
6522 width = std::max<size_t> (width,
static_cast<size_t> (11)) + 2;
6532 out <<
"Tpetra::CrsMatrix (Kokkos refactor):" << endl;
6534 Teuchos::OSTab tab1 (out);
6537 if (this->getObjectLabel () !=
"") {
6538 out <<
"Label: \"" << this->getObjectLabel () <<
"\", ";
6541 out <<
"Template parameters:" << endl;
6542 Teuchos::OSTab tab2 (out);
6543 out <<
"Scalar: " << TypeNameTraits<Scalar>::name () << endl
6544 <<
"LocalOrdinal: " << TypeNameTraits<LocalOrdinal>::name () << endl
6545 <<
"GlobalOrdinal: " << TypeNameTraits<GlobalOrdinal>::name () << endl
6546 <<
"Node: " << TypeNameTraits<Node>::name () << endl;
6548 if (isFillComplete()) {
6549 out <<
"isFillComplete: true" << endl
6550 <<
"Global dimensions: [" << getGlobalNumRows () <<
", "
6551 << getGlobalNumCols () <<
"]" << endl
6552 <<
"Global number of entries: " << getGlobalNumEntries () << endl
6553 << endl <<
"Global max number of entries in a row: "
6554 << getGlobalMaxNumRowEntries () << endl;
6557 out <<
"isFillComplete: false" << endl
6558 <<
"Global dimensions: [" << getGlobalNumRows () <<
", "
6559 << getGlobalNumCols () <<
"]" << endl;
6563 if (vl < VERB_MEDIUM) {
6569 out << endl <<
"Row Map:" << endl;
6571 if (getRowMap ().is_null ()) {
6573 out <<
"null" << endl;
6580 getRowMap ()->describe (out, vl);
6585 out <<
"Column Map: ";
6587 if (getColMap ().is_null ()) {
6589 out <<
"null" << endl;
6591 }
else if (getColMap () == getRowMap ()) {
6593 out <<
"same as row Map" << endl;
6599 getColMap ()->describe (out, vl);
6604 out <<
"Domain Map: ";
6606 if (getDomainMap ().is_null ()) {
6608 out <<
"null" << endl;
6610 }
else if (getDomainMap () == getRowMap ()) {
6612 out <<
"same as row Map" << endl;
6614 }
else if (getDomainMap () == getColMap ()) {
6616 out <<
"same as column Map" << endl;
6622 getDomainMap ()->describe (out, vl);
6627 out <<
"Range Map: ";
6629 if (getRangeMap ().is_null ()) {
6631 out <<
"null" << endl;
6633 }
else if (getRangeMap () == getDomainMap ()) {
6635 out <<
"same as domain Map" << endl;
6637 }
else if (getRangeMap () == getRowMap ()) {
6639 out <<
"same as row Map" << endl;
6645 getRangeMap ()->describe (out, vl);
6649 for (
int curRank = 0; curRank < numProcs; ++curRank) {
6650 if (myRank == curRank) {
6651 out <<
"Process rank: " << curRank << endl;
6652 Teuchos::OSTab tab2 (out);
6653 if (! staticGraph_->indicesAreAllocated ()) {
6654 out <<
"Graph indices not allocated" << endl;
6657 out <<
"Number of allocated entries: "
6658 << staticGraph_->getNodeAllocationSize () << endl;
6660 out <<
"Number of entries: " << getNodeNumEntries () << endl
6661 <<
"Max number of entries per row: " << getNodeMaxNumRowEntries ()
6670 if (vl < VERB_HIGH) {
6675 for (
int curRank = 0; curRank < numProcs; ++curRank) {
6676 if (myRank == curRank) {
6677 out << std::setw(width) <<
"Proc Rank"
6678 << std::setw(width) <<
"Global Row"
6679 << std::setw(width) <<
"Num Entries";
6680 if (vl == VERB_EXTREME) {
6681 out << std::setw(width) <<
"(Index,Value)";
6684 for (
size_t r = 0; r < getNodeNumRows (); ++r) {
6685 const size_t nE = getNumEntriesInLocalRow(r);
6686 GlobalOrdinal gid = getRowMap()->getGlobalElement(r);
6687 out << std::setw(width) << myRank
6688 << std::setw(width) << gid
6689 << std::setw(width) << nE;
6690 if (vl == VERB_EXTREME) {
6691 if (isGloballyIndexed()) {
6692 ArrayView<const GlobalOrdinal> rowinds;
6693 ArrayView<const Scalar> rowvals;
6694 getGlobalRowView (gid, rowinds, rowvals);
6695 for (
size_t j = 0; j < nE; ++j) {
6696 out <<
" (" << rowinds[j]
6697 <<
", " << rowvals[j]
6701 else if (isLocallyIndexed()) {
6702 ArrayView<const LocalOrdinal> rowinds;
6703 ArrayView<const Scalar> rowvals;
6704 getLocalRowView (r, rowinds, rowvals);
6705 for (
size_t j=0; j < nE; ++j) {
6706 out <<
" (" << getColMap()->getGlobalElement(rowinds[j])
6707 <<
", " << rowvals[j]
6723 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6736 const row_matrix_type* srcRowMat =
6737 dynamic_cast<const row_matrix_type*
> (&source);
6738 return (srcRowMat != NULL);
6741 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6744 applyCrsPadding(
const Kokkos::UnorderedMap<LocalOrdinal, size_t, device_type>& padding)
6747 using execution_space =
typename device_type::execution_space;
6748 using row_ptrs_type =
typename local_graph_type::row_map_type::non_const_type;
6749 using range_policy = Kokkos::RangePolicy<execution_space, Kokkos::IndexType<LocalOrdinal>>;
6752 const char tfecfFuncName[] =
"applyCrsPadding: ";
6754 if (! myGraph_->indicesAreAllocated ()) {
6755 this->allocateValues (GlobalIndices, GraphNotYetAllocated);
6758 if (padding.size() == 0)
6764 row_ptrs_type row_ptr_beg(
"row_ptr_beg", myGraph_->k_rowPtrs_.extent(0));
6767 const size_t N = (row_ptr_beg.extent(0) == 0 ? 0 : row_ptr_beg.extent(0) - 1);
6768 row_ptrs_type row_ptr_end(
"row_ptr_end", N);
6770 bool refill_num_row_entries =
false;
6771 if (myGraph_->k_numRowEntries_.extent(0) > 0) {
6773 refill_num_row_entries =
true;
6774 auto num_row_entries = myGraph_->k_numRowEntries_;
6775 Kokkos::parallel_for(
"Fill end row pointers", range_policy(0, N),
6776 KOKKOS_LAMBDA(
const size_t i){
6777 row_ptr_end(i) = row_ptr_beg(i) + num_row_entries(i);
6785 Kokkos::parallel_for(
"Fill end row pointers", range_policy(0, N),
6786 KOKKOS_LAMBDA(
const size_t i){
6787 row_ptr_end(i) = row_ptr_beg(i+1);
6792 using values_type =
typename local_matrix_type::values_type;
6793 values_type values(
"values", k_values1D_.size());
6796 if(myGraph_->isGloballyIndexed()) {
6797 using indices_type =
typename crs_graph_type::t_GlobalOrdinal_1D;
6798 indices_type indices(
"indices", myGraph_->k_gblInds1D_.extent(0));
6800 using padding_type = Kokkos::UnorderedMap<LocalOrdinal, size_t, device_type>;
6801 padCrsArrays<row_ptrs_type,indices_type,values_type,padding_type>(row_ptr_beg, row_ptr_end, indices, values, padding);
6802 myGraph_->k_gblInds1D_ = indices;
6803 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
6804 values.size() != indices.size(),
6806 "After padding, values and indices should be same size");
6809 using indices_type =
typename local_graph_type::entries_type::non_const_type;
6810 indices_type indices(
"indices", myGraph_->k_lclInds1D_.extent(0));
6812 using padding_type = Kokkos::UnorderedMap<LocalOrdinal, size_t, device_type>;
6813 padCrsArrays<row_ptrs_type,indices_type,values_type,padding_type>(row_ptr_beg, row_ptr_end, indices, values, padding);
6814 myGraph_->k_lclInds1D_ = indices;
6815 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
6816 values.size() != indices.size(),
6818 "After padding, values and indices should be same size");
6821 if (refill_num_row_entries) {
6822 auto num_row_entries = myGraph_->k_numRowEntries_;
6823 Kokkos::parallel_for(
"Fill num entries", range_policy(0, N),
6824 KOKKOS_LAMBDA(
const size_t i){
6825 num_row_entries(i) = row_ptr_end(i) - row_ptr_beg(i);
6829 myGraph_->k_rowPtrs_ = row_ptr_beg;
6830 k_values1D_ = values;
6833 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6835 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
6836 copyAndPermuteImpl (
const RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& srcMat,
6837 const size_t numSameIDs,
6838 const LocalOrdinal permuteToLIDs[],
6839 const LocalOrdinal permuteFromLIDs[],
6840 const size_t numPermutes)
6843 using Teuchos::Array;
6844 using Teuchos::ArrayView;
6845 typedef LocalOrdinal LO;
6846 typedef GlobalOrdinal GO;
6847 #ifdef HAVE_TPETRA_DEBUG
6849 const char tfecfFuncName[] =
"copyAndPermuteImpl: ";
6850 #endif // HAVE_TPETRA_DEBUG
6852 ProfilingRegion regionCAP (
"Tpetra::CrsMatrix::copyAndPermuteImpl");
6854 const bool sourceIsLocallyIndexed = srcMat.isLocallyIndexed ();
6859 const map_type& srcRowMap = * (srcMat.getRowMap ());
6861 Array<Scalar> rowVals;
6862 const LO numSameIDs_as_LID =
static_cast<LO
> (numSameIDs);
6863 for (LO sourceLID = 0; sourceLID < numSameIDs_as_LID; ++sourceLID) {
6867 const GO sourceGID = srcRowMap.getGlobalElement (sourceLID);
6868 const GO targetGID = sourceGID;
6871 ArrayView<const GO> rowIndsConstView;
6872 ArrayView<const Scalar> rowValsConstView;
6874 if (sourceIsLocallyIndexed) {
6875 const size_t rowLength = srcMat.getNumEntriesInGlobalRow (sourceGID);
6876 if (rowLength > static_cast<size_t> (rowInds.size())) {
6877 rowInds.resize (rowLength);
6878 rowVals.resize (rowLength);
6882 ArrayView<GO> rowIndsView = rowInds.view (0, rowLength);
6883 ArrayView<Scalar> rowValsView = rowVals.view (0, rowLength);
6888 size_t checkRowLength = 0;
6889 srcMat.getGlobalRowCopy (sourceGID, rowIndsView, rowValsView, checkRowLength);
6891 #ifdef HAVE_TPETRA_DEBUG
6892 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowLength != checkRowLength,
6893 std::logic_error,
"For global row index " << sourceGID <<
", the source"
6894 " matrix's getNumEntriesInGlobalRow() method returns a row length of "
6895 << rowLength <<
", but the getGlobalRowCopy() method reports that "
6896 "the row length is " << checkRowLength <<
". Please report this bug "
6897 "to the Tpetra developers.");
6898 #endif // HAVE_TPETRA_DEBUG
6900 rowIndsConstView = rowIndsView.view (0, rowLength);
6901 rowValsConstView = rowValsView.view (0, rowLength);
6904 srcMat.getGlobalRowView (sourceGID, rowIndsConstView, rowValsConstView);
6908 if (this->isStaticGraph ()) {
6911 combineGlobalValues (targetGID, rowIndsConstView, rowValsConstView,
REPLACE);
6917 combineGlobalValues (targetGID, rowIndsConstView, rowValsConstView,
INSERT);
6924 const map_type& tgtRowMap = * (this->getRowMap ());
6925 for (
size_t p = 0; p < numPermutes; ++p) {
6926 const GO sourceGID = srcRowMap.getGlobalElement (permuteFromLIDs[p]);
6927 const GO targetGID = tgtRowMap.getGlobalElement (permuteToLIDs[p]);
6930 ArrayView<const GO> rowIndsConstView;
6931 ArrayView<const Scalar> rowValsConstView;
6933 if (sourceIsLocallyIndexed) {
6934 const size_t rowLength = srcMat.getNumEntriesInGlobalRow (sourceGID);
6935 if (rowLength > static_cast<size_t> (rowInds.size ())) {
6936 rowInds.resize (rowLength);
6937 rowVals.resize (rowLength);
6941 ArrayView<GO> rowIndsView = rowInds.view (0, rowLength);
6942 ArrayView<Scalar> rowValsView = rowVals.view (0, rowLength);
6947 size_t checkRowLength = 0;
6948 srcMat.getGlobalRowCopy (sourceGID, rowIndsView, rowValsView, checkRowLength);
6950 #ifdef HAVE_TPETRA_DEBUG
6951 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(rowLength != checkRowLength,
6952 std::logic_error,
"For the source matrix's global row index "
6953 << sourceGID <<
", the source matrix's getNumEntriesInGlobalRow() "
6954 "method returns a row length of " << rowLength <<
", but the "
6955 "getGlobalRowCopy() method reports that the row length is "
6956 << checkRowLength <<
". Please report this bug to the Tpetra "
6958 #endif // HAVE_TPETRA_DEBUG
6960 rowIndsConstView = rowIndsView.view (0, rowLength);
6961 rowValsConstView = rowValsView.view (0, rowLength);
6964 srcMat.getGlobalRowView (sourceGID, rowIndsConstView, rowValsConstView);
6968 if (isStaticGraph()) {
6969 this->combineGlobalValues (targetGID, rowIndsConstView,
6973 this->combineGlobalValues (targetGID, rowIndsConstView,
6974 rowValsConstView,
INSERT);
6979 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
6981 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
6982 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
6984 #else // TPETRA_ENABLE_DEPRECATED_CODE
6986 #endif // TPETRA_ENABLE_DEPRECATED_CODE
6987 (
const SrcDistObject& srcObj,
6988 const size_t numSameIDs,
6989 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteToLIDs,
6990 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& permuteFromLIDs)
6997 const char tfecfFuncName[] =
"copyAndPermute: ";
6998 ProfilingRegion regionCAP (
"Tpetra::CrsMatrix::copyAndPermute");
7001 std::unique_ptr<std::string> prefix;
7004 auto map = this->getMap ();
7005 if (! map.is_null ()) {
7006 auto comm = map->getComm ();
7007 if (! comm.is_null ()) {
7008 myRank = comm->getRank ();
7011 prefix = [myRank] () {
7012 std::ostringstream pfxStrm;
7013 pfxStrm <<
"Proc " << myRank <<
": Tpetra::CrsMatrix::copyAndPermute: ";
7014 return std::unique_ptr<std::string> (
new std::string (pfxStrm.str ()));
7016 std::ostringstream os;
7017 os << *prefix << endl
7022 std::cerr << os.str ();
7025 const auto numPermute = permuteToLIDs.extent (0);
7026 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
7027 (numPermute != permuteFromLIDs.extent (0),
7028 std::invalid_argument,
"permuteToLIDs.extent(0) = "
7029 << numPermute <<
"!= permuteFromLIDs.extent(0) = "
7030 << permuteFromLIDs.extent (0) <<
".");
7032 TEUCHOS_ASSERT( ! permuteToLIDs.need_sync_host () );
7033 auto permuteToLIDs_h = permuteToLIDs.view_host ();
7034 TEUCHOS_ASSERT( ! permuteFromLIDs.need_sync_host () );
7035 auto permuteFromLIDs_h = permuteFromLIDs.view_host ();
7040 const RMT& srcMat =
dynamic_cast<const RMT&
> (srcObj);
7042 if (!this->isStaticGraph () && this->getProfileType () == StaticProfile) {
7044 this->myGraph_->computeCrsPadding(*srcMat.getGraph(), numSameIDs, permuteToLIDs, permuteFromLIDs);
7045 if (padding.size() > 0)
7046 this->applyCrsPadding(padding);
7051 std::ostringstream os;
7052 os << *prefix <<
"Call copyAndPermuteImpl" << endl;
7053 std::cerr << os.str ();
7055 this->copyAndPermuteImpl (srcMat, numSameIDs, permuteToLIDs_h.data (),
7056 permuteFromLIDs_h.data (), numPermute);
7059 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7061 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
7062 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
7064 #else // TPETRA_ENABLE_DEPRECATED_CODE
7066 #endif // TPETRA_ENABLE_DEPRECATED_CODE
7067 (
const SrcDistObject& source,
7068 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& exportLIDs,
7069 Kokkos::DualView<char*, buffer_device_type>& exports,
7070 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
7071 size_t& constantNumPackets,
7072 Distributor& distor)
7076 using Teuchos::outArg;
7077 using Teuchos::REDUCE_MAX;
7078 using Teuchos::reduceAll;
7080 typedef LocalOrdinal LO;
7081 typedef GlobalOrdinal GO;
7082 const char tfecfFuncName[] =
"packAndPrepare: ";
7083 ProfilingRegion regionPAP (
"Tpetra::CrsMatrix::packAndPrepare");
7089 Teuchos::RCP<const Teuchos::Comm<int> > pComm = this->getComm ();
7090 if (pComm.is_null ()) {
7093 const Teuchos::Comm<int>& comm = *pComm;
7094 const int myRank = comm.getSize ();
7096 std::unique_ptr<std::string> prefix;
7098 prefix = [myRank] () {
7099 std::ostringstream pfxStrm;
7100 pfxStrm <<
"Proc " << myRank <<
": Tpetra::CrsMatrix::packAndPrepare: ";
7101 return std::unique_ptr<std::string> (
new std::string (pfxStrm.str ()));
7103 std::ostringstream os;
7104 os << *prefix <<
"Start" << endl
7114 std::cerr << os.str ();
7137 std::ostringstream msg;
7140 using crs_matrix_type = CrsMatrix<Scalar, LO, GO, Node>;
7141 const crs_matrix_type* srcCrsMat =
7142 dynamic_cast<const crs_matrix_type*
> (&source);
7143 if (srcCrsMat !=
nullptr) {
7145 std::ostringstream os;
7146 os << *prefix <<
"Source matrix same (CrsMatrix) type as target; "
7147 "calling packNew" << endl;
7148 std::cerr << os.str ();
7151 srcCrsMat->packNew (exportLIDs, exports, numPacketsPerLID,
7152 constantNumPackets, distor);
7154 catch (std::exception& e) {
7156 msg <<
"Proc " << myRank <<
": " << e.what () << std::endl;
7160 using Kokkos::HostSpace;
7161 using Kokkos::subview;
7162 using exports_type = Kokkos::DualView<char*, buffer_device_type>;
7163 using range_type = Kokkos::pair<size_t, size_t>;
7166 std::ostringstream os;
7167 os << *prefix <<
"Source matrix NOT same (CrsMatrix) type as target"
7169 std::cerr << os.str ();
7172 using row_matrix_type = RowMatrix<Scalar, LO, GO, Node>;
7173 const row_matrix_type* srcRowMat =
7174 dynamic_cast<const row_matrix_type*
> (&source);
7175 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
7176 (srcRowMat ==
nullptr, std::invalid_argument,
7177 "The source object of the Import or Export operation is neither a "
7178 "CrsMatrix (with the same template parameters as the target object), "
7179 "nor a RowMatrix (with the same first four template parameters as the "
7190 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
7191 auto exportLIDs_h = exportLIDs.view_host ();
7192 Teuchos::ArrayView<const LO> exportLIDs_av (exportLIDs_h.data (),
7193 exportLIDs_h.size ());
7197 Teuchos::Array<char> exports_a;
7203 numPacketsPerLID.clear_sync_state ();
7204 numPacketsPerLID.modify_host ();
7205 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
7206 Teuchos::ArrayView<size_t> numPacketsPerLID_av (numPacketsPerLID_h.data (),
7207 numPacketsPerLID_h.size ());
7212 srcRowMat->pack (exportLIDs_av, exports_a, numPacketsPerLID_av,
7213 constantNumPackets, distor);
7215 catch (std::exception& e) {
7217 msg <<
"Proc " << myRank <<
": " << e.what () << std::endl;
7221 const size_t newAllocSize =
static_cast<size_t> (exports_a.size ());
7222 if (static_cast<size_t> (exports.extent (0)) < newAllocSize) {
7223 const std::string oldLabel = exports.d_view.label ();
7224 const std::string newLabel = (oldLabel ==
"") ?
"exports" : oldLabel;
7225 exports = exports_type (newLabel, newAllocSize);
7230 exports.modify_host();
7232 auto exports_h = exports.view_host ();
7233 auto exports_h_sub = subview (exports_h, range_type (0, newAllocSize));
7237 typedef typename exports_type::t_host::execution_space HES;
7238 typedef Kokkos::Device<HES, HostSpace> host_device_type;
7239 Kokkos::View<const char*, host_device_type>
7240 exports_a_kv (exports_a.getRawPtr (), newAllocSize);
7246 reduceAll<int, int> (comm, REDUCE_MAX, lclBad, outArg (gblBad));
7249 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
7250 (
true, std::logic_error,
"packNew() or pack() threw an exception on "
7251 "one or more participating processes.");
7255 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
7256 (lclBad != 0, std::logic_error,
"packNew threw an exception on one "
7257 "or more participating processes. Here is this process' error "
7258 "message: " << msg.str ());
7262 std::ostringstream os;
7263 os << *prefix <<
"packAndPrepare: Done!" << endl
7273 std::cerr << os.str ();
7277 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7279 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
7280 packRow (
char exports[],
7281 const size_t offset,
7282 const size_t numEnt,
7283 const GlobalOrdinal gidsIn[],
7284 const impl_scalar_type valsIn[],
7285 const size_t numBytesPerValue)
const
7288 using Kokkos::subview;
7290 typedef LocalOrdinal LO;
7291 typedef GlobalOrdinal GO;
7292 typedef impl_scalar_type ST;
7293 typedef typename View<int*, device_type>::HostMirror::execution_space HES;
7301 const LO numEntLO =
static_cast<size_t> (numEnt);
7303 const size_t numEntBeg = offset;
7304 const size_t numEntLen = PackTraits<LO, HES>::packValueCount (numEntLO);
7305 const size_t gidsBeg = numEntBeg + numEntLen;
7306 const size_t gidsLen = numEnt * PackTraits<GO, HES>::packValueCount (gid);
7307 const size_t valsBeg = gidsBeg + gidsLen;
7308 const size_t valsLen = numEnt * numBytesPerValue;
7310 char*
const numEntOut = exports + numEntBeg;
7311 char*
const gidsOut = exports + gidsBeg;
7312 char*
const valsOut = exports + valsBeg;
7314 size_t numBytesOut = 0;
7316 numBytesOut += PackTraits<LO, HES>::packValue (numEntOut, numEntLO);
7319 Kokkos::pair<int, size_t> p;
7320 p = PackTraits<GO, HES>::packArray (gidsOut, gidsIn, numEnt);
7321 errorCode += p.first;
7322 numBytesOut += p.second;
7324 p = PackTraits<ST, HES>::packArray (valsOut, valsIn, numEnt);
7325 errorCode += p.first;
7326 numBytesOut += p.second;
7329 const size_t expectedNumBytes = numEntLen + gidsLen + valsLen;
7330 TEUCHOS_TEST_FOR_EXCEPTION
7331 (numBytesOut != expectedNumBytes, std::logic_error,
"packRow: "
7332 "numBytesOut = " << numBytesOut <<
" != expectedNumBytes = "
7333 << expectedNumBytes <<
".");
7334 TEUCHOS_TEST_FOR_EXCEPTION
7335 (errorCode != 0, std::runtime_error,
"packRow: "
7336 "PackTraits::packArray returned a nonzero error code");
7341 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7343 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
7344 unpackRow (GlobalOrdinal gidsOut[],
7345 impl_scalar_type valsOut[],
7346 const char imports[],
7347 const size_t offset,
7348 const size_t numBytes,
7349 const size_t numEnt,
7350 const size_t numBytesPerValue)
7353 using Kokkos::subview;
7355 typedef LocalOrdinal LO;
7356 typedef GlobalOrdinal GO;
7357 typedef impl_scalar_type ST;
7358 typedef typename View<int*, device_type>::HostMirror::execution_space HES;
7360 if (numBytes == 0) {
7363 const int myRank = this->getMap ()->getComm ()->getRank ();
7364 TEUCHOS_TEST_FOR_EXCEPTION
7365 (
true, std::logic_error,
"(Proc " << myRank <<
") CrsMatrix::"
7366 "unpackRow: The number of bytes to unpack numBytes=0, but the "
7367 "number of entries to unpack (as reported by numPacketsPerLID) "
7368 "for this row numEnt=" << numEnt <<
" != 0.");
7373 if (numEnt == 0 && numBytes != 0) {
7374 const int myRank = this->getMap ()->getComm ()->getRank ();
7375 TEUCHOS_TEST_FOR_EXCEPTION
7376 (
true, std::logic_error,
"(Proc " << myRank <<
") CrsMatrix::"
7377 "unpackRow: The number of entries to unpack (as reported by "
7378 "numPacketsPerLID) numEnt=0, but the number of bytes to unpack "
7379 "numBytes=" << numBytes <<
" != 0.");
7385 const size_t numEntBeg = offset;
7386 const size_t numEntLen = PackTraits<LO, HES>::packValueCount (lid);
7387 const size_t gidsBeg = numEntBeg + numEntLen;
7388 const size_t gidsLen = numEnt * PackTraits<GO, HES>::packValueCount (gid);
7389 const size_t valsBeg = gidsBeg + gidsLen;
7390 const size_t valsLen = numEnt * numBytesPerValue;
7392 const char*
const numEntIn = imports + numEntBeg;
7393 const char*
const gidsIn = imports + gidsBeg;
7394 const char*
const valsIn = imports + valsBeg;
7396 size_t numBytesOut = 0;
7399 numBytesOut += PackTraits<LO, HES>::unpackValue (numEntOut, numEntIn);
7400 if (static_cast<size_t> (numEntOut) != numEnt ||
7401 numEntOut == static_cast<LO> (0)) {
7402 const int myRank = this->getMap ()->getComm ()->getRank ();
7403 std::ostringstream os;
7404 os <<
"(Proc " << myRank <<
") CrsMatrix::unpackRow: ";
7405 bool firstErrorCondition =
false;
7406 if (static_cast<size_t> (numEntOut) != numEnt) {
7407 os <<
"Number of entries from numPacketsPerLID numEnt=" << numEnt
7408 <<
" does not equal number of entries unpacked from imports "
7409 "buffer numEntOut=" << numEntOut <<
".";
7410 firstErrorCondition =
true;
7412 if (numEntOut == static_cast<LO> (0)) {
7413 if (firstErrorCondition) {
7416 os <<
"Number of entries unpacked from imports buffer numEntOut=0, "
7417 "but number of bytes to unpack for this row numBytes=" << numBytes
7418 <<
" != 0. This should never happen, since packRow should only "
7419 "ever pack rows with a nonzero number of entries. In this case, "
7420 "the number of entries from numPacketsPerLID is numEnt=" << numEnt
7423 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error, os.str ());
7427 Kokkos::pair<int, size_t> p;
7428 p = PackTraits<GO, HES>::unpackArray (gidsOut, gidsIn, numEnt);
7429 errorCode += p.first;
7430 numBytesOut += p.second;
7432 p = PackTraits<ST, HES>::unpackArray (valsOut, valsIn, numEnt);
7433 errorCode += p.first;
7434 numBytesOut += p.second;
7437 TEUCHOS_TEST_FOR_EXCEPTION
7438 (numBytesOut != numBytes, std::logic_error,
"unpackRow: numBytesOut = "
7439 << numBytesOut <<
" != numBytes = " << numBytes <<
".");
7441 const size_t expectedNumBytes = numEntLen + gidsLen + valsLen;
7442 TEUCHOS_TEST_FOR_EXCEPTION
7443 (numBytesOut != expectedNumBytes, std::logic_error,
"unpackRow: "
7444 "numBytesOut = " << numBytesOut <<
" != expectedNumBytes = "
7445 << expectedNumBytes <<
".");
7447 TEUCHOS_TEST_FOR_EXCEPTION
7448 (errorCode != 0, std::runtime_error,
"unpackRow: "
7449 "PackTraits::unpackArray returned a nonzero error code");
7454 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7456 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
7457 allocatePackSpaceNew (Kokkos::DualView<char*, buffer_device_type>& exports,
7458 size_t& totalNumEntries,
7459 const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& exportLIDs)
const
7463 typedef impl_scalar_type IST;
7464 typedef LocalOrdinal LO;
7465 typedef GlobalOrdinal GO;
7472 std::unique_ptr<std::string> prefix;
7475 auto map = this->getMap ();
7476 if (! map.is_null ()) {
7477 auto comm = map->getComm ();
7478 if (! comm.is_null ()) {
7479 myRank = comm->getRank ();
7483 prefix = [myRank] () {
7484 std::ostringstream pfxStrm;
7485 pfxStrm <<
"Proc " << myRank <<
": Tpetra::CrsMatrix::allocatePackSpaceNew: ";
7486 return std::unique_ptr<std::string> (
new std::string (pfxStrm.str ()));
7489 std::ostringstream os;
7490 os << *prefix <<
"Before:"
7498 std::cerr << os.str ();
7503 const LO numExportLIDs =
static_cast<LO
> (exportLIDs.extent (0));
7505 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
7506 auto exportLIDs_h = exportLIDs.view_host ();
7509 totalNumEntries = 0;
7510 for (LO i = 0; i < numExportLIDs; ++i) {
7511 const LO lclRow = exportLIDs_h[i];
7512 size_t curNumEntries = this->getNumEntriesInLocalRow (lclRow);
7515 if (curNumEntries == Teuchos::OrdinalTraits<size_t>::invalid ()) {
7518 totalNumEntries += curNumEntries;
7529 const size_t allocSize =
7530 static_cast<size_t> (numExportLIDs) *
sizeof (LO) +
7531 totalNumEntries * (
sizeof (IST) +
sizeof (GO));
7532 if (static_cast<size_t> (exports.extent (0)) < allocSize) {
7533 using exports_type = Kokkos::DualView<char*, buffer_device_type>;
7535 const std::string oldLabel = exports.d_view.label ();
7536 const std::string newLabel = (oldLabel ==
"") ?
"exports" : oldLabel;
7537 exports = exports_type (newLabel, allocSize);
7541 std::ostringstream os;
7542 os << *prefix <<
"After:"
7550 std::cerr << os.str ();
7554 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7557 packNew (
const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& exportLIDs,
7558 Kokkos::DualView<char*, buffer_device_type>& exports,
7559 const Kokkos::DualView<size_t*, buffer_device_type>& numPacketsPerLID,
7560 size_t& constantNumPackets,
7564 if (this->isStaticGraph ()) {
7565 using ::Tpetra::Details::packCrsMatrixNew;
7566 packCrsMatrixNew (*
this, exports, numPacketsPerLID, exportLIDs,
7567 constantNumPackets, dist);
7570 this->packNonStaticNew (exportLIDs, exports, numPacketsPerLID,
7571 constantNumPackets, dist);
7575 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7578 packNonStaticNew (
const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& exportLIDs,
7579 Kokkos::DualView<char*, buffer_device_type>& exports,
7580 const Kokkos::DualView<size_t*, buffer_device_type>& numPacketsPerLID,
7581 size_t& constantNumPackets,
7589 typedef LocalOrdinal LO;
7590 typedef GlobalOrdinal GO;
7591 typedef impl_scalar_type ST;
7592 typedef typename View<int*, device_type>::HostMirror::execution_space HES;
7593 const char tfecfFuncName[] =
"packNonStaticNew: ";
7599 std::unique_ptr<std::string> prefix;
7602 auto map = this->getMap ();
7603 if (! map.is_null ()) {
7604 auto comm = map->getComm ();
7605 if (! comm.is_null ()) {
7606 myRank = comm->getRank ();
7610 prefix = [myRank] () {
7611 std::ostringstream pfxStrm;
7612 pfxStrm <<
"(Proc " << myRank <<
") ";
7613 return std::unique_ptr<std::string> (
new std::string (pfxStrm.str ()));
7616 std::ostringstream os;
7617 os << *prefix <<
"Tpetra::CrsMatrix::packNonStaticNew:" << endl;
7618 std::cerr << os.str ();
7621 const size_t numExportLIDs =
static_cast<size_t> (exportLIDs.extent (0));
7622 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
7623 (numExportLIDs != static_cast<size_t> (numPacketsPerLID.extent (0)),
7624 std::invalid_argument,
"exportLIDs.size() = " << numExportLIDs
7625 <<
" != numPacketsPerLID.size() = " << numPacketsPerLID.extent (0)
7631 constantNumPackets = 0;
7636 size_t totalNumEntries = 0;
7637 this->allocatePackSpaceNew (exports, totalNumEntries, exportLIDs);
7638 const size_t bufSize =
static_cast<size_t> (exports.extent (0));
7641 exports.clear_sync_state();
7642 exports.modify_host();
7643 auto exports_h = exports.view_host ();
7645 std::ostringstream os;
7646 os << *prefix <<
"After marking exports as modified on host, "
7648 std::cerr << os.str ();
7652 auto exportLIDs_h = exportLIDs.view_host ();
7655 const_cast<Kokkos::DualView<size_t*, buffer_device_type>*
>(&numPacketsPerLID)->clear_sync_state();
7656 const_cast<Kokkos::DualView<size_t*, buffer_device_type>*
>(&numPacketsPerLID)->modify_host();
7657 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
7663 for (
size_t i = 0; i < numExportLIDs; ++i) {
7664 const LO lclRow = exportLIDs_h[i];
7667 numEnt = this->getNumEntriesInLocalRow (lclRow);
7674 numPacketsPerLID_h[i] = 0;
7679 View<GO*, HES> gidsIn_k;
7682 gidsIn_k = PackTraits<GO, HES>::allocateArray(gid, numEnt,
"gids");
7685 Teuchos::ArrayView<const Scalar> valsIn;
7686 if (this->isLocallyIndexed ()) {
7690 Teuchos::ArrayView<const LO> lidsIn;
7691 this->getLocalRowView (lclRow, lidsIn, valsIn);
7692 const map_type& colMap = * (this->getColMap ());
7693 for (
size_t k = 0; k < numEnt; ++k) {
7694 gidsIn_k[k] = colMap.getGlobalElement (lidsIn[k]);
7697 else if (this->isGloballyIndexed ()) {
7703 Teuchos::ArrayView<const GO> gblIndView;;
7704 const map_type& rowMap = * (this->getRowMap ());
7705 const GO gblRow = rowMap.getGlobalElement (lclRow);
7706 this->getGlobalRowView (gblRow, gblIndView, valsIn);
7707 for (
size_t k = 0; k < numEnt; ++k) {
7708 gidsIn_k[k] = gblIndView[k];
7715 typename HES::device_type outputDevice;
7718 reinterpret_cast<const ST*> (valsIn.getRawPtr ()),
7721 const size_t numBytesPerValue =
7722 PackTraits<ST,HES>::packValueCount (valsIn[0]);
7723 const size_t numBytes =
7724 this->packRow (exports_h.data (), offset, numEnt, gidsIn_k.data (),
7725 valsIn_k.data (), numBytesPerValue);
7726 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
7727 (offset > bufSize || offset + numBytes > bufSize, std::logic_error,
7728 "First invalid offset into 'exports' pack buffer at index i = " << i
7729 <<
". exportLIDs_h[i]: " << exportLIDs_h[i] <<
", bufSize: " <<
7730 bufSize <<
", offset: " << offset <<
", numBytes: " << numBytes <<
7735 numPacketsPerLID_h[i] = numBytes;
7740 std::ostringstream os;
7741 os << *prefix <<
"Tpetra::CrsMatrix::packNonStaticNew: After:" << endl
7748 std::cerr << os.str ();
7752 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7754 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
7755 combineGlobalValuesRaw (
const LocalOrdinal lclRow,
7756 const LocalOrdinal numEnt,
7757 const impl_scalar_type vals[],
7758 const GlobalOrdinal cols[],
7761 typedef GlobalOrdinal GO;
7766 const GO gblRow = this->myGraph_->rowMap_->getGlobalElement (lclRow);
7767 Teuchos::ArrayView<const GO> cols_av (numEnt == 0 ? NULL : cols, numEnt);
7768 Teuchos::ArrayView<const Scalar> vals_av (numEnt == 0 ? NULL : reinterpret_cast<const Scalar*> (vals), numEnt);
7773 this->combineGlobalValues (gblRow, cols_av, vals_av, combineMode);
7777 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7779 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
7780 combineGlobalValues (
const GlobalOrdinal globalRowIndex,
7781 const Teuchos::ArrayView<const GlobalOrdinal>& columnIndices,
7782 const Teuchos::ArrayView<const Scalar>& values,
7785 const char tfecfFuncName[] =
"combineGlobalValues: ";
7787 if (isStaticGraph ()) {
7791 if (combineMode ==
ADD) {
7792 sumIntoGlobalValues (globalRowIndex, columnIndices, values);
7794 else if (combineMode ==
REPLACE) {
7795 replaceGlobalValues (globalRowIndex, columnIndices, values);
7797 else if (combineMode ==
ABSMAX) {
7798 using ::Tpetra::Details::AbsMax;
7800 this->
template transformGlobalValues<AbsMax<Scalar> > (globalRowIndex,
7804 else if (combineMode ==
INSERT) {
7805 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
7806 isStaticGraph () && combineMode ==
INSERT, std::invalid_argument,
7807 "INSERT combine mode is not allowed if the matrix has a static graph "
7808 "(i.e., was constructed with the CrsMatrix constructor that takes a "
7809 "const CrsGraph pointer).");
7812 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
7813 true, std::logic_error,
"Invalid combine mode; should never get "
7814 "here! Please report this bug to the Tpetra developers.");
7818 if (combineMode ==
ADD || combineMode ==
INSERT) {
7826 this->insertGlobalValuesFiltered (globalRowIndex, columnIndices,
7829 catch (std::exception& e) {
7830 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
7831 (
true, std::runtime_error, std::endl
7832 <<
"insertGlobalValuesFiltered(" << globalRowIndex <<
", "
7833 << std::endl << Teuchos::toString (columnIndices) <<
", "
7834 << std::endl << Teuchos::toString (values)
7835 <<
") threw an exception: " << std::endl << e.what ());
7847 else if (combineMode ==
ABSMAX) {
7848 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
7849 ! isStaticGraph () && combineMode ==
ABSMAX, std::logic_error,
7850 "ABSMAX combine mode when the matrix has a dynamic graph is not yet "
7853 else if (combineMode ==
REPLACE) {
7854 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
7855 ! isStaticGraph () && combineMode ==
REPLACE, std::logic_error,
7856 "REPLACE combine mode when the matrix has a dynamic graph is not yet "
7860 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
7861 true, std::logic_error,
"Should never get here! Please report this "
7862 "bug to the Tpetra developers.");
7867 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
7869 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
7870 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
7872 #else // TPETRA_ENABLE_DEPRECATED_CODE
7874 #endif // TPETRA_ENABLE_DEPRECATED_CODE
7875 (
const Kokkos::DualView<const local_ordinal_type*, buffer_device_type>& importLIDs,
7876 Kokkos::DualView<char*, buffer_device_type> imports,
7877 Kokkos::DualView<size_t*, buffer_device_type> numPacketsPerLID,
7878 const size_t constantNumPackets,
7879 Distributor& distor,
7885 const char tfecfFuncName[] =
"unpackAndCombine: ";
7886 ProfilingRegion regionUAC (
"Tpetra::CrsMatrix::unpackAndCombine");
7890 constexpr
int numValidModes = 5;
7893 const char* validModeNames[numValidModes] =
7894 {
"ADD",
"REPLACE",
"ABSMAX",
"INSERT",
"ZERO"};
7896 std::unique_ptr<std::string> prefix;
7899 auto map = this->getMap ();
7900 if (! map.is_null ()) {
7901 auto comm = map->getComm ();
7902 if (! comm.is_null ()) {
7903 myRank = comm->getRank ();
7906 prefix = [myRank] () {
7907 std::ostringstream pfxStrm;
7908 pfxStrm <<
"Proc " << myRank <<
": Tpetra::CrsMatrix::unpackAndCombine: ";
7909 return std::unique_ptr<std::string> (
new std::string (pfxStrm.str ()));
7911 std::ostringstream os;
7912 os << *prefix <<
"Start:" << endl
7922 << *prefix <<
" constantNumPackets: " << constantNumPackets
7926 std::cerr << os.str ();
7930 if (std::find (validModes, validModes+numValidModes, combineMode) ==
7931 validModes+numValidModes) {
7932 std::ostringstream os;
7933 os <<
"Invalid combine mode. Valid modes are {";
7934 for (
int k = 0; k < numValidModes; ++k) {
7935 os << validModeNames[k];
7936 if (k < numValidModes - 1) {
7941 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
7942 (
true, std::invalid_argument, os.str ());
7946 if (combineMode ==
ZERO) {
7950 if (!this->isStaticGraph() && this->getProfileType() == StaticProfile) {
7951 auto padding = myGraph_->computeCrsPadding(importLIDs, numPacketsPerLID);
7952 if (padding.size() > 0)
7953 this->applyCrsPadding(padding);
7957 using Teuchos::reduceAll;
7958 std::unique_ptr<std::ostringstream> msg (
new std::ostringstream ());
7961 this->unpackAndCombineImpl (importLIDs, imports, numPacketsPerLID,
7962 constantNumPackets, distor, combineMode);
7963 }
catch (std::exception& e) {
7968 const Teuchos::Comm<int>& comm = * (this->getComm ());
7969 reduceAll<int, int> (comm, Teuchos::REDUCE_MAX,
7970 lclBad, Teuchos::outArg (gblBad));
7976 std::ostringstream os;
7977 os <<
"(Proc " << comm.getRank () <<
") " << msg->str () << endl;
7978 msg = std::unique_ptr<std::ostringstream> (
new std::ostringstream ());
7979 ::Tpetra::Details::gathervPrint (*msg, os.str (), comm);
7980 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
7981 (
true, std::logic_error, std::endl <<
"unpackAndCombineImpl "
7982 "threw an exception on one or more participating processes: "
7983 << endl << msg->str ());
7987 this->unpackAndCombineImpl (importLIDs, imports, numPacketsPerLID,
7988 constantNumPackets, distor, combineMode);
7992 std::ostringstream os;
7993 os << *prefix <<
"Done!" << endl
8003 std::cerr << os.str ();
8007 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
8009 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
8010 unpackAndCombineImpl (
const Kokkos::DualView<
const local_ordinal_type*,
8011 buffer_device_type>& importLIDs,
8012 const Kokkos::DualView<
const char*,
8013 buffer_device_type>& imports,
8014 const Kokkos::DualView<
const size_t*,
8015 buffer_device_type>& numPacketsPerLID,
8016 const size_t constantNumPackets,
8017 Distributor & distor,
8023 if (this->isStaticGraph ()) {
8024 using ::Tpetra::Details::unpackCrsMatrixAndCombineNew;
8025 unpackCrsMatrixAndCombineNew (*
this, imports, numPacketsPerLID,
8026 importLIDs, constantNumPackets,
8027 distor, combineMode, atomic);
8030 this->unpackAndCombineImplNonStatic (importLIDs, imports,
8033 distor, combineMode);
8037 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
8039 CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
8040 unpackAndCombineImplNonStatic (
const Kokkos::DualView<
const local_ordinal_type*,
8041 buffer_device_type>& importLIDs,
8042 const Kokkos::DualView<
const char*,
8043 buffer_device_type>& imports,
8044 const Kokkos::DualView<
const size_t*,
8045 buffer_device_type>& numPacketsPerLID,
8051 using Kokkos::subview;
8052 using Kokkos::MemoryUnmanaged;
8057 typedef LocalOrdinal LO;
8058 typedef GlobalOrdinal GO;
8059 typedef impl_scalar_type ST;
8060 typedef typename Teuchos::ArrayView<const LO>::size_type size_type;
8061 typedef typename View<int*, device_type>::HostMirror::execution_space HES;
8062 typedef std::pair<typename View<int*, HES>::size_type,
8063 typename View<int*, HES>::size_type> pair_type;
8064 typedef View<GO*, HES, MemoryUnmanaged> gids_out_type;
8065 typedef View<ST*, HES, MemoryUnmanaged> vals_out_type;
8066 const char tfecfFuncName[] =
"unpackAndCombineImplNonStatic: ";
8072 std::unique_ptr<std::string> prefix;
8075 auto map = this->getMap ();
8076 if (! map.is_null ()) {
8077 auto comm = map->getComm ();
8078 if (! comm.is_null ()) {
8079 myRank = comm->getRank ();
8083 prefix = [myRank] () {
8084 std::ostringstream pfxStrm;
8085 pfxStrm <<
"Proc " << myRank <<
": Tpetra::CrsMatrix::"
8086 "unpackAndCombineImplNonStatic: ";
8087 return std::unique_ptr<std::string> (
new std::string (pfxStrm.str ()));
8090 std::ostringstream os;
8091 os << *prefix << endl;
8092 std::cerr << os.str ();
8095 const size_type numImportLIDs = importLIDs.extent (0);
8096 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
8097 (numImportLIDs != static_cast<size_type> (numPacketsPerLID.extent (0)),
8098 std::invalid_argument,
"importLIDs.size() = " << numImportLIDs
8099 <<
" != numPacketsPerLID.size() = " << numPacketsPerLID.extent (0)
8101 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
8103 combineMode !=
ABSMAX && combineMode !=
ZERO, std::invalid_argument,
8104 "Invalid CombineMode value " << combineMode <<
". Valid "
8105 <<
"values include ADD, INSERT, REPLACE, ABSMAX, and ZERO.");
8106 if (combineMode ==
ZERO || numImportLIDs == 0) {
8113 imports_nc.sync_host ();
8115 auto imports_h = imports.view_host ();
8120 numPacketsPerLID_nc.sync_host ();
8122 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
8124 TEUCHOS_ASSERT( ! importLIDs.need_sync_host () );
8125 auto importLIDs_h = importLIDs.view_host ();
8127 size_t numBytesPerValue;
8138 numBytesPerValue = PackTraits<ST, HES>::packValueCount (val);
8143 size_t maxRowNumEnt = 0;
8144 for (size_type i = 0; i < numImportLIDs; ++i) {
8145 const size_t numBytes = numPacketsPerLID_h[i];
8146 if (numBytes == 0) {
8150 #ifdef HAVE_TPETRA_DEBUG
8151 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
8152 (offset + numBytes > static_cast<size_t> (imports_h.extent (0)),
8153 std::logic_error,
"At local row index importLIDs_h[i=" << i <<
"]="
8154 << importLIDs_h[i] <<
", offset (=" << offset <<
") + numBytes (="
8155 << numBytes <<
") > imports_h.extent(0)="
8156 << imports_h.extent (0) <<
".");
8157 #endif // HAVE_TPETRA_DEBUG
8161 #ifdef HAVE_TPETRA_DEBUG
8162 const size_t theNumBytes = PackTraits<LO, HES>::packValueCount (numEntLO);
8163 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
8164 (theNumBytes > numBytes, std::logic_error,
"theNumBytes = "
8165 << theNumBytes <<
" > numBytes = " << numBytes <<
".");
8166 #endif // HAVE_TPETRA_DEBUG
8168 const char*
const inBuf = imports_h.data () + offset;
8169 const size_t actualNumBytes =
8170 PackTraits<LO, HES>::unpackValue (numEntLO, inBuf);
8172 #ifdef HAVE_TPETRA_DEBUG
8173 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
8174 (actualNumBytes > numBytes, std::logic_error,
"At i = " << i
8175 <<
", actualNumBytes=" << actualNumBytes
8176 <<
" > numBytes=" << numBytes <<
".");
8177 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
8178 (numEntLO == 0, std::logic_error,
"At local row index importLIDs_h[i="
8179 << i <<
"]=" << importLIDs_h[i] <<
", the number of entries read "
8180 "from the packed data is numEntLO=" << numEntLO <<
", but numBytes="
8181 << numBytes <<
" != 0.");
8183 (void) actualNumBytes;
8184 #endif // HAVE_TPETRA_DEBUG
8186 maxRowNumEnt = std::max (static_cast<size_t> (numEntLO), maxRowNumEnt);
8194 View<GO*, HES> gblColInds;
8195 View<LO*, HES> lclColInds;
8196 View<ST*, HES> vals;
8209 gblColInds = PackTraits<GO, HES>::allocateArray (gid, maxRowNumEnt,
"gids");
8210 lclColInds = PackTraits<LO, HES>::allocateArray (lid, maxRowNumEnt,
"lids");
8211 vals = PackTraits<ST, HES>::allocateArray (val, maxRowNumEnt,
"vals");
8215 for (size_type i = 0; i < numImportLIDs; ++i) {
8216 const size_t numBytes = numPacketsPerLID_h[i];
8217 if (numBytes == 0) {
8221 const char*
const inBuf = imports_h.data () + offset;
8222 const size_t actualNumBytes = PackTraits<LO, HES>::unpackValue (numEntLO, inBuf);
8223 (void) actualNumBytes;
8225 const size_t numEnt =
static_cast<size_t>(numEntLO);;
8226 const LO lclRow = importLIDs_h[i];
8228 gids_out_type gidsOut = subview (gblColInds, pair_type (0, numEnt));
8229 vals_out_type valsOut = subview (vals, pair_type (0, numEnt));
8231 const size_t numBytesOut =
8232 unpackRow (gidsOut.data (), valsOut.data (), imports_h.data (),
8233 offset, numBytes, numEnt, numBytesPerValue);
8234 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
8235 (numBytes != numBytesOut, std::logic_error,
"At i = " << i <<
", "
8236 <<
"numBytes = " << numBytes <<
" != numBytesOut = " << numBytesOut
8239 const ST*
const valsRaw =
const_cast<const ST*
> (valsOut.data ());
8240 const GO*
const gidsRaw =
const_cast<const GO*
> (gidsOut.data ());
8241 this->combineGlobalValuesRaw (lclRow, numEnt, valsRaw, gidsRaw, combineMode);
8248 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
8249 Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
8252 const bool force)
const
8254 using Teuchos::null;
8258 TEUCHOS_TEST_FOR_EXCEPTION(
8259 ! this->hasColMap (), std::runtime_error,
"Tpetra::CrsMatrix::getColumn"
8260 "MapMultiVector: You may only call this method if the matrix has a "
8261 "column Map. If the matrix does not yet have a column Map, you should "
8262 "first call fillComplete (with domain and range Map if necessary).");
8266 TEUCHOS_TEST_FOR_EXCEPTION(
8267 ! this->getGraph ()->isFillComplete (), std::runtime_error,
"Tpetra::"
8268 "CrsMatrix::getColumnMapMultiVector: You may only call this method if "
8269 "this matrix's graph is fill complete.");
8272 RCP<const import_type> importer = this->getGraph ()->getImporter ();
8273 RCP<const map_type> colMap = this->getColMap ();
8286 if (! importer.is_null () || force) {
8287 if (importMV_.is_null () || importMV_->getNumVectors () != numVecs) {
8288 X_colMap = rcp (
new MV (colMap, numVecs));
8291 importMV_ = X_colMap;
8294 X_colMap = importMV_;
8305 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
8306 Teuchos::RCP<MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
8309 const bool force)
const
8311 using Teuchos::null;
8317 TEUCHOS_TEST_FOR_EXCEPTION(
8318 ! this->getGraph ()->isFillComplete (), std::runtime_error,
"Tpetra::"
8319 "CrsMatrix::getRowMapMultiVector: You may only call this method if this "
8320 "matrix's graph is fill complete.");
8323 RCP<const export_type> exporter = this->getGraph ()->getExporter ();
8327 RCP<const map_type> rowMap = this->getRowMap ();
8339 if (! exporter.is_null () || force) {
8340 if (exportMV_.is_null () || exportMV_->getNumVectors () != numVecs) {
8341 Y_rowMap = rcp (
new MV (rowMap, numVecs));
8342 exportMV_ = Y_rowMap;
8345 Y_rowMap = exportMV_;
8351 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
8356 TEUCHOS_TEST_FOR_EXCEPTION(
8357 myGraph_.is_null (), std::logic_error,
"Tpetra::CrsMatrix::"
8358 "removeEmptyProcessesInPlace: This method does not work when the matrix "
8359 "was created with a constant graph (that is, when it was created using "
8360 "the version of its constructor that takes an RCP<const CrsGraph>). "
8361 "This is because the matrix is not allowed to modify the graph in that "
8362 "case, but removing empty processes requires modifying the graph.");
8363 myGraph_->removeEmptyProcessesInPlace (newMap);
8367 this->map_ = this->getRowMap ();
8371 staticGraph_ = Teuchos::rcp_const_cast<
const Graph> (myGraph_);
8374 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
8375 Teuchos::RCP<RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
8380 const Teuchos::RCP<const map_type>& domainMap,
8381 const Teuchos::RCP<const map_type>& rangeMap,
8382 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
8384 using Teuchos::Array;
8385 using Teuchos::ArrayView;
8386 using Teuchos::ParameterList;
8389 using Teuchos::rcp_implicit_cast;
8390 using Teuchos::sublist;
8391 typedef LocalOrdinal LO;
8392 typedef GlobalOrdinal GO;
8396 const crs_matrix_type& B = *
this;
8397 const Scalar
ZERO = Teuchos::ScalarTraits<Scalar>::zero ();
8398 const Scalar ONE = Teuchos::ScalarTraits<Scalar>::one ();
8405 RCP<const map_type> A_rangeMap = A.
getRangeMap ();
8406 RCP<const map_type> B_domainMap = B.getDomainMap ();
8407 RCP<const map_type> B_rangeMap = B.getRangeMap ();
8409 RCP<const map_type> theDomainMap = domainMap;
8410 RCP<const map_type> theRangeMap = rangeMap;
8412 if (domainMap.is_null ()) {
8413 if (B_domainMap.is_null ()) {
8414 TEUCHOS_TEST_FOR_EXCEPTION(
8415 A_domainMap.is_null (), std::invalid_argument,
8416 "Tpetra::CrsMatrix::add: If neither A nor B have a domain Map, "
8417 "then you must supply a nonnull domain Map to this method.");
8418 theDomainMap = A_domainMap;
8420 theDomainMap = B_domainMap;
8423 if (rangeMap.is_null ()) {
8424 if (B_rangeMap.is_null ()) {
8425 TEUCHOS_TEST_FOR_EXCEPTION(
8426 A_rangeMap.is_null (), std::invalid_argument,
8427 "Tpetra::CrsMatrix::add: If neither A nor B have a range Map, "
8428 "then you must supply a nonnull range Map to this method.");
8429 theRangeMap = A_rangeMap;
8431 theRangeMap = B_rangeMap;
8435 #ifdef HAVE_TPETRA_DEBUG
8439 if (! A_domainMap.is_null () && ! A_rangeMap.is_null ()) {
8440 if (! B_domainMap.is_null () && ! B_rangeMap.is_null ()) {
8441 TEUCHOS_TEST_FOR_EXCEPTION(
8442 ! B_domainMap->isSameAs (*A_domainMap), std::invalid_argument,
8443 "Tpetra::CrsMatrix::add: The input RowMatrix A must have a domain Map "
8444 "which is the same as (isSameAs) this RowMatrix's domain Map.");
8445 TEUCHOS_TEST_FOR_EXCEPTION(
8446 ! B_rangeMap->isSameAs (*A_rangeMap), std::invalid_argument,
8447 "Tpetra::CrsMatrix::add: The input RowMatrix A must have a range Map "
8448 "which is the same as (isSameAs) this RowMatrix's range Map.");
8449 TEUCHOS_TEST_FOR_EXCEPTION(
8450 ! domainMap.is_null () && ! domainMap->isSameAs (*B_domainMap),
8451 std::invalid_argument,
8452 "Tpetra::CrsMatrix::add: The input domain Map must be the same as "
8453 "(isSameAs) this RowMatrix's domain Map.");
8454 TEUCHOS_TEST_FOR_EXCEPTION(
8455 ! rangeMap.is_null () && ! rangeMap->isSameAs (*B_rangeMap),
8456 std::invalid_argument,
8457 "Tpetra::CrsMatrix::add: The input range Map must be the same as "
8458 "(isSameAs) this RowMatrix's range Map.");
8461 else if (! B_domainMap.is_null () && ! B_rangeMap.is_null ()) {
8462 TEUCHOS_TEST_FOR_EXCEPTION(
8463 ! domainMap.is_null () && ! domainMap->isSameAs (*B_domainMap),
8464 std::invalid_argument,
8465 "Tpetra::CrsMatrix::add: The input domain Map must be the same as "
8466 "(isSameAs) this RowMatrix's domain Map.");
8467 TEUCHOS_TEST_FOR_EXCEPTION(
8468 ! rangeMap.is_null () && ! rangeMap->isSameAs (*B_rangeMap),
8469 std::invalid_argument,
8470 "Tpetra::CrsMatrix::add: The input range Map must be the same as "
8471 "(isSameAs) this RowMatrix's range Map.");
8474 TEUCHOS_TEST_FOR_EXCEPTION(
8475 domainMap.is_null () || rangeMap.is_null (), std::invalid_argument,
8476 "Tpetra::CrsMatrix::add: If neither A nor B have a domain and range "
8477 "Map, then you must supply a nonnull domain and range Map to this "
8480 #endif // HAVE_TPETRA_DEBUG
8485 bool callFillComplete =
true;
8486 RCP<ParameterList> constructorSublist;
8487 RCP<ParameterList> fillCompleteSublist;
8488 if (! params.is_null ()) {
8489 callFillComplete = params->get (
"Call fillComplete", callFillComplete);
8490 constructorSublist = sublist (params,
"Constructor parameters");
8491 fillCompleteSublist = sublist (params,
"fillComplete parameters");
8494 RCP<const map_type> A_rowMap = A.
getRowMap ();
8495 RCP<const map_type> B_rowMap = B.getRowMap ();
8496 RCP<const map_type> C_rowMap = B_rowMap;
8497 RCP<crs_matrix_type> C;
8504 if (A_rowMap->isSameAs (*B_rowMap)) {
8505 const LO localNumRows =
static_cast<LO
> (A_rowMap->getNodeNumElements ());
8506 Array<size_t> C_maxNumEntriesPerRow (localNumRows, 0);
8509 if (alpha != ZERO) {
8510 for (LO localRow = 0; localRow < localNumRows; ++localRow) {
8512 C_maxNumEntriesPerRow[localRow] += A_numEntries;
8517 for (LO localRow = 0; localRow < localNumRows; ++localRow) {
8518 const size_t B_numEntries = B.getNumEntriesInLocalRow (localRow);
8519 C_maxNumEntriesPerRow[localRow] += B_numEntries;
8523 if (constructorSublist.is_null ()) {
8524 C = rcp (
new crs_matrix_type (C_rowMap, C_maxNumEntriesPerRow (),
8527 C = rcp (
new crs_matrix_type (C_rowMap, C_maxNumEntriesPerRow (),
8528 StaticProfile, constructorSublist));
8538 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
8539 if (constructorSublist.is_null ()) {
8540 C = rcp (
new crs_matrix_type (C_rowMap, 0,
ProfileType(StaticProfile+1) ));
8542 C = rcp (
new crs_matrix_type (C_rowMap, 0,
ProfileType(StaticProfile+1) ,
8543 constructorSublist));
8547 TEUCHOS_TEST_FOR_EXCEPTION(
true,
8548 std::invalid_argument,
8549 "Tpetra::CrsMatrix::add: The row maps must be the same for statically "
8550 "allocated matrices in order to be sure that there is sufficient space "
8551 "to do the addition");
8556 #ifdef HAVE_TPETRA_DEBUG
8557 TEUCHOS_TEST_FOR_EXCEPTION(C.is_null (), std::logic_error,
8558 "Tpetra::RowMatrix::add: C should not be null at this point. "
8559 "Please report this bug to the Tpetra developers.");
8560 #endif // HAVE_TPETRA_DEBUG
8567 if (alpha != ZERO) {
8568 const LO A_localNumRows =
static_cast<LO
> (A_rowMap->getNodeNumElements ());
8569 for (LO localRow = 0; localRow < A_localNumRows; ++localRow) {
8571 const GO globalRow = A_rowMap->getGlobalElement (localRow);
8572 if (A_numEntries > static_cast<size_t> (ind.size ())) {
8573 ind.resize (A_numEntries);
8574 val.resize (A_numEntries);
8576 ArrayView<GO> indView = ind (0, A_numEntries);
8577 ArrayView<Scalar> valView = val (0, A_numEntries);
8581 for (
size_t k = 0; k < A_numEntries; ++k) {
8582 valView[k] *= alpha;
8585 C->insertGlobalValues (globalRow, indView, valView);
8590 const LO B_localNumRows =
static_cast<LO
> (B_rowMap->getNodeNumElements ());
8591 for (LO localRow = 0; localRow < B_localNumRows; ++localRow) {
8592 size_t B_numEntries = B.getNumEntriesInLocalRow (localRow);
8593 const GO globalRow = B_rowMap->getGlobalElement (localRow);
8594 if (B_numEntries > static_cast<size_t> (ind.size ())) {
8595 ind.resize (B_numEntries);
8596 val.resize (B_numEntries);
8598 ArrayView<GO> indView = ind (0, B_numEntries);
8599 ArrayView<Scalar> valView = val (0, B_numEntries);
8600 B.getGlobalRowCopy (globalRow, indView, valView, B_numEntries);
8603 for (
size_t k = 0; k < B_numEntries; ++k) {
8607 C->insertGlobalValues (globalRow, indView, valView);
8611 if (callFillComplete) {
8612 if (fillCompleteSublist.is_null ()) {
8613 C->fillComplete (theDomainMap, theRangeMap);
8615 C->fillComplete (theDomainMap, theRangeMap, fillCompleteSublist);
8618 return rcp_implicit_cast<row_matrix_type> (C);
8623 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
8627 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& rowTransfer,
8628 const Teuchos::RCP<const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node> > & domainTransfer,
8629 const Teuchos::RCP<const map_type>& domainMap,
8630 const Teuchos::RCP<const map_type>& rangeMap,
8631 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
8637 using Teuchos::ArrayRCP;
8638 using Teuchos::ArrayView;
8639 using Teuchos::Comm;
8640 using Teuchos::ParameterList;
8642 typedef LocalOrdinal LO;
8643 typedef GlobalOrdinal GO;
8644 typedef node_type NT;
8651 int MyPID = getComm ()->getRank ();
8653 std::unique_ptr<std::string> verbosePrefix;
8655 std::ostringstream os;
8656 os <<
"Proc " << MyPID <<
": transferAndFillComplete: ";
8657 verbosePrefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
8659 os <<
"start" << std::endl;
8660 std::cerr << os.str ();
8667 bool reverseMode =
false;
8668 bool restrictComm =
false;
8671 RCP<ParameterList> matrixparams;
8672 bool overrideAllreduce =
false;
8673 if (! params.is_null ()) {
8674 matrixparams = sublist (params,
"CrsMatrix");
8675 reverseMode = params->get (
"Reverse Mode", reverseMode);
8676 restrictComm = params->get (
"Restrict Communicator", restrictComm);
8677 auto & slist = params->sublist(
"matrixmatrix: kernel params",
false);
8678 isMM = slist.get(
"isMatrixMatrix_TransferAndFillComplete",
false);
8679 mm_optimization_core_count = slist.get(
"MM_TAFC_OptimizationCoreCount",mm_optimization_core_count);
8681 overrideAllreduce = slist.get(
"MM_TAFC_OverrideAllreduceCheck",
false);
8682 if(getComm()->getSize() < mm_optimization_core_count && isMM) isMM =
false;
8683 if(reverseMode) isMM =
false;
8687 std::shared_ptr< ::Tpetra::Details::CommRequest> iallreduceRequest;
8689 int reduced_mismatch = 0;
8690 if (isMM && !overrideAllreduce) {
8693 const bool source_vals = ! getGraph ()->getImporter ().is_null();
8694 const bool target_vals = ! (rowTransfer.getExportLIDs ().size() == 0 ||
8695 rowTransfer.getRemoteLIDs ().size() == 0);
8696 mismatch = (source_vals != target_vals) ? 1 : 0;
8699 Teuchos::REDUCE_MAX, * (getComm ()));
8702 #ifdef HAVE_TPETRA_MMM_TIMINGS
8703 using Teuchos::TimeMonitor;
8705 if(!params.is_null())
8706 label = params->get(
"Timer Label",label);
8707 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
": ");
8710 std::ostringstream os;
8711 if(isMM) os<<
":MMOpt";
8712 else os<<
":MMLegacy";
8716 Teuchos::TimeMonitor MMall(*TimeMonitor::getNewTimer(prefix + std::string(
"TAFC All") +tlstr ));
8724 const import_type* xferAsImport =
dynamic_cast<const import_type*
> (&rowTransfer);
8725 const export_type* xferAsExport =
dynamic_cast<const export_type*
> (&rowTransfer);
8726 TEUCHOS_TEST_FOR_EXCEPTION(
8727 xferAsImport == NULL && xferAsExport == NULL, std::invalid_argument,
8728 "Tpetra::CrsMatrix::transferAndFillComplete: The 'rowTransfer' input "
8729 "argument must be either an Import or an Export, and its template "
8730 "parameters must match the corresponding template parameters of the "
8738 Teuchos::RCP<const import_type> xferDomainAsImport = Teuchos::rcp_dynamic_cast<
const import_type> (domainTransfer);
8739 Teuchos::RCP<const export_type> xferDomainAsExport = Teuchos::rcp_dynamic_cast<
const export_type> (domainTransfer);
8741 if(! domainTransfer.is_null()) {
8742 TEUCHOS_TEST_FOR_EXCEPTION(
8743 (xferDomainAsImport.is_null() && xferDomainAsExport.is_null()), std::invalid_argument,
8744 "Tpetra::CrsMatrix::transferAndFillComplete: The 'domainTransfer' input "
8745 "argument must be either an Import or an Export, and its template "
8746 "parameters must match the corresponding template parameters of the "
8749 TEUCHOS_TEST_FOR_EXCEPTION(
8750 ( xferAsImport != NULL || ! xferDomainAsImport.is_null() ) &&
8751 (( xferAsImport != NULL && xferDomainAsImport.is_null() ) ||
8752 ( xferAsImport == NULL && ! xferDomainAsImport.is_null() )), std::invalid_argument,
8753 "Tpetra::CrsMatrix::transferAndFillComplete: The 'rowTransfer' and 'domainTransfer' input "
8754 "arguments must be of the same type (either Import or Export).");
8756 TEUCHOS_TEST_FOR_EXCEPTION(
8757 ( xferAsExport != NULL || ! xferDomainAsExport.is_null() ) &&
8758 (( xferAsExport != NULL && xferDomainAsExport.is_null() ) ||
8759 ( xferAsExport == NULL && ! xferDomainAsExport.is_null() )), std::invalid_argument,
8760 "Tpetra::CrsMatrix::transferAndFillComplete: The 'rowTransfer' and 'domainTransfer' input "
8761 "arguments must be of the same type (either Import or Export).");
8767 const bool communication_needed = rowTransfer.getSourceMap ()->isDistributed ();
8771 RCP<const map_type> MyRowMap = reverseMode ?
8772 rowTransfer.getSourceMap () : rowTransfer.getTargetMap ();
8773 RCP<const map_type> MyColMap;
8774 RCP<const map_type> MyDomainMap = ! domainMap.is_null () ?
8775 domainMap : getDomainMap ();
8776 RCP<const map_type> MyRangeMap = ! rangeMap.is_null () ?
8777 rangeMap : getRangeMap ();
8778 RCP<const map_type> BaseRowMap = MyRowMap;
8779 RCP<const map_type> BaseDomainMap = MyDomainMap;
8787 if (! destMat.is_null ()) {
8798 const bool NewFlag = ! destMat->getGraph ()->isLocallyIndexed () &&
8799 ! destMat->getGraph ()->isGloballyIndexed ();
8800 TEUCHOS_TEST_FOR_EXCEPTION(
8801 ! NewFlag, std::invalid_argument,
"Tpetra::CrsMatrix::"
8802 "transferAndFillComplete: The input argument 'destMat' is only allowed "
8803 "to be nonnull, if its graph is empty (neither locally nor globally "
8812 TEUCHOS_TEST_FOR_EXCEPTION(
8813 ! destMat->getRowMap ()->isSameAs (*MyRowMap), std::invalid_argument,
8814 "Tpetra::CrsMatrix::transferAndFillComplete: The (row) Map of the "
8815 "input argument 'destMat' is not the same as the (row) Map specified "
8816 "by the input argument 'rowTransfer'.");
8817 TEUCHOS_TEST_FOR_EXCEPTION(
8818 ! destMat->checkSizes (*
this), std::invalid_argument,
8819 "Tpetra::CrsMatrix::transferAndFillComplete: You provided a nonnull "
8820 "destination matrix, but checkSizes() indicates that it is not a legal "
8821 "legal target for redistribution from the source matrix (*this). This "
8822 "may mean that they do not have the same dimensions.");
8836 TEUCHOS_TEST_FOR_EXCEPTION(
8837 ! (reverseMode || getRowMap ()->isSameAs (*rowTransfer.getSourceMap ())),
8838 std::invalid_argument,
"Tpetra::CrsMatrix::transferAndFillComplete: "
8839 "rowTransfer->getSourceMap() must match this->getRowMap() in forward mode.");
8840 TEUCHOS_TEST_FOR_EXCEPTION(
8841 ! (! reverseMode || getRowMap ()->isSameAs (*rowTransfer.getTargetMap ())),
8842 std::invalid_argument,
"Tpetra::CrsMatrix::transferAndFillComplete: "
8843 "rowTransfer->getTargetMap() must match this->getRowMap() in reverse mode.");
8846 TEUCHOS_TEST_FOR_EXCEPTION(
8847 ! xferDomainAsImport.is_null() && ! xferDomainAsImport->getTargetMap()->isSameAs(*domainMap),
8848 std::invalid_argument,
8849 "Tpetra::CrsMatrix::transferAndFillComplete: The target map of the 'domainTransfer' input "
8850 "argument must be the same as the rebalanced domain map 'domainMap'");
8852 TEUCHOS_TEST_FOR_EXCEPTION(
8853 ! xferDomainAsExport.is_null() && ! xferDomainAsExport->getSourceMap()->isSameAs(*domainMap),
8854 std::invalid_argument,
8855 "Tpetra::CrsMatrix::transferAndFillComplete: The source map of the 'domainTransfer' input "
8856 "argument must be the same as the rebalanced domain map 'domainMap'");
8869 const size_t NumSameIDs = rowTransfer.getNumSameIDs();
8870 ArrayView<const LO> ExportLIDs = reverseMode ?
8871 rowTransfer.getRemoteLIDs () : rowTransfer.getExportLIDs ();
8872 ArrayView<const LO> RemoteLIDs = reverseMode ?
8873 rowTransfer.getExportLIDs () : rowTransfer.getRemoteLIDs ();
8874 ArrayView<const LO> PermuteToLIDs = reverseMode ?
8875 rowTransfer.getPermuteFromLIDs () : rowTransfer.getPermuteToLIDs ();
8876 ArrayView<const LO> PermuteFromLIDs = reverseMode ?
8877 rowTransfer.getPermuteToLIDs () : rowTransfer.getPermuteFromLIDs ();
8878 Distributor& Distor = rowTransfer.getDistributor ();
8881 Teuchos::Array<int> SourcePids;
8882 Teuchos::Array<int> TargetPids;
8885 RCP<const map_type> ReducedRowMap, ReducedColMap,
8886 ReducedDomainMap, ReducedRangeMap;
8887 RCP<const Comm<int> > ReducedComm;
8891 if (destMat.is_null ()) {
8892 destMat = rcp (
new this_type (MyRowMap, 0, StaticProfile, matrixparams));
8899 ReducedRowMap = MyRowMap->removeEmptyProcesses ();
8900 ReducedComm = ReducedRowMap.is_null () ?
8902 ReducedRowMap->getComm ();
8903 destMat->removeEmptyProcessesInPlace (ReducedRowMap);
8905 ReducedDomainMap = MyRowMap.getRawPtr () == MyDomainMap.getRawPtr () ?
8907 MyDomainMap->replaceCommWithSubset (ReducedComm);
8908 ReducedRangeMap = MyRowMap.getRawPtr () == MyRangeMap.getRawPtr () ?
8910 MyRangeMap->replaceCommWithSubset (ReducedComm);
8913 MyRowMap = ReducedRowMap;
8914 MyDomainMap = ReducedDomainMap;
8915 MyRangeMap = ReducedRangeMap;
8918 if (! ReducedComm.is_null ()) {
8919 MyPID = ReducedComm->getRank ();
8926 ReducedComm = MyRowMap->getComm ();
8935 RCP<const import_type> MyImporter = getGraph ()->getImporter ();
8938 bool bSameDomainMap = BaseDomainMap->isSameAs (*getDomainMap ());
8940 if (! restrictComm && ! MyImporter.is_null () && bSameDomainMap ) {
8947 Import_Util::getPids (*MyImporter, SourcePids,
false);
8949 else if (restrictComm && ! MyImporter.is_null () && bSameDomainMap) {
8952 IntVectorType SourceDomain_pids(getDomainMap (),
true);
8953 IntVectorType SourceCol_pids(getColMap());
8955 SourceDomain_pids.putScalar(MyPID);
8957 SourceCol_pids.doImport (SourceDomain_pids, *MyImporter,
INSERT);
8958 SourcePids.resize (getColMap ()->getNodeNumElements ());
8959 SourceCol_pids.get1dCopy (SourcePids ());
8961 else if (MyImporter.is_null () && bSameDomainMap) {
8963 SourcePids.resize (getColMap ()->getNodeNumElements ());
8964 SourcePids.assign (getColMap ()->getNodeNumElements (), MyPID);
8966 else if ( ! MyImporter.is_null () &&
8967 ! domainTransfer.is_null () ) {
8974 IntVectorType TargetDomain_pids (domainMap);
8975 TargetDomain_pids.putScalar (MyPID);
8978 IntVectorType SourceDomain_pids (getDomainMap ());
8981 IntVectorType SourceCol_pids (getColMap ());
8983 if (! reverseMode && ! xferDomainAsImport.is_null() ) {
8984 SourceDomain_pids.doExport (TargetDomain_pids, *xferDomainAsImport,
INSERT);
8986 else if (reverseMode && ! xferDomainAsExport.is_null() ) {
8987 SourceDomain_pids.doExport (TargetDomain_pids, *xferDomainAsExport,
INSERT);
8989 else if (! reverseMode && ! xferDomainAsExport.is_null() ) {
8990 SourceDomain_pids.doImport (TargetDomain_pids, *xferDomainAsExport,
INSERT);
8992 else if (reverseMode && ! xferDomainAsImport.is_null() ) {
8993 SourceDomain_pids.doImport (TargetDomain_pids, *xferDomainAsImport,
INSERT);
8996 TEUCHOS_TEST_FOR_EXCEPTION(
8997 true, std::logic_error,
"Tpetra::CrsMatrix::"
8998 "transferAndFillComplete: Should never get here! "
8999 "Please report this bug to a Tpetra developer.");
9001 SourceCol_pids.doImport (SourceDomain_pids, *MyImporter,
INSERT);
9002 SourcePids.resize (getColMap ()->getNodeNumElements ());
9003 SourceCol_pids.get1dCopy (SourcePids ());
9005 else if ( ! MyImporter.is_null () &&
9006 BaseDomainMap->isSameAs (*BaseRowMap) &&
9007 getDomainMap ()->isSameAs (*getRowMap ())) {
9010 IntVectorType TargetRow_pids (domainMap);
9011 IntVectorType SourceRow_pids (getRowMap ());
9012 IntVectorType SourceCol_pids (getColMap ());
9014 TargetRow_pids.putScalar (MyPID);
9015 if (! reverseMode && xferAsImport != NULL) {
9016 SourceRow_pids.doExport (TargetRow_pids, *xferAsImport,
INSERT);
9018 else if (reverseMode && xferAsExport != NULL) {
9019 SourceRow_pids.doExport (TargetRow_pids, *xferAsExport,
INSERT);
9021 else if (! reverseMode && xferAsExport != NULL) {
9022 SourceRow_pids.doImport (TargetRow_pids, *xferAsExport,
INSERT);
9024 else if (reverseMode && xferAsImport != NULL) {
9025 SourceRow_pids.doImport (TargetRow_pids, *xferAsImport,
INSERT);
9028 TEUCHOS_TEST_FOR_EXCEPTION(
9029 true, std::logic_error,
"Tpetra::CrsMatrix::"
9030 "transferAndFillComplete: Should never get here! "
9031 "Please report this bug to a Tpetra developer.");
9034 SourceCol_pids.doImport (SourceRow_pids, *MyImporter,
INSERT);
9035 SourcePids.resize (getColMap ()->getNodeNumElements ());
9036 SourceCol_pids.get1dCopy (SourcePids ());
9039 TEUCHOS_TEST_FOR_EXCEPTION(
9040 true, std::invalid_argument,
"Tpetra::CrsMatrix::"
9041 "transferAndFillComplete: This method only allows either domainMap == "
9042 "getDomainMap (), or (domainMap == rowTransfer.getTargetMap () and "
9043 "getDomainMap () == getRowMap ()).");
9047 size_t constantNumPackets = destMat->constantNumberOfPackets ();
9048 if (constantNumPackets == 0) {
9049 destMat->reallocArraysForNumPacketsPerLid (ExportLIDs.size (),
9050 RemoteLIDs.size ());
9057 const size_t rbufLen = RemoteLIDs.size() * constantNumPackets;
9058 destMat->reallocImportsIfNeeded (rbufLen,
false,
nullptr);
9063 using Teuchos::outArg;
9064 using Teuchos::REDUCE_MAX;
9065 using Teuchos::reduceAll;
9068 RCP<const Teuchos::Comm<int> > comm = this->getComm ();
9069 const int myRank = comm->getRank ();
9071 std::ostringstream errStrm;
9075 Teuchos::ArrayView<size_t> numExportPacketsPerLID;
9078 destMat->numExportPacketsPerLID_.modify_host ();
9079 numExportPacketsPerLID =
9082 catch (std::exception& e) {
9083 errStrm <<
"Proc " << myRank <<
": getArrayViewFromDualView threw: "
9084 << e.what () << std::endl;
9088 errStrm <<
"Proc " << myRank <<
": getArrayViewFromDualView threw "
9089 "an exception not a subclass of std::exception" << std::endl;
9093 if (! comm.is_null ()) {
9094 reduceAll<int, int> (*comm, REDUCE_MAX, lclErr, outArg (gblErr));
9097 ::Tpetra::Details::gathervPrint (cerr, errStrm.str (), *comm);
9098 TEUCHOS_TEST_FOR_EXCEPTION(
9099 true, std::runtime_error,
"getArrayViewFromDualView threw an "
9100 "exception on at least one process.");
9104 std::ostringstream os;
9105 os << *verbosePrefix <<
"Calling packCrsMatrixWithOwningPIDs"
9107 std::cerr << os.str ();
9112 numExportPacketsPerLID,
9118 catch (std::exception& e) {
9119 errStrm <<
"Proc " << myRank <<
": packCrsMatrixWithOwningPIDs threw: "
9120 << e.what () << std::endl;
9124 errStrm <<
"Proc " << myRank <<
": packCrsMatrixWithOwningPIDs threw "
9125 "an exception not a subclass of std::exception" << std::endl;
9130 std::ostringstream os;
9131 os << *verbosePrefix <<
"Done with packCrsMatrixWithOwningPIDs"
9133 std::cerr << os.str ();
9136 if (! comm.is_null ()) {
9137 reduceAll<int, int> (*comm, REDUCE_MAX, lclErr, outArg (gblErr));
9140 ::Tpetra::Details::gathervPrint (cerr, errStrm.str (), *comm);
9141 TEUCHOS_TEST_FOR_EXCEPTION(
9142 true, std::runtime_error,
"packCrsMatrixWithOwningPIDs threw an "
9143 "exception on at least one process.");
9148 destMat->numExportPacketsPerLID_.modify_host ();
9149 Teuchos::ArrayView<size_t> numExportPacketsPerLID =
9152 std::ostringstream os;
9153 os << *verbosePrefix <<
"Calling packCrsMatrixWithOwningPIDs"
9155 std::cerr << os.str ();
9159 numExportPacketsPerLID,
9165 std::ostringstream os;
9166 os << *verbosePrefix <<
"Done with packCrsMatrixWithOwningPIDs"
9168 std::cerr << os.str ();
9173 if (! communication_needed) {
9175 std::ostringstream os;
9176 os << *verbosePrefix <<
"Communication not needed" << std::endl;
9177 std::cerr << os.str ();
9182 if (constantNumPackets == 0) {
9184 std::ostringstream os;
9185 os << *verbosePrefix <<
"Reverse mode, variable # packets / LID"
9187 std::cerr << os.str ();
9192 destMat->numExportPacketsPerLID_.sync_host ();
9193 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
9195 destMat->numImportPacketsPerLID_.sync_host ();
9196 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
9200 std::ostringstream os;
9201 os << *verbosePrefix <<
"Calling 3-arg doReversePostsAndWaits"
9203 std::cerr << os.str ();
9205 Distor.doReversePostsAndWaits (numExportPacketsPerLID, 1,
9206 numImportPacketsPerLID);
9208 std::ostringstream os;
9209 os << *verbosePrefix <<
"Finished 3-arg doReversePostsAndWaits"
9211 std::cerr << os.str ();
9214 size_t totalImportPackets = 0;
9215 for (
Array_size_type i = 0; i < numImportPacketsPerLID.size (); ++i) {
9216 totalImportPackets += numImportPacketsPerLID[i];
9221 destMat->reallocImportsIfNeeded (totalImportPackets, verbose,
9222 verbosePrefix.get ());
9223 destMat->imports_.modify_host ();
9224 Teuchos::ArrayView<char> hostImports =
9228 destMat->exports_.sync_host ();
9229 Teuchos::ArrayView<const char> hostExports =
9232 std::ostringstream os;
9233 os << *verbosePrefix <<
"Calling 4-arg doReversePostsAndWaits"
9235 std::cerr << os.str ();
9237 Distor.doReversePostsAndWaits (hostExports,
9238 numExportPacketsPerLID,
9240 numImportPacketsPerLID);
9242 std::ostringstream os;
9243 os << *verbosePrefix <<
"Finished 4-arg doReversePostsAndWaits"
9245 std::cerr << os.str ();
9250 std::ostringstream os;
9251 os << *verbosePrefix <<
"Reverse mode, constant # packets / LID"
9253 std::cerr << os.str ();
9255 destMat->imports_.modify_host ();
9256 Teuchos::ArrayView<char> hostImports =
9260 destMat->exports_.sync_host ();
9261 Teuchos::ArrayView<const char> hostExports =
9264 std::ostringstream os;
9265 os << *verbosePrefix <<
"Calling 3-arg doReversePostsAndWaits"
9267 std::cerr << os.str ();
9269 Distor.doReversePostsAndWaits (hostExports,
9273 std::ostringstream os;
9274 os << *verbosePrefix <<
"Finished 3-arg doReversePostsAndWaits"
9276 std::cerr << os.str ();
9281 if (constantNumPackets == 0) {
9283 std::ostringstream os;
9284 os << *verbosePrefix <<
"Forward mode, variable # packets / LID"
9286 std::cerr << os.str ();
9291 destMat->numExportPacketsPerLID_.sync_host ();
9292 Teuchos::ArrayView<const size_t> numExportPacketsPerLID =
9294 destMat->numImportPacketsPerLID_.sync_host ();
9295 Teuchos::ArrayView<size_t> numImportPacketsPerLID =
9298 std::ostringstream os;
9299 os << *verbosePrefix <<
"Calling 3-arg doPostsAndWaits"
9301 std::cerr << os.str ();
9303 Distor.doPostsAndWaits (numExportPacketsPerLID, 1,
9304 numImportPacketsPerLID);
9306 std::ostringstream os;
9307 os << *verbosePrefix <<
"Finished 3-arg doPostsAndWaits"
9309 std::cerr << os.str ();
9312 size_t totalImportPackets = 0;
9313 for (
Array_size_type i = 0; i < numImportPacketsPerLID.size (); ++i) {
9314 totalImportPackets += numImportPacketsPerLID[i];
9319 destMat->reallocImportsIfNeeded (totalImportPackets, verbose,
9320 verbosePrefix.get ());
9321 destMat->imports_.modify_host ();
9322 Teuchos::ArrayView<char> hostImports =
9326 destMat->exports_.sync_host ();
9327 Teuchos::ArrayView<const char> hostExports =
9330 std::ostringstream os;
9331 os << *verbosePrefix <<
"Calling 4-arg doPostsAndWaits"
9333 std::cerr << os.str ();
9335 Distor.doPostsAndWaits (hostExports,
9336 numExportPacketsPerLID,
9338 numImportPacketsPerLID);
9340 std::ostringstream os;
9341 os << *verbosePrefix <<
"Finished 4-arg doPostsAndWaits"
9343 std::cerr << os.str ();
9348 std::ostringstream os;
9349 os << *verbosePrefix <<
"Forward mode, constant # packets / LID"
9351 std::cerr << os.str ();
9353 destMat->imports_.modify_host ();
9354 Teuchos::ArrayView<char> hostImports =
9358 destMat->exports_.sync_host ();
9359 Teuchos::ArrayView<const char> hostExports =
9362 std::ostringstream os;
9363 os << *verbosePrefix <<
"Calling 3-arg doPostsAndWaits"
9365 std::cerr << os.str ();
9367 Distor.doPostsAndWaits (hostExports,
9371 std::ostringstream os;
9372 os << *verbosePrefix <<
"Finished 3-arg doPostsAndWaits"
9374 std::cerr << os.str ();
9385 destMat->numImportPacketsPerLID_.sync_host ();
9386 Teuchos::ArrayView<const size_t> numImportPacketsPerLID =
9388 destMat->imports_.sync_host ();
9389 Teuchos::ArrayView<const char> hostImports =
9393 std::ostringstream os;
9394 os << *verbosePrefix <<
"Calling unpackAndCombineWithOwningPIDsCount"
9396 std::cerr << os.str ();
9402 numImportPacketsPerLID,
9410 std::ostringstream os;
9411 os << *verbosePrefix <<
"unpackAndCombineWithOwningPIDsCount returned "
9412 << mynnz << std::endl;
9413 std::cerr << os.str ();
9415 size_t N = BaseRowMap->getNodeNumElements ();
9418 ArrayRCP<size_t> CSR_rowptr(N+1);
9419 ArrayRCP<GO> CSR_colind_GID;
9420 ArrayRCP<LO> CSR_colind_LID;
9421 ArrayRCP<Scalar> CSR_vals;
9422 CSR_colind_GID.resize (mynnz);
9423 CSR_vals.resize (mynnz);
9427 if (
typeid (LO) ==
typeid (GO)) {
9428 CSR_colind_LID = Teuchos::arcp_reinterpret_cast<LO> (CSR_colind_GID);
9431 CSR_colind_LID.resize (mynnz);
9435 std::ostringstream os;
9436 os << *verbosePrefix <<
"Calling unpackAndCombineIntoCrsArrays"
9438 std::cerr << os.str ();
9448 numImportPacketsPerLID,
9460 Teuchos::av_reinterpret_cast<impl_scalar_type> (CSR_vals ()),
9470 Teuchos::Array<int> RemotePids;
9472 std::ostringstream os;
9473 os << *verbosePrefix <<
"Calling lowCommunicationMakeColMapAndReindex"
9475 std::cerr << os.str ();
9477 Import_Util::lowCommunicationMakeColMapAndReindex (CSR_rowptr (),
9486 std::ostringstream os;
9487 os << *verbosePrefix <<
"restrictComm="
9488 << (restrictComm ?
"true" :
"false") << std::endl;
9489 std::cerr << os.str ();
9496 ReducedColMap = (MyRowMap.getRawPtr () == MyColMap.getRawPtr ()) ?
9498 MyColMap->replaceCommWithSubset (ReducedComm);
9499 MyColMap = ReducedColMap;
9504 std::ostringstream os;
9505 os << *verbosePrefix <<
"Calling replaceColMap" << std::endl;
9506 std::cerr << os.str ();
9508 destMat->replaceColMap (MyColMap);
9515 if (ReducedComm.is_null ()) {
9517 std::ostringstream os;
9518 os << *verbosePrefix <<
"I am no longer in the communicator; "
9519 "returning" << std::endl;
9520 std::cerr << os.str ();
9528 if ((! reverseMode && xferAsImport != NULL) ||
9529 (reverseMode && xferAsExport != NULL)) {
9531 std::ostringstream os;
9532 os << *verbosePrefix <<
"Calling sortCrsEntries" << std::endl;
9533 std::cerr << os.str ();
9535 Import_Util::sortCrsEntries (CSR_rowptr (),
9539 else if ((! reverseMode && xferAsExport != NULL) ||
9540 (reverseMode && xferAsImport != NULL)) {
9542 std::ostringstream os;
9543 os << *verbosePrefix <<
"Calling sortAndMergeCrsEntries" << std::endl;
9544 std::cerr << os.str ();
9546 Import_Util::sortAndMergeCrsEntries (CSR_rowptr (),
9549 if (CSR_rowptr[N] != mynnz) {
9550 CSR_colind_LID.resize (CSR_rowptr[N]);
9551 CSR_vals.resize (CSR_rowptr[N]);
9555 TEUCHOS_TEST_FOR_EXCEPTION(
9556 true, std::logic_error,
"Tpetra::CrsMatrix::"
9557 "transferAndFillComplete: Should never get here! "
9558 "Please report this bug to a Tpetra developer.");
9565 std::ostringstream os;
9566 os << *verbosePrefix <<
"Calling destMat->setAllValues" << std::endl;
9567 std::cerr << os.str ();
9575 destMat->setAllValues (CSR_rowptr, CSR_colind_LID, CSR_vals);
9581 Teuchos::ParameterList esfc_params;
9583 RCP<import_type> MyImport;
9586 if (iallreduceRequest.get () !=
nullptr) {
9588 std::ostringstream os;
9589 os << *verbosePrefix <<
"Calling iallreduceRequest->wait()" << std::endl;
9590 std::cerr << os.str ();
9592 iallreduceRequest->wait ();
9593 if (reduced_mismatch != 0) {
9599 #ifdef HAVE_TPETRA_MMM_TIMINGS
9600 Teuchos::TimeMonitor MMisMM (*TimeMonitor::getNewTimer(prefix + std::string(
"isMM Block")));
9605 std::ostringstream os;
9606 os << *verbosePrefix <<
"Calling getAllValues" << std::endl;
9607 std::cerr << os.str ();
9610 Teuchos::ArrayRCP<LocalOrdinal> type3LIDs;
9611 Teuchos::ArrayRCP<int> type3PIDs;
9612 Teuchos::ArrayRCP<const size_t> rowptr;
9613 Teuchos::ArrayRCP<const LO> colind;
9614 Teuchos::ArrayRCP<const Scalar> vals;
9616 #ifdef HAVE_TPETRA_MMM_TIMINGS
9617 TimeMonitor tm_getAllValues (*TimeMonitor::getNewTimer(prefix + std::string(
"isMMgetAllValues")));
9619 getAllValues(rowptr,colind,vals);
9623 std::ostringstream os;
9624 os << *verbosePrefix <<
"Calling reverseNeighborDiscovery" << std::endl;
9625 std::cerr << os.str ();
9629 #ifdef HAVE_TPETRA_MMM_TIMINGS
9630 TimeMonitor tm_rnd (*TimeMonitor::getNewTimer(prefix + std::string(
"isMMrevNeighDis")));
9632 Import_Util::reverseNeighborDiscovery(*
this,
9644 std::ostringstream os;
9645 os << *verbosePrefix <<
"Done with reverseNeighborDiscovery" << std::endl;
9646 std::cerr << os.str ();
9649 Teuchos::ArrayView<const int> EPID1 = MyImporter.is_null() ? Teuchos::ArrayView<const int>() : MyImporter->getExportPIDs();
9650 Teuchos::ArrayView<const LO> ELID1 = MyImporter.is_null() ? Teuchos::ArrayView<const int>() : MyImporter->getExportLIDs();
9652 Teuchos::ArrayView<const int> TEPID2 = rowTransfer.getExportPIDs();
9653 Teuchos::ArrayView<const LO> TELID2 = rowTransfer.getExportLIDs();
9655 const int numCols = getGraph()->getColMap()->getNodeNumElements();
9657 std::vector<bool> IsOwned(numCols,
true);
9658 std::vector<int> SentTo(numCols,-1);
9659 if (! MyImporter.is_null ()) {
9660 for (
auto && rlid : MyImporter->getRemoteLIDs()) {
9661 IsOwned[rlid]=
false;
9665 std::vector<std::pair<int,GO> > usrtg;
9666 usrtg.reserve(TEPID2.size());
9669 const auto& colMap = * (this->getColMap ());
9671 const LO row = TELID2[i];
9672 const int pid = TEPID2[i];
9673 for (
auto j = rowptr[row]; j < rowptr[row+1]; ++j) {
9674 const int col = colind[j];
9675 if (IsOwned[col] && SentTo[col] != pid) {
9677 GO gid = colMap.getGlobalElement (col);
9678 usrtg.push_back (std::pair<int,GO> (pid, gid));
9685 std::sort(usrtg.begin(),usrtg.end());
9686 auto eopg = std ::unique(usrtg.begin(),usrtg.end());
9688 usrtg.erase(eopg,usrtg.end());
9691 Teuchos::ArrayRCP<int> EPID2=Teuchos::arcp(
new int[type2_us_size],0,type2_us_size,
true);
9692 Teuchos::ArrayRCP< LO> ELID2=Teuchos::arcp(
new LO[type2_us_size],0,type2_us_size,
true);
9695 for(
auto && p : usrtg) {
9696 EPID2[pos]= p.first;
9697 ELID2[pos]= this->getDomainMap()->getLocalElement(p.second);
9701 Teuchos::ArrayView<int> EPID3 = type3PIDs();
9702 Teuchos::ArrayView< LO> ELID3 = type3LIDs();
9703 GO InfGID = std::numeric_limits<GO>::max();
9704 int InfPID = INT_MAX;
9707 #endif // TPETRA_MIN3
9708 #define TPETRA_MIN3(x,y,z) ((x)<(y)?(std::min(x,z)):(std::min(y,z)))
9709 int i1=0, i2=0, i3=0;
9710 int Len1 = EPID1.size();
9711 int Len2 = EPID2.size();
9712 int Len3 = EPID3.size();
9714 int MyLen=Len1+Len2+Len3;
9715 Teuchos::ArrayRCP<LO> userExportLIDs = Teuchos::arcp(
new LO[MyLen],0,MyLen,
true);
9716 Teuchos::ArrayRCP<int> userExportPIDs = Teuchos::arcp(
new int[MyLen],0,MyLen,
true);
9719 while(i1 < Len1 || i2 < Len2 || i3 < Len3){
9720 int PID1 = (i1<Len1)?(EPID1[i1]):InfPID;
9721 int PID2 = (i2<Len2)?(EPID2[i2]):InfPID;
9722 int PID3 = (i3<Len3)?(EPID3[i3]):InfPID;
9724 GO GID1 = (i1<Len1)?getDomainMap()->getGlobalElement(ELID1[i1]):InfGID;
9725 GO GID2 = (i2<Len2)?getDomainMap()->getGlobalElement(ELID2[i2]):InfGID;
9726 GO GID3 = (i3<Len3)?getDomainMap()->getGlobalElement(ELID3[i3]):InfGID;
9728 int MIN_PID = TPETRA_MIN3(PID1,PID2,PID3);
9729 GO MIN_GID = TPETRA_MIN3( ((PID1==MIN_PID)?GID1:InfGID), ((PID2==MIN_PID)?GID2:InfGID), ((PID3==MIN_PID)?GID3:InfGID));
9732 #endif // TPETRA_MIN3
9733 bool added_entry=
false;
9735 if(PID1 == MIN_PID && GID1 == MIN_GID){
9736 userExportLIDs[iloc]=ELID1[i1];
9737 userExportPIDs[iloc]=EPID1[i1];
9742 if(PID2 == MIN_PID && GID2 == MIN_GID){
9744 userExportLIDs[iloc]=ELID2[i2];
9745 userExportPIDs[iloc]=EPID2[i2];
9751 if(PID3 == MIN_PID && GID3 == MIN_GID){
9753 userExportLIDs[iloc]=ELID3[i3];
9754 userExportPIDs[iloc]=EPID3[i3];
9762 std::ostringstream os;
9763 os << *verbosePrefix <<
"Create Import" << std::endl;
9764 std::cerr << os.str ();
9767 #ifdef HAVE_TPETRA_MMM_TIMINGS
9768 auto ismmIctor(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMIportCtor")));
9770 Teuchos::RCP<Teuchos::ParameterList> plist = rcp(
new Teuchos::ParameterList());
9772 MyImport = rcp (
new import_type (MyDomainMap,
9775 userExportLIDs.view(0,iloc).getConst(),
9776 userExportPIDs.view(0,iloc).getConst(),
9781 std::ostringstream os;
9782 os << *verbosePrefix <<
"Call expertStaticFillComplete" << std::endl;
9783 std::cerr << os.str ();
9787 #ifdef HAVE_TPETRA_MMM_TIMINGS
9788 TimeMonitor esfc (*TimeMonitor::getNewTimer(prefix + std::string(
"isMM::destMat->eSFC")));
9789 esfc_params.set(
"Timer Label",label+std::string(
"isMM eSFC"));
9791 if(!params.is_null())
9792 esfc_params.set(
"compute global constants",params->get(
"compute global constants",
true));
9793 destMat->expertStaticFillComplete (MyDomainMap, MyRangeMap, MyImport,Teuchos::null,rcp(
new Teuchos::ParameterList(esfc_params)));
9799 #ifdef HAVE_TPETRA_MMM_TIMINGS
9800 TimeMonitor MMnotMMblock (*TimeMonitor::getNewTimer(prefix + std::string(
"TAFC notMMblock")));
9803 std::ostringstream os;
9804 os << *verbosePrefix <<
"Create Import" << std::endl;
9805 std::cerr << os.str ();
9808 #ifdef HAVE_TPETRA_MMM_TIMINGS
9809 TimeMonitor notMMIcTor(*TimeMonitor::getNewTimer(prefix + std::string(
"TAFC notMMCreateImporter")));
9811 Teuchos::RCP<Teuchos::ParameterList> mypars = rcp(
new Teuchos::ParameterList);
9812 mypars->set(
"Timer Label",
"notMMFrom_tAFC");
9813 MyImport = rcp (
new import_type (MyDomainMap, MyColMap, RemotePids, mypars));
9816 std::ostringstream os;
9817 os << *verbosePrefix <<
"Call expertStaticFillComplete" << std::endl;
9818 std::cerr << os.str ();
9821 #ifdef HAVE_TPETRA_MMM_TIMINGS
9822 TimeMonitor esfcnotmm(*TimeMonitor::getNewTimer(prefix + std::string(
"notMMdestMat->expertStaticFillComplete")));
9823 esfc_params.set(
"Timer Label",prefix+std::string(
"notMM eSFC"));
9825 esfc_params.set(
"Timer Label",std::string(
"notMM eSFC"));
9828 if (!params.is_null ()) {
9829 esfc_params.set (
"compute global constants",
9830 params->get (
"compute global constants",
true));
9832 destMat->expertStaticFillComplete (MyDomainMap, MyRangeMap,
9833 MyImport, Teuchos::null,
9834 rcp (
new Teuchos::ParameterList (esfc_params)));
9838 std::ostringstream os;
9839 os << *verbosePrefix <<
"Done!" << std::endl;
9840 std::cerr << os.str ();
9845 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
9850 const Teuchos::RCP<const map_type>& domainMap,
9851 const Teuchos::RCP<const map_type>& rangeMap,
9852 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
9854 transferAndFillComplete (destMatrix, importer, Teuchos::null, domainMap, rangeMap, params);
9857 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
9863 const Teuchos::RCP<const map_type>& domainMap,
9864 const Teuchos::RCP<const map_type>& rangeMap,
9865 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
9867 transferAndFillComplete (destMatrix, rowImporter, Teuchos::rcpFromRef(domainImporter), domainMap, rangeMap, params);
9870 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
9875 const Teuchos::RCP<const map_type>& domainMap,
9876 const Teuchos::RCP<const map_type>& rangeMap,
9877 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
9879 transferAndFillComplete (destMatrix, exporter, Teuchos::null, domainMap, rangeMap, params);
9882 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
9888 const Teuchos::RCP<const map_type>& domainMap,
9889 const Teuchos::RCP<const map_type>& rangeMap,
9890 const Teuchos::RCP<Teuchos::ParameterList>& params)
const
9892 transferAndFillComplete (destMatrix, rowExporter, Teuchos::rcpFromRef(domainExporter), domainMap, rangeMap, params);
9904 #define TPETRA_CRSMATRIX_MATRIX_INSTANT(SCALAR,LO,GO,NODE) \
9906 template class CrsMatrix< SCALAR , LO , GO , NODE >; \
9907 template Teuchos::RCP< CrsMatrix< SCALAR , LO , GO , NODE > > \
9908 CrsMatrix< SCALAR , LO , GO , NODE >::convert< SCALAR > () const;
9910 #define TPETRA_CRSMATRIX_CONVERT_INSTANT(SO,SI,LO,GO,NODE) \
9912 template Teuchos::RCP< CrsMatrix< SO , LO , GO , NODE > > \
9913 CrsMatrix< SI , LO , GO , NODE >::convert< SO > () const;
9915 #define TPETRA_CRSMATRIX_IMPORT_AND_FILL_COMPLETE_INSTANT(SCALAR, LO, GO, NODE) \
9917 Teuchos::RCP<CrsMatrix<SCALAR, LO, GO, NODE> > \
9918 importAndFillCompleteCrsMatrix (const Teuchos::RCP<const CrsMatrix<SCALAR, LO, GO, NODE> >& sourceMatrix, \
9919 const Import<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9920 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9921 CrsMatrix<SCALAR, LO, GO, NODE>::node_type>& importer, \
9922 const Teuchos::RCP<const Map<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9923 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9924 CrsMatrix<SCALAR, LO, GO, NODE>::node_type> >& domainMap, \
9925 const Teuchos::RCP<const Map<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9926 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9927 CrsMatrix<SCALAR, LO, GO, NODE>::node_type> >& rangeMap, \
9928 const Teuchos::RCP<Teuchos::ParameterList>& params);
9930 #define TPETRA_CRSMATRIX_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(SCALAR, LO, GO, NODE) \
9932 Teuchos::RCP<CrsMatrix<SCALAR, LO, GO, NODE> > \
9933 importAndFillCompleteCrsMatrix (const Teuchos::RCP<const CrsMatrix<SCALAR, LO, GO, NODE> >& sourceMatrix, \
9934 const Import<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9935 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9936 CrsMatrix<SCALAR, LO, GO, NODE>::node_type>& rowImporter, \
9937 const Import<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9938 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9939 CrsMatrix<SCALAR, LO, GO, NODE>::node_type>& domainImporter, \
9940 const Teuchos::RCP<const Map<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9941 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9942 CrsMatrix<SCALAR, LO, GO, NODE>::node_type> >& domainMap, \
9943 const Teuchos::RCP<const Map<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9944 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9945 CrsMatrix<SCALAR, LO, GO, NODE>::node_type> >& rangeMap, \
9946 const Teuchos::RCP<Teuchos::ParameterList>& params);
9949 #define TPETRA_CRSMATRIX_EXPORT_AND_FILL_COMPLETE_INSTANT(SCALAR, LO, GO, NODE) \
9951 Teuchos::RCP<CrsMatrix<SCALAR, LO, GO, NODE> > \
9952 exportAndFillCompleteCrsMatrix (const Teuchos::RCP<const CrsMatrix<SCALAR, LO, GO, NODE> >& sourceMatrix, \
9953 const Export<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9954 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9955 CrsMatrix<SCALAR, LO, GO, NODE>::node_type>& exporter, \
9956 const Teuchos::RCP<const Map<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9957 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9958 CrsMatrix<SCALAR, LO, GO, NODE>::node_type> >& domainMap, \
9959 const Teuchos::RCP<const Map<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9960 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9961 CrsMatrix<SCALAR, LO, GO, NODE>::node_type> >& rangeMap, \
9962 const Teuchos::RCP<Teuchos::ParameterList>& params);
9964 #define TPETRA_CRSMATRIX_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(SCALAR, LO, GO, NODE) \
9966 Teuchos::RCP<CrsMatrix<SCALAR, LO, GO, NODE> > \
9967 exportAndFillCompleteCrsMatrix (const Teuchos::RCP<const CrsMatrix<SCALAR, LO, GO, NODE> >& sourceMatrix, \
9968 const Export<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9969 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9970 CrsMatrix<SCALAR, LO, GO, NODE>::node_type>& rowExporter, \
9971 const Export<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9972 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9973 CrsMatrix<SCALAR, LO, GO, NODE>::node_type>& domainExporter, \
9974 const Teuchos::RCP<const Map<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9975 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9976 CrsMatrix<SCALAR, LO, GO, NODE>::node_type> >& domainMap, \
9977 const Teuchos::RCP<const Map<CrsMatrix<SCALAR, LO, GO, NODE>::local_ordinal_type, \
9978 CrsMatrix<SCALAR, LO, GO, NODE>::global_ordinal_type, \
9979 CrsMatrix<SCALAR, LO, GO, NODE>::node_type> >& rangeMap, \
9980 const Teuchos::RCP<Teuchos::ParameterList>& params);
9983 #define TPETRA_CRSMATRIX_INSTANT(SCALAR, LO, GO ,NODE) \
9984 TPETRA_CRSMATRIX_MATRIX_INSTANT(SCALAR, LO, GO, NODE) \
9985 TPETRA_CRSMATRIX_IMPORT_AND_FILL_COMPLETE_INSTANT(SCALAR, LO, GO, NODE) \
9986 TPETRA_CRSMATRIX_EXPORT_AND_FILL_COMPLETE_INSTANT(SCALAR, LO, GO, NODE) \
9987 TPETRA_CRSMATRIX_IMPORT_AND_FILL_COMPLETE_INSTANT_TWO(SCALAR, LO, GO, NODE) \
9988 TPETRA_CRSMATRIX_EXPORT_AND_FILL_COMPLETE_INSTANT_TWO(SCALAR, LO, GO, NODE)
9990 #endif // TPETRA_CRSMATRIX_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...
Teuchos::RCP< const map_type > getRowMap() const override
Returns the Map that describes the row distribution in this graph.
dual_view_type::t_host getLocalViewHost() const
A local Kokkos::View of host memory.
bool hasColMap() const override
Whether the matrix has a well-defined column Map.
bool indicesAreSorted_
Whether the graph's indices are sorted in each row, on this process.
static int TAFC_OptimizationCoreCount()
The core count above which Tpetra::CrsMatrix::transferAndFillComplete will attempt to do advanced nei...
global_size_t getGlobalNumCols() const override
The number of global columns in the matrix.
Impl::CreateMirrorViewFromUnmanagedHostArray< ValueType, OutputDeviceType >::output_view_type create_mirror_view_from_raw_host_array(const OutputDeviceType &, ValueType *inPtr, const size_t inSize, const bool copy=true, const char label[]="")
Variant of Kokkos::create_mirror_view that takes a raw host 1-d array as input.
Functor for the the ABSMAX CombineMode of Import and Export operations.
void checkInternalState() const
Check that this object's state is sane; throw if it's not.
Abstract interface for local operators (e.g., matrices and preconditioners).
Sparse matrix that presents a row-oriented interface that lets users read or modify entries...
size_t getNodeNumCols() const override
The number of columns connected to the locally owned rows of this matrix.
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...
CrsGraph< LocalOrdinal, GlobalOrdinal, Node > crs_graph_type
The CrsGraph specialization suitable for this CrsMatrix specialization.
void replaceColMap(const Teuchos::RCP< const map_type > &newColMap)
Replace the matrix's column Map with the given Map.
virtual bool supportsRowViews() const override
Return true if getLocalRowView() and getGlobalRowView() are valid for this object.
LocalOrdinal getViewRaw(impl_scalar_type *&vals, LocalOrdinal &numEnt, const RowInfo &rowinfo) const
Nonconst pointer to all entries (including extra space) in the given row.
void replaceDomainMapAndImporter(const Teuchos::RCP< const map_type > &newDomainMap, Teuchos::RCP< const import_type > &newImporter)
Replace the current domain Map and Import with the given objects.
bool isNodeGlobalElement(GlobalOrdinal globalIndex) const
Whether the given global index is owned by this Map on the calling process.
LocalOrdinal replaceLocalValues(const LocalOrdinal localRow, const typename UnmanagedView< LocalIndicesViewType >::type &inputInds, const typename UnmanagedView< ImplScalarViewType >::type &inputVals) const
Replace one or more entries' values, using local row and column indices.
Teuchos::RCP< const map_type > getRangeMap() const override
The range Map of this matrix.
global_size_t getGlobalNumRows() const override
Number of global elements in the row map of this matrix.
std::map< GlobalOrdinal, std::pair< Teuchos::Array< GlobalOrdinal >, Teuchos::Array< Scalar > > > nonlocals_
Nonlocal data added using insertGlobalValues().
void sortAndMergeIndicesAndValues(const bool sorted, const bool merged)
Sort and merge duplicate local column indices in all rows on the calling process, along with their co...
typename device_type::execution_space execution_space
The Kokkos execution space.
void getLocalRowCopy(LocalOrdinal localRow, const Teuchos::ArrayView< LocalOrdinal > &colInds, const Teuchos::ArrayView< Scalar > &vals, size_t &numEntries) const override
Fill given arrays with a deep copy of the locally owned entries of the matrix in a given row...
void clear_sync_state()
Clear "modified" flags on both host and device sides.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
size_t getNumEntriesInLocalRow(local_ordinal_type localRow) const override
Get the number of entries in the given row (local index).
typename Kokkos::ArithTraits< impl_scalar_type >::mag_type mag_type
Type of a norm result.
void putScalar(const Scalar &value)
Set all values in the multivector with the given value.
size_t getNumVectors() const
Number of columns in the multivector.
size_t getLocalLength() const
Local number of rows on the calling process.
void setAllToScalar(const Scalar &alpha)
Set all matrix entries equal to alpha.
bool isConstantStride() const
Whether this multivector has constant stride between columns.
Traits class for packing / unpacking data of type T, using Kokkos data structures that live in the gi...
One or more distributed dense vectors.
size_t getNodeNumEntries() const override
The local number of entries in this matrix.
virtual size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const =0
The current number of entries on the calling process in the specified local row.
void scale(const Scalar &alpha)
Scale the matrix's values: this := alpha*this.
Teuchos::RCP< const map_type > getDomainMap() const override
Returns the Map associated with the domain of this graph.
Declare and define Tpetra::Details::copyOffsets, an implementation detail of Tpetra (in particular...
size_t getNodeNumRows() const override
The number of matrix rows owned by the calling process.
void fillLocalGraphAndMatrix(const Teuchos::RCP< Teuchos::ParameterList > ¶ms)
Fill data into the local graph and matrix.
void resumeFill(const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Resume operations that may change the values or structure of the matrix.
void leftScale(const Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &x) override
Scale the matrix on the left with the given Vector.
bool noRedundancies_
Whether the graph's indices are non-redundant (merged) in each row, on this process.
bool isDistributed() const
Whether this is a globally distributed object.
void reindexColumns(crs_graph_type *const graph, const Teuchos::RCP< const map_type > &newColMap, const Teuchos::RCP< const import_type > &newImport=Teuchos::null, const bool sortEachRow=true)
Reindex the column indices in place, and replace the column Map. Optionally, replace the Import objec...
void packCrsMatrixWithOwningPIDs(const CrsMatrix< ST, LO, GO, NT > &sourceMatrix, Kokkos::DualView< char *, typename DistObject< char, 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 matrix for communication.
void getGlobalRowCopy(GlobalOrdinal GlobalRow, const Teuchos::ArrayView< GlobalOrdinal > &Indices, const Teuchos::ArrayView< Scalar > &Values, size_t &NumEntries) const override
Fill given arrays with a deep copy of the locally owned entries of the matrix in a given row...
Teuchos::RCP< const crs_graph_type > getCrsGraph() const
This matrix's graph, as a CrsGraph.
static bool debug()
Whether Tpetra is in debug mode.
size_t getGlobalMaxNumRowEntries() const override
Maximum number of entries in any row of the matrix, over all processes in the matrix's communicator...
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRangeMap() const =0
The Map associated with the range of this operator, which must be compatible with Y...
void applyNonTranspose(const MV &X_in, MV &Y_in, Scalar alpha, Scalar beta) const
Special case of apply() for mode == Teuchos::NO_TRANS.
Teuchos::RCP< CrsMatrix< T, LocalOrdinal, GlobalOrdinal, Node > > convert() const
Return another CrsMatrix with the same entries, but converted to a different Scalar type T...
Allocation information for a locally owned row in a CrsGraph or CrsMatrix.
LocalOrdinal sumIntoLocalValues(const LocalOrdinal localRow, const typename UnmanagedView< LocalIndicesViewType >::type &inputInds, const typename UnmanagedView< ImplScalarViewType >::type &inputVals, const bool atomic=useAtomicUpdatesByDefault) const
Sum into one or more sparse matrix entries, using local row and column indices.
void swap(CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &matrix)
Swaps the data from *this with the data and maps from crsMatrix.
void fillLocalMatrix(const Teuchos::RCP< Teuchos::ParameterList > ¶ms)
Fill data into the local matrix.
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 isGloballyIndexed() const override
Whether the graph's column indices are stored as global indices.
Teuchos_Ordinal Array_size_type
Size type for Teuchos Array objects.
void globalAssemble()
Communicate nonlocal contributions to other processes.
void getLocalDiagCopy(Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &diag) const override
Get a copy of the diagonal entries of the matrix.
bool isNodeLocalElement(LocalOrdinal localIndex) const
Whether the given local index is valid for this Map on the calling process.
std::shared_ptr< local_multiply_op_type > lclMatrix_
The local sparse matrix, wrapped in a multiply operator.
void gaussSeidel(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &D, const Scalar &dampingFactor, const ESweepDirection direction, const int numSweeps) const
"Hybrid" Jacobi + (Gauss-Seidel or SOR) on .
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.
bool isFillActive() const
Whether the matrix is not fill complete.
Teuchos::RCP< MV > importMV_
Column Map MultiVector used in apply() and gaussSeidel().
typename Kokkos::ArithTraits< Scalar >::val_type impl_scalar_type
The type used internally in place of Scalar.
bool isStaticGraph() const
Indicates that the graph is static, so that new entries cannot be added to this matrix.
size_t global_size_t
Global size_t object.
bool hasTransposeApply() const override
Whether apply() allows applying the transpose or conjugate transpose.
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.
virtual void getGlobalRowCopy(GlobalOrdinal GlobalRow, const Teuchos::ArrayView< GlobalOrdinal > &Indices, const Teuchos::ArrayView< Scalar > &Values, size_t &NumEntries) const =0
Get a copy of the given global row's entries.
void clearGlobalConstants()
Clear matrix properties that require collectives.
void gaussSeidelCopy(MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &D, const Scalar &dampingFactor, const ESweepDirection direction, const int numSweeps, const bool zeroInitialGuess) const
Version of gaussSeidel(), with fewer requirements on X.
LocalOrdinal getLocalRowViewRaw(const LocalOrdinal lclRow, LocalOrdinal &numEnt, const LocalOrdinal *&lclColInds, const Scalar *&vals) const override
Get a constant, nonpersisting, locally indexed view of the given row of the matrix, using "raw" pointers instead of Teuchos::ArrayView.
void allocateValues(ELocalGlobal lg, GraphAllocationStatus gas)
Allocate values (and optionally indices) using the Node.
void exportAndFillComplete(Teuchos::RCP< CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &destMatrix, 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 matrix, and make the result fill complete.
Insert new values that don't currently exist.
bool isFillComplete() const override
Whether the matrix is fill complete.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
The communicator over which the matrix is distributed.
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.
void importAndFillComplete(Teuchos::RCP< CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &destMatrix, 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 matrix, and make the result fill complete.
void scale(const Scalar &alpha)
Scale in place: this = alpha*this.
Teuchos::RCP< const map_type > rowMap_
The Map describing the distribution of rows of the graph.
void packNew(const Kokkos::DualView< const local_ordinal_type *, buffer_device_type > &exportLIDs, Kokkos::DualView< char *, buffer_device_type > &exports, const Kokkos::DualView< size_t *, buffer_device_type > &numPacketsPerLID, size_t &constantNumPackets, Distributor &dist) const
Pack this object's data for an Import or Export.
num_row_entries_type k_numRowEntries_
The number of local entries in each locally owned row.
void reorderedGaussSeidelCopy(MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &D, const Teuchos::ArrayView< LocalOrdinal > &rowIndices, const Scalar &dampingFactor, const ESweepDirection direction, const int numSweeps, const bool zeroInitialGuess) const
Version of reorderedGaussSeidel(), with fewer requirements on X.
ESweepDirection
Sweep direction for Gauss-Seidel or Successive Over-Relaxation (SOR).
Functions for manipulating CRS arrays.
GlobalOrdinal getIndexBase() const override
The index base for global indices for this matrix.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
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.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getDomainMap() const =0
The Map associated with the domain of this operator, which must be compatible with X...
Teuchos::RCP< MV > getColumnMapMultiVector(const MV &X_domainMap, const bool force=false) const
Create a (or fetch a cached) column Map MultiVector.
#define TPETRA_ABUSE_WARNING(throw_exception_test, Exception, msg)
Handle an abuse warning, according to HAVE_TPETRA_THROW_ABUSE_WARNINGS and HAVE_TPETRA_PRINT_ABUSE_WA...
Sets up and executes a communication plan for a Tpetra DistObject.
mag_type frobNorm_
Cached Frobenius norm of the (global) matrix.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const override
Print this object with the given verbosity level to the given output stream.
Teuchos::RCP< const RowGraph< LocalOrdinal, GlobalOrdinal, Node > > getGraph() const override
This matrix's graph, as a RowGraph.
GlobalOrdinal getGlobalElement(LocalOrdinal localIndex) const
The global index corresponding to the given local index.
static bool verbose()
Whether Tpetra is in verbose mode.
CombineMode
Rule for combining data in an Import or Export.
Sum new values into existing values.
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
bool isFillComplete() const override
Whether fillComplete() has been called and the graph is in compute mode.
bool haveGlobalConstants() const
Returns true if globalConstants have been computed; false otherwise.
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...
bool isGloballyIndexed() const override
Whether the matrix is globally indexed on the calling process.
RowInfo getRowInfoFromGlobalRowIndex(const global_ordinal_type gblRow) const
Get information about the locally owned row with global index gblRow.
LocalOrdinal sumIntoGlobalValues(const GlobalOrdinal globalRow, const Teuchos::ArrayView< const GlobalOrdinal > &cols, const Teuchos::ArrayView< const Scalar > &vals, const bool atomic=useAtomicUpdatesByDefault)
Sum into one or more sparse matrix entries, using global indices.
Utility functions for packing and unpacking sparse matrix entries.
virtual Teuchos::RCP< RowMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > add(const Scalar &alpha, const RowMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Scalar &beta, const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &domainMap, const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &rangeMap, const Teuchos::RCP< Teuchos::ParameterList > ¶ms) const override
Implementation of RowMatrix::add: return alpha*A + beta*this.
bool fillComplete_
Whether the matrix is fill complete.
Replace old value with maximum of magnitudes of old and new values.
Abstract base class for objects that can be the source of an Import or Export operation.
typename Node::device_type device_type
The Kokkos device type.
size_t getNumEntriesInLocalRow(local_ordinal_type localRow) const override
Number of entries in the sparse matrix in the given local row, on the calling (MPI) process...
static LocalMapType::local_ordinal_type getDiagCopyWithoutOffsets(const DiagType &D, const LocalMapType &rowMap, const LocalMapType &colMap, const CrsMatrixType &A)
Given a locally indexed, local sparse matrix, and corresponding local row and column Maps...
Teuchos::RCP< MV > getRowMapMultiVector(const MV &Y_rangeMap, const bool force=false) const
Create a (or fetch a cached) row Map MultiVector.
std::string description() const override
A one-line description of this object.
void getLocalDiagOffsets(Teuchos::ArrayRCP< size_t > &offsets) const
Get offsets of the diagonal entries in the matrix.
void apply(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=Teuchos::ScalarTraits< Scalar >::one(), Scalar beta=Teuchos::ScalarTraits< Scalar >::zero()) const override
Compute a sparse matrix-MultiVector multiply.
LO getLocalDiagCopyWithoutOffsetsNotFillComplete(::Tpetra::Vector< SC, LO, GO, NT > &diag, const ::Tpetra::RowMatrix< SC, LO, GO, NT > &A, const bool debug=false)
Given a locally indexed, global sparse matrix, extract the matrix's diagonal entries into a Tpetra::V...
Replace existing values with new values.
void computeGlobalConstants()
Compute matrix properties that require collectives.
#define TPETRA_EFFICIENCY_WARNING(throw_exception_test, Exception, msg)
Print or throw an efficency warning.
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 matrix that you are done changing its structure or values, and that you are ready to do comp...
Teuchos::RCP< const map_type > getRangeMap() const override
Returns the Map associated with the domain of this graph.
Replace old values with zero.
std::string combineModeToString(const CombineMode combineMode)
Human-readable string representation of the given CombineMode.
void insertGlobalValues(const GlobalOrdinal globalRow, const Teuchos::ArrayView< const GlobalOrdinal > &cols, const Teuchos::ArrayView< const Scalar > &vals)
Insert one or more entries into the matrix, using global column indices.
void modify_host()
Mark data as modified on the host side.
bool isLocallyComplete() const
Is this Export or Import locally complete?
local_matrix_type::values_type getLocalValuesView() const
Get the Kokkos local values.
RowInfo getRowInfo(const local_ordinal_type myRow) const
Get information about the locally owned row with local index myRow.
ProfileType getProfileType() const
Returns true if the matrix was allocated with static data structures.
void getGlobalRowView(GlobalOrdinal GlobalRow, Teuchos::ArrayView< const GlobalOrdinal > &indices, Teuchos::ArrayView< const Scalar > &values) const override
Get a constant, nonpersisting view of a row of this matrix, using global row and column indices...
std::string dualViewStatusToString(const DualViewType &dv, const char name[])
Return the status of the given Kokkos::DualView, as a human-readable string.
virtual void removeEmptyProcessesInPlace(const Teuchos::RCP< const map_type > &newMap) override
Remove processes owning zero rows from the Maps and their communicator.
LocalOrdinal getLocalElement(GlobalOrdinal globalIndex) const
The local index corresponding to the given global index.
virtual bool checkSizes(const SrcDistObject &source) override
Compare the source and target (this) objects for compatibility.
local_map_type getLocalMap() const
Get the local Map for Kokkos kernels.
void insertLocalValues(const LocalOrdinal localRow, const Teuchos::ArrayView< const LocalOrdinal > &cols, const Teuchos::ArrayView< const Scalar > &vals)
Insert one or more entries into the matrix, using local column indices.
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2)
Sort the first array, and apply the resulting permutation to the second array.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
A parallel distribution of indices over processes.
void doExport(const SrcDistObject &source, const Export< LocalOrdinal, GlobalOrdinal, Node > &exporter, const CombineMode CM, const bool restrictedMode=false)
Export data into this object using an Export object ("forward mode").
Teuchos::RCP< const map_type > getDomainMap() const override
The domain Map of this matrix.
Teuchos::ArrayView< const impl_scalar_type > getView(RowInfo rowinfo) const
Constant view of all entries (including extra space) in the given row.
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.
KokkosSparse::CrsMatrix< impl_scalar_type, local_ordinal_type, execution_space, void, typename local_graph_type::size_type > local_matrix_type
The specialization of Kokkos::CrsMatrix that represents the part of the sparse matrix on each MPI pro...
void setAllValues(const typename local_matrix_type::row_map_type &ptr, const typename local_graph_type::entries_type::non_const_type &ind, const typename local_matrix_type::values_type &val)
Set the local matrix using three (compressed sparse row) arrays.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects...
A read-only, row-oriented interface to a sparse matrix.
local_matrix_type getLocalMatrix() const
The local sparse matrix.
void getLocalRowView(LocalOrdinal LocalRow, Teuchos::ArrayView< const LocalOrdinal > &indices, Teuchos::ArrayView< const Scalar > &values) const override
Get a constant, nonpersisting view of a row of this matrix, using local row and column indices...
void rightScale(const Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &x) override
Scale the matrix on the right with the given Vector.
size_t getNodeMaxNumRowEntries() const override
Maximum number of entries in any row of the matrix, on this process.
Scalar operator()(const Scalar &x, const Scalar &y)
Return the maximum of the magnitudes (absolute values) of x and y.
A distributed dense vector.
Declaration of Tpetra::Details::iallreduce.
void reduce()
Sum values of a locally replicated multivector across all processes.
Declaration and definition of Tpetra::Details::castAwayConstDualView, an implementation detail of Tpe...
std::shared_ptr< CommRequest > iallreduce(const InputViewType &sendbuf, const OutputViewType &recvbuf, const ::Teuchos::EReductionType op, const ::Teuchos::Comm< int > &comm)
Nonblocking all-reduce, for either rank-1 or rank-0 Kokkos::View objects.
KOKKOS_INLINE_FUNCTION void merge2(IT1 &indResultOut, IT2 &valResultOut, IT1 indBeg, IT1 indEnd, IT2 valBeg, IT2)
Merge values in place, additively, with the same index.
void applyTranspose(const MV &X_in, MV &Y_in, const Teuchos::ETransp mode, Scalar alpha, Scalar beta) const
Special case of apply() for mode != Teuchos::NO_TRANS.
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const ExecutionSpace &execSpace, const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
Kokkos::DualView< ValueType *, DeviceType > castAwayConstDualView(const Kokkos::DualView< const ValueType *, DeviceType > &input_dv)
Cast away const-ness of a 1-D Kokkos::DualView.
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 matrix that already has data.
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.
size_t getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const override
Number of entries in the sparse matrix in the given global row, on the calling (MPI) process...
size_t mergeRowIndicesAndValues(crs_graph_type &graph, const RowInfo &rowInfo)
Merge duplicate row indices in the given row, along with their corresponding values.
dual_view_type::t_dev getLocalViewDevice() const
A local Kokkos::View of device memory.
LocalOrdinal replaceGlobalValues(const GlobalOrdinal globalRow, const typename UnmanagedView< GlobalIndicesViewType >::type &inputInds, const typename UnmanagedView< ImplScalarViewType >::type &inputVals) const
Replace one or more entries' values, using global indices.
bool isLocallyIndexed() const override
Whether the matrix is locally indexed on the calling process.
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...
Teuchos::RCP< const map_type > getColMap() const override
The Map that describes the column distribution in this matrix.
void reorderedGaussSeidel(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &D, const Teuchos::ArrayView< LocalOrdinal > &rowIndices, const Scalar &dampingFactor, const ESweepDirection direction, const int numSweeps) const
Reordered "Hybrid" Jacobi + (Gauss-Seidel or SOR) on .
Declaration and definition of Tpetra::Details::getEntryOnHost.
Teuchos::ArrayView< impl_scalar_type > getViewNonConst(const RowInfo &rowinfo) const
Nonconst view of all entries (including extra space) in the given row.
Teuchos::RCP< const map_type > colMap_
The Map describing the distribution of columns of the graph.
LocalOrdinal local_ordinal_type
The type of each local index in the matrix.
mag_type getFrobeniusNorm() const override
Compute and return the Frobenius norm of the matrix.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRowMap() const =0
The Map that describes the distribution of rows over processes.
::Tpetra::Details::EStorageStatus storageStatus_
Status of the matrix's storage, when not in a fill-complete state.
void localApply(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Y, const Teuchos::ETransp mode=Teuchos::NO_TRANS, const Scalar &alpha=Teuchos::ScalarTraits< Scalar >::one(), const Scalar &beta=Teuchos::ScalarTraits< Scalar >::zero()) const
Compute the local part of a sparse matrix-(Multi)Vector multiply.
LocalOrdinal getViewRawConst(const impl_scalar_type *&vals, LocalOrdinal &numEnt, const RowInfo &rowinfo) const
Const pointer to all entries (including extra space) in the given row.
bool isStorageOptimized() const
Returns true if storage has been optimized.
Functions that wrap Kokkos::create_mirror_view, in order to avoid deep copies when not necessary...
void sync_device()
Synchronize to Device.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
Teuchos::RCP< MV > exportMV_
Row Map MultiVector used in apply().
Teuchos::RCP< const map_type > getRowMap() const override
The Map that describes the row distribution in this matrix.
global_size_t getGlobalNumEntries() const override
The global number of entries in this matrix.