[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
runge_kutta_store_entropy.cpp
1 #include "rrk_ode_solver_base.h"
2 #include "physics/euler.h"
3 #include "physics/physics_factory.h"
4 
5 namespace PHiLiP {
6 namespace ODE {
7 
8 template <int dim, typename real, typename MeshType>
10  std::shared_ptr<RKTableauBase<dim,real,MeshType>> rk_tableau_input)
11  : EmptyRRKBase<dim,real,MeshType>(rk_tableau_input)
12  , butcher_tableau(rk_tableau_input)
13  , n_rk_stages(butcher_tableau->n_rk_stages)
14  , mpi_communicator(MPI_COMM_WORLD)
15  , mpi_rank(dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD))
16  , pcout(std::cout, mpi_rank==0)
17 {
18  this->rk_stage_solution.resize(n_rk_stages);
19 
20 }
21 
22 template <int dim, typename real, typename MeshType>
23 void RKNumEntropy<dim,real,MeshType>::store_stage_solutions(const int istage, const dealii::LinearAlgebra::distributed::Vector<double> rk_stage_i)
24 {
25  //Store the solution value
26  //This function is called before rk_stage is modified to hold the time-derivative
27  this->rk_stage_solution[istage] = rk_stage_i;
28 }
29 
30 template <int dim, typename real, typename MeshType>
31 dealii::LinearAlgebra::distributed::Vector<double> RKNumEntropy<dim,real,MeshType>::compute_entropy_vars(const dealii::LinearAlgebra::distributed::Vector<double> &u,
32  std::shared_ptr<DGBase<dim,real,MeshType>> dg) const
33 {
34  // hard-code nstate for Euler/NS - ODESolverFactory has already ensured that we use Euler/NS
35  const unsigned int nstate = dim + 2;
36  // Currently only implemented for constant p
37  const unsigned int poly_degree = dg->get_max_fe_degree();
38  if (poly_degree != dg->get_min_fe_degree()){
39  this->pcout << "Error: Entropy RRK is only implemented for uniform p. Aborting..." << std::endl;
40  std::abort();
41  }
42 
43  // Select Euler physics. ODESolverFactory has already ensured that we are using Euler orSelect Euler physics. ODESolverFactory has already ensured that we are using Euler or NS, which both use the same entropy variable computation.
44  PHiLiP::Parameters::AllParameters parameters_using_euler_pde_type = *(dg->all_parameters);
45  parameters_using_euler_pde_type.pde_type = Parameters::AllParameters::PartialDifferentialEquation::euler;
46  std::shared_ptr < Physics::Euler<dim, dim+2, double > > euler_physics = std::dynamic_pointer_cast<Physics::Euler<dim,dim+2,double>>(
47  Physics::PhysicsFactory<dim,dim+2,double>::create_Physics(&parameters_using_euler_pde_type));
48 
49  const unsigned int n_dofs_cell = dg->fe_collection[poly_degree].dofs_per_cell;
50  const unsigned int n_quad_pts = dg->volume_quadrature_collection[poly_degree].size();
51  const unsigned int n_shape_fns = n_dofs_cell / nstate;
52  //We have to project the vector of entropy variables because the mass matrix has an interpolation from solution nodes built into it.
53  OPERATOR::vol_projection_operator<dim,2*dim,double> vol_projection(1, poly_degree, dg->max_grid_degree);
54  vol_projection.build_1D_volume_operator(dg->oneD_fe_collection_1state[poly_degree], dg->oneD_quadrature_collection[poly_degree]);
55 
56  OPERATOR::basis_functions<dim,2*dim,double> soln_basis(1, poly_degree, dg->max_grid_degree);
57  soln_basis.build_1D_volume_operator(dg->oneD_fe_collection_1state[poly_degree], dg->oneD_quadrature_collection[poly_degree]);
58 
59  dealii::LinearAlgebra::distributed::Vector<double> entropy_var_hat_global(dg->right_hand_side);
60  std::vector<dealii::types::global_dof_index> dofs_indices (n_dofs_cell);
61 
62  for (auto cell = dg->dof_handler.begin_active(); cell!=dg->dof_handler.end(); ++cell) {
63  if (!cell->is_locally_owned()) continue;
64  cell->get_dof_indices (dofs_indices);
65 
66  std::array<std::vector<double>,nstate> soln_coeff;
67  for(unsigned int idof=0; idof<n_dofs_cell; idof++){
68  const unsigned int istate = dg->fe_collection[poly_degree].system_to_component_index(idof).first;
69  const unsigned int ishape = dg->fe_collection[poly_degree].system_to_component_index(idof).second;
70  if(ishape == 0)
71  soln_coeff[istate].resize(n_shape_fns);
72  soln_coeff[istate][ishape] = u(dofs_indices[idof]);
73  }
74 
75  std::array<std::vector<double>,nstate> soln_at_q;
76  for(unsigned int istate=0; istate<nstate; istate++){
77  soln_at_q[istate].resize(n_quad_pts);
78  soln_basis.matrix_vector_mult_1D(soln_coeff[istate], soln_at_q[istate],
79  soln_basis.oneD_vol_operator);
80  }
81  std::array<std::vector<double>,nstate> entropy_var_at_q;
82  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
83  std::array<double,nstate> soln_state;
84  for(unsigned int istate=0; istate<nstate; istate++){
85  soln_state[istate] = soln_at_q[istate][iquad];
86  }
87 
88  std::array<double,nstate> entropy_var = euler_physics->compute_entropy_variables(soln_state);
89 
90  for(unsigned int istate=0; istate<nstate; istate++){
91  if(iquad==0)
92  entropy_var_at_q[istate].resize(n_quad_pts);
93  entropy_var_at_q[istate][iquad] = entropy_var[istate];
94  }
95  }
96  for(unsigned int istate=0; istate<nstate; istate++){
97  //Projected vector of entropy variables.
98  std::vector<double> entropy_var_hat(n_shape_fns);
99  vol_projection.matrix_vector_mult_1D(entropy_var_at_q[istate], entropy_var_hat,
100  vol_projection.oneD_vol_operator);
101 
102  for(unsigned int ishape=0; ishape<n_shape_fns; ishape++){
103  const unsigned int idof = istate * n_shape_fns + ishape;
104  entropy_var_hat_global[dofs_indices[idof]] = entropy_var_hat[ishape];
105  }
106  }
107  }
108  return entropy_var_hat_global;
109 }
110 
111 
112 template <int dim, typename real, typename MeshType>
114  std::shared_ptr<DGBase<dim,real,MeshType>> dg,
115  const std::vector<dealii::LinearAlgebra::distributed::Vector<double>> &rk_stage,
116  const bool compute_K_norm) const
117 {
118  double entropy_contribution = 0;
119 
120  for (int istage = 0; istage<n_rk_stages; ++istage){
121 
122  // Recall rk_stage is IMM * RHS
123  // therefore, RHS = M * rk_stage = M * du/dt
124  dealii::LinearAlgebra::distributed::Vector<double> M_matrix_times_rk_stage(dg->solution);
125  dealii::LinearAlgebra::distributed::Vector<double> MpK_matrix_times_rk_stage(dg->solution);
126  if(dg->all_parameters->use_inverse_mass_on_the_fly)
127  {
128  dg->apply_global_mass_matrix(rk_stage[istage],M_matrix_times_rk_stage,
129  false, // use_auxiliary_eq,
130  true // use M norm
131  );
132 
133  dg->apply_global_mass_matrix(rk_stage[istage],MpK_matrix_times_rk_stage,
134  false, // use_auxiliary_eq,
135  false // use M+K norm
136  );
137  } else {
138  this->pcout << "ERROR: FR Numerical entropy estimate currently not compatible with use_inverse_mass_matrix = false. Please modify params." << std::endl;
139  std::abort();
140  }
141 
142  // transform solution into entropy variables based on PDE type
144  dealii::LinearAlgebra::distributed::Vector<double> entropy_var_hat_global=0;
145  if (dg->all_parameters->pde_type == PDEEnum::burgers_inviscid){
146  entropy_var_hat_global = this->rk_stage_solution[istage];
147  } else if (dg->all_parameters->pde_type == PDEEnum::euler || dg->all_parameters->pde_type == PDEEnum::navier_stokes) {
148  entropy_var_hat_global = this->compute_entropy_vars(this->rk_stage_solution[istage], dg);
149  } else {
150  this->pcout << "ERROR: Cannot store FR-corrected numerical entropy for this PDE type. Aborting..." << std::endl;
151  std::abort();
152  }
153 
154  double entropy_contribution_stage = 0;
155  if (compute_K_norm) {
156  entropy_contribution_stage = entropy_var_hat_global * MpK_matrix_times_rk_stage - entropy_var_hat_global * M_matrix_times_rk_stage;
157  }else {
158  entropy_contribution_stage = entropy_var_hat_global * M_matrix_times_rk_stage;
159  }
160 
161  entropy_contribution += this->butcher_tableau->get_b(istage) * entropy_contribution_stage;
162  }
163 
164  entropy_contribution *= dt;
165 
166  return entropy_contribution;
167 }
168 
171 #if PHILIP_DIM != 1
173 #endif
174 
175 } // ODESolver namespace
176 } // PHiLiP namespace
const int n_rk_stages
Number of RK stages.
PartialDifferentialEquation pde_type
Store the PDE type to be solved.
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1082
dealii::LinearAlgebra::distributed::Vector< double > compute_entropy_vars(const dealii::LinearAlgebra::distributed::Vector< double > &u, std::shared_ptr< DGBase< dim, real, MeshType >> dg) const
Return the entropy variables from a solution vector u.
real compute_FR_entropy_contribution(const real dt, std::shared_ptr< DGBase< dim, real, MeshType >> dg, const std::vector< dealii::LinearAlgebra::distributed::Vector< double >> &rk_stage, const bool compute_K_norm) const override
Calculate FR entropy adjustment.
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1732
PartialDifferentialEquation
Possible Partial Differential Equations to solve.
Files for the baseline physics.
Definition: ADTypes.hpp:10
void store_stage_solutions(const int istage, const dealii::LinearAlgebra::distributed::Vector< double > rk_stage_i) override
Update stored quantities at the current stage.
Main parameter class that contains the various other sub-parameter classes.
dealii::ConditionalOStream pcout
Parallel std::cout that only outputs on mpi_rank==0.
RKNumEntropy(std::shared_ptr< RKTableauBase< dim, real, MeshType >> rk_tableau_input)
Default constructor that will set the constants.
Euler equations. Derived from PhysicsBase.
Definition: euler.h:78
dealii::FullMatrix< double > oneD_vol_operator
Stores the one dimensional volume operator.
Definition: operators.h:355
static std::shared_ptr< PhysicsBase< dim, nstate, real > > create_Physics(const Parameters::AllParameters *const parameters_input, std::shared_ptr< ModelBase< dim, nstate, real > > model_input=nullptr)
Factory to return the correct physics given input file.
Base class for storing the RK method.
DGBase is independent of the number of state variables.
Definition: dg_base.hpp:82
std::vector< dealii::LinearAlgebra::distributed::Vector< double > > rk_stage_solution
Storage for the solution at each Runge-Kutta stage.
std::shared_ptr< RKTableauBase< dim, real, MeshType > > butcher_tableau
Store pointer to RK tableau.
void matrix_vector_mult_1D(const std::vector< real > &input_vect, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis_x, const bool adding=false, const double factor=1.0)
Apply the matrix vector operation using the 1D operator in each direction.
Definition: operators.cpp:308
Projection operator corresponding to basis functions onto M-norm (L2).
Definition: operators.h:694