- Yifan Hao

# Optimizing the performance of the OLI Computational Engine to deliver more rapid simulation insights

OLI Systems has a long history of successfully delivering comprehensive, process modeling solutions for industrial electrolyte and water chemistry applications. Our solutions are used in a variety of industries including oil & gas, power generation, metals & mining, chemicals, and water treatment to design and operate processes more effectively. The OLI solutions portfolio helps to make engineering users more productive and enhance the efficiency and sustainability of operations while reducing unplanned downtime.

The OLI solution includes a comprehensive chemistry property database, detailed thermodynamic and kinetic models, proven software applications that leverage the power of the OLI Computation Engine together with deep industry applications expertise, and sustained research and development. The schematic below shows the various elements of OLI’s process modeling solution. The performance of the OLI Engine directly impacts the speed and scalability of the OLI software applications. In this article, we will take a closer look at how three different numerical techniques have been implemented in the OLI Engine.

__The OLI Computational Engine:__

The OLI Engine is the heart of the OLI Solutions portfolio which enables software applications to utilize the property database and thermodynamic models to perform the numerical calculations and deliver process insights. It is the core computational engine with numerical solvers that has been continually enhanced since OLI’s inception. In addition to being accessed by the OLI software applications, the OLI Engine can also be accessed by third-party simulation software tools and applications with APIs.

__Enhancing the performance of the OLI Engine__

Over the years, OLI’s computational engine has evolved significantly to deliver more robust convergence, optimal speed, and rigorous, accurate predictions. It has been adapted to take advantage of newer technologies including modern programming languages, advanced solver algorithms, and state-of-art electrolyte thermodynamic frameworks. In this article, we will share one example of how the OLI engine’s performance can be improved by applying different numerical algorithms and open-source technologies.

Engineering calculations often require evaluation of function derivatives for equations solving, optimization, etc. There are three categories of algorithms that are widely used for programming such computations: numerical differentiation, analytical differentiation, and automatic differentiation. The OLI Engine uses all three types of algorithms in different situations based on the individual strength and weaknesses of each technique.

Numerical differentiation with finite differences is one of the most widely used algorithms. It is fast, simple to implement, but the accuracy depends on the selection of step size. In thermodynamic calculations, differentiation with respect to mixture composition is often required. With compositions of different components that could be varied in different scales, it is difficult to select one suitable step size to satisfy both accuracy and sensitivity for all composition variables.

Analytical differentiation is mostly used to compute accurate function derivative when the function expression is explicit and simple. There are some computer algebra libraries, like SymPy [1], can be used to symbolically differentiate the function which can be programmed into any other languages. Figure 1 below shows an example to evaluate the analytical expression of the Rackett model [2] for the temperature derivative of saturated liquid molar volume using SymPy. However, analytical differentiation normally expands the expression comparing to the original function. It requires a non-trivial amount of effort to optimize such algorithms to compete with the performance of numerical or automatic differentiation.

```
import sympy as sp
from fractions import Fraction
R, Tc, Pc, Zc, T = sp.symbols('R, Tc, Pc, Zc, T')
Vs = R*Tc/Pc*Zc**(1+(1-T/Tc)**Fraction(2,7))
sp.diff(Vs, T)
>>> -2*R*Zc**((-T/Tc + 1)**(2/7) + 1)*log(Zc)/(7*Pc*(-T/Tc + 1)**(5/7))
```

Figure 1. Using SymPy to evaluate the analytical derivative expression of a function.

Automatic differentiation has performance efficiency like numerical differentiation and the same degree of accuracy like analytical differentiation. It is based on applying the chain rule repeatedly to the sequence of elementary arithmetic operations [3]. There are several open-source libraries for applying the automatic differentiation algorithm, such as Ceres Solver [4], and Adept [5] in C++, and JAX [6] in Python. Figure 2 shows a simple example using Adept to compute the Jacobian of ionic strength with respect to molarity.

```
using adept::adouble;
//I = sum(0.5*ci*zi^2)
const adouble IonicStrength(const std::vector<double>& zi,
const std::vector<adouble>& ci)
{
adouble I = 0.0;
for (int i = 0; i < ci.size(); ++i)
I += 0.5*ci[i] * zi[i] * zi[i];
return I;
}
int main() {
adept::Stack stack;
std::vector<adouble> ci = { 0.2, 0.4, 1.0, 0.3 };//molarity
std::vector<double> zi = { 1.0, 1.0, 0.0, -2.0 };//charge
stack.new_recording();
adouble I;
stack.independent(ci.data(), ci.size());
stack.dependent(&Ix, 1);
Ix = IonicStrength(zi, ci);
double* pJac = new double[ci.size()];
stack.jacobian(pJac);
for (int i = 0; i < ci.size(); ++i)
std::cout << pJac[i] << " ";
}
>>> 0.5 0.5 0.0 2.0
```

Figure 2. Using automatic differentiation from Adept.

To compare the performance between automatic differentiation with analytical differentiation, we computed the activity coefficients of 600 species in the mixture using our routine for the UNIQUAC model [7]. As shown in Table 1, automatic differentiation shows significant speed improvement in calculating the full Jacobian matrix (600×600) of activity coefficients w.r.t. composition, compared to our optimized analytical differentiation algorithm. On the other hand, since it requires additional algorithms to trace all dependent and independent variables, it is much slower to evaluate the original function.

Table 1. Time comparison in millisecond between analytical differentiation and automatic differentiation.

__Summary:__

As a summary, all these algorithms have their strengths and weaknesses and should be applied based on the situation and the associated requirements. Numerical differentiation can be used for fast estimation where accuracy is less critical. Analytical differentiation and automatic differentiation should be implemented in solver algorithms to ensure robust convergence and accurate results: automatic differentiation should be applied to the bottleneck of the program computation to achieve optimum speed; otherwise analytical differentiation could be applied for easy code maintenance.

This article illustrates one fundamental aspect of the improvements of the OLI computational engine, and we look forward to sharing more exciting technologies applied to the OLI software products. All these new capabilities and improvements will gradually be incorporated into the OLI Software Platform over the next 24 to 36 months beginning in V11.

For more information on the OLI Engine or the OLI Software Platform please email sales@olisystems.com or complete this form to request an appointment with an OLI representative.

**References**

[1] https://www.sympy.org/en/index.html

[2] Rackett, H. G. (1970). Equation of state for saturated liquids. *Journal of Chemical and Engineering Data*, *15*(4), 514-517.

[3] https://en.wikipedia.org/wiki/Automatic_differentiation

[4] http://ceres-solver.org/index.html

[5] http://www.met.reading.ac.uk/clouds/adept/

[6] https://github.com/google/jax

[7] Abrams, D. S., & Prausnitz, J. M. (1975). Statistical thermodynamics of liquid mixtures: a new expression for the excess Gibbs energy of partly or completely miscible systems. *AIChE Journal*, *21*(1), 116-128.