! ! HDXDAT.B4S: Hardy-Cross Pipe Network Analysis Data ! Management Program ! ! Installed as: ...HDD ! ! Include files ! {BL:[101,5]TRUTH.B4S} {BL:[101,5]FCSERRCOM.B4S} ! ! File channel definitions ! {HDDDEF.B4S} ! ! Buffer and Map definitions ! {HDDMAP.B4S} ! DIM field$(.max.args%) ! workfile%, outfile%, flows%, heads%, lo.op%, loopdata%, co.eff%, debug% = .false% pipe.coeff = 120 ! unless otherwise set title$ = "NO TITLE ASSIGNED" ! ! *************** GCL parameter input ******************* ! ! not.finished% = .true% rwatitle$ = chr$(27%) + "[2J" + chr$(27%) + "[3;1H" + & " Richard Wittenoom and Associates Pty Ltd" + CR + LF + LF + & " HARDY CROSS PIPE NETWORK DATA MANAGEMENT" + CR + LF + LF + LF + LF ! frst% = .true% ! WHILE not.finished% more.data% = .true% help% = .false% ! WHILE more.data% ! IF frst% & THEN prompt$ = rwatitle$ + "HDD>" & \ frst% = .false% & ELSE prompt$ = LF + LF + CR + "HDD>" ! CALL GCL.(prompt$,LEN(prompt$), command.buffer$, .cmd.line.siz%, len.got%, EG%, EF%, ED%) command$ = EDIT$(left$(command.buffer$, len.got%), 32%+128%) ! fields% = .max.args% field$(i%) = "" for i% = 1% to (.max.args% -1%) ! zero the beast ! CALL READTF (command$, 2%, 0%, 0%, field$(), "", fields%) ! CALL HDDSET(field$(), command$, title$, workfile$, outfile$, err.msg$) ! GOTO 32000 IF (NOT (not.finished%)) ! bomb without the unwanted messages ! call HDDHLP("HELP", "") IF help% help% = .false% ! NEXT ! ! log.file$ = workfile$ + ".LOG" ! ! CALL OPEN. (log.file$, "W", .log.chan%, 0%) IF debug% > 0% ! ! ! ********* main tree processing routine ******* ! ! call close.(.node.chan%) \ node.file.open% = .false% ! call close.(.pipe.chan%) \ pipe.file.open% = .false% ! call close.(.loop.chan%) \ loop.file.open% = .false% ! ! open the data files - open for update unless created during data entry for this run ! IF NOT (node.file.open%) & THEN do% = fn.open.workfile%(".N", "U", .node.chan%, .node.buf.siz%) & \ node.file.open% = .true% ! IF NOT (pipe.file.open%) & THEN do% = fn.open.workfile%(".P", "U", .pipe.chan%, .pipe.buf.siz%) & \ pipe.file.open% = .true% ! IF NOT (loop.file.open%) & THEN do% = fn.open.workfile%(".L", "U", .loop.chan%, .loop.buf.siz%) & \ loop.file.open% = .true% ! CALL FCSNOR (.node.chan%, numrecs) num.node.recs% = numrecs CALL FCSNOR (.pipe.chan%, numrecs) num.pipe.recs% = numrecs CALL FCSNOR (.loop.chan%, numrecs) num.loop.recs% = numrecs ! print "nodes, pipes, loops: "; num.node.recs%, num.pipe.recs%, num.loop.recs% ! ! write a first zero into non-valid loop records (i.e. loops that have not been written by the GCL input routine) ! FOR r% = 1% to num.loop.recs% CALL GET.(.loop.chan%, loop$, r%) ! print "err1%: "; err1% IF err1% ! ! print "loop rec check" ! print "r, loop, first"; r%, loop%, l.node%(0) IF r% <> loop% & THEN loop% = 0% & \ CALL PUT.(.loop.chan%, loop$, r%) & ELSE IF ((l.node%(0%) < 1%) OR (l.node%(0%) > num.node.recs%)) & THEN loop% = 0% & \ CALL PUT.(.loop.chan%, loop$, r%) ! print "loop after the ITE : "; loop% ! NEXT r% ! ! zero the processing flag for each node to permit tree processing ! do% = fn.clear.procflag% IF heads% OR nodes% ! print "zero procflag d1,2,3: "; debug1%, debug2%, debug3% ! CALL HDDHLP("NODES", title$, num.node.recs%) IF debug1% ! dump the nodes file CALL HDDHLP("PIPES", title$, num.pipe.recs%) IF debug2% ! dump the pipes file CALL HDDHLP("LOOPS", title$, num.loop.recs%) IF debug3% ! dump the loops file ! ! carry out tree processing if heads% OR flows% ! ! print "starting the tree" IF heads% & THEN IF flows% & THEN heads% = .false% ! turn off head processing for the present & \ do% = fn.process.tree% ! process flows & \ flows% = .false% ! flows off & \ heads% = .true% & \ do% = fn.clear.procflag% ! so we can go down the tree again & \ do% = fn.process.tree% ! process heads & \ heads% = .false% & ELSE do% = fn.process.tree% & \ heads% = .false% & ELSE IF flows% & THEN do% = fn.process.tree% & \ flows% = .false% ! print "exiting the tree" ! heads%, flows% = .false% ! don't go through the tree again unless explicitly instructed ! ! ! print "loopdata%, infildata%; "; loopdata%, infildata% CALL HDDOUT("LOOPS", title$, outfile$, num.node.recs%, num.pipe.recs%, num.loop.recs%) IF loopdata% CALL HDDOUT("RESULTS", title$, outfile$, num.node.recs%, num.pipe.recs%, num.loop.recs%) IF results% ! ! print "leaving the loop ZZZZ" NEXT ! re-enter the loop while (not.finished%) ! GOTO 32000 ! in case we haven't picked this up elsewhere ! ! ********************** FUNCTIONS ************************* ! ! ******************* fn.clear.procflag% ******************* ! ! zero the processing flag for each node to permit tree processing ! DEF fn.clear.procflag% ! IF heads% OR nodes% & THEN FOR j% = 1% to num.node.recs% & \ CALL GET.(.node.chan%, node$, j%) & \ procflag% = .false% ! i.e. zero all bits & \ CALL PUT.(.node.chan%, node$, j%) & \ NEXT j% ! FNEND ! ! ************* fn.process.tree%() ************* ! start at the topmost node - this will be node 1. ! DEF fn.process.tree% ! fir.st% = .true% this.adr% = 1% CALL GET.(.node.chan%, node$, this.adr%) ! WHILE ((this.adr% > 1%) OR fir.st%) ! i.e. stop after the fn.up% which arrives back at adr% = 1 ! fir.st% = .false% down.adr% = fn.find.down%(this.adr%) ! IF down.adr% > 0% & THEN this.adr% = fn.down%(down.adr%, this.adr%) & ELSE this.adr% = fn.up%(this.adr%) ! fn.up returns the new address ! NEXT ! FNEND ! ! ************** fn.down% ********************* ! DEF fn.down%(this%, prev%) ! ! - here with the previous record still in the node buffer. ! - first store the head information at the previous node. ! prev.node.elevation = elevation prev.node.head = resid.head ! CALL GET.(.node.chan%, node$, this%) ! ! first make sure where we have just come down from is first in the connected node array ! IF n%(0%) <> prev% & THEN FOR i% = 1% to 3% & \ IF n%(i%) = prev% & THEN tmp% = n%(0%) & \ n%(0%) = n%(i%) & \ n%(i%) = tmp% & ELSE dont% = sw.ap% & \ NEXT i% & ! ! print "FN.DOWN: node0, prev "; n%(0%), prev% ! print "ERROR - FN.DOWN: previous node "; prev%; " not pointed to by next node"; this% IF prev% <> n%(0%) ! ! if heads% is set true, calculate heads on the way down ! fn.down% = this% ! FNEXIT IF NOT (heads%) ! pipe% = fn.get.pipe% (prev%, this%) ! note that the pipe record is now in the pipe buffer ! IF node1% = prev% & THEN sense% = +1% ! sense% is +ve if the +ve & ELSE sense% = -1% ! direction is DOWNSTREAM ! ! print "pipe, sense, node1, prev, this: "; pipe%; sense%; node1%; prev%; this% IF debug% => 8% ! ! head at downstream node will be: ! ! prev.node.elevation + prev.node.head - pipe.loss - elevation ! downstr.q = pipeflow * sense% / 1000 ! convert to c.m./sec q.sign = sgn(downstr.q) qval = abs(downstr.q) ! setup to avoid -ve arg in, exp expr'n ! K = ((1/(PI * (diam^2)/4.0E6)) / (0.849 * pipe.coeff * ((diam/4.0E3)^0.63)))^1.85 pipe.loss = K * q.sign * (qval^1.85) * length ! ! now find and store the head in the current node record ! resid.head = prev.node.elevation + prev.node.head - pipe.loss - elevation ! ! print "dsq, hloss, res.h, pr.n.head, pn.elev, elev: " if debug% > 5% ! print " "; downstr.q; pipe.loss; resid.head; prev.node.head; prev.node.elevation; elevation if debug% > 5% ! ! store the record ! CALL PUT.(.node.chan%, node$, this%) CALL PUT.(.pipe.chan%, pipe$, pipe%) ! FNEND ! ! *********************** fn.get.pipe%() ******************* ! DEF fn.get.pipe%(nod1%, nod2%) ! get the required pipe record into the pipe buffer ! pipe.found% = .false% i1% = 0% WHILE ((i1% < num.pipe.recs%) AND (NOT(pipe.found%))) i1% = i1% + 1% CALL GET.(.pipe.chan%, pipe$, i1%) IF ((nod1% = node1%) AND (nod2% = node2%)) OR ((nod1% = node2%) AND (nod2% = node1%)) & THEN pipe.found% = .true% ! NEXT ! fn.get.pipe% = i1% ! FNEND ! ! ************* fn.find.down% ************************ ! DEF fn.find.down%(this%) ! return address of next down path or -1% if none ! ! at this point we know that the downstream nodes are n%(1%) -> ! and that a zero node number denotes a nonexistent branch ! ! processing flag bit settings: ! bit 0 set: no significance (procflag% = 1%) ! bit 1 set: branch 1 processing flagged (procflag% = 2%) ! etc. ! ! ! ! IF (n%(1%) > 0%) AND ((procflag% AND 2%) < 1%) & THEN addr% = n%(1%) & \ procflag% = procflag% + 2% & ELSE IF (n%(2%) > 0%) AND ((procflag% AND 4%) < 1%) & THEN addr% = n%(2%) & \ procflag% = procflag% + 4% & ELSE IF (n%(3%) > 0%) AND ((procflag% AND 8%) < 1%) & THEN addr% = n%(3%) & \ procflag% = procflag% + 8% & ELSE addr% = -1% ! ! print "fn.find.down: addr%: "; addr% IF debug% > 9% fn.find.down% = addr% ! CALL PUT.(.node.chan%, node$, this%) ! FNEND ! ! ********************** fn.up%() *********************** ! DEF fn.up%(this%) ! ! we are currently at a node for which all branches have been satisfied (or a terminal node). ! note that the current node record is already in the node buffer ! ! if flows are required, invoke fn.get.flow and store these in the upstream pipe record. ! do% = fn.accumulate.flows(this%) IF flows% ! get the flows and write into the upstream pipe record ! fn.up% = n%(0%) ! store the upstream node for return CALL GET.(.node.chan%, node$, n%(0%)) ! get the upstr record into the node buffer before returning ! FNEND ! ! ************** fn.accumulate.flows() ******************** ! ! (here with the current node in the buffer) ! DEF fn.accumulate.flows(th.is%) ! th.is% is the node in the buffer ! uspipeflow = nodeflow ! first store the node draw-off ! FOR i% = 1% to 3% ! IF n%(i%) > 0% ! i.e. the node exists and the line is not CLOSED & THEN do% = fn.get.pipe%(th.is%, n%(i%)) ! returns with the pipe in the pipe buffer & \ IF node1% = th.is% & THEN sense% = +1% ! sense% is +ve if the +ve & ELSE sense% = -1% ! direction is DOWNSTREAM ! ! print "fn.get.flow: th.is, n%(i%), node1%, node2%, sense%: "; th.is%; n1%(i%), node1%; node2%, sense% IF debug% => 7% ! downstr.q = pipeflow * sense% ! uspipeflow = uspipeflow + downstr.q IF n%(i%) > 0% ! add it in only if the branch exists ! NEXT i% ! upstr.pipe.adr% = fn.get.pipe%(n%(0%), th.is%) ! IF node1% = n%(0%) & THEN sense% = +1% ! (sense% is +ve if the +ve) & ELSE sense% = -1% ! (direction is DOWNSTREAM ) ! ! print "upstream pipe: n%(0), th.is%, node1%, sense%: ", pipe.adr%, n%(0%); th.is%, node1%, sense% ! CALL GET.(.pipe.chan%, pipe$, upstr.pipe.adr%) ! write out the pipe record including the flow pipeflow = uspipeflow * sense% ! store the flow in the buffer in the correct sense for the pipe CALL PUT.(.pipe.chan%, pipe$, upstr.pipe.adr%) ! write out the pipe record including the flow ! ! print ! print "******* pipe, uspipeflow, sense%: "; upstr.pipe.adr%, uspipeflow, sense% ! print ! FNEND ! ! ************* fn.open.workfile%() ************* ! DEF fn.open.workfile%(ext$, mode$, chan%, reclen%) ! IF workfile$ = "" & THEN workfile$ = "HDXDAT" ! CALL OPEN.(workfile$ + ext$, mode$, chan%, reclen%) ! FNEND ! ! {BL:[101,5]FNSAW.B4S} {BL:[101,5]FNANSCHK.B4S} ! 32000 CALL CLOSE. (.tf.out.chan%) CALL CLOSE. (.node.chan%) CALL CLOSE. (.pipe.chan%) CALL CLOSE. (.loop.chan%) CALL CLOSE. (.log.chan%) ! 32767 END