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