28. Oktober 2021

Neue Steuerungen für Unit Pools in INOSIM 13 anwenden

Die Frameworks für die Steuerungstypen Teilanlagenpoolbelegung und Transfer in/aus Teilanlagenpool haben sich in der neuen INOSIM Version 13 geändert. Die Änderungen bieten einige neue Möglichkeiten, die Steuerungen zu nutzen. Auch wenn es hier neue Funktionen gibt, müssen Sie die Art und Weise, wie Sie diese Steuerelemente schreiben, nicht ändern. Hier zeigen wir Ihnen, was sich geändert hat und was die Vorteile des neuen Verhaltens der Steuerungen sind.

Teilanlagenpoolbelegung

In INOSIM werden Teilanlagenpoolbelegungen genutzt, um zu entscheiden, welche Teilanlage aus einem Pool von einem Teilgrundrezept belegt wird. Bei der neuen Version INOSIM 13 ist die Funktionalität dieser Steuerung verbessert. In INOSIM 12 sah das Framework für die Teilanlagenpoolbelegung noch so aus:

Function Sample_UnitPoolAllocation(proc As ProcedureInstance, u As Unit) As Boolean

    ' Always allocate the requested unit
    Sample_UnitPoolAllocation = True

End Function

Die Steuerung hat zwei Eingabeargumente: Die ProcedureInstance, die die Steuerung aufruft, und die Teilanlage, die belegt werden soll. Der Rückgabewert der Funktion  ist ein Boolean, der die Belegung der vorgeschlagenen Teilanlage ermöglicht. Wird die Steuerung aufgerufen, schlägt sie die erste verfügbare Teilanlage (u) im Pool vor. Innerhalb Ihrer Steuerung können Sie entscheiden, ob eine Teilanlage akzeptiert wird oder nicht. Wenn Sie eine Teilanlage ablehnen, wird die Steuerung für die nächste verfügbare Teilanlage im Pool erneut aufgerufen. Dieses Verhalten kann zu vielen Aufrufen der Steuerung führen, selbst wenn Sie sofort wissen, welche Teilanlage zugeordnet werden muss.

In Version 13 wurde dieses Verhalten verbessert. Das neue Framework sieht aus wie folgt:

Sub Sample_UnitPoolAllocation(proc As ProcedureInstance, p As UnitPool, u As Unit, ByRef allocate As Boolean)

End Sub

Als erstes sehen Sie, dass die neue Steuerung, wie andere Steuerungen in INOSIM, ein Sub anstatt einer Funktion ist. Anstatt den Rückgabewert der Steuerung auf true oder false zu setzen, um eine Teilanlage zu akzeptieren oder abzulehnen, wird die Variable allocate verwendet. Die wesentliche Verbesserung besteht darin, dass im ersten Aufruf der Steuerung durch Setzen des PendingUnitsMode der Prozedur für die Mitglieder des Teilanlagenpools entschieden werden kann, ob eine Teilanlage dem Rezept zugewiesen werden kann. Der PendingUnitsMode kann auf puAllocate, puIgnore und puDefault gesetzt werden. Im Fall von puAllocate wird die Teilanlage für die ProcedureInstance verwendet, mit puIgnore wird sie nicht verwendet. Teilanlagen mit dem PendingUnitsMode puDefault werden behandelt wie in Version 12, die Steuerung wird für alle Teilanlagen mit diesem PendingUnitsMode aufgerufen, bis eine Teilanlage für das Rezept akzeptiert wird. Anders als in Version 12, wo u die erste vorgeschlagene Teilanlage im ersten Aufruf ist, kann der erste Aufruf der Steuerung in Version 13 erkannt werden, wenn das Argument u Nothing ist. Zusätzlich wurde der Teilanlagenpool, für den die Steuerung aufgerufen wird, als neues Argument der Steuerung eingeführt. Dies erleichtert den Zugriff auf die Mitglieder des Teilanlagenpools.

Beispiel: Mehrproduktanlage

