Chemical System

In this section, we’ll consider a few different ways to describe the behavior of a chemical system. We’ll start by building a model without using the array functionality. Then, we’ll implement the same behavior using vectors. Finally, we’ll implement the same model again using enumerations.

In all of our examples, we’ll be building a model for the following system of reactions:

\[\begin{split}A + B &\underset{1}{\rightarrow} X \\ A + B &\underset{2}{\leftarrow} X \\ X + B &\underset{3}{\rightarrow} R + S\end{split}\]

It should be noted that \(X\) is simply an intermediate result of this reaction. The overall reaction can be expressed as:

\[A + 2B \rightarrow R + S\]

Using the law of mass action we can transform these chemical equations into the following mathematical ones:

\[\begin{split}\frac{\mathrm{d}[A]}{\mathrm{d}t} &= -k_1 [A] [B] + k_2 [X] \\ \frac{\mathrm{d}[B]}{\mathrm{d}t} &= -k_1 [A] [B] + k_2 [X] -k_3 [B] [X] \\ \frac{\mathrm{d}[X]}{\mathrm{d}t} &= k_1 [A] [B] - k_2 [X] -k_3 [B] [X]\end{split}\]

where \(k_1\), \(k_2\) and \(k_3\) are the reaction coefficients for the first, second and third reactions, respectively. These equations are derived by considering the change in each species due to each reaction involving that species. So, for example, since the first reaction \(A + B \rightarrow X\) transforms molecules of \(A\) and \(B\) into molecules of \(X\), we see the term \(-k_1 [A] [B]\) in the balance equation for \(A\), which represents the reduction in the amount of \(A\) as a result of that reaction. Each term in these balance equations is derived in a similar fashion.

Without Arrays

Let us start with an approach that doesn’t utilize arrays at all. In this case, we simply represent the concentrations \([A]\), \([B]\) and \([X]\) by the variables cA, cB and cX as follows:

model Reactions_NoArrays "Modeling a chemical reaction without arrays"
  Real cA;
  Real cB;
  Real cX;
  parameter Real k1=0.1;
  parameter Real k2=0.1;
  parameter Real k3=10;
initial equation
  cA = 1;
  cB = 1;
  cX = 0;
equation
  der(cA) = -k1*cA*cB + k2*cX;
  der(cB) = -k1*cA*cB + k2*cX - k3*cB*cX;
  der(cX) = k1*cA*cB - k2*cX - k3*cB*cX;
end Reactions_NoArrays;

With this approach, we create an equation for the balance of each species. If we simulate this model, we get the following results:

../../../_images/RNA.png

Using Arrays

Another way to approach modeling of the chemical system is to use vectors. With this approach, we associated the species \(A\), \(B\) and \(X\) with the indices \(1\), \(2\) and \(3\), respectively. The concentrations are mapped to the vector variable C. We can also cast the reaction coefficients into a vector of reaction coefficients, k.

With this transformation, all the equations are then transformed into vector equations:

model Reactions_Array "Modeling a chemical reaction with arrays"
  Real C[3];
  parameter Real k[3] = {0.1, 0.1, 10};
initial equation
  C = {1, 1, 0};
equation
  der(C) = {-k[1]*C[1]*C[2] + k[2]*C[3],
            -k[1]*C[1]*C[2] + k[2]*C[3] - k[3]*C[2]*C[3],
            k[1]*C[1]*C[2] - k[2]*C[3] - k[3]*C[2]*C[3]};
end Reactions_Array;

The reaction equations are non-linear, so they cannot be transformed into a completely linear form. But we could simplify them further by using a matrix-vector product. In other words, the equations:

\[\begin{split}\frac{\mathrm{d}[A]}{\mathrm{d}t} &= -k_1 [A] [B] + k_2 [X] \\ \frac{\mathrm{d}[B]}{\mathrm{d}t} &= -k_1 [A] [B] + k_2 [X] -k_3 [B] [X] \\ \frac{\mathrm{d}[X]}{\mathrm{d}t} &= k_1 [A] [B] - k_2 [X] -k_3 [B] [X]\end{split}\]

can be transformed into the following form:

\[\begin{split}\frac{\mathrm{d}}{\mathrm{d}t} \left\{ \begin{array}{c} [A] \\[0pt] [B] \\[0pt] [X] \end{array} \right\} = \left[ \begin{array}{rrr} -k_1 [B] & 0 & k_2 \\ -k_1 [B] & -k_3 [X] & k_2 \\ k_1 [B] & -k_3 [X] & -k_2 \end{array} \right] \left\{ \begin{array}{c} [A] \\[0pt] [B] \\[0pt] [X] \end{array} \right\}\end{split}\]

which can then be represented in Modelica as:

der(C) = [-k[1]*C[2], 0,          k[2];
          -k[1]*C[2], -k[3]*C[3], k[2];
          k[1]*C[2],  -k[3]*C[3], -k[2]]*C;

The drawback of this approach is that we have to constantly keep track of which index (e.g., 1, 2, or 3) corresponds to which species (e.g., \(A\), \(B\), or \(X\)).

Using Enumerations

To address this issue of having to map back and forth from numbers to names, our third approach will utilize the enumeration type in Modelica. An enumeration allows us to define a set of names which we can then use to define the subscripts associated with an array. We’ll define our enumeration as follows:

type Species = enumeration(A, B, X);

This defines a special type named Species that has exactly three possible values, A, B and X. We can then use this enumeration as a dimension in an array as follows:

Real C[Species];

Since the Species type has only three possible values, this means that the vector C has exactly three components. We can then refer to the individual components of C as C[Species.A], C[Species.B] and C[Species.X].

Because it is awkward to constantly prefix each species name with Species, we can define a few convenient constants as follows:

constant Species A = Species.A;
constant Species B = Species.B;
constant Species X = Species.X;

In this way, we can now refer to the concentration of species \(A\) as C[A]. Pulling all of this together we can represent our chemical system using enumerations as:

model Reactions_Enum "Modeling a chemical reaction with enums"
  type Species = enumeration(
      A,
      B,
      X);
  Real C[Species] "Species concentrations";
  parameter Real k[3] = {0.1, 0.1, 10};
  constant Species A = Species.A;
  constant Species B = Species.B;
  constant Species X = Species.X;
initial equation
  C[A] = 1.0;
  C[B] = 1.0;
  C[X] = 0.0;
equation
  der(C[A]) = -k[1]*C[A]*C[B] + k[2]*C[X];
  der(C[B]) = -k[1]*C[A]*C[B] + k[2]*C[X] - k[3]*C[B]*C[X];
  der(C[X]) = k[1]*C[A]*C[B] - k[2]*C[X] - k[3]*C[B]*C[X];
end Reactions_Enum;
../../../_images/RE.png

Conclusion

In this chapter, we showed how a set of chemical equations could be represented with and without arrays. We also demonstrated how the enumeration type can be used in conjunction with arrays to make the resulting equations more readable by replacing numeric indices with names. Furthermore, this section also demonstrated how the enumeration type can be used not only to index the array, but also to define one or more dimensions in the declaration.