29 const Scalar& t_init,
const Scalar& t_final,
30 const Teuchos::RCP<const Teuchos::ParameterList>& pList)
32 adjoint_model_(adjoint_model),
35 mass_matrix_is_computed_(false),
36 t_interp_(
Teuchos::ScalarTraits<Scalar>::rmax())
40 using Thyra::VectorSpaceBase;
41 typedef Thyra::ModelEvaluatorBase MEB;
44 Teuchos::RCP<Teuchos::ParameterList> pl =
45 Teuchos::rcp(
new Teuchos::ParameterList);
46 if (pList != Teuchos::null) *pl = *pList;
50 p_index_ = pl->get<
int>(
"Sensitivity Parameter Index", 0);
51 g_index_ = pl->get<
int>(
"Response Function Index", 0);
55 TEUCHOS_TEST_FOR_EXCEPTION(
57 "AdjointAuxSensitivityModelEvaluator currently does not support "
58 <<
"non-constant mass matrix df/dx_dot!");
66 Array<RCP<const VectorSpaceBase<Scalar> > > x_spaces(2);
67 Array<RCP<const VectorSpaceBase<Scalar> > > f_spaces(2);
76 MEB::InArgs<Scalar> me_inArgs =
model_->createInArgs();
79 MEB::InArgsSetup<Scalar> inArgs;
80 inArgs.setModelEvalDescription(this->description());
81 inArgs.setSupports(MEB::IN_ARG_x);
82 inArgs.setSupports(MEB::IN_ARG_t);
83 if (me_inArgs.supports(MEB::IN_ARG_x_dot))
84 inArgs.setSupports(MEB::IN_ARG_x_dot);
85 inArgs.setSupports(MEB::IN_ARG_alpha);
86 inArgs.setSupports(MEB::IN_ARG_beta);
89 inArgs.set_Np(me_inArgs.Np());
92 MEB::OutArgs<Scalar> me_outArgs =
model_->createOutArgs();
93 MEB::OutArgs<Scalar> adj_me_outArgs =
adjoint_model_->createOutArgs();
94 MEB::OutArgsSetup<Scalar> outArgs;
95 outArgs.setModelEvalDescription(this->description());
96 outArgs.set_Np_Ng(me_inArgs.Np(), 0);
97 outArgs.setSupports(MEB::OUT_ARG_f);
98 outArgs.setSupports(MEB::OUT_ARG_W_op);
103 TEUCHOS_ASSERT(me_inArgs.supports(MEB::IN_ARG_x));
104 TEUCHOS_ASSERT(adj_me_outArgs.supports(MEB::OUT_ARG_W_op));
105 if (me_inArgs.supports(MEB::IN_ARG_x_dot)) {
106 TEUCHOS_ASSERT(me_inArgs.supports(MEB::IN_ARG_alpha));
107 TEUCHOS_ASSERT(me_inArgs.supports(MEB::IN_ARG_beta));
244 const Thyra::ModelEvaluatorBase::InArgs<Scalar>& inArgs,
245 const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs)
const
247 typedef Thyra::ModelEvaluatorBase MEB;
249 using Teuchos::rcp_dynamic_cast;
258 TEUCHOS_ASSERT(sh_ != Teuchos::null);
259 const Scalar t = inArgs.get_t();
260 const Scalar forward_t = t_final_ + t_init_ - t;
261 if (forward_state_ == Teuchos::null || t_interp_ != t) {
262 if (forward_state_ == Teuchos::null)
263 forward_state_ = sh_->interpolateState(forward_t);
265 sh_->interpolateState(forward_t, forward_state_.get());
270 MEB::InArgs<Scalar> me_inArgs = model_->getNominalValues();
271 me_inArgs.set_x(forward_state_->getX());
272 if (me_inArgs.supports(MEB::IN_ARG_x_dot) &&
273 inArgs.get_x_dot() != Teuchos::null)
274 me_inArgs.set_x_dot(forward_state_->getXDot());
275 if (me_inArgs.supports(MEB::IN_ARG_t)) me_inArgs.set_t(forward_t);
276 const int np = me_inArgs.Np();
277 for (
int i = 0; i < np; ++i) me_inArgs.set_p(i, inArgs.get_p(i));
280 RCP<Thyra::LinearOpBase<Scalar> > op = outArgs.get_W_op();
281 if (op != Teuchos::null) {
282 if (me_inArgs.supports(MEB::IN_ARG_alpha))
283 me_inArgs.set_alpha(inArgs.get_alpha());
284 if (me_inArgs.supports(MEB::IN_ARG_beta))
285 me_inArgs.set_beta(inArgs.get_beta());
288 RCP<Thyra::DefaultBlockedLinearOp<Scalar> > block_op =
289 rcp_dynamic_cast<Thyra::DefaultBlockedLinearOp<Scalar> >(op,
true);
290 RCP<Thyra::MultiVectorLinearOp<Scalar> > mv_adjoint_op =
291 rcp_dynamic_cast<Thyra::MultiVectorLinearOp<Scalar> >(
292 block_op->getNonconstBlock(0, 0),
true);
293 RCP<Thyra::LinearOpBase<Scalar> > adjoint_op =
294 mv_adjoint_op->getNonconstLinearOp();
295 MEB::OutArgs<Scalar> adj_me_outArgs = adjoint_model_->createOutArgs();
296 adj_me_outArgs.set_W_op(adjoint_op);
297 adjoint_model_->evalModel(me_inArgs, adj_me_outArgs);
300 RCP<Thyra::ScaledIdentityLinearOpWithSolve<Scalar> > si_op =
301 rcp_dynamic_cast<Thyra::ScaledIdentityLinearOpWithSolve<Scalar> >(
302 block_op->getNonconstBlock(1, 1),
true);
303 si_op->setScale(inArgs.get_alpha());
311 RCP<Thyra::VectorBase<Scalar> > f = outArgs.get_f();
312 if (f != Teuchos::null) {
313 RCP<const Thyra::VectorBase<Scalar> > x = inArgs.get_x().assert_not_null();
314 RCP<const DPV> prod_x = rcp_dynamic_cast<const DPV>(x,
true);
315 RCP<const Thyra::VectorBase<Scalar> > adjoint_x = prod_x->getVectorBlock(0);
316 RCP<const Thyra::MultiVectorBase<Scalar> > adjoint_x_mv =
317 rcp_dynamic_cast<const DMVPV>(adjoint_x,
true)->getMultiVector();
319 RCP<DPV> prod_f = rcp_dynamic_cast<DPV>(f,
true);
320 RCP<Thyra::VectorBase<Scalar> > adjoint_f =
321 prod_f->getNonconstVectorBlock(0);
322 RCP<Thyra::MultiVectorBase<Scalar> > adjoint_f_mv =
323 rcp_dynamic_cast<DMVPV>(adjoint_f,
true)->getNonconstMultiVector();
325 MEB::OutArgs<Scalar> adj_me_outArgs = adjoint_model_->createOutArgs();
327 if (my_dfdx_ == Teuchos::null) my_dfdx_ = adjoint_model_->create_W_op();
328 adj_me_outArgs.set_W_op(my_dfdx_);
329 if (me_inArgs.supports(MEB::IN_ARG_alpha)) me_inArgs.set_alpha(0.0);
330 if (me_inArgs.supports(MEB::IN_ARG_beta)) me_inArgs.set_beta(1.0);
331 adjoint_model_->evalModel(me_inArgs, adj_me_outArgs);
334 my_dfdx_->apply(Thyra::NOTRANS, *adjoint_x_mv, adjoint_f_mv.ptr(),
335 Scalar(-1.0), Scalar(0.0));
339 RCP<const DPV> prod_x_dot;
340 if (me_inArgs.supports(MEB::IN_ARG_x_dot)) {
341 RCP<const Thyra::VectorBase<Scalar> > x_dot = inArgs.get_x_dot();
342 if (x_dot != Teuchos::null) {
343 prod_x_dot = rcp_dynamic_cast<const DPV>(x_dot,
true);
344 RCP<const Thyra::VectorBase<Scalar> > adjoint_x_dot =
345 prod_x_dot->getVectorBlock(0);
346 RCP<const Thyra::MultiVectorBase<Scalar> > adjoint_x_dot_mv =
347 rcp_dynamic_cast<const DMVPV>(adjoint_x_dot,
true)
349 if (mass_matrix_is_identity_) {
351 Thyra::V_StVpV(adjoint_f_mv.ptr(), Scalar(-1.0), *adjoint_f_mv,
355 if (my_dfdxdot_ == Teuchos::null)
356 my_dfdxdot_ = adjoint_model_->create_W_op();
357 if (!mass_matrix_is_constant_ || !mass_matrix_is_computed_) {
358 adj_me_outArgs.set_W_op(my_dfdxdot_);
359 me_inArgs.set_alpha(1.0);
360 me_inArgs.set_beta(0.0);
361 adjoint_model_->evalModel(me_inArgs, adj_me_outArgs);
363 mass_matrix_is_computed_ =
true;
365 my_dfdxdot_->apply(Thyra::NOTRANS, *adjoint_x_dot_mv,
366 adjoint_f_mv.ptr(), Scalar(1.0), Scalar(-1.0));
373 RCP<Thyra::VectorBase<Scalar> > adjoint_g =
374 prod_f->getNonconstVectorBlock(1);
375 RCP<Thyra::MultiVectorBase<Scalar> > adjoint_g_mv =
376 rcp_dynamic_cast<DMVPV>(adjoint_g,
true)->getNonconstMultiVector();
378 MEB::OutArgs<Scalar> me_outArgs2 = model_->createOutArgs();
379 MEB::DerivativeSupport dfdp_support =
380 me_outArgs2.supports(MEB::OUT_ARG_DfDp, p_index_);
381 Thyra::EOpTransp trans = Thyra::CONJTRANS;
382 if (dfdp_support.supports(MEB::DERIV_LINEAR_OP)) {
383 if (my_dfdp_op_ == Teuchos::null)
384 my_dfdp_op_ = model_->create_DfDp_op(p_index_);
385 me_outArgs2.set_DfDp(p_index_, MEB::Derivative<Scalar>(my_dfdp_op_));
386 trans = Thyra::CONJTRANS;
388 else if (dfdp_support.supports(MEB::DERIV_MV_JACOBIAN_FORM)) {
389 if (my_dfdp_mv_ == Teuchos::null)
390 my_dfdp_mv_ = createMembers(model_->get_f_space(),
391 model_->get_p_space(p_index_)->dim());
392 me_outArgs2.set_DfDp(
394 MEB::Derivative<Scalar>(my_dfdp_mv_, MEB::DERIV_MV_JACOBIAN_FORM));
395 my_dfdp_op_ = my_dfdp_mv_;
396 trans = Thyra::CONJTRANS;
398 else if (dfdp_support.supports(MEB::DERIV_MV_GRADIENT_FORM)) {
399 if (my_dfdp_mv_ == Teuchos::null)
400 my_dfdp_mv_ = createMembers(model_->get_p_space(p_index_),
401 model_->get_f_space()->dim());
402 me_outArgs2.set_DfDp(
404 MEB::Derivative<Scalar>(my_dfdp_mv_, MEB::DERIV_MV_GRADIENT_FORM));
405 my_dfdp_op_ = my_dfdp_mv_;
409 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
410 "Invalid df/dp support");
411 model_->evalModel(me_inArgs, me_outArgs2);
412 my_dfdp_op_->apply(trans, *adjoint_x_mv, adjoint_g_mv.ptr(), Scalar(1.0),
415 if (prod_x_dot != Teuchos::null) {
416 RCP<const Thyra::VectorBase<Scalar> > z_dot =
417 prod_x_dot->getVectorBlock(1);
418 RCP<const Thyra::MultiVectorBase<Scalar> > z_dot_mv =
419 rcp_dynamic_cast<const DMVPV>(z_dot,
true)->getMultiVector();
420 Thyra::V_VmV(adjoint_g_mv.ptr(), *z_dot_mv, *adjoint_g_mv);