|
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 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00025 // 00026 // *********************************************************************** 00027 //@HEADER 00028 */ 00029 00030 #ifndef IFPACK2_SINGLETONFILTER_DEF_HPP 00031 #define IFPACK2_SINGLETONFILTER_DEF_HPP 00032 #include "Ifpack2_SingletonFilter_decl.hpp" 00033 00034 #include "Tpetra_ConfigDefs.hpp" 00035 #include "Tpetra_RowMatrix.hpp" 00036 #include "Tpetra_Map.hpp" 00037 #include "Tpetra_MultiVector.hpp" 00038 #include "Tpetra_Vector.hpp" 00039 00040 namespace Ifpack2 { 00041 00042 //========================================================================== 00043 template<class MatrixType> 00044 SingletonFilter<MatrixType>::SingletonFilter(const Teuchos::RCP<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >& Matrix): 00045 A_(Matrix), 00046 NumSingletons_(0), 00047 NumRows_(0), 00048 NumNonzeros_(0), 00049 MaxNumEntries_(0), 00050 MaxNumEntriesA_(0) 00051 { 00052 00053 // use this filter only on serial matrices 00054 if (A_->getComm()->getSize() != 1 || A_->getNodeNumRows() != A_->getGlobalNumRows()) { 00055 throw std::runtime_error("Ifpack2::SingeltonFilter can be used with Comm().getSize() == 1 only. This class is a tool for Ifpack2_AdditiveSchwarz, and it is not meant to be used otherwise."); 00056 } 00057 00058 // Number of rows in A 00059 size_t NumRowsA_ = A_->getNodeNumRows(); 00060 00061 // tentative value for MaxNumEntries. This is the number of 00062 // nonzeros in the local matrix 00063 MaxNumEntriesA_ = A_->getNodeMaxNumRowEntries(); 00064 00065 // ExtractMyRowCopy() will use these vectors 00066 Indices_.resize(MaxNumEntriesA_); 00067 Values_.resize(MaxNumEntriesA_); 00068 00069 // Initialize reordering vector to -1 00070 Reorder_.resize(NumRowsA_); 00071 Reorder_.assign(Reorder_.size(),-1); 00072 00073 // first check how may singletons I do have 00074 NumRows_=0; 00075 for (size_t i = 0 ; i < NumRowsA_ ; ++i) { 00076 size_t Nnz; 00077 A_->getLocalRowCopy(i,Indices_,Values_,Nnz); 00078 if (Nnz != 1) { 00079 Reorder_[i] = NumRows_++; 00080 } 00081 else { 00082 NumSingletons_++; 00083 } 00084 } 00085 00086 // build the inverse reordering 00087 InvReorder_.resize(NumRows_); 00088 for (size_t i = 0 ; i < NumRowsA_ ; ++i) { 00089 if (Reorder_[i] < 0) 00090 continue; 00091 InvReorder_[Reorder_[i]] = i; 00092 } 00093 NumEntries_.resize(NumRows_); 00094 SingletonIndex_.resize(NumSingletons_); 00095 00096 00097 // now compute the nonzeros per row 00098 size_t count = 0; 00099 for (size_t i = 0 ; i < NumRowsA_ ; ++i) { 00100 size_t Nnz; 00101 A_->getLocalRowCopy(i,Indices_,Values_,Nnz); 00102 LocalOrdinal ii = Reorder_[i]; 00103 if (ii >= 0) { 00104 NumEntries_[ii] = Nnz; 00105 NumNonzeros_ += Nnz; 00106 if (Nnz > MaxNumEntries_) 00107 MaxNumEntries_ = Nnz; 00108 } 00109 else { 00110 SingletonIndex_[count] = i; 00111 count++; 00112 } 00113 } 00114 00115 // Build the reduced map. This map should be serial 00116 ReducedMap_ = Teuchos::rcp( new Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node>(NumRows_,0,A_->getComm()) ); 00117 00118 // and finish up with the diagonal entry 00119 Diagonal_ = Teuchos::rcp( new Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(ReducedMap_) ); 00120 00121 Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> DiagonalA(A_->getRowMap()); 00122 A_->getLocalDiagCopy(DiagonalA); 00123 const Teuchos::ArrayRCP<const Scalar> & DiagonalAview = DiagonalA.get1dView(); 00124 for (size_t i = 0 ; i < NumRows_ ; ++i) { 00125 LocalOrdinal ii = InvReorder_[i]; 00126 Diagonal_->replaceLocalValue((LocalOrdinal)i,DiagonalAview[ii]); 00127 } 00128 } 00129 00130 //========================================================================= 00131 template<class MatrixType> 00132 SingletonFilter<MatrixType>::~SingletonFilter() { } 00133 00134 //========================================================================== 00135 template<class MatrixType> 00136 const Teuchos::RCP<const Teuchos::Comm<int> > & SingletonFilter<MatrixType>::getComm() const 00137 { 00138 return A_->getComm(); 00139 } 00140 00141 //========================================================================== 00142 template<class MatrixType> 00143 Teuchos::RCP <typename MatrixType::node_type> SingletonFilter<MatrixType>::getNode() const 00144 { 00145 return A_->getNode(); 00146 } 00147 00148 //========================================================================== 00149 template<class MatrixType> 00150 const Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, 00151 typename MatrixType::global_ordinal_type, 00152 typename MatrixType::node_type> >& 00153 SingletonFilter<MatrixType>::getRowMap() const 00154 { 00155 return ReducedMap_; 00156 } 00157 00158 //========================================================================== 00159 template<class MatrixType> 00160 const Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, 00161 typename MatrixType::global_ordinal_type, 00162 typename MatrixType::node_type> >& 00163 SingletonFilter<MatrixType>::getColMap() const 00164 { 00165 return ReducedMap_; 00166 } 00167 00168 //========================================================================== 00169 template<class MatrixType> 00170 const Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, 00171 typename MatrixType::global_ordinal_type, 00172 typename MatrixType::node_type> >& 00173 SingletonFilter<MatrixType>::getDomainMap() const 00174 { 00175 return ReducedMap_; 00176 } 00177 00178 //========================================================================== 00179 template<class MatrixType> 00180 const Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, 00181 typename MatrixType::global_ordinal_type, 00182 typename MatrixType::node_type> >& 00183 SingletonFilter<MatrixType>::getRangeMap() const 00184 { 00185 return ReducedMap_; 00186 } 00187 00188 //========================================================================== 00189 template<class MatrixType> 00190 Teuchos::RCP<const Tpetra::RowGraph<typename MatrixType::local_ordinal_type, 00191 typename MatrixType::global_ordinal_type, 00192 typename MatrixType::node_type> > 00193 SingletonFilter<MatrixType>::getGraph() const 00194 { 00195 throw std::runtime_error("Ifpack2::SingletonFilter: does not support getGraph."); 00196 } 00197 00198 //========================================================================== 00199 template<class MatrixType> 00200 global_size_t SingletonFilter<MatrixType>::getGlobalNumRows() const 00201 { 00202 return NumRows_; 00203 } 00204 00205 //========================================================================== 00206 template<class MatrixType> 00207 global_size_t SingletonFilter<MatrixType>::getGlobalNumCols() const 00208 { 00209 return NumRows_; 00210 } 00211 00212 //========================================================================== 00213 template<class MatrixType> 00214 size_t SingletonFilter<MatrixType>::getNodeNumRows() const 00215 { 00216 return NumRows_; 00217 } 00218 00219 //========================================================================== 00220 00221 template<class MatrixType> 00222 size_t SingletonFilter<MatrixType>::getNodeNumCols() const 00223 { 00224 return NumRows_; 00225 } 00226 00227 //========================================================================== 00228 template<class MatrixType> 00229 typename MatrixType::global_ordinal_type SingletonFilter<MatrixType>::getIndexBase() const 00230 { 00231 return A_->getIndexBase(); 00232 } 00233 00234 //========================================================================== 00235 template<class MatrixType> 00236 global_size_t SingletonFilter<MatrixType>::getGlobalNumEntries() const 00237 { 00238 return NumNonzeros_; 00239 } 00240 00241 //========================================================================== 00242 template<class MatrixType> 00243 size_t SingletonFilter<MatrixType>::getNodeNumEntries() const 00244 { 00245 return NumNonzeros_; 00246 } 00247 00248 //========================================================================== 00249 template<class MatrixType> 00250 size_t SingletonFilter<MatrixType>::getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const 00251 { 00252 throw std::runtime_error("Ifpack2::SingletonFilter does not implement getNumEntriesInGlobalRow."); 00253 } 00254 00255 //========================================================================== 00256 template<class MatrixType> 00257 size_t SingletonFilter<MatrixType>::getNumEntriesInLocalRow(LocalOrdinal localRow) const 00258 { 00259 return NumEntries_[localRow]; 00260 } 00261 00262 //========================================================================== 00263 template<class MatrixType> 00264 global_size_t SingletonFilter<MatrixType>::getGlobalNumDiags() const 00265 { 00266 return A_->getGlobalNumDiags(); 00267 } 00268 00269 //========================================================================== 00270 template<class MatrixType> 00271 size_t SingletonFilter<MatrixType>::getNodeNumDiags() const 00272 { 00273 return A_->getNodeNumDiags(); 00274 } 00275 00276 //========================================================================== 00277 template<class MatrixType> 00278 size_t SingletonFilter<MatrixType>::getGlobalMaxNumRowEntries() const 00279 { 00280 return MaxNumEntries_; 00281 } 00282 00283 //========================================================================== 00284 template<class MatrixType> 00285 size_t SingletonFilter<MatrixType>::getNodeMaxNumRowEntries() const 00286 { 00287 return MaxNumEntries_; 00288 } 00289 00290 //========================================================================== 00291 template<class MatrixType> 00292 bool SingletonFilter<MatrixType>::hasColMap() const 00293 { 00294 return true; 00295 } 00296 00297 //========================================================================== 00298 template<class MatrixType> 00299 bool SingletonFilter<MatrixType>::isLowerTriangular() const 00300 { 00301 return A_->isLowerTriangular(); 00302 } 00303 00304 //========================================================================== 00305 template<class MatrixType> 00306 bool SingletonFilter<MatrixType>::isUpperTriangular() const 00307 { 00308 return A_->isUpperTriangular(); 00309 } 00310 00311 //========================================================================== 00312 template<class MatrixType> 00313 bool SingletonFilter<MatrixType>::isLocallyIndexed() const 00314 { 00315 return A_->isLocallyIndexed(); 00316 } 00317 00318 //========================================================================== 00319 template<class MatrixType> 00320 bool SingletonFilter<MatrixType>::isGloballyIndexed() const 00321 { 00322 return A_->isGloballyIndexed(); 00323 } 00324 00325 //========================================================================== 00326 template<class MatrixType> 00327 bool SingletonFilter<MatrixType>::isFillComplete() const 00328 { 00329 return A_->isFillComplete(); 00330 } 00331 00332 //========================================================================== 00333 template<class MatrixType> 00334 void SingletonFilter<MatrixType>::getGlobalRowCopy(GlobalOrdinal GlobalRow, 00335 const Teuchos::ArrayView<GlobalOrdinal> &Indices, 00336 const Teuchos::ArrayView<Scalar> &Values, 00337 size_t &NumEntries) const 00338 { 00339 throw std::runtime_error("Ifpack2::SingletonFilter does not implement getGlobalRowCopy."); 00340 } 00341 00342 //========================================================================== 00343 template<class MatrixType> 00344 void SingletonFilter<MatrixType>::getLocalRowCopy(LocalOrdinal LocalRow, 00345 const Teuchos::ArrayView<LocalOrdinal> &Indices, 00346 const Teuchos::ArrayView<Scalar> &Values, 00347 size_t &NumEntries) const 00348 { 00349 TEUCHOS_TEST_FOR_EXCEPTION((LocalRow < 0 || (size_t) LocalRow >= NumRows_ || (size_t) Indices.size() < NumEntries_[LocalRow]), std::runtime_error, "Ifpack2::SingletonFilter::getLocalRowCopy invalid row or array size."); 00350 00351 size_t Nnz; 00352 LocalOrdinal ARow = InvReorder_[LocalRow]; 00353 A_->getLocalRowCopy(ARow,Indices_(),Values_(),Nnz); 00354 00355 // populate the user's vectors 00356 NumEntries = 0; 00357 for (size_t i = 0 ; i < Nnz ; ++i) { 00358 LocalOrdinal ii = Reorder_[Indices_[i]]; 00359 if ( ii >= 0) { 00360 Indices[NumEntries] = ii; 00361 Values[NumEntries] = Values_[i]; 00362 NumEntries++; 00363 } 00364 } 00365 00366 } 00367 00368 //========================================================================== 00369 template<class MatrixType> 00370 void SingletonFilter<MatrixType>::getGlobalRowView(GlobalOrdinal GlobalRow, 00371 Teuchos::ArrayView<const GlobalOrdinal> &indices, 00372 Teuchos::ArrayView<const Scalar> &values) const 00373 { 00374 throw std::runtime_error("Ifpack2::SingletonFilter: does not support getGlobalRowView."); 00375 } 00376 00377 //========================================================================== 00378 template<class MatrixType> 00379 void SingletonFilter<MatrixType>::getLocalRowView(LocalOrdinal LocalRow, 00380 Teuchos::ArrayView<const LocalOrdinal> &indices, 00381 Teuchos::ArrayView<const Scalar> &values) const 00382 { 00383 throw std::runtime_error("Ifpack2::SingletonFilter: does not support getLocalRowView."); 00384 } 00385 00386 //========================================================================== 00387 template<class MatrixType> 00388 void SingletonFilter<MatrixType>::getLocalDiagCopy(Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> &diag) const 00389 { 00390 // This is somewhat dubious as to how the maps match. 00391 return A_->getLocalDiagCopy(diag); 00392 } 00393 00394 //========================================================================== 00395 template<class MatrixType> 00396 void SingletonFilter<MatrixType>::leftScale(const Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& x) 00397 { 00398 throw std::runtime_error("Ifpack2::SingletonFilter does not support leftScale."); 00399 } 00400 00401 //========================================================================== 00402 template<class MatrixType> 00403 void SingletonFilter<MatrixType>::rightScale(const Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& x) 00404 { 00405 throw std::runtime_error("Ifpack2::SingletonFilter does not support rightScale."); 00406 } 00407 00408 //========================================================================== 00409 template<class MatrixType> 00410 void SingletonFilter<MatrixType>::apply(const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> &X, 00411 Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> &Y, 00412 Teuchos::ETransp mode, 00413 Scalar alpha, 00414 Scalar beta) const 00415 { 00416 // Note: This isn't AztecOO compliant. But neither was Ifpack's version. 00417 00418 TEUCHOS_TEST_FOR_EXCEPTION(X.getNumVectors() != Y.getNumVectors(), std::runtime_error, 00419 "Ifpack2::SingletonFilter::apply ERROR: X.getNumVectors() != Y.getNumVectors()."); 00420 00421 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero(); 00422 Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > x_ptr = X.get2dView(); 00423 Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > y_ptr = Y.get2dViewNonConst(); 00424 00425 Y.putScalar(zero); 00426 size_t NumVectors = Y.getNumVectors(); 00427 00428 00429 for (size_t i = 0 ; i < NumRows_ ; ++i) { 00430 size_t Nnz; 00431 // Use this class's getrow to make the below code simpler 00432 getLocalRowCopy(i,Indices_(),Values_(),Nnz); 00433 if (mode==Teuchos::NO_TRANS){ 00434 for (size_t j = 0 ; j < Nnz ; ++j) 00435 for (size_t k = 0 ; k < NumVectors ; ++k) 00436 y_ptr[k][i] += Values_[j] * x_ptr[k][Indices_[j]]; 00437 } 00438 else if (mode==Teuchos::TRANS){ 00439 for (size_t j = 0 ; j < Nnz ; ++j) 00440 for (size_t k = 0 ; k < NumVectors ; ++k) 00441 y_ptr[k][Indices_[j]] += Values_[j] * x_ptr[k][i]; 00442 } 00443 else { //mode==Teuchos::CONJ_TRANS 00444 for (size_t j = 0 ; j < Nnz ; ++j) 00445 for (size_t k = 0 ; k < NumVectors ; ++k) 00446 y_ptr[k][Indices_[j]] += Teuchos::ScalarTraits<Scalar>::conjugate(Values_[j]) * x_ptr[k][i]; 00447 } 00448 } 00449 } 00450 00451 00452 //========================================================================== 00453 template<class MatrixType> 00454 bool SingletonFilter<MatrixType>::hasTransposeApply() const 00455 { 00456 return true; 00457 } 00458 00459 //============================================================================== 00460 template<class MatrixType> 00461 void SingletonFilter<MatrixType>::SolveSingletons(const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& RHS, 00462 Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& LHS) 00463 { 00464 Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > RHS_ptr = RHS.get2dView(); 00465 Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > LHS_ptr = LHS.get2dViewNonConst(); 00466 00467 for (size_t i = 0 ; i < NumSingletons_ ; ++i) { 00468 LocalOrdinal ii = SingletonIndex_[i]; 00469 // get the diagonal value for the singleton 00470 size_t Nnz; 00471 A_->getLocalRowCopy(ii,Indices_(),Values_(),Nnz); 00472 for (size_t j = 0 ; j < Nnz ; ++j) { 00473 if (Indices_[j] == ii) { 00474 for (size_t k = 0 ; k < LHS.getNumVectors() ; ++k) 00475 LHS_ptr[k][ii] = RHS_ptr[k][ii] / Values_[j]; 00476 } 00477 } 00478 } 00479 } 00480 00481 //============================================================================== 00482 template<class MatrixType> 00483 void SingletonFilter<MatrixType>::CreateReducedRHS(const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& LHS, 00484 const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& RHS, 00485 Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& ReducedRHS) 00486 { 00487 Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > RHS_ptr = RHS.get2dView(); 00488 Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > LHS_ptr = LHS.get2dView(); 00489 Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > ReducedRHS_ptr = ReducedRHS.get2dViewNonConst(); 00490 00491 size_t NumVectors = LHS.getNumVectors(); 00492 00493 for (size_t i = 0 ; i < NumRows_ ; ++i) 00494 for (size_t k = 0 ; k < NumVectors ; ++k) 00495 ReducedRHS_ptr[k][i] = RHS_ptr[k][InvReorder_[i]]; 00496 00497 for (size_t i = 0 ; i < NumRows_ ; ++i) { 00498 LocalOrdinal ii = InvReorder_[i]; 00499 size_t Nnz; 00500 A_->getLocalRowCopy(ii,Indices_(),Values_(),Nnz); 00501 00502 for (size_t j = 0 ; j < Nnz ; ++j) { 00503 if (Reorder_[Indices_[j]] == -1) { 00504 for (size_t k = 0 ; k < NumVectors ; ++k) 00505 ReducedRHS_ptr[k][i] -= Values_[j] * LHS_ptr[k][Indices_[j]]; 00506 } 00507 } 00508 } 00509 } 00510 00511 //============================================================================== 00512 template<class MatrixType> 00513 void SingletonFilter<MatrixType>::UpdateLHS(const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& ReducedLHS, 00514 Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& LHS) 00515 { 00516 00517 Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > LHS_ptr = LHS.get2dViewNonConst(); 00518 Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > ReducedLHS_ptr = ReducedLHS.get2dView(); 00519 00520 for (size_t i = 0 ; i < NumRows_ ; ++i) 00521 for (size_t k = 0 ; k < LHS.getNumVectors() ; ++k) 00522 LHS_ptr[k][InvReorder_[i]] = ReducedLHS_ptr[k][i]; 00523 } 00524 00525 //========================================================================== 00526 template<class MatrixType> 00527 typename Teuchos::ScalarTraits<typename MatrixType::scalar_type>::magnitudeType SingletonFilter<MatrixType>::getFrobeniusNorm() const 00528 { 00529 throw std::runtime_error("Ifpack2::SingletonFilter does not implement getFrobeniusNorm."); 00530 } 00531 00532 //========================================================================== 00533 template<class MatrixType> 00534 TPETRA_DEPRECATED void SingletonFilter<MatrixType>::getGlobalRowView(GlobalOrdinal GlobalRow, 00535 Teuchos::ArrayRCP<const GlobalOrdinal> &indices, 00536 Teuchos::ArrayRCP<const Scalar> &values) const 00537 { 00538 throw std::runtime_error("Ifpack2::SingletonFilter does not implement getGlobalRowView."); 00539 } 00540 00541 //========================================================================== 00542 template<class MatrixType> 00543 TPETRA_DEPRECATED void SingletonFilter<MatrixType>::getLocalRowView(LocalOrdinal LocalRow, 00544 Teuchos::ArrayRCP<const LocalOrdinal> &indices, 00545 Teuchos::ArrayRCP<const Scalar> &values) const 00546 { 00547 throw std::runtime_error("Ifpack2::SingletonFilter does not implement getLocalRowView."); 00548 } 00549 00550 00551 00552 00553 }// namespace Ifpack2 00554 00555 #endif
1.7.6.1