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


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

 Input files should include detailed comments, so you can easily 
 identify all input values, and any deviation from the allowed ranges. 


 Multi-block input files
 -----------------------
 If the input values are arranged in a documented "block", like the
 one in the following example, then an "open loop" in the program 
 can read and execute several such "blocks" one after another until 
 it gets to the end of the input file:


!------------------------------------------------------------------------
!   NSTEP                              Number of time steps
    1000
!------------------------------------------------------------------------
!     X1            X2                 Time range of integration
  0.000D+000    1.000D+000
!------------------------------------------------------------------------
!     K                                A useful constant
  0.333D-000  
!------------------------------------------------------------------------
!    EPS                               Accuracy required
  0.100D-003


 A code excerpt implementing an "open loop" for processing several 
 consecutive "input blocks" like the one showed above:


100   continue
      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) x1, x2
c     ------------------------------------------------------------------
      read(unit=10, fmt='(/)', err=998, end=999)
      read(unit=10, fmt=*, err=998, end=999) k 
c     ------------------------------------------------------------------
      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 '



 XDR - Portable binary files
 ---------------------------


 HDF - A de facto standard for data files
 ----------------------------------------


 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 appropriate 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 write
 special routines, or running 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