-
Notifications
You must be signed in to change notification settings - Fork 52
Step 1 Creating a coarse mesh
In this example we will build our first coarse mesh and write it to .vtu
files in order to visualize it with Paraview
.
You will find the code to this example in tutorials/general/step1_coarsemesh.c
and it creates the executable tutorials/general/step1_coarsemesh
.
In order to build an adaptive mesh t8code
actually manages two meshes. The coarse mesh (cmesh
) and the forest mesh (forest
).
The coarse mesh is the initial input that describes the geometrical and topological properties of the meshed domain.
It describes the coarsest possible mesh.
It is a classical unstructured mesh as it would be generated by a standard mesh generator such as gmsh
.
It can be as simple as a single hexahedron specifying a cube domain, or as complex as billions of tetrahedra, prisms, pyramids and hexahedra
describing an airplane geometry.
We view each element of the coarse mesh as the root of recursive refinement. The forest
is the collection of these refined
elements. Due to the tree-like nature of recursive refinement, we call the elements of the cmesh
trees.
The cmesh
will (usually) not change during a computation.
A cmesh
can be partitioned among the processes or each process can hold a copy of the complete cmesh
.
These two pictures illustrate the coarse and the forest mesh for a square shaped domain with a circular hole. Left: The coarse mesh that describes the geometry and tree shapes. Right: The forest mesh. Each tree in the coarse mesh is refined to a certain refinement level. In this example the refinement criterion was chosen to refine elements that are close to the domain boundary. The colors represent a distribution of the elements among 4 MPI processes.
t8code
offers different ways to create coarse meshes, which can be found in t8_cmesh.h
The most important are
- reading files from mesh generators
gmsh
,Tetgen
orTRIANGLE
- Building a
cmesh
by hand by specifying its trees and neighbor connections - Using one of the provided
t8_cmesh_new_*
functions
In this example we use t8_cmesh_new_hypercube
to create a cmesh
that models a cube domain.
cmesh = t8_cmesh_new_hypercube (T8_ECLASS_TET, comm, 0, 0, 0);
It offers various parameters that control what kind of cube is created and how it is meshed.
It also gets an sc_MPI_Comm
parameter to specify on which processes this cmesh
should live (usually sc_MPI_COMM_WORLD).
The first parameter T8_ECLASS_TET
specifies the kind of geometric trees to use to model the cube and also
changes the dimension.
t8code
supports eight different basic tree shapes for the cmesh
, see also t8_eclass.h
:
element shape | description | Number of elements in cube |
---|---|---|
T8_ECLASS_VERTEX | 0D points | 1 |
T8_ECLASS_LINE | 1D lines | 1 |
T8_ECLASS_QUAD | 2D quadrilaterals | 1 |
T8_ECLASS_TRIANGLE | 2D triangles | 2 |
T8_ECLASS_HEX | 3D hexahedra | 1 |
T8_ECLASS_TET | 3D tetrahedra | 6 |
T8_ECLASS_PRISM | 3D prisms | 2 |
T8_ECLASS_PYRAMID | 3D pyramids | 3 |
Each of these can be chosen as first parameter for t8_cmesh_new_hypercube
and will create a [0,1]^d
cube of the specified dimension
and tree type.
The other parameters are flags that control whether the cmesh
should be created on root and broadcasted to the other processes, whether it should be partitioned among the processes, and whether it should have periodic boundaries.
In t8_cmesh.h
you find various functions to gather information about our coarse mesh.
We now want to get the global number of trees (6) and the number of process local trees (depends on the number of processes and whether the coarse mesh is partitioned or not, ca. 6/#ranks) and print them.
To do this we use the two function calls:
t8_locidx_t local_num_trees = t8_cmesh_get_num_local_trees (cmesh);
t8_gloidx_t global_num_trees = t8_cmesh_get_num_trees (cmesh);
which we then print with:
t8_global_productionf (" [step2] Local number of trees:\t%i\n", local_num_trees);
t8_global_productionf (" [step2] Global number of trees:\t%li\n", global_num_trees);
Note that due to using t8_global_productionf
opposed to t8_productionf
only rank 0 will print its local number of trees.
If you use t8_productionf
instead, you can compare the local tree numbers for different processes.
Also note that since in this example the coarse mesh is not partitioned, each process has a complete copy of the coarse mesh and hence each process has 6 local and 6 global trees.
Side note Index types:
To index t8code
trees (or similar entities such as elements or ghosts) we have two integer types that are
used:
t8_locidx_t is used for everything that is process local, such as local number of elements or trees.
t8_gloidx_t is used for everything that is global across all processes, such as global number of elements or trees.
There is also the third type t8_linearidx_t that is explicitly used to store space-filling curve indices.
After creating the cmesh
we can write it out to .vtu
files in order to view it in Paraview
.
We do this with the function call
t8_cmesh_vtk_write_file (cmesh, prefix, 1.0);
which will create the files prefix.pvtu
and prefix_0000.vtu
. If the cmesh
was partitioned then it would create one file
prefix_MPIRANK.vtu
for each MPI rank. Since in this example it is not partitioned, we only get the file from the root process with rank 0
.
To view it with Paraview
, open the file prefix.pvtu
. The t8_step1_coarsemesh
example will create the file t8_step1_tetcube.pvtu
.
As we can see our geometry is a three-dimensional cube that consists of six tetrahedral trees.
Installation Guide
Configure Options
Setup t8code on JUWELS and other Slurm based systems
Setup t8code for VTK
General
Step 0 Hello World
Step 1 Creating a coarse mesh
Step 2 Creating a uniform forest
Step 3 Adapting a forest
Step 4 Partition,-Balance,-Ghost
Step 5 Store element data
Step 6 Computing stencils
Step 7 Interpolation
Features
Documentation
Tree Indexing
Element Indexing
Running on JUWELS using Slurm
Overview of the most used API functions
Known issues
Workflow - FreeCAD to t8code
Reproducing Scaling Resluts
Coding Guidelines
Tips
Debugging with gdb
Debugging with valgrind
Test driven development
Testing with GoogleTest
Writing C interface code