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
21 changes: 21 additions & 0 deletions src/t8_schemes/t8_scheme.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,27 @@ class t8_scheme {
eclass_schemes[tree_class]);
};

/** Given a face of an element and a level coarser than (or equal to)
* the element's level, return the face number
* of the ancestor of the element that matches the element's face. Or return -1 if
* no face of the ancestor matches the face.
* \param [in] tree_class The eclass of the current tree.
* \param [in] element The element.
* \param [in] ancestor_level A refinement level smaller than (or equal to) \a element's level.
* \param [in] face Then number of a face of \a element.
* \return If \a face of \a element is a subface of a face of \a element's ancestor at level \a ancestor_level,
* the face number of this face. Otherwise -1.
* \note For the root element this function always returns \a face.
*/
inline int
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
inline int
constexpr int

element_face_get_ancestor_face (const t8_eclass_t tree_class, const t8_element_t *element, const int ancestor_level,
const int face) const
{
return std::visit (
[&] (auto &&scheme) { return scheme.element_face_get_ancestor_face (element, ancestor_level, face); },
eclass_schemes[tree_class]);
}

/** Given an element and a face of this element. If the face lies on the
* tree boundary, return the face number of the tree face.
* If not the return value is arbitrary.
Expand Down
44 changes: 44 additions & 0 deletions src/t8_schemes/t8_scheme_helpers.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,50 @@ class t8_scheme_helpers: public t8_crtp_basic<TUnderlyingEclassScheme> {
{
return TEclass;
}

/** Given a face of an element and a level coarser than (or equal to)
* the element's level, return the face number
* of the ancestor of the element that matches the element's face. Or return -1 if
* no face of the ancestor matches the face.
* \param [in] tree_class The eclass of the current tree.
* \param [in] element The element.
* \param [in] ancestor_level A refinement level smaller than (or equal to) \a element's level.
* \param [in] face Then number of a face of \a element.
* \return If \a face of \a element is a subface of a face of \a element's ancestor at level \a ancestor_level,
* the face number of this face. Otherwise -1.
* \note For the root element this function always returns \a face.
*/
inline int
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check if this can be constexpr

element_face_get_ancestor_face (const t8_element_t *element, const int ancestor_level, const int face) const
{
auto underlying_impl = this->underlying (); // Reference to the underlying scheme implementation

const int element_level = underlying_impl.element_get_level (element);
T8_ASSERT (element_level >= ancestor_level);
if (element_level == ancestor_level) {
// On the same level, the return value is the face itself
return face;
}
// Allocate memory for a temporary element.
t8_element_t *parent;
underlying_impl.element_new (1, &parent);
// Pointer to a temoporary element, that will move up the refinement hierarchy
const t8_element_t *temp_element = element;
int temp_face = face;
for (int ilevel = element_level; ilevel > ancestor_level; --ilevel) {
// Go one level up in the refinement hierarchy with the face
temp_face = underlying_impl.element_face_get_parent_face (temp_element, temp_face);
if (temp_face == -1) {
// This face is not a subface of an ancestor face.
underlying_impl.element_destroy (1, &parent);
return -1;
}
underlying_impl.element_get_parent (temp_element, parent);
temp_element = parent;
}
underlying_impl.element_destroy (1, &parent);
return temp_face;
}
};

#endif /* T8_SCHEME_HELPERS_HXX */
14 changes: 14 additions & 0 deletions test/t8_schemes/t8_gtest_child_parent_face.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
#include "t8_gtest_dfs_base.hxx"
#include <test/t8_gtest_macros.hxx>

/* TODO: extend this test or new test. On each level,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make an issue out of this ToDo?

* go multiple levels below and check against ancestor face */

class class_child_parent_face: public TestDFS {
void
check_element () override
Expand All @@ -49,6 +52,17 @@ class class_child_parent_face: public TestDFS {
const int parentface = scheme->element_face_get_parent_face (eclass, children[ifacechild], childface);
/* Check, that this is equal to the face that we started with */
EXPECT_EQ (iface, parentface);
const int element_level = scheme->element_get_level (eclass, element);
// Check the ancestor face function when input is the child and the level of the child.
// We expect the output face to be the input face
const int ancestor_face_same_level
= scheme->element_face_get_ancestor_face (eclass, children[ifacechild], element_level + 1, childface);
EXPECT_EQ (childface, ancestor_face_same_level);
// Check the ancestor face function when input is the element level/
// We expect the output face to be the original face
const int ancestor_face_one_level_higher
= scheme->element_face_get_ancestor_face (eclass, children[ifacechild], element_level, childface);
EXPECT_EQ (iface, ancestor_face_one_level_higher);
}
scheme->element_destroy (eclass, num_face_children, children);
T8_TESTSUITE_FREE (children);
Expand Down