|
Stratimikos Package Browser (Single Doxygen Collection)
Version of the Day
|
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
1.7.6.1