6.5 Métodos EDO con gráficos animados en Python


animación:

EDO Taylor 3t

Runge Kutta  dy/dx

Runge Kutta d2y/dx2

Sistemas EDO con RK


Solo para fines didácticos, y como complemento para los ejercicios presentados en la unidad para la solución de Ecuaciones Diferenciales Ordinarias, se presentan las instrucciones para las animaciones usadas en la presentación de los conceptos y ejercicios. Los algoritmos para animación NO son necesarios para realizar los ejercicios, que requieren una parte analítica con al menos tres iteraciones en papel y lápiz. Se lo adjunta como una herramienta didáctica de asistencia para las clases.


animación:

EDO Taylor 3t

Runge Kutta  dy/dx

Runge Kutta d2y/dx2

Sistemas EDO con RK


EDO con Taylor de 3 términos

EDO con Taylor 3términos gráfico animado

Tabla de resultados:

EDO con Taylor 3 términos
i,[xi, yi, d1yi, d2yi, término 1, término 2 ]
0 [0. 1. 0. 0. 0. 0.]
1 [0.1   1.215 2.    3.    0.2   0.015]
2 [0.2      1.461025 2.305    3.105    0.2305   0.015525]
3 [0.3        1.73923262 2.621025   3.221025   0.2621025  0.01610513]
4 [0.4        2.05090205 2.94923262 3.34923262 0.29492326 0.01674616]
5 [0.5        2.39744677 3.29090205 3.49090205 0.32909021 0.01745451]
6 [0.6        2.78042868 3.64744677 3.64744677 0.36474468 0.01823723]
7 [0.7        3.20157369 4.02042868 3.82042868 0.40204287 0.01910214]
8 [0.8        3.66278892 4.41157369 4.01157369 0.44115737 0.02005787]
9 [0.9        4.16618176 4.82278892 4.22278892 0.48227889 0.02111394]
10 [1.         4.71408085 5.25618176 4.45618176 0.52561818 0.02228091]
11 [1.1        5.30905934 5.71408085 4.71408085 0.57140808 0.0235704 ]
12 [1.2        5.95396057 6.19905934 4.99905934 0.61990593 0.0249953 ]
13 [1.3        6.65192643 6.71396057 5.31396057 0.67139606 0.0265698 ]
14 [1.4        7.4064287  7.26192643 5.66192643 0.72619264 0.02830963]
15 [1.5        8.22130371 7.8464287  6.0464287  0.78464287 0.03023214]
16 [1.6        9.1007906  8.47130371 6.47130371 0.84713037 0.03235652]
>>> 

Instrucciones en Python

# EDO. Método de Taylor con3 términos 
# estima solucion para muestras separadas h en eje x
# valores iniciales x0,y0
import numpy as np
 
def edo_taylor3t(d1y,d2y,x0,y0,h,muestras,
                 vertabla=False, precision=6):
    ''' solucion a EDO usando tres términos de Taylor,
    x0,y0 son valores iniciales, h es el tamaño de paso,
    muestras es la cantidad de puntos a calcular.
    '''
    tamano = muestras + 1
    tabla = np.zeros(shape=(tamano,6),dtype=float)
    # incluye el punto [x0,y0]
    tabla[0] = [x0,y0,0,0,0,0]
    x = x0
    y = y0
    for i in range(1,tamano,1):
        d1yi = d1y(x,y)
        d2yi = d2y(x,y)
        y = y + h*d1yi + ((h**2)/2)*d2yi
        x = x + h
        
        term1 = h*d1yi
        term2 = ((h**2)/2)*d2yi
        
        tabla[i] = [x,y,d1yi,d2yi,term1,term2]
    if vertabla==True:
        np.set_printoptions(precision)
        print(' EDO con Taylor 3 términos')
        print('i,[xi, yi, d1yi, d2yi, término 1, término 2 ]')
        for i in range(0,tamano,1):
            print(i,tabla[i])
        
    return(tabla)

 
# PROGRAMA PRUEBA -----------------
# Ref Rodriguez 9.1.1 p335 ejemplo.
# prueba y'-y-x+(x**2)-1 =0, y(0)=1
 
# INGRESO.
# d1y = y', d2y = y''
d1y = lambda x,y: y - x**2 + x + 1
d2y = lambda x,y: y - x**2 - x + 2
x0 = 0
y0 = 1
h = 0.1
muestras = 15+1
 
# PROCEDIMIENTO
tabla = edo_taylor3t(d1y,d2y,x0,y0,h,muestras)
n = len(tabla)
 
# SALIDA
print('EDO con Taylor 3 términos')
print('i,[xi, yi, d1yi, d2yi, término 1, término 2 ]')
for i in range(0,n,1):
    print(i,tabla[i])

# GRAFICA  --------------------
import matplotlib.pyplot as plt

titulo = 'EDO con Taylor 3 términos'
i = muestras # iteración en gráfica

titulo = titulo+', i='+str(i)
xi = tabla[:,0]
yi = tabla[:,1]
d1yi = tabla[:,2]
d2yi = tabla[:,3]

plt.plot(xi[0:i+2],yi[0:i+2]) # iteraciones
plt.plot(xi[0],yi[0],'o',
         color='red', label ='[x0,y0]')
plt.plot(xi[1:i+2],yi[1:i+2],'o',
         color='green', label ='[x[i],y[i]]')

if i<muestras: # gráfica para una iteración
    plt.plot(xi[i+1],yi[i+1],'o',color='orange',
             label ='[x[i+1],y[i+1]]')
    plt.plot(xi[i:i+3],yi[i:i+3],'.',color='gray')
    plt.plot(xi[i:i+2],[yi[i],yi[i]], color='orange',
             label='h',linestyle='dashed')
    term_1 = h*d1yi[i+1]
    plt.plot([xi[i+1],xi[i+1]],[yi[i],yi[i]+term_1],
             color='green',label='term2',linestyle='dashed')
    term_2 = (h**2)/2*d2yi[i+1]
    plt.plot([xi[i+1],xi[i+1]],[yi[i]+term_1,yi[i]+term_1+term_2],
             color='magenta',label='term3',linestyle='dashed')
# entorno de gráfica
plt.title(titulo)
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.grid()
plt.tight_layout()
# plt.show() #comentar para la siguiente gráfica

# GRAFICA CON ANIMACION --------
# import matplotlib.pyplot as plt
import matplotlib.animation as animation

unmetodo = 'Edo con Taylor 3 términos'
narchivo = 'EdoTaylor3t' # nombre archivo GIF

# Puntos para la gráfica
a = xi[0]
b = xi[1]
term1 = tabla[:,4]
term2 = tabla[:,5]
dfi = tabla[:,2]
n = len(xi)

# Parametros de trama/foto
retardo = 1000   # milisegundos entre tramas
tramas = len(xi)

