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