# ExaSlang 4 Documentation¶

## Language Structure¶

### Top-Level Statements¶

The following statements are supported:

• import

• inline knowledge

• declarations of knowledge objects

• domain declaration

• field layout declaration

• field declaration

• external field declaration

• direct stencil declaration

• stencil declaration from expression

• stencil declaration from default

• stencil field declaration

• global section

• function declarations

• function declaration

• function template declaration

• function instantiation

### Inner Statements¶

The following statements are supported:

• local declarations

• variable declaration

• value declaration

• assignment and compound assignment

• loops

• fixed-length loop

• conditional loop

• contraction loop

• field loop

• fragment loop

• conditional

• function call; implicitly wrapped in an expression statement

• apply bc

• communicate

• return statement

• level scope

• local solve

• repeat statement

• color statement

### Expressions¶

The following expressions are supported:

• literal

• access

• function call

• unary operations and binary operations

• field iterator access

TODO

## Basic Language Constructs¶

Comments are offered with C-like syntax.

#### Syntax¶

// comment
/* comment */


#### Example¶

// this is a comment

/* this is a
multi-line
comment
*/


### Data types¶

Represents a simple data type.

#### Syntax¶

dataType


#### Details¶

dataType may be one of the following:

• Unit (must not be used in declarations)

• Real

• Integer or Int

• String

• Boolean or Bool

• a higher dimensional data type

#### Example¶

cf examples for variable declarations and function declarations.

### Literals¶

Literals.

#### Syntax¶

number
boolean
'string'
"string"

#### Details¶

number may be integral or real.

boolean may be true or false.

#### Example¶

1
1.5
1.0e30
true
'some string'
"some string"

### Levels¶

#### Level Access¶

##### Syntax¶
@level

##### Details¶

level may be on of the following

• a constant

• a relative level

• a suitable level alias evaluating to a single level

##### Example¶
@10


#### Level Declaration¶

A group of levels used for declarations.

##### Syntax¶
@levels

##### Details¶

levels may be on of the following

• a constant

• a relative level

• a level list

• a suitable level alias

##### Example¶
@10

@(finest - 1)


#### Relative Level¶

##### Syntax¶
(base + offset)
(base - offset)
##### Details¶

base must be a constant or a suitable level alias evaluating to a single level.

offset must be an integer constant.

##### Example¶
(finest - 1)


#### Level Alias¶

Aliases for commonly used cases.

##### Syntax¶
alias

##### Details¶

alias may be on of the following: Used as level access:

• current, denoting that the level of the surrounding construct should be used

• finer, shorthand for @(current + 1)

• coarser, shorthand for @(current - 1)

Used as level access and level declaration:

• finest, denoting the finest level as specified by Knowledge.maxLevel

• coarsest, denoting the coarsest level as specified by Knowledge.minLevel

Used as level declaration:

• all, denoting all levels as specified by the range between Knowledge.minLevel and Knowledge.maxLevel

##### Example¶
@all


#### Level List¶

A list of levels used for level declarations.

##### Syntax¶
(
levels
/* optional */ but exclude
)

##### Details¶

levels must be a non-empty list of levels separated by comma or the and keyword, or a level range.

exclude, if provided, must be a valid level list without any nested exclude. The not keyword may be used instead of the but keyword.

##### Example¶
(0, 2, 4)
(all but finest)

#### Level Range¶

A range of levels used for level declarations.

##### Syntax¶
( begin to end )

##### Details¶

begin and end must be constants or suitable level aliases evaluating to single levels.

##### Example¶
(coarsest to finest)

### Functions¶

#### Function Declaration¶

Declares a new function with the given name, taking the provided arguments and with the given returnType.

##### Syntax¶
/* optional */ noinline
Function name
/* optional */ levels
/* optional */ ( arguments )
/* optional */ : returnType
{ body }

##### Details¶

Func may be used instead of Function.

noinline may be used to disallow inlining for this function.

The function declaration is regarded as leveled if levels is specified. Must be a valid level selection for declarations.

arguments, if provided, has to be a list of function arguments. May be empty.

returnType, if provided, has to be a valid language datatype. In this case, at least one return statement must be present in the body. If returnType is not provided, an implicit Unit type is assumed.

body must be a list of suitable statements. May be empty.

##### Example¶
Function F ( xPos : Real, yPos : Real ) : Real {
return sin ( xPos ) * cos ( yPos )
}

Function Smoother@all {
/* ... */
}


#### Function Argument¶

Specifies a function argument with the given name and dataType.

##### Syntax¶
name : dataType

##### Details¶

dataType must be a valid language datatype.

##### Example¶
someParam : Real


#### Return Statement¶

Statement used to exit a function and to optionally return a value.

##### Syntax¶
return
/* optional */ returnValue

##### Details¶

returnValue may be an arbitrary expression. Its data type must match the surrounding functions return type. In case of Unit returnValue must not be specified.

##### Example¶
return

return sin ( xPos ) * cos ( yPos )


#### Function Call¶

Call a function with the given name and the provided parameters.

##### Syntax¶
name
/* optional */ levels
/* optional */ offset
( parameters )

##### Details¶

If the called function is leveled and levels is not provided, an implicit @current is assumed. levels, if provided, must be a valid level access.

parameter is a list of arbitrary expressions. May be empty.

If the function call is used as a statement, it is implicitly wrapped in an expression statement.

##### Example¶
Var res : Real = F ( 0.5, 0.5 )

Smoother@current ( )


### Local Declarations¶

