Dynamic Project Overall Mass Balance
Jump to navigation
Jump to search
Navigation: PGMs ➔ Example PGM Files ➔ Dynamic Mass Balance
Simple Examples | Subroutines Examples | Dynamic Examples | Steady State Overall Mass Balance | Array and Matrix Examples | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Basic Layout | Simple Calculations | Initialise PreStart | Multi-Step Trigger | Checking Project | Counter, While and Random | Belt Filter Wash Loss | Startup Actions | Mass Balance | Mass Balance | Species Balance | Elemental Balance | Lookup Value | Set Values | Tridiagonal System |
Related Links: Example PGMs for Dynamic Projects
The following examples show how the Tag Select Class could be used to perform a simple mass balance in a dynamic project.
- This is best performed after the last iteration using the Terminate Solution sub-routine.
- It can also be performed every iteration for debugging.
- The main difference to the steady-state mass balance shown above is that is needs to take account of material in surges and tears (in dynamic, tears can have surge).
Notes:
- This mass balance only takes account of feeders and makeup sources as possible sources and sinks of material and tanks and tear blocks as possible surges of material.
- It ignores any reaction block sources and sinks and other units such as conveyor belts, multi-storage units (stockpiles) and tailings dams.
Example: Dynamic Project Mass Balance
PageLabel "MassBal"
Textbreak
TagSelect Inputs, Outputs, Surges, Tears
Array InputList, OutputList, SurgeList, TearList
Textbreak
real MassIn@("M","t"), MassOut@("M","t")
real StartSurgeMass@("M","t"), SurgeMass@("M","t"), TearMass@("M","t")
real MassBalanceError@("M","t"), RelativeError@("Frac", "Frac")
real Preset_surge, Preset_acc
Checkbox OK@, Recalc@
Sub InitMassBalance()
;find all true feeders (not connected) and makeup sources
OK = Inputs.Exec("([UnitType]=='FeederSink' AND [State]==1 AND [Active]==1) OR [UnitType] == 'MakeupSource'", false, false)
;find all true sinks (not connected)
OK = Outputs.Exec("[UnitType]=='FeederSink' AND [State]==2 AND [Active]==1",false, false)
;find all surges (tanks)
OK = Surges.Exec("[UnitType]=='Tank-1' AND [Active]==1", false, false)
;find all Tears
OK = Tears.Exec("[UnitType]=='Flange' AND [SubClass]=='Tear' AND [Active]==1", false, false)
;initialise masses
MassIn = 0.0
MassOut = 0.0
StartSurgeMass = 0.0
SurgeMass = 0.0
TearMass = 0.0
MassBalanceError = 0.0
RelativeError = 0.0
;check if recalculation of initial masses will be required because Preset is used
Recalc = iif(["$Solver.Dyn.Scenario.Start.Preset"]==1, TRUE, FALSE)
EndSub
Sub CalcStartMass()
;sum all Contents
StartSurgeMass = 0.0
Surges.GetValues(".Content.Mt (t)", SurgeList)
StartSurgeMass = SurgeList.Sum()
EndSub
Sub ReCalcStartMass()
; sum all Contents, recalculation after first iteration (due to Preset being used)
StartSurgeMass = 0
Surges.GetValues(".Content.Mt (t)", SurgeList)
Preset_surge = SurgeList.Sum()
Surges.GetValues(".QmAcc (t/s)", SurgeList)
Preset_acc = SurgeList.Sum()
StartSurgeMass = StartSurgeMass + Preset_surge - (Preset_acc*DeltaTime())
EndSub
Sub CalcMassBalance()
; sum all inputs
MassIn = 0.0
Inputs.GetValues(".QProd.Total.Mt (t)", InputList)
MassIn = InputList.Sum()
; sum all Outputs
MassOut = 0.0
Outputs.GetValues(".QProd.Total.Mt (t)", OutputList)
MassOut = OutputList.Sum()
; sum all Tank Surge
SurgeMass = 0.0
Surges.GetValues(".Content.Mt (t)", SurgeList)
SurgeMass = SurgeList.Sum()
; sum all Tears
TearMass = 0.0
Tears.GetValues(".Tear.Accum.Mt (t)", TearList)
TearMass = TearList.Sum()
; perform mass balance
MassBalanceError = MassIn - MassOut + StartSurgeMass - SurgeMass + TearMass
RelativeError = MassBalanceError/Max(MassIn,MassOut)
EndSub
Sub PreStart()
;--- Logic executed early before first iteration
InitMassBalance()
EndSub
Sub InitialiseSolution()
;--- Logic executed during initialisation before first iteration
CalcStartMass()
EndSub
Sub TerminateSolution()
;--- Logic executed after last iteration (when solver is stopped)
CalcMassBalance()
EndSub
if Recalc
; recalculate initial mass because Preset used
ReCalcStartMass()
Recalc = FALSE
endif
CalcMassBalance() ; include this line to perform mass balance every iteration for debugging
$ ; --- end of file ---