# tem_faceData_module Module

Datatypes and routines for face descriptions.

Faces complement elements in the mesh. Each element is enclosed by two faces in each direction. (For cubical elements we get 6 faces enclosing the element). We organize the faces by looking at each direction individually. Thus, each face can be identified by its normal direction and an ID. With this approach it is possible to use the same identification numbers as for the elements and also to utilize the level descriptor that is available for the elements, by just using it for each direction separately.

For each face we have two sides (left in negative axis direction and right in positive axis direction): left < | > right. Accordingly we have two adjacent elements. See tem_face_module for some more details about the internals and the construction of the face information.

Faces can have properties attached to them, similar to the properties we have for elements. It is possible to combine the properties by adding the corresponding properties, i.e. tem_fromFinerFace_prp + tem_remoteFace_prp represents a face which is communicated, but at the same time a face from a finer level (i.e. in this situation is is a halo which is refined on the remote partition).

## Variables

TypeVisibilityAttributesNameInitial
integer, public, parameter:: tem_left =1

Parameter to index left (1)

integer, public, parameter:: tem_right =2

Parameter to index right (2)

integer, public, parameter, dimension(2):: tem_invFace_map =[tem_right, tem_left]

Inverse face mapping.

This simply maps 1 to 2 and 2 to 1. So it returns left when right is given, and right when left is given.

integer, public, parameter, dimension(6):: tem_dirToFace_map =[tem_left, tem_left, tem_left, tem_right, tem_right, tem_right]

Mapping from spatial direction to left and right face.

Each cubic element has 6 faces. In many solvers the different spatial directions are treated similarly, but just rotated. Therefore, in this module, we have left and right faces of an element. The following array provides a mapping from spatial direction to left or right face. In 2D the situation is as follows:

                                      right face in y
------------------------------
/             / q__N         /
y dir             /             /              /
/               /  q__W       /      q__E    /
/     left face / <---------elem---------->  /   right face in x
/               /             /              /
/               /             /              /
/               /             / q__S         /
/               ------------------------------
left face in y
------------> x dir


In a similar way, we can generalize the upper situation to 3D. To convert direction a face direction, e.g. q__E q__E, to a face direction access the following array by tem_dirToFace_map(q__E).

integer, public, parameter:: tem_notExist_prp =1

Left/right property of a face if the left/right element does not exist

integer, public, parameter:: tem_fluidFace_prp =2

Left/right property of a face if the left/right element of the face is a fluid element.

integer, public, parameter:: tem_fromFinerFace_prp =4

Left/right property of a face if the left/right element of the face is a from finer element.

integer, public, parameter:: tem_fromCoarserFace_prp =8

Left/right property of a face if the left/right element of the face is a from coarser element.

integer, public, parameter:: tem_remoteFace_prp =16

Left/right property of a face if the left/right element of the face is a halo element.

integer, public, parameter:: tem_bndFace_prp =32

Left/right property of a face if the left/right element of the face is a bnd element.

## Derived Types

### type, public :: tem_faceList_type

A unique list (i.e. guaranteees that no duplicates occur) collecting a set of faces in one direction.

#### Components

TypeVisibilityAttributesNameInitial
type(dyn_longarray_type), private :: faceId

The unique identifiers of the faces, i.e. the treeID of the elements on the left side of the face.

type(grw_longarray_type), private :: rightElemId

The element id of the element on the right side of the face.

type(grw_intarray_type), private :: leftElemPos

Index of the element left of the face.

type(grw_intarray_type), private :: rightElemPos

Index of the element right of the face.

type(grw_intarray_type), private :: leftPrp

Properties on the left side of the face.

type(grw_intarray_type), private :: rightPrp

Properties on the right side of the face.

### type, public :: tem_faceIterator_type

Iterator for a certain type of faces

#### Components

TypeVisibilityAttributesNameInitial
integer, private, allocatable:: leftPos(:)

Index of the element on the left side of the face.

integer, private, allocatable:: rightPos(:)

Index of the element on the right side of the face.

integer, private, allocatable:: facePos(:)

Index of the face in the (overall) face description (tem_faceList_type).

### type, public :: tem_face_descriptor_type

