C ---------------------------------------------------------------------- INTEGER FUNCTION LINK_PARTCO(io,sim,net,act,veh,lnum) C ---------------------------------------------------------------------- C - Loops over all vehicles on link i or in it's generation queue and C - updates their positions using DYNASMART's mesoscopic position C - update rule (all vehicles move at the average speed of the link C - on which they're travelling; the average speed is determined using C - a modified form of Greeshield's speed-density equation). Those C - vehicles which reach the end of the link are put in the end queue C - for further processing during the second link pass C - INCLUDED FILES: #include "dyna.inc" #include "io.inc" #include "sim.inc" #include "network.inc" #include "activity.inc" #include "vehicle.inc" C - UNMODIFIED ARGUMENTS: RECORD /Io_Data/ io C - MODIFIED ARGUMENTS: RECORD /Sim_Data/ sim RECORD /Road_Network/ net RECORD /Activity/ act RECORD /Vehicle_Data/ veh(NU_VE) RECORD /Link_Data/ link INTEGER lnum C - MODIFIED GLOBAL DATA: ! ostr (see dyna.inc) C - LOCAL VARIABLES: INTEGER i ! link number INTEGER iii INTEGER k INTEGER j INTEGER nl INTEGER m INTEGER nlindex INTEGER ijj INTEGER nlii INTEGER kkk INTEGER nmindex INTEGER jnext INTEGER i1 INTEGER first INTEGER last REAL xposold REAL xpos REAL xposnew REAL thold REAL xspd REAL xvehmoved REAL lspd C - FUNCTIONS CALLED: INTEGER IGETLINK ! function ! ADDVEH ! REMOVEVEH ! DETPASS ! VEH_STAT ! SIMMSG C - RETURN VALUE: ! Simulation status C ---------------------------------------------------------------------- C - i is used as this link number in Partco i = lnum C - Do some bookkeeping in preparation for the link pass DO iii = 1,net.link(i).numdslinks i1 = net.link(i).dsmoveptr(iii) net.movement(i1).demand = 0 cr net.movement(i1).queued = 0 ! Don't zero until link2link, ! this is used in stopcontrol cr net.movement(i1).moved = 0 net.movement(i1).volume(sim.volumerhind) = 0 ENDDO net.link(i).nout = 0 ! init # veh leaving network from this link net.link(i).nin = 0 ! init # veh entering link net.link(i).nmov = 0 ! init # veh leaving link net.link(i).nenaflg = 0 C ******************************************************************* C - ONLINK loop C - Go through list of vehicles on the link and process the C - movement of each one j = net.link(i).on_link.first DO WHILE(j.NE.NULLP) IF (j.LE.0) THEN WRITE(ostr,'(2A)') 'partco: broken vehicle list?',CHAR(0) CALL DYNA_ERROR(ostr + ,DYNA_FATAL_ERROR + ,DYNA_LOGIC_BUG + ,DYNA_BAD_VEH_LIST) ENDIF C - Store pointer to next vehicle on link (since we might lose C - the pointer during the loop if vehicle j leaves the network jnext = veh(j).nextveh xposold = veh(j).xpar ! veh's crnt position lspd = net.link(i).speed ! link speed XPOS = veh(j).xpar-lspd*sim.timestep ! veh's new position xspd = lspd ! veh's speed xvehmoved = veh(j).xpar-xpos ! dist veh moved IF (xspd.LE.0) xspd = 0.005 ! catch for HYBRID C - the following calculates the time required for the vehicle to C - reach the end of the link under the prevailing conditions C - (tocross) and the time the vehicle didn't use during this C - timestep to reach the end of the link (tleft)...if this is C - negative, the vehicle hasn't yet reached the end of the link veh(j).tocross = veh(j).xpar/xspd veh(j).tleft = sim.timestep - veh(j).tocross C - This block performs loop detector simulation by comparing the C - vehicle's prior and current positions to loop detector C - locations. See Surveil.F xposold = 5280*(net.link(i).length - xposold) if (xposold.le.0.0) xposold = 0 xposnew = (net.link(i).length - xpos)*5280 C - See if vehicle crossed any detectors on its current link C - during this time step CALL DETPASS(net,xposold,xposnew,i) C *************************************************************** IF (XPOS.LE.0.000) THEN C - THE VEHICLE REACHED THE END OF THE LINK C - update the distance traveled and trip time by adding the C - distance and time used to reach the end of the link veh(j).distans = veh(j).distans + veh(j).xpar veh(j).ttilnow = veh(j).ttilnow + veh(j).tocross C - Check if the vehicle has reached its destination IF (net.link(i).idnod.EQ.act.destlist(veh(j).jdest)) THEN C - THE VEHICLE REACHED ITS DESTINATION i1 = net.node(net.link(i).idnod).izone act.zone(i1).nreach(veh(j).zfrom_index + ,veh(j).itag,veh(j).info) = + act.zone(i1).nreach(veh(j).zfrom_index + ,veh(j).itag,veh(j).info) + 1 CALL REMOVEVEH(net.link(i).on_link.first + ,net.link(i).on_link.last,veh,j) C - Increment counters net.link(i).nout = net.link(i).nout + 1 net.link(i).npar = net.link(i).npar - 1 C - Do vehicle exit stuff CALL VEH_EXIT_HOOKS(io,sim,net,act,veh(j)) veh(j).itag = 2 ! mark as exited sim.veh_ptr(veh(j).number) = -1 CR - Add the index j to the free slot list CALL ADDVEH(sim.freeslot.first,sim.freeslot.last,veh,j) ELSE Cr - Take the vehicle off link i's on_link list CALL REMOVEVEH(net.link(i).on_link.first + ,net.link(i).on_link.last,veh,j) Cr - Put the vehicle on link i's end queue list CALL ADDVEH(net.link(i).on_endq.first + ,net.link(i).on_endq.last,veh,j) ENDIF C *************************************************************** ELSEIF (xpos.GT.0) THEN C - VEHICLE STILL ON LINK AFTER TIME STEP C - Update the vehicle's position and its elapsed travel C - distance and travel time veh(j).xpar = XPOS veh(j).distans = veh(j).distans + xvehmoved veh(j).ttilnow = veh(j).ttilnow + sim.timestep ELSE CALL DYNA_ERROR('partco: Vehicle Processing Error'//CHAR(0) + ,DYNA_FATAL_ERROR + ,DYNA_LOGIC_BUG + ,DYNA_UNKNOWN_ERROR) ENDIF 8 CONTINUE j = jnext ENDDO C ******************************************************************* C - ENDQ LOOP C - Loop over the vehicles in the endq to determine routing C - decisions and count the demand for each movement j = net.link(i).on_endq.first DO WHILE (j.NE.NULLP) jnext = veh(j).nextveh IF (veh(j).qstatus.EQ.IN_ENDQ + .AND. + sim.sticky_queues) THEN ! sticky queues mean that vehicles ! must commit to a queue once they ! enter it Cr - Vehicle is already in a movement queue, use its current Cr - move index (this prevents multiple vehicle switches while Cr - waiting the queue i1 = veh(j).mvindex IF (i1.EQ.0) THEN CALL DYNA_ERROR('BOGUS MOVE INDEX!!!'//CHAR(0) + ,DYNA_FATAL_ERROR + ,DYNA_LOGIC_BUG + ,DYNA_INVALID_L2L_MOVE) ENDIF nl = net.movement(i1).tolink Cr - set the amount of time the vehicle has remaining to be used Cr - during the dequeuing. veh(j).tleft = sim.timestep ELSE ! (Note: these vehicles already have tleft set from ! above)...unless they're in the queue (this is a hack ! because of the sticky_queues hack) IF (veh(j).qstatus.EQ.IN_ENDQ) veh(j).tleft = sim.timestep NL = IGETLINK(sim,net,act,i,veh(j)) C - See if GETLINK returned a bogus nextlink (index <= 0) IF (NL.LT.1.OR.NL.GT.net.nlinks) THEN CALL DYNA_ERROR('Getlink returned a begus next link'// + CHAR(0) + ,DYNA_FATAL_ERROR + ,DYNA_LOGIC_BUG + ,DYNA_INVALID_GETLINK) sim.status = SIM_ERROR GOTO 113 ENDIF C - Verify next link returned by GETLINK is reachable from the C - particle's current node and get the next link's index [NLINDEX]. nlii = 1 DO WHILE( + net.movement(net.link(i).dsmoveptr(nlii)).tolink.NE.nl + .AND. + nlii.LE.net.link(i).numdslinks) nlii = nlii + 1 ENDDO IF (nlii.GT.net.link(i).numdslinks) THEN CALL DYNA_ERROR('Getlink returned a begus next link'// + CHAR(0) + ,DYNA_FATAL_ERROR + ,DYNA_LOGIC_BUG + ,DYNA_INVALID_GETLINK) sim.status = SIM_ERROR go to 113 ELSE nlindex = nlii ENDIF Cr - Verify next link returned by GETLINK is reachable based on Cr - move.dat info nmindex = net.link(i).dsmoveptr(nlindex) IF (net.movement(nmindex).type.LE.0) THEN WRITE(ostr,6997) j,net.link(i).iunod,link + .idnod,net.link(net.movement(nmindex).tolink) + .idnod,CHAR(0) 6997 FORMAT('Vehicle 'I6 + ' trying to make illegal move: ' + I3' ->'I3' ->'I3,A) CALL DYNA_ERROR(ostr + ,DYNA_FATAL_ERROR + ,DYNA_LOGIC_BUG + ,DYNA_INVALID_L2L_MOVE) ENDIF i1 = net.link(i).dsmoveptr(nlindex) veh(j).mvindex = i1 ENDIF net.movement(i1).demand = net.movement(i1).demand + 1 IF (.NOT.veh(j).qstatus.EQ.IN_ENDQ) THEN Cr - This is new demand for this movement, add to the movement Cr - volume rolling horizon for signalization calcs net.movement(i1).volume(sim.volumerhind) = + net.movement(i1).volume(sim.volumerhind) + 1 ENDIF net.link(nl).intoo = net.link(nl).intoo + 1 Cr - Take the vehicle off the endq list of link i CALL REMOVEVEH(net.link(i).on_endq.first + ,net.link(i).on_endq.last,veh,j) Cr - Put the vehicle on the into list of link nl CALL ADDVEH(net.link(nl).into.first + ,net.link(nl).into.last,veh,j) j = jnext ENDDO CR:DETECT Notify the any detectors on this link that theyve been CR processed DO k = 1,net.link(i).link_det_num kkk = net.link(i).link_det_list(k) net.station(kkk).processed = DET_ACTIVE ENDDO 113 continue LINK_PARTCO = sim.status RETURN END