Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
VanDerPol_IMEX_ExplicitModel_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_EXPLICITMODEL_IMPL_HPP
10 #define TEMPUS_TEST_VANDERPOL_IMEX_EXPLICITMODEL_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 #include "Thyra_DefaultBlockedLinearOp.hpp"
24 
25 #include <iostream>
26 
27 namespace Tempus_Test {
28 
29 template <class Scalar>
31  Teuchos::RCP<Teuchos::ParameterList> pList_, bool useProductVector)
32 {
33  useProductVector_ = useProductVector;
34  isInitialized_ = false;
35  dim_ = 2;
36  Np_ = 3; // Number of parameter vectors (p, dx/dp, dx_dot/dp)
37  np_ = 1; // Number of parameters in this vector (1)
38  Ng_ = 0; // Number of observation functions (0)
39  ng_ = 0; // Number of elements in this observation function (0)
40  acceptModelParams_ = 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  if (useProductVector_ == false) {
48  x_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
49  f_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
50  }
51  else {
52  // Create using ProductVector so we can use in partitioned IMEX-RK Stepper.
53  using Teuchos::RCP;
55  xSpace_ = Thyra::defaultSpmdVectorSpace<Scalar>(1);
56  for (int i = 0; i < dim_; ++i) yxSpaceArray.push_back(xSpace_);
57  x_space_ = Thyra::productVectorSpace<Scalar>(yxSpaceArray);
58  f_space_ = Thyra::productVectorSpace<Scalar>(yxSpaceArray);
59  }
60 
61  // Create p_space and g_space
62  p_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(np_);
63  g_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(ng_);
64  dxdp_space_ = Thyra::multiVectorProductVectorSpace(x_space_, np_);
65 
66  setParameterList(pList_);
67 }
68 
69 template <class Scalar>
72 {
73  return x_space_;
74 }
75 
76 template <class Scalar>
79 {
80  return f_space_;
81 }
82 
83 template <class Scalar>
86 {
87  TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
88  "Error, setupInOutArgs_ must be called first!\n");
89  return nominalValues_;
90 }
91 
92 template <class Scalar>
95 {
97  if (useProductVector_ == false)
98  W_op = Thyra::createMembers(x_space_, dim_);
99  else {
100  // When using product vector formulation, we have to create a block
101  // operator so that its domain space is consistent with x_space_
103  Thyra::createMembers(xSpace_, 1);
105  Thyra::createMembers(xSpace_, 1);
107  Thyra::createMembers(xSpace_, 1);
109  Thyra::createMembers(xSpace_, 1);
110  W_op = Thyra::nonconstBlock2x2(A00, A01, A10, A11);
111  }
112  return W_op;
113 }
114 
115 template <class Scalar>
118 {
119  setupInOutArgs_();
120  return inArgs_;
121 }
122 
123 template <class Scalar>
126 {
127  setupInOutArgs_();
128  return outArgs_;
129 }
130 
131 template <class Scalar>
133 {
134  if (isInitialized_) {
135  return;
136  }
137 
138  {
139  // Set up prototypical InArgs
141  inArgs.setModelEvalDescription(this->description());
142  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_x_dot);
143  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_x);
144  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_t);
145  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_alpha);
146  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_beta);
147  if (acceptModelParams_) {
148  inArgs.set_Np(Np_);
149  }
150  inArgs_ = inArgs;
151  }
152 
153  {
154  // Set up prototypical OutArgs
156  outArgs.setModelEvalDescription(this->description());
157  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_f);
158  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_W_op);
159  if (acceptModelParams_) {
160  outArgs.set_Np_Ng(Np_, Ng_);
161  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_DfDp, 0,
162  Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM);
163  }
164  outArgs_ = outArgs;
165  }
166 
167  // Set up nominal values
168  nominalValues_ = inArgs_;
169  if (haveIC_) {
170  using Teuchos::RCP;
171 
172  nominalValues_.set_t(t0_ic_);
173  const RCP<Thyra::VectorBase<Scalar> > x_ic = createMember(x_space_);
174  { // scope to delete DetachedVectorView
175  Thyra::DetachedVectorView<Scalar> x_ic_view(*x_ic);
176  x_ic_view[0] = x0_ic_;
177  x_ic_view[1] = x1_ic_;
178  }
179  nominalValues_.set_x(x_ic);
180 
181  if (acceptModelParams_) {
182  const RCP<Thyra::VectorBase<Scalar> > p_ic = createMember(p_space_);
183  {
184  Thyra::DetachedVectorView<Scalar> p_ic_view(*p_ic);
185  p_ic_view[0] = epsilon_;
186  }
187  nominalValues_.set_p(0, p_ic);
188  }
189  const RCP<Thyra::VectorBase<Scalar> > x_dot_ic = createMember(x_space_);
190  { // scope to delete DetachedVectorView
191  Thyra::DetachedVectorView<Scalar> x_dot_ic_view(*x_dot_ic);
192  x_dot_ic_view[0] = x1_ic_;
193  x_dot_ic_view[1] = ((1.0 - x0_ic_ * x0_ic_) * x1_ic_ - x0_ic_) / epsilon_;
194  }
195  nominalValues_.set_x_dot(x_dot_ic);
196  }
197 
198  isInitialized_ = true;
199 }
200 
201 template <class Scalar>
203  Teuchos::RCP<Teuchos::ParameterList> const &paramList)
204 {
205  using Teuchos::get;
208  Teuchos::rcp(new ParameterList("VanDerPol_IMEX_ExplicitModel"));
209  if (paramList != Teuchos::null) tmpPL = paramList;
210  tmpPL->validateParametersAndSetDefaults(*this->getValidParameters());
211  this->setMyParamList(tmpPL);
212  Teuchos::RCP<ParameterList> pl = this->getMyNonconstParamList();
213  bool acceptModelParams = get<bool>(*pl, "Accept model parameters");
214  bool haveIC = get<bool>(*pl, "Provide nominal values");
215  bool useDfDpAsTangent = get<bool>(*pl, "Use DfDp as Tangent");
216  if ((acceptModelParams != acceptModelParams_) || (haveIC != haveIC_)) {
217  isInitialized_ = false;
218  }
219  acceptModelParams_ = acceptModelParams;
220  haveIC_ = haveIC;
221  useDfDpAsTangent_ = useDfDpAsTangent;
222  epsilon_ = get<Scalar>(*pl, "Coeff epsilon");
223  x0_ic_ = get<Scalar>(*pl, "IC x0");
224  x1_ic_ = get<Scalar>(*pl, "IC x1");
225  t0_ic_ = get<Scalar>(*pl, "IC t0");
226  setupInOutArgs_();
227 }
228 
229 template <class Scalar>
232 {
234  if (is_null(validPL)) {
235  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
236  pl->set("Accept model parameters", false);
237  pl->set("Provide nominal values", true);
238  pl->set("Use DfDp as Tangent", false);
239  Teuchos::setDoubleParameter("Coeff epsilon", 1.0e-06,
240  "Coefficient a in model", &*pl);
241  Teuchos::setDoubleParameter("IC x0", 2.0, "Initial Condition for x0", &*pl);
242  Teuchos::setDoubleParameter("IC x1", 0.0, "Initial Condition for x1", &*pl);
243  Teuchos::setDoubleParameter("IC t0", 0.0, "Initial time t0", &*pl);
244  validPL = pl;
245  }
246  return validPL;
247 }
248 
249 template <class Scalar>
252 {
253  if (!acceptModelParams_) {
254  return Teuchos::null;
255  }
257  if (l == 0)
258  return p_space_;
259  else if (l == 1 || l == 2)
260  return dxdp_space_;
261  return Teuchos::null;
262 }
263 
264 template <class Scalar>
267 {
268  if (!acceptModelParams_) {
269  return Teuchos::null;
270  }
274  if (l == 0)
275  p_strings->push_back("Model Coefficient: epsilon");
276  else if (l == 1)
277  p_strings->push_back("DxDp");
278  else if (l == 2)
279  p_strings->push_back("Dx_dotDp");
280  return p_strings;
281 }
282 
283 template <class Scalar>
286 {
288  return g_space_;
289 }
290 
291 template <class Scalar>
294  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
295 {
297  using Teuchos::RCP;
298  using Teuchos::rcp_dynamic_cast;
299  TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
300  "Error, setupInOutArgs_ must be called first!\n");
301 
303  inArgs.get_x().assert_not_null();
305 
306  // double t = inArgs.get_t();
307  Scalar beta = inArgs.get_beta();
308  Scalar eps = epsilon_;
309  RCP<const Thyra::MultiVectorBase<Scalar> > dxdp_in, dxdotdp_in;
310  if (acceptModelParams_) {
311  const RCP<const Thyra::VectorBase<Scalar> > p_in = inArgs.get_p(0);
312  if (p_in != Teuchos::null) {
314  eps = p_in_view[0];
315  }
316  if (inArgs.get_p(1) != Teuchos::null) {
317  dxdp_in = rcp_dynamic_cast<const DMVPV>(inArgs.get_p(1), true)
318  ->getMultiVector();
319  }
320  if (inArgs.get_p(2) != Teuchos::null) {
321  dxdotdp_in = rcp_dynamic_cast<const DMVPV>(inArgs.get_p(2), true)
322  ->getMultiVector();
323  }
324  }
325 
326  const RCP<Thyra::VectorBase<Scalar> > f_out = outArgs.get_f();
327  const RCP<Thyra::LinearOpBase<Scalar> > W_out = outArgs.get_W_op();
329  if (acceptModelParams_) {
331  DfDp_out = DfDp.getMultiVector();
332  }
333 
334  if (inArgs.get_x_dot().is_null()) {
335  // Evaluate the Explicit ODE f(x,t) [= xdot]
336  if (!is_null(f_out)) {
337  Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
338  f_out_view[0] = x_in_view[1];
339  f_out_view[1] = -x_in_view[0] / eps;
340  }
341  if (!is_null(DfDp_out)) {
342  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
343  DfDp_out_view(0, 0) = 0.0;
344  DfDp_out_view(1, 0) = x_in_view[0] / (eps * eps);
345 
346  // Compute df/dp + (df/dx) * (dx/dp)
347  if (useDfDpAsTangent_ && !is_null(dxdp_in)) {
349  DfDp_out_view(0, 0) += dxdp(1, 0);
350  DfDp_out_view(1, 0) += -dxdp(0, 0) / eps;
351  }
352  }
353  if (!is_null(W_out)) {
354  if (useProductVector_ == false) {
356  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
357  true);
359  W_view(0, 0) = 0.0; // d(f0)/d(x0_n)
360  W_view(0, 1) = beta; // d(f0)/d(x1_n)
361  W_view(1, 0) = -beta / eps; // d(f1)/d(x0_n)
362  W_view(1, 1) = 0.0; // d(f1)/d(x1_n)
363  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
364  }
365  else {
367  Teuchos::rcp_dynamic_cast<Thyra::DefaultBlockedLinearOp<Scalar> >(
368  W_out, true);
370  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(
371  W_block->getNonconstBlock(0, 0), true);
373  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(
374  W_block->getNonconstBlock(0, 1), true);
376  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(
377  W_block->getNonconstBlock(1, 0), true);
379  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(
380  W_block->getNonconstBlock(1, 1), true);
385  W00_view(0, 0) = 0.0; // d(f0)/d(x0_n)
386  W01_view(0, 0) = beta; // d(f0)/d(x1_n)
387  W10_view(0, 0) = -beta / eps; // d(f1)/d(x0_n)
388  W11_view(0, 0) = 0.0; // d(f1)/d(x1_n)
389  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
390  }
391  }
392  }
393  else {
394  // Evaluate the implicit ODE f(xdot, x, t) [= 0]
396  x_dot_in = inArgs.get_x_dot().assert_not_null();
397  Scalar alpha = inArgs.get_alpha();
398 
399  if (!is_null(f_out)) {
400  Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
401  Thyra::ConstDetachedVectorView<Scalar> x_dot_in_view(*x_dot_in);
402  f_out_view[0] = x_dot_in_view[0] - x_in_view[1];
403  f_out_view[1] = x_dot_in_view[1] + x_in_view[0] / eps;
404  }
405  if (!is_null(DfDp_out)) {
406  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
407  DfDp_out_view(0, 0) = 0.0;
408  DfDp_out_view(1, 0) = -x_in_view[0] / (eps * eps);
409 
410  // Compute df/dp + (df/dx_dot)*(dx_dot/dp) + (df/dx) * (dx/dp)
411  if (useDfDpAsTangent_ && !is_null(dxdotdp_in)) {
412  Thyra::ConstDetachedMultiVectorView<Scalar> dxdotdp(*dxdotdp_in);
413  DfDp_out_view(0, 0) += dxdotdp(0, 0);
414  DfDp_out_view(1, 0) += dxdotdp(1, 0);
415  }
416  if (useDfDpAsTangent_ && !is_null(dxdp_in)) {
418  DfDp_out_view(0, 0) += -dxdp(1, 0);
419  DfDp_out_view(1, 0) += dxdp(0, 0) / eps;
420  }
421  }
422  if (!is_null(W_out)) {
423  if (useProductVector_ == false) {
425  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
426  true);
428  W_view(0, 0) = alpha; // d(f0)/d(x0_n)
429  W_view(0, 1) = -beta; // d(f0)/d(x1_n)
430  W_view(1, 0) = beta / eps; // d(f1)/d(x0_n)
431  W_view(1, 1) = alpha; // d(f1)/d(x1_n)
432  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
433  }
434  else {
436  Teuchos::rcp_dynamic_cast<Thyra::DefaultBlockedLinearOp<Scalar> >(
437  W_out, true);
439  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(
440  W_block->getNonconstBlock(0, 0), true);
442  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(
443  W_block->getNonconstBlock(0, 1), true);
445  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(
446  W_block->getNonconstBlock(1, 0), true);
448  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(
449  W_block->getNonconstBlock(1, 1), true);
454  W00_view(0, 0) = alpha; // d(f0)/d(x0_n)
455  W01_view(0, 0) = -beta; // d(f0)/d(x1_n)
456  W10_view(0, 0) = beta / eps; // d(f1)/d(x0_n)
457  W11_view(0, 0) = alpha; // d(f1)/d(x1_n)
458  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
459  }
460  }
461  }
462 }
463 
464 } // namespace Tempus_Test
465 #endif // TEMPUS_TEST_VANDERPOL_IMEX_EXPLICITMODEL_IMPL_HPP
bool is_null(const boost::shared_ptr< T > &p)
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Derivative< Scalar > get_DfDp(int l) const
RCP< const VectorBase< Scalar > > get_x_dot() const
void setModelEvalDescription(const std::string &modelEvalDescription)
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_f_space() const
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_x_space() const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_p_space(int l) const
Evaluation< VectorBase< Scalar > > get_f() const
void setParameterList(Teuchos::RCP< Teuchos::ParameterList > const &paramList)
#define TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE(index, lower_inclusive, upper_exclusive)
void setSupports(EInArgsMembers arg, bool supports=true)
Teuchos::RCP< Thyra::LinearOpBase< Scalar > > create_W_op() const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Thyra::ModelEvaluatorBase::InArgs< Scalar > getNominalValues() const
Thyra::ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
void push_back(const value_type &x)
void setSupports(EOutArgsMembers arg, bool supports=true)
Thyra::ModelEvaluatorBase::OutArgs< Scalar > createOutArgsImpl() const
VanDerPol_IMEX_ExplicitModel(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null, bool useProductVector=false)
void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs_bar, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs_bar) const
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int l) const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_g_space(int j) const
void setModelEvalDescription(const std::string &modelEvalDescription)
RCP< LinearOpBase< Scalar > > get_W_op() const
RCP< const VectorBase< Scalar > > get_x() const
RCP< const VectorBase< Scalar > > get_p(int l) const
RCP< MultiVectorBase< Scalar > > getMultiVector() const