// Fill prolongation matrices with embedding operators
FETools::compute_embedding_matrices (*this, this->prolongation);
initialize_restriction ();
-
- switch (dim)
- {
- case 2:
- this->interface_constraints.reinit (
- GeometryInfo<dim>::max_children_per_face * this->dofs_per_face,
- this->dofs_per_face);
- break;
- case 3:
- this->interface_constraints.reinit (
- GeometryInfo<dim>::max_children_per_face * this->dofs_per_face
- - 4 * this->dofs_per_line,
- this->dofs_per_face);
- break;
- default:
- Assert(false, ExcNotImplemented());
- break;
- }
-
+
FullMatrix<double> face_embeddings[GeometryInfo<dim>::max_children_per_face];
-
+
for (unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_face; ++i)
- face_embeddings[i].reinit (this->dofs_per_face, this->dofs_per_face);
-
+ face_embeddings[i].reinit (this->dofs_per_face, this->dofs_per_face);
+
FETools::compute_face_embedding_matrices<dim,double>
(*this, face_embeddings, 0, 0);
-
- // In two space dimensions, things are easy, since the child
- // faces do not share any degrees of freedom
- Assert (dim<4, ExcNotImplemented());
- if (dim==2)
- {
- unsigned int target_row = 0;
-
- for (unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_face; ++i)
- for (unsigned int j = 0; j < face_embeddings[i].m (); ++j)
- {
- for (unsigned int k = 0; k < face_embeddings[i].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[i] (j, k);
-
- ++target_row;
- }
- }
- // Now the 2D case, where the children share degrees of freedom on
- // edges. which means, we must go though all edges to reproduce the numbering.
- // Lets pray that at least the subfaces are numbered as expected
- else
- {
- unsigned int target_row = 0;
- // right edge of lower left child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + this->dofs_per_line + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[0] (j, k);
- ++target_row;
- }
- // right edge of upper left child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + this->dofs_per_line + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[2] (j, k);
- ++target_row;
- }
- // upper edge of lower left child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + 3*this->dofs_per_line + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[0] (j, k);
- ++target_row;
- }
- // upper edge of lower right child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + 3*this->dofs_per_line + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[1] (j, k);
- ++target_row;
- }
- // left edge of lower left child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[0] (j, k);
- ++target_row;
- }
- // left edge of upper left child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[2] (j, k);
- ++target_row;
- }
- // right edge of lower right child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + this->dofs_per_line + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[1] (j, k);
- ++target_row;
- }
- // right edge of upper right child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + this->dofs_per_line + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[3] (j, k);
- ++target_row;
- }
- // lower edge of lower left child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + 2*this->dofs_per_line + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[0] (j, k);
- ++target_row;
- }
- // lower edge of lower right child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + 2*this->dofs_per_line + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[1] (j, k);
- ++target_row;
- }
- // upper edge of upper left child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + 3*this->dofs_per_line + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[2] (j, k);
- ++target_row;
- }
- // upper edge of upper right child
- for (unsigned int jj = 0; jj < this->dofs_per_line; ++jj)
- {
- const unsigned int j = this->first_face_line_index + 3*this->dofs_per_line + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[3] (j, k);
- ++target_row;
- }
- // Now the interior dofs of each subface
- for (unsigned int jj = 0; jj < this->dofs_per_quad; ++jj)
- {
- const unsigned int j = this->first_face_quad_index + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[0] (j, k);
- ++target_row;
- }
- for (unsigned int jj = 0; jj < this->dofs_per_quad; ++jj)
- {
- const unsigned int j = this->first_face_quad_index + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[1] (j, k);
- ++target_row;
- }
- for (unsigned int jj = 0; jj < this->dofs_per_quad; ++jj)
- {
- const unsigned int j = this->first_face_quad_index + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[2] (j, k);
- ++target_row;
- }
- for (unsigned int jj = 0; jj < this->dofs_per_quad; ++jj)
- {
- const unsigned int j = this->first_face_quad_index + jj;
- for (unsigned int k = 0; k < face_embeddings[0].n (); ++k)
- this->interface_constraints (target_row, k)
- = face_embeddings[3] (j, k);
- ++target_row;
- }
- Assert(target_row == this->interface_constraints.m(), ExcInternalError());
- }
+ this->interface_constraints.reinit ((1 << (dim - 1)) * this->dofs_per_face,
+ this->dofs_per_face);
+
+ unsigned int target_row = 0;
+
+ for (unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_face; ++i)
+ for (unsigned int j = 0; j < face_embeddings[i].m (); ++j)
+ {
+ for (unsigned int k = 0; k < face_embeddings[i].n (); ++k)
+ this->interface_constraints (target_row, k)
+ = face_embeddings[i] (j, k);
+
+ ++target_row;
+ }
}
// have to be kept in synch
std::ostringstream namebuf;
- namebuf << "FE_Nedelec<" << dim << ">(" << this->tensor_degree()-1 << ")";
+ namebuf << "FE_Nedelec<" << dim << ">(" << deg << ")";
return namebuf.str();
}
void
FE_Nedelec<dim>::initialize_restriction ()
{
- // To save some computation time we just
- // put in the correct values, which can
- // be calculated by projection-based
- // interpolation.
+ // This function does the same as the
+ // function interpolate further below.
+ // But since the functions, which we
+ // interpolate here, are discontinuous
+ // we have to use more quadrature
+ // points as in interpolate.
+ const QGauss<1> edge_quadrature (2 * this->degree);
+ const std::vector<Point<1> >& edge_quadrature_points
+ = edge_quadrature.get_points ();
+ const unsigned int&
+ n_edge_quadrature_points = edge_quadrature.size ();
+
switch (dim)
{
case 2:
{
- const unsigned int n_boundary_dofs
- = GeometryInfo<dim>::lines_per_cell * this->degree;
-
- for (unsigned int ref = RefinementCase<dim>::cut_x;
- ref <= RefinementCase<dim>::isotropic_refinement; ++ref)
+ for (unsigned int ref = RefinementCase<2>::cut_x;
+ ref <= RefinementCase<2>::isotropic_refinement; ++ref)
{
const unsigned int index = ref - 1;
switch (ref)
{
- case RefinementCase<dim>::cut_x:
- {
- for (unsigned int i = 0; i <= deg; ++i)
- {
- for (unsigned int j = 0; j < 2; ++j)
- this->restriction[index][j] (i + j * this->degree,
- i + j * this->degree)
- = 2.0;
-
- for (unsigned int j = 2;
- j < GeometryInfo<dim>::lines_per_cell; ++j)
- for (unsigned int k = 0; k < 2; ++k)
- this->restriction[index][k]
- (i + j * this->degree, i + j * this->degree)
- = 1.0;
-
- for (unsigned int j = 0; j < deg; ++j)
- for (unsigned int k = 0; k < 2; ++k)
- for (unsigned int child = 0;
- child < GeometryInfo<dim>::n_children
- (RefinementCase<dim> (ref));
- ++ child)
- this->restriction[index][child]
- ((i + k * this->degree) * deg + j
- + n_boundary_dofs,
- (i + k * this->degree) * deg + j
- + n_boundary_dofs) = 1.0;
- }
-
- break;
- }
-
- case RefinementCase<dim>::cut_y:
- {
- for (unsigned int i = 0; i < this->degree; ++i)
- {
- for (unsigned int j = 0; j < 2; ++j)
- {
- for (unsigned int k = 0; k < 2; ++k)
- this->restriction[index][k]
- (i + j * this->degree, i + j * this->degree)
- = 1.0;
-
- this->restriction[index][j]
- (i + (j + 2) * this->degree,
- i + (j + 2) * this->degree) = 2.0;
- }
-
- for (unsigned int j = 0; j < deg; ++j)
- for (unsigned int k = 0; k < 2; ++k)
- for (unsigned int child = 0;
- child < GeometryInfo<dim>::n_children
- (RefinementCase<dim> (ref));
- ++ child)
- this->restriction[index][child]
- ((i + k * this->degree) * deg + j
- + n_boundary_dofs,
- (i + k * this->degree) * deg + j
- + n_boundary_dofs) = 1.0;
- }
-
- break;
- }
-
- case RefinementCase<dim>::isotropic_refinement:
+ case RefinementCase<2>::cut_x:
{
- for (unsigned int i = 0; i < this->degree; ++i)
- {
- for (unsigned int j = 0; j < 2; ++j)
+ // First interpolate the shape
+ // functions of the child cells
+ // to the lowest order shape
+ // functions of the parent cell.
+ for (unsigned int dof = 0; dof < this->dofs_per_cell;
+ ++dof)
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
+ {
{
- this->restriction[index][j]
- (i + j * this->degree, i + j * this->degree)
- = 1.0;
- this->restriction[index][j]
- (i + 2 * this->degree, i + 2 * this->degree)
- = 1.0;
- this->restriction[index][j + 2]
- (i + j * this->degree, i + j * this->degree)
- = 1.0;
- this->restriction[index][j + 2]
- (i + 3 * this->degree, i + 3 * this->degree)
- = 1.0;
+ const double
+ weight = edge_quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ {
+ const Point<dim>
+ quadrature_point
+ (i, edge_quadrature_points[q_point] (0));
+
+ this->restriction[index][i]
+ (i * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 1);
+ }
}
-
- for (unsigned int j = 0; j < deg; ++j)
- for (unsigned int k = 0; k < 2; ++k)
- for (unsigned int child = 0;
- child < GeometryInfo<dim>::n_children
- (RefinementCase<dim> (ref));
- ++ child)
- this->restriction[index][child]
- ((i + k * this->degree) * deg + j
- + n_boundary_dofs,
- (i + k * this->degree) * deg + j
- + n_boundary_dofs) = 0.5;
- }
-
- break;
- }
-
- default:
- Assert (false, ExcNotImplemented ());
- }
- }
-
- break;
- }
-
- case 3:
- {
- const unsigned int n_edge_dofs
- = GeometryInfo<dim>::lines_per_cell * deg;
- const unsigned int n_boundary_dofs
- = n_edge_dofs
- + 2 * GeometryInfo<dim>::faces_per_cell * deg * this->degree;
-
- for (unsigned int ref = RefinementCase<dim>::cut_x;
- ref <= RefinementCase<dim>::isotropic_refinement; ++ref)
- {
- const unsigned int index = ref - 1;
-
- switch (ref)
- {
- case RefinementCase<3>::cut_x:
- {
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < 2; ++j)
- {
- this->restriction[index][j] (i + j * this->degree,
- i + j * this->degree)
- = 2.0;
- this->restriction[index][j] (i + 2 * this->degree,
- i + 2 * this->degree)
- = 1.0;
- this->restriction[index][j] (i + 3 * this->degree,
- i + 3 * this->degree)
- = 1.0;
- this->restriction[index][j]
- (i + (j + 4) * this->degree,
- i + (j + 4) * this->degree) = 2.0;
- this->restriction[index][j] (i + 6 * this->degree,
- i + 6 * this->degree)
- = 1.0;
- this->restriction[index][j] (i + 7 * this->degree,
- i + 7 * this->degree)
- = 1.0;
- this->restriction[index][j]
- (i + (j + 8) * this->degree,
- i + (j + 8) * this->degree) = 2.0;
- this->restriction[index][j]
- (i + (j + 10) * this->degree,
- i + (j + 10) * this->degree) = 2.0;
- }
-
- for (unsigned int i = 0; i < 2 * this->degree * deg; ++i)
- for (unsigned int j = 0; j < 2; ++j)
- {
- this->restriction[index][j]
- (i + j * this->degree * deg + n_edge_dofs,
- i + j * this->degree + deg + n_edge_dofs) = 2.0;
-
- for (unsigned int k = 0; k < 4; ++k)
- this->restriction[index][j]
- (i + (2 * k + 4) * this->degree * deg
- + n_edge_dofs,
- i + (2 * k + 4) * this->degree * deg
- + n_edge_dofs) = 1.0;
+
+ const double weight
+ = 2.0 * edge_quadrature.weight (q_point);
+
+ if (edge_quadrature_points[q_point] (0) < 0.5)
+ for (unsigned int i = 0; i < 2; ++i)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * edge_quadrature_points[q_point] (0),
+ i);
+
+ this->restriction[index][0]
+ ((i + 2) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ }
+
+ else
+ for (unsigned int i = 0; i < 2; ++i)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0, i);
+
+ this->restriction[index][1]
+ ((i + 2) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ }
}
-
- break;
- }
-
- case RefinementCase<3>::cut_y:
- {
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < 2; ++j)
+ // Then project the shape functions
+ // of the child cells to the higher
+ // order shape functions of the
+ // parent cell.
+ if (deg > 0)
+ {
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials
+ = Polynomials::Legendre::generate_complete_basis
+ (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
{
- this->restriction[index][j] (i, i) = 1.0;
- this->restriction[index][j] (i + this->degree,
- i + this->degree)
- = 1.0;
- this->restriction[index][j]
- (i + (j + 2) * this->degree,
- i + (j + 2) * this->degree) = 2.0;
- this->restriction[index][j] (i + 4 * this->degree,
- i + 4 * this->degree)
- = 1.0;
- this->restriction[index][j] (i + 5 * this->degree,
- i + 5 * this->degree)
- = 1.0;
-
- for (unsigned int k = 3; k < 6; ++k)
- this->restriction[index][j]
- (i + (j + 2 * k) * this->degree,
- i + (j + 2 * k) * this->degree) = 2.0;
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (edge_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point)
+ = weight
+ * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+ }
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
}
-
- for (unsigned int i = 0; i < 2 * this->degree * deg; ++i)
- for (unsigned int j = 0; j < 2; ++j)
+
+ FullMatrix<double> solution (deg, 3);
+ FullMatrix<double> system_rhs (deg, 3);
+ Vector<double> tmp (3);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ for (unsigned int i = 0; i < 2; ++i)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = edge_quadrature.weight (q_point);
+ Point<dim> quadrature_point_0 (i,
+ edge_quadrature_points[q_point]
+ (0));
+
+ tmp (0) = weight
+ * (this->shape_value_component
+ (dof, quadrature_point_0, 1)
+ - this->restriction[index][i]
+ (i * this->degree, dof)
+ * this->shape_value_component
+ (i * this->degree,
+ quadrature_point_0, 1));
+ quadrature_point_0
+ = Point<dim> (edge_quadrature_points[q_point] (0),
+ i);
+
+ if (edge_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point_1 (2.0 * edge_quadrature_points[q_point] (0),
+ i);
+
+ tmp (1) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_1,
+ 0)
+ - this->restriction[index][0]
+ ((i + 2) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2) * this->degree,
+ quadrature_point_0,
+ 0));
+ tmp (2) = -1.0 * weight
+ * this->restriction[index][1]
+ ((i + 2) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2) * this->degree,
+ quadrature_point_0,
+ 0);
+ }
+
+ else
+ {
+ tmp (1) = -1.0 * weight
+ * this->restriction[index][0]
+ ((i + 2) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2) * this->degree,
+ quadrature_point_0,
+ 0);
+
+ const Point<dim>
+ quadrature_point_1 (2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0,
+ i);
+
+ tmp (2) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_1,
+ 0)
+ - this->restriction[index][1]
+ ((i + 2) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2) * this->degree,
+ quadrature_point_0,
+ 0));
+ }
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double L_j
+ = legendre_polynomials[j + 1].value
+ (edge_quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0;
+ k < tmp.size (); ++k)
+ system_rhs (j, k) += tmp (k) * L_j;
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ if (std::abs (solution (j, 0)) > 1e-14)
+ this->restriction[index][i]
+ (i * this->degree + j + 1, dof)
+ = solution (j, 0);
+
+ for (unsigned int k = 0; k < 2; ++k)
+ if (std::abs (solution (j, k + 1))
+ > 1e-14)
+ this->restriction[index][k]
+ ((i + 2) * this->degree + j + 1,
+ dof) = solution (j, k + 1);
+ }
+ }
+
+ const QGauss<dim> quadrature (2 * this->degree);
+ const std::vector<Point<dim> >&
+ quadrature_points = quadrature.get_points ();
+ const std::vector<Polynomials::Polynomial<double> >&
+ lobatto_polynomials = Polynomials::Lobatto::generate_complete_basis
+ (this->degree);
+ const unsigned int n_boundary_dofs
+ = GeometryInfo<dim>::faces_per_cell * this->degree;
+ const unsigned int& n_quadrature_points
+ = quadrature.size ();
+
{
- this->restriction[index][j] (i + n_edge_dofs,
- i + n_edge_dofs)
- = 1.0;
- this->restriction[index][j]
- (i + 2 * this->degree * deg + n_edge_dofs,
- i + 2 * this->degree * deg + n_edge_dofs) = 1.0;
- this->restriction[index][j]
- (i + (2 * j + 4) * this->degree * deg
- + n_edge_dofs,
- i + (2 * j + 4) * this->degree * deg
- + n_edge_dofs) = 2.0;
- this->restriction[index][j]
- (i + 8 * this->degree * deg + n_edge_dofs,
- i + 8 * this->degree * deg + n_edge_dofs) = 1.0;
- this->restriction[index][j]
- (i + 10 * this->degree * deg + n_edge_dofs,
- i + 10 * this->degree * deg + n_edge_dofs) = 1.0;
+ FullMatrix<double>
+ assembling_matrix (deg * this->degree,
+ n_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ const double weight
+ = std::sqrt (quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i
+ = weight * legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ assembling_matrix (i * deg + j,
+ q_point)
+ = L_i * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
}
-
- break;
- }
-
- case RefinementCase<3>::cut_xy:
- {
- for (unsigned int i = 0; i <= deg; ++i)
- {
- for (unsigned int j = 0; j < 2; ++j)
+
+ solution.reinit (system_matrix_inv.m (), 4);
+ system_rhs.reinit (system_matrix_inv.m (), 4);
+ tmp.reinit (4);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
{
- this->restriction[index][2 * j] (i, i) = 1.0;
- this->restriction[index][2 * j + 1]
- (i + this->degree, i + this->degree) = 1.0;
- this->restriction[index][j]
- (i + 2 * this->degree, i + 2 * this->degree)
- = 1.0;
- this->restriction[index][j + 2]
- (i + 3 * this->degree, i + 3 * this->degree)
- = 1.0;
- this->restriction[index][2 * j]
- (i + 4 * this->degree, i + 4 * this->degree)
- = 1.0;
- this->restriction[index][2 * j + 1]
- (i + 5 * this->degree, i + 5 * this->degree)
- = 1.0;
- this->restriction[index][j]
- (i + 6 * this->degree, i + 6 * this->degree)
- = 1.0;
- this->restriction[index][j + 2]
- (i + 7 * this->degree, i + 7 * this->degree)
- = 1.0;
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ tmp = 0.0;
+
+ if (quadrature_points[q_point] (0) < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0),
+ quadrature_points[q_point] (1));
+
+ tmp (0) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (1) += this->shape_value_component
+ (dof, quadrature_point, 1);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ quadrature_points[q_point] (1));
+
+ tmp (2) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (3) += this->shape_value_component
+ (dof, quadrature_point, 1);
+ }
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ for (unsigned int k = 2; k < 4; ++k)
+ tmp (2 * i)
+ -= this->restriction[index][i]
+ (j + k * this->degree, dof)
+ * this->shape_value_component
+ (j + k * this->degree,
+ quadrature_points[q_point],
+ 0);
+
+ tmp (2 * i + 1)
+ -= this->restriction[index][i]
+ (i * this->degree + j, dof)
+ * this->shape_value_component
+ (i * this->degree + j,
+ quadrature_points[q_point], 1);
+ }
+
+ tmp *= quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i_0
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+ const double L_i_1
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j_0
+ = L_i_0 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ const double l_j_1
+ = L_i_1 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0; k < 2;
+ ++k)
+ {
+ system_rhs (i * deg + j, 2 * k)
+ += tmp (2 * k) * l_j_0;
+ system_rhs (i * deg + j,
+ 2 * k + 1)
+ += tmp (2 * k + 1) * l_j_1;
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ for (unsigned int j = 0; j < deg; ++j)
+ for (unsigned int k = 0; k < 2; ++k)
+ {
+ if (std::abs (solution (i * deg + j,
+ 2 * k))
+ > 1e-14)
+ this->restriction[index][k]
+ (i * deg + j + n_boundary_dofs, dof)
+ = solution (i * deg + j, 2 * k);
+
+ if (std::abs (solution (i * deg + j,
+ 2 * k + 1))
+ > 1e-14)
+ this->restriction[index][k]
+ (i + (deg + j) * this->degree
+ + n_boundary_dofs, dof)
+ = solution (i * deg + j,
+ 2 * k + 1);
+ }
}
-
- for (unsigned int j = 0; j < 4; ++j)
- this->restriction[index][j]
- (i + (j + 8) * this->degree,
- i + (j + 8) * this->degree) = 2.0;
}
-
- for (unsigned int i = 0; i < 2 * this->degree * deg; ++i)
- for (unsigned int j = 0; j < 2; ++j)
- {
- this->restriction[index][2 * j] (i + n_edge_dofs,
- i + n_edge_dofs)
- = 1.0;
- this->restriction[index][2 * j + 1]
- (i + 2 * this->degree * deg + n_edge_dofs,
- i + 2 * this->degree * deg + n_edge_dofs) = 1.0;
- this->restriction[index][j]
- (i + 4 * this->degree * deg + n_edge_dofs,
- i + 4 * this->degree * deg + n_edge_dofs) = 1.0;
- this->restriction[index][j + 2]
- (i + 6 * this->degree * deg + n_edge_dofs,
- i + 6 * this->degree * deg + n_edge_dofs) = 1.0;
-
- for (unsigned int k = 0; k < 4; ++k)
- this->restriction[index][k]
- (i + 2 * (j + 4) * this->degree * deg
- + n_edge_dofs,
- i + 2 * (j + 4) * this->degree * deg
- + n_edge_dofs) = 0.5;
- }
-
- break;
- }
-
- case RefinementCase<3>::cut_z:
- {
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < 4; ++j)
- for (unsigned int k = 0; k < 2; ++k)
- {
- this->restriction[index][k]
- (i + (j + 4 * k) * this->degree,
- i + (j + 4 * k) * this->degree) = 2.0;
- this->restriction[index][k]
- (i + (j + 8) * this->degree,
- i + (j + 8) * this->degree) = 1.0;
- }
-
- for (unsigned int i = 0; i < 2 * this->degree * deg; ++i)
- for (unsigned int j = 0; j < 2; ++j)
- {
- for (unsigned int k = 0; k < 3; ++k)
- this->restriction[index][j]
- (i + 2 * k * this->degree * deg + n_edge_dofs,
- i + 2 * k * this->degree * deg + n_edge_dofs)
- = 1.0;
-
- this->restriction[index][j]
- (i + 2 * (j + 4) * this->degree * deg
- + n_edge_dofs,
- i + 2 * (j + 4) * this->degree * deg
- + n_edge_dofs) = 2.0;
- }
-
+
break;
}
- case RefinementCase<3>::cut_xz:
+ case RefinementCase<2>::cut_y:
{
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < 2; ++j)
+ // First interpolate the shape
+ // functions of the child cells
+ // to the lowest order shape
+ // functions of the parent cell.
+ for (unsigned int dof = 0; dof < this->dofs_per_cell;
+ ++dof)
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
{
- this->restriction[index][j] (i + j * this->degree,
- i + j * this->degree)
- = 2.0;
- this->restriction[index][j + 2]
- (i + (j + 4) * this->degree,
- i + (j + 4) * this->degree) = 2.0;
-
- for (unsigned int k = 0; k < 2; ++k)
+ {
+ const double weight
+ = 2.0 * edge_quadrature.weight (q_point);
+
+ if (edge_quadrature_points[q_point] (0) < 0.5)
+ for (unsigned int i = 0; i < 2; ++i)
+ {
+ const Point<dim> quadrature_point (i,
+ 2.0 * edge_quadrature_points[q_point] (0));
+
+ this->restriction[index][0]
+ (i * this->degree, dof) += weight
+ * this->shape_value_component
+ (dof,
+ quadrature_point,
+ 1);
+ }
+
+ else
+ for (unsigned int i = 0; i < 2; ++i)
+ {
+ const Point<dim> quadrature_point (i,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0);
+
+ this->restriction[index][1]
+ (i * this->degree, dof) += weight
+ * this->shape_value_component
+ (dof,
+ quadrature_point,
+ 1);
+ }
+ }
+
+ const double weight
+ = edge_quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i < 2; ++i)
{
- this->restriction[index][j]
- (i + (k + 2) * this->degree,
- i + (k + 2) * this->degree) = 1.0;
- this->restriction[index][j + 2]
- (i + (k + 6) * this->degree,
- i + (k + 6) * this->degree) = 1.0;
- this->restriction[index][2 * j]
- (i + 2 * (k + 4) * this->degree,
- i + 2 * (k + 4) * this->degree) = 1.0;
- this->restriction[index][2 * j + 1]
- (i + (2 * k + 9) * this->degree,
- i + (2 * k + 9) * this->degree) = 1.0;
+ const Point<dim>
+ quadrature_point (edge_quadrature_points[q_point] (0),
+ i);
+
+ this->restriction[index][i]
+ ((i + 2) * this->degree, dof) += weight
+ * this->shape_value_component
+ (dof,
+ quadrature_point,
+ 0);
}
}
-
- for (unsigned int i = 0; i < 2 * this->degree * deg; ++i)
- for (unsigned int j = 0; j < 2; ++j)
+
+ // Then project the shape functions
+ // of the child cells to the higher
+ // order shape functions of the
+ // parent cell.
+ if (deg > 0)
+ {
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials = Polynomials::Legendre::generate_complete_basis
+ (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
{
- this->restriction[index][2 * j] (i + n_edge_dofs,
- i + n_edge_dofs)
- = 1.0;
- this->restriction[index][2 * j + 1]
- (i + 2 * this->degree * deg + n_edge_dofs,
- i + 2 * this->degree * deg + n_edge_dofs) = 1.0;
-
- for (unsigned int k = 0; k < 2; ++k)
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
{
- this->restriction[index][j + 2 * k]
- (i + 4 * this->degree * deg + n_edge_dofs,
- i + 4 * this->degree * deg + n_edge_dofs)
- = 0.5;
- this->restriction[index][j + 2 * k]
- (i + 6 * this->degree * deg + n_edge_dofs,
- i + 6 * this->degree * deg + n_edge_dofs)
- = 0.5;
- this->restriction[index][j + 2 * k]
- (i + 2 * (k + 4) * this->degree * deg
- + n_edge_dofs,
- i + 2 * (k + 4) * this->degree * deg
- + n_edge_dofs) = 1.0;
+ const double weight
+ = std::sqrt (edge_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point)
+ = weight * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
}
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
}
-
- break;
- }
-
- case RefinementCase<3>::cut_yz:
- {
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < 2; ++j)
- for (unsigned int k = 0; k < 2; ++k)
- {
- for (unsigned int l = 0; l < 2; ++l)
- {
- this->restriction[index][j + 2 * l]
- (i + (k + 4 * l) * this->degree,
- i + (k + 4 * l) * this->degree) = 1.0;
- this->restriction[index][2 * j + l]
- (i + (k + 2 * (l + 4)) * this->degree,
- i + (k + 2 * (l + 4)) * this->degree) = 1.0;
- }
-
- this->restriction[index][j + 2 * k]
- (i + (j + 4 * k + 2) * this->degree,
- i + (j + 4 * k + 2) * this->degree) = 2.0;
- }
-
- for (unsigned int i = 0; i < 2 * this->degree * deg; ++i)
- for (unsigned int j = 0; j < 2; ++j)
- {
- for (unsigned int child = 0;
- child < GeometryInfo<dim>::n_children
- (RefinementCase<dim> (ref)); ++child)
- this->restriction[index][child]
- (i + 2 * j * this->degree * deg + n_edge_dofs,
- i + 2 * j * this->degree * deg + n_edge_dofs)
- = 0.5;
-
- for (unsigned int k = 0; k < 2; ++k)
+
+ FullMatrix<double> solution (deg, 3);
+ FullMatrix<double> system_rhs (deg, 3);
+ Vector<double> tmp (3);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ for (unsigned int i = 0; i < 2; ++i)
{
- this->restriction[index][j + 2 * k]
- (i + 2 * (j + 2) * this->degree * deg
- + n_edge_dofs,
- i + 2 * (j + 2) * this->degree * deg
- + n_edge_dofs) = 1.0;
- this->restriction[index][2 * j + k]
- (i + 2 * (j + 4) * this->degree * deg
- + n_edge_dofs,
- i + 2 * (j + 4) * this->degree * deg
- + n_edge_dofs) = 1.0;
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = edge_quadrature.weight (q_point);
+ Point<dim> quadrature_point_0 (i,
+ edge_quadrature_points[q_point] (0));
+
+ if (edge_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point_1 (i,
+ 2.0 * edge_quadrature_points[q_point] (0));
+
+ tmp (0) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_1,
+ 1)
+ - this->restriction[index][0]
+ (i * this->degree,
+ dof)
+ * this->shape_value_component
+ (i * this->degree,
+ quadrature_point_0,
+ 1));
+ tmp (1) = -1.0 * weight
+ * this->restriction[index][1]
+ (i * this->degree,
+ dof)
+ * this->shape_value_component
+ (i * this->degree,
+ quadrature_point_0,
+ 1);
+ }
+
+ else
+ {
+ tmp (0) = -1.0 * weight
+ * this->restriction[index][0]
+ (i * this->degree,
+ dof)
+ * this->shape_value_component
+ (i * this->degree,
+ quadrature_point_0,
+ 1);
+
+ const Point<dim>
+ quadrature_point_1 (i,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0);
+
+ tmp (1) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_1,
+ 1)
+ - this->restriction[index][1]
+ (i * this->degree,
+ dof)
+ * this->shape_value_component
+ (i * this->degree,
+ quadrature_point_0,
+ 1));
+ }
+
+ quadrature_point_0
+ = Point<dim> (edge_quadrature_points[q_point] (0),
+ i);
+ tmp (2) = weight
+ * (this->shape_value_component
+ (dof, quadrature_point_0, 0)
+ - this->restriction[index][i]
+ ((i + 2) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2) * this->degree,
+ quadrature_point_0, 0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double L_j
+ = legendre_polynomials[j + 1].value
+ (edge_quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0;
+ k < tmp.size (); ++k)
+ system_rhs (j, k) += tmp (k) * L_j;
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ for (unsigned int k = 0; k < 2; ++k)
+ if (std::abs (solution (j, k)) > 1e-14)
+ this->restriction[index][k]
+ (i * this->degree + j + 1, dof)
+ = solution (j, k);
+
+ if (std::abs (solution (j, 2)) > 1e-14)
+ this->restriction[index][i]
+ ((i + 2) * this->degree + j + 1, dof)
+ = solution (j, 2);
+ }
}
- }
-
- break;
- }
-
- case RefinementCase<3>::isotropic_refinement:
- {
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < 2; ++j)
+
+ const QGauss<dim> quadrature (2 * this->degree);
+ const std::vector<Point<dim> >&
+ quadrature_points = quadrature.get_points ();
+ const std::vector<Polynomials::Polynomial<double> >&
+ lobatto_polynomials = Polynomials::Lobatto::generate_complete_basis
+ (this->degree);
+ const unsigned int n_boundary_dofs
+ = GeometryInfo<dim>::faces_per_cell * this->degree;
+ const unsigned int& n_quadrature_points
+ = quadrature.size ();
+
{
- for (unsigned int k = 0; k < 2; ++k)
+ FullMatrix<double>
+ assembling_matrix (deg * this->degree,
+ n_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
{
- this->restriction[index][2 * j + k]
- (i + k * this->degree, i + k * this->degree)
- = 1.0;
- this->restriction[index][j + 2 * k]
- (i + (k + 2) * this->degree,
- i + (k + 2) * this->degree) = 1.0;
- this->restriction[index][2 * (j + 2) + k]
- (i + (k + 4) * this->degree,
- i + (k + 4) * this->degree) = 1.0;
- this->restriction[index][j + 2 * (k + 2)]
- (i + (k + 6) * this->degree,
- i + (k + 6) * this->degree) = 1.0;
- this->restriction[index][4 * j + k]
- (i + (k + 8) * this->degree,
- i + (k + 8) * this->degree) = 1.0;
- }
-
- this->restriction[index][2 * (2 * j + 1)]
- (i + 10 * this->degree, i + 10 * this->degree)
- = 1.0;
- this->restriction[index][4 * j + 3]
- (i + 11 * this->degree, i + 11 * this->degree)
- = 1.0;
+ const double weight
+ = std::sqrt (quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i
+ = weight * legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ assembling_matrix (i * deg + j, q_point)
+ = L_i * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
}
+
+ solution.reinit (system_matrix_inv.m (), 4);
+ system_rhs.reinit (system_matrix_inv.m (), 4);
+ tmp.reinit (4);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ tmp = 0.0;
+
+ if (quadrature_points[q_point] (1) < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1));
+
+ tmp (0) += this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (1) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 1);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1)
+ - 1.0);
+
+ tmp (2) += this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (3) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 1);
+ }
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ tmp (2 * i)
+ -= this->restriction[index][i]
+ ((i + 2) * this->degree + j,
+ dof)
+ * this->shape_value_component
+ ((i + 2) * this->degree + j,
+ quadrature_points[q_point], 0);
+
+ for (unsigned int k = 0; k < 2; ++k)
+ tmp (2 * i + 1)
+ -= this->restriction[index][i]
+ (j + k * this->degree, dof)
+ * this->shape_value_component
+ (j + k * this->degree,
+ quadrature_points[q_point],
+ 1);
+ }
+
+ tmp *= quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i_0
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+ const double L_i_1
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j_0
+ = L_i_0 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ const double l_j_1
+ = L_i_1 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0; k < 2;
+ ++k)
+ {
+ system_rhs (i * deg + j, 2 * k)
+ += tmp (2 * k) * l_j_0;
+ system_rhs (i * deg + j,
+ 2 * k + 1)
+ += tmp (2 * k + 1) * l_j_1;
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ for (unsigned int j = 0; j < deg; ++j)
+ for (unsigned int k = 0; k < 2; ++k)
+ {
+ if (std::abs (solution (i * deg + j,
+ 2 * k))
+ > 1e-14)
+ this->restriction[index][k]
+ (i * deg + j + n_boundary_dofs, dof)
+ = solution (i * deg + j, 2 * k);
+
+ if (std::abs (solution (i * deg + j,
+ 2 * k + 1))
+ > 1e-14)
+ this->restriction[index][k]
+ (i + (deg + j) * this->degree
+ + n_boundary_dofs, dof)
+ = solution (i * deg + j,
+ 2 * k + 1);
+ }
+ }
+ }
+
+ break;
+ }
- for (unsigned int i = 0; i < 2 * this->degree * deg; ++i)
+ case RefinementCase<2>::isotropic_refinement:
+ {
+ // First interpolate the shape
+ // functions of the child cells
+ // to the lowest order shape
+ // functions of the parent cell.
+ for (unsigned int dof = 0; dof < this->dofs_per_cell;
+ ++dof)
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
+ {
+ const double weight
+ = 2.0 * edge_quadrature.weight (q_point);
+
+ if (edge_quadrature_points[q_point] (0) < 0.5)
+ {
+ Point<dim> quadrature_point (0.0,
+ 2.0 * edge_quadrature_points[q_point] (0));
+
+ this->restriction[index][0] (0, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 1);
+ quadrature_point (0) = 1.0;
+ this->restriction[index][1] (this->degree,
+ dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 1);
+ quadrature_point (0) = quadrature_point (1);
+ quadrature_point (1) = 0.0;
+ this->restriction[index][0] (2 * this->degree,
+ dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ quadrature_point (1) = 1.0;
+ this->restriction[index][2] (3 * this->degree,
+ dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ }
+
+ else
+ {
+ Point<dim> quadrature_point (0.0,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0);
+
+ this->restriction[index][2] (0, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 1);
+ quadrature_point (0) = 1.0;
+ this->restriction[index][3] (this->degree,
+ dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 1);
+ quadrature_point (0) = quadrature_point (1);
+ quadrature_point (1) = 0.0;
+ this->restriction[index][1] (2 * this->degree,
+ dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ quadrature_point (1) = 1.0;
+ this->restriction[index][3] (3 * this->degree,
+ dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ }
+ }
+
+ // Then project the shape functions
+ // of the child cells to the higher
+ // order shape functions of the
+ // parent cell.
+ if (deg > 0)
{
- for (unsigned int j = 0; j < 4; ++j)
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials
+ = Polynomials::Legendre::generate_complete_basis
+ (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
+ {
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (edge_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point)
+ = weight * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+ }
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ FullMatrix<double> solution (deg, 4);
+ FullMatrix<double> system_rhs (deg, 4);
+ Vector<double> tmp (4);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ for (unsigned int i = 0; i < 2; ++i)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = edge_quadrature.weight (q_point);
+ const Point<dim> quadrature_point_0 (i,
+ edge_quadrature_points[q_point] (0));
+ const Point<dim>
+ quadrature_point_1
+ (edge_quadrature_points[q_point] (0),
+ i);
+
+ if (edge_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ Point<dim> quadrature_point_2 (i,
+ 2.0 * edge_quadrature_points[q_point] (0));
+
+ tmp (0) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 1)
+ - this->restriction[index][i]
+ (i * this->degree,
+ dof)
+ * this->shape_value_component
+ (i * this->degree,
+ quadrature_point_0,
+ 1));
+ tmp (1) = -1.0 * weight
+ * this->restriction[index][i + 2]
+ (i * this->degree,
+ dof)
+ * this->shape_value_component
+ (i * this->degree,
+ quadrature_point_0,
+ 1);
+ quadrature_point_2
+ = Point<dim> (2.0 * edge_quadrature_points[q_point] (0),
+ i);
+ tmp (2) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 0)
+ - this->restriction[index][2 * i]
+ ((i + 2) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2) * this->degree,
+ quadrature_point_1,
+ 0));
+ tmp (3) = -1.0 * weight
+ * this->restriction[index][2 * i + 1]
+ ((i + 2) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2) * this->degree,
+ quadrature_point_1,
+ 0);
+ }
+
+ else
+ {
+ tmp (0) = -1.0 * weight
+ * this->restriction[index][i]
+ (i * this->degree,
+ dof)
+ * this->shape_value_component
+ (i * this->degree,
+ quadrature_point_0,
+ 1);
+
+ Point<dim> quadrature_point_2 (i,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0);
+
+ tmp (1) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 1)
+ - this->restriction[index][i + 2]
+ (i * this->degree,
+ dof)
+ * this->shape_value_component
+ (i * this->degree,
+ quadrature_point_0,
+ 1));
+ tmp (2) = -1.0 * weight
+ * this->restriction[index][2 * i]
+ ((i + 2) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2) * this->degree,
+ quadrature_point_1,
+ 0);
+ quadrature_point_2
+ = Point<dim> (2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0, i);
+ tmp (3) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 0)
+ - this->restriction[index][2 * i + 1]
+ ((i + 2) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2) * this->degree,
+ quadrature_point_1,
+ 0));
+ }
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double L_j
+ = legendre_polynomials[j + 1].value
+ (edge_quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0;
+ k < tmp.size (); ++k)
+ system_rhs (j, k) += tmp (k) * L_j;
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int j = 0; j < deg; ++j)
+ for (unsigned int k = 0; k < 2; ++k)
+ {
+ if (std::abs (solution (j, k)) > 1e-14)
+ this->restriction[index][i + 2 * k]
+ (i * this->degree + j + 1, dof)
+ = solution (j, k);
+
+ if (std::abs (solution (j, k + 2))
+ > 1e-14)
+ this->restriction[index][2 * i + k]
+ ((i + 2) * this->degree + j + 1, dof)
+ = solution (j, k + 2);
+ }
+ }
+
+ const QGauss<dim> quadrature (2 * this->degree);
+ const std::vector<Point<dim> >&
+ quadrature_points = quadrature.get_points ();
+ const std::vector<Polynomials::Polynomial<double> >&
+ lobatto_polynomials
+ = Polynomials::Lobatto::generate_complete_basis
+ (this->degree);
+ const unsigned int n_boundary_dofs
+ = GeometryInfo<dim>::faces_per_cell * this->degree;
+ const unsigned int& n_quadrature_points
+ = quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * this->degree,
+ n_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ const double weight
+ = std::sqrt (quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i
+ = weight * legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ assembling_matrix (i * deg + j,
+ q_point)
+ = L_i * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 8);
+ system_rhs.reinit (system_matrix_inv.m (), 8);
+ tmp.reinit (8);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
{
- this->restriction[index][2 * j] (i + n_edge_dofs,
- i + n_edge_dofs)
- = 0.5;
- this->restriction[index][2 * j + 1]
- (i + 2 * this->degree * deg + n_edge_dofs,
- i + 2 * this->degree * deg + n_edge_dofs) = 0.5;
- this->restriction[index][j]
- (i + 8 * this->degree * deg + n_edge_dofs,
- i + 8 * this->degree * deg + n_edge_dofs) = 0.5;
- this->restriction[index][j + 4]
- (i + 10 * this->degree * deg + n_edge_dofs,
- i + 10 * this->degree * deg + n_edge_dofs)
- = 0.5;
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ tmp = 0.0;
+
+ if (quadrature_points[q_point] (0) < 0.5)
+ {
+ if (quadrature_points[q_point] (1)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1));
+
+ tmp (0) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (1) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 1);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1)
+ - 1.0);
+
+ tmp (4) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (5) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 1);
+ }
+ }
+
+ else
+ if (quadrature_points[q_point] (1) < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (1));
+
+ tmp (2) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (3) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 1);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (1)
+ - 1.0);
+
+ tmp (6) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (7) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 1);
+ }
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ tmp (2 * i)
+ -= this->restriction[index][i]
+ (j + 2 * this->degree, dof)
+ * this->shape_value_component
+ (j + 2 * this->degree,
+ quadrature_points[q_point], 0);
+ tmp (2 * i + 1)
+ -= this->restriction[index][i]
+ (i * this->degree + j, dof)
+ * this->shape_value_component
+ (i * this->degree + j,
+ quadrature_points[q_point], 1);
+ tmp (2 * (i + 2))
+ -= this->restriction[index][i + 2]
+ (j + 3 * this->degree, dof)
+ * this->shape_value_component
+ (j + 3 * this->degree,
+ quadrature_points[q_point], 0);
+ tmp (2 * i + 5)
+ -= this->restriction[index][i + 2]
+ (i * this->degree + j, dof)
+ * this->shape_value_component
+ (i * this->degree + j,
+ quadrature_points[q_point], 1);
+ }
+
+ tmp *= quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i_0
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+ const double L_i_1
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j_0
+ = L_i_0 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ const double l_j_1
+ = L_i_1 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0; k < 4;
+ ++k)
+ {
+ system_rhs (i * deg + j, 2 * k)
+ += tmp (2 * k) * l_j_0;
+ system_rhs (i * deg + j,
+ 2 * k + 1)
+ += tmp (2 * k + 1) * l_j_1;
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ for (unsigned int j = 0; j < deg; ++j)
+ for (unsigned int k = 0; k < 4; ++k)
+ {
+ if (std::abs (solution (i * deg + j,
+ 2 * k))
+ > 1e-14)
+ this->restriction[index][k]
+ (i * deg + j + n_boundary_dofs, dof)
+ = solution (i * deg + j, 2 * k);
+
+ if (std::abs (solution (i * deg + j,
+ 2 * k + 1))
+ > 1e-14)
+ this->restriction[index][k]
+ (i + (deg + j) * this->degree
+ + n_boundary_dofs, dof)
+ = solution (i * deg + j,
+ 2 * k + 1);
+ }
}
-
- for (unsigned int j = 0; j < 2; ++j)
- for (unsigned int k = 0; k < 2; ++k)
- for (unsigned int l = 0; l < 2; ++l)
- this->restriction[index][j + 2 * (2 * k + l)]
- (i + 2 * (l + 2) * this->degree * deg
- + n_edge_dofs,
- i + 2 * (l + 2) * this->degree * deg
- + n_edge_dofs) = 0.5;
}
-
+
break;
}
default:
Assert (false, ExcNotImplemented ());
}
-
- for (unsigned int i = 0; i < 3 * this->degree * deg * deg; ++i)
- for (unsigned int child = 0;
- child < GeometryInfo<dim>::n_children
- (RefinementCase<dim> (ref)); ++child)
- this->restriction[index][child] (i + n_boundary_dofs,
- i + n_boundary_dofs)
- = 2.0 / GeometryInfo<dim>::n_children
- (RefinementCase<dim> (ref));
}
break;
}
- default:
- Assert (false, ExcNotImplemented ());
- }
-}
-
-
-#if deal_II_dimension == 1
-
-template <>
-std::vector<unsigned int>
-FE_Nedelec<1>::get_dpo_vector (const unsigned int degree)
-{
- std::vector<unsigned int> dpo (2);
-
- dpo[0] = 1;
- dpo[1] = degree;
- return dpo;
-}
-
-#endif
-
-
-template <int dim>
-std::vector<unsigned int>
-FE_Nedelec<dim>::get_dpo_vector (const unsigned int degree)
-{
- std::vector<unsigned int> dpo (dim + 1);
-
- dpo[0] = 0;
- dpo[1] = degree + 1;
- dpo[2] = 2 * degree * (degree + 1);
-
- if (dim == 3)
- dpo[3] = 3 * degree * degree * (degree + 1);
-
- return dpo;
-}
-
-//---------------------------------------------------------------------------
-// Data field initialization
-//---------------------------------------------------------------------------
-
- // Chech wheter a given shape
- // function has support on a
- // given face.
-
- // We just switch through the
- // faces of the cell and return
- // true, if the shape function
- // has support on the face
- // and false otherwise.
-template <int dim>
-bool
-FE_Nedelec<dim>::has_support_on_face (const unsigned int shape_index,
- const unsigned int face_index) const
-{
- Assert (shape_index < this->dofs_per_cell,
- ExcIndexRange (shape_index, 0, this->dofs_per_cell));
- Assert (face_index < GeometryInfo<dim>::faces_per_cell,
- ExcIndexRange (face_index, 0, GeometryInfo<dim>::faces_per_cell));
-
- switch (dim)
- {
- case 2:
- switch (face_index)
- {
- case 0:
- if (!((shape_index > deg) && (shape_index < 2 * this->degree)))
- return true;
-
- else
- return false;
-
- case 1:
- if ((shape_index > deg) &&
- (shape_index
- < GeometryInfo<2>::lines_per_cell * this->degree))
- return true;
-
- else
- return false;
-
- case 2:
- if (shape_index < 3 * this->degree)
- return true;
-
- else
- return false;
-
- case 3:
- if (!((shape_index >= 2 * this->degree) &&
- (shape_index < 3 * this->degree)))
- return true;
-
- else
- return false;
-
- default:
- {
- Assert (false, ExcNotImplemented ());
- return false;
- }
- }
-
case 3:
- switch (face_index)
- {
- case 0:
- if (((shape_index > deg) && (shape_index < 2 * this->degree)) ||
- ((shape_index >= 5 * this->degree) &&
- (shape_index < 6 * this->degree)) ||
- ((shape_index >= 9 * this->degree) &&
- (shape_index < 10 * this->degree)) ||
- ((shape_index >= 11 * this->degree) &&
- (shape_index
- < GeometryInfo<3>::lines_per_cell * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 2 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 5 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 6 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 7 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 8 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 9 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 10 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 11 * deg)
- * this->degree)))
- return false;
-
- else
- return true;
+ {
+ for (unsigned int ref = RefinementCase<3>::cut_x;
+ ref <= RefinementCase<3>::isotropic_refinement; ++ref)
+ {
+ const unsigned int index = ref - 1;
- case 1:
- if (((shape_index > deg) && (shape_index < 4 * this->degree)) ||
- ((shape_index >= 5 * this->degree) &&
- (shape_index < 8 * this->degree)) ||
- ((shape_index >= 9 * this->degree) &&
- (shape_index < 10 * this->degree)) ||
- ((shape_index >= 11 * this->degree) &&
- (shape_index
- < GeometryInfo<3>::lines_per_cell * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 2 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 4 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 5 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 6 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 7 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 8 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 9 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 10 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 11 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 12 * deg)
- * this->degree)))
- return true;
-
- else
- return false;
-
- case 2:
- if ((shape_index < 3 * this->degree) ||
- ((shape_index >= 4 * this->degree) &&
- (shape_index < 7 * this->degree)) ||
- ((shape_index >= 8 * this->degree) &&
- (shape_index < 10 * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 2 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 3 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 6 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 8 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 9 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 10 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 11 * deg)
- * this->degree)))
- return true;
-
- else
- return false;
-
- case 3:
- if ((shape_index < 2 * this->degree) ||
- ((shape_index >= 3 * this->degree) &&
- (shape_index < 6 * this->degree)) ||
- ((shape_index >= 7 * this->degree) &&
- (shape_index < 8 * this->degree)) ||
- ((shape_index >= 10 * this->degree) &&
- (shape_index
- < GeometryInfo<3>::lines_per_cell * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 2 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 3 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 4 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 6 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 9 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 10 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 11 * deg)
- * this->degree)))
- return true;
-
- else
- return false;
-
- case 4:
- if ((shape_index < 4 * this->degree) ||
- ((shape_index >= 8 * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 2 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 3 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 4 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 5 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 6 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 7 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 8 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 10 * deg)
- * this->degree)))
- return true;
-
- else
- return false;
-
- case 5:
- if (((shape_index >= 4 * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 2 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 3 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 4 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 5 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 6 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 7 * deg)
- * this->degree)) ||
- ((shape_index
- >= (GeometryInfo<3>::lines_per_cell + 10 * deg)
- * this->degree) &&
- (shape_index
- < (GeometryInfo<3>::lines_per_cell + 12 * deg)
- * this->degree)))
- return true;
-
- else
- return false;
-
- default:
- {
- Assert (false, ExcNotImplemented ());
- return false;
- }
- }
-
- default:
- {
- Assert (false, ExcNotImplemented ());
- return false;
- }
- }
-}
-
-template <int dim>
-bool
-FE_Nedelec<dim>::hp_constraints_are_implemented () const
-{
- return false;//dim != 2;
-}
-
-template <int dim>
-std::vector<std::pair<unsigned int, unsigned int> >
-FE_Nedelec<dim>::hp_vertex_dof_identities (const FiniteElement<dim>&)
-const
-{
- // Nedelec elements do not have any dofs
- // on vertices, hence return an empty vector.
- return std::vector<std::pair<unsigned int, unsigned int> > ();
-}
-
-template <int dim>
-std::vector<std::pair<unsigned int, unsigned int> >
-FE_Nedelec<dim>::hp_line_dof_identities (const FiniteElement<dim>& fe_other)
-const
-{
- // we can presently only compute these
- // identities if both FEs are
- // FE_Nedelec or if the other one is an
- // FE_Nothing
- if (const FE_Nedelec<dim> *fe_nedelec_other
- = dynamic_cast<const FE_Nedelec<dim>*> (&fe_other))
- {
- // dofs are located on lines, so
- // two dofs are identical, if their
- // edge shape functions have the
- // same polynomial degree.
- std::vector<std::pair<unsigned int, unsigned int> > identities;
-
- for (unsigned int i = 0;
- i < std::min (fe_nedelec_other->degree, this->degree); ++i)
- identities.push_back (std::make_pair (i, i));
-
- return identities;
- }
-
- else
- if (dynamic_cast<const FE_Nothing<dim>*> (&fe_other) != 0)
- {
- // the FE_Nothing has no
- // degrees of freedom, so there
- // are no equivalencies to be
- // recorded
- return std::vector<std::pair<unsigned int, unsigned int> > ();
- }
-
- else
- {
- Assert (false, ExcNotImplemented ());
- return std::vector<std::pair<unsigned int, unsigned int> > ();
- }
-}
-
-template <int dim>
-std::vector<std::pair<unsigned int, unsigned int> >
-FE_Nedelec<dim>::hp_quad_dof_identities (const FiniteElement<dim>& fe_other)
-const
-{
- // we can presently only compute
- // these identities if both FEs are
- // FE_Nedelec or if the other one is an
- // FE_Nothing
- if (const FE_Nedelec<dim> *fe_nedelec_other
- = dynamic_cast<const FE_Nedelec<dim>*> (&fe_other))
- {
- // dofs are located on the interior
- // of faces, so two dofs are identical,
- // if their face shape functions have
- // the same polynomial degree.
- const unsigned int p = fe_nedelec_other->degree;
- const unsigned int q = this->degree;
- const unsigned int p_min = std::min (p, q);
- std::vector<std::pair<unsigned int, unsigned int> > identities;
-
- for (unsigned int i = 0; i < p_min; ++i)
- for (unsigned int j = 0; j < p_min - 1; ++j)
- {
- identities.push_back (std::make_pair ((i + 1) * (q + 1) + j,
- (i + 1) * (p + 1) + j));
- identities.push_back (std::make_pair (i + (j + q + 2) * q,
- i + (j + p + 2) * p));
- }
-
- return identities;
- }
-
- else
- if (dynamic_cast<const FE_Nothing<dim>*> (&fe_other) != 0)
- {
- // the FE_Nothing has no
- // degrees of freedom, so there
- // are no equivalencies to be
- // recorded
- return std::vector<std::pair<unsigned int, unsigned int> > ();
- }
-
- else
- {
- Assert (false, ExcNotImplemented ());
- return std::vector<std::pair<unsigned int, unsigned int> > ();
- }
-}
-
- // In this function we compute the face
- // interpolation matrix. This is usually
- // done by projection-based interpolation,
- // but, since one can compute the entries
- // easy per hand, we save some computation
- // time at this point and just fill in the
- // correct values.
-template <int dim>
-void
-FE_Nedelec<dim>::get_face_interpolation_matrix
- (const FiniteElement<dim>& source, FullMatrix<double>& interpolation_matrix)
-const
-{
- // this is only implemented, if the
- // source FE is also a
- // Nedelec element
- typedef FE_Nedelec<dim> FEN;
- typedef FiniteElement<dim> FEL;
-
- AssertThrow ((source.get_name ().find ("FE_Nedelec<") == 0) ||
- (dynamic_cast<const FEN*> (&source) != 0),
- typename FEL::ExcInterpolationNotImplemented());
- Assert (interpolation_matrix.m () == source.dofs_per_face,
- ExcDimensionMismatch (interpolation_matrix.m (),
- source.dofs_per_face));
- Assert (interpolation_matrix.n () == this->dofs_per_face,
- ExcDimensionMismatch (interpolation_matrix.n (),
- this->dofs_per_face));
-
- // ok, source is a Nedelec element, so
- // we will be able to do the work
- const FE_Nedelec<dim> &source_fe
- = dynamic_cast<const FE_Nedelec<dim>&> (source);
-
- // Make sure, that the element,
- // for which the DoFs should be
- // constrained is the one with
- // the higher polynomial degree.
- // Actually the procedure will work
- // also if this assertion is not
- // satisfied. But the matrices
- // produced in that case might
- // lead to problems in the
- // hp procedures, which use this
- // method.
- Assert (this->dofs_per_face <= source_fe.dofs_per_face,
- typename FEL::ExcInterpolationNotImplemented ());
- interpolation_matrix = 0;
-
- // On lines we can just identify
- // all degrees of freedom.
- for (unsigned int i = 0; i <= deg; ++i)
- interpolation_matrix (i, i) = 1.0;
-
- // In 3d we have some lines more
- // and a face. The procedure stays
- // the same as above, but we have
- // to take a bit more care of the
- // indices of the degrees of
- // freedom.
- if (dim == 3)
- for (unsigned int i = 0; i <= deg; ++i)
- {
- for (int j = 1; j < (int) GeometryInfo<dim>::lines_per_face; ++j)
- interpolation_matrix (j * source_fe.degree + i,
- j * this->degree + i) = 1.0;
-
- for (unsigned int j = 0; j < deg; ++j)
- {
- interpolation_matrix
- (i + (j + GeometryInfo<2>::lines_per_cell) * source_fe.degree,
- i + (j + GeometryInfo<2>::lines_per_cell) * this->degree)
- = 1.0;
- interpolation_matrix
- ((i * (source_fe.degree - 1)
- + GeometryInfo<2>::lines_per_cell) * source_fe.degree + j,
- (i * deg + GeometryInfo<2>::lines_per_cell) * this->degree)
- = 1.0;
- }
- }
-}
-
-#if deal_II_dimension == 1
-
-template <int dim>
-void
-FE_Nedelec<dim>::get_subface_interpolation_matrix(
- const FiniteElement<dim>&,
- const unsigned int,
- FullMatrix<double>&) const
-{
- Assert (false, ExcNotImplemented ());
-}
-
-#else
-
- // In this function we compute the
- // subface interpolation matrix.
- // This is done by a projection-
- // based interpolation. Therefore
- // we first interpolate the
- // shape functions of the higher
- // order element on the lowest
- // order edge shape functions.
- // Then the remaining part of
- // the interpolated shape
- // functions is projected on the
- // higher order edge shape
- // functions, the face shape
- // functions and the interior
- // shape functions (if they all
- // exist).
-template <int dim>
-void
-FE_Nedelec<dim>::get_subface_interpolation_matrix(
- const FiniteElement<dim>& source,
- const unsigned int subface,
- FullMatrix<double>& interpolation_matrix) const
-{
- // this is only implemented, if the
- // source FE is also a
- // Nedelec element
- typedef FE_Nedelec<dim> FEN;
- typedef FiniteElement<dim> FEL;
-
- AssertThrow ((source.get_name ().find ("FE_Nedelec<") == 0) ||
- (dynamic_cast<const FEN*> (&source) != 0),
- typename FEL::ExcInterpolationNotImplemented ());
- Assert (interpolation_matrix.m () == source.dofs_per_face,
- ExcDimensionMismatch (interpolation_matrix.m (),
- source.dofs_per_face));
- Assert (interpolation_matrix.n () == this->dofs_per_face,
- ExcDimensionMismatch (interpolation_matrix.n (),
- this->dofs_per_face));
-
- // ok, source is a Nedelec element, so
- // we will be able to do the work
- const FE_Nedelec<dim> &source_fe
- = dynamic_cast<const FE_Nedelec<dim>&> (source);
-
- // Make sure, that the element,
- // for which the DoFs should be
- // constrained is the one with
- // the higher polynomial degree.
- // Actually the procedure will work
- // also if this assertion is not
- // satisfied. But the matrices
- // produced in that case might
- // lead to problems in the
- // hp procedures, which use this
- // method.
- Assert (this->dofs_per_face <= source_fe.dofs_per_face,
- typename FEL::ExcInterpolationNotImplemented ());
- interpolation_matrix = 0;
- // Perform projection-based interpolation
- // as usual.
- switch (dim)
- {
- case 2:
- {
- const QGauss<dim - 1> reference_edge_quadrature (this->degree);
- const Quadrature<dim - 1>& edge_quadrature
- = QProjector<dim - 1>::project_to_child
- (reference_edge_quadrature, subface);
- const unsigned int& n_edge_points = edge_quadrature.size ();
- const std::vector<Point<dim - 1> >&
- quadrature_points = edge_quadrature.get_points ();
-
- // Let us begin with the
- // interpolation part.
- for (unsigned int q_point = 0; q_point < n_edge_points; ++q_point)
- {
- const double weight = edge_quadrature.weight (q_point);
-
- for (unsigned int dof = 0; dof < this->dofs_per_face; ++dof)
- interpolation_matrix (0, dof)
- += weight
- * this->shape_value_component
- (dof, Point<dim> (0.0, quadrature_points[q_point] (0)),
- 1);
- }
-
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int dof = 0; dof < this->dofs_per_face; ++dof)
- if (std::abs (interpolation_matrix (0, dof)) < 1e-14)
- interpolation_matrix (0, dof) = 0.0;
-
- // If the degree is greater
- // than 0, then we have still
- // some higher order edge
- // shape functions to
- // consider.
- // Here the projection part
- // starts. The dof values
- // are obtained by solving
- // a linear system of
- // equations.
- if (deg > 0)
- {
- // Shift value for scaling
- // of quadrature points.
- const double shift[2] = {0.0, -1.0};
- const std::vector<Polynomials::Polynomial<double> >&
- lobatto_polynomials
- = Polynomials::Lobatto::generate_complete_basis
- (this->degree);
- FullMatrix<double> assembling_matrix (deg, n_edge_points);
- std::vector<Polynomials::Polynomial<double> >
- lobatto_polynomials_grad (this->degree);
-
- for (unsigned int i = 0; i < lobatto_polynomials_grad.size ();
- ++i)
- lobatto_polynomials_grad[i]
- = lobatto_polynomials[i + 1].derivative ();
-
- // Set up the system matrix
- // and right hand side
- // vector.
- for (unsigned int q_point = 0; q_point < n_edge_points;
- ++q_point)
- {
- const double tmp = 2.0 * quadrature_points[q_point] (0)
- + shift[subface];
- const double weight
- = std::sqrt (edge_quadrature.weight (q_point));
-
- for (unsigned int i = 0; i < deg; ++i)
- assembling_matrix (i, q_point)
- = weight * lobatto_polynomials_grad[i + 1].value (tmp);
- }
-
- FullMatrix<double> system_matrix (deg, deg);
-
- assembling_matrix.mTmult (system_matrix, assembling_matrix);
-
- FullMatrix<double> system_matrix_inv (deg, deg);
-
- system_matrix_inv.invert (system_matrix);
-
- Vector<double> solution (deg);
- Vector<double> system_rhs (deg);
-
- for (unsigned int dof = 0; dof < this->dofs_per_face; ++dof)
+ switch (ref)
{
- system_rhs = 0;
+ case RefinementCase<3>::cut_x:
+ {
+ // First interpolate the shape
+ // functions of the child cells
+ // to the lowest order shape
+ // functions of the parent cell.
+ for (unsigned int dof = 0; dof < this->dofs_per_cell;
+ ++dof)
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
+ {
+ {
+ const double
+ weight = edge_quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ Point<dim> quadrature_point (i,
+ edge_quadrature_points[q_point] (0),
+ j);
+
+ this->restriction[index][i]
+ ((i + 4 * j) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 1);
+ quadrature_point = Point<dim> (i, j,
+ edge_quadrature_points[q_point] (0));
+ this->restriction[index][i]
+ ((i + 2 * (j + 4)) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+ }
+
+ const double weight
+ = 2.0 * edge_quadrature.weight (q_point);
+
+ if (edge_quadrature_points[q_point] (0) < 0.5)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * edge_quadrature_points[q_point] (0),
+ i, j);
+
+ this->restriction[index][0]
+ ((i + 4 * j + 2) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ }
+
+ else
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0, i, j);
+
+ this->restriction[index][1]
+ ((i + 4 * j + 2) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ }
+ }
+
+ // Then project the shape functions
+ // of the child cells to the higher
+ // order shape functions of the
+ // parent cell.
+ if (deg > 0)
+ {
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials
+ = Polynomials::Legendre::generate_complete_basis
+ (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
+ {
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (edge_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point)
+ = weight * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+ }
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ FullMatrix<double> solution (deg, 4);
+ FullMatrix<double> system_rhs (deg, 4);
+ Vector<double> tmp (4);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = edge_quadrature.weight (q_point);
+ Point<dim> quadrature_point_0 (i,
+ edge_quadrature_points[q_point] (0), j);
+
+ tmp (0)
+ = weight * (this->shape_value_component
+ (dof, quadrature_point_0,
+ 1)
+ - this->restriction[index][i]
+ ((i + 4 * j) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j) * this->degree,
+ quadrature_point_0,
+ 1));
+
+ quadrature_point_0
+ = Point<dim> (edge_quadrature_points[q_point] (0),
+ i, j);
+
+ if (edge_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point_1
+ (2.0 * edge_quadrature_points[q_point] (0),
+ i, j);
+
+ tmp (1)
+ = weight * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_1,
+ 0)
+ - this->restriction[index][0]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_0,
+ 0));
+ tmp (2) = -1.0 * weight
+ * this->restriction[index][1]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_0,
+ 0);
+ }
+
+ else
+ {
+ tmp (1) = -1.0 * weight
+ * this->restriction[index][0]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_0,
+ 0);
+
+ const Point<dim>
+ quadrature_point_1
+ (2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0, i, j);
+
+ tmp (2)
+ = weight * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_1,
+ 0)
+ - this->restriction[index][1]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_0,
+ 0));
+ }
+
+ quadrature_point_0 = Point<dim> (i, j,
+ edge_quadrature_points[q_point] (0));
+ tmp (3)
+ = weight * (this->shape_value_component
+ (dof, quadrature_point_0,
+ 2)
+ - this->restriction[index][i]
+ ((i + 2 * (j + 4))
+ * this->degree, dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_0,
+ 2));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double L_k
+ = legendre_polynomials[k + 1].value
+ (edge_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0;
+ l < tmp.size (); ++l)
+ system_rhs (k, l) += tmp (l)
+ * L_k;
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ if (std::abs (solution (k, 0)) > 1e-14)
+ this->restriction[index][i]
+ ((i + 4 * j) * this->degree + k + 1,
+ dof) = solution (k, 0);
+
+ for (unsigned int l = 0; l < 2; ++l)
+ if (std::abs (solution (k, 1))
+ > 1e-14)
+ this->restriction[index][l]
+ ((i + 4 * j + 2) * this->degree + k
+ + 1, dof)
+ = solution (k, l + 1);
+
+ if (std::abs (solution (k, 3)) > 1e-14)
+ this->restriction[index][i]
+ ((i + 2 * (j + 4)) * this->degree + k
+ + 1, dof)
+ = solution (k, 3);
+ }
+ }
+
+ const QGauss<2> face_quadrature (2 * this->degree);
+ const std::vector<Point<2> >&
+ face_quadrature_points
+ = face_quadrature.get_points ();
+ const std::vector<Polynomials::Polynomial<double> >&
+ lobatto_polynomials
+ = Polynomials::Lobatto::generate_complete_basis
+ (this->degree);
+ const unsigned int n_edge_dofs
+ = GeometryInfo<dim>::lines_per_cell * this->degree;
+ const unsigned int& n_face_quadrature_points
+ = face_quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * this->degree,
+ n_face_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (face_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i
+ = weight * legendre_polynomials[i].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ assembling_matrix (i * deg + j, q_point)
+ = L_i * lobatto_polynomials[j + 2].value
+ (face_quadrature_points[q_point] (1));
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 10);
+ system_rhs.reinit (system_matrix_inv.m (), 10);
+ tmp.reinit (10);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ tmp = 0.0;
+
+ const Point<dim> quadrature_point_0 (i,
+ face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1));
+
+ tmp (0) += this->shape_value_component
+ (dof, quadrature_point_0, 1);
+ tmp (1) += this->shape_value_component
+ (dof, quadrature_point_0, 2);
+
+ if (face_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ Point<dim>
+ quadrature_point_1
+ (2.0 * face_quadrature_points[q_point] (0),
+ i,
+ face_quadrature_points[q_point] (1));
+
+ tmp (2) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_1,
+ 0);
+ tmp (3) += this->shape_value_component
+ (dof, quadrature_point_1,
+ 2);
+ quadrature_point_1
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1),
+ i);
+ tmp (6) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_1,
+ 0);
+ tmp (7) += this->shape_value_component
+ (dof, quadrature_point_1,
+ 1);
+ }
+
+ else
+ {
+ Point<dim>
+ quadrature_point_1
+ (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0, i,
+ face_quadrature_points[q_point] (1));
+
+ tmp (4) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_1,
+ 0);
+ tmp (5) += this->shape_value_component
+ (dof, quadrature_point_1,
+ 2);
+ quadrature_point_1
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ face_quadrature_points[q_point] (1),
+ i);
+ tmp (8) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_1,
+ 0);
+ tmp (9) += this->shape_value_component
+ (dof, quadrature_point_1,
+ 1);
+ }
+
+ const Point<dim>
+ quadrature_point_2
+ (face_quadrature_points[q_point] (0), i,
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_3
+ (face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1),
+ i);
+
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ {
+ tmp (0) -= this->restriction[index][i]
+ ((i + 4 * j)
+ * this->degree + k,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0, 1);
+ tmp (1) -= this->restriction[index][i]
+ ((i + 2 * (j + 4))
+ * this->degree + k,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_0, 2);
+ tmp (2 * j + 3) -= this->restriction[index][j]
+ ((2 * (i + 4)
+ + j)
+ * this->degree
+ + k, dof)
+ * this->shape_value_component
+ ((2 * (i + 4)
+ + j)
+ * this->degree
+ + k,
+ quadrature_point_2,
+ 2);
+ tmp (2 * j + 7)
+ -= this->restriction[index][j]
+ ((4 * i + j) * this->degree
+ + k, dof)
+ * this->shape_value_component
+ ((4 * i + j) * this->degree + k,
+ quadrature_point_3, 1);
+
+ for (unsigned int l = 0; l < 2; ++l)
+ {
+ tmp (2 * (l + 1))
+ -= this->restriction[index][l]
+ ((i + 4 * j + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_2, 0);
+ tmp (2 * (l + 3))
+ -= this->restriction[index][l]
+ ((4 * i + j + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((4 * i + j + 2)
+ * this->degree + k,
+ quadrature_point_3, 0);
+ }
+ }
+
+ tmp *= face_quadrature.weight (q_point);
+
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ const double L_j_0
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (0));
+ const double L_j_1
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double l_k_0
+ = L_j_0 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (1));
+ const double l_k_1
+ = L_j_1 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0; l < 5;
+ ++l)
+ {
+ system_rhs (j * deg + k,
+ 2 * l)
+ += tmp (2 * l) * l_k_0;
+ system_rhs (j * deg + k,
+ 2 * l + 1)
+ += tmp (2 * l + 1) * l_k_1;
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int j = 0; j <= deg; ++j)
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ if (std::abs (solution (j * deg + k, 0))
+ > 1e-14)
+ this->restriction[index][i]
+ ((2 * i * this->degree + j) * deg + k
+ + n_edge_dofs,
+ dof) = solution (j * deg + k, 0);
+
+ if (std::abs (solution (j * deg + k, 1))
+ > 1e-14)
+ this->restriction[index][i]
+ (((2 * i + 1) * deg + k) * this->degree
+ + j
+ + n_edge_dofs,
+ dof) = solution (j * deg + k, 1);
+
+ for (unsigned int l = 0; l < 2; ++l)
+ for (unsigned int m = 0; m < 2; ++m)
+ {
+ if (std::abs (solution (j * deg + k,
+ 2 * (l + 2 * m + 1)))
+ > 1e-14)
+ this->restriction[index][l]
+ ((2 * (i + 2 * (m + 1))
+ * this->degree + j) * deg + k
+ + n_edge_dofs, dof)
+ = solution (j * deg + k,
+ 2 * (l + 2 * m
+ + 1));
+
+ if (std::abs (solution (j * deg + k,
+ 2 * (l + 2 * m)
+ + 3))
+ > 1e-14)
+ this->restriction[index][l]
+ (((2 * (i + 2 * m) + 5) * deg + k)
+ * this->degree + j + n_edge_dofs,
+ dof) = solution (j * deg + k,
+ 2 * (l + 2 * m)
+ + 3);
+ }
+ }
+ }
+
+ const QGauss<dim> quadrature (2 * this->degree);
+ const std::vector<Point<dim> >&
+ quadrature_points = quadrature.get_points ();
+ const unsigned int n_boundary_dofs
+ = 2 * GeometryInfo<dim>::faces_per_cell * deg
+ * this->degree + n_edge_dofs;
+ const unsigned int&
+ n_quadrature_points = quadrature.size ();
+
+ {
+ FullMatrix<double> assembling_matrix (deg * deg
+ * this->degree,
+ n_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ const double weight
+ = std::sqrt (quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i
+ = weight * legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j
+ = L_i * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ assembling_matrix ((i * deg + j)
+ * deg + k,
+ q_point)
+ = l_j * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ }
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 6);
+ system_rhs.reinit (system_matrix_inv.m (), 6);
+ tmp.reinit (6);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ tmp = 0.0;
+
+ if (quadrature_points[q_point] (0) < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0),
+ quadrature_points[q_point] (1),
+ quadrature_points[q_point] (2));
+
+ tmp (0) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (1) += this->shape_value_component
+ (dof, quadrature_point, 1);
+ tmp (2) += this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ quadrature_points[q_point] (1),
+ quadrature_points[q_point] (2));
+
+ tmp (3) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (4) += this->shape_value_component
+ (dof, quadrature_point, 1);
+ tmp (5) += this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ for (unsigned int k = 0; k < 2; ++k)
+ {
+ for (unsigned int l = 0; l < 2;
+ ++l)
+ {
+ tmp (3 * i)
+ -= this->restriction[index][i]
+ (j + (k + 4 * l + 2)
+ * this->degree, dof)
+ * this->shape_value_component
+ (j + (k + 4 * l + 2)
+ * this->degree,
+ quadrature_points[q_point],
+ 0);
+
+ for (unsigned int m = 0;
+ m < deg; ++m)
+ {
+ tmp (3 * i)
+ -= this->restriction[index][i]
+ ((j + 2 * (k + 2 * (l + 1))
+ * this->degree)
+ * deg + m
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ ((j + 2 * (k + 2 * (l + 1))
+ * this->degree)
+ * deg + m
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ }
+ }
+
+ for (unsigned int l = 0; l < deg;
+ ++l)
+ {
+ tmp (3 * i + 1)
+ -= this->restriction[index][i]
+ (j + ((2 * k + 9) * deg
+ + l)
+ * this->degree
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (j + ((2 * k + 9) * deg
+ + l)
+ * this->degree
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * i + 2)
+ -= this->restriction[index][i]
+ (j + ((2 * k + 5) * deg
+ + l)
+ * this->degree
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (j * ((2 * k + 5) * deg
+ + l)
+ * this->degree
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ }
+
+ tmp (3 * i + 1)
+ -= this->restriction[index][i]
+ ((i + 4 * k) * this->degree
+ + j, dof)
+ * this->shape_value_component
+ ((i + 4 * k) * this->degree
+ + j,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * i + 2)
+ -= this->restriction[index][i]
+ ((i + 2 * (k + 4))
+ * this->degree + j, dof)
+ * this->shape_value_component
+ ((i + 2 * (k + 4))
+ * this->degree + j,
+ quadrature_points[q_point],
+ 2);
+ }
+
+ for (unsigned int k = 0; k < deg;
+ ++k)
+ {
+ tmp (3 * i + 1)
+ -= this->restriction[index][i]
+ ((2 * i * this->degree + j)
+ * deg + k + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((2 * i * this->degree + j)
+ * deg + k + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * i + 2)
+ -= this->restriction[index][i]
+ (j + (k + (2 * i + 1) * deg)
+ * this->degree
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (j + (k + (2 * i + 1) * deg)
+ * this->degree
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ }
+ }
+
+ tmp *= quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i_0
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+ const double L_i_1
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (1));
+ const double L_i_2
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (2));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j_0
+ = L_i_0 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ const double l_j_1
+ = L_i_1 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+ const double l_j_2
+ = L_i_2 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double l_k_0
+ = l_j_0 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_1
+ = l_j_1 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_2
+ = l_j_2 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int l = 0; l < 2;
+ ++l)
+ {
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l)
+ += tmp (3 * l) * l_k_0;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 1)
+ += tmp (3 * l + 1)
+ * l_k_1;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 2)
+ += tmp (3 * l + 2)
+ * l_k_2;
+ }
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= deg; ++j)
+ for (unsigned int k = 0; k < deg; ++k)
+ for (unsigned int l = 0; l < deg; ++l)
+ {
+ if (std::abs (solution ((j * deg + k)
+ * deg + l,
+ 3 * i))
+ > 1e-14)
+ this->restriction[index][i]
+ ((j * deg + k) * deg + l
+ + n_boundary_dofs,
+ dof) = solution ((j * deg + k)
+ * deg + l,
+ 3 * i);
+
+ if (std::abs (solution ((j * deg + k)
+ * deg + l,
+ 3 * i + 1))
+ > 1e-14)
+ this->restriction[index][i]
+ ((j + (k + deg) * this->degree)
+ * deg + l + n_boundary_dofs, dof)
+ = solution ((j * deg + k) * deg
+ + l,
+ 3 * i + 1);
+
+ if (std::abs (solution ((j * deg + k)
+ * deg + l,
+ 3 * i + 2))
+ > 1e-14)
+ this->restriction[index][i]
+ (j + ((k + 2 * deg) * deg + l)
+ * this->degree + n_boundary_dofs,
+ dof) = solution ((j * deg + k)
+ * deg + l,
+ 3 * i + 2);
+ }
+ }
+ }
+
+ break;
+ }
- for (unsigned int q_point = 0; q_point < n_edge_points;
- ++q_point)
+ case RefinementCase<3>::cut_y:
{
- const double tmp
- = 2.0 * quadrature_points[q_point] (0)
- + shift[subface];
- const double weight
- = edge_quadrature.weight (q_point)
- * (this->shape_value_component
- (dof, Point<dim> (0.0,
- quadrature_points[q_point] (0)),
- 1) - interpolation_matrix (0, dof));
-
- for (unsigned int i = 0; i < deg; ++i)
- system_rhs (i)
- += weight
- * lobatto_polynomials_grad[i + 1].value (tmp);
+ // First interpolate the shape
+ // functions of the child cells
+ // to the lowest order shape
+ // functions of the parent cell.
+ for (unsigned int dof = 0; dof < this->dofs_per_cell;
+ ++dof)
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
+ {
+ {
+ const double weight
+ = 2.0 * edge_quadrature.weight (q_point);
+
+ if (edge_quadrature_points[q_point] (0) < 0.5)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ const Point<dim> quadrature_point (i,
+ 2.0 * edge_quadrature_points[q_point] (0),
+ j);
+
+ this->restriction[index][0]
+ ((i + 4 * j) * this->degree, dof)
+ += weight
+ * this->shape_value_component (dof,
+ quadrature_point,
+ 1);
+ }
+
+ else
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ const Point<dim> quadrature_point (i,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0,
+ j);
+
+ this->restriction[index][1]
+ ((i + 4 * j) * this->degree, dof)
+ += weight
+ * this->shape_value_component (dof,
+ quadrature_point,
+ 1);
+ }
+ }
+
+ const double weight
+ = edge_quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ Point<dim>
+ quadrature_point
+ (edge_quadrature_points[q_point] (0), i,
+ j);
+
+ this->restriction[index][i]
+ ((i + 4 * j + 2) * this->degree, dof)
+ += weight
+ * this->shape_value_component (dof,
+ quadrature_point,
+ 1);
+ quadrature_point = Point<dim> (i, j,
+ edge_quadrature_points[q_point] (0));
+ this->restriction[index][j]
+ ((i + 2 * (j + 4)) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+ }
+
+ // Then project the shape functions
+ // of the child cells to the higher
+ // order shape functions of the
+ // parent cell.
+ if (deg > 0)
+ {
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials
+ = Polynomials::Legendre::generate_complete_basis
+ (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
+ {
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (edge_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point)
+ = weight * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+ }
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ FullMatrix<double> solution (deg, 4);
+ FullMatrix<double> system_rhs (deg, 4);
+ Vector<double> tmp (4);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = edge_quadrature.weight (q_point);
+ Point<dim> quadrature_point_0 (i,
+ edge_quadrature_points[q_point] (0),
+ j);
+
+ if (edge_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point_1 (i,
+ 2.0 * edge_quadrature_points[q_point] (0),
+ j);
+
+ tmp (0) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_1,
+ 1)
+ - this->restriction[index][0]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1));
+ tmp (1) = -1.0 * this->restriction[index][1]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1);
+ }
+
+ else
+ {
+ tmp (0) = -1.0 * this->restriction[index][0]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1);
+
+ const Point<dim>
+ quadrature_point_1 (i,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0,
+ j);
+
+ tmp (1) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_1,
+ 1)
+ - this->restriction[index][1]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1));
+ }
+
+ quadrature_point_0
+ = Point<dim> (edge_quadrature_points[q_point] (0),
+ i, j);
+ tmp (2) = weight
+ * (this->shape_value_component
+ (dof, quadrature_point_0,
+ 0)
+ - this->restriction[index][i]
+ ((i + 4 * j + 2)
+ * this->degree, dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_0,
+ 0));
+ quadrature_point_0 = Point<dim> (i, j,
+ edge_quadrature_points[q_point] (0));
+ tmp (3) = weight
+ * (this->shape_value_component
+ (dof, quadrature_point_0,
+ 2)
+ - this->restriction[index][j]
+ ((i + 2 * (j + 4))
+ * this->degree, dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_0, 0));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double L_k
+ = legendre_polynomials[k + 1].value
+ (edge_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0;
+ l < tmp.size (); ++l)
+ system_rhs (k, l) += tmp (l)
+ * L_k;
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ for (unsigned int l = 0; l < 2; ++l)
+ if (std::abs (solution (k, l))
+ > 1e-14)
+ this->restriction[index][l]
+ ((i + 4 * j) * this->degree + k
+ + 1, dof)
+ = solution (k, l);
+
+ if (std::abs (solution (k, 2)) > 1e-14)
+ this->restriction[index][i]
+ ((i + 4 * j + 2) * this->degree + k
+ + 1, dof)
+ = solution (k, 2);
+
+ if (std::abs (solution (k, 3)) > 1e-14)
+ this->restriction[index][j]
+ ((i + 2 * (j + 4)) * this->degree + k
+ + 1, dof)
+ = solution (k, 3);
+ }
+ }
+
+ const QGauss<2> face_quadrature (2 * this->degree);
+ const std::vector<Point<2> >&
+ face_quadrature_points
+ = face_quadrature.get_points ();
+ const std::vector<Polynomials::Polynomial<double> >&
+ lobatto_polynomials
+ = Polynomials::Lobatto::generate_complete_basis
+ (this->degree);
+ const unsigned int n_edge_dofs
+ = GeometryInfo<dim>::lines_per_cell * this->degree;
+ const unsigned int& n_face_quadrature_points
+ = face_quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * this->degree,
+ n_face_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (face_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i
+ = weight
+ * legendre_polynomials[i].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ assembling_matrix (i * deg + j,
+ q_point)
+ = L_i * lobatto_polynomials[j + 2].value
+ (face_quadrature_points[q_point] (1));
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 10);
+ system_rhs.reinit (system_matrix_inv.m (), 10);
+ tmp.reinit (10);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ tmp = 0.0;
+
+ if (face_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ Point<dim> quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1));
+
+ tmp (0) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ tmp (1) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (face_quadrature_points[q_point] (1),
+ 2.0 * face_quadrature_points[q_point] (0),
+ i);
+ tmp (6) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (7) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ }
+
+ else
+ {
+ Point<dim> quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ face_quadrature_points[q_point] (1));
+
+ tmp (2) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ tmp (3) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (face_quadrature_points[q_point] (1),
+ 2.0 * face_quadrature_points[q_point] (0)
+ - 1.0, i);
+ tmp (8) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (9) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ }
+
+ const Point<dim> quadrature_point_1 (i,
+ face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_2
+ (face_quadrature_points[q_point] (0), i,
+ face_quadrature_points[q_point] (1));
+
+ tmp (4) += this->shape_value_component
+ (dof, quadrature_point_2, 0);
+ tmp (5) += this->shape_value_component
+ (dof, quadrature_point_2, 2);
+
+ const Point<dim>
+ quadrature_point_3
+ (face_quadrature_points[q_point] (1),
+ face_quadrature_points[q_point] (0),
+ i);
+
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ {
+ for (unsigned int l = 0; l < 2;
+ ++l)
+ {
+ tmp (2 * l)
+ -= this->restriction[index][l]
+ ((i + 4 * j)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 4 * j) * this->degree
+ + k,
+ quadrature_point_1, 1);
+ tmp (2 * l + 7)
+ -= this->restriction[index][l]
+ ((4 * i + j)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((4 * i + j) * this->degree
+ + k,
+ quadrature_point_3, 1);
+ }
+
+ tmp (2 * j + 1)
+ -= this->restriction[index][j]
+ ((i + 2 * (j + 4))
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree + k,
+ quadrature_point_1, 2);
+ tmp (4) -= this->restriction[index][i]
+ ((i + 4 * j + 2)
+ * this->degree + k,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree + k,
+ quadrature_point_2, 0);
+ tmp (5) -= this->restriction[index][i]
+ ((2 * (i + 4) + j)
+ * this->degree + k,
+ dof)
+ * this->shape_value_component
+ ((2 * (i + 4) + j)
+ * this->degree + k,
+ quadrature_point_2, 2);
+ tmp (2 * (j + 3))
+ -= this->restriction[index][j]
+ ((4 * i + j + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((4 * i + j + 2) * this->degree
+ + k,
+ quadrature_point_3, 0);
+ }
+
+ tmp *= face_quadrature.weight (q_point);
+
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ const double L_j_0
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (0));
+ const double L_j_1
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg;
+ ++k)
+ {
+ const double l_k_0
+ = L_j_0 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (1));
+ const double l_k_1
+ = L_j_1 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0; l < 3;
+ ++l)
+ {
+ system_rhs (j * deg + k,
+ 2 * l)
+ += tmp (2 * l) * l_k_0;
+ system_rhs (j * deg + k,
+ 2 * l + 1)
+ += tmp (2 * l + 1) * l_k_1;
+ }
+
+ for (unsigned int l = 3; l < 5;
+ ++l)
+ {
+ system_rhs (j * deg + k,
+ 2 * l)
+ += tmp (2 * l) * l_k_1;
+ system_rhs (j * deg + k,
+ 2 * l + 1)
+ += tmp (2 * l + 1) * l_k_0;
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int j = 0; j <= deg; ++j)
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ for (unsigned int l = 0; l < 2; ++l)
+ {
+ if (std::abs (solution (j * deg + k,
+ 2 * l))
+ > 1e-14)
+ this->restriction[index][l]
+ (2 * i * this->degree + j * deg
+ + k + n_edge_dofs, dof)
+ = solution (j * deg + k, 2 * l);
+
+ if (std::abs (solution (j * deg + k,
+ 2 * l + 1))
+ > 1e-14)
+ this->restriction[index][l]
+ (((2 * i + 1) * deg + k)
+ * this->degree + j + n_edge_dofs,
+ dof)
+ = solution (j * deg + k,
+ 2 * l + 1);
+
+ if (std::abs (solution (j * deg + k,
+ 2 * (l + 3)))
+ > 1e-14)
+ this->restriction[index][l]
+ (2 * (i + 4) * this->degree
+ + j * deg + k + n_edge_dofs,
+ dof)
+ = solution (j * deg + k,
+ 2 * (l + 3));
+
+ if (std::abs (solution (j * deg + k,
+ 2 * l + 7))
+ > 1e-14)
+ this->restriction[index][l]
+ (((2 * i + 9) * deg + k)
+ * this->degree + j + n_edge_dofs,
+ dof) = solution (j * deg + k,
+ 2 * l + 7);
+ }
+
+ if (std::abs (solution (j * deg + k,
+ 4)) > 1e-14)
+ this->restriction[index][i]
+ (2 * (i + 2) * this->degree + j * deg
+ + k + n_edge_dofs, dof)
+ = solution (j * deg + k, 4);
+
+ if (std::abs (solution (j * deg + k,
+ 5)) > 1e-14)
+ this->restriction[index][i]
+ (((2 * i + 5) * deg + k)
+ * this->degree + j + n_edge_dofs,
+ dof) = solution (j * deg + k, 5);
+ }
+ }
+
+ const QGauss<dim> quadrature (2 * this->degree);
+ const std::vector<Point<dim> >&
+ quadrature_points = quadrature.get_points ();
+ const unsigned int n_boundary_dofs
+ = 2 * GeometryInfo<dim>::faces_per_cell * deg
+ * this->degree + n_edge_dofs;
+ const unsigned int&
+ n_quadrature_points = quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * deg * this->degree,
+ n_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ const double weight
+ = std::sqrt (quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i
+ = weight
+ * legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j
+ = L_i * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ assembling_matrix ((i * deg + j)
+ * deg + k,
+ q_point)
+ = l_j * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ }
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 6);
+ system_rhs.reinit (system_matrix_inv.m (), 6);
+ tmp.reinit (6);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points;
+ ++q_point)
+ {
+ tmp = 0.0;
+
+ if (quadrature_points[q_point] (1) < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1),
+ quadrature_points[q_point] (2));
+
+ tmp (0) += this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (1) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 1);
+ tmp (2) += this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1)
+ - 1.0,
+ quadrature_points[q_point] (2));
+
+ tmp (3) += this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (4) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 1);
+ tmp (5) += this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ for (unsigned int k = 0; k < 2; ++k)
+ {
+ tmp (3 * i)
+ -= this->restriction[index][i]
+ ((i + 4 * k + 2)
+ * this->degree + j, dof)
+ * this->shape_value_component
+ ((i + 4 * k + 2)
+ * this->degree + j,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * i + 2)
+ -= this->restriction[index][i]
+ ((2 * (i + 4) + k)
+ * this->degree + j, dof)
+ * this->shape_value_component
+ ((2 * (i + 4) + k)
+ * this->degree + j,
+ quadrature_points[q_point],
+ 2);
+
+ for (unsigned int l = 0; l < deg;
+ ++l)
+ {
+ tmp (3 * i)
+ -= this->restriction[index][i]
+ ((j + 2 * (k + 4)
+ * this->degree)
+ * deg + l + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((j + 2 * (k + 4)
+ * this->degree) * deg
+ + l + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * i + 1)
+ -= this->restriction[index][i]
+ ((j + 2 * k
+ * this->degree)
+ * deg + l + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((j + 2 * k
+ * this->degree)
+ * deg + l + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * i + 1)
+ -= this->restriction[index][i]
+ (j + ((2 * k + 9) * deg
+ + l)
+ * this->degree
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (j + ((2 * k + 9) * deg
+ + l)
+ * this->degree
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * i + 2)
+ -= this->restriction[index][i]
+ (j + ((2 * k + 1) * deg
+ + l)
+ * this->degree
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (j + ((2 * k + 1) * deg
+ + l) * this->degree
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ }
+
+ for (unsigned int l = 0; l < 2;
+ ++l)
+ {
+ tmp (3 * i + 1)
+ -= this->restriction[index][i]
+ (j + (k + 4 * l)
+ * this->degree, dof)
+ * this->shape_value_component
+ (j + (k + 4 * l)
+ * this->degree,
+ quadrature_points[q_point],
+ 1);
+ }
+ }
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ tmp (3 * i)
+ -= this->restriction[index][i]
+ ((2 * (i + 2) * this->degree
+ + j) * deg + k
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ ((2 * (i + 2) * this->degree
+ + j) * deg + k
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * i + 2)
+ -= this->restriction[index][i]
+ (((2 * i + 5) * deg + k)
+ * this->degree + j
+ + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ (((2 * i + 5) * deg + k)
+ * this->degree + j
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ }
+ }
+
+ tmp *= quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i_0
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+ const double L_i_1
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (1));
+ const double L_i_2
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (2));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j_0
+ = L_i_0 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ const double l_j_1
+ = L_i_1 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+ const double l_j_2
+ = L_i_2 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0; k < deg;
+ ++k)
+ {
+ const double l_k_0
+ = l_j_0 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_1
+ = l_j_1 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_2
+ = l_j_2 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int l = 0; l < 2;
+ ++l)
+ {
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l)
+ += tmp (3 * l) * l_k_0;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 1)
+ += tmp (3 * l + 1)
+ * l_k_1;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 2)
+ += tmp (3 * l + 2)
+ * l_k_2;
+ }
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= deg; ++j)
+ for (unsigned int k = 0; k < deg; ++k)
+ for (unsigned int l = 0; l < deg; ++l)
+ {
+ if (std::abs (solution ((j * deg + k)
+ * deg + l,
+ 3 * i))
+ > 1e-14)
+ this->restriction[index][i]
+ ((j * deg + k) * deg + l
+ + n_boundary_dofs, dof)
+ = solution ((j * deg + k) * deg
+ + l,
+ 3 * i);
+
+ if (std::abs (solution ((j * deg + k)
+ * deg + l,
+ 3 * i + 1))
+ > 1e-14)
+ this->restriction[index][i]
+ ((j + (k + deg) * this->degree)
+ * deg + l + n_boundary_dofs, dof)
+ = solution ((j * deg + k) * deg
+ + l,
+ 3 * i + 1);
+
+ if (std::abs (solution ((j * deg + k)
+ * deg + l,
+ 3 * i + 2))
+ > 1e-14)
+ this->restriction[index][i]
+ (j + ((k + 2 * deg) * deg + l)
+ * this->degree + n_boundary_dofs,
+ dof) = solution ((j * deg + k)
+ * deg + l,
+ 3 * i + 2);
+ }
+ }
+ }
+
+ break;
}
- system_matrix_inv.vmult (solution, system_rhs);
-
- for (unsigned int i = 0; i < deg; ++i)
- if (std::abs (solution (i)) > 1e-14)
- interpolation_matrix (i + 1, dof) = solution (i);
- }
- }
-
- break;
- }
-
- case 3:
- {
- const QGauss<1> reference_edge_quadrature (this->degree);
-
- switch (subface)
- {
- case 0:
- {
- const Quadrature<1>& edge_quadrature
- = QProjector<1>::project_to_child
- (reference_edge_quadrature, 0);
- const unsigned int n_edge_points = edge_quadrature.size ();
- const std::vector<Point<1> >&
- edge_quadrature_points = edge_quadrature.get_points ();
-
- // Let us begin with the
- // interpolation part.
- for (unsigned int q_point = 0; q_point < n_edge_points;
- ++q_point)
+ case RefinementCase<3>::cut_xy:
{
- const double
- weight = edge_quadrature.weight (q_point);
-
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
+ // First interpolate the shape
+ // functions of the child cells
+ // to the lowest order shape
+ // functions of the parent cell.
+ for (unsigned int dof = 0; dof < this->dofs_per_cell;
+ ++dof)
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
{
- interpolation_matrix (i * source_fe.degree, dof)
- += weight
- * this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (0.5 * i,
- edge_quadrature_points[q_point] (0), 0.0),
- 1);
- interpolation_matrix ((i + 2) * source_fe.degree,
- dof)
- += weight
- * this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (edge_quadrature_points[q_point] (0),
- 0.5 * i, 0.0), 0);
+ {
+ const double weight
+ = 2.0 * edge_quadrature.weight (q_point);
+
+ if (edge_quadrature_points[q_point] (0) < 0.5)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ Point<dim> quadrature_point (i,
+ 2.0 * edge_quadrature_points[q_point] (0),
+ j);
+
+ this->restriction[index][i]
+ ((i + 4 * j) * this->degree, dof)
+ += weight
+ * this->shape_value_component (dof,
+ quadrature_point,
+ 1);
+ quadrature_point
+ = Point<dim> (2.0 * edge_quadrature_points[q_point] (0),
+ i, j);
+ this->restriction[index][2 * i]
+ ((i + 4 * j + 2) * this->degree, dof)
+ += weight
+ * this->shape_value_component (dof,
+ quadrature_point,
+ 0);
+ }
+
+ else
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ Point<dim> quadrature_point (i,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0,
+ j);
+
+ this->restriction[index][i + 2]
+ ((i + 4 * j) * this->degree, dof)
+ += weight
+ * this->shape_value_component
+ (dof, quadrature_point, 1);
+ quadrature_point
+ = Point<dim> (2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0, i, j);
+ this->restriction[index][2 * i + 1]
+ ((i + 4 * j + 2) * this->degree, dof)
+ += weight
+ * this->shape_value_component (dof,
+ quadrature_point,
+ 0);
+ }
+ }
+
+ const double weight
+ = edge_quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ const Point<dim> quadrature_point (i, j,
+ edge_quadrature_points[q_point] (0));
+
+ this->restriction[index][i + 2 * j]
+ ((i + 2 * (j + 4)) * this->degree, dof)
+ += weight
+ * this->shape_value_component (dof,
+ quadrature_point,
+ 2);
+ }
+ }
+
+ // Then project the shape functions
+ // of the child cells to the higher
+ // order shape functions of the
+ // parent cell.
+ if (deg > 0)
+ {
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials
+ = Polynomials::Legendre::generate_complete_basis
+ (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
+ {
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (edge_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point)
+ = weight
+ * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+ }
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ FullMatrix<double> solution (deg, 5);
+ FullMatrix<double> system_rhs (deg, 5);
+ Vector<double> tmp (5);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = edge_quadrature.weight (q_point);
+ const Point<dim> quadrature_point_0 (i,
+ edge_quadrature_points[q_point] (0),
+ j);
+ Point<dim>
+ quadrature_point_1
+ (edge_quadrature_points[q_point] (0),
+ i, j);
+
+ if (edge_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ Point<dim> quadrature_point_2 (i,
+ 2.0 * edge_quadrature_points[q_point] (0),
+ j);
+
+ tmp (0) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 1)
+ - this->restriction[index][i]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1));
+ tmp (1)
+ = -1.0 * weight
+ * this->restriction[index][i + 2]
+ ((i + 4 * j)
+ * this->degree, dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1);
+ quadrature_point_2
+ = Point<dim> (2.0 * edge_quadrature_points[q_point] (0),
+ i, j);
+ tmp (2) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 0)
+ - this->restriction[index][2 * i]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_1,
+ 0));
+ tmp (3) = -1.0 * weight
+ * this->restriction[index][2 * i + 1]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_1,
+ 0);
+ }
+
+ else
+ {
+ tmp (0) = -1.0 * weight
+ * this->restriction[index][i]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1);
+
+ Point<dim> quadrature_point_2 (i,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0,
+ j);
+
+ tmp (1) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 1)
+ - this->restriction[index][i + 2]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1));
+ tmp (2) = -1.0 * weight
+ * this->restriction[index][2 * i]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_1,
+ 0);
+ quadrature_point_2
+ = Point<dim> (2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0, i, j);
+ tmp (3) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 0)
+ - this->restriction[index][2 * i + 1]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_1,
+ 0));
+ }
+
+ quadrature_point_1 = Point<dim> (i, j,
+ edge_quadrature_points[q_point] (0));
+ tmp (4) = weight
+ * (this->shape_value_component
+ (dof, quadrature_point_1,
+ 2)
+ - this->restriction[index][i + 2 * j]
+ ((i + 2 * (j + 4))
+ * this->degree, dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_1, 2));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double L_k
+ = legendre_polynomials[k + 1].value
+ (edge_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0;
+ l < tmp.size (); ++l)
+ system_rhs (k, l) += tmp (l)
+ * L_k;
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ for (unsigned int l = 0; l < 2; ++l)
+ {
+ if (std::abs (solution (k, l))
+ > 1e-14)
+ this->restriction[index][i + 2 * l]
+ ((i + 4 * j) * this->degree + k
+ + 1, dof)
+ = solution (k, l);
+
+ if (std::abs (solution (k, l + 2))
+ > 1e-14)
+ this->restriction[index][2 * i + l]
+ ((i + 4 * j + 2) * this->degree
+ + k + 1, dof)
+ = solution (k, l + 2);
+ }
+
+ if (std::abs (solution (k, 4)) > 1e-14)
+ this->restriction[index][i + 2 * j]
+ ((i + 2 * (j + 4)) * this->degree + k
+ + 1, dof)
+ = solution (k, 4);
+ }
+ }
+
+ const QGauss<2> face_quadrature (2 * this->degree);
+ const std::vector<Point<2> >&
+ face_quadrature_points
+ = face_quadrature.get_points ();
+ const std::vector<Polynomials::Polynomial<double> >&
+ lobatto_polynomials
+ = Polynomials::Lobatto::generate_complete_basis
+ (this->degree);
+ const unsigned int n_edge_dofs
+ = GeometryInfo<dim>::lines_per_cell
+ * this->degree;
+ const unsigned int& n_face_quadrature_points
+ = face_quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * this->degree,
+ n_face_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (face_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i = weight
+ * legendre_polynomials[i].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ assembling_matrix (i * deg + j,
+ q_point)
+ = L_i * lobatto_polynomials[j + 2].value
+ (face_quadrature_points[q_point] (1));
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 16);
+ system_rhs.reinit (system_matrix_inv.m (), 16);
+ tmp.reinit (16);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ tmp = 0.0;
+
+ if (face_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ Point<dim> quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1));
+
+ tmp (0) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ tmp (1) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0),
+ i,
+ face_quadrature_points[q_point] (1));
+ tmp (4) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (5) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+
+ if (face_quadrature_points[q_point] (1)
+ < 0.5)
+ {
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1),
+ i);
+ tmp (8) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 0);
+ tmp (9) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 1);
+ }
+
+ else
+ {
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0, i);
+ tmp (12) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 0);
+ tmp (13) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 1);
+ }
+ }
+
+ else
+ {
+ Point<dim> quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ face_quadrature_points[q_point] (1));
+
+ tmp (2) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ tmp (3) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0, i,
+ face_quadrature_points[q_point] (1));
+ tmp (6) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (7) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+
+ if (face_quadrature_points[q_point] (1)
+ < 0.5)
+ {
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * face_quadrature_points[q_point] (1),
+ i);
+ tmp (10) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 0);
+ tmp (11) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 1);
+ }
+
+ else
+ {
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0, i);
+ tmp (14) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 0);
+ tmp (15) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 1);
+ }
+ }
+
+ const Point<dim> quadrature_point_1 (i,
+ face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_2
+ (face_quadrature_points[q_point] (0), i,
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_3
+ (face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1),
+ i);
+
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ {
+ for (unsigned int l = 0; l < 2;
+ ++l)
+ {
+ tmp (2 * l)
+ -= this->restriction[index][i + 2 * l]
+ ((i + 4 * j)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 4 * j) * this->degree
+ + k,
+ quadrature_point_1, 1);
+ tmp (2 * (l + 2))
+ -= this->restriction[index][2 * i + l]
+ ((i + 4 * j + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree + k,
+ quadrature_point_2, 0);
+ tmp (2 * (2 * j + l + 2))
+ -= this->restriction[index][2 * j + l]
+ ((4 * i + j + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((4 * i + j + 2)
+ * this->degree + k,
+ quadrature_point_3, 0);
+ tmp (2 * (2 * j + l) + 9)
+ -= this->restriction[index][2 * j + l]
+ ((4 * i + l)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((4 * i + l)
+ * this->degree + k,
+ quadrature_point_3, 1);
+ }
+
+ tmp (2 * j + 1)
+ -= this->restriction[index][i + 2 * j]
+ ((i + 2 * (j + 4))
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree + k,
+ quadrature_point_1, 2);
+ tmp (2 * j + 5)
+ -= this->restriction[index][2 * i + j]
+ ((2 * (i + 4) + j)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((2 * (i + 4) + j)
+ * this->degree + k,
+ quadrature_point_2, 2);
+ }
+
+ tmp *= face_quadrature.weight (q_point);
+
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ const double L_j_0
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (0));
+ const double L_j_1
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg;
+ ++k)
+ {
+ const double l_k_0 = L_j_0
+ * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (1));
+ const double l_k_1 = L_j_1
+ * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0; l < 8;
+ ++l)
+ {
+ system_rhs (j * deg + k,
+ 2 * l)
+ += tmp (2 * l) * l_k_0;
+ system_rhs (j * deg + k,
+ 2 * l + 1)
+ += tmp (2 * l + 1) * l_k_1;
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ for (unsigned int l = 0; l < deg; ++l)
+ {
+ if (std::abs (solution (k * deg + l,
+ 2 * j))
+ > 1e-14)
+ this->restriction[index][i + 2 * j]
+ ((2 * i * this->degree + k) * deg
+ + l
+ + n_edge_dofs,
+ dof) = solution (k * deg + l,
+ 2 * j);
+
+ if (std::abs (solution (k * deg + l,
+ 2 * j + 1))
+ > 1e-14)
+ this->restriction[index][i + 2 * j]
+ (((2 * i + 1) * deg + l)
+ * this->degree + k + n_edge_dofs,
+ dof) = solution (k * deg + l,
+ 2 * j + 1);
+
+ if (std::abs (solution (k * deg + l,
+ 2 * (j + 2)))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ ((2 * (i + 2) * this->degree + k)
+ * deg + l + n_edge_dofs, dof)
+ = solution (k * deg + l,
+ 2 * (j + 2));
+
+ if (std::abs (solution (k * deg + l,
+ 2 * j + 5))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ (((2 * i + 5) * deg + l)
+ * this->degree + k + n_edge_dofs,
+ dof) = solution (k * deg + l,
+ 2 * j + 5);
+
+ for (unsigned int m = 0; m < 2; ++m)
+ {
+ if (std::abs (solution (k * deg
+ + l,
+ 2 * (2 * j + m + 2)))
+ > 1e-14)
+ this->restriction[index][2 * j + m]
+ ((2 * (i + 4) * this->degree
+ + k) * deg + l
+ + n_edge_dofs, dof)
+ = solution (k * deg + l,
+ 2 * (2 * j + m
+ + 2));
+
+ if (std::abs (solution (k * deg
+ + l,
+ 2 * (2 * j + m) + 9))
+ > 1e-14)
+ this->restriction[index][2 * j + m]
+ (((2 * i + 9) * deg + l)
+ * this->degree + k
+ + n_edge_dofs, dof)
+ = solution (k * deg + l,
+ 2 * (2 * j + m)
+ + 9);
+ }
+ }
+ }
+
+ const QGauss<dim> quadrature (2 * this->degree);
+ const std::vector<Point<dim> >&
+ quadrature_points = quadrature.get_points ();
+ const unsigned int n_boundary_dofs
+ = 2 * GeometryInfo<dim>::faces_per_cell * deg
+ * this->degree + n_edge_dofs;
+ const unsigned int&
+ n_quadrature_points = quadrature.size ();
+
+ {
+ FullMatrix<double> assembling_matrix (deg * deg
+ * this->degree,
+ n_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ const double weight
+ = std::sqrt (quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i = weight
+ * legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j
+ = L_i * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ assembling_matrix ((i * deg + j)
+ * deg + k,
+ q_point)
+ = l_j * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ }
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
}
+
+ solution.reinit (system_matrix_inv.m (), 12);
+ system_rhs.reinit (system_matrix_inv.m (), 12);
+ tmp.reinit (12);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ tmp = 0.0;
+
+ if (quadrature_points[q_point] (0) < 0.5)
+ {
+ if (quadrature_points[q_point] (1)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point (2.0 * quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1),
+ quadrature_points[q_point] (2));
+
+ tmp (0) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (1) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 1);
+ tmp (2)
+ += this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point (2.0 * quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1)
+ - 1.0,
+ quadrature_points[q_point] (2));
+
+ tmp (3) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (4) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 1);
+ tmp (5)
+ += this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+ }
+
+ else
+ if (quadrature_points[q_point] (1) < 0.5)
+ {
+ const Point<dim>
+ quadrature_point (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (1),
+ quadrature_points[q_point] (2));
+
+ tmp (6) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (7) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 1);
+ tmp (8)
+ += this->shape_value_component (dof,
+ quadrature_point,
+ 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (1)
+ - 1.0,
+ quadrature_points[q_point] (2));
+
+ tmp (9) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (10) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 1);
+ tmp (11)
+ += this->shape_value_component (dof,
+ quadrature_point,
+ 2);
+ }
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ {
+ for (unsigned int l = 0; l < 2; ++l)
+ {
+ tmp (3 * (i + 2 * j))
+ -= this->restriction[index][2 * i + j]
+ ((i + 4 * l + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 4 * l + 2)
+ * this->degree + k,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * (i + 2 * j) + 1)
+ -= this->restriction[index][2 * i + j]
+ (k + (j + 4 * l)
+ * this->degree, dof)
+ * this->shape_value_component
+ (k + (j + 4 * l)
+ * this->degree,
+ quadrature_points[q_point],
+ 1);
+
+ for (unsigned int m = 0;
+ m < deg; ++m)
+ {
+ tmp (3 * (i + 2 * j))
+ -= this->restriction[index][2 * i + j]
+ ((k + 2 * (l + 4)
+ * this->degree)
+ * deg + m
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ ((k + 2 * (l + 4)
+ * this->degree)
+ * deg + m
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * (i + 2 * j) + 1)
+ -= this->restriction[index][2 * i + j]
+ (k + ((2 * l + 9) * deg
+ + m)
+ * this->degree
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (k + ((2 * l + 9) * deg
+ + m)
+ * this->degree
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ }
+ }
+
+ for (unsigned int l = 0; l < deg;
+ ++l)
+ {
+ tmp (3 * (i + 2 * j))
+ -= this->restriction[index][2 * i + j]
+ ((2 * (i + 2)
+ * this->degree + k)
+ * deg + l + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((2 * (i + 2)
+ * this->degree + k)
+ * deg + l + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * (i + 2 * j) + 1)
+ -= this->restriction[index][2 * i + j]
+ ((2 * j * this->degree + k)
+ * deg + l + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((2 * j * this->degree + k)
+ * deg + l + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * (i + 2 * j) + 2)
+ -= this->restriction[index][2 * i + j]
+ (((2 * j + 1) * deg + l)
+ * this->degree + k
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * j + 1) * deg + l)
+ * this->degree + k
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ tmp (3 * (i + 2 * j) + 2)
+ -= this->restriction[index][2 * i + j]
+ (((2 * i + 5) * deg + l)
+ * this->degree + k
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * i + 5) * deg + l)
+ * this->degree + k
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ }
+
+ tmp (3 * (i + 2 * j) + 2)
+ -= this->restriction[index][2 * i + j]
+ ((2 * (i + 4) + j)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((2 * (i + 4) + j)
+ * this->degree + k,
+ quadrature_points[q_point],
+ 2);
+ }
+
+ tmp *= quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i_0
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+ const double L_i_1
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (1));
+ const double L_i_2
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (2));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j_0
+ = L_i_0 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ const double l_j_1
+ = L_i_1 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+ const double l_j_2
+ = L_i_2 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0; k < deg;
+ ++k)
+ {
+ const double l_k_0
+ = l_j_0 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_1
+ = l_j_1 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_2
+ = l_j_2 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int l = 0; l < 4;
+ ++l)
+ {
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l)
+ += tmp (3 * l) * l_k_0;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 1)
+ += tmp (3 * l + 1)
+ * l_k_1;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 2)
+ += tmp (3 * l + 2)
+ * l_k_2;
+ }
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ for (unsigned int l = 0; l < deg; ++l)
+ for (unsigned int m = 0; m < deg; ++m)
+ {
+ if (std::abs (solution
+ ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j)))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ ((k * deg + l) * deg + m
+ + n_boundary_dofs,
+ dof)
+ = solution ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j));
+
+ if (std::abs (solution
+ ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j) + 1))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ ((k + (l + deg) * this->degree)
+ * deg + m + n_boundary_dofs, dof)
+ = solution ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j)
+ + 1);
+
+ if (std::abs (solution
+ ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j) + 2))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ (k + ((l + 2 * deg) * deg + m)
+ * this->degree
+ + n_boundary_dofs, dof)
+ = solution ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j)
+ + 2);
+ }
+ }
+ }
+
+ break;
}
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- {
- if (std::abs (interpolation_matrix
- (i * source_fe.degree, dof)) < 1e-14)
- interpolation_matrix (i * source_fe.degree, dof)
- = 0.0;
-
- if (std::abs (interpolation_matrix
- ((i + 2) * source_fe.degree, dof))
- < 1e-14)
- interpolation_matrix ((i + 2) * source_fe.degree,
- dof) = 0.0;
- }
-
- // If the degree is greater
- // than 0, then we have still
- // some higher order edge
- // shape functions to
- // consider.
- // Here the projection part
- // starts. The dof values
- // are obtained by solving
- // a linear system of
- // equations.
- if (deg > 0)
+ case RefinementCase<3>::cut_z:
{
- // We start with projection
- // on the higher order edge
- // shape function.
- const QGauss<dim - 1> reference_face_quadrature
- (this->degree);
- const Quadrature<dim - 1>& face_quadrature
- = QProjector<dim - 1>::project_to_child
- (reference_face_quadrature, 0);
- const std::vector<Polynomials::Polynomial<double> >&
- legendre_polynomials
- = Polynomials::Legendre::generate_complete_basis
- (deg);
- const std::vector<Polynomials::Polynomial<double> >&
- lobatto_polynomials
- = Polynomials::Lobatto::generate_complete_basis
- (this->degree);
- const std::vector<Point<dim - 1> >&
- face_quadrature_points = face_quadrature.get_points ();
- const unsigned int& n_face_points
- = face_quadrature.size ();
- FullMatrix<double> assembling_matrix
- (deg, n_edge_points);
- FullMatrix<double> system_matrix (deg, deg);
- FullMatrix<double> system_matrix_inv (deg, deg);
- std::vector<Polynomials::Polynomial<double> >
- lobatto_polynomials_grad (this->degree);
-
- for (unsigned int i = 0; i <= deg; ++i)
- lobatto_polynomials_grad[i]
- = lobatto_polynomials[i + 1].derivative ();
-
-//TODO:[Markus Buerg] We should not need those, since the projections
-//on each face should just be copies of each other.
-
- // Shifted and scaled
- // quadrature points on
- // the four edges of a
- // face.
- std::vector<std::vector<Point<dim> > >
- edge_quadrature_points_full_dim
- (GeometryInfo<dim>::lines_per_face,
- std::vector<Point<dim> > (n_edge_points));
-
- for (unsigned int q_point = 0; q_point < n_edge_points;
- ++q_point)
+ // First interpolate the shape
+ // functions of the child cells
+ // to the lowest order shape
+ // functions of the parent cell.
+ for (unsigned int dof = 0; dof < this->dofs_per_cell;
+ ++dof)
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
+ {
+ {
+ const double weight
+ = edge_quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ Point<dim> quadrature_point (i,
+ edge_quadrature_points[q_point] (0),
+ j);
+
+ this->restriction[index][j]
+ ((i + 4 * j) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 1);
+ quadrature_point
+ = Point<dim> (edge_quadrature_points[q_point] (0),
+ i, j);
+ this->restriction[index][j]
+ ((i + 4 * j + 2) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ }
+ }
+
+ const double weight
+ = 2.0 * edge_quadrature.weight (q_point);
+
+ if (edge_quadrature_points[q_point] (0) < 0.5)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ const Point<dim> quadrature_point (i, j,
+ 2.0 * edge_quadrature_points[q_point] (0));
+
+ this->restriction[index][0]
+ ((i + 2 * (j + 4)) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ else
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ const Point<dim> quadrature_point (i, j,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0);
+
+ this->restriction[index][1]
+ ((i + 2 * (j + 4)) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+ }
+
+ // Then project the shape functions
+ // of the child cells to the higher
+ // order shape functions of the
+ // parent cell.
+ if (deg > 0)
{
- edge_quadrature_points_full_dim[0][q_point]
- = Point<dim> (0.0,
- edge_quadrature_points[q_point] (0),
- 0.0);
- edge_quadrature_points_full_dim[1][q_point]
- = Point<dim> (0.5,
- edge_quadrature_points[q_point] (0),
- 0.0);
- edge_quadrature_points_full_dim[2][q_point]
- = Point<dim> (edge_quadrature_points[q_point] (0),
- 0.0, 0.0);
- edge_quadrature_points_full_dim[3][q_point]
- = Point<dim> (edge_quadrature_points[q_point] (0),
- 0.5, 0.0);
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials
+ = Polynomials::Legendre::generate_complete_basis
+ (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
+ {
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (edge_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point)
+ = weight
+ * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+ }
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ FullMatrix<double> solution (deg, 4);
+ FullMatrix<double> system_rhs (deg, 4);
+ Vector<double> tmp (4);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = edge_quadrature.weight (q_point);
+ Point<dim> quadrature_point_0 (i,
+ edge_quadrature_points[q_point] (0),
+ j);
+
+ tmp (0) = weight
+ * (this->shape_value_component
+ (dof, quadrature_point_0,
+ 1)
+ - this->restriction[index][j]
+ ((i + 4 * j) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j) * this->degree,
+ quadrature_point_0, 1));
+ quadrature_point_0
+ = Point<dim> (edge_quadrature_points[q_point] (0),
+ i, j);
+ tmp (1) = weight
+ * (this->shape_value_component
+ (dof, quadrature_point_0,
+ 0)
+ - this->restriction[index][j]
+ ((i + 4 * j + 2) * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2) * this->degree,
+ quadrature_point_0, 0));
+ quadrature_point_0
+ = Point<dim> (i, j,
+ edge_quadrature_points[q_point] (0));
+
+ if (edge_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ const Point<dim> quadrature_point_1
+ (i, j,
+ 2.0 * edge_quadrature_points[q_point] (0));
+
+ tmp (2) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_1,
+ 2)
+ - this->restriction[index][0]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_0,
+ 2));
+ tmp (3) = -1.0 * weight
+ * this->restriction[index][1]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_0,
+ 2);
+ }
+
+ else
+ {
+ tmp (2) = -1.0 * weight
+ * this->restriction[index][0]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_0,
+ 2);
+
+ const Point<dim>
+ quadrature_point_1 (i, j,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0);
+
+ tmp (3) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_1,
+ 2)
+ - this->restriction[index][1]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_0,
+ 2));
+ }
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double L_k
+ = legendre_polynomials[k + 1].value
+ (edge_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0;
+ l < tmp.size (); ++l)
+ system_rhs (k, l) += tmp (l)
+ * L_k;
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int k = 0; k < 2; ++k)
+ for (unsigned int l = 0; l < deg; ++l)
+ {
+ if (std::abs (solution (l, k))
+ > 1e-14)
+ this->restriction[index][j]
+ ((i + 2 * (2 * j + k))
+ * this->degree + l + 1, dof)
+ = solution (l, k);
+
+ if (std::abs (solution (l, k + 2))
+ > 1e-14)
+ this->restriction[index][k]
+ ((i + 2 * (j + 4)) * this->degree
+ + l + 1, dof)
+ = solution (l, k + 2);
+ }
+ }
+
+ const QGauss<2> face_quadrature (2 * this->degree);
+ const std::vector<Point<2> >&
+ face_quadrature_points
+ = face_quadrature.get_points ();
+ const std::vector<Polynomials::Polynomial<double> >&
+ lobatto_polynomials
+ = Polynomials::Lobatto::generate_complete_basis
+ (this->degree);
+ const unsigned int n_edge_dofs
+ = GeometryInfo<dim>::lines_per_cell
+ * this->degree;
+ const unsigned int& n_face_quadrature_points
+ = face_quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * this->degree,
+ n_face_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (face_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i = weight
+ * legendre_polynomials[i].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ assembling_matrix (i * deg + j, q_point)
+ = L_i * lobatto_polynomials[j + 2].value
+ (face_quadrature_points[q_point] (1));
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 10);
+ system_rhs.reinit (system_matrix_inv.m (), 10);
+ tmp.reinit (10);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ tmp = 0.0;
+
+ if (face_quadrature_points[q_point] (1)
+ < 0.5)
+ {
+ Point<dim> quadrature_point_0 (i,
+ face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1));
+
+ tmp (0) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ tmp (1) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (face_quadrature_points[q_point] (0),
+ i,
+ 2.0 * face_quadrature_points[q_point] (1));
+ tmp (4) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (5) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ }
+
+ else
+ {
+ Point<dim> quadrature_point_0 (i,
+ face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0);
+
+ tmp (2) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ tmp (3) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (face_quadrature_points[q_point] (0),
+ i,
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0);
+ tmp (6) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (7) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ }
+
+ const Point<dim> quadrature_point_1 (i,
+ face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_2
+ (face_quadrature_points[q_point] (0), i,
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_3
+ (face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1),
+ i);
+
+ tmp (8) += this->shape_value_component
+ (dof, quadrature_point_3, 0);
+ tmp (9) += this->shape_value_component
+ (dof, quadrature_point_3, 1);
+
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ {
+ tmp (2 * j)
+ -= this->restriction[index][j]
+ ((i + 4 * j) * this->degree
+ + k, dof)
+ * this->shape_value_component
+ ((i + 4 * j) * this->degree
+ + k,
+ quadrature_point_1, 1);
+ tmp (2 * (j + 2))
+ -= this->restriction[index][j]
+ ((i + 4 * j + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2) * this->degree
+ + k,
+ quadrature_point_2, 0);
+ tmp (8)
+ -= this->restriction[index][i]
+ ((4 * i + j + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((4 * i + j + 2) * this->degree
+ + k,
+ quadrature_point_3, 0);
+ tmp (9)
+ -= this->restriction[index][i]
+ ((4 * i + j) * this->degree
+ + k, dof)
+ * this->shape_value_component
+ ((4 * i + j) * this->degree
+ + k,
+ quadrature_point_3, 1);
+
+ for (unsigned int l = 0; l < 2;
+ ++l)
+ {
+ tmp (2 * l + 1)
+ -= this->restriction[index][l]
+ ((2 * (j + 4) + i)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((2 * (j + 4) + i)
+ * this->degree + k,
+ quadrature_point_1, 2);
+ tmp (2 * l + 5)
+ -= this->restriction[index][l]
+ ((j + 2 * (i + 4))
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((j + 2 * (i + 4))
+ * this->degree + k,
+ quadrature_point_2, 2);
+ }
+ }
+
+ tmp *= face_quadrature.weight (q_point);
+
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ const double L_j_0
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (0));
+ const double L_j_1
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double l_k_0
+ = L_j_0 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (1));
+ const double l_k_1
+ = L_j_1 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0; l < 5;
+ ++l)
+ {
+ system_rhs (j * deg + k,
+ 2 * l)
+ += tmp (2 * l) * l_k_0;
+ system_rhs (j * deg + k,
+ 2 * l + 1)
+ += tmp (2 * l + 1) * l_k_1;
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int j = 0; j <= deg; ++j)
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ for (unsigned int l = 0; l < 2; ++l)
+ {
+ if (std::abs (solution (j * deg + k,
+ 2 * l))
+ < 1e-14)
+ this->restriction[index][l]
+ ((2 * i * this->degree + j) * deg
+ + k
+ + n_edge_dofs,
+ dof) = solution (j * deg + k,
+ 2 * l);
+
+ if (std::abs (solution (j * deg + k,
+ 2 * l + 1))
+ < 1e-14)
+ this->restriction[index][l]
+ (((2 * i + 1) * deg + k)
+ * this->degree + j + n_edge_dofs,
+ dof) = solution (j * deg + k,
+ 2 * l + 1);
+
+ if (std::abs (solution (j * deg + k,
+ 2 * (l + 2)))
+ < 1e-14)
+ this->restriction[index][l]
+ ((2 * (i + 2) * this->degree + j)
+ * deg + k + n_edge_dofs, dof)
+ = solution (j * deg + k,
+ 2 * (l + 2));
+
+ if (std::abs (solution (j * deg + k,
+ 2 * l + 5))
+ < 1e-14)
+ this->restriction[index][l]
+ (((2 * i + 5) * deg + k)
+ * this->degree + j + n_edge_dofs,
+ dof) = solution (j * deg + k,
+ 2 * l + 5);
+ }
+
+ if (std::abs (solution (j * deg + k, 8))
+ < 1e-14)
+ this->restriction[index][i]
+ ((2 * (i + 4) * this->degree + j)
+ * deg + k + n_edge_dofs, dof)
+ = solution (j * deg + k, 8);
+
+ if (std::abs (solution (j * deg + k, 9))
+ < 1e-14)
+ this->restriction[index][i]
+ (((2 * i + 9) * deg + k)
+ * this->degree + j + n_edge_dofs,
+ dof) = solution (j * deg + k, 9);
+ }
+ }
+
+ const QGauss<dim> quadrature (2 * this->degree);
+ const std::vector<Point<dim> >&
+ quadrature_points = quadrature.get_points ();
+ const unsigned int n_boundary_dofs
+ = 2 * GeometryInfo<dim>::faces_per_cell * deg
+ * this->degree + n_edge_dofs;
+ const unsigned int&
+ n_quadrature_points = quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * deg * this->degree,
+ n_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ const double weight
+ = std::sqrt (quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i = weight
+ * legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j
+ = L_i * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ assembling_matrix ((i * deg + j)
+ * deg + k,
+ q_point)
+ = l_j * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ }
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 6);
+ system_rhs.reinit (system_matrix_inv.m (), 6);
+ tmp.reinit (6);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ tmp = 0.0;
+
+ if (quadrature_points[q_point] (2) < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (quadrature_points[q_point] (0),
+ quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2));
+
+ tmp (0) += this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (1) += this->shape_value_component
+ (dof, quadrature_point, 1);
+ tmp (2) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (quadrature_points[q_point] (0),
+ quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2)
+ - 1.0);
+
+ tmp (3) += this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (4) += this->shape_value_component
+ (dof, quadrature_point, 1);
+ tmp (5) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ for (unsigned int k = 0; k < 2; ++k)
+ {
+ tmp (3 * i)
+ -= this->restriction[index][i]
+ ((4 * i + k + 2)
+ * this->degree + j, dof)
+ * this->shape_value_component
+ ((4 * i + k + 2)
+ * this->degree + j,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * i + 1)
+ -= this->restriction[index][i]
+ ((4 * i + k) * this->degree
+ + j, dof)
+ * this->shape_value_component
+ ((4 * i + k) * this->degree
+ + j,
+ quadrature_points[q_point],
+ 1);
+
+ for (unsigned int l = 0; l < deg;
+ ++l)
+ {
+ tmp (3 * i)
+ -= this->restriction[index][i]
+ ((j + 2 * (k + 2)
+ * this->degree) * deg
+ + l
+ + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((j + 2 * (k + 2)
+ * this->degree)
+ * deg + l + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * i + 1)
+ -= this->restriction[index][i]
+ ((j + 2 * k
+ * this->degree)
+ * deg + l + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((j + 2 * k * this->degree)
+ * deg + l
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ }
+
+ for (unsigned int l = 0; l < 2;
+ ++l)
+ {
+ tmp (3 * i + 2)
+ -= this->restriction[index][i]
+ (j + (k + 2 * (l + 4))
+ * this->degree, dof)
+ * this->shape_value_component
+ (j + (k + 2 * (l + 4))
+ * this->degree,
+ quadrature_points[q_point],
+ 2);
+
+ for (unsigned int m = 0;
+ m < deg; ++m)
+ tmp (3 * i + 2)
+ -= this->restriction[index][i]
+ (j + ((2 * (k + 2 * m)
+ + 1) * deg
+ + l)
+ * this->degree
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (j + ((2 * (k + 2 * m)
+ + 1) * deg + l)
+ * this->degree
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ }
+ }
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ tmp (3 * i)
+ -= this->restriction[index][i]
+ ((2 * (i + 4) * this->degree
+ + j) * deg + k
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ ((2 * (i + 4) * this->degree
+ + j) * deg + k
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * i + 1)
+ -= this->restriction[index][i]
+ (((2 * i + 9) * deg + k)
+ * this->degree + j
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * i + 9) * deg + k)
+ * this->degree + j
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ }
+ }
+
+ tmp *= quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i_0
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+ const double L_i_1
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (1));
+ const double L_i_2
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (2));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j_0
+ = L_i_0 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ const double l_j_1
+ = L_i_1 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+ const double l_j_2
+ = L_i_2 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0; k < deg;
+ ++k)
+ {
+ const double l_k_0
+ = l_j_0 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_1
+ = l_j_1 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_2
+ = l_j_2 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int l = 0; l < 2;
+ ++l)
+ {
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l)
+ += tmp (3 * l) * l_k_0;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 1)
+ += tmp (3 * l + 1)
+ * l_k_1;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 2)
+ += tmp (3 * l + 2)
+ * l_k_2;
+ }
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= deg; ++j)
+ for (unsigned int k = 0; k < deg; ++k)
+ for (unsigned int l = 0; l < deg; ++l)
+ {
+ if (std::abs (solution ((j * deg + k)
+ * deg + l,
+ 3 * i))
+ > 1e-14)
+ this->restriction[index][i]
+ ((j * deg + k) * deg + l
+ + n_boundary_dofs,
+ dof) = solution ((j * deg + k)
+ * deg + l,
+ 3 * i);
+
+ if (std::abs (solution ((j * deg + k)
+ * deg + l,
+ 3 * i + 1))
+ > 1e-14)
+ this->restriction[index][i]
+ ((j + (k + deg) * this->degree)
+ * deg + l + n_boundary_dofs, dof)
+ = solution ((j * deg + k) * deg
+ + l,
+ 3 * i + 1);
+
+ if (std::abs (solution ((j * deg + k)
+ * deg + l,
+ 3 * i + 2))
+ > 1e-14)
+ this->restriction[index][i]
+ (j + ((k + 2 * deg) * deg + l)
+ * this->degree + n_boundary_dofs,
+ dof) = solution ((j * deg + k)
+ * deg + l,
+ 3 * i + 2);
+ }
+ }
}
+
+ break;
+ }
- // Set up the system matrix.
- // This can be used for all
- // edges.
- for (unsigned int q_point = 0;
- q_point < n_edge_points; ++q_point)
- {
- const double tmp
- = 2.0 * edge_quadrature_points[q_point] (0);
- const double weight
- = std::sqrt (edge_quadrature.weight (q_point));
-
- for (unsigned int i = 0; i < deg; ++i)
- assembling_matrix (i, q_point)
- = weight * lobatto_polynomials_grad[i + 1].value
- (tmp);
- }
-
- assembling_matrix.mTmult (system_matrix,
- assembling_matrix);
- system_matrix_inv.invert (system_matrix);
-
- Vector<double> solution (deg);
- Vector<double> system_rhs (deg);
-
- for (unsigned int dof = 0; dof < this->dofs_per_face;
+ case RefinementCase<3>::cut_xz:
+ {
+ // First interpolate the shape
+ // functions of the child cells
+ // to the lowest order shape
+ // functions of the parent cell.
+ for (unsigned int dof = 0; dof < this->dofs_per_cell;
++dof)
- for (unsigned int line = 0;
- line < GeometryInfo<dim>::lines_per_face;
- ++line)
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
+ {
{
- // Set up the right hand side.
- system_rhs = 0;
-
+ const double weight
+ = edge_quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ const Point<dim> quadrature_point (i,
+ edge_quadrature_points[q_point] (0),
+ j);
+
+ this->restriction[index][2 * i + j]
+ ((i + 4 * j) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 1);
+ }
+ }
+
+ const double weight
+ = 2.0 * edge_quadrature.weight (q_point);
+
+ if (edge_quadrature_points[q_point] (0) < 0.5)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ Point<dim>
+ quadrature_point
+ (2.0 * edge_quadrature_points[q_point] (0),
+ i, j);
+
+ this->restriction[index][j]
+ ((i + 4 * j + 2) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ quadrature_point = Point<dim> (i, j,
+ edge_quadrature_points[q_point] (0));
+ this->restriction[index][2 * i]
+ ((i + 2 * (j + 4)) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ else
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ Point<dim>
+ quadrature_point
+ (2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0, i, j);
+
+ this->restriction[index][j + 2]
+ ((i + 4 * j + 2) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ quadrature_point = Point<dim> (i, j,
+ edge_quadrature_points[q_point] (0));
+ this->restriction[index][2 * i + 1]
+ ((i + 2 * (j + 4)) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+ }
+
+ // Then project the shape functions
+ // of the child cells to the higher
+ // order shape functions of the
+ // parent cell.
+ if (deg > 0)
+ {
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials
+ = Polynomials::Legendre::generate_complete_basis
+ (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
+ {
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (edge_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point) = weight
+ * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+ }
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ FullMatrix<double> solution (deg, 5);
+ FullMatrix<double> system_rhs (deg, 5);
+ Vector<double> tmp (5);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = edge_quadrature.weight (q_point);
+ Point<dim> quadrature_point_0 (i,
+ edge_quadrature_points[q_point] (0),
+ j);
+ tmp (0) = weight
+ * (this->shape_value_component
+ (dof, quadrature_point_0,
+ 1)
+ - this->restriction[index][2 * i + j]
+ ((i + 4 * j)
+ * this->degree, dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1));
+ quadrature_point_0
+ = Point<dim> (edge_quadrature_points[q_point] (0),
+ i, j);
+
+ const Point<dim> quadrature_point_1 (i,
+ j,
+ edge_quadrature_points[q_point] (0));
+
+ if (edge_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ Point<dim>
+ quadrature_point_2 (2.0 * edge_quadrature_points[q_point] (0),
+ i, j);
+
+ tmp (1) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 0)
+ - this->restriction[index][j]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_0,
+ 0));
+ tmp (2) = -1.0 * weight
+ * this->restriction[index][j + 2]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_0,
+ 0);
+ quadrature_point_2 = Point<dim> (i,
+ j,
+ 2.0 * edge_quadrature_points[q_point] (0));
+ tmp (3) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 2)
+ - this->restriction[index][2 * i]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_1,
+ 2));
+ tmp (4) = -1.0 * weight
+ * this->restriction[index][2 * i + 1]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_1,
+ 2);
+ }
+
+ else
+ {
+ tmp (1) = -1.0 * weight
+ * this->restriction[index][j]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_0,
+ 0);
+
+ Point<dim>
+ quadrature_point_2
+ (2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0, i, j);
+
+ tmp (2) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 0)
+ - this->restriction[index][j + 2]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_0,
+ 0));
+ tmp (3) = -1.0 * weight
+ * this->restriction[index][2 * i]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_1,
+ 2);
+ quadrature_point_2 = Point<dim> (i,
+ j,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0);
+ tmp (4) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 2)
+ - this->restriction[index][2 * i + 1]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_1,
+ 2));
+ }
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double L_k
+ = legendre_polynomials[k + 1].value
+ (edge_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0;
+ l < tmp.size (); ++l)
+ system_rhs (k, l) += tmp (l)
+ * L_k;
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ if (std::abs (solution (k, 0))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ ((i + 4 * j) * this->degree + k + 1,
+ dof) = solution (k, 0);
+
+ for (unsigned int l = 0; l < 2; ++l)
+ {
+ if (std::abs (solution (k, l + 1))
+ > 1e-14)
+ this->restriction[index][j + 2 * l]
+ ((i + 4 * j + 2) * this->degree
+ + k + 1, dof)
+ = solution (k, l + 1);
+
+ if (std::abs (solution (k, l + 3))
+ > 1e-14)
+ this->restriction[index][2 * i + l]
+ ((i + 2 * (j + 4)) * this->degree
+ + k + 1, dof)
+ = solution (k, l + 3);
+ }
+ }
+ }
+
+ const QGauss<2> face_quadrature (2 * this->degree);
+ const std::vector<Point<2> >& face_quadrature_points
+ = face_quadrature.get_points ();
+ const std::vector<Polynomials::Polynomial<double> >&
+ lobatto_polynomials
+ = Polynomials::Lobatto::generate_complete_basis
+ (this->degree);
+ const unsigned int n_edge_dofs
+ = GeometryInfo<dim>::lines_per_cell
+ * this->degree;
+ const unsigned int& n_face_quadrature_points
+ = face_quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * this->degree,
+ n_face_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (face_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i = weight
+ * legendre_polynomials[i].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ assembling_matrix (i * deg + j, q_point)
+ = L_i * lobatto_polynomials[j + 2].value
+ (face_quadrature_points[q_point] (1));
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 16);
+ system_rhs.reinit (system_matrix_inv.m (), 16);
+ tmp.reinit (16);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ tmp = 0.0;
+
+ if (face_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ Point<dim> quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1));
+
+ tmp (0) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ tmp (1) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1),
+ i);
+ tmp (12) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (13)
+ += this->shape_value_component (dof,
+ quadrature_point_0,
+ 1);
+
+ if (face_quadrature_points[q_point] (1)
+ < 0.5)
+ {
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0),
+ i,
+ 2.0 * face_quadrature_points[q_point] (1));
+ tmp (4) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 0);
+ tmp (5) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 2);
+ }
+
+ else
+ {
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0),
+ i,
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0);
+ tmp (6) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 0);
+ tmp (7) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 2);
+ }
+ }
+
+ else
+ {
+ Point<dim> quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ face_quadrature_points[q_point] (1));
+
+ tmp (2) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ tmp (3) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ face_quadrature_points[q_point] (1),
+ i);
+ tmp (14) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (15)
+ += this->shape_value_component (dof,
+ quadrature_point_0,
+ 1);
+
+ if (face_quadrature_points[q_point] (1)
+ < 0.5)
+ {
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0, i,
+ 2.0 * face_quadrature_points[q_point] (1));
+ tmp (8) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (9) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ }
+
+ else
+ {
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0, i,
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0);
+ tmp (10) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 0);
+ tmp (11) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 2);
+ }
+ }
+
+ const Point<dim> quadrature_point_1 (i,
+ face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_2
+ (face_quadrature_points[q_point] (0), i,
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_3
+ (face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1),
+ i);
+
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ {
+ tmp (2 * j)
+ -= this->restriction[index][2 * i + j]
+ ((i + 4 * j) * this->degree
+ + k, dof)
+ * this->shape_value_component
+ ((i + 4 * j) * this->degree + k,
+ quadrature_point_1, 1);
+ tmp (2 * j + 13)
+ -= this->restriction[index][i + 2 * j]
+ ((4 * i + j) * this->degree
+ + k, dof)
+ * this->shape_value_component
+ ((4 * i + j) * this->degree + k,
+ quadrature_point_3, 1);
+
+ for (unsigned int l = 0; l < 2; ++l)
+ {
+ tmp (2 * l + 1)
+ -= this->restriction[index][2 * i + l]
+ ((i + 2 * (j + 4))
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree + k,
+ quadrature_point_1, 2);
+ tmp (2 * (j + 2 * (l + 1)))
+ -= this->restriction[index][j + 2 * l]
+ ((i + 4 * j + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_2, 0);
+ tmp (2 * (j + 2 * l) + 5)
+ -= this->restriction[index][j + 2 * l]
+ ((2 * (i + 4) + l)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((2 * (i + 4) + l)
+ * this->degree,
+ quadrature_point_2, 2);
+ tmp (2 * (l + 6))
+ -= this->restriction[index][i + 2 * l]
+ ((4 * i + j + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((4 * i + j + 2)
+ * this->degree + k,
+ quadrature_point_3, 0);
+ }
+ }
+
+ tmp *= face_quadrature.weight (q_point);
+
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ const double L_j_0
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (0));
+ const double L_j_1
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double l_k_0
+ = L_j_0 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (1));
+ const double l_k_1
+ = L_j_1 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0; l < 8;
+ ++l)
+ {
+ system_rhs (j * deg + k,
+ 2 * l)
+ += tmp (2 * l) * l_k_0;
+ system_rhs (j * deg + k,
+ 2 * l + 1)
+ += tmp (2 * l + 1) * l_k_1;
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ for (unsigned int l = 0; l < deg; ++l)
+ {
+ if (std::abs (solution (k * deg + l,
+ 2 * j))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ ((2 * i * this->degree + k) * deg
+ + l
+ + n_edge_dofs,
+ dof) = solution (k * deg + l,
+ 2 * j);
+
+ if (std::abs (solution (k * deg + l,
+ 2 * j + 1))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ (((2 * i + 1) * deg + l)
+ * this->degree + k + n_edge_dofs,
+ dof) = solution (k * deg + l,
+ 2 * j + 1);
+
+ if (std::abs (solution (k * deg + l,
+ 2 * (j + 6)))
+ > 1e-14)
+ this->restriction[index][i + 2 * j]
+ ((2 * (i + 4) * this->degree + k)
+ * deg + l + n_edge_dofs, dof)
+ = solution (k * deg + l,
+ 2 * (j + 6));
+
+ if (std::abs (solution (k * deg + l,
+ 2 * j + 13))
+ > 1e-14)
+ this->restriction[index][i + 2 * j]
+ (((2 * i + 9) * deg + l)
+ * this->degree + k + n_edge_dofs,
+ dof) = solution (k * deg + l,
+ 2 * j + 13);
+
+ for (unsigned int m = 0; m < 2; ++m)
+ {
+ if (std::abs (solution
+ (k * deg + l,
+ 2 * (j + 2 * (m + 1))))
+ > 1e-14)
+ this->restriction[index][j + 2 * m]
+ ((2 * (i + 2) * this->degree
+ + k) * deg + l
+ + n_edge_dofs, dof)
+ = solution (k * deg + l,
+ 2 * (j + 2 * (m + 1)));
+
+ if (std::abs (solution
+ (k * deg + l,
+ 2 * (j + 2 * m) + 5))
+ > 1e-14)
+ this->restriction[index][j + 2 * m]
+ (((2 * i + 5) * deg + l)
+ * this->degree + k
+ + n_edge_dofs, dof)
+ = solution (k * deg + l,
+ 2 * (j + 2 * m) + 5);
+ }
+ }
+ }
+
+ const QGauss<dim> quadrature (2 * this->degree);
+ const std::vector<Point<dim> >&
+ quadrature_points = quadrature.get_points ();
+ const unsigned int n_boundary_dofs
+ = 2 * GeometryInfo<dim>::faces_per_cell * deg
+ * this->degree + n_edge_dofs;
+ const unsigned int&
+ n_quadrature_points = quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * deg * this->degree,
+ n_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ const double weight
+ = std::sqrt (quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i = weight
+ * legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j
+ = L_i * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ assembling_matrix ((i * deg + j)
+ * deg + k,
+ q_point)
+ = l_j * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ }
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 12);
+ system_rhs.reinit (system_matrix_inv.m (), 12);
+ tmp.reinit (12);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
for (unsigned int q_point = 0;
- q_point < n_edge_points; ++q_point)
+ q_point < n_quadrature_points; ++q_point)
{
- const double right_hand_side_value
- = std::sqrt (edge_quadrature.weight
- (q_point))
- * (this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- edge_quadrature_points_full_dim[line][q_point],
- 1)
- - interpolation_matrix
- (line * source_fe.degree, dof));
- const double tmp
- = 2.0 * edge_quadrature_points[q_point] (0);
-
- for (unsigned int i = 0; i < deg; ++i)
- system_rhs (i)
- += right_hand_side_value
- * lobatto_polynomials_grad[i + 1].value
- (tmp);
+ tmp = 0.0;
+
+ if (quadrature_points[q_point] (0) < 0.5)
+ {
+ if (quadrature_points[q_point] (2)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0),
+ quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2));
+
+ tmp (0) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (1)
+ += this->shape_value_component
+ (dof, quadrature_point, 1);
+ tmp (2) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0),
+ quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2)
+ - 1.0);
+
+ tmp (3) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (4)
+ += this->shape_value_component
+ (dof, quadrature_point, 1);
+ tmp (5) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 2);
+ }
+ }
+
+ else
+ if (quadrature_points[q_point] (2) < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2));
+
+ tmp (6) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (7)
+ += this->shape_value_component (dof,
+ quadrature_point,
+ 1);
+ tmp (8) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2)
+ - 1.0);
+
+ tmp (9) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (10)
+ += this->shape_value_component (dof,
+ quadrature_point,
+ 1);
+ tmp (11) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ {
+ for (unsigned int l = 0; l < 2; ++l)
+ {
+ tmp (3 * (i + 2 * j))
+ -= this->restriction[index][i + 2 * j]
+ ((l + 4 * i + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((l + 4 * i + 2)
+ * this->degree + k,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * (i + 2 * j) + 2)
+ -= this->restriction[index][i + 2 * j]
+ ((j + 2 * (l + 4))
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((j + 2 * (l + 4))
+ * this->degree + k,
+ quadrature_points[q_point],
+ 2);
+
+ for (unsigned int m = 0;
+ m < deg; ++m)
+ {
+ tmp (3 * (i + 2 * j))
+ -= this->restriction[index][i + 2 * j]
+ ((k + 2 * (l + 2)
+ * this->degree)
+ * deg + m
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ ((k + 2 * (l + 2)
+ * this->degree)
+ * deg + m
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * (i + 2 * j) + 2)
+ -= this->restriction[index][i + 2 * j]
+ (((2 * l + 5) * deg
+ + m)
+ * this->degree + k
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * l + 5) * deg + m)
+ * this->degree + k
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ }
+ }
+
+ for (unsigned int l = 0; l < deg;
+ ++l)
+ {
+ tmp (3 * (i + 2 * j))
+ -= this->restriction[index][i + 2 * j]
+ ((2 * (i + 4)
+ * this->degree + k)
+ * deg + l + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((2 * (i + 4) * this->degree
+ + k) * deg + l
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * (i + 2 * j) + 1)
+ -= this->restriction[index][i + 2 * j]
+ ((2 * j * this->degree + k)
+ * deg + l + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((2 * j * this->degree + k)
+ * deg + l + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * (i + 2 * j) + 1)
+ -= this->restriction[index][i + 2 * j]
+ (((2 * i + 9) * deg + l)
+ * this->degree + k
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * i + 9) * deg + l)
+ * this->degree + k
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * (i + 2 * j) + 2)
+ -= this->restriction[index][i + 2 * j]
+ (((2 * j + 1) * deg + l)
+ * this->degree + k
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * j + 1) * deg + l)
+ * this->degree + k
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ }
+
+ tmp (3 * (i + 2 * j) + 1)
+ -= this->restriction[index][i + 2 * j]
+ ((4 * i + j) * this->degree
+ + k, dof)
+ * this->shape_value_component
+ ((4 * i + j) * this->degree + k,
+ quadrature_points[q_point], 1);
+ }
+
+ tmp *= quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i_0
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+ const double L_i_1
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (1));
+ const double L_i_2
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (2));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j_0
+ = L_i_0 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ const double l_j_1
+ = L_i_1 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+ const double l_j_2
+ = L_i_2 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0; k < deg;
+ ++k)
+ {
+ const double l_k_0
+ = l_j_0 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_1
+ = l_j_1 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_2
+ = l_j_2 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int l = 0; l < 4;
+ ++l)
+ {
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l)
+ += tmp (3 * l) * l_k_0;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 1)
+ += tmp (3 * l + 1)
+ * l_k_1;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 2)
+ += tmp (3 * l + 2)
+ * l_k_2;
+ }
+ }
+ }
+ }
}
-
- system_matrix_inv.vmult (solution, system_rhs);
-
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i < deg; ++i)
- if (std::abs (solution (i)) > 1e-14)
- interpolation_matrix
- (line * source_fe.degree + i + 1, dof)
- = solution (i);
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ for (unsigned int l = 0; l < deg; ++l)
+ for (unsigned int m = 0; m < deg; ++m)
+ {
+ if (std::abs (solution
+ ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j)))
+ > 1e-14)
+ this->restriction[index][i + 2 * j]
+ ((k * deg + l) * deg + m
+ + n_boundary_dofs,
+ dof) = solution ((k * deg + l)
+ * deg + m,
+ 3 * (i + 2 * j));
+
+ if (std::abs (solution
+ ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j)
+ + 1)) > 1e-14)
+ this->restriction[index][i + 2 * j]
+ ((k + (l + deg) * this->degree)
+ * deg + m + n_boundary_dofs,
+ dof) = solution ((k * deg + l)
+ * deg + m,
+ 3 * (i + 2 * j)
+ + 1);
+
+ if (std::abs (solution
+ ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j) + 2))
+ > 1e-14)
+ this->restriction[index][i + 2 * j]
+ (k + ((l + 2 * deg) * deg + m)
+ * this->degree
+ + n_boundary_dofs, dof)
+ = solution ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j)
+ + 2);
+ }
}
+ }
+
+ break;
+ }
- assembling_matrix.reinit (deg * this->degree,
- n_face_points);
-
- for (unsigned int q_point = 0; q_point < n_face_points;
- ++q_point)
+ case RefinementCase<3>::cut_yz:
+ {
+ // First interpolate the shape
+ // functions of the child cells
+ // to the lowest order shape
+ // functions of the parent cell.
+ for (unsigned int dof = 0; dof < this->dofs_per_cell;
+ ++dof)
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
+ {
+ {
+ const double weight
+ = 2.0 * edge_quadrature.weight (q_point);
+
+ if (edge_quadrature_points[q_point] (0) < 0.5)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ Point<dim> quadrature_point (i,
+ 2.0 * edge_quadrature_points[q_point] (0),
+ j);
+
+ this->restriction[index][2 * j]
+ ((i + 4 * j) * this->degree, dof)
+ += weight
+ * this->shape_value_component (dof,
+ quadrature_point,
+ 1);
+ quadrature_point = Point<dim> (i, j,
+ 2.0 * edge_quadrature_points[q_point] (0));
+ this->restriction[index][j]
+ ((i + 2 * (j + 4)) * this->degree, dof)
+ += weight
+ * this->shape_value_component (dof,
+ quadrature_point,
+ 2);
+ }
+
+ else
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ Point<dim> quadrature_point (i,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0,
+ j);
+
+ this->restriction[index][2 * j + 1]
+ ((i + 4 * j) * this->degree, dof)
+ += weight
+ * this->shape_value_component (dof,
+ quadrature_point,
+ 1);
+ quadrature_point = Point<dim> (i, j,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0);
+ this->restriction[index][j + 2]
+ ((i + 2 * (j + 4)) * this->degree, dof)
+ += weight
+ * this->shape_value_component (dof,
+ quadrature_point,
+ 2);
+ }
+ }
+
+ const double weight
+ = edge_quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ const Point<dim>
+ quadrature_point
+ (edge_quadrature_points[q_point] (0), i,
+ j);
+
+ this->restriction[index][i + 2 * j]
+ ((i + 4 * j + 2) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ }
+ }
+
+ // Then project the shape functions
+ // of the child cells to the higher
+ // order shape functions of the
+ // parent cell.
+ if (deg > 0)
{
- const Point<dim - 1> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0),
- 2.0 * face_quadrature_points[q_point] (1));
- const double weight
- = std::sqrt (face_quadrature.weight (q_point));
-
- for (unsigned int i = 0; i <= deg; ++i)
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials
+ = Polynomials::Legendre::generate_complete_basis
+ (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
+ {
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (edge_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point) = weight
+ * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+ }
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ FullMatrix<double> solution (deg, 5);
+ FullMatrix<double> system_rhs (deg, 5);
+ Vector<double> tmp (5);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = edge_quadrature.weight (q_point);
+ const Point<dim> quadrature_point_0 (i,
+ edge_quadrature_points[q_point] (0),
+ j);
+ Point<dim> quadrature_point_1 (i, j,
+ edge_quadrature_points[q_point] (0));
+
+ if (edge_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ Point<dim> quadrature_point_2 (i,
+ 2.0 * edge_quadrature_points[q_point] (0),
+ j);
+
+ tmp (0) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 1)
+ - this->restriction[index][2 * j]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1));
+ tmp (1) = -1.0 * weight
+ * this->restriction[index][2 * j + 1]
+ ((i + 4 * j)
+ * this->degree, dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1);
+ quadrature_point_2 = Point<dim> (i,
+ j,
+ 2.0 * edge_quadrature_points[q_point] (0));
+ tmp (3) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 2)
+ - this->restriction[index][j]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_1,
+ 2));
+ tmp (4) = -1.0 * weight
+ * this->restriction[index][j + 2]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_1,
+ 2);
+ }
+
+ else
+ {
+ tmp (0) = -1.0 * weight
+ * this->restriction[index][2 * j]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1);
+
+ Point<dim> quadrature_point_2 (i,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0,
+ j);
+
+ tmp (1) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 1)
+ - this->restriction[index][2 * j + 1]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1));
+ tmp (3) = -1.0 * weight
+ * this->restriction[index][j]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_1,
+ 2);
+ quadrature_point_2 = Point<dim> (i,
+ j,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0);
+ tmp (4) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_2,
+ 2)
+ - this->restriction[index][j + 2]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_1,
+ 2));
+ }
+
+ quadrature_point_1
+ = Point<dim> (edge_quadrature_points[q_point] (0),
+ i, j);
+ tmp (2) = weight
+ * (this->shape_value_component
+ (dof, quadrature_point_1,
+ 0)
+ - this->restriction[index][i + 2 * j]
+ ((i + 4 * j + 2)
+ * this->degree, dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_1, 0));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double L_k
+ = legendre_polynomials[k + 1].value
+ (edge_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0;
+ l < tmp.size (); ++l)
+ system_rhs (k, l) += tmp (l)
+ * L_k;
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ for (unsigned int l = 0; l < 2; ++l)
+ {
+ if (std::abs (solution (k, l))
+ > 1e-14)
+ this->restriction[index][2 * j + l]
+ ((i + 4 * j) * this->degree + k
+ + 1, dof)
+ = solution (k, l);
+
+ if (std::abs (solution (k, l + 2))
+ > 1e-14)
+ this->restriction[index][j + 2 * l]
+ ((i + 2 * (j + 4)) * this->degree
+ + k + 1, dof)
+ = solution (k, l + 2);
+ }
+
+ if (std::abs (solution (k, 2)) > 1e-14)
+ this->restriction[index][i + 2 * j]
+ ((i + 4 * j + 2) * this->degree + k
+ + 1, dof)
+ = solution (k, 2);
+ }
+ }
+
+ const QGauss<2> face_quadrature (2 * this->degree);
+ const std::vector<Point<2> >&
+ face_quadrature_points
+ = face_quadrature.get_points ();
+ const std::vector<Polynomials::Polynomial<double> >&
+ lobatto_polynomials
+ = Polynomials::Lobatto::generate_complete_basis
+ (this->degree);
+ const unsigned int n_edge_dofs
+ = GeometryInfo<dim>::lines_per_cell
+ * this->degree;
+ const unsigned int& n_face_quadrature_points
+ = face_quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * this->degree,
+ n_face_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (face_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i = weight
+ * legendre_polynomials[i].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ assembling_matrix (i * deg + j, q_point)
+ = L_i * lobatto_polynomials[j + 2].value
+ (face_quadrature_points[q_point] (1));
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 16);
+ system_rhs.reinit (system_matrix_inv.m (), 16);
+ tmp.reinit (16);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ tmp = 0.0;
+
+ if (face_quadrature_points[q_point] (1)
+ < 0.5)
+ {
+ if (face_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1));
+
+ tmp (0) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 1);
+ tmp (1) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * face_quadrature_points[q_point] (1));
+
+ tmp (2) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 1);
+ tmp (3) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 2);
+ }
+
+ Point<dim>
+ quadrature_point_0
+ (face_quadrature_points[q_point] (0),
+ i,
+ 2.0 * face_quadrature_points[q_point] (1));
+
+ tmp (8) += this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (9) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1),
+ i);
+ tmp (12)
+ += this->shape_value_component (dof,
+ quadrature_point_0,
+ 0);
+ tmp (13) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ }
+
+ else
+ {
+ if (face_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0);
+
+ tmp (4) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 1);
+ tmp (5) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0);
+
+ tmp (6) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 1);
+ tmp (7) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 2);
+ }
+
+ Point<dim>
+ quadrature_point_0
+ (face_quadrature_points[q_point] (0),
+ i,
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0);
+
+ tmp (10)
+ += this->shape_value_component (dof,
+ quadrature_point_0,
+ 0);
+ tmp (11) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0,
+ i);
+ tmp (14)
+ += this->shape_value_component (dof,
+ quadrature_point_0,
+ 0);
+ tmp (15) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ }
+
+ const Point<dim> quadrature_point_1 (i,
+ face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_2
+ (face_quadrature_points[q_point] (0), i,
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_3
+ (face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1),
+ i);
+
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ {
+ for (unsigned int l = 0; l < 2; ++l)
+ {
+ tmp (2 * (2 * j + l))
+ -= this->restriction[index][2 * j + l]
+ ((i + 4 * j) * this->degree
+ + k, dof)
+ * this->shape_value_component
+ ((i + 4 * j) * this->degree
+ + k,
+ quadrature_point_1, 1);
+ tmp (2 * (2 * j + l) + 1)
+ -= this->restriction[index][2 * j + l]
+ ((i + 2 * (l + 4))
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 2 * (l + 4))
+ * this->degree + k,
+ quadrature_point_1, 1);
+ tmp (2 * l + 9)
+ -= this->restriction[index][i + 2 * l]
+ ((2 * (i + 4) + j)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((2 * (i + 4) + j)
+ * this->degree + k,
+ quadrature_point_2, 2);
+ tmp (2 * l + 13)
+ -= this->restriction[index][2 * i + l]
+ ((4 * i + j)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((4 * i + j) * this->degree
+ + k,
+ quadrature_point_3, 1);
+ }
+
+ tmp (2 * (j + 4))
+ -= this->restriction[index][i + 2 * j]
+ ((i + 4 * j + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2) * this->degree
+ + k,
+ quadrature_point_2, 0);
+ tmp (2 * (j + 6))
+ -= this->restriction[index][2 * i + j]
+ ((4 * i + j + 2) * this->degree
+ + k, dof)
+ * this->shape_value_component
+ ((4 * i + j + 2) * this->degree
+ + k,
+ quadrature_point_3, 0);
+ }
+
+ tmp *= face_quadrature.weight (q_point);
+
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ const double L_j_0
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (0));
+ const double L_j_1
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg;
+ ++k)
+ {
+ const double l_k_0
+ = L_j_0 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (1));
+ const double l_k_1
+ = L_j_1 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0; l < 8;
+ ++l)
+ {
+ system_rhs (j * deg + k,
+ 2 * l)
+ += tmp (2 * l) * l_k_0;
+ system_rhs (j * deg + k,
+ 2 * l + 1)
+ += tmp (2 * l + 1) * l_k_1;
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ for (unsigned int l = 0; l < deg; ++l)
+ {
+ for (unsigned int m = 0; m < 2; ++m)
+ {
+ if (std::abs (solution
+ (k * deg + l,
+ 2 * (2 * j + m)))
+ > 1e-14)
+ this->restriction[index][2 * j + m]
+ ((2 * i * this->degree + k)
+ * deg + l + n_edge_dofs, dof)
+ = solution (k * deg + l,
+ 2 * (2 * j + m));
+
+ if (std::abs (solution
+ (k * deg + l,
+ 2 * (2 * j + m) + 1))
+ > 1e-14)
+ this->restriction[index][2 * j + m]
+ (((2 * i + 1) * deg + l)
+ * this->degree + k
+ + n_edge_dofs, dof)
+ = solution (k * deg + l,
+ 2 * (2 * j + m) + 1);
+ }
+
+ if (std::abs (solution (k * deg + l,
+ 2 * (j + 4)))
+ > 1e-14)
+ this->restriction[index][i + 2 * j]
+ ((2 * (i + 2) * this->degree + k)
+ * deg + l + n_edge_dofs, dof)
+ = solution (k * deg + l,
+ 2 * (j + 4));
+
+ if (std::abs (solution (k * deg + l,
+ 2 * j + 9))
+ > 1e-14)
+ this->restriction[index][i + 2 * j]
+ (((2 * i + 5) * deg + l)
+ * this->degree + k + n_edge_dofs,
+ dof) = solution (k * deg + l,
+ 2 * j + 9);
+
+ if (std::abs (solution (k * deg + l,
+ 2 * (j + 6)))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ ((2 * (i + 4) * this->degree + k)
+ * deg + l + n_edge_dofs, dof)
+ = solution (k * deg + l,
+ 2 * (j + 6));
+
+ if (std::abs (solution (k * deg + l,
+ 2 * j + 13))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ (((2 * i + 9) * deg + l)
+ * this->degree + k + n_edge_dofs,
+ dof) = solution (k * deg + l,
+ 2 * j + 13);
+ }
+ }
+
+ const QGauss<dim> quadrature (2 * this->degree);
+ const std::vector<Point<dim> >&
+ quadrature_points = quadrature.get_points ();
+ const unsigned int n_boundary_dofs
+ = 2 * GeometryInfo<dim>::faces_per_cell * deg
+ * this->degree + n_edge_dofs;
+ const unsigned int&
+ n_quadrature_points = quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * deg * this->degree,
+ n_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ const double weight
+ = std::sqrt (quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i = weight
+ * legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j
+ = L_i * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ assembling_matrix ((i * deg + j)
+ * deg + k,
+ q_point)
+ = l_j * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ }
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 12);
+ system_rhs.reinit (system_matrix_inv.m (), 12);
+ tmp.reinit (12);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
{
- const double tmp
- = weight * legendre_polynomials[i].value
- (quadrature_point (0));
-
- for (unsigned int j = 0; j < deg; ++j)
- assembling_matrix (i * deg + j, q_point)
- = tmp * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ tmp = 0.0;
+
+ if (quadrature_points[q_point] (1) < 0.5)
+ {
+ if (quadrature_points[q_point] (2)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2));
+
+ tmp (0)
+ += this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (1) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 1);
+ tmp (2) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2)
+ - 1.0);
+
+ tmp (3)
+ += this->shape_value_component
+ (dof, quadrature_point, 0);
+ tmp (4) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 1);
+ tmp (5) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 2);
+ }
+ }
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ {
+ tmp (3 * (i + 2 * j))
+ -= this->restriction[index][2 * i + j]
+ ((4 * i + j + 2)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((4 * i + j + 2) * this->degree
+ + k,
+ quadrature_points[q_point], 0);
+
+ for (unsigned int l = 0; l < deg;
+ ++l)
+ {
+ tmp (3 * (i + 2 * j))
+ -= this->restriction[index][2 * i + j]
+ ((2 * (j + 2)
+ * this->degree + k)
+ * deg + l + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((2 * (j + 2)
+ * this->degree + k)
+ * deg + l + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * (i + 2 * j))
+ -= this->restriction[index][2 * i + j]
+ ((2 * (i + 4)
+ * this->degree + k)
+ * deg + l + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((2 * (i + 4) * this->degree
+ + k) * deg + l
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * (i + 2 * j) + 1)
+ -= this->restriction[index][2 * i + j]
+ (((2 * i + 9) * deg + l)
+ * this->degree + k
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * i + 9) * deg + l)
+ * this->degree + k
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * (i + 2 * j) + 2)
+ -= this->restriction[index][2 * i + j]
+ (((2 * j + 5) * deg + l)
+ * this->degree + k
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * j + 5) * deg + l)
+ * this->degree + k
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ }
+
+ for (unsigned int l = 0; l < 2; ++l)
+ {
+ tmp (3 * (i + 2 * j) + 1)
+ -= this->restriction[index][2 * i + j]
+ ((4 * i + l) * this->degree
+ + k, dof)
+ * this->shape_value_component
+ ((4 * i + l) * this->degree
+ + k,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * (i + 2 * j) + 2)
+ -= this->restriction[index][2 * i + j]
+ ((2 * (j + 4) + l)
+ * this->degree + k, dof)
+ * this->shape_value_component
+ ((2 * (j + 4) + l)
+ * this->degree + k,
+ quadrature_points[q_point],
+ 2);
+
+ for (unsigned int m = 0;
+ m < deg; ++m)
+ {
+ tmp (3 * (i + 2 * j) + 1)
+ -= this->restriction[index][2 * i + j]
+ ((2 * l * this->degree
+ + k) * deg + m
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ ((2 * l * this->degree
+ + k) * deg + m
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * (i + 2 * j) + 2)
+ -= this->restriction[index][2 * i + j]
+ (((2 * l + 1) * deg
+ + m)
+ * this->degree + k
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * l + 1) * deg + m)
+ * this->degree + k
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ }
+ }
+ }
+
+ tmp *= quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i_0
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+ const double L_i_1
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (1));
+ const double L_i_2
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (2));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j_0
+ = L_i_0 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ const double l_j_1
+ = L_i_1 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+ const double l_j_2
+ = L_i_2 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0; k < deg;
+ ++k)
+ {
+ const double l_k_0
+ = l_j_0 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_1
+ = l_j_1 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_2
+ = l_j_2 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int l = 0; l < 4;
+ ++l)
+ {
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l)
+ += tmp (3 * l) * l_k_0;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 1)
+ += tmp (3 * l + 1)
+ * l_k_1;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 2)
+ += tmp (3 * l + 2)
+ * l_k_2;
+ }
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k <= deg; ++k)
+ for (unsigned int l = 0; l < deg; ++l)
+ for (unsigned int m = 0; m < deg; ++m)
+ {
+ if (std::abs (solution
+ ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j)))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ ((k * deg + l) * deg + m
+ + n_boundary_dofs,
+ dof)
+ = solution ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j));
+
+ if (std::abs (solution
+ ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j) + 1))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ ((k + (l + deg) * this->degree)
+ * deg + m + n_boundary_dofs, dof)
+ = solution ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j)
+ + 1);
+
+ if (std::abs (solution
+ ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j) + 2))
+ > 1e-14)
+ this->restriction[index][2 * i + j]
+ (k + ((l + 2 * deg) * deg + m)
+ * this->degree
+ + n_boundary_dofs, dof)
+ = solution ((k * deg + l) * deg
+ + m,
+ 3 * (i + 2 * j)
+ + 2);
+ }
}
}
+
+ break;
+ }
- system_matrix.reinit (assembling_matrix.m (),
- assembling_matrix.m ());
- assembling_matrix.mTmult (system_matrix,
- assembling_matrix);
- system_matrix_inv.reinit (system_matrix.m (),
- system_matrix.m ());
- system_matrix_inv.invert (system_matrix);
- solution.reinit (system_matrix_inv.m ());
- system_rhs.reinit (system_matrix_inv.m ());
-
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
+ case RefinementCase<3>::isotropic_refinement:
+ {
+ // First interpolate the shape
+ // functions of the child cells
+ // to the lowest order shape
+ // functions of the parent cell.
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
+ {
+ const double weight
+ = 2.0 * edge_quadrature.weight (q_point);
+
+ if (edge_quadrature_points[q_point] (0) < 0.5)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ Point<dim> quadrature_point (i,
+ 2.0 * edge_quadrature_points[q_point] (0),
+ j);
+
+ this->restriction[index][i + 4 * j]
+ ((i + 4 * j) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 1);
+ quadrature_point
+ = Point<dim> (2.0 * edge_quadrature_points[q_point] (0),
+ i, j);
+ this->restriction[index][2 * (i + 2 * j)]
+ ((i + 4 * j + 2) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ quadrature_point = Point<dim> (i, j,
+ 2.0 * edge_quadrature_points[q_point] (0));
+ this->restriction[index][i + 2 * j]
+ ((i + 2 * (j + 4)) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+
+ else
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ Point<dim> quadrature_point (i,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0,
+ j);
+
+ this->restriction[index][i + 4 * j + 2]
+ ((i + 4 * j) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 1);
+ quadrature_point
+ = Point<dim> (2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0, i, j);
+ this->restriction[index][2 * (i + 2 * j) + 1]
+ ((i + 4 * j + 2) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 0);
+ quadrature_point = Point<dim> (i, j,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0);
+ this->restriction[index][i + 2 * (j + 2)]
+ ((i + 2 * (j + 4)) * this->degree, dof)
+ += weight * this->shape_value_component
+ (dof, quadrature_point, 2);
+ }
+ }
+
+ // Then project the shape functions
+ // of the child cells to the higher
+ // order shape functions of the
+ // parent cell.
+ if (deg > 0)
{
- system_rhs = 0;
-
- // Now we project the remaining
- // part on the face shape
- // functions. First on the
- // horizontal ones, then on
- // the vertical ones.
- for (unsigned int q_point = 0;
- q_point < n_face_points; ++q_point)
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials
+ = Polynomials::Legendre::generate_complete_basis
+ (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
+ {
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (edge_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point) = weight
+ * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+ }
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ FullMatrix<double> solution (deg, 6);
+ FullMatrix<double> system_rhs (deg, 6);
+ Vector<double> tmp (6);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = edge_quadrature.weight (q_point);
+ const Point<dim> quadrature_point_0 (i,
+ edge_quadrature_points[q_point] (0),
+ j);
+ const Point<dim>
+ quadrature_point_1
+ (edge_quadrature_points[q_point] (0),
+ i, j);
+ const Point<dim> quadrature_point_2 (i,
+ j,
+ edge_quadrature_points[q_point] (0));
+
+ if (edge_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ Point<dim> quadrature_point_3 (i,
+ 2.0 * edge_quadrature_points[q_point] (0),
+ j);
+
+ tmp (0) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_3,
+ 1)
+ - this->restriction[index][i + 4 * j]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1));
+ tmp (1) = -1.0 * weight
+ * this->restriction[index][i + 4 * j + 2]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1);
+ quadrature_point_3
+ = Point<dim> (2.0 * edge_quadrature_points[q_point] (0),
+ i, j);
+ tmp (2) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_3,
+ 0)
+ - this->restriction[index][2 * (i + 2 * j)]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_1,
+ 0));
+ tmp (3) = -1.0 * weight
+ * this->restriction[index][2 * (i + 2 * j) + 1]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_1,
+ 0);
+ quadrature_point_3 = Point<dim> (i,
+ j,
+ 2.0 * edge_quadrature_points[q_point] (0));
+ tmp (4) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_3,
+ 2)
+ - this->restriction[index][i + 2 * j]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_2,
+ 2));
+ tmp (5) = -1.0 * weight
+ * this->restriction[index][i + 2 * (j + 2)]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_2,
+ 2);
+ }
+
+ else
+ {
+ tmp (0) = -1.0 * weight
+ * this->restriction[index][i + 4 * j]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1);
+
+ Point<dim> quadrature_point_3 (i,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0,
+ j);
+
+ tmp (1) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_3,
+ 1)
+ - this->restriction[index][i + 4 * j + 2]
+ ((i + 4 * j)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j)
+ * this->degree,
+ quadrature_point_0,
+ 1));
+ tmp (2) = -1.0 * weight
+ * this->restriction[index][2 * (i + 2 * j)]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_1,
+ 0);
+ quadrature_point_3
+ = Point<dim> (2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0, i, j);
+ tmp (3) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_3,
+ 0)
+ - this->restriction[index][2 * (i + 2 * j) + 1]
+ ((i + 4 * j + 2)
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree,
+ quadrature_point_1,
+ 0));
+ tmp (4) = -1.0 * weight
+ * this->restriction[index][i + 2 * j]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_2,
+ 2);
+ quadrature_point_3 = Point<dim> (i,
+ j,
+ 2.0 * edge_quadrature_points[q_point] (0)
+ - 1.0);
+ tmp (5) = weight
+ * (2.0 * this->shape_value_component
+ (dof,
+ quadrature_point_3,
+ 2)
+ - this->restriction[index][i + 2 * (j + 2)]
+ ((i + 2 * (j + 4))
+ * this->degree,
+ dof)
+ * this->shape_value_component
+ ((i + 2 * (j + 4))
+ * this->degree,
+ quadrature_point_2,
+ 2));
+ }
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double L_k
+ = legendre_polynomials[k + 1].value
+ (edge_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0;
+ l < tmp.size (); ++l)
+ system_rhs (k, l) += tmp (l)
+ * L_k;
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int k = 0; k < 2; ++k)
+ for (unsigned int l = 0; l < deg; ++l)
+ {
+ if (std::abs (solution (l, k))
+ > 1e-14)
+ this->restriction[index][i + 2 * (2 * j + k)]
+ ((i + 4 * j) * this->degree + l + 1,
+ dof) = solution (l, k);
+
+ if (std::abs (solution (l, k + 2))
+ > 1e-14)
+ this->restriction[index][2 * (i + 2 * j) + k]
+ ((i + 4 * j + 2) * this->degree + l
+ + 1, dof)
+ = solution (l, k + 2);
+
+ if (std::abs (solution (l, k + 4))
+ > 1e-14)
+ this->restriction[index][i + 2 * (j + 2 * k)]
+ ((i + 2 * (j + 4)) * this->degree
+ + l + 1, dof)
+ = solution (l, k + 4);
+ }
+ }
+
+ const QGauss<2> face_quadrature (2 * this->degree);
+ const std::vector<Point<2> >& face_quadrature_points
+ = face_quadrature.get_points ();
+ const std::vector<Polynomials::Polynomial<double> >&
+ lobatto_polynomials
+ = Polynomials::Lobatto::generate_complete_basis
+ (this->degree);
+ const unsigned int n_edge_dofs
+ = GeometryInfo<dim>::lines_per_cell
+ * this->degree;
+ const unsigned int& n_face_quadrature_points
+ = face_quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * this->degree,
+ n_face_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ const double weight
+ = std::sqrt (face_quadrature.weight
+ (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i = weight
+ * legendre_polynomials[i].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ assembling_matrix (i * deg + j, q_point)
+ = L_i * lobatto_polynomials[j + 2].value
+ (face_quadrature_points[q_point] (1));
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 24);
+ system_rhs.reinit (system_matrix_inv.m (), 24);
+ tmp.reinit (24);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_face_quadrature_points;
+ ++q_point)
+ {
+ tmp = 0.0;
+
+ if (face_quadrature_points[q_point] (0)
+ < 0.5)
+ {
+ if (face_quadrature_points[q_point] (1)
+ < 0.5)
+ {
+ Point<dim> quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1));
+
+ tmp (0) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 1);
+ tmp (1) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0),
+ i,
+ 2.0 * face_quadrature_points[q_point] (1));
+ tmp (8) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 0);
+ tmp (9) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1),
+ i);
+ tmp (16) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 0);
+ tmp (17) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 1);
+ }
+
+ else
+ {
+ Point<dim> quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0);
+
+ tmp (2) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 1);
+ tmp (3) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0, 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0),
+ i,
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0);
+ tmp (10) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 0);
+ tmp (11) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0),
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0, i);
+ tmp (18) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 0);
+ tmp (19) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 1);
+ }
+ }
+
+ else
+ if (face_quadrature_points[q_point] (1)
+ < 0.5)
+ {
+ Point<dim> quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * face_quadrature_points[q_point] (1));
+
+ tmp (4) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ tmp (5) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0, i,
+ 2.0 * face_quadrature_points[q_point] (1));
+ tmp (12) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 0);
+ tmp (13) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * face_quadrature_points[q_point] (1),
+ i);
+ tmp (20) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 0);
+ tmp (21) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point_0,
+ 1);
+ }
+
+ else
+ {
+ Point<dim> quadrature_point_0 (i,
+ 2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0);
+
+ tmp (6) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ tmp (7) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0, i,
+ 2.0 * face_quadrature_points[q_point] (1) - 1.0);
+ tmp (14) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (15) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 2);
+ quadrature_point_0
+ = Point<dim> (2.0 * face_quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * face_quadrature_points[q_point] (1)
+ - 1.0, i);
+ tmp (22) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 0);
+ tmp (23) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point_0,
+ 1);
+ }
+
+ const Point<dim> quadrature_point_0 (i,
+ face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_1
+ (face_quadrature_points[q_point] (0), i,
+ face_quadrature_points[q_point] (1));
+ const Point<dim>
+ quadrature_point_2
+ (face_quadrature_points[q_point] (0),
+ face_quadrature_points[q_point] (1),
+ i);
+
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k < 2; ++k)
+ for (unsigned int l = 0; l <= deg;
+ ++l)
+ {
+ tmp (2 * (j + 2 * k))
+ -= this->restriction[index][i + 2 * (2 * j + k)]
+ ((i + 4 * j) * this->degree
+ + l, dof)
+ * this->shape_value_component
+ ((i + 4 * j) * this->degree
+ + l,
+ quadrature_point_0, 1);
+ tmp (2 * (j + 2 * k) + 1)
+ -= this->restriction[index][i + 2 * (2 * j + k)]
+ ((i + 2 * (k + 4))
+ * this->degree + l, dof)
+ * this->shape_value_component
+ ((i + 2 * (k + 4))
+ * this->degree + l,
+ quadrature_point_0, 2);
+ tmp (2 * (j + 2 * (k + 2)))
+ -= this->restriction[index][2 * (i + 2 * j) + k]
+ ((i + 4 * j + 2)
+ * this->degree + l, dof)
+ * this->shape_value_component
+ ((i + 4 * j + 2)
+ * this->degree + l,
+ quadrature_point_1, 0);
+ tmp (2 * (j + 2 * k) + 9)
+ -= this->restriction[index][2 * (i + 2 * j) + k]
+ ((2 * (i + 4) + k)
+ * this->degree + l, dof)
+ * this->shape_value_component
+ ((2 * (i + 4) + k)
+ * this->degree + l,
+ quadrature_point_1, 2);
+ tmp (2 * (j + 2 * (k + 4)))
+ -= this->restriction[index][2 * (2 * i + j) + k]
+ ((4 * i + j + 2)
+ * this->degree + l, dof)
+ * this->shape_value_component
+ ((4 * i + j + 2)
+ * this->degree + l,
+ quadrature_point_2, 0);
+ tmp (2 * (j + 2 * k) + 17)
+ -= this->restriction[index][2 * (2 * i + j) + k]
+ ((4 * i + k) * this->degree
+ + l, dof)
+ * this->shape_value_component
+ ((4 * i + k) * this->degree
+ + l,
+ quadrature_point_2, 1);
+ }
+
+ tmp *= face_quadrature.weight (q_point);
+
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ const double L_j_0
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (0));
+ const double L_j_1
+ = legendre_polynomials[j].value
+ (face_quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ {
+ const double l_k_0
+ = L_j_0 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (1));
+ const double l_k_1
+ = L_j_1 * lobatto_polynomials[k + 2].value
+ (face_quadrature_points[q_point] (0));
+
+ for (unsigned int l = 0; l < 12;
+ ++l)
+ {
+ system_rhs (j * deg + k,
+ 2 * l)
+ += tmp (2 * l) * l_k_0;
+ system_rhs (j * deg + k,
+ 2 * l + 1)
+ += tmp (2 * l + 1) * l_k_1;
+ }
+ }
+ }
+ }
+
+ system_matrix_inv.mmult (solution,
+ system_rhs);
+
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k < 2; ++k)
+ for (unsigned int l = 0; l <= deg; ++l)
+ for (unsigned int m = 0; m < deg; ++m)
+ {
+ if (std::abs (solution (l * deg + m,
+ 2 * (j + 2 * k)))
+ > 1e-14)
+ this->restriction[index][i + 2 * (2 * j + k)]
+ ((2 * i * this->degree + l) * deg
+ + m
+ + n_edge_dofs,
+ dof) = solution (l * deg + m,
+ 2 * (j + 2 * k));
+
+ if (std::abs (solution (l * deg + m,
+ 2 * (j + 2 * k) + 1))
+ > 1e-14)
+ this->restriction[index][i + 2 * (2 * j + k)]
+ (((2 * i + 1) * deg + m)
+ * this->degree + l + n_edge_dofs,
+ dof) = solution (l * deg + m,
+ 2 * (j + 2 * k) + 1);
+
+ if (std::abs (solution (l * deg + m,
+ 2 * (j + 2 * (k + 2))))
+ > 1e-14)
+ this->restriction[index][2 * (i + 2 * j) + k]
+ ((2 * (i + 2) * this->degree + l)
+ * deg + m + n_edge_dofs, dof)
+ = solution (l * deg + m,
+ 2 * (j + 2 * (k + 2)));
+
+ if (std::abs (solution (l * deg + m,
+ 2 * (j + 2 * k) + 9))
+ > 1e-14)
+ this->restriction[index][2 * (i + 2 * j) + k]
+ (((2 * i + 5) * deg + m)
+ * this->degree + l + n_edge_dofs,
+ dof) = solution (l * deg + m,
+ 2 * (j + 2 * k) + 9);
+
+ if (std::abs (solution (l * deg + m,
+ 2 * (j + 2 * (k + 4))))
+ > 1e-14)
+ this->restriction[index][2 * (2 * i + j) + k]
+ ((2 * (i + 4) * this->degree + l)
+ * deg + m + n_edge_dofs, dof)
+ = solution (l * deg + m,
+ 2 * (j + 2 * (k + 4)));
+
+ if (std::abs (solution (l * deg + m,
+ 2 * (j + 2 * k) + 17))
+ > 1e-14)
+ this->restriction[index][2 * (2 * i + j) + k]
+ (((2 * i + 9) * deg + m)
+ * this->degree + l + n_edge_dofs,
+ dof) = solution (l * deg + m,
+ 2 * (j + 2 * k) + 17);
+ }
+ }
+
+ const QGauss<dim> quadrature (2 * this->degree);
+ const std::vector<Point<dim> >&
+ quadrature_points = quadrature.get_points ();
+ const unsigned int n_boundary_dofs
+ = 2 * GeometryInfo<dim>::faces_per_cell * deg
+ * this->degree + n_edge_dofs;
+ const unsigned int&
+ n_quadrature_points = quadrature.size ();
+
+ {
+ FullMatrix<double>
+ assembling_matrix (deg * deg * this->degree,
+ n_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ const double weight
+ = std::sqrt (quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i = weight
+ * legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j
+ = L_i * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int k = 0; k < deg; ++k)
+ assembling_matrix ((i * deg + j)
+ * deg + k,
+ q_point)
+ = l_j * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ }
+ }
+ }
+
+ FullMatrix<double>
+ system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix,
+ assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 24);
+ system_rhs.reinit (system_matrix_inv.m (), 24);
+ tmp.reinit (24);
+
+ for (unsigned int dof = 0;
+ dof < this->dofs_per_cell; ++dof)
{
- const Point<dim> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0),
- 2.0 * face_quadrature_points[q_point] (1),
- 0.0);
- double right_hand_side_value
- = this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (face_quadrature_points[q_point] (0),
- face_quadrature_points[q_point] (1), 0.0),
- 1);
-
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int j = 0; j < source_fe.degree;
- ++j)
- right_hand_side_value
- -= interpolation_matrix
- (i * source_fe.degree + j, dof)
- * source_fe.shape_value_component
- (i * source_fe.degree + j,
- quadrature_point, 1);
-
- right_hand_side_value
- *= face_quadrature.weight (q_point);
-
- for (unsigned int i = 0; i <= deg; ++i)
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
{
- const double tmp
- = right_hand_side_value
- * legendre_polynomials[i].value
- (quadrature_point (0));
-
- for (unsigned int j = 0; j < deg; ++j)
- system_rhs (i * deg + j)
- += tmp
- * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
+ tmp = 0.0;
+
+ if (quadrature_points[q_point] (0) < 0.5)
+ {
+ if (quadrature_points[q_point] (1)
+ < 0.5)
+ {
+ if (quadrature_points[q_point] (2)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2));
+
+ tmp (0) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point, 0);
+ tmp (1) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point, 1);
+ tmp (2) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point, 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2)
+ - 1.0);
+
+ tmp (3) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point, 0);
+ tmp (4) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point, 1);
+ tmp (5) += 2.0
+ * this->shape_value_component
+ (dof,
+ quadrature_point, 2);
+ }
+ }
+
+ else
+ if (quadrature_points[q_point] (2)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (2));
+
+ tmp (6) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (7) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 1);
+ tmp (8) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0),
+ 2.0 * quadrature_points[q_point] (1)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (2)
+ - 1.0);
+
+ tmp (9) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (10) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 1);
+ tmp (11) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 2);
+ }
+ }
+
+ else
+ if (quadrature_points[q_point] (1) < 0.5)
+ {
+ if (quadrature_points[q_point] (2)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2));
+
+ tmp (12) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (13) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 1);
+ tmp (14) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (1),
+ 2.0 * quadrature_points[q_point] (2)
+ - 1.0);
+
+ tmp (15) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (16) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 1);
+ tmp (17) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 2);
+ }
+ }
+
+ else
+ if (quadrature_points[q_point] (2)
+ < 0.5)
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (1)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (2));
+
+ tmp (18) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (19) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 1);
+ tmp (20) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 2);
+ }
+
+ else
+ {
+ const Point<dim>
+ quadrature_point
+ (2.0 * quadrature_points[q_point] (0)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (1)
+ - 1.0,
+ 2.0 * quadrature_points[q_point] (2)
+ - 1.0);
+
+ tmp (21) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 0);
+ tmp (22) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 1);
+ tmp (23) += 2.0
+ * this->shape_value_component
+ (dof, quadrature_point,
+ 2);
+ }
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k < 2; ++k)
+ for (unsigned int l = 0; l <= deg;
+ ++l)
+ {
+ tmp (3 * (i + 2 * (j + 2 * k)))
+ -= this->restriction[index][2 * (2 * i + j) + k]
+ ((4 * i + j + 2)
+ * this->degree + l, dof)
+ * this->shape_value_component
+ ((4 * i + j + 2)
+ * this->degree + l,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * (i + 2 * (j + 2 * k))
+ + 1)
+ -= this->restriction[index][2 * (2 * i + j) + k]
+ ((4 * i + k) * this->degree
+ + l, dof)
+ * this->shape_value_component
+ ((4 * i + k) * this->degree
+ + l,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * (i + 2 * (j + 2 * k))
+ + 2)
+ -= this->restriction[index][2 * (2 * i + j) + k]
+ ((2 * (j + 4) + k)
+ * this->degree + l, dof)
+ * this->shape_value_component
+ ((2 * (j + 4) + k)
+ * this->degree + l,
+ quadrature_points[q_point],
+ 2);
+
+ for (unsigned int m = 0; m < deg;
+ ++m)
+ {
+ tmp (3 * (i + 2 * (j + 2 * k)))
+ -= this->restriction[index][2 * (2 * i + j) + k]
+ ((2 * (j + 2)
+ * this->degree + l)
+ * deg + m + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((2 * (j + 2)
+ * this->degree + l)
+ * deg + m + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * (i + 2 * (j + 2 * k)))
+ -= this->restriction[index][2 * (2 * i + j) + k]
+ ((2 * (i + 4)
+ * this->degree + l)
+ * deg + m + n_edge_dofs,
+ dof)
+ * this->shape_value_component
+ ((2 * (i + 4)
+ * this->degree + l)
+ * deg + m + n_edge_dofs,
+ quadrature_points[q_point],
+ 0);
+ tmp (3 * (i + 2 * (j + 2 * k))
+ + 1)
+ -= this->restriction[index][2 * (2 * i + j) + k]
+ ((2 * k * this->degree
+ + l) * deg + m
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ ((2 * k * this->degree
+ + l) * deg + m
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * (i + 2 * (j + 2 * k))
+ + 1)
+ -= this->restriction[index][2 * (2 * i + j) + k]
+ (((2 * i + 9) * deg + m)
+ * this->degree + l
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * i + 9) * deg + m)
+ * this->degree + l
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 1);
+ tmp (3 * (i + 2 * (j + 2 * k))
+ + 2)
+ -= this->restriction[index][2 * (2 * i + j) + k]
+ (((2 * k + 1) * deg + m)
+ * this->degree + l
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * k + 1) * deg + m)
+ * this->degree + l
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ tmp (3 * (i + 2 * (j + 2 * k))
+ + 2)
+ -= this->restriction[index][2 * (2 * i + j) + k]
+ (((2 * j + 5) * deg + m)
+ * this->degree + l
+ + n_edge_dofs, dof)
+ * this->shape_value_component
+ (((2 * j + 5) * deg + m)
+ * this->degree + l
+ + n_edge_dofs,
+ quadrature_points[q_point],
+ 2);
+ }
+ }
+
+ tmp *= quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i_0
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+ const double L_i_1
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (1));
+ const double L_i_2
+ = legendre_polynomials[i].value
+ (quadrature_points[q_point] (2));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ const double l_j_0
+ = L_i_0 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ const double l_j_1
+ = L_i_1 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+ const double l_j_2
+ = L_i_2 * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int k = 0; k < deg;
+ ++k)
+ {
+ const double l_k_0
+ = l_j_0 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_1
+ = l_j_1 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (2));
+ const double l_k_2
+ = l_j_2 * lobatto_polynomials[k + 2].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int l = 0; l < 8;
+ ++l)
+ {
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l)
+ += tmp (3 * l) * l_k_0;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 1)
+ += tmp (3 * l + 1)
+ * l_k_1;
+ system_rhs ((i * deg + j)
+ * deg + k,
+ 3 * l + 2)
+ += tmp (3 * l + 2)
+ * l_k_2;
+ }
+ }
+ }
+ }
}
- }
-
- system_matrix_inv.vmult (solution, system_rhs);
-
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < deg; ++j)
- if (std::abs (solution (i * deg + j)) > 1e-14)
- interpolation_matrix
- ((i + 4) * source_fe.degree + j - i, dof)
- = solution (i * deg + j);
-
- // Set up the right hand side
- // for the vertical shape
- // functions.
- system_rhs = 0;
-
- for (unsigned int q_point = 0;
- q_point < n_face_points; ++q_point)
- {
- const Point<dim> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0),
- 2.0 * face_quadrature_points[q_point] (1),
- 0.0);
- double right_hand_side_value
- = this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (face_quadrature_points[q_point] (0),
- face_quadrature_points[q_point] (1), 0.0),
- 0);
-
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int j = 0; j < source_fe.degree;
- ++j)
- right_hand_side_value
- -= interpolation_matrix
- ((i + 2) * source_fe.degree + j, dof)
- * source_fe.shape_value_component
- (i * source_fe.degree + j,
- quadrature_point, 0);
+ for (unsigned int j = 0; j < 2; ++j)
+ for (unsigned int k = 0; k < 2; ++k)
+ for (unsigned int l = 0; l <= deg; ++l)
+ for (unsigned int m = 0; m < deg; ++m)
+ for (unsigned int n = 0; n < deg; ++n)
+ {
+ if (std::abs (solution
+ ((l * deg + m) * deg
+ + n,
+ 3 * (i + 2 * (j + 2 * k))))
+ > 1e-14)
+ this->restriction[index][2 * (2 * i + j) + k]
+ ((l * deg + m) * deg + n
+ + n_boundary_dofs,
+ dof) = solution ((l * deg + m)
+ * deg + n,
+ 3 * (i + 2 * (j + 2 * k)));
+
+ if (std::abs (solution
+ ((l * deg + m) * deg
+ + n,
+ 3 * (i + 2 * (j + 2 * k))
+ + 1)) > 1e-14)
+ this->restriction[index][2 * (2 * i + j) + k]
+ ((l + (m + deg) * this->degree)
+ * deg + n + n_boundary_dofs,
+ dof) = solution ((l * deg + m)
+ * deg + n,
+ 3 * (i + 2 * (j + 2 * k))
+ + 1);
+
+ if (std::abs (solution
+ ((l * deg + m) * deg
+ + n,
+ 3 * (i + 2 * (j + 2 * k))
+ + 2)) > 1e-14)
+ this->restriction[index][2 * (2 * i + j) + k]
+ (l + ((m + 2 * deg) * deg + n)
+ * this->degree
+ + n_boundary_dofs, dof)
+ = solution ((l * deg + m)
+ * deg + n,
+ 3 * (i + 2 * (j + 2 * k))
+ + 2);
+ }
+ }
+ }
+
+ break;
+ }
- right_hand_side_value
- *= face_quadrature.weight (q_point);
+ default:
+ Assert (false, ExcNotImplemented ());
+ }
+ }
- for (unsigned int i = 0; i <= deg; ++i)
- {
- const double tmp
- = right_hand_side_value
- * legendre_polynomials[i].value
- (quadrature_point (0));
+ break;
+ }
- for (unsigned int j = 0; j < deg; ++j)
- system_rhs (i * deg + j)
- += tmp
- * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
- }
- }
+ default:
+ Assert (false, ExcNotImplemented ());
+ }
+}
- system_matrix_inv.vmult (solution, system_rhs);
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < deg; ++j)
- if (std::abs (solution (i * deg + j)) > 1e-14)
- interpolation_matrix
- (i + (j + source_fe.degree + 3)
- * source_fe.degree, dof) = solution (i * deg
- + j);
- }
- }
+#if deal_II_dimension == 1
- break;
- }
+template <>
+std::vector<unsigned int>
+FE_Nedelec<1>::get_dpo_vector (const unsigned int degree)
+{
+ std::vector<unsigned int> dpo (2);
- case 1:
- {
- const Quadrature<1>& edge_quadrature_x
- = QProjector<1>::project_to_child
- (reference_edge_quadrature, 1);
- const Quadrature<1>& edge_quadrature_y
- = QProjector<1>::project_to_child
- (reference_edge_quadrature, 0);
- const std::vector<Point<1> >&
- edge_quadrature_x_points = edge_quadrature_x.get_points ();
- const std::vector<Point<1> >&
- edge_quadrature_y_points = edge_quadrature_y.get_points ();
- const unsigned int& n_edge_points
- = edge_quadrature_x.size ();
+ dpo[0] = 1;
+ dpo[1] = degree;
+ return dpo;
+}
- // Let us begin with the
- // interpolation part.
- for (unsigned int q_point = 0; q_point < n_edge_points;
- ++q_point)
- {
- const double weight
- = edge_quadrature_x.weight (q_point);
+#endif
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- {
- interpolation_matrix (i * source_fe.degree, dof)
- += weight
- * this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (0.5 * (i + 1),
- edge_quadrature_y_points[q_point] (0), 0.0),
- 1);
- interpolation_matrix
- ((i + 2) * source_fe.degree, dof)
- += weight
- * this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (edge_quadrature_x_points[q_point] (0),
- 0.5 * i, 0.0), 0);
- }
- }
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- {
- if (std::abs (interpolation_matrix
- (i * source_fe.degree, dof)) < 1e-14)
- interpolation_matrix (i * source_fe.degree, dof)
- = 0.0;
-
- if (std::abs (interpolation_matrix
- ((i + 2) * source_fe.degree, dof))
- < 1e-14)
- interpolation_matrix ((i + 2) * source_fe.degree,
- dof) = 0.0;
- }
+template <int dim>
+std::vector<unsigned int>
+FE_Nedelec<dim>::get_dpo_vector (const unsigned int degree)
+{
+ std::vector<unsigned int> dpo (dim + 1);
- // If the degree is greater
- // than 0, then we have still
- // some higher order edge
- // shape functions to
- // consider.
- // Here the projection part
- // starts. The dof values
- // are obtained by solving
- // a linear system of
- // equations.
- if (deg > 0)
- {
- // We start with projection
- // on the higher order edge
- // shape function.
- const QGauss<dim - 1> reference_face_quadrature
- (this->degree);
- const Quadrature<dim - 1>& face_quadrature
- = QProjector<dim - 1>::project_to_child
- (reference_face_quadrature, 1);
- const std::vector<Point<dim - 1> >&
- face_quadrature_points = face_quadrature.get_points ();
- const std::vector<Polynomials::Polynomial<double> >&
- legendre_polynomials
- = Polynomials::Legendre::generate_complete_basis
- (deg);
- const std::vector<Polynomials::Polynomial<double> >&
- lobatto_polynomials
- = Polynomials::Lobatto::generate_complete_basis
- (this->degree);
- const unsigned int&
- n_face_points = face_quadrature.size ();
- FullMatrix<double> assembling_matrix (deg,
- n_edge_points);
- FullMatrix<double> system_matrix (deg, deg);
- FullMatrix<double> system_matrix_inv (deg, deg);
- std::vector<Polynomials::Polynomial<double> >
- lobatto_polynomials_grad (this->degree);
-
- for (unsigned int i = 0;
- i < lobatto_polynomials_grad.size (); ++i)
- lobatto_polynomials_grad[i]
- = lobatto_polynomials[i + 1].derivative ();
-
- // Shifted and scaled
- // quadrature points and
- // weights on the four
- // edges of a face.
- std::vector<std::vector<double> > edge_quadrature_points
- (GeometryInfo<dim>::lines_per_face,
- std::vector<double> (n_edge_points));
- std::vector<std::vector<double> >
- edge_quadrature_weights
- (GeometryInfo<dim>::lines_per_face,
- std::vector<double> (n_edge_points));
- std::vector<std::vector<Point<dim> > >
- edge_quadrature_points_full_dim
- (GeometryInfo<dim>::lines_per_face,
- std::vector<Point<dim> > (n_edge_points));
+ dpo[0] = 0;
+ dpo[1] = degree + 1;
+ dpo[2] = 2 * degree * (degree + 1);
- for (unsigned int q_point = 0; q_point < n_edge_points;
- ++q_point)
- {
- edge_quadrature_points[0][q_point]
- = 2.0 * edge_quadrature_y_points[q_point] (0);
- edge_quadrature_points[1][q_point]
- = edge_quadrature_points[0][q_point];
- edge_quadrature_points[2][q_point]
- = 2.0 * edge_quadrature_x_points[q_point] (0)
- - 1.0;
- edge_quadrature_points[3][q_point]
- = edge_quadrature_points[2][q_point];
- edge_quadrature_points_full_dim[0][q_point]
- = Point<dim>
- (0.5, edge_quadrature_y_points[q_point] (0),
- 0.0);
- edge_quadrature_points_full_dim[1][q_point]
- = Point<dim>
- (1.0, edge_quadrature_y_points[q_point] (0),
- 0.0);
- edge_quadrature_points_full_dim[2][q_point]
- = Point<dim>
- (edge_quadrature_x_points[q_point] (0), 0.0,
- 0.0);
- edge_quadrature_points_full_dim[3][q_point]
- = Point<dim>
- (edge_quadrature_x_points[q_point] (0), 0.5,
- 0.0);
- edge_quadrature_weights[0][q_point]
- = std::sqrt (edge_quadrature_y.weight (q_point));
- edge_quadrature_weights[1][q_point]
- = edge_quadrature_weights[0][q_point];
- edge_quadrature_weights[2][q_point]
- = std::sqrt (edge_quadrature_x.weight (q_point));
- edge_quadrature_weights[3][q_point]
- = edge_quadrature_weights[2][q_point];
- }
+ if (dim == 3)
+ dpo[3] = 3 * degree * degree * (degree + 1);
- // Set up the system matrix.
- // This can be used for all
- // edges.
- for (unsigned int q_point = 0;
- q_point < n_edge_points; ++q_point)
- {
- const double tmp
- = 2.0 * edge_quadrature_y_points[q_point] (0);
- const double weight
- = std::sqrt (edge_quadrature_y.weight (q_point));
-
- for (unsigned int i = 0; i < deg; ++i)
- assembling_matrix (i, q_point)
- = weight
- * lobatto_polynomials_grad[i + 1].value (tmp);
- }
-
- assembling_matrix.mTmult (system_matrix,
- assembling_matrix);
- system_matrix_inv.invert (system_matrix);
-
- Vector<double> system_rhs (system_matrix.m ());
- Vector<double> solution (system_rhs.size ());
-
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- for (unsigned int line = 0;
- line < GeometryInfo<dim - 1>::lines_per_cell;
- ++line)
- {
- // Set up the right hand side.
- system_rhs = 0;
+ return dpo;
+}
- for (unsigned int q_point = 0;
- q_point < n_edge_points; ++q_point)
- {
- const double right_hand_side_value
- = edge_quadrature_weights[line][q_point]
- * (this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- edge_quadrature_points_full_dim[line][q_point],
- 1) - interpolation_matrix
- (line * source_fe.degree,
- dof));
-
- for (unsigned int i = 0; i < deg; ++i)
- system_rhs (i)
- += right_hand_side_value
- * lobatto_polynomials_grad[i + 1].value
- (edge_quadrature_points[line][q_point]);
- }
+//---------------------------------------------------------------------------
+// Data field initialization
+//---------------------------------------------------------------------------
- system_matrix_inv.vmult (solution, system_rhs);
+ // Chech wheter a given shape
+ // function has support on a
+ // given face.
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i < solution.size ();
- ++i)
- if (std::abs (solution (i)) > 1e-14)
- interpolation_matrix
- (line * source_fe.degree + i + 1, dof)
- = solution (i);
- }
+ // We just switch through the
+ // faces of the cell and return
+ // true, if the shape function
+ // has support on the face
+ // and false otherwise.
+template <int dim>
+bool
+FE_Nedelec<dim>::has_support_on_face (const unsigned int shape_index,
+ const unsigned int face_index) const
+{
+ Assert (shape_index < this->dofs_per_cell,
+ ExcIndexRange (shape_index, 0, this->dofs_per_cell));
+ Assert (face_index < GeometryInfo<dim>::faces_per_cell,
+ ExcIndexRange (face_index, 0, GeometryInfo<dim>::faces_per_cell));
- // Now we project the remaining
- // part on the face shape
- // functions. First on the
- // horizontal ones, then on
- // the vertical ones.
- assembling_matrix.reinit (deg * this->degree,
- n_face_points);
+ switch (dim)
+ {
+ case 2:
+ switch (face_index)
+ {
+ case 0:
+ if (!((shape_index > deg) && (shape_index < 2 * this->degree)))
+ return true;
- for (unsigned int q_point = 0;
- q_point < n_face_points; ++q_point)
- {
- const Point<dim - 1> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0)
- - 1.0,
- 2.0 * face_quadrature_points[q_point] (1));
- const double weight
- = std::sqrt (face_quadrature.weight (q_point));
-
- for (unsigned int i = 0; i <= deg; ++i)
- {
- const double tmp
- = weight * legendre_polynomials[i].value
- (quadrature_point (0));
+ else
+ return false;
- for (unsigned int j = 0; j < deg; ++j)
- assembling_matrix (i * deg + j, q_point)
- = tmp * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
- }
- }
+ case 1:
+ if ((shape_index > deg) &&
+ (shape_index
+ < GeometryInfo<2>::lines_per_cell * this->degree))
+ return true;
- system_matrix.reinit (assembling_matrix.m (),
- assembling_matrix.m ());
- assembling_matrix.mTmult (system_matrix,
- assembling_matrix);
- system_matrix_inv.reinit (system_matrix.m (),
- system_matrix.m ());
- system_matrix_inv.invert (system_matrix);
- solution.reinit (system_matrix_inv.m ());
- system_rhs.reinit (assembling_matrix.m ());
-
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- {
- system_rhs = 0;
+ else
+ return false;
- for (unsigned int q_point = 0;
- q_point < n_face_points; ++q_point)
- {
- const Point<dim> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0)
- - 1.0,
- 2.0 * face_quadrature_points[q_point] (1),
- 0.0);
- double right_hand_side_value
- = this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (face_quadrature_points[q_point] (0),
- face_quadrature_points[q_point] (1), 0),
- 1);
+ case 2:
+ if (shape_index < 3 * this->degree)
+ return true;
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int j = 0; j < source_fe.degree;
- ++j)
- right_hand_side_value
- -= interpolation_matrix
- (i * source_fe.degree + j, dof)
- * source_fe.shape_value_component
- (i * source_fe.degree + j,
- quadrature_point, 1);
+ else
+ return false;
- right_hand_side_value
- *= face_quadrature.weight (q_point);
+ case 3:
+ if (!((shape_index >= 2 * this->degree) &&
+ (shape_index < 3 * this->degree)))
+ return true;
- for (unsigned int i = 0; i <= deg; ++i)
- {
- const double tmp
- = right_hand_side_value
- * legendre_polynomials[i].value
- (quadrature_point (0));
+ else
+ return false;
- for (unsigned int j = 0; j < deg; ++j)
- system_rhs (i * deg + j)
- = tmp
- * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
- }
- }
+ default:
+ {
+ Assert (false, ExcNotImplemented ());
+ return false;
+ }
+ }
- system_matrix_inv.vmult (solution, system_rhs);
+ case 3:
+ switch (face_index)
+ {
+ case 0:
+ if (((shape_index > deg) && (shape_index < 2 * this->degree)) ||
+ ((shape_index >= 5 * this->degree) &&
+ (shape_index < 6 * this->degree)) ||
+ ((shape_index >= 9 * this->degree) &&
+ (shape_index < 10 * this->degree)) ||
+ ((shape_index >= 11 * this->degree) &&
+ (shape_index
+ < GeometryInfo<3>::lines_per_cell * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 2 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 5 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 6 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 7 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 8 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 9 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 10 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 11 * deg)
+ * this->degree)))
+ return false;
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < deg; ++j)
- if (std::abs (solution (i * deg + j)) > 1e-14)
- interpolation_matrix
- ((i + 4) * source_fe.degree + j - i, dof)
- = solution (i * deg + j);
+ else
+ return true;
- // Set up the right hand side
- // for the vertical shape
- // functions.
- system_rhs = 0;
+ case 1:
+ if (((shape_index > deg) && (shape_index < 4 * this->degree)) ||
+ ((shape_index >= 5 * this->degree) &&
+ (shape_index < 8 * this->degree)) ||
+ ((shape_index >= 9 * this->degree) &&
+ (shape_index < 10 * this->degree)) ||
+ ((shape_index >= 11 * this->degree) &&
+ (shape_index
+ < GeometryInfo<3>::lines_per_cell * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 2 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 4 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 5 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 6 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 7 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 8 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 9 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 10 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 11 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 12 * deg)
+ * this->degree)))
+ return true;
- for (unsigned int q_point = 0;
- q_point < n_face_points; ++q_point)
- {
- const Point<dim> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0)
- - 1.0,
- 2.0 * face_quadrature_points[q_point] (1),
- 0.0);
- double right_hand_side_value
- = this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (face_quadrature_points[q_point] (0),
- face_quadrature_points[q_point] (1), 0),
- 0);
+ else
+ return false;
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int j = 0; j < source_fe.degree;
- ++j)
- right_hand_side_value
- -= interpolation_matrix
- ((i + 2) * source_fe.degree + j, dof)
- * source_fe.shape_value_component
- (i * source_fe.degree + j,
- quadrature_point, 0);
+ case 2:
+ if ((shape_index < 3 * this->degree) ||
+ ((shape_index >= 4 * this->degree) &&
+ (shape_index < 7 * this->degree)) ||
+ ((shape_index >= 8 * this->degree) &&
+ (shape_index < 10 * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 2 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 3 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 6 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 8 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 9 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 10 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 11 * deg)
+ * this->degree)))
+ return true;
- right_hand_side_value
- *= face_quadrature.weight (q_point);
+ else
+ return false;
- for (unsigned int i = 0; i <= deg; ++i)
- {
- const double tmp
- = right_hand_side_value
- * legendre_polynomials[i].value
- (quadrature_point (0));
+ case 3:
+ if ((shape_index < 2 * this->degree) ||
+ ((shape_index >= 3 * this->degree) &&
+ (shape_index < 6 * this->degree)) ||
+ ((shape_index >= 7 * this->degree) &&
+ (shape_index < 8 * this->degree)) ||
+ ((shape_index >= 10 * this->degree) &&
+ (shape_index
+ < GeometryInfo<3>::lines_per_cell * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 2 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 3 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 4 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 6 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 9 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 10 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 11 * deg)
+ * this->degree)))
+ return true;
- for (unsigned int j = 0; j < deg; ++j)
- system_rhs (i * deg + j)
- += tmp
- * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
- }
- }
+ else
+ return false;
- system_matrix_inv.vmult (solution, system_rhs);
+ case 4:
+ if ((shape_index < 4 * this->degree) ||
+ ((shape_index >= 8 * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 2 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 3 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 4 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 5 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 6 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 7 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 8 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 10 * deg)
+ * this->degree)))
+ return true;
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < deg; ++j)
- if (std::abs (solution (i * deg + j)) > 1e-14)
- interpolation_matrix
- (i + (j + source_fe.degree + 3)
- * source_fe.degree, dof)
- = solution (i * deg + j);
- }
- }
+ else
+ return false;
- break;
- }
+ case 5:
+ if (((shape_index >= 4 * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 2 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 3 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 4 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 5 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 6 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 7 * deg)
+ * this->degree)) ||
+ ((shape_index
+ >= (GeometryInfo<3>::lines_per_cell + 10 * deg)
+ * this->degree) &&
+ (shape_index
+ < (GeometryInfo<3>::lines_per_cell + 12 * deg)
+ * this->degree)))
+ return true;
- case 2:
- {
- const Quadrature<1>& edge_quadrature_x
- = QProjector<1>::project_to_child
- (reference_edge_quadrature, 0);
- const Quadrature<1>& edge_quadrature_y
- = QProjector<1>::project_to_child
- (reference_edge_quadrature, 1);
- const unsigned int& n_edge_points
- = edge_quadrature_x.size ();
- const std::vector<Point<1> >&
- edge_quadrature_x_points = edge_quadrature_x.get_points ();
- const std::vector<Point<1> >&
- edge_quadrature_y_points = edge_quadrature_y.get_points ();
+ else
+ return false;
- // Let us begin with the
- // interpolation part.
- for (unsigned int q_point = 0; q_point < n_edge_points;
- ++q_point)
- {
- const double weight
- = edge_quadrature_x.weight (q_point);
+ default:
+ {
+ Assert (false, ExcNotImplemented ());
+ return false;
+ }
+ }
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- {
- interpolation_matrix (i * source_fe.degree, dof)
- += weight
- * this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (0.5 * i,
- edge_quadrature_y_points[q_point] (0), 0.0),
- 1);
- interpolation_matrix ((i + 2) * source_fe.degree,
- dof)
- += weight
- * this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (edge_quadrature_x_points[q_point] (0),
- 0.5 * (i + 1), 0.0), 0);
- }
- }
+ default:
+ {
+ Assert (false, ExcNotImplemented ());
+ return false;
+ }
+ }
+}
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- {
- if (std::abs (interpolation_matrix
- (i * source_fe.degree, dof)) < 1e-14)
- interpolation_matrix (i * source_fe.degree, dof)
- = 0.0;
-
- if (std::abs (interpolation_matrix
- ((i + 2) * source_fe.degree, dof))
- < 1e-14)
- interpolation_matrix ((i + 2) * source_fe.degree,
- dof) = 0.0;
- }
+template <int dim>
+FiniteElementDomination::Domination
+FE_Nedelec<dim>::compare_for_face_domination (const FiniteElement<dim> &fe_other) const
+{
+ if (const FE_Nedelec<dim> *fe_nedelec_other
+ = dynamic_cast<const FE_Nedelec<dim>*>(&fe_other))
+ {
+ if (this->degree < fe_nedelec_other->degree)
+ return FiniteElementDomination::this_element_dominates;
+ else if (this->degree == fe_nedelec_other->degree)
+ return FiniteElementDomination::either_element_can_dominate;
+ else
+ return FiniteElementDomination::other_element_dominates;
+ }
+ else if (dynamic_cast<const FE_Nothing<dim>*>(&fe_other) != 0)
+ {
+ // the FE_Nothing has no
+ // degrees of
+ // freedom. nevertheless, we
+ // say that the FE_Q element
+ // dominates so that we don't
+ // have to force the FE_Q side
+ // to become a zero function
+ // and rather allow the
+ // function to be discontinuous
+ // along the interface
+ return FiniteElementDomination::other_element_dominates;
+ }
- // If the degree is greater
- // than 0, then we have still
- // some higher order edge
- // shape functions to
- // consider.
- // Here the projection part
- // starts. The dof values
- // are obtained by solving
- // a linear system of
- // equations.
- if (deg > 0)
- {
- // We start with projection
- // on the higher order edge
- // shape function.
- const QGauss<dim - 1> reference_face_quadrature (this->degree);
- const Quadrature<dim - 1>& face_quadrature
- = QProjector<dim - 1>::project_to_child
- (reference_face_quadrature, 2);
- const std::vector<Point<dim - 1> >&
- face_quadrature_points = face_quadrature.get_points ();
- const std::vector<Polynomials::Polynomial<double> >& legendre_polynomials
- = Polynomials::Legendre::generate_complete_basis (deg);
- const std::vector<Polynomials::Polynomial<double> >& lobatto_polynomials
- = Polynomials::Lobatto::generate_complete_basis (this->degree);
- const unsigned int& n_face_points
- = face_quadrature.size ();
- FullMatrix<double> assembling_matrix (deg,
- n_edge_points);
- FullMatrix<double> system_matrix (deg, deg);
- FullMatrix<double> system_matrix_inv (deg, deg);
- std::vector<Polynomials::Polynomial<double> >
- lobatto_polynomials_grad (this->degree);
-
- for (unsigned int i = 0;
- i < lobatto_polynomials_grad.size (); ++i)
- lobatto_polynomials_grad[i]
- = lobatto_polynomials[i + 1].derivative ();
-
- // Shifted and scaled
- // quadrature points and
- // weights on the four
- // edges of a face.
- std::vector<std::vector<double> >
- edge_quadrature_points
- (GeometryInfo<dim>::lines_per_face,
- std::vector<double> (n_edge_points));
- std::vector<std::vector<double> >
- edge_quadrature_weights
- (GeometryInfo<dim>::lines_per_face,
- std::vector<double> (n_edge_points));
- std::vector<std::vector<Point<dim> > >
- edge_quadrature_points_full_dim
- (GeometryInfo<dim>::lines_per_face,
- std::vector<Point<dim> > (n_edge_points));
+ Assert (false, ExcNotImplemented());
+ return FiniteElementDomination::neither_element_dominates;
+}
- for (unsigned int q_point = 0; q_point < n_edge_points;
- ++q_point)
- {
- edge_quadrature_points[0][q_point]
- = 2.0 * edge_quadrature_y_points[q_point] (0)
- - 1.0;
- edge_quadrature_points[1][q_point]
- = edge_quadrature_points[0][q_point];
- edge_quadrature_points[2][q_point]
- = 2.0 * edge_quadrature_x_points[q_point] (0);
- edge_quadrature_points[3][q_point]
- = edge_quadrature_points[2][q_point];
- edge_quadrature_points_full_dim[0][q_point]
- = Point<dim>
- (0.0, edge_quadrature_y_points[q_point] (0),
- 0.0);
- edge_quadrature_points_full_dim[1][q_point]
- = Point<dim>
- (0.5, edge_quadrature_y_points[q_point] (0),
- 0.0);
- edge_quadrature_points_full_dim[2][q_point]
- = Point<dim>
- (edge_quadrature_x_points[q_point] (0), 0.5,
- 0.0);
- edge_quadrature_points_full_dim[3][q_point]
- = Point<dim>
- (edge_quadrature_x_points[q_point] (0), 1.0,
- 0.0);
- edge_quadrature_weights[0][q_point]
- = std::sqrt (edge_quadrature_y.weight (q_point));
- edge_quadrature_weights[1][q_point]
- = edge_quadrature_weights[0][q_point];
- edge_quadrature_weights[2][q_point]
- = std::sqrt (edge_quadrature_x.weight (q_point));
- edge_quadrature_weights[3][q_point]
- = edge_quadrature_weights[2][q_point];
- }
+template <int dim>
+bool
+FE_Nedelec<dim>::hp_constraints_are_implemented () const
+{
+ return true;
+}
- // Set up the system matrix.
- // This can be used for all
- // edges.
- for (unsigned int q_point = 0;
- q_point < n_edge_points; ++q_point)
- {
- const double weight
- = std::sqrt (edge_quadrature_y.weight
- (q_point));
- const double tmp
- = 2.0 * edge_quadrature_y_points[q_point] (0)
- - 1.0;
-
- for (unsigned int i = 0; i < deg; ++i)
- assembling_matrix (i, q_point)
- = weight
- * lobatto_polynomials_grad[i + 1].value
- (tmp);
- }
+template <int dim>
+std::vector<std::pair<unsigned int, unsigned int> >
+FE_Nedelec<dim>::hp_vertex_dof_identities (const FiniteElement<dim>&)
+const
+{
+ // Nedelec elements do not have any dofs
+ // on vertices, hence return an empty vector.
+ return std::vector<std::pair<unsigned int, unsigned int> > ();
+}
- assembling_matrix.mTmult (system_matrix,
- assembling_matrix);
- system_matrix_inv.invert (system_matrix);
+template <int dim>
+std::vector<std::pair<unsigned int, unsigned int> >
+FE_Nedelec<dim>::hp_line_dof_identities (const FiniteElement<dim>& fe_other)
+const
+{
+ // we can presently only compute these
+ // identities if both FEs are
+ // FE_Nedelec or if the other one is an
+ // FE_Nothing
+ if (const FE_Nedelec<dim> *fe_nedelec_other
+ = dynamic_cast<const FE_Nedelec<dim>*> (&fe_other))
+ {
+ // dofs are located on lines, so
+ // two dofs are identical, if their
+ // edge shape functions have the
+ // same polynomial degree.
+ std::vector<std::pair<unsigned int, unsigned int> > identities;
- Vector<double> system_rhs (system_matrix.m ());
- Vector<double> solution (system_rhs.size ());
+ for (unsigned int i = 0;
+ i < std::min (fe_nedelec_other->degree, this->degree); ++i)
+ identities.push_back (std::make_pair (i, i));
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- for (unsigned int line = 0;
- line < GeometryInfo<dim - 1>::lines_per_cell;
- ++line)
- {
- // Set up the right hand side.
- system_rhs = 0;
+ return identities;
+ }
- for (unsigned int q_point = 0;
- q_point < n_edge_points; ++q_point)
- {
- const double right_hand_side_value
- = edge_quadrature_weights[line][q_point]
- * (this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- edge_quadrature_points_full_dim[line][q_point],
- 1) - interpolation_matrix
- (line * source_fe.degree, dof));
-
- for (unsigned int i = 0; i < deg; ++i)
- system_rhs (i)
- += right_hand_side_value
- * lobatto_polynomials_grad[i + 1].value
- (edge_quadrature_points[line][q_point]);
- }
+ else
+ if (dynamic_cast<const FE_Nothing<dim>*> (&fe_other) != 0)
+ {
+ // the FE_Nothing has no
+ // degrees of freedom, so there
+ // are no equivalencies to be
+ // recorded
+ return std::vector<std::pair<unsigned int, unsigned int> > ();
+ }
- system_matrix_inv.vmult (solution, system_rhs);
+ else
+ {
+ Assert (false, ExcNotImplemented ());
+ return std::vector<std::pair<unsigned int, unsigned int> > ();
+ }
+}
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i < solution.size ();
- ++i)
- if (std::abs (solution (i)) > 1e-14)
- interpolation_matrix
- (line * source_fe.degree + i + 1, dof)
- = solution (i);
- }
+template <int dim>
+std::vector<std::pair<unsigned int, unsigned int> >
+FE_Nedelec<dim>::hp_quad_dof_identities (const FiniteElement<dim>& fe_other)
+const
+{
+ // we can presently only compute
+ // these identities if both FEs are
+ // FE_Nedelec or if the other one is an
+ // FE_Nothing
+ if (const FE_Nedelec<dim> *fe_nedelec_other
+ = dynamic_cast<const FE_Nedelec<dim>*> (&fe_other))
+ {
+ // dofs are located on the interior
+ // of faces, so two dofs are identical,
+ // if their face shape functions have
+ // the same polynomial degree.
+ const unsigned int p = fe_nedelec_other->degree;
+ const unsigned int q = this->degree;
+ const unsigned int p_min = std::min (p, q);
+ std::vector<std::pair<unsigned int, unsigned int> > identities;
- assembling_matrix.reinit (deg * this->degree,
- n_face_points);
+ for (unsigned int i = 0; i < p_min; ++i)
+ for (unsigned int j = 0; j < p_min - 1; ++j)
+ {
+ identities.push_back (std::make_pair ((i + 1) * (q + 1) + j,
+ (i + 1) * (p + 1) + j));
+ identities.push_back (std::make_pair (i + (j + q + 2) * q,
+ i + (j + p + 2) * p));
+ }
- for (unsigned int q_point = 0;
- q_point < n_face_points; ++q_point)
- {
- const double weight
- = std::sqrt (face_quadrature.weight (q_point));
- const Point<dim - 1> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0),
- 2.0 * face_quadrature_points[q_point] (1) - 1.0);
-
- for (unsigned int i = 0; i <= deg; ++i)
- {
- const double tmp
- = weight * legendre_polynomials[i].value
- (quadrature_point (0));
-
- for (unsigned int j = 0; j < deg; ++j)
- assembling_matrix (i * deg + j, q_point)
- = tmp * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
- }
- }
+ return identities;
+ }
- system_matrix.reinit (assembling_matrix.m (),
- assembling_matrix.m ());
- assembling_matrix.mTmult (system_matrix,
- assembling_matrix);
- system_matrix_inv.reinit (system_matrix.m (),
- system_matrix.m ());
- system_matrix_inv.invert (system_matrix);
- solution.reinit (system_matrix_inv.m ());
- system_rhs.reinit (assembling_matrix.m ());
- system_rhs = 0;
+ else
+ if (dynamic_cast<const FE_Nothing<dim>*> (&fe_other) != 0)
+ {
+ // the FE_Nothing has no
+ // degrees of freedom, so there
+ // are no equivalencies to be
+ // recorded
+ return std::vector<std::pair<unsigned int, unsigned int> > ();
+ }
- // Now we project the remaining
- // part on the face shape
- // functions. First on the
- // horizontal ones, then on
- // the vertical ones.
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- {
- for (unsigned int q_point = 0;
- q_point < n_face_points; ++q_point)
- {
- const Point<dim> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0),
- 2.0 * face_quadrature_points[q_point] (1)
- - 1.0, 0.0);
- double right_hand_side_value
- = this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (face_quadrature_points[q_point] (0),
- face_quadrature_points[q_point] (1), 0.0),
- 1);
+ else
+ {
+ Assert (false, ExcNotImplemented ());
+ return std::vector<std::pair<unsigned int, unsigned int> > ();
+ }
+}
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int j = 0; j < source_fe.degree;
- ++j)
- right_hand_side_value
- -= interpolation_matrix
- (i * source_fe.degree + j, dof)
- * source_fe.shape_value_component
- (i * source_fe.degree + j,
- quadrature_point, 1);
+ // In this function we compute the face
+ // interpolation matrix. This is usually
+ // done by projection-based interpolation,
+ // but, since one can compute the entries
+ // easy per hand, we save some computation
+ // time at this point and just fill in the
+ // correct values.
+template <int dim>
+void
+FE_Nedelec<dim>::get_face_interpolation_matrix
+ (const FiniteElement<dim>& source, FullMatrix<double>& interpolation_matrix)
+const
+{
+ // this is only implemented, if the
+ // source FE is also a
+ // Nedelec element
+ typedef FE_Nedelec<dim> FEN;
+ typedef FiniteElement<dim> FEL;
- right_hand_side_value
- *= face_quadrature.weight (q_point);
+ AssertThrow ((source.get_name ().find ("FE_Nedelec<") == 0) ||
+ (dynamic_cast<const FEN*> (&source) != 0),
+ typename FEL::ExcInterpolationNotImplemented());
+ Assert (interpolation_matrix.m () == source.dofs_per_face,
+ ExcDimensionMismatch (interpolation_matrix.m (),
+ source.dofs_per_face));
+ Assert (interpolation_matrix.n () == this->dofs_per_face,
+ ExcDimensionMismatch (interpolation_matrix.n (),
+ this->dofs_per_face));
- for (unsigned int i = 0; i <= deg; ++i)
- {
- const double tmp
- = right_hand_side_value
- * legendre_polynomials[i].value
- (quadrature_point (0));
+ // ok, source is a Nedelec element, so
+ // we will be able to do the work
+ const FE_Nedelec<dim> &source_fe
+ = dynamic_cast<const FE_Nedelec<dim>&> (source);
- for (unsigned int j = 0; j < deg; ++j)
- system_rhs (i * deg + j)
- += tmp
- * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
- }
- }
+ // Make sure, that the element,
+ // for which the DoFs should be
+ // constrained is the one with
+ // the higher polynomial degree.
+ // Actually the procedure will work
+ // also if this assertion is not
+ // satisfied. But the matrices
+ // produced in that case might
+ // lead to problems in the
+ // hp procedures, which use this
+ // method.
+ Assert (this->dofs_per_face <= source_fe.dofs_per_face,
+ typename FEL::ExcInterpolationNotImplemented ());
+ interpolation_matrix = 0;
- system_matrix_inv.vmult (solution, system_rhs);
+ // On lines we can just identify
+ // all degrees of freedom.
+ for (unsigned int i = 0; i <= deg; ++i)
+ interpolation_matrix (i, i) = 1.0;
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < deg; ++j)
- if (std::abs (solution (i * deg + j)) > 1e-14)
- interpolation_matrix
- ((i + 4) * source_fe.degree + j - i, dof)
- = solution (i * deg + j);
+ // In 3d we have some lines more
+ // and a face. The procedure stays
+ // the same as above, but we have
+ // to take a bit more care of the
+ // indices of the degrees of
+ // freedom.
+ if (dim == 3)
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ for (int j = 1; j < (int) GeometryInfo<dim>::lines_per_face; ++j)
+ interpolation_matrix (j * source_fe.degree + i,
+ j * this->degree + i) = 1.0;
- // Set up the right hand side
- // for the vertical shape
- // functions.
- system_rhs = 0;
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ interpolation_matrix
+ (i + (j + GeometryInfo<2>::lines_per_cell) * source_fe.degree,
+ i + (j + GeometryInfo<2>::lines_per_cell) * this->degree)
+ = 1.0;
+ interpolation_matrix
+ ((i * (source_fe.degree - 1)
+ + GeometryInfo<2>::lines_per_cell) * source_fe.degree + j,
+ (i * deg + GeometryInfo<2>::lines_per_cell) * this->degree)
+ = 1.0;
+ }
+ }
+}
- for (unsigned int q_point = 0;
- q_point < n_face_points; ++q_point)
- {
- const Point<dim> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0),
- 2.0 * face_quadrature_points[q_point] (1)
- - 1.0, 0.0);
- double right_hand_side_value
- = this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (face_quadrature_points[q_point] (0),
- face_quadrature_points[q_point] (1), 0.0),
- 0);
+#if deal_II_dimension == 1
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int j = 0; j < source_fe.degree;
- ++j)
- right_hand_side_value
- -= interpolation_matrix
- ((i + 2) * source_fe.degree + j, dof)
- * source_fe.shape_value_component
- (i * source_fe.degree + j,
- quadrature_point, 0);
+template <int dim>
+void
+FE_Nedelec<dim>::get_subface_interpolation_matrix(
+ const FiniteElement<dim>&,
+ const unsigned int,
+ FullMatrix<double>&) const
+{
+ Assert (false, ExcNotImplemented ());
+}
- right_hand_side_value *= face_quadrature.weight
- (q_point);
+#else
- for (unsigned int i = 0; i <= deg; ++i)
- {
- const double tmp
- = right_hand_side_value
- * legendre_polynomials[i].value
- (quadrature_point (0));
+ // In this function we compute the
+ // subface interpolation matrix.
+ // This is done by a projection-
+ // based interpolation. Therefore
+ // we first interpolate the
+ // shape functions of the higher
+ // order element on the lowest
+ // order edge shape functions.
+ // Then the remaining part of
+ // the interpolated shape
+ // functions is projected on the
+ // higher order edge shape
+ // functions, the face shape
+ // functions and the interior
+ // shape functions (if they all
+ // exist).
+template <int dim>
+void
+FE_Nedelec<dim>::get_subface_interpolation_matrix(
+ const FiniteElement<dim>& source,
+ const unsigned int subface,
+ FullMatrix<double>& interpolation_matrix) const
+{
+ // this is only implemented, if the
+ // source FE is also a
+ // Nedelec element
+ typedef FE_Nedelec<dim> FEN;
+ typedef FiniteElement<dim> FEL;
- for (unsigned int j = 0; j < deg; ++j)
- system_rhs (i * deg + j)
- += tmp
- * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
- }
- }
+ AssertThrow ((source.get_name ().find ("FE_Nedelec<") == 0) ||
+ (dynamic_cast<const FEN*> (&source) != 0),
+ typename FEL::ExcInterpolationNotImplemented ());
+ Assert (interpolation_matrix.m () == source.dofs_per_face,
+ ExcDimensionMismatch (interpolation_matrix.m (),
+ source.dofs_per_face));
+ Assert (interpolation_matrix.n () == this->dofs_per_face,
+ ExcDimensionMismatch (interpolation_matrix.n (),
+ this->dofs_per_face));
- system_matrix_inv.vmult (solution, system_rhs);
+ // ok, source is a Nedelec element, so
+ // we will be able to do the work
+ const FE_Nedelec<dim> &source_fe
+ = dynamic_cast<const FE_Nedelec<dim>&> (source);
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < deg; ++j)
- if (std::abs (solution (i * deg + j)) > 1e-14)
- interpolation_matrix
- (i + (j + source_fe.degree + 3)
- * source_fe.degree, dof)
- = solution (i * deg + j);
- }
+ // Make sure, that the element,
+ // for which the DoFs should be
+ // constrained is the one with
+ // the higher polynomial degree.
+ // Actually the procedure will work
+ // also if this assertion is not
+ // satisfied. But the matrices
+ // produced in that case might
+ // lead to problems in the
+ // hp procedures, which use this
+ // method.
+ Assert (this->dofs_per_face <= source_fe.dofs_per_face,
+ typename FEL::ExcInterpolationNotImplemented ());
+ interpolation_matrix = 0.0;
+ // Perform projection-based interpolation
+ // as usual.
+ const QGauss<1> edge_quadrature (source_fe.degree);
+ const std::vector<Point<1> >&
+ edge_quadrature_points = edge_quadrature.get_points ();
+ const unsigned int& n_edge_quadrature_points = edge_quadrature.size ();
+
+ switch (dim)
+ {
+ case 2:
+ {
+ for (unsigned int dof = 0; dof < this->dofs_per_face; ++dof)
+ for (unsigned int q_point = 0; q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const Point<dim> quadrature_point (0.0,
+ 0.5 * (edge_quadrature_points[q_point] (0)
+ + subface));
+
+ interpolation_matrix (0, dof) += 0.5
+ * edge_quadrature.weight (q_point)
+ * this->shape_value_component
+ (dof, quadrature_point, 1);
+ }
+
+ if (deg > 0)
+ {
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials
+ = Polynomials::Legendre::generate_complete_basis (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
+ {
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
+ {
+ const double weight
+ = std::sqrt (edge_quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point) = weight
+ * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+ }
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix, assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ Vector<double> solution (deg);
+ Vector<double> system_rhs (deg);
+
+ for (unsigned int dof = 0; dof < this->dofs_per_face; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
+ {
+ const Point<dim> quadrature_point_0 (0.0,
+ 0.5 * (edge_quadrature_points[q_point] (0)
+ + subface));
+ const Point<dim> quadrature_point_1 (0.0,
+ edge_quadrature_points[q_point] (0));
+ const double tmp = edge_quadrature.weight (q_point)
+ * (0.5 * this->shape_value_component
+ (dof, quadrature_point_0, 1)
+ - interpolation_matrix (0,
+ dof)
+ * source_fe.shape_value_component
+ (0, quadrature_point_1, 1));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ system_rhs (i) += tmp
+ * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
}
-
- break;
+
+ system_matrix_inv.vmult (solution, system_rhs);
+
+ for (unsigned int i = 0; i < deg; ++i)
+ if (std::abs (solution (i)) > 1e-14)
+ interpolation_matrix (i + 1, dof) = solution (i);
}
+ }
+
+ break;
+ }
- case 3:
+ case 3:
+ {
+ const double shifts[4][2] = { { 0.0, 0.0 }, { 1.0, 0.0 },
+ { 0.0, 1.0 }, { 1.0, 1.0 } };
+
+ for (unsigned int dof = 0; dof < this->dofs_per_face; ++dof)
+ for (unsigned int q_point = 0; q_point < n_edge_quadrature_points;
+ ++q_point)
+ {
+ const double weight = 0.5 * edge_quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ {
+ Point<dim>
+ quadrature_point (0.5 * (i + shifts[subface][0]),
+ 0.5 * (edge_quadrature_points[q_point] (0)
+ + shifts[subface][1]), 0.0);
+
+ interpolation_matrix (i * source_fe.degree, dof) += weight
+ * this->shape_value_component
+ (this->face_to_cell_index (dof, 4),
+ quadrature_point,
+ 1);
+ quadrature_point
+ = Point<dim> (0.5 * (edge_quadrature_points[q_point] (0)
+ + shifts[subface][0]),
+ 0.5 * (i + shifts[subface][1]), 0.0);
+ interpolation_matrix ((i + 2) * source_fe.degree, dof)
+ += weight * this->shape_value_component
+ (this->face_to_cell_index (dof, 4),
+ quadrature_point, 0);
+ }
+ }
+
+ if (deg > 0)
+ {
+ const std::vector<Polynomials::Polynomial<double> >&
+ legendre_polynomials
+ = Polynomials::Legendre::generate_complete_basis (deg);
+ FullMatrix<double> system_matrix_inv (deg, deg);
+
+ {
+ FullMatrix<double> assembling_matrix (deg,
+ n_edge_quadrature_points);
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
+ {
+ const double weight
+ = std::sqrt (edge_quadrature.weight (q_point));
+
+ for (unsigned int i = 0; i < deg; ++i)
+ assembling_matrix (i, q_point) = weight
+ * legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+ }
+
+ FullMatrix<double> system_matrix (deg, deg);
+
+ assembling_matrix.mTmult (system_matrix, assembling_matrix);
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ FullMatrix<double> solution (deg,
+ GeometryInfo<dim>::lines_per_face);
+ FullMatrix<double> system_rhs (deg,
+ GeometryInfo<dim>::lines_per_face);
+ Vector<double> tmp (GeometryInfo<dim>::lines_per_face);
+
+ for (unsigned int dof = 0; dof < this->dofs_per_face; ++dof)
{
- const Quadrature<1>& edge_quadrature
- = QProjector<1>::project_to_child
- (reference_edge_quadrature, 1);
- const unsigned int& n_edge_points = edge_quadrature.size ();
- const std::vector<Point<1> >&
- edge_quadrature_points = edge_quadrature.get_points ();
-
- // Let us begin with the
- // interpolation part.
- for (unsigned int q_point = 0; q_point < n_edge_points;
- ++q_point)
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_edge_quadrature_points; ++q_point)
{
const double weight = edge_quadrature.weight (q_point);
-
+
for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- {
- interpolation_matrix (i * source_fe.degree, dof)
- += weight
- * this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (0.5 * (i + 1),
- edge_quadrature_points[q_point] (0), 0.0),
- 1);
- interpolation_matrix ((i + 2) * source_fe.degree,
- dof)
- += weight
- * this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (edge_quadrature_points[q_point] (0),
- 0.5 * (i + 1), 0.0), 0);
- }
- }
-
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- {
- if (std::abs (interpolation_matrix
- (i * source_fe.degree, dof)) < 1e-14)
- interpolation_matrix (i * source_fe.degree, dof)
- = 0.0;
-
- if (std::abs (interpolation_matrix
- ((i + 2) * source_fe.degree, dof))
- < 1e-14)
- interpolation_matrix ((i + 2) * source_fe.degree,
- dof) = 0.0;
- }
-
- // If the degree is greater
- // than 0, then we have still
- // some higher order edge
- // shape functions to
- // consider.
- // Here the projection part
- // starts. The dof values
- // are obtained by solving
- // a linear system of
- // equations.
- if (deg > 1)
- {
- // We start with projection
- // on the higher order edge
- // shape function.
- const QGauss<dim - 1>
- reference_face_quadrature (this->degree);
- const Quadrature<dim - 1>& face_quadrature
- = QProjector<dim - 1>::project_to_child
- (reference_face_quadrature, 3);
- const std::vector<Point<dim - 1> >&
- face_quadrature_points = face_quadrature.get_points ();
- const std::vector<Polynomials::Polynomial<double> >&
- legendre_polynomials
- = Polynomials::Legendre::generate_complete_basis
- (deg);
- const std::vector<Polynomials::Polynomial<double> >&
- lobatto_polynomials
- = Polynomials::Lobatto::generate_complete_basis
- (this->degree);
- const unsigned int& n_face_points
- = face_quadrature.size ();
- FullMatrix<double> assembling_matrix (deg,
- n_edge_points);
- FullMatrix<double> system_matrix (deg, deg);
- FullMatrix<double> system_matrix_inv (deg, deg);
- std::vector<Polynomials::Polynomial<double> >
- lobatto_polynomials_grad (this->degree);
-
- for (unsigned int i = 0;
- i < lobatto_polynomials_grad.size (); ++i)
- lobatto_polynomials_grad[i]
- = lobatto_polynomials[i + 1].derivative ();
-
- // Shifted and scaled
- // quadrature points on
- // the four edges of a
- // face.
- std::vector<std::vector<Point<dim> > >
- edge_quadrature_points_full_dim
- (GeometryInfo<dim>::lines_per_face,
- std::vector<Point<dim> > (n_edge_points));
-
- for (unsigned int q_point = 0; q_point < n_edge_points;
- ++q_point)
{
- edge_quadrature_points_full_dim[0][q_point]
- = Point<dim>
- (0.5, edge_quadrature_points[q_point] (0), 0.0);
- edge_quadrature_points_full_dim[1][q_point]
- = Point<dim>
- (1.0, edge_quadrature_points[q_point] (0), 0.0);
- edge_quadrature_points_full_dim[2][q_point]
- = Point<dim> (edge_quadrature_points[q_point] (0),
- 0.5, 0.0);
- edge_quadrature_points_full_dim[3][q_point]
+ Point<dim>
+ quadrature_point_0
+ (0.5 * (i + shifts[subface][0]),
+ 0.5 * (edge_quadrature_points[q_point] (0)
+ + shifts[subface][1]), 0.0);
+ Point<dim> quadrature_point_1 (i,
+ edge_quadrature_points[q_point] (0),
+ 0.0);
+
+ tmp (i) = weight
+ * (0.5 * this->shape_value_component
+ (this->face_to_cell_index (dof, 4),
+ quadrature_point_0, 1)
+ - interpolation_matrix
+ (i * source_fe.degree, dof)
+ * source_fe.shape_value_component
+ (i * source_fe.degree,
+ quadrature_point_1, 1));
+ quadrature_point_0
+ = Point<dim> (0.5 * (edge_quadrature_points[q_point] (0)
+ + shifts[subface][0]),
+ 0.5 * (i + shifts[subface][1]),
+ 0.0);
+ quadrature_point_1
= Point<dim> (edge_quadrature_points[q_point] (0),
- 1.0, 0.0);
+ i, 0.0);
+ tmp (i + 2) = weight
+ * (0.5 * this->shape_value_component
+ (this->face_to_cell_index (dof, 4),
+ quadrature_point_0, 0)
+ - interpolation_matrix
+ ((i + 2) * source_fe.degree,
+ dof)
+ * source_fe.shape_value_component
+ ((i + 2) * source_fe.degree,
+ quadrature_point_1, 0));
}
-
- // Set up the system matrix.
- // This can be used for all
- // edges.
- for (unsigned int q_point = 0;
- q_point < n_edge_points; ++q_point)
- {
- const double tmp
- = 2.0 * edge_quadrature_points[q_point] (0)
- - 1.0;
- const double weight
- = std::sqrt (edge_quadrature.weight (q_point));
-
- for (unsigned int i = 0; i < deg; ++i)
- assembling_matrix (i, q_point)
- = weight
- * lobatto_polynomials_grad[i + 1].value
- (tmp);
- }
-
- assembling_matrix.mTmult (system_matrix,
- assembling_matrix);
- system_matrix_inv.invert (system_matrix);
-
- Vector<double> system_rhs (system_matrix.m ());
- Vector<double> solution (system_rhs.size ());
-
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- for (unsigned int line = 0;
- line < GeometryInfo<dim - 1>::lines_per_cell;
- ++line)
- {
- // Set up the right hand side.
- system_rhs = 0;
-
- for (unsigned int q_point = 0;
- q_point < n_edge_points; ++q_point)
- {
- const double right_hand_side_value
- = std::sqrt (edge_quadrature.weight
- (q_point))
- * (this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- edge_quadrature_points_full_dim[line][q_point],
- 1) - interpolation_matrix
- (line * source_fe.degree, dof));
- const double tmp
- = 2.0 * edge_quadrature_points[q_point] (0)
- - 1.0;
-
- for (unsigned int i = 0; i < deg; ++i)
- system_rhs (i)
- += right_hand_side_value
- * lobatto_polynomials_grad[i + 1].value
- (tmp);
- }
-
- system_matrix_inv.vmult (solution, system_rhs);
-
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i < solution.size ();
- ++i)
- if (std::abs (solution (i)) > 1e-14)
- interpolation_matrix
- (line * source_fe.degree + i + 1, dof)
- = solution (i);
- }
-
- assembling_matrix.reinit (deg * this->degree,
- n_face_points);
-
- for (unsigned int q_point = 0;
- q_point < n_face_points; ++q_point)
+
+ for (unsigned int i = 0; i < deg; ++i)
{
- const double weight
- = std::sqrt (face_quadrature.weight
- (q_point));
- const Point<dim - 1> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0) - 1.0,
- 2.0 * face_quadrature_points[q_point] (1) - 1.0);
-
- for (unsigned int i = 0; i <= deg; ++i)
- {
- const double tmp
- = weight * legendre_polynomials[i].value
- (quadrature_point (0));
-
- for (unsigned int j = 0; j < deg; ++j)
- assembling_matrix (i * deg + j, q_point)
- = tmp * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
- }
+ const double L_i
+ = legendre_polynomials[i + 1].value
+ (edge_quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0;
+ j < GeometryInfo<dim>::lines_per_face; ++j)
+ system_rhs (i, j) += tmp (j) * L_i;
}
-
- system_matrix.reinit (assembling_matrix.m (),
- assembling_matrix.m ());
- assembling_matrix.mTmult (system_matrix,
- assembling_matrix);
- system_matrix_inv.reinit (system_matrix.m (),
- system_matrix.m ());
- system_matrix_inv.invert (system_matrix);
- solution.reinit (system_matrix.m ());
- system_rhs.reinit (assembling_matrix.m ());
- system_rhs = 0;
-
- for (unsigned int dof = 0; dof < this->dofs_per_face;
- ++dof)
- {
- // Now we project the remaining
- // part on the face shape
- // functions. First on the
- // horizontal ones, then on
- // the vertical ones.
- for (unsigned int q_point = 0;
- q_point < n_face_points; ++q_point)
- {
- const Point<dim> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0)
- - 1.0,
- 2.0 * face_quadrature_points[q_point] (1)
- - 1.0, 0.0);
- double right_hand_side_value
- = this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (face_quadrature_points[q_point] (0),
- face_quadrature_points[q_point] (1), 0.0),
- 1);
-
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int j = 0; j < source_fe.degree;
- ++j)
- right_hand_side_value
- -= interpolation_matrix
+ }
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int i = 0;
+ i < GeometryInfo<dim>::lines_per_face; ++i)
+ for (unsigned int j = 0; j < deg; ++j)
+ if (std::abs (solution (j, i)) > 1e-14)
+ interpolation_matrix (i * source_fe.degree + j + 1,
+ dof) = solution (j, i);
+ }
+
+ const QGauss<2> quadrature (source_fe.degree);
+ const std::vector<Point<2> >&
+ quadrature_points = quadrature.get_points ();
+ const std::vector<Polynomials::Polynomial<double> >&
+ lobatto_polynomials
+ = Polynomials::Lobatto::generate_complete_basis
+ (this->degree);
+ const unsigned int n_boundary_dofs
+ = GeometryInfo<dim>::lines_per_face * source_fe.degree;
+ const unsigned int& n_quadrature_points = quadrature.size ();
+
+ {
+ FullMatrix<double> assembling_matrix (deg * this->degree,
+ n_quadrature_points);
+
+ for (unsigned int q_point = 0; q_point < n_quadrature_points;
+ ++q_point)
+ {
+ const double weight = quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const unsigned L_i = weight
+ * legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+
+ for (unsigned int j = 0; j < deg; ++j)
+ assembling_matrix (i * deg + j, q_point)
+ = L_i * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ }
+ }
+
+ FullMatrix<double> system_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+
+ assembling_matrix.mTmult (system_matrix, assembling_matrix);
+ system_matrix_inv.reinit (system_matrix.m (),
+ system_matrix.m ());
+ system_matrix_inv.invert (system_matrix);
+ }
+
+ solution.reinit (system_matrix_inv.m (), 2);
+ system_rhs.reinit (system_matrix_inv.m (), 2);
+ tmp.reinit (2);
+
+ for (unsigned int dof = 0; dof < this->dofs_per_face; ++dof)
+ {
+ system_rhs = 0.0;
+
+ for (unsigned int q_point = 0;
+ q_point < n_quadrature_points; ++q_point)
+ {
+ Point<dim>
+ quadrature_point
+ (0.5 * (quadrature_points[q_point] (0)
+ + shifts[subface][0]),
+ 0.5 * (quadrature_points[q_point] (1)
+ + shifts[subface][1]), 0.0);
+ tmp (0) = 0.5 * this->shape_value_component
+ (this->face_to_cell_index (dof, 4),
+ quadrature_point, 0);
+ tmp (1) = 0.5 * this->shape_value_component
+ (this->face_to_cell_index (dof, 4),
+ quadrature_point, 1);
+ quadrature_point
+ = Point<dim> (quadrature_points[q_point] (0),
+ quadrature_points[q_point] (1), 0.0);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= deg; ++j)
+ {
+ tmp (0) -= interpolation_matrix
+ ((i + 2) * source_fe.degree + j, dof)
+ * source_fe.shape_value_component
+ ((i + 2) * source_fe.degree + j,
+ quadrature_point, 0);
+ tmp (1) -= interpolation_matrix
(i * source_fe.degree + j, dof)
- * source_fe.shape_value_component
- (i * source_fe.degree + j,
- quadrature_point, 1);
-
- right_hand_side_value
- *= face_quadrature.weight (q_point);
-
- for (unsigned int i = 0; i <= deg; ++i)
- {
- const double tmp
- = right_hand_side_value
- * legendre_polynomials[i].value
- (quadrature_point (0));
-
- for (unsigned int j = 0; j < deg; ++j)
- system_rhs (i * deg + j)
- += tmp
- * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
- }
- }
-
- system_matrix_inv.vmult (solution, system_rhs);
-
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < deg; ++j)
- if (std::abs (solution (i * deg + j)) > 1e-14)
- interpolation_matrix
- ((i + 4) * source_fe.degree + j - i, dof)
- = solution (i * deg + j);
-
- // Set up the right hand side
- // for the vertical shape
- // functions.
- system_rhs = 0;
-
- for (unsigned int q_point = 0;
- q_point < n_face_points; ++q_point)
+ * source_fe.shape_value_component
+ (i * source_fe.degree + j,
+ quadrature_point, 1);
+ }
+
+ tmp *= quadrature.weight (q_point);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ {
+ const double L_i_0 = legendre_polynomials[i].value
+ (quadrature_points[q_point] (0));
+ const double L_i_1 = legendre_polynomials[i].value
+ (quadrature_points[q_point] (1));
+
+ for (unsigned int j = 0; j < deg; ++j)
{
- const Point<dim> quadrature_point
- (2.0 * face_quadrature_points[q_point] (0)
- - 1.0,
- 2.0 * face_quadrature_points[q_point] (1)
- - 1.0, 0.0);
- double right_hand_side_value
- = this->shape_value_component
- (this->face_to_cell_index (dof, 4),
- Point<dim>
- (face_quadrature_points[q_point] (0),
- face_quadrature_points[q_point] (1), 0.0),
- 0);
-
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int j = 0; j < source_fe.degree;
- ++j)
- right_hand_side_value
- -= interpolation_matrix
- ((i + 2) * source_fe.degree + j, dof)
- * source_fe.shape_value_component
- (i * source_fe.degree + j,
- quadrature_point, 0);
-
- right_hand_side_value
- *= face_quadrature.weight (q_point);
-
- for (unsigned int i = 0; i <= deg; ++i)
- {
- const double L_i
- = legendre_polynomials[i].value
- (quadrature_point (0));
- const double tmp
- = right_hand_side_value * L_i;
-
- for (unsigned int j = 0; j < deg; ++j)
- system_rhs (i * deg + j)
- += tmp
- * lobatto_polynomials[j + 2].value
- (quadrature_point (1));
- }
+ system_rhs (i * deg + j, 0) += tmp (0) * L_i_0
+ * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (1));
+ system_rhs (i * deg + j, 1) += tmp (1) * L_i_1
+ * lobatto_polynomials[j + 2].value
+ (quadrature_points[q_point] (0));
}
-
- system_matrix_inv.vmult (solution, system_rhs);
-
- // Add the computed values
- // to the interpolation
- // matrix only, if they are
- // not too small.
- for (unsigned int i = 0; i <= deg; ++i)
- for (unsigned int j = 0; j < deg; ++j)
- if (std::abs (solution (i * deg + j)) > 1e-14)
- interpolation_matrix
- (i + (j + source_fe.degree + 3)
- * source_fe.degree, dof)
- = solution (i * deg + j);
}
}
-
- break;
+
+ system_matrix_inv.mmult (solution, system_rhs);
+
+ for (unsigned int i = 0; i <= deg; ++i)
+ for (unsigned int j = 0; j < deg; ++j)
+ {
+ if (std::abs (solution (i * deg + j, 0)) > 1e-14)
+ interpolation_matrix (i * deg + j + n_boundary_dofs,
+ dof) = solution (i * deg + j,
+ 0);
+
+ if (std::abs (solution (i * deg + j, 1)) > 1e-14)
+ interpolation_matrix (i + (j + deg)
+ * source_fe.degree
+ + n_boundary_dofs, dof)
+ = solution (i * deg + j, 1);
+ }
}
-
- default:
- Assert (false, ExcNotImplemented ());
}
-
+
break;
}