Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Low storage runge kutta #259

Draft
wants to merge 26 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4f19280
First commit of new Low Storage RK ODESolver. [Does not compile]
jocelynpoon Jun 12, 2024
93f71f1
low storage test
jocelynpoon Jun 12, 2024
01d72b3
compiles
jocelynpoon Jun 12, 2024
ca60d55
this works
jocelynpoon Jun 12, 2024
555565c
compiles
jocelynpoon Jun 13, 2024
8cb35d8
compiles but time step does not change as expected
jocelynpoon Jun 13, 2024
303cbf6
fixed w term need to fix dt
jocelynpoon Jun 13, 2024
d858fe7
this runs
jocelynpoon Jun 14, 2024
35170cc
step size change
jocelynpoon Jun 17, 2024
15ad87c
save
jocelynpoon Jun 25, 2024
820d80c
works with mpi > 1
jocelynpoon Jun 25, 2024
e758b4a
update
jocelynpoon Jun 26, 2024
ee073a4
add test euler inviscid tgv largest stable cfl
jocelynpoon Jun 27, 2024
7acd254
add 3s*+ method and RK3(2)5F[3S*+]
jocelynpoon Jul 2, 2024
40d4e00
low storage algorithms, need to fix coefficients for RK3_2_5F_3SStarPlus
jocelynpoon Jul 3, 2024
659719b
correct convergence for both algorithms (3S* and 3S*+)
jocelynpoon Jul 3, 2024
4a99eac
add tolerances as parameters
jocelynpoon Jul 5, 2024
ac2b446
tolerance parameters work
jocelynpoon Jul 8, 2024
8836f90
documentation and basic changes
jocelynpoon Jul 15, 2024
fa1c9ce
move code around
jocelynpoon Jul 22, 2024
ea7cc56
clean up code
jocelynpoon Jul 23, 2024
c633755
add code for automatic initial step size
jocelynpoon Jul 24, 2024
59f3165
update to automatic initial time step, add ode_output param
jocelynpoon Jul 25, 2024
940d163
add tolerance and beta parameters to own lsrk parameter subsection
jocelynpoon Jul 30, 2024
26efcdf
Add RK4(3)9F[3S*+] method
jocelynpoon Aug 5, 2024
48d3ff6
add RK5_4_10F_3SStarPlus scheme
jocelynpoon Aug 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ tests/integration_tests_control_files/decaying_homogeneous_isotropic_turbulence/
tests/integration_tests_control_files/decaying_homogeneous_isotropic_turbulence/setup_files/4proc/*.dat
tests/unit_tests/grid/gmsh_reader/*.msh
tests/meshes/*.msh
*.vscode
13 changes: 10 additions & 3 deletions src/flow_solver/flow_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,9 @@ int FlowSolver<dim,nstate>::run() const
if(flow_solver_param.adaptive_time_step == true) {
pcout << "Setting initial adaptive time step... " << std::flush;
time_step = flow_solver_case->get_adaptive_time_step_initial(dg);
} else if(flow_solver_param.error_adaptive_time_step == true) {
pcout << "Setting initial error adaptive time step... " << std::flush;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! The organization looks good.

time_step = ode_solver->get_automatic_initial_step_size(time_step,false);
} else {
pcout << "Setting constant time step... " << std::flush;
time_step = flow_solver_case->get_constant_time_step(dg);
Expand Down Expand Up @@ -500,19 +503,23 @@ int FlowSolver<dim,nstate>::run() const
}

// update time step in flow_solver_case
flow_solver_case->set_time_step(time_step);

ode_solver->step_in_time(time_step,false);
// advance solution
ode_solver->step_in_time(time_step,false); // pseudotime==false

// Compute the unsteady quantities, write to the dealii table, and output to file
flow_solver_case->compute_unsteady_data_and_write_to_table(ode_solver, dg, unsteady_data_table);
// update next time step

if(flow_solver_param.adaptive_time_step == true) {
cpethrick marked this conversation as resolved.
Show resolved Hide resolved
next_time_step = flow_solver_case->get_adaptive_time_step(dg);
} else if (flow_solver_param.error_adaptive_time_step == true) {
next_time_step = ode_solver->get_automatic_error_adaptive_step_size(time_step,false);
} else {
next_time_step = flow_solver_case->get_constant_time_step(dg);
}



#if PHILIP_DIM>1
if(flow_solver_param.output_restart_files == true) {
Expand Down
12 changes: 10 additions & 2 deletions src/flow_solver/flow_solver_cases/periodic_turbulence.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "periodic_turbulence.h"

#include "ode_solver/low_storage_runge_kutta_ode_solver.h"
#include <deal.II/base/function.h>
#include <stdlib.h>
#include <iostream>
Expand Down Expand Up @@ -329,6 +329,9 @@ void PeriodicTurbulence<dim, nstate>::compute_and_update_integrated_quantities(D
// Initialize the maximum local wave speed to zero; only used for adaptive time step
if(this->all_param.flow_solver_param.adaptive_time_step == true) this->maximum_local_wave_speed = 0.0;

// Initialize the maximum local wave speed to zero; only used for adaptive time step
if(this->all_param.flow_solver_param.error_adaptive_time_step == true) this->maximum_local_wave_speed = 0.0;

// Overintegrate the error to make sure there is not integration error in the error estimate
int overintegrate = 10;

Expand Down Expand Up @@ -471,6 +474,12 @@ void PeriodicTurbulence<dim, nstate>::compute_and_update_integrated_quantities(D
const double local_wave_speed = this->navier_stokes_physics->max_convective_eigenvalue(soln_at_q);
if(local_wave_speed > this->maximum_local_wave_speed) this->maximum_local_wave_speed = local_wave_speed;
}

// Update the maximum local wave speed (i.e. convective eigenvalue) if using an adaptive time step
if(this->all_param.flow_solver_param.error_adaptive_time_step == true) {
const double local_wave_speed = this->navier_stokes_physics->max_convective_eigenvalue(soln_at_q);
if(local_wave_speed > this->maximum_local_wave_speed) this->maximum_local_wave_speed = local_wave_speed;
}
}
}
this->maximum_local_wave_speed = dealii::Utilities::MPI::max(this->maximum_local_wave_speed, this->mpi_communicator);
Expand Down Expand Up @@ -686,7 +695,6 @@ void PeriodicTurbulence<dim, nstate>::compute_unsteady_data_and_write_to_table(
//unpack current iteration and current time from ode solver
const unsigned int current_iteration = ode_solver->current_iteration;
const double current_time = ode_solver->current_time;

// Compute and update integrated quantities
this->compute_and_update_integrated_quantities(*dg);
// Get computed quantities
Expand Down
3 changes: 3 additions & 0 deletions src/ode_solver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ set(ODE_SOURCE
ode_solver_factory.cpp
ode_solver_base.cpp
runge_kutta_ode_solver.cpp
low_storage_runge_kutta_ode_solver.cpp
runge_kutta_methods/runge_kutta_methods.cpp
runge_kutta_methods/rk_tableau_base.cpp
runge_kutta_methods/low_storage_rk_tableau_base.cpp
runge_kutta_methods/low_storage_runge_kutta_methods.cpp
relaxation_runge_kutta/empty_RRK_base.cpp
relaxation_runge_kutta/runge_kutta_store_entropy.cpp
relaxation_runge_kutta/rrk_ode_solver_base.cpp
Expand Down
271 changes: 271 additions & 0 deletions src/ode_solver/low_storage_runge_kutta_ode_solver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
#include "low_storage_runge_kutta_ode_solver.h"

namespace PHiLiP {
namespace ODE {

template <int dim, typename real, int n_rk_stages, typename MeshType>
LowStorageRungeKuttaODESolver<dim,real,n_rk_stages, MeshType>::LowStorageRungeKuttaODESolver(std::shared_ptr< DGBase<dim, real, MeshType> > dg_input,
std::shared_ptr<LowStorageRKTableauBase<dim,real,MeshType>> rk_tableau_input,
std::shared_ptr<EmptyRRKBase<dim,real,MeshType>> RRK_object_input)
: ODESolverBase<dim,real,MeshType>(dg_input)
, butcher_tableau(rk_tableau_input)
, relaxation_runge_kutta(RRK_object_input)
{ epsilon[0] = 1.0;
epsilon[1] = 1.0;
epsilon[2] = 1.0;
}

template <int dim, typename real, int n_rk_stages, typename MeshType>
void LowStorageRungeKuttaODESolver<dim,real,n_rk_stages, MeshType>::step_in_time (real dt, const bool /*pseudotime*/)
{
this->original_time_step = dt;
this->solution_update = this->dg->solution; //storing u_n
double sum_delta = 0.0;

storage_register_1.reinit(this->solution_update);
storage_register_2.reinit(this->solution_update);
storage_register_1 = this->dg->solution;
storage_register_2 *= 0;
storage_register_3 = storage_register_1;
rhs = storage_register_1;
if (is_3Sstarplus == true){
storage_register_4 = storage_register_1;
}

for (int i = 1; i < n_rk_stages +1; i++ ){
storage_register_2.add(this->butcher_tableau->get_delta(i-1) , storage_register_1);
this->dg->solution = rhs;
cpethrick marked this conversation as resolved.
Show resolved Hide resolved

// Apply limiter at every RK stage
if (this->limiter) {
this->limiter->limit(this->dg->solution,
this->dg->dof_handler,
this->dg->fe_collection,
this->dg->volume_quadrature_collection,
this->dg->high_order_grid->fe_system.tensor_degree(),
this->dg->max_degree,
this->dg->oneD_fe_collection_1state,
this->dg->oneD_quadrature_collection);
}
this->dg->assemble_residual();
this->dg->apply_inverse_global_mass_matrix(this->dg->right_hand_side, rhs);
storage_register_1 *= this->butcher_tableau->get_gamma(i, 0);
storage_register_1.add(this->butcher_tableau->get_gamma(i, 1), storage_register_2);
storage_register_1.add(this->butcher_tableau->get_gamma(i, 2), storage_register_3);
rhs *= dt;
storage_register_1.add(this->butcher_tableau->get_beta(i), rhs);
if (is_3Sstarplus == true){
storage_register_4.add(this->butcher_tableau->get_b_hat(i-1), rhs);
}
rhs = storage_register_1;
}

if (is_3Sstarplus == false){
for (int i = 0; i < num_delta; i++){
sum_delta = sum_delta + this->butcher_tableau->get_delta(i);
}
storage_register_2.add(this->butcher_tableau->get_delta(n_rk_stages), storage_register_1);
storage_register_2.add(this->butcher_tableau->get_delta(n_rk_stages+1), storage_register_3);
storage_register_2 /= sum_delta;
}
else if (is_3Sstarplus == true){
this->dg->solution = rhs;
// Apply limiter at every RK stage
if (this->limiter) {
this->limiter->limit(this->dg->solution,
this->dg->dof_handler,
this->dg->fe_collection,
this->dg->volume_quadrature_collection,
this->dg->high_order_grid->fe_system.tensor_degree(),
this->dg->max_degree,
this->dg->oneD_fe_collection_1state,
this->dg->oneD_quadrature_collection);
}
this->dg->assemble_residual();
this->dg->apply_inverse_global_mass_matrix(this->dg->right_hand_side, rhs);
rhs *= dt;
storage_register_4.add(this->butcher_tableau->get_b_hat(n_rk_stages), rhs);

}
this->dg->solution = storage_register_1;

// Apply limiter at every RK stage
if (this->limiter) {
this->limiter->limit(this->dg->solution,
this->dg->dof_handler,
this->dg->fe_collection,
this->dg->volume_quadrature_collection,
this->dg->high_order_grid->fe_system.tensor_degree(),
this->dg->max_degree,
this->dg->oneD_fe_collection_1state,
this->dg->oneD_quadrature_collection);
}

if ((this->ode_param.ode_output) == Parameters::OutputEnum::verbose &&
(this->current_iteration%this->ode_param.print_iteration_modulo) == 0 ) {
this->pcout << " Evaluating system update... " << std::endl;
}

this->pcout << std::endl;
++(this->current_iteration);
this->current_time += dt;
this->pcout << " Time is: " << this->current_time <<std::endl;
this->pcout << std::endl;
}

