The 1981 EXTRAN III Workbench and Wasm Engine

The 1981 EXTRAN III Workbench — From the Printed Manual to WebAssembly
SWMM5.org · Historical Hydraulic Engines in WebAssembly

The 1981 EXTRAN III Workbench: From the Printed Manual to WebAssembly in Your Browser

EXTRAN—the Extended Transport block of the EPA Storm Water Management Model (SWMM) Version III—was developed at Camp Dresser & McKee (CDM) by Larry A. Roesner, Robert P. Shubinski, and John A. Aldrich under EPA Cooperative Agreement No. CR805664 (Final Report period February 1979 – August 1981). Its 1981 user’s manual (Addendum I EXTRAN) printed the complete DEC-20 FORTRAN-10 source code as an appendix on pages 167–228, dated 20 May 1981.

1. Executive Summary: History You Can Run

That 1981 line-printer appendix is the only surviving copy of EXTRAN III’s source code, preserved only as raw OCR text of the scanned manual. The EXTRAN III Workbench reconstructs that listing line by line, compiles it to WebAssembly (wasm32-wasi), and runs it directly in your browser alongside a WebAssembly build of modern EPA SWMM 5.2.4. Nothing is uploaded to a server; the engines, the 80-column card decks, and your .inp models execute locally in background threads using an in-memory file system.

2,998
Numbered FORTRAN lines reconstructed across 15 program units at their exact 1981 printed line numbers.
1,425
OCR-damaged lines repaired and logged by reason and confidence (1,289 sure, 133 likely, 3 guesses).
27
Minimal compiler port edits applied so modern compilers accept the DEC-20 FORTRAN-10 syntax.
259
SWMM5 models from the SWMM Enablement corpus converted to 1981 card decks and benchmarked.

2. Rebuilding the 1981 Engine from OCR to WebAssembly

Anatomy of the 15 Program Units

The OCR text of pages 167–228 was split into the original 15 subroutines and block data units, preserving the exact line numbering from the 1981 compiler listing:

Program Unit Manual Pages Lines OCR Repairs (Sure / Likely / Guess) Role in the 1981 Engine
EXTRANpp. 167–1688925 / 0 / 0Main stand-alone driver, SWMM interface tape setup, and DEC-20 file OPEN dialogs.
TRANSXpp. 169–177480230 / 10 / 0Executive driver performing the modified Euler solution of the motion and continuity equations.
BLKDATpp. 178–1796440 / 1 / 0BLOCK DATA tables (ANORM, HRNORM, TWNORM) for 5 closed conduit shapes.
BOUNDpp. 180–185285121 / 6 / 0Computes link flows QP(LINK) for tidal boundaries, storage nodes, orifices, weirs, pumps, and outfalls.
CURVEpp. 186–1878626 / 0 / 0Sets up X/Y scales and draws curves into the line-printer plot grid.
DEPTHXpp. 188–18910740 / 3 / 0Computes critical depth (YC) and normal depth (YNORM) for closed conduits and trapezoids.
HEADpp. 190–19213552 / 6 / 0Converts nodal depths to pipe depths, assigns surface area AS, and computes area, velocity, and hydraulic radius.
HYDRADpp. 193–1947020 / 2 / 0Interpolates geometry tables or computes exact properties for rectangular and trapezoidal cross-sections.
INDATApp. 195–211925420 / 62 / 3Reads and echoes Card Groups 1–22, initializes conditions, and converts node-conduit links to internal numbering.
INFLOWpp. 212–21414277 / 3 / 0Interpolates input hydrograph ordinates at each time step from interface tape (N21) and/or Card Group 22.
OUTPUTpp. 215–21923597 / 28 / 0Prints the end-of-run continuity balance, HGL/flow time histories, summary tables, and triggers printer plots.
PINEpp. 220–2216822 / 2 / 0Rasterizes line segments between (X1,Y1) and (X2,Y2) onto the character plot grid.
PPLOTpp. 222–2238141 / 4 / 0Maintains the 41×101 character buffer A(51,101) and prints formatted ASCII plots.
SCALEpp. 224–2258822 / 0 / 0Scans arrays for min/max bounds and selects clean axis step intervals (2, 4, 5, 8, 10).
TIDCFpp. 226–22814356 / 6 / 0Computes 7 Fourier coefficients (A1–A7) for diurnal tidal stage boundary conditions (NTIDE = 4).

Resolving OCR Ambiguities by Running the 1981 Examples

