Tempus Version of the Day
Time Integration
Loading...
Searching...
No Matches
VanDerPolModel_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_MODEL_IMPL_HPP
11#define TEMPUS_TEST_VANDERPOL_MODEL_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
23#include <iostream>
24
25namespace Tempus_Test {
26
27template <class Scalar>
29 Teuchos::RCP<Teuchos::ParameterList> pList_)
30{
31 isInitialized_ = false;
32 dim_ = 2;
33 Np_ = 1; // Number of parameter vectors (1)
34 np_ = 1; // Number of parameters in this vector (1)
35 Ng_ = 0; // Number of observation functions (0)
36 ng_ = 0; // Number of elements in this observation function (0)
37 acceptModelParams_ = false;
38 haveIC_ = true;
39 epsilon_ = 1.0e-06;
40 x0_ic_ = 2.0;
41 x1_ic_ = 0.0;
42 t0_ic_ = 0.0;
43
44 // Create x_space and f_space
45 x_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
46 f_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
47 // Create p_space and g_space
48 p_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(np_);
49 g_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(ng_);
50
51 setParameterList(pList_);
52}
53
54template <class Scalar>
55Thyra::ModelEvaluatorBase::InArgs<Scalar>
57{
58 TEUCHOS_TEST_FOR_EXCEPTION(
59 true, std::logic_error,
60 "Error - No exact solution for van der Pol problem!\n");
61 return (inArgs_);
62}
63
64template <class Scalar>
65Thyra::ModelEvaluatorBase::InArgs<Scalar>
67{
68 TEUCHOS_TEST_FOR_EXCEPTION(
69 !isInitialized_, std::logic_error,
70 "Error - No exact sensitivities for van der Pol problem!\n");
71 return (inArgs_);
72}
73
74template <class Scalar>
75Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
77{
78 return x_space_;
79}
80
81template <class Scalar>
82Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
84{
85 return f_space_;
86}
87
88template <class Scalar>
89Thyra::ModelEvaluatorBase::InArgs<Scalar>
91{
92 TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
93 "Error, setupInOutArgs_ must be called first!\n");
94 return nominalValues_;
95}
96
97template <class Scalar>
98Teuchos::RCP<Thyra::LinearOpWithSolveBase<Scalar> >
100{
101 using Teuchos::RCP;
102 RCP<const Thyra::LinearOpWithSolveFactoryBase<Scalar> > W_factory =
103 this->get_W_factory();
104 RCP<Thyra::LinearOpBase<Scalar> > matrix = this->create_W_op();
105 {
106 // 01/20/09 tscoffe: This is a total hack to provide a full rank matrix to
107 // linearOpWithSolve because it ends up factoring the matrix during
108 // initialization, which it really shouldn't do, or I'm doing something
109 // wrong here. The net effect is that I get exceptions thrown in
110 // optimized mode due to the matrix being rank deficient unless I do this.
111 RCP<Thyra::MultiVectorBase<Scalar> > multivec =
112 Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(matrix,
113 true);
114 {
115 RCP<Thyra::VectorBase<Scalar> > vec = Thyra::createMember(x_space_);
116 {
117 Thyra::DetachedVectorView<Scalar> vec_view(*vec);
118 vec_view[0] = 0.0;
119 vec_view[1] = 1.0;
120 }
121 V_V(multivec->col(0).ptr(), *vec);
122 {
123 Thyra::DetachedVectorView<Scalar> vec_view(*vec);
124 vec_view[0] = 1.0;
125 vec_view[1] = 0.0;
126 }
127 V_V(multivec->col(1).ptr(), *vec);
128 }
129 }
130 RCP<Thyra::LinearOpWithSolveBase<Scalar> > W =
131 Thyra::linearOpWithSolve<Scalar>(*W_factory, matrix);
132
133 return W;
134}
135
136template <class Scalar>
137Teuchos::RCP<Thyra::LinearOpBase<Scalar> > VanDerPolModel<Scalar>::create_W_op()
138 const
139{
140 Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > matrix =
141 Thyra::createMembers(x_space_, dim_);
142 return (matrix);
143}
144
145template <class Scalar>
146Teuchos::RCP<const Thyra::LinearOpWithSolveFactoryBase<Scalar> >
148{
149 Teuchos::RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> > W_factory =
150 Thyra::defaultSerialDenseLinearOpWithSolveFactory<Scalar>();
151 return W_factory;
152}
153
154template <class Scalar>
155Thyra::ModelEvaluatorBase::InArgs<Scalar> VanDerPolModel<Scalar>::createInArgs()
156 const
157{
158 setupInOutArgs_();
159 return inArgs_;
160}
161
162// Private functions overridden from ModelEvaluatorDefaultBase
163
164template <class Scalar>
165Thyra::ModelEvaluatorBase::OutArgs<Scalar>
167{
168 setupInOutArgs_();
169 return outArgs_;
170}
171
172template <class Scalar>
174 const Thyra::ModelEvaluatorBase::InArgs<Scalar> &inArgs,
175 const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
176{
177 using Teuchos::RCP;
178 TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
179 "Error, setupInOutArgs_ must be called first!\n");
180
181 const RCP<const Thyra::VectorBase<Scalar> > x_in =
182 inArgs.get_x().assert_not_null();
183 Thyra::ConstDetachedVectorView<Scalar> x_in_view(*x_in);
184
185 // double t = inArgs.get_t();
186 Scalar epsilon = epsilon_;
187 if (acceptModelParams_) {
188 const RCP<const Thyra::VectorBase<Scalar> > p_in =
189 inArgs.get_p(0).assert_not_null();
190 Thyra::ConstDetachedVectorView<Scalar> p_in_view(*p_in);
191 epsilon = p_in_view[0];
192 }
193
194 Scalar beta = inArgs.get_beta();
195
196 const RCP<Thyra::VectorBase<Scalar> > f_out = outArgs.get_f();
197 const RCP<Thyra::LinearOpBase<Scalar> > W_out = outArgs.get_W_op();
198 RCP<Thyra::MultiVectorBase<Scalar> > DfDp_out;
199 if (acceptModelParams_) {
200 Thyra::ModelEvaluatorBase::Derivative<Scalar> DfDp = outArgs.get_DfDp(0);
201 DfDp_out = DfDp.getMultiVector();
202 }
203
204 if (inArgs.get_x_dot().is_null()) {
205 // Evaluate the Explicit ODE f(x,t) [= xdot]
206 if (!is_null(f_out)) {
207 Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
208 f_out_view[0] = x_in_view[1];
209 f_out_view[1] =
210 ((1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] - x_in_view[0]) /
211 epsilon;
212 }
213 if (!is_null(W_out)) {
214 RCP<Thyra::MultiVectorBase<Scalar> > matrix =
215 Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
216 true);
217 Thyra::DetachedMultiVectorView<Scalar> matrix_view(*matrix);
218 matrix_view(0, 0) = 0.0; // d(f0)/d(x0_n)
219 matrix_view(0, 1) = +beta; // d(f0)/d(x1_n)
220 matrix_view(1, 0) = -beta * (2.0 * x_in_view[0] * x_in_view[1] + 1.0) /
221 epsilon; // d(f1)/d(x0_n)
222 matrix_view(1, 1) = beta * (1.0 - x_in_view[0] * x_in_view[0]) /
223 epsilon; // d(f1)/d(x1_n)
224 // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
225 }
226 if (!is_null(DfDp_out)) {
227 Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
228 DfDp_out_view(0, 0) = 0.0;
229 DfDp_out_view(1, 0) =
230 -((1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] - x_in_view[0]) /
231 (epsilon * epsilon);
232 }
233 }
234 else {
235 // Evaluate the implicit ODE f(xdot, x, t) [= 0]
236 RCP<const Thyra::VectorBase<Scalar> > x_dot_in;
237 x_dot_in = inArgs.get_x_dot().assert_not_null();
238 Scalar alpha = inArgs.get_alpha();
239 if (!is_null(f_out)) {
240 Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
241 Thyra::ConstDetachedVectorView<Scalar> x_dot_in_view(*x_dot_in);
242 f_out_view[0] = x_dot_in_view[0] - x_in_view[1];
243 f_out_view[1] =
244 x_dot_in_view[1] -
245 ((1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] - x_in_view[0]) /
246 epsilon;
247 }
248 if (!is_null(W_out)) {
249 RCP<Thyra::MultiVectorBase<Scalar> > matrix =
250 Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
251 true);
252 Thyra::DetachedMultiVectorView<Scalar> matrix_view(*matrix);
253 matrix_view(0, 0) = alpha; // d(f0)/d(x0_n)
254 matrix_view(0, 1) = -beta; // d(f0)/d(x1_n)
255 matrix_view(1, 0) = beta * (2.0 * x_in_view[0] * x_in_view[1] + 1.0) /
256 epsilon; // d(f1)/d(x0_n)
257 matrix_view(1, 1) = alpha - beta * (1.0 - x_in_view[0] * x_in_view[0]) /
258 epsilon; // d(f1)/d(x1_n)
259 // Note: alpha = d(xdot)/d(x_n) and beta = d(x)/d(x_n)
260 }
261 if (!is_null(DfDp_out)) {
262 Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
263 DfDp_out_view(0, 0) = 0.0;
264 DfDp_out_view(1, 0) =
265 ((1.0 - x_in_view[0] * x_in_view[0]) * x_in_view[1] - x_in_view[0]) /
266 (epsilon * epsilon);
267 }
268 }
269}
270
271template <class Scalar>
272Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
274{
275 if (!acceptModelParams_) {
276 return Teuchos::null;
277 }
278 TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE(l, 0, Np_);
279 return p_space_;
280}
281
282template <class Scalar>
283Teuchos::RCP<const Teuchos::Array<std::string> >
285{
286 if (!acceptModelParams_) {
287 return Teuchos::null;
288 }
289 TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE(l, 0, Np_);
290 Teuchos::RCP<Teuchos::Array<std::string> > p_strings =
291 Teuchos::rcp(new Teuchos::Array<std::string>());
292 p_strings->push_back("Model Coefficient: epsilon");
293 return p_strings;
294}
295
296template <class Scalar>
297Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
299{
300 TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE(j, 0, Ng_);
301 return g_space_;
302}
303
304// private
305
306template <class Scalar>
308{
309 if (isInitialized_) {
310 return;
311 }
312
313 {
314 // Set up prototypical InArgs
315 Thyra::ModelEvaluatorBase::InArgsSetup<Scalar> inArgs;
316 inArgs.setModelEvalDescription(this->description());
317 inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_t);
318 inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_x);
319 inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_beta);
320 inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_x_dot);
321 inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_alpha);
322 if (acceptModelParams_) {
323 inArgs.set_Np(Np_);
324 }
325 inArgs_ = inArgs;
326 }
327
328 {
329 // Set up prototypical OutArgs
330 Thyra::ModelEvaluatorBase::OutArgsSetup<Scalar> outArgs;
331 outArgs.setModelEvalDescription(this->description());
332 outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_f);
333 outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_W_op);
334 if (acceptModelParams_) {
335 outArgs.set_Np_Ng(Np_, Ng_);
336 outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_DfDp, 0,
337 Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM);
338 }
339 outArgs_ = outArgs;
340 }
341
342 // Set up nominal values
343 nominalValues_ = inArgs_;
344 if (haveIC_) {
345 using Teuchos::RCP;
346 nominalValues_.set_t(t0_ic_);
347 const RCP<Thyra::VectorBase<Scalar> > x_ic = createMember(x_space_);
348 { // scope to delete DetachedVectorView
349 Thyra::DetachedVectorView<Scalar> x_ic_view(*x_ic);
350 x_ic_view[0] = x0_ic_;
351 x_ic_view[1] = x1_ic_;
352 }
353 nominalValues_.set_x(x_ic);
354 if (acceptModelParams_) {
355 const RCP<Thyra::VectorBase<Scalar> > p_ic = createMember(p_space_);
356 {
357 Thyra::DetachedVectorView<Scalar> p_ic_view(*p_ic);
358 p_ic_view[0] = epsilon_;
359 }
360 nominalValues_.set_p(0, p_ic);
361 }
362 const RCP<Thyra::VectorBase<Scalar> > x_dot_ic = createMember(x_space_);
363 { // scope to delete DetachedVectorView
364 Thyra::DetachedVectorView<Scalar> x_dot_ic_view(*x_dot_ic);
365 x_dot_ic_view[0] = x1_ic_;
366 x_dot_ic_view[1] = ((1.0 - x0_ic_ * x0_ic_) * x1_ic_ - x0_ic_) / epsilon_;
367 }
368 nominalValues_.set_x_dot(x_dot_ic);
369 }
370
371 isInitialized_ = true;
372}
373
374template <class Scalar>
376 Teuchos::RCP<Teuchos::ParameterList> const &paramList)
377{
378 using Teuchos::get;
379 using Teuchos::ParameterList;
380 Teuchos::RCP<ParameterList> tmpPL =
381 Teuchos::rcp(new ParameterList("VanDerPolModel"));
382 if (paramList != Teuchos::null) tmpPL = paramList;
383 tmpPL->validateParametersAndSetDefaults(*this->getValidParameters());
384 this->setMyParamList(tmpPL);
385 Teuchos::RCP<ParameterList> pl = this->getMyNonconstParamList();
386 bool acceptModelParams = get<bool>(*pl, "Accept model parameters");
387 bool haveIC = get<bool>(*pl, "Provide nominal values");
388 if ((acceptModelParams != acceptModelParams_) || (haveIC != haveIC_)) {
389 isInitialized_ = false;
390 }
391 acceptModelParams_ = acceptModelParams;
392 haveIC_ = haveIC;
393 epsilon_ = get<Scalar>(*pl, "Coeff epsilon");
394 x0_ic_ = get<Scalar>(*pl, "IC x0");
395 x1_ic_ = get<Scalar>(*pl, "IC x1");
396 t0_ic_ = get<Scalar>(*pl, "IC t0");
397 setupInOutArgs_();
398}
399
400template <class Scalar>
401Teuchos::RCP<const Teuchos::ParameterList>
403{
404 static Teuchos::RCP<const Teuchos::ParameterList> validPL;
405 if (is_null(validPL)) {
406 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
407 pl->set("Accept model parameters", false);
408 pl->set("Provide nominal values", true);
409 Teuchos::setDoubleParameter("Coeff epsilon", 1.0e-06,
410 "Coefficient a in model", &*pl);
411 Teuchos::setDoubleParameter("IC x0", 2.0, "Initial Condition for x0", &*pl);
412 Teuchos::setDoubleParameter("IC x1", 0.0, "Initial Condition for x1", &*pl);
413 Teuchos::setDoubleParameter("IC t0", 0.0, "Initial time t0", &*pl);
414 Teuchos::setIntParameter("Number of Time Step Sizes", 1,
415 "Number time step sizes for convergence study",
416 &*pl);
417 validPL = pl;
418 }
419 return validPL;
420}
421
422} // namespace Tempus_Test
423#endif // TEMPUS_TEST_VANDERPOL_MODEL_IMPL_HPP
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int l) const
Thyra::ModelEvaluatorBase::OutArgs< Scalar > createOutArgsImpl() const
Thyra::ModelEvaluatorBase::InArgs< Scalar > getExactSolution(double t) const
Thyra::ModelEvaluatorBase::InArgs< Scalar > getExactSensSolution(int j, double t) const
Thyra::ModelEvaluatorBase::InArgs< Scalar > getNominalValues() const
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Thyra::ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs_bar, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs_bar) const
VanDerPolModel(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_f_space() const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_x_space() const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_p_space(int l) const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_g_space(int j) const
Teuchos::RCP< Thyra::LinearOpBase< Scalar > > create_W_op() const
Teuchos::RCP< Thyra::LinearOpWithSolveBase< Scalar > > create_W() const
Teuchos::RCP< const Thyra::LinearOpWithSolveFactoryBase< Scalar > > get_W_factory() const
void setParameterList(Teuchos::RCP< Teuchos::ParameterList > const &paramList)