p4est
2.8.7
p4est is a software library for parallel adaptive mesh refinement.
|
An overview of the connectivity structure.
p4est leverages structured octree grids for efficient highly-scalable adaptive mesh refinement (AMR). At the same time p4est enables the user to represent a general and possibly non-squared (2D), non-cubic (3D) domain. This flexibility for the domain choice is achieved by using a forest of quadtrees (2D) or octrees (3D) instead of a single tree. The forest represents a coarse mesh topology where each tree is a logical hypercube. To represent a general domain, we cover the domain with a conforming mesh of (potentially mapped) squares (2D) or cubes (3D). Each square (2D) or cube (3D) represents a quadtree (2D) or octree (3D) root. These trees are connected with respect to their root's topological entities, i.e. in 2D corners and faces and in 3D corners, faces and edges. This coarsest possible mesh is defined as the connectivity of a forest. It can not be changed during a simulation and in particular it can not be coarsened further.
Since the connectivity can not be changed during a simulation it should be designed carefully. A few guidelines (replace cube(s) by square(s) for 2D) are:
We have successfully connected millions of trees. Below 100k, there is no need to even think about reducing their number if the procedure would not be obvious.
The easiest way to create a connectivity is to use one of the predefined functions in p4est_connectivity.h (2D) or p8est_connectivity.h (3D). These predefined functions p4est_connectivity_new_*
(2D) and p8est_connectivity_new_*
(3D) implement some basic connectivities like a unit square (p4est_connectivity_new_unitsquare) or a unit cube (p8est_connectivity_new_unitcube) but also more advanced connectivities like an icosahedron (p4est_connectivity_new_icosahedron) or a 3D torus (p8est_connectivity_new_torus).
Moreover, we want to point to the possibility of connecting topological entities inside a single tree. This means that one can create periodic connectivities, e.g. p4est_connectivity_new_periodic (2D) and p8est_connectivity_new_periodic (3D).
We also offer the functions p4est_connectivity_read_inp (2D) and p8est_connectivity_read_inp (3D) to read a connectivity from an Abaqus .inp
file.
The user can also create a new connectivity by allocating and populating the connectivity structure using p4est_connectivity_new_copy (2D) or p8est_connectivity_new_copy (3D). See the next section and p4est_connectivity_t (2D) or p8est_connectivity_t (3D) for more information on the elements of the connectivity structure.
Since the connectivity must be identical on every process, it is sufficient to generate it once on every shared memory node and share its contents using MPI3 functionality. We provide the function p4est_connectivity_share for this purpose. Prior to calling it, the user may make the connectivity available on every first rank of every shared-memory node, for example using p4est_connectivity_bcast over a communicator that contains these first ranks only.
For convenience, we integrate this approach in p4est_connectivity_mission. It requires to input a connectivity on just the root of the world communicatior and then distributes it using MPI-3 shared memory. This function uses safe fallbacks when MPI-3 is not detected on configuration, or when we compile entirely without MPI.
The connectivity data structure (cf. p4est_connectivity_t (2D), p8est_connectivity_t (3D)) is a public struct with documented entries and it is independent of the MPI rank and hence must be the same on all MPI ranks.
You may build any numbers of forests with the same connectivity object, but the connectivity object must be destroyed only after the last of the forests has been freed and the connectivity object must definitely be destroyed (p4est_connectivity_destroy (2D), p8est_connectivity_destroy (3D)).
The connectivity data structure consists of arrays and counts of different entities. In particular, the connectivity data structure contains the number of trees num_trees and the number of vertices num_vertices. The vertices are stored in the double array vertices. It is important to note that the vertices are always points in the three-dimensional space; even in the 2D connectivity. The vertices are used to embed each tree into the three-dimensional space in the array tree_to_vertex. This embedding is for example used for visualization (cf. p4est_vtk.h (2D), p8est_vtk.h (3D)) or a custom transformation from tree-local coordinates to a user-defined physical space (cf. p4est_geometry_new_connectivity (2D), p8est_geometry_new_connectivity (3D)). The remaining counts in the connectivity structure are the number of different topological entities that help to define the coarse mesh: The num_corners is the number of corners that are not part of a face neighborhood (or edge neighborhood in 3D) but connect trees. Similarly, we have num_edges in addition in 3D – storing the number of edges that are not part of a face neighborhood but connect trees. Then arrays like tree_to_tree and tree_to_face encode the inter-tree connectivity information. For more information of the encoding in these arrays and the other arrays see the documentation of p4est_connectivity_t (2D) and p8est_connectivity_t (3D) and the documentation of the respective elements of these two structures.
For information on further connectivity functionalities we refer to p4est_connectivity.h (2D) and p8est_connectivity.h (3D). In particular, you can find there functions for writing and reading a connectivity in a p4est internal file format. There are also functions to manipulate connectivity objects, e.g. one can use METIS – if it is available – to reorder a connectivity.
An example of using various predefined connectivities can be found in simple/simple2.c (2D) and simple/simple3.c (3D).