ATTENTION

This FlexSim Community Forum is read-only. Please post any new questions, ideas, or discussions to our new community (we call it Answers) at https://answers.flexsim.com/. Our new Question & Answer site brings a modern, mobile-friendly interface and more focus on getting answers quickly. There are a few differences between how our new Q&A community works vs. a classic, threaded-conversation-style forum like the one below, so be sure to read our Answers Best Practices.


flexsim.com

Go Back   FlexSim Community Forum > FlexSim Healthcare (HC) > FlexSim HC: Q&A
Downloads

FlexSim HC: Q&A Questions about FlexSim Healthcare

  #1  
Old 03-24-2014
Pongjetanapong Pongjetanapong is offline
Flexsim User
 
Join Date: Jul 2013
Posts: 19
Downloads: 5
Uploads: 0
Thanks: 8
Thanked 2 Times in 2 Posts
Rep Power: 85
Pongjetanapong is on a distinguished road
Question OnResourceAvailable & Queue strategy

Hi All,

I know that in General Flexsim you can edit the code in the "OnResourceAvailable" trigger to customize the queue strategy when a taskexecuter fire an "OnresourceAvailable" function. Can we do that in Flexsim HC?

Thank you in advance
Ploy
  #2  
Old 03-27-2014
mefhsmflexsimbr mefhsmflexsimbr is offline
FlexSim Brasil
 
Join Date: May 2013
Location: Campinas, SP Brasil
Posts: 23
Downloads: 10
Uploads: 0
Thanks: 73
Thanked 10 Times in 8 Posts
Rep Power: 92
mefhsmflexsimbr is on a distinguished road
Default Questions about FlexSim Healthcare

That´s for HC:
During the course of a model run, requests are made for resources to perform a series of tasks. These requests, otherwise known as task sequences, are generated by patient activities to satisfy staff, equipment and transport requirements. Staff requests are also be generated by Item objects to perform setup and process times, and to call staff for transporting flow items.

Resource requests are sent to either alternate groups, primary groups, or directly to the resources themselves. It’s possible for alternate group members to be resources, primary groups or even other alternate groups. Primary groups, of course, only have their own resources as members, and individual resources do not have members at all. The members of a group are connected to the output ports of the group object.

When a request cannot be acted upon immediately by a resource, the request must wait in queue. Both resources and group objects have a variable called the “tasksequencequeue” where requests (i.e. task sequences) queue up when waiting to be activated. Requests can be designated for a specific resource, or designated for any member of a particular group. There will always be a group association for requests generated by activities, even when the request is for a specific resource. The group association is used to determine where a request will be redirected when the intended resource is off schedule and cannot be preempted. Requests that meet certain criteria are allowed to preempt (interrupt/abort) the active task sequence of a resource, rather than sit in queue and wait for the resource to become available.

Two events play a key role in the handling of requests: 1) when a request is first generated and sent to a resource or group, and 2) when a resource completes one task sequence and becomes available to receive another. The first event will fire the receivetasksequence() method on the group or resource that received the dispatched request. The second event fires the OnResourceAvailable() method of the resource who became available (just finished a task sequence).

Dispatcher::receivetasksequence()
The general purpose of the receivetasksequence() function for a group object is to determine which resource, if any, should ultimately receive and activate the request. This is accomplished through the “Member Selection Policy” which can be modified or completely redefined by the user. The standard selection policy is described here.

The purpose of the selection process is to choose which, if any, of the downstream objects connected to a group’s output ports, the newly received request should be sent to. This involves looking for candidate resources that are connected directly to the group, or connected to another group object that is connected to the group. For a resource to be considered a candidate, it must pass certain requirements. Candidates are then given a score by which they are compared with other candidates. The request will be dispatched to the candidate with the highest score, or if the candidate is connected to a member that is a group, then the request will first be dispatched to the group which will dispatch it to the actual candidate resource.