#### Variable Declaration¶

Declares a new variable

##### Syntax¶
Var name : dataType
/* optional */ levels
/* optional */ = initial

##### Details¶

Variable may be used instead of Var.

dataType must be a valid language datatype.

The declaration is regarded as leveled if levels is specified. Must be a valid level selection for declarations.

initial may be an arbitrary expression. It is used to initialize the variable in the generated code if provided.

##### Example¶
Var cnt : Int = 0
Var curError : Real = 0


#### Value Declaration¶

Declares a new constant variable

##### Syntax¶
Val name : dataType
/* optional */ levels
= initial

##### Details¶

Value may be used instead of Val.

dataType must be a valid language datatype.

The declaration is regarded as leveled if levels is specified. Must be a valid level selection for declarations.

initial may be an arbitrary expression.

Right now values are propagated by default and without check for side effects. This effectively means that they work like a C define. Can be controlled via Knowledge.experimental_l4_inlineValueDeclarations.

##### Example¶
Val maxNumIts : Int = 128
Val a : Real = 10.5 * 4.


### Assignments¶

#### Basic Assignment¶

Assigns src to dest.

##### Syntax¶
dest = src

##### Details¶

dest must be a valid access.

src maybe an arbitrary expression evaluating to the data type of dest.

##### Example¶
Var cnt : Int
cnt = 0


#### Compound Assignment¶

Performs a compound assignment from src to dest with the specified operation.

##### Syntax¶
dest += src
dest -= src
dest *= src
dest /= src
##### Details¶

dest must be a valid access.

src maybe an arbitrary expression evaluating to the data type of dest.

##### Example¶
Var cnt : Int = 0
cnt += 1


### Unary Operations¶

Performs basic calculations.

#### Syntax¶

op target


#### Details¶

target may be arbitrary expressions.

op may be one of the following:

• for numeric expressions

• -

• for boolean expressions

• !

#### Example¶

-1
!true

### Binary Operations¶

Performs basic calculations.

#### Syntax¶

left op right


#### Details¶

left and right may be arbitrary expressions.

op may be one of the following:

• for numeric expressions

• + - * /

• % for modulo operations

• ** or ^ for power operations

• for boolean expressions

• || or ‘or’

• && or ‘and’

• < <= > >= == and != for comparison operations

the precedence is given by:

• for numeric expressions

• ** ^

• * / %

• + -

• for boolean expressions

• || or

• && and

• < <= > >= == !=

#### Example¶

1 + 2
MyStencil * MyField

### Basic Loops¶

#### Fixed-Length Loop¶

Executes statements a constant number of times.

##### Syntax¶
repeat n times
/* optional */ count variable
{ body }

##### Details¶

n must be an integral number.

The current iteration number is stored in variable, if provided, which needs to be declared beforehand.

body must be a list of suitable statements. May be empty.

##### Example¶
Var cnt : Int = 0
repeat 10 times count cnt {
print ( 'Iteration', cnt )
}


#### Conditional Loop¶

Executes statements while or until a given condition is met.

##### Syntax¶
 repeat until condition { body }
 repeat while condition { body }
##### Details¶

condition may be an arbitrary expression evaluating to a Boolean value.

body must be a list of suitable statements. May be empty.

##### Example¶
Var cnt : Int = 0
repeat until 10 == cnt {
print ( 'Iteration', cnt )
cnt += 1
}


### Conditional¶

brief

#### Syntax¶

if ( condition ) { ifBranch }
/* optional */ else elseBranch


#### Details¶

Exectues ifBranch if condition evaluates to true, elseBranch otherwise (if it is specified).

condition may be an arbitrary expression evaluating to a Boolean.

ifBranch must be a list of suitable statements. May be empty.

elseBranch may be

• another conditional

• a list of suitable statements; may be empty

#### Example¶

if ( true ) {
print ( 'always true' )
} else {
print ( 'will not be evaluated' )
}

Var someVar : Real = 0.5
if ( 0. == someVar or 1. == someVar ) {
// ...
}


### Index¶

#### Constant Index¶

A constant index which can, e.g., be used as offset or direction.

##### Syntax¶
[ i_0 ]
[ i_0 , i_1 ]
[ i_0 , i_1 , i_2 ]
##### Details¶

i_n must be integral constants. More than 3 dimensions are supported, but omitted here.

##### Example¶
[ 1, 0 ]
[ 0, 1, -1 ]

#### Expression Index¶

An index with expressions.

##### Syntax¶
[ e_0 ]
[ e_0 , e_1 ]
[ e_0 , e_1 , e_2 ]
##### Details¶

e_n may be arbitrary expressions evaluating to Int. More than 3 dimensions are supported, but omitted here.

##### Example¶
[ 0, 1, -1 ]
[ ( i0 % 2 ), ( i1 % 2 ) ]

## Knowledge Objects¶

### Domains¶

#### Domain Declaration¶

Declares a new domain with the given name.

##### Syntax¶
Domain name < lower to upper >

##### Details¶

lower and upper are coordinates of the axis-aligned bounding box surrounding the domain. Their dimensionality must match. Currently it must also be identical to Knowledge.dimesionality.

In case of multiple domains, the boundaries of all (sub-)domains must coincide with the domain partitioning.

There must be at least one domain named ‘global’. This domain must include all other domains.

##### Example¶
Domain unitSquare < [0., 0.] to [1., 1.] >
Domain global < [0, 0, 0] to [2, 4, 6] >

### Fields¶

#### Field Layout Declaration¶

