Thyra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Thyra_LinearOpWithSolveFactoryExamples.hpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Thyra: Interfaces and Support for Abstract Numerical Algorithms
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP
43 #define THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP
44 
45 
46 #include "Thyra_LinearOpWithSolveFactoryBase.hpp"
47 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
48 #include "Thyra_LinearOpWithSolveBase.hpp"
49 #include "Thyra_PreconditionerFactoryHelpers.hpp"
50 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
51 #include "Thyra_DefaultPreconditioner.hpp"
52 #include "Thyra_MultiVectorStdOps.hpp"
53 #include "Thyra_VectorStdOps.hpp"
54 #include "Thyra_VectorBase.hpp"
55 
56 
57 namespace Thyra {
58 
59 
60 //
61 // Helper code
62 //
63 
74 template<class Scalar>
76 public:
78  virtual ~LinearOpChanger() {}
80  virtual void changeOp( const Teuchos::Ptr<LinearOpBase<Scalar> > &op ) const = 0;
81 };
82 
86 template<class Scalar>
87 class NullLinearOpChanger : public LinearOpChanger<Scalar> {
88 public:
90  void changeOp( const Teuchos::Ptr<LinearOpBase<Scalar> > &op ) const {}
91 };
92 
93 
94 } // namespace Thyra
95 
96 
97 //
98 // Individual non-externally preconditioned use cases
99 //
100 
101 
102 // begin singleLinearSolve
106 template<class Scalar>
107 void singleLinearSolve(
110  const Thyra::VectorBase<Scalar> &b,
113  )
114 {
116  using Teuchos::rcpFromRef;
117  Teuchos::OSTab tab(out);
118  out << "\nPerforming a single linear solve ...\n";
119  // Create the LOWSB object that will be used to solve the linear system
121  Thyra::linearOpWithSolve(lowsFactory, rcpFromRef(A));
122  // Solve the system using a default solve criteria using a non-member helper function
123  assign(x, ST::zero()); // Must initialize to a guess before solve!
125  status = Thyra::solve<Scalar>(*invertibleA, Thyra::NOTRANS, b, x);
126  out << "\nSolve status:\n" << status;
127 } // end singleLinearSolve
128 
129 
130 // begin createScaledAdjointLinearOpWithSolve
135 template<class Scalar>
137 createScaledAdjointLinearOpWithSolve(
138  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
139  const Scalar &scalar,
142  )
143 {
144  Teuchos::OSTab tab(out);
145  out << "\nCreating a scaled adjoint LinearOpWithSolveBase object ...\n";
146  // Create the LOWSB object that will be used to solve the linear system
148  Thyra::linearOpWithSolve(lowsFactory,scale(scalar,adjoint(A)));
149  out << "\nCreated LOWSB object:\n" << describe(*invertibleAdjointA,
151  return invertibleAdjointA;
152 } // end createScaledAdjointLinearOpWithSolve
153 
154 
155 // begin solveNumericalChangeSolve
160 template<class Scalar>
161 void solveNumericalChangeSolve(
163  const Thyra::LinearOpChanger<Scalar> &opChanger,
165  const Thyra::VectorBase<Scalar> &b1,
167  const Thyra::VectorBase<Scalar> &b2,
170  )
171 {
172  using Teuchos::as; using Teuchos::ptr; using Teuchos::rcpFromPtr;
173  Teuchos::OSTab tab(out);
174  out << "\nPerforming a solve, changing the operator, then performing another"
175  << " solve ...\n";
176  // Get a local non-owned RCP to A to be used by lowsFactory
177  Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > rcpA = rcpFromPtr(A);
178  // Create the LOWSB object that will be used to solve the linear system
180  lowsFactory.createOp();
181  // Initialize the invertible linear operator given the forward operator
182  Thyra::initializeOp<Scalar>(lowsFactory, rcpA, invertibleA.ptr());
183  // Solve the system using a default solve criteria using a non-member helper function
184  Thyra::assign(x1, as<Scalar>(0.0));
185  Thyra::solve<Scalar>(*invertibleA, Thyra::NOTRANS, b1, x1);
186  // Before the forward operator A is changed it is recommended that you
187  // uninitialize *invertibleA first to avoid accidental use of *invertiableA
188  // while it may be in an inconsistent state from the time between *A changes
189  // and *invertibleA is explicitly updated. However, this step is not
190  // required!
191  Thyra::uninitializeOp<Scalar>(lowsFactory, invertibleA.ptr());
192  // Change the operator and reinitialize the invertible operator
193  opChanger.changeOp(A);
194  Thyra::initializeOp<Scalar>(lowsFactory, rcpA, invertibleA.ptr());
195  // Note that above will reuse any factorization structures that may have been
196  // created in the first call to initializeOp(...).
197  // Finally, solve another linear system with new values of A
198  Thyra::assign<Scalar>(x2, as<Scalar>(0.0));
199  Thyra::solve<Scalar>(*invertibleA, Thyra::NOTRANS, b2, x2);
200 } // end solveNumericalChangeSolve
201 
202 
203 // begin solveSmallNumericalChangeSolve
209 template<class Scalar>
210 void solveSmallNumericalChangeSolve(
212  const Thyra::LinearOpChanger<Scalar> &opSmallChanger,
214  const Thyra::VectorBase<Scalar> &b1,
216  const Thyra::VectorBase<Scalar> &b2,
219  )
220 {
221  using Teuchos::ptr; using Teuchos::as; using Teuchos::rcpFromPtr;
222  Teuchos::OSTab tab(out);
223  out << "\nPerforming a solve, changing the operator in a very small way,"
224  << " then performing another solve ...\n";
225  // Get a local non-owned RCP to A to be used by lowsFactory
226  Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > rcpA = rcpFromPtr(A);
227  // Create the LOWSB object that will be used to solve the linear system
229  lowsFactory.createOp();
230  // Initialize the invertible linear operator given the forward operator
231  Thyra::initializeOp<Scalar>(lowsFactory, rcpA, invertibleA.ptr());
232  // Solve the system using a default solve criteria using a non-member helper function
233  Thyra::assign(x1, as<Scalar>(0.0));
234  Thyra::solve<Scalar>(*invertibleA, Thyra::NOTRANS, b1, x1);
235  // Before the forward operator A is changed it is recommended that you
236  // uninitialize *invertibleA first to avoid accidental use of *invertiableA
237  // while it may be in an inconsistent state from the time between *A changes
238  // and *invertibleA is explicitly updated. However, this step is not
239  // required!
240  Thyra::uninitializeOp<Scalar>(lowsFactory, invertibleA.ptr());
241  // Change the operator and reinitialize the invertible operator
242  opSmallChanger.changeOp(A);
243  Thyra::initializeAndReuseOp<Scalar>(lowsFactory, rcpA, invertibleA.ptr());
244  // Note that above a maximum amount of reuse will be achieved, such as
245  // keeping the same preconditioner.
246  Thyra::assign(x2, as<Scalar>(0.0));
247  Thyra::solve<Scalar>(*invertibleA, Thyra::NOTRANS, b2, x2);
248 } // end solveSmallNumericalChangeSolve
249 
250 
251 // begin solveMajorChangeSolve
257 template<class Scalar>
258 void solveMajorChangeSolve(
260  const Thyra::LinearOpChanger<Scalar> &opMajorChanger,
262  const Thyra::VectorBase<Scalar> &b1,
264  const Thyra::VectorBase<Scalar> &b2,
267  )
268 {
269  using Teuchos::as; using Teuchos::rcpFromPtr;
270  Teuchos::OSTab tab(out);
271  out << "\nPerforming a solve, changing the operator in a major way, then performing"
272  << " another solve ...\n";
273  // Get a local non-owned RCP to A to be used by lowsFactory
274  Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > rcpA = rcpFromPtr(A);
275  // Create the LOWSB object that will be used to solve the linear system
277  lowsFactory.createOp();
278  // Initialize the invertible linear operator given the forward operator
279  Thyra::initializeOp<Scalar>(lowsFactory, rcpA, invertibleA.ptr());
280  // Solve the system using a default solve criteria using a non-member helper function
281  Thyra::assign(x1, as<Scalar>(0.0));
282  Thyra::solve<Scalar>(*invertibleA, Thyra::NOTRANS, b1, x1);
283  // Before the forward operator A is changed it is recommended that you
284  // uninitialize *invertibleA first to avoid accidental use of *invertiableA
285  // while it may be in an inconsistent state from the time between *A changes
286  // and *invertibleA is explicitly updated. However, this step is not
287  // required!
288  Thyra::uninitializeOp<Scalar>(lowsFactory, invertibleA.ptr());
289  // Change the operator in some major way (perhaps even changing its structure)
290  opMajorChanger.changeOp(A);
291  // Recreate the LOWSB object and initialize it from scratch
292  invertibleA = lowsFactory.createOp();
293  Thyra::initializeOp<Scalar>(lowsFactory, rcpA, invertibleA.ptr());
294  // Solve another set of linear systems
295  Thyra::assign(x2, as<Scalar>(0.0));
296  Thyra::solve<Scalar>(*invertibleA, Thyra::NOTRANS, b2, x2);
297 } // end solveMajorChangeSolve
298 
299 
300 //
301 // Individual externally preconditioned use cases
302 //
303 
304 
305 // begin createGeneralPreconditionedLinearOpWithSolve
311 template<class Scalar>
313 createGeneralPreconditionedLinearOpWithSolve(
314  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
318  )
319 {
320  Teuchos::OSTab tab(out);
321  out << "\nCreating an externally preconditioned LinearOpWithSolveBase object ...\n";
323  lowsFactory.createOp();
324  Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A, P, invertibleA.ptr());
325  out << "\nCreated LOWSB object:\n" << describe(*invertibleA, Teuchos::VERB_MEDIUM);
326  return invertibleA;
327 } // end createGeneralPreconditionedLinearOpWithSolve
328 
329 
330 // begin createUnspecifiedPreconditionedLinearOpWithSolve
336 template<class Scalar>
338 createUnspecifiedPreconditionedLinearOpWithSolve(
339  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
340  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op,
343  )
344 {
345  Teuchos::OSTab tab(out);
346  out << "\nCreating an LinearOpWithSolveBase object given a preconditioner operator"
347  << " not targeted to the left or right ...\n";
349  lowsFactory.createOp();
350  Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A,
351  Thyra::unspecifiedPrec<Scalar>(P_op), invertibleA.ptr());
352  // Above, the lowsFactory object will decide whether to apply the single
353  // preconditioner operator on the left or on the right.
354  out << "\nCreated LOWSB object:\n" << describe(*invertibleA, Teuchos::VERB_MEDIUM);
355  return invertibleA;
356 } // end createUnspecifiedPreconditionedLinearOpWithSolve
357 
358 
359 // begin createLeftPreconditionedLinearOpWithSolve
365 template<class Scalar>
367 createLeftPreconditionedLinearOpWithSolve(
368  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
369  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_left,
372  )
373 {
374  Teuchos::OSTab tab(out);
375  out << "\nCreating an LinearOpWithSolveBase object given a left preconditioner"
376  << " operator ...\n";
378  lowsFactory.createOp();
379  Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A,
380  Thyra::leftPrec<Scalar>(P_op_left), invertibleA.ptr());
381  out << "\nCreated LOWSB object:\n" << describe(*invertibleA, Teuchos::VERB_MEDIUM);
382  return invertibleA;
383 } // end createLeftPreconditionedLinearOpWithSolve
384 
385 
386 // begin createRightPreconditionedLinearOpWithSolve
392 template<class Scalar>
394 createRightPreconditionedLinearOpWithSolve(
395  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
396  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_right,
399  )
400 {
401  Teuchos::OSTab tab(out);
402  out << "\nCreating an LinearOpWithSolveBase object given a right"
403  << " preconditioner operator ...\n";
405  lowsFactory.createOp();
406  Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A,
407  Thyra::rightPrec<Scalar>(P_op_right), invertibleA.ptr());
408  out << "\nCreated LOWSB object:\n" << describe(*invertibleA, Teuchos::VERB_MEDIUM);
409  return invertibleA;
410 } // end createRightPreconditionedLinearOpWithSolve
411 
412 
413 // begin createLeftRightPreconditionedLinearOpWithSolve
419 template<class Scalar>
421 createLeftRightPreconditionedLinearOpWithSolve(
422  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
423  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_left,
424  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_right,
427  )
428 {
429  Teuchos::OSTab tab(out);
430  out << "\nCreating an LinearOpWithSolveBase object given a left and"
431  << "right preconditioner operator ...\n";
433  lowsFactory.createOp();
434  Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A,
435  Thyra::splitPrec<Scalar>(P_op_left, P_op_right), invertibleA.ptr());
436  out << "\nCreated LOWSB object:\n" << describe(*invertibleA, Teuchos::VERB_MEDIUM);
437  return invertibleA;
438 } // end createLeftRightPreconditionedLinearOpWithSolve
439 
440 
441 // begin createMatrixPreconditionedLinearOpWithSolve
447 template<class Scalar>
449 createMatrixPreconditionedLinearOpWithSolve(
450  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A,
451  const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A_approx,
454  )
455 {
456  Teuchos::OSTab tab(out);
457  out << "\nCreating a LinearOpWithSolveBase object given an approximate forward"
458  << " operator to define the preconditioner ...\n";
460  lowsFactory.createOp();
461  Thyra::initializeApproxPreconditionedOp<Scalar>(lowsFactory, A, A_approx,
462  invertibleA.ptr());
463  out << "\nCreated LOWSB object:\n" << describe(*invertibleA, Teuchos::VERB_MEDIUM);
464  return invertibleA;
465 } // end createMatrixPreconditionedLinearOpWithSolve
466 
467 
468 // begin externalPreconditionerReuseWithSolves
472 template<class Scalar>
473 void externalPreconditionerReuseWithSolves(
474  const Teuchos::Ptr<Thyra::LinearOpBase<Scalar> > &A_inout,
475  const Thyra::LinearOpChanger<Scalar> &opChanger,
477  const Thyra::PreconditionerFactoryBase<Scalar> &precFactory,
478  const Thyra::VectorBase<Scalar> &b1,
480  const Thyra::VectorBase<Scalar> &b2,
483  )
484 {
485  using Teuchos::tab; using Teuchos::rcpFromPtr;
487  Teuchos::OSTab tab2(out);
488  out << "\nShowing resuse of the preconditioner ...\n";
489  Teuchos::RCP<Thyra::LinearOpBase<Scalar> > A = rcpFromPtr(A_inout);
490  // Create the initial preconditioner for the input forward operator
492  precFactory.createPrec();
493  Thyra::initializePrec<Scalar>(precFactory, A, P.ptr());
494  // Create the invertible LOWS object given the preconditioner
496  lowsFactory.createOp();
497  Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A, P, invertibleA.ptr());
498  // Solve the first linear system
499  assign(x1, ST::zero());
500  Thyra::SolveStatus<Scalar> status1 = Thyra::solve<Scalar>(*invertibleA,
501  Thyra::NOTRANS, b1, x1);
502  out << "\nSolve status:\n" << status1;
503  // Change the forward linear operator without changing the preconditioner
504  opChanger.changeOp(A.ptr());
505  // Warning! After the above change the integrity of the preconditioner
506  // linear operators in P is undefined. For some implementations of the
507  // preconditioner, its behavior will remain unchanged (e.g. ILU) which in
508  // other cases the behavior will change but the preconditioner will still
509  // work (e.g. Jacobi). However, there may be valid implementations where
510  // the preconditioner will simply break if the forward operator that it is
511  // based on breaks.
512  //
513  // Reinitialize the LOWS object given the updated forward operator A and the
514  // old preconditioner P.
515  Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A, P, invertibleA.ptr());
516  // Solve the second linear system
517  assign(x2, ST::zero());
518  Thyra::SolveStatus<Scalar>status2 = Thyra::solve<Scalar>(*invertibleA,
519  Thyra::NOTRANS, b2, x2);
520  out << "\nSolve status:\n" << status2;
521 } // end externalPreconditionerReuseWithSolves
522 
523 
524 //
525 // Combined use cases
526 //
527 
528 
534 template<class Scalar>
535 void nonExternallyPreconditionedLinearSolveUseCases(
538  bool supportsAdjoints,
540  )
541 {
542  using Teuchos::as;
543  Teuchos::OSTab tab(out);
544  out << "\nRunning example use cases for a LinearOpWithSolveFactoryBase object ...\n";
545  // Create a non-const A object (don't worry, it will not be changed)
546  const Teuchos::Ptr<Thyra::LinearOpBase<Scalar> > A_nonconst =
547  Teuchos::ptrFromRef(const_cast<Thyra::LinearOpBase<Scalar>&>(A));
548  // Create the RHS (which is just a random set of coefficients)
550  b1 = Thyra::createMember(A.range()),
551  b2 = Thyra::createMember(A.range());
552  Thyra::randomize( as<Scalar>(-1.0), as<Scalar>(+1.0), b1.ptr() );
553  Thyra::randomize( as<Scalar>(-1.0), as<Scalar>(+1.0), b2.ptr() );
554  // Create the LHS for the linear solve
556  x1 = Thyra::createMember(A.domain()),
557  x2 = Thyra::createMember(A.domain());
558  // Perform a single, non-adjoint, linear solve
559  singleLinearSolve(A, lowsFactory, *b1, x1.ptr(), out);
560  // Creating a scaled adjoint LinearOpWithSolveBase object
561  if(supportsAdjoints) {
563  invertibleAdjointA = createScaledAdjointLinearOpWithSolve(
564  Teuchos::rcp(&A,false),as<Scalar>(2.0),lowsFactory,out);
565  }
566  // Perform a solve, change the operator, and then solve again.
567  solveNumericalChangeSolve<Scalar>(
568  A_nonconst, // Don't worry, it will not be changed!
569  Thyra::NullLinearOpChanger<Scalar>(), // This object will not really change A!
570  lowsFactory, *b1, x1.ptr(), *b2, x1.ptr(), out );
571  // Perform a solve, change the operator in a very small way, and then solve again.
572  solveSmallNumericalChangeSolve<Scalar>(
573  A_nonconst, // Don't worry, it will not be changed!
574  Thyra::NullLinearOpChanger<Scalar>(), // This object will not really change A!
575  lowsFactory, *b1, x1.ptr(), *b2, x1.ptr(), out );
576  // Perform a solve, change the operator in a major way, and then solve again.
577  solveMajorChangeSolve<Scalar>(
578  A_nonconst, // Don't worry, it will not be changed!
579  Thyra::NullLinearOpChanger<Scalar>(), // This object will not really change A!
580  lowsFactory, *b1, x1.ptr(), *b2, x1.ptr(), out );
581 }
582 
583 
589 template<class Scalar>
590 void externallyPreconditionedLinearSolveUseCases(
593  const Thyra::PreconditionerFactoryBase<Scalar> &precFactory,
594  const bool supportsLeftPrec,
595  const bool supportsRightPrec,
597  )
598 {
599  using Teuchos::rcpFromRef; using Teuchos::as;
600  Teuchos::OSTab tab(out);
601  out << "\nRunning example use cases with an externally defined"
602  << " preconditioner with a LinearOpWithSolveFactoryBase object ...\n";
603  // Create a non-const A object (don't worry, it will not be changed)
604  const Teuchos::Ptr<Thyra::LinearOpBase<Scalar> > A_nonconst =
605  Teuchos::ptrFromRef(const_cast<Thyra::LinearOpBase<Scalar>&>(A));
606  // Create the RHS (which is just a random set of coefficients)
608  b1 = Thyra::createMember(A.range()),
609  b2 = Thyra::createMember(A.range());
610  Thyra::randomize( as<Scalar>(-1.0), as<Scalar>(+1.0), b1.ptr() );
611  Thyra::randomize( as<Scalar>(-1.0), as<Scalar>(+1.0), b2.ptr() );
612  // Create the LHS for the linear solve
614  x1 = Thyra::createMember(A.domain()),
615  x2 = Thyra::createMember(A.domain());
616  // Create a preconditioner for the input forward operator
618  P = precFactory.createPrec();
619  Thyra::initializePrec<Scalar>(precFactory, rcpFromRef(A), P.ptr());
620  // Above, we don't really know the nature of the preconditioner. It could a
621  // single linear operator to be applied on the left or the right or it could
622  // be a split preconditioner with different linear operators to be applied
623  // on the right or left. Or, it could be a single linear operator that is
624  // not targeted to the left or the right.
625  //
626  // Create a LOWSB object given the created preconditioner
628  invertibleA = createGeneralPreconditionedLinearOpWithSolve<Scalar>(
629  Teuchos::rcp(&A, false), P.getConst(), lowsFactory, out);
630  // Grab a preconditioner operator out of the preconditioner object
632  // Clang 3.2 issues a warning if semicolons are on the same line as
633  // the 'if' statement. It's good practice in any case to make the
634  // empty 'if' body clear.
635  if (nonnull (P_op = P->getUnspecifiedPrecOp ()))
636  ;
637  else if (nonnull (P_op = P->getLeftPrecOp ()))
638  ;
639  else if (nonnull (P_op = P->getRightPrecOp ()))
640  ;
641  // Create a LOWSB object given an unspecified preconditioner operator
642  invertibleA = createUnspecifiedPreconditionedLinearOpWithSolve(
643  rcpFromRef(A), P_op, lowsFactory, out);
644  // Create a LOWSB object given a left preconditioner operator
645  if(supportsLeftPrec) {
646  invertibleA = createLeftPreconditionedLinearOpWithSolve(
647  rcpFromRef(A), P_op, lowsFactory,out);
648  }
649  // Create a LOWSB object given a right preconditioner operator
650  if(supportsRightPrec) {
651  invertibleA = createRightPreconditionedLinearOpWithSolve(
652  rcpFromRef(A), P_op, lowsFactory, out);
653  }
654  // Create a LOWSB object given (bad set of) left and right preconditioner
655  // operators
656  if( supportsLeftPrec && supportsRightPrec ) {
657  invertibleA = createLeftRightPreconditionedLinearOpWithSolve(
658  rcpFromRef(A), P_op, P_op, lowsFactory, out);
659  }
660  // Create a LOWSB object given a (very good) approximate forward linear
661  // operator to construct the preconditoner from..
662  invertibleA = createMatrixPreconditionedLinearOpWithSolve<Scalar>(
663  rcpFromRef(A), rcpFromRef(A), lowsFactory,out);
664  // Preconditioner reuse example
665  externalPreconditionerReuseWithSolves<Scalar>(
666  A_nonconst, // Don't worry, it will not be changed!
667  Thyra::NullLinearOpChanger<Scalar>(), // This object will not really change A!
668  lowsFactory, precFactory,
669  *b1, x1.ptr(), *b2, x2.ptr(), out );
670 }
671 
672 
673 #endif // THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP
void changeOp(const Teuchos::Ptr< LinearOpBase< Scalar > > &op) const
virtual RCP< const VectorSpaceBase< Scalar > > range() const =0
Return a smart pointer for the range space for this operator.
Silly abstract strategy interface for changing Thyra::LinearOpBase objects.
void assign(const Ptr< MultiVectorBase< Scalar > > &V, Scalar alpha)
V = alpha.
Use the non-transposed operator.
virtual RCP< PreconditionerBase< Scalar > > createPrec() const =0
Create an (uninitialized) LinearOpBase object to be initialized as the preconditioner later in this-&gt;...
Simple interface class to access a precreated preconditioner as one or more linear operators objects ...
virtual RCP< LinearOpWithSolveBase< Scalar > > createOp() const =0
Create an (uninitialized) LinearOpWithSolveBase object to be initialized later in this-&gt;initializeOp(...
RCP< const LinearOpBase< Scalar > > scale(const Scalar &scalar, const RCP< const LinearOpBase< Scalar > > &Op, const std::string &label="")
Build an implicit const scaled linear operator.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Factory interface for creating LinearOpWithSolveBase objects from compatible LinearOpBase objects...
Ptr< T > ptr() const
Abstract interface for finite-dimensional dense vectors.
Factory interface for creating preconditioner objects from LinearOpBase objects.
Simple struct for the return status from a solve.
Base class for all linear operators.
RCP< const LinearOpBase< Scalar > > adjoint(const RCP< const LinearOpBase< Scalar > > &Op, const std::string &label="")
Build an implicit const adjoined linear operator.
virtual RCP< const VectorSpaceBase< Scalar > > domain() const =0
Return a smart pointer for the domain space for this operator.
bool nonnull(const boost::shared_ptr< T > &p)
TypeTo as(const TypeFrom &t)
virtual void changeOp(const Teuchos::Ptr< LinearOpBase< Scalar > > &op) const =0