The scoring system is a little different depending on a user-specified criteria of either PROXIMITY (closest resource) or UTILIZATION (least utilized resource), but the overriding selection preference is as follows:

Idle and unkept
Idle and kept
Busy and unkept
Busy and kept
In other words, a resource that is idle will always selected before a resource that is busy, and unkept resources are selected before kept ones; regardless of the resource’s proximity or utilization values. Resources that are busy or kept can only be considered candidates for selection, if the request is capable of preemption. This is true even when the kept resource is idle and does not actually have an active task. This restriction is in place to prevent a member from hijacking a string of activities intended for a different member. In other words, the assumption is that when a request is sent to a group, the modeler intended for the request to be given to a member other than the one who is already being kept to perform a string of activities for the patient.

Preemption capability can be determined by one of the following two criteria:

The new request must have a preemption value other than PREEMPT_NOT, and have a priority value exceeding the priority of the resource’s active task sequence.
The new request must have a priority value in a higher tier than the priority of the resource’s active task sequence (0-99 = 1st tier, 100-199 = 2nd tier, 200-299 = 3rd tier, and so on).
The possible preemption values and their meanings are as follows:

0 - PREEMPT_NOT, do not preempt
1 - PREEMPT_ONLY, preempt active tasks of lower priority to be done later or by different resource
2 - PREEMPT_AND_ABORT_ACTIVE, preempt and destroy active task sequence of lower priority
3 - PREEMPT_AND_ABORT_ALL, preempt and destroy active task sequence of lower priority, and destroy all requests queued for the resource.
When a request has a priority value in a higher tier than that of the active task, it acts the same as the PREEMPT_ONLY case described above. PREEMPT_ONLY is also the case invoked when the “Preempt Resources if Necessary” box is checked for an activity requiring resources.

When a kept resource is idle, the priority of the keeping patient’s most recent activity is used in determining preemption capability since there is no active task sequence to obtain a priority from. A staff member traveling to home base as a result of nothing to do, is always considered idle.

A special case arises when a resource is both idle and in an “Off Schedule” state. This is the case when a member has been removed as one of the “Usable Members” of a group. Unusable members need to be ignored by the member selection process. An off schedule resource with an active task sequence on the other hand, is treated like any other resource, and can be preempted using standard preemption criteria if necessary.

In technical terms, a group member’s score, as calculated during the standard selection process, is a single number composed of two parts: an integer part and a decimal part. The integer part is based on the selection preferences listed above, and is assigned as follows:

Idle, Unkept: score = 1000
Idle, Unkept: score = 1000
Busy, Unkept: score = -1 * (priority of member’s active task sequence +1)
Busy, Kept: score = -1000 * (priority of member’s active task sequence +1)
The decimal portion of the score is assigned in one of the following two ways based on the user-specified criteria:

PROXIMITY: score += 1 / max(1, distanceaway);
UTILIZATION: score -= GetTimeInState(member, STAT_PerformingTask) / GetElapsedTime()
In situations where no members of the group are possible candidates, the new request remains in the group’s tasksequencequeue waiting for a downstream resource to become available and fire its OnResourceAvailable function.

TaskExecuter::receivetasksequence()
When a resource is sent a request directly, or when an upstream group passes a request down to it, the receivetasksequence() function of the resource is executed. Resources are dispatched requests directly when the resource requirement of an activity calls for a specific resource, or “Used in Earlier Activity”, or “First Used From Group”. Requests can also be sent directly to a resource by Item Class objects who are requesting staff for setup times, processing times, or transportation of a flowitem to a downstream object.

The resource’s receivetasksequence() function is executed to notify the resource of a new request that has been placed in its tasksequencequeue. When a new request is received by a resource, one of four things can happen. The task sequence can either:

