Tempus  Version of the Day
Time Integration
Tempus_IntegratorPseudoTransientForwardSensitivity_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_IntegratorPseudoTransientForwardSensitivity_impl_hpp
10 #define Tempus_IntegratorPseudoTransientForwardSensitivity_impl_hpp
11 
12 #include "Thyra_DefaultMultiVectorProductVector.hpp"
13 #include "Thyra_VectorStdOps.hpp"
14 #include "Thyra_MultiVectorStdOps.hpp"
15 
17 
18 
19 namespace Tempus {
20 
21 template <class Scalar>
23  const Teuchos::RCP<Thyra::ModelEvaluator<Scalar>> &model,
24  const Teuchos::RCP<SensitivityModelEvaluatorBase<Scalar>> &sens_model,
25  const Teuchos::RCP<IntegratorBasic<Scalar>> &fwd_integrator,
26  const Teuchos::RCP<IntegratorBasic<Scalar>> &sens_integrator,
27  const bool reuse_solver,
28  const bool force_W_update)
29  : model_(model)
30  , sens_model_(sens_model)
31  , state_integrator_(fwd_integrator)
32  , sens_integrator_(sens_integrator)
33  , reuse_solver_(reuse_solver)
34  , force_W_update_(force_W_update)
35 {
36 }
37 
38 template<class Scalar>
41  reuse_solver_(false),
42  force_W_update_(false)
43 {
44  state_integrator_ = createIntegratorBasic<Scalar>();
45  sens_integrator_ = createIntegratorBasic<Scalar>();
46 }
47 
48 template<class Scalar>
49 bool
52 {
53  using Teuchos::RCP;
54  using Thyra::VectorBase;
55 
56  // Run state integrator and get solution
57  bool state_status = state_integrator_->advanceTime();
58 
59  // Set solution in sensitivity ME
60  sens_model_->setForwardSolutionState(state_integrator_->getCurrentState());
61 
62  // Reuse state solver if requested
63  if (reuse_solver_ &&
64  state_integrator_->getStepper()->getSolver() != Teuchos::null) {
65  sens_model_->setSolver(state_integrator_->getStepper()->getSolver(),
66  force_W_update_);
67  }
68 
69  // Run sensitivity integrator
70  bool sens_status = sens_integrator_->advanceTime();
71 
72  buildSolutionHistory();
73 
74  return state_status && sens_status;
75 }
76 
77 template<class Scalar>
78 bool
80 advanceTime(const Scalar timeFinal)
81 {
82  using Teuchos::RCP;
83  using Thyra::VectorBase;
84 
85  // Run state integrator and get solution
86  bool state_status = state_integrator_->advanceTime(timeFinal);
87 
88  // Set solution in sensitivity ME
89  sens_model_->setForwardSolutionState(state_integrator_->getCurrentState());
90 
91  // Reuse state solver if requested
92  if (reuse_solver_ &&
93  state_integrator_->getStepper()->getSolver() != Teuchos::null) {
94  sens_model_->setSolver(state_integrator_->getStepper()->getSolver(),
95  force_W_update_);
96  }
97 
98  // Run sensitivity integrator
99  bool sens_status = sens_integrator_->advanceTime(timeFinal);
100 
101  buildSolutionHistory();
102 
103  return state_status && sens_status;
104 }
105 
106 template<class Scalar>
107 Scalar
109 getTime() const
110 {
111  return solutionHistory_->getCurrentTime();
112 }
113 
114 template<class Scalar>
115 int
117 getIndex() const
118 {
119  return solutionHistory_->getCurrentIndex();
120 }
121 
122 template<class Scalar>
123 Status
125 getStatus() const
126 {
127  Status state_status = state_integrator_->getStatus();
128  Status sens_status = sens_integrator_->getStatus();
129  if (state_status == FAILED || sens_status == FAILED)
130  return FAILED;
131  if (state_status == WORKING || sens_status == WORKING)
132  return WORKING;
133  return PASSED;
134 }
135 
136 template <class Scalar>
138  const Status st) {
139  state_integrator_->setStatus(st);
140  sens_integrator_->setStatus(st);
141 }
142 
143 template<class Scalar>
144 Teuchos::RCP<Stepper<Scalar> >
146 getStepper() const
147 {
148  return state_integrator_->getStepper();
149 }
150 
151 template<class Scalar>
152 Teuchos::RCP<const SolutionHistory<Scalar> >
155 {
156  return solutionHistory_;
157 }
158 
159 template<class Scalar>
160 Teuchos::RCP<SolutionHistory<Scalar> >
163 {
164  return solutionHistory_;
165 }
166 
167 template<class Scalar>
168 Teuchos::RCP<const TimeStepControl<Scalar> >
171 {
172  return state_integrator_->getTimeStepControl();
173 }
174 
175 template<class Scalar>
176 Teuchos::RCP<TimeStepControl<Scalar> >
179 {
180  return state_integrator_->getNonConstTimeStepControl();
181 }
182 
183 template<class Scalar>
186  Teuchos::RCP<const Thyra::VectorBase<Scalar> > x0,
187  Teuchos::RCP<const Thyra::VectorBase<Scalar> > xdot0,
188  Teuchos::RCP<const Thyra::VectorBase<Scalar> > xdotdot0,
189  Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > DxDp0,
190  Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > DxdotDp0,
191  Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> > DxdotdotDp0)
192 {
193  using Teuchos::RCP;
194  using Teuchos::rcp_dynamic_cast;
195  using Thyra::VectorSpaceBase;
196  using Thyra::assign;
197  using Thyra::createMember;
198  typedef Thyra::DefaultMultiVectorProductVector<Scalar> DMVPV;
199 
200  //
201  // Create and initialize product X, Xdot, Xdotdot
202 
203  RCP< const VectorSpaceBase<Scalar> > space = sens_model_->get_x_space();
204  RCP<DMVPV> X = rcp_dynamic_cast<DMVPV>(createMember(space));
205  RCP<DMVPV> Xdot = rcp_dynamic_cast<DMVPV>(createMember(space));
206  RCP<DMVPV> Xdotdot = rcp_dynamic_cast<DMVPV>(createMember(space));
207  const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
208 
209  // x
210  if (DxDp0 == Teuchos::null)
211  assign(X->getNonconstMultiVector().ptr(), zero);
212  else
213  assign(X->getNonconstMultiVector().ptr(), *DxDp0);
214 
215  // xdot
216  if (DxdotDp0 == Teuchos::null)
217  assign(Xdot->getNonconstMultiVector().ptr(), zero);
218  else
219  assign(Xdot->getNonconstMultiVector().ptr(), *DxdotDp0);
220 
221  // xdotdot
222  if (DxdotDp0 == Teuchos::null)
223  assign(Xdotdot->getNonconstMultiVector().ptr(), zero);
224  else
225  assign(Xdotdot->getNonconstMultiVector().ptr(), *DxdotdotDp0);
226 
227  state_integrator_->initializeSolutionHistory(t0, x0, xdot0, xdotdot0);
228  sens_integrator_->initializeSolutionHistory(t0, X, Xdot, Xdotdot);
229 }
230 
231 template<class Scalar>
232 Teuchos::RCP<const Thyra::VectorBase<Scalar> >
234 getX() const
235 {
236  using Teuchos::RCP;
237  using Teuchos::rcp_dynamic_cast;
238  typedef Thyra::DefaultMultiVectorProductVector<Scalar> DMVPV;
239 
240  RCP<const DMVPV> X =
241  rcp_dynamic_cast<const DMVPV>(solutionHistory_->getCurrentState()->getX());
242  return X->getMultiVector()->col(0);
243 }
244 
245 template<class Scalar>
246 Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> >
248 getDxDp() const
249 {
250  using Teuchos::RCP;
251  using Teuchos::rcp_dynamic_cast;
252  typedef Thyra::DefaultMultiVectorProductVector<Scalar> DMVPV;
253 
254  RCP<const DMVPV> X =
255  rcp_dynamic_cast<const DMVPV>(solutionHistory_->getCurrentState()->getX());
256  const int num_param = X->getMultiVector()->domain()->dim()-1;
257  const Teuchos::Range1D rng(1,num_param);
258  return X->getMultiVector()->subView(rng);
259 }
260 
261 template<class Scalar>
262 Teuchos::RCP<const Thyra::VectorBase<Scalar> >
264 getXDot() const
265 {
266  using Teuchos::RCP;
267  using Teuchos::rcp_dynamic_cast;
268  typedef Thyra::DefaultMultiVectorProductVector<Scalar> DMVPV;
269 
270  RCP<const DMVPV> Xdot =
271  rcp_dynamic_cast<const DMVPV>(solutionHistory_->getCurrentState()->getXDot());
272  return Xdot->getMultiVector()->col(0);
273 }
274 
275 template<class Scalar>
276 Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> >
278 getDXDotDp() const
279 {
280  using Teuchos::RCP;
281  using Teuchos::rcp_dynamic_cast;
282  typedef Thyra::DefaultMultiVectorProductVector<Scalar> DMVPV;
283 
284  RCP<const DMVPV> Xdot =
285  rcp_dynamic_cast<const DMVPV>(solutionHistory_->getCurrentState()->getXDot());
286  const int num_param = Xdot->getMultiVector()->domain()->dim()-1;
287  const Teuchos::Range1D rng(1,num_param);
288  return Xdot->getMultiVector()->subView(rng);
289 }
290 
291 template<class Scalar>
292 Teuchos::RCP<const Thyra::VectorBase<Scalar> >
294 getXDotDot() const
295 {
296  using Teuchos::RCP;
297  using Teuchos::rcp_dynamic_cast;
298  typedef Thyra::DefaultMultiVectorProductVector<Scalar> DMVPV;
299 
300  RCP<const DMVPV> Xdotdot =
301  rcp_dynamic_cast<const DMVPV>(solutionHistory_->getCurrentState()->getXDotDot());
302  return Xdotdot->getMultiVector()->col(0);
303 }
304 
305 template<class Scalar>
306 Teuchos::RCP<const Thyra::MultiVectorBase<Scalar> >
309 {
310  using Teuchos::RCP;
311  using Teuchos::rcp_dynamic_cast;
312  typedef Thyra::DefaultMultiVectorProductVector<Scalar> DMVPV;
313 
314  RCP<const DMVPV> Xdotdot =
315  rcp_dynamic_cast<const DMVPV>(solutionHistory_->getCurrentState()->getXDotDot());
316  const int num_param = Xdotdot->getMultiVector()->domain()->dim()-1;
317  const Teuchos::Range1D rng(1,num_param);
318  return Xdotdot->getMultiVector()->subView(rng);
319 }
320 
321 template<class Scalar>
322 std::string
324 description() const
325 {
326  std::string name = "Tempus::IntegratorPseudoTransientForwardSensitivity";
327  return(name);
328 }
329 
330 template<class Scalar>
331 void
334  Teuchos::FancyOStream &out,
335  const Teuchos::EVerbosityLevel verbLevel) const
336 {
337  auto l_out = Teuchos::fancyOStream( out.getOStream() );
338  Teuchos::OSTab ostab(*l_out, 2, this->description());
339  l_out->setOutputToRootOnly(0);
340 
341  *l_out << description() << "::describe" << std::endl;
342  state_integrator_->describe(*l_out, verbLevel);
343  sens_integrator_->describe(*l_out, verbLevel);
344 }
345 
346 
347 template<class Scalar>
348 void
351 {
352  using Teuchos::RCP;
353  using Teuchos::rcp;
354  using Teuchos::rcp_dynamic_cast;
355  using Teuchos::ParameterList;
356  using Thyra::VectorBase;
358  using Thyra::VectorSpaceBase;
359  using Thyra::createMembers;
360  using Thyra::multiVectorProductVector;
361  using Thyra::assign;
362  typedef Thyra::DefaultMultiVectorProductVector<Scalar> DMVPV;
363 
364  //TODO: get the solution history PL or create it
365 
366  // Create combined solution histories, first for the states with zero
367  // sensitivities and then for the sensitivities with frozen states
368  RCP<ParameterList> shPL;
369  //Teuchos::sublist(state_integrator_->getIntegratorParameterList(), "Solution History", true);
370  solutionHistory_ = createSolutionHistoryPL<Scalar>(shPL);
371 
372  const int num_param =
373  rcp_dynamic_cast<const DMVPV>(sens_integrator_->getX())->getMultiVector()->domain()->dim();
374  RCP<const VectorSpaceBase<Scalar> > x_space = model_->get_x_space();
375  RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > prod_space =
376  Thyra::multiVectorProductVectorSpace(x_space, num_param+1);
377  const Teuchos::Range1D rng(1,num_param);
378  const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
379 
380  RCP<const SolutionHistory<Scalar> > state_solution_history =
381  state_integrator_->getSolutionHistory();
382  int num_states = state_solution_history->getNumStates();
383  for (int i=0; i<num_states; ++i) {
384  RCP<const SolutionState<Scalar> > state = (*state_solution_history)[i];
385 
386  // X
387  RCP< MultiVectorBase<Scalar> > x_mv =
388  createMembers(x_space, num_param+1);
389  assign(x_mv->col(0).ptr(), *(state->getX()));
390  assign(x_mv->subView(rng).ptr(), zero);
391  RCP<VectorBase<Scalar> > x = multiVectorProductVector(prod_space, x_mv);
392 
393  // X-Dot
394  RCP<VectorBase<Scalar> > x_dot;
395  if (state->getXDot() != Teuchos::null) {
396  RCP< MultiVectorBase<Scalar> > x_dot_mv =
397  createMembers(x_space, num_param+1);
398  assign(x_dot_mv->col(0).ptr(), *(state->getXDot()));
399  assign(x_dot_mv->subView(rng).ptr(), zero);
400  x_dot = multiVectorProductVector(prod_space, x_dot_mv);
401  }
402 
403  // X-Dot-Dot
404  RCP<VectorBase<Scalar> > x_dot_dot;
405  if (state->getXDotDot() != Teuchos::null) {
406  RCP< MultiVectorBase<Scalar> > x_dot_dot_mv =
407  createMembers(x_space, num_param+1);
408  assign(x_dot_dot_mv->col(0).ptr(), *(state->getXDotDot()));
409  assign(x_dot_dot_mv->subView(rng).ptr(), zero);
410  x_dot_dot = multiVectorProductVector(prod_space, x_dot_dot_mv);
411  }
412 
413  RCP<SolutionState<Scalar> > prod_state = state->clone();
414  prod_state->setX(x);
415  prod_state->setXDot(x_dot);
416  prod_state->setXDotDot(x_dot_dot);
417  solutionHistory_->addState(prod_state);
418  }
419 
420  RCP<const VectorBase<Scalar> > frozen_x =
421  state_solution_history->getCurrentState()->getX();
422  RCP<const VectorBase<Scalar> > frozen_x_dot =
423  state_solution_history->getCurrentState()->getXDot();
424  RCP<const VectorBase<Scalar> > frozen_x_dot_dot =
425  state_solution_history->getCurrentState()->getXDotDot();
426  RCP<const SolutionHistory<Scalar> > sens_solution_history =
427  sens_integrator_->getSolutionHistory();
428  num_states = sens_solution_history->getNumStates();
429  for (int i=0; i<num_states; ++i) {
430  RCP<const SolutionState<Scalar> > state = (*sens_solution_history)[i];
431 
432  // X
433  RCP< MultiVectorBase<Scalar> > x_mv =
434  createMembers(x_space, num_param+1);
435  RCP<const MultiVectorBase<Scalar> > dxdp =
436  rcp_dynamic_cast<const DMVPV>(state->getX())->getMultiVector();
437  assign(x_mv->col(0).ptr(), *(frozen_x));
438  assign(x_mv->subView(rng).ptr(), *dxdp);
439  RCP<VectorBase<Scalar> > x = multiVectorProductVector(prod_space, x_mv);
440 
441  // X-Dot
442  RCP<VectorBase<Scalar> > x_dot;
443  if (state->getXDot() != Teuchos::null) {
444  RCP< MultiVectorBase<Scalar> > x_dot_mv =
445  createMembers(x_space, num_param+1);
446  RCP<const MultiVectorBase<Scalar> > dxdotdp =
447  rcp_dynamic_cast<const DMVPV>(state->getXDot())->getMultiVector();
448  assign(x_dot_mv->col(0).ptr(), *(frozen_x_dot));
449  assign(x_dot_mv->subView(rng).ptr(), *dxdotdp);
450  x_dot = multiVectorProductVector(prod_space, x_dot_mv);
451  }
452 
453  // X-Dot-Dot
454  RCP<VectorBase<Scalar> > x_dot_dot;
455  if (state->getXDotDot() != Teuchos::null) {
456  RCP< MultiVectorBase<Scalar> > x_dot_dot_mv =
457  createMembers(x_space, num_param+1);
458  RCP<const MultiVectorBase<Scalar> > dxdotdotdp =
459  rcp_dynamic_cast<const DMVPV>(state->getXDotDot())->getMultiVector();
460  assign(x_dot_dot_mv->col(0).ptr(), *(frozen_x_dot_dot));
461  assign(x_dot_dot_mv->subView(rng).ptr(), *dxdotdotdp);
462  x_dot_dot = multiVectorProductVector(prod_space, x_dot_dot_mv);
463  }
464 
465  RCP<SolutionState<Scalar> > prod_state = state->clone();
466  prod_state->setX(x);
467  prod_state->setXDot(x_dot);
468  prod_state->setXDotDot(x_dot_dot);
469  solutionHistory_->addState(prod_state, false);
470  }
471 }
472 
474 template<class Scalar>
475 Teuchos::RCP<Tempus::IntegratorPseudoTransientForwardSensitivity<Scalar> >
477  Teuchos::RCP<Teuchos::ParameterList> pList,
478  const Teuchos::RCP<Thyra::ModelEvaluator<Scalar> >& model)
479 {
480 
481  auto fwd_integrator = createIntegratorBasic<Scalar>(pList, model);
482  Teuchos::RCP<SensitivityModelEvaluatorBase<Scalar> > sens_model;
483  Teuchos::RCP<IntegratorBasic<Scalar> > sens_integrator;
484 
485  {
486  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::rcp(new Teuchos::ParameterList);
487  Teuchos::RCP<const Teuchos::ParameterList> integrator_pl = fwd_integrator->getValidParameters();
488  Teuchos::RCP<const Teuchos::ParameterList> sensitivity_pl =
490  pl->setParameters(*integrator_pl);
491  pl->sublist("Sensitivities").setParameters(*sensitivity_pl);
492  pl->sublist("Sensitivities").set("Reuse State Linear Solver", false);
493  pl->sublist("Sensitivities").set("Force W Update", false);
494  pList->setParametersNotAlreadySet(*pl);
495  }
496 
497  bool reuse_solver = pList->sublist("Sensitivities").get("Reuse State Linear Solver", false);
498  bool force_W_update = pList->sublist("Sensitivities").get("Force W Update", false);
499 
500  {
501  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
502  if (pList!= Teuchos::null)
503  {
504  *pl = pList->sublist("Sensitivities");
505  }
506  pl->remove("Reuse State Linear Solver");
507  pl->remove("Force W Update");
508  sens_model = wrapStaggeredFSAModelEvaluator(model, pl);
509  sens_integrator = createIntegratorBasic<Scalar>(pList, sens_model);
510  }
511 
512  Teuchos::RCP<Tempus::IntegratorPseudoTransientForwardSensitivity<Scalar>> integrator =
514  model, sens_model, fwd_integrator, sens_integrator, reuse_solver, force_W_update));
515 
516  return(integrator);
517 }
518 
519 
521 template<class Scalar>
522 Teuchos::RCP<Tempus::IntegratorPseudoTransientForwardSensitivity<Scalar> >
524 {
525  Teuchos::RCP<Tempus::IntegratorPseudoTransientForwardSensitivity<Scalar> > integrator =
527  return(integrator);
528 }
529 
530 } // namespace Tempus
531 #endif // Tempus_IntegratorPseudoTransientForwardSensitivity_impl_hpp
virtual Teuchos::RCP< const Thyra::VectorBase< Scalar > > getX() const
Get current the solution, x.
virtual Teuchos::RCP< Stepper< Scalar > > getStepper() const override
Get the Stepper.
virtual Teuchos::RCP< const Thyra::MultiVectorBase< Scalar > > getDXDotDp() const
virtual Teuchos::RCP< const SolutionHistory< Scalar > > getSolutionHistory() const override
Get the SolutionHistory.
Teuchos::RCP< SensitivityModelEvaluatorBase< Scalar > > wrapStaggeredFSAModelEvaluator(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model, const Teuchos::RCP< const Teuchos::ParameterList > &pList=Teuchos::null)
virtual Teuchos::RCP< TimeStepControl< Scalar > > getNonConstTimeStepControl() override
virtual Teuchos::RCP< const Thyra::VectorBase< Scalar > > getXDot() const
Get current the time derivative of the solution, xdot.
virtual Teuchos::RCP< const Thyra::MultiVectorBase< Scalar > > getDxDp() const
virtual void initializeSolutionHistory(Scalar t0, Teuchos::RCP< const Thyra::VectorBase< Scalar > > x0, Teuchos::RCP< const Thyra::VectorBase< Scalar > > xdot0=Teuchos::null, Teuchos::RCP< const Thyra::VectorBase< Scalar > > xdotdot0=Teuchos::null, Teuchos::RCP< const Thyra::MultiVectorBase< Scalar > > DxDp0=Teuchos::null, Teuchos::RCP< const Thyra::MultiVectorBase< Scalar > > DxdotDp0=Teuchos::null, Teuchos::RCP< const Thyra::MultiVectorBase< Scalar > > DxdotdotDp0=Teuchos::null)
Set the initial state from Thyra::VectorBase(s)
virtual bool advanceTime()
Advance the solution to timeMax, and return true if successful.
virtual Teuchos::RCP< const Thyra::VectorBase< Scalar > > getXDotDot() const
Get current the second time derivative of the solution, xdotdot.
Status
Status for the Integrator, the Stepper and the SolutionState.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const override
Time integrator suitable for pseudotransient forward sensitivity analysis.
Teuchos::RCP< Tempus::IntegratorPseudoTransientForwardSensitivity< Scalar > > createIntegratorPseudoTransientForwardSensitivity(Teuchos::RCP< Teuchos::ParameterList > pList, const Teuchos::RCP< Thyra::ModelEvaluator< Scalar > > &model)
Nonmember constructor.
virtual Teuchos::RCP< const TimeStepControl< Scalar > > getTimeStepControl() const override
Get the TimeStepControl.
virtual Teuchos::RCP< SolutionHistory< Scalar > > getNonConstSolutionHistory() override
Get the SolutionHistory.
virtual Teuchos::RCP< const Thyra::MultiVectorBase< Scalar > > getDXDotDotDp() const