diff --git a/src/t8_eclass/t8_eclass.h b/src/t8_eclass/t8_eclass.h index 68a3ec2cae..82f8369015 100644 --- a/src/t8_eclass/t8_eclass.h +++ b/src/t8_eclass/t8_eclass.h @@ -82,6 +82,8 @@ typedef enum t8_eclass { #define T8_ECLASS_MAX_DIM 3 /** The maximal number of children any element may have.*/ #define T8_ECLASS_MAX_CHILDREN 10 +/** The maximal number of children a face may have.*/ +#define T8_ECLASS_MAX_FACE_CHILDREN 4 /* clang-format off */ diff --git a/src/t8_forest/t8_forest.cxx b/src/t8_forest/t8_forest.cxx index 7421936a1e..6dd26e3f07 100644 --- a/src/t8_forest/t8_forest.cxx +++ b/src/t8_forest/t8_forest.cxx @@ -2073,6 +2073,36 @@ t8_forest_same_level_leaf_face_neighbor_index (const t8_forest_t forest, const t return neigh_index; } +int +t8_forest_leaf_neighbor_subface (t8_forest_t forest, t8_locidx_t ltreeid, const t8_element_t *leaf, int face, + t8_eclass_t neighbor_tree_class, const t8_element_t *neighbor_leaf, int neighbor_face) +{ + t8_scheme const *scheme = t8_forest_get_scheme (forest); + + t8_element_t *target_virtual_face_neighbor = nullptr; // the neighbor subface we are looking for + scheme->element_new (neighbor_tree_class, 1, &target_virtual_face_neighbor); + t8_forest_element_face_neighbor (forest, ltreeid, leaf, target_virtual_face_neighbor, neighbor_tree_class, face, + nullptr); + + int const num_children = scheme->element_get_num_face_children (neighbor_tree_class, neighbor_leaf, neighbor_face); + + std::array children; // assumes the forest is (locally) 2:1 balanced + scheme->element_new (neighbor_tree_class, children.size (), children.begin ()); + + scheme->element_get_children_at_face (neighbor_tree_class, neighbor_leaf, neighbor_face, children.begin (), + num_children, nullptr); + + auto iter = std::find_if (children.begin (), children.end (), [&] (t8_element *candidate) -> bool { + return scheme->element_compare (neighbor_tree_class, target_virtual_face_neighbor, candidate) == 0; + }); + T8_ASSERT (iter != children.end ()); // make sure target_virtual_face_neighbor was found + int neighbor_subface_index = iter - children.begin (); + + scheme->element_destroy (neighbor_tree_class, 4, children.begin ()); + scheme->element_destroy (neighbor_tree_class, 1, &target_virtual_face_neighbor); + return neighbor_subface_index; +} + void t8_forest_print_all_leaf_neighbors (t8_forest_t forest) { diff --git a/src/t8_forest/t8_forest_general.h b/src/t8_forest/t8_forest_general.h index b80ef18a41..6a9d5b697c 100644 --- a/src/t8_forest/t8_forest_general.h +++ b/src/t8_forest/t8_forest_general.h @@ -675,6 +675,26 @@ t8_locidx_t t8_forest_same_level_leaf_face_neighbor_index (const t8_forest_t forest, const t8_locidx_t element_index, const int face_index, const t8_gloidx_t global_treeid, int *dual_face); +/** Compute the subface index for a coarser neighbor + * \param [in] forest The forest. Must be committed. + * \param [in] ltreeid A local tree id. + * \param [in] leaf A leaf in \a ltreeid. + * \param [in] face The face index of \a leaf to consider. + * \param [in] neighbor_tree_class The eclass of the neighbor element. + * \param [in] neighbor_leaf The leaf of \a forest on the other side of the face of index \a face of element \a leaf. + * \param [in] neighbor_face The face index of \a neighbor_leaf (i.e. the dual face of \a face). + * \returns The index of the subface of \a neighbor_face which corresponds to \a face. + * \pre \a leaf and \a neighbor_leaf must be a face neighbors. The common face must correspond to \a face for \a leaf + * and \a neighbor_face for \a neighbor_leaf respectively. \a neighbor_leaf must be one level coarser than \a leaf. + * Otherwise the behavior is undefined. + * \note This function is designed to be called after \ref t8_forest_leaf_face_neighbors_ext to complement its output. + * It is primarily intended for balanced forests, but can be used on any committed forest as long as the preconditions + * hold (i.e. the forest must be ''locally balanced''). + */ +int +t8_forest_leaf_neighbor_subface (t8_forest_t forest, t8_locidx_t ltreeid, const t8_element_t *leaf, int face, + t8_eclass_t neighbor_tree_class, const t8_element_t *neighbor_leaf, int neighbor_face); + /** Exchange ghost information of user defined element data. * \param [in] forest The forest. Must be committed. * \param [in] element_data An array of length num_local_elements + num_ghosts