Tech Note

Title:               Product Flow in a Stochastic Facility Model
Date:              February 13, 2007
Written by:     Peter Bosch
Number:        TN-016
Version:         0.1

The primary activity that happens in a Stochastic Facility Model is that of moving and transforming lots, each of which activities may or may not consume time, acquire or release resources, and relate in some way to some other activity. This tech note describes that process in the stochastic facility model, from the Market’s introduction of an Order into a model, to the Manufacturer’s delivery of a corresponding shipment back to the market. It should be understood that the Market and an Enterprise are relative and metaphorical. While this implementation will include a Market and an Enterprise class, any object that expresses a need for goods is a Market - and expresses the fact by implementing the IMarket interface. Similarly, any object that is able to satisfy some need expressible by a market, is an Enterprise, expressed by its’ implementing the IProducer interface. A Manufacturer of one type of finished goods may be a Market for a different set of raw materials.

An Enterprise has an Order Dispatcher, defines Policies and contains Facilities. Facilities imply a physical location, and may contain other facilities. Each Facility has a dispatcher, a set of zero or more processes, and zero or more resource managers (pools.) Facilities may eventually have policies as well.

An Order Dispatcher receives orders and returns shipments. It typically creates work items and sends them to facilities for processing. When a work item is returned from the facility, its state may be “in process” or “complete”. If its state indicates that it is still in process, then the Order Dispatcher must know which facility to send the work item to for further processing. If a work item is returned to an order dispatcher in the “complete” state, the order dispatcher is also responsible for deciding when to collect the results of one or more work items whose processing has completed into a shipment to forward back to the market.

A Facility Dispatcher receives work items and routes them to sub-facilities or to processes that it owns. When a work items returns from processing, the Facility Dispatcher must know whether to pass it down into another facility, another process, or return it back upward to the dispatcher that initially provided it.

A Manufacturing Process is a hierarchical step-based construct. See figure 2 for the structure of Processes in general.

drug product plant structure

Figure 1 : Drug Product Plant Structure


process structure

Figure 2 : Process Structure

In Sage® Fab Advisor™ version 1, Customers are modeled as ProductionRequestSource objects. Customers are a part of the Market, which is a part of the Sage Model. During initialization of the model, Customers provide all of their pending orders to the FabProductDispatcher (1).

The FabProductDispatcher, upon receiving an order, creates a LotStream object, and adds it to a sorted collection of LotStream objects that it maintains (2). This is the only way that a LotStream may be added to a FabProductDispatcher. LotStreams are sorted by which one has the soonest lot to be released.

When the model starts, the FabProductDispatcher inspects its list of LotStreams, and for the first LotStream, asks it to emit a lot (3), and schedules an event for that release. When that scheduled time arrives, the FabProductDispatcher retrieves a carrier from the carrier pool (4), places the lot into the carrier and the lot onto the LoadingDock (5), advances the lot’s MasterCursor, and asks the MasterCursor which tool family it must first visit. Then that ToolFamily (which implements ICarrierDispatcher) is asked to accept the Lot. Finally, the FabProductDispatcher resorts its list of LotStreams, and asks the next-to-emit LotStream to emit a new lot, schedules that lot for release and the cycle continues.

A ToolFamily, upon being asked to accept a lot, will first query its member tools to determine if a tool is available that can work on the lot. If it locates one, it tells that tool to accept the lot (note that the lot is still at its preceding location – it has not been moved yet.)

Upon accepting the lot, a tool will ask the TransportSystem to move the lot to the tool (7,8,9) Upon its arrival at the tool, it occupies a LoadPort, and at some point after that (depending on details of the tool itself), the lot is inducted into the tool, and for a period of time the tool works on the Lot. Finally, the tool notifies the ToolFamily that it has completed work on that lot. The ToolFamily then advances the Lot’s MasterCursor, asks the MasterCursor what ToolFamily is next, and asks that ToolFamily to accept the Lot. The next ToolFamily accepts the lot, and again, the cycle continues.

If a ToolFamily is unable to find a suitable tool to work on the Lot, it asks the TransportSystem to move the Lot to its LocalStorage location, which is a PassiveStorage object – able to receive, store and emit ITransportable implementers on request. The Lot will remain in the LocalStorage location until the ToolFamily finds a tool to work on the Lot, and that Tool asks the TransportSystem to move the Lot to the Tool.

When a Tool has completed processing the last step in a Lot’s ProcessFlow, it notifies the ToolFamily, which advances the MasterCursor. The MasterCursor now indicates that the FabProductDispatcher is the next ICarrierDispatcher to receive custody of the Lot. The FabProductDispatcher accepts responsibility for the Lot, and asks the TransportSystem to move the Lot to the LoadingDock (10), where it stays until the simulation is done.

The architecture supports a ShipmentGenerationStrategy which, while currently unimplemented, can decide when enough lots from a given LotStream have been completed, gather up those lots from the LoadingDock (11), and send them in a Shipment to the Customer who originally submitted the order.


More Detailed Notes (20050914)

Model is constructed. Lots of model objects get created, Initialize(...) is called on each.

Each Initialize(...) call results in a request to the InitializationManager to make a deferred call to _Initialize(...)

Main code calls Model.Initialize().

On commit, in the transition to Initializing, InitializationManager sorts model objects' init requests, and calls them.

Each model object's _Initialize(...) call sets internal state, including as it relates to other model objects. Demand Source loads or creates an array of Demand Elements.

Model enters Initializing state.

Automatic follow-on to 'initialized' state takes place.

On commit to Initialized, the transport system recalculates, if necessary. This generates the transport (from/to) cost matrix.

On commit to Initialized, all tool dispatchers register for notification when a carrier arrives at one of their load ports.

Model is done initializing.

Recorder, if attached, detaches.

Main code calls Model.Validate().

Model transitions to Validating state.

Automatic follow-on to Validated state.

Main code calls Run(); Model state transitions to Running.

On commit to running, Demand source sorts all of its Demand Elements, figures out the next order submission time, and registers a callback at that time to EmitProductionRequest(...).

At the appropriate time, FabProductDispatcher.EmitProductionRequest() is called.

The DemandSource requires its productionRequestSink (FabProductDispatcher) to accept the production request. productionRequestSink.Accept(...).

Whenever the FabProductDispatcher is asked to accept a ProductionRequest, it creates a new LotStream, and initializes it with the productionRequest (i.e. where the lots come from) and its defaultShipmentGenerationStrategy (how it is to determine that a set of completed lots should be transformed into a shipment) and a shipmentSink (where to send the shipments to). It then adds the new lotStream to the LotStreamManager, and calls Dispatch, to send a lot if appropriate.

Whenever the FabProductDispatcher.Dispatch(...) method is called, it grabs a carrier from the carrier pool, and a lot from the next lotStream. If the carrier is not available, or the next LotStream has no next lot, then it returns the carrier to the carrier pool.

If the FabProductDispatcher finds both a carrier and a lot, then it advances the cursor on the carrier's first lot's first process flow's cursor, and asks the first recipient (a toolfamily) if it can accept the lot. If it can, then it is asked to do so, and WIP level in the plant is increased. If it cannot, then the lot is returned to the LotStream.

When a ToolFamily is asked to accept the lot, it does so, at this point, unconditionally, passing the carrier to the ToolFamilyDispatcher's AcceptResponsibility method.

When the ToolFamilyDispatcher is asked to accept responsibility for a carrier, it first tries to find a tool dispatcher to immediately accept the carrier. If it can find such a tool dispatcher, it passes responsibility for that carrier to that tool's toolDispatcher. If not, it moves the carrier to an interim storage location, currently in a single, unconstrained PassiveStorage device.

When a tool dispatcher is asked to accept a carrier, it checks its pending carriers list. If this list is empty, then it begins to process the carrier. If it has pending carriers, then it usually (with decreasing probability as the pending list gets fuller) accepts responsibility and calls for a move from wherever the the carrier currently sits, to its PassiveStorage device. With increasing probability as the list gets fuller, it refuses to accept the carrier.

When a tool dispatcher begins to process a carrier, it finds a free load port, if one exists, and moves the carrier to that load port. If it cannot find a free load port, then //TODO: it moves the carrier to a passiveStorage device.

When a tool dispatcher identifies a load port to receive the carrier, it orders a move from its current location to that load port.

When a carrier arrives at a load port, the tool is marked as not-idle, and a call to 'DoneProcessing' is scheduled at the appropriate time.

"When DoneProcessing" is called, the tool is (erroneously) marked as idle, and the tool family is informed that the tool has finished with the carrier. The tool family advances the carrier's master cursor, and tries to get that next recipient (another tool family) to accept responsibility for that carrier, starting the process over again.

The last 'NextRecipient' is the FabProductDispatcher, which when it is asked, always accepts responsibility, advances the lot's cursor, and moves the carrier to the loading dock, at which time it is done with manufacturing. If there is a ShipmentGenerationStrategy assigned to the FabProductDispatcher, then we will, at some point, send the lots’ wafers, in a shipment, to the ShipmentSink (probably the customer…)