Rythmos_BackwardEulerStepper.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_BACKWARD_EULER_STEPPER_H
00030 #define Rythmos_BACKWARD_EULER_STEPPER_H
00031 
00032 #include "Rythmos_StepperBase.hpp"
00033 #include "Rythmos_DataStore.hpp"
00034 #include "Rythmos_LinearInterpolator.hpp"
00035 #include "Rythmos_SingleResidualModelEvaluator.hpp"
00036 #include "Rythmos_SolverAcceptingStepperBase.hpp"
00037 #include "Rythmos_StepperHelpers.hpp"
00038 
00039 #include "Thyra_VectorBase.hpp"
00040 #include "Thyra_ModelEvaluator.hpp"
00041 #include "Thyra_ModelEvaluatorHelpers.hpp"
00042 #include "Thyra_AssertOp.hpp"
00043 #include "Thyra_NonlinearSolverBase.hpp"
00044 #include "Thyra_TestingTools.hpp"
00045 
00046 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
00047 #include "Teuchos_as.hpp"
00048 
00049 
00050 namespace Rythmos {
00051 
00052 
00063 template<class Scalar>
00064 class BackwardEulerStepper : virtual public SolverAcceptingStepperBase<Scalar>
00065 {
00066 public:
00067   
00069   typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType ScalarMag;
00070   
00073 
00075   BackwardEulerStepper();
00076   
00078   BackwardEulerStepper(
00079     const RCP<const Thyra::ModelEvaluator<Scalar> > &model,
00080     const RCP<Thyra::NonlinearSolverBase<Scalar> > &solver
00081     );
00082   
00084   void setInterpolator(RCP<InterpolatorBase<Scalar> > interpolator);
00085   
00087   RCP<InterpolatorBase<Scalar> > unsetInterpolator();
00088 
00090 
00093 
00095   void setSolver(
00096     const RCP<Thyra::NonlinearSolverBase<Scalar> > &solver
00097     );
00098 
00100   RCP<Thyra::NonlinearSolverBase<Scalar> >
00101   getNonconstSolver();
00102 
00104   RCP<const Thyra::NonlinearSolverBase<Scalar> >
00105   getSolver() const;
00106 
00108 
00111  
00113   bool supportsCloning() const;
00114 
00122   RCP<StepperBase<Scalar> > cloneStepperAlgorithm() const;
00123 
00125   void setModel(const RCP<const Thyra::ModelEvaluator<Scalar> > &model);
00126   
00128   RCP<const Thyra::ModelEvaluator<Scalar> >
00129   getModel() const;
00130 
00132   void setInitialCondition(
00133     const Thyra::ModelEvaluatorBase::InArgs<Scalar> &initialCondition
00134     );
00135 
00137   Scalar takeStep(Scalar dt, StepSizeType flag);
00138   
00140   const StepStatus<Scalar> getStepStatus() const;
00141   
00143 
00146 
00148   RCP<const Thyra::VectorSpaceBase<Scalar> >
00149   get_x_space() const;
00150 
00152   void addPoints(
00153     const Array<Scalar>& time_vec,
00154     const Array<RCP<const Thyra::VectorBase<Scalar> > >& x_vec,
00155     const Array<RCP<const Thyra::VectorBase<Scalar> > >& xdot_vec
00156     );
00157   
00159   TimeRange<Scalar> getTimeRange() const;
00160   
00162   void getPoints(
00163     const Array<Scalar>& time_vec,
00164     Array<RCP<const Thyra::VectorBase<Scalar> > >* x_vec,
00165     Array<RCP<const Thyra::VectorBase<Scalar> > >* xdot_vec,
00166     Array<ScalarMag>* accuracy_vec
00167     ) const;
00168   
00170   void getNodes(Array<Scalar>* time_vec) const;
00171   
00173   void removeNodes(Array<Scalar>& time_vec);
00174 
00176   int getOrder() const;
00177 
00179   
00182 
00184   void setParameterList(RCP<Teuchos::ParameterList> const& paramList);
00185   
00187   RCP<Teuchos::ParameterList> getNonconstParameterList();
00188   
00190   RCP<Teuchos::ParameterList> unsetParameterList();
00191   
00193   RCP<const Teuchos::ParameterList> getValidParameters() const;
00194  
00196 
00199   
00201   void describe(
00202     Teuchos::FancyOStream  &out,
00203     const Teuchos::EVerbosityLevel verbLevel
00204     ) const;
00205 
00207 
00208 private:
00209 
00210   // ///////////////////////
00211   // Private date members
00212 
00213   bool isInitialized_;
00214   bool haveInitialCondition_;
00215   RCP<const Thyra::ModelEvaluator<Scalar> > model_;
00216   RCP<Thyra::NonlinearSolverBase<Scalar> > solver_;
00217   RCP<Thyra::VectorBase<Scalar> > scaled_x_old_;
00218   RCP<Thyra::VectorBase<Scalar> > x_dot_old_;
00219 
00220   Thyra::ModelEvaluatorBase::InArgs<Scalar> basePoint_;
00221   RCP<Thyra::VectorBase<Scalar> > x_;
00222   RCP<Thyra::VectorBase<Scalar> > x_dot_;
00223   Scalar t_;
00224   Scalar t_old_;
00225 
00226   Scalar dt_;
00227   int numSteps_;
00228 
00229   RCP<Rythmos::SingleResidualModelEvaluator<Scalar> >  neModel_;
00230 
00231   RCP<Teuchos::ParameterList> parameterList_;
00232 
00233   RCP<InterpolatorBase<Scalar> > interpolator_;
00234 
00235 
00236   // //////////////////////////
00237   // Private member functions
00238 
00239   void initialize();
00240 
00241 };
00242 
00243 
00248 template<class Scalar>
00249 RCP<BackwardEulerStepper<Scalar> >
00250 backwardEulerStepper(
00251   const RCP<const Thyra::ModelEvaluator<Scalar> > &model,
00252   const RCP<Thyra::NonlinearSolverBase<Scalar> > &solver
00253   )
00254 {
00255   return Teuchos::rcp(new BackwardEulerStepper<Scalar>(model, solver));
00256 }
00257 
00258 
00259 // ////////////////////////////
00260 // Defintions
00261 
00262 
00263 // Constructors, intializers, Misc.
00264 
00265 
00266 template<class Scalar>
00267 BackwardEulerStepper<Scalar>::BackwardEulerStepper()
00268   :isInitialized_(false),
00269    haveInitialCondition_(false),
00270    t_(-1.0),
00271    t_old_(0.0),
00272    dt_(0.0),
00273    numSteps_(0)
00274 {}
00275 
00276 
00277 template<class Scalar>
00278 BackwardEulerStepper<Scalar>::BackwardEulerStepper(
00279   const RCP<const Thyra::ModelEvaluator<Scalar> > &model,
00280   const RCP<Thyra::NonlinearSolverBase<Scalar> > &solver
00281   )
00282   :isInitialized_(false),
00283    haveInitialCondition_(false),
00284    t_(-1.0),
00285    t_old_(0.0),
00286    dt_(0.0),
00287    numSteps_(0)
00288 {
00289   setModel(model);
00290   setSolver(solver);
00291 }
00292 
00293 
00294 template<class Scalar>
00295 void BackwardEulerStepper<Scalar>::setInterpolator(
00296   RCP<InterpolatorBase<Scalar> > interpolator
00297   )
00298 {
00299 #ifdef TEUCHOS_DEBUG
00300   TEST_FOR_EXCEPT(is_null(interpolator));
00301 #endif
00302   interpolator_ = interpolator;
00303   isInitialized_ = false;
00304 }
00305 
00306 
00307 template<class Scalar>
00308 RCP<InterpolatorBase<Scalar> >
00309 BackwardEulerStepper<Scalar>::unsetInterpolator()
00310 {
00311   RCP<InterpolatorBase<Scalar> > temp_interpolator = interpolator_;
00312   interpolator_ = Teuchos::null;
00313   return(temp_interpolator);
00314   isInitialized_ = false;
00315 }
00316 
00317 
00318 // Overridden from SolverAcceptingStepperBase
00319 
00320 
00321 template<class Scalar>
00322 void BackwardEulerStepper<Scalar>::setSolver(
00323   const RCP<Thyra::NonlinearSolverBase<Scalar> > &solver
00324   )
00325 {
00326   using Teuchos::as;
00327 
00328   TEST_FOR_EXCEPT(solver == Teuchos::null)
00329 
00330   RCP<Teuchos::FancyOStream> out = this->getOStream();
00331   Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00332   Teuchos::OSTab ostab(out,1,"BES::setSolver");
00333   if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00334     *out << "solver = " << solver->description() << std::endl;
00335   }
00336 
00337   solver_ = solver;
00338 
00339   isInitialized_ = false;
00340 
00341 }
00342 
00343 
00344 template<class Scalar>
00345 RCP<Thyra::NonlinearSolverBase<Scalar> >
00346 BackwardEulerStepper<Scalar>::getNonconstSolver()
00347 {
00348   return solver_;
00349 }
00350 
00351 
00352 template<class Scalar>
00353 RCP<const Thyra::NonlinearSolverBase<Scalar> >
00354 BackwardEulerStepper<Scalar>::getSolver() const
00355 {
00356   return solver_;
00357 }
00358 
00359 
00360 // Overridden from StepperBase
00361  
00362 
00363 template<class Scalar>
00364 bool BackwardEulerStepper<Scalar>::supportsCloning() const
00365 {
00366   return true;
00367 }
00368 
00369 
00370 template<class Scalar>
00371 RCP<StepperBase<Scalar> >
00372 BackwardEulerStepper<Scalar>::cloneStepperAlgorithm() const
00373 {
00374   RCP<BackwardEulerStepper<Scalar> >
00375     stepper = Teuchos::rcp(new BackwardEulerStepper<Scalar>);
00376   stepper->isInitialized_ = isInitialized_;
00377   stepper->model_ = model_; // Model is stateless so shallow copy is okay!
00378   if (!is_null(solver_))
00379     stepper->solver_ = solver_->cloneNonlinearSolver().assert_not_null();
00380   if (!is_null(x_))
00381     stepper->x_ = x_->clone_v().assert_not_null();
00382   if (!is_null(scaled_x_old_))
00383     stepper->scaled_x_old_ = scaled_x_old_->clone_v().assert_not_null();
00384   stepper->t_ = t_;
00385   stepper->t_old_ = t_old_;
00386   stepper->dt_ = dt_;
00387   stepper->numSteps_ = numSteps_;
00388   if (!is_null(neModel_))
00389     stepper->neModel_
00390     = Teuchos::rcp(new Rythmos::SingleResidualModelEvaluator<Scalar>);
00391   if (!is_null(parameterList_))
00392     stepper->parameterList_ = parameterList(*parameterList_);
00393   if (!is_null(interpolator_))
00394     stepper->interpolator_
00395       = interpolator_->cloneInterpolator().assert_not_null(); // ToDo: Implement cloneInterpolator()
00396   return stepper;
00397 }
00398 
00399 
00400 template<class Scalar>
00401 void BackwardEulerStepper<Scalar>::setModel(
00402   const RCP<const Thyra::ModelEvaluator<Scalar> > &model
00403   )
00404 {
00405 
00406   using Teuchos::as;
00407 
00408   TEST_FOR_EXCEPT( is_null(model) );
00409   assertValidModel( *this, *model );
00410 
00411   RCP<Teuchos::FancyOStream> out = this->getOStream();
00412   Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00413   Teuchos::OSTab ostab(out,1,"BES::setModel");
00414   if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00415     *out << "model = " << model->description() << std::endl;
00416   }
00417   model_ = model;
00418 
00419   // Wipe out x.  This will either be set thorugh setInitialCondition(...) or
00420   // it will be taken from the model's nominal vlaues!
00421   x_ = Teuchos::null;
00422   scaled_x_old_ = Teuchos::null;
00423   x_dot_ = Teuchos::null;
00424   x_dot_old_ = Teuchos::null;
00425 
00426   isInitialized_ = false;
00427   haveInitialCondition_ = setDefaultInitialConditionFromNominalValues<Scalar>(
00428     *model_, Teuchos::ptr(this) );
00429   
00430 }
00431 
00432 
00433 template<class Scalar>
00434 RCP<const Thyra::ModelEvaluator<Scalar> >
00435 BackwardEulerStepper<Scalar>::getModel() const
00436 {
00437   return model_;
00438 }
00439 
00440 
00441 template<class Scalar>
00442 void BackwardEulerStepper<Scalar>::setInitialCondition(
00443   const Thyra::ModelEvaluatorBase::InArgs<Scalar> &initialCondition
00444   )
00445 {
00446 
00447   typedef Teuchos::ScalarTraits<Scalar> ST;
00448   typedef Thyra::ModelEvaluatorBase MEB;
00449 
00450   TEST_FOR_EXCEPT( is_null(model_) );
00451 
00452   basePoint_ = initialCondition;
00453 
00454   // x
00455 
00456   RCP<const Thyra::VectorBase<Scalar> >
00457     x_init = initialCondition.get_x();
00458 
00459 #ifdef TEUCHOS_DEBUG
00460   TEST_FOR_EXCEPTION(
00461     is_null(x_init), std::logic_error,
00462     "Error, if the client passes in an intial condition to setInitialCondition(...),\n"
00463     "then x can not be null!" );
00464   THYRA_ASSERT_VEC_SPACES(
00465     "Rythmos::BackwardEulerStepper::setInitialCondition(...)",
00466     *x_init->space(), *model_->get_x_space() );
00467 #endif
00468 
00469   x_ = x_init->clone_v();
00470 
00471   // x_dot
00472 
00473   x_dot_ = createMember(model_->get_x_space());
00474 
00475   RCP<const Thyra::VectorBase<Scalar> >
00476     x_dot_init = initialCondition.get_x_dot();
00477 
00478   if (!is_null(x_dot_init))
00479     assign(&*x_dot_,*x_dot_init);
00480   else
00481     assign(&*x_dot_,ST::zero());
00482   
00483   // t
00484   
00485   t_ = initialCondition.get_t();
00486 
00487   t_old_ = t_;
00488 
00489   haveInitialCondition_ = true;
00490 
00491 }
00492 
00493 
00494 template<class Scalar>
00495 Scalar BackwardEulerStepper<Scalar>::takeStep(Scalar dt, StepSizeType stepSizeType)
00496 {
00497 
00498   using Teuchos::as;
00499   using Teuchos::incrVerbLevel;
00500   typedef Teuchos::ScalarTraits<Scalar> ST;
00501   typedef Thyra::NonlinearSolverBase<Scalar> NSB;
00502   typedef Teuchos::VerboseObjectTempState<NSB> VOTSNSB;
00503 
00504   initialize();
00505 
00506   RCP<Teuchos::FancyOStream> out = this->getOStream();
00507   Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00508   Teuchos::OSTab ostab(out,1,"BES::takeStep");
00509   VOTSNSB solver_outputTempState(solver_,out,incrVerbLevel(verbLevel,-1));
00510 
00511   if ( !is_null(out) && as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW) ) {
00512     *out
00513       << "\nEntering " << Teuchos::TypeNameTraits<BackwardEulerStepper<Scalar> >::name()
00514       << "::takeStep("<<dt<<","<<toString(stepSizeType)<<") ...\n"; 
00515   }
00516 
00517   dt_ = dt;
00518 
00519   if ((stepSizeType == STEP_TYPE_VARIABLE) || (dt == ST::zero())) {
00520     if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW) )
00521       *out << "\nThe arguments to takeStep are not valid for BackwardEulerStepper at this time." << std::endl;
00522     // print something out about this method not supporting automatic variable step-size
00523     return(Scalar(-ST::one()));
00524   }
00525   if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00526     *out << "\ndt = " << dt << std::endl;
00527   }
00528 
00529 
00530   //
00531   // Setup the nonlinear equations:
00532   //
00533   //   f( (1/dt)* x + (-1/dt)*x_old), x, t ) = 0
00534   //
00535 
00536   V_StV( &*scaled_x_old_, Scalar(-ST::one()/dt), *x_ );
00537   t_old_ = t_;
00538   if(!neModel_.get()) {
00539     neModel_ = Teuchos::rcp(new Rythmos::SingleResidualModelEvaluator<Scalar>());
00540   }
00541   neModel_->initializeSingleResidualModel(
00542     model_, basePoint_,
00543     Scalar(ST::one()/dt), scaled_x_old_,
00544     ST::one(), Teuchos::null,
00545     t_old_+dt,
00546     Teuchos::null
00547     );
00548   if( solver_->getModel().get() != neModel_.get() ) {
00549     solver_->setModel(neModel_);
00550   }
00551   // 2007/05/18: rabartl: ToDo: Above, set the stream and the verbosity level
00552   // on solver_ so that we an see what it is doing!
00553 
00554   //
00555   // Solve the implicit nonlinear system to a tolerance of ???
00556   //
00557   
00558   if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW) ) {
00559     *out << "\nSolving the implicit backward-Euler timestep equation ...\n";
00560   }
00561 
00562   Thyra::SolveStatus<Scalar>
00563     neSolveStatus = solver_->solve(&*x_);
00564 
00565   // In the above solve, on input *x_ is the old value of x for the previous
00566   // time step which is used as the initial guess for the solver.  On output,
00567   // *x_ is the converged timestep solution.
00568  
00569   if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW) ) {
00570     *out << "\nOutput status of nonlinear solve:\n" << neSolveStatus;
00571   }
00572 
00573   // 2007/05/18: rabartl: ToDo: Above, get the solve status from the above
00574   // solve and at least print warning message if the solve fails!  Actually,
00575   // you should most likely thrown an exception if the solve fails or return
00576   // false if appropriate
00577 
00578   //
00579   // Update the step
00580   //
00581 
00582   assign( &*x_dot_old_, *x_dot_ );
00583 
00584   // x_dot = (1/dt)*x - (1/dt)*x_old 
00585   V_StV( &*x_dot_, Scalar(ST::one()/dt), *x_ );
00586   Vp_StV( &*x_dot_, Scalar(ST::one()), *scaled_x_old_ );
00587 
00588   t_ += dt;
00589 
00590   numSteps_++;
00591 
00592   if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00593     *out << "\nt_old_ = " << t_old_ << std::endl;
00594     *out << "\nt_ = " << t_ << std::endl;
00595   }
00596 
00597 #ifdef TEUCHOS_DEBUG
00598 
00599   if ( includesVerbLevel(verbLevel,Teuchos::VERB_LOW) )
00600     *out << "\nChecking to make sure that solution and the interpolated solution are the same! ...\n";
00601 
00602   {
00603 
00604     typedef ScalarTraits<Scalar> ST;
00605     typedef typename ST::magnitudeType ScalarMag;
00606     typedef ScalarTraits<ScalarMag> SMT;
00607     
00608     Teuchos::OSTab tab(out);
00609 
00610     const StepStatus<Scalar> stepStatus = this->getStepStatus();
00611 
00612     RCP<const Thyra::VectorBase<Scalar> >
00613       x = stepStatus.solution,
00614       xdot = stepStatus.solutionDot;
00615 
00616     Array<Scalar> time_vec = Teuchos::tuple(stepStatus.time);
00617     Array<RCP<const Thyra::VectorBase<Scalar> > > x_vec, xdot_vec;
00618     this->getPoints(time_vec,&x_vec,&xdot_vec,0);
00619 
00620     RCP<const Thyra::VectorBase<Scalar> >
00621       x_interp = x_vec[0],
00622       xdot_interp = xdot_vec[0];
00623 
00624     TEST_FOR_EXCEPT(
00625       !Thyra::testRelNormDiffErr(
00626         "x", *x, "x_interp", *x_interp,
00627         "2*epsilon", ScalarMag(100.0*SMT::eps()),
00628         "2*epsilon", ScalarMag(100.0*SMT::eps()),
00629         includesVerbLevel(verbLevel,Teuchos::VERB_HIGH) ? out.get() : 0
00630         )
00631       );
00632 
00633     TEST_FOR_EXCEPT(
00634       !Thyra::testRelNormDiffErr(
00635         "xdot", *xdot, "xdot_interp", *xdot_interp,
00636         "2*epsilon", ScalarMag(100.0*SMT::eps()),
00637         "2*epsilon", ScalarMag(100.0*SMT::eps()),
00638         includesVerbLevel(verbLevel,Teuchos::VERB_HIGH) ? out.get() : 0
00639         )
00640       );
00641 
00642   }
00643 
00644   // 2007/07/25: rabartl: ToDo: Move the above test into a helper function so
00645   // that it can be used from lots of different places!
00646 
00647 #endif
00648 
00649   if ( !is_null(out) && as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW) ) {
00650     *out
00651       << "\nLeaving " << Teuchos::TypeNameTraits<BackwardEulerStepper<Scalar> >::name()
00652       << "::takeStep(...) ...\n"; 
00653   }
00654 
00655   return(dt);
00656 
00657 }
00658 
00659 
00660 template<class Scalar>
00661 const StepStatus<Scalar> BackwardEulerStepper<Scalar>::getStepStatus() const
00662 {
00663 
00664   typedef Teuchos::ScalarTraits<Scalar> ST;
00665 
00666   StepStatus<Scalar> stepStatus; // Defaults to unknown status
00667 
00668   if (!isInitialized_) {
00669     stepStatus.stepStatus = STEP_STATUS_UNINITIALIZED;
00670   }
00671   else if (numSteps_ > 0) {
00672     stepStatus.stepStatus = STEP_STATUS_CONVERGED; 
00673   }
00674   // else unknown
00675 
00676   stepStatus.stepSize = dt_;
00677   stepStatus.order = 1;
00678   stepStatus.time = t_;
00679   stepStatus.solution = x_;
00680   stepStatus.solutionDot = x_dot_;
00681 
00682   return(stepStatus);
00683 
00684 }
00685 
00686 
00687 // Overridden from InterpolationBufferBase
00688 
00689 
00690 template<class Scalar>
00691 RCP<const Thyra::VectorSpaceBase<Scalar> >
00692 BackwardEulerStepper<Scalar>::get_x_space() const
00693 {
00694   return ( !is_null(model_) ? model_->get_x_space() : Teuchos::null );
00695 }
00696 
00697 
00698 template<class Scalar>
00699 void BackwardEulerStepper<Scalar>::addPoints(
00700   const Array<Scalar>& time_vec,
00701   const Array<RCP<const Thyra::VectorBase<Scalar> > >& x_vec,
00702   const Array<RCP<const Thyra::VectorBase<Scalar> > >& xdot_vec
00703   )
00704 {
00705 
00706   typedef Teuchos::ScalarTraits<Scalar> ST;
00707   using Teuchos::as;
00708 
00709   initialize();
00710 
00711 #ifdef TEUCHOS_DEBUG
00712   TEST_FOR_EXCEPTION(
00713     time_vec.size() == 0, std::logic_error,
00714     "Error, addPoints called with an empty time_vec array!\n");
00715 #endif // TEUCHOS_DEBUG
00716 
00717   RCP<Teuchos::FancyOStream> out = this->getOStream();
00718   Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00719   Teuchos::OSTab ostab(out,1,"BES::setPoints");
00720 
00721   if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00722     *out << "time_vec = " << std::endl;
00723     for (int i=0 ; i<Teuchos::as<int>(time_vec.size()) ; ++i) {
00724       *out << "time_vec[" << i << "] = " << time_vec[i] << std::endl;
00725     }
00726   }
00727   else if (time_vec.size() == 1) {
00728     int n = 0;
00729     t_ = time_vec[n];
00730     t_old_ = t_;
00731     Thyra::V_V(&*x_,*x_vec[n]);
00732     Thyra::V_V(&*scaled_x_old_,*x_);
00733   }
00734   else {
00735     int n = time_vec.size()-1;
00736     int nm1 = time_vec.size()-2;
00737     t_ = time_vec[n];
00738     t_old_ = time_vec[nm1];
00739     Thyra::V_V(&*x_,*x_vec[n]);
00740     Scalar dt = t_ - t_old_;
00741     Thyra::V_StV(&*scaled_x_old_,Scalar(-ST::one()/dt),*x_vec[nm1]);
00742   }
00743 }
00744 
00745 
00746 template<class Scalar>
00747 TimeRange<Scalar> BackwardEulerStepper<Scalar>::getTimeRange() const
00748 {
00749   if ( !isInitialized_ && haveInitialCondition_ )
00750     return timeRange<Scalar>(t_,t_);
00751   if ( !isInitialized_ && !haveInitialCondition_ )
00752     return invalidTimeRange<Scalar>();
00753   return timeRange<Scalar>(t_old_,t_);
00754 }
00755 
00756 
00757 template<class Scalar>
00758 void BackwardEulerStepper<Scalar>::getPoints(
00759   const Array<Scalar>& time_vec,
00760   Array<RCP<const Thyra::VectorBase<Scalar> > >* x_vec,
00761   Array<RCP<const Thyra::VectorBase<Scalar> > >* xdot_vec,
00762   Array<ScalarMag>* accuracy_vec
00763   ) const
00764 {
00765 
00766   using Teuchos::as;
00767   typedef Teuchos::ScalarTraits<Scalar> ST;
00768   typedef typename ST::magnitudeType ScalarMag;
00769   typedef Teuchos::ScalarTraits<ScalarMag> SMT;
00770   typename DataStore<Scalar>::DataStoreVector_t ds_nodes;
00771   typename DataStore<Scalar>::DataStoreVector_t ds_out;
00772 
00773 #ifdef TEUCHOS_DEBUG
00774   TEST_FOR_EXCEPT(!haveInitialCondition_);
00775   TEST_FOR_EXCEPT( 0 == x_vec );
00776 #endif
00777 
00778   RCP<Teuchos::FancyOStream> out = this->getOStream();
00779   Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00780   Teuchos::OSTab ostab(out,1,"BES::getPoints");
00781   if ( !is_null(out) && as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW) ) {
00782     *out
00783       << "\nEntering " << Teuchos::TypeNameTraits<BackwardEulerStepper<Scalar> >::name()
00784       << "::getPoints(...) ...\n"; 
00785   }
00786   if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00787     for (int i=0 ; i<Teuchos::as<int>(time_vec.size()) ; ++i) {
00788       *out << "time_vec[" << i << "] = " << time_vec[i] << std::endl;
00789     }
00790     *out << "I can interpolate in the interval [" << t_old_ << "," << t_ << "]." << std::endl;
00791   }
00792   if (t_old_ != t_) {
00793     if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00794       *out << "Passing two points to interpolator:  " << t_old_ << " and " << t_ << std::endl;
00795     }
00796     DataStore<Scalar> ds_temp;
00797     Scalar dt = t_ - t_old_;
00798 #ifdef TEUCHOS_DEBUG
00799     TEST_FOR_EXCEPT(
00800       !Thyra::testRelErr(
00801         "dt", dt, "dt_", dt_,
00802         "1e+4*epsilon", ScalarMag(1e+4*SMT::eps()),
00803         "1e+2*epsilon", ScalarMag(1e+2*SMT::eps()),
00804         as<int>(verbLevel) >= as<int>(Teuchos::VERB_MEDIUM) ? out.get() : 0
00805         )
00806       );
00807 #endif
00808     RCP<Thyra::VectorBase<Scalar> >
00809       x_temp = scaled_x_old_->clone_v();
00810     Thyra::Vt_S(&*x_temp,Scalar(-ST::one()*dt));  // undo the scaling
00811     ds_temp.time = t_old_;
00812     ds_temp.x = x_temp;
00813     ds_temp.xdot = x_dot_old_;
00814     ds_temp.accuracy = ScalarMag(dt);
00815     ds_nodes.push_back(ds_temp);
00816     ds_temp.time = t_;
00817     ds_temp.x = x_;
00818     ds_temp.xdot = x_dot_;
00819     ds_temp.accuracy = ScalarMag(dt);
00820     ds_nodes.push_back(ds_temp);
00821   }
00822   else {
00823     if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00824       *out << "Passing one point to interpolator:  " << t_ << std::endl;
00825     }
00826     DataStore<Scalar> ds_temp;
00827     ds_temp.time = t_;
00828     ds_temp.x = x_;
00829     ds_temp.xdot = x_dot_;
00830     ds_temp.accuracy = ScalarMag(ST::zero());
00831     ds_nodes.push_back(ds_temp);
00832   }
00833   interpolator_->interpolate(ds_nodes,time_vec,&ds_out);
00834   Array<Scalar> time_out;
00835   dataStoreVectorToVector(ds_out,&time_out,x_vec,xdot_vec,accuracy_vec);
00836   if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00837     *out << "Passing out the interpolated values:" << std::endl;
00838     for (int i=0; i<Teuchos::as<int>(time_out.size()) ; ++i) {
00839       *out << "time[" << i << "] = " << time_out[i] << std::endl;
00840       *out << "x_vec[" << i << "] = " << std::endl;
00841       (*x_vec)[i]->describe(*out,Teuchos::VERB_EXTREME);
00842       if (xdot_vec) {
00843         if ( (*xdot_vec)[i] == Teuchos::null) {
00844           *out << "xdot_vec[" << i << "] = Teuchos::null" << std::endl;
00845         }
00846         else {
00847           *out << "xdot_vec[" << i << "] = " << std::endl;
00848           (*xdot_vec)[i]->describe(*out,Teuchos::VERB_EXTREME);
00849         }
00850       }
00851       if(accuracy_vec) {
00852         *out << "accuracy[" << i << "] = " << (*accuracy_vec)[i] << std::endl;
00853       }
00854     }
00855   }
00856   if ( !is_null(out) && as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW) ) {
00857     *out
00858       << "Leaving " << Teuchos::TypeNameTraits<BackwardEulerStepper<Scalar> >::name()
00859       << "::getPoints(...) ...\n"; 
00860   }
00861 
00862 }
00863 
00864 
00865 template<class Scalar>
00866 void BackwardEulerStepper<Scalar>::getNodes(Array<Scalar>* time_vec) const
00867 {
00868   using Teuchos::as;
00869 
00870 
00871 #ifdef TEUCHOS_DEBUG
00872   TEST_FOR_EXCEPT(!haveInitialCondition_);
00873 #endif
00874 
00875   time_vec->clear();
00876   time_vec->push_back(t_old_);
00877   if (numSteps_ > 0) {
00878     time_vec->push_back(t_);
00879   }
00880   RCP<Teuchos::FancyOStream> out = this->getOStream();
00881   Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00882   Teuchos::OSTab ostab(out,1,"BES::getNodes");
00883   if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00884     *out << this->description() << std::endl;
00885     for (int i=0 ; i<Teuchos::as<int>(time_vec->size()) ; ++i) {
00886       *out << "time_vec[" << i << "] = " << (*time_vec)[i] << std::endl;
00887     }
00888   }
00889 }
00890 
00891 
00892 template<class Scalar>
00893 void BackwardEulerStepper<Scalar>::removeNodes(Array<Scalar>& time_vec) 
00894 {
00895   initialize();
00896   using Teuchos::as;
00897   RCP<Teuchos::FancyOStream> out = this->getOStream();
00898   Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00899   Teuchos::OSTab ostab(out,1,"BES::removeNodes");
00900   if ( as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH) ) {
00901     *out << "time_vec = " << std::endl;
00902     for (int i=0 ; i<Teuchos::as<int>(time_vec.size()) ; ++i) {
00903       *out << "time_vec[" << i << "] = " << time_vec[i] << std::endl;
00904     }
00905   }
00906   TEST_FOR_EXCEPTION(true,std::logic_error,"Error, removeNodes is not implemented for BackwardEulerStepper at this time.\n");
00907   // TODO:
00908   // if any time in time_vec matches t_ or t_old_, then do the following:
00909   // remove t_old_:  set t_old_ = t_ and set scaled_x_old_ = x_
00910   // remove t_:  set t_ = t_old_ and set x_ = -dt*scaled_x_old_
00911 }
00912 
00913 
00914 template<class Scalar>
00915 int BackwardEulerStepper<Scalar>::getOrder() const
00916 {
00917   return(1);
00918 }
00919 
00920 
00921 // Overridden from Teuchos::ParameterListAcceptor
00922 
00923 
00924 template <class Scalar>
00925 void BackwardEulerStepper<Scalar>::setParameterList(
00926   RCP<Teuchos::ParameterList> const& paramList
00927   )
00928 {
00929   TEST_FOR_EXCEPT(is_null(paramList));
00930   paramList->validateParametersAndSetDefaults(*this->getValidParameters());
00931   parameterList_ = paramList;
00932   Teuchos::readVerboseObjectSublist(&*parameterList_,this);
00933 }
00934 
00935 
00936 template <class Scalar>
00937 RCP<Teuchos::ParameterList>
00938 BackwardEulerStepper<Scalar>::getNonconstParameterList()
00939 {
00940   return(parameterList_);
00941 }
00942 
00943 
00944 template <class Scalar>
00945 RCP<Teuchos::ParameterList>
00946 BackwardEulerStepper<Scalar>::unsetParameterList()
00947 {
00948   RCP<Teuchos::ParameterList>
00949     temp_param_list = parameterList_;
00950   parameterList_ = Teuchos::null;
00951   return(temp_param_list);
00952 }
00953 
00954 
00955 template<class Scalar>
00956 RCP<const Teuchos::ParameterList>
00957 BackwardEulerStepper<Scalar>::getValidParameters() const
00958 {
00959   using Teuchos::ParameterList;
00960   static RCP<const ParameterList> validPL;
00961   if (is_null(validPL)) {
00962     RCP<ParameterList> pl = Teuchos::parameterList();
00963     Teuchos::setupVerboseObjectSublist(&*pl);
00964     validPL = pl;
00965   }
00966   return validPL;
00967 }
00968 
00969 
00970 // Overridden from Teuchos::Describable
00971 
00972 
00973 template<class Scalar>
00974 void BackwardEulerStepper<Scalar>::describe(
00975   Teuchos::FancyOStream &out,
00976   const Teuchos::EVerbosityLevel verbLevel
00977   ) const
00978 {
00979   using Teuchos::as;
00980   Teuchos::OSTab tab(out);
00981   if (!isInitialized_) {
00982     out << this->description() << " : This stepper is not initialized yet" << std::endl;
00983     return;
00984   }
00985   if (
00986     as<int>(verbLevel) == as<int>(Teuchos::VERB_DEFAULT)
00987     ||
00988     as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW)
00989     )
00990   {
00991     out << this->description() << "::describe:" << std::endl;
00992     out << "model = " << model_->description() << std::endl;
00993     out << "solver = " << solver_->description() << std::endl;
00994     if (neModel_ == Teuchos::null) {
00995       out << "neModel = Teuchos::null" << std::endl;
00996     } else {
00997       out << "neModel = " << neModel_->description() << std::endl;
00998     }
00999   }
01000   else if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW)) {
01001     out << "t_ = " << t_ << std::endl;
01002     out << "t_old_ = " << t_old_ << std::endl;
01003   }
01004   else if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_MEDIUM)) {
01005   }
01006   else if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH)) {
01007     out << "model_ = " << std::endl;
01008     model_->describe(out,verbLevel);
01009     out << "solver_ = " << std::endl;
01010     solver_->describe(out,verbLevel);
01011     if (neModel_ == Teuchos::null) {
01012       out << "neModel = Teuchos::null" << std::endl;
01013     } else {
01014       out << "neModel = " << std::endl;
01015       neModel_->describe(out,verbLevel);
01016     }
01017     out << "x_ = " << std::endl;
01018     x_->describe(out,verbLevel);
01019     out << "scaled_x_old_ = " << std::endl;
01020     scaled_x_old_->describe(out,verbLevel);
01021   }
01022 }
01023 
01024 
01025 // private
01026 
01027 
01028 template <class Scalar>
01029 void BackwardEulerStepper<Scalar>::initialize()
01030 {
01031 
01032   if (isInitialized_)
01033     return;
01034 
01035   TEST_FOR_EXCEPT(is_null(model_));
01036   TEST_FOR_EXCEPT(is_null(solver_));
01037   TEST_FOR_EXCEPT(!haveInitialCondition_);
01038 
01039   if ( is_null(interpolator_) ) {
01040     // If an interpolator has not been explicitly set, then just create
01041     // a default linear interpolator.
01042     interpolator_ = Teuchos::rcp(new LinearInterpolator<Scalar> );
01043     // 2007/05/18: rabartl: ToDo: Replace this with a Hermete interplator
01044     // when it is implementated!
01045   }
01046 
01047   if (is_null(scaled_x_old_))
01048     scaled_x_old_ = createMember(model_->get_x_space());
01049 
01050   if (is_null(x_dot_))
01051     x_dot_ = createMember(model_->get_x_space());
01052 
01053   if (is_null(x_dot_old_))
01054     x_dot_old_ = createMember(model_->get_x_space());
01055 
01056   // Note: above, we don't need to actually initialize x_dot or x_dot_old
01057   // since these will be initialized after each step
01058 
01059   isInitialized_ = true;
01060 
01061 }
01062 
01063 
01064 } // namespace Rythmos
01065 
01066 #endif //Rythmos_BACKWARD_EULER_STEPPER_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends

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