[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
anisotropic_mesh_adaptation.cpp
1 #include "anisotropic_mesh_adaptation.h"
2 #include <deal.II/base/symmetric_tensor.h>
3 #include "linear_solver/linear_solver.h"
4 #include "physics/physics_factory.h"
5 #include "physics/model_factory.h"
6 #include "mesh/gmsh_reader.hpp"
7 #include "metric_to_mesh_generator.h"
8 #include <deal.II/dofs/dof_renumbering.h>
9 #include "fe_values_shape_hessian.h"
10 
11 namespace PHiLiP {
12 
13 template <int dim, int nstate, typename real, typename MeshType>
15  std::shared_ptr< DGBase<dim, real, MeshType> > dg_input,
16  const real _norm_Lp,
17  const real _complexity,
18  const bool _use_goal_oriented_approach)
19  : dg(dg_input)
20  , use_goal_oriented_approach(_use_goal_oriented_approach)
21  , normLp(_norm_Lp)
22  , complexity(_complexity)
23  , mpi_communicator(MPI_COMM_WORLD)
24  , pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(mpi_communicator)==0)
25  , initial_poly_degree(dg->get_min_fe_degree())
26  , max_dofs_per_cell(dg->dof_handler.get_fe_collection().max_dofs_per_cell())
27 {
28  MPI_Comm_rank(mpi_communicator, &mpi_rank);
29  MPI_Comm_size(mpi_communicator, &n_mpi);
30 
32  {
33  if(normLp != 1)
34  {
35  std::cout<<"Optimal metric for the goal oriented approach has been derived w.r.t the error in L1 norm. Aborting..."<<std::flush;
36  std::abort();
37  }
38 
39  std::shared_ptr<Physics::ModelBase<dim,nstate,real>> pde_model_double = Physics::ModelFactory<dim,nstate,real>::create_Model(dg->all_parameters);
42  }
43 
44  if(dg->get_min_fe_degree() != dg->get_max_fe_degree())
45  {
46  std::cout<<"This class is currently coded assuming a constant poly degree. To be changed in future if required."<<std::endl;
47  std::abort();
48  }
49 
50  if(initial_poly_degree != 1)
51  {
52  pcout<<"Warning: The optimal metric used by this class has been derived for p1."
53  <<" For any other p, it might be a good approximation but will not be optimal."<<std::endl;
54  }
55 
56  Assert(this->dg->triangulation->get_mesh_smoothing() == typename dealii::Triangulation<dim>::MeshSmoothing(dealii::Triangulation<dim>::none),
57  dealii::ExcMessage("Mesh smoothing might h-refine cells while changing p order."));
58 
59 }
60 
61 template<int dim, int nstate, typename real, typename MeshType>
63  :: get_positive_definite_tensor(const dealii::Tensor<2, dim, real> &input_tensor) const
64 {
65  // Check if the tensor is symmetric.
66  dealii::Tensor<2, dim, real> input_tensor_copy = input_tensor;
67  for(int i=0; i<dim; ++i)
68  {
69  for(int j=0; j<dim-i; ++j)
70  {
71  if(abs(input_tensor_copy[i][j] - input_tensor_copy[j][i]) > 1.0e-10)
72  {
73  std::cout<<"Input tensor needs to be symmetric. Difference = "<< abs(input_tensor_copy[i][j] - input_tensor_copy[j][i]) <<". Aborting.."<<std::endl<<std::flush;
74  std::abort();
75  }
76  else
77  {
78  input_tensor_copy[j][i] = input_tensor_copy[i][j];
79  }
80  }
81  }
82  dealii::SymmetricTensor<2,dim,real> symmetric_input_tensor(input_tensor_copy);
83  std::array<std::pair<real, dealii::Tensor<1, dim, real>>, dim> eigen_pair = dealii::eigenvectors(symmetric_input_tensor);
84 
85  std::array<real, dim> abs_eigenvalues;
86  const real min_eigenvalue = 1.0e-8;
87  const real max_eigenvalue = 1.0e8;
88  // Get absolute values of eigenvalues
89  for(unsigned int i = 0; i<dim; ++i)
90  {
91  abs_eigenvalues[i] = abs(eigen_pair[i].first);
92  if(abs_eigenvalues[i] < min_eigenvalue) {abs_eigenvalues[i] = min_eigenvalue;}
93  if(abs_eigenvalues[i] > max_eigenvalue) {abs_eigenvalues[i] = max_eigenvalue;}
94  }
95 
96  dealii::Tensor<2, dim, real> positive_definite_tensor; // all entries are 0 by default.
97 
98  // Form the matrix again with updated eigenvalues
99  // If matrix of eigenvectors = [v1 v2 vdim], the new matrix would be
100  // [v1 v2 vdim] * diag(eig1, eig2, eigdim) * [v1 v2 vdim]^T
101  // = eig1*v1*v1^T + eig2*v2*v2^T + eigdim*vdim*vdim^T with vi*vi^T coming from dealii's outer product.
102  for(unsigned int i=0; i<dim; ++i)
103  {
104  dealii::Tensor<1, dim, real> eigenvector_i = eigen_pair[i].second;
105  dealii::Tensor<2, dim, real> outer_product_i = dealii::outer_product(eigenvector_i, eigenvector_i);
106  outer_product_i *= abs_eigenvalues[i];
107  positive_definite_tensor += outer_product_i;
108  }
109 
110  return positive_definite_tensor;
111 }
112 
113 template<int dim, int nstate, typename real, typename MeshType>
115 {
116  cellwise_optimal_metric.clear();
117  cellwise_hessian.clear();
118  const unsigned int n_active_cells = dg->triangulation->n_active_cells();
119 
120  dealii::Tensor<2, dim, real> zero_tensor; // initialized to 0 by default.
121  for(unsigned int i=0; i<n_active_cells; ++i)
122  {
123  cellwise_optimal_metric.push_back(zero_tensor);
124  cellwise_hessian.push_back(zero_tensor);
125  }
126 }
127 
128 template<int dim, int nstate, typename real, typename MeshType>
130 {
132  compute_abs_hessian(); // computes hessian according to goal oriented or feature based approach.
133 
134  pcout<<"Computing optimal metric field."<<std::endl;
135 
136  const unsigned int n_active_cells = dg->triangulation->n_active_cells();
137  dealii::Vector<real> abs_hessian_determinant(n_active_cells);
138 
139  // Compute hessian determinants
140  for(const auto &cell : dg->dof_handler.active_cell_iterators())
141  {
142  if(! cell->is_locally_owned()) {continue;}
143 
144  const unsigned int cell_index = cell->active_cell_index();
145  abs_hessian_determinant[cell_index] = dealii::determinant(cellwise_hessian[cell_index]);
146  }
147 
148  // Using Eq 4.40, page 153 in Dervieux, A., Alauzet, F., Loseille, A., Koobus, B. (2022). Mesh Adaptation for Computational Fluid Dynamics 1.
149  const auto mapping = (*(dg->high_order_grid->mapping_fe_field));
150  dealii::hp::MappingCollection<dim> mapping_collection(mapping);
151  const dealii::UpdateFlags update_flags = dealii::update_JxW_values;
152  dealii::hp::FEValues<dim,dim> fe_values_collection_volume (mapping_collection, dg->fe_collection, dg->volume_quadrature_collection, update_flags);
153 
154  real integral_val = 0;
155  for(const auto &cell : dg->dof_handler.active_cell_iterators())
156  {
157  if(! cell->is_locally_owned()) {continue;}
158 
159  const unsigned int cell_index = cell->active_cell_index();
160  const unsigned int i_fele = cell->active_fe_index();
161  const unsigned int i_quad = i_fele;
162  const unsigned int i_mapp = 0;
163  fe_values_collection_volume.reinit(cell, i_quad, i_mapp, i_fele);
164  const dealii::FEValues<dim,dim> &fe_values_volume = fe_values_collection_volume.get_present_fe_values();
165 
166  const real exponent = normLp/(2.0*normLp + dim);
167  const real integrand = pow(abs_hessian_determinant[cell_index], exponent);
168 
169  for(unsigned int iquad = 0; iquad<fe_values_volume.n_quadrature_points; ++iquad)
170  {
171  integral_val += integrand * fe_values_volume.JxW(iquad);
172  }
173  }
174 
175  const real integral_val_global = dealii::Utilities::MPI::sum(integral_val, mpi_communicator);
176  const real exponent = 2.0/dim;
177  const real scaling_factor = pow(complexity, exponent) * pow(integral_val_global, -exponent); // Factor by which the metric is scaled to get a mesh of required complexity/# of elements.
178 
179  // Now loop over to fill in the optimal metric.
180  for(const auto &cell : dg->dof_handler.active_cell_iterators())
181  {
182  if(! cell->is_locally_owned()) {continue;}
183 
184  const unsigned int cell_index = cell->active_cell_index();
185 
186  const real exponent2 = -1.0/(2.0*normLp + dim);
187  const real scaling_factor2 = pow(abs_hessian_determinant[cell_index], exponent2);
188  const real scaling_factor_this_cell = scaling_factor * scaling_factor2;
189 
190  cellwise_optimal_metric[cell_index] = cellwise_hessian[cell_index];
191  cellwise_optimal_metric[cell_index] *= scaling_factor_this_cell;
192  }
193 
194  pcout<<"Done computing optimal metric."<<std::endl;
195 }
196 
197 template<int dim, int nstate, typename real, typename MeshType>
199 {
200  VectorType solution_old = dg->solution;
201  solution_old.update_ghost_values();
202  // This class is based on INRIA's work in which the exact solution is assumed to be quadratic while the numerical solution is p1.
203  // Future work could consider the (p+1)th order directional derivative from GridRefinement::ReconstructPoly.
204  change_p_degree_and_interpolate_solution(2); // Interpolate to p2
206 
208  {
210  }
211  else
212  {
214  }
215 
217  dg->solution = solution_old; // reset solution
218  dg->solution.update_ghost_values();
219 }
220 
221 template<int dim, int nstate, typename real, typename MeshType>
223 {
224  assert(dg->get_min_fe_degree() == dg->get_max_fe_degree());
225  const unsigned int current_poly_degree = dg->get_min_fe_degree();
226  pcout<<"Changing poly degree from "<<current_poly_degree<< " to "<<poly_degree<<" and interpolating solution."<<std::endl;
227  VectorType solution_coarse = dg->solution;
228  solution_coarse.update_ghost_values();
229 
230  using DoFHandlerType = typename dealii::DoFHandler<dim>;
231  using SolutionTransfer = typename MeshTypeHelper<MeshType>::template SolutionTransfer<dim,VectorType,DoFHandlerType>;
232 
233  SolutionTransfer solution_transfer(this->dg->dof_handler);
234  solution_transfer.prepare_for_coarsening_and_refinement(solution_coarse);
235 
236  dg->set_all_cells_fe_degree(poly_degree);
237  dg->allocate_system();
238  dg->solution.zero_out_ghosts();
239 
240  if constexpr (std::is_same_v<typename dealii::SolutionTransfer<dim,VectorType,DoFHandlerType>,
241  decltype(solution_transfer)>) {
242  solution_transfer.interpolate(solution_coarse, this->dg->solution);
243  } else {
244  solution_transfer.interpolate(this->dg->solution);
245  }
246 
247  this->dg->solution.update_ghost_values();
248 }
249 
250 template<int dim, int nstate, typename real, typename MeshType>
252 {
253  assert(dg->get_min_fe_degree() == 2);
254  pcout<<"Reconstructing p2 solution."<<std::endl;
255  dg->assemble_residual(true);
256  VectorType delU = dg->solution;
257  solve_linear(dg->system_matrix, dg->right_hand_side, delU, dg->all_parameters->linear_solver_param);
258  delU *= -1.0;
259  delU.update_ghost_values();
260  dg->solution += delU;
261  dg->solution.update_ghost_values();
262 }
263 
264 template<int dim, int nstate, typename real, typename MeshType>
266 {
267  assert(dg->get_min_fe_degree() == dg->get_max_fe_degree());
268  assert(dg->get_min_fe_degree() == 2);
269  pcout<<"Computing feature based Hessian."<<std::endl;
270  // Based on Loseille, A. and Alauzet, F. "Continuous mesh framework part II.", 2011.
271  // Compute Hessian of the solution for now (can be changed to Mach number or some other sensor when required).
272  const auto mapping = (*(dg->high_order_grid->mapping_fe_field));
273  dealii::hp::MappingCollection<dim> mapping_collection(mapping);
274  const dealii::UpdateFlags update_flags = dealii::update_jacobian_pushed_forward_grads | dealii::update_inverse_jacobians;
275  dealii::hp::FEValues<dim,dim> fe_values_collection_volume (mapping_collection, dg->fe_collection, dg->volume_quadrature_collection, update_flags);
276  PHiLiP::FEValuesShapeHessian<dim> fe_values_shape_hessian;
277 
278  std::vector<dealii::types::global_dof_index> dof_indices(max_dofs_per_cell);
279 
280  for(const auto &cell : dg->dof_handler.active_cell_iterators())
281  {
282  if(! cell->is_locally_owned()) {continue;}
283 
284  const unsigned int cell_index = cell->active_cell_index();
285  const unsigned int i_fele = cell->active_fe_index();
286  const unsigned int i_quad = i_fele;
287  const unsigned int i_mapp = 0;
288  fe_values_collection_volume.reinit(cell, i_quad, i_mapp, i_fele);
289  const dealii::FEValues<dim,dim> &fe_values_volume = fe_values_collection_volume.get_present_fe_values();
290 
291  const unsigned int n_dofs_cell = fe_values_volume.dofs_per_cell;
292  dof_indices.resize(n_dofs_cell);
293  cell->get_dof_indices(dof_indices);
294 
295  cellwise_hessian[cell_index] = 0;
296  const unsigned int iquad = get_iquad_near_cellcenter(fe_values_volume.get_quadrature());
297  fe_values_shape_hessian.reinit(fe_values_volume, iquad);
298  const dealii::FESystem<dim,dim> &fe_ref = fe_values_volume.get_fe();
299 
300  for(unsigned int idof = 0; idof<n_dofs_cell; ++idof)
301  {
302  const unsigned int icomp = fe_values_volume.get_fe().system_to_component_index(idof).first;
303  // Computing hesssian of solution at state 0. Might need to change it later.
304  if(icomp == 0)
305  {
306  cellwise_hessian[cell_index] += dg->solution(dof_indices[idof])*fe_values_shape_hessian.shape_hessian_component(idof, iquad, icomp, fe_ref);
307  }
308  }
310  }
311 }
312 
313 template<int dim, int nstate, typename real, typename MeshType>
315 {
316  assert(dg->get_min_fe_degree() == dg->get_max_fe_degree());
317  assert(dg->get_min_fe_degree() == 2);
318 
319  // Compute goal oriented pseudo hessian.
320  // From Eq. 28 in Loseille, A., Dervieux, A., and Alauzet, F. "Fully anisotropic goal-oriented mesh adaptation for 3D steady Euler equations.", 2010.
321  // Also, metric terms related to faces do not make a difference and hence are not included (cf. footnote on page 78 in
322  // Dervieux, A., Alauzet, F., Loseille, A., Koobus, B. (2022). Mesh Adaptation for Computational Fluid Dynamics 2.
323 
324  // Compute the adjoint ===================================================================
325  VectorType adjoint(dg->solution);
326  dg->assemble_residual(true);
327  functional->evaluate_functional(true);
328  solve_linear(dg->system_matrix_transpose, functional->dIdw, adjoint, dg->all_parameters->linear_solver_param);
329  adjoint *= -1.0;
330  adjoint.update_ghost_values();
331  //==========================================================================================
332 
333  pcout<<"Computing goal-oriented Hessian."<<std::endl;
334  const auto mapping = (*(dg->high_order_grid->mapping_fe_field));
335  dealii::hp::MappingCollection<dim> mapping_collection(mapping);
336  const dealii::UpdateFlags update_flags = dealii::update_values | dealii::update_gradients | dealii::update_jacobian_pushed_forward_grads | dealii::update_inverse_jacobians;
337  dealii::hp::FEValues<dim,dim> fe_values_collection_volume (mapping_collection, dg->fe_collection, dg->volume_quadrature_collection, update_flags);
338  PHiLiP::FEValuesShapeHessian<dim> fe_values_shape_hessian;
339 
340  std::vector<dealii::types::global_dof_index> dof_indices(max_dofs_per_cell);
341 
342  for(const auto &cell : dg->dof_handler.active_cell_iterators())
343  {
344  if(! cell->is_locally_owned()) {continue;}
345 
346  const unsigned int cell_index = cell->active_cell_index();
347  const unsigned int i_fele = cell->active_fe_index();
348  const unsigned int i_quad = i_fele;
349  const unsigned int i_mapp = 0;
350  fe_values_collection_volume.reinit(cell, i_quad, i_mapp, i_fele);
351  const dealii::FEValues<dim,dim> &fe_values_volume = fe_values_collection_volume.get_present_fe_values();
352 
353  const unsigned int n_dofs_cell = fe_values_volume.dofs_per_cell;
354  dof_indices.resize(n_dofs_cell);
355  cell->get_dof_indices(dof_indices);
356 
357  const unsigned int iquad = get_iquad_near_cellcenter(fe_values_volume.get_quadrature());
358  fe_values_shape_hessian.reinit(fe_values_volume, iquad);
359  const dealii::FESystem<dim,dim> &fe_ref = fe_values_volume.get_fe();
360 
361  // Compute adjoint gradient
362  std::array<dealii::Tensor<1,dim,real>,nstate> adjoint_gradient; // initialized to 0 by default.
363  for(unsigned int idof = 0; idof<n_dofs_cell; ++idof)
364  {
365  const unsigned int istate = fe_ref.system_to_component_index(idof).first;
366  adjoint_gradient[istate] += adjoint(dof_indices[idof]) * fe_values_volume.shape_grad_component(idof,iquad,istate);
367  }
368 
369  // Obtain flux coeffs
370  std::vector<std::array<dealii::Tensor<1,dim,real>,nstate>> flux_at_support_pts(n_dofs_cell);
371  get_flux_at_support_pts(flux_at_support_pts, fe_values_volume, dof_indices, cell);
372 
373  // Compute Hessian
374  cellwise_hessian[cell_index] = 0;
375  for(unsigned int istate = 0; istate < nstate; ++istate)
376  {
377  for(unsigned int idim = 0; idim < dim; ++idim)
378  {
379  dealii::Tensor<2,dim,real> flux_hessian_at_istate_idim;
380  for(unsigned int idof = 0; idof<n_dofs_cell; ++idof)
381  {
382  const unsigned int icomp = fe_values_volume.get_fe().system_to_component_index(idof).first;
383  if(icomp == istate)
384  {
385  flux_hessian_at_istate_idim += flux_at_support_pts[idof][istate][idim]*fe_values_shape_hessian.shape_hessian_component(idof, iquad, istate, fe_ref);
386  }
387  } // idof
388  flux_hessian_at_istate_idim = get_positive_definite_tensor(flux_hessian_at_istate_idim);
389  flux_hessian_at_istate_idim *= abs(adjoint_gradient[istate][idim]);
390  cellwise_hessian[cell_index] += flux_hessian_at_istate_idim;
391  } //idim
392  } //istate
393  } // cell loop ends
394 }
395 
396 template<int dim, int nstate, typename real, typename MeshType>
398  const dealii::Quadrature<dim> &volume_quadrature) const
399 {
400  dealii::Point<dim,real> ref_center;
401  for(unsigned int idim = 0; idim < dim; ++idim){
402  ref_center[idim] = 0.5;}
403 
404  unsigned int iquad_center = 0;
405  real min_distance = 10000.0;
406  for(unsigned int iquad = 0; iquad<volume_quadrature.size(); ++iquad)
407  {
408  const dealii::Point<dim, real> &ref_point = volume_quadrature.point(iquad);
409  const real ref_distance = ref_point.distance(ref_center);
410  if(min_distance > ref_distance)
411  {
412  min_distance = ref_distance;
413  iquad_center = iquad;
414  }
415  }
416 
417  return iquad_center;
418 }
419 
420 // Flux referenced by flux[idof][istate][idim]
421 template<int dim, int nstate, typename real, typename MeshType>
423  std::vector<std::array<dealii::Tensor<1,dim,real>,nstate>> &flux_at_support_pts,
424  const dealii::FEValues<dim,dim> &fe_values_input,
425  const std::vector<dealii::types::global_dof_index> &dof_indices,
426  typename dealii::DoFHandler<dim>::active_cell_iterator cell) const
427 {
428  if( ! fe_values_input.get_fe().has_support_points() )
429  {
430  pcout<<"The code here treats flux at support points as flux coeff at idof "
431  <<"which requires an interpolatory FE with support points. Aborting.."<<std::endl;
432  std::abort();
433  }
434 
435  const unsigned int n_dofs_cell = dof_indices.size();
436  dealii::Quadrature<dim> support_pts = fe_values_input.get_fe().get_unit_support_points();
437  dealii::FEValues<dim, dim> fe_values_support_pts(fe_values_input.get_mapping(), fe_values_input.get_fe(),
438  support_pts, dealii::update_values);
439  fe_values_support_pts.reinit(cell);
440  const unsigned int n_quad_pts = fe_values_support_pts.n_quadrature_points;
441  Assert(n_quad_pts == n_dofs_cell, dealii::ExcMessage("n_quad_pts != n_dofs_cell"));
442 
443  for(unsigned int iquad = 0; iquad<n_quad_pts; ++iquad)
444  {
445  std::array< real, nstate > soln_at_q;
446  soln_at_q.fill(0.0);
447  for(unsigned int idof = 0; idof < n_dofs_cell; ++idof)
448  {
449  const unsigned int istate = fe_values_support_pts.get_fe().system_to_component_index(idof).first;
450  soln_at_q[istate] += dg->solution(dof_indices[idof]) * fe_values_support_pts.shape_value_component(idof, iquad, istate);
451  }
452 
453  flux_at_support_pts[iquad] = pde_physics_double->convective_flux(soln_at_q);
454  }
455 
456 }
457 
458 template<int dim, int nstate, typename real, typename MeshType>
460 {
462 
463  std::unique_ptr<MetricToMeshGenerator<dim, nstate, real>> metric_to_mesh_generator
464  = std::make_unique<MetricToMeshGenerator<dim, nstate, real>> (dg->high_order_grid->mapping_fe_field, dg->triangulation);
465  metric_to_mesh_generator->generate_mesh_from_cellwise_metric(cellwise_optimal_metric);
466 
467  std::shared_ptr<HighOrderGrid<dim,double,MeshType>> new_high_order_mesh =
468  read_gmsh <dim, dim> (metric_to_mesh_generator->get_generated_mesh_filename(), dg->all_parameters->do_renumber_dofs);
469  dg->set_high_order_grid(new_high_order_mesh);
470  dg->allocate_system();
471 
472  // Need to either interpolate or initialize solution on the new mesh. Currently just set it to 0.
473  dg->solution = 0;
474  dg->solution.update_ghost_values();
475 }
476 
477 // Instantiations
478 #if PHILIP_DIM!=1
484 #endif
485 } // PHiLiP namespace
std::shared_ptr< Functional< dim, nstate, real, MeshType > > functional
Functional to evaluate the adjoint for goal oriented anisotropic meshing.
int mpi_rank
Processor# of current processor.
void compute_feature_based_hessian()
Computes feature based hessian (i.e. hessian of the solution).
std::shared_ptr< DGBase< dim, real, MeshType > > dg
Shared pointer to DGBase.
dealii::Tensor< 2, dim, double > shape_hessian_component(const unsigned int idof, const unsigned int iquad, const unsigned int istate, const dealii::FESystem< dim, dim > &fe_ref) const
Evaluates hessian of shape functions w.r.t. phyical quadrature points.
void initialize_cellwise_metric_and_hessians()
Initializes cellwise metric and hessian to zero tensors.
std::pair< unsigned int, double > solve_linear(const dealii::TrilinosWrappers::SparseMatrix &system_matrix, dealii::LinearAlgebra::distributed::Vector< double > &right_hand_side, dealii::LinearAlgebra::distributed::Vector< double > &solution, const Parameters::LinearSolverParam &param)
dealii::ConditionalOStream pcout
std::cout only on processor #0.
std::shared_ptr< Physics::PhysicsBase< dim, nstate, real > > pde_physics_double
Contains the physics of the PDE with real type.
Files for the baseline physics.
Definition: ADTypes.hpp:10
void adapt_mesh()
Function which adapts mesh and loads in new mesh.
std::vector< dealii::Tensor< 2, dim, real > > cellwise_hessian
Stores hessian in each cell.
void get_flux_at_support_pts(std::vector< std::array< dealii::Tensor< 1, dim, real >, nstate >> &flux_at_support_pts, const dealii::FEValues< dim, dim > &fe_values_input, const std::vector< dealii::types::global_dof_index > &dof_indices, typename dealii::DoFHandler< dim >::active_cell_iterator cell) const
Returns flux coeffs by evaluating flux at support points of fe.
void reinit(const dealii::FEValues< dim, dim > &fe_values_volume, const unsigned int iquad)
Store inverse jacobian and 3rd order tensors which will be the same for a combination of cell/physica...
const real normLp
Lp Norm w.r.t. which the anlytical optimization is done.
dealii::LinearAlgebra::distributed::Vector< double > VectorType
Alias for dealii&#39;s parallel distributed vector.
unsigned int get_iquad_near_cellcenter(const dealii::Quadrature< dim > &volume_quadrature) const
Returns quadrature number of a point which is closest to the reference cell&#39;s center.
void compute_goal_oriented_hessian()
Computes pseudo Hessian for the goal oriented approach.
std::vector< dealii::Tensor< 2, dim, real > > cellwise_optimal_metric
Stores optimal metric in each cell.
const unsigned int max_dofs_per_cell
Stores max dofs per cell to initialize dof_indices.
void change_p_degree_and_interpolate_solution(const unsigned int poly_degree)
Change the polynomial order and interpolate solution.
static std::shared_ptr< ModelBase< dim, nstate, real > > create_Model(const Parameters::AllParameters *const parameters_input)
Factory to return the correct model given input parameters.
AnisotropicMeshAdaptation(std::shared_ptr< DGBase< dim, real, MeshType > > dg_input, const real _norm_Lp, const real _complexity, const bool _use_goal_oriented_approach=false)
Constructor.
dealii::Tensor< 2, dim, real > get_positive_definite_tensor(const dealii::Tensor< 2, dim, real > &input_tensor) const
Returns positive tensor from an input tensor by taking absolute of eigenvalues.
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.
void reconstruct_p2_solution()
Reconstructs p2 solution after interpolation.
const unsigned int initial_poly_degree
Stores initial polynomial degree.
Class to evaluate hessians of shape functions w.r.t. physical quadrature points.
static std::shared_ptr< Functional< dim, nstate, real, MeshType > > create_Functional(PHiLiP::Parameters::AllParameters const *const param, std::shared_ptr< PHiLiP::DGBase< dim, real, MeshType > > dg)
Create standard functional object from constant parameter file.
const bool use_goal_oriented_approach
Flag to use goal oriented approach. It is set to false by default.
void compute_cellwise_optimal_metric()
Computes optimal metric depending on goal oriented or feature based approach.
void compute_abs_hessian()
Computes hessian using the input coefficients, which can be a solution sensor or (for goal oriented a...
DGBase is independent of the number of state variables.
Definition: dg_base.hpp:82
MPI_Comm mpi_communicator
Alias for MPI_COMM_WORLD.
const real complexity
Analogue of number of vertices/elements in continuous mesh framework.