Declares a new field layout with the given name and options.

##### Syntax¶
Layout name < dataType , localization >
/* optional */ levels
{ options }

##### Details¶

Specifies that quantities of the given dataType are stored at specific parts of the grid chosen by localization.

dataType must be a valid language datatype.

localization must be one of the following:

• Node

• Cell

• Face_x

• Face_y if dimensionality at least 2

• Face_z if dimensionality at least 3

The declaration is always regarded as leveled. If levels is specified it must be a valid level selection for declarations. If it is not specified, an implicit @all is assumed.

layoutOptions is a list of layout options which may be separated by comma. May be empty.

##### Example¶
Layout CellLayout < Real , Cell > @all {
duplicateLayers = [ 0, 0, 0 ]
ghostLayers     = [ 1, 1, 1 ] with communication
}


#### Layout Option¶

Specification of an option to be used for field layouts.

##### Syntax¶
option = index
/* optional */ with communication

##### Details¶

option may be one of the following:

• duplicateLayers

• ghostLayers

• innerPoints

index specifies the number of layers per dimension for the chosen option.

with communication marks the chosen layers for communication. Layers that are not marked here will not be communicated, even when communicate statements are given.

##### Example¶

cf example for field layout declarations.

#### Field Declaration¶

Declares a new field with the given name and the provided options.

##### Syntax¶
Field name < domain , layout , boundaryCondition >
/* optional */ [ numSlots ]
/* optional */ levels

##### Details¶

Each field is tied to a specific domain accessed through its name.

Data type, localization of the field, etc is controlled by the linked layout. An implicit @current is always assumed. This is only a name - providing a level in addition is not supported.

boundaryCondition may be a valid boundary condition.

If numSlots is specified, the field is slotted with the given number. Must be an integer constant.

The declaration is always regarded as leveled. If levels is specified it must be a valid level selection for declarations. If it is not specified, an implicit @all is assumed.

##### Example¶
Field vis < global, CellLayout, None >
Field rho < global, CellLayout, Neumann > [2] @all

#### Boundary Condition¶

Specifies the boundary conditions to be used for a given field

##### Syntax¶
None
Neumann
/* optional */ ( order )

dirichlet
bcFunction ( )
##### Details¶

None corresponds to no boundary handling.

Neumann corresponds to Neumann-0 boundary conditions. If order is not specified it is defaulted to Knowledge.discr_defaultNeumannOrder.

dirichlet may take the shape of an arbitrary expression evaluating to the data type of the field.

bcFunction is a function reference, with optional level, to a user function implementing the boundary handling routine. The function’s return type must be Unit.

Since dirchlet can be a function call, an thus may look like a call to a bcFunction, the return type of the called function must be known at generation time. It is used to switch both cases.

##### Example¶
Neumann ( 1 )
sin ( vf_boundaryPosition_x )
applyBoundaries ( )

#### External Field Declaration¶

Declares a new external field with the given name and the provided options.

##### Syntax¶
external Field name < layout > => internal

##### Details¶

Used to transfer data from external program parts to fields declared in the DSL.

layout must describe the layout of the external counterpart.

internal is a reference to a declared field. A level specification is necessary.

Using this information, copy-in and copy-out functions are set up. These can be called from the external program.

If Knowledge.generateFortranInterface is set, the external counterpart is assumed to be in Fortran-compliant ordering, otherwise lexicographic ordering is assumed.

##### Example¶
Layout CellLayout < Real , Cell > { /* ... */ }
Layout ExternalLayout < Real , Cell > @finest { /* ... */ }

Field p < global, CellLayout, Neumann >

external Field p_0 < ExternalLayout > => p@finest


### Stencils¶

#### Direct Stencil Declaration¶

Declares a new stencil with the given name and the provided entries.

##### Syntax¶
Stencil name
/* optional */ levels
{ entries }

##### Details¶

The declaration is always regarded as leveled. If levels is specified it must be a valid level selection for declarations. If it is not specified, an implicit @all is assumed.

entries is a list of offset entries or mapping entries. May be separated by comma. May be empty.

##### Example¶
Stencil FivePoint@all {
[ 0,  0] =>  4.0
[-1,  0] => -1.0
[ 1,  0] => -1.0
[ 0, -1] => -1.0
[ 0,  1] => -1.0
}

Stencil RestrictCell {
[i0, i1] from [ 2 * i0,     2 * i1     ] with 0.25
[i0, i1] from [ 2 * i0,     2 * i1 + 1 ] with 0.25
[i0, i1] from [ 2 * i0 + 1, 2 * i1     ] with 0.25
[i0, i1] from [ 2 * i0 + 1, 2 * i1 + 1 ] with 0.25
}


#### Stencil Offset Entry¶

A single stencil entry in offset notation.

##### Syntax¶
offset => coefficient

##### Details¶

offset must be a const index. coefficient may be an arbitrary expression.

##### Example¶
[ 0,  0] =>  4.0 * alpha + epsilon


#### Stencil Mapping Entry¶

A single stencil entry in mapping notation.

##### Syntax¶
row from col with coefficient

##### Details¶

row and col can be interpreted as the corresponding row and column positions for the coefficient were the matrix represented by the stencil constructed explicitly.

coefficient may be an arbitrary expression.

##### Example¶
[i0, i1] from [ 2 * i0, 2 * i1 ] with 1.0


#### Stencil From Expression¶

Declares a new stencil with the given name and constructs it based on expression

##### Syntax¶
Stencil name
/* optional */ levels
from expression

