# Introduction

Currently, Optferm only supports the loading of fermentation process models described in its own format. This format follows a well defined structure, that is described in the following topics.

# OptFerm Model Structure

The OptFerm model format follows a simple struture, in a way of helping the researchers in descrition of the different parts concerning to a fermentation process. Thus, there are a set of rules that are mandatory in this description, which are:

Declaration of the fields in the same order that are shown below:

1. NOTES {...} (this is the only field that is optional).
2. STATE_VARIABLES {...}
3. VOLUME_VARIABLE {...}
4. FEED_VARIABLES {...}
5. PARAMETERS {...}
6. DIFFERENTIAL_EQUATIONS{...}
7. KINETIC_EQUATIONS {...}
8. OBJECTIVE_FUNCTIONS {...}

All statements must be declared within the curly brackets "{...}" in the fields presented above.

When a equation is assigned to a variable or a constant is declared, these statements must be completed by a semi-colon ";".

Example:

x=1;  or x=(y+e)*6;


After the KINETIC_EQUATIONS field shown above, it is mandatory to declare which are the kinetic/rate variables that will be displayed in the result plots. These variables are declared between squared brackets and separated by comma.

Example of the OptFerm model structure:

NOTES {
date = "current date";
description = "Model of a fermentation process";
}

STATE_VARIABLES {
A = 5.0;
B = 0;
}

VOLUME_VARIABLE{
V= 2 [1,3];
}

FEED_VARIABLES{
Ain= 5 [F];
}

PARAMETERS {
k1=3.164 [1.3,5.6];
k2=8.36E-5;

}

DIFFERENTIAL_EQUATIONS {
D=F/V;
A=(mu1+mu2)*A + D*Ain;
B=(k2*mu2)-D*B;
V=F;
}

KINETIC_EQUATIONS[mu1,mu2]{

if(A>0){
mu1=k1*K2;
mu2=k2;
}
else{
mu1=0;
mu2=0;
}

}

OBJECTIVE_FUNCTIONS {

myobjfunct1 {

return $max(B); } myobjfunct2 ["My Objective Function2"] { return$max(B/V);
}

}


## Notes

The field Notes is optional and can be used to describe any information concerning to user fermentation model. Inside this field is possible to put multiple assignments through a key=value coding. The key its any variable defined by user, which have an associated value, that must be enclosed by quotation marks.
These statements can be described as follow:

NOTES {

key_1="any value_1";
.
.
.
key_n="any value_n";
}


## State Variables

Here, user must describe the main components (which have interest to follow its concentration over time) concerning to the fermentation model. All reported variables will be shown in the results, such as tables and plots, during the analysis procedures. User can use two different annotations in order to describe those variables, and they are:

Variable Name = Initial Value;
Variable Name = Initial Value [Lower Limit, Upper Limit];


A lower limit and a upper limit values can be defined, and they can be used as bounds in the optimization or parameters estimation process.

Example, of how to describe the state variables:

STATE_VARIABLES {
X = 0.3;
S = 0 [0,100];
A = 1e-4 [1e-5,2];
}


## Volume Variable

The Volume variable can be declared using any name. However, it is mandatory to attribute an initial value, a lower limit and a upper limit, using the same annotation presented before. Thus, this variable must be described as following:

Variable Name = Initial value [Lower Limit, Upper Limit];


Example:

VOLUME_VARIABLE{

Vol = 3 [1,5.5];
}


## Feed Variables

All feeding variables of a fermentation model must be declared in this field. However, there are some important aspects that must be taken into account.

There are a reserved word @feed that is used by OptFerm to return the total feeding rate in a given time instant (t), along the fermentation time. Thus, in the ODE concerning to Weight/Volume (equation for mass/volume variation inside the reactor) should be assigned the @feed variable.

If more than one feed variable in the fermentation model is defined, the feeding rate variable name that links to a feed variable and which will be used on Ordinary Differential Equations, must be declared. For example, FS1 and FS2 are declared as feed variables, but in the ODEs the corresponding feeding variables are referenced as FS1in and FS2in. It is mandatory to assign the name used in ODEs to the name declared in this field, by using the following annotation:

FS1 = Concentration_Value [FS1in];
FS2 = Concentration_Value [FS2in];


The feeding rate values for FS1in and FS2in will be calculated automatically in OptFerm and passed to the ODEs along simulation time.

If only one feed variable in the fermentation model is defined, is not mandatory the declaration of a linking variable, to be used in ODEs. However, in the beginning of ODEs (DIFFERENTIAL_EQUATIONS field) is advisable the assignment of a variable to get the value returned by @feed.

Fin=@feed; --> in the beginning of the ODEs declaration.


In resume, feed variables can be declared as presented below:

Feed Variable Name = Concentration Value;
Feed Variable Name = Concentration Value [Feeding Variable Name declared in ODEs];


Example:

Sc= 200;
Sc= 200 [Scin]; -> in the ODEs, SCin is used as feeding variable in a corresponding equation.


## Parameters

All the kinetic and yield parameters that are contained on both Differential equations and the Kinetic equations, are described in this field. Their description is quite similar to that is used in the State Variables field. In that way, a parameter can be declared using one of the following annotations:

Parameter Name = Value;
Parameter Name = Value [Lower Limit, Upper Limit];


A lower limit and a upper limit values can be defined to be used as bounds in the parameters estimation process.

Example, of how the parameters can be outlined:

 PARAMETERS {
K1 = 0.1428 [0.01,2];
K2 = 1.25e-3;
YOS = 2.02;
}


## Differential Equations

