module io_dist 1,8 use shr_kind_mod, only : r8 => shr_kind_r8, r4 => shr_kind_r4 use decompmodule, only : decomptype use dynamics_vars, only : T_FVDYCORE_GRID use dyn_internal_state, only : get_dyn_state_grid use abortutils, only : endrun use cam_logfile, only : iulog #if ( defined SPMD ) use mod_comm, only: mp_sendirr, mp_recvirr, mp_sendirr_r4, mp_recvirr_r4, & mp_sendirr_i4, mp_recvirr_i4 use parutilitiesmodule, only: parpatterntype #endif implicit none private save public :: & fv_scatter_r4,& fv_gather_r4, & fv_read_r4, & fv_write_r4, & fv_scatter_r8,& fv_gather_r8, & fv_read_r8, & fv_write_r8, & fv_scatter_i4,& fv_gather_i4, & fv_read_i4 !==================================================================================== CONTAINS !==================================================================================== subroutine fv_scatter_r8(pattern_type, bufres, lenarr, arr),4 !----------------------------------------------------------------------- ! Wrapper routine to read real variable from restart binary file !----------------------------------------------------------------------- character(len=*), intent(in) :: pattern_type ! Type of comm pattern real(r8) bufres(*) ! Array to scatter integer, intent(in) :: lenarr ! Global size of array #if defined( SPMD ) real(r8), intent(out) :: arr(*) ! Array to be gathered #else real(r8), intent(out) :: arr(lenarr) ! Array (SMP-only) #endif !---------------------------Local variables----------------------------- #ifdef SPMD type (T_FVDYCORE_GRID), pointer :: grid ! grid information type (parpatterntype):: pattern ! Pattern descriptor #endif !----------------------------------------------------------------------- #ifdef SPMD grid => get_dyn_state_grid() pattern = get_pattern( grid, pattern_type, 'r8' ) ! ! Should check if this is a "scatter" pattern ! if (grid%iam .lt. grid%npes_xy) then CALL mp_sendirr(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) CALL mp_recvirr(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) endif ! grid%iam .lt. grid%npes_xy #else arr(1:lenarr) = bufres(1:lenarr) #endif return end subroutine fv_scatter_r8 !==================================================================================== subroutine fv_gather_r8( pattern_type, arr, lenarr, bufres),4 !----------------------------------------------------------------------- ! Wrapper routine to write restart binary file !----------------------------------------------------------------------- character(len=*), intent(in) :: pattern_type ! Type of comm pattern integer lenarr ! Global size of array #if defined( SPMD ) real(r8) arr(*) ! Array to be gathered #else real(r8) arr(lenarr) ! Array (SMP-only) #endif real(r8), intent(out) :: bufres(*) ! Gathered array !---------------------------Local variables----------------------------- integer ioerr ! errorcode #if ( defined SPMD ) type (T_FVDYCORE_GRID), pointer :: grid ! grid information type (parpatterntype):: pattern ! Pattern descriptor #endif !----------------------------------------------------------------------- #if ( defined SPMD ) ! ! Should check if this is a "gather" pattern ! grid => get_dyn_state_grid() pattern = get_pattern( grid, pattern_type, 'r8' ) if (grid%iam .lt. grid%npes_xy) then CALL mp_sendirr(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, arr, bufres, & modc=grid%modc_gather ) CALL mp_recvirr(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, arr, bufres, & modc=grid%modc_gather ) endif ! grid%iam .lt. grid%npes_xy #else bufres(1:lenarr) = arr(1:lenarr) #endif return end subroutine fv_gather_r8 !==================================================================================== subroutine fv_read_r8(iu, pattern_type, arr, lenarr),6 !----------------------------------------------------------------------- ! Wrapper routine to read real variable from restart binary file !----------------------------------------------------------------------- integer, intent(in) :: iu ! Logical unit character(len=*), intent(in) :: pattern_type ! Type of comm pattern integer, intent(in) :: lenarr ! Global size of array #if defined( SPMD ) real(r8), intent(out) :: arr(*) ! Array to be gathered #else real(r8), intent(out) :: arr(lenarr) ! Array (SMP-only) #endif !---------------------------Local variables----------------------------- integer ioerr ! errorcode #ifdef SPMD type (T_FVDYCORE_GRID), pointer :: grid ! grid information type (parpatterntype):: pattern ! Pattern descriptor real(r8), allocatable :: bufres(:) #endif !----------------------------------------------------------------------- #ifdef SPMD grid => get_dyn_state_grid() pattern = get_pattern( grid, pattern_type, 'r8' ) ! ! Should check if this is a "scatter" pattern ! if (grid%iam == 0) then allocate (bufres(lenarr)) read (iu,iostat=ioerr) bufres if (ioerr /= 0 ) then write(iulog,*) 'FV_READ_R8 ioerror ',ioerr,' on i/o unit = ',iu call endrun end if else allocate (bufres(1)) endif if (grid%iam .lt. grid%npes_xy) then CALL mp_sendirr(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) CALL mp_recvirr(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) endif ! grid%iam .lt. grid%npes_xy deallocate (bufres) #else read (iu,iostat=ioerr) arr if (ioerr /= 0 ) then write(iulog,*) 'FV_READ_R8 ioerror ',ioerr,' on i/o unit = ',iu call endrun end if #endif return end subroutine fv_read_r8 !==================================================================================== subroutine fv_write_r8(iu, pattern_type, arr, lenarr),6 !----------------------------------------------------------------------- ! Wrapper routine to write restart binary file !----------------------------------------------------------------------- integer, intent(in) :: iu ! Logical unit character(len=*), intent(in) :: pattern_type ! Type of comm pattern integer, intent(in) :: lenarr ! Global length of array #if defined( SPMD ) real(r8) arr(*) ! Array to be gathered #else real(r8) arr(lenarr) ! Array (SMP-only) #endif !---------------------------Local variables----------------------------- integer ioerr ! errorcode #if ( defined SPMD ) type (T_FVDYCORE_GRID), pointer :: grid ! grid information type (parpatterntype):: pattern ! Pattern descriptor real(r8), allocatable :: bufres(:) #endif !----------------------------------------------------------------------- #if ( defined SPMD ) ! ! Should check if this is a "gather" pattern ! grid => get_dyn_state_grid() pattern = get_pattern( grid, pattern_type, 'r8' ) if ( grid%iam == 0 ) then allocate( bufres(lenarr) ) else allocate( bufres(1) ) endif if (grid%iam .lt. grid%npes_xy) then CALL mp_sendirr(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, arr, bufres, & modc=grid%modc_gather ) CALL mp_recvirr(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, arr, bufres, & modc=grid%modc_gather ) endif ! grid%iam .lt. grid%npes_xy if (grid%iam == 0) then write (iu,iostat=ioerr) bufres if (ioerr /= 0 ) then write(iulog,*) 'FV_WRITE_R8 ioerror ',ioerr,' on i/o unit = ',iu call endrun ('FV_WRITE_R8') end if endif deallocate( bufres ) #else write (iu,iostat=ioerr) arr if (ioerr /= 0 ) then write(iulog,*) 'fv_write_r8 ioerror ',ioerr,' on i/o unit = ',iu call endrun ('FV_WRITE_R8') end if #endif return end subroutine fv_write_r8 !==================================================================================== subroutine fv_scatter_r4(pattern_type, bufres, lenarr, arr),4 !----------------------------------------------------------------------- ! Wrapper routine to read real variable from restart binary file !----------------------------------------------------------------------- character(len=*), intent(in) :: pattern_type ! Type of comm pattern real(r4) bufres(*) ! Array to scatter integer, intent(in) :: lenarr ! Global size of array #if defined( SPMD ) real(r4), intent(out) :: arr(*) ! Array to be gathered #else real(r4), intent(out) :: arr(lenarr) ! Array (SMP-only) #endif !---------------------------Local variables----------------------------- #ifdef SPMD type (T_FVDYCORE_GRID), pointer :: grid ! grid information type (parpatterntype):: pattern ! Pattern descriptor #endif !----------------------------------------------------------------------- #ifdef SPMD grid => get_dyn_state_grid() pattern = get_pattern( grid, pattern_type, 'r4' ) ! ! Should check if this is a "scatter" pattern ! if (grid%iam .lt. grid%npes_xy) then CALL mp_sendirr_r4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) CALL mp_recvirr_r4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) endif ! grid%iam .lt. grid%npes_xy #else arr(1:lenarr) = bufres(1:lenarr) #endif return end subroutine fv_scatter_r4 !==================================================================================== subroutine fv_gather_r4(pattern_type, arr, lenarr, bufres),4 !----------------------------------------------------------------------- ! Wrapper routine to write restart binary file !----------------------------------------------------------------------- character(len=*), intent(in) :: pattern_type ! Type of comm pattern integer lenarr ! Global size of array #if defined( SPMD ) real(r4) arr(*) ! Array to be gathered #else real(r4) arr(lenarr) ! Array (SMP-only) #endif real(r4), intent(out) :: bufres(*) ! Gathered array !---------------------------Local variables----------------------------- integer ioerr ! errorcode #if ( defined SPMD ) type (T_FVDYCORE_GRID), pointer :: grid ! grid information type (parpatterntype):: pattern ! Pattern descriptor #endif !----------------------------------------------------------------------- #if ( defined SPMD ) ! ! Should check if this is a "gather" pattern ! grid => get_dyn_state_grid() pattern = get_pattern( grid, pattern_type, 'r4' ) if (grid%iam .lt. grid%npes_xy) then CALL mp_sendirr_r4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, arr, bufres, & modc=grid%modc_gather ) CALL mp_recvirr_r4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, arr, bufres, & modc=grid%modc_gather ) endif ! grid%iam .lt. grid%npes_xy #else bufres(1:lenarr) = arr(1:lenarr) #endif return end subroutine fv_gather_r4 !==================================================================================== subroutine fv_read_r4(iu, pattern_type, arr, lenarr),6 !----------------------------------------------------------------------- ! Wrapper routine to read real variable from restart binary file !----------------------------------------------------------------------- integer, intent(in) :: iu ! Logical unit character(len=*), intent(in) :: pattern_type ! Type of comm pattern integer, intent(in) :: lenarr ! Global size of array #if defined( SPMD ) real(r4), intent(out) :: arr(*) ! Array to be gathered #else real(r4), intent(out) :: arr(lenarr) ! Array (SMP-only) #endif !---------------------------Local variables----------------------------- integer ioerr ! errorcode #ifdef SPMD type (T_FVDYCORE_GRID), pointer :: grid ! grid information type (parpatterntype):: pattern ! Pattern descriptor real(r4), allocatable :: bufres(:) #endif !----------------------------------------------------------------------- #ifdef SPMD grid => get_dyn_state_grid() pattern = get_pattern( grid, pattern_type, 'r4' ) ! ! Should check if this is a "scatter" pattern ! if (grid%iam == 0) then allocate (bufres(lenarr)) read (iu,iostat=ioerr) bufres if (ioerr /= 0 ) then write(iulog,*) 'FV_READ_R4 ioerror ',ioerr,' on i/o unit = ',iu call endrun end if else allocate (bufres(1)) endif if (grid%iam .lt. grid%npes_xy) then CALL mp_sendirr_r4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) CALL mp_recvirr_r4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) endif ! grid%iam .lt. grid%npes_xy deallocate (bufres) #else read (iu,iostat=ioerr) arr if (ioerr /= 0 ) then write(iulog,*) 'FV_READ_R4 ioerror ',ioerr,' on i/o unit = ',iu call endrun end if #endif return end subroutine fv_read_r4 !==================================================================================== subroutine fv_write_r4(iu, pattern_type, arr, lenarr),6 !----------------------------------------------------------------------- ! Wrapper routine to write restart binary file !----------------------------------------------------------------------- integer, intent(in) :: iu ! Logical unit character(len=*), intent(in) :: pattern_type ! Type of comm pattern integer, intent(in) :: lenarr ! Global length of array #if defined( SPMD ) real(r4) arr(*) ! Array to be gathered #else real(r4) arr(lenarr) ! Array (SMP-only) #endif !---------------------------Local variables----------------------------- integer ioerr ! errorcode #if ( defined SPMD ) type (T_FVDYCORE_GRID), pointer :: grid ! grid information type (parpatterntype):: pattern ! Pattern descriptor real(r4), allocatable :: bufres(:) #endif !----------------------------------------------------------------------- #if ( defined SPMD ) ! ! Should check if this is a "gather" pattern ! grid => get_dyn_state_grid() pattern = get_pattern( grid, pattern_type, 'r4' ) if ( grid%iam == 0 ) then allocate( bufres(lenarr) ) else allocate( bufres(1) ) endif if (grid%iam .lt. grid%npes_xy) then CALL mp_sendirr_r4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, arr, bufres, & modc=grid%modc_gather ) CALL mp_recvirr_r4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, arr, bufres, & modc=grid%modc_gather ) endif ! grid%iam .lt. grid%npes_xy if (grid%iam == 0) then write (iu,iostat=ioerr) bufres if (ioerr /= 0 ) then write(iulog,*) 'FV_WRITE_R4 ioerror ',ioerr,' on i/o unit = ',iu call endrun ('FV_WRITE_R4') end if endif deallocate( bufres ) #else write (iu,iostat=ioerr) arr if (ioerr /= 0 ) then write(iulog,*) 'fv_write_r4 ioerror ',ioerr,' on i/o unit = ',iu call endrun ('FV_WRITE_R4') end if #endif return end subroutine fv_write_r4 !==================================================================================== subroutine fv_scatter_i4(pattern_type, bufres, lenarr, arr),4 !----------------------------------------------------------------------- ! Wrapper routine to read real variable from restart binary file !----------------------------------------------------------------------- character(len=*), intent(in) :: pattern_type ! Type of comm pattern integer bufres(*) ! Array to scatter integer, intent(in) :: lenarr ! Global size of array #if defined( SPMD ) integer, intent(out) :: arr(*) ! Array to be gathered #else integer, intent(out) :: arr(lenarr) ! Array (SMP-only) #endif !---------------------------Local variables----------------------------- #ifdef SPMD type (T_FVDYCORE_GRID), pointer :: grid ! grid information type (parpatterntype):: pattern ! Pattern descriptor #endif !----------------------------------------------------------------------- #ifdef SPMD grid => get_dyn_state_grid() pattern = get_pattern( grid, pattern_type, 'i4' ) ! ! Should check if this is a "scatter" pattern ! if (grid%iam .lt. grid%npes_xy) then CALL mp_sendirr_i4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) CALL mp_recvirr_i4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) endif ! grid%iam .lt. grid%npes_xy #else arr(1:lenarr) = bufres(1:lenarr) #endif return end subroutine fv_scatter_i4 !==================================================================================== subroutine fv_gather_i4(pattern_type, arr, lenarr, bufres),4 !----------------------------------------------------------------------- ! Wrapper routine to write restart binary file !----------------------------------------------------------------------- character(len=*), intent(in) :: pattern_type ! Type of comm pattern integer lenarr ! Global size of array #if defined( SPMD ) integer arr(*) ! Array to be gathered #else integer arr(lenarr) ! Array (SMP-only) #endif integer, intent(out) :: bufres(*) ! Gathered array !---------------------------Local variables----------------------------- integer ioerr ! errorcode #if ( defined SPMD ) type (T_FVDYCORE_GRID), pointer :: grid ! grid information type (parpatterntype):: pattern ! Pattern descriptor #endif !----------------------------------------------------------------------- #if ( defined SPMD ) ! ! Should check if this is a "gather" pattern ! grid => get_dyn_state_grid() pattern = get_pattern( grid, pattern_type, 'i4' ) if (grid%iam .lt. grid%npes_xy) then CALL mp_sendirr_i4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, arr, bufres, & modc=grid%modc_gather ) CALL mp_recvirr_i4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, arr, bufres, & modc=grid%modc_gather ) endif ! grid%iam .lt. grid%npes_xy #else bufres(1:lenarr) = arr(1:lenarr) #endif return end subroutine fv_gather_i4 !==================================================================================== subroutine fv_read_i4(iu, pattern_type, arr, lenarr),6 !----------------------------------------------------------------------- ! Wrapper routine to read real variable from restart binary file !----------------------------------------------------------------------- integer, intent(in) :: iu ! Logical unit character(len=*), intent(in) :: pattern_type ! Type of comm pattern integer, intent(in) :: lenarr ! Global size of array #if defined( SPMD ) integer, intent(out) :: arr(*) ! Array to be gathered #else integer, intent(out) :: arr(lenarr) ! Array (SMP-only) #endif !---------------------------Local variables----------------------------- integer ioerr ! errorcode #ifdef SPMD type (T_FVDYCORE_GRID), pointer :: grid ! grid information type (parpatterntype):: pattern ! Pattern descriptor integer, allocatable :: bufres(:) #endif !----------------------------------------------------------------------- #ifdef SPMD grid => get_dyn_state_grid() pattern = get_pattern( grid, pattern_type, 'i4' ) ! ! Should check if this is a "scatter" pattern ! if (grid%iam == 0) then allocate (bufres(lenarr)) read (iu,iostat=ioerr) bufres if (ioerr /= 0 ) then write(iulog,*) 'FV_READ_I4 ioerror ',ioerr,' on i/o unit = ',iu call endrun end if else allocate (bufres(1)) endif if (grid%iam .lt. grid%npes_xy) then CALL mp_sendirr_i4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) CALL mp_recvirr_i4(pattern%Comm, pattern%SendDesc, pattern%RecvDesc, bufres, arr, & modc=grid%modc_scatter ) endif ! grid%iam .lt. grid%npes_xy deallocate (bufres) #else read (iu,iostat=ioerr) arr if (ioerr /= 0 ) then write(iulog,*) 'FV_READ_I4 ioerror ',ioerr,' on i/o unit = ',iu call endrun end if #endif return end subroutine fv_read_i4 !==================================================================================== function get_decomp( grid, type ) 7,10 ! this utility function probably belongs where the decomptype objects are stored type (T_FVDYCORE_GRID), pointer :: grid ! grid information character(len=*), intent(in) :: type type (decomptype) :: get_decomp ! Decomposition descriptor select case (type) case ('2d') get_decomp = grid%strip2d case ('3dxzy') get_decomp = grid%strip3dxzy case ('3dxzyp') get_decomp = grid%strip3dxzyp case ('3dxyz') get_decomp = grid%strip3dxyz case default write(iulog,*)'get_decomp: invalid number decomposition type=', type call endrun () end select end function get_decomp !==================================================================================== #if defined( SPMD ) function get_pattern( grid, type, data_type ) 11,7 ! this utility function probably belongs where the decomptype objects are stored type (T_FVDYCORE_GRID) :: grid ! grid information character(len=*), intent(in) :: type character(len=*), intent(in) :: data_type type (ParPatternType) :: get_pattern ! grid information select case (type) case ('s_2dxy') select case (data_type) case ('r8') get_pattern = grid%s_2dxy_r8 case ('r4') get_pattern = grid%s_2dxy_r4 case ('i4') get_pattern = grid%s_2dxy_i4 case default write(iulog,*)'get_pattern: ', data_type, ' not supported in decomposition ', type call endrun () end select case ('s_3dxyz') select case (data_type) case ('r8') get_pattern = grid%s_3dxyz_r8 case ('r4') get_pattern = grid%s_3dxyz_r4 case default write(iulog,*)'get_pattern: ', data_type, ' not supported in decomposition ', type call endrun () end select case ('s_3dxyzp') select case (data_type) case ('r8') get_pattern = grid%s_3dxyzp_r8 case ('r4') get_pattern = grid%s_3dxyzp_r4 case default write(iulog,*)'get_pattern: ', data_type, ' not supported in decomposition ', type call endrun () end select case ('g_2dxy') select case (data_type) case ('r8') get_pattern = grid%g_2dxy_r8 case ('r4') get_pattern = grid%g_2dxy_r4 case ('i4') get_pattern = grid%g_2dxy_i4 case default write(iulog,*)'get_pattern: ', data_type, ' not supported in decomposition ', type call endrun () end select case ('g_3dxyz') select case (data_type) case ('r8') get_pattern = grid%g_3dxyz_r8 case ('r4') get_pattern = grid%g_3dxyz_r4 case default write(iulog,*)'get_pattern: ', data_type, ' not supported in decomposition ', type call endrun () end select case ('g_3dxyzp') select case (data_type) case ('r8') get_pattern = grid%g_3dxyzp_r8 case ('r4') get_pattern = grid%g_3dxyzp_r4 case default write(iulog,*)'get_pattern: ', data_type, ' not supported in decomposition ', type call endrun () end select case default write(iulog,*)'get_pattern: invalid number decomposition type=', type call endrun () end select end function get_pattern #endif end module io_dist