Torres de absorción rellenas - Funciones JavaScript

En este capítulo, por conveniencia, las funciones JavaScript, tienen los mismos nombres que las funciones HP equivalentes.

Flujos de entrada y salida en torres rellenas

La función que calcula los flujos y composiciones de salida, contando con los flujos y composiciones de entrada (L2, x2, V1, y1) y el porcentaje de absorción (pa), se denomina abrc1:

function abrc1({L2, x2, V1, y1, pa}={}) { const B = L2*(1-x2); const C = V1*(1-y1); const A = B*(x2/(1-x2))+C*(y1/(1-y1)); const V2y2 = V1*y1*(1-pa/100); const V2 = C+V2y2; const y2 = V2y2/V2; const D = (A-C*(y2/(1-y2)))/B; const x1 = D/(1+D); const L1 = B/(1-x1); return {L1, x1, V2, y2}; }

Para resolver, con esta función, el ejemplo 5.1.1 del texto, se procede de la siguiente forma:

Primero se guardan los datos conocidos:

L2 = Qty("50.5 kmol/h").to("kmol/s").scalar.round(6)
V1 = Qty("15.02 kmol/h").to("kmol/s").scalar.round(6)
x2 = 0; y1 = 0.040; y2 = 0.005;

Con los datos conocidos se calcula el porcentaje de absorción (siguiendo los pasos explicados en el texto):

C = (V1*(1-y1)).round(6)
V2 = (C/(1-y2)).round(6)
pa = ((V1*y1-V2*y2)/(V1*y1)*100).round(6)

Finalmente, con todos los datos conocidos, se calculan las composiciones y flujos de salida:

round(abrc1({L2, x2, V1, y1, pa}),6)

Coeficientes de transferencia de masa

Coeficientes individuales ideales

El cálculo de las fracciones molares en la interfaz gas-líquido (xi, yi), así como los flujos molares superficiales (Nax, Nay), ha sido programada en la función xiyi1:

function xiyi1({x, y, kpx, kpy, fx, fy}={}) { let yi; function f(xi) { yi = fx(xi); return kpx/kpy+(y-yi)/(x-xi); } const xi = f.refa({xi:x+1e-5, xf: fy(y)-1e-5}); Nax = kpx*(xi-x); Nay = kpy*(y-yi); return {xi, yi, Nax, Nay} }

Esta función recibe las fracciones molares (x, y), los coeficientes individuales ideales (kpx, kpy) y las funciones de equilibrio (fx, fy). Se les recuerda que el código de la función está disponible también en las referencias de las funciones, al final del capítulo, pero también puede ser recuperada en cualquier instrucción de la calculadora escribiendo el nombre de la función, como se muestra a continuación:

xiyi1

Para resolver, con esta función, el ejemplo 5.3.1.1 el texto, se procede de la siguiente forma:

Con los datos de equilibrio conocidos, se crean las funciones de equilibrio:

vx = [0,0.05,0.10,0.15,0.20,0.25,0.30,0.35]; vy = [0,0.022,0.052,0.087,0.131,0.187,0.265,0.385]; fx = [vx, vy].inLin1; fy = [vy, vx].inLin1;

Se guardan los datos conocidos:

x = 0.1; y = 0.38; kpx = 1.967e-3, kpy = 1.465e-3;

Finalmente, con todos los datos conocidos, se calculan las fracciones molares en la interfaz gas-líquido y los flujos molares (en kmol/s*m2) con xiyi1:

xiyi1({x, y, kpx, kpy, fx, fy})

Coeficientes individuales reales

Cuando en lugar de los coeficientes individuales ideales, se cuenta con los coeficientes individuales reales, se emplea igualmente el programa xiyi1, sólo que en lugar de enviar a la función los coeficientes ideales, se envía los coeficientes reales.

Así, el ejemplo 5.3.2.1 del texto se resuelve con las siguientes instrucciones:

vx = [0,0.05,0.10,0.15,0.20,0.25,0.30,0.35]; vy = [0,0.022,0.052,0.087,0.131,0.187,0.265,0.385]; fx = [vx, vy].inLin1; fy = [vy, vx].inLin1;
x = 0.1; y = 0.38; kx = 0.0024, ky = 0.00207;
xiyi1({x, y, kpx:kx, kpy:ky, fx, fy})

Cálculo de los coeficientes individuales reales a partir de los ideales

El programa que realiza el cálculo se denomina xiyi2, el cual recibe las fracciones molares en las fases gaseosa y líquida (x, y), los coeficientes individuales ideales (kpx, kpy) y las funciones de equilibrio (fx y fy):

