VertexCFD  0.0-dev
VertexCFD_TempusTimeStepControl_GlobalCFL_impl.hpp
1 #ifndef VERTEXCFD_TEMPUSTIMESTEPCONTROL_GLOBALCFL_IMPL_HPP
2 #define VERTEXCFD_TEMPUSTIMESTEPCONTROL_GLOBALCFL_IMPL_HPP
3 
4 #include "VertexCFD_TempusTimeStepControl_GlobalCFL.hpp"
5 
6 #include <Teuchos_ParameterList.hpp>
7 #include <Teuchos_RCP.hpp>
8 #include <Teuchos_StandardParameterEntryValidators.hpp>
9 
10 #include <algorithm>
11 #include <string>
12 
13 namespace VertexCFD
14 {
15 namespace TempusTimeStepControl
16 {
17 //---------------------------------------------------------------------------//
18 template<class Scalar>
19 GlobalCFL<Scalar>::GlobalCFL(const Teuchos::ParameterList& user_params,
20  Teuchos::RCP<PhysicsManager> physics_manager)
21  : _cfl(user_params.get<double>("CFL"))
22  , _cfl_init(user_params.isType<double>("CFL_init")
23  ? user_params.get<double>("CFL_init")
24  : _cfl)
25  , _cfl_transition_init(0.0)
26  , _cfl_transition(0.0)
27  , _cfl_type(CflTransitionType::steps)
28  , _response_manager(physics_manager)
29 {
30  // Validate transition type if present
31  if (user_params.isType<std::string>("CFL_transition_type"))
32  {
33  const auto type_validator = Teuchos::rcp(
34  new Teuchos::StringToIntegralParameterEntryValidator<CflTransitionType>(
35  Teuchos::tuple<std::string>("steps", "time"), "steps"));
36  _cfl_type = type_validator->getIntegralValue(
37  user_params.get<std::string>("CFL_transition_type"));
38  }
39 
40  // Check for ramping options
41  if (user_params.isType<double>("CFL_transition"))
42  {
43  _cfl_transition = user_params.get<double>("CFL_transition");
44  if (user_params.isType<double>("CFL_transition_init"))
45  {
46  _cfl_transition_init
47  = user_params.get<double>("CFL_transition_init");
48  }
49  }
50  else if (user_params.isType<double>("CFL_transition_init"))
51  {
52  const std::string msg
53  = "\n\n'CFL_transition_init' must be"
54  "specified with 'CFL_transition'\n"
55  "in the input file. Please add 'CFL_transition'\n"
56  "to your input file.\n";
57  throw std::runtime_error(msg);
58  }
59 
60  this->setCurrentCFL(_cfl_init);
61 
62  _response_manager.addMinValueResponse("global_cfl_time_step", "local_dt");
63 
64  // For the new Tempus::TimeStepControlStrategy interface, we need to
65  // set a few base class member variables. In particular, incorrect
66  // behavior may result if "stepType_" is not set to "Variable".
67  this->stepType_ = "Variable";
68  this->strategyType_ = "CFL Strategy";
69  this->name_ = "CFL Strategy";
70 }
71 
72 //---------------------------------------------------------------------------//
73 // Determine the time step size.
74 template<class Scalar>
75 void GlobalCFL<Scalar>::setNextTimeStep(
76  const Tempus::TimeStepControl<Scalar>& tsc,
77  Teuchos::RCP<Tempus::SolutionHistory<Scalar>> solution_history,
78  Tempus::Status&)
79 {
80  // Get the working state.
81  auto working_state = solution_history->getWorkingState();
82 
83  // Get minimum time step that ensures CFL <= 1
84  _response_manager.evaluateResponses(working_state->getX(),
85  working_state->getXDot());
86  const double dt_cfl1 = _response_manager.value();
87 
88  // Compute linear weight based on input parameters
89  double wt;
90  if (_cfl_transition > 0)
91  {
92  // Current time step index/time
93  double dt_index = 0.0;
94  if (_cfl_type == CflTransitionType::steps)
95  dt_index = static_cast<double>(solution_history->getCurrentIndex());
96  else
97  dt_index = solution_history->getCurrentTime();
98 
99  if (dt_index < _cfl_transition_init)
100  {
101  wt = 0.0;
102  }
103  else if (dt_index >= _cfl_transition_init
104  && dt_index <= _cfl_transition + _cfl_transition_init)
105  {
106  wt = std::min((dt_index - _cfl_transition_init) / _cfl_transition,
107  1.0);
108  }
109  else
110  {
111  wt = 1.0;
112  }
113  }
114  else
115  {
116  wt = 1.0;
117  }
118 
119  // Compute time step based on desired CFL
120  const double cfl_desired = (1.0 - wt) * _cfl_init + wt * _cfl;
121  double dt = cfl_desired * dt_cfl1;
122 
123  // If it is out of the bounds specified by the user then restrict it
124  // before setting it.
125  const int dt_index = working_state->getIndex() - 1;
126  if (dt_index == 0 && tsc.getInitTimeStep() != tsc.getMinTimeStep())
127  {
128  dt = tsc.getInitTimeStep();
129  }
130  else if (dt < tsc.getMinTimeStep())
131  {
132  dt = tsc.getMinTimeStep();
133  }
134  else if (dt > tsc.getMaxTimeStep())
135  {
136  dt = tsc.getMaxTimeStep();
137  }
138  working_state->setTimeStep(dt);
139  working_state->setTime(solution_history->getCurrentTime() + dt);
140 
141  // Save current CFL so it may be accessed elsewhere
142  this->setCurrentCFL(dt / dt_cfl1);
143 }
144 
145 //---------------------------------------------------------------------------//
146 
147 } // end namespace TempusTimeStepControl
148 } // end namespace VertexCFD
149 
150 #endif // end VERTEXCFD_TEMPUSTIMESTEPCONTROL_GLOBALCFL_IMPL_HPP
VertexCFD
Definition: tstMethodManufacturedSolutionBC.cpp:23