The class PHZ 6156, computer methods in physics, is about using computers to solve physics problems such as interpolation, integration, transforms, and differential equations. Since computers are constantly evolving and at present there are many different flavors available to members of the physics department, the course concentrates on the lowest common denominator which works with modifications on all computers. More user friendly editors and routines exist and I do not object to their use, but such users will have to be semi-independent.
At the beginning of the course, I hand out a CD containing Watfor. This is Fortran 77 restricted to 640K which was once thought to be the most that anyone would ever need. It is also the best debugger that I have ever found. It is adequate for the course. Openwatcom is an open-source version of the combination Fortran and C compiler that Watcom was working on when it went bankrupt. It contains a reasonably friendly IDE (editor/compiler) and allows a reasonably easy mixing of Fortran and C in windows. It chief virtue is that it is free. The programming part of the course is natural in Unix/Linux. These come with open-source f77 and gcc, and Fortran and C mix easily. Debugging is a little harder than with Watfor and the word processing is not as easy.
To display the results of codes, it is necessary to have plotting routines. On the PC's the locally written GPLOT which is available from the website enables this. On Unix/Linux machines, gnuplot is available (and much more complete) for this same purpose.
Fortran is the most evolved language. Methods for compilers to test the code in debugging mode provide very desirable error checking. It's rather rigid rules began at a time when codes were submitted as decks of cards and many things that are desirable for file control, directory structure, the incorporation of other codes, screen displays or controlling equipment are either not possible or are possible only in very awkward ways. The Unix operating system is "essentially" written in C. It is a recent language with access to most machine operations through a large set of callable functions. It is not easy to debug. Even the compiler error messages frequently are wrong in their guess at the mistake. There is no checking that the array element a[100] is not actually part of the code. In the class, routines will usually be written first in fortran and then in C.
In C each variable needs to be individually typed. The three types of concern in the beginning are double precision reals, integers and character variables.
double x;
int i,j,nl=100 ;
char string[80];
In fortran the typing is by default that all variables are single precision reals except those beginning with I,j,k,l,m, and n. Single precision is inadequate, so all main codes must begin with
IMPLICIT REAL*8 (A-H,O-Z)
And this needs to be the second line of all functions and subroutines.
The codes written for the class will need to read from the keyboard and write to the screen. In fortran the commands needed to read and write the integer I and double precision X are.
PRINT*,' ENTER I, X'
READ(*,*)I,X
PRINT*,I,X
The input from the screen could be
17, 32.5
or equally well
17 32.5
or even
17 32
In C the Input is a bit more complex. First I need an address to go to
again:
printf("enter a value for i,x ");
j=scanf("%d %lf",&i,&x);
if(j != 2)
{printf(" incorrect input probably a ,\n");
printf("Input a string:\n");
gets(string);
printf("The erroneous input was: %s\n", string);
goto again;}
which is the again:. Then I need the format %d to tell scanf that the first variable is an integer, and the format %lf to tell it that the second variable is double precision. Note that i, j, and x were defined in the previous section. The code runs correctly with a space delimeter
enter a value for i,x 1 3.7
i = 1 x=3.700000
The decimal point is not needed in the 3.7, but the standard fortran comma delimeter causes
enter a value for i,x 1,3
incorrect input probably a ,
Input a string:
The erroneous input was: ,3
enter a value for i,x
The gets(string) command is necessary to clear the input buffer. Otherwise all subsequent calls to scanf will not work. This problem with scanf is so bad that some authors recommend avoiding it for a string read followed by scanning the string. The above, however, does seem to be an innocuous fix to the problem.
In order to plot output using GPLOT or gnuplot, it is necessary to put the data in file. In fortran, this involves associating a unit number with the file
IMPLICIT REAL*8 (A-H,O-Z)
DIMENSION F(137)
DO I=1,137
F(I)=I*I
ENDDO
OPEN(1,FILE='test.out')
WRITE(1,'(I5,G20.6)')(I,F(I),I=1,137)
END
Note that the format in the write statement allows for 5 digit intgers and 6 digit reals taking up 20 spaces. The G format basically tells the computer to figure it out.
A useful variant of this is
DIMENSION R(256000)
DO I=1,256000
R=I
ENDDO
OPEN(1,STATUS=’SCRATCH’)
WRITE(1)R
DO I=1,256000
R=I*I
ENDDO
…
REWIND(1)
READ(1)R
In the interval marked by … all sorts of things could happen, R is free for use. After the rewind and read, R is again equal to I. The scratch file is handled by the system. If it is written to the disk, it is erased at then end of the file. A set of open parameters are in Open.txt.
In C the open is a bit more openly mysterious. The name of the file is a special type enabling the computer to keep track of all sorts of details.
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
FILE *fp;
double f[137];
int i;
for(i=0;i<137;++i)
{f[i]=i*i;}
if((fp=fopen("test.out","w+"))==NULL){printf(" cannot open file\n");
return;}
for(i=0;i<137;++i)
{fprintf(fp, "%d %lf \n", i, f[i]);}
fclose(fp);
}
The w+ opens the file for reading and writing. A w or an r would restrict the file to writing only or reading only. Details about this parameter are in CfileModes.htm. As might be expected in a modern computer oriented language there are many other ways of reading and writing files. The addition of C++ especially provides for very flexible I/O.
The Fortran scratch object is somewhat meaningless to C since it has the call remove to delete any file.
#include <stdio.h>
void main()
{ remove( "vm.tmp" ); }
The file is however written to the disk and then removed, while the Fortran scratch at the operating systems discretion can be left in memory or swap space. I have found C binary reads from the disk to be very efficient.
The following is mostly from The C Programming Language, Brian W. Kernighan and Dennis M. Ritchie, Prentice Hall (1988) Chapter 1 a tutorial introduction.
enter emacs with the command emacs hello.c
note ^K kills lines in order of its use, ^Y yanks the lines back to where the cursor is
the ^^ makes a mark, ^W kills text from the mark to the cursor. ^Y yanks it back
For information about the GNU Project and its goals, type C-h C-p.
C-x C-c
(No files need saving)
enter the c code to say hello
#include <stdio.h> the standard input output
main() a special subroutine with no args
{ function statements begin
printf("hello, world\n"); \n advances to the next line after the print
} function statements end
exit emacs by entering ^x ^c
-----Emacs: hello.c (C)--All------------------------------------------
compile the c code
run the c code
hello, world
leave
neptune[~] exit
logout
A more complex code comparing Fortran and C
The following is a Fortran code for Fahrenheit to Celsius conversion.
<beginning of file>
LOWER=0 note that by starting the name
IUPPER=300 with an I,J,K,L,M. or N it is
ISTEP=20 a 4byte integer
DO IFAHR=LOWER,IUPPER,ISTEP
PRINT'(I4,F6.1)',IFAHR,(5./9.)*(IFAHR-32) The format is in
ENDDO ‘( )’, The math is floating
END point because of the 5.
<end of file>
WATFOR-77 V3.0 Copyright WATCOM Systems Inc. 1984, 1988
F1:Pg_ 2:Pg_ 3:L_ 4:L_ 5:LIns 6:LDel 7:Select/Deselect 8:Cut 9:Scrn/Cmd 10:Help
fcconv.for (8,1,36853) WATFOR-77 V3.0 PC/DOS
The command RUN produces the following output
RUN
0 -17.8
20 -6.7
40 4.4
60 15.6
80 26.7
100 37.8
120 48.9
140 60.0
160 71.1
180 82.2
200 93.3
220 104.4
240 115.6
260 126.7
280 137.8
300 148.9
<hold>
The c version of the same code is
#include <stdio.h>
#define LOWER 0 /* lower limit of table */ these are symbolic names
#define UPPER 300 /* upper limit */ they go into code exactly as
#define STEP 20 /* step size */ is and are strings not numbers
/* print Fahrenheit-Celsius table */
main()
{
int fahr;
for (fahr=LOWER; fahr <= UPPER; fahr = fahr + STEP ) a do loop
printf("%3D %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
it is saved as fahr2cel.c and compiled with the command
cc fahr2cel.c
a.out
0 -17.8
20 -6.7
40 4.4
60 15.6
80 26.7
100 37.8
120 48.9
140 60.0
160 71.1
180 82.2
200 93.3
220 104.4
240 115.6
260 126.7
280 137.8
300 148.9
neptune[~] exit
logout
CLI: Connection closed.
port2@annex: hangup
the following code results from the fortran code above when run on quark with the command
f2c fahr2cel.f
/* fahr2cel.f -- translated by f2c (version 19950105).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
#include "f2c.h"
/* Table of constant values */
static integer c__1 = 1;
/* Main program */ MAIN__()
{
/* System generated locals */
integer i__1, i__2;
real r__1;
/* Builtin functions */
integer s_wsfe(), do_fio(), e_wsfe(); start, do fortran io, end
/* Local variables */
static integer ifahr, istep, lower, iupper;
/* Fortran I/O blocks */
static cilist io___5 = { 0, 6, 0, "(I4,F6.1)", 0 };
lower = 0;
iupper = 300;
istep = 20;
i__1 = iupper;
i__2 = istep;
for (ifahr = lower; i__2 < 0 ? ifahr >= i__1 : ifahr <= i__1; ifahr += same for loop
i__2) {
s_wsfe(&io___5); starts wsfe
do_fio(&c__1, (char *)&ifahr, (ftnlen)sizeof(integer)); outputs integer
int r r__1 = (ifahr - 32) * (float).55555555555555558; double precision
do_fio(&c__1, (char *)&r__1, (ftnlen)sizeof(real)); outputs real
e_wsfe(); end wsfe
}
} /* MAIN__ */
The code is compiled on quark with the command
cc fahr2cel.c -I/usr/local/include -lf2c -lm
↑ f2c library ↑
seach this dir for includes normal math library