Skip to content
Merged
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
3 changes: 2 additions & 1 deletion mesh_handle/constructor_wrappers.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -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 <T8MeshType TMeshClass>
std::unique_ptr<TMeshClass>
Expand Down
10 changes: 10 additions & 0 deletions mesh_handle/mesh.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,16 @@ class mesh: public TMeshCompetencePack::template apply<mesh<TElementCompetencePa
return t8_forest_get_local_num_leaf_elements (m_forest);
}

/**
* Getter for the number of global elements in the mesh.
* \return Number of global elements in the mesh.
*/
t8_gloidx_t
get_num_global_elements () const
{
return t8_forest_get_global_num_leaf_elements (m_forest);
}

Comment thread
Vyp3er marked this conversation as resolved.
/**
* Getter for the number of ghost elements.
* \return Number of ghost elements in the mesh.
Expand Down
1 change: 1 addition & 0 deletions test/mesh_handle/t8_gtest_compare_handle_to_forest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ TEST (t8_gtest_compare_handle_to_forest, compare_handle_to_forest)

const t8_mesh_handle::mesh<> 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));

Expand Down
1 change: 1 addition & 0 deletions tutorials/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
2 changes: 1 addition & 1 deletion tutorials/general/t8_step1_coarsemesh.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
4 changes: 2 additions & 2 deletions tutorials/general/t8_step2_uniform_forest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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");
Expand Down
161 changes: 161 additions & 0 deletions tutorials/mesh_handle/t8_mesh_step2_uniform_mesh.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
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 <t8.h> /** General t8code header, always include this. */
#include <mesh_handle/mesh.hxx> /** General mesh header, always needed for mesh_handle code. */
#include <t8_cmesh/t8_cmesh.h> /** Cmesh definition and basic interface. */
#include <mesh_handle/constructor_wrappers.hxx> /** Wrapper for basic cmesh to mesh_handle conversions. */
#include <mesh_handle/mesh_io.hxx> /** Used to export mesh to vtk files. */
#include <t8_schemes/t8_default/t8_default.hxx> /** Default refinement scheme. */
#include <mesh_handle/concepts.hxx> /** Include this to use c++ concepts related to the mesh handle. This can be used to constraint the template parameters to only allow mesh handle classes. */
#include <memory>

/** Builds cmesh of 2 prisms that build up a unit cube.
* See \ref tutorials/general/t8_step1_coarsemesh.cxx 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 (" [mesh_step2] Constructed coarse mesh with 2 prisms.\n");

return cmesh;
}

/** Build a uniform mesh on a cmesh using the default refinement scheme.
*
* The mesh type is constrained by the \ref t8_mesh_handle::T8MeshType concept,
* which ensures that TMeshClass provides the required mesh handle interface.
*
* \tparam TMeshClass the mesh handle type to construct. It must satisfy the \ref t8_mesh_handle::T8MeshType concept.
* \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.
*/
Comment thread
Vyp3er marked this conversation as resolved.
template <t8_mesh_handle::T8MeshType TMeshClass>
static std::unique_ptr<TMeshClass>
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<TMeshClass> (cmesh, scheme, level, comm);

t8_global_productionf (" [mesh_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 (" [mesh_step2] \n");
t8_global_productionf (" [mesh_step2] Hello, this is step 2 of t8code's mesh handle tutorials.\n");
t8_global_productionf (
" [mesh_step2] In this tutorial we build our first uniform mesh and output it to vtu files.\n");
t8_global_productionf (" [mesh_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 be destroyed automatically at the end of this scope.
* This is only needed because SC_CHECK_MPI checks for leftover references.
* Otherwise, it would be destroyed at the end of the main function.
*/
{
/** Build the uniform mesh using a mesh type that satisfies the T8MeshType concept.
* The mesh class is templated so that further capabilities and features that not needed by default can be added.
* In this case, the default mesh class is sufficient.
*/
using mesh_class = t8_mesh_handle::mesh<>;

auto mesh = t8_step2_build_uniform_mesh<mesh_class> (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 (" [mesh_step2] Created uniform mesh.\n");
t8_global_productionf (" [mesh_step2] Refinement level:\t\t\t%i\n", level);
t8_global_productionf (" [mesh_step2] Local number of elements:\t\t%i\n", local_num_elements);
t8_global_productionf (" [mesh_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 (" [mesh_step2] Wrote mesh to vtu files:\t%s*\n", prefix);

} /** End of Mesh scope. */
t8_global_productionf (" [mesh_step2] Mesh scope ended.\n");

sc_finalize ();

mpiret = sc_MPI_Finalize ();
SC_CHECK_MPI (mpiret);

return 0;
}
Loading