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" 21 template <
int dim,
int nspecies,
typename real,
typename MeshType>
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);
33 display_error_ode_solver_factory(ode_solver_type,
false);
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)
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);
52 display_error_ode_solver_factory(ode_solver_type,
true);
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)
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);
67 display_error_ode_solver_factory(ode_solver_type,
true);
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)
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);
83 display_error_ode_solver_factory(ode_solver_type,
false);
88 template <
int dim,
int nspecies,
typename real,
typename MeshType>
89 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)
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);
101 display_error_ode_solver_factory(ode_solver_type,
true);
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)
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);
115 display_error_ode_solver_factory(ode_solver_type,
true);
121 template <
int dim,
int nspecies,
typename real,
typename MeshType>
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";
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;
148 pcout <<
"pod_galerkin" << std::endl;
149 pcout <<
"pod_petrov_galerkin" << std::endl;
150 pcout <<
"pod_galerkin_runge_kutta" << std::endl;
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;
161 pcout <<
"Specified ODE solver type cannot be created for nspecies > 1." <<std::endl;
163 pcout <<
"********************************************************************" << std::endl;
167 template <
int dim,
int nspecies,
typename real,
typename MeshType>
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);
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) {
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);
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);
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);
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);
198 pcout <<
"Error: invalid number of stages. Aborting..." << std::endl;
202 }
else if (ode_solver_type == ODEEnum::low_storage_runge_kutta_solver && nspecies==1) {
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);
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);
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);
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);
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);
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);
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);
230 pcout <<
"Error: invalid number of stages. Aborting..." << std::endl;
235 display_error_ode_solver_factory(ode_solver_type,
false);
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)
243 dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
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);
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) {
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" 258 <<
"Please set use_inverse_mass_on_the_fly=false and try again" 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);
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);
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);
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);
277 pcout <<
"Error: invalid number of stages. Aborting..." << std::endl;
283 display_error_ode_solver_factory(ode_solver_type,
false);
288 template <
int dim,
int nspecies,
typename real,
typename MeshType>
291 dealii::ConditionalOStream pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0);
293 const RKMethodEnum rk_method = dg_input->all_parameters->ode_solver_param.runge_kutta_method;
295 const int n_rk_stages = dg_input->all_parameters->ode_solver_param.n_rk_stages;
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) {
305 pcout <<
"Error: RRK is not valid for Forward Euler. Aborting..." << std::endl;
308 }
else return std::make_shared<EulerExplicit<dim, real, MeshType>> (n_rk_stages,
"Forward Euler (explicit)");
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)");
315 const int num_delta = dg_input->all_parameters->ode_solver_param.num_delta;
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");
322 pcout <<
"Error: invalid RK method. Aborting..." << std::endl;
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,
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;
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 ) )
341 return std::make_shared<RKNumEntropy<dim,nspecies,real,MeshType>>(rk_tableau_butcher);
343 else if (dg_input->all_parameters->ode_solver_param.use_relaxation_runge_kutta){
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;
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";
361 pcout <<
"PDE type has no assigned numerical entropy variable. Aborting..." << std::endl;
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);
372 return std::make_shared<EmptyRRKBase<dim,nspecies,real,MeshType>> (rk_tableau_butcher);
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.
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.
ODESolverEnum
Types of ODE solver.
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.
Base class for storing the RK method.