Graham Jones (Surrey, British Columbia, IT Pro)
In part 3 I described the “struggles” with the establishment; a “people” problem again. Now I will get back to some of the “techie” stuff. FORTRAN 66 was widely recognized as a “suitable” language for technical computing. However, it was a lousy language when it came to data input. Everything had to be done in “fixed format”. For example “3F8.2” would mean 3 real number fields of size of 8 and 2 decimal places and “80A1” would mean 80 fields of single characters, ie. a whole punched card. It was all too easy to be only one column out when creating (or copying – notoriously error prone) the punched card input. You could then go “card blind” and “get a lot older” trying to find the error.
“There had to be a better way”. Free form input was clearly more attractive but it wasn’t supported then (it is today). The dilemma was how to maintain as much standard content as possible for portability versus usability. We decided that we had to “break our own rules” if we were going to “popularize” our applications. The best apps with no users is hardly a formula for success! IBM mainframes used a character code system called EBCDIC (Extended Binary-Coded Decimal Interchange Code – what a mouthful). The first step was to be able to read each column on a punched card as a single character and to be able to identify the character. The rest was a matter of deciding how to interpret that character as part of the input stream. It just so happened that if each card was read using the “80A1” format into an array of 80 4 byte signed integer variables (no unsigned integer variables then) then the most significant byte would contain the character. By bit shifting (ie. dividing by 16777216 which is 2^24) the character could be moved into the least significant byte. The numerical value (0 to 255) would then represent the character code and could therefore be identified. But what about the sign bit which is the high order bit in the most significant byte? This doesn’t move with the integer division. The way to deal with that of course was to test to see if the integer was a –ve. If it was then multiply by -1 and add 128 (2^7) to the shifted result.
Having got this far we started thinking in broader terms. If we can now identify each individual character why not go for a “keyword” input system (eg. temperature = 20.6) rather than just freeform numeric input. Then the order of input is less restrictive. Better still, why not permit math expressions and units conversion (eg. ft/sec to metres/min) on input. Units in engineering is something of a nightmare and I know of examples where entire process plants failed because units were not converted correctly. So what started out as “small” project mushroomed into a separate “major” project of its own, ie. a flexible input system for FORTRAN 66 on IBM 360/370 to be used by all of the new apps. Although this worked well on an IBM 360/370 and we believed it was all standard FORTRAN what about running our programs on a Control Data Corporation (CDC) mainframe for example (this becomes relevant later)? The code had also become quite large and complex and execution space was at a premium. We decided that if we were going to “break the rules” that we might as well “really” break them and gain some other benefits (mainly executable size and speed) at the same time. We decided to re-write the data input system in Assembler fully recognizing that this would definitely be different from manufacturer to manufacturer. Since I had a major involvement in the FORTRAN based version I got this task. So it was on to teaching myself IBM 360/370 Assembler never having even opened a book on the subject! Welcome to the fascinating and much more flexible world of working much closer to the “guts” of the machine. I soon realized how limiting high level languages are. At the same time there have to be practical limits as to what can be incorporated. Look at how features are added to high level languages over time as need and demand dictates.
There was one other major challenge using FORTRAN. The array storage needs for many process unit designs are 2 dimensional. The size of the dimensions is dictated by the number of chemical components and the number of stages in a piece of process equipment. In the case of distillation this might be the number of separation units (often trays) inside a distillation column. In distillation the objective is to take a feed stream(s) and split it(them) into 2 or more streams of desired composition based upon the differing boiling points of the components (that’s the simple version but I hope that is reasonably clear). For example, if you boil alcohol and water (making moonshine :)) and then condense the distillate (the stuff that boils off) you get something containing a higher % of alcohol. Do this enough times and you get close to pure alcohol. A distillation column is just a way of doing this much more efficiently. The problem is that the number of components and the number of stages can vary hugely from one case to the next. FORTRAN 66 only permitted fixed dimensioned arrays (no ReDim facility for example like in many languages today). Also, remember data storage space was limited by the partition size on the machine. At first I had to make some compromise assumptions based upon input from around the company. The other choice was to have several different versions of the program with different problem size ranges; a maintenance nightmare in the making especially when you consider that the app was to be installed at several different computer centres around the UK.
“There had to be a better way”. My excursion into the Assembler world gave me some ideas. In IBM 360/370 Assembler you can request storage space from the OS as needed and get an address to the space. Further you can indicate whether it is permanent or temporary. I discovered that permanent space was allocated at the top of storage “stack” and temporary space at the bottom working backwards. When the next request for space is made that causes them to overlap then an exception is generated. You have to either get rid of some temporary space or abort. Variables are used to store the addresses of the various data in the storage “stack”. I thought to myself, “why can’t I apply the same principles in FORTRAN?”. Basically I defined a single dimension storage array sized to fit the limits of the machine partition allowing for the executable code. Rather than have separate arrays for storing the addresses within the main array or any defined constants I stored everything within a pre-allocated area at the top of the main array. Then it became a matter of writing code to request space (permanent or temporary) based upon the problem characteristics and managing it. With this approach we never encountered a problem that couldn’t be solved from a storage space standpoint.
However, managing the storage and input were really the least of the challenges in writing an effective distillation design program in those days. They are important but only the “admin” side of things. The guts of the program has to do the equation solving computation. I will discuss the math side of the challenge in part 5 and how it was necessary to take more than one math approach to solving a wide range of distillation design problems.