s1Eva_IIT2019_T1 Ecuación Recursiva

la ecuación recursiva es:

x_n = g(x_{n-1}) = \sqrt{3 + x_{n-1}}

literal a y b

g(x) es creciente en todo el intervalo, con valor minimo en g(1) = 2, y máximo en g(3) =2.449. Por observación de la gráfica, la pendiente g(x) es menor que la recta identidad en todo el intervalo

Verifique la cota de g'(x)

g(x) = \sqrt{3 + x} =(3+x)^{1/2} g'(x) =\frac{1}{2}(3+x)^{-1/2} g'(x) =\frac{1}{2\sqrt{3+x}}

Tarea: verificar que g'(x) es menor que 1 en todo el intervalo.

Literal c

Usando el algoritmo del punto fijo, iniciando con el punto x0=2
y tolerancia de 10-4, se tiene que:

Iteración 1: x0=2

g(x_0) = \sqrt{3 + 2} = 2.2361

error = |2.2361 – 2| = 0.2361

Iteración 2: x1 = 2.2361

g(x_1) = \sqrt{3 + 2.2361} = 2.2882

error = |2.2882 – 2.2361| = 0.0522

Iteración 3: x2 = 2.2882

g(x_2) = \sqrt{3 + 2.2882} = 2.2996

error = |2.2996 – 2.28821| = 0.0114

Iteración 4: x3 = 2.2996

g(x_3) = \sqrt{3 + 2.2996} = 2.3021

error = |2.3021- 2.2996| = 0.0025

Iteración 5: x4 = 2.3021

g(x_4) = \sqrt{3 + 2.3021} = 2.3026

error = |2.3021- 2.2996| = 5.3672e-04

con lo que determina que el error en la 5ta iteración es de 5.3672e-04 y el error se reduce en casi 1/4 entre iteraciones. El punto fijo converge a 2.3028

Se muestra como referencia la tabla resumen.

