|
Ifpack2 Templated Preconditioning Package
Version 1.0
|
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
1.7.6.1