# ply_split_element_module Module

This module provides the methods to project the polynomial representation in elements onto the representations in their halves in each dimension.

To perform the projection for Legendre polynomials we will use the computed coefficients for the Clenshaw algorithm from ply_split_legendre_module. With those the transformation is just a simple triangular matrix multiplication, but we need to take care of the orthogonal degrees of freedom as we want to handle all of them at the same time. Further we want to allow the transformation to be performed for multiple elements at once.

In each dimension we need to perform the following coordinate transformation:

Where $x$ refers to the coordinate in the original (coarse) element, and $\xi$ to the coordinates in the two (left and right) halves of the element.

## Variables

TypeVisibilityAttributesNameInitial
real(kind=rk), private, allocatable:: split_legendre(:,:)

Precomputed matrix to hold the transformation operation to project Legendre polynomials to its two half intervals.

This is computed by ply_split_legendre_matrix, see there for details. There are two triangular matrices stored in this array, one for the projection to the left half (-1,0) , and one for the projection to the right half (0,1).

This is a module variable, as it is only needed to be computed once with sufficient size. All lower orders are just subarrays out of the larger one.

## Abstract Interfaces

• ### public subroutine ply_split_element(parent_degree, child_degree, parent_data, child_data, ignore_highmodes)

Split elements of degree parent_degree into elements with polynomials of degree child_degree.

#### Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: parent_degree

Polynomial degree in the parent element.

integer, intent(in) :: child_degree

Polynomial degree in the child elements.

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

Polynomial data in the parent element. The first index describes the degrees of freedom. The second index refers to the elements to split.

real(kind=rk), intent(out) :: child_data(:,:)

Polynomial data in the child elements. The first index describes the degrees of freedom. The second index refers to the elements, there needs to be four times as many elements than in the parent_data.

Elements follow the ordering of the Z space filling curve.

logical, intent(in), optional :: ignore_highmodes

Whether to ignore high modes from the parent element.

This can be used as a simple lowpass filter by ignoring all higher modes from the parent element, that exceed the target polynomial degree. Thus, the polynomials are filtered before projection, instead of cutting them only of after refinement. Defaults to false (no filtering).

## Subroutines

### public subroutine ply_split_element_init(nMaxModes)

Initialization of the module. This needs to be performed before any call of the actual transformation ply_split_element_1D.

#### Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: nMaxModes

Maximal number of expected modes to perform the splitting for.

### public subroutine ply_split_element_singleD(nDims, inLen, outLen, parent_data, child_data, ignore)

Project a polynomial representation in elements in one dimension to its two halves in that direction.

#### Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: nDims

Number of dimensions of the polynomial data.

integer, intent(in) :: inLen(nDims)

Number degrees of freedom for each direction in parent_Data.

The first index of parent_data needs to have a length equal to the product of all inLen components. The splitting operation will be done in the last dimension.

integer, intent(in) :: outLen(nDims)

Number degrees of freedom for each direction in child_Data.

The first index of child_data needs to have a length equal to the product of all outLen components. The data will be cyclicly exchanged. Thus, the last dimension in parent_data corresponds to the first in one in child_data and all other components are shifted once to the right.

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

Polynomial representation in the parent elements.

The first index are the degrees of freedom in elements, the second index are the elements. In the first index the shape of data has to be in the form (inLen(1), inLen(2), ... , inLen(nDims)). The splitting operation is performed on the last dimension in that data.

real(kind=rk), intent(out) :: child_data(:,:)

Computed projection of the polynomial representation in the child elements.

Again, the first index refers to the degrees of freedom, while the second index are the elements. There need to be twice as many elements as in the parent_data. Left childs are stored in iChild = (iParent2 - 1), and the right childs in iParent2.

In the first index the shape of the data has to be in the form (outLen(1), outLen(2), ... , outLen(nDims)), the data is rotated in comparison to parent_data and the splitted direction has to be the first one in child_data (while it was the last in parent_data), and all other dimensions are shifted by one to the right.

logical, intent(in) :: ignore

Whether to ignore high modes that exceed the target maximal polynomial degree.

This can be used as a simple lowpass filter that cuts off the highest modes in the parent elements prior to mapping to child elements.

### public subroutine ply_split_element_1D(parent_degree, child_degree, parent_data, child_data, ignore_highmodes)

Split one-dimensional elements of degree parent_degree into two elements with polynomials of degree child_degree.

#### Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: parent_degree

Polynomial degree in the parent element.

integer, intent(in) :: child_degree

Polynomial degree in the child elements.

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

Polynomial data in the parent element. The first index describes the degrees of freedom. The second index refers to the elements to split.

real(kind=rk), intent(out) :: child_data(:,:)

Polynomial data in the child elements. The first index describes the degrees of freedom. The second index refers to the elements, there needs to be four times as many elements than in the parent_data.

Elements follow the ordering of the Z space filling curve.

logical, intent(in), optional :: ignore_highmodes

Whether to ignore high modes from the parent element.

This can be used as a simple lowpass filter by ignoring all higher modes from the parent element, that exceed the target polynomial degree. Thus, the polynomials are filtered before projection, instead of cutting them only of after refinement. Defaults to false (no filtering).

### public subroutine ply_split_element_2D(parent_degree, child_degree, parent_data, child_data, ignore_highmodes)

Split two-dimensional elements of degree parent_degree into four elements with polynomials of degree child_degree.

#### Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: parent_degree

Polynomial degree in the parent element.

integer, intent(in) :: child_degree

Polynomial degree in the child elements.

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

Polynomial data in the parent element. The first index describes the degrees of freedom. The second index refers to the elements to split.

real(kind=rk), intent(out) :: child_data(:,:)

Polynomial data in the child elements. The first index describes the degrees of freedom. The second index refers to the elements, there needs to be four times as many elements than in the parent_data.

Elements follow the ordering of the Z space filling curve.

logical, intent(in), optional :: ignore_highmodes

Whether to ignore high modes from the parent element.

This can be used as a simple lowpass filter by ignoring all higher modes from the parent element, that exceed the target polynomial degree. Thus, the polynomials are filtered before projection, instead of cutting them only of after refinement. Defaults to false (no filtering).

### public subroutine ply_split_element_3D(parent_degree, child_degree, parent_data, child_data, ignore_highmodes)

Split three-dimensional elements of degree parent_degree into eight elements with polynomials of degree child_degree.

#### Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: parent_degree

Polynomial degree in the parent element.

integer, intent(in) :: child_degree

Polynomial degree in the child elements.

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

Polynomial data in the parent element. The first index describes the degrees of freedom. The second index refers to the elements to split.

real(kind=rk), intent(out) :: child_data(:,:)

Polynomial data in the child elements. The first index describes the degrees of freedom. The second index refers to the elements, there needs to be four times as many elements than in the parent_data.

Elements follow the ordering of the Z space filling curve.

logical, intent(in), optional :: ignore_highmodes

Whether to ignore high modes from the parent element.

This can be used as a simple lowpass filter by ignoring all higher modes from the parent element, that exceed the target polynomial degree. Thus, the polynomials are filtered before projection, instead of cutting them only of after refinement. Defaults to false (no filtering).

### public subroutine ply_split_element_test(success)

Testing routine for the functions of this module.

#### Arguments

TypeIntentOptionalAttributesName
logical, intent(out) :: success

Indication whether the tests were completed successfully.

### private subroutine ply_split_element_1D_test(nModes, success)

Testing the 1D splitting.

#### Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: nModes

Number of modes in the (1D) polynomials to use in the check.

logical, intent(out) :: success

Indication whether the tests were completed successfully.

### private subroutine ply_split_element_2D_test(nModes, success)

Testing the 2D splitting.

#### Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: nModes

Number of modes in the (1D) polynomials to use in the check.

logical, intent(out) :: success

Indication whether the tests were completed successfully.

### private subroutine ply_split_element_3D_test(nModes, success)

Testing the 3D splitting.