10 #ifndef THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP
11 #define THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP
14 #include "Thyra_LinearOpWithSolveFactoryBase.hpp"
15 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
16 #include "Thyra_LinearOpWithSolveBase.hpp"
17 #include "Thyra_PreconditionerFactoryHelpers.hpp"
18 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
19 #include "Thyra_DefaultPreconditioner.hpp"
20 #include "Thyra_MultiVectorStdOps.hpp"
21 #include "Thyra_VectorStdOps.hpp"
22 #include "Thyra_VectorBase.hpp"
42 template<
class Scalar>
54 template<
class Scalar>
74 template<
class Scalar>
75 void singleLinearSolve(
84 using Teuchos::rcpFromRef;
86 out <<
"\nPerforming a single linear solve ...\n";
89 Thyra::linearOpWithSolve(lowsFactory, rcpFromRef(A));
94 out <<
"\nSolve status:\n" << status;
103 template<
class Scalar>
105 createScaledAdjointLinearOpWithSolve(
107 const Scalar &scalar,
113 out <<
"\nCreating a scaled adjoint LinearOpWithSolveBase object ...\n";
116 Thyra::linearOpWithSolve(lowsFactory,
scale(scalar,
adjoint(A)));
117 out <<
"\nCreated LOWSB object:\n" << describe(*invertibleAdjointA,
119 return invertibleAdjointA;
128 template<
class Scalar>
129 void solveNumericalChangeSolve(
140 using Teuchos::as;
using Teuchos::ptr;
using Teuchos::rcpFromPtr;
142 out <<
"\nPerforming a solve, changing the operator, then performing another"
150 Thyra::initializeOp<Scalar>(lowsFactory, rcpA, invertibleA.
ptr());
152 Thyra::assign(x1, as<Scalar>(0.0));
159 Thyra::uninitializeOp<Scalar>(lowsFactory, invertibleA.ptr());
162 Thyra::initializeOp<Scalar>(lowsFactory, rcpA, invertibleA.ptr());
166 Thyra::assign<Scalar>(x2, as<Scalar>(0.0));
177 template<
class Scalar>
178 void solveSmallNumericalChangeSolve(
189 using Teuchos::ptr;
using Teuchos::as;
using Teuchos::rcpFromPtr;
191 out <<
"\nPerforming a solve, changing the operator in a very small way,"
192 <<
" then performing another solve ...\n";
199 Thyra::initializeOp<Scalar>(lowsFactory, rcpA, invertibleA.
ptr());
201 Thyra::assign(x1, as<Scalar>(0.0));
208 Thyra::uninitializeOp<Scalar>(lowsFactory, invertibleA.ptr());
211 Thyra::initializeAndReuseOp<Scalar>(lowsFactory, rcpA, invertibleA.ptr());
214 Thyra::assign(x2, as<Scalar>(0.0));
225 template<
class Scalar>
226 void solveMajorChangeSolve(
239 out <<
"\nPerforming a solve, changing the operator in a major way, then performing"
240 <<
" another solve ...\n";
247 Thyra::initializeOp<Scalar>(lowsFactory, rcpA, invertibleA.
ptr());
249 Thyra::assign(x1, as<Scalar>(0.0));
256 Thyra::uninitializeOp<Scalar>(lowsFactory, invertibleA.ptr());
260 invertibleA = lowsFactory.createOp();
261 Thyra::initializeOp<Scalar>(lowsFactory, rcpA, invertibleA.ptr());
263 Thyra::assign(x2, as<Scalar>(0.0));
279 template<
class Scalar>
281 createGeneralPreconditionedLinearOpWithSolve(
289 out <<
"\nCreating an externally preconditioned LinearOpWithSolveBase object ...\n";
292 Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A, P, invertibleA.
ptr());
304 template<
class Scalar>
306 createUnspecifiedPreconditionedLinearOpWithSolve(
314 out <<
"\nCreating an LinearOpWithSolveBase object given a preconditioner operator"
315 <<
" not targeted to the left or right ...\n";
318 Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A,
319 Thyra::unspecifiedPrec<Scalar>(P_op), invertibleA.
ptr());
333 template<
class Scalar>
335 createLeftPreconditionedLinearOpWithSolve(
343 out <<
"\nCreating an LinearOpWithSolveBase object given a left preconditioner"
344 <<
" operator ...\n";
347 Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A,
348 Thyra::leftPrec<Scalar>(P_op_left), invertibleA.
ptr());
360 template<
class Scalar>
362 createRightPreconditionedLinearOpWithSolve(
370 out <<
"\nCreating an LinearOpWithSolveBase object given a right"
371 <<
" preconditioner operator ...\n";
374 Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A,
375 Thyra::rightPrec<Scalar>(P_op_right), invertibleA.
ptr());
387 template<
class Scalar>
389 createLeftRightPreconditionedLinearOpWithSolve(
398 out <<
"\nCreating an LinearOpWithSolveBase object given a left and"
399 <<
"right preconditioner operator ...\n";
402 Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A,
403 Thyra::splitPrec<Scalar>(P_op_left, P_op_right), invertibleA.
ptr());
415 template<
class Scalar>
417 createMatrixPreconditionedLinearOpWithSolve(
425 out <<
"\nCreating a LinearOpWithSolveBase object given an approximate forward"
426 <<
" operator to define the preconditioner ...\n";
429 Thyra::initializeApproxPreconditionedOp<Scalar>(lowsFactory, A, A_approx,
440 template<
class Scalar>
441 void externalPreconditionerReuseWithSolves(
453 using Teuchos::tab;
using Teuchos::rcpFromPtr;
456 out <<
"\nShowing resuse of the preconditioner ...\n";
461 Thyra::initializePrec<Scalar>(precFactory, A, P.
ptr());
465 Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A, P, invertibleA.
ptr());
470 out <<
"\nSolve status:\n" << status1;
483 Thyra::initializePreconditionedOp<Scalar>(lowsFactory, A, P, invertibleA.ptr());
488 out <<
"\nSolve status:\n" << status2;
502 template<
class Scalar>
503 void nonExternallyPreconditionedLinearSolveUseCases(
506 bool supportsAdjoints,
512 out <<
"\nRunning example use cases for a LinearOpWithSolveFactoryBase object ...\n";
518 b1 = Thyra::createMember(A.
range()),
519 b2 = Thyra::createMember(A.
range());
520 Thyra::randomize( as<Scalar>(-1.0), as<Scalar>(+1.0), b1.
ptr() );
521 Thyra::randomize( as<Scalar>(-1.0), as<Scalar>(+1.0), b2.ptr() );
524 x1 = Thyra::createMember(A.
domain()),
525 x2 = Thyra::createMember(A.
domain());
527 singleLinearSolve(A, lowsFactory, *b1, x1.
ptr(), out);
529 if(supportsAdjoints) {
531 invertibleAdjointA = createScaledAdjointLinearOpWithSolve(
532 Teuchos::rcp(&A,
false),as<Scalar>(2.0),lowsFactory,out);
535 solveNumericalChangeSolve<Scalar>(
538 lowsFactory, *b1, x1.
ptr(), *b2, x1.ptr(), out );
540 solveSmallNumericalChangeSolve<Scalar>(
543 lowsFactory, *b1, x1.
ptr(), *b2, x1.ptr(), out );
545 solveMajorChangeSolve<Scalar>(
548 lowsFactory, *b1, x1.
ptr(), *b2, x1.ptr(), out );
557 template<
class Scalar>
558 void externallyPreconditionedLinearSolveUseCases(
562 const bool supportsLeftPrec,
563 const bool supportsRightPrec,
569 out <<
"\nRunning example use cases with an externally defined"
570 <<
" preconditioner with a LinearOpWithSolveFactoryBase object ...\n";
576 b1 = Thyra::createMember(A.
range()),
577 b2 = Thyra::createMember(A.
range());
578 Thyra::randomize( as<Scalar>(-1.0), as<Scalar>(+1.0), b1.
ptr() );
579 Thyra::randomize( as<Scalar>(-1.0), as<Scalar>(+1.0), b2.ptr() );
582 x1 = Thyra::createMember(A.
domain()),
583 x2 = Thyra::createMember(A.
domain());
587 Thyra::initializePrec<Scalar>(precFactory, rcpFromRef(A), P.ptr());
596 invertibleA = createGeneralPreconditionedLinearOpWithSolve<Scalar>(
597 Teuchos::rcp(&A,
false), P.getConst(), lowsFactory, out);
603 if (
nonnull (P_op = P->getUnspecifiedPrecOp ()))
605 else if (
nonnull (P_op = P->getLeftPrecOp ()))
607 else if (
nonnull (P_op = P->getRightPrecOp ()))
610 invertibleA = createUnspecifiedPreconditionedLinearOpWithSolve(
611 rcpFromRef(A), P_op, lowsFactory, out);
613 if(supportsLeftPrec) {
614 invertibleA = createLeftPreconditionedLinearOpWithSolve(
615 rcpFromRef(A), P_op, lowsFactory,out);
618 if(supportsRightPrec) {
619 invertibleA = createRightPreconditionedLinearOpWithSolve(
620 rcpFromRef(A), P_op, lowsFactory, out);
624 if( supportsLeftPrec && supportsRightPrec ) {
625 invertibleA = createLeftRightPreconditionedLinearOpWithSolve(
626 rcpFromRef(A), P_op, P_op, lowsFactory, out);
630 invertibleA = createMatrixPreconditionedLinearOpWithSolve<Scalar>(
631 rcpFromRef(A), rcpFromRef(A), lowsFactory,out);
633 externalPreconditionerReuseWithSolves<Scalar>(
636 lowsFactory, precFactory,
637 *b1, x1.
ptr(), *b2, x2.ptr(), out );
641 #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->...
Simple interface class to access a precreated preconditioner as one or more linear operators objects ...
virtual ~LinearOpChanger()
virtual RCP< LinearOpWithSolveBase< Scalar > > createOp() const =0
Create an (uninitialized) LinearOpWithSolveBase object to be initialized later in this->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...
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