In der Prozessindustrie ist es nicht ungewöhnlich, dass sich der Bedarf an Ressourcen über eine Prozessoperation ändert. Typische Beispiele hierfür sind Kühlmäntel von Reaktoren, in denen sich der Kühlmittelbedarf über die Reaktionsdauer ändert. Da es sich bei INOSIM um eine ereignis-diskrete Simulationssoftware handelt, kann der Ressourcenbedarf nur zu bestimmten Ereignissen geändert werden. Zeitlich veränderliche Ressourcenbedarfe können über zusätzliche Ereignisse modelliert werden. Im Folgenden werden zwei Methoden vorgestellt, um veränderliche Ressourcenmengen zu modellieren:
Erste Option: Operation teilen
Um zusätzliche Ereignisse zu schaffen, wird bei dieser Methode eine Operation in mehrere Operationen aufgeteilt. Mit jeder zusätzlichen Operation wird ein neues Parametrisierungsereignis erschaffen, an denen der Ressourcenbedarf geändert werden kann. In einem Beispiel fällt der Bedarf an Kühlmittel über die Reaktionszeit. Dazu wird die Reaktion in vier Schritte aufgeteilt:
In der ersten Reaktionsoperation wird eine Parametersteuerung verwendet, um die Dauer der einzelnen Reaktionsoperationen und die benötigte Menge der Ressource zu setzen. Dabei kann dann zum Beispiel eine Funktion genutzt werden, die den Ressourcenbedarf in jedem Schritt bestimmt. In diesem Beispiel wird eine Exponentialfunktion verwendet, um den Kühlmittelstrom im Kühlmantel über die Zeit zu beschreiben. Damit die Ressource nicht nach jeder Reaktionsoperation wieder freigegeben wird, wird die Ressource dauerhaft belegt. Am Anfang der ersten Reaktionsoperation wird der benötigte Startwert des benötigten Kühlmittels als Ressource dauerhaft zugeordnet. Am Ende jeder Reaktionsoperation wird die Differenz zwischen dem Funktionswert und dem Ressourcenbedarf aus dem vorherigen Schritt wieder freigegeben. Die Parametersteuerung zu dem beschriebenen Vorgehen sieht so aus (bitte beachten Sie: in allen Codebeispielen dieses Artikels wird WWB.NET verwendet):
Sub Cooling_exponential_SplitOperations(cop As OrderOperation, mop As RecipeOperation)
'f(x)=0.9^(x-25), with x in [h]
Dim n_op As Integer
Dim res As New OrderResource
Dim res_start As New OrderResource
Dim start As Double
Dim i As Integer
Dim op As OrderOperation
n_op=4 'number of operations
For i=1 To n_op
op=cop.OrderProcedure.OrderOperations("Reaction" & i)
op.Duration=t_reac(cop.Order.Material.Name, "ReactionDuration")*3600/n_op
'set the duration for every single operation
'durations are saved in parameter sheet
res=New OrderResource
If i=1 Then
start=0.9^(0-25)
'at the beginning of the first operation, the start value
'has to be assigned in this case it is for x=0
res_start.Amount=start
res_start.Allocation=0
'the resource should be allocated over the whole
'duration of the Reaction (amount>0 and allocation=0)
res_start.Resources=Resources("Cooling agent")
op.OrderResources.Add res_start
res.Amount=-(start-0.9^((i)*op.Duration/3600-25))
'at the end of the operation the difference between
'the start value and the first value of the function
'should be deallocated (allocation=0 and amount<0)
ElseIf i=n_op Then
'the last operation
res.Amount=-(0.9^((i-1)*op.Duration/3600-25))
'at the end of the last operation the rest of
'the resource should be deallocated
Else
res.Amount=-(start-0.9^((i)*op.Duration/3600-25))
'in every other call: difference between value
'of function for last batch(saved in CustomAttribute)
'and value for current batch is deallocated (amount<0)
End If
start=(0.9^((i)*op.Duration/3600-25))
'saving the current value of function for next loop
res.Allocation=0
res.Resources=Resources("Cooling agent")
op.OrderResources.Add res
Next
End Sub
Die Ergebnisse der Simulation zeigen dann einen abnehmenden Bedarf an Kühlmittel über die gesamte Reaktionszeit:
Diese Lösung ist der einfachste Weg, neue Events für einen zeitlich veränderlichen Ressourcenbedarf zu erschaffen. Der Nachteil ist allerdings, dass der Ansatz sehr unflexibel ist und Rezepte sehr groß werden können, falls eine genauere Auflösung des Ressourcenbedarfs nötig ist. Um eine größere Anzahl an Events zu erzeugen, kann ein zweiter Ansatz genutzt werden.
Zweite Option: Verwendung einer zusätzlichen Teilanlage
Die zweite Möglichkeit, zeitlich veränderliche Ressourcenbedarfe darzustellen, ist eine zusätzliche Teilanlage einzuführen, auf der mehrere Events erzeugt werden. An dem Kühlmantel-Beispiel wird gezeigt, wie diese Methode umgesetzt wird.
Der Kühlmantel des Reaktors wird hier als extra Teilanlage modelliert. Um nun zusätzliche Events zu erschaffen, wird der Kühlmantel in einer zweiten UnitProcedure modelliert und durch den Start der Reaktion synchronisiert. So wird die Kühlmantel-Teilanlage erst belegt, wenn die Reaktion startet.
Mit der UnitProcedure auf dem Kühlmantel werden nun neue künstliche Events erzeugt, indem die Anzahl der Instanzen der UnitProcedure pro Batch gesetzt wird. Durch die zusätzlichen Instanzen wird die UnitProcedure mehr als einmal pro Batch ausgeführt. Diese Einstellung ist in den Eigenschaften der UnitProcedure zu finden:
Die Dauer der Operation Cool muss dementsprechend an die Anzahl der Instanzen angepasst werden. In diesem Beispiel ist die Dauer der Einzeloperationen somit die gesamte Reaktionszeit geteilt durch 50.
Im letzten Schritt muss in einer Parametersteuerung für die Operation Cool erstellt werden, welche der Operation den Ressourcenbedarf, hier bestimmt durch eine Funktion, zuordnet. Wie auch zuvor wird hier zunächst der Startwert als permanente Ressource zugeordnet. Am Ende der Operation wird die Differenz zwischen der Funktion und dem vorherigen Ressourcenbedarf freigegeben.
Sub Cooling_exponential(cop As OrderOperation, mop As RecipeOperation)
'f(x)=0.9^(x-25), with x in [h]
Dim batch As Integer
Dim duration As Double
Dim res As New OrderResource
Dim res_start As New OrderResource
Dim start As Double
batch=cop.OrderProcedure.Batch
'Currently executed instance of the batch
duration=cop.Duration
If batch=1 Then
start=0.9^(0-25)
'at the beginning of the first batch, the start
'value has to be assigned in this case it is at x=0
res_start.Amount=start
res_start.Allocation=0
'the resource should be allocated over the whole
'duration of the Reaction (amount>0 and allocation=0)
res_start.Resources=Resources("Cooling agent")
cop.OrderResources.Add res_start
res.Amount=-(start-0.9^((batch)*duration/3600-25))
'at the end of the operation the difference between
'the start value and the first value of the function
'should be deallocated (allocation=0 and amount<0)
ElseIf batch=cop.ProcedureInstance.Batches Then
'the last operation
start=cop.Order.CustomAttributes("start")
res.Amount=-(0.9^((batch-1)*duration/3600-25))
'at the end of the last operation the rest
'of the resource should be deallocated
Else
start=cop.Order.CustomAttributes("start")
res.Amount=-(start-0.9^((batch)*duration/3600-25))
'in every other call: difference between value of
'function for last batch(saved in CustomAttribute)
'and value for current batch is deallocated (amount<0)
End If
cop.Order.CustomAttributes("start")=(0.9^((batch)*duration/3600-25))
'saving the current value of function for next instance
res.Allocation=0
res.Resources=Resources("Cooling agent")
cop.OrderResources.Add res
End Sub
Als Ergebnis ist eine exponentiell fallende Ressourcenmenge über die Reaktionszeit zu sehen:
Um die Flexibilität des Modells noch weiter zu erhöhen, ist es auch möglich, die Anzahl an Instanzen pro Batch in VBA zu ändern. In der ersten Instanz der UnitProcedure kann die Anzahl der Batches so auf 50 gesetzt werden:
If cop.OrderProcedure.Batch=1 Then
cop.ProcedureInstance.Batches=50
End If
In diesem Fall kann es dann auch von Vorteil sein, die Dauer der Operation entsprechend per VBA anzupassen.
Mit diesem Vorgehen kann man zum Beispiel Peaks in Ressourcenverbräuchen identifizieren. Um einen limitierenden Einfluss der Ressource auf das Modell zu ermitteln, ist diese Methode so noch nicht ausreichend, da die Ressource nicht direkt mit dem Reaktor, sondern mit dem Kühlmantel verbunden ist. Falls es also zu einem Mangel an einer Ressource kommt, kommt es nur zu einer Wartezeit auf dem Kühlmantel, aber nicht auf dem Reaktor. Damit der Reaktor auch wartet, muss das Rezept erweitert werden.
Nach der Cool-Operation wurden eine Alternativverzweigung und eine Verknüpfungsbedingung eingeführt. In der Bedingung wird überprüft, ob es sich um die letzte Instanz der UnitProcedure handelt. Falls es sich um die letzte Instanz handelt, wird der Alternativzweig mit der NoOperation ausgeführt. Diese NoOperation synchronisiert wiederum die Operation nach der Reaktion. Dadurch wird die Ausführung des Rezeptes nach der Reaktion verzögert, falls nicht genug Kühlmittel zur Verfügung steht.
Die Steuerung für die Alternativbedingung:
Sub Condition_LastBatch(cond As OrderLinkCondition)
If cond.OrderOperationFrom.OrderProcedure.Batch=cond.OrderOperationFrom.ProcedureInstance.Batches Then
'if it is the last batch
cond.Value=False
Else
cond.Value=True
End If
End Sub
In diesem Simulationslauf ist die verfügbare Kühlmittelmenge auf 35 kg/h beschränkt. Die Simulation zeigt dann Wartezeiten im Gantt-Diagramm. Die Wartezeiten auf dem Kühlmantel sieht man am Anfang der Reaktionszeit, während die Wartezeiten auf den Reaktoren am Ende der Reaktion zu sehen sind. Es kommt also zu einer Unschärfe in der Darstellung im Gantt-Diagramm. Der Ressourcenbedarf wird jedoch korrekt abgebildet, da die Ressource nur genutzt wird, wenn auch genug davon vorhanden ist. Falls nicht genug Ressource zur Verfügung steht, kommt es ebenfalls zu einer Verzögerung in der Reaktion.
Spezialfall: abnehmender Ressourcenbedarf
In dem gezeigten Beispiel wird ein über die Reaktionsdauer abfallenden Ressourcenbedarf betrachtet. Um so einen Bedarf abzubilden, gibt es eine weitere Möglichkeit. Dazu müssen keine neuen Events in INOSIM genutzt werden, sondern es wird die Möglichkeit ausgenutzt Ressourcen nur für einen bestimmten Anteil am Anfang der Reaktionszeit zu belegen (Ressource Allocation <1). In diesem Beispiel wir der Ressourcenbedarf in 50 Schritten entsprechend einer Exponentialfunktion über die Reaktionszeit geändert. Dazu wird der kleinste Wert der Funktion, die den Kühlmitelbedarf beschreibt, über die ganze Reaktionszeit benötigt. Die Differenz zwischen dem kleinsten Funktionswert und dem nächstgrößeren wird dann für die gesamte Reaktionszeit minus der Schrittweite benötigt. In diesem Beispiel würde sich so die Differenz für 49/50 der Reaktionszeit zu dem kleinsten Funktionswert addieren. So geht man bis zum höchsten Funktionswert vor, dessen Differenz zum vorherigen Wert dann nur in den ersten 1/50 der Reaktionszeit benötigt wird. In VBA lässt sich dieses Verhalten mit einer Schleife in einer Parametersteuerung lösen:
Sub Cooling_exponential_ressourcesplit(cop As OrderOperation, mop As RecipeOperation)
'f(x)=0.9^(x-25) x in h
Dim duration As Double
Dim res As New OrderResource
Dim start As Double
Dim number As Integer
Dim i As Integer
number=50 'number of increments
cop.Duration=t_reac(cop.Order.Material.Name, "ReactionDuration")*3600'Duration of Reaction is saved in parameter sheet
For i=1 To number
duration=cop.Duration/number 'Duration of increment
res=New OrderResource
res.Resources=Resources("Cooling agent")
If i=1Then
res.Amount=(0.9^((number-i)*duration/3600-25)) 'first loop:smallest value that is need over the whole reaction duration (allocation:50/50=1)
Else
res.Amount=(0.9^((number-i)*duration/3600-25))-start 'difference between current function and value before, adding up to the function (allocation: 49/50; 48/50; ...)
End If
res.Allocation=1-(i-1)/number 'allocation of increment: 50/50; 49/50; 48/50; ...
cop.OrderResources.Add res
start=0.9^((number-i)*duration/3600-25) 'saving value for next loop
Next
End Sub
In einer Simulation, bei der ebenfalls die Ressourcenverfügbarkeit limitiert ist, erhält man folgendes Gantt Chart:
Dieses Vorgehen kann jedoch nur bei abnehmenden Ressourcenverbräuchen genutzt werden. Bei einem Ressourcenbedarf, der nur für einen Teil der Operation benötigt wird (Allocation<1), wird dieser in INOSIM für den entsprechenden ersten Anteil der Operationsdauer genutzt. Das bedeutet bei dieser Methode kann der Ressourcenbedarf nur am Anfang der Prozesszeit höher dargestellt werden.
Diese Methoden von zeitlich veränderlichen Ressourcenverbräuchen sind sehr sinnvoll, wenn ein detailliertes Ressourcenmodell nötig ist, um zum Beispiel Peaks oder Limitierungen zu bestimmen. Die zusätzlichen Events können jedoch dafür sorgen, dass die Simulation langsamer wird, wenn es sehr viele sind. Falls ein detailliertes Bild nötig ist, bildet diese Vorgehensweise jedoch einen guten Workaround.
Das vollständige Modell ist in den Downloads zu finden.
Fragen?
Möchten Sie mehr über dieses Thema erfahren oder haben weitere Fragen? Bitte kontaktieren Sie uns.
Mehr Tipps & Tricks
Laufzeitfehler vermeiden und benutzerdefiniert abfangen
Dieser Tipp & Trick beschreibt eine Vielzahl von Methoden zur Vermeidung und Behandlung von Laufzeitfehlern in Ihrem VBA-Code. Sie werden mit den FindColumn– und FindRow-Methoden…
Transferanalyse mit Power BI
In diesem Tipp und Trick wird das Transfer-Analyse-Dashboard vorgestellt. Es handelt sich um eine Erweiterung des Power BI-Standard-Dashboards, mit dem Sie den Netto-Massenfluss einer Teilanlage…
Komplexe Gantt-Diagramme als PDF erzeugen
In diesem Tipp zeigen wir Ihnen, wie Sie einen ausgewählten Zeitbereich eines umfangreichen Gantt-Diagramms als PDF ausgeben und Ihr Firmenlogo in die Kopfzeile einfügen. Das INOSIM…