Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SteadyQuadraticModel_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_STEADY_QUADRATIC_MODEL_IMPL_HPP
11 #define TEMPUS_TEST_STEADY_QUADRATIC_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_MultiVectorStdOps.hpp"
22 #include "Thyra_VectorStdOps.hpp"
23 #include "Thyra_DefaultMultiVectorProductVector.hpp"
24 
25 #include <iostream>
26 
27 namespace Tempus_Test {
28 
29 template <class Scalar>
32 {
33  isInitialized_ = false;
34  dim_ = 1;
35  Np_ = 3; // Number of parameter vectors (p, dx/dp, dx_dot/dp)
36  np_ = 1; // Number of parameters in this vector (3)
37  Ng_ = 1; // Number of observation functions (1)
38  ng_ = 1; // Number of elements in this observation function (1)
39  useDfDpAsTangent_ = false;
40  b_ = 1.0;
41 
42  // Create x_space and f_space
43  x_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
44  f_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(dim_);
45  // Create p_space and g_space
46  p_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(np_);
47  g_space_ = Thyra::defaultSpmdVectorSpace<Scalar>(ng_);
48 
49  setParameterList(pList_);
50 
51  // Create DxDp product space
52  DxDp_space_ = Thyra::multiVectorProductVectorSpace(x_space_, np_);
53 }
54 
55 template <class Scalar>
57 {
58  if (b_ < 0.0) return b_;
59  return -b_;
60 }
61 
62 template <class Scalar>
64 {
65  if (b_ < 0.0) return 1.0;
66  return -1.0;
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 {
96  using Teuchos::RCP;
98  this->get_W_factory();
99  RCP<Thyra::LinearOpBase<Scalar> > matrix = this->create_W_op();
100  {
101  // 01/20/09 tscoffe: This is a total hack to provide a full rank matrix to
102  // linearOpWithSolve because it ends up factoring the matrix during
103  // initialization, which it really shouldn't do, or I'm doing something
104  // wrong here. The net effect is that I get exceptions thrown in
105  // optimized mode due to the matrix being rank deficient unless I do this.
107  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(matrix,
108  true);
109  {
110  RCP<Thyra::VectorBase<Scalar> > vec = Thyra::createMember(x_space_);
111  {
112  Thyra::DetachedVectorView<Scalar> vec_view(*vec);
113  vec_view[0] = 1.0;
114  }
115  V_V(multivec->col(0).ptr(), *vec);
116  }
117  }
119  Thyra::linearOpWithSolve<Scalar>(*W_factory, matrix);
120  return W;
121 }
122 
123 template <class Scalar>
126 {
128  Thyra::createMembers(x_space_, dim_);
129  return (matrix);
130 }
131 
132 template <class Scalar>
135 {
137  Thyra::defaultSerialDenseLinearOpWithSolveFactory<Scalar>();
138  return W_factory;
139 }
140 
141 template <class Scalar>
144 {
145  setupInOutArgs_();
146  return inArgs_;
147 }
148 
149 // Private functions overridden from ModelEvaluatorDefaultBase
150 
151 template <class Scalar>
154 {
155  setupInOutArgs_();
156  return outArgs_;
157 }
158 
159 template <class Scalar>
162  const Thyra::ModelEvaluatorBase::OutArgs<Scalar> &outArgs) const
163 {
165  using Teuchos::RCP;
166  using Teuchos::rcp_dynamic_cast;
168  using Thyra::VectorBase;
169  TEUCHOS_TEST_FOR_EXCEPTION(!isInitialized_, std::logic_error,
170  "Error, setupInOutArgs_ must be called first!\n");
171 
172  const RCP<const VectorBase<Scalar> > x_in = inArgs.get_x().assert_not_null();
174 
175  Scalar b = b_;
176  const RCP<const VectorBase<Scalar> > p_in = inArgs.get_p(0);
177  if (p_in != Teuchos::null) {
179  b = p_in_view[0];
180  }
181 
182  RCP<const MultiVectorBase<Scalar> > DxDp_in, DxdotDp_in;
183  if (inArgs.get_p(1) != Teuchos::null)
184  DxDp_in = rcp_dynamic_cast<const DMVPV>(inArgs.get_p(1))->getMultiVector();
185  if (inArgs.get_p(2) != Teuchos::null)
186  DxdotDp_in =
187  rcp_dynamic_cast<const DMVPV>(inArgs.get_p(2))->getMultiVector();
188 
189  Scalar beta = inArgs.get_beta();
190 
191  const RCP<VectorBase<Scalar> > f_out = outArgs.get_f();
192  const RCP<Thyra::LinearOpBase<Scalar> > W_out = outArgs.get_W_op();
195  DfDp_out = DfDp.getMultiVector();
196 
197  if (inArgs.get_x_dot().is_null()) {
198  // Evaluate the Explicit ODE f(x,t) [= 0]
199  if (!is_null(f_out)) {
200  Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
201  f_out_view[0] = x_in_view[0] * x_in_view[0] - b * b;
202  }
203  if (!is_null(W_out)) {
205  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
206  true);
207  Thyra::DetachedMultiVectorView<Scalar> matrix_view(*matrix);
208  matrix_view(0, 0) = beta * 2.0 * x_in_view[0];
209  }
210  if (!is_null(DfDp_out)) {
211  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
212  DfDp_out_view(0, 0) = -2.0 * b;
213 
214  // Compute df/dp + (df/dx) * (dx/dp)
215  if (useDfDpAsTangent_ && !is_null(DxDp_in)) {
217  DfDp_out_view(0, 0) += 2.0 * x_in_view[0] * DxDp(0, 0);
218  }
219  }
220  }
221  else {
222  // Evaluate the implicit ODE f(xdot, x, t) [= 0]
223  RCP<const VectorBase<Scalar> > x_dot_in;
224  x_dot_in = inArgs.get_x_dot().assert_not_null();
225  Scalar alpha = inArgs.get_alpha();
226  if (!is_null(f_out)) {
227  Thyra::DetachedVectorView<Scalar> f_out_view(*f_out);
228  Thyra::ConstDetachedVectorView<Scalar> x_dot_in_view(*x_dot_in);
229  f_out_view[0] = x_dot_in_view[0] - (x_in_view[0] * x_in_view[0] - b * b);
230  }
231  if (!is_null(W_out)) {
233  Teuchos::rcp_dynamic_cast<Thyra::MultiVectorBase<Scalar> >(W_out,
234  true);
235  Thyra::DetachedMultiVectorView<Scalar> matrix_view(*matrix);
236  matrix_view(0, 0) = alpha - beta * 2.0 * x_in_view[0];
237  }
238  if (!is_null(DfDp_out)) {
239  Thyra::DetachedMultiVectorView<Scalar> DfDp_out_view(*DfDp_out);
240  DfDp_out_view(0, 0) = 2.0 * b;
241 
242  // Compute df/dp + (df/dx_dot) * (dx_dot/dp) + (df/dx) * (dx/dp)
243  if (useDfDpAsTangent_ && !is_null(DxdotDp_in)) {
244  Thyra::ConstDetachedMultiVectorView<Scalar> DxdotDp(*DxdotDp_in);
245  DfDp_out_view(0, 0) += DxdotDp(0, 0);
246  }
247  if (useDfDpAsTangent_ && !is_null(DxDp_in)) {
249  DfDp_out_view(0, 0) += -2.0 * x_in_view[0] * DxDp(0, 0);
250  }
251  }
252  }
253 
254  // Responses: g = x
255  RCP<VectorBase<Scalar> > g_out = outArgs.get_g(0);
256  if (g_out != Teuchos::null) Thyra::assign(g_out.ptr(), *x_in);
257 
259  outArgs.get_DgDp(0, 0).getMultiVector();
260  if (DgDp_out != Teuchos::null) Thyra::assign(DgDp_out.ptr(), Scalar(0.0));
261 
263  outArgs.get_DgDx(0).getMultiVector();
264  if (DgDx_out != Teuchos::null) {
265  Thyra::DetachedMultiVectorView<Scalar> DgDx_out_view(*DgDx_out);
266  DgDx_out_view(0, 0) = 1.0;
267  }
268 }
269 
270 template <class Scalar>
273 {
275  if (l == 0)
276  return p_space_;
277  else if (l == 1 || l == 2)
278  return DxDp_space_;
279  return Teuchos::null;
280 }
281 
282 template <class Scalar>
285 {
289  if (l == 0) {
290  p_strings->push_back("Model Coefficient: b");
291  }
292  else if (l == 1)
293  p_strings->push_back("DxDp");
294  else if (l == 2)
295  p_strings->push_back("Dx_dotDp");
296  return p_strings;
297 }
298 
299 template <class Scalar>
302 {
304  return g_space_;
305 }
306 
307 // private
308 
309 template <class Scalar>
311 {
312  if (isInitialized_) {
313  return;
314  }
315 
316  {
317  // Set up prototypical InArgs
319  inArgs.setModelEvalDescription(this->description());
320  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_t);
321  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_x);
322  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_beta);
323  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_x_dot);
324  inArgs.setSupports(Thyra::ModelEvaluatorBase::IN_ARG_alpha);
325  inArgs.set_Np(Np_);
326  inArgs_ = inArgs;
327  }
328 
329  {
330  // Set up prototypical OutArgs
332  outArgs.setModelEvalDescription(this->description());
333  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_f);
334  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_W_op);
335  outArgs.set_Np_Ng(Np_, Ng_);
336  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_DfDp, 0,
337  Thyra::ModelEvaluatorBase::DERIV_MV_JACOBIAN_FORM);
338  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_DgDx, 0,
339  Thyra::ModelEvaluatorBase::DERIV_MV_GRADIENT_FORM);
340  outArgs.setSupports(Thyra::ModelEvaluatorBase::OUT_ARG_DgDp, 0, 0,
341  Thyra::ModelEvaluatorBase::DERIV_MV_GRADIENT_FORM);
342  outArgs_ = outArgs;
343  }
344 
345  // Set up nominal values
346  nominalValues_ = inArgs_;
347  nominalValues_.set_t(0.0);
348  const Teuchos::RCP<Thyra::VectorBase<Scalar> > x_ic = createMember(x_space_);
349  { // scope to delete DetachedVectorView
350  Thyra::DetachedVectorView<Scalar> x_ic_view(*x_ic);
351  x_ic_view[0] = 0.0;
352  }
353  nominalValues_.set_x(x_ic);
354  const Teuchos::RCP<Thyra::VectorBase<Scalar> > p_ic = createMember(p_space_);
355  {
356  Thyra::DetachedVectorView<Scalar> p_ic_view(*p_ic);
357  p_ic_view[0] = b_;
358  }
359  nominalValues_.set_p(0, p_ic);
360 
361  const Teuchos::RCP<Thyra::VectorBase<Scalar> > x_dot_ic =
362  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] = 0.0;
366  }
367  nominalValues_.set_x_dot(x_dot_ic);
368 
369  isInitialized_ = true;
370 }
371 
372 template <class Scalar>
374  Teuchos::RCP<Teuchos::ParameterList> const &paramList)
375 {
376  using Teuchos::get;
379  Teuchos::rcp(new ParameterList("SteadyQuadraticModel"));
380  if (paramList != Teuchos::null) tmpPL = paramList;
381  tmpPL->validateParametersAndSetDefaults(*this->getValidParameters());
382  this->setMyParamList(tmpPL);
383  Teuchos::RCP<ParameterList> pl = this->getMyNonconstParamList();
384  useDfDpAsTangent_ = get<bool>(*pl, "Use DfDp as Tangent");
385  b_ = get<Scalar>(*pl, "Coeff b");
386  isInitialized_ = false; // For setup of new in/out args
387  setupInOutArgs_();
388 }
389 
390 template <class Scalar>
393 {
395  if (is_null(validPL)) {
396  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
397  pl->set("Use DfDp as Tangent", false);
398  Teuchos::setDoubleParameter("Coeff b", 1.0, "Coefficient b in model", &*pl);
399  validPL = pl;
400  }
401  return validPL;
402 }
403 
404 } // namespace Tempus_Test
405 #endif // TEMPUS_TEST_STEADY_QUADRATIC_MODEL_IMPL_HPP
Teuchos::RCP< Thyra::LinearOpBase< Scalar > > create_W_op() const
void evalModelImpl(const Thyra::ModelEvaluatorBase::InArgs< Scalar > &inArgs_bar, const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs_bar) const
bool is_null(const boost::shared_ptr< T > &p)
Derivative< Scalar > get_DfDp(int l) const
RCP< const VectorBase< Scalar > > get_x_dot() const
void setModelEvalDescription(const std::string &modelEvalDescription)
#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_g(int j) const
Evaluation< VectorBase< Scalar > > get_f() const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Thyra::ModelEvaluatorBase::InArgs< Scalar > createInArgs() const
Derivative< Scalar > get_DgDp(int j, int l) const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_g_space(int j) const
#define TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE(index, lower_inclusive, upper_exclusive)
void setSupports(EInArgsMembers arg, bool supports=true)
Teuchos::RCP< const Teuchos::Array< std::string > > get_p_names(int l) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void setParameterList(Teuchos::RCP< Teuchos::ParameterList > const &paramList)
Ptr< T > ptr() const
Teuchos::RCP< Thyra::LinearOpWithSolveBase< Scalar > > create_W() const
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
Thyra::ModelEvaluatorBase::InArgs< Scalar > getNominalValues() const
void setSupports(EOutArgsMembers arg, bool supports=true)
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_f_space() const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_x_space() const
Teuchos::RCP< const Thyra::LinearOpWithSolveFactoryBase< Scalar > > get_W_factory() const
void setModelEvalDescription(const std::string &modelEvalDescription)
Thyra::ModelEvaluatorBase::OutArgs< Scalar > createOutArgsImpl() const
RCP< LinearOpBase< Scalar > > get_W_op() const
RCP< const VectorBase< Scalar > > get_x() const
SteadyQuadraticModel(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
RCP< const VectorBase< Scalar > > get_p(int l) const
RCP< MultiVectorBase< Scalar > > getMultiVector() const
Derivative< Scalar > get_DgDx(int j) const