# GRAFICA animada en fig_ani
fig_ani, graf_ani = plt.subplots()
ymax = np.max([yi[0],yi[2]])
ymin = np.min([yi[0],yi[2]])
deltax = np.abs(xi[2]-xi[0])
deltay = np.abs(yi[2]-yi[0])
graf_ani.set_xlim([xi[0],xi[2]+0.05*deltax])
graf_ani.set_ylim([ymin-0.05*deltay,ymax+0.05*deltay])
# Lineas y puntos base
linea_fx, = graf_ani.plot(xi, yi,color='blue',
                          linestyle='dashed')
puntof, = graf_ani.plot(xi[0], yi[0],'o',
                        color='green',
                        label='xi,yi')
puntoa, = graf_ani.plot(xi[0], yi[0],'o',
                        color='Blue')
puntob, = graf_ani.plot(xi[1], yi[1],'o',
                        color='orange')

linea_h, = graf_ani.plot(xi, xi, color='orange',
                         label='h',
                         linestyle='dashed')
linea_term1, = graf_ani.plot(xi, xi,
                             color='green',label="h*y'[i]",
                             linestyle='dashed')
linea_term2, = graf_ani.plot(xi, yi, linewidth=4,
                             color='magenta',
                             label="((h**2)/2!)*y''[i]")
# Aproximacion con tangente
b0 = yi[0] - dfi[1]*xi[0]
tangentei = dfi[1]*xi + b0
linea_tang, = graf_ani.plot(xi, tangentei, color='dodgerblue',
                             label="tangente",
                             linestyle='dotted')

# Cuadros de texto en gráfico
txt_i  = graf_ani.text(xi[0], yi[0]+0.03*deltay,'[x[i],y[i]]',
                       horizontalalignment='center')
txt_i1 = graf_ani.text(xi[1], xi[1]+0.03*deltay,'[x[i+1],y[i+1]]',
                       horizontalalignment='center')
txt_titulo = graf_ani.set_title(unmetodo)

# Configura gráfica
graf_ani.axhline(0, color='black')  # Linea horizontal en cero
graf_ani.set_xlabel('x')
graf_ani.set_ylabel('f(x)')
graf_ani.legend()
graf_ani.grid()

# Nueva Trama
def unatrama(i,xi,yi,dfi,term1,term2):
    
    if i>1:
        ymax = np.max([yi[0:i+2]])
        ymin = np.min([yi[0:i+2]])
        deltax = np.abs(xi[i+1]-xi[0])
        deltay = np.abs(ymax-ymin)
        graf_ani.set_xlim([xi[0]-0.05*deltax,xi[i+1]+0.05*deltax])
        graf_ani.set_ylim([ymin-0.05*deltay,ymax+0.1*deltay])
    else:
        ymax = np.max([yi[0],yi[2]])
        ymin = np.min([yi[0],yi[2]])
        deltax = np.abs(xi[2]-xi[0])
        deltay = np.abs(ymax-ymin)
        graf_ani.set_xlim([xi[0]-0.05*deltax,xi[2]+0.05*deltax])
        graf_ani.set_ylim([ymin-0.05*deltay,ymax+0.1*deltay])
    # actualiza cada punto
    puntoa.set_xdata([xi[i]]) 
    puntoa.set_ydata([yi[i]])
    puntob.set_xdata([xi[i+1]]) 
    puntob.set_ydata([yi[i+1]])
    puntof.set_xdata([xi[0:i]]) 
    puntof.set_ydata([yi[0:i]])
    # actualiza cada linea
    linea_fx.set_xdata(xi[0:i+1])
    linea_fx.set_ydata(yi[0:i+1])
    linea_h.set_xdata([xi[i],xi[i+1]])
    linea_h.set_ydata([yi[i],yi[i]])
    linea_term1.set_xdata([xi[i+1],xi[i+1]])
    linea_term1.set_ydata([yi[i],yi[i]+term1[i+1]])
    linea_term2.set_xdata([xi[i+1],xi[i+1]])
    linea_term2.set_ydata([yi[i]+term1[i+1],
                           yi[i]+term1[i+1]+term2[i+1]])
    
    b0 = yi[i] - dfi[i+1]*xi[i]
    tangentei = dfi[i+1]*xi + b0
    linea_tang.set_ydata(tangentei)
    # actualiza texto
    txt_i.set_position([xi[i], yi[i]+0.03*deltay])
    txt_i1.set_position([xi[i+1], yi[i+1]+0.03*deltay])
    txt_titulo.set_text(unmetodo+', i='+str(i))

    return (puntoa,puntob,puntof,
            linea_fx,linea_h,linea_tang,
            linea_term1,linea_term2,
            txt_i,txt_i1)
# Limpia Trama anterior
def limpiatrama(): 
    puntoa.set_ydata(np.ma.array(xi, mask=True))
    puntob.set_ydata(np.ma.array(xi, mask=True))
    puntof.set_ydata(np.ma.array(xi, mask=True))
    linea_h.set_ydata(np.ma.array(xi, mask=True))
    linea_term1.set_ydata(np.ma.array(xi, mask=True))
    linea_term2.set_ydata(np.ma.array(xi, mask=True))
    linea_tang.set_ydata(np.ma.array(xi, mask=True))
    return (puntoa,puntob,puntof,
            linea_fx,linea_h,linea_tang,
            linea_term1,linea_term2,
            txt_i,txt_i1)

# Trama contador
i = np.arange(0,tramas-1,1)
ani = animation.FuncAnimation(fig_ani,
                              unatrama,
                              i ,
                              fargs = (xi,yi,dfi,term1,term2),
                              init_func = limpiatrama,
                              interval = retardo,
                              blit=False)
# Graba Archivo GIFAnimado y video
ani.save(narchivo+'_ani.gif', writer='pillow')
# ani.save(narchivo+'_video.mp4')
plt.draw()
plt.show()

animación:

EDO Taylor 3t

Runge Kutta  dy/dx

Runge Kutta d2y/dx2

Sistemas EDO con RK


Runge Kutta de 2do Orden para primera derivada

EDO Runge-Kutta 2 orden df/dx_gráfico animado
EDO dy/dx con Runge-Kutta 2 Orden
i, [xi,     yi,     K1,    K2]
0 [0. 1. 0. 0.]
1 [0.1    1.2145 0.2    0.229 ]
2 [0.2       1.4599725 0.23045   0.260495 ]
3 [0.3        1.73756961 0.26199725 0.29319698]
4 [0.4        2.04856442 0.29475696 0.32723266]
5 [0.5        2.39436369 0.32885644 0.36274209]
6 [0.6        2.77652187 0.36443637 0.39988001]
7 [0.7        3.19675667 0.40165219 0.43881741]
8 [0.8        3.65696612 0.44067567 0.47974323]
9 [0.9        4.15924756 0.48169661 0.52286627]
10 [1.         4.70591856 0.52492476 0.56841723]
11 [1.1        5.29954001 0.57059186 0.61665104]
12 [1.2        5.94294171 0.618954   0.6678494 ]
13 [1.3        6.63925059 0.67029417 0.72232359]
14 [1.4        7.3919219  0.72492506 0.78041756]
15 [1.5        8.2047737  0.78319219 0.84251141]
16 [1.6        9.08202493 0.84547737 0.90902511]