Cross-checking COMMON block declarations across all 15 subroutines and against SWMM 4.4h (EXTBLK) resolved almost all OCR syntax damage mechanically. Where OCR ambiguities affected program logic, running the manual’s seven example problems settled the reading. For example, on INDATA lines 487 and 541 (weir and pump connectivity loops), the OCR text read DO 873 NK=1,8 and DO 1180 NK=1,8, even though the loop bodies tested and assigned NCHAN(J,KK). Compiled with NK, Example 4 missed the 1981 printed junction summary in 14 out of 77 values; compiled with KK, Example 4 and Example 7 matched the 1981 printed summaries (75 exact, 2 OCR digit confusions), proving the printed page had KK.

The 27 Compiler Port Edits (P1–P5)

  1. P1 – DEC-20 File I/O (13 lines in EXTRAN): Replaced 5-character word arrays (INTEGER IFNAM(3)) and interactive terminal prompts (DEVICE='DSK', DIALOG=IFNAM) with CHARACTER*256, command-line argument retrieval (CALL GETARG), and standard Fortran OPEN statements.
  2. P2 – Implied-DO Sublists (10 lines in INDATA, INFLOW, TRANSX): Unwrapped inner parentheses inside implied-DO lists such as ((JUN(J),Y(J),JCHECK(J)),J=1,NJ) to (JUN(J),Y(J),JCHECK(J),J=1,NJ).
  3. P3 – DATA Statement Type & Count Rules (2 lines in INDATA): Converted character literals initializing a REAL array (DATA OTYPE/'SIDE','SUMP'/) to Hollerith constants (4HSIDE,4HSUMP), and commented out the unused DATA ENOTE/6HERROR ,6HERRORS/ on an undimensioned scalar.
  4. P4 – Subroutine Name Mismatch (1 line in HEAD line 33): Updated CALL DEPTH(...) to CALL DEPTHX(...) to match the printed subroutine name SUBROUTINE DEPTHX.
  5. P5 – Common Block Alignment (1 line in HYDRAD line 15): Uncommented C REAL LEN in HYDRAD so COMMON/PIPE/ has an identical byte layout across all compilation units.

36-Bit DEC-20 Words vs. Modern WebAssembly

The WebAssembly engine produces output that is byte-for-byte identical to native desktop builds across all seven example decks while preserving DEC-20 static storage semantics. Minor last-digit differences against the 1981 paper tables arise because CDM’s 1981 runs executed on a DECsystem-20 using a 36-bit single-precision word with a 27-bit mantissa (between IEEE 754 24-bit float and 53-bit double), and f2c evaluates intrinsics (SQRT, SIN, COS, EXP) in double precision.

3. The 10 Bugs Found in 1981 EXTRAN III

The workbench ships with two complete WebAssembly builds: As printed (preserving the exact numerical behavior—bugs included—that produced CDM’s 1981 manual printouts) and Bugs fixed (modifying the 10 specific defects below).

Part A: Two Bugs Active in CDM’s 1981 Printed Manual Runs

1. Uninitialized DTEMP in Trapezoid Normal Depth DEPTHX line 95 · p. 189
C**** DEPTHX, listing lines 89–99, manual page 189 — trapezoid normal depth
  665 QNORMO=0.
      SROOTS=SQRT(1.+STHETA(N)**2.)+SQRT(1.+SPHI(N)**2.)
      DO 680 I=2,26
      YI=0.04*FLOAT(I-1)*DEEP(N)
      AREA=YI*(WIDE(N)+YI/2.*(STHETA(N)+SPHI(N)))
-     HRAD=AREA/(WIDE(N)+DTEMP*SROOTS)
+     HRAD=AREA/(WIDE(N)+YI*SROOTS)

Mechanism & Impact: DTEMP is never assigned anywhere in the program, so DEC-20 static storage initializes it to 0.0. The wetted perimeter is evaluated as the bottom width WIDE(N) alone, overestimating hydraulic radius and normal flow and returning a normal depth that is far too shallow. Someone pencilled “Replace DTEMP by YI” in the margin of the scanned 1981 manual. In Example 1, free outfall 10208 peaks at 0.53 ft as printed, but 2.51 ft when fixed (matching SWMM 5.2.4’s 2.53 ft). Across the SWMM5 corpus, this fix cuts median peak-depth error from 0.48 ft to 0.11 ft across 82 models.

2. Exponent 0.677 Instead of 2/3 in Trapezoid Manning Equation DEPTHX lines 96–97 · p. 189
      QNORM=SQRT(32.2*(ZP(N,1)-ZP(N,2))/(LEN(N)*ROUGH(N)))*AREA*HRAD**0.
-    2677
+    26667

Mechanism & Impact: Raises HRAD to 0.677 instead of 0.6667 (whereas closed conduits on line 58 use 0.6667), overestimating normal flow by ~0.7%–1.7%. Fixing this line alone causes Example 1 to differ from the 1981 printout in 99 places instead of 13, confirming the 1981 printout ran with 0.677.

