|
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_DENSESOLVER_DEF_HPP 00044 #define IFPACK2_DETAILS_DENSESOLVER_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 DenseSolver<MatrixType, false>:: 00067 DenseSolver (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 DenseSolver<MatrixType, false>::map_type> 00082 DenseSolver<MatrixType, false>::getDomainMap () const { 00083 TEUCHOS_TEST_FOR_EXCEPTION( 00084 A_.is_null (), std::runtime_error, "Ifpack2::Details::DenseSolver::" 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, DenseSolver 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 DenseSolver<MatrixType, false>::map_type> 00095 DenseSolver<MatrixType, false>::getRangeMap () const { 00096 TEUCHOS_TEST_FOR_EXCEPTION( 00097 A_.is_null (), std::runtime_error, "Ifpack2::Details::DenseSolver::" 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, DenseSolver 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 DenseSolver<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 DenseSolver<MatrixType, false>::isInitialized () const { 00117 return isInitialized_; 00118 } 00119 00120 00121 template<class MatrixType> 00122 bool 00123 DenseSolver<MatrixType, false>::isComputed () const { 00124 return isComputed_; 00125 } 00126 00127 00128 template<class MatrixType> 00129 int 00130 DenseSolver<MatrixType, false>::getNumInitialize () const { 00131 return numInitialize_; 00132 } 00133 00134 00135 template<class MatrixType> 00136 int 00137 DenseSolver<MatrixType, false>::getNumCompute () const { 00138 return numCompute_; 00139 } 00140 00141 00142 template<class MatrixType> 00143 int 00144 DenseSolver<MatrixType, false>::getNumApply () const { 00145 return numApply_; 00146 } 00147 00148 00149 template<class MatrixType> 00150 double 00151 DenseSolver<MatrixType, false>::getInitializeTime () const { 00152 return initializeTime_; 00153 } 00154 00155 00156 template<class MatrixType> 00157 double 00158 DenseSolver<MatrixType, false>::getComputeTime () const { 00159 return computeTime_; 00160 } 00161 00162 00163 template<class MatrixType> 00164 double 00165 DenseSolver<MatrixType, false>::getApplyTime () const { 00166 return applyTime_; 00167 } 00168 00169 00170 template<class MatrixType> 00171 typename DenseSolver<MatrixType, false>::magnitude_type 00172 DenseSolver<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 DenseSolver<MatrixType, false>::magnitude_type 00184 DenseSolver<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 DenseSolver<MatrixType, false>::row_matrix_type> 00191 DenseSolver<MatrixType, false>::getMatrix () const { 00192 return A_; 00193 } 00194 00195 00196 template<class MatrixType> 00197 void DenseSolver<MatrixType, false>:: 00198 reset () 00199 { 00200 isInitialized_ = false; 00201 isComputed_ = false; 00202 A_local_ = ::Teuchos::null; 00203 A_local_dense_.reshape (0, 0); 00204 ipiv_.resize (0); 00205 } 00206 00207 00208 template<class MatrixType> 00209 void DenseSolver<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::DenseSolver::" 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 DenseSolver<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::DenseSolver::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::DenseSolver::" 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::DenseSolver: " 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::DenseSolver::" 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 dense 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::DenseSolver::" 00279 "initialize: Local filter matrix is not square. This should never happen. " 00280 "Please report this bug to the Ifpack2 developers."); 00281 A_local_dense_.reshape (numRows, numCols); 00282 ipiv_.resize (std::min (numRows, numCols)); 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 DenseSolver<MatrixType, false>::~DenseSolver() 00297 {} 00298 00299 00300 template<class MatrixType> 00301 void DenseSolver<MatrixType, false>::compute () 00302 { 00303 using ::Teuchos::RCP; 00304 const std::string timerName ("Ifpack2::Details::DenseSolver::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::DenseSolver::" 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::DenseSolver::" 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_dense_, *A_local_); // extract the dense local matrix 00329 factor (A_local_dense_, ipiv_ ()); // factor the dense local matrix 00330 00331 isComputed_ = true; 00332 ++numCompute_; 00333 } 00334 // timer->totalElapsedTime() returns the total time over all timer 00335 // calls. Thus, we use = instead of +=. 00336 computeTime_ = timer->totalElapsedTime (); 00337 } 00338 00339 template<class MatrixType> 00340 void DenseSolver<MatrixType, false>:: 00341 factor (::Teuchos::SerialDenseMatrix<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.GETRF (A.numRows (), A.numCols (), A.values (), A.stride (), 00350 ipiv.getRawPtr (), &INFO); 00351 // INFO < 0 is a bug. 00352 TEUCHOS_TEST_FOR_EXCEPTION( 00353 INFO < 0, std::logic_error, "Ifpack2::Details::DenseSolver::factor: " 00354 "LAPACK's _GETRF (LU factorization with partial pivoting) was called " 00355 "incorrectly. INFO = " << INFO << " < 0. " 00356 "Please report this bug to the Ifpack2 developers."); 00357 // INFO > 0 means the matrix is singular. This is probably an issue 00358 // either with the choice of rows the rows we extracted, or with the 00359 // input matrix itself. 00360 TEUCHOS_TEST_FOR_EXCEPTION( 00361 INFO > 0, std::runtime_error, "Ifpack2::Details::DenseSolver::factor: " 00362 "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the " 00363 "computed U factor is exactly singular. U(" << INFO << "," << INFO << ") " 00364 "(one-based index i) is exactly zero. This probably means that the input " 00365 "matrix has a singular diagonal block."); 00366 } 00367 00368 00369 template<class MatrixType> 00370 void DenseSolver<MatrixType, false>:: 00371 applyImpl (const MV& X, 00372 MV& Y, 00373 const ::Teuchos::ETransp mode, 00374 const scalar_type alpha, 00375 const scalar_type beta) const 00376 { 00377 using ::Teuchos::ArrayRCP; 00378 using ::Teuchos::RCP; 00379 using ::Teuchos::rcp; 00380 using ::Teuchos::rcpFromRef; 00381 using ::Teuchos::CONJ_TRANS; 00382 using ::Teuchos::TRANS; 00383 00384 const int numVecs = static_cast<int> (X.getNumVectors ()); 00385 if (alpha == STS::zero ()) { // don't need to solve the linear system 00386 if (beta == STS::zero ()) { 00387 // Use BLAS AXPY semantics for beta == 0: overwrite, clobbering 00388 // any Inf or NaN values in Y (rather than multiplying them by 00389 // zero, resulting in NaN values). 00390 Y.putScalar (STS::zero ()); 00391 } 00392 else { // beta != 0 00393 Y.scale (STS::zero ()); 00394 } 00395 } 00396 else { // alpha != 0; must solve the linear system 00397 ::Teuchos::LAPACK<int, scalar_type> lapack; 00398 // If beta is nonzero, Y is not constant stride, or alpha != 1, we 00399 // have to use a temporary output multivector Y_tmp. It gets a 00400 // copy of alpha*X, since GETRS overwrites its (multi)vector input 00401 // with its output. 00402 RCP<MV> Y_tmp; 00403 if (beta == STS::zero () && Y.isConstantStride () && alpha == STS::one ()) { 00404 deep_copy (Y, X); 00405 Y_tmp = rcpFromRef (Y); 00406 } 00407 else { 00408 Y_tmp = rcp (new MV (X, ::Teuchos::Copy)); // constructor copies X 00409 if (alpha != STS::one ()) { 00410 Y_tmp->scale (alpha); 00411 } 00412 } 00413 const int Y_stride = static_cast<int> (Y_tmp->getStride ()); 00414 ArrayRCP<scalar_type> Y_view = Y_tmp->get1dViewNonConst (); 00415 scalar_type* const Y_ptr = Y_view.getRawPtr (); 00416 int INFO = 0; 00417 const char trans = 00418 (mode == CONJ_TRANS ? 'C' : (mode == TRANS ? 'T' : 'N')); 00419 lapack.GETRS (trans, A_local_dense_.numRows (), numVecs, 00420 A_local_dense_.values (), A_local_dense_.stride (), 00421 ipiv_.getRawPtr (), Y_ptr, Y_stride, &INFO); 00422 TEUCHOS_TEST_FOR_EXCEPTION( 00423 INFO != 0, std::runtime_error, "Ifpack2::Details::DenseSolver::" 00424 "applyImpl: LAPACK's _GETRS (solve using LU factorization with " 00425 "partial pivoting) failed with INFO = " << INFO << " != 0."); 00426 00427 if (beta != STS::zero ()) { 00428 Y.update (alpha, *Y_tmp, beta); 00429 } 00430 else if (! Y.isConstantStride ()) { 00431 deep_copy (Y, *Y_tmp); 00432 } 00433 } 00434 } 00435 00436 00437 template<class MatrixType> 00438 void DenseSolver<MatrixType, false>:: 00439 apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X, 00440 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y, 00441 ::Teuchos::ETransp mode, 00442 scalar_type alpha, 00443 scalar_type beta) const 00444 { 00445 using ::Teuchos::ArrayView; 00446 using ::Teuchos::as; 00447 using ::Teuchos::RCP; 00448 using ::Teuchos::rcp; 00449 using ::Teuchos::rcpFromRef; 00450 00451 const std::string timerName ("Ifpack2::Details::DenseSolver::apply"); 00452 RCP<::Teuchos::Time> timer = ::Teuchos::TimeMonitor::lookupCounter (timerName); 00453 if (timer.is_null ()) { 00454 timer = ::Teuchos::TimeMonitor::getNewCounter (timerName); 00455 } 00456 00457 // Begin timing here. 00458 { 00459 ::Teuchos::TimeMonitor timeMon (*timer); 00460 00461 TEUCHOS_TEST_FOR_EXCEPTION( 00462 ! isComputed_, std::runtime_error, "Ifpack2::Details::DenseSolver::apply: " 00463 "You must have called the compute() method before you may call apply(). " 00464 "You may call the apply() method as many times as you want after calling " 00465 "compute() once, but you must have called compute() at least once."); 00466 00467 const size_t numVecs = X.getNumVectors (); 00468 00469 TEUCHOS_TEST_FOR_EXCEPTION( 00470 numVecs != Y.getNumVectors (), std::runtime_error, 00471 "Ifpack2::Details::DenseSolver::apply: X and Y have different numbers " 00472 "of vectors. X has " << X.getNumVectors () << ", but Y has " 00473 << X.getNumVectors () << "."); 00474 00475 if (numVecs == 0) { 00476 return; // done! nothing to do 00477 } 00478 00479 // Set up "local" views of X and Y. 00480 RCP<const MV> X_local; 00481 RCP<MV> Y_local; 00482 const bool multipleProcs = (A_->getRowMap ()->getComm ()->getSize () >= 1); 00483 if (multipleProcs) { 00484 // Interpret X and Y as "local" multivectors, that is, in the 00485 // local filter's domain resp. range Maps. "Interpret" means that 00486 // we create views with different Maps; we don't have to copy. 00487 X_local = X.offsetView (A_local_->getDomainMap (), 0); 00488 Y_local = Y.offsetViewNonConst (A_local_->getRangeMap (), 0); 00489 } 00490 else { // only one process in A_'s communicator 00491 // X and Y are already "local"; no need to set up local views. 00492 X_local = rcpFromRef (X); 00493 Y_local = rcpFromRef (Y); 00494 } 00495 00496 // Apply the local operator: 00497 // Y_local := beta*Y_local + alpha*M^{-1}*X_local 00498 this->applyImpl (*X_local, *Y_local, mode, alpha, beta); 00499 00500 ++numApply_; // We've successfully finished the work of apply(). 00501 } 00502 00503 // timer->totalElapsedTime() returns the total time over all timer 00504 // calls. Thus, we use = instead of +=. 00505 applyTime_ = timer->totalElapsedTime (); 00506 } 00507 00508 00509 template<class MatrixType> 00510 std::string 00511 DenseSolver<MatrixType, false>::description () const 00512 { 00513 std::ostringstream out; 00514 00515 // Output is a valid YAML dictionary in flow style. If you don't 00516 // like everything on a single line, you should call describe() 00517 // instead. 00518 out << "\"Ifpack2::Details::DenseSolver\": "; 00519 out << "{"; 00520 if (this->getObjectLabel () != "") { 00521 out << "Label: \"" << this->getObjectLabel () << "\", "; 00522 } 00523 out << "Initialized: " << (isInitialized () ? "true" : "false") << ", " 00524 << "Computed: " << (isComputed () ? "true" : "false") << ", "; 00525 00526 if (A_.is_null ()) { 00527 out << "Matrix: null"; 00528 } 00529 else { 00530 out << "Matrix: not null" 00531 << ", Global matrix dimensions: [" 00532 << A_->getGlobalNumRows () << ", " << A_->getGlobalNumCols () << "]"; 00533 } 00534 00535 out << "}"; 00536 return out.str (); 00537 } 00538 00539 00540 template<class MatrixType> 00541 void DenseSolver<MatrixType, false>:: 00542 describeLocal (::Teuchos::FancyOStream& out, 00543 const ::Teuchos::EVerbosityLevel verbLevel) const 00544 { 00545 using ::Teuchos::FancyOStream; 00546 using ::Teuchos::OSTab; 00547 using ::Teuchos::RCP; 00548 using ::Teuchos::rcpFromRef; 00549 using std::endl; 00550 00551 if (verbLevel == ::Teuchos::VERB_NONE) { 00552 return; 00553 } 00554 else { 00555 RCP<FancyOStream> ptrOut = rcpFromRef (out); 00556 OSTab tab1 (ptrOut); 00557 if (this->getObjectLabel () != "") { 00558 out << "label: " << this->getObjectLabel () << endl; 00559 } 00560 out << "initialized: " << (isInitialized_ ? "true" : "false") << endl 00561 << "computed: " << (isComputed_ ? "true" : "false") << endl 00562 << "number of initialize calls: " << numInitialize_ << endl 00563 << "number of compute calls: " << numCompute_ << endl 00564 << "number of apply calls: " << numApply_ << endl 00565 << "total time in seconds in initialize: " << initializeTime_ << endl 00566 << "total time in seconds in compute: " << computeTime_ << endl 00567 << "total time in seconds in apply: " << applyTime_ << endl; 00568 if (verbLevel >= ::Teuchos::VERB_EXTREME) { 00569 out << "A_local_dense_:" << endl; 00570 { 00571 OSTab tab2 (ptrOut); 00572 out << "["; 00573 for (int i = 0; i < A_local_dense_.numRows (); ++i) { 00574 for (int j = 0; j < A_local_dense_.numCols (); ++j) { 00575 out << A_local_dense_(i,j); 00576 if (j + 1 < A_local_dense_.numCols ()) { 00577 out << ", "; 00578 } 00579 } 00580 if (i + 1 < A_local_dense_.numRows ()) { 00581 out << ";" << endl; 00582 } 00583 } 00584 out << "]" << endl; 00585 } 00586 out << "ipiv_: " << ::Teuchos::toString (ipiv_) << endl; 00587 } 00588 } 00589 } 00590 00591 00592 template<class MatrixType> 00593 void DenseSolver<MatrixType, false>:: 00594 describe (::Teuchos::FancyOStream& out, 00595 const ::Teuchos::EVerbosityLevel verbLevel) const 00596 { 00597 using ::Teuchos::FancyOStream; 00598 using ::Teuchos::OSTab; 00599 using ::Teuchos::RCP; 00600 using ::Teuchos::rcpFromRef; 00601 using std::endl; 00602 00603 RCP<FancyOStream> ptrOut = rcpFromRef (out); 00604 OSTab tab0 (ptrOut); 00605 if (A_.is_null ()) { 00606 // If A_ is null, we don't have a communicator, so we can't 00607 // safely print local data on all processes. Just print the 00608 // local data without arbitration between processes, and hope 00609 // for the best. 00610 if (verbLevel > ::Teuchos::VERB_NONE) { 00611 out << "Ifpack2::Details::DenseSolver:" << endl; 00612 } 00613 describeLocal (out, verbLevel); 00614 } 00615 else { 00616 // If A_ is not null, we have a communicator, so we can 00617 // arbitrate among all processes to print local data. 00618 const ::Teuchos::Comm<int>& comm = * (A_->getRowMap ()->getComm ()); 00619 const int myRank = comm.getRank (); 00620 const int numProcs = comm.getSize (); 00621 if (verbLevel > ::Teuchos::VERB_NONE && myRank == 0) { 00622 out << "Ifpack2::Details::DenseSolver:" << endl; 00623 } 00624 OSTab tab1 (ptrOut); 00625 for (int p = 0; p < numProcs; ++p) { 00626 if (myRank == p) { 00627 out << "Process " << myRank << ":" << endl; 00628 describeLocal (out, verbLevel); 00629 } 00630 comm.barrier (); 00631 comm.barrier (); 00632 comm.barrier (); 00633 } // for p = 0 .. numProcs-1 00634 } 00635 } 00636 00637 00638 template<class MatrixType> 00639 void DenseSolver<MatrixType, false>:: 00640 extract (::Teuchos::SerialDenseMatrix<int, scalar_type>& A_local_dense, 00641 const row_matrix_type& A_local) 00642 { 00643 using ::Teuchos::Array; 00644 using ::Teuchos::ArrayView; 00645 typedef local_ordinal_type LO; 00646 typedef typename ::Teuchos::ArrayView<LO>::size_type size_type; 00647 00648 // Fill the local dense matrix with zeros. 00649 A_local_dense.putScalar (STS::zero ()); 00650 00651 // 00652 // Map both row and column indices to local indices. We can use the 00653 // row Map's local indices for row indices, and the column Map's 00654 // local indices for column indices. It doesn't really matter; 00655 // either way is just a permutation of rows and columns. 00656 // 00657 const map_type& rowMap = * (A_local.getRowMap ()); 00658 00659 // Temporary arrays to hold the indices and values of the entries in 00660 // each row of A_local. 00661 const size_type maxNumRowEntries = 00662 static_cast<size_type> (A_local.getNodeMaxNumRowEntries ()); 00663 Array<LO> localIndices (maxNumRowEntries); 00664 Array<scalar_type> values (maxNumRowEntries); 00665 00666 const LO numLocalRows = static_cast<LO> (rowMap.getNodeNumElements ()); 00667 const LO minLocalRow = rowMap.getMinLocalIndex (); 00668 // This slight complication of computing the upper loop bound avoids 00669 // issues if the row Map has zero entries on the calling process. 00670 const LO maxLocalRow = minLocalRow + numLocalRows; // exclusive bound 00671 for (LO localRow = minLocalRow; localRow < maxLocalRow; ++localRow) { 00672 // The LocalFilter automatically excludes "off-process" entries. 00673 // That means all the column indices in this row belong to the 00674 // domain Map. We can, therefore, just use the local row and 00675 // column indices to put each entry directly in the dense matrix. 00676 // It's OK if the column Map puts the local indices in a different 00677 // order; the Import will bring them into the correct order. 00678 const size_type numEntriesInRow = 00679 static_cast<size_type> (A_local.getNumEntriesInLocalRow (localRow)); 00680 size_t numEntriesOut = 0; // ignored 00681 A_local.getLocalRowCopy (localRow, 00682 localIndices (0, numEntriesInRow), 00683 values (0, numEntriesInRow), 00684 numEntriesOut); 00685 for (LO k = 0; k < numEntriesInRow; ++k) { 00686 const LO localCol = localIndices[k]; 00687 const scalar_type val = values[k]; 00688 // We use += instead of =, in case there are duplicate entries 00689 // in the row. There should not be, but why not be general? 00690 A_local_dense(localRow, localCol) += val; 00691 } 00692 } 00693 } 00694 00696 // Stub implementation 00698 00699 template<class MatrixType> 00700 DenseSolver<MatrixType, true>:: 00701 DenseSolver (const ::Teuchos::RCP<const row_matrix_type>& A) { 00702 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00703 } 00704 00705 00706 template<class MatrixType> 00707 ::Teuchos::RCP<const typename DenseSolver<MatrixType, true>::map_type> 00708 DenseSolver<MatrixType, true>::getDomainMap () const { 00709 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00710 } 00711 00712 00713 template<class MatrixType> 00714 ::Teuchos::RCP<const typename DenseSolver<MatrixType, true>::map_type> 00715 DenseSolver<MatrixType, true>::getRangeMap () const { 00716 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00717 } 00718 00719 00720 template<class MatrixType> 00721 void 00722 DenseSolver<MatrixType, true>:: 00723 setParameters (const ::Teuchos::ParameterList& params) { 00724 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00725 } 00726 00727 00728 template<class MatrixType> 00729 bool 00730 DenseSolver<MatrixType, true>::isInitialized () const { 00731 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00732 } 00733 00734 00735 template<class MatrixType> 00736 bool 00737 DenseSolver<MatrixType, true>::isComputed () const { 00738 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00739 } 00740 00741 00742 template<class MatrixType> 00743 int 00744 DenseSolver<MatrixType, true>::getNumInitialize () const { 00745 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00746 } 00747 00748 00749 template<class MatrixType> 00750 int 00751 DenseSolver<MatrixType, true>::getNumCompute () const { 00752 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00753 } 00754 00755 00756 template<class MatrixType> 00757 int 00758 DenseSolver<MatrixType, true>::getNumApply () const { 00759 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00760 } 00761 00762 00763 template<class MatrixType> 00764 double 00765 DenseSolver<MatrixType, true>::getInitializeTime () const { 00766 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00767 } 00768 00769 00770 template<class MatrixType> 00771 double 00772 DenseSolver<MatrixType, true>::getComputeTime () const { 00773 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00774 } 00775 00776 00777 template<class MatrixType> 00778 double 00779 DenseSolver<MatrixType, true>::getApplyTime () const { 00780 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00781 } 00782 00783 00784 template<class MatrixType> 00785 typename DenseSolver<MatrixType, true>::magnitude_type 00786 DenseSolver<MatrixType, true>:: 00787 computeCondEst (CondestType CT, 00788 local_ordinal_type MaxIters, 00789 magnitude_type Tol, 00790 const ::Teuchos::Ptr<const row_matrix_type>& Matrix) 00791 { 00792 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00793 } 00794 00795 00796 template<class MatrixType> 00797 typename DenseSolver<MatrixType, true>::magnitude_type 00798 DenseSolver<MatrixType, true>::getCondEst () const { 00799 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00800 } 00801 00802 00803 template<class MatrixType> 00804 ::Teuchos::RCP<const typename DenseSolver<MatrixType, true>::row_matrix_type> 00805 DenseSolver<MatrixType, true>::getMatrix () const { 00806 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00807 } 00808 00809 00810 template<class MatrixType> 00811 void DenseSolver<MatrixType, true>:: 00812 setMatrix (const ::Teuchos::RCP<const row_matrix_type>& A) 00813 { 00814 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00815 } 00816 00817 00818 template<class MatrixType> 00819 void DenseSolver<MatrixType, true>::initialize () 00820 { 00821 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00822 } 00823 00824 00825 template<class MatrixType> 00826 DenseSolver<MatrixType, true>::~DenseSolver () 00827 { 00828 // Destructors should never throw exceptions. 00829 } 00830 00831 00832 template<class MatrixType> 00833 void DenseSolver<MatrixType, true>::compute () 00834 { 00835 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00836 } 00837 00838 00839 template<class MatrixType> 00840 void DenseSolver<MatrixType, true>:: 00841 apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X, 00842 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y, 00843 ::Teuchos::ETransp mode, 00844 scalar_type alpha, 00845 scalar_type beta) const 00846 { 00847 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00848 } 00849 00850 00851 template<class MatrixType> 00852 std::string 00853 DenseSolver<MatrixType, true>::description () const 00854 { 00855 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00856 } 00857 00858 00859 template<class MatrixType> 00860 void DenseSolver<MatrixType, true>:: 00861 describe (::Teuchos::FancyOStream& out, 00862 const ::Teuchos::EVerbosityLevel verbLevel) const 00863 { 00864 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented"); 00865 } 00866 00867 00868 } // namespace Details 00869 } // namespace Ifpack2 00870 00871 #define IFPACK2_DETAILS_DENSESOLVER_INSTANT(S,LO,GO,N) \ 00872 template class Ifpack2::Details::DenseSolver< Tpetra::CrsMatrix<S, LO, GO, N> >; \ 00873 template class Ifpack2::Details::DenseSolver< Tpetra::RowMatrix<S, LO, GO, N> >; 00874 00875 #endif // IFPACK2_DETAILS_DENSESOLVER_HPP
1.7.6.1