00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP
00030 #define THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP
00031
00032 #include "Thyra_LinearOpWithSolveFactoryBase.hpp"
00033 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
00034 #include "Thyra_PreconditionerFactoryHelpers.hpp"
00035 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
00036 #include "Thyra_DefaultPreconditioner.hpp"
00037
00038 namespace Thyra {
00039
00040
00041
00042
00043
00054 template<class Scalar>
00055 class LinearOpChanger {
00056 public:
00058 virtual ~LinearOpChanger() {}
00060 virtual void changeOp( LinearOpBase<Scalar> *op ) const = 0;
00061 };
00062
00066 template<class Scalar>
00067 class NullLinearOpChanger : public LinearOpChanger<Scalar> {
00068 public:
00070 void changeOp( LinearOpBase<Scalar> *op ) const {}
00071 };
00072
00073 }
00074
00075
00076
00077
00078
00079
00083 template<class Scalar>
00084 void singleLinearSolve(
00085 const Thyra::LinearOpBase<Scalar> &A
00086 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00087 ,const Thyra::VectorBase<Scalar> &b
00088 ,Thyra::VectorBase<Scalar> *x
00089 ,Teuchos::FancyOStream &out
00090 )
00091 {
00092 Teuchos::OSTab tab(out);
00093 out << "\nPerforming a single linear solve ...\n";
00094
00095 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00096 invertibleA = Thyra::linearOpWithSolve(lowsFactory,Teuchos::rcp(&A,false));
00097
00098 assign(&*x,Teuchos::ScalarTraits<Scalar>::zero());
00099 Thyra::SolveStatus<Scalar>
00100 status = Thyra::solve(*invertibleA,Thyra::NOTRANS,b,x);
00101 out << "\nSolve status:\n" << status;
00102 }
00103
00104
00109 template<class Scalar>
00110 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00111 createScaledAdjointLinearOpWithSolve(
00112 const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A
00113 ,const Scalar &scalar
00114 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00115 ,Teuchos::FancyOStream &out
00116 )
00117 {
00118 Teuchos::OSTab tab(out);
00119 out << "\nCreating a scaled adjoint LinearOpWithSolveBase object ...\n";
00120
00121 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00122 invertibleAdjointA
00123 = Thyra::linearOpWithSolve(lowsFactory,scale(scalar,adjoint(A)));
00124 out << "\nCreated LOWSB object:\n" << describe(*invertibleAdjointA,Teuchos::VERB_MEDIUM);
00125 return invertibleAdjointA;
00126 }
00127
00128
00133 template<class Scalar>
00134 void solveNumericalChangeSolve(
00135 Thyra::LinearOpBase<Scalar> *A
00136 ,const Thyra::LinearOpChanger<Scalar> &opChanger
00137 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00138 ,const Thyra::VectorBase<Scalar> &b1
00139 ,Thyra::VectorBase<Scalar> *x1
00140 ,const Thyra::VectorBase<Scalar> &b2
00141 ,Thyra::VectorBase<Scalar> *x2
00142 ,Teuchos::FancyOStream &out
00143 )
00144 {
00145 Teuchos::OSTab tab(out);
00146 out << "\nPerforming a solve, changing the operator, then performing another solve ...\n";
00147
00148 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00149 rcpA = Teuchos::rcp(A,false);
00150
00151 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00152 invertibleA = lowsFactory.createOp();
00153
00154 Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00155
00156 Thyra::assign(x1,Scalar(0.0));
00157 solve(*invertibleA,Thyra::NOTRANS,b1,x1);
00158
00159
00160
00161
00162
00163 Thyra::uninitializeOp<Scalar>(lowsFactory,&*invertibleA);
00164
00165 opChanger.changeOp(A);
00166 Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00167
00168
00169
00170 Thyra::assign(x2,Scalar(0.0));
00171 solve(*invertibleA,Thyra::NOTRANS,b2,x2);
00172 }
00173
00174
00180 template<class Scalar>
00181 void solveSmallNumericalChangeSolve(
00182 Thyra::LinearOpBase<Scalar> *A
00183 ,const Thyra::LinearOpChanger<Scalar> &opSmallChanger
00184 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00185 ,const Thyra::VectorBase<Scalar> &b1
00186 ,Thyra::VectorBase<Scalar> *x1
00187 ,const Thyra::VectorBase<Scalar> &b2
00188 ,Thyra::VectorBase<Scalar> *x2
00189 ,Teuchos::FancyOStream &out
00190 )
00191 {
00192 Teuchos::OSTab tab(out);
00193 out << "\nPerforming a solve, changing the operator in a very small way, then performing another solve ...\n";
00194
00195 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00196 rcpA = Teuchos::rcp(A,false);
00197
00198 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00199 invertibleA = lowsFactory.createOp();
00200
00201 Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00202
00203 Thyra::assign(x1,Scalar(0.0));
00204 solve(*invertibleA,Thyra::NOTRANS,b1,x1);
00205
00206
00207
00208
00209
00210 Thyra::uninitializeOp<Scalar>(lowsFactory,&*invertibleA);
00211
00212 opSmallChanger.changeOp(A);
00213 Thyra::initializeAndReuseOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00214
00215
00216 Thyra::assign(x2,Scalar(0.0));
00217 solve(*invertibleA,Thyra::NOTRANS,b2,x2);
00218 }
00219
00220
00226 template<class Scalar>
00227 void solveMajorChangeSolve(
00228 Thyra::LinearOpBase<Scalar> *A
00229 ,const Thyra::LinearOpChanger<Scalar> &opMajorChanger
00230 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00231 ,const Thyra::VectorBase<Scalar> &b1
00232 ,Thyra::VectorBase<Scalar> *x1
00233 ,const Thyra::VectorBase<Scalar> &b2
00234 ,Thyra::VectorBase<Scalar> *x2
00235 ,Teuchos::FancyOStream &out
00236 )
00237 {
00238 Teuchos::OSTab tab(out);
00239 out << "\nPerforming a solve, changing the operator in a major way, then performing another solve ...\n";
00240
00241 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00242 rcpA = Teuchos::rcp(A,false);
00243
00244 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00245 invertibleA = lowsFactory.createOp();
00246
00247 Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00248
00249 Thyra::assign(x1,Scalar(0.0));
00250 solve(*invertibleA,Thyra::NOTRANS,b1,x1);
00251
00252
00253
00254
00255
00256 Thyra::uninitializeOp<Scalar>(lowsFactory,&*invertibleA);
00257
00258 opMajorChanger.changeOp(A);
00259
00260 invertibleA = lowsFactory.createOp();
00261 Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00262
00263 Thyra::assign(x2,Scalar(0.0));
00264 solve(*invertibleA,Thyra::NOTRANS,b2,x2);
00265 }
00266
00267
00268
00269
00270
00271
00277 template<class Scalar>
00278 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00279 createGeneralPreconditionedLinearOpWithSolve(
00280 const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A
00281 ,const Teuchos::RCP<const Thyra::PreconditionerBase<Scalar> > &P
00282 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00283 ,Teuchos::FancyOStream &out
00284 )
00285 {
00286 Teuchos::OSTab tab(out);
00287 out << "\nCreating an externally preconditioned LinearOpWithSolveBase object ...\n";
00288 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00289 invertibleA = lowsFactory.createOp();
00290 Thyra::initializePreconditionedOp<Scalar>(lowsFactory,A,P,&*invertibleA);
00291 out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00292 return invertibleA;
00293 }
00294
00295
00301 template<class Scalar>
00302 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00303 createUnspecifiedPreconditionedLinearOpWithSolve(
00304 const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A
00305 ,const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op
00306 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00307 ,Teuchos::FancyOStream &out
00308 )
00309 {
00310 Teuchos::OSTab tab(out);
00311 out << "\nCreating an LinearOpWithSolveBase object given a preconditioner operator not targeted to the left or right ...\n";
00312 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00313 invertibleA = lowsFactory.createOp();
00314 Thyra::initializePreconditionedOp<Scalar>(
00315 lowsFactory,A,Thyra::unspecifiedPrec<Scalar>(P_op)
00316 ,&*invertibleA
00317 );
00318
00319
00320 out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00321 return invertibleA;
00322 }
00323
00324
00330 template<class Scalar>
00331 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00332 createLeftPreconditionedLinearOpWithSolve(
00333 const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A
00334 ,const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_left
00335 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00336 ,Teuchos::FancyOStream &out
00337 )
00338 {
00339 Teuchos::OSTab tab(out);
00340 out << "\nCreating an LinearOpWithSolveBase object given a left preconditioner operator ...\n";
00341 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00342 invertibleA = lowsFactory.createOp();
00343 Thyra::initializePreconditionedOp<Scalar>(
00344 lowsFactory,A,Thyra::leftPrec<Scalar>(P_op_left)
00345 ,&*invertibleA
00346 );
00347 out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00348 return invertibleA;
00349 }
00350
00351
00357 template<class Scalar>
00358 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00359 createRightPreconditionedLinearOpWithSolve(
00360 const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A
00361 ,const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_right
00362 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00363 ,Teuchos::FancyOStream &out
00364 )
00365 {
00366 Teuchos::OSTab tab(out);
00367 out << "\nCreating an LinearOpWithSolveBase object given a right preconditioner operator ...\n";
00368 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00369 invertibleA = lowsFactory.createOp();
00370 Thyra::initializePreconditionedOp<Scalar>(
00371 lowsFactory,A,Thyra::rightPrec<Scalar>(P_op_right)
00372 ,&*invertibleA
00373 );
00374 out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00375 return invertibleA;
00376 }
00377
00378
00384 template<class Scalar>
00385 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00386 createLeftRightPreconditionedLinearOpWithSolve(
00387 const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A
00388 ,const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_left
00389 ,const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &P_op_right
00390 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00391 ,Teuchos::FancyOStream &out
00392 )
00393 {
00394 Teuchos::OSTab tab(out);
00395 out << "\nCreating an LinearOpWithSolveBase object given a left and right preconditioner operator ...\n";
00396 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00397 invertibleA = lowsFactory.createOp();
00398 Thyra::initializePreconditionedOp<Scalar>(
00399 lowsFactory,A,Thyra::splitPrec<Scalar>(P_op_left,P_op_right)
00400 ,&*invertibleA
00401 );
00402 out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00403 return invertibleA;
00404 }
00405
00406
00412 template<class Scalar>
00413 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00414 createMatrixPreconditionedLinearOpWithSolve(
00415 const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A
00416 ,const Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > &A_approx
00417 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00418 ,Teuchos::FancyOStream &out
00419 )
00420 {
00421 Teuchos::OSTab tab(out);
00422 out << "\nCreating a LinearOpWithSolveBase object given an approximate forward"
00423 << " operator to define the preconditioner ...\n";
00424 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00425 invertibleA = lowsFactory.createOp();
00426 Thyra::initializeApproxPreconditionedOp<Scalar>(lowsFactory,A,A_approx,&*invertibleA);
00427 out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00428 return invertibleA;
00429 }
00430
00431
00435 template<class Scalar>
00436 void externalPreconditionerReuseWithSolves(
00437 Thyra::LinearOpBase<Scalar> *A_inout
00438 ,const Thyra::LinearOpChanger<Scalar> &opChanger
00439 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00440 ,const Thyra::PreconditionerFactoryBase<Scalar> &precFactory
00441 ,const Thyra::VectorBase<Scalar> &b1
00442 ,Thyra::VectorBase<Scalar> *x1
00443 ,const Thyra::VectorBase<Scalar> &b2
00444 ,Thyra::VectorBase<Scalar> *x2
00445 ,Teuchos::FancyOStream &out
00446 )
00447 {
00448 Teuchos::OSTab tab(out);
00449 out << "\nShowing resuse of the preconditioner ...\n";
00450 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
00451 A = rcp(A_inout,false);
00452
00453 Teuchos::RCP<Thyra::PreconditionerBase<Scalar> >
00454 P = precFactory.createPrec();
00455 Thyra::initializePrec<Scalar>(precFactory,A,&*P);
00456
00457 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00458 invertibleA = lowsFactory.createOp();
00459 Thyra::initializePreconditionedOp<Scalar>(lowsFactory,A,P,&*invertibleA);
00460
00461 assign(&*x1,Teuchos::ScalarTraits<Scalar>::zero());
00462 Thyra::SolveStatus<Scalar>
00463 status1 = Thyra::solve(*invertibleA,Thyra::NOTRANS,b1,x1);
00464 out << "\nSolve status:\n" << status1;
00465
00466 opChanger.changeOp(&*A);
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 Thyra::initializePreconditionedOp<Scalar>(lowsFactory,A,P,&*invertibleA);
00478
00479 assign(&*x2,Teuchos::ScalarTraits<Scalar>::zero());
00480 Thyra::SolveStatus<Scalar>
00481 status2 = Thyra::solve(*invertibleA,Thyra::NOTRANS,b2,x2);
00482 out << "\nSolve status:\n" << status2;
00483 }
00484
00485
00486
00487
00488
00494 template<class Scalar>
00495 void nonExternallyPreconditionedLinearSolveUseCases(
00496 const Thyra::LinearOpBase<Scalar> &A
00497 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00498 ,bool supportsAdjoints
00499 ,Teuchos::FancyOStream &out
00500 )
00501 {
00502 Teuchos::OSTab tab(out);
00503 out << "\nRunning example use cases for a LinearOpWithSolveFactoryBase object ...\n";
00504
00505 Teuchos::RCP<Thyra::VectorBase<Scalar> >
00506 b1 = Thyra::createMember(A.range()),
00507 b2 = Thyra::createMember(A.range());
00508 Thyra::randomize( Scalar(-1.0), Scalar(+1.0), &*b1 );
00509 Thyra::randomize( Scalar(-1.0), Scalar(+1.0), &*b2 );
00510
00511 Teuchos::RCP<Thyra::VectorBase<Scalar> >
00512 x1 = Thyra::createMember(A.domain()),
00513 x2 = Thyra::createMember(A.domain());
00514
00515 singleLinearSolve(A,lowsFactory,*b1,&*x1,out);
00516
00517 if(supportsAdjoints) {
00518 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00519 invertibleAdjointA = createScaledAdjointLinearOpWithSolve(
00520 Teuchos::rcp(&A,false),Scalar(2.0),lowsFactory,out);
00521 }
00522
00523 solveNumericalChangeSolve(
00524 const_cast<Thyra::LinearOpBase<Scalar>*>(&A)
00525 ,Thyra::NullLinearOpChanger<Scalar>()
00526 ,lowsFactory,*b1,&*x1,*b2,&*x1,out
00527 );
00528
00529 solveSmallNumericalChangeSolve(
00530 const_cast<Thyra::LinearOpBase<Scalar>*>(&A)
00531 ,Thyra::NullLinearOpChanger<Scalar>()
00532 ,lowsFactory,*b1,&*x1,*b2,&*x1,out
00533 );
00534
00535 solveMajorChangeSolve(
00536 const_cast<Thyra::LinearOpBase<Scalar>*>(&A)
00537 ,Thyra::NullLinearOpChanger<Scalar>()
00538 ,lowsFactory,*b1,&*x1,*b2,&*x1,out
00539 );
00540 }
00541
00547 template<class Scalar>
00548 void externallyPreconditionedLinearSolveUseCases(
00549 const Thyra::LinearOpBase<Scalar> &A
00550 ,const Thyra::LinearOpWithSolveFactoryBase<Scalar> &lowsFactory
00551 ,const Thyra::PreconditionerFactoryBase<Scalar> &precFactory
00552 ,const bool supportsLeftPrec
00553 ,const bool supportsRightPrec
00554 ,Teuchos::FancyOStream &out
00555 )
00556 {
00557 Teuchos::OSTab tab(out);
00558 out << "\nRunning example use cases with an externally defined"
00559 << " preconditioner with a LinearOpWithSolveFactoryBase object ...\n";
00560
00561 Teuchos::RCP<Thyra::VectorBase<Scalar> >
00562 b1 = Thyra::createMember(A.range()),
00563 b2 = Thyra::createMember(A.range());
00564 Thyra::randomize( Scalar(-1.0), Scalar(+1.0), &*b1 );
00565 Thyra::randomize( Scalar(-1.0), Scalar(+1.0), &*b2 );
00566
00567 Teuchos::RCP<Thyra::VectorBase<Scalar> >
00568 x1 = Thyra::createMember(A.domain()),
00569 x2 = Thyra::createMember(A.domain());
00570
00571 Teuchos::RCP<Thyra::PreconditionerBase<Scalar> >
00572 P = precFactory.createPrec();
00573 Thyra::initializePrec<Scalar>(precFactory,Teuchos::rcp(&A,false),&*P);
00574
00575
00576
00577
00578
00579
00580
00581 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00582 invertibleA = createGeneralPreconditionedLinearOpWithSolve<Scalar>(
00583 Teuchos::rcp(&A,false),P,lowsFactory,out);
00584
00585 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > P_op;
00586 if((P_op=P->getUnspecifiedPrecOp()).get());
00587 else if((P_op=P->getLeftPrecOp()).get());
00588 else if((P_op=P->getRightPrecOp()).get());
00589
00590 invertibleA = createUnspecifiedPreconditionedLinearOpWithSolve(
00591 Teuchos::rcp(&A,false),P_op,lowsFactory,out);
00592
00593 if(supportsLeftPrec) {
00594 invertibleA = createLeftPreconditionedLinearOpWithSolve(
00595 Teuchos::rcp(&A,false),P_op,lowsFactory,out);
00596 }
00597
00598 if(supportsRightPrec) {
00599 invertibleA = createRightPreconditionedLinearOpWithSolve(
00600 Teuchos::rcp(&A,false),P_op,lowsFactory,out);
00601 }
00602
00603
00604 if( supportsLeftPrec && supportsRightPrec ) {
00605 invertibleA = createLeftRightPreconditionedLinearOpWithSolve(
00606 Teuchos::rcp(&A,false),P_op,P_op,lowsFactory,out);
00607 }
00608
00609
00610 invertibleA = createMatrixPreconditionedLinearOpWithSolve<Scalar>(
00611 Teuchos::rcp(&A,false),Teuchos::rcp(&A,false),lowsFactory,out);
00612
00613 externalPreconditionerReuseWithSolves(
00614 const_cast<Thyra::LinearOpBase<Scalar>*>(&A)
00615 ,Thyra::NullLinearOpChanger<Scalar>()
00616 ,lowsFactory,precFactory
00617 ,*b1,&*x1,*b2,&*x2,out
00618 );
00619 }
00620
00621 #endif // THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP