None Notebook

This notebook contains material from cbe30338-2021; content is available on Github.

< 7.4 Batch Chemical Process | Contents | Tag Index | 8.0 Projects >

Open in Colab

Download

7.5 Simulating Queuing Systems

Queuing theory is one of the foundations for the analysis of discrete-event systems. This notebook introduces the nomenclature and terminology of queuing theory that will be used in later applications.

7.5.1 Examples of Queues

Manufacturing Lines

Tesla China - Shanghai Gigafactory production line.

7.5.1.1 Service Lines

mathworks queue

7.5.2 Concepts

7.5.2.1 Nomenclature

7.5.2.2 Service Disciplines (of many possibilities)

7.5.3 Poisson Process

Poisson processes describe the occurance of independent random events. Examples:

Poisson processes are a useful approximation for many simulations, and also very easy to implement in practice. This section introduces some theory before describing a typical implementation.

Binomial distribution

Suppose there is a probability $p$ of an event occurring in a short interval. We'll assume the interval is short enough that two or more events in the same interval would be extremely unlikely. Assuming each event is independent, the probability of seeing $k$ events in $n$ intervals is given by the binomial distribution

$$\text{Binomial}(k | n, p) = \frac{n!}{k! (n-k)!} p^k (1 - p)^{n-k}$$

The term $p^k (1 - p)^{n-k}$ is the probability of seeing a particular sequence of $k$ intervals with events and $n-k$ intervals with no events, assuming all of the events are independent of one another. The multiplier $\frac{n!}{k! (n-k)!}$ is the number of different sequences that can be constructed from $k$ events occurring in $n$ intervals.

7.5.3.1 Poisson distribution

Now imagine the events are occuring at an average rate $r$ of events per unit time. In period $t$ there would be, on average, $r t$ events. If that period is broken into $n$ intervals then

$$ p = \frac{rt}{n}$$

which leads to the Poisson distribution

$$\begin{align*} \text{Poisson}(k | r, t) & = \lim_{n\rightarrow\infty}\text{Binomial}(k | n, \frac{rt}{n}) \\ & = \lim_{n\rightarrow\infty} \frac{n!}{k! (n-k)!} (\frac{rt}{n})^k (1 - \frac{rt}{n})^{n-k} \end{align*}$$

We're interested in the limit $n\rightarrow\infty$. Without detailing the math, the limit works out to be

$$\text{Poisson}(k | r, t) = \frac{(rt)^k e^{-rt}}{k!}$$

which is the probability of seeing $k$ events in an interval of length $t$ when the average rate is $r$ events per unit time.

7.5.3.2 Waiting time between events

Suppose an event has just occurred. What is the probability of no additional events in the next $t$ units of time? This is calculated with the Poisson distribution where $k=0$.

$$\text{Poisson}(0 | r, t) = e^{-r t}$$

We can treat this as the probability distribution for the time period between events. We refer to this as the exponential distribution

$$\text{Exponential}(t | r) = e^{-r t}$$

This fact is useful in creating simulations of independent random events. For a given rate $r$, we sample values from an exponential distribution.

7.5.4 Simulating a Poisson Process in SimPy

Poisson processes are easy to implement in SimPy. A single parameter, commonly denoted as $r$ or $\lambda$, is required to specify the average rate of occurance in units of number per unit time. For example, a value $\lambda = 4.2 \text{ min}^{-1}$ corresponds to an average of 4.2 events per minute.

An alternative specification is so express the mean time between events. The rate of machine failures, for example, is typically specified as "mean time between failures" (MTBF). In these cases, $r = \lambda = \frac{1}{\bar{\tau}}$ where $\bar{\tau}$ is the mean time between events.

Once the mean rate has been determined, the time between events can be simulated by drawing samples from an exponential distribution

$$\text{Exponential}(t | r) = e^{-r t}$$

The following cell demonstrates the simulation of a Poisson process with an average $r$ events per unit time.

Visualization

7.5.5 Kendall notation for queues

Kendall notation is a standardized methods to describe and classify queues. The notation consists of three factors written as A/S/c where where A describes the arrival process, S the service process, and c is the number of servers attending the queue.

Example: M/D/1

Aircraft queue

Example: M/M/8

