# p4est 2020 HCM Summer School: Forest

## Create and manipulate a forest of octrees

p4est represents a mesh topology as a forest of octrees. This forest can be created by p4est given a connectivity. In this tutorial, we talk about the typical workflow in p4est to create and manipulate a forest of quadtrees (2D) or octrees (3D) to represent a mesh topology.

Required skills
Build, connectivity and optional the VTK graphics tutorial.
Skills acquired
Create a forest of quadtrees and change the refinement structure of the created forest.
For an example that covers the content of this tutorial see simple2.c.
Reference to more advanced tutorials when they exist.

### Create a forest of octrees

A fundamental step of a typical workflow with p4est is to create a forest of octrees or quadtrees. The p4est libary offers the functions p4est_new and p4est_new_ext (a version with more parameters) to create such a forest.

typedef my_user_data {
int foo;
} my_user_data_t;
((my_user_data_t *) quadrant->p.user_data)->foo = *(int *) p4est->user_pointer;
}
static int foo = 17489;
void *user_pointer = &foo;
p4est = p4est_new_ext (mpicomm, connectivity, 0, level, 1,


mpicomm is an MPI communicator (see the example simple for a usage example). The highest occurring level of refinement is specified. If it is zero or negative, there will be no refinement beyond the coarse mesh connectivity at this point. We provide an optional callback mechanism to initialize the user data that we allocate inside any forest leaf. The user_pointer is assigned to the member of the same name in the p4est created (before the init callback function is called the first time). This is a way to keep application state referenced in a p4est object. For more details see p4est.h and p4est_extended.h (as always, the 3D equivalents are prefixed with p8est).

Exercise F1: Choose in p4est_connectivity.h a connectivity that you like and create a forest of quadtrees.

### Manipulate the refinement structure and the partition

The hypercubic elements for the dimensions two and three are called quadrants (the code uses this term also for three dimensional octants). In p4est.h the struct p4est_quadrant is declared and documented.

Our next step in the workflow is to manipulate the refinement structure. The p4est libary offers the following functions to manipulate the forest of quadtrees (2D) or octrees (3D). They are collective over the MPI communicator passed to p4est_new.

p4est_refine
Refinement of specific hypercubes given a refinement criterion, i.e. a user-defined callback function. While it is possible (and fun) to turn on recursive refinement, in practice we set it to non-recursive and loop around the function. This has the advantage that we can repartition in parallel after every iteration.
p4est_coarsen
Coarsen a family of hypercubes given a coarsening criterion, i.e. a user-defined callback function.
p4est_balance
This function ensures a 2:1 balance of the size differences of neigboring elements in a forest by refining quadrants. This is accomplished by adding some more refinement where needed.
p4est_partition
Partition the forest in parallel, equally or according to a given user-defined weight per quadrant.

Exercise F2: Use p4est_refine in a loop to refine at the boundary (choose a boundary thickness) of a circle until the quadrants there reach the refinement level six, and then redistribute the quadrants between the processes using p4est_partition. Verify your program using the VTK output.

Exercise F3: Coarsen all families of quadrants that have a level greater than four and call p4est_balance on the forest. In parallel, examine the difference between standard partition and partition_ext (p4est, 1, NULL). Verify your program using the VTK output.

Exercise F4: Formulate a weight function for p4est_partition_ext. Tweak it in such a way that you can have from 0 to 15 elements on process zero chosen by command line argument, and the rest of them partitioned evenly acress the other processes.