c_interop.F90 Source File


This file depends on

sourcefile~~c_interop.f90~~EfferentGraph sourcefile~c_interop.f90 c_interop.F90 sourcefile~basis_tools.f90 basis_tools.F90 sourcefile~c_interop.f90->sourcefile~basis_tools.f90 sourcefile~messages.f90 messages.F90 sourcefile~c_interop.f90->sourcefile~messages.f90 sourcefile~strings.f90 strings.F90 sourcefile~c_interop.f90->sourcefile~strings.f90 sourcefile~tagarray_driver.f90 tagarray_driver.F90 sourcefile~c_interop.f90->sourcefile~tagarray_driver.f90 sourcefile~types.f90 types.F90 sourcefile~c_interop.f90->sourcefile~types.f90 sourcefile~basis_tools.f90->sourcefile~messages.f90 sourcefile~atomic_structure.f90 atomic_structure.F90 sourcefile~basis_tools.f90->sourcefile~atomic_structure.f90 sourcefile~basis_library.f90 basis_library.F90 sourcefile~basis_tools.f90->sourcefile~basis_library.f90 sourcefile~constants.f90 constants.F90 sourcefile~basis_tools.f90->sourcefile~constants.f90 sourcefile~constants_io.f90 constants_io.F90 sourcefile~basis_tools.f90->sourcefile~constants_io.f90 sourcefile~elements.f90 elements.F90 sourcefile~basis_tools.f90->sourcefile~elements.f90 sourcefile~parallel.f90 parallel.F90 sourcefile~basis_tools.f90->sourcefile~parallel.f90 sourcefile~precision.f90 precision.F90 sourcefile~basis_tools.f90->sourcefile~precision.f90 sourcefile~messages.f90->sourcefile~constants_io.f90 sourcefile~messages.f90->sourcefile~precision.f90 sourcefile~tagarray_driver.f90->sourcefile~messages.f90 sourcefile~types.f90->sourcefile~basis_tools.f90 sourcefile~types.f90->sourcefile~atomic_structure.f90 sourcefile~functionals.f90 functionals.F90 sourcefile~types.f90->sourcefile~functionals.f90 sourcefile~types.f90->sourcefile~parallel.f90 sourcefile~types.f90->sourcefile~precision.f90 sourcefile~atomic_structure.f90->sourcefile~strings.f90 sourcefile~basis_library.f90->sourcefile~strings.f90 sourcefile~basis_library.f90->sourcefile~constants.f90 sourcefile~basis_library.f90->sourcefile~constants_io.f90 sourcefile~basis_library.f90->sourcefile~elements.f90 sourcefile~constants.f90->sourcefile~precision.f90 sourcefile~elements.f90->sourcefile~strings.f90 sourcefile~physical_constants.f90 physical_constants.F90 sourcefile~elements.f90->sourcefile~physical_constants.f90 sourcefile~functionals.f90->sourcefile~messages.f90 sourcefile~functionals.f90->sourcefile~precision.f90 sourcefile~parallel.f90->sourcefile~precision.f90

Files dependent on this one

sourcefile~~c_interop.f90~~AfferentGraph sourcefile~c_interop.f90 c_interop.F90 sourcefile~apply_basis.f90 apply_basis.F90 sourcefile~apply_basis.f90->sourcefile~c_interop.f90 sourcefile~electric_moments.f90 electric_moments.F90 sourcefile~electric_moments.f90->sourcefile~c_interop.f90 sourcefile~get_basis_overlap.f90 get_basis_overlap.F90 sourcefile~get_basis_overlap.f90->sourcefile~c_interop.f90 sourcefile~get_states_overlap.f90 get_states_overlap.F90 sourcefile~get_states_overlap.f90->sourcefile~c_interop.f90 sourcefile~guess_hcore.f90 guess_hcore.F90 sourcefile~guess_hcore.f90->sourcefile~c_interop.f90 sourcefile~guess_huckel.f90 guess_huckel.F90 sourcefile~guess_huckel.f90->sourcefile~c_interop.f90 sourcefile~guess_json.f90 guess_json.F90 sourcefile~guess_json.f90->sourcefile~c_interop.f90 sourcefile~hf_energy.f90 hf_energy.f90 sourcefile~hf_energy.f90->sourcefile~c_interop.f90 sourcefile~hf_gradient.f90 hf_gradient.F90 sourcefile~hf_gradient.f90->sourcefile~c_interop.f90 sourcefile~int1e.f90 int1e.F90 sourcefile~int1e.f90->sourcefile~c_interop.f90 sourcefile~oqp_banner.f90 oqp_banner.F90 sourcefile~oqp_banner.f90->sourcefile~c_interop.f90 sourcefile~population_analysis.f90 population_analysis.F90 sourcefile~population_analysis.f90->sourcefile~c_interop.f90 sourcefile~resp.f90 resp.F90 sourcefile~resp.f90->sourcefile~c_interop.f90 sourcefile~tdhf_energy.f90 tdhf_energy.F90 sourcefile~tdhf_energy.f90->sourcefile~c_interop.f90 sourcefile~tdhf_gradient.f90 tdhf_gradient.F90 sourcefile~tdhf_gradient.f90->sourcefile~c_interop.f90 sourcefile~tdhf_mrsf_energy.f90 tdhf_mrsf_energy.F90 sourcefile~tdhf_mrsf_energy.f90->sourcefile~c_interop.f90 sourcefile~tdhf_sf_energy.f90 tdhf_sf_energy.F90 sourcefile~tdhf_sf_energy.f90->sourcefile~c_interop.f90 sourcefile~tdhf_z_vector.f90 tdhf_z_vector.F90 sourcefile~tdhf_z_vector.f90->sourcefile~c_interop.f90

