% THE THERMODYNAMICS-BASED BLACK-BOX MODEL OF MICROBIAL REACTIONS AND MASS
% TRANSFER-BASED MODEL OF A LARGE-SCALE BUBBLE COLUMN BIOREACTOR FOR SYNGAS
% FERMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% By:
% Eduardo F. Almeida Benalcázar, de Ecuador pa'l mundo
% Henk Noorman
% Rubens Maciel Filho
% John A. Posada Duque

% year 2019

% This code simulates the fermentation of pure CO. 


function BC_CO

% This subroutine calls the optimization function to solve the systems of
% equations for a determined range of CO dissolved concentrations (CCO). 
% After all the CCO (or C_D) range is covered, results stored in matrix 
% 'FF', which is stored in a '.mat' file with a customizable name.
% The matrix FF is then used to estimate the C_D concentration profiles
% along the height of the liquid column. Two variables are obtained from
% this search, one that saves mean-log C_D where a threshold is reached at
% the top of the liquid column and a second variable which saves the mean
% -log C_D where inhibition has been reached at the bottom of the reactor
% where the C_D profile becomes distorted and often the 'fmincon' function
% fails to converge.
% Once the operation point has been found considering the location of the 
% threshold and the inhibition, it is used to calculate the process 
% energy requirements.


clear all
close all


global R Temp MWw MWet MWX pHo HT H Ptop Feed VR T Pmix Yet F_mlM qCO...
    kLa_CO vsGC P_ml CCOb CCOml CCOt DH Nmix L_et L_w L_mix MTC_CO...
    EG DG01_Cat_et_CO FL_out VL Pb Cet Rates CCO2ml CCO2b CCO2t K...
    Umax_CO_et YXCO_et mS_et_CO D_CO D_O2 HS qSmax KCO KI y exitflag2


% Input parameterss

Temp = 37 + 273.15;         % Temperature, K
Ptop = 1.5;                 % Top pressure, atm
Dil = 0;                    % gas dilution percentage, %
Cet_i = 45;                 % Maximum allowed ethanol concentration, g/L
H = 20;                     % Vessel height, m
K = 1.0;                      % Mass transfer coefficient multiplying factor
EG = 0.15;                  % Gas hold-up


pcv = [Temp, Ptop, Dil, Cet_i, H, K, EG];       % Vector saved with the input parameters
a = 'CO_0.mat';   % Name for FF matrix storage


% Other fixed & complementary parameters

CCO_max = 2;                % Maximum CO concentration for C_D range, mol/m^3
R = 0.008314;               % Ideal gas constant, kJ/mol/K, for Pa*m^3/mol/K multiply by 1000
MWw = 18.015;               % Water mol weight, g/mol
MWet = 46.069;              % Ethanol mol weight, g/mol
MWX = 25.25;                % Microbial biomass mol weight, g/mol
pHo = 5.5;                  % Extracellular pH
VR = 700;                       % Reactor total volume, m^3
T = (VR*4/(3.1416*H))^(1/2);    % Reactor diameter, m
HT = H/T;                       % reactor asepct ratio
Feed = [100 - Dil, 0.00001, 0.00001, Dil]./100; % Composition of gas feed, % mol: [y_CO, y_H2, y_CO2, y_Dilution]
VL = VR*0.8*(1 - EG);       % Volume of liquid in bioreactor, m^3
g = 9.8;                    % Gravity's acceleration
dens = 1000;                % fermentation broth density, kg/m^3


% Tank dimensions

Hmix = 0.8*H;                       % Height of gas-liquid coçlumn, m
AT = 3.1416*T^2/4;                  % reactor cross-sectional area, m^2
Pb = Ptop + 9800*Hmix/101325;       % Bottom pressure, atm
P_ml = (Pb - Ptop)/log(Pb/Ptop);    % Mean log pressure, atm


% Estimation of ethanol-water Vapor-Liquid Equilibria data as function of temperature

YY = NRTL_VLE(Temp);


% Kinetic parameters

KI = 0.1;           % Inhibition constant, mM
KCO = 0.005;        % Half saturation constant, mM


% Latent heats of vaporization, kJ/mol

C = [5.21E7,    0.3199, -0.212, 0.25795,    647.13;
    5.69E7,     0.3359, 0,  	0,          513.92];

L_w = C(1,1)*(1 - Temp/C(1,5))^(C(1,2) + C(1,3)*Temp/C(1,5) + C(1,4)*(Temp/C(1,5))^2);   % For water, J/kmol
L_w = L_w/1e6;          % kJ/mol

L_et = C(2,1)*(1 - Temp/C(2,5))^(C(2,2) + C(2,3)*Temp/C(2,5) + C(2,4)*(Temp/C(2,5))^2);  % For ethanol, J/kmol
L_et = L_et/1e6;        % kJ/mol


% Gas diffusivities in pure water, cm^2/s

MV_O2 = 25.6;
MV_CO = 30.7;

D_O2 = 0.000000074*(2.6*MWw)^0.5*(Temp)/0.7/MV_O2^0.6;
D_CO = 0.000000074*(2.6*MWw)^0.5*(Temp)/0.7/MV_CO^0.6;


% Henry's coefficients

[H_CO, H_H2, H_CO2] = Henry;
HS = [H_CO, H_H2, H_CO2];


% Empty vectors for results storage

FF = [];            % Reactor localized data
cco = [];           % CO concentration range


% Extra auxiliary variables

w = 0;              % Indicator of iteration number
hh = 1;             % Loop breaker initializer


% Successful initial guesses

