Detalles aclaratorios para el dibujo de mallas de E.F.

Primera Parte

En esta página trataremos de aclarar los detalles relativos a la visualización de mallas de Elementos Finitos, tratadas en la primera página para los NO iniciados.

Antes de aclarar someramente el funcionamiento de AWK daremos unas explicaciones respecto al tipo de mallas que se pueden representar. En principio, el programa que se da aquí está previsto para elementos isoparamétricos de ocho nodos. Evidentemente, para cuadriláteros de cuatro nodos, por ejemplo, sería todavía más sencillo... (aunque tampoco mucho más).

El conjunto de los programas --"programitas", podríamos decir-- que se incluyen en el fichero dist.tar.gz consiste en una especie de "caja de herramientas", que, jugando unas un papel y otras otro, nos permiten realizar la labor que deseamos. El papel principal se lo reparten AWK, MAKE y METAPOST, jugando éste último un papel más bien mecánico.

Voy a transcribir el listado de uno de los programas escritos con AWK, para poderlo analizar y aclarar.

El siguiente listado corresponde al programa "premeta.awk".


. 1--- BEGIN {maxx=0; maxy=0; minx=10000; miny=10000; esc=1}
. 2--- NR == 1 { nel=$1; nod=$2}
. 3--- NR < nel+2 {n=n+1; a[n-1]="z["$3"]--z["$4"]--z["$5"]..tension 1.5..z["$6"]..tension 1.5..z["$7"]--z["$8"]--z["$9"]..tension..1.5..z["$10"]..tension 1.5..cycle"; e[n-1]="label(\""n-1"\", (z["$3"]+z["$7"])/2); circ((z["$3"]+z["$7"])/2);" }
. 4--- NR > nel+1 {j=j+1; z[j]="("$2"u,"$3"u);"
. 5--- if ($2 > maxx) maxx=$2
. 6--- if ($2 < minx) minx=$2
. 7--- if ($3 > maxy) maxy=$3
. 8--- if ($3 < miny) miny=$3 }
. 9--- END {ux=13/(maxx-minx);uy=20/(maxy-miny);esc=uy;if(ux < uy) esc=ux
10--- print nel" "nod" "esc > "mesh.d"
11--- { for (i=1 ; i < nod+1 ; i++) print z[i] > "mesh.d"}
12--- { for (i=1 ; i < nel+1 ; i++) print a[i] > "mesh.d"}
13--- { for (i=1 ; i < nel+1 ; i++) print e[i] > "mesh.d"} }


