SUBROUTINE ACTIVITY_CLEAR(act) #include "dyna.inc" #include "activity.inc" RECORD /Activity/ act INTEGER izn,znnum act.nzones = 0 act.ndests = 0 DO izn = 1,NU_ZN CALL ZONE_CLEAR(act.zone(izn)) act.dest2zone(izn) = 0 act.destlist(izn) = 0 ENDDO DO znnum = 1,MAX_ZN_NU act.zonelist(znnum) = 0 ENDDO CALL DEMAND_CLEAR(act.dem) RETURN END SUBROUTINE ACTIVITY_INIT(sim,act) #include "dyna.inc" #include "sim.inc" #include "activity.inc" RECORD /Sim_Data/ sim RECORD /Activity/ act RECORD /Zone_Data/ zone INTEGER ZONE_READ !function C - Read all zones from the zone file REWIND(ZONE_FILE) CALL READSTAT('zones',ZONE_FILE) DO WHILE( ZONE_READ(ZONE_FILE,zone).EQ.0 ) CALL ADD_ZONE(sim,act,zone) ENDDO CALL DEMAND_INIT(sim,act) RETURN END SUBROUTINE DEMAND_CLEAR(dem) #include "dyna.inc" #include "activity.inc" RECORD /OD_Demand/ dem INTEGER i dem.nints = 0 DO i = 1,MAX_DEMAND_INTERVALS dem.begint(i) = 0.D0 ENDDO dem.interval = 0 dem.tnext = 0.D0 dem.fracinf = 0.D0 dem.ribfa = 0.D0 dem.bound = 0.D0 dem.startfrom = 0.D0 dem.load_factor = 1.D0 RETURN END SUBROUTINE DEMAND_INIT(sim,act) #include "dyna.inc" #include "sim.inc" #include "activity.inc" RECORD /Sim_Data/ sim RECORD /Activity/ act C - Read the demand REWIND(DEMAND_FILE) CALL READSTAT('OD-matrices',DEMAND_FILE) CALL DEMAND_READ(DEMAND_FILE,sim,act) C - Initialize the interval counter act.dem.interval = 0 act.dem.tnext = act.dem.BEGINT(1) IF (act.dem.load_factor.LT.0.D0) act.dem.load_factor = 1.D0 IF (act.dem.startfrom.LT.0.OR.act.dem.startfrom.GT.1) THEN WRITE(ostr,'(A,F5.2,A)') 'Illegal ''startfrom'' value: ' + ,act.dem.startfrom,CHAR(0) CALL SIMMSG(STATUS,ostr) CALL SIMMSG(STATUS,'Using default value of 0.5.'//CHAR(0)) act.dem.startfrom = 0.5 !default value ENDIF RETURN END SUBROUTINE DEMAND_READ(unit,sim,act) #include "dyna.inc" #include "sim.inc" #include "activity.inc" INTEGER unit RECORD /Sim_Data/ sim RECORD /Activity/ act INTEGER i,iz,izz,interval INTEGER i1,ico CALL FND(unit) READ(unit,'(I5)') act.dem.nints CALL FND(unit) READ(unit,'(10F6.1)') + (act.dem.begint(i),i=1,act.dem.nints+1) DO i = 1,act.dem.nints-1 IF (act.dem.begint(i+1) + .LE. + act.dem.begint(i)) THEN WRITE(ostr,'(A,I2,A,F5.1,A,F5.1,A)') + 'Invalid act.demand interval specified #' + ,i,' [',act.dem.begint(i) + ,'->',act.dem.begint(i+1) + ,']'//CHAR(0) CALL DYNA_ERROR(ostr + ,DYNA_FATAL_ERROR + ,DYNA_INPUT_ERROR + ,DYNA_INVALID_DEMAND_INT) ENDIF ENDDO IF (act.dem.begint(act.dem.nints+1) + .LE. + act.dem.begint(act.dem.nints)) THEN CALL DYNA_ERROR('No termination time specified for'// + ' final demand interval...assuming max sim time'//CHAR(0) + ,DYNA_NONFATAL_WARNING + ,DYNA_INPUT_ERROR + ,DYNA_INVALID_DEMAND_INT) act.dem.begint(act.dem.nints+1) = sim.maxtime ENDIF C - READ THE ZONAL DEMAND DATA MATRIX C - THE MATRIX IS FORMED USING THE PSEUDO-ZONE NUMBERS CALL FND(unit) cr -- This block reads the demand for all intervals for each zone. [This cr -- was done in the JAY dataset, the Austin dataset may be separated cr -- as an O-D matrix for each time interval] DO iz=1,act.nzones DO interval=1,act.dem.nints CR - Read the demand from IZ to each dest zone IZZ in this CR - interval CALL FND(unit) act.zone(iz).totdem(interval)=0.0 READ(unit,'(6F10.1)') + (act.zone(iz).demand(izz,interval),izz=1,act.ndests) ! !CR Was NZONES) CR - Now find the total demand from zone IZ to all dest zones IZZ CR - in this time interval looping over *all* zones... DO izz=1,act.nzones CR - Increment only if the current origin IZ is not the same CR - as the destination and only if IZZ is a destination (in CR - which case IOZ != 0 i1 = act.zone(izz).destindex IF (iz.NE.izz.AND.i1.NE.0) + act.zone(iz).totdem(interval) = + act.zone(iz).totdem(interval) + + act.zone(iz).demand(i1,interval) ENDDO ENDDO ENDDO C - FIX UP THE CUMULATIVE PROBABILITY CURVE FOR GENERATION C - OF DEMAND TOWARDS EACH ZONE, IN ZFDEM(IZ,IZZ,interval) do interval=1,act.dem.nints DO iz=1,act.nzones ico = 0 DO izz=1,act.nzones ! ndests !CR Was incorrectly NZONES IF (act.zone(izz).destindex.NE.0) THEN ico = act.zone(izz).destindex !Dest zone pointer IF (ico.EQ.1) THEN IF (act.zone(iz).totdem(interval).GT.0.0005) THEN act.zone(iz).cumdem(ico,interval) = + act.zone(iz).demand(ico,interval) / + act.zone(iz).totdem(interval) CR - Ignore intrazonal trips (trips from and to the CR - same zone IF (iz.EQ.izz) + act.zone(iz).cumdem(ico,interval) = 0.0 ELSE act.zone(iz).cumdem(ico,interval) = 0.0 ENDIF ELSE IF (act.zone(iz).totdem(interval).GT.0.0005) THEN act.zone(iz).cumdem(ico,interval) = + act.zone(iz).cumdem(ico-1,interval) + + act.zone(iz).demand(ico,interval) / + act.zone(iz).totdem(interval) CR - Ignore intrazonal trips (trips from and to the CR - same zone IF (IZ.EQ.izz) + act.zone(iz).cumdem(ico,interval) = + act.zone(iz).cumdem(ico-1,interval) ELSE act.zone(iz).cumdem(ico,interval) = + act.zone(iz).cumdem(ico-1,interval) ENDIF ENDIF ENDIF ENDDO IF (act.zone(iz).cumdem(act.ndests,interval).GT.1.005) THEN WRITE(ostr,'(A,I3,A,I2,A/5X,A,F6.2,A)') + 'CUMULATIVE PROBABILITY CURVE FROM ZONE: ',IZ, + 'FOR INTERVAL: ',interval,' IS GREATER THAN 100%!', + 'ZFDEM = ' + ,act.zone(iz).cumdem(act.ndests,interval)*100,'%' + //CHAR(0) CALL DYNA_ERROR(ostr + ,DYNA_NONFATAL_WARNING + ,DYNA_LOGIC_BUG + ,DYNA_CUM_DEM_OVER_1) ELSE IF ( + act.zone(iz).cumdem(act.ndests,interval).LT.0.9995 + .AND. + act.zone(iz).cumdem(act.ndests,interval).GT.0.0005) + THEN WRITE(ostr,'(A,I3,A,I2,A/5X,A,F6.2,A)') + 'CUMULATIVE PROBABILITY CURVE FROM ZONE: ',IZ, + 'FOR INTERVAL: ',interval,' IS LESS THAN 100%!', + 'ZFDEM = ' + ,act.zone(iz).cumdem(act.ndests,interval)*100,'%' + //CHAR(0) CALL DYNA_ERROR(ostr + ,DYNA_NONFATAL_WARNING + ,DYNA_LOGIC_BUG + ,DYNA_CUM_DEM_UNDER_1) ENDIF ENDDO ENDDO CR --- GOOD SPOT FOR OD-SUMMARY PRINTOUT --- RETURN END C ---------------------------------------------------------------------- INTEGER FUNCTION DEMAND(io,sim,net,act,veh) C ---------------------------------------------------------------------- C - Top level routine for updating the demand state (based on the C - time varying OD-matrix). C - INCLUDED FILES: #include "dyna.inc" #include "io.inc" #include "sim.inc" #include "network.inc" #include "activity.inc" #include "vehicle.inc" C - UNMODIFIED ARGUMENTS: ! NONE C - MODIFIED ARGUMENTS: RECORD /Io_Data/ io RECORD /Sim_Data/ sim RECORD /Road_Network/ net RECORD /Activity/ act RECORD /Vehicle_Data/ veh(NU_VE) C - MODIFIED GLOBAL DATA: ! NONE C - LOCAL VARIABLES: INTEGER i,j,k,il,iz ! counters and storage vars INTEGER l INTEGER ilink ! current generation link number REAL momentum ! the relative "weight" of a particular ! link in the generation of it's zone's ! demand. REAL expgen ! A zone's expected generation REAL actgen ! A zone's actual generation LOGICAL new_interval ! Flag = T if a new_interval is starting INTEGER previntlength C - FUNCTIONS CALLED: ! NONE C - RETURN VALUE: ! Simulation status C ---------------------------------------------------------------------- C - CHECK IF A NEW DEMAND INTERVAL IS STARTING IF (sim.iter*sim.timestep.gt.(act.dem.tnext+0.005)) THEN C - Yes, it is, update INTERVAL counter IF (act.dem.interval.EQ.0) THEN expgen = 0 ELSE IF (act.dem.interval.GT.0) THEN cr expgen = 0 actgen = 0 DO i = 1,act.nzones expgen = expgen + act.zone(i).totdem(act.dem.interval) + * act.dem.load_factor DO j = 0,1 DO k = 0,1 DO l = 1,act.nzones actgen = actgen + act.zone(i).ngen(j,k,l) ENDDO ENDDO ENDDO ENDDO WRITE(ostr,600) act.dem.interval + ,expgen,actgen,CHAR(0) 600 FORMAT('INTERVAL 'I1' COMPLETE: exp'E10.5', act'E10.5,A) CALL SIMMSG(STATUS,ostr) ENDIF C - Record the start time of the *next* interval IF (act.dem.interval+1.LE.act.dem.nints) THEN act.dem.tnext = act.dem.begint(act.dem.interval+2) new_interval = .TRUE. act.dem.interval = act.dem.interval + 1 ELSE C - If the last interval is over (but there is still more C - simulation time remaining), continue generating traffic as C - was generated during the last interval previntlength = act.dem.tnext - + act.dem.begint(act.dem.interval) act.dem.begint(act.dem.interval) = act.dem.tnext act.dem.tnext = act.dem.begint(act.dem.interval) + + previntlength new_interval = .FALSE. ENDIF ELSE new_interval = .FALSE. ENDIF C --- ================================================================== C - CALCULATE VOLUME GENERATION FOR ALL LINKS C - Loop over all generation links of all zones in the network DO iz=1,act.nzones IF (new_interval) THEN C - Update the expected generation per time step, to all C - destinations in the network, for duration of the next demand C - interval for this zone. act.zone(iz).expgenz = + act.zone(iz).totdem(act.dem.interval)/ + ( (1/sim.timestep)* + (act.dem.tnext-act.dem.begint(act.dem.interval)) ) + * act.dem.load_factor ENDIF DO il=1,act.zone(iz).numgenlink C - Determine the expected vehicle generation for this time step ilink = act.zone(iz).genlink(il) ! The current generation link's number momentum = net.link(ilink).xl ! The lane miles of that link expgen = act.zone(iz).expgenz*momentum/act.zone(iz).totlmz C - Now generate the integer portion of the expected demand and C - probablistically determine if the non-integer portion of the C - expected demand generates a vehicle or not. IF ((expgen-IFIX(expgen)).GE.RAN1(sim.iseed)) THEN net.link(act.zone(iz).genlink(il)).vlg = cr + net.link(act.zone(iz).genlink(il)).vlg + + IFIX(expgen) + 1 ELSE net.link(act.zone(iz).genlink(il)).vlg = cr + net.link(act.zone(iz).genlink(il)).vlg + + IFIX(expgen) ENDIF ENDDO ENDDO DEMAND = sim.status RETURN END C ---------------------------------------------------------------------- INTEGER FUNCTION LINK_GENERATE(io,sim,net,act,link,veh) C ---------------------------------------------------------------------- C - Generates new vehicle demand on a given link (link) based on the C - prevailing OD-demand C - INCLUDED FILES: #include "dyna.inc" #include "io.inc" #include "sim.inc" #include "network.inc" #include "activity.inc" #include "vehicle.inc" C - UNMODIFIED ARGUMENTS: INTEGER link C - MODIFIED ARGUMENTS: RECORD /Io_Data/ io RECORD /Sim_Data/ sim RECORD /Road_Network/ net RECORD /Activity/ act RECORD /Vehicle_Data/ veh(NU_VE) C - MODIFIED GLOBAL DATA: ! NONE C - LOCAL VARIABLES: INTEGER i ! local storage for link number INTEGER mnum ! REAL genm ! INTEGER limentr ! INTEGER cnt ! INTEGER j,k ! counters INTEGER jnum ! a newly generated vehicle's number (id) INTEGER new1 INTEGER jnext ! ptr to the next vehicle in the vehicle list INTEGER first,last ! vehicle list pointer storage C - FUNCTIONS CALLED: ! ADDVEH ! REMOVEVEH C - RETURN VALUE: ! Simulation status C ---------------------------------------------------------------------- i = link C ******************************************************************* C VEHICLE GENERATION C ******************************************************************* C C ADD THE NEW INCOMING VOLUME TO THE WAITING VOLUME. **** C CR: GEN is the number of vehicles waiting to be generated onto link i CR: VLG is the number of vehicles to be generated during this step net.link(i).gen = net.link(i).gen + net.link(i).vlg C C NQAC1 HAS THE NUMBER OF TIME STEPS WITH GENERATION **** C OR ENTRY QUEUE. **** IF (net.link(i).gen.GT.0) + net.link(i).nqac1 = net.link(i).nqac1 + 1 C C CALCULATE THE AVAILABLE CAPACITY IN THE LINK. **** genm = (DENSMAX*net.link(i).xl)-net.link(i).npar limentr = IFIX(ENTRYMX*sim.timestep*net.link(i).nlanes) !SHOULD THIS TAKE NLANES INTO CONSIDERATION? IF (net.link(i).conc.GE.net.link(i).cmax*2.0/3.0) + LIMENTR = NINT(limentr/2.0) IF (net.link(i).gen.GT.genm) mnum = genm/MTNUM IF (net.link(i).gen.LE.genm) + mnum = net.link(i).gen/MTNUM IF (mnum.GT.limentr) mnum = limentr C --- If any particles can get on the link this timestep... IF (mnum.GT.0) THEN C --- Determine how many particles THAT WERE ALREADY IN THE ENTRY C - QUEUE move from the entry queue for this link and move them C - from MTQJ to MTXJ for this link IF (net.link(i).ntryq.GT.0) THEN IF (mnum.GE.net.link(i).ntryq) k = net.link(i).ntryq IF (mnum.LT.net.link(i).ntryq) k = mnum cnt = 1 j = net.link(i).on_genq.first DO WHILE(cnt.LE.k.AND.j.NE.NULLP) C - Store the next vehicle in the queued list (since we'll C - loose this pointer when we call ADDVEH jnext = veh(j).nextveh C - Remove the vehicle from the link's genq list CALL REMOVEVEH(net.link(i).on_genq.first + ,net.link(i).on_genq.last,veh,j) C - Add the vehicle to the link's on link list CALL ADDVEH(net.link(i).on_link.first + ,net.link(i).on_link.last,veh,j) net.link(i).npar = net.link(i).npar + 1 veh(j).curlink = i veh(j).zfrom_index = net.node(net.link(i).ildem).izone C - Fix the vehicle's position on the link IF (net.link(i).type.NE.CONNECTOR) THEN veh(j).xpar = (1-act.dem.startfrom)*net.link(i).length ELSE veh(j).xpar = net.link(i).length ENDIF IF (sim.iqwait.NE.1) THEN veh(j).stime = sim.time.minutes veh(j).ttilnow = 0.0 cr veh(j).ttstop = 0.0 ENDIF veh(j).qstatus = IN_NETWORK cnt = cnt + 1 j = jnext ENDDO ENDIF C --- Now generate the particles that weren't in the entry queue C - at the end of the last timestep (that is, particles that were C - generated this timestep. These particles will be generated C - directly onto link i (put in MTXJ) rather than into the queue C - (put in MTQJ). For these particles, driver characteristics and C - a destination are chosen. IF (mnum.GT.net.link(i).ntryq) THEN IF (net.link(i).ntryq.GT.0) K= mnum - net.link(i).ntryq IF (net.link(i).ntryq.LT.1) K= mnum DO jnum = sim.jj+1,sim.jj+k CR - Use the first free slot j = sim.freeslot.first IF (j.EQ.NULLP) THEN WRITE(ostr,'(3A)') + 'No free vehicles slots available...' + ,'increase NU_VE parameter' + ,CHAR(0) CALL DYNA_ERROR(ostr + ,DYNA_FATAL_ERROR + ,DYNA_OUT_OF_MEMORY + ,DYNA_TOO_MANY_VEH) ENDIF CR - Take this index off the free slot list CALL REMOVEVEH(sim.freeslot.first + ,sim.freeslot.last,veh,j) C - Clear the vehicle storage slot CALL VEHICLE_CLEAR(veh(j)) veh(j).index = j veh(j).number = jnum sim.veh_ptr(jnum) = j CR - Determine the vehicle's characteristics CALL GENERATEVEH(sim,net,act,veh(j),i) CR - Add the vehicle to this link CALL ADDVEH(net.link(i).on_link.first + ,net.link(i).on_link.last,veh,j) IF (net.link(i).type.NE.CONNECTOR) THEN veh(j).xpar = (1-act.dem.startfrom) + *net.link(i).length ELSE veh(j).xpar = net.link(i).length ENDIF net.link(i).npar = net.link(i).npar + 1 veh(j).curlink = i veh(j).zfrom_index = net.node(net.link(i).ildem).izone ENDDO C --- Increment the number of particles by the number of new C --- particles just created above (K) sim.JJ = sim.JJ + K C --- CHECK IF GEOMETRY EXCEEDS PROGRAM PARAMETERS IF (sim.jj.GT.MAX_VE) THEN IF (io.use_file(ERROR_FILE)) + WRITE(ERROR_FILE,693) sim.jj,MAX_VE WRITE(ostr,693) sim.jj,MAX_VE,CHAR(0) 693 FORMAT(/'ERROR: Number of vehicles ['I6 + ,'] greater than array parameter MAX_VE [' + ,I6']'A) CALL DYNA_ERROR(ostr + ,DYNA_FATAL_ERROR + ,DYNA_OPERATIONS_BUG + ,DYNA_TOO_MANY_VEH) ENDIF ENDIF C --- Now readjust the size of the entry queue and the number of C --- particles waiting to be generated based on the number of C --- particles just admitted onto link i. IF ((mnum.GE.net.link(i).ntryq) + .AND. + (net.link(i).ntryq.GT.0)) net.link(i).ntryq = 0 IF (MNUM.LT.net.link(i).ntryq) + net.link(i).ntryq = net.link(i).ntryq - mnum net.link(i).gen = net.link(i).gen - mnum*MTNUM ENDIF C C C THE FOLLOWING IS THE CASE WHEN NO MORE PARTICLES ARE **** C ENTERING THIS LINK DURING THIS TIME STEP. **** C C C CREATE MACROPARTICLES AT THE ENTRY QUEUE ITSELF. **** C AS SOON AS THERE IS ENOUGH NUMBER OF VEHICLES COMING IN **** C TO FORM A MACROPARTICLE, CREATE THE PARTICLE . **** C NEW1 IS THE TOTAL NUMBER OF PARTICLES IN THE QUEUE AND **** C NTRYQ HAS THE NUMBER IN THE QUEUE AT THE END OF THE **** C PREVIOUS TIME STEP. **** C GEN(I) STILL HAS THE ACTUAL TRAFFIC VOLUME THAT IS **** C WAITING TO GET IN. **** C --- If there are still vehicles remaining to be generated, but they C --- won't fit directly onto the link, generate them into the entry C --- queue for the link. IF (net.link(i).gen.GT.0.0) THEN new1 = net.link(i).gen/MTNUM C --- The difference between NEW1 and NTRYQ is the number of vehicles C --- that were generated this time step and didn't move onto the C --- link. This difference should always be VLG. IF (new1.GT.net.link(i).ntryq) THEN DO jnum = sim.jj+1,sim.jj+new1-net.link(i).ntryq j = sim.freeslot.first IF (j.EQ.NULLP) THEN CALL DYNA_ERROR('No free vehicles slots available!' + //CHAR(0) + ,DYNA_FATAL_ERROR,DYNA_OUT_OF_MEMORY + ,DYNA_TOO_MANY_VEH) ENDIF CALL REMOVEVEH(sim.freeslot.first + ,sim.freeslot.last,veh,j) C - Clear the vehicle storage slot CALL VEHICLE_CLEAR(veh(j)) veh(j).index = j veh(j).number = jnum sim.veh_ptr(jnum) = j veh(j).curlink = i C --- Put the newly generated vehicle at the *end* of the entry queue C --- which will be compressed to the top of the array later. CALL ADDVEH(net.link(i).on_genq.first + ,net.link(i).on_genq.last,veh,j) CR - Determine the vehicle's characteristics CALL GENERATEVEH(sim,net,act,veh(j),i) CR - this must follow call to GENERATEVEH which sets qstatus CR - to IN_NETWORK veh(j).qstatus = IN_GENQ ENDDO C --- Increment the number of particles by the number of new C --- particles just created above (NEW1 - NTRYQ()) sim.jj = sim.jj + new1 - net.link(i).ntryq C --- CHECK IF GEOMETRY EXCEEDS PROGRAM PARAMETERS IF (sim.jj.GT.MAX_VE) THEN IF (io.use_file(ERROR_FILE)) + WRITE(ERROR_FILE,693) sim.jj,MAX_VE Cr: NOTE: FORMAT 693 is above WRITE(ostr,693) sim.jj,MAX_VE,CHAR(0) CALL DYNA_ERROR(ostr + ,DYNA_FATAL_ERROR + ,DYNA_OPERATIONS_BUG + ,DYNA_TOO_MANY_VEH) ENDIF net.link(i).ntryq = new1 net.link(i).nqactiv = net.link(i).nqactiv + 1 net.link(i).totalql = net.link(i).totalql + + net.link(i).ntryq ENDIF C ENDIF LINK_GENERATE = sim.status RETURN END SUBROUTINE GENERATEVEH(sim,net,act,veh,fromlink) #include "dyna.inc" #include "sim.inc" #include "network.inc" #include "activity.inc" #include "vehicle.inc" RECORD /Sim_Data/ sim RECORD /Road_Network/ net RECORD /Activity/ act RECORD /Vehicle_Data/ veh INTEGER fromlink INTEGER i INTEGER i1 INTEGER level REAL cum,rhold INTEGER GETDEST i = fromlink veh.decision = 0 veh.switch = 1 veh.qstatus = IN_NETWORK veh.tqwait = 0.0 veh.ttilnow = 0.0 veh.jpflag = 0 veh.distans = 0 veh.stime = sim.time.minutes veh.isec = net.link(i).number CR - Verify that the generating node is in a zone i1 = net.node(net.link(i).ildem).izone IF (i1.EQ.0) THEN WRITE(ostr,'(A,I5,A,I5,2A)') + 'Invalid generating node [',net.link(i).ildem + ,'] for link [',i,'] has no zone!',CHAR(0) CALL DYNA_ERROR(ostr + ,DYNA_FATAL_ERROR,DYNA_LOGIC_BUG + ,DYNA_NONGEN_ZONE) ENDIF CR - Find a destination for the vehicle veh.jdest = GETDEST(sim,net,act,i1) ! destindex Cr - Set the vehicle's behavior and info level IF (sim.time.minutes.LT.sim.starttm) THEN veh.info = 0 veh.ribf = 0 veh.ifamiliar = 3 veh.itag = 0 ELSE IF (sim.time.minutes.LT.sim.endtm) THEN veh.itag = 1 ELSE veh.itag = 0 ENDIF IF (RAN1(sim.iseed).LT.act.dem.fracinf) THEN veh.info = 1 veh.ribf = act.dem.ribfa + (RTRI(sim.iseed)-0.5) + * (act.dem.ribfa*0.5) ELSE veh.info = 0 veh.ribf = 0 ENDIF CR - Set the vehicle's familiarity level level = 1 cum = act.zone(act.dest2zone(veh.jdest)). + famsplit(level) rhold = RAN1(sim.iseed) DO WHILE (cum.LT.rhold.AND. + cum.LE.1.D0.AND. + level.LE.3) level = level + 1 cum = cum + + act.zone(act.dest2zone(veh.jdest)). + famsplit(level) ENDDO veh.ifamiliar = level ENDIF CR - Keep track of the number of veh generated from each zone act.zone(i1).ngen(veh.itag,veh.info,act.dest2zone(veh.jdest)) = + act.zone(i1).ngen(veh.itag,veh.info,act.dest2zone(veh.jdest)) + + 1 IF (veh.itag.EQ.1) THEN net.nin_tag = net.nin_tag + 1 net.ngen_tag = net.ngen_tag + 1 ELSE net.nin_nontag = net.nin_nontag + 1 net.ngen_nontag = net.ngen_nontag + 1 ENDIF CR - Keep track of the number of veh generated from each link net.link(i).gentot(veh.jdest) = net.link(i).gentot(veh.jdest) + 1 C SELECT THE INITIALLY PLANNED ROUTE. **** CALL BEGINRT(sim,net,act,veh,i) RETURN END INTEGER FUNCTION GETDEST(sim,net,act,fromzone) #include "dyna.inc" #include "sim.inc" #include "network.inc" #include "activity.inc" RECORD /Sim_Data/ sim RECORD /Road_Network/ net RECORD /Activity/ act INTEGER fromzone INTEGER iz REAL rhold C CALL A RANDOM NUMBER AND PICK A DESTINATION **** C AMONG THE DESTINATIONS, BASED ON THE FRACTION **** C OF DEMAND THAT GOES INTO EACH DESTINATION ZONE. **** C JDEST(J) HAS THE ORDER-NUMBER OF THE VEHICLE'S **** C DESTINATION. IZONE IS THE ACTUAL ZONE NUMBER, **** C NPZ IS THE PSEUDO ZONE NUMBER AND IOZ HAS THE **** C ORDER NUMBER (IN IDESTS()) OF THAT PSEUDO-ZONE. **** rhold = RAN1(sim.iseed) iz = 1 DO WHILE (.NOT. + ( + act.zone(fromzone).demand(iz,act.dem.interval).GT.0.0 + .AND. + rhold.LT. + act.zone(fromzone).cumdem(iz,act.dem.interval) + ) .AND. + iz.LE.act.ndests) iz = iz + 1 ENDDO IF (iz.LE.0) THEN CALL DYNA_ERROR( + 'No destination found for vehicle'//CHAR(0) + ,DYNA_FATAL_ERROR + ,DYNA_LOGIC_BUG + ,DYNA_UNKNOWN_ERROR) ELSE IF (iz.GT.act.ndests) THEN iz = act.ndests ENDIF GETDEST = iz RETURN END