Ejercicio: 1Eva2018TI_T3 Temperatura en nodos de placa

literal a
Plantear el sistema de ecuaciones. Usando el promedio para cada nodo interior, según el enunciado:
La temperatura en los nodos de la malla de una placa se puede calcular con el promedio de las temperaturas de los 4 nodos vecinos de la izquierda, derecha, arriba y abajo.
a=\frac{50+c+100+b}{4} b=\frac{a+30+50+d}{4} c=\frac{a+60+100+d}{4} d=\frac{b+60+c+30}{4}que reordenando se convierte en:
4a=150+c+b 4b=a+80+d 4c=a+160+d 4d=b+c+90simplificando:
4a-b-c= 150 a-4b+d = -80 a-4c+d = -160 b+c-4d = -90que a forma matricial se convierte en:
A = [[ 4, -1, -1, 0],
[ 1, -4, 0, 1],
[ 1, 0, -4, 1],
[ 0, 1, 1,-4]]
B = [150,-80,-160,-90]
Observación: la matriz A ya es diagonal dominante, no requiere pivotear por filas. Para usar el algoritmo se requiere convertir A y B en arreglos:
A = np.array(A, dtype=float)
B = np.array(B, dtype=float)
El número de condición es:
np.linalg.cond(A) = 3.0
que es cercano a 1 en un orden de magnitud, por lo que la solución matricial es "estable" y los cambios en los coeficientes afectan proporcionalmente a los resultados. Se puede aplicar métodos iterativos sin mayores inconvenientes.
b y c) método de Jacobi para sistemas de ecuaciones, con vector inicial
X(0) = [60.0,40,70,50]
reemplazando los valores iniciales en cada ecuación sin cambios.
iteración 1
a=\frac{50+70+100+40}{4} = 65 b=\frac{60+30+50+50}{4} = 47.5 c=\frac{60+60+100+50}{4} = 67.5 d=\frac{40+60+70+30}{4} = 50X(1) = [65,47.5,67.5,50]
vector de error = [ |65-60|,|47.5-40|,|67.5-70|,|50-50|]
= [ |5|,|7.5|,|-2.5|,|0| ]
errormax = 7.5
iteración 2
a=\frac{50+67.5+100+47.5}{4} = 66.25
X(2) = [66.25,48.75,68.75,51.3]
vector de error = [ |66.25-65|, |48.75-47.5|,|68.75-67.5|,|51.3-50| ]
= [ |1.25|,|1.25|,|1.25|,|1.3| ]
errormax = 1.3
iteración 3
a=\frac{50+68.75+100+48.75}{4} = 66.875 b=\frac{66.25+30+50+51.3}{4} = 49.38 c=\frac{66.25+60+100+51.3}{4} = 69.3875 d=\frac{48.75+60+68.75+30}{4} = 51.875X(2) = [66.875,49.38,69.3875,51.875]
vector de error = [ |66.875-66.25|,|49.38-48.75|,|69.3875-68.75|,|51.875-51.3| ]
= [ |0.655|,|0,63|,|0.6375|,|0.575| ]
errormax = 0.655
con error relativo de:
100*0.655/66.875 = 0.97%
siguiendo las iteraciones se debería llegar a:
>>> np.linalg.solve(A,B)
array([67.5, 50., 70., 52.5])
Algoritmo en Python
Matriz aumentada
[[ 4. -1. -1. 0. 150.]
[ 1. -4. 0. 1. -80.]
[ 1. 0. -4. 1. -160.]
[ 0. 1. 1. -4. -90.]]
Pivoteo parcial:
Pivoteo por filas NO requerido
Iteraciones Jacobi
itera,[X]
,errado,|diferencia|
0 [60. 40. 70. 50.]
nan
1 [65. 47.5 67.5 50. ]
7.5 [5. 7.5 2.5 0. ]
2 [66.25 48.75 68.75 51.25]
1.25 [1.25 1.25 1.25 1.25]
3 [66.875 49.375 69.375 51.875]
0.625 [0.625 0.625 0.625 0.625]
4 [67.1875 49.6875 69.6875 52.1875]
0.3125 [0.3125 0.3125 0.3125 0.3125]
5 [67.3438 49.8438 69.8438 52.3438]
0.15625 [0.1562 0.1562 0.1562 0.1562]
6 [67.4219 49.9219 69.9219 52.4219]
0.078125 [0.0781 0.0781 0.0781 0.0781]
7 [67.4609 49.9609 69.9609 52.4609]
0.0390625 [0.0391 0.0391 0.0391 0.0391]
8 [67.4805 49.9805 69.9805 52.4805]
0.01953125 [0.0195 0.0195 0.0195 0.0195]
9 [67.4902 49.9902 69.9902 52.4902]
0.009765625 [0.0098 0.0098 0.0098 0.0098]
10 [67.4951 49.9951 69.9951 52.4951]
0.0048828125 [0.0049 0.0049 0.0049 0.0049]
11 [67.4976 49.9976 69.9976 52.4976]
0.00244140625 [0.0024 0.0024 0.0024 0.0024]
12 [67.4988 49.9988 69.9988 52.4988]
0.001220703125 [0.0012 0.0012 0.0012 0.0012]
13 [67.4994 49.9994 69.9994 52.4994]
0.0006103515625 [0.0006 0.0006 0.0006 0.0006]
Metodo de Jacobi
numero de condición: 3.000000000000001
X: [67.4994 49.9994 69.9994 52.4994]
errado: 0.0006103515625
iteraciones: 13
>>>

