diff --git a/mesh_handle/competences.hxx b/mesh_handle/competences.hxx index 69a2880868..a7a2616912 100644 --- a/mesh_handle/competences.hxx +++ b/mesh_handle/competences.hxx @@ -48,6 +48,52 @@ along with t8code; if not, write to the Free Software Foundation, Inc., namespace t8_mesh_handle { +/** + * Competence to cache the volume of an element at the first function call. + * \tparam TUnderlying Use the \ref element with specified competences as template parameter. + */ +template +struct cache_volume: public t8_crtp_operator +{ + public: + /** + * Function that checks if the cache for the volume has been filled. + * \return true if the cache has been filled, false otherwise. + */ + bool + volume_cache_filled () const + { + return m_volume.has_value (); + } + + protected: + mutable std::optional + m_volume; /**< Cache for the volume. Use optional to allow no value if cache is not filled. */ +}; + +/** + * Competence to cache the diameter of an element at the first function call. + * \tparam TUnderlying Use the \ref element with specified competences as template parameter. + */ +template +struct cache_diameter: public t8_crtp_operator +{ + public: + /** + * Function that checks if the cache for the diameter has been filled. + * \return true if the cache has been filled, false otherwise. + */ + bool + diameter_cache_filled () const + { + return m_diameter.has_value (); + } + + protected: + mutable std::optional + m_diameter; /**< Cache for the diameter. Use optional to allow no value if cache is not filled. */ +}; + /** * Competence to cache the vertex coordinates of an element at the first function call. * \tparam TUnderlying Use the \ref element with specified competences as template parameter. @@ -94,6 +140,75 @@ struct cache_centroid: public t8_crtp_operator m_centroid; /**< Cache for the coordinates of the centroid. Use optional to allow no value if cache is not filled. */ }; +/** + * Competence to cache the area of a specific face at the first function call. + * \tparam TUnderlying Use the \ref element with specified competences as template parameter. + */ +template +struct cache_face_area: t8_crtp_operator +{ + public: + /** + * Function that checks if the cache for a face has been filled. + * \param [in] face The face for which the cache should be checked. + * \return true if the cache has been filled, false otherwise. + */ + bool + face_area_cache_filled (int face) const + { + return m_face_area[face].has_value (); + } + + protected: + mutable std::vector> m_face_area; /**< Vector with the face area each face. */ +}; + +/** + * Competence to cache the centroid of a specific face at the first function call. + * \tparam TUnderlying Use the \ref element with specified competences as template parameter. + */ +template +struct cache_face_centroid: t8_crtp_operator +{ + public: + /** + * Function that checks if the cache for a face has been filled. + * \param [in] face The face for which the cache should be checked. + * \return true if the cache has been filled, false otherwise. + */ + bool + face_centroid_cache_filled (int face) const + { + return m_face_centroid[face].has_value (); + } + + protected: + mutable std::vector> m_face_centroid; /**< Vector with the face centroid each face. */ +}; + +/** + * Competence to cache the normal of a specific face at the first function call. + * \tparam TUnderlying Use the \ref element with specified competences as template parameter. + */ +template +struct cache_face_normal: t8_crtp_operator +{ + public: + /** + * Function that checks if the cache for a face has been filled. + * \param [in] face The face for which the cache should be checked. + * \return true if the cache has been filled, false otherwise. + */ + bool + face_normal_cache_filled (int face) const + { + return m_face_normal[face].has_value (); + } + + protected: + mutable std::vector> m_face_normal; /**< Vector with the face normal each face. */ +}; + /** * Competence to cache the neighbors of an element at a specific face at the first function call. * \tparam TUnderlying Use the \ref element with specified competences as template parameter. diff --git a/mesh_handle/element.hxx b/mesh_handle/element.hxx index 9c35440d54..1ab61b7c6f 100644 --- a/mesh_handle/element.hxx +++ b/mesh_handle/element.hxx @@ -21,7 +21,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., */ /** \file element.hxx - * Definition of the element class of the \ref t8_mesh_handle::mesh handle (can be ghost or mesh elements). + * Definition of the element class of the \ref t8_mesh_handle::mesh handle (can be ghost or mesh elements). */ #ifndef T8_ELEMENT_HXX @@ -69,9 +69,8 @@ class element: public TCompetence>... { using mesh_class = mesh; /**< Type of the mesh class used. */ friend mesh_class; /**< Define mesh_class as friend to be able to access e.g. the constructor. */ - /** - * Private constructor for an element of a mesh. This could be a simple mesh element or a ghost element. - * This constructor should only be called by the mesh_class (and invisible for the user). + /** Private constructor for an element of a mesh. This could be a simple mesh element or a ghost element. + * This constructor should only be called by the mesh_class (and invisible for the user). * \param [in] mesh Pointer to the mesh the element should belong to. * \param [in] tree_id The tree id of the element in the forest defining the mesh. * \param [in] element_id The element id of the element in the forest defining the mesh. @@ -80,6 +79,7 @@ class element: public TCompetence>... { element (mesh_class* mesh, t8_locidx_t tree_id, t8_locidx_t element_id, bool is_ghost_element = false) : m_mesh (mesh), m_tree_id (tree_id), m_element_id (element_id), m_is_ghost_element (is_ghost_element) { + // Cache the t8_element_t from the forest as it is often used. if (m_is_ghost_element) { // The local ghost tree id is per definition the local tree id - number of local (non-ghost) trees. m_element = t8_forest_ghost_get_leaf_element ( @@ -89,158 +89,225 @@ class element: public TCompetence>... { m_element = t8_forest_get_leaf_element_in_tree (m_mesh->m_forest, m_tree_id, m_element_id); } - if constexpr (neighbor_cache_exists) { - // Resize neighbor caches for clean access to the caches. - const int num_faces = this->get_num_faces (); + // Resize caches for clean access where the cache vector may not be filled completely at once. + if constexpr (has_face_neighbor_cache ()) { + const int num_faces = get_num_faces (); this->m_num_neighbors.resize (num_faces); this->m_dual_faces.resize (num_faces); this->m_neighbors.resize (num_faces); } + if constexpr (has_face_area_cache ()) { + const int num_faces = get_num_faces (); + this->m_face_area.resize (num_faces); + } + if constexpr (has_face_centroid_cache ()) { + const int num_faces = get_num_faces (); + this->m_face_centroid.resize (num_faces); + } + if constexpr (has_face_normal_cache ()) { + const int num_faces = get_num_faces (); + this->m_face_normal.resize (num_faces); + } } - // --- Variables to check which functionality is defined in TCompetence. --- - /** Helper function to check if class T implements the function vertex_cache_filled. - * \tparam T The competence to be checked. - * \return true if T implements the function, false if not. + public: + // --- Public functions to check if caches exist. --- + /** Function that checks if a cache for the element's volume exists. + * \return true if a cache exists, false otherwise. */ - template