Modeling Flash Separations Using Matlab

 

Examples from BGW

  1. Example 3.2 from BGW: Ideal flash, Case 1: Specified Recovery of a compound & Pressure, Case 2: Specified temperature and pressure, Case 3: Specified pressure and vapor recovery
  2. Example 7.3 from BGW: Non-ideal Liquid, specified T and P, derivation of terms in marg1 using Maple
  3. Example 7.4 from BGW: Non-ideal Liquid, adiabatic at specified P

Programs Used in Simulations

  1. Basic ideal flash: flsh
  2. Margules two suffix activity coefficients with marg1
  3. First non-ideal flash program based on TP Flash Sequence in BGW: flshg
  4. Second non-ideal flash program using ssec2: flshg2
  5. Third non-ideal flash program using fsolve: flshg3
  6. Comparison of three non-ideal flash programs
  7. An adiabatic flash

We will start with an example from Biegler, L. T., Grossman, I. E., and Westerberg, A. W. Systematic Methods of Chemical Process Design. Example 3.2 in that text shows how to analyze several types of flash separators. The mixture separated includes benzene, toluene and o-xylene. Thus we need property data for those compounds. Using start403a and start403b in Matlab we get a list of our compounds and can set three streams for our separator:

How many streams will there be?3
Here are your compounds' formulae and names:
No. Formula         Name
  1  C6H6           benzene 
  2  C6H5CH3        toluene 
  3  C6H4CH3CH3-o   o-xylene

In Case 1 we are given the fraction of toluene that should be recovered in the vapor. The text shows how this may be estimated with the assumption of constant relative volatilities among the compounds. We will use trial and error to find this temperature with our Matlab programs.

The flsh program can be used to find the fraction of each compound that goes out in the vapor of a flash tank. It also gives the fraction of the feed: V/F that is in the vapor product. Here is a listing of the program.

Here is a program (bgw23) that uses the flsh function to determine the fraction of each compound that goes overhead. The returned value is the error giving the difference between the value for toluene and the specified value: 0.9. The flash is to be carried out at 100 kPa with a feed containing 30 mols benzene, 50 mols toluene and 40 mols o-xylene. Here is the function:

Here is our determination of the flash temperature:

>> bgw32(390)
ans =
    0.1986
>> bgw32(395)
ans =
   -0.0938
>> Tcase1=ssec2([390 395],'bgw32(x)')
Tcase1 =
  393.2825   <-- The text gave 393K
>> flash(Tcase1,100,[30 50 40]/120)
Temperature= 393.28K Pressure= 100.00 kPa V/F=0.8720
Compound      Feed      Liquid    Vapor     K=y/x
 benzene    0.25000   0.09110   0.27333   3.00041
 toluene    0.41667   0.32551   0.43005   1.32115
 o-xylene   0.33333   0.58339   0.29662   0.50844

The liquid mol fractions reported were: 0.089, 0.325 and 0.586. To verify that we really did satisfy the 90% recovery of toluene, we can execute:

>> tof=flsh(Tcase1,100,[30 50 40]/120) 
tof =
    0.9534    0.9000    0.7760

We can also use the mass balance modules to see all the flows:

>> ns(1,:)=[30 50 40];  <-- Setting the feed flows
>> sep(tof,1,2:3)       <-- Separating stream 1 into 2 and 3
>> showm(1,2:3,10,3)    <-- Displaying the flows
Compound   Inlet    |            Outlet            
   Stream         1 |         2         3   Total  
 benzene     30.000 |    28.601     1.399    30.000
 toluene     50.000 |    45.000     5.000    50.000
 o-xylene    40.000 |    31.039     8.961    40.000
Total       120.000 |   104.639    15.361   120.000

All these results agree very well with those found in the text example.

In case 2 we are given the temperature and pressure so our flash function may be used directly to determine the compositions and amounts of the product streams.

>> flash(390,100,[30 50 40]/120)
Temperature= 390.00K Pressure= 100.00 kPa V/F=0.6604
Compound      Feed      Liquid    Vapor     K=y/x
 benzene    0.25000   0.11531   0.31927   2.76875
 toluene    0.41667   0.36639   0.44253   1.20781
 o-xylene   0.33333   0.51830   0.23820   0.45958
 

The text reports liquid mol fractions of: 0.102, 0.347, 0.55. If we want to see the flows:

>> tof=flsh1(390,100,[30 50 40]/120)
tof =
    0.8433    0.7013    0.4719
>> sep(tof,1,2:3)
>> showm(1,2:3,10,3)
Compound   Inlet    |            Outlet            
   Stream         1 |         2         3   Total  
 benzene     30.000 |    25.300     4.700    30.000
 toluene     50.000 |    35.067    14.933    50.000
 o-xylene    40.000 |    18.876    21.124    40.000
Total       120.000 |    79.244    40.756   120.000

Here the agreement with the text is less good since they report the liquid (stream 3) flows as: 2.94, 10 and 15.84.

In the third case, we are given the vapor fraction and pressure. Thus we need to estimate the temperature again.

Just as in the other two cases, we can then find:

>> bgw32b(390)
ans =
    0.1396
>> bgw32b(395)
ans =
   -0.1915
>> Tcase3=ssec2([390 395],'bgw32b(x)')
Tcase3 =
  392.1950
>> flash(Tcase3,100,[30 50 40]/120)
Temperature= 392.20K Pressure= 100.00 kPa V/F=0.8000
Compound      Feed      Liquid    Vapor     K=y/x
 benzene    0.25000   0.09852   0.28788   2.92208
 toluene    0.41667   0.33981   0.43588   1.28271
 o-xylene   0.33333   0.56167   0.27624   0.49181
>> tof=flsh(Tcase3,100,[30 50 40]/120)
tof =
    0.9212    0.8369    0.6630
>> sep(tof,1,2:3)
>> showm(1,2:3,10,3)
Compound   Inlet    |            Outlet            
   Stream         1 |         2         3   Total  
 benzene     30.000 |    27.636     2.364    30.000
 toluene     50.000 |    41.845     8.155    50.000
 o-xylene    40.000 |    26.520    13.480    40.000
Total       120.000 |    96.000    24.000   120.000
 

These results are much closer to those found in the text than for Case 2.

A Non-ideal Example from BGW Ex. 7.3

Example 7.3 in BGW shows a flash of three compounds that are non-ideal: methanol, propanol and acetone. It gives a relation to find the excess Gibbs energy so we can determine the activity coefficients of each compound. The expression is:

GE/RT=-0.753x1x2 + 0.6495x1x3 + 0.557x2x3

The following Maple sessions were used to check the values reported for the activity coefficients derived using eq. 7.14 in BGW.

That gave the value of the natural log of the activity coefficient for methanol in the mixture. If we substitute the values given for the Aij into this, we can check the values found in the example.

Finally, we should go back to the symbolic form for all the activity coefficients:

 

Now we need some Matlab programs to calculate the activity coefficients for given properties and then use them in a modified flash program. Here is a program used to determine the activity coefficients for a three component system:

 

The example in the comments for the function are taken from BGW Ex 7.6. Executing them gives:

>> global Amar
>> Amar=[-.0753 .6495 .557];
>> marg1([.3934 .2063 .4003])
ans =
    1.1077    1.0525    1.2564

These values check with the results shown in Ex 7.6 except for the middle one and that can be accounted for by an error in the matrix shown in the problem.

Here is the first function written to simulate a flash unit. It follows as closely as possible the TP Flash Calculation Sequence outlined on page 220 of BGW.

Use of the function to correct the results in Ex 7.3 is shown in the session:

How many streams will there be?3
Here are your compounds' formulae and names:
No. Formula Name
  1  CH3OH      methanol  
  2  C3H7OH     n-propanol
  3  CH3COCH3   acetone   
>> global Amar
>> Amar=[-.0753 .6495 .557];  <-- From eq. 7.49
>> T=343;      <-- Temperature in K
>> P=101.325;  <-- Pressure in kPa
>> zs=[.4 .2 .4];  <-- Feed mol fraction
>> gamf='marg1';  <-- Name of activity coefficient function
>>  [ts,vof]=flshg(T,P,zs,gamf)
ts =
    0.8883    0.6765    0.9385  <-- Fraction of compounds to Top
vof =
    0.8661  <-- Much larger than the value: 0.046 reported for V/F
>> ns(1,:)=zs  Using the mass balance modules to show all flows
ns =
    0.4000    0.2000    0.4000
         0         0         0
         0         0         0
>> sep(ts,1,[2 3])
>> showm(1,2:3,10,5)
Compound     Inlet    |            Outlet            
     Stream         1 |         2         3   Total  
 methanol     0.40000 |   0.35533   0.04467   0.40000
 n-propanol   0.20000 |   0.13529   0.06471   0.20000
 acetone      0.40000 |   0.37538   0.02462   0.40000
Total         1.00000 |   0.86601   0.13399   1.00000
>> ys=ns(2,:)/sum(ns(2,:));
>> xs=ns(3,:)/sum(ns(3,:));
>> gams=marg1(xs);
>> ks=kval(T,P).*gams;
>> M=[ys;xs;ks;gams]'
M = <- y         x        K        gamma  Compound
    0.4103    0.3334    1.2302    1.0059  methanol
    0.1562    0.4829    0.3234    1.0002  n-propanol
    0.4335    0.1837    2.3633    1.5045  acetone
 

After correcting the spread sheet program used to generate the results shown in the text, the authors found:

For this mixture at this temperature and pressure, V/F =
0.8639 and the compositions, K values and activity coefficients are
given by:
 
           yi       xi   Ki      gi
Methanol 0.4107  0.3319 1.2374 1.00642
Propanol 0.1555  0.4824 0.3224 1.00376
Acetone  0.4337  0.1857 2.3362 1.5014

 

Extending our Non-ideal Example to an Adiabatic Flash: BGW Ex. 7.4

In this example, we wish to flash a liquid at a higher temperature and pressure (373K and 10 atm.) to atmospheric pressure without adding or subtracting heat from the unit. We can anticipate that this will require additional trial and error to find the temperature that will make the process adiabatic. We can use the mass and energy balance modules to find out how much heat would have to be used for a specified temperature. The case examined in Ex 7.3 would produce:

>> [ts,vof]=flshg(T,P,zs,gamf)
ts =
    0.8883    0.6765    0.9385
vof =
    0.8661
>> setne('l',1,373,zs)   
>> sepe('v','l',T,T,1,2:3,ts)
ans =
   25.0908   <-- Thus 25 kJ would have to be added to the flash unit
>> T=340;    <-- We will try a lower temperature.                     
>> [ts,vof]=flshg(T,P,zs,gamf)
ts =
    0.7210    0.3956    0.8268
vof =
    0.6983
>> sepe('v','l',T,T,1,2:3,ts) 
ans =
   18.7848   <-- Now we need only 19 kJ, but we need to lower the
>> T=335;         temperature again.
>> [ts,vof]=flshg(T,P,zs,gamf)
??? Error using ==> fzero  <-- Bad news!
The function values at the interval endpoints must differ in sign.
 
Error in ==> /home/ceng403/matlab/flshg.m
On line 39  ==>    vof=fzero(fx,vofi,erc,[],P1);

This error in fsolve was found to persist at all temperatures below 339K, a long way from the adiabatic conditions we want.

 

A second non-ideal flash program was then written that avoided the use of fsolve. It used instead the program ssec2 that has been used at Rice for many years.

 

 

An examination of the procedure used in both flshg and flshg2 led to the conclusion that both could give problems associated with the trial and error used to find V/F inside a trial and error used to find the liquid composition.

It might be better and more reliable to look for all the variables at once. We can solve for any number of unknowns using the function: fsolve. It requires an auxiliary function to return an error vector of the same dimension as the number of unknowns. We have one plus the number of compounds as our unknowns. Actually we could reduce that by one by making use of the fact that the mol fractions must sum to one, but that does not help very much. Here is the auxiliary function: flshgaux

This function is used in our third non-ideal flash function: flshg3

Here is a session used to compare the three programs and to determine which might a) require more computation in case we need to do this by hand and b) might be more "robust" and able to handle more difficult cases.

How many streams will there be?3
Here are your compounds' formulae and names:
No. Formula Name
  1  CH3OH      methanol  
  2  C3H7OH     n-propanol
  3  CH3COCH3   acetone   
>> global Amar
>> Amar=[-.0753 .6495 .557];
>> T=343;
>> P=101.325;
>> zs=[.4 .2 .4];
>> gamf='marg1';
>> fl1=flops
fl1 =
        9283
>> [ts,vof]=flshg(T,P,zs,gamf)
ts =
    0.8883    0.6765    0.9385
vof =
    0.8661
>> dfl=flops-fl1
dfl =
        2603  <-- flshg used only 2603 FLOPs
>> fl1=flops
fl1 =
       11887
