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  : 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
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 bool getICConsistencyCheckDefault() const
virtual void initialize()
Initialize after construction and changing input parameters.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
Thyra Base interface for time steppers.
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
StepperState is a simple class to hold state information about the stepper.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
void setICConsistencyCheck(bool c)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
StepperObserver class for Stepper class.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
void predictVelocity(Thyra::VectorBase< Scalar > &vPred, const Thyra::VectorBase< Scalar > &v, const Thyra::VectorBase< Scalar > &a, const Scalar dt) const
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
void correctVelocity(Thyra::VectorBase< Scalar > &v, const Thyra::VectorBase< Scalar > &vPred, const Thyra::VectorBase< Scalar > &a, const Scalar dt) const
Thyra Base interface for implicit time steppers.
void getValidParametersBasic(Teuchos::RCP< Teuchos::ParameterList > pl, std::string stepperType)
Provide basic parameters to Steppers.
void setStepperType(std::string s)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
void setICConsistency(std::string s)