Fortran tips and tricks
* [[http://www.yolinux.com/TUTORIALS/LinuxTutorialMixingFortranAndC.html|Using C/C++ and fortran together]]
* [[http://www.fortran.com/ibm.html|IBM fortran manual]]
* [[http://www.cs.rpi.edu/~szymansk/OOF90/bugs.html | Mistakes in Fortran 90 Programs That Might Surprise You]]
* [[http://www.nicdan.id.au/computers/compiling/recompile.html | Avoiding the Unnecessary Recompilation of Fortran 90 Modules]]
Fortran compilers
There are several free fortran compilers available now. GCC has a sufficiently good compiler called [[http://gcc.gnu.org/fortran/|gfortran]]. Another free compiler is [[http://www.g95.org|g95]] which is the work of Andy Vaught. If you are using Linux then the ifort compiler from Intel is also free for non-commercial use, and probably the best choice on Intel machines.
Passing a function to a subroutine
You can pass a function as an argument to a subroutine. See the following example with two functions ''f'' and ''g''. The subroutine ''testfunc'' is first called with ''f'' and then with ''g''. Compile and run the code.
program main
implicit real*8 (a-h,o-z)
external f, g
call testfunc(f)
call testfunc(g)
stop
end
subroutine testfunc(func)
implicit real*8 (a-h,o-z)
x=func()
return
end
real*8 function f()
implicit real*8 (a-h,o-z)
print*,"This is function f"
f = 1.0
return
end
real*8 function g()
implicit real*8 (a-h,o-z)
print*,"This is function g"
g = 1.0
return
end
You should get the following output.
This is function f
This is function g
It is important to the declare the functions as external.
Measuring elapsed time
You can find out how long your program has been running by calling the built-in etime() function. This includes only time spent running your program, regardless of what else is running on the same processor. The time is reported in seconds, in three parts:
* User time, time actually spent in your program;
* System time, time spent in the operating system on your program’s behalf; and
* Total time.
To measure elapsed time, declare a real*4 array with two elements, and pass that array as an argument to etime. The first element of the array will be set to the user time, the second element will be set to the system time, and the etime() function will return the total time.
program main
real etime
real elapsed(2)
real total
integer i, j
do i = 1, 5000000
j = j + 1
end do
total = etime(elapsed)
print *, 'End: total=', total, ' user=', elapsed(1),
+ ' system=', elapsed(2)
stop
end
Random numbers
The Fortran rand() always returns a number between 0 and 1. More specifically, it is a number in the half-open interval [0,1), so you might get a 0.0 result, but the result will never be exactly 1.0 or greater. Such a number can be scaled to produce uniformly distributed pseudorandom numbers in any interval.
If you want an integer between m and n inclusive, use the expression:
int(rand(0)*(n+1-m))+m
If you want a real number in the interval [x,y), use this expression:
(rand(0)*(y-x))+x
Getting current time and date
To get the current date and time, declare two arrays of type integer*4, each with three elements. Then call the built-in idate and itime functions to place the day, month, and year into the first array and the hour, minute, and second into the second array:
program when
integer*4 today(3), now(3)
call idate(today) ! today(1)=day, (2)=month, (3)=year
call itime(now) ! now(1)=hour, (2)=minute, (3)=second
write ( *, 10 ) today(2), today(1), today(3), now
10 format ( 'Date ', i2.2, '/', i2.2, '/', i4.4, '; time ',
& i2.2, ':', i2.2, ':', i2.2 )
stop
end
Running this program might produce output something like this:
Date 04/01/1995; time 14:07:40
Reading big-endian, unformatted files
pgf compiler: Open the file using the "convert" option
open(10,file='case1_u.cogsg',form='unformatted',iostat=ios,
& status='old', convert='BIG_ENDIAN')
g95 compiler: This does not seem to accept the "convert" flag. You can use a compile flag as below
g95 -fendian=big convert.f