p4est 2020 HCM Summer School: Forest
Author: Carsten Burstedde

We are organizing a `p4est` summer school sponsored by the Hausdorff Center for Mathematics at the University of Bonn, Germany. Please see also the school's home page and application forms.

## 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.
Additional material
  For an example that covers the content of this tutorial see simple2.c.
Next steps (with links?)
  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;
    static void my_quadrant_init (p4est, which_tree, quadrant) {
      ((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,
                           sizeof (my_user_data_t), my_quadrant_init, user_pointer);

`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.