Skip to content
Draft
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
1 change: 0 additions & 1 deletion example/forest/t8_extruded_hex.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ main (int argc, char **argv)
t8_cmesh_t cmesh;
t8_cmesh_init (&cmesh);
t8_cmesh_new_brick_3d (cmesh, num_x, num_y, num_z, 0, 0, 0, comm);
SC_CHECK_ABORT (t8_cmesh_is_extrusion_compatible (cmesh), "The cmesh is not compatible with extruded hexes.");

t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_extruded (), level, 0, comm);
t8_global_productionf ("Uniform forest of level %i with %lli elements.\n", level,
Expand Down
2 changes: 1 addition & 1 deletion src/t8_cmesh/t8_cmesh_examples.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ t8_cmesh_new_hypercube (t8_cmesh_t *pcmesh, t8_eclass_t eclass, sc_MPI_Comm comm
t8_cmesh_set_tree_vertices (cmesh, 1, attr_vertices, 6);
if (periodic) {
t8_cmesh_set_join (cmesh, 0, 1, 0, 1, 0);
t8_cmesh_set_join (cmesh, 0, 1, 2, 0, 0);
t8_cmesh_set_join (cmesh, 0, 1, 2, 0, 1);
t8_cmesh_set_join (cmesh, 0, 0, 3, 4, 0);
t8_cmesh_set_join (cmesh, 1, 1, 3, 4, 0);
}
Expand Down
3 changes: 3 additions & 0 deletions src/t8_forest/t8_forest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3306,6 +3306,9 @@ t8_forest_commit (t8_forest_t forest)
* TODO: Remove when trees access schemes via key.
* Also remove the complete function t8_forest_scheme_is_valid */
T8_ASSERT (t8_forest_scheme_is_valid (forest->scheme));
/* Check if the scheme supports the trees of the cmesh and their face connections. */
SC_CHECK_ABORT (forest->scheme->cmesh_is_compatible (forest->cmesh),
"The cmesh is not compatible with the scheme of the forest.");

/* dup communicator if requested */
if (forest->do_dup) {
Expand Down
44 changes: 16 additions & 28 deletions src/t8_schemes/t8_extruded/t8_extruded.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ t8_extruded_num_lateral_faces (const t8_eclass_t eclass)
}
}

/** Check whether a single face connection of an extruded tree is compatible with the extruded schemes.
/** Check whether a single face connection between two extruded trees is compatible with the extruded schemes.
* \param [in] eclass The eclass of the tree, hex or prism.
* \param [in] face A face of the tree.
* \param [in] neigh_class The eclass of the neighbor tree.
* \param [in] neigh_class The eclass of the neighbor tree, hex or prism.
* \param [in] neigh_face The face of the neighbor tree.
* \param [in] orientation The orientation of the face connection.
* \return True if the connection is compatible.
Expand All @@ -90,10 +90,7 @@ t8_extruded_face_connection_is_compatible (const t8_eclass_t eclass, const int f
const int neigh_face, const int orientation)
{
const int neigh_num_lateral_faces = t8_extruded_num_lateral_faces (neigh_class);
if (neigh_num_lateral_faces < 0) {
/* The neighbor tree is not extruded. */
return false;
}
T8_ASSERT (neigh_num_lateral_faces > 0);
const bool face_is_lateral = face < t8_extruded_num_lateral_faces (eclass);
const bool neigh_face_is_lateral = neigh_face < neigh_num_lateral_faces;
if (face_is_lateral != neigh_face_is_lateral) {
Expand All @@ -116,34 +113,25 @@ t8_extruded_face_connection_is_compatible (const t8_eclass_t eclass, const int f
}

bool
t8_cmesh_is_extrusion_compatible (t8_cmesh_t cmesh)
t8_extruded_cmesh_tree_is_compatible (const t8_scheme *scheme, const t8_cmesh_t cmesh, const t8_locidx_t ltreeid)
{
T8_ASSERT (t8_cmesh_is_committed (cmesh));
const t8_locidx_t num_local_trees = t8_cmesh_get_num_local_trees (cmesh);
for (t8_locidx_t ltree = 0; ltree < num_local_trees; ++ltree) {
const t8_eclass_t eclass = t8_cmesh_get_tree_class (cmesh, ltree);
if (t8_eclass_to_dimension[eclass] < 3) {
/* Lower dimensional trees use the default schemes. */
const t8_eclass_t eclass = t8_cmesh_get_tree_class (cmesh, ltreeid);
T8_ASSERT (t8_eclass_scheme_is_extruded (scheme, eclass));
for (int face = 0; face < t8_eclass_num_faces[eclass]; ++face) {
int neigh_face;
int orientation;
const t8_locidx_t neigh_tree = t8_cmesh_get_face_neighbor (cmesh, ltreeid, face, &neigh_face, &orientation);
if (neigh_tree < 0) {
/* No neighbor across this face. */
continue;
}
if (t8_extruded_num_lateral_faces (eclass) < 0) {
t8_debugf ("Local tree %i of class %s cannot be extruded.\n", ltree, t8_eclass_to_string[eclass]);
const t8_eclass_t neigh_class = t8_cmesh_get_tree_face_neighbor_eclass (cmesh, ltreeid, face);
if (!t8_eclass_scheme_is_extruded (scheme, neigh_class)
|| !t8_extruded_face_connection_is_compatible (eclass, face, neigh_class, neigh_face, orientation)) {
t8_debugf ("Face %i of local tree %i is not compatible with the extruded schemes.\n", face, ltreeid);
return false;
}
for (int face = 0; face < t8_eclass_num_faces[eclass]; ++face) {
int neigh_face;
int orientation;
const t8_locidx_t neigh_tree = t8_cmesh_get_face_neighbor (cmesh, ltree, face, &neigh_face, &orientation);
if (neigh_tree < 0) {
/* No neighbor across this face. */
continue;
}
const t8_eclass_t neigh_class = t8_cmesh_get_tree_face_neighbor_eclass (cmesh, ltree, face);
if (!t8_extruded_face_connection_is_compatible (eclass, face, neigh_class, neigh_face, orientation)) {
t8_debugf ("Face %i of local tree %i is not compatible with the extruded schemes.\n", face, ltree);
return false;
}
}
}
return true;
}
15 changes: 0 additions & 15 deletions src/t8_schemes/t8_extruded/t8_extruded.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,3 @@ t8_scheme_new_extruded ();
*/
int
t8_eclass_scheme_is_extruded (const t8_scheme *scheme, const t8_eclass_t eclass);

/** Check whether a cmesh is compatible with the extruded schemes.
* All 3D trees have to be extruded, that is hexes or prisms, no tets or pyramids.
* The extruded elements span the whole tree height, so the extrusion (z-) directions of
* neighboring trees have to be parallel. That is, for each local 3D tree:
* - A lateral face (hex: 0, ..., 3, prism: 0, 1, 2) is only connected to a lateral face of another hex or prism tree,
* such that the z-axes of both trees are parallel (possibly with opposite directions).
* - The bottom and top face (hex: 4, 5, prism: 3, 4) are only connected to the bottom or top face of another tree.
* Cmeshes without 3D trees are always compatible.
* \param [in] cmesh A committed cmesh.
* \return True if all local trees and their face connections are compatible, false otherwise.
* \note This function is not collective. It only checks the local trees of \a cmesh.
*/
bool
t8_cmesh_is_extrusion_compatible (t8_cmesh_t cmesh);
33 changes: 31 additions & 2 deletions src/t8_schemes/t8_extruded/t8_extruded_scheme.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@
*
* Face numbering: The lateral faces 0, ..., F-1 are the extrusions of the F faces of the base element.
* Face F is the bottom and face F + 1 the top face. Vertex v is the base vertex v % V at the bottom (v < V) or
* the top (v >= V), where V is the number of base vertices. This matches the default hex (and prism) conventions.
* the top (v >= V), where V is the number of base vertices. This matches the default hex and prism conventions.
*
* The face elements of lateral faces are quads in the scheme of the face eclass. Since the element spans the whole tree
* height, the lateral face element stores the in-plane coordinate in x and 0 in y. The z-part is ignored when
* extruding the face again. This is only consistent, if all trees glued at lateral faces have parallel extrusion
* directions, see \ref t8_cmesh_is_extrusion_compatible.
* directions, see \ref t8_extruded_cmesh_tree_is_compatible.
*/

#pragma once
Expand All @@ -50,6 +50,21 @@
#include <cstring>
#include <utility>

/** Check whether a local hex or prism tree of a cmesh is compatible with the extruded schemes.
* The extruded elements span the whole tree height, so the extrusion (z-) directions of neighboring trees have to be
* parallel. That is, for each face of the tree:
* - The neighbor tree also uses an extruded scheme.
* - A lateral face (hex: 0, ..., 3, prism: 0, 1, 2) is only connected to a lateral face, such that the z-axes of
* both trees are parallel (possibly with opposite directions).
* - The bottom and top face (hex: 4, 5, prism: 3, 4) are only connected to the bottom or top face of another tree.
* \param [in] scheme The scheme containing the extruded schemes.
* \param [in] cmesh A committed cmesh.
* \param [in] ltreeid A local tree of \a cmesh, whose class uses an extruded scheme in \a scheme.
* \return True if all face connections of the tree are compatible, false otherwise.
*/
bool
t8_extruded_cmesh_tree_is_compatible (const t8_scheme *scheme, const t8_cmesh_t cmesh, const t8_locidx_t ltreeid);

/** Scheme for extruded elements.
* \tparam TEclass The 3D element class of the extruded trees.
* \tparam TBaseScheme The scheme of the 2D base elements.
Expand Down Expand Up @@ -111,6 +126,20 @@ struct t8_extruded_scheme: public t8_scheme_helpers<TEclass, t8_extruded_scheme<
return sizeof (TBaseElem);
}

/** Check whether a local tree of a cmesh can be used with the extruded scheme,
* see \ref t8_extruded_cmesh_tree_is_compatible.
* \param [in] scheme The scheme this eclass scheme is part of.
* \param [in] cmesh A committed cmesh.
* \param [in] ltreeid A local tree of \a cmesh of class \a TEclass.
* \return True if the face connections of the tree are compatible.
*/
inline bool
cmesh_tree_is_compatible (const t8_scheme *scheme, const t8_cmesh_t cmesh, const t8_locidx_t ltreeid) const
{
T8_ASSERT (t8_cmesh_get_tree_class (cmesh, ltreeid) == TEclass);
return t8_extruded_cmesh_tree_is_compatible (scheme, cmesh, ltreeid);
}

/** Returns true, if there is one element in the tree, that does not refine into 2^dim children.
* \return Dictated by the base scheme because no refinement occurs in extruded direction.
*/
Expand Down
9 changes: 9 additions & 0 deletions src/t8_schemes/t8_scheme.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ t8_scheme_unref (t8_scheme_c **pscheme)
}
}

int
t8_scheme_cmesh_is_compatible (const t8_scheme_c *scheme, struct t8_cmesh *cmesh)
{
T8_ASSERT (scheme != NULL);
T8_ASSERT (cmesh != NULL);

return scheme->cmesh_is_compatible (cmesh);
}

size_t
t8_element_get_element_size (const t8_scheme_c *scheme, const t8_eclass_t tree_class)
{
Expand Down
12 changes: 12 additions & 0 deletions src/t8_schemes/t8_scheme.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
*/
typedef struct t8_scheme t8_scheme_c;

/* Forward declaration of the cmesh, since t8_cmesh.h includes this header. */
struct t8_cmesh;

T8_EXTERN_C_BEGIN ();

/** Increase the reference counter of a scheme.
Expand All @@ -58,6 +61,15 @@ t8_scheme_ref (t8_scheme_c *scheme);
void
t8_scheme_unref (t8_scheme_c **pscheme);

/** Check whether all local trees of a cmesh can be used with a scheme.
* \param [in] scheme A scheme.
* \param [in] cmesh A committed cmesh.
* \return True if all local trees and their face connections are supported by \a scheme.
* \note This function is not collective. It only checks the local trees of \a cmesh.
*/
int
t8_scheme_cmesh_is_compatible (const t8_scheme_c *scheme, struct t8_cmesh *cmesh);

/** Return the size of any element of a given class.
* \return The size of an element of class \b ts.
* We provide a default implementation of this routine that should suffice
Expand Down
31 changes: 31 additions & 0 deletions src/t8_schemes/t8_scheme.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <vector>
#include <t8_helper_functions/t8_refcount.h>
#include <t8_eclass/t8_eclass.h>
#include <t8_cmesh/t8_cmesh.h>
#include <t8_schemes/t8_default/t8_default.hxx>
#include <t8_schemes/t8_default/t8_default_vertex/t8_default_vertex.hxx>
#include <t8_schemes/t8_default/t8_default_line/t8_default_line.hxx>
Expand Down Expand Up @@ -191,6 +192,36 @@ struct t8_scheme
return std::visit ([&] (auto &&scheme) { return scheme.get_dimension (); }, eclass_schemes[tree_class]);
}

/** Check whether a local tree of a cmesh can be used with its eclass scheme.
* \param [in] tree_class The eclass of the tree.
* \param [in] cmesh A committed cmesh.
* \param [in] ltreeid A local tree of \a cmesh of class \a tree_class.
* \return True if the tree and its face connections are supported by the eclass scheme.
*/
inline bool
cmesh_tree_is_compatible (const t8_eclass_t tree_class, const t8_cmesh_t cmesh, const t8_locidx_t ltreeid) const
{
return std::visit ([&] (auto &&scheme) { return scheme.cmesh_tree_is_compatible (this, cmesh, ltreeid); },
eclass_schemes[tree_class]);
}

/** Check whether all local trees of a cmesh can be used with this scheme.
* \param [in] cmesh A committed cmesh.
* \return True if all local trees and their face connections are supported.
* \note This function is not collective. It only checks the local trees of \a cmesh.
*/
inline bool
cmesh_is_compatible (const t8_cmesh_t cmesh) const
{
const t8_locidx_t num_local_trees = t8_cmesh_get_num_local_trees (cmesh);
for (t8_locidx_t ltreeid = 0; ltreeid < num_local_trees; ++ltreeid) {
if (!cmesh_tree_is_compatible (t8_cmesh_get_tree_class (cmesh, ltreeid), cmesh, ltreeid)) {
return false;
}
}
return true;
}

/** Return the size of any element of a given class.
* \param [in] tree_class The eclass of the current tree.
* \return The size of an element of class \a tree_class.
Expand Down
17 changes: 17 additions & 0 deletions src/t8_schemes/t8_scheme_helpers.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
#include <t8_element/t8_element.h>
#include <t8_types/t8_crtp.hxx>
#include <t8_eclass/t8_eclass.h>
#include <t8_cmesh/t8_cmesh.h>

struct t8_scheme;

/**
* Class which provides helper functions and default implementations for different schemes.
Expand Down Expand Up @@ -65,6 +68,20 @@ struct t8_scheme_helpers: public t8_crtp_basic<TUnderlyingEclassScheme>
return TEclass;
}

/** Check whether a local tree of a cmesh can be used with this eclass scheme.
* By default, all trees and face connections are supported.
* \param [in] scheme The scheme this eclass scheme is part of, to look up the schemes of neighbor trees.
* \param [in] cmesh A committed cmesh.
* \param [in] ltreeid A local tree of \a cmesh of class \a TEclass.
* \return True if the tree and its face connections are supported.
*/
inline bool
cmesh_tree_is_compatible ([[maybe_unused]] const t8_scheme *scheme, [[maybe_unused]] const t8_cmesh_t cmesh,
[[maybe_unused]] const t8_locidx_t ltreeid) const
{
return true;
}

/** 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
Expand Down
8 changes: 4 additions & 4 deletions test/t8_forest/t8_gtest_leaf_face_neighbors.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ TEST_P (forest_face_neighbors_two_quad_mesh, check_neighbors)
T8_FREE (dual_faces);
}
} // End face loop
} // End leaf in tree loop
} // End leaf in tree loop
if (gtreeid == 0) {
// Tree 0 must have >0 faces with 1 neighbor.
EXPECT_GE (num_faces_with_1_neighbor, 1) << "Tree 1 must have 1 face with 2 neighbors.";
Expand Down Expand Up @@ -775,7 +775,7 @@ TEST_P (forest_face_neighbors_subface, test_face_neighbor_subface)
T8_TESTSUITE_FREE (neigh_children);

} // end if(neighbor_level == level - 1)
} // end if(num_neighbors == 1)
} // end if(num_neighbors == 1)

// Manually free memory allocated by t8code inside t8_forest_leaf_face_neighbors_ext.
if (num_neighbors > 0) {
Expand All @@ -784,8 +784,8 @@ TEST_P (forest_face_neighbors_subface, test_face_neighbor_subface)
T8_FREE (dual_faces);
}
} // end face loop
} // end element loop
} // end tree loop
} // end element loop
} // end tree loop
}

// We check for all cmesh examples and scheme collections.
Expand Down
4 changes: 2 additions & 2 deletions test/t8_forest/t8_gtest_user_data.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ TEST_P (forest_user_data, test_user_function)
void (*funpointer_second) (void);

/* Set the t8_test_function_42 as user function pointer. */
t8_forest_set_user_function (forest, (void (*) (void)) &t8_test_function_42);
t8_forest_set_user_function (forest, (void (*) (void)) & t8_test_function_42);
/* Retrieve the function pointer from the forest. */
funpointer = (double (*) (int)) t8_forest_get_user_function (forest);

Expand All @@ -135,7 +135,7 @@ TEST_P (forest_user_data, test_user_function)
ASSERT_EQ (funpointer (0), 42.42) << "Forest function pointer returned wrong result.";

/* Overwrite the function user pointer with a second function. */
t8_forest_set_user_function (forest, (void (*) (void)) &t8_test_function_second);
t8_forest_set_user_function (forest, (void (*) (void)) & t8_test_function_second);
/* Retrieve the function pointer from the forest. */
funpointer_second = (void (*) (void)) t8_forest_get_user_function (forest);

Expand Down
12 changes: 5 additions & 7 deletions test/t8_gtest_schemes.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,8 @@ create_from_scheme_id (const int scheme_id)
}
}

/** Check whether a cmesh is supported by the scheme of a given scheme id.
* The extruded scheme only supports cmeshes whose hex trees have parallel extrusion directions,
* see \ref t8_cmesh_is_extrusion_compatible. All other schemes support all cmeshes.
/** Check whether a cmesh is supported by the scheme of a given scheme id, see \ref t8_scheme::cmesh_is_compatible.
* For example, the extruded scheme only supports cmeshes whose extruded trees have parallel extrusion directions.
* \param [in] scheme_id The scheme id, see \ref create_from_scheme_id.
* \param [in] cmesh A committed cmesh.
* \param [in] comm The communicator of \a cmesh.
Expand All @@ -64,10 +63,9 @@ create_from_scheme_id (const int scheme_id)
inline bool
t8_test_scheme_supports_cmesh (const int scheme_id, t8_cmesh_t cmesh, sc_MPI_Comm comm)
{
if (scheme_id != 2) {
return true;
}
int is_compatible = t8_cmesh_is_extrusion_compatible (cmesh);
const t8_scheme *scheme = create_from_scheme_id (scheme_id);
int is_compatible = scheme->cmesh_is_compatible (cmesh);
scheme->unref ();
int is_compatible_all = 0;
const int mpiret = sc_MPI_Allreduce (&is_compatible, &is_compatible_all, 1, sc_MPI_INT, sc_MPI_LAND, comm);
SC_CHECK_MPI (mpiret);
Expand Down
Loading