user2378824
user2378824

Reputation: 1

Pointer to a function inside a derived type on a module in fortran

I guess I could easily use some help here, since I'm messing around with some fortran 2003 but can't seem to understand how to do things really. The fact is that I need to write a fortran code that declares, inside a module, a new data type that has as one of its members a pointer to a real function. Something like

module new_mod
  type my_type
    real*8 :: a, b
    (here something that declares a real*8 function), pointer :: ptr
  end type my_type
end module_new

module funcs
  real*8 function function1(x)
    real*8 :: x
    function1 = x*x
  end function function1
  real*8 function function2(x)
    real*8 :: x
    function2 = x*x
  end function function2
end module funcs

then in the main program I would like to have something like

program my_prog
  use module_new
  use module_funcs
  implicit none
  real*8 :: y, z
  type(my_type) :: atom
  ...
  atom%ptr => function1
  y = atom%ptr(x)
  ...
  atom%ptr => function2
  z = atom%ptr(x)
end program my_prog

while

so the main idea is that module_new contains a type that has a pointer to a real function. This pointer in th eobjects of the new type I must be able to point to different functions in the main program. I have seen one can do similar things with abstract interfaces and such, but honestly, I'm in a mess here. If someone could help, I'll appreciate that. Cheers...

Upvotes: 0

Views: 736

Answers (1)

Bálint Aradi
Bálint Aradi

Reputation: 3812

Well, that is not really the type of question you would send to stackoverflow, but actually your code needs only a "slight improvement" (by appropriate definition of slight) to work:

module accuracy
  implicit none

  integer, parameter :: dp = kind(1.0d0)

end module accuracy


module typedef
  use accuracy
  implicit none

  type :: mytype
    real(dp) :: aa, bb
    procedure(myinterface), pointer, nopass :: myfunc
  end type mytype

  abstract interface
    function myinterface(xx)
      import :: dp
      real(dp), intent(in) :: xx
      real(dp) :: myinterface
    end function myinterface
  end interface

end module typedef

module funcs
  use accuracy
  implicit none

contains

  function func1(xx)
    real(dp), intent(in) :: xx
    real(dp) :: func1

    func1 = xx

  end function func1

  function func2(xx)
    real(dp), intent(in) :: xx
    real(dp) :: func2

    func2 = 2.0_dp * xx

  end function func2

end module funcs


program test
  use accuracy
  use typedef
  use funcs
  implicit none

  real(dp) :: xx
  type(mytype) :: atom

  xx = 12.0_dp
  atom%myfunc => func1
  print *, atom%myfunc(xx)
  atom%myfunc => func2
  print *, atom%myfunc(xx)

end program test

There are several things to be worth to mentioned:

  • You should use one global parameter for your accuracy (see module accuracy) and forget about real*8.

  • Your procedure pointer in your derived type needs an interface, which is provided within the following abstract interface block (see 'abstract interfaces' in a good F2003 book).

  • You need the nopass option for the procedure pointer in the derived type as otherwise Fortran will assume that the first parameter passed to the function/subroutine is the derived type itself (see 'type bound procedures' in a good F2003 book).

  • Finally, although rather obvious: You should definitely read a book about the Fortran 2003 features if you are serious about using them in a production code.

Upvotes: 3

Related Questions