1 #include <deal.II/hp/fe_collection.h> 2 #include <deal.II/hp/fe_values.h> 3 #include <deal.II/hp/mapping_collection.h> 4 #include <deal.II/hp/q_collection.h> 5 #include <deal.II/dofs/dof_handler.h> 6 #include <deal.II/lac/la_parallel_vector.h> 7 #include <deal.II/base/tensor.h> 8 #include <deal.II/base/polynomial.h> 9 #include <deal.II/base/polynomial_space.h> 10 #include <deal.II/grid/grid_tools.h> 12 #include "reconstruct_poly.h" 13 #include "physics/manufactured_solution.h" 17 namespace GridRefinement {
19 template <
int dim,
int nstate,
typename real>
21 const dealii::DoFHandler<dim>& dof_handler,
22 const dealii::hp::MappingCollection<dim>& mapping_collection,
23 const dealii::hp::FECollection<dim>& fe_collection,
24 const dealii::hp::QCollection<dim>& quadrature_collection,
25 const dealii::UpdateFlags& update_flags) :
26 dof_handler(dof_handler),
27 mapping_collection(mapping_collection),
28 fe_collection(fe_collection),
29 quadrature_collection(quadrature_collection),
30 update_flags(update_flags),
31 norm_type(NormType::H1)
33 reinit(dof_handler.get_triangulation().n_active_cells());
36 template <
int dim,
int nstate,
typename real>
42 template <
int dim,
int nstate,
typename real>
50 template <
int dim,
int nstate,
typename real>
52 const dealii::LinearAlgebra::distributed::Vector<real>& solution,
53 const unsigned int rel_order)
66 if(!cell->is_locally_owned())
continue;
69 unsigned int order = cell->active_fe_index()+rel_order;
70 dealii::PolynomialSpace<dim> poly_space(dealii::Polynomials::Monomial<double>::generate_complete_basis(order));
79 const unsigned int n_poly = poly_space.n();
80 const unsigned int n_degree = poly_space.degree();
83 std::vector<real> coeffs;
84 std::vector<std::array<unsigned int, dim>> indices;
85 unsigned int n_vec = 0;
87 for(
unsigned int i = 0; i < n_poly; ++i){
88 std::array<unsigned int, dim> arr = compute_index<dim>(i, n_degree);
91 for(
int j = 0; j < dim; ++j)
99 coeffs.push_back(coeffs_non_hom[i]);
100 indices.push_back(arr);
105 std::array<real,dim> A_cell;
106 std::array<dealii::Tensor<1,dim,real>,dim> chord_vec;
110 std::array<std::pair<dealii::Tensor<1,dim,real>, dealii::Tensor<1,dim,real>>,dim> chord_nodes;
111 for(
unsigned int vertex = 0; vertex < dealii::GeometryInfo<dim>::vertices_per_cell; ++vertex){
114 for(
unsigned int i = 0; i < dim; ++i){
125 if(vertex>>i % 2 == 0){
126 chord_nodes[i].first += cell->vertex(vertex);
128 chord_nodes[i].second += cell->vertex(vertex);
136 for(
unsigned int i = 0; i < dim; ++i)
137 chord_vec[i] = chord_nodes[i].second - chord_nodes[i].first;
140 for(
unsigned int i = 0; i < dim; ++i)
141 chord_vec[i] /= chord_vec[i].
norm();
144 for(
unsigned int i = 0; i < dim; ++i){
146 for(
unsigned int n = 0; n < n_vec; ++n){
147 real poly_val = coeffs[n];
149 for(
unsigned int d = 0; d < dim; ++d)
150 poly_val *= pow(chord_vec[i][d], indices[n][d]);
153 A_cell[i] += poly_val;
157 const unsigned int index = cell->active_cell_index();
165 template <
int dim,
int nstate,
typename real>
167 const dealii::LinearAlgebra::distributed::Vector<real>& solution,
168 const unsigned int rel_order)
170 const real pi = atan(1)*4.0;
173 if(!cell->is_locally_owned())
continue;
176 unsigned int order = cell->active_fe_index()+rel_order;
177 dealii::PolynomialSpace<dim> poly_space(dealii::Polynomials::Monomial<double>::generate_complete_basis(order));
186 const unsigned int n_poly = poly_space.n();
187 const unsigned int n_degree = poly_space.degree();
190 std::vector<real> coeffs;
191 std::vector<std::array<unsigned int, dim>> indices;
192 unsigned int n_vec = 0;
194 for(
unsigned int i = 0; i < n_poly; ++i){
195 std::array<unsigned int, dim> arr = compute_index<dim>(i, n_degree);
197 unsigned int sum = 0;
198 for(
int j = 0; j < dim; ++j)
206 coeffs.push_back(coeffs_non_hom[i]);
207 indices.push_back(arr);
212 std::array<real,dim> value_cell;
213 std::array<dealii::Tensor<1,dim,real>,dim> direction_cell;
216 Assert(n_vec == 1, dealii::ExcInternalError());
218 value_cell[0] = coeffs[0];
219 direction_cell[0][0] = 1.0;
221 }
else if(order == 2){
224 Assert(n_vec == dim*(dim+1)/2, dealii::ExcInternalError());
226 dealii::SymmetricTensor<2,dim,real> hessian;
228 for(
unsigned int n = 0; n < n_vec; ++n){
231 for(
unsigned int i = 0; i < dim; ++i){
234 if((indices[n][i] == 2)){
235 hessian[i][i] = coeffs[n];
239 for(
unsigned int j = i+1; j < dim; ++j){
240 if((indices[n][i] == 1) && (indices[n][j] == 1)){
241 hessian[i][j] = 0.5 * coeffs[n];
256 using eigenpair = std::pair<real,dealii::Tensor<1,dim,real>>;
257 std::array<eigenpair,dim> eig = dealii::eigenvectors(hessian);
260 std::sort(eig.begin(), eig.end(), [](
261 const eigenpair left,
262 const eigenpair right)
264 return abs(left.first) > abs(right.first);
268 for(
int d = 0; d < dim; ++d){
269 value_cell[d] = abs(eig[d].first);
270 direction_cell[d] = eig[d].second;
276 auto eval = [&](
const dealii::Tensor<1,dim,real>& point) -> real{
278 for(
unsigned int i = 0; i < n_vec; ++i){
279 real val_coeff = coeffs[i];
280 for(
int d = 0; d < dim; ++d)
281 val_coeff *= pow(point[d], indices[i][d]);
291 const unsigned int n_sample = 180;
294 real A_max = 0.0, t_max = 0.0;
297 real r = 1.0, theta, val;
298 dealii::Tensor<1,dim,real> p_sample;
299 for(
unsigned int i = 0; i < n_sample; ++i){
300 theta = i*pi/n_sample;
302 p_sample[0] = r*cos(theta);
303 p_sample[1] = r*sin(theta);
305 val = abs(eval(p_sample));
312 dealii::Tensor<1,dim,real> p_1;
313 p_1[0] = r*cos(t_max);
314 p_1[1] = r*sin(t_max);
317 dealii::Tensor<1,dim,real> p_2;
318 p_2[0] = r*cos(t_max+pi/2.0);
319 p_2[1] = r*sin(t_max+pi/2.0);
321 value_cell[0] = A_max;
322 value_cell[1] = abs(eval(p_2));
324 direction_cell[0] = p_1;
325 direction_cell[1] = p_2;
331 const unsigned int n_sample = 180, n_sample_3d = 180*90;
335 dealii::Tensor<1,dim,real> p_1;
338 real offset = 1.0/n_sample_3d;
339 real increment = pi * (3 - sqrt(5));
343 dealii::Tensor<1,dim,real> p_sample;
344 for(
unsigned int i = 0; i < n_sample_3d; ++i){
346 y = (i*offset) - 1 + offset/2;
347 r = sqrt(1-pow(y,2));
349 phi = remainder(i, 2*n_sample_3d) * increment;
351 p_sample[0] = r*cos(phi);
353 p_sample[2] = r*sin(phi);
355 val = abs(eval(p_sample));
358 p_1 = p_sample/p_sample.norm();
363 dealii::Tensor<1,dim,real> u;
364 dealii::Tensor<1,dim,real> v;
367 dealii::Tensor<1,dim,real> px;
369 if(abs(px*p_1) < 1.0/sqrt(2.0)){
371 u = dealii::cross_product_3d(p_1, px);
373 dealii::Tensor<1,dim,real> py;
375 u = dealii::cross_product_3d(p_1, py);
378 v = dealii::cross_product_3d(p_1, u);
385 real A_2 = 0.0, t_2 = 0.0;
389 dealii::Tensor<1,dim,real> p_2;
390 for(
unsigned int i = 0; i < n_sample; ++i){
391 theta = i*pi/n_sample;
392 p_2 = cos(theta)*u + sin(theta)*v;
394 val = abs(eval(p_2));
402 p_2 = cos(t_2)*u + sin(t_2)*v;
405 dealii::Tensor<1,dim,real> p_3 = cos(t_2+pi/2.0)*u + sin(t_2+pi/2.0)*v;
410 value_cell[2] = abs(eval(p_3));
412 direction_cell[0] = p_1;
413 direction_cell[1] = p_2;
414 direction_cell[2] = p_3;
419 Assert(
false, dealii::ExcInternalError());
425 const unsigned int index = cell->active_cell_index();
431 template <
int dim,
int nstate,
typename real>
434 const unsigned int rel_order)
437 if(!cell->is_locally_owned())
continue;
439 unsigned int order = cell->active_fe_index() + rel_order;
444 dealii::Point<dim,real> center_point = cell->center();
445 dealii::SymmetricTensor<2,dim,real> hessian =
446 manufactured_solution->hessian(center_point);
449 using eigenpair = std::pair<real,dealii::Tensor<1,dim,real>>;
450 std::array<eigenpair,dim> eig = dealii::eigenvectors(hessian);
452 std::sort(eig.begin(), eig.end(), [](
453 const eigenpair left,
454 const eigenpair right)
456 return abs(left.first) > abs(right.first);
460 const unsigned int index = cell->active_cell_index();
461 for(
int d = 0; d < dim; ++d){
473 std::array<unsigned int, 1> compute_index<1>(
474 const unsigned int i,
481 std::array<unsigned int, 2> compute_index<2>(
482 const unsigned int i,
483 const unsigned int size)
486 for(
unsigned int iy = 0; iy < size; ++iy)
493 Assert(
false, dealii::ExcInternalError());
494 return {{dealii::numbers::invalid_unsigned_int, dealii::numbers::invalid_unsigned_int}};
498 std::array<unsigned int, 3> compute_index<3>(
499 const unsigned int i,
500 const unsigned int size)
503 for(
unsigned int iz = 0; iz < size; ++iz)
504 for(
unsigned int iy = 0; iy < size - iz; ++iy)
506 return {{i-k, iy, iz}};
511 Assert(
false, dealii::ExcInternalError());
512 return {{dealii::numbers::invalid_unsigned_int, dealii::numbers::invalid_unsigned_int, dealii::numbers::invalid_unsigned_int}};
515 template <
int dim,
int nstate,
typename real>
516 template <
typename DoFCellAccessorType>
519 const DoFCellAccessorType & curr_cell,
520 const dealii::PolynomialSpace<dim> ps,
521 const dealii::LinearAlgebra::distributed::Vector<real> &solution)
524 if(norm_type == NormType::H1){
531 }
else if(norm_type == NormType::L2){
542 return dealii::Vector<real>(0);
548 template <
int dim,
int nstate,
typename real>
549 template <
typename DoFCellAccessorType>
551 const DoFCellAccessorType & curr_cell,
552 const dealii::PolynomialSpace<dim> ps,
553 const dealii::LinearAlgebra::distributed::Vector<real> &solution)
557 dealii::Point<dim,real> center_point = curr_cell->center();
560 std::vector<std::array<real,nstate>> soln_at_q_vec;
561 std::vector<std::array<dealii::Tensor<1,dim,real>,nstate>> grad_at_q_vec;
562 std::vector<dealii::Point<dim,real>> qpoint_vec;
563 std::vector<real> JxW_vec;
566 unsigned int n_vec = 0;
569 dealii::hp::FEValues<dim,dim> fe_values_collection(
578 for(
auto cell : cell_patch){
579 const unsigned int mapping_index = 0;
580 const unsigned int fe_index = cell->active_fe_index();
581 const unsigned int quad_index = fe_index;
583 const unsigned int n_dofs =
fe_collection[fe_index].n_dofs_per_cell();
586 fe_values_collection.reinit(cell, quad_index, mapping_index, fe_index);
587 const dealii::FEValues<dim,dim> &fe_values = fe_values_collection.get_present_fe_values();
589 std::vector<dealii::types::global_dof_index> dofs_indices(fe_values.dofs_per_cell);
590 cell->get_dof_indices(dofs_indices);
593 std::array<real,nstate> soln_at_q;
594 std::array<dealii::Tensor<1,dim,real>,nstate> grad_at_q;
595 for(
unsigned int iquad = 0; iquad < n_quad; ++iquad){
597 for(
unsigned int istate = 0; istate < nstate; ++istate)
598 grad_at_q[istate] = 0.0;
601 for(
unsigned int idof = 0; idof < n_dofs; ++idof){
602 const unsigned int istate = fe_values.get_fe().system_to_component_index(idof).first;
603 soln_at_q[istate] += solution[dofs_indices[idof]] * fe_values.shape_value_component(idof, iquad, istate);
604 grad_at_q[istate] += solution[dofs_indices[idof]] * fe_values.shape_grad_component(idof, iquad, istate);
608 dealii::Tensor<1,dim,real> tensor_q = fe_values.quadrature_point(iquad) - center_point;
609 dealii::Point<dim,real> point_q(tensor_q);
612 soln_at_q_vec.push_back(soln_at_q);
613 grad_at_q_vec.push_back(grad_at_q);
614 qpoint_vec.push_back(point_q);
615 JxW_vec.push_back(fe_values.JxW(iquad));
621 const unsigned int n_poly = ps.n();
624 dealii::FullMatrix<real> mat(n_poly);
625 dealii::Vector<real> rhs(n_poly);
629 for(
unsigned int i_poly = 0; i_poly < n_poly; ++i_poly){
630 for(
unsigned int j_poly = 0; j_poly < n_poly; ++j_poly){
633 for(
unsigned int i_vec = 0; i_vec < n_vec; ++i_vec)
634 mat.add(i_poly, j_poly,
635 ((ps.compute_value(i_poly, qpoint_vec[i_vec]) * ps.compute_value(j_poly, qpoint_vec[i_vec]))
636 +(ps.compute_grad(i_poly, qpoint_vec[i_vec]) * ps.compute_grad(j_poly, qpoint_vec[i_vec])))
642 dealii::Vector<real> rhs_poly(nstate);
643 for(
unsigned int istate = 0; istate < nstate; ++istate)
644 for(
unsigned int i_vec = 0; i_vec < n_vec; ++i_vec)
645 rhs[i_poly] += ((ps.compute_value(i_poly, qpoint_vec[i_vec]) * soln_at_q_vec[i_vec][istate])
646 +(ps.compute_grad(i_poly, qpoint_vec[i_vec]) * grad_at_q_vec[i_vec][istate]))
651 dealii::Vector<real> coeffs(n_poly);
654 mat.vmult(coeffs, rhs);
659 template <
int dim,
int nstate,
typename real>
660 template <
typename DoFCellAccessorType>
662 const DoFCellAccessorType & curr_cell,
663 const dealii::PolynomialSpace<dim> ps,
664 const dealii::LinearAlgebra::distributed::Vector<real> &solution)
667 dealii::Point<dim,real> center_point = curr_cell->center();
670 std::vector<std::array<real,nstate>> soln_at_q_vec;
671 std::vector<dealii::Point<dim,real>> qpoint_vec;
672 std::vector<real> JxW_vec;
675 unsigned int n_vec = 0;
678 dealii::hp::FEValues<dim,dim> fe_values_collection(
687 for(
auto cell : cell_patch){
688 const unsigned int mapping_index = 0;
689 const unsigned int fe_index = cell->active_fe_index();
690 const unsigned int quad_index = fe_index;
692 const unsigned int n_dofs =
fe_collection[fe_index].n_dofs_per_cell();
695 fe_values_collection.reinit(cell, quad_index, mapping_index, fe_index);
696 const dealii::FEValues<dim,dim> &fe_values = fe_values_collection.get_present_fe_values();
698 std::vector<dealii::types::global_dof_index> dofs_indices(fe_values.dofs_per_cell);
699 cell->get_dof_indices(dofs_indices);
702 std::array<real,nstate> soln_at_q;
703 for(
unsigned int iquad = 0; iquad < n_quad; ++iquad){
707 for(
unsigned int idof = 0; idof < n_dofs; ++idof){
708 const unsigned int istate = fe_values.get_fe().system_to_component_index(idof).first;
709 soln_at_q[istate] += solution[dofs_indices[idof]] * fe_values.shape_value_component(idof, iquad, istate);
713 dealii::Tensor<1,dim,real> tensor_q = fe_values.quadrature_point(iquad) - center_point;
714 dealii::Point<dim,real> point_q(tensor_q);
717 soln_at_q_vec.push_back(soln_at_q);
718 qpoint_vec.push_back(point_q);
719 JxW_vec.push_back(fe_values.JxW(iquad));
725 const unsigned int n_poly = ps.n();
728 dealii::FullMatrix<real> mat(n_poly);
729 dealii::Vector<real> rhs(n_poly);
733 for(
unsigned int i_poly = 0; i_poly < n_poly; ++i_poly){
734 for(
unsigned int j_poly = 0; j_poly < n_poly; ++j_poly){
737 for(
unsigned int i_vec = 0; i_vec < n_vec; ++i_vec)
738 mat.add(i_poly, j_poly,
739 (ps.compute_value(i_poly, qpoint_vec[i_vec]) * ps.compute_value(j_poly, qpoint_vec[i_vec]))
745 dealii::Vector<real> rhs_poly(nstate);
746 for(
unsigned int istate = 0; istate < nstate; ++istate)
747 for(
unsigned int i_vec = 0; i_vec < n_vec; ++i_vec)
748 rhs[i_poly] += (ps.compute_value(i_poly, qpoint_vec[i_vec]) * soln_at_q_vec[i_vec][istate])
753 dealii::Vector<real> coeffs(n_poly);
756 mat.vmult(coeffs, rhs);
764 template <
int dim,
int nstate,
typename real>
765 template <
typename DoFCellAccessorType>
767 const DoFCellAccessorType &cell)
769 Assert(cell->is_locally_owned(), dealii::ExcInternalError());
771 std::vector<DoFCellAccessorType> patch;
772 patch.push_back(cell);
774 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
775 if(cell->face(iface)->at_boundary())
continue;
777 Assert(cell->neighbor(iface).state() == dealii::IteratorState::valid,
778 dealii::ExcInternalError());
780 if(cell->neighbor(iface)->has_children() ==
false){
781 patch.push_back(cell->neighbor(iface));
784 for(
unsigned int subface = 0; subface < cell->face(iface)->n_children(); ++subface)
785 patch.push_back(cell->neighbor_child_on_subface(iface, subface));
787 DoFCellAccessorType neighbor = cell->neighbor(iface);
790 while(neighbor->has_children())
791 neighbor = neighbor->child(1-iface);
793 Assert(neighbor->neighbor(1-iface) == cell, dealii::ExcInternalError());
794 patch.push_back(neighbor);
802 template <
int dim,
int nstate,
typename real>
804 const unsigned int index)
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.
std::vector< std::array< dealii::Tensor< 1, dim, real >, dim > > derivative_direction
Derivative directions.
Polynomial Reconstruction Class.
Manufactured solution used for grid studies to check convergence orders.
dealii::Vector< real > reconstruct_norm(const NormType norm_type, const DoFCellAccessorType &curr_cell, const dealii::PolynomialSpace< dim > ps, const dealii::LinearAlgebra::distributed::Vector< real > &solution)
Performs polynomial patchwise reconstruction on the current cell in the selected norm.
const dealii::UpdateFlags & update_flags
Update flags used in obtaining local cell representation.
const dealii::hp::MappingCollection< dim > & mapping_collection
Collection of mapping rules for reference element conversion.
Files for the baseline physics.
void reconstruct_directional_derivative(const dealii::LinearAlgebra::distributed::Vector< real > &solution, const unsigned int rel_order)
Construct the set of largest perpendicular directional derivatives.
void reinit(const unsigned int n)
Reinitialze the internal vectors.
std::vector< std::array< real, dim > > derivative_value
Derivative values.
const dealii::hp::FECollection< dim > & fe_collection
Collection of Finite elements to represent discontinuous solution space.
ReconstructPoly(const dealii::DoFHandler< dim > &dof_handler, const dealii::hp::MappingCollection< dim > &mapping_collection, const dealii::hp::FECollection< dim > &fe_collection, const dealii::hp::QCollection< dim > &quadrature_collection, const dealii::UpdateFlags &update_flags)
Constructor. Stores required information about the mesh and quadrature rules.
void set_norm_type(const NormType norm_type)
Select the Norm to be used in reconstruction.
NormType norm_type
Setting controls the choice of norm used in reconstruction. Set via set_norm_type.
dealii::Vector< real > get_derivative_value_vector_dealii(const unsigned int index)
Gets the i^th largest componet of the directional derivative vector as a dealii::Vector.
const dealii::DoFHandler< dim > & dof_handler
Degree of freedom handler for iteration over mesh elements and their nodes.
dealii::Vector< real > reconstruct_H1_norm(const DoFCellAccessorType &curr_cell, const dealii::PolynomialSpace< dim > ps, const dealii::LinearAlgebra::distributed::Vector< real > &solution)
Performs polynomial patchwise reconstruction on the current cell in the H1 semi-norm.
const dealii::hp::QCollection< dim > & quadrature_collection
Collection of quadrature rules used to evaluate volume integrals.
std::vector< DoFCellAccessorType > get_patch_around_dof_cell(const DoFCellAccessorType &cell)
Get the patch of cells surrounding the current cell of DofCellAccessorType.
void reconstruct_manufactured_derivative(const std::shared_ptr< ManufacturedSolutionFunction< dim, real >> &manufactured_solution, const unsigned int rel_order)
Constructs directional derivates based on the manufactured solution hessian.
dealii::Vector< real > reconstruct_L2_norm(const DoFCellAccessorType &curr_cell, const dealii::PolynomialSpace< dim > ps, const dealii::LinearAlgebra::distributed::Vector< real > &solution)
Performs polynomial patchwise reconstruction on the current cell in the L2 norm.
real1 norm(const dealii::Tensor< 1, dim, real1 > x)
Returns norm of dealii::Tensor<1,dim,real>