I’m trying to run a simulation on a process where a process stream can contain various chemical components. For example, ethanol (C2H5OH) and water (H2). There’s a lot of places in the simulation where it makes sense to have things sitting in vectors that can be indexed by these components. For example
stream.massFlows[ indexer[:C2H5OH] ]
stream.densities[ indexer[:C2H5OH] ]
As we progress in modelling, these components can change, but they change very rarely. As I plan to have this running on a server, it would be nice if I could change these components without having to completely reload Julia. So the indexer becomes a global “nearly constant” variable (and is definitely constant for the duration of any function execution that uses it). This is pretty performance-sensitive as these references will happen inside an optimizer.
I tried using a NamedTuple as a constant, but if I change the indices, the actual type changes which is not allowed (I’d have to reload Julia). Ideally, all a change in the indexer would do is compile new methods for functions that use the indexer. However, I don’t want to be explicitly passing the indexer as an argument all the time.
So among the options I know of, I have:
(1) Global variable INDEXER that consists of named tuples (name to index) and use it in a function. I’ve heard this is inefficient, because the optimizer has trouble with it. Is it because the function that uses a global variable recompiles a new method if the type changes? If that’s the case, that’s what I want. INDEXER will maintain the same type during the execution, but it may change between executions.
(2) Global variable INDEXER passed as an optional named argument
myfunc(...; indexer=INEXER)
Does a change in INDEXER type cause multiple dispatch to create a new method like I want? Is this the only way to get this behavior?
(3) Global constant dictionary INDEXER that consists of symbols and Integer indices. I heard this could be pretty inefficient if you’re just looking at a small set of variables (which I am).
(4) Global constant list COMPONENTS that merely contains list symbols and at the beginning of every function I write " indexer = NamedTuple{COMPONENTS}(1:length(COMPONENTS)) "
I’m thinking that Option (2) is probably the most performant if it works. Are there any other (potentially better) options I might consider? Is Option (2) the “Official” Julia way of handling a global variable that doesn’t change type (or values for that matter) within a function execution?