1 #include <deal.II/dofs/dof_tools.h> 3 #include <deal.II/grid/grid_refinement.h> 4 #include <deal.II/distributed/grid_refinement.h> 6 #include "grid_refinement/reconstruct_poly.h" 8 #include "grid_refinement_fixed_fraction.h" 12 namespace GridRefinement {
14 template <
int dim,
int nstate,
typename real,
typename MeshType>
18 RefinementTypeEnum refinement_type = this->grid_refinement_param.refinement_type;
24 if(refinement_type == RefinementTypeEnum::hp){
25 smoothness_indicator();
29 dealii::IndexSet locally_owned_dofs, locally_relevant_dofs;
30 locally_owned_dofs = this->dg->dof_handler.locally_owned_dofs();
31 dealii::DoFTools::extract_locally_relevant_dofs(this->dg->dof_handler, locally_relevant_dofs);
33 dealii::LinearAlgebra::distributed::Vector<double> solution_old(this->dg->solution);
34 solution_old.update_ghost_values();
36 using VectorType =
typename dealii::LinearAlgebra::distributed::Vector<double>;
37 using DoFHandlerType =
typename dealii::DoFHandler<dim>;
40 SolutionTransfer solution_transfer(this->dg->dof_handler);
41 solution_transfer.prepare_for_coarsening_and_refinement(solution_old);
43 this->dg->high_order_grid->prepare_for_coarsening_and_refinement();
44 this->dg->triangulation->prepare_coarsening_and_refinement();
47 if(refinement_type == RefinementTypeEnum::h){
49 }
else if(refinement_type == RefinementTypeEnum::p){
51 }
else if(refinement_type == RefinementTypeEnum::hp){
58 std::cout <<
"Checking for aniso option" << std::endl;
61 if(this->grid_refinement_param.anisotropic){
62 std::cout <<
"beginning anistropic flagging" << std::endl;
66 this->tria->execute_coarsening_and_refinement();
67 this->dg->high_order_grid->execute_coarsening_and_refinement();
70 this->dg->allocate_system();
71 this->dg->solution.zero_out_ghosts();
73 if constexpr (std::is_same_v<
typename dealii::SolutionTransfer<dim,VectorType,DoFHandlerType>,
74 decltype(solution_transfer)>){
75 solution_transfer.interpolate(solution_old, this->dg->solution);
77 solution_transfer.interpolate(this->dg->solution);
80 this->dg->solution.update_ghost_values();
86 template <
int dim,
int nstate,
typename real,
typename MeshType>
91 dealii::GridRefinement::refine_and_coarsen_fixed_number(
94 this->grid_refinement_param.refinement_fraction,
95 this->grid_refinement_param.coarsening_fraction);
105 template <
int dim,
int nstate,
typename real,
typename MeshType>
110 for(
auto cell = this->dg->dof_handler.begin_active(); cell != this->dg->dof_handler.end(); ++cell)
111 if(cell->is_locally_owned())
112 if(cell->refine_flag_set()){
113 cell->clear_refine_flag();
114 if(cell->active_fe_index()+1 <= this->dg->max_degree)
115 cell->set_active_fe_index(cell->active_fe_index()+1);
119 template <
int dim,
int nstate,
typename real,
typename MeshType>
127 for(
auto cell = this->dg->dof_handler.begin_active(); cell != this->dg->dof_handler.end(); ++cell)
128 if(cell->is_locally_owned() && cell->active_fe_index()+1 <= this->dg->max_degree)
129 if(cell->refine_flag_set()){
133 bool perform_p_refinement_instead =
true;
135 if(perform_p_refinement_instead)
137 cell->clear_refine_flag();
138 cell->set_active_fe_index(cell->active_fe_index()+1);
143 template <
int dim,
int nstate,
typename real,
typename MeshType>
147 for(
auto cell = this->dg->dof_handler.begin_active(); cell != this->dg->dof_handler.end(); ++cell){
148 if(!cell->is_locally_owned())
continue;
151 for(
unsigned int face = 0; face < dealii::GeometryInfo<dim>::faces_per_cell; ++face){
152 if(cell->face(face)->at_boundary()){
153 cell->set_refine_flag();
160 template <
int dim,
int nstate,
typename real,
typename MeshType>
164 smoothness.reinit(this->tria->n_active_cells());
172 template <
int dim,
int nstate,
typename real,
typename MeshType>
176 AnisoIndicator aniso_indicator = this->grid_refinement_param.anisotropic_indicator;
179 if(aniso_indicator == AnisoIndicator::jump_based){
180 anisotropic_h_jump_based();
181 }
else if(aniso_indicator == AnisoIndicator::reconstruction_based){
182 anisotropic_h_reconstruction_based();
187 template <
int dim,
int nstate,
typename real,
typename MeshType>
190 const dealii::hp::MappingCollection<dim> mapping_collection(*(this->dg->high_order_grid->mapping_fe_field));
191 const dealii::hp::FECollection<dim> fe_collection(this->dg->fe_collection);
192 const dealii::hp::QCollection<dim-1> face_quadrature_collection(this->dg->face_quadrature_collection);
194 dealii::hp::FEFaceValues<dim,dim> fe_values_collection_face_int(
197 face_quadrature_collection,
198 this->face_update_flags);
199 dealii::hp::FEFaceValues<dim,dim> fe_values_collection_face_ext(
202 face_quadrature_collection,
203 this->neighbor_face_update_flags);
204 dealii::hp::FESubfaceValues<dim,dim> fe_values_collection_subface(
207 face_quadrature_collection,
208 this->face_update_flags);
210 const dealii::LinearAlgebra::distributed::Vector<real> solution(this->dg->solution);
211 solution.update_ghost_values();
213 real anisotropic_threshold_ratio = this->grid_refinement_param.anisotropic_threshold_ratio;
215 for(
auto cell = this->dg->dof_handler.begin_active(); cell != this->dg->dof_handler.end(); ++cell){
216 if(!(cell->is_locally_owned()) || !(cell->refine_flag_set()))
continue;
218 dealii::Point<dim> jump;
219 dealii::Point<dim> area;
221 const unsigned int mapping_index = 0;
222 const unsigned int fe_index = cell->active_fe_index();
223 const unsigned int quad_index = fe_index;
225 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
226 if(cell->face(iface)->at_boundary())
continue;
228 const auto face = cell->face(iface);
230 Assert(cell->neighbor(iface).state() == dealii::IteratorState::valid,
231 dealii::ExcInternalError());
232 const auto neig = cell->neighbor(iface);
234 if(face->has_children()){
235 unsigned int neig2 = cell->neighbor_face_no(iface);
236 for(
unsigned int subface = 0; subface < face->number_of_children(); ++subface){
237 const auto neig_child = cell->neighbor_child_on_subface(iface, subface);
238 Assert(!neig_child->has_children(), dealii::ExcInternalError());
240 fe_values_collection_subface.reinit(cell,iface,subface,quad_index,mapping_index,fe_index);
241 const dealii::FESubfaceValues<dim,dim> &fe_int_subface = fe_values_collection_subface.get_present_fe_values();
242 std::vector<real> u_face(fe_int_subface.n_quadrature_points);
243 fe_int_subface.get_function_values(solution,u_face);
245 fe_values_collection_face_ext.reinit(neig_child,neig2,quad_index,mapping_index,fe_index);
246 const dealii::FEFaceValues<dim,dim> &fe_ext_face = fe_values_collection_face_ext.get_present_fe_values();
247 std::vector<real> u_neig(fe_ext_face.n_quadrature_points);
248 fe_ext_face.get_function_values(solution,u_neig);
250 const std::vector<real> &JxW = fe_int_subface.get_JxW_values();
251 for(
unsigned int iquad = 0; iquad < fe_int_subface.n_quadrature_points; ++iquad){
252 jump[iface/2] += abs(u_face[iquad] - u_neig[iquad]) * JxW[iquad];
253 area[iface/2] += JxW[iquad];
257 if(!cell->neighbor_is_coarser(iface)){
258 unsigned int neig2 = cell->neighbor_of_neighbor(iface);
260 fe_values_collection_face_int.reinit(cell,iface,quad_index,mapping_index,fe_index);
261 const dealii::FEFaceValues<dim,dim> &fe_int_face = fe_values_collection_face_int.get_present_fe_values();
262 std::vector<real> u_face(fe_int_face.n_quadrature_points);
263 fe_int_face.get_function_values(solution,u_face);
265 fe_values_collection_face_ext.reinit(neig,neig2,quad_index,mapping_index,fe_index);
266 const dealii::FEFaceValues<dim,dim> &fe_ext_face = fe_values_collection_face_ext.get_present_fe_values();
267 std::vector<real> u_neig(fe_ext_face.n_quadrature_points);
268 fe_ext_face.get_function_values(solution,u_neig);
270 const std::vector<real> &JxW = fe_int_face.get_JxW_values();
271 for(
unsigned int iquad = 0; iquad < fe_int_face.n_quadrature_points; ++iquad){
272 jump[iface/2] += abs(u_face[iquad] - u_neig[iquad]) * JxW[iquad];
273 area[iface/2] += JxW[iquad];
276 std::pair<unsigned int, unsigned int> neig_face_subface = cell->neighbor_of_coarser_neighbor(iface);
277 Assert(neig_face_subface.first < dealii::GeometryInfo<dim>::faces_per_cell,
278 dealii::ExcInternalError());
279 Assert(neig_face_subface.second < neig->face(neig_face_subface.first)->number_of_children(),
280 dealii::ExcInternalError());
281 Assert(neig->neighbor_child_on_subface(neig_face_subface.first, neig_face_subface.second) == cell,
282 dealii::ExcInternalError());
284 fe_values_collection_face_int.reinit(cell,iface,quad_index,mapping_index,fe_index);
285 const dealii::FEFaceValues<dim,dim> &fe_int_face = fe_values_collection_face_int.get_present_fe_values();
286 std::vector<real> u_face(fe_int_face.n_quadrature_points);
287 fe_int_face.get_function_values(solution,u_face);
289 fe_values_collection_subface.reinit(neig,neig_face_subface.first,neig_face_subface.second,quad_index,mapping_index,fe_index);
290 const dealii::FESubfaceValues<dim,dim> &fe_ext_subface = fe_values_collection_subface.get_present_fe_values();
291 std::vector<real> u_neig(fe_ext_subface.n_quadrature_points);
292 fe_ext_subface.get_function_values(solution,u_neig);
294 const std::vector<real> &JxW = fe_int_face.get_JxW_values();
295 for(
unsigned int iquad = 0; iquad < fe_int_face.n_quadrature_points; ++iquad){
296 jump[iface/2] += abs(u_face[iquad] - u_neig[iquad]) * JxW[iquad];
297 area[iface/2] += JxW[iquad];
303 std::array<real,dim> average_jumps;
304 real sum_of_average_jumps = 0.0;
306 for(
unsigned int i = 0; i < dim; ++i){
307 average_jumps[i] = jump[i]/area[i];
308 sum_of_average_jumps += average_jumps[i];
311 for(
unsigned int i = 0; i < dim; ++i)
312 if(average_jumps[i] > anisotropic_threshold_ratio * (sum_of_average_jumps - average_jumps[i]))
313 cell->set_refine_flag(dealii::RefinementCase<dim>::cut_axis(i));
317 template <
int dim,
int nstate,
typename real,
typename MeshType>
321 const dealii::hp::MappingCollection<dim> mapping_collection(*(this->dg->high_order_grid->mapping_fe_field));
324 const unsigned int rel_order = 1;
328 this->dg->dof_handler,
330 this->dg->fe_collection,
331 this->dg->volume_quadrature_collection,
332 this->volume_update_flags);
340 real anisotropic_threshold_ratio = this->grid_refinement_param.anisotropic_threshold_ratio;
343 for(
auto cell = this->dg->dof_handler.begin_active(); cell != this->dg->dof_handler.end(); ++cell){
344 if(!(cell->is_locally_owned()) || !(cell->refine_flag_set()))
continue;
347 std::array<std::pair<dealii::Tensor<1,dim,real>, dealii::Tensor<1,dim,real>>,dim> chord_nodes;
348 std::array<dealii::Tensor<1,dim,real>,dim> chord_vec;
351 for(
unsigned int vertex = 0; vertex < dealii::GeometryInfo<dim>::vertices_per_cell; ++vertex)
352 for(
unsigned int i = 0; i < dim; ++i)
353 if(vertex % (
unsigned int)pow(2,i) == 0){
354 chord_nodes[i].first += cell->vertex(vertex);
356 chord_nodes[i].second += cell->vertex(vertex);
360 for(
unsigned int i = 0; i < dim; ++i){
361 chord_nodes[i].first /= pow(2,dim-1);
362 chord_nodes[i].second /= pow(2,dim-1);
366 for(
unsigned int i = 0; i < dim; ++i){
367 chord_vec[i] = chord_nodes[i].second - chord_nodes[i].first;
371 dealii::Tensor<1,dim,real> indicator;
372 for(
unsigned int i = 0; i < dim; ++i)
373 indicator[i] += reconstruct_poly.
derivative_value[cell->active_cell_index()][i] * pow(chord_vec[i].
norm(), cell->active_fe_index()+rel_order);
376 for(
unsigned int i = 0; i < dim; ++i)
381 for(
unsigned int i = 0; i < dim; ++i)
382 if(indicator[i] / sum > anisotropic_threshold_ratio/(1.0 + anisotropic_threshold_ratio))
383 cell->set_refine_flag(dealii::RefinementCase<dim>::cut_axis(i));
387 template <
int dim,
int nstate,
typename real,
typename MeshType>
392 if(this->error_indicator_type == ErrorIndicatorEnum::error_based){
393 error_indicator_error();
394 }
else if(this->error_indicator_type == ErrorIndicatorEnum::hessian_based){
395 error_indicator_hessian();
396 }
else if(this->error_indicator_type == ErrorIndicatorEnum::residual_based){
397 error_indicator_residual();
398 }
else if(this->error_indicator_type == ErrorIndicatorEnum::adjoint_based){
399 error_indicator_adjoint();
401 std::cout <<
"Warning: error_indicator_type not recognized." << std::endl;
405 template <
int dim,
int nstate,
typename real,
typename MeshType>
415 int overintegrate = 10;
416 int poly_degree = this->dg->get_max_fe_degree();
417 dealii::QGauss<dim> quadrature(this->dg->max_degree+overintegrate);
418 dealii::FEValues<dim,dim> fe_values(*(this->dg->high_order_grid->mapping_fe_field), this->dg->fe_collection[poly_degree], quadrature,
419 dealii::update_values | dealii::update_JxW_values | dealii::update_quadrature_points);
421 const unsigned int n_quad_pts = fe_values.n_quadrature_points;
422 std::array<double,nstate> soln_at_q;
425 double norm_Lq = this->grid_refinement_param.norm_Lq;
428 std::vector<dealii::types::global_dof_index> dofs_indices(fe_values.dofs_per_cell);
429 this->indicator.reinit(this->tria->n_active_cells());
430 for(
auto cell = this->dg->dof_handler.begin_active(); cell != this->dg->dof_handler.end(); ++cell){
431 if(!cell->is_locally_owned())
continue;
433 fe_values.reinit(cell);
434 cell->get_dof_indices(dofs_indices);
436 double cell_error = 0;
437 for(
unsigned int iquad = 0; iquad < n_quad_pts; ++iquad){
438 std::fill(soln_at_q.begin(), soln_at_q.end(), 0);
439 for(
unsigned int idof = 0; idof < fe_values.dofs_per_cell; ++idof){
440 const unsigned int istate = fe_values.get_fe().system_to_component_index(idof).first;
441 soln_at_q[istate] += this->dg->solution[dofs_indices[idof]] * fe_values.shape_value_component(idof,iquad,istate);
444 const dealii::Point<dim> qpoint = (fe_values.quadrature_point(iquad));
446 for(
int istate = 0; istate < nstate; ++istate){
447 const double uexact = this->physics->manufactured_solution_function->value(qpoint,istate);
448 cell_error += pow(abs(soln_at_q[istate] - uexact), norm_Lq) * fe_values.JxW(iquad);
451 this->indicator[cell->active_cell_index()] = cell_error;
456 template <
int dim,
int nstate,
typename real,
typename MeshType>
462 const dealii::hp::MappingCollection<dim> mapping_collection(*(this->dg->high_order_grid->mapping_fe_field));
465 const unsigned int rel_order = 1;
469 this->dg->dof_handler,
471 this->dg->fe_collection,
472 this->dg->volume_quadrature_collection,
473 this->volume_update_flags);
480 this->indicator.reinit(this->tria->n_active_cells());
481 for(
auto cell = this->dg->dof_handler.begin_active(); cell < this->dg->dof_handler.end(); ++cell)
482 if(cell->is_locally_owned()){
490 this->indicator[cell->active_cell_index()] = 0.0;
491 for(
unsigned int d = 0; d < dim; ++d){
494 real derivative_value = reconstruct_poly.
derivative_value[cell->active_cell_index()][d];
497 if(this->indicator[cell->active_cell_index()] < derivative_value)
498 this->indicator[cell->active_cell_index()] = derivative_value;
502 this->indicator[cell->active_cell_index()] *= pow(cell->measure(), (cell->active_fe_index()+rel_order)/dim);
506 template <
int dim,
int nstate,
typename real,
typename MeshType>
556 template <
int dim,
int nstate,
typename real,
typename MeshType>
561 this->adjoint->fine_grid_adjoint();
564 this->indicator.reinit(this->adjoint->dg->triangulation->n_active_cells());
565 this->indicator = this->adjoint->dual_weighted_residual();
571 template <
int dim,
int nstate,
typename real,
typename MeshType>
574 std::vector< std::pair<dealii::Vector<real>, std::string> > data_out_vector;
578 data_out_vector.push_back(
583 smoothness_indicator();
584 data_out_vector.push_back(
587 "smoothness_indicator"));
589 return data_out_vector;
void reconstruct_chord_derivative(const dealii::LinearAlgebra::distributed::Vector< real > &solution, const unsigned int rel_order)
Construct directional derivatives along the chords of the cell.
Polynomial Reconstruction Class.
ErrorIndicator
Types of error indicator to be used in the grid refinement.
void refine_grid() override
Perform call to the grid refinement object of choice.
void error_indicator_error()
Compute error indicator based on Lq norm relative to exact manufactured solution. ...
void error_indicator()
Performs call to proper error indcator function based on type of error_indicator parameter.
void anisotropic_h_jump_based()
Sets anisotropic refinement flags for cells based on discontinuity between neighbors.
Files for the baseline physics.
void anisotropic_h_reconstruction_based()
Sets anisotropic refinement flags for cells based on directional derivatives reconstructed along the ...
void refine_grid_hp()
(NOT IMPLEMENTED) Based on error and smoothness indicator, perform fixed-fraction flagging and decisi...
void error_indicator_adjoint()
Compute error indicator for goal-oriented approach using a dual-weighted residual.
AnisoIndicator
Control of anisotropic splitting indicator to be used in fixed-fraction methods.
void reconstruct_directional_derivative(const dealii::LinearAlgebra::distributed::Vector< real > &solution, const unsigned int rel_order)
Construct the set of largest perpendicular directional derivatives.
std::vector< std::array< real, dim > > derivative_value
Derivative values.
void refine_grid_p()
Based on error indicator, performs fixed-fraction flagging for polynomial order enrichment.
Fixed-Fraction Grid Refinement Class.
void smoothness_indicator()
(NOT IMPLEMENTED) Computes smoothness indicator for -refinement decisions
void anisotropic_h()
Performs anisotropic adaptation of the mesh.
RefinementType
Controls the type of refinement to be performed.
std::vector< std::pair< dealii::Vector< real >, std::string > > output_results_vtk_method() override
Output refinement method dependent results.
void error_indicator_hessian()
Compute error indicator based on reconstructed directional derivatives.
void error_indicator_residual()
(NOT IMPLEMENTED) Compute error indicator based on fine grid residual distribution ...
void refine_boundary_h()
Flags the domain boundaries for refinement.
real1 norm(const dealii::Tensor< 1, dim, real1 > x)
Returns norm of dealii::Tensor<1,dim,real>
void refine_grid_h()
Based on error indicator, performs fixed-fraction flagging for element splitting. ...