Be moved immediately to the resource’s activetasksequence variable and started.
Preempt the resource’s active task sequence, and then be moved into the resource’s activetasksequence variable and started.
Be put in the resource’s tasksequencequeue variable and have to wait.
Be bumped to a group object when the resource happens to be Off Schedule and can’t be preempted.
When this function fires, we will assume that the new request is specifically intended for this particular resource, and therefore it will not be bumped back to a group except in the special case where the resource is in the Off Schedule state and cannot be preempted. When a request is to be bumped to a group, we need to determine which group it should be bumped to. For requests generated by patient activities, there is always a group designation associated with the request. This is because a group selection was required before a specific resource could be selected for an activity. The group designation is recorded on the TAG task that immediately follows the resource allocation task in the original coordinated task sequence created by the start of the activity. In those cases where a valid TAG task cannot be found, the task sequence was probably generated by item flow objects, and the request should be bumped to the resource’s primary group by default.

If a request is received when a resource is busy, there will obviously be an active task sequence in the resource’s activetasksequence variable. If the new request can preempt the active task sequence, the task sequence will be terminated and put back in the resource’s tasksequencequeue variable, or destroyed, depending on the type of preemption. After the active task sequence is preempted, the new request can be moved into the activetasksequence variable and started. If the new request has preemption capability, then it is allowed to preempt the resource whether the resource is currently being kept by the same patient or not.

If the resource is idle and happens to be kept by a different patient than the one who spawned the new request, the request will require preemption capability before it can start. This is true even though the resource may not have an actual task sequence needing preemption. When this resource is traveling home as a result of having nothing to do, the resource will be treated as though it were idle; however, in this case it will be necessary to preempt (and abort) the active task sequence before the new request can be started.

As explained earlier, preemption capability can be determined by either the preemption attribute on the new request, or by comparing the priority tier of the new request and the active task sequence. When the resource is idle or traveling home idle, the priority of the most recent activity of the patient who is keeping the resource must be used rather than the priority of an active task sequence.

We need to let new requests start on idle resources who are kept by the same patient who spawned the request, or else the keeping functionality will not allow resources to be kept across multiple activities, and therefore would be useless. This decision could present a problem if a modeler has multiple series of activities defined on the same patient, and the modeler demands the same specific resource for the resource requirement on the starting activity of each series. In this case, it will be possible for the starting activity of a new series of activities to pull over a resource that is currently being kept by the same patient for what the modeler would like to think of as a separate set of activities. It is simply not possible during runtime to discern which sets of activities should be grouped together as a series and which should not, when the activities of various sets are all progressing simultaneously in parallel fashion and calling for the exact same resource on the same patient! The modeler should avoid defining tracks in such a manner. The solution is to use “Any Member” from a group for the resource requirement definition of the first activity in a series.

If a new request cannot be started immediately for any of the reasons mentioned above, including a delay in preemption due to the resource carrying or being carried by something at the time the request was first received, the new request will remain in the resource’s tasksequencequeue variable waiting for the resource to become available and execute its OnResourceAvailable function.

Dispatcher::OnResourceAvailable()
When a resource becomes available (finishes a task sequence), the Dispatcher::OnResourceAvailable() function is executed. The function first looks through the available resource’s own tasksequencequeue, and then proceeds to look upstream by executing the OnResourceAvailable() method consecutively on each group object connected upstream in pursuit of a suitable request for the resource to work on next.

The default selection process begins in the available resource’s tasksequencequeue to find a suitable request. When a resource is kept, only those requests issued by the same patient keeping the resource are candidates for selection. If more than one valid request is in a queue, the request that was created earliest with the highest priority will be selected. There is no need to check whether the request is able to preempt a kept resource as we did in the Member Selection Policy, because if the request was able to preempt, it already would have.

If a request was not selected in the tasksequencequeue of the resource that just became available, then the default selection process continues to look for a valid request in the tasksequence queues of upstream group objects. The process considers each tasksequencequeue one at time when choosing a request.

When a valid request is found, it will be transferred directly into the available resource (no need to pass it through a series of groups to get to the resource), and the receivetasksequence() is called on the resource. Requests that are not chosen will remain in the queue they are in until a resource becomes available again.

