computing‎ > ‎

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