From: phillies@wpi.WPI.EDU (George D. Phillies)
Subject: Physical formatting issues
Organization: Worcester Polytechnic Institute
Distribution: na
Date: Tue, 1 Sep 1992 03:17:41 GMT

We have had a variety of somewhat airy discussions of programming style.
Ignoring the theological fundamentalists who wish to convert us to
another language (COBOL, C, etc.) eliminate GOTO's and other well-defined
language constructs, et tedious cetera, there is the interesting question 
as to how one might physically format a program for documentability
and readability.

I follow, for general discussion, a section of local code, taken from a
Brownian Dynamics program we wrote here.  Large parts of the code have 
been deleted, but there is a main, several subroutines, slices of the
variables and procedures documentation, and the included common block.
(The rationale for COMMON blocks via INCLUDE is explained before the
COMMON block.)  The subroutines (there are lots of these in the
original) are carefully kept alphabetical, without which your chances of
finding anything on a printout go downhill. Very far.  Very fast.)

The subject of discussion (other people have other approaches) is the
issue of physical formatting of code for legibility.  I don't mind 
being chopped on the readability (the code is not meant to be used by
third parties, but should be readable in a few years), but I think most 
of the group is acutely disinterested in being converted to some other
language.  (By the way, does anyone have a useful C to Fortran converter?)

George Phillies                   * C Users Anonymous *
phillies@wpi.wpi.edu              * Salvation Through Fortran*

C *************************************************
C * Program DIFFUSION     Version 1.01            *
C * Monte Carlo Diffusion through a random        *
C * Lennard-Jones potential background.           *
C * Program by (names of guilty parties deleted)  *
C *                  1991                         *
C *                                               *
C * Variables are listed and discussed in the     *
C * VARIABLES section at the end of the program   * 
C * Test was Microway NDP FORTRAN, which allows   *
C * 'INCLUDE' and names up to 31 characters long  *
C *************************************************

C *************************************************
C * Required control files are *.dat, namely      *
C * RANDOM.DAT, REMOTE.DAT, COMMON01.DAT,         *
C * CORRTIME.DAT.                                 *
C * Files continuing output are *.OUT, namely     *
C * RUN.OUT and RESULT.OUT.                       *
C *************************************************

      program diffusion
      include 'common01.dat'

C variables for testing program
      integer*4 ilocal

c...opening steps that are the same for all runs
      call start1
      write(6,1000) ' start1'
1000  format(A)

C a few lines of code deleted here

c...stable termination of the run
      call shutdown
      write(6,1000) ' shutdown'
C********NEXT LINE MUST BE LAST LINE*************************
      end
C********PREVIOUS LINE MUST BE LAST LINE*********************

C ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
C * END OF PROGRAM diffusion        *
C * End of Main Program Body.       *
C * Subroutines follow.             *
C * GDJP August 1991                *
C ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


C ***********************************************
C * subroutine RANDOM                           *
C * Random generator of linear variates on 0,1  *
C * based on Wichman and Hill Byte article      *
C * GDJP 1/9/90                                 *
C ***********************************************
      subroutine random

      include 'common01.dat'

      xrandom=171*(xrandom-177*INT(xrandom/177))-2*INT(xrandom/177)
      IF (xrandom .le. 0) xrandom = xrandom + 30269
      yrandom=172*(yrandom-176*INT(yrandom/176))-35*INT(yrandom/176)
      IF (yrandom .le. 0) yrandom = yrandom + 30307
      zrandom=170*(zrandom-178*INT(zrandom/178))-63*INT(zrandom/178)
      IF (zrandom .le. 0) zrandom = zrandom + 30323
      TEMPRAND = xrandom/30269.0+yrandom/30307.0+zrandom/30323.0
      rand = TEMPRAND - INT(TEMPRAND)
      return
      end
C ^^^^^^^^^^^^^^^^^^^^^^^^^^^^END OF RANDOM^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


