Modelado de Medios Porosos Interactuando con Fluidos

74
Tesis de Grado Modelado de Medios Porosos Interactuando con Fluidos Santiago Tolley Directores: Dr. Gustavo Boroni Dr. Javier Dottori Facultad de Ciencias Exactas Universidad Nacional del Centro de la Provincia de Buenos Aires Tandil

Transcript of Modelado de Medios Porosos Interactuando con Fluidos

Page 1: Modelado de Medios Porosos Interactuando con Fluidos

Tesis de Grado

Modelado de Medios Porosos Interactuando con Fluidos

Santiago Tolley

Directores: Dr. Gustavo Boroni Dr. Javier Dottori

Facultad de Ciencias Exactas

Universidad Nacional del Centro de la Provincia de Buenos Aires Tandil

Page 2: Modelado de Medios Porosos Interactuando con Fluidos

Indice Capítulo 1: Introducción

Capítulo 2: Marco Teórico Resumen LBM El Método Immersed Boundary (IB) Modelado de Medios Porosos

Capítulo 3: Implementación Resumen Implementación de LBM Implementación de Medios Porosos Simulación

Inicialización Ejecución Finalización Post-Procesamiento

Parámetros de la Simulación

Capítulo 4: Resultados Resumen Casos de Estudio

Condiciones de Contorno Parámetros de la Simulación

Análisis de un Flujo Laminar Parámetros del Flujo Laminar Análisis de un Flujo Turbulento Parámetros del Flujo Turbulento

Resultados Flujo Laminar Análisis de Perfil Laminar en un Punto Análisis de Perfil Laminar en un Corte Flujo Turbulento

Page 3: Modelado de Medios Porosos Interactuando con Fluidos

Efecto de Von Karman Análisis de Perfil Turbulento en un Punto Análisis de Perfil Turbulento en un Corte Comparativa de Ambos Flujos

Capítulo 5: Conclusión

Referencias

Apéndice 1: Código Main/Principal

Apéndice 2: Código de Medio Poroso

Apéndice 3: Entorno y Compilación

Apéndice 4: Archivos

Page 4: Modelado de Medios Porosos Interactuando con Fluidos

Capítulo 1: Introducción La simulación numérica de fluidos tiene importantes aplicaciones en distintas áreas de la ciencia. En particular, analizar el flujo en medios porosos es de gran interés en una variedad de dominios, como las corrientes de fluidos a través de cultivos o plantaciones acuáticas (Levy, 2014; Lima, 2015; Mattis, 2015). En aplicaciones tecnológicas puede verse en problemas como en el enfriamiento de componentes electrónicos (Bhukta, 2014; Mahdi, 2015) y en desviadores de flujos en aneurismas cerebrales (Bouillot, 2016) entre otros. Un ejemplo de esta última puede verse en la Figura 1.1.

Figura 1.1. Modelado del flujo sanguíneo en un aneurisma cerebral (Acevedo-Malavé, 2017). Una característica interesante de estos ujos es que fácilmente se convierten en inestables en el límite entre la zona permeable y el ujo libre (White, 2007). Esta inestabilidad está asociada

Page 5: Modelado de Medios Porosos Interactuando con Fluidos

a puntos de inexión del perl de velocidad, y se maniesta como estructuras de ondas y vórtices coherentes que amplican la difusión de momento en la dirección transversal al ujo (Coppola, 2009; Ozalp, 2010). La Figura 1.2 muestra un ejemplo de un flujo inestable. Estas estructuras son útiles por modicar los escalares del transporte no sólo donde las estructuras son generadas, sino también dentro y fuera de la obstrucción. Así pueden favorecer procesos como la polinización, transferencia de calor y masa, y transporte de nutrientes (Pan, 2014; Patton 2016). Una gran cantidad de estudios analíticos recientes han tenido como objetivo la caracterización de la estabilidad de canales parcialmente penetrables (Deepu, 2015; Roşca, 2013; Sajjadi, 2013; Silin, 2011; White, 2007).

Figura 1.2. Desprendimiento de vórtices causado por la interacción de un flujo con una obstrucción. Este fenómeno se conoce como calle de vórtices de von Karman. (Van Dyke, 1982). El método de lattice-Boltzmann (lattice-Boltzmann Method - LBM) es un método basado en autómatas celulares utilizado para en simulación numérica de fluidos que permite reproducir las reglas físicas que rigen al fluido en el nivel macroscópico (Chen, 1998). Un método utilizado comúnmente para modelar la interacción entre fluido y estructura es el método frontera inmersa (Immersed Boundary - IB) (Boroni, 2013; Peskin, 2002). Dicho método propone representar la estructura sobre una grilla euleriana mediante una sucesión de puntos con coordenadas lagrangianas que se unen formando una curva o supercie. La frontera inmersa es considerada como una bra elástica o una membrana sin masa que se mueve con la velocidad local del uido. En el trabajo de Boroni (2015) se planteó un modelo basado en la representación de la interacción con regiones permeables mediante fuerzas, siguiendo un procedimiento similar al del método IB. La diferencia con IB radica en que utiliza puntos de referencia independientes, y que la fuerza ejercida sigue la ley de Darcy.

Page 6: Modelado de Medios Porosos Interactuando con Fluidos

En este trabajo se desarrolló una herramienta que permite modelar fluidos interactuando con obstrucciones porosas, utilizando el método especificado en Boroni (2015). La implementación del método de lattice-Boltzmann se llevó a cabo mediante el uso de el framework open source OpenLB (OpenLB), elegido por las múltiples facilidades que ofrece. La simulación se divide en tres etapas marcadas: inicialización de estructuras de trabajo, ejecución del bucle principal y finalización. Luego de la simulación se realiza un post-procesamiento de los datos extraídos para facilitar su análisis.

Para validar la herramienta se construyeron casos de estudio a partir de un canal parcialmente obstruido por un medio poroso. Con este experimento se analizó el efecto del medio poroso sobre el flujo.

Utilizando programas como ParaView (ParaView) es posible visualizar los resultados de la simulación.

Figura 1.3. Aplicación open source para análisis de datos ParaView.

Page 7: Modelado de Medios Porosos Interactuando con Fluidos

Capítulo 2: Marco Teórico

Resumen En este capítulo se presentan las bases teóricas que rigen al modelo implementado: el método de lattice-Boltzmann, el método de Frontera Inmersa y el modelado de medios porosos. El método de lattice-Boltzmann (lattice-Boltzmann Method - LBM) es un método basado en autómatas celulares utilizado para la simulación numérica de fluidos. El método de frontera inmersa (Immersed Boundary - IB) que se usa para modelar estructuras sólidas interactuando con fluidos. Y por último el modelado de medios porosos, el cual se aplica siguiendo un enfoque basado en el método de frontera inmersa.

LBM LBM es un método basado en autómatas celulares utilizado para en simulación numérica de fluidos, que permite reproducir las reglas físicas que rigen al fluido en el nivel macroscópico (Chen, 1998). Opera en una grilla espacial regular con actualización de estados en tiempos discretos. El estado de cada celda de la grilla en el tiempo t está definido por funciones escalares que representan la función de distribución de partículas f i que se mueven con velocidad e i . El conjunto de velocidades está definido por la discretización de la ecuación de Boltzmann en el espacio de las fases. De esta manera, cada esquema LBM se clasifica con el código DdQq , donde d es la dimensión espacial (d = 1, 2 ó 3) y q es el número de velocidades permitidas. El esquema más común para dos dimensiones es el D2Q9 .

Figura 2.1. Esquema D2Q9.

Page 8: Modelado de Medios Porosos Interactuando con Fluidos

En cada celda colisionan las partículas y luego se desplazan a las celdas vecinas. Así, la ecuación fundamental de LBM gobierna la variación del estado de las celdas a través de un paso de colisión y uno de advección, según las ecuaciones 2.1 y 2.2 respectivamente

(2.1)

(2.2)

donde i = 0..8 según las direcciones del esquema D2Q9. En este caso τ es un parámetro de

relajación que servirá para controlar la viscosidad del fluido, x la posición de la celda, Δt el

paso de tiempo, f ie la distribución de equilibrio, f i

’ la función de densidad de partículas en el siguiente paso de tiempo, y gi  es el término asociado a las fuerzas externas que se aplican en el fluido, cuya expresión está dada por

(2.3) donde c s es una pseudo-velocidad del sonido, u es la velocidad del fluido, y g es la fuerza,   definida como

(2.4) siendo a la aceleración causada por la fuerza g y ρ la densidad de partículas.

El parámetro cs2 toma el valor 1/3 en unidades de (Δ x/Δ t)2 .

Los coeficientes wi dependen del tipo y dimensión de la grilla. Para el esquema D2Q9 se tiene(Geier, 2006)

(2.5)

Page 9: Modelado de Medios Porosos Interactuando con Fluidos

La relación entre c s , la presión (p ) y la densidad ( ) está dada porρ

(2.6)

La función f i

e distribución de equilibrio se construye a partir de la densidad ( ) y la velocidad (u ) ρ macroscópica definidas por

(2.7)

(2.8) Estas variables macroscópicas son los observables del sistema. La inclusión del término de fuerza en (2.8) garantiza la precisión de segundo orden (Guo Z, 2002). La distribución de equilibrio es clave para que la ecuación de LBM se comporte como las ecuaciones de un fluido. El esquema Bhatnagar-Gross-Krook (BGK) (Bhatnagar et al. 1954), el cual reproduce las ecuaciones de Navier-Stokes (N-S) (Chen H,1992), propone el siguiente polinomio de segundo orden en u/c s . La función de equilibrio se calcula solo en base a variables macroscópicas locales

(2.9) La viscosidad del fluido queda determinada por el parámetro de relajación de acuerdo a

(2.10)

Page 10: Modelado de Medios Porosos Interactuando con Fluidos

Desarrollando una versión simplificada y discretizada de la física de partículas, se evita resolver ecuaciones cinemáticas complicadas como las ecuaciones completas de Boltzmann o simular cada partícula por separado.

El Método Immersed Boundary (IB) En general, las condiciones de contorno en LBM se introducen a nivel de la población; por ejemplo, las condiciones típicas de este tipo son de rebote o condiciones de contorno regularizados. Otra posibilidad es utilizar el término de fuerza para emular condiciones de contorno. Esto se puede aplicar para simular objetos deformables o rígidos inmersos en el flujo. Teniendo en cuenta que estas fuerzas pueden generarse de la interacción fluido-estructura se suele separar el término de fuerza en dos partes; por una lado las contribuciones físicas, como por ejemplo la gravedad; y por otro lado el campo de fuerza generado por las condiciones de contorno (Cheng, 2010). En particular, el método de fronteras inmersas (IB – Immersed Boundary) fue introducido por Peskin (1977) en simulaciones de problemas de fluidos cardiovasculares. Cuando se aplica IB sobre un fluido se tienen dos sistemas de coordenadas: la red Euleriana para el fluido, y la malla Lagrangiana asociada a los puntos de frontera (ver Figura 2.2). La información entre ambos sistemas de coordenadas es comunicada por interpolaciones. En este sentido el desplazamiento del fluido es afectado por los términos de fuerza, y se comporta como si hubiera una frontera sólida flexible.

Page 11: Modelado de Medios Porosos Interactuando con Fluidos

Figura 2.2. Immerse Boundary en un lattice 2D. Los puntos de la frontera en el dominio Γb están representados por funciones X (s , t ) (con longitud de arco s), que permiten obtener las posiciones de los nodos x k . La influencia de la frontera alrededor de x k está representada por la densidad de fuerza F k , la cual es transferida al dominio del fluido Ωf a través del término de fuerza de la Eq. 2.1. La densidad de fuerza F k está definida por la configuración de la frontera, considerando las fuerzas de tensión, flexión y fijación

(2.11) donde X es la posición de referencia del punto; k c , k γ y k f son los coeficientes de tensión, flexión y fijación respectivamente, y Z la posición objetivo de la frontera. La discretización de la Eq. 2.11 puede ser expresada por

Page 12: Modelado de Medios Porosos Interactuando con Fluidos

(2.12) En Cheng y Zhang (2010) se propuso un método de interacción de LBM con el método de IB para simular el movimiento de paredes curvas en una válvula mitral cardíaca. Este método desacopla las soluciones de las ecuaciones que gobiernan el comportamiento del fluido y las condiciones de contorno. El efecto del contorno sobre el fluido circundante se sustituye por la adición de fuerzas a las ecuaciones de fluidos. Así, el acoplamiento LBM-IB queda expresado por

,

(2.13)

(2.14) donde h =Δx es el espacio nodal, y Δs k es la longitud del segmento de x k , y F IB es el término de fuerza externa que se aplica al fluido. La función delta δ h es una aproximación de la función de distribución Dirac dada por

(2.15)

(2.16) En la ecuación Eq. 2.13, las fuerzas que actúan sobre la frontera también actúan sobre el fluido (acción-reacción), lo cual asegura la conservación de momento. En la ecuación Eq. 2.14 la velocidad de la frontera se calcula a partir de la velocidad del fluido. Detalles del algoritmo

Page 13: Modelado de Medios Porosos Interactuando con Fluidos

numérico y de implementación del modelo acoplado IB-LBM puede encontrarse en Boroni et al. (2013).

