Thyra_LinearOpWithSolveFactoryExamples.hpp

00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //    Thyra: Interfaces and Support for Abstract Numerical Algorithms
00005 //                 Copyright (2004) 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 #ifndef THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP
00030 #define THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP
00031 
00032 
00033 #include "Thyra_LinearOpWithSolveFactoryBase.hpp"
00034 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
00035 #include "Thyra_PreconditionerFactoryHelpers.hpp"
00036 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
00037 #include "Thyra_DefaultPreconditioner.hpp"
00038 
00039 
00040 namespace Thyra {
00041 
00042 
00043 //
00044 // Helper code
00045 //
00046 
00057 template<class Scalar>
00058 class LinearOpChanger {
00059 public:
00061   virtual ~LinearOpChanger() {}
00063   virtual void changeOp( LinearOpBase<Scalar> *op ) const = 0;
00064 };
00065 
00069 template<class Scalar>
00070 class NullLinearOpChanger : public LinearOpChanger<Scalar> {
00071 public:
00073   void changeOp( LinearOpBase<Scalar> *op ) const {}
00074 };
00075 
00076 
00077 } // namespace Thyra
00078 
00079 
00080 //
00081 // Individual non-externally preconditioned use cases
00082 //
00083 
00084 
00085 // begin singleLinearSolve
00089 template<class Scalar>
00090 void singleLinearSolve(
00091   const Thyra::LinearOpBase<Scalar> &A,
00092   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00093   const Thyra::VectorBase<Scalar> &b,
00094   Thyra::VectorBase<Scalar> *x,
00095   Teuchos::FancyOStream &out
00096   )
00097 {
00098   Teuchos::OSTab tab(out);
00099   out << "\nPerforming a single linear solve ...\n";
00100   // Create the LOWSB object that will be used to solve the linear system
00101   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00102     invertibleA = Thyra::linearOpWithSolve(lowsFactory,Teuchos::rcp(&A,false));
00103   // Solve the system using a default solve criteria using a non-member helper function 
00104   assign(&*x,Teuchos::ScalarTraits<Scalar>::zero()); // Must initialize to a guess before solve!
00105   Thyra::SolveStatus<Scalar>
00106     status = Thyra::solve(*invertibleA,Thyra::NOTRANS,b,x);
00107   out << "\nSolve status:\n" << status;
00108 } // end singleLinearSolve
00109 
00110 
00111 // begin createScaledAdjointLinearOpWithSolve
00116 template<class Scalar>
00117 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00118 createScaledAdjointLinearOpWithSolve(
00119   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
00120   const Scalar &scalar,
00121   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00122   Teuchos::FancyOStream &out
00123   )
00124 {
00125   Teuchos::OSTab tab(out);
00126   out << "\nCreating a scaled adjoint LinearOpWithSolveBase object ...\n";
00127   // Create the LOWSB object that will be used to solve the linear system
00128   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00129     invertibleAdjointA
00130     = Thyra::linearOpWithSolve(lowsFactory,scale(scalar,adjoint(A)));
00131   out << "\nCreated LOWSB object:\n" << describe(*invertibleAdjointA,Teuchos::VERB_MEDIUM);
00132   return invertibleAdjointA;
00133 } // end createScaledAdjointLinearOpWithSolve
00134 
00135 
00136 // begin solveNumericalChangeSolve
00141 template<class Scalar>
00142 void solveNumericalChangeSolve(
00143   Thyra::LinearOpBase<Scalar> *A,
00144   const Thyra::LinearOpChanger<Scalar> &opChanger,
00145   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00146   const Thyra::VectorBase<Scalar> &b1,
00147   Thyra::VectorBase<Scalar> *x1,
00148   const Thyra::VectorBase<Scalar> &b2,
00149   Thyra::VectorBase<Scalar> *x2,
00150   Teuchos::FancyOStream &out
00151   )
00152 {
00153   Teuchos::OSTab tab(out);
00154   out << "\nPerforming a solve, changing the operator, then performing another solve ...\n";
00155   // Get a local non-owned RCP to A to be used by lowsFactory
00156   Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00157     rcpA = Teuchos::rcp(A,false); // Note: This is the right way to do this!
00158   // Create the LOWSB object that will be used to solve the linear system
00159   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00160     invertibleA = lowsFactory.createOp();
00161   // Initialize the invertible linear operator given the forward operator
00162   Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00163   // Solve the system using a default solve criteria using a non-member helper function
00164   Thyra::assign(x1,Scalar(0.0));
00165   solve(*invertibleA,Thyra::NOTRANS,b1,x1);
00166   // Before the forward operator A is changed it is recommended that you
00167   // uninitialize *invertibleA first to avoid accidental use of *invertiableA
00168   // while it may be in an inconsistent state from the time between *A changes
00169   // and *invertibleA is explicitly updated. However, this step is not
00170   // required!
00171   Thyra::uninitializeOp<Scalar>(lowsFactory,&*invertibleA);
00172   // Change the operator and reinitialize the invertible operator
00173   opChanger.changeOp(A);
00174   Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00175   // Note that above will reuse any factorization structures that may have been
00176   // created in the first call to initializeOp(...).
00177   // Finally, solve another linear system with new values of A
00178   Thyra::assign(x2,Scalar(0.0));
00179   solve(*invertibleA,Thyra::NOTRANS,b2,x2);
00180 } // end solveNumericalChangeSolve
00181 
00182 
00183 // begin solveSmallNumericalChangeSolve
00189 template<class Scalar>
00190 void solveSmallNumericalChangeSolve(
00191   Thyra::LinearOpBase<Scalar> *A,
00192   const Thyra::LinearOpChanger<Scalar> &opSmallChanger,
00193   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00194   const Thyra::VectorBase<Scalar> &b1,
00195   Thyra::VectorBase<Scalar> *x1,
00196   const Thyra::VectorBase<Scalar> &b2,
00197   Thyra::VectorBase<Scalar> *x2,
00198   Teuchos::FancyOStream &out
00199   )
00200 {
00201   Teuchos::OSTab tab(out);
00202   out << "\nPerforming a solve, changing the operator in a very small way, then performing another solve ...\n";
00203   // Get a local non-owned RCP to A to be used by lowsFactory
00204   Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00205     rcpA = Teuchos::rcp(A,false); // Note: This is the right way to do this!
00206   // Create the LOWSB object that will be used to solve the linear system
00207   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00208     invertibleA = lowsFactory.createOp();
00209   // Initialize the invertible linear operator given the forward operator
00210   Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00211   // Solve the system using a default solve criteria using a non-member helper function
00212   Thyra::assign(x1,Scalar(0.0));
00213   solve(*invertibleA,Thyra::NOTRANS,b1,x1);
00214   // Before the forward operator A is changed it is recommended that you
00215   // uninitialize *invertibleA first to avoid accidental use of *invertiableA
00216   // while it may be in an inconsistent state from the time between *A changes
00217   // and *invertibleA is explicitly updated. However, this step is not
00218   // required!
00219   Thyra::uninitializeOp<Scalar>(lowsFactory,&*invertibleA);
00220   // Change the operator and reinitialize the invertible operator
00221   opSmallChanger.changeOp(A);
00222   Thyra::initializeAndReuseOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00223   // Note that above a maximum amount of reuse will be achieved, such as
00224   // keeping the same precondtioner.
00225   Thyra::assign(x2,Scalar(0.0));
00226   solve(*invertibleA,Thyra::NOTRANS,b2,x2);
00227 } // end solveSmallNumericalChangeSolve
00228 
00229 
00230 // begin solveMajorChangeSolve
00236 template<class Scalar>
00237 void solveMajorChangeSolve(
00238   Thyra::LinearOpBase<Scalar> *A,
00239   const Thyra::LinearOpChanger<Scalar> &opMajorChanger,
00240   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00241   const Thyra::VectorBase<Scalar> &b1,
00242   Thyra::VectorBase<Scalar> *x1,
00243   const Thyra::VectorBase<Scalar> &b2,
00244   Thyra::VectorBase<Scalar> *x2,
00245   Teuchos::FancyOStream &out
00246   )
00247 {
00248   Teuchos::OSTab tab(out);
00249   out << "\nPerforming a solve, changing the operator in a major way, then performing another solve ...\n";
00250   // Get a local non-owned RCP to A to be used by lowsFactory
00251   Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00252     rcpA = Teuchos::rcp(A,false); // Note: This is the right way to do this!
00253   // Create the LOWSB object that will be used to solve the linear system
00254   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00255     invertibleA = lowsFactory.createOp();
00256   // Initialize the invertible linear operator given the forward operator
00257   Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00258   // Solve the system using a default solve criteria using a non-member helper function
00259   Thyra::assign(x1,Scalar(0.0));
00260   solve(*invertibleA,Thyra::NOTRANS,b1,x1);
00261   // Before the forward operator A is changed it is recommended that you
00262   // uninitialize *invertibleA first to avoid accidental use of *invertiableA
00263   // while it may be in an inconsistent state from the time between *A changes
00264   // and *invertibleA is explicitly updated. However, this step is not
00265   // required!
00266   Thyra::uninitializeOp<Scalar>(lowsFactory,&*invertibleA);
00267   // Change the operator in some major way (perhaps even changing its structure)
00268   opMajorChanger.changeOp(A);
00269   // Recreate the LOWSB object and initialize it from scratch
00270   invertibleA = lowsFactory.createOp();
00271   Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00272   // Solve another set of linear systems
00273   Thyra::assign(x2,Scalar(0.0));
00274   solve(*invertibleA,Thyra::NOTRANS,b2,x2);
00275 } // end solveMajorChangeSolve
00276 
00277 
00278 //
00279 // Individual externally preconditioned use cases
00280 //
00281 
00282 
00283 // begin createGeneralPreconditionedLinearOpWithSolve
00289 template<class Scalar>
00290 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00291 createGeneralPreconditionedLinearOpWithSolve(
00292   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
00293   const Teuchos::RCP<const Thyra::PreconditionerBase<Scalar> > &P,
00294   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00295   Teuchos::FancyOStream &out
00296   )
00297 {
00298   Teuchos::OSTab tab(out);
00299   out << "\nCreating an externally preconditioned LinearOpWithSolveBase object ...\n";
00300   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00301     invertibleA = lowsFactory.createOp();
00302   Thyra::initializePreconditionedOp<Scalar>(lowsFactory,A,P,&*invertibleA);
00303   out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00304   return invertibleA;
00305 } // end createGeneralPreconditionedLinearOpWithSolve
00306 
00307 
00308 // begin createUnspecifiedPreconditionedLinearOpWithSolve
00314 template<class Scalar>
00315 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00316 createUnspecifiedPreconditionedLinearOpWithSolve(
00317   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
00318   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op,
00319   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00320   Teuchos::FancyOStream &out
00321   )
00322 {
00323   Teuchos::OSTab tab(out);
00324   out << "\nCreating an LinearOpWithSolveBase object given a preconditioner operator not targeted to the left or right ...\n";
00325   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00326     invertibleA = lowsFactory.createOp();
00327   Thyra::initializePreconditionedOp<Scalar>(
00328     lowsFactory,A,Thyra::unspecifiedPrec<Scalar>(P_op)
00329     ,&*invertibleA
00330     );
00331   // Above, the lowsFactory object will decide whether to apply the single
00332   // preconditioner operator on the left or on the right.
00333   out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00334   return invertibleA;
00335 } // end createUnspecifiedPreconditionedLinearOpWithSolve
00336 
00337 
00338 // begin createLeftPreconditionedLinearOpWithSolve
00344 template<class Scalar>
00345 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00346 createLeftPreconditionedLinearOpWithSolve(
00347   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
00348   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_left,
00349   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00350   Teuchos::FancyOStream &out
00351   )
00352 {
00353   Teuchos::OSTab tab(out);
00354   out << "\nCreating an LinearOpWithSolveBase object given a left preconditioner"
00355       << " operator ...\n";
00356   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00357     invertibleA = lowsFactory.createOp();
00358   Thyra::initializePreconditionedOp<Scalar>(
00359     lowsFactory,A,Thyra::leftPrec<Scalar>(P_op_left)
00360     ,&*invertibleA
00361     );
00362   out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00363   return invertibleA;
00364 } // end createLeftPreconditionedLinearOpWithSolve
00365 
00366 
00367 // begin createRightPreconditionedLinearOpWithSolve
00373 template<class Scalar>
00374 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00375 createRightPreconditionedLinearOpWithSolve(
00376   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
00377   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_right,
00378   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00379   Teuchos::FancyOStream &out
00380   )
00381 {
00382   Teuchos::OSTab tab(out);
00383   out << "\nCreating an LinearOpWithSolveBase object given a right preconditioner operator ...\n";
00384   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00385     invertibleA = lowsFactory.createOp();
00386   Thyra::initializePreconditionedOp<Scalar>(
00387     lowsFactory,A,Thyra::rightPrec<Scalar>(P_op_right)
00388     ,&*invertibleA
00389     );
00390   out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00391   return invertibleA;
00392 } // end createRightPreconditionedLinearOpWithSolve
00393 
00394 
00395 // begin createLeftRightPreconditionedLinearOpWithSolve
00401 template<class Scalar>
00402 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00403 createLeftRightPreconditionedLinearOpWithSolve(
00404   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
00405   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_left,
00406   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_right,
00407   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00408   Teuchos::FancyOStream &out
00409   )
00410 {
00411   Teuchos::OSTab tab(out);
00412   out << "\nCreating an LinearOpWithSolveBase object given a left and"
00413       << "right preconditioner operator ...\n";
00414   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00415     invertibleA = lowsFactory.createOp();
00416   Thyra::initializePreconditionedOp<Scalar>(
00417     lowsFactory,A,Thyra::splitPrec<Scalar>(P_op_left,P_op_right)
00418     ,&*invertibleA
00419     );
00420   out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00421   return invertibleA;
00422 } // end createLeftRightPreconditionedLinearOpWithSolve
00423 
00424 
00425 // begin createMatrixPreconditionedLinearOpWithSolve
00431 template<class Scalar>
00432 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00433 createMatrixPreconditionedLinearOpWithSolve(
00434   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
00435   const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A_approx,
00436   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00437   Teuchos::FancyOStream &out
00438   )
00439 {
00440   Teuchos::OSTab tab(out);
00441   out << "\nCreating a LinearOpWithSolveBase object given an approximate forward"
00442       << " operator to define the preconditioner ...\n";
00443   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00444     invertibleA = lowsFactory.createOp();
00445   Thyra::initializeApproxPreconditionedOp<Scalar>(lowsFactory,A,A_approx,&*invertibleA);
00446   out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00447   return invertibleA;
00448 } // end createMatrixPreconditionedLinearOpWithSolve
00449 
00450 
00451 // begin externalPreconditionerReuseWithSolves
00455 template<class Scalar>
00456 void externalPreconditionerReuseWithSolves(
00457   Thyra::LinearOpBase<Scalar> *A_inout,
00458   const Thyra::LinearOpChanger<Scalar> &opChanger,
00459   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00460   const Thyra::PreconditionerFactoryBase<Scalar> &precFactory,
00461   const Thyra::VectorBase<Scalar> &b1,
00462   Thyra::VectorBase<Scalar> *x1,
00463   const Thyra::VectorBase<Scalar> &b2,
00464   Thyra::VectorBase<Scalar> *x2,
00465   Teuchos::FancyOStream &out
00466   )
00467 {
00468   Teuchos::OSTab tab(out);
00469   out << "\nShowing resuse of the preconditioner ...\n";
00470   Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
00471     A = rcp(A_inout,false);
00472   // Create the initial preconditioner for the input forward operator
00473   Teuchos::RCP<Thyra::PreconditionerBase<Scalar> >
00474     P = precFactory.createPrec();
00475   Thyra::initializePrec<Scalar>(precFactory,A,&*P);
00476   // Create the invertible LOWS object given the preconditioner
00477   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00478     invertibleA = lowsFactory.createOp();
00479   Thyra::initializePreconditionedOp<Scalar>(lowsFactory,A,P,&*invertibleA);
00480   // Solve the first linear system
00481   assign(&*x1,Teuchos::ScalarTraits<Scalar>::zero());
00482   Thyra::SolveStatus<Scalar>
00483     status1 = Thyra::solve(*invertibleA,Thyra::NOTRANS,b1,x1);
00484   out << "\nSolve status:\n" << status1;
00485   // Change the forward linear operator without changing the preconditioner
00486   opChanger.changeOp(&*A);
00487   // Warning! After the above change the integrity of the preconditioner
00488   // linear operators in P is undefined. For some implementations of the
00489   // preconditioner, its behavior will remain unchanged (e.g. ILU) which in
00490   // other cases the behavior will change but the preconditioner will still
00491   // work (e.g. Jacobi). However, there may be valid implementations where
00492   // the preconditioner will simply break if the forward operator that it is
00493   // based on breaks.
00494   //
00495   // Reinitialize the LOWS object given the updated forward operator A and the
00496   // old preconditioner P.
00497   Thyra::initializePreconditionedOp<Scalar>(lowsFactory,A,P,&*invertibleA);
00498   // Solve the second linear system
00499   assign(&*x2,Teuchos::ScalarTraits<Scalar>::zero());
00500   Thyra::SolveStatus<Scalar>
00501     status2 = Thyra::solve(*invertibleA,Thyra::NOTRANS,b2,x2);
00502   out << "\nSolve status:\n" << status2;
00503 } // end externalPreconditionerReuseWithSolves
00504 
00505 
00506 //
00507 // Combined use cases
00508 //
00509 
00510 
00516 template<class Scalar>
00517 void nonExternallyPreconditionedLinearSolveUseCases(
00518   const Thyra::LinearOpBase<Scalar> &A,
00519   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00520   bool supportsAdjoints,
00521   Teuchos::FancyOStream &out
00522   )
00523 {
00524   Teuchos::OSTab tab(out);
00525   out << "\nRunning example use cases for a LinearOpWithSolveFactoryBase object ...\n";
00526   // Create the RHS (which is just a random set of coefficients)
00527   Teuchos::RCP<Thyra::VectorBase<Scalar> >
00528     b1 = Thyra::createMember(A.range()),
00529     b2 = Thyra::createMember(A.range());
00530   Thyra::randomize( Scalar(-1.0), Scalar(+1.0), &*b1 );
00531   Thyra::randomize( Scalar(-1.0), Scalar(+1.0), &*b2 );
00532   // Create the LHS for the linear solve
00533   Teuchos::RCP<Thyra::VectorBase<Scalar> >
00534     x1 = Thyra::createMember(A.domain()),
00535     x2 = Thyra::createMember(A.domain());
00536   // Perform a single, non-adjoint, linear solve
00537   singleLinearSolve(A,lowsFactory,*b1,&*x1,out);
00538   // Creating a scaled adjoint LinearOpWithSolveBase object
00539   if(supportsAdjoints) {
00540     Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00541       invertibleAdjointA = createScaledAdjointLinearOpWithSolve(
00542         Teuchos::rcp(&A,false),Scalar(2.0),lowsFactory,out);
00543   }
00544   // Perform a solve, change the operator, and then solve again.
00545   solveNumericalChangeSolve(
00546     const_cast<Thyra::LinearOpBase<Scalar>*>(&A) // Don't worry, it will not be changed!
00547     ,Thyra::NullLinearOpChanger<Scalar>() // This object will not really change A!
00548     ,lowsFactory,*b1,&*x1,*b2,&*x1,out
00549     );
00550   // Perform a solve, change the operator in a very small way, and then solve again.
00551   solveSmallNumericalChangeSolve(
00552     const_cast<Thyra::LinearOpBase<Scalar>*>(&A) // Don't worry, it will not be changed!
00553     ,Thyra::NullLinearOpChanger<Scalar>() // This object will not really change A!
00554     ,lowsFactory,*b1,&*x1,*b2,&*x1,out
00555     );
00556   // Perform a solve, change the operator in a major way, and then solve again.
00557   solveMajorChangeSolve(
00558     const_cast<Thyra::LinearOpBase<Scalar>*>(&A) // Don't worry, it will not be changed!
00559     ,Thyra::NullLinearOpChanger<Scalar>() // This object will not really change A!
00560     ,lowsFactory,*b1,&*x1,*b2,&*x1,out
00561     );
00562 }
00563 
00564 
00570 template<class Scalar>
00571 void externallyPreconditionedLinearSolveUseCases(
00572   const Thyra::LinearOpBase<Scalar> &A,
00573   const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory,
00574   const Thyra::PreconditionerFactoryBase<Scalar> &precFactory,
00575   const bool supportsLeftPrec,
00576   const bool supportsRightPrec,
00577   Teuchos::FancyOStream &out
00578   )
00579 {
00580   Teuchos::OSTab tab(out);
00581   out << "\nRunning example use cases with an externally defined"
00582       << " preconditioner with a LinearOpWithSolveFactoryBase object ...\n";
00583   // Create the RHS (which is just a random set of coefficients)
00584   Teuchos::RCP<Thyra::VectorBase<Scalar> >
00585     b1 = Thyra::createMember(A.range()),
00586     b2 = Thyra::createMember(A.range());
00587   Thyra::randomize( Scalar(-1.0), Scalar(+1.0), &*b1 );
00588   Thyra::randomize( Scalar(-1.0), Scalar(+1.0), &*b2 );
00589   // Create the LHS for the linear solve
00590   Teuchos::RCP<Thyra::VectorBase<Scalar> >
00591     x1 = Thyra::createMember(A.domain()),
00592     x2 = Thyra::createMember(A.domain());
00593   // Create a preconditioner for the input forward operator
00594   Teuchos::RCP<Thyra::PreconditionerBase<Scalar> >
00595     P = precFactory.createPrec();
00596   Thyra::initializePrec<Scalar>(precFactory,Teuchos::rcp(&A,false),&*P);
00597   // Above, we don't really know the nature of the preconditioner. It could a
00598   // single linear operator to be applied on the left or the right or it could
00599   // be a split preconditioner with different linear operators to be applied
00600   // on the right or left. Or, it could be a single linear operator that is
00601   // not targeted to the left or the right.
00602   //
00603   // Create a LOWSB object given the created preconditioner
00604   Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00605     invertibleA = createGeneralPreconditionedLinearOpWithSolve<Scalar>(
00606       Teuchos::rcp(&A,false),P,lowsFactory,out);
00607   // Grab a preconditioner operator out of the preconditioner object
00608   Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > P_op;
00609   if((P_op=P->getUnspecifiedPrecOp()).get());
00610   else if((P_op=P->getLeftPrecOp()).get());
00611   else if((P_op=P->getRightPrecOp()).get());
00612   // Create a LOWSB object given an unspecified preconditioner operator
00613   invertibleA = createUnspecifiedPreconditionedLinearOpWithSolve(
00614     Teuchos::rcp(&A,false),P_op,lowsFactory,out);
00615   // Create a LOWSB object given a left preconditioner operator
00616   if(supportsLeftPrec) {
00617     invertibleA = createLeftPreconditionedLinearOpWithSolve(
00618       Teuchos::rcp(&A,false),P_op,lowsFactory,out);
00619   }
00620   // Create a LOWSB object given a right preconditioner operator
00621   if(supportsRightPrec) {
00622     invertibleA = createRightPreconditionedLinearOpWithSolve(
00623       Teuchos::rcp(&A,false),P_op,lowsFactory,out);
00624   }
00625   // Create a LOWSB object given (bad set of) left and right preconditioner
00626   // operators
00627   if( supportsLeftPrec && supportsRightPrec ) {
00628     invertibleA = createLeftRightPreconditionedLinearOpWithSolve(
00629       Teuchos::rcp(&A,false),P_op,P_op,lowsFactory,out);
00630   }
00631   // Create a LOWSB object given a (very good) approximate forward linear
00632   // operator to construct the preconditoner from..
00633   invertibleA = createMatrixPreconditionedLinearOpWithSolve<Scalar>(
00634     Teuchos::rcp(&A,false),Teuchos::rcp(&A,false),lowsFactory,out);
00635   // Preconditioner reuse example
00636   externalPreconditionerReuseWithSolves(
00637     const_cast<Thyra::LinearOpBase<Scalar>*>(&A) // Don't worry, it will not be changed!
00638     ,Thyra::NullLinearOpChanger<Scalar>() // This object will not really change A!
00639     ,lowsFactory,precFactory
00640     ,*b1,&*x1,*b2,&*x2,out
00641     );
00642 }
00643 
00644 
00645 #endif // THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP

Generated on Wed May 12 21:42:47 2010 for Thyra Operator Solve Support by  doxygen 1.4.7