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_EXPLICIT_TAYLOR_POLYNOMIAL_STEPPER_H
00030 #define RYTHMOS_EXPLICIT_TAYLOR_POLYNOMIAL_STEPPER_H
00031
00032 #include "Rythmos_StepperBase.hpp"
00033 #include "Teuchos_RCP.hpp"
00034 #include "Teuchos_ParameterList.hpp"
00035 #include "Thyra_VectorBase.hpp"
00036 #include "Thyra_ModelEvaluator.hpp"
00037 #include "Thyra_ModelEvaluatorHelpers.hpp"
00038 #include "RTOpPack_RTOpTHelpers.hpp"
00039
00040 namespace Rythmos {
00041
00043
00050 RTOP_ROP_1_REDUCT_SCALAR( ROpLogNormInf,
00051 typename ScalarTraits<Scalar>::magnitudeType,
00052 RTOpPack::REDUCT_TYPE_MAX
00053 )
00054 {
00055 using Teuchos::as;
00056 typedef ScalarTraits<Scalar> ST;
00057 typedef typename ST::magnitudeType ScalarMag;
00058 const ScalarMag mag = std::log(as<ScalarMag>(1e-100) + ST::magnitude(v0));
00059 reduct = TEUCHOS_MAX( mag, reduct );
00060 }
00061
00159 template<class Scalar>
00160 class ExplicitTaylorPolynomialStepper : virtual public StepperBase<Scalar>
00161 {
00162 public:
00163
00165 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType ScalarMag;
00166
00168 ExplicitTaylorPolynomialStepper();
00169
00171 ~ExplicitTaylorPolynomialStepper();
00172
00174 RCP<const Thyra::VectorSpaceBase<Scalar> > get_x_space() const;
00175
00177 void setModel(const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > &model);
00178
00180 Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >
00181 getModel() const;
00182
00184 Scalar takeStep(Scalar dt, StepSizeType flag);
00185
00187 const StepStatus<Scalar> getStepStatus() const;
00188
00190
00191 void setParameterList(Teuchos::RCP<Teuchos::ParameterList> const& paramList);
00192
00194 Teuchos::RCP<Teuchos::ParameterList> getNonconstParameterList();
00195
00197 Teuchos::RCP<Teuchos::ParameterList> unsetParameterList();
00198
00200 std::string description() const;
00201
00203 std::ostream& describe(
00204 std::ostream &out
00205 ,const Teuchos::EVerbosityLevel verbLevel
00206 ,const std::string leadingIndent
00207 ,const std::string indentSpacer
00208 ) const;
00209
00212 void addPoints(
00213 const Array<Scalar>& time_vec
00214 ,const Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x_vec
00215 ,const Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& xdot_vec
00216 );
00217
00219 void getPoints(
00220 const Array<Scalar>& time_vec
00221 ,Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >* x_vec
00222 ,Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >* xdot_vec
00223 ,Array<ScalarMag>* accuracy_vec) const;
00224
00226 void setRange(
00227 const TimeRange<Scalar>& range,
00228 const InterpolationBufferBase<Scalar> & IB
00229 );
00230
00232 TimeRange<Scalar> getTimeRange() const;
00233
00235 void getNodes(Array<Scalar>* time_vec) const;
00236
00238 void removeNodes(Array<Scalar>& time_vec);
00239
00241 int getOrder() const;
00242
00243 private:
00244
00246 void computeTaylorSeriesSolution_();
00247
00252 ScalarMag estimateLogRadius_();
00253
00255 Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > model_;
00256
00258 Teuchos::RCP<Teuchos::ParameterList> parameterList_;
00259
00261 Teuchos::RCP<Thyra::VectorBase<Scalar> > x_vector_;
00262
00264 Teuchos::RCP<Thyra::VectorBase<Scalar> > x_dot_vector_;
00265
00267 Teuchos::RCP<Thyra::VectorBase<Scalar> > f_vector_;
00268
00270 Teuchos::RCP<Teuchos::Polynomial<Thyra::VectorBase<Scalar> > > x_poly_;
00271
00273 Teuchos::RCP<Teuchos::Polynomial<Thyra::VectorBase<Scalar> > > f_poly_;
00274
00276 Scalar t_;
00277
00279 Scalar dt_;
00280
00282 Scalar t_initial_;
00283
00285 Scalar t_final_;
00286
00288 ScalarMag local_error_tolerance_;
00289
00291 Scalar min_step_size_;
00292
00294 Scalar max_step_size_;
00295
00297 unsigned int degree_;
00298
00300 Scalar linc_;
00301 };
00302
00304 template <typename Scalar>
00305 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
00306 log_norm_inf(const Thyra::VectorBase<Scalar>& x)
00307 {
00308 ROpLogNormInf<Scalar> log_norm_inf_op;
00309 Teuchos::RCP<RTOpPack::ReductTarget> log_norm_inf_targ =
00310 log_norm_inf_op.reduct_obj_create();
00311 const Thyra::VectorBase<Scalar>* vecs[] = { &x };
00312 Thyra::applyOp<Scalar>(log_norm_inf_op,1,vecs,0,
00313 (Thyra::VectorBase<Scalar>**)NULL,
00314 log_norm_inf_targ.get());
00315
00316 return log_norm_inf_op(*log_norm_inf_targ);
00317 }
00318
00319 template<class Scalar>
00320 ExplicitTaylorPolynomialStepper<Scalar>::ExplicitTaylorPolynomialStepper()
00321 {
00322 }
00323
00324 template<class Scalar>
00325 ExplicitTaylorPolynomialStepper<Scalar>::~ExplicitTaylorPolynomialStepper()
00326 {
00327 }
00328
00329 template<class Scalar>
00330 void ExplicitTaylorPolynomialStepper<Scalar>::setModel(
00331 const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > &model
00332 )
00333 {
00334 TEST_FOR_EXCEPT(model == Teuchos::null)
00335
00336 model_ = model;
00337 x_vector_ = model_->getNominalValues().get_x()->clone_v();
00338 x_dot_vector_ = Thyra::createMember(model_->get_x_space());
00339 f_vector_ = Thyra::createMember(model_->get_f_space());
00340 }
00341
00342
00343 template<class Scalar>
00344 Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >
00345 ExplicitTaylorPolynomialStepper<Scalar>::getModel() const
00346 {
00347 return model_;
00348 }
00349
00350 template<class Scalar>
00351 Scalar
00352 ExplicitTaylorPolynomialStepper<Scalar>::takeStep(Scalar dt, StepSizeType flag)
00353 {
00354 if (x_poly_ == Teuchos::null)
00355 x_poly_ =
00356 Teuchos::rcp(new Teuchos::Polynomial<
00357 Thyra::VectorBase<Scalar> >(0,*x_vector_,degree_));
00358
00359 if (f_poly_ == Teuchos::null)
00360 f_poly_ =
00361 Teuchos::rcp(new Teuchos::Polynomial<
00362 Thyra::VectorBase<Scalar> >(0, *f_vector_, degree_));
00363 if (flag == STEP_TYPE_VARIABLE) {
00364
00365 if (t_ > t_final_) {
00366 dt_ = Teuchos::ScalarTraits<Scalar>::zero();
00367 return dt_;
00368 }
00369
00370
00371 computeTaylorSeriesSolution_();
00372
00373
00374 Scalar rho = estimateLogRadius_();
00375
00376
00377 Scalar dt = std::exp(linc_ - rho);
00378
00379
00380 if (dt > max_step_size_) {
00381 dt = max_step_size_;
00382 }
00383
00384
00385 if (t_+dt > t_final_) {
00386 dt = t_final_-t_;
00387 }
00388
00389 ScalarMag local_error;
00390
00391 do {
00392
00393
00394 x_poly_->evaluate(dt, x_vector_.get(), x_dot_vector_.get());
00395
00396
00397 Thyra::eval_f(*model_, *x_vector_, t_+dt, f_vector_.get());
00398
00399
00400 Thyra::Vp_StV(x_dot_vector_.get(), -Teuchos::ScalarTraits<Scalar>::one(),
00401 *f_vector_);
00402 local_error = norm_inf(*x_dot_vector_);
00403
00404 if (local_error > local_error_tolerance_) {
00405 dt *= 0.7;
00406 }
00407
00408 } while (local_error > local_error_tolerance_ && dt > min_step_size_);
00409
00410
00411 TEST_FOR_EXCEPTION(dt < min_step_size_,
00412 std::runtime_error,
00413 "ExplicitTaylorPolynomialStepper<Scalar>::takeStep(): "
00414 << "Step size reached minimum step size "
00415 << min_step_size_ << ". Failing step." );
00416
00417
00418 t_ += dt;
00419
00420 dt_ = dt;
00421
00422 return dt;
00423
00424 } else {
00425
00426
00427 if (t_ > t_final_) {
00428 dt_ = Teuchos::ScalarTraits<Scalar>::zero();
00429 return dt_;
00430 }
00431
00432
00433 computeTaylorSeriesSolution_();
00434
00435
00436 if (dt > max_step_size_) {
00437 dt = max_step_size_;
00438 }
00439
00440
00441 if (t_+dt > t_final_) {
00442 dt = t_final_-t_;
00443 }
00444
00445
00446 x_poly_->evaluate(dt, x_vector_.get());
00447
00448
00449 t_ += dt;
00450
00451 dt_ = dt;
00452
00453 return dt;
00454 }
00455 }
00456
00457
00458 template<class Scalar>
00459 const StepStatus<Scalar>
00460 ExplicitTaylorPolynomialStepper<Scalar>::getStepStatus() const
00461 {
00462 typedef Teuchos::ScalarTraits<Scalar> ST;
00463 StepStatus<Scalar> stepStatus;
00464
00465 stepStatus.stepSize = dt_;
00466 stepStatus.order = this->getOrder();
00467 stepStatus.time = t_;
00468 stepStatus.solution = x_vector_;
00469 stepStatus.solutionDot = x_dot_vector_;
00470 stepStatus.residual = f_vector_;
00471
00472 return(stepStatus);
00473 }
00474
00475 template<class Scalar>
00476 void ExplicitTaylorPolynomialStepper<Scalar>::setParameterList(Teuchos::RCP<Teuchos::ParameterList> const& paramList)
00477 {
00478 typedef Teuchos::ScalarTraits<Scalar> ST;
00479
00480 parameterList_ = paramList;
00481
00482
00483 t_initial_ = parameterList_->get("Initial Time", ST::zero());
00484
00485
00486 t_final_ = parameterList_->get("Final Time", ST::one());
00487
00488
00489 local_error_tolerance_ =
00490 parameterList_->get("Local Error Tolerance", ScalarMag(1.0e-10));
00491
00492
00493 min_step_size_ = parameterList_->get("Minimum Step Size", Scalar(1.0e-10));
00494
00495
00496 max_step_size_ = parameterList_->get("Maximum Step Size", Scalar(1.0));
00497
00498
00499 degree_ = parameterList_->get("Taylor Polynomial Degree", 40);
00500
00501 linc_ = Scalar(-16.0*std::log(10.0)/degree_);
00502 t_ = t_initial_;
00503 }
00504
00505 template<class Scalar>
00506 Teuchos::RCP<Teuchos::ParameterList>
00507 ExplicitTaylorPolynomialStepper<Scalar>::getNonconstParameterList()
00508 {
00509 return parameterList_;
00510 }
00511
00512 template<class Scalar>
00513 Teuchos::RCP<Teuchos::ParameterList>
00514 ExplicitTaylorPolynomialStepper<Scalar>:: unsetParameterList()
00515 {
00516 Teuchos::RCP<Teuchos::ParameterList> temp_param_list = parameterList_;
00517 parameterList_ = Teuchos::null;
00518 return temp_param_list;
00519 }
00520
00521 template<class Scalar>
00522 std::string ExplicitTaylorPolynomialStepper<Scalar>::description() const
00523 {
00524 std::string name = "Rythmos::ExplicitTaylorPolynomialStepper";
00525 return name;
00526 }
00527
00528 template<class Scalar>
00529 std::ostream& ExplicitTaylorPolynomialStepper<Scalar>::describe(
00530 std::ostream &out
00531 ,const Teuchos::EVerbosityLevel verbLevel
00532 ,const std::string leadingIndent
00533 ,const std::string indentSpacer
00534 ) const
00535 {
00536 if (verbLevel == Teuchos::VERB_EXTREME) {
00537 out << description() << "::describe" << std::endl;
00538 out << "model_ = " << std::endl;
00539 out << model_->describe(out,verbLevel,leadingIndent,indentSpacer) << std::endl;
00540 out << "x_vector_ = " << std::endl;
00541 out << x_vector_->describe(out,verbLevel,leadingIndent,indentSpacer) << std::endl;
00542 out << "x_dot_vector_ = " << std::endl;
00543 out << x_dot_vector_->describe(out,verbLevel,leadingIndent,indentSpacer) << std::endl;
00544 out << "f_vector_ = " << std::endl;
00545 out << f_vector_->describe(out,verbLevel,leadingIndent,indentSpacer) << std::endl;
00546 out << "x_poly_ = " << std::endl;
00547 out << x_poly_->describe(out,verbLevel,leadingIndent,indentSpacer) << std::endl;
00548 out << "f_poly_ = " << std::endl;
00549 out << f_poly_->describe(out,verbLevel,leadingIndent,indentSpacer) << std::endl;
00550 out << "t_ = " << t_ << std::endl;
00551 out << "t_initial_ = " << t_initial_ << std::endl;
00552 out << "t_final_ = " << t_final_ << std::endl;
00553 out << "local_error_tolerance_ = " << local_error_tolerance_ << std::endl;
00554 out << "min_step_size_ = " << min_step_size_ << std::endl;
00555 out << "max_step_size_ = " << max_step_size_ << std::endl;
00556 out << "degree_ = " << degree_ << std::endl;
00557 out << "linc_ = " << linc_ << std::endl;
00558 }
00559 return(out);
00560 }
00561
00562
00563 template<class Scalar>
00564 void ExplicitTaylorPolynomialStepper<Scalar>::addPoints(
00565 const Array<Scalar>& time_vec
00566 ,const Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x_vec
00567 ,const Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& xdot_vec
00568 )
00569 {
00570 TEST_FOR_EXCEPTION(true,std::logic_error,"Error, addPoints is not implemented for the ExplicitTaylorPolynomialStepper.\n");
00571 }
00572
00573 template<class Scalar>
00574 void ExplicitTaylorPolynomialStepper<Scalar>::getPoints(
00575 const Array<Scalar>& time_vec
00576 ,Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >* x_vec
00577 ,Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >* xdot_vec
00578 ,Array<ScalarMag>* accuracy_vec) const
00579 {
00580 TEST_FOR_EXCEPTION(true,std::logic_error,"Error, getPoints is not implemented for the ExplicitTaylorPolynomialStepper.\n");
00581 }
00582
00583 template<class Scalar>
00584 TimeRange<Scalar> ExplicitTaylorPolynomialStepper<Scalar>::getTimeRange() const
00585 {
00586 return invalidTimeRange<Scalar>();
00587 }
00588
00589 template<class Scalar>
00590 void ExplicitTaylorPolynomialStepper<Scalar>::getNodes(Array<Scalar>* time_list) const
00591 {
00592 TEST_FOR_EXCEPTION(true,std::logic_error,"Error, getNodes is not implemented for the ExplicitTaylorPolynomialStepper.\n");
00593 }
00594
00595 template<class Scalar>
00596 void ExplicitTaylorPolynomialStepper<Scalar>::removeNodes(Array<Scalar>& time_vec)
00597 {
00598 TEST_FOR_EXCEPTION(true,std::logic_error,"Error, removeNodes is not implemented for the ExplicitTaylorPolynomialStepper.\n");
00599 }
00600
00601
00602 template<class Scalar>
00603 int ExplicitTaylorPolynomialStepper<Scalar>::getOrder() const
00604 {
00605 return degree_;
00606 }
00607
00608
00609
00610
00611
00612 template<class Scalar>
00613 void
00614 ExplicitTaylorPolynomialStepper<Scalar>::computeTaylorSeriesSolution_()
00615 {
00616 Teuchos::RCP<Thyra::VectorBase<Scalar> > tmp;
00617
00618
00619 x_poly_->setDegree(0);
00620 f_poly_->setDegree(0);
00621
00622
00623 x_poly_->setCoefficient(0, *x_vector_);
00624
00625 for (unsigned int k=1; k<=degree_; k++) {
00626
00627
00628 Thyra::eval_f_poly(*model_, *x_poly_, t_, f_poly_.get());
00629
00630 x_poly_->setDegree(k);
00631 f_poly_->setDegree(k);
00632
00633
00634 tmp = x_poly_->getCoefficient(k);
00635 copy(*(f_poly_->getCoefficient(k-1)), tmp.get());
00636 scale(Scalar(1.0)/Scalar(k), tmp.get());
00637 }
00638
00639 }
00640
00641 template<class Scalar>
00642 typename ExplicitTaylorPolynomialStepper<Scalar>::ScalarMag
00643 ExplicitTaylorPolynomialStepper<Scalar>::estimateLogRadius_()
00644 {
00645 ScalarMag rho = 0;
00646 ScalarMag tmp;
00647 for (unsigned int k=degree_/2; k<=degree_; k++) {
00648 tmp = log_norm_inf(*(x_poly_->getCoefficient(k))) / k;
00649 if (tmp > rho) {
00650 rho = tmp;
00651 }
00652 }
00653 return rho;
00654 }
00655
00656 template<class Scalar>
00657 RCP<const Thyra::VectorSpaceBase<Scalar> > ExplicitTaylorPolynomialStepper<Scalar>::get_x_space() const
00658 {
00659 return(x_vector_->space());
00660 }
00661
00662 }
00663
00664 #endif // RYTHMOS_EXPLICIT_TAYLOR_POLYNOMIAL_STEPPER_H