Tempus  Version of the Day
Time Integration
Tempus_StepperNewmarkImplicitDForm_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_StepperNewmarkImplicitDForm_impl_hpp
10 #define Tempus_StepperNewmarkImplicitDForm_impl_hpp
11 
12 #include "NOX_Thyra.H"
14 #include "Tempus_config.hpp"
15 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
16 
17 //#define VERBOSE_DEBUG_OUTPUT
18 //#define DEBUG_OUTPUT
19 
20 namespace Tempus {
21 
22 // Forward Declaration for recursive includes (this Stepper <--> StepperFactory)
23 template <class Scalar>
24 class StepperFactory;
25 
26 template <class Scalar>
27 void
29  Thyra::VectorBase<Scalar>& vPred, const Thyra::VectorBase<Scalar>& v,
30  const Thyra::VectorBase<Scalar>& a, const Scalar dt) const {
31 #ifdef VERBOSE_DEBUG_OUTPUT
32  *out_ << "DEBUG: " << __PRETTY_FUNCTION__ << "\n";
33 #endif
34  // vPred = v + dt*(1.0-gamma_)*a
35  Thyra::V_StVpStV(Teuchos::ptrFromRef(vPred), 1.0, v, dt * (1.0 - gamma_), a);
36 }
37 
38 template <class Scalar>
39 void
41  Thyra::VectorBase<Scalar>& dPred, const Thyra::VectorBase<Scalar>& d,
42  const Thyra::VectorBase<Scalar>& v, const Thyra::VectorBase<Scalar>& a,
43  const Scalar dt) const {
44 #ifdef VERBOSE_DEBUG_OUTPUT
45  *out_ << "DEBUG: " << __PRETTY_FUNCTION__ << "\n";
46 #endif
47  Teuchos::RCP<const Thyra::VectorBase<Scalar>> tmp =
48  Thyra::createMember<Scalar>(dPred.space());
49  // dPred = dt*v + dt*dt/2.0*(1.0-2.0*beta_)*a
50  Scalar aConst = dt * dt / 2.0 * (1.0 - 2.0 * beta_);
51  Thyra::V_StVpStV(Teuchos::ptrFromRef(dPred), dt, v, aConst, a);
52  // dPred += d;
53  Thyra::Vp_V(Teuchos::ptrFromRef(dPred), d, 1.0);
54 }
55 
56 template <class Scalar>
57 void
59  Thyra::VectorBase<Scalar>& v, const Thyra::VectorBase<Scalar>& vPred,
60  const Thyra::VectorBase<Scalar>& a, const Scalar dt) const {
61 #ifdef VERBOSE_DEBUG_OUTPUT
62  *out_ << "DEBUG: " << __PRETTY_FUNCTION__ << "\n";
63 #endif
64  // v = vPred + dt*gamma_*a
65  Thyra::V_StVpStV(Teuchos::ptrFromRef(v), 1.0, vPred, dt * gamma_, a);
66 }
67 
68 template <class Scalar>
69 void
71  Thyra::VectorBase<Scalar>& d, const Thyra::VectorBase<Scalar>& dPred,
72  const Thyra::VectorBase<Scalar>& a, const Scalar dt) const {
73 #ifdef VERBOSE_DEBUG_OUTPUT
74  *out_ << "DEBUG: " << __PRETTY_FUNCTION__ << "\n";
75 #endif
76  // d = dPred + beta_*dt*dt*a
77  Thyra::V_StVpStV(Teuchos::ptrFromRef(d), 1.0, dPred, beta_ * dt * dt, a);
78 }
79 
80 template <class Scalar>
81 void
83  Thyra::VectorBase<Scalar>& a, const Thyra::VectorBase<Scalar>& dPred,
84  const Thyra::VectorBase<Scalar>& d, const Scalar dt) const {
85 #ifdef VERBOSE_DEBUG_OUTPUT
86  *out_ << "DEBUG: " << __PRETTY_FUNCTION__ << "\n";
87 #endif
88  // a = (d - dPred) / (beta_*dt*dt)
89  Scalar const c = 1.0 / beta_ / dt / dt;
90  Thyra::V_StVpStV(Teuchos::ptrFromRef(a), c, d, -c, dPred);
91 }
92 
93 template<class Scalar>
95 {
96  if (schemeName_ != "User Defined") {
97  *out_ << "\nWARNING: schemeName != 'User Defined' (=" <<schemeName_<< ").\n"
98  << " Not setting beta, and leaving as beta = " << beta_ << "!\n";
99  return;
100  }
101 
102  beta_ = beta;
103 
104  if (beta_ == 0.0) {
105  *out_ << "\nWARNING: Running (implicit implementation of) Newmark "
106  << "Implicit a-Form Stepper with Beta = 0.0, which \n"
107  << "specifies an explicit scheme. Mass lumping is not possible, "
108  << "so this will be slow! To run explicit \n"
109  << "implementation of Newmark Implicit a-Form Stepper, please "
110  << "re-run with 'Stepper Type' = 'Newmark Explicit a-Form'.\n"
111  << "This stepper allows for mass lumping when called through "
112  << "Piro::TempusSolver.\n";
113  }
114 
115  TEUCHOS_TEST_FOR_EXCEPTION( (beta_ > 1.0) || (beta_ < 0.0),
116  std::logic_error,
117  "\nError in 'Newmark Implicit a-Form' stepper: invalid value of Beta = "
118  << beta_ << ". Please select Beta >= 0 and <= 1. \n");
119 
120  this->isInitialized_ = false;
121 }
122 
123 
124 template<class Scalar>
126 {
127  if (schemeName_ != "User Defined") {
128  *out_ << "\nWARNING: schemeName != 'User Defined' (=" <<schemeName_<< ").\n"
129  << " Not setting gamma, and leaving as gamma = " << gamma_ << "!\n";
130  return;
131  }
132 
133  gamma_ = gamma;
134 
135  TEUCHOS_TEST_FOR_EXCEPTION( (gamma_ > 1.0) || (gamma_ < 0.0),
136  std::logic_error,
137  "\nError in 'Newmark Implicit a-Form' stepper: invalid value of Gamma ="
138  <<gamma_ << ". Please select Gamma >= 0 and <= 1. \n");
139 
140  this->isInitialized_ = false;
141 }
142 
143 
144 template<class Scalar>
146  std::string schemeName)
147 {
148  schemeName_ = schemeName;
149 
150  if (schemeName_ == "Average Acceleration") {
151  beta_= 0.25; gamma_ = 0.5;
152  }
153  else if (schemeName_ == "Linear Acceleration") {
154  beta_= 0.25; gamma_ = 1.0/6.0;
155  }
156  else if (schemeName_ == "Central Difference") {
157  beta_= 0.0; gamma_ = 0.5;
158  }
159  else if (schemeName_ == "User Defined") {
160  beta_= 0.25; gamma_ = 0.5; // Use defaults until setBeta and setGamma calls.
161  }
162  else {
163  TEUCHOS_TEST_FOR_EXCEPTION(true,
164  std::logic_error,
165  "\nError in Tempus::StepperNewmarkImplicitDForm! "
166  <<"Invalid Scheme Name = " << schemeName_ <<". \n"
167  <<"Valid Scheme Names are: 'Average Acceleration', "
168  <<"'Linear Acceleration', \n"
169  <<"'Central Difference' and 'User Defined'.\n");
170  }
171 
172  this->isInitialized_ = false;
173 }
174 
175 
176 template <class Scalar>
178  : out_(Teuchos::VerboseObjectBase::getDefaultOStream()) {
179 #ifdef VERBOSE_DEBUG_OUTPUT
180  *out_ << "DEBUG: " << __PRETTY_FUNCTION__ << "\n";
181 #endif
182 
183  this->setStepperType( "Newmark Implicit d-Form");
184  this->setUseFSAL( this->getUseFSALDefault());
187  this->setZeroInitialGuess( false);
188  this->setSchemeName( "Average Acceleration");
189 
190  this->setObserver();
191  this->setDefaultSolver();
192 }
193 
194 template <class Scalar>
196  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar>>& appModel,
197  const Teuchos::RCP<StepperObserver<Scalar> >& obs,
198  const Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> >& solver,
199  bool useFSAL,
200  std::string ICConsistency,
201  bool ICConsistencyCheck,
202  bool zeroInitialGuess,
203  std::string schemeName,
204  Scalar beta,
205  Scalar gamma)
206  : out_(Teuchos::VerboseObjectBase::getDefaultOStream())
207 {
208  this->setStepperType( "Newmark Implicit d-Form");
209  this->setUseFSAL( useFSAL);
210  this->setICConsistency( ICConsistency);
211  this->setICConsistencyCheck( ICConsistencyCheck);
212  this->setZeroInitialGuess( zeroInitialGuess);
213  this->setSchemeName( schemeName);
214  this->setBeta( beta);
215  this->setGamma( gamma);
216 
217  this->setObserver(obs);
218  this->setSolver(solver);
219 
220  if (appModel != Teuchos::null) {
221  this->setModel(appModel);
222  this->initialize();
223  }
224 }
225 
226 
227 template <class Scalar>
228 void
230  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar>>& appModel) {
231 #ifdef VERBOSE_DEBUG_OUTPUT
232  *out_ << "DEBUG: " << __PRETTY_FUNCTION__ << "\n";
233 #endif
234  validSecondOrderODE_DAE(appModel);
235  Teuchos::RCP<WrapperModelEvaluatorSecondOrder<Scalar> > wrapperModel =
237  appModel, "Newmark Implicit d-Form"));
238  this->wrapperModel_ = wrapperModel;
239 
240  this->isInitialized_ = false;
241 }
242 
243 
244 template <class Scalar>
245 void
247  const Teuchos::RCP<SolutionHistory<Scalar>>& solutionHistory) {
248 #ifdef VERBOSE_DEBUG_OUTPUT
249  *out_ << "DEBUG: " << __PRETTY_FUNCTION__ << "\n";
250 #endif
251  this->checkInitialized();
252 
253  using Teuchos::RCP;
254 
255  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperNewmarkImplicitDForm::takeStep()");
256  {
257  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
258  std::logic_error,
259  "Error - StepperNewmarkImplicitDForm<Scalar>::takeStep(...)\n"
260  "Need at least two SolutionStates for NewmarkImplicitDForm.\n"
261  " Number of States = " << solutionHistory->getNumStates() << "\n"
262  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
263  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
264 
265  RCP<SolutionState<Scalar>> workingState =solutionHistory->getWorkingState();
266  RCP<SolutionState<Scalar>> currentState =solutionHistory->getCurrentState();
267 
268  Teuchos::RCP<WrapperModelEvaluatorSecondOrder<Scalar> > wrapperModel =
269  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorSecondOrder<Scalar> >(
270  this->wrapperModel_);
271 
272  // Get values of d, v and a from previous step
273  RCP<const Thyra::VectorBase<Scalar>> d_old = currentState->getX();
274  RCP<Thyra::VectorBase<Scalar>> v_old = currentState->getXDot();
275  RCP<Thyra::VectorBase<Scalar>> a_old = currentState->getXDotDot();
276 
277  // Get new values of d, v and a from current workingState
278  //(to be updated here)
279  RCP<Thyra::VectorBase<Scalar>> d_new = workingState->getX();
280  RCP<Thyra::VectorBase<Scalar>> v_new = workingState->getXDot();
281  RCP<Thyra::VectorBase<Scalar>> a_new = workingState->getXDotDot();
282 
283  // Get time and dt
284  const Scalar time = currentState->getTime();
285  const Scalar dt = workingState->getTimeStep();
286  // Update time
287  Scalar t = time + dt;
288 
289 
290 #ifdef DEBUG_OUTPUT
291  Teuchos::Range1D range;
292 
293  *out_ << "\n*** d_old ***\n";
294  RTOpPack::ConstSubVectorView<Scalar> dov;
295  d_old->acquireDetachedView(range, &dov);
296  auto doa = dov.values();
297  for (auto i = 0; i < doa.size(); ++i) *out_ << doa[i] << " ";
298  *out_ << "\n*** d_old ***\n";
299 
300  *out_ << "\n*** v_old ***\n";
301  RTOpPack::ConstSubVectorView<Scalar> vov;
302  v_old->acquireDetachedView(range, &vov);
303  auto voa = vov.values();
304  for (auto i = 0; i < voa.size(); ++i) *out_ << voa[i] << " ";
305  *out_ << "\n*** v_old ***\n";
306 
307  *out_ << "\n*** a_old ***\n";
308  RTOpPack::ConstSubVectorView<Scalar> aov;
309  a_old->acquireDetachedView(range, &aov);
310  auto aoa = aov.values();
311  for (auto i = 0; i < aoa.size(); ++i) *out_ << aoa[i] << " ";
312  *out_ << "\n*** a_old ***\n";
313 #endif
314 
315  // allocate d and v predictors
316  RCP<Thyra::VectorBase<Scalar>> d_pred = Thyra::createMember(d_old->space());
317  RCP<Thyra::VectorBase<Scalar>> v_pred = Thyra::createMember(v_old->space());
318 
319  // compute displacement and velocity predictors
320  predictDisplacement(*d_pred, *d_old, *v_old, *a_old, dt);
321  predictVelocity(*v_pred, *v_old, *a_old, dt);
322 
323 #ifdef DEBUG_OUTPUT
324  *out_ << "\n*** d_pred ***\n";
325  RTOpPack::ConstSubVectorView<Scalar> dpv;
326  d_pred->acquireDetachedView(range, &dpv);
327  auto dpa = dpv.values();
328  for (auto i = 0; i < dpa.size(); ++i) *out_ << dpa[i] << " ";
329  *out_ << "\n*** d_pred ***\n";
330 
331  *out_ << "\n*** v_pred ***\n";
332  RTOpPack::ConstSubVectorView<Scalar> vpv;
333  v_pred->acquireDetachedView(range, &vpv);
334  auto vpa = vpv.values();
335  for (auto i = 0; i < vpa.size(); ++i) *out_ << vpa[i] << " ";
336  *out_ << "\n*** v_pred ***\n";
337 
338 #endif
339  // inject d_pred, v_pred, a and other relevant data into wrapperModel
340  wrapperModel->initializeNewmark(v_pred, d_pred, dt, t, beta_, gamma_);
341 
342  // create initial guess in NOX solver
343  RCP<Thyra::VectorBase<Scalar>> initial_guess = Thyra::createMember(d_pred->space());
344  if ((time == solutionHistory->minTime()) && (this->initialGuess_ != Teuchos::null)) {
345  //if first time step and initialGuess_ is provided, set initial_guess = initialGuess_
346  //Throw an exception if initial_guess is not compatible with solution
347  bool is_compatible = (initial_guess->space())->isCompatible(*this->initialGuess_->space());
348  TEUCHOS_TEST_FOR_EXCEPTION(
349  is_compatible != true, std::logic_error,
350  "Error in Tempus::NemwarkImplicitDForm takeStep(): user-provided initial guess'!\n"
351  << "for Newton is not compatible with solution vector!\n");
352  Thyra::copy(*this->initialGuess_, initial_guess.ptr());
353  }
354  else {
355  //Otherwise, set initial guess = diplacement predictor
356  Thyra::copy(*d_pred, initial_guess.ptr());
357  }
358 
359  //Set d_pred as initial guess for NOX solver, and solve nonlinear system.
360  const Thyra::SolveStatus<Scalar> sStatus =
361  this->solveImplicitODE(initial_guess);
362 
363  workingState->setSolutionStatus(sStatus); // Converged --> pass.
364 
365  //solveImplicitODE will return converged solution in initial_guess
366  //vector. Copy it here to d_new, to define the new displacement.
367  Thyra::copy(*initial_guess, d_new.ptr());
368 
369  //correct acceleration, velocity
370  correctAcceleration(*a_new, *d_pred, *d_new, dt);
371  correctVelocity(*v_new, *v_pred, *a_new, dt);
372 
373 #ifdef DEBUG_OUTPUT
374  *out_ << "\n*** d_new ***\n";
375  RTOpPack::ConstSubVectorView<Scalar> dnv;
376  d_new->acquireDetachedView(range, &dnv);
377  auto dna = dnv.values();
378  for (auto i = 0; i < dna.size(); ++i) *out_ << dna[i] << " ";
379  *out_ << "\n*** d_new ***\n";
380 
381  *out_ << "\n*** v_new ***\n";
382  RTOpPack::ConstSubVectorView<Scalar> vnv;
383  v_new->acquireDetachedView(range, &vnv);
384  auto vna = vnv.values();
385  for (auto i = 0; i < vna.size(); ++i) *out_ << vna[i] << " ";
386  *out_ << "\n*** v_new ***\n";
387 
388  *out_ << "\n*** a_new ***\n";
389  RTOpPack::ConstSubVectorView<Scalar> anv;
390  a_new->acquireDetachedView(range, &anv);
391  auto ana = anv.values();
392  for (auto i = 0; i < ana.size(); ++i) *out_ << ana[i] << " ";
393  *out_ << "\n*** a_new ***\n";
394 #endif
395 
396  workingState->setOrder(this->getOrder());
397  workingState->computeNorms(currentState);
398  }
399  return;
400 }
401 
402 /** \brief Provide a StepperState to the SolutionState.
403  * This Stepper does not have any special state data,
404  * so just provide the base class StepperState with the
405  * Stepper description. This can be checked to ensure
406  * that the input StepperState can be used by this Stepper.
407  */
408 template <class Scalar>
409 Teuchos::RCP<Tempus::StepperState<Scalar>>
411 #ifdef VERBOSE_DEBUG_OUTPUT
412  *out_ << "DEBUG: " << __PRETTY_FUNCTION__ << "\n";
413 #endif
414  Teuchos::RCP<Tempus::StepperState<Scalar>> stepperState =
415  rcp(new StepperState<Scalar>(this->getStepperType()));
416  return stepperState;
417 }
418 
419 template <class Scalar>
420 void
422  Teuchos::FancyOStream& out,
423  const Teuchos::EVerbosityLevel verbLevel) const {
424 #ifdef VERBOSE_DEBUG_OUTPUT
425  *out_ << "DEBUG: " << __PRETTY_FUNCTION__ << "\n";
426 #endif
427 
428  out << std::endl;
429  Stepper<Scalar>::describe(out, verbLevel);
430  StepperImplicit<Scalar>::describe(out, verbLevel);
431 
432  out << "--- StepperNewmarkImplicitDForm ---\n";
433  out << " schemeName_ = " << schemeName_ << std::endl;
434  out << " beta_ = " << beta_ << std::endl;
435  out << " gamma_ = " << gamma_ << std::endl;
436  out << "-----------------------------------" << std::endl;
437 }
438 
439 
440 template<class Scalar>
441 bool StepperNewmarkImplicitDForm<Scalar>::isValidSetup(Teuchos::FancyOStream & out) const
442 {
443  bool isValidSetup = true;
444 
445  if ( !Stepper<Scalar>::isValidSetup(out) ) isValidSetup = false;
446 
447  //if ( !StepperImplicit<Scalar>::isValidSetup(out) ) isValidSetup = false;
448  if (this->wrapperModel_->getAppModel() == Teuchos::null) {
449  isValidSetup = false;
450  out << "The application ModelEvaluator is not set!\n";
451  }
452 
453  if (this->wrapperModel_ == Teuchos::null) {
454  isValidSetup = false;
455  out << "The wrapper ModelEvaluator is not set!\n";
456  }
457 
458  if (this->solver_ == Teuchos::null) {
459  isValidSetup = false;
460  out << "The solver is not set!\n";
461  }
462 
463  return isValidSetup;
464 }
465 
466 
467 template <class Scalar>
468 Teuchos::RCP<const Teuchos::ParameterList>
470 #ifdef VERBOSE_DEBUG_OUTPUT
471  *out_ << "DEBUG: " << __PRETTY_FUNCTION__ << "\n";
472 #endif
473  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
474  getValidParametersBasic(pl, this->getStepperType());
475  pl->set<std::string>("Scheme Name", "Average Acceleration");
476  pl->set<double> ("Beta" , 0.25);
477  pl->set<double> ("Gamma", 0.5 );
478  pl->set<std::string>("Solver Name", "Default Solver");
479  pl->set<bool> ("Zero Initial Guess", false);
480  Teuchos::RCP<Teuchos::ParameterList> solverPL = defaultSolverParameters();
481  pl->set("Default Solver", *solverPL);
482 
483  return pl;
484 }
485 
486 } // namespace Tempus
487 #endif // Tempus_StepperNewmarkImplicitDForm_impl_hpp
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual void setZeroInitialGuess(bool zIG)
Set parameter so that the initial guess is set to zero (=True) or use last timestep (=False).
virtual void setSolver(Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > solver)
Set solver.
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar >> &solutionHistory)
Take the specified timestep, dt, and return true if successful.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
void correctVelocity(Thyra::VectorBase< Scalar > &v, const Thyra::VectorBase< Scalar > &vPred, const Thyra::VectorBase< Scalar > &a, const Scalar dt) const
void correctAcceleration(Thyra::VectorBase< Scalar > &a, const Thyra::VectorBase< Scalar > &dPred, const Thyra::VectorBase< Scalar > &d, const Scalar dt) const
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
void predictVelocity(Thyra::VectorBase< Scalar > &vPred, const Thyra::VectorBase< Scalar > &v, const Thyra::VectorBase< Scalar > &a, const Scalar dt) const
virtual void setObserver(Teuchos::RCP< StepperObserver< Scalar > >=Teuchos::null)
Set Observer.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.
void correctDisplacement(Thyra::VectorBase< Scalar > &d, const Thyra::VectorBase< Scalar > &dPred, const Thyra::VectorBase< Scalar > &a, const Scalar dt) const
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar >> &appModel)
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 bool getUseFSALDefault() const
virtual void initialize()
Initialize after construction and changing input parameters.
virtual std::string getICConsistencyDefault() const
void setStepperType(std::string s)
void setICConsistency(std::string s)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
A ModelEvaluator for residual evaluations given a state. This ModelEvaluator takes a state,...
void getValidParametersBasic(Teuchos::RCP< Teuchos::ParameterList > pl, std::string stepperType)
Provide basic parameters to Steppers.
void validSecondOrderODE_DAE(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model)
Validate ME supports 2nd order implicit ODE/DAE evaluation, f(xdotdot,xdot,x,t) [= 0].
Teuchos::RCP< Teuchos::ParameterList > defaultSolverParameters()
Returns the default solver ParameterList for implicit Steppers.