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 ); } }
void assertValidModel( const StepperBase<Scalar>& stepper, const Thyra::ModelEvaluator<Scalar>& model ) { typedef Thyra::ModelEvaluatorBase MEB; TEUCHOS_ASSERT(stepper.acceptsModel()); const MEB::InArgs<Scalar> inArgs = model.createInArgs(); const MEB::OutArgs<Scalar> outArgs = model.createOutArgs(); //TEUCHOS_ASSERT(inArgs.supports(MEB::IN_ARG_t)); TEUCHOS_ASSERT(inArgs.supports(MEB::IN_ARG_x)); TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_f)); if (stepper.isImplicit()) { // implicit stepper TEUCHOS_ASSERT( inArgs.supports(MEB::IN_ARG_x_dot) ); TEUCHOS_ASSERT( inArgs.supports(MEB::IN_ARG_alpha) ); TEUCHOS_ASSERT( inArgs.supports(MEB::IN_ARG_beta) ); TEUCHOS_ASSERT( outArgs.supports(MEB::OUT_ARG_W) ); } //else { // explicit stepper // TEUCHOS_ASSERT( !inArgs.supports(MEB::IN_ARG_x_dot) ); // TEUCHOS_ASSERT( !inArgs.supports(MEB::IN_ARG_alpha) ); // TEUCHOS_ASSERT( !inArgs.supports(MEB::IN_ARG_beta) ); // TEUCHOS_ASSERT( !outArgs.supports(MEB::OUT_ARG_W) ); //} }
ModelEvaluatorBase::OutArgs<Scalar> DefaultModelEvaluatorWithSolveFactory<Scalar>::createOutArgsImpl() const { typedef ModelEvaluatorBase MEB; const RCP<const ModelEvaluator<Scalar> > thyraModel = this->getUnderlyingModel(); const MEB::OutArgs<Scalar> wrappedOutArgs = thyraModel->createOutArgs(); MEB::OutArgsSetup<Scalar> outArgs; outArgs.setModelEvalDescription(this->description()); outArgs.set_Np_Ng(wrappedOutArgs.Np(),wrappedOutArgs.Ng()); outArgs.setSupports(wrappedOutArgs); outArgs.setSupports(MEB::OUT_ARG_W, wrappedOutArgs.supports(MEB::OUT_ARG_W_op)&&W_factory_.get()!=NULL); return outArgs; }
RCP<LinearOpBase<Scalar> > ModelEvaluatorDefaultBase<Scalar>::create_DgDp_op_impl(int j, int l) const { typedef ModelEvaluatorBase MEB; MEB::OutArgs<Scalar> outArgs = this->createOutArgsImpl(); TEUCHOS_TEST_FOR_EXCEPTION( outArgs.supports(MEB::OUT_ARG_DgDp,j,l).supports(MEB::DERIV_LINEAR_OP), std::logic_error, "Error, The ModelEvaluator subclass "<<this->description()<<" says that it" " supports the LinearOpBase form of DgDp("<<j<<","<<l<<")" " (as determined from its OutArgs object created by createOutArgsImpl())" " but this function create_DgDp_op_impl(...) has not been overriden" " to create such an object!" ); return Teuchos::null; }
void DefaultStateEliminationModelEvaluator<Scalar>::evalModelImpl( const ModelEvaluatorBase::InArgs<Scalar> &inArgs, const ModelEvaluatorBase::OutArgs<Scalar> &outArgs ) const { typedef ModelEvaluatorBase MEB; using Teuchos::RCP; using Teuchos::rcp; using Teuchos::rcp_const_cast; using Teuchos::rcp_dynamic_cast; using Teuchos::OSTab; Teuchos::Time totalTimer(""), timer(""); totalTimer.start(true); const Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream(); const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel(); Teuchos::OSTab tab(out); if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW)) *out << "\nEntering Thyra::DefaultStateEliminationModelEvaluator<Scalar>::evalModel(...) ...\n"; const Teuchos::RCP<const ModelEvaluator<Scalar> > thyraModel = this->getUnderlyingModel(); const int Np = outArgs.Np(), Ng = outArgs.Ng(); // Get the intial state guess if not already gotten if (is_null(x_guess_solu_)) { const ModelEvaluatorBase::InArgs<Scalar> nominalValues = thyraModel->getNominalValues(); if(nominalValues.get_x().get()) { x_guess_solu_ = nominalValues.get_x()->clone_v(); } else { x_guess_solu_ = createMember(thyraModel->get_x_space()); assign(&*x_guess_solu_,Scalar(0.0)); } } // Reset the nominal values MEB::InArgs<Scalar> wrappedNominalValues = thyraModel->getNominalValues(); wrappedNominalValues.setArgs(inArgs,true); wrappedNominalValues.set_x(x_guess_solu_); typedef Teuchos::VerboseObjectTempState<ModelEvaluatorBase> VOTSME; //VOTSME thyraModel_outputTempState(rcp(&wrappedThyraModel,false),out,verbLevel); typedef Teuchos::VerboseObjectTempState<NonlinearSolverBase<Scalar> > VOTSNSB; VOTSNSB statSolver_outputTempState( stateSolver_,out ,static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW) ? Teuchos::VERB_LOW : Teuchos::VERB_NONE ); if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_EXTREME)) *out << "\ninArgs =\n" << Teuchos::describe(inArgs,verbLevel) << "\noutArgs on input =\n" << Teuchos::describe(outArgs,Teuchos::VERB_LOW); if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW)) *out << "\nSolving f(x,...) for x ...\n"; wrappedThyraModel_->setNominalValues( rcp(new MEB::InArgs<Scalar>(wrappedNominalValues)) ); SolveStatus<Scalar> solveStatus = stateSolver_->solve(&*x_guess_solu_,NULL); if( solveStatus.solveStatus == SOLVE_STATUS_CONVERGED ) { if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW)) *out << "\nComputing the output functions at the solved state solution ...\n"; MEB::InArgs<Scalar> wrappedInArgs = thyraModel->createInArgs(); MEB::OutArgs<Scalar> wrappedOutArgs = thyraModel->createOutArgs(); wrappedInArgs.setArgs(inArgs,true); wrappedInArgs.set_x(x_guess_solu_); wrappedOutArgs.setArgs(outArgs,true); for( int l = 0; l < Np; ++l ) { for( int j = 0; j < Ng; ++j ) { if( outArgs.supports(MEB::OUT_ARG_DgDp,j,l).none()==false && outArgs.get_DgDp(j,l).isEmpty()==false ) { // Set DfDp(l) and DgDx(j) to be computed! //wrappedOutArgs.set_DfDp(l,...); //wrappedOutArgs.set_DgDx(j,...); TEST_FOR_EXCEPT(true); } } } thyraModel->evalModel(wrappedInArgs,wrappedOutArgs); // // Compute DgDp(j,l) using direct sensitivties // for( int l = 0; l < Np; ++l ) { if( wrappedOutArgs.supports(MEB::OUT_ARG_DfDp,l).none()==false && wrappedOutArgs.get_DfDp(l).isEmpty()==false ) { // // Compute: D(l) = -inv(DfDx)*DfDp(l) // TEST_FOR_EXCEPT(true); for( int j = 0; j < Ng; ++j ) { if( outArgs.supports(MEB::OUT_ARG_DgDp,j,l).none()==false && outArgs.get_DgDp(j,l).isEmpty()==false ) { // // Compute: DgDp(j,l) = DgDp(j,l) + DgDx(j)*D // TEST_FOR_EXCEPT(true); } } } } // ToDo: Add a mode to compute DgDp(l) using adjoint sensitivities? } else { if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW)) *out << "\nFailed to converge, returning NaNs ...\n"; outArgs.setFailed(); } if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_EXTREME)) *out << "\noutArgs on output =\n" << Teuchos::describe(outArgs,verbLevel); totalTimer.stop(); if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW)) *out << "\nTotal evaluation time = "<<totalTimer.totalElapsedTime()<<" sec\n" << "\nLeaving Thyra::DefaultStateEliminationModelEvaluator<Scalar>::evalModel(...) ...\n"; }
void ModelEvaluatorDefaultBase<Scalar>::initializeDefaultBase() { typedef ModelEvaluatorBase MEB; // In case we throw half way thorugh, set to uninitialized isInitialized_ = false; default_W_support_ = false; // // A) Get the InArgs and OutArgs from the subclass // const MEB::InArgs<Scalar> inArgs = this->createInArgs(); const MEB::OutArgs<Scalar> outArgsImpl = this->createOutArgsImpl(); // // B) Validate the subclasses InArgs and OutArgs // #ifdef TEUCHOS_DEBUG assertInArgsOutArgsSetup( this->description(), inArgs, outArgsImpl ); #endif // TEUCHOS_DEBUG // // C) Set up support for default derivative objects and prototype OutArgs // const int l_Ng = outArgsImpl.Ng(); const int l_Np = outArgsImpl.Np(); // Set support for all outputs supported in the underly implementation MEB::OutArgsSetup<Scalar> outArgs; outArgs.setModelEvalDescription(this->description()); outArgs.set_Np_Ng(l_Np,l_Ng); outArgs.setSupports(outArgsImpl); // DfDp DfDp_default_op_support_.clear(); if (outArgs.supports(MEB::OUT_ARG_f)) { for ( int l = 0; l < l_Np; ++l ) { const MEB::DerivativeSupport DfDp_l_impl_support = outArgsImpl.supports(MEB::OUT_ARG_DfDp,l); const DefaultDerivLinearOpSupport DfDp_l_op_support = determineDefaultDerivLinearOpSupport(DfDp_l_impl_support); DfDp_default_op_support_.push_back(DfDp_l_op_support); outArgs.setSupports( MEB::OUT_ARG_DfDp, l, updateDefaultLinearOpSupport( DfDp_l_impl_support, DfDp_l_op_support ) ); } } // DgDx_dot DgDx_dot_default_op_support_.clear(); for ( int j = 0; j < l_Ng; ++j ) { const MEB::DerivativeSupport DgDx_dot_j_impl_support = outArgsImpl.supports(MEB::OUT_ARG_DgDx_dot,j); const DefaultDerivLinearOpSupport DgDx_dot_j_op_support = determineDefaultDerivLinearOpSupport(DgDx_dot_j_impl_support); DgDx_dot_default_op_support_.push_back(DgDx_dot_j_op_support); outArgs.setSupports( MEB::OUT_ARG_DgDx_dot, j, updateDefaultLinearOpSupport( DgDx_dot_j_impl_support, DgDx_dot_j_op_support ) ); } // DgDx DgDx_default_op_support_.clear(); for ( int j = 0; j < l_Ng; ++j ) { const MEB::DerivativeSupport DgDx_j_impl_support = outArgsImpl.supports(MEB::OUT_ARG_DgDx,j); const DefaultDerivLinearOpSupport DgDx_j_op_support = determineDefaultDerivLinearOpSupport(DgDx_j_impl_support); DgDx_default_op_support_.push_back(DgDx_j_op_support); outArgs.setSupports( MEB::OUT_ARG_DgDx, j, updateDefaultLinearOpSupport( DgDx_j_impl_support, DgDx_j_op_support ) ); } // DgDp DgDp_default_op_support_.clear(); DgDp_default_mv_support_.clear(); for ( int j = 0; j < l_Ng; ++j ) { DgDp_default_op_support_.push_back(Array<DefaultDerivLinearOpSupport>()); DgDp_default_mv_support_.push_back(Array<DefaultDerivMvAdjointSupport>()); for ( int l = 0; l < l_Np; ++l ) { const MEB::DerivativeSupport DgDp_j_l_impl_support = outArgsImpl.supports(MEB::OUT_ARG_DgDp,j,l); // LinearOpBase support const DefaultDerivLinearOpSupport DgDp_j_l_op_support = determineDefaultDerivLinearOpSupport(DgDp_j_l_impl_support); DgDp_default_op_support_[j].push_back(DgDp_j_l_op_support); outArgs.setSupports( MEB::OUT_ARG_DgDp, j, l, updateDefaultLinearOpSupport( DgDp_j_l_impl_support, DgDp_j_l_op_support ) ); // MultiVectorBase const DefaultDerivMvAdjointSupport DgDp_j_l_mv_support = determineDefaultDerivMvAdjointSupport( DgDp_j_l_impl_support, *this->get_g_space(j), *this->get_p_space(l) ); DgDp_default_mv_support_[j].push_back(DgDp_j_l_mv_support); outArgs.setSupports( MEB::OUT_ARG_DgDp, j, l, updateDefaultDerivMvAdjointSupport( outArgs.supports(MEB::OUT_ARG_DgDp, j, l), DgDp_j_l_mv_support ) ); } } // 2007/09/09: rabart: ToDo: Move the above code into a private helper // function! // W (given W_op and W_factory) default_W_support_ = false; if ( outArgsImpl.supports(MEB::OUT_ARG_W_op) && !is_null(this->get_W_factory()) && !outArgsImpl.supports(MEB::OUT_ARG_W) ) { default_W_support_ = true; outArgs.setSupports(MEB::OUT_ARG_W); outArgs.set_W_properties(outArgsImpl.get_W_properties()); } // // D) All done! // prototypeOutArgs_ = outArgs; isInitialized_ = true; }
void ModelEvaluatorDefaultBase<Scalar>::evalModel( const ModelEvaluatorBase::InArgs<Scalar> &inArgs, const ModelEvaluatorBase::OutArgs<Scalar> &outArgs ) const { using Teuchos::outArg; typedef ModelEvaluatorBase MEB; lazyInitializeDefaultBase(); const int l_Np = outArgs.Np(); const int l_Ng = outArgs.Ng(); // // A) Assert that the inArgs and outArgs object match this class! // #ifdef TEUCHOS_DEBUG assertInArgsEvalObjects(*this,inArgs); assertOutArgsEvalObjects(*this,outArgs,&inArgs); #endif // // B) Setup the OutArgs object for the underlying implementation's // evalModelImpl(...) function // MEB::OutArgs<Scalar> outArgsImpl = this->createOutArgsImpl(); Array<MultiVectorAdjointPair> DgDp_temp_adjoint_copies; { outArgsImpl.setArgs(outArgs,true); // DfDp(l) if (outArgsImpl.supports(MEB::OUT_ARG_f)) { for ( int l = 0; l < l_Np; ++l ) { const DefaultDerivLinearOpSupport defaultLinearOpSupport = DfDp_default_op_support_[l]; if (defaultLinearOpSupport.provideDefaultLinearOp()) { outArgsImpl.set_DfDp( l, getOutArgImplForDefaultLinearOpSupport( outArgs.get_DfDp(l), defaultLinearOpSupport ) ); } else { // DfDp(l) already set by outArgsImpl.setArgs(...)! } } } // DgDx_dot(j) for ( int j = 0; j < l_Ng; ++j ) { const DefaultDerivLinearOpSupport defaultLinearOpSupport = DgDx_dot_default_op_support_[j]; if (defaultLinearOpSupport.provideDefaultLinearOp()) { outArgsImpl.set_DgDx_dot( j, getOutArgImplForDefaultLinearOpSupport( outArgs.get_DgDx_dot(j), defaultLinearOpSupport ) ); } else { // DgDx_dot(j) already set by outArgsImpl.setArgs(...)! } } // DgDx(j) for ( int j = 0; j < l_Ng; ++j ) { const DefaultDerivLinearOpSupport defaultLinearOpSupport = DgDx_default_op_support_[j]; if (defaultLinearOpSupport.provideDefaultLinearOp()) { outArgsImpl.set_DgDx( j, getOutArgImplForDefaultLinearOpSupport( outArgs.get_DgDx(j), defaultLinearOpSupport ) ); } else { // DgDx(j) already set by outArgsImpl.setArgs(...)! } } // DgDp(j,l) for ( int j = 0; j < l_Ng; ++j ) { const Array<DefaultDerivLinearOpSupport> &DgDp_default_op_support_j = DgDp_default_op_support_[j]; const Array<DefaultDerivMvAdjointSupport> &DgDp_default_mv_support_j = DgDp_default_mv_support_[j]; for ( int l = 0; l < l_Np; ++l ) { const DefaultDerivLinearOpSupport defaultLinearOpSupport = DgDp_default_op_support_j[l]; const DefaultDerivMvAdjointSupport defaultMvAdjointSupport = DgDp_default_mv_support_j[l]; MEB::Derivative<Scalar> DgDp_j_l; if (!outArgs.supports(MEB::OUT_ARG_DgDp,j,l).none()) DgDp_j_l = outArgs.get_DgDp(j,l); if ( defaultLinearOpSupport.provideDefaultLinearOp() && !is_null(DgDp_j_l.getLinearOp()) ) { outArgsImpl.set_DgDp( j, l, getOutArgImplForDefaultLinearOpSupport( DgDp_j_l, defaultLinearOpSupport ) ); } else if ( defaultMvAdjointSupport.provideDefaultAdjoint() && !is_null(DgDp_j_l.getMultiVector()) ) { const RCP<MultiVectorBase<Scalar> > DgDp_j_l_mv = DgDp_j_l.getMultiVector(); if ( defaultMvAdjointSupport.mvAdjointCopyOrientation() == DgDp_j_l.getMultiVectorOrientation() ) { // The orientation of the multi-vector is different so we need to // create a temporary copy to pass to evalModelImpl(...) and then // copy it back again! const RCP<MultiVectorBase<Scalar> > DgDp_j_l_mv_adj = createMembers(DgDp_j_l_mv->domain(), DgDp_j_l_mv->range()->dim()); outArgsImpl.set_DgDp( j, l, MEB::Derivative<Scalar>( DgDp_j_l_mv_adj, getOtherDerivativeMultiVectorOrientation( defaultMvAdjointSupport.mvAdjointCopyOrientation() ) ) ); // Remember these multi-vectors so that we can do the transpose copy // back after the evaluation! DgDp_temp_adjoint_copies.push_back( MultiVectorAdjointPair(DgDp_j_l_mv, DgDp_j_l_mv_adj) ); } else { // The form of the multi-vector is supported by evalModelImpl(..) // and is already set on the outArgsImpl object. } } else { // DgDp(j,l) already set by outArgsImpl.setArgs(...)! } } } // W { RCP<LinearOpWithSolveBase<Scalar> > W; if ( default_W_support_ && !is_null(W=outArgs.get_W()) ) { const RCP<const LinearOpWithSolveFactoryBase<Scalar> > W_factory = this->get_W_factory(); // Extract the underlying W_op object (if it exists) RCP<const LinearOpBase<Scalar> > W_op_const; uninitializeOp<Scalar>(*W_factory, W.ptr(), outArg(W_op_const)); RCP<LinearOpBase<Scalar> > W_op; if (!is_null(W_op_const)) { // Here we remove the const. This is perfectly safe since // w.r.t. this class, we put a non-const object in there and we can // expect to change that object after the fact. That is our // prerogative. W_op = Teuchos::rcp_const_cast<LinearOpBase<Scalar> >(W_op_const); } else { // The W_op object has not been initialized yet so create it. The // next time through, we should not have to do this! W_op = this->create_W_op(); } outArgsImpl.set_W_op(W_op); } } } // // C) Evaluate the underlying model implementation! // this->evalModelImpl( inArgs, outArgsImpl ); // // D) Post-process the output arguments // // Do explicit transposes for DgDp(j,l) if needed const int numMvAdjointCopies = DgDp_temp_adjoint_copies.size(); for ( int adj_copy_i = 0; adj_copy_i < numMvAdjointCopies; ++adj_copy_i ) { const MultiVectorAdjointPair adjPair = DgDp_temp_adjoint_copies[adj_copy_i]; doExplicitMultiVectorAdjoint( *adjPair.mvImplAdjoint, &*adjPair.mvOuter ); } // Update W given W_op and W_factory { RCP<LinearOpWithSolveBase<Scalar> > W; if ( default_W_support_ && !is_null(W=outArgs.get_W()) ) { const RCP<const LinearOpWithSolveFactoryBase<Scalar> > W_factory = this->get_W_factory(); W_factory->setOStream(this->getOStream()); W_factory->setVerbLevel(this->getVerbLevel()); initializeOp<Scalar>(*W_factory, outArgsImpl.get_W_op().getConst(), W.ptr()); } } }