Betrachten wir, als Beispiel für die Vorteile der neuen Steuerung, eine Mehrproduktanlage. In unserem Beispiel haben wir eine Anlage, die 20 verschiedene Produkte herstellt und für diese Produkte 20 verschiedene Produkttanks hat. Im Modell dauert die Herstellung eines jeden Produktes einen Tag. Nach der Produktion wird das Produkt in LKW abgefüllt. Dieselbe AllocationControl wird für die Auswahl des Tanks innerhalb der Produktion und für die Auswahl des Tanks, der von einem LKW entleert wird, verwendet.


Layout für das Beispiel. Es gibt eine Produktionsstraße, die 20 verschiedene Produkte herstellt. Die Produkte befinden sich in 20 verschiedenen Tanks.

Sowohl die Produktionsaufträge als auch die Abfüllaufträge haben das Material, das sie aktuell produzieren, als Eigenschaft. In diesem Beispiel sind die Produkte und Tanks von 1 bis 20 nummeriert. So kann der Tank entsprechend dem Produktnamen ausgewählt werden. Das Verhalten der Steuerung entspricht Version 12. Für jeden Auftrag wird die Steuerung für die Mitglieder des Tankpools aufgerufen, bis die passende Teilanlage gefunden ist.

Sub Product_Tank_V12(proc As ProcedureInstance, p As UnitPool, _
        u As Unit, ByRef allocate As Boolean)
    
    If u Is Nothing Then
        Exit Sub
    End If 
    'skipping the first call of the control to have the same behavior as in Version 12

    If u.Name="Tank " & Right(proc.Order.Material.Name,Len(proc.Order.Material.Name)-Len("Produkt ")) Then
        allocate=True 
        'If the number of the product name is the same as the number of the tank
    Else
        allocate=False '
    End If

End Sub

Um den richtigen Tank zu finden, testet die Steuerung jedes Mitglied des Teilanlagenpools, das aktuell verfügbar ist. Findet die Steuerung nicht die richtige Teilanlage, z. B. weil diese durch einen anderen Befehl belegt ist, muss die Steuerung erneut aufgerufen werden, wenn eines der Mitglieder des Pools wieder verfügbar wird. Dies kann zu vielen Aufrufen der Steuerung führen, um die richtige Teilanlage zu finden

Der Vorteil des Verhaltens in Version 13 ist nun, dass Sie beim ersten Aufruf der Steuerung entscheiden können, welche Teilanlage für die Zuweisung der Prozedur erlaubt ist. Da der Aufruf nur einmal erfolgt, spart das viel Simulationszeit.

Dim pm As Unit
    If u Is Nothing Then 'identifies the first call of the control 
        For Each pm In p.Members
            If pm.Name="Tank " & Right(proc.Order.Material.Name,Len(proc.Order.Material.Name)-Len("Produkt ")) Then
                proc.PendingUnitsMode(pm.Name)=PendingUnitMode.puAllocate 
                'the tank which has the same number as the product is allowed to be allocated
            Else
                proc.PendingUnitsMode(pm.Name)=PendingUnitMode.puIgnore 
                'all other tanks are ignored
            End If
        Next
    End If

Innerhalb desselben Modells spart die Verwendung der Steuerung, die das neue Verhalten in Version 13 nutzt, 36% der Simulationszeit in diesem einfachen Modell, wenn ein Produktionsjahr simuliert wird. In komplexeren Modellen könnte dies sogar noch vorteilhafter sein. Darüber hinaus ist es möglich, einer Teilanlage ein Rezept zuzuweisen, die derzeit noch nicht bereit für die Belegung ist, z. B. weil sie noch anderweitig belegt ist. In Version 12 wäre die Steuerung für dieses Rezept jedes Mal aufgerufen worden, wenn eine Teilanlage aus dem Pool wieder zur Verfügung steht. Dann wären alle Teilanlagen aus dem Pool erneut getestet worden.. Was Sie mit benutzerdefiniertem Code erreicht hätten, unterstützt INOSIM 13 jetzt nativ, indem eine feste Teilanlage aus einem Pool einem Rezept zugeordnet wird.

Workaround / Kompatibilität mit V12-Steuerungen

