Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
Ifpack2_Details_Amesos2Wrapper_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_DETAILS_AMESOS2WRAPPER_DEF_HPP
00044 #define IFPACK2_DETAILS_AMESOS2WRAPPER_DEF_HPP
00045 
00046 #include <Teuchos_TimeMonitor.hpp>
00047 #include <Teuchos_TypeNameTraits.hpp>
00048 
00049 #include <Ifpack2_Heap.hpp>
00050 #include <Ifpack2_Condest.hpp>
00051 #include <Ifpack2_LocalFilter.hpp>
00052 
00053 #ifdef HAVE_IFPACK2_AMESOS2
00054 #include <Amesos2.hpp>
00055 // include <Ifpack2_Details_Amesos2Wrapper_decl.hpp>
00056 
00057 namespace Ifpack2 {
00058 namespace Details {
00059 
00060 template <class MatrixType>
00061 Amesos2Wrapper<MatrixType>::
00062 Amesos2Wrapper (const Teuchos::RCP<const row_matrix_type>& A) :
00063   A_(A),
00064   Condest_ (-STM::one ()),
00065   InitializeTime_ (0.0),
00066   ComputeTime_ (0.0),
00067   ApplyTime_ (0.0),
00068   NumInitialize_ (0),
00069   NumCompute_ (0),
00070   NumApply_ (0),
00071   IsInitialized_ (false),
00072   IsComputed_ (false),
00073   SolverName_ ("")
00074 {}
00075 
00076 template <class MatrixType>
00077 Amesos2Wrapper<MatrixType>::~Amesos2Wrapper()
00078 {}
00079 
00080 template <class MatrixType>
00081 void Amesos2Wrapper<MatrixType>::setParameters (const Teuchos::ParameterList& params)
00082 {
00083   using Teuchos::ParameterList;
00084   using Teuchos::RCP;
00085   using Teuchos::rcp;
00086 
00087   // FIXME (mfh 12 Sep 2014) Why does this code make a deep copy of
00088   // the input ParameterList?  Does Amesos2 want a deep copy?
00089 
00090   // Extract the list called "Amesos2" that contains the Amesos2
00091   // solver's options.
00092   RCP<ParameterList> theList;
00093   if (params.name () == "Amesos2") {
00094 
00095     theList = rcp (new ParameterList (params));
00096   } else if (params.isSublist ("Amesos2")) {
00097     // FIXME (mfh 12 Sep 2014) This code actually makes _two_ deep copies.
00098     ParameterList subpl = params.sublist ("Amesos2");
00099     theList = rcp (new ParameterList (subpl));
00100     theList->setName ("Amesos2"); //FIXME hack until Teuchos sublist name bug is fixed
00101     if (params.isParameter ("Amesos2 solver name")) {
00102       SolverName_ = params.get<std::string>("Amesos2 solver name");
00103     }
00104   } else {
00105     // Amesos2 silently ignores any list not called "Amesos2".  We'll
00106     // throw an exception.
00107     TEUCHOS_TEST_FOR_EXCEPTION(
00108       true, std::runtime_error, "The ParameterList passed to Amesos2 must be "
00109       "called \"Amesos2\".");
00110   }
00111 
00112   // If amesos2solver_ hasn't been allocated yet, cache the parameters and set them
00113   // once the concrete solver does exist.
00114   if (amesos2solver_ == Teuchos::null) {
00115     parameterList_ = theList;
00116     return;
00117   }
00118 
00119   amesos2solver_->setParameters(theList);
00120 }
00121 
00122 
00123 template <class MatrixType>
00124 Teuchos::RCP<const Teuchos::Comm<int> >
00125 Amesos2Wrapper<MatrixType>::getComm () const {
00126   TEUCHOS_TEST_FOR_EXCEPTION(
00127     A_.is_null (), std::runtime_error, "Ifpack2::Amesos2Wrapper::getComm: "
00128     "The matrix is null.  Please call setMatrix() with a nonnull input "
00129     "before calling this method.");
00130   return A_->getComm ();
00131 }
00132 
00133 
00134 template <class MatrixType>
00135 Teuchos::RCP<const typename Amesos2Wrapper<MatrixType>::row_matrix_type>
00136 Amesos2Wrapper<MatrixType>::getMatrix () const {
00137   return A_;
00138 }
00139 
00140 
00141 template <class MatrixType>
00142 Teuchos::RCP<const typename Amesos2Wrapper<MatrixType>::map_type>
00143 Amesos2Wrapper<MatrixType>::getDomainMap () const
00144 {
00145   TEUCHOS_TEST_FOR_EXCEPTION(
00146     A_.is_null (), std::runtime_error, "Ifpack2::Amesos2Wrapper::getDomainMap: "
00147     "The matrix is null.  Please call setMatrix() with a nonnull input "
00148     "before calling this method.");
00149   return A_->getDomainMap ();
00150 }
00151 
00152 
00153 template <class MatrixType>
00154 Teuchos::RCP<const typename Amesos2Wrapper<MatrixType>::map_type>
00155 Amesos2Wrapper<MatrixType>::getRangeMap () const
00156 {
00157   TEUCHOS_TEST_FOR_EXCEPTION(
00158     A_.is_null (), std::runtime_error, "Ifpack2::Amesos2Wrapper::getRangeMap: "
00159     "The matrix is null.  Please call setMatrix() with a nonnull input "
00160     "before calling this method.");
00161   return A_->getRangeMap ();
00162 }
00163 
00164 
00165 template <class MatrixType>
00166 bool Amesos2Wrapper<MatrixType>::hasTransposeApply () const {
00167   return true;
00168 }
00169 
00170 
00171 template <class MatrixType>
00172 int Amesos2Wrapper<MatrixType>::getNumInitialize () const {
00173   return NumInitialize_;
00174 }
00175 
00176 
00177 template <class MatrixType>
00178 int Amesos2Wrapper<MatrixType>::getNumCompute () const {
00179   return NumCompute_;
00180 }
00181 
00182 
00183 template <class MatrixType>
00184 int Amesos2Wrapper<MatrixType>::getNumApply () const {
00185   return NumApply_;
00186 }
00187 
00188 
00189 template <class MatrixType>
00190 double Amesos2Wrapper<MatrixType>::getInitializeTime () const {
00191   return InitializeTime_;
00192 }
00193 
00194 
00195 template<class MatrixType>
00196 double Amesos2Wrapper<MatrixType>::getComputeTime () const {
00197   return ComputeTime_;
00198 }
00199 
00200 
00201 template<class MatrixType>
00202 double Amesos2Wrapper<MatrixType>::getApplyTime () const {
00203   return ApplyTime_;
00204 }
00205 
00206 template<class MatrixType>
00207 typename Amesos2Wrapper<MatrixType>::magnitude_type
00208 Amesos2Wrapper<MatrixType>::
00209 computeCondEst (CondestType CT,
00210                 local_ordinal_type MaxIters,
00211                 magnitude_type Tol,
00212                 const Teuchos::Ptr<const row_matrix_type>& matrix)
00213 {
00214   if (! isComputed ()) {
00215     return -STM::one ();
00216   }
00217   // NOTE: this is computing the *local* condest
00218   if (Condest_ == -STM::one ()) {
00219     Condest_ = Ifpack2::Condest (*this, CT, MaxIters, Tol, matrix);
00220   }
00221   return Condest_;
00222 }
00223 
00224 
00225 template<class MatrixType>
00226 void Amesos2Wrapper<MatrixType>::setMatrix (const Teuchos::RCP<const row_matrix_type>& A)
00227 {
00228   // It's legal for A to be null; in that case, you may not call
00229   // initialize() until calling setMatrix() with a nonnull input.
00230   // Regardless, setting the matrix invalidates any previous
00231   // factorization.
00232   IsInitialized_ = false;
00233   IsComputed_ = false;
00234   Condest_ = -STM::one ();
00235 
00236   if (A.is_null ()) {
00237     A_ = Teuchos::null;
00238   }
00239   else {
00240     A_ = A;
00241   }
00242 
00243   // FIXME (mfh 10 Dec 2013) Currently, initialize() recreates
00244   // amesos2solver_ unconditionally, so this code won't have any
00245   // effect.  Once we fix initialize() so that it keeps
00246   // amesos2solver_, the code below will be effective.
00247   //if (! amesos2solver_.is_null ()) {
00248   //  amesos2solver_->setA (A_);
00249   //}
00250   // FIXME JJH 2014-July18 A_ might not be a locally filtered CRS matrix, which
00251   // means we have to do that dance all over again before calling amesos2solver_->setA ....
00252 }
00253 
00254 template<class MatrixType>
00255 Teuchos::RCP<const typename Amesos2Wrapper<MatrixType>::row_matrix_type>
00256 Amesos2Wrapper<MatrixType>::makeLocalFilter (const Teuchos::RCP<const row_matrix_type>& A)
00257 {
00258   using Teuchos::RCP;
00259   using Teuchos::rcp;
00260   using Teuchos::rcp_dynamic_cast;
00261   using Teuchos::rcp_implicit_cast;
00262 
00263   // If A_'s communicator only has one process, or if its column and
00264   // row Maps are the same, then it is already local, so use it
00265   // directly.
00266   if (A->getRowMap ()->getComm ()->getSize () == 1 ||
00267       A->getRowMap ()->isSameAs (* (A->getColMap ()))) {
00268     return A;
00269   }
00270 
00271   // If A_ is already a LocalFilter, then use it directly.  This
00272   // should be the case if RILUK is being used through
00273   // AdditiveSchwarz, for example.  There are (unfortunately) two
00274   // kinds of LocalFilter, depending on the template parameter, so we
00275   // have to test for both.
00276   RCP<const LocalFilter<row_matrix_type> > A_lf_r =
00277     rcp_dynamic_cast<const LocalFilter<row_matrix_type> > (A);
00278   if (! A_lf_r.is_null ()) {
00279     return rcp_implicit_cast<const row_matrix_type> (A_lf_r);
00280   }
00281   RCP<const LocalFilter<crs_matrix_type> > A_lf_c =
00282     rcp_dynamic_cast<const LocalFilter<crs_matrix_type> > (A);
00283   if (! A_lf_c.is_null ()) {
00284     return rcp_implicit_cast<const row_matrix_type> (A_lf_c);
00285   }
00286 
00287   // A_'s communicator has more than one process, its row Map and
00288   // its column Map differ, and A_ is not a LocalFilter.  Thus, we
00289   // have to wrap it in a LocalFilter.
00290   return rcp (new LocalFilter<row_matrix_type> (A));
00291 }
00292 
00293 
00294 template<class MatrixType>
00295 void Amesos2Wrapper<MatrixType>::initialize ()
00296 {
00297   using Teuchos::RCP;
00298   using Teuchos::rcp;
00299   using Teuchos::rcp_const_cast;
00300   using Teuchos::rcp_dynamic_cast;
00301   using Teuchos::Time;
00302   using Teuchos::TimeMonitor;
00303   typedef Tpetra::Import<local_ordinal_type,
00304     global_ordinal_type, node_type> import_type;
00305 
00306   const std::string timerName ("Ifpack2::Amesos2Wrapper::initialize");
00307   RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
00308   if (timer.is_null ()) {
00309     timer = TimeMonitor::getNewCounter (timerName);
00310   }
00311 
00312   { // Start timing here.
00313     TimeMonitor timeMon (*timer);
00314 
00315     // Check that the matrix is nonnull.
00316     TEUCHOS_TEST_FOR_EXCEPTION(
00317       A_.is_null (), std::runtime_error, "Ifpack2::Amesos2Wrapper::initialize: "
00318       "The matrix to precondition is null.  Please call setMatrix() with a "
00319       "nonnull input before calling this method.");
00320 
00321     // Clear any previous computations.
00322     IsInitialized_ = false;
00323     IsComputed_ = false;
00324     Condest_ = -STM::one ();
00325 
00326     RCP<const row_matrix_type> A_local = makeLocalFilter (A_);
00327     TEUCHOS_TEST_FOR_EXCEPTION(
00328       A_local.is_null (), std::logic_error, "Ifpack2::AmesosWrapper::initialize: "
00329       "makeLocalFilter returned null; it failed to compute A_local.  "
00330       "Please report this bug to the Ifpack2 developers.");
00331 
00332     {
00333       // The matrix that Amesos2 will build the preconditioner on must be a Tpetra::Crs matrix.
00334       // If A_local isn't, then we build one.
00335       RCP<const crs_matrix_type> A_local_crs =
00336         rcp_dynamic_cast<const crs_matrix_type> (A_local);
00337 
00338       if (A_local_crs.is_null ()) {
00339         // FIXME (mfh 24 Jan 2014) It would be smarter to count up the
00340         // number of elements in each row of A_local, so that we can
00341         // create A_local_crs_nc using static profile.  The code below is
00342         // correct but potentially slow.
00343         RCP<crs_matrix_type> A_local_crs_nc =
00344           rcp (new crs_matrix_type (A_local->getRowMap (),
00345                                     A_local->getColMap (), 0));
00346         // FIXME (mfh 24 Jan 2014) This Import approach will only work
00347         // if A_ has a one-to-one row Map.  This is generally the case
00348         // with matrices given to Ifpack2.
00349         //
00350         // Source and destination Maps are the same in this case.
00351         // That way, the Import just implements a copy.
00352         import_type import (A_local->getRowMap (), A_local->getRowMap ());
00353         A_local_crs_nc->doImport (*A_local, import, Tpetra::REPLACE);
00354         A_local_crs_nc->fillComplete (A_local->getDomainMap (), A_local->getRangeMap ());
00355         A_local_crs = rcp_const_cast<const crs_matrix_type> (A_local_crs_nc);
00356       }
00357       A_local_crs_ = A_local_crs;
00358     }
00359 
00360     // (9 May 2014) JJH Ifpack2 shouldn't be checking the availability direct solvers.
00361     // It's up to Amesos2 to test for this and throw an exception
00362     // (which it does in Amesos2::Factory::create).
00363 
00364     if (SolverName_ == "") {
00365       if (Amesos2::query("klu"))
00366         SolverName_ = "klu";
00367       else if (Amesos2::query("superlu"))
00368         SolverName_ = "superlu";
00369       else if (Amesos2::query("superludist"))
00370         SolverName_ = "superludist";
00371       else if (Amesos2::query("cholmod"))
00372         SolverName_ = "cholmod";
00373       else {
00374         // FIXME (9 May 2014) JJH Amesos2 does not yet expose KLU2,
00375         // its internal direct solver.  This means there's no fallback
00376         // option, thus we throw an exception here.
00377         TEUCHOS_TEST_FOR_EXCEPTION(
00378           true, std::invalid_argument, "Amesos2 has not been configured with "
00379           "any direct solver support.");
00380       }
00381     }
00382 
00383     // FIXME (10 Dec 2013) It shouldn't be necessary to recreate the
00384     // solver each time, since Amesos2::Solver has a setA() method.
00385     // See the implementation of setMatrix().
00386 
00387     amesos2solver_ = Amesos2::create<crs_matrix_type, MV> (SolverName_, A_local_crs_);
00388     // If parameters have been already been cached via setParameters, set them now.
00389     if (parameterList_ != Teuchos::null) {
00390       setParameters(*parameterList_);
00391       parameterList_ = Teuchos::null;
00392     }
00393     amesos2solver_->preOrdering ();
00394 
00395     // The symbolic factorization properly belongs to initialize(),
00396     // since initialize() is concerned with the matrix's structure
00397     // (and compute() with the matrix's values).
00398     amesos2solver_->symbolicFactorization ();
00399   } // Stop timing here.
00400 
00401   IsInitialized_ = true;
00402   ++NumInitialize_;
00403 
00404   // timer->totalElapsedTime() returns the total time over all timer
00405   // calls.  Thus, we use = instead of +=.
00406   InitializeTime_ = timer->totalElapsedTime ();
00407 }
00408 
00409 template<class MatrixType>
00410 void Amesos2Wrapper<MatrixType>::compute ()
00411 {
00412   using Teuchos::RCP;
00413   using Teuchos::Time;
00414   using Teuchos::TimeMonitor;
00415 
00416   // Don't count initialization in the compute() time.
00417   if (! isInitialized ()) {
00418     initialize ();
00419   }
00420 
00421   const std::string timerName ("Ifpack2::AdditiveSchwarz::compute");
00422   RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
00423   if (timer.is_null ()) {
00424     timer = TimeMonitor::getNewCounter (timerName);
00425   }
00426 
00427   { // Start timing here.
00428     TimeMonitor timeMon (*timer);
00429     amesos2solver_->numericFactorization ();
00430   } // Stop timing here.
00431 
00432   IsComputed_ = true;
00433   ++NumCompute_;
00434 
00435   // timer->totalElapsedTime() returns the total time over all timer
00436   // calls.  Thus, we use = instead of +=.
00437   ComputeTime_ = timer->totalElapsedTime ();
00438 }
00439 
00440 
00441 template <class MatrixType>
00442 void Amesos2Wrapper<MatrixType>::
00443 apply (const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
00444        Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
00445        Teuchos::ETransp mode,
00446        scalar_type alpha,
00447        scalar_type beta) const
00448 {
00449   using Teuchos::ArrayView;
00450   using Teuchos::RCP;
00451   using Teuchos::rcp;
00452   using Teuchos::rcpFromRef;
00453   using Teuchos::Time;
00454   using Teuchos::TimeMonitor;
00455 
00456   // X = RHS
00457   // Y = solution
00458 
00459   const std::string timerName ("Ifpack2::Amesos2Wrapper::apply");
00460   RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
00461   if (timer.is_null ()) {
00462     timer = TimeMonitor::getNewCounter (timerName);
00463   }
00464 
00465   { // Start timing here.
00466     TimeMonitor timeMon (*timer);
00467 
00468     TEUCHOS_TEST_FOR_EXCEPTION(
00469       ! isComputed (), std::runtime_error,
00470       "Ifpack2::Amesos2Wrapper::apply: You must call compute() to compute the "
00471       "incomplete factorization, before calling apply().");
00472 
00473     TEUCHOS_TEST_FOR_EXCEPTION(
00474       X.getNumVectors() != Y.getNumVectors(), std::runtime_error,
00475       "Ifpack2::Amesos2Wrapper::apply: X and Y must have the same number of columns.  "
00476       "X has " << X.getNumVectors () << " columns, but Y has "
00477       << Y.getNumVectors () << " columns.");
00478 
00479     TEUCHOS_TEST_FOR_EXCEPTION(
00480       mode != Teuchos::NO_TRANS, std::logic_error,
00481       "Ifpack2::Amesos2Wrapper::apply: Solving with the transpose (mode == "
00482       "Teuchos::TRANS) or conjugate transpose (Teuchos::CONJ_TRANS) is not "
00483       "implemented.");
00484 
00485     // If alpha != 1 or beta != 0, create a temporary multivector
00486     // Y_temp to hold the contents of alpha*M^{-1}*X.  Otherwise,
00487     // alias Y_temp to Y.
00488     RCP<MV> Y_temp = (alpha != STS::one () || beta != STS::zero ()) ?
00489       rcp (new MV (Y.getMap (), Y.getNumVectors ())) :
00490       rcpFromRef (Y);
00491 
00492     // If X and Y are pointing to the same memory location, create an
00493     // auxiliary vector, X_temp, so that we don't clobber the input
00494     // when computing the output.  Otherwise, alias X_temp to X.
00495     RCP<const MV> X_temp;
00496     if (X.getLocalMV ().getValues () == Y.getLocalMV ().getValues ()) {
00497       X_temp = rcp (new MV (X, Teuchos::Copy));
00498     } else {
00499       X_temp = rcpFromRef (X);
00500     }
00501 
00502     // Set up "local" views of X and Y.
00503     RCP<const MV> X_local;
00504     RCP<MV> Y_local;
00505     const bool multipleProcs = (A_->getRowMap ()->getComm ()->getSize () >= 1);
00506     if (multipleProcs) {
00507       // Interpret X and Y as "local" multivectors, that is, in the
00508       // local filter's domain resp. range Maps.  "Interpret" means that
00509       // we create views with different Maps; we don't have to copy.
00510       X_local = X_temp->offsetView (A_local_crs_->getDomainMap (), 0);
00511       Y_local = Y_temp->offsetViewNonConst (A_local_crs_->getRangeMap (), 0);
00512     }
00513     else { // only one process in A_'s communicator
00514       // X and Y are already "local"; no need to set up local views.
00515       X_local = X_temp;
00516       Y_local = Y_temp;
00517     }
00518 
00519     // Use the precomputed factorization to solve.
00520     amesos2solver_->setX (Y_local);
00521     amesos2solver_->setB (X_local);
00522     amesos2solver_->solve ();
00523 
00524     if (alpha != STS::one () || beta != STS::zero ()) {
00525       Y.update (alpha, *Y_temp, beta);
00526     }
00527   } // Stop timing here.
00528 
00529   ++NumApply_;
00530 
00531   // timer->totalElapsedTime() returns the total time over all timer
00532   // calls.  Thus, we use = instead of +=.
00533   ApplyTime_ = timer->totalElapsedTime ();
00534 }
00535 
00536 
00537 template <class MatrixType>
00538 std::string Amesos2Wrapper<MatrixType>::description () const {
00539   using Teuchos::TypeNameTraits;
00540   std::ostringstream os;
00541 
00542   // Output is a valid YAML dictionary in flow style.  If you don't
00543   // like everything on a single line, you should call describe()
00544   // instead.
00545   os << "\"Ifpack2::Amesos2Wrapper\": {";
00546   if (this->getObjectLabel () != "") {
00547     os << "Label: \"" << this->getObjectLabel () << "\", ";
00548   }
00549   os << "Initialized: " << (isInitialized () ? "true" : "false")
00550      << ", Computed: " << (isComputed () ? "true" : "false");
00551 
00552   if (A_local_crs_.is_null ()) {
00553     os << ", Matrix: null";
00554   }
00555   else {
00556     os << ", Global matrix dimensions: ["
00557        << A_local_crs_->getGlobalNumRows () << ", " << A_local_crs_->getGlobalNumCols () << "]";
00558   }
00559   //describe the Amesos2 method being called
00560   os << ", {";
00561   os << amesos2solver_->description();
00562   os << "}";
00563 
00564   os << "}";
00565   return os.str ();
00566 }
00567 
00568 
00569 template <class MatrixType>
00570 void
00571 Amesos2Wrapper<MatrixType>::
00572 describe (Teuchos::FancyOStream& out,
00573           const Teuchos::EVerbosityLevel verbLevel) const
00574 {
00575   using Teuchos::Comm;
00576   using Teuchos::OSTab;
00577   using Teuchos::RCP;
00578   using Teuchos::TypeNameTraits;
00579   using std::endl;
00580 
00581   const Teuchos::EVerbosityLevel vl = (verbLevel == Teuchos::VERB_DEFAULT) ?
00582     Teuchos::VERB_LOW : verbLevel;
00583 
00584   // describe() starts, by convention, with a tab before it prints anything.
00585   OSTab tab0 (out);
00586   if (vl > Teuchos::VERB_NONE) {
00587     out << "\"Ifpack2::Amesos2Wrapper\":" << endl;
00588     OSTab tab1 (out);
00589     out << "MatrixType: \"" << TypeNameTraits<MatrixType>::name ()
00590         << "\"" << endl;
00591 
00592     if (this->getObjectLabel () != "") {
00593       out << "Label: \"" << this->getObjectLabel () << "\"" << endl;
00594     }
00595 
00596     out << "Initialized: " << (isInitialized () ? "true" : "false") << endl;
00597     out << "Computed: " << (isComputed () ? "true" : "false") << endl;
00598     out << "Number of initialize calls: " << getNumInitialize () << endl;
00599     out << "Number of compute calls: " << getNumCompute () << endl;
00600     out << "Number of apply calls: " << getNumApply () << endl;
00601     out << "Total time in seconds for initialize: " << getInitializeTime () << endl;
00602     out << "Total time in seconds for compute: " << getComputeTime () << endl;
00603     out << "Total time in seconds for apply: " << getApplyTime () << endl;
00604 
00605     if (vl > Teuchos::VERB_LOW) {
00606       out << "Matrix:" << endl;
00607       A_local_crs_->describe (out, vl);
00608     }
00609   }
00610 }
00611 
00612 } // namespace Details
00613 } // namespace Ifpack2
00614 
00615 // FIXME (mfh 16 Sep 2014) We should really only use RowMatrix here!
00616 // There's no need to instantiate for CrsMatrix too.  All Ifpack2
00617 // preconditioners can and should do dynamic casts if they need a type
00618 // more specific than RowMatrix.
00619 
00620 #define IFPACK2_DETAILS_AMESOS2WRAPPER_INSTANT(S,LO,GO,N) \
00621   template class Ifpack2::Details::Amesos2Wrapper< Tpetra::RowMatrix<S, LO, GO, N> >; \
00622   template class Ifpack2::Details::Amesos2Wrapper< Tpetra::CrsMatrix<S, LO, GO, N> >;
00623 
00624 #endif // HAVE_IFPACK2_AMESOS2
00625 #endif // IFPACK2_DETAILS_AMESOS2WRAPPER_DEF_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends