Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
Ifpack2_Krylov_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_KRYLOV_DEF_HPP
00044 #define IFPACK2_KRYLOV_DEF_HPP
00045 
00046 #include "Ifpack2_Krylov_decl.hpp"
00047 
00048 namespace Ifpack2 {
00049 
00050 template <class MatrixType>
00051 Krylov<MatrixType>::
00052 Krylov (const Teuchos::RCP<const row_matrix_type>& A) :
00053   A_ (A),
00054   // Default values
00055   iterationType_ ("GMRES"),
00056   numIters_ (5),
00057   resTol_ (0.001), // FIXME (mfh 17 Jan 2014) Make a function of STS::eps()
00058   BlockSize_ (1),
00059   ZeroStartingSolution_ (true),
00060   PreconditionerType_ (1),
00061   // General
00062   Condest_ (-STM::one ()),
00063   IsInitialized_ (false),
00064   IsComputed_ (false),
00065   NumInitialize_ (0),
00066   NumCompute_ (0),
00067   NumApply_ (0),
00068   InitializeTime_ (0.0),
00069   ComputeTime_ (0.0),
00070   ApplyTime_ (0.0)
00071 {}
00072 
00073 
00074 template <class MatrixType>
00075 Krylov<MatrixType>::~Krylov() {}
00076 
00077 
00078 template <class MatrixType>
00079 void Krylov<MatrixType>::setMatrix (const Teuchos::RCP<const row_matrix_type>& A)
00080 {
00081   // Check in serial or one-process mode if the matrix is square.
00082   TEUCHOS_TEST_FOR_EXCEPTION(
00083     ! A.is_null () && A->getComm ()->getSize () == 1 &&
00084     A->getNodeNumRows () != A->getNodeNumCols (),
00085     std::runtime_error, "Ifpack2::Krylov::setMatrix: If A's communicator only "
00086     "contains one process, then A must be square.  Instead, you provided a "
00087     "matrix A with " << A->getNodeNumRows () << " rows and "
00088     << A->getNodeNumCols () << " columns.");
00089 
00090   // It's legal for A to be null; in that case, you may not call
00091   // initialize() until calling setMatrix() with a nonnull input.
00092   // Regardless, setting the matrix invalidates any previous
00093   // factorization.
00094   IsInitialized_ = false;
00095   IsComputed_ = false;
00096   Condest_ = -STM::one ();
00097 
00098   A_ = A;
00099 }
00100 
00101 
00102 template <class MatrixType>
00103 void Krylov<MatrixType>::setParameters (const Teuchos::ParameterList& plist)
00104 {
00105   using Teuchos::as;
00106   using Teuchos::ParameterList;
00107   using Teuchos::Exceptions::InvalidParameterName;
00108   using Teuchos::Exceptions::InvalidParameterType;
00109 
00110   // FIXME (mfh 12 Sep 2014) Don't rewrite Belos::SolverFactory!!! Use
00111   // that instead.
00112 
00113   ParameterList params = plist;
00114 
00115   // Get the current parameters' values.  We don't assign to the
00116   // instance data directly until we've gotten all the parameters.
00117   // This ensures "transactional" semantics, so that if attempting to
00118   // get some parameter throws an exception, the class' state doesn't
00119   // change.
00120   magnitude_type resTol = resTol_;
00121   int numIters = numIters_;
00122   std::string iterType = iterationType_;
00123   int blockSize = BlockSize_;
00124   bool zeroStartingSolution = ZeroStartingSolution_;
00125   int precType = PreconditionerType_;
00126 
00127   //
00128   // Get the "krylov: iteration type" parameter.
00129   //
00130   // We prefer std::string (name of Belos solver), but allow int
00131   // ("enum" value) for backwards compatibility.
00132   //
00133   bool gotIterType = false;
00134   try {
00135     iterType = params.get<std::string> ("krylov: iteration type");
00136     gotIterType = true;
00137   }
00138   catch (InvalidParameterName) {
00139     gotIterType = true; // the parameter is not there, so don't try to get it anymore
00140   }
00141   catch (InvalidParameterType) {
00142     // Perhaps the user specified it as int.
00143   }
00144   // If it's not string, it has to be int.
00145   // We've already checked whether the name exists.
00146   if (! gotIterType) {
00147     const int iterTypeInt = params.get<int> ("krylov: iteration type");
00148     gotIterType = true;
00149 
00150     if (iterTypeInt == 1) {
00151       iterType = "GMRES";
00152     } else if (iterTypeInt == 2) {
00153       iterType = "CG";
00154     } else {
00155       TEUCHOS_TEST_FOR_EXCEPTION(
00156         true, std::invalid_argument, "Ifpack2::Krylov::setParameters: Invalid "
00157         "\"krylov: iteration type\" value " << iterTypeInt << ".  Valid int "
00158         "values are 1 (GMRES) and 2 (CG).  Please prefer setting this "
00159         "parameter as a string (the name of the Krylov solver to use).");
00160     }
00161   }
00162 
00163   resTol = params.get ("krylov: residual tolerance", resTol);
00164   numIters = params.get ("krylov: number of iterations", numIters);
00165   blockSize = params.get ("krylov: block size", blockSize);
00166   zeroStartingSolution = params.get ("krylov: zero starting solution",
00167                                      zeroStartingSolution);
00168   precType = params.get ("krylov: preconditioner type", precType);
00169 
00170   // Separate preconditioner parameters into another list
00171   //
00172   // FIXME (mfh 17 Jan 2014) Inner preconditioner's parameters should
00173   // be a sublist, not part of the main list!!!
00174   if (PreconditionerType_ == 1) {
00175     precParams_.set ("relaxation: sweeps",
00176                      params.get ("relaxation: sweeps", 1));
00177     precParams_.set ("relaxation: damping factor",
00178                      params.get ("relaxation: damping factor", (scalar_type) 1.0));
00179     precParams_.set ("relaxation: min diagonal value",
00180                      params.get ("relaxation: min diagonal value", STS::one ()));
00181     precParams_.set ("relaxation: zero starting solution",
00182                      params.get ("relaxation: zero starting solution", true));
00183     precParams_.set ("relaxation: backward mode",
00184                      params.get ("relaxation: backward mode", false));
00185   }
00186   // FIXME (mfh 17 Jan 2014) AdditiveSchwarz's ParameterList no longer
00187   // takes parameters for its subdomain solver!  You have to pass them
00188   // into a sublist.
00189   if (PreconditionerType_ == 2 || PreconditionerType_ == 3) {
00190     // FIXME (mfh 17 Jan 2014) should be an integer, given how ILUT
00191     // works!  Furthermore, this parameter does not mean what you
00192     // think it means.
00193     precParams_.set ("fact: ilut level-of-fill",
00194                      params.get ("fact: ilut level-of-fill", (double) 1.0));
00195     precParams_.set ("fact: iluk level-of-fill",
00196                      params.get ("fact: iluk level-of-fill", (double) 1.0));
00197     // FIXME (mfh 17 Jan 2014) scalar_type or magnitude_type? not
00198     // sure, but double is definitely wrong.
00199     precParams_.set ("fact: absolute threshold",
00200                      params.get ("fact: absolute threshold", (double) 0.0));
00201     // FIXME (mfh 17 Jan 2014) scalar_type or magnitude_type? not
00202     // sure, but double is definitely wrong.
00203     precParams_.set ("fact: relative threshold",
00204                      params.get("fact: relative threshold", (double) 1.0));
00205     // FIXME (mfh 17 Jan 2014) scalar_type or magnitude_type? not
00206     // sure, but double is definitely wrong.
00207     precParams_.set ("fact: relax value",
00208                      params.get ("fact: relax value", (double) 0.0));
00209   }
00210 
00211   // "Commit" the new values to the instance data.
00212   iterationType_ = iterType;
00213   numIters_ = numIters;
00214   resTol_ = resTol;
00215   BlockSize_ = blockSize;
00216   ZeroStartingSolution_ = zeroStartingSolution;
00217   PreconditionerType_ = precType;
00218 }
00219 
00220 
00221 template <class MatrixType>
00222 Teuchos::RCP<const Teuchos::Comm<int> >
00223 Krylov<MatrixType>::getComm () const {
00224   TEUCHOS_TEST_FOR_EXCEPTION(
00225     A_.is_null (), std::runtime_error, "Ifpack2::Krylov::getComm: "
00226     "The input matrix A is null.  Please call setMatrix() with a nonnull "
00227     "input matrix before calling this method.");
00228   return A_->getComm ();
00229 }
00230 
00231 
00232 template <class MatrixType>
00233 Teuchos::RCP<const Tpetra::RowMatrix<typename MatrixType::scalar_type,typename MatrixType::local_ordinal_type,typename MatrixType::global_ordinal_type,typename MatrixType::node_type> >
00234 Krylov<MatrixType>::getMatrix () const {
00235   return A_;
00236 }
00237 
00238 
00239 template <class MatrixType>
00240 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type,typename MatrixType::global_ordinal_type,typename MatrixType::node_type> >
00241 Krylov<MatrixType>::getDomainMap () const
00242 {
00243   TEUCHOS_TEST_FOR_EXCEPTION(
00244     A_.is_null (), std::runtime_error, "Ifpack2::Krylov::getDomainMap: "
00245     "The input matrix A is null.  Please call setMatrix() with a nonnull "
00246     "input matrix before calling this method.");
00247   return A_->getDomainMap ();
00248 }
00249 
00250 
00251 template <class MatrixType>
00252 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type,typename MatrixType::global_ordinal_type,typename MatrixType::node_type> >
00253 Krylov<MatrixType>::getRangeMap () const
00254 {
00255   TEUCHOS_TEST_FOR_EXCEPTION(
00256     A_.is_null (), std::runtime_error, "Ifpack2::Krylov::getRangeMap: "
00257     "The input matrix A is null.  Please call setMatrix() with a nonnull "
00258     "input matrix before calling this method.");
00259   return A_->getRangeMap ();
00260 }
00261 
00262 
00263 template <class MatrixType>
00264 bool Krylov<MatrixType>::hasTransposeApply () const {
00265   // FIXME (mfh 17 Jan 2014) apply() does not currently work with mode
00266   // != NO_TRANS, so it's correct to return false here.
00267   return false;
00268 }
00269 
00270 
00271 template <class MatrixType>
00272 int Krylov<MatrixType>::getNumInitialize () const {
00273   return NumInitialize_;
00274 }
00275 
00276 
00277 template <class MatrixType>
00278 int Krylov<MatrixType>::getNumCompute () const {
00279   return NumCompute_;
00280 }
00281 
00282 
00283 template <class MatrixType>
00284 int Krylov<MatrixType>::getNumApply () const {
00285   return NumApply_;
00286 }
00287 
00288 
00289 template <class MatrixType>
00290 double Krylov<MatrixType>::getInitializeTime () const {
00291   return InitializeTime_;
00292 }
00293 
00294 
00295 template <class MatrixType>
00296 double Krylov<MatrixType>::getComputeTime () const {
00297   return ComputeTime_;
00298 }
00299 
00300 
00301 template <class MatrixType>
00302 double Krylov<MatrixType>::getApplyTime () const {
00303   return ApplyTime_;
00304 }
00305 
00306 
00307 template <class MatrixType>
00308 typename Krylov<MatrixType>::magnitude_type
00309 Krylov<MatrixType>::
00310 computeCondEst (CondestType CT,
00311                 local_ordinal_type MaxIters,
00312                 magnitude_type Tol,
00313                 const Teuchos::Ptr<const row_matrix_type>& matrix)
00314 {
00315   if (! isComputed ()) { // cannot compute right now
00316     return -STM::one ();
00317   }
00318   // NOTE: this is computing the *local* condest
00319   if (Condest_ == -STM::one ()) {
00320     Condest_ = Ifpack2::Condest (*this, CT, MaxIters, Tol, matrix);
00321   }
00322   return Condest_;
00323 }
00324 
00325 
00326 template <class MatrixType>
00327 void Krylov<MatrixType>::initialize ()
00328 {
00329   using Teuchos::ParameterList;
00330   using Teuchos::RCP;
00331   using Teuchos::rcp;
00332   typedef Tpetra::MultiVector<scalar_type, local_ordinal_type,
00333                               global_ordinal_type, node_type> TMV;
00334   typedef Tpetra::Operator<scalar_type, local_ordinal_type,
00335                            global_ordinal_type, node_type> TOP;
00336 
00337   TEUCHOS_TEST_FOR_EXCEPTION(
00338     A_.is_null (), std::runtime_error, "Ifpack2::Krylov::initialize: "
00339     "The input matrix A is null.  Please call setMatrix() with a nonnull "
00340     "input matrix before calling this method.");
00341 
00342   // clear any previous allocation
00343   IsInitialized_ = false;
00344   IsComputed_ = false;
00345 
00346   Teuchos::Time timer ("initialize");
00347   { // The body of code to time
00348     Teuchos::TimeMonitor timeMon (timer);
00349 
00350     // Belos parameter list
00351     RCP<ParameterList> belosList = rcp (new ParameterList ("GMRES"));
00352     belosList->set ("Maximum Iterations", numIters_);
00353     belosList->set ("Convergence Tolerance", resTol_);
00354 
00355     // FIXME (17 Jan 2014) This whole "preconditioner type" thing is
00356     // not how we want Krylov to initialize its inner preconditioner.
00357     // Krylov should be initialized like AdditiveSchwarz: the Factory
00358     // should create it, in order to avoid circular dependencies.
00359 
00360     if (PreconditionerType_ == 0) {
00361       // no preconditioner
00362     }
00363     else if (PreconditionerType_==1) {
00364       ifpack2_prec_=rcp (new Relaxation<MatrixType> (A_));
00365     }
00366     else if (PreconditionerType_==2) {
00367       ifpack2_prec_=rcp (new ILUT<MatrixType> (A_));
00368     }
00369     else if (PreconditionerType_==3) {
00370       ifpack2_prec_ = rcp (new RILUK<MatrixType> (A_));
00371     }
00372     else if (PreconditionerType_==4) {
00373       ifpack2_prec_ = rcp (new Chebyshev<MatrixType> (A_));
00374     }
00375     if (PreconditionerType_>0) {
00376       ifpack2_prec_->initialize();
00377       ifpack2_prec_->setParameters(precParams_);
00378     }
00379     belosProblem_ = rcp (new Belos::LinearProblem<belos_scalar_type,TMV,TOP> ());
00380     belosProblem_->setOperator (A_);
00381 
00382     if (iterationType_ == "GMRES") {
00383       belosSolver_ =
00384         rcp (new Belos::BlockGmresSolMgr<belos_scalar_type,TMV,TOP> (belosProblem_, belosList));
00385     }
00386     else {
00387       belosSolver_ =
00388         rcp (new Belos::BlockCGSolMgr<belos_scalar_type,TMV,TOP> (belosProblem_, belosList));
00389     }
00390 
00391   }
00392   IsInitialized_ = true;
00393   ++NumInitialize_;
00394   InitializeTime_ += timer.totalElapsedTime ();
00395 }
00396 
00397 
00398 template <class MatrixType>
00399 void Krylov<MatrixType>::compute ()
00400 {
00401   TEUCHOS_TEST_FOR_EXCEPTION(
00402     A_.is_null (), std::runtime_error, "Ifpack2::Krylov::compute: "
00403     "The input matrix A is null.  Please call setMatrix() with a nonnull "
00404     "input matrix before calling this method.");
00405 
00406   // Don't time the initialize(); that gets timed separately.
00407   if (! isInitialized ()) {
00408     initialize ();
00409   }
00410 
00411   Teuchos::Time timer ("compute");
00412   { // The body of code to time
00413     Teuchos::TimeMonitor timeMon (timer);
00414     if (PreconditionerType_ > 0) {
00415       ifpack2_prec_->compute ();
00416       belosProblem_->setLeftPrec (ifpack2_prec_);
00417     }
00418   }
00419   IsComputed_ = true;
00420   ++NumCompute_;
00421   ComputeTime_ += timer.totalElapsedTime ();
00422 }
00423 
00424 
00425 template <class MatrixType>
00426 void Krylov<MatrixType>::
00427 apply (const Tpetra::MultiVector<typename MatrixType::scalar_type,
00428        typename MatrixType::local_ordinal_type,
00429        typename MatrixType::global_ordinal_type,
00430        typename MatrixType::node_type>& X,
00431        Tpetra::MultiVector<typename MatrixType::scalar_type,
00432                            typename MatrixType::local_ordinal_type,
00433                            typename MatrixType::global_ordinal_type,
00434                            typename MatrixType::node_type>& Y,
00435        Teuchos::ETransp mode,
00436        typename MatrixType::scalar_type alpha,
00437        typename MatrixType::scalar_type beta) const
00438 {
00439   using Teuchos::RCP;
00440   using Teuchos::rcp;
00441   using Teuchos::rcpFromRef;
00442   typedef Tpetra::MultiVector<scalar_type, local_ordinal_type,
00443                               global_ordinal_type, node_type> MV;
00444   TEUCHOS_TEST_FOR_EXCEPTION(
00445     ! isComputed (), std::runtime_error,
00446     "Ifpack2::Krylov::apply: You must call compute() before you may call apply().");
00447   TEUCHOS_TEST_FOR_EXCEPTION(
00448     X.getNumVectors () != Y.getNumVectors (), std::invalid_argument,
00449     "Ifpack2::Krylov::apply: The MultiVector inputs X and Y do not have the "
00450     "same number of columns.  X.getNumVectors() = " << X.getNumVectors ()
00451     << " != Y.getNumVectors() = " << Y.getNumVectors () << ".");
00452 
00453   // Catch unimplemented cases: alpha != 1, beta != 0, mode != NO_TRANS.
00454   TEUCHOS_TEST_FOR_EXCEPTION(
00455     alpha != STS::one (), std::logic_error,
00456     "Ifpack2::Krylov::apply: alpha != 1 has not been implemented.");
00457   TEUCHOS_TEST_FOR_EXCEPTION(
00458     beta != STS::zero (), std::logic_error,
00459     "Ifpack2::Krylov::apply: zero != 0 has not been implemented.");
00460   TEUCHOS_TEST_FOR_EXCEPTION(
00461     mode != Teuchos::NO_TRANS, std::logic_error,
00462     "Ifpack2::Krylov::apply: mode != Teuchos::NO_TRANS has not been implemented.");
00463 
00464   Teuchos::Time timer ("apply");
00465   { // The body of code to time
00466     Teuchos::TimeMonitor timeMon (timer);
00467 
00468     // If X and Y are pointing to the same memory location,
00469     // we need to create an auxiliary vector, Xcopy
00470     RCP<const MV> Xcopy;
00471     if (X.getLocalMV ().getValues () == Y.getLocalMV ().getValues ()) {
00472       Xcopy = rcp (new MV (X, Teuchos::Copy));
00473     } else {
00474       Xcopy = rcpFromRef (X);
00475     }
00476 
00477     RCP<MV> Ycopy = rcpFromRef (Y);
00478     if (ZeroStartingSolution_) {
00479       Ycopy->putScalar (STS::zero ());
00480     }
00481 
00482     // Set left and right hand sides for Belos
00483     belosProblem_->setProblem (Ycopy, Xcopy);
00484     belosSolver_->solve (); // solve the linear system
00485   }
00486   ++NumApply_;
00487   ApplyTime_ += timer.totalElapsedTime ();
00488 }
00489 
00490 
00491 template <class MatrixType>
00492 std::string Krylov<MatrixType>::description () const
00493 {
00494   std::ostringstream os;
00495 
00496   // Output is a valid YAML dictionary in flow style.  If you don't
00497   // like everything on a single line, you should call describe()
00498   // instead.
00499   os << "\"Ifpack2::Krylov\": {";
00500   if (this->getObjectLabel () != "") {
00501     os << "Label: \"" << this->getObjectLabel () << "\", ";
00502   }
00503   os << "Initialized: " << (isInitialized () ? "true" : "false") << ", "
00504      << "Computed: " << (isComputed () ? "true" : "false") << ", ";
00505 
00506   if (A_.is_null ()) {
00507     os << "Matrix: null";
00508   }
00509   else {
00510     os << "Matrix: not null"
00511        << ", Global matrix dimensions: ["
00512        << A_->getGlobalNumRows () << ", " << A_->getGlobalNumCols () << "]";
00513   }
00514 
00515   os << "}";
00516   return os.str ();
00517 }
00518 
00519 
00520 template <class MatrixType>
00521 void Krylov<MatrixType>::
00522 describe (Teuchos::FancyOStream &out,
00523           const Teuchos::EVerbosityLevel verbLevel) const
00524 {
00525   using std::endl;
00526   using std::setw;
00527   using Teuchos::VERB_DEFAULT;
00528   using Teuchos::VERB_NONE;
00529   using Teuchos::VERB_LOW;
00530   using Teuchos::VERB_MEDIUM;
00531   using Teuchos::VERB_HIGH;
00532   using Teuchos::VERB_EXTREME;
00533 
00534   const Teuchos::EVerbosityLevel vl =
00535     (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
00536 
00537   if (vl != VERB_NONE) {
00538     // describe() always starts with a tab by convention.
00539     Teuchos::OSTab tab0 (out);
00540     out << "\"Ifpack2::Krylov\":";
00541 
00542     Teuchos::OSTab tab1 (out);
00543     if (this->getObjectLabel () != "") {
00544       out << "Label: " << this->getObjectLabel () << endl;
00545     }
00546     out << "Initialized: " << (isInitialized () ? "true" : "false") << endl
00547         << "Computed: " << (isComputed () ? "true" : "false") << endl
00548         << "Global number of rows: " << A_->getGlobalNumRows () << endl
00549         << "Global number of columns: " << A_->getGlobalNumCols () << endl
00550         << "Matrix:";
00551     if (A_.is_null ()) {
00552       out << " null" << endl;
00553     } else {
00554       A_->describe (out, vl);
00555     }
00556   }
00557 }
00558 
00559 } // namespace Ifpack2
00560 
00561 // FIXME (mfh 16 Sep 2014) We should really only use RowMatrix here!
00562 // There's no need to instantiate for CrsMatrix too.  All Ifpack2
00563 // preconditioners can and should do dynamic casts if they need a type
00564 // more specific than RowMatrix.
00565 //
00566 // In fact, Krylov really doesn't _need_ the RowMatrix methods; it
00567 // could very well just rely on the Operator interface.  initialize()
00568 // need only check whether the domain and range Maps have changed
00569 // (which would necessitate reinitializing the Krylov solver).
00570 
00571 #define IFPACK2_KRYLOV_INSTANT(S,LO,GO,N) \
00572   template class Ifpack2::Krylov< Tpetra::RowMatrix<S, LO, GO, N> >; \
00573   template class Ifpack2::Krylov< Tpetra::CrsMatrix<S, LO, GO, N> >;
00574 
00575 #endif /* IFPACK2_KRYLOV_DEF_HPP */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends