! !################################################################## !################################################################## !###### ###### !###### SUBROUTINEs for array allocation/deallocation ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! !----------------------------------------------------------------------- ! ! PURPOSE: ! Suboroutines to allocate and deallocate arrays using pointer. ! They also keep track of total memory usage. !----------------------------------------------------------------------- ! ! AUTHOR: Ming Xue ! 07/14/99 ! ! MODIFICATION HISTORY: ! ! 2000/04/17 (Gene Bassett) ! Converted to F90 fixed format. ! !----------------------------------------------------------------------- !----------------------------------------------------------------------- ! Allocate real arrays !----------------------------------------------------------------------- SUBROUTINE alloc_real_1d_array(array,variable,nx),2 IMPLICIT NONE REAL, POINTER :: array(:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx INTEGER :: istatus ALLOCATE(array(nx),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = 0. CALL f_memory_use(nx) RETURN END SUBROUTINE alloc_real_1d_array SUBROUTINE alloc_real_2d_array(array,variable,nx,ny),2 IMPLICIT NONE REAL, POINTER :: array(:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx,ny INTEGER :: istatus ALLOCATE(array(nx,ny),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = 0. CALL f_memory_use(nx*ny) RETURN END SUBROUTINE alloc_real_2d_array SUBROUTINE alloc_real_3d_array(array,variable,nx,ny,nz),2 REAL, POINTER :: array(:,:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx,ny,nz INTEGER :: istatus ALLOCATE(array(nx,ny,nz),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = 0. CALL f_memory_use(nx*ny*nz) RETURN END SUBROUTINE alloc_real_3d_array SUBROUTINE alloc_real_4d_array(array,variable,nx,ny,nz,nt),2 IMPLICIT NONE REAL, POINTER :: array(:,:,:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx,ny,nz,nt INTEGER :: istatus ALLOCATE(array(nx,ny,nz,nt),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = 0. CALL f_memory_use(nx*ny*nz*nt) RETURN END SUBROUTINE alloc_real_4d_array !----------------------------------------------------------------------- ! Allocate integer arrays !----------------------------------------------------------------------- SUBROUTINE alloc_int_1d_array(array,variable,nx),2 IMPLICIT NONE INTEGER, POINTER :: array(:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx INTEGER :: istatus ALLOCATE(array(nx),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = 0 CALL f_memory_use(nx) RETURN END SUBROUTINE alloc_int_1d_array SUBROUTINE alloc_int_2d_array(array,variable,nx,ny),2 IMPLICIT NONE INTEGER, POINTER :: array(:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx,ny INTEGER :: istatus ALLOCATE(array(nx,ny),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = 0 CALL f_memory_use(nx*ny) RETURN END SUBROUTINE alloc_int_2d_array SUBROUTINE alloc_int_3d_array(array,variable,nx,ny,nz),2 INTEGER, POINTER :: array(:,:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx,ny,nz INTEGER :: istatus ALLOCATE(array(nx,ny,nz),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = 0 CALL f_memory_use(nx*ny*nz) RETURN END SUBROUTINE alloc_int_3d_array SUBROUTINE alloc_int_4d_array(array,variable,nx,ny,nz,nt),2 IMPLICIT NONE INTEGER, POINTER :: array(:,:,:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx,ny,nz,nt INTEGER :: istatus IF (ASSOCIATED(array)) THEN WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Warning: Array ',variable,' had already been allocated.', & 'Allocating it again will distroy its existing content.' ENDIF ALLOCATE(array(nx,ny,nz,nt),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = 0 CALL f_memory_use(nx*ny*nz*nt) RETURN END SUBROUTINE alloc_int_4d_array SUBROUTINE alloc_logic_2d_array(array,variable,nx,ny),2 IMPLICIT NONE LOGICAL, POINTER :: array(:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx,ny INTEGER :: istatus ALLOCATE(array(nx,ny),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = .false. CALL f_memory_use(nx*ny) RETURN END SUBROUTINE alloc_logic_2d_array !----------------------------------------------------------------------- ! Allocate misc arrays !----------------------------------------------------------------------- SUBROUTINE alloc_int2_1d_array(array,variable,nx),2 INTEGER(kind=2), POINTER :: array(:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx INTEGER :: istatus ALLOCATE(array(nx),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = 0_2 CALL f_memory_use(nx/2) RETURN END SUBROUTINE alloc_int2_1d_array SUBROUTINE alloc_int2_2d_array(array,variable,nx,ny),2 INTEGER(kind=2), POINTER :: array(:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx,ny INTEGER :: istatus ALLOCATE(array(nx,ny),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = 0_2 CALL f_memory_use((nx*ny)/2) RETURN END SUBROUTINE alloc_int2_2d_array SUBROUTINE alloc_int2_3d_array(array,variable,nx,ny,nz),2 INTEGER(kind=2), POINTER :: array(:,:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx,ny,nz INTEGER :: istatus ALLOCATE(array(nx,ny,nz),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) array = 0_2 CALL f_memory_use((nx*ny*nz)/2) RETURN END SUBROUTINE alloc_int2_3d_array SUBROUTINE alloc_char_1d_array(array,variable,nx),2 CHARACTER, POINTER :: array(:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER, INTENT(IN) :: nx INTEGER :: istatus ALLOCATE(array(nx),STAT=istatus) IF(istatus /= 0) CALL alloc_failed(istatus,variable) CALL f_memory_use(nx) RETURN END SUBROUTINE alloc_char_1d_array !----------------------------------------------------------------------- ! Deallocate real arrays !----------------------------------------------------------------------- SUBROUTINE dealloc_real_1d_array(array,variable),2 IMPLICIT NONE REAL, POINTER :: array(:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_real_1d_array SUBROUTINE dealloc_real_2d_array(array,variable),2 IMPLICIT NONE REAL, POINTER :: array(:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_real_2d_array SUBROUTINE dealloc_real_3d_array(array,variable),2 REAL, POINTER :: array(:,:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_real_3d_array SUBROUTINE dealloc_real_4d_array(array,variable),2 IMPLICIT NONE REAL, POINTER :: array(:,:,:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_real_4d_array !----------------------------------------------------------------------- ! Deallocate integer arrays !----------------------------------------------------------------------- SUBROUTINE dealloc_int_1d_array(array,variable),2 IMPLICIT NONE INTEGER, POINTER :: array(:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_int_1d_array SUBROUTINE dealloc_int_2d_array(array,variable),2 IMPLICIT NONE INTEGER, POINTER :: array(:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_int_2d_array SUBROUTINE dealloc_int_3d_array(array,variable),2 INTEGER, POINTER :: array(:,:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_int_3d_array SUBROUTINE dealloc_int_4d_array(array,variable),2 IMPLICIT NONE INTEGER, POINTER :: array(:,:,:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_int_4d_array !----------------------------------------------------------------------- ! Deallocate misc arrays !----------------------------------------------------------------------- SUBROUTINE dealloc_logic_2d_array(array,variable),2 IMPLICIT NONE LOGICAL, POINTER :: array(:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_logic_2d_array SUBROUTINE dealloc_int2_1d_array(array,variable),2 INTEGER(kind=2), POINTER :: array(:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size/2) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_int2_1d_array SUBROUTINE dealloc_int2_2d_array(array,variable),2 INTEGER(kind=2), POINTER :: array(:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size/2) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_int2_2d_array SUBROUTINE dealloc_int2_3d_array(array,variable),2 INTEGER(kind=2), POINTER :: array(:,:,:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size/2) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_int2_3d_array SUBROUTINE dealloc_char_1d_array(array,variable),2 CHARACTER, POINTER :: array(:) CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF (ASSOCIATED(array)) THEN a_size = size(array) DEALLOCATE(array,STAT=istatus) IF(istatus /= 0) THEN CALL dealloc_failed(istatus,variable) ELSE CALL f_memory_use(-a_size) ENDIF ELSE WRITE(6,'(/1x,a,a,a,/1x,a/)') & 'Pointer array ', variable, & ' is not currently allocated, therefore', & 'it could not be deallocated. Program will continue.' ENDIF RETURN END SUBROUTINE dealloc_char_1d_array !----------------------------------------------------------------------- ! Array allocation status reporting !----------------------------------------------------------------------- SUBROUTINE alloc_failed(istatus,variable) 14,1 IMPLICIT NONE INTEGER, INTENT(IN) :: istatus CHARACTER(len=*), INTENT(IN) :: variable WRITE(6,'(/1x,a,a,/1x,a,i2,a/)') & 'Program failed when allocating memory space for array ', & variable, & 'Program stopped. Status of allocation is ', istatus,'.' CALL arpsstop('arpsstop called from alloc_failed',1) END SUBROUTINE alloc_failed SUBROUTINE dealloc_failed(istatus,variable) 14 IMPLICIT NONE INTEGER, INTENT(IN) :: istatus CHARACTER(len=*), INTENT(IN) :: variable WRITE(6,'(/1x,a,a,/1x,a,i2,a/)') & 'Program failed when deallocating memory space for array ', & variable, & 'Program will continue. Status of allocation is ', istatus,'.' RETURN END SUBROUTINE dealloc_failed SUBROUTINE Alloc_status_accounting(istatus,a_size,variable) 162,3 CHARACTER(len=*), INTENT(IN) :: variable INTEGER :: istatus, a_size IF(istatus /= 0) THEN IF(a_size.ge.0) then CALL alloc_failed(istatus,variable) ELSE CALL dealloc_failed(istatus,variable) ENDIF ELSE CALL f_memory_use(a_size) ENDIF RETURN END SUBROUTINE Alloc_status_accounting ! !################################################################## !################################################################## !###### ###### !###### MODULE memory_accounting ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! MODULE memory_accounting !----------------------------------------------------------------------- ! ! PURPOSE: ! Module for saving and passing memory usage information. ! !----------------------------------------------------------------------- ! ! AUTHOR: Ming Xue ! 07/14/99 ! ! MODIFICATION HISTORY: ! ! 2000/04/17 (Gene Bassett) ! Converted to F90 fixed format. !----------------------------------------------------------------------- IMPLICIT NONE SAVE REAL :: current_memory_use = 0.0 REAL :: max_memory_use = 0.0 END MODULE memory_accounting !################################################################## !################################################################## !###### ###### !###### SUBROUTINE f_memory_use ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## SUBROUTINE f_memory_use( n_word ) !----------------------------------------------------------------------- ! ! PURPOSE: ! Subroutine for performing memory accounting ! !----------------------------------------------------------------------- ! ! AUTHOR: Ming Xue ! 7/14/99 ! ! MODIFICATION HISTORY: ! ! 2000/04/17 (Gene Bassett) ! Converted to F90 fixed format. ! !----------------------------------------------------------------------- IMPLICIT NONE INCLUDE 'alloc.inc' INTEGER, INTENT(IN) :: n_word ! Number of words to be allocated (positive) ! or deallocated (nagative). current_memory_use = current_memory_use + n_word max_memory_use = max(max_memory_use,current_memory_use) END SUBROUTINE f_memory_use !wdt update !################################################################## !################################################################## !###### ###### !###### SUBROUTINE check_alloc_status ###### !###### ###### !################################################################## !################################################################## SUBROUTINE check_alloc_status( status, message ) 348 !----------------------------------------------------------------------- ! ! PURPOSE: Check status of array allocation. ! !----------------------------------------------------------------------- ! ! AUTHOR: Richard Carpenter, 2001/12/07 ! ! MODIFICATION HISTORY: ! !----------------------------------------------------------------------- IMPLICIT NONE INTEGER, INTENT(IN) :: status CHARACTER*(*), INTENT(IN) :: message LOGICAL :: cont = .FALSE. IF (status == 0) THEN !WRITE(*,'(A,I2,8A)') 'check_alloc_status: status=', status, & ! ' [', TRIM(message), ']' ELSE WRITE(*,'(A,I2,8A)') 'check_alloc_status: ERROR: status=', status, & ' [', TRIM(message), ']' END IF IF (status /= 0) THEN WRITE(*,'(8A)') & 'check_alloc_status: FATAL: Unable to allocate array. Program ends' STOP END IF END SUBROUTINE check_alloc_status