1-13 PROGRAM INPUT AND OUTPUT 
 *****************************


 Input files - an efficient way to read data 
 -------------------------------------------
 Input files are an efficient way to pass parameters and initial 
 values to a program.

 Put detailed comments in your input files, so you can identify 
 easily every value you put in the input file and know the allowed 
 range of values.

 When you arranged the input values in such a documented 'block' 
 you can write an 'open' loop in the program that will read and 
 execute such 'blocks' one after another until it gets to the end 
 of the input file.

 An example of an input file: 


!------------------------------------------------------------------------
!   NSTEP                              Number of time steps
    1999
!------------------------------------------------------------------------
!     X1            X2                 Time range of integration
  0.000D+000    1.100D+000
!------------------------------------------------------------------------
!     K1          K2         K3         K4         K5         K6  (seconds)
  0.276D-032  0.686D-015  0.12D-010  0.38D-010  0.18D-011  0.97D-011
!------------------------------------------------------------------------
!    EPS                               Accuracy required
  0.100D-005


 A possible code for reading such an input file may contain an 'open'
 loop that can process several consecutive 'input blocks' like the one
 depicted above:


100   CONTINUE
      READ(UNIT=10, FMT=*, ERR=998, END=999)
      READ(UNIT=10, FMT=*, ERR=998, END=999)
      READ(UNIT=10, FMT=*, ERR=998, END=999) NSTEP
C     ------------------------------------------------------------------
      READ(UNIT=10, FMT=*, ERR=998, END=999)
      READ(UNIT=10, FMT=*, ERR=998, END=999)
      READ(UNIT=10, FMT=*, ERR=998, END=999) X1, X2
C     ------------------------------------------------------------------
      READ(UNIT=10, FMT=*, ERR=998, END=999)
      READ(UNIT=10, FMT=*, ERR=998, END=999)
      READ(UNIT=10, FMT=*, ERR=998, END=999) (K(I), I = 1, 6)
C     ------------------------------------------------------------------
      READ(UNIT=10, FMT=*, ERR=998, END=999)
      READ(UNIT=10, FMT=*, ERR=998, END=999)
      READ(UNIT=10, FMT=*, ERR=998, END=999) EPS
C     ------------------------------------------------------------------
      CALL COMPUTE(NSTEP, X1, X2, K, EPS)
      GOTO 100
C     ------------------------------------------------------------------
998   STOP ' Error reading input file '
999   STOP ' End of input file '
      END



 Using checkpoints to safeguard long calculations
 ------------------------------------------------
 Programs doing long calculations that may take hours or more, should 
 use checkpoints, as a safeguard against system crashes and unexpected
 program aborts that may trash the output files.

 On every reasonable time interval, or when the program reaches some 
 naturally defined dividing point, all essential data should be written 
 to a special file (sometimes called 'basic point').

 The data written to the file should be sufficient to continue the 
 computation from the point reached when the data was dumped.



 Flushing sequential output files at run-time
 --------------------------------------------
 It is useful to inspect the intermediary results of programs that
 take a long time to run, if a serious error is found the program
 can be aborted, and the error rectified without wasting more time.

 If the results are written to a files, you may have a problem
 inspecting them, the output of your program may be left in the
 buffers assigned by the system or I/O run-time library, until 
 they find it apropriate to "flush" the contents into the disk.

 There is no system-independent method to overcome this problem, 
 some methods used are:

   1) Closing the file, opening it again in "append mode"
      (non-standard! may be implemented with OPEN keywords
      like: ACCESS='APPEND', or  POSITION='APPEND'), 
      and resume writing to it

   2) Using FORTRAN statements like: ENDFILE and BACKSPACE.
      On some systems (e.g. AIX) they cause flushing

   3) Using routines from an optional FORTRAN library,
      e.g. "flush" from the "libU77" library.

   4) Using Standard C functions like "fflush", "fseek".
      fseek(lun, 0,1) works on HP systems.

   5) Using POSIX routines: "PXFFFLUSH"

   6) Using special "system calls", e.g. "fsync" or 
      "sync" on UNIX (preferably with a FORTRAN binding), 
      "SYS$FLUSH" on VMS.

 By the way, running a program in batch mode on VMS, you can
 write your output to the "log file" if you use WRITE (*,...).
 The log file is frequently and automatically flushed to disk.



 Reading FORTRAN expressions
 ---------------------------
 You can read numbers (into a numeric variable) or strings (into a 
 character variable) from the keyboard/file but not a function.
 Functions must be defined in FUNCTION procedures (or be intrinsics, 
 i.e. pre-defined).

 The Fortran EXTERNAL statement wouldn't help in this case, it just 
 tells the compiler that the following identifier is a subroutine or 
 function, and lets you pass it to another procedure as an argument.

 It would be a nice FORTRAN extension if we could read an expression
 into a character string, and have the program compute its value for
 given values of the argument(s).

 Such a capability could be useful, if you had a simulation program 
 requiring a lot of initial data that can be computed from some 
 mathematical expressions. Using a "function reader" you could try 
 various initial input sets for the program without having to run 
 programs for preparing the initial input. 

 By the way, interactive plotting programs usually have such a capability, 
 making it possible to study the behaviour of complex functions without 
 using analytical tools.

 In order to appreciate what is involved in implementing such a "function 
 reader" extension, note that a FORTRAN function is an entity very 
 different from ordinary variables.

 A function (or a mathematical expression) is really a list of instructions 
 for computing a number from one or more given numbers, i.e. a function is 
 a piece of machine code, not just a passive memory chunk you assign values 
 to like ordinary variables. 

 To compute the value of a function, something with functionality similar 
 to that of an interpreter (or compiler) is needed. Machine code that will 
 compute the values must be produced and run in some way (not necessarily 
 in a direct way). Producing the machine code involve complex stages like 
 parsing and code generation.

 If you read a mathematical expression at run-time, it's already after 
 the compilation was finished, so the compiler can't parse the expression 
 for you, unless it planted a lot of parsing code in your program.
     


Return to contents page