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 
28 namespace Tempus_Test {
29 
30 template<class Scalar>
33  Teuchos::RCP<Teuchos::ParameterList> pList_, bool useProductVector)
34 {
35  useProductVector_ = useProductVector;
36  isInitialized_ = false;
37  dim_ = 2;
38  Np_ = 3; // Number of parameter vectors (p, dx/dp, dx_dot/dp)
39  np_ = 1; // Number of parameters in this vector (1)
40  Ng_ = 0; // Number of observation functions (0)
41  ng_ = 0; // Number of elements in this observation function (0)
42  acceptModelParams_ = false;
43  haveIC_ = true;
44  epsilon_ = 1.0e-06;
45  x0_ic_ = 2.0;
46  x1_ic_ = 0.0;
47  t0_ic_ = 0.0;
48 
49  if (useProductVector_ == false) {
50  x_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
51  f_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
52  } else {
53  // Create using ProductVector so we can use in partitioned IMEX-RK Stepper.
54  using Teuchos::RCP;
56  xSpace_ = Thyra::defaultSpmdVectorSpace<Scalar>(1);
57  for (int i=0; i < dim_; ++i) yxSpaceArray.push_back(xSpace_);
58  x_space_ = Thyra::productVectorSpace<Scalar>(yxSpaceArray);
59  f_space_ = Thyra::productVectorSpace<Scalar>(yxSpaceArray);
60  }
61 
62  // Create p_space and g_space
63  p_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(np_);
64  g_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(ng_);
65  dxdp_space_ = Thyra::multiVectorProductVectorSpace(x_space_, np_);
66 
67  setParameterList(pList_);
68 }
69 
70 template<class Scalar>
73 get_x_space() const
74 {
75  return x_space_;
76 }
77 
78 
79 template<class Scalar>
82 get_f_space() const
83 {
84  return f_space_;
85 }
86 
87 
88 template<class Scalar>
92 {
93  TEUCHOS_TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error,
94  "Error, setupInOutArgs_ must be called first!\n");
95  return nominalValues_;
96 }
97 
98 
99 template<class Scalar>
102 create_W_op() const
103 {
105  if (useProductVector_ == false)
106  W_op = Thyra::createMembers(x_space_, dim_);
107  else {
108  // When using product vector formulation, we have to create a block
109  // operator so that its domain space is consistent with x_space_
111  Thyra::createMembers(xSpace_, 1);
113  Thyra::createMembers(xSpace_, 1);
115  Thyra::createMembers(xSpace_, 1);
117  Thyra::createMembers(xSpace_, 1);
118  W_op = Thyra::nonconstBlock2x2(A00, A01, A10, A11);
119  }
120  return W_op;
121 }
122 
123 
124 template<class Scalar>
128 {
129  setupInOutArgs_();
130  return inArgs_;
131 }
132 
133 
134 template<class Scalar>
138 {
139  setupInOutArgs_();
140  return outArgs_;
141 }
142 
143 
144 template<class Scalar>
145 void
148 {
149  if (isInitialized_) {
150  return;
151  }
152 
153  {
154  // Set up prototypical InArgs
156  inArgs.setModelEvalDescription(this->description());
157  inArgs.setSupports( Thyra::ModelEvaluatorBase::IN_ARG_x_dot );
158  inArgs.setSupports( Thyra::ModelEvaluatorBase::IN_ARG_x );
159  inArgs.setSupports( Thyra::ModelEvaluatorBase::IN_ARG_t );
160  inArgs.setSupports( Thyra::ModelEvaluatorBase::IN_ARG_alpha );
161  inArgs.setSupports( Thyra::ModelEvaluatorBase::IN_ARG_beta );
162  if (acceptModelParams_) {
163  inArgs.set_Np(Np_);
164  }
165  inArgs_ = inArgs;
166  }
167 
168  {
169  // Set up prototypical OutArgs
171  outArgs.setModelEvalDescription(this->description());
172  outArgs.setSupports( Thyra::ModelEvaluatorBase::OUT_ARG_f );
173  outArgs.setSupports( Thyra::ModelEvaluatorBase::OUT_ARG_W_op );
174  if (acceptModelParams_) {
175  outArgs.set_Np_Ng(Np_,Ng_);
176  outArgs.setSupports( Thyra::ModelEvaluatorBase::OUT_ARG_DfDp,0,
177  Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM );
178  }
179  outArgs_ = outArgs;
180  }
181 
182  // Set up nominal values
183  nominalValues_ = inArgs_;
184  if (haveIC_)
185  {
186  using Teuchos::RCP;
187 
188  nominalValues_.set_t(t0_ic_);
189  const RCP<Thyra::VectorBase<Scalar> > x_ic = createMember(x_space_);
190  { // scope to delete DetachedVectorView
191  Thyra::DetachedVectorView<Scalar> x_ic_view( *x_ic );
192  x_ic_view[0] = x0_ic_;
193  x_ic_view[1] = x1_ic_;
194  }
195  nominalValues_.set_x(x_ic);
196 
197  if (acceptModelParams_) {
198  const RCP<Thyra::VectorBase<Scalar> > p_ic = createMember(p_space_);
199  {
200  Thyra::DetachedVectorView<Scalar> p_ic_view( *p_ic );
201  p_ic_view[0] = epsilon_;
202  }
203  nominalValues_.set_p(0,p_ic);
204  }
205  const RCP<Thyra::VectorBase<Scalar> > x_dot_ic = createMember(x_space_);
206  { // scope to delete DetachedVectorView
207  Thyra::DetachedVectorView<Scalar> x_dot_ic_view( *x_dot_ic );
208  x_dot_ic_view[0] = x1_ic_;
209  x_dot_ic_view[1] = ((1.0-x0_ic_*x0_ic_)*x1_ic_-x0_ic_)/epsilon_;
210  }
211  nominalValues_.set_x_dot(x_dot_ic);
212  }
213 
214  isInitialized_ = true;
215 }
216 
217 template<class Scalar>
218 void
221 {
222  using Teuchos::get;
224  Teuchos::RCP<ParameterList> tmpPL = Teuchos::rcp(new ParameterList("VanDerPol_IMEX_ExplicitModel"));
225  if (paramList != Teuchos::null) tmpPL = paramList;
226  tmpPL->validateParametersAndSetDefaults(*this->getValidParameters());
227  this->setMyParamList(tmpPL);
228  Teuchos::RCP<ParameterList> pl = this->getMyNonconstParamList();
229  bool acceptModelParams = get<bool>(*pl,"Accept model parameters");
230  bool haveIC = get<bool>(*pl,"Provide nominal values");
231  bool useDfDpAsTangent = get<bool>(*pl, "Use DfDp as Tangent");
232  if ( (acceptModelParams != acceptModelParams_) ||
233  (haveIC != haveIC_)
234  ) {
235  isInitialized_ = false;
236  }
237  acceptModelParams_ = acceptModelParams;
238  haveIC_ = haveIC;
239  useDfDpAsTangent_ = useDfDpAsTangent;
240  epsilon_ = get<Scalar>(*pl,"Coeff epsilon");
241  x0_ic_ = get<Scalar>(*pl,"IC x0");
242  x1_ic_ = get<Scalar>(*pl,"IC x1");
243  t0_ic_ = get<Scalar>(*pl,"IC t0");
244  setupInOutArgs_();
245 }
246 
247 template<class Scalar>
251 {
253  if (is_null(validPL)) {
254  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
255  pl->set("Accept model parameters", false);
256  pl->set("Provide nominal values", true);
257  pl->set("Use DfDp as Tangent", false);
258  Teuchos::setDoubleParameter(
259  "Coeff epsilon", 1.0e-06, "Coefficient a in model", &*pl);
260  Teuchos::setDoubleParameter(
261  "IC x0", 2.0, "Initial Condition for x0", &*pl);
262  Teuchos::setDoubleParameter(
263  "IC x1", 0.0, "Initial Condition for x1", &*pl);
264  Teuchos::setDoubleParameter(
265  "IC t0", 0.0, "Initial time t0", &*pl);
266  validPL = pl;
267  }
268  return validPL;
269 }
270 
271 template<class Scalar>
274 get_p_space(int l) const
275 {
276  if (!acceptModelParams_) {
277  return Teuchos::null;
278  }
280  if (l == 0)
281  return p_space_;
282  else if (l == 1 || l == 2)
283  return dxdp_space_;
284  return Teuchos::null;
285 }
286 
287 template<class Scalar>
290 get_p_names(int l) const
291 {
292  if (!acceptModelParams_) {
293  return Teuchos::null;
294  }
298  if (l == 0)
299  p_strings->push_back("Model Coefficient: epsilon");
300  else if (l == 1)
301  p_strings->push_back("DxDp");
302  else if (l == 2)
303  p_strings->push_back("Dx_dotDp");
304  return p_strings;
305 }
306 
307 template<class Scalar>
310 get_g_space(int j) const
311 {
313  return g_space_;
314 }
315 
316 template<class Scalar>
317 void
320  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
321 {
323  using Teuchos::RCP;
324  using Teuchos::rcp_dynamic_cast;
325  TEUCHOS_TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error,
326  "Error, setupInOutArgs_ must be called first!\n");
327 
329  inArgs.get_x().assert_not_null();
330  Thyra::ConstDetachedVectorView<Scalar> x_in_view( *x_in );
331 
332  //double t = inArgs.get_t();
333  Scalar beta = inArgs.get_beta();
334  Scalar eps = epsilon_;
335  RCP<const Thyra::MultiVectorBase<Scalar> > dxdp_in, dxdotdp_in;
336  if (acceptModelParams_) {
338  inArgs.get_p(0);
339  if (p_in != Teuchos::null) {
340  Thyra::ConstDetachedVectorView<Scalar> p_in_view( *p_in );
341  eps = p_in_view[0];
342  }
343  if (inArgs.get_p(1) != Teuchos::null) {
344  dxdp_in =
345  rcp_dynamic_cast<const DMVPV>(inArgs.get_p(1),true)->getMultiVector();
346  }
347  if (inArgs.get_p(2) != Teuchos::null) {
348  dxdotdp_in =
349  rcp_dynamic_cast<const DMVPV>(inArgs.get_p(2),true)->getMultiVector();
350  }
351  }
352 
353  const RCP<Thyra::VectorBase<Scalar> > f_out = outArgs.get_f();
354  const RCP<Thyra::LinearOpBase<Scalar> > W_out = outArgs.get_W_op();
356  if (acceptModelParams_) {
358  DfDp_out = DfDp.getMultiVector();
359  }
360 
361  if (inArgs.get_x_dot().is_null()) {
362 
363  // Evaluate the Explicit ODE f(x,t) [= xdot]
364  if (!is_null(f_out)) {
365  Thyra::DetachedVectorView<Scalar> f_out_view( *f_out );
366  f_out_view[0] = x_in_view[1];
367  f_out_view[1] = -x_in_view[0]/eps;
368  }
369  if (!is_null(DfDp_out)) {
370  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view( *DfDp_out );
371  DfDp_out_view(0,0) = 0.0;
372  DfDp_out_view(1,0) = x_in_view[0]/(eps*eps);
373 
374  // Compute df/dp + (df/dx) * (dx/dp)
375  if (useDfDpAsTangent_ && !is_null(dxdp_in)) {
377  DfDp_out_view(0,0) += dxdp(1,0);
378  DfDp_out_view(1,0) += -dxdp(0,0)/eps;
379  }
380  }
381  if (!is_null(W_out)) {
382  if (useProductVector_ == false) {
384  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,true);
386  W_view(0,0) = 0.0; // d(f0)/d(x0_n)
387  W_view(0,1) = beta; // d(f0)/d(x1_n)
388  W_view(1,0) = -beta/eps; // d(f1)/d(x0_n)
389  W_view(1,1) = 0.0; // d(f1)/d(x1_n)
390  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
391  }
392  else {
394  Teuchos::rcp_dynamic_cast<Thyra::DefaultBlockedLinearOp<Scalar> >(W_out, true);
396  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_block->getNonconstBlock(0,0),true);
398  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_block->getNonconstBlock(0,1),true);
400  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_block->getNonconstBlock(1,0),true);
402  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_block->getNonconstBlock(1,1),true);
407  W00_view(0,0) = 0.0; // d(f0)/d(x0_n)
408  W01_view(0,0) = beta; // d(f0)/d(x1_n)
409  W10_view(0,0) = -beta/eps; // d(f1)/d(x0_n)
410  W11_view(0,0) = 0.0; // d(f1)/d(x1_n)
411  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
412  }
413  }
414  } else {
415 
416  // Evaluate the implicit ODE f(xdot, x, t) [= 0]
418  x_dot_in = inArgs.get_x_dot().assert_not_null();
419  Scalar alpha = inArgs.get_alpha();
420 
421  if (!is_null(f_out)) {
422  Thyra::DetachedVectorView<Scalar> f_out_view( *f_out );
423  Thyra::ConstDetachedVectorView<Scalar> x_dot_in_view( *x_dot_in );
424  f_out_view[0] = x_dot_in_view[0] - x_in_view[1];
425  f_out_view[1] = x_dot_in_view[1] + x_in_view[0]/eps;
426  }
427  if (!is_null(DfDp_out)) {
428  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view( *DfDp_out );
429  DfDp_out_view(0,0) = 0.0;
430  DfDp_out_view(1,0) = -x_in_view[0]/(eps*eps);
431 
432  // Compute df/dp + (df/dx_dot)*(dx_dot/dp) + (df/dx) * (dx/dp)
433  if (useDfDpAsTangent_ && !is_null(dxdotdp_in)) {
434  Thyra::ConstDetachedMultiVectorView<Scalar> dxdotdp( *dxdotdp_in );
435  DfDp_out_view(0,0) += dxdotdp(0,0);
436  DfDp_out_view(1,0) += dxdotdp(1,0);
437  }
438  if (useDfDpAsTangent_ && !is_null(dxdp_in)) {
440  DfDp_out_view(0,0) += -dxdp(1,0);
441  DfDp_out_view(1,0) += dxdp(0,0)/eps;
442  }
443  }
444  if (!is_null(W_out)) {
445  if (useProductVector_ == false) {
447  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,true);
449  W_view(0,0) = alpha; // d(f0)/d(x0_n)
450  W_view(0,1) = -beta; // d(f0)/d(x1_n)
451  W_view(1,0) = beta/eps; // d(f1)/d(x0_n)
452  W_view(1,1) = alpha; // d(f1)/d(x1_n)
453  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
454  }
455  else {
457  Teuchos::rcp_dynamic_cast<Thyra::DefaultBlockedLinearOp<Scalar> >(W_out, true);
459  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_block->getNonconstBlock(0,0),true);
461  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_block->getNonconstBlock(0,1),true);
463  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_block->getNonconstBlock(1,0),true);
465  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_block->getNonconstBlock(1,1),true);
470  W00_view(0,0) = alpha; // d(f0)/d(x0_n)
471  W01_view(0,0) = -beta; // d(f0)/d(x1_n)
472  W10_view(0,0) = beta/eps; // d(f1)/d(x0_n)
473  W11_view(0,0) = alpha; // d(f1)/d(x1_n)
474  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
475  }
476  }
477  }
478 }
479 
480 
481 } // namespace Tempus_Test
482 #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