Modelado de Medios Porosos LBM se distingue de otros métodos utilizados para modelar problemas de fluidos en medios porosos. La ventaja de LBM es que tiene mucha flexibilidad para introducir interacciones a nivel local, ya sea modificando las reglas de actualización de las poblaciones o mediante el término de fuerza externa. De la primera opción se pueden obtener buenos resultados utilizando un modelo de bounce-back parcial (Bhatnagar et al. 1954), que introduce una pseudo-condición de contorno en las celdas de la zona porosa. Sin embargo, cuando se desea modelar regiones complejas, es necesario trabajar con grillas de tamaños significativos para lograr la representación del objeto a partir de una configuración de celdas. Los mejores resultados se lograron con un modelo de fuerzas distribuidas alrededor de puntos de referencia, el cual se describe a continuación. Una propuesta para modelar un flujo en medios porosos en LBM es por medio del término fuerza externa. En efecto, un medio poroso se caracteriza por ofrecer una resistencia al movimiento por unidad de volumen que satisface la ley de Darcy

(2.17) donde υ es la viscosidad dinámica y κ es la permeabilidad. Este modelo es atrayente por lo simple que resulta su implementación considerando las Eq. 2.1 y 2.3; no obstante, pruebas numéricas realizadas mostraron diferencias significativas con los experimentos, especialmente en rangos inestables (Silin, 2011). El análisis de los resultados llevó a la conclusión que la principal razón de las diferencias estaba asociada a la distribución de las fuerzas sobre las celdas adyacentes. En base a estas observaciones, Dottori (2016) propuso un modelo de fuerzas distribuidas alrededor de puntos de referencia, basado en el método de frontera inmersa. La zona porosa se define en este modelo con un conjunto de puntos de referencia x k , cada uno de los cuales aporta un término de fuerza a su entorno cercano, dado por

(2.18)

Page 14: Modelado de Medios Porosos Interactuando con Fluidos

donde ν es la viscosidad cinemática, δ h es una aproximación de la función delta de Dirac (Eq. 2.15) y U k es la velocidad característica del vecindario. Es decir, la fuerza se distribuye entre las celdas que se encuentran a una cierta distancia del punto de referencia x k , siguiendo la ley de Darcy. El signo negativo indica que la fuerza se opone al movimiento del fluido. La velocidad característica se calcula como la velocidad de las celdas del vecindario ponderadas por su distancia al punto de referencia x k

(2.19) Los puntos de referencia son equivalentes a los nodos x k de la frontera del método de frontera inmersa, con dos diferencias fundamentales: los puntos de referencia son fijos e independientes. Esto significa que no se desplazan con el fluido ni ejercen fuerzas unos sobre otros.

Page 15: Modelado de Medios Porosos Interactuando con Fluidos

Capítulo 3: Implementación

Resumen En este capítulo se describe la implementación de las distintas partes del sistema: la implementación de LBM y el método de medios porosos, la ejecución de la simulación, y el post-procesamiento de los datos obtenidos. La implementación de LBM se realizó mediante el framework OpenLB. Finalmente se presentan los parámetros utilizados por la herramienta para configurar los modelos y la simulación.

Implementación de LBM Inicialmente se optó por implementar la solución propuesta sobre un código propio, sin el uso de un framework. El objetivo fue analizar cada una de las partes de los métodos involucrados y así poder comprender mejor los pros y contras de su implementación. Posteriormente, se consideró utilizar un framework que optimice las funciones principales de LBM para asegurar una buena performance, enfocando el trabajo en el diseño e implementación del método de medios porosos. Concretamente, para la implementación de LBM se utilizó un framework open source orientado a objetos llamado OpenLB (OpenLB). Para la selección del mismo se tuvieron en cuenta frameworks que implementan LBM y reconocidos en el ambiente científico, tales como Palabos, waLBerla y Hemo LBM. La comparación se realizó en base a las siguientes características según la propuesta de desarrollo: ecuaciones que modela, almacenamiento de resultados, carga de parámetros a la simulación, posibilidad de guardados parciales (checkpoints), posibilidades de paralelización, y la existencia de foros activos con ejemplos, lo cual es de mucha ayuda en caso de que sea necesario consultar problemas puntuales. En la Tabla 3.1 se muestra el resumen del relevamiento realizado.

Page 16: Modelado de Medios Porosos Interactuando con Fluidos

Motor Ecuación que Modela

Almacenamiento de Resultados

Carga de Parámetros

Guardados Parciales

Ejecución Paralela

Tutoriales o Ejemplos

Foro Activo

OpenLB - BGK - MRT - Medios Porosos etc

- VTK - VTI

XML (OpenGPI)

Si Si Múltiples ejemplos

Si

Palabos - BGK - MRT - Reg BGK - RLB - LW-ACM

VTK XML Si Si 1 Tutorial Si

Hemo LBM

BKG VTK Sin Info Si Si No No

waLBerla

SRT, TRT, MRT

Sin Info Sin Info No No 1 Tutorial No

Tabla 3.1: Comparación de frameworks para la implementación de LBM. En base al análisis se decidió utilizar OpenLB, teniendo en cuenta que modela la ecuación BGK (entre otras), facilita el ingreso de parámetros a la simulación por medio de archivos xml, posee la capacidad de realizar guardados parciales (checkpoints), permite paralelización (aunque no es utilizada en el presente trabajo), permite trabajar tanto con el modelo compresible como con el incompresible, incorpora clases que permiten la escritura de archivos .vtk para su posterior visualización o post-procesamiento mediante otros programas como ParaView, y cuenta con el apoyo de un foro activo, entre otros.

Implementación de Medios Porosos La implementación del medio poroso sigue el enfoque propuesto por Boroni (2015) explicado en el Capítulo 2, adaptado al framework OpenLB. Consiste en una variante del método de Frontera Inmersa (Immersed Boundary - IB), en donde los puntos de referencia son fijos e independientes.

Page 17: Modelado de Medios Porosos Interactuando con Fluidos

Mediante este método, se calcula la fuerza ejercida sobre el punto mediante una suma ponderada (mediante la función Delta de Dirac (Eq. 2.15), según su distancia al punto) de las velocidades de las celdas en un radio cercano al punto (Eq. 2.19). Posteriormente, esta fuerza es distribuida en las celdas cercanas, nuevamente ponderando por la distancia hacia el punto según la ecuación 2.18. El medio poroso se implementa como una clase (“PorousMedium”) que contiene los puntos de referencia, el radio de influencia de éstos, y un parámetro de permeabilidad del medio. Mediante el método “applyForce”, aplica en forma de componente de fuerza externa el efecto del medio poroso sobre un lattice dado.

Figura 3.1: Diagráma de Clases.

Page 18: Modelado de Medios Porosos Interactuando con Fluidos

En las siguientes secciones se dan los detalles de las clases y métodos vinculados a la implementación de LBM y medios porosos. En el Figura 3.1 se muestra el diagrama de clases de dicha implementación, donde el tipo “T” es parametrizado, y en este trabajo se lo instancia con el tipo “double”.

Simulación La ejecución de la simulación se divide en tres etapas:

1. Inicialización de las estructuras de trabajo, 2. Ejecución del bucle principal, 3. Finalización y guardado de checkpoint.

Una vez finalizada la simulación se realiza un post-procesamiento sobre los datos extraídos. Inicialización Durante la primera etapa se cargan e inicializan los valores del entorno de trabajo: se cargan valores de los archivos de parámetros y se inicializan las estructuras principales (el conversor de unidades, la geometría y el lattice). Además, si se decide continuar una simulación previa, es posible cargar los valores guardados del checkpoint al lattice. Parámetros Para la carga de valores de parámetros OpenLB cuenta con la clase “XMLreader”. Al instanciar un objeto de esta clase, se carga un archivo xml, que luego puede ser accedido en sus distintos campos como si se tratara de un arreglo. Para extraer un valor de un campo particular se utiliza el método “get<T>”, siendo T el tipo del valor a extraer. Por ejemplo dado un archivo xml con formato: <parametro>

<valor> 5 </valor> </parametro> Se utilizará el siguiente código para almacenar “valor” en una variable entera “n”: int n = xmlFile[“parametro”][“valor”].get<int>(); Conversor El conversor de unidades debe inicializarse con valores apropiados para la simulación: la dimensión del dominio (2D o 3D), tamaño de una celda (medido en metros m), velocidad en unidades del lattice (proporcionales al número Mach), viscosidad cinemática (medida en m2/s), largo característico (en metros m con valor por defecto 1), velocidad característica (en m/s con valor por defecto 1), factor de densidad (en kg/md siendo d la dimensión y con valor de factor por defecto 1), y una constante de presión (en pascales con valor por defecto 0).

Page 19: Modelado de Medios Porosos Interactuando con Fluidos

Luego de inicializado, el conversor es utilizado para consultar valores (por ejemplo consultar el tamaño de una celda en unidades físicas, la velocidad del lattice, el largo característico, la viscosidad cinemática, o la frecuencia de relajamiento), o convertir valores de unidades físicas a unidades del lattice y viceversa (como convertir un valor de porosidad de unidades físicas a unidades de lattice, un número de iteraciones a tiempo físico (en segundos s), o una distancia física a un número de celdas). Desde el punto de vista experimental y de validación esto resulta muy práctico dado que permite trabajar únicamente con parámetros reales, sin preocuparse por las unidades que se utilice para la simulación. Geometría La geometría del modelo está dada por un conjunto de “cuboids” que forman una grilla. Los “cuboids” son estructuras que contienen nodos. Estos nodos definen la posición de las celdas del espacio de trabajo. Para almacenar la geometría de la simulación se utiliza la clase “SuperGeometry2D”. Para definir esta clase se necesitan dos elementos: el “CuboidGeometry2D” (contenedor de cuboids) y el “HeuristicLoadBalancer” (balanceador de carga entre cuboids generado a partir del “CuboidGeometry2D”). A su vez, para crear el “CuboidGeometry2D” es necesario definir sus dimensiones (las dimensiones del espacio de trabajo), el tamaño de los voxels que lo componen (el tamaño de una celda, medida en metros), y el número de “cuboids” en los que se divide. La división en “cuboids” es útil a la hora de ejecutar el código en paralelo, pudiendo asignar fácilmente cada cuboid a una unidad de procesamiento distinta. Una familia de estructuras auxiliares utilizadas ampliamente a la hora de delimitar regiones es la de los indicadores (“IndicatorF2D”). Existen formas especializadas que se ajustan a la forma geométrica deseada, como “IndicatorCuboid2D” para rectángulos. Estas son utilizadas, por ejemplo, para definir las dimensiones del área de trabajo. El siguiente código genera una geometría con 1,26 m (1260 celdas) de ancho y 0,085 m (85 celdas) de altura. Esta geometría se subdivide en 7 “cuboids” y está compuesta por voxels cuya dimensión está dada por “converter.getLatticeL()”. El resultado puede verse en la Figura 3.2.

Page 20: Modelado de Medios Porosos Interactuando con Fluidos

/// Definición del indicador rectangular con esquinas en (0,0), (0,85),

(1260,0) y (1260,85)

std::vector<T> origin(2,T()); // vector en (0,0)

std::vector<T> extend(2,T());

extend[0] = 1260; // largo del canal en el eje X

extend[1] = 85; // largo del canal en el eje Y

IndicatorCuboid2D<T> cuboid(extend, origin);

/// Definición del conjunto de cuboids

const int noOfCuboids = 7; // número de cuboids en los que se

divide de la geometría

CuboidGeometry2D<T> cuboidGeometry(cuboid, converter.getLatticeL(),

noOfCuboids);

HeuristicLoadBalancer<T> loadBalancer(cuboidGeometry);

/// Definición de la geometría

SuperGeometry2D<T> superGeometry(cuboidGeometry, loadBalancer, 2);

Figura 3.2: Geometría Dividida en Cuboids. Canal de 1,26 m de ancho y 0,085 m de alto dividido en 7 “cuboids”. Una vez definida la geometría se deben distinguir las diferentes regiones de materiales utilizando el método “rename”. Cada región se identifica con un número que representa un material. El método “rename” recibe el número de material que uno desea convertir, el número de material al que uno quiere convertirlo y la región en la que se debe llevar a cabo este reemplazo. Esta región puede estar dada por offsets o desplazamientos, o utilizando indicadores (“IndicatorF2D”). Inicialmente toda el área de la geometría considera el material 0. De este modo pueden definirse las regiones que ocupará el fluido, los bordes del canal, la entrada y la salida del canal, u otros elementos. La Figura 3.3 presenta un ejemplo de cómo quedaría un canal con los números de materiales asociados.

Page 21: Modelado de Medios Porosos Interactuando con Fluidos

Figura 3.3: Ejemplo de Materiales. A modo de ejemplo consideremos una grilla de 40 x 16 celdas. Esta representa el canal por donde circula un fluido, el cual ingresa por el extremo izquierdo y sale por el extremo derecho. En este caso se coloca un cilindro sumergido en el fluido cerca de la entrada del canal. Para modelar este ejemplo se definen los materiales del siguiente modo (con su dinámica asociada):

- 1 representa el fluido, - 2 representa los bordes del canal (se le asocia una dinámica de bounce back), - 3 representa la entrada del canal (se le asocia una condición de contorno de velocidad), - 4 representa la salida del canal (condición de contorno de presión), - 5 representa un objeto sólido (al igual que los bordes posee una dinámica de bounce

back), - 0 representa el interior del objeto, el cual no interactúa con el fluido.

Lattice El lattice es el contenedor de todas las celdas del modelo, ordenadas dentro de la geometría. La clase utilizada para modelar el mismo en 2D es “SuperLattice2D”, que requiere de una “SuperGeometry2D”. A partir del lattice se definen las condiciones de contorno que regirán en la simulación. Como contenedor de las condiciones de contorno se utiliza una instancia de “OnLatticeBoundaryCondition2D”. Cada condición se define sobre un material (referenciado a través del número que lo identifica). Este es uno de los motivos por los que se define la entrada y la salida del canal como materiales aislados (como puede verse en el ejemplo de la Figura 3.3). El otro motivo es para poder definir la velocidad del fluido en la entrada del canal. Luego, a través del lattice se le asigna una dinámica a cada material. Utilizando el método “defineDynamics” se le asigna comportamiento a cada material en la forma de una clase de tipo “Dynamics”. Éstas definen la reacción del material al interactuar con otros elementos del modelo. En este trabajo se utiliza “ForcedBGKdynamics” para el fluido, que implementa el paso

Page 22: Modelado de Medios Porosos Interactuando con Fluidos

de colisión de BGK considerando las fuerzas externas. Para los bordes del canal se aplica una dinámica de “BounceBack”, ocasionando que el fluido rebote al chocar con estas celdas. Las condiciones iniciales de velocidad y presión para cada material se definen utilizando el método “defineRhoU”. El estado de equilibrio para cada material se inicializa mediante el método “iniEquilibrium”. Las dinámicas se aplican a la hora de ejecutar el paso de colisión, donde se llama al método “collide” de la dinámica correspondiente a la celda. Si se cuenta con un archivo de checkpoint generado en una ejecución anterior, es posible cargar el estado del lattice desde dicho archivo utilizando el método “load”, luego del paso de inicialización. Antes de que comience la ejecución de la simulación se define el número de iteración en la que comenzará (cero si es una ejecución nueva, o el valor correspondiente cargado en el archivo xml, si se desea continuar una simulación anterior). Descriptores Un elemento importante de OpenLB son los templates conocidos como descriptores. Estos cambian la forma en que ejecutan diversas funciones del framework. Principalmente, definen las dimensiones (2D o 3D) y el esquema del trabajo (como se explicó en el Capítulo 2, LBM). En este trabajo se utiliza el descriptor “ForcedD2Q9Descriptor”. Éste indica al framework que se utilizará el esquema D2Q9, lo que significa 2 dimensiones, con 9 componentes de velocidad, y con un tratamiento especial para fuerzas externas. Esto significa que el término de fuerza se almacenará físicamente junto a los valores de velocidad y densidad de cada celda, reduciendo así los tiempos de acceso a la información de una celda en particular. Para utilizar un descriptor se lo pasa como parámetro a modo de tipo en funciones parametrizadas. Para facilitar esta tarea es conveniente definirlo como un “String” constante. Se lo utiliza particularmente al inicializar el “SuperLattice”, las dinámicas asociadas a cada material, las condiciones de contorno y las celdas. Existe una amplia variedad de descriptores, como por ejemplo “PorousD2Q9Descriptor”. Este descriptor permite utilizar una dinámica que le da un comportamiento de medio poroso al material. Sin embargo, este descriptor simplemente aplica la ley de Darcy en las celdas asociadas. Como se explicó en el capítulo anterior, este enfoque no es ideal, por lo tanto, no es utilizado en el presente trabajo. Medio Poroso Para utilizar el medio poroso es necesario cargar los puntos que lo componen, la permeabilidad del medio, y el radio de influencia de los puntos medido en número de celdas. Esto se lleva a cabo con los métodos “setPoints”, “setPermeability” y “setInfluenceRadius” respectivamente. Para llevar a cabo los cálculos de fuerza del medio poroso es necesario consultar los valores de velocidad de las celdas, utilizando el método “computeU” de la celda. También es posible

Page 23: Modelado de Medios Porosos Interactuando con Fluidos

acceder a este valor llamando al método “computeU” desde una dinámica, pasando como parámetro la celda correspondiente. Para acceder a una celda se llama al método “get” del lattice pasando como parámetro las coordenadas de la celda deseada, en unidades físicas. Además es necesario acceder al término de fuerza externa. Para esto se utiliza el método “getExternal” de la celda, que devuelve una referencia al vector de fuerza que actúa sobre ésta. Al recibir una referencia, es posible operar sobre este mismo vector. Para evitar arrastrar valores de fuerzas de las iteraciones anteriores, se eliminan los valores de todos los vectores de fuerza utilizando el método ”defineExternalField” del lattice. Más adelante se presentan los pseudo-códigos de los métodos más relevantes al cálculo del medio poroso: “Compute Velocity” y “Apply Force”. Ejecución Durante la segunda etapa se realizan iteraciones que llevan a cabo los cálculos de la simulación. Cada iteración se desarrolla de la siguiente manera:

- Incremento de velocidad - Cálculo del medio poroso:

- Cálculo de velocidad (Compute Velocity) (Eq. 2.19) - Cálculo y aplicación de fuerzas (Apply Force) (Eq. 2.18)

- Cálculo de LBM: - Colisión de poblaciones y propagación. (Eq. 2.1 y 2.2)

- Extracción de resultados: Valores del lattice, número de Reynolds (Eq. 3.1), velocidad y presión del corte y punto a analizar.

Incremento de velocidad Para lograr el aumento de velocidad se utiliza el método de lattice “defineU”. Éste método funciona de manera similar a “defineRhoU” utilizado en la definición de la condición inicial, con la diferencia que solo fija el valor de la velocidad, dejando sin cambios el de presión. El cambio de velocidad se lleva a cabo en la entrada del canal, identificando dicha región por su número de material. El incremento se realiza cada 5 iteraciones, de forma que sea gradual pero evitando tener que realizar la operación en cada iteración. El incremento gradual ayuda a evitar problemas de inestabilidad del modelo. Compute Velocity En este método se almacena en el arreglo “Velocidad_Punto” la suma de las velocidades de la región cercana a cada punto ponderada por la función delta de Dirac.

Page 24: Modelado de Medios Porosos Interactuando con Fluidos

For (P: Puntos){

For (C: celdas en el radio de influencia){

C.computeU(Velociadad_Celda);

D = Delta_Dirac(P - C); // toma la distancia entre cada celda y

el punto

Velocidad = Velocidad + D * Velociadad_Celda;

}

Velocidad_Punto[P] = Velocidad;

Velocidad = 0;

}

Apply Force Este método aplica una fuerza a cada celda de la región cercana a cada punto ponderada por la función delta de Dirac.

For (P: Puntos){

F = -Nu * Velocidad_Punto[P] / K;

For (C: celdas en el radio de influencia){

FuerzaExterna = C.getExternal();

D = Delta_Dirac(P - C);

FuerzaExterna = D * F;

}

}

siendo Nu la viscosidad del fluido, K la permeabilidad del medio, y Velocidad_Punto[P] la velocidad calculada en Compute Velocity para el punto P. Paso de Colisión y Advección Para llevar a cabo los pasos de colisión y advección se llama al método “collideAndStream” del lattice. OpenLB realiza primero el paso de colisión seguido del paso de advección. En el paso de colisión calcula el choque de las poblaciones de partículas de cada celda. Los cálculos llevados a cabo en este paso pueden cambiar dependiendo de la dinámica asignada a las celdas de la región. En el paso de advección se calcula el desplazamiento de las poblaciones, donde se propagan los cambios calculados en el paso anterior a las celdas vecinas. Este último paso es invariante independientemente de la dinámica de la región. Extracción de Resultados Para analizar los resultados de la simulación se guarda el número de Reynolds, la historia de un punto y la historia de un corte.

Page 25: Modelado de Medios Porosos Interactuando con Fluidos

El número de Reynolds es un valor utilizado para caracterizar el movimiento de un fluido y predecir la transición de un flujo laminar a uno turbulento. Se define mediante la siguiente ecuación

(3.1) donde v es la velocidad del fluido, l el largo característico y ν la viscosidad cinemática del fluido. Para guardar la historia tanto de un punto como de un corte se utilizó el framework VTK, que permite almacenar valores en formato vtk. También permite la lectura de estos archivos facilitando análisis posteriores. La historia incluye valores de velocidad (en los ejes x e y) y densidad de partículas. El formato vtk trabaja con un conjunto de puntos a los que se le anexan vectores con los valores de velocidad (un vector para cada eje) y presión. También se extraen periódicamente los valores de velocidad y presión de todo el lattice, para su posterior visualización a través de programas como ParaView (ParaView). Esta extracción se realiza cada 20 iteraciones para conseguir valores representativos sin aumentar considerablemente el tiempo de simulación. Finalización Por último, en la tercera etapa se guarda el estado del lattice como checkpoint. De esta manera permite continuar la simulación en diferentes ejecuciones, y se realiza simplemente cargandola como parámetro en la primera etapa. Checkpoint Para crear un archivo de checkpoint se utiliza el método “save” del lattice indicando un nombre de archivo. Para cargar adecuadamente los parámetros y continuar la simulación se almacena además el valor de la velocidad en la entrada y el número de la última iteración que se ejecutó. Estos valores deben introducirse en los archivos xml correspondientes al setup y al checkpoint, respectivamente, antes de ejecutar una continuación de la simulación. Post-Procesamiento Esta etapa se corresponde con el análisis de las historias del corte y el punto. En el caso que nos interesa, el post-procesamiento consiste en el cálculo de media y desvío estándar sobre la historia del corte y la del punto. Más concretamente se utiliza para analizar de manera más fácil los valores calculados y poder hacer validaciones y/o comparaciones en el caso de contar con resultados experimentos. Los resultados obtenidos mediante esta etapa son los que se analizan en el Capítulo 4.

Page 26: Modelado de Medios Porosos Interactuando con Fluidos

Parámetros de la Simulación A fin de describir los experimentos a simular se diseñaron archivos en formato XML. En cada archivo se cargan los parámetros relevantes a un aspecto de la simulación. A continuación se detallan los archivos definidos y los parámetros contenidos en cada uno. Archivos XML:

● Checkpoint ○ Uso: indica si se cargará desde el checkpoint o si se iniciará una simulación

nueva. ○ Iteración: el número de la iteración en la que debe comenzar a ejecutar al cargar

desde el checkpoint. ● Geometria

○ Dimensiones del canal: lx y ly, medidos en unidades físicas. ○ Posición de los puntos: posición de los puntos que forman la región porosa,

definidos en unidades físicas. ○ Permeabilidad (K): indica la permeabilidad del medio poroso, en unidades

físicas. ● Discretización

○ N: resolución del modelo. ○ M: refinamiento de la discretización de tiempo. ○ Delta: tamaño de una celda en unidades físicas. ○ Radio de influencia: radio (medido en celdas) considerado a la hora de calcular y

aplicar la fuerza ejercida por lo puntos del medio poroso. ○ LatticeU: velocidad característica del modelo, en unidades del modelo. Utilizado

para el cálculo del tiempo de relajación. ● Simulación

○ Tiempo de simulación: tiempo total de la simulación, medido en segundos. ○ Nu: viscosidad del fluido, en unidades físicas.

● Setup ○ Velocidad inicial: valor inicial de la velocidad de la entrada, en unidades físicas. ○ Velocidad intermedia: valor de velocidad al finalizar la etapa de aumento

significativo de la velocidad. ○ Velocidad máxima: valor de la velocidad al finalizar la ejecución. ○ Tiempo de aumento significativo: duración en segundos de la etapa de

incremento significativo de velocidad. ○ Tiempo de aumento leve: duración en segundos de la etapa de incremento leve

de velocidad. ● Extracción

○ Posición para el cálculo del número de Reynolds

Page 27: Modelado de Medios Porosos Interactuando con Fluidos

○ Posición del punto de historia ○ Posición del corte de historia ○ Iteraciones: número de iteraciones consideradas para la extracción de datos

En el Apéndice 1 se encuentra el código principal, que contiene la instanciación de todos los elementos de trabajo, el bucle principal de la simulación, y la finalización de la ejecución. El Apéndice 2 contiene el código de la clase “PorousMedium” utilizada para representar el medio poroso. Presenta todos los atributos y métodos detallados en la figura 3.1. En el Apéndice 3 se muestra el entorno utilizado. Un detalle de los nombres de archivos utilizados se puede encontrar en el Apéndice 4.

Page 28: Modelado de Medios Porosos Interactuando con Fluidos

Capítulo 4: Resultados

Resumen En este capítulo se presentan los casos de estudio, el análisis realizado y los resultados obtenidos. Los casos de estudio consisten en simular fluido circulando por un canal recto parcialmente obstruido. La obstrucción es un medio poroso compuesto por una grilla de puntos fijos situada en el centro del canal, con los que colisiona el fluido. En el primer caso se trata de un flujo laminar, mientras que en el segundo se simula un flujo turbulento. Estos ujos se convierten en inestables en el límite entre la zona permeable y el ujo libre, formando estructuras de ondas y vórtices (White, 2007). Éstas son útiles por modicar los escalares del transporte no sólo donde las estructuras son generadas, sino también dentro y fuera de la obstrucción. Así pueden favorecer procesos como la polinización, transferencia de calor y masa, y transporte de nutrientes (Pan 2014, Patton 2016).

