Fundamentals of Fortran, Programming Principles


Assignment :

Read Chapts. 2 &3 in your Text, and my discussion of Assignment statements.

New Fortran:

PROGRAM, SUBROUTINE, CALL, MODULE, USE, STOP, RETURN, END, READ, PRINT, REAL

The first principle of programming

You won't learn how to program without doing it.

Take the time to not only do your homework, but also to type in examples of all programming constructs to check your understanding of their behavior. The best way to learn a language construct is to:

  1. Read about it in these notes or your text;
  2. Form an idea of how the construct works;.
  3. Write a brief program that tests your idea;
  4. Check to see if the program results match your expectations; and
  5. If unexpected results occur, modify your understanding of the construct and try another test, or get help from another programmer.

Creating and Modifying Programs

My current (6/2013) recommendation is to create programs within Microsoft Visual Studio.  The editor is very good and linkage to a compiler like Intel Fortran and use of the Visual Studio debugger makes this the best development environment that I've found.  For those looking for a free alternative jEdit is an excellent choice for an editor to develop source code and the Code::Blocks development environment is also worth at look.

Compiling Your Program

The CPU of a computer hasn't a clue what to do with Fortran instructions in a text file. You must convert the contents of the Fortran text file to an executable file containing machine instructions recognized by the CPU. Note that the content and range of machine instructions varies wildly from one brand of computer CPU to another. Instructions recognized by an Intel chip will not be recognized by a Sun SPARC chip. One of the beauties of languages like Fortran, is that they are largely independent of the computer on which they are applied. Each machine has its own special program, called a compiler, that translates the Fortran program into the appropriate set of its own machine instructions.

If you can afford it, Intel Fortran is a good choice, as are Absoft, Lahey and Portland compilers.  For those in need of something free take a look and GFortran or g95 (and their integration into Code::Blocks).

A word on Standard Versions of Fortran

Scientists like to wander around quite a bit, but don't like to rewrite programs every time they visit some place with a different computer. National and International standards are just rules for the people who write and use compilers, so that everyone knows what a computer will do in response to various well defined statements and language structures. The standards for Fortran have been established at several points in time by the X3J3 subcommittee of the American National Standards Institute (ANSI). The process of establishing a standard for the language involves many years of negotiation between various groups of users and vendors of hardware and software. The first such standard for Fortran was .issued in 1966, and was significantly improved with the 1978 release of Fortran 77 (particularly with respect to representing and manipulating character data). The most recent standard is Fortran 2008, which includes significant extensions for dealing with more complex data structures, and for performing scientific calculations involving heavy use of arrays (vectors and matrices) of numbers. This class material dates to Fortran 90 which is a subset of all subsequent Fortran standards available on all Fortran compilers.

Nothing from Fortran 77 has been dropped from Fortran 90. It forms the core of the new version of the language. For this reason, and because you will need to be competent in Fortran 77 to utilize the enormous body of existing Fortran 77 applications, we will concentrate on learning this core of Fortran Statements. Most useful Fortran 90 features will also be introduced, but the entire language will not be covered.

Rules on the Format of Fortran Statements

To understand the basic rules of where you can and can't type things in a line of Fortran, you need to know something about how we entered programs and data back in the stone age. Each "record" of a program or data deck (translate that to line of a text file) was contained on a single 7 3/8" by 3 1/4" computer card. A character or number was represented by a unique combination of holes in a column on the card. Each column was aligned along the narrow dimension of the card, and a total of 80 columns fit across the wide dimension of the card. As a result, most Fortran compilers by default ignore anything past the 80th character position in a line. However, this can usually be over-ridden with compiler options.

Depending on the size of your program and data, the necessary cards were held in a box or bound together with a rubber band for storage. To execute the program the rubber band was removed, or cards removed from the box, and the deck was placed in the input tray of a card reader. From time to time the programmer or computer operator would get clumsy, or a rubber band would break and the cards would be spread across the floor. To ease recovery from such situations, it was decided very early in the history of electronic computing, that some of the columns on the card should be reserved for storing a card sequence number. Card sorters already existed that could use this number to unscramble a deck. For Fortran 77 (and earlier standards) the last 8 columns were reserved for a card identifier. This was more than enough for any program or data deck length, giving room for other useful identification such as the owner's initials or some other meaningful abbreviation.

