Tempus  Version of the Day
Time Integration
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  : gammaDefault_(Scalar(0.5)), gamma_(Scalar(0.5))
63 {
64  this->setStepperType( "Newmark Explicit a-Form");
65  this->setUseFSAL( this->getUseFSALDefault());
68 
69  //this->setObserver();
70 }
71 
72 
73 template<class Scalar>
75  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
76  const Teuchos::RCP<StepperObserver<Scalar> >& obs,
77  bool useFSAL,
78  std::string ICConsistency,
79  bool ICConsistencyCheck,
80  Scalar gamma)
81  : gammaDefault_(Scalar(0.5)), gamma_(Scalar(0.5))
82 {
83  this->setStepperType( "Newmark Explicit a-Form");
84  this->setUseFSAL( useFSAL);
85  this->setICConsistency( ICConsistency);
86  this->setICConsistencyCheck( ICConsistencyCheck);
87 
88  //this->setObserver(obs);
89 
90  setGamma(gamma);
91 
92  if (appModel != Teuchos::null) {
93 
94  this->setModel(appModel);
95  this->initialize();
96  }
97 }
98 
99 
100 template<class Scalar>
102  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
103 {
104  using Teuchos::RCP;
105 
106  int numStates = solutionHistory->getNumStates();
107 
108  TEUCHOS_TEST_FOR_EXCEPTION(numStates < 1, std::logic_error,
109  "Error - setInitialConditions() needs at least one SolutionState\n"
110  " to set the initial condition. Number of States = " << numStates);
111 
112  if (numStates > 1) {
113  RCP<Teuchos::FancyOStream> out = this->getOStream();
114  Teuchos::OSTab ostab(out,1,
115  "StepperNewmarkExplicitAForm::setInitialConditions()");
116  *out << "Warning -- SolutionHistory has more than one state!\n"
117  << "Setting the initial conditions on the currentState.\n"<<std::endl;
118  }
119 
120  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
121  RCP<Thyra::VectorBase<Scalar> > x = initialState->getX();
122  RCP<Thyra::VectorBase<Scalar> > xDot = initialState->getXDot();
123 
124  // If initialState has x and xDot set, treat them as the initial conditions.
125  // Otherwise use the x and xDot from getNominalValues() as the ICs.
126  TEUCHOS_TEST_FOR_EXCEPTION(
127  !((initialState->getX() != Teuchos::null &&
128  initialState->getXDot() != Teuchos::null) ||
129  (this->inArgs_.get_x() != Teuchos::null &&
130  this->inArgs_.get_x_dot() != Teuchos::null)), std::logic_error,
131  "Error - We need to set the initial conditions for x and xDot from\n"
132  " either initialState or appModel_->getNominalValues::InArgs\n"
133  " (but not from a mixture of the two).\n");
134 
135  this->inArgs_ = this->appModel_->getNominalValues();
136  using Teuchos::rcp_const_cast;
137  // Use the x and xDot from getNominalValues() as the ICs.
138  if ( initialState->getX() == Teuchos::null ||
139  initialState->getXDot() == Teuchos::null ) {
140  TEUCHOS_TEST_FOR_EXCEPTION( (this->inArgs_.get_x() == Teuchos::null) ||
141  (this->inArgs_.get_x_dot() == Teuchos::null), std::logic_error,
142  "Error - setInitialConditions() needs the ICs from the SolutionHistory\n"
143  " or getNominalValues()!\n");
144  x =rcp_const_cast<Thyra::VectorBase<Scalar> >(this->inArgs_.get_x());
145  initialState->setX(x);
146  xDot =rcp_const_cast<Thyra::VectorBase<Scalar> >(this->inArgs_.get_x_dot());
147  initialState->setXDot(xDot);
148  } else {
149  this->inArgs_.set_x(x);
150  this->inArgs_.set_x_dot(xDot);
151  }
152 
153  // Check if we need Stepper storage for xDotDot
154  if (initialState->getXDotDot() == Teuchos::null)
155  initialState->setXDotDot(initialState->getX()->clone_v());
156 
157  // Perform IC Consistency
158  std::string icConsistency = this->getICConsistency();
159  if (icConsistency == "None") {
160  if (initialState->getXDotDot() == Teuchos::null) {
161  RCP<Teuchos::FancyOStream> out = this->getOStream();
162  Teuchos::OSTab ostab(out,1,"StepperForwardEuler::setInitialConditions()");
163  *out << "Warning -- Requested IC consistency of 'None' but\n"
164  << " initialState does not have an xDotDot.\n"
165  << " Setting a 'Consistent' xDotDot!\n" << std::endl;
166  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
167  this->evaluateExplicitODE(initialState->getXDotDot(), x, xDot,
168  initialState->getTime(), p);
169 
170  initialState->setIsSynced(true);
171  }
172  }
173  else if (icConsistency == "Zero")
174  Thyra::assign(initialState->getXDotDot().ptr(), Scalar(0.0));
175  else if (icConsistency == "App") {
176  auto xDotDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
177  this->inArgs_.get_x_dot_dot());
178  TEUCHOS_TEST_FOR_EXCEPTION(xDotDot == Teuchos::null, std::logic_error,
179  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
180  " but 'App' returned a null pointer for xDotDot!\n");
181  Thyra::assign(initialState->getXDotDot().ptr(), *xDotDot);
182  }
183  else if (icConsistency == "Consistent") {
184  // Evaluate xDotDot = f(x,t).
185  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
186  this->evaluateExplicitODE(initialState->getXDotDot(), x, xDot,
187  initialState->getTime(), p);
188 
189  // At this point, x, xDot and xDotDot are sync'ed or consistent
190  // at the same time level for the initialState.
191  initialState->setIsSynced(true);
192  }
193  else {
194  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
195  "Error - setInitialConditions() invalid IC consistency, "
196  << icConsistency << ".\n");
197  }
198 
199  // Test for consistency.
200  if (this->getICConsistencyCheck()) {
201  auto xDotDot = initialState->getXDotDot();
202  auto f = initialState->getX()->clone_v();
203  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
204  this->evaluateExplicitODE(f, x, xDot, initialState->getTime(), p);
205  Thyra::Vp_StV(f.ptr(), Scalar(-1.0), *(xDotDot));
206  Scalar reldiff = Thyra::norm(*f);
207  Scalar normxDotDot = Thyra::norm(*xDotDot);
208  //The following logic is to prevent FPEs
209  Scalar eps = Scalar(100.0)*std::abs(Teuchos::ScalarTraits<Scalar>::eps());
210  if (normxDotDot > eps*reldiff) reldiff /= normxDotDot;
211 
212  if (reldiff > eps) {
213  RCP<Teuchos::FancyOStream> out = this->getOStream();
214  Teuchos::OSTab ostab(out,1,"StepperForwardEuler::setInitialConditions()");
215  *out << "Warning -- Failed consistency check but continuing!\n"
216  << " ||xDotDot-f(x,t)||/||xDotDot|| > eps" << std::endl
217  << " ||xDotDot-f(x,t)|| = " << Thyra::norm(*f)
218  << std::endl
219  << " ||xDotDot|| = " << Thyra::norm(*xDotDot)
220  << std::endl
221  << " ||xDotDot-f(x,t)||/||xDotDot|| = " << reldiff << std::endl
222  << " eps = " << eps << std::endl;
223  }
224  }
225 }
226 
227 
228 template<class Scalar>
230  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
231 {
232  this->checkInitialized();
233 
234  using Teuchos::RCP;
235 
236  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperNewmarkExplicitAForm::takeStep()");
237  {
238  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
239  std::logic_error,
240  "Error - StepperNewmarkExplicitAForm<Scalar>::takeStep(...)\n"
241  "Need at least two SolutionStates for NewmarkExplicitAForm.\n"
242  " Number of States = " << solutionHistory->getNumStates() << "\n"
243  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
244  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
245 
246  RCP<SolutionState<Scalar> > currentState=solutionHistory->getCurrentState();
247  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
248 
249  //Get values of d, v and a from previous step
250  RCP<const Thyra::VectorBase<Scalar> > d_old = currentState->getX();
251  RCP<const Thyra::VectorBase<Scalar> > v_old = currentState->getXDot();
252  RCP< Thyra::VectorBase<Scalar> > a_old = currentState->getXDotDot();
253 
254  //Get dt and time
255  const Scalar dt = workingState->getTimeStep();
256  const Scalar time_old = currentState->getTime();
257 
258  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(dt));
259  if ( !(this->getUseFSAL()) ) {
260  // Evaluate xDotDot = f(x, xDot, t).
261  this->evaluateExplicitODE(a_old, d_old, v_old, time_old, p);
262 
263  // For UseFSAL=false, x and xDot sync'ed or consistent
264  // at the same time level for the currentState.
265  currentState->setIsSynced(true);
266  }
267 
268  //New d, v and a to be computed here
269  RCP<Thyra::VectorBase<Scalar> > d_new = workingState->getX();
270  RCP<Thyra::VectorBase<Scalar> > v_new = workingState->getXDot();
271  RCP<Thyra::VectorBase<Scalar> > a_new = workingState->getXDotDot();
272 
273  //compute displacement and velocity predictors
274  predictDisplacement(*d_new, *d_old, *v_old, *a_old, dt);
275  predictVelocity(*v_new, *v_old, *a_old, dt);
276 
277  // Evaluate xDotDot = f(x, xDot, t).
278  this->evaluateExplicitODE(a_new, d_new, v_new, time_old, p);
279 
280  // Set xDot in workingState to velocity corrector
281  correctVelocity(*v_new, *v_new, *a_new, dt);
282 
283  if ( this->getUseFSAL() ) {
284  // Evaluate xDotDot = f(x, xDot, t).
285  const Scalar time_new = workingState->getTime();
286  this->evaluateExplicitODE(a_new, d_new, v_new, time_new, p);
287 
288  // For UseFSAL=true, x, xDot and xDotxDot are now sync'ed or consistent
289  // for the workingState.
290  workingState->setIsSynced(true);
291  } else {
292  assign(a_new.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
293  workingState->setIsSynced(false);
294  }
295 
296  workingState->setSolutionStatus(Status::PASSED);
297  workingState->setOrder(this->getOrder());
298  workingState->computeNorms(currentState);
299  }
300  return;
301 }
302 
303 
304 /** \brief Provide a StepperState to the SolutionState.
305  * This Stepper does not have any special state data,
306  * so just provide the base class StepperState with the
307  * Stepper description. This can be checked to ensure
308  * that the input StepperState can be used by this Stepper.
309  */
310 template<class Scalar>
311 Teuchos::RCP<Tempus::StepperState<Scalar> > StepperNewmarkExplicitAForm<Scalar>::
313 {
314  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
315  rcp(new StepperState<Scalar>(this->getStepperType()));
316  return stepperState;
317 }
318 
319 
320 template<class Scalar>
322  Teuchos::FancyOStream &out,
323  const Teuchos::EVerbosityLevel verbLevel) const
324 {
325  out << std::endl;
326  Stepper<Scalar>::describe(out, verbLevel);
327  StepperExplicit<Scalar>::describe(out, verbLevel);
328 
329  out << "--- StepperNewmarkExplicitAForm ---\n";
330  out << " gamma_ = " << gamma_ << std::endl;
331  out << "-----------------------------------" << std::endl;
332 }
333 
334 
335 template<class Scalar>
336 bool StepperNewmarkExplicitAForm<Scalar>::isValidSetup(Teuchos::FancyOStream & out) const
337 {
338  bool isValidSetup = true;
339 
340  if ( !Stepper<Scalar>::isValidSetup(out) ) isValidSetup = false;
341  if ( !StepperExplicit<Scalar>::isValidSetup(out) ) isValidSetup = false;
342 
343  return isValidSetup;
344 }
345 
346 
347 template<class Scalar>
348 Teuchos::RCP<const Teuchos::ParameterList>
350 {
351  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
352  getValidParametersBasic(pl, this->getStepperType());
353  pl->set<bool>("Use FSAL", this->getUseFSALDefault());
354  pl->set<std::string>("Initial Condition Consistency",
355  this->getICConsistencyDefault());
356  pl->sublist("Newmark Explicit Parameters", false, "");
357  pl->sublist("Newmark Explicit Parameters", false, "").set("Gamma",
358  0.5, "Newmark Explicit parameter");
359  return pl;
360 }
361 
362 
363 } // namespace Tempus
364 #endif // Tempus_StepperNewmarkExplicitAForm_impl_hpp
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
Thyra Base interface for implicit time steppers.
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
void correctVelocity(Thyra::VectorBase< Scalar > &v, const Thyra::VectorBase< Scalar > &vPred, const Thyra::VectorBase< Scalar > &a, const Scalar dt) const
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
void predictVelocity(Thyra::VectorBase< Scalar > &vPred, 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.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
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
StepperObserver class for Stepper class.
StepperState is a simple class to hold state information about the stepper.
Thyra Base interface for time steppers.
virtual bool getICConsistencyCheckDefault() const
void setICConsistencyCheck(bool c)
virtual void initialize()
Initialize after construction and changing input parameters.
void setStepperType(std::string s)
void setICConsistency(std::string s)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
void getValidParametersBasic(Teuchos::RCP< Teuchos::ParameterList > pl, std::string stepperType)
Provide basic parameters to Steppers.