nsharpx.gms : Synthesis of General Distillation Sequences


This is a direct MINLP formulation of the gamslib model NONSHARP, which
solves this problem with a special Benders method called APROS. The initial
GAMS implementation was done by Skip Paules.

Small Model of Type : MINLP

Category : GAMS Model library

Main file : nsharpx.gms

$title Synthesis of General Distillation Sequences (NSHARPX,SEQ=226)

This is a direct MINLP formulation of the gamslib model NONSHARP, which
solves this problem with a special Benders method called APROS. The initial
GAMS implementation was done by Skip Paules.

Aggarwal, A, and Floudas, C A, Synthesis of General Distillation
Sequences: Nonsharp Separation. Computers and Chemical Engineering
14, 6 (1990), 631-653.

Keywords: mixed integer nonlinear programming, chemical engineering, distillation sequences,
          process synthesis, nonsharp distillation

   c 'components'     / a, b, c        /
   i 'columns'        / col-1*col-2    /
   p 'products'       / prod-1, prod-2 /
   s 'column streams' / top, bot       /

* Derived Sets - These sets are used to define the mapping of the
* superstructure for the problem at any stage
   inter(i,i,s) 'column i fed by column j top or bottom'
                / col-1.col-2.top, col-2.col-1.bot /
   key(i,s,c)   'key components for column'
                / col-1.top.a, (col-2.top,col-1.bot).b, col-2.bot.c /
   link(i,s,c)  'nondistribution of nonkeys'
                / col-1.top.c, col-2.bot.a /;

Alias (i,j);

   feed(c)  'feed of each component' / a  100, b  100, c  100 /
   cost(i)  'alpha coeffs' / col-1      0.23947  , col-2      0.75835   /
   a1(i)    'a1 coeffs'    / col-1     -0.0139904, col-2     -0.0661588 /
   a2(i,s)  'a2 coeffs'    / col-1.top  0.0093514, col-2.top  0.0338147
                             col-1.bot  0.0077308, col-2.bot  0.0373349 /
   a3(i,c)  'a3 coeffs (corresponds to feed composition)'
                           / col-1.a   -0.0005719, col-2.a    0.0016371
                             col-1.b    0.0042656, col-2.b    0.0288996
                             col-1.c    0.0      , col-2.c    0.0       /
   out(c,p) 'product composition' / a.prod-1 80, b.prod-1 30, c.prod-1 20
                                    a.prod-2 20, b.prod-2 70, c.prod-2 80 /
   xinit(c) 'composition of flow finite and fby'
   totfeed  'total flow to the superstructure';

totfeed  = sum(c, feed(c));
xinit(c) = feed(c)/totfeed;

Variable cobj 'total cost';

Binary Variable y(i) 'existence of column i';

Positive Variable
    finit(i)     'flow from initial splitter to column i'
    fin(i)       'total flow to column i'
    f(i,s)       'flow rate of column top & bottom product streams'
    fint(i,j,s)  'flow rate of interconnecting streams'
    fpr(i,s,p)   'flow rate of streams to products'
    fby(p)       'flow rate of bypass streams'
    cfin(i,c)    'component flow to column i'
    xin(i,c)     'composition of flow fin'
    x(i,s,c)     'composition of flow f'
    rec(i,s,c)   'recovery of key components';

   obj           'objective function'
   spblinit      'initial splitter balance'
   spblcol(i,s)  'splitter balances at each column top & bottom outlets'
   mixbal(i,c)   'mixer balance equations at inlet of each column'
   colbal(i,c)   'component balance equations around each column'
   keybal(i,s,c) 'key component balances for each column'
   probal(p,c)   'component balance equations for each product'
   cfloin(i,c)   'equations defining component flowrates for column inlet'
   molsum(i,s)   'constraint for sum of mole fractions for column products'
   molsumin(i)   'constraint for sum of mole fractions for column inlet'
   dist(i,s,c)   'constraint defining the nondistribution of nonkeys'
   intcon(i)     'logical constraints';

obj..          cobj =e= sum(i,  cost(i)*y(i)
                             + (a1(i) + sum(key(i,s,c), a2(i,s)*rec(key))
                                      + sum(c, a3(i,c)*xin(i,c)))*fin(i));

spblinit..     sum(i, finit(i)) + sum(p, fby(p)) =e= totfeed;

spblcol(i,s).. f(i,s) =e= sum(inter(j,i,s), fint(inter)) + sum(p, fpr(i,s,p));

mixbal(i,c)..  cfin(i,c) =e= finit(i)*xinit(c) + sum(inter(i,j,s), fint(inter)*x(j,s,c));

colbal(i,c)..  cfin(i,c) =e= sum(s, f(i,s)*x(i,s,c));

keybal(key(i,s,c)).. cfin(i,c)*rec(key) =e= f(i,s)*x(key);

probal(p,c)..  sum((i,s), fpr(i,s,p)*x(i,s,c)) + fby(p)*xinit(c) =e= out(c,p);

cfloin(i,c)..  fin(i)*xin(i,c)  =e= cfin(i,c);

molsum(i,s)..  sum(c, x(i,s,c)) =e= 1;

molsumin(i)..  sum(c, xin(i,c)) =e= 1;

dist(link)..   x(link) =e= 0;

intcon(i)..    fin(i) =l= totfeed*y(i);

cfin.up(i,c) = feed(c);
rec.lo(key)  = .85;
rec.up(key)  = 1;

Model nonsharp / all /;

finit.up(i)    = totfeed;
fin.up(i)      = totfeed;
f.up(i,s)      = totfeed;
fint.up(i,j,s) = totfeed;
fpr.up(i,s,p)  = totfeed;

x.up(i,s,c) = 1;
xin.up(i,c) = 1;

* we need to give initial values and bounds to avoid getting
* stuck at an infeasible point when the NLP solver starts up

y.l(i) = 1/card(i);

finit.l(i)    = totfeed/card(i);
fin.l(i)      = finit.l(i);
f.l(i,s)      = fin.l(i)/card(s);
fint.l(i,j,s) = f.l(i,s)/card(j);
fpr.l(i,s,p)  = f.l(i,s)/card(p);

x.l(i,s,c)  = 1/card(c);
xin.l(i,c)  = 1/card(c);
cfin.l(i,c) = sum(s, f.l(i,s)*x.l(i,s,c));

solve nonsharp using minlp minmizing cobj;