Casos de Estudio Los problemas simulados consisten en un fluido circulando por un canal recto de 1,26 m x 0,085 m, parcialmente obstruido por un medio poroso. El medio poroso es una grilla de puntos de 0,5 m x 0,025 m, situada a 0,23 m de la entrada del canal, centrada respecto del eje Y.

Figura 4.1: Elementos de los Casos de Estudio.

Page 29: Modelado de Medios Porosos Interactuando con Fluidos

Utilizando el método descripto en el capítulo anterior, se modelan los puntos del medio poroso como puntos de referencia que ejercen una fuerza sobre el fluido. En la etapa de post-procesamiento se analizó el perfil en un punto y en un corte a fin de ver el efecto del medio poroso sobre el fluido. La extracción de estos valores se realiza sobre las últimas 50.000 iteraciones del experimento, restringiendo el análisis únicamente al período de flujo estable. El corte se tomó en la posición 0,623 m a lo largo de del eje Y, situado cerca de la salida del medio poroso. El punto se tomó en las coordenadas (1,1 m; 0,0425 m), cerca de la salida del canal. Además se calculó el número de Reynolds (Eq. 3.1), tomando el promedio de velocidad de un corte situado entre la entrada del canal y el medio poroso (a 0,126 m de la entrada), suficientemente alejado de ambas como para evitar que las inestabilidades del flujo alteren la velocidad de forma considerable. Como se explicó en el Capítulo 3, este valor es utilizado para predecir la transición de un flujo laminar a uno turbulento (White, 2007). La Figura 4.1 muestra la posición del medio poroso, del corte y punto de extracción, y de la posición para el cálculo del número de Reynolds. Condiciones de Contorno Para modelar la entrada del canal se utilizó una condición de contorno de velocidad, mientras que para la salida se utilizó una condición de contorno de presión. El cálculo de estas condiciones está basado en el algoritmo propuesto por Skordos (1993). Los bordes del canal se modelaron utilizando una dinámica de Bounce Back. Esto causa que el fluido sea repelido al chocar con los bordes del canal, lo que representa el efecto de una pared sólida y rígida.

Parámetros de la Simulación Los parámetros utilizados para modelar el experimento fueron los siguientes:

● Geometria ○ Dimensiones del canal: 1,26 m x 0,085 m ○ Permeabilidad del medio (K): 0,000145 m2

● Discretización ○ N: 1 ○ M: 1 ○ Delta: 0,001 m ○ Radio de influencia: 2 celdas ○ LatticeU: 0,18

● Simulación ○ Nu: 0,00002 m2/s

● Extracción ○ Posición para el cálculo del número de Reynolds: 0,126 m ○ Posición del punto de historia: (1,1 m; 0,0425 m)

Page 30: Modelado de Medios Porosos Interactuando con Fluidos

○ Posición del corte de historia: 0,623 m ○ Iteraciones: 50.000

Dados los valores de viscosidad (Nu) y velocidad del lattice (LatticeU) se trabaja con un tiempo de relajación de 0,554 y un frecuencia de relajación de 1,80505. Cada segundo de la simulación se corresponde con 1111 iteraciones de LBM. Esta equivalencia es calculada por el conversor de unidades mediante la siguiente fórmula

(4.1)

siendo latticeTime  el número de iteraciones, physTime el tiempo medido en segundos, charU  la velocidad característica, latticeL el largo del lattice, y latticeU la velocidad del lattice. La velocidad característica tiene un valor de 0,2 m/s. El largo del lattice se corresponde al valor Delta dividido por la resolución del modelo (N).

El canal está compuesto por 107100 celdas distribuidas en 85 filas de 1260 celdas cada una.

Los puntos que componen el medio poroso están dispuestos formando un rectángulo, con esquinas en (0,23 m; 0,03005 m), (0,73 m; 0,03005 m), (0,23 m; 0,05505 m) y (0,73 m; 0,05505 m), con una separación de 2,5mm a lo largo del eje Y, y una separación de 5mm a lo largo del eje X. Esto da un total de 1111 puntos.

Análisis de un Flujo Laminar En el primer caso de estudio se analizó el efecto del medio poroso sobre un flujo laminar. Con una velocidad en la entrada de 0,045 m/s, se trabajó con un número de Reynolds de 141.

Parámetros del Flujo Laminar Partiendo de una velocidad en la entrada del canal de 0,03 m/s se incrementó gradualmente hasta alcanzar una velocidad de 0,045 m/s. La simulación abarcó 120 segundos de fluido circulando por el canal. La velocidad en la entrada del canal se incrementó durante los primeros 15 segundos simulados dejando los 105 segundos restantes para que se estabilice el flujo a lo largo del canal.

Análisis de un Flujo Turbulento En el segundo caso de estudio se buscó simular y analizar un flujo turbulento. Para ello, partiendo de la configuración anterior se fue incrementando suavemente la velocidad en la entrada del canal hasta generar vórtices. A lo largo del experimento se alcanzó un número de Reynolds de 806.

Page 31: Modelado de Medios Porosos Interactuando con Fluidos

Estabilidad del modelo Para evitar comprometer la estabilidad del modelo se incrementó la velocidad de forma gradual. Se partió de una velocidad inicial de 0,03 m/s y se alcanzó una velocidad de 0,255728 m/s, en la entrada del canal.

Como una segunda medida, el experimento se realizó por partes, haciendo uso de la capacidad de guardar checkpoints de OpenLB, como se explicó en el capítulo 3. De esta manera se evitó perder grandes avances cuando el experimento fallaba. Los fallos eran causados por incrementar la velocidad de forma brusca/violenta/repentina, generando inestabilidades en el modelo.

Parámetros del Flujo Turbulento Como se explicó anteriormente, esta simulación se realizó por partes, aprovechando la función de guardado de checkpoints de OpenLB . Los parámetros cargados en los archivos Checkpoint y Setup, y el parámetro de tiempo de simulación del archivo Simulación se presentan en la tabla a continuación (Tabla 4.1), ya que estos se modificaban cada vez que se realizaba una ejecución distinta.

Cada iteración se divide en tres etapas de velocidad: aumento significativo, aumento leve, y velocidad constante para estabilizar el canal. Cada etapa tiene una duración especificada en la tabla. La velocidad intermedia es la alcanzada al finalizar la etapa de aumento significativo. El experimento se simuló a lo largo de 4 ejecuciones.

Ejecución Velocidad Inicial

Velocidad Intermedia

Velocidad Máxima

Tiempo Aumento Significativo

Tiempo Aumento Leve

Tiempo de Estabilización

1 0,03 m/s 0,1 m/s 0,12 m/s 60 seg 20 seg 20 seg

2 0,12 m/s 0,2 m/s 0,22 m/s 60 seg 20 seg 20 seg

3 0,22 m/s 0,25 m/s 0,255 m/s 70 seg 20 seg 10 seg

4 0,255 m/s 0,255728 m/s 0,255728 m/s 40 seg 0 seg 100 seg

Tabla 4.1. Parámetros de ejecución.

Resultados Los resultados se analizaron sobre las variables macroscópicas de velocidad y densidad de partículas. Para visualizar las salidas se utilizó el programa ParaView[2], que permite abrir y analizar archivos de formato vtk.

Page 32: Modelado de Medios Porosos Interactuando con Fluidos

Flujo Laminar A continuación se presentan imágenes de los perfiles de velocidad (Figura 4.2) y presión (Figura 4.3) creadas a partir de los datos extraídos durante la simulación.

Figura 4.2. Flujo Laminar: Perfil de Velocidad Desarrollado.

Figura 4.3. Flujo Laminar: Perfil de Presión Desarrollado.

En las Figura 4.2 y 4.3 muestran la velocidad y presión del flujo desarrollado, respectivamente. Como se puede observar, la velocidad del fluido aumenta donde no está presente el medio poroso, para conservar el caudal. Éste también tiene un claro efecto sobre la presión, causando que sea notablemente mayor en la entrada del canal respecto a la salida. Análisis de Perfil Laminar en un Punto De los valores extraídos del punto de historia situado en (1,1 m ; 0,0425 m), se tomó el promedio y el desvío.

Promedio Desvio

Velocidad X 0,043200 m/s 0,000019 m/s

Velocidad Y 0,000009 m/s 0 m/s

Presión 1,000527 Pa 0,000006 Pa

Tabla 4.2. Historia de Flujo Laminar en un Punto El desvío es notablemente bajo en el flujo laminar, ya que se vuelve estable al salir del medio poroso.

Page 33: Modelado de Medios Porosos Interactuando con Fluidos

Análisis de Perfil Laminar en un Corte Se calculó el promedio de los valores extraídos del corte. A continuación, se muestran los resultados en las Figuras 4.4 a 4.6 para las variables de velocidad en el eje X, velocidad en el eje Y, y presión respectivamente.

Figura 4.4. Flujo Laminar: Promedio de Velocidad en X.

Page 34: Modelado de Medios Porosos Interactuando con Fluidos

Figura 4.5. Flujo Laminar: Promedio de Velocidad en Y.

Figura 4.6. Flujo Laminar: Promedio de Presión.

Page 35: Modelado de Medios Porosos Interactuando con Fluidos

El medio poroso detiene notablemente el paso del fluido, reduciendo su velocidad. Esto puede verse en la Figura 4.4, donde el fluido tiene mayor velocidad en el eje X donde no está presente el medio poroso. Además, el medio poroso tiene un efecto sobre la velocidad en el eje Y. Al chocar con éste, el flujo se desvía hacia los bordes del canal, causando que la velocidad en esta zona tienda a ser positiva en la mitad superior del canal, y negativa en la mitad inferior, como puede verse en la Figura 4.5. Esto representa el fluido siendo empujado hacia los bordes del canal. La oscilación se debe a que cada punto del medio poroso tiene localmente un efecto considerable sobre el fluido, desviándose tanto hacia arriba como hacia abajo. La presión es prácticamente constante fuera del medio poroso, como muestra la Figura 4.6. Sin embargo, en la región límite entre éste y el flujo libre, aumenta considerablemente a causa del flujo desviado por el medio poroso. Por último, no se muestran los gráficos de desvío de velocidad, ya que al ser un flujo laminar, la variación de velocidad es mínima. En cuanto al desvío de presión, el corte tiene un valor de 0,000025 Pa en todas las posiciones medidas. Flujo Turbulento Como se mencionó anteriormente, a lo largo de la simulación del caso de estudio se tomaron valores de velocidad y presión. A continuación se presentan imágenes del canal mostrando los valores de velocidad (Figura 4.7) y de presión (Figura 4.9) a lo largo del canal, junto con imágenes detallando el final del canal (Figuras 4.8 y 4.10), donde ocurren los fenómenos más destacables.

Figura 4.7. Flujo Turbulento: Perfil de velocidad alcanzado (m/s).

Page 36: Modelado de Medios Porosos Interactuando con Fluidos

Figura 4.8. Flujo Turbulento: Detalle del perfil de velocidad (m/s) del extremo derecho del canal luego del medio poroso.

Figura 4.9. Flujo Turbulento: Perfil de presión alcanzado (Pa).

Figura 4.10. Flujo Turbulento: Detalle del perfil de presión (Pa) del extremo derecho del canal. Cabe destacar que el caso de flujo turbulento se corresponde casi directamente con el estudio realizado en Boroni (2015). Si bien no se realizaron comparaciones contra resultados experimentales en esta etapa, se espera poder realizar la misma en otra instancia. Esto se debe a que el ajuste debe ser muy fino para poder analizar ambas salidas. No obstante esto es importante mencionar que las formas de las curvas de las salidas, las frecuencias que se producen producto de las inestabilidades, y los valores promedios puntuales poseen mucha concordancia con los resultados descriptos en dicho artículo, lo cual hace preveer que el desarrollo realizado será de gran utilidad para la validación contra datos experimentales.

Page 37: Modelado de Medios Porosos Interactuando con Fluidos

Efecto de Von Karman Como puede verse en las Figuras 4.7 y 4.8, la distorsión en el flujo causada por el medio poroso genera un desprendimiento de vórtices cerca de la salida del canal. Este fenómeno es conocido como “Calle de Vórtices Von Karman” (von Karman, 1938). Análisis de Perfil Turbulento en un Punto Se tomaron los valores de velocidad y presión del punto (1,1 m ; 0,0425 m). Realizando el post-procesamiento descripto se consiguieron los siguientes promedios y desvíos:

Promedio Desvío

Velocidad en X 0,282482 m/s 0,009620 m/s

Velocidad en Y 0,000821 m/s 0,058607 m/s

Presión 0,997199 Pa 0,001632 Pa

Tabla 4.3. Historia de Flujo Turbulento en un Punto. Como puede verse, a pesar de que la velocidad es menor en el eje Y, el desvío es mayor. Esto indica que el flujo es más inestable en esta dirección, debido a la generación de vórtices. En cambio la presión varía poco en esta región. Análisis de Perfil Turbulento en un Corte Los valores de velocidad y presión del corte de historia extraídos durante la simulación fueron procesados, calculando su media y desvío. El resultado fue plasmado en los siguientes gráficos (Figuras 4.11 a 4.16).

