From f148d49faa8bb00847bb648b072888650aa6beb9 Mon Sep 17 00:00:00 2001 From: Lena Ploetzke Date: Tue, 13 Jan 2026 12:22:09 +0100 Subject: [PATCH 1/6] add constructor wrapper --- mesh_handle/constructor_wrapper.hxx | 97 +++++++++++++++++++ .../mesh_handle/t8_gtest_cache_competence.cxx | 47 ++------- .../t8_gtest_custom_competence.cxx | 31 +++--- test/mesh_handle/t8_gtest_ghost.cxx | 56 +++++------ test/mesh_handle/t8_gtest_mesh_handle.cxx | 59 +++++------ 5 files changed, 170 insertions(+), 120 deletions(-) create mode 100644 mesh_handle/constructor_wrapper.hxx diff --git a/mesh_handle/constructor_wrapper.hxx b/mesh_handle/constructor_wrapper.hxx new file mode 100644 index 0000000000..4e1a6913f5 --- /dev/null +++ b/mesh_handle/constructor_wrapper.hxx @@ -0,0 +1,97 @@ +/* + 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. +*/ + +/** \file constructor_wrapper.hxx + * Construct a mesh handle instance from a cmesh and some default mesh handles. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace t8_mesh_handle +{ + +/** Build a uniformly refined mesh handle on a coarse mesh using a default scheme. + * \param [in] cmesh A coarse mesh. + * \param [in] level An initial uniform refinement level. + * \param [in] comm MPI communicator to use. + * \param [in] do_face_ghost If true, a layer of ghost elements is created. + * \tparam TMesh The mesh handle class. + * \return Unique pointer to a uniformly refined mesh handle with coarse mesh \a cmesh and refinement level \a level. + */ +template +std::unique_ptr +handle_new_uniform_default (const t8_cmesh_t cmesh, const int level, const sc_MPI_Comm comm, + const bool do_face_ghost = false) +{ + const t8_scheme *scheme = t8_scheme_new_default (); + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, do_face_ghost, sc_MPI_COMM_WORLD); + return std::make_unique (forest); +} + +/** Hybercube with 6 Tets, 6 Prism, 4 Hex. Refined uniformly to given level using the default scheme. + * \param [in] level An initial uniform refinement level. + * \param [in] comm MPI communicator to use. + * \param [in] do_partition If non-zero create a partitioned cmesh. + * \param [in] do_face_ghost If true, a layer of ghost elements is created. + * \param [in] periodic If non-zero create a periodic cmesh in each direction. + * \tparam TMesh The mesh handle class. + * \return Unique pointer to a uniformly refined mesh handle initially consisting of 6 Tets, 6 prism and 4 hex. + * Together, they form a cube. +*/ +template +std::unique_ptr +handle_hybrid_hypercube_uniform_default (const int level, const sc_MPI_Comm comm, const bool do_partition = false, + const bool do_face_ghost = false, const bool periodic = false) +{ + t8_cmesh_t cmesh = t8_cmesh_new_hypercube_hybrid (comm, do_partition, periodic); + return handle_new_uniform_default (cmesh, level, comm, do_face_ghost); +} + +/** Construct hybercube from one primitive tree class. Refined uniformly to given level using the default scheme. + * \param [in] eclass This element class determines the dimension and the number of trees needed to construct a cube. + * \param [in] level An initial uniform refinement level. + * \param [in] comm MPI communicator to use. + * \param [in] do_partition If non-zero create a partitioned cmesh. + * \param [in] do_face_ghost If true, a layer of ghost elements is created. + * \param [in] periodic If non-zero create a periodic cmesh in each direction. Not possible with \a eclass pyramid. + * \tparam TMesh The mesh handle class. + * \return Unique pointer to a uniformly refined mesh handle hypercube. +*/ +template +std::unique_ptr +handle_hypercube_uniform_default (t8_eclass_t eclass, const int level, const sc_MPI_Comm comm, + const bool do_partition = false, const bool do_face_ghost = false, + const bool periodic = false) +{ + // Broadcast option is hidden from the user. + t8_cmesh_t cmesh = t8_cmesh_new_hypercube (eclass, comm, 0, do_partition, periodic); + return handle_new_uniform_default (cmesh, level, comm, do_face_ghost); +} + +} // namespace t8_mesh_handle diff --git a/test/mesh_handle/t8_gtest_cache_competence.cxx b/test/mesh_handle/t8_gtest_cache_competence.cxx index 7c8f3521cd..0201c3e96f 100644 --- a/test/mesh_handle/t8_gtest_cache_competence.cxx +++ b/test/mesh_handle/t8_gtest_cache_competence.cxx @@ -30,10 +30,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include -#include -#include -#include -#include +#include #include #include @@ -67,44 +64,20 @@ struct cache_centroid_overwrite: public t8_mesh_handle::cache_centroidrc.refcount > 0) { - t8_forest_unref (&forest); - } - } - - t8_forest_t forest; - int level; -}; - /** Use child class of \ref t8_mesh_handle::cache_vertex_coordinates class to check that the cache is actually set * and accessed correctly. This is done by modifying the cache to an unrealistic value and * checking that the functionality actually outputs this unrealistic value. */ -TEST_F (t8_gtest_cache_competence, cache_vertex_coordinates) +TEST (t8_gtest_cache_competence, cache_vertex_coordinates) { + const int level = 1; using mesh_class = t8_mesh_handle::mesh; - using element_class = mesh_class::element_class; - mesh_class mesh = mesh_class (forest); + using element_class = typename mesh_class::element_class; + const auto mesh = t8_mesh_handle::handle_hybrid_hypercube_uniform_default (level, sc_MPI_COMM_WORLD); EXPECT_TRUE (element_class::has_vertex_cache ()); - EXPECT_FALSE (element_class::has_centroid_cache ()); std::vector unrealistic_vertex = { t8_3D_point ({ 41, 42, 43 }), t8_3D_point ({ 99, 100, 101 }) }; - for (auto it = mesh.begin (); it != mesh.end (); ++it) { + for (auto it = mesh->begin (); it != mesh->end (); ++it) { // Check that cache is empty at the beginning. EXPECT_FALSE (it->vertex_cache_filled ()); // Check that values are valid. @@ -128,16 +101,16 @@ TEST_F (t8_gtest_cache_competence, cache_vertex_coordinates) * and accessed correctly. This is done by modifying the cache to an unrealistic value and * checking that the functionality actually outputs this unrealistic value. */ -TEST_F (t8_gtest_cache_competence, cache_centroid) +TEST (t8_gtest_cache_competence, cache_centroid) { + const int level = 1; using mesh_class = t8_mesh_handle::mesh; using element_class = mesh_class::element_class; - mesh_class mesh = mesh_class (forest); - EXPECT_FALSE (element_class::has_vertex_cache ()); + const auto mesh = t8_mesh_handle::handle_hybrid_hypercube_uniform_default (level, sc_MPI_COMM_WORLD); EXPECT_TRUE (element_class::has_centroid_cache ()); t8_3D_point unrealistic_centroid ({ 999, 1000, 998 }); - for (auto it = mesh.begin (); it != mesh.end (); ++it) { + for (auto it = mesh->begin (); it != mesh->end (); ++it) { // Check that cache is empty at the beginning. EXPECT_FALSE (it->centroid_cache_filled ()); // Check that values are valid. diff --git a/test/mesh_handle/t8_gtest_custom_competence.cxx b/test/mesh_handle/t8_gtest_custom_competence.cxx index 8c842f3d6e..8d9fe89068 100644 --- a/test/mesh_handle/t8_gtest_custom_competence.cxx +++ b/test/mesh_handle/t8_gtest_custom_competence.cxx @@ -30,10 +30,8 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include -#include -#include +#include #include -#include #include /** @@ -45,9 +43,9 @@ struct dummy_get_level: public t8_crtp_operator { public: /** Getter for the level of the element. This function needs to access several members - * of the element such that we need the crtp structure here. - * \return Level of the element. - */ + * of the element such that we need the crtp structure here. + * \return Level of the element. + */ t8_element_level get_level_dummy () const { @@ -82,26 +80,23 @@ struct dummy_trivial: public t8_crtp_operator */ TEST (t8_gtest_custom_competence, custom_competence) { - // Define forest to construct mesh. - const int level = 1; - t8_cmesh_t cmesh = t8_cmesh_new_hypercube_hybrid (sc_MPI_COMM_WORLD, 0, 0); - const t8_scheme *scheme = t8_scheme_new_default (); - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); - // Check mesh with custom defined competence. - t8_mesh_handle::mesh mesh = t8_mesh_handle::mesh (forest); + using mesh_class = t8_mesh_handle::mesh; + const int level = 1; + const auto mesh = t8_mesh_handle::handle_hybrid_hypercube_uniform_default (level, sc_MPI_COMM_WORLD); - for (auto it = mesh.begin (); it != mesh.end (); ++it) { + for (auto it = mesh->begin (); it != mesh->end (); ++it) { EXPECT_EQ (it->get_level (), it->get_level_dummy ()); EXPECT_EQ (level, it->get_level_dummy ()); } - t8_forest_ref (forest); // Test with two custom competences and a predefined competence. - using mesh_class = t8_mesh_handle::mesh; - mesh_class mesh_more_competences = mesh_class (forest); + using mesh_class_more_cmpetences + = t8_mesh_handle::mesh; + auto mesh_more_competences + = t8_mesh_handle::handle_hybrid_hypercube_uniform_default (level, sc_MPI_COMM_WORLD); - for (auto it = mesh_more_competences.begin (); it != mesh_more_competences.end (); ++it) { + for (auto it = mesh_more_competences->begin (); it != mesh_more_competences->end (); ++it) { EXPECT_EQ (it->get_level (), it->get_level_dummy ()); EXPECT_EQ (it->get_value_dummy (), 1); EXPECT_FALSE (it->centroid_cache_filled ()); diff --git a/test/mesh_handle/t8_gtest_ghost.cxx b/test/mesh_handle/t8_gtest_ghost.cxx index 4b3038a3e6..868e9fa910 100644 --- a/test/mesh_handle/t8_gtest_ghost.cxx +++ b/test/mesh_handle/t8_gtest_ghost.cxx @@ -31,6 +31,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include +#include #include #include #include @@ -45,50 +46,42 @@ class t8_mesh_ghost_test: public testing::TestWithParam (GetParam ()); + eclass = std::get<0> (GetParam ()); level = std::get<1> (GetParam ()); - t8_cmesh_t cmesh = t8_cmesh_new_hypercube (eclass, sc_MPI_COMM_WORLD, 0, 1, 0); - forest = t8_forest_new_uniform (cmesh, scheme, level, 1, sc_MPI_COMM_WORLD); } - void - TearDown () override - { - if (forest->rc.refcount > 0) { - t8_forest_unref (&forest); - } - } - t8_forest_t forest; + + t8_eclass_t eclass; int level; }; /** Check the implementation of ghosts and all functions accessible by ghosts. */ TEST_P (t8_mesh_ghost_test, check_ghosts) { - t8_forest_ghost_print (forest); + using mesh_class = t8_mesh_handle::mesh<>; + auto mesh = t8_mesh_handle::handle_hypercube_uniform_default (eclass, level, sc_MPI_COMM_WORLD, true, + true, false); - t8_mesh_handle::mesh<> mesh = t8_mesh_handle::mesh<> (forest); - EXPECT_EQ (mesh.get_num_ghosts (), t8_forest_get_num_ghosts (forest)); - if ((mesh.get_dimension () > 1) && (mesh.get_num_local_elements () > 1)) { + EXPECT_EQ (mesh->get_num_ghosts (), t8_forest_get_num_ghosts (mesh->get_forest ())); + if ((mesh->get_dimension () > 1) && (mesh->get_num_local_elements () > 1)) { // Ensure that we actually have ghost elements in this test. - EXPECT_GT (mesh.get_num_ghosts (), 0); + EXPECT_GT (mesh->get_num_ghosts (), 0); } else { GTEST_SKIP () << "Skipping test as no ghost elements are created for 1D or single element meshes."; } // Check functions for ghost elements. - const t8_locidx_t num_local_elements = mesh.get_num_local_elements (); - const t8_locidx_t num_ghost_elements = mesh.get_num_ghosts (); + const t8_locidx_t num_local_elements = mesh->get_num_local_elements (); + const t8_locidx_t num_ghost_elements = mesh->get_num_ghosts (); for (t8_locidx_t ighost = num_local_elements; ighost < num_local_elements + num_ghost_elements; ++ighost) { - EXPECT_TRUE (mesh[ighost].is_ghost_element ()); - EXPECT_EQ (level, mesh[ighost].get_level ()); - auto centroid = mesh[ighost].get_centroid (); + EXPECT_TRUE ((*mesh)[ighost].is_ghost_element ()); + EXPECT_EQ (level, (*mesh)[ighost].get_level ()); + auto centroid = (*mesh)[ighost].get_centroid (); for (const auto& coordinate : centroid) { EXPECT_GE (1, coordinate); EXPECT_LE (0, coordinate); } - auto vertex_coordinates = mesh[ighost].get_vertex_coordinates (); + auto vertex_coordinates = (*mesh)[ighost].get_vertex_coordinates (); for (int ivertex = 0; ivertex < (int) vertex_coordinates.size (); ++ivertex) { for (const auto& coordinate : vertex_coordinates[ivertex]) { EXPECT_GE (1, coordinate); @@ -101,23 +94,23 @@ TEST_P (t8_mesh_ghost_test, check_ghosts) /** Check that the function \ref t8_mesh_handle::element::get_face_neighbors of the handle works as intended (equal results to forest).*/ TEST_P (t8_mesh_ghost_test, compare_neighbors_to_forest) { - ASSERT_TRUE (t8_forest_is_committed (forest)); + const t8_scheme* scheme = t8_scheme_new_default (); + t8_forest_t forest = t8_forest_new_uniform (t8_cmesh_new_hypercube (eclass, sc_MPI_COMM_WORLD, 0, 1, 0), scheme, + level, 1, sc_MPI_COMM_WORLD); t8_mesh_handle::mesh<> mesh = t8_mesh_handle::mesh<> (forest); EXPECT_EQ (mesh.get_num_ghosts (), t8_forest_get_num_ghosts (forest)); // Iterate over the elements of the forest and of the mesh handle simultaneously and compare results. - const t8_scheme* scheme = t8_forest_get_scheme (forest); auto mesh_iterator = mesh.begin (); for (t8_locidx_t itree = 0; itree < t8_forest_get_num_local_trees (forest); ++itree) { - const t8_eclass_t tree_class = t8_forest_get_tree_class (forest, itree); for (t8_locidx_t ielem = 0; ielem < t8_forest_get_tree_num_leaf_elements (forest, itree); ++ielem) { // --- Compare elements. --- EXPECT_EQ (mesh_iterator->get_local_tree_id (), itree); EXPECT_EQ (mesh_iterator->get_local_element_id (), ielem); // --- Compare neighbors. --- const t8_element_t* elem = t8_forest_get_leaf_element_in_tree (forest, itree, ielem); - const int num_faces = scheme->element_get_num_faces (tree_class, elem); + const int num_faces = scheme->element_get_num_faces (t8_forest_get_tree_class (forest, itree), elem); EXPECT_EQ (mesh_iterator->get_num_faces (), num_faces); for (int iface = 0; iface < num_faces; iface++) { // --- Get neighbors from forest. --- @@ -182,16 +175,17 @@ TEST_P (t8_mesh_ghost_test, cache_neighbors) { using mesh_class = t8_mesh_handle::mesh; using element_class = mesh_class::element_class; - mesh_class mesh = mesh_class (forest); + auto mesh = t8_mesh_handle::handle_hypercube_uniform_default (eclass, level, sc_MPI_COMM_WORLD, true, + true, false); EXPECT_TRUE (element_class::has_face_neighbor_cache ()); - if (mesh.get_num_local_elements () == 0) { + if (mesh->get_num_local_elements () == 0) { GTEST_SKIP () << "No local elements in the mesh to test the cache functionality."; } const std::vector unrealistic_neighbors - = { &mesh[0], &mesh[mesh.get_num_local_elements () - 1] }; + = { &((*mesh)[0]), &((*mesh)[mesh->get_num_local_elements () - 1]) }; const std::vector unrealistic_dual_faces = { 100, 1012000 }; - for (auto it = mesh.begin (); it != mesh.end (); ++it) { + for (auto it = mesh->begin (); it != mesh->end (); ++it) { // Check that cache is empty at the beginning. EXPECT_FALSE (it->neighbor_cache_filled_any ()); it->fill_face_neighbor_cache (); diff --git a/test/mesh_handle/t8_gtest_mesh_handle.cxx b/test/mesh_handle/t8_gtest_mesh_handle.cxx index 5d5a954cb7..f2d57edea3 100644 --- a/test/mesh_handle/t8_gtest_mesh_handle.cxx +++ b/test/mesh_handle/t8_gtest_mesh_handle.cxx @@ -31,10 +31,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include -#include -#include -#include -#include +#include /** Parametrized test fixture for the mesh handle tests. */ class t8_mesh_handle_test: public testing::TestWithParam> { @@ -42,36 +39,26 @@ class t8_mesh_handle_test: public testing::TestWithParam (GetParam ()); + eclass = std::get<0> (GetParam ()); level = std::get<1> (GetParam ()); - t8_cmesh_t cmesh = t8_cmesh_new_hypercube (eclass, sc_MPI_COMM_WORLD, 0, 1, 0); - forest = t8_forest_new_uniform (cmesh, scheme, level, 0, sc_MPI_COMM_WORLD); - } - void - TearDown () override - { - if (forest->rc.refcount > 0) { - t8_forest_unref (&forest); - } } - t8_forest_t forest; + t8_eclass_t eclass; int level; }; /** Test some default functionality and the iterator of \ref t8_mesh_handle::mesh class. */ TEST_P (t8_mesh_handle_test, test_iterator) { - // --- Check default functionality. --- using mesh_class = t8_mesh_handle::mesh<>; - using element_class = mesh_class::element_class; - mesh_class mesh = mesh_class (forest); + using element_class = typename mesh_class::element_class; + auto mesh = t8_mesh_handle::handle_hypercube_uniform_default (eclass, level, sc_MPI_COMM_WORLD, true, + true, false); EXPECT_FALSE (element_class::has_vertex_cache ()); EXPECT_FALSE (element_class::has_centroid_cache ()); // Iterate with the iterator over all mesh elements and check some functionality. - for (auto it = mesh.begin (); it != mesh.end (); ++it) { + for (auto it = mesh->begin (); it != mesh->end (); ++it) { EXPECT_FALSE (it->has_vertex_cache ()); EXPECT_FALSE (it->has_centroid_cache ()); auto centroid = it->get_centroid (); @@ -90,8 +77,8 @@ TEST_P (t8_mesh_handle_test, test_iterator) } // Check loop with indices. - for (int ielement = 0; ielement < mesh.get_num_local_elements (); ielement++) { - EXPECT_EQ (level, mesh[ielement].get_level ()); + for (int ielement = 0; ielement < mesh->get_num_local_elements (); ielement++) { + EXPECT_EQ (level, (*mesh)[ielement].get_level ()); } } @@ -100,13 +87,15 @@ TEST_P (t8_mesh_handle_test, test_competences) { // --- Version with cached vertex coordinates. --- using mesh_class_vertex = t8_mesh_handle::mesh; - using element_class_vertex = mesh_class_vertex::element_class; - mesh_class_vertex mesh_vertex = mesh_class_vertex (forest); + using element_class_vertex = typename mesh_class_vertex::element_class; + auto mesh_vertex = t8_mesh_handle::handle_hypercube_uniform_default ( + eclass, level, sc_MPI_COMM_WORLD, true, true, false); + EXPECT_TRUE (element_class_vertex::has_vertex_cache ()); EXPECT_FALSE (element_class_vertex::has_centroid_cache ()); // Iterate with the iterator over all mesh elements and check functionality. - for (auto it = mesh_vertex.begin (); it != mesh_vertex.end (); ++it) { + for (auto it = mesh_vertex->begin (); it != mesh_vertex->end (); ++it) { EXPECT_FALSE (it->vertex_cache_filled ()); EXPECT_EQ (level, it->get_level ()); auto centroid = it->get_centroid (); @@ -123,7 +112,7 @@ TEST_P (t8_mesh_handle_test, test_competences) } } // Check cached value. - for (auto it = mesh_vertex.begin (); it != mesh_vertex.end (); ++it) { + for (auto it = mesh_vertex->begin (); it != mesh_vertex->end (); ++it) { EXPECT_TRUE (it->vertex_cache_filled ()); auto vertex_coordinates = it->get_vertex_coordinates (); for (int ivertex = 0; ivertex < (int) vertex_coordinates.size (); ++ivertex) { @@ -135,15 +124,15 @@ TEST_P (t8_mesh_handle_test, test_competences) } // --- Version with cached centroid variable. --- - t8_forest_ref (forest); using mesh_class_centroid = t8_mesh_handle::mesh; - using element_class_centroid = mesh_class_centroid::element_class; - mesh_class_centroid mesh_centroid = mesh_class_centroid (forest); + using element_class_centroid = typename mesh_class_centroid::element_class; + auto mesh_centroid = t8_mesh_handle::handle_hypercube_uniform_default ( + eclass, level, sc_MPI_COMM_WORLD, true, true, false); EXPECT_FALSE (element_class_centroid::has_vertex_cache ()); EXPECT_TRUE (element_class_centroid::has_centroid_cache ()); // Iterate with the iterator over all mesh elements. - for (auto it = mesh_centroid.begin (); it != mesh_centroid.end (); ++it) { + for (auto it = mesh_centroid->begin (); it != mesh_centroid->end (); ++it) { EXPECT_FALSE (it->centroid_cache_filled ()); auto centroid = it->get_centroid (); for (const auto& coordinate : centroid) { @@ -164,13 +153,15 @@ TEST_P (t8_mesh_handle_test, test_2_competences) { // --- Use competences to cache level and centroid. --- using mesh_class = t8_mesh_handle::mesh; - using element_class = mesh_class::element_class; - mesh_class mesh = mesh_class (forest); + using element_class = typename mesh_class::element_class; + auto mesh = t8_mesh_handle::handle_hypercube_uniform_default (eclass, level, sc_MPI_COMM_WORLD, true, + true, false); + EXPECT_TRUE (element_class::has_vertex_cache ()); EXPECT_TRUE (element_class::has_centroid_cache ()); // Iterate with the iterator over all mesh elements. - for (auto it = mesh.begin (); it != mesh.end (); ++it) { + for (auto it = mesh->begin (); it != mesh->end (); ++it) { EXPECT_FALSE (it->centroid_cache_filled ()); EXPECT_FALSE (it->vertex_cache_filled ()); EXPECT_EQ (level, it->get_level ()); @@ -188,7 +179,7 @@ TEST_P (t8_mesh_handle_test, test_2_competences) } } // Test dereference operator. (Here the cached values should be used.) - for (auto it = mesh.begin (); it != mesh.end (); ++it) { + for (auto it = mesh->begin (); it != mesh->end (); ++it) { EXPECT_TRUE (it->centroid_cache_filled ()); EXPECT_TRUE (it->vertex_cache_filled ()); EXPECT_EQ (level, (*it).get_level ()); From a0a63e30e2a5b20bde9f16a7a13ea2fb3172fa0f Mon Sep 17 00:00:00 2001 From: Lena Ploetzke Date: Wed, 14 Jan 2026 16:21:38 +0100 Subject: [PATCH 2/6] small corrections --- mesh_handle/README.md | 7 +++-- mesh_handle/constructor_wrapper.hxx | 30 +++++++++++++++---- .../mesh_handle/t8_gtest_cache_competence.cxx | 4 +-- .../t8_gtest_custom_competence.cxx | 6 ++-- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/mesh_handle/README.md b/mesh_handle/README.md index 7cb21192ec..6316dfad89 100644 --- a/mesh_handle/README.md +++ b/mesh_handle/README.md @@ -7,6 +7,7 @@ Some application codes are designed for unstructured or uniform meshes and canno If you want to use the handle, note that is has its own library. Turn the option `T8CODE_BUILD_MESH_HANDLE` to `ON` and link against the target `T8_MESH_HANDLE` in addition to the usual t8code target please. The folder's most important files are: -The [mesh.hxx](mesh.hxx) defines the mesh class of the handle. This is the central file of the mesh handle. -The [element.hxx](element.hxx) defines the elements (mesh or ghost elements) of the mesh handle. -The [competences.hxx](competences.hxx) defines additional competences/functionality of an element to access additional data. +- The [mesh.hxx](mesh.hxx) defines the mesh class of the handle. This is the central file of the mesh handle. +- The [element.hxx](element.hxx) defines the elements (mesh or ghost elements) of the mesh handle. +- The [competences.hxx](competences.hxx) defines additional competences/functionality of an element to access additional data. +- The [constructor_wrapper.hxx](constructor_wrapper.hxx) allows to define a mesh handle using a cmesh instead of a forest and provides a very small number of examples where the user needs no cmesh. diff --git a/mesh_handle/constructor_wrapper.hxx b/mesh_handle/constructor_wrapper.hxx index 4e1a6913f5..77c498db45 100644 --- a/mesh_handle/constructor_wrapper.hxx +++ b/mesh_handle/constructor_wrapper.hxx @@ -21,7 +21,10 @@ */ /** \file constructor_wrapper.hxx - * Construct a mesh handle instance from a cmesh and some default mesh handles. + * Wrapper to construct a mesh handle instance from a cmesh. + * Additionally, a very small fraction of example coarse meshes is wrapped directly for easy access and + * for the use in tests. + * See \ref t8_cmesh_examples.hxx for more exemplary cmeshes to be put into the wrapper constructors. */ #pragma once @@ -36,6 +39,24 @@ namespace t8_mesh_handle { +/** Build a uniformly refined mesh handle on a coarse mesh using a scheme. + * \param [in] cmesh A coarse mesh. + * \param [in] scheme Refinement scheme to use. + * \param [in] level An initial uniform refinement level. + * \param [in] comm MPI communicator to use. + * \param [in] do_face_ghost If true, a layer of ghost elements is created. + * \tparam TMesh The mesh handle class. + * \return Unique pointer to a uniformly refined mesh handle with coarse mesh \a cmesh and refinement level \a level. + */ +template +std::unique_ptr +handle_new_uniform (const t8_cmesh_t cmesh, const t8_scheme *scheme, const int level, const sc_MPI_Comm comm, + const bool do_face_ghost = false) +{ + t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, do_face_ghost, sc_MPI_COMM_WORLD); + return std::make_unique (forest); +} + /** Build a uniformly refined mesh handle on a coarse mesh using a default scheme. * \param [in] cmesh A coarse mesh. * \param [in] level An initial uniform refinement level. @@ -49,11 +70,10 @@ std::unique_ptr handle_new_uniform_default (const t8_cmesh_t cmesh, const int level, const sc_MPI_Comm comm, const bool do_face_ghost = false) { - const t8_scheme *scheme = t8_scheme_new_default (); - t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, level, do_face_ghost, sc_MPI_COMM_WORLD); - return std::make_unique (forest); + return handle_new_uniform (cmesh, t8_scheme_new_default (), level, comm, do_face_ghost); } +// --- A very small fraction of example coarse meshes is wrapped here for easy access and for the use in tests. --- /** Hybercube with 6 Tets, 6 Prism, 4 Hex. Refined uniformly to given level using the default scheme. * \param [in] level An initial uniform refinement level. * \param [in] comm MPI communicator to use. @@ -66,7 +86,7 @@ handle_new_uniform_default (const t8_cmesh_t cmesh, const int level, const sc_MP */ template std::unique_ptr -handle_hybrid_hypercube_uniform_default (const int level, const sc_MPI_Comm comm, const bool do_partition = false, +handle_hypercube_hybrid_uniform_default (const int level, const sc_MPI_Comm comm, const bool do_partition = false, const bool do_face_ghost = false, const bool periodic = false) { t8_cmesh_t cmesh = t8_cmesh_new_hypercube_hybrid (comm, do_partition, periodic); diff --git a/test/mesh_handle/t8_gtest_cache_competence.cxx b/test/mesh_handle/t8_gtest_cache_competence.cxx index 0201c3e96f..a9798c13f4 100644 --- a/test/mesh_handle/t8_gtest_cache_competence.cxx +++ b/test/mesh_handle/t8_gtest_cache_competence.cxx @@ -73,7 +73,7 @@ TEST (t8_gtest_cache_competence, cache_vertex_coordinates) const int level = 1; using mesh_class = t8_mesh_handle::mesh; using element_class = typename mesh_class::element_class; - const auto mesh = t8_mesh_handle::handle_hybrid_hypercube_uniform_default (level, sc_MPI_COMM_WORLD); + const auto mesh = t8_mesh_handle::handle_hypercube_hybrid_uniform_default (level, sc_MPI_COMM_WORLD); EXPECT_TRUE (element_class::has_vertex_cache ()); std::vector unrealistic_vertex = { t8_3D_point ({ 41, 42, 43 }), t8_3D_point ({ 99, 100, 101 }) }; @@ -106,7 +106,7 @@ TEST (t8_gtest_cache_competence, cache_centroid) const int level = 1; using mesh_class = t8_mesh_handle::mesh; using element_class = mesh_class::element_class; - const auto mesh = t8_mesh_handle::handle_hybrid_hypercube_uniform_default (level, sc_MPI_COMM_WORLD); + const auto mesh = t8_mesh_handle::handle_hypercube_hybrid_uniform_default (level, sc_MPI_COMM_WORLD); EXPECT_TRUE (element_class::has_centroid_cache ()); t8_3D_point unrealistic_centroid ({ 999, 1000, 998 }); diff --git a/test/mesh_handle/t8_gtest_custom_competence.cxx b/test/mesh_handle/t8_gtest_custom_competence.cxx index 8d9fe89068..850f9a3736 100644 --- a/test/mesh_handle/t8_gtest_custom_competence.cxx +++ b/test/mesh_handle/t8_gtest_custom_competence.cxx @@ -83,7 +83,7 @@ TEST (t8_gtest_custom_competence, custom_competence) // Check mesh with custom defined competence. using mesh_class = t8_mesh_handle::mesh; const int level = 1; - const auto mesh = t8_mesh_handle::handle_hybrid_hypercube_uniform_default (level, sc_MPI_COMM_WORLD); + const auto mesh = t8_mesh_handle::handle_hypercube_hybrid_uniform_default (level, sc_MPI_COMM_WORLD); for (auto it = mesh->begin (); it != mesh->end (); ++it) { EXPECT_EQ (it->get_level (), it->get_level_dummy ()); @@ -91,10 +91,10 @@ TEST (t8_gtest_custom_competence, custom_competence) } // Test with two custom competences and a predefined competence. - using mesh_class_more_cmpetences + using mesh_class_more_competences = t8_mesh_handle::mesh; auto mesh_more_competences - = t8_mesh_handle::handle_hybrid_hypercube_uniform_default (level, sc_MPI_COMM_WORLD); + = t8_mesh_handle::handle_hypercube_hybrid_uniform_default (level, sc_MPI_COMM_WORLD); for (auto it = mesh_more_competences->begin (); it != mesh_more_competences->end (); ++it) { EXPECT_EQ (it->get_level (), it->get_level_dummy ()); From 31972ea8df157bc777af40d2f94df285dc4c7ddf Mon Sep 17 00:00:00 2001 From: Lena Ploetzke Date: Thu, 15 Jan 2026 09:57:42 +0100 Subject: [PATCH 3/6] doxygen --- mesh_handle/constructor_wrapper.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh_handle/constructor_wrapper.hxx b/mesh_handle/constructor_wrapper.hxx index 77c498db45..d5d11c1de6 100644 --- a/mesh_handle/constructor_wrapper.hxx +++ b/mesh_handle/constructor_wrapper.hxx @@ -24,7 +24,7 @@ * Wrapper to construct a mesh handle instance from a cmesh. * Additionally, a very small fraction of example coarse meshes is wrapped directly for easy access and * for the use in tests. - * See \ref t8_cmesh_examples.hxx for more exemplary cmeshes to be put into the wrapper constructors. + * See \ref t8_cmesh_examples.h for more exemplary cmeshes to be put into the wrapper constructors. */ #pragma once From e59c3f8f828f1dda6dfb673428d26bd0526350de Mon Sep 17 00:00:00 2001 From: lenaploetzke <70579874+lenaploetzke@users.noreply.github.com> Date: Mon, 19 Jan 2026 10:51:01 +0100 Subject: [PATCH 4/6] Apply suggestions from code review Co-authored-by: spenke91 --- mesh_handle/constructor_wrapper.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesh_handle/constructor_wrapper.hxx b/mesh_handle/constructor_wrapper.hxx index d5d11c1de6..11c44678ad 100644 --- a/mesh_handle/constructor_wrapper.hxx +++ b/mesh_handle/constructor_wrapper.hxx @@ -3,7 +3,7 @@ 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 + Copyright (C) 2026 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 From 5fce00e0d297dc34595703850501868a659dbcd2 Mon Sep 17 00:00:00 2001 From: Lena Ploetzke Date: Mon, 19 Jan 2026 10:56:12 +0100 Subject: [PATCH 5/6] rename constrcutor_wrapper --- mesh_handle/README.md | 2 +- .../{constructor_wrapper.hxx => constructor_wrappers.hxx} | 2 +- test/mesh_handle/t8_gtest_cache_competence.cxx | 2 +- test/mesh_handle/t8_gtest_custom_competence.cxx | 2 +- test/mesh_handle/t8_gtest_ghost.cxx | 2 +- test/mesh_handle/t8_gtest_mesh_handle.cxx | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename mesh_handle/{constructor_wrapper.hxx => constructor_wrappers.hxx} (99%) diff --git a/mesh_handle/README.md b/mesh_handle/README.md index 6316dfad89..96303c6b28 100644 --- a/mesh_handle/README.md +++ b/mesh_handle/README.md @@ -10,4 +10,4 @@ The folder's most important files are: - The [mesh.hxx](mesh.hxx) defines the mesh class of the handle. This is the central file of the mesh handle. - The [element.hxx](element.hxx) defines the elements (mesh or ghost elements) of the mesh handle. - The [competences.hxx](competences.hxx) defines additional competences/functionality of an element to access additional data. -- The [constructor_wrapper.hxx](constructor_wrapper.hxx) allows to define a mesh handle using a cmesh instead of a forest and provides a very small number of examples where the user needs no cmesh. +- The [constructor_wrappers.hxx](constructor_wrappers.hxx) allows to define a mesh handle using a cmesh instead of a forest and provides a very small number of examples where the user needs no cmesh. diff --git a/mesh_handle/constructor_wrapper.hxx b/mesh_handle/constructor_wrappers.hxx similarity index 99% rename from mesh_handle/constructor_wrapper.hxx rename to mesh_handle/constructor_wrappers.hxx index 11c44678ad..a18159c5ce 100644 --- a/mesh_handle/constructor_wrapper.hxx +++ b/mesh_handle/constructor_wrappers.hxx @@ -20,7 +20,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/** \file constructor_wrapper.hxx +/** \file constructor_wrappers.hxx * Wrapper to construct a mesh handle instance from a cmesh. * Additionally, a very small fraction of example coarse meshes is wrapped directly for easy access and * for the use in tests. diff --git a/test/mesh_handle/t8_gtest_cache_competence.cxx b/test/mesh_handle/t8_gtest_cache_competence.cxx index a9798c13f4..b505aa79aa 100644 --- a/test/mesh_handle/t8_gtest_cache_competence.cxx +++ b/test/mesh_handle/t8_gtest_cache_competence.cxx @@ -30,7 +30,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include -#include +#include #include #include diff --git a/test/mesh_handle/t8_gtest_custom_competence.cxx b/test/mesh_handle/t8_gtest_custom_competence.cxx index 850f9a3736..21ffb1705a 100644 --- a/test/mesh_handle/t8_gtest_custom_competence.cxx +++ b/test/mesh_handle/t8_gtest_custom_competence.cxx @@ -30,7 +30,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include -#include +#include #include #include diff --git a/test/mesh_handle/t8_gtest_ghost.cxx b/test/mesh_handle/t8_gtest_ghost.cxx index 868e9fa910..c6c709b82b 100644 --- a/test/mesh_handle/t8_gtest_ghost.cxx +++ b/test/mesh_handle/t8_gtest_ghost.cxx @@ -31,7 +31,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include -#include +#include #include #include #include diff --git a/test/mesh_handle/t8_gtest_mesh_handle.cxx b/test/mesh_handle/t8_gtest_mesh_handle.cxx index f2d57edea3..d8f21d0388 100644 --- a/test/mesh_handle/t8_gtest_mesh_handle.cxx +++ b/test/mesh_handle/t8_gtest_mesh_handle.cxx @@ -31,7 +31,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include -#include +#include /** Parametrized test fixture for the mesh handle tests. */ class t8_mesh_handle_test: public testing::TestWithParam> { From 73c27cbc7f18fdcb455ebb155b87d4d47df75c6b Mon Sep 17 00:00:00 2001 From: Lena Ploetzke Date: Mon, 19 Jan 2026 11:06:05 +0100 Subject: [PATCH 6/6] code review --- test/mesh_handle/t8_gtest_mesh_handle.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/mesh_handle/t8_gtest_mesh_handle.cxx b/test/mesh_handle/t8_gtest_mesh_handle.cxx index d8f21d0388..b98fe4dc47 100644 --- a/test/mesh_handle/t8_gtest_mesh_handle.cxx +++ b/test/mesh_handle/t8_gtest_mesh_handle.cxx @@ -43,8 +43,8 @@ class t8_mesh_handle_test: public testing::TestWithParam (GetParam ()); } - t8_eclass_t eclass; - int level; + t8_eclass_t eclass; /**< Element class used for testing.*/ + int level; /**< Refinement level used for testing.*/ }; /** Test some default functionality and the iterator of \ref t8_mesh_handle::mesh class. */