%       C_x,    F_in,       F_out,      Y_CO_out,   Y_CO2_out,  Cet,        FL_out
x0 = [  10      798.1412    769.9998    0.859       0.11352     60/MWet     0.0012];
% The model unknowns are:
% C_x: biomass concentration (Cmol_x/m^3)
% F_in: Gas inflow rate (mol/s)
% F_out: Gas outflow rate (mol/s)
% Y_CO_out: CO mol fraction in offgas (-)
% Y_CO2_out: CO2 mol fraction in offgas (-)
% FL_out: Liquid volumetric outflow rate (m^3/s)

% Iteration loop, solves bioreactor operation at 400 different values
% of C_D

for CCO = logspace(log10(CCO_max),log10(1e-5),400)
    
    
    % Lower and upper bounds
    
    lb = [1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 0.1/MWet, 0];
    ub = [100000, 10000, 10000, Feed(1), 1, Cet_i/MWet, 3];
    
    
    % Two sets of options, one for each optimization method. sqp is used to
    % stabilize value, although sometimes it does not converge.
    % Interior-point is used to take sqp off from 'stubborn' answer, sort
    % of like shaking the table a bit so the little balls fall into the
    % holes.
    
    options1 = optimset('Display','off',...
        'Algorithm','sqp','ScaleProblem','obj-and-constr');
    
    options2 = optimset('Display','off',...
        'Algorithm','interior-point','ScaleProblem','obj-and-constr',...
        'TolCon',1e-10); %
    
    
    % First optimization, if this one fails, then optimizations in
    % series will try to stabilize the solution using the two
    % aforementioned optimization algorithms
    
    [f,fval,exitflag] = fmincon(@(x)...
        solving(x,KI,KCO,AT,Pb,CCO,YY),...
        x0,[],[],[],[],lb,ub,@(x) mycon2(x,CCO),options1); x0 = f;
    
    
    % Loop with a maximum of 10 sets of shake-and-point optimizations. Used
    % to help convergence.
    
    while exitflag == -2
        
        [f] = fmincon(@(x)...
            solving(x,KI,KCO,AT,Pb,CCO,YY),...
            x0,[],[],[],[],lb,ub,@(x) mycon2(x,CCO),options2); x0 = f;
        
        [f,fval,exitflag] = fmincon(@(x)...
            solving(x,KI,KCO,AT,Pb,CCO,YY),...
            x0,[],[],[],[],lb,ub,@(x) mycon2(x,CCO),options1); x0 = f;
        
        
        % Controller for excessively difficult results, after 2 sets of
        % optimizations, loop is broken.
        
        hh = hh + 1;
        
        if hh == 2     % Maximum number of optimizations in series
            break
        end
        
    end
    
    
    % Data storage. A condition is used to store only data that comes
    % derived from successfully solved optimizations.
    
    if exitflag == 1 
        
        
        % Definition of other variables to store
        
        CO_cons = (f(2)*Feed(1) - f(3)*f(4))*100/(f(2)*Feed(1));    % Gas utilization, %
        Pro_et = f(1)*Rates(4)/3600;                                % Ethanol volumetric productivity, mol/m^3/s
        et_l = Cet*1000*FL_out/(f(1)*Rates(4)*VL/3600);             % Portion of ethanol produced that leaves the bioreactor along the liquid phase, dimensionless
        et_g = Yet*Pmix*f(3)/(Ptop*f(1)*Rates(4)*VL/3600);          % Portion of ethanol produced that leaves the bioreactor along the gas phase, dimensionless
        CO_used = kLa_CO*(CCOml - CCO)*VL;                          % CO consumed, mol/s
        CO_fed = f(2)*Feed(1);                                      % CO fed, mol/s
        CO_out = f(3)*f(4);                                         % CO unconsumed, mol/s
        CO2_pro = f(1)*Rates(8)*VL/3600;                            % CO2 produced, mol/s
        
        
        % Variables storage
        
        FF = [FF;
            f,...           % 1 - 7: Model's solved unknowns, see line 137
            Pro_et,...      % 8: Ethanol productivity, mol/m^3/s
            et_l,...        % 9: Fraction of ethanol through the liquid, mol/mol
            et_g,...        % 10: Fraction of ethanol through the gas, mol/mol
            CO_cons,...     % 11: CO consumption, %
            CO_used,...     % 12: CO used, mol/s
            CO_fed,...      % 13: CO fed to system, mol/s
            CO_out,...      % 14: CO Un-used, mol/s
            CO2_pro,...     % 15: CO2 produced, mol/s
            Rates(7),...    % 16: Biomass growth rate, h^-1
            Rates(1),...    % 17: CO consumption rate, mol_CO/molX/h
            Rates(8),...    % 18: CO2 production rate, mol_CO2/molX/h
            F_mlM,...       % 19: Mean log gas flow rate, mol/s
            qCO,...         % 20: Specific CO uptake rate, mol_CO/Cmol_X/h
            kLa_CO,...      % 21: CO kLa, 1/s
            vsGC,...        % 22: Superficial gas velocity, P corrected, m/s
            P_ml,...        % 23: Mean log pressure, atm
            Pb,...          % 24: Bottom pressure, atm
            CCOb,...        % 25: Saturation C_CO @ reactor bottom, m^3/s
            CCOml,...       % 26: Saturation C_CO @ mean log pressure, m^3/s
            CCOt,...        % 27: Saturation C_CO @ reactor top, m^3/s
            CCO2b,...       % 28: Saturation C_CO2 @ reactor bottom, m^3/s
            CCO2ml,...      % 29: Saturation C_CO2 @ mean log pressure, m^3/s
            CCO2t,...       % 30: Saturation C_CO2 @ reactor top, m^3/s
            MTC_CO,...      % 31: CO mass transfer capacity, mol/m^3/s
            DH,...          % 32: Enthalpy of reaction, kJ/mol_e-donor
            Nmix,...        % 33: Water-ethanol rate of evaporation, mol/s
            Pmix,...        % 34: Ethanol/water mix partial pressure, atm
            Yet,...         % 35: Ethanol fraction in water/ethanol vapor mix, mol/mol
            L_mix,...       % 36: Latent heat of etOH/water mix, kJ/mol
            DG01_Cat_et_CO,...  % 37: Gibbs free energy change in catabolic reaction @ physiological conditions, kJ/mol_{e-donor}
            Umax_CO_et,...  % 38: U_max according to qS_max
            YXCO_et...      % 39: Biomass yield, Cmol_x/mol_{carbon source}
            mS_et_CO,...    % 40: Maintenance coefficient, mol_D/Cmol_x/h
            Rates(9)];      % 41: Specific rate of water consumption, mol_water/Cmol_x/h
        
        cco = [cco CCO];
        save(a,'FF','cco','pcv');
        x0 = f;     % Optimization for the next CCO value takes this solution as initial guess. Improves convergence stability
        
    end
    
    
    w = w + 1;      % Iteration counter
    hh = 1;         % Optimization loop reset
    
    
    % Display message
    
    di = [' Iteration: ',num2str(w),'; exitflag: ',num2str(exitflag)];
    disp(di)
        
