00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "TSFEpetraMatrix.hpp"
00030 #include "TSFEpetraVector.hpp"
00031 #include "TSFVectorSpaceDecl.hpp"
00032 #include "TSFVectorDecl.hpp"
00033 #include "TSFLinearOperatorDecl.hpp"
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