({{, (RefLink[DiscreteVariables, paclet:ref/DiscreteVariables])
is an option for (RefLink[NDSolve, paclet:ref/NDSolve]) and other functions that specifies variables that only change at discrete times in a temporal integration.}})

OpenersNotesSection(Spacer1)Details

(RefLink[DiscreteVariables, paclet:ref/DiscreteVariables])->{(Subscript[v, 1]), (Subscript[v, 2]),…} specifies that (Subscript[v, 1]), (Subscript[v, 2]), … should be treated as variables that only change at discrete times.

The value of a discrete variable v can be changed through (RefLink[WhenEvent, paclet:ref/WhenEvent])[event,v->val] or (RefLink[WhenEvent, paclet:ref/WhenEvent])[event,v->"DiscontinuitySignature"].

The discrete variable solution v can be returned by using (RefLink[NDSolve, paclet:ref/NDSolve])[eqn,{v,…},…].

(RefLink[DiscreteVariables, paclet:ref/DiscreteVariables])->{(Subscript[vspec, 1]),(Subscript[vspec, 2]),…} can be used to specify the ranges for discrete variables.

Possible forms for (Subscript[vspec, i]) are:

Derivatives with respect to time of discrete variables are zero almost everywhere and should not appear in the equations.

For partial differential equations, discrete variables can depend only on the temporal independent variable in a method of lines semi-discretization.

OpenersPrimaryExamplesSection(Spacer1)Examples  (18)

OpenersExampleSection0(Spacer1)Basic Examples  (2)

Solve for y with a, a discrete variable that changes at regular intervals in time:

