Ejemplos de programación
El círculo de Möhr

Mario de Lama   malar@arrakis.es
http://www.arrakis.es/~malar
Regresar Me lo bajo

Creo que por la utilidad que este círculo tiene en el estudio de las tensiones, será del agrado de muchos. Para los que no esteis interesados en el tema pero si en la programación (sobre todo en los comandos gráficos) os recomiendo también este archivo, hallareis numerosos ejemplos de programación. En un principio el programa lo hice para la HP42 (mi primera HP) y todavía conservo el listado (naturalmente no dibuja el círculo). Si alguien lo desea puede encontrarlo en mohr.zip. Al final del archivo incluyo el listado con una explicación de cada línea. En caso de que sólo quieras utilizarlo, creo que una somera lectura te bastará para aprender a introducir los datos e interpretar los resultados.

En todo este documento, cuando se lea "S" habrá de leerse sigma y cuando se lea "T", tau.

Para empezar habrá que fijarse en que al enfrentarnos a uno de estos problemas, pueden presentarse dos casos:

  1. Hallar el estado tensional de un punto en una dirección, dadas las tensiones principales y el ángulo que define dicha dirección.
  2. Hallar las tensiones principales dadas las tensiones normales en dos direcciones ortogonales y sus correspondientes tensiones tangenciales.
Podéis ver que no he incluido el estado de tensiones triple ya que lo normal es el estudio de sistemas planos.

Por todo lo anterior, al iniciarse el programa se nos pide elegir entre una de estas dos opciones, presentando en pantalla un menú con las teclas S12, Sxy y el mensaje: ¿Qué buscas,S12 ó Sxy?. Si presionamos Sxy se activa el indicador 6 y el programa continúa, en caso de presionar S12 el programa simplemente continúa. Aclarar que este archivo trata del programa MOHR.SGX (válido para la SX y la GX) que puedes encontrar en mohr.zip, el programa MOHR.GX, que también se incluye, es básicamente igual diferenciándose en la forma de introducir los datos, y que es totalmente gráfico.

A continuación aparecerá la pantalla para la entrada de datos (dependiendo del indicador 6 contendrá unas u otras etiquetas), tras dar los valores correspondientes presionamos ENTER con lo que iniciamos una cláusula IF THEN ELSE END que, dependiendo también del estado de 6, nos resolverá el caso que hemos seleccionado. Para la entrada de datos, seguid el criterio de signos del GROB.1; en él, las direcciones positivas son todas las que no tengan expresamente el signo negativo. Cuando demos el ángulo, este siempre será el que forma el eje 1 con la dirección X (el mismo que forma 2 e Y)

Para la resolución numérica se utilizan las seis fórmulas que aparecen en la figura (podéis ver que las dos primeras son en realidad cuatro, dependiendo del signo).
Podemos destacar en THEN (de la anterior cláusula IF), que si por equivocación hemos dado unos datos tal que S1 es menor que S2, el programa produce un error y termina, ya que siempre ha de ser al contrario o como mucho pueden ser iguales. En ELSE puede producirse un error al tratar de hallar el ángulo que nos da la dirección en que se producen las tensiones principales, esto se puede deber a que se anulen numerador y denominador o solo el denominador. En el primer caso está claro que la solución ha de ser cero, ya que el círculo es un punto en el que todas las direcciones son principales. El segundo caso nos daría infinito y por tanto el arcotangente de infinito es 90 grados, para que la calculadora no nos de error al dividir por cero, activamos al principio del programa el flag -22 de forma que la división por cero nos de MAXR (su arctang. es 90).

Tras esta cláusula hemos de presentar los resultados y preparar el programa para dibujar el círculo y dado que no hemos utilizado en THEN y ELSE los mismos nombres para las mismas variables, hemos de hacerlo ahora, para ello y al final de ELSE podéis ver que recupero todas las variables que voy a usar luego y las guardo con los nombres que hubiera utilizado THEN.

Como en la construcción del círculo calculo la escala con un tamaño prefijado de PICT, le doy a este las dimensiones por defecto de la 48.

El programa nos presenta ahora otro menú para optar entre ver o no el gráfico, si presionamos NO, el programa termina. Si optamos por SI, se presenta un mensaje de espera que sobrepone todo el área de estado (por ello el salto de línea que tiene "Un momento...").

Seguidamente se ponen en la pila una serie de GROBS, que han de pegarse al gráfico, y también las coordenadas del centro y el radio del círculo. Guardamos todo ello en variables locales e iniciamos el trazado. En caso de que sea un punto (radio=0), presenta un mensaje y termina.

