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" 23 template <
int dim,
typename real,
typename MeshType>
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);
35 display_error_ode_solver_factory(ode_solver_type,
false);
40 template <
int dim,
typename real,
typename MeshType>
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);
54 display_error_ode_solver_factory(ode_solver_type,
true);
59 template <
int dim,
typename real,
typename MeshType>
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);
69 display_error_ode_solver_factory(ode_solver_type,
true);
74 template <
int dim,
typename real,
typename MeshType>
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);
85 display_error_ode_solver_factory(ode_solver_type,
false);
90 template <
int dim,
typename real,
typename MeshType>
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);
103 display_error_ode_solver_factory(ode_solver_type,
true);
108 template <
int dim,
typename real,
typename MeshType>
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);
117 display_error_ode_solver_factory(ode_solver_type,
true);
123 template <
int dim,
typename real,
typename MeshType>
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";
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;
149 pcout <<
"pod_galerkin" << std::endl;
150 pcout <<
"pod_petrov_galerkin" << std::endl;
151 pcout <<
"pod_galerkin_runge_kutta" << std::endl;
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;
160 pcout <<
"********************************************************************" << std::endl;
164 template <
int dim,
typename real,
typename MeshType>
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);
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) {
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);
183 else if (n_rk_stages == 2){
184 return std::make_shared<RungeKuttaODESolver<dim,real,2,MeshType>>(dg_input,rk_tableau,RRK_object);
186 else if (n_rk_stages == 3){
187 return std::make_shared<RungeKuttaODESolver<dim,real,3,MeshType>>(dg_input,rk_tableau,RRK_object);
189 else if (n_rk_stages == 4){
190 return std::make_shared<RungeKuttaODESolver<dim,real,4,MeshType>>(dg_input,rk_tableau,RRK_object);
193 pcout <<
"Error: invalid number of stages. Aborting..." << std::endl;
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);;
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);
206 else if (n_rk_stages == 2){
207 return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,2, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
209 else if (n_rk_stages == 3){
210 return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,3, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
212 else if (n_rk_stages == 4){
213 return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,4, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
215 else if (n_rk_stages == 5){
216 return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,5, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
218 else if (n_rk_stages == 9){
219 return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,9, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
221 else if (n_rk_stages == 10){
222 return std::make_shared<LowStorageRungeKuttaODESolver<dim,real,10, MeshType>>(dg_input,ls_rk_tableau,RRK_object);
225 pcout <<
"Error: invalid number of stages. Aborting..." << std::endl;
230 display_error_ode_solver_factory(ode_solver_type,
false);
235 template <
int dim,
typename real,
typename MeshType>
238 dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
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);
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) {
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" 251 <<
"Please set use_inverse_mass_on_the_fly=false and try again" 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);
260 else if (n_rk_stages == 2){
261 return std::make_shared<PODGalerkinRungeKuttaODESolver<dim,real,2,MeshType>>(dg_input,rk_tableau,RRK_object,pod);
263 else if (n_rk_stages == 3){
264 return std::make_shared<PODGalerkinRungeKuttaODESolver<dim,real,3,MeshType>>(dg_input,rk_tableau,RRK_object,pod);
266 else if (n_rk_stages == 4){
267 return std::make_shared<PODGalerkinRungeKuttaODESolver<dim,real,4,MeshType>>(dg_input,rk_tableau,RRK_object,pod);
270 pcout <<
"Error: invalid number of stages. Aborting..." << std::endl;
276 display_error_ode_solver_factory(ode_solver_type,
false);
281 template <
int dim,
typename real,
typename MeshType>
285 dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
287 const RKMethodEnum rk_method = dg_input->all_parameters->ode_solver_param.runge_kutta_method;
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;
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");
297 pcout <<
"Error: invalid LS RK method. Aborting..." << std::endl;
303 template <
int dim,
typename real,
typename MeshType>
306 dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
308 const RKMethodEnum rk_method = dg_input->all_parameters->ode_solver_param.runge_kutta_method;
310 const int n_rk_stages = dg_input->all_parameters->ode_solver_param.n_rk_stages;
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) {
320 pcout <<
"Error: RRK is not valid for Forward Euler. Aborting..." << std::endl;
323 }
else return std::make_shared<EulerExplicit<dim, real, MeshType>> (n_rk_stages,
"Forward Euler (explicit)");
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)");
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)");
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)");
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)");
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)");
346 pcout <<
"Error: invalid RK method. Aborting..." << std::endl;
352 template <
int dim,
typename real,
typename MeshType>
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;
360 if (ode_solver_type == ODEEnum::runge_kutta_solver && dg_input->all_parameters->flow_solver_param.do_calculate_numerical_entropy) {
362 return std::make_shared<RKNumEntropy<dim,real,MeshType>>(rk_tableau);
364 else if (ode_solver_type == ODEEnum::rrk_explicit_solver){
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;
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";
382 pcout <<
"PDE type has no assigned numerical entropy variable. Aborting..." << std::endl;
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);
393 return std::make_shared<EmptyRRKBase<dim,real,MeshType>> (rk_tableau);
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.
RKMethodEnum
Types of RK method (i.e., unique Butcher tableau)
ODESolverEnum
Types of ODE solver.
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.
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...