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: Copyright (2017) Sandia Corporation
4 //
5 // Distributed under BSD 3-clause license (See accompanying file Copyright.txt)
6 // ****************************************************************************
7 // @HEADER
8 
9 #ifndef TEMPUS_TEST_VANDERPOL_IMEX_IMPLICITMODEL_IMPL_HPP
10 #define TEMPUS_TEST_VANDERPOL_IMEX_IMPLICITMODEL_IMPL_HPP
11 
12 #include "Teuchos_StandardParameterEntryValidators.hpp"
13 
14 #include "Thyra_DefaultSpmdVectorSpace.hpp"
15 #include "Thyra_DetachedVectorView.hpp"
16 #include "Thyra_DetachedMultiVectorView.hpp"
17 #include "Thyra_DefaultSerialDenseLinearOpWithSolveFactory.hpp"
18 #include "Thyra_DefaultMultiVectorLinearOpWithSolve.hpp"
19 #include "Thyra_DefaultLinearOpSource.hpp"
20 #include "Thyra_VectorStdOps.hpp"
21 #include "Thyra_MultiVectorStdOps.hpp"
22 #include "Thyra_DefaultMultiVectorProductVector.hpp"
23 
24 #include <iostream>
25 
26 namespace Tempus_Test {
27 
28 template <class Scalar>
31 {
32  isInitialized_ = false;
33  dim_ = 2;
34  Np_ = 3; // Number of parameter vectors (p, dx/dp, dx_dot/dp)
35  np_ = 1; // Number of parameters in this vector (1)
36  Ng_ = 0; // Number of observation functions (0)
37  ng_ = 0; // Number of elements in this observation function (0)
38  acceptModelParams_ = false;
39  useDfDpAsTangent_ = false;
40  haveIC_ = true;
41  epsilon_ = 1.0e-06;
42  x0_ic_ = 2.0;
43  x1_ic_ = 0.0;
44  t0_ic_ = 0.0;
45 
46  // Create x_space and f_space
47  x_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
48  f_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
49  // Create p_space and g_space
50  p_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(np_);
51  dxdp_space_ = Thyra::multiVectorProductVectorSpace(x_space_, np_);
52 
53  // g_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(ng_);
54 
55  setParameterList(pList_);
56 }
57 
58 template <class Scalar>
61 {
62  return x_space_;
63 }
64 
65 template <class Scalar>
68 {
69  return f_space_;
70 }
71 
72 template <class Scalar>
75 {
76  TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
77  "Error, setupInOutArgs_ must be called first!\n");
78  return nominalValues_;
79 }
80 
81 template <class Scalar>
84 {
85  using Teuchos::RCP;
87  this->get_W_factory();
88  RCP<Thyra::LinearOpBase<Scalar> > matrix = this->create_W_op();
89  {
90  // 01/20/09 tscoffe: This is a total hack to provide a full rank matrix to
91  // linearOpWithSolve because it ends up factoring the matrix during
92  // initialization, which it really shouldn't do, or I'm doing something
93  // wrong here. The net effect is that I get exceptions thrown in
94  // optimized mode due to the matrix being rank deficient unless I do this.
96  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(matrix,
97  true);
98  {
99  RCP<Thyra::VectorBase<Scalar> > vec = Thyra::createMember(x_space_);
100  {
101  Thyra::DetachedVectorView<Scalar> vec_view(*vec);
102  vec_view[0] = 0.0;
103  vec_view[1] = 1.0;
104  }
105  V_V(multivec->col(0).ptr(), *vec);
106  {
107  Thyra::DetachedVectorView<Scalar> vec_view(*vec);
108  vec_view[0] = 1.0;
109  vec_view[1] = 0.0;
110  }
111  V_V(multivec->col(1).ptr(), *vec);
112  }
113  }
115  Thyra::linearOpWithSolve<Scalar>(*W_factory, matrix);
116 
117  return W;
118 }
119 
120 template <class Scalar>
123 {
125  Thyra::createMembers(x_space_, dim_);
126  return (matrix);
127 }
128 
129 template <class Scalar>
132 {
134  Thyra::defaultSerialDenseLinearOpWithSolveFactory<Scalar>();
135  return W_factory;
136 }
137 
138 template <class Scalar>
141 {
142  setupInOutArgs_();
143  return inArgs_;
144 }
145 
146 // Private functions overridden from ModelEvaluatorDefaultBase
147 
148 template <class Scalar>
151 {
152  setupInOutArgs_();
153  return outArgs_;
154 }
155 
156 template <class Scalar>
159  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
160 {
162  using Teuchos::RCP;
163  using Teuchos::rcp_dynamic_cast;
164  TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
165  "Error, setupInOutArgs_ must be called first!\n");
166 
168  inArgs.get_x().assert_not_null();
170 
171  // double t = inArgs.get_t();
172  Scalar beta = inArgs.get_beta();
173  Scalar eps = epsilon_;
174  RCP<const Thyra::MultiVectorBase<Scalar> > dxdp_in, dxdotdp_in;
175  if (acceptModelParams_) {
176  const RCP<const Thyra::VectorBase<Scalar> > p_in = inArgs.get_p(0);
177  if (p_in != Teuchos::null) {
179  eps = p_in_view[0];
180  }
181  if (inArgs.get_p(1) != Teuchos::null) {
182  dxdp_in = rcp_dynamic_cast<const DMVPV>(inArgs.get_p(1), true)
183  ->getMultiVector();
184  }
185  if (inArgs.get_p(2) != Teuchos::null) {
186  dxdotdp_in = rcp_dynamic_cast<const DMVPV>(inArgs.get_p(2), true)
187  ->getMultiVector();
188  }
189  }
190 
191  const RCP<Thyra::VectorBase<Scalar> > f_out = outArgs.get_f();
192  const RCP<Thyra::LinearOpBase<Scalar> > W_out = outArgs.get_W_op();
194  if (acceptModelParams_) {
196  DfDp_out = DfDp.getMultiVector();
197  }
198 
199  if (inArgs.get_x_dot().is_null()) {
200  // Evaluate the Explicit ODE f(x,t) [= xdot]
201  if (!is_null(f_out)) {
202  Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
203  f_out_view[0] = 0;
204  f_out_view[1] = (1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] / eps;
205  }
206  if (!is_null(DfDp_out)) {
207  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
208  DfDp_out_view(0, 0) = 0.0;
209  DfDp_out_view(1, 0) =
210  -(1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] / (eps * eps);
211 
212  // Compute df/dp + (df/dx) * (dx/dp)
213  if (useDfDpAsTangent_ && !is_null(dxdp_in)) {
215  DfDp_out_view(1, 0) +=
216  -2.0 * x_in_view[0] * x_in_view[1] / eps * dxdp(0, 0) +
217  (1.0 - x_in_view[0] * x_in_view[0]) / eps * dxdp(1, 0);
218  }
219  }
220  if (!is_null(W_out)) {
222  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
223  true);
225  W_view(0, 0) = 0.0; // d(f0)/d(x0_n)
226  W_view(0, 1) = 0.0; // d(f0)/d(x1_n)
227  W_view(1, 0) =
228  -2.0 * beta * x_in_view[0] * x_in_view[1] / eps; // d(f1)/d(x0_n)
229  W_view(1, 1) =
230  beta * (1.0 - x_in_view[0] * x_in_view[0]) / eps; // d(f1)/d(x1_n)
231  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
232  }
233  }
234  else {
235  // Evaluate the implicit ODE f(xdot, x, t) [= 0]
237  x_dot_in = inArgs.get_x_dot().assert_not_null();
238  Scalar alpha = inArgs.get_alpha();
239 
240  if (!is_null(f_out)) {
241  Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
242  Thyra::ConstDetachedVectorView<Scalar> x_dot_in_view(*x_dot_in);
243  f_out_view[0] = x_dot_in_view[0];
244  f_out_view[1] = x_dot_in_view[1] -
245  (1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] / eps;
246  }
247  if (!is_null(DfDp_out)) {
248  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
249  DfDp_out_view(0, 0) = 0.0;
250  DfDp_out_view(1, 0) =
251  (1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] / (eps * eps);
252 
253  // Compute df/dp + (df/dx_dot)*(dx_dot/dp) + (df/dx)*(dx/dp)
254  if (useDfDpAsTangent_ && !is_null(dxdotdp_in)) {
255  Thyra::ConstDetachedMultiVectorView<Scalar> dxdotdp(*dxdotdp_in);
256  DfDp_out_view(0, 0) += dxdotdp(0, 0);
257  DfDp_out_view(1, 0) += dxdotdp(1, 0);
258  }
259  if (useDfDpAsTangent_ && !is_null(dxdp_in)) {
261  DfDp_out_view(1, 0) +=
262  2.0 * x_in_view[0] * x_in_view[1] / eps * dxdp(0, 0) -
263  (1.0 - x_in_view[0] * x_in_view[0]) / eps * dxdp(1, 0);
264  }
265  }
266  if (!is_null(W_out)) {
268  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
269  true);
271  W_view(0, 0) = alpha; // d(f0)/d(x0_n)
272  W_view(0, 1) = 0.0; // d(f0)/d(x1_n)
273  W_view(1, 0) =
274  2.0 * beta * x_in_view[0] * x_in_view[1] / eps; // d(f1)/d(x0_n)
275  W_view(1, 1) = alpha - beta * (1.0 - x_in_view[0] * x_in_view[0]) /
276  eps; // d(f1)/d(x1_n)
277  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
278  }
279  }
280 }
281 
282 template <class Scalar>
285 {
286  if (!acceptModelParams_) {
287  return Teuchos::null;
288  }
290  if (l == 0)
291  return p_space_;
292  else if (l == 1 || l == 2)
293  return dxdp_space_;
294  return Teuchos::null;
295 }
296 
297 template <class Scalar>
300 {
301  if (!acceptModelParams_) {
302  return Teuchos::null;
303  }
307  p_strings->push_back("Model Coefficient: epsilon");
308  if (l == 0)
309  p_strings->push_back("Model Coefficient: epsilon");
310  else if (l == 1)
311  p_strings->push_back("DxDp");
312  else if (l == 2)
313  p_strings->push_back("Dx_dotDp");
314  return p_strings;
315 }
316 
317 template <class Scalar>
320 {
322  return g_space_;
323 }
324 
325 template <class Scalar>
327 {
328  if (isInitialized_) {
329  return;
330  }
331 
332  {
333  // Set up prototypical InArgs
335  inArgs.setModelEvalDescription(this->description());
336  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_x_dot);
337  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_x);
338  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_t);
339  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_alpha);
340  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_beta);
341  if (acceptModelParams_) {
342  inArgs.set_Np(Np_);
343  }
344  inArgs_ = inArgs;
345  }
346 
347  {
348  // Set up prototypical OutArgs
350  outArgs.setModelEvalDescription(this->description());
351  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_f);
352  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_W_op);
353  if (acceptModelParams_) {
354  outArgs.set_Np_Ng(Np_, Ng_);
355  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_DfDp, 0,
356  Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM);
357  }
358  outArgs_ = outArgs;
359  }
360 
361  // Set up nominal values
362  nominalValues_ = inArgs_;
363  if (haveIC_) {
364  nominalValues_.set_t(t0_ic_);
366  createMember(x_space_);
367  { // scope to delete DetachedVectorView
368  Thyra::DetachedVectorView<Scalar> x_ic_view(*x_ic);
369  x_ic_view[0] = x0_ic_;
370  x_ic_view[1] = x1_ic_;
371  }
372  nominalValues_.set_x(x_ic);
373  if (acceptModelParams_) {
375  createMember(p_space_);
376  {
377  Thyra::DetachedVectorView<Scalar> p_ic_view(*p_ic);
378  p_ic_view[0] = epsilon_;
379  }
380  nominalValues_.set_p(0, p_ic);
381  }
382  const Teuchos::RCP<Thyra::VectorBase<Scalar> > x_dot_ic =
383  createMember(x_space_);
384  { // scope to delete DetachedVectorView
385  Thyra::DetachedVectorView<Scalar> x_dot_ic_view(*x_dot_ic);
386  x_dot_ic_view[0] = x1_ic_;
387  x_dot_ic_view[1] = ((1.0 - x0_ic_ * x0_ic_) * x1_ic_ - x0_ic_) / epsilon_;
388  }
389  nominalValues_.set_x_dot(x_dot_ic);
390  }
391 
392  isInitialized_ = true;
393 }
394 
395 template <class Scalar>
397  Teuchos::RCP<Teuchos::ParameterList> const &paramList)
398 {
399  using Teuchos::get;
402  Teuchos::rcp(new ParameterList("VanDerPol_IMEX_ImplicitModel"));
403  if (paramList != Teuchos::null) tmpPL = paramList;
404  tmpPL->validateParametersAndSetDefaults(*this->getValidParameters());
405  this->setMyParamList(tmpPL);
406  Teuchos::RCP<ParameterList> pl = this->getMyNonconstParamList();
407  bool acceptModelParams = get<bool>(*pl, "Accept model parameters");
408  bool haveIC = get<bool>(*pl, "Provide nominal values");
409  bool useDfDpAsTangent = get<bool>(*pl, "Use DfDp as Tangent");
410  if ((acceptModelParams != acceptModelParams_) || (haveIC != haveIC_)) {
411  isInitialized_ = false;
412  }
413  acceptModelParams_ = acceptModelParams;
414  haveIC_ = haveIC;
415  useDfDpAsTangent_ = useDfDpAsTangent;
416  epsilon_ = get<Scalar>(*pl, "Coeff epsilon");
417  x0_ic_ = get<Scalar>(*pl, "IC x0");
418  x1_ic_ = get<Scalar>(*pl, "IC x1");
419  t0_ic_ = get<Scalar>(*pl, "IC t0");
420  setupInOutArgs_();
421 }
422 
423 template <class Scalar>
426 {
428  if (is_null(validPL)) {
429  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
430  pl->set("Accept model parameters", false);
431  pl->set("Provide nominal values", true);
432  pl->set("Use DfDp as Tangent", false);
433  Teuchos::setDoubleParameter("Coeff epsilon", 1.0e-06,
434  "Coefficient a in model", &*pl);
435  Teuchos::setDoubleParameter("IC x0", 2.0, "Initial Condition for x0", &*pl);
436  Teuchos::setDoubleParameter("IC x1", 0.0, "Initial Condition for x1", &*pl);
437  Teuchos::setDoubleParameter("IC t0", 0.0, "Initial time t0", &*pl);
438  validPL = pl;
439  }
440  return validPL;
441 }
442 
443 } // namespace Tempus_Test
444 #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)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
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
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