MODULE NFUTIL ! ! NAME: NFUTIL ! STATUS: Ver. 1.0 ! PURPOSE: utility routines ! LIBRARY: MATH ! TYPE: SINGLE, DOUBLE PRECISION ! AUTHOR: Shigeru Inagaki ! National Institute for Fusion Science ! +81-572-58-2143 ! inagaki@LHD.nifs.ac.jp ! ! DESCRIPTION: ! Utility routines are packaged ! ! SEE ALSO: ! CALLED: ! REVISION HISTORY: ! 14-MAY-2004 (CREATION) ! 14-SEP-2004 REALLOCATE, INDMASK added ! COMMENTS: ! USE NFNUM_KINDS, ONLY : i4b, sp, dp, lgt ! IMPLICIT NONE ! PRIVATE ! INTERFACE IMINLOC MODULE PROCEDURE IMINLOC_I4B, IMINLOC_SP, IMINLOC_DP END INTERFACE ! INTERFACE IMAXLOC MODULE PROCEDURE IMAXLOC_I4B, IMAXLOC_SP, IMAXLOC_DP END INTERFACE ! INTERFACE INTERPOL MODULE PROCEDURE INTERPOL_SP, INTERPOL_DP END INTERFACE ! INTERFACE REALLOCATE MODULE PROCEDURE REALLOCATE_VEC_STR, REALLOCATE_VEC_I4B, & & REALLOCATE_VEC_SP, REALLOCATE_VEC_DP, & & REALLOCATE_MAT_I4B, REALLOCATE_MAT_SP, & & REALLOCATE_MAT_DP END INTERFACE ! INTERFACE RESIZE MODULE PROCEDURE RESIZE_VEC_STR, RESIZE_VEC_I4B, & & RESIZE_VEC_SP, RESIZE_VEC_DP END INTERFACE ! INTERFACE CLEAR MODULE PROCEDURE CLEAR_VEC_STR, CLEAR_VEC_I4B, & & CLEAR_VEC_SP, CLEAR_VEC_DP, & & CLEAR_MAT_I4B, CLEAR_MAT_SP, & & CLEAR_MAT_DP END INTERFACE ! PUBLIC :: LGT_TO_INT, INT_TO_LGT PUBLIC :: DATENOW, IFIRSTLOC, INDMASK, IMINLOC, IMAXLOC, INTERPOL PUBLIC :: REALLOCATE, CLEAR, RESIZE ! CONTAINS ! !------------------------------------------------------- ! ELEMENTAL FUNCTION LGT_TO_INT(bool) RESULT(i) LOGICAL(lgt), INTENT(IN) :: bool INTEGER(i4b) :: i ! IF (bool) THEN i = 1 ELSE i = 0 ENDIF RETURN END FUNCTION LGT_TO_INT ! !------------------------------------------------------- ! ELEMENTAL FUNCTION INT_TO_LGT(i) RESULT(bool) INTEGER(i4b), INTENT(IN) :: i LOGICAL(lgt) :: bool ! IF (i > 0) THEN bool = .TRUE. ELSE bool = .FALSE. ENDIF RETURN END FUNCTION INT_TO_LGT ! !------------------------------------------------------- ! FUNCTION DATENOW() ! ! Make and set date as MM/DD/YYYY HH:MM ! CHARACTER(LEN=16) :: DATENOW ! INTEGER(i4b) :: date_time(8) CHARACTER(LEN=2) :: month, day, hour, minute CHARACTER(LEN=4) :: year ! CALL DATE_AND_TIME(VALUES = date_time) WRITE(year, '(I4.4)') date_time(1) WRITE(month, '(I2.2)') date_time(2) WRITE(day, '(I2.2)') date_time(3) WRITE(hour, '(I2.2)') date_time(5) WRITE(minute, '(I2.2)') date_time(6) DATENOW = month//'/'//day//'/'//year//' '//hour//':'//minute RETURN END FUNCTION DATENOW ! !------------------------------------------------------- ! FUNCTION INDMASK(mask) RESULT(indx) LOGICAL(lgt), INTENT(IN) :: mask(:) INTEGER(i4b), POINTER :: indx(:) ! INTEGER(i4b) :: n, m, i, istat INTEGER(i4b) :: series(SIZE(mask)) ! n = COUNT(mask) m = SIZE(mask) ALLOCATE(indx(n), STAT=istat) IF (istat /= 0) THEN indx => NULL() RETURN ENDIF ! FORALL(i=1:m) series(i) = i indx = PACK(series, mask) RETURN END FUNCTION INDMASK ! !------------------------------------------------------- ! FUNCTION IFIRSTLOC(mask) RESULT(iloc) ! ! Return the location of the first true element of mask. ! LOGICAL(lgt), INTENT(in) :: mask(:) INTEGER(i4b) :: iloc ! INTEGER(i4b) :: loc(1) ! loc = MAXLOC(MERGE(1,0,mask)) iloc = loc(1) IF (.NOT. mask(iloc)) THEN iloc = SIZE(mask) + 1 ENDIF RETURN END FUNCTION IFIRSTLOC ! !------------------------------------------------------- ! FUNCTION IMINLOC_I4B(vec, mask) RESULT(iloc) ! ! Return the location of the minimum element of vec. ! INTEGER(i4b), INTENT(IN) :: vec(:) LOGICAL(lgt), OPTIONAL, INTENT(IN) :: mask(:) INTEGER(i4b) :: iloc ! INTEGER(i4b) :: loc(1) ! IF (.NOT. PRESENT(mask)) THEN loc = MINLOC(vec) ELSE loc = MINLOC(vec, MASK=mask) ENDIF iloc = loc(1) RETURN END FUNCTION IMINLOC_I4B ! !------------------------------------------------------- ! FUNCTION IMINLOC_SP(vec, mask) RESULT(iloc) ! ! Return the location of the minimum element of vec. ! REAL(sp), INTENT(IN) :: vec(:) LOGICAL(lgt), OPTIONAL, INTENT(IN) :: mask(:) INTEGER(i4b) :: iloc ! INTEGER(i4b) :: loc(1) ! IF (.NOT. PRESENT(mask)) THEN loc = MINLOC(vec) ELSE loc = MINLOC(vec, MASK=mask) ENDIF iloc = loc(1) RETURN END FUNCTION IMINLOC_SP ! !------------------------------------------------------- ! FUNCTION IMINLOC_DP(vec, mask) RESULT(iloc) ! ! Return the location of the minimum element of vec. ! REAL(dp), INTENT(IN) :: vec(:) LOGICAL(lgt), OPTIONAL, INTENT(IN) :: mask(:) INTEGER(i4b) :: iloc ! INTEGER(i4b) :: loc(1) ! IF (.NOT. PRESENT(mask)) THEN loc = MINLOC(vec) ELSE loc = MINLOC(vec, MASK=mask) ENDIF iloc = loc(1) RETURN END FUNCTION IMINLOC_DP ! !------------------------------------------------------- ! FUNCTION IMAXLOC_I4B(vec, mask) RESULT(iloc) ! ! Return the location of the maximum element of vec. ! INTEGER(i4b), INTENT(IN) :: vec(:) LOGICAL(lgt), OPTIONAL, INTENT(IN) :: mask(:) INTEGER(i4b) :: iloc ! INTEGER(i4b) :: loc(1) ! IF (.NOT. PRESENT(mask)) THEN loc = MAXLOC(vec) ELSE loc = MAXLOC(vec, MASK=mask) ENDIF iloc = loc(1) RETURN END FUNCTION IMAXLOC_I4B ! !------------------------------------------------------- ! FUNCTION IMAXLOC_SP(vec, mask) RESULT(iloc) ! ! Return the location of the maximum element of vec. ! REAL(sp), INTENT(IN) :: vec(:) LOGICAL(lgt), OPTIONAL, INTENT(IN) :: mask(:) INTEGER(i4b) :: iloc ! INTEGER(i4b) :: loc(1) ! IF (.NOT. PRESENT(mask)) THEN loc = MAXLOC(vec) ELSE loc = MAXLOC(vec, MASK=mask) ENDIF iloc = loc(1) RETURN END FUNCTION IMAXLOC_SP ! !------------------------------------------------------- ! FUNCTION IMAXLOC_DP(vec, mask) RESULT(iloc) ! ! Return the location of the maximum element of vec. ! REAL(dp), INTENT(IN) :: vec(:) LOGICAL(lgt), OPTIONAL, INTENT(IN) :: mask(:) INTEGER(i4b) :: iloc ! INTEGER(i4b) :: loc(1) ! IF (.NOT. PRESENT(mask)) THEN loc = MAXLOC(vec) ELSE loc = MAXLOC(vec, MASK=mask) ENDIF iloc = loc(1) RETURN END FUNCTION IMAXLOC_DP ! !------------------------------------------------------- ! SUBROUTINE INTERPOL_SP(xa,ya,x,y,errid) ! ! Given arrays xa and ya of length N, and given a value x, this ! routine returns a value y ! USE NFERR, ONLY : ERRSTAT, DANGER ! REAL(sp), INTENT(IN) :: xa(:), ya(:) REAL(sp), INTENT(IN) :: x REAL(sp), INTENT(OUT) :: y TYPE(ERRSTAT), OPTIONAL, INTENT(OUT) :: errid ! INTEGER(i4b) :: n, ns REAL(sp) :: a ! IF (PRESENT(errid)) THEN errid%routine_name = "INTERPOL" ENDIF n = SIZE(xa) IF (n > SIZE(ya) .OR. x > MAXVAL(xa) .OR. x < MINVAL(xa)) THEN IF (PRESENT(errid)) THEN errid%message = "n > SIZE(ya) .OR. x > MAXVAL(xa) .OR. x < MINVAL(xa)" errid%level = DANGER ENDIF RETURN ENDIF ! Find index ns of closest table entry. ns = IMINLOC(ABS(x-xa)) IF (xa(ns) > x) THEN IF (xa(ns) == xa(ns-1)) GOTO 10 a = (ya(ns) - ya(ns-1))/(xa(ns) - xa(ns-1)) y = ya(ns-1) + a*(x - xa(ns-1)) ELSE IF (xa(ns+1) == xa(ns)) GOTO 20 a = (ya(ns+1) - ya(ns))/(xa(ns+1) - xa(ns)) y = ya(ns) + a*(x - xa(ns)) ENDIF RETURN ! 10 CONTINUE IF (PRESENT(errid)) THEN errid%message = "xa(ns) == xa(ns-1)" errid%level = DANGER ENDIF RETURN ! 20 CONTINUE IF (PRESENT(errid)) THEN errid%message = "xa(ns+1) == xa(ns)" errid%level = DANGER ENDIF RETURN END SUBROUTINE INTERPOL_SP ! !------------------------------------------------------- ! SUBROUTINE INTERPOL_DP(xa,ya,x,y,errid) ! ! Given arrays xa and ya of length N, and given a value x, this ! routine returns a value y ! USE NFERR, ONLY : ERRSTAT, DANGER ! REAL(dp), INTENT(IN) :: xa(:), ya(:) REAL(dp), INTENT(IN) :: x REAL(dp), INTENT(OUT) :: y TYPE(ERRSTAT), OPTIONAL, INTENT(OUT) :: errid ! INTEGER(i4b) :: n, ns REAL(dp) :: a ! IF (PRESENT(errid)) THEN errid%routine_name = "INTERPOL" ENDIF n = SIZE(xa) IF (n > SIZE(ya) .OR. x > MAXVAL(xa) .OR. x < MINVAL(xa)) THEN IF (PRESENT(errid)) THEN errid%message = "n > SIZE(ya) .OR. x > MAXVAL(xa) .OR. x < MINVAL(xa)" errid%level = DANGER ENDIF RETURN ENDIF ! Find index ns of closest table entry. ns = IMINLOC(ABS(x-xa)) IF (xa(ns) > x) THEN IF (xa(ns) == xa(ns-1)) GOTO 10 a = (ya(ns) - ya(ns-1))/(xa(ns) - xa(ns-1)) y = ya(ns-1) + a*(x - xa(ns-1)) ELSE IF (xa(ns+1) == xa(ns)) GOTO 20 a = (ya(ns+1) - ya(ns))/(xa(ns+1) - xa(ns)) y = ya(ns) + a*(x - xa(ns)) ENDIF RETURN ! 10 CONTINUE IF (PRESENT(errid)) THEN errid%message = "xa(ns) == xa(ns-1)" errid%level = DANGER ENDIF RETURN ! 20 CONTINUE IF (PRESENT(errid)) THEN errid%message = "xa(ns+1) == xa(ns)" errid%level = DANGER ENDIF RETURN END SUBROUTINE INTERPOL_DP ! !------------------------------------------------------- ! FUNCTION REALLOCATE_VEC_STR(vec, n, strlen) RESULT(istat) INTEGER(i4b), INTENT(IN) :: strlen CHARACTER(LEN=strlen), POINTER :: vec(:) INTEGER(i4b), INTENT(IN) :: n INTEGER(i4b) :: istat ! istat = 0 IF (ASSOCIATED(vec)) THEN IF (SIZE(vec) /= n) THEN DEALLOCATE(vec) ALLOCATE(vec(n), STAT=istat) ENDIF ELSE ALLOCATE(vec(n), STAT=istat) ENDIF IF (istat /= 0) THEN vec => NULL() RETURN ENDIF vec(1:n) = '' RETURN END FUNCTION REALLOCATE_VEC_STR ! !------------------------------------------------------- ! FUNCTION REALLOCATE_VEC_I4B(vec, n) RESULT(istat) INTEGER(i4b), POINTER :: vec(:) INTEGER(i4b), INTENT(IN) :: n INTEGER(i4b) :: istat ! istat = 0 IF (ASSOCIATED(vec)) THEN IF (SIZE(vec) /= n) THEN DEALLOCATE(vec, STAT=istat) ALLOCATE(vec(n), STAT=istat) ENDIF ELSE ALLOCATE(vec(n), STAT=istat) ENDIF IF (istat /= 0) THEN vec => NULL() RETURN ENDIF vec(1:n) = 0 RETURN END FUNCTION REALLOCATE_VEC_I4B ! !------------------------------------------------------- ! FUNCTION REALLOCATE_VEC_SP(vec, n) RESULT(istat) REAL(sp), POINTER :: vec(:) INTEGER(i4b), INTENT(IN) :: n INTEGER(i4b) :: istat ! istat = 0 IF (ASSOCIATED(vec)) THEN IF (SIZE(vec) /= n) THEN DEALLOCATE(vec) ALLOCATE(vec(n), STAT=istat) ENDIF ELSE ALLOCATE(vec(n), STAT=istat) ENDIF IF (istat /= 0) THEN vec => NULL() RETURN ENDIF vec(1:n) = 0.0_sp RETURN END FUNCTION REALLOCATE_VEC_SP ! !------------------------------------------------------- ! FUNCTION REALLOCATE_VEC_DP(vec, n) RESULT(istat) REAL(dp), POINTER :: vec(:) INTEGER(i4b), INTENT(IN) :: n INTEGER(i4b) :: istat ! istat = 0 IF (ASSOCIATED(vec)) THEN IF (SIZE(vec) /= n) THEN DEALLOCATE(vec) ALLOCATE(vec(n), STAT=istat) ENDIF ELSE ALLOCATE(vec(n), STAT=istat) ENDIF IF (istat /= 0) THEN vec => NULL() RETURN ENDIF vec(1:n) = 0.0_dp RETURN END FUNCTION REALLOCATE_VEC_DP ! !------------------------------------------------------- ! FUNCTION REALLOCATE_MAT_I4B(mat, n, m) RESULT(istat) INTEGER(i4b), POINTER :: mat(:,:) INTEGER(i4b), INTENT(IN) :: n, m INTEGER(i4b) :: istat ! istat = 0 IF (ASSOCIATED(mat)) THEN IF (SIZE(mat, DIM=1) /= n .OR. SIZE(mat, DIM=2) /= m) THEN DEALLOCATE(mat) ALLOCATE(mat(n,m), STAT=istat) ENDIF ELSE ALLOCATE(mat(n,m), STAT=istat) ENDIF IF (istat /= 0) THEN mat => NULL() RETURN ENDIF mat(1:n, 1:m) = 0 RETURN END FUNCTION REALLOCATE_MAT_I4B ! !------------------------------------------------------- ! FUNCTION REALLOCATE_MAT_SP(mat, n, m) RESULT(istat) REAL(sp), POINTER :: mat(:,:) INTEGER(i4b), INTENT(IN) :: n, m INTEGER(i4b) :: istat ! istat = 0 IF (ASSOCIATED(mat)) THEN IF (SIZE(mat, DIM=1) /= n .OR. SIZE(mat, DIM=2) /= m) THEN DEALLOCATE(mat) ALLOCATE(mat(n,m), STAT=istat) ENDIF ELSE ALLOCATE(mat(n,m), STAT=istat) ENDIF IF (istat /= 0) THEN mat => NULL() RETURN ENDIF mat(1:n, 1:m) = 0.0_sp RETURN END FUNCTION REALLOCATE_MAT_SP ! !------------------------------------------------------- ! FUNCTION REALLOCATE_MAT_DP(mat, n, m) RESULT(istat) REAL(dp), POINTER :: mat(:, :) INTEGER(i4b), INTENT(IN) :: n, m INTEGER(i4b) :: istat ! istat = 0 IF (ASSOCIATED(mat)) THEN IF (SIZE(mat, DIM=1) /= n .OR. SIZE(mat, DIM=2) /= m) THEN DEALLOCATE(mat) ALLOCATE(mat(n,m), STAT=istat) ENDIF ELSE ALLOCATE(mat(n,m), STAT=istat) ENDIF IF (istat /= 0) THEN mat => NULL() RETURN ENDIF mat(1:n, 1:m) = 0.0_dp RETURN END FUNCTION REALLOCATE_MAT_DP ! !------------------------------------------------------- ! FUNCTION RESIZE_VEC_STR(vec, n, strlen) RESULT(istat) INTEGER(i4b), INTENT(IN) :: strlen CHARACTER(LEN=strlen), POINTER :: vec(:) INTEGER(i4b), INTENT(IN) :: n INTEGER(i4b) :: istat ! INTEGER(i4b) :: nold CHARACTER(LEN=strlen), ALLOCATABLE :: tmp(:) ! IF (n <= 0) THEN istat = 2 RETURN ENDIF ! IF (.NOT. ASSOCIATED(vec)) THEN ALLOCATE(vec(n), STAT=istat) RETURN ENDIF ! nold = SIZE(vec) IF (nold == 0) THEN istat = 1 RETURN ENDIF ! ALLOCATE(tmp(nold), STAT = istat) IF (istat /= 0) RETURN tmp(1:nold) = vec(1:nold) istat = REALLOCATE(vec, n, strlen) IF (istat /= 0) GOTO 10 IF (n > nold) THEN vec(1:nold) = tmp(1:nold) vec(nold+1:n) = '' ELSE vec(1:n) = tmp(1:n) ENDIF 10 CONTINUE DEALLOCATE(tmp) RETURN END FUNCTION RESIZE_VEC_STR ! !------------------------------------------------------- ! FUNCTION RESIZE_VEC_I4B(vec, n) RESULT(istat) INTEGER(i4b), POINTER :: vec(:) INTEGER(i4b), INTENT(IN) :: n INTEGER(i4b) :: istat ! INTEGER(i4b) :: nold INTEGER(i4b), ALLOCATABLE :: tmp(:) ! IF (n <= 0) THEN istat = 2 RETURN ENDIF ! IF (.NOT. ASSOCIATED(vec)) THEN istat = REALLOCATE(vec, n) RETURN ENDIF ! nold = SIZE(vec) IF (nold == 0) THEN istat = 1 RETURN ENDIF ! ALLOCATE(tmp(nold), STAT = istat) IF (istat /= 0) RETURN tmp(1:nold) = vec(1:nold) istat = REALLOCATE(vec, n) IF (istat /= 0) GOTO 10 IF (n > nold) THEN vec(1:nold) = tmp(1:nold) vec(nold+1:n) = 0 ELSE vec(1:n) = tmp(1:n) ENDIF 10 CONTINUE DEALLOCATE(tmp) RETURN END FUNCTION RESIZE_VEC_I4B ! !------------------------------------------------------- ! FUNCTION RESIZE_VEC_SP(vec, n) RESULT(istat) REAL(sp), POINTER :: vec(:) INTEGER(i4b), INTENT(IN) :: n INTEGER(i4b) :: istat ! INTEGER(i4b) :: nold REAL(sp), ALLOCATABLE :: tmp(:) ! IF (n <= 0) THEN istat = 2 RETURN ENDIF ! IF (.NOT. ASSOCIATED(vec)) THEN istat = REALLOCATE(vec, n) RETURN ENDIF ! nold = SIZE(vec) IF (nold == 0) THEN istat = 1 RETURN ENDIF ! ALLOCATE(tmp(nold), STAT = istat) IF (istat /= 0) RETURN tmp(1:nold) = vec(1:nold) istat = REALLOCATE(vec, n) IF (istat /= 0) GOTO 10 IF (n > nold) THEN vec(1:nold) = tmp(1:nold) vec(nold+1:n) = 0.0_sp ELSE vec(1:n) = tmp(1:n) ENDIF 10 CONTINUE DEALLOCATE(tmp) RETURN END FUNCTION RESIZE_VEC_SP ! !------------------------------------------------------- ! FUNCTION RESIZE_VEC_DP(vec, n) RESULT(istat) REAL(dp), POINTER :: vec(:) INTEGER(i4b), INTENT(IN) :: n INTEGER(i4b) :: istat ! INTEGER(i4b) :: nold REAL(dp), ALLOCATABLE :: tmp(:) ! IF (n <= 0) THEN istat = 2 RETURN ENDIF ! IF (.NOT. ASSOCIATED(vec)) THEN istat = REALLOCATE(vec, n) RETURN ENDIF ! nold = SIZE(vec) IF (nold == 0) THEN istat = 1 RETURN ENDIF ! ALLOCATE(tmp(nold), STAT = istat) IF (istat /= 0) RETURN tmp(1:nold) = vec(1:nold) istat = REALLOCATE(vec, n) IF (istat /= 0) GOTO 10 IF (n > nold) THEN vec(1:nold) = tmp(1:nold) vec(nold+1:n) = 0.0_dp ELSE vec(1:n) = tmp(1:n) ENDIF 10 CONTINUE DEALLOCATE(tmp) RETURN END FUNCTION RESIZE_VEC_DP ! !------------------------------------------------------- ! SUBROUTINE CLEAR_VEC_STR(vec) CHARACTER(LEN=*), POINTER :: vec(:) ! IF (ASSOCIATED(vec)) THEN DEALLOCATE(vec) vec => NULL() ENDIF RETURN END SUBROUTINE CLEAR_VEC_STR ! !------------------------------------------------------- ! SUBROUTINE CLEAR_VEC_I4B(vec) INTEGER(i4b), POINTER :: vec(:) ! IF (ASSOCIATED(vec)) THEN DEALLOCATE(vec) vec => NULL() ENDIF RETURN END SUBROUTINE CLEAR_VEC_I4B ! !------------------------------------------------------- ! SUBROUTINE CLEAR_VEC_SP(vec) REAL(sp), POINTER :: vec(:) ! IF (ASSOCIATED(vec)) THEN DEALLOCATE(vec) vec => NULL() ENDIF RETURN END SUBROUTINE CLEAR_VEC_SP ! !------------------------------------------------------- ! SUBROUTINE CLEAR_VEC_DP(vec) REAL(dp), POINTER :: vec(:) ! IF (ASSOCIATED(vec)) THEN DEALLOCATE(vec) vec => NULL() ENDIF RETURN END SUBROUTINE CLEAR_VEC_DP ! !------------------------------------------------------- ! SUBROUTINE CLEAR_MAT_I4B(mat) INTEGER(i4b), POINTER :: mat(:,:) ! IF (ASSOCIATED(mat)) THEN DEALLOCATE(mat) mat => NULL() ENDIF RETURN END SUBROUTINE CLEAR_MAT_I4B ! !------------------------------------------------------- ! SUBROUTINE CLEAR_MAT_SP(mat) REAL(sp), POINTER :: mat(:,:) ! IF (ASSOCIATED(mat)) THEN DEALLOCATE(mat) mat => NULL() ENDIF RETURN END SUBROUTINE CLEAR_MAT_SP ! !------------------------------------------------------- ! SUBROUTINE CLEAR_MAT_DP(mat) REAL(dp), POINTER :: mat(:,:) ! IF (ASSOCIATED(mat)) THEN DEALLOCATE(mat) mat => NULL() ENDIF RETURN END SUBROUTINE CLEAR_MAT_DP END MODULE NFUTIL