10#ifndef IFPACK2_DETAILS_TRIDISOLVER_DEF_HPP
11#define IFPACK2_DETAILS_TRIDISOLVER_DEF_HPP
13#include "Ifpack2_LocalFilter.hpp"
14#include "Teuchos_LAPACK.hpp"
15#include "Tpetra_MultiVector.hpp"
16#include "Tpetra_Map.hpp"
17#include "Tpetra_Import.hpp"
18#include "Tpetra_Export.hpp"
22# include "Teuchos_DefaultMpiComm.hpp"
24# include "Teuchos_DefaultSerialComm.hpp"
35template<
class MatrixType>
37TriDiSolver (
const Teuchos::RCP<const row_matrix_type>& A) :
39 initializeTime_ (0.0),
45 isInitialized_ (false),
50template<
class MatrixType>
51Teuchos::RCP<const typename TriDiSolver<MatrixType, false>::map_type>
53 TEUCHOS_TEST_FOR_EXCEPTION(
54 A_.is_null (), std::runtime_error,
"Ifpack2::Details::TriDiSolver::"
55 "getDomainMap: The input matrix A is null. Please call setMatrix() with a "
56 "nonnull input matrix before calling this method.");
59 return A_->getRangeMap ();
63template<
class MatrixType>
64Teuchos::RCP<const typename TriDiSolver<MatrixType, false>::map_type>
66 TEUCHOS_TEST_FOR_EXCEPTION(
67 A_.is_null (), std::runtime_error,
"Ifpack2::Details::TriDiSolver::"
68 "getRangeMap: The input matrix A is null. Please call setMatrix() with a "
69 "nonnull input matrix before calling this method.");
72 return A_->getDomainMap ();
76template<
class MatrixType>
84template<
class MatrixType>
87 return isInitialized_;
91template<
class MatrixType>
98template<
class MatrixType>
101 return numInitialize_;
105template<
class MatrixType>
112template<
class MatrixType>
119template<
class MatrixType>
122 return initializeTime_;
126template<
class MatrixType>
133template<
class MatrixType>
140template<
class MatrixType>
141Teuchos::RCP<const typename TriDiSolver<MatrixType, false>::row_matrix_type>
147template<
class MatrixType>
151 isInitialized_ =
false;
153 A_local_ = Teuchos::null;
154 A_local_tridi_.reshape (0);
159template<
class MatrixType>
161setMatrix (
const Teuchos::RCP<const row_matrix_type>& A)
165 if (! A_.is_null ()) {
166 const global_size_t numRows = A->getRangeMap ()->getGlobalNumElements ();
167 const global_size_t numCols = A->getDomainMap ()->getGlobalNumElements ();
168 TEUCHOS_TEST_FOR_EXCEPTION(
169 numRows != numCols, std::invalid_argument,
"Ifpack2::Details::TriDiSolver::"
170 "setMatrix: Input matrix must be (globally) square. "
171 "The matrix you provided is " << numRows <<
" by " << numCols <<
".");
181template<
class MatrixType>
189 using Teuchos::TimeMonitor;
190 const std::string timerName (
"Ifpack2::Details::TriDiSolver::initialize");
192 RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
193 if (timer.is_null ()) {
194 timer = TimeMonitor::getNewCounter (timerName);
197 double startTime = timer->wallTime();
200 Teuchos::TimeMonitor timeMon (*timer);
202 TEUCHOS_TEST_FOR_EXCEPTION(
203 A_.is_null (), std::runtime_error,
"Ifpack2::Details::TriDiSolver::"
204 "initialize: The input matrix A is null. Please call setMatrix() "
205 "with a nonnull input before calling this method.");
207 TEUCHOS_TEST_FOR_EXCEPTION(
208 ! A_->hasColMap (), std::invalid_argument,
"Ifpack2::Details::TriDiSolver: "
209 "The constructor's input matrix must have a column Map, "
210 "so that it has local indices.");
216 if (A_->getComm ()->getSize () > 1) {
222 TEUCHOS_TEST_FOR_EXCEPTION(
223 A_local_.is_null (), std::logic_error,
"Ifpack2::Details::TriDiSolver::"
224 "initialize: A_local_ is null after it was supposed to have been "
225 "initialized. Please report this bug to the Ifpack2 developers.");
228 const size_t numRows = A_local_->getLocalNumRows ();
229 const size_t numCols = A_local_->getLocalNumCols ();
230 TEUCHOS_TEST_FOR_EXCEPTION(
231 numRows != numCols, std::logic_error,
"Ifpack2::Details::TriDiSolver::"
232 "initialize: Local filter matrix is not square. This should never happen. "
233 "Please report this bug to the Ifpack2 developers.");
234 A_local_tridi_.reshape (numRows);
235 ipiv_.resize (numRows);
236 std::fill (ipiv_.begin (), ipiv_.end (), 0);
238 isInitialized_ =
true;
242 initializeTime_ += (timer->wallTime() - startTime);
246template<
class MatrixType>
251template<
class MatrixType>
255 const std::string timerName (
"Ifpack2::Details::TriDiSolver::compute");
257 RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName);
258 if (timer.is_null ()) {
259 timer = Teuchos::TimeMonitor::getNewCounter (timerName);
262 double startTime = timer->wallTime();
266 Teuchos::TimeMonitor timeMon (*timer);
267 TEUCHOS_TEST_FOR_EXCEPTION(
268 A_.is_null (), std::runtime_error,
"Ifpack2::Details::TriDiSolver::"
269 "compute: The input matrix A is null. Please call setMatrix() with a "
270 "nonnull input, then call initialize(), before calling this method.");
272 TEUCHOS_TEST_FOR_EXCEPTION(
273 A_local_.is_null (), std::logic_error,
"Ifpack2::Details::TriDiSolver::"
274 "compute: A_local_ is null. Please report this bug to the Ifpack2 "
281 extract (A_local_tridi_, *A_local_);
283 factor (A_local_tridi_, ipiv_ ());
288 computeTime_ += (timer->wallTime() - startTime);
291template<
class MatrixType>
293 const Teuchos::ArrayView<int>& ipiv)
296 std::fill (ipiv.begin (), ipiv.end (), 0);
298 Teuchos::LAPACK<int, scalar_type> lapack;
300 lapack.GTTRF (A.numRowsCols (),
305 ipiv.getRawPtr (), &INFO);
307 TEUCHOS_TEST_FOR_EXCEPTION(
308 INFO < 0, std::logic_error,
"Ifpack2::Details::TriDiSolver::factor: "
309 "LAPACK's _GTTRF (tridiagonal LU factorization with partial pivoting) "
310 "was called incorrectly. INFO = " << INFO <<
" < 0. "
311 "Please report this bug to the Ifpack2 developers.");
315 TEUCHOS_TEST_FOR_EXCEPTION(
316 INFO > 0, std::runtime_error,
"Ifpack2::Details::TriDiSolver::factor: "
317 "LAPACK's _GTTRF (tridiagonal LU factorization with partial pivoting) "
318 "reports that the computed U factor is exactly singular. U(" << INFO <<
319 "," << INFO <<
") (one-based index i) is exactly zero. This probably "
320 "means that the input matrix has a singular diagonal block.");
324template<
class MatrixType>
325void TriDiSolver<MatrixType, false>::
326applyImpl (
const MV& X,
328 const Teuchos::ETransp mode,
329 const scalar_type alpha,
330 const scalar_type beta)
const
332 using Teuchos::ArrayRCP;
335 using Teuchos::rcpFromRef;
336 using Teuchos::CONJ_TRANS;
337 using Teuchos::TRANS;
339 const int numVecs =
static_cast<int> (X.getNumVectors ());
340 if (alpha == STS::zero ()) {
341 if (beta == STS::zero ()) {
345 Y.putScalar (STS::zero ());
348 Y.scale (STS::zero ());
352 Teuchos::LAPACK<int, scalar_type> lapack;
358 if (beta == STS::zero () && Y.isConstantStride () && alpha == STS::one ()) {
360 Y_tmp = rcpFromRef (Y);
363 Y_tmp = rcp (
new MV (createCopy(X)));
364 if (alpha != STS::one ()) {
365 Y_tmp->scale (alpha);
368 const int Y_stride =
static_cast<int> (Y_tmp->getStride ());
369 ArrayRCP<scalar_type> Y_view = Y_tmp->get1dViewNonConst ();
370 scalar_type*
const Y_ptr = Y_view.getRawPtr ();
373 (mode == CONJ_TRANS ?
'C' : (mode ==
TRANS ?
'T' :
'N'));
374 lapack.GTTRS (trans, A_local_tridi_.numRowsCols(), numVecs,
378 A_local_tridi_.DU2(),
379 ipiv_.getRawPtr (), Y_ptr, Y_stride, &INFO);
380 TEUCHOS_TEST_FOR_EXCEPTION(
381 INFO != 0, std::runtime_error,
"Ifpack2::Details::TriDiSolver::"
382 "applyImpl: LAPACK's _GTTRS (tridiagonal solve using LU factorization "
383 "with partial pivoting) failed with INFO = " << INFO <<
" != 0.");
385 if (beta != STS::zero ()) {
386 Y.update (alpha, *Y_tmp, beta);
388 else if (! Y.isConstantStride ()) {
389 deep_copy(Y, *Y_tmp);
395template<
class MatrixType>
397apply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
398 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
399 Teuchos::ETransp mode,
403 using Teuchos::ArrayView;
407 using Teuchos::rcpFromRef;
409 const std::string timerName (
"Ifpack2::Details::TriDiSolver::apply");
410 RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName);
411 if (timer.is_null ()) {
412 timer = Teuchos::TimeMonitor::getNewCounter (timerName);
415 double startTime = timer->wallTime();
419 Teuchos::TimeMonitor timeMon (*timer);
421 TEUCHOS_TEST_FOR_EXCEPTION(
422 ! isComputed_, std::runtime_error,
"Ifpack2::Details::TriDiSolver::apply: "
423 "You must have called the compute() method before you may call apply(). "
424 "You may call the apply() method as many times as you want after calling "
425 "compute() once, but you must have called compute() at least once.");
427 const size_t numVecs = X.getNumVectors ();
429 TEUCHOS_TEST_FOR_EXCEPTION(
430 numVecs != Y.getNumVectors (), std::runtime_error,
431 "Ifpack2::Details::TriDiSolver::apply: X and Y have different numbers "
432 "of vectors. X has " << X.getNumVectors () <<
", but Y has "
433 << X.getNumVectors () <<
".");
440 RCP<const MV> X_local;
442 const bool multipleProcs = (A_->getRowMap ()->getComm ()->getSize () >= 1);
447 X_local = X.offsetView (A_local_->getDomainMap (), 0);
448 Y_local = Y.offsetViewNonConst (A_local_->getRangeMap (), 0);
452 X_local = rcpFromRef (X);
453 Y_local = rcpFromRef (Y);
458 this->applyImpl (*X_local, *Y_local, mode, alpha, beta);
463 applyTime_ += (timer->wallTime() - startTime);
467template<
class MatrixType>
470 std::ostringstream out;
475 out <<
"\"Ifpack2::Details::TriDiSolver\": ";
477 if (this->getObjectLabel () !=
"") {
478 out <<
"Label: \"" << this->getObjectLabel () <<
"\", ";
480 out <<
"Initialized: " << (
isInitialized () ?
"true" :
"false") <<
", "
481 <<
"Computed: " << (
isComputed () ?
"true" :
"false") <<
", ";
484 out <<
"Matrix: null";
487 out <<
"Matrix: not null"
488 <<
", Global matrix dimensions: ["
489 << A_->getGlobalNumRows () <<
", " << A_->getGlobalNumCols () <<
"]";
497template<
class MatrixType>
499 const Teuchos::EVerbosityLevel verbLevel)
const {
500 using Teuchos::FancyOStream;
501 using Teuchos::OSTab;
503 using Teuchos::rcpFromRef;
506 if (verbLevel == Teuchos::VERB_NONE) {
510 RCP<FancyOStream> ptrOut = rcpFromRef (out);
512 if (this->getObjectLabel () !=
"") {
513 out <<
"label: " << this->getObjectLabel () << endl;
515 out <<
"initialized: " << (isInitialized_ ?
"true" :
"false") << endl
516 <<
"computed: " << (isComputed_ ?
"true" :
"false") << endl
517 <<
"number of initialize calls: " << numInitialize_ << endl
518 <<
"number of compute calls: " << numCompute_ << endl
519 <<
"number of apply calls: " << numApply_ << endl
520 <<
"total time in seconds in initialize: " << initializeTime_ << endl
521 <<
"total time in seconds in compute: " << computeTime_ << endl
522 <<
"total time in seconds in apply: " << applyTime_ << endl;
523 if (verbLevel >= Teuchos::VERB_EXTREME) {
524 out <<
"A_local_tridi_:" << endl;
525 A_local_tridi_.print(out);
527 out <<
"ipiv_: " << Teuchos::toString (ipiv_) << endl;
531template<
class MatrixType>
533 const Teuchos::EVerbosityLevel verbLevel)
const
535 using Teuchos::FancyOStream;
536 using Teuchos::OSTab;
538 using Teuchos::rcpFromRef;
541 RCP<FancyOStream> ptrOut = rcpFromRef (out);
548 if (verbLevel > Teuchos::VERB_NONE) {
549 out <<
"Ifpack2::Details::TriDiSolver:" << endl;
551 describeLocal (out, verbLevel);
556 const Teuchos::Comm<int>& comm = * (A_->getRowMap ()->getComm ());
557 const int myRank = comm.getRank ();
558 const int numProcs = comm.getSize ();
559 if (verbLevel > Teuchos::VERB_NONE && myRank == 0) {
560 out <<
"Ifpack2::Details::TriDiSolver:" << endl;
563 for (
int p = 0; p < numProcs; ++p) {
565 out <<
"Process " << myRank <<
":" << endl;
566 describeLocal (out, verbLevel);
575template<
class MatrixType>
579 using Teuchos::Array;
580 using Teuchos::ArrayView;
582 typedef typename Teuchos::ArrayView<LO>::size_type size_type;
585 A_local_tridi.putScalar (STS::zero ());
593 const map_type& rowMap = * (A_local.getRowMap ());
597 const size_type maxNumRowEntries =
598 static_cast<size_type
> (A_local.getLocalMaxNumRowEntries ());
599 nonconst_local_inds_host_view_type localIndices(
"localIndices",maxNumRowEntries);
600 nonconst_values_host_view_type values (
"values",maxNumRowEntries);
602 const LO numLocalRows =
static_cast<LO
> (rowMap.getLocalNumElements ());
603 const LO minLocalRow = rowMap.getMinLocalIndex ();
606 const LO maxLocalRow = minLocalRow + numLocalRows;
607 for (LO localRow = minLocalRow; localRow < maxLocalRow; ++localRow) {
614 const size_type numEntriesInRow =
615 static_cast<size_type
> (A_local.getNumEntriesInLocalRow (localRow));
616 size_t numEntriesOut = 0;
617 A_local.getLocalRowCopy (localRow,
621 for (LO k = 0; k < numEntriesInRow; ++k) {
622 const LO localCol = localIndices[k];
623 const scalar_type val = values[k];
627 if( localCol >= localRow-1 && localCol <= localRow+1 )
628 A_local_tridi(localRow, localCol) += val;
637template<
class MatrixType>
639 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
643template<
class MatrixType>
644Teuchos::RCP<const typename TriDiSolver<MatrixType, true>::map_type>
646 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
650template<
class MatrixType>
651Teuchos::RCP<const typename TriDiSolver<MatrixType, true>::map_type>
653 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
657template<
class MatrixType>
660 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
664template<
class MatrixType>
667 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
671template<
class MatrixType>
674 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
678template<
class MatrixType>
681 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
685template<
class MatrixType>
688 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
692template<
class MatrixType>
695 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
699template<
class MatrixType>
702 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
706template<
class MatrixType>
709 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
713template<
class MatrixType>
716 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
720template<
class MatrixType>
721Teuchos::RCP<const typename TriDiSolver<MatrixType, true>::row_matrix_type>
723 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
727template<
class MatrixType>
730 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
734template<
class MatrixType>
737 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
741template<
class MatrixType>
748template<
class MatrixType>
751 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
755template<
class MatrixType>
757 const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
758 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
759 Teuchos::ETransp mode,
763 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
767template<
class MatrixType>
771 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
775template<
class MatrixType>
777 const Teuchos::EVerbosityLevel verbLevel)
const
779 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Not implemented");
785#define IFPACK2_DETAILS_TRIDISOLVER_INSTANT(S,LO,GO,N) \
786 template class Ifpack2::Details::TriDiSolver< Tpetra::RowMatrix<S, LO, GO, N> >;
virtual void setMatrix(const Teuchos::RCP< const Tpetra::RowMatrix< MatrixType::scalar_type, MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > > &A)=0
bool isInitialized() const
True if the preconditioner has been successfully initialized, else false.
Definition Ifpack2_Details_TriDiSolver_def.hpp:86
TriDiSolver(const Teuchos::RCP< const row_matrix_type > &matrix)
Constructor.
Definition Ifpack2_Details_TriDiSolver_def.hpp:37
void initialize()
Set up the graph structure of this preconditioner.
Definition Ifpack2_Details_TriDiSolver_def.hpp:182
bool isComputed() const
True if the preconditioner has been successfully computed, else false.
Definition Ifpack2_Details_TriDiSolver_def.hpp:93
MatrixType::scalar_type scalar_type
The type of entries in the input (global) matrix.
Definition Ifpack2_Details_TriDiSolver_decl.hpp:76
TriDiSolver(const Teuchos::RCP< const row_matrix_type > &matrix)
Constructor.
Definition Ifpack2_Details_TriDiSolver_def.hpp:638
MatrixType::scalar_type scalar_type
The type of entries in the input (global) matrix.
Definition Ifpack2_Details_TriDiSolver_decl.hpp:337
"Preconditioner" that uses LAPACK's tridi LU.
Definition Ifpack2_Details_TriDiSolver_decl.hpp:52
Access only local rows and columns of a sparse matrix.
Definition Ifpack2_LocalFilter_decl.hpp:131
virtual double getComputeTime() const=0
virtual bool isInitialized() const=0
virtual int getNumCompute() const=0
virtual Teuchos::RCP< const Tpetra::RowMatrix< MatrixType::scalar_type, MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > > getMatrix() const=0
virtual int getNumApply() const=0
virtual double getApplyTime() const=0
virtual void setParameters(const Teuchos::ParameterList &List)=0
virtual void apply(const Tpetra::MultiVector< MatrixType::scalar_type, MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > &X, Tpetra::MultiVector< MatrixType::scalar_type, MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, MatrixType::scalar_type alpha=Teuchos::ScalarTraits< MatrixType::scalar_type >::one(), MatrixType::scalar_type beta=Teuchos::ScalarTraits< MatrixType::scalar_type >::zero()) const=0
virtual Teuchos::RCP< const Tpetra::Map< MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > > getRangeMap() const=0
virtual Teuchos::RCP< const Tpetra::Map< MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > > getDomainMap() const=0
virtual bool isComputed() const=0
virtual void initialize()=0
virtual double getInitializeTime() const=0
virtual int getNumInitialize() const=0
Preconditioners and smoothers for Tpetra sparse matrices.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:41