/************************************************************************ / / PULL-DRIVEN SCHEDULING / / 31 May 97 IDT / / The assumptions made in this model are described in the report: / / Tommelein, Iris D. (1997). Discrete-Event Simulation of a / Materials-Handling Process that Requires Resource Matching: / Example of Pipe-Spool Installation. Technical Report 97-2, / Construction Engineering and Management Program, Department / of Civil and Environmental Engineering, University of / California, Berkeley, CA. / / In this model, 600 pipe spools are to be installed in 15 areas, / so there are 40 spools per area. / / Time units are [days]. / /************************************************************************ /* INPUT PARAMETERS OUTFILE OutputFile "PipeSpool.sto"; VARIABLE SingleRun 1; / Set this variable to 1 meaning yes (0 = no) when you want to collect / data on elements in queues for a SINGLE simulation run, and print / that data to the OutputFile file. This file can then be used to / generate plots using Excel. / When SingleRun equals 0, MULTIPLE runs will be performed in order / to collect statistical data. / Print the column headers for the spreadsheet table: IF SingleRun; PRINT OutputFile "\t Queue \t SimTime \t StagedSpool \t WorkAreaReady \t AreaDone \t DefectSpool \t CutSheet \t WorkArea \t Specs \t Feedback \t Status \n"; ENDIF; /************************************************************************ /* Definition of resource types /=== OFF SITE === GENTYPE AStart; CHARTYPE ATextFile; SUBTYPE ATextFile ASpec; SAVEPROPS ATextFile SpecNo RandomNo; / SpecNo is the number of the specification (Spec), where each Spec will / refer to exactly one isometric (ISO) drawing. / RandomNo truly is a random number. This will be used to define the / draw order to model the uncoordinated and the pull-driven processes. CHARTYPE AGraphicFile; SUBTYPE AGraphicFile ACutSheet; SAVEPROPS AGraphicFile SpecNo DwgNo RandomNo FinalAreaNo AreaReady; / SpecNo is the number of the Spec used as the basis from which to / create cutsheets. It is assumed (later in this file) that there / are 4 cutsheets per ISO. / DwgNo is the number of the cutsheet drawing, and each cutsheet will / refer to exactly one pipe spool's TagNo. / RandomNo truly is a random number. This will be used to define the / draw order to model the uncoordinated and the pull-driven processes. / FinalAreaNo records which area the spool must end up in. / AreaReady is for the pull-driven model to re-sequence spools for / fabrication to match progress on site. GENTYPE ADesignTeam; CHARTYPE AMaterial; SUBTYPE AMaterial ASpool; SAVEPROPS AMaterial TagNo RandomNo FinalAreaNo AreaReady; / TagNo is the spool's identification number that corresponds to the / cutsheet's drawing number (DwgNo). GENTYPE AFabCrew; /=== ON SITE === CHARTYPE ASpace; SUBTYPE ASpace AnArea; SAVEPROPS ASpace AreaNo; / AreaNo is a specific number assigned to each area. / Spaces need not have a RandomNo property, they need not be in random / order. In any model, any order will appear to be random during / simulation, compared to the random ordering of spools. GENTYPE APrepCrew; / Resource to Provide Feedback Necessary to Pull CHARTYPE ADataPiece; SUBTYPE ADataPiece ADatum; SAVEPROPS ADataPiece AreaReadyNo; / === JOINED === GENTYPE AnInstallCrew; COMPTYPE AnAreaDone; SAVEPROPS AnAreaDone MinValTagNo MaxValTagNo AreaNo; /************************************************************************ /* Definition of network nodes /=== OFF SITE === QUEUE StartOffSite AStart; COMBI OffSiteWork; QUEUE Specs ATextFile; QUEUE DesignTeam ADesignTeam; COMBI Design; QUEUE CutSheet AGraphicFile; QUEUE FabCrew AFabCrew; COMBI Fabricate; FORK GoodBad AMaterial; QUEUE DefectSpool AMaterial; / Rework must take place before Fabricate so Rework gets a higher / PRIORITY (default = 0) [Martinez 1996 p. 98] COMBI Rework; PRIORITY Rework 1; CONSOLIDATOR AwaitTransport; NORMAL Transport; /=== ON SITE === QUEUE StartOnSite AStart; COMBI FieldWork; QUEUE WorkArea ASpace; QUEUE PrepCrew APrepCrew; COMBI PrereqWork; /=== JOINED === QUEUE StagedSpool AMaterial; QUEUE WorkAreaReady ASpace; QUEUE InstallCrew AnInstallCrew; COMBI Install; ASSEMBLER SpoolInArea AnAreaDone; QUEUE AreaDone AnAreaDone; /=== PULL === QUEUE Feedback ADataPiece; / Update must take place before Fabricate so Update gets a higher / PRIORITY (default = 0) [Martinez 1996 p. 98] COMBI Update; PRIORITY Update 1; /************************************************************************* /* Definition of network Links /=== ON SITE === / Specify on site before off site this time, so link priorities will be / correct. LINK ON1 StartOnSite FieldWork; LINK CR5 PrepCrew PrereqWork; LINK CR6 PrereqWork PrepCrew; LINK WA1 FieldWork WorkArea; LINK WA2 WorkArea PrereqWork; LINK WA3 PrereqWork WorkAreaReady; LINK WA4 WorkAreaReady Install; / Define WA4 before PS8 (and CR7) to make sure work area will be drawn / before the spool or the crew, as set of spools drawn must match the / work area. [Martinez 1996 p. 89] /=== OFF SITE === LINK OF1 StartOffSite OffSiteWork; LINK SP1 OffSiteWork Specs; LINK SP2 Specs Design; LINK DT1 DesignTeam Design; LINK DT2 Design DesignTeam; LINK DW1 Design CutSheet; LINK DW2 CutSheet Fabricate; LINK CR1 FabCrew Rework; LINK CR2 Rework FabCrew; LINK CR3 FabCrew Fabricate; LINK CR4 Fabricate FabCrew; LINK PS1 Fabricate GoodBad; LINK PS2 GoodBad AwaitTransport; LINK PS3 GoodBad DefectSpool; LINK PS4 DefectSpool Rework; LINK PS5 Rework AwaitTransport AMaterial; LINK PS6 AwaitTransport Transport AMaterial; LINK PS7 Transport StagedSpool; LINK PS8 StagedSpool Install; /=== JOINED === LINK CR7 InstallCrew Install; LINK CR8 Install InstallCrew; LINK WA5 Install SpoolInArea ASpace; LINK PS9 Install SpoolInArea AMaterial; LINK AD1 SpoolInArea AreaDone; /=== Pull === LINK FB1 PrereqWork Feedback; LINK DW3 CutSheet Update; LINK FB2 Feedback Update; / Define DW3 before FB2 so CutSheet gets drawn before Feedback as there / will be many pieces of feedback data that are essentially the same. LINK DW4 Update CutSheet; /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- / OFF-SITE ACTIVITY SEQUENCE /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- /******************** /* Statements to assist in the definition of attributes of StartOffSite / and its related links INIT StartOffSite 1; /******************** /* Startup of OffSiteWork DURATION OffSiteWork '0'; /******************** /* Termination of OffSiteWork VARIABLE TotNoSpecs 150; BEFOREEND OffSiteWork GENERATE TotNoSpecs ASpec; / Number each specification in the order in which it is created. / Since all specs are generated at the same simulation time and none will / have had the chance to leave the Specs queue, Count will be able to / uniquely number each resource entering the Specs queue. ONRELEASE SP1 ASSIGN SpecNo Specs.ASpec.Count+1; / [Martinez 1996 p. 204] / Then assign a random number so their draw sequence (or a discipline / that sorts them upon entry into a queue) can be "random". ONRELEASE SP1 ASSIGN RandomNo Rnd[]; /******************** /* Entry of resources into Specs SAVEVALUE EnteringSpec 0; ONENTRY Specs ASSIGN EnteringSpec EnteringSpec+1; IF SingleRun; ONENTRY Specs PRINT OutputFile "\t Specs \t %.2f \t\t\t\t\t\t\t %.2f \t\t entered \n" SimTime 100*EnteringSpec/TotNoSpecs; ONENTRY Specs PRINT OutputFile "\t Specs \t %.2f \t\t\t\t\t\t\t %f \t\t in \n" SimTime Specs.ASpec.Count; ENDIF; /******************** /* Statements to assist in the definition of attributes of DesignTeam / and its related links INIT DesignTeam 1; /******************** /* Startup of Design IF SingleRun; ONDRAW SP2 PRINT OutputFile "\t Specs \t %.2f \t\t\t\t\t\t\t %.0f \t\t out \n" SimTime Specs.CurCount; ENDIF; DURATION Design '1'; / It takes about 1 day [8 hrs] to create an ISO. / At this time, I have no data on how much time it takes to create / cutsheets once the ISO has been completed. /******************** /* Termination of Design BEFOREEND Design GENERATE 4 ACutSheet; / On average there will be 4 cutsheets per ISO [cf. Mike Villejas at / Jacobs Engineering, personal communication (February 1997)]. SAVEVALUE TempSpecNo 0; BEFOREEND Design ASSIGN TempSpecNo Design.ATextFile.SpecNo; ONRELEASE DW1 ASSIGN SpecNo TempSpecNo; ONRELEASE DW1 ASSIGN RandomNo Rnd[]; / Number the cutsheets incrementally. SAVEVALUE NextCutSheetNo 0; ONRELEASE DW1 ASSIGN NextCutSheetNo NextCutSheetNo+1; ONRELEASE DW1 ASSIGN DwgNo NextCutSheetNo; / Next, figure out which final area the spool will have to be installed in. / This is computed here, though in reality it reflects information shown / in specs and on design dwgs. The formula results in spools 1 through / 40 going to area 1001, 41 through 80 to area 1002, etc.; that is: 40 / spools per area. ONRELEASE DW1 ASSIGN FinalAreaNo 1001+Int[(DwgNo-1)/40]; ONRELEASE DW1 ASSIGN AreaReady 0; / 0 means area on site is NOT yet ready for spool installation, so / that the spool's fabrication is not "urgent". /******************** /* Entry of resources into CutSheet SAVEVALUE EnteringCutSheet 0; ONRELEASE DW1 ASSIGN EnteringCutSheet EnteringCutSheet+1; / Note that there are two links going into the CutSheet Queue. / The "entering" cutsheet counter should ONLY count cutsheets being / output by the Design combi activity and NOT count the updates / being done through link DW3. IF SingleRun; ONENTRY CutSheet PRINT OutputFile "\t CutSheet \t %.2f \t\t\t\t\t %.2f \t\t\t\t entered \n" SimTime 100*EnteringCutSheet/(TotNoSpecs*4); / Compute % of cutsheets that have been prepared. ONENTRY CutSheet PRINT OutputFile "\t CutSheet \t %.2f \t\t\t\t\t %.0f \t\t\t\t in \n" SimTime CutSheet.ACutSheet.Count; ENDIF; /******************** /* Statements to assist in the definition of attributes of FabCrew and /* its related links INIT FabCrew 20; /******************** /* Startup of Fabricate / Coordinated Model: / Process cutsheets in numerical order. / This will be the case by default. No DRAWORDER is to be specified. / Pull and Random Model: / First process CutSheets for which matching area is ready; / then proceed with random ordering. DRAWORDER DW2 '-AreaReady-RandomNo'; / This draw order reflects that spools for which the corresponding / installation area is ready on site (AreaReady = 1) must get fabricated / ahead of others and then rushed to the site. This expression works / because by construction: / AreaReady takes on a value of 0 or 1; / SpecNo, DwgNo, TagNo, or FinalAreaNo takes on a value in thousands. / Random number ranges from 0 to 1 (0 <= Rnd[] <= 1). / and DRAWORDER takes smallest numbers first (ascending order). / In case of the Random model, using DRAWORDER DW2 'RandomNo'; would / work equally well as all CutSheets have the value AreaReady == 0 / by default. Note however that the numerical results will be different / when the simulation is run with a specified seed because of the minus / sign in front of the random number. IF SingleRun; ONDRAW DW2 PRINT OutputFile "\t CutSheet \t %.2f \t\t\t\t\t %.0f \t\t\t\t out \n" SimTime CutSheet.CurCount; ENDIF; / Deterministic Model: / Use a constant value of 5, which is the 'most likely' value / from the Pertpg distribution. /DURATION Fabricate 5; / Random, Coordinated, and Pull-driven Model: / Use the probabilistic duration value from CII report by Howell / and Ballard (1995 p. 19). DURATION Fabricate Pertpg[3,5,14]; /******************** /* Termination of Fabricate / For each cutsheet fabricate one spool. BEFOREEND Fabricate GENERATE 1 ASpool; / Each spool gets the number of the drawing (cutsheet) that shows / its design. BEFOREEND Fabricate ASSIGN Fabricate.AMaterial.TagNo Fabricate.AGraphicFile.DwgNo; / Other property values can also passed along for checking purposes, / though they are not needed further downstream. BEFOREEND Fabricate ASSIGN Fabricate.AMaterial.RandomNo Fabricate.AGraphicFile.RandomNo; BEFOREEND Fabricate ASSIGN Fabricate.AMaterial.FinalAreaNo Fabricate.AGraphicFile.FinalAreaNo; BEFOREEND Fabricate ASSIGN Fabricate.AMaterial.AreaReady Fabricate.AGraphicFile.AreaReady; /************************************************************************* /* Activation of successors and routing of resources through GoodBad / Deterministic Model: / Assume there is no rework so spools will never go to DefectSpool. /STRENGTH PS2 '100'; /STRENGTH PS3 '0'; / Random, Coordinated, and Pull-driven Models: / Assume that 10% of the spools require rework [cf. Glenn Ballard / (1996), personal communication: "industry spool defect rate / ranges from 1 to 10%"]. STRENGTH PS2 '90'; STRENGTH PS3 '10'; /******************** /* Entry of resources into DefectSpool SAVEVALUE EnteringDefectSpool 0; ONENTRY DefectSpool ASSIGN EnteringDefectSpool EnteringDefectSpool+1; IF SingleRun; ONENTRY DefectSpool PRINT OutputFile "\t DefectSpool \t %.2f \t\t\t\t %.2f \t\t\t\t\t entered \n" SimTime 100*EnteringDefectSpool/(TotNoSpecs*4); / Compute % of spools that are defective. ONENTRY DefectSpool PRINT OutputFile "\t DefectSpool \t %.2f \t\t\t\t %.0f \t\t\t\t\t in \n" SimTime DefectSpool.ASpool.Count; ENDIF; /******************** /* Startup of Rework IF SingleRun; ONDRAW PS4 PRINT OutputFile "\t DefectSpool \t %.2f \t\t\t\t %.0f \t\t\t\t\t out \n" SimTime DefectSpool.CurCount; ENDIF; DURATION Rework Pertpg[3,5,14]; / Assume a pretty bad situation (though not necessarily the worst / situation possible): rework takes the same amount of time as / fabricating a new spool. /******************** /* Termination of AwaitTransport CONSOLIDATEWHEN AwaitTransport 'AwaitTransport.ASpool.Count>=10'; / Consolidate 10 spools for each shipment. /******************** /* Startup of Transport / Deterministic Model: / Constant value of 3. /DURATION Transport 3; / Random, Coordinated, and Pull-driven Models: / IDT assumes 3 days plus or minus 1 day. DURATION Transport Normal[3,1]; /******************** /* Entry of resources into StagedSpool SAVEVALUE EnteringStagedSpool 0; ONENTRY StagedSpool ASSIGN EnteringStagedSpool EnteringStagedSpool+1; IF SingleRun; ONENTRY StagedSpool PRINT OutputFile "\t StagedSpool \t %.2f \t %.2f \t\t\t\t\t\t\t\t entered \n" SimTime 100*EnteringStagedSpool/(TotNoSpecs*4); / Keep track of the number of spools that entered this queue / and compute it as a % of the total number of spools. ONENTRY StagedSpool PRINT OutputFile "\t StagedSpool \t %.2f \t %.0f \t\t\t\t\t\t\t\t in \n" SimTime StagedSpool.ASpool.Count; ENDIF; /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- / ON-SITE ACTIVITY SEQUENCE /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- /******************** /* Statements to assist in the definition of attributes of StartOnSite / and its related links INIT StartOnSite 1; /******************** /* Startup of FieldWork DURATION FieldWork '85'; / This number has been chosen by IDT to reflect build-up of buffer of / pipe spools for 95 days (WorkAreas available at time 85 and the first / one readied 10 days later) before installation starts (see deterministic / model for first WorkAreaReady at time 95). / Practitioners say they like spools to be on site for 5 to 6 months / prior to installation! Counting 20 working days per month, 95 days / is nearly 5 months. Of course, the larger the buffer, the smaller the / impact of uncertainty on the downstream process. /******************** /* Termination of FieldWork VARIABLE TotNoAreas 15; BEFOREEND FieldWork GENERATE TotNoAreas AnArea; ONRELEASE WA1 ASSIGN AreaNo WorkArea.AnArea.Count+1001; / This numbers each area in the order in which it is created. / The number is expressed in thousands (4 digits) as opposed to being a / single- or double-digit number. This was determined rather arbitrarily; / otherwise there are just too many simple 1s and 2s to keep track of in / this model. However,note that DRAWORDER DW2 relies on this convention. /******************** /* Entry of resources into WorkArea DISCIPLINE WorkArea 'AreaNo'; SAVEVALUE EnteringWorkArea 0; ONENTRY WorkArea ASSIGN EnteringWorkArea EnteringWorkArea+1; IF SingleRun; ONENTRY WorkArea PRINT OutputFile "\t WorkArea \t %.2f \t\t\t\t\t\t %.2f \t\t\t entered \n" SimTime 100*EnteringWorkArea/TotNoAreas; / Keep track of the number of areas that entered this queue / and compute it as a % of the total number of areas. ONENTRY WorkArea PRINT OutputFile "\t WorkArea \t %.2f \t\t\t\t\t\t %.0f \t\t\t in \n" SimTime WorkArea.AnArea.Count; ENDIF; /******************** /* Statements to assist in the definition of attributes of PrepCrew and / its related links INIT PrepCrew 1; /******************** /* Startup of PrereqWork IF SingleRun; ONDRAW WA2 PRINT OutputFile "\t WorkArea \t %.2f \t\t\t\t\t\t %.0f \t\t\t out \n" SimTime WorkArea.CurCount; ENDIF; DURATION PrereqWork '10'; /******************** /* Termination of PrereqWork /------------------------------------------------------------------------ / Feedback mechanism for pulling /------------------------------------------------------------------------ / The dummy CurrentAreaNo keeps track of the current area number so that / each piece of feedback generated in the PreReqWork combi gets this / number associated with it. It is needed because there are 40 such / pieces generated for each combi instance and ASSIGN only works on / one element at a time. Thus, ONRELEASE is used (instead of ASSIGN) / to assign the area number to the piece of feedback. At the moment / ONRELEASE gets evaluated, though, the combi instance has been / terminated and so the ASpace resource (needed to evaluate / PrereqWork.ASpace.AreaNo) has been destroyed, whereas the dummy can / explicitly keep track of this value, beyond the life of the combi / instance. / Note that STROBOSCOPE will not confuse values of CurrentAreaNo when / multiple instances of PreReqWork exist concurrently as the assignment / is instance-specific. SAVEVALUE Pulling 1; IF Pulling; SAVEVALUE CurrentAreaNo 0; BEFOREEND PrereqWork GENERATE 40 ADatum; BEFOREEND PrereqWork ASSIGN CurrentAreaNo PrereqWork.ASpace.AreaNo; ONRELEASE FB1 ASSIGN AreaReadyNo CurrentAreaNo; /******************** /* Startup of Update /-------------------- / Matching Feedback with CutSheets /-------------------- / For other examples using FILTERS see Martinez (1996) Chapter 12. / SYNTAX: FILTER FilterName CharType CursoredFilterExpression; / SYNTAX: VARPROP TypeName VarPropName ExpressionINTermsOfOtherProps; /-------------------- /Dummy filter to be refined later; any datapiece will do for now. FILTER DataThatMatches ADataPiece 1; / First make sure the cutsheet being considered has not been updated yet. / Next there must be at least one piece of feedback in the Feedback queue / or otherwise there is nothing to be checked. As there may be several / (up to 40) data pieces in that queue that match, take the MinVal to get / a single value (they will all have the same value anyway). VARPROP AGraphicFile FeedBackAvailable 'AreaReady==0 & Feedback.DataThatMatches.Count>0 & Feedback.DataThatMatches.AreaReadyNo.MinVal==FinalAreaNo'; / A cutsheet can be updated if matching feedback is available: FILTER DocumentCanBeUpdated AGraphicFile FeedBackAvailable; / Find which specific cutsheet is being considered for updating: VARIABLE CurrentlyCursoredAreaNo 'DocumentCanBeUpdated.HasCursor ? DocumentCanBeUpdated.FinalAreaNo : DW3.FinalAreaNo'; / For that specific cutsheet, find the matching feedback. Feedback / matches when the area that is ready (AreaReadyNo) equals the final / installation area of the spool shown on the cutsheet (FinalAreaNo). FILTEREXP DataThatMatches 'AreaReadyNo==CurrentlyCursoredAreaNo'; ENOUGH DW3 CutSheet.DocumentCanBeUpdated.Count; / 1 is enough DRAWWHERE DW3 FeedBackAvailable; DRAWWHERE FB2 AreaReadyNo==Update.AGraphicFile.FinalAreaNo; /******************** SAVEVALUE EnteringFeedback 0; ONENTRY Feedback ASSIGN EnteringFeedback EnteringFeedback+1; IF SingleRun; ONENTRY Feedback PRINT OutputFile "\t Feedback \t %.2f \t\t\t\t\t\t\t %.2f \t entered \n" SimTime 100*EnteringFeedback/(TotNoAreas*40); / Keep track of the number of datapieces that entered this queue / and compute it as a % of the total number of data pieces. ONENTRY Feedback PRINT OutputFile "\t Feedback \t %.2f \t\t\t\t\t\t\t %.0f \t in \n" SimTime Feedback.ADatum.Count; ENDIF; IF SingleRun; ONDRAW FB2 PRINT OutputFile "\t Feedback \t %.2f \t\t\t\t\t\t\t %.0f \t out \n" SimTime Feedback.CurCount; ENDIF; /******************** /* Termination of Update ONRELEASE DW4 ASSIGN AreaReady 1; IF SingleRun; ONRELEASE DW4 PRINT OutputFile "Update performed at time %.2f for CutSheet %.0f with FinalAreaNo %.0f generated from SpecNo %.0f \n" SimTime DwgNo FinalAreaNo SpecNo; ENDIF; ENDIF; / end of pulling mechanism /------------------------------------------------------------------------ /******************** /* Entry of resources into WorkAreaReady SAVEVALUE EnteringWorkAreaReady 0; ONENTRY WorkAreaReady ASSIGN EnteringWorkAreaReady EnteringWorkAreaReady+1; IF SingleRun; ONENTRY WorkAreaReady PRINT OutputFile "\t WorkAreaReady \t %.2f \t\t %.2f \t\t\t\t\t\t\t entered \n" SimTime 100*EnteringWorkAreaReady/TotNoAreas; / compute the % of total number of areas ONENTRY WorkAreaReady PRINT OutputFile "\t WorkAreaReady \t %.2f \t\t %.0f \t\t\t\t\t\t\t in \n" SimTime WorkAreaReady.AnArea.Count; ENDIF; /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- / COMBINED ACTIVITY SEQUENCE /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- /******************** /* Statements to assist in the definition of attributes of InstallCrew / and its related links INIT InstallCrew 1; /******************** /* Startup of Install IF SingleRun; ONDRAW WA4 PRINT OutputFile "\t WorkAreaReady \t %.2f \t\t %.0f \t\t\t\t\t\t out \n" SimTime WorkAreaReady.CurCount; ONDRAW PS8 PRINT OutputFile "\t StagedSpool \t %.2f \t %.0f \t\t\t\t\t\t\t out \n" SimTime StagedSpool.CurCount; ENDIF; DURATION Install 10; /------------------------------------------------------------------------ / Strategy for matching spools with areas. /------------------------------------------------------------------------ / Areas are served in FIFO order if possible, otherwise serve the first / area for with the 40 matching spools are available. Each spool must / match the area that is drawn from the WorkAreaReady queue. /------------------------------------------------------------------------ / NOTE: need to define the WA4 link BEFORE the PS8 link, / i.e., first define the link through which areas are drawn. / SpoolThatMatches is a dummy filter for now. / Any spool will do; this filter will get refined later on. FILTER SpoolThatMatches AMaterial 1; / VARPROP will be TRUE for Areas for which 40 matching spools are / available in the StagedSpool queue: / Count that there are at least 40 spools in the queue, if not, there is / no chance of finding 40 matching ones anyways. Count is also needed to / make sure at least one element is in the StagedSpool queue; otherwise, / STROBOSCOPE gives a run-time error. VARPROP ASpace MatchingSpoolAvail 'StagedSpool.SpoolThatMatches.Count>=40 & AreaNo==StagedSpool.SpoolThatMatches.FinalAreaNo.MinVal'; / Filter to single out those areas for which a matching spool is available: FILTER AreaWSpoolReady ASpace MatchingSpoolAvail; / Now get the specific area number of the area first in line for which a / matching spool is available: VARIABLE NowCursoredAreaNo 'AreaWSpoolReady.HasCursor ? AreaWSpoolReady.AreaNo : WA4.AreaNo'; / Once we know which area we are talking about, get the corresponding / spool(s). This redefines the dummy filter that was used at first. FILTEREXP SpoolThatMatches FinalAreaNo==NowCursoredAreaNo; / We have enough areas if there is at least one in the queue from which / we are going to draw for which the matching spool is available: ENOUGH WA4 WorkAreaReady.AreaWSpoolReady.Count; / Now draw the area for which there is a set of matching spools: DRAWWHERE WA4 MatchingSpoolAvail; / The attribute of PS8 assumes that the area is in the Install instance. DRAWWHERE PS8 FinalAreaNo==Install.ASpace.AreaNo; / Note that in this model 40 spools will match, so DRAWUNTIL *is* needed, / otherwise only one spool will be drawn from the StagedSpool queue. DRAWUNTIL PS8 Install.AMaterial.Count>=40; /******************** /* Assembly of resources in SpoolInArea ONASSEMBLY SpoolInArea ASSIGN AreaNo SpoolInArea.ASpace.AreaNo; ONASSEMBLY SpoolInArea ASSIGN MinValTagNo SpoolInArea.AMaterial.TagNo.MinVal; ONASSEMBLY SpoolInArea ASSIGN MaxValTagNo SpoolInArea.AMaterial.TagNo.MaxVal; /******************** /* Entry of resources into AreaDone SAVEVALUE EnteringAreaDone 0; ONENTRY AreaDone ASSIGN EnteringAreaDone EnteringAreaDone+1; FILTER AreaThatIsDone AnAreaDone 1; IF SingleRun; ONENTRY AreaDone PRINT OutputFile "\t AreaDone \t %.2f \t\t\t %.2f \t\t\t\t\t entered \n" SimTime 100*EnteringAreaDone/TotNoAreas; / Compute % of areas completed. ONENTRY AreaDone PRINT OutputFile "\t AreaDone \t %.2f \t\t\t %.0f \t\t\t\t\t in \n" SimTime AreaDone.AreaThatIsDone.Count; ENDIF; /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- / Go Single Run! /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- / Use the following two lines to run a single simulation. / The seed as shown is the one used in Tommelein's 1997 IGLC-5 and her / ASCE Construction Congress V papers. IF SingleRun; SEED 527817728; SIMULATE; ENDIF; /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- / Go Multiple Runs! /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- / When doing multiple runs, set the variable SingleRun at the beginning / of this file == 0. This will cause STROBOSCOPE to use the following / code to obtain certainty intervals on numbers of resources and times / to reach completion by collecting data over multiple simulation runs. IF !SingleRun; /******************** /* DATA COLLECTION /******************** / Save values of interest during each simulation run for each of the / following variables: / EnteringSpec <- not interesting; 150 Specs will be / available simultaneously at simulation time 0. / EnteringCutSheet / EnteringDefectSpool / EnteringStagedSpool / EnteringWorkArea <- not interesting; 15 Areas will be / available simultaneously at simulation time 85. / EnteringWorkAreaReady / EnteringAreaDone / EnteringFeedback / For the single-run case, this was done using SAVEVALUEs in the / (see preceding code) but now multiple values need to be COLLECTed / and then statistically processed. / Save the project duration (which is when Install last finishes): SAVEVALUE ProjectFinish 0; ONENTRY AreaDone ASSIGN ProjectFinish 'EnteringAreaDone==15&ProjectFinish==0 ? SimTime : 0'; /******************** / Introduce the TimeStep combi so we will be certain that the / simulation clock reaches the exact times at which we want to / collect data. VARIABLE TimeStepSize 10; COMBI TimeStep; SEMAPHORE TimeStep !TimeStep.CurInst; / Allow only one instance to exist at a time. DURATION TimeStep TimeStepSize; / Data will be collected every X=TimeStepSize days. BEFOREEND TimeStep PRINT OutputFile "Time is now %6.4f \n" SimTime; / Make sure the simulation does not go on forever (TimeStep would). / Set simulation end time at 450 which should be upper bound on the / project completion time using random sequencing. VARIABLE EndTime 500; SIMULATEUNTIL SimTime>=EndTime; /******************** /* COLLECTORS /******************** / Define collectors that will gather data over multiple simulation runs. / Collectors need to be persistent (add '*' to their name to make them / persistent) or else the data will get lost when the CLEAR command is / invoked upon start of a new iteration. COLLECTOR ProjDuration*; COLLECTOR InstallFirstCollector*; SAVEVALUE CurrentStep 0; WHILE CurrentStep<=EndTime; COLLECTOR PercentCutSheetAtTime$$*; COLLECTOR NrCutSheetAtTime$$*; COLLECTOR PercentDefectSpoolAtTime$$*; COLLECTOR NrDefectSpoolAtTime$$*; COLLECTOR PercentStagedSpoolAtTime$$*; COLLECTOR NrStagedSpoolAtTime$$*; COLLECTOR PercentFeedbackAtTime$$*; COLLECTOR NrFeedbackAtTime$$*; COLLECTOR PercentWorkAreaReadyAtTime$$*; COLLECTOR NrWorkAreaReadyAtTime$$*; COLLECTOR PercentAreaDoneAtTime$$*; COLLECTOR NrAreaDoneAtTime$$*; ASSIGN CurrentStep CurrentStep+TimeStepSize; WEND; /******************** /* ITERATION /******************** VARIABLE NrIterations 1000; SAVEVALUE CurrentIteration* 1; SAVEVALUE CurrentStepTwo* 0; WHILE CurrentIteration<=NrIterations; CLEAR; INIT StartOffSite 1; INIT DesignTeam 1; INIT FabCrew 20; INIT StartOnSite 1; INIT PrepCrew 1; INIT InstallCrew 1; WHILE CurrentStepTwo<=EndTime; SIMULATEUNTIL SimTime>=CurrentStepTwo; COLLECT PercentCutSheetAtTime$$ 100*EnteringCutSheet/(TotNoSpecs*4); COLLECT NrCutSheetAtTime$$ CutSheet.ACutSheet.Count; COLLECT PercentDefectSpoolAtTime$$ 100*EnteringDefectSpool/(TotNoSpecs*4); COLLECT NrDefectSpoolAtTime$$ DefectSpool.ASpool.Count; COLLECT PercentStagedSpoolAtTime$$ 100*EnteringStagedSpool/(TotNoSpecs*4); COLLECT NrStagedSpoolAtTime$$ StagedSpool.ASpool.Count; IF Pulling; COLLECT PercentFeedbackAtTime$$ 100*EnteringFeedback/(TotNoAreas*40); COLLECT NrFeedbackAtTime$$ Feedback.ADatum.Count; ENDIF; COLLECT PercentWorkAreaReadyAtTime$$ 100*EnteringWorkAreaReady/TotNoAreas; COLLECT NrWorkAreaReadyAtTime$$ WorkAreaReady.AnArea.Count; COLLECT PercentAreaDoneAtTime$$ 100*EnteringAreaDone/TotNoAreas; COLLECT NrAreaDoneAtTime$$ AreaDone.AreaThatIsDone.Count; PRINT OutputFile "Time %f CutSheet %.4f %.0f DefectSpool %.4f %.0f StagedSpool %.4f %.0f Feedback %.4f %.0f WorkAreaReady %.4f %.0f AreaDone %.4f %.0f \n" CurrentStepTwo 100*EnteringCutSheet/(TotNoSpecs*4) CutSheet.ACutSheet.Count 100*EnteringDefectSpool/(TotNoSpecs*4) DefectSpool.ASpool.Count 100*EnteringStagedSpool/(TotNoSpecs*4) StagedSpool.ASpool.Count 100*EnteringFeedback/(TotNoAreas*40) Feedback.ADatum.Count 100*EnteringWorkAreaReady/TotNoAreas WorkAreaReady.AnArea.Count 100*EnteringAreaDone/TotNoAreas AreaDone.AreaThatIsDone.Count; ASSIGN CurrentStepTwo CurrentStepTwo+TimeStepSize; WEND; COLLECT ProjDuration ProjectFinish; COLLECT InstallFirstCollector Install.FirstStart; PRINT OutputFile " + - + - + - + - + - + - + - \n"; PRINT OutputFile "Iteration %.0f Project Finish %.4f \n" CurrentIteration ProjectFinish; PRINT OutputFile " + - + - + - + - + - + - + - \n"; ASSIGN CurrentIteration CurrentIteration+1; ASSIGN CurrentStepTwo 0; WEND; ENDIF; /******************** /* REPORTING /******************** / Now that iterations are done, print out statistics on the collectors. REPORT; /*** END * OF * FILE *************************************************