>> [ts,vof]=flshg2(T,P,zs,gamf)
ts =
    0.8883    0.6764    0.9384
vof =
    0.8660
>>  dfl=flops-fl1
dfl =
        3515  <-- flshg2 used 3515 FLOPs
>> fl1=flops
fl1 =
       15403
>> [ts,vof]=flshg3(T,P,zs,gamf)
ts =
    0.8882    0.6763    0.9386
vof =
    0.8660
>> dfl=flops-fl1
dfl =
        9597  <-- flshg3 used over 9500 FLOPs

For this case where all three programs converge, it would appear that the use of fsolve to find all four unknowns at once costs a lot of computer time. Part of that extra time may be used to satisfy more stringent convergence tests than were used in the other two programs. Look at what happened when we moved to a lower temperature:

>> [ts,vof]=flshg(335,P,zs,gamf)
??? Error using ==> fzero  <-- we get our error in flshg
The function values at the interval endpoints must differ in sign.
 
Error in ==> /home/ceng403/matlab/flshg.m
On line 39  ==>    vof=fzero(fx,vofi,erc,[],P1);
 
>> fl1=flops                     
fl1 =
       25114
>> [ts,vof]=flshg2(335,P,zs,gamf)
*******************************************************
* ssec2 did not converge, xl:   0.99902 xr:         1 *
*******************************************************
ts =
    0.2445    0.0712    0.3483
vof =
    0.2511
>> dfl=flops-fl1
dfl =
        4118  <-- flshg2 takes a few more FLOPs and gives a warning 
>> fl1=flops
fl1 =
       29233
>> [ts,vof]=flshg3(335,P,zs,gamf)
ts =
    0.2456    0.0716    0.3488
vof =
    0.2521
>> dfl=flops-fl1
dfl =
        9032  <-- flshg3 takes fewer FLOPs and does not seem to have
                   any problems.

We will next use the third non-ideal flash program to find the adiabatic temperature for the flash. Here is an auxiliary function that gives the heat required for a given assumed temperature:

Here is the final solution of Example 7.4:

>> global flshP flshTf
>> flshP=P
flshP =
  101.3250
>> flshTf=373
flshTf =
   373
>> flshgad(340)
ans =
   18.7851  <-- Too high
>> flshgad(335)
ans =
    3.2788  <-- Still too high
>> flshgad(333)
ans =
   -9.2870  <-- Too low
>> ssec2([333 335],'flshgad(x)')
ans =
  334.3531  <-- Temperature that should be about right.
>> showe(1,2:3,10,5)
             Inlet    |            Outlet            
     Stream         1 |         2         3   Total  
  Tmp K        373.00 |    334.35    334.35          
  State       liquid  |    vapor    liquid           
  Entlpy     -245.864 |   -32.298  -213.566  -245.864
Compound    Stream Flows                             
 methanol     0.40000 |   0.05874   0.34126   0.40000
 n-propanol   0.20000 |   0.00776   0.19224   0.20000
 acetone      0.40000 |   0.08668   0.31332   0.40000
Total         1.00000 |   0.15318   0.84682   1.00000
 

Let's make a table like the one reported in the Examples:

 
>> ns  <-- The molar flows are in the matrix ns
ns =
    0.4000    0.2000    0.4000
    0.0587    0.0078    0.0867
    0.3413    0.1922    0.3133
>> ys=ns(2,:)/sum(ns(2,:))
ys =
    0.3834    0.0507    0.5659
>> xs=ns(3,:)/sum(ns(3,:))
xs =
    0.4030    0.2270    0.3700
>> Ks=ys./xs
Ks =
    0.9515    0.2233    1.5294
>> gams=marg1(xs)
gams =
    1.0903    1.0398    1.2859
>> M=[ys;xs;Ks;gams]'
M =    y         x         K       gamma
    0.3834    0.4030    0.9515    1.0903  methanol
    0.0507    0.2270    0.2233    1.0398  n-propanol
    0.5659    0.3700    1.5294    1.2859  acetone 
 

The authors found using their spread sheet programs:

 
A temperature of 334.58 K with V/F = 0.1782. The results of the
adiabatic flash are given below:
 
            yi    xi     Ki     gi
Methanol 0.3874 0.4027 0.9621 1.0877
Propanol 0.0526 0.2320 0.2266 1.0510
Acetone  0.5600 0.3653 1.5330 1.2905