Call Center

7.5.6 Example: Simulation of an Order Processing Queue

A chemical storeroom processes orders for a large research campus. At peak loads it is expected to receive an average of one order every 12 minutes. The time required to process each order is a fixed 10 minutes.

  1. Describe the process using the Kendall notation: M/D/1

  2. Create a simulation of the order queue that operates for 8 hours. Determine the average time between the arrival and completion of an order, and determine the average queue length.

7.5.7 Batch Processing Example (NEEDS REWORK)

Note that this model is incorrect! Update expected soon.

Schultheisz, Daniel, and Jude T. Sommerfeld. "Discrete-Event Simulation in Chemical Engineering." Chemical Engineering Education 22.2 (1988): 98-102.

Batch Process

"... a small, single-product batch chemical plant has three identical reactors in parallel, followed by a single storage tank and a batch still. Customer orders (batches) to be filled (which begin with processing in the reactor) occur every 115 ± 30 minutes, uniformly distributed. The reaction time in a given reactor is 335 ± 60 minutes, and the distillation time in the still is 110 ± 25 minutes, both times uniformly distributed. The holding capacity of the storage tank is exactly one batch. Hence, the storage tank must be empty for a given reactor to discharge its batch; if not, the reactor cannot begin processing a new batch until the storage tank becomes empty. The simulation is to be run for 100 batches. The model should have the capability to collect waiting line statistics for the queue im- mediately upstream of the reactor.""

G/G/3

The first step in any SimPy simulation is to setup the simulation environment and define any shared resources that may be used in the course of the simulation.

In this application, the batch process is conceptually modeled as a sequence of components that process individual orders. Here we use the SimPy Store primative to describe the reactor queue and storage tank. These components will accept orders corresponding to batches, and process them on a first-in, first-out (FIFO) basis. We'll put no upper limit on the orders that can be stored in the reactor queue, but we will establish the storage tank so that it can accept only one batch at a time.

Next we turn to the process that will generate the customer orders. The function order_generator begins by initializing a counter that will be used to assigned a consecutive order numbers, after which order_generator enters a loop that will create a total of 100 orders for the simulation.

At the start of each loop, order_generator issues a yield statement that will return control back to the simulation for a simulated period extending into the future. The period is given by a random number uniformly distributed in the range 115 +/- 30 minutes.

Technically speaking, the yield statement defines the function as a generator of events, and provides the means for order_generator to communicate with other processes and to be controlled by the simulation environment. At least one yield statement is needed in every function that will simulate a SimPy process.

Once control returns to order_generator, the order counter is incremented and a second yield used to request the simuation environment put the order into the reactor queue. On return the order_generator completes the loop by writing an entry into the simulation log.

The env.process() creates order generator within the simulation environment. The actual simulation, however, happens later when we use env.run() after creating the other needed processes for this application.

The user is responsible for managing the logging of simulation events. A simple but useful approach is to initialize a Python list, then append data containing a description of the event and time at which it occurred. Later we'll see how to process this log to get the desired process performance indicators.

Next we create a function batch_reactor that will be use to create processes corresponding to each of the three batch reactors. Each reactor is assigned a unique name so they can be distinguished in the simulation log.

The batch reactors have three interactions with the simulation environment. The first is to get an orderID from the reactor_queue. The batch_reactor yields to the simulation environment until an order is ready for processing. Once the processing can start, and suitable event is written to the log, the process waits a period of time corresponding the length of the reaction, and the order put into the storage_tank. The reactor will wait until the storage tank is ready to accept a new batch.

env.process() is called three times to put three copies of the batch_reactor process into the simulation environment.

The last process to model is the batch still. Similar to the reactor model, batch_still yields control while waiting for an orderID to be retrieved from a preceding unit. Once an order has been received from the storage_tank, a message is written to the simulation log, time is yielded to the simulation environment corresponding to the time required for distillation, and then a final completion message is written to the log.

We're now ready to run the the simulation. In this case the simulation is limited to the 100 orders generated in the order_generator process. Simulation is complete once all of the resulting events have been processed.

7.5.8 Processing the Simulation Log

< 7.4 Batch Chemical Process | Contents | Tag Index | 8.0 Projects >

Open in Colab

Download