Rythmos_ExplicitTaylorPolynomialStepper.hpp

00001 //@HEADER
00002 // ***********************************************************************
00003 //
00004 //                           Rythmos Package
00005 //                 Copyright (2006) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Todd S. Coffey (tscoffe@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 //@HEADER
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, // Reduction object type
00052     RTOpPack::REDUCT_TYPE_MAX // Reduction object reduction
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       // If t_ > t_final_, we're done
00365       if (t_ > t_final_) {
00366         dt_ = Teuchos::ScalarTraits<Scalar>::zero();
00367         return dt_;
00368       }
00369 
00370       // Compute a local truncated Taylor series solution to system
00371       computeTaylorSeriesSolution_();
00372 
00373       // Estimate log of radius of convergence of Taylor series
00374       Scalar rho = estimateLogRadius_();
00375 
00376       // Set step size
00377       Scalar dt = std::exp(linc_ - rho);
00378 
00379       // If step size is too big, reduce
00380       if (dt > max_step_size_) {
00381         dt = max_step_size_;
00382       }
00383 
00384       // If step goes past t_final_, reduce
00385       if (t_+dt > t_final_) {
00386         dt = t_final_-t_;
00387       }
00388 
00389       ScalarMag local_error;
00390 
00391       do {
00392 
00393         // compute x(t_+dt), xdot(t_+dt)
00394         x_poly_->evaluate(dt, x_vector_.get(), x_dot_vector_.get());
00395 
00396         // compute f( x(t_+dt), t_+dt )
00397         Thyra::eval_f(*model_, *x_vector_, t_+dt, f_vector_.get());
00398 
00399         // compute || xdot(t_+dt) - f( x(t_+dt), t_+dt ) ||
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       // Check if minimum step size was reached
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       // Increment t_
00418       t_ += dt;
00419 
00420       dt_ = dt;
00421 
00422       return dt;
00423 
00424     } else {
00425 
00426       // If t_ > t_final_, we're done
00427       if (t_ > t_final_) {
00428         dt_ = Teuchos::ScalarTraits<Scalar>::zero();
00429         return dt_;
00430       }
00431 
00432       // Compute a local truncated Taylor series solution to system
00433       computeTaylorSeriesSolution_();
00434 
00435       // If step size is too big, reduce
00436       if (dt > max_step_size_) {
00437         dt = max_step_size_;
00438       }
00439 
00440       // If step goes past t_final_, reduce
00441       if (t_+dt > t_final_) {
00442         dt = t_final_-t_;
00443       }
00444 
00445       // compute x(t_+dt)
00446       x_poly_->evaluate(dt, x_vector_.get());
00447 
00448       // Increment t_
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     // Get initial time
00483     t_initial_ = parameterList_->get("Initial Time", ST::zero());
00484 
00485     // Get final time
00486     t_final_ = parameterList_->get("Final Time", ST::one());
00487 
00488     // Get local error tolerance
00489     local_error_tolerance_ = 
00490       parameterList_->get("Local Error Tolerance", ScalarMag(1.0e-10));
00491 
00492     // Get minimum step size
00493     min_step_size_ = parameterList_->get("Minimum Step Size", Scalar(1.0e-10));
00494 
00495     // Get maximum step size
00496     max_step_size_ = parameterList_->get("Maximum Step Size", Scalar(1.0));
00497 
00498     // Get degree_ of Taylor polynomial expansion
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   // Definitions of protected methods
00610   //
00611 
00612   template<class Scalar>
00613   void
00614   ExplicitTaylorPolynomialStepper<Scalar>::computeTaylorSeriesSolution_()
00615   {
00616     Teuchos::RCP<Thyra::VectorBase<Scalar> > tmp;
00617 
00618     // Set degree_ of polynomials to 0
00619     x_poly_->setDegree(0);
00620     f_poly_->setDegree(0);
00621 
00622     // Set degree_ 0 coefficient
00623     x_poly_->setCoefficient(0, *x_vector_);
00624 
00625     for (unsigned int k=1; k<=degree_; k++) {
00626 
00627       // compute [f] = f([x])
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       // x[k] = f[k-1] / k
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 } // namespace Rythmos
00663 
00664 #endif // RYTHMOS_EXPLICIT_TAYLOR_POLYNOMIAL_STEPPER_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends

Generated on Tue Oct 20 10:24:09 2009 for Rythmos - Transient Integration for Differential Equations by  doxygen 1.6.1