Instrucciones en Python

# EDO dy/dx. M todo de RungeKutta 2do Orden 
# estima la solucion para muestras espaciadas h en eje x
# valores iniciales x0,y0, entrega tabla[xi,yi,K1,K2]
import numpy as np
 
# INGRESO
# d1y = y' = f
d1y = lambda x,y: y -x**2 + x + 1
x0 = 0
y0 = 1
h  = 0.1
muestras = 15+1
 
# algoritmos como funcion
def rungekutta2(d1y,x0,y0,h,muestras,
                vertabla=False,precision=6):
    '''solucion a EDO dy/dx, con Runge Kutta de 2do orden
    d1y es la expresion dy/dx, tambien planteada como f(x,y),
    valores iniciales: x0,y0, tamano de paso h.
    muestras es la cantidad de puntos a calcular. 
    '''
    tamano = muestras + 1
    tabla = np.zeros(shape=(tamano,2+2),dtype=float)
    tabla[0] = [x0,y0,0,0] # incluye el punto [x0,y0]
     
    xi = x0 # valores iniciales
    yi = y0
    for i in range(1,tamano,1):
        K1 = h * d1y(xi,yi)
        K2 = h * d1y(xi+h, yi + K1)
 
        yi = yi + (K1+K2)/2
        xi = xi + h
         
        tabla[i] = [xi,yi,K1,K2]
        
    if vertabla==True:
        np.set_printoptions(precision)
        print( 'EDO dy/dx con Runge-Kutta 2 Orden')
        print('i, [xi,     yi,     K1,    K2]')
        for i in range(0,tamano,1):
            print(i,tabla[i])
 
    return(tabla)
 
# PROCEDIMIENTO
tabla = rungekutta2(d1y,x0,y0,h,muestras)
n = len(tabla)
 
# SALIDA
print('EDO dy/dx con Runge-Kutta 2 Orden')
print('i, [xi,     yi,     K1,    K2]')
for i in range(0,n,1):
    print(i,tabla[i])

# GRAFICA  --------------------
import matplotlib.pyplot as plt
 
titulo = 'EDO dy/dx con Runge-Kutta 2 Orden'
i = muestras # iteración en gráfica
 
titulo = titulo+', i='+str(i)
xi = tabla[:,0]
yi = tabla[:,1]
K1 = tabla[:,2]
K2 = tabla[:,3]
 
plt.plot(xi[0:i+2],yi[0:i+2]) # iteraciones
plt.plot(xi[0],yi[0],'o',
         color='red', label ='[x0,y0]')
plt.plot(xi[1:i+2],yi[1:i+2],'o',
         color='green', label ='[x[i],y[i]]')
 
if i<muestras: # gráfica para una iteración
    plt.plot(xi[i+1],yi[i+1],'o',color='orange',
             label ='[x[i+1],y[i+1]]')
    plt.plot(xi[i:i+3],yi[i:i+3],'.',color='gray')
    plt.plot(xi[i:i+2],[yi[i],yi[i]], color='orange',
             label='h',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]-0.02*h],
             [yi[i],yi[i]+K1[i+1]],
             color='green',label='K1',linestyle='dashed')
    plt.plot([xi[i+1]+0.02*h,xi[i+1]+0.02*h],
             [yi[i],yi[i]+K2[i+1]],
             color='magenta',label='K2',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]+0.02*h],
             [yi[i]+K1[i+1],yi[i]+K2[i+1]],
             color='magenta')
# entorno de gráfica
plt.title(titulo)
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.grid()
plt.tight_layout()
plt.show() # plt.show() #comentar para la siguiente gráfica

# GRAFICA CON ANIMACION --------
# import matplotlib.pyplot as plt
import matplotlib.animation as animation
 
unmetodo = 'EDO: Runge-Kutta 2do Orden primera derivada'
narchivo = 'EdoRK2df' # nombre archivo GIF
muestras = 51
 
# Puntos para la gráfica
a = xi[0]
b = xi[1]
K1 = tabla[:,2]
K2 = tabla[:,3]
n = len(xi)
 
# Parametros de trama/foto
retardo = 1000   # milisegundos entre tramas
tramas = len(xi)
 
# GRAFICA animada en fig_ani
fig_ani, graf_ani = plt.subplots()
ymax = np.max([yi[0],yi[2]])
ymin = np.min([yi[0],yi[2]])
deltax = np.abs(xi[2]-xi[0])
deltay = np.abs(yi[2]-yi[0])
graf_ani.set_xlim([xi[0]-0.05*deltax,xi[2]+0.05*deltax])
graf_ani.set_ylim([ymin-0.05*deltay,ymax+0.1*deltay])
# Lineas y puntos base
linea_fx, = graf_ani.plot(xi, yi,color='blue',
                          linestyle='dashed')
puntof, = graf_ani.plot(xi[0], yi[0],'o',
                        color='green',
                        label='xi,yi')
puntoa, = graf_ani.plot(xi[0], yi[0],'o',
                        color='Blue')
puntob, = graf_ani.plot(xi[1], yi[1],'o',
                        color='orange')
 
linea_h, = graf_ani.plot(xi, xi, color='orange',
                         label='h',
                         linestyle='dashed')
linea_K1, = graf_ani.plot(xi-0.02*deltax, xi-0.02*deltax,
                          color='green',label="K1",
                          linestyle='dashed')
linea_K2, = graf_ani.plot(xi+0.02*deltax, yi,
                          color='magenta',
                          label="K2",
                          linestyle='dashed')
linea_K12, = graf_ani.plot(xi, yi,
                          color='magenta')
linea_tang, = graf_ani.plot(xi[0:2], yi[0:2],
                            color='dodgerblue',
                            linestyle='dotted')
 
# Cuadros de texto en gráfico
txt_i  = graf_ani.text(xi[0], yi[0]+0.05*deltay,'[x[i],y[i]]',
                       horizontalalignment='center')
txt_i1 = graf_ani.text(xi[1], xi[1]+0.05*deltay,'[x[i+1],y[i+1]]',
                       horizontalalignment='center')
txt_titulo = graf_ani.set_title(unmetodo)

# Configura gráfica
graf_ani.axhline(0, color='black')  # Linea horizontal en cero
graf_ani.set_xlabel('x')
graf_ani.set_ylabel('f(x)')
graf_ani.legend()
graf_ani.grid()
 