Este es el primer programa de AWK que se utiliza. El listado que he transcrito, lo he numerado línea a línea para poder comentarlas. En la realidad, las líneas no llevan ningún número de orden ni guión delante, como se puede ver en "dist.tar.gz". Ahora, paso a comentar el programa:

  • En primer lugar se establecen unos valores para calcular el tamaño máximo del dibujo que se va a hacer y buscar la escala --"esc"--- adecuada para que quepa en la pantalla.
  • Como la ventaja de AWK es que automáticamente lee las líneas del fichero que se le envía, le ponemos la condición --"NR==1"-- de que si la línea es la primera --NR representa el número de línea que está leyendo-- lea el número de elementos y de nodos de la malla, que son los datos que figuran en la primera línea del fichero de lectura. AWK lee por "campos", es decir lee todo aquello que está en la línea hasta encontrarse un espacio en blanco que hace la función de separador. Al primer campo que lee le asigna el valor $1, al segundo $2...y así consecutivamente. Por tanto en la segunda línea del programa asignamos a las variables "nel" y "nod" los dos primeros valores que figuran en el fichero de lectura, que son precisamente el número de elementos y el de nodos de la malla.
  • A continuación, y cumpliendo la condición de que pase por todos los elementos, Vamos haciendo dos cosas al mismo tiempo: por un lado preparamos la escritura que entenderá MetaPost y por otro guardamos los valores de la conectividad de la malla, es decir los nodos de que están compuestos los elementos para un determinado sentido de giro, que en este caso es según las agujas del reloj, empezando por el nodo inferior izquierdo del elemento. En este programa, aprovechamos para situar la zona en que vamos a numerar los elementos dentro de un ciculito.
  • En la línea 4 leemos las coordenadas de los nodos que son los datos que vienen a continuación en el fichero "mesh" de lectura. y los asignamos a las variables "z" para su utilización por MetaPost.
  • Las líneas 5 a 8 incluídas ambas, nos sirven para fijar esos valores máximos del tamaño de la malla y para establecer el valor de la escala del dibujo --"esc"-- que vamos a utilizar.
  • La línea novena empieza por "END", lo que significa que AWK ha terminado su lectura y tiene los datos guardados como le hemos dicho. Inmediatamente, empezamos a escribir valores en el nuevo fichero de lectura. El original se llamaba "mesh" y al nuevo le llamamos "mesh.d", que irá teniendo la estructura de un programa de metapost, aunque todavía hay que depurarlo, lo que haremos en otra pasada.
  • De la línea 10 al final de este programa, escribimos el resto de los datos a "mesh.d"

    Vamos a ver el efecto de correr este programa. Si tenemos el fichero original "mesh",
    escribimos "awk -f premeta.awk mesh" y obtenemos el nuevo fichero "mesh.d". (Después de "echar una ojeada a estos ficheros, para volver a esta página pulse el botón de "página anterior" en el navegador).

    Después de hacer lo anterior el fichero "mesh.d" tiene todos los datos necesarios para que una nueva pasada por otro sencillo programa AWK, lo transforme en un fichero de salida que sea un verdadero programa de MetaPost. Veamos como se lleva a cabo este segundo proceso. El nuevo programa a utilizar se llama "genmp.awk" --de "GENeración del programa en MetaPost". Repetiré la operación anterior de transcribirlo y comentarlo (ya dije en la página anterior, que esta era la página "rollo").


    .1--- Begin{
    .2--- NR == 1 {nel=$1; nod=$2; esc=$3}
    .3--- NR < nod+2 {n=n+1; z[n]=$0}
    .4--- NR > nod+1 && NR < nod+nel+2 {k=k+1; a[k]=$0}
    .5--- END{print "beginfig(1);","u="esc"cm;" > "mesh.mp"
    .6--- print "pickup pencircle scaled 1.5;" > "mesh.mp"
    .7--- {for (i= 1; i < nod+1; i++)
    .8--- print "z["i"] = "z[i+1] > "mesh.mp" }
    .9--- {for (i= 1; i < nel+1; i++)
    10--- print "draw "a[i]" withcolor blue;" > "mesh.mp" }
    11--- print "endfig;","end" > "mesh.mp"
    12--- }


    Bueno, pues vamos con este nuevo listado-awk. Empezamos como antes leyendo la primera línea --ahora del fichero reformado mesh.d-- donde además del número de elementos y el de nodos tenemos ya escrita la escala a la que debemos realizar el dibujo para que nos entre en unos márgenes razonables. A continuación leemos las coordenadas de los nodos --obsérvese que hemos cambiado el orden de lectura de conectividad y nodos-- y las guardamos en el vector de puntos "z[n]". Después leemos la conectividad por elementos y la guardamos en "a[k]". Con eso llegamos a "END", es decir, AWK ha recorrido entero el fichero "mesh.d". A partir de ese momento empezamos a escribir el fichero-programa definitivo de MetaPost. El programa se llamará "mesh.mp" y lo empezamos en la misma línea 5 con el clásico inicio de todo programa en este lenguaje gráfico: "beginfig...". Tomamos como escala la calculada con anterioridad, colocamos el tamaño de grosor de línea que queremos (línea 6) y empezamos un bucle de tipo "for"que, sencillamente, nos escribe las coordenadas de los nodos de la malla en el formato preciso. Terminamos en la línea 8 y en la 9 iniciamos otro bucle para escribir las órdenes de dibujo de acuerdo con nuestro idioma "metapostiano". Terminamos en la línea 11 con el también clásico final de todos los programas en Metapost: "endfig; end".

    Y eso es todo. Si "alimentamos" a este segundo programa con el fichero ya conocido "mesh.d", obtenemos el programa final en MetaPost "mesh.mp". Este último se trata como a cualquier programa de metapost. Se compila con "mpost mesh.mp" y se visualiza en la forma acostumbrada.

    De todo ello hablaremos en la segunda parte de estos "Detalles aclaratorios", para no hacer demasiado pesada esta página. En la segunda parte hablaremos de MAKE, TeX y algo de Fortran y Elementos Finitos....