43 #ifndef IFPACK2_EXPERIMENTAL_CRSRBILUK_DEF_HPP
44 #define IFPACK2_EXPERIMENTAL_CRSRBILUK_DEF_HPP
46 #include "Tpetra_BlockMultiVector.hpp"
47 #include "Tpetra_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 {
68 template<
class MatrixType>
69 struct LocalRowHandler
71 using LocalOrdinal =
typename MatrixType::local_ordinal_type;
72 using row_matrix_type = Tpetra::RowMatrix<
73 typename MatrixType::scalar_type,
75 typename MatrixType::global_ordinal_type,
76 typename MatrixType::node_type>;
77 using inds_type =
typename row_matrix_type::local_inds_host_view_type;
78 using vals_type =
typename row_matrix_type::values_host_view_type;
83 if (!A_->supportsRowViews())
85 const auto maxNumRowEntr = A_->getLocalMaxNumRowEntries();
86 const auto blockSize = A_->getBlockSize();
87 ind_nc_ = inds_type_nc(
"Ifpack2::RBILUK::LocalRowHandler::indices",maxNumRowEntr);
88 val_nc_ = vals_type_nc(
"Ifpack2::RBILUK::LocalRowHandler::values",maxNumRowEntr*blockSize*blockSize);
92 void getLocalRow(LocalOrdinal local_row, inds_type & InI, vals_type & InV, LocalOrdinal & NumIn)
94 if (A_->supportsRowViews())
96 A_->getLocalRowView(local_row,InI,InV);
97 NumIn = (LocalOrdinal)InI.size();
102 A_->getLocalRowCopy(local_row,ind_nc_,val_nc_,cnt);
105 NumIn = (LocalOrdinal)cnt;
111 using inds_type_nc =
typename row_matrix_type::nonconst_local_inds_host_view_type;
112 using vals_type_nc =
typename row_matrix_type::nonconst_values_host_view_type;
115 inds_type_nc ind_nc_;
116 vals_type_nc val_nc_;
121 template<
class MatrixType>
126 template<
class MatrixType>
132 template<
class MatrixType>
136 template<
class MatrixType>
148 this->isAllocated_ =
false;
149 this->isInitialized_ =
false;
150 this->isComputed_ =
false;
151 this->Graph_ = Teuchos::null;
152 L_block_ = Teuchos::null;
153 U_block_ = Teuchos::null;
154 D_block_ = Teuchos::null;
160 template<
class MatrixType>
161 const typename RBILUK<MatrixType>::block_crs_matrix_type&
165 L_block_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getL: The L factor "
166 "is null. Please call initialize() (and preferably also compute()) "
167 "before calling this method. If the input matrix has not yet been set, "
168 "you must first call setMatrix() with a nonnull input matrix before you "
169 "may call initialize() or compute().");
174 template<
class MatrixType>
175 const typename RBILUK<MatrixType>::block_crs_matrix_type&
179 D_block_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getD: The D factor "
180 "(of diagonal entries) is null. Please call initialize() (and "
181 "preferably also compute()) before calling this method. If the input "
182 "matrix has not yet been set, you must first call setMatrix() with a "
183 "nonnull input matrix before you may call initialize() or compute().");
188 template<
class MatrixType>
189 const typename RBILUK<MatrixType>::block_crs_matrix_type&
193 U_block_.is_null (), std::runtime_error,
"Ifpack2::RILUK::getU: The U factor "
194 "is null. Please call initialize() (and preferably also compute()) "
195 "before calling this method. If the input matrix has not yet been set, "
196 "you must first call setMatrix() with a nonnull input matrix before you "
197 "may call initialize() or compute().");
201 template<
class MatrixType>
207 if (! this->isAllocated_) {
219 L_block_ =
rcp(
new block_crs_matrix_type(*this->Graph_->getL_Graph (), blockSize_) );
220 U_block_ =
rcp(
new block_crs_matrix_type(*this->Graph_->getU_Graph (), blockSize_) );
221 D_block_ =
rcp(
new block_crs_matrix_type(*(Ifpack2::Details::computeDiagonalGraph(*(this->Graph_->getOverlapGraph()))),
223 L_block_->setAllToScalar (STM::zero ());
224 U_block_->setAllToScalar (STM::zero ());
225 D_block_->setAllToScalar (STM::zero ());
228 this->isAllocated_ =
true;
233 template<
class MatrixType>
235 makeLocalFilter (
const Teuchos::RCP<
const typename RBILUK<MatrixType>::row_matrix_type>& A)
237 using row_matrix_type =
typename RBILUK<MatrixType>::row_matrix_type;
240 using Teuchos::rcp_dynamic_cast;
241 using Teuchos::rcp_implicit_cast;
246 if (A->getRowMap ()->getComm ()->getSize () == 1 ||
247 A->getRowMap ()->isSameAs (* (A->getColMap ()))) {
254 RCP<const LocalFilter<row_matrix_type> > A_lf_r =
255 rcp_dynamic_cast<
const LocalFilter<row_matrix_type> > (A);
256 if (! A_lf_r.is_null ()) {
257 return rcp_implicit_cast<
const row_matrix_type> (A_lf_r);
263 return rcp (
new LocalFilter<row_matrix_type> (A));
267 template<
class MatrixType>
269 getBlockCrsGraph(
const Teuchos::RCP<
const typename RBILUK<MatrixType>::row_matrix_type>& A,
const typename MatrixType::local_ordinal_type blockSize)
271 using local_ordinal_type =
typename MatrixType::local_ordinal_type;
274 using Teuchos::rcp_dynamic_cast;
275 using Teuchos::rcp_const_cast;
276 using Teuchos::rcpFromRef;
277 using row_matrix_type =
typename RBILUK<MatrixType>::row_matrix_type;
278 using crs_graph_type =
typename RBILUK<MatrixType>::crs_graph_type;
279 using block_crs_matrix_type =
typename RBILUK<MatrixType>::block_crs_matrix_type;
281 auto A_local = makeLocalFilter<MatrixType>(A);
284 RCP<const LocalFilter<row_matrix_type> > filteredA =
285 rcp_dynamic_cast<
const LocalFilter<row_matrix_type> >(A_local);
286 RCP<const OverlappingRowMatrix<row_matrix_type> > overlappedA = Teuchos::null;
287 RCP<const block_crs_matrix_type > A_block = Teuchos::null;
288 if (!filteredA.is_null ())
290 overlappedA = rcp_dynamic_cast<
const OverlappingRowMatrix<row_matrix_type> > (filteredA->getUnderlyingMatrix ());
293 if (! overlappedA.is_null ()) {
294 A_block = rcp_dynamic_cast<
const block_crs_matrix_type>(overlappedA->getUnderlyingMatrix());
296 else if (!filteredA.is_null ()){
298 A_block = rcp_dynamic_cast<
const block_crs_matrix_type>(filteredA->getUnderlyingMatrix());
302 A_block = rcp_dynamic_cast<
const block_crs_matrix_type>(A_local);
305 if (!A_block.is_null()){
306 return rcpFromRef(A_block->getCrsGraph());
312 local_ordinal_type numRows = A_local->getLocalNumRows();
314 for(local_ordinal_type i = 0; i < numRows; i++) {
315 entriesPerRow[i] = A_local->getNumEntriesInLocalRow(i);
317 RCP<crs_graph_type> A_local_crs_nc =
318 rcp (
new crs_graph_type (A_local->getRowMap (),
319 A_local->getColMap (),
323 using LocalRowHandler_t = LocalRowHandler<MatrixType>;
324 LocalRowHandler_t localRowHandler(A_local);
325 typename LocalRowHandler_t::inds_type indices;
326 typename LocalRowHandler_t::vals_type values;
327 for(local_ordinal_type i = 0; i < numRows; i++) {
328 local_ordinal_type numEntries = 0;
329 localRowHandler.getLocalRow(i, indices, values, numEntries);
330 A_local_crs_nc->insertLocalIndices(i, numEntries,indices.data());
334 A_local_crs_nc->fillComplete (A_local->getDomainMap (), A_local->getRangeMap ());
335 return rcp_const_cast<
const crs_graph_type> (A_local_crs_nc);
343 template<
class MatrixType>
348 using Teuchos::rcp_dynamic_cast;
349 const char prefix[] =
"Ifpack2::Experimental::RBILUK::initialize: ";
352 (this->A_.
is_null (), std::runtime_error, prefix <<
"The matrix (A_, the "
353 "RowMatrix) is null. Please call setMatrix() with a nonnull input "
354 "before calling this method.");
356 (! this->A_->isFillComplete (), std::runtime_error, prefix <<
"The matrix "
357 "(A_, the BlockCrsMatrix) is not fill complete. You may not invoke "
358 "initialize() or compute() with this matrix until the matrix is fill "
359 "complete. Note: BlockCrsMatrix is fill complete if and only if its "
360 "underlying graph is fill complete.");
362 blockSize_ = this->A_->getBlockSize();
365 double startTime = timer.
wallTime();
376 this->isInitialized_ =
false;
377 this->isAllocated_ =
false;
378 this->isComputed_ =
false;
379 this->Graph_ = Teuchos::null;
381 RCP<const crs_graph_type> matrixCrsGraph = getBlockCrsGraph<MatrixType>(this->A_,blockSize_);
383 this->LevelOfFill_, 0));
385 this->Graph_->initialize ();
386 allocate_L_and_U_blocks ();
387 #ifdef IFPACK2_RBILUK_INITIAL
392 this->isInitialized_ =
true;
393 this->numInitialize_ += 1;
394 this->initializeTime_ += (timer.
wallTime() - startTime);
398 template<
class MatrixType>
404 typedef Tpetra::Map<LO,GO,node_type> map_type;
406 LO NumIn = 0, NumL = 0, NumU = 0;
407 bool DiagFound =
false;
408 size_t NumNonzeroDiags = 0;
409 size_t MaxNumEntries = this->A_->getLocalMaxNumRowEntries();
410 LO blockMatSize = blockSize_*blockSize_;
417 bool gidsAreConsistentlyOrdered=
true;
418 GO indexOfInconsistentGID=0;
419 for (GO i=0; i<rowGIDs.
size(); ++i) {
420 if (rowGIDs[i] != colGIDs[i]) {
421 gidsAreConsistentlyOrdered=
false;
422 indexOfInconsistentGID=i;
427 "The ordering of the local GIDs in the row and column maps is not the same"
428 << std::endl <<
"at index " << indexOfInconsistentGID
429 <<
". Consistency is required, as all calculations are done with"
430 << std::endl <<
"local indexing.");
441 L_block_->setAllToScalar (STM::zero ());
442 U_block_->setAllToScalar (STM::zero ());
443 D_block_->setAllToScalar (STM::zero ());
460 RCP<const map_type> rowMap = L_block_->getRowMap ();
472 using LocalRowHandler_t = LocalRowHandler<MatrixType>;
473 LocalRowHandler_t localRowHandler(this->A_);
474 typename LocalRowHandler_t::inds_type InI;
475 typename LocalRowHandler_t::vals_type InV;
476 for (
size_t myRow=0; myRow<this->A_->getLocalNumRows(); ++myRow) {
477 LO local_row = myRow;
479 localRowHandler.getLocalRow(local_row, InI, InV, NumIn);
486 for (LO j = 0; j < NumIn; ++j) {
488 const LO blockOffset = blockMatSize*j;
490 if (k == local_row) {
493 for (LO jj = 0; jj < blockMatSize; ++jj)
494 diagValues[jj] = this->Rthresh_ * InV[blockOffset+jj] + IFPACK2_SGN(InV[blockOffset+jj]) * this->Athresh_;
495 D_block_->replaceLocalValues(local_row, &InI[j], diagValues.getRawPtr(), 1);
499 true, std::runtime_error,
"Ifpack2::RILUK::initAllValues: current "
500 "GID k = " << k <<
" < 0. I'm not sure why this is an error; it is "
501 "probably an artifact of the undocumented assumptions of the "
502 "original implementation (likely copied and pasted from Ifpack). "
503 "Nevertheless, the code I found here insisted on this being an error "
504 "state, so I will throw an exception here.");
506 else if (k < local_row) {
508 const LO LBlockOffset = NumL*blockMatSize;
509 for (LO jj = 0; jj < blockMatSize; ++jj)
510 LV[LBlockOffset+jj] = InV[blockOffset+jj];
513 else if (Teuchos::as<size_t>(k) <= rowMap->getLocalNumElements()) {
515 const LO UBlockOffset = NumU*blockMatSize;
516 for (LO jj = 0; jj < blockMatSize; ++jj)
517 UV[UBlockOffset+jj] = InV[blockOffset+jj];
528 for (LO jj = 0; jj < blockSize_; ++jj)
529 diagValues[jj*(blockSize_+1)] = this->Athresh_;
530 D_block_->replaceLocalValues(local_row, &local_row, diagValues.getRawPtr(), 1);
534 L_block_->replaceLocalValues(local_row, &LI[0], &LV[0], NumL);
538 U_block_->replaceLocalValues(local_row, &UI[0], &UV[0], NumU);
553 this->isInitialized_ =
true;
562 template<
class LittleBlockType>
563 struct GetManagedView {
564 static_assert (Kokkos::is_view<LittleBlockType>::value,
565 "LittleBlockType must be a Kokkos::View.");
566 typedef Kokkos::View<
typename LittleBlockType::non_const_data_type,
567 typename LittleBlockType::array_layout,
568 typename LittleBlockType::device_type> managed_non_const_type;
569 static_assert (static_cast<int> (managed_non_const_type::rank) ==
570 static_cast<int> (LittleBlockType::rank),
571 "managed_non_const_type::rank != LittleBlock::rank. "
572 "Please report this bug to the Ifpack2 developers.");
577 template<
class MatrixType>
580 typedef impl_scalar_type IST;
581 const char prefix[] =
"Ifpack2::Experimental::RBILUK::compute: ";
587 (this->A_.
is_null (), std::runtime_error, prefix <<
"The matrix (A_, "
588 "the BlockCrsMatrix) is null. Please call setMatrix() with a nonnull "
589 "input before calling this method.");
591 (! this->A_->isFillComplete (), std::runtime_error, prefix <<
"The matrix "
592 "(A_, the BlockCrsMatrix) is not fill complete. You may not invoke "
593 "initialize() or compute() with this matrix until the matrix is fill "
594 "complete. Note: BlockCrsMatrix is fill complete if and only if its "
595 "underlying graph is fill complete.");
597 if (! this->isInitialized ()) {
620 double startTime = timer.
wallTime();
623 this->isComputed_ =
false;
633 LO NumL, NumU, NumURead;
636 const size_t MaxNumEntries =
637 L_block_->getLocalMaxNumRowEntries () + U_block_->getLocalMaxNumRowEntries () + 1;
639 const LO blockMatSize = blockSize_*blockSize_;
644 const LO rowStride = blockSize_;
647 Kokkos::View<
int*, Kokkos::HostSpace,
648 Kokkos::MemoryUnmanaged> ipiv (ipiv_teuchos.
getRawPtr (), blockSize_);
650 Kokkos::View<IST*, Kokkos::HostSpace,
651 Kokkos::MemoryUnmanaged> work (work_teuchos.getRawPtr (), blockSize_);
653 size_t num_cols = U_block_->getColMap()->getLocalNumElements();
656 typename GetManagedView<little_block_host_type>::managed_non_const_type diagModBlock (
"diagModBlock", blockSize_, blockSize_);
657 typename GetManagedView<little_block_host_type>::managed_non_const_type matTmp (
"matTmp", blockSize_, blockSize_);
658 typename GetManagedView<little_block_host_type>::managed_non_const_type multiplier (
"multiplier", blockSize_, blockSize_);
666 for (
size_t j = 0; j < num_cols; ++j) {
672 const LO numLocalRows = L_block_->getLocalNumRows ();
673 for (LO local_row = 0; local_row < numLocalRows; ++local_row) {
677 NumIn = MaxNumEntries;
678 local_inds_host_view_type colValsL;
679 values_host_view_type valsL;
681 L_block_->getLocalRowView(local_row, colValsL, valsL);
682 NumL = (LO) colValsL.size();
683 for (LO j = 0; j < NumL; ++j)
685 const LO matOffset = blockMatSize*j;
686 little_block_host_type lmat((
typename little_block_host_type::value_type*) &valsL[matOffset],blockSize_,rowStride);
687 little_block_host_type lmatV((
typename little_block_host_type::value_type*) &InV[matOffset],blockSize_,rowStride);
689 Tpetra::COPY (lmat, lmatV);
690 InI[j] = colValsL[j];
693 little_block_host_type dmat = D_block_->getLocalBlockHostNonConst(local_row, local_row);
694 little_block_host_type dmatV((
typename little_block_host_type::value_type*) &InV[NumL*blockMatSize], blockSize_, rowStride);
696 Tpetra::COPY (dmat, dmatV);
697 InI[NumL] = local_row;
699 local_inds_host_view_type colValsU;
700 values_host_view_type valsU;
701 U_block_->getLocalRowView(local_row, colValsU, valsU);
702 NumURead = (LO) colValsU.
size();
704 for (LO j = 0; j < NumURead; ++j)
706 if (!(colValsU[j] < numLocalRows))
continue;
707 InI[NumL+1+j] = colValsU[j];
708 const LO matOffset = blockMatSize*(NumL+1+j);
709 little_block_host_type umat((
typename little_block_host_type::value_type*) &valsU[blockMatSize*j], blockSize_, rowStride);
710 little_block_host_type umatV((
typename little_block_host_type::value_type*) &InV[matOffset], blockSize_, rowStride);
712 Tpetra::COPY (umat, umatV);
718 for (
size_t j = 0; j < NumIn; ++j) {
722 #ifndef IFPACK2_RBILUK_INITIAL
723 for (LO i = 0; i < blockSize_; ++i)
724 for (LO j = 0; j < blockSize_; ++j){
726 diagModBlock(i,j) = 0;
731 Kokkos::deep_copy (diagModBlock, diagmod);
734 for (LO jj = 0; jj < NumL; ++jj) {
736 little_block_host_type currentVal((
typename little_block_host_type::value_type*) &InV[jj*blockMatSize], blockSize_, rowStride);
738 Tpetra::COPY (currentVal, multiplier);
740 const little_block_host_type dmatInverse = D_block_->getLocalBlockHostNonConst(j,j);
742 #ifndef IFPACK2_RBILUK_INITIAL_NOKK
743 KokkosBatched::Experimental::SerialGemm
744 <KokkosBatched::Experimental::Trans::NoTranspose,
745 KokkosBatched::Experimental::Trans::NoTranspose,
746 KokkosBatched::Experimental::Algo::Gemm::Blocked>::invoke
747 (STS::one (), currentVal, dmatInverse, STS::zero (), matTmp);
749 Tpetra::GEMM (
"N",
"N", STS::one (), currentVal, dmatInverse,
750 STS::zero (), matTmp);
754 Tpetra::COPY (matTmp, currentVal);
755 local_inds_host_view_type UUI;
756 values_host_view_type UUV;
758 U_block_->getLocalRowView(j, UUI, UUV);
759 NumUU = (LO) UUI.size();
761 if (this->RelaxValue_ == STM::zero ()) {
762 for (LO k = 0; k < NumUU; ++k) {
763 if (!(UUI[k] < numLocalRows))
continue;
764 const int kk = colflag[UUI[k]];
766 little_block_host_type kkval((
typename little_block_host_type::value_type*) &InV[kk*blockMatSize], blockSize_, rowStride);
767 little_block_host_type uumat((
typename little_block_host_type::value_type*) &UUV[k*blockMatSize], blockSize_, rowStride);
768 #ifndef IFPACK2_RBILUK_INITIAL_NOKK
769 KokkosBatched::Experimental::SerialGemm
770 <KokkosBatched::Experimental::Trans::NoTranspose,
771 KokkosBatched::Experimental::Trans::NoTranspose,
772 KokkosBatched::Experimental::Algo::Gemm::Blocked>::invoke
773 (
magnitude_type(-STM::one ()), multiplier, uumat, STM::one (), kkval);
775 Tpetra::GEMM (
"N",
"N",
magnitude_type(-STM::one ()), multiplier, uumat,
783 for (LO k = 0; k < NumUU; ++k) {
784 if (!(UUI[k] < numLocalRows))
continue;
785 const int kk = colflag[UUI[k]];
786 little_block_host_type uumat((
typename little_block_host_type::value_type*) &UUV[k*blockMatSize], blockSize_, rowStride);
788 little_block_host_type kkval((
typename little_block_host_type::value_type*) &InV[kk*blockMatSize], blockSize_, rowStride);
789 #ifndef IFPACK2_RBILUK_INITIAL_NOKK
790 KokkosBatched::Experimental::SerialGemm
791 <KokkosBatched::Experimental::Trans::NoTranspose,
792 KokkosBatched::Experimental::Trans::NoTranspose,
793 KokkosBatched::Experimental::Algo::Gemm::Blocked>::invoke
794 (
magnitude_type(-STM::one ()), multiplier, uumat, STM::one (), kkval);
796 Tpetra::GEMM (
"N",
"N",
magnitude_type(-STM::one ()), multiplier, uumat,
802 #ifndef IFPACK2_RBILUK_INITIAL_NOKK
803 KokkosBatched::Experimental::SerialGemm
804 <KokkosBatched::Experimental::Trans::NoTranspose,
805 KokkosBatched::Experimental::Trans::NoTranspose,
806 KokkosBatched::Experimental::Algo::Gemm::Blocked>::invoke
807 (
magnitude_type(-STM::one ()), multiplier, uumat, STM::one (), diagModBlock);
809 Tpetra::GEMM (
"N",
"N",
magnitude_type(-STM::one ()), multiplier, uumat,
810 STM::one (), diagModBlock);
823 Tpetra::COPY (dmatV, dmat);
825 if (this->RelaxValue_ != STM::zero ()) {
827 Tpetra::AXPY (this->RelaxValue_, diagModBlock, dmat);
841 for (
int k = 0; k < blockSize_; ++k) {
845 Tpetra::GETF2 (dmat, ipiv, lapackInfo);
848 lapackInfo != 0, std::runtime_error,
"Ifpack2::Experimental::RBILUK::compute: "
849 "lapackInfo = " << lapackInfo <<
" which indicates an error in the factorization GETRF.");
851 Tpetra::GETRI (dmat, ipiv, work, lapackInfo);
854 lapackInfo != 0, std::runtime_error,
"Ifpack2::Experimental::RBILUK::compute: "
855 "lapackInfo = " << lapackInfo <<
" which indicates an error in the matrix inverse GETRI.");
858 for (LO j = 0; j < NumU; ++j) {
859 little_block_host_type currentVal((
typename little_block_host_type::value_type*) &InV[(NumL+1+j)*blockMatSize], blockSize_, rowStride);
861 #ifndef IFPACK2_RBILUK_INITIAL_NOKK
862 KokkosBatched::Experimental::SerialGemm
863 <KokkosBatched::Experimental::Trans::NoTranspose,
864 KokkosBatched::Experimental::Trans::NoTranspose,
865 KokkosBatched::Experimental::Algo::Gemm::Blocked>::invoke
866 (STS::one (), dmat, currentVal, STS::zero (), matTmp);
868 Tpetra::GEMM (
"N",
"N", STS::one (), dmat, currentVal,
869 STS::zero (), matTmp);
873 Tpetra::COPY (matTmp, currentVal);
878 U_block_->replaceLocalValues (local_row, &InI[NumL+1], &InV[blockMatSize*(NumL+1)], NumU);
881 #ifndef IFPACK2_RBILUK_INITIAL
883 for (
size_t j = 0; j < NumIn; ++j) {
884 colflag[InI[j]] = -1;
888 for (
size_t j = 0; j < num_cols; ++j) {
911 this->isComputed_ =
true;
912 this->numCompute_ += 1;
913 this->computeTime_ += (timer.
wallTime() - startTime);
917 template<
class MatrixType>
920 apply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
921 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
931 this->A_.
is_null (), std::runtime_error,
"Ifpack2::Experimental::RBILUK::apply: The matrix is "
932 "null. Please call setMatrix() with a nonnull input, then initialize() "
933 "and compute(), before calling this method.");
935 ! this->isComputed (), std::runtime_error,
936 "Ifpack2::Experimental::RBILUK::apply: If you have not yet called compute(), "
937 "you must call compute() before calling this method.");
938 TEUCHOS_TEST_FOR_EXCEPTION(
939 X.getNumVectors () != Y.getNumVectors (), std::invalid_argument,
940 "Ifpack2::Experimental::RBILUK::apply: X and Y do not have the same number of columns. "
941 "X.getNumVectors() = " << X.getNumVectors ()
942 <<
" != Y.getNumVectors() = " << Y.getNumVectors () <<
".");
943 TEUCHOS_TEST_FOR_EXCEPTION(
945 "Ifpack2::Experimental::RBILUK::apply: mode = Teuchos::CONJ_TRANS is not implemented for "
946 "complex Scalar type. Please talk to the Ifpack2 developers to get this "
947 "fixed. There is a FIXME in this file about this very issue.");
949 const LO blockMatSize = blockSize_*blockSize_;
951 const LO rowStride = blockSize_;
953 BMV yBlock (Y, * (this->Graph_->getA_Graph()->getDomainMap ()), blockSize_);
954 const BMV xBlock (X, * (this->A_->getColMap ()), blockSize_);
957 little_host_vec_type lclvec((
typename little_host_vec_type::value_type*)&lclarray[0], blockSize_);
958 const scalar_type one = STM::one ();
959 const scalar_type zero = STM::zero ();
962 double startTime = timer.
wallTime();
965 if (alpha == one && beta == zero) {
973 const LO numVectors = xBlock.getNumVectors();
974 BMV cBlock (* (this->Graph_->getA_Graph()->getDomainMap ()), blockSize_, numVectors);
975 BMV rBlock (* (this->Graph_->getA_Graph()->getDomainMap ()), blockSize_, numVectors);
976 for (LO imv = 0; imv < numVectors; ++imv)
978 for (
size_t i = 0; i < D_block_->getLocalNumRows(); ++i)
981 const_host_little_vec_type xval =
982 xBlock.getLocalBlockHost(local_row, imv, Tpetra::Access::ReadOnly);
983 little_host_vec_type cval =
984 cBlock.getLocalBlockHost(local_row, imv, Tpetra::Access::OverwriteAll);
986 Tpetra::COPY (xval, cval);
988 local_inds_host_view_type colValsL;
989 values_host_view_type valsL;
990 L_block_->getLocalRowView(local_row, colValsL, valsL);
991 LO NumL = (LO) colValsL.size();
993 for (LO j = 0; j < NumL; ++j)
995 LO col = colValsL[j];
996 const_host_little_vec_type prevVal =
997 cBlock.getLocalBlockHost(col, imv, Tpetra::Access::ReadOnly);
999 const LO matOffset = blockMatSize*j;
1000 little_block_host_type lij((
typename little_block_host_type::value_type*) &valsL[matOffset],blockSize_,rowStride);
1003 Tpetra::GEMV (-one, lij, prevVal, cval);
1009 D_block_->applyBlock(cBlock, rBlock);
1012 for (LO imv = 0; imv < numVectors; ++imv)
1014 const LO numRows = D_block_->getLocalNumRows();
1015 for (LO i = 0; i < numRows; ++i)
1017 LO local_row = (numRows-1)-i;
1018 const_host_little_vec_type rval =
1019 rBlock.getLocalBlockHost(local_row, imv, Tpetra::Access::ReadOnly);
1020 little_host_vec_type yval =
1021 yBlock.getLocalBlockHost(local_row, imv, Tpetra::Access::OverwriteAll);
1023 Tpetra::COPY (rval, yval);
1025 local_inds_host_view_type colValsU;
1026 values_host_view_type valsU;
1027 U_block_->getLocalRowView(local_row, colValsU, valsU);
1028 LO NumU = (LO) colValsU.size();
1030 for (LO j = 0; j < NumU; ++j)
1032 LO col = colValsU[NumU-1-j];
1033 const_host_little_vec_type prevVal =
1034 yBlock.getLocalBlockHost(col, imv, Tpetra::Access::ReadOnly);
1036 const LO matOffset = blockMatSize*(NumU-1-j);
1037 little_block_host_type uij((
typename little_block_host_type::value_type*) &valsU[matOffset], blockSize_, rowStride);
1040 Tpetra::GEMV (-one, uij, prevVal, yval);
1046 TEUCHOS_TEST_FOR_EXCEPTION(
1047 true, std::runtime_error,
1048 "Ifpack2::Experimental::RBILUK::apply: transpose apply is not implemented for the block algorithm. ");
1052 if (alpha == zero) {
1059 MV Y_tmp (Y.getMap (), Y.getNumVectors ());
1060 apply (X, Y_tmp, mode);
1061 Y.update (alpha, Y_tmp, beta);
1066 this->numApply_ += 1;
1067 this->applyTime_ += (timer.
wallTime() - startTime);
1071 template<
class MatrixType>
1074 std::ostringstream os;
1079 os <<
"\"Ifpack2::Experimental::RBILUK\": {";
1080 os <<
"Initialized: " << (this->isInitialized () ?
"true" :
"false") <<
", "
1081 <<
"Computed: " << (this->isComputed () ?
"true" :
"false") <<
", ";
1083 os <<
"Level-of-fill: " << this->getLevelOfFill() <<
", ";
1086 os <<
"Matrix: null";
1089 os <<
"Global matrix dimensions: ["
1090 << this->A_->getGlobalNumRows () <<
", " << this->A_->getGlobalNumCols () <<
"]"
1091 <<
", Global nnz: " << this->A_->getGlobalNumEntries();
1106 #define IFPACK2_EXPERIMENTAL_RBILUK_INSTANT(S,LO,GO,N) \
1107 template class Ifpack2::Experimental::RBILUK< Tpetra::BlockCrsMatrix<S, LO, GO, N> >; \
1108 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:344
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition: Ifpack2_Experimental_RBILUK_decl.hpp:146
virtual ~RBILUK()
Destructor (declared virtual for memory safety).
Definition: Ifpack2_Experimental_RBILUK_def.hpp:133
const block_crs_matrix_type & getUBlock() const
Return the U factor of the ILU factorization.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:190
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:920
#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:153
ILU(k) factorization of a given Tpetra::RowMatrix.
Definition: Ifpack2_RILUK_decl.hpp:245
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition: Ifpack2_Experimental_RBILUK_decl.hpp:150
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:176
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:578
File for utility functions.
Construct a level filled graph for use in computing an ILU(k) incomplete factorization.
Definition: Ifpack2_IlukGraph.hpp:100
void setMatrix(const Teuchos::RCP< const block_crs_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:138
const block_crs_matrix_type & getLBlock() const
Return the L factor of the ILU factorization.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:162
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:159
std::string description() const
A one-line description of this object.
Definition: Ifpack2_Experimental_RBILUK_def.hpp:1072
ILU(k) factorization of a given Tpetra::BlockCrsMatrix.
Definition: Ifpack2_Experimental_RBILUK_decl.hpp:128