# Nueva Trama
def unatrama(i,xi,yi,term1,term2):   
    if i>1:
        ymax = np.max([yi[0:i+2]])
        ymin = np.min([yi[0:i+2]])
        deltax = np.abs(xi[i+1]-xi[0])
        deltay = np.abs(ymax-ymin)
        graf_ani.set_xlim([xi[0]-0.05*deltax,xi[i+1]+0.05*deltax])
        graf_ani.set_ylim([ymin-0.05*deltay,ymax+0.1*deltay])
    else:
        ymax = np.max([yi[0],yi[2]])
        ymin = np.min([yi[0],yi[2]])
        deltax = np.abs(xi[2]-xi[0])
        deltay = np.abs(ymax-ymin)
        graf_ani.set_xlim([xi[0]-0.05*deltax,xi[2]+0.05*deltax])
        graf_ani.set_ylim([ymin-0.05*deltay,ymax+0.1*deltay])
    # actualiza cada punto
    puntoa.set_xdata([xi[i]]) 
    puntoa.set_ydata([yi[i]])
    puntob.set_xdata([xi[i+1]]) 
    puntob.set_ydata([yi[i+1]])
    puntof.set_xdata(xi[0:i]) 
    puntof.set_ydata(yi[0:i])
    # actualiza cada linea
    linea_fx.set_xdata(xi[0:i+1])
    linea_fx.set_ydata(yi[0:i+1])
    linea_h.set_xdata([xi[i],xi[i+1]])
    linea_h.set_ydata([yi[i],yi[i]])
    linea_K1.set_xdata([xi[i+1]-0.02*deltax,xi[i+1]-0.02*deltax])
    linea_K1.set_ydata([yi[i],yi[i]+K1[i+1]])
    linea_K2.set_xdata([xi[i+1]+0.02*deltax,xi[i+1]+0.02*deltax])
    linea_K2.set_ydata([yi[i],yi[i]+K2[i+1]])
    linea_K12.set_xdata([xi[i+1]-0.02*deltax,xi[i+1]+0.02*deltax])
    linea_K12.set_ydata([yi[i]+K1[i+1],yi[i]+K2[i+1]])
    linea_tang.set_xdata([xi[i],xi[i+1]])
    linea_tang.set_ydata([yi[i],yi[i+1]])
    # actualiza texto
    txt_i.set_position([xi[i], yi[i]+0.05*deltay])
    txt_i1.set_position([xi[i+1], yi[i+1]+0.05*deltay])
    txt_titulo.set_text(unmetodo+', i='+str(i))
 
    return (puntoa,puntob,puntof,
            linea_fx,linea_h,linea_K1,linea_K2,linea_K12,
            linea_tang,txt_i,txt_i1,)
# Limpia Trama anterior
def limpiatrama(): 
    puntoa.set_ydata(np.ma.array(xi, mask=True))
    puntob.set_ydata(np.ma.array(xi, mask=True))
    puntof.set_ydata(np.ma.array(xi, mask=True))
    linea_h.set_ydata(np.ma.array(xi, mask=True))
    linea_K1.set_ydata(np.ma.array(xi, mask=True))
    linea_K2.set_ydata(np.ma.array(xi, mask=True))
    linea_K12.set_ydata(np.ma.array(xi, mask=True))
    linea_tang.set_ydata(np.ma.array(xi, mask=True))
    return (puntoa,puntob,puntof,
            linea_fx,linea_h,linea_K1,linea_K2,linea_K12,
            linea_tang,txt_i,txt_i1,)
 
# Trama contador
i = np.arange(0,tramas-1,1)
ani = animation.FuncAnimation(fig_ani,
                              unatrama,
                              i ,
                              fargs = (xi,yi,K1,K2),
                              init_func = limpiatrama,
                              interval = retardo,
                              blit=False)
# Graba Archivo GIFAnimado y video
ani.save(narchivo+'_ani.gif', writer='pillow')
# ani.save(narchivo+'_video.mp4')
plt.draw()
plt.show()

animación:

EDO Taylor 3t

Runge Kutta  dy/dx

Runge Kutta d2y/dx2

Sistemas EDO con RK


Runge Kutta de 2do Orden para Segunda derivada

EDO Runge-Kutta 2Orden d2y/dx2 gráfica animada
# EDO d2y/dx2. Método de RungeKutta 2do Orden 
# estima la solucion para muestras espaciadas h en eje x
# valores iniciales x0,y0,z0 entrega tabla[xi,yi,zi,K1y,K1z,K2y,K2z]
import numpy as np
 
# INGRESO
# 2Eva_IT2018_T1 Paracaidista wingsuit
f = lambda t,y,v: -v # el signo, revisar diagrama cuerpo libre
g = lambda t,y,v: 9.8 - (0.225/90)*(v**2)
t0 = 0
y0 = 1000
v0 = 0
h  = 2
muestras = 14+1
 
# Algoritmo como función
def rungekutta2_fg(f,g,x0,y0,z0,h,muestras,
                   vertabla=False, precision=6):
    ''' solucion a EDO d2y/dx2 con Runge-Kutta 2do Orden,
    f(x,y,z) = z #= y'
    g(x,y,z) = expresion d2y/dx2 con z=y'
    tambien es solucion a sistemas edo f() y g()
    x0,y0,z0 son valores iniciales, h es tamano de paso,
    muestras es la cantidad de puntos a calcular.
    '''
    tamano = muestras + 1
    tabla = np.zeros(shape=(tamano,3+4),dtype=float)
    # incluye el punto [x0,y0,z0,K1y,K1z,K2y,K2z]
    tabla[0] = [x0,y0,z0,0,0,0,0]
     
    xi = x0 # valores iniciales
    yi = y0
    zi = z0
    for i in range(1,tamano,1):
        K1y = h * f(xi,yi,zi)
        K1z = h * g(xi,yi,zi)
         
        K2y = h * f(xi+h, yi + K1y, zi + K1z)
        K2z = h * g(xi+h, yi + K1y, zi + K1z)
 
        yi = yi + (K1y+K2y)/2
        zi = zi + (K1z+K2z)/2
        xi = xi + h
         
        tabla[i] = [xi,yi,zi,K1y,K1z,K2y,K2z]
         
    if vertabla==True:
        np.set_printoptions(precision)
        print('EDO f,g con Runge-Kutta 2 Orden')
        print('i ','[ xi,  yi,  zi',']')
        print('   [ K1y,  K1z,  K2y,  K2z ]')
        for i in range(0,tamano,1):  
            txt = ' '
            if i>=10:
                txt = '  '
            print(str(i),tabla[i,0:3])
            print(txt,tabla[i,3:])
     
    return(tabla)
 
# PROCEDIMIENTO
tabla = rungekutta2_fg(f,g,t0,y0,v0,h,muestras,
                       vertabla=True, precision=4)
# SALIDA
##print('EDO f,g con Runge-Kutta 2 Orden')
##print('i ','[ xi,  yi,  zi',']')
##print('   [ K1y,  K1z,  K2y,  K2z ]')
##for i in range(0,tamano,1):  
##    txt = ' '
##    if i>=10:
##        txt = '  '
##    print(str(i),tabla[i,0:3])
##    print(txt,tabla[i,3:])

# GRAFICA ---------------------
import matplotlib.pyplot as plt
 
titulo = 'EDO Runge-Kutta 2ord - Paracaidista Wingsuit'
i = muestras # iteración en gráfica
 
