How to perform an Overall Mass Balance (Build136)
Navigation: PGMs - Example PGM Files - PGM Files using Class and Functions
Related Links: Tag Select Class, Species Mass Balance, Elemental Mass Balance, Example PGM Files
This page is for SysCAD 9.3 Build 136 or earlier. For SysCAD 9.3 Build 137 or later please see How to perform an Overall Mass Balance
Steady-State Project Overall Mass Balance
It is often important to perform an overall mass balance to account for the total inputs and total outputs. Here we will show how to obtain a quick balance of the overall mass by adding a PGM file using the TagSelect Class to sum up the total in and out and perform a balance.
The following two examples show how the Tag Select Class could be used to perform a simple mass balance in a steady-state project.
NOTES:
- the total input is calculated by adding all the feeders and makeup sources.
- the total output is calculated by adding all the Outputs(FeederSink).
- The Reaction Block (RB) sources and sinks are NOT included in this calculation, but could easily be extended with an additional TagSelect call, please see How to perform a Species Mass Balance for more information on this topic.
- This would best be performed after the last iteration using the Terminate Solution sub-routine.
Example 1: Steady-State Project Mass Balance
This example is for users using Build 136 or earlier. For users using the latest build of SysCAD, please see Example 1 for a simpler version of this file using the GetValue function call (available in Build137 or later).
TagSelect Inputs, Outputs integer [email protected], [email protected], i real [email protected]("Qm","t/h"), [email protected]("Qm","t/h"), [email protected]("Qm","t/h") CheckBox [email protected] string flow_tag Sub CalcMassBalance() ; find all true feeders (not connected) and makeup sources OK = Inputs.Exec("([UnitType]=='FeederSink' AND [State]==1) OR [UnitType] == 'MakeupSource'", false, false) ; find total number of inputs InCount = Inputs.GetLen() ; sum all input flows i=0 FlowIn = 0 while (i<InCount) flow_tag = Concatenate (Inputs.Tag(i),".QProd.Qm (t/h)" ) FlowIn = FlowIn + [flow_tag] i = i + 1 endwhile ; find all true sinks (not connected) OK = Outputs.Exec("[UnitType]=='FeederSink' AND [State]==2", false, false) ; find total number of outputs OutCount = Outputs.GetLen() ; sum all Output flows i=0 FlowOut = 0 while (i<OutCount) flow_tag = Concatenate (Outputs.Tag(i),".QProd.Qm (t/h)" ) FlowOut = FlowOut + [flow_tag] i = i + 1 endwhile ; perform mass balance Balance = FlowIn - FlowOut EndSub Sub TerminateSolution() ;--- Logic executed after last iteration (when solver is stopped) CalcMassBalance() EndSub $ ; --- end of file ---
Dynamic Project Overall Mass Balance
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 2: Dynamic Project Mass Balance
This example is for users using Build 136 or earlier. For users using the latest build of SysCAD, please see Example 2 for a simpler version of this file using the GetValue function call (available in Build137 or later).
TagSelect Inputs, Outputs, Surges, Tears integer [email protected], [email protected], [email protected], [email protected] real [email protected]("M","t"), [email protected]("M","t"), [email protected]("M","t"), [email protected]("M","t"), [email protected]("M","t"), [email protected]("M","t"), [email protected] bit [email protected],Recalc integer i string TempTag,TempTag2 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 total number of inputs InCount = Inputs.GetLen() ; find all true sinks (not connected) OK = Outputs.Exec("[UnitType]=='FeederSink' AND [State]==2 AND [Active]==1", false, false) ; find total number of outputs OutCount = Outputs.GetLen() ; find all surges (tanks) OK = Surges.Exec("[UnitType]=='Tank-1' AND [Active]==1", false, false) ; find total number of surges SurgeCount = Surges.GetLen() ; find all Tears OK = Tears.Exec("[UnitType]=='Flange' AND [SubClass]=='Tear' AND [Active]==1", false, false) ; find total number of tears TearCount = Tears.GetLen() ; 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 if ["$Solver.Dyn.Scenario.Start.Preset"] Recalc = TRUE else Recalc = FALSE endif EndSub Sub CalcStartMass() ; sum all Contents i = 0 StartSurgeMass = 0 while(i<SurgeCount) TempTag = Concatenate(Surges.Tag(i),".Content.Mt (t)") StartSurgeMass = StartSurgeMass + [TempTag] i = i + 1 endwhile EndSub Sub ReCalcStartMass() ; sum all Contents, recalculation after first iteration (due to Preset being used) i = 0 StartSurgeMass = 0 while(i<SurgeCount) TempTag = Concatenate(Surges.Tag(i),".Content.Mt (t)") TempTag2 = Concatenate(Surges.Tag(i),".QmAcc (t/s)") StartSurgeMass = StartSurgeMass + [TempTag] - ([TempTag2]*DeltaTime()) i = i + 1 endwhile EndSub Sub CalcMassBalance() ; sum all inputs i = 0 MassIn = 0 while(i<InCount) TempTag = Concatenate(Inputs.Tag(i),".QProd.Total.Mt (t)") MassIn = MassIn + [TempTag] i = i + 1 endwhile ; sum all outputs i = 0 MassOut = 0 while(i<OutCount) TempTag = Concatenate(Outputs.Tag(i),".QProd.Total.Mt (t)") MassOut = MassOut + [TempTag] i = i + 1 endwhile ; sum all Contents i = 0 SurgeMass = 0 while(i<SurgeCount) TempTag = Concatenate(Surges.Tag(i),".Content.Mt (t)") SurgeMass = SurgeMass + [TempTag] i = i + 1 endwhile ; sum all accumulated mass in Tears i = 0 TearMass = 0 while(i<TearCount) TempTag = Concatenate(Tears.Tag(i),".Tear.Accum.Mt (t)") TearMass = TearMass + [TempTag] i = i + 1 endwhile ; 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 ---