TEUCHOS_UNIT_TEST( Rythmos_ForwardSensitivityExplicitModelEvaluator, args ) {
  RCP<ForwardSensitivityExplicitModelEvaluator<double> > model =
    forwardSensitivityExplicitModelEvaluator<double>();
  RCP<SinCosModel> innerModel = sinCosModel();
  {
    RCP<ParameterList> pl = Teuchos::parameterList();
    pl->set("Accept model parameters",true);
    pl->set("Implicit model formulation",false);
    innerModel->setParameterList(pl);
  }
  model->initializeStructure(innerModel, 0 );
  typedef Thyra::ModelEvaluatorBase MEB;
  {
    MEB::InArgs<double> inArgs = model->createInArgs();
    TEST_EQUALITY_CONST( inArgs.supports(MEB::IN_ARG_t), true );
    TEST_EQUALITY_CONST( inArgs.supports(MEB::IN_ARG_x), true );
    TEST_EQUALITY_CONST( inArgs.supports(MEB::IN_ARG_x_dot), false );
    TEST_EQUALITY_CONST( inArgs.supports(MEB::IN_ARG_alpha), false );
    TEST_EQUALITY_CONST( inArgs.supports(MEB::IN_ARG_beta), true );
  }
  {
    MEB::OutArgs<double> outArgs = model->createOutArgs();
    TEST_EQUALITY_CONST( outArgs.supports(MEB::OUT_ARG_f), true );
    TEST_EQUALITY_CONST( outArgs.supports(MEB::OUT_ARG_W_op), false );
    TEST_EQUALITY_CONST( outArgs.supports(MEB::OUT_ARG_W), false );
  }
}
TEUCHOS_UNIT_TEST( Rythmos_ThetaStepper, createImplicitEuler) {
  // Model
  RCP<SinCosModel> model = sinCosModel(true);

  RCP<ParameterList> modelPL = 
    Teuchos::getParametersFromXmlFile("modelParams.xml");
  modelPL->validateParametersAndSetDefaults(*model->getValidParameters());

  Thyra::ModelEvaluatorBase::InArgs<double> ic = model->getNominalValues();

  // Solver
  RCP<TimeStepNonlinearSolver<double> > solver = 
    timeStepNonlinearSolver<double>();

  // test reading params from .xml file
  RCP<ParameterList> stepperParamList = 
    Teuchos::getParametersFromXmlFile("implicitEulerParams.xml");

  // Stepper
  RCP<ThetaStepper<double> > stepper = 
    thetaStepper<double>(model, solver, stepperParamList);
  TEST_ASSERT( !is_null(stepper) );

  stepper->setInitialCondition(ic);

  // for testing purposes only
  stepper->setVerbLevel(Teuchos::VERB_EXTREME);

  double dt = 1.0;
  double dt_taken = 0.0;
  TEST_NOTHROW( dt_taken = stepper->takeStep(dt,STEP_TYPE_FIXED) );
  TEST_EQUALITY_CONST( dt_taken, dt );
}
 RCP<StepperBase<double> > create() const 
 { 
   RCP<SinCosModel> model = sinCosModel(false);
   RCP<ExplicitTaylorPolynomialStepper<double> > stepper = Teuchos::rcp(new ExplicitTaylorPolynomialStepper<double>);
   stepper->setModel(model);
   RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
   stepper->setParameterList(pl);
   return stepper;
 }
