1

I have the following code, where I call a function from a subroutine, all of them in the same module:

      module mymodule
      implicit none
      contains  

      subroutine mycode
      real :: y0(3), a = 0.0, b = 1.0
      integer :: i, N = 10
      real, allocatable :: y(:,:)
      y0(:) = [1.0, 1.0, 1.0]
      y = AB2(od, a, b, N, y0)
      do i = 1, N
          print *, y(:,i)
      end do      
      end subroutine mycode

      function AB2(f, a, b, N, y0)
          real, allocatable :: AB2(:,:)
          interface
              function f(x, y)
                  real, allocatable :: f(:)
                  real, intent(in) :: x, y(:)
              end function
          end interface
          real, intent(in) :: a, b
          integer, intent(in) :: N
          real, intent(in) :: y0(:)
          real :: xn0, xn1, step
          real, allocatable :: yn0(:), yn1(:)
          integer :: i
          allocate(AB2(size(y0),N))
          step = (b-a)/(N-1)
          AB2(:,1) = y0
          AB2(:,2) = y0 + step*f(a, y0)
          do i = 3, N
              xn0 = a+(i-2)*step
              xn1 = a+(i-1)*step
              yn0 = AB2(:,i-2)
              yn1 = AB2(:,i-1)
              AB2(:,i) = AB2(:,i-1) + step*(3.0/2.0*f(xn1,yn1)
     &             -0.5*f(xn0,yn0))
          end do
      end function

      function od(x, y)
          real, allocatable :: od(:)
          real, intent(in) :: x, y(:)
          allocate(od(3))
          od(1) =  x + y(1)
          od(2) = -y(3) - y(2) - x
          od(3) =  x - y(1) + y(3)
      end function

      end module mymodule

If I want to give another parameter to the function od, say c, I have to include it on this line

real, intent(in) :: x, c, y(:)

and also

   function od(x,c,y)

However, where do I provide the value for this argument? There is no option in the call

y = AB2(od, a, b, N, y0)
17
  • 1
    What error message do you get? How do you call your function? some more details (argument list, return value etc.) of the function are required. Commented Jan 7, 2018 at 18:06
  • Please show the complete code. Not just a module, but also the program that uses it. Compile your code with error checking debugging options like gfortran -g -traceback -Wall -fcheck=all and show the complete output. Your current error message is useless. If those options I showed don't help, you should at least identify at which line of code does the crash happen. Commented Jan 7, 2018 at 19:15
  • Why do you even make the function to return an allocatable array? Let it just return fixed-size array, it is simpler. Also, why is N=3 and od size 3? Shouldn't they be compatible? Commented Jan 7, 2018 at 19:17
  • 1
    Maybe need -standard-semantics (or -assume realloc_lhs) because auto-reallocation of allocatable arrays are used ? (e.g. yn0 = AB2(:,i-2)). Commented Jan 7, 2018 at 19:23
  • @roygvib did you manage to get it running? Commented Jan 7, 2018 at 20:00

1 Answer 1

1

This answer does not try to duplicate answers to Fortran minimization of a function with additional arguments Passing external function of multiple variables as a function of one variable in Fortran or Implementing anonymous functions in Fortran but to introduce the problem on a very basic level.

Suppose you have a function AB2 and another small function od.

They are used in such a way that AB2 accepts od as an argument, so you call

y = AB2(od)

the functions look like

real function AB2(f)
  interface
    real function f(x)
      real x
    end function
  end interface
  ... call f(x) here ...
end function

real function od(x)
  real x
end function

You need to pass additional data c to od. How to do that?

You cannot just change od by adding an argument for c and keep AB2 unchanged. AB2 contains a description of the interface of the argument f and od(x,c) would not be compatible with f(x).

Also, you would not be able to pass the data to AB2. You certainly cannot do

y = AB2(od(c))

by doing od(c) you are computing a number by calling od(x) you would then try to pass this number to AB2 instead of the function that should be passed.

There are several ways how to mitigate this. They are described in the answers linked above. I will show one simple possibility.

Let's say we nave have function od(b,x) and wee need to pass c to b, but we don't know how to do that with our AB2.

 real function od(b,x)
   real b, x
 end function

In our calling code we create a wrapper function that calls od with c for us. It can be an internal function or a module function. And we pass the wrapper to AB2.

subroutine caller(c)
  y = AB2(wrapper)
contains
  real function wrapper(x)
    real x
    !we must be able to see c from here, by host association or by using a module
    wrapper = od(c,x)
  end function
end subroutine
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.