p4est 2020 HCM Summer School: Connectivity

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.

The roots of the forest

The mesh topology of p4est is a general forest of octrees. Each octree is a logical hypercube. To represent a general and possibly non-cubic domain \(\Omega\), we begin by covering it with a conforming mesh of (potentially mapped) squares (2D) or cubes (3D). This coarsest possible mesh or connectivity cannot be changed during the simulation. In particular, it cannot be coarsened further. It is thus wise to design it carefully. A few guidelines are:

  1. Use as many cubes as needed to capture the domain's topology (connected components, holes, tunnels, etc.).
  2. Invest some more cubes to achieve an ideally uniform individual aspect ratio of each cube.
  3. Invest some more cubes if the distortion in any single mapped octree appears too large.
  4. Reduce the number of octrees if the coarse mesh must be limited for numerical reasons.

We have successfully connected millions of octrees. Below 100k, there is no need to even think about reducing their number if the procedure would not be obvious. The connectivity is the first data structure that is built in a p4est program. This tutorial covers its definition and ways to construct it.

Required skills
Knowing about the C language's struct and array data types. Optional: using valgrind; using a debugger.
Skills acquired
Creating and destroying p4est connectivity structures. Saving them to a file and loading them later.
Next steps
Construct several connectivities by builtin constructor functions. Construct a connectivity by hard-coding its members yourself. Use each connectivity to construct a coarse p4est and visualize it via the VTK output.

The p4est_connectivity data structure

The convention for the connectivity's members is documented separately for the 2D connectivity and the 3D connectivity. Note that we prefix 2D functions and objects with p4est and their 3D cousins with p8est.

The Moebius strip is an example of a 2D connectivity embedded into 3D space. We construct it from five trees, where an odd number of face connections has a non-standard relative orientation. Note that we do not need to add corner connections to the connectivity data structure for this mesh, since there is no corner connection that is not already a face connection.

The z-order convention for all boundary entities of a mesh hypercube. This picture shows the 3D case; the 2D case is contained in the x-y-plane. When writing all numbers in binary format, each bit corresponds to a coordinate/normal direction. This convention facilitates dimension-independent programming: All entities relevant to 2D are bitwise reductions of 3D entities.

In principle, there is nothing wrong with allocating and populating the connectivity yourself. This is, in fact, a great way to learn the meaning of its members. However, there are other ways, too. The easiest is to look through say the 3D connectivity header and call one of our predefined p8est_connectivity_new_* functions. We also offer a function to read the connectivity from an Abaqus .inp file.

You may build any numbers of forests with the same connectivity object, but please (a) destroy it only after the last of the forests has been freed and (b) definitely destroy it. It is advised to use the valgrind tool to check for proper deallocation.

Exercise C1: On one MPI rank, call p4est_connectivity_save, p4est_connectivity_load and p4est_connectivity_is_equal to verify that the connectivity structure survived the file I/O. Examine its contents with gdb and compare with the documentation block in the header file. Further down in the program, collectively call p4est_connectivity_bcast to replicate the connectivity on all MPI ranks of the world communicator. Destroy the connectivities on all ranks. Use valgrind to make sure no memory is leaked.

Exercise C2: Write a converter to load your favorite conforming hexahedral mesh format from disk and populate a p4est connectivity structure in memory. Use p{4,8}est_connectivity_new to allocate the required memory once the numbers of trees and edge/corner connections have been determined, then hand-code a bunch of loops to fill all data fields with values. Finally, check the object with p{4,8}est_connectivity_is_valid.