Método de Euler¶
As considerações anteriores sobre malhas numéricas são fundamentais para sugerir a notação que utilizaremos para expressar os métodos numéricos que estudaremos. O primeiro deles, chamado método de Euler, é considerado o método numérico mais simples para resolver PVIs. Embora não seja muito eficiente, é o ponto de partida para a compreensão de uma enorme família de métodos.
Ao longo do texto, denotaremos por a solução aproximada de um PVI.
Definição do método de Euler¶
A derivação do método de Euler inicia-se com a seguinte aproximação para a derivada:
conhecida como aproximação por diferença finita avançada (ou progressiva). Se aplicarmos esta definição ao nosso PVI padrão, em teremos , donde segue que
O método de Euler toma esta aproximação como exata, de modo que o esquema numérico resultante é
A estimativa inicial é ou alguma aproximação de . Quando é obtido empiricamente, seu valor é conhecido apenas aproximadamente. A fórmula anterior permite o cálculo sequencial das iteradas do método de Euler , aproximações para os valores exatos de nesses instantes.
Interpretação geométrica¶
A figura a seguir ajuda-nos a interpretar o método de Euler geometricamente. A aproximação numérica da curva exata (azul) é feita por meio de retas tangentes. O valor é erroneamente computado (comprimento ) e excede o valor exato (comprimento ) por uma quantidade (comprimento ). Isto é, a equação da reta tangente a é . Na verdade, coincide com o ponto .
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0.5,4,50)
plt.plot(x,np.log(x),'b')
x0 = 1.0
x1 = 3.0
plt.plot(x,np.log(x0) + x/x0 -1,'r--')
plt.plot(x0,np.log(x0),'ob')
plt.plot(x1,np.log(x1),'ob')
plt.plot(x1,0,'ok')
plt.plot(x,0*x,'k--')
plt.plot(x1,np.log(x0) + x1/x0 -1,'or')
plt.vlines(x1+0.1,ymin=0,ymax=np.log(x0) + x1/x0 -1,colors='r',linestyles='dashed')
plt.vlines(x1,ymin=0,ymax=np.log(x1),colors='b',linestyles='dashed')
xt = [x0,x1]
plt.box(False)
locs, labels = plt.xticks()
plt.xticks(xt, ('$t_n$','$t_{n+1}$'))
plt.tick_params(axis='both',width=0.0,labelleft=False)
fs = 18
plt.annotate('A',xy=(x0-0.2,np.log(x0)+0.2),fontsize=fs)
plt.annotate('B',xy=(x1-0.2,0+0.2),fontsize=fs)
plt.annotate('C',xy=(x1-0.1,np.log(x1)+0.2),fontsize=fs)
plt.annotate('D',xy=(x1-0.2,np.log(x0) + x1/x0 - 1 +0.2),fontsize=fs)
Exemplo: A solução exata do PVI
é . O método de Euler é dado por
com e .
Para , temos, por exemplo
cujos erros são
Implementação computacional¶
O seguinte código implementa o método de Euler explícito.
from numpy import *
def euler_expl(t0,tf,y0,h,fun):
"""
Resolve o PVI y' = f(t,y), t0 <= t <= tf, y(t0) = y0
com passo h usando o metodo de Euler explicito.
Entrada:
t0 - tempo inicial
tf - tempo final
y0 - condicao inicial
h - passo
fun - funcao f(t,y) (anonima)
Saida:
t - nos da malha numerica
y - solucao aproximada
"""
n = round((tf - t0)/h) + 1
t = linspace(t0,t0+(n-1)*h,n)
y = linspace(t0,t0+(n-1)*h,n)
y = zeros((n,))
y[0] = y0
for i in range(1,n):
y[i] = y[i-1] + h*f(t[i-1],y[i-1])
return (t,y)Exemplo: Resolva
Defina como a solução numérica, calcule o erro relativo e plote o gráfico de juntamente com o da solução exata
Solução: O processo iterativo de Euler será dado por
Entretanto, vamos usar o nosso programa euler_expl.
# define funcao
f = lambda t,y: (y + t**2 - 2)/(t+1)
# invoca metodo
t0 = 0.0
tf = 6.0
y0 = 2.0
h = 0.1
t,y = euler_expl(t0,tf,y0,h,f)
# plota funcoes
yex = t**2 + 2*t + 2 - 2*(t+1)*log(t+1)
plt.plot(t,y,'b--',label='$y_h(t)$')
plt.plot(t,yex,'k',label='$y(t)$')
plt.legend();
Agora, vamos computar a curva do erro relativo e plotá-la.
def erro_relativo(y,yh):
return abs(y-yh)/abs(yh)
e = erro_relativo(yex,y)+0.1
plt.plot(t,e,'r',label='$ER$')
plt.legend()
emax = np.max(e)
emin = np.min(e)
plt.plot(t,np.ones(t.shape)*emax,'b--')
plt.plot(t,np.ones(t.shape)*emin,'g--');
Exercício: Resolva o PVI do exemplo anterior usando por computador para . Produza um script para imprimir, para cada , os dados da saída na forma da tabela a seguir:
Análise de erro¶
A análise de erro para o método de Euler tem o propósito de entender como o método funciona para que se possa estimar o erro ao usá-lo e, possivelmente, acelerar sua convergência. Procedimentos similares são aplicáveis a métodos numéricos mais eficientes.
Para a análise, assumiremos que o PVI padrão possui solução única em e que esta solução tem uma segunda derivada limitada neste intervalo.
Consideremos a série de Taylor para aproximar :
Uma vez que satisfaz a EDO, temos que
O termo , erro de truncamento para o método de Euler, é o erro na aproximação
Assim, tendo em vista que
subtraímos as equações para obter
mostrando que o error em consiste de duas partes:
erro propagado: .
erro de truncamento: .
O erro propagado pode ser simplificado pelo teorema do valor médio:
Se definirmos o erro , podemos reescrever a última equação como
assim obtendo uma equação geral para análise de erro do método de Euler.
Teoremas para limite de erro¶
Teorema: Suponha que seja definida em um conjunto convexo . Se existe uma constante com
Teorema (limite de erro): Suponha que f seja contínua e satisfaça a condição de Lipschitz com constante em e que exista uma constante com . Seja única solução do PVI
e sejam aproximações geradas pelo método de Euler para algum inteiro positivo . Então, para cada ,
O último teorema fornece um limitante de erro para o método de Euler. Ele evidencia a dependência linear do tamanho de passo . Logo, à medida que , uma maior precisão nas aproximações deve ser obtida.
Exemplo: Consideremos o PVI
Uma vez que , temos . Assim, . A solução exata deste problema é , de modo que e . Pelo teorema do limite de erro, temos que
def f(t,y):
return y - t**2 + 1
# solucao numerica
t,y = euler_expl(0,2,0.5,0.2,f)
# solucao exata
yex = (t+1)**2 - 0.5*np.exp(t)
# erro
erro = np.abs(y - yex)
# limite de erro
lim_erro = 0.1*(0.5*np.exp(1)**2 - 2)*(np.exp(t) - 1.)
# tabela
print("Imprimindo comparação...\n\n ti | ei | Ei\n")
for i in range(len(y)):
print("{0:.1f} | {1:0.5f} | {2:0.5f}\n".format(t[i],erro[i],lim_erro[i]))
Imprimindo comparação...
ti | ei | Ei
0.0 | 0.00000 | 0.00000
0.2 | 0.02930 | 0.03752
0.4 | 0.06209 | 0.08334
0.6 | 0.09854 | 0.13931
0.8 | 0.13875 | 0.20767
1.0 | 0.18268 | 0.29117
1.2 | 0.23013 | 0.39315
1.4 | 0.28063 | 0.51771
1.6 | 0.33336 | 0.66985
1.8 | 0.38702 | 0.85568
2.0 | 0.43969 | 1.08264
Problemas¶
Resolva os seguintes problemas usando o método de Euler com passos . Compute o erro relativo usando a solução exata . Para valores selecionados de , observe a razão com que o erro diminui à medida que é reduzido pela metade. a.
b.
c.
d.
Considere o problema linear
A solução exata é . Resolva este problema usando o método de Euler com vários valores de e , para . Comente sobre os resultados.
a. .
b.
c.
d.
Faça uma análise do erro obtido pelo método de Euler ao ser resolver o caso a. do problema 2, .