Source Code

module c_interop

  use types, only: information
  use messages, only: without_abort
!  use types, only: oqp_handle_t
  use iso_c_binding, only: c_int, c_ptr, c_loc, c_f_pointer, c_associated, c_null_ptr, c_double, c_int32_t, c_int64_t, c_char

  implicit none

  private

  public oqp_handle_t

  public oqp_init
  public oqp_handle_refresh_ptr
  public oqp_handle_get_info

  interface oqp_handle_get_info
    module procedure oqp_handle_get_info_f
    module procedure oqp_handle_get_info_c
  end interface oqp_handle_get_info


  type, bind(C) :: oqp_handle_t
    type(c_ptr) :: inf
    type(c_ptr) :: xyz
    type(c_ptr) :: qn
    type(c_ptr) :: mass
    type(c_ptr) :: grad
    type(c_ptr) :: mol_prop
    type(c_ptr) :: mol_energy
    type(c_ptr) :: dft
    type(c_ptr) :: tddft
    type(c_ptr) :: control
    type(c_ptr) :: mpiinfo
    type(c_ptr) :: elshell
  end type

contains

!--------------------------------------------------------------------------------

  function oqp_init() bind(C, name='oqp_init') result(res)

    implicit none
    type(c_ptr) :: res
    type(oqp_handle_t), pointer :: c_handle
    type(information), pointer :: inf
    integer :: ok

    res = c_null_ptr

    allocate(inf, stat=ok)
    if (ok /= 0) return

    allocate(c_handle, stat=ok)
    if (ok /= 0) return

    c_handle%inf = c_loc(inf)
    call oqp_handle_refresh_ptr(c_handle)

    res = c_loc(c_handle)

    call inf%dat%new("OQP")

  end function oqp_init

!--------------------------------------------------------------------------------

  function oqp_clean(c_handle) bind(C, name='oqp_clean') result(ok)

    implicit none
    integer(c_int) :: ok
    type(c_ptr), value :: c_handle

    type(oqp_handle_t), pointer :: f_handle
    type(information), pointer :: inf

    call c_f_pointer(c_handle, f_handle)
    call c_f_pointer(f_handle%inf, inf)

    call inf%dat%delete()

    deallocate(inf, stat=ok)

    if (ok/=0) return

    deallocate(f_handle, stat=ok)

  end function oqp_clean

!--------------------------------------------------------------------------------

  subroutine oqp_handle_refresh_ptr(c_handle)

    implicit none
    type(oqp_handle_t), intent(inout) :: c_handle
    type(information), pointer :: inf

    call c_f_pointer(c_handle%inf, inf)

    c_handle%mol_prop    = c_loc(inf%mol_prop)
    c_handle%mol_energy  = c_loc(inf%mol_energy)
    c_handle%dft         = c_loc(inf%dft)
    c_handle%control     = c_loc(inf%control)
    c_handle%tddft       = c_loc(inf%tddft)
    c_handle%mpiinfo     = c_loc(inf%mpiinfo)
    c_handle%elshell     = c_loc(inf%elshell)
    if (allocated(inf%atoms%xyz)) then
        c_handle%xyz  = c_loc(inf%atoms%xyz)
        c_handle%qn   = c_loc(inf%atoms%zn)
        c_handle%mass = c_loc(inf%atoms%mass)
    end if
    if (allocated(inf%atoms%grad)) then
        c_handle%grad = c_loc(inf%atoms%grad)
    end if

  end subroutine oqp_handle_refresh_ptr

