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