[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
ode_solver_factory.cpp
1 #include "ode_solver_factory.h"
2 #include "parameters/all_parameters.h"
3 #include "ode_solver_base.h"
4 #include "runge_kutta_ode_solver.h"
5 #include "low_storage_runge_kutta_ode_solver.h"
6 #include "implicit_ode_solver.h"
7 #include "relaxation_runge_kutta/algebraic_rrk_ode_solver.h"
8 #include "relaxation_runge_kutta/root_finding_rrk_ode_solver.h"
9 #include "pod_galerkin_ode_solver.h"
10 #include "pod_petrov_galerkin_ode_solver.h"
11 #include "pod_galerkin_runge_kutta_ode_solver.h"
12 #include "hyper_reduced_petrov_galerkin_ode_solver.h"
13 #include <deal.II/distributed/solution_transfer.h>
14 #include "runge_kutta_methods/runge_kutta_methods.h"
15 #include "runge_kutta_methods/rk_tableau_base.h"
16 #include "runge_kutta_methods/low_storage_rk_tableau_base.h"
17 #include "runge_kutta_methods/low_storage_runge_kutta_methods.h"
18 #include "relaxation_runge_kutta/empty_RRK_base.h"
19 
20 namespace PHiLiP {
21 namespace ODE {
22 
23 template <int dim, typename real, typename MeshType>
24 std::shared_ptr<ODESolverBase<dim,real,MeshType>> ODESolverFactory<dim,real,MeshType>::create_ODESolver(std::shared_ptr< DGBase<dim,real,MeshType> > dg_input)
25 {
26  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
27  pcout << "Creating ODE Solver..." << std::endl;
29  const ODEEnum ode_solver_type = dg_input->all_parameters->ode_solver_param.ode_solver_type;
30  if((ode_solver_type == ODEEnum::runge_kutta_solver)||(ode_solver_type == ODEEnum::rrk_explicit_solver || ode_solver_type == ODEEnum::low_storage_runge_kutta_solver))
31  return create_RungeKuttaODESolver(dg_input);
32  if(ode_solver_type == ODEEnum::implicit_solver)
33  return std::make_shared<ImplicitODESolver<dim,real,MeshType>>(dg_input);
34  else {
35  display_error_ode_solver_factory(ode_solver_type, false);
36  return nullptr;
37  }
38 }
39 
40 template <int dim, typename real, typename MeshType>
41 std::shared_ptr<ODESolverBase<dim,real,MeshType>> ODESolverFactory<dim,real,MeshType>::create_ODESolver(std::shared_ptr< DGBase<dim,real,MeshType> > dg_input, std::shared_ptr<ProperOrthogonalDecomposition::PODBase<dim>> pod)
42 {
43  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
44  pcout << "Creating ODE Solver..." << std::endl;
46  const ODEEnum ode_solver_type = dg_input->all_parameters->ode_solver_param.ode_solver_type;
47  if(ode_solver_type == ODEEnum::pod_galerkin_solver)
48  return std::make_shared<PODGalerkinODESolver<dim,real,MeshType>>(dg_input, pod);
49  if(ode_solver_type == ODEEnum::pod_petrov_galerkin_solver)
50  return std::make_shared<PODPetrovGalerkinODESolver<dim,real,MeshType>>(dg_input, pod);
51  if(ode_solver_type == ODEEnum::pod_galerkin_runge_kutta_solver)
52  return create_RungeKuttaODESolver(dg_input, pod);
53  else {
54  display_error_ode_solver_factory(ode_solver_type, true);
55  return nullptr;
56  }
57 }
58 
59 template <int dim, typename real, typename MeshType>
60 std::shared_ptr<ODESolverBase<dim,real,MeshType>> ODESolverFactory<dim,real,MeshType>::create_ODESolver(std::shared_ptr< DGBase<dim,real,MeshType> > dg_input, std::shared_ptr<ProperOrthogonalDecomposition::PODBase<dim>> pod, Epetra_Vector weights)
61 {
62  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
63  pcout << "Creating ODE Solver..." << std::endl;
65  const ODEEnum ode_solver_type = dg_input->all_parameters->ode_solver_param.ode_solver_type;
66  if(ode_solver_type == ODEEnum::hyper_reduced_petrov_galerkin_solver)
67  return std::make_shared<HyperReducedODESolver<dim,real,MeshType>>(dg_input, pod, weights);
68  else {
69  display_error_ode_solver_factory(ode_solver_type, true);
70  return nullptr;
71  }
72 }
73 
74 template <int dim, typename real, typename MeshType>
75 std::shared_ptr<ODESolverBase<dim,real,MeshType>> ODESolverFactory<dim,real,MeshType>::create_ODESolver_manual(Parameters::ODESolverParam::ODESolverEnum ode_solver_type, std::shared_ptr< DGBase<dim,real,MeshType> > dg_input)
76 {
77  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
78  pcout << "Creating ODE Solver..." << std::endl;
80  if((ode_solver_type == ODEEnum::runge_kutta_solver)||(ode_solver_type == ODEEnum::rrk_explicit_solver))
81  return create_RungeKuttaODESolver(dg_input);
82  if(ode_solver_type == ODEEnum::implicit_solver)
83  return std::make_shared<ImplicitODESolver<dim,real,MeshType>>(dg_input);
84  else {
85  display_error_ode_solver_factory(ode_solver_type, false);
86  return nullptr;
87  }
88 }
89 
90 template <int dim, typename real, typename MeshType>
91 std::shared_ptr<ODESolverBase<dim,real,MeshType>> ODESolverFactory<dim,real,MeshType>::create_ODESolver_manual(Parameters::ODESolverParam::ODESolverEnum ode_solver_type, std::shared_ptr< DGBase<dim,real,MeshType> > dg_input, std::shared_ptr<ProperOrthogonalDecomposition::PODBase<dim>> pod)
92 {
93  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
94  pcout << "Creating ODE Solver..." << std::endl;
96  if(ode_solver_type == ODEEnum::pod_galerkin_solver)
97  return std::make_shared<PODGalerkinODESolver<dim,real,MeshType>>(dg_input, pod);
98  if(ode_solver_type == ODEEnum::pod_petrov_galerkin_solver)
99  return std::make_shared<PODPetrovGalerkinODESolver<dim,real,MeshType>>(dg_input, pod);
100  if(ode_solver_type == ODEEnum::pod_galerkin_runge_kutta_solver)
101  return create_RungeKuttaODESolver(dg_input, pod);
102  else {
103  display_error_ode_solver_factory(ode_solver_type, true);
104  return nullptr;
105  }
106 }
107 
108 template <int dim, typename real, typename MeshType>
109 std::shared_ptr<ODESolverBase<dim,real,MeshType>> ODESolverFactory<dim,real,MeshType>::create_ODESolver_manual(Parameters::ODESolverParam::ODESolverEnum ode_solver_type, std::shared_ptr< DGBase<dim,real,MeshType> > dg_input, std::shared_ptr<ProperOrthogonalDecomposition::PODBase<dim>> pod, Epetra_Vector weights)
110 {
111  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
112  pcout << "Creating ODE Solver..." << std::endl;
114  if(ode_solver_type == ODEEnum::hyper_reduced_petrov_galerkin_solver)
115  return std::make_shared<HyperReducedODESolver<dim,real,MeshType>>(dg_input, pod, weights);
116  else {
117  display_error_ode_solver_factory(ode_solver_type, true);
118  return nullptr;
119  }
120 }
121 
122 
123 template <int dim, typename real, typename MeshType>
125 {
127 
128  std::string solver_string;
129  if (ode_solver_type == ODEEnum::runge_kutta_solver) solver_string = "runge_kutta";
130  else if (ode_solver_type == ODEEnum::implicit_solver) solver_string = "implicit";
131  else if (ode_solver_type == ODEEnum::rrk_explicit_solver) solver_string = "rrk_explicit";
132  else if (ode_solver_type == ODEEnum::pod_galerkin_solver) solver_string = "pod_galerkin";
133  else if (ode_solver_type == ODEEnum::pod_petrov_galerkin_solver) solver_string = "pod_petrov_galerkin";
134  else if (ode_solver_type == ODEEnum::hyper_reduced_petrov_galerkin_solver)
135  solver_string = "hyper_reduced_petrov_galerkin";
136  else if (ode_solver_type == ODEEnum::low_storage_runge_kutta_solver)
137  solver_string = "low_storage_runge_kutta_solver";
138  else if (ode_solver_type == ODEEnum::pod_galerkin_runge_kutta_solver)
139  solver_string = "pod_galerkin_runge_kutta";
140  else solver_string = "undefined";
141 
142 
143  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
144  pcout << "********************************************************************" << std::endl;
145  pcout << "Can't create ODE solver since solver type is not clear." << std::endl;
146  pcout << "Solver type specified: " << solver_string << std::endl;
147  pcout << "Solver type possible: " << std::endl;
148  if(reduced_order){
149  pcout << "pod_galerkin" << std::endl;
150  pcout << "pod_petrov_galerkin" << std::endl;
151  pcout << "pod_galerkin_runge_kutta" << std::endl;
152  }
153  else{
154  pcout << "runge_kutta" << std::endl;
155  pcout << "implicit" << std::endl;
156  pcout << "rrk_explicit" << std::endl;
157  pcout << " With rrk_explicit only being valid for " <<std::endl;
158  pcout << " pde_type = burgers, flux_nodes_type = GLL, overintegration = 0, and dim = 1" <<std::endl;
159  }
160  pcout << "********************************************************************" << std::endl;
161  std::abort();
162 }
163 
164 template <int dim, typename real, typename MeshType>
165 std::shared_ptr<ODESolverBase<dim,real,MeshType>> ODESolverFactory<dim,real,MeshType>::create_RungeKuttaODESolver(std::shared_ptr< DGBase<dim,real,MeshType> > dg_input)
166 {
167  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
168  std::shared_ptr<RKTableauBase<dim,real,MeshType>> rk_tableau = create_RKTableau(dg_input);
169  std::shared_ptr<EmptyRRKBase<dim,real,MeshType>> RRK_object = create_RRKObject(dg_input, rk_tableau);
170 
171 
172  const int n_rk_stages = dg_input->all_parameters->ode_solver_param.n_rk_stages;
174  const ODEEnum ode_solver_type = dg_input->all_parameters->ode_solver_param.ode_solver_type;
175  if (ode_solver_type == ODEEnum::runge_kutta_solver || ode_solver_type == ODEEnum::rrk_explicit_solver) {
176 
177  // Hard-coded templating of n_rk_stages because it is not known at compile time
178  pcout << "Creating Runge Kutta ODE Solver with "
179  << n_rk_stages << " stage(s)..." << std::endl;
180  if (n_rk_stages == 1){
181  return std::make_shared<RungeKuttaODESolver<dim,real,1,MeshType>>(dg_input,rk_tableau,RRK_object);
182  }
183  else if (n_rk_stages == 2){
184  return std::make_shared<RungeKuttaODESolver<dim,real,2,MeshType>>(dg_input,rk_tableau,RRK_object);
185  }
186  else if (n_rk_stages == 3){
187  return std::make_shared<RungeKuttaODESolver<dim,real,3,MeshType>>(dg_input,rk_tableau,RRK_object);
188  }
189  else if (n_rk_stages == 4){
190  return std::make_shared<RungeKuttaODESolver<dim,real,4,MeshType>>(dg_input,rk_tableau,RRK_object);
191  }
192  else{
193  pcout << "Error: invalid number of stages. Aborting..." << std::endl;
194  std::abort();
195  return nullptr;
196  }
197  } else if (ode_solver_type == ODEEnum::low_storage_runge_kutta_solver) {
198  std::shared_ptr<LowStorageRKTableauBase<dim,real,MeshType>> ls_rk_tableau = create_LowStorageRKTableau(dg_input);;
199 
200  // Hard-coded templating of n_rk_stages because it is not known at compile time
201  pcout << "Creating Low-Storage Runge Kutta ODE Solver with "
202  << n_rk_stages << " stage(s)..." << std::endl;
203  if (n_rk_stages == 1){
204  return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,1, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
205  }
206  else if (n_rk_stages == 2){
207  return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,2, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
208  }
209  else if (n_rk_stages == 3){
210  return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,3, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
211  }
212  else if (n_rk_stages == 4){
213  return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,4, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
214  }
215  else if (n_rk_stages == 5){
216  return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,5, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
217  }
218  else if (n_rk_stages == 9){
219  return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,9, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
220  }
221  else if (n_rk_stages == 10){
222  return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,10, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
223  }
224  else{
225  pcout << "Error: invalid number of stages. Aborting..." << std::endl;
226  std::abort();
227  return nullptr;
228  }
229  } else {
230  display_error_ode_solver_factory(ode_solver_type, false);
231  return nullptr;
232  }
233 }
234 
235 template <int dim, typename real, typename MeshType>
236 std::shared_ptr<ODESolverBase<dim,real,MeshType>> ODESolverFactory<dim,real,MeshType>::create_RungeKuttaODESolver(std::shared_ptr< DGBase<dim, real, MeshType> > dg_input, std::shared_ptr<ProperOrthogonalDecomposition::PODBase<dim>> pod)
237 {
238  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
239 
240  std::shared_ptr<RKTableauBase<dim,real,MeshType>> rk_tableau = create_RKTableau(dg_input);
241  std::shared_ptr<EmptyRRKBase<dim,real,MeshType>> RRK_object = create_RRKObject(dg_input, rk_tableau);
242 
243  const int n_rk_stages = dg_input->all_parameters->ode_solver_param.n_rk_stages;
245  const ODEEnum ode_solver_type = dg_input->all_parameters->ode_solver_param.ode_solver_type;
246  if (ode_solver_type == ODEEnum::pod_galerkin_runge_kutta_solver) {
247  // Hard-coded templating of n_rk_stages because it is not known at compile time
248  if(dg_input->all_parameters->use_inverse_mass_on_the_fly){
249  pcout << "Not Implemented: use_inverse_mass_on_the_fly=true && ode_solver_type=pod_galerkin_rk_solver"
250  << '\n'
251  << "Please set use_inverse_mass_on_the_fly=false and try again"
252  << std::endl;
253  std::abort();
254  }
255  pcout << "Creating Galerkin Runge Kutta ODE Solver with "
256  << n_rk_stages << " stage(s)..." << std::endl;
257  if (n_rk_stages == 1){
258  return std::make_shared<PODGalerkinRungeKuttaODESolver<dim,real,1,MeshType>>(dg_input,rk_tableau,RRK_object,pod);
259  }
260  else if (n_rk_stages == 2){
261  return std::make_shared<PODGalerkinRungeKuttaODESolver<dim,real,2,MeshType>>(dg_input,rk_tableau,RRK_object,pod);
262  }
263  else if (n_rk_stages == 3){
264  return std::make_shared<PODGalerkinRungeKuttaODESolver<dim,real,3,MeshType>>(dg_input,rk_tableau,RRK_object,pod);
265  }
266  else if (n_rk_stages == 4){
267  return std::make_shared<PODGalerkinRungeKuttaODESolver<dim,real,4,MeshType>>(dg_input,rk_tableau,RRK_object,pod);
268  }
269  else{
270  pcout << "Error: invalid number of stages. Aborting..." << std::endl;
271  std::abort();
272  return nullptr;
273  }
274  }
275  else {
276  display_error_ode_solver_factory(ode_solver_type, false);
277  return nullptr;
278  }
279 }
280 
281 template <int dim, typename real, typename MeshType>
282 std::shared_ptr<LowStorageRKTableauBase<dim,real,MeshType>> ODESolverFactory<dim,real,MeshType>::create_LowStorageRKTableau(std::shared_ptr< DGBase<dim,real,MeshType> > dg_input)
283 {
284 
285  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
286  using RKMethodEnum = Parameters::ODESolverParam::RKMethodEnum;
287  const RKMethodEnum rk_method = dg_input->all_parameters->ode_solver_param.runge_kutta_method;
288 
289  const int n_rk_stages = dg_input->all_parameters->ode_solver_param.n_rk_stages;
290  const int num_delta = dg_input->all_parameters->ode_solver_param.num_delta;
291 
292  if (rk_method == RKMethodEnum::RK3_2_5F_3SStarPlus) return std::make_shared<RK3_2_5F_3SStarPlus<dim, real, MeshType>> (n_rk_stages, num_delta, "RK3_2_5F_3SStarPlus");
293  if (rk_method == RKMethodEnum::RK4_3_5_3SStar) return std::make_shared<RK4_3_5_3SStar<dim, real, MeshType>> (n_rk_stages, num_delta, "RK4_3_5_3SStar");
294  if (rk_method == RKMethodEnum::RK4_3_9F_3SStarPlus) return std::make_shared<RK4_3_9F_3SStarPlus<dim, real, MeshType>> (n_rk_stages, num_delta, "RK4_3_9F_3SStarPlus");
295  if (rk_method == RKMethodEnum::RK5_4_10F_3SStarPlus) return std::make_shared<RK5_4_10F_3SStarPlus<dim, real, MeshType>> (n_rk_stages, num_delta, "RK5_4_10F_3SStarPlus");
296  else {
297  pcout << "Error: invalid LS RK method. Aborting..." << std::endl;
298  std::abort();
299  return nullptr;
300  }
301 }
302 
303 template <int dim, typename real, typename MeshType>
304 std::shared_ptr<RKTableauBase<dim,real,MeshType>> ODESolverFactory<dim,real,MeshType>::create_RKTableau(std::shared_ptr< DGBase<dim,real,MeshType> > dg_input)
305 {
306  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
307  using RKMethodEnum = Parameters::ODESolverParam::RKMethodEnum;
308  const RKMethodEnum rk_method = dg_input->all_parameters->ode_solver_param.runge_kutta_method;
309 
310  const int n_rk_stages = dg_input->all_parameters->ode_solver_param.n_rk_stages;
311 
312  if (rk_method == RKMethodEnum::ssprk3_ex) return std::make_shared<SSPRK3Explicit<dim, real, MeshType>> (n_rk_stages, "3rd order SSP (explicit)");
313  if (rk_method == RKMethodEnum::rk4_ex) return std::make_shared<RK4Explicit<dim, real, MeshType>> (n_rk_stages, "4th order classical RK (explicit)");
314  if (rk_method == RKMethodEnum::heun2_ex) return std::make_shared<HeunExplicit<dim, real, MeshType>> (n_rk_stages, "2nd order Heun's method (explicit)");
315  if (rk_method == RKMethodEnum::euler_ex) {
317  ODEEnum ode_solver_type = dg_input->all_parameters->ode_solver_param.ode_solver_type;
318  if (ode_solver_type == ODEEnum::rrk_explicit_solver) {
319  //forward Euler is invalid for RRK: sum(b_i*a_ij) = 0 (see Lemma 2.1 in Ketcheson 2019)
320  pcout << "Error: RRK is not valid for Forward Euler. Aborting..." << std::endl;
321  std::abort();
322  return nullptr;
323  } else return std::make_shared<EulerExplicit<dim, real, MeshType>> (n_rk_stages, "Forward Euler (explicit)");
324  }
325  if (rk_method == RKMethodEnum::euler_im) return std::make_shared<EulerImplicit<dim, real, MeshType>> (n_rk_stages, "Implicit Euler (implicit)");
326  if (rk_method == RKMethodEnum::dirk_2_im) return std::make_shared<DIRK2Implicit<dim, real, MeshType>> (n_rk_stages, "2nd order diagonally-implicit (implicit)");
327  if (rk_method == RKMethodEnum::dirk_3_im) return std::make_shared<DIRK3Implicit<dim, real, MeshType>> (n_rk_stages, "3nd order diagonally-implicit (implicit)");
328  else {
329  // Return dummy RK method when running LSRK method because an RK tableau has to be created
330  if (rk_method == RKMethodEnum::RK3_2_5F_3SStarPlus){
331  pcout << "WARNING: returning dummy RK method!" << std::endl;
332  return std::make_shared<SSPRK3Explicit<dim, real, MeshType>> (n_rk_stages, "3rd order SSP (explicit)");
333  }
334  if (rk_method == RKMethodEnum::RK4_3_5_3SStar) {
335  pcout << "WARNING: returning dummy RK method!" << std::endl;
336  return std::make_shared<SSPRK3Explicit<dim, real, MeshType>> (n_rk_stages, "3rd order SSP (explicit)");
337  }
338  if (rk_method == RKMethodEnum::RK4_3_9F_3SStarPlus) {
339  pcout << "WARNING: returning dummy RK method!" << std::endl;
340  return std::make_shared<SSPRK3Explicit<dim, real, MeshType>> (n_rk_stages, "3rd order SSP (explicit)");
341  }
342  if (rk_method == RKMethodEnum::RK5_4_10F_3SStarPlus) {
343  pcout << "WARNING: returning dummy RK method!" << std::endl;
344  return std::make_shared<SSPRK3Explicit<dim, real, MeshType>> (n_rk_stages, "3rd order SSP (explicit)");
345  }
346  pcout << "Error: invalid RK method. Aborting..." << std::endl;
347  std::abort();
348  return nullptr;
349  }
350 }
351 
352 template <int dim, typename real, typename MeshType>
353 std::shared_ptr<EmptyRRKBase<dim,real,MeshType>> ODESolverFactory<dim,real,MeshType>::create_RRKObject( std::shared_ptr< DGBase<dim,real,MeshType> > dg_input,
354  std::shared_ptr<RKTableauBase<dim,real,MeshType>> rk_tableau)
355 {
356  dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
358  const ODEEnum ode_solver_type = dg_input->all_parameters->ode_solver_param.ode_solver_type;
359 
360  if (ode_solver_type == ODEEnum::runge_kutta_solver && dg_input->all_parameters->flow_solver_param.do_calculate_numerical_entropy) {
361  // If calculating numerical entropy, select the class which has that functionality
362  return std::make_shared<RKNumEntropy<dim,real,MeshType>>(rk_tableau);
363  }
364  else if (ode_solver_type == ODEEnum::rrk_explicit_solver){
365 
367  const PDEEnum pde_type = dg_input->all_parameters->pde_type;
369  const NumFluxEnum two_point_num_flux_type = dg_input->all_parameters->two_point_num_flux_type;
370 
371  enum NumEntropyEnum {energy, nonlinear};
372  NumEntropyEnum numerical_entropy_type;
373  std::string rrk_type_string;
374  if (pde_type == PDEEnum::burgers_inviscid){
375  numerical_entropy_type = NumEntropyEnum::energy;
376  rrk_type_string = "Algebraic";
377  } else if ((pde_type == PDEEnum::euler || pde_type == PDEEnum::navier_stokes)
378  && (two_point_num_flux_type != NumFluxEnum::KG)){
379  numerical_entropy_type = NumEntropyEnum::nonlinear;
380  rrk_type_string = "Root-finding";
381  } else{
382  pcout << "PDE type has no assigned numerical entropy variable. Aborting..." << std::endl;
383  std::abort();
384  }
385 
386  pcout << "Adding " << rrk_type_string << " Relaxation Runge Kutta to the ODE solver..." << std::endl;
387  if (numerical_entropy_type==NumEntropyEnum::energy)
388  return std::make_shared<AlgebraicRRKODESolver<dim,real,MeshType>>(rk_tableau);
389  else if (numerical_entropy_type==NumEntropyEnum::nonlinear)
390  return std::make_shared<RootFindingRRKODESolver<dim,real,MeshType>>(rk_tableau);
391  else return nullptr; // no need for message as numerical_entropy_type has already been checked
392  } else {
393  return std::make_shared<EmptyRRKBase<dim,real,MeshType>> (rk_tableau);
394  }
395 }
396 
399 #if PHILIP_DIM != 1
401 #endif
402 
403 } // ODE namespace
404 } // PHiLiP namespace
static std::shared_ptr< ODESolverBase< dim, real, MeshType > > create_ODESolver_manual(Parameters::ODESolverParam::ODESolverEnum ode_solver_type, std::shared_ptr< DGBase< dim, real, MeshType > > dg_input)
Creates either implicit or explicit ODE solver based on manual input (no POD basis given) ...
static std::shared_ptr< LowStorageRKTableauBase< dim, real, MeshType > > create_LowStorageRKTableau(std::shared_ptr< DGBase< dim, real, MeshType > > dg_input)
Creates an RKTableau object based on the specified RK method.
PartialDifferentialEquation
Possible Partial Differential Equations to solve.
Files for the baseline physics.
Definition: ADTypes.hpp:10
RKMethodEnum
Types of RK method (i.e., unique Butcher tableau)
Create specified ODE solver as ODESolverBase object.
static std::shared_ptr< ODESolverBase< dim, real, MeshType > > create_RungeKuttaODESolver(std::shared_ptr< DGBase< dim, real, MeshType > > dg_input)
Creates an ODESolver object based on the specified RK method, including derived classes.
TwoPointNumericalFlux
Two point numerical flux type for split form.
static void display_error_ode_solver_factory(Parameters::ODESolverParam::ODESolverEnum ode_solver_type, bool reduced_order)
Output error message for Implicit and Explicit solver.
static std::shared_ptr< RKTableauBase< dim, real, MeshType > > create_RKTableau(std::shared_ptr< DGBase< dim, real, MeshType > > dg_input)
Creates an RKTableau object based on the specified RK method.
Base class for storing the RK method.
DGBase is independent of the number of state variables.
Definition: dg_base.hpp:82
static std::shared_ptr< ODESolverBase< dim, real, MeshType > > create_ODESolver(std::shared_ptr< DGBase< dim, real, MeshType > > dg_input)
Creates either implicit or explicit ODE solver based on parameter value(no POD basis given) ...
static std::shared_ptr< EmptyRRKBase< dim, real, MeshType > > create_RRKObject(std::shared_ptr< DGBase< dim, real, MeshType > > dg_input, std::shared_ptr< RKTableauBase< dim, real, MeshType >> rk_tableau)
Creates an RRK object with specified RRK type; if no RRK is being used, creates an RRK object with em...