You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 19 Next »

In XBeach repetitive code is stored in include files. These include files are generated by the "makeincludes" program that is compiled and run as a pre-compile action for the XBeach library (src/xbeachlibrary). The "makeincludes" program is, like XBeach, written in Fortran. Recently, a new development branch for XBeach is started that implements a Basic Model Interface (BMI). A BMI lets XBeach communicate with other models and is used to connect XBeach, for example, to aeolian sediment transport models. Implementation of a BMI is relatively simple, but involves a lot of repetitive code and therefore many include files. Generating all these files using more Fortan code was considered cumbersome, time-consuming and not transparent. Therefore the "makeincludes" program is replaced by a simple Python script in this branch.

The BMI branch is soon to be merged with the trunk. Therefore it becomes relevant for all XBeach developers to understand the differences between the "makeincludes" program and the Python script. These differences are listed on this page.

Is this information relevant to me?

It is if:

Components

The "makeincludes" program is replaced by the following components:

Python script

The "makeincludes" program was used to parse src/xbeachlibrary/params.F90 and src/xbeachlibrary/spaceparams.tmpl to find all input parameters and output variables respectively. The new templating system uses a Python script located in scripts/generate.py to parse the Fortran code. Also, the spaceparams.tmpl file is replaced by the src/xbeachlibrary/variables.F90 file. The main reason is that the Python script then only needs to parse Fortran code and not also a custom template format as used in the original spaceparams.tmpl file.

