[ anterior ] [ Contenidos ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ siguiente ]
Fortran 90
para la asignatura Química Computacional
Los objetivos de esta clase son los siguientes:
Enumerar las reglas básicas de la sintaxis de Fortran
y el juego
de caracteres usado en los programas.
La ejecución de operaciones básicas aritméticas y el orden en que se ejecutan los operadores aritméticos.
El uso de la orden PARAMETER.
Explicar los diferentes tipos que existen de variables numéricas y cómo definirlas.
Reglas básicas de sintaxis:
Número máximo de caracteres por línea de código: 132.
Número máximo de caracteres en la definición de una variable: 31.
'&' es el carácter de continuación de línea. Solo se coloca al final de la línea.[1]
'!' es el carácter que marca inicio de comentario. Los comentarios tras el comando están permitidos.
';' es el carácter que permite separar dos (o más) comandos en una misma línea.
En la definición de variables puede usarse el guión bajo ('_') y mezclar números y letras, aunque el nombre de la variable no puede comenzar por un número.
Juego de caracteres usados en códigos Fortran
A-Z Letters 0-9 Digits _ Underscore Blank = Equal + Plus - Minus * Asterisk / Slash or oblique ' Apostrophe ( Left parenthesis ) Right parenthesis , Comma . Period or decimal point : Colon ; Semicolon ! Exclamation mark "" Quotation mark % Percent & Ampersand < Less than > Greater than
Jerarquía de operadores aritméticos:
Operadores aritméticos: {+,-,*,/,**}.
Jerarquía: (1) ** (dcha. a izqda.); (2) *,/ (depende del compilador); (3) +,- (depende del compilador).
Atención al redondeo, a la mezcla de tipos diferentes de variables en funciones aritméticas. Se deben realizar las operaciones de modo que la pérdida de precisión se minimice.
Cuando se realizan operaciones aritméticas, el procesador utiliza variables del mismo tipo, por lo que si las variables utilizadas son de diferente tipo una de ellas cambia de tipo para que sean ambos iguales. El orden de prioridad, de más bajo a más alto, es: INTEGER, REAL, DOUBLE PRECISION y COMPLEX, por lo que si se combina un número entero con uno real de doble precisión, el entero promociona a doble precisión y el resultado se da en doble precisión. Una vez terminada la operación u operaciones aritméticas, el tipo del resultado final se determina de acuerdo con el tipo de la variable a la que se asignará.
Tamaño de enteros
Entero 32 bits ::(2**31)-1 = 2,147,483,647 (~ 10**9)
Entero 64 bits :: (2**63)-1 = 9,223,372,036,854,774,807 (~ 10**19)
Tamaño y precisión de números reales
Real 32 bits :: precisión = 6-9 ~ 0.3E38 - 1.7E38
Real 64 bits :: precisión = 15-18 ~ 0.5E308 - 0.8E308
Usando PARAMETER al definir una variable podemos definir constantes en los programas. En la definición pueden llevarse a cabo operaciones aritméticas simples. Ver Programa ejemplo_2_4.f90, Sección 2.3.4.
(*) Presentar los diferentes tipos de enteros y de reales que existen en
Fortran
y las funciones intrínsecas [2] KIND, EPSILON,
PRECISION y HUGE etc., así como la manera de definir
variables dentro de los diferentes tipos que existen.
En el caso de variables enteras, si queremos definir una variable llamada i0 que pueda tomar, como mínimo, todos los valores posibles entre -999999 y 999999 debemos establecer una constante, llamada por ejemplo ki, usando la función intrínseca SELECTED_INT_KIND() y utilizarla en la definición de la variable
INTEGER, PARAMETER :: ki = SELECTED_INT_KIND(6) INTEGER(KIND=ki) :: i0
La función intrínseca[3] SELECTED_INT_KIND(X) tiene como salida un entero que nos indica el tipo (kind) de una variable entera que es capaz de reproducir todos los números enteros en el rango (-10E+X, 10E+X) donde X es un escalar entero. De este modo si queremos que una constante entera en nuestro programa tenga esta precisión debemos hacer referencia a ella del siguiente modo:
-1234_ki 2354_ki 2_ki
Si hubiera algún error al compilar con las órdenes anteriores y definir un entero, entonces la función SELECTED_INT_KIND(X) tendrá como salida -1.
En el caso de variables reales hemos de usar una representación del número con
decimales (floating point representation). Todas las que siguen son
representaciones válidas de constantes reales en Fortran
-10.66E-20 0.66E10 1. -0.4 1.32D-44 2E-12 3.141592653
En este caso la orden para alterar el modo de almacenamiento de reales es usando la función SELECTED_REAL_KIND(p=X,r=Y), con dos parámetros. Proporciona como salida un número entero asociado con el tipo (kind) de la variable definida. Permite definir a una variable real que cumpla con las siguientes condiciones:
Que tenga una precisión que sea al menos X y con un rango de exponentes decimales que viene dado al menos por Y. Las etiquetas de los argumentos son opcionales.
Si varios resultados son posibles se escogerá aquel con la menor precisión decimal.
Al menos uno de los dos parámetros de entrada, X o Y, debe expresarse en la definición de la variable. Tanto X como Y son enteros. Si no existe una variable que se acomode a las condiciones exigidas la salida de SELECTED_REAL_KIND(X,Y) será -1 si la precisión no alcanza el nivel impuesto, -2 si es el exponente el que no lo alcanza y -3 si ambos no son posibles.
Si por ejemplo queremos definir una variable real llamada a0 que tenga una precisión de 15 decimales y con exponentes entre -306 y 307 lo podemos hacer con las ordenes
INTEGER, PARAMETER :: kr = SELECTED_REAL_KIND(15,307) REAL(KIND=kr) :: a0
Si queremos que los escalares reales que hemos mencionado anteriormente sean de este tipo haremos referencia a ellos como
-10.66E-20_kr 0.66E10_kr 142857._kr -0.4_kr 2E-12_kr 3.141592653_kr
El programa Programa ejemplo_2_5.f90, Sección 2.3.5 permite ver cómo usar la orden KIND, que nos proporciona el valor de KIND asociado a un escalar o una variable dada. En este programa corto podemos ver el resultado por defecto de KIND obtenido para diferentes variables.
El programa Programa ejemplo_2_6.f90, Sección 2.3.6 se pueden encontrar ejemplos de los diferentes tipos, cómo definirlos y de las funciones que proporcionan información acerca de sus límites presentando las útiles funciones intrínsecas KIND, DIGITS, EPSILON, TINY, HUGE, EXPONENT, MAXEXPONENT, MINEXPONENT, PRECISION , RADIX y RANGE.
En este programa se definen las variables usando las funciones SELECTED_INT_KIND y SELECTED_REAL_KIND directamente en la definición. Es correcto aunque es mejor cuando se definen varias variables usar el procedimiento descrito en las notas.
Las funciones usadas dan la siguiente información:
KIND(x): su salida es de tipo entero y proporciona el parámetro de tipo de la variable x.
DIGITS(x): su salida es de tipo entero y proporciona el número de cifras significativas de x.
EPSILON(x): si el argumento x es real su salida es otro real, con el mismo de tipo (kind) que x, y que es el número más pequeño de este tipo tal que 1.0 + EPSILON(X) > 1.
TINY(x): si el argumento x es real su salida es un valor del mismo tipo que x, siendo el mínimo valor positivo definible para dicho tipo de variables.
HUGE(x): si el argumento x es real o entero su salida es un valor del mismo tipo que x, siendo el máximo valor definible en dicho tipo.
EXPONENT(x): exponente del valor x. Si x = 0 entonces EXPONENT(x)=0.
MAXEXPONENT(x): máximo exponente posible en el tipo del valor x.
MINEXPONENT(x): mínimo exponente posible en el tipo del valor x.
PRECISION(x): si el argumento x es real o complejo su salida es un valor entero que informa de la precisión decimal en el tipo de variable de x.
RADIX(x): resultado entero e igual a la base del tipo de x.
RANGE(x): resultado entero e igual al rango del exponente para el tipo de x.
(*) Presentar como se pierde precisión al ejecutar cálculos y como indicar que una constante es de un tipo determinado para mejorar la precisión en los cálculos.
PROGRAM ej_2_1 IMPLICIT NONE ! ! Ejemplo de programa que permite calcular la energía ! de un modo normal dados el número de cuantos (v), la ! frecuencia (w) y la anarmonicidad (wx) como ! ! Ge(v) = we (v+1/2) - wexe (v+1/2)^2 ! ! ! Definicion de variables REAL :: energ_0, energ, delta_e ! deltae = energ-energ0 REAL :: we = 250.0, wexe = 0.25 ! Unidades: cm-1 INTEGER :: v = 0 CHARACTER(LEN=60) :: for_mol ! Operaciones I/O PRINT *,'Formula de la molecula : ' READ(*,*), for_mol PRINT *,'Num. de quanta de excitacion : ' READ(*,*), v ! Calculos energ = we*(v+0.5) - wexe*(v+0.5)**2 energ_0 = we*(0.5) - wexe*(0.5)**2 delta_e = energ - energ_0 ! Operaciones I/O PRINT * PRINT *,'Especie molecular: ', for_mol PRINT *,'num. de quanta: ', v PRINT *,'energ = ',energ,'cm-1' PRINT *,'energ_0 = ',energ_0,'cm-1' PRINT *,'energ - energ_0 = ',delta_e,'cm-1' END PROGRAM ej_2_1
PROGRAM ej_2_2 IMPLICIT NONE REAL :: A,B,C INTEGER :: I A = 1.5 B = 2.0 C = A / B I = A / B PRINT * PRINT *, 'Caso (1), variable real' PRINT *,A,'/',B,' = ',C PRINT *, 'Caso (2), variable entera' PRINT *,A,'/',B,' = ',I END PROGRAM ej_2_2
PROGRAM ej_2_3 IMPLICIT NONE INTEGER :: I,J,K REAL :: Answer I = 5 J = 2 K = 4 Answer = I / J * K PRINT *,'I = ',I PRINT *,'J = ',J PRINT *,'K = ',K PRINT *,'I / J * K = ',Answer END PROGRAM ej_2_3
PROGRAM ej_2_4 ! Programa para calcular el tiempo que tarda la luz en ! recorrer una distancia dada en unidades astronómicas. ! 1 UA = 1,50E11 m ! !Definicion de variables IMPLICIT NONE ! u_a : unidad astronomica en km REAL , PARAMETER :: u_a=1.50*10.0**8 ! a_luz : año luz --> distancia en km recorrida por la luz en un año. REAL , PARAMETER :: a_luz=9.46*10.0**12 ! m_luz : minuto luz --> distancia en km recorrida por la luz en un minuto. REAL :: m_luz ! dist : distancia recorrida en UAs (INPUT) REAL :: dist ! t_min : tiempo en minutos necesario para recorrer la distancia Distance REAL :: t_min ! ! min : parte entera de t_min ! seg : número de segundos (parte decimal de t_min) INTEGER :: min, seg ! m_luz = a_luz/(365.25 * 24.0 * 60.0) ! Calculo del minuto-luz ! PRINT * PRINT *,'Distancia en UAs' READ(*,*), dist PRINT * ! t_min = (dist*u_a)/m_luz min = t_min; seg = (t_min - min) * 60 ! PRINT *,' La luz tarda ' , min,' minutos y ', seg,' segundos' Print *,' en recorrer una distancia de ',dist,' UA.' END PROGRAM ej_2_4
PROGRAM ej_2_5 INTEGER :: i REAL :: r CHARACTER :: c LOGICAL :: l COMPLEX :: cp PRINT *,' Integer ',KIND(i) PRINT *,' Real ',KIND(r) PRINT *,' Char ',KIND(c) PRINT *,' Logical ',KIND(l) PRINT *,' Complex ',KIND(cp) END PROGRAM ej_2_5
PROGRAM ej_2_6 ! From Program ch0806 of Chivers & Sleightholme ! ! Examples of the use of the kind ! function and the numeric inquiry functions ! ! Integer arithmetic ! ! 32 bits is a common word size, ! and this leads quite cleanly ! to the following ! 8 bit integers ! -128 to 127 10**2 ! 16 bit integers ! -32768 to 32767 10**4 ! 32 bit integers ! -2147483648 to 2147483647 10**9 ! ! 64 bit integers are increasingly available. ! This leads to ! -9223372036854775808 to ! 9223372036854775807 10**19 ! ! You may need to comment out some of the following ! depending on the hardware platform and compiler ! that you use. INTEGER :: I INTEGER ( SELECTED_INT_KIND( 2)) :: I1 INTEGER ( SELECTED_INT_KIND( 4)) :: I2 INTEGER ( SELECTED_INT_KIND( 8)) :: I3 INTEGER ( SELECTED_INT_KIND(16)) :: I4 ! Real arithmetic ! ! 32 and 64 bit reals are normally available. ! ! 32 bit reals 8 bit exponent, 24 bit mantissa ! ! 64 bit reals 11 bit exponent 53 bit mantissa ! REAL :: R = 1.0 REAL ( SELECTED_REAL_KIND( 6, 37)) :: R1 = 1.0 REAL ( SELECTED_REAL_KIND(15,307)) :: R2 = 1.0 REAL ( SELECTED_REAL_KIND(18,310)) :: R3 = 1.0 PRINT *,' ' PRINT *,' Integer values' PRINT *,' Kind Huge' PRINT *,' ' PRINT *,KIND(I ),' ',HUGE(I ) PRINT *,' ' PRINT *,KIND(I1 ),' ',HUGE(I1 ) PRINT *,KIND(I2 ),' ',HUGE(I2 ) PRINT *,KIND(I3 ),' ',HUGE(I3 ) PRINT *,KIND(I4 ),' ',HUGE(I4 ) PRINT *,' ' PRINT *,' ----------------------------------- ' PRINT *,' ' PRINT *,' Real values' ! PRINT *,' Kind ', KIND(R ), ' Digits ', DIGITS(R ) PRINT *,' Huge = ',HUGE(R ), ' Tiny =', TINY(R) PRINT *,' Epsilon = ',EPSILON(R),' Precision = ', PRECISION(R) PRINT *,' Exponent = ',EXPONENT(R), 'MAXExponent = ', MAXEXPONENT(R), ' MINExponent = ',MINEXPONENT(R) PRINT *,' Radix = ', RADIX(R ), ' Range =', RANGE(R) PRINT *,' ' ! ! PRINT *,' Kind ', KIND(R1 ), ' Digits ', DIGITS(R1 ) PRINT *,' Huge = ',HUGE(R1 ), ' Tiny =', TINY(R1) PRINT *,' Epsilon = ',EPSILON(R1),' Precision = ', PRECISION(R1) PRINT *,' Exponent = ',EXPONENT(R1), 'MAXExponent = ', MAXEXPONENT(R1), ' MINExponent = ',MINEXPONENT(R1) PRINT *,' Radix = ', RADIX(R1 ), ' Range =', RANGE(R1) PRINT *,' ' ! ! PRINT *,' Kind ', KIND(R2 ), ' Digits ', DIGITS(R2 ) PRINT *,' Huge = ',HUGE(R2 ), ' Tiny =', TINY(R2) PRINT *,' Epsilon = ',EPSILON(R2),' Precision = ', PRECISION(R2) PRINT *,' Exponent = ',EXPONENT(R2), 'MAXExponent = ', MAXEXPONENT(R2), ' MINExponent = ',MINEXPONENT(R2) PRINT *,' Radix = ', RADIX(R2 ), ' Range =', RANGE(R2) PRINT *,' ' ! ! PRINT *,' Kind ', KIND(R3 ), ' Digits ', DIGITS(R3 ) PRINT *,' Huge = ',HUGE(R3 ), ' Tiny =', TINY(R3) PRINT *,' Epsilon = ',EPSILON(R3),' Precision = ', PRECISION(R3) PRINT *,' Exponent = ',EXPONENT(R3), 'MAXExponent = ', MAXEXPONENT(R3), ' MINExponent = ',MINEXPONENT(R3) PRINT *,' Radix = ', RADIX(R3 ), ' Range =', RANGE(R3) PRINT *,' ' ! END PROGRAM ej_2_6
[ anterior ] [ Contenidos ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ siguiente ]
Lecciones de Fortran 90
para la asignatura Química Computacional
mailto:francisco.perez@dfaie.uhu.es