43 #ifndef IFPACK2_DETAILS_DENSESOLVER_DEF_HPP 
   44 #define IFPACK2_DETAILS_DENSESOLVER_DEF_HPP 
   46 #include "Ifpack2_LocalFilter.hpp" 
   48 #include "Ifpack2_Details_DenseSolver.hpp" 
   54 #  include "Teuchos_DefaultSerialComm.hpp" 
   65 template<
class MatrixType>
 
   69   initializeTime_ (0.0),
 
   75   isInitialized_ (false),
 
   80 template<
class MatrixType>
 
   84     A_.is_null (), std::runtime_error, 
"Ifpack2::Details::DenseSolver::" 
   85     "getDomainMap: The input matrix A is null.  Please call setMatrix() with a " 
   86     "nonnull input matrix before calling this method.");
 
   89   return A_->getRangeMap ();
 
   93 template<
class MatrixType>
 
   97     A_.is_null (), std::runtime_error, 
"Ifpack2::Details::DenseSolver::" 
   98     "getRangeMap: The input matrix A is null.  Please call setMatrix() with a " 
   99     "nonnull input matrix before calling this method.");
 
  102   return A_->getDomainMap ();
 
  106 template<
class MatrixType>
 
  114 template<
class MatrixType>
 
  117   return isInitialized_;
 
  121 template<
class MatrixType>
 
  128 template<
class MatrixType>
 
  131   return numInitialize_;
 
  135 template<
class MatrixType>
 
  142 template<
class MatrixType>
 
  149 template<
class MatrixType>
 
  152   return initializeTime_;
 
  156 template<
class MatrixType>
 
  163 template<
class MatrixType>
 
  170 template<
class MatrixType>
 
  177 template<
class MatrixType>
 
  181   isInitialized_ = 
false;
 
  183   A_local_ = Teuchos::null;
 
  184   A_local_dense_.reshape (0, 0);
 
  189 template<
class MatrixType>
 
  195   if (! A_.is_null ()) {
 
  196     const global_size_t numRows = A->getRangeMap ()->getGlobalNumElements ();
 
  197     const global_size_t numCols = A->getDomainMap ()->getGlobalNumElements ();
 
  199       numRows != numCols, std::invalid_argument, 
"Ifpack2::Details::DenseSolver::" 
  200       "setMatrix: Input matrix must be (globally) square.  " 
  201       "The matrix you provided is " << numRows << 
" by " << numCols << 
".");
 
  211 template<
class MatrixType>
 
  220   const std::string timerName (
"Ifpack2::Details::DenseSolver::initialize");
 
  222   RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
 
  223   if (timer.is_null ()) {
 
  224     timer = TimeMonitor::getNewCounter (timerName);
 
  231       A_.is_null (), std::runtime_error, 
"Ifpack2::Details::DenseSolver::" 
  232       "initialize: The input matrix A is null.  Please call setMatrix() " 
  233       "with a nonnull input before calling this method.");
 
  236       ! A_->hasColMap (), std::invalid_argument, 
"Ifpack2::Details::DenseSolver: " 
  237       "The constructor's input matrix must have a column Map, " 
  238       "so that it has local indices.");
 
  244     if (A_->getComm ()->getSize () > 1) {
 
  251       A_local_.is_null (), std::logic_error, 
"Ifpack2::Details::DenseSolver::" 
  252       "initialize: A_local_ is null after it was supposed to have been " 
  253       "initialized.  Please report this bug to the Ifpack2 developers.");
 
  256     const size_t numRows = A_local_->getNodeNumRows ();
 
  257     const size_t numCols = A_local_->getNodeNumCols ();
 
  259       numRows != numCols, std::logic_error, 
"Ifpack2::Details::DenseSolver::" 
  260       "initialize: Local filter matrix is not square.  This should never happen.  " 
  261       "Please report this bug to the Ifpack2 developers.");
 
  262     A_local_dense_.reshape (numRows, numCols);
 
  263     ipiv_.resize (std::min (numRows, numCols));
 
  264     std::fill (ipiv_.begin (), ipiv_.end (), 0);
 
  266     isInitialized_ = 
true;
 
  272   initializeTime_ = timer->totalElapsedTime ();
 
  276 template<
class MatrixType>
 
  281 template<
class MatrixType>
 
  285   const std::string timerName (
"Ifpack2::Details::DenseSolver::compute");
 
  288   if (timer.is_null ()) {
 
  296       A_.is_null (), std::runtime_error, 
"Ifpack2::Details::DenseSolver::" 
  297       "compute: The input matrix A is null.  Please call setMatrix() with a " 
  298       "nonnull input, then call initialize(), before calling this method.");
 
  301       A_local_.is_null (), std::logic_error, 
