From: Marc Fehling Date: Thu, 11 Oct 2018 01:26:39 +0000 (-0600) Subject: Introduced 'compare_for_domination()' functions. Deprecated 'compare_for_face_dominat... X-Git-Tag: v9.1.0-rc1~584^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F7337%2Fhead;p=dealii.git Introduced 'compare_for_domination()' functions. Deprecated 'compare_for_face_domination()' functions. --- diff --git a/doc/news/changes/incompatibilities/20181011Fehling b/doc/news/changes/incompatibilities/20181011Fehling new file mode 100644 index 0000000000..4c8eb0100b --- /dev/null +++ b/doc/news/changes/incompatibilities/20181011Fehling @@ -0,0 +1,5 @@ +Deprecated: FiniteElement::compare_for_face_domination() has been +deprecated and will be replaced by the more versatile function +FiniteElement::compare_for_domination(). +
+(Marc Fehling, 2018/10/11) diff --git a/doc/news/changes/major/20181011Fehling b/doc/news/changes/major/20181011Fehling new file mode 100644 index 0000000000..8ab781adee --- /dev/null +++ b/doc/news/changes/major/20181011Fehling @@ -0,0 +1,5 @@ +New: Function FiniteElement::compare_for_domination() inspects two +FiniteElement objects upon FiniteElementDomination, and uses a codim +parameter that determines in which subspace we actually compare them. +
+(Marc Fehling, 2018/10/11) diff --git a/include/deal.II/fe/fe.h b/include/deal.II/fe/fe.h index bcb5fda482..01b4b05546 100644 --- a/include/deal.II/fe/fe.h +++ b/include/deal.II/fe/fe.h @@ -1356,10 +1356,31 @@ public: * For a definition of domination, see FiniteElementDomination::Domination * and in particular the * @ref hp_paper "hp paper". + * + * @deprecated Use compare_for_domination() with `codim=1` instead. */ - virtual FiniteElementDomination::Domination + DEAL_II_DEPRECATED virtual FiniteElementDomination::Domination compare_for_face_domination( - const FiniteElement &fe_other) const; + const FiniteElement &fe_other) const final; + + /** + * Return whether this element dominates another one given as argument + * @p fe_other, whether it is the other way around, whether neither dominates, + * or if either could dominate. The @p codim parameter describes the codimension + * of the investigated subspace and specifies that it is subject to this + * comparison. For example, if `codim==0` then this function compares which + * element dominates at the cell level. If `codim==1`, then the elements are + * compared at faces, i.e., the comparison happens between the function spaces + * of the two finite elements as restricted to a face. Larger values of + * `codim` work correspondingly. + * + * For a definition of domination, see FiniteElementDomination::Domination + * and in particular the + * @ref hp_paper "hp paper". + */ + virtual FiniteElementDomination::Domination + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const; //@} diff --git a/include/deal.II/fe/fe_base.h b/include/deal.II/fe/fe_base.h index c5e4fb312d..95deafb58e 100644 --- a/include/deal.II/fe/fe_base.h +++ b/include/deal.II/fe/fe_base.h @@ -39,13 +39,13 @@ namespace FiniteElementDomination * strictly larger than that of the dominating element. For example, in 2-d * Q(2) elements dominate Q(4) elements, because the traces of Q(4) elements * are quartic polynomials which is a space strictly larger than the - * quadratic polynomials (the restriction of the Q(2) element). In general, - * Q(k) dominates Q(k') if $k\le k'$. + * quadratic polynomials (the restriction of the Q(2) element). Similar + * reasonings apply for vertices and cells as well. In general, Q(k) dominates + * Q(k') if $k\le k'$. * - * This enum is used in the FiniteElement::compare_for_face_domination() - * function that is used in the context of hp finite element methods when - * determining what to do at faces where two different finite elements meet - * (see the + * This enum is used in the FiniteElement::compare_for_domination() function + * that is used in the context of hp finite element methods when determining + * what to do at faces where two different finite elements meet (see the * @ref hp_paper "hp paper" * for a more detailed description of the following). In that case, the * degrees of freedom of one side need to be constrained to those on the @@ -53,11 +53,6 @@ namespace FiniteElementDomination * of a comparison for mutual domination: the dominated side is constrained * to the dominating one. * - * A similar situation happens in 3d, where we have to consider different - * elements meeting at only an edge, not an entire face. Such comparisons - * are then implemented in the FiniteElement::compare_for_line_domination() - * function. - * * Note that there are situations where neither side dominates. The * @ref hp_paper "hp paper" * lists two case, with the simpler one being that a $Q_2\times Q_1$ vector- diff --git a/include/deal.II/fe/fe_bernstein.h b/include/deal.II/fe/fe_bernstein.h index 3d02720b23..f3dde79500 100644 --- a/include/deal.II/fe/fe_bernstein.h +++ b/include/deal.II/fe/fe_bernstein.h @@ -180,18 +180,11 @@ public: const FiniteElement &fe_other) const override; /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; - + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; /** * Return a string that uniquely identifies a finite element. This class diff --git a/include/deal.II/fe/fe_dgp.h b/include/deal.II/fe/fe_dgp.h index 5016822b7a..355252111a 100644 --- a/include/deal.II/fe/fe_dgp.h +++ b/include/deal.II/fe/fe_dgp.h @@ -385,17 +385,11 @@ public: hp_constraints_are_implemented() const override; /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; /** * @} diff --git a/include/deal.II/fe/fe_dgp_monomial.h b/include/deal.II/fe/fe_dgp_monomial.h index 11be38054d..16dffa8ed8 100644 --- a/include/deal.II/fe/fe_dgp_monomial.h +++ b/include/deal.II/fe/fe_dgp_monomial.h @@ -357,17 +357,11 @@ public: hp_constraints_are_implemented() const override; /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; /** * @} diff --git a/include/deal.II/fe/fe_dgp_nonparametric.h b/include/deal.II/fe/fe_dgp_nonparametric.h index c6c1b534fb..80a5654271 100644 --- a/include/deal.II/fe/fe_dgp_nonparametric.h +++ b/include/deal.II/fe/fe_dgp_nonparametric.h @@ -474,17 +474,11 @@ public: hp_constraints_are_implemented() const override; /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; /** * @} diff --git a/include/deal.II/fe/fe_dgq.h b/include/deal.II/fe/fe_dgq.h index 32d50c3c3c..de3c697509 100644 --- a/include/deal.II/fe/fe_dgq.h +++ b/include/deal.II/fe/fe_dgq.h @@ -280,17 +280,11 @@ public: hp_constraints_are_implemented() const override; /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; /** * @} diff --git a/include/deal.II/fe/fe_enriched.h b/include/deal.II/fe/fe_enriched.h index b123f9772d..b09de46b91 100644 --- a/include/deal.II/fe/fe_enriched.h +++ b/include/deal.II/fe/fe_enriched.h @@ -454,17 +454,12 @@ public: const FiniteElement &fe_other) const override; /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementBase::Domination and in - * particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; + //@} diff --git a/include/deal.II/fe/fe_face.h b/include/deal.II/fe/fe_face.h index 91aa2a07eb..c0238f6deb 100644 --- a/include/deal.II/fe/fe_face.h +++ b/include/deal.II/fe/fe_face.h @@ -175,17 +175,12 @@ public: hp_constraints_are_implemented() const override; /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; + /** * @} */ @@ -324,19 +319,6 @@ public: hp_quad_dof_identities( const FiniteElement<1, spacedim> &fe_other) const override; - /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". - */ - virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement<1, spacedim> &fe_other) const override; - /** * Return a list of constant modes of the element. For this element, it * simply returns one row with all entries set to true. @@ -548,17 +530,11 @@ public: hp_constraints_are_implemented() const override; /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; /** * Return a list of constant modes of the element. For this element, the diff --git a/include/deal.II/fe/fe_nedelec.h b/include/deal.II/fe/fe_nedelec.h index 25acab28d2..0256343594 100644 --- a/include/deal.II/fe/fe_nedelec.h +++ b/include/deal.II/fe/fe_nedelec.h @@ -150,12 +150,11 @@ public: hp_constraints_are_implemented() const override; /** - * Return whether this element dominates the one, which is given as - * argument. + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; /** * If, on a vertex, several finite elements are active, the hp code first @@ -219,6 +218,7 @@ public: get_subface_interpolation_matrix(const FiniteElement &source, const unsigned int subface, FullMatrix &matrix) const override; + /** * Projection from a fine grid space onto a coarse grid space. If this * projection operator is associated with a matrix @p P, then the diff --git a/include/deal.II/fe/fe_nothing.h b/include/deal.II/fe/fe_nothing.h index 384ad5f6b5..fd3b8270e6 100644 --- a/include/deal.II/fe/fe_nothing.h +++ b/include/deal.II/fe/fe_nothing.h @@ -86,11 +86,11 @@ public: * finite element (default = 1). * * Second argument decides whether FE_Nothing will dominate any other FE in - * compare_for_face_domination() (default = false). Therefore at interfaces - * where, for example, a Q1 meets an FE_Nothing, we will force the traces of - * the two functions to be the same. Because the FE_Nothing encodes a space - * that is zero everywhere, this means that the Q1 field will be forced to - * become zero at this interface. + * compare_for_domination() (default = false). Therefore at interfaces where, + * for example, a Q1 meets an FE_Nothing, we will force the traces of the two + * functions to be the same. Because the FE_Nothing encodes a space that is + * zero everywhere, this means that the Q1 field will be forced to become zero + * at this interface. */ FE_Nothing(const unsigned int n_components = 1, const bool dominate = false); @@ -184,13 +184,7 @@ public: &output_data) const override; /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() * * In the current case, this element is assumed to dominate if the second * argument in the constructor @p dominate is true. When this argument is @@ -198,8 +192,8 @@ public: * dominate. Otherwise there are no_requirements. */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; @@ -277,7 +271,9 @@ public: private: /** * If true, this element will dominate any other apart from itself in - * compare_for_face_domination(); + * compare_for_domination(). This is because a space that only contains the + * zero function is definitely smaller (and consequently dominant) when + * compared to any other finite element space. */ const bool dominate; }; diff --git a/include/deal.II/fe/fe_q.h b/include/deal.II/fe/fe_q.h index 0487ac7655..e5ba575fea 100644 --- a/include/deal.II/fe/fe_q.h +++ b/include/deal.II/fe/fe_q.h @@ -595,6 +595,13 @@ public: convert_generalized_support_point_values_to_dof_values( const std::vector> &support_point_values, std::vector & nodal_values) const override; + + /** + * @copydoc FiniteElement::compare_for_domination() + */ + virtual FiniteElementDomination::Domination + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; }; diff --git a/include/deal.II/fe/fe_q_base.h b/include/deal.II/fe/fe_q_base.h index aa89ec321a..39e9c3282d 100644 --- a/include/deal.II/fe/fe_q_base.h +++ b/include/deal.II/fe/fe_q_base.h @@ -263,18 +263,6 @@ public: hp_quad_dof_identities( const FiniteElement &fe_other) const override; - /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". - */ - virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; //@} /** diff --git a/include/deal.II/fe/fe_q_bubbles.h b/include/deal.II/fe/fe_q_bubbles.h index f906065ebf..05651de719 100644 --- a/include/deal.II/fe/fe_q_bubbles.h +++ b/include/deal.II/fe/fe_q_bubbles.h @@ -152,6 +152,13 @@ public: virtual std::unique_ptr> clone() const override; + /** + * @copydoc FiniteElement::compare_for_domination() + */ + virtual FiniteElementDomination::Domination + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; + private: /** * Return the restriction_is_additive flags. Only the last components for diff --git a/include/deal.II/fe/fe_q_dg0.h b/include/deal.II/fe/fe_q_dg0.h index e23a841e24..fd6f8c4e9b 100644 --- a/include/deal.II/fe/fe_q_dg0.h +++ b/include/deal.II/fe/fe_q_dg0.h @@ -302,6 +302,13 @@ public: virtual std::unique_ptr> clone() const override; + /** + * @copydoc FiniteElement::compare_for_domination() + */ + virtual FiniteElementDomination::Domination + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; + private: /** * Return the restriction_is_additive flags. Only the last component is diff --git a/include/deal.II/fe/fe_q_hierarchical.h b/include/deal.II/fe/fe_q_hierarchical.h index 85c4a7533f..7b25ab08b8 100644 --- a/include/deal.II/fe/fe_q_hierarchical.h +++ b/include/deal.II/fe/fe_q_hierarchical.h @@ -630,6 +630,13 @@ public: virtual std::vector> hp_quad_dof_identities(const FiniteElement &fe_other) const override; + /** + * @copydoc FiniteElement::compare_for_domination() + */ + virtual FiniteElementDomination::Domination + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; + /*@}*/ /** @@ -663,19 +670,6 @@ public: const unsigned int subface, FullMatrix &matrix) const override; - /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". - */ - virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; - /** * Determine an estimate for the memory consumption (in bytes) of this * object. diff --git a/include/deal.II/fe/fe_q_iso_q1.h b/include/deal.II/fe/fe_q_iso_q1.h index ca10e762d7..6231dc67c2 100644 --- a/include/deal.II/fe/fe_q_iso_q1.h +++ b/include/deal.II/fe/fe_q_iso_q1.h @@ -153,17 +153,12 @@ public: */ /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; + //@} }; diff --git a/include/deal.II/fe/fe_raviart_thomas.h b/include/deal.II/fe/fe_raviart_thomas.h index 73d93cc98a..af43eafd16 100644 --- a/include/deal.II/fe/fe_raviart_thomas.h +++ b/include/deal.II/fe/fe_raviart_thomas.h @@ -292,9 +292,12 @@ public: virtual std::vector> hp_quad_dof_identities(const FiniteElement &fe_other) const override; + /** + * @copydoc FiniteElement::compare_for_domination() + */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; private: /** diff --git a/include/deal.II/fe/fe_system.h b/include/deal.II/fe/fe_system.h index bc269b5bab..06c3cc1f5c 100644 --- a/include/deal.II/fe/fe_system.h +++ b/include/deal.II/fe/fe_system.h @@ -957,17 +957,12 @@ public: const FiniteElement &fe_other) const override; /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; + //@} /** diff --git a/include/deal.II/fe/fe_trace.h b/include/deal.II/fe/fe_trace.h index 7551f93656..86205542c8 100644 --- a/include/deal.II/fe/fe_trace.h +++ b/include/deal.II/fe/fe_trace.h @@ -125,17 +125,11 @@ public: FullMatrix &matrix) const override; /** - * Return whether this element dominates the one given as argument when they - * meet at a common face, whether it is the other way around, whether - * neither dominates, or if either could dominate. - * - * For a definition of domination, see FiniteElementDomination::Domination - * and in particular the - * @ref hp_paper "hp paper". + * @copydoc FiniteElement::compare_for_domination() */ virtual FiniteElementDomination::Domination - compare_for_face_domination( - const FiniteElement &fe_other) const override; + compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim = 0) const override final; private: /** diff --git a/include/deal.II/hp/fe_collection.h b/include/deal.II/hp/fe_collection.h index 10e09287e7..c078660001 100644 --- a/include/deal.II/hp/fe_collection.h +++ b/include/deal.II/hp/fe_collection.h @@ -252,17 +252,15 @@ namespace hp * within that set of dominating elements, we find the least * dominant one. * - * For example, if - * an FECollection consists of `{FE_Q(1),FE_Q(2),FE_Q(3),FE_Q(4)}` elements + * 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. * - * 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 + * 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 @@ -276,30 +274,70 @@ namespace hp * a single element `{3}`, then the function returns 3. * * 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 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. + * 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. + * + * @deprecated Use + * hp::FECollection::find_least_face_dominating_fe_in_collection(fes, 1) + * instead. */ - unsigned int - find_least_face_dominating_fe_in_collection( - const std::set &fes) const; + DEAL_II_DEPRECATED unsigned int + find_least_face_dominating_fe(const std::set &fes) const; /** - * @copydoc FECollection::find_least_face_dominating_fe_in_collection() + * 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. + * + * 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. + * + * 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 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. * - * @deprecated This function has been renamed. Use - * hp::FECollection::find_least_face_dominating_fe_in_collection() instead. + * 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. + * + * The @p codim parameter describes the codimension of of the investigated + * subspace and specifies that it is subject to this comparison. */ - DEAL_II_DEPRECATED unsigned int - find_least_face_dominating_fe(const std::set &fes) const; + unsigned int + find_least_dominating_fe_in_collection(const std::set &fes, + const unsigned int codim = 0) const; /** * Try to find a most face dominating finite element inside the subset of @@ -310,8 +348,9 @@ namespace hp * answer is FE_Q(3) and therefore this function will return its index in * the FECollection, namely `2`. * - * This function differs from find_least_face_dominating_fe() in such a way - * that it looks for the most dominating finite element within the given + * 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. * @@ -324,9 +363,13 @@ namespace hp * * If the function is not able to find a finite element, the function * 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. */ unsigned int - find_face_dominating_fe_in_subset(const std::set &fes) const; + find_dominating_fe_in_subset(const std::set &fes, + const unsigned int codim = 0) const; /** * Return a component mask with as many elements as this object has vector diff --git a/source/distributed/active_fe_indices_transfer.cc b/source/distributed/active_fe_indices_transfer.cc index e956c7f6bb..60ea718f17 100644 --- a/source/distributed/active_fe_indices_transfer.cc +++ b/source/distributed/active_fe_indices_transfer.cc @@ -138,9 +138,10 @@ namespace parallel fe_indices_children.insert(child->active_fe_index()); } - fe_index = dof_handler->get_fe() - .find_least_face_dominating_fe_in_collection( - fe_indices_children); + fe_index = + dof_handler->get_fe_collection() + .find_least_dominating_fe_in_collection(fe_indices_children, + /*codim=*/0); Assert(fe_index != numbers::invalid_unsigned_int, ExcMessage( diff --git a/source/distributed/cell_weights.cc b/source/distributed/cell_weights.cc index c031c46543..365c86051f 100644 --- a/source/distributed/cell_weights.cc +++ b/source/distributed/cell_weights.cc @@ -150,8 +150,9 @@ namespace parallel cell->child(child_index)->active_fe_index()); fe_index = - dof_handler->get_fe().find_least_face_dominating_fe_in_collection( - fe_indices_children); + dof_handler->get_fe_collection() + .find_least_dominating_fe_in_collection(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 e1b57c8da4..4c4f5d9f26 100644 --- a/source/distributed/solution_transfer.cc +++ b/source/distributed/solution_transfer.cc @@ -253,8 +253,8 @@ namespace parallel cell->child(child_index)->active_fe_index()); fe_index = dof_handler->get_fe_collection() - .find_least_face_dominating_fe_in_collection( - fe_indices_children); + .find_least_dominating_fe_in_collection( + 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 7297b43163..613746b074 100644 --- a/source/dofs/dof_handler_policy.cc +++ b/source/dofs/dof_handler_policy.cc @@ -968,7 +968,8 @@ namespace internal // the ones that are used on this line const unsigned int most_dominating_fe_index = dof_handler.get_fe_collection() - .find_face_dominating_fe_in_subset(fe_indices); + .find_dominating_fe_in_subset(fe_indices, + /*codim=*/dim - 1); // if we found the most dominating element, then use this // to eliminate some of the degrees of freedom by @@ -1127,7 +1128,8 @@ namespace internal // element of the ones that are used on this quad const unsigned int most_dominating_fe_index = dof_handler.get_fe_collection() - .find_face_dominating_fe_in_subset(fe_indices); + .find_dominating_fe_in_subset(fe_indices, + /*codim=*/dim - 2); // if we found the most dominating element, then use // this to eliminate some of the degrees of freedom @@ -1681,7 +1683,8 @@ namespace internal // the ones that are used on this line const unsigned int most_dominating_fe_index = dof_handler.get_fe_collection() - .find_face_dominating_fe_in_subset(fe_indices); + .find_dominating_fe_in_subset(fe_indices, + /*codim=*/dim - 1); // if we found the most dominating element, then use this // to eliminate some of the degrees of freedom by @@ -1823,7 +1826,8 @@ namespace internal // element of the ones that are used on this quad const unsigned int most_dominating_fe_index = dof_handler.get_fe_collection() - .find_face_dominating_fe_in_subset(fe_indices); + .find_dominating_fe_in_subset(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 c0ecfcdefa..86348638f9 100644 --- a/source/dofs/dof_tools_constraints.cc +++ b/source/dofs/dof_tools_constraints.cc @@ -1145,8 +1145,8 @@ namespace DoFTools { mother_face_dominates = mother_face_dominates & - (cell->get_fe().compare_for_face_domination( - subcell->get_fe())); + (cell->get_fe().compare_for_domination( + subcell->get_fe(), /*codim=*/1)); fe_ind_face_subface.insert( subcell->active_fe_index()); } @@ -1199,8 +1199,9 @@ namespace DoFTools // subface between FE_Q(1) and FE_Nothing, there are // no constraints that we need to take care of. in // that case, just continue - if (cell->get_fe().compare_for_face_domination( - subface->get_fe(subface_fe_index)) == + if (cell->get_fe().compare_for_domination( + subface->get_fe(subface_fe_index), + /*codim=*/1) == FiniteElementDomination::no_requirements) continue; @@ -1284,21 +1285,20 @@ namespace DoFTools // 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_face_dominating_fe_in_collection() + // 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 // neither_element_dominates (e.g. Q1xQ1xQ2 and Q1xQ2xQ1 // for subfaces and Q2xQ1xQ1 for mother face). This // requires usage of - // find_least_face_dominating_fe_in_collection() with + // find_least_dominating_fe_in_collection() with // fe_indices of 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_face_dominating_fe_in_collection( - fe_ind_face_subface); + fe_collection.find_least_dominating_fe_in_collection( + fe_ind_face_subface, /*codim=*/1); AssertThrow( dominating_fe_index != numbers::invalid_unsigned_int, ExcMessage( @@ -1494,8 +1494,9 @@ namespace DoFTools neighbor = cell->neighbor(face); // see which side of the face we have to constrain - switch (cell->get_fe().compare_for_face_domination( - neighbor->get_fe())) + switch ( + cell->get_fe().compare_for_domination(neighbor->get_fe(), + /*codim=*/1)) { case FiniteElementDomination::this_element_dominates: { @@ -1597,8 +1598,8 @@ namespace DoFTools &fe_collection = dof_handler.get_fe_collection(); const unsigned int dominating_fe_index = fe_collection - .find_least_face_dominating_fe_in_collection( - fes); + .find_least_dominating_fe_in_collection( + fes, /*codim=*/1); AssertThrow( dominating_fe_index != diff --git a/source/fe/fe.cc b/source/fe/fe.cc index b35ab09ab7..74e768387c 100644 --- a/source/fe/fe.cc +++ b/source/fe/fe.cc @@ -962,7 +962,18 @@ FiniteElement::hp_quad_dof_identities( template FiniteElementDomination::Domination FiniteElement::compare_for_face_domination( - const FiniteElement &) const + const FiniteElement &fe_other) const +{ + return this->compare_for_domination(fe_other, 1); +} + + + +template +FiniteElementDomination::Domination +FiniteElement::compare_for_domination( + const FiniteElement &, + const unsigned int) const { Assert(false, ExcNotImplemented()); return FiniteElementDomination::neither_element_dominates; diff --git a/source/fe/fe_bernstein.cc b/source/fe/fe_bernstein.cc index 394ba22f6c..99294631a2 100644 --- a/source/fe/fe_bernstein.cc +++ b/source/fe/fe_bernstein.cc @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -278,9 +279,24 @@ FE_Bernstein::hp_quad_dof_identities( template FiniteElementDomination::Domination -FE_Bernstein::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_Bernstein::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { + Assert(codim <= dim, ExcImpossibleInDim(dim)); + + // vertex/line/face domination + // (if fe_other is derived from FE_DGQ) + // ------------------------------------ + if (codim > 0) + if (dynamic_cast *>(&fe_other) != nullptr) + // there are no requirements between continuous and discontinuous elements + return FiniteElementDomination::no_requirements; + + // vertex/line/face domination + // (if fe_other is not derived from FE_DGQ) + // & cell domination + // ---------------------------------------- if (const FE_Bernstein *fe_b_other = dynamic_cast *>(&fe_other)) { @@ -291,20 +307,16 @@ FE_Bernstein::compare_for_face_domination( else return FiniteElementDomination::other_element_dominates; } - else if (const FE_Nothing *fe_nothing = - dynamic_cast *>(&fe_other)) + else if (const FE_Nothing *fe_nothing = + dynamic_cast *>(&fe_other)) { if (fe_nothing->is_dominating()) - { - return FiniteElementDomination::other_element_dominates; - } + return FiniteElementDomination::other_element_dominates; else - { - // the FE_Nothing has no degrees of freedom and it is typically used - // in a context where we don't require any continuity along the - // interface - return FiniteElementDomination::no_requirements; - } + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; } Assert(false, ExcNotImplemented()); diff --git a/source/fe/fe_dgp.cc b/source/fe/fe_dgp.cc index 0fa056545a..9b43acf48e 100644 --- a/source/fe/fe_dgp.cc +++ b/source/fe/fe_dgp.cc @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -213,14 +214,44 @@ FE_DGP::hp_quad_dof_identities( template FiniteElementDomination::Domination -FE_DGP::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_DGP::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { - // check whether both are discontinuous elements, see the description of - // FiniteElementDomination::Domination - if (dynamic_cast *>(&fe_other) != nullptr) + Assert(codim <= dim, ExcImpossibleInDim(dim)); + + // vertex/line/face domination + // --------------------------- + if (codim > 0) + // this is a discontinuous element, so by definition there will + // be no constraints wherever this element comes together with + // any other kind of element return FiniteElementDomination::no_requirements; + // cell domination + // --------------- + if (const FE_DGP *fe_dgp_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_dgp_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_dgp_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Nothing *fe_nothing = + dynamic_cast *>(&fe_other)) + { + if (fe_nothing->is_dominating()) + return FiniteElementDomination::other_element_dominates; + else + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; + } + Assert(false, ExcNotImplemented()); return FiniteElementDomination::neither_element_dominates; } diff --git a/source/fe/fe_dgp_monomial.cc b/source/fe/fe_dgp_monomial.cc index 759c2d9f83..3e1176bfae 100644 --- a/source/fe/fe_dgp_monomial.cc +++ b/source/fe/fe_dgp_monomial.cc @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -390,16 +391,43 @@ FE_DGPMonomial::hp_quad_dof_identities( template FiniteElementDomination::Domination -FE_DGPMonomial::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_DGPMonomial::compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim) const { - // check whether both are discontinuous - // elements, see - // the description of - // FiniteElementDomination::Domination - if (dynamic_cast *>(&fe_other) != nullptr) + Assert(codim <= dim, ExcImpossibleInDim(dim)); + + // vertex/line/face domination + // --------------------------- + if (codim > 0) + // this is a discontinuous element, so by definition there will + // be no constraints wherever this element comes together with + // any other kind of element return FiniteElementDomination::no_requirements; + // cell domination + // --------------- + if (const FE_DGPMonomial *fe_monomial_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_monomial_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_monomial_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Nothing *fe_nothing = + dynamic_cast *>(&fe_other)) + { + if (fe_nothing->is_dominating()) + return FiniteElementDomination::other_element_dominates; + else + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; + } + Assert(false, ExcNotImplemented()); return FiniteElementDomination::neither_element_dominates; } diff --git a/source/fe/fe_dgp_nonparametric.cc b/source/fe/fe_dgp_nonparametric.cc index 99c94c4aba..140a11c524 100644 --- a/source/fe/fe_dgp_nonparametric.cc +++ b/source/fe/fe_dgp_nonparametric.cc @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -590,16 +591,44 @@ FE_DGPNonparametric::hp_quad_dof_identities( template FiniteElementDomination::Domination -FE_DGPNonparametric::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_DGPNonparametric::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { - // check whether both are discontinuous - // elements, see the description of - // FiniteElementDomination::Domination - if (dynamic_cast *>(&fe_other) != - nullptr) + Assert(codim <= dim, ExcImpossibleInDim(dim)); + + // vertex/line/face domination + // --------------------------- + if (codim > 0) + // this is a discontinuous element, so by definition there will + // be no constraints wherever this element comes together with + // any other kind of element return FiniteElementDomination::no_requirements; + // cell domination + // --------------- + if (const FE_DGPNonparametric *fe_nonparametric_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_nonparametric_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_nonparametric_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Nothing *fe_nothing = + dynamic_cast *>(&fe_other)) + { + if (fe_nothing->is_dominating()) + return FiniteElementDomination::other_element_dominates; + else + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; + } + Assert(false, ExcNotImplemented()); return FiniteElementDomination::neither_element_dominates; } diff --git a/source/fe/fe_dgq.cc b/source/fe/fe_dgq.cc index 439fb5d7b5..07ff80d9a3 100644 --- a/source/fe/fe_dgq.cc +++ b/source/fe/fe_dgq.cc @@ -19,7 +19,14 @@ #include #include +#include #include +#include +#include +#include +#include +#include +#include #include #include @@ -600,13 +607,109 @@ FE_DGQ::hp_quad_dof_identities( template FiniteElementDomination::Domination -FE_DGQ::compare_for_face_domination( - const FiniteElement & /*fe_other*/) const +FE_DGQ::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { - // this is a discontinuous element, so by definition there will - // be no constraints wherever this element comes together with - // any other kind of element - return FiniteElementDomination::no_requirements; + Assert(codim <= dim, ExcImpossibleInDim(dim)); + + // vertex/line/face domination + // --------------------------- + if (codim > 0) + // this is a discontinuous element, so by definition there will + // be no constraints wherever this element comes together with + // any other kind of element + return FiniteElementDomination::no_requirements; + + // cell domination + // --------------- + // The following block of conditionals is rather ugly, but there is currently + // no other way how to deal with a robust comparison of FE_DGQ elements with + // relevant others in the current implementation. + if (const FE_DGQ *fe_dgq_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_dgq_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_dgq_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Q *fe_q_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_q_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_q_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Bernstein *fe_bernstein_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_bernstein_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_bernstein_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Q_Bubbles *fe_bubbles_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_bubbles_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_bubbles_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Q_DG0 *fe_dg0_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_dg0_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_dg0_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Q_iso_Q1 *fe_q_iso_q1_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_q_iso_q1_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_q_iso_q1_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Q_Hierarchical *fe_hierarchical_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_hierarchical_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_hierarchical_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Nothing *fe_nothing = + dynamic_cast *>(&fe_other)) + { + if (fe_nothing->is_dominating()) + return FiniteElementDomination::other_element_dominates; + else + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; + } + + Assert(false, ExcNotImplemented()); + return FiniteElementDomination::neither_element_dominates; } diff --git a/source/fe/fe_enriched.cc b/source/fe/fe_enriched.cc index e6aaa77705..fc0b24487b 100644 --- a/source/fe/fe_enriched.cc +++ b/source/fe/fe_enriched.cc @@ -975,9 +975,14 @@ FE_Enriched::hp_quad_dof_identities( template FiniteElementDomination::Domination -FE_Enriched::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_Enriched::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { + Assert(codim <= dim, ExcImpossibleInDim(dim)); + + // vertex/line/face/cell domination + // -------------------------------- // need to decide which element constrain another. // for example Q(2) dominate Q(4) and thus some DoFs of Q(4) will be // constrained. If we have Q(2) and Q(4)+POU, then it's clear that Q(2) @@ -985,14 +990,14 @@ FE_Enriched::compare_for_face_domination( // However, we need to check for situations like Q(4) vs Q(2)+POU. // In that case the domination for the underlying FEs should be the other way, // but this implies that we can't constrain POU dofs to make the field - // continuous. In that case, through an error + // continuous. In that case, throw an error // if it's also enriched, do domination based on each one's FESystem if (const FE_Enriched *fe_enr_other = dynamic_cast *>(&fe_other)) { - return fe_system->compare_for_face_domination( - fe_enr_other->get_fe_system()); + return fe_system->compare_for_domination(fe_enr_other->get_fe_system(), + codim); } else { @@ -1001,6 +1006,7 @@ FE_Enriched::compare_for_face_domination( } } + template const FullMatrix & FE_Enriched::get_prolongation_matrix( @@ -1258,8 +1264,7 @@ namespace ColorEnriched * 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_face_dominating_fe_in_collection(). If we don't + * 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 @@ -1275,7 +1280,7 @@ namespace ColorEnriched * 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_face_dominating_fe_in_collection. + * 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 diff --git a/source/fe/fe_face.cc b/source/fe/fe_face.cc index 62505a05ae..02db2fb446 100644 --- a/source/fe/fe_face.cc +++ b/source/fe/fe_face.cc @@ -436,15 +436,21 @@ FE_FaceQ::hp_quad_dof_identities( template FiniteElementDomination::Domination -FE_FaceQ::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_FaceQ::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { - if (const FE_FaceQ *fe_q_other = + Assert(codim <= dim, ExcImpossibleInDim(dim)); + (void)codim; + + // vertex/line/face/cell domination + // -------------------------------- + if (const FE_FaceQ *fe_faceq_other = dynamic_cast *>(&fe_other)) { - if (this->degree < fe_q_other->degree) + if (this->degree < fe_faceq_other->degree) return FiniteElementDomination::this_element_dominates; - else if (this->degree == fe_q_other->degree) + else if (this->degree == fe_faceq_other->degree) return FiniteElementDomination::either_element_can_dominate; else return FiniteElementDomination::other_element_dominates; @@ -453,24 +459,18 @@ FE_FaceQ::compare_for_face_domination( dynamic_cast *>(&fe_other)) { if (fe_nothing->is_dominating()) - { - return FiniteElementDomination::other_element_dominates; - } + return FiniteElementDomination::other_element_dominates; else - { - // the FE_Nothing has no degrees of freedom and it is typically used - // in a context where we don't require any continuity along the - // interface - return FiniteElementDomination::no_requirements; - } + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; } Assert(false, ExcNotImplemented()); return FiniteElementDomination::neither_element_dominates; } - - template std::pair, std::vector> FE_FaceQ::get_constant_modes() const @@ -643,16 +643,6 @@ FE_FaceQ<1, spacedim>::hp_quad_dof_identities( -template -FiniteElementDomination::Domination -FE_FaceQ<1, spacedim>::compare_for_face_domination( - const FiniteElement<1, spacedim> & /*fe_other*/) const -{ - return FiniteElementDomination::no_requirements; -} - - - template std::pair, std::vector> FE_FaceQ<1, spacedim>::get_constant_modes() const @@ -830,15 +820,21 @@ FE_FaceP::hp_constraints_are_implemented() const template FiniteElementDomination::Domination -FE_FaceP::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_FaceP::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { - if (const FE_FaceP *fe_q_other = + Assert(codim <= dim, ExcImpossibleInDim(dim)); + (void)codim; + + // vertex/line/face/cell domination + // -------------------------------- + if (const FE_FaceP *fe_facep_other = dynamic_cast *>(&fe_other)) { - if (this->degree < fe_q_other->degree) + if (this->degree < fe_facep_other->degree) return FiniteElementDomination::this_element_dominates; - else if (this->degree == fe_q_other->degree) + else if (this->degree == fe_facep_other->degree) return FiniteElementDomination::either_element_can_dominate; else return FiniteElementDomination::other_element_dominates; @@ -847,16 +843,12 @@ FE_FaceP::compare_for_face_domination( dynamic_cast *>(&fe_other)) { if (fe_nothing->is_dominating()) - { - return FiniteElementDomination::other_element_dominates; - } + return FiniteElementDomination::other_element_dominates; else - { - // the FE_Nothing has no degrees of freedom and it is typically used - // in a context where we don't require any continuity along the - // interface - return FiniteElementDomination::no_requirements; - } + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; } Assert(false, ExcNotImplemented()); diff --git a/source/fe/fe_nedelec.cc b/source/fe/fe_nedelec.cc index 51f5fe7515..c37e8111ff 100644 --- a/source/fe/fe_nedelec.cc +++ b/source/fe/fe_nedelec.cc @@ -2274,9 +2274,14 @@ FE_Nedelec::has_support_on_face(const unsigned int shape_index, template FiniteElementDomination::Domination -FE_Nedelec::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_Nedelec::compare_for_domination(const FiniteElement &fe_other, + const unsigned int codim) const { + Assert(codim <= dim, ExcImpossibleInDim(dim)); + (void)codim; + + // vertex/line/face/cell domination + // -------------------------------- if (const FE_Nedelec *fe_nedelec_other = dynamic_cast *>(&fe_other)) { @@ -2290,29 +2295,13 @@ FE_Nedelec::compare_for_face_domination( else if (const FE_Nothing *fe_nothing = dynamic_cast *>(&fe_other)) { - // TODO: ??? - // the FE_Nothing has no - // degrees of - // freedom. nevertheless, we - // say that the FE_Q element - // dominates so that we don't - // have to force the FE_Q side - // to become a zero function - // and rather allow the - // function to be discontinuous - // along the interface - // return FiniteElementDomination::other_element_dominates; if (fe_nothing->is_dominating()) - { - return FiniteElementDomination::other_element_dominates; - } + return FiniteElementDomination::other_element_dominates; else - { - // the FE_Nothing has no degrees of freedom and it is typically used - // in a context where we don't require any continuity along the - // interface - return FiniteElementDomination::no_requirements; - } + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; } Assert(false, ExcNotImplemented()); diff --git a/source/fe/fe_nothing.cc b/source/fe/fe_nothing.cc index ba1df8393f..1777528ed6 100644 --- a/source/fe/fe_nothing.cc +++ b/source/fe/fe_nothing.cc @@ -206,24 +206,22 @@ operator==(const FiniteElement &f) const template FiniteElementDomination::Domination -FE_Nothing::compare_for_face_domination( - const FiniteElement &fe) const +FE_Nothing::compare_for_domination( + const FiniteElement &fe, + const unsigned int codim) const { - // if FE_Nothing does not dominate, there are no requirements + Assert(codim <= dim, ExcImpossibleInDim(dim)); + (void)codim; + if (!dominate) - { - return FiniteElementDomination::no_requirements; - } - // if it does and the other is FE_Nothing, either can dominate + // if FE_Nothing does not dominate, there are no requirements + return FiniteElementDomination::no_requirements; else if (dynamic_cast *>(&fe) != nullptr) - { - return FiniteElementDomination::either_element_can_dominate; - } - // otherwise we dominate whatever fe is provided + // if it does and the other is FE_Nothing, either can dominate + return FiniteElementDomination::either_element_can_dominate; else - { - return FiniteElementDomination::this_element_dominates; - } + // otherwise we dominate whatever fe is provided + return FiniteElementDomination::this_element_dominates; } diff --git a/source/fe/fe_q.cc b/source/fe/fe_q.cc index e959cd1665..2b5f2ee150 100644 --- a/source/fe/fe_q.cc +++ b/source/fe/fe_q.cc @@ -17,6 +17,8 @@ #include #include +#include +#include #include #include @@ -171,6 +173,54 @@ FE_Q::clone() const } + +template +FiniteElementDomination::Domination +FE_Q::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const +{ + Assert(codim <= dim, ExcImpossibleInDim(dim)); + + // vertex/line/face domination + // (if fe_other is derived from FE_DGQ) + // ------------------------------------ + if (codim > 0) + if (dynamic_cast *>(&fe_other) != nullptr) + // there are no requirements between continuous and discontinuous elements + return FiniteElementDomination::no_requirements; + + // vertex/line/face domination + // (if fe_other is not derived from FE_DGQ) + // & cell domination + // ---------------------------------------- + if (const FE_Q *fe_q_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_q_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_q_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Nothing *fe_nothing = + dynamic_cast *>(&fe_other)) + { + if (fe_nothing->is_dominating()) + return FiniteElementDomination::other_element_dominates; + else + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; + } + + Assert(false, ExcNotImplemented()); + return FiniteElementDomination::neither_element_dominates; +} + + // explicit instantiations #include "fe_q.inst" diff --git a/source/fe/fe_q_base.cc b/source/fe/fe_q_base.cc index fd4f429c22..6d96202b1a 100644 --- a/source/fe/fe_q_base.cc +++ b/source/fe/fe_q_base.cc @@ -887,51 +887,6 @@ FE_Q_Base::hp_quad_dof_identities( -template -FiniteElementDomination::Domination -FE_Q_Base::compare_for_face_domination( - const FiniteElement &fe_other) const -{ - if (const FE_Q_Base *fe_q_other = - dynamic_cast *>( - &fe_other)) - { - if (this->degree < fe_q_other->degree) - return FiniteElementDomination::this_element_dominates; - else if (this->degree == fe_q_other->degree) - return FiniteElementDomination::either_element_can_dominate; - else - return FiniteElementDomination::other_element_dominates; - } - else if (const FE_Nothing *fe_nothing = - dynamic_cast *>(&fe_other)) - { - if (fe_nothing->is_dominating()) - { - return FiniteElementDomination::other_element_dominates; - } - else - { - // the FE_Nothing has no degrees of freedom and it is typically used - // in a context where we don't require any continuity along the - // interface - return FiniteElementDomination::no_requirements; - } - } - else if ((dynamic_cast *>(&fe_other) != - nullptr) || - (dynamic_cast *>(&fe_other) != nullptr)) - { - // there are no requirements between continuous and - // discontinuous elements - return FiniteElementDomination::no_requirements; - } - - Assert(false, ExcNotImplemented()); - return FiniteElementDomination::neither_element_dominates; -} - - //--------------------------------------------------------------------------- // Auxiliary functions //--------------------------------------------------------------------------- diff --git a/source/fe/fe_q_bubbles.cc b/source/fe/fe_q_bubbles.cc index ce0ff54ef8..ba8c36efa9 100644 --- a/source/fe/fe_q_bubbles.cc +++ b/source/fe/fe_q_bubbles.cc @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -505,6 +506,55 @@ FE_Q_Bubbles::get_restriction_matrix( return this->restriction[refinement_case - 1][child]; } + + +template +FiniteElementDomination::Domination +FE_Q_Bubbles::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const +{ + Assert(codim <= dim, ExcImpossibleInDim(dim)); + + // vertex/line/face domination + // (if fe_other is derived from FE_DGQ) + // ------------------------------------ + if (codim > 0) + if (dynamic_cast *>(&fe_other) != nullptr) + // there are no requirements between continuous and discontinuous elements + return FiniteElementDomination::no_requirements; + + // vertex/line/face domination + // (if fe_other is not derived from FE_DGQ) + // & cell domination + // ---------------------------------------- + if (const FE_Q_Bubbles *fe_bubbles_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_bubbles_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_bubbles_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Nothing *fe_nothing = + dynamic_cast *>(&fe_other)) + { + if (fe_nothing->is_dominating()) + return FiniteElementDomination::other_element_dominates; + else + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; + } + + Assert(false, ExcNotImplemented()); + return FiniteElementDomination::neither_element_dominates; +} + + // explicit instantiations #include "fe_q_bubbles.inst" diff --git a/source/fe/fe_q_dg0.cc b/source/fe/fe_q_dg0.cc index f582f5dfe7..6cbc96a7cf 100644 --- a/source/fe/fe_q_dg0.cc +++ b/source/fe/fe_q_dg0.cc @@ -22,6 +22,7 @@ #include +#include #include #include @@ -291,6 +292,53 @@ FE_Q_DG0::get_constant_modes() const +template +FiniteElementDomination::Domination +FE_Q_DG0::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const +{ + Assert(codim <= dim, ExcImpossibleInDim(dim)); + + // vertex/line/face domination + // (if fe_other is derived from FE_DGQ) + // ------------------------------------ + if (codim > 0) + if (dynamic_cast *>(&fe_other) != nullptr) + // there are no requirements between continuous and discontinuous elements + return FiniteElementDomination::no_requirements; + + // vertex/line/face domination + // (if fe_other is not derived from FE_DGQ) + // & cell domination + // ---------------------------------------- + if (const FE_Q_DG0 *fe_dg0_other = + dynamic_cast *>(&fe_other)) + { + if (this->degree < fe_dg0_other->degree) + return FiniteElementDomination::this_element_dominates; + else if (this->degree == fe_dg0_other->degree) + return FiniteElementDomination::either_element_can_dominate; + else + return FiniteElementDomination::other_element_dominates; + } + else if (const FE_Nothing *fe_nothing = + dynamic_cast *>(&fe_other)) + { + if (fe_nothing->is_dominating()) + return FiniteElementDomination::other_element_dominates; + else + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; + } + + Assert(false, ExcNotImplemented()); + return FiniteElementDomination::neither_element_dominates; +} + + // explicit instantiations #include "fe_q_dg0.inst" diff --git a/source/fe/fe_q_hierarchical.cc b/source/fe/fe_q_hierarchical.cc index 06294e3aa2..a46b0106b2 100644 --- a/source/fe/fe_q_hierarchical.cc +++ b/source/fe/fe_q_hierarchical.cc @@ -16,6 +16,7 @@ #include +#include #include #include @@ -333,17 +334,30 @@ FE_Q_Hierarchical::hp_quad_dof_identities( template FiniteElementDomination::Domination -FE_Q_Hierarchical::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_Q_Hierarchical::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { - if (const FE_Q_Hierarchical *fe_q_other = + Assert(codim <= dim, ExcImpossibleInDim(dim)); + + // vertex/line/face domination + // (if fe_other is derived from FE_DGQ) + // ------------------------------------ + if (codim > 0) + if (dynamic_cast *>(&fe_other) != nullptr) + // there are no requirements between continuous and discontinuous elements + return FiniteElementDomination::no_requirements; + + // vertex/line/face domination + // (if fe_other is not derived from FE_DGQ) + // & cell domination + // ---------------------------------------- + if (const FE_Q_Hierarchical *fe_hierarchical_other = dynamic_cast *>(&fe_other)) { - // the element with lowest polynomial degree - // dominates the other. - if (this->degree < fe_q_other->degree) + if (this->degree < fe_hierarchical_other->degree) return FiniteElementDomination::this_element_dominates; - else if (this->degree == fe_q_other->degree) + else if (this->degree == fe_hierarchical_other->degree) return FiniteElementDomination::either_element_can_dominate; else return FiniteElementDomination::other_element_dominates; @@ -352,16 +366,12 @@ FE_Q_Hierarchical::compare_for_face_domination( dynamic_cast *>(&fe_other)) { if (fe_nothing->is_dominating()) - { - return FiniteElementDomination::other_element_dominates; - } + return FiniteElementDomination::other_element_dominates; else - { - // the FE_Nothing has no degrees of freedom and it is typically used - // in a context where we don't require any continuity along the - // interface - return FiniteElementDomination::no_requirements; - } + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; } Assert(false, ExcNotImplemented()); diff --git a/source/fe/fe_q_iso_q1.cc b/source/fe/fe_q_iso_q1.cc index 0e1214febe..69aed15a54 100644 --- a/source/fe/fe_q_iso_q1.cc +++ b/source/fe/fe_q_iso_q1.cc @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -106,9 +107,25 @@ FE_Q_iso_Q1::clone() const template FiniteElementDomination::Domination -FE_Q_iso_Q1::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_Q_iso_Q1::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { + Assert(codim <= dim, ExcImpossibleInDim(dim)); + (void)codim; + + // vertex/line/face domination + // (if fe_other is derived from FE_DGQ) + // ------------------------------------ + if (codim > 0) + if (dynamic_cast *>(&fe_other) != nullptr) + // there are no requirements between continuous and discontinuous elements + return FiniteElementDomination::no_requirements; + + // vertex/line/face domination + // (if fe_other is not derived from FE_DGQ) + // & cell domination + // ---------------------------------------- if (const FE_Q_iso_Q1 *fe_q_iso_q1_other = dynamic_cast *>(&fe_other)) { @@ -130,16 +147,12 @@ FE_Q_iso_Q1::compare_for_face_domination( dynamic_cast *>(&fe_other)) { if (fe_nothing->is_dominating()) - { - return FiniteElementDomination::other_element_dominates; - } + return FiniteElementDomination::other_element_dominates; else - { - // the FE_Nothing has no degrees of freedom and it is typically used - // in a context where we don't require any continuity along the - // interface - return FiniteElementDomination::no_requirements; - } + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; } Assert(false, ExcNotImplemented()); diff --git a/source/fe/fe_raviart_thomas_nodal.cc b/source/fe/fe_raviart_thomas_nodal.cc index 038a255659..7368158080 100644 --- a/source/fe/fe_raviart_thomas_nodal.cc +++ b/source/fe/fe_raviart_thomas_nodal.cc @@ -505,33 +505,35 @@ FE_RaviartThomasNodal::hp_quad_dof_identities( template FiniteElementDomination::Domination -FE_RaviartThomasNodal::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_RaviartThomasNodal::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { - if (const FE_RaviartThomasNodal *fe_q_other = + Assert(codim <= dim, ExcImpossibleInDim(dim)); + (void)codim; + + // vertex/line/face/cell domination + // -------------------------------- + if (const FE_RaviartThomasNodal *fe_rt_nodal_other = dynamic_cast *>(&fe_other)) { - if (this->degree < fe_q_other->degree) + if (this->degree < fe_rt_nodal_other->degree) return FiniteElementDomination::this_element_dominates; - else if (this->degree == fe_q_other->degree) + else if (this->degree == fe_rt_nodal_other->degree) return FiniteElementDomination::either_element_can_dominate; else return FiniteElementDomination::other_element_dominates; } - else if (const FE_Nothing *fe_q_other = + else if (const FE_Nothing *fe_nothing = dynamic_cast *>(&fe_other)) { - if (fe_q_other->is_dominating()) - { - return FiniteElementDomination::other_element_dominates; - } + if (fe_nothing->is_dominating()) + return FiniteElementDomination::other_element_dominates; else - { - // FE_Nothing has no degrees of freedom and is typically - // used in a context where there are no continuity - // requirements along the interface - return FiniteElementDomination::no_requirements; - } + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; } Assert(false, ExcNotImplemented()); diff --git a/source/fe/fe_system.cc b/source/fe/fe_system.cc index 89f88c634f..55a9f52c3e 100644 --- a/source/fe/fe_system.cc +++ b/source/fe/fe_system.cc @@ -2245,9 +2245,14 @@ FESystem::hp_quad_dof_identities( template FiniteElementDomination::Domination -FESystem::compare_for_face_domination( - const FiniteElement &fe_other) const +FESystem::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { + Assert(codim <= dim, ExcImpossibleInDim(dim)); + + // vertex/line/face/cell domination + // -------------------------------- // at present all we can do is to compare with other FESystems that have the // same number of components and bases if (const FESystem *fe_sys_other = @@ -2274,8 +2279,8 @@ FESystem::compare_for_face_domination( // for this pair of base elements, check who dominates and combine // with previous result const FiniteElementDomination::Domination base_domination = - (this->base_element(b).compare_for_face_domination( - fe_sys_other->base_element(b))); + (this->base_element(b).compare_for_domination( + fe_sys_other->base_element(b), codim)); domination = domination & base_domination; } diff --git a/source/fe/fe_trace.cc b/source/fe/fe_trace.cc index 083260b6b9..9761c8b1f1 100644 --- a/source/fe/fe_trace.cc +++ b/source/fe/fe_trace.cc @@ -177,15 +177,21 @@ FE_TraceQ::hp_constraints_are_implemented() const template FiniteElementDomination::Domination -FE_TraceQ::compare_for_face_domination( - const FiniteElement &fe_other) const +FE_TraceQ::compare_for_domination( + const FiniteElement &fe_other, + const unsigned int codim) const { - if (const FE_TraceQ *fe_q_other = + Assert(codim <= dim, ExcImpossibleInDim(dim)); + (void)codim; + + // vertex/line/face/cell domination + // -------------------------------- + if (const FE_TraceQ *fe_traceq_other = dynamic_cast *>(&fe_other)) { - if (this->degree < fe_q_other->degree) + if (this->degree < fe_traceq_other->degree) return FiniteElementDomination::this_element_dominates; - else if (this->degree == fe_q_other->degree) + else if (this->degree == fe_traceq_other->degree) return FiniteElementDomination::either_element_can_dominate; else return FiniteElementDomination::other_element_dominates; @@ -194,16 +200,12 @@ FE_TraceQ::compare_for_face_domination( dynamic_cast *>(&fe_other)) { if (fe_nothing->is_dominating()) - { - return FiniteElementDomination::other_element_dominates; - } + return FiniteElementDomination::other_element_dominates; else - { - // the FE_Nothing has no degrees of freedom and it is typically used - // in a context where we don't require any continuity along the - // interface - return FiniteElementDomination::no_requirements; - } + // the FE_Nothing has no degrees of freedom and it is typically used + // in a context where we don't require any continuity along the + // interface + return FiniteElementDomination::no_requirements; } Assert(false, ExcNotImplemented()); diff --git a/source/hp/fe_collection.cc b/source/hp/fe_collection.cc index 4677a30efb..ce980da3b6 100644 --- a/source/hp/fe_collection.cc +++ b/source/hp/fe_collection.cc @@ -24,9 +24,22 @@ namespace hp { template unsigned int - FECollection::find_least_face_dominating_fe_in_collection( + FECollection::find_least_face_dominating_fe( const std::set &fes) const { + return find_least_dominating_fe_in_collection(fes, /*codim*/ 1); + } + + + + template + unsigned int + FECollection::find_least_dominating_fe_in_collection( + const std::set &fes, + const unsigned int codim) const + { + Assert(codim <= dim, ExcImpossibleInDim(dim)); + for (auto it = fes.cbegin(); it != fes.cend(); ++it) AssertIndexRange(*it, finite_elements.size()); @@ -52,8 +65,8 @@ namespace hp // 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_face_domination( - *finite_elements[other_fe]); + domination & finite_elements[cur_fe]->compare_for_domination( + *finite_elements[other_fe], codim); // if we found dominating element, keep them in a set. if ( @@ -76,10 +89,9 @@ namespace hp for (const auto &other_fe : candidate_fes) if (current_fe != other_fe) - domination = - domination & - finite_elements[current_fe]->compare_for_face_domination( - *finite_elements[other_fe]); + domination = domination & + finite_elements[current_fe]->compare_for_domination( + *finite_elements[other_fe], codim); if ((domination == FiniteElementDomination::other_element_dominates) || @@ -96,19 +108,12 @@ namespace hp template unsigned int - FECollection::find_least_face_dominating_fe( - const std::set &fes) const + FECollection::find_dominating_fe_in_subset( + const std::set &fes, + const unsigned int codim) const { - return find_least_face_dominating_fe_in_collection(fes); - } - - + Assert(codim <= dim, ExcImpossibleInDim(dim)); - template - unsigned int - FECollection::find_face_dominating_fe_in_subset( - const std::set &fes) const - { for (auto it = fes.cbegin(); it != fes.cend(); ++it) AssertIndexRange(*it, finite_elements.size()); @@ -131,9 +136,8 @@ namespace hp for (const auto &other_fe : fes) if (other_fe != current_fe) domination = - domination & - finite_elements[current_fe]->compare_for_face_domination( - *finite_elements[other_fe]); + 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 diff --git a/tests/fe/fe_enriched_color_08.cc b/tests/fe/fe_enriched_color_08.cc index 8e5f849c07..f3640f39af 100644 --- a/tests/fe/fe_enriched_color_08.cc +++ b/tests/fe/fe_enriched_color_08.cc @@ -268,8 +268,9 @@ main(int argc, char **argv) << std::endl; } - deallog << "Dominating set for 1 and 2: " - << fe_collection.find_least_face_dominating_fe_in_collection({1, 2}) + deallog << "Face dominating set for 1 and 2: " + << fe_collection.find_least_dominating_fe_in_collection({1, 2}, + /*codim=*/1) << std::endl; dof_handler.distribute_dofs(fe_collection); diff --git a/tests/fe/fe_enriched_color_08.with_mpi=true.with_trilinos=true.with_trilinos_with_zoltan=true.output b/tests/fe/fe_enriched_color_08.with_mpi=true.with_trilinos=true.with_trilinos_with_zoltan=true.output index 675f3567bb..270629affe 100644 --- a/tests/fe/fe_enriched_color_08.with_mpi=true.with_trilinos=true.with_trilinos_with_zoltan=true.output +++ b/tests/fe/fe_enriched_color_08.with_mpi=true.with_trilinos=true.with_trilinos_with_zoltan=true.output @@ -16,7 +16,7 @@ DEAL:0::name:FE_Enriched<2>[FE_Q<2>(2)-FE_Nothing<2>(dominating)-FE_Nothing<2>(d DEAL:0::n_blocks:4 DEAL:0::n_comp:1 DEAL:0::n_dofs:13 -DEAL:0::Dominating set for 1 and 2: 3 +DEAL:0::Face dominating set for 1 and 2: 3 9 = 0 10 = 0 12 = 0 diff --git a/tests/hp/fe_collection_05.cc b/tests/hp/fe_collection_05.cc index 5ad07d1344..5285334087 100644 --- a/tests/hp/fe_collection_05.cc +++ b/tests/hp/fe_collection_05.cc @@ -15,7 +15,8 @@ /* clang-format off */ -// test the results of FECollection::find_least_face_dominating_fe_in_collection(), namely for: +// test the results of FECollection::find_least_dominating_fe_in_collection() +// for faces (codim=1), namely for: // {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 @@ -53,7 +54,8 @@ 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_face_dominating_fe_in_collection(fes) + deallog << fe_collection.find_least_dominating_fe_in_collection(fes, + /*codim=*/1) << std::endl; } @@ -64,7 +66,8 @@ 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_face_dominating_fe_in_collection(fes) + deallog << fe_collection.find_least_dominating_fe_in_collection(fes, + /*codim=*/1) << std::endl; } @@ -77,7 +80,8 @@ test() std::set fes; fes.insert(1); fes.insert(2); - deallog << fe_collection.find_least_face_dominating_fe_in_collection(fes) + deallog << fe_collection.find_least_dominating_fe_in_collection(fes, + /*codim=*/1) << std::endl; } @@ -93,7 +97,7 @@ test() fe_collection.push_back( FESystem(FE_Nothing(), 1, FE_Q(1), 1)); const unsigned int ind = - fe_collection.find_least_face_dominating_fe_in_collection(fes); + fe_collection.find_least_dominating_fe_in_collection(fes, /*codim=*/1); if (ind == numbers::invalid_unsigned_int) deallog << "numbers::invalid_unsigned_int" << std::endl; else @@ -112,7 +116,8 @@ 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_face_dominating_fe_in_collection(fes) + deallog << fe_collection.find_least_dominating_fe_in_collection(fes, + /*codim=*/1) << std::endl; } @@ -124,7 +129,8 @@ 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_face_dominating_fe_in_collection(fes) + deallog << fe_collection.find_least_dominating_fe_in_collection(fes, + /*codim=*/1) << std::endl; } @@ -136,7 +142,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_face_dominating_fe_in_collection(fes); + fe_collection.find_least_dominating_fe_in_collection(fes, /*codim=*/1); if (ind == numbers::invalid_unsigned_int) deallog << "numbers::invalid_unsigned_int" << std::endl; else @@ -152,7 +158,8 @@ test() fe_collection.push_back(FE_Q(3)); std::set fes; fes.insert(3); - deallog << fe_collection.find_least_face_dominating_fe_in_collection(fes) + deallog << fe_collection.find_least_dominating_fe_in_collection(fes, + /*codim=*/1) << std::endl; } @@ -163,7 +170,8 @@ 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_face_dominating_fe_in_collection(fes) + deallog << fe_collection.find_least_dominating_fe_in_collection(fes, + /*codim=*/1) << std::endl; } }