function xiyi2({x, y, kpx, kpy, fx, fy}={}) { // Función de la fracción molar en el líquido en la interfaz gas-líquido let yi, xim, yim, kx, ky; function fxi(xi) { yi = fx(xi); xim = ((1-x)-(1-xi))/Math.log((1-x)/(1-xi)); yim = ((1-yi)-(1-y))/Math.log((1-yi)/(1-y)); kx = kpx/xim; ky = kpy/yim; return kx/ky+(y-yi)/(x-xi); } // Resolución de la función "fxi" const xi = fxi.refa({xi:x+1e-5, xf:fy(y)-1e-5}); // Flujos de soluto const Nax = kx*(xi-x); const Nay = ky*(y-yi); return {xi, yi, xim, yim, kx, ky, Nax, Nay}; }

Así, para resolver el ejemplo 5.3.3.1 del texto, se escriben las instrucciones:

vx = [0,0.05,0.10,0.15,0.20,0.25,0.30,0.35]; vy = [0,0.022,0.052,0.087,0.131,0.187,0.265,0.385]; fx = [vx, vy].inLin1; fy = [vy, vx].inLin1;
xiyi2({x:0.1, y:0.38, kpx:1.967e-3, kpy:1.465e-3, fx, fy})

Con lo que se obtienen los resultados requeridos.

Coeficientes globales ideales de transferencia de masa

Las funciones JavaScript equivalentes a las funciones Kx1 y Ky1 de la calculadora HP, son:

function Kx1({y, xi, yi, kpx, kpy, xa}={}) { const m = (y-yi)/(xa-xi); return 1/(1/(m*kpy)+1/kpx); }

function Ky1({x, xi, yi, kpx, kpy, ya}={}) { const m = (yi-ya)/(xi-x); return 1/(1/kpy+m/kpx); }

Empleando estas funciones (y las elaboradas previamente) el ejemplo 5.3.4.1, se resuelve con la siguiente función inmediatamente invocada (función IIFE):

(function() { const x=0.1, y=0.38, kpx=1.967e-3, kpy=1.465e-3; const vx = [0,0.05,0.10,0.15,0.20,0.25,0.30,0.35]; const vy = [0,0.022,0.052,0.087,0.131,0.187,0.265,0.385]; const fx = [vx,vy].inLin1; const fy = [vy,vx].inLin1; const {xi, yi} = xiyi1({x, y, kpx, kpy, fx, fy}); const xa = fy(y); const ya = fx(x); const Kx = Kx1({y, xi, yi, kpx, kpy, xa}); const Ky = Ky1({x, xi, yi, kpx, kpy, ya}); const Nax = Kx*(xa-x); const Nay = Ky*(y-ya); return {Kx, Ky, Nax, Nay} })()

Y el ejemplo 5.3.5.1, se resuelve con la siguiente función invocada inmediatamente:

(function () { const x=0.1, y=0.38; kpx=1.967e-3, kpy=1.465e-3; const vx = [0,0.05,0.10,0.15,0.20,0.25,0.30,0.35]; const vy = [0,0.022,0.052,0.087,0.131,0.187,0.265,0.385]; const fx = [vx,vy].inLin1; const fy = [vy,vx].inLin1; const {xi, yi, kx, ky} = xiyi2({x, y, kpx, kpy, fx, fy}); const xa = fy(y); const ya = fx(x); const Kx = Kx1({y, xi, yi, kpx, kpy, xa}); const Ky = Ky1({x, xi, yi, kpx, kpy, ya}); const Nax = Kx*(xa-x); const Nay = Ky*(y-ya); return {Kx, Ky, Nax, Nay} })()

Coeficientes globales reales a partir de coeficientes globales ideales

Las funciones JavaScript equivalentes a las funciones HP Kx2 y Ky2, son:

function Kx2({x, Kxi, xa}={}) { const ml = ((1-x)-(1-xa))/Math.log((1-x)/(1-xa)); return Kxi/ml }

function Ky2({y, Kyi, ya}={}) { const ml = ((1-ya)-(1-y))/Math.log((1-ya)/(1-y)); return Kyi/ml; }

Con estas funciones y las elaboradas previamente, el ejemplo 5.3.6.1, se resuelve con la siguiente función invocada inmediatamente:

(function() { const x=0.1, y=0.38; kpx=1.967e-3, kpy=1.465e-3; const vx = [0,0.05,0.10,0.15,0.20,0.25,0.30,0.35]; const vy = [0,0.022,0.052,0.087,0.131,0.187,0.265,0.385]; const fx = [vx,vy].inLin1; const fy = [vy,vx].inLin1; const {xi, yi} = xiyi1({x, y, kpx, kpy, fx, fy}); const xa = fy(y); const ya = fx(x); const Kpx = Kx1({y, xi, yi, kpx, kpy, xa}); const Kpy = Ky1({x, xi, yi, kpx, kpy, ya}); const Kx = Kx2({x, Kpx, xa}); const Ky = Ky2({y, Kpy, ya}); const Nax = Kx*(xa-x); const Nay = Ky*(y-ya); return {Kx, Ky, Nax, Nay}; })()

Altura de una torre de absorción, para mezclas gaseosas diluidas

La función JavaScript equivalente a la función HP zabkxi, es:

function zabkxi({L2, x2, L1, x1, y1, y2, kpx, kpy, fx, fy, S}={}) { const L = (L1+L2)/2; const HL = L/(kpx*S); const {xi:xi1, xim:xim1} = xiyi2({x:x1, y:y1, kpx, kpy, fx, fy}); const {xi:xi2, xim:xim2} = xiyi2({x:x2, y:y2, kpx, kpy, fx, fy}); const xmi = ((xi1-x1)-(xi2-x2))/Math.log((xi1-x1)/(xi2-x2)); const xm = (xim1/(1-x1)+xim2/(1-x2))/2; const NL = xm*(x1-x2)/xmi; const z = HL*NL; return {HL, NL, z}; }

Para resolver el ejemplo 5.4.1.1 con esta función y las elaboradas previamente, se procede de la siguiente manera:

Se llevan a cabo las conversiones necesarias (gas inerte: C (a kmol/s), líquido puro: B (a kmol/s) y presión P (a mmHg):

C = Qty("13.65 kmol/h").to("kmol/s").scalar.round(6)
B = Qty("45.36 kmol/h").to("kmol/s").scalar.round(6)
P = Qty("1 atm").to("mmHg").scalar.round(4)

Los datos conocidos son:

L2 = B; y1 = 0.026; y2 = 0.005; x2 = 0; kpx = 0.0616; kpy = 0.0378; S = 0.186;
vx = [0,0.033,0.0720,0.117,0.171]; vy = [0,30,62.8,85.4,103].div(P); fx = [vx, vy].inLin1; fy = [vy, vx].inLin1;

Con el flujo de gas inerte (C), se calculan los flujos inicial (V1) y final (V2) de gas:

V1 = (C/(1-y1)).round(6)
V2 = (C/(1-y2)).round(6)

Y con estos valores se calcula el porcentaje de absorción (pa):

pa = ((V1*y1-V2*y2)/(V1*y1)*100).round(3)

Con abrc1 se calcula el flujo y composición final del líquido:

var {L1, x1} = round(abrc1({L2, x2, V1, y1, pa}),6); [L1, x1]

Finalmente, con todos los datos requeridos, se llama a la función zabkxi para resolver el problema:

zabkxi({L2, x2, L1, x1, y1, y2, kpx, kpy, fx, fy, S})

La función JavaScript equivalente a la función HP zabkx, es:

function zabkx({L2, x2, L1, x1, y1, y2, kx, ky, fx, fy, S}={}) { const {xi:xi1} = xiyi1({x:x1, y:y1, kpx:kx, kpy:ky, fx, fy}); const {xi:xi2} = xiyi1({x:x2, y:y2, kpx:kx, kpy:ky, fx, fy}); const xim1 = ((1-x1)-(1-xi1))/Math.log((1-x1)/(1-xi1)); const xim2 = ((1-x2)-(1-xi2))/Math.log((1-x2)/(1-xi2)); const Lm = (L1/xim1+L2/xim2)/2; const HL = Lm/(kx*S); const xmi = ((xi1-x1)-(xi2-x2))/Math.log((xi1-x1)/(xi2-x2)); const xm = (xim1/(1-x1)+xim2/(1-x2))/2; const NL = xm*(x1-x2)/xmi; const z = HL*NL; return {HL, NL, z}; }

Para resolver el ejemplo 5.4.1.3 con esta función y los datos del anterior ejemplo (excepto para kx y ky) se escribe la siguiente instrucción:

kx=0.0623; ky=0.0381;
zabkx({L2, x2, L1, x1, y1, y2, kx:0.0626, ky:0.0380, fx, fy, S})

La función JavaScript equivalente a la función zabkyi es:

function zabkyi({V1, y1, V2, y2, x2, x1, kpx, kpy, fx, fy, S}={}) { const V = (V1+V2)/2; const HG = V/(kpy*S); const {yi:yi1, yim:yim1} = xiyi2({x:x1, y:y1, kpx, kpy, fx, fy}); const {yi:yi2, yim:yim2} = xiyi2({x:x2, y:y2, kpx, kpy, fx, fy}); const ymi = ((y1-yi1)-(y2-yi2))/Math.log((y1-yi1)/(y2-yi2)); const ym = (yim1/(1-y1)+yim2/(1-y2))/2; const NG = ym*(y1-y2)/ymi; const z = HG*NG; return {HG, NG, z}; }

Para resolver, con esta función, el ejemplo 5.4.1.5 (con los datos del ejemplo 5.4.1.1) se escribe la siguiente instrucción:

zabkyi({V1, y1, V2, y2, x2, x1, kpx, kpy, fx, fy, S})

La función JavaScript equivalente a la función zabky, es:

function zabky({V1, y1, V2, y2, x2, x1, kx, ky, fx, fy, S}={}) { const {yi:yi1} = xiyi1({x:x1, y:y1, kpx:kx, kpy:ky, fx, fy}); const {yi:yi2} = xiyi1({x:x2, y:y2, kpx:kx, kpy:ky, fx, fy}); const yim1 = ((1-yi1)-(1-y1))/Math.log((1-yi1)/(1-y1)); const yim2 = ((1-yi2)-(1-y2))/Math.log((1-yi2)/(1-y2)); const ymi = ((y1-yi1)-(y2-yi2))/Math.log((y1-yi1)/(y2-yi2)); const Vm = (V1/yim1+V2/yim2)/2; const HG = Vm/(ky*S); const ym = (yim1/(1-y1)+yim2/(1-y2))/2; const NG = ym*(y1-y2)/ymi; const z = HG*NG; return {HG, NG, z}; }

Para resolver, con esta función, el ejemplo 5.4.1.7 (con los datos del ejemplo 5.4.1.3), se escribe la siguiente instrucción:

zabky({V1, y1, V2, y2, x2, x1, kx, ky, fx, fy, S})

La función JavaScript equivalente a la función zabKxi de la HP, es:

function zabKxi({L2, x2, L1, x1, y1, y2, Kpx, fy, S}={}) { const L = (L1+L2)/2; const HOL = L/(Kpx*S); const xa1 = fy(y1); const xa2 = fy(y2); const xam1 = ((1-x1)-(1-xa1))/Math.log((1-x1)/(1-xa1)); const xam2 = ((1-x2)-(1-xa2))/Math.log((1-x2)/(1-xa2)); const xma = ((xa1-x1)-(xa2-x2))/Math.log((xa1-x1)/(xa2-x2)); const xm = (xam1/(1-x1)+xam2/(1-x2))/2; const NOL = xm*(x1-x2)/xma; const z = HOL*NOL; return {HOL, NOL, z}; }

Para resolver, con esta función, el ejemplo 5.4.1.9 (con los datos del ejemplo 5.4.1.1, con excepción del coeficiente global ideal KPx), se escribe la instrucción:

Kpx = 0.026;
zabKxi({L2, x2, L1, x1, y1, y2, Kpx, fy, S})

La función JavaScript equivalente a la función zabKx de la HP, es:

function zabKx({L2, x2, L1, x1, y1, y2, Kx, fy, S}={}) { const xa1 = fy(y1); const xa2 = fy(y2); const xam1 = ((1-x1)-(1-xa1))/Math.log((1-x1)/(1-xa1)); const xam2 = ((1-x2)-(1-xa2))/Math.log((1-x2)/(1-xa2)); const xma = ((xa1-x1)-(xa2-x2))/Math.log((xa1-x1)/(xa2-x2)); const Lm= (L1/xam1+L2/xam2)/2; const HOL = Lm/(Kx*S); const xm = (xam1/(1-x1)+xam2/(1-x2))/2; const NOL = xm*(x1-x2)/xma; const z = HOL*NOL; return {HOL, NOL, z}; }

Para resolver, con esta función, el ejemplo 5.4.1.11 (con los datos del ejercicio 5.4.1.1, con excepción del coeficiente global Kx), se escribe la instrucción:

Kx = 0.0263;
zabKx({L2, x2, L1, x1, y1, y2, Kx, fy, S})

La función JavaScript equivalente a la función zabKyi de la HP, es:

function zabKyi({V1, y1, V2, y2, x2, x1, Kpy, fx, S}={}) { const V = (V1+V2)/2; const HOG = V/(Kpy*S); const ya1 = fx(x1); const ya2 = fx(x2); const yam1 = ((1-ya1)-(1-y1))/Math.log((1-ya1)/(1-y1)); const yam2 = ((1-ya2)-(1-y2))/Math.log((1-ya2)/(1-y2)); const yma = ((y1-ya1)-(y2-ya2))/Math.log((y1-ya1)/(y2-ya2)); const ym = (yam1/(1-y1)+yam2/(1-y2))/2; const NOG = ym*(y1-y2)/yma; const z = HOG*NOG; return {HOG, NOG, z}; }

Para resolver, con esta función, el ejemplo 5.4.1.13 (con los datos del ejercicio 5.4.1.1, con excepción del coeficiente global ideal Kpy), se escribe la instrucción:

Kpy = 0.02178;
zabKyi({V1, y1, V2, y2, x2, x1, Kpy, fx, S})

La función JavaScript equivalente a la función zabKy de la HP, es:

function zabKy({V1, y1, V2, y2, x2, x1, Ky, fx, S}={}) { const ya1 = fx(x1); const ya2 = fx(x2); const yam1 = ((1-ya1)-(1-y1))/Math.log((1-ya1)/(1-y1)); const yam2 = ((1-ya2)-(1-y2))/Math.log((1-ya2)/(1-y2)); const yma = ((y1-ya1)-(y2-ya2))/Math.log((y1-ya1)/(y2-ya2)); const Vm = (V1/yam1+V2/yam2)/2; const HOG = Vm/(Ky*S); const ym = (yam1/(1-y1)+yam2/(1-y2))/2; const NOG = ym*(y1-y2)/yma; const z = HOG*NOG; return {HOG, NOG, z}; }

Para resolver, con esta función, el ejemplo 5.4.1.15 (con los datos del ejercicio 5.4.1.1, con excepción del coeficiente global Ky), se escribe la instrucción:

Ky = 0.02199;
zabKy({V1, y1, V2, y2, x2, x1, Ky, fx, S})

Mezclas gaseosas concentradas

El método JavaScript equivalente a la función Trapt de la HP, para el cálculo de la integral a partir de datos tabulados, se denomina trapecio, el cual se llama desde la tabla que contiene los datos conocidos (filas x-y) a integrar.

Array.prototype.trapecio = function({a, b}={}) { if (this.length<2) throw "trapecio: la tabla debe tener dos filas: datos 'x' y datos 'y'"; let [x, y] = [this[0].slice(), this[1].slice()]; if (x.length != y.length) throw "trapecio: las dos filas deben tener el mismo número de elementos." if (x.length<2) throw "trapecio: La tabla debe tener por lo menos 2 puntos"; // Función local de interpolación lineal const inLin = (xc,i,j) => { const b = (y[i]-y[j])/(x[i]-x[j]); const a = y[i]-b*x[i]; return a+b*xc; }; // Si se ha mandado el límite inferior de integración if (a!=undefined) { // Y el límite es menor al menor valor tabulado, se extrapola el punto y se añade a los datos if (a<x[0]) { let yc = inLin(a,0,1); x.unshift(a); y.unshift(yc); // Si no corresponde a uno de los puntos tabulados se interpola el punto, se eliminan los puntos previos y se añade al principio el punto interpolado } else if (x.indexOf(a)<0) { let j = x.findIndex(e => e>a); if (j<0 || j>x.length-1) throw "trapecio: el límite inferior debe ser menor al último punto tabulado" let yc = inLin(a,j-1,j); x.splice(0,j); x.unshift(a); y.splice(0,j); y.unshift(yc); // Si es uno de los puntos tabulados, se eliminan los puntos previos } else { let i = x.indexOf(a); x.splice(0,i); y.splice(0,i); } } // Si se ha mandado el límite superior de integración if (b!=undefined) { // Y el límite es mayor al mayor valor tabulado, se extrapola el punto y se añade a los datos if (b>x[x.length-1]) { let j = x.length-1; let yc = inLin(b,j-1,j) x.push(b); y.push(yc); // Si no corresponde a uno de los puntos tabulados se interpola el punto, se eliminan los puntos posteriores y se añade al filan el punto interpolado } else if (x.indexOf(b)<0) { let j = x.findIndex(e => e>b); if (j<0 || j<1) throw "trapecio: el límite superior debe ser mayor al primer punto tabulado" let yc = inLin(b,j-1,j); x.splice(j); x.push(b); y.splice(j); y.push(yc); // Si es uno de los puntos tabulados, se eliminan los puntos posteriores } else { let k = x.indexOf(b); x.splice(k+1); y.splice(k+1); } } // Se calcula la integral con el método del trapecio let s = 0; for (let i=0; i<x.length-1; i++) { s += (x[i+1]-x[i])/2*(y[i]+y[i+1]); } return s; };

Sin embargo, como se puede ver en el código, el método implementado en JavaScript no sólo integra todos los datos de la tabla (como ocurre con la versión HP), sino que permite integrar desde un valor intermedio (existente o no) hasta otro valor intermedio (existente o no) así como desde un valor anterior o posterior a los datos tabulados. El cálculo de la integral propiamente (que es lo único que se calcula en la versión HP), está programado en el último bloque del método.

El método JavaScript equivalente a la función Simpt de la Hp, se denomina simpson y al igual que en el método del trapecio, debe ser llamado desde la tabla con los datos conocidos (filas x-y):

Array.prototype.simpson = function({a, b}={}) { if (this.length<2) throw "simpson: la tabla debe tener dos filas: datos 'x' y datos 'y'"; let [x, y] = [this[0].slice(), this[1].slice()]; if (x.length != y.length) throw "simpson: las dos filas deben tener el mismo número de elementos." if (x.length<3) throw "simpson: La tabla debe tener por lo menos 3 puntos"; // Cálculo de los coeficientes de la ecuación cuadrática const coeficientes = (i,j,k) => { const a = ((y[i]-y[k])*(x[i]-x[j])-(y[i]-y[j])*(x[i]-x[k]))/ ((x[i]**2-x[k]**2)*(x[i]-x[j])-(x[i]**2-x[j]**2)*(x[i]-x[k])); const b = ((y[i]-y[j])-a*(x[i]**2-x[j]**2))/(x[i]-x[j]); const c = y[i]-a*x[i]**2-b*x[i]; return [a,b,c]; }; // Cálculo del área debajo de la curva cuadrática const area = (a,b,c,i,k) => a/3*(x[k]**3-x[i]**3)+b/2*(x[k]**2-x[i]**2)+c*(x[k]-x[i]); // Si se ha mandado el límite inferior de integración if (a!=undefined) { // Y el límite es menor al menor valor tabulado, se extrapola el punto y se añade a los datos if (a<x[0]) { const [ca,cb,cc] = coeficientes(0,1,2); x.unshift(a); y.unshift(ca*a**2+cb*a+cc); // Si no corresponde a uno de los puntos tabulados se interpola el punto, se eliminan los puntos previos y se añade al principio el punto interpolado } else if (x.indexOf(a)<0) { let j = x.findIndex(e => e>a); if (j<0 || j>x.length-2) throw "simpson: el límite inferior debe ser menor al penúltimo punto tabulado" const [ca,cb,cc] = coeficientes(j-1,j,j+1); x.splice(0,j); x.unshift(a); y.splice(0,j); y.unshift(ca*a**2+cb*a+cc); // Si es uno de los puntos tabulados, se eliminan los puntos previos } else { let i = x.indexOf(a); x.splice(0,i); y.splice(0,i); } } // Si se ha mandado el límite superior de integración if (b!=undefined) { // Y el límite es mayor al mayor valor tabulado, se extrapola el punto y se añade a los datos if (b>x[x.length-1]) { let k = x.length-1; const [ca,cb,cc] = coeficientes(k-2,k-1,k); x.push(b); y.push(ca*b**2+cb*b+cc); // Si no corresponde a uno de los puntos tabulados se interpola el punto, se eliminan los puntos posteriores y se añade al filan el punto interpolado } else if (x.indexOf(b)<0) { let j = x.findIndex(e => e>b); if (j<0 || j<2) throw "simpson: el límite superior debe ser mayor al segundo punto tabulado" const [ca,cb,cc] = coeficientes(j-2,j-1,j); x.splice(j); x.push(b); y.splice(j); y.push(ca*b**2+cb*b+cc); // Si es uno de los puntos tabulados, se eliminan los puntos posteriores } else { let k = x.indexOf(b); x.splice(k+1); y.splice(k+1); } } // Se calcula la integral con el método de Simpson let s=0, i=0, n=(x.length-1).quot(2); if (x.length%2===0) { const [a,b,c] = coeficientes(0,1,2); s += area(a,b,c,0,1); i++; } for (let l=0; l<n; l++) { const [a,b,c] = coeficientes(i,i+1,i+2); s += area(a,b,c,i,i+2); i+=2; } return s; };

Al igual que el método del trapecio, el método de Sinpson permite integrar entre valores intermedios e inclusive entre valores anteriores y posteriores a los datos tabulados. La integración propiamente está programa en el último bloque de instrucciones del método.

Para los datos de la sección 5.4.2 del texto:

vx = [2.0, 2.5, 2.7, 3.0, 3.3, 3.8, 4.2, 4.5, 5.1, 5.7, 6.0, 6.4, 6.9, 7.2, 7.5]; vy = vy = [4.800, 6.625, 7.509, 9.00, 10.689, 13.944, 16.944, 19.425, 24.981, 31.329, 34.800, 39.736, 46.401, 50.664, 55.125];

Para integrar entre 2.5 y 7.2 (tanto con trapecio como con Simpson, se escribe:

[vx, vy].trapecio({a:2.5, b:7.2}).round(6)
[vx, vy].simpson({a:2.5, b:7.2}).round(6)

Con lo que se obtienen los mismos resultados que con Trapt y Simpt, sólo que, con los métodos trapecio y simpson, no es necesario recortar la tabla hasta los límites de integración, sino que se emplea la tabla completa y se mandan los límites de integración.

Para integrar desde el límite inicial hasta el límite final de la tabla, simplemente no se mandan los límites de integración:

[vx, vy].trapecio().round(6)
[vx, vy].simpson().round(6)

Para integrar entre valores intermedios no tabulados (interpolados), simplemente se escriben esos límites:

[vx, vy].trapecio({a:2.9, b:7.1}).round(6)
[vx, vy].simpson({a:2.9, b:7.1}).round(6)

Igualmente, para integrar entre valores anteriores y/o posteriores a los datos tabulados (extrapolación), simplemente se escriben los límites (por supuesto al tratarse de una extrapolación, no se puede garantizar la exactitud de los resultados):

[vx, vy].trapecio({a:1.8, b:7.6}).round(6)
[vx, vy].simpson({a:1.8, b:7.6}).round(6)

La función JavaScript equivalente a la función abkxi, es:

function abkxi({x2, L1, x1, V1, y1, fkpxkpy, fx, fy, S}={}) { const B = L1*(1-x1); const C = V1*(1-y1); const D1 = B*x1/(1-x1)-C*y1/(1-y1); const fkxi = x => { const D2 = (B*x/(1-x)-D1)/C; const y = D2/(1+D2); const L = B/(1-x); const V = C/(1-y); const {kpx, kpy} = fkpxkpy({L, x, V, y, S}); const {xi, xim} = xiyi2({x, y, kpx, kpy, fx, fy}); return xim*L/(kpx*S*(1-x)*(xi-x)); }; return fkxi.simpson({a:x2, b:x1, n:10}); }

Así, para resolver el ejemplo 5.4.2.1 con esta función, se procede de la siguiente forma:

Los datos conocidos son:

x2=0.0; y1=0.2; y2=0.02; C=6.53e-4; B=L2=4.2e-2; S=0.0929;
P=Qty("1.01325e5 Pa").to("mmHg").scalar.round(2)
vx = [0,0.0000562,0.0001403,0.000280,0.000422,0.000564,0.000842,0.001403,0.001965,0.00279,0.00420,0.00698,0.01385,0.0206,0.0273]; vy = [0,0.5,1.2,3.2,5.8,8.5,14.1,26,39,59,92,161,336,517,698].div(P); fx = [vx, vy].inLin1; fy = [vy, vx].inLin1;

Con el flujo de gas inerte conocido (C), se calculan los flujos de gas y el porcentaje de absorción (pa):

V1 = C/(1-y1); V2 = (C/(1-y2)); pa = (V1*y1-V2*y2)/(V1*y1)*100; print(V1, V2, pa)

Entonces, con la función abrc1 se calculan el flujo y fracción molar final del líquido (L1, x1):

var {L1, x1} = abrc1({L2, x2, V1, y1, pa}); print(L1, x1)

Se programa la función que devuelve las coeficientes ideales de transferencia de masa:

function fkpxkpy({L, x, V, y, S}={}) { const Gx = (L*(1-x)*18.02+L*x*64.1)/S; const Gy = (V*(1-y)*28.97+V*y*64.1)/S const kpy = 0.0594*Gy**0.7*Gx**0.25; const kpx = 0.152*Gx**0.82; return {kpx, kpy}; }

Finalmente, con todos los datos disponibles, se llama a la función abkxi, con lo que se obtiene la altura de la torre de absorción:

abkxi({x2, L1, x1, V1, y1, fkpxkpy, fx, fy, S})

La función JavaScript equivalente a la función abkx de la HP, es:

function abkx({x2, L1, x1, V1, y1, fkxky, fx, fy, S}={}) { const B = L1*(1-x1); const C = V1*(1-y1); const D1 = B*x1/(1-x1)-C*y1/(1-y1); const fkxi = x => { const D2 = (B*x/(1-x)-D1)/C; const y = D2/(1+D2); const L = B/(1-x); const V = C/(1-y); const {kx, ky} = fkxky({L, x, V, y, S}); const {xi} = xiyi1({x, y, kpx:kx, kpy:ky, fx, fy}); return L/(kx*S*(1-x)*(xi-x)); }; return fkxi.simpson({a:x2, b:x1, n:10}); }

Para resolver, con esta función, el ejemplo 5.4.2.3, con los mismos datos que el ejemplo 5.4.2.1, con excepción del cálculo de los coeficientes de transferencia de masa individuales, que ahora se calculan con:

function fkxky({L, x, V, y, S}={}) { const Gx = (L*(1-x)*18.02+L*x*64.1)/S; const Gy = (V*(1-y)*28.97+V*y*64.1)/S const kx = 0.159*Gx**0.82; const ky = 0.0599*Gy**0.7*Gx**0.25; return {kx, ky}; }

Se a la función, con lo que se obtiene la solución buscada (la altura de la torre de absorción):

abkx({x2, L1, x1, V1, y1, fkxky, fx, fy, S})

La función JavaScript equivalente a la función abkyi, es:

function abkyi({L1, x1, V1, y1, y2, fkpxkpy, fx, fy, S}={}) { const B = L1*(1-x1); const C = V1*(1-y1); const D1 = B*x1/(1-x1)-C*y1/(1-y1); const fkxi = y => { const D3 = (C*y/(1-y)+D1)/B; const x = D3/(1+D3); const L = B/(1-x); const V = C/(1-y); const {kpx, kpy} = fkpxkpy({L, x, V, y, S}); const {yi, yim} = xiyi2({x, y, kpx, kpy, fx, fy}); return yim*V/(kpy*S*(1-y)*(y-yi)); }; return fkxi.simpson({a:y2, b:y1, n:10}); }

Para resolver, con esta función, el ejemplo 5.4.2.5, con los datos del ejemplo 5.4.2.1, se escribe la instrucción:

abkyi({L1, x1, V1, y1, y2, fkpxkpy, fx, fy, S})

La función JavaScript equivalente a la función abky, es:

function abky({L1, x1, V1, y1, y2, fkxky, fx, fy, S}={}) { const B = L1*(1-x1); const C = V1*(1-y1); const D1 = B*x1/(1-x1)-C*y1/(1-y1); const fkxi = y => { const D3 = (C*y/(1-y)+D1)/B; const x = D3/(1+D3); const L = B/(1-x); const V = C/(1-y); const {kx, ky} = fkxky({L, x, V, y, S}); const {yi} = xiyi1({x, y, kpx:kx, kpy:ky, fx, fy}); return V/(ky*S*(1-y)*(y-yi)); }; return fkxi.simpson({a:y2, b:y1, n:10}); }

Para resolver, con esta función, el ejemplo 5.4.2.7, con los datos del ejemplo 5.4.2.1, se escribe la instrucción:

abky({L1, x1, V1, y1, y2, fkxky, fx, fy, S})

La función JavaScript equivalente a la función abKxi, es:

function abKxi({x2, L1, x1, V1, y1, fKpx, fy, S}={}) { const B = L1*(1-x1); const C = V1*(1-y1); const D1 = B*x1/(1-x1)-C*y1/(1-y1); const fKxi = x => { const D2 = (B*x/(1-x)-D1)/C; const y = D2/(1+D2); const L = B/(1-x); const V = C/(1-y); const Kpx = fKpx(); const xa = fy(y); const xam = ((1-x)-(1-xa))/Math.log((1-x)/(1-xa)); return xam*L/(Kpx*S*(1-x)*(xa-x)); }; const z = fKxi.simpson({a:x2, b:x1, n:10}); return z; }

Para resolver con esta función el ejemplo 5.4.2.9, asumiendo que los datos del ejemplo 5.4.2.1 corresponden a un columna real, se procede de la siguiente forma.

Primero con los datos del ejemplo 5.4.2.1 y asumiendo que la altura calculada en ese ejemplo (1.57 m), es la altura real de un equipo de absorción, se calcula el coeficiente global ideal (Kpx), asumiendo valores del coeficiente hasta que la altura calculada (con abKxi) sea igual a la altura conocida (1.57 m). La función que devuelve 0, cuando se cumple que la altura calculada es igual a la conocida, es:

function fK(K) { fKpx = () =>K; return abKxi({x2, L1, x1, V1, y1, fKpx, fy, S})-1.57; }

Esta función puede ser resuelta con uno de los métodos, para resolver ecuaciones algebraicas no lineales. Así, empleando el método de secante (como en el texto), se obtiene:

Kpx = fK.secante({xi:0.8, xf:0.81})

Por supuesto se podría emplear otro método, por ejemplo Regula-Falsi:

Kpx = fK.refa({xi:0.1, xf:0.9})

Ahora, con el coeficiente global ideal calculado (Kpx) y el porcentaje de absorción fijado (pa=98), se calculan los nuevos valores del flujo molar y fracción molar final del líquido (L1n, xin):

var {L1:L1n, x1:x1n} = abrc1({L2, x2, V1, y1, pa:98}); print(L1n, x1n)

Y con estos nuevos flujos se calcula la nueva altura de la torre:

abKxi({x2, L1:L1n, x1:x1n, V1, y1, fKpx:()=>Kpx, fy, S})

La función JavaScript equivalente a la función abKx de HP, es:

function abKx({x2, L1, x1, V1, y1, fKx, fy, S}={}) { const B = L1*(1-x1); const C = V1*(1-y1); const D1 = B*x1/(1-x1)-C*y1/(1-y1); const fK = x => { const D2 = (B*x/(1-x)-D1)/C; const y = D2/(1+D2); const L = B/(1-x); const V = C/(1-y); const Kx = fKx(); const xa = fy(y); return L/(Kx*S*(1-x)*(xa-x)); }; const z = fK.simpson({a:x2, b:x1, n:10}); return z; }

Para resolver el ejemplo 5.4.2.11, con los mismos datos del ejemplo 5.4.2.9, primero se calcula el coeficiente global de transferencia de masa:

function fK(K) { fKx = () =>K; return abKx({x2, L1, x1, V1, y1, fKx, fy, S})-1.57; }
Kx = fK.secante({xi:0.8, xf:0.81})

Entonces, para empleando el flujo y composición finales correspondientes al nuevo porcentaje de absorción requerido (L1n, x1n), se calcula la altura de la torre:

abKx({x2, L1:L1n, x1:x1n, V1, y1, fKx:()=>Kx, fy, S})

La función JavaScript equivalente a la función abKy1 de la HP, es:

function abKyi({L1, x1, V1, y1, y2, fKpy, fx, S}={}) { const B = L1*(1-x1); const C = V1*(1-y1); const D1 = B*x1/(1-x1)-C*y1/(1-y1); const fKyi = y => { const D3 = (C*y/(1-y)+D1)/B; const x = D3/(1+D3); const L = B/(1-x); const V = C/(1-y); const Kpy = fKpy(); const ya = fx(x); const yam = ((1-ya)-(1-y))/Math.log((1-ya)/(1-y)); return yam*V/(Kpy*S*(1-y)*(y-ya)); }; const z = fKyi.simpson({a:y2, b:y1, n:10}); return z; }

Para resolver el ejemplo 5.4.2.13, con los datos del ejemplo 5.4.2.9, primero se calcula el coeficiente global ideal de la fase gaseosa:

function fK(K) { const fKpy = () => K; return abKyi({L1, x1, V1, y1, y2, fKpy, fx, S})-1.57; }
Kpy = fK.secante({xi:0.0035, xf:0.0036})

Entonces, con el nuevo flujo y composición inicial requeridos (L1n, x1n) y el coeficiente calculado (Kpy), se calcula la nueva altura de la torre de absorción:

abKyi({L1:L1n, x1:x1n, V1, y1, y2, fKpy:()=>Kpy, fx, S})

La función javascript equivalente a la función abKy de la HP, es:

function abKy({L1, x1, V1, y1, y2, fKy, fx, S}={}) { const B = L1*(1-x1); const C = V1*(1-y1); const D1 = B*x1/(1-x1)-C*y1/(1-y1); const fK = y => { const D3 = (C*y/(1-y)+D1)/B; const x = D3/(1+D3); const L = B/(1-x); const V = C/(1-y); const Ky = fKy(); const ya = fx(x); const yam = ((1-ya)-(1-y))/Math.log((1-ya)/(1-y)); return V/(Ky*S*(1-y)*(y-ya)); }; const z = fK.simpson({a:y2, b:y1, n:10}); return z; }

Para resolver el ejemplo 5.4.2.15, con los datos del ejemplo 5.4.2.9, primero se calcula el coeficiente global de la fase gaseosa:

function fK(K) { const fKy = () => K; return abKy({L1, x1, V1, y1, y2, fKy, fx, S})-1.57; }
Ky = fK.secante({xi:0.0035, xf:0.0036})

Entonces, con el nuevo flujo y composición final requeridos (L1n, x1n) y el coeficiente calculado (Ky), se calcula la nueva altura de la torre de absorción:

abKy({L1:L1n, x1:x1n, V1, y1, y2, fKy:()=>Ky, fx, S})

Referencia de las funciones disponibles

La referencia detallada de las funciones presentadas en este y en los anteriores capítulos (incluido el código de los programas elaborados), está disponible en el siguiente enlace (donde se irán incorporando otras funciones a medida que se las presente y utilice):

Referencia funciones disponibles