I am trying to solve this differential equation with the Euler Method using Python3:
According to Wolfram Alpha, that's the plot of the correct equation.
Again, according to Wolfram Alpha, in this case, the classic Euler Method should not be stable, as you can see by the end of the interval:
However, on my implementation, Euler method provides a stable result, which is strange. I wonder that my implementation is wrong for some reason. Nonetheless, I can't find the error.
I generated some points and a plot comparing my approximation and the analytic output of the function. In blue, the analytic result as control group. In red, the output of my implementation:
That's my code:
import math
import numpy as np
from matplotlib import pyplot as plt
import pylab
def f(x):
return (math.e)**(-10*x)
def euler(x):
y_init = 1
x_init = 0
old_dy_dx = -10*y_init
old_y = y_init
new_y = None
new_dy_dx = None
delta_x = 0.001
limite = 0
while x>limite:
#for i in range(1,6):
new_y = delta_x*old_dy_dx + old_y
#print ("new_y", new_y)
new_dy_dx = -10*new_y
#print ("new dy_dx", new_dy_dx)
old_y = new_y
#print ("old_y", old_y)
old_dy_dx = new_dy_dx
#print ("old delta y_delta x", old_dy_dx)
#print ("iterada",i)
limite = limite +delta_x
return new_y
t = np.linspace(-1,5, 80)
lista_outputs = []
for i in t:
lista_outputs.append(euler(i))
print (i)
# red dashes, blue squares and green triangles
plt.plot(t, f(t), 'b-', label='Output resultado analítico')
plt.plot(t , lista_outputs, 'ro', label="Output resultado numérico")
plt.title('Comparação Euler/Analítico - tolerância: 0.3')
pylab.legend(loc='upper left')
plt.show()
Thanks for the help.
============================================================
UPDATE
With @SourabhBhat help, I was able to see that my implementation was, actually, right. It was, indeed, generating an instability. Besides increasing the step size, I needed to do some zoom in to see it happening.
The picture bellow speaks for itself (step size of 0.22):
Depending on the time step size, the Euler integration can be stable or unstable, since it is an explicit method. You have chosen a pretty small time step. If you increase it you will start seeing the oscillations, as shown in figure below.
Here is a small testing program which I wrote (try slowly increasing the steps
variable [20,30,40,50....]):
import numpy as np
import matplotlib.pyplot as plt
steps = 20
def exact_solution(t):
return np.exp(-10.0 * t)
def numerical_solution(y0, dt, num_steps):
y = np.zeros(num_steps + 1)
y[0] = y0
for step in range(num_steps):
y[step + 1] = y[step] - 10.0 * y[step] * dt
return y
if __name__ == "__main__":
t0 = 0
time = np.linspace(t0, 5, steps + 1)
num_sol = numerical_solution(exact_solution(t0), time[1] - time[0], steps)
exact_sol = exact_solution(time)
plt.plot(time, num_sol, ".--", label="numerical")
plt.plot(time, exact_sol, label="exact")
plt.legend(loc="best")
plt.show()