Chemcad 5 Services To Visual Basic Applications
Chemcad 5 Services To Visual Basic Applications
BASIC APPLICATIONS
User Manual
Chemstations, Inc.
INTRODUCTION
CHEMCAD 5 offers three approaches link with Visual Basic applications or other Windows
applications. In the first approach CHEMCAD 5 is activated as an out-of-process server from a
Visual Basic application. This enables a VBA application, such as Excel macros, to delegate
computational tasks to CHEMCAD 5 running in background. The second approach functions
through the addition of a new unit operation in CHEMCAD 5 called Excel Unit. With this unit
operation, a user can program specific tasks in VBA macros within an Excel workbook, and
CHEMCAD 5 can execute these macros in the context of a unit operation during a simulation run.
The third approach facilitates user-specified rate expressions in use with CHEMCAD 5 built-in
kinetic reactor (KREA) and batch reactor (BREA).
CHEMCAD 5 publishes a set of COM interfaces to two type libraries, cc5.tlb and ccx2xls.tlb.
Through these interfaces, many CHEMCAD 5 functions and data are made available to other
Windows applications. By executing the interface methods, a user can retrieve flowsheet topology
and its unit operations, update stream data and unit operation parameters, calculate k-value and
enthalpy, flash streams and convert engineering units. This document presents a detailed
discussion on the uses of these published interfaces within user-developed programs. We
assume that user is familiar with VBA syntax and has some knowledge of Microsoft COM. The
knowledge on process modeling with CHEMCAD 5 is necessary.
VB SERVER
In this approach, CHEMCAD 5 plays the role of a simulation engine, and the user application
organizes the calculation activities. The user application presents a user interface for any user
instructions on the calculations, while CHEMCAD 5 carries out the instructions on the
background. The user application is often developed in MS Excel using VBA programs. It is
responsible for activating CHEMCAD 5 as a COM object. After activating CHEMCAD 5, the user
application should proceed with its calculation tasks that may in turn be delegated to CHEMCAD
5.
To activate CHEMCAD 5, a user application executes VBA command
CreateObject(CHEMCAD.VBServer), where CHEMCAD.VBServer is the programmatic
identifier (ProgID) for CHEMCAD 5. This command returns a handle to an object interface called
ICHEMCADVBServer. Through the methods on this interface, the user application can further
access many other CHEMCAD 5 object interfaces. In this section, we discuss interface
ICHEMCADVBServer and its methods. This interface is published in CC5.tlb.
Description
Definition:
dispinterface ICHEMCADVBServer
{
methods:
boolean LoadJob(BSTR* bstrJobPath);
boolean RunJob();
// interfaces defined in ccx2xls.tlb
VARIANT GetFlowsheet();
VARIANT GetUnitOpInfo();
VARIANT GetUnitOpSpecUnitConversion();
VARIANT GetStreamInfo();
VARIANT GetStreamUnitConversion();
VARIANT GetStreamProperty();
VARIANT GetKValues();
VARIANT GetEnthalpy();
VARIANT GetFlash();
VARIANT GetEngUnitConversion();
VARIANT GetCompPPData();
// simulation job operations
BSTR GetWorkDir();
boolean SwitchWorkDir(BSTR* bstrNewWorkDir);
short GetNoOfJobsInWorkDir();
BSTR GetJobAt(short jobIndex);
short GetNoOfCasesInJob(BSTR* jobName);
BSTR GetCaseAt(BSTR* jobName, short caseIndex);
// simulations
short SSRunAllUnits();
short SSRunSelectedUnits(VARIANT unitIDs);
short DynamicRunAllSteps();
short DynamicRunStep();
void DynamicRestoreToInitialState();
float GetDynamicTimeInMinute();
float GetDynamicTimeStepInMinute();
short GetSimulationMode();
};
Methods
GetFlowsheet
a handle to IFlowsheet
Method
Returns
GetUnitOpInfo
a handle to IUnitOpInfo
Method
Returns
GetUnitOpSpecUnitConversion
a handle to IunitOpSpecUnitConversion
Method
Returns
GetStreamInfo
a handle to IStreamInfo
Method
Returns
GetStreamUnitConversion
a handle to IStreamUnitConversion
Method
Returns
GetStreamProperty
a handle to IStreamProperty
Method
Returns
GetEnthalpy
a handle to IEnthalpy
Method
Returns
GetKValues
a handle to IKValues
Method
Returns
GetFlash
a handle to IFlash
Method
Returns
GetEngUnitConversion
a handle to IEngUnitConversion
Method
Returns
GetCompPPData
a handle to ICompPPData
The following methods defined on this interface can be used to switch current
work directory, locate a simulation job, and load one of its cases.
Method
Returns
Argument
bstrJobPath
LoadJob
a boolean flag, TRUE if a job is loaded
Type
BSTR*
Description
Job path, e.g., c:\cc5data\job1\case1.ccx
Method
Returns
GetWorkDir
a string of work directory
Method
Returns
SwitchWorkDir
a boolean flag, TRUE if a job is loaded
Argument
Type
Description
bstrNewWorkDir
BSTR*
Method
Returns
GetNoOfJobsInWorkDir
count of jobs in work directory
Method
Returns
GetJobAt
a string of job name
Argument
jobIndex
Method
Returns
Argument
jobName
Method
Returns
Argument
jobName
caseIndex
Type
int
Description
job index in job array
GetNoOfCasesInJob
count of cases in job directory
Type
String
Description
job name for which cases are seeked
GetCaseAt
a string of case name
Type
String
Int
Description
job name for which cases are seeked
case index
After a job is loaded, the following functions can be called for steady state or
dynamic simulations.
Call SSRunAllUnits to simulation entire flowsheet, and use SSRunSelectedUnits
to run selected set of units on the flowsheet.
Method
Returns
SSRunAllUnits
0 - normal return; otherwise if error occurs.
Method
Returns
SSRunSelectedUnits
0 - normal return; otherwise if error occurs.
Argument
unitIDs
Type
Integer
Description
Array of unitop ids.
DynamicRunAllSteps
0 - normal return; otherwise if error occurs.
Method
Returns
DynamicRunStep
0 - normal return; otherwise if error occurs.
Method
DynamicRestoreToInitialState
Method
Returns
GetDynamicTimeInMinute
Current dynamic time in minutes
Method
Returns
GetDynamicTimeStepInMinute
Current dynamic time step in minutes.
Before running any simulation functions listed above, the simulation mode set in
CHEMCAD 5 for the currently loaded simulation job can be determined using
Method
Returns
GetSimulationMode()
Current mode, 0 - steady state, 1 - dynamic.
RunJob
a boolean flag, TRUE if recycle is converged.
EXCEL UNIT
A versatile and user-friendly unit operation, Excel Unit, is available in CHEMCAD 5. As all other
CHEMCAD 5 unit operations, this unit has a dedicated unit icon, and it may have user-defined
parameters and unit operation dialog. This unit serves as a link between CHEMCAD 5 and an
Excel workbook. When placing an Excel Unit icon on a flowsheet, specifying the path to an Excel
workbook and a list of macros, and running the flowsheet, CHEMCAD loads the specified Excel
workbook into an instance of Excel and runs the given list of VBA macros in the Excel workbook.
Furthermore, CHEMCAD exports a set of COM interfaces to provide an adequate modeling
environment to users of Excel Unit. Every time a VBA macro is executed, a handle to a COM
object created in CHEMCAD 5 is passed to the macro as an argument. Through the object
handle, user can access a number of CHEMCAD functions within their macros. By developing
user macros, a list of tasks can be accomplished. User can retrieve the topology of the current
flowsheet, such as stream and unit IDs, and their connections. From these IDs, user can retrieve
and update stream data and unit specifications. For stream data, user may also apply flash
calculations, K-value and enthalpy calculations. Engineering unit conversions are made available
for stream data, unit specifications, and general unit conversion cases.
Before the Excel Unit is made available, many user-specific tasks can only be accomplished
using Calculators or User-Added Modules in CHEMCAD 5. Compared to these unit operations,
the Excel unit has several advantages. Since Excel unit delegates all calculations to its Excel
workbook, it does not require any compilation and linking with CHEMCAD 5. A user develops
VBA macros in an Excel workbook. An Excel unit can have up to 10 macros. A user can break
down the calculation task into smaller pieces, and implement them in several macros. The testing
is also straightforward. VBA is an interpretive language, breakpoints can be placed at any part of
the macros, and the values of the variables can be monitored during the execution.
The steps of specifying an Excel Unit are simple to follow. First, place an icon of Excel Unit on the
current flowsheet, and make stream connections to or from other unit icons, i.e., feeds or
products. Second, switch to simulation mode, double click the Excel Unit icon to open the build-in
Excel Unit dialog box, and examine the paths of unit dialog files, the Excel workbook and the
names of the macros to be executed during a simulation run. Third, program VBA macros in the
specified Excel workbook and set breakpoints for debugging. After finishing all previous steps, run
simulations from CHEMCAD 5, and debug through the Excel macros.
Four files are required to support an Excel Unit. They are screen layout (*.my), variable map
(*.map), labels for report (*.lab), and an Excel workbook (*.xls). As default, these four files are
created upon the first opening of Excel Unit dialog, under the current job directory with current
case name followed by respective extensions. For example, the current job directory is
\CC5Data\MyExcelJob and a case CaseA is loaded. When user double-clicks the Excel Unit
icon for the first time, four files CaseA.my, CaseA.map, CaseA.lab and CaseA.xls are created
under directory \CC5Data\MyExcelJob. These files can be renamed or modified to meet users
needs. Dialog layout file, map file and label file are required to have identical name. These files
are necessary for entering parameters of the Excel Unit. These parameters can later be retrieved
within the Excel macros during simulation runs. User can find more information on creating unit
specification dialog files elsewhere [1]. The default Excel workbook created by CHEMCAD 5
copies the first inlet to the first outlet for its Excel Unit. The user can change Excel workbook path,
and should modify or provide macros for their intended calculations.
For the new users, simple editing of the VBA macros can be done within the Excel Unit dialog.
When a user opens the Excel Unit dialog and selects VB Sub tab, a portion of the macro ExclUop
will appear. In this macro, we have retrieved the inlet and outlet data, and equipment parameters
to VB variables. A user can use these variables directly in the subsequent calculations. The
common procedure is to calculate the outlets from given inlets and equipment parameters.
Following this portion, the outlets will be flashed with the given flash mode. The user macros in
the given Excel workbook will only be updated when the user marks the option Write to Excel
workbook, otherwise CHEMCAD 5 will only update the source code in .bas file. This facility
should be used with caution, and users should be aware that CHEMCAD 5 will not compile the
VB code and the code shown in the dialog will not reflect the changes made directly in the Excel
workbook using Visual Basic Editor.
The interface ICHEMCADEntry for Excel Unit is one that will lead to all other interfaces. The only
role of this interface is to allow user to reach other interfaces within their macros. Only after
getting hold of other interfaces can a user use any ChemCAD 5 calculations. Therefore, each of
the VBA macros should have exactly one argument, i.e., Sub UserSub (ByVal ChemCADEntry As
Object), if it will be activated from CHEMCAD 5.
Description
ICHEMCADEntry interface is the entry point to all other interfaces. When calling
an Excel workbook macro during a simulation run, CHEMCAD 5 always passes a
handle of this interface to the VBA macro as shown in the following example.
Sub MyMacro (ByVal ChemCADEntry As Object)
On Error Resume Next
' Get ChemCAD objects
Dim curUnitOp As Object
Dim strInfo As Object
Dim uopInfo As Object
Set curUnitOp = ChemCADEntry.GetCurUnitOp
Set strInfo = ChemCADEntry.GetStreamInfo
Set uopInfo = ChemCADEntry.GetUnitOpInfo
End Sub
The writer of a macro should determine the selection of other interfaces to bring
into his/her subroutine to meet the calculation needs. In this example, three
interfaces are obtained through the methods of ICHEMCADEntry. They are
ICurUnitOp, IStreamInfo and IUnitOpInfo. With the handles of these interfaces, a
user can access the methods provided by these interfaces. The functionality of
these interfaces and those of others will be explained in detail in the following
sections.
Definition:
dispinterface ICHEMCADEntry
{
methods:
VARIANT GetFlash();
VARIANT GetStreamUnitConversion();
VARIANT GetCurUnitOp();
VARIANT GetEnthalpy();
VARIANT GetKValues();
VARIANT GetFlowsheet();
VARIANT GetStreamInfo();
VARIANT GetStreamProperty();
VARIANT GetUnitOpInfo();
VARIANT GetUnitOpSpecUnitConversion();
VARIANT GetEngUnitConversion();
VARIANT GetCompPPData();
boolean GetSaveWorkBookFlag();
boolean SetSaveWorkBookFlag(boolean bSaveAfterRun);
};
Methods
GetFlash
a handle to IFlash
Method
Returns
GetStreamUnitConversion
a handle to IStreamUnitConversion
Method
Returns
GetCurUnitOp
a handle to ICurUnitOp
Method
Returns
GetEnthalpy
a handle to IEnthalpy
Method
Returns
GetKValues
a handle to IKValues
Method
Returns
GetFlowsheet
a handle to IFlowsheet
Method
Returns
GetStreamInfo
a handle to IStreamInfo
Method
Returns
GetStreamProperty
a handle to IStreamProperty
Method
Returns
GetUnitOpInfo
a handle to IUnitOpInfo
Method
Returns
GetUnitOpSpecUnitConversion
a handle to IUnitOpSpecUnitConversion
Method
Returns
GetEngUnitConversion
a handle to IEngUnitConversion
Method
Returns
GetCompPPData
a handle to ICompPPData
The following two methods give Excel UnitOp user the control to decide when to
save the current workbook. By default CHEMCAD saves the workbook after
every run of the current Excel UnitOp. Alternatively, user can set the flag to
FALSE during a run using SetSaveWorkBookFlag to skip saving workbook after
the run.
Method
Returns
GetSaveWorkBookFlag
a boolean flag
Method
Returns
SetSaveWorkBookFlag
a boolean flag
Argument
bSaveAfterRun
Type
boolean
Description
CHEMCAD saves workbook if set TRUE
End Sub
Here array Rate returns the rates of chemical reactions to a CHEMCAD 5 reactor, Temp is current
temperature in user unit, Pres is current pressure in user unit, Rpm is the propeller speed, RVol is
reactor volume, LFrc is the current liquid volume fraction in the reactor, array Conc contains
concentrations in user units, array PPri contains the partial pressures, array KPar carries kinetic
parameters, and ChemCADEntry is an object handle through which many CHEMCAD 5
information can be accessed. Currently 10 kinetic parameters are assigned for each reaction.
Among the 10 parameters, the first is frequency factor and the second is the exponential term
including activation energy and temperature. The rest in the 10 are reserved at this time. Within
this macro, the functions for each of the rate expressions are called. The rate function for reaction
no. 1 looks like the following
Function RxnRate002(ByVal Temp As Double, ByVal Pres As Double, ByVal Rpm As
Double, ByVal RVol As Double, ByVal LFrc As Double, ByRef Conc() As Double,
ByRef PPri() As Double, ByRef KPar() As Single, ByVal ChemCADEntry As Object)
As Double
RxnRate001 =
End Function
These codes are initially generated by CHEMCAD 5. A user can make changes as needed.
Additional information can be accessed through ChemCADEntry object handle. The interface for
this object handle is described in the previous section on Excel Unit.
FLOWSHEET
This section describes the interfaces from which the topology of current flowsheet can be
established. Two interfaces, ICurUnitOp and IFlowsheet, are discussed.
Description
ICurUnitOp interface gives the counts and IDs of the inlets and outlets of the
current Excel Unit. User can also get the unit ID of the current Excel Unit, loop
count and maximum number of runs.
Definition
dispinterface ICurUnitOp
{
methods:
short GetNoOfInlets();
short GetInletIDs(VARIANT inletIDs);
short GetNoOfOutlets();
short GetOutletIDs(VARIANT outletIDs);
short GetCurUnitOpID();
short GetLoopCount();
short GetLoopLimit();
short GetReactorLiquidPhase(VARIANT compLbmol);
short GetReactorVaporPhase(VARIANT compLbmol);
short GetRerunFlowsheetFlag();
short SetRerunFlowsheetFlag(short rerunIfOne);
};
Methods
The following two methods give the count and the IDs of inlets. The ID array
need to be defined in VBA macro before calling GetInletIDs with lower bound at
one and upper bound at no less than the inlet count.
Method
Returns
GetNoOfInlet
count of inlets
Method
Returns
GetInletIDs
count of inlet IDs returned in array inletIDs
Argument
inletIDs
Type
short[]
Description
Integer array containing inlet IDs [out]
The following two methods give the count and the IDs of outlets. The ID array
need to be defined in VBA macro before calling GetOutletIDs with lower bound at
one and upper bound at no less than the outlet count.
Method
Returns
GetNoOfOutlets
count of outlets
Method
Returns
GetOutletIDs(VARIANT outletIDs)
count of outlet IDs returned in array outletIDs
Argument
outletIDs
Type
short[]
Description
Integer array containing outlet IDs [out]
The next group of methods gives the ID of current Excel Unit, current loop count
and the maximum number of runs respectively.
Method
Returns
GetCurUnitOpID
ID of the current Excel Unit
Method
Returns
GetLoopCount
current loop number
Method
Returns
GetLoopLimit
maximum number of runs
If the current unit is kinetic reactor (KREA) or batch reactor (BREA) and user
specifies rate expressions, user may retrieve liquid (include solid) and vapor
phase from the following functions.
Method
Returns
GetReactorLiquidPhase / GetReactorVaporPhase
count of data items returns
Argument
compLbmol
Type
float[]
Description
Float array containing liquid or vapor amount
GetRerunFlowsheetFlag / SetRerunFlowsheetFlag
current value of RerunFlag
Description
IFlowsheet provides methods for querying the connections of streams and unit
operations on the current flowsheet. For a given stream, the source and target
unit can be determined. If a unit ID is known, the inlets and outlets of the unit can
be queried. All feed streams or product streams can be identified.
Definition
dispinterface IFlowsheet
{
methods:
short GetNoOfStreams();
short GetNoOfUnitOps();
short GetAllStreamIDs(VARIANT idArray);
short GetAllUnitOpIDs(VARIANT idArray);
short GetStreamCountsToUnitOp(short unitOpID, short* nInlets,
short* nOutlets);
short GetStreamIDsToUnitOp(short unitOpID, VARIANT idArray);
short GetInletStreamIDsToUnitOp(short unitOpID, VARIANT idInlets);
short GetOutletStreamIDsToUnitOp(short unitOpID, VARIANT
idOutlets);
short GetSourceAndTargetForStream(short streamID, short* sourceID,
short* targetID);
short GetNoOfFeedStreams();
short GetNoOfProductStreams();
short GetFeedStreamIDs(VARIANT idArray);
short GetProductStreamIDs(VARIANT idArray);
short GetDynamicTime(float* dynTime, BSTR* timeUnit);
};
Methods
Stream IDs can be retrieved for the entire flowsheet, streams around a unit, feed
stream only or product stream only using
Method
Returns
GetNoOfStreams
count of all streams on the current flowsheet
Method
Returns
GetAllStreamIDs
count of stream IDs returned in idArray
Argument
idArray
Type
short[]
Method
Returns
GetStreamCountsToUnitOp
total number of streams connected to the given unit
Argument
unitOpID
nInlets
nOutlets
Type
short
short
short
Method
GetStreamIDsToUnitOp / GetInletStreamIDsToUnitOp /
GetOutletStreamIDsToUnitOp
total number of IDs returned in idArray, idInlets or idOutlets
Returns
Argument
unitOpID
idArray
idInlets
idOutlets
Type
short
short[]
short[]
short[]
Description
Integer array containing all stream IDs [out]
Description
ID of a unit on the flowsheet [in]
count of inlets to the unit [out]
count of outlets to the unit [out]
Description
ID of a unit on the flowsheet [in]
IDs of inlets (>0) and outlet (<0) to the unit [out]
IDs of inlets to the unit [out]
IDs of outlets to the unit [out]
Method
Returns
GetNoOfFeedStreams
count of feed streams on the current flowsheet
Method
Returns
GetFeedStreamIDs
count of feed stream IDs returned in idArray
Argument
idArray
Type
short[]
Description
Integer array containing feed stream IDs [out]
Method
Returns
GetNoOfProductStreams
count of product streams on the current flowsheet
Method
Returns
GetProductStreamIDs
count of product stream IDs returned in idArray
Argument
idArray
Type
short[]
Description
Integer array containing product stream IDs [out]
Unit IDs can be retrieved for the entire flowsheet or a given stream using
Method
Returns
GetNoOfUnitOps
count of unit operations on the current flowsheet
Method
Returns
GetAllUnitOpIDs
count of unit IDs returned in idArray
Argument
idArray
Type
short[]
Description
Integer array containing all unit IDs
Example
Method
Returns
GetSourceAndTargetForStream
number of unit IDs returned
Argument
streamID
sourceID
targetID
Type
short
short
short
Method
Returns
GetDynamicTime
number of items returned
Argument
dynTime
timeUnit
Type
float*
BSTR*
Description
ID of a stream on the flowsheet [in]
count of inlets to the unit [out]
count of outlets to the unit [out]
Description
current dynamic time [out]
engineering unit of dynamic time [out]
The example shows how to make a table of the inlets and outlets for all the units
on the current flowsheet. In this example, the inlets appear as positive integers,
and the outlets as negative integers.
Sub PrintFlowsheetIDs(ByVal ChemCADEntry As Object)
On Error Resume Next
' get cc5 object
Dim flowsheet As Object
Set flowsheet = ChemCADEntry.GetFlowsheet
'streams and unitops
Dim streamCount As Integer
Dim unitOpCount As Integer
streamCount = flowsheet.GetNoOfStreams
unitOpCount = flowsheet.GetNoOfUnitOps
Dim check As Integer
Dim streamIDs(1 To 100) As Integer
Dim unitOpIDs(1 To 100) As Integer
check = flowsheet.GetAllStreamIDs(streamIDs)
If (check <> streamCount) Then
MsgBox "Not all stream IDs are returned"
End If
check = 0
check = flowsheet.GetAllUnitOpIDs(unitOpIDs)
If (check <> unitOpCount) Then
MsgBox "Not all unitOp IDs are returned"
End If
'feed and product streams
Dim feedCount, prodCount As Integer
Dim feedIDs(1 To 100) As Integer
Dim prodIDs(1 To 100) As Integer
feedCount = flowsheet.GetNoOfFeedStreams
check = flowsheet.GetFeedStreamIDs(feedIDs)
If (check <> feedCount) Then
MsgBox "Not all feed stream IDs are returned"
End If
prodCount = flowsheet.GetNoOfProductStreams
check = flowsheet.GetProductStreamIDs(prodIDs)
curUnitIndex As Integer
curID As Integer
curInletIndex As Integer
curOutletIndex As Integer
curStreamIndex As Integer
curRow As Integer
curCol As Integer
id As Integer
dummy As Integer
STREAM DATA
Stream data define the thermodynamic state and the rates of transportation of processing
materials in a process. The data may be used in operational decisions or computational
procedures. CHEMCAD 5 allows access of the data from Excel macros through interface
IStreamInfo and IStreamProperty.
Description
With a known stream ID, IStreamInfo allows to retrieve and update stream data,
including stream label, temperature, pressure, mole fraction, enthalpy, and
component flowrates. All the engineering quantities are given in CHEMCAD 5
internal units. The component names and their IDs are also provided through the
methods on this interface.
Definition
dispinterface IStreamInfo
{
methods:
short GetNoOfComponents();
short PutStreamByID(short streamID, float tempR, float presPsia,
float moleVapFrac, float enthBtu_Hr, VARIANT compFlowLbmol_Hr);
short GetStreamByID(short streamID, float* tempR, float* presPsia,
float* moleVapFrac, float* enthBtu_Hr, VARIANT compFlowLbmol_Hr);
short GetIDsOfComponents(VARIANT compIDs);
BSTR GetComponentNameByPosBaseOne(short compPos);
short GetComponentIDByPosBaseOne(short compPos);
BSTR GetStreamLabelByID(short streamID);
short ReflashStream(short streamID);
short PutStreamInCurUserUnitByID(short streamID, short flashMode,
float temp, float pres, float enth, float mvf, float tRate,
short tRateOption, VARIANT compRate);
short GetStreamInCurUserUnitByID(short streamID, float* temp,
float* pres, float* enth, float* mvf, float* tMoleRate, float*
tMassRate, float* tStdLVolRate, float* tStdVVolRate, VARIANT
compRate);
void GetCurUserUnitString(VARIANT* tempUnit, VARIANT* presUnit,
VARIANT* enthUnit, VARIANT* tMoleRateUnit, VARIANT*
tMassRateUnit, VARIANT* tStdLVolRateUnit, VARIANT*
tStdVVolRateUnit, VARIANT* compUnit, VARIANT* compCate);
};
Methods
Two key method, GetStreamByID and PutStreamByID, are for retrieving and
updating stream data.
Method
Returns
GetStreamByID
count of returned component data items in compFlowLbmol_Hr
Argument
streamID
tempR
presPsia
moleVapFrac
enthBtu_Hr
compFlowLbmol_Hr
Type
short
float
float
float
float
float[]
Description
ID of a stream [in]
Temperature (R) [out]
Pressure (psia) [out]
Mole vapor fraction [out]
Enthalpy (Btu/hr) [out]
Component flowrates (lbmol/hr) [out]
Method
Returns
PutStreamByID
count of received data items from compFlowLbmol_Hr
Argument
streamID
tempR
presPsia
moleVapFrac
enthBtu_Hr
compFlowLbmol_Hr
Type
short
float
float
float
float
float[]
Description
ID of a stream [in]
Temperature (R) [in]
Pressure (psia) [in]
Mole vapor fraction [in]
Enthalpy (Btu/hr) [in]
Component flowrates (lbmol/hr) [in]
GetStreamLabelByID
user label string of the stream
Type
short[]
Description
stream ID for which the label is retrieved [in]
GetIDsOfComponents
count of component IDs returned in compIDs
Type
short[]
Description
component IDs
Method
Returns
GetComponentIDByPosBaseOne(short compPos);
ID of the component at position compPos on the component list
Method
Returns
Argument
compPos
Method
Returns
Type
short[]
Description
component position on the component list [in]
The next pair of methods allows user to retrieve stream data in current user units.
Method
Returns
Argument
streamID
temp
pres
enth
mvf
tMoleRate
tMassRate
tStdLVolRate
tStdVVolRate
compRate
GetStreamInCurUserUnitByID
number of data items returned in array compRate
Type
integer
float
float
float
float
float
float
float
float
float[]
Description
stream id
temperature [out]
pressure [out]
enthalpy [out]
vapor mole fraction [out]
total mole rate [out]
total mass rate [out]
total standard liquid volume rate [out]
total standard vapor volume rate [out]
component flowrates or compositions [out]
Method
Returns
PutStreamInCurUserUnitByID
number of data items received from array compRate
Argument
streamID
flashMode
temp
pres
enth
mvf
tRate
tRateOption
compFlow
Type
integer
integer
float
float
float
float
float
short
float[]
Description
stream ID
flash calculation mode [in]
temperature [in]
pressure [in]
enthalpy [in]
mole vapor fraction [in]
total flowrate [in]
definition of total flowrate [in]
component flowrates or compositions [in]
Note that the argument flashMode defines the flash applied to the stream data,
1 TP flash; 2 VP flash; 3 VT flash; 4 HP flash; otherwise no flash
calculation. The argument tRateOption identifies the meaning of argument flow. It
may be one the four choices 1 mole rate; 2 mass rate; 3 standard liquid
volume rate; 4 standard vapor volume rate.
When tabulating the stream data, one more method can be called to get the
engineering unit strings of the current user units.
Method
GetCurUserUnitString
Argument
tempUnit
presUnit
enthUnit
tMoleRateUnit
tMassRateUnit
tStdLVolRateUnit
tStdVVolRateUnit
compUnit
compCate
Type
BSTR
BSTR
BSTR
BSTR
BSTR
BSTR
BSTR
BSTR
BSTR
Description
temperature unit string[out]
pressure unit string [out]
enthalpy unit string [out]
total mole rate unit string [out]
total mass rate unit string [out]
total standard liquid volume rate unit string [out]
total standard vapor volume rate unit string [out]
component data unit string [out]
component data category [out]
Description
Property ID
-i
-(i+200)
-(i+400)
-(i+600)
-(i+800)
-(i+1000)
Property ID
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Units
Lbmol/hr
lb/hr
ft3/hr
Units
R
psia
Btu/hr
lbmol/hr
lb/hr
ft3/hr
ft3/hr
ft3/hr
lb/ft3
Definition
Property ID
26
27
28
29
30
31
32
33
34
35
36
37
38
Units
Property ID
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Units
dispinterface IStreamProperty
{
methods:
short GetNoOfComponents();
short DefineStream(float tempR, float presPsia, float moleVapFrac,
float
enthBut_Hr, VARIANT compFlowLbmol_Hr);
float GetStreamProperty(short propID);
short GetStreamPropertiesInUserUnits(short streamID, VARIANT
streamProp, VARIANT propUserUnits);
};
Methods
DefineStream
number of data items received from array compFlowLbmol_Hr
Argument
tempR
presPsia
moleVapFrac
enthBtu_Hr
compFlowLbmol_Hr
Type
float
float
float
float
float[]
Description
Temperature (R) [in]
Pressure (psia) [in]
Mole vapor fraction [in]
Enthalpy (Btu/hr) [in]
Component flowrates (lbmol/hr) [in]
After a valid stream is specified, its properties can be retrieved one at a time from
Method
Returns
Argument
propID
Method
Returns
Argument
streamID
streamProp
propUserUnits
Example
GetStreamProperty
stream property
Type
short
Description
Stream property ID [in]
GetStreamPropertiesInUserUnits
number of data items returned fro array streamProp
Type
short
float[60]
BSTR[60]
Description
Stream ID [in]
Stream property array [out]
User units of the property [out]
Definition
dispinterface IUnitOpInfo
{
methods:
short GetUnitOpSpecArrayDimension();
short GetUnitOpSpecByID(short unitOpID, VARIANT unitOpSpec);
short PutUnitOpSpecByID(short unitOpID, VARIANT unitOpSpec);
BSTR GetUnitOpLabelByID(short unitOpID);
short GetUnitOpCategoryByID(short unitOpID, BSTR* unitOpCate);
// column specific functions
short GetNoOfStagesByID(short unitOpID);
short GetColumnHydraulicsFromSizing(short unitOpID, BSTR
columnType, VARIANT holdupLbmol, VARIANT pressurePsia,
VARIANT floodPercent);
short SetColumnPressureProfile(short unitOpID, VARIANT
pressurePsia);
short GetColumnStageData(short unitOpID, short stageID, VARIANT
vaporLbmol_Hr, VARIANT liquidLbmol_Hr, float* temperatureR,
float* pressurePsia);
};
Methods
Each unit can store up to 250 parameters in an array of float type. The number of
actual parameters can be found from the following method.
Method
Returns
GetUnitOpSpecArrayDimension
number of actual parameters for this unit operation
With a known unit ID, a user can retrieve or update unit specification parameters.
Method
Returns
Argument
unitOpID
unitOpSpec
Method
Returns
Argument
unitOpID
unitOpSpec
Method
Returns
Argument
unitOpID
GetUnitOpSpecByID
number of parameters returned in unitOpSpec
Description
Unit ID [in]
Unit specification parameters [out]
PutUnitOpSpecByID
number of parameters received from unitOpSpec
Description
Unit ID [in]
Unit specification parameters [in]
GetUnitOpLabelByID
user-defined unit label
Description
Unit ID [in]
Each unit has its identity. This identify informs us the role of the unit on a
flowsheet, such as mixer, flash, or kinetic reactor. In CHEMCAD 5, this identify is
given by either a unique category ID or a four-character string.
Method
Returns
Argument
UnitOpID
unitOpCate
GetUnitOpCategoryByID
unit category ID
Description
Unit ID [in]
4 character string of category name
Several functions are provided for the computational needs with CHEMCAD 5
column units, distillation towers (TOWR and SCDS), tower plus (TPLS) and
liquid-liquid extractor (EXTR). These functions have no effect when called upon
other types of unit operations.
Method
Returns
GetNoOfStagesByID
stage number for column units, 0 otherwise.
GetColumnHydraulicsFromSizing
-1 wrong input; 0 normal; 1 no sizing data file.
Description
Unit ID [in]
4 character string, pack or tray; either cases [in]
Array containing mole holdup on each tray [out]
Array containing pressure of each tray [out]
Array containing flood percentage of each tray [out]
SetColumnPressureProfile
-1 wrong input; 0 normal; 1 no update.
Description
Unit ID [in]
Array containing pressure of each tray [in]
GetColumnStageData
-1 wrong input; 0 normal; 1 error.
vaporLbmol_Hr
liquidLbmol_Hr
temperatureR
Example
Description
Unit ID [in]
Stage ID, base 1 [in]
Array containing component vapor holdup [our]
Array containing component liquid holdup [out]
temperature of the stage [out]
pressure of the stage [out]
FLASH
Description
Definition
dispinterface IFlash
{
methods:
long GetNoOfComponents();
short DefineFeedStream(float tempR, float presPsia, float
enthBtu_Hr, VARIANT compFlowLbmol_Hr);
short CalculateHPFlash(float enthBtu_Hr, float presPsia);
short GetVaporStream(float* tempR, float* presPsia, float*
enthBtu_Hr, float* rateLbmol_Hr, VARIANT compFlowLbmol_Hr);
float GetMoleVaporFraction();
float GetCalculatedHeatDuty();
short CalculateTPFlash(float tempR, float presPsia);
short CalculateVPFlash(float moleVapFrac, float presPsia);
short CalculateVTFlash(float moleVapFrac, float tempR);
short GetKValues(VARIANT kValues);
short GetIonRates(VARIANT ionFlowLbmol_Hr);
short GetLiquidStream(float* tempR, float* presPsia, float*
enthBtu_Hr, float* rateLbmol_Hr, VARIANT compFlowLbmol_Hr);
float GetTotalEnthalpy();
float GetTemperature();
float GetPressure();
};
Methods
The methods defined in this interface are devised around flash calculations. The
correct calling sequence should be that 1) define feed streams; 2) execute a
proper flash calculation; 3) retrieve calculation results. The user can redefine
feed stream if multiple streams need to be flashed. For a defined feed stream,
the user can also call different flash calculations. After each flash calculation is
converged, the calculated data (liquid and vapor stream, etc.) can only be
retrieved once.
Before calling the methods, user need to declare component array in VBA macro.
The lower bound of a component array has to be one, and the upper bound
should be no less than the actual number of components. All the units of the
arguments on the methods of this interface are CHEMCAD internal units.
Method
Returns
GetNoOfComponents
count of components in current job
Method
Returns
DefineFeedStream
number of flowrates received from compFlowLbmol_Hr
Argument
tempR
presPsia
enthBtu_Hr
compFlowLbmol_Hr
Description
Temperature (R) [in]
Pressure (psia) [in]
Enthalpy (Btu/hr) [in]
Component flowrates (lbmol/hr) [in]
HP flash at given enthalpy and pressure is carried out through the following
method.
Method
Return
CalculateHPFlash
convergence of the flash routine (0 converge, 1 diverge)
Description
Pressure (psia) [in]
Enthalpy (Btu/hr) [in]
TP flash at specified temperature and pressure is carried out by the next method.
Method
Return
CalculateTPFlash
convergence of the flash routine (0 converge, 1 diverge)
Description
Temperature (R) [in]
Pressure (psia) [in]
CalculateVPFlash
convergence of the flash routine (0 converge, 1 diverge)
Description
Pressure (psia) [in]
Mole vapor fraction [in]
CalculateVTFlash
convergence of the flash routine (0 converge, 1 diverge)
Description
Temperature (R) [in]
Mole vapor fraction [in]
After a flash calculation has converged, the following methods can be called to
retrieve calculation data.
Method
Returns
GetVaporStream / GetLiquidStream
number of data items returned in array compFlowLbmol_Hr
Argument
tempR
presPsia
enthBtu_Hr
rateLbmol_Hr
compFlowLbmol_Hr
Method
Returns
Description
Temperature (R) [out]
Pressure (psia) [out]
Enthalpy (Btu/hr) [out]
Total mole rate (lbmol/hr) [out}
Component flowrates (lbmol/hr) [out]
GetKValues
number of data items returned in array kValues
Description
Calculated k-values [out]
Method
Returns
GetIonRates
number of data items returned in array ionFlowLbmol_Hr
Argument
ionFlowLbmol_Hr
Example
Description
Ion rates in liquid phase [out]
Method
Returns
GetMoleVaporFraction
calculated mole vapor fraction
Method
Returns
GetCalculatedHeatDuty
calculated heat duty
Method
Returns
GetTotalEnthalpy
total enthalpy in liquid and vapor
Method
Returns
GetTemperature
flash temperature
Method
Returns
GetPressure
flash pressure
This subroutine shows the calling sequence of methods from IFlash interface
Sub MixerInExcel(ByVal ChemCADEntry As Object)
On Error Resume Next
' get all cc5 objects
Dim curUnitOp As Object
Dim strInfo As Object
Dim uopInfo As Object
Dim flash As Object
Set
Set
Set
Set
curUnitOp = ChemCADEntry.GetCurUnitOp
strInfo = ChemCADEntry.GetStreamInfo
uopInfo = ChemCADEntry.GetUnitOpInfo
flash = ChemCADEntry.GetFlash
End Sub
ENTHALPY
Description
Definition
dispinterface IEnthalpy
{
methods:
short GetNoOfComponents();
short DefingStream(float tempR, float presPsia, VARIANT
compFlowLbmol_Hr);
short CalculateLiquidEnthalpy(float* enthBtu_Hr);
short CalculateVaporEnthalpy(float* enthBtu_Hr);
};
Methods
When stream enthalpy is needed, the user call the following function to specify
the stream data.
Method
Returns
DefingStream
number of data items received from compFlowLbmol_Hr
Argument
tempR
presPsia
compFlowLbmol_Hr
Type
float
float
float[]
Description
temperature [in]
pressure [in]
liquid/vapor component flowrates [in]
After the stream data is specified, the enthalpy of the stream can be calculated
using one of the functions
Method
Returns
Argument
enthBtu_Hr
Example
CalculateLiquidEnthalpy / CalculateVaporEnthalpy
1 return value is valid; 0 the return value is invalid
Type
float
Description
enthalpy [out]
K-VALUES
Description
Definition
dispinterface IKValues
{
methods:
short GetNoOfComponents();
short DefineLiquidStream(float tempR, float presPsia, VARIANT
compFlowLbmol_Hr);
short DefineVaporStreamComponentRates(VARIANT compFlowLbmol_Hr);
short
short
short
short
GetKValues(VARIANT kValues);
GetIonRates(VARIANT ionFlowLbmol_Hr);
GetActivityCoefficients(VARIANT actCoef);
GetFugacityCoefficients(VARIANT fugCoef);
};
Methods
The first step is to define the liquid-vapor two phase system, its temperature,
pressure and compositions using the two methods given below
Method
Returns
DefineLiquidStream / DefineVaporStreamComponentRates
number of data items received from array compFlowLbmol_Hr
Argument
tempR
presPsia
compFlowLbmol_Hr
Type
float
float
float[]
Description
temperature [in]
pressure [in]
liquid/vapor component flowrates [in]
The calling sequence of the methods given above is arbitrary. As soon as liquidvapor data are defined, the k-values are calculated. User can call the following
methods to get the results
Method
Returns
GetKValues / GetIonRates
number of data items returned in the argument array
Argument
kValues
ionFlowLbmol_Hr
Type
float[]
float[]
Description
calculated k-values [out]
ion rates in liquid phase [out]
If the activity coefficients or the fugacity coefficients are required, the next two
functions can be used
Method
Returns
Argument
actCoef
fugCoef
Example
GetActivityCoefficients / GetFugacityCoefficients
number of data items returned in the argument array
Type
float[]
float[]
Description
Activity coefficients [out]
Fugacity coefficients [out]
Definition
dispinterface IStreamUnitConversion
{
methods:
short DefineStreamInCurUserUnit(float temp, float pres, float enth,
float flow, short flowOption, VARIANT compFlow);
short GetStreamInInternalUnit(float* tempR, float* presPsia, float*
enthBtu_Hr, float* rateLbmol_Hr, VARIANT compFlowLbmol_Hr);
short GetStreamInCurUserUnit(float* temp, float* pres, float* enth,
float* tMoleRate, float* tMassRate, float* tStdLVolRate, float*
tStdVVolRate, VARIANT compFlow);
short DefineStreamInInternalUnit(float tempR, float presPsia, float
enthBtu_Hr, VARIANT compFlowLbmol_Hr);
void GetCurUserUnitString(BSTR* tempUnit, BSTR* presUnit, BSTR*
enthUnit, BSTR* tMoleRateUnit, BSTR* tMassRateUnit, BSTR*
tStdLVolRateUnit, BSTR* tStdVVolRateUnit, BSTR* compUnit, BSTR*
compCate);
};
Methods
It takes two methods calls to complete a unit conversion for stream data. The first
method defines a set of stream data and the following method call returns the
converted stream data to the caller.
To convert stream data in current user units, user first call
Method
Returns
Argument
temp
pres
enth
flow
flowOption
compFlow
DefineStreamInCurUserUnit
number of data items received from array compFlow
Type
float
float
float
float
short
float[]
Description
temperature [in]
pressure [in]
enthalpy [in]
total flowrate [in]
definition of total flowrate [in]
component flowrates or compositions [in]
Note that the argument flowOption identifies the meaning of argument flow. It
may be one the four choices 1 mole rate; 2 mass rate; 3 standard liquid
volume rate; 4 standard vapor volume rate. After defining a set of stream data,
user calls
Method
Returns
GetStreamInInternalUnit
numbre of data items returned in array compFlowLbmol_Hr
Argument
tempR
presPsia
enthBtu_Hr
rateLbmol_Hr
compFlowLbmol_Hr
Type
float
float
float
float
float[]
Description
temperature [out]
pressure [out]
enthalpy [out]
total flowrate [out]
component flowrates [out]
The next pair of methods is for conversion of stream data in internal units to
current user units.
Method
Returns
DefineStreamInInternalUnit
number of data items received from array compFlowLbmol_Hr
Argument
tempR
presPsia
enthBtu_Hr
compFlowLbmol_Hr
Method
Returns
Type
float
float
float
float[]
Description
temperature [in]
pressure [in]
enthalpy [in]
component flowrates [in]
GetStreamInCurUserUnit
number of data items returned in array compFlow
Argument
temp
pres
enth
tMoleRate
tMassRate
tStdLVolRate
tStdVVolRate
compFlow
Type
float
float
float
float
float
float
float
float[]
Description
temperature [out]
pressure [out]
enthalpy [out]
total mole rate [out]
total mass rate [out]
total standard liquid volume rate [out]
total standard vapor volume rate [out]
component flowrates or compositions [out]
When tabulating the stream data, one more method can be called to get the
engineering unit strings of the current user units.
Method
GetCurUserUnitString
Argument
tempUnit
presUnit
enthUnit
tMoleRateUnit
tMassRateUnit
tStdLVolRateUnit
tStdVVolRateUnit
compUnit
compCate
Type
BSTR
BSTR
BSTR
BSTR
BSTR
BSTR
BSTR
BSTR
BSTR
Description
temperature unit string[out]
pressure unit string [out]
enthalpy unit string [out]
total mole rate unit string [out]
total mass rate unit string [out]
total standard liquid volume rate unit string [out]
total standard vapor volume rate unit string [out]
component data unit string [out]
component data category [out]
Description
Definition
dispinterface IUnitOpSpecUnitConversion
{
methods:
short FromInternalUnitsToCurUserUnits(VARIANT specInInternal,
VARIANT specInCurUser);
short FromCurUserUnitsToInternalUnits(VARIANT specInCurUser,
VARIANT specInInternal);
short GetUnitOpSpecArrayDimension();
short GetCurUserUnitString(short unitOpID, short parIndex, BSTR*
unitString, BSTR* paramName);
short GetNoOfParameters(short unitOpID);
};
Methods
One method need to be called when converting data from current user units to
internal units
Method
Returns
Argument
specInCurUser
specInInternal
FromCurUserUnitsToInternalUnits
number of data items returned
Type
Float[]
Float[]
Description
Unit specifications in current user units [in]
Unit specifications in internal units [out]
On the other hand, when converting data from internal units to current user units,
user calls
Method
Returns
Argument
specInInternal
specInCurUser
FromInternalUnitsToCurUserUnits
number of data items returned
Type
Float[]
Float[]
Description
Unit specifications in current user units [in]
Unit specifications in internal units [out]
GetCurUserUnitString
number of data item returned
Type
short
short
BSTR
BSTR
Description
Unit ID [in]
Unit specification array index (base one) [in]
Parameter engineering unit string
Name of the parameter
or call
Method
Returns
GetNoOfParameters
number of parameters used by the given unit
to find out the actual number of parameters occupied by the specifications for the unit.
Description
EngUnit ID
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Definition
Description
Molar flow rate
Temperature
Temperature difference
Pressure
Pressure difference
Enthalpy rate
Work rate
Area
Heat transfer coefficient
Heat of reaction
Length
Diameter
Liquid density
Viscosity
Surface tension
Mass flow rate
Crude flow rate
Cake resistance
Solubility
Specific volume
Dipole moment
Vapor density
Volume
Velocity
Medium resistance
Packed column pressure drop
Specific heat capacity (mass base)
Thermal conductivity
Liquid volume rate
Vapor volume rate
Mole (no time)
Mass (no time)
Heat (no time)
Enthalpy/Mole
Enthalpy/Mole or Enthalpy/Mass
Enthalpy/Mass
Fouling factor (reserved)
Heat capacity mole or mass bases
Inverse liquid volume
Time
Abbreviation
MOLE
TEMP
DELTAT
PRES
DELTAP
QRATE
WORK
AREA
HTC
HREAC
LEN
DIA
LDEN
VISC
ST
MASS
CRUDE
CAKE
SOL
SVOL
DMOMENT
VDEN
VOL
VEL
MRES
PACKDP
WHEAT
TCOND
LVRATE
VVRATE
WTMOLE
WTMASS
HEAT
MOLEHC
SPHC
MHEAT
FOULF
HEATCAP
ILV
TIME
dispinterface IEngUnitConversion
{
methods:
short FromInternalUnitToCurUserUnit(short engUnitID, float
valueInInternal, float* valueInUser, BSTR* userUnitString);
short FromCurUserUnitToInternalUnit(short engUnitID, float
valueInUser, float* valueInInternal);
};
Methods
FromInternalUnitToCurUserUnit
number of value returned
Type
short
float
float
BSTR
Description
Engineering unit category ID [in]
Value in CC5 internal unit [in]
Value in current user unit [out]
User unit string [out]
To convert a value in current user units to CHEMCAD 5 internal units, user calls
Method
Returns
Argument
engUnitID
valueInUser
valueInInternal
Example
FromCurUserUnitToInternalUnit
number of value returned
Type
short
float
float
Description
Engineering unit category ID [in]
Value in CC5 internal unit [in]
Value in current user unit [out]
This subroutine generates a table of stream data for outlets in current user units.
Sub PrintATableOfOutletStreams(ByVal ChemCADEntry As Object)
On Error Resume Next
' generate a table of outlet stream data in current user units
' get chemCAD objects
Dim curUnitOp As Object
Dim strInfo As Object
Dim strConv As Object
Set curUnitOp = ChemCADEntry.GetCurUnitOp
Set strInfo = ChemCADEntry.GetStreamInfo
Set strConv = ChemCADEntry.GetStreamUnitConversion
'inlets
Dim check As Integer
Dim nOutlets As Integer
nOutlets = curUnitOp.GetNoOfOutlets
Dim outletIDs(1 To SIZE_STREAM_ARRAY) As Integer
check = curUnitOp.GetOutletIDs(outletIDs)
' setup table header
Dim tempUnit As String
Dim presUnit As String
Dim enthUnit As String
Dim moleRateUnit As String
Dim massRateUnit As String
Dim stdLRateUnit As String
Dim stdVRateUnit As String
Dim compUnit As String
Dim compCategory As String
check = -1
strConv.GetCurUserUnitString tempUnit, presUnit, enthUnit, moleRateUnit,
massRateUnit, stdLRateUnit, stdVRateUnit, compUnit, compCategory
pressure As Single
enthalpy As Single
temperature As Single
mvf As Single
moleRate As Single
massRate As Single
stdLRate As Single
stdVRate As Single
compRate(1 To SIZE_COMP_ARRAY) As Single
moleRate
massRate
= stdLRate
= stdVRate
This interface provides the connection to retrieve pure component data for any
component on current component list. The following component physical
properties are made available.
Property ID
1
2
3
4
5
6
7
8
Definition
R
Psia
R
Btu/lbmol
Btu/lbmol
dispinterface ICompPPData
{
methods:
short GetDataInInternalUnit(short compPos, short compPPID, float*
value);
};
Methods
Method
Returns
Argument
CompPos
CompPPID
GetDataInInternalUnit
number of item returned
(0 pos or/and id is invalid; 1 value found)
Type
short
short
Description
Component position [in]
Stream property ID [in]
Example
REFERENCE
[1]
Units