--- title: "Hydrology" id: 56297 type: "computer_media" slug: "hydrology" url: "http://localhost/computer_media/hydrology/" markdown_url: "http://localhost/computer_media/hydrology.md" published_at: "2024-08-04T10:49:46+00:00" modified_at: "2026-03-30T21:43:01+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/08/hydrology.png" excerpt: "A menu-driven hydrology suite that calculates watershed slopes, draws drainage maps, prepares unit hydrographs, and fits lognormal distributions — all with embedded machine code." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Engineering" slug: "engineering" taxonomy: "genre" url: "http://localhost/type/engineering/" media_contents: - id: 56277 title: "Timex Sinclair Public Domain Library Tape 2001" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-2001/" - id: 60550 title: "Fort Worth TS2068 Club Library Tape" type: "computer_media" url: "http://localhost/computer_media/fort-worth-ts2068-club-library-tape/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Hydrology%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/08/hydrology.png" media_type_tags: "Engineering" --- # Hydrology This program is a hydrology toolkit that offers four computational modules selectable from a menu: slope computation, a watershed map drawing routine, unit hydrograph preparation (UHG PREP), and a mathematical unit hydrograph generator (MATH UHG). The menu dispatcher at line 50 uses a single multiply-and-branch idiom (`GO TO 10*Number`) to jump to subroutines at lines 60, 100, 200, and 250 based on the user’s input of 6, 10, 20, or 25. The map-drawing module (line 100) POKEs 12 bytes of machine code into address 23760 and then calls it via `RANDOMIZE USR 23760`, implementing an LDIR block-copy routine (opcodes `ED B0`) capped with a `RET` (`C9`). The MATH UHG section (line 250) implements a lognormal distribution fitting algorithm with an iterative sigma convergence loop and computes either instantaneous or average unit hydrograph ordinates using numerical integration by Simpson’s rule. *** ## Program Analysis ### Program Structure The program is organized as a menu-driven dispatcher. Lines 1–45 display a menu and read the user’s selection into `Number`. Line 50 computes `GO TO 10*Number`, routing to one of four modules: | Input | Target line | Module | | --- | --- | --- | | 6 | 60 | Slope computation | | 10 | 100 | Map draw | | 20 | 200 | UHG Prep | | 25 | 250 | Math UHG | | 100 | 1000 | STOP | Each module ends with `GO TO 18`, which jumps to a non-existent line — falling through to line 19 (the blank PRINT). In practice this is effectively a restart of the menu from line 19 onward, since BASIC will run the next available line after an unfound target in some interpreters, though this is noted as a known technique. The REM at line 1 flags the author’s awareness of bugs. ### Machine Code Usage The map-draw module (lines 106–108) POKEs 12 bytes into RAM starting at address 23760 and then invokes them with `RANDOMIZE USR 23760` at line 125. The DATA at line 127 decodes as: | Address | Byte (hex) | Z80 mnemonic | | --- | --- | --- | | 23760 | 33 00 40 | LD HL,16384 (start of display) | | 23763 | 64 11 00 E3 | partial operands / LD DE,… | | 23767 | 01 00 1B | LD BC,… | | 23770 | ED B0 | LDIR (block copy) | | 23772 | C9 | RET | The exact byte sequence is `33,0,64,17,0,230,1,0,27,237,176,201`. The LDIR instruction copies a block of memory, and the RET returns cleanly to BASIC. The purpose appears to be a display-area memory operation, consistent with copying or clearing graphics data. ### Slope Computation Module (lines 60–90) This module computes the Taylor-Schwarz channel slope formula used in hydrology. It reads N elevation points, a reach length `DL`, and a total length `L` from DATA. For each pair of adjacent elevations it computes `D(I) = 1 / SQR(ELDIFF/DL)`, then calculates overall slope as `S = ((N-1) / SUM)^2`. The result is truncated to four decimal places using the `INT(x*10000)/10000` idiom and converted to ft/mile by multiplying by 5280. ### Map Drawing Module (lines 100–136) This module plots a watershed boundary and stream network using pixel-level PLOT and DRAW commands. Two pairs of 2D arrays (`x`, `y` for boundary; `z`, `u` for stream) store coordinate sequences read from DATA. The boundary data is at line 132 and stream data at line 134, giving sequences of absolute pixel coordinates. The DRAW calls use relative offsets computed from successive coordinate differences. A sentinel check `IF x(c,1)>255 THEN GO TO 135` at line 112 and a similar check at line 120 guard against out-of-range coordinates, though the check at 120 tests `z(1,1)` (the first element) rather than `z(c,1)` (the current element), which is likely a bug — it will never trigger mid-loop as intended. ### UHG Preparation Module (lines 200–229) This module implements the Snyder synthetic unit hydrograph method. It computes lag time `TP`, time-to-peak `TPR`, and peak discharge `QP` from basin parameters: drainage area `DA`, main channel length `L`, length to centroid `LCA`, storm duration `TR`, and empirical coefficients `CT` and `CP640`. The formula `NUM=(L*LCA)^0.3` is the standard Snyder lag parameter. An urbanization parameter `PAR = L*LCA/SQR(S)` is also printed for lookup on an external curve. ### Mathematical UHG Module (lines 250–326) This is the most computationally intensive module, implementing a lognormal unit hydrograph. It fits a sigma parameter iteratively by bracketing the solution to match a lognormal CDF target (`YO`), converging in two passes of decreasing step size (0.0005, then 0.000005). The core loop structure is: 1. Compute `YO = TMQ * QMAX / (111.80941 * A)` (the lognormal argument) 2. Estimate initial `SIGMA` from a polynomial approximation using `Y = log10(YO)` 3. Iteratively refine SIGMA at lines 268–281 until `S ≈ YO` within 0.0001 4. Compute the mode time `T` from SIGMA 5. Evaluate ordinates in the FOR loop at lines 293–318 The constant 111.80941 is `SQR(12500)`, a normalisation factor for the lognormal unit hydrograph. When `INSTA=0`, average flows are computed using a simple trapezoidal/Simpson accumulation (`TOT + 2*Q`) inside the inner loop, divided by 20 at line 309. The loop exit condition at lines 315–316 terminates when both time has passed the mode *and* flow has dropped to 2 or below. ### Notable Techniques and Idioms - **Computed GO TO:**`GO TO 10*Number` at line 50 is an efficient menu dispatcher, avoiding a chain of IF statements. - **Rounding idiom:**`INT(x*10000)/10000` and `INT(x*100+.5)/100` are used throughout for controlled decimal truncation and rounding respectively. - **DATA reuse:** All module parameters are stored in DATA statements local to each module section, so the READ pointer advances naturally as each module is entered once per run. Re-entering a module after a GO TO 18 restart would exhaust the DATA pointer — a latent bug for repeated use within one run. - **Polynomial sigma inversion:** Lines 264–267 use a degree-6 polynomial in `Y = log10(YO)` to approximate the inverse normal, seeding the iterative refinement efficiently. ### Bugs and Anomalies - **Line 120 sentinel check:**`IF z(1,1)>255` always tests the first stream coordinate, not the current loop variable `z(c,1)`. This means the stream loop never terminates early via this guard. - **Line 294 dead code:**`IF (J-1)>=0 THEN GO TO 296` is always true for `J=1 TO 11` (since J starts at 1), so line 295 (`LET TT=TT-DT/10`) is never executed. - **DATA pointer exhaustion:** Modules use READ/DATA without RESTORE, so selecting the same module twice in one session will cause an error when data runs out. - **Line 90 / 136 / 229 / 326 — GO TO 18:** Line 18 contains `PRINT "MENU SELECTION"`, so the menu is redisplayed from line 18 rather than from line 15 (which prints the title). This skips the title and the CLS at line 45 is not re-executed, so old output remains on screen. - **Line 72 square root of ratio:**`SQR(ELDIFF/DL)` will produce an error if any adjacent elevations are equal or decrease, as the argument becomes zero or negative. ## Source Code ``` 1 REM Program seems to have some "bug problems" 10 REM "hydrology1" 15 PRINT AT 1,7;"HYDROLOGY #1" 17 PRINT 18 PRINT "MENU SELECTION" 19 PRINT 20 PRINT "Input a 6 for Slope, Input a 10 for map draw Input a 20 for UHG PREP Input a 25 for MATH UHG Input a 100 if you are finished." 21 PRINT 25 PRINT "If you want a copy, use break key and then COPY." 40 INPUT Number 45 CLS 50 GO TO 10*Number 60 REM "SLOPE" 61 PRINT AT 11,1;"PROGRAM FOR SLOPE COMPUTATION" 62 DIM D(11): DIM E(11) 63 READ N,L,DL,T$ 64 FOR I=1 TO N 65 READ E(I) 66 NEXT I 67 PRINT AT 14,10;T$ 68 PRINT 69 LET SUM=0 70 FOR I=2 TO N 71 LET ELDIFF=E(I)-E(I-1) 72 LET A=SQR (ELDIFF/DL) 73 LET D(I)=1.0/A 74 LET SUM=SUM+D(I) 75 NEXT I 76 LET S=((N-1)/SUM)^2 77 LET S=INT (S*10000)/10000 78 LET SO=S*5280 79 PRINT AT 18,2;"SLOPE = ";S;" FT/FT" 80 PRINT 81 PRINT AT 20,2;"Or ";SO; " FT/MILE" 82 PRINT 83 DATA 8,1840,1840,"WILLOW LAKE" 84 DATA 657.5,675,690,710,735,750,800,830 90 GO TO 18 100 REM "map draw" 101 PRINT "Put no of boundary, stream lines, title, drainage area in data line 126. Put starting x, y for boundary in 131, for stream in 133. Put x, y data for boundary in 132, stream in 134." 102 PAUSE 120: CLS 103 DIM x(30,30): DIM y(30,30) 104 DIM z(20,20): DIM u(20,20) 105 READ nl,ns,T$,DA,S 106 FOR a=23760 TO 23771 107 READ b: POKE a,b 108 NEXT a 109 READ x(1,1): READ y(1,1) 110 PLOT x(1,1),y(1,1) 111 FOR c=2 TO nl 112 READ x(c,1): IF x(c,1)>255 THEN GO TO 135 113 READ y(c,1) 114 DRAW x(c,1)-x(c-1,1),y(c,1)-y(c-1,1) 115 PLOT x(c,1),y(c,1) 116 NEXT c 117 READ z(1,1): READ u(1,1) 118 PLOT z(1,1),u(1,1) 119 FOR c=2 TO ns 120 READ z(c,1): IF z(1,1)>255 THEN GO TO 135 121 READ u(c,1) 122 DRAW z(c,1)-z(c-1,1),u(c,1)-u(c-1,1) 123 PLOT z(c,1),u(c,1) 124 NEXT c 125 RANDOMIZE USR 23760 126 DATA 20,16,"Willow Lake",1.22,.01172 127 DATA 33,0,64,17,0,230,1,0,27,237,176,201 128 PRINT AT 19,3;T$ 129 PRINT AT 20,3;"DA= ";DA 130 PRINT AT 21,3;"Slope =";S 131 DATA 2,168 132 DATA 32,173,56,168,104,162,120,154,157,96,208,112,232,78,224,68,254,48,218,2,168,21,144,36,120,74,88,94,76,112,40,122,40,149,16,160,2,168 133 DATA 8,168 134 DATA 38,165,92,136,94,128,128,97,162,60,180,64,204,37,205,32,205,24,210,20,218,2,207,12,202,17,201,24,205,32 135 PRINT 136 GO TO 18 200 REM "UHG PREP" 201 PRINT "PROGRAM DEVELOPS UNIT HYDROGRAPH DATA" 202 READ T$ 203 READ DA,L,LCA,TR,CT,CP640,S 204 LET NUM=(L*LCA)^.3 205 LET TP=CT*NUM 206 LET TLR=TP/5.5 207 LET TPR=(TP+.25*(TR-TLR)) 208 LET AMT=INT (TPR*1000) 209 LET TPR=AMT/1000 210 LET QLP=(CP640/TPR) 211 LET QP=INT (QLP*DA) 212 PRINT TAB 10;T$ 213 PRINT 214 PRINT "INPUT DATA" 215 PRINT "AREA";TAB 5;" L ";TAB 11;" LCA ";TAB 17;" TR ";TAB 22;" CT ";TAB 27;"CP640" 216 PRINT DA;TAB 6;L;TAB 11;LCA;TAB 17;TR;TAB 22;CT;TAB 27;CP640 217 PRINT 218 PRINT "TR";TAB 6;"TPR";TAB 12;"TR";TAB 18;"QMAX";TAB 24;"AREA" 219 PRINT 220 PRINT TR;TAB 6;TPR;TAB 12;TR;TAB 18;QP;TAB 24;DA 221 PRINT 222 LET PAR=INT (L*LCA/(SQR S)*100) 223 LET PAR=PAR/100 224 PRINT "PAR = ";PAR 225 PRINT 226 PRINT AT 20,0;"USE PAR TO GET TPR FROM AN URBANIZATION CURVE" 227 DATA "WILLOW LAKE" 228 DATA 1.22,2.5,1.1,.50,.70,418,61.9 229 GO TO 18 250 REM "MATH UHG" 251 PRINT "THIS PROGRAM EXECUTES VERY SLOWLY... BE PATIENT" 252 READ T$,DT,TPR,TR,QMAX,A,INSTA 253 CLS 254 PRINT TAB 5;T$ 255 PRINT 256 PRINT "INPUT DATA" 257 PRINT "DT";TAB 5;"TPR";TAB 12;"TR";TAB 17;"QMAX";TAB 23;"A";TAB 26;"INSTA" 258 PRINT DT;TAB 6;TPR;TAB 12;TR;TAB 17;QMAX;TAB 22;A;TAB 28;INSTA 259 PRINT 260 LET TMQ=TPR+TR/2 261 LET Q=0 262 LET SUM =0 263 LET YO=TMQ*QMAX/(111.80941*A) 264 LET Y=.43429448*LN (YO) 265 LET X=-.295133-.4522*Y-.242919*Y^2-.103329*Y^3 266 LET X=X+(.0091443*Y^4)+(.0353098*Y^5)+(.0117619*Y^6) 267 LET SIGMA=10^X 268 LET S=EXP (-2.65049*SIGMA^2)/SIGMA 269 LET B=(S-YO+.001) 270 IF B>=0 THEN GO TO 273 271 LET SIGMA=SIGMA-.0005 272 GO TO 268 273 LET B=(YO-S+.001) 274 IF B>=0 THEN GO TO 276 275 LET SIGMA=SIGMA+.0005 276 IF (S-YO+.0001)>=0 THEN GO TO 279 277 LET SIGMA=SIGMA-.00005 278 GO TO 268 279 IF (YO-S+.0001)>=0 THEN GO TO 282 280 LET SIGMA=SIGMA+.000005 281 GO TO 268 282 LET T=10^(2.3025851*SIGMA^2+.43429448*LN (TMQ)) 283 LET NUM=T 284 LET NUM=INT (T*100+.5)/100 285 LET T=NUM 286 PRINT "TIME TO HALF VOL =";TAB 19;T 287 PRINT "SIGMA ";SIGMA 288 LET TT=DT 289 IF INSTA=0 THEN GO TO 292 290 PRINT "NO OF HOURS";TAB 13;"INSTA FLOW" 291 GO TO 293 292 PRINT "NO OF HOURS";TAB 13;"AVG FLOW" 293 FOR J=1 TO 11 294 IF (J-1)>=0 THEN GO TO 296 295 LET TT=TT-DT/10 296 LET Q=111.80941*A/(TT*SIGMA) 297 LET C=(2*SIGMA^2) 298 LET D=.434*LN (TT/T) 299 LET E=ABS D^2 300 LET F=E/C 301 LET Q=Q*EXP (-F) 302 IF INSTA=0 THEN GO TO 311 303 IF (J-1)>0 THEN GO TO 306 304 LET TOT=Q 305 GO TO 308 306 IF (J-11)>0 THEN GO TO 308 307 LET TOT=TOT+2*Q 308 NEXT J 309 LET Q=(TOT+Q)/20 310 LET TT=TT+DT 311 LET Q=INT (Q+.5) 312 PRINT TT;TAB 14;Q 313 LET SUM=SUM+Q 314 LET TT=TT+DT 315 IF (T-TT)>=0 THEN GO TO 317 316 IF (Q-2)<=0 THEN GO TO 319 317 IF (INSTA)<=0 THEN GO TO 296 318 IF (INSTA)>0 THEN GO TO 293 319 PRINT 320 PRINT "THE SUM IS";TAB 14;SUM 321 LET VOL=SUM/(12/DT) 322 PRINT "THE VOLUME IS";TAB 14;VOL 323 DATA "WILLOW LAKE" 324 DATA .50,.86,.50,650,1.22,0 325 PRINT 326 GO TO 18 1000 STOP ```