00001
00002 #ifndef __sun
00003
00004 #ifndef THYRA_BELOS_LINEAR_OP_WITH_SOLVE_HPP
00005 #define THYRA_BELOS_LINEAR_OP_WITH_SOLVE_HPP
00006
00007 #include "Thyra_BelosLinearOpWithSolveDecl.hpp"
00008 #include "Teuchos_Time.hpp"
00009
00010 namespace Thyra {
00011
00012 namespace PrivateUtilities {
00013
00014 template<class LP>
00015 class BelosLinearProblemTempBlockSizeSetter {
00016 public:
00017 BelosLinearProblemTempBlockSizeSetter( const Teuchos::RefCountPtr<LP> &lp, const int newBlockSize )
00018 :lp_(lp), oldBlockSize_(lp->GetBlockSize())
00019 {
00020 lp_->SetBlockSize(newBlockSize);
00021 }
00022 ~BelosLinearProblemTempBlockSizeSetter()
00023 {
00024 lp_->SetBlockSize(oldBlockSize_);
00025 }
00026 private:
00027 Teuchos::RefCountPtr<LP> lp_;
00028 int oldBlockSize_;
00029
00030 BelosLinearProblemTempBlockSizeSetter();
00031 BelosLinearProblemTempBlockSizeSetter(const BelosLinearProblemTempBlockSizeSetter&);
00032 BelosLinearProblemTempBlockSizeSetter& operator=(const BelosLinearProblemTempBlockSizeSetter&);
00033 };
00034
00035 }
00036
00037
00038
00039 template<class Scalar>
00040 BelosLinearOpWithSolve<Scalar>::BelosLinearOpWithSolve()
00041 :isExternalPrec_(false)
00042 ,supportSolveUse_(SUPPORT_SOLVE_UNSPECIFIED)
00043 ,defaultTol_(-1.0)
00044 {}
00045
00046 template<class Scalar>
00047 BelosLinearOpWithSolve<Scalar>::BelosLinearOpWithSolve(
00048 const Teuchos::RefCountPtr<Belos::LinearProblem<Scalar,MV_t,LO_t> > &lp
00049 ,const bool adjustableBlockSize
00050 ,const int maxNumberOfKrylovVectors
00051 ,const Teuchos::RefCountPtr<Teuchos::ParameterList> &gmresPL
00052 ,const Teuchos::RefCountPtr<Belos::StatusTestResNorm<Scalar,MV_t,LO_t> > &resNormST
00053 ,const Teuchos::RefCountPtr<Belos::IterativeSolver<Scalar,MV_t,LO_t> > &iterativeSolver
00054 ,const Teuchos::RefCountPtr<Belos::OutputManager<Scalar> > &outputManager
00055 ,const Teuchos::RefCountPtr<const LinearOpSourceBase<Scalar> > &fwdOpSrc
00056 ,const Teuchos::RefCountPtr<const PreconditionerBase<Scalar> > &prec
00057 ,const bool isExternalPrec
00058 ,const Teuchos::RefCountPtr<const LinearOpSourceBase<Scalar> > &approxFwdOpSrc
00059 ,const ESupportSolveUse &supportSolveUse
00060 )
00061 {
00062 initialize(
00063 lp,adjustableBlockSize,maxNumberOfKrylovVectors,gmresPL,resNormST,iterativeSolver
00064 ,outputManager,fwdOpSrc,prec,isExternalPrec,approxFwdOpSrc,supportSolveUse
00065 );
00066 }
00067
00068 template<class Scalar>
00069 void BelosLinearOpWithSolve<Scalar>::initialize(
00070 const Teuchos::RefCountPtr<Belos::LinearProblem<Scalar,MV_t,LO_t> > &lp
00071 ,const bool adjustableBlockSize
00072 ,const int maxNumberOfKrylovVectors
00073 ,const Teuchos::RefCountPtr<Teuchos::ParameterList> &gmresPL
00074 ,const Teuchos::RefCountPtr<Belos::StatusTestResNorm<Scalar,MV_t,LO_t> > &resNormST
00075 ,const Teuchos::RefCountPtr<Belos::IterativeSolver<Scalar,MV_t,LO_t> > &iterativeSolver
00076 ,const Teuchos::RefCountPtr<Belos::OutputManager<Scalar> > &outputManager
00077 ,const Teuchos::RefCountPtr<const LinearOpSourceBase<Scalar> > &fwdOpSrc
00078 ,const Teuchos::RefCountPtr<const PreconditionerBase<Scalar> > &prec
00079 ,const bool isExternalPrec
00080 ,const Teuchos::RefCountPtr<const LinearOpSourceBase<Scalar> > &approxFwdOpSrc
00081 ,const ESupportSolveUse &supportSolveUse
00082 )
00083 {
00084 this->setLinePrefix("BELOS/T");
00085
00086 lp_ = lp;
00087 adjustableBlockSize_ = adjustableBlockSize;
00088 maxNumberOfKrylovVectors_ = maxNumberOfKrylovVectors;
00089 gmresPL_ = gmresPL;
00090 resNormST_ = resNormST;
00091 iterativeSolver_ = iterativeSolver;
00092 outputManager_ = outputManager;
00093 fwdOpSrc_ = fwdOpSrc;
00094 prec_ = prec;
00095 isExternalPrec_ = isExternalPrec;
00096 approxFwdOpSrc_ = approxFwdOpSrc;
00097 supportSolveUse_ = supportSolveUse;
00098 defaultTol_ = resNormST_->GetTolerance();
00099 }
00100
00101 template<class Scalar>
00102 Teuchos::RefCountPtr<const LinearOpSourceBase<Scalar> >
00103 BelosLinearOpWithSolve<Scalar>::extract_fwdOpSrc()
00104 {
00105 Teuchos::RefCountPtr<const LinearOpSourceBase<Scalar> >
00106 _fwdOpSrc = fwdOpSrc_;
00107 fwdOpSrc_ = Teuchos::null;
00108 return _fwdOpSrc;
00109 }
00110
00111 template<class Scalar>
00112 Teuchos::RefCountPtr<const PreconditionerBase<Scalar> >
00113 BelosLinearOpWithSolve<Scalar>::extract_prec()
00114 {
00115 Teuchos::RefCountPtr<const PreconditionerBase<Scalar> >
00116 _prec = prec_;
00117 prec_ = Teuchos::null;
00118 return _prec;
00119 }
00120
00121 template<class Scalar>
00122 bool BelosLinearOpWithSolve<Scalar>::isExternalPrec() const
00123 {
00124 return isExternalPrec_;
00125 }
00126
00127 template<class Scalar>
00128 Teuchos::RefCountPtr<const LinearOpSourceBase<Scalar> >
00129 BelosLinearOpWithSolve<Scalar>::extract_approxFwdOpSrc()
00130 {
00131 Teuchos::RefCountPtr<const LinearOpSourceBase<Scalar> >
00132 _approxFwdOpSrc = approxFwdOpSrc_;
00133 approxFwdOpSrc_ = Teuchos::null;
00134 return _approxFwdOpSrc;
00135 }
00136
00137 template<class Scalar>
00138 ESupportSolveUse BelosLinearOpWithSolve<Scalar>::supportSolveUse() const
00139 {
00140 return supportSolveUse_;
00141 }
00142
00143 template<class Scalar>
00144 void BelosLinearOpWithSolve<Scalar>::uninitialize(
00145 Teuchos::RefCountPtr<Belos::LinearProblem<Scalar,MV_t,LO_t> > *lp
00146 ,bool *adjustableBlockSize
00147 ,int *maxNumberOfKrylovVectors
00148 ,Teuchos::RefCountPtr<Teuchos::ParameterList> *gmresPL
00149 ,Teuchos::RefCountPtr<Belos::StatusTestResNorm<Scalar,MV_t,LO_t> > *resNormST
00150 ,Teuchos::RefCountPtr<Belos::IterativeSolver<Scalar,MV_t,LO_t> > *iterativeSolver
00151 ,Teuchos::RefCountPtr<Belos::OutputManager<Scalar> > *outputManager
00152 ,Teuchos::RefCountPtr<const LinearOpSourceBase<Scalar> > *fwdOpSrc
00153 ,Teuchos::RefCountPtr<const PreconditionerBase<Scalar> > *prec
00154 ,bool *isExternalPrec
00155 ,Teuchos::RefCountPtr<const LinearOpSourceBase<Scalar> > *approxFwdOpSrc
00156 ,ESupportSolveUse *supportSolveUse
00157 )
00158 {
00159 TEST_FOR_EXCEPT(true);
00160 }
00161
00162
00163
00164 template<class Scalar>
00165 Teuchos::RefCountPtr< const VectorSpaceBase<Scalar> >
00166 BelosLinearOpWithSolve<Scalar>::range() const
00167 {
00168 return lp_->GetOperator()->range();
00169 }
00170
00171 template<class Scalar>
00172 Teuchos::RefCountPtr< const VectorSpaceBase<Scalar> >
00173 BelosLinearOpWithSolve<Scalar>::domain() const
00174 {
00175 return lp_->GetOperator()->domain();
00176 }
00177
00178 template<class Scalar>
00179 Teuchos::RefCountPtr<const LinearOpBase<Scalar> >
00180 BelosLinearOpWithSolve<Scalar>::clone() const
00181 {
00182 return Teuchos::null;
00183 }
00184
00185
00186
00187 template<class Scalar>
00188 std::string BelosLinearOpWithSolve<Scalar>::description() const
00189 {
00190 std::ostringstream oss;
00191 oss << "Thyra::BelosLinearOpWithSolve<"<<Teuchos::ScalarTraits<Scalar>::name()<<">";
00192 if(lp_->GetOperator().get()) {
00193 oss << "{";
00194 oss << "iterativeSolver=\'"<<iterativeSolver_->description()<<"\'";
00195 oss << ",fwdOp=\'"<<lp_->GetOperator()->description()<<"\'";
00196 if(lp_->GetLeftPrec().get())
00197 oss << ",leftPrecOp=\'"<<lp_->GetLeftPrec()->description()<<"\'";
00198 if(lp_->GetRightPrec().get())
00199 oss << ",rightPrecOp=\'"<<lp_->GetRightPrec()->description()<<"\'";
00200 oss << "}";
00201 }
00202
00203
00204 return oss.str();
00205 }
00206
00207 template<class Scalar>
00208 void BelosLinearOpWithSolve<Scalar>::describe(
00209 Teuchos::FancyOStream &out_arg
00210 ,const Teuchos::EVerbosityLevel verbLevel
00211 ) const
00212 {
00213 typedef Teuchos::ScalarTraits<Scalar> ST;
00214 using Teuchos::RefCountPtr;
00215 using Teuchos::FancyOStream;
00216 using Teuchos::OSTab;
00217 using Teuchos::describe;
00218 RefCountPtr<FancyOStream> out = rcp(&out_arg,false);
00219 OSTab tab(out);
00220 switch(verbLevel) {
00221 case Teuchos::VERB_DEFAULT:
00222 case Teuchos::VERB_LOW:
00223 *out << this->description() << std::endl;
00224 break;
00225 case Teuchos::VERB_MEDIUM:
00226 case Teuchos::VERB_HIGH:
00227 case Teuchos::VERB_EXTREME:
00228 {
00229 *out
00230 << "type = \'Thyra::BelosLinearOpWithSolve<" << ST::name() << ">\', "
00231 << "rangeDim = " << this->range()->dim() << ", domainDim = " << this->domain()->dim() << std::endl;
00232 if(lp_->GetOperator().get()) {
00233 OSTab tab(out);
00234 *out
00235 << "iterativeSolver:\n"<<describe(*iterativeSolver_,verbLevel)
00236 << "fwdOp:\n" << describe(*lp_->GetOperator(),verbLevel);
00237 if(lp_->GetLeftPrec().get())
00238 *out << "leftPrecOp:\n"<<describe(*lp_->GetLeftPrec(),verbLevel);
00239 if(lp_->GetRightPrec().get())
00240 *out << "rightPrecOp:\n"<<describe(*lp_->GetRightPrec(),verbLevel);
00241 }
00242 break;
00243 }
00244 default:
00245 TEST_FOR_EXCEPT(true);
00246 }
00247 }
00248
00249
00250
00251
00252
00253 template<class Scalar>
00254 bool BelosLinearOpWithSolve<Scalar>::opSupported(ETransp M_trans) const
00255 {
00256 return ::Thyra::opSupported(*lp_->GetOperator(),M_trans);
00257 }
00258
00259 template<class Scalar>
00260 void BelosLinearOpWithSolve<Scalar>::apply(
00261 const ETransp M_trans
00262 ,const MultiVectorBase<Scalar> &X
00263 ,MultiVectorBase<Scalar> *Y
00264 ,const Scalar alpha
00265 ,const Scalar beta
00266 ) const
00267 {
00268 ::Thyra::apply(*lp_->GetOperator(),M_trans,X,Y,alpha,beta);
00269 }
00270
00271
00272
00273 template<class Scalar>
00274 bool BelosLinearOpWithSolve<Scalar>::solveSupportsTrans(ETransp M_trans) const
00275 {
00276 if(real_trans(M_trans)==NOTRANS) return true;
00277 return false;
00278 }
00279
00280 template<class Scalar>
00281 bool BelosLinearOpWithSolve<Scalar>::solveSupportsSolveMeasureType(ETransp M_trans, const SolveMeasureType& solveMeasureType) const
00282 {
00283 if(real_trans(M_trans)==NOTRANS) {
00284 return (
00285 solveMeasureType.useDefault()
00286 ||
00287 (solveMeasureType(SOLVE_MEASURE_NORM_RESIDUAL,SOLVE_MEASURE_NORM_RHS) && resNormST_.get())
00288 );
00289 }
00290
00291 return false;
00292 }
00293
00294 template<class Scalar>
00295 void BelosLinearOpWithSolve<Scalar>::solve(
00296 const ETransp M_trans
00297 ,const MultiVectorBase<Scalar> &B
00298 ,MultiVectorBase<Scalar> *X
00299 ,const int numBlocks
00300 ,const BlockSolveCriteria<Scalar> blockSolveCriteria[]
00301 ,SolveStatus<Scalar> blockSolveStatus[]
00302 ) const
00303 {
00304 using Teuchos::RefCountPtr;
00305 using Teuchos::rcp;
00306 using Teuchos::FancyOStream;
00307 using Teuchos::OSTab;
00308 typedef Teuchos::ScalarTraits<Scalar> ST;
00309 typedef typename ST::magnitudeType ScalarMag;
00310 Teuchos::Time totalTimer(""), timer("");
00311 totalTimer.start(true);
00312
00313 TEST_FOR_EXCEPT(numBlocks > 1);
00314 TEST_FOR_EXCEPT(!this->solveSupportsTrans(M_trans));
00315
00316 const int numRhs = B.domain()->dim();
00317 const int numEquations = B.range()->dim();
00318
00319 Teuchos::RefCountPtr<Teuchos::FancyOStream> out = this->getOStream();
00320 Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00321 OSTab tab = this->getOSTab();
00322 if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_NONE))
00323 *out
00324 << "\nStarting iterations with Belos solver of type \""<<iterativeSolver_->description()<<"\""
00325 << ", #Eqns="<<numEquations<<", #RHSs="<<numRhs<<" ...\n";
00326
00327
00328
00329
00330 const int currBlockSize = lp_->GetBlockSize();
00331 const int newBlockSize =
00332 ( adjustableBlockSize_
00333 ? TEUCHOS_MIN(numRhs,TEUCHOS_MIN(currBlockSize,numEquations/2))
00334
00335
00336
00337 : currBlockSize
00338
00339
00340 );
00341
00342
00343
00344
00345 PrivateUtilities::BelosLinearProblemTempBlockSizeSetter<Belos::LinearProblem<Scalar,MV_t,LO_t> >
00346 tempBlockSizeSetter(lp_,newBlockSize);
00347 if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_NONE))
00348 *out << "\nAdjusted block size = " << newBlockSize << "\n";
00349
00350
00351
00352 if(gmresPL_.get()) {
00353 const int BlockGmres_length = maxNumberOfKrylovVectors_/newBlockSize;
00354 gmresPL_->set("Length",BlockGmres_length);
00355 if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_NONE))
00356 *out
00357 << "\nAdjusted max number of GMRES Krylov basis blocks (maxNumberOfKrylovVectors/blockSize) = ("
00358 << maxNumberOfKrylovVectors_ << ")/(" << newBlockSize << ") = " << BlockGmres_length << "\n";
00359 }
00360
00361
00362
00363 lp_->Reset(Teuchos::rcp(X,false),Teuchos::rcp(&B,false));
00364
00365
00366
00367 SolveMeasureType solveMeasureType;
00368 if(numBlocks==1) {
00369 solveMeasureType = blockSolveCriteria[0].solveCriteria.solveMeasureType;
00370 const ScalarMag requestedTol = blockSolveCriteria[0].solveCriteria.requestedTol;
00371 TEST_FOR_EXCEPT( !( solveMeasureType.useDefault() || solveMeasureType(SOLVE_MEASURE_NORM_RESIDUAL,SOLVE_MEASURE_NORM_RHS) ) );
00372 if( solveMeasureType.useDefault() ) {
00373 resNormST_->ResetTolerance(defaultTol_);
00374 }
00375 else if( solveMeasureType(SOLVE_MEASURE_NORM_RESIDUAL,SOLVE_MEASURE_NORM_RHS) ) {
00376 if( requestedTol != SolveCriteria<Scalar>::unspecifiedTolerance() )
00377 resNormST_->ResetTolerance(requestedTol);
00378 else
00379 resNormST_->ResetTolerance(defaultTol_);
00380 resNormST_->DefineScaleForm(StatusTestResNorm_t::NormOfRHS,Belos::TwoNorm);
00381 }
00382 else {
00383 TEST_FOR_EXCEPT(true);
00384 }
00385 }
00386 else {
00387 resNormST_->ResetTolerance(defaultTol_);
00388 }
00389
00390
00391
00392 iterativeSolver_->GetStatusTest()->Reset();
00393 iterativeSolver_->Reset();
00394 if(1){
00395 RefCountPtr<FancyOStream>
00396 outUsed =
00397 ( static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_NONE)
00398 ? out
00399 : rcp(new FancyOStream(rcp(new Teuchos::oblackholestream())))
00400 );
00401 outputManager_->SetOStream(outUsed);
00402 Teuchos::OSTab tab(outUsed,1,"BELOS");
00403 iterativeSolver_->Solve();
00404 }
00405
00406
00407
00408 totalTimer.stop();
00409 const Belos::StatusType belosSolveStatus = resNormST_->GetStatus();
00410 const std::vector<ScalarMag>* resNormValues = resNormST_->GetTestValue();
00411 TEST_FOR_EXCEPT(resNormValues==NULL);
00412 const ScalarMag belosAchievedTol = *std::max_element(resNormValues->begin(),resNormValues->end());
00413 TEST_FOR_EXCEPTION(
00414 belosSolveStatus==Belos::Failed || belosSolveStatus==Belos::NaN, CatastrophicSolveFailure
00415 ,"Error, something really bad happened in the Belos solver!"
00416 );
00417
00418 ESolveStatus solveStatus = SOLVE_STATUS_UNKNOWN;
00419 ScalarMag achievedTol = SolveStatus<Scalar>::unknownTolerance();
00420 if(solveMeasureType(SOLVE_MEASURE_NORM_RESIDUAL,SOLVE_MEASURE_NORM_RHS)) {
00421 switch(belosSolveStatus) {
00422 case Belos::Unchecked:
00423 solveStatus = SOLVE_STATUS_UNKNOWN;
00424 break;
00425 case Belos::Unconverged:
00426 solveStatus = SOLVE_STATUS_UNCONVERGED;
00427 break;
00428 case Belos::Converged:
00429 solveStatus = SOLVE_STATUS_CONVERGED;
00430 break;
00431 default:
00432 TEST_FOR_EXCEPT(true);
00433 }
00434 achievedTol = belosAchievedTol;
00435 }
00436 const int iterations = iterativeSolver_->GetNumIters();
00437
00438 std::ostringstream ossmessage;
00439 ossmessage
00440 << "The Belos solver of type \""<<iterativeSolver_->description()<<"\" returned a solve status of \""
00441 << toString(belosSolveStatus) << "\" in " << iterations << " iterations and achieved an approximate max tolerance of "
00442 << belosAchievedTol << " with total CPU time of " << totalTimer.totalElapsedTime() << " sec" ;
00443 if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_NONE))
00444 *out << "\n" << ossmessage.str() << "\n";
00445
00446 if( numBlocks && blockSolveStatus ) {
00447 blockSolveStatus[0].solveStatus = solveStatus;
00448 blockSolveStatus[0].achievedTol = achievedTol;
00449 blockSolveStatus[0].message = ossmessage.str();
00450 }
00451 if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00452 *out
00453 << "\nTotal solve time = "<<totalTimer.totalElapsedTime()<<" sec\n";
00454 }
00455
00456 }
00457
00458 #endif // THYRA_BELOS_LINEAR_OP_WITH_SOLVE_HPP
00459
00460 #endif // __sun