[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
mesh_adaptation.cpp
1 #include "mesh_adaptation.h"
2 #include <deal.II/hp/refinement.h>
3 
4 namespace PHiLiP {
5 
6 template <int dim, int nspecies, typename real, typename MeshType>
8  : dg(dg_input)
9  , current_mesh_adaptation_cycle(0)
10  , mesh_adaptation_param(mesh_adaptation_param_input)
11  , pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0)
12  {
13  if (nspecies == 1)
15  else
17 
18  }
19 
20 
21 template <int dim, int nspecies, typename real, typename MeshType>
23 {
24  [[maybe_unused]] unsigned int expected_size_of_cellwise_errors = dg->triangulation->n_active_cells();
25  cellwise_errors = mesh_error->compute_cellwise_errors();
26  [[maybe_unused]] unsigned int actual_size_of_cellwise_errors = cellwise_errors.size();
27  AssertDimension(expected_size_of_cellwise_errors, actual_size_of_cellwise_errors);
28 
31  pcout<<"Mesh has been adapted according to the specified error indicator. Adaptation cycle = "<<current_mesh_adaptation_cycle<<std::endl;
32 }
33 
34 
35 template <int dim, int nspecies, typename real, typename MeshType>
37 {
38  dealii::LinearAlgebra::distributed::Vector<real> old_solution(dg->solution);
39  dealii::parallel::distributed::SolutionTransfer<dim, dealii::LinearAlgebra::distributed::Vector<real>, dealii::DoFHandler<dim>> solution_transfer(dg->dof_handler);
40  solution_transfer.prepare_for_coarsening_and_refinement(old_solution);
41  dg->high_order_grid->prepare_for_coarsening_and_refinement();
42 
43  if constexpr(dim == 1 || !std::is_same<MeshType, dealii::parallel::distributed::Triangulation<dim>>::value)
44  {
45  dealii::GridRefinement::refine_and_coarsen_fixed_number(*(dg->high_order_grid->triangulation),
49  }
50  else
51  {
52  dealii::parallel::distributed::GridRefinement::refine_and_coarsen_fixed_number(*(dg->high_order_grid->triangulation),
56  }
57 
58 //=========================================================================================================================================================
59  using MeshAdaptationTypeEnum = Parameters::MeshAdaptationParam::MeshAdaptationType;
60  MeshAdaptationTypeEnum mesh_adaptation_type = mesh_adaptation_param->mesh_adaptation_type;
61 
62 
63  if(mesh_adaptation_type == MeshAdaptationTypeEnum::h_adaptation){
64  // Do nothing, cells are already flagged for h-adaptation
65  } else if(mesh_adaptation_type == MeshAdaptationTypeEnum::p_adaptation){
66  dealii::hp::Refinement::p_adaptivity_fixed_number(dg->dof_handler,
68  1.0,
69  0.0);
70 
71  // If a cell is flagged for both h and p adaptation, perform only p adaptation.
72  dealii::hp::Refinement::force_p_over_h(dg->dof_handler);
73  } else if(mesh_adaptation_type == MeshAdaptationTypeEnum::hp_adaptation){
75  }
76 //=========================================================================================================================================================
77 
78  dg->high_order_grid->triangulation->execute_coarsening_and_refinement();
79  dg->high_order_grid->execute_coarsening_and_refinement();
80 
81  dg->allocate_system ();
82  dg->solution.zero_out_ghosts();
83  solution_transfer.interpolate(dg->solution);
84  dg->solution.update_ghost_values();
85  dg->assemble_residual ();
86 }
87 
88 template <int dim, int nspecies, typename real, typename MeshType>
90 {
91  const auto mapping = (*(dg->high_order_grid->mapping_fe_field));
92  dealii::hp::MappingCollection<dim> mapping_collection(mapping);
93  const dealii::UpdateFlags update_flags = dealii::update_values | dealii::update_JxW_values;
94  dealii::hp::FEValues<dim,dim> fe_values_collection_volume (mapping_collection, dg->fe_collection, dg->volume_quadrature_collection, update_flags);
95 
96  std::vector< real > soln_coeff_high;
97  std::vector<dealii::types::global_dof_index> dof_indices;
98 
99  for (auto cell : dg->dof_handler.active_cell_iterators()) {
100  if (!(cell->is_locally_owned() || cell->is_ghost())) continue;
101  if(!cell->refine_flag_set()) continue;
102 
103 
104  const int i_fele = cell->active_fe_index();
105  const int i_quad = i_fele;
106  const int i_mapp = 0;
107 
108  const dealii::FESystem<dim,dim> &fe_high = dg->fe_collection[i_fele];
109  const unsigned int degree = fe_high.tensor_degree();
110 
111  if (degree == 0)
112  {
113  pcout<<"Degree of the current cell is 0. Cannot compute smoothness indicator as we cannot interpolate to a lower polynomial order"<<std::endl;
114  std::abort();
115  }
116 
117  const unsigned int nstate = fe_high.components;
118  const unsigned int n_dofs_high = fe_high.dofs_per_cell;
119 
120  fe_values_collection_volume.reinit (cell, i_quad, i_mapp, i_fele);
121  const dealii::FEValues<dim,dim> &fe_values_volume = fe_values_collection_volume.get_present_fe_values();
122 
123  dof_indices.resize(n_dofs_high);
124  cell->get_dof_indices (dof_indices);
125 
126  soln_coeff_high.resize(n_dofs_high);
127  for (unsigned int idof=0; idof<n_dofs_high; ++idof) {
128  soln_coeff_high[idof] = dg->solution[dof_indices[idof]];
129  }
130 
131  // Lower degree basis.
132  const unsigned int lower_degree = degree-1;
133  const dealii::FE_DGQLegendre<dim> fe_dgq_lower(lower_degree);
134  const dealii::FESystem<dim,dim> fe_lower(fe_dgq_lower, nstate);
135 
136  // Projection quadrature.
137  const dealii::QGauss<dim> projection_quadrature(degree+5);
138  std::vector< real > soln_coeff_lower = project_function<dim, nspecies, real>( soln_coeff_high, fe_high, fe_lower, projection_quadrature);
139 
140  // Quadrature used for solution difference.
141  const dealii::Quadrature<dim> &quadrature = fe_values_volume.get_quadrature();
142  const std::vector<dealii::Point<dim,real>> &unit_quad_pts = quadrature.get_points();
143 
144  const unsigned int n_quad_pts = quadrature.size();
145  const unsigned int n_dofs_lower = fe_lower.dofs_per_cell;
146 
147  real element_volume = 0.0;
148  real error = 0.0;
149  real soln_norm = 0.0;
150  std::vector<real> soln_high(nstate);
151  std::vector<real> soln_lower(nstate);
152  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
153  for (unsigned int s=0; s<nstate; ++s) {
154  soln_high[s] = 0.0;
155  soln_lower[s] = 0.0;
156  }
157  // Interpolate solution
158  for (unsigned int idof=0; idof<n_dofs_high; ++idof) {
159  const unsigned int istate = fe_high.system_to_component_index(idof).first;
160  soln_high[istate] += soln_coeff_high[idof] * fe_high.shape_value_component(idof,unit_quad_pts[iquad],istate);
161  }
162  // Interpolate low order solution
163  for (unsigned int idof=0; idof<n_dofs_lower; ++idof) {
164  const unsigned int istate = fe_lower.system_to_component_index(idof).first;
165  soln_lower[istate] += soln_coeff_lower[idof] * fe_lower.shape_value_component(idof,unit_quad_pts[iquad],istate);
166  }
167  // Quadrature
168  element_volume += fe_values_volume.JxW(iquad);
169  // Only integrate over the first state variable.
170  for (unsigned int s=0; s<1/*nstate*/; ++s)
171  {
172  error += (soln_high[s] - soln_lower[s]) * (soln_high[s] - soln_lower[s]) * fe_values_volume.JxW(iquad);
173  soln_norm += soln_high[s] * soln_high[s] * fe_values_volume.JxW(iquad);
174  }
175  }
176 
177  if (soln_norm < 1e-12)
178  {
179  continue;
180  }
181 
182  real smoothness_sensor = error / soln_norm;
183 
184  if(smoothness_sensor < mesh_adaptation_param->hp_smoothness_tolerance)
185  {
186  cell->clear_refine_flag();
187  cell->set_future_fe_index(cell->active_fe_index()+1);
188  }
189  }
190 }
191 
192 
195 #if PHILIP_DIM != 1
197 #endif
198 
199 } // namespace PHiLiP
dealii::Vector< real > cellwise_errors
Stores errors in each cell.
const Parameters::MeshAdaptationParam *const mesh_adaptation_param
Holds parameters of mesh adaptation.
void adapt_mesh()
Function to adapt the mesh based on input parameters.
int current_mesh_adaptation_cycle
Stores the current adaptation cycle.
dealii::ConditionalOStream pcout
Parallel std::cout.
Files for the baseline physics.
Definition: ADTypes.hpp:10
void fixed_fraction_isotropic_refinement_and_coarsening()
Performs fixed fraction refinement based on refinement and coarsening fractions.
std::unique_ptr< MeshErrorEstimateBase< dim, nspecies, real, MeshType > > mesh_error
Pointer to the error estimator class.
std::shared_ptr< DGBase< dim, nspecies, real, MeshType > > dg
Pointer to DGBase.
static std::unique_ptr< MeshErrorEstimateBase< dim, nspecies, real, MeshType > > create_mesh_error(std::shared_ptr< DGBase< dim, nspecies, real, MeshType > > dg)
Returns pointer of the mesh error&#39;s abstract class.
MeshAdaptation(std::shared_ptr< DGBase< dim, nspecies, real, MeshType > > dg_input, const Parameters::MeshAdaptationParam *const mesh_adaptation_param_input)
Constructor to initialize the class with a pointer to DG.
MeshAdaptationType mesh_adaptation_type
Selection of mesh adaptation type.
MeshAdaptationType
Choices for mesh adaptation to be used.
double h_coarsen_fraction
Fraction of cells to be h-coarsened.
void smoothness_sensor_based_hp_refinement()
Decide whether to perform h or p refinement based on a smoothness indicator.
DGBase is independent of the number of state variables.
Definition: dg_base.hpp:82
double refine_fraction
Fraction of cells to be h or p-refined.