Card deck (unit 5)
Continuity (from the printout)
Rainfall hyetograph (in/hr)
Hydrographs at saved points (cfs) — from the interface tape, unit 8
Pollutographs at saved points — SFQUAL, from the rewritten interface tape (NQUAL = 3)
Overland flow depth on each subarea plane (ft) — from blank COMMON at the last step
Run a deck first.
Lines decided by judgement (not by a clean read)
| Card | As transcribed | Why it needed a decision |
|---|---|---|
| WSHE 73 | IF(DELR.LT..0001*WDEPTH(J,K)) GO TO 280 | The constant is smudged in the print (..0021 / ..0014 in OCR). .0001 fits the role: a tolerance after the 11-pass Newton loop fails. Only affects whether a "NO CONVERGENCE" line is printed, not the depth. |
| GUTT 13 | WCON(160,3),NAMEW(160),PCIMP(160) | Blurred in GUTTER; confirmed by the same COMMON statement printed clearly in HCURVE, HYDRO, RHYDRO and WSHED. |
| HCUR 22–27 | DATA TITL / … / VER / … / | Hollerith strings read from the image; the exact blank padding inside 4H fields matters only for the printer-plot titles. |
| RHYD 32 | … ZERO DETENTION DEPTH') | Literal breaks across a continuation line at column 72 (DE / PTH); joined as the compiler would. |
| RUNO 9 | CALL GRAPH(0) | Argument reads as 0 or O; GRAPH is the Executive Block printer-plot driver, not implemented here. |
| SFQU 13 | CBASTM(160) | Printed as CBASTH/CBASTM in the COMMON; every use is CBASTM, so CBASTM. |
| SFQU245 | C PRESENT COMPUTATIONS ASSUME CBS EFFECT ONLY BOD | The C in column 1 is missing on the page; it can only be a comment. |
| SFQU221–224 | IF(KLAND(J).EQ.1)SFCOLI(JJ)=590000000*… | Nine- and ten-digit coliform factors read from the image; KLAND is subscripted J (the inlet pointer), not JJ, as printed. |
| SFQU326–343, 462–464 | FORMAT 630 / 605 / 616 dash rules | Dash counts inferred from column 72 of each continuation card; cosmetic only. |
| SFQU371 | 631 FORMAT(' ',I5,I7,T17,F8.2,T25,F11.2,T39,F11.2,T52,F8.2,T62,F8.2,T72,F8.2) | Smudged; taken to be the first half of FORMAT 612, which is clear. |
Card group A — title (2 cards, 20A4, RHYD 20)
Two 80-column cards of text, stored in TITLE(40), echoed on the printout and written as record 1 of the interface tape.
Card B — run control (2I5,I3,I2,F5.1,I5,F5.0, RHYD 22)
| Cols | Field | Meaning | Default |
|---|---|---|---|
| 1–5 | INLET | Inlet (manhole) number this deck drains to; a label only | — |
| 6–10 | NSTEP | Number of integration time steps | — |
| 11–13 | NHR | Start hour of the storm | 0 |
| 14–15 | NMN | Start minute | 0 |
| 16–20 | DELT | Integration time step, minutes | — |
| 21–25 | NRGAG | Number of rain gages (max 10) | — |
| 26–30 | PCTZER | Percent of impervious area with zero detention storage | 25 |
Card C — hyetograph control (I5,F5.0, RHYD 37)
| Cols | Field | Meaning |
|---|---|---|
| 1–5 | NHISTO | Number of rainfall intensity values per gage (max 160) |
| 6–10 | THISTO | Rainfall interval, minutes |
Cards D — rainfall intensities (10F5.0, RHYD 44), NRGAG sets
NHISTO values in inches per hour, ten per card, as many cards as needed per gage. Converted internally to ft/s (÷ 43200).
Cards E — subareas (3I5,3F5.0,7F5.3,F10.5, RHYD 72), one per subarea, ended by a card with cols 6–10 blank/zero
1971 trap: the read loop is DO 340 I=1,NW with NW = 160, so after exactly 160 subarea cards it stops without looking for a terminator — punch the blank card only when there are fewer than 160. The same holds for the 160 gutter cards (RHYD 144). The converter follows this rule.
| Cols | Field | Meaning | Default when 0 |
|---|---|---|---|
| 1–5 | JK | Rain gage number | 1 |
| 6–10 | N | Subarea number (1–160); zero ends the group | — |
| 11–15 | NGOTO | Gutter/pipe number it drains to; 0 = direct to inlet | inlet |
| 16–20 | W1 | Width of overland flow, ft | — |
| 21–25 | W2 | Area, acres | — |
| 26–30 | W3 | Percent impervious | — |
| 31–35 | W4 | Ground slope, ft/ft | 0.03 |
| 36–40 | W5 | Manning n, impervious | 0.013 |
| 41–45 | W6 | Manning n, pervious | 0.25 |
| 46–50 | W7 | Detention storage, impervious, inches | 0.062 |
| 51–55 | W8 | Detention storage, pervious, inches | 0.184 |
| 56–60 | W9 | Horton maximum infiltration, in/hr | 3.0 |
| 61–65 | W10 | Horton minimum infiltration, in/hr | 0.52 |
| 66–75 | W11 | Horton decay rate, 1/second | 0.00115 |
Cards F — gutters and pipes (4I5,7F8.0, RHYD 145), one per element, ended by a card with cols 6–10 blank/zero
| Cols | Field | Meaning | Note |
|---|---|---|---|
| 1–5 | JK | Unused (printed in error messages as "inlet") | |
| 6–10 | N | Gutter/pipe number (1–160) | |
| 11–15 | NGOTO | Downstream gutter/pipe; 0 = discharges to the inlet | |
| 16–20 | NP | 1 = trapezoidal gutter, 2 = circular pipe | 3 is created internally for a manhole with no element |
| 21–28 | G1 | Bottom width (trapezoid) or diameter (pipe), ft | |
| 29–36 | G2 | Length, ft | |
| 37–44 | G3 | Invert slope, ft/ft | used as 1.486·√S/n |
| 45–52 | G4 | Left side slope, horizontal per vertical | trapezoid |
| 53–60 | G5 | Right side slope | trapezoid |
| 61–68 | G6 | Manning n | |
| 69–76 | G7 | Overflow depth, trapezoid (the header says IN, the code uses it in FT; 0 → 10 ft). Pipes always use 2.62 rad = 93 % of diameter. |
Card G — hydrographs to save (16I5, RHYD 262)
NSAVE on one card, then the gutter numbers whose inflow is written to the interface tape (unit 8) every step. These are what the chart shows.
Card H — hydrographs to print (16I5, RHYD 277)
NPRNT, INTERV on one card, then the gutter numbers to list on the printout every INTERV steps.
Surface quality cards (SFQUAL) — optional; if none follow, the engine prints a note and skips SFQUAL
Card Q1 — control (2I5,F5.0,4I5, SFQU 21)
| Cols | Field | Meaning |
|---|---|---|
| 1–5 | KTNUM | Number of quality subarea cards (Q4) |
| 6–10 | NINLTS | Number of sewer inputs = must equal NSAVE (SFQU 122 stops otherwise) |
| 11–15 | DT | Time step, minutes (same as DELT) |
| 16–20 | KHOUR | Start hour |
| 21–25 | KMIN | Start minute |
| 26–30 | NTSTEP | Number of steps = number of records GUTTER wrote on the scratch tape (NSTEP rounded up to a multiple of M = (NSTEP+99)/100) |
| 31–35 | NPRINT | 0 = one summary table; n > 0 = per-input time tables every n steps |
Card Q2 — street condition (2F10.0,I5, SFQU 31)
| Cols | Field | Meaning |
|---|---|---|
| 1–10 | DRYDAY | Dry days before the storm |
| 11–20 | CLFREQ | Street-cleaning interval, days |
| 21–25 | NOPASS | Sweeper passes: 1, 2 or 3 (sets the removal efficiency REFF with CLFREQ) |
Card Q3 — catch basins (3F10.0, SFQU 53)
| Cols | Field | Meaning |
|---|---|---|
| 1–10 | CBDEN | Catch basins per acre (0 = none) |
| 11–20 | CBBOD | BOD of the stored liquid, mg/l |
| 21–30 | CBVOL | Stored volume per basin, gallons |
Cards Q4 — quality subareas (3I5,2F10.2, SFQU 73), KTNUM cards, grouped by INPUT
| Cols | Field | Meaning |
|---|---|---|
| 1–5 | KNUM | Subarea number (label) |
| 6–10 | INPUT | Sewer input it drains to = one of the saved gutter numbers (card G); consecutive cards with the same INPUT form one input area |
| 11–15 | KLAND | Land use: 1 single-family, 2 multi-family, 3 commercial, 4 industrial, 5 undeveloped/park (sets the dust-and-dirt, BOD and coliform factors from the Chicago APWA study) |
| 16–25 | ASUB | Area, acres |
| 26–35 | GUTTER | Curb/gutter length, hundreds of feet (0 = no washoff from this subarea) |
Start with what the machine was
In 1971 a storm-water model was a box of punched cards, a reel of tape and a line printer. You read the cards once, in order, through unit 5; you wrote your report to unit 6, one line at a time, with the first character of each line telling the printer whether to skip to a new page; and you left your real results on a tape for the next program in the chain. The Runoff Block of SWMM Version 1 is about a thousand cards of Fortran IV written for an IBM 360, and every design decision in it comes from that environment. Keep that in mind and the code stops looking odd and starts looking sensible.
This app runs that code. Not a re-derivation of it, not a modern model with a 1971 label — the same statements, in the same order, translated into C with the names and labels kept, compiled to WebAssembly, fed the same 80-column cards. If the original authors could watch, they would recognize every line of the printout.
The watershed as three buckets
A subarea in SWMM 1 is not one surface. RHYDRO splits every subarea into three planes and WSHED solves each of them separately (figure 1). Plane 1 is the impervious ground that holds some water before it runs off — roofs and pavement with their puddles. Plane 2 is the pervious ground, the only one that infiltrates. Plane 3 is the share of the impervious area the modeler says has no depression storage at all: the default is a quarter of it, PCTZER = 25, and it starts running off the instant the rain starts. That third plane is why a SWMM 1 hydrograph rises at the first drop instead of waiting for the puddles to fill. It is a small idea with a big effect on the first ten minutes.
All three planes share the subarea width W1 and slope W4. The width is the one number a modeler has to think about: it is the length of the imaginary curb the sheet of water flows over, and it sets how fast the plane drains. The 1971 manual told you to take the area divided by the average overland flow length, and that advice has not changed in fifty years.
Rain in, water out: the nonlinear reservoir
Each plane is a reservoir with a leak that depends on how full it is. Water depth d on the plane rises with rain i, falls with infiltration f, and falls with outflow, and the outflow is Manning's equation applied to the sheet of water above the depression storage dp:
There is no closed form for that, so WSHED does what an engineer with a desk calculator would do: guess the change in depth over the step, evaluate the balance at the midpoint depth, correct the guess by Newton's method, and stop when the correction is under one percent of the change. Eleven passes are allowed; it usually needs two or three. The sign convention is worth a second look — WCON is stored negative, so the whole Manning term carries its own minus sign, and D0 is the depth above the puddles at mid-step, clamped at zero. If the rain and the stored water together cannot even fill the depression storage, the code skips the solver entirely and just adds the water to the puddle (WSHE 62, 285). Nothing runs off a plane until its puddles are full. Figure 2 shows how steep that leak is: outflow goes with the five-thirds power of the excess depth, so a plane that has a quarter inch standing on it drains an order of magnitude faster than one with a tenth.
Horton's law of diminishing returns
The pervious plane loses water to the soil at a rate that starts high and decays to a floor — Horton's equation, with the three numbers that every SWMM user since has typed in: a maximum rate (3 in/hr), a minimum rate (0.52 in/hr) and a decay constant (0.00115 per second, which is 4.14 per hour). SWMM 1 evaluates it against time since the start of the storm, not against cumulative infiltration, and it does not recover during dry spells — the decay runs on the clock, which is the right model for a single storm and the wrong one for a week of weather. There is one more guard: if the loss over a step would take more water than the plane has, the loss is cut to what is there (WSHE 52–58). That keeps the mass balance honest when a light shower falls on dry ground.
Gutters and pipes: the same trick with geometry
A gutter in SWMM 1 is also a reservoir with a Manning leak, only the geometry is honest about the cross section. GUTTER takes the inflow from the subareas and the upstream elements that drain to it, and solves for the depth at the end of the step so that the change in stored volume equals inflow minus the average outflow over the step. Newton again, up to thirty passes, converged when the volume residual is under a tenth of a cubic foot.
Two choices in that routine deserve attention. First, the pipe is never allowed to fill. DFULL for a pipe is 2.62 radians, which is a depth of 93 percent of the diameter — just about where the flow in a circular pipe is greatest, and comfortably away from the place where Manning's equation goes to pieces as the top of the pipe closes in. Second, when a gutter or pipe hits its full depth the excess is not lost; it is parked in QSUR, printed as a surcharge in cubic feet, and fed back as inflow on the next step (GUTT 162–164). That is a storage node at every manhole, done in three cards. The modern dynamic-wave engine does it with a pressurization slot and a full momentum equation; the 1971 engine did it with a bucket, and for a 5-minute step on a small system the bucket is not a bad answer.
The tree, upside down
The elements have to be solved upstream first, so each gutter knows its inflow before it is asked for its outflow. HYDRO does not ask you to order the cards. It finds the elements that discharge to the inlet, puts them at the far end of NGUT, then walks back up the tree prepending each element's feeders, and finally slides the whole list to the front (figure 5). Thirty cards, no recursion, no stack — just an array walked from the back. The same routine also invents a dummy element, NPG = 3, for any manhole number that subareas or gutters drain to but no gutter card describes; a dummy element passes its inflow straight through. That is how a subarea can drain to a manhole rather than a pipe.
The walk has a limit that the manual does not advertise. RHYDRO collects the elements that discharge to the inlet in two small arrays, NWTOI and NGTOI, and fills them with a loop that runs J = 1 to NIN, and NIN is 10 (RHYD 181). The eleventh subarea or gutter that drains straight to the inlet is reported as "LARGER THAN THE ALLOWED NO" — a message written for a different mistake — and the run stops. In 1971 this was a modelling rule you learned once: collect your laterals into a trunk before the inlet. The converters in this app learn it for you. When a SWMM 5 or SWMM 4 model has more than ten links reaching the outfall, they add pass-through collector elements, ten feeders each, and chain them, so the deck runs and each inlet keeps its own saved hydrograph. The Lancaster example, SWDAT1 from the SWMM 4 distribution, needs one such collector for its fifteen Transport inlets.
Tapes, and what the next block got
The printout is for the engineer. The results are on tape. At every step GUTTER writes the time and the inflow to each saved element to unit NOUT, after a three-record header (figure 6). The Transport Block read that tape as its inflow hydrographs; the quality routine SFQUAL read a second copy on a scratch unit. This app reads the same records back and draws them — the charts you see are not re-computed from the printout; they are the tape.
Dirt, by land use
The second half of the Runoff Block is SFQUAL, Metcalf & Eddy's surface quality model, and it is the part of SWMM 1 that had no precedent. The premise is blunt: what washes off a street is the dust and dirt that accumulated in the gutter since it was last cleaned, and how much accumulated depends on the land use and the length of curb. The Chicago APWA study gave the rates — 0.7 to 4.6 pounds per day per hundred feet of gutter for single-family through industrial land — and the BOD and coliform content of that dirt. Street sweeping takes a fixed fraction each pass (60 to 98 percent, by sweeping interval and number of passes), so the load at the start of the storm is a geometric series over the dry days. Catch basins add a second source: a tank of stale liquid of known BOD that the first runoff flushes out, with an exponential that saturates after about one and a half basin volumes have passed through.
Here r is the runoff rate in inches per hour over the area draining to the input, and the washoff fraction is a power law in it. Look at the exponent D before you trust a pollutograph: it is 1.0 above one inch per hour and climbs toward 2.6 as the flow dies away, so the solids removed per step can rise again on the recession, when the exponent outruns the falling flow. That is not a transcription error — the cards say it — it is what the 1971 authors fitted, and it is one reason later versions replaced this function with the exponential washoff SWMM uses today. SFQUAL reads the hydrographs back from the scratch tape GUTTER left, works per sewer input, writes a per-step table of flow, BOD and solids, and then overwrites the interface tape with NQUAL = 3 so the Transport Block received quality as well as flow (figure 7).
Reading the printout
The report ends with four totals and a number worth trusting more than any single hydrograph: the error in continuity as a percentage of rainfall (HYDR 139). Rainfall in, minus infiltration, minus flow that reached the inlet, minus water still standing on the planes, should be zero. On sample deck 1 it is 0.14 percent; on deck 2, 0.9 percent. A 1971 engineer would have been pleased with either. The error has three sources — the midpoint depth in the planes, the averaged outflow in the gutters, and the fact that the surcharge bucket is not counted as storage — and it grows with the time step. Halve DELT and watch it fall; that is the oldest convergence test there is and it still works.
A model that keeps its mass balance in a visible number on the last page is a model that expects to be checked. Keep that habit.
What this rebuild changed, and what it did not
The Fortran was read from the page images of the listing — the OCR layer in the PDF turns WDEPTH into WOEPTH and 160 into 16O often enough to be useless as a source and good enough to be a scaffold. Each of the seven routines was typed back into fixed form with its identification field in columns 73–80, then translated to C one statement at a time. Blank COMMON is a single array of four-byte words, so the layout, the column-major arrays and even the one place the code deliberately clears past the end of HGRAPH behave exactly as they did on the 360. REAL is a 32-bit float; the 360 used hexadecimal floating point with a slightly different precision, and no one should expect the sixth digit to agree with a 1971 run. Blanks in numeric fields are ignored here, where the 360 read them as zeros; a card punched correctly reads the same either way, and a card typed carelessly now reads the way you meant it.
- Included: RUNOFF, HYDRO, RHYDRO, WSHED, GUTTER, HCURVE — the whole quantity side, the card reader, the report, the interface tape.
- Included: SFQUAL, the surface-quality model, with its scratch-tape read-back and the NQUAL = 3 interface tape. Not included: the Executive Block printer plots that HCURVE sets up. Transport, Storage and Receiving Water are separate volumes of work.
- Imported: SWMM 5 .inp files and SWMM 4 .DAT files with a $RUNOFF block, including the SWDAT series that shipped with SWMM 4. Decks whose rain comes from a Rain Block file, or that only call EXTRAN, Storage or Stats, are shown but not run.
- Verified: wasm and native builds produce byte-identical printouts; the engine is re-entrant; continuity closes within a percent on both sample decks. On the Lancaster deck the reported error is 29 percent, and that is water in transit: the SWMM 4 run ends at 60 minutes while the rain lasts to 65, and HYDR133–139 count rain, infiltration, inlet flow and subcatchment storage but not what is sitting in the gutters and pipes. Not verified: against an actual 1971 run, because none survives in this reconstruction.
Your run
Change a width, halve the slope, move PCTZER to zero and run again. It takes two milliseconds. In 1971 it took a trip to the card punch, a place in the queue and a wait for the printer. The physics did not change in between; the patience required did.
What this is
The Runoff Block of the original Storm Water Management Model, Version 1, as published in Storm Water Management Model, Volume IV — Program Listing (EPA Water Quality Office, report 11024 DOC 10/71, October 1971) by Metcalf & Eddy, Inc., the University of Florida and Water Resources Engineers, Inc. Section 2 of that volume prints seven Fortran IV routines — RUNOFF, GUTTER, HCURVE, HYDRO, RHYDRO, WSHED and the surface-quality routine SFQUAL. All seven were transcribed from the page images, translated statement for statement into C, and compiled to WebAssembly. The engine reads the same 80-column card images and writes the same line-printer report.
What is and is not here
- Included: the whole Runoff Block — hydrology and gutter/pipe routing (RUNO, HYDR, RHYD, WSHE, GUTT), the card reader, the printed report, the hydrograph scratch tape (unit 10) and interface tape (unit 8), and SFQUAL, the Metcalf & Eddy surface-quality model (dust and dirt by land use, street sweeping, catch basins, BOD, suspended solids, coliforms), which rewrites the interface tape with NQUAL = 3 as the Transport Block expected.
- Not included: the Executive Block printer plots (GRAPH, CURVE, PLOT, PPLOT) that HCURVE drives — HCURVE itself is translated; its CURVE call is a no-op. The Transport, Storage and Receiving Water Blocks (pages 41–248) are not transcribed.
- SWMM 5 import: the converter punches a SWMM 1 deck from a SWMM 5
.inp— subcatchments to subarea cards (Horton or approximated from Green-Ampt), conduits to gutter/pipe cards (circular, trapezoidal, rectangular, triangular; other shapes as circular), weirs/orifices/outlets/pumps as pass-through elements, gage series to the 10F5.0 histogram (averaged to coarser blocks when a run needs more than 160 values), SI models converted to US units, and default surface-quality cards. It lists every approximation it makes. SWMM 1 limits apply: 160 subareas, 160 links, 10 gages, one inlet, no storage, no flow splitting. - SWMM 4 import: a SWMM 4
.DATwith a$RUNOFFblock is converted the same way — H1 subcatchments, G1 gutters and pipes (NPG 1/2/3), E1/E3 rain cards (TZRAIN becomes leading zero intervals), J1/L1 quality, Green-Ampt (INFILM = 1) mapped to Horton. Transport inlets become pass-through elements and are the saved points. Decks whose rain comes from a Rain Block interface file, or that have no$RUNOFFblock (the EXTRAN, Storage and Stats examples), are shown for reference and not run. The SWDAT1–6 and EXAM1–4 decks from SWMMEnablement/legacy-swmm-ai are in the sample list. - Two 1971 traps both converters work around: RHYD 181–185 fill
NGTOI/NWTOIwith aDO J=1,NINloop, so at most 10 elements may discharge to the inlet — the 11th prints "… IS LARGER THAN THE ALLOWED NO" and STOPs. The converters chain extra terminal elements through added pass-through collector elements. AndDO 340 I=1,NW/DO 480 I=1,NG(RHYD 71, 144) read at most 160 cards and never see a terminator after the 160th, so a group of exactly 160 cards is punched without one. - Deliberate differences: REAL is IEEE single precision rather than IBM hexadecimal floating point; blanks in numeric card fields are ignored rather than read as zeros; DO loops are zero-trip;
STOPafter a data error returns to the host instead of ending the job. Everything else, including the overflow of theNRANVL=200clearing loop pastHGRAPH(160), behaves as the listing says.
AI use
This app was built with Claude, Anthropic's AI model, in a Claude session on 22 October 2026, under the direction of Robert (Bob) Dickinson, who supplied the scanned listing, set the goal (the SWMM 1 engine in Fortran, as a wasm engine, with an HTML app) and reviews the result. Responsibility for the work is his.
What Claude did. It read the 25 Runoff Block pages as images, using the PDF's OCR layer only as a scaffold, and typed all seven routines (1,311 cards) back into fixed-form Fortran with their card identification fields; translated them line for line into C with the blank COMMON kept as one word array; wrote the Fortran-IV formatted-I/O runtime (card reader, FORMAT interpreter, carriage control, unformatted tapes); compiled the engine to WebAssembly with wasi-sdk; wrote the two sample decks, the SWMM 5 .inp converter, this page, the Doc essay and the Word version of it, and this text.
How it was checked. Mechanically: the wasm printout is byte-identical to the native C build on both sample decks, the engine is re-entrant (two runs, identical output), continuity errors are 0.14 % and 0.91 %, and the hyetograph/hydrograph charts are read from the engine's own tape and COMMON rather than re-computed. By reading: every transcribed line was compared with the page image; the eleven lines that needed a judgement are listed on the Fortran tab. Not yet checked by anyone: no run of the original 1971 program exists to compare against, so there is no value-by-value score against a printed 1971 output; the printer plots have not been transcribed; no person other than Claude has yet proof-read the transcription, and the SFQUAL washoff numbers in particular have only been checked for plausibility, not against a published example.
Sources
- Metcalf & Eddy, Inc., University of Florida, Water Resources Engineers, Inc. (1971). Storm Water Management Model, Volume IV — Program Listing. EPA 11024 DOC 10/71. Section 2, Runoff Block, pp. 13–40.
- Same authors (1971). Volume I — Final Report (11024 DOC 07/71) and Volume III — User's Manual (11024 DOC 09/71), for the meaning of the card fields.
- wasi-sdk 24 (clang 18) for the wasm32 build; no runtime imports are used.