Wenn Sie ein Modell der Version 12 mit Version 13 verwenden möchten oder das Verhalten der Steuerung wie in Version 12 beibehalten möchten, können Sie den ersten Aufruf der Steuerung einfach überspringen, indem Sie am Anfang der Steuerung Folgendes eingeben:

If u Is Nothing Then
    Exit Function 'in the first call the control is skipped
End If

Steuerung für Transfer in/aus Teilanlagenpool

Das Verhalten der Steuerung für Transfer in/aus Teilanlagenpool wurde ebenfalls geändert. In einer Transfer-Steuerung können Sie die Senke oder Quelle für die Transferoperationen SimpleInflux, SimpleOutflux oder SimpleTransfer auswählen. In Version 12 sieht das Framework für die Steuerung Transfer in/aus Teilanlagenpool aus wie folgt:

Function Sample_Transfer(cop As OrderOperation, u As Unit, amount As Double, ByRef retry As Boolean) As Unit
    ' take the first suitable unit

    Set Sample_Transfer = cop.SourceSinkUnits(1)

End Function

Die Eingaben der Steuerung sind die aktuelle OrderOperation, die die Steuerung aufruft, die Restmenge des Transfers und der Boolesche Wert retry. Wenn retry auf true gesetzt ist, wird die Steuerung erneut aufgerufen, um eine andere geeignete Teilanlage auszuwählen, falls die Übertragung wegen voller oder leerer Teilanlagen gestoppt wird. Der Parameter u ist Nothing im ersten Aufruf der Steuerung. Bei späteren Aufrufen ist es die aktuell verwendete Teilanlage für den Transfer. Der Rückgabewert der Funktion ist die Teilanlage, die für den Transfer verwendet werden soll.

In der neuen Version wurde das Framework leicht verändert:

Sub Sample_Transfer(p As UnitPool, cop As OrderOperation, amount As Double, ByRef u As Unit, ByRef retry As Boolean)

End Sub

Zunächst einmal ist die Steuerung nicht mehr eine Funktion mit Rückgabewert, sondern eine Prozedur. Der Parameter u ist die Teilanlage, die für den Transfer verwendet wird. Im ersten Aufruf wird die für den Transfer vorgeschlagene Teilanlage im Parameter u gespeichert. Um den ersten Aufruf der Steuerung in Version 13 zu identifizieren, würden Sie verwenden:

If cop.Transfer Is Nothing Then
      'first call
Else
      'later call 
End If

Wenn die Transfer-Eigenschaft nothing ist, können Sie den Parameter u auf die Teilanlage ändern, die für den Transfer verwendet werden soll. Als zusätzlichen Parameter haben Sie den Teilanlagenpool, für den die Steuerung aufgerufen wird.

Beispiel: Edukt-Transfer

Im folgenden Beispiel sollte Edukt A für eine Reaktion aus einem Tankpool entnommen werden. Beim ersten Aufruf der Steuerung wird ein Tank für den Transfer gesetzt. Wenn dieser Tank leer ist, wird die Steuerung erneut aufgerufen und der vollste Tank aus dem Pool ausgewählt, um den Transfer fortzusetzen. Für den nächsten Transfer wird derselbe Tank verwendet, bis er leer ist. Danach soll der nun vollste Tank ausgewählt werden. In Version 12 könnte die Steuerung so aussehen:

Public LastEductTank As Unit 'Global Variable

Function Educt_Transfer(cop As OrderOperation, u As Unit, amount As Double, _
        ByRef retry As Boolean) As Unit

    Dim pm As Unit
    Dim EductTank As Unit
    Dim i As Integer

    retry=True
    
    If LastEductTank Is Nothing Then
        'in the beginning the last tank has to be set to the first member of 
        'the SourceSinkUnits collection, the pool cannot directly be accessed

        Set LastEductTank=cop.SourceSinkUnits(1)

    End If
    
    If u Is Nothing Then
        'for the first call of the control the tank from the last 
        'transfer	should be used until it is empty

        Set EductTank=LastEductTank

    Else
        'if one tank runs empty, the control is called again and 
        'the tank	with the highest content should be used

        Set EductTank=u
    
        For i=1 To cop.SourceSinkUnits.Count

            If cop.SourceSinkUnits.Item(i).Contents > EductTank.Contents Then
                Set EductTank=cop.SourceSinkUnits.Item(i)

            End If

        Next

    End If

    Set Educt_Transfer=EductTank	'set the chosen unit

    Set LastEductTank=EductTank	'update the last educt tank used

