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 Rythmos_IMPLICIT_RK_STEPPER_H
00030 #define Rythmos_IMPLICIT_RK_STEPPER_H
00031
00032 #include "Rythmos_Types.hpp"
00033 #include "Rythmos_StepperBase.hpp"
00034 #include "Rythmos_DataStore.hpp"
00035 #include "Rythmos_LinearInterpolator.hpp"
00036 #include "Rythmos_SingleResidualModelEvaluator.hpp"
00037 #include "Rythmos_SolverAcceptingStepperBase.hpp"
00038 #include "Rythmos_ImplicitRKModelEvaluator.hpp"
00039
00040 #include "Thyra_VectorBase.hpp"
00041 #include "Thyra_ModelEvaluator.hpp"
00042 #include "Thyra_ModelEvaluatorHelpers.hpp"
00043 #include "Thyra_ProductVectorBase.hpp"
00044 #include "Thyra_AssertOp.hpp"
00045 #include "Thyra_NonlinearSolverBase.hpp"
00046 #include "Thyra_TestingTools.hpp"
00047
00048 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
00049 #include "Teuchos_as.hpp"
00050
00051
00052 namespace Rythmos {
00053
00054
00056 template<class Scalar>
00057 class ImplicitRKStepper : virtual public SolverAcceptingStepperBase<Scalar>
00058 {
00059 public:
00060
00062 typedef typename ScalarTraits<Scalar>::magnitudeType ScalarMag;
00063
00066
00068 ImplicitRKStepper();
00069
00071 void initialize(
00072 const RCP<const Thyra::ModelEvaluator<Scalar> > &model,
00073 const RCP<Thyra::NonlinearSolverBase<Scalar> > &solver,
00074 const RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > &irk_W_factory
00075 );
00076
00078 void setInterpolator(RCP<InterpolatorBase<Scalar> > interpolator);
00079
00081 RCP<InterpolatorBase<Scalar> > unsetInterpolator();
00082
00084
00087
00089 void setSolver(
00090 const RCP<Thyra::NonlinearSolverBase<Scalar> > &solver
00091 );
00092
00094 RCP<Thyra::NonlinearSolverBase<Scalar> >
00095 getNonconstSolver();
00096
00098 RCP<const Thyra::NonlinearSolverBase<Scalar> >
00099 getSolver() const;
00100
00102
00105
00107 bool supportsCloning() const;
00108
00110 RCP<StepperBase<Scalar> > cloneStepperAlgorithm() const;
00111
00113 void setModel(const RCP<const Thyra::ModelEvaluator<Scalar> > &model);
00114
00116 RCP<const Thyra::ModelEvaluator<Scalar> >
00117 getModel() const;
00118
00120 void setInitialCondition(
00121 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &initialCondition
00122 );
00123
00125 Scalar takeStep(Scalar dt, StepSizeType flag);
00126
00128 const StepStatus<Scalar> getStepStatus() const;
00129
00131
00134
00136 RCP<const Thyra::VectorSpaceBase<Scalar> >
00137 get_x_space() const;
00138
00140 void addPoints(
00141 const Array<Scalar>& time_vec,
00142 const Array<RCP<const Thyra::VectorBase<Scalar> > >& x_vec,
00143 const Array<RCP<const Thyra::VectorBase<Scalar> > >& xdot_vec
00144 );
00145
00147 TimeRange<Scalar> getTimeRange() const;
00148
00150 void getPoints(
00151 const Array<Scalar>& time_vec,
00152 Array<RCP<const Thyra::VectorBase<Scalar> > >* x_vec,
00153 Array<RCP<const Thyra::VectorBase<Scalar> > >* xdot_vec,
00154 Array<ScalarMag>* accuracy_vec
00155 ) const;
00156
00158 void getNodes(Array<Scalar>* time_vec) const;
00159
00161 void removeNodes(Array<Scalar>& time_vec);
00162
00164 int getOrder() const;
00165
00167
00170
00172 void setParameterList(RCP<ParameterList> const& paramList);
00173
00175 RCP<ParameterList> getNonconstParameterList();
00176
00178 RCP<ParameterList> unsetParameterList();
00179
00181 RCP<const ParameterList> getValidParameters() const;
00182
00184
00187
00189 void describe(
00190 FancyOStream &out,
00191 const Teuchos::EVerbosityLevel verbLevel
00192 ) const;
00193
00195
00196 private:
00197
00198
00199
00200
00201 bool isInitialized_;
00202 RCP<const Thyra::ModelEvaluator<Scalar> > model_;
00203 RCP<Thyra::NonlinearSolverBase<Scalar> > solver_;
00204 RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > irk_W_factory_;
00205 RCP<ParameterList> paramList_;
00206
00207 int numStages_;
00208
00209 Thyra::ModelEvaluatorBase::InArgs<Scalar> basePoint_;
00210 RCP<Thyra::VectorBase<Scalar> > x_;
00211 RCP<Thyra::VectorBase<Scalar> > x_old_;
00212 RCP<Thyra::VectorBase<Scalar> > x_dot_;
00213
00214 TimeRange<Scalar> timeRange_;
00215
00216 RCP<ImplicitRKModelEvaluator<Scalar> > irkModel_;
00217 RKButcherTableau<Scalar> irkButcherTableau_;
00218
00219
00220 RCP<Thyra::ProductVectorBase<Scalar> > x_stage_bar_;
00221
00222
00223
00224
00225 void initialize_();
00226
00227 };
00228
00229
00234 template<class Scalar>
00235 RCP<ImplicitRKStepper<Scalar> >
00236 implicitRKStepper(
00237 const RCP<const Thyra::ModelEvaluator<Scalar> > &model,
00238 const RCP<Thyra::NonlinearSolverBase<Scalar> > &solver,
00239 const RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > &irk_W_factory
00240 )
00241 {
00242 RCP<ImplicitRKStepper<Scalar> > stepper(new ImplicitRKStepper<Scalar>());
00243 stepper->initialize( model, solver, irk_W_factory );
00244 return stepper;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 template<class Scalar>
00256 ImplicitRKStepper<Scalar>::ImplicitRKStepper()
00257 : isInitialized_(false),
00258 numStages_(1)
00259 {}
00260
00261
00262 template<class Scalar>
00263 void ImplicitRKStepper<Scalar>::initialize(
00264 const RCP<const Thyra::ModelEvaluator<Scalar> > &model,
00265 const RCP<Thyra::NonlinearSolverBase<Scalar> > &solver,
00266 const RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > &irk_W_factory
00267 )
00268 {
00269
00270
00271
00272 model_ = model;
00273 solver_ = solver;
00274 irk_W_factory_ = irk_W_factory;
00275
00276 }
00277
00278
00279 template<class Scalar>
00280 void ImplicitRKStepper<Scalar>::setInterpolator(
00281 RCP<InterpolatorBase<Scalar> > interpolator
00282 )
00283 {
00284 TEST_FOR_EXCEPT(true);
00285 }
00286
00287
00288 template<class Scalar>
00289 RCP<InterpolatorBase<Scalar> >
00290 ImplicitRKStepper<Scalar>::unsetInterpolator()
00291 {
00292 TEST_FOR_EXCEPT(true);
00293 return Teuchos::null;
00294 }
00295
00296
00297
00298
00299
00300 template<class Scalar>
00301 void ImplicitRKStepper<Scalar>::setSolver(
00302 const RCP<Thyra::NonlinearSolverBase<Scalar> > &solver
00303 )
00304 {
00305 TEST_FOR_EXCEPT(true);
00306 }
00307
00308
00309 template<class Scalar>
00310 RCP<Thyra::NonlinearSolverBase<Scalar> >
00311 ImplicitRKStepper<Scalar>::getNonconstSolver()
00312 {
00313 return solver_;
00314 }
00315
00316
00317 template<class Scalar>
00318 RCP<const Thyra::NonlinearSolverBase<Scalar> >
00319 ImplicitRKStepper<Scalar>::getSolver() const
00320 {
00321 return solver_;
00322 }
00323
00324
00325
00326
00327
00328 template<class Scalar>
00329 bool ImplicitRKStepper<Scalar>::supportsCloning() const
00330 {
00331 return true;
00332 }
00333
00334
00335 template<class Scalar>
00336 RCP<StepperBase<Scalar> >
00337 ImplicitRKStepper<Scalar>::cloneStepperAlgorithm() const
00338 {
00339 TEST_FOR_EXCEPT(true);
00340 return Teuchos::null;
00341 }
00342
00343
00344 template<class Scalar>
00345 void ImplicitRKStepper<Scalar>::setModel(
00346 const RCP<const Thyra::ModelEvaluator<Scalar> > &model
00347 )
00348 {
00349 TEST_FOR_EXCEPT(true);
00350 }
00351
00352
00353 template<class Scalar>
00354 RCP<const Thyra::ModelEvaluator<Scalar> >
00355 ImplicitRKStepper<Scalar>::getModel() const
00356 {
00357 return model_;
00358 }
00359
00360
00361 template<class Scalar>
00362 void ImplicitRKStepper<Scalar>::setInitialCondition(
00363 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &initialCondition
00364 )
00365 {
00366
00367 typedef ScalarTraits<Scalar> ST;
00368 typedef Thyra::ModelEvaluatorBase MEB;
00369
00370 TEST_FOR_EXCEPT( is_null(model_) );
00371
00372 basePoint_ = initialCondition;
00373
00374
00375
00376 RCP<const Thyra::VectorBase<Scalar> >
00377 x_init = initialCondition.get_x();
00378
00379 #ifdef TEUCHOS_DEBUG
00380 TEST_FOR_EXCEPTION(
00381 is_null(x_init), std::logic_error,
00382 "Error, if the client passes in an intial condition to setInitialCondition(...),\n"
00383 "then x can not be null!" );
00384 THYRA_ASSERT_VEC_SPACES(
00385 "Rythmos::BackwardEulerStepper::setInitialCondition(...)",
00386 *x_init->space(), *model_->get_x_space() );
00387 #endif
00388
00389 x_ = x_init->clone_v();
00390
00391
00392
00393 x_dot_ = createMember(model_->get_x_space());
00394
00395 RCP<const Thyra::VectorBase<Scalar> >
00396 x_dot_init = initialCondition.get_x_dot();
00397
00398 if (!is_null(x_dot_init))
00399 assign(&*x_dot_,*x_dot_init);
00400 else
00401 assign(&*x_dot_,ST::zero());
00402
00403
00404
00405 const Scalar t =
00406 (
00407 initialCondition.supports(MEB::IN_ARG_t)
00408 ? initialCondition.get_t()
00409 : ST::zero()
00410 );
00411
00412 timeRange_ = timeRange(t,t);
00413
00414 }
00415
00416
00417 template<class Scalar>
00418 Scalar ImplicitRKStepper<Scalar>::takeStep(Scalar dt, StepSizeType stepSizeType)
00419 {
00420
00421
00422 using Teuchos::as;
00423 using Teuchos::incrVerbLevel;
00424 typedef ScalarTraits<Scalar> ST;
00425 typedef Thyra::NonlinearSolverBase<Scalar> NSB;
00426 typedef Teuchos::VerboseObjectTempState<NSB> VOTSNSB;
00427
00428 RCP<FancyOStream> out = this->getOStream();
00429 Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00430 Teuchos::OSTab ostab(out,1,"BES::takeStep");
00431 VOTSNSB solver_outputTempState(solver_,out,incrVerbLevel(verbLevel,-1));
00432
00433 if ( !is_null(out) && as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW) ) {
00434 *out
00435 << "\nEntering " << Teuchos::TypeNameTraits<ImplicitRKStepper<Scalar> >::name()
00436 << "::takeStep("<<dt<<","<<toString(stepSizeType)<<") ...\n";
00437 }
00438
00439 if (!isInitialized_) {
00440 initialize_();
00441 }
00442
00443 TEST_FOR_EXCEPT( stepSizeType != STEP_TYPE_FIXED );
00444
00445
00446
00447
00448
00449 V_V( &*x_old_, *x_ );
00450 Scalar current_dt = dt;
00451 Scalar t = timeRange_.upper();
00452 irkModel_->setTimeStepPoint( x_old_, t, current_dt );
00453
00454
00455
00456
00457
00458 V_S( &*x_stage_bar_, ST::zero() );
00459
00460
00461 solver_->solve( &*x_stage_bar_ );
00462
00463
00464
00465
00466
00467
00468 assembleIRKSolution( irkButcherTableau_.b(), current_dt, *x_old_, *x_stage_bar_,
00469 outArg(*x_)
00470 );
00471
00472
00473 timeRange_ = timeRange(t,t+current_dt);
00474
00475 return current_dt;
00476
00477 }
00478
00479
00480 template<class Scalar>
00481 const StepStatus<Scalar> ImplicitRKStepper<Scalar>::getStepStatus() const
00482 {
00483 StepStatus<Scalar> stepStatus;
00484 TEST_FOR_EXCEPT(true);
00485 return(stepStatus);
00486 }
00487
00488
00489
00490
00491
00492 template<class Scalar>
00493 RCP<const Thyra::VectorSpaceBase<Scalar> >
00494 ImplicitRKStepper<Scalar>::get_x_space() const
00495 {
00496 return ( !is_null(model_) ? model_->get_x_space() : Teuchos::null );
00497 }
00498
00499
00500 template<class Scalar>
00501 void ImplicitRKStepper<Scalar>::addPoints(
00502 const Array<Scalar>& time_vec
00503 ,const Array<RCP<const Thyra::VectorBase<Scalar> > >& x_vec
00504 ,const Array<RCP<const Thyra::VectorBase<Scalar> > >& xdot_vec
00505 )
00506 {
00507 TEST_FOR_EXCEPT(true);
00508 }
00509
00510
00511 template<class Scalar>
00512 TimeRange<Scalar> ImplicitRKStepper<Scalar>::getTimeRange() const
00513 {
00514 return timeRange_;
00515 }
00516
00517
00518 template<class Scalar>
00519 void ImplicitRKStepper<Scalar>::getPoints(
00520 const Array<Scalar>& time_vec
00521 ,Array<RCP<const Thyra::VectorBase<Scalar> > >* x_vec
00522 ,Array<RCP<const Thyra::VectorBase<Scalar> > >* xdot_vec
00523 ,Array<ScalarMag>* accuracy_vec) const
00524 {
00525
00526 if (x_vec)
00527 x_vec->resize( time_vec.size() );
00528 if (xdot_vec)
00529 xdot_vec->resize( time_vec.size() );
00530 if (accuracy_vec)
00531 accuracy_vec->resize( time_vec.size() );
00532
00533
00534 if (time_vec.size() == 1 && compareTimeValues(timeRange_.upper(),time_vec[0])==0 ) {
00535 if (x_vec) {
00536 (*x_vec)[0] = x_;
00537 }
00538 TEST_FOR_EXCEPT( 0 != xdot_vec );
00539
00540 return;
00541 }
00542
00543 TEST_FOR_EXCEPT(true);
00544
00545 }
00546
00547
00548 template<class Scalar>
00549 void ImplicitRKStepper<Scalar>::getNodes(Array<Scalar>* time_vec) const
00550 {
00551 TEST_FOR_EXCEPT(true);
00552 }
00553
00554
00555 template<class Scalar>
00556 void ImplicitRKStepper<Scalar>::removeNodes(Array<Scalar>& time_vec)
00557 {
00558 TEST_FOR_EXCEPT(true);
00559 }
00560
00561
00562 template<class Scalar>
00563 int ImplicitRKStepper<Scalar>::getOrder() const
00564 {
00565 TEST_FOR_EXCEPT(true);
00566 return -1;
00567 }
00568
00569
00570
00571
00572
00573 template <class Scalar>
00574 void ImplicitRKStepper<Scalar>::setParameterList(
00575 RCP<ParameterList> const& paramList
00576 )
00577 {
00578 TEST_FOR_EXCEPT(is_null(paramList));
00579 paramList->validateParametersAndSetDefaults(*this->getValidParameters());
00580 paramList_ = paramList;
00581 numStages_ = paramList_->get("Num Stages",numStages_);
00582 Teuchos::readVerboseObjectSublist(&*paramList_,this);
00583 }
00584
00585
00586 template <class Scalar>
00587 RCP<ParameterList>
00588 ImplicitRKStepper<Scalar>::getNonconstParameterList()
00589 {
00590 return(paramList_);
00591 }
00592
00593
00594 template <class Scalar>
00595 RCP<ParameterList>
00596 ImplicitRKStepper<Scalar>::unsetParameterList()
00597 {
00598 RCP<ParameterList>
00599 temp_param_list = paramList_;
00600 paramList_ = Teuchos::null;
00601 return(temp_param_list);
00602 }
00603
00604
00605 template<class Scalar>
00606 RCP<const ParameterList>
00607 ImplicitRKStepper<Scalar>::getValidParameters() const
00608 {
00609 static RCP<const ParameterList> validPL;
00610 if (is_null(validPL)) {
00611 RCP<ParameterList> pl = Teuchos::parameterList();
00612 pl->set("Num Stages",1);
00613 Teuchos::setupVerboseObjectSublist(&*pl);
00614 validPL = pl;
00615 }
00616 return validPL;
00617 }
00618
00619
00620
00621
00622
00623 template<class Scalar>
00624 void ImplicitRKStepper<Scalar>::describe(
00625 FancyOStream &out,
00626 const Teuchos::EVerbosityLevel verbLevel
00627 ) const
00628 {
00629 using std::endl;
00630 using Teuchos::as;
00631 Teuchos::OSTab tab(out);
00632 if (!isInitialized_) {
00633 out << this->description() << " : This stepper is not initialized yet" << std::endl;
00634 return;
00635 }
00636 if (
00637 as<int>(verbLevel) == as<int>(Teuchos::VERB_DEFAULT)
00638 ||
00639 as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW)
00640 )
00641 {
00642 out << this->description() << ":" << endl;
00643 Teuchos::OSTab tab(out);
00644 out << "model = " << Teuchos::describe(*model_,verbLevel);
00645 out << "solver = " << Teuchos::describe(*solver_,verbLevel);
00646 out << "irk_W_factory = " << Teuchos::describe(*irk_W_factory_,verbLevel);
00647 }
00648 }
00649
00650
00651
00652
00653
00654 template <class Scalar>
00655 void ImplicitRKStepper<Scalar>::initialize_()
00656 {
00657
00658 typedef ScalarTraits<Scalar> ST;
00659 const Scalar one = ST::one();
00660 const Scalar zero = ST::zero();
00661 using Teuchos::rcp_dynamic_cast;
00662
00663 TEST_FOR_EXCEPT(model_ == Teuchos::null);
00664 TEST_FOR_EXCEPT(solver_ == Teuchos::null);
00665 TEST_FOR_EXCEPT(irk_W_factory_ == Teuchos::null);
00666
00667 if (is_null(x_)) {
00668
00669
00670
00671 this->setInitialCondition(model_->getNominalValues());
00672 }
00673
00674 if (is_null(x_dot_)) {
00675 x_dot_ = createMember(model_->get_x_space());
00676 V_S(&*x_dot_,ScalarTraits<Scalar>::zero());
00677 }
00678
00679 x_old_ = x_->clone_v();
00680
00681
00682
00683 Teuchos::SerialDenseMatrix<int,Scalar> A(numStages_,numStages_);
00684 Teuchos::SerialDenseVector<int,Scalar> b(numStages_);
00685 Teuchos::SerialDenseVector<int,Scalar> c(numStages_);
00686
00687
00688 TEUCHOS_ASSERT( numStages_ == 1 || numStages_ == 2 );
00689
00690 if (numStages_ == 1) {
00691
00692 A(0,0) = one;
00693
00694 b(0) = one;
00695
00696 c(0) = one;
00697
00698 }
00699 else if (numStages_ == 2) {
00700
00701 const Scalar half = 0.5 * one;
00702
00703 A(0,0) = half; A(0,1) = -half;
00704 A(1,0) = half; A(1,1) = half;
00705
00706 b(0) = half;
00707 b(1) = half;
00708
00709 c(0) = zero;
00710 c(1) = one;
00711
00712
00713 }
00714 else {
00715 TEST_FOR_EXCEPT(true);
00716 }
00717
00718 irkButcherTableau_ = RKButcherTableau<Scalar>(A,b,c);
00719
00720
00721
00722 irkModel_ = implicitRKModelEvaluator(
00723 model_,basePoint_,irk_W_factory_,irkButcherTableau_);
00724
00725 solver_->setModel(irkModel_);
00726
00727
00728 x_stage_bar_ = rcp_dynamic_cast<Thyra::ProductVectorBase<Scalar> >(
00729 createMember(irkModel_->get_x_space())
00730 );
00731
00732 isInitialized_ = true;
00733
00734 }
00735
00736
00737 }
00738
00739 #endif //Rythmos_IMPLICIT_RK_STEPPER_H