!=======================================================================
!BOP
!
! !MODULE: ice_fileunits
!
! !DESCRIPTION:
! This module contains an I/O unit manager for tracking, assigning
! and reserving I/O unit numbers.
!
! There are three reserved I/O units set as parameters in this
! module. The default units for standard input (stdin), standard
! output (stdout) and standard error (stderr). These are currently
! set as units 5,6,6, respectively as that is the most commonly
! used among vendors. However, the user may change these if those
! default units are conflicting with other models or if the
! vendor is using different values.
!
! The maximum number of I/O units per node is currently set by
! the parameter ice\_IOMaxUnits.
!
! !REVISION HISTORY:
! SVN:$Id: ice_fileunits.F90 58 2007-03-29 15:56:53Z eclare $
!
! author: Elizabeth C. Hunke, LANL
! 2006: ECH converted to free source form (F90)
! 2007: ECH added dynamic file units, modified from POP_IOUnitsMod.F90
!
! !INTERFACE:
!
module ice_fileunits 37,2
!
! !USES:
use ice_kinds_mod
#ifdef CCSMCOUPLED
use shr_file_mod
#endif
!
!EOP
!=======================================================================
implicit none
save
character (len=char_len) :: &
diag_type ! 'stdout' or 'file'
integer (kind=int_kind) :: &
nu_grid , & ! grid file
nu_kmt , & ! land mask file
nu_nml , & ! namelist input file
nu_forcing , & ! forcing data file
nu_dump , & ! dump file for restarting
nu_restart , & ! restart input file
nu_dump_aero , & ! dump file for restarting ice aerosol tracer MH
nu_restart_aero,& ! restart input file for ice aerosol tracer MH
nu_dump_age , & ! dump file for restarting ice age tracer
nu_restart_age, & ! restart input file for ice age tracer
nu_dump_FY , & ! dump file for restarting FY ice tracer
nu_restart_FY , & ! restart input file for FY ice tracer
nu_dump_lvl , & ! dump file for restarting level ice tracer
nu_restart_lvl, & ! restart input file for level ice tracer
nu_dump_pond , & ! dump file for restarting melt pond tracer
nu_restart_pond,& ! restart input file for melt pond tracer
nu_rst_pointer, & ! pointer to latest restart file
nu_history , & ! binary history output file
nu_hdr , & ! header file for binary history output
nu_diag , & ! diagnostics output file
nu_timing ! timing output file
integer (kind=int_kind) :: &
diag_level ! per-processor diagnostics level
character (6), parameter :: &
nml_filename = 'ice_in' ! namelist input file name
integer (kind=int_kind), parameter :: &
ice_stdin = 5, & ! reserved unit for standard input
ice_stdout = 6, & ! reserved unit for standard output
ice_stderr = 6 ! reserved unit for standard error
!EOP
!BOC
integer (kind=int_kind), parameter :: &
ice_IOUnitsMinUnits = 11, & ! do not use unit numbers below this
ice_IOUnitsMaxUnits = 99 ! maximum number of open units
logical (kind=log_kind), dimension(ice_IOUnitsMaxUnits) :: &
ice_IOUnitsInUse ! flag=.true. if unit currently open
!EOC
!=======================================================================
contains
!=======================================================================
!BOP
! !IROUTINE: init_fileunits
! !INTERFACE:
subroutine init_fileunits 1,38
! !DESCRIPTION:
! This routine grabs needed unit numbers.
! nu_diag is set to 6 (stdout) but may be reset later by the namelist.
! nu_nml is obtained separately.
nu_diag = ice_stdout ! default
#ifdef CCSMCOUPLED
ice_IOUnitsInUse = .false.
ice_IOUnitsInUse(ice_stdin) = .true. ! reserve unit 5
ice_IOUnitsInUse(ice_stdout) = .true. ! reserve unit 6
ice_IOUnitsInUse(ice_stderr) = .true.
nu_grid = shr_file_getUnit
()
nu_kmt = shr_file_getUnit
()
nu_forcing = shr_file_getUnit
()
nu_dump = shr_file_getUnit
()
nu_restart = shr_file_getUnit
()
nu_dump_aero = shr_file_getUnit
()
nu_restart_aero= shr_file_getUnit
()
nu_dump_age = shr_file_getUnit
()
nu_restart_age = shr_file_getUnit
()
nu_dump_FY = shr_file_getUnit
()
nu_restart_FY = shr_file_getUnit
()
nu_dump_lvl = shr_file_getUnit
()
nu_restart_lvl = shr_file_getUnit
()
nu_dump_pond = shr_file_getUnit
()
nu_restart_pond = shr_file_getUnit
()
nu_rst_pointer = shr_file_getUnit
()
nu_history = shr_file_getUnit
()
nu_hdr = shr_file_getUnit
()
nu_timing = shr_file_getUnit
()
#else
call get_fileunit
(nu_grid)
call get_fileunit
(nu_kmt)
call get_fileunit
(nu_forcing)
call get_fileunit
(nu_dump)
call get_fileunit
(nu_restart)
call get_fileunit
(nu_dump_aero)
call get_fileunit
(nu_restart_aero)
call get_fileunit
(nu_dump_age)
call get_fileunit
(nu_restart_age)
call get_fileunit
(nu_dump_FY)
call get_fileunit
(nu_restart_FY)
call get_fileunit
(nu_dump_lvl)
call get_fileunit
(nu_restart_lvl)
call get_fileunit
(nu_dump_pond)
call get_fileunit
(nu_restart_pond)
call get_fileunit
(nu_rst_pointer)
call get_fileunit
(nu_history)
call get_fileunit
(nu_hdr)
call get_fileunit
(nu_timing)
#endif
end subroutine init_fileunits
!=======================================================================
!BOP
! !IROUTINE: get_fileunit
! !INTERFACE:
subroutine get_fileunit(iunit) 25,1
! !DESCRIPTION:
! This routine returns the next available I/O unit and marks it as
! in use to prevent any later use.
! Note that {\em all} processors must call this routine even if only
! the master task is doing the I/O. This is necessary insure that
! the units remain synchronized for other parallel I/O functions.
!
! !REVISION HISTORY:
! same as module
! !OUTPUT PARAMETERS:
integer (kind=int_kind), intent(out) :: &
iunit ! next free I/O unit
!EOP
!BOC
integer (kind=int_kind) :: n ! dummy loop index
logical (kind=log_kind) :: alreadyInUse
#ifdef CCSMCOUPLED
iunit = shr_file_getUnit
()
#else
srch_units: do n=ice_IOUnitsMinUnits, ice_IOUnitsMaxUnits
if (.not. ice_IOUnitsInUse(n)) then ! I found one, I found one
!*** make sure not in use by library or calling routines
INQUIRE (unit=n,OPENED=alreadyInUse)
if (.not. alreadyInUse) then
iunit = n ! return the free unit number
ice_IOUnitsInUse(n) = .true. ! mark iunit as being in use
exit srch_units
else
!*** if inquire shows this unit in use, mark it as
!*** in use to prevent further queries
ice_IOUnitsInUse(iunit) = .true.
endif
endif
end do srch_units
if (iunit > ice_IOUnitsMaxUnits) stop 'ice_IOUnitsGet: No free units'
#endif
!EOC
end subroutine get_fileunit
!=======================================================================
!BOP
! !IROUTINE: release_all_fileunits
! !INTERFACE:
subroutine release_all_fileunits 1,20
! !DESCRIPTION:
! This routine releases unit numbers at the end of a run.
call release_fileunit
(nu_grid)
call release_fileunit
(nu_kmt)
call release_fileunit
(nu_forcing)
call release_fileunit
(nu_dump)
call release_fileunit
(nu_restart)
call release_fileunit
(nu_dump_aero)
call release_fileunit
(nu_restart_aero)
call release_fileunit
(nu_dump_age)
call release_fileunit
(nu_restart_age)
call release_fileunit
(nu_dump_FY)
call release_fileunit
(nu_restart_FY)
call release_fileunit
(nu_dump_lvl)
call release_fileunit
(nu_restart_lvl)
call release_fileunit
(nu_dump_pond)
call release_fileunit
(nu_restart_pond)
call release_fileunit
(nu_rst_pointer)
call release_fileunit
(nu_history)
call release_fileunit
(nu_hdr)
call release_fileunit
(nu_timing)
if (nu_diag /= ice_stdout) call release_fileunit
(nu_diag)
end subroutine release_all_fileunits
!=======================================================================
!BOP
! !IROUTINE: release_fileunit
! !INTERFACE:
subroutine release_fileunit(iunit) 25,1
! !DESCRIPTION:
! This routine releases an I/O unit (marks it as available).
! Note that {\em all} processors must call this routine even if only
! the master task is doing the I/O. This is necessary insure that
! the units remain synchronized for other parallel I/O functions.
!
! !REVISION HISTORY:
! same as module
! !INPUT PARAMETER:
integer (kind=int_kind), intent(in) :: &
iunit ! I/O unit to be released
!EOP
!BOC
#ifdef CCSMCOUPLED
call shr_file_freeUnit
(iunit)
#else
! check for proper unit number
if (iunit < 1 .or. iunit > ice_IOUnitsMaxUnits) then
stop 'release_fileunit: bad unit'
endif
! mark the unit as not in use
ice_IOUnitsInUse(iunit) = .false. ! that was easy...
#endif
!EOC
end subroutine release_fileunit
!=======================================================================
!BOP
! !IROUTINE: flush_fileunit
! !INTERFACE:
subroutine flush_fileunit(iunit) 3,2
! !DESCRIPTION:
! This routine enables a user to flush the output from an IO unit
! (typically stdout) to force output when the system is buffering
! such output. Because this system function is system dependent,
! we only support this wrapper and users are welcome to insert the
! code relevant to their local machine. In the case where the CCSM
! libraries are available, the shared routine for sys flush can be
! used (and is provided here under a preprocessor option).
!
! !REVISION HISTORY:
! same as module
!
! !USES:
#ifdef CCSMCOUPLED
use shr_sys_mod
, only : shr_sys_flush
#endif
! !INPUT PARAMETER:
integer (kind=int_kind), intent(in) :: &
iunit ! I/O unit to be flushed
!EOP
!BOC
!-----------------------------------------------------------------------
!
! insert your system code here
!
!-----------------------------------------------------------------------
#if (defined IRIX64 || defined CRAY || defined OSF1 || defined SUNOS || defined LINUX || defined NEC_SX | defined UNICOSMP)
call flush(iunit)
#endif
#if (defined AIX)
call flush_(iunit)
#endif
#ifdef CCSMCOUPLED
call shr_sys_flush
(iunit)
#endif
!EOC
end subroutine flush_fileunit
!=======================================================================
end module ice_fileunits
!=======================================================================