Skip to content

Step 3 Adapting a Mesh

Vincent Schmitt edited this page Oct 14, 2026 · 3 revisions

Step 3 – Adapting a Mesh with the Mesh Handle

Adaption is the process of refining and coarsening the elements in a mesh according to a given criterion. It is the core idea behind adaptive mesh refinement and thus the first major mesh handle algorithm that we discuss. In this example we describe how to define an adaption criterion function and how to adapt our mesh with it. You find the code to this tutorial in the tutorials/mesh_handle/t8_mesh_step3_adapt_mesh.cxx and it creates the executable tutorials/mesh_handle/ t8_mesh_step3_adapt_mesh. Some functionality is outsourced to tutorials/mesh_handle/t8_mesh_tutorials_common.hxxas we will reuse it in the following tutorials. As in the previous examples (Step 1 and Step 2) we will use a cube geometry for our coarse mesh, but this time modelled as a hybrid mesh with different element types (tetrahedra, prisms and hexahedra). The refinement criterion will be a geometrical one. We will refine elements if they are within a radius of 0.2 of the point (0.5, 0.5, 1) and we will coarsen the elements if they are outside a radius of 0.4. We start with our mesh handle mesh as in step 2 and adapt once, thus refining or coarsening by one level.

The uniform level 3 mesh (left) will get adapted and then also have level 4 and level 2 elements (right). The colors correspond to the refinement levels.

Adapting a Mesh

When adapting a mesh, the user needs to define a suitable adaption criterion in terms of a callback function. t8code will iterate through all elements of our mesh and call the provided callback function once per element. If the return value of the callback is 0 then the element will not change. If the return value is 1 it will be refined, thus replaced with a number of smaller elements, depending on the element type. A family is the set of all smaller elements that could be replaced with one bigger element. If the input element to our callback function is the first element in a family – and all elements of the family are local to our current MPI Process - then the whole family is passed to the callback function. If this function then returns a value of -1, it will specify that the whole family should be coarsened, thus be replaced with a single bigger element. In this case, the callback function will not be called by any other member of the family. If we have an adaption callback adapt_callback_sphere and a mesh object mesh, we can adapt this mesh with

mesh->set_adapt(TMeshClass::template mesh_adapt_callback_wrapper<adapt_data> (adapt_callback_sphere<TMeshClass>, adapt_params));
mesh->commit ();

A key point you must know is how adaption and other mesh-manipulating algorithms are executed in t8code. In the mesh interface, adaptation uses lazy evaluation. This means, the calculation is only flagged until it is explicitly called or needed. You first register your callback using set_adapt(). This merely sets a flag. The actual mesh modification does not happen until you explicitly call commit(). The adaption can be done either with or without user data. Adaption without user data is much simpler. If the goal is to simply refine every element in the mesh that is below refinement level 2, we can do so without passing any external data into the callback. To do this, we simply omit the data template and parameters:

mesh->set_adapt (adapt_callback_level<TMeshClass>);
mesh->commit();

Here, adapt_callback_level is a simple function, that does not use any user data. It could be a simple if-statement like:

template <t8_mesh_handle::T8MeshType TMeshClass>
int
adapt_callback_level(std::span<const typename TMeshClass::element_class> elements)
{
  if (elements[0].get_level() < 2) 
  {
		return 1;
  }
  return 0;
}

The adaption callback function

For all the mesh handle tutorials, we defined one overall adapt_callback_sphere function in the file t8_mesh_tutorials_common.hxx. We will have a look at this exemplary callback such that you learn how to write your own callback. The callback declaration looks like this:

int	adapt_callback_sphere ([[maybe_unused]] const TMeshClass &mesh, std::span<const typename TMeshClass::element_class> elements, const adapt_data &adapt_params)

A callback with adaptation parameter should always look similar to this. This function will be called for each element (or first element of a family) while the mesh gets adapted. Its parameters are:

Parameter Description
mesh The mesh that should be adapted
elements One element or a family of elements to consider for adaptation
adapt_data The user data to be used during the adaptation process

We want to refine an element, or coarsen a family of elements, depending on their distance from a given point. To do this, we retrieve the coordinates of the element’s centroid (or the first element’s centroid in the case of a family) via:

auto element_centroid = elements[0].get_centroid ();

Which stores the coordinates into the variable element_centroid. All we need to do now is to compute the distance between centroid and our point from the adapt_data and depending on the predefined thresholds adapt accordingly. Please note that the midpoint of our “adaption sphere” is also part of the user defined adapt_data. For our example, the struct adapt_data should therefore look like this:

struct adapt_data adapt_params = {
  { 0.5, 0.5, 1.0 },  /* Coordinates of the midpoint of the adaption sphere. */
  0.2, /* Refine if inside this radius. */
  0.4 /* Coarsen if outside this radius. */
};

Finally, we apply our criterion:

double dist = t8_dist<t8_3D_vec, t8_3D_vec> (element_centroid, adapt_data.midpoint);
if (dist < adapt_data.refine_radius) {
   return 1;  // refine
}            //first check if there is a family, and only if yes check if we should coarsen.
else if ((elements.size () > 1) && (dist > adapt_data.coarsen_radius)) {
   return -1;  // coarsen
}
  return 0;  // do nothing

In the end we should get a result, that looks like this:

In this view we cut into the cube and show how the adaptation criterion affects the elements inside.

Clone this wiki locally