Datatype to provide face information for all faces in one direction on the same level.

#### Components

TypeVisibilityAttributesNameInitial
type(tem_faceList_type), private :: faceList

A dynamic list of faces in this descriptor.

type(tem_faceDep_type), private :: faceDep

For each element in tem_faceList_type we store the up- and downward facial dependencies.

type(tem_faceIterator_type), private :: computeFace

Datatype which holds iterators for the computable faces.

type(tem_faceInterpolation_type), private :: fromFinerFace(2)

Datatype which holds iterators for the from finer faces. We separate left and right faces. To determine which direction corresponds to left or right face, have a look at this tem_dirToFace_map.

type(tem_communication_type), private :: recvBuffer_state(2)

Buffer for state data which will be received before each compute step One buffer for the left faces of each cell and another one for the right faces of the cells. To determine which direction corresponds to left or right face, have a look at this tem_dirToFace_map.

type(tem_communication_type), private :: sendBuffer_state(2)

Buffer for state data which will be send before each compute step. One buffer for the left faces of each cell and another one for the right faces of the cells. To determine which direction corresponds to left or right face, have a look at this tem_dirToFace_map.

type(tem_communication_type), private :: recvBuffer_flux(2)

Buffer for flux data which will be received before each compute step One buffer for the left faces of each cell and another one for the right faces of the cells. To determine which direction corresponds to left or right face, have a look at this tem_dirToFace_map.

type(tem_communication_type), private :: sendBuffer_flux(2)

Buffer for flux data which will be send before each compute step. One buffer for the left faces of each cell and another one for the right faces of the cells. To determine which direction corresponds to left or right face, have a look at this tem_dirToFace_map.

### type, public :: tem_face_type

Datatype for all faces in the mesh per level.

#### Components

TypeVisibilityAttributesNameInitial
type(tem_face_descriptor_type), private :: faces(3)

Face information: one descriptor for each direction (x,y,z).

type(tem_levelDesc_type), private :: dimByDimDesc(3)

Dimension-by-dimension level descriptors (these descriptors are necessary to build up the face descriptions). The first of this descriptor is build with (-1,0,0) and (+1,0,0) stencil for the x-direction. The second is build with (0,-1,0) and (0,+1,0) stencil for the y-direction. The third is build with (0,0,-1) and (0,0,+1) stencil for the z-direction.

### type, private :: tem_faceDep_type

Datatype to represent dependencies (in up- and downward direction) of the faces in a TREELM mesh. We only store face dependencies between the two adjacent refinement levels (i.e. vertical dependencies consider only a refinement level jump of 1 in both refinement directions).

#### Components

TypeVisibilityAttributesNameInitial
integer(kind=long_k), private, allocatable:: parentFaceId(:)

integer, private, allocatable:: parentFacePos(:)

The parent elements position in the face description of the next coarser level. If any element does not have a parent face this array will hold a -1 entry at its position.

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

The downwards (current level -> finer level) facial dependencies. The size of this array is 4 (as we have 4 child faces) and the number of faces on the current level. If a face does not have/require child faces its entries are set to -1.

integer(kind=long_k), private, allocatable:: childFaceIdOp(:,:)
integer, private, allocatable:: childFacePos(:,:)

The child element positions in the face desciption of the next finer level. If any element does not have child faces, its entries will be set to -1.

integer, private, allocatable:: childFacePosOp(:,:)

### type, private :: tem_faceInterpolation_type

Container to store the face that require interpolations.

#### Components

TypeVisibilityAttributesNameInitial
integer, private, allocatable:: elemPos(:)

The element position. Since interpolations are done facewise (left or right) we only need one element position here.

integer, private, allocatable:: childPos(:,:)

The element positions of the finer child elements. As a face has exactly 4 children the first dimension is 4. The second dimension is the number of faces in this container.

integer, private, allocatable:: elemPosOp(:)

The element position opposite to the refined face. E.g. if the left element is refined, the right face of the left element position is stored here.

integer, private, allocatable:: childPosOp(:,:)

The child element positions opposite to the refined face.

integer, private, allocatable:: facePos(:)

Position of the face in the face description.