Subroutines can call other subroutines.
various declarations statements
:
:
executable statements
:
RETURN
END
Communication:1) Arguments: The arguments in a subroutine transfer the memory addresses of the variables from the calling statement to the subroutine and vice versa. In Fortran actual variable values are not transferred!! This is known as ‘pass by address’, i.e. subroutines use call by reference, not call by value. The arguments are pointers to addresses that contain the desired value.
2) COMMON statements: COMMON statements assign a variable or variables to a block of shared memory. This memory is accessed by every program or subroutine that contains the COMMON block. COMMON blocks have the form:
COMMON/NAME/VAR1, VAR2, VAR3
where:
NAME is the name of the COMMON block.
VAR1, VAR2, VAR3 are the variables that define the memory that is being
shared in the COMMON block.
Example of call by reference:
CALL GETXY (X(3), 2, Z)
The values of X(3), 2, and Z are NOT passed but the addresses in memory for X(3), 2, and Z are passed to the subroutine GETXY. The use of ‘2’ is dangerous in that it may be redefined to some other value associated with that address. All further uses of ‘2’ in the program may then have a strange value.
Call by reference is very useful for many applications. A simple example for filters and moving averages is:
NX=5
DO J=1,10
CALL GETXY (X(J), NX, Z(J))
END DO
The subroutine will look at successive addresses of array X:
J=1 – calling program
X(1), X(2), X(3), X(4), X(5) – subroutine
J = 2 – calling program
X(2), X(3), X(4), X(5), X(6) – subroutine
etc.
Dimensions:Example:
In the main program, we declare the arrays:
PARAMETER (N=100)
REAL X(N), Z(N)
:
:
NX=N
CALL GETXY (X,NX,Z)
Thus, we can declare in the subroutine:
SUBROUTINE GETXY(ARG1, ARG2, ARG3)
REAL ARG1 (*), ARG3 (*)
INTEGER ARG2
or, we can use the same variable names:
SUBROUTINE GETXY(X,NX,Z)
REAL X(*), Z(*)
INTEGER NX
Function:1) one or more arguments just like a subroutine;
2) it itself has a value which is returned to the program unit that calls the function.
Example:
X = X2 (Y (I))
where:
Y (I) is the argument for the function X2.
Example:
REAL FUNCTION X2 (X)
C This function finds the square of X.
REAL X
X2 = X*X
RETURN
END
There are many ‘intrinsic’ Fortran functions. Some of these are:
EXP, SQRT, SIN, ATAN, ALOG, ALOG10,
MIN, MAX AMIN1, AMAX1, MOD, etc.
Functions can have any of the variable types allowed in Fortran, e.g., LOGICAL, REAL, INTEGER, COMPLEX, etc.
Example:
LOGICAL SEARCH
:
:
if (SEARCH (I, J, K)) then
:
END IF
LOGICAL FUNCTION SEARCH (I, J, K)
INTEGER I, J, K
if (I.EQ.J .AND. J.EQ.K) then
SEARCH = .TRUE.
ELSE
SEARCH = .FALSE.
RETURN
END
c pls 9-7-93
c make data records for use in other programs
c each record will contain up to mx real variables
c x(1 ... mx) real vector for data
integer mx
parameter (mx=1000)
real x(mx)
c nx actual number of variables in each record
c nrecs number of records of data to make
integer nx, nrecs
c file name to save data for future use
character*32 fname
c logical unit number for file
integer ifile
c counters
integer jx, jrec
c bytes/real this machine
integer mbytes
parameter (mbytes=4)
c get the input parameters from the user:
c filename, data values/record, # of records
write(*,*)'enter name of file to store data: '
read(*, '(a32)')fname
write(*,'(a32)')fname
write(* ,'(/)')
write(*,*)'number of data values/record='
read(*,*) nx
write(*,*)nx
write(* ,'(/)')
write(*,*)'number of records to save='
read(*,*) nrecs
write(*,*)nrecs
write(* ,'(/)')
c open the file fname as unformatted, direct access
c logical unit number is ifile=12
ifile=12
open(ifile,file=fname,form='unformatted',status='unknown',
- access='direct',recl=mbytes*nx)
c loop over all nrecs records, jrec=1,...nrecs
c define data, x, as record number, jrec, for jx=1,...nx
c save on file with logical unit number, ifile
do jrec=1,nrecs
do jx=1,nx
x(jx)=float(jrec)
enddo
write(ifile,rec=jrec)(x(jx),jx=1,nx)
enddo
c close file, quit
close(ifile)
stop
end
c pls 9-7-93
c read data records and calculate their mean, post for user
c each record will contain up to mx real variables
c x(1 ... mx) real vector for data
integer mx
parameter (mx=1000)
real x(mx)
c nx actual number of variables in each record
c nrecs number of records of data
integer nx, nrecs
c file name for data to be used
character*32 fname
c logical unit number
integer ifile
c counters
integer jx, jrec
c bytes/real this machine
integer mbytes
parameter (mbytes=4)
c mean value
real xmean
c get the input parameters from the user:
c filename, data values/record, # of records
write(*,*)'enter name of file to read: '
read(*, '(a32)')fname
write(*,'(a32)')fname
write(* ,'(/)')
write(*,*)'number of data values/record='
read(*,*) nx
write(*,*)nx
write(* ,'(/)')
write(*,*)'number of records to read='
read(*,*) nrecs
write(*,*)nrecs
write(* ,'(/)')
c open the file fname as unformatted, direct access
c logical unit=12
ifile=12
open(ifile,file=fname,form='unformatted',status='unknown',
- access='direct',recl=mbytes*nx)
c loop over all nrecs records
c read data get mean
do jrec=1,nrecs
read(ifile,rec=jrec)(x(jx),jx=1,nx)
call mean(x,nx,xmean)
write(*,*)'the mean for record ',jrec,' is',xmean
enddo
c close file, quit
close(ifile)
stop
end
subroutine mean(x,nx,xmean)
real x(*), xmean
integer nx
c for the vector x of length nx
c get the mean value, xmean
c counter jx
integer jx
c initialize xmean as zero
c guard against divide by zero
xmean=0.
if(nx.le.0) return
c sum
do jx=1,nx
xmean=xmean+x(jx)
enddo
c get mean
xmean=xmean/nx
return
end
Internal READs and WRITEs:FORTRAN users can read from and write to character strings in a program. These character strings are known as internal files. In these specialized READs and WRITEs, the Logical Unit Numbers are replaced with character string variables.
Example:
If a user has 20 files in the directory, each named FILE1.DAT, FILE2.DAT, . . . . FILE20.DAT, and he or she wants to open each file to do some processing; the following code below will achieve that result. Note that only one file will be open at a time.
CHARACTER*40 FNAME
CHARACTER*1 CHAR1
CHARACTER*2 CHAR2
INTEGER I
DO I = 1, 20
IF (I.LE.9) THEN
WRIte (char1, 10010) I
fname = ‘file’ // char1// ‘.dat’
else
Write (char2, 10010) i
fname = ‘file’ // char2 // ‘.dat’
endif
open (lun, file = fname, status = ‘old’)
:
(processing)
:
END DO
10010 FORMAT (A)