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 #ifndef SUN_CXX
00032
00033
00034 #include "Thyra_AztecOOLinearOpWithSolveFactory.hpp"
00035 #include "Thyra_AztecOOLinearOpWithSolve.hpp"
00036 #include "Thyra_PreconditionerFactoryHelpers.hpp"
00037 #include "Thyra_EpetraOperatorViewExtractorStd.hpp"
00038 #include "Thyra_ScaledAdjointLinearOpBase.hpp"
00039 #include "Thyra_EpetraLinearOpBase.hpp"
00040 #include "Thyra_EpetraOperatorWrapper.hpp"
00041 #include "EpetraExt_ProductOperator.h"
00042 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
00043 #include "Teuchos_ParameterList.hpp"
00044 #include "Teuchos_dyn_cast.hpp"
00045 #include "AztecOOParameterList.hpp"
00046
00047
00048 namespace {
00049
00050
00051 const std::string AOOLOWSF_epetraPrecOp_str
00052 = "AOOLOWSF::epetraPrecOp";
00053 const std::string AOOLOWSF_aztec_epetra_epetraFwdOp_str
00054 = "AOOLOWSF::aztec_epetra_epetraFwdOp";
00055 const std::string AOOLOWSF_aztec_epetra_epetraAdjOp_str
00056 = "AOOLOWSF::aztec_epetra_epetraAdjOp";
00057 const std::string AOOLOWSF_rowmatrix_epetraFwdOp_str
00058 = "AOOLOWSF::rowmatrix_epetraFwdOp";
00059 const std::string AOOLOWSF_rowmatrix_epetraPrecOp_str
00060 = "AOOLOWSF::rowmatrix_epetraPrecOp";
00061 const std::string AOOLOWSF_aztec_fwd_epetra_epetraPrecOp_str
00062 = "AOOLOWSF::aztec_fwd_epetra_epetraPrecOp";
00063 const std::string AOOLOWSF_aztec_adj_epetra_epetraPrecOp_str
00064 = "AOOLOWSF::aztec_adj_epetra_epetraPrecOp";
00065 const std::string AOOLOWSF_setPrecondtionerOperator_str
00066 = "AOOLOWSF::setPrecondtionerOperator";
00067 const std::string AOOLOWSF_constructedAztecPreconditoner_str
00068 = "AOOLOWSF::constructedAztecPreconditoner";
00069
00070
00071 const std::string ForwardSolve_name = "Forward Solve";
00072 const std::string AdjointSolve_name = "Adjoint Solve";
00073 const std::string MaxIterations_name = "Max Iterations";
00074 const int MaxIterations_default = 400;
00075 const std::string Tolerance_name = "Tolerance";
00076 const double Tolerance_default = 1e-6;
00077 const std::string OutputEveryRhs_name = "Output Every RHS";
00078 const bool OutputEveryRhs_default = false;
00079 const std::string AztecOO_Settings_name = "AztecOO Settings";
00080
00081
00082 }
00083
00084
00085 namespace Thyra {
00086
00087
00088
00089
00090
00091 AztecOOLinearOpWithSolveFactory::AztecOOLinearOpWithSolveFactory(
00092 Teuchos::RCP<Teuchos::ParameterList> const& paramList
00093 )
00094 :epetraFwdOpViewExtractor_(Teuchos::rcp(new EpetraOperatorViewExtractorStd()))
00095 ,defaultFwdMaxIterations_(MaxIterations_default)
00096 ,defaultFwdTolerance_(Tolerance_default)
00097 ,defaultAdjMaxIterations_(MaxIterations_default)
00098 ,defaultAdjTolerance_(Tolerance_default)
00099 ,outputEveryRhs_(OutputEveryRhs_default)
00100 {
00101 updateThisValidParamList();
00102 if(paramList.get())
00103 setParameterList(paramList);
00104 }
00105
00106
00107
00108
00109
00110 bool AztecOOLinearOpWithSolveFactory::acceptsPreconditionerFactory() const
00111 {
00112 return true;
00113 }
00114
00115
00116 void AztecOOLinearOpWithSolveFactory::setPreconditionerFactory(
00117 const Teuchos::RCP<PreconditionerFactoryBase<double> > &precFactory,
00118 const std::string &precFactoryName
00119 )
00120 {
00121 TEST_FOR_EXCEPT(!precFactory.get());
00122 Teuchos::RCP<const Teuchos::ParameterList>
00123 precFactoryValidPL = precFactory->getValidParameters();
00124 const std::string _precFactoryName =
00125 ( precFactoryName != ""
00126 ? precFactoryName
00127 : ( precFactoryValidPL.get()
00128 ? precFactoryValidPL->name()
00129 : "GENERIC PRECONDITIONER FACTORY"
00130 )
00131 );
00132 precFactory_ = precFactory;
00133 precFactoryName_ = _precFactoryName;
00134 updateThisValidParamList();
00135 }
00136
00137
00138 Teuchos::RCP<PreconditionerFactoryBase<double> >
00139 AztecOOLinearOpWithSolveFactory::getPreconditionerFactory() const
00140 {
00141 return precFactory_;
00142 }
00143
00144
00145 void AztecOOLinearOpWithSolveFactory::unsetPreconditionerFactory(
00146 Teuchos::RCP<PreconditionerFactoryBase<double> > *precFactory,
00147 std::string *precFactoryName
00148 )
00149 {
00150 if(precFactory) *precFactory = precFactory_;
00151 if(precFactoryName) *precFactoryName = precFactoryName_;
00152 precFactory_ = Teuchos::null;
00153 precFactoryName_ = "";
00154 updateThisValidParamList();
00155 }
00156
00157
00158 bool AztecOOLinearOpWithSolveFactory::isCompatible(
00159 const LinearOpSourceBase<double> &fwdOpSrc
00160 ) const
00161 {
00162 return epetraFwdOpViewExtractor_->isCompatible(*fwdOpSrc.getOp());
00163 }
00164
00165
00166 Teuchos::RCP<LinearOpWithSolveBase<double> >
00167 AztecOOLinearOpWithSolveFactory::createOp() const
00168 {
00169 return Teuchos::rcp(new AztecOOLinearOpWithSolve());
00170 }
00171
00172
00173 void AztecOOLinearOpWithSolveFactory::initializeOp(
00174 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc,
00175 LinearOpWithSolveBase<double> *Op,
00176 const ESupportSolveUse supportSolveUse
00177 ) const
00178 {
00179 this->initializeOp_impl(fwdOpSrc,Teuchos::null,Teuchos::null,false,Op);
00180 }
00181
00182
00183 void AztecOOLinearOpWithSolveFactory::initializeAndReuseOp(
00184 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc,
00185 LinearOpWithSolveBase<double> *Op
00186 ) const
00187 {
00188 this->initializeOp_impl(fwdOpSrc,Teuchos::null,Teuchos::null,true,Op);
00189 }
00190
00191
00192 bool AztecOOLinearOpWithSolveFactory::supportsPreconditionerInputType(
00193 const EPreconditionerInputType precOpType
00194 ) const
00195 {
00196 const_cast<bool&>(useAztecPrec_) = (
00197 paramList_.get()
00198 &&
00199 paramList_->sublist(ForwardSolve_name).sublist(AztecOO_Settings_name).get(
00200 "Aztec Preconditioner","none"
00201 )!="none"
00202 );
00203 switch(precOpType) {
00204 case PRECONDITIONER_INPUT_TYPE_AS_OPERATOR:
00205 return true;
00206 break;
00207 case PRECONDITIONER_INPUT_TYPE_AS_MATRIX:
00208 return useAztecPrec_;
00209 break;
00210 default:
00211 TEST_FOR_EXCEPT(true);
00212 }
00213 return PRECONDITIONER_INPUT_TYPE_AS_OPERATOR;
00214 }
00215
00216
00217 void AztecOOLinearOpWithSolveFactory::initializePreconditionedOp(
00218 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc,
00219 const Teuchos::RCP<const PreconditionerBase<double> > &prec,
00220 LinearOpWithSolveBase<double> *Op,
00221 const ESupportSolveUse supportSolveUse
00222 ) const
00223 {
00224 TEST_FOR_EXCEPT(prec.get()==NULL);
00225 this->initializeOp_impl(fwdOpSrc,prec,Teuchos::null,false,Op);
00226 }
00227
00228
00229 void AztecOOLinearOpWithSolveFactory::initializeApproxPreconditionedOp(
00230 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc,
00231 const Teuchos::RCP<const LinearOpSourceBase<double> > &approxFwdOpSrc,
00232 LinearOpWithSolveBase<double> *Op,
00233 const ESupportSolveUse supportSolveUse
00234 ) const
00235 {
00236 TEST_FOR_EXCEPT(approxFwdOpSrc.get()==NULL);
00237 TEST_FOR_EXCEPT(approxFwdOpSrc->getOp().get()==NULL);
00238 this->initializeOp_impl(fwdOpSrc,Teuchos::null,approxFwdOpSrc,false,Op);
00239 }
00240
00241
00242 void AztecOOLinearOpWithSolveFactory::uninitializeOp(
00243 LinearOpWithSolveBase<double> *Op,
00244 Teuchos::RCP<const LinearOpSourceBase<double> > *fwdOpSrc,
00245 Teuchos::RCP<const PreconditionerBase<double> > *prec,
00246 Teuchos::RCP<const LinearOpSourceBase<double> > *approxFwdOpSrc,
00247 ESupportSolveUse *supportSolveUse
00248 ) const
00249 {
00250 #ifdef TEUCHOS_DEBUG
00251 TEST_FOR_EXCEPT(Op==NULL);
00252 #endif
00253 AztecOOLinearOpWithSolve
00254 *aztecOp = &Teuchos::dyn_cast<AztecOOLinearOpWithSolve>(*Op);
00255
00256 Teuchos::RCP<const LinearOpSourceBase<double> >
00257 _fwdOpSrc = aztecOp->extract_fwdOpSrc(),
00258 _approxFwdOpSrc = aztecOp->extract_approxFwdOpSrc();
00259 if(fwdOpSrc) *fwdOpSrc = _fwdOpSrc;
00260 if(approxFwdOpSrc) *approxFwdOpSrc = _approxFwdOpSrc;
00261
00262
00263
00264 if(aztecOp->isExternalPrec()) {
00265 Teuchos::RCP<const PreconditionerBase<double> >
00266 _prec = aztecOp->extract_prec();
00267 if(prec) *prec = _prec;
00268 }
00269
00270
00271
00272 }
00273
00274
00275
00276
00277
00278 void AztecOOLinearOpWithSolveFactory::setParameterList(
00279 Teuchos::RCP<Teuchos::ParameterList> const& paramList
00280 )
00281 {
00282 TEST_FOR_EXCEPT(paramList.get()==NULL);
00283 paramList->validateParameters(*this->getValidParameters());
00284 paramList_ = paramList;
00285
00286 outputEveryRhs_ = paramList_->get(OutputEveryRhs_name,OutputEveryRhs_default);
00287
00288 Teuchos::ParameterList
00289 &fwdSolvePL = paramList_->sublist(ForwardSolve_name);
00290 defaultFwdMaxIterations_ = fwdSolvePL.get(MaxIterations_name,defaultFwdMaxIterations_);
00291 defaultFwdTolerance_ = fwdSolvePL.get(Tolerance_name,defaultFwdTolerance_);
00292
00293 if( !paramList_->getPtr<Teuchos::ParameterList>(AdjointSolve_name) ) {
00294
00295 paramList_->sublist(AdjointSolve_name).setParameters(fwdSolvePL);
00296 }
00297 Teuchos::ParameterList
00298 &adjSolvePL = paramList_->sublist(AdjointSolve_name);
00299 defaultAdjMaxIterations_ = adjSolvePL.get(MaxIterations_name,defaultAdjMaxIterations_);
00300 defaultAdjTolerance_ = adjSolvePL.get(Tolerance_name,defaultAdjTolerance_);
00301
00302 if(precFactory_.get()) {
00303
00304
00305
00306 const bool nestedPFSublistExists = paramList_->isSublist(precFactoryName_);
00307 const bool alreadyHasSublist = !is_null(precFactory_->getParameterList());
00308 if( nestedPFSublistExists || !alreadyHasSublist ) {
00309 precFactory_->setParameterList(Teuchos::sublist(paramList_,precFactoryName_));
00310 }
00311 }
00312 Teuchos::readVerboseObjectSublist(&*paramList_,this);
00313 }
00314
00315
00316 Teuchos::RCP<Teuchos::ParameterList>
00317 AztecOOLinearOpWithSolveFactory::getParameterList()
00318 {
00319 return paramList_;
00320 }
00321
00322
00323 Teuchos::RCP<Teuchos::ParameterList>
00324 AztecOOLinearOpWithSolveFactory::unsetParameterList()
00325 {
00326 Teuchos::RCP<Teuchos::ParameterList> _paramList = paramList_;
00327 paramList_ = Teuchos::null;
00328 return _paramList;
00329 }
00330
00331
00332 Teuchos::RCP<const Teuchos::ParameterList>
00333 AztecOOLinearOpWithSolveFactory::getParameterList() const
00334 {
00335 return paramList_;
00336 }
00337
00338
00339 Teuchos::RCP<const Teuchos::ParameterList>
00340 AztecOOLinearOpWithSolveFactory::getValidParameters() const
00341 {
00342 return thisValidParamList_;
00343 }
00344
00345
00346
00347
00348
00349 std::string AztecOOLinearOpWithSolveFactory::description() const
00350 {
00351 std::ostringstream oss;
00352 oss << "Thyra::AztecOOLinearOpWithSolveFactory{";
00353 oss << "precFactory=";
00354 if(!is_null(precFactory_))
00355 oss << precFactory_->description();
00356 else
00357 oss << "NULL";
00358 oss << "}";
00359 return oss.str();
00360 }
00361
00362
00363
00364
00365
00366 Teuchos::RCP<const Teuchos::ParameterList>
00367 AztecOOLinearOpWithSolveFactory::generateAndGetValidParameters()
00368 {
00369 static Teuchos::RCP<Teuchos::ParameterList> validParamList;
00370 if(validParamList.get()==NULL) {
00371 validParamList = Teuchos::rcp(
00372 new Teuchos::ParameterList("AztecOOLinearOpWithSolveFactory"));
00373 validParamList->set(
00374 OutputEveryRhs_name,OutputEveryRhs_default
00375 ,"Determines if output is created for each individual RHS (true or 1) or if output\n"
00376 "is just created for an entire set of RHSs (false or 0)."
00377 );
00378 static Teuchos::RCP<const Teuchos::ParameterList>
00379 aztecParamList = getValidAztecOOParameters();
00380 Teuchos::ParameterList
00381 &fwdSolvePL = validParamList->sublist(
00382 ForwardSolve_name, false
00383 ,"Gives the options for the forward solve."
00384 );
00385 fwdSolvePL.set(
00386 Tolerance_name,Tolerance_default
00387 ,"The tolerence used in the convergence check (see the convergence test\n"
00388 "in the sublist \"" + AztecOO_Settings_name + "\")"
00389 );
00390 fwdSolvePL.set(
00391 MaxIterations_name,MaxIterations_default
00392 ,"The maximum number of iterations the AztecOO solver is allowed to perform."
00393 );
00394 fwdSolvePL.sublist(
00395 AztecOO_Settings_name,false
00396 ,"Sets the parameters on the AztecOO object itself."
00397 ).setParameters(*aztecParamList);
00398 Teuchos::ParameterList
00399 &adjSolvePL = validParamList->sublist(
00400 AdjointSolve_name, false
00401 ,"The options for the adjoint solve.\n"
00402 "If this sublist is missing then the parameters from the\n"
00403 "\""+ForwardSolve_name+"\" sublist are used instead."
00404 );
00405
00406 adjSolvePL.setParameters(fwdSolvePL);
00407 }
00408 return validParamList;
00409 }
00410
00411
00412 void AztecOOLinearOpWithSolveFactory::updateThisValidParamList()
00413 {
00414 thisValidParamList_ = Teuchos::rcp(
00415 new Teuchos::ParameterList(*generateAndGetValidParameters())
00416 );
00417 if(precFactory_.get()) {
00418 Teuchos::RCP<const Teuchos::ParameterList>
00419 precFactoryValidParamList = precFactory_->getValidParameters();
00420 if(precFactoryValidParamList.get()) {
00421 thisValidParamList_->sublist(precFactoryName_).setParameters(
00422 *precFactoryValidParamList);
00423 }
00424 }
00425 Teuchos::setupVerboseObjectSublist(&*thisValidParamList_);
00426 }
00427
00428
00429 void AztecOOLinearOpWithSolveFactory::initializeOp_impl(
00430 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc,
00431 const Teuchos::RCP<const PreconditionerBase<double> > &prec,
00432 const Teuchos::RCP<const LinearOpSourceBase<double> > &approxFwdOpSrc,
00433 const bool reusePrec,
00434 LinearOpWithSolveBase<double> *Op
00435 ) const
00436 {
00437 using Teuchos::RCP;
00438 using Teuchos::null;
00439 using Teuchos::rcp;
00440 using Teuchos::rcp_dynamic_cast;
00441 using Teuchos::rcp_const_cast;
00442 using Teuchos::set_extra_data;
00443 using Teuchos::get_optional_extra_data;
00444 typedef EpetraExt::ProductOperator PO;
00445
00446 const Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
00447 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00448 Teuchos::OSTab tab(out);
00449 if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00450 *out << "\nEntering Thyra::AztecOOLinearOpWithSolveFactory::initializeOp_impl(...) ...\n";
00451
00452 typedef Teuchos::VerboseObjectTempState<PreconditionerFactoryBase<double> > VOTSPF;
00453 VOTSPF precFactoryOutputTempState(precFactory_,out,verbLevel);
00454
00455 #ifdef TEUCHOS_DEBUG
00456 TEST_FOR_EXCEPT(Op==NULL);
00457 TEST_FOR_EXCEPT(fwdOpSrc.get()==NULL);
00458 TEST_FOR_EXCEPT(fwdOpSrc->getOp().get()==NULL);
00459 #endif
00460
00461
00462
00463
00464
00465
00466 Teuchos::RCP<const LinearOpBase<double> >
00467 tmpFwdOp = fwdOpSrc->getOp(),
00468 tmpApproxFwdOp = ( approxFwdOpSrc.get() ? approxFwdOpSrc->getOp() : Teuchos::null );
00469 Teuchos::RCP<const LinearOpBase<double> > fwdOp;
00470 Teuchos::RCP<const LinearOpBase<double> > approxFwdOp;
00471 if ( dynamic_cast<const EpetraLinearOpBase*>(tmpFwdOp.get())!=0 )
00472 {
00473 fwdOp = tmpFwdOp;
00474 approxFwdOp = tmpApproxFwdOp;
00475 }
00476 else
00477 {
00478 fwdOp = makeEpetraWrapper(ConstLinearOperator<double>(tmpFwdOp));
00479 if (
00480 tmpApproxFwdOp.get()
00481 &&
00482 dynamic_cast<const EpetraLinearOpBase*>(&*tmpApproxFwdOp.get())
00483 )
00484 {
00485 approxFwdOp = makeEpetraWrapper(ConstLinearOperator<double>(tmpApproxFwdOp));
00486 }
00487 }
00488
00489
00490
00491
00492 AztecOOLinearOpWithSolve
00493 *aztecOp = &Teuchos::dyn_cast<AztecOOLinearOpWithSolve>(*Op);
00494
00495
00496
00497
00498 Teuchos::RCP<const Epetra_Operator> epetra_epetraFwdOp;
00499 ETransp epetra_epetraFwdOpTransp;
00500 EApplyEpetraOpAs epetra_epetraFwdOpApplyAs;
00501 EAdjointEpetraOp epetra_epetraFwdOpAdjointSupport;
00502 double epetra_epetraFwdOpScalar;
00503 epetraFwdOpViewExtractor_->getEpetraOpView(
00504 fwdOp,
00505 &epetra_epetraFwdOp, &epetra_epetraFwdOpTransp,
00506 &epetra_epetraFwdOpApplyAs, &epetra_epetraFwdOpAdjointSupport,
00507 &epetra_epetraFwdOpScalar
00508 );
00509 TEST_FOR_EXCEPTION(
00510 epetra_epetraFwdOp.get()==NULL, std::logic_error
00511 ,"Error, The input fwdOp object must be fully initialized "
00512 "before calling this function!"
00513 );
00514
00515
00516
00517
00518 Teuchos::RCP<PreconditionerBase<double> > myPrec;
00519 Teuchos::RCP<const PreconditionerBase<double> > precUsed;
00520 if (prec.get()) {
00521
00522 precUsed = prec;
00523 }
00524 else if (precFactory_.get() ) {
00525
00526
00527 myPrec =
00528 ( !aztecOp->isExternalPrec()
00529 ? Teuchos::rcp_const_cast<PreconditionerBase<double> >(
00530 aztecOp->extract_prec())
00531 : Teuchos::null
00532 );
00533 if(myPrec.get()) {
00534
00535
00536 }
00537 else {
00538 myPrec = precFactory_->createPrec();
00539 }
00540 precFactory_->initializePrec(fwdOpSrc,&*myPrec);
00541 precUsed = myPrec;
00542 }
00543
00544
00545
00546
00547 RCP<const LinearOpBase<double> > rightPrecOp;
00548 if (precUsed.get()) {
00549 RCP<const LinearOpBase<double> > unspecified = precUsed->getUnspecifiedPrecOp();
00550 RCP<const LinearOpBase<double> > left = precUsed->getLeftPrecOp();
00551 RCP<const LinearOpBase<double> > right = precUsed->getRightPrecOp();
00552 TEST_FOR_EXCEPTION(
00553 !( left.get() || right.get() || unspecified.get() ), std::logic_error
00554 ,"Error, at least one preconditoner linear operator objects must be set!"
00555 );
00556 if(unspecified.get()) {
00557 rightPrecOp = unspecified;
00558 }
00559 else {
00560
00561 TEST_FOR_EXCEPTION(
00562 left.get(),std::logic_error
00563 ,"Error, we can not currently handle a left"
00564 " preconditioner with the AztecOO/Thyra adapters!"
00565 );
00566 rightPrecOp = right;
00567 }
00568 }
00569 double wrappedPrecOpScalar = 0.0;
00570 ETransp wrappedPrecOpTransp = NOTRANS;
00571 RCP<const LinearOpBase<double> > wrappedPrecOp = null;
00572 RCP<const EpetraLinearOpBase> epetraPrecOp;
00573 Teuchos::RCP<const Epetra_Operator> epetra_epetraPrecOp;
00574 ETransp epetra_epetraPrecOpTransp;
00575 EApplyEpetraOpAs epetra_epetraPrecOpApplyAs;
00576 EAdjointEpetraOp epetra_epetraPrecOpAdjointSupport;
00577 ETransp overall_epetra_epetraPrecOpTransp;
00578 if(rightPrecOp.get()) {
00579 RCP<const LinearOpBase<double> > tmpWrappedPrecOp;
00580 unwrap(
00581 rightPrecOp,&wrappedPrecOpScalar,&wrappedPrecOpTransp,&tmpWrappedPrecOp);
00582 if( dynamic_cast<const EpetraLinearOpBase*>(&*tmpWrappedPrecOp) ) {
00583 wrappedPrecOp = tmpWrappedPrecOp;
00584 }
00585 else {
00586 wrappedPrecOp = makeEpetraWrapper(
00587 ConstLinearOperator<double>(tmpWrappedPrecOp));
00588 }
00589 epetraPrecOp = rcp_dynamic_cast<const EpetraLinearOpBase>(
00590 wrappedPrecOp,true);
00591 epetraPrecOp->getEpetraOpView(
00592 &epetra_epetraPrecOp,&epetra_epetraPrecOpTransp,
00593 &epetra_epetraPrecOpApplyAs,&epetra_epetraPrecOpAdjointSupport);
00594 TEST_FOR_EXCEPTION(
00595 epetra_epetraPrecOp.get()==NULL,std::logic_error
00596 ,"Error, The input prec object and its embedded precondtioner"
00597 " operator must be fully initialized before calling this function!"
00598 );
00599
00600
00601
00602
00603
00604
00605
00606 overall_epetra_epetraPrecOpTransp
00607 = trans_trans(
00608 real_trans(wrappedPrecOpTransp),
00609 real_trans(epetra_epetraPrecOpTransp)
00610 );
00611 }
00612
00613
00614
00615
00616
00617 if(approxFwdOp.get()) {
00618
00619
00620 unwrap(approxFwdOp,&wrappedPrecOpScalar,&wrappedPrecOpTransp,&wrappedPrecOp);
00621 epetraPrecOp = rcp_dynamic_cast<const EpetraLinearOpBase>(
00622 wrappedPrecOp,true);
00623 epetraPrecOp->getEpetraOpView(
00624 &epetra_epetraPrecOp, &epetra_epetraPrecOpTransp,
00625 &epetra_epetraPrecOpApplyAs, &epetra_epetraPrecOpAdjointSupport
00626 );
00627 TEST_FOR_EXCEPTION(
00628 epetra_epetraPrecOp.get()==NULL,std::logic_error
00629 ,"Error, The input approxFwdOp object must be fully initialized"
00630 " before calling this function!"
00631 );
00632
00633
00634
00635
00636
00637
00638
00639
00640 overall_epetra_epetraPrecOpTransp
00641 = trans_trans(
00642 real_trans(wrappedPrecOpTransp),
00643 real_trans(epetra_epetraPrecOpTransp)
00644 );
00645 }
00646
00647
00648
00649
00650
00651 RCP<const Epetra_RowMatrix>
00652 rowmatrix_epetraFwdOp = rcp_dynamic_cast<const Epetra_RowMatrix>(
00653 epetra_epetraFwdOp),
00654 rowmatrix_epetraPrecOp = rcp_dynamic_cast<const Epetra_RowMatrix>(
00655 epetra_epetraPrecOp);
00656
00657
00658
00659
00660 this->supportsPreconditionerInputType(PRECONDITIONER_INPUT_TYPE_AS_MATRIX);
00661 enum ELocalPrecType {
00662 PT_NONE, PT_AZTEC_FROM_OP, PT_AZTEC_FROM_APPROX_FWD_MATRIX,
00663 PT_FROM_PREC_OP
00664 };
00665 ELocalPrecType localPrecType;
00666 if( precUsed.get()==NULL && approxFwdOp.get()==NULL && !useAztecPrec_ ) {
00667
00668 localPrecType = PT_NONE;
00669 }
00670 else if( precUsed.get()==NULL && approxFwdOp.get()==NULL && useAztecPrec_ ) {
00671
00672
00673 localPrecType = PT_AZTEC_FROM_OP;
00674 }
00675 else if( approxFwdOp.get() && useAztecPrec_ ) {
00676
00677
00678 localPrecType = PT_AZTEC_FROM_APPROX_FWD_MATRIX;
00679 }
00680 else if( precUsed.get() ) {
00681
00682
00683 localPrecType = PT_FROM_PREC_OP;
00684 }
00685
00686
00687
00688
00689
00690 RCP<AztecOO> aztecFwdSolver, aztecAdjSolver;
00691 bool startingOver;
00692 {
00693
00694
00695
00696 Teuchos::RCP<const LinearOpBase<double> > old_fwdOp;
00697 Teuchos::RCP<const LinearOpSourceBase<double> > old_fwdOpSrc;
00698 Teuchos::RCP<const PreconditionerBase<double> > old_prec;
00699 bool old_isExternalPrec;
00700 Teuchos::RCP<const LinearOpSourceBase<double> > old_approxFwdOpSrc;
00701 Teuchos::RCP<AztecOO> old_aztecFwdSolver;
00702 Teuchos::RCP<AztecOO> old_aztecAdjSolver;
00703 double old_aztecSolverScalar;
00704 aztecOp->uninitialize(
00705 &old_fwdOp
00706 ,&old_fwdOpSrc
00707 ,&old_prec
00708 ,&old_isExternalPrec
00709 ,&old_approxFwdOpSrc
00710 ,&old_aztecFwdSolver
00711 ,NULL
00712 ,&old_aztecAdjSolver
00713 ,NULL
00714 ,&old_aztecSolverScalar
00715 );
00716 if( old_aztecFwdSolver.get()==NULL ) {
00717
00718 startingOver = true;
00719 }
00720 else {
00721
00722
00723
00724 aztecFwdSolver = old_aztecFwdSolver;
00725 aztecAdjSolver = old_aztecAdjSolver;
00726 startingOver = false;
00727
00728
00729 bool *constructedAztecPreconditioner = NULL;
00730 if(
00731 !reusePrec
00732 && ( constructedAztecPreconditioner = get_optional_extra_data<bool>(
00733 aztecFwdSolver,"AOOLOWSF::constructedAztecPreconditoner") )
00734 && *constructedAztecPreconditioner
00735 )
00736 {
00737 aztecFwdSolver->DestroyPreconditioner();
00738 *constructedAztecPreconditioner = false;
00739 }
00740
00741
00742 bool *setPreconditionerOperator = NULL;
00743 if(
00744 localPrecType != PT_FROM_PREC_OP
00745 && ( setPreconditionerOperator = get_optional_extra_data<bool>(
00746 aztecFwdSolver,"AOOLOWSF::setPreconditonerOperator") )
00747 && *setPreconditionerOperator
00748 )
00749 {
00750
00751
00752 startingOver = true;
00753 }
00754 }
00755 }
00756
00757
00758
00759
00760 startingOver = true;
00761 if(startingOver) {
00762
00763 aztecFwdSolver = rcp(new AztecOO());
00764 aztecFwdSolver->SetAztecOption(AZ_diagnostics,AZ_none);
00765 aztecFwdSolver->SetAztecOption(AZ_keep_info,1);
00766
00767 if(
00768 epetra_epetraFwdOpAdjointSupport==EPETRA_OP_ADJOINT_SUPPORTED
00769 &&
00770 localPrecType!=PT_AZTEC_FROM_OP && localPrecType!=PT_AZTEC_FROM_APPROX_FWD_MATRIX
00771 )
00772 {
00773 aztecAdjSolver = rcp(new AztecOO());
00774 aztecAdjSolver->SetAztecOption(AZ_diagnostics,AZ_none);
00775
00776 }
00777 }
00778
00779
00780
00781
00782 if( startingOver ) {
00783 if(paramList_.get())
00784 setAztecOOParameters(
00785 ¶mList_->sublist(ForwardSolve_name).sublist(AztecOO_Settings_name),
00786 &*aztecFwdSolver
00787 );
00788 if(aztecAdjSolver.get() && paramList_.get())
00789 setAztecOOParameters(
00790 ¶mList_->sublist(AdjointSolve_name).sublist(AztecOO_Settings_name),
00791 &*aztecAdjSolver
00792 );
00793 }
00794
00795
00796
00797
00798 RCP<const Epetra_Operator>
00799 aztec_epetra_epetraFwdOp,
00800 aztec_epetra_epetraAdjOp;
00801
00802 RCP<const Epetra_Operator>
00803 epetraOps[]
00804 = { epetra_epetraFwdOp };
00805 Teuchos::ETransp
00806 epetraOpsTransp[]
00807 = { epetra_epetraFwdOpTransp==NOTRANS ? Teuchos::NO_TRANS : Teuchos::TRANS };
00808 PO::EApplyMode
00809 epetraOpsApplyMode[]
00810 = { epetra_epetraFwdOpApplyAs==EPETRA_OP_APPLY_APPLY
00811 ? PO::APPLY_MODE_APPLY
00812 : PO::APPLY_MODE_APPLY_INVERSE };
00813 if(
00814 epetraOpsTransp[0] == Teuchos::NO_TRANS
00815 &&
00816 epetraOpsApplyMode[0] == PO::APPLY_MODE_APPLY
00817 )
00818 {
00819 aztec_epetra_epetraFwdOp = epetra_epetraFwdOp;
00820 }
00821 else
00822 {
00823 aztec_epetra_epetraFwdOp = rcp(
00824 new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode));
00825 }
00826 if(
00827 startingOver
00828 ||
00829 aztec_epetra_epetraFwdOp.get() != aztecFwdSolver->GetUserOperator()
00830 )
00831 {
00832
00833
00834 aztecFwdSolver->SetUserOperator(
00835 const_cast<Epetra_Operator*>(&*aztec_epetra_epetraFwdOp));
00836 set_extra_data(
00837 aztec_epetra_epetraFwdOp, AOOLOWSF_aztec_epetra_epetraFwdOp_str,
00838 &aztecFwdSolver, Teuchos::POST_DESTROY, false
00839 );
00840 }
00841
00842 if( aztecAdjSolver.get() ) {
00843 epetraOpsTransp[0] = (
00844 epetra_epetraFwdOpTransp==NOTRANS
00845 ? Teuchos::TRANS
00846 : Teuchos::NO_TRANS
00847 );
00848 if(
00849 epetraOpsTransp[0] == Teuchos::NO_TRANS
00850 &&
00851 epetraOpsApplyMode[0] == PO::APPLY_MODE_APPLY
00852 )
00853 {
00854 aztec_epetra_epetraAdjOp = epetra_epetraFwdOp;
00855 }
00856 else {
00857 aztec_epetra_epetraAdjOp = rcp(
00858 new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode));
00859 }
00860 aztecAdjSolver->SetUserOperator(
00861 const_cast<Epetra_Operator*>(&*aztec_epetra_epetraAdjOp));
00862 set_extra_data(
00863 aztec_epetra_epetraAdjOp, AOOLOWSF_aztec_epetra_epetraAdjOp_str,
00864 &aztecAdjSolver, Teuchos::POST_DESTROY, false
00865 );
00866 }
00867
00868
00869
00870
00871 RCP<const Epetra_Operator>
00872 aztec_fwd_epetra_epetraPrecOp,
00873 aztec_adj_epetra_epetraPrecOp;
00874 bool setAztecPreconditioner = false;
00875 switch(localPrecType) {
00876 case PT_NONE: {
00877
00878
00879
00880 break;
00881 }
00882 case PT_AZTEC_FROM_OP: {
00883
00884
00885
00886
00887 if( startingOver || !reusePrec ) {
00888 TEST_FOR_EXCEPTION(
00889 rowmatrix_epetraFwdOp.get()==NULL, std::logic_error,
00890 "AztecOOLinearOpWithSolveFactory::initializeOp_impl(...): "
00891 "Error, There is no preconditioner given by client, but the client "
00892 "passed in an Epetra_Operator for the forward operator of type \'"
00893 <<typeName(*epetra_epetraFwdOp)<<"\' that does not "
00894 "support the Epetra_RowMatrix interface!"
00895 );
00896 TEST_FOR_EXCEPTION(
00897 epetra_epetraFwdOpTransp!=NOTRANS, std::logic_error,
00898 "AztecOOLinearOpWithSolveFactory::initializeOp_impl(...):"
00899 " Error, There is no preconditioner given by client and the client "
00900 "passed in an Epetra_RowMatrix for the forward operator but the "
00901 "overall transpose is not NOTRANS and therefore we can can just "
00902 "hand this over to aztec without making a copy which is not supported here!"
00903 );
00904 aztecFwdSolver->SetPrecMatrix(
00905 const_cast<Epetra_RowMatrix*>(&*rowmatrix_epetraFwdOp));
00906 set_extra_data(
00907 rowmatrix_epetraFwdOp, AOOLOWSF_rowmatrix_epetraFwdOp_str,
00908 &aztecFwdSolver, Teuchos::POST_DESTROY, false
00909 );
00910 }
00911 setAztecPreconditioner = true;
00912 break;
00913 }
00914 case PT_AZTEC_FROM_APPROX_FWD_MATRIX: {
00915
00916
00917
00918
00919 if( startingOver || !reusePrec ) {
00920 TEST_FOR_EXCEPTION(
00921 rowmatrix_epetraPrecOp.get()==NULL, std::logic_error
00922 ,"AztecOOLinearOpWithSolveFactor::initializeOp_impl(...): The client "
00923 "passed in an Epetra_Operator for the preconditioner matrix of type \'"
00924 <<typeName(*epetra_epetraPrecOp)<<"\' that does not "
00925 "support the Epetra_RowMatrix interface!"
00926 );
00927 TEST_FOR_EXCEPTION(
00928 overall_epetra_epetraPrecOpTransp!=NOTRANS, std::logic_error
00929 ,"AztecOOLinearOpWithSolveFactor::initializeOp_impl(...): Error, The client "
00930 "passed in an Epetra_RowMatrix for the preconditoner matrix but the overall "
00931 "transpose is not NOTRANS and therefore we can can just "
00932 "hand this over to aztec without making a copy which is not supported here!"
00933 );
00934 aztecFwdSolver->SetPrecMatrix(
00935 const_cast<Epetra_RowMatrix*>(&*rowmatrix_epetraPrecOp));
00936 set_extra_data(
00937 rowmatrix_epetraPrecOp, AOOLOWSF_rowmatrix_epetraPrecOp_str,
00938 &aztecFwdSolver, Teuchos::POST_DESTROY, false
00939 );
00940 }
00941 setAztecPreconditioner = true;
00942 break;
00943 }
00944 case PT_FROM_PREC_OP: {
00945
00946
00947
00948
00949 RCP<const Epetra_Operator>
00950 epetraOps[]
00951 = { epetra_epetraPrecOp };
00952 Teuchos::ETransp
00953 epetraOpsTransp[]
00954 = { overall_epetra_epetraPrecOpTransp==NOTRANS
00955 ? Teuchos::NO_TRANS
00956 : Teuchos::TRANS };
00957
00958
00959 PO::EApplyMode
00960 epetraOpsApplyMode[]
00961 = { epetra_epetraPrecOpApplyAs==EPETRA_OP_APPLY_APPLY
00962 ? PO::APPLY_MODE_APPLY_INVERSE
00963 : PO::APPLY_MODE_APPLY };
00964 if(
00965 epetraOpsTransp[0] == Teuchos::NO_TRANS
00966 &&
00967 epetra_epetraPrecOpApplyAs==EPETRA_OP_APPLY_APPLY_INVERSE
00968 )
00969 {
00970 aztec_fwd_epetra_epetraPrecOp = epetra_epetraPrecOp;
00971 }
00972 else {
00973 aztec_fwd_epetra_epetraPrecOp = rcp(new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode));
00974 }
00975 aztecFwdSolver->SetPrecOperator(
00976 const_cast<Epetra_Operator*>(&*aztec_fwd_epetra_epetraPrecOp));
00977 set_extra_data(
00978 aztec_fwd_epetra_epetraPrecOp, AOOLOWSF_aztec_fwd_epetra_epetraPrecOp_str,
00979 &aztecFwdSolver, Teuchos::POST_DESTROY, false
00980 );
00981
00982 if(
00983 aztecAdjSolver.get()
00984 &&
00985 epetra_epetraPrecOpAdjointSupport == EPETRA_OP_ADJOINT_SUPPORTED
00986 )
00987 {
00988 epetraOpsTransp[0] = (
00989 overall_epetra_epetraPrecOpTransp==NOTRANS
00990 ? Teuchos::TRANS
00991 : Teuchos::NO_TRANS
00992 );
00993 if(
00994 epetraOpsTransp[0] == Teuchos::NO_TRANS
00995 &&
00996 epetra_epetraPrecOpApplyAs==EPETRA_OP_APPLY_APPLY_INVERSE
00997 )
00998 {
00999 aztec_adj_epetra_epetraPrecOp = epetra_epetraPrecOp;
01000 }
01001 else {
01002 aztec_adj_epetra_epetraPrecOp = rcp(
01003 new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode));
01004 }
01005 aztecAdjSolver->SetPrecOperator(
01006 const_cast<Epetra_Operator*>(&*aztec_adj_epetra_epetraPrecOp));
01007 set_extra_data(
01008 aztec_adj_epetra_epetraPrecOp, AOOLOWSF_aztec_adj_epetra_epetraPrecOp_str,
01009 &aztecAdjSolver, Teuchos::POST_DESTROY, false
01010 );
01011 set_extra_data<bool>(
01012 true, AOOLOWSF_setPrecondtionerOperator_str,
01013 &aztecFwdSolver, Teuchos::POST_DESTROY, false
01014 );
01015 }
01016 break;
01017 }
01018 default:
01019 TEST_FOR_EXCEPT(true);
01020 }
01021
01022
01023
01024
01025 if(setAztecPreconditioner) {
01026 if( startingOver || !reusePrec ) {
01027 double condNumEst = -1.0;
01028 TEST_FOR_EXCEPT(0!=aztecFwdSolver->ConstructPreconditioner(condNumEst));
01029
01030 set_extra_data<bool>(
01031 true, AOOLOWSF_constructedAztecPreconditoner_str,
01032 &aztecFwdSolver, Teuchos::POST_DESTROY, false
01033 );
01034 }
01035 else {
01036
01037 }
01038 }
01039
01040
01041
01042
01043 if(aztecAdjSolver.get()) {
01044 aztecOp->initialize(
01045 fwdOp, fwdOpSrc,precUsed, prec.get()!=NULL, approxFwdOpSrc,
01046 aztecFwdSolver, true, aztecAdjSolver, true, epetra_epetraFwdOpScalar
01047 );
01048 }
01049 else {
01050 aztecOp->initialize(
01051 fwdOp, fwdOpSrc, precUsed, prec.get()!=NULL, approxFwdOpSrc,
01052 aztecFwdSolver, true, null, false, epetra_epetraFwdOpScalar
01053 );
01054 }
01055 aztecOp->fwdDefaultMaxIterations(defaultFwdMaxIterations_);
01056 aztecOp->fwdDefaultTol(defaultFwdTolerance_);
01057 aztecOp->adjDefaultMaxIterations(defaultAdjMaxIterations_);
01058 aztecOp->adjDefaultTol(defaultAdjTolerance_);
01059 aztecOp->outputEveryRhs(outputEveryRhs_);
01060 aztecOp->setOStream(this->getOStream());
01061 if(!is_null(this->getOverridingOStream()))
01062 aztecOp->setOverridingOStream(this->getOverridingOStream());
01063 aztecOp->setVerbLevel(this->getVerbLevel());
01064
01065 #ifdef TEUCHOS_DEBUG
01066 if(paramList_.get())
01067 paramList_->validateParameters(*this->getValidParameters());
01068 #endif
01069
01070 if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
01071 *out << "\nLeaving Thyra::AztecOOLinearOpWithSolveFactory::initializeOp_impl(...) ...\n";
01072
01073 }
01074
01075
01076 }
01077
01078
01079 #endif // SUN_CXX