|
Stratimikos Package Browser (Single Doxygen Collection)
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Stratimikos: Thyra-based strategies for linear solvers 00005 // Copyright (2006) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 00043 #ifndef SUN_CXX 00044 00045 00046 #include "Thyra_AztecOOLinearOpWithSolveFactory.hpp" 00047 #include "Thyra_AztecOOLinearOpWithSolve.hpp" 00048 #include "Thyra_PreconditionerFactoryHelpers.hpp" 00049 #include "Thyra_EpetraOperatorViewExtractorStd.hpp" 00050 #include "Thyra_ScaledAdjointLinearOpBase.hpp" 00051 #include "Thyra_EpetraLinearOpBase.hpp" 00052 #include "Thyra_EpetraOperatorWrapper.hpp" 00053 #include "EpetraExt_ProductOperator.h" 00054 #include "Teuchos_VerboseObjectParameterListHelpers.hpp" 00055 #include "Teuchos_ParameterList.hpp" 00056 #include "Teuchos_dyn_cast.hpp" 00057 #include "AztecOOParameterList.hpp" 00058 00059 00060 namespace { 00061 00062 00063 const std::string AOOLOWSF_epetraPrecOp_str 00064 = "AOOLOWSF::epetraPrecOp"; 00065 const std::string AOOLOWSF_aztec_epetra_epetraFwdOp_str 00066 = "AOOLOWSF::aztec_epetra_epetraFwdOp"; 00067 const std::string AOOLOWSF_aztec_epetra_epetraAdjOp_str 00068 = "AOOLOWSF::aztec_epetra_epetraAdjOp"; 00069 const std::string AOOLOWSF_rowmatrix_epetraFwdOp_str 00070 = "AOOLOWSF::rowmatrix_epetraFwdOp"; 00071 const std::string AOOLOWSF_rowmatrix_epetraPrecOp_str 00072 = "AOOLOWSF::rowmatrix_epetraPrecOp"; 00073 const std::string AOOLOWSF_aztec_fwd_epetra_epetraPrecOp_str 00074 = "AOOLOWSF::aztec_fwd_epetra_epetraPrecOp"; 00075 const std::string AOOLOWSF_aztec_adj_epetra_epetraPrecOp_str 00076 = "AOOLOWSF::aztec_adj_epetra_epetraPrecOp"; 00077 const std::string AOOLOWSF_setPrecondtionerOperator_str 00078 = "AOOLOWSF::setPrecondtionerOperator"; 00079 const std::string AOOLOWSF_constructedAztecPreconditoner_str 00080 = "AOOLOWSF::constructedAztecPreconditoner"; 00081 00082 00083 const std::string ForwardSolve_name = "Forward Solve"; 00084 const std::string AdjointSolve_name = "Adjoint Solve"; 00085 const std::string MaxIterations_name = "Max Iterations"; 00086 const int MaxIterations_default = 400; 00087 const std::string Tolerance_name = "Tolerance"; 00088 const double Tolerance_default = 1e-6; 00089 const std::string OutputEveryRhs_name = "Output Every RHS"; 00090 const bool OutputEveryRhs_default = false; 00091 const std::string AztecOO_Settings_name = "AztecOO Settings"; 00092 00093 00094 } // namespace 00095 00096 00097 namespace Thyra { 00098 00099 00100 // Constructors/initializers/accessors 00101 00102 00103 AztecOOLinearOpWithSolveFactory::AztecOOLinearOpWithSolveFactory( 00104 Teuchos::RCP<Teuchos::ParameterList> const& paramList 00105 ) 00106 :epetraFwdOpViewExtractor_(Teuchos::rcp(new EpetraOperatorViewExtractorStd())) 00107 ,defaultFwdMaxIterations_(MaxIterations_default) 00108 ,defaultFwdTolerance_(Tolerance_default) 00109 ,defaultAdjMaxIterations_(MaxIterations_default) 00110 ,defaultAdjTolerance_(Tolerance_default) 00111 ,outputEveryRhs_(OutputEveryRhs_default) 00112 ,useAztecPrec_(false) 00113 { 00114 updateThisValidParamList(); 00115 if(paramList.get()) 00116 setParameterList(paramList); 00117 } 00118 00119 00120 // Overridden from LinearOpWithSolveFactoryBase 00121 00122 00123 bool AztecOOLinearOpWithSolveFactory::acceptsPreconditionerFactory() const 00124 { 00125 return true; 00126 } 00127 00128 00129 void AztecOOLinearOpWithSolveFactory::setPreconditionerFactory( 00130 const Teuchos::RCP<PreconditionerFactoryBase<double> > &precFactory, 00131 const std::string &precFactoryName 00132 ) 00133 { 00134 TEUCHOS_TEST_FOR_EXCEPT(!precFactory.get()); 00135 Teuchos::RCP<const Teuchos::ParameterList> 00136 precFactoryValidPL = precFactory->getValidParameters(); 00137 const std::string _precFactoryName = 00138 ( precFactoryName != "" 00139 ? precFactoryName 00140 : ( precFactoryValidPL.get() 00141 ? precFactoryValidPL->name() 00142 : "GENERIC PRECONDITIONER FACTORY" 00143 ) 00144 ); 00145 precFactory_ = precFactory; 00146 precFactoryName_ = _precFactoryName; 00147 updateThisValidParamList(); 00148 } 00149 00150 00151 Teuchos::RCP<PreconditionerFactoryBase<double> > 00152 AztecOOLinearOpWithSolveFactory::getPreconditionerFactory() const 00153 { 00154 return precFactory_; 00155 } 00156 00157 00158 void AztecOOLinearOpWithSolveFactory::unsetPreconditionerFactory( 00159 Teuchos::RCP<PreconditionerFactoryBase<double> > *precFactory, 00160 std::string *precFactoryName 00161 ) 00162 { 00163 if(precFactory) *precFactory = precFactory_; 00164 if(precFactoryName) *precFactoryName = precFactoryName_; 00165 precFactory_ = Teuchos::null; 00166 precFactoryName_ = ""; 00167 updateThisValidParamList(); 00168 } 00169 00170 00171 bool AztecOOLinearOpWithSolveFactory::isCompatible( 00172 const LinearOpSourceBase<double> &fwdOpSrc 00173 ) const 00174 { 00175 return epetraFwdOpViewExtractor_->isCompatible(*fwdOpSrc.getOp()); 00176 } 00177 00178 00179 Teuchos::RCP<LinearOpWithSolveBase<double> > 00180 AztecOOLinearOpWithSolveFactory::createOp() const 00181 { 00182 return Teuchos::rcp(new AztecOOLinearOpWithSolve()); 00183 } 00184 00185 00186 void AztecOOLinearOpWithSolveFactory::initializeOp( 00187 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc, 00188 LinearOpWithSolveBase<double> *Op, 00189 const ESupportSolveUse supportSolveUse 00190 ) const 00191 { 00192 this->initializeOp_impl(fwdOpSrc,Teuchos::null,Teuchos::null,false,Op); 00193 } 00194 00195 00196 void AztecOOLinearOpWithSolveFactory::initializeAndReuseOp( 00197 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc, 00198 LinearOpWithSolveBase<double> *Op 00199 ) const 00200 { 00201 this->initializeOp_impl(fwdOpSrc,Teuchos::null,Teuchos::null,true,Op); 00202 } 00203 00204 00205 bool AztecOOLinearOpWithSolveFactory::supportsPreconditionerInputType( 00206 const EPreconditionerInputType precOpType 00207 ) const 00208 { 00209 const_cast<bool&>(useAztecPrec_) = ( 00210 paramList_.get() 00211 && 00212 paramList_->sublist(ForwardSolve_name).sublist(AztecOO_Settings_name).get( 00213 "Aztec Preconditioner","none" 00214 )!="none" 00215 ); 00216 switch(precOpType) { 00217 case PRECONDITIONER_INPUT_TYPE_AS_OPERATOR: 00218 return true; 00219 break; 00220 case PRECONDITIONER_INPUT_TYPE_AS_MATRIX: 00221 return useAztecPrec_; 00222 break; 00223 default: 00224 TEUCHOS_TEST_FOR_EXCEPT(true); 00225 } 00226 return PRECONDITIONER_INPUT_TYPE_AS_OPERATOR; // Should never be called! 00227 } 00228 00229 00230 void AztecOOLinearOpWithSolveFactory::initializePreconditionedOp( 00231 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc, 00232 const Teuchos::RCP<const PreconditionerBase<double> > &prec, 00233 LinearOpWithSolveBase<double> *Op, 00234 const ESupportSolveUse supportSolveUse 00235 ) const 00236 { 00237 TEUCHOS_TEST_FOR_EXCEPT(prec.get()==NULL); 00238 this->initializeOp_impl(fwdOpSrc,prec,Teuchos::null,false,Op); 00239 } 00240 00241 00242 void AztecOOLinearOpWithSolveFactory::initializeApproxPreconditionedOp( 00243 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc, 00244 const Teuchos::RCP<const LinearOpSourceBase<double> > &approxFwdOpSrc, 00245 LinearOpWithSolveBase<double> *Op, 00246 const ESupportSolveUse supportSolveUse 00247 ) const 00248 { 00249 TEUCHOS_TEST_FOR_EXCEPT(approxFwdOpSrc.get()==NULL); 00250 TEUCHOS_TEST_FOR_EXCEPT(approxFwdOpSrc->getOp().get()==NULL); 00251 this->initializeOp_impl(fwdOpSrc,Teuchos::null,approxFwdOpSrc,false,Op); 00252 } 00253 00254 00255 void AztecOOLinearOpWithSolveFactory::uninitializeOp( 00256 LinearOpWithSolveBase<double> *Op, 00257 Teuchos::RCP<const LinearOpSourceBase<double> > *fwdOpSrc, 00258 Teuchos::RCP<const PreconditionerBase<double> > *prec, 00259 Teuchos::RCP<const LinearOpSourceBase<double> > *approxFwdOpSrc, 00260 ESupportSolveUse *supportSolveUse 00261 ) const 00262 { 00263 #ifdef TEUCHOS_DEBUG 00264 TEUCHOS_TEST_FOR_EXCEPT(Op==NULL); 00265 #endif 00266 AztecOOLinearOpWithSolve 00267 *aztecOp = &Teuchos::dyn_cast<AztecOOLinearOpWithSolve>(*Op); 00268 // Extract and unset the fwdOP and approxFwdOp objects 00269 Teuchos::RCP<const LinearOpSourceBase<double> > 00270 _fwdOpSrc = aztecOp->extract_fwdOpSrc(), // Will be null if not initialized! 00271 _approxFwdOpSrc = aztecOp->extract_approxFwdOpSrc(); // Will be null if not set 00272 if(fwdOpSrc) *fwdOpSrc = _fwdOpSrc; 00273 if(approxFwdOpSrc) *approxFwdOpSrc = _approxFwdOpSrc; 00274 // Only extract and uset the prec object if it is external. If it is 00275 // internal, then we need to hold on to this so that we can reinitialize it 00276 // later. 00277 if(aztecOp->isExternalPrec()) { 00278 Teuchos::RCP<const PreconditionerBase<double> > 00279 _prec = aztecOp->extract_prec(); // Will be null if not external preconditioner was set 00280 if(prec) *prec = _prec; 00281 } 00282 // ToDo: Extract the Epetra_Operator views what where used to initialize the 00283 // forward and adjoint solvers! This is needed to make this totally 00284 // stateless. 00285 } 00286 00287 00288 // Overridden from ParameterListAcceptor 00289 00290 00291 void AztecOOLinearOpWithSolveFactory::setParameterList( 00292 Teuchos::RCP<Teuchos::ParameterList> const& paramList 00293 ) 00294 { 00295 TEUCHOS_TEST_FOR_EXCEPT(paramList.get()==NULL); 00296 paramList->validateParameters(*this->getValidParameters()); 00297 paramList_ = paramList; 00298 // 00299 outputEveryRhs_ = paramList_->get(OutputEveryRhs_name,OutputEveryRhs_default); 00300 // Foward Solve parameters 00301 Teuchos::ParameterList 00302 &fwdSolvePL = paramList_->sublist(ForwardSolve_name); 00303 defaultFwdMaxIterations_ = fwdSolvePL.get(MaxIterations_name,defaultFwdMaxIterations_); 00304 defaultFwdTolerance_ = fwdSolvePL.get(Tolerance_name,defaultFwdTolerance_); 00305 // Adjoint Solve parameters 00306 if( !paramList_->getPtr<Teuchos::ParameterList>(AdjointSolve_name) ) { 00307 // If adjoint solve sublist is not set, then use the forward solve parameters 00308 paramList_->sublist(AdjointSolve_name).setParameters(fwdSolvePL); 00309 } 00310 Teuchos::ParameterList 00311 &adjSolvePL = paramList_->sublist(AdjointSolve_name); 00312 defaultAdjMaxIterations_ = adjSolvePL.get(MaxIterations_name,defaultAdjMaxIterations_); 00313 defaultAdjTolerance_ = adjSolvePL.get(Tolerance_name,defaultAdjTolerance_); 00314 // 00315 if(precFactory_.get()) { 00316 // Only reset the PF's PL if the sublist exists or the PF does not already 00317 // have a PL. We don't want to overwrite an externally set PL for the PF 00318 // if we don't have a nested sublist defined here! 00319 const bool nestedPFSublistExists = paramList_->isSublist(precFactoryName_); 00320 const bool alreadyHasSublist = !is_null(precFactory_->getParameterList()); 00321 if( nestedPFSublistExists || !alreadyHasSublist ) { 00322 precFactory_->setParameterList(Teuchos::sublist(paramList_,precFactoryName_)); 00323 } 00324 } 00325 Teuchos::readVerboseObjectSublist(&*paramList_,this); 00326 } 00327 00328 00329 Teuchos::RCP<Teuchos::ParameterList> 00330 AztecOOLinearOpWithSolveFactory::getNonconstParameterList() 00331 { 00332 return paramList_; 00333 } 00334 00335 00336 Teuchos::RCP<Teuchos::ParameterList> 00337 AztecOOLinearOpWithSolveFactory::unsetParameterList() 00338 { 00339 Teuchos::RCP<Teuchos::ParameterList> _paramList = paramList_; 00340 paramList_ = Teuchos::null; 00341 return _paramList; 00342 } 00343 00344 00345 Teuchos::RCP<const Teuchos::ParameterList> 00346 AztecOOLinearOpWithSolveFactory::getParameterList() const 00347 { 00348 return paramList_; 00349 } 00350 00351 00352 Teuchos::RCP<const Teuchos::ParameterList> 00353 AztecOOLinearOpWithSolveFactory::getValidParameters() const 00354 { 00355 return thisValidParamList_; 00356 } 00357 00358 00359 // Public functions overridden from Teuchos::Describable 00360 00361 00362 std::string AztecOOLinearOpWithSolveFactory::description() const 00363 { 00364 std::ostringstream oss; 00365 oss << "Thyra::AztecOOLinearOpWithSolveFactory{"; 00366 oss << "precFactory="; 00367 if(!is_null(precFactory_)) 00368 oss << precFactory_->description(); 00369 else 00370 oss << "NULL"; 00371 oss << "}"; 00372 return oss.str(); 00373 } 00374 00375 00376 // private 00377 00378 00379 Teuchos::RCP<const Teuchos::ParameterList> 00380 AztecOOLinearOpWithSolveFactory::generateAndGetValidParameters() 00381 { 00382 static Teuchos::RCP<Teuchos::ParameterList> validParamList; 00383 if(validParamList.get()==NULL) { 00384 validParamList = Teuchos::rcp( 00385 new Teuchos::ParameterList("AztecOOLinearOpWithSolveFactory")); 00386 validParamList->set( 00387 OutputEveryRhs_name,OutputEveryRhs_default 00388 ,"Determines if output is created for each individual RHS (true or 1) or if output\n" 00389 "is just created for an entire set of RHSs (false or 0)." 00390 ); 00391 static Teuchos::RCP<const Teuchos::ParameterList> 00392 aztecParamList = getValidAztecOOParameters(); 00393 Teuchos::ParameterList 00394 &fwdSolvePL = validParamList->sublist( 00395 ForwardSolve_name, false 00396 ,"Gives the options for the forward solve." 00397 ); 00398 fwdSolvePL.set( 00399 Tolerance_name,Tolerance_default 00400 ,"The tolerence used in the convergence check (see the convergence test\n" 00401 "in the sublist \"" + AztecOO_Settings_name + "\")" 00402 ); 00403 fwdSolvePL.set( 00404 MaxIterations_name,MaxIterations_default 00405 ,"The maximum number of iterations the AztecOO solver is allowed to perform." 00406 ); 00407 fwdSolvePL.sublist( 00408 AztecOO_Settings_name,false 00409 ,"Sets the parameters on the AztecOO object itself." 00410 ).setParameters(*aztecParamList); 00411 Teuchos::ParameterList 00412 &adjSolvePL = validParamList->sublist( 00413 AdjointSolve_name, false 00414 ,"The options for the adjoint solve.\n" 00415 "If this sublist is missing then the parameters from the\n" 00416 "\""+ForwardSolve_name+"\" sublist are used instead." 00417 ); 00418 // Make the adjoint solve have same defaults as forward solve 00419 adjSolvePL.setParameters(fwdSolvePL); 00420 } 00421 return validParamList; 00422 } 00423 00424 00425 void AztecOOLinearOpWithSolveFactory::updateThisValidParamList() 00426 { 00427 thisValidParamList_ = Teuchos::rcp( 00428 new Teuchos::ParameterList(*generateAndGetValidParameters()) 00429 ); 00430 if(precFactory_.get()) { 00431 Teuchos::RCP<const Teuchos::ParameterList> 00432 precFactoryValidParamList = precFactory_->getValidParameters(); 00433 if(precFactoryValidParamList.get()) { 00434 thisValidParamList_->sublist(precFactoryName_).setParameters( 00435 *precFactoryValidParamList); 00436 } 00437 } 00438 Teuchos::setupVerboseObjectSublist(&*thisValidParamList_); 00439 } 00440 00441 00442 void AztecOOLinearOpWithSolveFactory::initializeOp_impl( 00443 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc, 00444 const Teuchos::RCP<const PreconditionerBase<double> > &prec, 00445 const Teuchos::RCP<const LinearOpSourceBase<double> > &approxFwdOpSrc, 00446 const bool reusePrec, 00447 LinearOpWithSolveBase<double> *Op 00448 ) const 00449 { 00450 using Teuchos::RCP; 00451 using Teuchos::null; 00452 using Teuchos::rcp; 00453 using Teuchos::rcp_dynamic_cast; 00454 using Teuchos::rcp_const_cast; 00455 using Teuchos::set_extra_data; 00456 using Teuchos::get_optional_extra_data; 00457 using Teuchos::get_optional_nonconst_extra_data; 00458 using Teuchos::outArg; 00459 typedef EpetraExt::ProductOperator PO; 00460 00461 const Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream(); 00462 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel(); 00463 Teuchos::OSTab tab(out); 00464 if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_LOW)) 00465 *out << "\nEntering Thyra::AztecOOLinearOpWithSolveFactory::initializeOp_impl(...) ...\n"; 00466 00467 typedef Teuchos::VerboseObjectTempState<PreconditionerFactoryBase<double> > VOTSPF; 00468 VOTSPF precFactoryOutputTempState(precFactory_,out,verbLevel); 00469 00470 #ifdef TEUCHOS_DEBUG 00471 TEUCHOS_TEST_FOR_EXCEPT(Op==NULL); 00472 TEUCHOS_TEST_FOR_EXCEPT(fwdOpSrc.get()==NULL); 00473 TEUCHOS_TEST_FOR_EXCEPT(fwdOpSrc->getOp().get()==NULL); 00474 #endif 00475 00476 // 00477 // Determine whether the operators are EpetraLinearOp objects. If so, we're 00478 // good to go. If not, we need to wrap it as an Epetra_Operator with some 00479 // invasive code. 00480 // 00481 Teuchos::RCP<const LinearOpBase<double> > 00482 tmpFwdOp = fwdOpSrc->getOp(), 00483 tmpApproxFwdOp = ( approxFwdOpSrc.get() ? approxFwdOpSrc->getOp() : Teuchos::null ); 00484 Teuchos::RCP<const LinearOpBase<double> > fwdOp; 00485 Teuchos::RCP<const LinearOpBase<double> > approxFwdOp; 00486 if ( dynamic_cast<const EpetraLinearOpBase*>(tmpFwdOp.get())!=0 ) 00487 { 00488 fwdOp = tmpFwdOp; 00489 approxFwdOp = tmpApproxFwdOp; 00490 } 00491 else 00492 { 00493 fwdOp = makeEpetraWrapper(tmpFwdOp); 00494 if ( 00495 tmpApproxFwdOp.get() 00496 && 00497 dynamic_cast<const EpetraLinearOpBase*>(&*tmpApproxFwdOp.get()) 00498 ) 00499 { 00500 approxFwdOp = makeEpetraWrapper(tmpApproxFwdOp); 00501 } 00502 } 00503 00504 // 00505 // Get the AztecOOLinearOpWithSolve object 00506 // 00507 AztecOOLinearOpWithSolve 00508 *aztecOp = &Teuchos::dyn_cast<AztecOOLinearOpWithSolve>(*Op); 00509 00510 // 00511 // Unwrap and get the forward operator or matrix 00512 // 00513 Teuchos::RCP<const Epetra_Operator> epetra_epetraFwdOp; 00514 EOpTransp epetra_epetraFwdOpTransp; 00515 EApplyEpetraOpAs epetra_epetraFwdOpApplyAs; 00516 EAdjointEpetraOp epetra_epetraFwdOpAdjointSupport; 00517 double epetra_epetraFwdOpScalar; 00518 epetraFwdOpViewExtractor_->getEpetraOpView( 00519 fwdOp, 00520 outArg(epetra_epetraFwdOp), outArg(epetra_epetraFwdOpTransp), 00521 outArg(epetra_epetraFwdOpApplyAs), outArg(epetra_epetraFwdOpAdjointSupport), 00522 outArg(epetra_epetraFwdOpScalar) 00523 ); 00524 TEUCHOS_TEST_FOR_EXCEPTION( 00525 epetra_epetraFwdOp.get()==NULL, std::logic_error 00526 ,"Error, The input fwdOp object must be fully initialized " 00527 "before calling this function!" 00528 ); 00529 00530 // 00531 // Get the preconditioner object to use 00532 // 00533 Teuchos::RCP<PreconditionerBase<double> > myPrec; 00534 Teuchos::RCP<const PreconditionerBase<double> > precUsed; 00535 if (prec.get()) { 00536 // We will be used the passed in external preconditioner 00537 precUsed = prec; 00538 } 00539 else if (precFactory_.get() ) { 00540 // We will be creating our own preconditioner using an externally set 00541 // preconditioner factory 00542 myPrec = 00543 ( !aztecOp->isExternalPrec() 00544 ? Teuchos::rcp_const_cast<PreconditionerBase<double> >( 00545 aztecOp->extract_prec()) 00546 : Teuchos::null 00547 ); 00548 if(myPrec.get()) { 00549 // ToDo: Get the forward operator and validate that it is the same 00550 // operator that is used here! 00551 } 00552 else { 00553 myPrec = precFactory_->createPrec(); 00554 } 00555 precFactory_->initializePrec(fwdOpSrc,&*myPrec); 00556 precUsed = myPrec; 00557 } 00558 00559 // 00560 // Unwrap and get the preconditioner operator 00561 // 00562 RCP<const LinearOpBase<double> > rightPrecOp; 00563 if (precUsed.get()) { 00564 RCP<const LinearOpBase<double> > unspecified = precUsed->getUnspecifiedPrecOp(); 00565 RCP<const LinearOpBase<double> > left = precUsed->getLeftPrecOp(); 00566 RCP<const LinearOpBase<double> > right = precUsed->getRightPrecOp(); 00567 TEUCHOS_TEST_FOR_EXCEPTION( 00568 !( left.get() || right.get() || unspecified.get() ), std::logic_error 00569 ,"Error, at least one preconditoner linear operator objects must be set!" 00570 ); 00571 if(unspecified.get()) { 00572 rightPrecOp = unspecified; 00573 } 00574 else { 00575 // Set a left, right or split preconditioner 00576 TEUCHOS_TEST_FOR_EXCEPTION( 00577 left.get(),std::logic_error 00578 ,"Error, we can not currently handle a left" 00579 " preconditioner with the AztecOO/Thyra adapters!" 00580 ); 00581 rightPrecOp = right; 00582 } 00583 } 00584 double wrappedPrecOpScalar = 0.0; 00585 EOpTransp wrappedPrecOpTransp = NOTRANS; 00586 RCP<const LinearOpBase<double> > wrappedPrecOp = null; 00587 RCP<const EpetraLinearOpBase> epetraPrecOp; 00588 Teuchos::RCP<const Epetra_Operator> epetra_epetraPrecOp; 00589 EOpTransp epetra_epetraPrecOpTransp; 00590 EApplyEpetraOpAs epetra_epetraPrecOpApplyAs; 00591 EAdjointEpetraOp epetra_epetraPrecOpAdjointSupport; 00592 EOpTransp overall_epetra_epetraPrecOpTransp; 00593 if(rightPrecOp.get()) { 00594 RCP<const LinearOpBase<double> > tmpWrappedPrecOp; 00595 unwrap( 00596 rightPrecOp,&wrappedPrecOpScalar,&wrappedPrecOpTransp,&tmpWrappedPrecOp); 00597 if( dynamic_cast<const EpetraLinearOpBase*>(&*tmpWrappedPrecOp) ) { 00598 wrappedPrecOp = tmpWrappedPrecOp; 00599 } 00600 else { 00601 wrappedPrecOp = makeEpetraWrapper(tmpWrappedPrecOp); 00602 } 00603 epetraPrecOp = rcp_dynamic_cast<const EpetraLinearOpBase>( 00604 wrappedPrecOp,true); 00605 epetraPrecOp->getEpetraOpView( 00606 outArg(epetra_epetraPrecOp), outArg(epetra_epetraPrecOpTransp), 00607 outArg(epetra_epetraPrecOpApplyAs), outArg(epetra_epetraPrecOpAdjointSupport)); 00608 TEUCHOS_TEST_FOR_EXCEPTION( 00609 epetra_epetraPrecOp.get()==NULL,std::logic_error 00610 ,"Error, The input prec object and its embedded preconditioner" 00611 " operator must be fully initialized before calling this function!" 00612 ); 00613 // 2007/08/10: rabartl: This next set_extra_data(...) call is likely to be 00614 // setting up a circular reference! Since epetra_epetraPrecOp was 00615 // gotten from epetraPrecOp, if you set epetraPrecOp as extra data 00616 // on the RCP epetra_epetraPrecOp then you have a circular reference! 00617 //set_extra_data( 00618 // epetraPrecOp, AOOLOWSF_epetraPrecOp_str, &epetra_epetraPrecOp, 00619 // Teuchos::POST_DESTROY, false ); 00620 overall_epetra_epetraPrecOpTransp 00621 = trans_trans( 00622 real_trans(wrappedPrecOpTransp), 00623 real_trans(epetra_epetraPrecOpTransp) 00624 ); 00625 } 00626 00627 // 00628 // Unwrap and get the approximate forward operator to be used to generate a 00629 // preconditioner 00630 // 00631 if(approxFwdOp.get()) { 00632 // Note, here we just use the same members data that would be set for an 00633 // extenral preconditioner operator since it is not getting used. 00634 unwrap(approxFwdOp,&wrappedPrecOpScalar,&wrappedPrecOpTransp,&wrappedPrecOp); 00635 epetraPrecOp = rcp_dynamic_cast<const EpetraLinearOpBase>( 00636 wrappedPrecOp,true); 00637 epetraPrecOp->getEpetraOpView( 00638 outArg(epetra_epetraPrecOp), outArg(epetra_epetraPrecOpTransp), 00639 outArg(epetra_epetraPrecOpApplyAs), outArg(epetra_epetraPrecOpAdjointSupport) 00640 ); 00641 TEUCHOS_TEST_FOR_EXCEPTION( 00642 epetra_epetraPrecOp.get()==NULL,std::logic_error 00643 ,"Error, The input approxFwdOp object must be fully initialized" 00644 " before calling this function!" 00645 ); 00646 // 2007/08/10: rabartl: This next set_extra_data(...) call is likely to be 00647 // setting up a circular reference! Since epetra_epetraPrecOp was 00648 // gotten from epetraPrecOp, if you set epetraPrecOp as extra data 00649 // on the RCP epetra_epetraPrecOp then you have a circular reference! 00650 //set_extra_data( 00651 // epetraPrecOp, AOOLOWSF_epetraPrecOp_str, &epetra_epetraPrecOp, 00652 // Teuchos::POST_DESTROY, false 00653 // ); 00654 overall_epetra_epetraPrecOpTransp 00655 = trans_trans( 00656 real_trans(wrappedPrecOpTransp), 00657 real_trans(epetra_epetraPrecOpTransp) 00658 ); 00659 } 00660 00661 // 00662 // Determine if the forward and preconditioner operators are a row matrices 00663 // or not 00664 // 00665 RCP<const Epetra_RowMatrix> 00666 rowmatrix_epetraFwdOp = rcp_dynamic_cast<const Epetra_RowMatrix>( 00667 epetra_epetraFwdOp), 00668 rowmatrix_epetraPrecOp = rcp_dynamic_cast<const Epetra_RowMatrix>( 00669 epetra_epetraPrecOp); 00670 // 00671 // Determine the type of preconditoner 00672 // 00673 // Update useAztecPrec_, input value does not matter 00674 this->supportsPreconditionerInputType(PRECONDITIONER_INPUT_TYPE_AS_MATRIX); 00675 enum ELocalPrecType { 00676 PT_NONE, PT_AZTEC_FROM_OP, PT_AZTEC_FROM_APPROX_FWD_MATRIX, 00677 PT_FROM_PREC_OP 00678 }; 00679 ELocalPrecType localPrecType; 00680 if( precUsed.get()==NULL && approxFwdOp.get()==NULL && !useAztecPrec_ ) { 00681 // No preconditioning at all! 00682 localPrecType = PT_NONE; 00683 } 00684 else if( precUsed.get()==NULL && approxFwdOp.get()==NULL && useAztecPrec_ ) { 00685 // We are using the forward matrix for the preconditioner using aztec 00686 // preconditioners 00687 localPrecType = PT_AZTEC_FROM_OP; 00688 } 00689 else if( approxFwdOp.get() && useAztecPrec_ ) { 00690 // The preconditioner comes from the input as a matrix and we are using 00691 // aztec preconditioners 00692 localPrecType = PT_AZTEC_FROM_APPROX_FWD_MATRIX; 00693 } 00694 else if( precUsed.get() ) { 00695 // The preconditioner comes as an external operator so let's use it as 00696 // such 00697 localPrecType = PT_FROM_PREC_OP; 00698 } 00699 00700 // 00701 // Determine if aztecOp already contains solvers and if we need to 00702 // reinitialize or not 00703 // 00704 RCP<AztecOO> aztecFwdSolver, aztecAdjSolver; 00705 bool startingOver; 00706 { 00707 // Let's assume that fwdOp, prec and/or approxFwdOp are compatible with 00708 // the already created AztecOO objects. If they are not, then the client 00709 // should have created a new LOWSB object from scratch! 00710 Teuchos::RCP<const LinearOpBase<double> > old_fwdOp; 00711 Teuchos::RCP<const LinearOpSourceBase<double> > old_fwdOpSrc; 00712 Teuchos::RCP<const PreconditionerBase<double> > old_prec; 00713 bool old_isExternalPrec; 00714 Teuchos::RCP<const LinearOpSourceBase<double> > old_approxFwdOpSrc; 00715 Teuchos::RCP<AztecOO> old_aztecFwdSolver; 00716 Teuchos::RCP<AztecOO> old_aztecAdjSolver; 00717 double old_aztecSolverScalar; 00718 aztecOp->uninitialize( 00719 &old_fwdOp 00720 ,&old_fwdOpSrc 00721 ,&old_prec 00722 ,&old_isExternalPrec 00723 ,&old_approxFwdOpSrc 00724 ,&old_aztecFwdSolver 00725 ,NULL 00726 ,&old_aztecAdjSolver 00727 ,NULL 00728 ,&old_aztecSolverScalar 00729 ); 00730 if( old_aztecFwdSolver.get()==NULL ) { 00731 // This has never been initialized before 00732 startingOver = true; 00733 } 00734 else { 00735 // Let's assume that fwdOp, prec and/or approxFwdOp are compatible with 00736 // the already created AztecOO objects. If they are not, then the 00737 // client should have created a new LOWSB object from scratch! 00738 aztecFwdSolver = old_aztecFwdSolver; 00739 aztecAdjSolver = old_aztecAdjSolver; 00740 startingOver = false; 00741 // We must wipe out the old preconditoner if we are not reusing the 00742 // preconditioner 00743 Ptr<bool> constructedAztecPreconditioner; 00744 if( 00745 !reusePrec 00746 && 00747 !is_null(constructedAztecPreconditioner = get_optional_nonconst_extra_data<bool>( 00748 aztecFwdSolver, "AOOLOWSF::constructedAztecPreconditoner") ) 00749 && 00750 *constructedAztecPreconditioner 00751 ) 00752 { 00753 aztecFwdSolver->DestroyPreconditioner(); 00754 *constructedAztecPreconditioner = false; 00755 } 00756 // We must see if we set an external preconditioner but will not do so 00757 // again in which case we must blow away AztecOO and start over again! 00758 Ptr<bool> setPreconditionerOperator; 00759 if( 00760 localPrecType != PT_FROM_PREC_OP 00761 && !is_null( setPreconditionerOperator = get_optional_nonconst_extra_data<bool>( 00762 aztecFwdSolver,"AOOLOWSF::setPreconditonerOperator") ) 00763 && *setPreconditionerOperator 00764 ) 00765 { 00766 // We must start over again since there is no way to unset an external 00767 // preconditioner! 00768 startingOver = true; 00769 } 00770 } 00771 } 00772 00773 // 00774 // Create the AztecOO solvers if we are starting over 00775 // 00776 startingOver = true; // ToDo: Remove this and figure out why this is not working! 00777 if(startingOver) { 00778 // Forward solver 00779 aztecFwdSolver = rcp(new AztecOO()); 00780 aztecFwdSolver->SetAztecOption(AZ_diagnostics,AZ_none); // This was turned off in NOX? 00781 aztecFwdSolver->SetAztecOption(AZ_keep_info,1); 00782 // Adjoint solver (if supported) 00783 if( 00784 epetra_epetraFwdOpAdjointSupport==EPETRA_OP_ADJOINT_SUPPORTED 00785 && 00786 localPrecType!=PT_AZTEC_FROM_OP && localPrecType!=PT_AZTEC_FROM_APPROX_FWD_MATRIX 00787 ) 00788 { 00789 aztecAdjSolver = rcp(new AztecOO()); 00790 aztecAdjSolver->SetAztecOption(AZ_diagnostics,AZ_none); 00791 //aztecAdjSolver->SetAztecOption(AZ_keep_info,1); 00792 } 00793 } 00794 00795 // 00796 // Set the options on the AztecOO solvers 00797 // 00798 if( startingOver ) { 00799 if(paramList_.get()) 00800 setAztecOOParameters( 00801 ¶mList_->sublist(ForwardSolve_name).sublist(AztecOO_Settings_name), 00802 &*aztecFwdSolver 00803 ); 00804 if(aztecAdjSolver.get() && paramList_.get()) 00805 setAztecOOParameters( 00806 ¶mList_->sublist(AdjointSolve_name).sublist(AztecOO_Settings_name), 00807 &*aztecAdjSolver 00808 ); 00809 } 00810 00811 // 00812 // Process the forward operator 00813 // 00814 RCP<const Epetra_Operator> 00815 aztec_epetra_epetraFwdOp, 00816 aztec_epetra_epetraAdjOp; 00817 // Forward solve 00818 RCP<const Epetra_Operator> 00819 epetraOps[] 00820 = { epetra_epetraFwdOp }; 00821 Teuchos::ETransp 00822 epetraOpsTransp[] 00823 = { epetra_epetraFwdOpTransp==NOTRANS ? Teuchos::NO_TRANS : Teuchos::TRANS }; 00824 PO::EApplyMode 00825 epetraOpsApplyMode[] 00826 = { epetra_epetraFwdOpApplyAs==EPETRA_OP_APPLY_APPLY 00827 ? PO::APPLY_MODE_APPLY 00828 : PO::APPLY_MODE_APPLY_INVERSE }; 00829 if( 00830 epetraOpsTransp[0] == Teuchos::NO_TRANS 00831 && 00832 epetraOpsApplyMode[0] == PO::APPLY_MODE_APPLY 00833 ) 00834 { 00835 aztec_epetra_epetraFwdOp = epetra_epetraFwdOp; 00836 } 00837 else 00838 { 00839 aztec_epetra_epetraFwdOp = rcp( 00840 new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode)); 00841 } 00842 if( 00843 startingOver 00844 || 00845 aztec_epetra_epetraFwdOp.get() != aztecFwdSolver->GetUserOperator() 00846 ) 00847 { 00848 // Here we will be careful not to reset the forward operator in fears that 00849 // it will blow out the internally created stuff. 00850 aztecFwdSolver->SetUserOperator( 00851 const_cast<Epetra_Operator*>(&*aztec_epetra_epetraFwdOp)); 00852 set_extra_data( 00853 aztec_epetra_epetraFwdOp, AOOLOWSF_aztec_epetra_epetraFwdOp_str, 00854 Teuchos::inOutArg(aztecFwdSolver), Teuchos::POST_DESTROY, false 00855 ); 00856 } 00857 // Adjoint solve 00858 if( aztecAdjSolver.get() ) { 00859 epetraOpsTransp[0] = ( 00860 epetra_epetraFwdOpTransp==NOTRANS 00861 ? Teuchos::TRANS 00862 : Teuchos::NO_TRANS 00863 ); 00864 if( 00865 epetraOpsTransp[0] == Teuchos::NO_TRANS 00866 && 00867 epetraOpsApplyMode[0] == PO::APPLY_MODE_APPLY 00868 ) 00869 { 00870 aztec_epetra_epetraAdjOp = epetra_epetraFwdOp; 00871 } 00872 else { 00873 aztec_epetra_epetraAdjOp = rcp( 00874 new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode)); 00875 } 00876 aztecAdjSolver->SetUserOperator( 00877 const_cast<Epetra_Operator*>(&*aztec_epetra_epetraAdjOp)); 00878 set_extra_data( 00879 aztec_epetra_epetraAdjOp, AOOLOWSF_aztec_epetra_epetraAdjOp_str, 00880 Teuchos::inOutArg(aztecAdjSolver), Teuchos::POST_DESTROY, false 00881 ); 00882 } 00883 00884 // 00885 // Process the preconditioner 00886 // 00887 RCP<const Epetra_Operator> 00888 aztec_fwd_epetra_epetraPrecOp, 00889 aztec_adj_epetra_epetraPrecOp; 00890 bool setAztecPreconditioner = false; 00891 switch(localPrecType) { 00892 case PT_NONE: { 00893 // 00894 // No preconditioning at all! 00895 // 00896 break; 00897 } 00898 case PT_AZTEC_FROM_OP: { 00899 // 00900 // We are using the forward matrix for the preconditioner using aztec 00901 // preconditioners 00902 // 00903 if( startingOver || !reusePrec ) { 00904 TEUCHOS_TEST_FOR_EXCEPTION( 00905 rowmatrix_epetraFwdOp.get()==NULL, std::logic_error, 00906 "AztecOOLinearOpWithSolveFactory::initializeOp_impl(...): " 00907 "Error, There is no preconditioner given by client, but the client " 00908 "passed in an Epetra_Operator for the forward operator of type \'" 00909 <<typeName(*epetra_epetraFwdOp)<<"\' that does not " 00910 "support the Epetra_RowMatrix interface!" 00911 ); 00912 TEUCHOS_TEST_FOR_EXCEPTION( 00913 epetra_epetraFwdOpTransp!=NOTRANS, std::logic_error, 00914 "AztecOOLinearOpWithSolveFactory::initializeOp_impl(...):" 00915 " Error, There is no preconditioner given by client and the client " 00916 "passed in an Epetra_RowMatrix for the forward operator but the " 00917 "overall transpose is not NOTRANS and therefore we can can just " 00918 "hand this over to aztec without making a copy which is not supported here!" 00919 ); 00920 aztecFwdSolver->SetPrecMatrix( 00921 const_cast<Epetra_RowMatrix*>(&*rowmatrix_epetraFwdOp)); 00922 set_extra_data( 00923 rowmatrix_epetraFwdOp, AOOLOWSF_rowmatrix_epetraFwdOp_str, 00924 Teuchos::inOutArg(aztecFwdSolver), Teuchos::POST_DESTROY, false 00925 ); 00926 } 00927 setAztecPreconditioner = true; 00928 break; 00929 } 00930 case PT_AZTEC_FROM_APPROX_FWD_MATRIX: { 00931 // 00932 // The preconditioner comes from the input as a matrix and we are using 00933 // aztec preconditioners 00934 // 00935 if( startingOver || !reusePrec ) { 00936 TEUCHOS_TEST_FOR_EXCEPTION( 00937 rowmatrix_epetraPrecOp.get()==NULL, std::logic_error 00938 ,"AztecOOLinearOpWithSolveFactor::initializeOp_impl(...): The client " 00939 "passed in an Epetra_Operator for the preconditioner matrix of type \'" 00940 <<typeName(*epetra_epetraPrecOp)<<"\' that does not " 00941 "support the Epetra_RowMatrix interface!" 00942 ); 00943 TEUCHOS_TEST_FOR_EXCEPTION( 00944 overall_epetra_epetraPrecOpTransp!=NOTRANS, std::logic_error 00945 ,"AztecOOLinearOpWithSolveFactor::initializeOp_impl(...): Error, The client " 00946 "passed in an Epetra_RowMatrix for the preconditoner matrix but the overall " 00947 "transpose is not NOTRANS and therefore we can can just " 00948 "hand this over to aztec without making a copy which is not supported here!" 00949 ); 00950 aztecFwdSolver->SetPrecMatrix( 00951 const_cast<Epetra_RowMatrix*>(&*rowmatrix_epetraPrecOp)); 00952 set_extra_data( 00953 rowmatrix_epetraPrecOp, AOOLOWSF_rowmatrix_epetraPrecOp_str, 00954 Teuchos::inOutArg(aztecFwdSolver), Teuchos::POST_DESTROY, false 00955 ); 00956 } 00957 setAztecPreconditioner = true; 00958 break; 00959 } 00960 case PT_FROM_PREC_OP: { 00961 // 00962 // The preconditioner comes as an operator so let's use it as such 00963 // 00964 // Forward solve 00965 RCP<const Epetra_Operator> 00966 epetraOps[] 00967 = { epetra_epetraPrecOp }; 00968 Teuchos::ETransp 00969 epetraOpsTransp[] 00970 = { overall_epetra_epetraPrecOpTransp==NOTRANS 00971 ? Teuchos::NO_TRANS 00972 : Teuchos::TRANS }; 00973 // Here we must toggle the apply mode since aztecoo applies the 00974 // preconditioner using ApplyInverse(...) 00975 PO::EApplyMode 00976 epetraOpsApplyMode[] 00977 = { epetra_epetraPrecOpApplyAs==EPETRA_OP_APPLY_APPLY 00978 ? PO::APPLY_MODE_APPLY_INVERSE 00979 : PO::APPLY_MODE_APPLY }; 00980 if( 00981 epetraOpsTransp[0] == Teuchos::NO_TRANS 00982 && 00983 epetra_epetraPrecOpApplyAs==EPETRA_OP_APPLY_APPLY_INVERSE 00984 ) 00985 { 00986 aztec_fwd_epetra_epetraPrecOp = epetra_epetraPrecOp; 00987 } 00988 else { 00989 aztec_fwd_epetra_epetraPrecOp = rcp(new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode)); 00990 } 00991 aztecFwdSolver->SetPrecOperator( 00992 const_cast<Epetra_Operator*>(&*aztec_fwd_epetra_epetraPrecOp)); 00993 set_extra_data( 00994 aztec_fwd_epetra_epetraPrecOp, AOOLOWSF_aztec_fwd_epetra_epetraPrecOp_str, 00995 Teuchos::inOutArg(aztecFwdSolver), Teuchos::POST_DESTROY, false 00996 ); 00997 // Adjoint solve 00998 if( 00999 aztecAdjSolver.get() 01000 && 01001 epetra_epetraPrecOpAdjointSupport == EPETRA_OP_ADJOINT_SUPPORTED 01002 ) 01003 { 01004 epetraOpsTransp[0] = ( 01005 overall_epetra_epetraPrecOpTransp==NOTRANS 01006 ? Teuchos::TRANS 01007 : Teuchos::NO_TRANS 01008 ); 01009 if( 01010 epetraOpsTransp[0] == Teuchos::NO_TRANS 01011 && 01012 epetra_epetraPrecOpApplyAs==EPETRA_OP_APPLY_APPLY_INVERSE 01013 ) 01014 { 01015 aztec_adj_epetra_epetraPrecOp = epetra_epetraPrecOp; 01016 } 01017 else { 01018 aztec_adj_epetra_epetraPrecOp = rcp( 01019 new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode)); 01020 } 01021 aztecAdjSolver->SetPrecOperator( 01022 const_cast<Epetra_Operator*>(&*aztec_adj_epetra_epetraPrecOp)); 01023 set_extra_data( 01024 aztec_adj_epetra_epetraPrecOp, AOOLOWSF_aztec_adj_epetra_epetraPrecOp_str, 01025 Teuchos::inOutArg(aztecAdjSolver), Teuchos::POST_DESTROY, false 01026 ); 01027 set_extra_data<bool>( 01028 true, AOOLOWSF_setPrecondtionerOperator_str, 01029 Teuchos::inOutArg(aztecFwdSolver), Teuchos::POST_DESTROY, false 01030 ); 01031 } 01032 break; 01033 } 01034 default: 01035 TEUCHOS_TEST_FOR_EXCEPT(true); 01036 } 01037 01038 // 01039 // Initialize the interal aztec preconditioner 01040 // 01041 if(setAztecPreconditioner) { 01042 if( startingOver || !reusePrec ) { 01043 double condNumEst = -1.0; 01044 TEUCHOS_TEST_FOR_EXCEPT(0!=aztecFwdSolver->ConstructPreconditioner(condNumEst)); 01045 //aztecFwdSolver->SetAztecOption(AZ_pre_calc, AZ_calc); 01046 set_extra_data<bool>( 01047 true, AOOLOWSF_constructedAztecPreconditoner_str, 01048 Teuchos::inOutArg(aztecFwdSolver), Teuchos::POST_DESTROY, false 01049 ); 01050 } 01051 else { 01052 //aztecFwdSolver->SetAztecOption(AZ_pre_calc, AZ_reuse); 01053 } 01054 } 01055 01056 // 01057 // Initialize the AztecOOLinearOpWithSolve object and set its options 01058 // 01059 if(aztecAdjSolver.get() && aztecAdjSolver->GetPrecOperator()) { 01060 aztecOp->initialize( 01061 fwdOp, fwdOpSrc,precUsed, prec.get()!=NULL, approxFwdOpSrc, 01062 aztecFwdSolver, true, aztecAdjSolver, true, epetra_epetraFwdOpScalar 01063 ); 01064 } 01065 else { 01066 aztecOp->initialize( 01067 fwdOp, fwdOpSrc, precUsed, prec.get()!=NULL, approxFwdOpSrc, 01068 aztecFwdSolver, true, null, false, epetra_epetraFwdOpScalar 01069 ); 01070 } 01071 aztecOp->fwdDefaultMaxIterations(defaultFwdMaxIterations_); 01072 aztecOp->fwdDefaultTol(defaultFwdTolerance_); 01073 aztecOp->adjDefaultMaxIterations(defaultAdjMaxIterations_); 01074 aztecOp->adjDefaultTol(defaultAdjTolerance_); 01075 aztecOp->outputEveryRhs(outputEveryRhs_); 01076 aztecOp->setOStream(this->getOStream()); 01077 if(!is_null(this->getOverridingOStream())) 01078 aztecOp->setOverridingOStream(this->getOverridingOStream()); 01079 aztecOp->setVerbLevel(this->getVerbLevel()); 01080 01081 #ifdef TEUCHOS_DEBUG 01082 if(paramList_.get()) 01083 paramList_->validateParameters(*this->getValidParameters()); 01084 #endif 01085 01086 if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_LOW)) 01087 *out << "\nLeaving Thyra::AztecOOLinearOpWithSolveFactory::initializeOp_impl(...) ...\n"; 01088 01089 } 01090 01091 01092 } // namespace Thyra 01093 01094 01095 #endif // SUN_CXX
1.7.6.1