# =========================================================================== # Copyright 2013 University of Limerick # # This file is part of DREAM. # # DREAM is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # DREAM is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with DREAM. If not, see <http://www.gnu.org/licenses/>. # =========================================================================== ''' Created on 8 Nov 2012 @author: George ''' ''' models the source object that generates the entities ''' from SimPy.Simulation import now, Process, Resource, infinity, hold from Part import Part from RandomNumberGenerator import RandomNumberGenerator from CoreObject import CoreObject from Globals import G #============================================================================ # The Source object is a Process #============================================================================ class Source(CoreObject): def __init__(self, id, name, distribution='Fixed', mean=1, item=Part): Process.__init__(self) # general properties self.id=id self.objName=name self.distType=distribution # label that sets the distribution type # properties used for statistics self.totalInterArrivalTime=0 # the total interarrival time self.numberOfArrivals=0 # the number of entities that were created # list containing objects that follow in the routing self.next=[] # list with the next objects in the flow self.nextIds=[] # list with the ids of the next objects in the flow self.previousIds=[] # list with the ids of the previous objects in the flow. # For the source it is always empty! self.type="Source" #String that shows the type of object self.rng=RandomNumberGenerator(self, self.distType) self.rng.avg=mean self.item=item #the type of object that the Source will generate def initialize(self): # using the Process __init__ and not the CoreObject __init__ CoreObject.initialize(self) # Process.__init__(self) # # no predecessor or successor index # self.Up=True #Boolean that shows if the object is in failure ("Down") or not ("up") # self.currentEntity=None # # ============================== total times =============================================== # self.totalBlockageTime=0 #holds the total blockage time # self.totalFailureTime=0 #holds the total failure time # self.totalWaitingTime=0 #holds the total waiting time # self.totalWorkingTime=0 #holds the total working time # self.completedJobs=0 #holds the number of completed jobs # # ============================== Entity related attributes ================================= # self.timeLastEntityEnded=0 #holds the last time that an entity # # ended processing in the object # self.nameLastEntityEnded="" #holds the name of the last entity # #that ended processing in the object # self.timeLastEntityEntered=0 #holds the last time that an # #entity entered in the object # self.nameLastEntityEntered="" #holds the name of the last # #entity that entered in the object # self.timeLastFailure=0 #holds the time that the last # #failure of the object started # self.timeLastFailureEnded=0 #holds the time that the last # #failure of the object Ended # # ============================== failure related times ===================================== # self.downTimeProcessingCurrentEntity=0 #holds the time that the object was down # #while processing the current entity # self.downTimeInTryingToReleaseCurrentEntity=0 #holds the time that the object was down while trying # #to release the current entity # self.downTimeInCurrentEntity=0 #holds the total time that the object was down # #while holding current entity # self.timeLastEntityLeft=0 #holds the last time that an entity left the object # # self.processingTimeOfCurrentEntity=0 #holds the total processing time that the current entity required # # ============================== waiting flag ============================================== # self.waitToDispose=False #shows if the object waits to dispose an entity # initialize the internal Queue (type Resource) of the Source self.Res=Resource(capacity=infinity) self.Res.activeQ=[] self.Res.waitQ=[] def run(self): # get active object and its queue activeObject=self.getActiveObject() activeObjectQueue=self.getActiveObjectQueue() while 1: entity=self.createEntity() # create the Entity object and assign its name entity.creationTime=now() # assign the current simulation time as the Entity's creation time entity.startTime=now() # assign the current simulation time as the Entity's start time entity.currentStation=self # update the current station of the Entity self.outputTrace(self.item.type+\ str(self.numberOfArrivals)) # output the trace activeObjectQueue.append(entity) # append the entity to the resource self.numberOfArrivals+=1 # we have one new arrival G.numberOfEntities+=1 yield hold,self,self.calculateInterarrivalTime() # wait until the next arrival #============================================================================ # sets the routing out element for the Source #============================================================================ def defineRouting(self, successorList=[]): self.next=successorList # only successors allowed for the source #============================================================================ # creates an Entity #============================================================================ def createEntity(self): return self.item(id = self.item.type+str(G.numberOfEntities), name = self.item.type+str(self.numberOfArrivals)) #return the newly created Entity #============================================================================ # calculates the processing time #============================================================================ def calculateInterarrivalTime(self): return self.rng.generateNumber() #this is if we have a default interarrival time for all the entities #============================================================================ # outputs message to the trace.xls. # Format is (Simulation Time | Entity Name | "generated") #============================================================================ def outputTrace(self, message): from Globals import G if(G.trace=="Yes"): # output only if the user has selected to # handle the 3 columns G.traceSheet.write(G.traceIndex,0,str(now())) G.traceSheet.write(G.traceIndex,1,message) G.traceSheet.write(G.traceIndex,2,"generated") G.traceIndex+=1 #increment the row # if we reach row 65536 we need to create a new sheet (excel limitation) if(G.traceIndex==65536): G.traceIndex=0 G.sheetIndex+=1 G.traceSheet=G.traceFile.add_sheet('sheet '+str(G.sheetIndex), cell_overwrite_ok=True)