Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
Ifpack2_Hiptmair_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_HIPTMAIR_DEF_HPP
00044 #define IFPACK2_HIPTMAIR_DEF_HPP
00045 
00046 #include "Ifpack2_Hiptmair_decl.hpp"
00047 #include "Ifpack2_Details_OneLevelFactory_decl.hpp"
00048 #include "Ifpack2_Details_OneLevelFactory_def.hpp"
00049 
00050 namespace Ifpack2 {
00051 
00052 template <class MatrixType>
00053 Hiptmair<MatrixType>::
00054 Hiptmair (const Teuchos::RCP<const row_matrix_type>& A,
00055           const Teuchos::RCP<const row_matrix_type>& PtAP,
00056           const Teuchos::RCP<const row_matrix_type>& P) :
00057   A_ (A),
00058   PtAP_ (PtAP),
00059   P_ (P),
00060   // Default values
00061   precType1_ ("CHEBYSHEV"),
00062   precType2_ ("CHEBYSHEV"),
00063   preOrPost_ ("both"),
00064   ZeroStartingSolution_ (true),
00065   // General
00066   Condest_ (-STM::one ()),
00067   IsInitialized_ (false),
00068   IsComputed_ (false),
00069   NumInitialize_ (0),
00070   NumCompute_ (0),
00071   NumApply_ (0),
00072   InitializeTime_ (0.0),
00073   ComputeTime_ (0.0),
00074   ApplyTime_ (0.0)
00075 {}
00076 
00077 
00078 template <class MatrixType>
00079 Hiptmair<MatrixType>::~Hiptmair() {}
00080 
00081 template <class MatrixType>
00082 void Hiptmair<MatrixType>::setParameters (const Teuchos::ParameterList& plist)
00083 {
00084   using Teuchos::as;
00085   using Teuchos::ParameterList;
00086   using Teuchos::Exceptions::InvalidParameterName;
00087   using Teuchos::Exceptions::InvalidParameterType;
00088 
00089   ParameterList params = plist;
00090 
00091   // Get the current parameters' values.  We don't assign to the
00092   // instance data directly until we've gotten all the parameters.
00093   // This ensures "transactional" semantics, so that if attempting to
00094   // get some parameter throws an exception, the class' state doesn't
00095   // change.
00096   std::string precType1 = precType1_;
00097   std::string precType2 = precType2_;
00098   std::string preOrPost = preOrPost_;
00099   Teuchos::ParameterList precList1 = precList1_;
00100   Teuchos::ParameterList precList2 = precList2_;
00101   bool zeroStartingSolution = ZeroStartingSolution_;
00102 
00103   precType1 = params.get("hiptmair: smoother type 1", precType1);
00104   precType2 = params.get("hiptmair: smoother type 2", precType2);
00105   precList1 = params.get("hiptmair: smoother list 1", precList1);
00106   precList2 = params.get("hiptmair: smoother list 2", precList2);
00107   preOrPost = params.get("hiptmair: pre or post",     preOrPost);
00108   zeroStartingSolution = params.get("hiptmair: zero starting solution",
00109                                     zeroStartingSolution);
00110 
00111   // "Commit" the new values to the instance data.
00112   precType1_ = precType1;
00113   precType2_ = precType2;
00114   precList1_ = precList1;
00115   precList2_ = precList2;
00116   preOrPost_ = preOrPost;
00117   ZeroStartingSolution_ = zeroStartingSolution;
00118 }
00119 
00120 
00121 template <class MatrixType>
00122 Teuchos::RCP<const Teuchos::Comm<int> >
00123 Hiptmair<MatrixType>::getComm () const {
00124   TEUCHOS_TEST_FOR_EXCEPTION(
00125     A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::getComm: "
00126     "The input matrix A is null.  Please call setMatrix() with a nonnull "
00127     "input matrix before calling this method.");
00128   return A_->getComm ();
00129 }
00130 
00131 
00132 template <class MatrixType>
00133 Teuchos::RCP<const Tpetra::RowMatrix<typename MatrixType::scalar_type,typename MatrixType::local_ordinal_type,typename MatrixType::global_ordinal_type,typename MatrixType::node_type> >
00134 Hiptmair<MatrixType>::getMatrix () const {
00135   return A_;
00136 }
00137 
00138 
00139 template <class MatrixType>
00140 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type,typename MatrixType::global_ordinal_type,typename MatrixType::node_type> >
00141 Hiptmair<MatrixType>::getDomainMap () const
00142 {
00143   TEUCHOS_TEST_FOR_EXCEPTION(
00144     A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::getDomainMap: "
00145     "The input matrix A is null.  Please call setMatrix() with a nonnull "
00146     "input matrix before calling this method.");
00147   return A_->getDomainMap ();
00148 }
00149 
00150 
00151 template <class MatrixType>
00152 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type,typename MatrixType::global_ordinal_type,typename MatrixType::node_type> >
00153 Hiptmair<MatrixType>::getRangeMap () const
00154 {
00155   TEUCHOS_TEST_FOR_EXCEPTION(
00156     A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::getRangeMap: "
00157     "The input matrix A is null.  Please call setMatrix() with a nonnull "
00158     "input matrix before calling this method.");
00159   return A_->getRangeMap ();
00160 }
00161 
00162 
00163 template <class MatrixType>
00164 bool Hiptmair<MatrixType>::hasTransposeApply () const {
00165   // FIXME (mfh 17 Jan 2014) apply() does not currently work with mode
00166   // != NO_TRANS, so it's correct to return false here.
00167   return false;
00168 }
00169 
00170 
00171 template <class MatrixType>
00172 int Hiptmair<MatrixType>::getNumInitialize () const {
00173   return NumInitialize_;
00174 }
00175 
00176 
00177 template <class MatrixType>
00178 int Hiptmair<MatrixType>::getNumCompute () const {
00179   return NumCompute_;
00180 }
00181 
00182 
00183 template <class MatrixType>
00184 int Hiptmair<MatrixType>::getNumApply () const {
00185   return NumApply_;
00186 }
00187 
00188 
00189 template <class MatrixType>
00190 double Hiptmair<MatrixType>::getInitializeTime () const {
00191   return InitializeTime_;
00192 }
00193 
00194 
00195 template <class MatrixType>
00196 double Hiptmair<MatrixType>::getComputeTime () const {
00197   return ComputeTime_;
00198 }
00199 
00200 
00201 template <class MatrixType>
00202 double Hiptmair<MatrixType>::getApplyTime () const {
00203   return ApplyTime_;
00204 }
00205 
00206 
00207 template <class MatrixType>
00208 typename Hiptmair<MatrixType>::magnitude_type
00209 Hiptmair<MatrixType>::
00210 computeCondEst (CondestType CT,
00211                 local_ordinal_type MaxIters,
00212                 magnitude_type Tol,
00213                 const Teuchos::Ptr<const row_matrix_type>& matrix)
00214 {
00215   if (! isComputed ()) { // cannot compute right now
00216     return -STM::one ();
00217   }
00218   // NOTE: this is computing the *local* condest
00219   if (Condest_ == -STM::one ()) {
00220     Condest_ = Ifpack2::Condest (*this, CT, MaxIters, Tol, matrix);
00221   }
00222   return Condest_;
00223 }
00224 
00225 
00226 template <class MatrixType>
00227 void Hiptmair<MatrixType>::initialize ()
00228 {
00229   using Teuchos::ParameterList;
00230   using Teuchos::RCP;
00231   using Teuchos::rcp;
00232 
00233   TEUCHOS_TEST_FOR_EXCEPTION(
00234     A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::initialize: "
00235     "The input matrix A is null.  Please call setMatrix() with a nonnull "
00236     "input matrix before calling this method.");
00237 
00238   // clear any previous allocation
00239   IsInitialized_ = false;
00240   IsComputed_ = false;
00241 
00242   Teuchos::Time timer ("initialize");
00243   { // The body of code to time
00244     Teuchos::TimeMonitor timeMon (timer);
00245 
00246     Details::OneLevelFactory<MatrixType> factory;
00247 
00248     ifpack2_prec1_=factory.create(precType1_,A_);
00249     ifpack2_prec1_->initialize();
00250     ifpack2_prec1_->setParameters(precList1_);
00251 
00252     ifpack2_prec2_=factory.create(precType2_,PtAP_);
00253     ifpack2_prec2_->initialize();
00254     ifpack2_prec2_->setParameters(precList2_);
00255 
00256   }
00257   IsInitialized_ = true;
00258   ++NumInitialize_;
00259   InitializeTime_ += timer.totalElapsedTime ();
00260 }
00261 
00262 
00263 template <class MatrixType>
00264 void Hiptmair<MatrixType>::compute ()
00265 {
00266   TEUCHOS_TEST_FOR_EXCEPTION(
00267     A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::compute: "
00268     "The input matrix A is null.  Please call setMatrix() with a nonnull "
00269     "input matrix before calling this method.");
00270 
00271   // Don't time the initialize(); that gets timed separately.
00272   if (! isInitialized ()) {
00273     initialize ();
00274   }
00275 
00276   Teuchos::Time timer ("compute");
00277   { // The body of code to time
00278     Teuchos::TimeMonitor timeMon (timer);
00279     ifpack2_prec1_->compute();
00280     ifpack2_prec2_->compute();
00281   }
00282   IsComputed_ = true;
00283   ++NumCompute_;
00284   ComputeTime_ += timer.totalElapsedTime ();
00285 }
00286 
00287 
00288 template <class MatrixType>
00289 void Hiptmair<MatrixType>::
00290 apply (const Tpetra::MultiVector<typename MatrixType::scalar_type,
00291        typename MatrixType::local_ordinal_type,
00292        typename MatrixType::global_ordinal_type,
00293        typename MatrixType::node_type>& X,
00294        Tpetra::MultiVector<typename MatrixType::scalar_type,
00295                            typename MatrixType::local_ordinal_type,
00296                            typename MatrixType::global_ordinal_type,
00297                            typename MatrixType::node_type>& Y,
00298        Teuchos::ETransp mode,
00299        typename MatrixType::scalar_type alpha,
00300        typename MatrixType::scalar_type beta) const
00301 {
00302   using Teuchos::RCP;
00303   using Teuchos::rcp;
00304   using Teuchos::rcpFromRef;
00305   typedef Tpetra::MultiVector<scalar_type, local_ordinal_type,
00306                               global_ordinal_type, node_type> MV;
00307   TEUCHOS_TEST_FOR_EXCEPTION(
00308     ! isComputed (), std::runtime_error,
00309     "Ifpack2::Hiptmair::apply: You must call compute() before you may call apply().");
00310   TEUCHOS_TEST_FOR_EXCEPTION(
00311     X.getNumVectors () != Y.getNumVectors (), std::invalid_argument,
00312     "Ifpack2::Hiptmair::apply: The MultiVector inputs X and Y do not have the "
00313     "same number of columns.  X.getNumVectors() = " << X.getNumVectors ()
00314     << " != Y.getNumVectors() = " << Y.getNumVectors () << ".");
00315 
00316   // Catch unimplemented cases: alpha != 1, beta != 0, mode != NO_TRANS.
00317   TEUCHOS_TEST_FOR_EXCEPTION(
00318     alpha != STS::one (), std::logic_error,
00319     "Ifpack2::Hiptmair::apply: alpha != 1 has not been implemented.");
00320   TEUCHOS_TEST_FOR_EXCEPTION(
00321     beta != STS::zero (), std::logic_error,
00322     "Ifpack2::Hiptmair::apply: zero != 0 has not been implemented.");
00323   TEUCHOS_TEST_FOR_EXCEPTION(
00324     mode != Teuchos::NO_TRANS, std::logic_error,
00325     "Ifpack2::Hiptmair::apply: mode != Teuchos::NO_TRANS has not been implemented.");
00326 
00327   Teuchos::Time timer ("apply");
00328   { // The body of code to time
00329     Teuchos::TimeMonitor timeMon (timer);
00330 
00331     // If X and Y are pointing to the same memory location,
00332     // we need to create an auxiliary vector, Xcopy
00333     RCP<const MV> Xcopy;
00334     if (X.getLocalMV ().getValues () == Y.getLocalMV ().getValues ()) {
00335       Xcopy = rcp (new MV (X, Teuchos::Copy));
00336     } else {
00337       Xcopy = rcpFromRef (X);
00338     }
00339 
00340     RCP<MV> Ycopy = rcpFromRef (Y);
00341     if (ZeroStartingSolution_) {
00342       Ycopy->putScalar (STS::zero ());
00343     }
00344 
00345     // apply Hiptmair Smoothing
00346     applyHiptmairSmoother (*Xcopy, *Ycopy);
00347 
00348   }
00349   ++NumApply_;
00350   ApplyTime_ += timer.totalElapsedTime ();
00351 }
00352 
00353 template <class MatrixType>
00354 void Hiptmair<MatrixType>::
00355 applyHiptmairSmoother(const Tpetra::MultiVector<typename MatrixType::scalar_type,
00356                       typename MatrixType::local_ordinal_type,
00357                       typename MatrixType::global_ordinal_type,
00358                       typename MatrixType::node_type>& X,
00359                       Tpetra::MultiVector<typename MatrixType::scalar_type,
00360                       typename MatrixType::local_ordinal_type,
00361                       typename MatrixType::global_ordinal_type,
00362                       typename MatrixType::node_type>& Y) const
00363 {
00364   using Teuchos::RCP;
00365   using Teuchos::rcp;
00366   using Teuchos::rcpFromRef;
00367   typedef Teuchos::ScalarTraits<scalar_type> STS;
00368   typedef Tpetra::MultiVector<scalar_type, local_ordinal_type,
00369     global_ordinal_type, node_type> MV;
00370   const scalar_type ZERO = STS::zero ();
00371   const scalar_type ONE = STS::one ();
00372 
00373   RCP<MV> res1 = rcp (new MV (A_->getRowMap (), X.getNumVectors ()));
00374   RCP<MV> vec1 = rcp (new MV (A_->getRowMap (), X.getNumVectors ()));
00375   RCP<MV> res2 = rcp (new MV (PtAP_->getRowMap (), X.getNumVectors ()));
00376   RCP<MV> vec2 = rcp (new MV (PtAP_->getRowMap (), X.getNumVectors ()));
00377 
00378   if (preOrPost_ == "pre" || preOrPost_ == "both") {
00379     // apply initial relaxation to primary space
00380     A_->apply (Y, *res1);
00381     res1->update (ONE, X, -ONE);
00382     vec1->putScalar (ZERO);
00383     ifpack2_prec1_->apply (*res1, *vec1);
00384     Y.update (ONE, *vec1, ONE);
00385   }
00386 
00387   // project to auxiliary space and smooth
00388   A_->apply (Y, *res1);
00389   res1->update (ONE, X, -ONE);
00390   P_->apply (*res1, *res2, Teuchos::TRANS);
00391   vec2->putScalar (ZERO);
00392   ifpack2_prec2_->apply (*res2, *vec2);
00393   P_->apply (*vec2, *vec1, Teuchos::NO_TRANS);
00394   Y.update (ONE,*vec1,ONE);
00395 
00396   if (preOrPost_ == "post" || preOrPost_ == "both") {
00397     // smooth again on primary space
00398     A_->apply (Y, *res1);
00399     res1->update (ONE, X, -ONE);
00400     vec1->putScalar (ZERO);
00401     ifpack2_prec1_->apply (*res1, *vec1);
00402     Y.update (ONE, *vec1, ONE);
00403   }
00404 }
00405 
00406 template <class MatrixType>
00407 std::string Hiptmair<MatrixType>::description () const
00408 {
00409   std::ostringstream os;
00410 
00411   // Output is a valid YAML dictionary in flow style.  If you don't
00412   // like everything on a single line, you should call describe()
00413   // instead.
00414   os << "\"Ifpack2::Hiptmair\": {";
00415   if (this->getObjectLabel () != "") {
00416     os << "Label: \"" << this->getObjectLabel () << "\", ";
00417   }
00418   os << "Initialized: " << (isInitialized () ? "true" : "false") << ", "
00419      << "Computed: " << (isComputed () ? "true" : "false") << ", ";
00420 
00421   if (A_.is_null ()) {
00422     os << "Matrix: null";
00423   }
00424   else {
00425     os << "Matrix: not null"
00426        << ", Global matrix dimensions: ["
00427        << A_->getGlobalNumRows () << ", " << A_->getGlobalNumCols () << "]";
00428   }
00429 
00430   os << "}";
00431   return os.str ();
00432 }
00433 
00434 
00435 template <class MatrixType>
00436 void Hiptmair<MatrixType>::
00437 describe (Teuchos::FancyOStream &out,
00438           const Teuchos::EVerbosityLevel verbLevel) const
00439 {
00440   using std::endl;
00441   using std::setw;
00442   using Teuchos::VERB_DEFAULT;
00443   using Teuchos::VERB_NONE;
00444   using Teuchos::VERB_LOW;
00445   using Teuchos::VERB_MEDIUM;
00446   using Teuchos::VERB_HIGH;
00447   using Teuchos::VERB_EXTREME;
00448 
00449   const Teuchos::EVerbosityLevel vl =
00450     (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
00451 
00452   if (vl != VERB_NONE) {
00453     // describe() always starts with a tab by convention.
00454     Teuchos::OSTab tab0 (out);
00455     out << "\"Ifpack2::Hiptmair\":";
00456 
00457     Teuchos::OSTab tab1 (out);
00458     if (this->getObjectLabel () != "") {
00459       out << "Label: " << this->getObjectLabel () << endl;
00460     }
00461     out << "Initialized: " << (isInitialized () ? "true" : "false") << endl
00462         << "Computed: " << (isComputed () ? "true" : "false") << endl
00463         << "Global number of rows: " << A_->getGlobalNumRows () << endl
00464         << "Global number of columns: " << A_->getGlobalNumCols () << endl
00465         << "Matrix:";
00466     if (A_.is_null ()) {
00467       out << " null" << endl;
00468     } else {
00469       A_->describe (out, vl);
00470     }
00471   }
00472 }
00473 
00474 } // namespace Ifpack2
00475 
00476 #define IFPACK2_HIPTMAIR_INSTANT(S,LO,GO,N) \
00477   template class Ifpack2::Hiptmair< Tpetra::CrsMatrix<S, LO, GO, N> >;
00478 
00479 #endif /* IFPACK2_HIPTMAIR_DEF_HPP */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends