Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F2PY wrap procedure that uses derived types only internally

It is stated in a lot of places that F2PY does not "support derived types", however, it is unclear to me whether this means that either

  • derived types may not be used as parameters to procedures wrapped by F2PY
  • derived types may not even be used internally in procedures I want to wrap with F2PY

To my use case the first point is an inconvenience but the second rather a deal breaker.

As an example, consider this module that computes a vector sum:

module derived_types

implicit none
public :: point, add

type :: point
   real :: x
   real :: y
end type point

contains

type(point) function add(p1, p2)

type(point), intent(in) :: p1
type(point), intent(in) :: p2

add%x = p1%x + p2%x
add%y = p1%y + p2%y

end function add

end module derived_types


module expose

use derived_types, only: point, add
implicit none

contains

subroutine vector_sum(x1, y1, x2, y2, x3, y3)

real, intent(in) ::  x1, y1, x2, y2
real, intent(out) :: x3, y3

type(point) :: p1, p2, p3

p1 = point(x1, y1)
p2 = point(x2, y2)

p3 = add(p1, p2)

x3 = p3%x
y3 = p3%y

end subroutine vector_sum

end module expose

Subroutine vector_sum shall be exposed to Python. The derived type point is not to be passed between Python and Fortran.

This works as plain Fortran program (with an appropriate program block added) but F2PY fails:

f2py -c ff.f90 only: vector_sum

running build
running config_cc
unifing config_cc, config, build_clib, build_ext, build commands --compiler options
running config_fc
unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options
running build_src
build_src
building extension "untitled" sources
f2py options: ['only:', 'vector_sum', ':']
f2py:> /tmp/tmpjdq8b9dq/src.linux-x86_64-3.8/untitledmodule.c
creating /tmp/tmpjdq8b9dq/src.linux-x86_64-3.8
Reading fortran codes...
    Reading file 'ff.f90' (format:free)
Line #7 in ff.f90:"type :: point "
    analyzeline: No name/args pattern found for line.
Post-processing...
    Block: untitled
            Block: derived_types
                Block: unknown_type
            Block: expose
                Block: vector_sum
            Block: run
Post-processing (stage 2)...
    Block: untitled
        Block: unknown_interface
            Block: derived_types
                Block: unknown_type
            Block: expose
                Block: vector_sum
            Block: run
Building modules...
    Building module "untitled"...
        Constructing F90 module support for "derived_types"...
          Variables: point add
getctype: No C-type found in "{'attrspec': ['public']}", assuming void.
Traceback (most recent call last):
File "/home/me/.pyenv/versions/anaconda3-2020.11/lib/python3.8/site-packages/numpy/f2py/f90mod_rules.py", line 143, in buildhooks
    at = capi_maps.c2capi_map[ct]
KeyError: 'void'

Can such a thing be done using F2PY at all?

like image 204
Christoph90 Avatar asked Oct 25 '25 18:10

Christoph90


1 Answers

You can use a single procedure, define the derived type therein as well as using contained procedures. This is a quick and dirty approach which will only suffice for smaller problems.

An example implementation follows

! file: a.f90
subroutine vector_sum(x1, y1, x2, y2, x3, y3)
  real, intent(in)  :: x1, y1, x2, y2
  real, intent(out) :: x3, y3

  type point
    real :: x(2)
  end type

  type(point) :: p1, p2, p3

  p1%x = [x1, y1]
  p2%x = [x2, y2]

  p3 = add(p1, p2)

  x3 = p3%x(1)
  y3 = p3%x(2)

contains

  type(point) function add(p1, p2)
    type(point), intent(in) :: p1
    type(point), intent(in) :: p2

    add%x = p1%x + p2%x
  end function

end subroutine

Compilation

$ f2py -c a.f90 -m amod

Usage in python

>>> import amod
>>> amod.vector_sum(1, 2, 3, 4)
(4.0, 6.0)
like image 115
jack Avatar answered Oct 28 '25 06:10

jack



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!