Page 38: Modelado de Medios Porosos Interactuando con Fluidos

Figura 4.11. Flujo Turbulento: Promedio de Velocidad en X.

Figura 4.12. Flujo Turbulento: Desvío de Velocidad en X.

Page 39: Modelado de Medios Porosos Interactuando con Fluidos

Figura 4.13. Flujo Turbulento: Promedio de Velocidad en Y.

Figura 4.14. Flujo Turbulento: Desvío de Velocidad en Y.

Page 40: Modelado de Medios Porosos Interactuando con Fluidos

Figura 4.15. Flujo Turbulento: Promedio de Presión.

Figura 4.16. Flujo Turbulento: Desvío de Presión.

Page 41: Modelado de Medios Porosos Interactuando con Fluidos

En general, el medio poroso se opone al movimiento del fluido, causando que éste se desvíe hacia los extremos superior e inferior del canal. Esto causa que la velocidad en el eje X aumente en esta región y disminuya en el interior del medio poroso. Esto puede observarse en la Figura 4.11, donde se presentan los máximos en los centros de las regiones libres y el mínimo en el centro del medio poroso. La Figura 4.13 muestra el efecto de este fenómeno sobre la velocidad en el eje Y: las celdas de la mitad inferior del canal presentan una velocidad negativa, es decir que el flujo se dirige al borde inferior del canal, mientras que las celdas de la mitad superior tienen una velocidad positiva, marcando la dirección del fluido hacia el borde superior del canal. La velocidad tiene sus valores extremos en zona de transición entre el flujo libre y el medio poroso. Puede notarse la diferencia con la Figura 4.5 que representa la velocidad en el eje Y para el flujo laminar. Al interactuar con un flujo laminar, el medio poroso actúa como una obstrucción completa. En cambio, al encontrarse con un flujo turbulento actúa como una obstrucción parcial. Al aproximarse a los bordes del canal el fluido pierde velocidad en el eje X, como se ve en los extremos de la Figura 4.11. En el eje Y la dirección del flujo se invierte, como puede observarse en el cambio de signo de la velocidad en la Figura 4.13. Esto se debe a que el fluido rebota con el borde del canal. En la región límite entre el flujo libre y el medio poroso, el flujo se vuelve más inestable, produciendo cambios más bruscos en la velocidad. En las Figuras 4.12 y 4.14 puede observarse el aumento en el desvío estándar de la velocidad en los ejes X e Y respectivamente en dicha región. Dicho de otro modo, el flujo se vuelve más estable al alejarse de la zona de transición. El desvío de la velocidad es considerablemente más bajo en el interior del medio poroso, donde las fluctuaciones y la velocidad son menores. También lo es en la región cercana a los bordes del canal, donde el medio poroso pierde influencia sobre el flujo. A medida que aumenta en X, se vuelve más inestable debido a la multiplicación del efecto de capa límite, que es lo que produce la oscilación. En cuanto a la presión, la misma disminuye al acercarse al medio poroso pero rápidamente aumenta dentro de éste, como se observa en la Figura 4.15. Los claros picos dentro del medio poroso se deben a la presencia de los puntos que lo conforman, los cuales repelen el fluido. El desvío estándar de la presión es mayor fuera del medio poroso, donde el fluido se mueve a mayor velocidad, y menor en el interior, llegando a su valor mínimo en el centro del canal, como se muestra en la Figura 4.16. Esto se debe a las grandes oscilaciones turbulentas de la zona libre.

Page 42: Modelado de Medios Porosos Interactuando con Fluidos

Comparativa de Ambos Flujos Al comparar ambos flujos se pueden observar claros patrones. Si analizamos la velocidad en X podemos ver que ambos flujos alcanzan su velocidad máxima en las posiciones 0,017 m y 0,069 m y su velocidad mínima en el centro del canal en la posición 0,044 m según las Figuras 4.4 y 4.11 respectivamente. Estos máximos y mínimos difieren notablemente, siendo 0,327874 m/s el máximo y 0,061941 m/s el mínimo para el flujo turbulento, y 0,055874 m/s el máximo y 0,005662 m/s el mínimo para el laminar. Puede notarse que el mínimo del flujo turbulento es mayor que el máximo del flujo laminar. El desvío de velocidad en el eje X varía entre 0,000089 m/s y 0,001602 m/s para el flujo turbulento (Figura 4.12) mientras que en el laminar varía entre 0,000021 m/s y 0,000002 m/s a lo largo del corte. Al analizar la velocidad en el eje Y notamos que ambos presentan valores tanto positivos como negativos, mostrando cierta simetría como puede verse en las Figuras 4.5 y 4.13. Mientras que el flujo laminar se mantiene en valores pequeños, con su máximo de 0,00003 m/s y su mínimo de -0,000053 m/s, el turbulento alcanza valores más extremos, con máximo de 0,001111 m/s y mínimo de -0,001042 m/s. Curiosamente, la posición de los máximos y mínimos en ambos flujos está invertida; el flujo laminar presenta su máximo en la posición 0,031 m y su mínimo en la posición 0,053 m, mientras que en el turbulento el máximo se ubica en la posición 0,053 m y el mínimo en la posición 0,031 m. El desvío en Y para el flujo turbulento oscila entre 0,00112 m/s en la posición 0,055 m y 0 m/s al alcanzar los bordes del canal (Figura 4.14). Para el flujo laminar este valor es nulo a lo largo de todo el corte. El perfil de presión es muy similar para ambos flujos; tanto el flujo laminar como el turbulento presentan picos en aproximadamente las mismas posiciones: 0,030 m, 0,034 m, 0,039 m, 0,044 m, 0,049 m y 0,054 m. Esto puede observarse en las Figuras 4.6 y 4.15. Sin embargo, los valores del flujo turbulento son más altos, oscilando entre 1,022101 Pa y 1,022296 Pa, mientras que los del flujo laminar se mueven entre 1,003895 Pa y 1,003937 Pa El desvío de presión del flujo turbulento varía entre 0,00019 Pa y 0,001576 Pa (Figura 4.16), mientras que en el flujo laminar es un valor mucho menor que se mantiene constante a lo largo del corte: 0,000006 Pa.

Page 43: Modelado de Medios Porosos Interactuando con Fluidos

Capítulo 5: Conclusión A lo largo del presente trabajo se desarrolló una herramienta que permite modelar la interacción entre fluidos y medios porosos. Para el modelado del fluido se utiliza el método de lattice-Boltzmann; un método basado en autómatas celulares que permite reproducir las reglas físicas que rigen al fluido en el nivel macroscópico. Una ventaja de este método es que tiene mucha flexibilidad para introducir interacciones a nivel local, ya sea modificando las reglas de actualización de las poblaciones o mediante el término de fuerza externa. El método de lattice-Boltzmann fue implementado sobre el framework OpenLB (OpenLB), el cual ofrece muchas facilidades tales como: un conversor de unidades que permite trabajar en unidades físicas sin necesidad de considerar las unidades del modelo, la capacidad de realizar guardados parciales, y la posibilidad de paralelización. Por otra parte para modelar el medio poroso se emplea una variante del método de frontera inmersa (usado para modelar estructuras sólidas y flexibles inmersas en fluido a través de una malla de puntos que ejercen una fuerza sobre el fluido y desde el fluido hacia dicha malla), propuesta en Dottori (2016). A diferencia del método de frontera inmersa, para el medio poroso se establecen puntos de referencia fijos e independientes. Al utilizar este método es posible modelar medios porosos que no coincidan con la grilla de LBM, interactuando con el fluido a través del término de fuerza externa. A la hora de simular un problema con la herramienta desarrollada hay que considerar tres etapas de implementación: inicialización de estructuras de trabajo (carga de parámetros e instanciación de estructuras), ejecución del bucle principal (pasando por las etapas de aumento de velocidad, cálculos del medio poroso y LBM, y extracción de resultados), y finalización para análisis de salidas y/o guardado de checkpoint. Para facilitar el modelado de problemas diversos, la herramienta recibe parámetros por medio de archivos xml. Estos parámetros permiten configurar el experimento, definiendo desde las dimensiones del canal hasta la posición del medio poroso. Para la extracción de resultados se generan salidas de archivos en formato vtk, permitiendo la visualización posterior de los datos utilizando programas como ParaView (ParaView). Al realizar

Page 44: Modelado de Medios Porosos Interactuando con Fluidos

un post-procesamiento sobre los datos extraídos se facilita el análisis de los resultados de la simulación. Luego de realizar las pruebas se pudo verificar que la herramienta construida es muy útil a la hora de simular medios porosos, dando resultados coherentes. Si bien no se realizaron ajustes con los experimentos realizados en Silin (2011), las medidas obtenidas sobre promedios y desvíos en la zona de porosidad se asemejan en su forma a los resultados publicados en dicho artículo. Por otra parte, es importante mencionar que a lo largo del desarrollo de la herramienta y de la ejecución de los casos de prueba se presentaron problemas de estabilidad del modelo. Esto es muy común cuando se trabaja con simulaciones que por sus características tienen asociados fenómenos turbulentos. Concretamente, en estos casos si se aumenta la velocidad de forma brusca el modelo falla, causando que los valores de velocidad y presión se vuelvan erráticos. Cuando esto sucede, no hay manera de recuperar el progreso realizado. Cuanto mayor es la velocidad actual del fluido, más difícil es aumentarla sin que se desestabilice. Esto hace que el proceso de alcanzar la velocidad deseada se realice de a pequeños incrementos, y en ese aspecto es donde se resalta la importancia de los guardados parciales o checkpoints. Finalmente, se realizaron pruebas intentando utilizar el mecanismo de paralelización del framework junto con el código agregado para el cálculo del medio poroso. Desafortunadamente no resultó viable en cuanto a la performance dado que la interacción entre el medio poroso y el fluido produce un overhead significativo, causando que el tiempo de ejecución del código en paralelo sea incluso mayor que el secuencial. Versiones futuras de OpenLB pueden ayudar a resolver este problema, por ejemplo con métodos que permitan operar de forma distinta en los diferentes “cuboids” de la geometría, dando la posibilidad de dividir el problema en subproblemas. Para la explicación de los “cuboids” ver la sección de Geometría en Inicialización de la Simulación del Capítulo 3.

Page 45: Modelado de Medios Porosos Interactuando con Fluidos

Referencias Acevedo-Malavé A. A blood flow with cardiac pulse in intracranial aneurysms using computational fluid dynamics (CFD): A comparison between transient and steady state regimes . J. Comput. Meth. in Science and Engineering, 2017.

Atom: Open source text editor. https://atom.io/

Bhatnagar P L, Gross E P, Krook M. A Model for Collision Processes in Gases. I. Small Amplitude Processes in Charged and Neutral One-Component Systems. Phys. Rev. 94, 511, 1954.

Bhukta D, Dash G C, Mishra S R. Heat and Mass Transfer on MHD Flow of a Viscoelastic Fluid through Porous Media over a Shrinking Sheet. International Scholarly Research Notices Volume 2014, 2014.

Boroni G, Dottori J, Dalponte D, Rinaldi P and Clausse A. An improved Immersed-Boundary algorithm for fluid-solid interaction in Lattice-Boltzmann simulations . Latin American Applied Research. ISSN Nº: 0327-0793, 2013.

Boroni G, Silin N, Dalponte D, Dottori J, Clausse A. Lattice-Boltzmann modeling of unstable flows amid arrays of wires . Computers and Fluids. ISSN Nº: 0045-7930, pp. 37-45, 2015.

Bouillot P, Brina O, Ouared R, Yilmaz H, Lovblad K-O, Farhat M, Pereira V M. Computational fluid dynamics with stents: quantitative comparison with particle image velocimetry for three commercial off the shelf intracranial stents. J Neurointerv Surg 8(3):309-15. doi: 10.1136/neurintsurg-2014-011468, 2016.

Bruneau C H, Creusé E, Gilliéron P, Mortazavi I. A glimpse on passive control using porous media for incompressible aerodynamics . International Journal of Aerodynamics Print ISSN: 1743-5447 Online ISSN: 1743-5455, 2014.

Chen H, Chen S, Matthaeus WH. Recovery of the navier-stokes equations using a lattice-gas boltzmann method. Phys. Rev. A, 45(8):R5339- R5342, 1992.

Chen S, Doolen G D. Lattice Boltzmann Method for Fluid Flows . Annual Reviews Fluid, 1998.

Cheng Y, Zhang H. Immersed boundary method and lattice-Boltzmann method coupled fsi simulation of mitral leaflet flow . Computers & Fluids, 39(5):871-881, 2010.

Coppola G, Gomez A. Experimental investigation on a turbulence generation system with high-blockage plates. Experim. Thermal Fluid Sci, 33:1037–1048, 2009.

Page 46: Modelado de Medios Porosos Interactuando con Fluidos

Dazeo N, Dottori J, Boroni G, Larrabide I. Flow diverter stents simulation with CFD: porous media modelling . Proc. SPIE 10160; DOI:10.1117/12.2256674, 2017.

Deepu P, Anand P, Basu S. Stability of Poiseuille flow in a fluid overlying an anisotropic and inhomogeneous porous layer. Phys. Rev. E 92, 023009, 2015.

