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
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.
Figure 1 : Drug Product Plant 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
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
If a ToolFamily is unable to find a suitable tool to work on
the Lot, it asks the TransportSystem to move the
When a Tool has completed processing the last step in a
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.
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…)