Wiki

Clone wiki

cosmosis / modules_fortran

Writing a module in Fortran

We do not condone the use of Fortran.

#!fortran

function setup(options) result(result)
    use cosmosis_modules
    use my_calculation_code
    implicit none
    integer(cosmosis_block), value :: options
    integer(cosmosis_status) :: status
    type(my_settings), pointer :: settings
    type(c_ptr) :: result

    !Make space for the configuration
    allocate(settings)

    !example: get an option from the section for this module.
    !we are assuming that the settings type has a my_option field in.
    status = datablock_get_int(options, option_section, "my_option", settings%my_option)

    if (status .ne. 0) then
        write(*,*) "Please set the option called 'my_option' in the ini file for my wonderful module'
        stop
    endif

    !Convert to the form that CosmoSIS needs.
    !c_loc is a built-in fortran function (in the iso_c_binding built-in module)
    !which converts from a Fortran pointer to a C pointer that python can understand.
    result = c_loc(settings)
end function setup


function execute(block, config) result(status)
    use cosmosis_modules
    use my_calculation_code

    implicit none
    integer(cosmosis_block), value :: block
    integer(cosmosis_status) :: status
    type(c_ptr), value :: config
    type(my_settings), pointer :: settings  

    call c_f_pointer(config, settings)

    return status

end function execute



function cleanup(config) result(status)
    use cosmosis_modules
    use my_calculation_code
    type(c_ptr), value :: config
    type(my_settings), pointer :: settings  
    integer(cosmosis_status) :: status

    !Free memory allocated in the setup function
    call c_f_pointer(config, settings)
    deallocate(settings)

    status = 0

end function cleanup

Listing of cosmosis fortran methods for modules

You use these functions in fortran to load and save data and parameters from the cosmosis_block that you get passed in the setup and execute modules. To use them, include the line at the top of your code:

They are listed in cosmosis/cosmosis/datablock/cosmosis_f90/cosmosis_modules.f90

#!fortran
Use cosmosis_modules

For all the functions listed below these parameters have these types:

#!fortran
integer(cosmosis_status) :: status
integer(cosmosis_block) :: block
character(*) :: section
character(*) :: name

The various value types are:

#!fortran
integer :: value  !for the "int" functions
logical :: value  !for the "logical" functions
real(c_double) :: value  !For the "double" functions.  
                         !This is the same as real(8) of double_precision
complex(c_double_complex) :: value  !For the "complex" functions
character(len=*) :: value !For the "string" functions

GET scalar functions

#!fortran

datablock_get_int(block, section, name, value) result(status)
datablock_get_double(block, section, name, value) result(status)
datablock_get_complex(block, section, name, value) result(status)
datablock_get_string(block, section, name, value) result(status)

datablock_get_int_default(block, section, name, default, value) result(status)
datablock_get_double_default(block, section, name, default, value) result(status)
datablock_get_complex_default(block, section, name, default, value) result(status)
datablock_get_string_default(block, section, name, default, value) result(status)

GET array functions

#!fortran
datablock_get_int_array_1d(block, section, name, value, size) result(status)
datablock_get_double_array_1d(block, section, name, value, size) result(status)
where the values are declared with assumed size "dimension(:)"

The other array functions are not available yet

PUT scalar functions

#!fortran
datablock_put_int(block, section, name, value) result(status)
datablock_put_double(block, section, name, value) result(status)
datablock_put_complex(block, section, name, value) result(status)
datablock_put_string(block, section, name, value) result(status)

PUT array functions

#!fortran
datablock_put_int_array_1d(block, section, name, value) result(status)
datablock_put_double_array_1d(block, section, name, value) result(status)
datablock_put_double_array_2d(block, section, name, value) result(status)

The REPLACE functions are the same as the PUT ones, with the word "replace" in place of the word "PUT"

GRID functions

A particularly common pattern in cosmology is a 2D grid where you have a function of two variables, for example P(k,z) where k and z are 1D arrays of size nk and nz, and P is a 2D array of size nk,nz.

There are specialized functions for this scenario:

#!fortran
datablock_put_double_grid(s, section, x_name, x, y_name, y, z_name, z) result(status)
datablock_get_double_grid(s, section, x_name, x, y_name, y, z_name, z) result(status)
datablock_put_double_grids(s, section, x_name, x, y_name, y, &
            z1_name, z1, z2_name, z2,  ..., z10_name, z10) result(status)
In the latter case multiple grids on the same axes are saved; all the grids after the first are optional. This code automatically takes care of the grid ordering - z will be allocated with size nx,ny regardless of how it was originally saved.

Updated