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   TEST_FOR_EXCEPT(!precFactory.get());
00122   Teuchos::RCP<const Teuchos::ParameterList>
00123     precFactoryValidPL = precFactory->getValidParameters();
00124   const std::string _precFactoryName =
00125     ( precFactoryName != ""
00126       ? precFactoryName
00127       : ( precFactoryValidPL.get()
00128         ? precFactoryValidPL->name()
00129         : "GENERIC PRECONDITIONER FACTORY"
00130         )
00131       );
00132   precFactory_ = precFactory;
00133   precFactoryName_ = _precFactoryName;
00134   updateThisValidParamList();
00135 }
00136 
00137 
00138 Teuchos::RCP<PreconditionerFactoryBase<double> >
00139 AztecOOLinearOpWithSolveFactory::getPreconditionerFactory() const
00140 {
00141   return precFactory_;
00142 }
00143 
00144 
00145 void AztecOOLinearOpWithSolveFactory::unsetPreconditionerFactory(
00146   Teuchos::RCP<PreconditionerFactoryBase<double> > *precFactory,
00147   std::string *precFactoryName
00148   )
00149 {
00150   if(precFactory) *precFactory = precFactory_;
00151   if(precFactoryName) *precFactoryName = precFactoryName_;
00152   precFactory_ = Teuchos::null;
00153   precFactoryName_ = "";
00154   updateThisValidParamList();
00155 }
00156 
00157 
00158 bool AztecOOLinearOpWithSolveFactory::isCompatible(
00159   const LinearOpSourceBase<double> &fwdOpSrc
00160   ) const
00161 {
00162   return epetraFwdOpViewExtractor_->isCompatible(*fwdOpSrc.getOp());
00163 }
00164 
00165 
00166 Teuchos::RCP<LinearOpWithSolveBase<double> >
00167 AztecOOLinearOpWithSolveFactory::createOp() const
00168 {
00169   return Teuchos::rcp(new AztecOOLinearOpWithSolve());
00170 }
00171 
00172 
00173 void AztecOOLinearOpWithSolveFactory::initializeOp(
00174   const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc,
00175   LinearOpWithSolveBase<double> *Op,
00176   const ESupportSolveUse supportSolveUse
00177   ) const
00178 {
00179   this->initializeOp_impl(fwdOpSrc,Teuchos::null,Teuchos::null,false,Op);
00180 }
00181 
00182 
00183 void AztecOOLinearOpWithSolveFactory::initializeAndReuseOp(
00184   const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc,
00185   LinearOpWithSolveBase<double> *Op
00186   ) const
00187 {
00188   this->initializeOp_impl(fwdOpSrc,Teuchos::null,Teuchos::null,true,Op);
00189 }
00190 
00191 
00192 bool AztecOOLinearOpWithSolveFactory::supportsPreconditionerInputType(
00193   const EPreconditionerInputType precOpType
00194   ) const
00195 {
00196   const_cast<bool&>(useAztecPrec_) = (
00197     paramList_.get()
00198     &&
00199     paramList_->sublist(ForwardSolve_name).sublist(AztecOO_Settings_name).get(
00200       "Aztec Preconditioner","none"
00201       )!="none"
00202     );
00203   switch(precOpType) {
00204     case PRECONDITIONER_INPUT_TYPE_AS_OPERATOR:
00205       return true;
00206       break;
00207     case PRECONDITIONER_INPUT_TYPE_AS_MATRIX:
00208       return useAztecPrec_;
00209       break;
00210     default:
00211       TEST_FOR_EXCEPT(true);
00212   }
00213   return PRECONDITIONER_INPUT_TYPE_AS_OPERATOR; // 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   TEST_FOR_EXCEPT(prec.get()==NULL);
00225   this->initializeOp_impl(fwdOpSrc,prec,Teuchos::null,false,Op);
00226 }
00227 
00228 
00229 void AztecOOLinearOpWithSolveFactory::initializeApproxPreconditionedOp(
00230   const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc,
00231   const Teuchos::RCP<const LinearOpSourceBase<double> > &approxFwdOpSrc,
00232   LinearOpWithSolveBase<double> *Op,
00233   const ESupportSolveUse supportSolveUse
00234   ) const
00235 {
00236   TEST_FOR_EXCEPT(approxFwdOpSrc.get()==NULL);
00237   TEST_FOR_EXCEPT(approxFwdOpSrc->getOp().get()==NULL);
00238   this->initializeOp_impl(fwdOpSrc,Teuchos::null,approxFwdOpSrc,false,Op);
00239 }
00240 
00241 
00242 void AztecOOLinearOpWithSolveFactory::uninitializeOp(
00243   LinearOpWithSolveBase<double> *Op,
00244   Teuchos::RCP<const LinearOpSourceBase<double> > *fwdOpSrc,
00245   Teuchos::RCP<const PreconditionerBase<double> > *prec,
00246   Teuchos::RCP<const LinearOpSourceBase<double> > *approxFwdOpSrc,
00247   ESupportSolveUse *supportSolveUse
00248   ) const
00249 {
00250 #ifdef TEUCHOS_DEBUG
00251   TEST_FOR_EXCEPT(Op==NULL);
00252 #endif
00253   AztecOOLinearOpWithSolve
00254     *aztecOp = &Teuchos::dyn_cast<AztecOOLinearOpWithSolve>(*Op);
00255   // 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   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   typedef EpetraExt::ProductOperator PO;
00445 
00446   const Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
00447   const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00448   Teuchos::OSTab tab(out);
00449   if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00450     *out << "\nEntering Thyra::AztecOOLinearOpWithSolveFactory::initializeOp_impl(...) ...\n";
00451 
00452   typedef Teuchos::VerboseObjectTempState<PreconditionerFactoryBase<double> > VOTSPF;
00453   VOTSPF precFactoryOutputTempState(precFactory_,out,verbLevel);
00454 
00455 #ifdef TEUCHOS_DEBUG
00456   TEST_FOR_EXCEPT(Op==NULL);
00457   TEST_FOR_EXCEPT(fwdOpSrc.get()==NULL);
00458   TEST_FOR_EXCEPT(fwdOpSrc->getOp().get()==NULL);
00459 #endif
00460 
00461   // 
00462   // Determine whether the operators are EpetraLinearOp objects. If so, we're
00463   // good to go.  If not, we need to wrap it as an Epetra_Operator with some
00464   // invasive code.
00465   //
00466   Teuchos::RCP<const LinearOpBase<double> >
00467     tmpFwdOp = fwdOpSrc->getOp(),
00468     tmpApproxFwdOp = ( approxFwdOpSrc.get() ? approxFwdOpSrc->getOp() : Teuchos::null );
00469   Teuchos::RCP<const LinearOpBase<double> > fwdOp;
00470   Teuchos::RCP<const LinearOpBase<double> > approxFwdOp;
00471   if ( dynamic_cast<const EpetraLinearOpBase*>(tmpFwdOp.get())!=0 )
00472   {
00473     fwdOp = tmpFwdOp;
00474     approxFwdOp = tmpApproxFwdOp;
00475   }
00476   else
00477   {
00478     fwdOp = makeEpetraWrapper(ConstLinearOperator<double>(tmpFwdOp));
00479     if (
00480       tmpApproxFwdOp.get()
00481       &&
00482       dynamic_cast<const EpetraLinearOpBase*>(&*tmpApproxFwdOp.get())
00483       )
00484     {
00485       approxFwdOp = makeEpetraWrapper(ConstLinearOperator<double>(tmpApproxFwdOp));
00486     }
00487   }
00488   
00489   //
00490   // Get the AztecOOLinearOpWithSolve object
00491   //
00492   AztecOOLinearOpWithSolve
00493     *aztecOp = &Teuchos::dyn_cast<AztecOOLinearOpWithSolve>(*Op);
00494 
00495   //
00496   // Unwrap and get the forward operator or matrix
00497   //
00498   Teuchos::RCP<const Epetra_Operator> epetra_epetraFwdOp;
00499   EOpTransp epetra_epetraFwdOpTransp;
00500   EApplyEpetraOpAs epetra_epetraFwdOpApplyAs;
00501   EAdjointEpetraOp epetra_epetraFwdOpAdjointSupport;
00502   double epetra_epetraFwdOpScalar;
00503   epetraFwdOpViewExtractor_->getEpetraOpView(
00504     fwdOp,
00505     &epetra_epetraFwdOp, &epetra_epetraFwdOpTransp,
00506     &epetra_epetraFwdOpApplyAs, &epetra_epetraFwdOpAdjointSupport,
00507     &epetra_epetraFwdOpScalar
00508     );
00509   TEST_FOR_EXCEPTION(
00510     epetra_epetraFwdOp.get()==NULL, std::logic_error
00511     ,"Error, The input fwdOp object must be fully initialized "
00512     "before calling this function!"
00513     );
00514 
00515   //
00516   // Get the preconditioner object to use
00517   //
00518   Teuchos::RCP<PreconditionerBase<double> >        myPrec;
00519   Teuchos::RCP<const PreconditionerBase<double> >  precUsed;
00520   if (prec.get()) {
00521     // We will be used the passed in external preconditioner
00522     precUsed = prec;
00523   }
00524   else if (precFactory_.get() ) {
00525     // We will be creating our own preconditioner using an externally set
00526     // preconditioner factory
00527     myPrec =
00528       ( !aztecOp->isExternalPrec()
00529         ? Teuchos::rcp_const_cast<PreconditionerBase<double> >(
00530           aztecOp->extract_prec())
00531         : Teuchos::null
00532         );
00533     if(myPrec.get()) {
00534       // ToDo: Get the forward operator and validate that it is the same
00535       // operator that is used here!
00536     }
00537     else {
00538       myPrec = precFactory_->createPrec();
00539     }
00540     precFactory_->initializePrec(fwdOpSrc,&*myPrec);
00541     precUsed = myPrec;
00542   }
00543 
00544   //
00545   // Unwrap and get the preconditioner operator
00546   //
00547   RCP<const LinearOpBase<double> > rightPrecOp;
00548   if (precUsed.get()) {
00549     RCP<const LinearOpBase<double> > unspecified = precUsed->getUnspecifiedPrecOp();
00550     RCP<const LinearOpBase<double> > left = precUsed->getLeftPrecOp();
00551     RCP<const LinearOpBase<double> > right = precUsed->getRightPrecOp();
00552     TEST_FOR_EXCEPTION(
00553       !( left.get() || right.get() || unspecified.get() ), std::logic_error
00554       ,"Error, at least one preconditoner linear operator objects must be set!"
00555       );
00556     if(unspecified.get()) {
00557       rightPrecOp = unspecified;
00558     }
00559     else {
00560       // Set a left, right or split preconditioner
00561       TEST_FOR_EXCEPTION(
00562         left.get(),std::logic_error
00563         ,"Error, we can not currently handle a left"
00564         " preconditioner with the AztecOO/Thyra adapters!"
00565         );
00566       rightPrecOp = right;
00567     }
00568   }
00569   double wrappedPrecOpScalar = 0.0;
00570   EOpTransp wrappedPrecOpTransp = NOTRANS;
00571   RCP<const LinearOpBase<double> > wrappedPrecOp = null;
00572   RCP<const EpetraLinearOpBase> epetraPrecOp;
00573   Teuchos::RCP<const Epetra_Operator> epetra_epetraPrecOp;
00574   EOpTransp epetra_epetraPrecOpTransp;
00575   EApplyEpetraOpAs epetra_epetraPrecOpApplyAs;
00576   EAdjointEpetraOp epetra_epetraPrecOpAdjointSupport;
00577   EOpTransp overall_epetra_epetraPrecOpTransp;
00578   if(rightPrecOp.get()) {
00579     RCP<const LinearOpBase<double> > tmpWrappedPrecOp;
00580     unwrap(
00581       rightPrecOp,&wrappedPrecOpScalar,&wrappedPrecOpTransp,&tmpWrappedPrecOp);
00582     if( dynamic_cast<const EpetraLinearOpBase*>(&*tmpWrappedPrecOp) ) {
00583       wrappedPrecOp = tmpWrappedPrecOp;
00584     }
00585     else {
00586       wrappedPrecOp = makeEpetraWrapper(
00587         ConstLinearOperator<double>(tmpWrappedPrecOp));
00588     }
00589     epetraPrecOp = rcp_dynamic_cast<const EpetraLinearOpBase>(
00590       wrappedPrecOp,true);
00591     epetraPrecOp->getEpetraOpView(
00592       &epetra_epetraPrecOp,&epetra_epetraPrecOpTransp,
00593       &epetra_epetraPrecOpApplyAs,&epetra_epetraPrecOpAdjointSupport);
00594     TEST_FOR_EXCEPTION(
00595       epetra_epetraPrecOp.get()==NULL,std::logic_error
00596       ,"Error, The input prec object and its embedded precondtioner"
00597       " operator must be fully initialized before calling this function!"
00598       );
00599     // 2007/08/10: rabartl: This next set_extra_data(...) call is likely to be
00600     // setting up a circular reference!  Since epetra_epetraPrecOp was
00601     // gotten from epetraPrecOp, if you set epetraPrecOp as extra data
00602     // on the RCP epetra_epetraPrecOp then you have a circular reference!
00603     //set_extra_data(
00604     //  epetraPrecOp, AOOLOWSF_epetraPrecOp_str, &epetra_epetraPrecOp,
00605     //  Teuchos::POST_DESTROY, false );
00606     overall_epetra_epetraPrecOpTransp
00607       = trans_trans(
00608         real_trans(wrappedPrecOpTransp),
00609         real_trans(epetra_epetraPrecOpTransp)
00610         );
00611   }
00612   
00613   //
00614   // Unwrap and get the approximate forward operator to be used to generate a
00615   // preconditioner
00616   //
00617   if(approxFwdOp.get()) {
00618     // Note, here we just use the same members data that would be set for an
00619     // extenral preconditioner operator since it is not getting used.
00620     unwrap(approxFwdOp,&wrappedPrecOpScalar,&wrappedPrecOpTransp,&wrappedPrecOp);
00621     epetraPrecOp = rcp_dynamic_cast<const EpetraLinearOpBase>(
00622       wrappedPrecOp,true);
00623     epetraPrecOp->getEpetraOpView(
00624       &epetra_epetraPrecOp, &epetra_epetraPrecOpTransp,
00625       &epetra_epetraPrecOpApplyAs, &epetra_epetraPrecOpAdjointSupport
00626       );
00627     TEST_FOR_EXCEPTION(
00628       epetra_epetraPrecOp.get()==NULL,std::logic_error
00629       ,"Error, The input approxFwdOp object must be fully initialized"
00630       " before calling this function!"
00631       );
00632     // 2007/08/10: rabartl: This next set_extra_data(...) call is likely to be
00633     // setting up a circular reference!  Since epetra_epetraPrecOp was
00634     // gotten from epetraPrecOp, if you set epetraPrecOp as extra data
00635     // on the RCP epetra_epetraPrecOp then you have a circular reference!
00636     //set_extra_data(
00637     //  epetraPrecOp, AOOLOWSF_epetraPrecOp_str, &epetra_epetraPrecOp,
00638     //  Teuchos::POST_DESTROY, false
00639     //  );
00640     overall_epetra_epetraPrecOpTransp
00641       = trans_trans(
00642         real_trans(wrappedPrecOpTransp),
00643         real_trans(epetra_epetraPrecOpTransp)
00644         );
00645   }
00646 
00647   //
00648   // Determine if the forward and preconditioner operators are a row matrices
00649   // or not
00650   //
00651   RCP<const Epetra_RowMatrix>
00652     rowmatrix_epetraFwdOp  = rcp_dynamic_cast<const Epetra_RowMatrix>(
00653       epetra_epetraFwdOp),
00654     rowmatrix_epetraPrecOp = rcp_dynamic_cast<const Epetra_RowMatrix>(
00655       epetra_epetraPrecOp);
00656   //
00657   // Determine the type of preconditoner
00658   //
00659   // Update useAztecPrec_, input value does not matter
00660   this->supportsPreconditionerInputType(PRECONDITIONER_INPUT_TYPE_AS_MATRIX);
00661   enum ELocalPrecType {
00662     PT_NONE, PT_AZTEC_FROM_OP, PT_AZTEC_FROM_APPROX_FWD_MATRIX,
00663     PT_FROM_PREC_OP
00664   };
00665   ELocalPrecType localPrecType;
00666   if( precUsed.get()==NULL && approxFwdOp.get()==NULL && !useAztecPrec_ ) {
00667     // No preconditioning at all!
00668     localPrecType = PT_NONE;
00669   }
00670   else if( precUsed.get()==NULL && approxFwdOp.get()==NULL && useAztecPrec_ ) {
00671     // We are using the forward matrix for the preconditioner using aztec
00672     // preconditioners
00673     localPrecType = PT_AZTEC_FROM_OP;
00674   }
00675   else if( approxFwdOp.get() && useAztecPrec_ ) {
00676     // The preconditioner comes from the input as a matrix and we are using
00677     // aztec preconditioners
00678     localPrecType = PT_AZTEC_FROM_APPROX_FWD_MATRIX;
00679   }
00680   else if( precUsed.get() ) {
00681     // The preconditioner comes as an external operator so let's use it as
00682     // such
00683     localPrecType = PT_FROM_PREC_OP;
00684   }
00685   
00686   //
00687   // Determine if aztecOp already contains solvers and if we need to
00688   // reinitialize or not
00689   //
00690   RCP<AztecOO> aztecFwdSolver, aztecAdjSolver;
00691   bool startingOver;
00692   {
00693     // Let's assume that fwdOp, prec and/or approxFwdOp are compatible with
00694     // the already created AztecOO objects.  If they are not, then the client
00695     // should have created a new LOWSB object from scratch!
00696     Teuchos::RCP<const LinearOpBase<double> > old_fwdOp;
00697     Teuchos::RCP<const LinearOpSourceBase<double> > old_fwdOpSrc;
00698     Teuchos::RCP<const PreconditionerBase<double> > old_prec;
00699     bool old_isExternalPrec;
00700     Teuchos::RCP<const LinearOpSourceBase<double> > old_approxFwdOpSrc;
00701     Teuchos::RCP<AztecOO> old_aztecFwdSolver;
00702     Teuchos::RCP<AztecOO> old_aztecAdjSolver;
00703     double old_aztecSolverScalar;
00704     aztecOp->uninitialize(
00705       &old_fwdOp
00706       ,&old_fwdOpSrc
00707       ,&old_prec
00708       ,&old_isExternalPrec
00709       ,&old_approxFwdOpSrc
00710       ,&old_aztecFwdSolver
00711       ,NULL
00712       ,&old_aztecAdjSolver
00713       ,NULL
00714       ,&old_aztecSolverScalar
00715       );
00716     if( old_aztecFwdSolver.get()==NULL ) {
00717       // This has never been initialized before
00718       startingOver = true;
00719     }
00720     else {
00721       // Let's assume that fwdOp, prec and/or approxFwdOp are compatible with
00722       // the already created AztecOO objects.  If they are not, then the
00723       // client should have created a new LOWSB object from scratch!
00724       aztecFwdSolver = old_aztecFwdSolver;
00725       aztecAdjSolver = old_aztecAdjSolver;
00726       startingOver = false;
00727       // We must wipe out the old preconditoner if we are not reusing the
00728       // preconditioner
00729       Ptr<bool> constructedAztecPreconditioner;
00730       if(
00731         !reusePrec
00732         && !is_null( constructedAztecPreconditioner = get_optional_nonconst_extra_data<bool>(
00733                aztecFwdSolver,"AOOLOWSF::constructedAztecPreconditoner") )
00734         && *constructedAztecPreconditioner
00735         )
00736       {
00737         aztecFwdSolver->DestroyPreconditioner();
00738         *constructedAztecPreconditioner = false;
00739       }
00740       // We must see if we set an external preconditioner but will not do so
00741       // again in which case we must blow away AztecOO and start over again!
00742       Ptr<bool> setPreconditionerOperator;
00743       if(
00744         localPrecType != PT_FROM_PREC_OP
00745         && !is_null( setPreconditionerOperator = get_optional_nonconst_extra_data<bool>(
00746                aztecFwdSolver,"AOOLOWSF::setPreconditonerOperator") )
00747         && *setPreconditionerOperator
00748         )
00749       {
00750         // We must start over again since there is no way to unset an external
00751         // preconditioner!
00752         startingOver = true;
00753       }
00754     }
00755   }
00756 
00757   //
00758   // Create the AztecOO solvers if we are starting over
00759   //
00760   startingOver = true; // ToDo: Remove this and figure out why this is not working!
00761   if(startingOver) {
00762     // Forward solver
00763     aztecFwdSolver = rcp(new AztecOO());
00764     aztecFwdSolver->SetAztecOption(AZ_diagnostics,AZ_none); // This was turned off in NOX?
00765     aztecFwdSolver->SetAztecOption(AZ_keep_info,1);
00766     // Adjoint solver (if supported)
00767     if(
00768       epetra_epetraFwdOpAdjointSupport==EPETRA_OP_ADJOINT_SUPPORTED
00769       &&
00770       localPrecType!=PT_AZTEC_FROM_OP && localPrecType!=PT_AZTEC_FROM_APPROX_FWD_MATRIX
00771       )
00772     {
00773       aztecAdjSolver = rcp(new AztecOO());
00774       aztecAdjSolver->SetAztecOption(AZ_diagnostics,AZ_none);
00775       //aztecAdjSolver->SetAztecOption(AZ_keep_info,1);
00776     }
00777   }
00778 
00779   //
00780   // Set the options on the AztecOO solvers
00781   //
00782   if( startingOver ) {
00783     if(paramList_.get())
00784       setAztecOOParameters(
00785         &paramList_->sublist(ForwardSolve_name).sublist(AztecOO_Settings_name),
00786         &*aztecFwdSolver
00787         );
00788     if(aztecAdjSolver.get() && paramList_.get())
00789       setAztecOOParameters(
00790         &paramList_->sublist(AdjointSolve_name).sublist(AztecOO_Settings_name),
00791         &*aztecAdjSolver
00792         );
00793   }
00794   
00795   //
00796   // Process the forward operator
00797   //
00798   RCP<const Epetra_Operator>
00799     aztec_epetra_epetraFwdOp,
00800     aztec_epetra_epetraAdjOp;
00801   // Forward solve
00802   RCP<const Epetra_Operator>
00803     epetraOps[]
00804     = { epetra_epetraFwdOp };
00805   Teuchos::ETransp
00806     epetraOpsTransp[]
00807     = { epetra_epetraFwdOpTransp==NOTRANS ? Teuchos::NO_TRANS : Teuchos::TRANS };
00808   PO::EApplyMode
00809     epetraOpsApplyMode[]
00810     = { epetra_epetraFwdOpApplyAs==EPETRA_OP_APPLY_APPLY
00811         ? PO::APPLY_MODE_APPLY
00812         : PO::APPLY_MODE_APPLY_INVERSE };
00813   if(
00814     epetraOpsTransp[0] == Teuchos::NO_TRANS
00815     &&
00816     epetraOpsApplyMode[0] == PO::APPLY_MODE_APPLY
00817     )
00818   {
00819     aztec_epetra_epetraFwdOp = epetra_epetraFwdOp;
00820   }
00821   else
00822   {
00823     aztec_epetra_epetraFwdOp = rcp(
00824       new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode));
00825   }
00826   if(
00827     startingOver
00828     ||
00829     aztec_epetra_epetraFwdOp.get() != aztecFwdSolver->GetUserOperator() 
00830     )
00831   {
00832     // Here we will be careful not to reset the forward operator in fears that
00833     // it will blow out the internally created stuff.
00834     aztecFwdSolver->SetUserOperator(
00835       const_cast<Epetra_Operator*>(&*aztec_epetra_epetraFwdOp));
00836     set_extra_data(
00837       aztec_epetra_epetraFwdOp, AOOLOWSF_aztec_epetra_epetraFwdOp_str,
00838       &aztecFwdSolver, Teuchos::POST_DESTROY, false
00839       );
00840   }
00841   // Adjoint solve
00842   if( aztecAdjSolver.get() ) {
00843     epetraOpsTransp[0] = (
00844       epetra_epetraFwdOpTransp==NOTRANS
00845       ? Teuchos::TRANS
00846       : Teuchos::NO_TRANS
00847       );
00848     if(
00849       epetraOpsTransp[0] == Teuchos::NO_TRANS
00850       &&
00851       epetraOpsApplyMode[0] == PO::APPLY_MODE_APPLY
00852       )
00853     {
00854       aztec_epetra_epetraAdjOp = epetra_epetraFwdOp;
00855     }
00856     else {
00857       aztec_epetra_epetraAdjOp = rcp(
00858         new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode));
00859     }
00860     aztecAdjSolver->SetUserOperator(
00861       const_cast<Epetra_Operator*>(&*aztec_epetra_epetraAdjOp));
00862     set_extra_data(
00863       aztec_epetra_epetraAdjOp, AOOLOWSF_aztec_epetra_epetraAdjOp_str,
00864       &aztecAdjSolver, Teuchos::POST_DESTROY, false
00865       );
00866   }
00867   
00868   //
00869   // Process the preconditioner
00870   //
00871   RCP<const Epetra_Operator>
00872     aztec_fwd_epetra_epetraPrecOp,
00873     aztec_adj_epetra_epetraPrecOp;
00874   bool setAztecPreconditioner = false;
00875   switch(localPrecType) {
00876     case PT_NONE: {
00877       //
00878       // No preconditioning at all!
00879       //
00880       break;
00881     }
00882     case PT_AZTEC_FROM_OP: {
00883       //
00884       // We are using the forward matrix for the preconditioner using aztec
00885       // preconditioners
00886       //
00887       if( startingOver || !reusePrec ) {
00888         TEST_FOR_EXCEPTION(
00889           rowmatrix_epetraFwdOp.get()==NULL, std::logic_error,
00890           "AztecOOLinearOpWithSolveFactory::initializeOp_impl(...): "
00891           "Error, There is no preconditioner given by client, but the client "
00892           "passed in an Epetra_Operator for the forward operator of type \'"
00893           <<typeName(*epetra_epetraFwdOp)<<"\' that does not "
00894           "support the Epetra_RowMatrix interface!"
00895           );
00896         TEST_FOR_EXCEPTION(
00897           epetra_epetraFwdOpTransp!=NOTRANS, std::logic_error,
00898           "AztecOOLinearOpWithSolveFactory::initializeOp_impl(...):"
00899           " Error, There is no preconditioner given by client and the client "
00900           "passed in an Epetra_RowMatrix for the forward operator but the "
00901           "overall transpose is not NOTRANS and therefore we can can just "
00902           "hand this over to aztec without making a copy which is not supported here!"
00903           );
00904         aztecFwdSolver->SetPrecMatrix(
00905           const_cast<Epetra_RowMatrix*>(&*rowmatrix_epetraFwdOp));
00906         set_extra_data(
00907           rowmatrix_epetraFwdOp, AOOLOWSF_rowmatrix_epetraFwdOp_str,
00908           &aztecFwdSolver, Teuchos::POST_DESTROY, false
00909           );
00910       }
00911       setAztecPreconditioner = true;
00912       break;
00913     }
00914     case PT_AZTEC_FROM_APPROX_FWD_MATRIX: {
00915       //
00916       // The preconditioner comes from the input as a matrix and we are using
00917       // aztec preconditioners
00918       //
00919       if( startingOver || !reusePrec ) {
00920         TEST_FOR_EXCEPTION(
00921           rowmatrix_epetraPrecOp.get()==NULL, std::logic_error
00922           ,"AztecOOLinearOpWithSolveFactor::initializeOp_impl(...): The client "
00923           "passed in an Epetra_Operator for the preconditioner matrix of type \'"
00924           <<typeName(*epetra_epetraPrecOp)<<"\' that does not "
00925           "support the Epetra_RowMatrix interface!"
00926           );
00927         TEST_FOR_EXCEPTION(
00928           overall_epetra_epetraPrecOpTransp!=NOTRANS, std::logic_error
00929           ,"AztecOOLinearOpWithSolveFactor::initializeOp_impl(...): Error, The client "
00930           "passed in an Epetra_RowMatrix for the preconditoner matrix but the overall "
00931           "transpose is not NOTRANS and therefore we can can just "
00932           "hand this over to aztec without making a copy which is not supported here!"
00933           );
00934         aztecFwdSolver->SetPrecMatrix(
00935           const_cast<Epetra_RowMatrix*>(&*rowmatrix_epetraPrecOp));
00936         set_extra_data(
00937           rowmatrix_epetraPrecOp, AOOLOWSF_rowmatrix_epetraPrecOp_str,
00938           &aztecFwdSolver, Teuchos::POST_DESTROY, false
00939           );
00940       }
00941       setAztecPreconditioner = true;
00942       break;
00943     }
00944     case PT_FROM_PREC_OP: {
00945       //
00946       // The preconditioner comes as an operator so let's use it as such
00947       //
00948       // Forawrd solve
00949       RCP<const Epetra_Operator>
00950         epetraOps[]
00951         = { epetra_epetraPrecOp };
00952       Teuchos::ETransp
00953         epetraOpsTransp[]
00954         = { overall_epetra_epetraPrecOpTransp==NOTRANS
00955             ? Teuchos::NO_TRANS
00956             : Teuchos::TRANS };
00957       // Here we must toggle the apply mode since aztecoo applies the
00958       // preconditioner using ApplyInverse(...)
00959       PO::EApplyMode
00960         epetraOpsApplyMode[]
00961         = { epetra_epetraPrecOpApplyAs==EPETRA_OP_APPLY_APPLY
00962             ? PO::APPLY_MODE_APPLY_INVERSE
00963             : PO::APPLY_MODE_APPLY };
00964       if(
00965         epetraOpsTransp[0] == Teuchos::NO_TRANS
00966         &&
00967         epetra_epetraPrecOpApplyAs==EPETRA_OP_APPLY_APPLY_INVERSE
00968         )
00969       {
00970         aztec_fwd_epetra_epetraPrecOp = epetra_epetraPrecOp;
00971       }
00972       else {
00973         aztec_fwd_epetra_epetraPrecOp = rcp(new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode));
00974       }
00975       aztecFwdSolver->SetPrecOperator(
00976         const_cast<Epetra_Operator*>(&*aztec_fwd_epetra_epetraPrecOp));
00977       set_extra_data(
00978         aztec_fwd_epetra_epetraPrecOp, AOOLOWSF_aztec_fwd_epetra_epetraPrecOp_str,
00979         &aztecFwdSolver, Teuchos::POST_DESTROY, false
00980         );
00981       // Adjoint solve
00982       if(
00983         aztecAdjSolver.get()
00984         &&
00985         epetra_epetraPrecOpAdjointSupport == EPETRA_OP_ADJOINT_SUPPORTED
00986         )
00987       {
00988         epetraOpsTransp[0] = ( 
00989           overall_epetra_epetraPrecOpTransp==NOTRANS
00990           ? Teuchos::TRANS
00991           : Teuchos::NO_TRANS
00992           );
00993         if(
00994           epetraOpsTransp[0] == Teuchos::NO_TRANS
00995           &&
00996           epetra_epetraPrecOpApplyAs==EPETRA_OP_APPLY_APPLY_INVERSE
00997           )
00998         {
00999           aztec_adj_epetra_epetraPrecOp = epetra_epetraPrecOp;
01000         }
01001         else {
01002           aztec_adj_epetra_epetraPrecOp = rcp(
01003             new PO(1,epetraOps,epetraOpsTransp,epetraOpsApplyMode));
01004         }
01005         aztecAdjSolver->SetPrecOperator(
01006           const_cast<Epetra_Operator*>(&*aztec_adj_epetra_epetraPrecOp));
01007         set_extra_data(
01008           aztec_adj_epetra_epetraPrecOp, AOOLOWSF_aztec_adj_epetra_epetraPrecOp_str,
01009           &aztecAdjSolver, Teuchos::POST_DESTROY, false
01010           );
01011         set_extra_data<bool>(
01012           true, AOOLOWSF_setPrecondtionerOperator_str,
01013           &aztecFwdSolver, Teuchos::POST_DESTROY, false
01014           );
01015       }
01016       break;
01017     }
01018     default:
01019       TEST_FOR_EXCEPT(true);
01020   }
01021   
01022   //
01023   // Initialize the interal aztec preconditioner
01024   //
01025   if(setAztecPreconditioner) {
01026     if( startingOver || !reusePrec ) {
01027       double condNumEst = -1.0;
01028       TEST_FOR_EXCEPT(0!=aztecFwdSolver->ConstructPreconditioner(condNumEst));
01029       //aztecFwdSolver->SetAztecOption(AZ_pre_calc, AZ_calc);
01030       set_extra_data<bool>(
01031         true, AOOLOWSF_constructedAztecPreconditoner_str,
01032         &aztecFwdSolver, Teuchos::POST_DESTROY, false
01033         );
01034     }
01035     else {
01036       //aztecFwdSolver->SetAztecOption(AZ_pre_calc, AZ_reuse);
01037     }
01038   }
01039 
01040   //
01041   // Initialize the AztecOOLinearOpWithSolve object and set its options
01042   //
01043   if(aztecAdjSolver.get() && aztecAdjSolver->GetPrecOperator()) {
01044     aztecOp->initialize(
01045       fwdOp, fwdOpSrc,precUsed, prec.get()!=NULL, approxFwdOpSrc,
01046       aztecFwdSolver, true, aztecAdjSolver, true, epetra_epetraFwdOpScalar
01047       );
01048   }
01049   else {
01050     aztecOp->initialize(
01051       fwdOp, fwdOpSrc, precUsed, prec.get()!=NULL, approxFwdOpSrc,
01052       aztecFwdSolver, true, null, false, epetra_epetraFwdOpScalar
01053       );
01054   }
01055   aztecOp->fwdDefaultMaxIterations(defaultFwdMaxIterations_);
01056   aztecOp->fwdDefaultTol(defaultFwdTolerance_);
01057   aztecOp->adjDefaultMaxIterations(defaultAdjMaxIterations_);
01058   aztecOp->adjDefaultTol(defaultAdjTolerance_);
01059   aztecOp->outputEveryRhs(outputEveryRhs_);
01060   aztecOp->setOStream(this->getOStream());
01061   if(!is_null(this->getOverridingOStream()))
01062     aztecOp->setOverridingOStream(this->getOverridingOStream());
01063   aztecOp->setVerbLevel(this->getVerbLevel());
01064 
01065 #ifdef TEUCHOS_DEBUG
01066   if(paramList_.get())
01067     paramList_->validateParameters(*this->getValidParameters());
01068 #endif
01069 
01070   if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
01071     *out << "\nLeaving Thyra::AztecOOLinearOpWithSolveFactory::initializeOp_impl(...) ...\n";
01072 
01073 }
01074 
01075 
01076 } // namespace Thyra
01077 
01078 
01079 #endif // SUN_CXX

Generated on Wed Jul 22 12:56:30 2009 for Stratimikos by  doxygen 1.5.8