Algorithm layer

In the PSyKAl separation of concerns, the Algorithm layer specifies the algorithm that the scientist would like to run (in terms of calls to kernel routines and Built-in operations) and logically operates on full fields. Algorithm code in the algorithm layer is not allowed to include any parallelisation calls or directives and passes datatypes specified by the particular API.

API

The Algorithm layer is forbidden from calling the Kernel layer directly. In PSyclone, if the programmer would like to call a Kernel routine or a Built-in operation from the algorithm layer they must use the invoke call (which is common to all APIs). The invoke call is not necessary (and indeed will not work) if the PSy layer is written manually.

To make an invoke call, the algorithm layer developer adds one or more call invoke() statements to their code and within the content of the invoke call they add a reference to the required Kernel/Built-in and the data to pass to it. For example,

...
call invoke(integrate_one_kernel(arg1,arg2))
...

For more information on the concept of Built-in operations see the Built-ins Section. Details of which operations are supported for a specific API are given in the documentation of that API.

The algorithm layer can consist of an arbitrary number of files containing fortran code, any of which may contain as many invoke() calls as is required. PSyclone is applied to an individual algorithm layer file and must therefore be run multiple times if multiple files containing invoke() calls exist in the algorithm layer.

The algorithm developer is also able to reference more than one Kernel/Built-in within an invoke. In fact this feature is encouraged for performance reasons. As a general guideline the developer should aim to use as few invokes as possible with as many Kernel references within them as is possible. The reason for this is that it allows for greater freedom for optimisation in the PSy layer as PSy layer optimisations are limited to the contents of individual invoke calls - PSyclone currently does not attempt to optimise the PSy layer over multiple invoke calls.

As well as generating the PSy layer code, PSyclone modifies the Algorithm layer code, replacing invoke calls with calls to the generated PSy layer so that the algorithm code is compilable and linkable to the PSy layer and adding in the appropriate use statement. For example, the above integrate_one_kernel invoke is translated into something like the following:

...
use psy, only : invoke_0_integrate_one_kernel
...
call invoke_0_integrate_one_kernel(arg1,arg2)
...

In addition, any use statements importing Kernels (integrate_one_kernel in this example) are removed because they are no longer required in the transformed algorithm code.

You may have noticed from other examples in this guide that an algorithm specification in an invoke call references the metadata type in an invoke call, not the code directly; this is by design.

For example, in the invoke call below, integrate_one_kernel is used.

...
call invoke(integrate_one_kernel(arg1,arg2))
...

integrate_one_kernel is the name of the metadata type in the module, not the name of the subroutine in the Kernel …

module integrate_one_module
  ...
  type, extends(kernel_type) :: integrate_one_kernel
    ...
  end type
  ...
contains
  ...
  subroutine integrate_one_code(...)
  ...
  end subroutine integrate_one_code
  ...
end module integrate_one_module

Named Invokes

PSyclone permits the user to optionally specify a label for an invoke call like so:

...
call invoke(integrate_one_kernel(arg1,arg2), &
            name="compute_something")
...

The name argument to the invoke call is optional. If supplied it must be a string literal. The content of this string is used in naming the corresponding PSy-layer routine generated by PSyclone. So, for the above example, the generated PSy-layer subroutine will be named “invoke_compute_something”. Each invoke label must currently be unique within an Algorithm source file. Note that, in keeping with the Fortran language, labels are not case-sensitive and must be valid Fortran names (e.g. name="compute(1)" is invalid). In the future it is intended that the labelling of invokes will help to support invoke-specific optimisations to be applied as well as enabling more readable profiling output. It may also be used to instruct PSyclone to just generate a single subroutine to implement all invokes that share the same label.

Limitations

In order to re-write the Algorithm layer, as just described, PSyclone must obviously be able to parse the invoke calls. Since the Fortran expression parser used by PSyclone is relatively simple, this means there are limitations on what Fortran may be used when specifying kernel arguments in an invoke call. Since these limitations can have a direct impact on the natural science code, the PSyclone developers endeavour to keep them to a minimum.

The current list of known limitations/restrictions on the form of kernel arguments within an invoke is:

  • No arithmetic expressions (e.g. kernel_type(a+b) or kernel_type(-a))

  • No named (optional) arguments (e.g. kernel_type(fn(my_arg=a)))

If you encounter any other limitations (or have a burning desire to use one of the above forms) then please contact the PSyclone developers.