Tempus  Version of the Day
Time Integration
Tempus_StepperStaggeredForwardSensitivity_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_StepperStaggeredForwardSensitivity_impl_hpp
10 #define Tempus_StepperStaggeredForwardSensitivity_impl_hpp
11 
12 #include "Thyra_VectorStdOps.hpp"
13 #include "Thyra_MultiVectorStdOps.hpp"
14 #include "Thyra_DefaultMultiVectorProductVectorSpace.hpp"
15 #include "Thyra_DefaultMultiVectorProductVector.hpp"
16 
17 #include "Tempus_StepperFactory.hpp"
20 
21 
22 namespace Tempus {
23 
24 
25 template<class Scalar>
28 {
29  this->setStepperName( "StaggeredForwardSensitivity");
30  this->setStepperType( "StaggeredForwardSensitivity");
31  this->setParams(Teuchos::null, Teuchos::null);
32 }
33 
34 
35 template<class Scalar>
38  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
39  const Teuchos::RCP<Teuchos::ParameterList>& pList,
40  const Teuchos::RCP<Teuchos::ParameterList>& sens_pList)
41 {
42  // Set all the input parameters and call initialize
43  this->setStepperName( "StaggeredForwardSensitivity");
44  this->setStepperType( "StaggeredForwardSensitivity");
45  this->setParams(pList, sens_pList);
46  this->setModel(appModel);
47  this->initialize();
48 }
49 
50 
51 template<class Scalar>
54  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
55 {
56  using Teuchos::RCP;
57  using Teuchos::rcp;
58  using Teuchos::ParameterList;
59 
60  // Create forward sensitivity model evaluator wrapper
61  Teuchos::RCP<Teuchos::ParameterList> spl = Teuchos::parameterList();
62  *spl = *sensPL_;
63  spl->remove("Reuse State Linear Solver");
64  spl->remove("Force W Update");
65  fsa_model_ = wrapStaggeredFSAModelEvaluator(appModel, spl);
66 
67  // Create combined FSA ME which serves as "the" ME for this stepper,
68  // so that getModel() has a ME consistent the FSA problem (including both
69  // state and sensitivity components), e.g., the integrator may call
70  // getModel()->getNominalValues(), which needs to be consistent.
71  combined_fsa_model_ = wrapCombinedFSAModelEvaluator(appModel, spl);
72 
73  // Create state and sensitivity steppers
74  RCP<StepperFactory<Scalar> > sf =Teuchos::rcp(new StepperFactory<Scalar>());
75  if (stateStepper_ == Teuchos::null)
76  stateStepper_ = sf->createStepper(stepperPL_, appModel);
77  else
78  stateStepper_->setModel(appModel);
79 
80  if (sensitivityStepper_ == Teuchos::null)
81  sensitivityStepper_ = sf->createStepper(stepperPL_, fsa_model_);
82  else
83  sensitivityStepper_->setModel(fsa_model_);
84 
85  this->isInitialized_ = false;
86 }
87 
88 
89 template<class Scalar>
90 Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >
92 getModel() const
93 {
94  return combined_fsa_model_;
95 }
96 
97 
98 template<class Scalar>
101  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > solver)
102 {
103  stateStepper_->setSolver(solver);
104  sensitivityStepper_->setSolver(solver);
105 
106  this->isInitialized_ = false;
107 }
108 
109 
110 template<class Scalar>
113  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
114 {
115  this->checkInitialized();
116 
117  using Teuchos::RCP;
118  using Teuchos::rcp;
119  using Teuchos::rcp_dynamic_cast;
120  using Thyra::VectorBase;
122  using Thyra::assign;
123  using Thyra::createMember;
124  using Thyra::multiVectorProductVector;
125  using Thyra::multiVectorProductVectorSpace;
126  typedef Thyra::DefaultMultiVectorProductVector<Scalar> DMVPV;
127  typedef Thyra::DefaultMultiVectorProductVectorSpace<Scalar> DMVPVS;
128 
129  // Initialize state, sensitivity solution histories if necessary.
130  // We only need to split the solution history into state and sensitivity
131  // components for the first step, otherwise the state and sensitivity
132  // histories are updated from the previous step.
133  if (stateSolutionHistory_ == Teuchos::null) {
134  RCP<Teuchos::ParameterList> shPL =
135  solutionHistory->getNonconstParameterList();
136 
137  // Get product X, XDot, XDotDot
138  RCP<SolutionState<Scalar> > state = solutionHistory->getCurrentState();
139  RCP<DMVPV> X, XDot, XDotDot;
140  X = rcp_dynamic_cast<DMVPV>(state->getX(),true);
141 
142  XDot = rcp_dynamic_cast<DMVPV>(state->getXDot(),true);
143  if (state->getXDotDot() != Teuchos::null)
144  XDotDot = rcp_dynamic_cast<DMVPV>(state->getXDotDot(),true);
145 
146  // Pull out state components (has to be non-const because of SolutionState
147  // constructor)
148  RCP<VectorBase<Scalar> > x, xdot, xdotdot;
149  x = X->getNonconstMultiVector()->col(0);
150  xdot = XDot->getNonconstMultiVector()->col(0);
151  if (XDotDot != Teuchos::null)
152  xdotdot = XDotDot->getNonconstMultiVector()->col(0);
153 
154  // Create state solution history
155  RCP<SolutionState<Scalar> > state_state = state->clone();
156  state_state->setX(x);
157  state_state->setXDot(xdot);
158  state_state->setXDotDot(xdotdot);
159  stateSolutionHistory_ = createSolutionHistoryPL<Scalar>(shPL);
160  stateSolutionHistory_->addState(state_state);
161 
162  const int num_param = X->getMultiVector()->domain()->dim()-1;
163  TEUCHOS_ASSERT(num_param > 0);
164  const Teuchos::Range1D rng(1,num_param);
165 
166  // Pull out sensitivity components
167  RCP<MultiVectorBase<Scalar> > dxdp, dxdotdp, dxdotdotdp;
168  dxdp = X->getNonconstMultiVector()->subView(rng);
169  dxdotdp = XDot->getNonconstMultiVector()->subView(rng);
170  if (XDotDot != Teuchos::null)
171  dxdotdotdp = XDotDot->getNonconstMultiVector()->subView(rng);
172 
173  // Create sensitivity product vectors
174  RCP<VectorBase<Scalar> > dxdp_vec, dxdotdp_vec, dxdotdotdp_vec;
175  RCP<const DMVPVS> prod_space =
176  multiVectorProductVectorSpace(X->getMultiVector()->range(), num_param);
177  dxdp_vec = multiVectorProductVector(prod_space, dxdp);
178  dxdotdp_vec = multiVectorProductVector(prod_space, dxdotdp);
179  if (XDotDot != Teuchos::null)
180  dxdotdotdp_vec = multiVectorProductVector(prod_space, dxdotdotdp);
181 
182  // Create sensitivity solution history
183  RCP<SolutionState<Scalar> > sens_state = state->clone();
184  sens_state->setX(dxdp_vec);
185  sens_state->setXDot(dxdotdp_vec);
186  sens_state->setXDotDot(dxdotdotdp_vec);
187  sensSolutionHistory_ = createSolutionHistoryPL<Scalar>(shPL);
188  sensSolutionHistory_->addState(sens_state);
189  }
190 
191  // Get our working state
192  RCP<SolutionState<Scalar> > prod_state = solutionHistory->getWorkingState();
193  RCP<DMVPV> X, XDot, XDotDot;
194  X = rcp_dynamic_cast<DMVPV>(prod_state->getX(),true);
195  XDot = rcp_dynamic_cast<DMVPV>(prod_state->getXDot(),true);
196  if (prod_state->getXDotDot() != Teuchos::null)
197  XDotDot = rcp_dynamic_cast<DMVPV>(prod_state->getXDotDot(),true);
198 
199  // Take step for state equations
200  stateSolutionHistory_->initWorkingState();
201  RCP<SolutionState<Scalar> > state = stateSolutionHistory_->getWorkingState();
202  state->getMetaData()->copy(prod_state->getMetaData());
203  stateStepper_->takeStep(stateSolutionHistory_);
204 
205  // Set state components of product state
206  assign(X->getNonconstMultiVector()->col(0).ptr(), *(state->getX()));
207  assign(XDot->getNonconstMultiVector()->col(0).ptr(), *(state->getXDot()));
208  if (XDotDot != Teuchos::null)
209  assign(XDotDot->getNonconstMultiVector()->col(0).ptr(),
210  *(state->getXDotDot()));
211  prod_state->setOrder(state->getOrder());
212 
213  // If step passed promote the state, otherwise fail and stop
214  if (state->getSolutionStatus() == Status::FAILED) {
215  prod_state->setSolutionStatus(Status::FAILED);
216  return;
217  }
218  stateSolutionHistory_->promoteWorkingState();
219 
220  // Get forward state in sensitivity model evaluator
221  fsa_model_->setForwardSolutionHistory(stateSolutionHistory_);
222  if (reuse_solver_ && stateStepper_->getSolver() != Teuchos::null)
223  fsa_model_->setSolver(stateStepper_->getSolver(), force_W_update_);
224 
225  // Take step in sensitivity equations
226  sensSolutionHistory_->initWorkingState();
227  RCP<SolutionState<Scalar> > sens_state =
228  sensSolutionHistory_->getWorkingState();
229  sens_state->getMetaData()->copy(prod_state->getMetaData());
230  sensitivityStepper_->takeStep(sensSolutionHistory_);
231 
232  // Set sensitivity components of product state
233  RCP<const MultiVectorBase<Scalar> > dxdp =
234  rcp_dynamic_cast<const DMVPV>(sens_state->getX(),true)->getMultiVector();
235  const int num_param = dxdp->domain()->dim();
236  const Teuchos::Range1D rng(1,num_param);
237  assign(X->getNonconstMultiVector()->subView(rng).ptr(), *dxdp);
238  RCP<const MultiVectorBase<Scalar> > dxdotdp =
239  rcp_dynamic_cast<const DMVPV>(sens_state->getXDot(),true)->getMultiVector();
240  assign(XDot->getNonconstMultiVector()->subView(rng).ptr(), *dxdotdp);
241  if (sens_state->getXDotDot() != Teuchos::null) {
242  RCP<const MultiVectorBase<Scalar> > dxdotdotdp =
243  rcp_dynamic_cast<const DMVPV>(sens_state->getXDotDot(),true)->getMultiVector();
244  assign(XDotDot->getNonconstMultiVector()->subView(rng).ptr(), *dxdotdotdp);
245  }
246  prod_state->setOrder(std::min(state->getOrder(), sens_state->getOrder()));
247 
248  // If step passed promote the state, otherwise fail and stop
249  if (sens_state->getSolutionStatus() == Status::FAILED) {
250  prod_state->setSolutionStatus(Status::FAILED);
251  }
252  else {
253  sensSolutionHistory_->promoteWorkingState();
254  prod_state->setSolutionStatus(Status::PASSED);
255  }
256 }
257 
258 
259 template<class Scalar>
260 Teuchos::RCP<Tempus::StepperState<Scalar> >
263 {
264  // ETP: Note, maybe this should be a special stepper state that combines
265  // states from both state and sensitivity steppers?
266  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
267  rcp(new StepperState<Scalar>(description()));
268  return stepperState;
269 }
270 
271 
272 template<class Scalar>
275  Teuchos::FancyOStream &out,
276  const Teuchos::EVerbosityLevel verbLevel) const
277 {
278  out.setOutputToRootOnly(0);
279  out << std::endl;
280  Stepper<Scalar>::describe(out, verbLevel);
281 
282  out << "--- StepperStaggeredForwardSensitivity ---\n";
283  out << " stateStepper_ = " << stateStepper_ <<std::endl;
284  out << " sensitivityStepper_ = " << sensitivityStepper_ <<std::endl;
285  out << " combined_fsa_model_ = " << combined_fsa_model_ <<std::endl;
286  out << " fsa_model_ = " << fsa_model_ <<std::endl;
287  out << " stateSolutionHistory_ = " << stateSolutionHistory_ <<std::endl;
288  out << " sensSolutionHistory_ = " << sensSolutionHistory_ <<std::endl;
289  out << "------------------------------------------" << std::endl;
290 
291  out << description() << "::describe:" << std::endl;
292  stateStepper_->describe(out, verbLevel);
293  out << std::endl;
294  sensitivityStepper_->describe(out, verbLevel);
295 }
296 
297 
298 template<class Scalar>
299 bool StepperStaggeredForwardSensitivity<Scalar>::isValidSetup(Teuchos::FancyOStream & out) const
300 {
301  out.setOutputToRootOnly(0);
302  bool isValidSetup = true;
303 
304  if ( !Stepper<Scalar>::isValidSetup(out) ) isValidSetup = false;
305 
306  if (stateStepper_ == Teuchos::null) {
307  isValidSetup = false;
308  out << "The state stepper is not set!\n";
309  }
310 
311  if (sensitivityStepper_ == Teuchos::null) {
312  isValidSetup = false;
313  out << "The sensitivity stepper is not set!\n";
314  }
315 
316  if (combined_fsa_model_ == Teuchos::null) {
317  isValidSetup = false;
318  out << "The combined FSA model is not set!\n";
319  }
320 
321  if (fsa_model_ == Teuchos::null) {
322  isValidSetup = false;
323  out << "The FSA model is not set!\n";
324  }
325 
326  return isValidSetup;
327 }
328 
329 
330 template <class Scalar>
333  Teuchos::RCP<Teuchos::ParameterList> const& pList)
334 {
335  if (pList == Teuchos::null) {
336  // Create default parameters if null, otherwise keep current parameters.
337  if (this->stepperPL_ == Teuchos::null) this->stepperPL_ =
338  Teuchos::rcp_const_cast<Teuchos::ParameterList>(this->getValidParameters());
339  } else {
340  this->stepperPL_ = pList;
341  }
342  // Can not validate because of optional Parameters (e.g., Solver Name).
343  //stepperPL_->validateParametersAndSetDefaults(*this->getValidParameters());
344 }
345 
346 
347 template<class Scalar>
348 Teuchos::RCP<const Teuchos::ParameterList>
351 {
352  return stateStepper_->getValidParameters();
353 }
354 
355 
356 template <class Scalar>
357 Teuchos::RCP<Teuchos::ParameterList>
360 {
361  return stepperPL_;
362 }
363 
364 
365 template <class Scalar>
366 Teuchos::RCP<Teuchos::ParameterList>
369 {
370  Teuchos::RCP<Teuchos::ParameterList> temp_plist = stepperPL_;
371  stepperPL_ = Teuchos::null;
372  return temp_plist;
373 }
374 
375 
376 template <class Scalar>
379  Teuchos::RCP<Teuchos::ParameterList> const& pList,
380  Teuchos::RCP<Teuchos::ParameterList> const& spList)
381 {
382  if (pList == Teuchos::null)
383  stepperPL_ = Teuchos::rcp_const_cast<Teuchos::ParameterList>(this->getValidParameters());
384  else
385  stepperPL_ = pList;
386 
387  if (spList == Teuchos::null)
388  sensPL_ = Teuchos::parameterList();
389  else
390  sensPL_ = spList;
391 
392  reuse_solver_ = sensPL_->get("Reuse State Linear Solver", false);
393  force_W_update_ = sensPL_->get("Force W Update", true);
394 
395  // Can not validate because of optional Parameters (e.g., Solver Name).
396  //stepperPL_->validateParametersAndSetDefaults(*this->getValidParameters());
397 }
398 
399 
400 template <class Scalar>
401 Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> >
403 get_x_space() const
404 {
405  using Teuchos::RCP;
406  using Teuchos::rcp_dynamic_cast;
407  typedef Thyra::DefaultMultiVectorProductVectorSpace<Scalar> DMVPVS;
408 
409  RCP<const Thyra::VectorSpaceBase<Scalar> > x_space =
410  stateStepper_->getModel()->get_x_space();
411  RCP<const DMVPVS> dxdp_space =
412  rcp_dynamic_cast<const DMVPVS>(sensitivityStepper_->getModel()->get_x_space(),true);
413  const int num_param = dxdp_space->numBlocks();
414  RCP<const Thyra::VectorSpaceBase<Scalar> > prod_space =
415  multiVectorProductVectorSpace(x_space, num_param+1);
416  return prod_space;
417 }
418 
419 } // namespace Tempus
420 
421 #endif // Tempus_StepperStaggeredForwardSensitivity_impl_hpp
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Teuchos::RCP< const Thyra::VectorSpaceBase< Scalar > > get_x_space() const
virtual Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > getModel() const
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
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< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.
Thyra Base interface for time steppers.
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
StepperState is a simple class to hold state information about the stepper.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
Teuchos::RCP< SensitivityModelEvaluatorBase< Scalar > > wrapCombinedFSAModelEvaluator(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model, const Teuchos::RCP< const Teuchos::ParameterList > &pList=Teuchos::null)
void setParams(const Teuchos::RCP< Teuchos::ParameterList > &pl, const Teuchos::RCP< Teuchos::ParameterList > &spl)
virtual void setSolver(Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > solver=Teuchos::null)
Set solver.
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &pl)