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