Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SinCosModel_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_SINCOS_MODEL_IMPL_HPP
10 #define TEMPUS_TEST_SINCOS_MODEL_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>
30 {
31  isInitialized_ = false;
32  dim_ = 2;
33  Np_ = 3; // Number of parameter vectors (p, dx/dp, dx_dot/dp)
34  np_ = 3; // Number of parameters in this vector (3)
35  Ng_ = 1; // Number of observation functions (1)
36  ng_ = dim_; // Number of elements in this observation function ( == x )
37  acceptModelParams_ = false;
38  useDfDpAsTangent_ = false;
39  haveIC_ = true;
40  a_ = 0.0;
41  f_ = 1.0;
42  L_ = 1.0;
43  x0_ic_ = 0.0;
44  x1_ic_ = 1.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  g_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(ng_);
53 
54  setParameterList(pList_);
55 
56  // Create DxDp product space
57  DxDp_space_ = Thyra::multiVectorProductVectorSpace(x_space_, np_);
58 }
59 
60 template <class Scalar>
62  double t) const
63 {
64  TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
65  "Error, setupInOutArgs_ must be called first!\n");
67  double exact_t = t;
68  inArgs.set_t(exact_t);
69  Teuchos::RCP<Thyra::VectorBase<Scalar> > exact_x = createMember(x_space_);
70  { // scope to delete DetachedVectorView
71  Thyra::DetachedVectorView<Scalar> exact_x_view(*exact_x);
72  exact_x_view[0] = a_ + b_ * sin((f_ / L_) * t + phi_);
73  exact_x_view[1] = b_ * (f_ / L_) * cos((f_ / L_) * t + phi_);
74  }
75  inArgs.set_x(exact_x);
76  Teuchos::RCP<Thyra::VectorBase<Scalar> > exact_x_dot = createMember(x_space_);
77  { // scope to delete DetachedVectorView
78  Thyra::DetachedVectorView<Scalar> exact_x_dot_view(*exact_x_dot);
79  exact_x_dot_view[0] = b_ * (f_ / L_) * cos((f_ / L_) * t + phi_);
80  exact_x_dot_view[1] =
81  -b_ * (f_ / L_) * (f_ / L_) * sin((f_ / L_) * t + phi_);
82  }
83  inArgs.set_x_dot(exact_x_dot);
84  return (inArgs);
85 }
86 
87 //
88 // 06/24/09 tscoffe:
89 // These are the exact sensitivities for the problem assuming the initial
90 // conditions are specified as:
91 // s(0) = [1;0] s(1) = [0;b/L] s(2) = [0;-b*f/(L*L)]
92 // sdot(0) = [0;0] sdot(1) = [0;-3*f*f*b/(L*L*L)] sdot(2) =
93 // [0;3*f*f*f*b/(L*L*L*L)]
94 //
95 template <class Scalar>
98 {
99  TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
100  "Error, setupInOutArgs_ must be called first!\n");
102  if (!acceptModelParams_) {
103  return inArgs;
104  }
106  double exact_t = t;
107  Scalar b = b_;
108  Scalar f = f_;
109  Scalar L = L_;
110  Scalar phi = phi_;
111  inArgs.set_t(exact_t);
112  Teuchos::RCP<Thyra::VectorBase<Scalar> > exact_s = createMember(x_space_);
113  { // scope to delete DetachedVectorView
114  Thyra::DetachedVectorView<Scalar> exact_s_view(*exact_s);
115  if (j == 0) { // dx/da
116  exact_s_view[0] = 1.0;
117  exact_s_view[1] = 0.0;
118  }
119  else if (j == 1) { // dx/df
120  exact_s_view[0] = (b / L) * t * cos((f / L) * t + phi);
121  exact_s_view[1] = (b / L) * cos((f / L) * t + phi) -
122  (b * f * t / (L * L)) * sin((f / L) * t + phi);
123  }
124  else { // dx/dL
125  exact_s_view[0] = -(b * f * t / (L * L)) * cos((f / L) * t + phi);
126  exact_s_view[1] = -(b * f / (L * L)) * cos((f / L) * t + phi) +
127  (b * f * f * t / (L * L * L)) * sin((f / L) * t + phi);
128  }
129  }
130  inArgs.set_x(exact_s);
131  Teuchos::RCP<Thyra::VectorBase<Scalar> > exact_s_dot = createMember(x_space_);
132  { // scope to delete DetachedVectorView
133  Thyra::DetachedVectorView<Scalar> exact_s_dot_view(*exact_s_dot);
134  if (j == 0) { // dxdot/da
135  exact_s_dot_view[0] = 0.0;
136  exact_s_dot_view[1] = 0.0;
137  }
138  else if (j == 1) { // dxdot/df
139  exact_s_dot_view[0] = (b / L) * cos((f / L) * t + phi) -
140  (b * f * t / (L * L)) * sin((f / L) * t + phi);
141  exact_s_dot_view[1] =
142  -(2.0 * b * f / (L * L)) * sin((f / L) * t + phi) -
143  (b * f * f * t / (L * L * L)) * cos((f / L) * t + phi);
144  }
145  else { // dxdot/dL
146  exact_s_dot_view[0] =
147  -(b * f / (L * L)) * cos((f / L) * t + phi) +
148  (b * f * f * t / (L * L * L)) * sin((f / L) * t + phi);
149  exact_s_dot_view[1] =
150  (2.0 * b * f * f / (L * L * L)) * sin((f / L) * t + phi) +
151  (b * f * f * f * t / (L * L * L * L)) * cos((f / L) * t + phi);
152  }
153  }
154  inArgs.set_x_dot(exact_s_dot);
155  return (inArgs);
156 }
157 
158 template <class Scalar>
161 {
162  return x_space_;
163 }
164 
165 template <class Scalar>
168 {
169  return f_space_;
170 }
171 
172 template <class Scalar>
175 {
176  TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
177  "Error, setupInOutArgs_ must be called first!\n");
178  return nominalValues_;
179 }
180 
181 template <class Scalar>
184 {
185  using Teuchos::RCP;
187  this->get_W_factory();
188  RCP<Thyra::LinearOpBase<Scalar> > matrix = this->create_W_op();
189  {
190  // 01/20/09 tscoffe: This is a total hack to provide a full rank matrix to
191  // linearOpWithSolve because it ends up factoring the matrix during
192  // initialization, which it really shouldn't do, or I'm doing something
193  // wrong here. The net effect is that I get exceptions thrown in
194  // optimized mode due to the matrix being rank deficient unless I do this.
196  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(matrix,
197  true);
198  {
199  RCP<Thyra::VectorBase<Scalar> > vec = Thyra::createMember(x_space_);
200  {
201  Thyra::DetachedVectorView<Scalar> vec_view(*vec);
202  vec_view[0] = 0.0;
203  vec_view[1] = 1.0;
204  }
205  V_V(multivec->col(0).ptr(), *vec);
206  {
207  Thyra::DetachedVectorView<Scalar> vec_view(*vec);
208  vec_view[0] = 1.0;
209  vec_view[1] = 0.0;
210  }
211  V_V(multivec->col(1).ptr(), *vec);
212  }
213  }
215  Thyra::linearOpWithSolve<Scalar>(*W_factory, matrix);
216  return W;
217 }
218 // Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
219 // SinCosModel<Scalar>::
220 // create_W() const
221 //{
222 // return Thyra::multiVectorLinearOpWithSolve<Scalar>();
223 // }
224 
225 template <class Scalar>
227  const
228 {
230  Thyra::createMembers(x_space_, dim_);
231  return (matrix);
232 }
233 
234 template <class Scalar>
237 {
239  Thyra::defaultSerialDenseLinearOpWithSolveFactory<Scalar>();
240  return W_factory;
241 }
242 // Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > fwdOp =
243 // this->create_W_op(); Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> > W =
244 // Thyra::linearOpWithSolve<Scalar>(
245 // *W_factory,
246 // fwdOp
247 // );
248 // W_factory->initializeOp(
249 // Thyra::defaultLinearOpSource<Scalar>(fwdOp),
250 // &*W,
251 // Thyra::SUPPORT_SOLVE_UNSPECIFIED
252 // );
253 
254 template <class Scalar>
256  const
257 {
258  setupInOutArgs_();
259  return inArgs_;
260 }
261 
262 // Private functions overridden from ModelEvaluatorDefaultBase
263 
264 template <class Scalar>
267 {
268  setupInOutArgs_();
269  return outArgs_;
270 }
271 
272 template <class Scalar>
275  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
276 {
278  using Teuchos::RCP;
279  using Teuchos::rcp_dynamic_cast;
281  using Thyra::VectorBase;
282  TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
283  "Error, setupInOutArgs_ must be called first!\n");
284 
285  const RCP<const VectorBase<Scalar> > x_in = inArgs.get_x().assert_not_null();
287 
288  // double t = inArgs.get_t();
289  Scalar a = a_;
290  Scalar f = f_;
291  Scalar L = L_;
292  if (acceptModelParams_) {
293  const RCP<const VectorBase<Scalar> > p_in =
294  inArgs.get_p(0).assert_not_null();
296  a = p_in_view[0];
297  f = p_in_view[1];
298  L = p_in_view[2];
299  }
300 
301  RCP<const MultiVectorBase<Scalar> > DxDp_in, DxdotDp_in;
302  if (acceptModelParams_) {
303  if (inArgs.get_p(1) != Teuchos::null)
304  DxDp_in =
305  rcp_dynamic_cast<const DMVPV>(inArgs.get_p(1))->getMultiVector();
306  if (inArgs.get_p(2) != Teuchos::null)
307  DxdotDp_in =
308  rcp_dynamic_cast<const DMVPV>(inArgs.get_p(2))->getMultiVector();
309  }
310 
311  Scalar beta = inArgs.get_beta();
312 
313  const RCP<VectorBase<Scalar> > f_out = outArgs.get_f();
314  const RCP<Thyra::LinearOpBase<Scalar> > W_out = outArgs.get_W_op();
316  if (acceptModelParams_) {
318  DfDp_out = DfDp.getMultiVector();
319  }
320 
321  if (inArgs.get_x_dot().is_null()) {
322  // Evaluate the Explicit ODE f(x,t) [= 0]
323  if (!is_null(f_out)) {
324  Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
325  f_out_view[0] = x_in_view[1];
326  f_out_view[1] = (f / L) * (f / L) * (a - x_in_view[0]);
327  }
328  if (!is_null(W_out)) {
330  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
331  true);
332  Thyra::DetachedMultiVectorView<Scalar> matrix_view(*matrix);
333  matrix_view(0, 0) = 0.0; // d(f0)/d(x0_n)
334  matrix_view(0, 1) = +beta; // d(f0)/d(x1_n)
335  matrix_view(1, 0) = -beta * (f / L) * (f / L); // d(f1)/d(x0_n)
336  matrix_view(1, 1) = 0.0; // d(f1)/d(x1_n)
337  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
338  }
339  if (!is_null(DfDp_out)) {
340  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
341  DfDp_out_view(0, 0) = 0.0;
342  DfDp_out_view(0, 1) = 0.0;
343  DfDp_out_view(0, 2) = 0.0;
344  DfDp_out_view(1, 0) = (f / L) * (f / L);
345  DfDp_out_view(1, 1) = (2.0 * f / (L * L)) * (a - x_in_view[0]);
346  DfDp_out_view(1, 2) = -(2.0 * f * f / (L * L * L)) * (a - x_in_view[0]);
347 
348  // Compute df/dp + (df/dx) * (dx/dp)
349  if (useDfDpAsTangent_ && !is_null(DxDp_in)) {
351  DfDp_out_view(0, 0) += DxDp(1, 0);
352  DfDp_out_view(0, 1) += DxDp(1, 1);
353  DfDp_out_view(0, 2) += DxDp(1, 2);
354  DfDp_out_view(1, 0) += -(f / L) * (f / L) * DxDp(0, 0);
355  DfDp_out_view(1, 1) += -(f / L) * (f / L) * DxDp(0, 1);
356  DfDp_out_view(1, 2) += -(f / L) * (f / L) * DxDp(0, 2);
357  }
358  }
359  }
360  else {
361  // Evaluate the implicit ODE f(xdot, x, t) [= 0]
362  RCP<const VectorBase<Scalar> > x_dot_in;
363  x_dot_in = inArgs.get_x_dot().assert_not_null();
364  Scalar alpha = inArgs.get_alpha();
365  if (!is_null(f_out)) {
366  Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
367  Thyra::ConstDetachedVectorView<Scalar> x_dot_in_view(*x_dot_in);
368  f_out_view[0] = x_dot_in_view[0] - x_in_view[1];
369  f_out_view[1] = x_dot_in_view[1] - (f / L) * (f / L) * (a - x_in_view[0]);
370  }
371  if (!is_null(W_out)) {
373  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
374  true);
375  Thyra::DetachedMultiVectorView<Scalar> matrix_view(*matrix);
376  matrix_view(0, 0) = alpha; // d(f0)/d(x0_n)
377  matrix_view(0, 1) = -beta; // d(f0)/d(x1_n)
378  matrix_view(1, 0) = +beta * (f / L) * (f / L); // d(f1)/d(x0_n)
379  matrix_view(1, 1) = alpha; // d(f1)/d(x1_n)
380  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
381  }
382  if (!is_null(DfDp_out)) {
383  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
384  DfDp_out_view(0, 0) = 0.0;
385  DfDp_out_view(0, 1) = 0.0;
386  DfDp_out_view(0, 2) = 0.0;
387  DfDp_out_view(1, 0) = -(f / L) * (f / L);
388  DfDp_out_view(1, 1) = -(2.0 * f / (L * L)) * (a - x_in_view[0]);
389  DfDp_out_view(1, 2) = +(2.0 * f * f / (L * L * L)) * (a - x_in_view[0]);
390 
391  // Compute df/dp + (df/dx_dot) * (dx_dot/dp) + (df/dx) * (dx/dp)
392  if (useDfDpAsTangent_ && !is_null(DxdotDp_in)) {
393  Thyra::ConstDetachedMultiVectorView<Scalar> DxdotDp(*DxdotDp_in);
394  DfDp_out_view(0, 0) += DxdotDp(0, 0);
395  DfDp_out_view(0, 1) += DxdotDp(0, 1);
396  DfDp_out_view(0, 2) += DxdotDp(0, 2);
397  DfDp_out_view(1, 0) += DxdotDp(1, 0);
398  DfDp_out_view(1, 1) += DxdotDp(1, 1);
399  DfDp_out_view(1, 2) += DxdotDp(1, 2);
400  }
401  if (useDfDpAsTangent_ && !is_null(DxDp_in)) {
403  DfDp_out_view(0, 0) += -DxDp(1, 0);
404  DfDp_out_view(0, 1) += -DxDp(1, 1);
405  DfDp_out_view(0, 2) += -DxDp(1, 2);
406  DfDp_out_view(1, 0) += (f / L) * (f / L) * DxDp(0, 0);
407  DfDp_out_view(1, 1) += (f / L) * (f / L) * DxDp(0, 1);
408  DfDp_out_view(1, 2) += (f / L) * (f / L) * DxDp(0, 2);
409  }
410  }
411  }
412 
413  // Responses: g = x
414  if (acceptModelParams_) {
415  RCP<VectorBase<Scalar> > g_out = outArgs.get_g(0);
416  if (g_out != Teuchos::null) Thyra::assign(g_out.ptr(), *x_in);
417 
419  outArgs.get_DgDp(0, 0).getMultiVector();
420  if (DgDp_out != Teuchos::null) Thyra::assign(DgDp_out.ptr(), Scalar(0.0));
421 
423  outArgs.get_DgDx(0).getMultiVector();
424  if (DgDx_out != Teuchos::null) {
425  Thyra::DetachedMultiVectorView<Scalar> DgDx_out_view(*DgDx_out);
426  DgDx_out_view(0, 0) = 1.0;
427  DgDx_out_view(0, 1) = 0.0;
428  DgDx_out_view(1, 0) = 0.0;
429  DgDx_out_view(1, 1) = 1.0;
430  }
431  }
432 }
433 
434 template <class Scalar>
437 {
438  if (!acceptModelParams_) {
439  return Teuchos::null;
440  }
442  if (l == 0)
443  return p_space_;
444  else if (l == 1 || l == 2)
445  return DxDp_space_;
446  return Teuchos::null;
447 }
448 
449 template <class Scalar>
452 {
453  if (!acceptModelParams_) {
454  return Teuchos::null;
455  }
459  if (l == 0) {
460  p_strings->push_back("Model Coefficient: a");
461  p_strings->push_back("Model Coefficient: f");
462  p_strings->push_back("Model Coefficient: L");
463  }
464  else if (l == 1)
465  p_strings->push_back("DxDp");
466  else if (l == 2)
467  p_strings->push_back("Dx_dotDp");
468  return p_strings;
469 }
470 
471 template <class Scalar>
474 {
476  return g_space_;
477 }
478 
479 // private
480 
481 template <class Scalar>
483 {
484  if (isInitialized_) {
485  return;
486  }
487 
488  using Teuchos::RCP;
489  typedef Thyra::ModelEvaluatorBase MEB;
490  {
491  // Set up prototypical InArgs
492  MEB::InArgsSetup<Scalar> inArgs;
493  inArgs.setModelEvalDescription(this->description());
494  inArgs.setSupports(MEB::IN_ARG_t);
495  inArgs.setSupports(MEB::IN_ARG_x);
496  inArgs.setSupports(MEB::IN_ARG_beta);
497  inArgs.setSupports(MEB::IN_ARG_x_dot);
498  inArgs.setSupports(MEB::IN_ARG_alpha);
499  if (acceptModelParams_) {
500  inArgs.set_Np(Np_);
501  }
502  inArgs_ = inArgs;
503  }
504 
505  {
506  // Set up prototypical OutArgs
507  MEB::OutArgsSetup<Scalar> outArgs;
508  outArgs.setModelEvalDescription(this->description());
509  outArgs.setSupports(MEB::OUT_ARG_f);
510  outArgs.setSupports(MEB::OUT_ARG_W_op);
511  if (acceptModelParams_) {
512  outArgs.set_Np_Ng(Np_, Ng_);
513  outArgs.setSupports(MEB::OUT_ARG_DfDp, 0, MEB::DERIV_MV_JACOBIAN_FORM);
514  outArgs.setSupports(MEB::OUT_ARG_DgDp, 0, 0, MEB::DERIV_MV_JACOBIAN_FORM);
515  outArgs.setSupports(MEB::OUT_ARG_DgDx, 0, MEB::DERIV_MV_GRADIENT_FORM);
516  }
517  outArgs_ = outArgs;
518  }
519 
520  // Set up nominal values
521  nominalValues_ = inArgs_;
522  if (haveIC_) {
523  nominalValues_.set_t(t0_ic_);
524  const RCP<Thyra::VectorBase<Scalar> > x_ic = createMember(x_space_);
525  { // scope to delete DetachedVectorView
526  Thyra::DetachedVectorView<Scalar> x_ic_view(*x_ic);
527  x_ic_view[0] = a_ + b_ * sin((f_ / L_) * t0_ic_ + phi_);
528  x_ic_view[1] = b_ * (f_ / L_) * cos((f_ / L_) * t0_ic_ + phi_);
529  }
530  nominalValues_.set_x(x_ic);
531  if (acceptModelParams_) {
532  const RCP<Thyra::VectorBase<Scalar> > p_ic = createMember(p_space_);
533  {
534  Thyra::DetachedVectorView<Scalar> p_ic_view(*p_ic);
535  p_ic_view[0] = a_;
536  p_ic_view[1] = f_;
537  p_ic_view[2] = L_;
538  }
539  nominalValues_.set_p(0, p_ic);
540  }
541  const RCP<Thyra::VectorBase<Scalar> > x_dot_ic = createMember(x_space_);
542  { // scope to delete DetachedVectorView
543  Thyra::DetachedVectorView<Scalar> x_dot_ic_view(*x_dot_ic);
544  x_dot_ic_view[0] = b_ * (f_ / L_) * cos((f_ / L_) * t0_ic_ + phi_);
545  x_dot_ic_view[1] =
546  -b_ * (f_ / L_) * (f_ / L_) * sin((f_ / L_) * t0_ic_ + phi_);
547  }
548  nominalValues_.set_x_dot(x_dot_ic);
549  }
550 
551  isInitialized_ = true;
552 }
553 
554 template <class Scalar>
556  Teuchos::RCP<Teuchos::ParameterList> const &paramList)
557 {
558  using Teuchos::get;
561  Teuchos::rcp(new ParameterList("SinCosModel"));
562  if (paramList != Teuchos::null) tmpPL = paramList;
563  tmpPL->validateParametersAndSetDefaults(*this->getValidParameters());
564  this->setMyParamList(tmpPL);
565  Teuchos::RCP<ParameterList> pl = this->getMyNonconstParamList();
566  bool acceptModelParams = get<bool>(*pl, "Accept model parameters");
567  bool haveIC = get<bool>(*pl, "Provide nominal values");
568  bool useDfDpAsTangent = get<bool>(*pl, "Use DfDp as Tangent");
569  if ((acceptModelParams != acceptModelParams_) || (haveIC != haveIC_)) {
570  isInitialized_ = false;
571  }
572  acceptModelParams_ = acceptModelParams;
573  haveIC_ = haveIC;
574  useDfDpAsTangent_ = useDfDpAsTangent;
575  a_ = get<Scalar>(*pl, "Coeff a");
576  f_ = get<Scalar>(*pl, "Coeff f");
577  L_ = get<Scalar>(*pl, "Coeff L");
578  x0_ic_ = get<Scalar>(*pl, "IC x0");
579  x1_ic_ = get<Scalar>(*pl, "IC x1");
580  t0_ic_ = get<Scalar>(*pl, "IC t0");
581  calculateCoeffFromIC_();
582  setupInOutArgs_();
583 }
584 
585 template <class Scalar>
588 {
590  if (is_null(validPL)) {
591  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
592  pl->set("Accept model parameters", false);
593  pl->set("Provide nominal values", true);
594  pl->set("Use DfDp as Tangent", false);
595  pl->set<std::string>("Output File Name", "Tempus_BDF2_SinCos");
596  Teuchos::setDoubleParameter("Coeff a", 0.0, "Coefficient a in model", &*pl);
597  Teuchos::setDoubleParameter("Coeff f", 1.0, "Coefficient f in model", &*pl);
598  Teuchos::setDoubleParameter("Coeff L", 1.0, "Coefficient L in model", &*pl);
599  Teuchos::setDoubleParameter("IC x0", 0.0, "Initial Condition for x0", &*pl);
600  Teuchos::setDoubleParameter("IC x1", 1.0, "Initial Condition for x1", &*pl);
601  Teuchos::setDoubleParameter("IC t0", 0.0, "Initial time t0", &*pl);
602  Teuchos::setIntParameter("Number of Time Step Sizes", 1,
603  "Number time step sizes for convergence study",
604  &*pl);
605  validPL = pl;
606  }
607  return validPL;
608 }
609 
610 template <class Scalar>
612 {
613  phi_ = atan(((f_ / L_) / x1_ic_) * (x0_ic_ - a_)) - (f_ / L_) * t0_ic_;
614  b_ = x1_ic_ / ((f_ / L_) * cos((f_ / L_) * t0_ic_ + phi_));
615 }
616 
617 template <class Scalar>
620 {
621  using Teuchos::RCP;
623  this->get_W_factory();
624  RCP<Thyra::LinearOpBase<Scalar> > matrix = this->create_W_op();
625  {
626  // 01/20/09 tscoffe: This is a total hack to provide a full rank matrix to
627  // linearOpWithSolve because it ends up factoring the matrix during
628  // initialization, which it really shouldn't do, or I'm doing something
629  // wrong here. The net effect is that I get exceptions thrown in
630  // optimized mode due to the matrix being rank deficient unless I do this.
632  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(matrix,
633  true);
634  {
635  RCP<Thyra::VectorBase<Scalar> > vec = Thyra::createMember(this->f_space_);
636  {
637  Thyra::DetachedVectorView<Scalar> vec_view(*vec);
638  vec_view[0] = 0.0;
639  vec_view[1] = 1.0;
640  }
641  V_V(multivec->col(0).ptr(), *vec);
642  {
643  Thyra::DetachedVectorView<Scalar> vec_view(*vec);
644  vec_view[0] = 1.0;
645  vec_view[1] = 0.0;
646  }
647  V_V(multivec->col(1).ptr(), *vec);
648  }
649  }
651  Thyra::linearOpWithSolve<Scalar>(*W_factory, matrix);
652  return W;
653 }
654 
655 template <class Scalar>
658 {
660  Thyra::createMembers(this->f_space_, this->dim_);
661  return (matrix);
662 }
663 
664 template <class Scalar>
667 {
668  // This ME should use the same InArgs as the base SinCosModel. However
669  // we can't just use it's InArgs directly because the description won't
670  // match (which is checked in debug builds). Instead create a new InArgsSetup
671  // initialized by SinCosModel::createInArgs() and set the description
672  // appropriately.
673  typedef Thyra::ModelEvaluatorBase MEB;
674  MEB::InArgsSetup<Scalar> inArgs = SinCosModel<Scalar>::createInArgs();
675  inArgs.setModelEvalDescription(this->description());
676  return inArgs;
677 }
678 
679 template <class Scalar>
682 {
683  typedef Thyra::ModelEvaluatorBase MEB;
684  MEB::OutArgsSetup<Scalar> outArgs;
685  outArgs.setModelEvalDescription(this->description());
686  outArgs.setSupports(
687  MEB::OUT_ARG_f); // Apparently all models have to support f
688  outArgs.setSupports(MEB::OUT_ARG_W_op);
689  outArgs.set_Np_Ng(this->Np_, 0);
690  return outArgs;
691 }
692 
693 template <class Scalar>
696  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
697 {
698  using Teuchos::RCP;
699  using Teuchos::rcp_dynamic_cast;
701  using Thyra::VectorBase;
702  TEUCHOS_TEST_FOR_EXCEPTION(!this->isInitialized_, std::logic_error,
703  "Error, setupInOutArgs_ must be called first!\n");
704 
705  const RCP<const VectorBase<Scalar> > x_in = inArgs.get_x().assert_not_null();
707 
708  // double t = inArgs.get_t();
709  // Scalar a = this->a_;
710  Scalar f = this->f_;
711  Scalar L = this->L_;
712  if (this->acceptModelParams_) {
713  const RCP<const VectorBase<Scalar> > p_in =
714  inArgs.get_p(0).assert_not_null();
716  // a = p_in_view[0];
717  f = p_in_view[1];
718  L = p_in_view[2];
719  }
720 
721  Scalar beta = inArgs.get_beta();
722 
723  const RCP<Thyra::LinearOpBase<Scalar> > W_out = outArgs.get_W_op();
724  if (inArgs.get_x_dot().is_null()) {
725  // Evaluate the Explicit ODE f(x,t) [= 0]
726  if (!is_null(W_out)) {
728  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
729  true);
730  Thyra::DetachedMultiVectorView<Scalar> matrix_view(*matrix);
731  matrix_view(0, 0) = 0.0; // d(f0)/d(x0_n)
732  matrix_view(1, 0) = +beta; // d(f0)/d(x1_n)
733  matrix_view(0, 1) = -beta * (f / L) * (f / L); // d(f1)/d(x0_n)
734  matrix_view(1, 1) = 0.0; // d(f1)/d(x1_n)
735  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
736  }
737  }
738  else {
739  // Evaluate the implicit ODE f(xdot, x, t) [= 0]
740  RCP<const VectorBase<Scalar> > x_dot_in;
741  x_dot_in = inArgs.get_x_dot().assert_not_null();
742  Scalar alpha = inArgs.get_alpha();
743  if (!is_null(W_out)) {
745  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
746  true);
747  Thyra::DetachedMultiVectorView<Scalar> matrix_view(*matrix);
748  matrix_view(0, 0) = alpha; // d(f0)/d(x0_n)
749  matrix_view(1, 0) = -beta; // d(f0)/d(x1_n)
750  matrix_view(0, 1) = +beta * (f / L) * (f / L); // d(f1)/d(x0_n)
751  matrix_view(1, 1) = alpha; // d(f1)/d(x1_n)
752  // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
753  }
754  }
755 }
756 
757 } // namespace Tempus_Test
758 #endif // TEMPUS_TEST_SINCOS_MODEL_IMPL_HPP
bool is_null(const boost::shared_ptr< T > &p)
Derivative< Scalar > get_DfDp(int l) const
RCP< const VectorBase< Scalar > > get_x_dot() const
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)
Thyra::ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
Evaluation< VectorBase< Scalar > > get_g(int j) const
Evaluation< VectorBase< Scalar > > get_f() const
Teuchos::RCP< Thyra::LinearOpBase< Scalar > > create_W_op() const
Teuchos::RCP< Thyra::LinearOpWithSolveBase< Scalar > > create_W() const
Thyra::ModelEvaluatorBase::InArgs< Scalar > getNominalValues() const
Derivative< Scalar > get_DgDp(int j, int l) const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_f_space() const
Teuchos::RCP< Thyra::LinearOpBase< Scalar > > create_W_op() const
#define TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE(index, lower_inclusive, upper_exclusive)
void set_x(const RCP< const VectorBase< Scalar > > &x)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs_bar, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs_bar) const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_x_space() const
Thyra::ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
Thyra::ModelEvaluatorBase::InArgs< Scalar > getExactSolution(double t) const
Ptr< T > ptr() const
SinCosModel(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_p_space(int l) const
Thyra::ModelEvaluatorBase::OutArgs< Scalar > createOutArgsImpl() const
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
void set_x_dot(const RCP< const VectorBase< Scalar > > &x_dot)
void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs_bar, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs_bar) const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_g_space(int j) const
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int l) const
Thyra::ModelEvaluatorBase::OutArgs< Scalar > createOutArgsImpl() const
Thyra::ModelEvaluatorBase::InArgs< Scalar > getExactSensSolution(int j, double t) const
Teuchos::RCP< const Thyra::LinearOpWithSolveFactoryBase< Scalar > > get_W_factory() const
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
Teuchos::RCP< Thyra::LinearOpWithSolveBase< Scalar > > create_W() const
void setParameterList(Teuchos::RCP< Teuchos::ParameterList > const &paramList)
Derivative< Scalar > get_DgDx(int j) const