9 #ifndef Tempus_AdjointSensitivityModelEvaluator_impl_hpp 10 #define Tempus_AdjointSensitivityModelEvaluator_impl_hpp 12 #include "Thyra_DefaultMultiVectorProductVectorSpace.hpp" 13 #include "Thyra_DefaultMultiVectorProductVector.hpp" 16 #include "Thyra_DefaultScaledAdjointLinearOp.hpp" 17 #include "Thyra_DefaultAdjointLinearOpWithSolve.hpp" 19 #include "Thyra_VectorStdOps.hpp" 20 #include "Thyra_MultiVectorStdOps.hpp" 24 template <
typename Scalar>
29 const Scalar& t_final,
30 const bool is_pseudotransient,
31 const Teuchos::RCP<const Teuchos::ParameterList>& pList) :
33 adjoint_model_(adjoint_model),
35 is_pseudotransient_(is_pseudotransient),
36 mass_matrix_is_computed_(false),
37 t_interp_(
Teuchos::ScalarTraits<Scalar>::rmax())
39 typedef Thyra::ModelEvaluatorBase MEB;
42 Teuchos::RCP<Teuchos::ParameterList> pl =
43 Teuchos::rcp(
new Teuchos::ParameterList);
44 if (pList != Teuchos::null)
49 p_index_ = pl->get<
int>(
"Sensitivity Parameter Index", 0);
50 g_index_ = pl->get<
int>(
"Response Function Index", 0);
54 TEUCHOS_TEST_FOR_EXCEPTION(
56 "AdjointSensitivityModelEvaluator currently does not support " <<
57 "non-constant mass matrix df/dx_dot!");
64 Thyra::multiVectorProductVectorSpace(
model_->get_p_space(
p_index_),
68 MEB::InArgs<Scalar> me_inArgs =
model_->createInArgs();
71 MEB::InArgsSetup<Scalar> inArgs;
72 inArgs.setModelEvalDescription(this->description());
73 inArgs.setSupports(MEB::IN_ARG_x);
74 inArgs.setSupports(MEB::IN_ARG_t);
75 if (me_inArgs.supports(MEB::IN_ARG_x_dot))
76 inArgs.setSupports(MEB::IN_ARG_x_dot);
77 if (me_inArgs.supports(MEB::IN_ARG_alpha))
78 inArgs.setSupports(MEB::IN_ARG_alpha);
79 if (me_inArgs.supports(MEB::IN_ARG_beta))
80 inArgs.setSupports(MEB::IN_ARG_beta);
83 inArgs.set_Np(me_inArgs.Np());
86 MEB::OutArgs<Scalar> me_outArgs =
model_->createOutArgs();
87 MEB::OutArgs<Scalar> adj_me_outArgs =
adjoint_model_->createOutArgs();
88 MEB::OutArgsSetup<Scalar> outArgs;
89 outArgs.setModelEvalDescription(this->description());
90 outArgs.set_Np_Ng(me_inArgs.Np(),1);
91 outArgs.setSupports(MEB::OUT_ARG_f);
92 outArgs.setSupports(MEB::OUT_ARG_W_op);
97 TEUCHOS_ASSERT(me_inArgs.supports(MEB::IN_ARG_x));
98 TEUCHOS_ASSERT(adj_me_outArgs.supports(MEB::OUT_ARG_W_op));
99 if (me_inArgs.supports(MEB::IN_ARG_x_dot)) {
100 TEUCHOS_ASSERT(me_inArgs.supports(MEB::IN_ARG_alpha));
101 TEUCHOS_ASSERT(me_inArgs.supports(MEB::IN_ARG_beta));
103 MEB::DerivativeSupport dgdx_support =
104 me_outArgs.supports(MEB::OUT_ARG_DgDx,
g_index_);
105 MEB::DerivativeSupport dgdp_support =
107 TEUCHOS_ASSERT(dgdx_support.supports(MEB::DERIV_MV_GRADIENT_FORM));
108 TEUCHOS_ASSERT(dgdp_support.supports(MEB::DERIV_MV_GRADIENT_FORM));
111 template <
typename Scalar>
118 if (is_pseudotransient_)
119 forward_state_ = sh_->getCurrentState();
121 t_interp_ = Teuchos::ScalarTraits<Scalar>::rmax();
122 forward_state_ = Teuchos::null;
126 template <
typename Scalar>
127 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
131 TEUCHOS_ASSERT(p < model_->Np());
132 return model_->get_p_space(p);
135 template <
typename Scalar>
136 Teuchos::RCP<const Teuchos::Array<std::string> >
140 TEUCHOS_ASSERT(p < model_->Np());
141 return model_->get_p_names(p);
144 template <
typename Scalar>
145 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
149 return adjoint_space_;
152 template <
typename Scalar>
153 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
157 return residual_space_;
160 template <
typename Scalar>
161 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
165 TEUCHOS_ASSERT(j == 0);
166 return response_space_;
169 template <
typename Scalar>
170 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
174 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > adjoint_op =
175 adjoint_model_->create_W_op();
176 return Thyra::nonconstMultiVectorLinearOp(adjoint_op, num_adjoint_);
179 template <
typename Scalar>
180 Teuchos::RCP<const Thyra::LinearOpWithSolveFactoryBase<Scalar> >
185 using Teuchos::rcp_dynamic_cast;
188 RCP<const LOWSFB> alowsfb = adjoint_model_->get_W_factory();
189 if (alowsfb == Teuchos::null)
190 return Teuchos::null;
192 return Thyra::multiVectorLinearOpWithSolveFactory(
193 alowsfb, residual_space_, adjoint_space_);
196 template <
typename Scalar>
197 Thyra::ModelEvaluatorBase::InArgs<Scalar>
201 return prototypeInArgs_;
204 template <
typename Scalar>
205 Thyra::ModelEvaluatorBase::InArgs<Scalar>
209 typedef Thyra::ModelEvaluatorBase MEB;
211 using Teuchos::rcp_dynamic_cast;
213 MEB::InArgs<Scalar> me_nominal = model_->getNominalValues();
214 MEB::InArgs<Scalar> nominal = this->createInArgs();
216 const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
219 RCP< Thyra::VectorBase<Scalar> > x = Thyra::createMember(*adjoint_space_);
220 Thyra::assign(x.ptr(), zero);
223 if (me_nominal.supports(MEB::IN_ARG_x_dot)) {
224 RCP< Thyra::VectorBase<Scalar> > x_dot =
225 Thyra::createMember(*adjoint_space_);
226 Thyra::assign(x_dot.ptr(), zero);
227 nominal.set_x_dot(x_dot);
230 const int np = model_->Np();
231 for (
int i=0; i<np; ++i)
232 nominal.set_p(i, me_nominal.get_p(i));
237 template <
typename Scalar>
238 Thyra::ModelEvaluatorBase::OutArgs<Scalar>
242 return prototypeOutArgs_;
245 template <
typename Scalar>
249 const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs)
const 251 typedef Thyra::ModelEvaluatorBase MEB;
253 using Teuchos::rcp_dynamic_cast;
262 TEUCHOS_ASSERT(sh_ != Teuchos::null);
263 const Scalar t = inArgs.get_t();
265 if (is_pseudotransient_)
266 forward_t = forward_state_->getTime();
268 forward_t = t_final_ - t;
269 if (forward_state_ == Teuchos::null || t_interp_ != t) {
270 if (forward_state_ == Teuchos::null)
271 forward_state_ = sh_->interpolateState(forward_t);
273 sh_->interpolateState(forward_t, forward_state_.get());
279 MEB::InArgs<Scalar> me_inArgs = model_->getNominalValues();
280 me_inArgs.set_x(forward_state_->getX());
281 if (me_inArgs.supports(MEB::IN_ARG_x_dot)) {
282 if (inArgs.get_x_dot() != Teuchos::null)
283 me_inArgs.set_x_dot(forward_state_->getXDot());
285 if (is_pseudotransient_) {
290 if (my_x_dot_ == Teuchos::null) {
291 my_x_dot_ = Thyra::createMember(model_->get_x_space());
292 Thyra::assign(my_x_dot_.ptr(), Scalar(0.0));
294 me_inArgs.set_x_dot(my_x_dot_);
299 me_inArgs.set_x_dot(Teuchos::null);
303 if (me_inArgs.supports(MEB::IN_ARG_t))
304 me_inArgs.set_t(forward_t);
305 const int np = me_inArgs.Np();
306 for (
int i=0; i<np; ++i)
307 me_inArgs.set_p(i, inArgs.get_p(i));
313 RCP<Thyra::LinearOpBase<Scalar> > op = outArgs.get_W_op();
314 if (op != Teuchos::null) {
315 if (me_inArgs.supports(MEB::IN_ARG_alpha))
316 me_inArgs.set_alpha(inArgs.get_alpha());
317 if (me_inArgs.supports(MEB::IN_ARG_beta))
318 me_inArgs.set_beta(inArgs.get_beta());
320 RCP<Thyra::MultiVectorLinearOp<Scalar> > mv_adjoint_op =
322 RCP<Thyra::LinearOpBase<Scalar> > adjoint_op =
324 MEB::OutArgs<Scalar> adj_me_outArgs = adjoint_model_->createOutArgs();
325 adj_me_outArgs.set_W_op(adjoint_op);
326 adjoint_model_->evalModel(me_inArgs, adj_me_outArgs);
329 RCP<Thyra::VectorBase<Scalar> > adjoint_f = outArgs.get_f();
330 RCP<Thyra::VectorBase<Scalar> > adjoint_g = outArgs.get_g(0);
331 RCP<const Thyra::MultiVectorBase<Scalar> > adjoint_x_mv;
332 if (adjoint_f != Teuchos::null || adjoint_g != Teuchos::null) {
333 RCP<const Thyra::VectorBase<Scalar> > adjoint_x =
334 inArgs.get_x().assert_not_null();
336 rcp_dynamic_cast<
const DMVPV>(adjoint_x,
true)->getMultiVector();
344 if (adjoint_f != Teuchos::null) {
345 RCP<Thyra::MultiVectorBase<Scalar> > adjoint_f_mv =
346 rcp_dynamic_cast<
DMVPV>(adjoint_f,
true)->getNonconstMultiVector();
348 MEB::OutArgs<Scalar> me_outArgs = model_->createOutArgs();
349 MEB::OutArgs<Scalar> adj_me_outArgs = adjoint_model_->createOutArgs();
353 if (!is_pseudotransient_ || my_dgdx_mv_ == Teuchos::null) {
354 if (my_dgdx_mv_ == Teuchos::null)
356 Thyra::createMembers(model_->get_x_space(),
357 model_->get_g_space(g_index_)->dim());
358 me_outArgs.set_DgDx(g_index_,
359 MEB::Derivative<Scalar>(my_dgdx_mv_,
360 MEB::DERIV_MV_GRADIENT_FORM));
361 model_->evalModel(me_inArgs, me_outArgs);
362 me_outArgs.set_DgDx(g_index_, MEB::Derivative<Scalar>());
364 Thyra::assign(adjoint_f_mv.ptr(), *my_dgdx_mv_);
368 if (!is_pseudotransient_ || my_dfdx_ == Teuchos::null) {
369 if (my_dfdx_ == Teuchos::null)
370 my_dfdx_ = adjoint_model_->create_W_op();
371 adj_me_outArgs.set_W_op(my_dfdx_);
372 if (me_inArgs.supports(MEB::IN_ARG_alpha))
373 me_inArgs.set_alpha(0.0);
374 if (me_inArgs.supports(MEB::IN_ARG_beta))
375 me_inArgs.set_beta(1.0);
376 adjoint_model_->evalModel(me_inArgs, adj_me_outArgs);
378 my_dfdx_->apply(Thyra::NOTRANS, *adjoint_x_mv, adjoint_f_mv.ptr(),
379 Scalar(-1.0), Scalar(1.0));
385 if (me_inArgs.supports(MEB::IN_ARG_x_dot)) {
386 RCP<const Thyra::VectorBase<Scalar> > adjoint_x_dot = inArgs.get_x_dot();
387 if (adjoint_x_dot != Teuchos::null) {
388 RCP<const Thyra::MultiVectorBase<Scalar> > adjoint_x_dot_mv =
389 rcp_dynamic_cast<
const DMVPV>(adjoint_x_dot,
true)->getMultiVector();
390 if (mass_matrix_is_identity_) {
392 Thyra::V_StVpV(adjoint_f_mv.ptr(), Scalar(-1.0), *adjoint_f_mv,
396 if (!is_pseudotransient_ || my_dfdxdot_ == Teuchos::null) {
397 if (my_dfdxdot_ == Teuchos::null)
398 my_dfdxdot_ = adjoint_model_->create_W_op();
399 if (!mass_matrix_is_constant_ || !mass_matrix_is_computed_) {
400 adj_me_outArgs.set_W_op(my_dfdxdot_);
401 me_inArgs.set_alpha(1.0);
402 me_inArgs.set_beta(0.0);
403 adjoint_model_->evalModel(me_inArgs, adj_me_outArgs);
404 mass_matrix_is_computed_ =
true;
407 my_dfdxdot_->apply(Thyra::NOTRANS, *adjoint_x_dot_mv,
408 adjoint_f_mv.ptr(), Scalar(1.0), Scalar(-1.0));
418 if (adjoint_g != Teuchos::null) {
419 RCP<Thyra::MultiVectorBase<Scalar> > adjoint_g_mv =
420 rcp_dynamic_cast<
DMVPV>(adjoint_g,
true)->getNonconstMultiVector();
422 MEB::OutArgs<Scalar> me_outArgs = model_->createOutArgs();
425 MEB::DerivativeSupport dgdp_support =
426 me_outArgs.supports(MEB::OUT_ARG_DgDp, g_index_, p_index_);
427 if (dgdp_support.supports(MEB::DERIV_MV_GRADIENT_FORM)) {
428 me_outArgs.set_DgDp(g_index_, p_index_,
429 MEB::Derivative<Scalar>(adjoint_g_mv,
430 MEB::DERIV_MV_GRADIENT_FORM));
431 model_->evalModel(me_inArgs, me_outArgs);
433 else if (dgdp_support.supports(MEB::DERIV_MV_JACOBIAN_FORM)) {
434 const int num_g = model_->get_g_space(g_index_)->dim();
435 const int num_p = model_->get_p_space(p_index_)->dim();
436 RCP<Thyra::MultiVectorBase<Scalar> > dgdp_trans =
437 createMembers(model_->get_g_space(g_index_), num_p);
438 me_outArgs.set_DgDp(g_index_, p_index_,
439 MEB::Derivative<Scalar>(dgdp_trans,
440 MEB::DERIV_MV_JACOBIAN_FORM));
441 model_->evalModel(me_inArgs, me_outArgs);
442 Thyra::DetachedMultiVectorView<Scalar> dgdp_view(*adjoint_g_mv);
443 Thyra::DetachedMultiVectorView<Scalar> dgdp_trans_view(*dgdp_trans);
444 for (
int i=0; i<num_p; ++i)
445 for (
int j=0; j<num_g; ++j)
446 dgdp_view(i,j) = dgdp_trans_view(j,i);
449 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
450 "Invalid dg/dp support");
451 me_outArgs.set_DgDp(g_index_, p_index_, MEB::Derivative<Scalar>());
454 MEB::DerivativeSupport dfdp_support =
455 me_outArgs.supports(MEB::OUT_ARG_DfDp, p_index_);
456 Thyra::EOpTransp trans = Thyra::CONJTRANS;
457 if (dfdp_support.supports(MEB::DERIV_LINEAR_OP)) {
458 if (my_dfdp_op_ == Teuchos::null)
459 my_dfdp_op_ = model_->create_DfDp_op(p_index_);
460 me_outArgs.set_DfDp(p_index_, MEB::Derivative<Scalar>(my_dfdp_op_));
461 trans = Thyra::CONJTRANS;
463 else if (dfdp_support.supports(MEB::DERIV_MV_JACOBIAN_FORM)) {
464 if (my_dfdp_mv_ == Teuchos::null)
465 my_dfdp_mv_ = createMembers(model_->get_f_space(),
466 model_->get_p_space(p_index_)->dim());
467 me_outArgs.set_DfDp(p_index_,
468 MEB::Derivative<Scalar>(my_dfdp_mv_,
469 MEB::DERIV_MV_JACOBIAN_FORM));
470 my_dfdp_op_ = my_dfdp_mv_;
471 trans = Thyra::CONJTRANS;
473 else if (dfdp_support.supports(MEB::DERIV_MV_GRADIENT_FORM)) {
474 if (my_dfdp_mv_ == Teuchos::null)
475 my_dfdp_mv_ = createMembers(model_->get_p_space(p_index_),
476 model_->get_f_space()->dim());
477 me_outArgs.set_DfDp(p_index_,
478 MEB::Derivative<Scalar>(my_dfdp_mv_,
479 MEB::DERIV_MV_GRADIENT_FORM));
480 my_dfdp_op_ = my_dfdp_mv_;
484 TEUCHOS_TEST_FOR_EXCEPTION(
485 true, std::logic_error,
"Invalid df/dp support");
486 model_->evalModel(me_inArgs, me_outArgs);
487 my_dfdp_op_->apply(trans, *adjoint_x_mv, adjoint_g_mv.ptr(),
488 Scalar(-1.0), Scalar(1.0));
492 template<
class Scalar>
493 Teuchos::RCP<const Teuchos::ParameterList>
497 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
498 pl->set<
int>(
"Sensitivity Parameter Index", 0);
499 pl->set<
int>(
"Response Function Index", 0);
500 pl->set<
bool>(
"Mass Matrix Is Constant",
true);
501 pl->set<
bool>(
"Mass Matrix Is Identity",
false);
static Teuchos::RCP< const Teuchos::ParameterList > getValidParameters()
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int p) const
Thyra::ModelEvaluatorBase::OutArgs< Scalar > createOutArgsImpl() const
Teuchos::RCP< const DMVPVS > residual_space_
Teuchos::RCP< const Thyra::LinearOpWithSolveFactoryBase< Scalar > > get_W_factory() const
Teuchos::RCP< const DMVPVS > adjoint_space_
AdjointSensitivityModelEvaluator(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model, const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &adjoint_model, const Scalar &t_final, const bool is_pseudotransient, const Teuchos::RCP< const Teuchos::ParameterList > &pList=Teuchos::null)
Constructor.
bool mass_matrix_is_identity_
RCP< LinearOpBase< Scalar > > getNonconstLinearOp()
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_g_space(int j) const
Teuchos::RCP< const DMVPVS > response_space_
Thyra::ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
bool mass_matrix_is_constant_
Thyra::ModelEvaluatorBase::InArgs< Scalar > prototypeInArgs_
Thyra::ModelEvaluatorBase::OutArgs< Scalar > prototypeOutArgs_
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_x_space() const
Thyra::DefaultMultiVectorProductVector< Scalar > DMVPV
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > model_
void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
void setForwardSolutionHistory(const Teuchos::RCP< const Tempus::SolutionHistory< Scalar > > &sh)
Set solution history from forward evaluation.
Implicit concrete LinearOpBase subclass that takes a flattended out multi-vector and performs a multi...
Thyra::ModelEvaluatorBase::InArgs< Scalar > getNominalValues() const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_p_space(int p) const
Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > adjoint_model_
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_f_space() const
Teuchos::RCP< Thyra::LinearOpBase< Scalar > > create_W_op() const