If no valid requests are found, the resource is considered idle, and the default functionality will create and dispatch a travel home request if the resource is not kept. Users may modify the default request selection process and travel home behavior using a picklist option in the OnResourceAvailable trigger field of a primary group called “Custom Request Selection Process and Idle Staff Handling”. This particular picklist option incorporates all the behavior of the standard request selection process (plus includes a few user edit options as well), and if used, it will override standard functionality. All code is available for modification by an advanced user, if so desired.

TaskExecuter::OnResourceAvailable()
When resources becomes available (finish a task sequence and do not have any task sequences in their own queue), they will execute the OnResourceAvailable(availableresource) function of upstream objects who have open outputs. When a group’s OnResourceAvailable(availableresource) function fires, it will look through its tasksequencequeue for the highest priority, longest waiting task sequence to send to the availableresource. If there aren’t any task sequences, or if the availableresource is kept and none of the queued task sequences are for the keeping patient, then the group will execute the OnResourceAvailable(availableresource) function of upstream objects who have open outputs. At this point, the resource is idle, or else the OnResourceAvailable function would not have fired for the resource; and therefore, if the resource is kept, we only want the resource to accept another task sequence from the same patient the resource is currently kept by. This will avoid a series of activities intended for the same resource from being hijacked by a different patient. There is no need to check whether the task sequence is able to preempt as we did in the Member Selection Policy, because if it could preempt, it already would have.

When a valid task sequence is found, it will be transferred directly into the available resource (no need to pass it through a series of groups to get to the resource), and call receivetasksequence() on the resource. When no task sequence is found, the task sequence simply remains where it is and waits for another available resource. None of the standard behavior associated with opening and closing of output ports will be needed on a group/resource.
__________________
Michael Machado - FlexSim Brasil
The Following User Says Thank You to mefhsmflexsimbr For This Useful Post:
sagar bolisetti (03-27-2014)
  #3  
Old 03-28-2014
Cliff King's Avatar
Cliff King Cliff King is offline
Vice President Technical Services
 
Join Date: Jul 2007
Location: Utah
Posts: 272
Downloads: 158
Uploads: 14
Thanks: 102
Thanked 304 Times in 110 Posts
Rep Power: 412
Cliff King has much to be proud ofCliff King has much to be proud ofCliff King has much to be proud ofCliff King has much to be proud ofCliff King has much to be proud ofCliff King has much to be proud ofCliff King has much to be proud ofCliff King has much to be proud ofCliff King has much to be proud of
Default

Resource behavior in FlexSim HC is different than in standard FlexSim. There is no "Queue Strategy" for Groups (i.e. Dispatchers) for requests (i.e. tasksequences). Instead, we provide the user with the "Resource Request Selection Policy" field that is evaluated to determine the next request that will be accepted by a resource at the time the resource finishes a previous request. This field is on the Group Properties window and on the advanced properties window for each individual resource member.

FlexSim HC also provides two additional trigger fields that can sometimes be useful for achieving advanced behavior: 1) the OnResourceIdle field found on a group object's advanced properties window, and 2) the OnAllocated trigger found on an individual resource member's advanced properties window.


Thread Thread Starter Forum Replies Last Post
Fluid modelling strategy question brett forbes Q&A 1 03-25-2013 07:30 PM
How to change the output strategy of a queue ? mearjun Q&A 1 10-15-2012 11:02 PM
Mix Pull and Push Strategy MoserGaudenz Q&A 1 06-23-2011 03:29 AM
OnResourceAvailable juan alberto Q&A 1 07-22-2010 04:30 AM
Pulling from a Queue vs Sorting the Queue Brandon Peterson Tips and Tricks 3 03-03-2010 01:27 AM


All times are GMT -6.
Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.
Copyright 1993-2018 FlexSim Software Products, Inc.