4 #include <deal.II/base/convergence_table.h> 5 #include <deal.II/fe/fe_values.h> 7 #include "euler_gaussian_bump.h" 9 #include "physics/initial_conditions/initial_condition_function.h" 10 #include "physics/euler.h" 12 #include "flow_solver/flow_solver_factory.h" 18 template <
int dim,
int nstate>
21 const dealii::ParameterHandler ¶meter_handler_input)
24 , parameter_handler(parameter_handler_input)
27 template<
int dim,
int nstate>
31 int convergence_order_achieved = 0;
33 if (abs(run_test_output) > 1e-15)
35 convergence_order_achieved = 1;
37 return convergence_order_achieved;
40 template<
int dim,
int nstate>
45 using GridEnum = ManParam::GridEnum;
49 Assert(dim == 2, dealii::ExcDimensionMismatch(dim, param.
dimension));
55 const unsigned int p_start = manu_grid_conv_param.
degree_start;
56 const unsigned int p_end = manu_grid_conv_param.degree_end;
58 const unsigned int n_grids = manu_grid_conv_param.number_of_grids;
64 param.euler_param.gamma_gas,
69 std::string error_string;
70 bool has_residual_converged =
true;
71 double artificial_dissipation_max_coeff = 0.0;
73 std::vector<int> fail_conv_poly;
74 std::vector<double> fail_conv_slop;
75 std::vector<dealii::ConvergenceTable> convergence_table_vector;
77 for (
unsigned int poly_degree = p_start; poly_degree <= p_end; ++poly_degree) {
80 std::vector<double> error(n_grids);
81 std::vector<double> grid_size(n_grids);
83 dealii::ConvergenceTable convergence_table;
86 param.flow_solver_param.number_of_subdivisions_in_x_direction = n_1d_cells[0] * 4;
87 param.flow_solver_param.number_of_subdivisions_in_y_direction = n_1d_cells[0];
89 for (
unsigned int igrid=0; igrid<n_grids; ++igrid) {
91 const double solution_degree = poly_degree;
92 const double grid_degree = solution_degree+1;
94 param.flow_solver_param.poly_degree = solution_degree;
95 param.flow_solver_param.max_poly_degree_for_adaptation = solution_degree;
96 param.flow_solver_param.grid_degree = grid_degree;
97 param.flow_solver_param.number_of_mesh_refinements = igrid;
99 pcout <<
"\n" <<
"************************************" <<
"\n" <<
"POLYNOMIAL DEGREE " << solution_degree
100 <<
", GRID NUMBER " << (igrid+1) <<
"/" << n_grids <<
"\n" <<
"************************************" << std::endl;
102 pcout <<
"\n" <<
"Creating FlowSolver" << std::endl;
109 int overintegrate = 10;
110 dealii::QGauss<dim> quad_extra(flow_solver->dg->max_degree+1+overintegrate);
111 const dealii::Mapping<dim> &mapping = (*(flow_solver->dg->high_order_grid->mapping_fe_field));
112 dealii::FEValues<dim,dim> fe_values_extra(mapping, flow_solver->dg->fe_collection[poly_degree], quad_extra,
113 dealii::update_values | dealii::update_JxW_values | dealii::update_quadrature_points);
114 const unsigned int n_quad_pts = fe_values_extra.n_quadrature_points;
115 std::array<double,nstate> soln_at_q;
119 std::vector<dealii::types::global_dof_index> dofs_indices (fe_values_extra.dofs_per_cell);
122 for (
auto cell = flow_solver->dg->dof_handler.begin_active(); cell!=flow_solver->dg->dof_handler.end(); ++cell) {
124 if (!cell->is_locally_owned())
continue;
125 fe_values_extra.reinit (cell);
126 cell->get_dof_indices (dofs_indices);
128 for (
unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
130 std::fill(soln_at_q.begin(), soln_at_q.end(), 0);
131 for (
unsigned int idof=0; idof<fe_values_extra.dofs_per_cell; ++idof) {
132 const unsigned int istate = fe_values_extra.get_fe().system_to_component_index(idof).first;
133 soln_at_q[istate] += flow_solver->dg->solution[dofs_indices[idof]] * fe_values_extra.shape_value_component(idof, iquad, istate);
136 double unumerical, uexact;
137 if(param.artificial_dissipation_param.use_enthalpy_error)
139 error_string =
"L2_enthalpy_error";
146 error_string =
"L2_entropy_error";
147 const double entropy_inf = euler_physics_double.
entropy_inf;
149 uexact = entropy_inf;
151 l2error += pow(unumerical - uexact, 2) * fe_values_extra.JxW(iquad);
154 const double l2error_mpi_sum = std::sqrt(dealii::Utilities::MPI::sum(l2error,
mpi_communicator));
155 last_error = l2error_mpi_sum;
157 const unsigned int n_dofs = flow_solver->dg->dof_handler.n_dofs();
158 const unsigned int n_global_active_cells = flow_solver->dg->triangulation->n_global_active_cells();
161 double dx = 1.0/pow(n_dofs,(1.0/dim));
162 grid_size[igrid] = dx;
163 error[igrid] = l2error_mpi_sum;
165 convergence_table.add_value(
"p", poly_degree);
166 convergence_table.add_value(
"cells", n_global_active_cells);
167 convergence_table.add_value(
"DoFs", n_dofs);
168 convergence_table.add_value(
"dx", dx);
169 convergence_table.add_value(error_string, l2error_mpi_sum);
170 convergence_table.add_value(
"Residual",flow_solver->ode_solver->residual_norm);
172 if(flow_solver->ode_solver->residual_norm > 1e-10)
174 has_residual_converged =
false;
177 artificial_dissipation_max_coeff = flow_solver->dg->max_artificial_dissipation_coeff;
179 pcout <<
" Grid size h: " << dx
180 <<
" L2-error: " << l2error_mpi_sum
181 <<
" Residual: " << flow_solver->ode_solver->residual_norm
185 const double slope_soln_err = log(error[igrid]/error[igrid-1])
186 / log(grid_size[igrid]/grid_size[igrid-1]);
187 pcout <<
"From grid " << igrid-1
188 <<
" to grid " << igrid
189 <<
" dimension: " << dim
190 <<
" polynomial degree p: " << poly_degree
192 <<
" " << error_string << 1 <<
" " << error[igrid-1]
193 <<
" " << error_string << 2 <<
" " << error[igrid]
194 <<
" slope " << slope_soln_err
199 if (igrid == n_grids-1)
201 if (param.mesh_adaptation_param.total_mesh_adaptation_cycles > 0)
203 dealii::Point<dim> smallest_cell_coord = flow_solver->dg->coordinates_of_highest_refined_cell();
204 pcout<<
" x = "<<smallest_cell_coord[0]<<
" y = "<<smallest_cell_coord[1]<<std::endl;
206 if ((smallest_cell_coord[0] > 0.1) && (smallest_cell_coord[0] < 0.5) && (smallest_cell_coord[1] > 0.0) && (smallest_cell_coord[1] < 0.5))
208 pcout<<
"Mesh is refined near the shock. Test passed"<<std::endl;
215 pcout <<
" ********************************************" << std::endl
216 <<
" Convergence rates for p = " << poly_degree << std::endl
217 <<
" ********************************************" << std::endl;
218 convergence_table.evaluate_convergence_rates(error_string,
"cells", dealii::ConvergenceTable::reduction_rate_log2, dim);
219 convergence_table.set_scientific(
"dx",
true);
220 convergence_table.set_scientific(error_string,
true);
221 convergence_table.set_scientific(
"Residual",
true);
223 if (
pcout.is_active()) convergence_table.write_text(
pcout.get_stream());
225 convergence_table_vector.push_back(convergence_table);
227 const double expected_slope = poly_degree+1;
229 double last_slope = 0.0;
233 last_slope = log(error[n_grids-1]/error[n_grids-2]) / log(grid_size[n_grids-1]/grid_size[n_grids-2]);
236 const double slope_avg = last_slope;
237 const double slope_diff = slope_avg-expected_slope;
239 double slope_deficit_tolerance = -std::abs(manu_grid_conv_param.slope_deficit_tolerance);
240 if(poly_degree == 0) slope_deficit_tolerance *= 2;
242 if( (slope_diff < slope_deficit_tolerance) || (n_grids==1) ) {
244 <<
"Convergence order not achieved. Average last 2 slopes of " 245 << slope_avg <<
" instead of expected " 246 << expected_slope <<
" within a tolerance of " 247 << slope_deficit_tolerance
250 if(poly_degree!=0) fail_conv_poly.push_back(poly_degree);
251 if(poly_degree!=0) fail_conv_slop.push_back(slope_avg);
255 pcout << std::endl << std::endl << std::endl << std::endl;
256 pcout <<
" ********************************************" << std::endl;
257 pcout <<
" Convergence summary" << std::endl;
258 pcout <<
" ********************************************" << std::endl;
259 for (
auto conv = convergence_table_vector.begin(); conv!=convergence_table_vector.end(); conv++) {
260 if (
pcout.is_active()) conv->write_text(
pcout.get_stream());
261 pcout <<
" ********************************************" << std::endl;
266 artificial_dissipation_test_enum arti_dissipation_test_type = param.artificial_dissipation_param.artificial_dissipation_test_type;
267 if (arti_dissipation_test_type == artificial_dissipation_test_enum::residual_convergence)
269 if(has_residual_converged)
271 pcout << std::endl <<
"Residual has converged. Test Passed"<<std::endl;
274 pcout << std::endl<<
"Residual has not converged. Test failed" << std::endl;
277 else if (arti_dissipation_test_type == artificial_dissipation_test_enum::discontinuity_sensor_activation)
279 if(artificial_dissipation_max_coeff < 1e-10)
281 pcout << std::endl <<
"Discontinuity sensor is not activated. Max dissipation coeff = " <<artificial_dissipation_max_coeff <<
" Test passed"<<std::endl;
284 pcout << std::endl <<
"Discontinuity sensor has been activated. Max dissipation coeff = " <<artificial_dissipation_max_coeff <<
" Test failed"<<std::endl;
287 else if (arti_dissipation_test_type == artificial_dissipation_test_enum::enthalpy_conservation)
294 int n_fail_poly = fail_conv_poly.size();
297 for (
int ifail=0; ifail < n_fail_poly; ++ifail)
299 const double expected_slope = fail_conv_poly[ifail]+1;
300 const double slope_deficit_tolerance = -0.1;
302 <<
"Convergence order not achieved for polynomial p = " 303 << fail_conv_poly[ifail]
305 << fail_conv_slop[ifail] <<
" instead of expected " 306 << expected_slope <<
" within a tolerance of " 307 << slope_deficit_tolerance
unsigned int degree_start
First polynomial degree to start the loop. If diffusion, must be at least 1.
Performs grid convergence for various polynomial degrees.
const double mach_inf
Farfield Mach number.
const double angle_of_attack
Angle of attack.
Parameters related to the manufactured convergence study.
const double gam
Constant heat capacity ratio of fluid.
const MPI_Comm mpi_communicator
MPI communicator.
ArtificialDissipationTestType
Specified choices of dissipation test types.
EulerGaussianBump()=delete
Constructor. Deleted the default constructor since it should not be used.
const double gamm1
Constant heat capacity ratio (Gamma-1.0) used often.
int run_test() const
Grid convergence on Euler Gaussian Bump.
Files for the baseline physics.
const double side_slip_angle
Sideslip angle.
unsigned int dimension
Number of dimensions. Note that it has to match the executable PHiLiP_xD.
Main parameter class that contains the various other sub-parameter classes.
ManufacturedConvergenceStudyParam manufactured_convergence_study_param
Contains parameters for manufactured convergence study.
static std::unique_ptr< FlowSolver< dim, nstate > > select_flow_case(const Parameters::AllParameters *const parameters_input, const dealii::ParameterHandler ¶meter_handler_input)
Factory to return the correct flow solver given input file.
const Parameters::AllParameters *const all_parameters
Pointer to all parameters.
const double entropy_inf
Entropy measure at infinity.
double run_euler_gaussian_bump() const
Returns either the order of convergence or enthalpy, depending on the test type.
real2 compute_pressure(const std::array< real2, nstate > &conservative_soln) const
Evaluate pressure from conservative variables.
real compute_specific_enthalpy(const std::array< real, nstate > &conservative_soln, const real pressure) const
Evaluate pressure from conservative variables.
const dealii::ParameterHandler & parameter_handler
Parameter handler for storing the .prm file being ran.
dealii::ConditionalOStream pcout
ConditionalOStream.
std::vector< int > get_number_1d_cells(const int ngrids) const
Evaluates the number of cells to generate the grids for 1D grid based on input file.
const double ref_length
Reference length.
const double pressure_inf
Non-dimensionalized pressure* at infinity.
const double mach_inf_sqr
Base class of all the tests.
real compute_entropy_measure(const std::array< real, nstate > &conservative_soln) const
Evaluate entropy from conservative variables.