The following assignment involves writing and testing several simple Fortran 77 programs. Follow the instructions carefully and please do all compilation and execution on your lnx account, or ensure that all programs compile and execute on the lnx machines. All files required by the assignment must reside in the correct places on your lnx account for the homework to be considered complete.
Important: Your solutions to each and every one of the problems
below MUST include a Makefile (or
makefile) that defines, at a minimum, targets for the executable
or executables required by the problem,
and clean, where the clean target, as usual, removes the executables
and object-code files. Furthermore, your makefiles MUST use
the macros F77, F77FLAGS, F77CFLAGS, F77LFLAGS as discussed
in class (i.e. you must define ``portable'' makefiles).
Problem 1:
In a directory /hw3/a1 on your lnx account, create
Fortran source files pgm1.f and pgm2.f that are
to be compiled into executables pgm1 and pgm2 with
behaviour as described below.
Important: Use real*8 arithmetic
and ``free-format'' I/O (i.e. read(*,*) and write(*,*))
here and throughout the homework. In particular, in accordance
with the ``Unix philosophy'', discussed in class, of keeping output
from programs as ``machine-readable'' as possible, do NOT,
put ``descriptive'' information such as ``f = '' in your output.
Your programs should detect and ignore invalid input in the same fashion as the mysum example discussed in class. Should you wish to print messages if invalid input is encountered, be sure to direct the messages to standard error (unit 0). Your programs will be tested with input of my own design.
As there has been confusion concerning this in the past, be sure that both of your programs accept 0 or more lines of input--i.e. do not assume that there will only be a single line of input.
Finally, note that there is a Fortran sqrt function--see Appendix A of the Professional Programmer's Guide to Fortran 77, by Clive Page (available on-line via the Fortran Programming notes page) for a full list of the Fortran 77 intrinsic (built-in) functions.
Problem 2: In a directory /hw3/a2 create source files dvvfrom.f and dvvto.f that define Fortran subroutines with the following headers:
subroutine dvvfrom(fname,v1,v2,n,maxn) implicit none character*(*) fname integer n, maxn real*8 v1(maxn), v2(maxn) subroutine dvvto(fname,v1,v2,n) implicit none character*(*) fname integer n real*8 v1(n), v2(n)These routines are to behave completely analogously to the routines dvfrom and dvto covered in the class notes except that they are to read and write pairs of real*8 vectors (one-dimensional arrays) from and to a file with name fname. Thus the format of the input and output is:
v1(1) v2(1) v1(2) v2(2) v1(3) v2(3) . . .If fname .eq. '-', the routines should use standard input or standard output as appropriate. In the same directory, write test programs tdvvfrom.f and tdvvto.f and create executables tdvvfrom and tdvvto that test your two routines. The arguments to tdvvfrom and tdvvto should be identical to the programs tdvfrom and tdvto, respectively, which were covered in class. Specifically, the usage of the test programs should be:
% tdvvfrom <file name> % tdvvto <file name> <n>tdvvfrom should report on standard error the length of the vectors that were read (i.e. how many pairs were read); tdvvto need not report anything under normal execution. Both testing programs should be adequately documented and must perform argument processing--this includes detection of insufficient or invalid arguments, in which case a usage message should be printed to standard error. Use the system routines iargc and getarg as well as i4arg from the p410f library discussed in class for argument parsing. You should also use the integer function indlnb from the p410f library to ensure that you don't create file names with trailing spaces. Your test programs, as well as your dvvfrom and dvvto routines themselves, will be evaluated with my own input and testing programs.
Problem 3: The Chaos Game
Let
In a directory /hw3/a3 on your lnx account write
a well-documented Fortran program called chaos2d that
implements this algorithm.
Note that, as discussed in class, the real*8 function drand48,
available in the p410f library,
can be used to generate a random number between 0 and 1--it is
up to you to figure out how to use drand48 to generate
the particular randomness required by the algorithm.
Be sure
that you declare the function properly in the main program, and
note that since it has no arguments, it should be invoked with an
empty argument list:
real*8 drand48 write(*,*) 'This is a pseudo-random number ', drand48()Your program must take a single integer argument that specifies the number of iterations to perform, and must echo a usage message to standard error if the argument is missing, or invalid, e.g.
usage: chaos2d <nsteps>Again, I suggest that you use the i4arg function discussed in class and available in the p410f library to parse the argument. Your program must write to standard output the and coordinates of all of the active points that are generated (including the original randomly chosen one). Specifically, use a write statement like the following
write(*,*) xactive, yactivein your iteration loop, so that the coordinate pairs appear one per line on standard output. You may optionally output (also to standard output) the coordinates of the three triangle vertices . If you choose to do so, output them once only, presumably at the beginning of the game. Finally, although the location of the initial active point is arbitrary, you should ensure that its distance from the center of the triangle does not exceed 2.5 (recall that the sides of the triangle are of length 1.0). Run your program for 10, 100, 1000 and 10000 iterations and redirect the output to files out10, out100, out1000, and out10000 respectively. Use gnuplot to plot the points defined by each of the output files and save the plots as postscript files out10.ps, out100.ps, out1000.ps, and out10000.ps. When you make your plots, you should use an aspect ratio of 1 (same physical size of and axis Hint: Use the set size command) and should not be afraid to clip a few points in order to focus on the region of interest (i.e. the base triangle and its interior). Also, be sure to use an appropriate ``style'' in gnuplot so that the interesting structure of the plot is visible (i.e. plot with dots).
Note that the process by which you determine the random initial point lying outside the triangle need not be elaborate; you should feel free, for example, simply to define some fixed point of your own choosing as the initial point (i.e. there is no need to use random number generation in this phase of the algorithm).
You may find it useful to write a script to automate the generation of the output files and the gnuplot plotting. With regards to the latter, note that one can use a ``here document'' (recall the Unix notes on shell programming) to provide ``in-place'' input to gnuplot. For example:
input=out10 output=$input.ps gnuplot<<END set terminal postscript set output "$output" plot "$input" quit END
OPTIONAL for ALL students: Generalize the game in various ways such as
If you do chose to generalize the game, be sure to create a new source file and executable--chaos2d must execute precisely as specified above. Leave comments describing your generalization(s) in a README file in the solution directory.
Problem 4: (for 555 credit, OPTIONAL for 410 students)
In a directory /hw3/a4 create a Fortran 77 source file rw2d.f and corresponding executable rw2d, which simulates and analyzes random walks of a particle on a two dimensional integer lattice. Specifically, if at step the current position of the particle performing the walk is , where and are integers, then, with equal probability (i.e. ), the position at step is either , , or . rw2d should accept two integer arguments as illustrated in this usage message:
usage: rw2d <nsteps> <nwalks>where <nsteps> is the number of steps to take per walk, and <nwalks> is the number of separate walks to be generated. Once again, note that you can use the i4arg function from the p410f library to parse the command-line arguments. For each walk, start the particle at and use real*8 values for the particle coordinates, even though the coordinates are restricted to integer values. When your program is finished simulating the random walks, it must write on standard output the average of the distance-squared of the particle from its starting point (i.e. compute using a simple average to compute the expectation value, and average over all walks) after each step, as a function of step number. Specifically, the output should consist of two numbers per line, generated using code such as the following:
do i = 1 , nsteps write(*,*) i, rsqavg(i) end doDocument and test your program thoroughly, then make runs of 10, 100, and 1000, 5000-step walks, and save the output in files out10, out100 and out1000 respectively. Use gnuplot, or another instructor-approved plotting package (contact me if you're not sure whether a given package is instructor-approved!) to produce a single plot of average-distance-squared versus step number for all three data-sets. Save a postscript version of the plot in distance.ps. What can you say about the behaviour of versus step number as the number of walks gets large? Answer in a file called README. Note that you should again use the drand48 function defined in the p410f library in order to complete this problem.