End Function

In Version 12 kann der Teilanlagenpool, für den die Steuerung aufgerufen wird, nicht direkt angesprochen werden. Stattdessen können Sie auf die SourceSinkUnits-Auflistung der Operation zugreifen. In Version 13 ist es möglich, direkt auf den Teilanlagenpool zuzugreifen, der die Steuerung aufruft.

Public LastEductTank As Unit 'Global Variable

Sub Educt_Transfer(p As UnitPool, cop As OrderOperation, amount As Double, _
        ByRef u As Unit, ByRef retry As Boolean)

      Dim pm As Unit
      Dim EductTank As Unit

      retry=True

      If LastEductTank Is Nothing Then
        'in the beginning the Last Tank has to be set to 
        'the first member of the unit pool

            lastEductTank=p.Members.Item(1)

      End If

      If cop.Transfer Is Nothing Then 
        'identifies the first call of the	control for this transfer

        'for the first call of the control the tank from the 
        'last transfer should be first used until it is empty

            EductTank=LastEductTank
      Else
        'if one tank runs empty, the control is called again 
        'and the tank 	with the highest content should be used

            EductTank=u

            For Each pm In p.Members
                  If pm.Contents > EductTank.Contents Then
                        EductTank=pm
                  End If
            Next

      End If

      u=EductTank 'set the chosen unit

      LastEductTank=u 'update the last Educt tank used

End Sub

Mit der Steuerung in Version 12 war es nicht möglich, auf Informationen über den Teilanlagenpool zuzugreifen, für den die Steuerung aufgerufen wird. Nun ist es nicht nur möglich, auf die Mitglieder dieses Pools zuzugreifen, sondern auch auf andere Eigenschaften wie zum Beispiel seinen Namen.

Workaround / Kompatibilität mit V12-Steuerungen

Wenn Sie ein bestehendes Modell aus Version 12 in Version 13 verwenden möchten, können Sie die alten Steuerungen beibehalten. Geändert werden muss die Art und Weise, zu überprüfen, ob es der erste Aufruf der Steuerung ist. In Version 12 ist u Nothing, aber in Version 13 ist u im ersten Aufruf die erste vorgeschlagene Teilanlage. Um den ersten Aufruf zu identifizieren, können Sie Folgendes verwenden:

If cop.Transfer Is Nothing Then
      'first call
Else
      'later call 
End If

Download

  • PDF-Ausdruck zu diesem Tipp & Trick

Fragen?

Möchten Sie mehr über dieses Thema erfahren oder haben weitere Fragen? Bitte kontaktieren Sie uns.

Array ( [posts_per_page] => 3 [post_type] => [category__in] => Array ( [0] => 171 ) [orderby] => rand [order] => ASC )

Mehr Tipps & Tricks

Dieser Tipp & Trick stellt Ihnen ein praktisches Werkzeug zur Visualisierung und Analyse von Transfers in Ihrem Modell mit der BICON-Erweiterung zur Verfügung. Die Tableau-Arbeitsmappe…

Arbeiten mit externen Excel-Arbeitsmappen Neben dem Zugriff auf die in INOSIM eingebaute Excel-Arbeitsmappe (siehe Tipp Nutzen Sie Ihr Excel-VBA-Wissen bei der Arbeit mit INOSIM), können mit Hilfe…

In INOSIM Simulationen können benutzerdefinierte, stochastische Teilanlagen-Störungen genutzt werden, um die Realität in einer Anlage möglichst präzise abzubilden. Mit dem Add-On Statistische Analyse kann dann…

mehr

INOSIM Kontakt

Zu den lokalen Geschäftszeiten

Deutschland +49 231 97 00 250