Equation constants that do not change between runs

I accidentally discovered that Brian2 treats

eqs = '''dv/dt = (v_rest - v + i_exc + i_inh) / (100*ms)  : volt (unless refractory)'''

and

tau_m = 100 * ms
eqs = '''dv/dt = (v_rest - v + i_exc + i_inh) / tau_m : volt (unless refractory)'''

differently. I believe the difference is that the value 100 ms is available to Brian2 in the first equation, allowing it to optimize code better. This leads to slight but annoying variations in neuronal state as the order of floating point operations changes (floating point is not associative). I guess this is because Brian2 thinks tau_m might change, hence it can’t just replace the constant with the value when building the network.

So my question is how to get the second example work like the first? I want to tell Brian2 that for these neurons tau_m won’t change so please just replace the variable with its value.

Hi @bjourne. You are right that the executed code will not be exactly the same in both cases, since, e.g.:

run(1*second)
tau_m = 200*ms
run(2*second)

would be allowed to change the value between the runs. Please note that in general, there are other reasons why the exact results can change (see the note here: Compatibility and reproducibility — Brian 2 2.7.1 documentation), so unfortunately you can never be 100% sure that the results stay exactly the same.

Having said that, the “canonical way” to turn the second equation into an equivalent of the first is to use:

tau_m = 100 * ms
eqs = Equations('''dv/dt = (v_rest - v + i_exc + i_inh) / tau_m : volt (unless refractory)''', tau_m=tau_m)

Under the hood, this will basically replace the string tau_m with its value…

Hope that helps!

Thanks for the quick reply! It partially solves my problem. Until now I have used (shared, constant) to create “really constants”, but I will use your method instead which should make my models faster. However, I’m still getting different results. That is,

Equations('dv/dt = (-65 * mV - v + I_synE + I_synI) / tau_mem  : volt (unless refractory)', tau_mem = 100 * ms)

is not identical to

Equations('dv/dt = (-65 * mV - v + I_synE + I_synI) / (100 * ms)  : volt (unless refractory)')

After testing more, I think I’ve found the root cause. Writing tau_mem expands to 100. * msecond, whereas writing 100 * ms expands to 100 * msecond without the dot.

I see, yes this is a bit unfortunate. Our handling of units within and outside of equations is not as consistent as it should be (outside of equations, quantities are always floating point values). We are currently looking into some updates of the unit system, potentially this would be addressed by this work as well.