Hacemos que todo ángulo mayor de 180 quede reducido al suplementario equivalente (tomando el resto de dividirlo por 180) esto se debe a que el programa ha de trazar un arco, para definir el ángulo de la dirección, de la siguiente manera:

Si el ángulo fuese 405, en vez de 45, el programa dibujaría un círculo y 45 grados más, para que dibuje sólo un arco de 45 es para lo que hemos de hallar el complementario.

Con XRNG e YRNG escalamos PICT de forma que el círculo siempre aparezca con un radio de 2 en coordenadas de usuario. Para ello se hace una simple proporción entre el tamaño del radio y de PICT en la realidad y en coordenadas de usuario:

Xreal/XPICT=Radioreal/RadioPICT

De esta proporción y su equivalente para el eje Y, hemos de despejar Xreal e Yreal que son las que utilizamos para fijar el rango de trazado.

Ahora mostramos la pantalla gráfica (con PVIEW) para ver como se va dibujando el círculo y no aburrirnos mientras tanto. Tras centrar PICT en el centro del círculo ( CENTR ) comenzamos a trazar este, los ejes y la línea que junto al arco nos definirá el ángulo. Al trazar el arco nos encontramos otra complicación: La calculadora siempre los traza en sentido antihorario y si no damos los parámetros con mucho cuidado, podemos encontrarnos con que el arco trazado puede ser cualquier otro menos el indicado, hay que contemplar todas las posibilidades, de ahí las cláusulas IF que aparecen en el listado.

Lo siguiente puede parecer una tontada, pero creo que el círculo tiene una mejor presentación si conseguimos que los dos GROBS que nos forman Sx (el rectángulo negro y Sx) quedan centrados en el punto (Sx,Txy) y no como nos quedarían si para pegarlos, únicamente damos las coordenadas de este punto (ver GROB.3).

El centrado se puede conseguir por el método que aparece en el GROB.4, no es ni más ni menos que otra proporción parecida a la anterior: hallamos lo que mediría este rectángulo en la realidad y restamos o sumamos, según convenga, la mitad de sus lados a las coordenadas del punto (Sx,Txy) -punto (A,B) del GROB.4-. Pero todavía no nos interesa pegar estos dos GROB, ya que en ese caso los siguientes, que siempre van a aparecer en unas coordenadas de usuario fijas, podrían superponerse a ellos y la idea es la contraria: que el rectángulo negro tape todo lo que hay debajo para a continuación pegar con GXOR el "Sx". Por ello, salvamos los valores reales de trazado (que hay en PPAR) en la pila y borramos esta variable. Así conseguimos pasar a coordenadas de usuario para poner los otros GROB en sus coordenadas fijas, tras lo cual volvemos a almacenar los valores de trazado y sobreponemos el rectángulo con "Sx".

Tras superar todas las pruebas, nuestra calculadora nos presentará algo parecido a la figura adjunta, su menú es el de la 48G,GX; los que tengan la 48S,SX les aparecerá el menú correspondiente. Podíamos haber presentado el dibujo directamente con { } PICT, en vez de con GRAPH (PICTURE en la G, GX) pero de esta forma habríamos perdido la posibilidad de movernos con el cursor por la pantalla y pedir el valor de las coordenadas cuando lo deseemos. Este valor solo reflejará datos reales mientras no salgamos del entorno gráfico, ya que al presionar ON el programa continúa y termina tras borrar PPAR y poner el menú de variables. Si volvemos al entorno gráfico nos encontraremos con el mismo dibujo, pero ahora las coordenadas son las de usuario, ya no está a escala.

Podéis ver que el programa podría reducirse mucho si quitamos el trazado del arco y algún que otro GROB, pero la verdad es que ocupa relativamente poca memoria y a cambio creo que ofrece una buena presentación. A continuación paso a comentar el listado, naturalmente he cortado el listado de los GROBS por cuestión de espacio, pero si tecleáis el programa, tened cuidado de poner todos los números seguidos (salvo los dos primeros grupos de cada uno). Pediría, como derechos de autor, que respetarais mi nombre en el dibujo. Podría decir "exijo" pero me haríais el mismo caso y queda peor.

El siguiente código corresponde al programa MOHR.SGX que puedes encontrar en mohr.zip.

En lo que sigue, donde se vea \S, \T, \A se leerán, respectivamente, las letras griegas sigma, tau y alfa.

Donde se vea <= , >= , ->, se leerá menor o igual, mayor o igual o flecha.