[[ x ,   g(x), 	 tramo  ] 
 [1.      2.      1.    ]
 [2.      2.2361  0.2361]
 [2.2361  2.2882  0.0522]
 [2.2882  2.2996  0.0114]
 [2.2996  2.3021  0.0025]
 [2.3021  2.3026  5.3672e-04]
 [2.3026  2.3027  1.1654e-04]
 [2.3027  2.3028  2.5305e-05]
raiz:  2.3027686193257098

con el siguiente comportamiento de la funcion:

literal e

Realizando el mismo ejercicio para el método de la bisección, se requiere cambiar a la forma f(x)=0

x = \sqrt{3 + x} 0 = \sqrt{3 + x} -x f(x) = \sqrt{3 + x} -x

tomando como intervalo el mismo que el inicio del problema [1,3], al realizar las operaciones se tiene que:

a = 1 ; f(a) = 1
b = 3 ; f(b) = -0.551
c = (a+b)/2 = (1+3)/2 = 2
f(c) = f(2) = (3 + 2)^(.5) +2 = 0.236
Siendo f(c) positivo, y tamaño de paso 2, se reduce a 1

a = 2 ; f(a) = 0.236
b = 3 ; f(b) = -0.551
c = (a+b)/2 = (2+3)/2 = 2.5
f(c) = f(2.5) = (3 + 2.5)^(.5) +2.5 = -0.155
Siendo fc(c) negativo y tamaño de paso 1, se reduce a .5

a = 2
b = 2.5
...

Siguiendo las operaciones se obtiene la siguiente tabla:

[ i, a,   c,   b,    f(a),  f(c),  f(b), paso]
 1 1.000 2.000 3.000 1.000  0.236 -0.551 2.000 
 2 2.000 2.500 3.000 0.236 -0.155 -0.551 1.000 
 3 2.000 2.250 2.500 0.236  0.041 -0.155 0.500 
 4 2.250 2.375 2.500 0.041 -0.057 -0.155 0.250 
 5 2.250 2.312 2.375 0.041 -0.008 -0.057 0.125 
 6 2.250 2.281 2.312 0.041  0.017 -0.008 0.062 
 7 2.281 2.297 2.312 0.017  0.005 -0.008 0.031 
 8 2.297 2.305 2.312 0.005 -0.001 -0.008 0.016 
 9 2.297 2.301 2.305 0.005  0.002 -0.001 0.008 
10 2.301 2.303 2.305 0.002  0.000 -0.001 0.004 
11 2.303 2.304 2.305 0.000 -0.001 -0.001 0.002 
12 2.303 2.303 2.304 0.000 -0.000 -0.001 0.001 
13 2.303 2.303 2.303 0.000 -0.000 -0.000 0.000 
14 2.303 2.303 2.303 0.000 -0.000 -0.000 0.000 
15 2.303 2.303 2.303 0.000 -0.000 -0.000 0.000 
16 2.303 2.303 2.303 0.000  0.000 -0.000 0.000 
raiz:  2.302764892578125

Donde se observa que para la misma tolerancia de 10-4, se incrementan las iteraciones a 16. Mientra que con punto fijo eran solo 8.

Nota: En la evaluación solo se requeria calcular hasta la 5ta iteración. Lo presentado es para fines didácticos

s1Eva_IIT2019_T3 Circuito eléctrico

Las ecuaciones del problema  son:

55 I_1 - 25 I_4 =-200 -37 I_3 - 4 I_4 =-250 -25 I_1 - 4 I_3 +29 I_4 =100 I_2 =-10

Planteo del problema en la forma A.X=B

A = np.array([[ 55, 0,   0,-25],
              [  0, 0, -37, -4],
              [-25, 0,  -4, 29],
              [  0, 1,   0,  0]],dtype=float)

B = np.array([[-200],
              [-250],
              [ 100],
              [ -10]],dtype=float)

El ejercicio se puede simplificar con una matriz de 3×3 dado que una de las corrientes I2 es conocida con valor -10, queda resolver el problema para
[I1 ,I3 ,I4 ]

A = np.array([[ 55,   0,-25],
              [  0, -37, -4],
              [-25,  -4, 29]],dtype=float)

B = np.array([[-200],
              [-250],
              [ 100]],dtype=float)

conformando la matriz aumentada

[[  55.    0.  -25. -200.]
 [   0.  -37.   -4. -250.]
 [ -25.   -4.   29.  100.]]

que se pivotea por filas para acercar a matriz diagonal dominante:

[[  55.    0.  -25. -200.]
 [   0.  -37.   -4. -250.]
 [ -25.   -4.   29.  100.]]

Literal a

Para métodos directos se aplica el método de eliminación hacia adelante.

Usando el primer elemento en la diagonal se convierten en ceros los números debajo de la posición primera de la diagonal

[[  55.    0.  -25.         -200.      ]
 [   0.  -37.   -4.         -250.      ]
 [   0.   -4.   17.636363      9.090909]]

luego se continúa con la segunda columna:

[[  55.    0.  -25.         -200.      ]
 [   0.  -37.   -4.         -250.      ]
 [   0.    0.   18.068796     36.117936]]

y para el método de Gauss se emplea sustitución hacia atras
se determina el valor de I4

18.068796 I_4 = 36.11793612 I_4 =\frac{36.11793612}{18.068796}= 1.99891216 -37 I_3 -4 I_4 = -250 -37 I_3= -250 + 4 I_4 I_3=\frac{-250 + 4 I_4}{-37} I_3=\frac{-250 + 4 (1.99891216)}{-37} = 6.54065815

y planteando se obtiene el último valor

55 I_1 +25 I_4 = -200 55 I_1 = -200 -25 I_4 I_1 = \frac{-200 -25 I_4}{55} I_1 = \frac{-200 -25(1.99891216)}{55} = -2.7277672

con lo que el vector solución es:

[[-2.7277672]
 [ 6.54065815]
 [ 1.99891216]]

sin embargo, para verificar la respuesta se aplica A.X=B

verificar que A.X = B, obteniendo nuevamente el vector B.
[[-200.]
 [-250.]
 [ 100.]]

literal b
La norma de la matriz infinito se determina como:

||x|| = max\Big[ |x_i| \Big]

considere que en el problema el término en A de magnitud mayor es 55.
El vector suma de filas es:

[[| 55|+|  0|+|-25|],    [[80],
 [|  0|+|-37|+| -4|],  =  [41],
 [[-25|+| -4|+| 29|]]     [58]]

por lo que la norma ∞ ejemplo ||A||∞ 
es el maximo de suma de filas: 80

para revisar la estabilidad de la solución, se observa el número de condición

>>> np.linalg.cond(A)
4.997509004325602

En éste caso no está muy alejado de 1. De resultar alejado del valor ideal de uno,  la solución se considera poco estable. Pequeños cambios en la entrada del sistema generan grandes cambios en la salida.

Tarea: Matriz de transición de Jacobi


Literal c

En el método de Gauss-Seidel acorde a lo indicado, se inicia con el vector cero. Como no se indica el valor de tolerancia para el error, se considera tolera = 0.0001

las ecuaciones para el método son:

I_1 =\frac{-200 + 25 I_4}{55} I_3 = \frac{-250+ 4 I_4}{-37} I_4 =\frac{100 +25 I_1 + 4 I_3}{29}

Como I2 es constante, no se usa en las iteraciones

I_2 =-10

teniendo como resultados de las iteraciones:

iteración:  1
 Xnuevo:      [-3.63636364  6.75675676  1.99891216]
 diferencia:  [3.63636364   6.75675676  1.99891216]
 error:  6.756756756756757
 iteración:  2
 Xnuevo:      [-2.7277672   6.54065815  1.99891216]
 diferencia:  [0.90859643   0.21609861  0.        ]
 error:  0.9085964348406557
 iteración:  3
 Xnuevo:      [-2.7277672   6.54065815  1.99891216]
 diferencia:  [0. 0. 0.]
 error:  0.0

con lo que el vector resultante es:

 Método de Gauss-Seidel
respuesta de A.X=B : 
[[-2.7277672 ]
 [ 6.54065815]
 [ 1.99891216]]

que para verificar, se realiza la operación A.X
observando que el resultado es igual a B

[[-200.00002751]
 [-249.9999956 ]
 [ 100.0000125 ]]


Solución alterna


Usando la matriz de 4×4, los resultados son iguales para las corrientes
[I1 ,I2 , I3 ,I4 ]. Realizando la matriz aumentada,

[[  55.    0.    0.  -25. -200.]
 [   0.    0.  -37.   -4. -250.]
 [ -25.    0.   -4.   29.  100.]
 [   0.    1.    0.    0.  -10.]]

que se pivotea por filas para acercar a matriz diagonal dominante:

[[  55.    0.    0.  -25. -200.]
 [   0.    1.    0.    0.  -10.]
 [   0.    0.  -37.   -4. -250.]
 [ -25.    0.   -4.   29.  100.]]

Literal a

Para métodos directos se aplica el método de eliminación hacia adelante.

Usando el primer elemento  en la diagonal.

[[  55.     0.     0.   -25.         -200.        ]
 [   0.     1.     0.     0.          -10.        ]
 [   0.     0.   -37.    -4.         -250.        ]
 [   0.     0.    -4.    17.63636364    9.09090909]]

para el segundo no es necesario, por debajo se encuentran valores cero.
Por lo que se pasa al tercer elemento de la diagonal

[[  55.     0.     0.     -25.         -200.        ]
 [   0.     1.     0.      0.          -10.        ]
 [   0.     0.   -37.     -4.         -250.        ]
 [   0.     0.     0.     18.06879607    36.11793612]]

y para el método de Gauss se emplea sustitución hacia atras.
para x4:

18.06879607 x_4 = 36.11793612 x_4 = 1.99891216

para x3:

-37 x_3 -4 x_3 = -250 37 x_3 = 250-4 x_4 = 250-4(1.99891216) x_3 = 6.54065815

como ejercicio, continuar con x1, dado que x2=-10

55 x_1 + 25 x_4 = -200

El vector solución obtenido es:

el vector solución X es:
[[ -2.7277672 ]
 [-10.        ]
 [  6.54065815]
 [  1.99891216]]

sin embargo, para verificar la respuesta se aplica A.X=B.

[[-200.]
 [-250.]
 [ 100.]
 [ -10.]]

Se revisa el número de condición de la matriz:

>>> np.linalg.cond(A)
70.21827416891405

Y para éste caso, el número de condición se encuentra alejado del valor 1, contrario a la respuesta del la primera forma de solución con la matriz 3×3. De resultar alejado del valor ideal de uno, la solución se considera poco estable. Pequeños cambios en la entrada del sistema generan grandes cambios en la salida.


Algoritmo en Python

Presentado por partes para revisión:

# Método de Gauss,
# Recibe las matrices A,B
# presenta solucion X que cumple: A.X=B
import numpy as np

# INGRESO
A = np.array([[ 55,   0,-25],
              [  0, -37, -4],
              [-25,  -4, 29]],dtype=float)

B = np.array([[-200],
              [-250],
              [ 100]],dtype=float)

# PROCEDIMIENTO
# Matriz Aumentada
casicero = 1e-15 # 0
AB = np.concatenate((A,B),axis=1)
print('aumentada: ')
print(AB)

# pivotea por fila AB
tamano = np.shape(AB)
n = tamano[0]
m = tamano[1]

for i in range(0,n-1,1):
    # columna desde diagonal i en adelante
    columna = np.abs(AB[i:,i])
    dondemax = np.argmax(columna)
    # revisa dondemax no está en la diagonal
    if (dondemax != 0):
        # intercambia fila
        temporal = np.copy(AB[i,:])
        AB[i,:] = AB[dondemax+i,:]
        AB[dondemax+i,:] = temporal
print('pivoteada: ')
print(AB)

# Gauss elimina hacia adelante
# tarea: verificar términos cero
print('Elimina hacia adelante')
for i in range(0,n,1):
    pivote = AB[i,i]
    adelante = i+1
    print('i: ', i)
    for k in range(adelante,n,1):
        print('k: ',k)
        if (np.abs(pivote)>=casicero):
            factor = AB[k,i]/pivote
            AB[k,:] = AB[k,:] - factor*AB[i,:]
        print(AB)
print('Elimina hacia adelante')
print(AB)

# Sustitución hacia atras
X = np.zeros(n,dtype=float) 
ultfila = n-1
ultcolumna = m-1
for i in range(ultfila,0-1,-1):
    suma = 0
    for j in range(i+1,ultcolumna,1):
        suma = suma + AB[i,j]*X[j]
    X[i] = (AB[i,ultcolumna]-suma)/AB[i,i]
X = np.transpose([X])

# Verifica resultado
verifica = np.dot(A,X)

# SALIDA
print('por sustitución hacia atras')
print('el vector solución X es:')
print(X)

print('verificar que A.X = B')
print(verifica)

# -------------------------------------------------
# # Algoritmo Gauss-Seidel,
# matrices, métodos iterativos
# Referencia: Chapra 11.2, p.310, pdf.334
#      Rodriguez 5.2 p.162
# ingresar iteramax si requiere más iteraciones

import numpy as np

def gauss_seidel(A,B,tolera,X,iteramax=100):
    tamano = np.shape(A)
    n = tamano[0]
    m = tamano[1]
    diferencia = np.ones(n, dtype=float)
    errado = np.max(diferencia)
    
    itera = 0
    while not(errado<=tolera or itera>iteramax):
        for i in range(0,n,1):
            nuevo = B[i]
            for j in range(0,m,1):
                if (i!=j): # excepto diagonal de A
                    nuevo = nuevo-A[i,j]*X[j]
            nuevo = nuevo/A[i,i]
            diferencia[i] = np.abs(nuevo-X[i])
            X[i] = nuevo
        errado = np.max(diferencia)
        print(' iteración: ', itera)
        print(' Xnuevo: ', X)
        print(' diferencia: ', diferencia)
        print(' error: ' ,errado)
        itera = itera + 1
    # Vector en columna
    X = np.transpose([X])
    # No converge
    if (itera>iteramax):
        X=0
    return(X)

# Programa de prueba #######
tolera = 0.0001

# PROCEDIMIENTO
# usando la pivoteada por filas
n = len(B)
Xgs = np.zeros(n, dtype=float)
respuesta = gauss_seidel(AB[:,:n],AB[:,n],tolera,Xgs)
verificags = np.dot(A,respuesta)

# SALIDA
print(' Método de Gauss-Seidel')
print('respuesta de A.X=B : ')
print(respuesta)
print('verificar A.X: ')
print(verificags)

s1Eva_IIT2019_T2 Proceso Termodinámico

la ecuación para el problema se describe como:

f(x)=e^{-0.5x}

ecuación que se usa para describir los siguientes puntos:

x 0 1 2 3 4
f(x) 1 0.60653065 0.36787944 0.22313016  0.13533528

Como el polinomio es de grado 2, se utilizan tres puntos. Para cubrir el intervalo los puntos seleccionados incluyen los extremos y el punto medio.

literal a

Con los puntos seleccionados se escriben las ecuaciones del polinomio:

p_2(x)= a_0 x^2 + a_1 x + a_2

usando los valores de la tabla:

p_2(0)=a_0 (0)^2 + a_1 (0) + a_2 = 1 p_2(2)=a_0 (2)^2 + a_1 (2) + a_2 = 0.36787944 p_2(4)=a_0 (4)^2 + a_1 (4) + a_2 = 0.13533528

con la que se escribe la matriz Vandermonde con la forma A.x=B

A= [[ 0.,  0.,  1.,]
    [ 4.,  2.,  1.,]
    [16.,  4.,  1.,]]

B= [[1.        ],
    [0.36787944],
    [0.13533528]]) 

matriz aumentada

[[ 0.,  0.,  1.,  1.        ]
 [ 4.,  2.,  1.,  0.36787944]
 [16.,  4.,  1.,  0.13533528]]

matriz pivoteada

[[16.,  4.,  1.,  0.13533528]
 [ 4.,  2.,  1.,  0.36787944]
 [ 0.,  0.,  1.,  1.        ]]

Resolviendo por algún método directo, la solución proporciona los coeficientes del polinomio

Tarea: escribir la solución del método directo, semejante a la presentada en el tema 3

[[ 0.04994705]
 [-0.41595438]
 [ 1.        ]]

con lo que el polinomio de interpolación es:

p_2(x) = 0.04994705 x^2 - 0.41595438 x + 1.0

en el enunciado se requiere la evaluación en x=2.4

p_2(2.4) = 0.04994705 (2.4)^2 - 0.41595438 (2.4) + 1.0 f(2.4)=e^{-0.5(2.4)} error = |f(2.4)-p_2(2.4)|
Evaluando p(2.4):  0.2894044975129779
Error en 2.4:      0.011789714399224216
Error relativo:    0.039143230291095066

La diferencia entre la función y el polinomio de interpolación se puede observar en la gráfica:


literal b

Tarea: Encontrar la cota de error con f(1.7)


Algoritmo en Python

Presntado por secciones, semejante a lo desarrollado en clases

# Interpolación por polinomio
import numpy as np
import matplotlib.pyplot as plt

# INGRESO, Datos de prueba
fx = lambda x: np.exp(-0.5*x)

xi = np.array([0,2,4])

# determina vector
n = len(xi)
fi = np.zeros(n,dtype=float)
for i in range(0,n,1):
    fi[i]= fx(xi[i])

# PROCEDIMIENTO
# Arreglos numpy 
xi = np.array(xi)
fi = np.array(fi)
n = len(xi)

# Vector B en columna
B = np.array(fi)
B = fi[:,np.newaxis]

# Matriz Vandermonde D
D = np.zeros(shape=(n,n),dtype =float)
for f in range(0,n,1):
    for c in range(0,n,1):
        potencia = (n-1)-c
        D[f,c] = xi[f]**potencia

# Resolver matriz aumentada
coeficiente =  np.linalg.solve(D,B)

# Polinomio en forma simbólica
import sympy as sym
x = sym.Symbol('x')
polinomio = 0
for i in range(0,n,1):
    potencia = (n-1)-i
    termino = coeficiente[i,0]*((x**potencia))
    polinomio = polinomio + termino

# Convierte polinomio a funcion 
# para evaluación más rápida
px = sym.lambdify(x,polinomio)

# Para graficar el polinomio
k = 100
inicio = np.min(xi)
fin = np.max(xi)
puntosx = np.linspace(inicio,fin,k)
puntosy = px(puntosx)

puntosf = fx(puntosx)

# Puntos evaluados
x1 = 2.4
px1 = px(x1)
fx1 = fx(x1)
errorx1 = np.abs(px1-fx1)
errorx1rel = errorx1/fx1

x2 = 1.7
px2 = px(x1)
fx2 = fx(x1)
errorx2 = np.abs(px1-fx1)
errorx2rel = errorx1/fx1
    
# SALIDA
print('Matriz Vandermonde: ')
print(D)
print('los coeficientes del polinomio: ')
print(coeficiente)
print('Polinomio de interpolación: ')
print(polinomio)
print()
print('Evaluando en X1: ',x1)
print('Evaluando p(x1): ',px1)
print('Error en x1:     ',errorx1)
print(' Error relativo: ', errorx1rel)
print()
print('Evaluando en X2: ',x2)
print('Evaluando p(x2): ',px2)
print('Error en x2:     ',errorx2)
print(' Error relativo: ', errorx2rel)

# Grafica
plt.plot(xi,fi,'o',label='muestras' )
plt.plot(puntosx,puntosy,label='p(x)')
plt.plot(puntosx,puntosf,label='f(x)')
plt.xlabel('x')
plt.legend()
plt.show()

s1Eva_IIT2019_T4 Concentración de químico

formula a usar:

C = C_{ent} ( 1 - e^{-0.04t})+C_{0} e^{-0.03t}

Se sustituyen los valores dados con:
C0 = 4, Cent = 10, C = 0.93 Cent.

0.93(10) = 10 ( 1 - e^{-0.04t}) + 4 e^{-0.03t}

igualando a cero para forma estandarizada del algoritmo,

10( 1 - e^{-0.04t}) + 4 e^{-0.03t} - 9.3 = 0 0.7 - 10 e^{-0.04t} + 4 e^{-0.03t} = 0

se usas las funciones f(t) y f'(t) para el método de Newton-Raphson,

f(t) = 0.7 - 10 e^{-0.04t} + 4 e^{-0.03t} f'(t) = - 10(-0.04) e^{-0.04t} + 4(-0.03) e^{-0.03t} f'(t) = 0.4 e^{-0.04t} - 0.12 e^{-0.03t}

con lo que se pueden realizar los cálculos de forma iterativa.

t_{i+1} = t_i -\frac{f(t_i)}{f'(t_i)}

De no disponer de la gráfica de f(t), y se desconoce el valor inicial para t0 se usa 0. Como no se indica la tolerancia, se estima en 10-4

Iteración 1

t0 = 0

f(0) = 0.7 - 10 e^{-0.04(0)} + 4 e^{-0.03(0)} = 5.3 f'(0) = 0.4 e^{-0.04(0)} - 0.12 e^{-0.03(0)} = -0.28 t_{1} = 0 -\frac{5.3}{-0.28} = 18.92 error = |18.92-0| = 18.92

Iteración 2

f(18.92) = 0.7 - 10 e^{-0.04(18.92)} + 4 e^{-0.03(18.92)} = -1.72308 f'(18.92) = 0.4 e^{-0.04(18.92)} - 0.12 e^{-0.03(18.92)} = 0.119593 t_{2} = 18.92 -\frac{-1.723087}{0.119593} = 33.3365 error = |33.3365 - 18.92| = 14.4079

Iteración 3

f(33.3365) = 0.7 - 10 e^{-0.04(33.3365)} + 4 e^{-0.03(33.3365)} = -0.4642 f'(33.3365) = 0.4 e^{-0.04(33.3365)} - 0.12 e^{-0.03(33.3365)} = 0.06128 t_{3} = 33.3365 -\frac{-0.46427}{-5.8013} = 40.912 error = |40.912 - 33.3365| = 7.5755

Observando que los errores disminuyen entre cada iteración, se encuentra que el método converge.

y se forma la siguiente tabla:

['xi' ,  'xnuevo', 'error']
[ 0.      18.9286  18.9286]
[18.9286  33.3365  14.4079]
[33.3365  40.912    7.5755]
[40.912   42.654     1.742]
[42.654   42.7316   0.0776]
[4.2732e+01 4.2732e+01 1.4632e-04]
raiz en:  42.731721341402796

Observando la gráfica de la función puede observar el resultado:


Algoritmo en Python

# 1Eva_IIT2019_T4
# Método de Newton-Raphson

import numpy as np
import matplotlib.pyplot as plt

# INGRESO
fx = lambda t: 0.7-10*np.exp(-0.04*t)+4*np.exp(-0.03*t)
dfx = lambda t:0.40*np.exp(-0.04*t)-0.12*np.exp(-0.03*t)

x0 = 0
tolera = 0.001

a = 0
b = 60
muestras = 21

# PROCEDIMIENTO
tabla = []
tramo = abs(2*tolera)
xi = x0
while (tramo>=tolera):
    xnuevo = xi - fx(xi)/dfx(xi)
    tramo = abs(xnuevo-xi)
    tabla.append([xi,xnuevo,tramo])
    xi = xnuevo

tabla = np.array(tabla)
n=len(tabla)

# para la gráfica
xk = np.linspace(a,b,muestras)
fk = fx(xk)

# SALIDA
print(['xi', 'xnuevo', 'error'])
np.set_printoptions(precision = 4)
for i in range(0,n,1):
    print(tabla[i])
print('raiz en: ', xi)

# grafica
plt.plot(xk,fk)
plt.axhline(0, color='black')
plt.xlabel('t')
plt.ylabel('f(t)')
plt.show()

s3Eva_IT2019_T3 Difusión en sólidos

Siguiendo el procedimiento planteado en la sección EDP parabólicas, se plantea la malla del ejercicio:

Para plantear la ecuación en forma discreta:

\frac{\phi_{i,j+1}-\phi_{i,j}}{\Delta t}=D\frac{\phi_{i+1,j}-2\phi_{i,j}+\phi_{i-1,j}}{(\Delta x)^2}

y resolver usando el método explícito para ecuaciones parabólicas, obteniendo el siguiente resultado:

\phi_{i,j+1}-\phi_{i,j}=D\frac{\Delta t }{\Delta x^2}(\phi_{i+1,j}-2\phi_{i,j}+\phi_{i-1,j}) \lambda = D\frac{\Delta t }{\Delta x^2} \phi_{i,j+1}-\phi_{i,j}=\lambda (\phi_{i+1,j}-2\phi_{i,j}+\phi_{i-1,j}) \phi_{i,j+1} =\lambda \phi_{i+1,j}-2\lambda\phi_{i,j}+\lambda\phi_{i-1,j}+\phi_{i,j} \phi_{i,j+1} =\lambda \phi_{i+1,j}(1-2\lambda)\phi_{i,j}+\lambda\phi_{i-1,j} \phi_{i,j+1} =P \phi_{i+1,j}+Q\phi_{i,j}+R\phi_{i-1,j}

siendo:
P = λ = 0.16 (Δx/100)/Δx2 = 0.0016/Δx = 0.0016/0.02=0.08
Q = 1-2λ = 1-2*(0.08) = 0.84
R = λ =0.08

\phi_{i,j+1} =0.08 \phi_{i+1,j}+ 0.84\phi_{i,j}+0.08\phi_{i-1,j}

Iteración 1 en tiempo:
i=1, j=0

\phi_{1,1} =0.08 \phi_{2,0}+ 0.84\phi_{1,0}+0.08\phi_{0,0} \phi_{1,1} =0.08 (0)+ 0.84(0)+0.08(5)=0.4

i=2,j=0

\phi_{2,1} =0.08 \phi_{3,0}+ 0.84\phi_{2,0}+0.08\phi_{1,0} = 0

Para los proximos valores i>2, todos los resultados son 0

Iteración 2 en tiempo
i=1, j=1

\phi_{1,2} =0.08 \phi_{2,0}+ 0.84\phi_{1,0}+0.08\phi_{0,0}

\phi_{1,2} =0.08 (0)+ 0.84(0.4)+0.08(5)=0.736
i=2, j=1

\phi_{2,2} =0.08 \phi_{3,1}+ 0.84\phi_{2,1}+0.08\phi_{1,1} \phi_{2,2} =0.08(0)+ 0.84(0)+0.08(0.4) = 0.032

i=3, j=1

\phi_{3,2} =0.08\phi_{4,1}+ 0.84\phi_{3,1}+0.08\phi_{2,1}=0

Para los proximos valores i>3, todos los resultados son 0

Tarea: Desarrollar la iteración 3 en el tiempo.

siguiendo las iteraciones se tiene la siguiente tabla:

[[5.0, 0.000, 0.000, 0.00000, 0.00000 , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
 [5.0, 0.400, 0.000, 0.00000, 0.00000 , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
 [5.0, 0.736, 0.032, 0.00000, 0.00000 , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
 [5.0, 1.021, 0.085, 0.00256, 0.00000 , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
 [5.0, 1.264, 0.153, 0.00901, 0.00020, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
...
]

Con lo que se obtiene la siguiente gráfica.

El resultado se interpreta mejor con una animación:

Tarea: Presentar el orden de error de la ecuación basado en las fórmulas de diferenciación


Algorirmo en Python

# 3EIT2019T4.Difusión en sólidos. 2da Ley de Fick
# EDP parabólicas. método explícito, usando diferencias finitas
# http://blog.espol.edu.ec/matg1013/3eva_it2018_t3-edp-parabolica-temperatura-en-varilla/
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
# Valores de frontera
Ta = 5
Tb = 0
T0 = 0
# longitud en x
a = 0
b = 0.1
# Constante K
K = 1/(1.6e-1)
# Tamaño de paso
dx = 0.02
dt = dx/100
# iteraciones en tiempo
n = 50

# PROCEDIMIENTO
# iteraciones en longitud
xi = np.arange(a,b+dx,dx)
m = len(xi)
ultimox = m-1

# Resultados en tabla u[x,t]
u = np.zeros(shape=(m,n), dtype=float)

# valores iniciales de u[:,j]
j=0
ultimot = n-1
u[0,j]= Ta
u[1:ultimox,j] = T0
u[ultimox,j] = Tb

# factores P,Q,R
lamb = dt/(K*dx**2)
P = lamb
Q = 1 - 2*lamb
R = lamb

# Calcula U para cada tiempo + dt
j = 0
while not(j>=ultimot):
    u[0,j+1] = Ta
    for i in range(1,ultimox,1):
        u[i,j+1] = P*u[i-1,j] + Q*u[i,j] + R*u[i+1,j]
    u[m-1,j+1] = Tb
    j=j+1

# SALIDA
print('Tabla de resultados')
np.set_printoptions(precision=2)
print(u)

# Gráfica
salto = int(n/10)
if (salto == 0):
    salto = 1
for j in range(0,n,salto):
    vector = u[:,j]
    plt.plot(xi,vector)
    plt.plot(xi,vector, '.r')
plt.xlabel('x[i]')
plt.ylabel('phi[i,j]')
plt.title('Solución EDP parabólica')
plt.show()

La animación se complementa con lo mostrado en la sección de Unidades.

s3Eva_IT2019_T2 Integral con interpolación

El ejercicio considera dos partes: interpolación e integración

a. Interpolación

Se requiere aproximar la función usando tres puntos. Para comprender la razón del método solicitado, se compara la función con dos interpolaciones:

a.1 Lagrange
a.2 Trazador cúbico sujeto

Observando la gráfica se aclara que en éste caso, una mejor aproximación se obtiene con el método  de trazador cúbico sujeto. Motivo por lo que el tema tiene un peso de 40/100 puntos

Los valores a considerar para la evaluación son:

puntos referencia xi,yi: 
[0.         0.78539816 1.57079633]
[ 0.          0.62426595 -0.97536797]
derivadas en los extremos:  
    3.141592653589793 
    0.6929852019184021
Polinomio de Lagrange
-1.80262534301178*x**2 + 2.21061873102778*x
Trazadores cúbicos sujetos
[0.         0.78539816]
-0.548171611756137*x**3 - 2.55744517923506*x**2 + 3.14159265358979*x

[0.78539816 1.57079633]
4.66299098804068*x**3 - 14.8359577843727*x**2 + 12.7851139029174*x - 2.52466795930204

------------------
Valores calculados para Trazadores cúbicos sujetos:
Matriz A: 
[[-0.26179939 -0.13089969  0.        ]
 [ 0.78539816  3.14159265  0.78539816]
 [ 0.          0.13089969  0.26179939]]
Vector B: 
[  2.34675256 -16.9893436    2.72970237]
coeficientes S: 
[-5.11489036 -7.69808822 14.27573913]
coeficientes a,b,c,d
[-0.54817161  4.66299099]
[-2.55744518 -3.84904411]
[ 3.14159265 -1.89005227]
[0.         0.62426595]

b. Integración

Como forma de comparacíon de resultados, se requiere integrar con varios métodos para comparar resultados y errores.

b.1 Integración con Cuadratura de Gauss, usando el resultado de trazador cúbico.

Se integra en cada tramo de cada polinomio:

Trazadores cúbicos sujetos
[0.         0.78539816]
-0.548171611756137*x**3 - 2.55744517923506*x**2 + 3.14159265358979*x

Se obtienen los puntos del método de cuadratura desplazados en el rango:

xa:  0.16597416116944688
xb:  0.6194240022280014
area:  0.5037962958529855

Para el segundo tramo:

[0.78539816 1.57079633]
4.66299098804068*x**3 - 14.8359577843727*x**2 + 12.7851139029174*x - 2.52466795930204
xa:  0.9513723245668951
xb:  1.4048221656254496
area:  -0.2706563884589365

Con lo que el integral total es:

Integral total:  0.23313990739404894

b.2 Integración analítica

\int_0^{\pi /2}sin(\pi x) dx

u = πx
du/dx = π
dx = du/π

se convierte en:

\frac{1}{\pi}\int sin(u) du \frac{1}{\pi}(-cos(u))

volviendo a la variable x:

\frac{1}{\pi}(-cos(\pi x)) \Big\rvert_{0}^{\frac{\pi}{2}} -\frac{1}{\pi}(cos(\pi \frac{\pi}{2})-cos(\pi(0))) = 0.24809580527879377

c. Estimación del error

Se restan los resultados de las secciones b.1 y b.2

error = |0.24809580527879377 – 0.23313990739404894 |

error = 0.014955897884744829


Algoritmo en Python

separado por literales

# 3Eva I T 2019 Interpola e Integra
import numpy as np
import sympy as sym
import matplotlib.pyplot as plt

def interpola_lagrange(xi,yi):
    '''
    Interpolación con método de Lagrange
    resultado: polinomio en forma simbólica
    '''
    # PROCEDIMIENTO
    n = len(xi)
    x = sym.Symbol('x')
    # Polinomio
    polinomio = 0
    for i in range(0,n,1):
        # Termino de Lagrange
        termino = 1
        for j  in range(0,n,1):
            if (j!=i):
                termino = termino*(x-xi[j])/(xi[i]-xi[j])
        polinomio = polinomio + termino*yi[i]
    # Expande el polinomio
    polinomio = polinomio.expand()
    return(polinomio)

def traza3sujeto(xi,yi,u,v):
    '''
    Trazador cúbico sujeto, splines
    resultado: polinomio en forma simbólica
    '''
    n = len(xi)
    # Valores h
    h = np.zeros(n-1, dtype=float)
    # Sistema de ecuaciones
    A = np.zeros(shape=(n,n), dtype=float)
    B = np.zeros(n, dtype=float)
    S = np.zeros(n-1, dtype=float)
    # coeficientes
    a = np.zeros(n-1, dtype=float)
    b = np.zeros(n-1, dtype=float)
    c = np.zeros(n-1, dtype=float)
    d = np.zeros(n-1, dtype=float)
    
    polinomios=[]
    
    if (n>=3):
        for i in range(0,n-1,1):
            h[i]=xi[i+1]-xi[i]
        A[0,0] = -h[0]/3
        A[0,1] = -h[0]/6
        B[0] = u-(yi[1]-yi[0])/h[0]
        for i in range(1,n-1,1):
            A[i,i-1] = h[i-1]
            A[i,i] = 2*(h[i-1]+h[i])
            A[i,i+1] = h[i]
            B[i] = 6*((yi[i+1]-yi[i])/h[i] - (yi[i]-yi[i-1])/h[i-1])
        A[n-1,n-2] = h[n-2]/6
        A[n-1,n-1] = h[n-2]/3
        B[n-1] = v-(yi[n-1]-yi[n-2])/h[n-2]

        # Resolver sistema de ecuaciones
        S = np.linalg.solve(A,B)

        # Coeficientes
        for i in range(0,n-1,1):
            a[i]=(S[i+1]-S[i])/(6*h[i])
            b[i]=S[i]/2
            c[i]=(yi[i+1]-yi[i])/h[i]-(2*h[i]*S[i]+h[i]*S[i+1])/6
            d[i]=yi[i]
      
        # polinomio en forma simbólica
        x=sym.Symbol('x')
        polinomios=[]
        for i in range(0,n-1,1):
            ptramo = a[i]*(x-xi[i])**3 + b[i]*(x-xi[i])**2 + c[i]*(x-xi[i])+ d[i]
            ptramo = ptramo.expand()
            polinomios.append(ptramo)
        parametros = [A,B,S,a,b,c,d]                                                           
    return(polinomios, parametros)

# INGRESO
f = lambda x: np.sin(np.pi*x)
muestrasf = 20
a = 0
b = np.pi/2
# Derivadas en los extremos
u = np.pi*np.cos(np.pi*a)
v = np.pi*np.cos(np.pi*b)
muestras = 3

# literal a
# PROCEDIMIENTO
xif = np.linspace(a,b,muestrasf)
yif = f(xif)

xi = np.linspace(a,b,muestras)
yi = f(xi)

# Usando Lagrange
x = sym.Symbol('x')
pL = interpola_lagrange(xi,yi)
pxL = sym.lambdify(x,pL)
pxiL =  pxL(xif)

# Trazador cúbico sujeto
pS, parametros = traza3sujeto(xi,yi,u,v)
pxiS = np.zeros(muestrasf,dtype=float)

# Evalua trazadores cúbicos sujetos
i=0
ap = xi[i]
bp = xi[i+1]
poli = sym.lambdify(x, pS[i])
for j in range(0,muestrasf,1):
    punto = xif[j]
    if (punto>bp):
        i = i+1
        ap = xi[i]
        bp = xi[i+1]
        poli = sym.lambdify(x,pS[i])
    pxiS[j] = poli(punto)

# SALIDA
print('puntos referencia xi,yi: ')
print(xi)
print(yi)
print('derivadas en los extremos: ',u,v)
print('Polinomio de Lagrange')
print(pL)
print('Trazadores cúbicos sujetos')
n = len(xi)
for i in range(0,n-1,1):
    print(xi[i:i+2])
    print(pS[i])
# Parametros de Trazadores cúbicos sujetos
print('Matriz A: ')
print(parametros[0])
print('Vector B: ')
print(parametros[1])
print('coeficientes S: ')
print(parametros[2])
print('coeficienetes a,b,c,d')
print(parametros[3])
print(parametros[4])
print(parametros[5])
print(parametros[6])

# Gráficas
plt.plot(xif,yif, label='funcion')
plt.plot(xi,yi,'o', label='muestras')
plt.plot(xif,pxiL, label='p(x)_Lagrange')
plt.plot(xif,pxiS, label='p(x)_Traza3Sujeto')
plt.legend()
plt.xlabel('x')
plt.show()

# literal b
# cuadratura de Gauss de dos puntos
def integraCuadGauss2p(funcionx,a,b):
    x0 = -1/np.sqrt(3)
    x1 = -x0
    xa = (b+a)/2 + (b-a)/2*(x0)
    xb = (b+a)/2 + (b-a)/2*(x1)
    area = ((b-a)/2)*(funcionx(xa) + funcionx(xb))
    print('xa: ',xa)
    print('xb: ',xb)
    print('area: ', area)
    return(area)

# INGRESO
f0 = sym.lambdify(x,pS[0])
f1 = sym.lambdify(x,pS[1])
# Procedimiento
I0 = integraCuadGauss2p(f0,xi[0],xi[1])
I1 = integraCuadGauss2p(f1,xi[1],xi[2])
It = I0+I1

# SALIDA
print('Integral 1: ', I0)
print('Integral 2: ', I1)
print('Integral total: ',It)

s3Eva_IT2019_T1 Ecuaciones simultáneas

Para plantear la intersección de las ecuaciones se pueden simplificar como:

y_1 = -x^2 +x + 0.75 y+5xy=x^3 y(1+5x)=x^3 y_2=\frac{x^3}{1+5x}

Quedando dos ecuaciones simplificadas:

y_1 = -x^2 +x + 0.75 y_2 = \frac{x^3}{1+5x}

cuyas gráficas son:

dónde se puede observar la intersección alrededor de 1.3

Restando ambas ecuaciones, se tiene que encontrar el valor de x para que el resultado sea cero.

y_1(x)-y_2(x)= -x^2 +x + 0.75 -\frac{x^3}{1+5x} f(x) = -x^2 +x + 0.75 -\frac{x^3}{1+5x} = 0

Para encontrarla derivada se procesa la expresión:

(1+5x)(-x^2 +x + 0.75) -x^3 = 0(1+5x) -6x^3+4x^2+4.75x+0.75 = 0 f'(x)= -18x^2 +8x + 4.75

Se usa el punto inicial x0=1 definido en el enunciado y se realizan las iteraciones siguiendo el algoritmo.

Se tiene que la raiz es:

raiz en:  1.3310736382369661
 [  xi, 	 xnuevo,	 fxi,	 dfxi, 	 tramo]
[[ 1.000e+00  1.111e+00  5.833e-01 -5.250e+00  1.111e-01]
 [ 1.111e+00  1.160e+00  4.173e-01 -8.583e+00  4.862e-02]
 [ 1.160e+00  1.193e+00  3.353e-01 -1.018e+01  3.293e-02]
 [ 1.193e+00  1.217e+00  2.766e-01 -1.131e+01  2.445e-02]
 [ 1.217e+00  1.236e+00  2.313e-01 -1.218e+01  1.899e-02]
 [ 1.236e+00  1.251e+00  1.951e-01 -1.286e+01  1.517e-02]
....
]

Algoritmo en Python

# 3Eva I T 2019 ecuaciones simultaneas
import numpy as np
import matplotlib.pyplot as plt

def newton_raphson(funcionx, fxderiva, xi, tolera):
    '''
    funciónx y fxderiva son de forma numérica
    xi es el punto inicial de búsqueda
    '''
    tabla = []
    tramo = abs(2*tolera)
    while (tramo>=tolera):
        fxi = funcionx(xi)
        dfxi = fxderiva(xi)
        xnuevo = xi - fxi/dfxi
        tramo = abs(xnuevo-xi)
        tabla.append([xi,xnuevo,fxi,dfxi,tramo])
        xi = xnuevo
    return(xi,tabla)

# INGRESO
y1 = lambda x: -x**2 +x +0.75
y2 = lambda x: (x**3)/(1+5*x)
a = 0.5
b = 1.5
muestras = 20

f = lambda x: -x**2+x+0.75-x**3/(1+5*x)
df = lambda x: -18*(x**2)+8*x +4.75
tolera = 1e-4
x0 = 1

# PROCEDIMIENTO
# datos para la gráfica
xi = np.linspace(a,b,muestras)
yi1 = y1(xi)
yi2 = y2(xi)
fi = f(xi)
# determina raiz
raiz, tabla = newton_raphson(f, df, x0, tolera)
tabla = np.array(tabla)

# SALIDA
np.set_printoptions(precision=3)
print('raiz en: ',raiz)
print(' [  xi, \t xnuevo,\t fxi,\t dfxi, \t tramo]')
print(tabla)

# Gráfica
plt.plot(xi,yi1, label ='yi1')
plt.plot(xi,yi2, label ='yi2')
plt.plot(xi,fi, label ='fi=yi1-yi2')
plt.axvline(raiz,linestyle='dashed')
plt.axhline(0)
plt.xlabel('x')
plt.legend()
plt.title('ecuaciones simultáneas')
plt.show()

s2Eva_IT2019_T3 EDP Elíptica Placa 6×5

La ecuación se discretiza con diferencias divididas centradas

\frac{\partial^2 u}{\partial x^2} (x,y)+\frac{\partial ^2 u}{\partial y^2 } (x,y) = -\frac{q}{K} \frac{u_{i+1,j}-2u_{i,j}+u_{i-1,j}}{(\Delta x)^2} + \frac{u_{i,j+1}-2u_{i,j}+u_{i,j-1}}{(\Delta y)^2}= -\frac{q}{K}

Para procesar los datos se toma como referencia la malla

se agrupan los términos conocidos de las diferencias divididas

\frac{(\Delta y)^2}{(\Delta x)^2} \Big( u_{i+1,j}-2u_{i,j} +u_{i-1,j} \Big) + u_{i,j+1}-2u_{i,j}+u_{i,j-1}=-\frac{q}{K}(\Delta y)^2

Considerando que hx =2, hy= 2.5 son diferentes, se mantiene el valor de λ para el desarrollo.

\lambda = \frac{(\Delta y)^2}{(\Delta x)^2} = \frac{(2.5)^2}{(2)^2} = 1.5625 \lambda u_{i+1,j}-2\lambda u_{i,j} +\lambda u_{i-1,j} + u_{i,j+1}-2u_{i,j}+u_{i,j-1}=-\frac{q}{K}(\Delta y)^2

Se agrupan términos de u que son iguales

\lambda u_{i+1,j}-2(1+\lambda) u_{i,j} +\lambda u_{i-1,j} + u_{i,j+1}+u_{i,j-1}=-\frac{q}{K}(\Delta y)^2

con lo que se puede generar el sistema de ecuaciones a resolver para los nodos de la malla.

i = 1 , j=1

1.5625 u_{2,1}-2(1+ 1.5625) u_{1,1} + 1.5625 u_{0,1} + +u_{1,2}+u_{1,0}=-\frac{1.5}{1.04}(2.5)^2 1.5625 u_{2,1}-5.125u_{1,1} + 1.5625 y_1(5-y_1) + + 0+x_i(6-x_i)=-9.0144 1.5625 u_{2,1}-5.125u_{1,1} + 1.5625[ 1(5-1)]+ + 0+2(6-2)=-9.0144

 

1.5625 u_{2,1}-5.125 u_{1,1} = =-9.0144 - 1.5625 [1(5-1)] - 0-2(6-2)

 

1.5625 u_{2,1}-5.125 u_{1,1} =-23.2644

i=2, j=1

1.5625 u_{3,1}-2(1+1.5625) u_{2,1} +1.5625 u_{1,1} + +u_{2,2}+u_{2,0}=-9.0144

 

1.5625 (0)-5.125 u_{2,1} +1.5625 u_{1,1} + 0 +x_2(6-x_2)=-9.0144 -5.125 u_{2,1} +1.5625 u_{1,1} + 0 +4(6-4)=-9.0144 -5.125 u_{2,1} +1.5625 u_{1,1} =-17.0144

las ecuaciones a resolver son:

1.5625 u_{2,1}-5.125 u_{1,1} =-23.2644 -5.125 u_{2,1} +1.5625 u_{1,1} =-17.0144

cuya solución es:

u_{2,1} = 5.1858 u_{1,1} =6.1204

Resuelto usando:

import numpy as np
A = np.array([[1.5625,-5.125],
             [-5.125, 1.5625]])
B = np.array([-23.2644,-17.0144])
x = np.linalg.solve(A,B)
print(x)

s2Eva_IT2019_T2 Péndulo vertical

Para resolver la ecuación usando Runge-Kutta se estandariza la ecuación a la forma:

\frac{d^2\theta }{dt^2}+\frac{g}{L}\sin (\theta)=0 \frac{d^2\theta }{dt^2}= -\frac{g}{L}\sin (\theta)

Se simplifica su forma a:

\frac{d\theta}{dt}=z = f_t(t,\theta,z) \frac{d^2\theta }{dt^2}= z' =-\frac{g}{L}\sin (\theta) = g_t(t,\theta,z)

y se usan los valores iniciales para iniciar la tabla:

\theta(0) = \frac{\pi}{6} \theta '(0) = 0
ti θ(ti) θ'(ti)=z
0 π/6 = 0.5235 0
0.2 0.3602 -1.6333
0.4 -0.0815 -2.2639

para las iteraciones se usan los valores (-g/L) = (-9.8/0.6)

Iteración 1:  ti = 0 ; yi = π/6 ; zi = 0

K1y = h * ft(ti,yi,zi) 
    = 0.2*(0) = 0
K1z = h * gt(ti,yi,zi) 
    = 0.2*(-9.8/0.6)*sin(π/6) = -1.6333
        
K2y = h * ft(ti+h, yi + K1y, zi + K1z)
    = 0.2*(0-1.6333)= -0.3266
K2z = h * gt(ti+h, yi + K1y, zi + K1z)
    = 0.2*(-9.8/0.6)*sin(π/6+0) = -1.6333

yi = yi + (K1y+K2y)/2 
   = π/6+ (0+(-0.3266))/2 = 0.3602
zi = zi + (K1z+K2z)/2 
   = 0+(-1.6333-1.6333)/2 = -1.6333
ti = ti + h = 0 + 0.2 = 0.2

estimado[i] = [0.2,0.3602,-1.6333]

Iteración 2: ti = 0.2 ; yi = 0.3602 ; zi = -1.6333

K1y = 0.2*( -1.6333) = -0.3266
K1z = 0.2*(-9.8/0.6)*sin(0.3602) = -1.1515
        
K2y = 0.2*(-1.6333-0.3266)= -0.5569
K2z = 0.2*(-9.8/0.6)*sin(0.3602-0.3266) = -0.1097

yi = 0.3602 + ( -0.3266 + (-0.3919))/2 = -0.0815
zi = -1.6333+(-1.151-0.1097)/2 = -2.2639
ti = ti + h = 0.2 + 0.2 = 0.4

estimado[i] = [0.4,-0.0815,-2.2639]

Se continúan con las iteraciones, hasta completar la tabla.

Tarea: realizar la Iteración 3

Usando el algoritmo RungeKutta_fg se obtienen los valores y luego la gráfica

 [ t, 		 y, 	 dyi/dti=z]
[[ 0.          0.52359878  0.        ]
 [ 0.2         0.36026544 -1.63333333]
 [ 0.4        -0.08155862 -2.263988  ]
 [ 0.6        -0.50774327 -1.2990876 ]
 [ 0.8        -0.60873334  0.62920692]
 [ 1.         -0.29609456  2.32161986]]

si se mejora la resolución disminuyendo h = 0.05 y muestras = 20 para cubrir el dominio [0,1] se obtiene el siguiente resultado:

Tarea: Para el literal b, se debe considerar que los errores se calculan con

Runge-Kutta 2do Orden tiene error de truncamiento O(h3)
Runge-Kutta 4do Orden tiene error de truncamiento O(h5)


Algoritmo python

# 3Eva_IT2019_T2 Péndulo vertical
import numpy as np
import matplotlib.pyplot as plt

def rungekutta2_fg(f,g,x0,y0,z0,h,muestras):
    tamano = muestras + 1
    estimado = np.zeros(shape=(tamano,3),dtype=float)
    # incluye el punto [x0,y0,z0]
    estimado[0] = [x0,y0,z0]
    xi = x0
    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
        
        estimado[i] = [xi,yi,zi]
    return(estimado)

# INGRESO theta = y
g = 9.8
L  = 0.6
ft = lambda t,y,z: z
gt = lambda t,y,z: (-g/L)*np.sin(y)

t0 = 0
y0 = np.pi/6
z0 = 0
h=0.2
muestras = 5

# PROCEDIMIENTO
tabla = rungekutta2_fg(ft,gt,t0,y0,z0,h,muestras)

# SALIDA
print(' [ t, \t\t y, \t dyi/dti=z]')
print(tabla)

# Grafica
ti = np.copy(tabla[:,0])
yi = np.copy(tabla[:,1])
zi = np.copy(tabla[:,2])
plt.subplot(121)
plt.plot(ti,yi)
plt.xlabel('ti')
plt.title('yi')
plt.subplot(122)
plt.plot(ti,zi, color='green')
plt.xlabel('ti')
plt.title('dyi/dti')
plt.show()

Otra solución propuesta puede seguir el problema semejante:

s2Eva_IT2010_T2 Movimiento angular

s2Eva_IT2019_T1 Esfuerzo en pulso cardiaco

Para resolver el ejercicio, la función a integrar es el cuadrado de los valores. Para minimizar los errores se usarán TODOS los puntos muestreados, aplicando los métodos adecuados.
Con aproximación de Simpson se requiere que los tamaños de paso sean iguales en cada segmento.
Por lo que primero se revisa el tamaño de paso entre lecturas.

tamaño de paso h:
[0.04 0.04 0.02 0.01 0.01 0.01 0.03 0.04 0.03 0.02 0.  ]
tiempos:
[0.   0.04 0.08 0.1  0.11 0.12 0.13 0.16 0.2  0.23 0.25]
ft:
[ 10.  18.   7.  -8. 110. -25.   9.   8.  25.   9.   9.]

Observando los tamaños de paso se tiene que:
– entre dos tamaños de paso iguales se usa Simpson de 1/3
– entre tres tamaños de paso iguales se usa Simpson de 3/8
– para tamaños de paso variables se usa trapecio.

Se procede a obtener el valor del integral,

Intervalo [0,0.8], h = 0.04

I_{S13} = \frac{0.04}{3}(10^2+4(18^2)+7^2)

Intervalo [0.08,0.1], h = 0.02

I_{Tr1} = \frac{0.02}{2}(7^2+(-8)^2)

Intervalo [0.1,0.13], h = 0.01

I_{S38} = \frac{3}{8}(0.01)((-8)^2+3(110)^2+3(-25)^2+9^2)

Intervalo [0.13,0.25], h = variable

I_{Tr2} = \frac{0.03}{2}(9^2+8^2) I_{Tr3} = \frac{0.04}{2}(8^2+25^2) I_{Tr4} = \frac{0.03}{2}(25^2+9^2) I_{Tr5} = \frac{0.02}{2}(9^2+9^2)

El integral es la suma de los valores parciales, y con el resultado se obtiene el valor Xrms requerido.

I_{total} = \frac{1}{0.08-0}I_{S13}+\frac{1}{0.1-0.08}I_{Tr1} +\frac{1}{0.13-0.1}I_{S38} + \frac{1}{0.16-0.13}I_{Tr2} + \frac{1}{0.2-0.16}I_{Tr3} +\frac{1}{0.23-0.2}I_{Tr4} + \frac{1}{0.25-0.23}I_{Tr5} X_{rms} = \sqrt{I_{total}}

Los valores resultantes son:

Is13:  19.26666666666667
ITr1:  1.1300000000000001
Is38:  143.7
ITr2:  2.175
ITr3:  13.780000000000001
ITr4:  10.59
ITr5:  1.62
Itotal:  5938.333333333333
Xrms:  77.06058222809722

Tarea: literal b

Para Simpson 1/3

error_{trunca} = -\frac{h^5}{90} f^{(4)}(z)

Para Simpson 3/8

error_{truncamiento} = -\frac{3}{80} h^5 f^{(4)} (z)

Para trapecios

error_{truncar} = -\frac{h^3}{12}f''(z)

Algoritmo en Python

# 3Eva_IT2019_T1 Esfuerzo Cardiaco
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
t  = np.array([0.0,0.04,0.08,0.1,0.11,0.12,0.13,0.16,0.20,0.23,0.25])
ft = np.array([10., 18, 7, -8, 110, -25, 9, 8, 25, 9, 9])

# PROCEDIMIENTO
# Revisar tamaño de paso h
n = len(t)
dt = np.zeros(n, dtype=float)
for i in range(0,n-1,1):
    dt[i]=t[i+1]-t[i]

# Integrales
Is13 = (0.04/3)*((10)**2 + 4*((18)**2) + (7)**2)
ITr1 = (0.02/2)*((7)**2 + (-8)**2)
Is38 = (3/8)*0.01*((-8)**2 + 3*((110)**2) + 3*((-25)**2) + (9)**2)

ITr2 = (0.03/2)*((9)**2 + (8)**2)
ITr3 = (0.04/2)*((8)**2 + (25)**2)
ITr4 = (0.03/2)*((25)**2 + (9)**2)
ITr5 = (0.02/2)*((9)**2 + (9)**2)

Itotal = (1/(0.08-0.0))*Is13 + (1/(0.1-0.08))*ITr1
Itotal = Itotal + (1/(0.13-0.1))*Is38 + (1/(0.16-0.13))*ITr2
Itotal = Itotal + (1/(0.20-0.16))*ITr3 + (1/(0.23-0.20))*ITr4
Itotal = Itotal + (1/(0.25-0.23))*ITr5
Xrms = np.sqrt(Itotal)

# SALIDA
print('tamaño de paso h:')
print(dt)
print('tiempos:')
print(t)
print('ft: ')
print(ft)
print('Is13: ', Is13)
print('ITr1: ', ITr1)
print('Is38: ', Is38)
print('ITr2: ', ITr2)
print('ITr3: ', ITr3)
print('ITr4: ', ITr4)
print('ITr5: ', ITr5)
print('Itotal: ', Itotal)
print('Xrms: ', Xrms)

# Grafica
plt.plot(t,ft)
for i in range(1,n,1):
    plt.axvline(t[i], color='green', linestyle='dashed')
plt.xlabel('tiempo s')
plt.ylabel('valor sensor')
plt.title('Un pulso cardiaco con sensor')
plt.show()