Introduction to Fully Threaded Trees

Figure 1

An octree is a data structure in which each cell may have up to eight children cell, corresponding to eight cubic subcells in three dimensions. The corresponding two-dimensional structure is a quadtree. The cells and tree structure of the quadtree are illustrated on Figure 1.

In the fully threaded tree implementation of the octree by Khokhlov the data structure contains, in each cell, a reference to the neighbors of the cell. This speeds up considerably the computation of the addresses of neighbor cells; since otherwise in the worst case scenario finding a neighbor cell implies going all the way up the tree to the root cell and then down again.

FTT library

The files ftt.c and ftt.h form a kind of "ftt library" that is completely independent from the rest of Gerris. The "data" member in FttCell is used so that the logical structure of the quadtree is entirely abstracted from its use in Gerris; i.e. the FTT implementation could be used as-is for an entirely different application requiring an octree.

Description of the FTT interface

At this stage it is important to recall the distinction we made in the previous session between the
public parts of the code and the private parts.
The file ftt.h provides the interfaces for a number of public functions, macros, and structures which are meant to be used elsewhere in the code. At this stage of the analysis of Gerris, we only need to know about the public aspects.

The description should logically involve three or four aspects. The prerequisite is a knowledge of the idea of the Fully Threaded Tree with oriented faces as shown above.
The three other aspects are the descriptions of structures, macros and functions.

This description is available from the Reference Manual. Notice that the manual respects the /*< public >*/ and /*< private >*/ tags: as in our table below, it will only show the public members of the structures.

However, not all the structures and macros have descriptions and other descriptions may not cure the bafflement of us dummies. In the previous section we have given some definitions and comments for some of the functions and macros. Now we try a more systematic approach.

Basic concepts

FttDirection

An orientation is defined in Gerris by the FttDirectionenum. As shown just above, the different directions (FTT_RIGHT, FTT_LEFT,…) are associated with an integer: FTT_RIGHT with 0, FTT_LEFT with 1 and so on. The number of neighbors FTT_NEIGHBORS is thus associated with 4 in 2D and 6 in 3D.

FttCellFace

Figure 2

struct _FttCellFace { FttCell * cell, * neighbor; FttDirection d;};

A face is oriented: it belongs to one FttCell (pointed to by) cell and has another as neighbor in FttDirection d. In other words, a face has an interior and an exterior. There is a corresponding reversed face. As a result the right face of Cell A is not the same object in the program as the left face of Cell B (Figure 2). This is useful for instance when programming the advection scheme when two states (the left and the right state) are present on the same boundary between cells.

_FttOct

This is the structure tag (it is not a type, only a tag) associated with the private members of the struct _FttCell. There is no type FttOct associated to _FttOct. Both facts indicate that the structure FttOct is not meant to be used outside of the ftt library: it is a private part. Other implementations of the library could be possible, not using the _FttOct.

Of course the particular implementation here is important as it allows to find neighbors rapidly.
But we need not know how it is done to use it, we can use it as a black box.

3D case

Introduction to public functions and macros

Here we give some examples of often used functions and their description. Some of the descriptions may be found in the Reference Manual, but at present some other definitions are not there. As we show below in the case of FTT_OPPOSITE_DIRECTION the meaning is however often easy to guess.

FTT_FACE_DIRECT (face)

ftt_face_type(face)

There are three types :

FTT_FINE_FINE when the neighbor is as fine as the cell .

FTT_FINE_COARSE when the neighbor is coarser than the cell

FTT_BOUNDARY when there is no neighbor.

The situation where the neighbor is finer than the cell cannot occur; if there are finer children cells across the face, the neighbor is defined as the contiguous cell at the same level. For instance if a leaf cell A has four neighboring finer leaf cells B, C, D, E the parent B+C+D+E of these four leaf cells is the neighbor of cell A .

FTT_OPPOSITE_DIRECTION(direction)

If you had to guess what FTT_OPPOSITE_DIRECTION does, what would you say? Well if you know that face->d is a direction and you guess that it takes a direction as argument and returns the opposite: left for right, bottom for top etc.… And you are right!

Traversing the tree

An important operation is the traversal of the tree. It allows to perform a sequence of calls of a given function, one call for each cell of a tree.

/** * ftt_cell_traverse: * @root: the root #FttCell of the tree to traverse. * @order: the order in which the cells are visited - %FTT_PRE_ORDER, * %FTT_POST_ORDER. * @flags: which types of children are to be visited. * @max_depth: the maximum depth of the traversal. Cells below this * depth will not be traversed. If @max_depth is -1 all cells in the * tree are visited. * @func: the function to call for each visited #FttCell. * @data: user data to pass to @func. * * Traverses a cell tree starting at the given root #FttCell. Calls * the given function for each cell visited. */void ftt_cell_traverse (FttCell * root, FttTraverseType order, FttTraverseFlags flags, gint max_depth, FttCellTraverseFunc func, gpointer data)

The whole FTT "library"

By now you should be getting and idea of the meaning of the various macros and modules of the FTT. Listed below are all the "public" functions and macros of FTT. You should now do the following exercise. For each item in the list below, either look up its meaning in the Reference Manual , or find the meaning by looking at the source code. In some cases it would be helpful to supplement the comments in the Reference Manual by some additional considerations, add them where necessary.

Not all the comments in Reference Manual can be found in the source code. Some were added by hand. Conversely, not all macros and functions are referenced in the Reference Manual, although some functions that I have not found in the Reference Manual have comment headers in the source code.

The list is rather long. Things can be accelerated by considering that some functions have obvious definitions. If you have a doubt on the operation of a function, you can always return to it later when you encounter it in other parts the code. Moreover, most of the functions not referenced in the Reference Manual are at the beginning of the list.