En el flujo de Couette generalizado, el fluido se encuentra confinado entre placas planas paralelas infinitas separadas por una distancia constante $L$ y se encuentra sometido a un gradiente de presión en dirección paralela a las placas. Adicionalmente, las velocidades de las placas son de $U_0$ y $U_1$ (en dirección x) respectivamente. De acuerdo con esto, se tienen las siguientes consideraciones:
De aquí, las ecuaciones de continuidad y de Navier-Stokes se reducen a:
\begin{align} \frac{\partial \rho}{\partial t} + \nabla\cdot(\rho \vec{u})=0 \quad &\to\quad \frac{\partial u}{\partial x}=0 \\ \rho\left(\frac{\partial \vec{u}}{\partial t}+\vec{u}\cdot\nabla\vec{u}\right)=\rho\vec{f}-\nabla p+\mu\nabla^2\vec{u}\quad &\to\quad 0=-\frac{\Delta p}{\ell}+\mu\frac{\partial^2u}{\partial y^2} \end{align}Se puede ver entonces que la ecuación resultante es un caso particular del problema de difusión estable:
$$k\frac{d^2 f}{d x^2}+s(x)=0$$Donde $k = \mu$, y $s(x)=-\frac{\Delta p}{\ell}$, y las condiciones de frontera corresponden a valores conocidos (tipo Dirichlet):
$$u(0)=U_0\quad u(L)=U_1$$Ahora, para aplicar el método de elementos espectrales, es necesario realizar los siguientes pasos:
Cada uno de los pasos se tratará en detalle a continuación
In [1]:
# Prepara el ambiente de trabajo con las librerías a utilizar
import numpy as np # Ofrece funciones para operaciones básicas con arreglos
import scipy.linalg as lin # Ofrece funciones para operaciones de álgebra lineal
import matplotlib.pyplot as plt # Permite incluir un ambiente de visualización
import timeit # Permite la medición de tiempos para los distintos algoritmos
from sem1D import * # Agrupa las funciones externas en un archivo
#%pylab inline
In [2]:
## Valores de prueba correspondientes al ejemplo del libro de Pozrikidis
# L = 1.
# mu = 1.
# U0 = 1.9639
# U1 = 0.
L = 2.
mu = 1.
U0 = 0.
U1 = 50.
p = np.array([-40,-20,0,20,40])
In [3]:
Ne = 6
Np = np.array((1,3,5,6,4,2))
# Genera los puntos correspondientes a los nodos extremos de cada elemento
(xe, h) = np.linspace(0,L,Ne+1,retstep=True)
Conociendo el número de elementos y su distribución, es posible generar los nodos correspondientes a los extremos de cada elemento. Sin embargo, como no se trabaja con elementos lineales (cada elemento tiene un orden), es necesario generar los nodos intermedios para cada elemento. Para ello, es necesario definir la familia de polinomios sobre la cual van a estar basados estos nodos. En este caso se utilizan los nodos de interpolación de Lobatto.
In [4]:
xint = genNodes(Ne,Np,xe)
In [5]:
(xglob, C) = genConn(Ne,Np,xint)
In [6]:
# Permite visualizar todos los nodos a utilizar
plt.plot(xe,np.zeros(xe.size),'bo',xglob,np.zeros(xglob.size),'r.')
plt.xlabel('Posicion (coord y)')
plt.show()
Para la generación de la matriz del problema es necesario definir cada una de las matrices de difusión y de masa por cada elemento:
$$\Theta_{ij}=\int_{-1}^1 \psi_i(\xi)\psi_j(\xi)d\xi \quad \Psi_{ij}=\int_{-1}^1 \frac{d\psi_i}{d\xi}\frac{d\psi_j}{d\xi}d\xi$$En este caso se aplica la cuadratura de Lobatto para la construcción de dichas matrices, con lo que se obtienen los siguientes resultados:
$$\Theta=\sum_{p=1}^{N_p+1} m_{ip}m_{jp}w_p \quad \Psi_{ij}=\sum_{p=1}^{N_p+1} d_{ip}d_{jp}w_p$$Teniendo ya construidos los componentes del sistema a resolver, basta aplicar un esquema de solución razonable para el tipo de matriz obtenida. En este caso se utiliza el solucionador por defecto del módulo linalg. Dado que los valores para el primer y último nodo son conocidos, se omiten los valores correspondientes.
In [7]:
plt.plot(np.linspace(U0,U1,Ne+1),xe,'-.or',ms=8)
plt.hold(True)
for it in range(5):
(Mat_dif, vec_b) = matDiff(Ne,Np,xe,xglob,C,U0,U1,mu,s= lambda x: -p[it])
sol = np.zeros(xglob.size-2)
A = Mat_dif[1:-1,1:-1]
sol = lin.solve(A,vec_b[1:-1])
solG = np.concatenate([[U0],sol,[U1]])
if(it == 0):
plt.plot(solG,xglob,'-ob',label='p = -40')
elif(it == 1):
plt.plot(solG,xglob,'--*g',label='p = -20')
elif(it == 2):
plt.plot(solG,xglob,'-.+c',label='p = 0')
elif(it == 3):
plt.plot(solG,xglob,':xm',label='p = 20')
else:
plt.plot(solG,xglob,'--vk',label='p = 40')
valy = np.linspace(0,L,100)
for num in range(5):
vec = np.zeros(xglob.size)
vec = p[num]/(2.*mu)*(valy**2-L*valy)+(U1-U0)/L*valy+U0
plt.plot(vec,valy,':r')
plt.legend(loc='upper left')
plt.title('Velocidades para Distintos Valores del Gradiente')
plt.ylabel('Posicion (coord y)')
plt.xlabel('Velocidad (U)')
plt.show()
In [ ]: