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