Modelación numérica de la dinámica de un mar abierto, en precencia de fricción y teniendo en cuenta la rotación de la Tierra, con forzamiento de marea Carlos Ramos Pérez Introducción:En este trabajo vamos a explicar un modelo sencillo para describir la dinámica de un mar abierto,en presencia de fricción no lineal, la fuerza de coriolis y el forzamiento de marea, vamos a presentar el código presentado por los autores del libro ’The Dynamics of coastal MOdels’, analizarlo de forma breve, resaltar algunos puntos que pueden ser mejorables del mismo y vamos a presentar el mismo código traducido a python y en cierta medida optimizado. 1. El modelo El modelo que vamos a utilizar para las simulaciones descirbe un cuerpo de agua bidimensional, cerrado por una parte y con comunicacion con el océano. Presenta una friccı́on no lineal y para estos estudios las variables se dividieron entre su escala caracterı́stica para hacerlas adimensionales. Tenemos dos ecuaciones (1) para la conservación del momento y (2) para la conservación del volumen. ∂ui ∂η =− − Cd |u|ui ∂t ∂xi (1) ∂η ∂(1 + η)ui =− ∂t ∂xi (2) 2. Estrategia Numérica Para resolver de forma numérica estas ecuaciones se usó el método de diferencias finitas en las componentes espaciales, sobre una malla regular Arakawa C, donde los valores de la velocidad fueron calculados en los lados de las celdas y el volúmen en el centro de las mismas. Para la componente temporal se usó un método de paso simple (Euler). Se escogieron estas configuraciones que son las más sencillas en aras de hacer un código mas simple, lo que trae como consecuencia la necesidad de un paso temporal muy pequeño para garantizar la estabilidad, en casos reales deben utilizarse mejores esquemas como los metodos 1 de Runge-Kutta o predictor-corrector. Las condiciones de fronteras se escogieron cerradas, simulando la costa. 3. El programa(Matlab) A continuación de presentamos el código presentado por los autores del texto citado anteriormente ??, lo vamos a describir a grandes rasgos y vamos a resaltar algunos cambios y errores. Aquı́ es de destacar que los autores no usaron todas las facilidades intrı́nsecas de un lenguaje de alto nivel como MatLab, con el objetivo expreso de que el código fuera facilmente adaptable a Fortran. En la primera parte(azul claro) se declaran las variablers que van a ser constantes en nuestro program,a y que describen el dominio, asi como los pasos tempporales y espaciales de la malla, además de algunas constantes fı́sicas como el parámetro de rozamiento y la frecuencia de Coriolis. Luego se definen los forzamientos externos debidos a la marea. A continuación comienza la iteración temporal donde se usa un ciclo ’while’ para iterar mientras el tiempo sea menor que cierto tiempo final. Dentro de este ciclo se hacen los calculos para cada celda de la malla, aplicando el método de diferencias finitas. En un primer paso para la componente u de la velocidad (violeta), donde se repite innecesariamente un ciclo ’for’, que fue optimizado en el código en python. Después (en verde) se resuelve la frontera izquierda de la componente u de la velocidad, que es la forntera que tiene forzamiento de marea. Luego (en amarillo) se resuelve el método de diferencias finitas para la componente v de la velocidad. A continuación (en rojo) se calcula la variación del volúmen para cada celda a partir de las velocidades calculadas anteriormente. Por último (en azul fuerte) se calculan las condiciones de fronteras, es de destacar que para u solo se calcula la frontera derecha ya que la izquierda depende del forzamiento de marea. Aqui hay errores, ya que se repiten las asignaciones de manera contradictoria, lo que es provablemente un error de tipografı́a. Como hemos podido observar, el código no está completamente optimizado y presenta algunos errores y reiteraciones innecesarias. 2 Fig. 1: Código en MatLab 4. Python En esta sección presentaremos el código en python, escrito a partir del programa en MatLab y con algunas optimizaciones, aunque el código es aún mejorable, además se agrega una función para graficar los resultados. # s e importan l a s l i b r e r i a s n e c e s a r i a s import numpy a s np import m a t p l o t l i b . p y p l o t a s p l t from m a t p l o t l i b . c o l o r s import BoundaryNorm from m a t p l o t l i b . t i c k e r import MaxNLocator 3 def p l o t f u n c t i o n (M, N, u , v , eta , t ) : # f u n c i o n de p l o t e o paso = 1 plt . figure () l e v e l s = MaxNLocator ( n b i n s =25). t i c k v a l u e s ( −.05 , . 0 5 ) # s e d e f i n e e l numero de c o n t o r n o s d e l mapa cmap = p l t . get cmap ( ’ coolwarm ’ ) norm = BoundaryNorm ( l e v e l s , n c o l o r s=cmap . N, c l i p=True ) # s e d e f i n e e l t i p o de p a l e t a de c o l o r e s x = y = u = v = eta np . l i n s p a c e ( 0 , 1 , M − 2 ) np . l i n s p a c e ( 0 , 1 , N − 1 ) u [ 2 : − 1 , 1: −1] v [ 2 : − 1 , 1: −1] = e t a [ 2 : − 1 , 1: −1] # s e preparan l a s v a r i a b l e s para g r a f i c a r yy , xx = np . meshgrid ( y , x ) # creamos l o s c o n t o r n o s c o n t = p l t . c o n t o u r f ( yy , xx , eta , l e v e l s=l e v e l s , cmap=cmap ) p l t . c o l o r b a r ( cont ) p l t . c o n t o u r ( yy , xx , eta , l e v e l s=l e v e l s , c o l o r s= ’ k ’ ) p l t . q u i v e r ( yy [ 0 : : paso , 0 : : paso ] , xx [ 0 : : paso , 0 : : paso ] , 100 ∗ u [ 0 : : paso , 0 : : paso ] , 100 ∗ v [ 0 : : paso , 0 : : paso ] ) p l t . t i t l e ( ’ O p e n C o a s t a l B a s i n d y n a m i c s w i t h p e r i o d i c t i d a l f o r c i n g {0} ’ . format ( t ) ) p l t . s a v e f i g ( ’ outputs ncdm / q u i v e r s { 0 } . png ’ . format ( t ) ) plt . close () # e d i t a m o s y s a l v a m o s l o s d e t a l l e s de l a f i g u r a ######################################################################### ############# COMIENZA EL METODO ################################## # D e c l a r a c i o n de c o n s t a n t e s y v a r i a b l e s n e c e s a r i a s N = 30 M = 20 dx = 1 . /N dy = dx dt = 0 . 0 0 1 tau = 20 f p r i m e = np . p i /10 tidal period = 5 a = np . z e r o s ( (M + 1 ) ) 4 u = np . z e r o s ( (M + 1 , N + 1 ) ) v = np . z e r o s ( (M + 1 , N + 1 ) ) e t a = np . z e r o s ( (M + 1 , N + 1 ) ) px = np . z e r o s ( (M + 1 , N + 1 ) ) py = np . z e r o s ( (M + 1 , N + 1 ) ) v f = np . z e r o s ( (M + 1 , N + 1 ) ) u f = np . z e r o s ( (M + 1 , N + 1 ) ) # Definimos e l f o r z a m i e n t o a [ 1 :M/ 5 ] = 0 . 0 5 a [ 4 ∗M/ 5 :M] = −0.05 t = .5 t f i n a l = 6.5 count = 71 # Comienza l a i t e r a c i i o n t e m o p r a l while t < t f i n a l : f o r j in np . a r a n g e (M) : f o r i in np . a r a n g e ( 1 , N ) : # hacemos un s o l o c i c l o por i px [ j , i ] = ( e t a [ j , i ] − e t a [ j , i − 1 ] ) / dx vf [ j , i ] = (v [ j , i ] + v [ j + 1 , i ] + v [ j , i + 1] + v[ j + 1 , i − 1]) / 4 u [ j , i ] = u [ j , i ] + dt ∗ (−px [ j , i ] + 0 ∗ f p r i m e ∗ v f [ j , i ] − u [ j , i ] / tau ) #c a l c u l a m o s u en l a f r o n t e r a i z q u i e r d a f o r j in np . a r a n g e (M) : px [ j , 0 ] = ( e t a [ j , 0 ] − a [ j ] ∗ np . s i n ( 2 ∗ np . p i ∗ t / t i d a l p e r i o d ) ) / dx vf [ j , 0] = v [ j , 0] + v [ j + 1 , 0] / 2 u [ j , 0 ] = u [ j , 1 ] + dt ∗ (−px [ j , 0 ] − u [ j , 0 ] / tau ) f o r i in np . a r a n g e ( 1 , N ) : # Calculamos l a f o r j in np . a r a n g e ( 1 , M) : py [ j , i ] = ( e t a [ j , i ] − e t a [ j −1, uf [ j , i ] = (u [ j , i ] + u [ j , i + 1] + u[ j − 1 , i + 1]) / 4 v [ j , i ] = v [ j , i ] + dt ∗ (−py [ j , ∗ u f [ j , i ] − v [ j , i ] / tau ) componente v i ] ) / dy + u[ j − 1, i ] i ] + 0 ∗ fprime f o r j in np . a r a n g e (M) : # Calculamos l a s o b r e e l e v a c i o n f o r i in np . a r a n g e (N ) : e t a [ j , i ] = e t a [ j , i ] − dt ∗ ( ( u [ j , i + 1 ] − u [ j , i ] ) / dx + 5 ( v [ j + 1 , i ] − v [ j , i ] ) / dy ) # Calculamos u y v en l a f r o n t e r a , o m i t i e n d o l a r e i t e r a c i o n d e l #l i b r o y usando una s i n t a x i s p r o p i a de l e n g u a j e s de a l t o n i v e l u [ : , N] = 0 v [M, : ] = 0 v[0 , : ] = 0 # llamamos a l a f u n c i o n de p l o t e o cada 70 i n t e r v a l o s t e m p o r a l e s i f np . mod( count , 7 0 ) == 0 : p l o t f u n c t i o n (M, N, u , v , eta , t ) count = count + 1 t = t + dt # Aqui s a l v a m o s en un formato b i n a r i o p r o p i o de python e l v a l o r #f i n a l de l a s v a r i a b l e s d e i n t e r e s , l u e g o de cumplido t o d o e l #i n t e r v a l o t e m p o r a l np . s a v e ( ’M’ , M) np . s a v e ( ’N ’ , N) np . s a v e ( ’ u ’ , u ) np . s a v e ( ’ v ’ , v ) np . s a v e ( ’ e t a ’ , e t a ) np . s a v e ( ’ time ’ , t f i n a l ) 5. Algunos Resultados A continuación mostraremos algunos resultados obtenidos usando el modelo antes descrito y el programa en python. En todos los gráficos que presentaremos a continuación en colores mostraremos la sobreelevacion adimensional de el nivel del mar y los vectores de velocidad. 5.1. Una entrada centrada Aqui podemos observar cómo los vectores tratan de moverse paralelos a las lineas de igual presión, moviéndose de zonas de mayor a zonas de menor presion de acuerdo a un valance geotrófico, aunque nunca es totalemtne paralelo debido a la componente disipativa de la ecuación del modelo, que representan una desviación del modelo geostrófico. Se pueden observar ciertas inestabilidades en la frontera izquierda, que pueden ser salvables escogiendo un esquema numérico más avanzado. 6 Fig. 2: Una entrada centrada 5.2. Otras configuraciones de la entrada Fig. 3: Una entrada Fig. 4: Dos entradas 7 Fig. 5: Sin Coriolis Fig. 6: Dos entradas en fase 6. Conclusiones De manera fgeneral se implementó un modelo para describir la dinámica de un mar con comunicación con el océano con forzamiento de marea, pudimos hacer determinados experimentos numéricos para entender la dinámica de estos sistemas, se recomienda implementar el modelo en un lenguaje de bajo nivel, por ejemplo, fortran, para incrementar la eficiencia del mismo. OBSERVAIÓN: En la carpeta compartida en el drive estarán algunas animaciones realizadas a partir de los experimentos numéricos realizados 8