template <int dim, typename real, int n_rk_stages, typename MeshType>
double LowStorageRungeKuttaODESolver<dim,real,n_rk_stages, MeshType>::get_automatic_error_adaptive_step_size (real dt, const bool /*pseudotime*/)
{
double error = 0.0;
w = 0.0;

// error based step size
if (is_3Sstarplus == false){
// loop sums elements at each mpi processor
for (dealii::LinearAlgebra::distributed::Vector<double>::size_type i = 0; i < storage_register_1.local_size(); ++i) {
error = storage_register_1.local_element(i) - storage_register_2.local_element(i);
w = w + pow(error / (atol + rtol * std::max(std::abs(storage_register_1.local_element(i)), std::abs(storage_register_2.local_element(i)))), 2);
}
}
else if (is_3Sstarplus == true){
// loop sums elements at each mpi processor
for (dealii::LinearAlgebra::distributed::Vector<double>::size_type i = 0; i < storage_register_1.local_size(); ++i) {
error = storage_register_1.local_element(i) - storage_register_4.local_element(i);
w = w + pow(error / (atol + rtol * std::max(std::abs(storage_register_1.local_element(i)), std::abs(storage_register_4.local_element(i)))), 2);
}
}
this->pcout << std::endl;

// sum over all elements
w = dealii::Utilities::MPI::sum(w, this->mpi_communicator);
w = pow(w / global_size, 0.5);
epsilon[2] = epsilon[1];
epsilon[1] = epsilon[0];
epsilon[0] = 1.0 / w;
dt = pow(epsilon[0], 1.0 * beta1/rk_order) * pow(epsilon[1], 1.0 * beta2/rk_order) * pow(epsilon[2], 1.0 * beta3/rk_order) * dt;
return dt;
}