!--------------------------------------------------------------------------------

  function oqp_handle_get_info_f(f_handle) result(res)

    implicit none
    type(oqp_handle_t), target :: f_handle
    type(information), pointer :: res

    call c_f_pointer(f_handle%inf, res)

  end function oqp_handle_get_info_f

!--------------------------------------------------------------------------------

  function oqp_handle_get_info_c(c_handle) result(res)

    implicit none
    type(c_ptr) :: c_handle
    type(information), pointer :: res
    type(oqp_handle_t), pointer :: f_handle

    call c_f_pointer(c_handle, f_handle)
    call c_f_pointer(f_handle%inf, res)

  end function oqp_handle_get_info_c

!--------------------------------------------------------------------------------

  function oqp_set_atoms(c_handle, natoms, x, y, z, q, mass) bind(C, name='oqp_set_atoms') result(ok)

    implicit none
    type(oqp_handle_t) :: c_handle
    integer(c_int64_t), value :: natoms
    real(c_double) :: x(*), y(*), z(*), q(*)
    real(c_double), optional :: mass(*)
    integer(c_int) :: ok

    type(information), pointer :: inf

    ok = 10
    if (.not.c_associated(c_handle%inf)) return
    call c_f_pointer(c_handle%inf, inf)

    ok = inf%set_atoms_arr(natoms, x, y, z, q, mass)
    if (ok/=0) return

    call oqp_handle_refresh_ptr(c_handle)

  end function oqp_set_atoms

!--------------------------------------------------------------------------------

  function oqp_get_atoms(c_handle, xyz) result(ok)
    type(oqp_handle_t) :: c_handle
    integer(c_int) :: ok
    real(c_double) :: xyz(3,*)

    integer :: nat
    type(information), pointer :: inf

    ok = 10
    if (.not.c_associated(c_handle%inf)) return
    call c_f_pointer(c_handle%inf, inf)

    ok = 1
    nat = ubound(inf%atoms%xyz,2)
    xyz(:,1:nat) = inf%atoms%xyz

  end function

!--------------------------------------------------------------------------------

  function oqp_get_natom(c_handle) result(n) bind(C, name='oqp_get_natom')
    type(oqp_handle_t) :: c_handle
    integer(c_int64_t) :: n

    type(information), pointer :: inf

    n = -1
    if (.not.c_associated(c_handle%inf)) return
    call c_f_pointer(c_handle%inf, inf)

    n = ubound(inf%atoms%xyz,2)

  end function

!--------------------------------------------------------------------------------

  function oqp_get_nbf(c_handle) result(n) bind(C, name='oqp_get_nbf')
    type(oqp_handle_t) :: c_handle
    integer(c_int64_t) :: n

    type(information), pointer :: inf

    n = -1
    if (.not.c_associated(c_handle%inf)) return
    call c_f_pointer(c_handle%inf, inf)

    n = inf%basis%nbf

  end function

!--------------------------------------------------------------------------------

  function oqp_get_basis(c_handle, nsh, nprim, nbf, am, at, cdeg, ex, cc) result(ret) bind(C, name='oqp_get_basis')
    use basis_tools, only: basis_set
    type(oqp_handle_t) :: c_handle
    integer(c_int64_t) :: nsh, nprim, nbf
    integer(c_int64_t) :: ret
    type(c_ptr), intent(out) :: am, at, cdeg, ex, cc

    type(information), pointer :: inf
    type(basis_set), pointer :: bas

    ret = -1
    if (.not.c_associated(c_handle%inf)) return
    call c_f_pointer(c_handle%inf, inf)

    bas => inf%basis

    nbf = bas%nbf
    nprim = bas%nprim
    nsh = bas%nshell

    if (nbf <= 0) return

#define ADDRESSOF(a,b) if(allocated(a))then;b=c_loc(a);else;return;endif
    ADDRESSOF(bas%ex,    ex)
    ADDRESSOF(bas%cc,    cc)
    ADDRESSOF(bas%am, am)
    ADDRESSOF(bas%origin, at)
    ADDRESSOF(bas%ncontr,   cdeg)
#undef ADDRESSOF

    ret = 0

  end function

