|
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_IDENTITY_SOLVER_DEF_HPP 00044 #define IFPACK2_IDENTITY_SOLVER_DEF_HPP 00045 00046 #include "Ifpack2_IdentitySolver_decl.hpp" 00047 #include "Ifpack2_Condest.hpp" 00048 00049 namespace Ifpack2 { 00050 00051 template<class MatrixType> 00052 IdentitySolver<MatrixType>:: 00053 IdentitySolver (const Teuchos::RCP<const row_matrix_type>& A) 00054 : matrix_ (A), 00055 isInitialized_ (false), 00056 isComputed_ (false), 00057 numInitialize_ (0), 00058 numCompute_ (0), 00059 numApply_ (0), 00060 initializeTime_(0.0), 00061 computeTime_(0.0), 00062 applyTime_(0.0), 00063 condEst_ (-Teuchos::ScalarTraits<magnitude_type>::one ()) 00064 { 00065 } 00066 00067 template<class MatrixType> 00068 IdentitySolver<MatrixType>::~IdentitySolver () 00069 { 00070 } 00071 00072 template<class MatrixType> 00073 void IdentitySolver<MatrixType>::setParameters (const Teuchos::ParameterList& /*params*/) 00074 { 00075 } 00076 00077 template<class MatrixType> 00078 void IdentitySolver<MatrixType>::initialize () 00079 { 00080 TEUCHOS_TEST_FOR_EXCEPTION( 00081 matrix_.is_null (), std::runtime_error, "Ifpack2::IdentitySolver: " 00082 "You must call setMatrix() with a nonnull input matrix " 00083 "before you may call initialize() or compute()."); 00084 00085 TEUCHOS_TEST_FOR_EXCEPTION( 00086 ! matrix_->getDomainMap ()->isCompatible (* (matrix_->getRangeMap ())), 00087 std::invalid_argument, 00088 "Ifpack2::IdentitySolver: The domain and range Maps " 00089 "of the input matrix must be compatible."); 00090 00091 // If the domain and range Maps are not the same, then we need to 00092 // construct an Export from the domain Map to the range Map, so that 00093 // this operator is really the identity and not a permutation. 00094 if (! matrix_->getDomainMap ()->isSameAs (* (matrix_->getRangeMap ()))) { 00095 export_ = Teuchos::rcp (new export_type (matrix_->getDomainMap (), 00096 matrix_->getRangeMap ())); 00097 } 00098 else { 00099 // If the Export is null, we won't do the Export in apply(). 00100 // Thus, we need to set it to null here as a flag. 00101 export_ = Teuchos::null; 00102 } 00103 00104 isInitialized_ = true; 00105 ++numInitialize_; 00106 } 00107 00108 template<class MatrixType> 00109 void IdentitySolver<MatrixType>::compute () 00110 { 00111 TEUCHOS_TEST_FOR_EXCEPTION( 00112 matrix_.is_null (), std::runtime_error, "Ifpack2::IdentitySolver: " 00113 "You must call setMatrix() with a nonnull input matrix " 00114 "before you may call initialize() or compute()."); 00115 00116 if (! isInitialized_) { 00117 initialize (); 00118 } 00119 00120 isComputed_ = true; 00121 ++numCompute_; 00122 } 00123 00124 template<class MatrixType> 00125 void IdentitySolver<MatrixType>:: 00126 apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X, 00127 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y, 00128 Teuchos::ETransp /*mode*/, 00129 scalar_type alpha, 00130 scalar_type beta) const 00131 { 00132 using Teuchos::RCP; 00133 typedef Teuchos::ScalarTraits<scalar_type> STS; 00134 typedef Tpetra::MultiVector<scalar_type, local_ordinal_type, 00135 global_ordinal_type, node_type> MV; 00136 00137 TEUCHOS_TEST_FOR_EXCEPTION( 00138 ! isComputed (), std::runtime_error, 00139 "Ifpack2::IdentitySolver::apply: If compute() has not yet been called, " 00140 "or if you have changed the matrix via setMatrix(), " 00141 "you must call compute() before you may call this method."); 00142 00143 // "Identity solver" does what it says: it's the identity operator. 00144 // We have to Export if the domain and range Maps are not the same. 00145 // Otherwise, this operator would be a permutation, not the identity. 00146 if (export_.is_null ()) { 00147 Y.update (alpha, X, beta); 00148 } 00149 else { 00150 if (alpha == STS::one () && beta == STS::zero ()) { // the common case 00151 Y.doExport (X, *export_, Tpetra::REPLACE); 00152 } 00153 else { 00154 // We know that the domain and range Maps are compatible. First 00155 // bring X into the range Map via Export. Then compute in place 00156 // in Y. 00157 MV X_tmp (Y.getMap (), Y.getNumVectors ()); 00158 X_tmp.doExport (X, *export_, Tpetra::REPLACE); 00159 Y.update (alpha, X_tmp, beta); 00160 } 00161 } 00162 ++numApply_; 00163 } 00164 00165 template<class MatrixType> 00166 typename IdentitySolver<MatrixType>::magnitude_type 00167 IdentitySolver<MatrixType>:: 00168 computeCondEst (CondestType CT, 00169 local_ordinal_type MaxIters, 00170 magnitude_type Tol, 00171 const Teuchos::Ptr<const row_matrix_type>& matrix) 00172 { 00173 // Forestall compiler warnings for unused variables. 00174 (void) CT; 00175 (void) MaxIters; 00176 (void) Tol; 00177 (void) matrix; 00178 00179 return -Teuchos::ScalarTraits<magnitude_type>::one (); 00180 } 00181 00182 template <class MatrixType> 00183 int IdentitySolver<MatrixType>::getNumInitialize() const { 00184 return(numInitialize_); 00185 } 00186 00187 template <class MatrixType> 00188 int IdentitySolver<MatrixType>::getNumCompute() const { 00189 return(numCompute_); 00190 } 00191 00192 template <class MatrixType> 00193 int IdentitySolver<MatrixType>::getNumApply() const { 00194 return(numApply_); 00195 } 00196 00197 template <class MatrixType> 00198 double IdentitySolver<MatrixType>::getInitializeTime() const { 00199 return(initializeTime_); 00200 } 00201 00202 template<class MatrixType> 00203 double IdentitySolver<MatrixType>::getComputeTime() const { 00204 return(computeTime_); 00205 } 00206 00207 template<class MatrixType> 00208 double IdentitySolver<MatrixType>::getApplyTime() const { 00209 return(applyTime_); 00210 } 00211 00212 template <class MatrixType> 00213 std::string IdentitySolver<MatrixType>::description () const 00214 { 00215 std::ostringstream os; 00216 00217 // Output is a valid YAML dictionary in flow style. If you don't 00218 // like everything on a single line, you should call describe() 00219 // instead. 00220 os << "\"Ifpack2::IdentitySolver\": {"; 00221 if (this->getObjectLabel () != "") { 00222 os << "Label: \"" << this->getObjectLabel () << "\", "; 00223 } 00224 os << "Initialized: " << (isInitialized () ? "true" : "false") << ", " 00225 << "Computed: " << (isComputed () ? "true" : "false") << ", "; 00226 00227 if (matrix_.is_null ()) { 00228 os << "Matrix: null"; 00229 } 00230 else { 00231 os << "Matrix: not null" 00232 << ", Global matrix dimensions: [" 00233 << matrix_->getGlobalNumRows () << ", " 00234 << matrix_->getGlobalNumCols () << "]"; 00235 } 00236 00237 os << "}"; 00238 return os.str (); 00239 } 00240 00241 template <class MatrixType> 00242 void IdentitySolver<MatrixType>:: 00243 describe (Teuchos::FancyOStream& out, 00244 const Teuchos::EVerbosityLevel verbLevel) const 00245 { 00246 using std::endl; 00247 const Teuchos::EVerbosityLevel vl 00248 = (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel; 00249 00250 if (vl != Teuchos::VERB_NONE) { 00251 // By convention, describe() should always begin with a tab. 00252 Teuchos::OSTab tab0 (out); 00253 out << "\"Ifpack2::IdentitySolver\":" << endl; 00254 Teuchos::OSTab tab1 (out); 00255 out << "MatrixType: " << Teuchos::TypeNameTraits<MatrixType>::name () << endl; 00256 out << "numInitialize: " << numInitialize_ << endl; 00257 out << "numCompute: " << numCompute_ << endl; 00258 out << "numApply: " << numApply_ << endl; 00259 } 00260 } 00261 00262 template <class MatrixType> 00263 Teuchos::RCP<const typename IdentitySolver<MatrixType>::map_type> IdentitySolver<MatrixType>::getDomainMap() const 00264 { 00265 TEUCHOS_TEST_FOR_EXCEPTION( 00266 matrix_.is_null (), std::runtime_error, "Ifpack2::IdentitySolver::getDomainMap: " 00267 "The matrix is null. Please call setMatrix() with a nonnull input " 00268 "before calling this method."); 00269 return matrix_->getDomainMap (); 00270 } 00271 00272 template <class MatrixType> 00273 Teuchos::RCP<const typename IdentitySolver<MatrixType>::map_type> IdentitySolver<MatrixType>::getRangeMap() const 00274 { 00275 TEUCHOS_TEST_FOR_EXCEPTION( 00276 matrix_.is_null (), std::runtime_error, "Ifpack2::IdentitySolver::getRangeMap: " 00277 "The matrix is null. Please call setMatrix() with a nonnull input " 00278 "before calling this method."); 00279 return matrix_->getRangeMap (); 00280 } 00281 00282 template<class MatrixType> 00283 void IdentitySolver<MatrixType>:: 00284 setMatrix (const Teuchos::RCP<const row_matrix_type>& A) 00285 { 00286 // Check in serial or one-process mode if the matrix is square. 00287 TEUCHOS_TEST_FOR_EXCEPTION( 00288 ! A.is_null () && A->getComm ()->getSize () == 1 && 00289 A->getNodeNumRows () != A->getNodeNumCols (), 00290 std::runtime_error, "Ifpack2::IdentitySolver::setMatrix: If A's communicator only " 00291 "contains one process, then A must be square. Instead, you provided a " 00292 "matrix A with " << A->getNodeNumRows () << " rows and " 00293 << A->getNodeNumCols () << " columns."); 00294 00295 // It's legal for A to be null; in that case, you may not call 00296 // initialize() until calling setMatrix() with a nonnull input. 00297 // Regardless, setting the matrix invalidates the preconditioner. 00298 isInitialized_ = false; 00299 isComputed_ = false; 00300 export_ = Teuchos::null; 00301 00302 matrix_ = A; 00303 } 00304 00305 } // namespace Ifpack2 00306 00307 #define IFPACK2_IDENTITYSOLVER_INSTANT(S,LO,GO,N) \ 00308 template class Ifpack2::IdentitySolver< Tpetra::CrsMatrix<S, LO, GO, N> >; \ 00309 template class Ifpack2::IdentitySolver< Tpetra::RowMatrix<S, LO, GO, N> >; 00310 00311 #endif // IFPACK2_IDENTITY_SOLVER_DEF_HPP
1.7.6.1