Algoritmo en Python
# 1Eva2018TI_T3 Temperatura en nodos de placa
# Metodo de Jacobi para sistemas de ecuaciones
import numpy as np
def jacobi(A,B,X0, tolera, iteramax=100,
vertabla=False, precision=4):
''' Método de Jacobi, tolerancia, vector inicial X0
para mostrar iteraciones y tabla: vertabla=True
'''
# Matrices como arreglo, numeros reales
A = np.array(A,dtype=float)
B = np.array(B,dtype=float)
X0 = np.array(X0,dtype=float)
tamano = np.shape(A) # tamaño A
n = tamano[0]
m = tamano[1]
# valores iniciales
diferencia = 2*tolera*np.ones(n, dtype=float)
errado = 2*tolera # np.max(diferencia)
tabla = [np.copy(X0)] # tabla de iteraciones
tabla = np.concatenate((tabla,[[np.nan]]),
axis=1) # errado
if vertabla==True:
print('Iteraciones Jacobi')
print('itera,[X]')
print(' ,errado,|diferencia|')
print(0,X0)
print(' ',np.nan)
np.set_printoptions(precision)
itera = 0 # Jacobi
X = np.copy(X0)
Xnuevo = np.copy(X0)
while errado>tolera and itera<=iteramax:
for i in range(0,n,1): # una ecuacion
suma = B[i]
for j in range(0,m,1): # un coeficiente
if (i!=j): # excepto diagonal de A
suma = suma-A[i,j]*X[j]
Xnuevo[i] = suma/A[i,i]
diferencia = abs(Xnuevo-X)
errado = np.max(diferencia)
X = np.copy(Xnuevo)
Xfila = np.concatenate((Xnuevo,[errado]),axis=0)
tabla = np.concatenate((tabla,[Xfila]),axis=0)
itera = itera + 1
if vertabla==True:
print(itera, Xnuevo)
print(' ',errado,diferencia)
# No converge
if (itera>iteramax):
X = np.nan
print('No converge,iteramax superado')
if vertabla==True:
X = [X,tabla]
return(X)
def pivoteafila(A,B,vertabla=False):
'''
Pivotea parcial por filas, entrega matriz aumentada AB
Si hay ceros en diagonal es matriz singular,
Tarea: Revisar si diagonal tiene ceros
'''
A = np.array(A,dtype=float)
B = np.array(B,dtype=float)
# Matriz aumentada
nB = len(np.shape(B))
if nB == 1:
B = np.transpose([B])
AB = np.concatenate((A,B),axis=1)
if vertabla==True:
print('Matriz aumentada')
print(AB)
print('Pivoteo parcial:')
# Pivoteo por filas AB
tamano = np.shape(AB)
n = tamano[0]
m = tamano[1]
# Para cada fila en AB
pivoteado = 0
for i in range(0,n-1,1):
# columna desde diagonal i en adelante
columna = np.abs(AB[i:,i])
dondemax = np.argmax(columna)
# dondemax no es en diagonal
if (dondemax != 0):
# intercambia filas
temporal = np.copy(AB[i,:])
AB[i,:] = AB[dondemax+i,:]
AB[dondemax+i,:] = temporal
pivoteado = pivoteado + 1
if vertabla==True:
print(' ',pivoteado, 'intercambiar filas: ',i,'y', dondemax+i)
if vertabla==True:
if pivoteado==0:
print(' Pivoteo por filas NO requerido')
else:
print('AB')
print(AB)
return(AB)
# PROGRAMA Búsqueda de solucion --------
# INGRESO
A = [[ 4, -1, -1, 0.0],
[ 1, -4, 0, 1.0],
[ 1, 0, -4, 1.0],
[ 0, 1, 1,-4.0]]
B = [150,-80,-160,-90]
X0 = [60.0,40,70,50]
tolera = 0.001
iteramax = 100
verdecimal = 4
# PROCEDIMIENTO
AB = pivoteafila(A,B,vertabla=True)
n,m = np.shape(AB)
A = AB[:,:n] # separa en A y B
B = AB[:,n]
[X, tabla] = jacobi(A,B,X0,tolera,iteramax,
vertabla=True,
precision=verdecimal)
n_itera = len(tabla)-1
errado = tabla[-1,-1]
# numero de condicion
ncond = np.linalg.cond(A)
# SALIDA
print('Metodo de Jacobi')
print('numero de condición:', ncond)
print('X: ',X)
print('errado:',errado)
print('iteraciones:', n_itera)
# GRAFICA de iteraciones
errados = tabla[:,n]
import matplotlib.pyplot as plt
# grafica de error por iteracion
fig2D = plt.figure()
graf = fig2D.add_subplot(111)
graf.plot(errados)
graf.set_xlabel('itera')
graf.set_ylabel('|error|')
graf.set_title('Método de Jacobi: error[itera]')
graf.grid()
plt.show()