# Class

Functions Sub Routines Classes
Defining a Function Predefined Functions Tag Functions Mathematical Functions String Functions Defining a Subroutine Trigger Subroutines Defining a Class

Related Links: User Defined Class and Functions

# What is "Class" and When should it be used

• A Class will allow a user to define a group of variables and functions/subroutines. The class definition is then used to make any number of "instances" or "objects" based on the class definition (or "class template").
• For example, a user may want to extend the functionality of the Tank and turn it into a complex type of tank (we have used "CSTR" in our example). To do this, the user will need to define functions to calculate the additional user variables.
• If the code is written without the use of class, the user will need to write the same code each time a CSTR tank is used. This can lead to repeating the same code a number of times depending on the number of CSTR tanks in the project.
• If the code is written in the form of a Class, the user can define all the CSTR Variables and Functions required as a "template" (class definition), then instruct SysCAD to use this template to create as many "instances" or "objects" of type CSTR, then use these to perform the CSTR calculations (n times) without the need to repeat the code.
• To aid the understanding of "Writing a Class" and to explain how to use the class function, a demonstration example project is distributed with the SysCAD install. Please see project Gold Project - CSTR pgm file. We will use this file to explain the use of Class in this document.

# How to Define a Class (Template of Variable and Functions)

## Syntax

Class className

Variable declaration(s)

Function(s)

EndClass

• The class declaration must begin with the Class keyword and end with the EndClass keyword. See Class Declaration.
• ClassName : is an unique name of the class definition. In our example, this is called CSTR.
• ClassTag: is the name of each instance of the class we are going to create. In our example, we have created Tank_A, Tank_B and TankC.
• ForEachClass Function: used to call subroutines for all instances of the class. See ForEachClass Function for more details.
• Variables can be declared within the class, their scope is limited to the class, and they are available to the instance of the class.
• When declaring variables in a class, the normal variable declaration rules will apply:
The user can define units;
Append * to make the variable visible and writeable in the access window; and/or
Append @ to make the variable visible in the Access window, but read only.
• Variables of type class can be declared within the class. These may be SysCAD classes (eg Matrix Class) or user defined classes.
• Any number of functions (of type Sub, Function and StrFunction) can be declared within the class and they are available to the instance of the class. The sequence of functions and variables within a class can be mixed and arranged as required.
• Class definitions cannot be nested. (i.e. classes cannot be defined within the definition of a class)

## Example PGM File

• A very condensed extract of the CSTR Class PGM file is presented below to explain the structure and use of the Class definition, for the full PGM file, please see the Gold distributed example project.
Class CSTR

;... Various Variable Definition.....
String     UnitTag{tag}*
Checkbox   ClassTag_is_UnitTag*<<1>>
Real       TankVolume*("Vol","m^3")<<300>>, CuLeachExtent*("Frac", "%")
;... Various Variable Definition.....

Sub Init()
If ClassTag_is_UnitTag
UnitTag = ClassTag()
Endif
[concatenate(UnitTag, ".ResTime.Volume (m^3)")] = TankVolume
EndSub

Sub CalculateCSTR()
;......Various Calculation Code .....
EndSub

Sub Exec()
;......Various Calculation Code .....
CalculateCSTR()
;......Various Calculation Code .....
[concatenate(UnitTag, ".RB.R3.Extent (%)")] = CuLeachExtent
EndSub

EndClass

1. The name of the Class (or template) is called CSTR.
2. All the variables that are associated with the CSTR are defined. (The full PGM file is available in the Gold distributed example project)
3. String tag "UnitTag" is defined here -
• User can either enter the actual Unit Model Tag name from the access window or
• define the class instance using the same name as the unit tag name, by ticking the "ClassTag_is_UnitTag" checkbox.
• the subroutine "Init" can also be used to initailise the class name if required.
4. Nested functions are allowed within a class, for example Sub "CalculateCSTR" is called inside the Sub "Exec"
5. In summary, the Class(template) "CSTR" contains a number of calculations and a number of Set Value Commands.

# How to use the Class (Perform actual Calculations using the Template)

Once the Class has been defined (template complete), the user can include this template in pgm files to perform calculations.

## Defining Class Instances

This is best shown using an example. In our sample file, the following lines represent the actual representation of the class:

 For Build 139.30599 or later  CSTR Tank_A, Tank_B, TankC Sub InitialiseSolution() TankC.UnitTag = "Tank_C" ForEachClass(CSTR, Init) EndSub ForEachClass(CSTR, Exec)  For earlier builds of SysCAD  CSTR Tank_A, Tank_B, TankC Sub InitialiseSolution() Tank_A.Init() Tank_B.Init() TankC.UnitTag = "Tank_C" TankC.Init() EndSub Tank_A.Exec() Tank_B.Exec() TankC.Exec() 