C ***********************************************
C * subroutine SHUTDOWN 1.01                    *
C * Closes files and turns everything off       *
C * GDJP 1/18/90                                *
C ***********************************************

      subroutine shutdown
      include 'common01.dat'

C when did we finish

      call dostim(hrs,mins,secs,hundrs)
      time2 = 3600.0*hrs+60.0*mins+1.0*secs+0.01*hundrs
      write(50,1000) 'timestamp at calculation end'
      write(50,1030) hrs, mins, secs, hundrs
      write(50,1010) ' Elapsed time was', time2-time 1, 'seconds'

1000  format (A)
1010  format (A, E14.7, A)
1030  format (4I8)

C commands to shut down stably
      open(63, file = 'random.dat', access = 
     Q 'SEQUENTIAL', status = 'UNKNOWN', form = 'UNFORMATTED')
      write(63,*) xrandom,yrandom,zrandom,iset3g
      close (63, status = 'KEEP')

C close the file that describes the run
      close (50, status = 'KEEP')

C close the file that records the results
      close (60, status = 'KEEP')
      return
      end
C ^^^^^^^^^^^^^^^^^^^^^^^^^^^^END OF SHUTDOWN^^^^^^^^^^^^^^^^^^^^^^^^^^^


C ***********************************************
C * subroutine START1 Version 2.0               *
C * Initialize variables, zero matrices,        *
C * Activate random number generator            *
C * Set default values                          *
C * GDJP 4/4/90  and 8/21/91                    *
C ***********************************************

      subroutine start1
      include 'common01.dat'

C zero matrices ---  or get an unpleasant surprise when you port
C reduced from full program

      do 98 i = 1,idof
         wrap(i)  =0
         xbox(i ) =0
         xcutoff(i) =0
         xinit(i) =0
         xpos(i) =0
         xtrial(i) =0
98    end do


C Set fixed variables
      iflagcreate = 0
      ncorr = 0

C open file for recording run parameters
      open(50, file = 'run.out', access = 
     Q 'SEQUENTIAL', status = 'UNKNOWN', form = 'UNFORMATTED')

C open file for recording results of work
      open(60, file = 'result.out', access = 
     Q 'SEQUENTIAL', status = 'UNKNOWN', form = 'UNFORMATTED')

C document program in use

      write(50,1000) '                                     '
      write(50,1000) '                                     ' 
      write(50,1000) '                                     '
      write(50,1000) '****************************         '
      write(50,1000) '****************************         '
      write(50,1000) '            RESULT                   '
      write(50,1000) '            RESULT                   '
      write(50,1000) '            RESULT                   '
      write(50,1000) '****************************         '
      write(50,1000) '****************************         '
      write(50,1000) 'SUBROUTINES: analysis1,arraypos,batch,compare'
      write(50,1000) 'change,compare,create   '
      write(50,1000) 'makelist,newpos,potcheck,potential   '
      write(50,1000) 'propagator,random,randomg,start1,shutdown       '
      write(50,1000) 'thermal                              '

      call dostim(hrs,mins,secs,hundrs)
      time1 = 3600.0*hrs+60.0*mins+1.0*secs+0.01*hundrs
      write(50,1000) 'timestamp at calculation start'
      write(50,1030) hrs, mins, secs, hundrs
      write(60,1030) hrs, mins, secs, hundrs

      write(50,1000) 'idof, lmax, nmol'
      write(50,1020) idof,lmax, nmol

1000  format (A)
1010  format (I4, 3I12 ,I4)
1020  format(3I8)
1030  format(4I8)

      return
      end

C ^^^^^^^^^^^^^^^^^^^^^^^^^^^^END OF START1^^^^^^^^^^^^^^^^^^^^^^^^^^^^^



C **********************************************************************
C **********************************************************************
C * No active code beyond this point.                *
C * Following are lists of variables and subroutines *
C ****************************************************

C **************************************************
C * Section VARIABLES     Version 1.01             *
C * This section contains no active program state- *
C * ments.  It contains only comment lines listing *
C * program variables.                             *  
C * CS, DR, GDJP August 1991                       *
C **************************************************

