Stratimikos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Thyra_AztecOOLinearOpWithSolveFactory.cpp
Go to the documentation of this file.
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         &paramList_->sublist(ForwardSolve_name).sublist(AztecOO_Settings_name),
00802         &*aztecFwdSolver
00803         );
00804     if(aztecAdjSolver.get() && paramList_.get())
00805       setAztecOOParameters(
00806         &paramList_->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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines