Monday, May 6, 2013

Of Fortran and Physicists: Part III

Part I: The Trinity of Physics Research
Part II: Why Fortran?


Part III:
Fun with Fortran

As I mentioned in Part II, Fortran is like that old man that lives next door who only comes out of the house on Sunday mornings to get the paper, but still manages to yell at all the kids as they walk across his lawn. The only real reason you should learn it is if you intend to perform computational research. Still, there are definitely some nifty features to the language. 

In Fortran, certain files or functions are assigned unit numbers and remain constant for at least some length of the code. These numbers can be assigned within the first 5 spaces of every line. In addition, certain units like 5 (keyboard input) and 0 or 6 (screen output) are constant for every program. As far as formatting, both ! and C comment out material.  It is also bad practive to allow any line of Fortran code to exceed 75 spaces (this is because an older compiler would not compile correctly otherwise). Because Fortran is used primarily for computational code, it is good practice to define the type of all values in the upper portion of your code, such as REAL*8 or INTEGER.

Because Fortran has been steadily advancing since its incarnation, there are subtle differences in syntax between the different years. That being said, the compiler for Fortran 66 might not work with your Fortran 2003 code. I have been saving all of my files as a ".f90" extension and compiling them with the gfortran command. For any of you who do not remember, gfortran will compile your code into an executable binary file to be used like so:

gfortran hello_world.f90 -o hello_world
./hello_world
That being said, I feel we can now move on to actual Fortran code. The following is a re-write of the "hello world" code.
! Define Program Intent
! Declare Variables
! Author, Date
!
! Possible Bug Fixes Since Last Update
!
!
      write (*,*) "hello world!"
      end
Prints:
hello world!
Note the use of the WRITE function. This, quite literally writes the phrase to it's output, the screen. The (*,*) can be translated as the following: (default object, unformatted length). In other words, the WRITE function defaults to the value of 0, the screen, and allows you to print whatever you feel like because there is no format to the data. Note that the PRINT function could have been used just as well. The READ function is essentially the opposite of the WRITE function. The following is an example of them together:
! Define Program Intent
! Declare Variables
! Author, Date
!
! Possible Bug Fixes Since Last Update
!
!
      IMPLICIT NONE
      character(len=32) :: name
!
      write (0,*) "Please enter name here: "
      read (5,*) name
      write (0,*) "Hello ", name
!
      end
With the keyboard input "Leios," the output is:
Hello Leios
You may have noticed the "IMPLICIT NONE" variable tag, along with the character tag for the "name" variable. Fortran is not case sensitive, so there was no need for me to capitalize the entire "IMPLICIT NONE" phrase (except for emphasis). If we had not specified that the "name" variable as a series of characters with a length no greater than 32 (that's the "(len=32)" tag), the compiler would have assumed that the variable "name" had an integer value or no value at all. Additionally, rather than allowing Fortran to use it's default settings for reading and writing, I added in 0 for the screen and 5 for the keyboard to show that default settings are not the only options. 

As the final Fortran trick of this post, I would like to explain the use of "subroutines." Subroutines are functions defined and called upon in the code. Interestingly, they can be placed anywhere within the code. In the following example, we find the average of two numbers using the subroutine "takeaverage."
!
!     Purpose: Take average of two real numbers
!     Variable: aver, real1, real2
!
!     Author Leios, May 2013
!
      real*8 :: aver, real1, real2
!
      write(*,*) "Enter first real number: "
      read(*,*) real1
      write(*,*) "Enter second real number: "
      read(*,*) real2
!
      call takeaverage(real1, real2, aver)
!
      print *, aver
      end
!
      subroutine takeaverage(reala, realb, avera)
      implicit none
      real*8 :: reala, realb, avera
      avera = (reala + realb)/2.000
With the inputs of 3 and 7, the output was:
  5.0000000000000000 
In my opinion, this is kind of cool. Following the file from top to bottom, it would seem as if we took the average of the two numbers after their average was printed on the screen. Actually, though, a subroutine is a "program within a program" that allows us to better organize our work and perform general tasks that can be called upon for any other function in the file. In this case, we defined completely different real numbers in the subroutine than in the primary function, thus giving us the option to write multiple functions in the same file that call upon that subroutine.

Well, that's all for today, but there is definitely more to learn about Fortran! I will try to use another day in the future to go over more complicated functions in Fortran such as do loops and dynamically allocatable arrays. All in all, the more I use this language, the more I like it as a computational tool. If you ever want to do computational research and your research group does not have a preference to the language you use, definitely take a look at Fortran!

Until next time,
Leios

No comments:

Post a Comment