This repository implements a type named HeterogeneousVector which is a segmented array type which can hold components of different concrete type while still supporting efficient type-stable broadcasting. Its components can either be other arrays or scalars. Note that the elements are mutable even if they are scalars, meaning that operations like: x.a += 2.5 do work as intended. This type is similar to NamedArrayPartition from RecursiveArrayTools.jl, the key differences being supporting heterogeneous components and mutable scalar components.
This data type is used in a realistic example simulating the COMBAT model for antibotic action provided in core_model.jl. This model is derived from Tran, Vi Ngoc-Nha et al. 2022 (https://doi.org/10.1186/s12859-021-04536-3) and Wiesch, P Abel zur et al. 2015 (https://doi.org/10.1126/scitranslmed.aaa8760). In this example, we use Unitful quantities to keep track of the units of measurement of the system variables and the parameters and simulate the system with DifferentialEquations' solver RK4. Doing this in an efficient and user-friendly manner requires us to use a structure like HeterogeneousVector.
The Pluto notebook equation_dimensions.jl takes a deep dive into the dimensionality of the COMBAT equations and highlights a dimension error in the original COMBAT model which was originally discovered when simulating the system with Unitful quantities. To open the notebook, launch Pluto by running
using Pluto
Pluto.run()Note that the notebook uses commands from the MathJax extension cases. If you really want to show these correctly, please change the properties:
window.MathJax = {
loader: {load: ['[tex]/cases']},
tex: {
inlineMath: [
["$", "$"],
["\\(", "\\)"],
],
packages: {'[+]': ['cases']},
}
}in the SetupMathJax.js file of the Pluto installation (it is not particulary easy, I know). Otherwise, you can change the parts of the notebook between begin{cases} and end{cases} with a more primitive, but supported TeX expression.
The problem described in core_model.jl is stiff and can thus be solved more efficiently with a solver such as Rosenbrock23. However, solving the system with Rosenbrock23 and related algorithms currently only works when stripping away the units of measurement and providing the system in a more convensional array format such as ComponentVector. Suggestions and contributions towards efficient solvers for stiff problems which can work natively with HeterogeneousVector and Unitful are welcome.
My vision is to make the key features HeterogeneousVector provides part of a registered Julia package. I don't know yet whether this should be its own package or be integrated in one of the existing ones (RecursiveArrayTools.jl is the obvious choice here). Please reach out to me if you want to collaborate.