After parsing the relevant Fortran code the Python script defines two dictionaries (equivalent of Matlab's struct): "parameters" and "variables" that hold all the input parameters and output variables respectively, including their properties like rank, size, type and description. These dictionaries are used to parse the templates stored in src/xbeachlibrary/templates/ and generate the include files necessary to compile XBeach.

Templates

Templates are written in Fortran and therefore have the F90 file extension. Each template file will result in a single include file that has the INC file extension and will be written in the src/xbeachlibrary/ directory. To add an include file simply add a template file to the src/xbeachlibrary/templates/ directory and it will be picked up by the Python script. Templates define the Fortran code that is repeated in include files. Additional template markers define how the code is repeated using snippets of Python code. The Mako template engine is used to do so (see http://www.makotemplates.org).

An example of a template that defines the "spaceparams" structure is:

spacedecl.f90
<%
def dimstr(variable):
    if not variable['rank']:
        txt = ''
    else:
        txt = 'dimension({colons}), '.format(
            colons=','.join(':'*variable['rank'])
        )
    return txt
%>

%for variable in variables:
    ${variable['fortrantype']}, ${dimstr(variable)} pointer :: ${variable['name']}
%endfor
!directions for vi vim: filetype=fortran : syntax=fortran 

Python code can be added to a template in between the "<%" and "%>" markers. Single line code can be preceded simply by a "%". Single Python variables can be added within Fortran code within "${" and "}" markers.

In this example the first 10 lines define a Python function that generates a Fortran code snippet to define the dimensions of a variable. The function is used on line 13. Line 13 is in fact the only Fortran code line in this template. Line 12 and 14 form a for-loop that loops over all variables defined in the "variables" dictionary provided by the Python script and holds all variables defined in src/xbeachlibrary/variables.F90. This include file will therefore contain a single line of Fortran code for each variable defined in src/xbeachlibrary/variables.F90. Each line uses the "fortrantype", "rank" and variables "name" from the "variables" dictionary  as is visible in line 13. The "rank" is used to generate a Fortran code snippet to define the variables dimensions. Take a look at the other templates in src/xbeachlibrary/templates/ for more examples.

The first few lines of the resulting include file will look as follows:

spacedecl.inc
    double precision, dimension(:,:),  pointer :: x
    double precision, dimension(:,:),  pointer :: y
    double precision, dimension(:,:),  pointer :: xz
    double precision, dimension(:,:),  pointer :: yz
    double precision, dimension(:,:),  pointer :: xu
    double precision, dimension(:,:),  pointer :: yu
    double precision, dimension(:,:),  pointer :: xv
    double precision, dimension(:,:),  pointer :: yv

Output variables (variables.F90 vs. spaceparams.tmpl)

The spaceparams.tmpl file is replaced by the src/xbeachlibrary/variables.F90 file. The main reason is that the Python script that parses the variables.F90 and params.F90 file only needs to parse Fortran code and not also a custom template format as used in the original spaceparams.tmpl file. Each variable is defined on a separate line and all variables are defined as "target". A comment at the end of the line contains meta-data related to the variable and adheres to a specific format. An example variable definition is as follows:

variables.F90
 double precision, allocatable, target :: x(:,:)           !< [m] x-coord. original cmp. grid {"shape": ["s%nx+1", "s%ny+1"], "standard_name": "projection_x_coordinate", "broadcast": "d"}

The definition starts with a Fortran variable type. The following types are supported: character, logical, double precision, integer and real. Then, separated by commas, the variable may be declared "allocatable" and must be declared "target". Two colons ("::"), the name and number of dimensions follow. The line ends with a comment, indicated by the "!". A comment starts with the variables units between brackets ("[" and "]") followed by a description of the variable. The comment ends with a JSON object that defines the fields "shape", "standard_name" and "broadcast" representing the shape of the variable in terms of XBeach dimensions s%nx+1, s%ny+1, s%nd, s%ngd, etc, the netCDF standard name according to the CF convention and a MPI broadcast type ("b" for "broadcast" and "d" for "distribute"). It is possible to add other fields to the JSON object. All values will be available during parsing of the Fortran templates through the "variables" dictionary. Be aware that the JSON part of the comment should be strict JSON format (e.g. only double quotes, no single quotes).

More changes

A few other things changed in the XBeach code structure along with the new templating system as explained in the following subsections.

Fortran variable type definitions

In the new templating system all input and output variables are defined in the params.F90 and variables.F90 files respectively. These Fortran files are parsed by the templating system and need to adhere to a certain syntax as explained in above. Also the variable types definitions are restricted to a certain notation since multiple notations exist in Fortran. The types that are supported are:

  • character
  • logical
  • double precision
  • integer

Static templates

If you use static templates that do not depend on the params or spaceparams structures, still put them in the src/xbeachlibrary/templates/ directory as F90 files. These files are converted to INC files automatically and without modification. If you would put these files as INC files directly in the src/xbeachlibrary/ directory they will be deleted upon project cleaning and not generated again.

Template for writelog functions

The writelog functions are also considered repetitive and therefore also generated using a template. You can add writelog functions by adding a format code to the "formats" variable in the src/xbeachlibrary/templates/writelog.f90 and src/xbeachlibrary/templates/writeloginterface.f90 templates (e.g. "aiaiafai"). The necessary functions and interfaces are generated accordingly.

Python dependency

Compiling XBeach now depends on Python to generate the include files. Python is shipped with all popular Unix distributions, therefore this is no problem for Unix users. For Windows users Python is not always available. Therefore the scripts/generate.py is compiled as Windows executable so Windows users do not need Python to compile XBeach. Only when the scripts/generate.py script is modified the executable needs to be recompiled on a Windows machine with Python and the "distutils", "mako" and "py2exe" packages installed. Compiling the executable is done from the command-line as follows:

>> cd scripts/
>> python setup.py py2exe

The Windows executable is stored in scripts/dist/. Be aware that there is no need to recompile the Python script after changing or adding templates, nor after changing or adding variables to the params.F90 or variables.F90 files. The only reason to recompile the Python script is if the templating system in scripts/generate.py itself has changed (e.g. the Fortran parser).

C interface

The original C-interface has become superfluous with the new BMI interface and is removed. In the following table a mapping form the original C-interface to the new BMI interface can be found:

original C-interfaceBMI interface
init()initialize()
outputext() 
executestep()update(dt)
final()finalize()
 get_var(var)
 get_var_type(var)
 get_var_rank(var)
 get_var_shape(var)
 set_var(var, val)
 get_start_time()
 get_current_time()
 get_end_time()

The BMI interface does not support getting derived variables (min, max, avg, var) nor does it support setting of input parameters. It does support some externally controlled time stepping. Externally set time steps are maximized according to the CFL condition. Negative time steps make the model to skip the absolute value of the time step in time, without executing any model. The external program should provide the updated model state as well.

  • No labels