[ 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:
presentar las ventajas que ofrece el uso de funciones, subrutinas y módulos.
presentar el concepto de función en Fortran
.
mostrar los diferentes tipos de funciones que pueden usarse: intrínsecas, genéricas, elementales, transformacionales e internas.
hacer posible la definición de funciones por el usuario.
mostrar la diferencia entre funciones externas y funciones contenidas en el programa principal.
El uso de estas estructuras permite desarrollar una programación más estructurada y eficaz ya que permiten
el desarrollo y comprobación de diferentes subtareas de forma independiente.
reciclar unidades en diferentes programas, disminuyendo el tiempo necesario para generar el código.
aislar el código de efectos inesperados ya que están perfectamente diferenciadas las variables generales y las variables a las que tiene acceso cada subrutina o función.
En primer lugar nos centramos en las funciones y, en la siguiente unidad, tratamos las subrutinas.
Características generales de las funciones.
Las principales características de una función son
Requieren el uso de uno o varios parámetros o argumentos al invocar la función.
Dichos argumentos pueden ser una expresión.
Generalmente una función da como resultado un valor, y dicho valor es función de los parámetros o argumentos con los que se ha invocado la función. El resultado de la evaluación de la función puede ser un escalar o una matriz de cualquier tipo.
Los argumentos pueden ser de diferente tipo.
En Fortran
existen aproximadamente más de cien funciones
predefinidas que pueden usarse de modo muy simple y directo. Por ejemplo, si
necesitamos funciones trigonométricas podemos usar, siendo X,
Y variables reales[11]:
Y = SIN(X)
Y = COS(X)
Y = TAN(X)
Este tipo de funciones son llamadas funciones intrínsecas. En esta
URL
puede encontrarse una lista completa de las funciones intrínsecas de que se
dispone al usar el compilador gfortran
. En general las funciones
intrínsecas son genéricas, lo que quiere decir que admiten distintos
tipos de argumentos (mejor dicho argumentos con diferente precisión). La
excepción son las cuatro funciones no genéricas, LGE,
LGT, LLE y LLT.
Las funciones llamadas elementales admiten como argumento tanto escalares como matrices. Un ejemplo de esto se puede ver en los ejemplos Programa ejemplo_8_1.f90, Sección 8.3.1 y Programa ejemplo_8_2.f90, Sección 8.3.2, donde se muestra el carácter elemental y genérico de algunas funciones. En el ejemplo Programa ejemplo_8_1.f90, Sección 8.3.1 se muestra también la diferencia entre variables reales con diferente precisión. Estas funciones elementales pueden aplicarse tanto a variables escalares como a arreglos. En el último caso la función se aplica a cada elemento del arreglo.
Existen también otro tipo de funciones. Entre ellas destacan las del tipo inquiry que dan información acerca de las características de un arreglo. Por ejemplo las funciones SIZE y ALLOCATED. Un ejemplo del uso de esta última función puede verse en el Programa ejemplo_5_5.f90, Sección 5.3.5 y en el Programa ejemplo_9_3.f90, Sección 9.3.3.
Otro tipo de funciones son las llamadas "transformacionales", p.e. REAL y TRANSPOSE, que transforman entre diferentes tipos de datos, y funciones que implican medidas de tiempo como SYSTEM_CLOCK y DATE_AND_TIME.
Conversión entre diferentes tipos de datos.
REAL(i): convierte un entero i en un real. El argumento i puede ser un entero, un real de doble precisión o un número complejo.
INT(x): convierte el real x en el entero equivalente, truncando la parte decimal, pudiendo ser x una variable real, real de doble precisión o compleja.
Las siguientes funciones son de interés para definir enteros a partir de reales.
CEILING(x): convierte un real x en el entero más pequeño mayor o igual a x.
FLOOR(x): convierte un real x en el mayor entero que sea menor o igual a x.
NINT(x): convierte un real x en el entero más próximo a x.
DBLE(a): convierte a a doble precisión. El argumento puede ser entero, real o complejo.
CMPLX(x) ó CMPLX(x,y): convierte en valores complejos (el segundo argumento es la parte imaginaria).
Además de las funciones intrínsecas, pueden definirse funciones. La definición de una función implica por una parte la propia definición y la posterior llamada a la función desde un programa. La definición de una función sigue el siguiente esquema:
FUNCTION fun_name(argument_list) IMPLICIT NONE Declaration section (including arguments and fun_name) .... Local variables declaration .... fun_name = expr RETURN ! Optional END FUNCTION fun_name
En el ejemplo Programa ejemplo_8_3.f90, Sección 8.3.3 se muestra como se define e invoca una función que calcula el máximo común divisor de dos números enteros. Es importante tener en cuenta lo siguiente:
En este ejemplo podemos distinguir dos bloques. Un primer bloque con el programa principal y un segundo bloque donde se define la función. De hecho la función puede definirse en un fichero diferente al programa principal, y dar ambos ficheros al compilador para que prepare el programa ejecutable.
Es importante tener en cuenta que las variables definidas en la función tienen carácter local respecto a las variables que se definen en el programa.
La función en este caso tiene como nombre MCD y su tipo es INTEGER. Por tanto, el programa espera que el valor que dé la función como resultado sea un entero.
El atributo INTENT(IN) en la definición de las variables A y B de la función:
INTEGER , INTENT(IN) :: A,B
indica que dichas variables son variables de entrada y sus valores no pueden ser modificados por la función.
Todos los argumentos de una función deben tener este atributo para evitar que inadvertidamente sus valores se modifiquen al evaluar la función.
Es posible definir funciones que sean internas, esto es, que se restrinjan a un determinado segmento de código, y no puedan ser llamadas desde otro punto del programa. Para ello se utiliza la orden CONTAINS como en los ejemplos Programa ejemplo_8_4.f90, Sección 8.3.4 y Programa ejemplo_8_5.f90, Sección 8.3.5. El primero de estos dos programas define una función con la que calcular la energía de un nivel vibracional teniendo en cuenta la frecuencia we y la anarmonicidad wexe. El segundo, dado un número entero, calcula los factores primos de dicho número. En este ejemplo Programa ejemplo_8_5.f90, Sección 8.3.5 podemos ver también el uso de un bucle del tipo REPEAT UNTIL.
PROGRAM EJEMPLO_8_1 IMPLICIT NONE !Definicion de variables INTEGER, PARAMETER :: Long=SELECTED_REAL_KIND(18,310) ! REAL (KIND=Long), PARAMETER :: DPI = ACOS(-1.0_Long) ! Definimos el número Pi REAL (KIND=Long) :: DANGLE, DANGLERAD ! REAL, PARAMETER :: PI = ACOS(-1.0) ! Definimos el número Pi REAL :: ANGLERAD ! PRINT*, 'INTRODUZCA UN ANGULO (EN GRADOS)' READ*, DANGLE PRINT* ! PASO A RADIANES DANGLERAD = DPI*DANGLE/180.0_Long ANGLERAD = PI*DANGLE/180.0 ! PRINT 20, DANGLE, DANGLERAD PRINT 21, DANGLE, ANGLERAD PRINT* PRINT* ! PRINT 22, DANGLERAD, SIN(DANGLERAD), COS(DANGLERAD), SIN(DANGLERAD)**2+COS(DANGLERAD)**2,& 1.0_Long-(SIN(DANGLERAD)**2+COS(DANGLERAD)**2) PRINT* PRINT 22, ANGLERAD, SIN(ANGLERAD), COS(ANGLERAD), SIN(ANGLERAD)**2+COS(ANGLERAD)**2,1.0 - (SIN(ANGLERAD)**2+COS(ANGLERAD)**2) ! 20 FORMAT (1X, 'UN ANGULO DE ',F14.8,' GRADOS = ', F14.8, ' RADIANES. (dp)') 21 FORMAT (1X, 'UN ANGULO DE ',F14.8,' GRADOS = ', F14.8, ' RADIANES. (sp)') 22 FORMAT (1X, 'ANGULO ',F14.8,', SIN = ', F13.9, ', COS =',F13.9,/'SIN**2+COS**2 = ', F16.12, ', 1 - SIN**2+COS**2 = ', F16.12) END PROGRAM EJEMPLO_8_1
PROGRAM EJEMPLO_8_2 IMPLICIT NONE !Definicion de variables INTEGER , PARAMETER :: NEL=5 REAL, PARAMETER :: PI = ACOS(-1.0) ! Definimos el número Pi REAL , DIMENSION(1:NEL) :: XR = (/ 0.0, PI/2.0, PI, 3.0*PI/2.0, 2.0*PI/) INTEGER , DIMENSION(1:NEL):: XI = (/ 0, 1, 2, 3, 4/) ! PRINT*, 'SENO DE ', XR, ' = ', SIN(XR) PRINT*, 'LOG10 DE ', XR, ' = ', LOG10(XR) PRINT*, 'REAL ', XI, ' = ', REAL(XI) END PROGRAM EJEMPLO_8_2
PROGRAM EJEMPLO_8_3 IMPLICIT NONE INTEGER :: I,J,Result INTEGER :: MCD EXTERNAL MCD PRINT *,' INTRODUCE DOS NUMEROS ENTEROS:' READ(*,*),I,J RESULT = MCD(I,J) PRINT *,' EL MAX COMUN DIV DE ',I,' Y ',J,' ES ',RESULT END PROGRAM EJEMPLO_8_3 ! INTEGER FUNCTION MCD(A,B) IMPLICIT NONE INTEGER , INTENT(IN) :: A,B INTEGER :: Temp IF (A < B) THEN Temp=A ELSE Temp=B ENDIF DO WHILE ((MOD(A,Temp) /= 0) .OR. (MOD(B,Temp) /=0)) Temp=Temp-1 END DO MCD=Temp END FUNCTION MCD
PROGRAM EJEMPLO_8_4 IMPLICIT NONE ! Uso de una función interna en el cálculo de la fórmula ! E(v) = we (v+1/2) - wexe (v+1/2)**2. INTEGER :: V, VMAX REAL :: we, wexe, Energy PRINT *,' INTRODUCE EL VALOR DE Vmax:' READ(*,*), VMAX PRINT *,' INTRODUCE EL VALOR DE we Y DE wexe:' READ(*,*),we, wexe DO V = 0, VMAX Energy = FEN(V) PRINT 100, V, Energy ENDDO 100 FORMAT(1X,'E(',I3,') = ',F14.6) CONTAINS ! REAL FUNCTION FEN(V) IMPLICIT NONE INTEGER , INTENT(IN) :: V FEN = we*(V+0.5)-wexe*(V+0.5)**2 END FUNCTION FEN ! END PROGRAM EJEMPLO_8_4
PROGRAM EJEMPLO_8_5 ! ! Simple program to compute the prime divisors of a given integer number. ! IMPLICIT NONE INTEGER :: NUMVAL INTEGER :: NUM ! READ(*,*), NUMVAL ! input ! DO NUM = QUOT(NUMVAL) IF (NUM == NUMVAL) THEN PRINT*, NUM EXIT ELSE PRINT*, NUMVAL/NUM, NUM NUMVAL = NUM ENDIF ENDDO ! CONTAINS ! INTEGER FUNCTION QUOT(NUM1) ! INTEGER, INTENT(IN) :: NUM1 INTEGER :: I ! QUOT = NUM1 ! DO I = 2, NUM1-1 IF (MOD(NUM1,I) == 0) THEN QUOT = NUM1/I EXIT ENDIF ENDDO ! END FUNCTION QUOT ! END PROGRAM EJEMPLO_8_5
PROGRAM EJEMPLO_8_6 ! ! Program to evaluate a 1D potential function on grid points ! IMPLICIT NONE ! REAL, DIMENSION(:), ALLOCATABLE :: X_grid, Pot_grid ! REAL :: X_min, X_max, Delta_X REAL :: V_0 = 10.0, a_val = 1.0 INTEGER :: Index, X_dim INTEGER :: Ierr ! ! INTERFACE Potf ELEMENTAL FUNCTION Potf(Depth, Inv_length, X) ! IMPLICIT NONE ! REAL, INTENT(IN) :: Depth, Inv_length, X REAL :: Potf ! END FUNCTION Potf END INTERFACE Potf ! ! READ(*,*), X_min, X_max, X_dim ! input minimum and maximum values of X and number of points ! ALLOCATE(X_grid(1:X_dim), STAT = Ierr) IF (Ierr /= 0) THEN STOP 'X_grid allocation failed' ENDIF ! ALLOCATE(Pot_grid(1:X_dim), STAT = Ierr) IF (Ierr /= 0) THEN STOP 'Pot_grid allocation failed' ENDIF ! ! Delta_X = (X_max - X_min)/REAL(X_dim - 1) ! X_grid = (/ (Index, Index = 0 , X_dim - 1 ) /) X_grid = X_min + Delta_X*X_grid ! Pot_grid = Potf(V_0, a_val, X_grid) ! DO Index = 1, X_dim PRINT*, X_grid, Pot_grid ENDDO ! DEALLOCATE(X_grid, STAT = Ierr) IF (Ierr /= 0) THEN STOP 'X_grid deallocation failed' ENDIF ! DEALLOCATE(Pot_grid, STAT = Ierr) IF (Ierr /= 0) THEN STOP 'Pot_grid deallocation failed' ENDIF ! ! END PROGRAM EJEMPLO_8_6 ! ELEMENTAL FUNCTION Potf(Depth, Inv_length, X) ! IMPLICIT NONE ! REAL, INTENT(IN) :: Depth, Inv_length, X ! REAL :: Potf ! Potf = -Depth/(COSH(Inv_length*X)**2) ! END FUNCTION Potf
[ 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