titulo = titulo+', i='+str(i)
xi = tabla[:,0]
yi = tabla[:,1]
zi = tabla[:,2]
K1y = tabla[:,3]
K1z = tabla[:,4]
K2y = tabla[:,5]
K2z = tabla[:,6]
 
plt.subplot(211)
plt.plot(xi[0],yi[0],'o',
         color='red', label ='[t0,y0]')
plt.plot(xi[1:i+2],yi[1:i+2],'o',
         color='green', label ='[t[i],y[i]]')
plt.plot(xi[0:i+2],yi[0:i+2],
         color='blue',label='y(t)')
if i<muestras: # gráfica para una iteración
    plt.plot(xi[i+1],yi[i+1],'o',color='orange',
             label ='[x[i+1],y[i+1]]')
    plt.plot(xi[i:i+3],yi[i:i+3],'.',color='gray')
    plt.plot(xi[i:i+2],[yi[i],yi[i]], color='orange',
             label='h',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]-0.02*h],
             [yi[i],yi[i]+K1y[i+1]],
             color='green',label='K1y',linestyle='dashed')
    plt.plot([xi[i+1]+0.02*h,xi[i+1]+0.02*h],
             [yi[i],yi[i]+K2y[i+1]],
             color='magenta',label='K2y',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]+0.02*h],
             [yi[i]+K1y[i+1],yi[i]+K2y[i+1]],
             color='magenta')
if np.min(yi[0:i+1])<0: # linea 0
    plt.axhline(0, color='red')
plt.ylabel('y = Altura')
plt.title(titulo)
plt.legend()
plt.grid()
plt.tight_layout()
 
plt.subplot(212)
plt.plot(xi[0],zi[0],'o',
         color='red', label ='[t0,v0]')
plt.plot(xi[1:i+2],zi[1:i+2],'o',
         color='green', label ='[t[i],v[i]]')
plt.plot(xi[0:i+2],zi[0:i+2],
         color='green',label='v(t)')
if i<muestras: # gráfica para una iteración
    plt.plot(xi[i+1],zi[i+1],'o',color='orange',
             label ='[t[i+1],v[i+1]]')
    plt.plot(xi[i:i+3],zi[i:i+3],'.',color='gray')
    plt.plot(xi[i:i+2],[zi[i],zi[i]], color='orange',
             label='h',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]-0.02*h],
             [zi[i],zi[i]+K1z[i+1]],
             color='green',label='K1z',linestyle='dashed')
    plt.plot([xi[i+1]+0.02*h,xi[i+1]+0.02*h],
             [zi[i],zi[i]+K2z[i+1]],
             color='magenta',label='K2z',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]+0.02*h],
             [zi[i]+K1z[i+1],zi[i]+K2z[i+1]],
             color='magenta')
 
plt.xlabel('x = tiempo')
plt.ylabel('z = velocidad')
plt.legend()
plt.grid()
plt.tight_layout()
 
#plt.show() #comentar para la siguiente gráfica

# GRAFICA CON ANIMACION --------
# import matplotlib.pyplot as plt
import matplotlib.animation as animation
  
unmetodo = 'EDO Runge-Kutta 2ord - Paracaidista Wingsuit'
narchivo = 'EdoRK_Wingsuit' # nombre archivo GIF
muestras = 51
  
# Puntos para la gráfica
n = len(xi)
  
# Parametros de trama/foto
retardo = 1000   # milisegundos entre tramas
tramas = len(xi)
  
# GRAFICA animada en fig_ani
fig_ani, (graf1_ani,graf2_ani) = plt.subplots(2)
ymax = np.max([yi[0],yi[2]])
ymin = np.min([yi[0],yi[2]])
deltax = np.abs(xi[2]-xi[0])
deltay = np.abs(yi[2]-yi[0])
graf1_ani.set_xlim([xi[0],xi[2]+0.05*deltax])
graf1_ani.set_ylim([ymin-0.05*deltay,ymax+0.05*deltay])
  
zmax = np.max([zi[0],zi[2]])
zmin = np.min([zi[0],zi[2]])
deltax = np.abs(xi[2]-xi[0])
deltaz = np.abs(zi[2]-zi[0])
graf2_ani.set_xlim([xi[0],xi[2]+0.05*deltax])
graf2_ani.set_ylim([zmin-0.05*deltaz,zmax+0.05*deltaz])
# Lineas y puntos base
linea_fx, = graf1_ani.plot(xi, yi,color='blue',
                           linestyle='dashed')
puntof, = graf1_ani.plot(xi[0], yi[0],'o',
                         color='blue',label='[xi,yi]')
puntoa, = graf1_ani.plot(xi[0], yi[0],'o',
                         color='orange')
puntob, = graf1_ani.plot(xi[1], yi[1],'o',
                         color='magenta')
linea_h, = graf1_ani.plot(xi, xi, color='orange',
                          linestyle='dashed',label='h')
linea_term1, = graf1_ani.plot(xi, xi,color='magenta',
                              linestyle='dashed',
                              label="(K1y+K2y)/2")
 
# Cuadros de texto en gráfico
#txt_i  = graf1_ani.text(xi[0], yi[0]+0.03*deltay,'[x[i],y[i]]',
#                       horizontalalignment='center')
#txt_i1 = graf1_ani.text(xi[1], xi[1]+0.03*deltay,'[x[i+1],y[i+1]]',
#                       horizontalalignment='center')
txt_titulo = graf1_ani.set_title(unmetodo)
  
linea_gx, = graf2_ani.plot(xi, zi,color='green',
                           linestyle='dashed')
puntog, = graf2_ani.plot(xi[0], zi[0],'o',
                         color='green',label='[xi,zi]')
puntog_a, = graf2_ani.plot(xi[0], zi[0],'o',
                           color='orange')
puntog_b, = graf2_ani.plot(xi[1], zi[1],'o',
                           color='magenta')
lineag_h, = graf2_ani.plot(xi, xi, color='orange',
                           linestyle='dashed',label='h')
lineag_term1, = graf2_ani.plot(xi, xi,
                               color='magenta',
                               linestyle='dashed',
                               label="(K1z+K2z)/2")
# Configura gráfica
graf1_ani.axhline(0, color='black')  # Linea horizontal en cero
graf1_ani.set_title(unmetodo)
graf1_ani.set_xlabel('x')
graf1_ani.set_ylabel('y(x)')
graf1_ani.legend()
graf1_ani.grid()
  
graf2_ani.axhline(0, color='black')  # Linea horizontal en cero
#graf2_ani.set_title(unmetodo)
graf2_ani.set_xlabel('x')
graf2_ani.set_ylabel('z(x)')
graf2_ani.legend()
graf2_ani.grid()
  
# Nueva Trama
def unatrama(i,xi,yi,zi):
      
    if i>0:
        ymax = np.max([yi[0:i+2]])
        ymin = np.min([yi[0:i+2]])
        deltax = np.abs(xi[i+1]-xi[0])
        deltay = np.abs(ymax-ymin)
        graf1_ani.set_xlim([xi[0]-0.05*deltax,xi[i+1]+0.05*deltax])
        graf1_ani.set_ylim([ymin-0.05*deltay,ymax+0.1*deltay])
  
        zmax = np.max([zi[0:i+2]])
        zmin = np.min([zi[0:i+2]])
        deltaz = np.abs(zmax-zmin)
        graf2_ani.set_xlim([xi[0]-0.05*deltax,xi[i+1]+0.05*deltax])
        graf2_ani.set_ylim([zmin-0.05*deltaz,zmax+0.1*deltaz])
    else:
        ymax = np.max([yi[0:2]])
        ymin = np.min([yi[0:2]])
        deltax = np.abs(xi[2]-xi[0])
        deltay = np.abs(ymax-ymin)
        graf1_ani.set_xlim([xi[0]-0.05*deltax,xi[2]+0.05*deltax])
        graf1_ani.set_ylim([ymin-0.05*deltay,ymax+0.1*deltay])
  
        zmax = np.max([zi[0:2]])
        zmin = np.min([zi[0:2]])
        deltaz = np.abs(zmax-zmin)
        graf2_ani.set_xlim([xi[0]-0.05*deltax,xi[2]+0.05*deltax])
        graf2_ani.set_ylim([zmin-0.05*deltaz,zmax+0.1*deltaz])
    # actualiza cada punto
    puntoa.set_xdata([xi[i]]) 
    puntoa.set_ydata([yi[i]])
    puntob.set_xdata([xi[i+1]]) 
    puntob.set_ydata([yi[i+1]])
    if i<20:
        puntof.set_xdata(xi[0:i]) 
        puntof.set_ydata(yi[0:i])
    # actualiza cada linea
    linea_fx.set_xdata(xi[0:i+1])
    linea_fx.set_ydata(yi[0:i+1])
    linea_h.set_xdata([xi[i],xi[i+1]])
    linea_h.set_ydata([yi[i],yi[i]])
    linea_term1.set_xdata([xi[i+1],xi[i+1]])
    linea_term1.set_ydata([yi[i],yi[i+1]])
    # actualiza texto
    #txt_i.set_position([xi[i], yi[i]+0.03*deltay])
    #txt_i1.set_position([xi[i+1], yi[i+1]+0.03*deltay])
  
    # actualiza cada punto
    puntog_a.set_xdata([xi[i]]) 
    puntog_a.set_ydata([zi[i]])
    puntog_b.set_xdata([xi[i+1]]) 
    puntog_b.set_ydata([zi[i+1]])
    if i<20:
        puntog.set_xdata(xi[0:i]) 
        puntog.set_ydata(zi[0:i])
    # actualiza cada linea
    linea_gx.set_xdata(xi[0:i+1])
    linea_gx.set_ydata(zi[0:i+1])
    lineag_h.set_xdata([xi[i],xi[i+1]])
    lineag_h.set_ydata([zi[i],zi[i]])
    lineag_term1.set_xdata([xi[i+1],xi[i+1]])
    lineag_term1.set_ydata([zi[i],zi[i+1]])
    txt_titulo.set_text(unmetodo+', i='+str(i))
  
    return (puntoa,puntob,puntof,
            linea_fx,linea_h,
            linea_term1,
            puntog_a,puntog_b,puntog,
            linea_gx,lineag_h,
            lineag_term1,)
            #txt_i,txt_i1,)
 
# Limpia Trama anterior
def limpiatrama(): 
    puntoa.set_ydata(np.ma.array(xi, mask=True))
    puntob.set_ydata(np.ma.array(xi, mask=True))
    puntof.set_ydata(np.ma.array(xi, mask=True))
    linea_h.set_ydata(np.ma.array(xi, mask=True))
    linea_term1.set_ydata(np.ma.array(xi, mask=True))
  
    puntog_a.set_ydata(np.ma.array(xi, mask=True))
    puntog_b.set_ydata(np.ma.array(xi, mask=True))
    puntog.set_ydata(np.ma.array(xi, mask=True))
    lineag_h.set_ydata(np.ma.array(xi, mask=True))
    lineag_term1.set_ydata(np.ma.array(xi, mask=True))
    return (puntoa,puntob,puntof,
            linea_fx,linea_h,
            linea_term1,
            puntog_a,puntog_b,puntog,
            linea_gx,lineag_h,
            lineag_term1,)
            #txt_i,txt_i1,)
  
# Trama contador
i = np.arange(0,tramas-1,1)
ani = animation.FuncAnimation(fig_ani,
                              unatrama,
                              i ,
                              fargs = (xi,yi,zi),
                              init_func = limpiatrama,
                              interval = retardo,
                              blit=False)
# Graba Archivo GIFAnimado y video
ani.save(narchivo+'_ani.gif', writer='pillow')
# ani.save(narchivo+'_video.mp4')
plt.draw()
plt.show()


animación:

EDO Taylor 3t

Runge Kutta  dy/dx

Runge Kutta d2y/dx2

Sistemas EDO con RK


Sistemas EDO. modelo depredador-presa con Runge-Kutta 2do Orden
.

EDO Sistema Runge-Kutta presa-predador gráfica animada

Instrucciones en Python

# Modelo predador-presa de Lotka-Volterra
# Sistemas EDO con Runge Kutta de 2do Orden
import numpy as np

# INGRESO
# Parámetros de las ecuaciones
a = 0.5
b = 0.7
c = 0.35
d = 0.35

# Ecuaciones
f = lambda t,x,y : a*x -b*x*y
g = lambda t,x,y : -c*y + d*x*y

# Condiciones iniciales
t0 = 0
x0 = 2
y0 = 1

# parámetros del algoritmo
h = 0.5
muestras = 101

# Algoritmo como función
def rungekutta2_fg(f,g,x0,y0,z0,h,muestras,
                   vertabla=False, precision=6):
    ''' solucion a EDO d2y/dx2 con Runge-Kutta 2do Orden,
    f(x,y,z) = z #= y'
    g(x,y,z) = expresion d2y/dx2 con z=y'
    tambien es solucion a sistemas edo f() y g()
    x0,y0,z0 son valores iniciales, h es tamano de paso,
    muestras es la cantidad de puntos a calcular.
    '''
    tamano = muestras + 1
    tabla = np.zeros(shape=(tamano,3+4),dtype=float)
    # incluye el punto [x0,y0,z0,K1y,K1z,K2y,K2z]
    tabla[0] = [x0,y0,z0,0,0,0,0]
     
    xi = x0 # valores iniciales
    yi = y0
    zi = z0
    for i in range(1,tamano,1):
        K1y = h * f(xi,yi,zi)
        K1z = h * g(xi,yi,zi)
         
        K2y = h * f(xi+h, yi + K1y, zi + K1z)
        K2z = h * g(xi+h, yi + K1y, zi + K1z)
 
        yi = yi + (K1y+K2y)/2
        zi = zi + (K1z+K2z)/2
        xi = xi + h
         
        tabla[i] = [xi,yi,zi,K1y,K1z,K2y,K2z]
         
    if vertabla==True:
        np.set_printoptions(precision)
        print('EDO f,g con Runge-Kutta 2 Orden')
        print('i ','[ xi,  yi,  zi',']')
        print('   [ K1y,  K1z,  K2y,  K2z ]')
        for i in range(0,tamano,1):  
            txt = ' '
            if i>=10:
                txt = '  '
            print(str(i),tabla[i,0:3])
            print(txt,tabla[i,3:])
     
    return(tabla)