1. Three CSTR instances are defined here, Tank_A, Tank_B & TankC.
2. When the PGM file is evaluated during the SysCAD initialisation step, each instance of the Class is assigned a UnitTag Name. In the Gold Example Project, TANK_A, TANK_B and TANK_C are actual process unit tags
• If we defined the instances of the CSTR class with the same name (such as Tank_A and Tank_B), then we can simply tick the ClassTag_is_UnitTag check box.
• If we want to assign a different class name to the unit name (such as TankC), we can either initiailise the tag in the PGM code (TankC.UnitTag = "Tank_C"), or enter it manually via the access window.
3. When the project is solved, at each iteration, the Exec() function is called for each of the CSTR instances.
4. When a Class instance has been defined, SysCAD will create variables and functions for that instance. For example: For CSTR Tank_A, the following variable and functions can be accessed:
• String1 = Tank_A.ClassTag() - returns the class instances tag name (in this case, "Tank_A" is returned as a text string variable)
• String2 = Tank_A.ClassName() - returns the class instance type name (in this case, "CSTR" is returned as a text string variable)
• Tank_A.UnitTag - This is an example of the class variable.
• Tank_A.Exec() - This is an example of the class function.

## Defining Class Instances in an array

Class instance can also be defined in an array format, for example an equivalent of the above code can be written as:

 For Build 139.30599 or later  CSTR Tank[4] Sub InitialiseSolution() Tank[1].UnitTag = "Tank_A" Tank[2].UnitTag = "Tank_B" Tank[3].UnitTag = "Tank_C" ForEachClass(Tank, Init) EndSub ForEachClass(Tank, Exec)  For earlier builds of SysCAD  CSTR Tank[4] ExcludeWatch Tank[0] Sub InitialiseSolution() Tank[1].UnitTag = "Tank_A" Tank[2].UnitTag = "Tank_B" Tank[3].UnitTag = "Tank_C" Tank[1].Init() Tank[2].Init() Tank[3].Init() EndSub Tank[1].Exec() Tank[2].Exec() Tank[3].Exec()  Four CSTR instances are defined here, Tank 0, Tank 1, Tank 2 & Tank 3. Note: The array always starts with 0, therefore, we have intentionally defined 4 instances here and we will use Tanks 1 to 3. The ExcludeWatch Keyword instructs SysCAD not to display Tank 0. In our PGM code we will skip Tank 0 and start with Tank 1. Tank[1].UnitTag - This is an example of the class variable. Tank[1].Exec() - This is an example of the class function.

With an array of instances of a class we can efficiently loop through these for the Exec function for each iteration. This makes it easier to change the number of tanks. The code above becomes:

After Build 139.30094 Before Build 139.30094
 const long TankCount = 4
CSTR Tank[TankCount] ;TankCount must be const long
ExcludeWatch Tank[0]

Sub InitialiseSolution()
Tank[1].UnitTag = "Tank_A"
Tank[2].UnitTag = "Tank_B"
Tank[3].UnitTag = "Tank_C"
ForEachClass(Tank, Init)
EndSub

ForEachClass(Tank,Exec)


Notes:

• This will also call Exec() for Tank[0]. Please use the old notation if this must be avoided.
• NOTE: If the "init" subroutine requires an input parameter, such as Init("tagname"), then ForEachClass(Tank,Init) cannot be used.
 long i
const long TankCount = 4
CSTR Tank[4]
ExcludeWatch Tank[0]

Sub InitialiseSolution()
Tank[1].UnitTag = "Tank_A"
Tank[2].UnitTag = "Tank_B"
Tank[3].UnitTag = "Tank_C"
i = 1
While (i<TankCount)
Tank[i].init()
i = i + 1
EndWhile
EndSub

i = 1
While (i<TankCount)
Tank[i].Exec()
i = i + 1
EndWhile


## ForEachClass Function

The predefined function ForEachClass provides an efficient method to loop through all instances of a class. This can be used in two ways:

1. ForEachClass(ClassName, SubroutineName), is used to loop through ALL instances of the defined Class (CSTR in the example above), and call the defined subroutine (e.g. Exec()) for each. All instances includes those in class arrays and stand alone instances.
2. ForEachClass(ClassArray, SubroutineName), is used to loop through all instances in the specified Array of classes (Tank in the example above), and call the defined subroutine (e.g. Exec2()) for each of the classes in the array.

NOTE:

• The subroutine must exist in the Class definition and have no parameters.
• The Class instances or Array must be in the global scope and declared before ForEachClass is called.
• A class instance within a class is excluded.

Some Examples on how to use the function:

The following code... Is equivalent to...
 CSTR Tank10, Tank20
CSTR Tank[3]

;Call Exec for all instances of CSTR Class
ForEachClass(CSTR,Exec)

;Call Exec2 for all instances in Tank[] Class Array
ForEachClass(Tank,Exec2)

CSTR Tank30

• Note that Tank30.Exec() is not called since Tank30 it is declared after ForEachClass(CSTR,Exec).
 CSTR Tank10, Tank20
CSTR Tank[3]

;Call Exec for all instances of CSTR Class
Tank10.Exec()
Tank20.Exec()
long i
i = 0
While (i<3)
Tank[i].Exec()
i = i + 1
EndWhile

;Call Exec2 for all instances in Tank[] Class Array
i = 0
While (i<3)
Tank[i].Exec2()
i = i + 1
EndWhile

CSTR Tank30


# Sharing Classes between Projects

The recommended method of setting up a class that will be used in a number of pgms, or projects is as follows:

1. The CLASS definition is defined in a separate file; for example: General_Classes_and_functions.pgm
• NOTE that this file must NOT contain the $sign or EndFile token at the end of the file. 2. For shared use in a single project - The class definition file can be stored in the project\controls folder, then inserted into other PGM files using include file syntax >>filename. • If the class definition file is stored in the same folder as the PGM file, then use >>General_Classes_and_functions.pgm to insert the file as needed. 3. For shared use across multiple projects - The include file can be saved in a common shared folder, then inserted into other PGM files using include file syntax >>filename, the file name needs to be the relative or full path name. • For example: >>d:\Users\SysCAD Common Files\General_Classes_and_functions.pgm (Also See example below) • See Include Files for more information. ## Example 1. Class to calculate the Agitator Power required in a Vessel The user wants to calculate the required agitator power in a number of vessels in a project. This functionality will be used in a number of different projects, and hence the file with the class will be stored on the network where it can be accessed by a number of users and projects. A formula that may be used to calculate the agitator power for turbulent flow is: $\displaystyle{ \mathbf{\mathit{P = P_{0} N^{3} D^{5} Density}} }$ where: P - Agitation Power; P0 - the dimensionless power number, which is a function of impeller geometry; N - agitator rotational speed; D - Diameter of the impeller; Density - Density of the material in the vessel. The class is saved in a file called AgitatorPower.pgm and is saved on the network at n:\Users\SysCAD Common Files\  The Class file is as follows: The main pgm file may have the following structure: Class AgitatorPower TextLabel() String UnitName{Tag}* real Po*<<1>> real N<<0.3>>{i, comment("Rotation per second")} real D<<1>>{i, ("L", "m"), comment("ImpellerDiameter")} string [email protected]{ Tag} real [email protected]("Rho", "kg/m^3") real [email protected]("Pwr", "kW") Sub Init() DensityTag = Concatenate(UnitName, ".QProd.SLRho (kg/m^3)") EndSub Sub Exec() Density = [DensityTag] Power = Po * N^3 * D^5 * Density EndSub EndClass  User needs to initialise the unit name, either enter the name directly into the access window or add in some lines in the PGM file (eg: in the "Sub initialiseSolution()" section). PageLabel(Agitators) >>n:\Users\SysCAD Common Files\AgitatorPower.pgm AgitatorPower Tank1, Tank2, StorageTank1 Sub InitialiseSolution() ForEachClass(AgitatorPower, init) EndSub ForEachClass(AgitatorPower, Exec)$ ; --- end of file --- ; ------------------------------------------------------------------------------ ; the ForEachClass function is only available in Build 139.30094 or later. ; For older versions of SysCAD, use the following lines: Sub InitialiseSolution() Tank1.Init() Tank2.Init() StorageTank1.Init() EndSub Tank1.Exec() Tank2.Exec() StorageTank1.Exec() 

And the access window of the controller will show the following fields:

Notes:

1. The user may follow the same rules for individual functions that may be useful in a number of pgms or in separate projects.

# Example User Defined Classes

1. Gold Project - demonstrates the use of Classes in the CSTR pgm file. This is used to calculate the gold and copper leaching and adsorption values in a number of individual tanks.
2. See Example Class Files for some example uses of user specified class definitions.