9 #ifndef Tempus_AdjointAuxSensitivityModelEvaluator_impl_hpp
10 #define Tempus_AdjointAuxSensitivityModelEvaluator_impl_hpp
14 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
15 #include "Thyra_DefaultAdjointLinearOpWithSolve.hpp"
19 #include "Thyra_DefaultBlockedLinearOp.hpp"
21 #include "Thyra_VectorStdOps.hpp"
22 #include "Thyra_MultiVectorStdOps.hpp"
26 template <
typename Scalar>
29 const Teuchos::RCP<
const Thyra::ModelEvaluator<Scalar> > & model,
30 const Scalar& t_final,
31 const Teuchos::RCP<const Teuchos::ParameterList>& pList) :
34 mass_matrix_is_computed_(false),
35 t_interp_(Teuchos::ScalarTraits<Scalar>::rmax())
39 using Thyra::VectorSpaceBase;
40 typedef Thyra::ModelEvaluatorBase MEB;
43 Teuchos::RCP<Teuchos::ParameterList> pl =
44 Teuchos::rcp(
new Teuchos::ParameterList);
45 if (pList != Teuchos::null)
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!");
65 Thyra::multiVectorProductVectorSpace(
model_->get_p_space(p_index_),
67 Array< RCP<const VectorSpaceBase<Scalar> > > x_spaces(2);
68 Array< RCP<const VectorSpaceBase<Scalar> > > f_spaces(2);
76 MEB::InArgs<Scalar> me_inArgs =
model_->createInArgs();
77 MEB::InArgsSetup<Scalar> inArgs;
78 inArgs.setModelEvalDescription(this->description());
79 inArgs.setSupports(MEB::IN_ARG_x);
80 inArgs.setSupports(MEB::IN_ARG_t);
81 if (me_inArgs.supports(MEB::IN_ARG_x_dot))
82 inArgs.setSupports(MEB::IN_ARG_x_dot);
83 inArgs.setSupports(MEB::IN_ARG_alpha);
84 inArgs.setSupports(MEB::IN_ARG_beta);
87 inArgs.set_Np(me_inArgs.Np());
90 MEB::OutArgs<Scalar> me_outArgs =
model_->createOutArgs();
91 MEB::OutArgsSetup<Scalar> outArgs;
92 outArgs.setModelEvalDescription(this->description());
93 outArgs.set_Np_Ng(me_inArgs.Np(),0);
94 outArgs.setSupports(MEB::OUT_ARG_f);
95 outArgs.setSupports(MEB::OUT_ARG_W_op);
100 TEUCHOS_ASSERT(me_inArgs.supports(MEB::IN_ARG_x));
101 TEUCHOS_ASSERT(me_outArgs.supports(MEB::OUT_ARG_W_op));
102 if (me_inArgs.supports(MEB::IN_ARG_x_dot)) {
103 TEUCHOS_ASSERT(me_inArgs.supports(MEB::IN_ARG_alpha));
104 TEUCHOS_ASSERT(me_inArgs.supports(MEB::IN_ARG_beta));
108 template <
typename Scalar>
115 t_interp_ = Teuchos::ScalarTraits<Scalar>::rmax();
116 forward_state_ = Teuchos::null;
119 template <
typename Scalar>
120 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
124 TEUCHOS_ASSERT(p < model_->Np());
125 return model_->get_p_space(p);
128 template <
typename Scalar>
129 Teuchos::RCP<const Teuchos::Array<std::string> >
133 TEUCHOS_ASSERT(p < model_->Np());
134 return model_->get_p_names(p);
137 template <
typename Scalar>
138 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
142 return x_prod_space_;
145 template <
typename Scalar>
146 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
150 return f_prod_space_;
153 template <
typename Scalar>
154 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
159 using Thyra::LinearOpBase;
161 RCP<LinearOpBase<Scalar> > op = model_->create_W_op();
162 RCP<LinearOpBase<Scalar> > mv_adjoint_op =
163 Thyra::nonconstMultiVectorLinearOp(Thyra::nonconstAdjoint(op),
165 RCP<const Thyra::VectorSpaceBase<Scalar> > g_space = response_space_;
166 RCP<LinearOpBase<Scalar> > g_op =
167 Thyra::scaledIdentity(g_space, Scalar(1.0));
168 RCP<LinearOpBase<Scalar> > null_op;
169 return nonconstBlock2x2(mv_adjoint_op, null_op, null_op, g_op);
172 template <
typename Scalar>
173 Teuchos::RCP<const Thyra::LinearOpWithSolveFactoryBase<Scalar> >
178 using Teuchos::rcp_dynamic_cast;
179 typedef Thyra::LinearOpWithSolveFactoryBase<Scalar> LOWSFB;
181 RCP<const LOWSFB > factory = model_->get_W_factory();
182 if (factory == Teuchos::null)
183 return Teuchos::null;
185 RCP<const LOWSFB > alowsfb = Thyra::adjointLinearOpWithSolveFactory(factory);
186 RCP<const LOWSFB > mv_alowsfb =
187 Thyra::multiVectorLinearOpWithSolveFactory(alowsfb, residual_space_,
190 RCP<const Thyra::VectorSpaceBase<Scalar> > g_space = response_space_;
191 RCP<const LOWSFB > g_lowsfb =
192 Thyra::scaledIdentitySolveFactory(g_space, Scalar(1.0));
194 Teuchos::Array< RCP<const LOWSFB > > lowsfbs(2);
195 lowsfbs[0] = mv_alowsfb;
196 lowsfbs[1] = g_lowsfb;
197 return Thyra::blockedTriangularLinearOpWithSolveFactory(lowsfbs);
200 template <
typename Scalar>
201 Thyra::ModelEvaluatorBase::InArgs<Scalar>
205 return prototypeInArgs_;
208 template <
typename Scalar>
209 Thyra::ModelEvaluatorBase::InArgs<Scalar>
213 typedef Thyra::ModelEvaluatorBase MEB;
215 using Teuchos::rcp_dynamic_cast;
217 MEB::InArgs<Scalar> me_nominal = model_->getNominalValues();
218 MEB::InArgs<Scalar> nominal = this->createInArgs();
220 const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
223 RCP< Thyra::VectorBase<Scalar> > x = Thyra::createMember(*x_prod_space_);
224 Thyra::assign(x.ptr(), zero);
227 if (me_nominal.supports(MEB::IN_ARG_x_dot)) {
228 RCP< Thyra::VectorBase<Scalar> > x_dot =
229 Thyra::createMember(*x_prod_space_);
230 Thyra::assign(x_dot.ptr(), zero);
231 nominal.set_x_dot(x_dot);
234 const int np = model_->Np();
235 for (
int i=0; i<np; ++i)
236 nominal.set_p(i, me_nominal.get_p(i));
241 template <
typename Scalar>
242 Thyra::ModelEvaluatorBase::OutArgs<Scalar>
246 return prototypeOutArgs_;
249 template <
typename Scalar>
253 const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs)
const
255 typedef Thyra::ModelEvaluatorBase MEB;
257 using Teuchos::rcp_dynamic_cast;
261 TEUCHOS_ASSERT(sh_ != Teuchos::null);
262 const Scalar t = inArgs.get_t();
263 const Scalar forward_t = t_final_ - t;
264 if (forward_state_ == Teuchos::null || t_interp_ != t) {
265 if (forward_state_ == Teuchos::null)
266 forward_state_ = sh_->interpolateState(forward_t);
268 sh_->interpolateState(forward_t, forward_state_.get());
273 MEB::InArgs<Scalar> me_inArgs = model_->getNominalValues();
274 me_inArgs.set_x(forward_state_->getX());
275 if (me_inArgs.supports(MEB::IN_ARG_x_dot) &&
276 inArgs.get_x_dot() != Teuchos::null)
277 me_inArgs.set_x_dot(forward_state_->getXDot());
278 if (me_inArgs.supports(MEB::IN_ARG_t))
279 me_inArgs.set_t(forward_t);
280 const int np = me_inArgs.Np();
281 for (
int i=0; i<np; ++i)
282 me_inArgs.set_p(i, inArgs.get_p(i));
285 RCP<Thyra::LinearOpBase<Scalar> > op = outArgs.get_W_op();
286 if (op != Teuchos::null) {
287 if (me_inArgs.supports(MEB::IN_ARG_alpha))
288 me_inArgs.set_alpha(inArgs.get_alpha());
289 if (me_inArgs.supports(MEB::IN_ARG_beta))
290 me_inArgs.set_beta(inArgs.get_beta());
293 RCP<Thyra::DefaultBlockedLinearOp<Scalar> > block_op =
294 rcp_dynamic_cast<Thyra::DefaultBlockedLinearOp<Scalar> >(op,
true);
295 RCP<Thyra::MultiVectorLinearOp<Scalar> > mv_adjoint_op =
297 block_op->getNonconstBlock(0,0),
true);
298 RCP<Thyra::DefaultScaledAdjointLinearOp<Scalar> > adjoint_op =
299 rcp_dynamic_cast<Thyra::DefaultScaledAdjointLinearOp<Scalar> >(
300 mv_adjoint_op->getNonconstLinearOp(),
true);
301 MEB::OutArgs<Scalar> me_outArgs = model_->createOutArgs();
302 me_outArgs.set_W_op(adjoint_op->getNonconstOp());
303 model_->evalModel(me_inArgs, me_outArgs);
306 RCP<Thyra::ScaledIdentityLinearOpWithSolve<Scalar> > si_op =
308 block_op->getNonconstBlock(1,1),
true);
309 si_op->
setScale(inArgs.get_alpha());
317 RCP<Thyra::VectorBase<Scalar> > f = outArgs.get_f();
318 if (f != Teuchos::null) {
319 RCP<const Thyra::VectorBase<Scalar> > x = inArgs.get_x().assert_not_null();
320 RCP<const DPV> prod_x = rcp_dynamic_cast<
const DPV>(x,
true);
321 RCP<const Thyra::VectorBase<Scalar> > adjoint_x = prod_x->getVectorBlock(0);
322 RCP<const Thyra::MultiVectorBase<Scalar> >adjoint_x_mv =
323 rcp_dynamic_cast<
const DMVPV>(adjoint_x,
true)->getMultiVector();
325 RCP<DPV> prod_f = rcp_dynamic_cast<
DPV>(f,
true);
326 RCP<Thyra::VectorBase<Scalar> > adjoint_f =
327 prod_f->getNonconstVectorBlock(0);
328 RCP<Thyra::MultiVectorBase<Scalar> > adjoint_f_mv =
329 rcp_dynamic_cast<DMVPV>(adjoint_f,
true)->getNonconstMultiVector();
331 MEB::OutArgs<Scalar> me_outArgs = model_->createOutArgs();
333 if (my_dfdx_ == Teuchos::null)
334 my_dfdx_ = model_->create_W_op();
335 me_outArgs.set_W_op(my_dfdx_);
336 if (me_inArgs.supports(MEB::IN_ARG_alpha))
337 me_inArgs.set_alpha(0.0);
338 if (me_inArgs.supports(MEB::IN_ARG_beta))
339 me_inArgs.set_beta(1.0);
340 model_->evalModel(me_inArgs, me_outArgs);
343 my_dfdx_->apply(Thyra::CONJTRANS, *adjoint_x_mv, adjoint_f_mv.ptr(),
344 Scalar(-1.0), Scalar(0.0));
348 RCP<const DPV> prod_x_dot;
349 if (me_inArgs.supports(MEB::IN_ARG_x_dot)) {
350 RCP<const Thyra::VectorBase<Scalar> > x_dot = inArgs.get_x_dot();
351 if (x_dot != Teuchos::null) {
352 prod_x_dot = rcp_dynamic_cast<
const DPV>(x_dot,
true);
353 RCP<const Thyra::VectorBase<Scalar> > adjoint_x_dot =
354 prod_x_dot->getVectorBlock(0);
355 RCP<const Thyra::MultiVectorBase<Scalar> > adjoint_x_dot_mv =
356 rcp_dynamic_cast<
const DMVPV>(adjoint_x_dot,
true)->getMultiVector();
357 if (mass_matrix_is_identity_) {
359 Thyra::V_StVpV(adjoint_f_mv.ptr(), Scalar(-1.0), *adjoint_f_mv,
363 if (my_dfdxdot_ == Teuchos::null)
364 my_dfdxdot_ = model_->create_W_op();
365 if (!mass_matrix_is_constant_ || !mass_matrix_is_computed_) {
366 me_outArgs.set_W_op(my_dfdxdot_);
367 me_inArgs.set_alpha(1.0);
368 me_inArgs.set_beta(0.0);
369 model_->evalModel(me_inArgs, me_outArgs);
371 mass_matrix_is_computed_ =
true;
373 my_dfdxdot_->apply(Thyra::CONJTRANS, *adjoint_x_dot_mv,
374 adjoint_f_mv.ptr(), Scalar(1.0), Scalar(-1.0));
381 RCP<Thyra::VectorBase<Scalar> > adjoint_g =
382 prod_f->getNonconstVectorBlock(1);
383 RCP<Thyra::MultiVectorBase<Scalar> > adjoint_g_mv =
384 rcp_dynamic_cast<DMVPV>(adjoint_g,
true)->getNonconstMultiVector();
386 MEB::OutArgs<Scalar> me_outArgs2 = model_->createOutArgs();
387 MEB::DerivativeSupport dfdp_support =
388 me_outArgs2.supports(MEB::OUT_ARG_DfDp, p_index_);
389 Thyra::EOpTransp trans = Thyra::CONJTRANS;
390 if (dfdp_support.supports(MEB::DERIV_LINEAR_OP)) {
391 if (my_dfdp_op_ == Teuchos::null)
392 my_dfdp_op_ = model_->create_DfDp_op(p_index_);
393 me_outArgs2.set_DfDp(p_index_, MEB::Derivative<Scalar>(my_dfdp_op_));
394 trans = Thyra::CONJTRANS;
396 else if (dfdp_support.supports(MEB::DERIV_MV_JACOBIAN_FORM)) {
397 if (my_dfdp_mv_ == Teuchos::null)
398 my_dfdp_mv_ = createMembers(model_->get_f_space(),
399 model_->get_p_space(p_index_)->dim());
400 me_outArgs2.set_DfDp(p_index_,
401 MEB::Derivative<Scalar>(my_dfdp_mv_,
402 MEB::DERIV_MV_JACOBIAN_FORM));
403 my_dfdp_op_ = my_dfdp_mv_;
404 trans = Thyra::CONJTRANS;
406 else if (dfdp_support.supports(MEB::DERIV_MV_GRADIENT_FORM)) {
407 if (my_dfdp_mv_ == Teuchos::null)
408 my_dfdp_mv_ = createMembers(model_->get_p_space(p_index_),
409 model_->get_f_space()->dim());
410 me_outArgs2.set_DfDp(p_index_,
411 MEB::Derivative<Scalar>(my_dfdp_mv_,
412 MEB::DERIV_MV_GRADIENT_FORM));
413 my_dfdp_op_ = my_dfdp_mv_;
417 TEUCHOS_TEST_FOR_EXCEPTION(
418 true, std::logic_error,
"Invalid df/dp support");
419 model_->evalModel(me_inArgs, me_outArgs2);
420 my_dfdp_op_->apply(trans, *adjoint_x_mv, adjoint_g_mv.ptr(),
421 Scalar(1.0), Scalar(0.0));
423 if (prod_x_dot != Teuchos::null) {
424 RCP<const Thyra::VectorBase<Scalar> > z_dot =
425 prod_x_dot->getVectorBlock(1);
426 RCP<const Thyra::MultiVectorBase<Scalar> > z_dot_mv =
427 rcp_dynamic_cast<
const DMVPV>(z_dot,
true)->getMultiVector();
428 Thyra::V_VmV(adjoint_g_mv.ptr(), *z_dot_mv, *adjoint_g_mv);
433 template<
class Scalar>
434 Teuchos::RCP<const Teuchos::ParameterList>
438 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
439 pl->set<
int>(
"Sensitivity Parameter Index", 0);
440 pl->set<
int>(
"Response Function Index", 0);
441 pl->set<
bool>(
"Mass Matrix Is Constant",
true);
442 pl->set<
bool>(
"Mass Matrix Is Identity",
false);
Teuchos::RCP< const Thyra::LinearOpWithSolveFactoryBase< Scalar > > get_W_factory() const
Implicit concrete LinearOpBase subclass that takes a flattended out multi-vector and performs a multi...
void setScale(const Scalar &s)
void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
static Teuchos::RCP< const Teuchos::ParameterList > getValidParameters()
Thyra::DefaultProductVector< Scalar > DPV
Teuchos::RCP< Thyra::LinearOpBase< Scalar > > create_W_op() const
bool mass_matrix_is_constant_
Thyra::ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_x_space() const
bool mass_matrix_is_identity_
Teuchos::RCP< const DPVS > f_prod_space_
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int p) const
Thyra::ModelEvaluatorBase::InArgs< Scalar > getNominalValues() const
Thyra::ModelEvaluatorBase::OutArgs< Scalar > createOutArgsImpl() const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_f_space() 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.
Implicit concrete LinearOpBase subclass that takes a flattended out multi-vector and performs a multi...
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_p_space(int p) const
Teuchos::RCP< const DPVS > x_prod_space_
Teuchos::RCP< const DMVPVS > residual_space_
Thyra::DefaultMultiVectorProductVector< Scalar > DMVPV
Teuchos::RCP< const DMVPVS > response_space_
Thyra::ModelEvaluatorBase::OutArgs< Scalar > prototypeOutArgs_
AdjointAuxSensitivityModelEvaluator(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model, const Scalar &t_final, const Teuchos::RCP< const Teuchos::ParameterList > &pList=Teuchos::null)
Constructor.
Teuchos::RCP< const DMVPVS > adjoint_space_
Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > model_