template <int dim, typename real, int n_rk_stages, typename MeshType>
double LowStorageRungeKuttaODESolver<dim,real,n_rk_stages, MeshType>::get_automatic_initial_step_size (real dt, const bool /*pseudotime*/)
{
// h will store the starting step size
double h0 = 0.0;
double h1 = 0.0;

// d estimates the derivate of the solution
double d0 = 0.0;
double d1 = 0.0;
double d2 = 0.0;

/// Storage of the solution to calculate the initial time step
dealii::LinearAlgebra::distributed::Vector<double> u_n;
dealii::LinearAlgebra::distributed::Vector<double> rhs_initial;

this->solution_update = this->dg->solution;
u_n.reinit(this->solution_update);
rhs_initial.reinit(this->solution_update);
storage_register_1.reinit(this->solution_update);
storage_register_1 = this->dg->solution;
u_n = storage_register_1;
rhs_initial = storage_register_1;

d0 = u_n.linfty_norm();

this->dg->solution = rhs_initial;
this->dg->assemble_residual();
this->dg->apply_inverse_global_mass_matrix(this->dg->right_hand_side, rhs_initial);

d1 = rhs_initial.linfty_norm();

if (d0 < pow(10, -5) || d1 < pow(10, -5)){
h0 = pow(10, -6);
}else{
h0 = 0.01 * d0 / d1;
}

u_n.add(h0, rhs_initial);
this->dg->solution = u_n;
this->dg->assemble_residual();
this->dg->apply_inverse_global_mass_matrix(this->dg->right_hand_side, u_n);

// Calculate d2
u_n.add(-1, rhs_initial);
d2 = u_n.linfty_norm();
d2 /= h0;

if (std::max(d1, d2) <= pow(10, -15))
{
h1 = std::max(pow(10, -6), pow(10, -3));
}
else
{
h1 = 0.01 / std::max(d1, d2);
}

dt = std::min(100 * h0, h1);
this->dg->solution = storage_register_1;
return dt;
}


