|
Ifpack2 Templated Preconditioning Package
Version 1.0
|
00001 /*@HEADER 00002 // *********************************************************************** 00003 // 00004 // Ifpack2: Templated 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_TRIDISOLVER_DEF_HPP 00044 #define IFPACK2_DETAILS_TRIDISOLVER_DEF_HPP 00045 00046 #include "Ifpack2_Condest.hpp" 00047 #include "Ifpack2_LocalFilter.hpp" 00048 #include "Teuchos_LAPACK.hpp" 00049 00050 #ifdef HAVE_MPI 00051 # include <mpi.h> 00052 # include "Teuchos_DefaultMpiComm.hpp" 00053 #else 00054 # include "Teuchos_DefaultSerialComm.hpp" 00055 #endif // HAVE_MPI 00056 00057 00058 namespace Ifpack2 { 00059 namespace Details { 00060 00062 // Non-stub (full) implementation 00064 00065 template<class MatrixType> 00066 TriDiSolver<MatrixType, false>:: 00067 TriDiSolver (const Teuchos::RCP<const row_matrix_type>& A) : 00068 A_ (A), 00069 initializeTime_ (0.0), 00070 computeTime_ (0.0), 00071 applyTime_ (0.0), 00072 numInitialize_ (0), 00073 numCompute_ (0), 00074 numApply_ (0), 00075 isInitialized_ (false), 00076 isComputed_ (false) 00077 {} 00078 00079 00080 template<class MatrixType> 00081 Teuchos::RCP<const typename TriDiSolver<MatrixType, false>::map_type> 00082 TriDiSolver<MatrixType, false>::getDomainMap () const { 00083 TEUCHOS_TEST_FOR_EXCEPTION( 00084 A_.is_null (), std::runtime_error, "Ifpack2::Details::TriDiSolver::" 00085 "getDomainMap: The input matrix A is null. Please call setMatrix() with a " 00086 "nonnull input matrix before calling this method."); 00087 // For an input matrix A, TriDiSolver solves Ax=b for x. 00088 // Thus, its Maps are reversed from those of the input matrix. 00089 return A_->getRangeMap (); 00090 } 00091 00092 00093 template<class MatrixType> 00094 Teuchos::RCP<const typename TriDiSolver<MatrixType, false>::map_type> 00095 TriDiSolver<MatrixType, false>::getRangeMap () const { 00096 TEUCHOS_TEST_FOR_EXCEPTION( 00097 A_.is_null (), std::runtime_error, "Ifpack2::Details::TriDiSolver::" 00098 "getRangeMap: The input matrix A is null. Please call setMatrix() with a " 00099 "nonnull input matrix before calling this method."); 00100 // For an input matrix A, TriDiSolver solves Ax=b for x. 00101 // Thus, its Maps are reversed from those of the input matrix. 00102 return A_->getDomainMap (); 00103 } 00104 00105 00106 template<class MatrixType> 00107 void 00108 TriDiSolver<MatrixType, false>:: 00109 setParameters (const Teuchos::ParameterList& params) { 00110 (void) params; // this preconditioner doesn't currently take any parameters 00111 } 00112 00113 00114 template<class MatrixType> 00115 bool 00116 TriDiSolver<MatrixType, false>::isInitialized () const { 00117 return isInitialized_; 00118 } 00119 00120 00121 template<class MatrixType> 00122 bool 00123 TriDiSolver<MatrixType, false>::isComputed () const { 00124 return isComputed_; 00125 } 00126 00127 00128 template<class MatrixType> 00129 int 00130 TriDiSolver<MatrixType, false>::getNumInitialize () const { 00131 return numInitialize_; 00132 } 00133 00134 00135 template<class MatrixType> 00136 int 00137 TriDiSolver<MatrixType, false>::getNumCompute () const { 00138 return numCompute_; 00139 } 00140 00141 00142 template<class MatrixType> 00143 int 00144 TriDiSolver<MatrixType, false>::getNumApply () const { 00145 return numApply_; 00146 } 00147 00148 00149 template<class MatrixType> 00150 double 00151 TriDiSolver<MatrixType, false>::getInitializeTime () const { 00152 return initializeTime_; 00153 } 00154 00155 00156 template<class MatrixType> 00157 double 00158 TriDiSolver<MatrixType, false>::getComputeTime () const { 00159 return computeTime_; 00160 } 00161 00162 00163 template<class MatrixType> 00164 double 00165 TriDiSolver<MatrixType, false>::getApplyTime () const { 00166 return applyTime_; 00167 } 00168 00169 00170 template<class MatrixType> 00171 typename TriDiSolver<MatrixType, false>::magnitude_type 00172 TriDiSolver<MatrixType, false>:: 00173 computeCondEst (CondestType type, 00174 local_ordinal_type maxIters, 00175 magnitude_type tol, 00176 const Teuchos::Ptr<const row_matrix_type>& matrix) 00177 { 00178 return Ifpack2::Condest (*this, type, maxIters, tol, matrix); 00179 } 00180 00181 00182 template<class MatrixType> 00183 typename TriDiSolver<MatrixType, false>::magnitude_type 00184 TriDiSolver<MatrixType, false>::getCondEst () const { 00185 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00186 } 00187 00188 00189 template<class MatrixType> 00190 Teuchos::RCP<const typename TriDiSolver<MatrixType, false>::row_matrix_type> 00191 TriDiSolver<MatrixType, false>::getMatrix () const { 00192 return A_; 00193 } 00194 00195 00196 template<class MatrixType> 00197 void TriDiSolver<MatrixType, false>:: 00198 reset () 00199 { 00200 isInitialized_ = false; 00201 isComputed_ = false; 00202 A_local_ = Teuchos::null; 00203 A_local_tridi_.reshape (0); 00204 ipiv_.resize (0); 00205 } 00206 00207 00208 template<class MatrixType> 00209 void TriDiSolver<MatrixType, false>:: 00210 setMatrix (const Teuchos::RCP<const row_matrix_type>& A) 00211 { 00212 // It's legitimate to call setMatrix() with a null input. This has 00213 // the effect of resetting the preconditioner's internal state. 00214 if (! A_.is_null ()) { 00215 const global_size_t numRows = A->getRangeMap ()->getGlobalNumElements (); 00216 const global_size_t numCols = A->getDomainMap ()->getGlobalNumElements (); 00217 TEUCHOS_TEST_FOR_EXCEPTION( 00218 numRows != numCols, std::invalid_argument, "Ifpack2::Details::TriDiSolver::" 00219 "setMatrix: Input matrix must be (globally) square. " 00220 "The matrix you provided is " << numRows << " by " << numCols << "."); 00221 } 00222 // Clear any previously computed objects. 00223 reset (); 00224 00225 // Now that we've cleared the state, we can keep the matrix. 00226 A_ = A; 00227 } 00228 00229 00230 template<class MatrixType> 00231 void TriDiSolver<MatrixType, false>::initialize () 00232 { 00233 using Teuchos::Comm; 00234 using Teuchos::null; 00235 using Teuchos::RCP; 00236 using Teuchos::rcp; 00237 using Teuchos::Time; 00238 using Teuchos::TimeMonitor; 00239 const std::string timerName ("Ifpack2::Details::TriDiSolver::initialize"); 00240 00241 RCP<Time> timer = TimeMonitor::lookupCounter (timerName); 00242 if (timer.is_null ()) { 00243 timer = TimeMonitor::getNewCounter (timerName); 00244 } 00245 00246 { // Begin timing here. 00247 Teuchos::TimeMonitor timeMon (*timer); 00248 00249 TEUCHOS_TEST_FOR_EXCEPTION( 00250 A_.is_null (), std::runtime_error, "Ifpack2::Details::TriDiSolver::" 00251 "initialize: The input matrix A is null. Please call setMatrix() " 00252 "with a nonnull input before calling this method."); 00253 00254 TEUCHOS_TEST_FOR_EXCEPTION( 00255 ! A_->hasColMap (), std::invalid_argument, "Ifpack2::Details::TriDiSolver: " 00256 "The constructor's input matrix must have a column Map, " 00257 "so that it has local indices."); 00258 00259 // Clear any previously computed objects. 00260 reset (); 00261 00262 // Make the local filter of the input matrix A. 00263 if (A_->getComm ()->getSize () > 1) { 00264 A_local_ = rcp (new LocalFilter<MatrixType> (A_)); 00265 } else { 00266 A_local_ = A_; 00267 } 00268 00269 TEUCHOS_TEST_FOR_EXCEPTION( 00270 A_local_.is_null (), std::logic_error, "Ifpack2::Details::TriDiSolver::" 00271 "initialize: A_local_ is null after it was supposed to have been " 00272 "initialized. Please report this bug to the Ifpack2 developers."); 00273 00274 // Allocate the TriDi local matrix and the pivot array. 00275 const size_t numRows = A_local_->getNodeNumRows (); 00276 const size_t numCols = A_local_->getNodeNumCols (); 00277 TEUCHOS_TEST_FOR_EXCEPTION( 00278 numRows != numCols, std::logic_error, "Ifpack2::Details::TriDiSolver::" 00279 "initialize: Local filter matrix is not square. This should never happen. " 00280 "Please report this bug to the Ifpack2 developers."); 00281 A_local_tridi_.reshape (numRows); 00282 ipiv_.resize (numRows); 00283 std::fill (ipiv_.begin (), ipiv_.end (), 0); 00284 00285 isInitialized_ = true; 00286 ++numInitialize_; 00287 } 00288 00289 // timer->totalElapsedTime() returns the total time over all timer 00290 // calls. Thus, we use = instead of +=. 00291 initializeTime_ = timer->totalElapsedTime (); 00292 } 00293 00294 00295 template<class MatrixType> 00296 TriDiSolver<MatrixType, false>::~TriDiSolver() 00297 {} 00298 00299 00300 template<class MatrixType> 00301 void TriDiSolver<MatrixType, false>::compute () 00302 { 00303 using Teuchos::RCP; 00304 const std::string timerName ("Ifpack2::Details::TriDiSolver::compute"); 00305 00306 RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName); 00307 if (timer.is_null ()) { 00308 timer = Teuchos::TimeMonitor::getNewCounter (timerName); 00309 } 00310 00311 // Begin timing here. 00312 { 00313 Teuchos::TimeMonitor timeMon (*timer); 00314 TEUCHOS_TEST_FOR_EXCEPTION( 00315 A_.is_null (), std::runtime_error, "Ifpack2::Details::TriDiSolver::" 00316 "compute: The input matrix A is null. Please call setMatrix() with a " 00317 "nonnull input, then call initialize(), before calling this method."); 00318 00319 TEUCHOS_TEST_FOR_EXCEPTION( 00320 A_local_.is_null (), std::logic_error, "Ifpack2::Details::TriDiSolver::" 00321 "compute: A_local_ is null. Please report this bug to the Ifpack2 " 00322 "developers."); 00323 00324 isComputed_ = false; 00325 if (! this->isInitialized ()) { 00326 this->initialize (); 00327 } 00328 extract (A_local_tridi_, *A_local_); // extract the tridi local matrix 00329 00330 factor (A_local_tridi_, ipiv_ ()); // factor the tridi local matrix 00331 00332 isComputed_ = true; 00333 ++numCompute_; 00334 } 00335 // timer->totalElapsedTime() returns the total time over all timer 00336 // calls. Thus, we use = instead of +=. 00337 computeTime_ = timer->totalElapsedTime (); 00338 } 00339 00340 template<class MatrixType> 00341 void TriDiSolver<MatrixType, false>::factor (Teuchos::SerialTriDiMatrix<int, scalar_type>& A, 00342 const Teuchos::ArrayView<int>& ipiv) 00343 { 00344 // Fill the LU permutation array with zeros. 00345 std::fill (ipiv.begin (), ipiv.end (), 0); 00346 00347 Teuchos::LAPACK<int, scalar_type> lapack; 00348 int INFO = 0; 00349 lapack.GTTRF (A.numRowsCols (), 00350 A.DL(), 00351 A.D(), 00352 A.DU(), 00353 A.DU2(), 00354 ipiv.getRawPtr (), &INFO); 00355 // INFO < 0 is a bug. 00356 TEUCHOS_TEST_FOR_EXCEPTION( 00357 INFO < 0, std::logic_error, "Ifpack2::Details::TriDiSolver::factor: " 00358 "LAPACK's _GETRF (LU factorization with partial pivoting) was called " 00359 "incorrectly. INFO = " << INFO << " < 0. " 00360 "Please report this bug to the Ifpack2 developers."); 00361 // INFO > 0 means the matrix is singular. This is probably an issue 00362 // either with the choice of rows the rows we extracted, or with the 00363 // input matrix itself. 00364 TEUCHOS_TEST_FOR_EXCEPTION( 00365 INFO > 0, std::runtime_error, "Ifpack2::Details::TriDiSolver::factor: " 00366 "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the " 00367 "computed U factor is exactly singular. U(" << INFO << "," << INFO << ") " 00368 "(one-based index i) is exactly zero. This probably means that the input " 00369 "matrix has a singular diagonal block."); 00370 } 00371 00372 00373 template<class MatrixType> 00374 void TriDiSolver<MatrixType, false>:: 00375 applyImpl (const MV& X, 00376 MV& Y, 00377 const Teuchos::ETransp mode, 00378 const scalar_type alpha, 00379 const scalar_type beta) const 00380 { 00381 using Teuchos::ArrayRCP; 00382 using Teuchos::RCP; 00383 using Teuchos::rcp; 00384 using Teuchos::rcpFromRef; 00385 using Teuchos::CONJ_TRANS; 00386 using Teuchos::TRANS; 00387 00388 const int numVecs = static_cast<int> (X.getNumVectors ()); 00389 if (alpha == STS::zero ()) { // don't need to solve the linear system 00390 if (beta == STS::zero ()) { 00391 // Use BLAS AXPY semantics for beta == 0: overwrite, clobbering 00392 // any Inf or NaN values in Y (rather than multiplying them by 00393 // zero, resulting in NaN values). 00394 Y.putScalar (STS::zero ()); 00395 } 00396 else { // beta != 0 00397 Y.scale (STS::zero ()); 00398 } 00399 } 00400 else { // alpha != 0; must solve the linear system 00401 Teuchos::LAPACK<int, scalar_type> lapack; 00402 // If beta is nonzero, Y is not constant stride, or alpha != 1, we 00403 // have to use a temporary output multivector Y_tmp. It gets a 00404 // copy of alpha*X, since GETRS overwrites its (multi)vector input 00405 // with its output. 00406 RCP<MV> Y_tmp; 00407 if (beta == STS::zero () && Y.isConstantStride () && alpha == STS::one ()) { 00408 deep_copy(Y, X); 00409 Y_tmp = rcpFromRef (Y); 00410 } 00411 else { 00412 Y_tmp = rcp (new MV (createCopy(X))); // constructor copies X 00413 if (alpha != STS::one ()) { 00414 Y_tmp->scale (alpha); 00415 } 00416 } 00417 const int Y_stride = static_cast<int> (Y_tmp->getStride ()); 00418 ArrayRCP<scalar_type> Y_view = Y_tmp->get1dViewNonConst (); 00419 scalar_type* const Y_ptr = Y_view.getRawPtr (); 00420 int INFO = 0; 00421 const char trans = 00422 (mode == CONJ_TRANS ? 'C' : (mode == TRANS ? 'T' : 'N')); 00423 lapack.GTTRS (trans, A_local_tridi_.numRowsCols(), numVecs, 00424 A_local_tridi_.DL(), 00425 A_local_tridi_.D(), 00426 A_local_tridi_.DU(), 00427 A_local_tridi_.DU2(), 00428 ipiv_.getRawPtr (), Y_ptr, Y_stride, &INFO); 00429 TEUCHOS_TEST_FOR_EXCEPTION( 00430 INFO != 0, std::runtime_error, "Ifpack2::Details::TriDiSolver::" 00431 "applyImpl: LAPACK's _GTTRS (solve using LU factorization with " 00432 "partial pivoting) failed with INFO = " << INFO << " != 0."); 00433 00434 if (beta != STS::zero ()) { 00435 Y.update (alpha, *Y_tmp, beta); 00436 } 00437 else if (! Y.isConstantStride ()) { 00438 deep_copy(Y, *Y_tmp); 00439 } 00440 } 00441 } 00442 00443 00444 template<class MatrixType> 00445 void TriDiSolver<MatrixType, false>:: 00446 apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X, 00447 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y, 00448 Teuchos::ETransp mode, 00449 scalar_type alpha, 00450 scalar_type beta) const 00451 { 00452 using Teuchos::ArrayView; 00453 using Teuchos::as; 00454 using Teuchos::RCP; 00455 using Teuchos::rcp; 00456 using Teuchos::rcpFromRef; 00457 00458 const std::string timerName ("Ifpack2::Details::TriDiSolver::apply"); 00459 RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName); 00460 if (timer.is_null ()) { 00461 timer = Teuchos::TimeMonitor::getNewCounter (timerName); 00462 } 00463 00464 // Begin timing here. 00465 { 00466 Teuchos::TimeMonitor timeMon (*timer); 00467 00468 TEUCHOS_TEST_FOR_EXCEPTION( 00469 ! isComputed_, std::runtime_error, "Ifpack2::Details::TriDiSolver::apply: " 00470 "You must have called the compute() method before you may call apply(). " 00471 "You may call the apply() method as many times as you want after calling " 00472 "compute() once, but you must have called compute() at least once."); 00473 00474 const size_t numVecs = X.getNumVectors (); 00475 00476 TEUCHOS_TEST_FOR_EXCEPTION( 00477 numVecs != Y.getNumVectors (), std::runtime_error, 00478 "Ifpack2::Details::TriDiSolver::apply: X and Y have different numbers " 00479 "of vectors. X has " << X.getNumVectors () << ", but Y has " 00480 << X.getNumVectors () << "."); 00481 00482 if (numVecs == 0) { 00483 return; // done! nothing to do 00484 } 00485 00486 // Set up "local" views of X and Y. 00487 RCP<const MV> X_local; 00488 RCP<MV> Y_local; 00489 const bool multipleProcs = (A_->getRowMap ()->getComm ()->getSize () >= 1); 00490 if (multipleProcs) { 00491 // Interpret X and Y as "local" multivectors, that is, in the 00492 // local filter's domain resp. range Maps. "Interpret" means that 00493 // we create views with different Maps; we don't have to copy. 00494 X_local = X.offsetView (A_local_->getDomainMap (), 0); 00495 Y_local = Y.offsetViewNonConst (A_local_->getRangeMap (), 0); 00496 } 00497 else { // only one process in A_'s communicator 00498 // X and Y are already "local"; no need to set up local views. 00499 X_local = rcpFromRef (X); 00500 Y_local = rcpFromRef (Y); 00501 } 00502 00503 // Apply the local operator: 00504 // Y_local := beta*Y_local + alpha*M^{-1}*X_local 00505 this->applyImpl (*X_local, *Y_local, mode, alpha, beta); 00506 00507 ++numApply_; // We've successfully finished the work of apply(). 00508 } 00509 00510 // timer->totalElapsedTime() returns the total time over all timer 00511 // calls. Thus, we use = instead of +=. 00512 applyTime_ = timer->totalElapsedTime (); 00513 } 00514 00515 00516 template<class MatrixType> 00517 std::string TriDiSolver<MatrixType, false>::description () const 00518 { 00519 std::ostringstream out; 00520 00521 // Output is a valid YAML dictionary in flow style. If you don't 00522 // like everything on a single line, you should call describe() 00523 // instead. 00524 out << "\"Ifpack2::Details::TriDiSolver\": "; 00525 out << "{"; 00526 if (this->getObjectLabel () != "") { 00527 out << "Label: \"" << this->getObjectLabel () << "\", "; 00528 } 00529 out << "Initialized: " << (isInitialized () ? "true" : "false") << ", " 00530 << "Computed: " << (isComputed () ? "true" : "false") << ", "; 00531 00532 if (A_.is_null ()) { 00533 out << "Matrix: null"; 00534 } 00535 else { 00536 out << "Matrix: not null" 00537 << ", Global matrix dimensions: [" 00538 << A_->getGlobalNumRows () << ", " << A_->getGlobalNumCols () << "]"; 00539 } 00540 00541 out << "}"; 00542 return out.str (); 00543 } 00544 00545 00546 template<class MatrixType> 00547 void TriDiSolver<MatrixType, false>::describeLocal (Teuchos::FancyOStream& out, 00548 const Teuchos::EVerbosityLevel verbLevel) const { 00549 using Teuchos::FancyOStream; 00550 using Teuchos::OSTab; 00551 using Teuchos::RCP; 00552 using Teuchos::rcpFromRef; 00553 using std::endl; 00554 00555 if (verbLevel == Teuchos::VERB_NONE) { 00556 return; 00557 } 00558 else { 00559 RCP<FancyOStream> ptrOut = rcpFromRef (out); 00560 OSTab tab1 (ptrOut); 00561 if (this->getObjectLabel () != "") { 00562 out << "label: " << this->getObjectLabel () << endl; 00563 } 00564 out << "initialized: " << (isInitialized_ ? "true" : "false") << endl 00565 << "computed: " << (isComputed_ ? "true" : "false") << endl 00566 << "number of initialize calls: " << numInitialize_ << endl 00567 << "number of compute calls: " << numCompute_ << endl 00568 << "number of apply calls: " << numApply_ << endl 00569 << "total time in seconds in initialize: " << initializeTime_ << endl 00570 << "total time in seconds in compute: " << computeTime_ << endl 00571 << "total time in seconds in apply: " << applyTime_ << endl; 00572 if (verbLevel >= Teuchos::VERB_EXTREME) { 00573 out << "A_local_tridi_:" << endl; 00574 A_local_tridi_.print(out); 00575 } 00576 out << "ipiv_: " << Teuchos::toString (ipiv_) << endl; 00577 } 00578 } 00579 00580 template<class MatrixType> 00581 void TriDiSolver<MatrixType, false>::describe (Teuchos::FancyOStream& out, 00582 const Teuchos::EVerbosityLevel verbLevel) const 00583 { 00584 using Teuchos::FancyOStream; 00585 using Teuchos::OSTab; 00586 using Teuchos::RCP; 00587 using Teuchos::rcpFromRef; 00588 using std::endl; 00589 00590 RCP<FancyOStream> ptrOut = rcpFromRef (out); 00591 OSTab tab0 (ptrOut); 00592 if (A_.is_null ()) { 00593 // If A_ is null, we don't have a communicator, so we can't 00594 // safely print local data on all processes. Just print the 00595 // local data without arbitration between processes, and hope 00596 // for the best. 00597 if (verbLevel > Teuchos::VERB_NONE) { 00598 out << "Ifpack2::Details::TriDiSolver:" << endl; 00599 } 00600 describeLocal (out, verbLevel); 00601 } 00602 else { 00603 // If A_ is not null, we have a communicator, so we can 00604 // arbitrate among all processes to print local data. 00605 const Teuchos::Comm<int>& comm = * (A_->getRowMap ()->getComm ()); 00606 const int myRank = comm.getRank (); 00607 const int numProcs = comm.getSize (); 00608 if (verbLevel > Teuchos::VERB_NONE && myRank == 0) { 00609 out << "Ifpack2::Details::TriDiSolver:" << endl; 00610 } 00611 OSTab tab1 (ptrOut); 00612 for (int p = 0; p < numProcs; ++p) { 00613 if (myRank == p) { 00614 out << "Process " << myRank << ":" << endl; 00615 describeLocal (out, verbLevel); 00616 } 00617 comm.barrier (); 00618 comm.barrier (); 00619 comm.barrier (); 00620 } // for p = 0 .. numProcs-1 00621 } 00622 } 00623 00624 template<class MatrixType> 00625 void TriDiSolver<MatrixType, false>::extract (Teuchos::SerialTriDiMatrix<int, scalar_type>& A_local_tridi, 00626 const row_matrix_type& A_local) 00627 { 00628 using Teuchos::Array; 00629 using Teuchos::ArrayView; 00630 typedef local_ordinal_type LO; 00631 typedef typename Teuchos::ArrayView<LO>::size_type size_type; 00632 00633 // Fill the local tridi matrix with zeros. 00634 A_local_tridi.putScalar (STS::zero ()); 00635 00636 // 00637 // Map both row and column indices to local indices. We can use the 00638 // row Map's local indices for row indices, and the column Map's 00639 // local indices for column indices. It doesn't really matter; 00640 // either way is just a permutation of rows and columns. 00641 // 00642 const map_type& rowMap = * (A_local.getRowMap ()); 00643 00644 // Temporary arrays to hold the indices and values of the entries in 00645 // each row of A_local. 00646 const size_type maxNumRowEntries = 00647 static_cast<size_type> (A_local.getNodeMaxNumRowEntries ()); 00648 Array<LO> localIndices (maxNumRowEntries); 00649 Array<scalar_type> values (maxNumRowEntries); 00650 00651 const LO numLocalRows = static_cast<LO> (rowMap.getNodeNumElements ()); 00652 const LO minLocalRow = rowMap.getMinLocalIndex (); 00653 // This slight complication of computing the upper loop bound avoids 00654 // issues if the row Map has zero entries on the calling process. 00655 const LO maxLocalRow = minLocalRow + numLocalRows; // exclusive bound 00656 for (LO localRow = minLocalRow; localRow < maxLocalRow; ++localRow) { 00657 // The LocalFilter automatically excludes "off-process" entries. 00658 // That means all the column indices in this row belong to the 00659 // domain Map. We can, therefore, just use the local row and 00660 // column indices to put each entry directly in the tridi matrix. 00661 // It's OK if the column Map puts the local indices in a different 00662 // order; the Import will bring them into the correct order. 00663 const size_type numEntriesInRow = 00664 static_cast<size_type> (A_local.getNumEntriesInLocalRow (localRow)); 00665 size_t numEntriesOut = 0; // ignored 00666 A_local.getLocalRowCopy (localRow, 00667 localIndices (0, numEntriesInRow), 00668 values (0, numEntriesInRow), 00669 numEntriesOut); 00670 for (LO k = 0; k < numEntriesInRow; ++k) { 00671 const LO localCol = localIndices[k]; 00672 const scalar_type val = values[k]; 00673 // We use += instead of =, in case there are duplicate entries 00674 // in the row. There should not be, but why not be general? 00675 // NOTE: we only extract the TriDi part of the row matrix. Do not extract DU2 00676 if( localCol >= localRow-1 && localCol <= localRow+1 ) 00677 A_local_tridi(localRow, localCol) += val; 00678 } 00679 } 00680 } 00681 00683 // Stub implementation 00685 00686 template<class MatrixType> 00687 TriDiSolver<MatrixType, true>::TriDiSolver (const Teuchos::RCP<const row_matrix_type>& A) { 00688 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00689 } 00690 00691 00692 template<class MatrixType> 00693 Teuchos::RCP<const typename TriDiSolver<MatrixType, true>::map_type> 00694 TriDiSolver<MatrixType, true>::getDomainMap () const { 00695 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00696 } 00697 00698 00699 template<class MatrixType> 00700 Teuchos::RCP<const typename TriDiSolver<MatrixType, true>::map_type> 00701 TriDiSolver<MatrixType, true>::getRangeMap () const { 00702 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00703 } 00704 00705 00706 template<class MatrixType> 00707 void 00708 TriDiSolver<MatrixType, true>::setParameters (const Teuchos::ParameterList& params) { 00709 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00710 } 00711 00712 00713 template<class MatrixType> 00714 bool 00715 TriDiSolver<MatrixType, true>::isInitialized () const { 00716 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00717 } 00718 00719 00720 template<class MatrixType> 00721 bool 00722 TriDiSolver<MatrixType, true>::isComputed () const { 00723 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00724 } 00725 00726 00727 template<class MatrixType> 00728 int 00729 TriDiSolver<MatrixType, true>::getNumInitialize () const { 00730 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00731 } 00732 00733 00734 template<class MatrixType> 00735 int 00736 TriDiSolver<MatrixType, true>::getNumCompute () const { 00737 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00738 } 00739 00740 00741 template<class MatrixType> 00742 int 00743 TriDiSolver<MatrixType, true>::getNumApply () const { 00744 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00745 } 00746 00747 00748 template<class MatrixType> 00749 double 00750 TriDiSolver<MatrixType, true>::getInitializeTime () const { 00751 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00752 } 00753 00754 00755 template<class MatrixType> 00756 double 00757 TriDiSolver<MatrixType, true>::getComputeTime () const { 00758 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00759 } 00760 00761 00762 template<class MatrixType> 00763 double 00764 TriDiSolver<MatrixType, true>::getApplyTime () const { 00765 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00766 } 00767 00768 00769 template<class MatrixType> 00770 typename TriDiSolver<MatrixType, true>::magnitude_type 00771 TriDiSolver<MatrixType, true>::computeCondEst (CondestType CT, 00772 local_ordinal_type MaxIters, 00773 magnitude_type Tol, 00774 const Teuchos::Ptr<const row_matrix_type>& Matrix) 00775 { 00776 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00777 } 00778 00779 00780 template<class MatrixType> 00781 typename TriDiSolver<MatrixType, true>::magnitude_type 00782 TriDiSolver<MatrixType, true>::getCondEst () const { 00783 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00784 } 00785 00786 00787 template<class MatrixType> 00788 Teuchos::RCP<const typename TriDiSolver<MatrixType, true>::row_matrix_type> 00789 TriDiSolver<MatrixType, true>::getMatrix () const { 00790 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00791 } 00792 00793 00794 template<class MatrixType> 00795 void TriDiSolver<MatrixType, true>::setMatrix (const Teuchos::RCP<const row_matrix_type>& A) 00796 { 00797 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00798 } 00799 00800 00801 template<class MatrixType> 00802 void TriDiSolver<MatrixType, true>::initialize () 00803 { 00804 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00805 } 00806 00807 00808 template<class MatrixType> 00809 TriDiSolver<MatrixType, true>::~TriDiSolver () 00810 { 00811 // Destructors should never throw exceptions. 00812 } 00813 00814 00815 template<class MatrixType> 00816 void TriDiSolver<MatrixType, true>::compute () 00817 { 00818 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00819 } 00820 00821 00822 template<class MatrixType> 00823 void TriDiSolver<MatrixType, true>::apply ( 00824 const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X, 00825 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y, 00826 Teuchos::ETransp mode, 00827 scalar_type alpha, 00828 scalar_type beta) const 00829 { 00830 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00831 } 00832 00833 00834 template<class MatrixType> 00835 std::string 00836 TriDiSolver<MatrixType, true>::description () const 00837 { 00838 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00839 } 00840 00841 00842 template<class MatrixType> 00843 void TriDiSolver<MatrixType, true>::describe(Teuchos::FancyOStream& out, 00844 const Teuchos::EVerbosityLevel verbLevel) const 00845 { 00846 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00847 } 00848 00849 }// namespace Details 00850 } // namespace Ifpack2 00851 00852 #define IFPACK2_DETAILS_TRIDISOLVER_INSTANT(S,LO,GO,N) \ 00853 template class Ifpack2::Details::TriDiSolver< Tpetra::CrsMatrix<S, LO, GO, N> >; \ 00854 template class Ifpack2::Details::TriDiSolver< Tpetra::RowMatrix<S, LO, GO, N> >; 00855 00856 #endif // IFPACK2_DETAILS_TRIDISOLVER_HPP
1.7.6.1