Fypp preprocessor generates Fortran code based on Python language. However, in some cases it is not straightforward. Read below to discover how to create higher level functions.

Let’s say our program requires to allocate an array for N supported ranks. dim is an array with the size of each rank.

allocate(var(dim(1)))
allocate(var(dim(1), dim(2)))
allocate(var(dim(1), dim(2), dim(3)))
allocate(var(dim(1), dim(2), dim(3), ...))
...
To N ranks

To make it possible We can provide to Fypp a new function to do such work:

allocate(var-place here our function-)

In the form of:

allocate(var${rankConstructor(4, “dim”)}$)

First step would be to create a pure python function:

def rankConstructor(ranks, dname):
    """
    Generate allocate dimensions for fortran
    genrank(4, "d") -> "(d(1),d(2),d(3),d(4))"
    
    usage:
      var(rankConstructor(4,"d"))

    output:
      var(d(1),d(2),d(3),d(4))
    """
    # create each dimension rank name
    output = [dname+"("+str(rank)+")" for rank in range(1,ranks+1)]
    # concatenate array with ","
    output_str = ','.join(map(str, output))
    # include parenthesis
    return "(" + output_str + ")"

Once it is certain it properly works, it is time to “translate” it into fypp:

#:def rankConstructor(RANKS,DNAMES)
#:set output = [DNAMES+"("+str(rank)+")" for rank in range(1,RANKS+1)]
#:set output_str = ','.join(map(str, output))
$:"(" + output_str + ")"
#:enddef rankConstructor

For every line creating a new local variable, set must be used. Finally, to return its value, use “$:” instead of using Python’s return keyword.

Leave a Reply

Your email address will not be published. Required fields are marked *