template <int dim, typename real, int n_rk_stages, typename MeshType>
void LowStorageRungeKuttaODESolver<dim,real,n_rk_stages, MeshType>::allocate_ode_system ()
{
this->solution_update.reinit(this->dg->solution);
storage_register_1.reinit(this->solution_update);

atol = this->ode_param.atol;
rtol = this->ode_param.rtol;
rk_order = this->ode_param.rk_order;
is_3Sstarplus = this->ode_param.is_3Sstarplus;
num_delta = this->ode_param.num_delta;
beta1 = this->ode_param.beta1;
beta2 = this->ode_param.beta2;
beta3 = this->ode_param.beta3;

global_size = dealii::Utilities::MPI::sum(storage_register_1.local_size(), this->mpi_communicator);
this->pcout << "Allocating ODE system..." << std::flush;
this->solution_update.reinit(this->dg->right_hand_side);
if(this->all_parameters->use_inverse_mass_on_the_fly == false) {
this->pcout << " evaluating inverse mass matrix..." << std::flush;
this->dg->evaluate_mass_matrices(true); // creates and stores global inverse mass matrix
//RRK needs both mass matrix and inverse mass matrix
using ODEEnum = Parameters::ODESolverParam::ODESolverEnum;
ODEEnum ode_type = this->ode_param.ode_solver_type;
if (ode_type == ODEEnum::rrk_explicit_solver){
this->dg->evaluate_mass_matrices(false); // creates and stores global mass matrix
}
}

this->pcout << std::endl;

this->butcher_tableau->set_tableau();
}

template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,1, dealii::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,2, dealii::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,3, dealii::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,4, dealii::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,5, dealii::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,9, dealii::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,10, dealii::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,1, dealii::parallel::shared::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,2, dealii::parallel::shared::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,3, dealii::parallel::shared::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,4, dealii::parallel::shared::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,5, dealii::parallel::shared::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,9, dealii::parallel::shared::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,10, dealii::parallel::shared::Triangulation<PHILIP_DIM> >;
#if PHILIP_DIM != 1
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,1, dealii::parallel::distributed::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,2, dealii::parallel::distributed::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,3, dealii::parallel::distributed::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,4, dealii::parallel::distributed::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,5, dealii::parallel::distributed::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,9, dealii::parallel::distributed::Triangulation<PHILIP_DIM> >;
template class LowStorageRungeKuttaODESolver<PHILIP_DIM, double,10, dealii::parallel::distributed::Triangulation<PHILIP_DIM> >;
#endif

} // ODESolver namespace
} // PHiLiP namespace
Loading