# PROCEDIMIENTO
tabla = rungekutta2_fg(f,g,t0,x0,y0,h,
                       muestras,vertabla=True)
# SALIDA
print('Sistemas EDO: Modelo presa-predador')
##print('i ','[ xi,  yi,  zi',']')
##print('   [ K1y,  K1z,  K2y,  K2z ]')
##for i in range(0,tamano,1):  
##    txt = ' '
##    if i>=10:
##        txt = '  '
##    print(str(i),tabla[i,0:3])
##    print(txt,tabla[i,3:])

# GRAFICA ---------------------
import matplotlib.pyplot as plt
 
titulo = 'Sistemas EDO Runge-Kutta 2ord - Modelo predador-presa'
i = muestras # iteración en gráfica
 
titulo = titulo+', i='+str(i)
xi = tabla[:,0]
yi = tabla[:,1]
zi = tabla[:,2]
K1y = tabla[:,3]
K1z = tabla[:,4]
K2y = tabla[:,5]
K2z = tabla[:,6]
 
plt.subplot(211)
plt.plot(xi[0],yi[0],'o',
         color='red', label ='[t0,y0]')
if i<20: # evita muchos puntos
    plt.plot(xi[1:i+2],yi[1:i+2],'o',
             color='green', label ='[t[i],y[i]]')
plt.plot(xi[0:i+2],yi[0:i+2],
         color='blue',label='y(t)')
if i<muestras: # gráfica para una iteración
    plt.plot(xi[i+1],yi[i+1],'o',color='orange',
             label ='[x[i+1],y[i+1]]')
    plt.plot(xi[i:i+3],yi[i:i+3],'.',color='gray')
    plt.plot(xi[i:i+2],[yi[i],yi[i]], color='orange',
             label='h',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]-0.02*h],
             [yi[i],yi[i]+K1y[i+1]],
             color='green',label='K1y',linestyle='dashed')
    plt.plot([xi[i+1]+0.02*h,xi[i+1]+0.02*h],
             [yi[i],yi[i]+K2y[i+1]],
             color='magenta',label='K2y',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]+0.02*h],
             [yi[i]+K1y[i+1],yi[i]+K2y[i+1]],
             color='magenta')
if np.min(yi[0:i+1])<0: # linea 0
    plt.axhline(0, color='red')
plt.ylabel('y = presa')
plt.title(titulo)
plt.legend()
plt.grid()
plt.tight_layout()
 
plt.subplot(212)
plt.plot(xi[0],zi[0],'o',
         color='red', label ='[t0,z0]')
if i<20: # evita muchos puntos
    plt.plot(xi[1:i+2],zi[1:i+2],'o',
             color='green', label ='[t[i],v[i]]')
plt.plot(xi[0:i+2],zi[0:i+2],
         color='green',label='z(t)')
if i<muestras: # gráfica para una iteración
    plt.plot(xi[i+1],zi[i+1],'o',color='orange',
             label ='[t[i+1],z[i+1]]')
    plt.plot(xi[i:i+3],zi[i:i+3],'.',color='gray')
    plt.plot(xi[i:i+2],[zi[i],zi[i]], color='orange',
             label='h',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]-0.02*h],
             [zi[i],zi[i]+K1z[i+1]],
             color='green',label='K1z',linestyle='dashed')
    plt.plot([xi[i+1]+0.02*h,xi[i+1]+0.02*h],
             [zi[i],zi[i]+K2z[i+1]],
             color='magenta',label='K2z',linestyle='dashed')
    plt.plot([xi[i+1]-0.02*h,xi[i+1]+0.02*h],
             [zi[i]+K1z[i+1],zi[i]+K2z[i+1]],
             color='magenta')
 
plt.xlabel('x = tiempo')
plt.ylabel('z = predador')
plt.legend()
plt.grid()
plt.tight_layout()
 
#plt.show() #comentar para la siguiente gráfica

# gráfica yi vs zi
titulo = 'Sistemas EDO Runge-Kutta 2ord - presa vs predador'
titulo = titulo+', i='+str(i)
fig_yz, graf3 = plt.subplots()
graf3.plot(yi,zi)
 
graf3.set_title(titulo)
graf3.set_xlabel('presa')
graf3.set_ylabel('predador')
graf3.grid()
#plt.show() #comentar para la siguiente gráfica


# GRAFICA CON ANIMACION --------
# import matplotlib.pyplot as plt
import matplotlib.animation as animation
 
unmetodo = 'Sistemas EDO Runge-Kutta 2ord - presa vs predador'
narchivo = 'EdoSistemaRK_presapredador' # nombre archivo GIF
muestras = 51
 
# Puntos para la gráfica
n = len(xi)
 
# Parametros de trama/foto
retardo = 1000   # milisegundos entre tramas
tramas = len(xi)
 
# GRAFICA animada en fig_ani
fig_ani, (graf1_ani,graf2_ani) = plt.subplots(2)
ymax = np.max([yi[0],yi[2]])
ymin = np.min([yi[0],yi[2]])
deltax = np.abs(xi[2]-xi[0])
deltay = np.abs(yi[2]-yi[0])
graf1_ani.set_xlim([xi[0],xi[2]+0.05*deltax])
graf1_ani.set_ylim([ymin-0.05*deltay,ymax+0.05*deltay])
 
zmax = np.max([zi[0],zi[2]])
zmin = np.min([zi[0],zi[2]])
deltax = np.abs(xi[2]-xi[0])
deltaz = np.abs(zi[2]-zi[0])
graf2_ani.set_xlim([xi[0],xi[2]+0.05*deltax])
graf2_ani.set_ylim([zmin-0.05*deltaz,zmax+0.05*deltaz])
# Lineas y puntos base
linea_fx, = graf1_ani.plot(xi, yi,color='blue',
                           linestyle='dashed')
puntof, = graf1_ani.plot(xi[0], yi[0],'o',
                         color='blue',label='[xi,yi]')
puntoa, = graf1_ani.plot(xi[0], yi[0],'o',
                         color='orange')
puntob, = graf1_ani.plot(xi[1], yi[1],'o',
                         color='magenta')
linea_h, = graf1_ani.plot(xi, xi, color='orange',
                          linestyle='dashed',label='h')
linea_term1, = graf1_ani.plot(xi, xi,color='magenta',
                              linestyle='dashed',
                              label="(K1y+K2y)/2")