Part B: Five Additional Bugs Found During Code Transcription

3. Rectangular Normal-Depth “Hydraulic Radius” Set to Wetted Perimeter DEPTHX line 56 · p. 188
  400 QNORMO=0.
      DO 600 I=2,26
      AREA=AFULL(N)*ANORM(I,NTYPE)
      HRAD=RFULL(N)*HRNORM(I,NTYPE)
-     IF(NTYPE.EQ. 2) HRAD=WIDE(N)+2.*(I-1)/25.*DEEP(N)
+     IF(NTYPE.EQ. 2) HRAD=AREA/(WIDE(N)+2.*(I-1)/25.*DEEP(N))

Mechanism & Impact: Sets HRAD for rectangular conduits (NTYPE = 2) to the wetted perimeter b + 2y instead of AREA / (b + 2y) during normal-depth calculation.

4. Surface Width Overwrites Mid-Conduit Hydraulic Radius HEAD line 86 · p. 191
C******** CRITICAL SECTION UPSTREAM' SURFACE AREA DOWNSTREAM
  200 HEAD1=YC+ZP(N,1)
      YNL=YC
      YMID=0.5*(YNL+YNH)
      IF (YMID.LE.0.0) YMID=0.0
      CALL HYDRAD(N,NKLASS(N),YNL,RNL,ANL,BNL)
-     CALL HYDRAD(N,NKLASS(N),YMID,RMID,AMID,RMID)
+     CALL HYDRAD(N,NKLASS(N),YMID,RMID,AMID,BMID)
      CALL HYDRAD(N,NKLASS(N),YNH,RNH,ANH,BNH)

Mechanism & Impact: Passes RMID twice to HYDRAD when the upstream end of a conduit is at critical depth, overwriting the midpoint hydraulic radius with the surface width and leaving BMID with a stale value from a previous pipe.

5. Surcharge Iteration Limit Hardcoded to 30 TRANSX line 340 · p. 175
C**** CHECK CONVERGENCE OF THE FLOW ERROR IN SURCHARGED AREAS
      IF(ABS(ERROR)-TOL) 565,565,561
  561 IT=IT+1
-     IF(IT-30)562,562,564
+     ITLIM=ITMAX
+     IF(ITLIM.LE.0) ITLIM=30
+     IF(IT-ITLIM)562,562,564

Mechanism & Impact: Card Group 3 reads ITMAX into COMMON/SURCHG/SURTOL,ITMAX, but line 340 hardcoded 30, ignoring user input.

6. Remaining Storage Volume Indexed by Junction Number Instead of Storage Index TRANSX line 459 · p. 177
C******** COMPUTE WATER VOLUME LEFT IN STORAGE
      IF(NSTORE.EQ.0) GO TO 801
      DO 800 I=1,NSTORE
      J=JSTORE(I)
- 800 VLEFT=VLEFT+Y(J)*ASTORE(J)
+ 800 VLEFT=VLEFT+Y(J)*ASTORE(I)

Mechanism & Impact: Indexes ASTORE(20) by the internal junction number J (up to 187) instead of the storage index I (up to 20), reading out-of-bounds memory when computing end-of-run continuity. In Example 5, fixing this changes reported remaining volume from 8,299 ft³ to 8,379 ft³.

7. In-Line Pump Third Stage Tests Downstream Depth Instead of Inlet Depth BOUND line 234 · p. 184
C****** SET PUMP RATE
  885 QOUT = PRATE(I,1)
      IF(YDEP(J1).GT.VRATE(I,1)) QOUT = PRATE(I,2)
-     IF(YDEP(J2).GT.VRATE(I,2)) QOUT = PRATE(I,3)
+     IF(YDEP(J1).GT.VRATE(I,2)) QOUT = PRATE(I,3)
  888 QP(LINK) = QOUT

Mechanism & Impact: Tests the downstream receiving node depth YDEP(J2) instead of the upstream wet-well depth YDEP(J1) when triggering the third pump stage PRATE(I,3).

Part C: Three Major Defects Discovered via the 259-Model SWMM5 Corpus

8. Dry In-Line Pump Bypasses Pump Capacity Curve BOUND line 229 · p. 184
  875 JSKIP(J1)=0
      IF(YDEP(J1)-0.001) 882,882,885
  882 QINJ=0.
      DO 883 K=1,8
      N=NCHAN(J1,K)
      IF(N.GT.NC) GO TO 884
      IF(NJUNC(N,2).EQ.J1) QINJ=QINJ+QP(N)
  883 CONTINUE
- 884 QOUT=QINJ
+ 884 QOUT=AMIN1(QINJ,PRATE(I,1))
      GO TO 888

