]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Refactored hp::FECollection: Get fe relations with respect to FiniteElementDomination.
authorMarc Fehling <marc.fehling@gmx.net>
Sat, 6 Apr 2019 22:42:49 +0000 (00:42 +0200)
committerMarc Fehling <marc.fehling@gmx.net>
Wed, 8 May 2019 14:19:41 +0000 (16:19 +0200)
21 files changed:
doc/news/changes/incompatibilities/20181008Fehling [deleted file]
doc/news/changes/incompatibilities/20190408Fehling [new file with mode: 0644]
doc/news/changes/minor/20181005MarcFehling [deleted file]
doc/news/changes/minor/20190408MarcFehling [new file with mode: 0644]
doc/news/changes/minor/20190408MarcFehling-1 [new file with mode: 0644]
doc/news/changes/minor/20190408MarcFehling-2 [new file with mode: 0644]
doc/news/changes/minor/20190408MarcFehling-3 [new file with mode: 0644]
include/deal.II/distributed/solution_transfer.h
include/deal.II/hp/dof_handler.h
include/deal.II/hp/fe_collection.h
source/distributed/cell_weights.cc
source/distributed/solution_transfer.cc
source/dofs/dof_handler_policy.cc
source/dofs/dof_tools_constraints.cc
source/fe/fe_enriched.cc
source/hp/dof_handler.cc
source/hp/fe_collection.cc
tests/fe/fe_enriched_color_08.cc
tests/hp/fe_collection_05.cc
tests/hp/fe_collection_06.cc [new file with mode: 0644]
tests/hp/fe_collection_06.output [new file with mode: 0644]

diff --git a/doc/news/changes/incompatibilities/20181008Fehling b/doc/news/changes/incompatibilities/20181008Fehling
deleted file mode 100644 (file)
index c31c8d4..0000000
+++ /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().
-<br>
-(Marc Fehling, 2018/10/08)
diff --git a/doc/news/changes/incompatibilities/20190408Fehling b/doc/news/changes/incompatibilities/20190408Fehling
new file mode 100644 (file)
index 0000000..15e2f27
--- /dev/null
@@ -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().
+<br>
+(Marc Fehling, 2019/04/08)
diff --git a/doc/news/changes/minor/20181005MarcFehling b/doc/news/changes/minor/20181005MarcFehling
deleted file mode 100644 (file)
index 4e24cf2..0000000
+++ /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.
-<br>
-(Marc Fehling, 2018/10/05)
diff --git a/doc/news/changes/minor/20190408MarcFehling b/doc/news/changes/minor/20190408MarcFehling
new file mode 100644 (file)
index 0000000..497e240
--- /dev/null
@@ -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.
+<br>
+(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 (file)
index 0000000..b0427c8
--- /dev/null
@@ -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.
+<br>
+(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 (file)
index 0000000..ea09694
--- /dev/null
@@ -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.
+<br>
+(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 (file)
index 0000000..d146817
--- /dev/null
@@ -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.
+<br>
+(Marc Fehling, 2019/04/08)
index ebc007c3d2162d6ddb5fa93541fe07dc5a76c9dc..2ec275a2224bd3f275e0a4fba0b6ce4caf5168d6 100644 (file)
@@ -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
index 3bff98e0d14a25964ecfcdb3306d0105de39a2d4..8ac961eb0d0a0fb33de95bc63bb142b25dd77f74 100644 (file)
@@ -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.
index c8ab5fb90890769425ba51a7589acecb61165965..ae36ff8cd53d79e6d67957f65aef3ec70de39019 100644 (file)
@@ -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<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
index 365c86051f8c5d2b37503faa2f038c9bd162628e..4e9f9989ad9f3bea088f2ba7a55409eaa42edce6 100644 (file)
@@ -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(
index 26e0cb1a70ddb3f3f07bd193660a1211df5800ac..5c56ad15de6b697eee5859a8fb231858bb6c57ec 100644 (file)
@@ -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<unsigned int> fe_indices_children;
                   for (unsigned int child_index = 0;
                        child_index < GeometryInfo<dim>::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,
index a2f2eca38fe405504dcd5582eadd6c312700e239..671309ccf56f36b1832a67ed2f6729cd5165b88f 100644 (file)
@@ -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
index a7af43b0a502c03dfd8cee4283347039432687b1..685e9df004d56505ceaeecfb45fb07b5065c5b1e 100644 (file)
@@ -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<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 !=
index ec5368122ca344bb1e2c2715414e61dc968e7c1e..cbed8a521a09638c8120ae60692ead123d246951 100644 (file)
@@ -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
index 6bfa72ddee6a405fcad49c9c52dac48f4c48798c..d6905af1dc9a15d645a0a1976dafeefa134c68bf 100644 (file)
@@ -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 <int dim, int spacedim>
         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,
index cc3c26634a8408b4ab09d2a2f0a7e4609f90b631..29c0275e55962e8f7d8d7361b5e98d8e00aebbff 100644 (file)
@@ -27,83 +27,133 @@ namespace hp
   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 &current_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 &current_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 <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 &current_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()
   {
index f3640f39af621f3b090b9bb7287c0074cffe81cf..8457335bbc9b9678ac65629edba061dcb78661ce 100644 (file)
@@ -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);
index 52853340873d937c56428fc52eba79d4693c7541..bc0cf7661fc08ff3c09bb4f77b2ad5e3e511f19d 100644 (file)
 
 
 /* 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<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;
   }
 
@@ -66,8 +67,7 @@ test()
     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;
   }
 
@@ -80,8 +80,7 @@ test()
     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;
   }
 
@@ -97,7 +96,7 @@ test()
     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
@@ -116,8 +115,7 @@ test()
       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;
   }
 
@@ -129,8 +127,7 @@ test()
     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;
   }
 
@@ -142,7 +139,7 @@ test()
     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
@@ -158,8 +155,7 @@ test()
     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;
   }
 
@@ -170,8 +166,7 @@ test()
     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;
   }
 }
diff --git a/tests/hp/fe_collection_06.cc b/tests/hp/fe_collection_06.cc
new file mode 100644 (file)
index 0000000..b940318
--- /dev/null
@@ -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 <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;
+}
diff --git a/tests/hp/fe_collection_06.output b/tests/hp/fe_collection_06.output
new file mode 100644 (file)
index 0000000..59f0566
--- /dev/null
@@ -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

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.