##### Details¶

expression may be an arbitrary expression evaluating to a stencil. Supported operations on stencils are:

• scaling

• multiplication

• transpose

• kron (Kronecker product)

##### Example¶
Stencil Horizontal { /* ... */ }
Stencil Vertical   { /* ... */ }
Stencil Combined from 2.0 * ( Horizontal + Vertical )


#### Stencil From Default¶

Declares a new stencil with the given name and constructs it based on the specified default operation.

##### Syntax¶
Stencil name
/* optional */ levels
from default operation on localization with parameter

##### Details¶

operation may be either restriction or prolongation.

localization specifies where the operator will be applied. Allowed values are the same as for field layout declarations.

For restriction and prolongation, parameter specifies the interpolation scheme. It may be ‘linear’ for values of discretized functions and ‘integral_linear’ for values of integrals over discretized functions. The former is usually applied in finite difference contexts, while the latter finds application in finite volume contexts.

##### Example¶
RestrictNode from default restriction on Node with 'linear'


#### Stencil Field Declaration¶

Declares a new stencil field with the given name, using the shape of stencil and storing the data in field.

##### Syntax¶
StencilField name < field => stencil >
/* optional */ levels

##### Details¶

For stencil and field, an implicit @current is always assumed. This is only a name - providing a level in addition is not supported.

The declaration is always regarded as leveled. If levels is specified it must be a valid level selection for declarations. If it is not specified, an implicit @all is assumed.

The order of coefficients in the linked stencil will remain and be mapped to the entries of the linked field’s data.

The data type of the linked field has to be vector. The vector size must match the number of coefficients in the linked stencil.

The coefficients of the stencil are used to initialize the field’s data.

##### Example¶
Layout SfLayout < Vector < Real, 5 > , Cell > { /* ... */ }
Field StencilData < global, SfLayout, None >

Stencil FivePointShape { /* ... */ }

StencilField StoredFivePoint < StencilData => FivePointShape >


## Domain-Specific Features¶

### Access¶

#### Syntax¶

target
/* optional */ [ slot ]
/* optional */ @ level
/* optional */ @ offet
/* optional */ : direction
/* optional */ [ component ]


#### Details¶

The actual type of access is deferred by the code generator. Depending on the type, invalid modifiers will be ignored.

slot, if specified, must be a valid slot access. It is only valid if target is a field. The field may be un-slotted.

level, if specified, must be a valid access level. It is only valid if target is leveled.

offset, if specified, must be a valid constant index. It is only valid if target is either a field, a stencil or a stencil field. In this case, target is not evaluated at the current point of iteration, given by the surrounding field loop, but at the current point plus the given offset.

direction, if specified, must be a valid constant index. It is only valid if target is either a stencil or a stencil field. In this case, target is evaluated in the given direction. This effectively means, that the entry of the target stencil (field) is selected that has the direction as offset. This selected entry is used instead of target.

component, if specified, must be an integral constant. If target is a vector field or a stencil field, a component of the vector of target is used instead of target. This feature will be removed in future versions of the language.

direction and component are currently mutually exclusive.

#### Example¶

someVar
someField[active]@current@[1, 0]
someStencil@current:[0, 0]
someStencilField@[1, 0]:[0, 0]

### Special Loops¶

#### Field Loop¶

Loops over the given field and executes the body at each point.

##### Syntax¶
loop over field
/* optional */ only region
/* optional */ sequentially
/* optional */ where condition
/* optional */ starting offsetBegin
/* optional */ ending offsetEnd
/* optional */ stepping stepSize
/* optional */ with reduction
/* optional */ preComm
/* optional */ postComm
{ body }

##### Details¶

If no level is provided for field, an implicit @current is assumed. Other modifiers such as slot, offset or direction access are ignored.

only region may be used to restrict iteration to a specific region. If it is not provided, inner is assumed.

sequentially prevents shared memory parallelization. This is only a temporary workaround.

where condition may be used to restrict the execution of body to only cases where condition is fulfilled. Prominent applications are colored kernels.

offsetBegin and offsetEnd may be used to extend or restrict the iteration space. Constant indices are required. offsetBegin is added to the loop start while offsetEnd is subtracted from the loop end.

stepSize may be used to adapt the generated loops’ step size. It must be a positive, non-zero constant indices.

reduction must be a valid reduction.

preComm and postComm, if defined, must be one or more expressions in the form of pre- and postcomm.

body must be a list of suitable statements. May be empty.

If a field loop is not in the scope of a fragment loop, an implicit fragment loop is wrapped around the field loop in the generation processs.

##### Example¶
loop over u { /* ... */ }
loop over u where 0 == ( i0 + i1 ) % 2 { /* ... */ }
loop over u only ghost [0, -1] on boundary { /* ... */ }
loop over u starting [1, 0] stepping [2, 1] { /* ... */ }
Var curErr : Real = 0.0
loop over u with reduction ( max, curErr ) { /* ... */ }


#### Region¶

Specifies an iteration region for a field loop.

##### Syntax¶
target direction
/* optional */ on boundary

##### Details¶

target may be one of the following:

• inner

• dup

• ghost

dup corresponds to duplicate layers. ghost corresponds to ghost layers. inner corresponds to inner layers.

direction specifies which part of the current fragment’s grid is selected. For example, [1, 0] would select the right edge. direction must be a constant indices. In case of inner as target, direction is ignored but should be zero in all dimensions by convention.

