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
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
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 }
00078
00079
00080
00081
00082
00083
00084
00085
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
00101 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00102 invertibleA = Thyra::linearOpWithSolve(lowsFactory,Teuchos::rcp(&A,false));
00103
00104 assign(&*x,Teuchos::ScalarTraits<Scalar>::zero());
00105 Thyra::SolveStatus<Scalar>
00106 status = Thyra::solve(*invertibleA,Thyra::NOTRANS,b,x);
00107 out << "\nSolve status:\n" << status;
00108 }
00109
00110
00111
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
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 }
00134
00135
00136
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
00156 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00157 rcpA = Teuchos::rcp(A,false);
00158
00159 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00160 invertibleA = lowsFactory.createOp();
00161
00162 Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00163
00164 Thyra::assign(x1,Scalar(0.0));
00165 solve(*invertibleA,Thyra::NOTRANS,b1,x1);
00166
00167
00168
00169
00170
00171 Thyra::uninitializeOp<Scalar>(lowsFactory,&*invertibleA);
00172
00173 opChanger.changeOp(A);
00174 Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00175
00176
00177
00178 Thyra::assign(x2,Scalar(0.0));
00179 solve(*invertibleA,Thyra::NOTRANS,b2,x2);
00180 }
00181
00182
00183
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
00204 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00205 rcpA = Teuchos::rcp(A,false);
00206
00207 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00208 invertibleA = lowsFactory.createOp();
00209
00210 Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00211
00212 Thyra::assign(x1,Scalar(0.0));
00213 solve(*invertibleA,Thyra::NOTRANS,b1,x1);
00214
00215
00216
00217
00218
00219 Thyra::uninitializeOp<Scalar>(lowsFactory,&*invertibleA);
00220
00221 opSmallChanger.changeOp(A);
00222 Thyra::initializeAndReuseOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00223
00224
00225 Thyra::assign(x2,Scalar(0.0));
00226 solve(*invertibleA,Thyra::NOTRANS,b2,x2);
00227 }
00228
00229
00230
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
00251 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00252 rcpA = Teuchos::rcp(A,false);
00253
00254 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00255 invertibleA = lowsFactory.createOp();
00256
00257 Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00258
00259 Thyra::assign(x1,Scalar(0.0));
00260 solve(*invertibleA,Thyra::NOTRANS,b1,x1);
00261
00262
00263
00264
00265
00266 Thyra::uninitializeOp<Scalar>(lowsFactory,&*invertibleA);
00267
00268 opMajorChanger.changeOp(A);
00269
00270 invertibleA = lowsFactory.createOp();
00271 Thyra::initializeOp<Scalar>(lowsFactory,rcpA,&*invertibleA);
00272
00273 Thyra::assign(x2,Scalar(0.0));
00274 solve(*invertibleA,Thyra::NOTRANS,b2,x2);
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
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 }
00306
00307
00308
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
00332
00333 out << "\nCreated LOWSB object:\n" << describe(*invertibleA,Teuchos::VERB_MEDIUM);
00334 return invertibleA;
00335 }
00336
00337
00338
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 }
00365
00366
00367
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 }
00393
00394
00395
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 }
00423
00424
00425
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 }
00449
00450
00451
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
00473 Teuchos::RCP<Thyra::PreconditionerBase<Scalar> >
00474 P = precFactory.createPrec();
00475 Thyra::initializePrec<Scalar>(precFactory,A,&*P);
00476
00477 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00478 invertibleA = lowsFactory.createOp();
00479 Thyra::initializePreconditionedOp<Scalar>(lowsFactory,A,P,&*invertibleA);
00480
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
00486 opChanger.changeOp(&*A);
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 Thyra::initializePreconditionedOp<Scalar>(lowsFactory,A,P,&*invertibleA);
00498
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 }
00504
00505
00506
00507
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
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
00533 Teuchos::RCP<Thyra::VectorBase<Scalar> >
00534 x1 = Thyra::createMember(A.domain()),
00535 x2 = Thyra::createMember(A.domain());
00536
00537 singleLinearSolve(A,lowsFactory,*b1,&*x1,out);
00538
00539 if(supportsAdjoints) {
00540 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00541 invertibleAdjointA = createScaledAdjointLinearOpWithSolve(
00542 Teuchos::rcp(&A,false),Scalar(2.0),lowsFactory,out);
00543 }
00544
00545 solveNumericalChangeSolve(
00546 const_cast<Thyra::LinearOpBase<Scalar>*>(&A)
00547 ,Thyra::NullLinearOpChanger<Scalar>()
00548 ,lowsFactory,*b1,&*x1,*b2,&*x1,out
00549 );
00550
00551 solveSmallNumericalChangeSolve(
00552 const_cast<Thyra::LinearOpBase<Scalar>*>(&A)
00553 ,Thyra::NullLinearOpChanger<Scalar>()
00554 ,lowsFactory,*b1,&*x1,*b2,&*x1,out
00555 );
00556
00557 solveMajorChangeSolve(
00558 const_cast<Thyra::LinearOpBase<Scalar>*>(&A)
00559 ,Thyra::NullLinearOpChanger<Scalar>()
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
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
00590 Teuchos::RCP<Thyra::VectorBase<Scalar> >
00591 x1 = Thyra::createMember(A.domain()),
00592 x2 = Thyra::createMember(A.domain());
00593
00594 Teuchos::RCP<Thyra::PreconditionerBase<Scalar> >
00595 P = precFactory.createPrec();
00596 Thyra::initializePrec<Scalar>(precFactory,Teuchos::rcp(&A,false),&*P);
00597
00598
00599
00600
00601
00602
00603
00604 Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
00605 invertibleA = createGeneralPreconditionedLinearOpWithSolve<Scalar>(
00606 Teuchos::rcp(&A,false),P,lowsFactory,out);
00607
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
00613 invertibleA = createUnspecifiedPreconditionedLinearOpWithSolve(
00614 Teuchos::rcp(&A,false),P_op,lowsFactory,out);
00615
00616 if(supportsLeftPrec) {
00617 invertibleA = createLeftPreconditionedLinearOpWithSolve(
00618 Teuchos::rcp(&A,false),P_op,lowsFactory,out);
00619 }
00620
00621 if(supportsRightPrec) {
00622 invertibleA = createRightPreconditionedLinearOpWithSolve(
00623 Teuchos::rcp(&A,false),P_op,lowsFactory,out);
00624 }
00625
00626
00627 if( supportsLeftPrec && supportsRightPrec ) {
00628 invertibleA = createLeftRightPreconditionedLinearOpWithSolve(
00629 Teuchos::rcp(&A,false),P_op,P_op,lowsFactory,out);
00630 }
00631
00632
00633 invertibleA = createMatrixPreconditionedLinearOpWithSolve<Scalar>(
00634 Teuchos::rcp(&A,false),Teuchos::rcp(&A,false),lowsFactory,out);
00635
00636 externalPreconditionerReuseWithSolves(
00637 const_cast<Thyra::LinearOpBase<Scalar>*>(&A)
00638 ,Thyra::NullLinearOpChanger<Scalar>()
00639 ,lowsFactory,precFactory
00640 ,*b1,&*x1,*b2,&*x2,out
00641 );
00642 }
00643
00644
00645 #endif // THYRA_LINEAR_OP_WITH_SOLVE_EXAMPLES_HPP