So far we have restricted the length of a standard Fortran statement to 72 characters. However, there is more. As you may recall from the second lecture, one of the basic instructions that a computer can perform is to branch around the next instruction in memory to another instruction elsewhere in memory. A means was needed within Fortran to uniquely label statements that are the targets of branches. The card sequence identifier was inadequate, because you wanted to redo these sequence identifiers as your program expanded, but you didn't want to change Fortran statements that contained branch instructions. The result of this need was to reserve the first 5 columns for holding Fortran statement labels. Here is an example of the use of such labels, preceded by two lines to give you an idea of character positions within the line.

c        1         2        3          4         5  
c2345678901234567890123456789012345678901234567890
if(i.gt.1) go to 100
x=1.0
go to 200
100 x = 2.0
200 y=2*x
This is a very poorly structured piece of Fortran by the way, but we'll learn about that later. If you look carefully at the example, you may notice a couple of odd features. First, I was fairly careless with the use of spaces. This is because Fortran largely ignores spaces, so I am free to use them to improve the way my code looks. You may also notice that I never got down to the serious business of writing a Fortran statement (as opposed to statement label) until at least column 7. The reason here was not simply neatness. At some point during this course you will realize that you can't type everything you want in some of your Fortran statements before bumping into column 72. You need some way to tell the Fortran compiler that you are continuing the statement on the next line. The Fortran convention for permitting statements to span more than one card is to put any character in the 6th column of any card (line) beyond the first of a continued statement.

