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.