# Manipulating local or external variable within NDSolve

I am wanting to save and use the value of a variable within NDSolve[] but without that variable being part of the equation itself.

Code below (ODE for the Leaky Integrate-and-Fire neuron) expresses what I want to do, with the value for the end of the refractory period updated within a WhenEvent[] statement.

Unfortunately it doesn't work and the error message suggests why not - but I don't know the solution though I am sure a simple one must exist.

trest = 0;
With[{τ = 10, R = 1, Jm = 1.5, vthresh = 1, vreset = 0, v0 = 0, tref = 3 },
lif = NDSolve[{v'[t] == If[ t >= trest, -(v[t] - Jm R)/τ, 0],
v == v0,
WhenEvent[ v[t] >= vthresh, {v[t] -> vreset, trest -> Evaluate[ t + tref ] } ]},
v[t], {t, 0, 60}] ]

NDSolve::wenset: Warning: the rule trest->Evaluate[t+3] will not directly set
the state because the left-hand side is not a list of state variables. >>


I realise that this can be done by adding another variable into the ODE, making its time derivative == 0 and just changing its value within the WhenEvent[] statement but this is rather messy and has potential to confuse the ODE solver.

• Why do you think that it "has potential to confuse the ODE solver"? Take a look at what DiscreteVariables do. – Dr. belisarius Nov 18 '13 at 12:52
• because having another variable in the problem with a zero derivative and then changing its value as a step function will have an impact on certain solution methods and their error/stiffness estimates – Michael Hopkins Nov 18 '13 at 18:10
• DiscreteVariables doesn't help, because it doesn't help to save the value that updates as you step through time. A solution that does this but needs the auxiliary variable defined within the system is: With[{\[Tau] = 10, R = 10, Jm = 0.7, vthresh = 1, vreset = 0, v0 = 0, tref = 2 }, lif = NDSolve[{v'[t] == If[ t >= trest[t], -(v[t] - Jm R)/\[Tau], 0], v == v0, trest'[t] == 0, trest == 0, WhenEvent[ v[t] >= vthresh, {v[t] -> vreset, trest[t] -> Evaluate[ t + tref] } ]}, {v[t], trest[t]}, {t, 0, 60}]] – Michael Hopkins Nov 18 '13 at 21:12
• any other thoughts? the above solution works but defining the auxiliary variable within the ODE feels wrong - surely there is a way of making WhenEvent[] save a value to a variable outside of the ODE itself? – Michael Hopkins Nov 19 '13 at 10:14

Another way is to make trest one of the DiscreteVariables.

Clear[trest]
With[{τ = 10, R = 1, Jm = 1.5, vthresh = 1, vreset = 0, v0 = 0, tref = 3},
lif = NDSolve[{v'[t] ==
Piecewise[{{-(v[t] - Jm R)/τ, t >= trest[t]}}, 0],
v == v0, trest == 0,
WhenEvent[v[t] >= vthresh, {v[t] -> vreset, trest[t] -> t + tref}]},
{v, trest}, {t, 0, 60}, DiscreteVariables -> {trest}]];

ListLinePlot[v /. First[lif], PlotRange -> All] 