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
5 changes: 4 additions & 1 deletion tutorials/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,8 @@ copy_tutorial_file (features/t8_features_curved_meshes_generate_cmesh_tet.geo)
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_step3_adapt_mesh SOURCES mesh_handle/t8_mesh_step3_adapt_mesh.cxx )
add_mesh_handle_tutorial( NAME t8_mesh_step4_partition_balance_ghost SOURCES mesh_handle/t8_mesh_step4_partition_balance_ghost.cxx )
add_mesh_handle_tutorial( NAME t8_mesh_step5_element_data SOURCES mesh_handle/t8_mesh_step5_element_data.cxx )
endif()

117 changes: 117 additions & 0 deletions tutorials/mesh_handle/t8_mesh_step3_adapt_mesh.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
This file is part of t8code.
Comment thread
Vyp3er marked this conversation as resolved.
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_step3_adapt_mesh.cxx
* This is step3 of the t8code mesh handle tutorials.
* Therefore, this is the same as general/t8_step3_adapt_forest.cxx but using the mesh handle interface instead of the forest
* interface.
* After generating a coarse mesh (step1) and building a uniform mesh
* on it (step2), we will now adapt (= refine and coarsen) the mesh
* according to our own criterion.
*
* The geometry (coarse mesh) is again a cube, this time modelled with
* 6 tetrahedra, 6 prisms and 4 cubes.
* We refine an element if its midpoint is within a sphere of given radius
* around the point (0.5, 0.5, 1) and we coarsen outside of a given radius.
* We will use non-recursive refinement, that means that the refinement level
* of any element will change by at most +-1.
*/

#include <t8.h> /** General t8code header. Always include this. */
#include <mesh_handle/mesh.hxx> /** General mesh header. Always needed for mesh_handle code. */
#include <mesh_handle/competence_pack.hxx> /** Competence pack for basic mesh_handle features. Look into tutorials/mesh_handle/t8_mesh_competences for more information. */
#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 <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. */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This line is too long and i think you can remove some line breaks in the file descriptions . If you want to i can show you how to add a helper for this in vscode :)

#include "t8_mesh_tutorials_common.hxx" /** Adaption function definition used for this tutorial. */
#include <memory>

/** Build our adapted mesh by transferring the adaption parameters and adapting once with our \ref adapt_callback function.
Comment thread
Vyp3er marked this conversation as resolved.
* \tparam TMeshClass The mesh handle class.
* \param sc_MPI_Comm The MPI communicator.
* \param level The initial uniform refinement level.
* \returns Unique pointer to the adapted mesh.
*/
template <t8_mesh_handle::T8MeshType TMeshClass>
std::unique_ptr<TMeshClass>
build_mesh (sc_MPI_Comm comm, int level)
{
/* Generate a hybrid hypercube, made out of cubes, prisms etc. */
auto mesh = t8_mesh_handle::handle_hypercube_hybrid_uniform_default<TMeshClass> (level, comm);
/* Defining the adaption parameters. */
adapt_data adapt_params = { { 0.5, 0.5, 1.0 }, 0.2, 0.4 };
/** Adapting once using our adapt callback.
* set_adapt() only records how the mesh should be changed, it does not modify anything yet.
* commit() is the function that actually builds the new, adapted mesh from these settings.
* This "configure, then commit" split let's t8code carry out several mesh operations together in one efficient pass, rather than one at a time.
*/
mesh->set_adapt (
TMeshClass::template mesh_adapt_callback_wrapper<adapt_data> (adapt_callback_sphere<TMeshClass>, adapt_params));
mesh->commit ();
Comment thread
Vyp3er marked this conversation as resolved.
return mesh;
}

/** Entry point of the program. */
int
main (int argc, char **argv)
{
/* 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);
/* We will use MPI_COMM_WORLD as a communicator. */
sc_MPI_Comm comm = sc_MPI_COMM_WORLD;

/* Print a starting message. */
t8_global_productionf (" [mesh_step3] \n");
t8_global_productionf (
" [mesh_step3] Hello, this is the mesh adaptation tutorial of t8code using the mesh handle.\n");
t8_global_productionf (
" [mesh_step3] In this tutorial we will adapt a mesh in a spherical shape around a given point "
"and write the adapted mesh to a vtu file.\n");
t8_global_productionf (" [mesh_step3] \n");

using mesh_type = t8_mesh_handle::mesh<>;

t8_global_productionf (" [mesh_step3] \n");
t8_global_productionf (" [mesh_step3] Creating an adapted mesh.\n");
t8_global_productionf (" [mesh_step3] \n");
/* The initial uniform refinement level. */
int uniform_level = 3;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
int uniform_level = 3;
const int uniform_level = 3;

Best way is to mark everything const if possible :)

