agate-model / Agate.jl

A Julia library to build flexible and composable aquatic ecosystems.
MIT License
4 stars 0 forks source link

Define library functions style guide #34

Open nanophyto opened 3 weeks ago

nanophyto commented 3 weeks ago

We should define some basic rules how functions within the library are formatted.

e.g. 1 For a function where the tracer is P, and T is also a state variable. Should P always be listed first, followed by T?

linear_plankton_loss(lᵖⁿ, Q₁₀, T, P)

vs

linear_plankton_loss(P, T, lᵖⁿ, Q₁₀)

e.g. 2 Should the state variable be listed inside the function?

linear_plankton_loss(P, T, lᵖⁿ, Q₁₀)

vs

linear_plankton_loss(T, lᵖⁿ, Q₁₀) * P

The former might be useful for a function like:

function quadratic_plankton_loss(l, Q₁₀, T, P)
    l * Q₁₀_temperature(Q₁₀, T) * P^2
end
nanophyto commented 3 weeks ago

e.g. 2 Should the state variable be listed inside the function?

linear_plankton_loss(P, T, lᵖⁿ, Q₁₀)

vs

linear_plankton_loss(T, lᵖⁿ, Q₁₀) * P

The former might be useful for a function like:

function quadratic_plankton_loss(l, Q₁₀, T, P)
    l * Q₁₀_temperature(Q₁₀, T) * P^2
end

There is a strong case to stick with the second option for functions like:

phytoplankton_growth = 
    μ₀ * 
    Q₁₀_temperature(Q₁₀, T) * 
    monod_limitation(N, kₙ) * 
    smith_light_limitation(PAR, α, μ₀*Q₁₀_temperature(Q₁₀, T))  *   
    P

Quadratic mortality is a special case where something like this may be appropriate:

function quadratic_plankton_loss(l, Q₁₀, T, P)
    l * Q₁₀_temperature(Q₁₀, T) * P
end

quadratic_plankton_loss(l, Q₁₀, T, P)*P
radka-j commented 2 weeks ago

Regarding the first question, I prefer having the state variables listed before the constant terms. Starting with the tracers also seems right.

As for the second question, I think it's OK to only have linear_plankton_loss(P, T, lᵖⁿ, Q₁₀) and then if someone wants to make it quadratic they can do linear_plankton_loss(P, T, lᵖⁿ, Q₁₀) * P. We could also include quadratic_plankton_loss(P, T, lᵖⁿ, Q₁₀) that does it internally for them if we think it's used often enough. I think the main thing is that the function names reflect what they are doing and that we include all the core ones and then the user can compose them in whichever way they find useful.