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 }