Search code examples
modulecompilationfortransubroutine

errors when transforming program into module with subroutine


Given a simple program, that runs just fine, e.g.:

program test
implicit none
real, allocatable :: x(:)
real :: su, si
allocate(x(3))
x(:) = (/1,2,3/)
su=sum(x(:))
si=size(x(:))
end program

I tried to transform it into an external module with a subroutine:

module test
implicit none
real, allocatable, intent(in) :: x(:)
real, intent(out) :: su, si
contains
subroutine sumsize(x(:),su,si)
    su=sum(x(:))
    si=size(x(:))
end subroutine
end module

However I cannot get it compiled with several error messages of which I believe most are based on x(:), su ,and si all not being DUMMY variables.

Where and how are dummies defined? It seems like this is a simple formal error.

Another error states junk in the subroutine head, and fades when defining it with subroutine sumsize(x,su,si). Why can the input for the subroutine not be a vector?

Compiling with gfortran - gcc v. 8.3.0-6 (Debian) via gfortran -ffree-form -c module_test.f -o test.o.


Solution

  • Dummy arguments, also called function parameters in other programming languages, must be declared inside the function or subroutine.

    Also, the argument list (the argument names in the parentheses after the subroutine name) should not contain any additional parentheses.

    module test
      implicit none
    
    contains
    
      subroutine sumsize(x,su,si)    
        real,  intent(in) :: x(:)
        real, intent(out) :: su, si
    
        su=sum(x(:))
        si=size(x(:))
      end subroutine
    end module
    

    Also, you typically do not want the dummy argument to be allocatable. That is normally used when the array is allocated or deallocated inside the subroutine or if you want to allow working with an unallocated array.

    program test
      implicit none
    
      real, allocatable :: main_x(:)
      real :: main_su, main_si
    
      allocate(main_x(3))
      main_x(:) = (/1,2,3/)
    
      call  sumsize(main_x, main_su, main_si)
    end program
    

    I renamed the variables with the main_prefix. It is not needed, it is just to make clear that they are distinct from the names inside the subroutine.