These conventions for leaving the 6th column blank (unless you are continuing a statement), and fitting everything within the first 72 columns are the single largest source of suffering by beginning programmers. If you inadvertently type your statement past the 72nd column, Fortran will ignore everything that you have entered in columns 73 and beyond. This can result in a syntax error message from the compiler (the structure of your Fortran statement doesn't make sense to the compiler), but you will stare at that line in your program and see nothing wrong. Worse yet, you may type your statement in such a way that losing the characters beyond column 72 will not be detected as a syntax error but will give you incorrect results.

Similar problems occur with column 6. If you inadvertently start a statement before column 7, it almost always places a character in column 6. This causes the line to be considered as a continuation of the previous one, and usually (but not always) results in a syntax error. If the statement starts before column 7, but has a blank in column 6, you will receive a syntax error complaining about a bad line label.

One final note on the above example. You may have noticed that I started my two column counting lines with a "c" rather than a "1". This is because they were meant to be contained within the program itself as markers. By placing "c" in column 1, I've told Fortran that the line is a comment and not a regular Fortran statement. The compiler ignores the line. You also have the option of using "C" or "*" in column 1 to designate a comment. Use comments generously in your program to describe its contents. This will assure you of better grades on your homework assignments. However, it has a far more important purpose. Unless your memory is exceptional, you will find that 6 months after you have written a program, you will have trouble understanding the variables and intent of the program. Comments make the job of modifying your program for another task much easier. Use of comments can also be important in a work setting. If someone considers a program important enough to pay you to write it, then it is almost always important enough to be checked by another programmer, and kept for later refinements. Poor internal documentation hampers both validation and later modification, and, hence, could adversely affect your professional standing and salary.

I have provided some examples of pit-falls associated with column position errors in the program errors.f. The results of compiling it on a Hammond Lab, IBM Workstation follow.

h22.26> f77 errors.f
"errors.f", line 8.0: 1515-010 (S) String is missing a closing delimiter.
Closing delimiter assumed at end of line.
"errors.f", line 9.16: 1515-022 (S) Syntax Error: Extra token " 'This
statement is OK, but tripped up by the next one " was found. The token is
ignored.
"errors.f", line 11.5: 1515-017 (S) Label contains characters that are not
permitted. Label is ignored.
"errors.f", line 11.7: 1515-019 (S) Syntax is incorrect.
** errors === End of Compilation 1 ===
1501-511 Compilation failed for file errors.f.
When the compiler output refers to "line 11.5", it is saying that it found an error in the 11th line of your file near the 5th column of that line. I've found, that one easy way to use this information in an XWindows session, is to start vi in a second window, opening the program file. Here I would click my left mouse button over a second window and type "vi errors.f". I can place my cursor in the 11th line by typing ":11", then inspect the region near the 5th column.

Fortran 90 Free Format

Fortran 90 permits a more flexible free format. This is the default format for current compilers particularly for files with a .f90 suffix. It is not compatible with the old fixed format because of changes in how comments are flagged and statements are continued.

A program statement can be up to 132 characters long (including blanks) and may start at any position in the line. The statement can span more than one line simply by placing an ampersand (&) at the end of the line to be continued. There are instances where you don't want to introduce blanks into the actual statement through the process of continuation. The best way to handle this is to use an ampersand as the first non-blank character in the continuation line. The compiler appends whatever follows this ampersand directly to whatever preceded the ampersand ending the previous line. The statement

        if (x.gt.0) print *, ' The value &
&of x is', x
is equivalent to

        if (x.gt.0) print *, ' The value of x is', x
but

        if (x.gt.0) print *, ' The value &
of x is', x
is valid but equivalent to

        if (x.gt.0) print *, ' The value           of x is', x
(note the extra blanks).

Comments must begin with an exclamation point (!). They can stand alone in a line or be placed at the end of a line containing a regular Fortran statement (but not after an ampersand used for line continuation).

! This is a Comment

x = a + b ! Add a to b, is also a valid in line comment

A First Program

The first step in creating or modifying a program is to write what you are going to do in plain English. For this example, I am going to ask the program user to type in 2 numbers. I will read these numbers into program variables, add them together, and finally print the result.

In general you need to state:

  1. What are the desired program results (problem output);
  2. What you already know (problem input, defining equations, and parameters);
  3. How you are going to get the desired results from existing knowledge (solution method).
With this done you should define variable names that correspond to your existing and desired information, then proceed to generate statements to implement the solution procedure.

From here, the program can take on any one of several different forms. I'll provide you with two approaches. The first is a fairly standard way to write this simple program. However, it teaches you some bad habits, so I'll also demonstrate a modular approach to the problem, that is more characteristic of the way the you should generally approach programming.

Read my description of the simple form of the program to get a concise description of the basic Fortran statements needed to accomplish the addition task. Next, read the description of the modular form of the program, showing a more standard method of allocating distinct sub-tasks to separate program units. The class lecture will focus on the modular approach to the program, since my primary purpose here is to introduce programming practices. We will focus on details of Fortran statements in subsequent lectures.

In practice, when I have to do a very simple calculation with a Fortran program, I use a layout similar to that of the simple form of this example. In fact, 99% of the time when I have a simple calculational task that will need to do more than once or twice in my life, I create a spreadsheet, or script for MathCad, or Mathematica, because calculational time is not important, but my time is. I generate Fortran programs when calculations and data processing are lengthy enough that the modular form is the most appropriate way to minimize my time debugging the program initially and understanding and modifying it later.

Unfortunately, I can't give you any firm guidelines on when to use spreadsheets, a mathematics program, or a programming language such as Fortran. You need to pay attention to your own work habits and competency with each of these classes of tools, to develop your own rules. You also need to make some educated guesses about how frequently you will repeat the calculation in the future, and you will need to gage the amount of time that the calculation will require to execute on a computer (some of my calculations run for days).

Take the time to look at the examples "add.f90" and add2.f. Save these files on your local file space, (I recommend making a subdirectory called "examples" to store these and other such files), then compile and execute the programs.


Exercises

  1. Convert my examples to programs that multiply two numbers together. First copy "add.f" to "mult.f". Next, replace "+" with "*" in the assignment statement. Change the variable "s" to "p" (for product) wherever it occurs. Finally, make all necessary changes to text in print statements, and to comments.
  2. Knowing that the sample computer card is a FORTRAN comment, what is the full text of this comment?

Up one level / Home


Authored and Maintained by John Mahaffy : jhm@psu.edu