# Cuadros de texto en gráfico
#txt_i  = graf1_ani.text(xi[0], yi[0]+0.03*deltay,'[x[i],y[i]]',
#                       horizontalalignment='center')
#txt_i1 = graf1_ani.text(xi[1], xi[1]+0.03*deltay,'[x[i+1],y[i+1]]',
#                       horizontalalignment='center')
txt_titulo = graf1_ani.set_title(unmetodo)
 
linea_gx, = graf2_ani.plot(xi, zi,color='green',
                           linestyle='dashed')
puntog, = graf2_ani.plot(xi[0], zi[0],'o',
                         color='green',label='[xi,zi]')
puntog_a, = graf2_ani.plot(xi[0], zi[0],'o',
                           color='orange')
puntog_b, = graf2_ani.plot(xi[1], zi[1],'o',
                           color='magenta')
lineag_h, = graf2_ani.plot(xi, xi, color='orange',
                           linestyle='dashed',label='h')
lineag_term1, = graf2_ani.plot(xi, xi,
                               color='magenta',
                               linestyle='dashed',
                               label="(K1z+K2z)/2")
# Configura gráfica
graf1_ani.axhline(0, color='black')  # Linea horizontal en cero
graf1_ani.set_title(unmetodo)
graf1_ani.set_xlabel('x')
graf1_ani.set_ylabel('y(x)')
graf1_ani.legend()
graf1_ani.grid()
 
graf2_ani.axhline(0, color='black')  # Linea horizontal en cero
#graf2_ani.set_title(unmetodo)
graf2_ani.set_xlabel('x')
graf2_ani.set_ylabel('z(x)')
graf2_ani.legend()
graf2_ani.grid()
 
# Nueva Trama
def unatrama(i,xi,yi,zi):
     
    if i>0:
        ymax = np.max([yi[0:i+2]])
        ymin = np.min([yi[0:i+2]])
        deltax = np.abs(xi[i+1]-xi[0])
        deltay = np.abs(ymax-ymin)
        graf1_ani.set_xlim([xi[0]-0.05*deltax,xi[i+1]+0.05*deltax])
        graf1_ani.set_ylim([ymin-0.05*deltay,ymax+0.1*deltay])
 
        zmax = np.max([zi[0:i+2]])
        zmin = np.min([zi[0:i+2]])
        deltaz = np.abs(zmax-zmin)
        graf2_ani.set_xlim([xi[0]-0.05*deltax,xi[i+1]+0.05*deltax])
        graf2_ani.set_ylim([zmin-0.05*deltaz,zmax+0.1*deltaz])
    else:
        ymax = np.max([yi[0:2]])
        ymin = np.min([yi[0:2]])
        deltax = np.abs(xi[2]-xi[0])
        deltay = np.abs(ymax-ymin)
        graf1_ani.set_xlim([xi[0]-0.05*deltax,xi[2]+0.05*deltax])
        graf1_ani.set_ylim([ymin-0.05*deltay,ymax+0.1*deltay])
 
        zmax = np.max([zi[0:2]])
        zmin = np.min([zi[0:2]])
        deltaz = np.abs(zmax-zmin)
        graf2_ani.set_xlim([xi[0]-0.05*deltax,xi[2]+0.05*deltax])
        graf2_ani.set_ylim([zmin-0.05*deltaz,zmax+0.1*deltaz])
    # actualiza cada punto
    puntoa.set_xdata([xi[i]]) 
    puntoa.set_ydata([yi[i]])
    puntob.set_xdata([xi[i+1]]) 
    puntob.set_ydata([yi[i+1]])
    if i<20:
        puntof.set_xdata(xi[0:i]) 
        puntof.set_ydata(yi[0:i])
    # actualiza cada linea
    linea_fx.set_xdata(xi[0:i+1])
    linea_fx.set_ydata(yi[0:i+1])
    linea_h.set_xdata([xi[i],xi[i+1]])
    linea_h.set_ydata([yi[i],yi[i]])
    linea_term1.set_xdata([xi[i+1],xi[i+1]])
    linea_term1.set_ydata([yi[i],yi[i+1]])
    # actualiza texto
    #txt_i.set_position([xi[i], yi[i]+0.03*deltay])
    #txt_i1.set_position([xi[i+1], yi[i+1]+0.03*deltay])
 
    # actualiza cada punto
    puntog_a.set_xdata([xi[i]]) 
    puntog_a.set_ydata([zi[i]])
    puntog_b.set_xdata([xi[i+1]]) 
    puntog_b.set_ydata([zi[i+1]])
    if i<20:
        puntog.set_xdata(xi[0:i]) 
        puntog.set_ydata(zi[0:i])
    # actualiza cada linea
    linea_gx.set_xdata(xi[0:i+1])
    linea_gx.set_ydata(zi[0:i+1])
    lineag_h.set_xdata([xi[i],xi[i+1]])
    lineag_h.set_ydata([zi[i],zi[i]])
    lineag_term1.set_xdata([xi[i+1],xi[i+1]])
    lineag_term1.set_ydata([zi[i],zi[i+1]])
    txt_titulo.set_text(unmetodo+', i='+str(i))
 
    return (puntoa,puntob,puntof,
            linea_fx,linea_h,
            linea_term1,
            puntog_a,puntog_b,puntog,
            linea_gx,lineag_h,
            lineag_term1,)
            #txt_i,txt_i1,)

# Limpia Trama anterior
def limpiatrama(): 
    puntoa.set_ydata(np.ma.array(xi, mask=True))
    puntob.set_ydata(np.ma.array(xi, mask=True))
    puntof.set_ydata(np.ma.array(xi, mask=True))
    linea_h.set_ydata(np.ma.array(xi, mask=True))
    linea_term1.set_ydata(np.ma.array(xi, mask=True))
 
    puntog_a.set_ydata(np.ma.array(xi, mask=True))
    puntog_b.set_ydata(np.ma.array(xi, mask=True))
    puntog.set_ydata(np.ma.array(xi, mask=True))
    lineag_h.set_ydata(np.ma.array(xi, mask=True))
    lineag_term1.set_ydata(np.ma.array(xi, mask=True))
    return (puntoa,puntob,puntof,
            linea_fx,linea_h,
            linea_term1,
            puntog_a,puntog_b,puntog,
            linea_gx,lineag_h,
            lineag_term1,)
            #txt_i,txt_i1,)
 
# Trama contador
i = np.arange(0,tramas-1,1)
ani = animation.FuncAnimation(fig_ani,
                              unatrama,
                              i ,
                              fargs = (xi,yi,zi),
                              init_func = limpiatrama,
                              interval = retardo,
                              blit=False)
# Graba Archivo GIFAnimado y video
ani.save(narchivo+'_ani.gif', writer='pillow')
# ani.save(narchivo+'_video.mp4')
plt.draw()
plt.show()

animación:

EDO Taylor 3t

Runge Kutta  dy/dx

Runge Kutta d2y/dx2

Sistemas EDO con RK


Unidades MN