Mechanism & Impact: When an in-line pump’s inlet node J1 is dry (YDEP(J1) <= 0.001 ft), EXTRAN sets QOUT = QINJ without capping it at PRATE(I,1). Pumping out 100% of inflow keeps J1 dry on the next step, locking the pump in the uncapped dry branch forever (e.g., passing 70.65 cfs through a 5 cfs pump in the extran6 models). Capping at AMIN1(QINJ, PRATE(I,1)) drops median peak-flow error from ~22% to 6–9% across 11 pump models.

9. Closed Rectangular Conduit Never Runs Full HYDRAD line 45 · p. 193
C******** FULL PIPE
  160 WIDTH = 0.
      AREA=AFULL(N)
      HRAD=RFULL(N)
      RETURN
C******** RECTANGULAR SECTION (SPECIAL CASE)
- 180 WIDTH=WIDE(N)
+ 180 IF(DEPTH.GE.DEEP(N)) GO TO 160
+     WIDTH=WIDE(N)
      AREA=WIDTH*DEPTH
      HRAD=AREA/(WIDTH+2.*DEPTH)

Mechanism & Impact: Unlike tabulated shapes (NKLASS = 1, 3, 4, 5), the rectangular special case (NKLASS = 2) had no full-depth check. When a closed box culvert surcharged, AREA and HRAD kept growing above the crown and WIDTH stayed at WIDE(N) instead of dropping to zero. Adding IF(DEPTH.GE.DEEP(N)) GO TO 160 reduces median peak-flow differences in the 13 extran1 shape test models from 340%–4,200% down to 2%–18%.

10. Continuity Balance Omits Initial System Water Volume OUTPUT line 62 & TRANSX line 102
C**** OUTPUT, listing lines 60–63, manual page 216
      WRITE(N6,5009) VLEFT
 5009 FORMAT(' VOLUME LEFT IN SYSTEM =',5X,F12.0,' CU FT',/)
-     PCTERR = ((SUMQIN-SUMOUT-VLEFT)/SUMQIN)*100.
+     PCTERR = ((SUMQIN+VINIT-SUMOUT-VLEFT)/(SUMQIN+VINIT))*100.
      WRITE(N6,5006) PCTERR

Mechanism & Impact: Any water initially in the system at t = 0 (from Card Groups 19–20 or submerged tidal outfalls) is counted in VLEFT or SUMOUT at the end of the run, but was omitted from the initial mass balance. Including VINIT improves extran8a‘s reported continuity error from −44.2% to +0.3%.

4. How the SWMM5-to-EXTRAN III Converter Works

  • Stage 1 – Run EPA SWMM 5.2.4 in WebAssembly: Runs your .inp model in the browser at the model’s routing time step (or reads your uploaded .rpt and .out files).
  • Stage 2 – Extract Lateral Inflows to Card Group 22: Extracts SWMM5 node lateral inflows onto 80-column hydrograph cards (shifted back by one routing step to match SWMM step-inflow evaluation) so both engines route the exact same water volume.
  • Stage 3 – Translate Geometry & Structures: Maps conduits to EXTRAN’s 6 shape classes (converting custom shapes to equivalent rectangles/trapezoids with matching full depth and area), maps orifices, weirs, pumps, and storage units to Card Groups 10–13, and enforces Courant stability on Δt.

5. Interactive Tour of the Workbench’s 8 Tabs

  1. Run: Execute any of the 7 manual examples with an animated HGL profile plot, multi-node/link time-series charts, one-click GIF recorder, and the As printed / Bugs fixed toggle.
  2. SWMM5 vs EXTRAN III: Upload any SWMM5/SWMM6 .inp model or pick from 10 built-in sample models to run side-by-side peak scatter plots and hydrograph comparisons.
  3. Card deck: Edit 80-column card decks with a live column ruler, Card Group gutter labels (CG 1–CG 22), and a cursor field inspector.
  4. Printed report: Read Unit 21 output on green-bar fanfold line-printer paper with ASCII printer plots and section jump links.
  5. Against 1981: Automated cell-by-cell comparison against the 1981 manual’s printed tables (Exact, Last digit, OCR, or Mismatch).
  6. Source listing: Browse all 2,998 FORTRAN lines across the 15 subroutines with interactive badges for all 1,425 OCR repairs, 27 port edits, and 10 bugs.
  7. Docs: Inspect unified diffs, physical explanations, and corpus impact stats for all 10 bugs, with a one-click “Run it both ways” diff runner.
  8. About: Complete documentation of provenance, DEC-20 36-bit floating-point behavior, and conversion methodology.
Live Embedded Application

Interactive EXTRAN III Workbench

Interact with the full WebAssembly workbench below, or open it in a full browser tab ↗.

Translate »
Scroll to Top