37. Métodos de Adams-Bashfort#

from numpy import *
from matplotlib.pyplot import *
# Metodo de Adams-Bashfort de 2a. ordem

def adams_bashfort_2nd_order(t0,tf,y0,h,fun):
    '''
    Resolve o PVI y' = f(t,y), t0 <= t <= b, y(t0)=y0
    usando a formula de Adams-Bashfort de ordem 2 
    com passo h. O metodo de Euler eh usado para 
    obter y1. A funcao f(t,y) deve ser definida 
    pelo usuario. 
  
    Saida: 
  
    A rotina AB2 retorna dois vetores, t e y,  
    contendo, nesta orde, os pontos nodais e 
    a solucao numerica. 
    '''

    # malha numerica  
    n = np.round((tf - t0)/h) + 1
    t = np.linspace(t0,t0+(n-1)*h,n)
    y = np.zeros(n)

    y[0] = y0 # condicao inicial 

    f1 = fun(t[0],y[0]) # f(t_i,y_i)
    y[1] = y[0] + h*f1 # Euler 

    for i in range(2,n):
        f2 = fun(t[i-1],y[i-1]) # f(t_i-1,y_i-1)
        y[i] = y[i-1] + h*(3*f2 - f1)/2 # esquema AB2
        f1 = f2 # atualiza 
        
    return t,y


def tab_erro_rel(t,y_n,y_e):

    # erro relativo
    e_r = abs(y_n - y_e)/abs(y_e)

    print('i \t t \t y_ex \t y_num \t e_r')
    for i in range(len(e_r)): 
        
        if i % 10 == 0:
            print('{0:d} \t {1:f} \t {2:f} \t {3:f} \t {4:e} \n'.format(i,t[i],y_e[i],y_n[i],e_r[i]))
            
def plot_fig(t,y_n,y_e,h):    
    plot(t,y_e,'r-')
    plot(t,y_n,'bo')
    title('Adams-Bashfort, 2a. ordem: $h=' + str(h) + '$')
    legend(['$y_{exata}$','$y_{num}$'])

Exemplo: Use o esquema de Adams-Bashfort de 2a. ordem para resolver o PVI.

\[\begin{split}\begin{cases} y'(t) = -y(t) + 2 \cos(t) \\ y(0) = 1 \\ 0 \le t \le 18 \\ \end{cases}\end{split}\]

Solução exata: \(y(t) = {\rm sen}(t) + \cos(t)\)

# define funcao
f = lambda t,y: -y + 2*cos(t)

# parametros
t0 = 0.0
tf = 18.0
y0 = 1.0
h = 0.5

# solucao numerica 
t,y_num = adams_bashfort_2nd_order(t0,tf,y0,h,f)
    
# solucao exata 
y_ex = sin(t) + cos(t)

plot_fig(t,y_num,y_ex,h)

tab_erro_rel(t,y_num,y_ex)
i 	 t 	 y_ex 	 y_num 	 e_r
0 	 0.000000 	 1.000000 	 1.000000 	 0.000000e+00 

10 	 5.000000 	 -0.675262 	 -0.670163 	 7.550607e-03 

20 	 10.000000 	 -1.383093 	 -1.477388 	 6.817733e-02 

30 	 15.000000 	 -0.109400 	 -0.167908 	 5.348066e-01 
../_images/extra-multistep-adamsBashfort_4_1.png
h = 0.1

# solucao numerica 
t,y_num = adams_bashfort_2nd_order(t0,tf,y0,h,f)
    
# solucao exata 
y_ex = sin(t) + cos(t)

plot(t,y_ex,'r-')
plot(t,y_num,'bo')
title('Adams-Bashfort, 2a. ordem: $h=0.5$')
legend(['$y_{exata}$','$y_{num}$'])

tab_erro_rel(t,y_num,y_ex)

plot_fig(t,y_num,y_ex,h)
i 	 t 	 y_ex 	 y_num 	 e_r
0 	 0.000000 	 1.000000 	 1.000000 	 0.000000e+00 

10 	 1.000000 	 1.381773 	 1.384518 	 1.986208e-03 

20 	 2.000000 	 0.493151 	 0.491752 	 2.835038e-03 

30 	 3.000000 	 -0.848872 	 -0.852907 	 4.752486e-03 

40 	 4.000000 	 -1.410446 	 -1.413326 	 2.041670e-03 

50 	 5.000000 	 -0.675262 	 -0.674309 	 1.410789e-03 

60 	 6.000000 	 0.680755 	 0.684675 	 5.758689e-03 

70 	 7.000000 	 1.410889 	 1.414177 	 2.330243e-03 

80 	 8.000000 	 0.843858 	 0.843492 	 4.337392e-04 

90 	 9.000000 	 -0.499012 	 -0.502694 	 7.379922e-03 

100 	 10.000000 	 -1.383093 	 -1.386706 	 2.612468e-03 

110 	 11.000000 	 -0.995565 	 -0.995786 	 2.227766e-04 

120 	 12.000000 	 0.307281 	 0.310655 	 1.097903e-02 

130 	 13.000000 	 1.327614 	 1.331481 	 2.913030e-03 

140 	 14.000000 	 1.127345 	 1.128150 	 7.144782e-04 

150 	 15.000000 	 -0.109400 	 -0.112397 	 2.739478e-02 

160 	 16.000000 	 -1.245563 	 -1.249607 	 3.246745e-03 

170 	 17.000000 	 -1.236561 	 -1.237934 	 1.110338e-03 

180 	 18.000000 	 -0.090671 	 -0.088110 	 2.823799e-02 
../_images/extra-multistep-adamsBashfort_5_1.png
h = 0.01

# solucao numerica 
t,y_num = adams_bashfort_2nd_order(t0,tf,y0,h,f)
    
# solucao exata 
y_ex = sin(t) + cos(t)

plot(t,y_ex,'r-')
plot(t,y_num,'bo')
title('Adams-Bashfort, 2a. ordem: $h=0.1$')
legend(['$y_{exata}$','$y_{num}$'])

#tab_erro_rel(t,y_num,y_ex)

plot_fig(t,y_num,y_ex,h)
../_images/extra-multistep-adamsBashfort_6_0.png