C **********************************************************************
c...  BINCORR stores <x^2>, <y^2> against time interval
c...  BOLT is the boltzmann weight exp(delener/temp)
c         with temperature in units such that k_B = 1
c...  DBARE =<x^2>/2 for one time step, no potential is a bare diffusion
c...       coefficient.

C...  Many lines deleted here

c...  XRANDOM used in random # generator
c...  XSTORE stores random # generator variable for probe starts
c...  XTEMP stores random # generator variable for non-probe starts
c...  XTRIAL() is particle position after jump (could reject this)
c...  YRANDOM used in random # generator

C... More deleted lines here

C **************************************************************************

C **************************************************
C * Section PROCEDURES    Version 1.01             *
C * This section contains no active program state- *
C * ments.  It contains only comment lines listing *
C * program subroutines.                           *  
C * GDJP August 1991                               *
C **************************************************

C *************************************************************************

C...  Unlisted routines are deleted here

C...  RANDOM: random number generator (linear variate RAND 0.0-1.0)
C        based on Wichman and Hill
C...  SHUTDOWN: stores RANDOM status and closes other files
C...  START1: zeros matrices, initializes RANDOM, opens files, other 
C        processes that are always the same
C *************************************************************************


C The following is the common block, which in a working program needs
C its own file. Why common blocks? Because experience shows that the
C largest waste of time, especially with student programmers who are
C not FORTRAN adepts, is failure to pass variables correctly between
C programs and subroutines, coupled with a student reluctance to debug by
C printing values for all variables on each line during a single pass 
C through each subroutine.  With common blocks (IMPLICIT NONE helps, too)
C the error rate in this category of mistake is depressed.

C ************************************************* 
C * COMMON01.DAT      Version 1.01                * 
C * Specifies all common blocks and variables for * 
C * glass simulations.  Includes all common       * 
C * blocks, variable type identifications, dimen- * 
C * sion statements, and parameter assignments.   * 
C * Must appear as separate file in order to      * 
C * operate.                                      * 
C * GDJP 8/19/1991                                * 
C ************************************************* 

C parameter declaration
      integer*4 idof, lmax, nmol

C idof is the dimensionality of the simulation
      parameter (idof = 2)
C lmax is maximum number of glass particles in interaction box
      parameter (lmax = 300)
C nmol is the maximum possible number of glass molecules
      parameter (nmol = 9000)
C CAUTION! Parameters can't be passed inside common blocks!
C We know this, but some users may forget.

C variable declaration
      integer*4 dbug, flag, glassmoltype, hundrs, hrs,
     Q i, iflagcreate, isample, iseed, 
C long deletion here
     Q xrandom,xstore,xtemp,yrandom,ystore,ytemp,zrandom, 
     Q zstore,ztemp,itest

C note that the declaration and common blocks statements match
C line by line
      common/integr4/ dbug, flag, glassmoltype, hundrs, hrs, 
     Q i, iflagcreate, isample, iseed, 
C long deletion here
     Q xrandom,xstore,xtemp,yrandom,ystore,ytemp,zrandom, 
     Q zstore,ztemp,itest

      dimension  glassmoltype(nmol), list(lmax), wrap(idof),
     Q wraptest(idof)  

      real*4 bolt, d, daverage, dbare, delener, density, 
C long deletion here
     Q xglass, xinit, xold, xpos, xtrial 

      dimension dist(idof), sig(4), sigavg(4), sigavg2(4), xbox(idof), 
     Q  xcutoff(idof), xglass(3,nmol), 
     Q  xinit(idof), xold(idof), xpos(idof), 
     Q  xtrial(idof) 
                    
C again the real*4 declaration and the common blocks match
      common/reel4/ bolt, d, daverage, dbare, delener, density, 
C long deletion here
     Q xglass, xinit, xpos, xtrial 

      character string(3)*10, glassname*72,test1

      common/caracter/string, glassname

C remainder of file deleted

********************