!BOP =========================================================================== ! ! !MODULE: ice_pio -- reads and writes driver files ! ! !DESCRIPTION: ! Writes netcdf files ! ! !REMARKS: ! ! !REVISION HISTORY: ! Created by Mariana Vertenstein, June 2009 ! ! !INTERFACE: ------------------------------------------------------------------ module ice_pio 3,14 ! !USES: use shr_kind_mod, only: r8 => shr_kind_r8, in=>shr_kind_in use shr_kind_mod, only: cl => shr_kind_cl use shr_sys_mod , only: shr_sys_flush use ice_kinds_mod use ice_blocks use ice_broadcast use ice_communicate use ice_domain, only : nblocks, blocks_ice use ice_domain_size use ice_fileunits use ice_exit use pio implicit none private save ! !PUBLIC TYPES: ! none !PUBLIC MEMBER FUNCTIONS: interface ice_pio_initdecomp 10 module procedure ice_pio_initdecomp_2d module procedure ice_pio_initdecomp_3d module procedure ice_pio_initdecomp_3d_inner end interface public ice_pio_init public ice_pio_finalize public ice_pio_initdecomp ! !PUBLIC DATA MEMBERS integer, public :: ice_pio_stride, ice_num_iotasks, ice_pio_root, ice_pio_type !EOP !---------------------------------------------------------------------------- ! Local data !---------------------------------------------------------------------------- type(iosystem_desc_t) :: ice_pio_subsystem !=============================================================================== contains !=============================================================================== !BOP ! ! !IROUTINE: ice_pio_finalize - finalize io for input or output ! ! !INTERFACE: subroutine ice_pio_finalize integer :: ierr call pio_finalize(ice_pio_subsystem,ierr) end subroutine ice_pio_finalize !=============================================================================== !BOP ! ! !IROUTINE: ice_pio_init - initialize io for input or output ! ! !INTERFACE: subroutine ice_pio_init(mode, filename, File, clobber, cdf64) 3,11 ! ! !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), optional :: mode character(len=*) , intent(in), optional :: filename type(file_desc_t) , intent(inout), optional :: File logical , intent(in), optional :: clobber logical , intent(in), optional :: cdf64 ! !EOP ! integer (int_kind) :: & nml_error ! namelist read error flag character(len=16) :: ice_pio_type_name logical :: exists logical :: lclobber logical :: lcdf64 integer :: status integer :: nmode character(*),parameter :: subName = '(ice_pio_wopen) ' logical, save :: first_call = .true. ! Input namelist namelist /ice_pio_nml/ & ice_num_iotasks, & ice_pio_stride, & ice_pio_type_name ice_pio_root = 1 ! defaulted to 1 ice_num_iotasks = -1 ! set based on io_stride value when initialized < 0 ice_pio_stride = -1 ! set based on num_iotasks value when initialized < 0 ice_pio_type_name = 'netcdf' if (my_task == master_task) then call get_fileunit(nu_nml) open (nu_nml, 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(nu_nml, nml=ice_pio_nml,iostat=nml_error) if (nml_error > 0) read(nu_nml,*) ! for Nagware compiler end do if (nml_error == 0) close(nu_nml) call ice_pio_set_params(ice_pio_type_name) call release_fileunit(nu_nml) write(nu_diag,*) 'CICE PIO parameter settings...' write(nu_diag,*) ' ice_pio_stride = ',ice_pio_stride write(nu_diag,*) ' ice_num_iotasks = ',ice_num_iotasks write(nu_diag,*) ' ice pio_type_name = ',ice_pio_type_name call shr_sys_flush(nu_diag) endif call broadcast_scalar(nml_error, master_task) if (nml_error /= 0) then call abort_ice('ice: error reading pio_nml') endif call broadcast_scalar(ice_num_iotasks, master_task) call broadcast_scalar(ice_pio_root, master_task) call broadcast_scalar(ice_pio_stride, master_task) call broadcast_scalar(ice_pio_type, master_task) if (first_call) then call pio_init(my_task, MPI_COMM_ICE, ice_num_iotasks, & ice_pio_root, ice_pio_stride, PIO_REARR_BOX, ice_pio_subsystem) first_call = .false. end if if (present(mode) .and. present(filename) .and. present(File)) then 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(ice_pio_subsystem, File, ice_pio_type, trim(filename), nmode) if (my_task == master_task) then write(nu_diag,*) subname,' create file ',trim(filename) end if else status = pio_openfile(ice_pio_subsystem, File, ice_pio_type, trim(filename), pio_write) if (my_task == master_task) then write(nu_diag,*) subname,' open file ',trim(filename) end if endif else nmode = pio_noclobber if (lcdf64) nmode = ior(nmode,PIO_64BIT_OFFSET) status = pio_createfile(ice_pio_subsystem, File, ice_pio_type, trim(filename), nmode) if (my_task == master_task) then write(nu_diag,*) 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(ice_pio_subsystem, File, ice_pio_type, trim(filename), pio_nowrite) else if(my_task==master_task) then write(nu_diag,*) 'ice_pio_ropen ERROR: file invalid ',trim(filename) end if call abort_ice('aborting in ice-pio_ropen with invalid file') endif end if end if end subroutine ice_pio_init !=============================================================================== !BOP ! ! !IROUTINE: ice_pio_set_params - set pio parameters ! ! !INTERFACE: subroutine ice_pio_set_params(ice_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) :: ice_pio_type_name ! !EOP ! character(len=16) :: tmpname integer (kind=int_kind) :: npes tmpname = shr_string_toupper(ice_pio_type_name) if (trim(tmpname) == 'NETCDF') then ice_pio_type = iotype_netcdf else if (trim(tmpname) == 'PNETCDF') then ice_pio_type = iotype_pnetcdf else if (my_task == master_task) then write(nu_diag,*)' Bad io_type argument - using iotype_netcdf' end if ice_pio_type = iotype_netcdf end if npes = get_num_procs() if (ice_pio_stride>0 .and. ice_num_iotasks<0) then ice_num_iotasks = npes/ice_pio_stride else if (ice_num_iotasks>0 .and. ice_pio_stride<0) then ice_pio_stride = npes/ice_num_iotasks else if (ice_num_iotasks<0 .and. ice_pio_stride<0) then ice_pio_stride = max(min(npes,4),npes/8) ice_num_iotasks = npes/ice_pio_stride end if if (ice_pio_root<0) then ice_pio_root = 1 endif ice_pio_root = min(ice_pio_root,npes-1) if(ice_pio_root + (ice_pio_stride)*(ice_num_iotasks-1) >= npes .or. & ice_pio_stride<=0 .or. ice_num_iotasks<=0 .or. ice_pio_root < 0 .or. & ice_pio_root > npes-1) then if (my_task == master_task) then write(nu_diag,*)& 'ice_pio_stride or ice_num_iotasks out of bounds, resetting to defaults ',& ice_pio_stride, ice_num_iotasks, ice_pio_root end if ice_pio_stride = max(1,npes/4) ice_num_iotasks = npes/ice_pio_stride ice_pio_root = min(1,npes-1) end if if (my_task == master_task) then write(nu_diag,*)'Using io_type=',tmpname,' stride=',ice_pio_stride,& ' iotasks=',ice_num_iotasks,' root=',ice_pio_root end if end subroutine ice_pio_set_params !================================================================================ subroutine ice_pio_initdecomp_2d(iodesc) 1,1 type(io_desc_t), intent(out) :: iodesc integer (kind=int_kind) :: & iblk,ilo,ihi,jlo,jhi,lon,lat,i,j,n,k type(block) :: this_block integer(kind=int_kind), pointer :: dof2d(:) allocate(dof2d(nx_block*ny_block*nblocks)) n=0 do iblk = 1, nblocks this_block = get_block(blocks_ice(iblk),iblk) ilo = this_block%ilo ihi = this_block%ihi jlo = this_block%jlo jhi = this_block%jhi do j=1,ny_block do i=1,nx_block n = n+1 if (j < jlo .or. j>jhi) then dof2d(n) = 0 else if (i < ilo .or. i > ihi) then dof2d(n) = 0 else lon = this_block%i_glob(i) lat = this_block%j_glob(j) dof2d(n) = (lat-1)*nx_global + lon endif enddo !i enddo !j end do call pio_initdecomp(ice_pio_subsystem, pio_double, (/nx_global,ny_global/), & dof2d, iodesc) deallocate(dof2d) end subroutine ice_pio_initdecomp_2d !================================================================================ subroutine ice_pio_initdecomp_3d (ndim3, iodesc) 1,1 integer(kind=int_kind), intent(in) :: ndim3 type(io_desc_t), intent(out) :: iodesc integer (kind=int_kind) :: & iblk,ilo,ihi,jlo,jhi,lon,lat,i,j,n,k type(block) :: this_block integer(kind=int_kind), pointer :: dof3d(:) allocate(dof3d(nx_block*ny_block*nblocks*ndim3)) n=0 do iblk = 1, nblocks this_block = get_block(blocks_ice(iblk),iblk) ilo = this_block%ilo ihi = this_block%ihi jlo = this_block%jlo jhi = this_block%jhi do k=1,ndim3 do j=1,ny_block do i=1,nx_block n = n+1 if (j < jlo .or. j>jhi) then dof3d(n)=0 else if (i < ilo .or. i > ihi) then dof3d(n) = 0 else lon = this_block%i_glob(i) lat = this_block%j_glob(j) dof3d(n) = ((lat-1)*nx_global + lon) + (k-1)*nx_global*ny_global endif enddo !i enddo !j enddo !ndim3 end do call pio_initdecomp(ice_pio_subsystem, pio_double, (/nx_global,ny_global,ndim3/), & dof3d, iodesc) deallocate(dof3d) end subroutine ice_pio_initdecomp_3d !================================================================================ subroutine ice_pio_initdecomp_3d_inner(ndim3, inner_dim, iodesc) 1,1 integer(kind=int_kind), intent(in) :: ndim3 logical, intent(in) :: inner_dim type(io_desc_t), intent(out) :: iodesc integer (kind=int_kind) :: & iblk,ilo,ihi,jlo,jhi,lon,lat,i,j,n,k type(block) :: this_block integer(kind=int_kind), pointer :: dof3d(:) allocate(dof3d(nx_block*ny_block*nblocks*ndim3)) n=0 do iblk = 1, nblocks this_block = get_block(blocks_ice(iblk),iblk) ilo = this_block%ilo ihi = this_block%ihi jlo = this_block%jlo jhi = this_block%jhi do j=1,ny_block do i=1,nx_block do k=1,ndim3 n = n+1 if (j < jlo .or. j>jhi) then dof3d(n) = 0 else if (i < ilo .or. i > ihi) then dof3d(n) = 0 else lon = this_block%i_glob(i) lat = this_block%j_glob(j) dof3d(n) = k + ((lon-1) + (lat-1)*nx_global)*ndim3 endif end do !ndim3 enddo !i enddo !j end do !iblk call pio_initdecomp(ice_pio_subsystem, pio_double, (/ndim3,nx_global,ny_global/), & dof3d, iodesc) deallocate(dof3d) end subroutine ice_pio_initdecomp_3d_inner end module ice_pio