1 #include <deal.II/base/tensor.h> 2 #include <deal.II/base/convergence_table.h> 4 #include "stability_fr_parameter_range.h" 5 #include "dg/dg_factory.hpp" 6 #include "ode_solver/ode_solver_base.h" 8 #include "ode_solver/ode_solver_factory.h" 9 #include "physics/initial_conditions/set_initial_condition.h" 10 #include "physics/initial_conditions/initial_condition_function.h" 11 #include "mesh/grids/straight_periodic_cube.hpp" 17 template <
int dim,
int nstate>
22 template<
int dim,
int nstate>
26 dealii::LinearAlgebra::distributed::Vector<double> mass_matrix_times_solution(dg->right_hand_side);
27 if(dg->all_parameters->use_inverse_mass_on_the_fly)
28 dg->apply_global_mass_matrix(dg->solution,mass_matrix_times_solution);
30 dg->global_mass_matrix.vmult( mass_matrix_times_solution, dg->solution);
33 energy = dg->solution * mass_matrix_times_solution;
38 template<
int dim,
int nstate>
42 double conservation = 0.0;
43 dealii::LinearAlgebra::distributed::Vector<double> mass_matrix_times_solution(dg->right_hand_side);
44 if(dg->all_parameters->use_inverse_mass_on_the_fly)
45 dg->apply_global_mass_matrix(dg->solution,mass_matrix_times_solution);
47 dg->global_mass_matrix.vmult( mass_matrix_times_solution, dg->solution);
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 std::vector<double> ones(n_quad_pts, 1.0);
53 std::vector<double> ones_hat(n_dofs_cell);
56 vol_projection.
build_1D_volume_operator(dg->oneD_fe_collection[poly_degree], dg->oneD_quadrature_collection[poly_degree]);
60 dealii::LinearAlgebra::distributed::Vector<double> ones_hat_global(dg->right_hand_side);
61 std::vector<dealii::types::global_dof_index> dofs_indices (n_dofs_cell);
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 for(
unsigned int idof=0;idof<n_dofs_cell; idof++){
66 ones_hat_global[dofs_indices[idof]] = ones_hat[idof];
70 conservation = ones_hat_global * mass_matrix_times_solution;
75 template <
int dim,
int nstate>
78 pcout <<
" Running stability ESFR parameter range test. " << std::endl;
85 std::vector<double> grid_size(n_grids);
86 std::vector<double> soln_error(n_grids);
87 std::vector<double> soln_error_inf(n_grids);
89 dealii::ConvergenceTable convergence_table;
91 pcout <<
" igrid_start" << igrid_start << std::endl;
92 const unsigned int grid_degree = 1;
97 const double log_c_min = std::log10(c_min);
98 const double log_c_max = std::log10(c_max);
99 std::vector<double> c_array(nb_c_value+1);
101 std::ofstream conv_tab_file;
102 const std::string fname =
"convergence_tables.txt";
103 conv_tab_file.open(fname);
106 for (
unsigned int ic = 0; ic < nb_c_value; ic++) {
107 double log_c = log_c_min + (log_c_max - log_c_min) / (nb_c_value - 1) * ic;
108 c_array[ic] = std::pow(10.0, log_c);
114 for (
unsigned int ic = 0; ic < nb_c_value+1; ic++) {
115 double c_value = c_array[ic];
117 for(
unsigned int igrid = igrid_start; igrid<n_grids; igrid++){
119 #if PHILIP_DIM==1 // dealii::parallel::distributed::Triangulation<dim> does not work for 1D 120 using Triangulation = dealii::Triangulation<dim>;
121 std::shared_ptr<Triangulation> grid = std::make_shared<Triangulation>(
122 typename dealii::Triangulation<dim>::MeshSmoothing(
123 dealii::Triangulation<dim>::smoothing_on_refinement |
124 dealii::Triangulation<dim>::smoothing_on_coarsening));
126 using Triangulation = dealii::parallel::distributed::Triangulation<dim>;
127 std::shared_ptr<Triangulation> grid = std::make_shared<Triangulation>(
129 typename dealii::Triangulation<dim>::MeshSmoothing(
130 dealii::Triangulation<dim>::smoothing_on_refinement |
131 dealii::Triangulation<dim>::smoothing_on_coarsening));
134 PHiLiP::Grids::straight_periodic_cube<dim, Triangulation>(grid, left, right, pow(2.0, igrid));
135 pcout <<
"Grid generated and refined" << std::endl;
144 pcout <<
"dg created" <<std::endl;
145 dg->allocate_system (
false,
false,
false);
148 pcout<<
"Setting up Initial Condition"<<std::endl;
150 std::shared_ptr< InitialConditionFunction<dim,nstate,double> > initial_condition_function =
160 ode_solver->current_iteration = 0;
162 ode_solver->advance_solution_time(finalTime);
163 const unsigned int n_global_active_cells = grid->n_global_active_cells();
164 const unsigned int n_dofs = dg->dof_handler.n_dofs();
165 pcout <<
"Dimension: " << dim
166 <<
"\t Polynomial degree p: " << poly_degree
168 <<
"Grid number: " << igrid+1 <<
"/" << n_grids
169 <<
". Number of active cells: " << n_global_active_cells
170 <<
". Number of degrees of freedom: " << n_dofs
174 int overintegrate = 10;
175 dealii::QGauss<dim> quad_extra(poly_degree+1+overintegrate);
176 dealii::FEValues<dim,dim> fe_values_extra(*(dg->high_order_grid->mapping_fe_field), dg->fe_collection[poly_degree], quad_extra,
177 dealii::update_values | dealii::update_JxW_values | dealii::update_quadrature_points);
178 const unsigned int n_quad_pts = fe_values_extra.n_quadrature_points;
179 std::array<double,nstate> soln_at_q;
181 double l2error = 0.0;
182 double linf_error = 0.0;
185 const double pi = atan(1)*4.0;
186 std::vector<dealii::types::global_dof_index> dofs_indices (fe_values_extra.dofs_per_cell);
187 for (
auto cell = dg->dof_handler.begin_active(); cell!=dg->dof_handler.end(); ++cell) {
189 if (!cell->is_locally_owned())
continue;
191 fe_values_extra.reinit (cell);
192 cell->get_dof_indices (dofs_indices);
194 for (
unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
196 std::fill(soln_at_q.begin(), soln_at_q.end(), 0.0);
197 for (
unsigned int idof=0; idof<fe_values_extra.dofs_per_cell; ++idof) {
198 const unsigned int istate = fe_values_extra.get_fe().system_to_component_index(idof).first;
199 soln_at_q[istate] += dg->solution[dofs_indices[idof]] * fe_values_extra.shape_value_component(idof, iquad, istate);
202 for (
int istate=0; istate<nstate; ++istate) {
204 const dealii::Point<dim> qpoint = (fe_values_extra.quadrature_point(iquad));
205 if (
all_parameters->
pde_type == PHiLiP::Parameters::AllParameters::PartialDifferentialEquation::burgers_inviscid){
206 for(
int idim=0; idim<dim; idim++){
207 uexact += cos(pi*(qpoint[idim]-finalTime));
210 else if (
all_parameters->
pde_type == PHiLiP::Parameters::AllParameters::PartialDifferentialEquation::advection){
213 for(
int idim=0; idim<dim; idim++){
215 uexact *= sin(2.0*pi*(qpoint[idim]-adv_speeds[idim]*finalTime));
218 uexact *= sin(pi*(qpoint[idim]- adv_speeds[idim]*finalTime));
222 l2error += pow(soln_at_q[istate] - uexact, 2) * fe_values_extra.JxW(iquad);
223 double inf_temp = std::abs(soln_at_q[istate]-uexact);
225 if(inf_temp > linf_error){
226 linf_error = inf_temp;
231 const double l2error_mpi_sum = std::sqrt(dealii::Utilities::MPI::sum(l2error,
mpi_communicator));
233 const double linferror_mpi= (dealii::Utilities::MPI::max(linf_error, this->
mpi_communicator));
236 const double dx = 1.0/pow(n_dofs,(1.0/dim));
237 grid_size[igrid] = dx;
238 soln_error[igrid] = l2error_mpi_sum;
239 soln_error_inf[igrid] = linferror_mpi;
242 double expected_order = poly_degree + 1;
247 const double order_tolerance = 1.0;
249 const double slope_soln_err = log(soln_error[igrid] / soln_error[igrid - 1])
250 / log(grid_size[igrid] / grid_size[igrid - 1]);
252 if (abs(slope_soln_err - expected_order) > order_tolerance){
254 pcout <<
"Expected convergence order was not reached at refinement " <<std::endl;
258 convergence_table.add_value(
"c", c_value);
259 convergence_table.add_value(
"p", poly_degree);
260 convergence_table.add_value(
"cells", n_global_active_cells);
261 convergence_table.add_value(
"DoFs", n_dofs);
262 convergence_table.add_value(
"dx", dx);
263 convergence_table.add_value(
"soln_L2_error", l2error_mpi_sum);
264 convergence_table.add_value(
"soln_Linf_error", linferror_mpi);
266 pcout <<
" Grid size h: " << dx
267 <<
" L2-soln_error: " << l2error_mpi_sum
268 <<
" Linf-soln_error: " << linferror_mpi
269 <<
" Residual: " << ode_solver->residual_norm
272 if (igrid > igrid_start) {
273 const double slope_soln_err = log(soln_error[igrid]/soln_error[igrid-1])
274 / log(grid_size[igrid]/grid_size[igrid-1]);
276 const double slope_soln_err_inf = log(soln_error_inf[igrid]/soln_error_inf[igrid-1])
277 / log(grid_size[igrid]/grid_size[igrid-1]);
278 pcout <<
"From grid " << igrid
279 <<
" to grid " << igrid+1
280 <<
" dimension: " << dim
281 <<
" polynomial degree p: " << poly_degree
283 <<
" solution_error1 " << soln_error[igrid-1]
284 <<
" solution_error2 " << soln_error[igrid]
285 <<
" slope " << slope_soln_err
286 <<
" solution_error1_inf " << soln_error_inf[igrid-1]
287 <<
" solution_error2_inf " << soln_error_inf[igrid]
288 <<
" slope " << slope_soln_err_inf
292 pcout <<
" ********************************************" 294 <<
" Convergence rates for p = " << poly_degree
296 <<
" ********************************************" 298 convergence_table.evaluate_convergence_rates(
"soln_L2_error",
"cells", dealii::ConvergenceTable::reduction_rate_log2, dim);
299 convergence_table.evaluate_convergence_rates(
"soln_Linf_error",
"cells", dealii::ConvergenceTable::reduction_rate_log2, dim);
300 convergence_table.set_scientific(
"c",
true);
301 convergence_table.set_scientific(
"dx",
true);
302 convergence_table.set_scientific(
"soln_L2_error",
true);
303 convergence_table.set_scientific(
"soln_Linf_error",
true);
304 if (
pcout.is_active()) convergence_table.write_text(
pcout.get_stream());
308 convergence_table.write_text(conv_tab_file);
309 convergence_table.clear();
311 conv_tab_file.close();
double final_time
Final solution time.
unsigned int degree_start
First polynomial degree to start the loop. If diffusion, must be at least 1.
PartialDifferentialEquation pde_type
Store the PDE type to be solved.
static dealii::Tensor< 1, 3, double > get_default_advection_vector()
gets the default advection vector
FlowSolverParam flow_solver_param
Contains the parameters for simulation cases (flow solver test)
int run_test() const override
Run test.
double ESFR_parameter_values_start
For user defined FR parameter tests, value of starting FR param.
const MPI_Comm mpi_communicator
MPI communicator.
StabilityFRParametersRange(const Parameters::AllParameters *const parameters_input)
Constructor.
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
int number_ESFR_parameter_values
For user defined FR parameter tests, number of values to be tested.
double ESFR_parameter_values_end
For user defined FR parameter tests, value of final FR param.
Files for the baseline physics.
Main parameter class that contains the various other sub-parameter classes.
double grid_left_bound
Left bound of domain for hyper_cube mesh based cases.
ManufacturedConvergenceStudyParam manufactured_convergence_study_param
Contains parameters for manufactured convergence study.
unsigned int initial_grid_size
const Parameters::AllParameters *const all_parameters
Pointer to all parameters.
static std::shared_ptr< DGBase< dim, real, MeshType > > create_discontinuous_galerkin(const Parameters::AllParameters *const parameters_input, const unsigned int degree, const unsigned int max_degree_input, const unsigned int grid_degree_input, const std::shared_ptr< Triangulation > triangulation_input)
Creates a derived object DG, but returns it as DGBase.
double FR_user_specified_correction_parameter_value
User specified flux recontruction correction parameter value.
Burgers' periodic unsteady test.
double compute_conservation(std::shared_ptr< PHiLiP::DGBase< dim, double > > &dg, const double poly_degree) const
Function computes the conservation.
dealii::FullMatrix< double > oneD_vol_operator
Stores the one dimensional volume operator.
dealii::ConditionalOStream pcout
ConditionalOStream.
double grid_right_bound
Right bound of domain for hyper_cube mesh based cases.
DGBase is independent of the number of state variables.
double compute_energy(std::shared_ptr< PHiLiP::DGBase< dim, double > > &dg) const
Function computes the energy.
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.
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) ...
Projection operator corresponding to basis functions onto M-norm (L2).
static void set_initial_condition(std::shared_ptr< InitialConditionFunction< dim, nstate, double > > initial_condition_function_input, std::shared_ptr< PHiLiP::DGBase< dim, real > > dg_input, const Parameters::AllParameters *const parameters_input)
Applies the given initial condition function to the given dg object.
Base class of all the tests.
static std::shared_ptr< InitialConditionFunction< dim, nstate, real > > create_InitialConditionFunction(Parameters::AllParameters const *const param)
Construct InitialConditionFunction object from global parameter file.
unsigned int number_of_grids
Number of grid in the grid study.