!--------------------------------------------------------------------------------

!> @brief Get calculation results from OQP handle
!> @param[in]    c_handle[in]  OQP handle
!> @param[in]    code[in]      Request string
!> @param[in]    v[out]        Pointer to data
!> @return       positive value:  success, returns size of the data
!>               negative values: -1 - handle not initialized;
!>                                -2 - data not available
!>                                -3 - unknown request code
  function oqp_get(c_handle, code, type_id, ndims, dims, v) result(n) bind(C, name='oqp_get')
    use strings, only: c_f_char
    use oqp_tagarray_driver, only: tagarray_get_cptr
    use tagarray_defines

    type(oqp_handle_t) :: c_handle
    integer(c_int64_t) :: n
    character(kind=c_char) :: code(*)
    type(c_ptr), intent(out) :: v
    integer(c_int32_t) :: type_id
    integer(c_int32_t) :: ndims
    integer(c_int64_t) :: dims(TA_DIMENSIONS_LENGTH)

    type(information), pointer :: inf
    character(:), allocatable :: code_str

    n = -1
    if (.not.c_associated(c_handle%inf)) return
    call c_f_pointer(c_handle%inf, inf)

    code_str = trim(adjustl(c_f_char(code)))

    n = tagarray_get_cptr(inf%dat, code_str, v, type_id, ndims, dims)
    if (.not.c_associated(v))  n = -2


  end function

!--------------------------------------------------------------------------------

!> @brief Allocate storage in OQP handle
!> @param[in]    c_handle[in]  OQP handle
!> @param[in]    tag[in]       Tag to store data at
!> @param[in]    v[out]        Pointer to the data
!> @return       positive value:  success, returns size of the data
!>               negative values: -1 - handle not initialized;
!>                                -2 - data not available
  function oqp_alloc(c_handle, tag, type_id, ndims, dims, v) result(n) bind(C, name='oqp_alloc')
    use strings, only: c_f_char
    use oqp_tagarray_driver, only: tagarray_get_cptr
    use tagarray_defines

    type(oqp_handle_t) :: c_handle
    integer(c_int64_t) :: n
    character(kind=c_char) :: tag(*)
    type(c_ptr), intent(out) :: v
    integer(c_int32_t) :: type_id
    integer(c_int32_t) :: ndims
    integer(c_int64_t) :: dims(TA_DIMENSIONS_LENGTH)

    type(information), pointer :: inf
    character(:), allocatable :: tag_str
    integer(c_int64_t) :: data_size

    n = -1
    if (.not.c_associated(c_handle%inf)) return
    call c_f_pointer(c_handle%inf, inf)

    tag_str = trim(adjustl(c_f_char(tag)))

    ! 1. check, if the data already exist, and clean it if yes
    call inf%dat%remove_records([tag_str])
    ! 2. allocate the memory in container
    call inf%dat%reserve_data(tag_str, type_id, product(dims(:ndims)), dims(:ndims))
    ! 3. Get the pointer to the freshly allocated data
    n = tagarray_get_cptr(inf%dat, tag_str, v, type_id, ndims, dims, data_size)
    if (.not.c_associated(v))  n = -2

  end function

!--------------------------------------------------------------------------------

!> @brief Clean an entry in OQP handle
!> @param[in]    c_handle[in]  OQP handle
!> @param[in]    tag[in]       Data tag
!> @return       positive value:  success, returns size of the data
!>               negative values: -1 - handle not initialized;
!>                                -2 - tag not found
!>                                -3 - error removing data
  function oqp_del(c_handle, tag) result(n) bind(C, name='oqp_del')
    use strings, only: c_f_char
    use oqp_tagarray_driver, only: data_has_tags, TA_OK
    use tagarray_defines

    type(oqp_handle_t) :: c_handle
    integer(c_int64_t) :: n
    character(kind=c_char) :: tag(*)
    integer(c_int32_t) :: stat

    type(information), pointer :: inf
    character(:), allocatable :: tag_str

    n = -1
    if (.not.c_associated(c_handle%inf)) return
    call c_f_pointer(c_handle%inf, inf)

    tag_str = trim(adjustl(c_f_char(tag)))

    n = -2
    call data_has_tags(inf%dat, [tag_str], 'c_interop', 'oqp_del', WITHOUT_ABORT, status=stat)
    if (stat /= TA_OK) return

    n = -3
    call inf%dat%remove_records([tag_str])

    n = 0

  end function

!--------------------------------------------------------------------------------
end module c_interop