Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_WrapperModelEvaluatorPairPartIMEX_CombinedFSA_impl.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ****************************************************************************
3 // Tempus: Copyright (2017) Sandia Corporation
4 //
5 // Distributed under BSD 3-clause license (See accompanying file Copyright.txt)
6 // ****************************************************************************
7 // @HEADER
8 
9 #ifndef Tempus_ModelEvaluatorPairPartIMEX_CombinedFSA_impl_hpp
10 #define Tempus_ModelEvaluatorPairPartIMEX_CombinedFSA_impl_hpp
11 
12 #include "Thyra_VectorStdOps.hpp"
13 #include "Thyra_MultiVectorStdOps.hpp"
14 
15 namespace Tempus {
16 
17 template <typename Scalar>
21  Scalar> >& forwardModel,
23  : forwardModel_(forwardModel),
24  use_dfdp_as_tangent_(false),
25  y_tangent_index_(3)
26 {
27  using Teuchos::RCP;
28  using Teuchos::rcp;
29  using Thyra::multiVectorProductVectorSpace;
30 
31  RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
32  if (pList != Teuchos::null) *pl = *pList;
34  use_dfdp_as_tangent_ = pl->get<bool>("Use DfDp as Tangent");
35  y_tangent_index_ = pl->get<int>("Sensitivity Y Tangent Index");
36  pl->remove("Sensitivity Y Tangent Index");
37 
38  appExplicitModel_ = forwardModel_->getExplicitModel();
39  appImplicitModel_ = forwardModel_->getImplicitModel();
44 
45  const int y_param_index = forwardModel_->getParameterIndex();
46  const int sens_param_index = pl->get<int>("Sensitivity Parameter Index");
47  const int num_sens_param =
48  appImplicitModel_->get_p_space(sens_param_index)->dim();
49  RCP<const Thyra::VectorSpaceBase<Scalar> > explicit_y_space =
50  appImplicitModel_->get_p_space(y_param_index);
51  RCP<const Thyra::VectorSpaceBase<Scalar> > implicit_x_space =
52  appImplicitModel_->get_x_space();
54  multiVectorProductVectorSpace(explicit_y_space, num_sens_param + 1);
56  multiVectorProductVectorSpace(explicit_y_space, num_sens_param);
58  multiVectorProductVectorSpace(implicit_x_space, num_sens_param + 1);
59 
61  forwardModel_->getNumExplicitOnlyBlocks(), y_param_index);
62 }
63 
64 template <typename Scalar>
66 {
67  using Teuchos::RCP;
68  using Teuchos::rcp_dynamic_cast;
69 
70  this->useImplicitModel_ = true;
71  this->wrapperImplicitInArgs_ = this->createInArgs();
72  this->wrapperImplicitOutArgs_ = this->createOutArgs();
73  this->useImplicitModel_ = false;
74 
75  RCP<const Thyra::VectorBase<Scalar> > z =
76  this->explicitModel_->getNominalValues().get_x();
77 
78  // A Thyra::VectorSpace requirement
80  !(getIMEXVector(z)->space()->isCompatible(
81  *(this->implicitModel_->get_x_space()))),
82  std::logic_error,
83  "Error - WrapperModelEvaluatorPairIMEX_CombinedFSA::initialize()\n"
84  << " Explicit and Implicit vector x spaces are incompatible!\n"
85  << " Explicit vector x space = "
86  << *(getIMEXVector(z)->space())
87  << "\n Implicit vector x space = "
88  << *(this->implicitModel_->get_x_space()) << "\n");
89 
90  // Valid number of blocks?
91  const RCP<const DMVPV> z_dmvpv = rcp_dynamic_cast<const DMVPV>(z, true);
92  const RCP<const Thyra::MultiVectorBase<Scalar> > z_mv =
93  z_dmvpv->getMultiVector();
94  RCP<const PMVB> zPVector = rcp_dynamic_cast<const PMVB>(z_mv);
96  zPVector == Teuchos::null, std::logic_error,
97  "Error - WrapperModelEvaluatorPairPartIMEX_CombinedFSA::initialize()\n"
98  " was given a VectorBase that could not be cast to a\n"
99  " ProductVectorBase!\n");
100 
101  int numBlocks = zPVector->productSpace()->numBlocks();
102 
103  TEUCHOS_TEST_FOR_EXCEPTION(
104  !(0 <= this->numExplicitOnlyBlocks_ &&
105  this->numExplicitOnlyBlocks_ < numBlocks),
106  std::logic_error,
107  "Error - WrapperModelEvaluatorPairPartIMEX_CombinedFSA::initialize()\n"
108  "Invalid number of explicit-only blocks = "
109  << this->numExplicitOnlyBlocks_
110  << "\nShould be in the interval [0, numBlocks) = [0, "
111  << numBlocks << ")\n");
112 }
113 
114 template <typename Scalar>
117 {
118  if (this->useImplicitModel_) {
119  if (i == this->parameterIndex_)
120  return explicit_y_dydp_prod_space_;
121  else
122  return appImplicitModel_->get_p_space(i);
123  }
124 
125  return appExplicitModel_->get_p_space(i);
126 }
127 
128 template <typename Scalar>
131  const Teuchos::RCP<Thyra::VectorBase<Scalar> >& full) const
132 {
133  using Teuchos::RCP;
134  using Teuchos::rcp_dynamic_cast;
136  using Thyra::multiVectorProductVector;
137  using Thyra::VectorBase;
138 
139  // CombinedFSA ME stores vectors as DMVPV's. To extract the implicit
140  // part of the vector, cast it to DMVPV, extract the multi-vector,
141  // cast it to a product multi-vector, extract the IMEX block, then
142  // create a DMVPV from it.
143 
144  if (full == Teuchos::null) return Teuchos::null;
145 
146  if (this->numExplicitOnlyBlocks_ == 0) return full;
147 
148  const RCP<DMVPV> full_dmvpv = rcp_dynamic_cast<DMVPV>(full, true);
149  const RCP<MultiVectorBase<Scalar> > full_mv =
150  full_dmvpv->getNonconstMultiVector();
151  const RCP<PMVB> blk_full_mv = rcp_dynamic_cast<PMVB>(full_mv, true);
152 
153  // special case where the implicit terms are not blocked
154  const int numBlocks = blk_full_mv->productSpace()->numBlocks();
155  const int numExplicitBlocks = this->numExplicitOnlyBlocks_;
156  if (numBlocks == numExplicitBlocks + 1) {
157  const RCP<MultiVectorBase<Scalar> > imex_mv =
158  blk_full_mv->getNonconstMultiVectorBlock(numExplicitBlocks);
159  return multiVectorProductVector(imex_x_dxdp_prod_space_, imex_mv);
160  }
161 
162  // Not supposed to get here, apparently
163  TEUCHOS_ASSERT(false);
164  return Teuchos::null;
165 }
166 
167 template <typename Scalar>
170  const Teuchos::RCP<const Thyra::VectorBase<Scalar> >& full) const
171 {
172  using Teuchos::RCP;
173  using Teuchos::rcp_dynamic_cast;
175  using Thyra::multiVectorProductVector;
176  using Thyra::VectorBase;
177 
178  // CombinedFSA ME stores vectors as DMVPV's. To extract the implicit
179  // part of the vector, cast it to DMVPV, extract the multi-vector,
180  // cast it to a product multi-vector, extract the IMEX block, then
181  // create a DMVPV from it.
182 
183  if (full == Teuchos::null) return Teuchos::null;
184 
185  if (this->numExplicitOnlyBlocks_ == 0) return full;
186 
187  const RCP<const DMVPV> full_dmvpv = rcp_dynamic_cast<const DMVPV>(full, true);
188  const RCP<const MultiVectorBase<Scalar> > full_mv =
189  full_dmvpv->getMultiVector();
190  const RCP<const PMVB> blk_full_mv =
191  rcp_dynamic_cast<const PMVB>(full_mv, true);
192 
193  // special case where the implicit terms are not blocked
194  const int numBlocks = blk_full_mv->productSpace()->numBlocks();
195  const int numExplicitBlocks = this->numExplicitOnlyBlocks_;
196  if (numBlocks == numExplicitBlocks + 1) {
197  const RCP<const MultiVectorBase<Scalar> > imex_mv =
198  blk_full_mv->getMultiVectorBlock(numExplicitBlocks);
199  return multiVectorProductVector(imex_x_dxdp_prod_space_, imex_mv);
200  }
201 
202  // Not supposed to get here, apparently
203  TEUCHOS_ASSERT(false);
204  return Teuchos::null;
205 }
206 
207 template <typename Scalar>
210  const Teuchos::RCP<Thyra::VectorBase<Scalar> >& full) const
211 {
212  using Teuchos::RCP;
213  using Teuchos::rcp_dynamic_cast;
215  using Thyra::multiVectorProductVector;
216  using Thyra::multiVectorProductVectorSpace;
217  using Thyra::VectorBase;
218 
219  // CombinedFSA ME stores vectors as DMVPV's. To extract the explicit
220  // part of the vector, cast it to DMVPV, extract the multi-vector,
221  // cast it to a product multi-vector, extract the explicit block, then
222  // create a DMVPV from it.
223 
224  if (full == Teuchos::null) return Teuchos::null;
225 
226  if (this->numExplicitOnlyBlocks_ == 0) return full;
227 
228  const RCP<DMVPV> full_dmvpv = rcp_dynamic_cast<DMVPV>(full, true);
229  const RCP<MultiVectorBase<Scalar> > full_mv =
230  full_dmvpv->getNonconstMultiVector();
231  const RCP<PMVB> blk_full_mv = rcp_dynamic_cast<PMVB>(full_mv, true);
232 
233  // special case where the explicit terms are not blocked
234  const int numExplicitBlocks = this->numExplicitOnlyBlocks_;
235  if (numExplicitBlocks == 1) {
236  const RCP<MultiVectorBase<Scalar> > explicit_mv =
237  blk_full_mv->getNonconstMultiVectorBlock(0);
238  return multiVectorProductVector(explicit_y_dydp_prod_space_, explicit_mv);
239  }
240 
241  // Not supposed to get here, apparently
242  TEUCHOS_ASSERT(false);
243  return Teuchos::null;
244 }
245 
246 template <typename Scalar>
249  const Teuchos::RCP<const Thyra::VectorBase<Scalar> >& full) const
250 {
251  using Teuchos::RCP;
252  using Teuchos::rcp_dynamic_cast;
254  using Thyra::multiVectorProductVector;
255  using Thyra::multiVectorProductVectorSpace;
256  using Thyra::VectorBase;
257 
258  // CombinedFSA ME stores vectors as DMVPV's. To extract the explicit
259  // part of the vector, cast it to DMVPV, extract the multi-vector,
260  // cast it to a product multi-vector, extract the explicit block, then
261  // create a DMVPV from it.
262 
263  if (full == Teuchos::null) return Teuchos::null;
264 
265  if (this->numExplicitOnlyBlocks_ == 0) return full;
266 
267  const RCP<const DMVPV> full_dmvpv = rcp_dynamic_cast<const DMVPV>(full, true);
268  const RCP<const MultiVectorBase<Scalar> > full_mv =
269  full_dmvpv->getMultiVector();
270  const RCP<const PMVB> blk_full_mv =
271  rcp_dynamic_cast<const PMVB>(full_mv, true);
272 
273  // special case where the explicit terms are not blocked
274  const int numExplicitBlocks = this->numExplicitOnlyBlocks_;
275  if (numExplicitBlocks == 1) {
276  const RCP<const MultiVectorBase<Scalar> > explicit_mv =
277  blk_full_mv->getMultiVectorBlock(0);
278  return multiVectorProductVector(explicit_y_dydp_prod_space_, explicit_mv);
279  }
280 
281  // Not supposed to get here, apparently
282  TEUCHOS_ASSERT(false);
283  return Teuchos::null;
284 }
285 
286 template <typename Scalar>
289 {
290  return forwardModel_;
291 }
292 
293 template <typename Scalar>
296 {
297  using Teuchos::RCP;
298  using Teuchos::rcp_dynamic_cast;
299  using Thyra::createMember;
300 
301  Thyra::ModelEvaluatorBase::InArgs<Scalar> inArgs = Base::createInArgs();
302 
303  // Set p to be the correct product vector form for the explicit only vector y
304  if (this->useImplicitModel_ == true) {
305  RCP<const Thyra::VectorBase<Scalar> > y =
306  inArgs.get_p(this->parameterIndex_);
307  if (y != Teuchos::null) {
308  RCP<DMVPV> y_dydp =
309  rcp_dynamic_cast<DMVPV>(createMember(*explicit_y_dydp_prod_space_));
310  Thyra::assign(y_dydp->getNonconstMultiVector().ptr(), Scalar(0.0));
311  Thyra::assign(y_dydp->getNonconstMultiVector()->col(0).ptr(), *y);
312  inArgs.set_p(this->parameterIndex_, y_dydp);
313  }
314  }
315  return inArgs;
316 }
317 
318 template <typename Scalar>
321  const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs) const
322 {
323  typedef Thyra::ModelEvaluatorBase MEB;
324  using Teuchos::Range1D;
325  using Teuchos::RCP;
326  using Teuchos::rcp_dynamic_cast;
327 
328  const int p_index = this->parameterIndex_;
329 
330  //
331  // From Base::evalModelImpl()
332  //
333  RCP<const Thyra::VectorBase<Scalar> > x = inArgs.get_x();
334  RCP<Thyra::VectorBase<Scalar> > x_dot =
335  Thyra::createMember(fsaImplicitModel_->get_x_space());
336  this->timeDer_->compute(x, x_dot);
337 
338  MEB::InArgs<Scalar> fsaImplicitInArgs(this->wrapperImplicitInArgs_);
339  MEB::OutArgs<Scalar> fsaImplicitOutArgs(this->wrapperImplicitOutArgs_);
340  fsaImplicitInArgs.set_x(x);
341  fsaImplicitInArgs.set_x_dot(x_dot);
342  for (int i = 0; i < fsaImplicitModel_->Np(); ++i) {
343  // Copy over parameters except for the parameter for explicit-only vector!
344  if ((inArgs.get_p(i) != Teuchos::null) && (i != p_index))
345  fsaImplicitInArgs.set_p(i, inArgs.get_p(i));
346  }
347 
348  // p-vector for index parameterIndex_ is part of the IMEX solution vector,
349  // and therefore is an n+1 column multi-vector where n is the number of
350  // sensitivity parameters. Pull out the sensitivity components before
351  // passing along to the ME, then use them for adding in dg/dy*dy/dp term.
352  RCP<const Thyra::VectorBase<Scalar> > y;
353  RCP<const Thyra::MultiVectorBase<Scalar> > dydp;
354  if (fsaImplicitInArgs.get_p(p_index) != Teuchos::null) {
355  RCP<const Thyra::VectorBase<Scalar> > p = fsaImplicitInArgs.get_p(p_index);
356  RCP<const Thyra::MultiVectorBase<Scalar> > p_mv =
357  rcp_dynamic_cast<const DMVPV>(p, true)->getMultiVector();
358  const int num_param = p_mv->domain()->dim() - 1;
359  y = p_mv->col(0);
360  dydp = p_mv->subView(Range1D(1, num_param));
361  fsaImplicitInArgs.set_p(p_index, y);
362  }
363  if (use_dfdp_as_tangent_) {
364  RCP<const Thyra::VectorBase<Scalar> > dydp_vec =
365  Thyra::multiVectorProductVector(explicit_dydp_prod_space_, dydp);
366  fsaImplicitInArgs.set_p(y_tangent_index_, dydp_vec);
367  }
368 
369  fsaImplicitOutArgs.set_f(outArgs.get_f());
370  fsaImplicitOutArgs.set_W_op(outArgs.get_W_op());
371 
372  fsaImplicitModel_->evalModel(fsaImplicitInArgs, fsaImplicitOutArgs);
373 
374  // Compute derivative of implicit residual with respect to explicit only
375  // vector y, which is passed as a parameter
376  if (!use_dfdp_as_tangent_ && outArgs.get_f() != Teuchos::null) {
377  MEB::InArgs<Scalar> appImplicitInArgs =
378  appImplicitModel_->getNominalValues();
379  RCP<const Thyra::VectorBase<Scalar> > app_x =
380  rcp_dynamic_cast<const DMVPV>(x, true)->getMultiVector()->col(0);
381  RCP<const Thyra::VectorBase<Scalar> > app_x_dot =
382  rcp_dynamic_cast<const DMVPV>(x_dot, true)->getMultiVector()->col(0);
383  appImplicitInArgs.set_x(app_x);
384  appImplicitInArgs.set_x_dot(app_x_dot);
385  for (int i = 0; i < appImplicitModel_->Np(); ++i) {
386  if (i != p_index) appImplicitInArgs.set_p(i, inArgs.get_p(i));
387  }
388  appImplicitInArgs.set_p(p_index, y);
389  if (appImplicitInArgs.supports(MEB::IN_ARG_t))
390  appImplicitInArgs.set_t(inArgs.get_t());
391  MEB::OutArgs<Scalar> appImplicitOutArgs =
392  appImplicitModel_->createOutArgs();
393  MEB::DerivativeSupport dfdp_support =
394  appImplicitOutArgs.supports(MEB::OUT_ARG_DfDp, p_index);
396  if (dfdp_support.supports(MEB::DERIV_LINEAR_OP)) {
397  if (my_dfdp_op_ == Teuchos::null)
398  my_dfdp_op_ = appImplicitModel_->create_DfDp_op(p_index);
399  appImplicitOutArgs.set_DfDp(p_index,
400  MEB::Derivative<Scalar>(my_dfdp_op_));
401  trans = Thyra::NOTRANS;
402  }
403  else if (dfdp_support.supports(MEB::DERIV_MV_JACOBIAN_FORM)) {
404  if (my_dfdp_mv_ == Teuchos::null)
405  my_dfdp_mv_ = Thyra::createMembers(
406  appImplicitModel_->get_f_space(),
407  appImplicitModel_->get_p_space(p_index)->dim());
408  appImplicitOutArgs.set_DfDp(
409  p_index,
410  MEB::Derivative<Scalar>(my_dfdp_mv_, MEB::DERIV_MV_JACOBIAN_FORM));
411  my_dfdp_op_ = my_dfdp_mv_;
412  trans = Thyra::NOTRANS;
413  }
414  else if (dfdp_support.supports(MEB::DERIV_MV_GRADIENT_FORM)) {
415  if (my_dfdp_mv_ == Teuchos::null)
416  my_dfdp_mv_ =
417  Thyra::createMembers(appImplicitModel_->get_p_space(p_index),
418  appImplicitModel_->get_f_space()->dim());
419  appImplicitOutArgs.set_DfDp(
420  p_index,
421  MEB::Derivative<Scalar>(my_dfdp_mv_, MEB::DERIV_MV_GRADIENT_FORM));
422  my_dfdp_op_ = my_dfdp_mv_;
423  trans = Thyra::TRANS;
424  }
425  else
426  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
427  "Invalid df/dp support");
428 
429  appImplicitModel_->evalModel(appImplicitInArgs, appImplicitOutArgs);
430 
431  // Add df/dy*dy/dp term to residual
432  RCP<DMVPV> f_dfdp = rcp_dynamic_cast<DMVPV>(outArgs.get_f(), true);
433  const int num_param = f_dfdp->getNonconstMultiVector()->domain()->dim() - 1;
434  RCP<Thyra::MultiVectorBase<Scalar> > dfdp =
435  f_dfdp->getNonconstMultiVector()->subView(Range1D(1, num_param));
436  my_dfdp_op_->apply(trans, *dydp, dfdp.ptr(), Scalar(1.0), Scalar(1.0));
437  }
438 }
439 
440 template <typename Scalar>
443  const
444 {
447  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList(*fsa_pl);
448  pl->set<int>("Sensitivity Y Tangent Index", 3);
449  return pl;
450 }
451 
452 } // namespace Tempus
453 
454 #endif // Tempus_ModelEvaluatorPairPartIMEX_CombinedFSA_impl_hpp
WrapperModelEvaluatorPairPartIMEX_CombinedFSA(const Teuchos::RCP< const WrapperModelEvaluatorPairPartIMEX_Basic< Scalar > > &forwardModel, const Teuchos::RCP< const Teuchos::ParameterList > &pList=Teuchos::null)
Constructor.
EOpTransp
virtual Teuchos::RCP< const ProductVectorSpaceBase< Scalar > > productSpace() const =0
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual Teuchos::RCP< MultiVectorBase< Scalar > > getNonconstMultiVectorBlock(const int k)=0
Evaluation< VectorBase< Scalar > > get_f() const
virtual Teuchos::RCP< Thyra::VectorBase< Scalar > > getExplicitOnlyVector(const Teuchos::RCP< Thyra::VectorBase< Scalar > > &full) const
Extract explicit-only vector from a full solution vector.
virtual Teuchos::RCP< const MultiVectorBase< Scalar > > getMultiVectorBlock(const int k) const =0
virtual Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > getForwardModel() const
Get the underlying forward model.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
ModelEvaluator pair for implicit and explicit (IMEX) evaulations.
virtual Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_p_space(int i) const
Get the p space.
RCP< const VectorBase< Scalar > > col(Ordinal j) const
RCP< const MultiVectorBase< Scalar > > getMultiVector() const
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
void setup(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &explicitModel, const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &implicitModel, int numExplicitOnlyBlocks=0, int parameterIndex=-1)
Setup ME when using default constructor – for derived classes.
void set_p(int l, const RCP< const VectorBase< Scalar > > &p_l)
RCP< MultiVectorBase< Scalar > > getNonconstMultiVector()
#define TEUCHOS_ASSERT(assertion_test)
Teuchos::RCP< const WrapperModelEvaluatorPairPartIMEX_Basic< Scalar > > forwardModel_
RCP< LinearOpBase< Scalar > > get_W_op() const
virtual void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs) const
RCP< const VectorBase< Scalar > > get_x() const
RCP< const VectorBase< Scalar > > get_p(int l) const
Teuchos::Range1D Range1D
virtual Teuchos::RCP< Thyra::VectorBase< Scalar > > getIMEXVector(const Teuchos::RCP< Thyra::VectorBase< Scalar > > &full) const
Extract IMEX vector from a full solution vector.