Program Listing for File element.hxx
↰ Return to documentation for file (mesh_handle/element.hxx)
/*
This file is part of t8code.
t8code is a C library to manage a collection (a forest) of multiple
connected adaptive space-trees of general element classes in parallel.
Copyright (C) 2025 the developers
t8code is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
t8code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with t8code; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef T8_ELEMENT_HXX
#define T8_ELEMENT_HXX
#include <t8.h>
#include <t8_element.h>
#include <t8_eclass.h>
#include <t8_forest/t8_forest_general.h>
#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>
class mesh;
template <template <typename> class... TCompetence>
class element: public TCompetence<element<TCompetence...>>... {
using SelfType = element<TCompetence...>;
private:
// --- Variables to check which functionality is defined in TCompetence. ---
template <template <typename> class T>
static constexpr bool
vertex_cache_defined ()
{
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 */
static constexpr bool vertex_cache_exists = (false || ... || vertex_cache_defined<TCompetence> ());
template <template <typename> class T>
static constexpr bool
centroid_cache_defined ()
{
return requires (T<SelfType>& competence) { competence.centroid_cache_filled (); };
}
/* This variable is true if any of the given competences \ref TCompetence implements
a function centroid_cache_filled. */
static constexpr bool centroid_cache_exists = (false || ... || centroid_cache_defined<TCompetence> ());
public:
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. ---
static constexpr bool
has_vertex_cache ()
{
return vertex_cache_exists;
}
static constexpr bool
has_centroid_cache ()
{
return centroid_cache_exists;
}
// --- Functionality of the element. In each function, it is checked if a cached version exists (and is used then). ---
t8_element_level
get_level () const
{
const t8_eclass_t tree_class = 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);
}
t8_element_shape_t
get_shape () const
{
return t8_forest_get_scheme (m_mesh->m_forest)->element_get_shape (get_tree_class (), get_element ());
}
std::vector<t8_3D_point>
get_vertex_coordinates () const
{
// Check if we have a cached version and if the cache has already been filled.
if constexpr (vertex_cache_exists) {
if (this->vertex_cache_filled ()) {
return this->m_vertex_coordinates;
}
}
// Calculate the vertex coordinates.
const t8_element_t* element = get_element ();
const int num_corners
= t8_forest_get_scheme (m_mesh->m_forest)->element_get_num_corners (get_tree_class (), element);
std::vector<t8_3D_point> vertex_coordinates (num_corners);
for (int icorner = 0; icorner < num_corners; ++icorner) {
t8_forest_element_coordinate (m_mesh->m_forest, m_tree_id, element, icorner, vertex_coordinates[icorner].data ());
}
// Fill the cache in the cached version.
if constexpr (vertex_cache_exists) {
this->m_vertex_coordinates = std::move (vertex_coordinates);
return this->m_vertex_coordinates;
}
return vertex_coordinates;
}
t8_3D_point
get_centroid () const
{
// Check if we have a cached version and if the cache has already been filled.
if constexpr (centroid_cache_exists) {
if (this->centroid_cache_filled ()) {
return this->m_centroid.value ();
}
}
t8_3D_point coordinates;
t8_forest_element_centroid (m_mesh->m_forest, m_tree_id, get_element (), coordinates.data ());
// Fill the cache in the cached version.
if constexpr (centroid_cache_exists) {
this->m_centroid = coordinates;
}
return coordinates;
}
//--- Getter for the member variables. ---
t8_locidx_t
get_local_tree_id () const
{
return m_tree_id;
}
t8_locidx_t
get_local_element_id () const
{
return m_element_id;
}
const mesh<SelfType>*
get_mesh () const
{
return m_mesh;
}
private:
//--- Private getter for internal use. ---
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);
}
t8_eclass_t
get_tree_class () const
{
return t8_forest_get_tree_class (m_mesh->m_forest, m_tree_id);
}
mesh<SelfType>* m_mesh;
t8_locidx_t m_tree_id;
t8_locidx_t m_element_id;
};
} // namespace t8_mesh_handle
#endif /* !T8_ELEMENT_HXX */