+++ /dev/null
-Changed: The function previously called
-FECollection::find_least_face_dominating_fe()
-is now named
-FECollection::find_least_face_dominating_fe_in_collection().
-<br>
-(Marc Fehling, 2018/10/08)
--- /dev/null
+Changed: Tasks of member function
+hp::FECollection::find_face_dominating_fe_in_subset() are now divided
+into two functions hp::FECollection::find_common_subspace()
+and hp::FECollection::find_dominated_fe().
+<br>
+(Marc Fehling, 2019/04/08)
+++ /dev/null
-New: Member function hp::FECollection::find_face_dominating_fe_in_subset()
-returns the index of the most dominating finite element out of a given
-set of indices.
-<br>
-(Marc Fehling, 2018/10/05)
--- /dev/null
+New: Member function hp::FECollection::find_common_subspace()
+returns a set of indices from the full FECollection whose associated
+finite elements dominate all elements of a given set of indices.
+<br>
+(Marc Fehling, 2019/04/08)
--- /dev/null
+New: Member function hp::FECollection::find_encapsulating_space()
+returns a set of indices from the full FECollection whose associated
+finite elements are dominated by all elements of a given set of indices.
+<br>
+(Marc Fehling, 2019/04/08)
--- /dev/null
+New: Member function hp::FECollection::find_dominating_fe()
+returns the index of the most dominating finite element out of a given
+set of indices.
+<br>
+(Marc Fehling, 2019/04/08)
--- /dev/null
+New: Member function hp::FECollection::find_dominated_fe()
+returns the index of the least dominating finite element out of a given
+set of indices.
+<br>
+(Marc Fehling, 2019/04/08)
* correpsonding `active_fe_index`. Further, if refinement is involved,
* data will be packed on the parent cell with its `active_fe_index` and
* unpacked later with the same index on its children. If cells get
- * coarsened into one, data will be packed on the latter with the least
- * dominating `active_fe_index` amongst its children, as determined by the
- * function hp::FECollection::find_least_face_dominating_fe_in_collection(),
- * and unpacked on the same cell with the same index.
+ * coarsened into one, data will be packed on the children with the least
+ * dominating finite element of their common subspace, and unpacked on the
+ * parent with this particular finite element.
*
* Transferring a solution across refinement works exactly like in the
* non-hp case. However, when considering serialization, we also have to
* - When coarsening cells, the (now active) parent cell will be assigned
* an active FE index that is determined from its (no longer active)
* children, following the FiniteElementDomination logic: We choose the
- * least dominant among all elements that dominate all of those used on the
- * children. See FECollection::find_least_dominating_fe_in_collection() for
- * further information on this topic.
+ * least dominant element of their common subspace. See
+ * hp::FECollection::find_common_subspace() and
+ * hp::FECollection::find_dominted_fe() for further information on this
+ * topic.
*
* @note Finite elements need to be assigned to each cell by calling
* distribute_dofs() first to make this functionality available.
* elements is empty, and we can not find a least dominant one among it. The
* return value is therefore numbers::invalid_unsigned_int.
*
- * @deprecated Use
- * hp::FECollection::find_least_face_dominating_fe_in_collection(fes, 1)
- * instead.
+ * @deprecated This function has been succeeded by
+ * `hp::FECollection::find_dominating_fe_extended(fes, 1)`.
+ * To recreate its exact behavior, use code such as
+ * `fe_collection.find_dominated_fe(
+ * fe_collection.find_common_fes(fes, 1), 1)`.
*/
DEAL_II_DEPRECATED unsigned int
find_least_face_dominating_fe(const std::set<unsigned int> &fes) const;
/**
- * Try to find a least dominant finite element inside this FECollection
- * which dominates all of those finite elements in the current collection
- * indexed by the numbers provided through @p fes . In other words, we
- * first form the set of elements in this collection that dominate
- * all of the ones that are indexed by the argument @p fes, and then
- * within that set of dominating elements, we find the <i>least</i>
- * dominant one.
+ * Return the indices of finite elements in this FECollection that dominate
+ * all elements associated with the provided set of indices @p fes.
*
- * For example, if an FECollection consists of
- * `{FE_Q(1),FE_Q(2),FE_Q(3),FE_Q(4)}` elements
- * and the argument @p fes equals `{2,3}`, then the set of dominating
- * elements consists of `{0,1,2}`, of which `2` (i.e., the `FE_Q(3)`) is the
- * least dominant one, and then that's what the function returns.
+ * You may find information about the domination behavior of finite elements
+ * in their respecitve class documentation or in the implementation of their
+ * inherited member function FiniteElement::compare_for_domination().
+ * Consider that a finite element may or may not dominate itself (e.g.
+ * FE_Nothing elements).
*
- * On the other hand, if the FECollection consists of
- * `{FE_Q(1)xFE_Q(1),FE_Q(2)xFE_Q(2),FE_Q(2)xFE_Q(3),FE_Q(3)xFE_Q(2)}`
- * elements and the argument is again @p fes equal to `{2,3}`, then the set of dominating
- * elements consists of `{0,1}` because now neither of the last two
- * elements dominates the other, of which `1` (i.e., the `FE_Q(2)xFE_Q(2)`)
- * is the least dominant one -- so that's what the function returns in
- * this case.
+ * For example, if a FECollection consists of
+ * `{FE_Q(1),FE_Q(2),FE_Q(3),FE_Q(4)}` elements and we are looking for the
+ * finite elements that dominate the middle elements of this
+ * collection (i.e., @p fes is `{1,2}`), then the answer is `{FE_Q(1),FE_Q(2)`
+ * and therefore this function will return their indices in the
+ * FECollection, namely `{0,1}`.
*
- * For the purpose of this function by domination we consider either
- * FiniteElementDomination::Domination::this_element_dominates or
- * FiniteElementDomination::Domination::either_element_can_dominate;
- * therefore the element can dominate itself. Thus, if an FECollection
- * contains `{FE_Q(1),FE_Q(2),FE_Q(3),FE_Q(4)}` and @p fes only has
- * a single element `{3}`, then the function returns 3.
+ * The @p codim parameter describes the codimension of the investigated
+ * subspace and specifies that it is subject to this comparison. See
+ * FiniteElement::compare_for_domination() for more information.
+ */
+ std::set<unsigned int>
+ find_common_fes(const std::set<unsigned int> &fes,
+ const unsigned int codim = 0) const;
+
+ /**
+ * Return the indices of finite elements in this FECollection that are
+ * dominated by all elements associated with the provided set of indices @p fes.
*
- * If the function is not able to find a finite element that satisfies
- * the description above, the function returns
- * numbers::invalid_unsigned_int. An example would go like this:
- * If the FECollection consists of `{FE_Nothing x FE_Nothing, FE_Q(1)xFE_Q(2), FE_Q(2)xFE_Q(1)}` with @p fes as `{1}`,
- * the function will not find a most dominating element as the default
- * behavior of FE_Nothing is to return
- * FiniteElementDomination::no_requirements when comparing for face
- * domination with any other element. In other words, the set of dominating
- * elements is empty, and we can not find a least dominant one among it. The
- * return value is therefore numbers::invalid_unsigned_int.
+ * You may find information about the domination behavior of finite elements
+ * in their respecitve class documentation or in the implementation of their
+ * inherited member function FiniteElement::compare_for_domination().
+ * Consider that a finite element may or may not dominate itself (e.g.
+ * FE_Nothing elements).
+ *
+ * For example, if a FECollection consists of
+ * `{FE_Q(1),FE_Q(2),FE_Q(3),FE_Q(4)}` elements and we are looking for the
+ * finite elements that are dominated by the middle elements of this
+ * collection (i.e., @p fes is `{1,2}`), then the answer is `{FE_Q(3),FE_Q(4)`
+ * and therefore this function will return their indices in the
+ * FECollection, namely `{2,3}`.
+ *
+ * The @p codim parameter describes the codimension of of the investigated
+ * subspace and specifies that it is subject to this comparison. See
+ * FiniteElement::compare_for_domination() for more information.
+ */
+ std::set<unsigned int>
+ find_enclosing_fes(const std::set<unsigned int> &fes,
+ const unsigned int codim = 0) const;
+
+ /**
+ * Return the index of a finite element from the provided set of indices @p fes
+ * that dominates all other elements of this very set.
+ *
+ * You may find information about the domination behavior of finite elements
+ * in their respecitve class documentation or in the implementation of their
+ * inherited member function FiniteElement::compare_for_domination().
+ * Consider that a finite element may or may not dominate itself (e.g.
+ * FE_Nothing elements).
+ *
+ * If this set consists of exactly one element, we consider it to be
+ * the dominating one and return its corresponding index. Further, if the
+ * function is not able to find a finite element at all, it returns
+ * numbers::invalid_unsigned_int.
+ *
+ * For example, if a FECollection consists of
+ * `{FE_Q(1),FE_Q(2),FE_Q(3),FE_Q(4)}` elements and we are looking for the
+ * dominating finite element among the middle elements of this
+ * collection (i.e., @p fes is `{1,2}`), then the answer is FE_Q(2)
+ * and therefore this function will return its index in the
+ * FECollection, namely `1`.
+ *
+ * It is of course possible that there is more than one element that
+ * dominates all selected elements. For example, if the collection consists
+ * of `{FE_Q(1),FE_Q(1),FE_Q(2),FE_Q(2)}` and `fes` covers all indices,
+ * then one could return zero or one. In that case, the function returns
+ * either `0` or `1` since there is no tie-breaker between the two.
*
* The @p codim parameter describes the codimension of of the investigated
- * subspace and specifies that it is subject to this comparison.
+ * subspace and specifies that it is subject to this comparison. See
+ * FiniteElement::compare_for_domination() for more information.
*/
unsigned int
- find_least_dominating_fe_in_collection(const std::set<unsigned int> &fes,
- const unsigned int codim = 0) const;
+ find_dominating_fe(const std::set<unsigned int> &fes,
+ const unsigned int codim = 0) const;
/**
- * Try to find a most face dominating finite element inside the subset of
- * fe_indices @p fes as part of this FECollection. For example, if an
- * FECollection consists of `{FE_Q(1),FE_Q(2),FE_Q(3),FE_Q(4)}` elements
- * and we are looking for the most face dominating finite element among the
- * last two elements of this collection (i.e., @p fes is `{2,3}`), then the
- * answer is FE_Q(3) and therefore this function will return its index in
- * the FECollection, namely `2`.
+ * Return the index of a finite element from the provided set of indices @p fes
+ * that is dominated by all other elements of this very set.
*
- * This function differs from find_least_dominating_fe_in_collection() in
- * such a way that it looks for the most dominating finite element within
- * the given
- * subset @p fes, instead of finding a finite element in the whole
- * FECollection that dominates all elements of the subset @p fes.
+ * You may find information about the domination behavior of finite elements
+ * in their respecitve class documentation or in the implementation of their
+ * inherited member function FiniteElement::compare_for_domination().
+ * Consider that a finite element may or may not dominate itself (e.g.
+ * FE_Nothing elements).
*
- * For the purpose of this function by domination we consider either
- * FiniteElementDomination::Domination::this_element_dominates or
- * FiniteElementDomination::Domination::either_element_can_dominate;
- * therefore the element can dominate itself. Thus, if an FECollection
- * contains `{FE_Q(1),FE_Q(2),FE_Q(3),FE_Q(4)}` and @p fes only has
- * a single element `{3}`, then the function returns 3.
+ * If this set consists of exactly one element, we consider it to be
+ * the dominated one and return its corresponding index. Further, if the
+ * function is not able to find a finite element at all, it returns
+ * numbers::invalid_unsigned_int.
+ *
+ * For example, if a FECollection consists of
+ * `{FE_Q(1),FE_Q(2),FE_Q(3),FE_Q(4)}` elements and we are looking for the
+ * dominated finite element among the middle elements of this
+ * collection (i.e., @p fes is `{1,2}`), then the answer is FE_Q(3)
+ * and therefore this function will return its index in the
+ * FECollection, namely `2`.
+ *
+ * It is of course possible that there is more than one element that is
+ * dominated by all selected elements. For example, if the collection
+ * consists of `{FE_Q(1),FE_Q(1),FE_Q(2),FE_Q(2)}` and `fes` covers all
+ * indices, then one could return two or three. In that case, the function
+ * returns either `2` or `3` since there is no tie-breaker between the two.
+ *
+ * The @p codim parameter describes the codimension of of the investigated
+ * subspace and specifies that it is subject to this comparison. See
+ * FiniteElement::compare_for_domination() for more information.
+ */
+ unsigned int
+ find_dominated_fe(const std::set<unsigned int> &fes,
+ const unsigned int codim = 0) const;
+
+ /**
+ * Return the index of a finite element from the provided set of indices @p fes
+ * that dominates all other elements of this very set. If we do not succeed,
+ * we extend our search on the whole collection by picking the least
+ * dominating one, which is the element that describes the largest finite
+ * element space of which all of the finite elements of the
+ * provided set @p fes are part of.
+ *
+ * You may find information about the domination behavior of finite elements
+ * in their respecitve class documentation or in the implementation of their
+ * inherited member function FiniteElement::compare_for_domination().
+ * Consider that a finite element may or may not dominate itself (e.g.
+ * FE_Nothing elements).
+ *
+ * If this set consists of exactly one element, we consider it to be
+ * the dominated one and return its corresponding index. Further, if the
+ * function is not able to find a finite element at all, it returns
+ * numbers::invalid_unsigned_int.
+ *
+ * The @p codim parameter describes the codimension of of the investigated
+ * subspace and specifies that it is subject to this comparison. See
+ * FiniteElement::compare_for_domination() for more information.
+ */
+ unsigned int
+ find_dominating_fe_extended(const std::set<unsigned int> &fes,
+ const unsigned int codim = 0) const;
+
+ /**
+ * Return the index of a finite element from the provided set of indices @p fes
+ * that is dominated by all other elements of this very set. If we do not
+ * succeed, we extend our search on the whole collection by picking the most
+ * dominated one, which is the element that describes the smallest finite
+ * element space which includes all finite elements of the provided set @p fes.
+ *
+ * You may find information about the domination behavior of finite elements
+ * in their respecitve class documentation or in the implementation of their
+ * inherited member function FiniteElement::compare_for_domination().
+ * Consider that a finite element may or may not dominate itself (e.g.
+ * FE_Nothing elements).
*
- * If the function is not able to find a finite element, the function
- * returns numbers::invalid_unsigned_int.
+ * If this set consists of exactly one element, we consider it to be
+ * the dominating one and return its corresponding index. Further, if the
+ * function is not able to find a finite element at all, it returns
+ * numbers::invalid_unsigned_int.
*
* The @p codim parameter describes the codimension of of the investigated
- * subspace and specifies that it is subject to this comparison.
+ * subspace and specifies that it is subject to this comparison. See
+ * FiniteElement::compare_for_domination() for more information.
*/
unsigned int
- find_dominating_fe_in_subset(const std::set<unsigned int> &fes,
- const unsigned int codim = 0) const;
+ find_dominated_fe_extended(const std::set<unsigned int> &fes,
+ const unsigned int codim = 0) const;
/**
* Set functions determining the hierarchy of finite elements, i.e. a
fe_indices_children.insert(
cell->child(child_index)->active_fe_index());
- fe_index =
- dof_handler->get_fe_collection()
- .find_least_dominating_fe_in_collection(fe_indices_children,
- /*codim=*/0);
+ unsigned int fe_index =
+ dof_handler->get_fe_collection().find_dominating_fe_extended(
+ fe_indices_children, /*codim=*/0);
Assert(fe_index != numbers::invalid_unsigned_int,
ExcMessage(
DoFHandlerType::space_dimension>::CELL_COARSEN:
{
// In case of coarsening, we need to find a suitable fe index
- // for the parent cell. We choose the 'least face dominating
- // fe index' on all children from the associated FECollection.
+ // for the parent cell. We choose the 'least dominating fe'
+ // on all children from the associated FECollection.
std::set<unsigned int> fe_indices_children;
for (unsigned int child_index = 0;
child_index < GeometryInfo<dim>::max_children_per_cell;
cell->child(child_index)->active_fe_index());
fe_index = dof_handler->get_fe_collection()
- .find_least_dominating_fe_in_collection(
- fe_indices_children, /*codim=*/0);
+ .find_dominating_fe_extended(fe_indices_children,
+ /*codim=*/0);
Assert(
fe_index != numbers::invalid_unsigned_int,
// find out which is the most dominating finite
// element of the ones that are used on this vertex
unsigned int most_dominating_fe_index =
- dof_handler.get_fe_collection()
- .find_dominating_fe_in_subset(fe_indices,
- /*codim=*/dim);
+ dof_handler.get_fe_collection().find_dominating_fe(
+ fe_indices,
+ /*codim*/ dim);
// if we haven't found a dominating finite element,
// choose the very first one to be dominant
unsigned int dominating_fe_index =
dof_handler.get_fe_collection()
- .find_dominating_fe_in_subset(
- fe_indices, /*codim=*/dim - 1);
+ .find_dominating_fe(fe_indices,
+ /*codim=*/dim - 1);
unsigned int other_fe_index =
numbers::invalid_unsigned_int;
// find out which is the most dominating finite element of
// the ones that are used on this line
const unsigned int most_dominating_fe_index =
- dof_handler.get_fe_collection()
- .find_dominating_fe_in_subset(fe_indices,
- /*codim=*/dim - 1);
+ dof_handler.get_fe_collection().find_dominating_fe(
+ fe_indices,
+ /*codim=*/dim - 1);
// if we found the most dominating element, then use this
// to eliminate some of the degrees of freedom by
// find out which is the most dominating finite
// element of the ones that are used on this quad
const unsigned int most_dominating_fe_index =
- dof_handler.get_fe_collection()
- .find_dominating_fe_in_subset(fe_indices,
- /*codim=*/dim - 2);
+ dof_handler.get_fe_collection().find_dominating_fe(
+ fe_indices,
+ /*codim=*/dim - 2);
// if we found the most dominating element, then use
// this to eliminate some of the degrees of freedom
// find out which is the most dominating finite
// element of the ones that are used on this vertex
const unsigned int most_dominating_fe_index =
- dof_handler.get_fe_collection()
- .find_dominating_fe_in_subset(fe_indices,
- /*codim=*/dim);
+ dof_handler.get_fe_collection().find_dominating_fe(
+ fe_indices,
+ /*codim=*/dim);
// if we found the most dominating element, then use
// this to eliminate some of the degrees of freedom
unsigned int dominating_fe_index =
dof_handler.get_fe_collection()
- .find_dominating_fe_in_subset(
- fe_indices, /*codim*/ dim - 1);
+ .find_dominating_fe(fe_indices,
+ /*codim*/ dim - 1);
unsigned int other_fe_index =
numbers::invalid_unsigned_int;
// find out which is the most dominating finite element of
// the ones that are used on this line
const unsigned int most_dominating_fe_index =
- dof_handler.get_fe_collection()
- .find_dominating_fe_in_subset(fe_indices,
- /*codim=*/dim - 1);
+ dof_handler.get_fe_collection().find_dominating_fe(
+ fe_indices,
+ /*codim=*/dim - 1);
// if we found the most dominating element, then use this
// to eliminate some of the degrees of freedom by
// find out which is the most dominating finite
// element of the ones that are used on this quad
const unsigned int most_dominating_fe_index =
- dof_handler.get_fe_collection()
- .find_dominating_fe_in_subset(fe_indices,
- /*codim=*/dim - 2);
+ dof_handler.get_fe_collection().find_dominating_fe(
+ fe_indices,
+ /*codim=*/dim - 2);
// if we found the most dominating element, then use
// this to eliminate some of the degrees of freedom
// we first have to find the finite element that is able
// to generate a space that all the other ones can be
// constrained to. At this point we potentially have
- // different scenarios: 1) sub-faces dominate mother
- // face and there is a dominating FE among sub faces. We
- // could loop over sub faces to find the needed FE
- // index. However, this will not work in the case when
+ // different scenarios:
+ //
+ // 1) sub-faces dominate mother face and there is a
+ // dominating FE among sub faces. We could loop over sub
+ // faces to find the needed FE index. However, this will
+ // not work in the case when ...
+ //
// 2) there is no dominating FE among sub faces (e.g.
// Q1xQ2 vs Q2xQ1), but subfaces still dominate mother
// face (e.g. Q2xQ2). To cover this case we would have
- // to use find_least_dominating_fe_in_collection()
- // of FECollection with fe_indices of sub faces. 3)
- // Finally, it could happen that we got here because
+ // to find the least dominating element amongst all
+ // finite elements on sub faces.
+ //
+ // 3) Finally, it could happen that we got here because
// neither_element_dominates (e.g. Q1xQ1xQ2 and Q1xQ2xQ1
// for subfaces and Q2xQ1xQ1 for mother face). This
- // requires usage of
- // find_least_dominating_fe_in_collection() with
- // fe_indices of sub-faces and the mother face.
+ // requires finding the least dominating element amongst
+ // all finite elements on sub faces and the mother face.
+ //
// Note that the last solution covers the first two
// scenarios, thus we stick with it assuming that we
// won't lose much time/efficiency.
- const unsigned int dominating_fe_index =
- fe_collection.find_least_dominating_fe_in_collection(
- fe_ind_face_subface, /*codim=*/1);
+ unsigned int dominating_fe_index =
+ fe_collection.find_dominating_fe_extended(
+ fe_ind_face_subface,
+ /*codim=*/1);
+
AssertThrow(
dominating_fe_index != numbers::invalid_unsigned_int,
ExcMessage(
fes.insert(neighbor_fe_index);
const dealii::hp::FECollection<dim, spacedim>
&fe_collection = dof_handler.get_fe_collection();
- const unsigned int dominating_fe_index =
- fe_collection
- .find_least_dominating_fe_in_collection(
- fes, /*codim=*/1);
+
+ unsigned int dominating_fe_index =
+ fe_collection.find_dominating_fe_extended(
+ fes,
+ /*codim=*/1);
AssertThrow(
dominating_fe_index !=
/*
* Treat interface between enriched cells specially,
* until #1496 (https://github.com/dealii/dealii/issues/1496) is resolved.
- * Each time we build constraints at the
- * interface between two different FE_Enriched, we look for the least
- * dominating FE via
- * hp::FECollection::find_least_dominating_fe_in_collection(). If we don't
- * take further actions, we may find a dominating FE that is too
- * restrictive, i.e. enriched FE consisting of only FE_Nothing. New
- * elements needs to be added to FECollection object to help find the
- * correct enriched FE underlying the spaces in the adjacent cells. This
- * is done by creating an appropriate set in fe_sets and a call to the
- * function make_fe_collection_from_colored_enrichments at a later stage.
+ * Each time we build constraints at the interface between two different
+ * FE_Enriched, we look for the least dominating FE of their common
+ * subspace via hp::FECollection::find_common_subspace() and
+ * hp::FECollection::find_dominated_fe(). If we don't take further
+ * actions, we may find a dominating FE that is too restrictive, i.e.
+ * enriched FE consisting of only FE_Nothing. New elements needs to be
+ * added to FECollection object to help find the correct enriched FE
+ * underlying the spaces in the adjacent cells. This is done by creating
+ * an appropriate set in fe_sets and a call to the function
+ * make_fe_collection_from_colored_enrichments at a later stage.
*
* Consider a domain with three predicates and hence with three different
* enrichment functions. Let the enriched finite element of a cell with
* the cell. If the interface has enriched FE [1 0 1] and [0 1 1]
* on adjacent cells, an enriched FE [0 0 1] should exist and is
* found as the least dominating finite element for the two cells by
- * DoFTools::make_hanging_node_constraints using a call to the function
- * hp::FECollection::find_least_dominating_fe_in_collection().
- * Denoting the fe set in adjacent cells as {1,3} and {2,3}, this
- * implies that an fe set {3} needs to be added! Based on the
- * predicate configuration, this may not be automatically done without
- * the following special treatment.
+ * DoFTools::make_hanging_node_constraints, using the above mentioned
+ * hp::FECollection functions. Denoting the fe set in adjacent cells as
+ * {1,3} and {2,3}, this implies that an fe set {3} needs to be added!
+ * Based on the predicate configuration, this may not be automatically
+ * done without the following special treatment.
*/
// loop through faces
* their childrean and thus will be stored as such.
*
* On cells to be coarsened, the active_fe_index on parent cells will be
- * determined by the least dominating finite element of its children. We
- * will thus assign the corresponding fe_index to the parent cell. See
- * documentation of
- * FECollection::find_least_dominating_fe_in_collection() for further
- * information.
+ * determined by the least dominating finite element of its children's
+ * common subspace. We will thus assign the corresponding fe_index to
+ * the parent cell. See documentation of
+ * hp::FECollection::find_common_subspace() and
+ * hp::FECollection::find_dominated_fe() for further information.
*/
template <int dim, int spacedim>
static void
fe_indices_children.insert(
parent->child(child_index)->active_fe_index());
}
+ Assert(!fe_indices_children.empty(),
+ ExcInternalError());
const unsigned int fe_index =
- dof_handler.fe_collection
- .find_least_dominating_fe_in_collection(
- fe_indices_children, /*codim=*/0);
+ dof_handler.fe_collection.find_dominating_fe_extended(
+ fe_indices_children,
+ /*codim=*/0);
Assert(
fe_index != numbers::invalid_unsigned_int,
FECollection<dim, spacedim>::find_least_face_dominating_fe(
const std::set<unsigned int> &fes) const
{
- return find_least_dominating_fe_in_collection(fes, /*codim*/ 1);
+ return find_dominated_fe(find_common_fes(fes, /*codim*/ 1),
+ /*codim*/ 1);
}
template <int dim, int spacedim>
- unsigned int
- FECollection<dim, spacedim>::find_least_dominating_fe_in_collection(
+ std::set<unsigned int>
+ FECollection<dim, spacedim>::find_common_fes(
const std::set<unsigned int> &fes,
const unsigned int codim) const
{
+ // Validate user inputs.
Assert(codim <= dim, ExcImpossibleInDim(dim));
+ for (const auto &fe : fes)
+ {
+ (void)fe;
+ AssertIndexRange(fe, finite_elements.size());
+ }
- for (const unsigned int fe_index : fes)
+ // Check if any element of this FECollection is able to dominate all
+ // elements of @p fes. If one was found, we add it to the set of
+ // dominating elements.
+ std::set<unsigned int> dominating_fes;
+ for (unsigned int current_fe = 0; current_fe < finite_elements.size();
+ ++current_fe)
{
- (void)fe_index;
- AssertIndexRange(fe_index, finite_elements.size());
+ // Check if current_fe can dominate all elements in @p fes.
+ FiniteElementDomination::Domination domination =
+ FiniteElementDomination::no_requirements;
+ for (const auto &other_fe : fes)
+ domination =
+ domination & finite_elements[current_fe]->compare_for_domination(
+ *finite_elements[other_fe], codim);
+
+ // If current_fe dominates, add it to the set.
+ if ((domination == FiniteElementDomination::this_element_dominates) ||
+ (domination == FiniteElementDomination::either_element_can_dominate
+ /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
+ dominating_fes.insert(current_fe);
}
+ return dominating_fes;
+ }
+
- // If the set of elements to be dominated contains only a single element X,
- // then by definition the dominating set contains this single element X
- // (because each element can dominate itself). There may also be others,
- // say Y1...YN. Next you have to find one or more elements in the dominating
- // set {X,Y1...YN} that is the weakest. Well, you can't find one that is
- // weaker than X because if it were, it would not dominate X. In other
- // words, X is guaranteed to be in the subset of {X,Y1...YN} of weakest
- // dominating elements. Since we only guarantee that the function returns
- // one of them, we may as well return X right away.
- if (fes.size() == 1)
- return *fes.begin();
- std::set<unsigned int> candidate_fes;
+ template <int dim, int spacedim>
+ std::set<unsigned int>
+ FECollection<dim, spacedim>::find_enclosing_fes(
+ const std::set<unsigned int> &fes,
+ const unsigned int codim) const
+ {
+ // Validate user inputs.
+ Assert(codim <= dim, ExcImpossibleInDim(dim));
+ for (const auto &fe : fes)
+ {
+ (void)fe;
+ AssertIndexRange(fe, finite_elements.size());
+ }
- // first loop over all FEs and check which can dominate those given in @p fes:
- for (unsigned int cur_fe = 0; cur_fe < finite_elements.size(); ++cur_fe)
+ // Check if any element of this FECollection is dominated by all
+ // elements of @p fes. If one was found, we add it to the set of
+ // dominated elements.
+ std::set<unsigned int> dominated_fes;
+ for (unsigned int current_fe = 0; current_fe < finite_elements.size();
+ ++current_fe)
{
+ // Check if current_fe is dominated by all other elements in @p fes.
FiniteElementDomination::Domination domination =
FiniteElementDomination::no_requirements;
- // check if cur_fe can dominate all FEs in @p fes:
for (const auto &other_fe : fes)
domination =
- domination & finite_elements[cur_fe]->compare_for_domination(
+ domination & finite_elements[current_fe]->compare_for_domination(
*finite_elements[other_fe], codim);
- // if we found dominating element, keep them in a set.
- if (
- domination == FiniteElementDomination::this_element_dominates ||
- domination == FiniteElementDomination::either_element_can_dominate /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/)
- candidate_fes.insert(cur_fe);
+ // If current_fe is dominated, add it to the set.
+ if ((domination == FiniteElementDomination::other_element_dominates) ||
+ (domination == FiniteElementDomination::either_element_can_dominate
+ /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
+ dominated_fes.insert(current_fe);
}
+ return dominated_fes;
+ }
+
+
- // among the ones we found, pick one that is dominated by all others and
- // thus should represent the largest FE space.
- if (candidate_fes.size() == 1)
+ template <int dim, int spacedim>
+ unsigned int
+ FECollection<dim, spacedim>::find_dominating_fe(
+ const std::set<unsigned int> &fes,
+ const unsigned int codim) const
+ {
+ // Validate user inputs.
+ Assert(codim <= dim, ExcImpossibleInDim(dim));
+ for (const auto &fe : fes)
{
- return *candidate_fes.begin();
+ (void)fe;
+ AssertIndexRange(fe, finite_elements.size());
}
- else
- for (const auto ¤t_fe : candidate_fes)
- {
- FiniteElementDomination::Domination domination =
- FiniteElementDomination::no_requirements;
-
- for (const auto &other_fe : candidate_fes)
- if (current_fe != other_fe)
- domination = domination &
- finite_elements[current_fe]->compare_for_domination(
+
+ // If the set of elements contains only a single element,
+ // then this very element is considered to be the dominating one.
+ if (fes.size() == 1)
+ return *fes.begin();
+
+ // There may also be others, in which case we'll check if any of these
+ // elements is able to dominate all others. If one was found, we stop
+ // looking further and return the dominating element.
+ for (const auto ¤t_fe : fes)
+ {
+ // Check if current_fe can dominate all elements in @p fes.
+ FiniteElementDomination::Domination domination =
+ FiniteElementDomination::no_requirements;
+ for (const auto &other_fe : fes)
+ if (current_fe != other_fe)
+ domination =
+ domination & finite_elements[current_fe]->compare_for_domination(
*finite_elements[other_fe], codim);
- if ((domination ==
- FiniteElementDomination::other_element_dominates) ||
- (domination ==
- FiniteElementDomination::either_element_can_dominate
- /*covers cases like candidate_fes={Q1,Q1}*/))
- return current_fe;
- }
- // We couldn't find the FE, return invalid_unsigned_int :
+ // If current_fe dominates, return its index.
+ if ((domination == FiniteElementDomination::this_element_dominates) ||
+ (domination == FiniteElementDomination::either_element_can_dominate
+ /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
+ return current_fe;
+ }
+
+ // If we couldn't find the dominating object, return an invalid one.
return numbers::invalid_unsigned_int;
}
template <int dim, int spacedim>
unsigned int
- FECollection<dim, spacedim>::find_dominating_fe_in_subset(
+ FECollection<dim, spacedim>::find_dominated_fe(
const std::set<unsigned int> &fes,
const unsigned int codim) const
{
+ // Validate user inputs.
Assert(codim <= dim, ExcImpossibleInDim(dim));
-
- for (const unsigned int fe_index : fes)
+ for (const auto &fe : fes)
{
- (void)fe_index;
- AssertIndexRange(fe_index, finite_elements.size());
+ (void)fe;
+ AssertIndexRange(fe, finite_elements.size());
}
- // If the set of elements to be dominated contains only a single element X,
- // then by definition the dominating set contains this single element
- // (because each element can dominate itself).
- // There may also be others, in which case we'll check if any of these
- // elements is able to dominate all others. If one was found, we stop
- // looking further and return the dominating element.
+ // If the set of elements contains only a single element,
+ // then this very element is considered to be the dominated one.
if (fes.size() == 1)
return *fes.begin();
- // loop over all finite elements given in the subset
- // and check which one dominates the whole subset
+ // There may also be others, in which case we'll check if any of these
+ // elements is dominated by all others. If one was found, we stop
+ // looking further and return the dominated element.
for (const auto ¤t_fe : fes)
{
+ // Check if current_fe is dominated by all other elements in @p fes.
FiniteElementDomination::Domination domination =
- FiniteElementDomination::either_element_can_dominate;
-
+ FiniteElementDomination::no_requirements;
for (const auto &other_fe : fes)
- if (other_fe != current_fe)
+ if (current_fe != other_fe)
domination =
domination & finite_elements[current_fe]->compare_for_domination(
*finite_elements[other_fe], codim);
- // see if this element is able to dominate all the other
- // ones, and if so take it
- if ((domination == FiniteElementDomination::this_element_dominates) ||
- (domination ==
- FiniteElementDomination::either_element_can_dominate) ||
- (domination == FiniteElementDomination::no_requirements))
+ // If current_fe is dominated, return its index.
+ if ((domination == FiniteElementDomination::other_element_dominates) ||
+ (domination == FiniteElementDomination::either_element_can_dominate
+ /*covers cases like {Q2,Q3,Q1,Q1} with fes={2,3}*/))
return current_fe;
}
- // if we couldn't find the most dominating object
+ // If we couldn't find the dominated object, return an invalid one.
return numbers::invalid_unsigned_int;
}
+ template <int dim, int spacedim>
+ unsigned int
+ FECollection<dim, spacedim>::find_dominating_fe_extended(
+ const std::set<unsigned int> &fes,
+ const unsigned int codim) const
+ {
+ unsigned int fe_index = find_dominating_fe(fes, codim);
+
+ if (fe_index == numbers::invalid_unsigned_int)
+ {
+ const std::set<unsigned int> dominating_fes =
+ find_common_fes(fes, codim);
+ fe_index = find_dominated_fe(dominating_fes, codim);
+ }
+
+ return fe_index;
+ }
+
+
+
+ template <int dim, int spacedim>
+ unsigned int
+ FECollection<dim, spacedim>::find_dominated_fe_extended(
+ const std::set<unsigned int> &fes,
+ const unsigned int codim) const
+ {
+ unsigned int fe_index = find_dominated_fe(fes, codim);
+
+ if (fe_index == numbers::invalid_unsigned_int)
+ {
+ const std::set<unsigned int> dominated_fes =
+ find_enclosing_fes(fes, codim);
+ fe_index = find_dominating_fe(dominated_fes, codim);
+ }
+
+ return fe_index;
+ }
+
+
+
template <int dim, int spacedim>
FECollection<dim, spacedim>::FECollection()
{
}
deallog << "Face dominating set for 1 and 2: "
- << fe_collection.find_least_dominating_fe_in_collection({1, 2},
- /*codim=*/1)
+ << fe_collection.find_dominating_fe_extended({1, 2}, /*codim=*/1)
<< std::endl;
dof_handler.distribute_dofs(fe_collection);
/* clang-format off */
-// test the results of FECollection::find_least_dominating_fe_in_collection()
-// for faces (codim=1), namely for:
+// find the least dominating fe from a set of fes on faces (codim=1).
+// for this task we concatenate the two functions
+// FECollection::find_common_subspace() and FECollection::find_dominated_fe().
+// we test the results for the following collections:
// {Q1, Q2, Q3, Q4} with {2,3} => Q3 2
// {Q1xQ1, Q2xQ2, Q3xQ4, Q4xQ3} with {2,3} => Q2xQ2 1
// {Q1xQ1, Q3xQ4, Q4xQ3} with {1,2} => Q1xQ1 0
// {0x0, 0x0, Q1x0, 0xQ1} with {2,3} => none invalid_unsigned_int
// {0x0, 0x0, Q1x0, 0xQ1} with {2,3} => 0x0 0 (with dominating FE_Nothing)
-// {Q1xQ1, Q1xQ1, Q2xQ1, Q1xQ2} with {2,3} => Q1 0
+// {Q1xQ1, Q1xQ1, Q2xQ1, Q1xQ2} with {2,3} => Q1xQ1 0
// {Q4xQ4, Q5xQ5, Q3xQ4, Q4xQ3} with {2,3} => none invalid_unsigned_int
// {Q1, Q2, Q4, Q3} with {3} => Q3 3
// {Q3, Q4, Q1, Q1} with {2,3} => Q1 2 (self-domination)
fe_collection.push_back(FE_Q<dim>(2));
fe_collection.push_back(FE_Q<dim>(3));
fe_collection.push_back(FE_Q<dim>(4));
- deallog << fe_collection.find_least_dominating_fe_in_collection(fes,
- /*codim=*/1)
+ deallog << fe_collection.find_dominating_fe_extended(fes, /*codim=*/1)
<< std::endl;
}
fe_collection.push_back(FESystem<dim>(FE_Q<dim>(2), 1, FE_Q<dim>(2), 1));
fe_collection.push_back(FESystem<dim>(FE_Q<dim>(3), 1, FE_Q<dim>(4), 1));
fe_collection.push_back(FESystem<dim>(FE_Q<dim>(4), 1, FE_Q<dim>(3), 1));
- deallog << fe_collection.find_least_dominating_fe_in_collection(fes,
- /*codim=*/1)
+ deallog << fe_collection.find_dominating_fe_extended(fes, /*codim=*/1)
<< std::endl;
}
std::set<unsigned int> fes;
fes.insert(1);
fes.insert(2);
- deallog << fe_collection.find_least_dominating_fe_in_collection(fes,
- /*codim=*/1)
+ deallog << fe_collection.find_dominating_fe_extended(fes, /*codim=*/1)
<< std::endl;
}
fe_collection.push_back(
FESystem<dim>(FE_Nothing<dim>(), 1, FE_Q<dim>(1), 1));
const unsigned int ind =
- fe_collection.find_least_dominating_fe_in_collection(fes, /*codim=*/1);
+ fe_collection.find_dominating_fe_extended(fes, /*codim=*/1);
if (ind == numbers::invalid_unsigned_int)
deallog << "numbers::invalid_unsigned_int" << std::endl;
else
FESystem<dim>(FE_Q<dim>(1), 1, FE_Nothing<dim>(1, true), 1));
fe_collection.push_back(
FESystem<dim>(FE_Nothing<dim>(1, true), 1, FE_Q<dim>(1), 1));
- deallog << fe_collection.find_least_dominating_fe_in_collection(fes,
- /*codim=*/1)
+ deallog << fe_collection.find_dominating_fe_extended(fes, /*codim=*/1)
<< std::endl;
}
fe_collection.push_back(FESystem<dim>(FE_Q<dim>(1), 1, FE_Q<dim>(1), 1));
fe_collection.push_back(FESystem<dim>(FE_Q<dim>(2), 1, FE_Q<dim>(1), 1));
fe_collection.push_back(FESystem<dim>(FE_Q<dim>(1), 1, FE_Q<dim>(2), 1));
- deallog << fe_collection.find_least_dominating_fe_in_collection(fes,
- /*codim=*/1)
+ deallog << fe_collection.find_dominating_fe_extended(fes, /*codim=*/1)
<< std::endl;
}
fe_collection.push_back(FESystem<dim>(FE_Q<dim>(3), 1, FE_Q<dim>(4), 1));
fe_collection.push_back(FESystem<dim>(FE_Q<dim>(4), 1, FE_Q<dim>(3), 1));
const unsigned int ind =
- fe_collection.find_least_dominating_fe_in_collection(fes, /*codim=*/1);
+ fe_collection.find_dominating_fe_extended(fes, /*codim=*/1);
if (ind == numbers::invalid_unsigned_int)
deallog << "numbers::invalid_unsigned_int" << std::endl;
else
fe_collection.push_back(FE_Q<dim>(3));
std::set<unsigned int> fes;
fes.insert(3);
- deallog << fe_collection.find_least_dominating_fe_in_collection(fes,
- /*codim=*/1)
+ deallog << fe_collection.find_dominating_fe_extended(fes, /*codim=*/1)
<< std::endl;
}
fe_collection.push_back(FE_Q<dim>(4));
fe_collection.push_back(FE_Q<dim>(1));
fe_collection.push_back(FE_Q<dim>(1));
- deallog << fe_collection.find_least_dominating_fe_in_collection(fes,
- /*codim=*/1)
+ deallog << fe_collection.find_dominating_fe_extended(fes, /*codim=*/1)
<< std::endl;
}
}
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2005 - 2019 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+/* clang-format off */
+// find the most dominating fe from a set of fes on faces (codim=1).
+// for this task we concatenate the two functions
+// FECollection::find_encapsulating_space() and FECollection::find_dominating_fe().
+// we test the results for the following collections:
+// {Q1, Q2, Q3, Q4} with {2,3} => Q4 3
+// {Q5xQ5, Q4xQ4, Q3xQ4, Q4xQ3} with {2,3} => Q4xQ4 1
+// {Q5xQ5, Q3xQ4, Q4xQ3} with {2,3} => Q5xQ5 0
+// {Q1x0, 0xQ1, 0x0, 0x0} with {2,3} => none invalid_unsigned_int
+// {Q1x0, 0xQ1, 0x0, 0x0} with {2,3} => 0x0 2 (with dominating FE_Nothing)
+// {Q2xQ2, Q2xQ2, Q2xQ1, Q1xQ2} with {2,3} => Q2xQ2 0
+// {Q2xQ2, Q3xQ3, Q3xQ4, Q4xQ3} with {2,3} => none invalid_unsigned_int
+// {Q1, Q2, Q4, Q3} with {3} => Q3 3
+// {Q3, Q4, Q1, Q1} with {2,3} => Q1 2 (self-domination)
+/* clang-format on */
+
+
+#include <deal.II/fe/fe_nothing.h>
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+
+#include <deal.II/hp/fe_collection.h>
+
+#include "../tests.h"
+
+
+template <int dim>
+void
+test()
+{
+ std::set<unsigned int> fes;
+ fes.insert(2);
+ fes.insert(3);
+
+ // {Q1, Q2, Q3, Q4}
+ {
+ hp::FECollection<dim> fe_collection;
+ fe_collection.push_back(FE_Q<dim>(1));
+ fe_collection.push_back(FE_Q<dim>(2));
+ fe_collection.push_back(FE_Q<dim>(3));
+ fe_collection.push_back(FE_Q<dim>(4));
+ deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1)
+ << std::endl;
+ }
+
+ // {Q5xQ5, Q4xQ4, Q3xQ4, Q4xQ3}
+ {
+ hp::FECollection<dim> fe_collection;
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(5), 1, FE_Q<dim>(5), 1));
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(4), 1, FE_Q<dim>(4), 1));
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(3), 1, FE_Q<dim>(4), 1));
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(4), 1, FE_Q<dim>(3), 1));
+ deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1)
+ << std::endl;
+ }
+
+ // {Q5xQ5, Q3xQ4, Q4xQ3}
+ {
+ hp::FECollection<dim> fe_collection;
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(5), 1, FE_Q<dim>(5), 1));
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(3), 1, FE_Q<dim>(4), 1));
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(4), 1, FE_Q<dim>(3), 1));
+ std::set<unsigned int> fes;
+ fes.insert(1);
+ fes.insert(2);
+ deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1)
+ << std::endl;
+ }
+
+ // {Q1x0, 0xQ1, 0x0, 0x0}
+ {
+ hp::FECollection<dim> fe_collection;
+ fe_collection.push_back(
+ FESystem<dim>(FE_Q<dim>(1), 1, FE_Nothing<dim>(), 1));
+ fe_collection.push_back(
+ FESystem<dim>(FE_Nothing<dim>(), 1, FE_Q<dim>(1), 1));
+ fe_collection.push_back(
+ FESystem<dim>(FE_Nothing<dim>(), 1, FE_Nothing<dim>(), 1));
+ fe_collection.push_back(
+ FESystem<dim>(FE_Nothing<dim>(), 1, FE_Nothing<dim>(), 1));
+ const unsigned int ind =
+ fe_collection.find_dominated_fe_extended(fes, /*codim=*/1);
+ if (ind == numbers::invalid_unsigned_int)
+ deallog << "numbers::invalid_unsigned_int" << std::endl;
+ else
+ deallog << ind << std::endl;
+ }
+
+ // dominating FE_Nothing
+ // {Q1x0, 0xQ1, 0x0, 0x0}
+ {
+ hp::FECollection<dim> fe_collection;
+ fe_collection.push_back(
+ FESystem<dim>(FE_Q<dim>(1), 1, FE_Nothing<dim>(1, true), 1));
+ fe_collection.push_back(
+ FESystem<dim>(FE_Nothing<dim>(1, true), 1, FE_Q<dim>(1), 1));
+ fe_collection.push_back(
+ FESystem<dim>(FE_Nothing<dim>(1, true), 1, FE_Nothing<dim>(1, true), 1));
+ fe_collection.push_back(
+ FESystem<dim>(FE_Nothing<dim>(1, true), 1, FE_Nothing<dim>(1, true), 1));
+ deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1)
+ << std::endl;
+ }
+
+
+ // {Q2xQ2, Q2xQ2, Q2xQ1, Q1xQ2}
+ {
+ hp::FECollection<dim> fe_collection;
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(2), 1, FE_Q<dim>(2), 1));
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(2), 1, FE_Q<dim>(2), 1));
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(2), 1, FE_Q<dim>(1), 1));
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(1), 1, FE_Q<dim>(2), 1));
+ deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1)
+ << std::endl;
+ }
+
+ // {Q2xQ2, Q3xQ3, Q3xQ4, Q4xQ3}
+ {
+ hp::FECollection<dim> fe_collection;
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(2), 1, FE_Q<dim>(2), 1));
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(3), 1, FE_Q<dim>(3), 1));
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(3), 1, FE_Q<dim>(4), 1));
+ fe_collection.push_back(FESystem<dim>(FE_Q<dim>(4), 1, FE_Q<dim>(3), 1));
+ const unsigned int ind =
+ fe_collection.find_dominated_fe_extended(fes, /*codim=*/1);
+ if (ind == numbers::invalid_unsigned_int)
+ deallog << "numbers::invalid_unsigned_int" << std::endl;
+ else
+ deallog << ind << std::endl;
+ }
+
+ // {Q1, Q2, Q4, Q3}
+ {
+ hp::FECollection<dim> fe_collection;
+ fe_collection.push_back(FE_Q<dim>(1));
+ fe_collection.push_back(FE_Q<dim>(2));
+ fe_collection.push_back(FE_Q<dim>(4));
+ fe_collection.push_back(FE_Q<dim>(3));
+ std::set<unsigned int> fes;
+ fes.insert(3);
+ deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1)
+ << std::endl;
+ }
+
+ // {Q3, Q4, Q1, Q1}
+ {
+ hp::FECollection<dim> fe_collection;
+ fe_collection.push_back(FE_Q<dim>(3));
+ fe_collection.push_back(FE_Q<dim>(4));
+ fe_collection.push_back(FE_Q<dim>(1));
+ fe_collection.push_back(FE_Q<dim>(1));
+ deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1)
+ << std::endl;
+ }
+}
+
+int
+main()
+{
+ initlog();
+ deallog.get_file_stream().precision(2);
+
+ deallog.push("2D");
+ test<2>();
+ deallog.pop();
+ deallog.push("3D");
+ test<3>();
+ deallog.pop();
+
+ deallog << "OK" << std::endl;
+}
--- /dev/null
+
+DEAL:2D::3
+DEAL:2D::1
+DEAL:2D::0
+DEAL:2D::numbers::invalid_unsigned_int
+DEAL:2D::2
+DEAL:2D::0
+DEAL:2D::numbers::invalid_unsigned_int
+DEAL:2D::3
+DEAL:2D::2
+DEAL:3D::3
+DEAL:3D::1
+DEAL:3D::0
+DEAL:3D::numbers::invalid_unsigned_int
+DEAL:3D::2
+DEAL:3D::0
+DEAL:3D::numbers::invalid_unsigned_int
+DEAL:3D::3
+DEAL:3D::2
+DEAL::OK