From 150679ddb9144d6b864ed0dc4559da8a1a1278f2 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Mon, 2 Nov 2015 22:33:52 -0600 Subject: [PATCH] Replace update_once/each by requires_update_flags() in FiniteElement. The purpose of this patch is to align the finite element classes with the way the mapping classes have already been converted. Specifically, there is no need for any of the users of finite element classes to actually know whether a FE implementation wants to treat a particular flags as update_once or update_each. This is an internal decision. Rather, all we need to know is what flags they need overall. This is now communicated by the new FiniteElement::requires_update_flags() function. The update_once() and update_each() functions have been retained -- for now -- as internal functions individual elements can implement, but they are no longer virtual. --- include/deal.II/fe/fe.h | 46 ++++++-------- include/deal.II/fe/fe_dgp_nonparametric.h | 9 ++- include/deal.II/fe/fe_face.h | 9 ++- include/deal.II/fe/fe_nothing.h | 32 +--------- include/deal.II/fe/fe_poly.h | 9 ++- include/deal.II/fe/fe_poly.templates.h | 7 +++ include/deal.II/fe/fe_poly_face.h | 9 ++- include/deal.II/fe/fe_poly_face.templates.h | 8 ++- include/deal.II/fe/fe_poly_tensor.h | 30 +++++---- include/deal.II/fe/fe_system.h | 9 ++- source/fe/fe_dgp_nonparametric.cc | 10 +++ source/fe/fe_face.cc | 9 +++ source/fe/fe_nothing.cc | 13 +--- source/fe/fe_poly_tensor.cc | 9 +++ source/fe/fe_system.cc | 69 +++++++++++---------- source/fe/fe_values.cc | 16 +++-- 16 files changed, 160 insertions(+), 134 deletions(-) diff --git a/include/deal.II/fe/fe.h b/include/deal.II/fe/fe.h index 3f3acf7962..70f222997d 100644 --- a/include/deal.II/fe/fe.h +++ b/include/deal.II/fe/fe.h @@ -2169,36 +2169,28 @@ protected: compute_n_nonzero_components (const std::vector &nonzero_components); /** - * Determine the values a finite element should compute on initialization of - * data for FEValues. + * Given a set of update flags, compute which other quantities also + * need to be computed in order to satisfy the request by the given flags. + * Then return the combination of the original set of flags and those + * just computed. + * + * As an example, if @p update_flags contains update_gradients + * a finite element class will typically + * require the computation of the inverse of the Jacobian matrix in order to + * rotate the gradient of shape functions on the reference cell to the + * real cell. It would then return not just + * update_gradients, but also update_covariant_transformation, the flag that + * makes the mapping class produce the inverse of the Jacobian matrix. * - * Given a set of flags indicating what quantities are requested from a - * FEValues object, update_once() and update_each() compute which values - * must really be computed. Then, the fill_*_values functions are - * called with the result of these. - * - * Furthermore, values must be computed either on the unit cell or on the - * physical cell. For instance, the function values of FE_Q do only depend - * on the quadrature points on the unit cell. Therefore, this flags will be - * returned by update_once(). The gradients require computation of the - * covariant transformation matrix. Therefore, @p - * update_covariant_transformation and @p update_gradients will be returned - * by update_each(). - * - * For an example see the same function in the derived class FE_Q. - */ - virtual UpdateFlags update_once (const UpdateFlags flags) const = 0; - - /** - * Complementary function for update_once(). - * - * While update_once() returns the values to be computed on the unit cell - * for yielding the required data, this function determines the values that - * must be recomputed on each cell. + * An extensive discussion of the interaction between this function and + * FEValues can be found in the @ref FE_vs_Mapping_vs_FEValues documentation + * module. * - * Refer to update_once() for more details. + * @see UpdateFlags */ - virtual UpdateFlags update_each (const UpdateFlags flags) const = 0; + virtual + UpdateFlags + requires_update_flags (const UpdateFlags update_flags) const = 0; /** * Prepare internal data structures and fill in values independent of the diff --git a/include/deal.II/fe/fe_dgp_nonparametric.h b/include/deal.II/fe/fe_dgp_nonparametric.h index ce173c0743..50556f7097 100644 --- a/include/deal.II/fe/fe_dgp_nonparametric.h +++ b/include/deal.II/fe/fe_dgp_nonparametric.h @@ -283,6 +283,11 @@ public: */ virtual std::string get_name () const; + // for documentation, see the FiniteElement base class + virtual + UpdateFlags + requires_update_flags (const UpdateFlags update_flags) const; + /** * Return the value of the @p ith shape function at the point @p p. See the * FiniteElement base class for more information about the semantics of this @@ -582,7 +587,7 @@ private: * * For the present kind of finite element, this is exactly the case. */ - virtual UpdateFlags update_once (const UpdateFlags flags) const; + UpdateFlags update_once (const UpdateFlags flags) const; /** * This is the opposite to the above function: given a set of flags @@ -593,7 +598,7 @@ private: * (for example, we often need the covariant transformation when gradients * need to be computed), include this in the result as well. */ - virtual UpdateFlags update_each (const UpdateFlags flags) const; + UpdateFlags update_each (const UpdateFlags flags) const; /** * Degree of the polynomials. diff --git a/include/deal.II/fe/fe_face.h b/include/deal.II/fe/fe_face.h index ad9cfa624b..acafae2abe 100644 --- a/include/deal.II/fe/fe_face.h +++ b/include/deal.II/fe/fe_face.h @@ -168,6 +168,11 @@ public: */ virtual std::string get_name () const; + // for documentation, see the FiniteElement base class + virtual + UpdateFlags + requires_update_flags (const UpdateFlags update_flags) const; + /** * Return the matrix interpolating from a face of of one element to the face * of the neighboring element. The size of the matrix is then @@ -322,7 +327,7 @@ protected: * All other flags of the result are cleared, since everything else must be * computed for each cell. */ - virtual UpdateFlags update_once (const UpdateFlags flags) const; + UpdateFlags update_once (const UpdateFlags flags) const; /** * Determine the values that need to be computed on every cell to be able to @@ -352,7 +357,7 @@ protected: * * */ - virtual UpdateFlags update_each (const UpdateFlags flags) const; + UpdateFlags update_each (const UpdateFlags flags) const; private: /** diff --git a/include/deal.II/fe/fe_nothing.h b/include/deal.II/fe/fe_nothing.h index 65bf2297aa..3985b5dac6 100644 --- a/include/deal.II/fe/fe_nothing.h +++ b/include/deal.II/fe/fe_nothing.h @@ -113,36 +113,10 @@ public: std::string get_name() const; - /** - * Determine the values a finite element should compute on initialization of - * data for FEValues. - * - * Given a set of flags indicating what quantities are requested from a - * FEValues object, update_once() and update_each() compute which values - * must really be computed. Then, the fill_*_values functions are - * called with the result of these. - * - * In this case, since the element has zero degrees of freedom and no - * information can be computed on it, this function simply returns the - * default (empty) set of update flags. - */ - - virtual - UpdateFlags - update_once (const UpdateFlags flags) const; - - /** - * Complementary function for update_once(). - * - * While update_once() returns the values to be computed on the unit cell - * for yielding the required data, this function determines the values that - * must be recomputed on each cell. - * - * Refer to update_once() for more details. - */ + // for documentation, see the FiniteElement base class virtual UpdateFlags - update_each (const UpdateFlags flags) const; + requires_update_flags (const UpdateFlags update_flags) const; /** * Return the value of the @p ith shape function at the point @p p. @p p is @@ -276,11 +250,11 @@ public: bool is_dominating() const; private: + /** * If true, this element will dominate any other apart from itself in compare_for_face_domination(); */ const bool dominate; - }; diff --git a/include/deal.II/fe/fe_poly.h b/include/deal.II/fe/fe_poly.h index c73b58117c..a2f3bc3489 100644 --- a/include/deal.II/fe/fe_poly.h +++ b/include/deal.II/fe/fe_poly.h @@ -83,6 +83,11 @@ public: */ unsigned int get_degree () const; + // for documentation, see the FiniteElement base class + virtual + UpdateFlags + requires_update_flags (const UpdateFlags update_flags) const; + /** * Return the numbering of the underlying polynomial space compared to * lexicographic ordering of the basis functions. Returns @@ -347,7 +352,7 @@ protected: * All other flags of the result are cleared, since everything else must be * computed for each cell. */ - virtual UpdateFlags update_once (const UpdateFlags flags) const; + UpdateFlags update_once (const UpdateFlags flags) const; /** * Determine the values that need to be computed on every cell to be able to @@ -377,7 +382,7 @@ protected: * * */ - virtual UpdateFlags update_each (const UpdateFlags flags) const; + UpdateFlags update_each (const UpdateFlags flags) const; /** * Fields of cell-independent data. diff --git a/include/deal.II/fe/fe_poly.templates.h b/include/deal.II/fe/fe_poly.templates.h index 74519fda03..da43087d1c 100644 --- a/include/deal.II/fe/fe_poly.templates.h +++ b/include/deal.II/fe/fe_poly.templates.h @@ -176,6 +176,13 @@ FE_Poly::shape_4th_derivative_component (const unsigned int i //--------------------------------------------------------------------------- +template +UpdateFlags +FE_Poly::requires_update_flags (const UpdateFlags flags) const +{ + return update_once(flags) | update_each(flags); +} + template diff --git a/include/deal.II/fe/fe_poly_face.h b/include/deal.II/fe/fe_poly_face.h index 31d85ea509..294fcee367 100644 --- a/include/deal.II/fe/fe_poly_face.h +++ b/include/deal.II/fe/fe_poly_face.h @@ -74,6 +74,11 @@ public: */ unsigned int get_degree () const; + // for documentation, see the FiniteElement base class + virtual + UpdateFlags + requires_update_flags (const UpdateFlags update_flags) const; + protected: /* * NOTE: The following functions have their definitions inlined into the class declaration @@ -196,7 +201,7 @@ protected: * All other flags of the result are cleared, since everything else must be * computed for each cell. */ - virtual UpdateFlags update_once (const UpdateFlags flags) const; + UpdateFlags update_once (const UpdateFlags flags) const; /** * Determine the values that need to be computed on every cell to be able to @@ -226,7 +231,7 @@ protected: * * */ - virtual UpdateFlags update_each (const UpdateFlags flags) const; + UpdateFlags update_each (const UpdateFlags flags) const; /** diff --git a/include/deal.II/fe/fe_poly_face.templates.h b/include/deal.II/fe/fe_poly_face.templates.h index 5497997a91..972118fcd8 100644 --- a/include/deal.II/fe/fe_poly_face.templates.h +++ b/include/deal.II/fe/fe_poly_face.templates.h @@ -49,14 +49,18 @@ FE_PolyFace::get_degree () const //--------------------------------------------------------------------------- +template +UpdateFlags +FE_PolyFace::requires_update_flags (const UpdateFlags flags) const +{ + return update_once(flags) | update_each(flags); +} template UpdateFlags FE_PolyFace::update_once (const UpdateFlags) const { - // for this kind of elements, only the values can be precomputed once and - // for all. set this flag if the values are requested at all return update_default; } diff --git a/include/deal.II/fe/fe_poly_tensor.h b/include/deal.II/fe/fe_poly_tensor.h index fefaba3f58..f1a0a303c2 100644 --- a/include/deal.II/fe/fe_poly_tensor.h +++ b/include/deal.II/fe/fe_poly_tensor.h @@ -126,6 +126,11 @@ public: const std::vector &restriction_is_additive_flags, const std::vector &nonzero_components); + // for documentation, see the FiniteElement base class + virtual + UpdateFlags + requires_update_flags (const UpdateFlags update_flags) const; + /** * Since these elements are vector valued, an exception is thrown. */ @@ -156,29 +161,30 @@ public: const Point &p, const unsigned int component) const; +protected: + /** + * The mapping type to be used to map shape functions from the reference + * cell to the mesh cell. + */ + MappingType mapping_type; + + /** * Given flags, determines the values which must be computed only * for the reference cell. Make sure, that #mapping_type is set by the * derived class, such that this function can operate correctly. */ - virtual UpdateFlags update_once (const UpdateFlags flags) const; + UpdateFlags update_once (const UpdateFlags flags) const; + /** * Given flags, determines the values which must be computed in * each cell cell. Make sure, that #mapping_type is set by the derived * class, such that this function can operate correctly. */ - virtual UpdateFlags update_each (const UpdateFlags flags) const; + UpdateFlags update_each (const UpdateFlags flags) const; -protected: - /** - * The mapping type to be used to map shape functions from the reference - * cell to the mesh cell. - */ - MappingType mapping_type; - /** - NOTE: The following function has its definition inlined into the class declaration - * because we otherwise run into a compiler error with MS Visual Studio. - */ + /* NOTE: The following function has its definition inlined into the class declaration + because we otherwise run into a compiler error with MS Visual Studio. */ virtual typename FiniteElement::InternalDataBase * get_data(const UpdateFlags update_flags, diff --git a/include/deal.II/fe/fe_system.h b/include/deal.II/fe/fe_system.h index ff256ef3a6..5547211bd2 100644 --- a/include/deal.II/fe/fe_system.h +++ b/include/deal.II/fe/fe_system.h @@ -430,6 +430,11 @@ public: */ virtual std::string get_name () const; + // for documentation, see the FiniteElement base class + virtual + UpdateFlags + requires_update_flags (const UpdateFlags update_flags) const; + /** * Return the value of the @p ith shape function at the point @p p. @p p is * a point on the reference element. Since this finite element is always @@ -842,12 +847,12 @@ protected: /** * Compute flags for initial update only. */ - virtual UpdateFlags update_once (const UpdateFlags flags) const; + UpdateFlags update_once (const UpdateFlags flags) const; /** * Compute flags for update on each cell. */ - virtual UpdateFlags update_each (const UpdateFlags flags) const; + UpdateFlags update_each (const UpdateFlags flags) const; /** * @p clone function instead of a copy constructor. diff --git a/source/fe/fe_dgp_nonparametric.cc b/source/fe/fe_dgp_nonparametric.cc index 00045beebd..8bc0ff4739 100644 --- a/source/fe/fe_dgp_nonparametric.cc +++ b/source/fe/fe_dgp_nonparametric.cc @@ -216,6 +216,16 @@ FE_DGPNonparametric::get_dpo_vector (const unsigned int deg) } + +template +UpdateFlags +FE_DGPNonparametric::requires_update_flags (const UpdateFlags flags) const +{ + return update_once(flags) | update_each(flags); +} + + + template UpdateFlags FE_DGPNonparametric::update_once (const UpdateFlags) const diff --git a/source/fe/fe_face.cc b/source/fe/fe_face.cc index 7f3c8b9458..5297500ea5 100644 --- a/source/fe/fe_face.cc +++ b/source/fe/fe_face.cc @@ -449,6 +449,15 @@ FE_FaceQ<1,spacedim>::update_once (const UpdateFlags) const +template +UpdateFlags +FE_FaceQ<1,spacedim>::requires_update_flags (const UpdateFlags flags) const +{ + return update_once(flags) | update_each(flags); +} + + + template UpdateFlags FE_FaceQ<1,spacedim>::update_each (const UpdateFlags flags) const diff --git a/source/fe/fe_nothing.cc b/source/fe/fe_nothing.cc index d122101c4d..3d5d9733c2 100644 --- a/source/fe/fe_nothing.cc +++ b/source/fe/fe_nothing.cc @@ -72,18 +72,9 @@ FE_Nothing::get_name () const template UpdateFlags -FE_Nothing::update_once (const UpdateFlags /*flags*/) const +FE_Nothing::requires_update_flags (const UpdateFlags flags) const { - return update_default; -} - - - -template -UpdateFlags -FE_Nothing::update_each (const UpdateFlags /*flags*/) const -{ - return update_default; + return flags; } diff --git a/source/fe/fe_poly_tensor.cc b/source/fe/fe_poly_tensor.cc index cd116087e8..dfc24c3bc7 100644 --- a/source/fe/fe_poly_tensor.cc +++ b/source/fe/fe_poly_tensor.cc @@ -1675,6 +1675,15 @@ fill_fe_subface_values (const Mapping } + +template +UpdateFlags +FE_PolyTensor::requires_update_flags(const UpdateFlags flags) const +{ + return update_once(flags) | update_each(flags); +} + + template UpdateFlags FE_PolyTensor::update_once (const UpdateFlags flags) const diff --git a/source/fe/fe_system.cc b/source/fe/fe_system.cc index 95f097d156..bbcf05c3ca 100644 --- a/source/fe/fe_system.cc +++ b/source/fe/fe_system.cc @@ -844,28 +844,13 @@ face_to_cell_index (const unsigned int face_dof_index, template UpdateFlags -FESystem::update_once (const UpdateFlags flags) const +FESystem::requires_update_flags (const UpdateFlags flags) const { UpdateFlags out = update_default; // generate maximal set of flags // that are necessary for (unsigned int base_no=0; base_non_base_elements(); ++base_no) - out |= base_element(base_no).update_once(flags); - return out; -} - - - -template -UpdateFlags -FESystem::update_each (const UpdateFlags flags) const -{ - UpdateFlags out = update_default; - // generate maximal set of flags - // that are necessary - for (unsigned int base_no=0; base_non_base_elements(); ++base_no) - out |= base_element(base_no).update_each(flags); - + out |= base_element(base_no).requires_update_flags (flags); return out; } @@ -873,13 +858,19 @@ FESystem::update_each (const UpdateFlags flags) const template typename FiniteElement::InternalDataBase * -FESystem::get_data (const UpdateFlags flags_, +FESystem::get_data (const UpdateFlags flags, const Mapping &mapping, const Quadrature &quadrature) const { - UpdateFlags flags = flags_; + // create an internal data object and set the update flags we will need + // to deal with. the current object does not make use of these flags, + // but we need to nevertheless set them correctly since we look + // into the update_each flag of base elements in fill_fe_values, + // and so the current object's update_each flag needs to be + // correct in case the current FESystem is a base element for another, + // higher-level FESystem itself. InternalData *data = new InternalData(this->n_base_elements()); - data->update_each = update_each(flags) | update_once(flags); + data->update_each = requires_update_flags(flags); // get data objects from each of the base elements and store // them. do the creation of these objects in parallel as their @@ -918,14 +909,19 @@ FESystem::get_data (const UpdateFlags flags_, template typename FiniteElement::InternalDataBase * -FESystem::get_face_data ( - const UpdateFlags flags_, - const Mapping &mapping, - const Quadrature &quadrature) const -{ - UpdateFlags flags = flags_; +FESystem::get_face_data (const UpdateFlags flags, + const Mapping &mapping, + const Quadrature &quadrature) const +{ + // create an internal data object and set the update flags we will need + // to deal with. the current object does not make use of these flags, + // but we need to nevertheless set them correctly since we look + // into the update_each flag of base elements in fill_fe_values, + // and so the current object's update_each flag needs to be + // correct in case the current FESystem is a base element for another, + // higher-level FESystem itself. InternalData *data = new InternalData(this->n_base_elements()); - data->update_each = update_each(flags) | update_once(flags); + data->update_each = requires_update_flags(flags); // get data objects from each of the base elements and store // them. do the creation of these objects in parallel as their @@ -966,14 +962,19 @@ FESystem::get_face_data ( template typename FiniteElement::InternalDataBase * -FESystem::get_subface_data ( - const UpdateFlags flags_, - const Mapping &mapping, - const Quadrature &quadrature) const -{ - UpdateFlags flags = flags_; +FESystem::get_subface_data (const UpdateFlags flags, + const Mapping &mapping, + const Quadrature &quadrature) const +{ + // create an internal data object and set the update flags we will need + // to deal with. the current object does not make use of these flags, + // but we need to nevertheless set them correctly since we look + // into the update_each flag of base elements in fill_fe_values, + // and so the current object's update_each flag needs to be + // correct in case the current FESystem is a base element for another, + // higher-level FESystem itself. InternalData *data = new InternalData(this->n_base_elements()); - data->update_each = update_each(flags) | update_once(flags); + data->update_each = requires_update_flags(flags); // get data objects from each of the base elements and store // them. do the creation of these objects in parallel as their diff --git a/source/fe/fe_values.cc b/source/fe/fe_values.cc index 2457767b9b..3bfb044265 100644 --- a/source/fe/fe_values.cc +++ b/source/fe/fe_values.cc @@ -3436,16 +3436,14 @@ template UpdateFlags FEValuesBase::compute_update_flags (const UpdateFlags update_flags) const { - - // first find out which objects - // need to be recomputed on each - // cell we visit. this we have to - // ask the finite element and mapping. - // elements are first since they - // might require update in mapping + // first find out which objects need to be recomputed on each + // cell we visit. this we have to ask the finite element and mapping. + // elements are first since they might require update in mapping + // + // there is no need to iterate since mappings will never require + // the finite element to compute something for them UpdateFlags flags = update_flags - | fe->update_once (update_flags) - | fe->update_each (update_flags); + | fe->requires_update_flags (update_flags); flags |= mapping->requires_update_flags (flags); return flags; -- 2.39.5