Todo lo que haya entre @ y final de línea, se considera un comentario y no forma parte del programa.

               MOHR.SGX

« RCLF -> f                        @ Guarda el estado actual de los flag
 « 6 CF -16 CF -17 CF              @ Fija: rectangulares, sexages.
  -18 CF -19 SF -22 SF             @ crear complejo de 2 reales y  
                                   @ el resultado infinito es MAXR.
                                   @ En las G,GX podeis poner:
                                   @ {6 -16 -17 -18} CF {-19 -22} SF
  { { } { "\S12" « CONT» }         @ Crea el menú para optar por \Sppal.
  { } { } { "\Sxy"                 @ o \S en una dirección dada. 
  « 6 SF CONT » } } TMENU          @ Esta última activa el flag 6   
  "¿Qué buscas,\S12 ó \Sxy?"                                    
  PROMPT                           @ Muestra el menú y un mensaje. 
  "Dame los datos.ENTER"           @ Crea un mensaje para INPUT  
     IF 6 FS?                                                   
      THEN { ":\S1:                @ Dependiendo del estado de 6, 
              :\S2:                @ crea una u otra lista de   
              :\A:" }              @ etiquetas para la entrada de 
      ELSE { ":\Sx:                @ datos con INPUT.           
              :\Sy:                                             
              :\Txy:" }                                         
     END                                                      
   { { 1 0 } V } + INPUT          @ Añade la posición del cursor y
  OBJ-> 0 0 ->                    @ verificar datos.            
   a b c d t                      @ Crea 5 variables locales.   
   «                                                            
     IF 6 FS?                     @ Si buscamos \S en una dir. 'X'
      THEN a b -                                                
        IF 0 <                                                  
         THEN f STOF 2 MENU        @ En el caso de que \S1<\S2, se 
          " Error:                 @ ponen los flag iniciales y el menú
          \S1 ha de ser >= que \S2"  @ de variables. A continuación se
          DOERR                    @ genera un error y acaba.  
        END                                                     
        a b - 2 / c 2 * COS * DUP                               
        a b + 2 / + DUP 'd' STO                                 
        '\Sx' ->TAG SWAP NEG a b +                               
        2 / + '\Sy' ->TAG c 2 * SIN  @ Halla y etiqueta \Sx,\Sy,\Txy 
        a b - 2 / * DUP 't' STO      @ y finalmente \Tmáx.         
        '\Txy' ->TAG a b - 2 /                                   
        '\Tmáx' ->TAG                                            
      ELSE                           @ Si buscábamos \S principales 
        a b - 2 / SQ c SQ + (raiz)   @ (raiz)= tecla a la drcha. de TAN.
        DUP a b + 2 / DUP ROT        @ Halla y etiqueta \S1 y \S2  
        + '\S1' ->TAG ROT ROT                                    
        - NEG '\S2' ->TAG DUP2                                   
        c 2 * NEG a b -           @ Para hallar '\A':           
        IF OVER 0 ==              @ Si 'c=0', ATAN dará 0. De esta
          THEN DROP               @ forma evitamos posibles 0/0.
          ELSE /                  @ En el caso de que 'a-b=0'
        END                       @ tendremos 'c/0= ±MAXR' (por
        ATAN                      @ tener fijado el flag -22)
        2 / '\A' ->TAG            @ Etiqueta al ángulo         
        3 DUPN a c 5 LIST         @ Hace una lista con \Sx, \Txyy 
        6 ROLL 6 ROLL - 2 /       @ los resultados, etiqueta \Tmáx
        '\Tmáx' ->TAG SWAP        @ Almacena los elementos de la 
        OBJ-> DROP 't' STO 'd' STO @ lista en las variables que  
        'c' STO 'b' STO 'a' STO   @ hubiera utilizado la claúsula 
                                  @ THEN (con el flag 6 activado)       
                                  @ Con la 48G-GX se puede hacer:
                                  @ eliminar las dos últimas líneas
      END                         @ y añadir: { a b c d t } STO
     # 130d # 63d PDIM            @ Dimensiona PICT.
     { { } { "SI" «               @ Crea un menú para optar por 
     " Un momento...              @ ver el círculo. 'NO' termina 
     "  1 DISP                    @ el programa tras poner los flag
     CONT » } { } { }             @ iniciales y el menú de variables.
     { "NO" « f STOF 2 MENU       @ 'SI' lo continúa y muestra un mensaje 
     KILL » } } TMENU             @ que se sobrepone al área de estado.
     " ¿Vemos el círculo?                                       
     "                            @ Muestra el menú con un mensaje
     1 DISP 1 FREEZE HALT         @ y los resultados numéricos. 
     GROB 24 1 55555F             @ GROB 'cadena de puntos'     
     GROB 9 6 00000410C510        @ GROB '\Sx'                  
              A800A4104410                                      
     GROB 10 7 FF30FF30FF3        @ GROB 'rectángulo negro'     
               0FF30FF30FF                                      
               30FF30                                           
     GROB 24 15 0000420000                                      
                0500045545                                      
                4C42AAA44C        @ GROB 'copy-right' (mi firma) 
                9AA4838A49                                      
                F08A0C0182                                      
                033280C252                                      
                0022320812                                      
                5204025202                                      
                04010008F0                                      
     GROB 8 5 0EE85E522E          @ GROB '\S2'                  
     GROB 8 5 06E454542E          @ GROB '\S1'                  
     GROB 20 7 00000004425        @ GROB '\Tmáx'                
               0EC65504457                                      
               20454550844                                      
               550000000                                        
     a b + 2 / a b - 2 /          @ Calcula el centro y el radio 
      p \Sx cu F \Sa \Sb \T       @ Almacena todo en variables. 
     C r                                                        
     «                                                          
        IF a b ==                                               
         THEN f STOF 2 MENU       @ Si \S1=\S2 el programa termina
          "El círculo es un pto.  @ tras poner los flag iniciales
          " DOERR                 @ y el menú de variables.
        END                                                     
        c ABS 180 MOD             @ Hallamos el complementario de  \A
        c SIGN * 'c' STO                                          
        r 3.25 * DUP NEG SWAP     @ Escala PICT para que el radio 
        r 1.6 * DUP NEG SWAP      @ sea siempre de 2 unidades en 
        YRNG XRNG                 @ coordenadas de usuario.     
        C 0 R->C DUP CENTR        @ Centra PICT con el círculo. 
        { # 0d # 0d } PVIEW       @ Muestra la pantalla de gáficos
        DRAX                      @ Traza los ejes.                    
        r 0 360 ARC               @ Traza la circunferencia.    
        PICT {#36d #34d} \Sa REPL @ Pega en PICT los GROBS: \S1, \S2, 
        PICT {#87d #34d} \Sb REPL @ puntos y \Tmáx. Las coordenadas van
        PICT {#22d #7d} \T REPL   @ en coord. de puntos porque son ctes.
        PICT {#42d #12d} p GOR    @ para todos los posibles círculos.
        PICT d t R->C             @ Prepara los argum. para pegar \Sx.
        DUP C 0 R->C LINE         @ Línea del centro al punto (\Sx,\Txy).
        C 0 R->C r 1.8 / c 2 *    @ Halla centro y radio del arco 
          IF 6 FS?C               @                          '2\A'
           THEN 0                 @ Mira si el arco lo traza de: 
             IF c 0 >=                                           
              THEN SWAP           @    1º, 2\A a 0              
             END                  @    2º, 0 a 2\A              
           ELSE                                                 
             IF c t * 0 <=                                       
              THEN NEG 0                                        
                IF c 0 <=         @    3º, (-2\A) a 0            
                 THEN SWAP        @    4º, 0 a (-2\A)           
                END                                             
              ELSE 180 SWAP                                     
                IF c 0 <=                                        
                 THEN NEG 180 -   @    5º, 180 a (-180+|2\A|)   
                 ELSE - 180       @    6º, (180-|2\A|) a 180    
                END                                             
             END                                                
          END                                                   
        ARC                       @ Traza el arco del ángulo.              
        C->R PPAR DUP 2 GET SWAP  @ Halla las coor. para colocar
        1 GET - C->R 21 / ROT     @ los GROBS 'rectángulo' y '\Sx'
        + SWAP .9 * 26 / ROT SWAP @ de forma que sus centros    
        - SWAP R->C DUP2          @ coincidan con el pto. (\Sx,\Txy).   
        cu GOR                    @ Pega el GROB 'rectángulo'.  
        \Sx GXOR                  @ Pega '\Sx'.                
        PICT {#106d #41d} F REPL  @ Pega la firma.
        GRAPH                     @ Muestra el entorno gráfico,
                                  @ (en las G,GX será PICTURE).
        'PPAR' PURGE f STOF 2 MENU @ Al salir de PICT pone el menú de
      »                           @ variables, los flag iniciales
    »                             @ y borra 'PPAR'  
  »
»

Regresar