Search code examples
arraysfortransubroutine

Fortran array mismatch in subroutine but no error?


I have a program that seems to work properly, but I don't understand how it can, because there seems to be an obvious error.

Main program(which use 'implicit') calls a subroutine:

  implicit integer(i-n)
  implicit double precision(a-h,o-y)
  implicit complex*16(z)

            call do_coulomb(zvecs0,zdualvecs0,n_f,n_f,1,
 $           nsubfilling,zcorrmatrix,0,aldet01abs,
 $           zcoulomb,epsilon)

where arrays, 'zvecs0','zdualvecs0','zcorrmatrix' are declared, but there is no declaration of 'nsubfilling' anywhere. (It could be a mistake or remnant of old version.)
Since I could not find any declaration of array 'nsubfilling' in main program ('grep -i nsubfilling *' ), I suppose 'nsubfilling' will be treated as an integer variable.

This is a subroutine of question:

      subroutine do_coulomb(zvecs,zdualvecs,n_A,n_Ap,n_C,
 $     nsubfilling,zcorrmatrix,n1_p0,aldet01abs,
 $     zcoulomb,eps)
  implicit integer(i-n)
  implicit double precision(a-h,o-y)
  implicit complex*16(z)
  include "input.inc"
  dimension zvecs(0:L-1,0:L-1,0:L-1,0:Lt,0:1,0:1,0:n_f-1)
  dimension zdualvecs(0:L-1,0:L-1,0:L-1,0:Lt,0:1,0:1,0:n_f-1)
  dimension nsubfilling(0:n_Ap-1,0:n_C-1)
  dimension zcorrmatrix(0:n_Ap-1,0:n_Ap-1)

('L' 'Lt' are defined in the "input.inc" file.) Because 'nsubfilling' is defined as an array in the subroutine, I thought the mismatch between main and subroutine would cause an error.
However, the program seems to run okay even with mismatch.

I tried to print out some variables.('n_f'=4,'n_c'=1 in this run) This is the output:

 Before 1st call in main:
 nsubfilling=           1
 zcorrmatrix(0,0)=     (20.510951695209510,0.13579118691198364)
 zcorrmatrix(0,1)=     (-1.0490102491588316,0.59453967445518319)
 zcorrmatrix(1,0)=     (-1.3791781667351797,-0.26247624491732802)
 zcorrmatrix(n_f-1,n_f-1)= (20.510951695209513,-0.13579118691198364)

 Inside do_coulomb subroutine:
 nsubfilling=           1           0           1           1
 zcorrmatrix(0,0)=       (20.510951695209510,0.13579118691198364)
 zcorrmatrix(0,1)=       (-1.0490102491588316,0.59453967445518319)
 zcorrmatrix(1,0)=       (-1.3791781667351797,-0.26247624491732802)
 zcorrmatrix(n_f-1,n_f-1)=  (20.510951695209513,-0.13579118691198364)
 n1p0=           0

 After 1st call in main:
 nsubfilling=           1
 zcorrmatrix(0,0)=       (20.510951695209510,0.13579118691198364)
 zcorrmatrix(0,1)=       (-1.0490102491588316,0.59453967445518319)
 zcorrmatrix(1,0)=       (-1.3791781667351797,-0.26247624491732802)
 zcorrmatrix(n_f-1,n_f-1)= (20.510951695209513,-0.13579118691198364)

The output shows that 'nsubfilling' is treated as an integer in main routine, but considered as an array in the subroutine and also the subroutine recognizes 'zcorrmatrix' correctly even with mismatch.

But, how this can be possible? I think there should be an error.
Could you let me understand how it work?

Thank you.


Solution

  • The main program does not have an explicit interface to subroutine do_coulomb. This means that the main program cannot check at compilation time whether the ranks of the actual arguments in the main program match the ranks of the dummy arguments in the subroutine.

    An explicit interface can be provided in a number of ways:

    • having subroutine do_coulomb as an internal subprogram of the main program (subroutine after main subprogram, after a CONTAINS statement and before the END statement of the main program), this is called host association;

    • via an interface block in the main program (provide name of subroutine, list of dummy arguments, their types and attributes); or

    • by including the subroutine inside of a module (foo) and adding a use statement (use module foo) before the implicit declarations, this is called use association.

    Why is your program not crashing? Well, because subroutine do_coulomb thinks it has access to a chunk of memory corresponding to nsubfilling of the size specified inside of the subroutine, and it happens to not do anything otherwise illegal when manipulating it - the chunk of memory happens to be in use by the same application. If the declared size of nsubfilling was very very big, and/or you had fewer arrays declared, it is likely that access to nsubfilling led to a segmentation fault.

    Note that, even if you have an explicit interface, the ranks and the dimensions may not match - and that can be legal, as long as the total size of the dummy argument in the subroutine is not larger than the total size of the actual argument in the main program.