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