cdef.f90 Source File


Source Code

!> This is a Fortran interface to the C-API of `vesin`, from the header `vesin.h`.
module vesin_c
    use, intrinsic :: iso_c_binding
    implicit none

    private
    public :: VesinUnknownDevice, VesinCPU
    public :: VesinOptions
    public :: VesinNeighborList
    public :: vesin_neighbors
    public :: vesin_free

    !> Device on which the data can be
    enum, bind(c)
        !> Unknown device, used for default initialization and to indicate no
        !! allocated data.
        enumerator :: VesinUnknownDevice = 0

        !> CPU device
        enumerator :: VesinCPU = 1
    end enum

    !> Used for storing Vesin options.
    type, bind(c) :: VesinOptions
        !> Spherical cutoff, only pairs below this cutoff will be included
        real(c_double) :: cutoff = 0.0_c_double

        !> Should the returned neighbor list be a full list (include both `i -> j`
        !! and `j -> i` pairs) or a half list (include only `i -> j`)?
        logical(c_bool) :: full

        !> Should the neighbor list be sorted? If yes, the returned pairs will be
        !! sorted using lexicographic order.
        logical(c_bool) :: sorted = .false.

        !> Should the returned `VesinNeighborList` contain `shifts`?
        logical(c_bool) :: return_shifts = .false.

        !> Should the returned `VesinNeighborList` contain `distances`?
        logical(c_bool) :: return_distances = .false.

        !> Should the returned `VesinNeighborList` contain `vector`?
        logical(c_bool) :: return_vectors = .false.

    end type VesinOptions

    !> Used as return type from `vesin_neighbors()`.
    !!
    !! Data is returned in the various `type(c_ptr)` pointers to memory allocated
    !! by C. They need to be transformed into fortran pointers in order to read
    !! the values.
    type, bind(c) :: VesinNeighborList
        !> Number of pairs in this neighbor list
        integer(c_size_t) :: length = 0_c_size_t

        !> Device used for the data allocations
        integer(c_int) :: device = VesinUnknownDevice

        !> Array of pairs (storing the indices of the first and second point in
        !! the pair), containing `length` elements.
        type(c_ptr) :: pairs = c_null_ptr

        !> Array of box shifts, one for each `pair`. This is only set if
        !! `options.return_pairs` was `true` during the calculation.
        type(c_ptr) :: shifts = c_null_ptr

        !> Array of pair distance (i.e. distance between the two points), one for
        !! each pair. This is only set if `options.return_distances` was `true`
        !! during the calculation.
        type(c_ptr) :: distances = c_null_ptr

        !> Array of pair vector (i.e. vector between the two points), one for
        !! each pair. This is only set if `options.return_vector` was `true`
        !! during the calculation.
        type(c_ptr) :: vectors = c_null_ptr
    end type VesinNeighborList

    !> Compute a neighbor list.
    !!
    !! The data is returned in a `VesinNeighborList`. For an initial call, the
    !! `VesinNeighborList` should be default-initalized. The `VesinNeighborList`
    !! can be re-used across calls to this functions to re-use memory allocations,
    !! and once it is no longer needed, users should call `vesin_free` to
    !! release the corresponding memory.
    interface
        function vesin_neighbors(&
            points,        &
            n_points,      &
            box,           &
            periodic,      &
            device,        &
            options,       &
            neighbors,     &
            error_message  &
        ) result(status) bind(c, name="vesin_neighbors")
            import:: c_double, c_size_t, c_bool, c_ptr, c_int, VesinOptions, VesinNeighborList

            !> Number of elements in the `points` array
            integer(c_size_t), value   :: n_points

            !> Positions of all points in the system;
            real(c_double), intent(in) :: points(3, n_points)

            !> Bounding box for the system. If the system is non-periodic,
            !! this is ignored. This should contain the three vectors of the
            !! bounding box, one vector per column of the matrix.
            real(c_double), intent(in) :: box(3,3)

            !> Is the system using periodic boundary conditions?
            logical(c_bool), value     :: periodic

            !> Device where the `points` and `box` data is allocated.
            integer(c_int), value      :: device

            !> Options for the calculation
            type(VesinOptions), value  :: options

            !> A `type(VesinNeighborList)` instance, that will be used
            !! to store the computed list of neighbors.
            type(VesinNeighborList)    :: neighbors

            !> A `type(c_ptr)` to a null-terminated `char*` containing the
            !! error message of this function if any.
            type(c_ptr), intent(in)    :: error_message

            !> Non-zero integer upon error; zero otherwise.
            integer(c_int)             :: status

        end function vesin_neighbors
    end interface

    !> Free all allocated memory inside a `VesinNeighborList`, according to it's
    !! `device`.
    interface
        subroutine vesin_free(neighbors) bind(C, name="vesin_free")
        import:: VesinNeighborList
        type(VesinNeighborList) :: neighbors
        end subroutine vesin_free
    end interface
contains

end module vesin_c