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
12 changes: 12 additions & 0 deletions src/t8_cmesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,18 @@ t8_locidx_t
t8_cmesh_get_face_neighbor (const t8_cmesh_t cmesh, const t8_locidx_t ltreeid, const int face, int *dual_face,
int *orientation);

/**
* Given a local tree id (of a local tree or ghost tree) and a face compute the eclass of the
* tree's face neighbor.
*
* \param [in] cmesh The cmesh to be considered.
* \param [in] ltreeid The local id of a tree or a ghost.
* \param [in] face A face number of the tree/ghost.
* \return The eclass of a neighbor tree of \a ltreeid across \a face. T8_ECLASS_INVALID if no neighbor exists.
*/
t8_eclass_t
t8_cmesh_get_tree_face_neighbor_eclass (const t8_cmesh_t cmesh, const t8_locidx_t ltreeid, const int face);

/** Print the collected statistics from a cmesh profile.
* \param [in] cmesh The cmesh.
*
Expand Down
30 changes: 30 additions & 0 deletions src/t8_cmesh/t8_cmesh.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,36 @@ t8_cmesh_get_face_neighbor (const t8_cmesh_t cmesh, const t8_locidx_t ltreeid, c
return face_neigh;
}

t8_eclass_t
t8_cmesh_get_tree_face_neighbor_eclass (const t8_cmesh_t cmesh, const t8_locidx_t ltreeid, const int face)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please assert that face is a positive number, or make it an uint.

Copy link
Collaborator Author

@holke holke Aug 20, 2025

Choose a reason for hiding this comment

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

Done.
Note that t8_cmesh_get_face_neighbor will also performs this check and also check whether face is smaller than the number of faces.
The latter is difficult to check at this place, since we do not have access to the eclass of the tree immediately.
And i figure it is ok to just check against 0 here since t8_cmesh_get_face_neighbor will do the other check.

{
T8_ASSERT (t8_cmesh_is_committed (cmesh));
T8_ASSERT (t8_cmesh_treeid_is_local_tree (cmesh, ltreeid) || t8_cmesh_treeid_is_ghost (cmesh, ltreeid));
T8_ASSERT (0 <= face);

const t8_locidx_t neighbor_id = t8_cmesh_get_face_neighbor (cmesh, ltreeid, face, NULL, NULL);
if (neighbor_id < 0) {
// No neighbor was found.
return T8_ECLASS_INVALID;
}
const bool neighbor_is_ghost = t8_cmesh_treeid_is_ghost (cmesh, neighbor_id);
if (!neighbor_is_ghost) {
// Neighbor was found and is a local tree
return t8_cmesh_get_tree_class (cmesh, neighbor_id);
}
else {
// Neighbor was found and is a ghost.
// Translate ltreeid from range num_local_trees <= ltreeid < num_local_trees + num_ghost_trees
// into 0 <= lghost_id < num_ghost_trees
const t8_locidx_t lghost_neihgbor_id = neighbor_id - t8_cmesh_get_num_local_trees (cmesh);

t8_debugf ("in: %i out: %i, num t: %i num g: %i\n", neighbor_id, lghost_neihgbor_id,
t8_cmesh_get_num_local_trees (cmesh), t8_cmesh_get_num_ghosts (cmesh));
// Look up ghost tree class
return t8_cmesh_get_ghost_class (cmesh, lghost_neihgbor_id);
}
}

void
t8_cmesh_print_profile (const t8_cmesh_t cmesh)
{
Expand Down
15 changes: 15 additions & 0 deletions test/t8_cmesh/t8_gtest_cmesh_face_is_boundary.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ TEST_P (cmesh_face_boundary_one_tree, check_face_is_boundary_one_tree)
ASSERT_TRUE (t8_cmesh_tree_face_is_boundary (cmesh, 0, iface)) << "Face is not detected as a boundary";
ASSERT_LT (t8_cmesh_get_face_neighbor (cmesh, 0, iface, NULL, NULL), 0)
<< "Face neighbor on boundary face detected";
const t8_eclass_t should_be_invalid = t8_cmesh_get_tree_face_neighbor_eclass (cmesh, 0, iface);
EXPECT_EQ (should_be_invalid, T8_ECLASS_INVALID)
<< "eclass of non-existing face neighbor should be invalid but is not.";
}
}

Expand Down Expand Up @@ -162,6 +165,12 @@ TEST_P (cmesh_face_boundary_two_trees, check_face_is_boundary_two_trees)
<< "Face neighbor on boundary face detected. Tree 0 face " << checkface << ".";
ASSERT_LT (t8_cmesh_get_face_neighbor (cmesh, 1, checkface, NULL, NULL), 0)
<< "Face neighbor on boundary face detected. Tree 1 face " << checkface << ".";
const t8_eclass_t should_be_invalid_tree0 = t8_cmesh_get_tree_face_neighbor_eclass (cmesh, 0, checkface);
EXPECT_EQ (should_be_invalid_tree0, T8_ECLASS_INVALID)
<< "eclass of non-existing face neighbor should be invalid but is not.";
const t8_eclass_t should_be_invalid_tree1 = t8_cmesh_get_tree_face_neighbor_eclass (cmesh, 1, checkface);
EXPECT_EQ (should_be_invalid_tree1, T8_ECLASS_INVALID)
<< "eclass of non-existing face neighbor should be invalid but is not.";
}
else {
/* checkface == iface
Expand All @@ -178,6 +187,9 @@ TEST_P (cmesh_face_boundary_two_trees, check_face_is_boundary_two_trees)
ASSERT_TRUE (face_neighbor) << "Wrong face neighbor computed. Expected 1 got" << face_neighbor << ".";
ASSERT_EQ (dual_face, checkface) << "Wrong dual face. Expected " << checkface << " got " << dual_face << ".";
ASSERT_EQ (orientation, 0) << "Wrong orientation. Expected 0 got " << orientation << ".";
// Check t8_cmesh_get_tree_face_neighbor_eclass
const t8_eclass_t neighbor_class_tree0 = t8_cmesh_get_tree_face_neighbor_eclass (cmesh, 0, iface);
EXPECT_EQ (neighbor_class_tree0, eclass) << "Wrong eclass of face neighbor computed.";
/* Check that tree 1 face is not a boundary */
ASSERT_FALSE (t8_cmesh_tree_face_is_boundary (cmesh, 1, checkface))
<< "Face is wrongly detected as a boundary.";
Expand All @@ -191,6 +203,9 @@ TEST_P (cmesh_face_boundary_two_trees, check_face_is_boundary_two_trees)
ASSERT_EQ (face_neighbor, 0) << "Wrong face neighbor computed. Expected 0 got " << face_neighbor << ".";
ASSERT_EQ (dual_face, checkface) << "Wrong dual face. Expected " << checkface << " got " << dual_face << ".";
ASSERT_EQ (orientation, 0) << "Wrong orientation. Expected 0 got " << orientation << ".";
// Check t8_cmesh_get_tree_face_neighbor_eclass
const t8_eclass_t neighbor_class_tree1 = t8_cmesh_get_tree_face_neighbor_eclass (cmesh, 1, checkface);
EXPECT_EQ (neighbor_class_tree1, eclass) << "Wrong eclass of face neighbor computed.";
}
}
t8_cmesh_destroy (&cmesh);
Expand Down
5 changes: 5 additions & 0 deletions test/t8_cmesh/t8_gtest_cmesh_readmshfile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ t8_supported_msh_file (t8_cmesh_t cmesh)
ltree_id = t8_cmesh_get_face_neighbor (cmesh, ltree_it, i, NULL, NULL);
ASSERT_EQ (ltree_id, face_neigh_elem[ltree_it][i])
<< "The face neighbor element in the example test file was not read correctly.";
const t8_eclass_t neighbor_eclass = t8_cmesh_get_tree_face_neighbor_eclass (cmesh, ltree_it, i);
// If a face neighbor exists, the return value must match the element type, otherwise it must
// be T8_ECLASS_INVALID
const t8_eclass_t reference_value = face_neigh_elem[ltree_it][i] == -1 ? T8_ECLASS_INVALID : elem_type;
EXPECT_EQ (neighbor_eclass, reference_value) << "mismatch in face neighbor eclass.";
}
}
}
Expand Down