Best way to pass 75 variables into a function or into a for loop?

I’m writing a chemistry simulation that has ~75 variables of which half of them are scalars while the other half of them are 2D or 1D arrays, and also half of them are constant while the other half of them are mutated by the code. All ~75 of the variables need to be passed into a function or into for loops (~4 nested for loops) for my main calculations. Computation speed is very important here.

What’s the best way of passing these ~75 variables into my for loops?

Should I place the entire code inside a module and define the ~75 variables as const globals? Except, of course, I can’t define the mutating scalars as const so I will have to do something different with them? I want the code to run fast, and I see all advice online says to have NO globals. So what do I do? Therefore I would have to write the code like this:

module foo
const scalar1 = 1;
const scalar2 = 1;
…etc…
const scalar30 =1;

const array1=[1 2];
const array2=[1 2];
const array3=[1 2];
…etc…
const array25=[1 2];

mutablescalar1=1;
mutablescalar2=1;
mutablescalar3=1;
…etc…
mutablescalar20=1;

function foo_function(mutablescalar1, mutablescalar2, mutablescalar3, …etc…, mutablescalar20)
global scalar1, scalar2, scalar3, … etc… scalar30, array1, array2, array3, …etc… array25

for i in 1:100
#do stuff
for i in 1:50
#do stuff
for I in 1:75
#do stuff
end
end
end
end

foo_function(mutablescalar1, mutablescalar2, mutablescalar3, …etc…, mutablescalar20)

end

This seems clumsy, and I’m wondering if there’s a better way to do it. I’m kind of a beginner here.

Is there a better way to organize the overall code strategy?

You may want to consider Parameters.jl or named tuples. There’s no such thing as a “mutable scalar”, since every scalar quantity is inherently immutable (i.e. 2.5f0 === 2.5f0). You can re-bind a variable as a different scalar, but as you noted, re-binding global variables is a sin in Julia.

Parameters.jl has some nice utilities for this sort of thing:

using Parameters

@with_kw mutable struct ChemMutables @deftype Float64
    a = 4
    b = 5
    c = 2pi
    d; e; f
end

@with_kw struct ChemConsts @deftype Float64
    q; r; s; t; u; v
end

@with_kw struct ChemArrays{T}
    A::Vector{T}
    B::Array{T, 2}
    C = T[1 2; 3 4]
end

# usage example
function f(CM::ChemMutables)
    CM.e = 2CM.e
end
CM0 = ChemMutables(d = 2, e = 40, f = 0)
f(CM0)  # CM0.e = 80
2 Likes

you can use an struct, look at a code that i have for a multiparameter helmoltz eos that i have:

struct GERG2008 <: AbstractHelmholtzModel
    N::Int64
    molecularWeight::Array{Float64,1}
    criticalDensity::Array{Float64,1}
    criticalTemperature::Array{Float64,1}
    ideal_iters::Array{Array{Int64,1},1}
    nr::Array{Float64,2}
    zeta::Array{Float64,2}
    n0ik::Array{Array{Float64,1},1}
    t0ik::Array{Array{Float64,1},1}
    d0ik::Array{Array{Float64,1},1}
    c0ik::Array{Array{Float64,1},1}
    k_pol_ik::Array{Int64,1}
    k_exp_ik::Array{Int64,1}
    gamma_v::Array{Float64,2}
    gamma_T::Array{Float64,2}
    beta_v::Array{Float64,2}
    beta_T::Array{Float64,2}
    Aij_indices::SparseArrays.SparseMatrixCSC{Int64,Int64}
    fij::Array{Float64,1}
    dijk::Array{Array{Float64,1},1}
    tijk::Array{Array{Float64,1},1}
    nijk::Array{Array{Float64,1},1}
    etaijk::Array{Array{Float64,1},1}
    epsijk::Array{Array{Float64,1},1}
    betaijk::Array{Array{Float64,1},1}
    gammaijk::Array{Array{Float64,1},1}
    k_pol_ijk::Array{Int64,1}
    k_exp_ijk::Array{Int64,1}
...
#400 lines of parameters
end
3 Likes

Why don’t you collect the scalars in a vector, and the arrays in a vector of arrays?

Those type annotations would be much easier to read if you used Vector and Matrix instead of Array everywhere. Less error prone too.

2 Likes

Because I’m a rookie and didn’t know if it would negatively affect computation speed. Do you think it would execute just as fast as the way I wrote the code in my original question?

Thanks, look good. And you believe that computation speed won’t be negatively affected as compared to the way I wrote the code in my original question?

It should be just as fast, and much easier to reason about. If your constant arrays are small (< ~100 elements), consider using StaticArrays.jl for further speed gains.

1 Like

The code works as expected, as the struct is an internal implementation, but I’m gonna take those advices in mind, thanks!