Numerical Integration and Differentiation

Assignment :

Read Chpt 15, Chpt. 18.8, Finish Hw11 and Start Hw12

New Fortran:

COMMON (blank and named), BLOCKDATA, INCLUDE

Numerical integration and differentiation are another set of topics that I've relegated to a Postscript file, because of the number of equations involved in illustrating the processes. You can look at some examples of the Trapezoidal rule for integration in trapezoid.f, trapz1.f, and trapz2.f. trapz1.f needs the files trapcom.h and trapcom1.h to compile properly. You can get all of these files by typing:

cp ~jhm/201/integrate/* .

These examples have been programmed to illustrate two other ways (besides argument lists) to pass information between program units (main program, subroutines, and functions. The first is the COMMON block, and the second the Fortran 90 MODULE structure. Both establish variable names (addresses in memory) that more than one program unit can use.


A COMMON block (see trapezoid.f ) is an old but useful feature in Fortran for letting subprograms communicate information. In its simplest form, blank COMMON, the statement name is followed immediately by a list of variables. If the same statement is repeated in different program units, all will agree on the memory location for any listed variables in the order that they are listed. A change in value of one of the listed variables, will be seen by all program units containing that COMMON statement. For example the following program:

      program test
      common a,b,c
      call sub1
      call sub2
      subroutine sub1
      common a,b,c
      c = a + b
      subroutine sub2
      common a,b,c
      print *, 'c = ', c
will correctly print out a value of three. The main program and two subroutines all agree on the locations for "a", "b", and "c."

One thing should be noticed in this example for those of you who like shortcuts. You might be tempted to replace the common statement in "sub2" with "common c". The result of this replacement would be for the program to print a value of one. As with argument lists, its really order that counts in the variable list for a COMMON block. For this example, the main program, and two subroutines all agree that the first variable name (whatever it may be) listed after the first occurrence of "COMMON" always refers to the same address in memory. The second variable listed after "COMMON" refers to the next address in memory after the space occupied by the first variable, and so on through the last listed variable. Although you can use this order dependency of COMMON to let different subroutines use different names for the same quantity (location), this leads to very unreadable code, and should be avoided. Use identical copies of blank COMMON (or named COMMON), when communicating information.

You may have noticed that I was careful in the last paragraph to refer to the "first occurrence" of COMMON. You are permitted to put multiple blank COMMON statements in a program unit. However, you are not really creating separate COMMON blocks. There can be only one blank COMMON in a program, and multiple COMMON statements just act to extend the length of the single blank COMMON. For example, writing the following two statements:

      common a,b,c
      common x,y,z
is exactly equivalent to writing

      common a,b,c,x,y,z 
Having just one COMMON can be fairly constraining, so Fortran also permits named COMMON blocks. The name of the common block immediately follows "COMMON" and is always delimited by "/". Examples of named COMMON are:

      common/intvar/ i,j,k
      common/miscvar/ x1,i1,y1,j1,z1,k1 
The name of the common block is arbitrary and you do not declare its type in a REAL or INTEGER statement. A COMMON may contain variables of any type, and mixtures of different types. However, if you mix data types, you must be a little cautious. Most computers want double precision real variables to begin at even multiples of the double precision word length. If "x1" and "y1" are 64 bit real numbers, and "i1" is a 32 bit integer in the above example, the even 64 bit spacing for the real numbers is broken, and trouble can result. Whenever possible segregate variables into different named COMMONs by type. When not possible (for example blank COMMON), list all of your REAL variables before listing any INTEGER or CHARACTER variables.

So why do we bother to have both blank and named COMMON? The reason is memory assignment. You should recall that when a program is compiled, space is generally reserved for all variables within the resulting executable file. One exception to this rule that we have already seen is the use of ALLOCATABLE arrays. Space for such arrays is not assigned until the program is running and requests a specific size for the array. This is very important for major scientific and engineering applications where arrays can occupy tens to hundreds of megabytes. However, ALLOCATABLE is a recent (Fortran 90) invention. Originally blank COMMON filled this need. Space for any variable listed in blank COMMON is not assigned until the program starts to execute. This last minute allocation of space, has one important side effect. You can not initialize values for any variable in blank COMMON with a DATA statement. There is no place in the executable file to store the initial value.

In addition to providing more convenient grouping of variables, named COMMON fills the need for COMMON variables that should be initialized with a DATA statement. Unless a special (nonstandard) compiler option is used, memory for named COMMONs is reserved in the executable file. However, a potential for significant confusion exists. With the named COMMON appearing in many subprograms (and perhaps not in the main program at all), where are you going to put the DATA statement? The Fortran standard saves you the decision by not letting you put it in any standard program unit. You must create a special BLOCKDATA subprogram to hold the DATA statements. Here is an example of one such routine, that I've chosen to name DATA1 (name is up to you as are any names chosen for named common blocks).

      blockdata  data1
      common/dtdata/ dt,dt1,dt2
      common/dxdata/ dx,dx1,dx2
      real dt,dt1,dt2
      real dx, dx1,dx2
      data dt,dt1,dt2/.01.001,.0001/,dx,dx1,dx2/.1,.2,.3/
You can create more than one such subprogram, located anywhere in your program. Usually, BLOCKDATAs are placed immediately after the main program, if the full program is contained in a single file. A BLOCKDATA routine is by its nature non-executable. It generally contains only the BLOCKDATA, END, COMMON, DATA, and type statements, but can also contain EQUIVALENCE, PARAMETER, IMPLICIT, and USE (see below).

I mentioned the value of blank COMMON for storing arrays, but haven't said anything about the interaction of COMMON (both blank and named) with the process of array declaration. Based on your current experience you might guess one approach.

      real a(10000), b(10000), c(10), d, e
      common a, b
However, you can also set the dimension in the COMMON statements.

      real a, b, c, d, e
      common a(10000), b(10000)

Either form has the same effect. Given that COMMON establishes a specific memory layout, I prefer the second form, giving the full details of the storage in one location.

One final note on mechanical details of named COMMON. Occasions may arise where the contents of a COMMON are lost. Suppose the main program calls SUBROUTINE A, and SUBROUTINE A calls SUBROUTINE B (but MAIN doesn't call B), and a COMMON named VAL is in A and B but not main. When A returns to MAIN, the Fortran 90 standard doesn't guarantee that the contents of VAL will be preserved for the next call to A. The best way to guarantee the contents of VAL won't disappear is to include a "COMMON/VAL/..." in the main program, even if none of the variables in VAL are used in MAIN. Another way is to use the SAVE statement. Both A and B must include the statement:

      save /val/
Important features of COMMON

While we are on the subject of COMMON blocks, I want to give another example of the value of EQUIVALENCE statements. Often in large programming applications you need to write the contents of all significant system variables including entire common blocks to a disk file for later continuation of your calculation. This is called a restart dump. Why bother? If you get 4 days into a 5 day long computer calculation and the machine crashes, you will suddenly appreciate the value of these restart dumps. Instead of starting the whole thing from scratch, you can pick up the last restart dump to continue with a relatively small loss of time. These dumps are also useful when running a large number of parametric calculations with a common starting point at the end of a long initialization calculation.

The task is simplified with the coding like this:

COMMON/CONTROL/DELT,DXB,DXA,XGB,YCOM,ZCOM,RDTA,XXA REAL CONTA(8) EQUIVALENCE (DELT,CONTA(1)) WRITE(11) CONTA So what? The example is greatly simplified. In real life it is not unusual to have large numbers of variables (>50) in a given named common. This structure makes the write statements cleaner, and easier to maintain if variables are added to the named common. What happened to the format number in the WRITE? This is an example of an unformatted write. The contents of the listed variables are dumped to the disk file attached to unit 11, in exactly the form they have in memory. Here you would send 8 strings of 32 bits to the disk, containing the bit representation of real numbers. They could be read back from disk with "READ(11) CONTA"

Using COMMON and argument lists is a balancing act. Each argument in an argument list generally has an associated cost in computer time to pass the argument address to the subprogram, and long argument lists also carry the burden of making the program more difficult to read. COMMON blocks simply establish a common agreement on variable locations, that is used during creation of the executable code. I can use COMMON variables in subroutines with no additional cost beyond use of local variables. The results of the test program funspeed.f give a little feel for the potential advantage of COMMON. The unoptimized code shows a significant difference between using an argument list and using a COMMON to pass information. This difference widens as more variables need to be passed. However, what is going on with the optimized results? I am passing the same variables in every pass through the DO loop. The compiler is smart enough to know that it only needs to do a single load at the beginning of the DO loop to set the addresses used by the subprogram to locate arguments. Use of argument lists within a DO loop is not always a significant disadvantage. When in doubt on the proper approach run some timing studies. If no major speed advantage is obvious, make your decision based on clarity of your program (could dictate either arguments or COMMON), and on the potential for use of your subprogram in other applications (usually encourages argument lists).


If you get tired of changing copies of COMMON blocks in many different subroutines, you can put a single copy of a COMMON block in its own file. The Unix (C) convention is that the file end with ".h". The contents of the file can be accessed by the compiler by including an INCLUDE statement at the appropriate location (see trapz1.f, trapcom.h and trapcom1.h ). Use of INCLUDE is not restricted to COMMON blocks. It is useful anytime you have a block of code that appears unaltered in more that one location in the program.


Discussion of COMMON blocks and the INCLUDE statement has been postponed because you obtained these basic capabilities early in the class from the combination of the MODULE and USE statements. The only capability of COMMON missing in a MODULE is the ability to force data to reside in machine memory in a specific order.

A MODULE has one major feature not available in COMMON blocks. Unlike COMMON, you can include ALLOCATABLE arrays in MODULES. In doing so you have the ability to allocate an array in one subroutine for use in others (see module.f.) MODULES also make it more convient to provide internal subprograms to program units than is possible with an INCLUDE statement. A single MODULE permits typing of variables and definition of internal subprograms. The same job would require two INCLUDEs.. When you get to the point of building internal functions, you may want to learn about the PUBLIC and PRIVATE statements.

My primary purpose in introducing COMMON blocks has been to prepare you to work with older FORTRAN programs. Unless you have a strong need to control the memory layout of your variables, you should stick with MODULE and USE statements in your own programs.

Up one level / Home

Written and Maintained by John Mahaffy :