Go to the documentation of this file.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
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "PlayaEpetraMatrix.hpp"
00043 #include "PlayaEpetraVector.hpp"
00044 #include "PlayaVectorSpaceDecl.hpp"
00045 #include "PlayaVectorDecl.hpp"
00046 #include "PlayaLinearOperatorDecl.hpp"
00047 #include "Teuchos_Array.hpp"
00048 #include "PlayaMPIComm.hpp"
00049 #include "PlayaIfpackILUOperator.hpp"
00050 #include "PlayaGenericLeftPreconditioner.hpp"
00051 #include "PlayaGenericRightPreconditioner.hpp"
00052 #include "Teuchos_dyn_cast.hpp"
00053 #include "Teuchos_getConst.hpp"
00054 #include "EpetraPlayaOperator.hpp"
00055 #include "Epetra_Comm.h"
00056 #include "Epetra_CrsMatrix.h"
00057
00058
00059 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00060 #include "PlayaVectorImpl.hpp"
00061 #include "PlayaLinearCombinationImpl.hpp"
00062 #include "PlayaLinearOperatorImpl.hpp"
00063 #include "PlayaLinearSolverImpl.hpp"
00064 #endif
00065
00066 using namespace Playa;
00067 using namespace Teuchos;
00068
00069 namespace Epetra
00070 {
00071
00072 Epetra_PlayaOperator::Epetra_PlayaOperator(const LinearOperator<double>& A,
00073 const LinearSolver<double>& solver)
00074 : A_(A), solver_(solver), useTranspose_(false), comm_(), domain_(), range_(),
00075 isNativeEpetra_(false), isCompoundEpetra_(false), label_(A.description())
00076 {
00077 const EpetraMatrix* em = dynamic_cast<const EpetraMatrix*>(A.ptr().get());
00078 const EpetraVectorSpace* ed = dynamic_cast<const EpetraVectorSpace*>(A.domain().ptr().get());
00079 const EpetraVectorSpace* er = dynamic_cast<const EpetraVectorSpace*>(A.range().ptr().get());
00080
00081 if (em)
00082 {
00083 isNativeEpetra_ = true;
00084 const Epetra_CrsMatrix* crs = em->crsMatrix();
00085 domain_ = rcp(new Epetra_Map(crs->OperatorDomainMap()));
00086 range_ = rcp(new Epetra_Map(crs->OperatorRangeMap()));
00087 useTranspose_ = crs->UseTranspose();
00088 comm_ = rcp(crs->Comm().Clone());
00089 }
00090 else if (er != 0 && ed != 0)
00091 {
00092 domain_ = ed->epetraMap();
00093 range_ = er->epetraMap();
00094 comm_ = rcp(domain_->Comm().Clone());
00095 isCompoundEpetra_ = true;
00096 }
00097 else
00098 {
00099 TEUCHOS_TEST_FOR_EXCEPT(true);
00100 }
00101 }
00102
00103
00104 int Epetra_PlayaOperator::Apply(const Epetra_MultiVector& in, Epetra_MultiVector& out) const
00105 {
00106 if (isNativeEpetra_)
00107 {
00108 const EpetraMatrix* em = dynamic_cast<const EpetraMatrix*>(A_.ptr().get());
00109 return em->crsMatrix()->Multiply(useTranspose_, in, out);
00110 }
00111 else if (isCompoundEpetra_)
00112 {
00113 const Epetra_Vector* cevIn = dynamic_cast<const Epetra_Vector*>(&in);
00114 Epetra_Vector* evIn = const_cast<Epetra_Vector*>(cevIn);
00115 Epetra_Vector* evOut = dynamic_cast<Epetra_Vector*>(&out);
00116 TEUCHOS_TEST_FOR_EXCEPTION(evIn==0, std::runtime_error, "Epetra_PlayaOperator::Apply "
00117 "cannot deal with multivectors");
00118 TEUCHOS_TEST_FOR_EXCEPTION(evOut==0, std::runtime_error, "Epetra_PlayaOperator::Apply "
00119 "cannot deal with multivectors");
00120
00121
00122 RCP<VectorBase<double> > vpIn
00123 = rcp(new EpetraVector(A_.domain(), rcp(evIn, false)));
00124 RCP<VectorBase<double> > vpOut
00125 = rcp(new EpetraVector(A_.range(), rcp(evOut, false)));
00126 Vector<double> vIn = vpIn;
00127 Vector<double> vOut = vpOut;
00128
00129 A_.apply(vIn, vOut);
00130 out = EpetraVector::getConcrete(vOut);
00131 return 0;
00132 }
00133 else
00134 {
00135 TEUCHOS_TEST_FOR_EXCEPT(true);
00136 return -1;
00137 }
00138 }
00139
00140 int Epetra_PlayaOperator::ApplyInverse(const Epetra_MultiVector& in, Epetra_MultiVector& out) const
00141 {
00142
00143 TEUCHOS_TEST_FOR_EXCEPTION(solver_.ptr().get()==0, std::runtime_error,
00144 "no solver provided for Epetra_PlayaOperator::ApplyInverse");
00145 TEUCHOS_TEST_FOR_EXCEPTION(!isNativeEpetra_ && !isCompoundEpetra_, std::runtime_error,
00146 "Epetra_PlayaOperator::ApplyInverse expects either "
00147 "a native epetra operator or a compound operator with "
00148 "Epetra domain and range spaces");
00149 const Epetra_Vector* cevIn = dynamic_cast<const Epetra_Vector*>(&in);
00150 Epetra_Vector* evIn = const_cast<Epetra_Vector*>(cevIn);
00151 Epetra_Vector* evOut = dynamic_cast<Epetra_Vector*>(&out);
00152
00153 TEUCHOS_TEST_FOR_EXCEPTION(evIn==0, std::runtime_error, "Epetra_PlayaOperator::Apply "
00154 "cannot deal with multivectors");
00155 TEUCHOS_TEST_FOR_EXCEPTION(evOut==0, std::runtime_error, "Epetra_PlayaOperator::Apply "
00156 "cannot deal with multivectors");
00157
00158 RCP<VectorBase<double> > vpIn
00159 = rcp(new EpetraVector(A_.domain(),
00160 rcp(evIn, false)));
00161 RCP<VectorBase<double> > vpOut
00162 = rcp(new EpetraVector(A_.range(),
00163 rcp(evOut, false)));
00164 Vector<double> vIn = vpIn;
00165 Vector<double> vOut = vpOut;
00166
00167 SolverState<double> state = solver_.solve(A_, vIn, vOut);
00168
00169 if (state.finalState() == SolveCrashed) return -1;
00170 else if (state.finalState() == SolveFailedToConverge) return -2;
00171 else out = EpetraVector::getConcrete(vOut);
00172
00173 return 0;
00174 }
00175
00176
00177
00178
00179 double Epetra_PlayaOperator::NormInf() const
00180 {
00181 TEUCHOS_TEST_FOR_EXCEPT(true);
00182 return -1;
00183 }
00184
00185 const char* Epetra_PlayaOperator::Label() const
00186 {
00187 return label_.c_str();
00188 }
00189
00190 }