Simulações Físicas em Python: Resolvendo Equações Diferenciais com o Método Numérico de Euler
Ao ler livros e trabalhos relacionados a ferramentas matemáticas utilizadas em engenharia e cursos de física, é possível encontrar uma variedade de métodos numéricos aplicados para solucionar diversos problemas em diferentes campos das ciências exatas. Neste artigo, daremos destaque ao método numérico de Euler, utilizado para resolver equações diferenciais ordinárias de primeira ordem.
Sua história
Numericamente, ela é denominada como método da reta tangente, que foi utilizado pela primeira vez pelo matemático suiço Leonhard Euler (1703–1783) em seus trabalhos de resolução de equações diferenciais. O método de Euler é muito atraente, por conta de sua simplicidade e boa resposta com os termos trabalhados.
Existem diversos métodos matemáticos para encontrar este método, particularmente, gosto de sair (de maneira meio trivial) da formulação da derivada até ela, pelo seguinte caminho:
Sabendo que a fórmula matemática da derivada em termos de limites é
podemos afirmar que
Relacionando as duas, para delta de x muito pequeno, podemos verificar que
E no final, encontrar o grandioso, simples e prático método de Euler
Trabalhando com o método de Euler em python
O seu algoritmo consiste na seguinte construção, presente no livro de equações diferenciais de Boyce e Diprima, em sua edição de 2010
Em termos de python, ele pode ficar assim em uma função
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
def euler_method(x,dy,dx:float=.01,y0:float=0.)->np.ndarray:
y_list = [y0] # determinando o valor inicial
for x_ in x: # caminhando pelo espaço amostral x
last_y = y_list[-1] # pegando o uĺtimo termo dos valores de y
y_ = last_y + dy(x_,last_y)*dx # aplicando o metódo de Euler
y_list.append(y_) # construindo a reta y por iteração
return np.array(y_list)
Aplicando a EDO de um corpo em queda livre
m = 80 # massa do corpo
g = 9.8 # aceleração da gravidade
k = 4.3 # possível resistência do ar
def dv(t,v):
return g -k*v/m # EDO da velocidade de um corpo em queda livre
def v(t):
return (m*g/k)*(1-np.exp(-t*k/m)) # resultado analítico da EDO de um corpo em queda livre
t_ = np.linspace(0,100,200) # espaço de tempo
Criando tabelas para diferentes h (ou deltas de x, mas o mais usado no lugar de delta de x é h mesmo), podemos verificar como a modificação de h no método de Euler pode melhorar a fitagem do resultado da equação.
Abaixo, estão os códigos seguidos de cada tabela com diferentes resultados para diferentes h em suas fitagens e os seus respectivos erros:
h_1 = .9
sol_euler_1 = euler_method(t_,dv,dx=h_1)
dt_1 = {'v real':v_,f'Euler h={h_1}':sol_euler_1,'erro':abs(v_-sol_euler_1)}
pd.DataFrame(dt_1).head()
h_1 = .7
sol_euler_1 = euler_method(t_,dv,dx=h_1)
dt_1 = {'v real':v_,f'Euler h={h_1}':sol_euler_1,'erro':abs(v_-sol_euler_1)}
pd.DataFrame(dt_1).head()
h_1 = .5
sol_euler_1 = euler_method(t_,dv,dx=h_1)
dt_1 = {'v real':v_,f'Euler h={h_1}':sol_euler_1,'erro':abs(v_-sol_euler_1)}
pd.DataFrame(dt_1).head()
h_1 = .3
sol_euler_1 = euler_method(t_,dv,dx=h_1)
dt_1 = {'v real':v_,f'Euler h={h_1}':sol_euler_1,'erro':abs(v_-sol_euler_1)}
pd.DataFrame(dt_1).head()
Podemos verificar, apenas analisando as tabelas feitas, que a fitagem com h=0.5 é a que melhor se aproxima do resultado real. Podemos verificar essa afirmação melhor fazendo o gráfico disso.
v_ = v(t_)
plt.plot(t_,v_,label='result. real')
h = .9
sol_euler = euler_method(t_,dv,dx=h)
plt.plot(t_,sol_euler,'--',label=f'h={h}')
h = .7
sol_euler = euler_method(t_,dv,dx=h)
plt.plot(t_,sol_euler,'--',label=f'h={h}')
h = .5
sol_euler = euler_method(t_,dv,dx=h)
plt.plot(t_,sol_euler,'--',label=f'h={h}')
h = .3
sol_euler = euler_method(t_,dv,dx=h)
plt.plot(t_,sol_euler,'--',label=f'h={h}')
plt.title('diferentes fitagens do metódo de Euler\npara diferentes h',fontweight='bold')
plt.legend()
plt.ylabel('velocidade (m/s)')
plt.xlabel('tempo (s)')
A fitagem feita pelo h=0.5 é praticamente perfeita para a melhor aproximação e solução da EDO do paraquedista através do método de Euler. Mas isso tem uma resposta bem simples e visível.
Como delta x é a diferença das interpolações dos pontos do espaço amostral de x, podemos simplesmente pegar a diferença presente no espaço amostral e fazer a interpolação pelo método de Euler, adicionando apenas uma linha específica no nosso algoritmo de Euler:
def euler_method(x,dy,dx:float=.01,y0:float=0.)->np.ndarray:
y_list = [y0] # determinando o valor inicial
dx = x[1]-x[0] # pegando a diferença de inter. em x *nossa linha adicional*
print(f'o h para este espaço x, deve ser: {dx:.2f}') # só pra denuncia msm
for x_ in x: # caminhando pelo espaço amostral x
last_y = y_list[-1] # pegando o uĺtimo termo dos valores de y
y_ = last_y + dy(x_,last_y)*dx # aplicando o metódo de Euler
y_list.append(y_) # construindo a reta y por iteração
return np.array(y_list)[:len(x)]
Se você for rodar o código anterior de novo, sem alterar nada na configuração do gráfico, vai verificar a seguinte denúncia seguido do seguinte gráfico:
Perceba, que todos foram fitaram praticamente que 100% do resultado real, colocando h como a diferença do espaço amostral usado para a plotagem. Os h na legenda ainda estão diferentes, por que não alteramos em nada a configuração da plotagem, para que você possa entender como realmente funciona o algoritmo de Euler se usado perfeitamente e de maneiras bem engenhosas.
Conclusão
Podemos terminar este artigo, concluindo que o método de Euler é sim uma das maneiras mais práticas, simples, elegantes e bonitas de se resolver numericamente equações diferenciais de primeira ordem. Contudo, é preciso notar que existem outras versões do próprio método de Euler, e de outros métodos numéricos que promovem o mesmo trabalho, mas que são um pouco mais complexos em seus algoritmos, como por exemplo, o método numérico de Runge-Kutta.
Este artigo foi com intuito de demonstrar, usando o método numérico mais elegante e bonito para este autor, como realmente funcionam os métodos numéricos para solução de problemas na física, matemática e em outras áreas das ciências que trabalham com números e valores exatos.
Muito obrigado pela sua leitura.
Referências
Boyce, William E.; Diprima, Richard C.;. Equações Diferenciais Elementares e Problemas de Valores de Contorno. Ed. Rio de Janeiro-RJ, 2010
Valle, Karine Nayara F.;. Métodos Numéricos de Euler e Runge-Kutta. Repositório UFMG. Belo Horizonte-MG, 2012