!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
module io_pio 1,6
!BOP
! !MODULE: io_pio
! !DESCRIPTION:
! Interfaces for pio initialization
!
! !REVISION HISTORY:
! SVN:$ID:
!
! !USES:
use kinds_mod
use broadcast
use communicate
use exit_mod
use POP_IOUnitsMod
use io_types
use pio
implicit none
private
save
!PUBLIC MEMBER FUNCTIONS:
public io_pio_init
public :: io_pio_initdecomp
!PUBLIC DATA MEMBERS
!EOP
!BOC
!-----------------------------------------------------------------------
!
! local variables
!
!-----------------------------------------------------------------------
integer, private :: io_pio_stride, io_pio_num_iotasks, &
io_pio_root, io_pio_type
type(iosystem_desc_t), public :: io_pio_subsystem
integer (i4), parameter :: nmax = 10
type ptr_ioDesc_int_type
type (IO_desc_t), pointer :: ioDesc(:)
end type ptr_ioDesc_int_type
type (ptr_ioDesc_int_type), dimension(:), allocatable :: ptr_ioDesc_i
type ptr_ioDesc_real_type
type (IO_desc_t), pointer :: ioDesc(:)
end type ptr_ioDesc_real_type
type (ptr_ioDesc_real_type), dimension(:), allocatable :: ptr_ioDesc_r
type ptr_ioDesc_double_type
type (IO_desc_t), pointer :: ioDesc(:)
end type ptr_ioDesc_double_type
type (ptr_ioDesc_double_type), dimension(:), allocatable :: ptr_ioDesc_d
integer(i4), parameter :: iunset = -999
integer(i4), dimension(nmax) :: nsize3d_i = iunset
integer(i4), dimension(nmax) :: nsize3d_r = iunset
integer(i4), dimension(nmax) :: nsize3d_d = iunset
integer(i4), dimension(nmax) :: ksize3d_i = iunset
integer(i4), dimension(nmax) :: ksize3d_r = iunset
integer(i4), dimension(nmax) :: ksize3d_d = iunset
!EOC
!***********************************************************************
contains
!***********************************************************************
!EOP
! !IROUTINE: io_pio_init - initialize io for input or output
! !INTERFACE:
subroutine io_pio_init(mode, filename, File, clobber, cdf64) 2,9
!
! !DESCRIPTION:
! Read the pio_inparm namelist and initialize the io subsystem
!
! !REVISION HISTORY:
! 2009-Feb-17 - J. Edwards - initial version
!
! !INPUT/OUTPUT PARAMETERS:
!
implicit none
character(len=*) , intent(in) :: mode
character(len=*) , intent(in) :: filename
type(file_desc_t) , intent(inout) :: File
logical,optional , intent(in) :: clobber
logical,optional , intent(in) :: cdf64
!
!EOP
!BOC
!-----------------------------------------------------------------------
!
! local variables
!
!-----------------------------------------------------------------------
integer (int_kind) :: &
nml_error ! namelist read error flag
character(len=16) :: io_pio_type_name
logical :: exists
logical :: lclobber
logical :: lcdf64
integer :: status
integer :: nmode
logical, save :: first_call = .true.
character(*),parameter :: subName = '(io_pio_init) '
! Input namelist
namelist /io_pio_nml/ &
io_pio_num_iotasks, &
io_pio_stride, &
io_pio_type_name
!-----------------------------------------------------------------------
!
! read and define namelist inputs
!
!-----------------------------------------------------------------------
if (first_call) then
! io_pio_root must be set to master_task since since currrently non-standard
! variables are only written from master_task
io_pio_root = master_task
io_pio_num_iotasks = -1 ! set based on io_stride value when initialized < 0
io_pio_stride = -1 ! set based on num_iotasks value when initialized < 0
io_pio_type_name = 'netcdf'
if (my_task == master_task) then
#ifdef CCSMCOUPLED
call get_unit
(nml_in)
#endif
open (nml_in, file=nml_filename, status='old',iostat=nml_error)
if (nml_error /= 0) then
nml_error = -1
else
nml_error = 1
endif
do while (nml_error > 0)
read(nml_in, nml=io_pio_nml,iostat=nml_error)
end do
if (nml_error == 0) close(nml_in)
call io_pio_set_params
(io_pio_type_name)
write(stdout,*) 'POP2 PIO parameter settings...'
write(stdout,*) ' io_pio_stride = ',io_pio_stride
write(stdout,*) ' io_pio_num_iotasks = ',io_pio_num_iotasks
write(stdout,*) ' io pio_type_name = ',io_pio_type_name
endif
call broadcast_scalar
(nml_error, master_task)
if (nml_error /= 0) then
call exit_POP
(sigAbort,' error reading pio_nml')
endif
call broadcast_scalar
(io_pio_num_iotasks, master_task)
call broadcast_scalar
(io_pio_root, master_task)
call broadcast_scalar
(io_pio_stride, master_task)
call broadcast_scalar
(io_pio_type, master_task)
call pio_init(my_task, MPI_COMM_OCN, io_pio_num_iotasks, &
0, io_pio_stride, PIO_REARR_BOX, io_pio_subsystem, base=io_pio_root)
first_call = .false.
end if
if (trim(mode) == 'write') then
lclobber = .false.
if (present(clobber)) lclobber=clobber
lcdf64 = .false.
if (present(cdf64)) lcdf64=cdf64
if (File%fh<0) then
! filename not open
inquire(file=trim(filename),exist=exists)
if (exists) then
if (lclobber) then
nmode = pio_clobber
if (lcdf64) nmode = ior(nmode,PIO_64BIT_OFFSET)
status = pio_createfile(io_pio_subsystem, File, io_pio_type, trim(filename), nmode)
if (my_task == master_task) then
write(stdout,*) subname,' create file ',trim(filename)
end if
else
status = pio_openfile(io_pio_subsystem, File, io_pio_type, trim(filename), pio_write)
if (my_task == master_task) then
write(stdout,*) subname,' open file ',trim(filename)
end if
endif
else
nmode = pio_noclobber
if (lcdf64) nmode = ior(nmode,PIO_64BIT_OFFSET)
status = pio_createfile(io_pio_subsystem, File, io_pio_type, trim(filename), nmode)
if (my_task == master_task) then
write(stdout,*) subname,' create file ',trim(filename)
end if
endif
else
! filename is already open, just return
endif
end if
if (trim(mode) == 'read') then
inquire(file=trim(filename),exist=exists)
if (exists) then
status = pio_openfile(io_pio_subsystem, File, io_pio_type, trim(filename), pio_nowrite)
else
if(my_task==master_task) then
write(stdout,*) 'io_pio_ropen ERROR: file invalid ',trim(filename)
end if
call exit_POP
(sigAbort, 'aborting in io_pio_ropen with invalid file')
endif
end if
end subroutine io_pio_init
!===============================================================================
!BOP
!
! !IROUTINE: io_pio_set_params - set pio parameters
!
! !INTERFACE:
subroutine io_pio_set_params(io_pio_type_name) 1,3
!
! !DESCRIPTION:
! Set the pio parameters for the subsystem
!
! !USES:
!
use shr_string_mod
,only: shr_string_toUpper
!
! !INPUT/OUTPUT PARAMETERS:
!
implicit none
character(len=*), intent(in) :: io_pio_type_name
!
!EOP
!
character(len=16) :: tmpname
integer (kind=int_kind) :: npes
tmpname = shr_string_toupper
(io_pio_type_name)
if (trim(tmpname) == 'NETCDF') then
io_pio_type = iotype_netcdf
else if (trim(tmpname) == 'PNETCDF') then
io_pio_type = iotype_pnetcdf
else
if (my_task == master_task) then
write(stdout,*)' Bad io_type argument - using iotype_netcdf'
end if
io_pio_type = iotype_netcdf
end if
npes = get_num_procs
()
if (io_pio_stride>0 .and. io_pio_num_iotasks<0) then
io_pio_num_iotasks = npes/io_pio_stride
else if (io_pio_num_iotasks>0 .and. io_pio_stride<0) then
io_pio_stride = npes/io_pio_num_iotasks
else if (io_pio_num_iotasks<0 .and. io_pio_stride<0) then
io_pio_stride = max(min(npes,4),npes/8)
io_pio_num_iotasks = npes/io_pio_stride
end if
if (io_pio_root<0) then
io_pio_root = 1
endif
io_pio_root = min(io_pio_root,npes-1)
if(io_pio_root + (io_pio_stride)*(io_pio_num_iotasks-1) >= npes .or. &
io_pio_stride<=0 .or. io_pio_num_iotasks<=0 .or. io_pio_root < 0 .or. &
io_pio_root > npes-1) then
if (my_task == master_task) then
write(stdout,*)&
'io_pio_stride or io_pio_num_iotasks out of bounds, resetting to defaults ',&
io_pio_stride, io_pio_num_iotasks, io_pio_root
end if
io_pio_stride = max(1,npes/4)
io_pio_num_iotasks = npes/io_pio_stride
io_pio_root = min(1,npes-1)
end if
if (my_task == master_task) then
write(stdout,*)'Using io_type=',tmpname,' stride=',io_pio_stride,&
' iotasks=',io_pio_num_iotasks,' root=',io_pio_root
end if
end subroutine io_pio_set_params
!================================================================================
subroutine io_pio_initdecomp (basetype, ndim3, kdim3, iodesc) 12,6
use blocks
, only : block, nx_block, ny_block, get_block
use domain
, only : nblocks_clinic, blocks_clinic
use POP_DomainSizeMod, only : POP_nxGlobal, POP_nyGlobal
integer (i4) , intent(in) :: basetype
integer(kind=int_kind), intent(in) :: ndim3
integer(kind=int_kind), intent(in) :: kdim3
type(io_desc_t) , pointer :: iodesc
integer (kind=int_kind) :: &
iblk,ib,ie,jb,je,lon,lat,i,j,n,k,index
type(block) :: this_block
integer(kind=int_kind), pointer :: dof3d(:)
logical, save :: first_time = .true.
logical :: set_iodesc
if (first_time) then
allocate(ptr_ioDesc_i(nmax))
allocate(ptr_ioDesc_r(nmax))
allocate(ptr_ioDesc_d(nmax))
do i = 1,nmax
allocate(ptr_ioDesc_i(i)%ioDesc(1))
allocate(ptr_ioDesc_r(i)%ioDesc(1))
allocate(ptr_ioDesc_d(i)%ioDesc(1))
end do
first_time = .false.
end if
if (basetype == PIO_INT) then
do i = 1,nmax
if (nsize3d_i(i) == ndim3 .and. ksize3d_i(i) == kdim3) then
index = i
set_ioDesc = .false.
exit
else if (nsize3d_i(i) == iunset .and. ksize3d_i(i) == iunset) then
index = i
nsize3d_i(index) = ndim3
ksize3d_i(index) = kdim3
set_ioDesc = .true.
exit
end if
end do
else if (basetype == PIO_REAL) then
do i = 1,nmax
if (nsize3d_r(i) == ndim3 .and. ksize3d_r(i) == kdim3) then
index = i
set_ioDesc = .false.
exit
else if (nsize3d_r(i) == iunset .and. ksize3d_r(i) == iunset) then
index = i
nsize3d_r(index) = ndim3
ksize3d_r(index) = kdim3
set_ioDesc = .true.
exit
end if
end do
else if (basetype == PIO_DOUBLE) then
do i = 1,nmax
if (nsize3d_d(i) == ndim3 .and. ksize3d_d(i) == kdim3) then
index = i
set_ioDesc = .false.
exit
else if (nsize3d_d(i) == iunset .and. ksize3d_d(i) == iunset) then
index = i
nsize3d_d(index) = ndim3
ksize3d_d(index) = kdim3
set_ioDesc = .true.
exit
end if
end do
end if
if (set_ioDesc) then
if ((ndim3 == 0 .and. kdim3 /= 0) .or. (ndim3 /=0 .and. kdim3 == 0)) then
call exit_POP
(sigAbort,' io_pio_initdecomp: ndim3 and kdim3 must both be zero or nonzero')
end if
if (ndim3 > kdim3) then
call exit_POP
(sigAbort,' io_pio_initdecomp: ndim3 must be less than or equal to kdim3')
end if
if (ndim3 == 0) then
allocate(dof3d(nx_block*ny_block*nblocks_clinic))
n=0
do iblk = 1, nblocks_clinic
this_block = get_block
(blocks_clinic(iblk),iblk)
ib = this_block%ib
ie = this_block%ie
jb = this_block%jb
je = this_block%je
do j=1,ny_block
do i=1,nx_block
n = n+1
if (j < jb .or. j>je) then
dof3d(n)=0
else if (i < ib .or. i > ie) then
dof3d(n) = 0
else
lon = this_block%i_glob(i)
lat = this_block%j_glob(j)
dof3d(n) = ((lat-1)*POP_nxGlobal + lon)
endif
enddo !i
enddo !j
end do
else
allocate(dof3d(nx_block*ny_block*nblocks_clinic*kdim3))
n=0
do iblk = 1, nblocks_clinic
this_block = get_block
(blocks_clinic(iblk),iblk)
ib = this_block%ib
ie = this_block%ie
jb = this_block%jb
je = this_block%je
do k=1,kdim3
do j=1,ny_block
do i=1,nx_block
n = n+1
if (j < jb .or. j>je) then
dof3d(n)=0
else if (i < ib .or. i > ie) then
dof3d(n) = 0
else
if (k > ndim3) then
dof3d(n) = 0
else
lon = this_block%i_glob(i)
lat = this_block%j_glob(j)
dof3d(n) = ((lat-1)*POP_nxGlobal + lon) + (k-1)*POP_nxGlobal*POP_nyGlobal
end if
endif
enddo !i
enddo !j
enddo !kdim3
end do
end if
if (basetype == PIO_INT) then
if (ndim3 == 0) then
call pio_initdecomp(io_pio_subsystem, basetype, (/POP_nxGlobal,POP_nyGlobal/), &
dof3d, ptr_ioDesc_i(index)%ioDesc(1))
else
call pio_initdecomp(io_pio_subsystem, basetype, (/POP_nxGlobal,POP_nyGlobal,ndim3/), &
dof3d, ptr_ioDesc_i(index)%ioDesc(1))
end if
else if (basetype == PIO_REAL) then
if (ndim3 == 0) then
call pio_initdecomp(io_pio_subsystem, basetype, (/POP_nxGlobal,POP_nyGlobal/), &
dof3d, ptr_ioDesc_r(index)%ioDesc(1))
else
call pio_initdecomp(io_pio_subsystem, basetype, (/POP_nxGlobal,POP_nyGlobal,ndim3/), &
dof3d, ptr_ioDesc_r(index)%ioDesc(1))
end if
else if (basetype == PIO_DOUBLE) then
if (ndim3 == 0) then
call pio_initdecomp(io_pio_subsystem, basetype, (/POP_nxGlobal,POP_nyGlobal/), &
dof3d, ptr_ioDesc_d(index)%ioDesc(1))
else
call pio_initdecomp(io_pio_subsystem, basetype, (/POP_nxGlobal,POP_nyGlobal,ndim3/), &
dof3d, ptr_ioDesc_d(index)%ioDesc(1))
end if
end if
deallocate(dof3d)
end if
if (basetype == PIO_INT) then
iodesc => ptr_ioDesc_i(index)%ioDesc(1)
elseif (basetype == PIO_REAL) then
iodesc => ptr_ioDesc_r(index)%ioDesc(1)
elseif (basetype == PIO_DOUBLE) then
iodesc => ptr_ioDesc_d(index)%ioDesc(1)
end if
end subroutine io_pio_initdecomp
!================================================================================
end module io_pio