# 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.

## COMMON

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
a=1.
b=2.
call sub1
call sub2
stop
end
subroutine sub1
common a,b,c
c = a + b
return
end
subroutine sub2
common a,b,c
print *, 'c = ', c
return
end
```
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/realvar/x,y,z
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/
end
```
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
common/other/c,d,e
```
However, you can also set the dimension in the COMMON statements.

```      real a, b, c, d, e
common a(10000), b(10000)
common/other/c(10),d,e
```

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

• The order of variables in a common block determines the order of their locations in memory
• Mixing integers and character variables with reals in common can cause compiler complaints, and possible inefficiencies. 32 bit machines want to align double precision real numbers on even word boundaries, and character variables can end on any byte.
• Blank COMMON does not claim space until execution begins, so there is nowhere to initialize variable values with a DATA statement.
• You can use named COMMON to give same information passing features and control of memory order, plus the ability to initialize with DATA statements. However, DATA statements must reside in one special place called a BLOCK DATA routine.
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"

## INCLUDE

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.

## MODULEs

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 : jhm@cac.psu.edu