Dottori J, Boroni G, Clausse A. Modelos de fuerza de frontera y máxima entropía para aplicaciones de lattice-Boltzmann en fluidos . Tesis Doctoral, 2016.

Geier M C. AB Initio Derivation of the Cascaded Lattice-Boltzmann Automaton, 2006.

Guo Z, Zheng C, Shi B. Discrete lattice effects on the forcing term in the lattice Boltzmann method . Phys. Rev. E 65 (2002), p. 046308, 2002.

Khanafer K, AlAmiri A, Bull J. Laminar natural convection heat transfer in a differentially heated cavity with a thin porous fin attached to the hot wall , 2015.

Levy B, Friedrich H, Cater J E, Clarke R J, Denier J P. The impact of twine/mesh ratio on the flow dynamics through a porous cylinder. Exp Fluids 55:1829 DOI 10.1007/s00348-014-1829-y, 2014.

Lima P H S, Janzen J G, Nepf H M. Flow patterns around two neighboring patches of emergent vegetation and possible implications for deposition and vegetation growth. Environ Fluid Mech 15:881–898 DOI 10.1007/s10652-015-9395-2, 2015.

Mahdi R A, Mohammed H A, Munisamy K M, Saeid N H. Review of convection heat transfer and fluid flow in porous media with nanofluid . Renewable and Sustainable Energy Reviews Volume 41, 2015.

Mattis S A, Dawson C N, Kees C E, Farthing M W. An immersed structure approach for fluid-vegetation interaction. Advances in Water Resources Volume 80, 2015.

OpenLB: Open source lattice Boltzmann code. http://optilb.org/openlb/

Ozalp C, Pinarbasi A, Sahin B. Experimental measurement of ow past cavities of diff erent shapes. Experimental Thermal and Fluid Science, 34(5):505–515, 2010.

Pan Y, Follett E, Chamecki M, Nepf H. Strong and weak, unsteady reconfiguration and its impact on turbulence structure within plant canopies . Physics of Fluids 26, 105102, 2014.

ParaView: Open source data analysis and visualization application. https://www.paraview.org/

Patton E G, Sullivan P P, Shaw R H, Finnigan J J, Weil J C. Atmospheric Stability Influences on Coupled Boundary Layer and Canopy Turbulence. Journal of the Atmospheric Sciences Volume 73 No. 4, 2016.

Peskin C. Numerical analysis of blood flow in the heart . Journal of Computational Physics Volume 25, Issue 3, 1977.

Roşca A V, Pop I. Flow and heat transfer over a vertical permeable stretching/shrinking sheet with a second order slip . International Journal of Heat and Mass Transfer Volume 60, 2013.

Page 47: Modelado de Medios Porosos Interactuando con Fluidos

Sajjadi M, Azaiez J. Scaling and unified characterization of flow instabilities in layered heterogeneous porous media . Phys. Rev. E 88, 033017, 2013.

Silin N, Converti J, Dalponte D, Clausse A. Flow instabilities between two parallel planes semi-obstructed by an easily penetrable porous medium , J Fluid Mech. 689 417-433, 2011.

Skordos P A. Initial and boundary conditions for the lattice Boltzmann method . Phys. Rev. E 48, pp. 4824–4842, 1993.

Van Dyke M. An Album of Fluid Motion , 1982.

Von Karman TH. Airfoil Theory for Non-Uniform Motion . Journal of the Aeronautical Sciences, Vol. 5, No. 10, pp. 379-390, 1938.

White B L, Nepf H M. Shear instability and coherent structures in shallow ow adjacent to a porous layer . Journal of Fluid Mechanics, 593:1–32, 2007.

Page 48: Modelado de Medios Porosos Interactuando con Fluidos

Apéndice 1: Código Main/Principal

#include "olb2D.h"

#include "olb2D.hh"

#include <vector>

#include <cmath>

#include <iostream>

#include <iomanip>

#include <fstream>

#include "io/xmlReader.h"

#include <omp.h>

#include "vtkCommonCoreModule.h"

#include "vtkSmartPointer.h"

#include "vtkCellArray.h"

#include "vtkDoubleArray.h"

#include "vtkFloatArray.h"

#include "vtkPointData.h"

#include "vtkPoints.h"

#include "vtkPolyData.h"

#include "vtkPolyDataWriter.h"

#include "vtkNew.h"

#include "PorousMedium.h"

using namespace olb;

using namespace olb::descriptors;

using namespace olb::graphics;

using namespace std;

typedef double T;

#define DESCRIPTOR ForcedD2Q9Descriptor

/// Parámetros de la simulación

T lx; // largo del canal

T ly; // alto del canal

int N; // resolución del modelo

Page 49: Modelado de Medios Porosos Interactuando con Fluidos

int M; // refinamiento del tiempo de disctretización

// (time discretization refinement)

T maxPhysT; // tiempo de simulación en segundos

T Nu; // viscosidad

T lattU; // velocidad del Lattice

T delta; // tamaño de celda

/// Checkpoints

int useCheckpoint = 0;

int checkpointIteration = 0;

string checkpointFile = "";

/// Etapas de velocidad (empinada y leve)

int phase1; // duración de fase de pendiente empinada

int phase2; // duración de fase de pendiente leve

T velocityPhase1 = 0.; // velocidad al finalizar la etapa 1

T maxVelocity = 0.; // velocidad al finalizar la etapa 2

T velocity = 0.;

/// Extracción de resultados

T extPointPosX = 0;

T extPointPosY = 0;

T extSlicePosX = 0;

T extReyX = 0;

int extNumIterations = 10000;

/// Guardado en VTK

vtkPolyData* polyCell;

vtkDoubleArray* polyCellVelX;

vtkDoubleArray* polyCellVelY;

vtkDoubleArray* polyCellRho;

vtkPolyData* slices;

vtkDoubleArray* polySliceVelX;

vtkDoubleArray* polySliceVelY;

vtkDoubleArray* polySliceRho;

/// Inicialización de la Geometría

void prepareGeometry(LBconverter<T> const& converter,

SuperGeometry2D<T>& superGeometry) {

OstreamManager clout(std::cout,"prepareGeometry");

Page 50: Modelado de Medios Porosos Interactuando con Fluidos

clout << "Prepare Geometry ..." << std::endl;

Vector<T,2> extend(lx,ly);

Vector<T,2> origin;

superGeometry.rename(0,2); // renombra todo el dominio a 2

superGeometry.rename(2,1,1,1); // renombra todo de 2 a 1

// exceptuando los bordes

/// Definición del número de material de la entrada

extend[0] = 2.*converter.getLatticeL();

origin[0] = -converter.getLatticeL();

IndicatorCuboid2D<T> inflow(extend, origin);

superGeometry.rename(2,3,1,inflow); // renombra de 2 a 3 las celdas

// dentro de inflow

/// Definición del número de material de la salida

origin[0] = lx-converter.getLatticeL();

IndicatorCuboid2D<T> outflow(extend, origin);

superGeometry.rename(2,4,1,outflow); // renombra de 2 a 4 las celdas

// dentro de outflow

/// Eliminación de voxels innecesarios fuera de la superficie

superGeometry.clean();

superGeometry.checkForErrors();

superGeometry.print();

clout << "Prepare Geometry ... OK" << std::endl;

}

/// Inicialización del Lattice

void prepareLattice(LBconverter<T> const& converter,

SuperLattice2D<T, DESCRIPTOR>& sLattice,

Dynamics<T, DESCRIPTOR>& bulkDynamics,

sOnLatticeBoundaryCondition2D<T,DESCRIPTOR>&

sBoundaryCondition,

SuperGeometry2D<T>& superGeometry ) {

OstreamManager clout(std::cout,"prepareLattice");

clout << "Prepare Lattice ..." << std::endl;

Page 51: Modelado de Medios Porosos Interactuando con Fluidos

T omega = converter.getOmega();

/// Material=0 --> no hace nada

sLattice.defineDynamics(superGeometry, 0, &instances::getNoDynamics<T,

DESCRIPTOR>());

/// Material=1 --> dinámica de fluido (canal)

sLattice.defineDynamics(superGeometry, 1, &bulkDynamics);

/// Material=2 --> dinámica de bounce back (bordes)

sLattice.defineDynamics(superGeometry, 2, &instances::getBounceBack<T,

DESCRIPTOR>());

/// Material=3 --> dinámica de fluido (entrada del canal)

sLattice.defineDynamics(superGeometry, 3, &bulkDynamics);

/// Material=4 --> dinámica de fluido (salida del canal)

sLattice.defineDynamics(superGeometry, 4, &bulkDynamics);

/// Definición de condiciones de contorno

sBoundaryCondition.addVelocityBoundary(superGeometry, 3, omega);

sBoundaryCondition.addPressureBoundary(superGeometry, 4, omega);

/// Condiciones iniciales

AnalyticalConst2D<T,T> rhoF(1);

std::vector<T> velocity(2,T(0));

AnalyticalConst2D<T,T> uF(velocity);

/// Inicialización de valores de velocidad y densidad

sLattice.defineRhoU(superGeometry, 1, rhoF, uF);

sLattice.iniEquilibrium(superGeometry, 1, rhoF, uF);

sLattice.defineRhoU(superGeometry, 3, rhoF, uF);

sLattice.iniEquilibrium(superGeometry, 3, rhoF, uF);

sLattice.defineRhoU(superGeometry, 4, rhoF, uF);

sLattice.iniEquilibrium(superGeometry, 4, rhoF, uF);

sLattice.initialize();

clout << "Prepare Lattice ... OK" << std::endl;

}

Page 52: Modelado de Medios Porosos Interactuando con Fluidos

/// Eliminación de archivos de otras ejecuciones

void deleteOldFiles(){

remove("VelocidadPromedio.txt");

remove("Reynolds.txt");

remove("DesvioEstandar.txt");

remove("EvolucionPunto.vtk");

remove("EvolucionPerfil.vtk");

char const * aux = checkpointFile.c_str();

remove(aux);

}

/// Guardado de Checkpoint

void saveState(SuperLattice2D<T,DESCRIPTOR>& sLattice, LBconverter<T>&

converter){

OstreamManager clout(std::cout,"Save");

clout << "Saving system state" << std::endl;

sLattice.save("porous.checkpoint");

/// Guardado de valores de velocidad e iteración finales

Cell<T,DESCRIPTOR> cell;

T vel[2];

if(sLattice.get(0,ly/2,cell)){

ForcedBGKdynamics<T, DESCRIPTOR> d (

converter.getOmega(),

instances::getBulkMomenta<T,DESCRIPTOR>()

);

d.computeU(cell,vel);

FILE *output = fopen("checkpointData.txt","w");

fprintf(output, "Iteracion: %d, Velocidad X: %lf\n",

converter.numTimeSteps(maxPhysT)-1, vel[0]);

fclose(output);

}

}

/// Cargado de valores desde Checkpoint

void loadCheckpoint(SuperLattice2D<T,DESCRIPTOR>& sLattice, int& iT){

OstreamManager clout(std::cout,"checkpoint");

clout << "Loading Checkpoint at t=" << checkpointIteration << std::endl;

sLattice.load(checkpointFile);

iT = checkpointIteration;

}

Page 53: Modelado de Medios Porosos Interactuando con Fluidos

/// Guardado de valores del canal

void getResults(SuperLattice2D<T,DESCRIPTOR>& sLattice,

LBconverter<T>& converter, int iT,

SuperGeometry2D<T>& superGeometry, Timer<T>& timer) {

SuperVTKwriter2D<T> vtkWriter("plbm");

SuperLatticePhysVelocity2D<T, DESCRIPTOR> velocity(sLattice, converter);

SuperLatticePhysPressure2D<T, DESCRIPTOR> pressure(sLattice, converter);

vtkWriter.addFunctor( velocity );

vtkWriter.addFunctor( pressure );

const int vtkIter = 20; // frecuencia de

// gardado

const int statIter = converter.numTimeSteps(.1); // frecuencia de

// estadísticas

const int startOnIter = 0; // iteración de

// comienzo de guardado

if (iT==0) {

/// Creación de archivo inicial para converter

writeLogFile(converter, "plbm");

/// Creación de archivos iniciales para geometría

SuperLatticeGeometry2D<T, DESCRIPTOR> geometry(sLattice,

superGeometry);

SuperLatticeCuboid2D<T, DESCRIPTOR> cuboid(sLattice);

SuperLatticeRank2D<T, DESCRIPTOR> rank(sLattice);

superGeometry.rename(0,2);

vtkWriter.write(geometry);

vtkWriter.write(cuboid);

vtkWriter.write(rank);

vtkWriter.createMasterFile();

}

/// Escritura de archivos vtk y "profile text file" TODO

if ((iT >= startOnIter)&&(iT%vtkIter==0)) {

vtkWriter.write(iT);

ofstream *ofile = 0;

if (singleton::mpi().isMainProcessor()) {

Page 54: Modelado de Medios Porosos Interactuando con Fluidos

ofile = new

ofstream((singleton::directories().getLogOutDir()+"centerVel.dat").c_str())

;

}

T Ly = converter.numCells(ly);

for (int iY=0; iY<=Ly; ++iY) {

T dx = converter.getDeltaX();

const T maxVelocity =

converter.physVelocity(converter.getLatticeU());

T point[2]={T(),T()};

point[0] = lx/2.;

point[1] = (T)iY/Ly;

const T radius = ly/2.;

std::vector<T> axisPoint(2,T());

axisPoint[0] = lx/2.;

axisPoint[1] = ly/2.;

std::vector<T> axisDirection(2,T());

axisDirection[0] = 1;

axisDirection[1] = 0;

Poiseuille2D<T> uSol(axisPoint, axisDirection, maxVelocity, radius);

T analytical[2] = {T(),T()};

uSol(analytical,point);

SuperLatticePhysVelocity2D<T, DESCRIPTOR> velocity(sLattice,

converter);

AnalyticalFfromSuperLatticeF2D<T, DESCRIPTOR>

intpolateVelocity(velocity, true);

T numerical[2] = {T(),T()};

intpolateVelocity(numerical,point);

if (singleton::mpi().isMainProcessor()) {

*ofile << iY*dx << " " << analytical[0]

<< " " << numerical[0] << "\n";

}

}

delete ofile;

}

/// Escritura por consola

if (iT%statIter==0) {

/// Valores del Timer

timer.update(iT);

timer.printStep();

Page 55: Modelado de Medios Porosos Interactuando con Fluidos

/// Estadisticas del Lattice

sLattice.getStatistics().print(iT,converter.physTime(iT));

}

}

