[ previous ] [ Contents ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ next ]


Fortran 90 Lessons for Computational Chemistry
Chapter 8 - Subprograms (I): FUNCTIONS


8.1 Objectives

The main aims of this lesson are the following:

  1. presenting the advantages of using functions, subroutines and modules.

  1. presenting the function concept in Fortran.

  1. showing the different types of functions: intrinsic, generic, elemental, transformational, and internal.

  1. making possible the definition of new functions by the user.

  1. evinving the difference beyween external and internal functions.

The use of subporgrams allows a more structured and efficient programming owing to


8.2 Main items.

We first focus in functions and will follow with subroutines and modules.


8.3 Example Codes


8.3.1 excode_8_1.f90

     PROGRAM ex_8_1
       IMPLICIT NONE
       ! Variable Definition
       INTEGER, PARAMETER :: Long=SELECTED_REAL_KIND(18,310)
       !
       REAL (KIND=Long), PARAMETER :: DPI = ACOS(-1.0_Long) ! Pi number double precision
       REAL (KIND=Long) :: DANGLE, DANGLERAD
       !
       REAL, PARAMETER :: PI = ACOS(-1.0) ! Pi number single precision
       REAL :: ANGLERAD
       !
       PRINT*, 'ANGLE INPUT (Degrees)'
       READ*, DANGLE
       PRINT*
       ! Transform to  RAD
       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, 'An angle of ',F14.8,' degrees = ', F14.8, ' rad. (dp)')
     21 FORMAT (1X, 'An angle of ',F14.8,' degrees = ', F14.8, ' rad. (sp)')
     22 FORMAT (1X, 'ANGLE ',F14.8,', SIN = ', F13.9, ', COS =',F13.9,/'SIN**2+COS**2 = ', F18.14, ', 1 - SIN**2+COS**2 = ', F18.14)
     END PROGRAM EX_8_1

8.3.2 excode_8_2.f90

     PROGRAM ex_8_2
       IMPLICIT NONE
       ! VARIABLE DEFINITION
       INTEGER , PARAMETER :: NEL=5
       REAL, PARAMETER :: PI = ACOS(-1.0) ! Pi number
       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*, 'Sin  ', XR, ' = ', SIN(XR)
       PRINT*, 'LOG10  ', XR, ' = ', LOG10(XR)
       PRINT*, 'REAL ', XI, ' = ', REAL(XI)
     END PROGRAM ex_8_2

8.3.3 Programa ejemplo_8_3.f90

     PROGRAM ex_8_3
       IMPLICIT NONE
       INTEGER :: I,J,Result
       INTEGER :: MCD
       EXTERNAL MCD
       PRINT *,' INTRODUCE TWO INTEGERS:'
       READ *,I,J
       RESULT = MCD(I,J)
       PRINT *,' THE GREATEST COMMON DIVISOR OF ',I,' AND ',J,' IS ',RESULT
     END PROGRAM ex_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

8.3.4 Programa ejemplo_8_4.f90

     PROGRAM ex_8_4
       IMPLICIT NONE
       ! Internal function example:
       ! E(v) = we (v+1/2) - wexe (v+1/2)**2.
       INTEGER :: V, VMAX
       REAL :: we, wexe, Energy
       PRINT *,' Vmax?:'
       READ *, VMAX
       PRINT *,' we and 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 EX_8_4

8.3.5 excode_8_5.f90

     PROGRAM ex_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 ex_8_5

8.3.6 excode_8_6.f90

     PROGRAM ex_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 ex_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

8.3.7 excode_8_7.f90

     PROGRAM ex_8_7
       !
       ! Program to characterize an array making use of inquiry functions
       !
       IMPLICIT NONE
       !
       REAL, DIMENSION(:,:), ALLOCATABLE :: X_grid
       INTEGER :: Ierr
       !
       ! 
       ALLOCATE(X_grid(-20:20,0:50), STAT = Ierr)
       IF (Ierr /= 0) THEN
          STOP 'X_grid allocation failed'
       ENDIF
       !
       WRITE(*, 100) SHAPE(X_grid)
     100 FORMAT(1X, "Shape :        ", 7I7)
       !
       WRITE(*, 110) SIZE(X_grid)
     110 FORMAT(1X, "Size :         ", I7)
       !
       WRITE(*, 120) LBOUND(X_grid)
     120 FORMAT(1X, "Lower bounds : ", 7I6)
       !
       WRITE(*, 130) UBOUND(X_grid)
     130 FORMAT(1X, "Upper bounds : ", 7I6)
       !
       DEALLOCATE(X_grid, STAT = Ierr)
       IF (Ierr /= 0) THEN
          STOP 'X_grid deallocation failed'
       ENDIF
       !
     END PROGRAM ex_8_7

[ previous ] [ Contents ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ next ]


Fortran 90 Lessons for Computational Chemistry

0.0

Curro Pérez-Bernal mailto:francisco.perez@dfaie.uhu.es