Data used in the Chemical Engineering modules has been stored in matrices. Since matrices must be rectangular and can hold either numeric or character data, this placed limits on the way the data was stored during use in the programs. It also made it rather difficult to extract data from the property data files and put the data in the arrays where they would be used. In Matlab versions through 4.2 this was the only choice for storage of data. Now Matlab 5.1 offers several choices that have definite advantages since they can store mixed (both numeric and character) data, can store data in higher dimensional arrays than matrices and can be used to avoid having to spend as much effort in storing and extracting the data from files. This chapter will show the basic ideas that were used in utilizing structures in the start301 program developed by Mike Cohen during the Summer of 1998.
First let's a brief review of the way chemical property data is stored in a chemical engineering session. The main types of arrays are:
|
|
|
|
|
|
|
4 |
|
|
|
ammonia nitrogen hydrogen argon |
|
|
|
17.0300 28.0130 2.0160 39.9480 |
|
|
|
15.494 13.45 12.78 13.915 2363.20 658.22 232.320 832.78 -22.62 -2.854 8.08 2.36 |
Cells could be used to store all four types of data in the same
array. We will give an example where data for the same four compounds
in Table 13.1 were put in a file with start301a and loaded with
start301b (these are the programs that start301
replaced. We see the familiar listing of compounds and
reactions at the end of this process:
Here are your compounds' formulae and names: No. Formula Name 1 NH3 ammonia 2 N2 nitrogen 3 H2 hydrogen 4 Ar argon Here are your reactions: 1 N2 + 3 H2 --> 2 NH3
We can consturct an empty cell array as indicated in the help notes
about the command by that name:
»help cell CELL Create cell array. CELL(N) is an N-by-N cell arrray of empty matrices. CELL(M,N) or CELL([M,N]) is an M-by-N cell array of empty matrices. CELL(M,N,P,...) or CELL([M N P ...]) is an M-by-N-by-P-by-... cell array of empty matrices. CELL(SIZE(A)) is a cell array the same size as A containing all empty matrices.
Thus we can create a cell to hold the data shown in Table 13.1 by:
»celldat=cell(4,1) <-- Making a empty, cell, column vector with place celldat = for four "things". [] [] [] [] »celldat{1,1}=nc <-- Putting nc in the first place. Note use of "{" and "}" celldat = [4] [] [] [] »celldat{2,1}=cnms; <-- Adding cnms in the second place. »celldat{3,1}=mw; <-- mw is put in the third place »celldat{4,1}=Aabc; <-- The matrix Aabc is put in the fourth place. »celldat <-- When we list the cell, we see the data we placed celldat = only in the scalar: nc [ 4] <-- nc is 4 [4x9 char ] <-- cnms is a 4 by 9 character matrix. [4x1 double] <-- mw is a numeric column vector with 4 elements [4x3 double] <-- Aabc is a 4 by 3 numeric matrix
The use of braces ( "{" and "}") to access the contents of a cell must be remembered. If you use parentheses instead you will find that it can lead to confusion:
»celldat(1,1) <-- This produces a cell with the number 4 in it ans = [4] »celldat{1,1} <-- This gives us the number 4 ans = 4 »celldat(4,1) <-- A cell having Aabc in it ans = [4x3 double] »celldat{4,1} <-- The numeric values of the coefficients ans = 1.0e+03 * 0.0155 2.3632 -0.0226 0.0134 0.6582 -0.0029 0.0128 0.2323 0.0081 0.0139 0.8328 0.0024
The same data may also be placed in a structure. Here is information to get started:
»help struct
STRUCT Create or convert to structure array.
S = STRUCT('field1',VALUES1,'field2',VALUES2,...)
creates a structure array with the specified fields and values. The value arrays VALUES1, VALUES2, etc. must be cell arrays of the same size, scalar cells or single values. Corresponding elements of the value arrays are placed into corresponding structure array elements.
The size of the resulting structure is the same size as the value cell arrays or 1-by-1 if none of the values is a cell.
STRUCT(OBJ)
converts the object OBJ into its equivalent structure. The class information is lost.
Example:
s = struct('type',{'big','little'},'color','red','x',{3 4}) See also CLASS, CELL, GETFIELD, SETFIELD, RMFIELD, FIELDNAMES.
From this help, we can make a structure with the same data we put in celldat:
»strucdat=struct('nc',nc,'cnms',cnms,'mw',mw,'Aabc',Aabc) strucdat = nc: 4 cnms: [4x9 char ] mw: [4x1 double] Aabc: [4x3 double]
Now if we want to access this data that we stored, we can use:
»strucdat.nc ans = 4 »strucdat.mw ans = 17.0300 28.0130 2.0160 39.9480
Matlab structures seem to offer the most efficient way to store and then retreive data. The main advantages of structures over cells are:
Two functions and a starting data base with part of the data in our data files were developed to explore the possibility of replacing our starting programs start301a and start301b with a single Matlab program. Help applied to the commands: fieldnames, getfield and setfield was used to understand ways that this might be done. The example programs: mkstruct and mkvars illustrate some of the advantages of using structures.
FIELDNAMES Get structure field names.
NAMES = FIELDNAMES(S)
returns the structure field names associated with the structure S as a cell array of strings.
See also GETFIELD, SETFIELD.
You must be careful in using fieldnames since it returns a
cell array.
>> fnames=fieldnames(strucdat) fnames = 'nc' 'cnms' 'mw' 'Aabc'
The class command tells us that:
>> class(fnames) ans = cell
One element of fnames may look like a string, but it is not.
>> class(fnames) ans = cell >> fn1=fnames(1) fn1 = 'nc' >> 'nc'==fn1 ??? Function '==' not defined for variables of class 'cell'. >> class(fn1) ans = cell
If we want the contents of a cell, we need to use braces:
>> fn1=fnames{1} fn1 = nc >> 'nc'==fn1 ans = 1 1 >> class(fn1) ans = char
GETFIELD Get structure field contents.
F = GETFIELD(S,'field')
returns the contents of the specified field. This is equivalent to the syntax F = S.field.
S must be a 1-by-1 structure.
F = GETFIELD(S,{i,j},'field',{k})
is equivalent to the syntax
F = S(i,j).field(k).
In other words,
F = GETFIELD(S,sub1,sub2,...)
returns the contents of the structure S using the subscripts or field references specified in sub1,sub2,etc. Each set of subscripts in parentheses must be enclosed in a cell array and passed to GETFIELD as a separate input. Field references are passed as strings.
See also SETFIELD, FIELDNAMES.
SETFIELD Set structure field contents.
S = SETFIELD(S,'field',V)
sets the contents of the specified field to the value V. This is equivalent to the syntax S.field = V. S must be a 1-by-1 structure. The changed structure is returned.
S = SETFIELD(S,{i,j},'field',{k},V)
is equivalent to the syntax
S(i,j).field(k) = V;
In other words,
S = SETFIELD(S,sub1,sub2,...,V)
sets the contents of the structure S to V using the subscripts or field references specified in sub1,sub2,etc. Each set of subscripts in parentheses must be enclosed in a cell array and passed to SETFIELD as a separate input. Field references are passed as strings.
See also GETFIELD, FIELDNAMES.
The function mkstruct allows us to add data for one compound to an existing structure. The fields in the existing structure are identical to the names of data variables set by start301a and start301b. Here is a listing of the program.
The function mkvars extracts all the data in a structure like the one created with mkstruct and puts the data in variables of the same names as the fields in the structure. All the compounds are added to these variables. Here is a listing of mkvars.
Note that the mkvars function returns a string with the command that makes all the variables global. Thus if this returned string is evaled, we will have a session ready to be used in the 301 modules.
The function mkstruct was used to produce a structure holding twelve types of data for twenty compounds. This procedure produced a structure called stdat. It was saved as the file: /home/ceng301/datbas/struct1.mat. Here is an example of using the mkstruct function to add the compound ethanol to the structure. First we use start301a and start301b:
»start301b Copyright 1996 Rice University All rights reserved If you have not run the FORTRAN program start301a to produce a data file, do so now or you can just set the names without any data. A blank reply for the file name will let you just set the names. Give the name of your data file:waterethanol How many streams will there be?1 Here are your compounds' formulae and names: No. Formula Name 1 H2O water 2 C2H5OH ethanol
Next we load the file that had data for our twenty compounds:
»load struct1 »who Your variables are: Aabc StStdh cpl form icpv stdat AcF StdhkJ cps hcpl mw Gibb TbpK cpv hcps nc LJones Tdeg critP hcpv ne LhlvkJ TmpK critT icpl ns LhslkJ cnms critZ icps nst
The structure stdat has the form shown by:
»stdat stdat = 20x1 struct array with fields: cnms form mw Aabc LhlvkJ StStdh StdhkJ TbpK cpl cpv hcpl hcpv
Here is the data for the first compound in the structure:
»stdat(1) ans = cnms: ' benzene ' form: ' C6H6 ' mw: 78.1130 Aabc: [14.1600 2.9488e+03 -44.5630] LhlvkJ: 30.7600 StStdh: 2 StdhkJ: 82.9300 TbpK: 353.2600 cpl: [-7.2732 0.7705 -0.0016 1.8979e-06] cpv: [18.5800 -0.0117 0.0013 -2.0790e-06 1.0500e-09] hcpl: [4.7448e-10 -5.4937e-07 3.8527e-04 -0.0073 28.4482] hcpv: [2.1000e-13 -5.1975e-10 4.2500e-07 -5.8700e-06 0.0186 70.2605]
Let's add the ethanol data to this data structure:
»stdat2=mkstruct(stdat',2) <-- Note transpose of stdat stdat2 = 1x21 struct array with fields: cnms form mw Aabc LhlvkJ StStdh StdhkJ TbpK cpl cpv hcpl hcpv »stdat2(21)<-- Seeing what was added for ethanol ans = cnms: ' ethanol' form: ' C2H5OH' mw: 46.0690 Aabc: [16.1950 3.4235e+03 -55.7150] LhlvkJ: 38.5800 StStdh: 2 StdhkJ: -234.8000 TbpK: 351.4800 cpl: [-325.1300 4.1379 -0.0140 1.7035e-05] cpv: [17.6900 0.1495 8.9480e-05 -1.9730e-07 8.3170e-11] hcpl: [4.2588e-09 -4.6767e-06 0.0021 -0.3251 -272.9021] hcpv: [1.6634e-14 -4.9325e-11 2.9827e-08 7.4750e-05 0.0177 -247.1590]
Let's save this new structure and reload it into a clear workspace, then use mkvars create a new set of variables for use in the 301 modules.
»save structnew stdat2 »clear »load structnew »who Your variables are: stdat2
Now use mkvars:
»mkvars(stdat2) ans = global cnms form mw Aabc LhlvkJ StStdh StdhkJ TbpK cpl cpv hcpl hcpv »eval(ans) <-- This makes the variables global (you could also do »who do it by: eval(mkvars(stdat2)). Your variables are: Aabc StdhkJ cnms form mw LhlvkJ TbpK cpl hcpl stdat2 StStdh ans cpv hcpv »cnms <-- We can now look at all the compounds in struct1 plus ethanol that we added in the session. cnms = benzene n-butane n-butanol n-butyric acid n-heptane n-hexadecane n-hexane n-octane n-pentane n-propanol neon nicotinic acid nitric acid nitric oxide nitrogen nitrogen dioxide nitromethane nitrous oxide toluene water ethanol »Aabc <-- checking to see that one of the numeric arrays is also set correctly. Aabc = 1.0e+03 * 0.0142 2.9488 -0.0446 0.0140 2.2924 -0.0279 0.0147 2.9030 -0.1029 0.0158 4.0961 -0.0718 0.0139 2.9327 -0.0556 0.0142 4.2053 -0.1192 0.0141 2.8254 -0.0427 0.0142 3.3042 -0.0552 0.0140 2.5546 -0.0363 0.0152 3.0083 -0.0865 NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.0169 1.3191 -0.0141 0.0134 0.6582 -0.0029 NaN NaN NaN NaN NaN NaN NaN NaN NaN 0.0143 3.2424 -0.0472 0.0165 3.9854 -0.0390 0.0162 3.4235 -0.0557 »