/* Building the mesh. */
{ /** Scope to ensure mesh is deleted properly. */
auto mesh = build_mesh<mesh_type> (comm, uniform_level);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I noticed that in the general tutorial, the uniform mesh is also stored as a vtk such that you can compare them. Why did you decided against this here?

/* Write the mesh to a vtu file. */
t8_global_productionf (" [mesh_step3] \n");
t8_global_productionf (" [mesh_step3] Writing adapted mesh to vtu file: step3_adapted_mesh.vtu\n");
t8_global_productionf (" [mesh_step3] \n");
t8_mesh_handle::write_mesh_to_vtk (*mesh, "step3_adapted_mesh.vtu");
}
sc_finalize ();
mpiret = sc_MPI_Finalize ();
SC_CHECK_MPI (mpiret);
return 0;
}
Comment thread
Vyp3er marked this conversation as resolved.
217 changes: 217 additions & 0 deletions tutorials/mesh_handle/t8_mesh_step4_partition_balance_ghost.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
/*
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_element_data.cxx

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please adapt :)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could you please adapt this?

* This is step4 of the t8code mesh handle tutorials.
* Therefore, this is the same as general/t8_step4_partition_balance_ghost.cxx but using the mesh handle interface instead of the forest
* interface.
* After generating a coarse mesh (step1), building a uniform mesh
* on it (step2) and adapting this mesh (step3)
* we will now learn how to control the mesh creation in more detail,
* how to partition and balance a mesh and how to generate a layer of ghost elements.
Comment on lines +29 to +30

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
* we will now learn how to control the mesh creation in more detail,
* how to partition and balance a mesh and how to generate a layer of ghost elements.
* we will now learn how to partition and balance a mesh and how to generate a layer of ghost elements.

*/

#include <t8.h> /** General t8code header. Always include this. */
#include <mesh_handle/mesh.hxx> /** General mesh header. Always needed for mesh_handle code. */
#include <mesh_handle/mesh_io.hxx> /** Used to export mesh to vtk files. */
#include <mesh_handle/constructor_wrappers.hxx> /** Wrapper for basic cmesh to mesh_handle conversions. */
#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 <t8_types/t8_vec.hxx> /** t8 vector dataclass. */
#include "t8_mesh_tutorials_common.hxx" /** Default adaption function. */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Also not "default" here. Just use the description that you provided in step 3 pls

#include <memory>
#include <iostream>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
#include <iostream>


using mesh_type = t8_mesh_handle::
mesh<>; /**< Mesh class used in this tutorial. We define it globally to get rid of the function templates to simplify the code. */

/** Helper function to print the total number of elements in the mesh after each step.
* \param mesh The mesh handle to get the number of elements from.
* \param stage The stage of the mesh (e.g. "Initial mesh", "Adapted mesh", etc.) to print in the output.
* \param comm The MPI communicator to use for the reduction and printing.
*/
void
print_mesh_stats (const std::unique_ptr<mesh_type>& mesh, const char* stage, sc_MPI_Comm comm)
{
int local_elements = mesh->get_num_local_elements ();
int global_elements = 0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think i already wrote is somewhere but please use your new mesh handle function here (already merged)

MPI_Allreduce (&local_elements, &global_elements, 1, MPI_INT, MPI_SUM, comm);

t8_global_productionf (" [mesh_step4] === %s === \n", stage);
t8_global_productionf (" [mesh_step4] Total elements: %i \n", global_elements);
}

/** Helper function to create an adapted mesh from an initial mesh.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Now you just adapt a mesh and dont create a new adapted mesh. Please change this

* \param mesh The initial mesh to adapt.
* \param adapt_params The adaptation parameters to use for the adaptation.
*/
void
create_adapted_mesh (std::unique_ptr<mesh_type>& mesh, const adapt_data& adapt_params)
{
/* Adapting the mesh once with our adapt_callback_sphere function from step 3 and the adapt_params. Both can be found in the file \ref t8_mesh_tutorials_common.hxx. */
mesh->set_adapt (
mesh_type::template mesh_adapt_callback_wrapper<adapt_data> (&adapt_callback_sphere<mesh_type>, adapt_params));
/* Committing the adapted mesh. */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not really. The mesh gets adapted at the commit step, so its not "the adapted mesh"

mesh->commit ();
}

/** Helper function to create a partitioned and balanced mesh from an initial mesh.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same as above

* \param mesh The initial mesh to adapt.
*/
void
create_partitioned_balanced_mesh (const std::unique_ptr<mesh_type>& mesh)
{
/* Calculate partition information.*/

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Maybe it is good if you have a look at the documentation of these functions and of commit. You do not calculate something, just setting the flags such that the mesh is partitioned at commit call. We can also talk about the commit procedure if you want to, just ask.

mesh->set_partition ();

/* Calculate balancing information. */
mesh->set_balance ();

/* Committing the mesh --> modifying the mesh according to the precalculated information. */
mesh->commit ();
}