end


%% Gas concentration profiles


thres = size(cco,2);    % value used if no threshold were found 
inh = size(cco,2);      % Value used if no inhibition were found


% Variable 'nnn' helps to pass from the saving of 'thres' to the
% saving of 'inh' variable

nnn = 1;

% Searching for thresholds at reactor top for each element in CCO
% vector. iii represents each location in vector CCO. iii starts from
% the end of CCO vector, where CCO is smallest, so a threhold is found
% first and the iteration ends where the inhibition is found i.e.,
% when solving CCO profile meets a large deviation at the
% bottom of the fermentor and the algorithm fails (exitflag = -2).

for iii = 1:size(cco,2)
    
    
    % Interpolation of parameters from stored matrix FF
    
    Ced_d = cco(end - iii + 1);                         % Mean log C_D, mol/m^3
    Pmix = interp1(cco,FF(:,34),Ced_d,'pchip')*101325;  % Partial pressure of ethanol-water mix, Pa
    Fin = interp1(cco,FF(:,2),Ced_d,'pchip')/(1 - Pmix/(Pb*101325)); % Gas inflow rate, mol/s 
    yCO_i = Feed(1);                                    % CO mol fraction at reactor inlet
    cet = interp1(cco,FF(:,6),Ced_d,'pchip');           % Ethanol concentration in the liquid, mol/L
    xx = interp1(cco,FF(:,1),Ced_d,'pchip');            % Biomass concentration, mol/m^3
    cco2t = interp1(cco,FF(:,30),Ced_d,'pchip');        % CO2 concentration @ top of bioreactor, mol/m^3
    
    
    % Discretization of height and hydrostatic pressure
    
    nn = 9;    % Number of points in the y-axis discretization
    HH = Hmix.*(1 - linspace(0,1,nn + 1));      % Discretized height, m
    PP = Ptop*101325 + g.*dens.*HH;             % Discretized pressure, Pa
    
    
    % Solving of concentration profiles by correcting variable F_in for 
    % mean log C_CO to fit with the top and bottom C_CO values.
    % The corrected value of F_in is not used for further calculations as 
    % it deviates by 3.5% from the un-corrected value. To check this, take
    % the corrected value from variable 'yyy'.
    
    opt3 = optimoptions(@fmincon,'Display','off',...
        'Algorithm','sqp');
    x0 = Fin;                       % Initial guess for gas inflow rate
    x00 = 0.0000001.*ones(nn,1);    % Initial guess for C_CO profile, mM
    w = 1;                          % Variable 'w' is used within the calculation of C_CO profile to improve convergence
    
    yyy = fmincon(@(x) iterat_CO(x,Ced_d,nn,HH,PP,yCO_i,Pb,Pmix,AT,xx,K,x00,w),...
        x0,[],[],[],[],1e-20,[],@(x) consFin(x,nn,Ced_d),opt3);
    
    
    % Estimation of DG_cat at the top of fermentor to check if threshold
    % was reached
    
    dgcat = Cat_CO(y(nn)/HS(1),cco2t/HS(3),cet);
    
    
    % Is DG_cat threshold?
    
    if dgcat(1) < -15
        if nnn < 2
            % thres takes the value of the coordinate where the threshold concentration is found
            thres = size(cco,2) - iii + 1;
            nnn = nnn + 1;
        else
            if exitflag2 == -2
                inh = size(cco,2) - iii + 1;
                break
            end
        end
    end
    
end


%% Selection of operation points for CO fermentation

% Data for formulating criteria

Cet = FF(:,6);              % Ethanol oncentration, mol/L
Rates_ed = FF(:,17);        % CO specific uptake rate, mol_CO/molX/h
qD = Rates_ed./-qSmax;      % Non-domensional CO specific uptake rate


% Where does Cet attain the maximum?

if isempty(find(Cet == Cet_i/MWet)) == 0
    limCet = find(Cet == Cet_i/MWet,1);
else
    limCet = 0;
end


% Find the very low qD = 0.1

if isempty(find(qD > 0.1,1)) == 0
    limqD = size(cco,2) - find(flipud(qD) > 0.1,1);
else
    limqD = 0;
end


crit = [limCet, thres, limqD, inh]; % Vector with the summary of criteria


% Selection of operation point

if crit(2) == max(crit)
    op = max([crit(1), crit(3)]);
else
    op = crit(2);
end


% Segregating FF data for operation point

FF_op = FF(op,:);


% Load relevant data from FF_op vector

F_in = FF_op(2);            % Gas inflow rate, mol/s
F_out = FF_op(3);           % Gas outflow rate, mol/s
Y_ed_out = FF_op(4);        % CO mol fraction in offgas
Y_CO2_out = FF_op(5);       % CO2 mol fraction in offgas
Cet = FF_op(6);             % Ethanol concentration, mol/L
FL_out = FF_op(7);          % Liquid outflow rate, m^3/s
Pro_et = FF_op(8);          % Ethanol volumetric productivity, mol/m^3/s
et_l = FF_op(9);            % Fraction of ethanol through the liquid, mol/mol
et_g = FF_op(10);           % Fraction of ethanol through the gas, mol/mol
ed_cons = FF_op(11);        % CO utilization per pass through bioreactor, %
qCO = FF_op(20);            % Specific CO uptake rate, mol_CO/Cmol_x/h
Pb = FF_op(24);             % Bottom pressure, atm
Pmix = FF_op(34);           % Ethanol/water mix partial pressure, atm
Yet = FF_op(35);            % Ethanol fraction in Water/ethanol vapor mix, mol/mol


%% ENERGY BALANCES

% Inflow compression power

gama_i = 1.4;                                           % Heat capacity ratio for gas feed
V_1 = F_in.*(ed_cons./100).*R.*1000.*Temp./(101325);    % Volumetric gas inflow rate, m^3/s (takes only the amount of gas needed considering the offgas recycle)
P_comp_i = ((gama_i./(gama_i - 1)).*(101325).*V_1.*((Pb/1).^((gama_i - 1)./gama_i) - 1))./(0.7.*1e3);   % kW
P_comp_i1 = P_comp_i./(MWet.*Pro_et.*VL);               % Specific power requirement, MJ/kg_ethanol


% Outflow compression power

gama_o = 1.4.*Y_ed_out + 1.300.*Y_CO2_out + 1.13.*(Yet.*Pmix./Ptop) + 1.330.*((1 - Yet).*Pmix./Ptop);   % Heat capacity ratio for offgas
V_out = F_out.*R.*1000.*Temp./(Ptop.*101325);   % Volumetric gas inflow rate, m^3/s
P_comp = ((gama_o./(gama_o - 1)).*(Ptop*101325).*V_out.*((Pb/Ptop).^((gama_o - 1)./gama_o) - 1))./(0.7.*1e3);   % kW
P_comp_1 = P_comp./(MWet.*Pro_et.*VL);          % Specific power requirement, MJ/kg_ethanol


% Water/ethanol condensation from offgas

T_c = 273.15 - 6;   % Condensation temperature, K
L_w = C(1,1)*(1 - T_c/C(1,5))^(C(1,2) + C(1,3)*T_c/C(1,5) + C(1,4)*(T_c/C(1,5))^2);   % J/kmol
L_w = L_w/1e6;
L_et = C(2,1)*(1 - T_c/C(2,5))^(C(2,2) + C(2,3)*T_c/C(2,5) + C(2,4)*(T_c/C(2,5))^2);  % J/kmol
L_et = L_et/1e6;
L_cond = L_w.*(1 - Yet) + L_et.*Yet;    % Latent heat of water/ethanol mixture condensation, J/kmol

P_cond = L_cond.*F_out.*(Pmix./Ptop).*0.21;     % kW
P_cond_1 = P_cond./(MWet.*Pro_et.*VL);          % Specific power requirement, MJ/kg_ethanol


% Product distillation, kW

Xw_g = Yet.*MWet./(Yet.*MWet + (1 - Yet).*MWw);     % Conversion from mol fractions to mass fractions
Xw_l = Cet.*MWet./1000;
P_dis_g = 22.194.*(Xw_g.*100).^(-0.794).*et_g;      % Specific power requirement for condensed vapors distillation, MJ/kg_ethanol
P_dis_l = 22.194.*(Xw_l.*100).^(-0.794).*et_l;      % Specific power requirement for fermentation broth distillation, MJ/kg_ethanol


% Total power requirements

PT = P_comp_i1 + P_comp_1 + P_cond_1 + P_dis_g + P_dis_l;   % Total electric energy, MJ/kg_et


% Display of final message

di1 = ['Ethanol volumetric productivity: ',num2str(Pro_et*MWet*3.6),' g/(L*h)'];
di2 = ['Gas utlization: ',num2str(ed_cons),' %'];
di3 = ['Total power requirements: ',num2str(PT),' MJ/kg_et'];
disp(di1)
disp(di2)
disp(di3)


end


%% Makes the concentration profile match with the mean log C_CO by
% adjusting the value of F_in

function yyy = iterat_CO(x,Ced_d,nn,HH,PP,yCO_i,Pb,Pmix,AT,xx,K,x00,w)

global y exitflag2

F_i = x;

opt = optimoptions(@fmincon,'Display','off','Algorithm','sqp','TolCon',1e-4);


% Condition put to improve the convergence and solving time by making x0 
% to take the last solved concentration profile

if w == 1
    x0 = x00;
else
    x0 = y;
end

lb = ones(size(x0)).*1e-20;     % Avoids concentrations getting negative values

[y,fval,exitflag2] = fmincon(@(x)...
    pro_CO(x),x0,[],[],[],[],lb,[],...
    @(x) cons(x,nn,HH,PP,F_i,yCO_i,Pb,Pmix,AT,xx,K),opt);

yyy = abs((y(1) - y(nn))/log(y(1)/y(nn)) - Ced_d);  % Does mean-log C_D agree with top and bottom C_D?

% Variable used to improve convergence by making the first result of 
% C_D profile to be used as the initial guess for the next mean-log C_D 
% point from CCO vector 
w = w + 1;  

end


%% Solving the concentration profiles

function f = pro_CO(x)

% Minimizes the first value of C_D. It is just a trick to use fmincon as
% a solver for the system of non-linear equations. fmincon brings the 
% advantage of constaining the solutions to positive values

f = x(1);   

end


%% Constraints for F_in correction

function [c,ceq] = consFin(x,nn,Ced_d)

global y