TEUCHOS_UNIT_TEST( Rythmos_BackwardEulerStepper, momento_create ) {
  RCP<const MomentoBase<double> > momento;
  {
    RCP<BackwardEulerStepper<double> > stepper = backwardEulerStepper<double>();
    RCP<SinCosModel> model = sinCosModel(true);
    stepper->setModel(model);
    momento = stepper->getMomento();
    TEST_ASSERT( !is_null(momento) );
  }
  {
    RCP<SinCosModel> model = sinCosModel(true);
    RCP<BackwardEulerStepper<double> > stepper = backwardEulerStepper<double>();
    stepper->setMomento(momento.ptr(),model,Teuchos::null);
    momento = Teuchos::null;
    RCP<const Thyra::ModelEvaluator<double> > modelOut = stepper->getModel();
    TEST_ASSERT( !is_null(modelOut) );
    RCP<const SinCosModel> scModel = Teuchos::rcp_dynamic_cast<const SinCosModel>(modelOut,false);
    TEST_ASSERT( !is_null(scModel) );
  }
}
TEUCHOS_UNIT_TEST( Rythmos_ForwardSensitivityExplicitModelEvaluator, spaces ) {
  RCP<ForwardSensitivityExplicitModelEvaluator<double> > model =
    forwardSensitivityExplicitModelEvaluator<double>();
  RCP<SinCosModel> innerModel = sinCosModel();
  {
    RCP<ParameterList> pl = Teuchos::parameterList();
    pl->set("Accept model parameters",true);
    pl->set("Implicit model formulation",false);
    innerModel->setParameterList(pl);
  }
  model->initializeStructure(innerModel, 0 );
  // x_space:
  {
    RCP<const Thyra::VectorSpaceBase<double> > x_space = model->get_x_space();
    TEST_EQUALITY_CONST( x_space->dim(), 6 );
    RCP<VectorBase<double> > x = createMember(*x_space);
    RCP<Thyra::DefaultMultiVectorProductVector<double> >
      x_bar = Teuchos::rcp_dynamic_cast<Thyra::DefaultMultiVectorProductVector<double> >(
        x, false
        );
    TEST_ASSERT( !is_null(x_bar) );
    RCP<Thyra::MultiVectorBase<double> > X = x_bar->getNonconstMultiVector();
    // Test that the vectors produced have the right number of columns
    TEST_EQUALITY_CONST( X->domain()->dim(), 3 );
    // Test that the vectors produced have the right number of rows
    TEST_EQUALITY_CONST( X->range()->dim(), 2 );
  }
  // f_space:
  {
    RCP<const Thyra::VectorSpaceBase<double> > f_space = model->get_f_space();
    TEST_EQUALITY_CONST( f_space->dim(), 6 );
    RCP<VectorBase<double> > f = createMember(*f_space);
    RCP<Thyra::DefaultMultiVectorProductVector<double> >
      f_bar = Teuchos::rcp_dynamic_cast<Thyra::DefaultMultiVectorProductVector<double> >(
        f, false
        );
    TEST_ASSERT( !is_null(f_bar) );
    RCP<Thyra::MultiVectorBase<double> > F = f_bar->getNonconstMultiVector();
    // Test that the vectors produced have the right number of columns
    TEST_EQUALITY_CONST( F->domain()->dim(), 3 );
    // Test that the vectors produced have the right number of rows
    TEST_EQUALITY_CONST( F->range()->dim(), 2 );
  }
}
TEUCHOS_UNIT_TEST( Rythmos_ThetaStepper, createTrapezoid) {
  // Model
  RCP<SinCosModel> model = sinCosModel(true);

  RCP<ParameterList> modelPL = 
    Teuchos::getParametersFromXmlFile("modelParams.xml");
  modelPL->validateParametersAndSetDefaults(*model->getValidParameters());

  Thyra::ModelEvaluatorBase::InArgs<double> ic = model->getNominalValues();

  // Solver
  RCP<TimeStepNonlinearSolver<double> > solver = 
    timeStepNonlinearSolver<double>();

  // test generating internal param list
  RCP<ParameterList> stepperParamList = Teuchos::parameterList();
  ParameterList& pl = stepperParamList->sublist("Step Control Settings");
  pl.set("Theta Stepper Type", "Trapezoid");

  //RCP<ParameterList> stepperParamList = 
  //  Teuchos::getParametersFromXmlFile("trapezoidParams.xml");

  // Stepper
  RCP<ThetaStepper<double> > stepper = 
    thetaStepper<double>(model, solver, stepperParamList);
  TEST_ASSERT( !is_null(stepper) );

  stepper->setInitialCondition(ic);

  // for testing purposes only
  stepper->setVerbLevel(Teuchos::VERB_EXTREME);

  double dt = 1.0;
  double dt_taken = 0.0;
  TEST_NOTHROW( dt_taken = stepper->takeStep(dt,STEP_TYPE_FIXED) );
  TEST_EQUALITY_CONST( dt_taken, dt );

  // take extra steps to verify 2nd order method is working
  TEST_NOTHROW( dt_taken = stepper->takeStep(dt,STEP_TYPE_FIXED) );
  TEST_EQUALITY_CONST( dt_taken, dt );

  TEST_NOTHROW( dt_taken = stepper->takeStep(dt,STEP_TYPE_FIXED) );
  TEST_EQUALITY_CONST( dt_taken, dt );
}
TEUCHOS_UNIT_TEST( Rythmos_BackwardEulerStepper, restart ) {
  RCP<const MomentoBase<double> > stepper_momento;
  // place to store solution at time = 1.0
  RCP<const VectorBase<double> > x_norestart; 
  RCP<const VectorBase<double> > xdot_norestart;
  // Create Backward Euler stepper
  // Step to t = 0.5, pull out the momento, then step the rest of the way to t = 1.0.
  {
    RCP<SinCosModel> model = sinCosModel(true);
    Thyra::ModelEvaluatorBase::InArgs<double> model_ic = model->getNominalValues();
    RCP<Thyra::NonlinearSolverBase<double> > neSolver = timeStepNonlinearSolver<double>();
    RCP<BackwardEulerStepper<double> > stepper = backwardEulerStepper<double>(model,neSolver);
    stepper->setInitialCondition(model_ic);
    double dt = 0.1;
    // Step to t=0.5
    for (int i=0 ; i<5 ; ++i) {
      double dt_taken = stepper->takeStep(dt,STEP_TYPE_FIXED);
      TEST_ASSERT( dt_taken == dt );
    }
    // Pull out the momento
    stepper_momento = stepper->getMomento();
    // Step to t=1.0
    for (int i=0 ; i<5 ; ++i) {
      double dt_taken = stepper->takeStep(dt,STEP_TYPE_FIXED);
      TEST_ASSERT( dt_taken == dt );
    }
    {
      // Pull out the final solution
      Array<double> time_vec;
      time_vec.push_back(1.0);
      Array<RCP<const VectorBase<double> > > x_vec;
      Array<RCP<const VectorBase<double> > > xdot_vec;
      Array<double> accuracy_vec;
      stepper->getPoints(time_vec,&x_vec,&xdot_vec,&accuracy_vec);
      x_norestart = x_vec[0];
      xdot_norestart = xdot_vec[0];
    }
  }
  // Create a new Backward Euler Stepper
  {
    RCP<BackwardEulerStepper<double> > stepper = backwardEulerStepper<double>();
    RCP<SinCosModel> model = sinCosModel(true);
    RCP<Thyra::NonlinearSolverBase<double> > neSolver = timeStepNonlinearSolver<double>();
    // Put the momento back into the stepper
    stepper->setMomento(stepper_momento.ptr(),model,neSolver);

    double dt = 0.1;
    // Step to t=1.0
    for (int i=0 ; i<5 ; ++i) {
      double dt_taken = stepper->takeStep(dt,STEP_TYPE_FIXED);
      TEST_ASSERT( dt_taken == dt );
    }
    {
      // Pull out the final solution after restart
      Array<double> time_vec;
      time_vec.push_back(1.0);
      Array<RCP<const VectorBase<double> > > x_vec;
      Array<RCP<const VectorBase<double> > > xdot_vec;
      Array<double> accuracy_vec;
      stepper->getPoints(time_vec,&x_vec,&xdot_vec,&accuracy_vec);
      RCP<const VectorBase<double> > x_restart = x_vec[0];
      RCP<const VectorBase<double> > xdot_restart = xdot_vec[0];

      // Verify that x_restart == x_norestart
      RCP<VectorBase<double> > x_diff = createMember(x_restart->space());
      V_VmV( x_diff.ptr(), *x_norestart, *x_restart );
      double x_normDiff = norm(*x_diff);
      double tol = 1.0e-10;
      TEST_COMPARE( x_normDiff, <, tol );

      // Verify that xdot_restart == xdot_norestart
      RCP<VectorBase<double> > xdot_diff = createMember(x_restart->space());
      V_VmV( xdot_diff.ptr(), *xdot_norestart, *xdot_restart );
      double xdot_normDiff = norm(*xdot_diff);
      TEST_COMPARE( xdot_normDiff, <, tol );

    }
  }
}
TEUCHOS_UNIT_TEST( Rythmos_BackwardEulerStepper, checkConsistentState ) {
  {
    RCP<SinCosModel> model = sinCosModel(true);
    Thyra::ModelEvaluatorBase::InArgs<double> model_ic = model->getNominalValues();
    RCP<Thyra::NonlinearSolverBase<double> > neSolver = timeStepNonlinearSolver<double>();
    RCP<BackwardEulerStepper<double> > stepper = backwardEulerStepper<double>(model,neSolver);
    stepper->setInitialCondition(model_ic);
    double dt = 0.1;
    double dt_taken = stepper->takeStep(dt,STEP_TYPE_FIXED);
    TEST_ASSERT( dt == dt_taken );
    RCP<const MomentoBase<double> > momento = stepper->getMomento();
    TEST_THROW(stepper->setMomento(momento.ptr(),Teuchos::null,Teuchos::null), std::logic_error);
    TEST_THROW(stepper->setMomento(momento.ptr(),model,Teuchos::null), std::logic_error);
    TEST_THROW(stepper->setMomento(momento.ptr(),Teuchos::null,neSolver), std::logic_error);
    TEST_NOTHROW(stepper->setMomento(momento.ptr(),model,neSolver));
  }
  {
    // Initialize a valid non-const momento:
    RCP<BackwardEulerStepperMomento<double> > momento;
    {
      RCP<SinCosModel> model = sinCosModel(true);
      Thyra::ModelEvaluatorBase::InArgs<double> model_ic = model->getNominalValues();
      RCP<Thyra::NonlinearSolverBase<double> > neSolver = timeStepNonlinearSolver<double>();
      RCP<BackwardEulerStepper<double> > stepper = backwardEulerStepper<double>(model,neSolver);
      stepper->setInitialCondition(model_ic);
      double dt = 0.1;
      double dt_taken = stepper->takeStep(dt,STEP_TYPE_FIXED);
      TEST_ASSERT( dt == dt_taken );
      RCP<const MomentoBase<double> > m = stepper->getMomento();
      RCP<const BackwardEulerStepperMomento<double> > beMomento = Teuchos::rcp_dynamic_cast<const BackwardEulerStepperMomento<double> >(m,true);
      momento = Teuchos::rcp_dynamic_cast<BackwardEulerStepperMomento<double> >(beMomento->clone(),true);
    }
    {
      // Check if isInitialized_ == true, but 
      // model_ = null or solver = null or haveInitialCondition_ = false or interpolator = null
      RCP<BackwardEulerStepperMomento<double> > m = Teuchos::rcp_dynamic_cast<BackwardEulerStepperMomento<double> >(momento->clone(),true);
      RCP<BackwardEulerStepper<double> > stepper = backwardEulerStepper<double>();
      RCP<SinCosModel> model = sinCosModel(true);
      RCP<Thyra::NonlinearSolverBase<double> > neSolver = timeStepNonlinearSolver<double>();
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));
      TEST_THROW(stepper->setMomento(m.ptr(),Teuchos::null,neSolver),std::logic_error);
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));
      TEST_THROW(stepper->setMomento(m.ptr(),model,Teuchos::null),std::logic_error);
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));
      m->set_haveInitialCondition(false);
      TEST_THROW(stepper->setMomento(m.ptr(),model,neSolver),std::logic_error);
      m->set_haveInitialCondition(true);
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));
      RCP<InterpolatorBase<double> > interp = m->get_interpolator();
      m->set_interpolator(Teuchos::null);
      TEST_THROW(stepper->setMomento(m.ptr(),model,neSolver),std::logic_error);
      m->set_interpolator(interp);
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));
    }
    {
      // Check if haveInitialCondition_ == true, but 
      // t_ == nan or 
      // t_old_ == nan or 
      // scaled_x_old == null or 
      // x_dot_old == null or
      // x == null or 
      // x_dot == null
      typedef Teuchos::ScalarTraits<double> ST;
      RCP<BackwardEulerStepperMomento<double> > m = Teuchos::rcp_dynamic_cast<BackwardEulerStepperMomento<double> >(momento->clone(),true);
      RCP<BackwardEulerStepper<double> > stepper = backwardEulerStepper<double>();
      RCP<SinCosModel> model = sinCosModel(true);
      RCP<Thyra::NonlinearSolverBase<double> > neSolver = timeStepNonlinearSolver<double>();
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));

      double t = m->get_t();
      m->set_t(ST::nan());
      TEST_THROW(stepper->setMomento(m.ptr(),model,neSolver),std::logic_error);
      m->set_t(t);
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));

      double t_old = m->get_t_old();
      m->set_t_old(ST::nan());
      TEST_THROW(stepper->setMomento(m.ptr(),model,neSolver),std::logic_error);
      m->set_t_old(t_old);
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));

      RCP<VectorBase<double> > scaled_x_old = m->get_scaled_x_old();
      m->set_scaled_x_old(Teuchos::null);
      TEST_THROW(stepper->setMomento(m.ptr(),model,neSolver),std::logic_error);
      m->set_scaled_x_old(scaled_x_old);
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));

      RCP<VectorBase<double> > x_dot_old = m->get_x_dot_old();
      m->set_x_dot_old(Teuchos::null);
      TEST_THROW(stepper->setMomento(m.ptr(),model,neSolver),std::logic_error);
      m->set_x_dot_old(x_dot_old);
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));

      RCP<VectorBase<double> > x = m->get_x();
      m->set_x(Teuchos::null);
      TEST_THROW(stepper->setMomento(m.ptr(),model,neSolver),std::logic_error);
      m->set_x(x);
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));

      RCP<VectorBase<double> > x_dot = m->get_x_dot();
      m->set_x_dot(Teuchos::null);
      TEST_THROW(stepper->setMomento(m.ptr(),model,neSolver),std::logic_error);
      m->set_x_dot(x_dot);
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));
    }
    {
      // Check that if numSteps_ > 0 then isInitialized_ == true and haveInitialCondition_ == true
      RCP<BackwardEulerStepperMomento<double> > m = Teuchos::rcp_dynamic_cast<BackwardEulerStepperMomento<double> >(momento->clone(),true);
      TEST_ASSERT( m->get_numSteps() == 1 );
      RCP<BackwardEulerStepper<double> > stepper = backwardEulerStepper<double>();
      RCP<SinCosModel> model = sinCosModel(true);
      RCP<Thyra::NonlinearSolverBase<double> > neSolver = timeStepNonlinearSolver<double>();
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));

      m->set_isInitialized(false);
      TEST_THROW(stepper->setMomento(m.ptr(),model,neSolver),std::logic_error);
      m->set_isInitialized(true);
      TEST_NOTHROW(stepper->setMomento(m.ptr(),model,neSolver));
    }
  }
}
TEUCHOS_UNIT_TEST( Rythmos_ImplicitBDFStepper, exactNumericalAnswer_BE ) {
  double a = 1.5;
  double f = 1.6;
  double L = 1.7;
  RCP<ParameterList> modelPL = Teuchos::parameterList();
  {
    modelPL->set("Implicit model formulation",true);
    modelPL->set("Coeff a",a);
    modelPL->set("Coeff f",f);
    modelPL->set("Coeff L",L);
  }
  RCP<SinCosModel> model = sinCosModel();
  model->setParameterList(modelPL);
  Thyra::ModelEvaluatorBase::InArgs<double> model_ic = model->getNominalValues();
  RCP<TimeStepNonlinearSolver<double> > nlSolver = timeStepNonlinearSolver<double>();
  RCP<ParameterList> stepperPL = Teuchos::parameterList();
  {
    ParameterList& pl = stepperPL->sublist("Step Control Settings");
    pl.set("minOrder",1);
    pl.set("maxOrder",1);
    ParameterList& vopl = pl.sublist("VerboseObject");
    vopl.set("Verbosity Level","none");
  }
  RCP<ImplicitBDFStepper<double> > stepper = implicitBDFStepper<double>(model,nlSolver,stepperPL);
  stepper->setInitialCondition(model_ic);
  // Take a few steps and compare the output.
  int N = 3;
  double dt = 0.1;
  double x_exact_0 = 0.0;
  double x_exact_1 = 1.0;
  for (int i=1 ; i<=N ; ++i) {
    double t = i*dt;
    double dt_taken = stepper->takeStep(dt,STEP_TYPE_FIXED);
    TEST_ASSERT( dt_taken == dt );
    RCP<const VectorBase<double> > x;
    RCP<const VectorBase<double> > xdot;
    {
      // Get x out of stepper.
      Array<double> t_vec;
      Array<RCP<const VectorBase<double> > > x_vec;
      Array<RCP<const VectorBase<double> > > xdot_vec;
      t_vec.resize(1); t_vec[0] = t;
      stepper->getPoints(t_vec,&x_vec,&xdot_vec,NULL);
      x = x_vec[0];
      xdot = xdot_vec[0];
    }
    // Compute exact solution:
    double c = dt/(1+f*f*dt*dt/(L*L));
    double x_e_0 = c*(x_exact_0/dt + x_exact_1 + dt*f*f/(L*L)*a);
    double x_e_1 = c*(-f*f/(L*L)*x_exact_0 + x_exact_1/dt + f*f/(L*L)*a);
    double xd_e_0 = (x_e_0-x_exact_0)/dt;
    double xd_e_1 = (x_e_1-x_exact_1)/dt;
    double tol = 1.0e-12;
    {
      Thyra::ConstDetachedVectorView<double> x_view( *x );
      TEST_FLOATING_EQUALITY( x_view[0], x_e_0, tol );
      TEST_FLOATING_EQUALITY( x_view[1], x_e_1, tol );

      Thyra::ConstDetachedVectorView<double> xdot_view( *xdot );
      TEST_FLOATING_EQUALITY( xdot_view[0], xd_e_0, tol );
      TEST_FLOATING_EQUALITY( xdot_view[1], xd_e_1, tol );
    }
    x_exact_0 = x_e_0;
    x_exact_1 = x_e_1;
  }
}
TEUCHOS_UNIT_TEST( Rythmos_ForwardSensitivityExplicitModelEvaluator, evalModel ) {
  typedef Thyra::ModelEvaluatorBase MEB;
  RCP<ForwardSensitivityExplicitModelEvaluator<double> > model =
    forwardSensitivityExplicitModelEvaluator<double>();
  RCP<SinCosModel> innerModel = sinCosModel(false);
  double a = 0.4;
  double f = 1.5;
  double L = 1.6;
  {
    RCP<ParameterList> pl = Teuchos::parameterList();
    pl->set("Accept model parameters",true);
    pl->set("Implicit model formulation",false);
    pl->set("Coeff a", a );
    pl->set("Coeff f", f );
    pl->set("Coeff L", L );
    innerModel->setParameterList(pl);
  }
  model->initializeStructure(innerModel, 0 );
  RCP<VectorBase<double> > x;
  MEB::InArgs<double> pointInArgs;  // Used to change the solution for re-evaluation
  RCP<StepperBase<double> > stepper; // Used for initializePointState
  {
    pointInArgs = innerModel->createInArgs();
    pointInArgs.set_t(0.1);
    x = Thyra::createMember(innerModel->get_x_space());
    {
      Thyra::DetachedVectorView<double> x_view( *x );
      x_view[0] = 2.0;
      x_view[1] = 3.0;
    }
    pointInArgs.set_x(x);
    RCP<VectorBase<double> > p0 = Thyra::createMember(innerModel->get_p_space(0));
    {
      Thyra::DetachedVectorView<double> p0_view( *p0 );
      p0_view[0] = a;
      p0_view[1] = f;
      p0_view[2] = L;
    }
    pointInArgs.set_p(0,p0);
    {
      // Create a stepper with these initial conditions to use to call
      // initializePointState on this ME:
      stepper = forwardEulerStepper<double>();
      stepper->setInitialCondition(pointInArgs);
      model->initializePointState(Teuchos::inOutArg(*stepper),false);
    }
  }
  MEB::InArgs<double> inArgs = model->createInArgs();
  RCP<VectorBase<double> > x_bar = Thyra::createMember(model->get_x_space());
  RCP<Thyra::DefaultMultiVectorProductVector<double> >
    s_bar = Teuchos::rcp_dynamic_cast<Thyra::DefaultMultiVectorProductVector<double> >(
      x_bar, true
      );
  RCP<Thyra::MultiVectorBase<double> >
    S = s_bar->getNonconstMultiVector();
  // Fill S with data
  {
    TEST_EQUALITY_CONST( S->domain()->dim(), 3 );
    TEST_EQUALITY_CONST( S->range()->dim(), 2 );
    RCP<VectorBase<double> > S0 = S->col(0);
    RCP<VectorBase<double> > S1 = S->col(1);
    RCP<VectorBase<double> > S2 = S->col(2);
    TEST_EQUALITY_CONST( S0->space()->dim(), 2 );
    TEST_EQUALITY_CONST( S1->space()->dim(), 2 );
    TEST_EQUALITY_CONST( S2->space()->dim(), 2 );
    Thyra::DetachedVectorView<double> S0_view( *S0 );
    S0_view[0] = 7.0;
    S0_view[1] = 8.0;
    Thyra::DetachedVectorView<double> S1_view( *S1 );
    S1_view[0] = 9.0;
    S1_view[1] = 10.0;
    Thyra::DetachedVectorView<double> S2_view( *S2 );
    S2_view[0] = 11.0;
    S2_view[1] = 12.0;
  }
  inArgs.set_x(x_bar);
  MEB::OutArgs<double> outArgs = model->createOutArgs();
  RCP<VectorBase<double> > f_bar = Thyra::createMember(model->get_f_space());
  RCP<Thyra::DefaultMultiVectorProductVector<double> >
    f_sens = Teuchos::rcp_dynamic_cast<Thyra::DefaultMultiVectorProductVector<double> >(
      f_bar, true
      );
  RCP<Thyra::MultiVectorBase<double> >
    F_sens = f_sens->getNonconstMultiVector().assert_not_null();

  V_S(Teuchos::outArg(*f_bar),0.0);
  outArgs.set_f(f_bar);
  
  inArgs.set_t(0.1);
  model->evalModel(inArgs,outArgs);

  // Verify F_sens = df/dx*S = df/dp
  // df/dx = [ 0             1 ]
  //         [ -(f/L)*(f/L)  0 ]
  // S =   [ 7   9  11 ]    x = [ 2 ]
  //       [ 8  10  12 ]        [ 3 ]
  // df/dp = [     0             0                   0              ]
  //         [ (f/L)*(f/L) 2*f/(L*L)*(a-x_0) -2*f*f/(L*L*L)*(a-x_0) ]
  // F_sens_0 = 
  // [            8               ]
  // [ -7*(f/L)*(f/L)+(f*f)/(L*L) ]
  // F_sens_1 = 
  // [            10                    ]
  // [ -9*(f/L)*(f/L)+2*f/(L*L)*(a-x_0) ]
  // F_sens_2 = 
  // [            12                         ]
  // [ -11*(f/L)*(f/L)-2*f*f/(L*L*L)*(a-x_0) ]
  // 
  double tol = 1.0e-10;
  {
    TEST_EQUALITY_CONST( F_sens->domain()->dim(), 3 );
    TEST_EQUALITY_CONST( F_sens->range()->dim(), 2 );
    RCP<VectorBase<double> > F_sens_0 = F_sens->col(0);
    RCP<VectorBase<double> > F_sens_1 = F_sens->col(1);
    RCP<VectorBase<double> > F_sens_2 = F_sens->col(2);
    TEST_EQUALITY_CONST( F_sens_0->space()->dim(), 2 );
    TEST_EQUALITY_CONST( F_sens_1->space()->dim(), 2 );
    TEST_EQUALITY_CONST( F_sens_2->space()->dim(), 2 );

    Thyra::DetachedVectorView<double> F_sens_0_view( *F_sens_0 );
    TEST_FLOATING_EQUALITY( F_sens_0_view[0], 8.0, tol );
    TEST_FLOATING_EQUALITY( F_sens_0_view[1], -7.0*(f/L)*(f/L)+(f*f)/(L*L), tol );

    Thyra::DetachedVectorView<double> F_sens_1_view( *F_sens_1 );
    TEST_FLOATING_EQUALITY( F_sens_1_view[0], 10.0, tol );
    TEST_FLOATING_EQUALITY( F_sens_1_view[1], -9*(f/L)*(f/L)+2*f/(L*L)*(a-2.0), tol );

    Thyra::DetachedVectorView<double> F_sens_2_view( *F_sens_2 );
    TEST_FLOATING_EQUALITY( F_sens_2_view[0], 12.0, tol );
    TEST_FLOATING_EQUALITY( F_sens_2_view[1], -11*(f/L)*(f/L)-2*f*f/(L*L*L)*(a-2.0), tol );
  }

  // Now change x and evaluate again.
  {
    Thyra::DetachedVectorView<double> x_view( *x );
    x_view[0] = 20.0;
    x_view[1] = 21.0;
  }
  // We need to call initializePointState again due to the vector
  // being cloned inside.
  stepper->setInitialCondition(pointInArgs);
  model->initializePointState(Teuchos::inOutArg(*stepper),false);

  model->evalModel(inArgs,outArgs);
  {
    TEST_EQUALITY_CONST( F_sens->domain()->dim(), 3 );
    TEST_EQUALITY_CONST( F_sens->range()->dim(), 2 );
    RCP<VectorBase<double> > F_sens_0 = F_sens->col(0);
    RCP<VectorBase<double> > F_sens_1 = F_sens->col(1);
    RCP<VectorBase<double> > F_sens_2 = F_sens->col(2);
    TEST_EQUALITY_CONST( F_sens_0->space()->dim(), 2 );
    TEST_EQUALITY_CONST( F_sens_1->space()->dim(), 2 );
    TEST_EQUALITY_CONST( F_sens_2->space()->dim(), 2 );

    Thyra::DetachedVectorView<double> F_sens_0_view( *F_sens_0 );
    TEST_FLOATING_EQUALITY( F_sens_0_view[0], 8.0, tol );
    TEST_FLOATING_EQUALITY( F_sens_0_view[1], -7.0*(f/L)*(f/L)+(f*f)/(L*L), tol );

    Thyra::DetachedVectorView<double> F_sens_1_view( *F_sens_1 );
    TEST_FLOATING_EQUALITY( F_sens_1_view[0], 10.0, tol );
    TEST_FLOATING_EQUALITY( F_sens_1_view[1], -9*(f/L)*(f/L)+2*f/(L*L)*(a-20.0), tol );

    Thyra::DetachedVectorView<double> F_sens_2_view( *F_sens_2 );
    TEST_FLOATING_EQUALITY( F_sens_2_view[0], 12.0, tol );
    TEST_FLOATING_EQUALITY( F_sens_2_view[1], -11*(f/L)*(f/L)-2*f*f/(L*L*L)*(a-20.0), tol );
  }

}
TEUCHOS_UNIT_TEST( Rythmos_GlobalErrorEstimator, SinCos ) {
  typedef Teuchos::ScalarTraits<double> ST;
  // Forward Solve, storing data in linear interpolation buffer
  int storageLimit = 100;
  double finalTime = 0.1;
  double dt = 0.1;
  RCP<IntegratorBuilder<double> > ib = integratorBuilder<double>();
  {
    RCP<ParameterList> ibPL = Teuchos::parameterList();
    ibPL->sublist("Integrator Settings").sublist("Integrator Selection").set("Integrator Type","Default Integrator");
    ibPL->sublist("Integrator Settings").set("Final Time",finalTime);
    ibPL->sublist("Integration Control Strategy Selection").set("Integration Control Strategy Type","Simple Integration Control Strategy");
    ibPL->sublist("Integration Control Strategy Selection").sublist("Simple Integration Control Strategy").set("Take Variable Steps",false);
    ibPL->sublist("Integration Control Strategy Selection").sublist("Simple Integration Control Strategy").set("Fixed dt",dt);

    ibPL->sublist("Stepper Settings").sublist("Stepper Selection").set("Stepper Type","Backward Euler");
    //ibPL->sublist("Stepper Settings").sublist("Stepper Selection").set("Stepper Type","Implicit RK");
    //ibPL->sublist("Stepper Settings").sublist("Runge Kutta Butcher Tableau Selection").set("Runge Kutta Butcher Tableau Type","Backward Euler");
    ibPL->sublist("Interpolation Buffer Settings").sublist("Trailing Interpolation Buffer Selection").set("Interpolation Buffer Type","Interpolation Buffer");
    ibPL->sublist("Interpolation Buffer Settings").sublist("Trailing Interpolation Buffer Selection").sublist("Interpolation Buffer").set("StorageLimit",storageLimit);
    ibPL->sublist("Interpolation Buffer Settings").sublist("Interpolator Selection").set("Interpolator Type","Linear Interpolator");
    ib->setParameterList(ibPL);
  }
  RCP<SinCosModel> fwdModel = sinCosModel(true); // implicit formulation
  Thyra::ModelEvaluatorBase::InArgs<double> fwdIC = fwdModel->getNominalValues();
  RCP<Thyra::NonlinearSolverBase<double> > fwdNLSolver = timeStepNonlinearSolver<double>();
  RCP<IntegratorBase<double> > fwdIntegrator = ib->create(fwdModel,fwdIC,fwdNLSolver);
  RCP<const VectorBase<double> > x_final;
  {
    Array<double> time_vec;
    time_vec.push_back(finalTime);
    Array<RCP<const Thyra::VectorBase<double> > > x_final_array;
    fwdIntegrator->getFwdPoints(time_vec,&x_final_array,NULL,NULL);
    x_final = x_final_array[0];
  }
  // Verify x_final is correct
  {
    // Defaults from SinCos Model:
    double f = 1.0;
    double L = 1.0;
    double a = 0.0;
    double x_ic_0 = 0.0;
    double x_ic_1 = 1.0;
    double x_0 = dt/(1.0+std::pow(dt*f/L,2))*(x_ic_0/dt+x_ic_1+dt*std::pow(f/L,2)*a);
    double x_1 = dt/(1.0+std::pow(dt*f/L,2))*(-std::pow(f/L,2)*x_ic_0+x_ic_1/dt+std::pow(f/L,2)*a);
    double tol = 1.0e-10;
    Thyra::ConstDetachedVectorView<double> x_final_view( *x_final );
    TEST_FLOATING_EQUALITY( x_final_view[0], x_0, tol );
    TEST_FLOATING_EQUALITY( x_final_view[1], x_1, tol );
  }
  // Copy InterpolationBuffer data into Cubic Spline interpolation buffer for use in Adjoint Solve
  TimeRange<double> fwdTimeRange; 
  RCP<InterpolationBufferBase<double> > fwdCubicSplineInterpBuffer;
  {
    RCP<PointwiseInterpolationBufferAppender<double> > piba = pointwiseInterpolationBufferAppender<double>();
    RCP<InterpolationBuffer<double> > sinkInterpBuffer = interpolationBuffer<double>();
    sinkInterpBuffer->setStorage(storageLimit);
    RCP<CubicSplineInterpolator<double> > csi = cubicSplineInterpolator<double>();
    sinkInterpBuffer->setInterpolator(csi);
    RCP<const InterpolationBufferBase<double> > sourceInterpBuffer;
    {
      RCP<TrailingInterpolationBufferAcceptingIntegratorBase<double> > tibaib = 
        Teuchos::rcp_dynamic_cast<TrailingInterpolationBufferAcceptingIntegratorBase<double> >(fwdIntegrator,true);
      sourceInterpBuffer = tibaib->getTrailingInterpolationBuffer();
    }
    fwdTimeRange = sourceInterpBuffer->getTimeRange();
    piba->append(*sourceInterpBuffer, fwdTimeRange, Teuchos::outArg(*sinkInterpBuffer));
    fwdCubicSplineInterpBuffer = sinkInterpBuffer;

    TimeRange<double> sourceRange = sourceInterpBuffer->getTimeRange();
    TimeRange<double> sinkRange = sinkInterpBuffer->getTimeRange();
    TEST_EQUALITY( sourceRange.lower(), sinkRange.lower() );
    TEST_EQUALITY( sourceRange.upper(), sinkRange.upper() );
  }
  // Adjoint Solve, reading forward solve data from Cubic Spline interpolation buffer
  {
    RCP<ParameterList> ibPL = Teuchos::parameterList();
    ibPL->sublist("Integrator Settings").sublist("Integrator Selection").set("Integrator Type","Default Integrator");
    ibPL->sublist("Integrator Settings").set("Final Time",finalTime);
    ibPL->sublist("Integration Control Strategy Selection").set("Integration Control Strategy Type","Simple Integration Control Strategy");
    ibPL->sublist("Integration Control Strategy Selection").sublist("Simple Integration Control Strategy").set("Take Variable Steps",false);
    ibPL->sublist("Integration Control Strategy Selection").sublist("Simple Integration Control Strategy").set("Fixed dt",dt);

    ibPL->sublist("Stepper Settings").sublist("Stepper Selection").set("Stepper Type","Backward Euler");
    //ibPL->sublist("Stepper Settings").sublist("Stepper Selection").set("Stepper Type","Implicit RK");
    //ibPL->sublist("Stepper Settings").sublist("Runge Kutta Butcher Tableau Selection").set("Runge Kutta Butcher Tableau Type","Implicit 1 Stage 2nd order Gauss");
    ibPL->sublist("Interpolation Buffer Settings").sublist("Trailing Interpolation Buffer Selection").set("Interpolation Buffer Type","Interpolation Buffer");
    ibPL->sublist("Interpolation Buffer Settings").sublist("Trailing Interpolation Buffer Selection").sublist("Interpolation Buffer").set("StorageLimit",storageLimit);
    ibPL->sublist("Interpolation Buffer Settings").sublist("Interpolator Selection").set("Interpolator Type","Linear Interpolator");
    ib->setParameterList(ibPL);
  }
  RCP<Thyra::ModelEvaluator<double> > adjModel;
  {
    RCP<Rythmos::AdjointModelEvaluator<double> > model = 
      Rythmos::adjointModelEvaluator<double>(
          fwdModel, fwdTimeRange
          );
    //model->setFwdStateSolutionBuffer(fwdCubicSplineInterpBuffer);
    adjModel = model;
  }
  Thyra::ModelEvaluatorBase::InArgs<double> adjIC = adjModel->getNominalValues();
  double phi_ic_0 = 2.0;
  double phi_ic_1 = 3.0;
  {
    // Initial conditions for adjoint:
    const RCP<const Thyra::VectorSpaceBase<double> >
      f_space = fwdModel->get_f_space();
    const RCP<Thyra::VectorBase<double> > x_ic = createMember(f_space);
    {
      Thyra::DetachedVectorView<double> x_ic_view( *x_ic );
      x_ic_view[0] = phi_ic_0;
      x_ic_view[1] = phi_ic_1;
    }
    const RCP<Thyra::VectorBase<double> > xdot_ic = createMember(f_space);
    V_S( Teuchos::outArg(*xdot_ic), ST::zero() );
    adjIC.set_x(x_ic);
    adjIC.set_x_dot(xdot_ic);
  }
  RCP<Thyra::LinearNonlinearSolver<double> > adjNLSolver = Thyra::linearNonlinearSolver<double>();
  RCP<IntegratorBase<double> > adjIntegrator = ib->create(adjModel,adjIC,adjNLSolver);
  RCP<const VectorBase<double> > phi_final;
  {
    Array<double> time_vec;
    time_vec.push_back(finalTime);
    Array<RCP<const Thyra::VectorBase<double> > > phi_final_array;
    adjIntegrator->getFwdPoints(time_vec,&phi_final_array,NULL,NULL);
    phi_final = phi_final_array[0];
  }
  // Verify phi_final is correct
  {
    // Defaults from SinCos Model:
    double f = 1.0;
    double L = 1.0;
    double h = -dt;
    double phi_0 = 1.0/(1.0+std::pow(f*h/L,2.0))*(phi_ic_0+std::pow(f/L,2.0)*h*phi_ic_1);
    double phi_1 = 1.0/(1.0+std::pow(f*h/L,2.0))*(-h*phi_ic_0+phi_ic_1);
    double tol = 1.0e-10;
    Thyra::ConstDetachedVectorView<double> phi_final_view( *phi_final );
    TEST_FLOATING_EQUALITY( phi_final_view[0], phi_0, tol );
    TEST_FLOATING_EQUALITY( phi_final_view[1], phi_1, tol );
  }
  // Compute error estimate
  //TEST_ASSERT( false );
}