"Ifpack2::Details::DenseSolver::" 
  302       "compute: A_local_ is null.  Please report this bug to the Ifpack2 " 
  309     extract (A_local_dense_, *A_local_); 
 
  310     factor (A_local_dense_, ipiv_ ()); 
 
  317   computeTime_ = timer->totalElapsedTime ();
 
  320 template<
class MatrixType>
 
  326   std::fill (ipiv.
begin (), ipiv.
end (), 0);
 
  334     INFO < 0, std::logic_error, 
"Ifpack2::Details::DenseSolver::factor: " 
  335     "LAPACK's _GETRF (LU factorization with partial pivoting) was called " 
  336     "incorrectly.  INFO = " << INFO << 
" < 0.  " 
  337     "Please report this bug to the Ifpack2 developers.");
 
  342     INFO > 0, std::runtime_error, 
"Ifpack2::Details::DenseSolver::factor: " 
  343     "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the " 
  344     "computed U factor is exactly singular.  U(" << INFO << 
"," << INFO << 
") " 
  345     "(one-based index i) is exactly zero.  This probably means that the input " 
  346     "matrix has a singular diagonal block.");
 
  350 template<
class MatrixType>
 
  351 void DenseSolver<MatrixType, false>::
 
  352 applyImpl (
const MV& X,
 
  355            const scalar_type alpha,
 
  356            const scalar_type beta)
 const 
  361   using Teuchos::rcpFromRef;
 
  365   const int numVecs = 
