|
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_DIAGONAL_DEF_HPP 00044 #define IFPACK2_DIAGONAL_DEF_HPP 00045 00046 #include "Ifpack2_Diagonal_decl.hpp" 00047 #include "Tpetra_CrsMatrix_def.hpp" 00048 #include "Ifpack2_Condest.hpp" 00049 00050 namespace Ifpack2 { 00051 00052 template<class MatrixType> 00053 Diagonal<MatrixType>::Diagonal (const Teuchos::RCP<const row_matrix_type>& A) : 00054 matrix_ (A), 00055 initializeTime_ (0.0), 00056 computeTime_ (0.0), 00057 applyTime_ (0.0), 00058 numInitialize_ (0), 00059 numCompute_ (0), 00060 numApply_ (0), 00061 condEst_ (-Teuchos::ScalarTraits<magnitude_type>::one ()), 00062 isInitialized_ (false), 00063 isComputed_ (false) 00064 {} 00065 00066 template<class MatrixType> 00067 Diagonal<MatrixType>::Diagonal (const Teuchos::RCP<const crs_matrix_type>& A) : 00068 matrix_ (A), 00069 initializeTime_ (0.0), 00070 computeTime_ (0.0), 00071 applyTime_ (0.0), 00072 numInitialize_ (0), 00073 numCompute_ (0), 00074 numApply_ (0), 00075 condEst_ (-Teuchos::ScalarTraits<magnitude_type>::one ()), 00076 isInitialized_ (false), 00077 isComputed_ (false) 00078 {} 00079 00080 template<class MatrixType> 00081 Diagonal<MatrixType>::Diagonal (const Teuchos::RCP<const vector_type>& diag) : 00082 userInverseDiag_ (diag), 00083 inverseDiag_ (diag), 00084 initializeTime_ (0.0), 00085 computeTime_ (0.0), 00086 applyTime_ (0.0), 00087 numInitialize_ (0), 00088 numCompute_ (0), 00089 numApply_ (0), 00090 condEst_ (-Teuchos::ScalarTraits<magnitude_type>::one ()), 00091 isInitialized_ (false), 00092 isComputed_ (false) 00093 {} 00094 00095 template<class MatrixType> 00096 Diagonal<MatrixType>::~Diagonal () 00097 {} 00098 00099 template<class MatrixType> 00100 Teuchos::RCP<const typename Diagonal<MatrixType>::map_type> 00101 Diagonal<MatrixType>::getDomainMap () const 00102 { 00103 if (matrix_.is_null ()) { 00104 if (userInverseDiag_.is_null ()) { 00105 TEUCHOS_TEST_FOR_EXCEPTION( 00106 true, std::runtime_error, "Ifpack2::Diagonal::getDomainMap: " 00107 "The input matrix A is null, and you did not provide a vector of " 00108 "inverse diagonal entries. Please call setMatrix() with a nonnull " 00109 "input matrix before calling this method."); 00110 } else { 00111 return userInverseDiag_->getMap (); 00112 } 00113 } else { 00114 return matrix_->getDomainMap (); 00115 } 00116 } 00117 00118 template<class MatrixType> 00119 Teuchos::RCP<const typename Diagonal<MatrixType>::map_type> 00120 Diagonal<MatrixType>::getRangeMap () const 00121 { 00122 if (matrix_.is_null ()) { 00123 if (userInverseDiag_.is_null ()) { 00124 TEUCHOS_TEST_FOR_EXCEPTION( 00125 true, std::runtime_error, "Ifpack2::Diagonal::getRangeMap: " 00126 "The input matrix A is null, and you did not provide a vector of " 00127 "inverse diagonal entries. Please call setMatrix() with a nonnull " 00128 "input matrix before calling this method."); 00129 } else { 00130 return userInverseDiag_->getMap (); 00131 } 00132 } else { 00133 return matrix_->getRangeMap (); 00134 } 00135 } 00136 00137 template<class MatrixType> 00138 void Diagonal<MatrixType>:: 00139 setParameters (const Teuchos::ParameterList& /*params*/) 00140 {} 00141 00142 template<class MatrixType> 00143 void Diagonal<MatrixType>::reset () 00144 { 00145 inverseDiag_ = Teuchos::null; 00146 offsets_ = Teuchos::null; 00147 condEst_ = -Teuchos::ScalarTraits<magnitude_type>::one (); 00148 isInitialized_ = false; 00149 isComputed_ = false; 00150 } 00151 00152 template<class MatrixType> 00153 void Diagonal<MatrixType>:: 00154 setMatrix (const Teuchos::RCP<const row_matrix_type>& A) 00155 { 00156 if (A.getRawPtr () != matrix_.getRawPtr ()) { // it's a different matrix 00157 reset (); 00158 matrix_ = A; 00159 } 00160 } 00161 00162 template<class MatrixType> 00163 void Diagonal<MatrixType>::initialize () 00164 { 00165 // Either the matrix to precondition must be nonnull, or the user 00166 // must have provided a Vector of diagonal entries. 00167 TEUCHOS_TEST_FOR_EXCEPTION( 00168 matrix_.is_null () && userInverseDiag_.is_null (), std::runtime_error, 00169 "Ifpack2::Diagonal::initialize: The matrix to precondition is null, " 00170 "and you did not provide a Tpetra::Vector of diagonal entries. " 00171 "Please call setMatrix() with a nonnull input before calling this method."); 00172 00173 // If the user did provide an input matrix, then that takes 00174 // precedence over the vector of inverse diagonal entries, if they 00175 // provided one earlier. This is only possible if they created this 00176 // Diagonal instance using the constructor that takes a 00177 // Tpetra::Vector pointer, and then called setMatrix() with a 00178 // nonnull input matrix. 00179 if (! matrix_.is_null ()) { 00180 // If you call initialize(), it means that you are asserting that 00181 // the structure of the input sparse matrix may have changed. 00182 // This means we should always recompute the diagonal offsets, if 00183 // the input matrix is a Tpetra::CrsMatrix. 00184 Teuchos::RCP<const crs_matrix_type> A_crs = 00185 Teuchos::rcp_dynamic_cast<const crs_matrix_type> (matrix_); 00186 if (A_crs.is_null ()) { 00187 offsets_ = Teuchos::null; // offsets are no longer valid 00188 } 00189 else { 00190 A_crs->getLocalDiagOffsets (offsets_); 00191 } 00192 } 00193 00194 isInitialized_ = true; 00195 ++numInitialize_; 00196 } 00197 00198 template<class MatrixType> 00199 void Diagonal<MatrixType>::compute () 00200 { 00201 // Either the matrix to precondition must be nonnull, or the user 00202 // must have provided a Vector of diagonal entries. 00203 TEUCHOS_TEST_FOR_EXCEPTION( 00204 matrix_.is_null () && userInverseDiag_.is_null (), std::runtime_error, 00205 "Ifpack2::Diagonal::compute: The matrix to precondition is null, " 00206 "and you did not provide a Tpetra::Vector of diagonal entries. " 00207 "Please call setMatrix() with a nonnull input before calling this method."); 00208 00209 if (! isInitialized_) { 00210 initialize (); 00211 } 00212 00213 // If the user did provide an input matrix, then that takes 00214 // precedence over the vector of inverse diagonal entries, if they 00215 // provided one earlier. This is only possible if they created this 00216 // Diagonal instance using the constructor that takes a 00217 // Tpetra::Vector pointer, and then called setMatrix() with a 00218 // nonnull input matrix. 00219 if (matrix_.is_null ()) { // accept the user's diagonal 00220 inverseDiag_ = userInverseDiag_; 00221 } 00222 else { 00223 Teuchos::RCP<vector_type> tmpVec (new vector_type (matrix_->getRowMap ())); 00224 Teuchos::RCP<const crs_matrix_type> A_crs = 00225 Teuchos::rcp_dynamic_cast<const crs_matrix_type> (matrix_); 00226 if (A_crs.is_null ()) { 00227 // Get the diagonal entries from the Tpetra::RowMatrix. 00228 matrix_->getLocalDiagCopy (*tmpVec); 00229 } 00230 else { 00231 // Get the diagonal entries from the Tpetra::CrsMatrix using the 00232 // precomputed offsets. 00233 A_crs->getLocalDiagCopy (*tmpVec, offsets_ ()); 00234 } 00235 tmpVec->reciprocal (*tmpVec); // invert the diagonal entries 00236 inverseDiag_ = tmpVec; 00237 } 00238 00239 isComputed_ = true; 00240 ++numCompute_; 00241 } 00242 00243 template<class MatrixType> 00244 void Diagonal<MatrixType>:: 00245 apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X, 00246 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y, 00247 Teuchos::ETransp /*mode*/, 00248 scalar_type alpha, 00249 scalar_type beta) const 00250 { 00251 TEUCHOS_TEST_FOR_EXCEPTION( 00252 ! isComputed (), std::runtime_error, "Ifpack2::Diagonal::apply: You " 00253 "must first call compute() before you may call apply(). Once you have " 00254 "called compute(), you need not call it again unless the values in the " 00255 "matrix have changed, or unless you have called setMatrix()."); 00256 00257 // FIXME (mfh 12 Sep 2014) This assumes that row Map == range Map == 00258 // domain Map. If the preconditioner has a matrix, we should ask 00259 // the matrix whether we need to do an Import before and/or an 00260 // Export after. 00261 00262 Y.elementWiseMultiply (alpha, *inverseDiag_, X, beta); 00263 ++numApply_; 00264 } 00265 00266 template<class MatrixType> 00267 typename Teuchos::ScalarTraits<typename MatrixType::scalar_type>::magnitudeType 00268 Diagonal<MatrixType>:: 00269 computeCondEst (CondestType CT, 00270 local_ordinal_type MaxIters, 00271 magnitude_type Tol, 00272 const Teuchos::Ptr<const row_matrix_type>& matrix) 00273 { 00274 const magnitude_type minusOne = -Teuchos::ScalarTraits<magnitude_type>::one (); 00275 00276 if (! isComputed ()) { // cannot compute right now 00277 return minusOne; 00278 } 00279 // NOTE: this is computing the *local* condest 00280 if (condEst_ == minusOne) { 00281 condEst_ = Ifpack2::Condest (*this, CT, MaxIters, Tol, matrix); 00282 } 00283 return condEst_; 00284 } 00285 00286 template <class MatrixType> 00287 int Diagonal<MatrixType>::getNumInitialize() const { 00288 return numInitialize_; 00289 } 00290 00291 template <class MatrixType> 00292 int Diagonal<MatrixType>::getNumCompute() const { 00293 return numCompute_; 00294 } 00295 00296 template <class MatrixType> 00297 int Diagonal<MatrixType>::getNumApply() const { 00298 return numApply_; 00299 } 00300 00301 template <class MatrixType> 00302 double Diagonal<MatrixType>::getInitializeTime() const { 00303 return initializeTime_; 00304 } 00305 00306 template<class MatrixType> 00307 double Diagonal<MatrixType>::getComputeTime() const { 00308 return computeTime_; 00309 } 00310 00311 template<class MatrixType> 00312 double Diagonal<MatrixType>::getApplyTime() const { 00313 return applyTime_; 00314 } 00315 00316 template <class MatrixType> 00317 std::string Diagonal<MatrixType>::description () const 00318 { 00319 std::ostringstream out; 00320 00321 // Output is a valid YAML dictionary in flow style. If you don't 00322 // like everything on a single line, you should call describe() 00323 // instead. 00324 out << "\"Ifpack2::Diagonal\": " 00325 << "{"; 00326 if (this->getObjectLabel () != "") { 00327 out << "Label: \"" << this->getObjectLabel () << "\", "; 00328 } 00329 if (matrix_.is_null ()) { 00330 out << "Matrix: null"; 00331 } 00332 else { 00333 out << "Matrix: not null" 00334 << ", Global matrix dimensions: [" 00335 << matrix_->getGlobalNumRows () << ", " 00336 << matrix_->getGlobalNumCols () << "]"; 00337 } 00338 00339 out << "}"; 00340 return out.str (); 00341 } 00342 00343 template <class MatrixType> 00344 void Diagonal<MatrixType>:: 00345 describe (Teuchos::FancyOStream &out, 00346 const Teuchos::EVerbosityLevel verbLevel) const 00347 { 00348 using std::endl; 00349 00350 const Teuchos::EVerbosityLevel vl = 00351 (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel; 00352 if (vl != Teuchos::VERB_NONE) { 00353 Teuchos::OSTab tab0 (out); 00354 out << "\"Ifpack2::Diagonal\":"; 00355 Teuchos::OSTab tab1 (out); 00356 out << "Template parameter: " 00357 << Teuchos::TypeNameTraits<MatrixType>::name () << endl; 00358 if (this->getObjectLabel () != "") { 00359 out << "Label: \"" << this->getObjectLabel () << "\", "; 00360 } 00361 out << "Number of initialize calls: " << numInitialize_ << endl 00362 << "Number of compute calls: " << numCompute_ << endl 00363 << "Number of apply calls: " << numApply_ << endl; 00364 } 00365 } 00366 00367 } // namespace Ifpack2 00368 00369 #define IFPACK2_DIAGONAL_INSTANT(S,LO,GO,N) \ 00370 template class Ifpack2::Diagonal< Tpetra::CrsMatrix<S, LO, GO, N> >; \ 00371 template class Ifpack2::Diagonal< Tpetra::RowMatrix<S, LO, GO, N> >; 00372 00373 #endif
1.7.6.1