%Fed-Batch model

function [dYdt, params, outputs] = FedBatchModel_EH(t, Y, params) %Fed-batch model function returning derivatives, updated parameters and outputs

X=Y(1); %Biomass (g)
S=Y(2); %Substrate (g)
V=Y(3); %Volume (L)
v=Y(4); %Volume substrate feed (L)
P=Y(5); %Product (g)
A=Y(6); %Acetate (g)


%Calculation of initial feed rate F_0
if params.i == 1 %Enables a single start of the feed
    if S./V <= params.C_s_crit %Substrate concentration must be below C_s_crit to start the feed
        params.t_FS = t; %Define the time value for feed start 
        params.X_FS = X; %Define the biomass value for feed start
        params.P_FS = P; %Define the product value for feed start
        params.Y_x_s_batch = (params.X_FS - params.X_0) / (params.S_0 - (params.C_s_crit*params.V_0)); %Define the yield for feed start
        params.F_0 = (params.my_f / params.Y_x_s_batch + params.m) * (params.X_FS / params.S_f) * params.rho_F %Calculation of initial feeding rate F_0
        params.i = 2; %Enables a single start of the feed
    end
end

%Starting the feed and feed function
if t >= params.t_FS %Check if feed start time has been reached
    if v >= 0 %Check if substrate feed is empty
        F = params.F_0 * exp(params.my_f * (t - params.t_FS)); %Exponential feed function
    else
        F = 0; %No feed if substrate feed is empty
    end
else
    F = 0; %No feed until t >= t_FS
end


%Growth rate calculation and maintenance
my_s = params.my_s_max * ((S/V) / ((S/V) + params.K_s))  * (1 / (1 + ((A/V)/params.K_i))); %Growth rate calculation via Monod kinetic including inhibition by acetate
if S./V <= params.C_s_crit && A > 0 && S > 0 %Check if growth on acetate is possible
    my_a = params.my_a_max * ((A./V) / ((A./V) + params.K_a)); %Growth rate calculation via Monod kinetic
else
    my_a = 0; %No usage of acetate
    params.m_a = 0; %no usage of acetate
end
    

%Yield calculation
Y_x_s = my_s ./ ((1./params.Y_x_s_true)*my_s + params.m); %Substarte to biomass conversion
Y_p_x = params.Y_p_x; %Production of product by biomass


%Acetate formation rate calculation
if S./V <= params.C_s_crit_a_1 %Check acetate formation
    b = 0; %No acetate formation if S./V <= params.C_s_crit_a_1
else
    if S./V > params.C_s_crit_a_1 && S./V < params.C_s_crit_a_2 %Check acetate formation
        b = (params.b_max / (params.C_s_crit_a_2 - params.C_s_crit_a_1))*(S./V) - (params.b_max * params.C_s_crit_a_1) / (params.C_s_crit_a_2 - params.C_s_crit_a_1); %Acetate formation if S./V > params.C_s_crit_a_1 && S./V < params.C_s_crit_a_2
    else
        b = params.b_max; %Acetate formation with maximum rate b_max if S./V >= params.C_s_crit_a_2
    end
end


%Differential equations for biomass X, substrate S, product P and acetate A
%Differential equations for volume V and substarte feeding volume v
%t_lag is the lag time
dVdt = (F/params.rho_F)*params.c; 
dvdt = - F/params.rho_F;
if t < params.t_lag %Check if t < params.t_lag: no biomass formation, no product formation, no acetate formation and substarte consumption just for maintenance
    dXdt = 0;
    dPdt = 0;
    dAdt = 0;
    dSdt = - params.m*X;
else %Check if t >= params.t_lag
    dXdt = my_s*X + my_a*X; %Biomass formation
    dPdt = my_s*Y_p_x*X; %Product formation by biomass
    dAdt = b*X - (my_a/params.Y_x_a)*X - params.m_a*X; %Acetate formation and consumption for biomass growth and maintenance
    if my_a > 0 %Check if biomass grow on acetate
        dSdt = (F/params.rho_F)*params.S_f - (my_s./Y_x_s)*X - (1/params.Y_p_s)*dPdt; %Substrate consumption for biomass growth and product formation; addition of substrate via feed
    else
        dSdt = (F/params.rho_F)*params.S_f - (my_s./Y_x_s)*X - (1/params.Y_p_s)*dPdt  - (1/params.Y_a_s)*dAdt; %Substrate consumption for biomass growth and product/acetate formation; addition of substrate via feed
    end   
end
w = dPdt./X; %Calculation of productivity w

dYdt = [dXdt dSdt dVdt dvdt dPdt dAdt]';

%Additional outputs my_s, Y_x_s, F and w
outputs = struct('my_s', my_s, 'Y_x_s', Y_x_s, 'F', F, 'w', w);

end






