Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Tempus_StepperNewmarkExplicitAForm_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_StepperNewmarkExplicitAForm_impl_hpp
10 #define Tempus_StepperNewmarkExplicitAForm_impl_hpp
11 
12 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
13 #include "Thyra_VectorStdOps.hpp"
14 
15 //#define DEBUG_OUTPUT
16 
17 namespace Tempus {
18 
19 
20 template<class Scalar>
22 predictVelocity(Thyra::VectorBase<Scalar>& vPred,
23  const Thyra::VectorBase<Scalar>& v,
24  const Thyra::VectorBase<Scalar>& a,
25  const Scalar dt) const
26 {
27  //vPred = v + dt*(1.0-gamma_)*a
28  Thyra::V_StVpStV(Teuchos::ptrFromRef(vPred), 1.0, v, dt*(1.0-gamma_), a);
29 }
30 
31 template<class Scalar>
33 predictDisplacement(Thyra::VectorBase<Scalar>& dPred,
34  const Thyra::VectorBase<Scalar>& d,
35  const Thyra::VectorBase<Scalar>& v,
36  const Thyra::VectorBase<Scalar>& a,
37  const Scalar dt) const
38 {
39  Teuchos::RCP<const Thyra::VectorBase<Scalar> > tmp =
40  Thyra::createMember<Scalar>(dPred.space());
41  //dPred = dt*v + dt*dt/2.0*a
42  Scalar aConst = dt*dt/2.0;
43  Thyra::V_StVpStV(Teuchos::ptrFromRef(dPred), dt, v, aConst, a);
44  //dPred += d;
45  Thyra::Vp_V(Teuchos::ptrFromRef(dPred), d, 1.0);
46 }
47 
48 template<class Scalar>
50 correctVelocity(Thyra::VectorBase<Scalar>& v,
51  const Thyra::VectorBase<Scalar>& vPred,
52  const Thyra::VectorBase<Scalar>& a,
53  const Scalar dt) const
54 {
55  //v = vPred + dt*gamma_*a
56  Thyra::V_StVpStV(Teuchos::ptrFromRef(v), 1.0, vPred, dt*gamma_, a);
57 }
58 
59 
60 template<class Scalar>
62 {
63  this->setParameterList(Teuchos::null);
64  this->modelWarning();
65 }
66 
67 
68 template<class Scalar>
70  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
71  Teuchos::RCP<Teuchos::ParameterList> pList)
72 {
73  this->setParameterList(pList);
74 
75  if (appModel == Teuchos::null) {
76  this->modelWarning();
77  }
78  else {
79  this->setModel(appModel);
80  this->initialize();
81  }
82 }
83 
84 
85 template<class Scalar>
87 {
88  TEUCHOS_TEST_FOR_EXCEPTION(
89  this->appModel_ == Teuchos::null, std::logic_error,
90  "Error - Need to set the model, setModel(), before calling "
91  "StepperNewmarkExplicitAForm::initialize()\n");
92 
93  this->setParameterList(this->stepperPL_);
94 }
95 
96 template<class Scalar>
98  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
99 {
100  using Teuchos::RCP;
101 
102  int numStates = solutionHistory->getNumStates();
103 
104  TEUCHOS_TEST_FOR_EXCEPTION(numStates < 1, std::logic_error,
105  "Error - setInitialConditions() needs at least one SolutionState\n"
106  " to set the initial condition. Number of States = " << numStates);
107 
108  if (numStates > 1) {
109  RCP<Teuchos::FancyOStream> out = this->getOStream();
110  Teuchos::OSTab ostab(out,1,
111  "StepperNewmarkExplicitAForm::setInitialConditions()");
112  *out << "Warning -- SolutionHistory has more than one state!\n"
113  << "Setting the initial conditions on the currentState.\n"<<std::endl;
114  }
115 
116  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
117  RCP<Thyra::VectorBase<Scalar> > x = initialState->getX();
118  RCP<Thyra::VectorBase<Scalar> > xDot = initialState->getXDot();
119 
120  // If initialState has x and xDot set, treat them as the initial conditions.
121  // Otherwise use the x and xDot from getNominalValues() as the ICs.
122  TEUCHOS_TEST_FOR_EXCEPTION(
123  !((initialState->getX() != Teuchos::null &&
124  initialState->getXDot() != Teuchos::null) ||
125  (this->inArgs_.get_x() != Teuchos::null &&
126  this->inArgs_.get_x_dot() != Teuchos::null)), std::logic_error,
127  "Error - We need to set the initial conditions for x and xDot from\n"
128  " either initialState or appModel_->getNominalValues::InArgs\n"
129  " (but not from a mixture of the two).\n");
130 
131  this->inArgs_ = this->appModel_->getNominalValues();
132  using Teuchos::rcp_const_cast;
133  // Use the x and xDot from getNominalValues() as the ICs.
134  if ( initialState->getX() == Teuchos::null ||
135  initialState->getXDot() == Teuchos::null ) {
136  TEUCHOS_TEST_FOR_EXCEPTION( (this->inArgs_.get_x() == Teuchos::null) ||
137  (this->inArgs_.get_x_dot() == Teuchos::null), std::logic_error,
138  "Error - setInitialConditions() needs the ICs from the SolutionHistory\n"
139  " or getNominalValues()!\n");
140  x =rcp_const_cast<Thyra::VectorBase<Scalar> >(this->inArgs_.get_x());
141  initialState->setX(x);
142  xDot =rcp_const_cast<Thyra::VectorBase<Scalar> >(this->inArgs_.get_x_dot());
143  initialState->setXDot(xDot);
144  } else {
145  this->inArgs_.set_x(x);
146  this->inArgs_.set_x_dot(xDot);
147  }
148 
149  // Check if we need Stepper storage for xDotDot
150  if (initialState->getXDotDot() == Teuchos::null)
151  initialState->setXDotDot(initialState->getX()->clone_v());
152 
153  // Perform IC Consistency
154  std::string icConsistency = this->getICConsistency();
155  if (icConsistency == "None") {
156  if (initialState->getXDotDot() == Teuchos::null) {
157  RCP<Teuchos::FancyOStream> out = this->getOStream();
158  Teuchos::OSTab ostab(out,1,"StepperForwardEuler::setInitialConditions()");
159  *out << "Warning -- Requested IC consistency of 'None' but\n"
160  << " initialState does not have an xDotDot.\n"
161  << " Setting a 'Consistent' xDotDot!\n" << std::endl;
162  this->evaluateExplicitODE(initialState->getXDotDot(), x, xDot,
163  initialState->getTime());
164 
165  initialState->setIsSynced(true);
166  }
167  }
168  else if (icConsistency == "Zero")
169  Thyra::assign(initialState->getXDotDot().ptr(), Scalar(0.0));
170  else if (icConsistency == "App") {
171  auto xDotDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
172  this->inArgs_.get_x_dot_dot());
173  TEUCHOS_TEST_FOR_EXCEPTION(xDotDot == Teuchos::null, std::logic_error,
174  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
175  " but 'App' returned a null pointer for xDotDot!\n");
176  Thyra::assign(initialState->getXDotDot().ptr(), *xDotDot);
177  }
178  else if (icConsistency == "Consistent") {
179  // Evaluate xDotDot = f(x,t).
180  this->evaluateExplicitODE(initialState->getXDotDot(), x, xDot,
181  initialState->getTime());
182 
183  // At this point, x, xDot and xDotDot are sync'ed or consistent
184  // at the same time level for the initialState.
185  initialState->setIsSynced(true);
186  }
187  else {
188  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
189  "Error - setInitialConditions() invalid IC consistency, "
190  << icConsistency << ".\n");
191  }
192 
193  // Test for consistency.
194  if (this->getICConsistencyCheck()) {
195  auto xDotDot = initialState->getXDotDot();
196  auto f = initialState->getX()->clone_v();
197  this->evaluateExplicitODE(f, x, xDot, initialState->getTime());
198  Thyra::Vp_StV(f.ptr(), Scalar(-1.0), *(xDotDot));
199  Scalar reldiff = Thyra::norm(*f);
200  Scalar normxDotDot = Thyra::norm(*xDotDot);
201  //The following logic is to prevent FPEs
202  Scalar eps = Scalar(100.0)*std::abs(Teuchos::ScalarTraits<Scalar>::eps());
203  if (normxDotDot > eps*reldiff) reldiff /= normxDotDot;
204 
205  if (reldiff > eps) {
206  RCP<Teuchos::FancyOStream> out = this->getOStream();
207  Teuchos::OSTab ostab(out,1,"StepperForwardEuler::setInitialConditions()");
208  *out << "Warning -- Failed consistency check but continuing!\n"
209  << " ||xDotDot-f(x,t)||/||xDotDot|| > eps" << std::endl
210  << " ||xDotDot-f(x,t)|| = " << Thyra::norm(*f)
211  << std::endl
212  << " ||xDotDot|| = " << Thyra::norm(*xDotDot)
213  << std::endl
214  << " ||xDotDot-f(x,t)||/||xDotDot|| = " << reldiff << std::endl
215  << " eps = " << eps << std::endl;
216  }
217  }
218 }
219 
220 
221 template<class Scalar>
223  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
224 {
225  using Teuchos::RCP;
226 
227  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperNewmarkExplicitAForm::takeStep()");
228  {
229  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
230  std::logic_error,
231  "Error - StepperNewmarkExplicitAForm<Scalar>::takeStep(...)\n"
232  "Need at least two SolutionStates for NewmarkExplicitAForm.\n"
233  " Number of States = " << solutionHistory->getNumStates() << "\n"
234  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
235  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
236 
237  RCP<SolutionState<Scalar> > currentState=solutionHistory->getCurrentState();
238  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
239 
240  //Get values of d, v and a from previous step
241  RCP<const Thyra::VectorBase<Scalar> > d_old = currentState->getX();
242  RCP<const Thyra::VectorBase<Scalar> > v_old = currentState->getXDot();
243  RCP< Thyra::VectorBase<Scalar> > a_old = currentState->getXDotDot();
244 
245  //Get dt and time
246  const Scalar dt = workingState->getTimeStep();
247  const Scalar time_old = currentState->getTime();
248 
249  if ( !(this->getUseFSAL()) ) {
250  // Evaluate xDotDot = f(x, xDot, t).
251  this->evaluateExplicitODE(a_old, d_old, v_old, time_old);
252 
253  // For UseFSAL=false, x and xDot sync'ed or consistent
254  // at the same time level for the currentState.
255  currentState->setIsSynced(true);
256  }
257 
258  //New d, v and a to be computed here
259  RCP<Thyra::VectorBase<Scalar> > d_new = workingState->getX();
260  RCP<Thyra::VectorBase<Scalar> > v_new = workingState->getXDot();
261  RCP<Thyra::VectorBase<Scalar> > a_new = workingState->getXDotDot();
262 
263  //compute displacement and velocity predictors
264  predictDisplacement(*d_new, *d_old, *v_old, *a_old, dt);
265  predictVelocity(*v_new, *v_old, *a_old, dt);
266 
267  // Evaluate xDotDot = f(x, xDot, t).
268  this->evaluateExplicitODE(a_new, d_new, v_new, time_old);
269 
270  // Set xDot in workingState to velocity corrector
271  correctVelocity(*v_new, *v_new, *a_new, dt);
272 
273  if ( this->getUseFSAL() ) {
274  // Evaluate xDotDot = f(x, xDot, t).
275  const Scalar time_new = workingState->getTime();
276  this->evaluateExplicitODE(a_new, d_new, v_new, time_new);
277 
278  // For UseFSAL=true, x, xDot and xDotxDot are now sync'ed or consistent
279  // for the workingState.
280  workingState->setIsSynced(true);
281  } else {
282  assign(a_new.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
283  workingState->setIsSynced(false);
284  }
285 
286  workingState->setSolutionStatus(Status::PASSED);
287  workingState->setOrder(this->getOrder());
288  }
289  return;
290 }
291 
292 
293 /** \brief Provide a StepperState to the SolutionState.
294  * This Stepper does not have any special state data,
295  * so just provide the base class StepperState with the
296  * Stepper description. This can be checked to ensure
297  * that the input StepperState can be used by this Stepper.
298  */
299 template<class Scalar>
300 Teuchos::RCP<Tempus::StepperState<Scalar> > StepperNewmarkExplicitAForm<Scalar>::
302 {
303  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
304  rcp(new StepperState<Scalar>(description()));
305  return stepperState;
306 }
307 
308 
309 template<class Scalar>
311 {
312  std::string name = "Newmark Explicit a-Form";
313  return(name);
314 }
315 
316 
317 template<class Scalar>
319  Teuchos::FancyOStream &out,
320  const Teuchos::EVerbosityLevel /* verbLevel */) const
321 {
322  out << description() << "::describe:" << std::endl
323  << "appModel_ = " << this->appModel_->description() << std::endl;
324 }
325 
326 
327 template <class Scalar>
329  const Teuchos::RCP<Teuchos::ParameterList> & pList)
330 {
331  if (pList == Teuchos::null) {
332  // Create default parameters if null, otherwise keep current parameters.
333  if (this->stepperPL_ == Teuchos::null)
334  this->stepperPL_ = this->getDefaultParameters();
335  } else {
336  this->stepperPL_ = pList;
337  }
338  this->stepperPL_->validateParametersAndSetDefaults(*this->getValidParameters());
339 
340  std::string stepperType =
341  this->stepperPL_->template get<std::string>("Stepper Type");
342  TEUCHOS_TEST_FOR_EXCEPTION( stepperType != "Newmark Explicit a-Form",
343  std::logic_error,
344  "Error - Stepper Type is not 'Newmark Explicit a-Form'!\n"
345  << " Stepper Type = "
346  << this->stepperPL_->template get<std::string>("Stepper Type") << "\n");
347 
348  gamma_ = this->stepperPL_->sublist("Newmark Explicit Parameters")
349  .template get<double>("Gamma");
350  TEUCHOS_TEST_FOR_EXCEPTION( (gamma_ > 1.0) || (gamma_ < 0.0),
351  std::logic_error,
352  "Error in 'Newmark Explicit a-Form' stepper: invalid value of Gamma = "
353  << gamma_ << ". Please select 0 <= Gamma <= 1. \n");
354 
355 }
356 
357 
358 template<class Scalar>
359 Teuchos::RCP<const Teuchos::ParameterList>
361 {
362  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
363  pl->setName("Default Stepper - " + this->description());
364  pl->set<std::string>("Stepper Type", "Newmark Explicit a-Form",
365  "'Stepper Type' must be 'Newmark Explicit a-Form'.");
366  this->getValidParametersBasic(pl);
367  pl->set<bool>("Use FSAL", true);
368  pl->set<std::string>("Initial Condition Consistency", "Consistent");
369  pl->sublist("Newmark Explicit Parameters", false, "");
370  pl->sublist("Newmark Explicit Parameters", false, "").set("Gamma",
371  0.5, "Newmark Explicit parameter");
372 
373  return pl;
374 }
375 
376 
377 template<class Scalar>
378 Teuchos::RCP<Teuchos::ParameterList>
380 {
381  using Teuchos::RCP;
382  using Teuchos::ParameterList;
383  using Teuchos::rcp_const_cast;
384 
385  RCP<ParameterList> pl =
386  rcp_const_cast<ParameterList>(this->getValidParameters());
387 
388  return pl;
389 }
390 
391 
392 template <class Scalar>
393 Teuchos::RCP<Teuchos::ParameterList>
395 {
396  return(this->stepperPL_);
397 }
398 
399 
400 template <class Scalar>
401 Teuchos::RCP<Teuchos::ParameterList>
403 {
404  Teuchos::RCP<Teuchos::ParameterList> temp_plist = this->stepperPL_;
405  this->stepperPL_ = Teuchos::null;
406  return(temp_plist);
407 }
408 
409 
410 } // namespace Tempus
411 #endif // Tempus_StepperNewmarkExplicitAForm_impl_hpp
void predictDisplacement(Thyra::VectorBase< Scalar > &dPred, const Thyra::VectorBase< Scalar > &d, const Thyra::VectorBase< Scalar > &v, const Thyra::VectorBase< Scalar > &a, const Scalar dt) const
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &pl)
StepperState is a simple class to hold state information about the stepper.
virtual void initialize()
Initialize during construction and after changing input parameters.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList()
Teuchos::RCP< SolutionHistory< Scalar > > solutionHistory(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
Nonmember constructor.
Teuchos::RCP< Teuchos::ParameterList > unsetParameterList()
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
void predictVelocity(Thyra::VectorBase< Scalar > &vPred, const Thyra::VectorBase< Scalar > &v, const Thyra::VectorBase< Scalar > &a, const Scalar dt) const
Teuchos::RCP< Teuchos::ParameterList > getDefaultParameters() const
void correctVelocity(Thyra::VectorBase< Scalar > &v, const Thyra::VectorBase< Scalar > &vPred, const Thyra::VectorBase< Scalar > &a, const Scalar dt) const
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const