Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
Ifpack2_IdentitySolver_def.hpp
00001 /*@HEADER
00002 // ***********************************************************************
00003 //
00004 //       Ifpack2: Tempated Object-Oriented Algebraic Preconditioner Package
00005 //                 Copyright (2009) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 //@HEADER
00041 */
00042 
00043 #ifndef IFPACK2_IDENTITY_SOLVER_DEF_HPP
00044 #define IFPACK2_IDENTITY_SOLVER_DEF_HPP
00045 
00046 #include "Ifpack2_IdentitySolver_decl.hpp"
00047 #include "Ifpack2_Condest.hpp"
00048 
00049 namespace Ifpack2 {
00050 
00051 template<class MatrixType>
00052 IdentitySolver<MatrixType>::
00053 IdentitySolver (const Teuchos::RCP<const row_matrix_type>& A)
00054   : matrix_ (A),
00055     isInitialized_ (false),
00056     isComputed_ (false),
00057     numInitialize_ (0),
00058     numCompute_ (0),
00059     numApply_ (0),
00060     initializeTime_(0.0),
00061     computeTime_(0.0),
00062     applyTime_(0.0),
00063     condEst_ (-Teuchos::ScalarTraits<magnitude_type>::one ())
00064 {
00065 }
00066 
00067 template<class MatrixType>
00068 IdentitySolver<MatrixType>::~IdentitySolver ()
00069 {
00070 }
00071 
00072 template<class MatrixType>
00073 void IdentitySolver<MatrixType>::setParameters (const Teuchos::ParameterList& /*params*/)
00074 {
00075 }
00076 
00077 template<class MatrixType>
00078 void IdentitySolver<MatrixType>::initialize ()
00079 {
00080   TEUCHOS_TEST_FOR_EXCEPTION(
00081     matrix_.is_null (), std::runtime_error, "Ifpack2::IdentitySolver: "
00082     "You must call setMatrix() with a nonnull input matrix "
00083     "before you may call initialize() or compute().");
00084 
00085   TEUCHOS_TEST_FOR_EXCEPTION(
00086     ! matrix_->getDomainMap ()->isCompatible (* (matrix_->getRangeMap ())),
00087     std::invalid_argument,
00088     "Ifpack2::IdentitySolver: The domain and range Maps "
00089     "of the input matrix must be compatible.");
00090 
00091   // If the domain and range Maps are not the same, then we need to
00092   // construct an Export from the domain Map to the range Map, so that
00093   // this operator is really the identity and not a permutation.
00094   if (! matrix_->getDomainMap ()->isSameAs (* (matrix_->getRangeMap ()))) {
00095     export_ = Teuchos::rcp (new export_type (matrix_->getDomainMap (),
00096                                              matrix_->getRangeMap ()));
00097   }
00098   else {
00099     // If the Export is null, we won't do the Export in apply().
00100     // Thus, we need to set it to null here as a flag.
00101     export_ = Teuchos::null;
00102   }
00103 
00104   isInitialized_ = true;
00105   ++numInitialize_;
00106 }
00107 
00108 template<class MatrixType>
00109 void IdentitySolver<MatrixType>::compute ()
00110 {
00111   TEUCHOS_TEST_FOR_EXCEPTION(
00112     matrix_.is_null (), std::runtime_error, "Ifpack2::IdentitySolver: "
00113     "You must call setMatrix() with a nonnull input matrix "
00114     "before you may call initialize() or compute().");
00115 
00116   if (! isInitialized_) {
00117     initialize ();
00118   }
00119 
00120   isComputed_ = true;
00121   ++numCompute_;
00122 }
00123 
00124 template<class MatrixType>
00125 void IdentitySolver<MatrixType>::
00126 apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
00127        Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
00128        Teuchos::ETransp /*mode*/,
00129        scalar_type alpha,
00130        scalar_type beta) const
00131 {
00132   using Teuchos::RCP;
00133   typedef Teuchos::ScalarTraits<scalar_type> STS;
00134   typedef Tpetra::MultiVector<scalar_type, local_ordinal_type,
00135                               global_ordinal_type, node_type> MV;
00136 
00137   TEUCHOS_TEST_FOR_EXCEPTION(
00138     ! isComputed (), std::runtime_error,
00139     "Ifpack2::IdentitySolver::apply: If compute() has not yet been called, "
00140     "or if you have changed the matrix via setMatrix(), "
00141     "you must call compute() before you may call this method.");
00142 
00143   // "Identity solver" does what it says: it's the identity operator.
00144   // We have to Export if the domain and range Maps are not the same.
00145   // Otherwise, this operator would be a permutation, not the identity.
00146   if (export_.is_null ()) {
00147     Y.update (alpha, X, beta);
00148   }
00149   else {
00150     if (alpha == STS::one () && beta == STS::zero ()) { // the common case
00151       Y.doExport (X, *export_, Tpetra::REPLACE);
00152     }
00153     else {
00154       // We know that the domain and range Maps are compatible.  First
00155       // bring X into the range Map via Export.  Then compute in place
00156       // in Y.
00157       MV X_tmp (Y.getMap (), Y.getNumVectors ());
00158       X_tmp.doExport (X, *export_, Tpetra::REPLACE);
00159       Y.update (alpha, X_tmp, beta);
00160     }
00161   }
00162   ++numApply_;
00163 }
00164 
00165 template<class MatrixType>
00166 typename IdentitySolver<MatrixType>::magnitude_type
00167 IdentitySolver<MatrixType>::
00168 computeCondEst (CondestType CT,
00169                 local_ordinal_type MaxIters,
00170                 magnitude_type Tol,
00171                 const Teuchos::Ptr<const row_matrix_type>& matrix)
00172 {
00173   // Forestall compiler warnings for unused variables.
00174   (void) CT;
00175   (void) MaxIters;
00176   (void) Tol;
00177   (void) matrix;
00178 
00179   return -Teuchos::ScalarTraits<magnitude_type>::one ();
00180 }
00181 
00182 template <class MatrixType>
00183 int IdentitySolver<MatrixType>::getNumInitialize() const {
00184   return(numInitialize_);
00185 }
00186 
00187 template <class MatrixType>
00188 int IdentitySolver<MatrixType>::getNumCompute() const {
00189   return(numCompute_);
00190 }
00191 
00192 template <class MatrixType>
00193 int IdentitySolver<MatrixType>::getNumApply() const {
00194   return(numApply_);
00195 }
00196 
00197 template <class MatrixType>
00198 double IdentitySolver<MatrixType>::getInitializeTime() const {
00199   return(initializeTime_);
00200 }
00201 
00202 template<class MatrixType>
00203 double IdentitySolver<MatrixType>::getComputeTime() const {
00204   return(computeTime_);
00205 }
00206 
00207 template<class MatrixType>
00208 double IdentitySolver<MatrixType>::getApplyTime() const {
00209   return(applyTime_);
00210 }
00211 
00212 template <class MatrixType>
00213 std::string IdentitySolver<MatrixType>::description () const
00214 {
00215   std::ostringstream os;
00216 
00217   // Output is a valid YAML dictionary in flow style.  If you don't
00218   // like everything on a single line, you should call describe()
00219   // instead.
00220   os << "\"Ifpack2::IdentitySolver\": {";
00221   if (this->getObjectLabel () != "") {
00222     os << "Label: \"" << this->getObjectLabel () << "\", ";
00223   }
00224   os << "Initialized: " << (isInitialized () ? "true" : "false") << ", "
00225      << "Computed: " << (isComputed () ? "true" : "false") << ", ";
00226 
00227   if (matrix_.is_null ()) {
00228     os << "Matrix: null";
00229   }
00230   else {
00231     os << "Matrix: not null"
00232        << ", Global matrix dimensions: ["
00233        << matrix_->getGlobalNumRows () << ", "
00234        << matrix_->getGlobalNumCols () << "]";
00235   }
00236 
00237   os << "}";
00238   return os.str ();
00239 }
00240 
00241 template <class MatrixType>
00242 void IdentitySolver<MatrixType>::
00243 describe (Teuchos::FancyOStream& out,
00244           const Teuchos::EVerbosityLevel verbLevel) const
00245 {
00246   using std::endl;
00247   const Teuchos::EVerbosityLevel vl
00248     = (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
00249 
00250   if (vl != Teuchos::VERB_NONE) {
00251     // By convention, describe() should always begin with a tab.
00252     Teuchos::OSTab tab0 (out);
00253     out << "\"Ifpack2::IdentitySolver\":" << endl;
00254     Teuchos::OSTab tab1 (out);
00255     out << "MatrixType: " << Teuchos::TypeNameTraits<MatrixType>::name () << endl;
00256     out << "numInitialize: " << numInitialize_ << endl;
00257     out << "numCompute: " << numCompute_ << endl;
00258     out << "numApply: " << numApply_ << endl;
00259   }
00260 }
00261 
00262 template <class MatrixType>
00263 Teuchos::RCP<const typename IdentitySolver<MatrixType>::map_type> IdentitySolver<MatrixType>::getDomainMap() const
00264 {
00265   TEUCHOS_TEST_FOR_EXCEPTION(
00266     matrix_.is_null (), std::runtime_error, "Ifpack2::IdentitySolver::getDomainMap: "
00267     "The matrix is null.  Please call setMatrix() with a nonnull input "
00268     "before calling this method.");
00269   return matrix_->getDomainMap ();
00270 }
00271 
00272 template <class MatrixType>
00273 Teuchos::RCP<const typename IdentitySolver<MatrixType>::map_type> IdentitySolver<MatrixType>::getRangeMap() const
00274 {
00275   TEUCHOS_TEST_FOR_EXCEPTION(
00276     matrix_.is_null (), std::runtime_error, "Ifpack2::IdentitySolver::getRangeMap: "
00277     "The matrix is null.  Please call setMatrix() with a nonnull input "
00278     "before calling this method.");
00279   return matrix_->getRangeMap ();
00280 }
00281 
00282 template<class MatrixType>
00283 void IdentitySolver<MatrixType>::
00284 setMatrix (const Teuchos::RCP<const row_matrix_type>& A)
00285 {
00286   // Check in serial or one-process mode if the matrix is square.
00287   TEUCHOS_TEST_FOR_EXCEPTION(
00288     ! A.is_null () && A->getComm ()->getSize () == 1 &&
00289     A->getNodeNumRows () != A->getNodeNumCols (),
00290     std::runtime_error, "Ifpack2::IdentitySolver::setMatrix: If A's communicator only "
00291     "contains one process, then A must be square.  Instead, you provided a "
00292     "matrix A with " << A->getNodeNumRows () << " rows and "
00293     << A->getNodeNumCols () << " columns.");
00294 
00295   // It's legal for A to be null; in that case, you may not call
00296   // initialize() until calling setMatrix() with a nonnull input.
00297   // Regardless, setting the matrix invalidates the preconditioner.
00298   isInitialized_ = false;
00299   isComputed_ = false;
00300   export_ = Teuchos::null;
00301 
00302   matrix_ = A;
00303 }
00304 
00305 } // namespace Ifpack2
00306 
00307 #define IFPACK2_IDENTITYSOLVER_INSTANT(S,LO,GO,N)                            \
00308   template class Ifpack2::IdentitySolver< Tpetra::CrsMatrix<S, LO, GO, N> >; \
00309   template class Ifpack2::IdentitySolver< Tpetra::RowMatrix<S, LO, GO, N> >;
00310 
00311 #endif // IFPACK2_IDENTITY_SOLVER_DEF_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends