# treelmesh_module Module

TREe based ELemental Mesh module, providing the definition and methods to act on a octree based mesh.

The mesh may either be externally generated by seeder or some simple mesh configurations can also be created internally. In case of an external mesh from seeder, the directory containing the mesh needs to be provided in the configuration:

  mesh = '/path/to/mesh/'


Note that the string provided here is used as a prefix. Thus, if the mesh is in a directory it needs to end in a path seperator. The default is 'mesh/', which results in the application to look for the mesh in the mesh subdirectory in the working directory of the application.

Internal meshes are defined in a table, where the first option describes which of the predefined meshes is to be generated, then there needs to be a definition of the universe (or root) cube within which the octree lives. This is given by an origin and then the length by which it extends along each axis. Further options may be required by the respective predefined mesh types. An example for a fully periodic uniform cubical mesh:

  mesh = {
predefined = 'cube',
origin = {0., 0., 0.},
length = 10.,
refinementLevel = 4
}


The following predefined meshes are available:

• 'cube' create a fully periodic cube without boundary conditions and uniform element sizes by refining the root element (universe). For this kind of mesh you need to provide an refinementLevel which defines how often the encompassing cube should be bisected in each dimension leading to meshes with 8^refinementLevel elements.
• 'slice' create a slice of the fully periodic cube with uniform elements. For the slice you need to provide the refinementLevel, as for the cube. The resulting mesh will consist of 4^refinementLevel elements.
• 'line' creates a periodic line. For this kind of mesh it is possible to specify either an refinementLevel to create meshes with 2^refinementLevel elements, or the number of elements in the mesh by setting element_count.
• 'line_bounded' create a line with boundary conditions in west (on the left) and east (on the right). For this mesh the length needs to be defined by element_count.

The mesh is stored in treelmesh_type. The definition is designed to be used for parallel executions. It includes a reference to tem_global_type and the number of elements, which were loaded on the local partition, as well as the first and last tree ID of each partition in the current communicator. This enables the determination of any tree ID's position among the processes, independent of their actual existence. This is important to identify the location of neighbor elements when creating connectivity lists for the linearized element lists locally on each process within the solvers.

## Derived Types

### type, public :: treelmesh_type

declaration of the overall mesh on the local partition

#### Components

TypeVisibilityAttributesNameInitial
type(tem_global_type), private :: global

This entry provides some global informations on the mesh, which is needed across all partitions.

integer, private :: nElems
integer(kind=long_k), private :: elemOffset
integer(kind=long_k), private, allocatable:: Part_First(:)

List of treeIDs of the first element on each partition, has a length of global%nParts

integer(kind=long_k), private, allocatable:: Part_Last(:)

List of treeIDs of the last element on each partition, has a length of global%nParts

integer(kind=long_k), private, allocatable:: treeID(:)

The treeIDs of each element (the array has a length of nElems) these IDs identify the element in the complete mesh, with a breadth-first numbering scheme. Allowing easy computation of parents and children. [treeid] \ref treeID

integer(kind=long_k), private, allocatable:: ElemPropertyBits(:)

Bit field of element properties for each element (the array has a length of nElems), each bit in the 8 byte integer indicates the presence or absence of a given property, which are further described in the Property component.

type(tem_property_type), private, pointer:: Property(:)=> null()

declaration of additional elemental properties, the array has a length of global%nProperties, each property provides a list of local element indices of elements with this property.

type(tem_path_type), private, allocatable:: pathList(:)

Path for all elements in the treeID array

character(len=pathLen), private :: weights_file =''

Name of the file that contains weight information for each element to allow load balancing. If empty string, balancing will be deactivated.

character(len=pathLen), private :: write_weights

File to write weights to after simulation. Defaults to the same name as weights_file, if you do not want to have the input file overwritten, you can provide a different file to write to by setting write_weights accordingly in the configuration.

real(kind=rk), private :: levelWeight(globalMaxLevels)

Level weights as provided by the solver.

## Functions

### private function tem_CoordOf_2d_Id(Id2d, level) result(coord)

#### Arguments

TypeIntentOptionalAttributesName
integer(kind=long_k), intent(in) :: Id2d

input element ID

integer, intent(in) :: level

#### Return Value integer(4)

coordinate of element return value

## Subroutines

### public subroutine load_tem(me, conf, myPart, nParts, comm, levelWeight, meshDir, parent)

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(out) :: me

Structure to load the mesh to

type(flu_State) :: conf

Directory containing the mesh informations

integer, intent(in) :: myPart

Partition to use on the calling process (= MPI Rank in comm)

integer, intent(in) :: nParts

Number of partitions, the mesh is partitioned into (= Number of MPI processes in comm).

integer, intent(in) :: comm

MPI Communicator to use now defaults to the one given in the tree%global%comm

real(kind=rk), intent(in), optional :: levelWeight(globalMaxLevels)

Balancing weight for elements on different levels. If these weights are present, the mesh is partitioned initially according to the given weights. This can not be combined with given offsets. If offset is also provided they will overwrite the levelWeight distribution.

character(len=*), intent(out), optional :: meshDir

output Mesh directory name

integer, intent(in), optional :: parent

optional parent handle

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(inout) :: me

Structure to load the mesh to

### public subroutine free_treelmesh(me)

Completely free the memory of the treelmesh again.

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(inout) :: me

Structure to free

### public subroutine tem_load_internal(me, conf, thandle, myPart, nParts, comm)

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(out) :: me

Structure to load the mesh to

type(flu_State) :: conf

Directory containing the mesh informations

integer, intent(in) :: thandle

Handle for the table to read the description of the mesh from.

integer, intent(in) :: myPart

Partition to use on the calling process (= MPI Rank in comm)

integer, intent(in) :: nParts

Number of partitions, the mesh is partitioned into (= Number of MPI processes in comm).

integer, intent(in) :: comm

MPI Communicator to use

This subroutine reads a mesh in treelm format from disk at the specified directory name.

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(inout) :: me

Structure to load the mesh to

integer, intent(in) :: nParts

Directory containing the mesh informations Partition to use on the calling process (= MPI Rank in comm) Number of partitions, the mesh is partitioned into (= Number of MPI processes in comm).

### public subroutine dump_treelmesh(me, root_only)

Write a given mesh to disk. it is stored to the directory given in the tem_global_type.

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(inout) :: me

Mesh to dump to disk

logical, intent(in), optional :: root_only

root dump global mesh when true and all process dump its own mesh when false

### public subroutine generate_treelm_cube(me, origin, length, level, myPart, nParts, comm)

Generate a predefined cube

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(out) :: me

Mesh to generate

real(kind=rk), intent(in) :: origin(3)

Corner of the cube

real(kind=rk), intent(in) :: length

Length of cube

integer, intent(in) :: level

Resolution level

integer, intent(in) :: myPart

Partition of the caller (starts with 0)

integer, intent(in) :: nParts

Number of partitions

integer, intent(in) :: comm

communicator to be used

### public subroutine treelmesh_fromList(me, tIDlist, comm, dirname)

This subroutine creates a simple mesh based on a treeID list requires the setting of me%global before hand Works on the communicator specified in me%global%comm

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(inout) :: me

Structure to load the mesh to

integer(kind=long_k), intent(in) :: tIDlist(:)

treeID list to generate the global list in the mesh from

integer, intent(in), optional :: comm

MPI Communicator to use, defaults to the one in me%global%comm if not specified

character(len=*), intent(in), optional :: dirname

Directory to store the mesh in. Is taken to be me%global%dirname if not specified

write mesh information

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(in) :: me

fluid tree from mesh

### public subroutine tem_load_weights(me, weights, success)

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(in) :: me
real(kind=rk), intent(out) :: weights(me%nElems)
logical, intent(out) :: success

### public subroutine tem_dump_weights(me, filename, weights)

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(in) :: me
character(len=*), intent(in) :: filename

Weights file name

real(kind=rk), intent(in) :: weights(me%nElems)

### public subroutine exchange_elements(me, sparta)

Exchange mesh elements with other process The following data within treelmesh_type is updated in this routine: treeID, ElemPropertyBits, Part_First, Part_Last Data pathList is deallocated.

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(inout) :: me

Tree Mesh type nElems and offset should be ready before this routine

type(tem_sparta_type), intent(in) :: sparta

How many elements to exchange with other processes

### private subroutine generate_treelm_slice(me, origin, length, level, myPart, nParts, comm)

Generate a predefined slice

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(out) :: me

Mesh to generate

real(kind=rk), intent(in) :: origin(3)

Corner of the cube

real(kind=rk), intent(in) :: length

Length of cube

integer, intent(in) :: level

Resolution level

integer, intent(in) :: myPart

Partition of the caller (starts with 0)

integer, intent(in) :: nParts

Number of partitions

integer, intent(in) :: comm

communicator to be used

### private subroutine generate_treelm_line(me, origin, length, level, myPart, nParts, comm)

Generate a predefined line

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(out) :: me

Mesh to generate

real(kind=rk), intent(in) :: origin(3)

Corner of the cube

real(kind=rk), intent(in) :: length

Length of cube

integer, intent(in) :: level

Resolution level

integer, intent(in) :: myPart

Partition of the caller (starts with 0)

integer, intent(in) :: nParts

Number of partitions

integer, intent(in) :: comm

communicator to be used

### private subroutine generate_treelm_elements(me, origin, length, elementcount, myPart, nParts, comm, predefined, bclabel)

Generate a predefined line with a given number of elements

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(out) :: me

Mesh to generate

real(kind=rk), intent(in) :: origin(3)

Corner of the cube

real(kind=rk), intent(in) :: length

Length of cube

integer, intent(in) :: elementcount

Number of elements in the line

integer, intent(in) :: myPart

Partition of the caller (starts with 0)

integer, intent(in) :: nParts

Number of partitions

integer, intent(in) :: comm

communicator to be used

character(len=*), intent(in) :: predefined

Label describing the internal mesh.

character(len=*), intent(in) :: bclabel

Label describing the boundary conditions to set for this mesh.

### private subroutine generate_treelm_single(me, origin, length, myPart, nParts, comm)

Generate a predefined single element

#### Arguments

TypeIntentOptionalAttributesName
type(treelmesh_type), intent(out) :: me

Mesh to generate

real(kind=rk), intent(in) :: origin(3)

Corner of the cube

real(kind=rk), intent(in) :: length

Length of cube

integer, intent(in) :: myPart

Partition of the caller (starts with 0)

integer, intent(in) :: nParts

Number of partitions

integer, intent(in) :: comm

communicator to be used