9 #ifndef Tempus_AdjointAuxSensitivityModelEvaluator_impl_hpp 10 #define Tempus_AdjointAuxSensitivityModelEvaluator_impl_hpp 16 #include "Thyra_DefaultBlockedLinearOp.hpp" 18 #include "Thyra_VectorStdOps.hpp" 19 #include "Thyra_MultiVectorStdOps.hpp" 23 template <
typename Scalar>
28 const Scalar& t_final,
29 const Teuchos::RCP<const Teuchos::ParameterList>& pList) :
31 adjoint_model_(adjoint_model),
33 mass_matrix_is_computed_(false),
34 t_interp_(
Teuchos::ScalarTraits<Scalar>::rmax())
38 using Thyra::VectorSpaceBase;
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 "AdjointAuxSensitivityModelEvaluator currently does not support " <<
57 "non-constant mass matrix df/dx_dot!");
64 Thyra::multiVectorProductVectorSpace(
model_->get_p_space(
p_index_),
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));
111 template <
typename Scalar>
118 t_interp_ = Teuchos::ScalarTraits<Scalar>::rmax();
119 forward_state_ = Teuchos::null;
122 template <
typename Scalar>
123 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
127 TEUCHOS_ASSERT(p < model_->Np());
128 return model_->get_p_space(p);
131 template <
typename Scalar>
132 Teuchos::RCP<const Teuchos::Array<std::string> >
136 TEUCHOS_ASSERT(p < model_->Np());
137 return model_->get_p_names(p);
140 template <
typename Scalar>
141 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
145 return x_prod_space_;
148 template <
typename Scalar>
149 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
153 return f_prod_space_;
156 template <
typename Scalar>
157 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
164 RCP<LinearOpBase<Scalar> > adjoint_op = adjoint_model_->create_W_op();
165 RCP<LinearOpBase<Scalar> > mv_adjoint_op =
166 Thyra::nonconstMultiVectorLinearOp(adjoint_op, num_adjoint_);
167 RCP<const Thyra::VectorSpaceBase<Scalar> > g_space = response_space_;
168 RCP<LinearOpBase<Scalar> > g_op =
169 Thyra::scaledIdentity(g_space, Scalar(1.0));
170 RCP<LinearOpBase<Scalar> > null_op;
171 return nonconstBlock2x2(mv_adjoint_op, null_op, null_op, g_op);
174 template <
typename Scalar>
175 Teuchos::RCP<const Thyra::LinearOpWithSolveFactoryBase<Scalar> >
180 using Teuchos::rcp_dynamic_cast;
183 RCP<const LOWSFB > alowsfb = adjoint_model_->get_W_factory();
184 if (alowsfb == Teuchos::null)
185 return Teuchos::null;
187 RCP<const LOWSFB > mv_alowsfb =
188 Thyra::multiVectorLinearOpWithSolveFactory(alowsfb, residual_space_,
191 RCP<const Thyra::VectorSpaceBase<Scalar> > g_space = response_space_;
192 RCP<const LOWSFB > g_lowsfb =
193 Thyra::scaledIdentitySolveFactory(g_space, Scalar(1.0));
195 Teuchos::Array< RCP<const LOWSFB > > lowsfbs(2);
196 lowsfbs[0] = mv_alowsfb;
197 lowsfbs[1] = g_lowsfb;
198 return Thyra::blockedTriangularLinearOpWithSolveFactory(lowsfbs);
201 template <
typename Scalar>
202 Thyra::ModelEvaluatorBase::InArgs<Scalar>
206 return prototypeInArgs_;
209 template <
typename Scalar>
210 Thyra::ModelEvaluatorBase::InArgs<Scalar>
214 typedef Thyra::ModelEvaluatorBase MEB;
216 using Teuchos::rcp_dynamic_cast;
218 MEB::InArgs<Scalar> me_nominal = model_->getNominalValues();
219 MEB::InArgs<Scalar> nominal = this->createInArgs();
221 const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
224 RCP< Thyra::VectorBase<Scalar> > x = Thyra::createMember(*x_prod_space_);
225 Thyra::assign(x.ptr(), zero);
228 if (me_nominal.supports(MEB::IN_ARG_x_dot)) {
229 RCP< Thyra::VectorBase<Scalar> > x_dot =
230 Thyra::createMember(*x_prod_space_);
231 Thyra::assign(x_dot.ptr(), zero);
232 nominal.set_x_dot(x_dot);
235 const int np = model_->Np();
236 for (
int i=0; i<np; ++i)
237 nominal.set_p(i, me_nominal.get_p(i));
242 template <
typename Scalar>
243 Thyra::ModelEvaluatorBase::OutArgs<Scalar>
247 return prototypeOutArgs_;
250 template <
typename Scalar>
254 const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs)
const 256 typedef Thyra::ModelEvaluatorBase MEB;
258 using Teuchos::rcp_dynamic_cast;
267 TEUCHOS_ASSERT(sh_ != Teuchos::null);
268 const Scalar t = inArgs.get_t();
269 const Scalar forward_t = t_final_ - t;
270 if (forward_state_ == Teuchos::null || t_interp_ != t) {
271 if (forward_state_ == Teuchos::null)
272 forward_state_ = sh_->interpolateState(forward_t);
274 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 inArgs.get_x_dot() != Teuchos::null)
283 me_inArgs.set_x_dot(forward_state_->getXDot());
284 if (me_inArgs.supports(MEB::IN_ARG_t))
285 me_inArgs.set_t(forward_t);
286 const int np = me_inArgs.Np();
287 for (
int i=0; i<np; ++i)
288 me_inArgs.set_p(i, inArgs.get_p(i));
291 RCP<Thyra::LinearOpBase<Scalar> > op = outArgs.get_W_op();
292 if (op != Teuchos::null) {
293 if (me_inArgs.supports(MEB::IN_ARG_alpha))
294 me_inArgs.set_alpha(inArgs.get_alpha());
295 if (me_inArgs.supports(MEB::IN_ARG_beta))
296 me_inArgs.set_beta(inArgs.get_beta());
299 RCP<Thyra::DefaultBlockedLinearOp<Scalar> > block_op =
300 rcp_dynamic_cast<Thyra::DefaultBlockedLinearOp<Scalar> >(op,
true);
301 RCP<Thyra::MultiVectorLinearOp<Scalar> > mv_adjoint_op =
303 block_op->getNonconstBlock(0,0),
true);
304 RCP<Thyra::LinearOpBase<Scalar> > adjoint_op =
306 MEB::OutArgs<Scalar> adj_me_outArgs = adjoint_model_->createOutArgs();
307 adj_me_outArgs.set_W_op(adjoint_op);
308 adjoint_model_->evalModel(me_inArgs, adj_me_outArgs);
311 RCP<Thyra::ScaledIdentityLinearOpWithSolve<Scalar> > si_op =
313 block_op->getNonconstBlock(1,1),
true);
314 si_op->
setScale(inArgs.get_alpha());
322 RCP<Thyra::VectorBase<Scalar> > f = outArgs.get_f();
323 if (f != Teuchos::null) {
324 RCP<const Thyra::VectorBase<Scalar> > x = inArgs.get_x().assert_not_null();
325 RCP<const DPV> prod_x = rcp_dynamic_cast<
const DPV>(x,
true);
326 RCP<const Thyra::VectorBase<Scalar> > adjoint_x = prod_x->getVectorBlock(0);
327 RCP<const Thyra::MultiVectorBase<Scalar> >adjoint_x_mv =
328 rcp_dynamic_cast<
const DMVPV>(adjoint_x,
true)->getMultiVector();
330 RCP<DPV> prod_f = rcp_dynamic_cast<
DPV>(f,
true);
331 RCP<Thyra::VectorBase<Scalar> > adjoint_f =
332 prod_f->getNonconstVectorBlock(0);
333 RCP<Thyra::MultiVectorBase<Scalar> > adjoint_f_mv =
334 rcp_dynamic_cast<
DMVPV>(adjoint_f,
true)->getNonconstMultiVector();
336 MEB::OutArgs<Scalar> adj_me_outArgs = adjoint_model_->createOutArgs();
338 if (my_dfdx_ == Teuchos::null)
339 my_dfdx_ = adjoint_model_->create_W_op();
340 adj_me_outArgs.set_W_op(my_dfdx_);
341 if (me_inArgs.supports(MEB::IN_ARG_alpha))
342 me_inArgs.set_alpha(0.0);
343 if (me_inArgs.supports(MEB::IN_ARG_beta))
344 me_inArgs.set_beta(1.0);
345 adjoint_model_->evalModel(me_inArgs, adj_me_outArgs);
348 my_dfdx_->apply(Thyra::NOTRANS, *adjoint_x_mv, adjoint_f_mv.ptr(),
349 Scalar(-1.0), Scalar(0.0));
353 RCP<const DPV> prod_x_dot;
354 if (me_inArgs.supports(MEB::IN_ARG_x_dot)) {
355 RCP<const Thyra::VectorBase<Scalar> > x_dot = inArgs.get_x_dot();
356 if (x_dot != Teuchos::null) {
357 prod_x_dot = rcp_dynamic_cast<
const DPV>(x_dot,
true);
358 RCP<const Thyra::VectorBase<Scalar> > adjoint_x_dot =
359 prod_x_dot->getVectorBlock(0);
360 RCP<const Thyra::MultiVectorBase<Scalar> > adjoint_x_dot_mv =
361 rcp_dynamic_cast<
const DMVPV>(adjoint_x_dot,
true)->getMultiVector();
362 if (mass_matrix_is_identity_) {
364 Thyra::V_StVpV(adjoint_f_mv.ptr(), Scalar(-1.0), *adjoint_f_mv,
368 if (my_dfdxdot_ == Teuchos::null)
369 my_dfdxdot_ = adjoint_model_->create_W_op();
370 if (!mass_matrix_is_constant_ || !mass_matrix_is_computed_) {
371 adj_me_outArgs.set_W_op(my_dfdxdot_);
372 me_inArgs.set_alpha(1.0);
373 me_inArgs.set_beta(0.0);
374 adjoint_model_->evalModel(me_inArgs, adj_me_outArgs);
376 mass_matrix_is_computed_ =
true;
378 my_dfdxdot_->apply(Thyra::NOTRANS, *adjoint_x_dot_mv,
379 adjoint_f_mv.ptr(), Scalar(1.0), Scalar(-1.0));
386 RCP<Thyra::VectorBase<Scalar> > adjoint_g =
387 prod_f->getNonconstVectorBlock(1);
388 RCP<Thyra::MultiVectorBase<Scalar> > adjoint_g_mv =
389 rcp_dynamic_cast<
DMVPV>(adjoint_g,
true)->getNonconstMultiVector();
391 MEB::OutArgs<Scalar> me_outArgs2 = model_->createOutArgs();
392 MEB::DerivativeSupport dfdp_support =
393 me_outArgs2.supports(MEB::OUT_ARG_DfDp, p_index_);
394 Thyra::EOpTransp trans = Thyra::CONJTRANS;
395 if (dfdp_support.supports(MEB::DERIV_LINEAR_OP)) {
396 if (my_dfdp_op_ == Teuchos::null)
397 my_dfdp_op_ = model_->create_DfDp_op(p_index_);
398 me_outArgs2.set_DfDp(p_index_, MEB::Derivative<Scalar>(my_dfdp_op_));
399 trans = Thyra::CONJTRANS;
401 else if (dfdp_support.supports(MEB::DERIV_MV_JACOBIAN_FORM)) {
402 if (my_dfdp_mv_ == Teuchos::null)
403 my_dfdp_mv_ = createMembers(model_->get_f_space(),
404 model_->get_p_space(p_index_)->dim());
405 me_outArgs2.set_DfDp(p_index_,
406 MEB::Derivative<Scalar>(my_dfdp_mv_,
407 MEB::DERIV_MV_JACOBIAN_FORM));
408 my_dfdp_op_ = my_dfdp_mv_;
409 trans = Thyra::CONJTRANS;
411 else if (dfdp_support.supports(MEB::DERIV_MV_GRADIENT_FORM)) {
412 if (my_dfdp_mv_ == Teuchos::null)
413 my_dfdp_mv_ = createMembers(model_->get_p_space(p_index_),
414 model_->get_f_space()->dim());
415 me_outArgs2.set_DfDp(p_index_,
416 MEB::Derivative<Scalar>(my_dfdp_mv_,
417 MEB::DERIV_MV_GRADIENT_FORM));
418 my_dfdp_op_ = my_dfdp_mv_;
422 TEUCHOS_TEST_FOR_EXCEPTION(
423 true, std::logic_error,
"Invalid df/dp support");
424 model_->evalModel(me_inArgs, me_outArgs2);
425 my_dfdp_op_->apply(trans, *adjoint_x_mv, adjoint_g_mv.ptr(),
426 Scalar(1.0), Scalar(0.0));
428 if (prod_x_dot != Teuchos::null) {
429 RCP<const Thyra::VectorBase<Scalar> > z_dot =
430 prod_x_dot->getVectorBlock(1);
431 RCP<const Thyra::MultiVectorBase<Scalar> > z_dot_mv =
432 rcp_dynamic_cast<
const DMVPV>(z_dot,
true)->getMultiVector();
433 Thyra::V_VmV(adjoint_g_mv.ptr(), *z_dot_mv, *adjoint_g_mv);
438 template<
class Scalar>
439 Teuchos::RCP<const Teuchos::ParameterList>
443 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
444 pl->set<
int>(
"Sensitivity Parameter Index", 0);
445 pl->set<
int>(
"Response Function Index", 0);
446 pl->set<
bool>(
"Mass Matrix Is Constant",
true);
447 pl->set<
bool>(
"Mass Matrix Is Identity",
false);
Thyra::ModelEvaluatorBase::OutArgs< Scalar > createOutArgsImpl() const
Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > adjoint_model_
Implicit concrete LinearOpBase subclass that takes a flattended out multi-vector and performs a multi...
void setScale(const Scalar &s)
Thyra::ModelEvaluatorBase::InArgs< Scalar > getNominalValues() const
static Teuchos::RCP< const Teuchos::ParameterList > getValidParameters()
Thyra::DefaultProductVector< Scalar > DPV
bool mass_matrix_is_constant_
RCP< LinearOpBase< Scalar > > getNonconstLinearOp()
bool mass_matrix_is_identity_
Teuchos::RCP< const DPVS > f_prod_space_
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_p_space(int p) const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_f_space() const
void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
Teuchos::RCP< const Thyra::LinearOpWithSolveFactoryBase< Scalar > > get_W_factory() const
Thyra::ModelEvaluatorBase::InArgs< Scalar > prototypeInArgs_
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
void setForwardSolutionHistory(const Teuchos::RCP< const Tempus::SolutionHistory< Scalar > > &sh)
Set solution history from forward evaluation.
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int p) const
Implicit concrete LinearOpBase subclass that takes a flattended out multi-vector and performs a multi...
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_x_space() const
Teuchos::RCP< const DPVS > x_prod_space_
Teuchos::RCP< const DMVPVS > residual_space_
AdjointAuxSensitivityModelEvaluator(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model, const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &adjoint_model, const Scalar &t_final, const Teuchos::RCP< const Teuchos::ParameterList > &pList=Teuchos::null)
Constructor.
Thyra::DefaultMultiVectorProductVector< Scalar > DMVPV
Teuchos::RCP< const DMVPVS > response_space_
Thyra::ModelEvaluatorBase::OutArgs< Scalar > prototypeOutArgs_
Teuchos::RCP< const DMVPVS > adjoint_space_
Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > model_
Thyra::ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
Teuchos::RCP< Thyra::LinearOpBase< Scalar > > create_W_op() const