TSFEpetraMatrix.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 /* ***********************************************************************
00003 // 
00004 //           TSFExtended: Trilinos Solver Framework Extended
00005 //                 Copyright (2004) 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 #include "TSFEpetraMatrix.hpp"
00030 #include "TSFEpetraVector.hpp"
00031 #include "TSFVectorSpaceDecl.hpp"  // changed from Impl
00032 #include "TSFVectorDecl.hpp"
00033 #include "TSFLinearOperatorDecl.hpp"  // changed from Impl
00034 #include "TSFIfpackOperator.hpp"
00035 #include "TSFPreconditioner.hpp"
00036 #include "TSFGenericLeftPreconditioner.hpp"
00037 #include "TSFGenericRightPreconditioner.hpp"
00038 #include "Thyra_VectorStdOps.hpp"
00039 #include "Teuchos_dyn_cast.hpp"
00040 #include "Teuchos_getConst.hpp"
00041 #include "Teuchos_Array.hpp"
00042 #include "Teuchos_MPIComm.hpp"
00043 
00044 #include "Thyra_EpetraThyraWrappers.hpp"
00045 
00046 
00047 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00048 #include "TSFVectorImpl.hpp"
00049 #include "TSFLinearOperatorImpl.hpp"
00050 #endif
00051 
00052 using namespace TSFExtended;
00053 using namespace Teuchos;
00054 using namespace Thyra;
00055 
00056 EpetraMatrix::EpetraMatrix(const Epetra_CrsGraph& graph,
00057   const RCP<const EpetraVectorSpace>& domain,
00058   const RCP<const EpetraVectorSpace>& range)
00059   : matrix_(rcp(new Epetra_CrsMatrix(Copy, graph))),
00060     range_(range),
00061     domain_(domain)
00062 {}
00063 
00064 EpetraMatrix::EpetraMatrix(const RCP<Epetra_CrsMatrix>& mat,
00065   const RCP<const EpetraVectorSpace>& domain,
00066   const RCP<const EpetraVectorSpace>& range)
00067   : matrix_(mat),
00068     range_(range),
00069     domain_(domain)
00070 {}
00071 
00072 
00073 bool EpetraMatrix::opSupportedImpl(Thyra::EOpTransp M_trans) const
00074 {
00075   return true;
00076 }
00077 
00078 
00079 void EpetraMatrix::applyImpl(
00080   const Thyra::EOpTransp M_trans,
00081   const Thyra::MultiVectorBase<double> &X,
00082   const Teuchos::Ptr<Thyra::MultiVectorBase<double> > &Y,
00083   const double alpha,
00084   const double beta
00085   ) const
00086 {
00087 
00088   using Teuchos::rcp_dynamic_cast;
00089 
00090   const OrdType numMvCols = X.domain()->dim();
00091 
00092   for (OrdType col_j = 0; col_j < numMvCols; ++col_j) {
00093 
00094     const RCP<const VectorBase<double> > x = X.col(col_j);
00095     const RCP<VectorBase<double> > y = Y->col(col_j);
00096 
00097     const RCP<const EpetraVector> tx = rcp_dynamic_cast<const EpetraVector>(x, true);
00098     const RCP<EpetraVector> ty = rcp_dynamic_cast<EpetraVector>(y, true);
00099 
00100     const Epetra_Vector* epx = tx->epetraVec().get();
00101     Epetra_Vector* epy = ty->epetraVec().get();
00102     
00103     bool trans = M_trans==Thyra::TRANS;
00104     int ierr=0;
00105     if (beta==0.0)
00106     {
00107       ierr = matrix_->Multiply(trans, *epx, *epy);
00108       TEST_FOR_EXCEPTION(ierr < 0, std::runtime_error, 
00109         "EpetraMatrix::generalApply() detected ierr="
00110         << ierr << " in matrix_->Multiply()");
00111       if (alpha != 1.0)
00112       {
00113         Thyra::Vt_S(y.ptr(), alpha);
00114       }
00115     }
00116     else
00117     {
00118       Epetra_Vector tmp(M_trans == NOTRANS 
00119         ? matrix_->OperatorRangeMap() 
00120         : matrix_->OperatorDomainMap(), 
00121         false);
00122       ierr = matrix_->Multiply(trans, *epx, tmp);
00123       TEST_FOR_EXCEPTION(ierr < 0, std::runtime_error, 
00124         "EpetraMatrix::generalApply() detected ierr="
00125         << ierr << " in matrix_->Multiply()");
00126       epy->Update(alpha, tmp, beta);
00127       TEST_FOR_EXCEPTION(ierr < 0, std::runtime_error, 
00128         "EpetraMatrix::generalApply() detected ierr="
00129         << ierr << " in epy->update()");
00130     }
00131 
00132   }
00133 
00134 }
00135 
00136 
00137 void EpetraMatrix::getNonconstEpetraOpView(
00138   const Teuchos::Ptr<Teuchos::RCP<Epetra_Operator> > &epetraOp,
00139   const Teuchos::Ptr<Thyra::EOpTransp> &epetraOpTransp,
00140   const Teuchos::Ptr<Thyra::EApplyEpetraOpAs> &epetraOpApplyAs,
00141   const Teuchos::Ptr<Thyra::EAdjointEpetraOp> &epetraOpAdjointSupport
00142   )
00143 {
00144   *epetraOp = rcp_dynamic_cast<Epetra_Operator>(matrix_);
00145   *epetraOpTransp = NOTRANS;
00146   *epetraOpApplyAs = EPETRA_OP_APPLY_APPLY;
00147   *epetraOpAdjointSupport = EPETRA_OP_ADJOINT_SUPPORTED;
00148   TEST_FOR_EXCEPTION(epetraOp->get()==0, std::runtime_error,
00149     "null operator in getEpetraOpView()");
00150 }
00151 
00152 
00153 void EpetraMatrix::getEpetraOpView(
00154   const Teuchos::Ptr<Teuchos::RCP<const Epetra_Operator> > &epetraOp,
00155   const Teuchos::Ptr<Thyra::EOpTransp> &epetraOpTransp,
00156   const Teuchos::Ptr<Thyra::EApplyEpetraOpAs> &epetraOpApplyAs,
00157   const Teuchos::Ptr<Thyra::EAdjointEpetraOp> &epetraOpAdjointSupport
00158   ) const
00159 {
00160   *epetraOp = rcp_dynamic_cast<const Epetra_Operator>(matrix_);
00161   *epetraOpTransp = NOTRANS;
00162   *epetraOpApplyAs = EPETRA_OP_APPLY_APPLY;
00163   *epetraOpAdjointSupport = EPETRA_OP_ADJOINT_SUPPORTED;
00164   TEST_FOR_EXCEPTION(epetraOp->get()==0, std::runtime_error,
00165     "null operator in getEpetraOpView()");
00166 }
00167 
00168 
00169 RCP<const ScalarProdVectorSpaceBase<double> >
00170 EpetraMatrix::rangeScalarProdVecSpc() const
00171 {
00172   return rcp_dynamic_cast<const ScalarProdVectorSpaceBase<double> >(range_);
00173 }
00174 
00175 
00176 RCP<const ScalarProdVectorSpaceBase<double> >
00177 EpetraMatrix::domainScalarProdVecSpc() const
00178 {
00179   return rcp_dynamic_cast<const ScalarProdVectorSpaceBase<double> >(domain_);
00180 }
00181 
00182 
00183 void EpetraMatrix::addToRow(int globalRowIndex,
00184   int nElemsToInsert,
00185   const int* globalColumnIndices,
00186   const double* elementValues)
00187 {
00188   int ierr = crsMatrix()->SumIntoGlobalValues(globalRowIndex,
00189     nElemsToInsert,
00190     (double*) elementValues,
00191     (int*) globalColumnIndices);
00192 
00193   TEST_FOR_EXCEPTION(ierr < 0, std::runtime_error, 
00194     "failed to add to row " << globalRowIndex
00195     << " in EpetraMatrix::addToRow() with nnz="
00196     << nElemsToInsert 
00197     << ". Error code was " << ierr);
00198 }
00199 
00200 void EpetraMatrix::addToElementBatch(int numRows, 
00201   int rowBlockSize,
00202   const int* globalRowIndices,
00203   int numColumnsPerRow,
00204   const int* globalColumnIndices,
00205   const double* values,
00206   const int* skipRow)
00207 {
00208   Epetra_CrsMatrix* crs = crsMatrix();
00209 
00210   int numRowBlocks = numRows/rowBlockSize;
00211   int row = 0;
00212 
00213   for (int rb=0; rb<numRowBlocks; rb++)
00214   {
00215     const int* cols = globalColumnIndices + rb*numColumnsPerRow;
00216     for (int r=0; r<rowBlockSize; r++, row++)
00217     {
00218       if (skipRow[row]) continue;
00219       const double* rowVals = values + row*numColumnsPerRow;
00220       int ierr=crs->SumIntoGlobalValues(globalRowIndices[row], 
00221         numColumnsPerRow,
00222         (double*) rowVals,
00223         (int*) cols);
00224       TEST_FOR_EXCEPTION(ierr < 0, std::runtime_error, 
00225         "failed to add to row " << globalRowIndices[row]
00226         << " in EpetraMatrix::addToRow() with nnz="
00227         << numColumnsPerRow
00228         << ". Error code was " << ierr);
00229     }
00230   }
00231 }
00232 
00233 
00234 void EpetraMatrix::zero()
00235 {
00236   crsMatrix()->PutScalar(0.0);
00237 }
00238 
00239 
00240 
00241 void EpetraMatrix::getILUKPreconditioner(int fillLevels,
00242   int overlapFill,
00243   double relaxationValue,
00244   double relativeThreshold,
00245   double absoluteThreshold,
00246   LeftOrRight leftOrRight,
00247   Preconditioner<double>& rtn) const
00248 {
00249   RCP<LinearOpBase<double> > a = rcp(new IfpackOperator(this, 
00250       fillLevels,
00251       overlapFill,
00252       relaxationValue,
00253       relativeThreshold,
00254       absoluteThreshold));
00255 
00256   LinearOperator<double> ilu = a;
00257 
00258 
00259   if (leftOrRight == Left)
00260   {
00261     rtn = new GenericLeftPreconditioner<double>(ilu);
00262   }
00263   else
00264   {
00265     rtn = new GenericRightPreconditioner<double>(ilu);
00266   }
00267 }
00268 
00269 
00270 void EpetraMatrix::print(std::ostream& os) const 
00271 {
00272   crsMatrix()->Print(os);
00273 }
00274 
00275 
00276 string EpetraMatrix::description() const 
00277 {
00278   if (name() != "") return name();
00279   std::string rtn = "EpetraMatrix[nRow=" 
00280     + Teuchos::toString(crsMatrix()->NumGlobalRows())
00281     + ", nCol=" + Teuchos::toString(crsMatrix()->NumGlobalCols())
00282     + "]";
00283   return rtn;
00284 }
00285 
00286 
00287 Epetra_CrsMatrix* EpetraMatrix::crsMatrix()
00288 {
00289   return matrix_.get();
00290 }
00291 
00292 
00293 const Epetra_CrsMatrix* EpetraMatrix::crsMatrix() const 
00294 {
00295   return matrix_.get();
00296 }
00297 
00298 
00299 Epetra_CrsMatrix& EpetraMatrix::getConcrete(const LinearOperator<double>& A)
00300 {
00301   return *Teuchos::dyn_cast<EpetraMatrix>(*A.ptr()).crsMatrix();
00302 }
00303 
00304 
00305 RCP<const Epetra_CrsMatrix>
00306 EpetraMatrix::getConcretePtr(const LinearOperator<double>& A)
00307 {
00308   return Teuchos::rcp_dynamic_cast<EpetraMatrix>(A.ptr())->matrix_;
00309 }
00310 
00311 
00312 void EpetraMatrix::getRow(const int& row, 
00313   Teuchos::Array<int>& indices, 
00314   Teuchos::Array<double>& values) const
00315 {
00316   const Epetra_CrsMatrix* crs = crsMatrix();
00317 
00318   int numEntries;
00319   int* epIndices;
00320   double* epValues;
00321 
00322   int info = crs->ExtractGlobalRowView(row, numEntries, epValues, epIndices);
00323   TEST_FOR_EXCEPTION(info != 0, std::runtime_error,
00324     "call to ExtractGlobalRowView not successful");
00325 
00326   indices.resize(numEntries);
00327   values.resize(numEntries);
00328   for (int i = 0; i < numEntries; i++)
00329   {
00330     indices[i] = *epIndices;
00331     values[i] = *epValues;
00332     epIndices++;
00333     epValues++;
00334   }
00335 }
00336 
00337 
00338 const Epetra_Map& EpetraMatrix::getRangeMap() const
00339 {
00340   return matrix_->OperatorRangeMap();
00341 }
00342 
00343 const Epetra_Map& EpetraMatrix::getDomainMap() const
00344 {
00345   return matrix_->OperatorDomainMap();
00346 }
00347 
00348 
00349 

Site Contact