Useful GEL code for teaching (or learning) - Differential Equations

Cut and paste the code into a new program and hit "Run" in the GNOME version.

D'Alembert solution animations

First, an initial pulse on a finite length string with fixed ends

# A periodic pulse function

function F(x) = (

while x < -1 do x = x + 2;

while x > 1 do x = x - 2;

if x < 0 then

-F(-x)

else if x < 0.45 or x > 0.55 then

0

else (

if x < 1/2 then

20*(x-0.45)

else

20*(0.55-x)

)

)

LinePlotDrawLegends = false;

# Run the animation

for n=1 to 1000 do (

t = n*0.005;

LinePlot(`(x)= (F(x-t) + F(x+t))/2,[0,1,-1.1,1.1])

)

Second, an initial square wave with zero initial velocity on an unbounded string (or at least not bounded within [-5,5])

function F(x) = (

if x < -1 or x > 1 then

0

else

1

)

LinePlotDrawLegends = false;

for n=1 to 300 do (

t = n*0.01;

LinePlot(`(x)=(F(x-t)+F(x+t))/2,[-5,5,-0.1,1.1])

)

And lastly, in initial position of 0 but the initial velocity of the square wave on an unbounded string

function G(x) = (

if x < -1 or x > 1 then

0

else

1

)

function integralofG(a,b) = (

if b < a then

integralofG(b,a)

else if b==a or b < -1 or a > 1 then

0

else (

min(b,1) - max(a,-1)

)

)

LinePlotDrawLegends = false;

for n=1 to 600 do (

t = n*0.01;

LinePlot(`(x)=(integralofG(x-t,x+t))/2,[-5,5,-0.1,1.1])

)

Standing waves animation

LinePlotDrawLegends = false;

for n=1 to 1000 do (

t = n*0.015;

LinePlot(`(x)=cos(t)*sin(x),[-5,5,-2,2])

)

Fourier series

Computing the Fourier series for a half sawtooth for 1 to 20 harmonics.

# The Fourier series up to nth harmonic

function ffsn(x,n) = (

(1/4) +

sum k=1 to n do (

(1/(k*pi)^2)*((-1)^k - 1) * cos(k*pi*x) + ((-1)^(k+1)/(k*pi)) * sin(k*pi*x)

)

)

LinePlotWindow=[-2,2,-0.5,1.5];

LinePlotDrawLegends=false;

LinePlotClear();

# Draw the graph by hand to correctly draw the gap

LinePlotDrawLine([-2,0;-1,1],"thickness",2,"color","darkblue");

LinePlotDrawLine([-1,0;0,0;1,1],"thickness",2,"color","darkblue");

LinePlotDrawLine([1,0;2,0],"thickness",2,"color","darkblue");

# Wait for 1 second before starting with the Fourier series

wait(1);

# Do first 20 harmonics

for n=1 to 20 do (

# compute values and put in a vector instead of using the built in function grapher

v=null;

for x=-2 to 2 by 0.003 do

v=[v,[x,ffsn(x,n)]];

LinePlotClear ();

# Draw the graph by hand to correctly draw the gap

LinePlotDrawLine([-2,0;-1,1],"thickness",2,"color","darkblue");

LinePlotDrawLine([-1,0;0,0;1,1],"thickness",2,"color","darkblue");

LinePlotDrawLine([1,0;2,0],"thickness",2,"color","darkblue");

# Plot the fourier series up to nth harmonic

LinePlotDrawLine(v,"thickness",2,"color","darkgreen");

)

Shock waves, traffic flow equation (nonlinear first order PDE)

If you have the equation ut + g(u) ux = 0 with initial condition u(x,0)=phi(x), you can solve by finding characteristics, but you can come up with shocks (discontinuities). So here's a way to draw the characteristics to see where shocks form:

# We are looking at characteristics (looking for shocks)

# for the equation u_t + g(u) u_x = 0, with initial condition

# u(x,0) = phi(x)

# this is for flux u*(2-u)

#function g(u) = 2-2*u;

# Quadratic flow for flux u^2 / 2

function g(u) = u;

# ramp down

function phi(x) = (

if x < 0 then 1

else if x < 1 then 1-x

else 0

);

# rampup

#function phi(x) = (

# if x < 0 then 0

# else if x < 1 then x

# else 1

#);

# we'll have x going from

xstart = -3;

xend = 3;

xstep = 0.1;

# end at this t, start at 0

tend = 1.5;

LinePlotWindow = [xstart,xend,-0.1,tend+0.1];

LinePlotDrawLegends = false;

LinePlotClear();

# Draw characteristics

for x0=xstart to xend by xstep do (

LinePlotDrawLine([x0,0,x0+g(phi(x0))*tend,tend])

)

Using RungeKuttaFull to draw solutions of differential equations

If we have just one first order ODE:

# clear the plot

LinePlotClear();

LinePlotDrawLegends = true;

# solve the equation and get the points

line = RungeKuttaFull(`(x,y)=y,0,1.0,3.0,50);

# draw the plot

LinePlotDrawLine(line,"window","fit","color","blue","legend","Exponential growth");

If we have a system of ODE (or a higher order ODE converted to a system)

# clear the plot

LinePlotClear();

LinePlotDrawLegends = true;

# solve the equation, make sure to use row vectors

lines = RungeKuttaFull(`(x,y)=[y@(2),-y@(1)],0,[1.0,1.0],10.0,100);

# flatten the matrix so that the solutions are simply the columns in the resulting matrix

lines = ExpandMatrix(lines);

# get the first line (columns 1 and 2, column 1 are the x values, column 2 are the y_1 values)

firstline = lines@(,[1,2]);

# get the second line (columns 1 and 3)

secondline = lines@(,[1,3]);

# set a plot window and draw, a fit wouldn't work here since, it would only

# fit the second line

LinePlotWindow = [0,10,-2,2];

LinePlotDrawLine(firstline,"color","blue","legend","First");

LinePlotDrawLine(secondline,"color","red","legend","Second");

You can also try playing around with EulersMethodFull, although unless you want to demonstrate that Eulers method is not good, I recommend you use RungeKutta