Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
VanDerPol_IMEX_ImplicitModel_impl.hpp
Go to the documentation of this file.
1 //@HEADER
2 // *****************************************************************************
3 // Tempus: Time Integration and Sensitivity Analysis Package
4 //
5 // Copyright 2017 NTESS and the Tempus contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 //@HEADER
9 
10 #ifndef TEMPUS_TEST_VANDERPOL_IMEX_IMPLICITMODEL_IMPL_HPP
11 #define TEMPUS_TEST_VANDERPOL_IMEX_IMPLICITMODEL_IMPL_HPP
12 
13 #include "Teuchos_StandardParameterEntryValidators.hpp"
14 
15 #include "Thyra_DefaultSpmdVectorSpace.hpp"
16 #include "Thyra_DetachedVectorView.hpp"
17 #include "Thyra_DetachedMultiVectorView.hpp"
18 #include "Thyra_DefaultSerialDenseLinearOpWithSolveFactory.hpp"
19 #include "Thyra_DefaultMultiVectorLinearOpWithSolve.hpp"
20 #include "Thyra_DefaultLinearOpSource.hpp"
21 #include "Thyra_VectorStdOps.hpp"
22 #include "Thyra_MultiVectorStdOps.hpp"
23 #include "Thyra_DefaultMultiVectorProductVector.hpp"
24 
25 #include <iostream>
26 
27 namespace Tempus_Test {
28 
29 template <class Scalar>
32 {
33  isInitialized_ = false;
34  dim_ = 2;
35  Np_ = 3; // Number of parameter vectors (p, dx/dp, dx_dot/dp)
36  np_ = 1; // Number of parameters in this vector (1)
37  Ng_ = 0; // Number of observation functions (0)
38  ng_ = 0; // Number of elements in this observation function (0)
39  acceptModelParams_ = false;
40  useDfDpAsTangent_ = false;
41  haveIC_ = true;
42  epsilon_ = 1.0e-06;
43  x0_ic_ = 2.0;
44  x1_ic_ = 0.0;
45  t0_ic_ = 0.0;
46 
47  // Create x_space and f_space
48  x_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
49  f_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
50  // Create p_space and g_space
51  p_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(np_);
52  dxdp_space_ = Thyra::multiVectorProductVectorSpace(x_space_, np_);
53 
54  // g_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(ng_);
55 
56  setParameterList(pList_);
57 }
58 
59 template <class Scalar>
62 {
63  return x_space_;
64 }
65 
66 template <class Scalar>
69 {
70  return f_space_;
71 }
72 
73 template <class Scalar>
76 {
77  TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
78  "Error, setupInOutArgs_ must be called first!\n");
79  return nominalValues_;
80 }
81 
82 template <class Scalar>
85 {
86  using Teuchos::RCP;
88  this->get_W_factory();
89  RCP<Thyra::LinearOpBase<Scalar> > matrix = this->create_W_op();
90  {
91  // 01/20/09 tscoffe: This is a total hack to provide a full rank matrix to
92  // linearOpWithSolve because it ends up factoring the matrix during
93  // initialization, which it really shouldn't do, or I'm doing something
94  // wrong here. The net effect is that I get exceptions thrown in
95  // optimized mode due to the matrix being rank deficient unless I do this.
97  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(matrix,
98  true);
99  {
100  RCP<Thyra::VectorBase<Scalar> > vec = Thyra::createMember(x_space_);
101  {
102  Thyra::DetachedVectorView<Scalar> vec_view(*vec);
103  vec_view[0] = 0.0;
104  vec_view[1] = 1.0;
105  }
106  V_V(multivec->col(0).ptr(), *vec);
107  {
108  Thyra::DetachedVectorView<Scalar> vec_view(*vec);
109  vec_view[0] = 1.0;
110  vec_view[1] = 0.0;
111  }
112  V_V(multivec->col(1).ptr(), *vec);
113  }
114  }
116  Thyra::linearOpWithSolve<Scalar>(*W_factory, matrix);
117 
118  return W;
119 }
120 
121 template <class Scalar>
124 {
126  Thyra::createMembers(x_space_, dim_);
127  return (matrix);
128 }
129 
130 template <class Scalar>
133 {
135  Thyra::defaultSerialDenseLinearOpWithSolveFactory<Scalar>();
136  return W_factory;
137 }
138 
139 template <class Scalar>
142 {
143  setupInOutArgs_();
144  return inArgs_;
145 }
146 
147 // Private functions overridden from ModelEvaluatorDefaultBase
148 
149 template <class Scalar>
152 {
153  setupInOutArgs_();
154  return outArgs_;
155 }
156 
157 template <class Scalar>
160  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
161 {
163  using Teuchos::RCP;
164  using Teuchos::rcp_dynamic_cast;
165  TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
166  "Error, setupInOutArgs_ must be called first!\n");
167 
169  inArgs.get_x().assert_not_null();
171 
172  // double t = inArgs.get_t();
173  Scalar beta = inArgs.get_beta();
174  Scalar eps = epsilon_;
175  RCP<const Thyra::MultiVectorBase<Scalar> > dxdp_in, dxdotdp_in;
176  if (acceptModelParams_) {
177  const RCP<const Thyra::VectorBase<Scalar> > p_in = inArgs.get_p(0);
178  if (p_in != Teuchos::null) {
180  eps = p_in_view[0];
181  }
182  if (inArgs.get_p(1) != Teuchos::null) {
183  dxdp_in = rcp_dynamic_cast<const DMVPV>(inArgs.get_p(1), true)
184  ->getMultiVector();
185  }
186  if (inArgs.get_p(2) != Teuchos::null) {
187  dxdotdp_in = rcp_dynamic_cast<const DMVPV>(inArgs.get_p(2), true)
188  ->getMultiVector();
189  }
190  }
191 
192  const RCP<Thyra::VectorBase<Scalar> > f_out = outArgs.get_f();
193  const RCP<Thyra::LinearOpBase<Scalar> > W_out = outArgs.get_W_op();
195  if (acceptModelParams_) {
197  DfDp_out = DfDp.getMultiVector();
198  }
199 
200  if (inArgs.get_x_dot().is_null()) {
201  // Evaluate the Explicit ODE f(x,t) [= xdot]
202  if (!is_null(f_out)) {
203  Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
204  f_out_view[0] = 0;
205  f_out_view[1] = (1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] / eps;
206  }
207  if (!is_null(DfDp_out)) {
208  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
209  DfDp_out_view(0, 0) = 0.0;
210  DfDp_out_view(1, 0) =
211  -(1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] / (eps * eps);
212 
213  // Compute df/dp + (df/dx) * (dx/dp)
214  if (useDfDpAsTangent_ && !is_null(dxdp_in)) {
216  DfDp_out_view(1, 0) +=
217  -2.0 * x_in_view[0] * x_in_view[1] / eps * dxdp(0, 0) +
218  (1.0 - x_in_view[0] * x_in_view[0]) / eps * dxdp(1, 0);
219  }
220  }
221  if (!is_null(W_out)) {
223  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
224  true);
226  W_view(0, 0) = 0.0; // d(f0)/d(x0_n)
227  W_view(0, 1) = 0.0; // d(f0)/d(x1_n)
228  W_view(1, 0) =
229  -2.0 * beta * x_in_view[0] * x_in_view[1] / eps; // d(f1)/d(x0_n)
230  W_view(1, 1) =
231  beta * (1.0 - x_in_view[0] * x_in_view[0]) / eps; // d(f1)/d(x1_n)
232  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
233  }
234  }
235  else {
236  // Evaluate the implicit ODE f(xdot, x, t) [= 0]
238  x_dot_in = inArgs.get_x_dot().assert_not_null();
239  Scalar alpha = inArgs.get_alpha();
240 
241  if (!is_null(f_out)) {
242  Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
243  Thyra::ConstDetachedVectorView<Scalar> x_dot_in_view(*x_dot_in);
244  f_out_view[0] = x_dot_in_view[0];
245  f_out_view[1] = x_dot_in_view[1] -
246  (1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] / eps;
247  }
248  if (!is_null(DfDp_out)) {
249  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
250  DfDp_out_view(0, 0) = 0.0;
251  DfDp_out_view(1, 0) =
252  (1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] / (eps * eps);
253 
254  // Compute df/dp + (df/dx_dot)*(dx_dot/dp) + (df/dx)*(dx/dp)
255  if (useDfDpAsTangent_ && !is_null(dxdotdp_in)) {
256  Thyra::ConstDetachedMultiVectorView<Scalar> dxdotdp(*dxdotdp_in);
257  DfDp_out_view(0, 0) += dxdotdp(0, 0);
258  DfDp_out_view(1, 0) += dxdotdp(1, 0);
259  }
260  if (useDfDpAsTangent_ && !is_null(dxdp_in)) {
262  DfDp_out_view(1, 0) +=
263  2.0 * x_in_view[0] * x_in_view[1] / eps * dxdp(0, 0) -
264  (1.0 - x_in_view[0] * x_in_view[0]) / eps * dxdp(1, 0);
265  }
266  }
267  if (!is_null(W_out)) {
269  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
270  true);
272  W_view(0, 0) = alpha; // d(f0)/d(x0_n)
273  W_view(0, 1) = 0.0; // d(f0)/d(x1_n)
274  W_view(1, 0) =
275  2.0 * beta * x_in_view[0] * x_in_view[1] / eps; // d(f1)/d(x0_n)
276  W_view(1, 1) = alpha - beta * (1.0 - x_in_view[0] * x_in_view[0]) /
277  eps; // d(f1)/d(x1_n)
278  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
279  }
280  }
281 }
282 
283 template <class Scalar>
286 {
287  if (!acceptModelParams_) {
288  return Teuchos::null;
289  }
291  if (l == 0)
292  return p_space_;
293  else if (l == 1 || l == 2)
294  return dxdp_space_;
295  return Teuchos::null;
296 }
297 
298 template <class Scalar>
301 {
302  if (!acceptModelParams_) {
303  return Teuchos::null;
304  }
308  p_strings->push_back("Model Coefficient: epsilon");
309  if (l == 0)
310  p_strings->push_back("Model Coefficient: epsilon");
311  else if (l == 1)
312  p_strings->push_back("DxDp");
313  else if (l == 2)
314  p_strings->push_back("Dx_dotDp");
315  return p_strings;
316 }
317 
318 template <class Scalar>
321 {
323  return g_space_;
324 }
325 
326 template <class Scalar>
328 {
329  if (isInitialized_) {
330  return;
331  }
332 
333  {
334  // Set up prototypical InArgs
336  inArgs.setModelEvalDescription(this->description());
337  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_x_dot);
338  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_x);
339  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_t);
340  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_alpha);
341  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_beta);
342  if (acceptModelParams_) {
343  inArgs.set_Np(Np_);
344  }
345  inArgs_ = inArgs;
346  }
347 
348  {
349  // Set up prototypical OutArgs
351  outArgs.setModelEvalDescription(this->description());
352  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_f);
353  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_W_op);
354  if (acceptModelParams_) {
355  outArgs.set_Np_Ng(Np_, Ng_);
356  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_DfDp, 0,
357  Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM);
358  }
359  outArgs_ = outArgs;
360  }
361 
362  // Set up nominal values
363  nominalValues_ = inArgs_;
364  if (haveIC_) {
365  nominalValues_.set_t(t0_ic_);
367  createMember(x_space_);
368  { // scope to delete DetachedVectorView
369  Thyra::DetachedVectorView<Scalar> x_ic_view(*x_ic);
370  x_ic_view[0] = x0_ic_;
371  x_ic_view[1] = x1_ic_;
372  }
373  nominalValues_.set_x(x_ic);
374  if (acceptModelParams_) {
376  createMember(p_space_);
377  {
378  Thyra::DetachedVectorView<Scalar> p_ic_view(*p_ic);
379  p_ic_view[0] = epsilon_;
380  }
381  nominalValues_.set_p(0, p_ic);
382  }
383  const Teuchos::RCP<Thyra::VectorBase<Scalar> > x_dot_ic =
384  createMember(x_space_);
385  { // scope to delete DetachedVectorView
386  Thyra::DetachedVectorView<Scalar> x_dot_ic_view(*x_dot_ic);
387  x_dot_ic_view[0] = x1_ic_;
388  x_dot_ic_view[1] = ((1.0 - x0_ic_ * x0_ic_) * x1_ic_ - x0_ic_) / epsilon_;
389  }
390  nominalValues_.set_x_dot(x_dot_ic);
391  }
392 
393  isInitialized_ = true;
394 }
395 
396 template <class Scalar>
398  Teuchos::RCP<Teuchos::ParameterList> const &paramList)
399 {
400  using Teuchos::get;
403  Teuchos::rcp(new ParameterList("VanDerPol_IMEX_ImplicitModel"));
404  if (paramList != Teuchos::null) tmpPL = paramList;
405  tmpPL->validateParametersAndSetDefaults(*this->getValidParameters());
406  this->setMyParamList(tmpPL);
407  Teuchos::RCP<ParameterList> pl = this->getMyNonconstParamList();
408  bool acceptModelParams = get<bool>(*pl, "Accept model parameters");
409  bool haveIC = get<bool>(*pl, "Provide nominal values");
410  bool useDfDpAsTangent = get<bool>(*pl, "Use DfDp as Tangent");
411  if ((acceptModelParams != acceptModelParams_) || (haveIC != haveIC_)) {
412  isInitialized_ = false;
413  }
414  acceptModelParams_ = acceptModelParams;
415  haveIC_ = haveIC;
416  useDfDpAsTangent_ = useDfDpAsTangent;
417  epsilon_ = get<Scalar>(*pl, "Coeff epsilon");
418  x0_ic_ = get<Scalar>(*pl, "IC x0");
419  x1_ic_ = get<Scalar>(*pl, "IC x1");
420  t0_ic_ = get<Scalar>(*pl, "IC t0");
421  setupInOutArgs_();
422 }
423 
424 template <class Scalar>
427 {
429  if (is_null(validPL)) {
430  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
431  pl->set("Accept model parameters", false);
432  pl->set("Provide nominal values", true);
433  pl->set("Use DfDp as Tangent", false);
434  Teuchos::setDoubleParameter("Coeff epsilon", 1.0e-06,
435  "Coefficient a in model", &*pl);
436  Teuchos::setDoubleParameter("IC x0", 2.0, "Initial Condition for x0", &*pl);
437  Teuchos::setDoubleParameter("IC x1", 0.0, "Initial Condition for x1", &*pl);
438  Teuchos::setDoubleParameter("IC t0", 0.0, "Initial time t0", &*pl);
439  validPL = pl;
440  }
441  return validPL;
442 }
443 
444 } // namespace Tempus_Test
445 #endif // TEMPUS_TEST_VANDERPOL_IMEX_IMPLICITMODEL_IMPL_HPP
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_p_space(int l) const
Teuchos::RCP< Thyra::LinearOpWithSolveBase< Scalar > > create_W() const
bool is_null(const boost::shared_ptr< T > &p)
Derivative< Scalar > get_DfDp(int l) const
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
RCP< const VectorBase< Scalar > > get_x_dot() const
void setModelEvalDescription(const std::string &modelEvalDescription)
VanDerPol_IMEX_ImplicitModel(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Teuchos::RCP< const Thyra::LinearOpWithSolveFactoryBase< Scalar > > get_W_factory() const
Thyra::ModelEvaluatorBase::OutArgs< Scalar > createOutArgsImpl() const
Thyra::ModelEvaluatorBase::InArgs< Scalar > getNominalValues() const
Evaluation< VectorBase< Scalar > > get_f() const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_g_space(int j) const
#define TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE(index, lower_inclusive, upper_exclusive)
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_x_space() const
void setSupports(EInArgsMembers arg, bool supports=true)
void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs_bar, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs_bar) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int l) const
Ptr< T > ptr() const
Thyra::ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
void setSupports(EOutArgsMembers arg, bool supports=true)
void setParameterList(Teuchos::RCP< Teuchos::ParameterList > const &paramList)
void setModelEvalDescription(const std::string &modelEvalDescription)
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_f_space() const
RCP< LinearOpBase< Scalar > > get_W_op() const
RCP< const VectorBase< Scalar > > get_x() const
Teuchos::RCP< Thyra::LinearOpBase< Scalar > > create_W_op() const
RCP< const VectorBase< Scalar > > get_p(int l) const
RCP< MultiVectorBase< Scalar > > getMultiVector() const