If on boundary is specified, the loop is only executed at outer boundaries, i.e., for fragments that don’t have a neighbor in the specified direction.

##### Example¶
only dup [0, -1] on boundary


#### Fragment Loop¶

Loops over all fragments.

##### Syntax¶
loop over fragments
/* optional */ with reduction
{ body }

##### Details¶

reduction must be a valid reduction.

body must be a list of suitable statements. May be empty.

body usually contains at least one field loop. Communicate statements and apply bc statements inside fragment loops are supported.

##### Example¶
Var sum : Real = 0.0
loop over fragments with reduction ( + : sum ) {
loop over u with reduction ( + : sum ) { /* ... */ }
}


#### Reduction¶

Specifies a reduction to be performed for an associated special loop.

##### Syntax¶
reduction ( op : target )

##### Details¶

op may be one of the following:

• + or *

• min or max

target must be the name of a previously declared variable.

If Knowledge.experimental_trimBoundsForReductionLoops is enabled, iteration spaces are adapted such that duplicate points are only handled on one fragment. This prevents adding the contribution of the same duplicate point multiple times.

##### Example¶
Var sum : Real = 0.0
loop over u with reduction ( + : sum ) { /* ... */ }


#### Contraction Loop¶

Contracts the iteration space of a loop with each repetition.

##### Syntax¶
repeat n times
/* optional */ count variable
with contraction posExtent
/* optional */ , negExtent
{ body }

##### Details¶

n must be an integral number.

The current iteration number is stored in variable, if provided, which needs to be declared beforehand.

posExtent and negExtent must be a const index.

body must be a list of suitable statements. May be empty.

##### Example¶
// 2D example

loop over fragments {
/* contraction: iterate over
[0-(5-1)*1, 0] to [32+(5-1)*1, 32]
[0-(5-2)*1, 0] to [32+(5-2)*1, 32]
...
[0, 0] to [32, 32]
*/
repeat 5 times with contraction [1, 0 ] {
// regular: iterate over [0, 0] to [32, 32]
loop over Solution@finest {
// ...
}
}

/* contraction: iterate over
[0-(3-1)*(-2), 0] to [32+(3-1)*1, 32],
[0-(3-2)*(-2), 0] to [32+(3-2)*1, 32],
[0, 0] to [32, 32]
*/
repeat 3 times with contraction [1, 0 ], [-2, 0] {
// regular: iterate over [0, 0] to [32, 32]
loop over Solution@finest {
// ...
}
}
}


### Communication¶

#### Communicate¶

Triggers data exchange for the given field.

##### Syntax¶
/* optional */ begin
/* optional */ finish
communicate targets of field
/* optional */ where condition

##### Details¶

begin and finish are mutually exclusive. They trigger the start and end of a communication phase. The user is responsible for ensuring that matching pairs exist and are called accordingly. If neither is given, a full communication is performed.

communicating can be used instead of communicate.

targets must be a list of valid communicate targets. It may be empty in which case all is assumed.

field must be a valid reference to a field to be communicated. An implicit @current is assumed if no level specification is given. Slot modifiers are honored. Other modifiers such as offset and direction access are ignored.

condition can be used to restrict exchange to data points fulfilling the given condition. It may be an arbitrary expression evaluating to a Boolean. NOT IMPLEMENTED YET

##### Example¶
communicate u[next]@current
begin communicating u
/* ... */
finish communicating u


#### Communicate Target¶

brief

##### Syntax¶
target
/* optional */ start
/* optional */ to end // inclusive indices

##### Details¶

target can be one of the following:

• all

• dup

• ghost

dup corresponds to duplicate layers. ghost corresponds to ghost layers. all corresponds to ghost and duplicate layers.

start and end have to be constant indices. Both are inclusive. If defined, the range of applicable layers to be communicated is restricted to the given range.

##### Example¶
examples of usage


#### Pre- and PostComm¶

Specifies a communication step to be performed before or after an associated loop.

##### Syntax¶
preComm
/* optional */ op
target
of field
/* optional */ where condition

postComm
/* optional */ op
target
of field
/* optional */ where condition

##### Details¶

op can be one of the following:

• begin

• finish

If op is not given, a synchronous (w.r.t. the Layer 4 execution path) communication is performed.

target must be a valid communicate target.

condition can be used to restrict the communication to points fulfilling it. This function is not fully implement yet.

##### Example¶
precomm all of Solution@current
postcomm dup of Solution where 0 == ( i0 + i1 ) % 2

### Field Operations¶

#### Apply BC¶

Applies the boundary conditions of a given field.

##### Syntax¶
apply bc to field

##### Details¶

field must be a valid reference to a field to be updated. An implicit @current is assumed if no level specification is given. Slot modifiers are honored. Other modifiers such as offset and direction access are ignored.

##### Example¶
apply bc to u


#### Field Iterator Access¶

##### Syntax¶
i0
i1
i2
##### Details¶

i0 through i2 access the iterator in the corresponding dimension of a surrounding field loop. Only valid in the scope of a field loop.

x, y and z can be used as well. This feature will be removed in future versions of the language.

##### Example¶
0 == ( i0 + i1 + i2 ) % 2


### Field Slotting¶

#### Slot Access¶

Selects the slot of a field.

##### Syntax¶
target

##### Details¶

target may be one of the following:

• active, activeSlot or currentSlot

• next or nextSlot

• previous or previousSlot

• an integral constant

##### Example¶

cf example of access.

Advances the slot of a given field.

##### Syntax¶
advance field

##### Details¶

