43 #ifndef IFPACK2_EXPERIMENTAL_CRSRBILUK_DEF_HPP
44 #define IFPACK2_EXPERIMENTAL_CRSRBILUK_DEF_HPP
46 #include "Tpetra_Experimental_BlockMultiVector.hpp"
47 #include "Tpetra_Experimental_BlockView.hpp"
48 #include "Ifpack2_OverlappingRowMatrix.hpp"
49 #include "Ifpack2_LocalFilter.hpp"
51 #include "Ifpack2_RILUK.hpp"
54 #define IFPACK2_RBILUK_INITIAL_NOKK
56 #ifndef IFPACK2_RBILUK_INITIAL_NOKK
57 #include "KokkosBatched_Gemm_Decl.hpp"
58 #include "KokkosBatched_Gemm_Serial_Impl.hpp"
59 #include "KokkosBatched_Util.hpp"
64 namespace Experimental {
66 template<
class MatrixType>
70 A_block_(Teuchos::rcp_dynamic_cast<const block_crs_matrix_type>(Matrix_in))
73 template<
class MatrixType>
80 template<
class MatrixType>
84 template<
class MatrixType>
94 if (A.
getRawPtr () != A_block_.getRawPtr ())
96 this->isAllocated_ =
false;
97 this->isInitialized_ =
false;
98 this->isComputed_ =
false;
99 this->Graph_ = Teuchos::null;
100 L_block_ = Teuchos::null;
101 U_block_ = Teuchos::null;
102 D_block_ = Teuchos::null;
109 template<
class MatrixType>
110 const typename RBILUK<MatrixType>::block_crs_matrix_type&
114 L_block_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getL: The L factor "
115 "is null. Please call initialize() (and preferably also compute()) "
116 "before calling this method. If the input matrix has not yet been set, "
117 "you must first call setMatrix() with a nonnull input matrix before you "
118 "may call initialize() or compute().");
123 template<
class MatrixType>
124 const typename RBILUK<MatrixType>::block_crs_matrix_type&
128 D_block_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getD: The D factor "
129 "(of diagonal entries) is null. Please call initialize() (and "
130 "preferably also compute()) before calling this method. If the input "
131 "matrix has not yet been set, you must first call setMatrix() with a "
132 "nonnull input matrix before you may call initialize() or compute().");
137 template<
class MatrixType>
138 const typename RBILUK<MatrixType>::block_crs_matrix_type&
142 U_block_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getU: The U factor "
143 "is null. Please call initialize() (and preferably also compute()) "
144 "before calling this method. If the input matrix has not yet been set, "
145 "you must first call setMatrix() with a nonnull input matrix before you "
146 "may call initialize() or compute().");
150 template<
class MatrixType>
156 if (! this->isAllocated_) {
168 L_block_ =
rcp(
new block_crs_matrix_type(*this->Graph_->getL_Graph (), blockSize_) );
169 U_block_ =
rcp(
new block_crs_matrix_type(*this->Graph_->getU_Graph (), blockSize_) );
170 D_block_ =
rcp(
new block_crs_matrix_type(*(Ifpack2::Details::computeDiagonalGraph(*(this->Graph_->getOverlapGraph()))),
172 L_block_->setAllToScalar (STM::zero ());
173 U_block_->setAllToScalar (STM::zero ());
174 D_block_->setAllToScalar (STM::zero ());
177 this->isAllocated_ =
true;
180 template<
class MatrixType>
186 template<
class MatrixType>
191 using Teuchos::rcp_dynamic_cast;
192 const char prefix[] =
"Ifpack2::Experimental::RBILUK::initialize: ";
203 if (A_block_.is_null ()) {
208 RCP<const LocalFilter<row_matrix_type> > filteredA =
211 (filteredA.is_null (), std::runtime_error, prefix <<
212 "Cannot cast to filtered matrix.");
213 RCP<const OverlappingRowMatrix<row_matrix_type> > overlappedA =
215 if (! overlappedA.is_null ()) {
216 A_block_ = rcp_dynamic_cast<
const block_crs_matrix_type>(overlappedA->getUnderlyingMatrix());
219 A_block_ = rcp_dynamic_cast<
const block_crs_matrix_type>(filteredA->getUnderlyingMatrix());
224 (A_block_.is_null (), std::runtime_error, prefix <<
"The matrix (A_block_, "
225 "the BlockCrsMatrix) is null. Please call setMatrix() with a nonnull "
226 "input before calling this method.");
228 (! A_block_->isFillComplete (), std::runtime_error, prefix <<
"The matrix "
229 "(A_block_, the BlockCrsMatrix) is not fill complete. You may not invoke "
230 "initialize() or compute() with this matrix until the matrix is fill "
231 "complete. Note: BlockCrsMatrix is fill complete if and only if its "
232 "underlying graph is fill complete.");
234 blockSize_ = A_block_->getBlockSize();
247 this->isInitialized_ =
false;
248 this->isAllocated_ =
false;
249 this->isComputed_ =
false;
250 this->Graph_ = Teuchos::null;
256 RCP<const crs_graph_type> matrixCrsGraph = Teuchos::rcpFromRef(A_block_->getCrsGraph() );
258 this->LevelOfFill_, 0));
260 this->Graph_->initialize ();
261 allocate_L_and_U_blocks ();
262 #ifdef IFPACK2_RBILUK_INITIAL
263 initAllValues (*A_block_);
267 this->isInitialized_ =
true;
268 this->numInitialize_ += 1;
273 template<
class MatrixType>
279 typedef Tpetra::Map<local_ordinal_type,global_ordinal_type,node_type> map_type;
281 local_ordinal_type NumIn = 0, NumL = 0, NumU = 0;
282 bool DiagFound =
false;
283 size_t NumNonzeroDiags = 0;
284 size_t MaxNumEntries = A.getNodeMaxNumRowEntries();
285 local_ordinal_type blockMatSize = blockSize_*blockSize_;
292 bool gidsAreConsistentlyOrdered=
true;
293 global_ordinal_type indexOfInconsistentGID=0;
294 for (global_ordinal_type i=0; i<rowGIDs.
size(); ++i) {
295 if (rowGIDs[i] != colGIDs[i]) {
296 gidsAreConsistentlyOrdered=
false;
297 indexOfInconsistentGID=i;
302 "The ordering of the local GIDs in the row and column maps is not the same"
303 << std::endl <<
"at index " << indexOfInconsistentGID
304 <<
". Consistency is required, as all calculations are done with"
305 << std::endl <<
"local indexing.");
316 L_block_->setAllToScalar (STM::zero ());
317 U_block_->setAllToScalar (STM::zero ());
318 D_block_->setAllToScalar (STM::zero ());
323 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
324 const_cast<block_crs_matrix_type&
> (A).
template sync<Kokkos::HostSpace> ();
325 L_block_->template sync<Kokkos::HostSpace> ();
326 U_block_->template sync<Kokkos::HostSpace> ();
327 D_block_->template sync<Kokkos::HostSpace> ();
329 L_block_->template modify<Kokkos::HostSpace> ();
330 U_block_->template modify<Kokkos::HostSpace> ();
331 D_block_->template modify<Kokkos::HostSpace> ();
333 const_cast<block_crs_matrix_type&
> (A).sync_host ();
334 L_block_->sync_host ();
335 U_block_->sync_host ();
336 D_block_->sync_host ();
338 L_block_->modify_host ();
339 U_block_->modify_host ();
340 D_block_->modify_host ();
343 RCP<const map_type> rowMap = L_block_->getRowMap ();
353 for (
size_t myRow=0; myRow<A.getNodeNumRows(); ++myRow) {
354 local_ordinal_type local_row = myRow;
358 const local_ordinal_type * InI = 0;
359 scalar_type * InV = 0;
360 A.getLocalRowView(local_row, InI, InV, NumIn);
368 for (local_ordinal_type j = 0; j < NumIn; ++j) {
369 const local_ordinal_type k = InI[j];
370 const local_ordinal_type blockOffset = blockMatSize*j;
372 if (k == local_row) {
375 for (local_ordinal_type jj = 0; jj < blockMatSize; ++jj)
376 diagValues[jj] = this->Rthresh_ * InV[blockOffset+jj] + IFPACK2_SGN(InV[blockOffset+jj]) * this->Athresh_;
377 D_block_->replaceLocalValues(local_row, &InI[j], diagValues.getRawPtr(), 1);
381 true, std::runtime_error,
"Ifpack2::RILUK::initAllValues: current "
382 "GID k = " << k <<
" < 0. I'm not sure why this is an error; it is "
383 "probably an artifact of the undocumented assumptions of the "
384 "original implementation (likely copied and pasted from Ifpack). "
385 "Nevertheless, the code I found here insisted on this being an error "
386 "state, so I will throw an exception here.");
388 else if (k < local_row) {
390 const local_ordinal_type LBlockOffset = NumL*blockMatSize;
391 for (local_ordinal_type jj = 0; jj < blockMatSize; ++jj)
392 LV[LBlockOffset+jj] = InV[blockOffset+jj];
395 else if (Teuchos::as<size_t>(k) <= rowMap->getNodeNumElements()) {
397 const local_ordinal_type UBlockOffset = NumU*blockMatSize;
398 for (local_ordinal_type jj = 0; jj < blockMatSize; ++jj)
399 UV[UBlockOffset+jj] = InV[blockOffset+jj];
410 for (local_ordinal_type jj = 0; jj < blockSize_; ++jj)
411 diagValues[jj*(blockSize_+1)] = this->Athresh_;
412 D_block_->replaceLocalValues(local_row, &local_row, diagValues.getRawPtr(), 1);
416 L_block_->replaceLocalValues(local_row, &LI[0], &LV[0], NumL);
420 U_block_->replaceLocalValues(local_row, &UI[0], &UV[0], NumU);
427 typedef typename block_crs_matrix_type::device_type device_type;
428 const_cast<block_crs_matrix_type&
> (A).
template sync<device_type> ();
429 L_block_->template sync<device_type> ();
430 U_block_->template sync<device_type> ();
431 D_block_->template sync<device_type> ();
433 this->isInitialized_ =
true;
442 template<
class LittleBlockType>
443 struct GetManagedView {
444 static_assert (Kokkos::Impl::is_view<LittleBlockType>::value,
445 "LittleBlockType must be a Kokkos::View.");
446 typedef Kokkos::View<
typename LittleBlockType::non_const_data_type,
447 typename LittleBlockType::array_layout,
448 typename LittleBlockType::device_type> managed_non_const_type;
449 static_assert (static_cast<int> (managed_non_const_type::rank) ==
450 static_cast<int> (LittleBlockType::rank),
451 "managed_non_const_type::rank != LittleBlock::rank. "
452 "Please report this bug to the Ifpack2 developers.");
457 template<
class MatrixType>
460 typedef impl_scalar_type IST;
461 const char prefix[] =
"Ifpack2::Experimental::RBILUK::compute: ";
467 (A_block_.is_null (), std::runtime_error, prefix <<
"The matrix (A_block_, "
468 "the BlockCrsMatrix) is null. Please call setMatrix() with a nonnull "
469 "input before calling this method.");
471 (! A_block_->isFillComplete (), std::runtime_error, prefix <<
"The matrix "
472 "(A_block_, the BlockCrsMatrix) is not fill complete. You may not invoke "
473 "initialize() or compute() with this matrix until the matrix is fill "
474 "complete. Note: BlockCrsMatrix is fill complete if and only if its "
475 "underlying graph is fill complete.");
477 if (! this->isInitialized ()) {
484 if (! A_block_.is_null ()) {
486 Teuchos::rcp_const_cast<block_crs_matrix_type> (A_block_);
487 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
488 A_nc->template sync<Kokkos::HostSpace> ();
493 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
494 L_block_->template sync<Kokkos::HostSpace> ();
495 U_block_->template sync<Kokkos::HostSpace> ();
496 D_block_->template sync<Kokkos::HostSpace> ();
498 L_block_->template modify<Kokkos::HostSpace> ();
499 U_block_->template modify<Kokkos::HostSpace> ();
500 D_block_->template modify<Kokkos::HostSpace> ();
502 L_block_->sync_host ();
503 U_block_->sync_host ();
504 D_block_->sync_host ();
506 L_block_->modify_host ();
507 U_block_->modify_host ();
508 D_block_->modify_host ();
514 this->isComputed_ =
false;
521 initAllValues (*A_block_);
527 const size_t MaxNumEntries =
528 L_block_->getNodeMaxNumRowEntries () + U_block_->getNodeMaxNumRowEntries () + 1;
538 Kokkos::View<
int*, Kokkos::HostSpace,
539 Kokkos::MemoryUnmanaged> ipiv (ipiv_teuchos.
getRawPtr (), blockSize_);
541 Kokkos::View<IST*, Kokkos::HostSpace,
542 Kokkos::MemoryUnmanaged> work (work_teuchos.getRawPtr (), blockSize_);
544 size_t num_cols = U_block_->getColMap()->getNodeNumElements();
547 typename GetManagedView<little_block_type>::managed_non_const_type diagModBlock (
"diagModBlock", blockSize_, blockSize_);
548 typename GetManagedView<little_block_type>::managed_non_const_type matTmp (
"matTmp", blockSize_, blockSize_);
549 typename GetManagedView<little_block_type>::managed_non_const_type multiplier (
"multiplier", blockSize_, blockSize_);
557 for (
size_t j = 0; j < num_cols; ++j) {
568 NumIn = MaxNumEntries;
572 L_block_->getLocalRowView(local_row, colValsL, valsL, NumL);
576 little_block_type lmat((
typename little_block_type::value_type*) &valsL[matOffset],blockSize_,rowStride);
577 little_block_type lmatV((
typename little_block_type::value_type*) &InV[matOffset],blockSize_,rowStride);
579 Tpetra::Experimental::COPY (lmat, lmatV);
580 InI[j] = colValsL[j];
583 little_block_type dmat = D_block_->getLocalBlock(local_row, local_row);
584 little_block_type dmatV((
typename little_block_type::value_type*) &InV[NumL*blockMatSize], blockSize_, rowStride);
586 Tpetra::Experimental::COPY (dmat, dmatV);
587 InI[NumL] = local_row;
591 U_block_->getLocalRowView(local_row, colValsU, valsU, NumURead);
595 if (!(colValsU[j] < numLocalRows))
continue;
596 InI[NumL+1+j] = colValsU[j];
598 little_block_type umat((
typename little_block_type::value_type*) &valsU[blockMatSize*j], blockSize_, rowStride);
599 little_block_type umatV((
typename little_block_type::value_type*) &InV[matOffset], blockSize_, rowStride);
601 Tpetra::Experimental::COPY (umat, umatV);
607 for (
size_t j = 0; j < NumIn; ++j) {
611 #ifndef IFPACK2_RBILUK_INITIAL
615 diagModBlock(i,j) = 0;
620 Kokkos::deep_copy (diagModBlock, diagmod);
625 little_block_type currentVal((
typename little_block_type::value_type*) &InV[jj*blockMatSize], blockSize_, rowStride);
627 Tpetra::Experimental::COPY (currentVal, multiplier);
629 const little_block_type dmatInverse = D_block_->getLocalBlock(j,j);
631 #ifndef IFPACK2_RBILUK_INITIAL_NOKK
632 KokkosBatched::Experimental::SerialGemm
633 <KokkosBatched::Experimental::Trans::NoTranspose,
634 KokkosBatched::Experimental::Trans::NoTranspose,
635 KokkosBatched::Experimental::Algo::Gemm::Blocked>::invoke
636 (STS::one (), currentVal, dmatInverse, STS::zero (), matTmp);
638 Tpetra::Experimental::GEMM (
"N",
"N", STS::one (), currentVal, dmatInverse,
639 STS::zero (), matTmp);
643 Tpetra::Experimental::COPY (matTmp, currentVal);
647 U_block_->getLocalRowView(j, UUI, UUV, NumUU);
649 if (this->RelaxValue_ == STM::zero ()) {
651 if (!(UUI[k] < numLocalRows))
continue;
652 const int kk = colflag[UUI[k]];
654 little_block_type kkval((
typename little_block_type::value_type*) &InV[kk*blockMatSize], blockSize_, rowStride);
655 little_block_type uumat((
typename little_block_type::value_type*) &UUV[k*blockMatSize], blockSize_, rowStride);
656 #ifndef IFPACK2_RBILUK_INITIAL_NOKK
657 KokkosBatched::Experimental::SerialGemm
658 <KokkosBatched::Experimental::Trans::NoTranspose,
659 KokkosBatched::Experimental::Trans::NoTranspose,
660 KokkosBatched::Experimental::Algo::Gemm::Blocked>::invoke
661 (
magnitude_type(-STM::one ()), multiplier, uumat, STM::one (), kkval);
663 Tpetra::Experimental::GEMM (
"N",
"N",
magnitude_type(-STM::one ()), multiplier, uumat,
672 if (!(UUI[k] < numLocalRows))
continue;
673 const int kk = colflag[UUI[k]];
674 little_block_type uumat((
typename little_block_type::value_type*) &UUV[k*blockMatSize], blockSize_, rowStride);
676 little_block_type kkval((
typename little_block_type::value_type*) &InV[kk*blockMatSize], blockSize_, rowStride);
677 #ifndef IFPACK2_RBILUK_INITIAL_NOKK
678 KokkosBatched::Experimental::SerialGemm
679 <KokkosBatched::Experimental::Trans::NoTranspose,
680 KokkosBatched::Experimental::Trans::NoTranspose,
681 KokkosBatched::Experimental::Algo::Gemm::Blocked>::invoke
682 (
magnitude_type(-STM::one ()), multiplier, uumat, STM::one (), kkval);
684 Tpetra::Experimental::GEMM (
"N",
"N",
magnitude_type(-STM::one ()), multiplier, uumat,
690 #ifndef IFPACK2_RBILUK_INITIAL_NOKK
691 KokkosBatched::Experimental::SerialGemm
692 <KokkosBatched::Experimental::Trans::NoTranspose,
693 KokkosBatched::Experimental::Trans::NoTranspose,
694 KokkosBatched::Experimental::Algo::Gemm::Blocked>::invoke
695 (
magnitude_type(-STM::one ()), multiplier, uumat, STM::one (), diagModBlock);
697 Tpetra::Experimental::GEMM (
"N",
"N",
magnitude_type(-STM::one ()), multiplier, uumat,
698 STM::one (), diagModBlock);
711 Tpetra::Experimental::COPY (dmatV, dmat);
713 if (this->RelaxValue_ != STM::zero ()) {
715 Tpetra::Experimental::AXPY (this->RelaxValue_, diagModBlock, dmat);
729 for (
int k = 0; k < blockSize_; ++k) {
733 Tpetra::Experimental::GETF2 (dmat, ipiv, lapackInfo);
736 lapackInfo != 0, std::runtime_error,
"Ifpack2::Experimental::RBILUK::compute: "
737 "lapackInfo = " << lapackInfo <<
" which indicates an error in the factorization GETRF.");
739 Tpetra::Experimental::GETRI (dmat, ipiv, work, lapackInfo);
742 lapackInfo != 0, std::runtime_error,
"Ifpack2::Experimental::RBILUK::compute: "
743 "lapackInfo = " << lapackInfo <<
" which indicates an error in the matrix inverse GETRI.");
747 little_block_type currentVal((
typename little_block_type::value_type*) &InV[(NumL+1+j)*blockMatSize], blockSize_, rowStride);
749 #ifndef IFPACK2_RBILUK_INITIAL_NOKK
750 KokkosBatched::Experimental::SerialGemm
751 <KokkosBatched::Experimental::Trans::NoTranspose,
752 KokkosBatched::Experimental::Trans::NoTranspose,
753 KokkosBatched::Experimental::Algo::Gemm::Blocked>::invoke
754 (STS::one (), dmat, currentVal, STS::zero (), matTmp);
756 Tpetra::Experimental::GEMM (
"N",
"N", STS::one (), dmat, currentVal,
757 STS::zero (), matTmp);
761 Tpetra::Experimental::COPY (matTmp, currentVal);
766 U_block_->replaceLocalValues (local_row, &InI[NumL+1], &InV[blockMatSize*(NumL+1)], NumU);
769 #ifndef IFPACK2_RBILUK_INITIAL
771 for (
size_t j = 0; j < NumIn; ++j) {
772 colflag[InI[j]] = -1;
776 for (
size_t j = 0; j < num_cols; ++j) {
786 typedef typename block_crs_matrix_type::device_type device_type;
787 if (! A_block_.is_null ()) {
789 Teuchos::rcp_const_cast<block_crs_matrix_type> (A_block_);
790 A_nc->template sync<device_type> ();
792 L_block_->template sync<device_type> ();
793 U_block_->template sync<device_type> ();
794 D_block_->template sync<device_type> ();
797 this->isComputed_ =
true;
798 this->numCompute_ += 1;
803 template<
class MatrixType>
806 apply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
807 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
813 typedef Tpetra::Experimental::BlockMultiVector<
scalar_type,
815 typedef Tpetra::MultiVector<scalar_type,
816 local_ordinal_type, global_ordinal_type,
node_type> MV;
819 A_block_.is_null (), std::runtime_error,
"Ifpack2::Experimental::RBILUK::apply: The matrix is "
820 "null. Please call setMatrix() with a nonnull input, then initialize() "
821 "and compute(), before calling this method.");
823 ! this->isComputed (), std::runtime_error,
824 "Ifpack2::Experimental::RBILUK::apply: If you have not yet called compute(), "
825 "you must call compute() before calling this method.");
826 TEUCHOS_TEST_FOR_EXCEPTION(
827 X.getNumVectors () != Y.getNumVectors (), std::invalid_argument,
828 "Ifpack2::Experimental::RBILUK::apply: X and Y do not have the same number of columns. "
829 "X.getNumVectors() = " << X.getNumVectors ()
830 <<
" != Y.getNumVectors() = " << Y.getNumVectors () <<
".");
831 TEUCHOS_TEST_FOR_EXCEPTION(
833 "Ifpack2::Experimental::RBILUK::apply: mode = Teuchos::CONJ_TRANS is not implemented for "
834 "complex Scalar type. Please talk to the Ifpack2 developers to get this "
835 "fixed. There is a FIXME in this file about this very issue.");
837 const local_ordinal_type blockMatSize = blockSize_*blockSize_;
839 const local_ordinal_type rowStride = blockSize_;
841 BMV yBlock (Y, * (A_block_->getGraph ()->getDomainMap ()), blockSize_);
842 const BMV xBlock (X, * (A_block_->getColMap ()), blockSize_);
845 little_vec_type lclvec((
typename little_vec_type::value_type*)&lclarray[0], blockSize_);
846 const scalar_type one = STM::one ();
847 const scalar_type zero = STM::zero ();
852 if (alpha == one && beta == zero) {
860 const local_ordinal_type numVectors = xBlock.getNumVectors();
861 BMV cBlock (* (A_block_->getGraph ()->getDomainMap ()), blockSize_, numVectors);
862 BMV rBlock (* (A_block_->getGraph ()->getDomainMap ()), blockSize_, numVectors);
863 for (local_ordinal_type imv = 0; imv < numVectors; ++imv)
865 for (
size_t i = 0; i < D_block_->getNodeNumRows(); ++i)
867 local_ordinal_type local_row = i;
868 little_vec_type xval = xBlock.getLocalBlock(local_row,imv);
869 little_vec_type cval = cBlock.getLocalBlock(local_row,imv);
871 Tpetra::Experimental::COPY (xval, cval);
873 local_ordinal_type NumL;
874 const local_ordinal_type * colValsL;
877 L_block_->getLocalRowView(local_row, colValsL, valsL, NumL);
879 for (local_ordinal_type j = 0; j < NumL; ++j)
881 local_ordinal_type col = colValsL[j];
882 little_vec_type prevVal = cBlock.getLocalBlock(col, imv);
884 const local_ordinal_type matOffset = blockMatSize*j;
885 little_block_type lij((
typename little_block_type::value_type*) &valsL[matOffset],blockSize_,rowStride);
888 Tpetra::Experimental::GEMV (-one, lij, prevVal, cval);
894 D_block_->applyBlock(cBlock, rBlock);
897 for (local_ordinal_type imv = 0; imv < numVectors; ++imv)
899 const local_ordinal_type numRows = D_block_->getNodeNumRows();
900 for (local_ordinal_type i = 0; i < numRows; ++i)
902 local_ordinal_type local_row = (numRows-1)-i;
903 little_vec_type rval = rBlock.getLocalBlock(local_row,imv);
904 little_vec_type yval = yBlock.getLocalBlock(local_row,imv);
906 Tpetra::Experimental::COPY (rval, yval);
908 local_ordinal_type NumU;
909 const local_ordinal_type * colValsU;
912 U_block_->getLocalRowView(local_row, colValsU, valsU, NumU);
914 for (local_ordinal_type j = 0; j < NumU; ++j)
916 local_ordinal_type col = colValsU[NumU-1-j];
917 little_vec_type prevVal = yBlock.getLocalBlock(col, imv);
919 const local_ordinal_type matOffset = blockMatSize*(NumU-1-j);
920 little_block_type uij((
typename little_block_type::value_type*) &valsU[matOffset], blockSize_, rowStride);
923 Tpetra::Experimental::GEMV (-one, uij, prevVal, yval);
929 TEUCHOS_TEST_FOR_EXCEPTION(
930 true, std::runtime_error,
931 "Ifpack2::Experimental::RBILUK::apply: transpose apply is not implemented for the block algorithm. ");
942 MV Y_tmp (Y.getMap (), Y.getNumVectors ());
943 apply (X, Y_tmp, mode);
944 Y.update (alpha, Y_tmp, beta);
949 this->numApply_ += 1;
954 template<
class MatrixType>
957 std::ostringstream os;
962 os <<
"\"Ifpack2::Experimental::RBILUK\": {";
963 os <<
"Initialized: " << (this->isInitialized () ?
"true" :
"false") <<
", "
964 <<
"Computed: " << (this->isComputed () ?
"true" :
"false") <<
", ";
966 os <<
"Level-of-fill: " << this->getLevelOfFill() <<
", ";
968 if (A_block_.is_null ()) {
969 os <<
"Matrix: null";
972 os <<
"Global matrix dimensions: ["
973 << A_block_->getGlobalNumRows () <<
", " << A_block_->getGlobalNumCols () <<
"]"
974 <<
", Global nnz: " << A_block_->getGlobalNumEntries();
989 #define IFPACK2_EXPERIMENTAL_RBILUK_INSTANT(S,LO,GO,N) \
990 template class Ifpack2::Experimental::RBILUK< Tpetra::BlockCrsMatrix<S, LO, GO, N> >; \
991 template class Ifpack2::Experimental::RBILUK< Tpetra::RowMatrix<S, LO, GO, N> >;
void initialize()
Initialize by computing the symbolic incomplete factorization.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:187
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition: Ifpack2_Experimental_RBILUK_decl.hpp:145
virtual ~RBILUK()
Destructor (declared virtual for memory safety).
Definition: Ifpack2_Experimental_RBILUK_def.hpp:81
Teuchos::RCP< const block_crs_matrix_type > getBlockMatrix() const
Get the input matrix.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:182
const block_crs_matrix_type & getUBlock() const
Return the U factor of the ILU factorization.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:139
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_Experimental_RBILUK_decl.hpp:136
void apply(const Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &X, Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, scalar_type alpha=Teuchos::ScalarTraits< scalar_type >::one(), scalar_type beta=Teuchos::ScalarTraits< scalar_type >::zero()) const
Apply the (inverse of the) incomplete factorization to X, resulting in Y.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:806
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Teuchos::ScalarTraits< scalar_type >::magnitudeType magnitude_type
The type of the magnitude (absolute value) of a matrix entry.
Definition: Ifpack2_Experimental_RBILUK_decl.hpp:151
ILU(k) factorization of a given Tpetra::RowMatrix.
Definition: Ifpack2_RILUK_decl.hpp:243
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition: Ifpack2_Experimental_RBILUK_decl.hpp:148
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition: Ifpack2_Experimental_RBILUK_decl.hpp:142
const block_crs_matrix_type & getDBlock() const
Return the diagonal entries of the ILU factorization.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:125
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void compute()
Compute the (numeric) incomplete factorization.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:458
File for utility functions.
Construct a level filled graph for use in computing an ILU(k) incomplete factorization.
Definition: Ifpack2_IlukGraph.hpp:97
void setMatrix(const Teuchos::RCP< const block_crs_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:86
const block_crs_matrix_type & getLBlock() const
Return the L factor of the ILU factorization.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:111
Sparse matrix (Tpetra::RowMatrix subclass) with ghost rows.
Definition: Ifpack2_OverlappingRowMatrix_decl.hpp:58
double totalElapsedTime(bool readCurrentTime=false) const
Access only local rows and columns of a sparse matrix.
Definition: Ifpack2_LocalFilter_decl.hpp:160
Tpetra::RowMatrix< scalar_type, local_ordinal_type, global_ordinal_type, node_type > row_matrix_type
Tpetra::RowMatrix specialization used by this class.
Definition: Ifpack2_Experimental_RBILUK_decl.hpp:157
std::string description() const
A one-line description of this object.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:955
ILU(k) factorization of a given Tpetra::BlockCrsMatrix.
Definition: Ifpack2_Experimental_RBILUK_decl.hpp:128