if (data.element_type == MatrixFreeFunctions::tensor_none)
{
const unsigned int n_dofs = data.dofs_per_component_on_cell;
- const unsigned int n_q_points = data.n_q_points_face;
+ const unsigned int n_q_points = data.n_q_points_faces[face_no];
const auto shape_info = data.data.front();
using Eval = EvaluatorTensorProduct<evaluate_general,
if (data.element_type == MatrixFreeFunctions::tensor_none)
{
const unsigned int n_dofs = data.dofs_per_component_on_cell;
- const unsigned int n_q_points = data.n_q_points_face;
+ const unsigned int n_q_points = data.n_q_points_faces[face_no];
const auto shape_info = data.data.front();
using Eval = EvaluatorTensorProduct<evaluate_general,
*/
unsigned char face_orientation;
+ /**
+ * Reference-cell type of the given face: 0 for line or quadrilateral,
+ * 1 for triangle.
+ */
+ unsigned char face_type;
+
/**
* Return the memory consumption of the present data structure.
*/
info.cells_exterior[0] = numbers::invalid_unsigned_int;
info.interior_face_no = f;
info.exterior_face_no = dcell->face(f)->boundary_id();
+ info.face_type =
+ dcell->face(f)->reference_cell() !=
+ dealii::ReferenceCells::get_hypercube<dim - 1>();
info.subface_index =
GeometryInfo<dim>::max_children_per_cell;
info.face_orientation = 0;
else
info.exterior_face_no = cell->neighbor_face_no(face_no);
+ info.face_type = cell->face(face_no)->reference_cell() !=
+ dealii::ReferenceCells::get_hypercube<dim - 1>();
+
info.subface_index = GeometryInfo<dim>::max_children_per_cell;
Assert(neighbor->level() <= cell->level(), ExcInternalError());
if (cell->level() > neighbor->level())
return false;
if (face1.face_orientation != face2.face_orientation)
return false;
+ if (face1.face_type != face2.face_type)
+ return false;
if (active_fe_indices.size() > 0)
{
operator()(const FaceToCellTopology<length> &face1,
const FaceToCellTopology<length> &face2) const
{
+ // check if active FE indices match
+ if (face1.face_type < face2.face_type)
+ return true;
+ else if (face1.face_type > face2.face_type)
+ return false;
+
// check if active FE indices match
if (active_fe_indices.size() > 0)
{
new_faces(face_comparator);
for (const auto &face_type : faces_type)
{
+ macro_face.face_type = faces_in[face_type[0]].face_type;
macro_face.interior_face_no =
faces_in[face_type[0]].interior_face_no;
macro_face.exterior_face_no =
const unsigned int n_q_points,
const bool is_interior_face,
const unsigned int active_fe_index,
- const unsigned int active_quad_index);
+ const unsigned int active_quad_index,
+ const unsigned int face_type);
/**
* Constructor that comes with reduced functionality and works similar as
const unsigned int n_q_points,
const bool is_interior_face,
const unsigned int active_fe_index,
- const unsigned int active_quad_index);
+ const unsigned int active_quad_index,
+ const unsigned int face_type);
/**
* Constructor that comes with reduced functionality and works similar as
const unsigned int n_q_points,
const bool is_interior_face = true,
const unsigned int active_fe_index = numbers::invalid_unsigned_int,
- const unsigned int active_quad_index = numbers::invalid_unsigned_int);
+ const unsigned int active_quad_index = numbers::invalid_unsigned_int,
+ const unsigned int face_type = numbers::invalid_unsigned_int);
/**
* Constructor with reduced functionality for similar usage of FEEvaluation
const unsigned int n_q_points,
const bool is_interior_face = true,
const unsigned int active_fe_index = numbers::invalid_unsigned_int,
- const unsigned int active_quad_index = numbers::invalid_unsigned_int);
+ const unsigned int active_quad_index = numbers::invalid_unsigned_int,
+ const unsigned int face_type = numbers::invalid_unsigned_int);
/**
* Constructor with reduced functionality for similar usage of FEEvaluation
const unsigned int n_q_points,
const bool is_interior_face = true,
const unsigned int active_fe_index = numbers::invalid_unsigned_int,
- const unsigned int active_quad_index = numbers::invalid_unsigned_int);
+ const unsigned int active_quad_index = numbers::invalid_unsigned_int,
+ const unsigned int face_type = numbers::invalid_unsigned_int);
/**
* Constructor with reduced functionality for similar usage of FEEvaluation
const unsigned int n_q_points,
const bool is_interior_face = true,
const unsigned int active_fe_index = numbers::invalid_unsigned_int,
- const unsigned int active_quad_index = numbers::invalid_unsigned_int);
+ const unsigned int active_quad_index = numbers::invalid_unsigned_int,
+ const unsigned int face_type = numbers::invalid_unsigned_int);
/**
* Constructor with reduced functionality for similar usage of FEEvaluation
* DoFHandler/AffineConstraints pair the given evaluator should be attached
* to.
*
+ * @param face_type In the case of a face, indicate its reference-cell type
+ * (0 for line or quadrilateral 1 for triangle).
+ *
* @param active_quad_index If matrix_free was set up with hp::Collection
* objects, this parameter selects the appropriate number of the quadrature
* formula.
const unsigned int quad_no = 0,
const unsigned int first_selected_component = 0,
const unsigned int active_fe_index = numbers::invalid_unsigned_int,
- const unsigned int active_quad_index = numbers::invalid_unsigned_int);
+ const unsigned int active_quad_index = numbers::invalid_unsigned_int,
+ const unsigned int face_type = numbers::invalid_unsigned_int);
/**
* Constructor. Takes all data stored in MatrixFree for a given face range,
const unsigned int n_q_points,
const bool is_interior_face,
const unsigned int active_fe_index_in,
- const unsigned int active_quad_index_in)
+ const unsigned int active_quad_index_in,
+ const unsigned int face_type)
: scratch_data_array(data_in.acquire_scratch_data())
, quad_no(quad_no_in)
, matrix_info(&data_in)
active_quad_index_in :
std::min<unsigned int>(active_fe_index,
mapping_data->descriptor.size() - 1)))
- , descriptor(&mapping_data->descriptor[active_quad_index])
+ , descriptor(
+ &mapping_data->descriptor
+ [is_face ?
+ (active_quad_index * std::max<unsigned int>(1, dim - 1) +
+ (face_type == numbers::invalid_unsigned_int ? 0 : face_type)) :
+ active_quad_index])
, n_quadrature_points(descriptor->n_q_points)
, data(&data_in.get_shape_info(
dof_no,
const unsigned int n_q_points,
const bool is_interior_face,
const unsigned int active_fe_index,
- const unsigned int active_quad_index)
+ const unsigned int active_quad_index,
+ const unsigned int face_type)
: FEEvaluationBaseData<dim, Number, is_face, VectorizedArrayType>(
data_in,
dof_no,
n_q_points,
is_interior_face,
active_fe_index,
- active_quad_index)
+ active_quad_index,
+ face_type)
, n_fe_components(data_in.get_dof_info(dof_no).start_components.back())
, dof_values_initialized(false)
, values_quad_initialized(false)
const unsigned int n_q_points,
const bool is_interior_face,
const unsigned int active_fe_index,
- const unsigned int active_quad_index)
+ const unsigned int active_quad_index,
+ const unsigned int face_type)
: FEEvaluationBase<dim, n_components_, Number, is_face, VectorizedArrayType>(
data_in,
dof_no,
n_q_points,
is_interior_face,
active_fe_index,
- active_quad_index)
+ active_quad_index,
+ face_type)
{}
const unsigned int n_q_points,
const bool is_interior_face,
const unsigned int active_fe_index,
- const unsigned int active_quad_index)
+ const unsigned int active_quad_index,
+ const unsigned int face_type)
: FEEvaluationBase<dim, 1, Number, is_face, VectorizedArrayType>(
data_in,
dof_no,
n_q_points,
is_interior_face,
active_fe_index,
- active_quad_index)
+ active_quad_index,
+ face_type)
{}
const unsigned int n_q_points,
const bool is_interior_face,
const unsigned int active_fe_index,
- const unsigned int active_quad_index)
+ const unsigned int active_quad_index,
+ const unsigned int face_type)
: FEEvaluationBase<dim, dim, Number, is_face, VectorizedArrayType>(
data_in,
dof_no,
n_q_points,
is_interior_face,
active_fe_index,
- active_quad_index)
+ active_quad_index,
+ face_type)
{}
const unsigned int n_q_points,
const bool is_interior_face,
const unsigned int active_fe_index,
- const unsigned int active_quad_index)
+ const unsigned int active_quad_index,
+ const unsigned int face_type)
: FEEvaluationBase<1, 1, Number, is_face, VectorizedArrayType>(
data_in,
dof_no,
n_q_points,
is_interior_face,
active_fe_index,
- active_quad_index)
+ active_quad_index,
+ face_type)
{}
const unsigned int quad_no,
const unsigned int first_selected_component,
const unsigned int active_fe_index,
- const unsigned int active_quad_index)
+ const unsigned int active_quad_index,
+ const unsigned int face_type)
: BaseClass(matrix_free,
dof_no,
first_selected_component,
static_n_q_points,
is_interior_face,
active_fe_index,
- active_quad_index)
+ active_quad_index,
+ face_type)
, dofs_per_component(this->data->dofs_per_component_on_cell)
, dofs_per_cell(this->data->dofs_per_component_on_cell * n_components_)
, n_q_points(this->n_quadrature_points)
quad_no,
first_selected_component,
matrix_free.get_face_active_fe_index(range,
- is_interior_face))
+ is_interior_face),
+ numbers::invalid_unsigned_int,
+ matrix_free.get_face_info(range.first).face_type)
{}
#ifndef DEAL_II_WITH_SIMPLEX_SUPPORT
// currently only non-hp-case...
AssertDimension(mapping_in.size(), 1);
- AssertDimension(mapping_info.face_data[my_q].descriptor.size(),
- 1);
#endif
// We assume that we have the faces sorted by the active FE
{
public:
FaceRangeCompartor(const std::vector<unsigned int> &fe_indices,
- const bool include)
+ const bool include,
+ const bool only_face_type)
: fe_indices(fe_indices)
, include(include)
+ , only_face_type(only_face_type)
{}
template <int vectorization_width>
bool
operator()(const internal::MatrixFreeFunctions::FaceToCellTopology<
- vectorization_width> &face,
- const unsigned int & fe_index)
+ vectorization_width> & face,
+ const std::array<unsigned int, 2> &fe_index)
{
- const unsigned int fe_index_face =
- fe_indices[face.cells_interior[0] / vectorization_width];
+ const unsigned int face_type = face.face_type;
- return fe_index_face < fe_index ||
- (include ? (fe_index_face == fe_index) : false);
+ if (only_face_type)
+ return include ? (face_type <= fe_index[0]) : (face_type < fe_index[0]);
+
+ const std::array<unsigned int, 2> fe_index_face = {
+ {face_type, fe_indices[face.cells_interior[0] / vectorization_width]}};
+
+ return include ? (fe_index_face <= fe_index) : (fe_index_face < fe_index);
}
template <int vectorization_width>
bool
operator()(const internal::MatrixFreeFunctions::FaceToCellTopology<
- vectorization_width> & face,
- const std::pair<unsigned int, unsigned int> &fe_index)
+ vectorization_width> & face,
+ const std::array<unsigned int, 3> &fe_index)
{
- const std::pair<unsigned int, unsigned int> fe_index_face = {
- fe_indices[face.cells_interior[0] / vectorization_width],
- fe_indices[face.cells_exterior[0] / vectorization_width]};
+ const unsigned int face_type = face.face_type;
+
+ if (only_face_type)
+ return include ? (face_type <= fe_index[0]) : (face_type < fe_index[0]);
+
+ const std::array<unsigned int, 3> fe_index_face = {
+ {face_type,
+ fe_indices[face.cells_interior[0] / vectorization_width],
+ fe_indices[face.cells_exterior[0] / vectorization_width]}};
return include ? (fe_index_face <= fe_index) : (fe_index_face < fe_index);
}
private:
const std::vector<unsigned int> &fe_indices;
const bool include;
+ const bool only_face_type;
};
} // namespace
const auto create_inner_face_subrange_hp_by_index =
[&](const std::pair<unsigned int, unsigned int> &range,
+ const unsigned int face_type,
const unsigned int fe_index_interior,
const unsigned int fe_index_exterior,
const unsigned int dof_handler_index =
0) -> std::pair<unsigned int, unsigned int> {
- if (dof_info[dof_handler_index].max_fe_index == 0 ||
- dof_handlers[dof_handler_index]->get_fe_collection().size() ==
- 1)
+ const unsigned int n_face_types =
+ std::max<unsigned int>(dim - 1, 1);
+
+ if ((dof_info[dof_handler_index].max_fe_index == 0 ||
+ dof_handlers[dof_handler_index]->get_fe_collection().size() ==
+ 1) &&
+ n_face_types == 1)
return range;
AssertIndexRange(fe_index_interior,
dof_info[dof_handler_index].max_fe_index);
const std::vector<unsigned int> &fe_indices =
dof_info[dof_handler_index].cell_active_fe_index;
- if (fe_indices.empty() == true)
+ if (fe_indices.empty() == true && n_face_types == 1)
return range;
else
{
+ const bool only_face_type =
+ dof_info[dof_handler_index].max_fe_index == 0 ||
+ dof_handlers[dof_handler_index]->get_fe_collection().size() ==
+ 1 ||
+ fe_indices.empty() == true;
+
std::pair<unsigned int, unsigned int> return_range;
return_range.first =
- std::lower_bound(face_info.faces.begin() + range.first,
- face_info.faces.begin() + range.second,
- std::pair<unsigned int, unsigned int>{
- fe_index_interior, fe_index_exterior},
- FaceRangeCompartor(fe_indices, false)) -
+ std::lower_bound(
+ face_info.faces.begin() + range.first,
+ face_info.faces.begin() + range.second,
+ std::array<unsigned int, 3>{
+ {face_type, fe_index_interior, fe_index_exterior}},
+ FaceRangeCompartor(fe_indices, false, only_face_type)) -
face_info.faces.begin();
return_range.second =
- std::lower_bound(face_info.faces.begin() + return_range.first,
- face_info.faces.begin() + range.second,
- std::pair<unsigned int, unsigned int>{
- fe_index_interior, fe_index_exterior},
- FaceRangeCompartor(fe_indices, true)) -
+ std::lower_bound(
+ face_info.faces.begin() + return_range.first,
+ face_info.faces.begin() + range.second,
+ std::array<unsigned int, 3>{
+ {face_type, fe_index_interior, fe_index_exterior}},
+ FaceRangeCompartor(fe_indices, true, only_face_type)) -
face_info.faces.begin();
Assert(return_range.first >= range.first &&
return_range.second <= range.second,
task_info.face_partition_data[i + 1]};
if (range.second > range.first)
- for (unsigned int i = 0; i < this->n_active_fe_indices();
- ++i)
- for (unsigned int j = 0; j < this->n_active_fe_indices();
- ++j)
- {
- const auto subrange =
- create_inner_face_subrange_hp_by_index(range, i, j);
+ for (unsigned int t = 0;
+ t < std::max<unsigned int>(dim - 1, 1);
+ ++t)
+ for (unsigned int i = 0; i < this->n_active_fe_indices();
+ ++i)
+ for (unsigned int j = 0;
+ j < this->n_active_fe_indices();
+ ++j)
+ {
+ const auto subrange =
+ create_inner_face_subrange_hp_by_index(range,
+ t,
+ i,
+ j);
- if (subrange.second <= subrange.first)
- continue;
+ if (subrange.second <= subrange.first)
+ continue;
- data.push_back(subrange.first);
- data.push_back(subrange.second);
- }
+ data.push_back(subrange.first);
+ data.push_back(subrange.second);
+ }
}
ptr.push_back(data.size() / 2);
const auto create_boundary_face_subrange_hp_by_index =
[&](const std::pair<unsigned int, unsigned int> &range,
+ const unsigned int face_type,
const unsigned int fe_index,
const unsigned int dof_handler_index =
0) -> std::pair<unsigned int, unsigned int> {
- if (dof_info[dof_handler_index].max_fe_index == 0 ||
- dof_handlers[dof_handler_index]->get_fe_collection().size() ==
- 1)
+ const unsigned int n_face_types =
+ std::max<unsigned int>(dim - 1, 1);
+
+ if ((dof_info[dof_handler_index].max_fe_index == 0 ||
+ dof_handlers[dof_handler_index]->get_fe_collection().size() ==
+ 1) &&
+ n_face_types == 1)
return range;
AssertIndexRange(fe_index,
dof_info[dof_handler_index].max_fe_index);
const std::vector<unsigned int> &fe_indices =
dof_info[dof_handler_index].cell_active_fe_index;
- if (fe_indices.empty() == true)
+ if (fe_indices.empty() == true && n_face_types == 1)
return range;
else
{
+ const bool only_face_type =
+ dof_info[dof_handler_index].max_fe_index == 0 ||
+ dof_handlers[dof_handler_index]->get_fe_collection().size() ==
+ 1 ||
+ fe_indices.empty() == true;
+
std::pair<unsigned int, unsigned int> return_range;
return_range.first =
- std::lower_bound(face_info.faces.begin() + range.first,
- face_info.faces.begin() + range.second,
- fe_index,
- FaceRangeCompartor(fe_indices, false)) -
+ std::lower_bound(
+ face_info.faces.begin() + range.first,
+ face_info.faces.begin() + range.second,
+ std::array<unsigned int, 2>{{face_type, fe_index}},
+ FaceRangeCompartor(fe_indices, false, only_face_type)) -
face_info.faces.begin();
return_range.second =
- std::lower_bound(face_info.faces.begin() + return_range.first,
- face_info.faces.begin() + range.second,
- fe_index,
- FaceRangeCompartor(fe_indices, true)) -
+ std::lower_bound(
+ face_info.faces.begin() + return_range.first,
+ face_info.faces.begin() + range.second,
+ std::array<unsigned int, 2>{{face_type, fe_index}},
+ FaceRangeCompartor(fe_indices, true, only_face_type)) -
face_info.faces.begin();
Assert(return_range.first >= range.first &&
return_range.second <= range.second,
task_info.boundary_partition_data[i + 1]};
if (range.second > range.first)
- for (unsigned int i = 0; i < this->n_active_fe_indices();
- ++i)
- {
- const auto cell_subrange =
- create_boundary_face_subrange_hp_by_index(range, i);
+ for (unsigned int t = 0;
+ t < std::max<unsigned int>(dim - 1, 1);
+ ++t)
+ for (unsigned int i = 0; i < this->n_active_fe_indices();
+ ++i)
+ {
+ const auto cell_subrange =
+ create_boundary_face_subrange_hp_by_index(range,
+ t,
+ i);
- if (cell_subrange.second <= cell_subrange.first)
- continue;
+ if (cell_subrange.second <= cell_subrange.first)
+ continue;
- data.push_back(cell_subrange.first);
- data.push_back(cell_subrange.second);
- }
+ data.push_back(cell_subrange.first);
+ data.push_back(cell_subrange.second);
+ }
}
ptr.push_back(data.size() / 2);
const auto fe_poly = dynamic_cast<const FE_Poly<dim, dim> *>(&fe);
- if (dynamic_cast<const FE_SimplexP<dim, dim> *>(&fe) != nullptr ||
- dynamic_cast<const FE_SimplexDGP<dim, dim> *>(&fe) != nullptr ||
- dynamic_cast<const FE_WedgeP<dim, dim> *>(&fe) != nullptr ||
- dynamic_cast<const FE_PyramidP<dim, dim> *>(&fe) != nullptr)
+ if (dynamic_cast<const FE_SimplexPoly<dim, dim> *>(&fe) != nullptr ||
+ dynamic_cast<const FE_Wedge<dim, dim> *>(&fe) != nullptr ||
+ dynamic_cast<const FE_Pyramid<dim, dim> *>(&fe) != nullptr)
{
scalar_lexicographic.resize(fe.n_dofs_per_cell());
for (unsigned int i = 0; i < scalar_lexicographic.size(); ++i)