Example #1
0
// Get a Kokkos::View of a Teuchos::ArrayView, and make sure that
// it points to the same data.  Thanks to Christian Trott for
// implementing the necessary functionality (View constructor for
// certain View specializations, that takes a raw pointer and
// dimensions) in Kokkos Array.
//
// This example will be useful for implementing the
// Tpetra::MultiVector methods get1dCopy and get2dCopy.
TEUCHOS_UNIT_TEST( LinkTeuchosAndKokkos, ViewOfArrayView ) {
  typedef Teuchos::Array<double>::size_type size_type;
  typedef Kokkos::View<double*, Kokkos::LayoutLeft, Kokkos::Threads, Kokkos::MemoryUnmanaged> ka_view_type;
  typedef Kokkos::View<const double*, Kokkos::LayoutLeft, Kokkos::Threads, Kokkos::MemoryUnmanaged> ka_const_view_type;

  const size_type numElts = 10;
  Teuchos::Array<double> x (numElts);
  for (size_type k = 0; k < numElts; ++k) {
    x[k] = 42.0 + static_cast<double> (k);
  }
  // You can make an (unmanaged) View of a raw array with left or
  // right (Fortran or C) layout on the HostSpace device, just by passing
  // the array and stride(s) into the constructor.  If you want the
  // dimensions to differ from the strides, you'll have to create a
  // subview with the desired dimensions.
  ka_view_type x_view (x.getRawPtr (), x.size ());

  TEST_EQUALITY( x.size(), static_cast<size_type>(x_view.dimension_0()) );
  for (size_type k = 0; k < x.size (); ++k) {
    TEST_EQUALITY( x_view[k], x[k] );
  }

  // This ensures that conversions from double* to const double* work correctly.
  // x.getRawPtr() returns double*.
  ka_const_view_type x_view_const ( (const double*) x.getRawPtr (), x.size ());

  TEST_EQUALITY( x.size(), static_cast<size_type>(x_view_const.dimension_0()) );
  for (size_type k = 0; k < x.size (); ++k) {
    TEST_EQUALITY( x_view_const[k], x[k] );
  }
}
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_ImplicitBDFStepper, exactNumericalAnswer_BE_nonlinear ) {
  double epsilon = 0.5;
  RCP<ParameterList> modelPL = Teuchos::parameterList();
  {
    modelPL->set("Implicit model formulation",true);
    modelPL->set("Coeff epsilon",epsilon);
  }
  RCP<VanderPolModel> model = vanderPolModel();
  model->setParameterList(modelPL);
  Thyra::ModelEvaluatorBase::InArgs<double> model_ic = model->getNominalValues();
  RCP<TimeStepNonlinearSolver<double> > nlSolver = timeStepNonlinearSolver<double>();
  {
    RCP<ParameterList> nlPL = Teuchos::parameterList();
    nlPL->set("Default Tol",1.0e-10);
    nlPL->set("Default Max Iters",20);
    nlSolver->setParameterList(nlPL);
  }
  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);
  double h = 0.1;
  std::vector<double> x_0_exact;
  std::vector<double> x_1_exact;
  std::vector<double> x_0_dot_exact;
  std::vector<double> x_1_dot_exact;
  {
    x_0_exact.push_back(2.0); // IC
    x_1_exact.push_back(0.0);

    x_0_exact.push_back(1.982896621392518e+00); // matlab 
    x_1_exact.push_back(-1.710337860748234e-01); 

    x_0_exact.push_back(1.951487185706842e+00); // matlab 
    x_1_exact.push_back(-3.140943568567556e-01); 
    
    x_0_exact.push_back(1.908249109758246e+00); // matlab 
    x_1_exact.push_back(-4.323807594859574e-01); 
    
    x_0_dot_exact.push_back(0.0);
    x_1_dot_exact.push_back(0.0);

    for ( int i=1 ; i< Teuchos::as<int>(x_0_exact.size()) ; ++i ) {
      x_0_dot_exact.push_back( (x_0_exact[i]-x_0_exact[i-1])/h );
      x_1_dot_exact.push_back( (x_1_exact[i]-x_1_exact[i-1])/h );
      //std::cout << "x_0_dot_exact["<<i<<"] = "<<x_0_dot_exact[i] << std::endl;
      //std::cout << "x_1_dot_exact["<<i<<"] = "<<x_1_dot_exact[i] << std::endl;
    }
  }
  double tol_discrete = 1.0e-12;
  double tol_continuous = 1.0e-2;
  {
    // Get IC out
    double t = 0.0;
    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];
    }
    {
      Thyra::ConstDetachedVectorView<double> x_view( *x );
      TEST_FLOATING_EQUALITY( x_view[0], x_0_exact[0], tol_discrete );
      TEST_FLOATING_EQUALITY( x_view[1], x_1_exact[0], tol_discrete );

      Thyra::ConstDetachedVectorView<double> xdot_view( *xdot );
      TEST_FLOATING_EQUALITY( xdot_view[0], x_0_dot_exact[0], tol_discrete );
      TEST_FLOATING_EQUALITY( xdot_view[1], x_1_dot_exact[0], tol_discrete );
    }
  }
  for (int i=1 ; i < Teuchos::as<int>(x_0_exact.size()); ++i) {
    // Each time step
    double t = 0.0+i*h;
    double h_taken = stepper->takeStep(h,STEP_TYPE_FIXED);
    TEST_ASSERT( h_taken == h );
    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];
    }
    {
      Thyra::ConstDetachedVectorView<double> x_view( *x );
      TEST_FLOATING_EQUALITY( x_view[0], x_0_exact[i], tol_discrete );
      TEST_FLOATING_EQUALITY( x_view[1], x_1_exact[i], tol_discrete );

      Thyra::ConstDetachedVectorView<double> xdot_view( *xdot );
      TEST_FLOATING_EQUALITY( xdot_view[0], x_0_dot_exact[i], tol_discrete );
      TEST_FLOATING_EQUALITY( xdot_view[1], x_1_dot_exact[i], tol_discrete );
    }
    // Now compare this to the continuous exact solution:
    {
      Thyra::ModelEvaluatorBase::InArgs<double> inArgs = model->getExactSolution(t);
      RCP<const VectorBase<double> > x_continuous_exact = inArgs.get_x();
      RCP<const VectorBase<double> > xdot_continuous_exact = inArgs.get_x_dot();
      {
        Thyra::ConstDetachedVectorView<double> x_view( *x );
        Thyra::ConstDetachedVectorView<double> xce_view( *x_continuous_exact );
        TEST_FLOATING_EQUALITY( x_view[0], xce_view[0], tol_continuous );
        TEST_FLOATING_EQUALITY( x_view[1], xce_view[1], tol_continuous*10 );

        Thyra::ConstDetachedVectorView<double> xdot_view( *xdot );
        Thyra::ConstDetachedVectorView<double> xdotce_view( *xdot_continuous_exact );
        TEST_FLOATING_EQUALITY( xdot_view[0], xdotce_view[0], tol_continuous*10 );
        TEST_FLOATING_EQUALITY( xdot_view[1], xdotce_view[1], tol_continuous*10 );
      }
    }
  }
}
int main(int argc, char **argv)
{
  Kokkos::initialize();

  try {

    // Create random field
    int M = 10;
    Teuchos::ParameterList solverParams;
    solverParams.set("Number of KL Terms", M);
    solverParams.set("Mean", 1.0);
    solverParams.set("Standard Deviation", 0.1);
    int ndim = 3;
    Teuchos::Array<double> domain_upper(ndim), domain_lower(ndim),
      correlation_length(ndim);
    for (int i=0; i<ndim; i++) {
      domain_upper[i] = 1.0;
      domain_lower[i] = 0.0;
      correlation_length[i] = 10.0;
    }
    solverParams.set("Domain Upper Bounds", domain_upper);
    solverParams.set("Domain Lower Bounds", domain_lower);
    solverParams.set("Correlation Lengths", correlation_length);
    Stokhos::KL::ExponentialRandomField<double> rf(solverParams);
    rf.print(std::cout);

    // Evaluate random field at a point
    Teuchos::Array<double> x(ndim);
    for (int i=0; i<ndim; i++)
      x[i] = (domain_upper[i] + domain_lower[i])/2.0 +
        0.1*(domain_upper[i] - domain_lower[i])/2.0;
    Teuchos::Array<double> rvar(M);
    for (int i=0; i<M; i++)
      rvar[i] = 1.5;
    double result = rf.evaluate(x, rvar);
    std::cout << "result (host)  = " << result << std::endl;

    // Evaluate random field in a functor on device
    typedef Kokkos::View<double*> view_type;
    typedef view_type::HostMirror host_view_type;
    view_type x_view("x", ndim);
    host_view_type host_x = Kokkos::create_mirror_view(x_view);
    for (int i=0; i<ndim; i++)
      host_x(i) = x[i];
    Kokkos::deep_copy(x_view, host_x);
    view_type rvar_view("rvar", M);
    host_view_type host_rvar = Kokkos::create_mirror_view(rvar_view);
    for (int i=0; i<M; i++)
      host_rvar(i) = rvar[i];
    Kokkos::deep_copy(rvar_view, host_rvar);
    RF<double> rf_func(rf, x_view, rvar_view);
    host_view_type host_y = Kokkos::create_mirror_view(rf_func.y);
    Kokkos::deep_copy(host_y, rf_func.y);
    double result2 = host_y(0);
    std::cout << "result (device)= " << result2 << std::endl;
  }
  catch (std::exception& e) {
    std::cout << e.what() << std::endl;
  }

  Kokkos::finalize();
}
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 );
  }

}