c = [];
ceq = (y(1) - y(nn))/log(y(1)/y(nn)) - Ced_d; % Does mean-log C_D agree with top and bottom C_D? here used as non-linear equality

end


%% Constraints for finding concentration profiles. Mass balances.

function [c,ceq] = cons(x,nn,HH,PP,F_i,yCO_i,Pb,Pmix,AT,xx,K)

global R Temp qSmax KCO KI HS D_CO D_O2

% Construction of the mass balance equations at the different compartments

c = [];
ceq = zeros(size(x));

for i = 1:nn
        
    % Calculation of mean-log gas flow rates in the discretized y-axis
    
    if i == 1
        
        % Equations for first point in 'nn' (initial conditions) @ reactor
        % bottom
        
        pml = (PP(i + 1) - PP(i))/log(PP(i + 1)/PP(i)); % Mean log pressure for mass transfer calculations
        fml = F_i;                                  % Gas flow rate, mol/s
        FCO = fml*yCO_i*(1 - Pmix/(Pb*101325));     % CO gas flow rate, mol/s
        FCO2 = 0;                                   % CO2 gas flow rate, mol/s
        
    else
        
        % Equations for rest of the column
        
        pml = (PP(i + 1) - PP(i))/log(PP(i + 1)/PP(i));
        FCO = FCO - MTC_CO/3600;
        FCO2 = FCO2 + RCO2/3600;
        fml = abs((FCO + FCO2)./(1 - Pmix/pml));
        
    end
    
    VL = AT*(HH(i) - HH(i + 1));            % Volume of liquid phase, m^3
    Vml = fml*R*1000*Temp/pml;              % Volumetric gas flow rate, m^3/s
    V0ml = Vml*pml*273.15/(Temp*101325);    % Volumetric gas flow rate @ standard conditions, m^3/s 
    vsG0 = V0ml/AT;                         % superficial gas velocity @ standard conditions, m/s 
    vsGC = vsG0*101325*log(PP(i + 1)/PP(i))/(PP(i + 1) - PP(i));    % Pressure-corrected superficial gas velocity, m/s
    
    kLa_CO = K*(0.32.*vsGC.^0.7).*(1.022.^(Temp - 293.15)).*(D_CO./D_O2)*3600;  % CO mass tranfer coeffcient, s^-1
    
    CCO_s = (pml/101325)*(HS(1))*(FCO/fml);         % CO saturation concentration, mol/m^3 
   
    MTC_CO = kLa_CO*(CCO_s - x(i))*VL;              % CO mass tranfer rate, mol/h
    
    qCO = -qSmax*x(i)/(KCO + x(i) + x(i)^2./KI);    % Specific CO uptake rate, mol/Cmol_x/h 
    qCO2 = -qCO*2/3;                                % Specific CO2 production rate, mol/Cmol_x/h 
    
    RCO = qCO*xx*VL;        % CO consumption rate by bacteria, mol/h
    RCO2 = qCO2*xx*VL;      % CO2 production rate by bacteria, mol/h
        
    ceq(i) = MTC_CO + RCO;        % Overall CO mass balance per each compartment
    
    
end

end


%% Mass transfer-based model of the large-scale syngas fermentor

function f = solving(x,KI,KCO,AT,Pb,CCO,YY)

% This is the function in which the mass balances around the fermentor are
% defined. It mixes mass transfer with the thermodynamic model of bacteria.


global R Temp MWet Ptop Feed Rates Pmix kLa_CO CCOml Yet EG MWw qCO vsGC...
    CCOb CCOt DH Nmix L_et L_w L_mix MTC_CO Cet F_mlM CCO2ml CCO2b CCO2t...
    VL FL_out K PCO PH2 PCO2 D_CO D_O2 HS qSmax  F_mlV


% Collection of unknowns (decision variables)

X = x(1);           % Biomass concentration, mol/m^3
F_in = x(2);        % Gas inflow rate, mol/s
F_out = x(3);       % Gas outflow rate, mol/s
Y_CO_out = x(4);    % CO mol fraction in offgas, mol/mol
Y_CO2_out = x(5);   % CO2 mol fraction in offgas, mol/mol
Cet = x(6);         % Ethanol concentration in liquid phase, mol/L
FL_out = x(7);      % Liquid outflow rate, m^3/s


% Interpolation of VLE data from YY matrix

Xet = Cet*MWet/1000;                                % Conversion of Cet, from mol/L to x w/w
Xet = Xet*MWw/(MWet + Xet*(MWw - MWet));            % X ethanol, mol/mol
Yet = interp1(YY(:,1),YY(:,2),Xet,'pchip');         % Mixture partial pressure, atm
Pmix = interp1(YY(:,1),YY(:,3),Xet,'pchip')/101.325;        % Y ethanol in vapor mixture, mol/mol


% Mean log mixing and mass transfer properties

vsGC = (EG/0.6)^(1/0.7);                            % Pressure corrected superficial gas velocity, m/s
vsG0 = vsGC/(log((Pb/Ptop))/(Pb - Ptop));           % Superficial gas velocity @ std conditions, m/s
F_mlV0 = vsG0*AT;                                   % Volumetric sas flow rate @ std conditions, m^3/s
Pml = (Pb - Ptop)/log(Pb/Ptop);                     % Mean log pressure, atm
F_mlV = F_mlV0*101325*Temp/(Pml*273.15*101325);     % Mean log volumetric gas flow rate @ process conditions, m^3/s
F_mlM = F_mlV*Pml*101325/(R*1000*Temp);             % Mean log gas mol flow rate @ process conditions, mol/s
Nmix = Pmix*x(3)/Ptop;                              % Ethanol/water mixture evaporated, mol/s
L_mix = 7.27495*(Cet*MWet/1000 + 0.010617)*L_et +...
    (1 - 7.27495*(Cet*MWet/1000 + 0.010617))*L_w;       % Latent heat of etOH/water mix


