void assertNodesUnChanged( const typename DataStore<Scalar>::DataStoreVector_t & nodes, const typename DataStore<Scalar>::DataStoreVector_t & nodes_copy ) { typedef Teuchos::ScalarTraits<Scalar> ST; int N = nodes.size(); int Ncopy = nodes_copy.size(); TEUCHOS_TEST_FOR_EXCEPTION( N != Ncopy, std::logic_error, "Error! The number of nodes passed in through setNodes has changed!" ); if (N > 0) { RCP<Thyra::VectorBase<Scalar> > xdiff = nodes[0].x->clone_v(); RCP<Thyra::VectorBase<Scalar> > xdotdiff = xdiff->clone_v(); V_S(outArg(*xdiff),ST::one()); V_S(outArg(*xdotdiff),ST::one()); for (int i=0 ; i<N ; ++i) { V_StVpStV(outArg(*xdiff),ST::one(),*nodes[i].x,-ST::one(),*nodes_copy[i].x); if ((!Teuchos::is_null(nodes[i].xdot)) && (!Teuchos::is_null(nodes_copy[i].xdot))) { V_StVpStV(outArg(*xdotdiff),ST::one(),*nodes[i].xdot,-ST::one(),*nodes_copy[i].xdot); } else if (Teuchos::is_null(nodes[i].xdot) && Teuchos::is_null(nodes_copy[i].xdot)) { V_S(outArg(*xdotdiff),ST::zero()); } Scalar xdiffnorm = norm_inf(*xdiff); Scalar xdotdiffnorm = norm_inf(*xdotdiff); TEUCHOS_TEST_FOR_EXCEPTION( ( ( nodes[i].time != nodes_copy[i].time ) || ( xdiffnorm != ST::zero() ) || ( xdotdiffnorm != ST::zero() ) || ( nodes[i].accuracy != nodes_copy[i].accuracy ) ), std::logic_error, "Error! The data in the nodes passed through setNodes has changed!" ); } } }
RCP<Thyra::VectorBase<Scalar> > computeArea( const Thyra::ModelEvaluator<Scalar>& me, const TimeRange<Scalar>& tr, const GaussQuadrature1D<Scalar>& gq ) { typedef Teuchos::ScalarTraits<Scalar> ST; RCP<Thyra::VectorBase<Scalar> > area = Thyra::createMember(me.get_x_space()); V_S(outArg(*area),ST::zero()); RCP<const TimeRange<Scalar> > sourceRange = gq.getRange(); RCP<const Array<Scalar> > sourcePts = gq.getPoints(); RCP<const Array<Scalar> > sourceWts = gq.getWeights(); Array<Scalar> destPts(*sourcePts); for (unsigned int i=0 ; i<sourcePts->size() ; ++i) { destPts[i] = translateTimeRange<Scalar>((*sourcePts)[i],*sourceRange,tr); } Scalar r = tr.length()/sourceRange->length(); for (unsigned int i=0 ; i<destPts.size() ; ++i) { RCP<Thyra::VectorBase<Scalar> > tmpVec = eval_f_t<Scalar>(me,destPts[i]); Vp_StV(outArg(*area),r*(*sourceWts)[i],*tmpVec); } return area; }
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 ); }