/** Helper function to create a mesh with ghosts from an initial mesh.
* \param mesh The initial mesh to adapt.
*/
void
create_ghost_mesh (const std::unique_ptr<mesh_type>& mesh)
{
/* Creating the ghost layers. */
mesh->set_ghost ();

/* Committing the ghost mesh. */
mesh->commit ();
}

/** Entry point of the program. */
int
main (int argc, char** argv)
{

/* 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);
/* We will use MPI_COMM_WORLD as a communicator. */
sc_MPI_Comm comm = sc_MPI_COMM_WORLD;

/* Print a starting message. */
t8_global_productionf (" [mesh_step4] \n");
t8_global_productionf (" [mesh_step4] Hello, this is the mesh adaptation example of t8code using the mesh handle.\n");
t8_global_productionf (" [mesh_step4] In this example we will create a mesh, adapt, partition, balance "
"and create a ghost layer on it. \n");
t8_global_productionf (" [mesh_step4] \n");

/* The initial uniform refinement level. */
int uniform_level = 3;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
int uniform_level = 3;
const int uniform_level = 3;


/* Parameters for the adaption step. */
struct adapt_data adapt_params = { { 0.5, 0.5, 1.0 }, 0.2, 0.4 };

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
struct adapt_data adapt_params = { { 0.5, 0.5, 1.0 }, 0.2, 0.4 };
adapt_data adapt_params = { { 0.5, 0.5, 1.0 }, 0.2, 0.4 };

The struct is old c style


/**
* INITIAL MESH
*/

t8_global_productionf (" [mesh_step4] \n");
t8_global_productionf (" [mesh_step4] Creating initial mesh.\n");
t8_global_productionf (" [mesh_step4] \n");
{ /** Mesh scope begin. */
/* Creating the initial mesh with uniform refinement. */
auto mesh = t8_mesh_handle::handle_hypercube_hybrid_uniform_default<mesh_type> (uniform_level, comm);

/* Printing the mesh information. */
print_mesh_stats (mesh, "Initial mesh", comm);

/* Writing the mesh to vtu and pvtu files, using the extended version of the function to ensure additional data like ghost elements, treeid etc. to be written into the files. */
t8_mesh_handle::write_mesh_to_vtk_ext (*mesh, "initial_mesh.vtu", 0, nullptr, true, true, true, true, true, false,
false);

/**
* ADAPTED MESH
*/

t8_global_productionf (" [mesh_step4] \n");
t8_global_productionf (" [mesh_step4] Creating adapted mesh.\n");
t8_global_productionf (" [mesh_step4] \n");

/** Call adaption helper function. */
create_adapted_mesh (mesh, adapt_params);

/* Printing the mesh information. */
print_mesh_stats (mesh, "Adapted mesh", comm);

/* Writing the mesh to vtu and pvtu files using the extended version of the function. */
t8_mesh_handle::write_mesh_to_vtk_ext (*mesh, "adapted_mesh.vtu", 0, nullptr, true, true, true, true, true, false,
false);

/**
* PARTITIONED, BALANCED MESH
*/

t8_global_productionf (" [mesh_step4] \n");
t8_global_productionf (" [mesh_step4] Creating partitioned and balanced mesh.\n");
t8_global_productionf (" [mesh_step4] \n");

/** Adapting the mesh from above a second time to see a difference when balancing. */
create_adapted_mesh (mesh, adapt_params);

/** Call partitioning and balancing helper function. */
create_partitioned_balanced_mesh (mesh);

/* Printing the mesh information. */
print_mesh_stats (mesh, "Partitioned and Balanced mesh", comm);

/* Writing the mesh to vtu and pvtu files using the extended version of the function. */
t8_mesh_handle::write_mesh_to_vtk_ext (*mesh, "partition_balance_mesh.vtu", 0, nullptr, true, true, true, true,
true, false, false);

/**
* GHOST MESH

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

At comments you have to pay attention to the indention please,this is not checked by the ci and not corrected by the indent script

*/

t8_global_productionf (" [mesh_step4] \n");
t8_global_productionf (" [mesh_step4] Creating ghost layer for mesh.\n");
t8_global_productionf (" [mesh_step4] \n");

/** Call ghost helper function. */
create_ghost_mesh (mesh);

/* Printing the mesh information. */
print_mesh_stats (mesh, "Ghost mesh", comm);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Maybe it would be nice to print also the number of ghost elements here (maybe only for one process or so).


/* Writing the mesh to vtu and pvtu files using the extended version of the function. */
t8_mesh_handle::write_mesh_to_vtk_ext (*mesh, "ghost_mesh.vtu", 0, nullptr, true, true, true, true, true, false,
false);

Comment thread
Vyp3er marked this conversation as resolved.
t8_global_productionf (" [mesh_step4] \n");
t8_global_productionf (" [mesh_step4] Finished all steps successfully.\n");
t8_global_productionf (" [mesh_step4] \n");
} /** Mesh scope end. */
sc_finalize ();
mpiret = sc_MPI_Finalize ();
SC_CHECK_MPI (mpiret);
return 0;
}
Loading