% Partial pressures @ bottom of reactor, excluding water-ethanol partial
% pressures

PCO = (Pb - Pmix)*Feed(1);
PH2 = (Pb - Pmix)*Feed(2);
PCO2 = (Pb - Pmix)*Feed(3);


% Partial pressures @ top of reactor

PCOt = Ptop*x(4);
PCO2t = Ptop*x(5);


% CO and CO2 saturation concentrations in pure water, mol/m^3

CCOt = PCOt*HS(1);
CCOb = Feed(1)*Pb*HS(1);
CCOml = (CCOb - CCOt)/log(CCOb/CCOt);

CCO2t = PCO2t*HS(3);
CCO2b = Feed(3)*Pb*HS(3);
CCO2ml = (CCO2b - CCO2t)/log(CCO2b/CCO2t);


% Mass transfer coefficient, 1/s

kLa_O2_20 = K*0.32*vsGC^0.7;
kLa_O2 = kLa_O2_20*1.022^(Temp - 293.15);
kLa_CO = kLa_O2*D_CO/D_O2;
MTC_CO = kLa_CO*(CCOml - CCO); % CO MTC, mol/m^3/s


% Retrival of microbial reaction rates from function 'micro'

CCO2 = CCO2ml;
CH2 = 1e-7;         % Setting H2 concentration very low
YYY = micro(CCO/HS(1),CH2/HS(2),CCO2/HS(3),Cet);
Met = YYY(1,:);
qSmax = YYY(3,3);


% Specific rates of reaction

qCO = -qSmax.*(CCO./(KCO + CCO + CCO.^2./KI));
Rates = qCO.*Met./(Met(1));                         % Rates, mol_i/Cmol_X/h


% Heat of reaction

DH_st = Met(13)/-Met(1);                               % Entalphy of reaction, kJ/mol_e-donor
dT = [Temp,25 + 273.15];
Cps = cp(dT);               % Cps = [Cp_CO,Cp_H2,Cp_etl,Cp_X,Cp_CO2,Cp_wl];
DH = DH_st + Cps(1)*Met(1)/Met(1) + Cps(2)*Met(2)/Met(1) +...
    Cps(3)*Met(4)/Met(1) + Cps(4)*Met(7)/Met(1) +...
    Cps(5)*Met(8)/Met(1) + Cps(6)*Met(9)/Met(1);


% Objective function: maximize productivity

f = Cet*1000*FL_out/(x(1)*Rates(4)*VL/3600); 

end


%% Optimization Constraints

function [c,ceq] = mycon2(x,CCO)

% This function defines the constraints for the optimization.
% All equations are derived from mass balances


global Rates Pmix kLa_CO CCOml Yet VL Ptop...
    Feed F_mlM Pb CCO2ml FL_out Cet

c(1) = - FL_out;                                % Liquid outflow rate is possitive
c(2) = (Rates(7)/3600)*VL - FL_out;             % Cells production rate does not surpass liquid outflow's capacity to remove them 

ceq(1) = kLa_CO*(CCOml - CCO) + Rates(1)*x(1)/3600;     % CO balance @ liquid
ceq(2) = x(2)*Feed(1) - x(3)*x(4)...
    - kLa_CO*(CCOml - CCO)*VL;                          % CO balance @ gas
ceq(3) = x(1)*Rates(8)*VL/3600 - ...
    x(3)*x(5) - FL_out*CCO2ml;                          % CO2 balance @ both phases
ceq(4) = x(1)*Rates(4)*VL/3600 - ...
    Yet*Pmix*x(3)/Ptop - (Cet*1000)*FL_out;             % Ethanol balance @ both phases
ceq(5) = 1 - x(4) - x(5) - Pmix/Ptop...
    - Feed(4)*x(2)/x(3);                                % Gas mol fractions summation at the gas exit
ceq(6) = F_mlM - abs((x(3) - x(2)/(1 - Pmix/Pb)))/...
    abs(log(x(3)/(x(2)/(1 - Pmix/Pb))));                % Mean log gas flow rate constraint


end


%% Heat capacities

function [Cps] = cp(dT)

% Calculates heat capacities of substances involved in metabolic reaction

T1 = dT(1);
T2 = dT(2);


% Constants

%       etOH_l         w_l          etOH_g
C1 = [1.0264e5,     2.7637e5,       0.492e5];
C2 = [-1.3963e2,    -2.0901e3,      1.4577e5];
C3 = [-3.0341e-2,   8.1250e0,       1.6628e3];
C4 = [2.0386e-3,    -1.4116e-2,     0.9390e5];
C5 = [0,            9.3701e-6,      744.7];


% Gases Cp
% From Perry's handbook

Cp_H2 = (6.62 + 0.00081*T2 +...
    6.62 + 0.00081*T1)*(4.184e-3)/2;                                    % kJ/K/mol
Cp_CO2 = (10.34 + 0.00274.*T2 - 195500/T2.^2 + ...
    10.34 + 0.00274.*T1 - 195500/T1.^2)*(4.184e-3)/2;                   % kJ/K/mol
Cp_CO = (6.60 + 0.0012*T2 +...
    6.60 + 0.0012*T1)*(4.184e-3)/2;                                     % kJ/K/mol
Cp_etl = (C1(1) + C2(1)*T2 + C3(1)*T2^2 + C4(1)*T2^3 + C5(1)*T2^4 +...
    C1(1) + C2(1)*T1 + C3(1)*T1^2 + C4(1)*T1^3 + C5(1)*T1^4)/(1e6*2);   % kJ/K/mol
Cp_wl = (C1(2) + C2(2)*T2 + C3(2)*T2^2 + C4(2)*T2^3 + C5(2)*T2^4 +...
    C1(2) + C2(2)*T1 + C3(2)*T1^2 + C4(2)*T1^3 + C5(2)*T1^4)/(1e6*2);   % kJ/K/mol
