Clear Filters
Clear Filters

Multicomponent gas separation in hollow fiber membranes

73 views (last 30 days)
Hi!
I'm trying to model gas separation of a gas with 4 components (H2, N2, N3H and O2) using a hollow fiber membrane. In papers I found the following equations:
(the change in the retentate flow rate)
( the change in the mole fraction of component i in the retentate)
( the change in the mole fraction of component i in the permeate)
I am solving these equations by first using the backwards finite difference method which turns the first two equations into:
Next, I am trying to use Newton's method to solve all 9 equations together. This is my code:
%% Gas separation in a cocurrent hollow fiber membrane
thickness_membrane = 1e-6; % thickness membrane [m]
Perm_H2 = 250*3.35e-16; % Permeability H2 [mol m/m2 s Pa]
Perm_N2 = 9*3.35e-16; % Permeability H2 [mol m/m2 s Pa]
Perm_NH3 = 830*3.35e-16; % Permeability H2 [mol m/m2 s Pa]
Perm_O2 = 37*3.35e-16;
R=8.314;
T = 273.15+25; % correlation temperature [K]
Per_H2 = Perm_H2/thickness_membrane; % Permeance of H2 [mol/m2 s Pa]
Per_N2 = Perm_N2/thickness_membrane; % Permeance of N2 [mol/m2 s Pa]
Per_NH3 = Perm_NH3/thickness_membrane; % Permeance of N2 [mol/m2 s Pa]
Per_O2 = Perm_O2/thickness_membrane;
%% Input parameters
F_feed = 1133.95/3.6; % feed [mol/s]
x_H2_F = 0.0268; % [-]
x_N2_F =0.9682; % [-]
x_NH3_F = 0.0049; % [-]
x_O2_F = 0.0001;
P_F = 35e5; % pressure feed [Pa]
P_P = 1e5; % pressure Permeate [Pa]
%% Assumptions membrane
L_fiber = 10;
r_fiber = (0.75e-3)/2;
n_fiber = 4000;
% Define the mesh
step= 80;
mesh = 0:(L_fiber/step):L_fiber; % linear space vector
nmesh= numel(mesh);
h = mesh(2)-mesh(1);
visc_H2 = 88e-6;
visc_N2 = 17.82e-6; % [Pa s]
visc_NH3 = 9.9e-6;
visc_O2 = 20.4e-6;
mu = visc_N2; % most present
syms xH2 yH2 Ff xN2 yN2 xNH3 yNH3 xO2 yO2
variables = [ Ff; xH2; xN2 ; xNH3; xO2; yH2; yN2; yNH3; yO2];
Final_results = zeros(10,10,numel(mesh));
xH2prev = x_H2_F;
xN2prev = x_N2_F;
xNH3prev = x_NH3_F;
xO2prev = x_O2_F;
%P_Pprev= P_P;
Ffprev = F_feed;
BETA = P_P/P_F;
for z = 1:nmesh
%% Equations to solve making use of the backward difference method
eq1 = (Ff-Ffprev)/h + 2*3.14*r_fiber*L_fiber*n_fiber*((Per_H2*(xH2*P_F + yH2*P_P)) + (Per_NH3*(xNH3*P_F + yNH3*P_P)) + (Per_N2*(xN2*P_F + yN2*P_P)) + (Per_O2*(xO2*P_F + yO2*P_P)) );
eq2 = (xH2- xH2prev)/h - 1/Ff * (2*3.14*r_fiber*L_fiber*n_fiber*Per_H2*(xH2*P_F + yH2*P_P) + xH2*(Ff-Ffprev)/h);
eq3 = (xN2- xN2prev)/h - 1/Ff * (2*3.14*r_fiber*L_fiber*n_fiber*Per_N2*(xN2*P_F + yN2*P_P) + xN2*(Ff-Ffprev)/h);
eq4 = (xNH3- xNH3prev)/h - 1/Ff * (2*3.14*r_fiber*L_fiber*n_fiber*Per_NH3*(xNH3*P_F + yNH3*P_P) + xNH3*(Ff-Ffprev)/h);
eq5 = (xO2- xO2prev)/h - 1/Ff * (2*3.14*r_fiber*L_fiber*n_fiber*Per_O2*(xO2*P_F + yO2*P_P) + xO2*(Ff-Ffprev)/h);
eq6 = yH2 - (Per_H2*xH2 * ((yH2/Per_H2) + (yN2/Per_N2) + (yNH3/Per_NH3) + (yO2/Per_O2) ) / (1-BETA + BETA*Per_H2*((yH2/Per_H2) + (yN2/Per_N2) + (yNH3/Per_NH3) + (yO2/Per_O2) )));
eq7 = yN2 - (Per_N2*xN2 * ((yH2/Per_H2) + (yN2/Per_N2) + (yNH3/Per_NH3) + (yO2/Per_O2) ) / (1-BETA + BETA*Per_N2*((yH2/Per_H2) + (yN2/Per_N2) + (yNH3/Per_NH3) + (yO2/Per_O2) )));
eq8 = yNH3 - (Per_NH3*xNH3 * ((yH2/Per_H2) + (yN2/Per_N2) + (yNH3/Per_NH3) + (yO2/Per_O2) ) / (1-BETA + BETA*Per_NH3*((yH2/Per_H2) + (yN2/Per_N2) + (yNH3/Per_NH3) + (yO2/Per_O2) )));
eq9 = yO2 - (Per_O2*xO2 * ((yH2/Per_H2) + (yN2/Per_N2) + (yNH3/Per_NH3) + (yO2/Per_O2) ) / (1-BETA + BETA*Per_O2*((yH2/Per_H2) + (yN2/Per_N2) + (yNH3/Per_NH3) + (yO2/Per_O2) )));
%eq10 = ((Pp - Ppprev)/h) -( (8*R*T*mu*(F_feed-Ff))/ (3.14*r_fiber^4*n_fiber*Pp));
F = [eq1;eq2;eq3;eq4;eq5;eq6;eq7;eq8;eq9];
J=jacobian([eq1,eq2,eq3,eq4,eq5,eq6,eq7,eq8,eq9],variables);
x_0 = [10 ;0.5; 0.001; 0.1; 0.0001; 0.3; 0.01; 1; 0.001];
Final_results(1,1:9,1) = x_0';
iterations = 100;
for iter=1:iterations
%% Newton
% Substitute the initial values into the Jacobian matrix
J_subs = subs(J, variables, x_0);
F_subs = subs(F,variables,x_0);
aug_matrix = [J_subs, -F_subs];
n= 9;
for i = 1:n-1
for j = i+1:n
factor = aug_matrix(j, i) / aug_matrix(i, i);
aug_matrix(j, :) = aug_matrix(j, :) - factor * aug_matrix(i, :);
end
end
y_0 = zeros(n, 1);
y_0(n) = aug_matrix(n, n+1) / aug_matrix(n,n);
for i = n-1:-1:1
y_0(i) = (aug_matrix(i, n+1) - aug_matrix(i, i+1:n) * y_0(i+1:n)) / aug_matrix(i, i);
end
x_result = y_0 + x_0;
Final_results(iter+1,1:9,z) = x_result';
err = norm(x_result - x_0);
Final_results(iter+1,10,z) = err;
x_0 = x_result;
if err <= 1e-8
%P_Pprev = x_result(10);
disp(['Converged after ', num2str(iter), ' iterations']);
break;
end
end
xH2prev = x_0(2);
xN2prev = x_0(3);
xNH3prev = x_0(4);
xO2prev = x_0(5);
Ffprev = x_0(1);
end
solution_Ff_Per_step = [];
solution_xH2_Per_step = [];
solution_xN2_Per_step = [];
solution_xNH3_Per_step = [];
solution_xO2_Per_step = [];
solution_yH2_Per_step = [];
solution_yN2_Per_step = [];
solution_yNH3_Per_step = [];
solution_yO2_Per_step = [];
solution_P_P_Per_step = [];
for m=1:numel(mesh)
solution_Ff_Per_step = [Final_results(end,1,m) solution_Ff_Per_step];
solution_xH2_Per_step = [Final_results(end,2,m) solution_xH2_Per_step];
solution_xN2_Per_step = [Final_results(end,3,m) solution_xN2_Per_step];
solution_xNH3_Per_step = [Final_results(end,4,m) solution_xNH3_Per_step];
solution_xO2_Per_step = [Final_results(end,5,m) solution_xO2_Per_step];
solution_yH2_Per_step = [Final_results(end,6,m) solution_yH2_Per_step];
solution_yN2_Per_step = [Final_results(end,7,m) solution_yN2_Per_step];
solution_yNH3_Per_step = [Final_results(end,8,m) solution_yNH3_Per_step];
solution_yO2_Per_step = [Final_results(end,9,m) solution_yO2_Per_step];
%solution_P_P_Per_step = [Final_results(end,10,m) solution_P_P_Per_step];
end
figure(1)
plot(mesh,solution_Ff_Per_step)
xlabel('Distance along membrane module [m]')
ylabel('Flow rate retentate [m/s]')
figure(2)
plot(mesh,solution_xH2_Per_step)
xlabel('Distance along membrane module [m]')
ylabel('Mole fraction H_{2} in retentate')
figure(3)
plot(mesh,solution_xN2_Per_step )
xlabel('Distance along membrane module [m]')
ylabel('Mole fraction N_{2} in retentate')
figure(4)
plot(mesh,solution_xNH3_Per_step)
xlabel('Distance along membrane module [m]')
ylabel('Mole fraction NH_{3} in retentate')
figure(5)
plot(mesh,solution_xO2_Per_step)
xlabel('Distance along membrane module [m]')
ylabel('Mole fraction O_{2} in retentate')
figure(6)
plot(mesh,solution_yH2_Per_step)
xlabel('Distance along membrane module [m]')
ylabel('Mole fraction H_{2} in Permeate')
figure(7)
plot(mesh,solution_yN2_Per_step)
xlabel('Distance along membrane module [m]')
ylabel('Mole fraction N_{2} in Permeate')
figure(8)
plot(mesh,solution_yNH3_Per_step)
xlabel('Distance along membrane module [m]')
ylabel('Mole fraction NH_{3} in Permeate')
figure(9)
plot(mesh,solution_yO2_Per_step)
xlabel('Distance along membrane module [m]')
ylabel('Mole fraction O_{2} in Permeate')
figure(10)
% plot(mesh,solution_P_P_Per_step)
xlabel('Distance along membrane module [m]')
ylabel('Permeate pressure [bar]')
For some reason, when the method converges it will always return the initial values of xH2prev, xNH3prev, xO2prev. xN2prev and Ffprev, meaning that there is no change in mole fractions along the membrane. When I try to change the initial conditions, the graphs show spikes in random positions whilst being 0 in other positions along the membrane. This should not be the case. Could you please help me figure out what went wrong in my code?
  4 Comments
Torsten
Torsten on 8 Jun 2024
I think the last four equations should start as
x(6) - (par.Per_H2*x(2)... )
x(7) - (par.Per_N2*x(3)... )
x(8) - (par.Per_NH3*x(4) ...)
x(9) - (par.Per_O2*x(5) ...)
because these are algebraic equations of the form
0*dyi/dt = y(i) - rhs(i) (i=6,...,9)
Try to give initial guesses for the yi that satisfy the algebraic equations - otherwise you might get the problem that ode15s cannot compute consistent initial values. You might want to use "fsolve" to compute these consistent initial values for the yi before calling ode15s.
MeepMeep
MeepMeep on 8 Jun 2024
Hi Torsten
Once again a big thank you for responding so quickly!
I changed the last equations and implemented fsolve (see my code below). I was wondering if there was also a way in which I could specify how to make sure these initial values are positive? Right now the program works, but along the membrane length the y_i values become negative, which should not physically be possible.
Thank you once again!
% Initial guess for x(6) to x(9)
par.initial_guess = [0.3 ;0.1 ;0.5 ;0.1]; % Example guess, you may need to adjust
%par.initial_guess = [0.1;0.015;0.1;0.015]; % Example guess, you may need to adjust
% Use fsolve to find consistent initial values
options = optimoptions('fsolve', 'Display', 'iter');
[par.initial_values, fval, exitflag] = fsolve(@(x) algebraic_constraints(x, par), par.initial_guess, options);
par.initial_values
% Check if fsolve was successful
if exitflag <= 0
error('fsolve did not converge to a solution');
end
par.x0 = [par.F_feed ; par.x_H2_F ; par.x_N2_F ;par.x_NH3_F ;par.x_O2_F ;par.initial_values(1);par.initial_values(2); par.initial_values(3); par.initial_values(4) ];
par.tspan = 0:0.05:par.L_fiber;
par.M = [1 0 0 0 0 0 0 0 0 ; 0 1 0 0 0 0 0 0 0 ; 0 0 1 0 0 0 0 0 0 ; 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 1 0 0 0 0 ; 0 0 0 0 0 0 0 0 0 ; 0 0 0 0 0 0 0 0 0; 0 0 0 0 0 0 0 0 0 ;0 0 0 0 0 0 0 0 0];
par.options = odeset('Mass',par.M,'RelTol',1e-6,'AbsTol',1.e-6*ones(9,1));
[par.Z, par.X] = ode15s(@(z,x) dae(z,x,par),par.tspan,par.x0, par.options);
end
function out = dae(z,x,par)
out = [- 2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*((par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P)) + (par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P)) + (par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P)) + (par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P)))
1/x(1) *2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P) + x(2)*(- 2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*((par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P)) + (par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P)) + (par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P)) + (par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P))))
1/x(1) *2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P) + x(3)*(- 2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*((par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P)) + (par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P)) + (par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P)) + (par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P))))
1/x(1) *2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P) + x(4)*(- 2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*((par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P)) + (par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P)) + (par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P)) + (par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P))))
1/x(1) *2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P) + x(5)*(- 2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*((par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P)) + (par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P)) + (par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P)) + (par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P))))
x(6) - (par.Per_H2*x(2) * ((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_H2*((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) )))
x(7) - (par.Per_N2*x(3) * ((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_N2*((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) )))
x(8) - (par.Per_NH3*x(4) * ((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_NH3*((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) )))
x(9) - (par.Per_O2*x(5) * ((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_O2*((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) )))];
%x(1) = F
%x(2) = xH2
%x(3) = xN2
%x(4) = xHNH3
%x(5) = xO2
%x(6) = yH2
%x(7) = yN2
%x(8) = yNH3
%x(9) = yO2
end
function F = algebraic_constraints(x, par)
sum_terms = (x(1)/par.Per_H2) + (x(2)/par.Per_N2) + (x(3)/par.Per_NH3) + (x(4)/par.Per_O2);
F = [
x(1) - (par.Per_H2*par.x_H2_F * ((x(1)/par.Per_H2) + (x(2)/par.Per_N2) + (x(3)/par.Per_NH3) + (x(4)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_H2*((x(1)/par.Per_H2) + (x(2)/par.Per_N2) + (x(3)/par.Per_NH3) + (x(4)/par.Per_O2) )))
x(2) - (par.Per_N2*par.x_N2_F * ((x(1)/par.Per_H2) + (x(2)/par.Per_N2) + (x(3)/par.Per_NH3) + (x(4)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_N2*((x(1)/par.Per_H2) + (x(2)/par.Per_N2) + (x(3)/par.Per_NH3) + (x(4)/par.Per_O2) )))
x(3) - (par.Per_NH3*par.x_NH3_F * ((x(1)/par.Per_H2) + (x(2)/par.Per_N2) + (x(3)/par.Per_NH3) + (x(4)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_NH3*((x(1)/par.Per_H2) + (x(2)/par.Per_N2) + (x(3)/par.Per_NH3) + (x(4)/par.Per_O2) )))
x(4) - (par.Per_O2*par.x_O2_F * ((x(1)/par.Per_H2) + (x(2)/par.Per_N2) + (x(3)/par.Per_NH3) + (x(4)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_O2*((x(1)/par.Per_H2) + (x(2)/par.Per_N2) + (x(3)/par.Per_NH3) + (x(4)/par.Per_O2) )))
];
end

Sign in to comment.

Accepted Answer

Torsten
Torsten on 9 Jun 2024
Edited: Torsten on 9 Jun 2024
par.thickness_membrane = 1e-6; % thickness membrane [m]
par.Perm_H2 = 250*3.35e-16; % Permeability H2 [mol m/m2 s Pa]
par.Perm_N2 = 9*3.35e-16; % Permeability H2 [mol m/m2 s Pa]
par.Perm_NH3 = 830*3.35e-16; % Permeability H2 [mol m/m2 s Pa]
par.Perm_O2 = 37*3.35e-16;
par.R=8.314;
par.T = 273.15+25; % correlation temPeratures [K]
par.Per_H2 = par.Perm_H2/par.thickness_membrane; % Permeance of H2 [mol/m2 s Pa]
par.Per_N2 = par.Perm_N2/par.thickness_membrane; % Permeance of N2 [mol/m2 s Pa]
par.Per_NH3 = par.Perm_NH3/par.thickness_membrane; % Permeance of N2 [mol/m2 s Pa]
par.Per_O2 = par.Perm_O2/par.thickness_membrane;
%T_g = 273.15+155; % glass transition temPerature of polymer membrane [K]
%% Input parameters
par.F_feed = 1133.95/3.6; % feed [mol/s]
par.x_H2_F = 0.0268322; % [-]
par.x_N2_F =0.96828; % [-]
par.x_NH3_F = 0.00475768; % [-]
par.x_O2_F = 0.000129826;
%par.y_H2_init = par.Per_H2*par.x_H2_F/ (par.Per_H2*par.x_H2_F + par.Per_N2*par.x_N2_F + par.Per_NH3*par.x_NH3_F + par.Per_O2*par.x_O2_F);
%par.y_N2_init = par.Per_N2*par.x_N2_F/ (par.Per_H2*par.x_H2_F + par.Per_N2*par.x_N2_F + par.Per_NH3*par.x_NH3_F + par.Per_O2*par.x_O2_F);
%par.y_NH3_init = par.Per_NH3*par.x_NH3_F/ (par.Per_H2*par.x_H2_F + par.Per_N2*par.x_N2_F + par.Per_NH3*par.x_NH3_F + par.Per_O2*par.x_O2_F);
%par.y_O2_init = par.Per_O2*par.x_O2_F/ (par.Per_H2*par.x_H2_F + par.Per_N2*par.x_N2_F + par.Per_NH3*par.x_NH3_F + par.Per_O2*par.x_O2_F);
par.P_f = 35e5; % pressure feed [Pa]
par.P_P = 1e5; % pressure Permeate [Pa]
%% Assumptions membrane
par.L_fiber = 15;
par.r_fiber = (0.75e-3)/2;
par.n_fiber = 4000;
par.visc_H2 = 88e-6;
par.visc_N2 = 17.82e-6; % [Pa s]
par.visc_NH3 = 9.9e-6;
par.visc_O2 = 20.4e-6;
par.mu = par.visc_N2; % most present
par.BETA = par.P_P/par.P_f;
% Initial guess for x(6) to x(9)
%par.initial_guess = [0.3 ;0.1 ;0.5 ;0.1]; % Example guess, you may need to adjust
%par.initial_guess = [0.1;0.015;0.1;0.015]; % Example guess, you may need to adjust
par.initial_guess = [1 2 3 4];
% Use fsolve to find consistent initial values
options = optimoptions('fsolve', 'Display', 'iter','TolX',1e-10,'TolFun',1e-10);
[par.initial_values, fval, exitflag] = fsolve(@(x) algebraic_constraints(x, par), par.initial_guess, options);
Norm of First-order Trust-region Iteration Func-count ||f(x)||^2 step optimality radius 0 5 340.232 131 1 1 10 136.345 1 59.4 1 2 15 8.35211 2.02452 7.4 2.5 3 20 0.49738 1.05013 0.918 5.06 4 25 0.028113 0.556721 0.113 5.06 5 30 0.00165936 0.300089 0.0166 5.06 6 35 0.000106594 0.155651 0.00514 5.06 7 40 5.30496e-06 0.0637521 0.00054 5.06 8 45 2.50833e-07 0.0226726 2.91e-05 5.06 9 50 5.92523e-09 0.00864321 6.21e-06 5.06 10 55 1.41591e-11 0.0019109 3.04e-07 5.06 11 60 1.22041e-16 0.000103533 8.92e-10 5.06 12 65 1.01353e-26 3.05755e-07 8.32e-15 5.06 Equation solved. fsolve completed because the vector of function values is near zero as measured by the value of the function tolerance, and the problem appears regular as measured by the gradient.
par.initial_values=par.initial_values.^2;
par.initial_values
ans = 1x4
0.3089 0.5876 0.1031 0.0003
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
sum(par.initial_values)
ans = 1.0000
% Check if fsolve was successful
if exitflag <= 0
error('fsolve did not converge to a solution');
end
par.x0 = [par.F_feed ; par.x_H2_F ; par.x_N2_F ;par.x_NH3_F ;par.x_O2_F ;par.initial_values(1);par.initial_values(2); par.initial_values(3); par.initial_values(4) ];
par.tspan = 0:0.05:par.L_fiber;
par.M = [1 0 0 0 0 0 0 0 0 ; 0 1 0 0 0 0 0 0 0 ; 0 0 1 0 0 0 0 0 0 ; 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 1 0 0 0 0 ; 0 0 0 0 0 0 0 0 0 ; 0 0 0 0 0 0 0 0 0; 0 0 0 0 0 0 0 0 0 ;0 0 0 0 0 0 0 0 0];
par.options = odeset('Mass',par.M,'RelTol',1e-6,'AbsTol',1e-6*ones(9,1));
[par.Z, par.X] = ode15s(@(z,x) dae(z,x,par),par.tspan,par.x0, par.options);
Warning: Failure at t=7.224374e-01. Unable to meet integration tolerances without reducing the step size below the smallest value allowed (1.776357e-15) at time t.
plot(par.Z,par.X(:,2:end))
function out = dae(z,x,par)
out = [- 2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*((par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P)) + (par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P)) + (par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P)) + (par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P)))
1/x(1) *2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P) + x(2)*(- 2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*((par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P)) + (par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P)) + (par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P)) + (par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P))))
1/x(1) *2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P) + x(3)*(- 2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*((par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P)) + (par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P)) + (par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P)) + (par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P))))
1/x(1) *2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P) + x(4)*(- 2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*((par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P)) + (par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P)) + (par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P)) + (par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P))))
1/x(1) *2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P) + x(5)*(- 2*3.14*par.r_fiber*par.L_fiber*par.n_fiber*((par.Per_H2*(x(2)*par.P_f + x(6)*par.P_P)) + (par.Per_NH3*(x(4)*par.P_f + x(8)*par.P_P)) + (par.Per_N2*(x(3)*par.P_f + x(7)*par.P_P)) + (par.Per_O2*(x(5)*par.P_f + x(9)*par.P_P))))
x(6) - (par.Per_H2*x(2) * ((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_H2*((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) )))
x(7) - (par.Per_N2*x(3) * ((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_N2*((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) )))
x(8) - (par.Per_NH3*x(4) * ((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_NH3*((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) )))
x(9) - (par.Per_O2*x(5) * ((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) ) / (1-par.BETA + par.BETA*par.Per_O2*((x(6)/par.Per_H2) + (x(7)/par.Per_N2) + (x(8)/par.Per_NH3) + (x(9)/par.Per_O2) )))];
%x(1) = F
%x(2) = xH2
%x(3) = xN2
%x(4) = xHNH3
%x(5) = xO2
%x(6) = yH2
%x(7) = yN2
%x(8) = yNH3
%x(9) = yO2
end
function F = algebraic_constraints(x, par)
x=x.^2;
sum_terms = (x(1)/par.Per_H2) + (x(2)/par.Per_N2) + (x(3)/par.Per_NH3) + (x(4)/par.Per_O2);
F = [
x(1) - par.Per_H2*par.x_H2_F * sum_terms / (1-par.BETA + par.BETA*par.Per_H2*sum_terms)
x(2) - par.Per_N2*par.x_N2_F * sum_terms / (1-par.BETA + par.BETA*par.Per_N2*sum_terms)
x(3) - par.Per_NH3*par.x_NH3_F * sum_terms / (1-par.BETA + par.BETA*par.Per_NH3*sum_terms)
x(4) - par.Per_O2*par.x_O2_F * sum_terms / (1-par.BETA + par.BETA*par.Per_O2*sum_terms)
];
end
  6 Comments
Sachin kumar Ramayampet
Sachin kumar Ramayampet on 21 Jun 2024
Hi!
Thank you for sharing the reference. I have some other questions regarding the code. If you could answer then it would be a great help.
  1. While initializing the membrane parameters (see below ) you have used par.A_range and then par.A_module instead of taking 2 * pi * R * L * N (which is given in the reference paper). So would you please explain is their any particular reason for taking par.A_module in this way.
%% Assumptions membrane
par.A_range = 15; % [m2/(mol/s)]
par.A_module =par.A_range *par.F_feed; % effective area
par.l=4; %[m]
par.r=0.75e-3/2;
par.n = par.A_module/(2*3.14*par.r*par.l);
2. In the plot of "molar Fraction in permeate", the mole fraction of the NH3 is increasing over the length of fiber module over the other components eventhough the initial mole fraction of NH3 in feed as well as the permeance of NH3 are considerably low when compared with other components. Could you explain this behaviour? (I am asking this because I am not familiar with this Topic.)
3. If I am correct this code is for the cocurrent configuration right?
I hope you would clarify the above questions and Thank you in advance.

Sign in to comment.

More Answers (0)

Categories

Find more on Scan Parameter Ranges in Help Center and File Exchange

Products


Release

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!