Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FORTRAN 95: OPTIONAL statement does not work (using FTN95 and Plato)

I am having a problem with the OPTIONAL statement in functions and subroutines with Fortran 95. Currently I am using Silverfrost's Plato and their FTN95 compiler (in "Release Win32" mode). After trying to implement the OPTIONAL statement in a more complex program I am writing, I created a very simple program to test it. Here is the code:

program TEST

implicit none
integer :: a=1, b=2

call Z(a,b)
call Z(a)
call Z(b)

end program TEST

subroutine Z(x,y)
implicit none
integer :: x
integer, optional :: y

if (present(y)) then
  write(*,*) x, y
  else
    write(*,*) x
endif

end subroutine Z

I expected the following result displayed on the screen:

1 2
1
2

Well, the code compiles, although I get a warning (673) that "SUBROUTINE Z has been called with too few arguments". After executing it, I get on my screen:

1 2

and then an "Access violation" error message. Can somebody understand what is wrong here?

Thanks a lot! Gilberto

like image 781
gilbertohasnofb Avatar asked Dec 21 '22 01:12

gilbertohasnofb


2 Answers

Try putting the subroutine in a module, like so:

module testoptional
contains
    subroutine Z(x,y)
    implicit none
    integer :: x
    integer, optional :: y

    if (present(y)) then
      write(*,*) x, y
      else
        write(*,*) x
    endif

    end subroutine Z
end module testoptional

program TEST
    use testoptional
    implicit none
    integer :: a=1, b=2

    call Z(a,b)
    call Z(a)
    call Z(b)

end program TEST

Compiling and running then gives the expected result using gfortran and ifort.

The problem is in how the main program knows (or guesses) the interface to Z(x,y). In the code you provide, although the main program and the subroutine are in the same file, there's nothing explicitly telling the main program the interface - the calling sequence, including argument counts, types, etc - of Z. The first call is to Z(a,b), so it infers there's a subroutine out there somewhere that takes two parameters; then it tries calling it with one parameter, which fails.

Putting the subroutine in a module, then using the module (you could also use contains for a contained subroutine, or explicitly/manually providing the main program the interface using an interface block) then gives the main program the information it needs about the calling sequence - e.g., that there's an optional argument - and things work correctly.

like image 72
Jonathan Dursi Avatar answered Jan 13 '23 12:01

Jonathan Dursi


Procedures with optional arguments must have explicit interfaces, so try giving one to Z. (E.g. just use the subroutine from a short module.)

I don't have this specific compiler on hand, but I've gotten an error when using the Cray compiler for cases like this.

like image 20
Sean Patrick Santos Avatar answered Jan 13 '23 12:01

Sean Patrick Santos