field must be a valid reference to a field. An implicit @current is assumed if no level specification is given. Slot modifiers and other modifiers such as offset and direction access are ignored.

##### Example¶
advance u


### Solver Extensions¶

#### Local Solve¶

Solves for multiple unknowns at once.

##### Syntax¶
solve locally
/* optional */ with jacobi
/* optional */ relax omega
{ components }

##### Details¶

Internally, a system of equations based on the given components is constructed and solved. The solution to the system is then written back to the unknowns.

with jacobi specifies that the writeback should be performed to the next slot of the unknowns’ fields.

omega, if provided, will be used to relax the found solution to the local system. It may be an arbitrary expression that evaluated to Double.

components must be a list of of valid solve components.

Must be inside the scope of a field loop.

##### Example¶
loop over u {
solve locally relax 0.8 {
u@[0, 0] => laplace@[0, 0] * u@[0, 0] == rhs_u@[0, 0]
u@[1, 0] => laplace@[1, 0] * u@[1, 0] == rhs_u@[1, 0]
}
}


#### Solve Component¶

Specifies one component of a local solve block.

##### Syntax¶
unknown => lhs == rhs

##### Details¶

unknown must be a valid reference to a field. An implicit @current is assumed if no level specification is given. Other modifiers are honored.

lhs and rhs are the left- and right-hand sides of the equation to be solved. They may be arbitrary expressions evaluating to the same data type. Equations not including the unknown are supported.

##### Example¶
u => laplace * u == 0.0
u@[1, 0] => laplace@[1, 0] * u@[1, 0] == rhs_u@[1, 0]

#### Repeat Statement¶

Repeats a set of statements in a body for given conditions.

##### Syntax¶
repeat with { conditions , body }

##### Details¶

conditions must be a comma-separated list of arbitrary expressions, each evaluating to Boolean.

body must be a list of suitable statements. May be empty. Currently only field loops are restricted. Other statements remain untouched. In future versions, apply bc and communicate will be handled as well.

During unfolding, the body is duplicated once for each condition. It is then adapted by adding the condition expression to, e.g., field loops.

##### Example¶
repeat with {
( 0 == ( i0 + i1 ) % 2 ),
( 1 == ( i0 + i1 ) % 2 ),

loop over p { /* ... */ }
communicate p
}


#### Color Statement¶

Colors a set of statements in a body with given colors computations.

##### Syntax¶
color with { colors , body }

##### Details¶

colors must be a comma-separated list of modulo expressions whose divisors are natural numbers. Each expression specifies how one element of the color vector is computed.

body must be a list of suitable statements. May be empty. Currently only field loops are colored. Other statements remain untouched. In future versions, apply bc and communicate will be handled as well.

During unfolding, the body is duplicated once for each color. It is then adapted to the current color by adding the color expression to, e.g., field loops as (potentially additional) condition.

##### Example¶
color with {
i0 % 2,
i1 % 2,

loop over p { /* ... */ }
communicate p
}


## Language Extensions¶

### Top-Level¶

#### Import¶

Imports the content of another DSL file.

##### Syntax¶
import filename

##### Details¶

filename is relative to the location of the current DSL file. The location is automatically adapted for nested imports.

Multiple import statements in the same file are supported.

##### Example¶
import '../lib/defaultGlobals.exa4'


#### Inline Knowledge¶

Allows specifying knowledge parameters in the DSL.

##### Syntax¶
Knowledge { parameters }

##### Details¶

parameters must be a list of key-value assignments. Separation by comma is not supported. May be empty.

Multiple knowledge inlines in the same file are supported.

##### Example¶
Knowledge {
opt_unroll            = 2
}


#### Global Section¶

Opens a new global section holding declarations of global variables and values.

##### Syntax¶
Globals { entries }

##### Details¶

entries must be a list of valid variable declarations and value declarations. May be empty.

Multiple global sections in one DSL document are supported.

##### Example¶
Globals {
Var omega     : Real = 0.8
Val maxNumIts : Int  = 128
}


#### Function Template¶

Declares a new function template with the given name.

##### Syntax¶
FunctionTemplate name < templateParams > ( functionParams ) : returnType { body }

##### Details¶

FuncTemplate can be used instead of FunctionTemplate.

templateParams must be a list of identifiers that must be separated by comma or newline. May be empty.

functionParams must be a list of function arguments. May be separated by comma. May be empty.

returnType must be a valid language data type.

This statement will not map to a function without suitable function instantiations.

body must be a list of suitable statements. May be empty.

##### Example¶
FunctionTemplate SetFieldComponent < target > ( value : Real ) : Unit {
loop over target {
target = value
}
}


#### Function Instantiation¶

Instantiates a function template as a new function with the given name.

##### Syntax¶
Instantiate template < templateArgs > as name
/* optional */ levels

##### Details¶

Inst can be used instead of Instantiate.

template must be the name of a declared function template.

templateArgs must be a list of expressions that must be separated by comma or newline. Its length must match the length on the template parameter list of the linked function template.

name is the name of the newly created function. If a suitable level declaration is given, the new function inherits it.

In the instantiation, occurrences of each function template parameter in the function template body are replaced with the corresponding given argument. Modifiers such as level, offset or direction accesses are merged.

##### Example¶
Instantiate SetFieldComponent < u@current > as SetSolution_u@all
Instantiate SetFieldComponent < v@current > as SetSolution_v@all


### Inner¶

#### LevelScope¶

Conditional execution of statements depending on the surrounding scope’s level.