Cp_X = 1.301;               % kJ/K/Cmol, from Battley et al 1997

Cps = [Cp_CO,Cp_H2,Cp_etl,Cp_X,Cp_CO2,Cp_wl];

end


%% Henry's constants

function [H_CO, H_H2, H_CO2] = Henry

% Calculates Henry's constants as a fucntion of Temperature

global Temp

H_CO = 9.5E-4*exp(1300*(1/Temp - 1/298.15))*1000;   % mol/m3/atm
H_H2 = 7.8E-4*exp(500*(1/Temp - 1/298.15))*1000;    % mol/m3/atm
H_CO2 = 3.4E-2*exp(2400*(1/Temp - 1/298.15))*1000;  % mol/m3/atm

end



%% Thermodynamics-based black-box model of bacterial reactions

function y = micro(PCO,PH2,PCO2,Cet)

% This function defines the stoichiometry of metabolic reactions. Also
% defines maximum substrate uptake rates. The calculation is based on the
% DH at physiological conditions.
% This function is called by the mass transfer model being optimized


global R Temp DG01_Cat_et_CO Umax_CO_et YXCO_et mS_et_CO


pHi = 7;                        % Intracellular pH
e_cap = 3;                      % Electron uptake capacity, e-mol/C-molX/h
Ea = -69000;                    % Energy of activation


%% STOICHIOMETRY
% The stoichiometry of reactions follows the same order of substances as 
% the rows in matrix S in function 'stoich'; see below.
% The definition of stochiometries starts by defining the equations for the
% electron donor and the electron acceptor. From those, electrons are
% balanced and one final equation is defined which contains the electron 
% donor and the acceptor. 
% The equations undergo an automatic balancing of Oxygen, Hydrogen and 
% Charge, which is excecuted by function 'stoich'; see below 


% Catabolism

D_et_CO = [-1 0 0 0 0 0 0 1];   % Stoichiometry of electron donor equation for ethanol production from CO
X = D_et_CO; Y = stoich(X,Temp); D_et_CO = Y;

A_et_CO = [-1 0 0 0.5 0 0 0 0]; % Stoichiometry of electron acceptor equation for ethanol production from CO
X = A_et_CO; Y = stoich(X,Temp); A_et_CO = Y;

Cat_et_CO = (D_et_CO(1:11)*A_et_CO(11) - A_et_CO(1:11)*D_et_CO(11))/(A_et_CO(11) - D_et_CO(11)); % Stoichiometry of catabolic equation for ethanol production from CO
X = Cat_et_CO(1:8); Y = stoich(X,Temp); Cat_et_CO = Y;


% Anabolism

D_X_CO = [-1 0 0 0 0 0 0 1];        % Stoichiometry of electron donor equation for anabolism from CO
X = D_X_CO; Y = stoich(X,Temp); D_X_CO = Y;

A_X_CO = [-1 0 -0.25 0 0 0 1 0];    % Stoichiometry of electron acceptor equation for anabolism from CO
X = A_X_CO; Y = stoich(X,Temp); A_X_CO = Y;

An_CO = (D_X_CO(1:11)*A_X_CO(11) - A_X_CO(1:11)*D_X_CO(11))/(A_X_CO(11) - D_X_CO(11));
An_CO = An_CO/An_CO(7);             % Stoichiometry of anabolic equation for ethanol production from CO

X = An_CO(1:8); Y = stoich(X,Temp); An_CO = Y;


%% ENERGETICS OF CATABOLISM & ANABOLISM


DG01_Cat_et_CO = Cat_et_CO(end) + R.*Temp.*(Cat_et_CO(1).*log(PCO) + Cat_et_CO(2).*log(PH2) + Cat_et_CO(3)*log(0.1)...
    + Cat_et_CO(4)*log(Cet) + Cat_et_CO(8).*log(PCO2) + Cat_et_CO(10)*log(10^-pHi)); % kJ/Cmol_x


% Energy dissipation in anabolism

DG_Dis_CO = 200 + 18*(6 - 1)^(1.8) + exp(((3.8 - 2)^2)^0.16*(3.6 + 0.4*1)); % kJ/Cmol_x


% Biomass yield

YXCO_et = 1./(DG_Dis_CO/-DG01_Cat_et_CO + 4/2); % Cmol_x/mol_CS


% Metabolic reaction from CO to ethanol

Met_et_CO = An_CO(1:8)*4/(2*-An_CO(1)) - Cat_et_CO(1:8)*DG_Dis_CO/DG01_Cat_et_CO;    % mol/C-molX
X = Met_et_CO; Y = stoich(X,Temp); Met_et_CO = Y;


% Maintenance coefficient

mS_et_CO = 4.5*exp(-69000/(R*1000)*(1/Temp - 1/298.15))./DG01_Cat_et_CO;    % mol_CO/Cmol_x/h


% q_S^max & U^max

ETC = e_cap*exp(Ea/(R*1000)*(1/Temp - 1/298.15));      % e-mol/C-molX/h
qSmax_CO = ETC/2;
Umax_CO_et = (qSmax_CO + mS_et_CO).*YXCO_et;


% Results export

y = zeros(3,size(Met_et_CO,2));
y(1,:) = Met_et_CO;
y(3,3) = qSmax_CO;

end


%% Thermodynamics-based black-box model of bacterial reactions

function y = Cat_CO(PCO,PCO2,Cet)

global R Temp


pHi = 7;    % Intracellular pH


% The stoichiometry of reactions follows the same order of substances as 
% the rows in matrix S in function 'stoich'; see below.

