Looper
Looper

Reputation: 364

Fortran: parameters/variables in external file

I have several programs that use the same block of code at the begining, but do different stuff. Is it possible to declare this block of code in an external file (fortran file or text file) so if I want to change one part of this code (in the block I'm talking about) I don't have to change it in every program?

Example: Two programs MAIN1 and MAIN2 that do different operations with the vector X generated in an external file.

PROGRAM MAIN1
  IMPLICIT NONE
  ! External block here
  REAL, PARAMETER :: M = REAL(N)*2.0
  INTEGER         :: i
  REAL            :: Out1
  Out1 = 0.0
  DO i = 1,SIZE(X,1)
     Out1 = Out1+M*X(i)
  END DO
  PRINT *, Out1
END PROGRAM MAIN1


PROGRAM MAIN2
  IMPLICIT NONE
  ! External block here
  REAL, PARAMETER :: M = 1.0
  INTEGER         :: i
  REAL            :: Out2
  Out1 = 1.0
  DO i = 1,SIZE(X,1)
     Out2 = Out2*M*X(i)
  END DO
  PRINT *, Out2
END PROGRAM MAIN2

And this is the external code:

INTEGER,PARAMETER :: N = 5
REAL              :: X(N)
CALL RANDOM_NUMBER(X)

I tried putting the external code in a module, but I cannot call subroutines in this way (as I understand that all the lines should be of the type INTEGER,PARAMETER :: N = 5) if want want to call the external block right after the IMPLICIT NONE statement.

Any ideas?

Upvotes: 1

Views: 694

Answers (1)

francescalus
francescalus

Reputation: 32451

What you seem to want to do is not possible without some form of restructuring. The reason for this is that the line

call random_number(x)

is an executable statement. Such a line must follow all declarations. A single literal text replacement (such as by an include statement) is therefore not allowed.

That said, a module is a viable approach: it just requires separating declarations and executable statements.

module shared
  implicit none

  integer, parameter :: N=5
  real x(N)

contains

  subroutine setup
    call random_number(x)
  end subroutine

end module

program main1
  use shared    ! Note _before_ implicit
  implicit none

  real, parameter :: M=REAL(N)*2
  integer i
  real Out1

  call setup    ! Executable, after declarations.

  Out1 = 0.0

  do i = 1,SIZE(x,1)
    Out1 = Out1+M*X(i)
  end do
  print *, Out1

end program main1

[An alternative is to have two distinct literal text insertions. Even worse, but reducing to a single insertion, would be use of block constructs - I'm not going to show that nastiness.]

Upvotes: 1

Related Questions