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