D_et_CO = [-1 0 0 0 0 0 0 1];   % Stoichiometry of electron donor equation for ethanol production from CO
X = D_et_CO; Y = stoich(X,Temp); D_et_CO = Y;

A_et_CO = [-1 0 0 0.5 0 0 0 0]; % Stochiometry of electron acceptor equation for ethanol production from CO
X = A_et_CO; Y = stoich(X,Temp); A_et_CO = Y;

Cat_et_CO = (D_et_CO(1:11)*A_et_CO(11) - A_et_CO(1:11)*D_et_CO(11))/(A_et_CO(11) - D_et_CO(11)); % Stoichiometry of catabolic equation for ethanol production from CO
X = Cat_et_CO(1:8); Y = stoich(X,Temp); Cat_et_CO = Y;


DG01_Cat_et_CO = Cat_et_CO(end) + R.*Temp.*(Cat_et_CO(1).*log(PCO) + Cat_et_CO(3)*log(0.1)...
    + Cat_et_CO(4)*log(Cet) + Cat_et_CO(8).*log(PCO2) ...
    + Cat_et_CO(10)*log(10^-pHi));  % kJ/mol_CS


y(:,1) = DG01_Cat_et_CO;            % kJ/mol_CS
y(:,2) = DG01_Cat_et_CO.*-Cat_et_CO(1)./Cat_et_CO(4);   % kJ/mol_et


end



%% Stochiometry of catabolic, anabolic and metabolic reactions

function Y = stoich(X,Temp)

% This function calculates the amounts of water, protons and electrons in
% electorn donor and acceptor reactions, also in catabolic, anabolic and
% metabolic reactions. It also calculates the standard DG and DH changes in
% all the said reactions.
% This function is called many times by function 'micro' and 'Cat_CO'.
% Acetate and acetic acid production is considered by this function,
% although such products are not reported in the main document. That part
% of the calculation was used for validating the threshold concentrations
% and the construction of figures SI2 and SI3 of the supplementary
% information material.
% Matrix S contains information abut the C, H, O and N content in each
% substance involved in the reactions, plus their charge (Ch), degree of 
% reduction (dr), mol weight (MW), standard Gibbs free energy (dG) and 
% Enthapy (dH) of formation per mole of substance


%    C  H       O       N       Ch  dr      MW      dG      dH 
S = [1	0       1       0       0	2       28      -137.17	-110.53;    % CO
    0	2       0       0       0	2       2       0       0      ;    % H2
    0	4       0       1       1	0       18      -80.4	-133.3 ;    % NH4+
    2	6       1       0       0	12      46      -181.6	-288.3 ;    % Ethanol
    2	3       2       0       -1	8       59      -369.4	-485.8 ;    % Acetate
    2	4       2       0       0	8       60      -396.1	-485.5 ;    % Acetic acid
    1	1.75	0.50	0.25	0	4.00	25.25	-67     -91    ;    % Biomass
    1	0       2       0       0	0       44      -394.4	-393.5 ;    % CO2
    0	2       1       0       0	0       18      -237.7	-285.33;    % H2O
    0	1       0       0       1	0       1       0       0      ;    % H+
    0	0       0       0       -1	1       0       0       0      ];   % Electrons


Y = X;

Y = [Y -(Y*S(1:length(Y),3))]; 	% Oxygen is balanced with H2O
Y = [Y -(Y*S(1:length(Y),2))];  % Hydrogen is balanced with H+
Y = [Y (Y*S(1:length(Y),5))];   % Charge is balanced with electrons
lim = length(Y);
Y = [Y Y*S(1:lim,8)];           % Standard Gibbs free energy
Y = [Y Y(1:lim)*S(1:lim,9)];    % Standard Enthalpy of reaction 
Y = [Y Temp*(Y(lim + 1)/298.15 + Y(lim + 2)*(1/Temp - 1/298.15))]; % dG correction for temperature


end


%% Estimation of vapor-liquid equilibria of the ethanol-water mixture

function YY = NRTL_VLE(Temp)

% Initial definition of temperature and pressure

R = 8.3144598; % m3*Pa/K*/mol


% Antoine coefficients, 1: ethanol, 2: water, P[kPa], T[K]

A = [7.24215,   7.11572];
B = [1596.044,  1684.123];
C = [-46.655,   -43.568];


n = 200;            % Number of data points for each curve
nn = 1;             % Counter
YY = zeros(n,3);    % Initiatization of data storage matrix

for x1 = linspace(0,1,n)
    
    % Definition of mol fractions in liquid
    
    x2 = 1 - x1;
    x = [x1; x2];
    
    
    % Individual parameters per substance
    
    a_11 = 0.3;
    
    th_12 = (88*4.184)/(R*Temp);
    th_21 = (976*4.184)/(R*Temp);
    
    G_12 = exp(-a_11*th_12);
    G_21 = exp(-a_11*th_21);
    
    
    % Activity coefficients in the liquid phase
    
    phi_liq(1) = exp(x(2)^2*(th_21*(G_21/(x(1) + x(2)*G_21))^2 +...
        th_12*G_12/(x(2) + x(1)*G_12)^2));
    
    phi_liq(2) = exp(x(1)^2*(th_12*(G_12/(x(2) + x(1)*G_12))^2 +...
        th_21*G_21/(x(1) + x(2)*G_21)^2));
    
    
    % Partial pressures and mol fractions in vapor phase
    
    P_i = 10.^(A - B./(C + (Temp))); % in kPa
    Pmix = P_i(1)*x(1)*phi_liq(1) + P_i(2)*x(2)*phi_liq(2);
    
    y(1) = P_i(1)*x(1)*phi_liq(1)/Pmix;
    y(2) = P_i(2)*x(2)*phi_liq(2)/Pmix;
    
    
    % Save values into one matrix
    
    YY(nn,:) = [x(1) y(1) Pmix];
    nn = nn + 1;
    
end

end
