4 #include <deal.II/base/convergence_table.h> 6 #include <deal.II/dofs/dof_tools.h> 8 #include <deal.II/distributed/tria.h> 9 #include <deal.II/grid/tria.h> 11 #include <deal.II/grid/grid_generator.h> 12 #include <deal.II/grid/grid_refinement.h> 13 #include <deal.II/grid/grid_tools.h> 14 #include <deal.II/grid/grid_out.h> 15 #include <deal.II/grid/grid_in.h> 17 #include <deal.II/numerics/vector_tools.h> 19 #include <deal.II/fe/fe_values.h> 21 #include "ADTypes.hpp" 26 #include "physics/physics_factory.h" 27 #include "physics/manufactured_solution.h" 28 #include "dg/dg_factory.hpp" 29 #include "dg/weak_dg.hpp" 30 #include "ode_solver/ode_solver_factory.h" 39 template <
int dim,
typename real>
43 using dealii::Function<dim,real>::value;
44 using dealii::Function<dim,real>::gradient;
45 using dealii::Function<dim,real>::hessian;
46 using dealii::Function<dim,real>::vector_gradient;
62 virtual real
value (
const dealii::Point<dim,real> &point,
const unsigned int )
const override 66 for (
int d=0;d<dim;d++) {
77 virtual dealii::Tensor<1,dim,real>
gradient (
const dealii::Point<dim,real> &point,
const unsigned int )
const override 82 for (
int d=0;d<dim;d++) {
83 gradient[d] = cos(point[d]);
92 virtual dealii::SymmetricTensor<2,dim,real>
hessian (
const dealii::Point<dim,real> &point,
const unsigned int )
const override 94 dealii::SymmetricTensor<2,dim,real>
hessian;
97 for (
int d=0;d<dim;d++) {
98 hessian[d][d] = -sin(point[d]);
104 template <
int dim,
int nstate>
108 pcout <<
"Evaluating solution integral..." << std::endl;
109 double solution_integral = 0.0;
116 int overintegrate = 10;
117 dealii::QGauss<dim> quad_extra(dg.
max_degree+1+overintegrate);
120 dealii::update_values | dealii::update_JxW_values | dealii::update_quadrature_points);
121 const unsigned int n_quad_pts = fe_values_extra.n_quadrature_points;
122 std::array<double,nstate> soln_at_q;
124 const bool linear_output =
false;
126 if (linear_output) power = 1;
130 std::vector<dealii::types::global_dof_index> dofs_indices (fe_values_extra.dofs_per_cell);
131 for (
auto cell : dg.
dof_handler.active_cell_iterators()) {
133 if (!cell->is_locally_owned())
continue;
135 fe_values_extra.reinit (cell);
136 cell->get_dof_indices (dofs_indices);
138 for (
unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
141 std::fill(soln_at_q.begin(), soln_at_q.end(), 0.0);
142 for (
unsigned int idof=0; idof<fe_values_extra.dofs_per_cell; ++idof) {
143 const unsigned int istate = fe_values_extra.get_fe().system_to_component_index(idof).first;
144 soln_at_q[istate] += dg.
solution[dofs_indices[idof]] * fe_values_extra.shape_value_component(idof, iquad, istate);
147 for (
int s=0; s<
nstate; s++) {
148 solution_integral += pow(soln_at_q[0], power) * fe_values_extra.JxW(iquad);
153 const double solution_integral_mpi_sum = dealii::Utilities::MPI::sum(solution_integral, mpi_communicator);
154 return solution_integral_mpi_sum;
164 const double time = 0.)
165 : dealii::Function<dim>(n_components, time)
168 virtual double value(
const dealii::Point<dim> &p,
169 const unsigned int )
const override 171 const double PI = std::atan(1) * 4.0;
172 return std::sin(p[0]*2.0*PI);
176 template <
int dim,
int nstate>
182 template <
int dim,
int nstate>
186 dealii::LinearAlgebra::distributed::Vector<double> solution_no_ghost;
192 template<
int dim,
int nstate>
197 using Triangulation = dealii::Triangulation<dim>;
199 using Triangulation = dealii::parallel::distributed::Triangulation<dim>;
203 using GridEnum = ManParam::GridEnum;
212 const unsigned int p_start = manu_grid_conv_param.
degree_start;
213 const unsigned int p_end = manu_grid_conv_param.degree_end;
215 const unsigned int n_grids_input = manu_grid_conv_param.number_of_grids;
223 std::shared_ptr shocked_1d1state_double = std::make_shared < Shocked1D1State<dim,double> > (nstate);
224 std::shared_ptr shocked_1d1state_fad = std::make_shared < Shocked1D1State<dim,FadType> > (nstate);
225 std::shared_ptr shocked_1d1state_rad = std::make_shared < Shocked1D1State<dim,RadType> > (nstate);
226 std::shared_ptr shocked_1d1state_fad_fad = std::make_shared < Shocked1D1State<dim,FadFadType> > (nstate);
227 std::shared_ptr shocked_1d1state_rad_fad = std::make_shared < Shocked1D1State<dim,RadFadType> > (nstate);
228 physics_double->manufactured_solution_function = shocked_1d1state_double;
229 physics_fad->manufactured_solution_function = shocked_1d1state_fad;
230 physics_fad_fad->manufactured_solution_function = shocked_1d1state_fad_fad;
231 physics_rad_fad->manufactured_solution_function = shocked_1d1state_rad_fad;
234 double exact_solution_integral;
235 pcout <<
"Evaluating EXACT solution integral..." << std::endl;
239 std::shared_ptr<Triangulation> grid_super_fine = std::make_shared<Triangulation>(
243 typename dealii::Triangulation<dim>::MeshSmoothing(
244 dealii::Triangulation<dim>::smoothing_on_refinement |
245 dealii::Triangulation<dim>::smoothing_on_coarsening));
246 dealii::GridGenerator::subdivided_hyper_cube(*grid_super_fine, n_1d_cells[n_grids_input-1]);
247 std::shared_ptr dg_super_fine = std::make_shared< DGWeak<dim,1,double> > (¶m, p_end, p_end, p_end+1, grid_super_fine);
248 dg_super_fine->set_physics(physics_double, physics_fad, physics_rad, physics_fad_fad, physics_rad_fad);
249 dg_super_fine->allocate_system ();
253 pcout <<
"Exact solution integral is " << exact_solution_integral << std::endl;
256 std::vector<int> fail_conv_poly;
257 std::vector<double> fail_conv_slop;
258 std::vector<dealii::ConvergenceTable> convergence_table_vector;
260 for (
unsigned int poly_degree = p_start; poly_degree <= p_end; ++poly_degree) {
263 unsigned int n_grids = n_grids_input;
264 if (poly_degree <= 1) n_grids = n_grids_input + 1;
266 std::vector<double> soln_error(n_grids);
267 std::vector<double> output_error(n_grids);
268 std::vector<double> grid_size(n_grids);
272 dealii::ConvergenceTable convergence_table;
274 std::shared_ptr<Triangulation> grid = std::make_shared<Triangulation>(
278 typename dealii::Triangulation<dim>::MeshSmoothing(
279 dealii::Triangulation<dim>::smoothing_on_refinement |
280 dealii::Triangulation<dim>::smoothing_on_coarsening));
282 dealii::Vector<float> estimated_error_per_cell;
283 for (
unsigned int igrid=n_grids-1; igrid<n_grids; ++igrid) {
285 dealii::GridGenerator::subdivided_hyper_cube(*grid, n_1d_cells[igrid]);
286 for (
auto cell = grid->begin_active(); cell != grid->end(); ++cell) {
288 cell->set_material_id(9002);
289 for (
unsigned int face=0; face<dealii::GeometryInfo<dim>::faces_per_cell; ++face) {
290 if (cell->face(face)->at_boundary()) cell->face(face)->set_boundary_id (1000);
293 std::vector<dealii::GridTools::PeriodicFacePair<typename Triangulation::cell_iterator> > matched_pairs;
294 dealii::GridTools::collect_periodic_faces(*grid,0,1,0,matched_pairs);
295 grid->add_periodicity(matched_pairs);
299 std::shared_ptr dg = std::make_shared< DGWeak<dim,1,double> > (¶m, poly_degree, poly_degree, poly_degree+1, grid);
300 dg->set_physics(physics_double, physics_fad, physics_rad, physics_fad_fad, physics_rad_fad);
301 dg->allocate_system ();
306 const unsigned int n_global_active_cells = grid->n_global_active_cells();
307 const unsigned int n_dofs = dg->dof_handler.n_dofs();
308 pcout <<
"Dimension: " << dim
309 <<
"\t Polynomial degree p: " << poly_degree
311 <<
"Grid number: " << igrid+1 <<
"/" << n_grids
312 <<
". Number of active cells: " << n_global_active_cells
313 <<
". Number of degrees of freedom: " << n_dofs
320 ode_solver->steady_state();
323 int overintegrate = 10;
324 dealii::QGauss<dim> quad_extra(dg->max_degree+overintegrate);
326 dealii::FEValues<dim,dim> fe_values_extra(*(dg->high_order_grid->mapping_fe_field), dg->fe_collection[poly_degree], quad_extra,
327 dealii::update_values | dealii::update_JxW_values | dealii::update_quadrature_points);
328 const unsigned int n_quad_pts = fe_values_extra.n_quadrature_points;
329 std::array<double,nstate> soln_at_q;
335 std::vector<dealii::types::global_dof_index> dofs_indices (fe_values_extra.dofs_per_cell);
336 estimated_error_per_cell.reinit(grid->n_active_cells());
337 for (
auto cell = dg->dof_handler.begin_active(); cell!=dg->dof_handler.end(); ++cell) {
339 if (!cell->is_locally_owned())
continue;
341 fe_values_extra.reinit (cell);
342 cell->get_dof_indices (dofs_indices);
344 double cell_l2error = 0;
345 for (
unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
347 std::fill(soln_at_q.begin(), soln_at_q.end(), 0);
348 for (
unsigned int idof=0; idof<fe_values_extra.dofs_per_cell; ++idof) {
349 const unsigned int istate = fe_values_extra.get_fe().system_to_component_index(idof).first;
350 soln_at_q[istate] += dg->solution[dofs_indices[idof]] * fe_values_extra.shape_value_component(idof, iquad, istate);
353 const dealii::Point<dim> qpoint = (fe_values_extra.quadrature_point(iquad));
355 for (
int istate=0; istate<nstate; ++istate) {
356 const double uexact = physics_double->manufactured_solution_function->value(qpoint, istate);
359 cell_l2error += pow(soln_at_q[istate] - uexact, 2) * fe_values_extra.JxW(iquad);
362 estimated_error_per_cell[cell->active_cell_index()] = cell_l2error;
363 l2error += cell_l2error;
366 const double l2error_mpi_sum = std::sqrt(dealii::Utilities::MPI::sum(l2error,
mpi_communicator));
371 const double dx = 1.0/pow(n_dofs,(1.0/dim));
372 grid_size[igrid] = dx;
373 soln_error[igrid] = l2error_mpi_sum;
374 output_error[igrid] = std::abs(solution_integral - exact_solution_integral);
376 convergence_table.add_value(
"p", poly_degree);
377 convergence_table.add_value(
"cells", n_global_active_cells);
378 convergence_table.add_value(
"DoFs", n_dofs);
379 convergence_table.add_value(
"dx", dx);
380 convergence_table.add_value(
"soln_L2_error", l2error_mpi_sum);
381 convergence_table.add_value(
"output_error", output_error[igrid]);
384 pcout <<
" Grid size h: " << dx
385 <<
" L2-soln_error: " << l2error_mpi_sum
386 <<
" Residual: " << ode_solver->residual_norm
389 pcout <<
" output_exact: " << exact_solution_integral
390 <<
" output_discrete: " << solution_integral
391 <<
" output_error: " << output_error[igrid]
395 pcout <<
" ********************************************" 397 <<
" Convergence rates for p = " << poly_degree
399 <<
" ********************************************" 401 convergence_table.evaluate_convergence_rates(
"soln_L2_error",
"cells", dealii::ConvergenceTable::reduction_rate_log2, dim);
402 convergence_table.evaluate_convergence_rates(
"output_error",
"cells", dealii::ConvergenceTable::reduction_rate_log2, dim);
403 convergence_table.set_scientific(
"dx",
true);
404 convergence_table.set_scientific(
"soln_L2_error",
true);
405 convergence_table.set_scientific(
"output_error",
true);
406 if (
pcout.is_active()) convergence_table.write_text(
pcout.get_stream());
408 convergence_table_vector.push_back(convergence_table);
411 pcout << std::endl << std::endl << std::endl << std::endl;
412 pcout <<
" ********************************************" << std::endl;
413 pcout <<
" Convergence summary" << std::endl;
414 pcout <<
" ********************************************" << std::endl;
415 for (
auto conv = convergence_table_vector.begin(); conv!=convergence_table_vector.end(); conv++) {
416 if (
pcout.is_active()) conv->write_text(
pcout.get_stream());
417 pcout <<
" ********************************************" << std::endl;
419 int n_fail_poly = fail_conv_poly.size();
420 if (n_fail_poly > 0) {
421 for (
int ifail=0; ifail < n_fail_poly; ++ifail) {
422 const double expected_slope = fail_conv_poly[ifail]+1;
423 const double slope_deficit_tolerance = -std::abs(manu_grid_conv_param.slope_deficit_tolerance);
425 <<
"Convergence order not achieved for polynomial p = " 426 << fail_conv_poly[ifail]
428 << fail_conv_slop[ifail] <<
" instead of expected " 429 << expected_slope <<
" within a tolerance of " 430 << slope_deficit_tolerance
437 template <
int dim,
int nstate>
441 dealii::Point<dim> q = p;
443 if (dim >= 2) q[0] += 1*std::sin(q[dim-1]);
444 if (dim >= 3) q[1] += 1*std::cos(q[dim-1]);
448 template <
int dim,
int nstate>
450 ::print_mesh_info(
const dealii::Triangulation<dim> &triangulation,
const std::string &filename)
const 452 pcout <<
"Mesh info:" << std::endl
453 <<
" dimension: " << dim << std::endl
454 <<
" no. of cells: " << triangulation.n_global_active_cells() << std::endl;
455 std::map<dealii::types::boundary_id, unsigned int> boundary_count;
456 for (
auto cell : triangulation.active_cell_iterators()) {
457 for (
unsigned int face=0; face < dealii::GeometryInfo<dim>::faces_per_cell; ++face) {
458 if (cell->face(face)->at_boundary()) boundary_count[cell->face(face)->boundary_id()]++;
461 pcout <<
" boundary indicators: ";
462 for (
const std::pair<const dealii::types::boundary_id, unsigned int> &pair : boundary_count) {
463 pcout << pair.first <<
"(" << pair.second <<
" times) ";
467 std::ofstream out (filename);
468 dealii::GridOut grid_out;
469 grid_out.write_eps (triangulation, out);
470 pcout <<
" written to " << filename << std::endl << std::endl;
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.
Shock1D()=delete
Constructor. Deleted the default constructor since it should not be used.
void initialize_perturbed_solution(DGBase< dim, double > &dg, const Physics::PhysicsBase< dim, nstate, double > &physics) const
Initialize the solution with the exact solution.
Parameters related to the manufactured convergence study.
Manufactured solution used for grid studies to check convergence orders.
const MPI_Comm mpi_communicator
MPI communicator.
SineInitialCondition(const unsigned int n_components=1, const double time=0.)
Constructor.
Shocked1D1State(const unsigned int nstate=1)
Constructor that initializes base_values, amplitudes, frequencies.
virtual dealii::SymmetricTensor< 2, dim, real > hessian(const dealii::Point< dim, real > &point, const unsigned int) const override
Hessian of the exact manufactured solution.
Files for the baseline physics.
Shocked 1D solution for 1 state variable.
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.
dealii::LinearAlgebra::distributed::Vector< double > solution
Current modal coefficients of the solution.
ManufacturedConvergenceStudyParam manufactured_convergence_study_param
Contains parameters for manufactured convergence study.
dealii::IndexSet locally_owned_dofs
Locally own degrees of freedom.
const Parameters::AllParameters *const all_parameters
Pointer to all parameters.
const unsigned int max_degree
Maximum degree used for p-refi1nement.
void print_mesh_info(const dealii::Triangulation< dim > &triangulation, const std::string &filename) const
Prints our mesh info and generates eps file if 2D grid.
std::shared_ptr< HighOrderGrid< dim, real, MeshType > > high_order_grid
High order grid that will provide the MappingFEField.
virtual double value(const dealii::Point< dim > &p, const unsigned int) const override
Initial value.
virtual dealii::Tensor< 1, dim, real > gradient(const dealii::Point< dim, real > &point, const unsigned int) const override
Gradient of the exact manufactured solution.
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.
int run_test() const
Manufactured grid convergence.
dealii::DoFHandler< dim > dof_handler
Finite Element Collection to represent the high-order grid.
double integrate_solution_over_domain(DGBase< dim, double > &dg) const
L2-Integral of the solution over the entire domain.
virtual real value(const dealii::Point< dim, real > &point, const unsigned int) const override
Manufactured solution exact value.
dealii::ConditionalOStream pcout
ConditionalOStream.
const unsigned int nstate
DGBase is independent of the number of state variables.
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.
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) ...
const dealii::hp::FECollection< dim > fe_collection
Finite Element Collection for p-finite-element to represent the solution.
Base class of all the tests.
static dealii::Point< dim > warp(const dealii::Point< dim > &p)
Warps mesh into sinusoidal.