##### Syntax¶
levels { body }

##### Details¶

body is only executed if the current level (usually given by a surrounding function) matches the given levels, or, in case of a given range or list, is included in it.

levels must be a valid level declaration.

body must be a list of suitable statements. May be empty.

##### Example¶
Function recursive@all () {
/* ... */

@(all but coarsest) {
recursive@coarser ( )
}
}


## TO BE INTEGRATED¶

### Higher-Dimensional Data Types¶

#### Vectors¶

Represents a one-dimensional number of scalar elements

##### Syntax¶
{expression, expression, ...  } /* optional */ T

##### Details¶

At least one expression is required to construct a one-dimensional vector. T can be used to transpose the defined vector expression.

##### Example¶
Var v1 : Vector<Real, 3> = { 1, 2, 3}
Var v2 : Vec3 = [1 2 3] + [4 5 6]
Var v3 : ColumnVector<Int, 3> = {1, 2, 3}T

##### Built-in functions¶
• transpose() to transpose a vector. For anonymous vector definitions, a suffixing T can be used.

• dot() to calculate dot product of two vectors

• supported operators for binary expression: +, -, *, /

• supported element-wise operations: .*, *./, .% (modulo), .^ (power)

#### Matrices¶

Represents a two-dimensional number of scalar elements

##### Declaration Syntax¶
{{expression, expression, ...  }, {expression, expression, ...  }, ... }

##### Details¶

At least one expression is required to construct a 1x1 matrix.

##### Example¶
Var m1 : Matrix<Real, 2, 2> = {{1, 2}, {3, 4}}
Var m2 : Matrix<Real, 2, 3> = [1 2 3; 4 5 6]

##### Access¶

Vectors and Matrices can be written to and read from via the []-operator:

Var quadMat : Matrix <Real, 2, 23> = {{0., 1.}, {1., 0.}}
Var colVecMat : Matrix <Real, 3, 13> = {{0.}, {1.}, {1337.}}
Var rowVec : RowVector <Real, 33> = {0., 1., 1337.}

Var tmp : Real = colVecMat[0]
rowVec[1] = 1

##### Slicing¶

The following functions can be used to obtain or set a submatrix of a given matrix:

• getElement(mat : Matrix<T>, j : Int, i : Int) : T returns the (j,i)th entry

• setElement(mat : Matrix<T>, j : Int, i : Int) : T sets the (j,i)th entry

• getSlice(mat : Matrix<T>, offsetRows : Int, offsetCols: Int, nRows : Int, nCols : Int) : Matrix<T> reads a submatrix of size (nRows x nCols) from position (offsetRows, offsetCols) in mat

• setSlice(mat : Matrix<T>, offsetRows : Int, offsetCols: Int, nRows : Int, nCols : Int, val : T) : Matrix<T> writes the value val to a submatrix of size (nRows x nCols) at position (offsetRows, offsetCols) in mat

• slicing operations can also be executed via the []-operator with index ranges or : for a complete dimension.

Some examples:

setSlice(quadMat,0,1,2,1,5) // quadMat = {{0., 1.}, {5., 5.}}
Var row : Matrix<Real, 1, 2 > = getSlice(quadMat,0,1,1,2) // row = {{5., 5.}}
Var col : Matrix<Real, 2, 1 > = quadMat[:][1] // col = {{1.},{5.}}
rowVec[0:3] = 4. // colVec = {{4.},{4.},{4.}}

##### Built-in functions¶
• transpose() to transpose a matrix

• dot() and cross() to calculate dot or cross product of two matrices

• det() to calculate the determinant

• norm() calculates the frobenius-norm of the matrix

• trace() calculates the trace

• transpose() transposes the matrix

• supported operators for binary expression: +, -, *, /

• supported element-wise operations: .*, *./, .% (modulo), .^ (power)

##### Direct solution of linear systems¶

Small linear systems can be solved directly at runtime or compiletime with the solveMatSys-statement, which takes a system matrix, unknowns and a right-hand-side of fitting dimensions as arguments:

Var A : Matrix<Real, 3, 3> = {{3,2,-1},{2,-2,4},{-1,0.5,-1}}
Var f : Matrix<Real, 3, 1> = {{1},{-2},{0}}
Var u : Matrix<Real, 3, 1>
solveMatSys A,u,f // u = {{1}, {-2}, {-2}}


Additional information about the shape of a matrix can be added:

solveMatSys A2,u2,f2 {shape=blockdiagonal,block=3} // A2 is a blockdiagonal matrix with blocks of size 3x3


The generator will then produce a routine that exploits the shape of the matrix.
Supported shapes are:

• blockdiagonal with block=… (diagonal block size)

• diagonal

If experimental_resolveLocalMatSys is set to Runtime, the system will be solved at runtime of the generated application. If experimental_resolveLocalMatSys is set to Compiletime, the system will be solved at generation time with certain restrictions.

##### Inversion¶

Matrices can be inverted by the inverse() function.

Var mat_inverse : Matrix<Real, 7, 7> = inverse(mat, "shape=schur", "block=6", "A=blockdiagonal", "Ablock=3")


Additional information about the shape of a matrix can be added as arguments. Next to blockdiagonal and diagonal matrices, also a Schur-shape can be specified, which allows a specialized solution technique. If experimental_resolveInverseFunctionCall is set to Runtime, the inversion will be executed at runtime of the generated application. If experimental_resolveInverseFunctionCall is set to Compiletime, the inversion will be executed at generation time with certain restrictions.

