Test 2: Caso 1D - Couette Generalizado

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:

  • El flujo se presenta únicamente en la dirección $x$ ($v=w=0$).
  • El gradiente de presión al que está sometido el fluido es constante ($\frac{\partial p}{\partial x} = \frac{\Delta p}{\ell}$).
  • El flujo no depende de la coordenada $z$ ($\frac{\partial}{\partial z}=0$).
  • El fluido se encuentra en estado estacionario ($\frac{\partial}{\partial t}=0$).
  • No hay fuerzas externas afectando el flujo ($f_x=f_y=f_z=0$).

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:

  • Introducción de la información del problema
  • Definición de los elementos a usar (cantidad $N_E$ y distribución, así como sus órdenes $N_P(i)$)
    • Selección de los nodos de interpolación a usar
    • Generación de la matriz de conectividad
    • Definición de la función de entrada
  • Generación de la matriz del problema
    • Generación de la matriz de difusión y el vector b
  • Solución del sistema resultante
  • Gráfica de la solución obtenida

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

Introducción de la información del problema

Se introducen los parámetros del problema. En este caso se tienen los parámetros $\mu$, $\nabla p$, $L$ y $U_0$.


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])

Definición de los elementos a usar

Se define primero el número de elementos y su distribución, así como los órdenes de cada uno de los mismos. Por simplicidad, inicialmente se toman elementos uniformemente espaciados.


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)

Selección de los nodos de interpolación a usar

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)

Generación de la matriz de conectividad

Una vez se definen los nodos, se utiliza la matriz de conectividad para almacenar de manera ordenada la numeración local y global de los mismos


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()

Definición de la función de entrada

Especifica $s(x)$ para cada uno de los nodos

# Construye la función de entrada ## s = lambda x: 10.*np.exp(-5.*(x**2)/L**2) # Función de prueba correspondiente al ejemplo del libro de Pozrikidiz s = lambda x,y: -p[x] # Para x en 0,1,2,3,4

Generación de la matriz del problema

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$$

Generación de la matriz de difusión y el vector b

Se recorre sobre los elementos para acoplar las matrices de cada elemento en un sistema global, aprovechando la matriz de conectividad

Solución del sistema resultante

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.

Gráfica de la solución obtenida

Una vez resuelto el sistema, es posible visualizar el resultado obtenido por medio de una gráfica. En este caso se conoce que la solución analítica corresponde a la linea recta entre las dos condiciones extremas, y se incluye también su gráfica.


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 [ ]: