Speed up DFT calculations with vector dual numbers
Implementation
This PR improves the speed of DFT calculations without affecting the convergence at all. Instead, vector dual numbers are used to calculate first and second partial derivatives of the Helmholtz energy. Having functions that are generic over the number of weighted densities in the FunctionalContribution trait makes it not object safe. Therefore, it is instead implemented via a derive macro.
Execution times
This PR replaces one AD method with another one; both produce exact (up to machine precision) derivatives. Therefore, no difference in convergence is to be expected.
Some benchmarks:
| model | components/segments | time old | time new |
|---|---|---|---|
| FMT | 1 | 55.3 ms | 37.1 ms |
| PC-SAFT | 1 | 74.7 ms | 54.6 ms |
| PC-SAFT | 2 | 208 ms | 124 ms |
| gc-PC-SAFT | 4 | 23.1 s | 7.95 s |
Compilation time
The new code generates a lot of additional code. While this is necessary to increase performance, it also slows down the compilation (and increases binary size). As compromise, the optimization is only applied for mixtures with up to 5 (PC-SAFT) or 3 (PeTS) components, and 10 (gc-PC-SAFT) segments.
With the lto profile being merged the performance gains change somewhat:
| model | components/segments | main (release) | main (lto) | new (release) | new (lto) |
|---|---|---|---|---|---|
| FMT | 1 | 50.6 ms | 28.2 ms | 34.3 ms | 27.9 ms |
| PC-SAFT | 1 | 68.3 ms | 27.6 ms | 53.1 ms | 30.1 ms |
| PC-SAFT | 2 | 205 ms | 89.9 ms | 139 ms | 85.5 ms |
| gc-PC-SAFT | 4 | 4.13 s | 2.21 s | 1.35 s | 0.80 s |
| compile time | 2 min 37 s | 8 min 34 s | 4 min 41 s | 13 min 53 s |
compile times are measured after cargo clean.