Rythmos_ForwardSensitivityStepper.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_FORWARD_SENSITIVITY_STEPPER_HPP
00030 #define RYTHMOS_FORWARD_SENSITIVITY_STEPPER_HPP
00031 
00032 
00033 #include "Rythmos_StepperBase.hpp"
00034 #include "Rythmos_ForwardSensitivityModelEvaluator.hpp"
00035 #include "Rythmos_StateAndForwardSensitivityModelEvaluator.hpp"
00036 #include "Rythmos_SolverAcceptingStepperBase.hpp"
00037 #include "Rythmos_IntegratorBase.hpp"
00038 #include "Rythmos_SingleResidualModelEvaluatorBase.hpp"
00039 #include "Thyra_ModelEvaluatorHelpers.hpp"
00040 #include "Thyra_LinearNonlinearSolver.hpp"
00041 #include "Thyra_AssertOp.hpp"
00042 #include "Teuchos_ParameterListAcceptorDefaultBase.hpp"
00043 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
00044 #include "Teuchos_Assert.hpp"
00045 #include "Teuchos_as.hpp"
00046 
00047 
00048 namespace Rythmos {
00049 
00050 
00199 template<class Scalar> 
00200 class ForwardSensitivityStepper
00201   : virtual public StepperBase<Scalar>,
00202     virtual public Teuchos::ParameterListAcceptorDefaultBase
00203 {
00204 public:
00205 
00207   typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType ScalarMag;
00208 
00211 
00213   ForwardSensitivityStepper();
00214 
00268   void initializeSyncedSteppers(
00269     const RCP<const Thyra::ModelEvaluator<Scalar> > &stateModel,
00270     const int p_index,
00271     const Thyra::ModelEvaluatorBase::InArgs<Scalar> &stateBasePoint,
00272     const RCP<StepperBase<Scalar> > &stateStepper,
00273     const RCP<Thyra::NonlinearSolverBase<Scalar> > &stateTimeStepSolver,
00274     const RCP<StepperBase<Scalar> > &sensStepper = Teuchos::null,
00275     const RCP<Thyra::NonlinearSolverBase<Scalar> > &sensTimeStepSolver = Teuchos::null
00276     );
00277 
00313   void initializeDecoupledSteppers(
00314     const RCP<const Thyra::ModelEvaluator<Scalar> > &stateModel,
00315     const int p_index,
00316     const Thyra::ModelEvaluatorBase::InArgs<Scalar> &stateBasePoint,
00317     const RCP<StepperBase<Scalar> > &stateStepper,
00318     const RCP<Thyra::NonlinearSolverBase<Scalar> > &stateTimeStepSolver,
00319     const RCP<IntegratorBase<Scalar> > &stateIntegrator,
00320     const Scalar &finalTime,
00321     const RCP<StepperBase<Scalar> > &sensStepper = Teuchos::null,
00322     const RCP<Thyra::NonlinearSolverBase<Scalar> > &sensTimeStepSolver = Teuchos::null
00323     );
00324 
00328   RCP<const Thyra::ModelEvaluator<Scalar> >
00329   getStateModel() const;
00330 
00334   RCP<const ForwardSensitivityModelEvaluator<Scalar> >
00335   getFwdSensModel() const;
00336 
00343   RCP<const StateAndForwardSensitivityModelEvaluator<Scalar> >
00344   getStateAndFwdSensModel() const;
00345 
00347 
00350 
00352   void setParameterList(RCP<Teuchos::ParameterList> const& paramList);
00354   RCP<const Teuchos::ParameterList> getValidParameters() const;
00355 
00357 
00360 
00362   bool acceptsModel() const;
00363 
00365   void setModel(
00366     const RCP<const Thyra::ModelEvaluator<Scalar> > &model
00367     );
00368 
00375   RCP<const Thyra::ModelEvaluator<Scalar> >
00376   getModel() const;
00377 
00378   // RAB: ToDo: 2007/05/15: I need to talk with Todd about potentially
00379   // removing the setModel() and getModel() functions from the StepperBase
00380   // interface.  In the case of this forward sensitivity solver, I am not sure
00381   // that it makes a lot of sense to define a model.  This surely will not be
00382   // the model that a generic client would expect.  The assumption I am sure
00383   // would be that this model has the same space for x as the interpolation
00384   // buffer but that is not true in this case.
00385 
00399   void setInitialCondition(
00400     const Thyra::ModelEvaluatorBase::InArgs<Scalar> &state_and_sens_ic
00401     );
00402 
00404   Scalar takeStep( Scalar dt, StepSizeType stepType );
00405 
00407   const StepStatus<Scalar> getStepStatus() const;
00408 
00410 
00413 
00420   RCP<const Thyra::VectorSpaceBase<Scalar> >
00421   get_x_space() const;
00422 
00424   void addPoints(
00425     const Array<Scalar>& time_vec,
00426     const Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x_vec,
00427     const Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& xdot_vec
00428     );
00429 
00431   TimeRange<Scalar> getTimeRange() const;
00432 
00434   void getPoints(
00435     const Array<Scalar>& time_vec,
00436     Array<RCP<const Thyra::VectorBase<Scalar> > >* x_vec,
00437     Array<RCP<const Thyra::VectorBase<Scalar> > >* xdot_vec,
00438     Array<ScalarMag>* accuracy_vec
00439     ) const;
00440 
00442   void getNodes(Array<Scalar>* time_vec) const;
00443 
00445   void removeNodes(Array<Scalar>& time_vec);
00446 
00448   int getOrder() const;
00449 
00451 
00454 
00456   void initialize(
00457     const RCP<const Thyra::ModelEvaluator<Scalar> > &stateModel,
00458     const int p_index,
00459     const Thyra::ModelEvaluatorBase::InArgs<Scalar> &stateBasePoint,
00460     const RCP<StepperBase<Scalar> > &stateStepper,
00461     const RCP<Thyra::NonlinearSolverBase<Scalar> > &stateTimeStepSolver,
00462     const RCP<StepperBase<Scalar> > &sensStepper = Teuchos::null,
00463     const RCP<Thyra::NonlinearSolverBase<Scalar> > &sensTimeStepSolver = Teuchos::null
00464     )
00465     {
00466       initializeSyncedSteppers(
00467         stateModel, p_index, stateBasePoint, stateStepper, stateTimeStepSolver,
00468         sensStepper, sensTimeStepSolver
00469         );
00470     }
00471 
00473 
00474 private:
00475 
00476   // /////////////////////////
00477   // Private data members
00478 
00479   bool forceUpToDateW_;
00480   RCP<const Thyra::ModelEvaluator<Scalar> > stateModel_;
00481   Thyra::ModelEvaluatorBase::InArgs<Scalar> stateBasePoint_;
00482   RCP<StepperBase<Scalar> > stateStepper_;
00483   RCP<Thyra::NonlinearSolverBase<Scalar> > stateTimeStepSolver_;
00484   RCP<IntegratorBase<Scalar> > stateIntegrator_;
00485   Scalar finalTime_;
00486   RCP<StepperBase<Scalar> > sensStepper_;
00487   RCP<Thyra::NonlinearSolverBase<Scalar> > sensTimeStepSolver_;
00488 
00489   bool isSingleResidualStepper_;
00490   RCP<ForwardSensitivityModelEvaluator<Scalar> > sensModel_;
00491   RCP<StateAndForwardSensitivityModelEvaluator<Scalar> > stateAndSensModel_;
00492   Thyra::ModelEvaluatorBase::InArgs<Scalar> stateBasePoint_t_;
00493 
00494   static const std::string forceUpToDateW_name_;
00495   static const bool forceUpToDateW_default_;
00496 
00497   // /////////////////////////
00498   // Private member functions
00499 
00500   void initializeCommon(
00501     const RCP<const Thyra::ModelEvaluator<Scalar> > &stateModel,
00502     const int p_index,
00503     const Thyra::ModelEvaluatorBase::InArgs<Scalar> &stateBasePoint,
00504     const RCP<StepperBase<Scalar> > &stateStepper,
00505     const RCP<Thyra::NonlinearSolverBase<Scalar> > &stateTimeStepSolver,
00506     const RCP<StepperBase<Scalar> > &sensStepper,
00507     const RCP<Thyra::NonlinearSolverBase<Scalar> > &sensTimeStepSolver
00508     );
00509 
00510   Scalar takeSyncedStep( Scalar dt, StepSizeType stepType );
00511 
00512   Scalar takeDecoupledStep( Scalar dt, StepSizeType stepType );
00513 
00514 };
00515 
00516 
00521 template<class Scalar> 
00522 inline
00523 RCP<ForwardSensitivityStepper<Scalar> >
00524 forwardSensitivityStepper()
00525 {
00526   return Teuchos::rcp(new ForwardSensitivityStepper<Scalar>());
00527 }
00528 
00529 
00534 template<class Scalar> 
00535 inline
00536 RCP<ForwardSensitivityStepper<Scalar> >
00537 forwardSensitivityStepper(
00538   const RCP<const Thyra::ModelEvaluator<Scalar> > &stateModel,
00539   const int p_index,
00540   const Thyra::ModelEvaluatorBase::InArgs<Scalar> &stateBasePoint,
00541   const RCP<StepperBase<Scalar> > &stateStepper,
00542   const RCP<Thyra::NonlinearSolverBase<Scalar> > &stateTimeStepSolver,
00543   const RCP<StepperBase<Scalar> > &sensStepper = Teuchos::null,
00544   const RCP<Thyra::NonlinearSolverBase<Scalar> > &sensTimeStepSolver = Teuchos::null
00545   )
00546 {
00547   RCP<ForwardSensitivityStepper<Scalar> >
00548     fwdSensStepper = Teuchos::rcp(new ForwardSensitivityStepper<Scalar>());
00549   fwdSensStepper->initialize(
00550     stateModel, p_index, stateBasePoint, stateStepper, stateTimeStepSolver );
00551   return fwdSensStepper;
00552 }
00553 
00554 
00560 template<class Scalar>
00561 int getParameterIndex(
00562   const ForwardSensitivityStepper<Scalar> &fwdSensStepper
00563   )
00564 {
00565   return fwdSensStepper.getFwdSensModel()->get_p_index();
00566 }
00567 
00568 
00569 //
00570 // Implementation
00571 //
00572 
00573 
00574 // Static members
00575 
00576 
00577 template<class Scalar> 
00578 const std::string ForwardSensitivityStepper<Scalar>::forceUpToDateW_name_
00579 = "Force Up-To-Date Jacobian";
00580 
00581 template<class Scalar> 
00582 const bool ForwardSensitivityStepper<Scalar>::forceUpToDateW_default_
00583 = true;
00584 
00585 
00586 // Constructors, Intializers, Misc.
00587 
00588 
00589 template<class Scalar> 
00590 ForwardSensitivityStepper<Scalar>::ForwardSensitivityStepper()
00591   :forceUpToDateW_(false),
00592    isSingleResidualStepper_(false)
00593 {}
00594 
00595 
00596 template<class Scalar> 
00597 void ForwardSensitivityStepper<Scalar>::initializeSyncedSteppers(
00598   const RCP<const Thyra::ModelEvaluator<Scalar> > &stateModel,
00599   const int p_index,
00600   const Thyra::ModelEvaluatorBase::InArgs<Scalar> &stateBasePoint,
00601   const RCP<StepperBase<Scalar> > &stateStepper,
00602   const RCP<Thyra::NonlinearSolverBase<Scalar> > &stateTimeStepSolver,
00603   const RCP<StepperBase<Scalar> > &sensStepper,
00604   const RCP<Thyra::NonlinearSolverBase<Scalar> > &sensTimeStepSolver
00605   )
00606   
00607 {
00608   initializeCommon(stateModel, p_index, stateBasePoint, stateStepper,
00609     stateTimeStepSolver, sensStepper, sensTimeStepSolver );
00610 }
00611 
00612 
00613 template<class Scalar> 
00614 void ForwardSensitivityStepper<Scalar>::initializeDecoupledSteppers(
00615   const RCP<const Thyra::ModelEvaluator<Scalar> > &stateModel,
00616   const int p_index,
00617   const Thyra::ModelEvaluatorBase::InArgs<Scalar> &stateBasePoint,
00618   const RCP<StepperBase<Scalar> > &stateStepper,
00619   const RCP<Thyra::NonlinearSolverBase<Scalar> > &stateTimeStepSolver,
00620   const RCP<IntegratorBase<Scalar> > &stateIntegrator,
00621   const Scalar &finalTime,
00622   const RCP<StepperBase<Scalar> > &sensStepper,
00623   const RCP<Thyra::NonlinearSolverBase<Scalar> > &sensTimeStepSolver
00624   )
00625 {
00626   TEST_FOR_EXCEPT(is_null(stateIntegrator));
00627   initializeCommon(stateModel, p_index, stateBasePoint, stateStepper,
00628     stateTimeStepSolver, sensStepper, sensTimeStepSolver );
00629   stateIntegrator_ = stateIntegrator;
00630   finalTime_ = finalTime;
00631 }
00632 
00633   
00634 template<class Scalar> 
00635 RCP<const Thyra::ModelEvaluator<Scalar> >
00636 ForwardSensitivityStepper<Scalar>::getStateModel() const
00637 {
00638   return stateModel_;
00639 }
00640 
00641   
00642 template<class Scalar> 
00643 RCP<const ForwardSensitivityModelEvaluator<Scalar> >
00644 ForwardSensitivityStepper<Scalar>::getFwdSensModel() const
00645 {
00646   return sensModel_;
00647 }
00648 
00649   
00650 template<class Scalar> 
00651 RCP<const StateAndForwardSensitivityModelEvaluator<Scalar> >
00652 ForwardSensitivityStepper<Scalar>::getStateAndFwdSensModel() const
00653 {
00654   return stateAndSensModel_;
00655 }
00656 
00657 
00658 // Overridden from Teuchos::ParameterListAcceptor
00659 
00660 
00661 template<class Scalar> 
00662 void ForwardSensitivityStepper<Scalar>::setParameterList(
00663   RCP<Teuchos::ParameterList> const& paramList
00664   )
00665 {
00666   TEST_FOR_EXCEPT(is_null(paramList));
00667   paramList->validateParameters(*getValidParameters());
00668   this->setMyParamList(paramList);
00669   forceUpToDateW_ = paramList->get(forceUpToDateW_name_,forceUpToDateW_default_);
00670   Teuchos::readVerboseObjectSublist(&*paramList,this);
00671 }
00672 
00673 
00674 template<class Scalar> 
00675 RCP<const Teuchos::ParameterList>
00676 ForwardSensitivityStepper<Scalar>::getValidParameters() const
00677 {
00678   static RCP<const ParameterList> validPL;
00679   if (is_null(validPL) ) {
00680     RCP<ParameterList> pl = Teuchos::parameterList();
00681     pl->set( forceUpToDateW_name_, forceUpToDateW_default_,
00682       "If set to true, then the Jacobian matrix W used in the\n"
00683       "state timestep equation will be forced to be up to date\n"
00684       "with the final value for x for the nonlinear solve.  If\n"
00685       "you are willing to live with slightly less accurate sensitivities\n"
00686       "then set this to false."
00687       );
00688     Teuchos::setupVerboseObjectSublist(&*pl);
00689     validPL = pl;
00690   }
00691   return validPL;
00692 }
00693 
00694 
00695 // Overridden from StepperBase
00696 
00697 template<class Scalar> 
00698 bool ForwardSensitivityStepper<Scalar>::acceptsModel() const
00699 {
00700   return false;
00701 }
00702 
00703 template<class Scalar> 
00704 void ForwardSensitivityStepper<Scalar>::setModel(
00705   const RCP<const Thyra::ModelEvaluator<Scalar> > &model
00706   )
00707 {
00708   TEST_FOR_EXCEPT_MSG( true,
00709     "Error, this stepper subclass does not accept a model"
00710     " as defined by the StepperBase interface!");
00711 }
00712 
00713 
00714 template<class Scalar> 
00715 RCP<const Thyra::ModelEvaluator<Scalar> >
00716 ForwardSensitivityStepper<Scalar>::getModel() const
00717 {
00718   return stateAndSensModel_;
00719 }
00720 
00721 
00722 template<class Scalar> 
00723 void ForwardSensitivityStepper<Scalar>::setInitialCondition(
00724   const Thyra::ModelEvaluatorBase::InArgs<Scalar> &state_and_sens_ic
00725   )
00726 {
00727   
00728   typedef Thyra::ModelEvaluatorBase MEB;
00729 
00730   // Get the product vectors for x_bar = [ x; s_bar ] and x_bar_dot
00731 
00732   TEST_FOR_EXCEPTION(
00733     is_null(state_and_sens_ic.get_x()), std::logic_error,
00734     "Error, the initial condition for x_bar = [ x; s_bar ] can not be null!" );
00735 
00736   const RCP<const Thyra::ProductVectorBase<Scalar> >
00737     x_bar_init = Thyra::productVectorBase<Scalar>(
00738       state_and_sens_ic.get_x()
00739       );
00740 
00741   const RCP<const Thyra::ProductVectorBase<Scalar> >
00742     x_bar_dot_init = Thyra::productVectorBase<Scalar>(
00743       state_and_sens_ic.get_x_dot()
00744       );
00745 
00746   // Remove x and x_dot from state_and_sens_ic_in to avoid cloning x and x dot!
00747   
00748   Thyra::ModelEvaluatorBase::InArgs<Scalar>
00749     state_and_sens_ic_no_x = state_and_sens_ic;
00750   state_and_sens_ic_no_x.set_x(Teuchos::null);
00751   state_and_sens_ic_no_x.set_x_dot(Teuchos::null);
00752 
00753   // Set initial condition for the state
00754 
00755   MEB::InArgs<Scalar> state_ic = stateModel_->createInArgs();
00756   state_ic.setArgs(state_and_sens_ic_no_x,true,true); // Set time, parameters etc.
00757   state_ic.set_x(x_bar_init->getVectorBlock(0)->clone_v());
00758   state_ic.set_x_dot(
00759     !is_null(x_bar_dot_init)
00760     ? x_bar_dot_init->getVectorBlock(0)->clone_v()
00761     : Teuchos::null
00762     );
00763   stateStepper_->setInitialCondition(state_ic);
00764 
00765   // Set up the integrator if needed
00766   if (!is_null(stateIntegrator_)) {
00767     stateIntegrator_->setStepper( stateStepper_, finalTime_ );
00768     sensModel_->setStateIntegrator( stateIntegrator_, state_ic );
00769   }
00770 
00771   // Set initial condition for the sensitivities
00772   
00773   MEB::InArgs<Scalar> sens_ic = sensModel_->createInArgs();
00774   sens_ic.setArgs(state_and_sens_ic_no_x,true,true); // Set time etc.
00775   sens_ic.set_x(x_bar_init->getVectorBlock(1)->clone_v());
00776   sens_ic.set_x_dot(
00777     !is_null(x_bar_dot_init)
00778     ? x_bar_dot_init->getVectorBlock(1)->clone_v()
00779     : Teuchos::null
00780     );
00781   sensStepper_->setInitialCondition(sens_ic);
00782 
00783 }
00784  
00785 
00786 template<class Scalar> 
00787 Scalar
00788 ForwardSensitivityStepper<Scalar>::takeStep(
00789   Scalar dt, StepSizeType stepType
00790   )
00791 {
00792 
00793 #ifdef ENABLE_RYTHMOS_TIMERS
00794   TEUCHOS_FUNC_TIME_MONITOR("Rythmos:ForwardSensitivityStepper::takeStep");
00795 #endif
00796 
00797   if (!is_null(stateIntegrator_)) {
00798     return takeDecoupledStep(dt,stepType);
00799   }
00800 
00801   return takeSyncedStep(dt,stepType);
00802 
00803 }
00804 
00805 
00806 template<class Scalar> 
00807 const StepStatus<Scalar>
00808 ForwardSensitivityStepper<Scalar>::getStepStatus() const
00809 {
00810 
00811   const StepStatus<Scalar> sensStepStatus = sensStepper_->getStepStatus();
00812   StepStatus<Scalar> stepStatus;
00813   
00814   stepStatus.message = sensStepStatus.message;
00815   stepStatus.stepStatus = sensStepStatus.stepStatus;
00816   stepStatus.stepLETStatus = sensStepStatus.stepLETStatus;
00817   stepStatus.stepSize = sensStepStatus.stepSize;
00818   stepStatus.order = sensStepStatus.order;
00819   stepStatus.time = sensStepStatus.time;
00820   stepStatus.stepLETValue = sensStepStatus.stepLETValue;
00821   stepStatus.extraParameters = sensStepStatus.extraParameters;
00822 
00823   if (is_null(stateIntegrator_)) {
00824     const StepStatus<Scalar> 
00825       stateStepStatus = stateStepper_->getStepStatus();
00826     if (!is_null(stateStepStatus.solution) && !is_null(sensStepStatus.solution))
00827       stepStatus.solution = stateAndSensModel_->create_x_bar_vec(
00828         stateStepStatus.solution, sensStepStatus.solution
00829         );
00830     if (!is_null(stateStepStatus.solutionDot) && !is_null(sensStepStatus.solutionDot))
00831       stepStatus.solutionDot = stateAndSensModel_->create_x_bar_vec(
00832         stateStepStatus.solutionDot, sensStepStatus.solutionDot
00833         );
00834   }
00835 
00836   return stepStatus;
00837 
00838 }
00839 
00840 
00841 // Overridden from InterpolationBufferBase
00842 
00843 
00844 template<class Scalar> 
00845 RCP<const Thyra::VectorSpaceBase<Scalar> >
00846 ForwardSensitivityStepper<Scalar>::get_x_space() const
00847 {
00848   return stateAndSensModel_->get_x_space();
00849 }
00850 
00851 
00852 template<class Scalar> 
00853 void ForwardSensitivityStepper<Scalar>::addPoints(
00854   const Array<Scalar>& time_vec,
00855   const Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x_vec,
00856   const Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& xdot_vec
00857   )
00858 {
00859   TEST_FOR_EXCEPT("Not implemented addPoints(...) yet but we could if we wanted!");
00860 }
00861 
00862 
00863 template<class Scalar> 
00864 TimeRange<Scalar>
00865 ForwardSensitivityStepper<Scalar>::getTimeRange() const
00866 {
00867   return sensStepper_->getTimeRange();
00868 }
00869 
00870 
00871 template<class Scalar> 
00872 void ForwardSensitivityStepper<Scalar>::getPoints(
00873   const Array<Scalar>& time_vec,
00874   Array<RCP<const Thyra::VectorBase<Scalar> > >* x_bar_vec,
00875   Array<RCP<const Thyra::VectorBase<Scalar> > >* x_bar_dot_vec,
00876   Array<ScalarMag>* accuracy_vec
00877   ) const
00878 {
00879 
00880   using Teuchos::as;
00881 
00882 #ifdef TEUCHOS_DEBUG
00883   TEST_FOR_EXCEPT( as<int>(time_vec.size()) == 0 );
00884 #endif
00885 
00886   const int numTimePoints = time_vec.size();
00887 
00888   if (x_bar_vec)
00889     x_bar_vec->clear();
00890 
00891   if (x_bar_dot_vec)
00892     x_bar_dot_vec->clear();
00893   
00894   Array<RCP<const Thyra::VectorBase<Scalar> > >
00895     x_vec, x_dot_vec;
00896 
00897   if (!is_null(stateIntegrator_)) {
00898     stateIntegrator_->getPoints(
00899       time_vec,
00900       x_bar_vec ? &x_vec: 0,
00901       x_bar_dot_vec ? &x_dot_vec: 0,
00902       0 // Ignoring accuracy from state for now!
00903       );
00904   }
00905   else {
00906     stateStepper_->getPoints(
00907       time_vec,
00908       x_bar_vec ? &x_vec: 0,
00909       x_bar_dot_vec ? &x_dot_vec: 0,
00910       0 // Ignoring accuracy from state for now!
00911       );
00912   }
00913   
00914   Array<RCP<const Thyra::VectorBase<Scalar> > >
00915     s_bar_vec, s_bar_dot_vec;
00916 
00917   sensStepper_->getPoints(
00918     time_vec,
00919     x_bar_vec ? &s_bar_vec: 0,
00920     x_bar_dot_vec ? &s_bar_dot_vec: 0,
00921     accuracy_vec
00922     );
00923   
00924   if ( x_bar_vec ) {
00925     for ( int i = 0; i < numTimePoints; ++i ) {
00926       x_bar_vec->push_back(
00927         stateAndSensModel_->create_x_bar_vec(x_vec[i],s_bar_vec[i])
00928         );
00929     }
00930   }
00931   
00932   if ( x_bar_dot_vec ) {
00933     for ( int i = 0; i < numTimePoints; ++i ) {
00934       x_bar_dot_vec->push_back(
00935         stateAndSensModel_->create_x_bar_vec(x_dot_vec[i],s_bar_dot_vec[i])
00936         );
00937     }
00938   }
00939 
00940 }
00941 
00942 
00943 template<class Scalar>
00944 void ForwardSensitivityStepper<Scalar>::getNodes(
00945   Array<Scalar>* time_vec
00946   ) const
00947 {
00948   TEST_FOR_EXCEPT("Not implemented yet but we can!");
00949 }
00950 
00951 
00952 template<class Scalar> 
00953 void ForwardSensitivityStepper<Scalar>::removeNodes(
00954   Array<Scalar>& time_vec
00955   )
00956 {
00957   TEST_FOR_EXCEPT("Not implemented yet but we can!");
00958 }
00959 
00960 
00961 template<class Scalar> 
00962 int ForwardSensitivityStepper<Scalar>::getOrder() const
00963 {
00964   return sensStepper_->getOrder();
00965   // Note: This assumes that stateStepper will have the same order!
00966 }
00967 
00968 
00969 // private
00970 
00971 
00972 template<class Scalar> 
00973 void ForwardSensitivityStepper<Scalar>::initializeCommon(
00974   const RCP<const Thyra::ModelEvaluator<Scalar> > &stateModel,
00975   const int p_index,
00976   const Thyra::ModelEvaluatorBase::InArgs<Scalar> &stateBasePoint,
00977   const RCP<StepperBase<Scalar> > &stateStepper,
00978   const RCP<Thyra::NonlinearSolverBase<Scalar> > &stateTimeStepSolver,
00979   const RCP<StepperBase<Scalar> > &sensStepper,
00980   const RCP<Thyra::NonlinearSolverBase<Scalar> > &sensTimeStepSolver
00981   )
00982 {
00983 
00984   using Teuchos::rcp_dynamic_cast;
00985 
00986   typedef Thyra::ModelEvaluatorBase MEB;
00987 
00988   //
00989   // Validate input
00990   //
00991 
00992   TEST_FOR_EXCEPT( is_null(stateModel) );
00993   TEST_FOR_EXCEPT( is_null(stateStepper) );
00994   TEST_FOR_EXCEPT( is_null(stateTimeStepSolver) ); // ToDo: allow to be null for explicit methods!
00995 
00996 
00997   //
00998   // Create the sensModel which will do some more validation
00999   //
01000   
01001   RCP<ForwardSensitivityModelEvaluator<Scalar> >
01002     sensModel = Teuchos::rcp(new ForwardSensitivityModelEvaluator<Scalar>);
01003   sensModel->initializeStructure(stateModel,p_index);
01004   
01005   //
01006   // Get the input objects
01007   //
01008 
01009   stateModel_ = stateModel;
01010 
01011   stateBasePoint_ = stateBasePoint;
01012 
01013   stateStepper_ = stateStepper;
01014   
01015   stateTimeStepSolver_ = stateTimeStepSolver;
01016 
01017   sensModel_ = sensModel;
01018 
01019   stateAndSensModel_ = Teuchos::rcp(new StateAndForwardSensitivityModelEvaluator<Scalar>);
01020   stateAndSensModel_->initializeStructure(sensModel_);
01021 
01022   if (!is_null(sensStepper)) {
01023     sensStepper_ = sensStepper;
01024   }
01025   else {
01026     sensStepper_ = stateStepper_->cloneStepperAlgorithm();
01027     TEST_FOR_EXCEPTION(
01028       is_null(sensStepper_), std::logic_error,
01029       "Error, if the client does not pass in a stepper for the senitivity\n"
01030       "equations then the stateStepper object must support cloning to create\n"
01031       "the sensitivity stepper!"
01032       );
01033   }
01034 
01035   if (!is_null(sensTimeStepSolver)) {
01036     sensTimeStepSolver_ = sensTimeStepSolver;
01037   }
01038   else {
01039     RCP<Thyra::LinearNonlinearSolver<Scalar> >
01040       linearNonlinearSolver(new Thyra::LinearNonlinearSolver<Scalar>);
01041     // ToDo: Set tolerance on the nonlinear solver???
01042     sensTimeStepSolver_ = linearNonlinearSolver;
01043   }
01044 
01045   //
01046   // Setup the steppers
01047   //
01048 
01049   isSingleResidualStepper_ = true; // ToDo: Add dynamic cast on
01050                                    // stateTimeStepSolver to check this!
01051 
01052   stateStepper_->setModel(stateModel_);
01053   rcp_dynamic_cast<SolverAcceptingStepperBase<Scalar> >(
01054     stateStepper_,true)->setSolver(stateTimeStepSolver_);
01055   sensStepper_->setModel(sensModel_);
01056   rcp_dynamic_cast<SolverAcceptingStepperBase<Scalar> >(
01057     sensStepper_,true)->setSolver(sensTimeStepSolver_);
01058 
01059   stateBasePoint_t_ = stateModel_->createInArgs();
01060 
01061   // 2007/05/18: rabartl: ToDo: Move the above initialization code to give
01062   // setInitializeCondition(...) a chance to set the initial condition.
01063 
01064 }
01065 
01066 
01067 template<class Scalar> 
01068 Scalar ForwardSensitivityStepper<Scalar>::takeSyncedStep(
01069   Scalar dt, StepSizeType stepType
01070   )
01071 {
01072 
01073 #ifdef ENABLE_RYTHMOS_TIMERS
01074   TEUCHOS_FUNC_TIME_MONITOR("Rythmos:ForwardSensitivityStepper::takeStep: synced");
01075 #endif
01076 
01077   using Teuchos::as;
01078   typedef Teuchos::ScalarTraits<Scalar> ST;
01079   typedef Teuchos::VerboseObjectTempState<InterpolationBufferBase<Scalar> > VOTSIBB;
01080   typedef Thyra::ModelEvaluatorBase MEB;
01081 
01082   RCP<Teuchos::FancyOStream> out = this->getOStream();
01083   Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
01084   const bool lowTrace =
01085     ( !is_null(out) && as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW) );
01086   const bool mediumTrace =
01087     ( !is_null(out) && as<int>(verbLevel) >= as<int>(Teuchos::VERB_MEDIUM) );
01088   Teuchos::OSTab tab(out);
01089 
01090   if (lowTrace) {
01091     *out
01092       << "\nEntering " << TypeNameTraits<ForwardSensitivityStepper<Scalar> >::name()
01093       << "::takeSyncedStep("<<dt<<","<<toString(stepType)<<") ...\n"; 
01094   }
01095 
01096   //
01097   // A) Compute the state timestep
01098   //
01099 
01100   if (lowTrace) {
01101     *out
01102       << "\nTaking state step using stepper : "
01103       << stateStepper_->description() << "\n";
01104   }
01105 
01106   Scalar state_dt = -1.0;
01107   {
01108 #ifdef ENABLE_RYTHMOS_TIMERS
01109     TEUCHOS_FUNC_TIME_MONITOR("Rythmos:ForwardSensitivityStepper::takeStep: stateStep");
01110 #endif
01111     VOTSIBB stateStepper_outputTempState(stateStepper_,out,verbLevel);
01112     state_dt = stateStepper_->takeStep(dt,stepType);
01113   }
01114 
01115   if (state_dt < Scalar(-ST::one())) {
01116     if (lowTrace)
01117       *out << "\nThe state stepper has failed so return a failed timestep!\n";
01118     return state_dt;
01119   }
01120   
01121   const StepStatus<Scalar> stateStepStatus = stateStepper_->getStepStatus();
01122   if (mediumTrace)
01123     *out << "\nState step status:\n" << stateStepStatus;
01124 
01125   //
01126   // B) Setup the sensitivity model for this timestep
01127   //
01128 
01129   {
01130 
01131 #ifdef ENABLE_RYTHMOS_TIMERS
01132     TEUCHOS_FUNC_TIME_MONITOR("Rythmos:ForwardSensitivityStepper::takeStep: updateSensModel");
01133 #endif
01134     
01135     TEST_FOR_EXCEPTION(
01136       stateStepStatus.stepStatus != STEP_STATUS_CONVERGED, std::logic_error,
01137       "Error, the status should be converged since a positive step size was returned!"
01138       );
01139     
01140     const Scalar curr_t = stateStepStatus.time;
01141     
01142     // Get both x and x_dot since these are needed compute other derivative
01143     // objects at these points.
01144 
01145     RCP<const Thyra::VectorBase<Scalar> > x, x_dot;
01146     get_x_and_x_dot(*stateStepper_,curr_t,&x,&x_dot);
01147     
01148     stateBasePoint_t_ = stateBasePoint_;
01149     stateBasePoint_t_.set_x_dot( x_dot );
01150     stateBasePoint_t_.set_x( x );
01151     stateBasePoint_t_.set_t( curr_t );
01152 
01153     // Grab the SingleResidualModel that was used to compute the state timestep.
01154     // From this, we can get the constants that where used to compute W!
01155     RCP<const Rythmos::SingleResidualModelEvaluatorBase<Scalar> >
01156       singleResidualModel
01157       = Teuchos::rcp_dynamic_cast<const Rythmos::SingleResidualModelEvaluatorBase<Scalar> >(
01158         stateTimeStepSolver_->getModel(), true
01159         );
01160     const Scalar
01161       coeff_x_dot = singleResidualModel->get_coeff_x_dot(),
01162       coeff_x = singleResidualModel->get_coeff_x();
01163     
01164     // Get W (and force an update if not up to date already)
01165 
01166     if (mediumTrace && forceUpToDateW_)
01167       *out << "\nForcing an update of W at the converged state timestep ...\n";
01168     
01169     RCP<Thyra::LinearOpWithSolveBase<Scalar> >
01170       W_tilde = stateTimeStepSolver_->get_nonconst_W(forceUpToDateW_);
01171     
01172     TEST_FOR_EXCEPTION(
01173       is_null(W_tilde), std::logic_error,
01174       "Error, the W from the state time step be non-null!"
01175       );
01176     
01177     sensModel_->initializeState( stateBasePoint_t_, W_tilde, coeff_x_dot, coeff_x );
01178 
01179   }
01180   // 2007/09/04: rabartl: ToDo: Move the above code that initializes the
01181   // senstivity stepper from the state stepper as a strategy object that can
01182   // be redefined.  This will allow me to make this class 100% general for all
01183   // time stepper methods ... Including explicit steppers!
01184 
01185   //
01186   // C) Compute the sensitivity timestep for the exact same timestep as was
01187   // used for the state solve.
01188   //
01189 
01190   if (lowTrace) {
01191     *out
01192       << "\nTaking sensitivity step using stepper : "
01193       << sensStepper_->description() << "\n";
01194   }
01195 
01196   Scalar sens_dt = -1.0;
01197   {
01198 #ifdef ENABLE_RYTHMOS_TIMERS
01199     TEUCHOS_FUNC_TIME_MONITOR("Rythmos:ForwardSensitivityStepper::takeStep: sensStep");
01200 #endif
01201     // Copy the step control data to make sure that the sensStepper takes the
01202     // same type of step that the statStepper took.  This is needed to ensure
01203     // that the W matrix is the same for one.
01204     sensStepper_->setStepControlData(*stateStepper_);
01205     VOTSIBB sensStepper_outputTempState(sensStepper_,out,verbLevel);
01206     sens_dt = sensStepper_->takeStep(state_dt,STEP_TYPE_FIXED);
01207   }
01208 
01209   if (mediumTrace) {
01210     const StepStatus<Scalar> sensStepStatus = sensStepper_->getStepStatus();
01211     *out << "\nSensitivity step status:\n" << sensStepStatus;
01212   }
01213   
01214   TEST_FOR_EXCEPTION(
01215     sens_dt != state_dt, std::logic_error,
01216     "Error, the sensitivity step failed for some reason.  We should\n"
01217     "just return a negative step size and reject the step but currently\n"
01218     "there is no way to roll back the state timestep it for back to\n"
01219     "the status before this function was called!"
01220     );
01221 
01222   // 2007/05/18: rabartl: ToDo: If stepType == STEP_TYPE_VARIABLE and the state
01223   // timestep sucessed but the sensitivity timestep failed, then we need to
01224   // really throw an excpetion because there is nothing that we can really do
01225   // here!
01226 
01227   // 2007/05/18: rabartl: ToDo: Replace the above std::logic_error type with
01228   // a Rythmos::CatastrophicFailure or just use Thyra::CatastrophicFailure!
01229 
01230   if (lowTrace) {
01231     *out
01232       << "\nLeaving " << TypeNameTraits<ForwardSensitivityStepper<Scalar> >::name()
01233       << "::takeSyncedStep("<<dt<<","<<toString(stepType)<<") ...\n"; 
01234   }
01235 
01236   return state_dt;
01237 
01238 }
01239 
01240 
01241 template<class Scalar> 
01242 Scalar ForwardSensitivityStepper<Scalar>::takeDecoupledStep(
01243   Scalar dt, StepSizeType stepType
01244   )
01245 {
01246 
01247 #ifdef ENABLE_RYTHMOS_TIMERS
01248   TEUCHOS_FUNC_TIME_MONITOR("Rythmos:ForwardSensitivityStepper::takeStep: decoupled");
01249 #endif
01250 
01251   using Teuchos::as;
01252   typedef Teuchos::ScalarTraits<Scalar> ST;
01253   typedef Teuchos::VerboseObjectTempState<InterpolationBufferBase<Scalar> > VOTSIBB;
01254   typedef Thyra::ModelEvaluatorBase MEB;
01255 
01256   RCP<Teuchos::FancyOStream> out = this->getOStream();
01257   Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
01258   const bool lowTrace =
01259     ( !is_null(out) && as<int>(verbLevel) >= as<int>(Teuchos::VERB_LOW) );
01260   const bool mediumTrace =
01261     ( !is_null(out) && as<int>(verbLevel) >= as<int>(Teuchos::VERB_MEDIUM) );
01262   Teuchos::OSTab tab(out);
01263 
01264   if (lowTrace) {
01265     *out
01266       << "\nEntering " << TypeNameTraits<ForwardSensitivityStepper<Scalar> >::name()
01267       << "::takeDecoupledStep("<<dt<<","<<toString(stepType)<<") ...\n"; 
01268   }
01269   
01270   //
01271   // A) Take the sens timestep
01272   //
01273 
01274   if (lowTrace) {
01275     *out
01276       << "\nTaking sensitivity step using stepper : "
01277       << sensStepper_->description() << "\n";
01278   }
01279 
01280   Scalar sens_dt = -1.0;
01281   VOTSIBB sensStepper_outputTempState(sensStepper_,out,verbLevel);
01282   sens_dt = sensStepper_->takeStep(dt,stepType);
01283 
01284   if (mediumTrace) {
01285     const StepStatus<Scalar> sensStepStatus = sensStepper_->getStepStatus();
01286     *out << "\nSensitivity step status:\n" << sensStepStatus;
01287   }
01288 
01289   //
01290   // B) Wipe out all state interp buffer info before this sens timestep
01291   //
01292   
01293   //TEST_FOR_EXCEPT(true);
01294 
01295   if (lowTrace) {
01296     *out
01297       << "\nLeaving " << TypeNameTraits<ForwardSensitivityStepper<Scalar> >::name()
01298       << "::takeDecoupledStep("<<dt<<","<<toString(stepType)<<") ...\n"; 
01299   }
01300 
01301   return sens_dt;
01302   
01303 }
01304 
01305 
01306 } // namespace Rythmos
01307 
01308 
01309 #endif //RYTHMOS_FORWARD_SENSITIVITY_STEPPER_HPP
 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