Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions mesh_handle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ Some application codes are designed for unstructured or uniform meshes and canno

If you want to use the handle, note that is has its own library. Turn the option `T8CODE_BUILD_MESH_HANDLE` to `ON` and link against the target `T8_MESH_HANDLE` in addition to the usual t8code target please.

The [mesh.hxx](mesh.hxx) defines the mesh class of the handle.
The [element.hxx](element.hxx) defines the elements used in the mesh class.
The folder's most important files are:
The [mesh.hxx](mesh.hxx) defines the mesh class of the handle. This is the central file of the mesh handle.
The [abstract_element.hxx](abstract_element.hxx) defines the common interface of the mesh elements and the ghost elements of the mesh handle.
The [mesh_element.hxx](mesh_element.hxx) implements a class for the mesh elements of the mesh handle (so non-ghost elements).
The [ghost_element.hxx](ghost_element.hxx) implements the class for the ghost elements of the mesh handle.
The [competences.hxx](competences.hxx) defines additional competences/functionality of an element to access additional data.
113 changes: 68 additions & 45 deletions mesh_handle/element.hxx → mesh_handle/abstract_element.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ along with t8code; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

/** \file element.hxx
* Definition of the elements used in the \ref t8_mesh_handle::mesh class.
/** \file abstract_element.hxx
* Common interface of the mesh elements and the ghost elements of the \ref t8_mesh_handle::mesh handle.
*/

#ifndef T8_ELEMENT_HXX
#define T8_ELEMENT_HXX
#ifndef T8_ABSTRACT_ELEMENT_HXX
#define T8_ABSTRACT_ELEMENT_HXX

#include <t8.h>
#include <t8_element.h>
Expand All @@ -34,25 +34,25 @@ along with t8code; if not, write to the Free Software Foundation, Inc.,
#include <t8_forest/t8_forest_geometrical.h>
#include <t8_schemes/t8_scheme.hxx>
#include <t8_types/t8_vec.hxx>
#include <array>
#include <vector>

