diff --git a/mesh_handle/constructor_wrappers.hxx b/mesh_handle/constructor_wrappers.hxx index 28a0c09907..bd85e6977b 100644 --- a/mesh_handle/constructor_wrappers.hxx +++ b/mesh_handle/constructor_wrappers.hxx @@ -47,7 +47,8 @@ namespace t8_mesh_handle * \param [in] comm MPI communicator to use. * \param [in] do_face_ghost If true, a layer of ghost elements is created. * \tparam TMeshClass The mesh handle class. - * \return Unique pointer to a uniformly refined mesh handle with coarse mesh \a cmesh and refinement level \a level. + * \return Unique pointer to a uniformly refined mesh handle with coarse mesh \a cmesh and refinement level \a level, + * partitioned across the processes in \a comm. */ template std::unique_ptr diff --git a/mesh_handle/mesh.hxx b/mesh_handle/mesh.hxx index b08fba5e78..6dacfc2419 100644 --- a/mesh_handle/mesh.hxx +++ b/mesh_handle/mesh.hxx @@ -141,6 +141,16 @@ class mesh: public TMeshCompetencePack::template apply mesh = t8_mesh_handle::mesh<> (forest); EXPECT_EQ (mesh.get_num_local_elements (), t8_forest_get_local_num_leaf_elements (forest)); + EXPECT_EQ (mesh.get_num_global_elements (), t8_forest_get_global_num_leaf_elements (forest)); EXPECT_EQ (mesh.get_num_ghosts (), t8_forest_get_num_ghosts (forest)); EXPECT_EQ (mesh.get_dimension (), t8_forest_get_dimension (forest)); diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index 4c21e232db..c9611a1346 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -83,4 +83,5 @@ copy_tutorial_file (features/t8_features_curved_meshes_generate_cmesh_tri.geo) if( T8CODE_BUILD_MESH_HANDLE ) add_mesh_handle_tutorial( NAME t8_mesh_element_data SOURCES mesh_handle/t8_mesh_element_data.cxx ) + add_mesh_handle_tutorial( NAME t8_mesh_step2_uniform_mesh SOURCES mesh_handle/t8_mesh_step2_uniform_mesh.cxx ) endif() diff --git a/tutorials/general/t8_step1_coarsemesh.cxx b/tutorials/general/t8_step1_coarsemesh.cxx index 4cc9074d5f..5b88faa0ac 100644 --- a/tutorials/general/t8_step1_coarsemesh.cxx +++ b/tutorials/general/t8_step1_coarsemesh.cxx @@ -110,7 +110,7 @@ main (int argc, char **argv) /* Initialize the sc library, has to happen before we initialize t8code. */ sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_ESSENTIAL); /* Initialize t8code with log level SC_LP_PRODUCTION. See sc.h for more info on the log levels. */ - t8_init (SC_LP_DEBUG); + t8_init (SC_LP_PRODUCTION); /* Print a message on the root process. */ t8_global_productionf (" [step1] \n"); diff --git a/tutorials/general/t8_step2_uniform_forest.cxx b/tutorials/general/t8_step2_uniform_forest.cxx index 5e6f432a6d..3b37e17b12 100644 --- a/tutorials/general/t8_step2_uniform_forest.cxx +++ b/tutorials/general/t8_step2_uniform_forest.cxx @@ -33,7 +33,7 @@ * forest how elements of each shape (t8_eclass_t) are refined, what their neighbor * are etc. * The default scheme in t8_schemes/t8_default/t8_default.hxx provides an implementation for - * all element shapes that t8code supports (with pyramids currently under construction). + * all element shapes that t8code supports. * * How you can experiment here: * - Use Paraview to visualize the output files. @@ -138,7 +138,7 @@ main (int argc, char **argv) /* Initialize the sc library, has to happen before we initialize t8code. */ sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_ESSENTIAL); /* Initialize t8code with log level SC_LP_PRODUCTION. See sc.h for more info on the log levels. */ - t8_init (SC_LP_DEBUG); + t8_init (SC_LP_PRODUCTION); /* Print a message on the root process. */ t8_global_productionf (" [step2] \n"); diff --git a/tutorials/mesh_handle/t8_mesh_step2_uniform_mesh.cxx b/tutorials/mesh_handle/t8_mesh_step2_uniform_mesh.cxx new file mode 100644 index 0000000000..cfccc0dcf4 --- /dev/null +++ b/tutorials/mesh_handle/t8_mesh_step2_uniform_mesh.cxx @@ -0,0 +1,147 @@ +/* + 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 types in parallel. + + 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 + 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 t8_mesh_step2_uniform_mesh.cxx + * This is step 2 of the t8code mesh handle tutorials. + * Therefore, this is the same as general/t8_step2_uniform_forest.cxx but using the mesh handle interface instead of the forest + * interface. + * After we learned how to create a cmesh in step1, we will + * now build our first partitioned mesh, get its local and global + * element count, and output it into .vtu files. + * + * When we create a mesh from a coarse mesh using the mesh handle interface, the mesh will always be + * uniform (every element has the same refinement level) and can then be adapted + * later (see the following steps). + * Together with the cmesh, we also need a refinement scheme. This scheme tells the + * mesh how elements of each shape (t8_eclass_t) are refined, what their neighbors + * are etc. + * The default scheme in t8_schemes/t8_default/t8_default.hxx provides an implementation for + * all element shapes that t8code supports. +*/ +#include /** General t8code header, always include this. */ +#include /** General Mesh Header, always needed for mesh_handle code. */ +#include /** cmesh definition and basic interface. */ +#include /** Wrapper for basic Cmesh to mesh_handle conversions. */ +#include /** Used to export mesh to vtk files. */ +#include /** default refinement scheme. */ +#include + +/** Builds cmesh of 2 prisms that build up a unit cube. + * See step1 for a detailed description. + * \param [in] comm MPI Communicator to use. + * \return The coarse mesh. + */ +static t8_cmesh_t +t8_step2_build_prismcube_coarse_mesh (sc_MPI_Comm comm) +{ + t8_cmesh_t cmesh; + + /* Build a coarse mesh of 2 prisms that form a cube. */ + t8_cmesh_init (&cmesh); + t8_cmesh_new_hypercube (&cmesh, T8_ECLASS_PRISM, comm, 0, 0, 0); + t8_global_productionf (" [tutorial] Constructed coarse mesh with 2 prisms.\n"); + + return cmesh; +} + +/** Build a uniform mesh on a cmesh using the default refinement scheme. + * \param [in] comm MPI Communicator to use. + * \param [in] cmesh The coarse mesh to build the uniform mesh on. + * \param [in] level The initial uniform refinement level. + * \return A uniform mesh with the given refinement level that is + * partitioned across the processes in \a comm. + */ +template +static std::unique_ptr +t8_step2_build_uniform_mesh (sc_MPI_Comm comm, t8_cmesh_t cmesh, int level) +{ + const t8_scheme *scheme = t8_scheme_new_default (); /** Default refinement scheme. */ + + /* Build the uniform mesh, it is automatically partitioned among the processes. */ + std::unique_ptr mesh = t8_mesh_handle::handle_new_uniform (cmesh, scheme, level, comm); + + t8_global_productionf (" [t8_step2] Constructed uniform mesh with refinement level %d.\n", level); + + return mesh; +} + +int +main (int argc, char **argv) +{ + /** File prefix for our vtk files. */ + const char *prefix = "t8_step2_uniform_mesh"; + /** Uniform refinement level of the mesh. */ + const int level = 3; + + /** Initialize MPI. This has to happen before we initialize sc or t8code. */ + int mpiret = sc_MPI_Init (&argc, &argv); + /** Error check the MPI return value. */ + SC_CHECK_MPI (mpiret); + + /** Initialize the sc library, has to happen before we initialize t8code. */ + sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_ESSENTIAL); + /** Initialize t8code with log level SC_LP_PRODUCTION. See sc.h for more info on the log levels. */ + t8_init (SC_LP_PRODUCTION); + + /** Print a message on the root process. */ + t8_global_productionf (" [t8_step2] \n"); + t8_global_productionf (" [t8_step2] Hello, this is the step2 example of t8code using the mesh handle.\n"); + t8_global_productionf (" [t8_step2] In this example we build our first uniform mesh and output it to vtu files.\n"); + t8_global_productionf (" [t8_step2] \n"); + + /** We will use MPI_COMM_WORLD as a communicator. */ + sc_MPI_Comm comm = sc_MPI_COMM_WORLD; + + /** Create the cmesh. */ + t8_cmesh_t cmesh = t8_step2_build_prismcube_coarse_mesh (comm); + /** + * We will put the Mesh in a separate scope here, + * because it will destroy itself completely on its own when reaching the end of this scope. + */ + { + /** Build the uniform mesh. */ + auto mesh = t8_step2_build_uniform_mesh> (comm, cmesh, level); + /** Get the number of local elements. */ + const t8_locidx_t local_num_elements = mesh->get_num_local_elements (); + /** Get the number of global elements. */ + const t8_gloidx_t global_num_elements = mesh->get_num_global_elements (); + + /** Print information on the mesh. */ + t8_global_productionf (" [t8_step2] Created uniform mesh.\n"); + t8_global_productionf (" [t8_step2] Refinement level:\t\t\t%i\n", level); + t8_global_productionf (" [t8_step2] Local number of elements:\t\t%i\n", local_num_elements); + t8_global_productionf (" [t8_step2] Global number of elements:\t%" T8_GLOIDX_FORMAT "\n", global_num_elements); + + /** Write mesh to vtu files. */ + t8_mesh_handle::write_mesh_to_vtk (*mesh, prefix); + t8_global_productionf (" [t8_step2] Wrote mesh to vtu files:\t%s*\n", prefix); + + } /** End of Mesh scope. */ + t8_global_productionf (" [t8_step2] Mesh scope ended.\n"); + + sc_finalize (); + + mpiret = sc_MPI_Finalize (); + SC_CHECK_MPI (mpiret); + + return 0; +}