/// Aumento de velocidad

void scaleVelocity(SuperLattice2D<T, DESCRIPTOR>& sLattice,

LBconverter<T> const& converter, int iT,

SuperGeometry2D<T>& superGeometry){

T distance2Wall = converter.getLatticeL()/2.;

int iTupdate = 5; // frecuencia de actualización en iteraciones

if(iT%iTupdate==0){

if(iT < phase1){ // aumento durante etapa 1

velocity = velocity + (velocityPhase1-velocity)/(phase1-iT) *

iTupdate;

}

else{

if(iT < phase2){ // aumento durante etapa 2

velocity = velocity + (maxVelocity-velocity)/(phase2-iT) *

iTupdate;

}

}

Poiseuille2D<T> poiseuilleU(superGeometry, 3, velocity, distance2Wall);

sLattice.defineU(superGeometry, 3, poiseuilleU);

}

}

/// Seteo de fuerzas externas en cero

void resetForces(SuperLattice2D<T,DESCRIPTOR>& sLattice,

LBconverter<T> const & converter,

SuperGeometry2D<T>& superGeometry){

std::vector<T> forceA(2,T());

forceA[0] = 0.;

forceA[1] = 0.;

AnalyticalConst2D<T,T> forceTerm(forceA); // término de fuerza en cero

std::vector<T> extend(2,T());

extend[0] = lx;

extend[1] = ly;

std::vector<T> origin(2,T());

Page 56: Modelado de Medios Porosos Interactuando con Fluidos

IndicatorCuboid2D<T> cuboid(extend, origin); // indicador que abarca

// todo el canal

// seteo del término en el área abarcada por el indicador

sLattice.defineExternalField(superGeometry, cuboid,

DESCRIPTOR<T>::ExternalField::forceBeginsAt,

DESCRIPTOR<T>::ExternalField::sizeOfForce, forceTerm);

}

/// Carga de Parámetros de geometría desde xml

/// Dimensiones del canal, los puntos del medio poroso y la permeabilidad

void setGeometryParameters(PorousMedium & pm){

string fName("geometria.xml");

XMLreader param (fName);

lx = param["parametros"]["lx"].get<T>();

ly = param["parametros"]["ly"].get<T>();

int numPoints = param["parametros"]["numPoints"].get<int>();

T physPermeability = param["parametros"]["physPermeability"].get<T>();

/// Puntos

T * pointX = new T[numPoints];

T * pointY = new T[numPoints];

char * p = new char[100]; // armado de string <px> </px>

p[0]= 'p';

char * c = new char[99];

for(int i = 0; i < numPoints; i++){

sprintf(c, "%d", i);

for (int j = 0; j < 99; j++){

p[j+1] = c[j];

}

pointX[i] = param["puntos"][p]["x"].get<T>();

pointY[i] = param["puntos"][p]["y"].get<T>();

}

pm.setPoints(pointX,pointY,numPoints);

pm.setPermeability(physPermeability);

delete [] p;

p = NULL;

delete [] c;

c = NULL;

delete [] pointX;

pointX = NULL;

Page 57: Modelado de Medios Porosos Interactuando con Fluidos

delete [] pointY;

pointY = NULL;

}

/// Carga de Parámetros de disctretización desde xml

/// N, M, velocidad del lattice, delta y Radio de influencia

void setDiscParameters(PorousMedium & pm){

string fName("discretizacion.xml");

XMLreader param (fName);

N = param["N"].get<int>();

M = param["M"].get<int>();

T influenceRadius = param["influenceRadius"].get<T>();

delta = param["delta"].get<T>();

lattU = param["latticeU"].get<T>();

pm.setInfluenceRadius(influenceRadius);

}

/// Carga de Parámetros de simulación desde xml

/// tiempo de simulación y viscosidad del fluido

void setSimulationParameters(){

string fName("simulacion.xml");

XMLreader param (fName);

maxPhysT = param["maxPhysT"].get<T>();

Nu = param["Nu"].get<T>();

}

/// Carga de Parámetros de setup desde xml

/// Evolución de la velocidad de entrada

void setSetupParameters(LBconverter<T> const & converter){

string fName("setup.xml");

XMLreader param (fName);

velocity = param["velIni"].get<T>();

velocityPhase1 = param["velMaxPahse1"].get<T>();

maxVelocity = param["velMax"].get<T>();

T aux1 = param["phase1"].get<T>(); // duración de etapa 1 en segundos

T aux2 = param["phase2"].get<T>(); // duración de etapa 2 en segundos

phase1 = converter.numTimeSteps(aux1); // traducción segundos-iteraciones

phase2 = converter.numTimeSteps(aux2); // traducción segundos-iteraciones

}

Page 58: Modelado de Medios Porosos Interactuando con Fluidos

/// Carga de Parámetros de checkpoint desde xml

/// Nombre de archivo, iteración inicial y si se cargará desde el

/// checkpoint

void setCheckpointParameters(){

string fName("checkpoint.xml");

XMLreader param (fName);

useCheckpoint = param["use"].get<int>();

checkpointFile = param["file"].get<string>();

checkpointIteration = param["iteration"].get<int>();

}

/// Carga de Parámetros de extracción desde xml

/// Posiciones del punto, el corte y el reynolds, y número de iteraciones a

/// guardar

void setExtractionParameters(){

string fName("extraccion.xml");

XMLreader param (fName);

extPointPosX = param["pointX"].get<T>();

extPointPosY = param["pointY"].get<T>();

extSlicePosX = param["sliceX"].get<T>();

extReyX = param["reyX"].get<T>();

extNumIterations = param["iterations"].get<int>();

}

/// Cálculo de Reynolds

T computeReynolds(T x, SuperLattice2D<T,DESCRIPTOR>& sLattice,

LBconverter<T> const & converter){

T inc = converter.getLatticeL(); // tamaño de celda

T y = inc;

Cell<T,DESCRIPTOR> cell;

std::vector<T> velocity(2,T());

T v[2];

velocity[0] = 0;

while(y < ly){ // iteración sobre corte en X

if (sLattice.get(x,y,cell)){

ForcedBGKdynamics<T, DESCRIPTOR> d (

converter.getOmega(),

Page 59: Modelado de Medios Porosos Interactuando con Fluidos

instances::getBulkMomenta<T,DESCRIPTOR>()

);

d.computeU(cell,v);

velocity[0] = velocity[0] + v[0]; //suma de velocidades en en eje X

}

y = y + inc;

}

velocity[0] = velocity[0]/(converter.numCells(ly)-1) *

converter.physVelocity(); // promedio de velocidad

return (velocity[0]*ly/converter.getCharNu()); // cálculo de reynolds

}

/// Extracción de Reynolds

void recordReynolds(int iT, T x, SuperLattice2D<T,DESCRIPTOR>& sLattice,

LBconverter<T> const & converter){

// iteración de comienzo

const int start = converter.numTimeSteps(maxPhysT) - extNumIterations;

const int reIter = 2; // frecuencia de extracción en iteraciones

if (iT > start){

if (iT%reIter==0) {

FILE *output = fopen("Reynolds.txt","a");

fprintf(output, "Iteracion: %d; Reynolds: %lf\n", iT,

computeReynolds(extReyX, sLattice, converter));

fclose(output);

}

}

}

/// Extracción de valores del punto

void updatePointEvolution(int iT, SuperLattice2D<T,DESCRIPTOR>& sLattice,

LBconverter<T> const & converter){

// iteración de comienzo

const int start = converter.numTimeSteps(maxPhysT) - extNumIterations;

if (iT >= start){

T v[2];

T rho;

Cell<T,DESCRIPTOR> cell;

ForcedBGKdynamics<T, DESCRIPTOR> d (

converter.getOmega(),

instances::getBulkMomenta<T,DESCRIPTOR>()

Page 60: Modelado de Medios Porosos Interactuando con Fluidos

);

if(sLattice.get(extPointPosX,extPointPosY,cell)){

d.computeRhoU(cell,rho,v);

// guardado de valores en estructura auxiliar

polyCellVelX->InsertNextValue(v[0]);

polyCellVelY->InsertNextValue(v[1]);

polyCellRho->InsertNextValue(rho);

}

}

}

/// Inicialización de estructuras de guardado del punto

void initExtractionPoint(){

polyCell = vtkPolyData::New();

vtkPoints* polyCellPoints = vtkPoints::New();

vtkCellArray* polyCellVerts = vtkCellArray::New();

vtkFloatArray* pcoordsCell = vtkFloatArray::New();

pcoordsCell->SetNumberOfComponents(3);

pcoordsCell->SetNumberOfTuples(extNumIterations);

for(int t = 0; t < extNumIterations; t++){

float dcell[2]= {t,0};

pcoordsCell->SetTuple(t,dcell);

}

// seteo de puntos

polyCellPoints->SetData(pcoordsCell);

pcoordsCell->Delete();

// seteo de vertices

for(int i = 0; i < extNumIterations; i++){

polyCellVerts->InsertNextCell(1);

polyCellVerts->InsertCellPoint(i);

}

// seteo de arreglos

polyCellVelX = vtkDoubleArray::New();

polyCellVelX->SetName("VelX");

polyCellVelY = vtkDoubleArray::New();

polyCellVelY->SetName("VelY");

polyCellRho = vtkDoubleArray::New();

polyCellRho->SetName("Rho");

Page 61: Modelado de Medios Porosos Interactuando con Fluidos

// seteo de polyData

polyCell->SetPoints(polyCellPoints);

polyCell->SetVerts(polyCellVerts);

polyCellPoints->Delete();

polyCellVerts->Delete();

}

/// Extracción de valores del corte

void updateProfileEvolution(int iT, SuperLattice2D<T,DESCRIPTOR>& sLattice,

LBconverter<T> const & converter){

// iteración de comienzo

const int start = converter.numTimeSteps(maxPhysT) - extNumIterations;

if (iT >= start){

T v[2];

T rho;

Cell<T,DESCRIPTOR> cell;

ForcedBGKdynamics<T, DESCRIPTOR> d (

converter.getOmega(),

instances::getBulkMomenta<T,DESCRIPTOR>()

);

T y = 0;

T inc = converter.getLatticeL(); // tamaño de celda

while(y < ly){

if(sLattice.get(extSlicePosX,y,cell)){

d.computeRhoU(cell,rho,v);

// guardado de valores en estructura auxiliar

polySliceVelX->InsertNextValue(v[0]);

polySliceVelY->InsertNextValue(v[1]);

polySliceRho->InsertNextValue(rho);

}

y = y + inc;

}

}

}

/// Inicialización de estructuras de guardado del corte

void initSlices(LBconverter<T> const & converter){

int cells = converter.numCells(ly);

int numPoints = extNumIterations*cells;

Page 62: Modelado de Medios Porosos Interactuando con Fluidos

slices = vtkPolyData::New();

vtkPoints* polySlicePoints = vtkPoints::New();

vtkCellArray* polySliceVerts = vtkCellArray::New();

vtkFloatArray* pcoords = vtkFloatArray::New();

// seteo de coordenadas

pcoords->SetNumberOfComponents(3);

pcoords->SetNumberOfTuples(numPoints);

for(int t = 0; t < extNumIterations; t++){

for(int y = 0; y < cells; y++){

float f[2] = {t,y};

pcoords->SetTuple(t*cells +y, f);

}

}

// seteo de puntos

polySlicePoints->SetData(pcoords);

pcoords->Delete();

// seteo de vertices

for(int i = 0; i < numPoints; i++){

polySliceVerts->InsertNextCell(1);

polySliceVerts->InsertCellPoint(i);

}

// seteo de arreglos

polySliceVelX = vtkDoubleArray::New();

polySliceVelX->SetName("VelX");

polySliceVelY = vtkDoubleArray::New();

polySliceVelY->SetName("VelY");

polySliceRho = vtkDoubleArray::New();

polySliceRho->SetName("Rho");

// seteo de polyData

slices->SetPoints(polySlicePoints);

slices->SetVerts(polySliceVerts);

polySlicePoints->Delete();

polySliceVerts->Delete();

}

/// Guardado de valores extraídos (punto o corte) de estructura auxiliar a

/// archivo vtk

Page 63: Modelado de Medios Porosos Interactuando con Fluidos

void recordData(vtkPolyData* container, vtkDoubleArray* velX,

vtkDoubleArray* velY, vtkDoubleArray* rho, string filename){

container->GetPointData()->AddArray(velX);

container->GetPointData()->AddArray(velY);

container->GetPointData()->AddArray(rho);

velX->Delete();

velY->Delete();

rho->Delete();

vtkSmartPointer<vtkPolyDataWriter> writer =

vtkSmartPointer<vtkPolyDataWriter>::New();

writer->SetInputData(container);

writer->SetFileName(filename);

writer->Write();

slices->Delete();

}

int main(int argc, char* argv[]) {

/// ===============================

/// === Etapa 1: Inicialización ===

/// ===============================

olbInit(&argc, &argv);

singleton::directories().setOutputDir("./tmp/");

OstreamManager clout(std::cout,"main");

#ifdef PARALLEL_MODE_MPI

int ierr = MPI_Comm_rank(MPI_COMM_WORLD, &node);

if (ierr) printf("> > > Error en MPI < < <\n");

else printf("nodo: %d\n", node);

#endif

/// Carga de parámetros desde xml

PorousMedium pMedium;

setGeometryParameters(pMedium);

setDiscParameters(pMedium);

setSimulationParameters();

setCheckpointParameters();

setExtractionParameters();

/// Inicialización del Conversor de unidades

LBconverter<T> converter(

(int) 2,

Page 64: Modelado de Medios Porosos Interactuando con Fluidos

(T) delta/N,

(T) lattU/M,

(T) Nu,

(T) 0.1,

(T) 0.2

);

converter.print();

/// Carga de parámetros desde xml e inicialización de

/// estructuras auxiliares

setSetupParameters(converter);

initSlices(converter);

initExtractionPoint();

/// Definición de la Geometría

std::vector<T> extend(2,T());

extend[0] = lx;

extend[1] = ly;

std::vector<T> origin(2,T());

IndicatorCuboid2D<T> cuboid(extend, origin);

#ifdef PARALLEL_MODE_MPI

const int noOfCuboids = singleton::mpi().getSize();

#else

const int noOfCuboids = 7;

#endif

CuboidGeometry2D<T> cuboidGeometry(cuboid, converter.getLatticeL(),

noOfCuboids);

HeuristicLoadBalancer<T> loadBalancer(cuboidGeometry);

SuperGeometry2D<T> superGeometry(cuboidGeometry, loadBalancer, 2);

prepareGeometry(converter, superGeometry);

/// Definición del Lattice

SuperLattice2D<T, DESCRIPTOR> sLattice(superGeometry);

/// Instanciación de la dinámica del fluido

ForcedBGKdynamics<T, DESCRIPTOR> bulkDynamics (

converter.getOmega(),

instances::getBulkMomenta<T,DESCRIPTOR>()

);

/// Condiciones de contorno

sOnLatticeBoundaryCondition2D<T, DESCRIPTOR>

sBoundaryCondition(sLattice);

createInterpBoundaryCondition2D<T, DESCRIPTOR> (sBoundaryCondition);

Page 65: Modelado de Medios Porosos Interactuando con Fluidos

prepareLattice(converter, sLattice, bulkDynamics, sBoundaryCondition,

superGeometry);

/// Carga de estado desde checkpoint

int iTini = 0;

if(useCheckpoint != 0){

loadCheckpoint(sLattice, converter, superGeometry, iTini);

}

else{

deleteOldFiles();

}

/// ==========================

/// === Etapa 2: Ejecución ===

/// ==========================

clout << "starting simulation..." << endl;

Timer<T> timer(converter.numTimeSteps(maxPhysT),

superGeometry.getStatistics().getNvoxel());

timer.start();

for (int iT = iTini; iT < converter.numTimeSteps(maxPhysT); ++iT) {

/// Aumento de Velocidad

scaleVelocity(sLattice, converter, iT, superGeometry);

/// Cálculo y aplicación de fuerzas del Medio Poroso

resetForces(sLattice, converter, superGeometry);

pMedium.applyForce(sLattice, converter);

/// Colisión de poblaciones y propagación

sLattice.collideAndStream();

/// Extracción de Resultados

getResults(sLattice, converter, iT, superGeometry, timer);

recordReynolds(iT, lx/2., sLattice, converter);

updatePointEvolution(iT, sLattice,converter);

updateProfileEvolution(iT, sLattice, converter);

}

/// =============================

/// === Etapa 3: Finalización ===

Page 66: Modelado de Medios Porosos Interactuando con Fluidos

/// =============================

/// Guardado de checkpoint

saveState(sLattice,converter);

//Guardado de valores del punto

recordData(polyCell, polyCellVelX, polyCellVelY, polyCellRho,

"EvolucionPunto.vtk");

//Guardado de valores del corte

recordData(slices, polySliceVelX, polySliceVelY, polySliceRho,

"EvolucionPerfil.vtk");

timer.stop();

timer.printSummary();

}

Page 67: Modelado de Medios Porosos Interactuando con Fluidos

Apéndice 2: Código de Medio Poroso

#include "olb2D.h"

#include <vector>

#include <cmath>

#include <iostream>

#include <iomanip>

#include <fstream>

#include <omp.h>

#include "PorousMedium.h"

using namespace olb;

using namespace olb::descriptors;

using namespace olb::graphics;

using namespace std;

typedef double T;

#define DESCRIPTOR ForcedD2Q9Descriptor

/// Función delta de Dirac, distancia medida en celdas

T PorousMedium::deltaDirac(T dist){

//Valor Absoluto de la distancia

if (dist < 0) {

dist = dist * -1;

}

if (dist < 1){ // Disatncia entre 0 y 1

return ((3. - 2.*dist + sqrt(1. + 4.*dist - 4*dist*dist))/8.);

}

if (dist < 2){ // Distancia entre 1 y 2

return ((5. - 2.*dist - sqrt(-7. + 12.*dist - 4.*dist*dist))/8.);

}

return 0.; // Diatancia mayor a 2

Page 68: Modelado de Medios Porosos Interactuando con Fluidos

}

/// Cálculo de velocidad del entorno a cada punto

void PorousMedium::computeVelocity(SuperLattice2D<T,DESCRIPTOR>& sLattice,

LBconverter<T> const & converter){

/// Recorre un entorno a cada punto y suma las velocidades

/// de las celdas ponderadas por la distancia

T velocity[2];

T v[2];

T inc = converter.getLatticeL(); // Tamaño de celda

Cell<T,DESCRIPTOR> cell;

T x;

T y;

T maxX;

T maxY;

T diracX;

T diracY;

T proximity = influenceRadius * inc; // Radio de influencia en

// unidades del Lattice

ForcedBGKdynamics<T, DESCRIPTOR> d (

converter.getOmega(),

instances::getBulkMomenta<T,DESCRIPTOR>()

);

for(int i = 0; i < numPoints; i++){

// Límites del entorno

x = pointX[i] - proximity;

y = pointY[i] - proximity;

maxX = pointX[i] + proximity;

maxY = pointY[i] + proximity;

velocity[0] = 0;

velocity[1] = 0;

while(x < maxX){

diracX = deltaDirac((x-pointX[i])/inc); // Cálculo parcial de

//función Dirac (eje X)

while(y < maxY){

if (sLattice.get(x,y,cell)) { // Evaluación de limites del dominio

d.computeU(cell,v);

diracY = deltaDirac((y-pointY[i])/inc); // Cálculo parcial de

// función Dirac (eje Y)

Page 69: Modelado de Medios Porosos Interactuando con Fluidos

velocity[0] = velocity[0] + diracX*diracY*v[0];

velocity[1] = velocity[1] + diracX*diracY*v[1];

}

y = y + inc;

}

x = x + inc;

y = pointY[i] - proximity;

}

pointVelX[i] = velocity[0];

pointVelY[i] = velocity[1];

}

}

/// Cálculo parcial de fuerza, sin ponderar por la distancia

Vector<T,2> PorousMedium::computeForce(LBconverter<T> const & converter,int

point){

T d = converter.latticePorosity(physPermeability);// Permeabilidad en

// unidades del Lattice

T tmp = (-1)*(converter.getLatticeNu()/d);

Vector<T,2> force (tmp*pointVelX[point],tmp*pointVelY[point]);

return (force);

}

/// Aplicación de fuerza de cada punto del medio poroso

void PorousMedium::applyForce(SuperLattice2D<T,DESCRIPTOR>& sLattice,

LBconverter<T> const & converter){

/// Recorre el entorno de cada punto, calculando y aplicando

/// la componente de fuerza del medio poroso.

computeVelocity(sLattice, converter);

T inc = converter.getLatticeL(); // Tamaño de celda

Cell<T,DESCRIPTOR> cell;

T x;

T y;

T maxX;

T maxY;

T diracX;

T diracY;

Vector<T,2> force;

Vector<T,2> pointForce;

Vector<T,2> forceX;

T proximity = influenceRadius * inc; // Radio de influencia en unidades

// del Lattice

Page 70: Modelado de Medios Porosos Interactuando con Fluidos

for (int i = 0; i < numPoints; i++){

// Límites del entorno

x = pointX[i] - proximity;

y = pointY[i] - proximity;

maxX = pointX[i] + proximity;

maxY = pointY[i] + proximity;

/// Cálculo de fuerza

force = computeForce(converter, i);

while(x < maxX){

diracX = deltaDirac((x-pointX[i])/inc); // Cálculo parcial de función

// Dirac (eje X)

forceX[0] = force[0]*diracX; // Aplicación parcial de función Dirac

forceX[1] = force[1]*diracX; // Aplicación parcial de función Dirac

while(y < maxY){

diracY = deltaDirac((y-pointY[i])/inc); // Cálculo parcial de

// función Dirac (eje Y)

if (sLattice.get(x,y,cell)){ // Evaluación de limites del dominio

/// Seteo de fuerza

T* externalData = cell.getExternal(0);

externalData[0] += (forceX[0]*diracY);

externalData[1] += (forceX[1]*diracY);

sLattice.set(x,y,cell);

}

y = y + inc;

}

x = x + inc;

y = pointY[i] - proximity;

}

}

}

/// Inicialización de puntos del medio poroso

void PorousMedium::setPoints(T * pX, T * pY, int number){

this.pointX = pX;

this.pointY = pY;

this.numPoints = num;

pointVelX = new T[numPoints];

pointVelY = new T[numPoints];

}

Page 71: Modelado de Medios Porosos Interactuando con Fluidos

/// Inicialización de permeabilidad del medio poroso

void PorousMedium::setPermeability(T physPerm){

this.physPermeability = physPerm;

}

/// Inicialización de radio de influencia de los puntos del medio poroso

void PorousMedium::setInfluenceRadius(T rad){

this.influenceRadius = rad;

}

Page 72: Modelado de Medios Porosos Interactuando con Fluidos

Apéndice 3: Entorno y Compilación Al desarrollar la herramienta se optó por utilizar el entorno de trabajo open source Atom (Atom) por preferencia personal.

Entorno open source Atom (Atom) utilizado para el desarrollo de la herramienta. La compilación del proyecto se facilitó por medio del uso de archivos Makefile. Tanto la compilación como la ejecución de la herramienta se realizaron por consola.

Page 73: Modelado de Medios Porosos Interactuando con Fluidos

Ejemplo de ejecución de la herramienta por consola Para la visualización de resultados se utilizó el programa ParaView (ParaView), que permite abrir y analizar de forma práctica archivos en formato vtk y vti.

Page 74: Modelado de Medios Porosos Interactuando con Fluidos

Apéndice 4: Archivos Los archivos xml utilizados para la carga de parámetros se separaron en base a su contenido:

- Parámetros relevantes a la administración de guardados parciales (checkpoint.xml) - Parámetros asociados a (discretizacion.xml) - Parámetros asociados a la extracción de datos (extraccion.xml) - Parámetros determinantes de la geometría del entorno (geometria.xml) - Parámetros que definen las etapas de progreso de la simulación (setup.xml) - Parámetros asociados a aspectos generales de la simulación (simulacion.xml)

En el capítulo 3 se encuentra una descripción más detallada del contenido de los archivos. La ejecución de la herramienta genera archivos en los que almacena los datos extraídos:

- EvolucionPerfil.vtk almacena la historia del corte, - EvolucionPunto.vtk almacena la historia del punto, - Reynolds.txt almacena el número de Reynolds tomado periódicamente, - checkpointData.txt almacena la información necesaria para cargar el checkpoint

generado al finalizar la ejecución (), - porous.checkpoint_rank0_size1.dat es el archivo de checkpoint que contiene la

información del estado guardado. Para el guardado de la simulación generan archivos dat, pvd y vti:

- centerVel.dat - plbm.dat - couboid_iT0000000.pvd - geometry_iT0000000.pvd - rank_iT0000000.pvd - plbm.pvd - plbm_iTXXXXXXXCXXXXX.vti - rank_iTXXXXXXXCXXXXX.vti - geometry_iTXXXXXXXCXXXXX.vti - cuboid_iTXXXXXXXCXXXXX.vti

Siendo las “X” números que identifican el orden de los archivos. Para visualizar la simulación por medio de ParaView es necesario abrir el archivo “plbm.pvd”