sol=NDSolve[{y'[t]==a[t],WhenEvent[Mod[t,1],a[t]->y[t]],y[0]==1,a[0]==1},{y,a},{t,0,4},DiscreteVariables->{a}]

Plot[Evaluate[{y[t],a[t]}/.sol],{t,0,4}]

Solve for y with a, a discrete variable that changes whenever y crosses 0:

sol=NDSolve[{y''[t]+a[t]y[t]==0,WhenEvent[y[t],a[t]->a[t]+1],y[0]==1,y'[0]==0,a[0]==1},{y,a},{t,0,20},DiscreteVariables->a]

Plot[y[t]/.sol,{t,0,20}]

Plot[a[t]/.sol,{t,0,20}]

OpenersExampleSection1(Spacer1)Scope  (7)

Increment a discrete variable at regular time intervals:

sol=NDSolve[{y'[t]==a[t],y[0]==0,a[0]==0,WhenEvent[Mod[t,1],a[t]->a[t]+1]},{y,a},{t,0,4},DiscreteVariables->a];

Plot[Evaluate[{y[t],a[t]}/.sol],{t,0,4}]

Increment a discrete variable when the solution crosses 0:

sol=NDSolve[{y''[t]==-y[t],y[0]==y'[0]==1,a[0]==0,WhenEvent[y[t]==0,a[t]->a[t]+1]},{y,a},{t,0,10},DiscreteVariables->a];

Plot[Evaluate[{y[t],a[t]}/.sol],{t,0,10}]

Modify multiple discrete variables simultaneously when the solution crosses 0:

eqns={y''[t]+.5 b[t]y'[t]==-a[t]y[t],a[0]==y[0]==y'[0]==1,b[0]==2};

sol1=NDSolve[{eqns,WhenEvent[y[t]==0,{a[t],b[t]}->{a[t]+1,b[t]+a[t]}]},{y,a,b},{t,0,8},DiscreteVariables->{a,b}];

Plot[Evaluate[{y[t],a[t],b[t]}/.sol1],{t,0,8}]

This time, enact the change in a before modifying b:

sol2=NDSolve[{eqns,WhenEvent[y[t]==0,{a[t]->a[t]+1,b[t]->b[t]+a[t]}]},{y,a,b},{t,0,8},DiscreteVariables->{a,b}];

Plot[Evaluate[{y[t],a[t],b[t]}/.sol2],{t,0,10}]

Stop the integration when a discrete variable goes out of the discrete range {1,2,3}:

eqns={x''[t]==-x[t],x[0]==1,x'[0]==0,a[0]==1,WhenEvent[x[t],a[t]->a[t]+1]};

NDSolve[eqns,x[t],{t,0,10},DiscreteVariables->{a[t]∈{1,2,3}}]

Stop when the discrete variable goes out of the continuous range [0, 3]:

NDSolve[eqns,x[t],{t,0,10},DiscreteVariables->{{a[t],0,3}}]

Print a message when out of range, but continue integrating the equation:

NDSolve[eqns,x,{t,0,10},DiscreteVariables->{a[t]∈{1,3,5,7}:>Print[{a[t],t}]}]

The initial condition is also out of range:

NDSolve[eqns,x,{t,0,10},DiscreteVariables->{a[t]∈{2,3}:>Print[{a[t],t}]}]

Discrete variables can take on non-numerical values:

NDSolve[{y'[t]==Switch[a[t],up,1,down,-1],y[0]==0,a[0]==up,WhenEvent[y[t]^2-1==0,a[t]->Switch[a[t],up,down,down,up]]},y,{t,0,10},DiscreteVariables->{a[t]∈{up,down}}];

Plot[y[t]/.%, {t, 0, 10}]

Allow sliding mode solutions by using the action "DiscontinuitySignature":

sol=NDSolve[{y'[t]==-a[t],y[0]==-1,a[0]==-1,WhenEvent[y[t],a[t]->"DiscontinuitySignature"]},{y,a},{t,0,5},DiscreteVariables->{a[t]∈{-1,0,1}}];

Plot the vector field and solution:

vf=VectorPlot[{1,-Sign[y]},{x,0,5},{y,-1,1},VectorStyle->{Gray,Arrowheads[.04]},VectorScale->Medium,VectorPoints->10,FrameLabel->{t,y}];

Show[vf,Plot[y[t]/.sol,{t, 0, 5}, PlotRange->{-1,1},PlotStyle->{Red}]]

The value of the discrete variable a is 0 when the solution is in sliding mode:

Plot[a[t]/.sol,{t,0,5}]

Set the discontinuity state variable v(t) when y(t) reaches a sliding discontinuity curve c(t):

c[t_]=Sin[t];

sol=NDSolve[{x'[t]==1,y'[t]==-v[t],WhenEvent[y[t]-c[t],v[t]->"DiscontinuitySignature"],x[0]==0,y[0]==.5,v[0]==1},{x,y,v},{t,0,6},DiscreteVariables->{v∈{-1,0,1}}];

curve=Plot[c[x],{x,0,2},PlotStyle->Red];

Show[curve,ParametricPlot[{{x[t],y[t]}}/.sol,{t,0,2}]]

OpenersExampleSection3(Spacer1)Applications  (5)

Switch between two right sides of a differential equation using a discrete variable:

rhs[t_,x_,1]=-x;
rhs[t_,x_,2]=1;

sol=NDSolve[{x'[t]==rhs[t,x[t],a[t]],x[0]==1,a[0]==1,WhenEvent[x[t]-.1,a[t]->2],WhenEvent[x[t]-2,a[t]-> 1]},{x,a},{t,0,15},DiscreteVariables->{a[t]∈{1,2}}];

Plot[x[t]/.sol,{t,0,10}]

Set up a differential equation that switches between multiple right sides:

Do[rhs[t_,x_,i]=t RandomReal[{-.1,.1}]+x RandomReal[{-1,1}]+RandomReal[{-.1,.1}],{i,11}]

NDSolve[{x'[t]==rhs[t,x[t],a[t]],x[0]==0,a[0]==1,WhenEvent[Mod[t,1],a[t]->a[t]+1]},x,{t,0,10},DiscreteVariables->{a[t]∈Range[11]}];

Plot[x[t] /. %, {t,0,10}]

Simulate a ball bouncing down steps:

c=.75;
xsol=NDSolve[{y''[t]==-9.8,y[0]==13.5,y'[0]==5,a[0]==13,WhenEvent[y[t]-a[t]==0,y'[t]->-c y'[t]],WhenEvent[Mod[t,1],a[t]->a[t]-1]},{y,a},{t,0,8},DiscreteVariables->{a}] ;

Plot[Evaluate[{y[t],a[t]}/.xsol],{t,0,8},Filling->{2->0}]

Plot the ball's kinetic, potential, and total energy:

kin[v_]:=.5 v^2;
pot[y_]:=9.8y;
energy[y_,v_]:=kin[v]+pot[y];

Plot[Evaluate[{kin[y'[t]],pot[y[t]],energy[y[t],y'[t]]}/.xsol],{t,0,8}]

Simulate the system y'==y+u stabilized with a discrete-time controller u(k τ)==-2 y(k τ):

τ=1.0;
sol=NDSolve[{y'[t]==y[t]+u[t],y[0]==1,u[0]==0,WhenEvent[Mod[t,τ],u[t]->-2y[t]]},{y,u},{t,0,20},DiscreteVariables->u];

Plot[Evaluate[{u[t],y[t]}/.sol], {t, 0, 10}, PlotRange->{-6,6}]

Change the wave speed a(t) at t==1,2,… in a wave equation:

sol=NDSolve[{(∂_(t,t))u[t,x]==a[t](∂_(x,x))u[t,x],u[0,x]==(E^(-(x^2))),Derivative[1,0][u][0,x]==0,u[t,-10]==u[t,10],a[0]==1,WhenEvent[Mod[t,1],a[t]->Sqrt[t]]},u,{t,0,40},{x,-10,10},DiscreteVariables->{a[t]}];

DensityPlot[Evaluate[First[u[t,x]/.sol]],{t,0,40},{x,-10,10},PlotPoints->50]

OpenersExampleSection4(Spacer1)Properties & Relations  (1)

(RefLink[NDSolve, paclet:ref/NDSolve]) automatically handles discontinuous functions like (RefLink[Sign, paclet:ref/Sign]) using discrete variables:

sol1=NDSolve[{y'[t]==Sign[1-y[t]],y[0]==0},y,{t,0,2}];

Plot[y[t]/.sol1, {t, 0,2}]

Use "DiscontinuitySignature" with a discrete variable to emulate the (RefLink[Sign, paclet:ref/Sign]) function:

sol2=NDSolve[{y'[t]==a[t],WhenEvent[1-y[t],a[t]->"DiscontinuitySignature"],y[0]==0,a[0]==1},y,{t,0,2},DiscreteVariables->{a∈{-1,0,1}}];

Plot[y[t]/.sol2, {t, 0,2}]

OpenersExampleSection5(Spacer1)Possible Issues  (3)

When a discrete variable goes out of range, a message is displayed and the integration halts:

NDSolve[{x''[t]==-x[t],x[0]==1,x'[0]==0,y[0]==0,WhenEvent[x[t],y[t]->y[t]+1]},{x,y},{t,0,8},DiscreteVariables->{{y[t], 0,2}}]

Derivatives of discrete variables cannot appear in the equations passed to (RefLink[NDSolve, paclet:ref/NDSolve]):

NDSolve[{x''[t]==-a'[t] x[t],x[0]==1,x'[0]==0,a[0]==0,WhenEvent[x[t],a[t]->a[t]+1]},{x,a},{t,0,8},DiscreteVariables->{{a[t],0,2}}]

Discrete variables with "DiscontinuitySignature" action must have range {-1,0,1}:

sol=NDSolve[{y'[t]==a[t],WhenEvent[1-y[t],a[t]->"DiscontinuitySignature"],y[0]==0,a[0]==1},y,{t,0,2},DiscreteVariables->{a∈{-2,-1,0,1}}];

If the range is {-1,1}, the sliding mode solution will not be found:

sol=NDSolve[{y'[t]==a[t],WhenEvent[1-y[t],a[t]->"DiscontinuitySignature"],y[0]==0,a[0]==1},y,{t,0,2},DiscreteVariables->{a∈{-1,1}}];

Plot[{y[t]/.sol}, {t, 0,2}]

Specify the range as (RefLink[Element, paclet:ref/Element])[a,{-1,0,1}] for sliding mode solutions:

sol=NDSolve[{y'[t]==a[t],WhenEvent[1-y[t],a[t]->"DiscontinuitySignature"],y[0]==0,a[0]==1},y,{t,0,2},DiscreteVariables->{a∈{-1,0,1}}];

Plot[{y[t]/.sol}, {t, 0,2}]

({{DocumentationFooterIconsRelatedFunction.png, ({{See Also}, {(RefLink[NDSolve, paclet:ref/NDSolve])  ▪  (RefLink[WhenEvent, paclet:ref/WhenEvent])  ▪  (RefLink[DependentVariables, paclet:ref/DependentVariables])  ▪  (RefLink[NDSolveValue, paclet:ref/NDSolveValue])  ▪  (RefLink[ParametricNDSolveValue, paclet:ref/ParametricNDSolveValue])}})}})

({{DocumentationFooterIconsRelatedGuide.png, ({{Related Guides}, {▪(RefLinkPlain[Differential Equations with Events, paclet:guide/DifferentialEquationsWithEvents])}})}})