From 80b12a1e24ea777e31433694f8906bf409c71c1f Mon Sep 17 00:00:00 2001 From: bangerth Date: Fri, 1 Sep 2006 18:28:47 +0000 Subject: [PATCH] Implement domination information for at least some of the elements git-svn-id: https://svn.dealii.org/trunk@13789 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/deal.II/include/fe/fe.h | 15 ++ deal.II/deal.II/include/fe/fe_base.h | 82 +++++++++++ deal.II/deal.II/include/fe/fe_dgp.h | 15 ++ deal.II/deal.II/include/fe/fe_dgp_monomial.h | 15 ++ .../deal.II/include/fe/fe_dgp_nonparametric.h | 15 ++ deal.II/deal.II/include/fe/fe_dgq.h | 15 ++ deal.II/deal.II/include/fe/fe_q.h | 14 ++ deal.II/deal.II/include/fe/fe_system.h | 14 ++ deal.II/deal.II/source/fe/fe.cc | 12 ++ deal.II/deal.II/source/fe/fe_dgp.cc | 17 +++ deal.II/deal.II/source/fe/fe_dgp_monomial.cc | 18 +++ .../deal.II/source/fe/fe_dgp_nonparametric.cc | 18 +++ deal.II/deal.II/source/fe/fe_q.cc | 23 ++++ deal.II/deal.II/source/fe/fe_system.cc | 130 ++++++++++++++++++ 14 files changed, 403 insertions(+) diff --git a/deal.II/deal.II/include/fe/fe.h b/deal.II/deal.II/include/fe/fe.h index 3be9e369f6..286334e481 100644 --- a/deal.II/deal.II/include/fe/fe.h +++ b/deal.II/deal.II/include/fe/fe.h @@ -1059,6 +1059,21 @@ class FiniteElement : public Subscriptor, virtual std::vector > hp_quad_dof_identities (const FiniteElement &fe_other) const; + + /** + * Return whether this element dominates + * the one given as argument, 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 hp paper. + */ + virtual + typename FiniteElementData::Domination + compare_for_domination (const FiniteElement &fe_other) const; //@} diff --git a/deal.II/deal.II/include/fe/fe_base.h b/deal.II/deal.II/include/fe/fe_base.h index 349df628d5..066c71fd52 100644 --- a/deal.II/deal.II/include/fe/fe_base.h +++ b/deal.II/deal.II/include/fe/fe_base.h @@ -155,6 +155,81 @@ class FiniteElementData */ H2 = 0x0e }; + + /** + * An enum that describes the + * outcome of comparing two elements for + * mutual domination. If one element + * dominates another, then the + * restriction of the space described by + * the dominated element to a face of the + * cell is 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'$. + * + * This enum is used in the + * FiniteElement::compare_fe_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 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 other side. The determination + * which side is which is based on the + * outcome of a comparison for mutual + * domination: the dominated side is + * constrained to the dominating one. + * + * Note that there are situations where + * neither side dominates. The hp paper + * lists two case, with the simpler one + * being that a $Q_2\times Q_1$ + * vector-valued element (i.e. a + * FESystem(FE_Q(2),1,FE_Q(1),1)) + * meets a $Q_1\times Q_2$ element: here, + * for each of the two vector-components, + * we can define a domination + * relationship, but it is different for + * the two components. + * + * It is clear that the concept of + * domination doesn't matter for + * discontinuous elements. However, + * discontinuous elements may be part of + * vector-valued elements and may + * therefore be compared against each + * other for domination. They should + * return + * either_element_can_dominate + * in that case. Likewise, when comparing + * two identical finite elements, they + * should return this code; the reason is + * that we can not decide which element + * will dominate at the time we look at + * the first component of, for example, + * two $Q_2\times Q_1$ and $Q_2\times + * Q_2$ elements, and have to keep our + * options open until we get to the + * second base element. + */ + enum Domination + { + this_element_dominates, + other_element_dominates, + neither_element_dominates, + either_element_can_dominate + }; + + /** * Number of degrees of freedom on @@ -472,6 +547,7 @@ class FiniteElementData }; + // --------- inline and template functions --------------- template @@ -483,6 +559,7 @@ FiniteElementData::n_dofs_per_vertex () const } + template inline unsigned int @@ -492,6 +569,7 @@ FiniteElementData::n_dofs_per_line () const } + template inline unsigned int @@ -501,6 +579,7 @@ FiniteElementData::n_dofs_per_quad () const } + template inline unsigned int @@ -510,6 +589,7 @@ FiniteElementData::n_dofs_per_hex () const } + template inline unsigned int @@ -519,6 +599,7 @@ FiniteElementData::n_dofs_per_face () const } + template inline unsigned int @@ -552,6 +633,7 @@ FiniteElementData::n_dofs_per_object () const } + template inline unsigned int diff --git a/deal.II/deal.II/include/fe/fe_dgp.h b/deal.II/deal.II/include/fe/fe_dgp.h index a1ffce4ac8..97a9dbd340 100644 --- a/deal.II/deal.II/include/fe/fe_dgp.h +++ b/deal.II/deal.II/include/fe/fe_dgp.h @@ -115,6 +115,21 @@ class FE_DGP : public FE_Poly,dim> */ virtual bool hp_constraints_are_implemented () const; + /** + * Return whether this element dominates + * the one given as argument, 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 hp paper. + */ + virtual + typename FiniteElementData::Domination + compare_for_domination (const FiniteElement &fe_other) const; + /** * Return the matrix * interpolating from a face of diff --git a/deal.II/deal.II/include/fe/fe_dgp_monomial.h b/deal.II/deal.II/include/fe/fe_dgp_monomial.h index 9210b66e85..7d2a27deab 100644 --- a/deal.II/deal.II/include/fe/fe_dgp_monomial.h +++ b/deal.II/deal.II/include/fe/fe_dgp_monomial.h @@ -116,6 +116,21 @@ class FE_DGPMonomial : public FE_Poly,dim> */ virtual bool hp_constraints_are_implemented () const; + /** + * Return whether this element dominates + * the one given as argument, 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 hp paper. + */ + virtual + typename FiniteElementData::Domination + compare_for_domination (const FiniteElement &fe_other) const; + /** * Return the matrix * interpolating from the given diff --git a/deal.II/deal.II/include/fe/fe_dgp_nonparametric.h b/deal.II/deal.II/include/fe/fe_dgp_nonparametric.h index 2c85dbd6d9..9d6031478f 100644 --- a/deal.II/deal.II/include/fe/fe_dgp_nonparametric.h +++ b/deal.II/deal.II/include/fe/fe_dgp_nonparametric.h @@ -271,6 +271,21 @@ class FE_DGPNonparametric : public FiniteElement */ virtual bool hp_constraints_are_implemented () const; + /** + * Return whether this element dominates + * the one given as argument, 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 hp paper. + */ + virtual + typename FiniteElementData::Domination + compare_for_domination (const FiniteElement &fe_other) const; + /** * Check for non-zero values on a face. * diff --git a/deal.II/deal.II/include/fe/fe_dgq.h b/deal.II/deal.II/include/fe/fe_dgq.h index 57f9e5b6ee..a9ecfb6dff 100644 --- a/deal.II/deal.II/include/fe/fe_dgq.h +++ b/deal.II/deal.II/include/fe/fe_dgq.h @@ -187,6 +187,21 @@ class FE_DGQ : public FE_Poly,dim> */ virtual bool hp_constraints_are_implemented () const; + /** + * Return whether this element dominates + * the one given as argument, 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 hp paper. + */ + virtual + typename FiniteElementData::Domination + compare_for_domination (const FiniteElement &fe_other) const; + /** * Check for non-zero values on a face. * diff --git a/deal.II/deal.II/include/fe/fe_q.h b/deal.II/deal.II/include/fe/fe_q.h index 2b32672c7f..c90ee992a3 100644 --- a/deal.II/deal.II/include/fe/fe_q.h +++ b/deal.II/deal.II/include/fe/fe_q.h @@ -421,6 +421,20 @@ class FE_Q : public FE_Poly,dim> std::vector > hp_quad_dof_identities (const FiniteElement &fe_other) const; + /** + * Return whether this element dominates + * the one given as argument, 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 hp paper. + */ + virtual + typename FiniteElementData::Domination + compare_for_domination (const FiniteElement &fe_other) const; //@} /** diff --git a/deal.II/deal.II/include/fe/fe_system.h b/deal.II/deal.II/include/fe/fe_system.h index 7a6636a8fd..cb0eb81ac8 100644 --- a/deal.II/deal.II/include/fe/fe_system.h +++ b/deal.II/deal.II/include/fe/fe_system.h @@ -523,6 +523,20 @@ class FESystem : public FiniteElement std::vector > hp_quad_dof_identities (const FiniteElement &fe_other) const; + /** + * Return whether this element dominates + * the one given as argument, 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 hp paper. + */ + virtual + typename FiniteElementData::Domination + compare_for_domination (const FiniteElement &fe_other) const; //@} /** diff --git a/deal.II/deal.II/source/fe/fe.cc b/deal.II/deal.II/source/fe/fe.cc index 6cc38f3759..f5f620729a 100644 --- a/deal.II/deal.II/source/fe/fe.cc +++ b/deal.II/deal.II/source/fe/fe.cc @@ -332,6 +332,7 @@ FiniteElement::component_to_block_index (const unsigned int index) const } + template bool FiniteElement::prolongation_is_implemented () const @@ -517,6 +518,17 @@ hp_quad_dof_identities (const FiniteElement &) const +template +typename FiniteElementData::Domination +FiniteElement:: +compare_for_domination (const FiniteElement &) const +{ + Assert (false, ExcNotImplemented()); + return FiniteElementData::neither_element_dominates; +} + + + template bool FiniteElement::operator == (const FiniteElement &f) const diff --git a/deal.II/deal.II/source/fe/fe_dgp.cc b/deal.II/deal.II/source/fe/fe_dgp.cc index 6736e464e0..3e99b0892d 100644 --- a/deal.II/deal.II/source/fe/fe_dgp.cc +++ b/deal.II/deal.II/source/fe/fe_dgp.cc @@ -155,6 +155,23 @@ FE_DGP::hp_constraints_are_implemented () const +template +typename FiniteElementData::Domination +FE_DGP::compare_for_domination (const FiniteElement &fe_other) const +{ + // check whether both are discontinuous + // elements and both could dominate, see + // the description of + // FiniteElementData::Domination + if (dynamic_cast*>(&fe_other) != 0) + return FiniteElementData::either_element_can_dominate; + + Assert (false, ExcNotImplemented()); + return FiniteElementData::neither_element_dominates; +} + + + template bool FE_DGP::has_support_on_face (const unsigned int, diff --git a/deal.II/deal.II/source/fe/fe_dgp_monomial.cc b/deal.II/deal.II/source/fe/fe_dgp_monomial.cc index 3585425791..347ea12afc 100644 --- a/deal.II/deal.II/source/fe/fe_dgp_monomial.cc +++ b/deal.II/deal.II/source/fe/fe_dgp_monomial.cc @@ -316,6 +316,24 @@ FE_DGPMonomial::hp_constraints_are_implemented () const +template +typename FiniteElementData::Domination +FE_DGPMonomial:: +compare_for_domination (const FiniteElement &fe_other) const +{ + // check whether both are discontinuous + // elements and both could dominate, see + // the description of + // FiniteElementData::Domination + if (dynamic_cast*>(&fe_other) != 0) + return FiniteElementData::either_element_can_dominate; + + Assert (false, ExcNotImplemented()); + return FiniteElementData::neither_element_dominates; +} + + + #if deal_II_dimension == 1 template <> diff --git a/deal.II/deal.II/source/fe/fe_dgp_nonparametric.cc b/deal.II/deal.II/source/fe/fe_dgp_nonparametric.cc index 584121ae35..73579bdfa2 100644 --- a/deal.II/deal.II/source/fe/fe_dgp_nonparametric.cc +++ b/deal.II/deal.II/source/fe/fe_dgp_nonparametric.cc @@ -485,6 +485,24 @@ FE_DGPNonparametric::hp_constraints_are_implemented () const +template +typename FiniteElementData::Domination +FE_DGPNonparametric:: +compare_for_domination (const FiniteElement &fe_other) const +{ + // check whether both are discontinuous + // elements and both could dominate, see + // the description of + // FiniteElementData::Domination + if (dynamic_cast*>(&fe_other) != 0) + return FiniteElementData::either_element_can_dominate; + + Assert (false, ExcNotImplemented()); + return FiniteElementData::neither_element_dominates; +} + + + template bool FE_DGPNonparametric::has_support_on_face (const unsigned int, diff --git a/deal.II/deal.II/source/fe/fe_q.cc b/deal.II/deal.II/source/fe/fe_q.cc index 7fc62790cc..d32ff982ac 100644 --- a/deal.II/deal.II/source/fe/fe_q.cc +++ b/deal.II/deal.II/source/fe/fe_q.cc @@ -677,6 +677,29 @@ hp_quad_dof_identities (const FiniteElement &fe_other) const } + +template +typename FiniteElementData::Domination +FE_Q:: +compare_for_domination (const FiniteElement &fe_other) const +{ + if (const FE_Q *fe_q_other + = dynamic_cast*>(&fe_other)) + { + if (this->degree < fe_q_other->degree) + return FiniteElementData::this_element_dominates; + else if (this->degree < fe_q_other->degree) + return FiniteElementData::either_element_can_dominate; + else + return FiniteElementData::other_element_dominates; + } + + Assert (false, ExcNotImplemented()); + return FiniteElementData::neither_element_dominates; +} + + + //--------------------------------------------------------------------------- // Auxiliary functions //--------------------------------------------------------------------------- diff --git a/deal.II/deal.II/source/fe/fe_system.cc b/deal.II/deal.II/source/fe/fe_system.cc index 96a41e1e31..d9c04abe0e 100644 --- a/deal.II/deal.II/source/fe/fe_system.cc +++ b/deal.II/deal.II/source/fe/fe_system.cc @@ -2272,6 +2272,136 @@ FESystem::hp_quad_dof_identities (const FiniteElement &fe_other) const +template +typename FiniteElementData::Domination +FESystem:: +compare_for_domination (const FiniteElement &fe_other) const +{ + // 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 + = dynamic_cast*>(&fe_other)) + { + Assert (this->n_components() == fe_sys_other->n_components(), + ExcNotImplemented()); + Assert (this->n_base_elements() == fe_sys_other->n_base_elements(), + ExcNotImplemented()); + + typename FiniteElementData::Domination + domination = FiniteElementData::either_element_can_dominate; + + // loop over all base elements and do + // some sanity checks + for (unsigned int b=0; bn_base_elements(); ++b) + { + Assert (this->base_element(b).n_components() == + fe_sys_other->base_element(b).n_components(), + ExcNotImplemented()); + Assert (this->element_multiplicity(b) == + fe_sys_other->element_multiplicity(b), + ExcNotImplemented()); + + // for this pair of base elements, + // check who dominates + const typename FiniteElementData::Domination + base_domination + = (this->base_element(b) + .compare_for_domination (fe_sys_other->base_element(b))); + + // now see what that means with + // regard to the previous state + switch (domination) + { + case FiniteElementData::either_element_can_dominate: + { + // we haven't made a decision + // yet, simply copy what this + // pair of bases have to say + domination = base_domination; + break; + } + + case FiniteElementData::this_element_dominates: + { + // the present element + // previously dominated. this + // will still be the case if + // either the present base + // dominates or if the two + // bases don't + // care. otherwise, there is + // a tie which we will not be + // able to escape from no + // matter what the other + // pairs of bases are going + // to say + switch (base_domination) + { + case FiniteElementData::either_element_can_dominate: + case FiniteElementData::this_element_dominates: + { + break; + } + + case FiniteElementData::other_element_dominates: + case FiniteElementData::neither_element_dominates: + { + return FiniteElementData::neither_element_dominates; + } + + default: + // shouldn't get + // here + Assert (false, ExcInternalError()); + } + break; + } + + case FiniteElementData::other_element_dominates: + { + // the opposite case + switch (base_domination) + { + case FiniteElementData::either_element_can_dominate: + case FiniteElementData::other_element_dominates: + { + break; + } + + case FiniteElementData::this_element_dominates: + case FiniteElementData::neither_element_dominates: + { + return FiniteElementData::neither_element_dominates; + } + + default: + Assert (false, ExcInternalError()); + } + break; + } + + default: + Assert (false, ExcInternalError()); + } + } + + // if we've gotten here, then we've + // either found a winner or either + // element is fine being dominated + Assert (domination != + FiniteElementData::neither_element_dominates, + ExcInternalError()); + + return domination; + } + + Assert (false, ExcNotImplemented()); + return FiniteElementData::neither_element_dominates; +} + + + template FiniteElementData FESystem::multiply_dof_numbers (const FiniteElementData &fe1, -- 2.39.5