Stratimikos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Thyra_BelosLinearOpWithSolveFactory_def.hpp
Go to the documentation of this file.
00001 /*
00002 // @HEADER
00003 // ***********************************************************************
00004 // 
00005 //         Stratimikos: Thyra-based strategies for linear solvers
00006 //                Copyright (2006) Sandia Corporation
00007 // 
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 // 
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 
00039 // 
00040 // ***********************************************************************
00041 // @HEADER
00042 */
00043 
00044 
00045 #ifndef THYRA_BELOS_LINEAR_OP_WITH_SOLVE_FACTORY_HPP
00046 #define THYRA_BELOS_LINEAR_OP_WITH_SOLVE_FACTORY_HPP
00047 
00048 
00049 #include "Thyra_BelosLinearOpWithSolveFactory_decl.hpp"
00050 #include "Thyra_BelosLinearOpWithSolve.hpp"
00051 #include "Thyra_ScaledAdjointLinearOpBase.hpp"
00052 
00053 #include "BelosBlockGmresSolMgr.hpp"
00054 #include "BelosPseudoBlockGmresSolMgr.hpp"
00055 #include "BelosBlockCGSolMgr.hpp"
00056 #include "BelosPseudoBlockCGSolMgr.hpp"
00057 #include "BelosPseudoBlockStochasticCGSolMgr.hpp"
00058 #include "BelosGCRODRSolMgr.hpp"
00059 #include "BelosRCGSolMgr.hpp"
00060 #include "BelosMinresSolMgr.hpp"
00061 #include "BelosTFQMRSolMgr.hpp"
00062 
00063 #include "BelosThyraAdapter.hpp"
00064 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
00065 #include "Teuchos_StandardParameterEntryValidators.hpp"
00066 #include "Teuchos_ParameterList.hpp"
00067 #include "Teuchos_dyn_cast.hpp"
00068 #include "Teuchos_ValidatorXMLConverterDB.hpp"
00069 #include "Teuchos_StandardValidatorXMLConverters.hpp"
00070 
00071 
00072 namespace Thyra {
00073 
00074 
00075 // Parameter names for Paramter List
00076 
00077 template<class Scalar>
00078 const std::string BelosLinearOpWithSolveFactory<Scalar>::SolverType_name = "Solver Type";
00079 template<class Scalar>
00080 const std::string BelosLinearOpWithSolveFactory<Scalar>::SolverType_default = "Pseudo Block GMRES";
00081 template<class Scalar>
00082 const std::string BelosLinearOpWithSolveFactory<Scalar>::SolverTypes_name = "Solver Types";
00083 template<class Scalar>
00084 const std::string BelosLinearOpWithSolveFactory<Scalar>::BlockGMRES_name = "Block GMRES";
00085 template<class Scalar>
00086 const std::string BelosLinearOpWithSolveFactory<Scalar>::PseudoBlockGMRES_name = "Pseudo Block GMRES";
00087 template<class Scalar>
00088 const std::string BelosLinearOpWithSolveFactory<Scalar>::BlockCG_name = "Block CG";
00089 template<class Scalar>
00090 const std::string BelosLinearOpWithSolveFactory<Scalar>::PseudoBlockCG_name = "Pseudo Block CG";
00091 template<class Scalar>
00092 const std::string BelosLinearOpWithSolveFactory<Scalar>::PseudoBlockStochasticCG_name = "Pseudo Block Stochastic CG";
00093 template<class Scalar>
00094 const std::string BelosLinearOpWithSolveFactory<Scalar>::GCRODR_name = "GCRODR";
00095 template<class Scalar>
00096 const std::string BelosLinearOpWithSolveFactory<Scalar>::RCG_name = "RCG";
00097 template<class Scalar>
00098 const std::string BelosLinearOpWithSolveFactory<Scalar>::MINRES_name = "MINRES";
00099 template<class Scalar>
00100 const std::string BelosLinearOpWithSolveFactory<Scalar>::TFQMR_name = "TFQMR";
00101 template<class Scalar>
00102 const std::string BelosLinearOpWithSolveFactory<Scalar>::ConvergenceTestFrequency_name = "Convergence Test Frequency";
00103 
00104 // Constructors/initializers/accessors
00105 
00106 
00107 template<class Scalar>
00108 BelosLinearOpWithSolveFactory<Scalar>::BelosLinearOpWithSolveFactory()
00109   :solverType_(SOLVER_TYPE_PSEUDO_BLOCK_GMRES),
00110    convergenceTestFrequency_(1)
00111 {
00112   updateThisValidParamList();
00113 }
00114 
00115 
00116 template<class Scalar>
00117 BelosLinearOpWithSolveFactory<Scalar>::BelosLinearOpWithSolveFactory(
00118   const RCP<PreconditionerFactoryBase<Scalar> > &precFactory
00119   )
00120   :solverType_(SOLVER_TYPE_PSEUDO_BLOCK_GMRES)
00121 {
00122   this->setPreconditionerFactory(precFactory, "");
00123 }
00124 
00125 
00126 // Overridden from LinearOpWithSolveFactoryBase
00127 
00128 
00129 template<class Scalar>
00130 bool BelosLinearOpWithSolveFactory<Scalar>::acceptsPreconditionerFactory() const
00131 {
00132   return true;
00133 }
00134 
00135 
00136 template<class Scalar>
00137 void BelosLinearOpWithSolveFactory<Scalar>::setPreconditionerFactory(
00138   const RCP<PreconditionerFactoryBase<Scalar> > &precFactory,
00139   const std::string &precFactoryName
00140   )
00141 {
00142   TEUCHOS_TEST_FOR_EXCEPT(!precFactory.get());
00143   RCP<const Teuchos::ParameterList>
00144     precFactoryValidPL = precFactory->getValidParameters();
00145   const std::string _precFactoryName =
00146     ( precFactoryName != ""
00147       ? precFactoryName
00148       : ( precFactoryValidPL.get() ? precFactoryValidPL->name() : "GENERIC PRECONDITIONER FACTORY" )
00149       );
00150   precFactory_ = precFactory;
00151   precFactoryName_ = _precFactoryName;
00152   updateThisValidParamList();
00153 }
00154 
00155 
00156 template<class Scalar>
00157 RCP<PreconditionerFactoryBase<Scalar> >
00158 BelosLinearOpWithSolveFactory<Scalar>::getPreconditionerFactory() const
00159 {
00160   return precFactory_;
00161 }
00162 
00163 
00164 template<class Scalar>
00165 void BelosLinearOpWithSolveFactory<Scalar>::unsetPreconditionerFactory(
00166   RCP<PreconditionerFactoryBase<Scalar> > *precFactory,
00167   std::string *precFactoryName
00168   )
00169 {
00170   if(precFactory) *precFactory = precFactory_;
00171   if(precFactoryName) *precFactoryName = precFactoryName_;
00172   precFactory_ = Teuchos::null;
00173   precFactoryName_ = "";
00174   updateThisValidParamList();
00175 }
00176 
00177 
00178 template<class Scalar>
00179 bool BelosLinearOpWithSolveFactory<Scalar>::isCompatible(
00180   const LinearOpSourceBase<Scalar> &fwdOpSrc
00181   ) const
00182 {
00183   if(precFactory_.get())
00184     return precFactory_->isCompatible(fwdOpSrc);
00185   return true; // Without a preconditioner, we are compatible with all linear operators!
00186 }
00187 
00188 
00189 template<class Scalar>
00190 RCP<LinearOpWithSolveBase<Scalar> >
00191 BelosLinearOpWithSolveFactory<Scalar>::createOp() const
00192 {
00193   return Teuchos::rcp(new BelosLinearOpWithSolve<Scalar>());
00194 }
00195 
00196 
00197 template<class Scalar>
00198 void BelosLinearOpWithSolveFactory<Scalar>::initializeOp(
00199   const RCP<const LinearOpSourceBase<Scalar> > &fwdOpSrc,
00200   LinearOpWithSolveBase<Scalar> *Op,
00201   const ESupportSolveUse supportSolveUse
00202   ) const
00203 {
00204   using Teuchos::null;
00205   initializeOpImpl(fwdOpSrc,null,null,false,Op,supportSolveUse);
00206 }
00207 
00208 
00209 template<class Scalar>
00210 void BelosLinearOpWithSolveFactory<Scalar>::initializeAndReuseOp(
00211   const RCP<const LinearOpSourceBase<Scalar> > &fwdOpSrc,
00212   LinearOpWithSolveBase<Scalar> *Op
00213   ) const
00214 {
00215   using Teuchos::null;
00216   initializeOpImpl(fwdOpSrc,null,null,true,Op,SUPPORT_SOLVE_UNSPECIFIED);
00217 }
00218 
00219 
00220 template<class Scalar>
00221 bool BelosLinearOpWithSolveFactory<Scalar>::supportsPreconditionerInputType(
00222   const EPreconditionerInputType precOpType
00223   ) const
00224 {
00225   if(precFactory_.get())
00226     return true;
00227   return (precOpType==PRECONDITIONER_INPUT_TYPE_AS_OPERATOR);
00228 }
00229 
00230 
00231 template<class Scalar>
00232 void BelosLinearOpWithSolveFactory<Scalar>::initializePreconditionedOp(
00233   const RCP<const LinearOpSourceBase<Scalar> > &fwdOpSrc,
00234   const RCP<const PreconditionerBase<Scalar> > &prec,
00235   LinearOpWithSolveBase<Scalar> *Op,
00236   const ESupportSolveUse supportSolveUse
00237   ) const
00238 {
00239   using Teuchos::null;
00240   initializeOpImpl(fwdOpSrc,null,prec,false,Op,supportSolveUse);
00241 }
00242 
00243 
00244 template<class Scalar>
00245 void BelosLinearOpWithSolveFactory<Scalar>::initializeApproxPreconditionedOp(
00246   const RCP<const LinearOpSourceBase<Scalar> > &fwdOpSrc,
00247   const RCP<const LinearOpSourceBase<Scalar> > &approxFwdOpSrc,
00248   LinearOpWithSolveBase<Scalar> *Op,
00249   const ESupportSolveUse supportSolveUse
00250   ) const
00251 {
00252   using Teuchos::null;
00253   initializeOpImpl(fwdOpSrc,approxFwdOpSrc,null,false,Op,supportSolveUse);
00254 }
00255 
00256 
00257 template<class Scalar>
00258 void BelosLinearOpWithSolveFactory<Scalar>::uninitializeOp(
00259   LinearOpWithSolveBase<Scalar> *Op,
00260   RCP<const LinearOpSourceBase<Scalar> > *fwdOpSrc,
00261   RCP<const PreconditionerBase<Scalar> > *prec,
00262   RCP<const LinearOpSourceBase<Scalar> > *approxFwdOpSrc,
00263   ESupportSolveUse *supportSolveUse
00264   ) const
00265 {
00266 #ifdef TEUCHOS_DEBUG
00267   TEUCHOS_TEST_FOR_EXCEPT(Op==NULL);
00268 #endif
00269   BelosLinearOpWithSolve<Scalar>
00270     &belosOp = Teuchos::dyn_cast<BelosLinearOpWithSolve<Scalar> >(*Op);
00271   RCP<const LinearOpSourceBase<Scalar> > 
00272     _fwdOpSrc = belosOp.extract_fwdOpSrc();
00273   RCP<const PreconditionerBase<Scalar> >
00274     _prec = ( belosOp.isExternalPrec() ? belosOp.extract_prec() : Teuchos::null );
00275   // Note: above we only extract the preconditioner if it was passed in
00276   // externally.  Otherwise, we need to hold on to it so that we can reuse it
00277   // in the next initialization.
00278   RCP<const LinearOpSourceBase<Scalar> >
00279     _approxFwdOpSrc = belosOp.extract_approxFwdOpSrc();
00280   ESupportSolveUse
00281     _supportSolveUse = belosOp.supportSolveUse();
00282   if(fwdOpSrc) *fwdOpSrc = _fwdOpSrc;
00283   if(prec) *prec = _prec;
00284   if(approxFwdOpSrc) *approxFwdOpSrc = _approxFwdOpSrc;
00285   if(supportSolveUse) *supportSolveUse = _supportSolveUse;
00286 }
00287 
00288 
00289 // Overridden from ParameterListAcceptor
00290 
00291 
00292 template<class Scalar>
00293 void BelosLinearOpWithSolveFactory<Scalar>::setParameterList(
00294   RCP<Teuchos::ParameterList> const& paramList
00295   )
00296 {
00297   TEUCHOS_TEST_FOR_EXCEPT(paramList.get()==NULL);
00298   paramList->validateParametersAndSetDefaults(*this->getValidParameters(), 1);
00299   paramList_ = paramList;
00300   solverType_ =
00301     Teuchos::getIntegralValue<EBelosSolverType>(*paramList_, SolverType_name);
00302   convergenceTestFrequency_ =
00303     Teuchos::getParameter<int>(*paramList_, ConvergenceTestFrequency_name);
00304   Teuchos::readVerboseObjectSublist(&*paramList_,this);
00305 }
00306 
00307 
00308 template<class Scalar>
00309 RCP<Teuchos::ParameterList>
00310 BelosLinearOpWithSolveFactory<Scalar>::getNonconstParameterList()
00311 {
00312   return paramList_;
00313 }
00314 
00315 
00316 template<class Scalar>
00317 RCP<Teuchos::ParameterList>
00318 BelosLinearOpWithSolveFactory<Scalar>::unsetParameterList()
00319 {
00320   RCP<Teuchos::ParameterList> _paramList = paramList_;
00321   paramList_ = Teuchos::null;
00322   return _paramList;
00323 }
00324 
00325 
00326 template<class Scalar>
00327 RCP<const Teuchos::ParameterList>
00328 BelosLinearOpWithSolveFactory<Scalar>::getParameterList() const
00329 {
00330   return paramList_;
00331 }
00332 
00333 
00334 template<class Scalar>
00335 RCP<const Teuchos::ParameterList>
00336 BelosLinearOpWithSolveFactory<Scalar>::getValidParameters() const
00337 {
00338   return thisValidParamList_;
00339 }
00340 
00341 
00342 // Public functions overridden from Teuchos::Describable
00343 
00344 
00345 template<class Scalar>
00346 std::string BelosLinearOpWithSolveFactory<Scalar>::description() const
00347 {
00348   std::ostringstream oss;
00349   oss << "Thyra::BelosLinearOpWithSolveFactory";
00350   //oss << "{";
00351   // ToDo: Fill this in some!
00352   //oss << "}";
00353   return oss.str();
00354 }
00355 
00356 
00357 // private
00358 
00359 
00360 template<class Scalar>
00361 RCP<const Teuchos::ParameterList>
00362 BelosLinearOpWithSolveFactory<Scalar>::generateAndGetValidParameters()
00363 {
00364   using Teuchos::as;
00365   using Teuchos::tuple;
00366   using Teuchos::setStringToIntegralParameter;
00367 Teuchos::ValidatorXMLConverterDB::addConverter(
00368   Teuchos::DummyObjectGetter<
00369     Teuchos::StringToIntegralParameterEntryValidator<EBelosSolverType> 
00370   >::getDummyObject(),
00371   Teuchos::DummyObjectGetter<Teuchos::StringToIntegralValidatorXMLConverter<
00372     EBelosSolverType> >::getDummyObject());
00373 
00374   typedef MultiVectorBase<Scalar> MV_t;
00375   typedef LinearOpBase<Scalar> LO_t;
00376   static RCP<Teuchos::ParameterList> validParamList;
00377   if(validParamList.get()==NULL) {
00378     validParamList = Teuchos::rcp(new Teuchos::ParameterList("BelosLinearOpWithSolveFactory"));
00379     setStringToIntegralParameter<EBelosSolverType>(
00380       SolverType_name, SolverType_default,
00381       "Type of linear solver algorithm to use.",
00382       tuple<std::string>(
00383         "Block GMRES",
00384         "Pseudo Block GMRES",
00385         "Block CG",
00386         "Pseudo Block CG",
00387         "Pseudo Block Stochastic CG",
00388         "GCRODR",
00389         "RCG",
00390         "MINRES",
00391         "TFQMR"
00392         ),
00393       tuple<std::string>(
00394         "Block GMRES solver for nonsymmetric linear systems.  It can also solve "
00395         "single right-hand side systems, and can also perform Flexible GMRES "
00396         "(where the preconditioner may change at every iteration, for example "
00397         "for inner-outer iterations), by setting options in the \"Block GMRES\" "
00398         "sublist.",
00399 
00400         "GMRES solver for nonsymmetric linear systems, that performs single "
00401         "right-hand side solves on multiple right-hand sides at once.  It "
00402         "exploits operator multivector multiplication in order to amortize "
00403         "global communication costs.  Individual linear systems are deflated "
00404         "out as they are solved.",
00405 
00406         "Block CG solver for symmetric (Hermitian in complex arithmetic) "
00407         "positive definite linear systems.  It can also solve single "
00408         "right-hand-side systems.",
00409 
00410         "CG solver that performs single right-hand side CG on multiple right-hand "
00411         "sides at once.  It exploits operator multivector multiplication in order "
00412         "to amortize global communication costs.  Individual linear systems are "
00413         "deflated out as they are solved.",
00414 
00415         "stochastic CG solver that performs single right-hand side CG on multiple right-hand "
00416         "sides at once.  It exploits operator multivector multiplication in order "
00417         "to amortize global communication costs.  Individual linear systems are "
00418         "deflated out as they are solved. [EXPERIMENTAL]",
00419 
00420         "Variant of GMRES that performs subspace recycling to accelerate "
00421         "convergence for sequences of solves with related linear systems.  "
00422   "Individual linear systems are deflated out as they are solved.  "
00423   "The current implementation only supports real-valued Scalar types.",
00424 
00425         "CG solver for symmetric (Hermitian in complex arithmetic) positive "
00426         "definite linear systems, that performs subspace recycling to "
00427         "accelerate convergence for sequences of related linear systems.",
00428 
00429         "MINRES solver for symmetric indefinite linear systems.  It performs "
00430         "single-right-hand-side solves on multiple right-hand sides sequentially.",
00431 
00432         "TFQMR (Transpose-Free QMR) solver for nonsymmetric linear systems."
00433         ),
00434       tuple<EBelosSolverType>(
00435         SOLVER_TYPE_BLOCK_GMRES,
00436         SOLVER_TYPE_PSEUDO_BLOCK_GMRES,
00437         SOLVER_TYPE_BLOCK_CG,
00438         SOLVER_TYPE_PSEUDO_BLOCK_CG,
00439         SOLVER_TYPE_PSEUDO_BLOCK_STOCHASTIC_CG,
00440         SOLVER_TYPE_GCRODR,
00441         SOLVER_TYPE_RCG,
00442         SOLVER_TYPE_MINRES,
00443         SOLVER_TYPE_TFQMR
00444         ),
00445       &*validParamList
00446       );
00447     validParamList->set(ConvergenceTestFrequency_name, as<int>(1),
00448       "Number of linear solver iterations to skip between applying"
00449       " user-defined convergence test.");
00450     Teuchos::ParameterList
00451       &solverTypesSL = validParamList->sublist(SolverTypes_name);
00452     {
00453       Belos::BlockGmresSolMgr<Scalar,MV_t,LO_t> mgr;
00454       solverTypesSL.sublist(BlockGMRES_name).setParameters(
00455         *mgr.getValidParameters()
00456         );
00457     }
00458     {
00459       Belos::PseudoBlockGmresSolMgr<Scalar,MV_t,LO_t> mgr;
00460       solverTypesSL.sublist(PseudoBlockGMRES_name).setParameters(
00461         *mgr.getValidParameters()
00462         );
00463     }
00464     {
00465       Belos::BlockCGSolMgr<Scalar,MV_t,LO_t> mgr;
00466       solverTypesSL.sublist(BlockCG_name).setParameters(
00467         *mgr.getValidParameters()
00468         );
00469     }
00470     {
00471       Belos::PseudoBlockCGSolMgr<Scalar,MV_t,LO_t> mgr;
00472       solverTypesSL.sublist(PseudoBlockCG_name).setParameters(
00473         *mgr.getValidParameters()
00474         );
00475     }
00476     {
00477       Belos::PseudoBlockStochasticCGSolMgr<Scalar,MV_t,LO_t> mgr;
00478       solverTypesSL.sublist(PseudoBlockStochasticCG_name).setParameters(
00479         *mgr.getValidParameters()
00480         );
00481     }
00482     {
00483       Belos::GCRODRSolMgr<Scalar,MV_t,LO_t> mgr;
00484       solverTypesSL.sublist(GCRODR_name).setParameters(
00485         *mgr.getValidParameters()
00486         );
00487     }
00488     {
00489       Belos::RCGSolMgr<Scalar,MV_t,LO_t> mgr;
00490       solverTypesSL.sublist(RCG_name).setParameters(
00491         *mgr.getValidParameters()
00492         );
00493     }
00494     {
00495       Belos::MinresSolMgr<Scalar,MV_t,LO_t> mgr;
00496       solverTypesSL.sublist(MINRES_name).setParameters(
00497         *mgr.getValidParameters()
00498         );
00499     }
00500     {
00501       Belos::TFQMRSolMgr<Scalar,MV_t,LO_t> mgr;
00502       solverTypesSL.sublist(TFQMR_name).setParameters(
00503         *mgr.getValidParameters()
00504         );
00505     }
00506   }
00507   return validParamList;
00508 }
00509 
00510 
00511 template<class Scalar>
00512 void BelosLinearOpWithSolveFactory<Scalar>::updateThisValidParamList()
00513 {
00514   thisValidParamList_ = Teuchos::rcp(
00515     new Teuchos::ParameterList(*generateAndGetValidParameters())
00516     );
00517   Teuchos::setupVerboseObjectSublist(&*thisValidParamList_);
00518 }
00519 
00520 
00521 template<class Scalar>
00522 void BelosLinearOpWithSolveFactory<Scalar>::initializeOpImpl(
00523   const RCP<const LinearOpSourceBase<Scalar> > &fwdOpSrc,
00524   const RCP<const LinearOpSourceBase<Scalar> > &approxFwdOpSrc,
00525   const RCP<const PreconditionerBase<Scalar> > &prec_in,
00526   const bool reusePrec,
00527   LinearOpWithSolveBase<Scalar> *Op,
00528   const ESupportSolveUse supportSolveUse
00529   ) const
00530 {
00531 
00532   using Teuchos::rcp;
00533   using Teuchos::set_extra_data;
00534   typedef Teuchos::ScalarTraits<Scalar> ST;
00535   typedef MultiVectorBase<Scalar> MV_t;
00536   typedef LinearOpBase<Scalar> LO_t;
00537 
00538   const RCP<Teuchos::FancyOStream> out = this->getOStream();
00539   const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00540   Teuchos::OSTab tab(out);
00541   if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_LOW))
00542     *out << "\nEntering Thyra::BelosLinearOpWithSolveFactory<"<<ST::name()<<">::initializeOpImpl(...) ...\n";
00543 
00544   // These lines are changing the verbosity of the preconditioner, which has its own verbose object list,
00545   // so I am commenting these out, as it is not the job of the linear solver to dictate preconditioner verbosity.
00546   //typedef Teuchos::VerboseObjectTempState<PreconditionerFactoryBase<Scalar> > VOTSPF;
00547   //VOTSPF precFactoryOutputTempState(precFactory_,out,verbLevel);
00548   
00549   TEUCHOS_TEST_FOR_EXCEPT(Op==NULL);
00550   TEUCHOS_TEST_FOR_EXCEPT(fwdOpSrc.get()==NULL);
00551   TEUCHOS_TEST_FOR_EXCEPT(fwdOpSrc->getOp().get()==NULL);
00552   RCP<const LinearOpBase<Scalar> >
00553     fwdOp = fwdOpSrc->getOp(),
00554     approxFwdOp = ( approxFwdOpSrc.get() ? approxFwdOpSrc->getOp() : Teuchos::null );
00555 
00556   //
00557   // Get the BelosLinearOpWithSolve interface
00558   //
00559 
00560   BelosLinearOpWithSolve<Scalar>
00561     *belosOp = &Teuchos::dyn_cast<BelosLinearOpWithSolve<Scalar> >(*Op);
00562 
00563   //
00564   // Get/Create the preconditioner
00565   //
00566 
00567   RCP<PreconditionerBase<Scalar> > myPrec = Teuchos::null;
00568   RCP<const PreconditionerBase<Scalar> > prec = Teuchos::null;
00569   if(prec_in.get()) {
00570     // Use an externally defined preconditioner
00571     prec = prec_in;
00572   }
00573   else {
00574     // Try and generate a preconditioner on our own
00575     if(precFactory_.get()) {
00576       myPrec =
00577         ( !belosOp->isExternalPrec()
00578           ? Teuchos::rcp_const_cast<PreconditionerBase<Scalar> >(belosOp->extract_prec())
00579           : Teuchos::null
00580           );
00581       bool hasExistingPrec = false;
00582       if(myPrec.get()) {
00583         hasExistingPrec = true;
00584         // ToDo: Get the forward operator and validate that it is the same
00585         // operator that is used here!
00586       }
00587       else {
00588         hasExistingPrec = false;
00589         myPrec = precFactory_->createPrec();
00590       }
00591       if( hasExistingPrec && reusePrec ) {
00592         // Just reuse the existing preconditioner again!
00593       }
00594       else {
00595         // Update the preconditioner
00596         if(approxFwdOp.get())
00597           precFactory_->initializePrec(approxFwdOpSrc,&*myPrec);
00598         else
00599           precFactory_->initializePrec(fwdOpSrc,&*myPrec);
00600       }
00601       prec = myPrec;
00602     }
00603   }
00604 
00605   //
00606   // Uninitialize the current solver object
00607   //
00608 
00609   bool oldIsExternalPrec = false;
00610   RCP<Belos::LinearProblem<Scalar,MV_t,LO_t> > oldLP = Teuchos::null;
00611   RCP<Belos::SolverManager<Scalar,MV_t,LO_t> > oldIterSolver = Teuchos::null;
00612   RCP<const LinearOpSourceBase<Scalar> > oldFwdOpSrc = Teuchos::null;
00613   RCP<const LinearOpSourceBase<Scalar> > oldApproxFwdOpSrc = Teuchos::null;   
00614   ESupportSolveUse oldSupportSolveUse = SUPPORT_SOLVE_UNSPECIFIED;
00615 
00616   belosOp->uninitialize( &oldLP, NULL, &oldIterSolver, &oldFwdOpSrc,
00617     NULL, &oldIsExternalPrec, &oldApproxFwdOpSrc, &oldSupportSolveUse );
00618 
00619   //
00620   // Create the Belos linear problem
00621   // NOTE:  If one exists already, reuse it.
00622   //
00623 
00624   typedef Belos::LinearProblem<Scalar,MV_t,LO_t> LP_t;
00625   RCP<LP_t> lp;
00626   if (oldLP != Teuchos::null) {
00627     lp = oldLP;
00628   }
00629   else {
00630     lp = rcp(new LP_t());
00631   }
00632 
00633   //
00634   // Set the operator
00635   //
00636 
00637   lp->setOperator(fwdOp);
00638 
00639   //
00640   // Set the preconditioner
00641   //
00642 
00643   if(prec.get()) {
00644     RCP<const LinearOpBase<Scalar> > unspecified = prec->getUnspecifiedPrecOp();
00645     RCP<const LinearOpBase<Scalar> > left = prec->getLeftPrecOp();
00646     RCP<const LinearOpBase<Scalar> > right = prec->getRightPrecOp();
00647     TEUCHOS_TEST_FOR_EXCEPTION(
00648       !( left.get() || right.get() || unspecified.get() ), std::logic_error
00649       ,"Error, at least one preconditoner linear operator objects must be set!"
00650       );
00651     if(unspecified.get()) {
00652       lp->setRightPrec(unspecified);
00653       // ToDo: Allow user to determine whether this should be placed on the
00654       // left or on the right through a parameter in the parameter list!
00655     }
00656     else {
00657       // Set a left, right or split preconditioner
00658       TEUCHOS_TEST_FOR_EXCEPTION(
00659         left.get(),std::logic_error
00660         ,"Error, we can not currently handle a left preconditioner!"
00661         );
00662       lp->setRightPrec(right);
00663     }
00664   }
00665   if(myPrec.get()) {
00666     set_extra_data<RCP<PreconditionerBase<Scalar> > >(myPrec,"Belos::InternalPrec",
00667       Teuchos::inOutArg(lp), Teuchos::POST_DESTROY, false);
00668   }
00669   else if(prec.get()) {
00670     set_extra_data<RCP<const PreconditionerBase<Scalar> > >(prec,"Belos::ExternalPrec",
00671       Teuchos::inOutArg(lp), Teuchos::POST_DESTROY, false);
00672   }
00673 
00674   //
00675   // Generate the parameter list.
00676   //
00677 
00678   typedef Belos::SolverManager<Scalar,MV_t,LO_t> IterativeSolver_t;
00679   RCP<IterativeSolver_t> iterativeSolver = Teuchos::null;
00680   RCP<Teuchos::ParameterList> solverPL = Teuchos::rcp( new Teuchos::ParameterList() );
00681   
00682   switch(solverType_) {
00683     case SOLVER_TYPE_BLOCK_GMRES: 
00684     {
00685       // Set the PL
00686       if(paramList_.get()) {
00687         Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
00688         Teuchos::ParameterList &gmresPL = solverTypesPL.sublist(BlockGMRES_name);
00689         solverPL = Teuchos::rcp( &gmresPL, false );
00690       }
00691       // Create the solver
00692       if (oldIterSolver != Teuchos::null) {
00693         iterativeSolver = oldIterSolver;
00694         iterativeSolver->setProblem( lp );
00695         iterativeSolver->setParameters( solverPL );
00696       } 
00697       else {
00698         iterativeSolver = rcp(new Belos::BlockGmresSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
00699       }
00700       break;
00701     }
00702     case SOLVER_TYPE_PSEUDO_BLOCK_GMRES:
00703     {
00704       // Set the PL
00705       if(paramList_.get()) {
00706         Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
00707         Teuchos::ParameterList &pbgmresPL = solverTypesPL.sublist(PseudoBlockGMRES_name);
00708         solverPL = Teuchos::rcp( &pbgmresPL, false );
00709       }
00710       // 
00711       // Create the solver
00712       // 
00713       if (oldIterSolver != Teuchos::null) {
00714         iterativeSolver = oldIterSolver;
00715         iterativeSolver->setProblem( lp );
00716         iterativeSolver->setParameters( solverPL );
00717       }
00718       else {
00719         iterativeSolver = rcp(new Belos::PseudoBlockGmresSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
00720       }
00721       break;
00722     }
00723     case SOLVER_TYPE_BLOCK_CG:
00724     {
00725       // Set the PL
00726       if(paramList_.get()) {
00727         Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
00728         Teuchos::ParameterList &cgPL = solverTypesPL.sublist(BlockCG_name);
00729         solverPL = Teuchos::rcp( &cgPL, false );
00730       }
00731       // Create the solver
00732       if (oldIterSolver != Teuchos::null) {
00733         iterativeSolver = oldIterSolver;
00734         iterativeSolver->setProblem( lp );
00735         iterativeSolver->setParameters( solverPL );
00736       }
00737       else {
00738         iterativeSolver = rcp(new Belos::BlockCGSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
00739       }
00740       break;
00741     }
00742     case SOLVER_TYPE_PSEUDO_BLOCK_CG:
00743     {
00744       // Set the PL
00745       if(paramList_.get()) {
00746         Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
00747         Teuchos::ParameterList &pbcgPL = solverTypesPL.sublist(PseudoBlockCG_name);
00748         solverPL = Teuchos::rcp( &pbcgPL, false );
00749       }
00750       // 
00751       // Create the solver
00752       // 
00753       if (oldIterSolver != Teuchos::null) {
00754         iterativeSolver = oldIterSolver;
00755         iterativeSolver->setProblem( lp );
00756         iterativeSolver->setParameters( solverPL );
00757       }
00758       else {
00759         iterativeSolver = rcp(new Belos::PseudoBlockCGSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
00760       }
00761       break;
00762     }
00763     case SOLVER_TYPE_PSEUDO_BLOCK_STOCHASTIC_CG:
00764     {
00765       // Set the PL
00766       if(paramList_.get()) {
00767         Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
00768         Teuchos::ParameterList &pbcgPL = solverTypesPL.sublist(PseudoBlockStochasticCG_name);
00769         solverPL = Teuchos::rcp( &pbcgPL, false );
00770       }
00771       // 
00772       // Create the solver
00773       // 
00774       if (oldIterSolver != Teuchos::null) {
00775         iterativeSolver = oldIterSolver;
00776         iterativeSolver->setProblem( lp );
00777         iterativeSolver->setParameters( solverPL );
00778       }
00779       else {
00780         iterativeSolver = rcp(new Belos::PseudoBlockStochasticCGSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
00781       }
00782       break;
00783     }
00784     case SOLVER_TYPE_GCRODR:
00785     {
00786       // Set the PL
00787       if(paramList_.get()) {
00788         Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
00789         Teuchos::ParameterList &gcrodrPL = solverTypesPL.sublist(GCRODR_name);
00790         solverPL = Teuchos::rcp( &gcrodrPL, false );
00791       }
00792       // Create the solver
00793       if (oldIterSolver != Teuchos::null) {
00794         iterativeSolver = oldIterSolver;
00795         iterativeSolver->setProblem( lp );
00796         iterativeSolver->setParameters( solverPL );
00797       } 
00798       else {
00799         iterativeSolver = rcp(new Belos::GCRODRSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
00800       }
00801       break;
00802     }
00803     case SOLVER_TYPE_RCG:
00804     {
00805       // Set the PL
00806       if(paramList_.get()) {
00807         Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
00808         Teuchos::ParameterList &rcgPL = solverTypesPL.sublist(RCG_name);
00809         solverPL = Teuchos::rcp( &rcgPL, false );
00810       }
00811       // Create the solver
00812       if (oldIterSolver != Teuchos::null) {
00813         iterativeSolver = oldIterSolver;
00814         iterativeSolver->setProblem( lp );
00815         iterativeSolver->setParameters( solverPL );
00816       } 
00817       else {
00818         iterativeSolver = rcp(new Belos::RCGSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
00819       }
00820       break;
00821     }
00822     case SOLVER_TYPE_MINRES:
00823     {
00824       // Set the PL
00825       if(paramList_.get()) {
00826         Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
00827         Teuchos::ParameterList &minresPL = solverTypesPL.sublist(MINRES_name);
00828         solverPL = Teuchos::rcp( &minresPL, false );
00829       }
00830       // Create the solver
00831       if (oldIterSolver != Teuchos::null) {
00832         iterativeSolver = oldIterSolver;
00833         iterativeSolver->setProblem( lp );
00834         iterativeSolver->setParameters( solverPL );
00835       }
00836       else {
00837         iterativeSolver = rcp(new Belos::MinresSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
00838       }
00839       break;
00840     }
00841     case SOLVER_TYPE_TFQMR:
00842     {
00843       // Set the PL
00844       if(paramList_.get()) {
00845         Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
00846         Teuchos::ParameterList &minresPL = solverTypesPL.sublist(TFQMR_name);
00847         solverPL = Teuchos::rcp( &minresPL, false );
00848       }
00849       // Create the solver
00850       if (oldIterSolver != Teuchos::null) {
00851         iterativeSolver = oldIterSolver;
00852         iterativeSolver->setProblem( lp );
00853         iterativeSolver->setParameters( solverPL );
00854       }
00855       else {
00856         iterativeSolver = rcp(new Belos::TFQMRSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
00857       }
00858       break;
00859     }
00860 
00861     default:
00862     {
00863       TEUCHOS_TEST_FOR_EXCEPT(true);
00864     }
00865   }
00866 
00867   //
00868   // Initialize the LOWS object
00869   //
00870 
00871   belosOp->initialize(
00872     lp, solverPL, iterativeSolver,
00873     fwdOpSrc, prec, myPrec.get()==NULL, approxFwdOpSrc,
00874     supportSolveUse, convergenceTestFrequency_
00875     );
00876   belosOp->setOStream(out);
00877   belosOp->setVerbLevel(verbLevel);
00878 #ifdef TEUCHOS_DEBUG
00879   if(paramList_.get()) {
00880     // Make sure we read the list correctly
00881     paramList_->validateParameters(*this->getValidParameters(),1); // Validate 0th and 1st level deep
00882   }
00883 #endif
00884   if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_LOW))
00885     *out << "\nLeaving Thyra::BelosLinearOpWithSolveFactory<"<<ST::name()<<">::initializeOpImpl(...) ...\n";
00886   
00887 }
00888 
00889 
00890 } // namespace Thyra
00891 
00892 
00893 #endif // THYRA_BELOS_LINEAR_OP_WITH_SOLVE_FACTORY_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines