From: Marc Fehling Date: Sat, 6 Apr 2019 22:42:49 +0000 (+0200) Subject: Refactored hp::FECollection: Get fe relations with respect to FiniteElementDomination. X-Git-Tag: v9.1.0-rc1~113^2~1 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=db5c80c298ba861da775df8ea1b406a8e7698576;p=dealii.git Refactored hp::FECollection: Get fe relations with respect to FiniteElementDomination. --- diff --git a/doc/news/changes/incompatibilities/20181008Fehling b/doc/news/changes/incompatibilities/20181008Fehling deleted file mode 100644 index c31c8d4365..0000000000 --- a/doc/news/changes/incompatibilities/20181008Fehling +++ /dev/null @@ -1,6 +0,0 @@ -Changed: The function previously called -FECollection::find_least_face_dominating_fe() -is now named -FECollection::find_least_face_dominating_fe_in_collection(). -
-(Marc Fehling, 2018/10/08) diff --git a/doc/news/changes/incompatibilities/20190408Fehling b/doc/news/changes/incompatibilities/20190408Fehling new file mode 100644 index 0000000000..15e2f27e55 --- /dev/null +++ b/doc/news/changes/incompatibilities/20190408Fehling @@ -0,0 +1,6 @@ +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(). +
+(Marc Fehling, 2019/04/08) diff --git a/doc/news/changes/minor/20181005MarcFehling b/doc/news/changes/minor/20181005MarcFehling deleted file mode 100644 index 4e24cf2e2b..0000000000 --- a/doc/news/changes/minor/20181005MarcFehling +++ /dev/null @@ -1,5 +0,0 @@ -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. -
-(Marc Fehling, 2018/10/05) diff --git a/doc/news/changes/minor/20190408MarcFehling b/doc/news/changes/minor/20190408MarcFehling new file mode 100644 index 0000000000..497e240c12 --- /dev/null +++ b/doc/news/changes/minor/20190408MarcFehling @@ -0,0 +1,5 @@ +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. +
+(Marc Fehling, 2019/04/08) diff --git a/doc/news/changes/minor/20190408MarcFehling-1 b/doc/news/changes/minor/20190408MarcFehling-1 new file mode 100644 index 0000000000..b0427c8838 --- /dev/null +++ b/doc/news/changes/minor/20190408MarcFehling-1 @@ -0,0 +1,5 @@ +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. +
+(Marc Fehling, 2019/04/08) diff --git a/doc/news/changes/minor/20190408MarcFehling-2 b/doc/news/changes/minor/20190408MarcFehling-2 new file mode 100644 index 0000000000..ea09694d85 --- /dev/null +++ b/doc/news/changes/minor/20190408MarcFehling-2 @@ -0,0 +1,5 @@ +New: Member function hp::FECollection::find_dominating_fe() +returns the index of the most dominating finite element out of a given +set of indices. +
+(Marc Fehling, 2019/04/08) diff --git a/doc/news/changes/minor/20190408MarcFehling-3 b/doc/news/changes/minor/20190408MarcFehling-3 new file mode 100644 index 0000000000..d146817538 --- /dev/null +++ b/doc/news/changes/minor/20190408MarcFehling-3 @@ -0,0 +1,5 @@ +New: Member function hp::FECollection::find_dominated_fe() +returns the index of the least dominating finite element out of a given +set of indices. +
+(Marc Fehling, 2019/04/08) diff --git a/include/deal.II/distributed/solution_transfer.h b/include/deal.II/distributed/solution_transfer.h index ebc007c3d2..2ec275a222 100644 --- a/include/deal.II/distributed/solution_transfer.h +++ b/include/deal.II/distributed/solution_transfer.h @@ -165,10 +165,9 @@ namespace parallel * 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 diff --git a/include/deal.II/hp/dof_handler.h b/include/deal.II/hp/dof_handler.h index 3bff98e0d1..8ac961eb0d 100644 --- a/include/deal.II/hp/dof_handler.h +++ b/include/deal.II/hp/dof_handler.h @@ -128,9 +128,10 @@ namespace hp * - 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. diff --git a/include/deal.II/hp/fe_collection.h b/include/deal.II/hp/fe_collection.h index c8ab5fb908..ae36ff8cd5 100644 --- a/include/deal.II/hp/fe_collection.h +++ b/include/deal.II/hp/fe_collection.h @@ -337,92 +337,189 @@ namespace hp * 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 &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 least - * 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 + find_common_fes(const std::set &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 + find_enclosing_fes(const std::set &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 &fes, - const unsigned int codim = 0) const; + find_dominating_fe(const std::set &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 &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 &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 &fes, - const unsigned int codim = 0) const; + find_dominated_fe_extended(const std::set &fes, + const unsigned int codim = 0) const; /** * Set functions determining the hierarchy of finite elements, i.e. a diff --git a/source/distributed/cell_weights.cc b/source/distributed/cell_weights.cc index 365c86051f..4e9f9989ad 100644 --- a/source/distributed/cell_weights.cc +++ b/source/distributed/cell_weights.cc @@ -149,10 +149,9 @@ namespace parallel 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( diff --git a/source/distributed/solution_transfer.cc b/source/distributed/solution_transfer.cc index 26e0cb1a70..5c56ad15de 100644 --- a/source/distributed/solution_transfer.cc +++ b/source/distributed/solution_transfer.cc @@ -263,8 +263,8 @@ namespace parallel 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 fe_indices_children; for (unsigned int child_index = 0; child_index < GeometryInfo::max_children_per_cell; @@ -273,8 +273,8 @@ namespace parallel 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, diff --git a/source/dofs/dof_handler_policy.cc b/source/dofs/dof_handler_policy.cc index a2f2eca38f..671309ccf5 100644 --- a/source/dofs/dof_handler_policy.cc +++ b/source/dofs/dof_handler_policy.cc @@ -637,9 +637,9 @@ namespace internal // 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 @@ -875,8 +875,8 @@ namespace internal 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; @@ -1009,9 +1009,9 @@ namespace internal // 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 @@ -1168,9 +1168,9 @@ namespace internal // 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 @@ -1477,9 +1477,9 @@ namespace internal // 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 @@ -1694,8 +1694,8 @@ namespace internal 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; @@ -1768,9 +1768,9 @@ namespace internal // 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 @@ -1910,9 +1910,9 @@ namespace internal // 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 diff --git a/source/dofs/dof_tools_constraints.cc b/source/dofs/dof_tools_constraints.cc index a7af43b0a5..685e9df004 100644 --- a/source/dofs/dof_tools_constraints.cc +++ b/source/dofs/dof_tools_constraints.cc @@ -1281,27 +1281,33 @@ namespace DoFTools // 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( @@ -1599,10 +1605,11 @@ namespace DoFTools fes.insert(neighbor_fe_index); const dealii::hp::FECollection &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 != diff --git a/source/fe/fe_enriched.cc b/source/fe/fe_enriched.cc index ec5368122c..cbed8a521a 100644 --- a/source/fe/fe_enriched.cc +++ b/source/fe/fe_enriched.cc @@ -1262,16 +1262,16 @@ namespace ColorEnriched /* * 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 @@ -1280,12 +1280,11 @@ namespace ColorEnriched * 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 diff --git a/source/hp/dof_handler.cc b/source/hp/dof_handler.cc index 6bfa72ddee..d6905af1dc 100644 --- a/source/hp/dof_handler.cc +++ b/source/hp/dof_handler.cc @@ -1063,11 +1063,11 @@ namespace internal * 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 static void @@ -1110,11 +1110,13 @@ namespace internal 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, diff --git a/source/hp/fe_collection.cc b/source/hp/fe_collection.cc index cc3c26634a..29c0275e55 100644 --- a/source/hp/fe_collection.cc +++ b/source/hp/fe_collection.cc @@ -27,83 +27,133 @@ namespace hp FECollection::find_least_face_dominating_fe( const std::set &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 - unsigned int - FECollection::find_least_dominating_fe_in_collection( + std::set + FECollection::find_common_fes( const std::set &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 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 candidate_fes; + template + std::set + FECollection::find_enclosing_fes( + const std::set &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 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 + unsigned int + FECollection::find_dominating_fe( + const std::set &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; } @@ -111,55 +161,90 @@ namespace hp template unsigned int - FECollection::find_dominating_fe_in_subset( + FECollection::find_dominated_fe( const std::set &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 + unsigned int + FECollection::find_dominating_fe_extended( + const std::set &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 dominating_fes = + find_common_fes(fes, codim); + fe_index = find_dominated_fe(dominating_fes, codim); + } + + return fe_index; + } + + + + template + unsigned int + FECollection::find_dominated_fe_extended( + const std::set &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 dominated_fes = + find_enclosing_fes(fes, codim); + fe_index = find_dominating_fe(dominated_fes, codim); + } + + return fe_index; + } + + + template FECollection::FECollection() { diff --git a/tests/fe/fe_enriched_color_08.cc b/tests/fe/fe_enriched_color_08.cc index f3640f39af..8457335bbc 100644 --- a/tests/fe/fe_enriched_color_08.cc +++ b/tests/fe/fe_enriched_color_08.cc @@ -269,8 +269,7 @@ main(int argc, char **argv) } 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); diff --git a/tests/hp/fe_collection_05.cc b/tests/hp/fe_collection_05.cc index 5285334087..bc0cf7661f 100644 --- a/tests/hp/fe_collection_05.cc +++ b/tests/hp/fe_collection_05.cc @@ -15,14 +15,16 @@ /* 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) @@ -54,8 +56,7 @@ test() fe_collection.push_back(FE_Q(2)); fe_collection.push_back(FE_Q(3)); fe_collection.push_back(FE_Q(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; } @@ -66,8 +67,7 @@ test() fe_collection.push_back(FESystem(FE_Q(2), 1, FE_Q(2), 1)); fe_collection.push_back(FESystem(FE_Q(3), 1, FE_Q(4), 1)); fe_collection.push_back(FESystem(FE_Q(4), 1, FE_Q(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; } @@ -80,8 +80,7 @@ test() std::set 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; } @@ -97,7 +96,7 @@ test() fe_collection.push_back( FESystem(FE_Nothing(), 1, FE_Q(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 @@ -116,8 +115,7 @@ test() FESystem(FE_Q(1), 1, FE_Nothing(1, true), 1)); fe_collection.push_back( FESystem(FE_Nothing(1, true), 1, FE_Q(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; } @@ -129,8 +127,7 @@ test() fe_collection.push_back(FESystem(FE_Q(1), 1, FE_Q(1), 1)); fe_collection.push_back(FESystem(FE_Q(2), 1, FE_Q(1), 1)); fe_collection.push_back(FESystem(FE_Q(1), 1, FE_Q(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; } @@ -142,7 +139,7 @@ test() fe_collection.push_back(FESystem(FE_Q(3), 1, FE_Q(4), 1)); fe_collection.push_back(FESystem(FE_Q(4), 1, FE_Q(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 @@ -158,8 +155,7 @@ test() fe_collection.push_back(FE_Q(3)); std::set 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; } @@ -170,8 +166,7 @@ test() fe_collection.push_back(FE_Q(4)); fe_collection.push_back(FE_Q(1)); fe_collection.push_back(FE_Q(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; } } diff --git a/tests/hp/fe_collection_06.cc b/tests/hp/fe_collection_06.cc new file mode 100644 index 0000000000..b940318944 --- /dev/null +++ b/tests/hp/fe_collection_06.cc @@ -0,0 +1,187 @@ +// --------------------------------------------------------------------- +// +// 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 +#include +#include + +#include + +#include "../tests.h" + + +template +void +test() +{ + std::set fes; + fes.insert(2); + fes.insert(3); + + // {Q1, Q2, Q3, Q4} + { + hp::FECollection fe_collection; + fe_collection.push_back(FE_Q(1)); + fe_collection.push_back(FE_Q(2)); + fe_collection.push_back(FE_Q(3)); + fe_collection.push_back(FE_Q(4)); + deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1) + << std::endl; + } + + // {Q5xQ5, Q4xQ4, Q3xQ4, Q4xQ3} + { + hp::FECollection fe_collection; + fe_collection.push_back(FESystem(FE_Q(5), 1, FE_Q(5), 1)); + fe_collection.push_back(FESystem(FE_Q(4), 1, FE_Q(4), 1)); + fe_collection.push_back(FESystem(FE_Q(3), 1, FE_Q(4), 1)); + fe_collection.push_back(FESystem(FE_Q(4), 1, FE_Q(3), 1)); + deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1) + << std::endl; + } + + // {Q5xQ5, Q3xQ4, Q4xQ3} + { + hp::FECollection fe_collection; + fe_collection.push_back(FESystem(FE_Q(5), 1, FE_Q(5), 1)); + fe_collection.push_back(FESystem(FE_Q(3), 1, FE_Q(4), 1)); + fe_collection.push_back(FESystem(FE_Q(4), 1, FE_Q(3), 1)); + std::set 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 fe_collection; + fe_collection.push_back( + FESystem(FE_Q(1), 1, FE_Nothing(), 1)); + fe_collection.push_back( + FESystem(FE_Nothing(), 1, FE_Q(1), 1)); + fe_collection.push_back( + FESystem(FE_Nothing(), 1, FE_Nothing(), 1)); + fe_collection.push_back( + FESystem(FE_Nothing(), 1, FE_Nothing(), 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 fe_collection; + fe_collection.push_back( + FESystem(FE_Q(1), 1, FE_Nothing(1, true), 1)); + fe_collection.push_back( + FESystem(FE_Nothing(1, true), 1, FE_Q(1), 1)); + fe_collection.push_back( + FESystem(FE_Nothing(1, true), 1, FE_Nothing(1, true), 1)); + fe_collection.push_back( + FESystem(FE_Nothing(1, true), 1, FE_Nothing(1, true), 1)); + deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1) + << std::endl; + } + + + // {Q2xQ2, Q2xQ2, Q2xQ1, Q1xQ2} + { + hp::FECollection fe_collection; + fe_collection.push_back(FESystem(FE_Q(2), 1, FE_Q(2), 1)); + fe_collection.push_back(FESystem(FE_Q(2), 1, FE_Q(2), 1)); + fe_collection.push_back(FESystem(FE_Q(2), 1, FE_Q(1), 1)); + fe_collection.push_back(FESystem(FE_Q(1), 1, FE_Q(2), 1)); + deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1) + << std::endl; + } + + // {Q2xQ2, Q3xQ3, Q3xQ4, Q4xQ3} + { + hp::FECollection fe_collection; + fe_collection.push_back(FESystem(FE_Q(2), 1, FE_Q(2), 1)); + fe_collection.push_back(FESystem(FE_Q(3), 1, FE_Q(3), 1)); + fe_collection.push_back(FESystem(FE_Q(3), 1, FE_Q(4), 1)); + fe_collection.push_back(FESystem(FE_Q(4), 1, FE_Q(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 fe_collection; + fe_collection.push_back(FE_Q(1)); + fe_collection.push_back(FE_Q(2)); + fe_collection.push_back(FE_Q(4)); + fe_collection.push_back(FE_Q(3)); + std::set fes; + fes.insert(3); + deallog << fe_collection.find_dominated_fe_extended(fes, /*codim=*/1) + << std::endl; + } + + // {Q3, Q4, Q1, Q1} + { + hp::FECollection fe_collection; + fe_collection.push_back(FE_Q(3)); + fe_collection.push_back(FE_Q(4)); + fe_collection.push_back(FE_Q(1)); + fe_collection.push_back(FE_Q(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; +} diff --git a/tests/hp/fe_collection_06.output b/tests/hp/fe_collection_06.output new file mode 100644 index 0000000000..59f0566c32 --- /dev/null +++ b/tests/hp/fe_collection_06.output @@ -0,0 +1,20 @@ + +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