static_cast<int> (X.getNumVectors ());
 
  366   if (alpha == STS::zero ()) { 
 
  367     if (beta == STS::zero ()) {
 
  371       Y.putScalar (STS::zero ());
 
  374       Y.scale (STS::zero ());
 
  384     if (beta == STS::zero () && Y.isConstantStride () && alpha == STS::one ()) {
 
  386       Y_tmp = rcpFromRef (Y);
 
  390       if (alpha != STS::one ()) {
 
  391         Y_tmp->scale (alpha);
 
  394     const int Y_stride = 
static_cast<int> (Y_tmp->getStride ());
 
  395     ArrayRCP<scalar_type> Y_view = Y_tmp->get1dViewNonConst ();
 
  396     scalar_type* 
const Y_ptr = Y_view.getRawPtr ();
 
  400     lapack.
GETRS (trans, A_local_dense_.numRows (), numVecs,
 
  401                   A_local_dense_.values (), A_local_dense_.stride (),
 
  402                   ipiv_.getRawPtr (), Y_ptr, Y_stride, &INFO);
 
  404       INFO != 0, std::runtime_error, 
"Ifpack2::Details::DenseSolver::" 
  405       "applyImpl: LAPACK's _GETRS (solve using LU factorization with " 
  406       "partial pivoting) failed with INFO = " << INFO << 
" != 0.");
 
  408     if (beta != STS::zero ()) {
 
  409       Y.update (alpha, *Y_tmp, beta);
 
  411     else if (! Y.isConstantStride ()) {
 
  412       deep_copy (Y, *Y_tmp);
 
  418 template<
class MatrixType>
 
  420 apply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
 
  421        Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
 
  430   using Teuchos::rcpFromRef;
 
  432   const std::string timerName (
"Ifpack2::Details::DenseSolver::apply");
 
  434   if (timer.is_null ()) {
 
  443       ! isComputed_, std::runtime_error, 
"Ifpack2::Details::DenseSolver::apply: " 
  444       "You must have called the compute() method before you may call apply().  " 
  445       "You may call the apply() method as many times as you want after calling " 
  446       "compute() once, but you must have called compute() at least once.");
 
  448     const size_t numVecs = X.getNumVectors ();
 
  451       numVecs != Y.getNumVectors (), std::runtime_error,
 
  452       "Ifpack2::Details::DenseSolver::apply: X and Y have different numbers " 
  453       "of vectors.  X has " << X.getNumVectors () << 
", but Y has " 
  454       << X.getNumVectors () << 
".");
 
  461     RCP<const MV> X_local;
 
  463     const bool multipleProcs = (A_->getRowMap ()->getComm ()->getSize () >= 1);
 
  468       X_local = X.offsetView (A_local_->getDomainMap (), 0);
 
  469       Y_local = Y.offsetViewNonConst (A_local_->getRangeMap (), 0);
 
  473       X_local = rcpFromRef (X);
 
  474       Y_local = rcpFromRef (Y);
 
  479     this->applyImpl (*X_local, *Y_local, mode, alpha, beta);
 
  486   applyTime_ = timer->totalElapsedTime ();
 
  490 template<
class MatrixType>
 
  494   std::ostringstream out;
 
  499   out << 
"\"Ifpack2::Details::DenseSolver\": ";
 
  501   if (this->getObjectLabel () != 
"") {
 
  502     out << 
"Label: \"" << this->getObjectLabel () << 
"\", ";
 
  504   out << 
"Initialized: " << (
isInitialized () ? 
"true" : 
"false") << 
", " 
  505       << 
"Computed: " << (
isComputed () ? 
"true" : 
"false") << 
", ";
 
  508     out << 
"Matrix: null";
 
  511     out << 
"Matrix: not null" 
  512         << 
", Global matrix dimensions: [" 
  513         << A_->getGlobalNumRows () << 
", " << A_->getGlobalNumCols () << 
"]";
 
  521 template<
class MatrixType>
 
  529   using Teuchos::rcpFromRef;
 
  536     RCP<FancyOStream> ptrOut = rcpFromRef (out);
 
  538     if (this->getObjectLabel () != 
"") {
 
  539       out << 
"label: " << this->getObjectLabel () << endl;
 
  541     out << 
"initialized: " << (isInitialized_ ? 
"true" : 
"false") << endl
 
  542         << 
"computed: " << (isComputed_ ? 
"true" : 
"false") << endl
 
  543         << 
"number of initialize calls: " << numInitialize_ << endl
 
  544         << 
"number of compute calls: " << numCompute_ << endl
 
  545         << 
"number of apply calls: " << numApply_ << endl
 
  546         << 
"total time in seconds in initialize: " << initializeTime_ << endl
 
  547         << 
"total time in seconds in compute: " << computeTime_ << endl
 
  548         << 
"total time in seconds in apply: " << applyTime_ << endl;
 
  550       out << 
"A_local_dense_:" << endl;
 
  554         for (
int i = 0; i < A_local_dense_.numRows (); ++i) {
 
  555           for (
int j = 0; j < A_local_dense_.numCols (); ++j) {
 
  556             out << A_local_dense_(i,j);
 
  557             if (j + 1 < A_local_dense_.numCols ()) {
 
  561           if (i + 1 < A_local_dense_.numRows ()) {
 
  573 template<
class MatrixType>
 
  581   using Teuchos::rcpFromRef;
 
  584   RCP<FancyOStream> ptrOut = rcpFromRef (out);
 
  592       out << 
"Ifpack2::Details::DenseSolver:" << endl;
 
  594     describeLocal (out, verbLevel);
 
  600     const int myRank = comm.
getRank ();
 
  601     const int numProcs = comm.
getSize ();
 
  603       out << 
"Ifpack2::Details::DenseSolver:" << endl;
 
  606     for (
int p = 0; p < numProcs; ++p) {
 
  608         out << 
"Process " << myRank << 
":" << endl;
 
  609         describeLocal (out, verbLevel);
 
  619 template<
class MatrixType>
 
  622          const row_matrix_type& A_local)
 
  626   typedef local_ordinal_type LO;
 
  638   const map_type& rowMap = * (A_local.getRowMap ());
 
  642   const size_type maxNumRowEntries =
 
  643     static_cast<size_type
> (A_local.getNodeMaxNumRowEntries ());
 
  644   Array<LO> localIndices (maxNumRowEntries);
 
  645   Array<scalar_type> values (maxNumRowEntries);
 
  647   const LO numLocalRows = 
static_cast<LO
> (rowMap.getNodeNumElements ());
 
  648   const LO minLocalRow = rowMap.getMinLocalIndex ();
 
  651   const LO maxLocalRow = minLocalRow + numLocalRows; 
 
  652   for (LO localRow = minLocalRow; localRow < maxLocalRow; ++localRow) {
 
  659     const size_type numEntriesInRow =
 
  660       static_cast<size_type
> (A_local.getNumEntriesInLocalRow (localRow));
 
  661     size_t numEntriesOut = 0; 
 
  662     A_local.getLocalRowCopy (localRow,
 
  663                              localIndices (0, numEntriesInRow),
 
  664                              values (0, numEntriesInRow),
 
  666     for (LO k = 0; k < numEntriesInRow; ++k) {
 
  667       const LO localCol = localIndices[k];
 
  668       const scalar_type val = values[k];
 
  671       A_local_dense(localRow, localCol) += val;
 
  680 template<
class MatrixType>
 
  681 DenseSolver<MatrixType, true>::
 
  687 template<
class MatrixType>
 
  694 template<
class MatrixType>
 
  701 template<
class MatrixType>
 
  709 template<
class MatrixType>
 
  716 template<
class MatrixType>
 
  723 template<
class MatrixType>
 
  730 template<
class MatrixType>
 
  737 template<
class MatrixType>
 
  744 template<
class MatrixType>
 
  751 template<
class MatrixType>
 
  758 template<
class MatrixType>
 
  765 template<
class MatrixType>
 
  772 template<
class MatrixType>
 
  780 template<
class MatrixType>
 
  787 template<
class MatrixType>
 
  788 DenseSolver<MatrixType, true>::~DenseSolver ()
 
  794 template<
class MatrixType>
 
  801 template<
class MatrixType>
 
  803 apply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
 
  804        Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
 
  807        scalar_type beta)
 const 
  813 template<
class MatrixType>
 
  815 DenseSolver<MatrixType, true>::description ()
 const 
  821 template<
class MatrixType>
 
  822 void DenseSolver<MatrixType, true>::
 
  833 #define IFPACK2_DETAILS_DENSESOLVER_INSTANT(S,LO,GO,N)                  \ 
  834   template class Ifpack2::Details::DenseSolver< Tpetra::RowMatrix<S, LO, GO, N> >; 
  836 #endif // IFPACK2_DETAILS_DENSESOLVER_HPP 
ScalarType * values() const 
 
virtual Teuchos::RCP< const Tpetra::Map< MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > > getDomainMap() const =0
The domain Map of this operator. 
 
virtual int getNumApply() const =0
The number of calls to apply(). 
 
virtual int getSize() 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
The input matrix given to the constructor. 
 
virtual int getRank() const =0
 
basic_OSTab< char > OSTab
 
DenseSolver(const Teuchos::RCP< const row_matrix_type > &matrix)
Constructor. 
Definition: Ifpack2_Details_DenseSolver_def.hpp:67
 
basic_FancyOStream< char > FancyOStream
 
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
 
virtual void compute()=0
Set up the numerical values in this preconditioner. 
 
"Preconditioner" that uses LAPACK's dense LU. 
Definition: Ifpack2_Details_DenseSolver_decl.hpp:73
 
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const 
Print the object with some verbosity level to the given FancyOStream. 
Definition: Ifpack2_Details_DenseSolver_def.hpp:575
 
virtual Teuchos::RCP< const Tpetra::Map< MatrixType::local_ordinal_type, MatrixType::global_ordinal_type, MatrixType::node_type > > getRangeMap() const =0
The range Map of this operator. 
 
void GETRF(const OrdinalType &m, const OrdinalType &n, ScalarType *A, const OrdinalType &lda, OrdinalType *IPIV, OrdinalType *info) const 
 
virtual void barrier() const =0
 
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
 
virtual int getNumCompute() const =0
The number of calls to compute(). 
 
int putScalar(const ScalarType value=Teuchos::ScalarTraits< ScalarType >::zero())
 
virtual double getInitializeTime() const =0
The time (in seconds) spent in initialize(). 
 
virtual void initialize()=0
Set up the graph structure of this preconditioner. 
 
virtual bool isComputed() const =0
True if the preconditioner has been successfully computed, else false. 
 
virtual int getNumInitialize() const =0
The number of calls to initialize(). 
 
OrdinalType numCols() const 
 
void GETRS(const char &TRANS, const OrdinalType &n, const OrdinalType &nrhs, const ScalarType *A, const OrdinalType &lda, const OrdinalType *IPIV, ScalarType *B, const OrdinalType &ldb, OrdinalType *info) const 
 
virtual void setParameters(const Teuchos::ParameterList &List)=0
Set this preconditioner's parameters. 
 
TypeTo as(const TypeFrom &t)
 
virtual double getComputeTime() const =0
The time (in seconds) spent in compute(). 
 
Access only local rows and columns of a sparse matrix. 
Definition: Ifpack2_LocalFilter_decl.hpp:160
 
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_typealpha=Teuchos::ScalarTraits< MatrixType::scalar_type >::one(), MatrixType::scalar_typebeta=Teuchos::ScalarTraits< MatrixType::scalar_type >::zero()) const =0
Apply the preconditioner to X, putting the result in Y. 
 
MatrixType::scalar_type scalar_type
The type of entries in the input (global) matrix. 
Definition: Ifpack2_Details_DenseSolver_decl.hpp:106
 
virtual bool isInitialized() const =0
True if the preconditioner has been successfully initialized, else false. 
 
virtual double getApplyTime() const =0
The time (in seconds) spent in apply(). 
 
OrdinalType stride() const 
 
OrdinalType numRows() const 
 
std::string toString(const T &t)
 
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
Set the new matrix.