namespace t8_mesh_handle
{
/* Forward declaration of the \ref mesh class of the handle.
*/
template <class TMeshElement>
template <template <typename> class... TCompetence>
class mesh;

/**
* Class for the elements of the mesh handle.
* The element without specified template parameters provides default implementations for basic functionality
* Common interface of the mesh elements and the ghost elements of the \ref mesh handle.
* An element without specified template parameters provides default implementations for basic functionality
* as accessing the refinement level or the centroid. With this implementation, the functionality is calculated each time
* the function is called.
* Use the competences defined in \ref competences.hxx as template parameter to cache the functionality instead of
* recalculating in every function call.
* To add functionality to the element, you can also simply write your own competence class and give it as a template parameter.
* You can access the functions implemented in your competence via the element.
* Please note that the competence should be valid for both, mesh elements and ghost elements.
*
* The inheritance pattern is inspired by the \ref T8Type class (which also uses the CRTP).
* We decided to use this structure 1.) to be able to add new functionality easily and
Expand All @@ -62,10 +62,25 @@ class mesh;
* \tparam TCompetence The competences you want to add to the default functionality of the element.
*/
template <template <typename> class... TCompetence>
class element: public TCompetence<element<TCompetence...>>... {
using SelfType = element<TCompetence...>;
class abstract_element: public TCompetence<abstract_element<TCompetence...>>... {
protected:
using SelfType
= abstract_element<TCompetence...>; /**< Type of the current class with all template parameters specified. */
using mesh_class = mesh<TCompetence...>; /**< Type of the mesh class the used. */
friend mesh_class; /**< Define mesh_class as friend to be able to access e.g. the constructor. */

/**
* Protected constructor for an element of a mesh.
* This constructor of the abstract class should only be called by child classes.
* \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.
*/
abstract_element (mesh_class* mesh, t8_locidx_t tree_id, t8_locidx_t element_id)
: m_mesh (mesh), m_tree_id (tree_id), m_element_id (element_id)
{
}

private:
// --- 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.
Expand All @@ -77,8 +92,8 @@ class element: public TCompetence<element<TCompetence...>>... {
{
return requires (T<SelfType>& competence) { competence.vertex_cache_filled (); };
}
/* This variable is true if any of the given competences \ref TCompetence implements
a function vertex_cache_filled */
/** This variable is true if any of the given competences \a TCompetence implements
a function vertex_cache_filled. */
static constexpr bool vertex_cache_exists = (false || ... || vertex_cache_defined<TCompetence> ());

/** Helper function to check if class T implements the function centroid_cache_filled.
Expand All @@ -91,22 +106,11 @@ class element: public TCompetence<element<TCompetence...>>... {
{
return requires (T<SelfType>& competence) { competence.centroid_cache_filled (); };
}
/* This variable is true if any of the given competences \ref TCompetence implements
/** This variable is true if any of the given competences \a TCompetence implements
a function centroid_cache_filled. */
static constexpr bool centroid_cache_exists = (false || ... || centroid_cache_defined<TCompetence> ());

public:
/**
* Constructor for an element of a mesh.
* \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.
*/
element (mesh<SelfType>* mesh, t8_locidx_t tree_id, t8_locidx_t element_id)
: m_mesh (mesh), m_tree_id (tree_id), m_element_id (element_id)
{
}

// --- Functions to check if caches exist. ---
/**
* Function that checks if a cache for the vertex coordinates exists.
Expand All @@ -130,20 +134,32 @@ class element: public TCompetence<element<TCompetence...>>... {

// --- Functionality of the element. In each function, it is checked if a cached version exists (and is used then). ---
/**
* Getter for the refinement level of the mesh element.
* Getter for the refinement level of the element.
* For this easily accessible variable, it makes no sense to provide a cached version.
* \return Refinement level of the mesh element.
* \return Refinement level of the element.
*/
t8_element_level
get_level () const
{
const t8_eclass_t tree_class = get_tree_class ();
const t8_eclass_t eclass = get_tree_class ();
const t8_element_t* element = get_element ();
return t8_forest_get_scheme (m_mesh->m_forest)->element_get_level (tree_class, element);
return t8_forest_get_scheme (m_mesh->m_forest)->element_get_level (eclass, element);
}

/**
* Getter for the number of faces of the element.
* For this easily accessible variable, it makes no sense to provide a cached version.
* \return Number of faces of the element.
*/
int
get_num_faces () const
{
return t8_forest_get_scheme (m_mesh->m_forest)->element_get_num_faces (get_tree_class (), get_element ());
}

/**
* Getter for the element's shape.
* For this easily accessible variable, it makes no sense to provide a cached version.
* \return The shape of the element.
*/
t8_element_shape_t
Expand All @@ -153,7 +169,7 @@ class element: public TCompetence<element<TCompetence...>>... {
}

/**
* Getter for the vertex coordinates of the mesh element.
* Getter for the vertex coordinates of the element.
* This function uses or sets the cached version defined in TCompetence if available and calculates if not.
* \return Vector with one coordinate array for each vertex of the element.
*/
Expand Down Expand Up @@ -183,7 +199,7 @@ class element: public TCompetence<element<TCompetence...>>... {
}

/**
* Getter for the center of mass of the mesh element.
* Getter for the center of mass of the element.
* This function uses the cached version defined in TCompetence if available and calculates if not.
* \return Coordinates of the center.
*/
Expand All @@ -207,7 +223,7 @@ class element: public TCompetence<element<TCompetence...>>... {

//--- Getter for the member variables. ---
/**
* Getter for the tree id of the mesh element.
* Getter for the tree id of the element.
* \return The element's local tree id.
*/
t8_locidx_t
Expand All @@ -217,8 +233,8 @@ class element: public TCompetence<element<TCompetence...>>... {
}

/**
* Getter for the local element id of the mesh element.
* \return The local element id of the mesh element.
* Getter for the local element id of the element.
* \return The local element id of the element.
*/
t8_locidx_t
get_local_element_id () const
Expand All @@ -227,29 +243,36 @@ class element: public TCompetence<element<TCompetence...>>... {
}

/**
* Getter for the mesh to which the mesh element is belonging.
* Getter for the mesh to which the element is belonging.
* \return Reference to the mesh.
*/
const mesh<SelfType>*
const mesh_class*
get_mesh () const
{
return m_mesh;
}

private:
/**
* Virtual function to check if the element is a ghost element.
* \return true if the element is a ghost element, false otherwise.
*/
virtual constexpr bool
is_ghost_element () const
= 0;

protected:
//--- Private getter for internal use. ---
/**
* Getter for the leaf element of the mesh element.
* Getter for the leaf element of the element.
* Has to be implemented differently for mesh elements and ghost elements.
* \return The leaf element.
*/
const t8_element_t*
virtual const t8_element_t*
get_element () const
{
return t8_forest_get_leaf_element_in_tree (m_mesh->m_forest, m_tree_id, m_element_id);
}
= 0;

/**
* Getter for the eclass of the tree of the mesh element.
* Getter for the eclass of the tree of the element.
* \return The eclass of the element's tree.
*/
t8_eclass_t
Expand All @@ -258,10 +281,10 @@ class element: public TCompetence<element<TCompetence...>>... {
return t8_forest_get_tree_class (m_mesh->m_forest, m_tree_id);
}

mesh<SelfType>* m_mesh; /**< Pointer to the mesh the element is defined for. */
mesh_class* m_mesh; /**< Pointer to the mesh the element is defined for. */
t8_locidx_t m_tree_id; /**< The tree id of the element in the forest defined in the mesh. */
t8_locidx_t m_element_id; /**< The element id of the element in the forest defined in the mesh. */
};

} // namespace t8_mesh_handle
#endif /* !T8_ELEMENT_HXX */
#endif /* !T8_ABSTRACT_ELEMENT_HXX */
54 changes: 48 additions & 6 deletions mesh_handle/competences.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ along with t8code; if not, write to the Free Software Foundation, Inc.,
* is called are provided.
*
* All competences have the same inheritance pattern:
* We use the CRTP pattern as we may need to access members of the derived class \ref t8_mesh_handle::element.
* We use the CRTP pattern as we may need to access members of the derived classes like
* \ref t8_mesh_handle::abstract_element.
* The t8_crtp_operator is used for convenience/clear code (avoid to type a static cast explicitly each time
* we need functionality of TUnderlying).
* Especially for the competences to cache functionality, the access of members is not necessary,
* such that it is not obvious why we use the crtp. For competences that extend the functionality of the element,
* this is required.
* We use it for all competences for consistency and compatibility with the \ref t8_mesh_handle::element class.
* We use it for all competences for consistency and compatibility with the \ref t8_mesh_handle::abstract_element class.
*/

#ifndef T8_COMPETENCES_HXX
Expand All @@ -41,8 +42,6 @@ along with t8code; if not, write to the Free Software Foundation, Inc.,
#include <t8.h>
#include <t8_types/t8_operators.hxx>
#include <t8_types/t8_vec.hxx>
#include <t8_eclass.h>
#include <array>
#include <vector>
#include <optional>

Expand All @@ -51,7 +50,7 @@ namespace t8_mesh_handle

/**
* 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.
* \tparam TUnderlying Use the \ref abstract_element with specified competences as template parameter.
*/
template <typename TUnderlying>
struct cache_vertex_coordinates: public t8_crtp_operator<TUnderlying, cache_vertex_coordinates>
Expand All @@ -74,7 +73,7 @@ struct cache_vertex_coordinates: public t8_crtp_operator<TUnderlying, cache_vert

/**
* Competence to cache the centroid of an element at the first function call.
* \tparam TUnderlying Use the \ref element with specified competences as template parameter.
* \tparam TUnderlying Use the \ref abstract_element with specified competences as template parameter.
*/
template <typename TUnderlying>
struct cache_centroid: public t8_crtp_operator<TUnderlying, cache_centroid>
Expand All @@ -95,5 +94,48 @@ struct cache_centroid: public t8_crtp_operator<TUnderlying, cache_centroid>
m_centroid; /**< Cache for the coordinates of the centroid. Use optional to allow no value if cache is not filled. */
};

/**
* Competence to cache the neighbors of an element at a specific face at the first function call.
* \tparam TUnderlying Use the \ref abstract_element with specified competences as template parameter.
*/
template <typename TUnderlying>
struct cache_neighbors: t8_crtp_operator<TUnderlying, cache_centroid>
{
public:
/**
* Function that checks if the neighbor 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
neighbor_cache_filled (int face) const
{
return m_num_neighbors[face].has_value ();
}

/**
* Function that checks if the neighbor cache for any face has been filled.
* \return true if the cache has been filled, false otherwise.
*/
bool
neighbor_cache_filled_any () const
{
for (int iface = 0; iface < this->underlying ().get_num_faces (); ++iface) {
if (neighbor_cache_filled (iface)) {
return true;
}
}
return false;
}

protected:
mutable std::vector<std::vector<t8_locidx_t>>
m_neighbor_indices; /**< Element indices of the neighbors at each face. The length of the vectors is stored in \ref m_num_neighbors. */
mutable std::vector<std::optional<int>>
m_num_neighbors; /**< Vector with the numbers of neighbor elements at each face. */
mutable std::vector<std::vector<int>>
m_dual_faces; /**< Face id's of the neighboring elements' faces for each face. */
};

} // namespace t8_mesh_handle
#endif /* !T8_COMPETENCES_HXX */
Loading