The system dynamics is represented by Ordinary differental equations (ODEs) in OptFerm models. These mathematical equations must describe the dynamical phenomena over time for each one of the State Variables in the fermentation process. Basically, is a derivative of a dependent variable y (State Variable) with respect to independent variable time, dy/dt. The description must follow the General Dynamical Model of Bioreactors formulation presented by Bastin and Dochain (1990), in which the dynamics of the concentration of each component on a fed-batch reactor are written as follows:

Where:

• $\xi _{i}$ is the concentration of the component i (State Variable);
• K is the yield or stoichiometric coefficients matrix $K=[k_{ij}]$;
• r is the reaction rates vector ($r^{T}=[r_{1},...,r_{n}]$);
• F is the liquid mass flow feed vector ($F^{T}=[F_{1},...,F_{n}]$)
• Q is the vector of rate of mass flow in gaseous form ($Q^{T}=[Q_{1},...,Q_{n}]$)
• D is the dilution rate, defined as the quotient between the total liquid mass flow feed rate and the weight/volume of liquid inside the reactor.

However, in the optferm model formulation the derivative variable of a certain component $\xi _{i}$ (State Variable) is declared using the same name of the corresponding State variable. For instance, you want to describe an ODE for a component which was named as A, corresponding to $\frac{\mathrm{d}A }{\mathrm{d} t}$. So, this variable must be declared as:

A = ODE for component A;


It is important the order of how the ODEs are declared in optferm model, because they will be evaluated according that order. Thus, if an ODE of a certain component x is dependent of another component y, is advisable that the ODE concerning to component y should to be firstly declared.

Moreover, the implementation of any auxiliar equation regarding to a variable that makes part of an ODE it is allowed, but as referred previously, that equation must be declared before the corresponding ODE.

Example: we want to declare a ODE for a component B, but this equation is dependent of an ODE of a component R.

Thus, first it is declared:

R= any ODE;


and after is declared:

B = any ODE which includes the variable R;


Example, of how to describe the Differential equations in the optferm model:

This example describes the dynamics (ODEs) of three main components, which are: biomass (X), substract (S) and product (P);

However,

1. these ODEs are dependent of the diluation rate (D) at each time instant, which is calculated by D=F/V, F is the feed rate and V is the volume in Bioreactor in that instant.
2. the product depends of the carbon dioxide transfer rate (CTR) over time, which is calculated using the following mathematical equation: (k1*mu1 + k3*mu2) * X;

Thus, the differential equations can be described as followed:

DIFFERENTIAL_EQUATIONS {

CTR = (k1*mu1 + k3*mu2) * X;

F= @feed;

D= F/V;

X=(mu1+mu2-D)*X;

S= -qs * X - D * S + F/W * Sin;

P=(k1*mu1 + k2 * mu2) * X - CTR - D * P;

V=F;

}


## Kinetic Equations

In this field is defined how the reaction rates are influenced by the concentration of the components (State Variables) along time.
OptFerm allows the definition of rules for the reaction rates using a formulation based on a condicional concept, making them more flexible. This is allowed through the use of conditional statements if...else, enabling the establishment of different actions for different decisions. These decision making structures are explained in more detail in the Conditional statements section. Similarly to what was referred above in the description of the differential equations, is also important the order of how the kinetic equations are defined in the fermentation model.

### Assignment of the main kinetic variables

One important aspect in the declaration of the the kinetic variables, is the description of which of these variables will be allowed to appear in the results of the various tasks of OptFerm. Thus, it is mandatory after the KINETIC_EQUATIONS annotation, the description of which variables will be included in the results. This can be performed using the following annotation:

  KINETIC_EQUATIONS [x1,x2,...,xn]


as can be seen these variables are enclosed by squared brackets and need to be separated by comma.

Example, of how to describe the Kinetic Equations in the optferm model:

 KINETIC_EQUATIONS[mu1,mu2]{

qac=qacmax*(S/(Ka+S))*(Kis/(Kis+S));

if(S<=0){
mu1=0.0;
mu2=0.0
}
else{
mu1 = qs / k1;
mu2 = qac/k4;

if(mu1>mu2){
mu1=qs/k3;
}
}
}


## Objective Functions

The formulation of the objective functions in OptFerm models is analogous to a simple scripting language. Multiple objective functions can be defined in a model, being required only the assignment of a different name for each one of these objective functions. Conditional, For Loop and Special Functions statements can be used in the definition of the objective functions.

### Structure of an objective function

A basic objective function is represented by the following annotation:

Function Name ["Name to be displayed in OptFerm Graphical Interface (this is an optional parameter)"] {

return  Objective Function Equation;
}


The Function Name and the return statements are mandatory. After the return statement a mathematical equation must be defined, which will be used to calculate the objective function value. These must be enclosed by curly brackets and the Objective Function Equation ends with a semi-colon ";".

As alternative, is also possible to define more complex objective functions, however, it is necessary to perform a slightly diference in the objective function annotation by adding a do: statement followed by one or a set of mathematical equations, before the return statement.

Annotation:

Function Name ["Name to be displayed in OptFerm Graphical Interface (this is an optional parameter)"] {

do:
statements

return  Objective Function Equation or variable value;
}


In the statements section, Conditional and/or For Loop statements can be used to define auxiliar variables to support the establishment of an objective function. In resume, in statements field it can be declared one or multiple equations as presented below:

X=a+b+c;

if(A>0)
X=D+F;
else
X=0;

A=0;

for i from 0 to 1000 {
B=$sum(x[i]-S[i]); if(B>200) A=2; }  Example, of how to describe the objective functions in the optferm model: OBJECTIVE_FUNCTIONS { OBJ1 ["Objective function 1"] { return$productivity(X,W);
}

OBJ2 ["Objective function 2"] {

do:

G=k1*S;
for i:1->[endstatevars]{
H = \$max(P[i]*G);
}

return H;
}

OBJ3 {
return P/V;
}

}