#### Solve locally extensions¶

##### System matrix shapes¶

The shape of the systems set up by solve locally statements can also be used to speed up the solution:

• If it is known, it can be communicated to the generator with the knowledge-attribute experimental_locMatShape. (in case of a Schur or blockdiagonal shape, also the attributes experimental_locMatBlocksize, experimental_locMatShapeA and experimental_locMatBlocksizeA can be specified)

• Another possible way is to provide the shape with the field declaration of the iterated field. Here, the same syntax as in section ‘direct solution of linear systems’ is used.

##### Execution time¶
• experimental_resolveLocalMatSys also determines execution time of solution of solve-locally-systems.

• if experimental_evalMOpRuntimeExe is set, solve-locally-systems will be solved depending on their size: small systems are feasible for solution at compiletime in order to reduce the runtime of the generated application. Larger systems can only be solved at runtime as they increase the compiletime extremely if executed at compiletime.

##### Shape classification¶

An automatic classification of the present shape with all block sizes in a solve-locally-system is done if the knowledge-attribute experimental_classifyLocMat is set to ‘true’. Currently, the three mentioned shapes diagonal, blockdiagonal and Schur are supported for automatic classification.

## I/O statements (Layer 4)¶

Currently, following (parallel) I/O approaches are supported:

• Single-shared file: Shared file where each process accesses different regions within a shared file.

• Locking: MPI processes share a common file but there is only one active writer/reader process. Uses the C++ standard I/O library for ASCII or binary in-/output.

• MPI I/O: MPI processes access different file regions concurrently. Binary format for in-/output.

• §HDF5: MPI processes access different file regions concurrently. HDF5 format (binary incl. meta-data) for in-/output.

• §netCDF: MPI processes access different file regions concurrently. NetCDF format (binary incl. meta-data) for in-/output.

• SionLib: MPI processes access different file regions concurrently. SIONlib format (binary incl. meta-data) for in-/output.

• File-per-process: Each MPI process is assigned an unshared file. Uses the C++ standard I/O library for ASCII or binary in-/output.

### Data storage and retrieval¶

For the storage of field data, following statements can be used.

// Locking: Binary or ASCII
writeField_lock ( filename: Expression, field: FieldAccess,
includeGhost: Boolean = false, useBinary: Boolean = false,
condition: Expression = true, separator: Expression = " " )
// File-per-process: Binary or ASCII
writeField_fpp ( filename: Expression, field: FieldAccess,
includeGhost: Boolean = false, useBinary: Boolean = false,
condition: Expression = true, separator: Expression = " " )
// MPI-I/O: only for MPI parallel applications. Binary
writeField_mpiio ( filename: Expression, field: FieldAccess,
includeGhost: Boolean = false, canonicalOrder: Boolean = false, repr: String = "native" )
// (P)HDF5
writeField_hdf5 ( filename: Expression, datasetPath: Expression, field: FieldAccess,
includeGhost: Boolean = false, canonicalOrder: Boolean = false )
// (P)netCDF
writeField_nc ( filename: Expression, varName: Expression, field: FieldAccess,
includeGhost: Boolean = false, canonicalOrder: Boolean = false )
// SIONlib: serial and parallel
writeField_sion ( filename: Expression, field: FieldAccess,
includeGhost: Boolean = false, condition: Expression = true )


Likewise, data can be retrieved via readField_xyz with identical function signature.

### Visualization¶

For visualization, two different types of statements can be used:

• For specific kinds of application (SWE, NS, NNF): Print multiple fields on an unstructured mesh.

// VTK printers: locking (ASCII). Extension: ".vtk"
printVtkSWE(filename: Expression, level: Int, fields : FieldAccess*)
printVtkNS (filename: Expression, level: Int)
printVtkNNF(filename: Expression, level: Int)
// XDMF printers: file-per-process (binary or ASCII). Extension: ".xmf"
printXdmfSWE_fpp(filename: Expression, level: Int, useBinary: Boolean, fields: FieldAccess*)
printXdmfNS_fpp (filename: Expression, level: Int, useBinary: Boolean)
printXdmfNNF_fpp(filename: Expression, level: Int, useBinary: Boolean)
// XDMF printers: single-shared file with either: xyz = mpiio or hdf5
printXdmfSWE_xyz(filename: Expression, level: Int, fields: FieldAccess*)
printXdmfNS_xyz (filename: Expression, level: Int)
printXdmfNNF_xyz(filename: Expression, level: Int)
// ExodusII printers: single-shared file with PnetCDF. Extension: ".e"
printExodusSWE(filename: Expression, level: Int, fields: FieldAccess*)
printExodusNS (filename: Expression, level: Int)
printExodusNNF(filename: Expression, level: Int)

• For any kind of application: Print one field on a (block-)structured mesh.

// CSV printer: locking (ASCII). Extension: ".csv"
printField_lock (filename: Expression, fieldAccess: FieldAccess, inclGhost: Boolean = false,
useBin: Boolean = false, cond: Expression = true, separator: Expression = " ")
// XDMF printers: file-per-process (binary or ASCII). Extension: ".xmf"
printField_fpp (filename: Expression, field: FieldAccess, useBinary : Boolean = false)
// XDMF printers: single-shared file with either: xyz = mpiio or hdf5
printField_xyz (filename: Expression, field: FieldAccess, canonicalLayout: Boolean = false)
// netCDF printer. Extension: ".nc"
printField_nc (filename: Expression, field: FieldAccess, canonicalLayout: Boolean = false)