LCOV - code coverage report
Current view: top level - cicecore/shared - ice_fileunits.F90 (source / functions) Hit Total Coverage
Test: 231018-211459:8916b9ff2c:1:quick Lines: 99 102 97.06 %
Date: 2023-10-18 15:30:36 Functions: 6 6 100.00 %

          Line data    Source code
       1             : !=======================================================================
       2             : !
       3             : !  This module contains an I/O unit manager for tracking, assigning
       4             : !  and reserving I/O unit numbers.
       5             : !
       6             : !  There are three reserved I/O units set as parameters in this
       7             : !  module.  The default units for standard input (stdin), standard
       8             : !  output (stdout) and standard error (stderr).  These are currently
       9             : !  set as units 5,6,6, respectively as that is the most commonly
      10             : !  used among vendors. However, the user may change these if those
      11             : !  default units are conflicting with other models or if the
      12             : !  vendor is using different values.
      13             : !
      14             : !  The maximum number of I/O units per node is currently set by
      15             : !  the parameter ice\_IOMaxUnit.
      16             : !
      17             : ! author: Elizabeth C. Hunke, LANL
      18             : ! 2006: ECH converted to free source form (F90)
      19             : ! 2007: ECH added dynamic file units, modified from POP_IOUnitsMod.F90
      20             : 
      21             :       module ice_fileunits
      22             : 
      23             :       use ice_kinds_mod
      24             : #ifdef CESMCOUPLED
      25             :       use shr_file_mod, only : shr_file_getunit, shr_file_freeunit
      26             : #endif
      27             : 
      28             :       implicit none
      29             :       private
      30             :       public :: init_fileunits, get_fileunit, flush_fileunit, &
      31             :                 release_fileunit, release_all_fileunits, &   ! LCOV_EXCL_LINE
      32             :                 goto_nml
      33             : 
      34             :       character (len=char_len), public :: &
      35             :          diag_type               ! 'stdout' or 'file'
      36             : 
      37             :       character (len=char_len), public :: &
      38             :          bfbflag                 ! method for bit-for-bit computations
      39             : 
      40             :       integer (kind=int_kind), public :: &
      41             :          nu_grid       , &  ! grid file   ! LCOV_EXCL_LINE
      42             :          nu_kmt        , &  ! land mask file   ! LCOV_EXCL_LINE
      43             :          nu_nml        , &  ! namelist input file   ! LCOV_EXCL_LINE
      44             :          nu_forcing    , &  ! forcing data file   ! LCOV_EXCL_LINE
      45             :          nu_dump       , &  ! dump file for restarting   ! LCOV_EXCL_LINE
      46             :          nu_restart    , &  ! restart input file   ! LCOV_EXCL_LINE
      47             :          nu_dump_age   , &  ! dump file for restarting ice age tracer   ! LCOV_EXCL_LINE
      48             :          nu_restart_age, &  ! restart input file for ice age tracer   ! LCOV_EXCL_LINE
      49             :          nu_dump_FY    , &  ! dump file for restarting first-year area tracer   ! LCOV_EXCL_LINE
      50             :          nu_restart_FY , &  ! restart input file for first-year area tracer   ! LCOV_EXCL_LINE
      51             :          nu_dump_lvl   , &  ! dump file for restarting level ice tracers   ! LCOV_EXCL_LINE
      52             :          nu_restart_lvl, &  ! restart input file for level ice tracers   ! LCOV_EXCL_LINE
      53             :          nu_dump_pond  , &  ! dump file for restarting melt pond tracer   ! LCOV_EXCL_LINE
      54             :          nu_restart_pond,&  ! restart input file for melt pond tracer   ! LCOV_EXCL_LINE
      55             :          nu_dump_snow  , &  ! dump file for restarting snow redist/metamorph tracers   ! LCOV_EXCL_LINE
      56             :          nu_restart_snow,&  ! restart input file for snow redist/metamorph tracers   ! LCOV_EXCL_LINE
      57             :          nu_dump_fsd   , &  ! dump file for restarting floe size distribution   ! LCOV_EXCL_LINE
      58             :          nu_restart_fsd, &  ! restart input file for floe size distribution   ! LCOV_EXCL_LINE
      59             :          nu_dump_iso   , &  ! dump file for restarting isotope tracers   ! LCOV_EXCL_LINE
      60             :          nu_restart_iso, &  ! restart input file for isotope tracers   ! LCOV_EXCL_LINE
      61             :          nu_dump_aero  , &  ! dump file for restarting aerosol tracer   ! LCOV_EXCL_LINE
      62             :          nu_restart_aero,&  ! restart input file for aerosol tracer   ! LCOV_EXCL_LINE
      63             :          nu_dump_bgc   , &  ! dump file for restarting bgc   ! LCOV_EXCL_LINE
      64             :          nu_restart_bgc, &  ! restart input file for bgc   ! LCOV_EXCL_LINE
      65             :          nu_dump_hbrine, &  ! dump file for restarting hbrine   ! LCOV_EXCL_LINE
      66             :          nu_restart_hbrine, &  ! restart input file for hbrine   ! LCOV_EXCL_LINE
      67             :          nu_dump_eap   , &  ! dump file for restarting eap dynamics   ! LCOV_EXCL_LINE
      68             :          nu_restart_eap, &  ! restart input file for eap dynamics   ! LCOV_EXCL_LINE
      69             :          nu_rst_pointer, &  ! pointer to latest restart file   ! LCOV_EXCL_LINE
      70             :          nu_history    , &  ! binary history output file   ! LCOV_EXCL_LINE
      71             :          nu_hdr             ! header file for binary history output
      72             : 
      73             :       character (32), public :: &
      74             :          nml_filename = 'ice_in' ! namelist input file name
      75             : 
      76             :       integer (kind=int_kind), parameter, public :: &
      77             :          ice_stdin  =  5, & ! reserved unit for standard input   ! LCOV_EXCL_LINE
      78             :          ice_stdout =  6, & ! reserved unit for standard output   ! LCOV_EXCL_LINE
      79             :          ice_stderr =  6    ! reserved unit for standard error
      80             : 
      81             :       integer (kind=int_kind), public :: &
      82             :          nu_diag = ice_stdout  ! diagnostics output file, unit number may be overwritten
      83             : 
      84             :       logical (kind=log_kind), public :: &
      85             :          nu_diag_set = .false. ! flag to indicate whether nu_diag is already set
      86             : 
      87             :       integer (kind=int_kind), public :: &
      88             :          ice_IOUnitsMinUnit = 11, & ! do not use unit numbers below   ! LCOV_EXCL_LINE
      89             :          ice_IOUnitsMaxUnit = 99    ! or above, set by setup_nml
      90             : 
      91             :       logical (kind=log_kind), dimension(:), allocatable :: &
      92             :          ice_IOUnitsInUse   ! flag=.true. if unit currently open
      93             : 
      94             :       ! instance control
      95             :       integer (kind=int_kind), public :: inst_index
      96             :       character(len=16)      , public :: inst_name
      97             :       character(len=16)      , public :: inst_suffix
      98             : 
      99             : !=======================================================================
     100             : 
     101             :       contains
     102             : 
     103             : !=======================================================================
     104             : 
     105             : !  This routine grabs needed unit numbers.
     106             : !  nu_diag is set to 6 (stdout) but may be reset later by the namelist.
     107             : !  nu_nml is obtained separately.
     108             : 
     109          37 :       subroutine init_fileunits
     110             : 
     111             :          character(len=*),parameter :: subname='(init_fileunits)'
     112             : 
     113          37 :          if (.not.allocated(ice_IOUnitsInUse)) allocate(ice_IOUnitsInUse(ice_IOUnitsMaxUnit))
     114        3700 :          ice_IOUnitsInUse = .false.
     115             : 
     116          37 :          ice_IOUnitsInUse(ice_stdin)  = .true. ! reserve unit 5
     117          37 :          ice_IOUnitsInUse(ice_stdout) = .true. ! reserve unit 6
     118          37 :          ice_IOUnitsInUse(ice_stderr) = .true.
     119          37 :          if (nu_diag >= 1 .and. nu_diag <= ice_IOUnitsMaxUnit) &
     120          37 :               ice_IOUnitsInUse(nu_diag) = .true. ! reserve unit nu_diag
     121             : #ifdef CESMCOUPLED
     122             :          ! CESM can have negative unit numbers.
     123             :          if (nu_diag < 0) nu_diag_set = .true.
     124             : #endif
     125             : 
     126          37 :          call get_fileunit(nu_grid)
     127          37 :          call get_fileunit(nu_kmt)
     128          37 :          call get_fileunit(nu_forcing)
     129          37 :          call get_fileunit(nu_dump)
     130          37 :          call get_fileunit(nu_restart)
     131          37 :          call get_fileunit(nu_dump_age)
     132          37 :          call get_fileunit(nu_restart_age)
     133          37 :          call get_fileunit(nu_dump_FY)
     134          37 :          call get_fileunit(nu_restart_FY)
     135          37 :          call get_fileunit(nu_dump_lvl)
     136          37 :          call get_fileunit(nu_restart_lvl)
     137          37 :          call get_fileunit(nu_dump_pond)
     138          37 :          call get_fileunit(nu_restart_pond)
     139          37 :          call get_fileunit(nu_dump_snow)
     140          37 :          call get_fileunit(nu_restart_snow)
     141          37 :          call get_fileunit(nu_dump_fsd)
     142          37 :          call get_fileunit(nu_restart_fsd)
     143          37 :          call get_fileunit(nu_dump_iso)
     144          37 :          call get_fileunit(nu_restart_iso)
     145          37 :          call get_fileunit(nu_dump_aero)
     146          37 :          call get_fileunit(nu_restart_aero)
     147          37 :          call get_fileunit(nu_dump_bgc)
     148          37 :          call get_fileunit(nu_restart_bgc)
     149          37 :          call get_fileunit(nu_dump_hbrine)
     150          37 :          call get_fileunit(nu_restart_hbrine)
     151          37 :          call get_fileunit(nu_dump_eap)
     152          37 :          call get_fileunit(nu_restart_eap)
     153          37 :          call get_fileunit(nu_rst_pointer)
     154          37 :          call get_fileunit(nu_history)
     155          37 :          call get_fileunit(nu_hdr)
     156             : 
     157          37 :       end subroutine init_fileunits
     158             : 
     159             : !=======================================================================
     160             : 
     161             : !  This routine returns the next available I/O unit and marks it as
     162             : !  in use to prevent any later use.
     163             : !  Note that {\em all} processors must call this routine even if only
     164             : !  the master task is doing the I/O.  This is necessary insure that
     165             : !  the units remain synchronized for other parallel I/O functions.
     166             : 
     167        1166 :       subroutine get_fileunit(iunit)
     168             : 
     169             :          integer (kind=int_kind), intent(out) :: &
     170             :             iunit                     ! next free I/O unit
     171             : 
     172             :          ! local variables
     173             : 
     174             : #ifndef CESMCOUPLED
     175             :          integer (kind=int_kind) :: n  ! dummy loop index
     176             :          logical (kind=log_kind) :: alreadyInUse
     177             : #endif
     178             : 
     179             :          character(len=*),parameter :: subname='(get_fileunit)'
     180             : 
     181             : #ifdef CESMCOUPLED
     182             :          iunit = shr_file_getUnit()
     183             : #else
     184             : 
     185       18451 :          srch_units: do n=ice_IOUnitsMinUnit, ice_IOUnitsMaxUnit
     186       18451 :             if (.not. ice_IOUnitsInUse(n)) then   ! I found one, I found one
     187             : 
     188             :                !*** make sure not in use by library or calling routines
     189        1166 :                INQUIRE (unit=n,OPENED=alreadyInUse)
     190             : 
     191        1166 :                if (.not. alreadyInUse) then
     192        1166 :                   iunit = n        ! return the free unit number
     193        1166 :                   ice_IOUnitsInUse(iunit) = .true.  ! mark iunit as being in use
     194        1166 :                   exit srch_units
     195             :                else
     196             :                   !*** if inquire shows this unit in use, mark it as
     197             :                   !***    in use to prevent further queries
     198           0 :                   ice_IOUnitsInUse(n) = .true.
     199             :                endif
     200             :             endif
     201             :          end do srch_units
     202             : 
     203        1166 :          if (iunit > ice_IOUnitsMaxUnit) stop 'ice_IOUnitsGet: No free units'
     204             : 
     205             : #endif
     206             : 
     207        1166 :       end subroutine get_fileunit
     208             : 
     209             : !=======================================================================
     210             : 
     211             : !  This routine releases unit numbers at the end of a run.
     212             : 
     213          37 :       subroutine release_all_fileunits
     214             : 
     215             :          character(len=*),parameter :: subname='(release_all_fileunits)'
     216             : 
     217          37 :          call release_fileunit(nu_grid)
     218          37 :          call release_fileunit(nu_kmt)
     219          37 :          call release_fileunit(nu_forcing)
     220          37 :          call release_fileunit(nu_dump)
     221          37 :          call release_fileunit(nu_restart)
     222          37 :          call release_fileunit(nu_dump_age)
     223          37 :          call release_fileunit(nu_restart_age)
     224          37 :          call release_fileunit(nu_dump_FY)
     225          37 :          call release_fileunit(nu_restart_FY)
     226          37 :          call release_fileunit(nu_dump_lvl)
     227          37 :          call release_fileunit(nu_restart_lvl)
     228          37 :          call release_fileunit(nu_dump_pond)
     229          37 :          call release_fileunit(nu_restart_pond)
     230          37 :          call release_fileunit(nu_dump_snow)
     231          37 :          call release_fileunit(nu_restart_snow)
     232          37 :          call release_fileunit(nu_dump_fsd)
     233          37 :          call release_fileunit(nu_restart_fsd)
     234          37 :          call release_fileunit(nu_dump_iso)
     235          37 :          call release_fileunit(nu_restart_iso)
     236          37 :          call release_fileunit(nu_dump_aero)
     237          37 :          call release_fileunit(nu_restart_aero)
     238          37 :          call release_fileunit(nu_dump_bgc)
     239          37 :          call release_fileunit(nu_restart_bgc)
     240          37 :          call release_fileunit(nu_dump_hbrine)
     241          37 :          call release_fileunit(nu_restart_hbrine)
     242          37 :          call release_fileunit(nu_dump_eap)
     243          37 :          call release_fileunit(nu_restart_eap)
     244          37 :          call release_fileunit(nu_rst_pointer)
     245          37 :          call release_fileunit(nu_history)
     246          37 :          call release_fileunit(nu_hdr)
     247             : #ifdef CESMCOUPLED
     248             :          ! CESM can have negative unit numbers
     249             :          if (nu_diag > 0 .and. nu_diag /= ice_stdout) call release_fileunit(nu_diag)
     250             : #else
     251          37 :          if (nu_diag /= ice_stdout) call release_fileunit(nu_diag)
     252             : #endif
     253             : 
     254          37 :       end subroutine release_all_fileunits
     255             : 
     256             : !=======================================================================
     257             : 
     258             : !  This routine releases an I/O unit (marks it as available).
     259             : !  Note that {\em all} processors must call this routine even if only
     260             : !  the master task is doing the I/O.  This is necessary insure that
     261             : !  the units remain synchronized for other parallel I/O functions.
     262             : 
     263        1166 :       subroutine release_fileunit(iunit)
     264             : 
     265             :          integer (kind=int_kind), intent(in) :: &
     266             :             iunit                    ! I/O unit to be released
     267             : 
     268             :          character(len=*),parameter :: subname='(release_fileunit)'
     269             : 
     270             : #ifdef CESMCOUPLED
     271             :          call shr_file_freeUnit(iunit)
     272             : #else
     273             : !  check for proper unit number
     274        1166 :          if (iunit < 1 .or. iunit > ice_IOUnitsMaxUnit) then
     275           0 :             stop 'release_fileunit: bad unit'
     276             :          endif
     277             : 
     278             : !  mark the unit as not in use
     279        1166 :          ice_IOUnitsInUse(iunit) = .false.  !  that was easy...
     280             : #endif
     281             : 
     282        1166 :       end subroutine release_fileunit
     283             : 
     284             : !=======================================================================
     285             : 
     286             : 
     287             : !  This routine enables a user to flush the output from an IO unit
     288             : !  (typically stdout) to force output when the system is buffering
     289             : !  such output.  Because this system function is system dependent,
     290             : !  we only support this wrapper and users are welcome to insert the
     291             : !  code relevant to their local machine.  In the case where the CESM
     292             : !  libraries are available, the shared routine for sys flush can be
     293             : !  used (and is provided here under a preprocessor option).
     294             : 
     295        1011 :       subroutine flush_fileunit(iunit)
     296             : 
     297             : #ifdef CESMCOUPLED
     298             :          use shr_sys_mod, only : shr_sys_flush
     299             : #endif
     300             : 
     301             :          integer (kind=int_kind), intent(in) :: &
     302             :             iunit                    ! I/O unit to be flushed
     303             : 
     304             :          character(len=*),parameter :: subname='(flush_fileunit)'
     305             : 
     306             : !-----------------------------------------------------------------------
     307             : !
     308             : !  insert your system code here
     309             : !
     310             : !-----------------------------------------------------------------------
     311             : 
     312             : #ifdef CESMCOUPLED
     313             :          call shr_sys_flush(iunit)
     314             : #else
     315             : #ifndef NO_F2003
     316        1011 :          flush(iunit)
     317             : #else
     318             : ! Place holder for old call.
     319             : #endif
     320             : #endif
     321             : 
     322        1011 :       end subroutine flush_fileunit
     323             : 
     324             : !=======================================================================
     325             : 
     326             : !=======================================================
     327             : 
     328         105 :       subroutine goto_nml(iunit, nml, status)
     329             :         ! Search to namelist group within ice_in file.
     330             :         ! for compilers that do not allow optional namelists
     331             : 
     332             :         ! passed variables
     333             :         integer(kind=int_kind), intent(in) :: &
     334             :              iunit ! namelist file unit
     335             : 
     336             :         character(len=*), intent(in) :: &
     337             :              nml ! namelist to search for
     338             : 
     339             :         integer(kind=int_kind), intent(out) :: &
     340             :              status ! status of subrouine
     341             : 
     342             :         ! local variables
     343             :         character(len=char_len) :: &
     344             :              file_str, & ! string in file   ! LCOV_EXCL_LINE
     345             :              nml_str     ! namelist string to test
     346             : 
     347             :         integer(kind=int_kind) :: &
     348             :              i, n ! dummy integers
     349             : 
     350             : 
     351             :         ! rewind file
     352         105 :         rewind(iunit)
     353             : 
     354             :         ! define test string with ampersand
     355         105 :         nml_str = '&' // trim(adjustl(nml))
     356             : 
     357             :         ! search for the record containing the namelist group we're looking for
     358       32242 :         do
     359       32347 :            read(iunit, '(a)', iostat=status) file_str
     360       32347 :            if (status /= 0) then
     361           0 :               exit ! e.g. end of file
     362             :            else
     363       32347 :               if (index(adjustl(file_str), nml_str) == 1) then
     364         105 :                  exit ! i.e. found record we're looking for
     365             :               end if
     366             :            end if
     367             :         end do
     368             : 
     369             :         ! backspace to namelist name in file
     370         105 :         backspace(iunit)
     371             : 
     372         105 :       end subroutine goto_nml
     373             : 
     374             : !=======================================================================
     375             : 
     376             :       end module ice_fileunits
     377             : 
     378             : !=======================================================================

Generated by: LCOV version 1.14-6-g40580cd