!===============================================================================
! SVN $Id: shr_stream_mod.F90 36506 2012-04-18 17:41:58Z tcraig $
! SVN $URL: https://svn-ccsm-models.cgd.ucar.edu/csm_share/trunk_tags/share3_121022/shr/shr_stream_mod.F90 $
!===============================================================================
!BOP ===========================================================================
!
! !MODULE: shr_stream_mod -- Data type and methods to manage input data streams.
!
! !DESCRIPTION:
! A "data stream" is a sequence of input files where each file contains the
! same set of data fields and all the data fields are on the same grid.
! The sequence of input data files provides an uninterupted time series of
! data.
!
! A stream data type stores information about one data stream, including the
! range of data date years to use and how data dates align with model dates.
!
! Given a model date, this module can return data dates that are upper and
! lower time bounds around the given model date and the names of the files
! containing those dates.
!
! !REMARKS:
!
! !REVISION HISTORY:
! 2005-Apr-13 - B. Kauffman - moved code from dshr to shr
! 2005-Apr-01 - B. Kauffman - first functional version of findBounds
! 2004-Dec-xx - B. Kauffman - initial module
!
! !INTERFACE: ------------------------------------------------------------------
module shr_stream_mod
use shr_sys_mod ! shared system calls
use shr_kind_mod ! kinds for strong typing
use shr_const_mod ! shared constants (including seconds per day)
use shr_string_mod ! string & list methods
use shr_mpi_mod ! shared mpi
use shr_file_mod ! file methods
use shr_cal_mod ! calendar methods
use shr_log_mod, only : s_loglev => shr_log_Level
use shr_log_mod, only : s_logunit => shr_log_Unit
use perf_mod
implicit none
private ! default private
! !PUBLIC TYPES:
public :: shr_stream_streamType ! stream data type with private components
public :: shr_stream_fileType
! !PUBLIC MEMBER FUNCTIONS:
public :: shr_stream_init ! initialize a stream
public :: shr_stream_set ! set stream values
public :: shr_stream_default ! set default values
public :: shr_stream_parseInput ! extract fileName,yearAlign, etc. from a string
public :: shr_stream_findBounds ! return lower/upper bounding date info
public :: shr_stream_getFileFieldList ! return input-file field name list
public :: shr_stream_getModelFieldList ! return model field name list
public :: shr_stream_getFileFieldName ! return k-th input-file field name
public :: shr_stream_getModelFieldName ! return k-th model field name list
public :: shr_stream_getFirstFileName ! return the 1st file name in stream
public :: shr_stream_getNextFileName ! return next file in sequence
public :: shr_stream_getPrevFileName ! return previous file in sequence
public :: shr_stream_getFilePath ! return file path
public :: shr_stream_getDataSource ! return the stream's meta data
public :: shr_stream_getDomainInfo ! return the stream's domain info data
public :: shr_stream_getFile ! acquire file, return name of file to open
public :: shr_stream_getNFiles ! get the number of files in a stream
public :: shr_stream_getCalendar ! get the stream calendar
public :: shr_stream_dataDump ! internal stream data for debugging
public :: shr_stream_restWrite ! write a streams restart file
public :: shr_stream_restRead ! read a streams restart file
public :: shr_stream_setDebug ! set internal shr_stream debug level
public :: shr_stream_setAbort ! set internal shr_stream abort flag
public :: shr_stream_getDebug ! get internal shr_stream debug level
public :: shr_stream_isInit ! check if stream is initialized
! public :: shr_stream_bcast ! broadcast a stream (untested)
! !PUBLIC DATA MEMBERS:
! none
!EOP
character(SHR_KIND_CS),parameter,public :: shr_stream_taxis_cycle = 'cycle'
character(SHR_KIND_CS),parameter,public :: shr_stream_taxis_extend = 'extend'
character(SHR_KIND_CS),parameter,public :: shr_stream_taxis_limit = 'limit'
character(SHR_KIND_CS),parameter,public :: shr_stream_file_null = 'not_set'
!--- a useful derived type to use inside shr_stream_streamType ---
type shr_stream_fileType
character(SHR_KIND_CL) :: name ! the file name
logical :: haveData ! has t-coord data been read in?
integer (SHR_KIND_IN) :: nt ! size of time dimension
integer (SHR_KIND_IN),pointer :: date(:) ! t-coord date: yyyymmdd
integer (SHR_KIND_IN),pointer :: secs(:) ! t-coord secs: elapsed on date
end type shr_stream_fileType
!--- hard-coded array dims ~ could allocate these at run time ---
integer(SHR_KIND_IN),parameter :: nFileMax = 1000 ! max number of files
type shr_stream_streamType
!private ! no public access to internal components
!--- input data file names and data ---
logical :: init ! has stream been initialized?
integer (SHR_KIND_IN),pointer :: initarr(:)! surrogate for init flag
integer (SHR_KIND_IN) :: nFiles ! number of data files
character(SHR_KIND_CS) :: dataSource ! meta data identifying data source
character(SHR_KIND_CL) :: filePath ! remote location of data files
type(shr_stream_fileType) :: file(nFileMax) ! data specific to each file
!--- specifies how model dates align with data dates ---
integer(SHR_KIND_IN) :: yearFirst ! first year to use in t-axis (yyyymmdd)
integer(SHR_KIND_IN) :: yearLast ! last year to use in t-axis (yyyymmdd)
integer(SHR_KIND_IN) :: yearAlign ! align yearFirst with this model year
integer(SHR_KIND_IN) :: offset ! offset in seconds of stream data
character(SHR_KIND_CS) :: taxMode ! cycling option for time axis
!--- useful for quicker searching ---
integer(SHR_KIND_IN) :: k_lvd,n_lvd ! file/sample of least valid date
logical :: found_lvd ! T <=> k_lvd,n_lvd have been set
integer(SHR_KIND_IN) :: k_gvd,n_gvd ! file/sample of greatest valid date
logical :: found_gvd ! T <=> k_gvd,n_gvd have been set
!--- stream data not used by stream module itself ---
character(SHR_KIND_CX) :: fldListFile ! field list: file's field names
character(SHR_KIND_CX) :: fldListModel ! field list: model's field names
character(SHR_KIND_CL) :: domFilePath ! domain file: file path of domain file
character(SHR_KIND_CL) :: domFileName ! domain file: name
character(SHR_KIND_CS) :: domTvarName ! domain file: time-dim var name
character(SHR_KIND_CS) :: domXvarName ! domain file: x-dim var name
character(SHR_KIND_CS) :: domYvarName ! domain file: y-dim var ame
character(SHR_KIND_CS) :: domAreaName ! domain file: area var name
character(SHR_KIND_CS) :: domMaskName ! domain file: mask var name
character(SHR_KIND_CS) :: tInterpAlgo ! Algorithm to use for time interpolation
character(SHR_KIND_CL) :: calendar ! stream calendar
end type shr_stream_streamType
!----- parameters -----
real(SHR_KIND_R8) ,parameter :: spd = SHR_CONST_CDAY ! seconds per day
integer(SHR_KIND_IN),parameter :: initarr_size = 3 ! size of initarr
integer(SHR_KIND_IN),save :: debug = 0 ! edit/turn-on for debug write statements
logical ,save :: doabort = .true. ! flag if abort on error
!===============================================================================
contains
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_init -- initialize stream datatype, read description text file
!
! !DESCRIPTION:
!
! !REMARKS:
! should input be via standard Fortran namelist?
!
! !REVISION HISTORY:
! 2007-Sep-17 - B. Kauffman - reworked wrt new streams.txt format
! 2005-Feb-03 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_init(strm,infoFile,yearFirst,yearLast,yearAlign,taxMode,rc)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType) ,intent(out) :: strm ! data stream
character(*) ,intent(in) :: infoFile ! file with stream info, must read
integer (SHR_KIND_IN) ,intent(in) :: yearFirst ! first year to use
integer (SHR_KIND_IN) ,intent(in) :: yearLast ! last year to use
integer (SHR_KIND_IN) ,intent(in) :: yearAlign ! align yearFirst with this model year
character(*) ,optional,intent(in) :: taxMode ! time axis cycling option
integer (SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer (SHR_KIND_IN) :: n ! generic index
character(SHR_KIND_CL) :: str ! string to parse from input data file
integer (SHR_KIND_IN) :: int ! integer to parse from input data file
character(SHR_KIND_CL) :: subStr ! sub-string of interest
integer (SHR_KIND_IN) :: nUnit ! file i/o unit number
character(SHR_KIND_CS) :: startTag ! input file start tag
character(SHR_KIND_CS) :: endTag ! input file end tag
character(SHR_KIND_CS) :: fldNameFile ! field name in data file field list
character(SHR_KIND_CS) :: fldNameModel ! field name in model field list
character(SHR_KIND_CX) :: fldListFile ! list of data file fields, colon delim list
character(SHR_KIND_CX) :: fldListModel ! list of model fields, colon delim list
character(SHR_KIND_CL) :: calendar ! stream calendar
integer (SHR_KIND_IN) :: rCode, rCode2 ! return code
!----- formats -----
character(*),parameter :: subName = '(shr_stream_init) '
character(*),parameter :: F00 = "('(shr_stream_init) ',8a)"
!-------------------------------------------------------------------------------
! notes:
! * should this use standard namelist input?
! * needs more robust error checking
! o yearFirst,yearLast,yearAlign are provided by calling routine
! o parse infoFile for remaining, except for...
! o fileNT,fileDates, & fileSecs, which are initially set to -1, but but are replaced with
! valid values as each file is opened for the first time
!-------------------------------------------------------------------------------
rCode = 0
write(s_logunit,F00) 'Reading file ',trim(infoFile)
call shr_stream_default(strm)
strm%yearFirst = yearFirst
strm%yearLast = yearLast
strm%yearAlign = yearAlign
if (present(taxMode)) then
strm%taxMode = trim(taxMode)
endif
!-----------------------------------------------------------------------------
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' reading data source'
!-----------------------------------------------------------------------------
nUnit = shr_file_getUnit() ! get unused unit number
!--- find start tag ---
startTag = ""
endTag = ""
open(nUnit,file=infoFile,STATUS='OLD',FORM='FORMATTED',ACTION='READ',iostat=rCode)
if (rCode /= 0) goto 999
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode)
if (rCode /= 0) goto 999
!--- read data ---
read(nUnit,'(a)',END=999) str
call shr_string_leftAlign(str)
strm%dataSource = str
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' * format = ', trim(strm%dataSource)
close(nUnit)
call shr_file_freeUnit(nUnit)
!-----------------------------------------------------------------------------
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' reading field data variable names'
!-----------------------------------------------------------------------------
!--- find start tag ---
open(nUnit,file=infoFile,STATUS='OLD',FORM='FORMATTED',ACTION='READ')
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode)
if (rCode /= 0) goto 999
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode)
if (rCode /= 0) goto 999
!--- read data ---
n=0
do while (.true.)
read(nUnit,'(a)',END=999) str
call shr_string_leftAlign(str)
n=n+1
if (str(1:len_trim(endTag)) == trim(endTag)) exit
fldNameFile = ""
fldNameModel = ""
read(str,*,iostat=rCode) fldNameFile,fldNameModel
if (len_trim(fldNameFile)==0 .or. len_trim(fldNameModel)==0 ) then
rCode = 1
write(s_logunit,F00) "ERROR: reading field names"
write(s_logunit,F00) '* fldNameFile = ',trim(fldNameFile)
write(s_logunit,F00) '* fldNameModel = ',trim(fldNameModel)
call shr_stream_abort(subName//"ERROR: reading field names")
end if
if (n==1) then
strm%fldListFile = trim(fldNameFile )
strm%fldListModel = trim(fldNameModel)
else
strm%fldListFile = trim(strm%fldListFile ) // ":" // trim(fldNameFile )
strm%fldListModel = trim(strm%fldListModel) // ":" // trim(fldNameModel)
end if
end do
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' * file field list = ',trim(strm%fldListFile )
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' * model field list = ',trim(strm%fldListModel)
if (n==0) then
rCode = 1
write(s_logunit,F00) "ERROR: no input field names"
call shr_stream_abort(subName//"ERROR: no input field names")
end if
close(nUnit)
!-----------------------------------------------------------------------------
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' reading time-interpolation alogrithm '
!-----------------------------------------------------------------------------
!--- find start tag ---
open(nUnit,file=infoFile,STATUS='OLD',FORM='FORMATTED',ACTION='READ')
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
close(nUnit)
!-----------------------------------------------------------------------------
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' reading offset'
!-----------------------------------------------------------------------------
!--- find start tag ---
open(nUnit,file=infoFile,STATUS='OLD',FORM='FORMATTED',ACTION='READ')
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,optionalTag=.true.,rc=rCode2)
if (rCode2 == 0) then
!--- read data ---
read(nUnit,*,END=999) int
strm%offset = int
else
strm%offset = 0
end if
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' * offset ',strm%offset
close(nUnit)
!-----------------------------------------------------------------------------
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' reading data file path'
!-----------------------------------------------------------------------------
!--- find start tag ---
open(nUnit,file=infoFile,STATUS='OLD',FORM='FORMATTED',ACTION='READ')
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
!--- read data ---
read(nUnit,'(a)',END=999) str
call shr_string_leftAlign(str)
n = len_trim(str)
if (n>0 .and. str(n:n) /= '/') str(n+1:n+2) = "/ " ! must have trailing slash
if (n==0) str = "./ " ! null path => ./
strm%FilePath = str
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' * data file path = ', trim(strm%FilePath)
close(nUnit)
!-----------------------------------------------------------------------------
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' reading field data file names'
!-----------------------------------------------------------------------------
!--- find start tag ---
open(nUnit,file=infoFile,STATUS='OLD',FORM='FORMATTED',ACTION='READ')
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
!--- read data ---
n=0
do while (.true.)
read(nUnit,'(a)',END=999) str
call shr_string_leftAlign(str)
if (str(1:len_trim(endTag)) == trim(endTag)) exit
n=n+1
if (n > nFileMax) then
rCode = 1
write(s_logunit,F00) "ERROR: exceeded max number of files"
call shr_stream_abort(subName//"ERROR: exceeded max number of files")
if ( present(rc) ) rc = rCode
close(nUnit)
call shr_file_freeUnit(nUnit)
return
end if
strm%file(n)%name = str
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' * ',trim(strm%file(n)%name)
end do
strm%nFiles = n
if (n==0) then
rCode = 1
write(s_logunit,F00) "ERROR: no input file names"
call shr_stream_abort(subName//"ERROR: no input file names")
end if
close(nUnit)
!-----------------------------------------------------------------------------
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' reading domain data variable names'
!-----------------------------------------------------------------------------
!--- find start tag ---
open(nUnit,file=infoFile,STATUS='OLD',FORM='FORMATTED',ACTION='READ')
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
!--- read data ---
n=0
do while (.true.)
read(nUnit,'(a)',END=999) str
call shr_string_leftAlign(str)
n=n+1
if (str(1:len_trim(endTag)) == trim(endTag)) exit
fldNameFile = ""
fldNameModel = ""
read(str,*,iostat=rCode2) fldNameFile,fldNameModel
if (len_trim(fldNameFile)==0 .or. len_trim(fldNameModel)==0 ) then
rCode = 1
write(s_logunit,F00) "ERROR: reading field names"
write(s_logunit,F00) '* fldNameFile = ',trim(fldNameFile)
write(s_logunit,F00) '* fldNameModel = ',trim(fldNameModel)
call shr_stream_abort(subName//"ERROR: reading field names")
end if
if (n==1) then
fldListFile = trim(fldNameFile )
fldListModel = trim(fldNameModel)
else
fldListFile = trim(fldListFile ) // ":" // trim(fldNameFile )
fldListModel = trim(fldListModel) // ":" // trim(fldNameModel)
end if
end do
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' * file field list = ',trim(fldListFile )
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' * model field list = ',trim(fldListModel)
if (n==0) then
rCode = 1
write(s_logunit,F00) "ERROR: no input field names"
call shr_stream_abort(subName//"ERROR: no input field names")
else
!--- get time variable name ---
n = shr_string_listGetIndexF(fldListModel,"time")
if (n==0) then
rCode = 1
write(s_logunit,F00) "ERROR: no input field names"
call shr_stream_abort(subName//"ERROR: no time variable name")
else
call shr_string_listGetName (fldListFile,n,substr,rc)
strm%domTvarName = subStr
endif
!--- get longitude variable name ---
n = shr_string_listGetIndexF(fldListModel,"lon")
if (n==0) then
rCode = 1
write(s_logunit,F00) "ERROR: no input field names"
call shr_stream_abort(subName//"ERROR: no lon variable name")
else
call shr_string_listGetName (fldListFile,n,substr,rc)
strm%domXvarName = subStr
endif
!--- get latitude variable name ---
n = shr_string_listGetIndexF(fldListModel,"lat")
if (n==0) then
rCode = 1
write(s_logunit,F00) "ERROR: no input field names"
call shr_stream_abort(subName//"ERROR: no lat variable name")
else
call shr_string_listGetName (fldListFile,n,substr,rc)
strm%domYvarName = subStr
endif
!--- get area variable name ---
n = shr_string_listGetIndexF(fldListModel,"area")
if (n==0) then
! rCode = 1
! write(s_logunit,F00) "ERROR: no input field names"
! call shr_stream_abort(subName//"ERROR: no area variable name")
strm%domAreaName = 'unknownname'
else
call shr_string_listGetName (fldListFile,n,substr,rc)
strm%domAreaName = subStr
endif
!--- get mask variable name ---
n = shr_string_listGetIndexF(fldListModel,"mask")
if (n==0) then
! rCode = 1
! write(s_logunit,F00) "ERROR: no input field names"
! call shr_stream_abort(subName//"ERROR: no mask variable name")
strm%domMaskName = 'unknownname'
else
call shr_string_listGetName (fldListFile,n,substr,rc)
strm%domMaskName = subStr
endif
end if
close(nUnit)
!-----------------------------------------------------------------------------
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' reading domain data file path'
!-----------------------------------------------------------------------------
!--- find start tag ---
startTag = ""
endTag = ""
open(nUnit,file=infoFile,STATUS='OLD',FORM='FORMATTED',ACTION='READ')
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
!--- read data ---
read(nUnit,'(a)',END=999) str
call shr_string_leftAlign(str)
n = len_trim(str)
if (n>0 .and. str(n:n) /= '/') str(n+1:n+2) = "/ " ! must have trailing slash
if (n==0) str = "./ " ! null path => ./
strm%domFilePath = str
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' * data file path = ', trim(strm%domFilePath)
close(nUnit)
!-----------------------------------------------------------------------------
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' reading domain data file name'
!-----------------------------------------------------------------------------
!--- find start tag ---
open(nUnit,file=infoFile,STATUS='OLD',FORM='FORMATTED',ACTION='READ')
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
startTag = ""
endTag = ""
call shr_stream_readUpToTag(nUnit,startTag,rc=rCode2)
if (rCode2 /= 0)then
rCode = rCode2
goto 999
end if
!--- read data ---
read(nUnit,'(a)',END=999) str
call shr_string_leftAlign(str)
strm%domFileName = str
if (debug>0 .and. s_loglev>0) write(s_logunit,F00) ' * ',trim(strm%domFileName)
close(nUnit)
!-----------------------------------------------------------------------------
! get initial calendar value
!-----------------------------------------------------------------------------
call shr_stream_getCalendar(strm,1,calendar)
strm%calendar = trim(calendar)
!-----------------------------------------------------------------------------
! normal return or end-of-file problem?
!-----------------------------------------------------------------------------
call shr_stream_setInit(strm)
if ( present(rc) ) rc = rCode
call shr_file_freeUnit(nUnit)
return
999 continue
write(s_logunit,F00) "ERROR: unexpected end-of-file while reading ",trim(startTag)
write(s_logunit,F00) " error code = ", rCode
call shr_stream_abort(subName//"ERROR: unexpected end-of-file")
close(nUnit)
if ( present(rc) ) rc = rCode
call shr_file_freeUnit(nUnit)
end subroutine shr_stream_init
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_set -- set values of stream datatype
!
! !DESCRIPTION:
!
! !REMARKS:
! set or override stream settings
!
! !REVISION HISTORY:
! 2010-Apr-20 - T. Craig - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_set(strm,yearFirst,yearLast,yearAlign,offset,taxMode, &
fldListFile,fldListModel,domFilePath,domFileName, &
domTvarName,domXvarName,domYvarName,domAreaName,domMaskName, &
filePath,filename,dataSource,rc)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType) ,intent(inout) :: strm ! data stream
integer (SHR_KIND_IN),optional,intent(in) :: yearFirst ! first year to use
integer (SHR_KIND_IN),optional,intent(in) :: yearLast ! last year to use
integer (SHR_KIND_IN),optional,intent(in) :: yearAlign ! align yearFirst with this model year
integer (SHR_KIND_IN),optional,intent(in) :: offset ! offset in seconds of stream data
character(*) ,optional,intent(in) :: taxMode ! time axis mode
character(*) ,optional,intent(in) :: fldListFile ! file field names, colon delim list
character(*) ,optional,intent(in) :: fldListModel ! model field names, colon delim list
character(*) ,optional,intent(in) :: domFilePath ! domain file path
character(*) ,optional,intent(in) :: domFileName ! domain file name
character(*) ,optional,intent(in) :: domTvarName ! domain time dim name
character(*) ,optional,intent(in) :: domXvarName ! domain x dim name
character(*) ,optional,intent(in) :: domYvarName ! domain y dim nam
character(*) ,optional,intent(in) :: domAreaName ! domain area name
character(*) ,optional,intent(in) :: domMaskName ! domain mask name
character(*) ,optional,intent(in) :: filePath ! path for filenames
character(*) ,optional,intent(in) :: filename(:) ! input filenames
character(*) ,optional,intent(in) :: dataSource ! comment line
integer (SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: n
character(SHR_KIND_CL) :: calendar ! stream calendar
!----- formats -----
character(*),parameter :: subName = '(shr_stream_set) '
character(*),parameter :: F00 = "('(shr_stream_set) ',8a)"
character(*),parameter :: F01 = "('(shr_stream_set) ',1a,i6)"
!-------------------------------------------------------------------------------
call shr_stream_default(strm)
if ( present(rc) ) rc = 0
if (present(yearFirst)) then
strm%yearFirst = yearFirst
endif
if (present(yearLast)) then
strm%yearLast = yearLast
endif
if (present(yearAlign)) then
strm%yearAlign = yearAlign
endif
if (present(offset)) then
strm%offset = offset
endif
if (present(taxMode)) then
strm%taxMode = trim(taxMode)
endif
if (present(fldListFile)) then
strm%fldListFile = trim(fldListFile)
endif
if (present(fldListModel)) then
strm%fldListModel = trim(fldListModel)
endif
if (present(domFilePath)) then
strm%domFilePath = trim(domFilePath)
endif
if (present(domFileName)) then
strm%domFileName = trim(domFileName)
endif
if (present(domTvarName)) then
strm%domTvarName = trim(domTvarName)
endif
if (present(domXvarName)) then
strm%domXvarName = trim(domXvarName)
endif
if (present(domYvarName)) then
strm%domYvarName = trim(domYvarName)
endif
if (present(domAreaName)) then
strm%domAreaName = trim(domAreaName)
endif
if (present(domMaskName)) then
strm%domMaskName = trim(domMaskName)
endif
if (present(filePath)) then
strm%filePath = trim(filePath)
endif
if (present(filename)) then
write(s_logunit,F01) "size of filename = ",size(filename)
write(s_logunit,F00) "filename = ",filename
do n = 1,size(filename)
if (trim(filename(n)) == trim(shr_stream_file_null)) then
! ignore it
else
if (n > nFileMax) then
write(s_logunit,F00) "ERROR: exceeded max number of files"
call shr_stream_abort(subName//"ERROR: exceeded max number of files")
if ( present(rc) ) rc = 1
return
endif
strm%nFiles = n
strm%file(n)%name = trim(filename(n))
endif
enddo
endif
!-----------------------------------------------------------------------------
! get initial calendar value
!-----------------------------------------------------------------------------
call shr_stream_getCalendar(strm,1,calendar)
strm%calendar = trim(calendar)
call shr_stream_setInit(strm)
end subroutine shr_stream_set
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_default -- set defaults for stream
!
! !DESCRIPTION:
!
! !REMARKS:
! set basic default values for streams
!
! !REVISION HISTORY:
! 2010-Oct-20 - T. Craig - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_default(strm,rc)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType) ,intent(inout) :: strm ! data stream
integer (SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: n
!----- formats -----
character(*),parameter :: subName = '(shr_stream_default) '
character(*),parameter :: F00 = "('(shr_stream_default) ',8a)"
character(*),parameter :: F01 = "('(shr_stream_default) ',1a,i6)"
!-------------------------------------------------------------------------------
!-----------------------------------------------------------------------------
! set default values for everything in stream
!-----------------------------------------------------------------------------
call shr_stream_clearInit(strm)
strm%nFiles = 0
strm%dataSource = 'undefined'
strm%filePath = ' '
do n=1,nFileMax
strm%file%name = trim(shr_stream_file_null)
strm%file%haveData = .false.
strm%file%nt = 0
! strm%file%date = undefined ! note: unallocated
! strm%file%secs = undefined ! note: unallocated
end do
strm%yearFirst = 0
strm%yearLast = 0
strm%yearAlign = 0
strm%offset = 0
strm%taxMode = trim(shr_stream_taxis_cycle)
strm%k_lvd = -1
strm%n_lvd = -1
strm%found_lvd = .false.
strm%k_gvd = -1
strm%n_gvd = -1
strm%found_gvd = .false.
strm%fldListFile = ' '
strm%fldListModel = ' '
strm%domFilePath = ' '
strm%domFileName = ' '
strm%domTvarName = ' '
strm%domXvarName = ' '
strm%domYvarName = ' '
strm%domAreaName = ' '
strm%domMaskName = ' '
strm%calendar = shr_cal_noleap
if ( present(rc) ) rc = 0
end subroutine shr_stream_default
!===============================================================================
subroutine shr_stream_readUpToTag(nUnit,tag,optionalTag,rc)
!----- input/output -----
integer(SHR_KIND_IN),intent(in ) :: nUnit ! i/o unit to read from
character(*) ,intent(in ) :: tag ! string to search for
logical, optional ,intent(in ) :: optionalTag ! this is an optional tag
integer(SHR_KIND_IN),intent(out) :: rc ! return code
!----- local -----
character(SHR_KIND_CL) :: str ! temp char string
logical :: localOptionalTag ! local version of optionalTag
!----- formats -----
character(*),parameter :: subName = '(shr_stream_readUpToTag) '
character(*),parameter :: F00 = "('(shr_stream_readUpToTag) ',8a)"
!-------------------------------------------------------------------------------
! Note: does not rewind to start of file
!-------------------------------------------------------------------------------
rc = 1
localOptionalTag = .false.
if (present(optionalTag)) localOptionalTag = optionalTag
do while (.true.)
read(nUnit,'(a)',END=999) str
str = adjustL(str)
if (str(1:len_trim(adjustL(tag))) == trim(adjustL(tag))) then
rc = 0
exit
end if
end do
999 continue
if (rc /= 0 .and. .not. localOptionalTag ) then
write(s_logunit,F00) "ERROR: tag not found: ",trim(tag)
call shr_stream_abort(subName//"ERROR: tag not found")
end if
end subroutine shr_stream_readUpToTag
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_parseInput -- extract fileName,yearAlign, etc. from a string
!
! !DESCRIPTION:
! shr_stream_parseInput -- extract fileName,yearAlign, etc. from a string
!
! !REMARKS:
! should input be via standard Fortran namelist?
!
! !REVISION HISTORY:
! 2007-Aug-01 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_parseInput(str,fileName,yearAlign,yearFirst,yearLast,rc)
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: str ! string to parse
character(*) ,intent(out) :: fileName ! file name
integer (SHR_KIND_IN) ,intent(out) :: yearFirst ! first year to use
integer (SHR_KIND_IN) ,intent(out) :: yearLast ! last year to use
integer (SHR_KIND_IN) ,intent(out) :: yearAlign ! align yearFirst with this model year
integer (SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer (SHR_KIND_IN) :: n ! generic index
character(SHR_KIND_CL) :: str2 ! temp work string
!----- formats -----
character(*),parameter :: subName = '(shr_stream_parseInput) '
character(*),parameter :: F00 = "('(shr_stream_parseInput) ',8a)"
character(*),parameter :: F01 = "('(shr_stream_parseInput) ',a,3i10)"
!-------------------------------------------------------------------------------
! notes:
! - this routine exists largely because of the difficulty of reading file names
! that include dir paths, ie. containing "/", from char strings
! because the "/" is interpreted as an end-of-record.
!-------------------------------------------------------------------------------
if (debug>1 .and. s_loglev > 0) write(s_logunit,F00) "str = ",trim(str)
str2 = adjustL(str)
n = index(str2," ")
fileName = str2(:n)
read(str2(n:),*) yearAlign,yearFirst,yearLast
if (debug>1 .and. s_loglev > 0) then
write(s_logunit,F00) "fileName = ",trim(fileName)
write(s_logunit,F01) "yearAlign = ",yearAlign
write(s_logunit,F01) "yearFirst = ",yearFirst
write(s_logunit,F01) "yearLast = ",yearLast
end if
if (present(rc)) rc = 0
end subroutine shr_stream_parseInput
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_findBounds -- find stream data bounding a model date
!
! !DESCRIPTION:
! Given a stream and a model date, find time coordinates of the upper and
! lower time bounds surrounding the models date. Returns the model date,
! data date, elasped seconds, time index, and file names associated with
! these upper and lower time bounds.
!
! !REVISION HISTORY:
! 2009-Sep-01 - T. Craig - modified
! 2005-Apr-01 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_findBounds(strm,mDateIn, secIn, &
& mDateLB,dDateLB,secLB,n_lb,fileLB, &
& mDateUB,dDateUB,secUB,n_ub,fileUB )
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType),intent(inout):: strm ! data stream to query
integer(SHR_KIND_IN) ,intent(in) :: mDateIn ! model date (yyyymmdd)
integer(SHR_KIND_IN) ,intent(in) :: secIn ! elapsed sec on model date
integer(SHR_KIND_IN) ,intent(out) :: mDateLB ! model date of LB
integer(SHR_KIND_IN) ,intent(out) :: dDateLB ! data date of LB
integer(SHR_KIND_IN) ,intent(out) :: secLB ! elap sec of LB
integer(SHR_KIND_IN) ,intent(out) :: n_lb ! t-coord index of LB
character(*) ,intent(out) :: fileLB ! file containing LB
integer(SHR_KIND_IN) ,intent(out) :: mDateUB ! model date of UB
integer(SHR_KIND_IN) ,intent(out) :: dDateUB ! data date of UB
integer(SHR_KIND_IN) ,intent(out) :: secUB ! elap sec of UB
integer(SHR_KIND_IN) ,intent(out) :: n_ub ! t-coord index of UB
character(*) ,intent(out) :: fileUB ! file containing UB
!EOP
!----- local -----
character(SHR_KIND_CL) :: fileName ! string
integer (SHR_KIND_IN) :: nt ! size of a time-coord dimension
integer (SHR_KIND_IN) :: dDateIn ! model date mapped onto a data date
integer (SHR_KIND_IN) :: dDateF ! first date
integer (SHR_KIND_IN) :: dDateL ! last date
integer (SHR_KIND_IN) :: n,nf ! loop index wrt t-coord array within one file
integer (SHR_KIND_IN) :: k,kf ! loop index wrt list of files
integer (SHR_KIND_IN) :: k_ub,k_lb ! file index of U/L bounds
integer (SHR_KIND_IN) :: rCode ! return code
integer (SHR_KIND_IN) :: mYear ! year of model date
integer (SHR_KIND_IN) :: yrFirst ! first year of data loop
integer (SHR_KIND_IN) :: yrLast ! last year of data loop
integer (SHR_KIND_IN) :: yrAlign ! model year that aligns with yearFirst
integer (SHR_KIND_IN) :: nYears ! number of years in data loop
integer (SHR_KIND_IN) :: dYear ! data year corresponding to model year
integer (SHR_KIND_IN) :: yy,mm,dd ! year,month,day
real (SHR_KIND_R8) :: rDateIn ! model dDateIn + secs/(secs per day)
real (SHR_KIND_R8) :: rDate1 ! stream dDateIn + secs/(secs per day)
real (SHR_KIND_R8) :: rDate2 ! stream dDateIn + secs/(secs per day)
real (SHR_KIND_R8) :: rDatelvd ! lvd dDate + secs/(secs per day)
real (SHR_KIND_R8) :: rDategvd ! gvd dDate + secs/(secs per day)
logical :: cycle ! is cycling on or off
logical :: limit ! is limiting on or off
!----- formats -----
character(*),parameter :: subName = '(shr_stream_findBounds) '
character(*),parameter :: F00 = "('(shr_stream_findBounds) ',8a)"
character(*),parameter :: F01 = "('(shr_stream_findBounds) ',a,i9.8,a)"
character(*),parameter :: F02 = "('(shr_stream_findBounds) ',a,2i9.8,i6,i5,1x,a)"
character(*),parameter :: F03 = "('(shr_stream_findBounds) ',a,i4)"
character(*),parameter :: F04 = "('(shr_stream_findBounds) ',2a,i4)"
!-------------------------------------------------------------------------------
! Purpose:
! 1) take the model date, map it into the data date range
! 2) find the upper and lower bounding data dates
! 3) return the bounding data and model dates, file names, & t-coord indicies
!-------------------------------------------------------------------------------
if (debug>0 .and. s_loglev > 0) write(s_logunit,F02) "DEBUG: ---------- enter ------------------"
rCode = 0
if ( .not. shr_stream_isInit(strm)) then
rCode = 1
call shr_stream_abort(trim(subName)//" ERROR: trying to find bounds of uninitialized stream")
return
end if
if (trim(strm%taxMode) == trim(shr_stream_taxis_cycle)) then
cycle = .true.
limit = .false.
elseif (trim(strm%taxMode) == trim(shr_stream_taxis_extend)) then
cycle = .false.
limit = .false.
elseif (trim(strm%taxMode) == trim(shr_stream_taxis_limit)) then
cycle = .false.
limit = .true.
else
write(s_logunit,*) trim(subName),' ERROR: illegal taxMode = ',trim(strm%taxMode)
call shr_stream_abort(trim(subName)//' ERROR: illegal taxMode = '//trim(strm%taxMode))
endif
!----------------------------------------------------------------------------
! convert/map the model year/date into a data year/date
! note: these values will be needed later to convert data year to model year
!----------------------------------------------------------------------------
mYear = mDateIn/10000 ! assumes/require F90 truncation
yrFirst = strm%yearFirst ! first year in data sequence
yrLast = strm%yearLast ! last year in data sequence
yrAlign = strm%yearAlign ! model year corresponding to yearFirst
nYears = yrLast - yrFirst + 1 ! number of years in data sequence
dDateF = yrFirst * 10000 + 101 ! first date in valid range
dDateL = (yrLast+1) * 10000 + 101 ! last date in valid range
if (cycle) then
dYear = yrFirst + modulo(mYear-yrAlign+(2*nYears),nYears) ! current data year
else
dYear = yrFirst + mYear - yrAlign
endif
if (dYear < 0) then
write(s_logunit,*) trim(subName),' ERROR: dyear lt zero = ',dYear
call shr_stream_abort(trim(subName)//' ERROR: dyear lt one')
endif
dDateIn = dYear*10000 + modulo(mDateIn,10000) ! mDateIn mapped to range of data years
rDateIn = dDateIn + secIn/spd ! dDateIn + fraction of a day
! write(s_logunit,*) 'tcx fbd1 ',mYear,dYear,dDateIn,rDateIn
! write(s_logunit,*) 'tcx fbd2 ',yrFirst,yrLast,yrAlign,nYears
! call shr_sys_flush(s_logunit)
!----------------------------------------------------------------------------
! find least valid date (lvd)
!----------------------------------------------------------------------------
if (.not. strm%found_lvd) then
A: do k=1,strm%nFiles
if (.not. strm%file(k)%haveData) then
call shr_stream_readtCoord(strm, k, rCode)
if ( rCode /= 0 )then
call shr_stream_abort(trim(subName)//" ERROR: readtCoord1")
return
end if
end if
do n=1,strm%file(k)%nt
if ( dDateF <= strm%file(k)%date(n) ) then
!--- found a date in or beyond yearFirst ---
strm%k_lvd = k
strm%n_lvd = n
strm%found_lvd = .true.
exit A
end if
end do
end do A
if (.not. strm%found_lvd) then
rCode = 1
write(s_logunit,F00) "ERROR: LVD not found, all data is before yearFirst"
call shr_stream_abort(trim(subName)//" ERROR: LVD not found, all data is before yearFirst")
else
!--- LVD is in or beyond yearFirst, verify it is not beyond yearLast ---
if ( dDateL <= strm%file(strm%k_lvd)%date(strm%n_lvd) ) then
rCode = 1
write(s_logunit,F00) "ERROR: LVD not found, all data is after yearLast"
call shr_stream_abort(trim(subName)//" ERROR: LVD not found, all data is after yearLast")
end if
end if
if (debug>1 .and. s_loglev > 0) then
if (strm%found_lvd) write(s_logunit,F01) "DEBUG: found LVD = ",strm%file(k)%date(n)
end if
end if
if (strm%found_lvd) then
k = strm%k_lvd
n = strm%n_lvd
rDatelvd = strm%file(k)%date(n) + strm%file(k)%secs(n)/spd ! LVD date + frac day
else
write(s_logunit,F00) "ERROR: LVD not found yet"
call shr_stream_abort(trim(subName)//" ERROR: LVD not found yet")
endif
if (strm%found_gvd) then
k = strm%k_gvd
n = strm%n_gvd
rDategvd = strm%file(k)%date(n) + strm%file(k)%secs(n)/spd ! GVD date + frac day
else
rDategvd = 99991231.0
endif
! write(s_logunit,*) 'tcx fbd3 ',rDateIn,rDatelvd,rDategvd
! call shr_sys_flush(s_logunit)
!-----------------------------------------------------------
! dateIn < rDatelvd
! limit -> abort
! extend -> use lvd value, set LB to 00000101
! cycle -> lvd is UB, gvd is LB, shift mDateLB by -nYears
!-----------------------------------------------------------
if (rDateIn < rDatelvd) then
if (limit) then
write(s_logunit,*) trim(subName)," ERROR: limit on and rDateIn lt rDatelvd",rDateIn,rDatelvd
call shr_stream_abort(trim(subName)//" ERROR: rDateIn lt rDatelvd limit true")
return
endif
if (.not.cycle) then
k_lb = strm%k_lvd
n_lb = strm%n_lvd
dDateLB = 00000101
mDateLB = 00000101
secLB = 0
fileLB = strm%file(k_lb)%name
k_ub = strm%k_lvd
n_ub = strm%n_lvd
dDateUB = strm%file(k_ub)%date(n_ub)
call shr_cal_date2ymd(dDateUB,yy,mm,dd)
yy = yy + (mYear-dYear)
call shr_cal_ymd2date(yy,mm,dd,mDateUB)
secUB = strm%file(k_ub)%secs(n_ub)
fileUB = strm%file(k_ub)%name
! write(s_logunit,*)'tcx fb1 ',n_lb,mDateLB,secLB,n_ub,mDateUB,secUB
! call shr_sys_flush(s_logunit)
return
endif
if (cycle) then
!--- find greatest valid date (GVD) ---
if (.not. strm%found_gvd) then
!--- start search at last file & move toward first file ---
B: do k=strm%nFiles,1,-1
!--- read data for file number k ---
if (.not. strm%file(k)%haveData) then
call shr_stream_readtCoord(strm, k, rCode)
if ( rCode /= 0 )then
call shr_stream_abort(trim(subName)//" ERROR: readtCoord2")
return
end if
end if
!--- start search at greatest date & move toward least date ---
do n=strm%file(k)%nt,1,-1
if ( strm%file(k)%date(n) < dDateL ) then
strm%k_gvd = k
strm%n_gvd = n
strm%found_gvd = .true.
rDategvd = strm%file(k)%date(n) + strm%file(k)%secs(n)/spd ! GVD date + frac day
if (debug>1 .and. s_loglev > 0) write(s_logunit,F01) "DEBUG: found GVD ",strm%file(k)%date(n)
exit B
end if
end do
end do B
end if
if (.not. strm%found_gvd) then
write(s_logunit,F00) "ERROR: GVD not found1"
call shr_stream_abort(trim(subName)//" ERROR: GVD not found1")
endif
k_lb = strm%k_gvd
n_lb = strm%n_gvd
dDateLB = strm%file(k_lb)%date(n_lb)
call shr_cal_date2ymd(dDateLB,yy,mm,dd)
yy = yy + (mYear-dYear-nYears)
call shr_cal_ymd2date(yy,mm,dd,mDateLB)
secLB = strm%file(k_lb)%secs(n_lb)
fileLB = strm%file(k_lb)%name
k_ub = strm%k_lvd
n_ub = strm%n_lvd
dDateUB = strm%file(k_ub)%date(n_ub)
call shr_cal_date2ymd(dDateUB,yy,mm,dd)
yy = yy + (mYear-dYear)
call shr_cal_ymd2date(yy,mm,dd,mDateUB)
secUB = strm%file(k_ub)%secs(n_ub)
fileUB = strm%file(k_ub)%name
! write(s_logunit,*)'tcx fb2 ',n_lb,mDateLB,secLB,n_ub,mDateUB,secUB
! call shr_sys_flush(s_logunit)
return
endif
!-----------------------------------------------------------
! dateIn > rDategvd
! limit -> abort
! extend -> use gvd value, set UB to 99991231
! cycle -> lvd is UB, gvd is LB, shift mDateLB by +nYears
!-----------------------------------------------------------
else if (strm%found_gvd .and. rDateIn >= rDategvd) then
if (limit) then
write(s_logunit,*) trim(subName)," ERROR: limit on and rDateIn gt rDategvd",rDateIn,rDategvd
call shr_stream_abort(trim(subName)//" ERROR: rDateIn gt rDategvd limit true")
return
endif
if (.not.cycle) then
k_lb = strm%k_gvd
n_lb = strm%n_gvd
dDateLB = strm%file(k_lb)%date(n_lb)
call shr_cal_date2ymd(dDateLB,yy,mm,dd)
yy = yy + (mYear-dYear)
call shr_cal_ymd2date(yy,mm,dd,mDateLB)
secLB = strm%file(k_lb)%secs(n_lb)
fileLB = strm%file(k_lb)%name
k_ub = strm%k_gvd
n_ub = strm%n_gvd
dDateUB = 99991231
mDateUB = 99991231
secUB = 0
fileUB = strm%file(k_ub)%name
! write(s_logunit,*)'tcx fb3 ',n_lb,mDateLB,secLB,n_ub,mDateUB,secUB
! call shr_sys_flush(s_logunit)
return
endif
if (cycle) then
k_lb = strm%k_gvd
n_lb = strm%n_gvd
dDateLB = strm%file(k_lb)%date(n_lb)
call shr_cal_date2ymd(dDateLB,yy,mm,dd)
yy = yy + (mYear-dYear)
call shr_cal_ymd2date(yy,mm,dd,mDateLB)
secLB = strm%file(k_lb)%secs(n_lb)
fileLB = strm%file(k_lb)%name
k_ub = strm%k_lvd
n_ub = strm%n_lvd
dDateUB = strm%file(k_ub)%date(n_ub)
call shr_cal_date2ymd(dDateUB,yy,mm,dd)
yy = yy + (mYear-dYear+nYears)
call shr_cal_ymd2date(yy,mm,dd,mDateUB)
secUB = strm%file(k_ub)%secs(n_ub)
fileUB = strm%file(k_ub)%name
! write(s_logunit,*)'tcx fb4 ',n_lb,mDateLB,secLB,n_ub,mDateUB,secUB
! call shr_sys_flush(s_logunit)
return
endif
else
!-----------------------------------------------------------
! dateIn > rDatelvd
!-----------------------------------------------------------
k_lb = strm%k_lvd
n_lb = strm%n_lvd
C: do k=strm%k_lvd,strm%nFiles
!--- read data for file number k ---
if (.not. strm%file(k)%haveData) then
call shr_stream_readtCoord(strm, k, rCode)
if ( rCode /= 0 )then
call shr_stream_abort(trim(subName)//" ERROR: readtCoord3")
return
end if
end if
!--- examine t-coords for file k ---
n = strm%file(k)%nt ! last t-index in file
rDate1 = strm%file(k)%date(n) + strm%file(k)%secs(n)/spd ! last date + frac day
if (.not. strm%found_gvd) then
n = strm%file(k)%nt
if (dDateL <= strm%file(k)%date(n)) then
!--- set gvd to last timestep in previous file then advance through current file ---
if (k > 1) then
strm%k_gvd = k-1
strm%n_gvd = strm%file(k-1)%nt
strm%found_gvd = .true.
endif
do n=1,strm%file(k)%nt
if ( strm%file(k)%date(n) < dDateL ) then
strm%k_gvd = k
strm%n_gvd = n
strm%found_gvd = .true.
endif
enddo
elseif (k == strm%nFiles) then
strm%k_gvd = k
strm%n_gvd = strm%file(k)%nt
strm%found_gvd = .true.
end if
if (strm%found_gvd) then
kf = strm%k_gvd
nf = strm%n_gvd
rDategvd = strm%file(kf)%date(nf) + strm%file(kf)%secs(nf)/spd ! GVD date + frac day
endif
end if
!-----------------------------------------------------------
! dateIn > rDategvd
! limit -> abort
! extend -> use gvd value, set UB to 99991231
! cycle -> lvd is UB, gvd is LB, shift mDateLB by nYears
!-----------------------------------------------------------
if (strm%found_gvd .and. rDateIn >= rDategvd) then
if (limit) then
write(s_logunit,*) trim(subName)," ERROR: limit on and rDateIn gt rDategvd",rDateIn,rDategvd
call shr_stream_abort(trim(subName)//" ERROR: rDateIn gt rDategvd limit true")
return
endif
if (.not.cycle) then
k_lb = strm%k_gvd
n_lb = strm%n_gvd
dDateLB = strm%file(k_lb)%date(n_lb)
call shr_cal_date2ymd(dDateLB,yy,mm,dd)
yy = yy + (mYear-dYear)
call shr_cal_ymd2date(yy,mm,dd,mDateLB)
secLB = strm%file(k_lb)%secs(n_lb)
fileLB = strm%file(k_lb)%name
k_ub = strm%k_gvd
n_ub = strm%n_gvd
dDateUB = 99991231
mDateUB = 99991231
secUB = 0
fileUB = strm%file(k_ub)%name
! write(s_logunit,*)'tcx fb5 ',n_lb,mDateLB,secLB,n_ub,mDateUB,secUB
! call shr_sys_flush(s_logunit)
return
endif
if (cycle) then
k_lb = strm%k_gvd
n_lb = strm%n_gvd
dDateLB = strm%file(k_lb)%date(n_lb)
call shr_cal_date2ymd(dDateLB,yy,mm,dd)
yy = yy + (mYear-dYear)
call shr_cal_ymd2date(yy,mm,dd,mDateLB)
secLB = strm%file(k_lb)%secs(n_lb)
fileLB = strm%file(k_lb)%name
k_ub = strm%k_lvd
n_ub = strm%n_lvd
dDateUB = strm%file(k_ub)%date(n_ub)
call shr_cal_date2ymd(dDateUB,yy,mm,dd)
yy = yy + (mYear-dYear+nYears)
call shr_cal_ymd2date(yy,mm,dd,mDateUB)
secUB = strm%file(k_ub)%secs(n_ub)
fileUB = strm%file(k_ub)%name
! write(s_logunit,*)'tcx fb6 ',n_lb,mDateLB,secLB,n_ub,mDateUB,secUB
! call shr_sys_flush(s_logunit)
return
endif
endif
if ( rDate1 < rDateIn ) then
!--- increment lb and continue to search ---
k_lb = k
n_lb = strm%file(k)%nt
else
!--- the greatest lower-bound is in file k, find it ---
do n=1,strm%file(k)%nt
rDate2 = strm%file(k)%date(n) + strm%file(k)%secs(n)/spd ! date + frac day
if ( rDate2 <= rDateIn ) then
!--- found another/greater lower-bound ---
k_lb = k
n_lb = n
else
!--- found the least upper-bound ---
k_ub = k
n_ub = n
dDateLB = strm%file(k_lb)%date(n_lb)
call shr_cal_date2ymd(dDateLB,yy,mm,dd)
yy = yy + (mYear-dYear)
call shr_cal_ymd2date(yy,mm,dd,mDateLB)
secLB = strm%file(k_lb)%secs(n_lb)
fileLB = strm%file(k_lb)%name
dDateUB = strm%file(k_ub)%date(n_ub)
call shr_cal_date2ymd(dDateUB,yy,mm,dd)
yy = yy + (mYear-dYear)
call shr_cal_ymd2date(yy,mm,dd,mDateUB)
secUB = strm%file(k_ub)%secs(n_ub)
fileUB = strm%file(k_ub)%name
! write(s_logunit,*)'tcx fb7 ',n_lb,mDateLB,secLB,n_ub,mDateUB,secUB
! call shr_sys_flush(s_logunit)
return
endif
enddo
endif
end do C
endif
call shr_stream_abort(trim(subName)//' ERROR: findBounds failed')
return
end subroutine shr_stream_findBounds
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_readTCoord -- read in time coordinates with possible offset
!
! !DESCRIPTION:
! verify time coordinate data is OK
!
! !REVISION HISTORY:
! 2009-Sep-01 - T. Craig - modified
! 2005-Apr-18 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_readTCoord(strm,k,rc)
use netcdf
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType) ,intent(inout) :: strm ! data stream to query
integer(SHR_KIND_IN) ,intent(in) :: k ! stream index
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
character(SHR_KIND_CL) :: fileName ! filename to read
integer(SHR_KIND_IN) :: nt
integer(SHR_KIND_IN) :: num,n
integer(SHR_KIND_IN) :: din,dout
integer(SHR_KIND_IN) :: sin,sout,offin
integer(SHR_KIND_IN) :: lrc
integer(SHR_KIND_IN) :: fid,vid,ndims,rcode
integer(SHR_KIND_IN),allocatable :: dids(:)
character(SHR_KIND_CS) :: units,calendar
character(SHR_KIND_CS) :: bunits ! time units (days,secs,...)
integer(SHR_KIND_IN) :: bdate ! base date: calendar date
real(SHR_KIND_R8) :: bsec ! base date: elapsed secs
integer(SHR_KIND_IN) :: ndate ! calendar date of time value
real(SHR_KIND_R8) :: nsec ! elapsed secs on calendar date
real(SHR_KIND_R8),allocatable :: tvar(:)
!----- formats -----
character(*),parameter :: subname = '(shr_stream_readTCoord) '
character(*),parameter :: F01 = "('(shr_stream_readTCoord) ',a,2i7)"
!-------------------------------------------------------------------------------
lrc = 0
!--- need to read in this data ---
call shr_stream_getFile(strm%filePath,strm%file(k)%name,fileName)
rCode = nf90_open(fileName,nf90_nowrite,fid)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_open file '//trim(filename))
rCode = nf90_inq_varid(fid,trim(strm%domTvarName),vid)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_inq_varid')
rCode = nf90_inquire_variable(fid,vid,ndims=ndims)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_inquire_variable1')
allocate(dids(ndims))
rCode = nf90_inquire_variable(fid,vid,dimids=dids)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_inquire_variable2')
rCode = nf90_inquire_dimension(fid,dids(1),len=nt)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_inquire_dimension')
deallocate(dids)
allocate(strm%file(k)%date(nt),strm%file(k)%secs(nt))
strm%file(k)%nt = nt
units = ' '
calendar = ' '
rCode = nf90_get_att(fid, vid, 'units', units)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_get_att units')
rCode = nf90_inquire_attribute(fid, vid, 'calendar')
if (rCode == nf90_noerr) then
rCode = nf90_get_att(fid, vid, 'calendar', calendar)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_get_att calendar')
else
calendar = trim(shr_cal_noleap)
endif
n = len_trim(units)
if (ichar(units(n:n)) == 0 ) units(n:n) = ' '
n = len_trim(calendar)
if (ichar(calendar(n:n)) == 0 ) calendar(n:n) = ' '
call shr_string_leftalign(units)
call shr_string_leftalign(calendar)
call shr_string_parseCFtunit(units,bunits,bdate,bsec)
strm%calendar = trim(shr_cal_calendarName(trim(calendar)))
allocate(tvar(nt))
rcode = nf90_get_var(fid,vid,tvar)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_get_var')
rCode = nf90_close(fid)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_close')
do n = 1,nt
call shr_cal_advDate(tvar(n),bunits,bdate,bsec,ndate,nsec,calendar)
strm%file(k)%date(n) = ndate
strm%file(k)%secs(n) = nint(nsec)
enddo
deallocate(tvar)
if (strm%offset /= 0) then
if (size(strm%file(k)%date) /= size(strm%file(k)%secs)) then
! rc = 1
write(s_logunit,F01) "Incompatable date and secs sizes",size(strm%file(k)%date),size(strm%file(k)%secs)
call shr_sys_abort()
endif
num = size(strm%file(k)%date)
offin = strm%offset
do n = 1,num
din = strm%file(k)%date(n)
sin = strm%file(k)%secs(n)
call shr_cal_advDateInt(offin,'seconds',din,sin,dout,sout,calendar)
! write(s_logunit,*) 'tcx debug rtc1 ',n,strm%offset,din,sin,dout,sout
strm%file(k)%date(n) = dout
strm%file(k)%secs(n) = sout
enddo
endif
strm%file(k)%haveData = .true.
call shr_stream_verifyTCoord(strm,k,lrc) ! check new t-coord data
if (present(rc)) then
rc = lrc
endif
end subroutine shr_stream_readTCoord
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_verifyTCoord -- verify time coordinate data is OK
!
! !DESCRIPTION:
! verify time coordinate data is OK
!
! !REVISION HISTORY:
! 2005-Apr-18 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_verifyTCoord(strm,k,rc)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType),intent(in) :: strm ! data stream
integer(SHR_KIND_IN) :: k ! index of file to check
integer(SHR_KIND_IN) :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: n ! generic loop index
integer(SHR_KIND_IN) :: nt ! size of t-dimension
integer(SHR_KIND_IN) :: date1,secs1 ! date and seconds for a time coord
integer(SHR_KIND_IN) :: date2,secs2 ! date and seconds for next time coord
logical :: checkIt ! have data / do comparison
!----- formats -----
character(*),parameter :: subName = '(shr_stream_verifyTCoord) '
character(*),parameter :: F00 = "('(shr_stream_verifyTCoord) ',8a)"
character(*),parameter :: F01 = "('(shr_stream_verifyTCoord) ',a,2i7)"
character(*),parameter :: F02 = "('(shr_stream_verifyTCoord) ',a,2i9.8)"
!-------------------------------------------------------------------------------
! Notes:
! o checks that dates are increasing (must not decrease)
! o does not check for valid dates (eg. day=0 & month = 13 are "OK")
! o checks that secs are strictly increasing within any one day
! o checks that 0 <= secs <= spd (seconds per day)
! o checks all dates from one file plus last date of previous file and
! first date of next file
!-------------------------------------------------------------------------------
rc = 0
if (debug>1 .and. s_loglev > 0) write(s_logunit,F01) "checking t-coordinate data for file k =",k
if ( .not. strm%file(k)%haveData) then
rc = 1
write(s_logunit,F01) "Don't have data for file ",k
call shr_stream_abort(subName//"ERROR: can't check -- file not read.")
return
end if
do n=1,strm%file(k)%nt+1
checkIt = .false.
!--- do we have data for two consecutive dates? ---
if (n==1) then
!--- compare with previous file? ---
if (k>1) then
if ( strm%file(k-1)%haveData ) then
nt = strm%file(k-1)%nt
date1 = strm%file(k-1)%date(nt)
secs1 = strm%file(k-1)%secs(nt)
date2 = strm%file(k )%date(n)
secs2 = strm%file(k )%secs(n)
checkIt = .true.
if (debug>1 .and. s_loglev > 0) write(s_logunit,F01) "comparing with previous file for file k =",k
end if
end if
else if (n==strm%file(k)%nt+1) then
!--- compare with next file? ---
if (k1 .and. s_loglev > 0) write(s_logunit,F01) "comparing with next file for file k =",k
end if
end if
else
!--- compare within this file ---
date1 = strm%file(k)%date(n-1)
secs1 = strm%file(k)%secs(n-1)
date2 = strm%file(k)%date(n )
secs2 = strm%file(k)%secs(n )
checkIt = .true.
end if
!--- compare two consecutive dates ---
if (checkIt) then
if ( date1 > date2 ) then
rc = 1
write(s_logunit,F01) "ERROR: calendar dates must be increasing"
write(s_logunit,F02) "date(n), date(n+1) = ",date1,date2
call shr_stream_abort(subName//"ERROR: calendar dates must be increasing")
return
else if ( date1 == date2 ) then
if ( secs1 >= secs2 ) then
rc = 1
write(s_logunit,F01) "ERROR: elapsed seconds on a date must be strickly increasing"
write(s_logunit,F02) "secs(n), secs(n+1) = ",secs1,secs2
call shr_stream_abort(subName//"ERROR: elapsed seconds must be increasing")
return
end if
end if
if ( secs1 < 0 .or. spd < secs1 ) then
rc = 1
write(s_logunit,F01) "ERROR: elapsed seconds out of valid range [0,spd]"
write(s_logunit,F02) "secs(n) = ",secs1
call shr_stream_abort(subName//"ERROR: elapsed seconds out of range")
return
end if
end if
end do
if (debug>0 .and. s_loglev > 0) write(s_logunit,F01) "data is OK (non-decreasing) for file k =",k
end subroutine shr_stream_verifyTCoord
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getFileFieldList -- Get list of file fields
!
! !DESCRIPTION:
! Get list of file fields
! \newline
! call shr\_stream\_getFileFieldList(stream,list,rc)
!
! !REVISION HISTORY:
! 2005-May-10 - B. Kauffman
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getFileFieldList(stream,list,rc)
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType) ,intent(in) :: stream ! stream in question
character(*) ,intent(out) :: list ! field list
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: rCode ! return code
!----- formats -----
character(*),parameter :: subName = '(shr_stream_getFileFieldList) '
character(*),parameter :: F00 = "('(shr_stream_getFileFieldList) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
rCode = 0
list = stream%fldListFile
if (present(rc)) rc = rCode
end subroutine shr_stream_getFileFieldList
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getModelFieldList -- Get list of file fields
!
! !DESCRIPTION:
! Get list of file fields
! \newline
! call shr\_stream\_getModelFieldList(stream,list,rc)
!
! !REVISION HISTORY:
! 2005-May-10 - B. Kauffman
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getModelFieldList(stream,list,rc)
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType) ,intent(in) :: stream ! stream in question
character(*) ,intent(out) :: list ! field list
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: rCode ! return code
!----- formats -----
character(*),parameter :: subName = '(shr_stream_getModelFieldList) '
character(*),parameter :: F00 = "('(shr_stream_getModelFieldList) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
rCode = 0
list = stream%fldListModel
if (present(rc)) rc = rCode
end subroutine shr_stream_getModelFieldList
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getFileFieldName -- Get name of k-th field in list
!
! !DESCRIPTION:
! Get name of k-th field in list
! \newline
! call shr\_stream\_getFileFieldName(stream,k,name,rc)
!
! !REVISION HISTORY:
! 2005-May-05 - B. Kauffman
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getFileFieldName(stream,k,name,rc)
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType) ,intent(in) :: stream ! stream in question
integer(SHR_KIND_IN) ,intent(in) :: k ! index of field
character(*) ,intent(out) :: name ! k-th name in list
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: rCode ! return code
!----- formats -----
character(*),parameter :: subName = '(shr_stream_getFileFieldName) '
character(*),parameter :: F00 = "('(shr_stream_getFileFieldName) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
rCode = 0
call shr_string_listGetName(stream%fldListFile,k,name,rCode)
if (present(rc)) rc = rCode
end subroutine shr_stream_getFileFieldName
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getModelFieldName -- Get name of k-th field in list
!
! !DESCRIPTION:
! Get name of k-th field in list
! \newline
! call shr\_stream\_getModelFieldName(stream,k,name,rc)
!
! !REVISION HISTORY:
! 2005-May-05 - B. Kauffman
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getModelFieldName(stream,k,name,rc)
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType) ,intent(in) :: stream ! stream in question
integer(SHR_KIND_IN) ,intent(in) :: k ! index of field
character(*) ,intent(out) :: name ! k-th name in list
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
integer(SHR_KIND_IN) :: rCode ! return code
!----- formats -----
character(*),parameter :: subName = '(shr_stream_getModelFieldName) '
character(*),parameter :: F00 = "('(shr_stream_getModelFieldName) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
rCode = 0
call shr_string_listGetName(stream%fldListModel,k,name,rCode)
if (present(rc)) rc = rCode
end subroutine shr_stream_getModelFieldName
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getFilePath -- return file path
!
! !DESCRIPTION:
! Returns file path.
!
! !REVISION HISTORY:
! 2005-Nov-23 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getFilepath(strm,path)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType),intent(in) :: strm ! data stream
character(*) ,intent(out) :: path ! file path
!EOP
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
path = strm%filePath
end subroutine shr_stream_getFilePath
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getDataSource -- return data source meta data
!
! !DESCRIPTION:
! Returns data source meta data.
!
! !REVISION HISTORY:
! 2005-Feb-18 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getDataSource(strm,str)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType),intent(in) :: strm ! data stream
character(*) ,intent(out) :: str ! meta data
!EOP
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
str = strm%dataSource
end subroutine shr_stream_getDataSource
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getCalendar -- return calendar name
!
! !DESCRIPTION:
! Returns calendar name
!
! !REVISION HISTORY:
! 2010-Oct-11 - T. Craig - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getCalendar(strm,k,calendar)
use netcdf
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType),intent(in) :: strm ! data stream
integer(SHR_KIND_IN) ,intent(in) :: k ! file to query
character(*) ,intent(out) :: calendar ! calendar name
!EOP
integer(SHR_KIND_IN) :: fid, vid, n
character(SHR_KIND_CL) :: fileName,strmfile,lcal
integer(SHR_KIND_IN) :: rCode
character(*),parameter :: subName = '(shr_stream_getCalendar) '
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
lcal = ' '
calendar = ' '
if (k > strm%nfiles) call shr_sys_abort(subname//' ERROR: k gt nfiles')
strmfile = strm%file(k)%name
call shr_stream_getFile(strm%filePath,strmfile,fileName)
rCode = nf90_open(fileName,nf90_nowrite,fid)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_open file '//trim(filename))
rCode = nf90_inq_varid(fid,trim(strm%domTvarName),vid)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_inq_varid')
rCode = nf90_inquire_attribute(fid, vid, 'calendar')
if (rCode == nf90_noerr) then
rCode = nf90_get_att(fid, vid, 'calendar', lcal)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_get_att calendar')
else
lcal = trim(shr_cal_noleap)
endif
n = len_trim(lcal)
if (ichar(lcal(n:n)) == 0 ) lcal(n:n) = ' '
call shr_string_leftalign(lcal)
calendar = trim(shr_cal_calendarName(trim(lcal)))
rCode = nf90_close(fid)
if (rcode /= nf90_noerr) call shr_sys_abort(subname//' ERROR: nf90_close')
return
end subroutine shr_stream_getCalendar
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getDomainInfo -- return domain information
!
! !DESCRIPTION:
! Returns domain information data.
!
! !REVISION HISTORY:
! 2005-Mar-13 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getDomainInfo(strm,filePath,fileName,timeName,lonName,latName,maskName,areaName)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType),intent(in) :: strm ! data stream
character(*) ,intent(out) :: filePath ! domain file path
character(*) ,intent(out) :: fileName ! domain file name
character(*) ,intent(out) :: timeName ! domain time var name
character(*) ,intent(out) :: lonName ! domain lon var name
character(*) ,intent(out) :: latName ! domain lat var name
character(*) ,intent(out) :: maskName ! domain mask var name
character(*) ,intent(out) :: areaName ! domain area var name
!EOP
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
filePath = strm%domFilePath
fileName = strm%domFileName
timeName = strm%domTvarName
lonName = strm%domXvarName
latName = strm%domYvarName
maskName = strm%domMaskName
areaName = strm%domAreaName
end subroutine shr_stream_getDomainInfo
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getFile -- Acquire file, return name of file to open
!
! !DESCRIPTION:
! Acquire file (if necessary) and return name of file to open
! \newline
! call shr\_stream\_getFile(path,fileName,localFileName,rc)
!
! !REVISION HISTORY:
! 2007-Aug-24 - B. Kauffman
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getFile(filePath,fileName,localFile,rc)
use shr_file_mod, only: shr_file_queryPrefix, shr_file_noPrefix
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*) ,intent(in) :: filePath ! file path
character(*) ,intent(inout) :: fileName ! file name
character(*) ,optional,intent(out) :: localFile ! name of acquired file
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!----- local -----
character(SHR_KIND_CL) :: localFn ! name of acquired file
integer (SHR_KIND_IN) :: rCode ! return code
!----- formats -----
character(*),parameter :: subName = '(shr_stream_getFile) '
character(*),parameter :: F00 = "('(shr_stream_getFile) ',4a)"
!-------------------------------------------------------------------------------
! Notes:
! - this routine reflects an added stream file handling requirement:
! for files on an nfs-mounted file system (available via unix cp),
! there are two options...
! 1) read the file without making a local copy: read path/file
! 2) copy path/file to file, and then read file
! - the shr_file_get/put file name format is used to select the option:
! using shr_file_queryPrefix -- if recognized prefix found -- do shr_file_get
! otherwise use the file in place.
! - if optional argument localFile is present
! then fileName is unaltered and localFile is the file to be read
! else fileName is altered and contains the name of the file to be read
! - this routine is somewhat awkward but reduces redundant code
!-------------------------------------------------------------------------------
rCode = 0
if ( shr_file_queryPrefix(filePath) /= shr_file_noPrefix ) then
localFn = fileName
call shr_file_get(rCode,localFn, trim(filePath)//fileName)
else ! don't copy file, read original file
localFn = trim(filePath)//fileName
end if
if (debug>0 .and. s_loglev > 0) then
write(s_logunit,F00) "DEBUG: remote file : ",trim(filePath)//trim(fileName)
write(s_logunit,F00) "DEBUG: local file : ",trim(localFn)
end if
if (.not. present(localFile)) fileName = localFn ! clobber input fileName
if ( present(localFile)) localFile = localFn ! don't clobber fileName
if (present(rc)) rc = rCode
end subroutine shr_stream_getFile
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getFirstFileName -- returns first file name
!
! !DESCRIPTION:
! Returns first file name in stream.
!
! !REVISION HISTORY:
! 2005-Feb-18 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getFirstFileName(strm,file,path)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType),intent(in) :: strm ! data stream
character(*) ,intent(out) :: file ! file name
character(*),optional ,intent(out) :: path ! file path
!EOP
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
if (present(path)) path = strm%filePath
file = strm%file(1)%name
end subroutine shr_stream_getFirstFileName
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getNextFileName -- returns next file name in sequence
!
! !DESCRIPTION:
! Returns next file name in sequence
!
! !REVISION HISTORY:
! 2005-Nov-18 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getNextFileName(strm,fn,fnNext,path,rc)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType),intent(in) :: strm ! data stream
character(*) ,intent(in) :: fn ! file name
character(*) ,intent(out) :: fnNext ! next file name
character(*),optional ,intent(out) :: path ! file path
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!--- local ---
integer (SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: n ! loop index
logical :: found ! file name found?
!--- formats ---
character(*),parameter :: subName = '(shr_stream_getNextFileName) '
character(*),parameter :: F00 = "('(shr_stream_getNextFileName) ',8a)"
!-------------------------------------------------------------------------------
! Note: will wrap-around data loop if lvd & gvd are known
! otherwise may return file name = "unknown"
!-------------------------------------------------------------------------------
rCode = 0
if (present(path)) path = strm%filePath
!--- locate input file in the stream's list of files ---
found = .false.
do n = 1,strm%nFiles
if ( trim(fn) == trim(strm%file(n)%name)) then
found = .true.
exit
end if
end do
if (.not. found) then
rCode = 1
write(s_logunit,F00) "ERROR: input file name is not in stream: ",trim(fn)
call shr_stream_abort(subName//"ERROR: file name not in stream: "//trim(fn))
end if
!--- get next file name ---
n = n+1 ! next in list
if (strm%found_lvd .and. strm%found_gvd) then
if (n > strm%k_gvd) n = strm%k_lvd ! wrap-around to lvd
else if (strm%found_lvd ) then
if (n > strm%nFiles) n = strm%k_lvd ! wrap-around to lvd
else if (n > strm%nFiles ) then
n = 1 ! wrap-around to 1st file
end if
fnNext = trim(strm%file(n)%name)
if ( present(rc) ) rc = rCode
end subroutine shr_stream_getNextFileName
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getPrevFileName -- returns previous file name in sequence
!
! !DESCRIPTION:
! Returns previous file name in sequence
!
! !REVISION HISTORY:
! 2005-Nov-18 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getPrevFileName(strm,fn,fnPrev,path,rc)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType) ,intent(in) :: strm ! data stream
character(*) ,intent(in) :: fn ! file name
character(*) ,intent(out) :: fnPrev ! preciding file name
character(*),optional ,intent(out) :: path ! file path
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!--- local ---
integer (SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: n ! loop index
logical :: found ! file name found?
!--- formats ---
character(*),parameter :: subName = '(shr_stream_getPrevFileName) '
character(*),parameter :: F00 = "('(shr_stream_getPrevFileName) ',8a)"
!-------------------------------------------------------------------------------
! Note: will wrap-around data loop if lvd & gvd are known
! otherwise may return file name = "unknown"
!-------------------------------------------------------------------------------
rCode = 0
if (present(path)) path = strm%filePath
!--- locate input file in the stream's list of files ---
found = .false.
do n = 1,strm%nFiles
if ( trim(fn) == trim(strm%file(n)%name)) then
found = .true.
exit
end if
end do
if (.not. found) then
rCode = 1
write(s_logunit,F00) "ERROR: input file name is not in stream: ",trim(fn)
call shr_stream_abort(subName//"ERROR: file name not in stream: "//trim(fn))
end if
!--- get previous file name ---
n = n-1 ! previous in list
if (strm%found_lvd .and. strm%found_gvd) then
if ( n < strm%k_lvd) n = strm%k_gvd ! do wrap-around ---
end if
if (n>0) then
fnPrev = trim(strm%file(n)%name)
else
fnPrev = "unknown "
end if
if ( present(rc) ) rc = rCode
end subroutine shr_stream_getPrevFileName
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getNFiles -- returns number of input files in stream
!
! !DESCRIPTION:
! Returns number of input files in stream
!
! !REVISION HISTORY:
! 2010-Apr-28 - T. Craig - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getNFiles(strm,nfiles)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType),intent(in) :: strm ! data stream
integer(SHR_KIND_IN) ,intent(out) :: nfiles ! number of input files in stream
!EOP
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
nfiles = strm%nfiles
end subroutine shr_stream_getNFiles
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_restWrite -- write stream data to a restart file
!
! !DESCRIPTION:
! Write stream data to a restart file.
!
! !REVISION HISTORY:
! 2005-Nov-21 -- B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_restWrite(strm,fileName,caseName,caseDesc,nstrms,rc)
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType) ,intent(in) :: strm(:) ! vector of data streams
character(*) ,intent(in) :: fileName ! name of restart file
character(*) ,intent(in) :: caseName ! case name
character(*) ,intent(in) :: caseDesc ! case description
integer(SHR_KIND_IN),optional,intent(in) :: nstrms ! number of streams
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!--- local ---
integer (SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: nStreams ! number of streams
integer(SHR_KIND_IN) :: k,n ! generic loop index
character( 8) :: dStr ! F90 wall clock date str yyyymmdd
character(10) :: tStr ! F90 wall clock time str hhmmss.sss
character(SHR_KIND_CS) :: str ! generic text string
integer(SHR_KIND_IN) :: nUnit ! a file unit number
integer(SHR_KIND_IN) :: nt ! number of time samples
character(SHR_KIND_CS) :: tInterpAlgo ! for backwards compatability
!--- formats ---
character(*),parameter :: subName = '(shr_stream_restWrite) '
character(*),parameter :: F00 = "('(shr_stream_restWrite) ',16a) "
character(*),parameter :: F01 = "('(shr_stream_restWrite) ',a,i5,a,5a) "
character(*),parameter :: F02 = "('(shr_stream_restWrite) ',a,i5,a,5i8) "
character(*),parameter :: F03 = "('(shr_stream_restWrite) ',a,i5,a,5l3) "
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
rCode = 0
tInterpAlgo = 'unused'
if (present(nstrms)) then
if (size(strm) < nstrms) then
write(s_logunit,F02) "ERROR: nstrms too large for strm",size(strm),nstrms
call shr_stream_abort(subname//": ERROR: nstrms too large for strm")
endif
nStreams = nstrms
else
nStreams = size(strm)
endif
call date_and_time(dStr,tStr)
!--- log info to stdout ---
if (s_loglev > 0) then
write(s_logunit,F00) "case name : ",trim(caseName)
write(s_logunit,F00) "case description : ",trim(caseDesc)
write(s_logunit,F00) "File created : ",dStr(1:4)//'-'//dStr(5:6)//'-'//dStr(7:8)//' ' &
& //tStr(1:2)//':'//tStr(3:4)//':'//tStr(5:6)
write(s_logunit,F01) "Number of streams ",nStreams
endif
!----------------------------------------------------------------------------
! write the data
!----------------------------------------------------------------------------
nUnit = shr_file_getUnit() ! get an unused unit number
open(nUnit,file=trim(fileName),form="unformatted",action="write")
str = "case name : "//caseName
write(nUnit) str
str = "case description : "//caseDesc
write(nUnit) str
str = 'File created : '//dStr(1:4)//'-'//dStr(5:6)//'-'//dStr(7:8)//' ' &
& //tStr(1:2)//':'//tStr(3:4)//':'//tStr(5:6)
write(nUnit) str
write(nUnit) nStreams
do k = 1,nStreams
if (.not. shr_stream_isInit(strm(k))) then ! has stream been initialized?
rCode = 1
write(s_logunit,F01) "ERROR: can't write uninitialized stream to a restart file, k = ",k
call shr_stream_abort(subName//": ERROR: given uninitialized stream")
end if
write(nUnit) strm(k)%init ! has stream been initialized?
write(nUnit) strm(k)%nFiles ! number of data files
write(nUnit) strm(k)%dataSource ! meta data identifying data source
write(nUnit) strm(k)%filePath ! remote location of files
if (s_loglev > 0) write(s_logunit,F01) "* stream ",k," first file name = ",trim(strm(k)%file(1)%name)
if (s_loglev > 0) write(s_logunit,F03) "* stream ",k," first have data = ",strm(k)%file(1)%haveData
if (s_loglev > 0) write(s_logunit,F02) "* stream ",k," first nt = ",strm(k)%file(1)%nt
nt = strm(k)%file(1)%nt
if (strm(k)%file(1)%haveData) then
if (s_loglev > 0) write(s_logunit,F02) "* stream ",k," first date secs = ", &
strm(k)%file(1)%date(1),strm(k)%file(1)%secs(1)
if (s_loglev > 0) write(s_logunit,F02) "* stream ",k," last date secs = ", &
strm(k)%file(1)%date(nt),strm(k)%file(1)%secs(nt)
endif
do n=1,strm(k)%nFiles ! data specific to each file...
write(nUnit) strm(k)%file(n)%name ! the file name
write(nUnit) strm(k)%file(n)%haveData ! has t-coord data been read in?
write(nUnit) strm(k)%file(n)%nt ! size of time dimension
if (strm(k)%file(n)%haveData) then ! ie. if arrays have been allocated
write(nUnit) strm(k)%file(n)%date(:) ! t-coord date: yyyymmdd
write(nUnit) strm(k)%file(n)%secs(:) ! t-coord secs: elapsed on date
end if
end do
write(nUnit) strm(k)%yearFirst ! first year to use in t-axis (yyyymmdd)
write(nUnit) strm(k)%yearLast ! last year to use in t-axis (yyyymmdd)
write(nUnit) strm(k)%yearAlign ! align yearFirst with this model year
write(nUnit) strm(k)%offset ! time axis offset
! write(nUnit) strm(k)%taxMode ! time axis cycling mode
write(nUnit) strm(k)%k_lvd ! file of least valid date
write(nUnit) strm(k)%n_lvd ! sample of least valid date
write(nUnit) strm(k)%found_lvd ! T <=> k_lvd,n_lvd have been set
write(nUnit) strm(k)%k_gvd ! file of greatest valid date
write(nUnit) strm(k)%n_gvd ! sample of greatest valid date
write(nUnit) strm(k)%found_gvd ! T <=> k_gvd,n_gvd have been set
write(nUnit) strm(k)%fldListFile ! field list: file's field names
write(nUnit) strm(k)%fldListModel ! field list: model's field names
write(nUnit) tInterpAlgo ! unused
write(nUnit) strm(k)%domFileName ! domain file: name
write(nUnit) strm(k)%domFilePath ! domain file: path
write(nUnit) strm(k)%domTvarName ! domain file: time-dim var name
write(nUnit) strm(k)%domXvarName ! domain file: x-dim var name
write(nUnit) strm(k)%domYvarName ! domain file: y-dim var ame
write(nUnit) strm(k)%domAreaName ! domain file: area var name
write(nUnit) strm(k)%domMaskName ! domain file: mask var name
end do
close(nUnit)
call shr_file_freeUnit(nUnit)
if ( present(rc) ) rc = rCode
end subroutine shr_stream_restWrite
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_restRead -- read stream data from a restart file
!
! !DESCRIPTION:
! Read stream data to a restart file.
! Either shr_stream_init xor shr_stream_restRead must be called
! Do not call both routines.
!
! !REVISION HISTORY:
! 2005-Nov-21 -- B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_restRead(strm,fileName,nstrms,rc)
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType) ,intent(inout) :: strm(:) ! vector of data streams
character(*) ,intent(in) :: fileName ! name of restart file
integer(SHR_KIND_IN),optional,intent(in) :: nstrms ! number of streams in strm
integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code
!EOP
!--- local ---
integer (SHR_KIND_IN) :: rCode ! return code
integer(SHR_KIND_IN) :: nStreams ! number of streams
integer(SHR_KIND_IN) :: k,n ! generic loop index
character(SHR_KIND_CS) :: str ! generic text string
integer(SHR_KIND_IN) :: nUnit ! a file unit number
integer(SHR_KIND_IN) :: inpi ! input integer
real(SHR_KIND_R8) :: inpr ! input real
character(SHR_KIND_CX) :: inpcx ! input char
character(SHR_KIND_CL) :: inpcl ! input char
character(SHR_KIND_CS) :: inpcs ! input char
integer(SHR_KIND_IN) :: nt ! size of time dimension
character(SHR_KIND_CS) :: tInterpAlgo ! for backwards compatability
character(SHR_KIND_CL) :: name ! local variables
integer(SHR_KIND_IN) :: nFiles ! local variables
integer(SHR_KIND_IN) :: k_lvd, n_lvd, k_gvd, n_gvd ! local variables
logical :: found_lvd, found_gvd, haveData ! local variables
integer(SHR_KIND_IN),pointer :: date(:),secs(:) ! local variables
logical :: abort ! abort the restart read
logical :: readok ! read of restarts ok
!--- formats ---
character(*),parameter :: subName = '(shr_stream_restRead) '
character(*),parameter :: F00 = "('(shr_stream_restRead) ',16a) "
character(*),parameter :: F01 = "('(shr_stream_restRead) ',a,i5,a,5a) "
character(*),parameter :: F02 = "('(shr_stream_restRead) ',a,i5,a,5i8) "
character(*),parameter :: F03 = "('(shr_stream_restRead) ',a,i5,a,5l3) "
character(*),parameter :: F04 = "('(shr_stream_restRead) ',a,4i8) "
character(*),parameter :: F05 = "('(shr_stream_restRead) ',a,2i8,6a) "
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
rCode = 0
tInterpAlgo = 'unused'
abort = .false.
inpcl = ' '
!----------------------------------------------------------------------------
! read the data
!----------------------------------------------------------------------------
nUnit = shr_file_getUnit() ! get an unused unit number
open(nUnit,file=trim(fileName),form="unformatted",status="old",action="read", iostat=rCode)
if ( rCode /= 0 )then
call shr_file_freeUnit(nUnit)
call shr_stream_abort(subName//": ERROR: error opening file: "//trim(fileName) )
if ( present(rc) ) rc = rCode
return
end if
read(nUnit) str ! case name
if (s_loglev > 0) write(s_logunit,F00) trim(str)
read(nUnit) str ! case description
if (s_loglev > 0) write(s_logunit,F00) trim(str)
read(nUnit) str ! file creation date
if (s_loglev > 0) write(s_logunit,F00) trim(str)
read(nUnit) nStreams
if (present(nstrms)) then
if (nstrms /= nStreams) then
write(s_logunit,F02) "ERROR: nstrms ne nStreams on restart",nstrms,' ',nStreams
call shr_stream_abort(subname//": ERROR: nstrms ne nStreams on restart")
endif
nStreams = nstrms
endif
if (s_loglev > 0) write(s_logunit,F01) "Number of streams ",nStreams
do k = 1,nStreams
read(nUnit) strm(k)%init ! has stream been initialized?
if (.not. strm(k)%init) then
rCode = 1
write(s_logunit,F01) "ERROR: uninitialized stream in restart file, k = ",k
call shr_stream_abort(subName//": ERROR: reading uninitialized stream")
end if
call shr_stream_setInit(strm(k))
readok = .true.
! tcraig, don't overwrite these from input
read(nUnit) nFiles ! number of data files
read(nUnit) inpcs ! dataSource ! meta data identifying data source
read(nUnit) inpcl ! filePath ! remote location of files
do n=1,nFiles ! data specific to each file...
read(nUnit) name ! the file name
read(nUnit) haveData ! has t-coord data been read in?
read(nUnit) nt ! size of time dimension
if (haveData) then ! ie. if arrays have been allocated
allocate(date(nt))
allocate(secs(nt))
read(nUnit) date(:) ! t-coord date: yyyymmdd
read(nUnit) secs(:) ! t-coord secs: elapsed on date
if (strm(k)%nFiles >= n) then
if (trim(name) == trim(strm(k)%file(n)%name)) then
write(s_logunit,F05) "reading time axis for stream restart filename ",k,n,' ',trim(name),' ',trim(strm(k)%file(n)%name)
strm(k)%file(n)%nt = nt
strm(k)%file(n)%haveData = haveData
allocate(strm(k)%file(n)%date(nt))
allocate(strm(k)%file(n)%secs(nt))
strm(k)%file(n)%date(1:nt) = date(1:nt)
strm(k)%file(n)%secs(1:nt) = secs(1:nt)
else
write(s_logunit,F05) "WARNING, skip time axis for stream restart filename ",k,n,' ',trim(name),' ',trim(strm(k)%file(n)%name)
readok = .false.
endif ! filenames consistent
endif ! strm nfiles
deallocate(date)
deallocate(secs)
end if
end do
if (s_loglev > 0) write(s_logunit,F01) "* stream ",k," first file name = ",trim(strm(k)%file(1)%name)
if (s_loglev > 0) write(s_logunit,F03) "* stream ",k," first have data = ",strm(k)%file(1)%haveData
if (s_loglev > 0) write(s_logunit,F02) "* stream ",k," first nt = ",strm(k)%file(1)%nt
if (strm(k)%file(1)%haveData) then
nt = strm(k)%file(1)%nt
if (s_loglev > 0) write(s_logunit,F02) "* stream ",k," first date secs = ", &
strm(k)%file(1)%date(1),strm(k)%file(1)%secs(1)
if (s_loglev > 0) write(s_logunit,F02) "* stream ",k," last date secs = ", &
strm(k)%file(1)%date(nt),strm(k)%file(1)%secs(nt)
endif
! tcraig, apr 2 2012, offset is the only field that should not change here for time axis
! read(nUnit) strm(k)%yearFirst ! last year to use in t-axis (yyyymmdd)
! read(nUnit) strm(k)%yearLast ! last year to use in t-axis (yyyymmdd)
! read(nUnit) strm(k)%yearAlign ! align yearFirst with this model year
! read(nUnit) strm(k)%offset ! time axis offset
read(nUnit) inpi ! first year to use in t-axis (yyyymmdd)
! if (inpi /= strm(k)%yearFirst) then
! write(s_logunit,F04) " ERROR: yearFirst disagrees ",k,strm(k)%yearFirst,inpi
! abort=.true.
! endif
read(nUnit) inpi ! last year to use in t-axis (yyyymmdd)
! if (inpi /= strm(k)%yearLast) then
! write(s_logunit,F04) " ERROR: yearLast disagrees ",k,strm(k)%yearLast,inpi
! abort=.true.
! endif
read(nUnit) inpi ! align year to use in t-axis (yyyymmdd)
! if (inpi /= strm(k)%yearAlign) then
! write(s_logunit,F04) " ERROR: yearAlign disagrees ",k,strm(k)%yearAlign,inpi
! abort=.true.
! endif
read(nUnit) inpi ! time axis offset
if (inpi /= strm(k)%offset) then
write(s_logunit,F04) " ERROR: offset disagrees ",k,strm(k)%offset,inpi
abort=.true.
endif
! read(nUnit) strm(k)%taxMode ! time axis cycling mode
read(nUnit) k_lvd ! file of least valid date
read(nUnit) n_lvd ! sample of least valid date
read(nUnit) found_lvd ! T <=> k_lvd,n_lvd have been set
read(nUnit) k_gvd ! file of greatest valid date
read(nUnit) n_gvd ! sample of greatest valid date
read(nUnit) found_gvd ! T <=> k_gvd,n_gvd have been set
! tcraig, april 2012, only overwrite if restart read is ok
if (readok) then
write(s_logunit,F05) "setting k n and found lvd gvd on restart ",k,n,' ',trim(name)
strm(k)%k_lvd = k_lvd
strm(k)%n_lvd = n_lvd
strm(k)%found_lvd = found_lvd
strm(k)%k_gvd = k_gvd
strm(k)%n_gvd = n_gvd
strm(k)%found_gvd = found_gvd
endif
! tcraig, april 2012, don't overwrite these from input
read(nUnit) inpcx ! fldListFile ! field list: file's field names
read(nUnit) inpcx ! fldListModel ! field list: model's field names
read(nUnit) inpcs ! tInterpAlgo ! unused
read(nUnit) inpcl ! domFileName ! domain file: name
read(nUnit) inpcl ! domFilePath ! domain file: path
read(nUnit) inpcs ! domTvarName ! domain file: time-dim var name
read(nUnit) inpcs ! domXvarName ! domain file: x-dim var name
read(nUnit) inpcs ! domYvarName ! domain file: y-dim var ame
read(nUnit) inpcs ! domAreaName ! domain file: area var name
read(nUnit) inpcs ! domMaskName ! domain file: mask var name
end do
if (abort) then
write(s_logunit,F00) "ERRORS Detected ABORTING NOW"
call shr_stream_abort(subName//": ERRORS Detected ABORTING NOW")
endif
close(nUnit)
call shr_file_freeUnit(nUnit)
if ( present(rc) ) rc = rCode
end subroutine shr_stream_restRead
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_dataDump -- dump all data to stdout for debugging
!
! !DESCRIPTION:
! Dump all data to stdout for debugging
!
! !REVISION HISTORY:
! 2005-Mar-23 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_dataDump(strm)
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType),intent(in) :: strm ! data stream
!EOP
!----- local -----
integer(SHR_KIND_IN) :: k ! generic loop index
!----- formats -----
character(*),parameter :: subName = '(shr_stream_dataDump) '
character(*),parameter :: F00 = "('(shr_stream_dataDump) ',8a)"
character(*),parameter :: F01 = "('(shr_stream_dataDump) ',a,3i5)"
character(*),parameter :: F02 = "('(shr_stream_dataDump) ',a,365i9.8)"
character(*),parameter :: F03 = "('(shr_stream_dataDump) ',a,365i6)"
!-------------------------------------------------------------------------------
! notes:
!-------------------------------------------------------------------------------
if (s_loglev <= 0) return
write(s_logunit,F00) "dump internal data for debugging..."
!-----------------------------------------------------------------------------
! dump internal data
!-----------------------------------------------------------------------------
write(s_logunit,F01) "nFiles = ", strm%nFiles
write(s_logunit,F00) "filePath = ", trim(strm%filePath)
do k=1,strm%nFiles
write(s_logunit,F01) "data for file k = ",k
write(s_logunit,F00) "* file(k)%name = ", trim(strm%file(k)%name)
if ( strm%file(k)%haveData ) then
write(s_logunit,F01) "* file(k)%nt = ", strm%file(k)%nt
write(s_logunit,F02) "* file(k)%date(:) = ", strm%file(k)%date(:)
write(s_logunit,F03) "* file(k)%Secs(:) = ", strm%file(k)%secs(:)
else
write(s_logunit,F00) "* time coord data not read in yet for this file"
end if
end do
write(s_logunit,F01) "yearF/L/A = ", strm%yearFirst,strm%yearLast,strm%yearAlign
write(s_logunit,F01) "offset = ", strm%offset
write(s_logunit,F00) "taxMode = ", trim(strm%taxMode)
write(s_logunit,F00) "fldListFile = ", trim(strm%fldListFile)
write(s_logunit,F00) "fldListModel = ", trim(strm%fldListModel)
write(s_logunit,F00) "domFileName = ", trim(strm%domFileName)
write(s_logunit,F00) "domFilePath = ", trim(strm%domFilePath)
write(s_logunit,F00) "domTvarName = ", trim(strm%domTvarName)
write(s_logunit,F00) "domXvarName = ", trim(strm%domXvarName)
write(s_logunit,F00) "domYvarName = ", trim(strm%domYvarName)
write(s_logunit,F00) "domAreaName = ", trim(strm%domAreaName)
write(s_logunit,F00) "domMaskName = ", trim(strm%domMaskName)
end subroutine shr_stream_dataDump
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_setDebug -- Set local debug level
!
! !DESCRIPTION:
! Set local/internal debug level, 0 = production
! \newline
! General Usage: call shr\_stream\_setDebug(2)
!
! !REVISION HISTORY:
! 2005-May-10 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_setDebug(level)
implicit none
! !INPUT/OUTPUT PARAMETERS:
integer,intent(in) :: level
!EOP
!--- formats ---
character(*),parameter :: subName = '(shr_stream_setDebug) '
character(*),parameter :: F00 = "('(shr_stream_setDebug) ',a) "
character(*),parameter :: F01 = "('(shr_stream_setDebug) ',a,i4) "
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
debug = level
if (s_loglev > 0) write(s_logunit,F01) "debug level reset to ",level
end subroutine shr_stream_setDebug
!==============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_getDebug -- return local/internal debug level
!
! !DESCRIPTION:
! Return internal debug level, 0 = production
! \newline
! General Usage: call shr\_stream\_getDebug(level)
!
! !REVISION HISTORY:
! 2005-May-10 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_getDebug(level)
implicit none
! !INPUT/OUTPUT PARAMETERS:
integer,intent(out) :: level
!EOP
!--- formats ---
character(*),parameter :: subName = '(shr_stream_getDebug) '
character(*),parameter :: F00 = "('(shr_stream_getDebug) ',a) "
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
level = debug
end subroutine shr_stream_getDebug
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_setAbort -- Set abort level
!
! !DESCRIPTION:
! Set local/internal abort level, .true. = production
! \newline
! General Usage: call shr\_stream\_setAbort(.false.)
!
! !REVISION HISTORY:
! 2008-May-28 - E. Kluzek - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_setAbort(flag)
implicit none
! !INPUT/OUTPUT PARAMETERS:
logical,intent(in) :: flag
!EOP
!--- formats ---
character(*),parameter :: subName = '(shr_stream_setAbort) '
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
doabort = flag
end subroutine shr_stream_setAbort
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_abort -- Call abort and end
!
! !DESCRIPTION:
! Local interface for shr_stream abort calls
! General Usage: call shr\_stream\_abort(msg)
!
! !REVISION HISTORY:
! 2008-May-28 - E. Kluzek - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_abort( msg )
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(len=*), optional, intent(IN) :: msg ! Message to describe error
!EOP
character(SHR_KIND_CL) :: lmsg
!--- formats ---
character(*),parameter :: subName = '(shr_stream_abort) '
character(*),parameter :: F00 = "('(shr_stream_abort) ',a) "
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
lmsg = ' '
if (present(msg)) lmsg= msg
if (doabort) then
call shr_sys_abort(lmsg)
else
write(s_logunit,F00) trim(lmsg)
endif
end subroutine shr_stream_abort
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_isInit - checks if stream is initialized
!
! !DESCRIPTION:
! Checks if stream is initialized
!
! !REVISION HISTORY:
! 2010-Oct-22 - T. Craig - initial version
!
! !INTERFACE: -----------------------------------------------------------------
logical function shr_stream_isInit(strm,rc)
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType), intent(in) :: strm
integer(SHR_KIND_IN),optional,intent(out) :: rc
!EOP
!--- local ---
character(*),parameter :: subName = "(shr_stream_isInit)"
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
shr_stream_isInit = .false.
if (size(strm%initarr) == initarr_size) then
shr_stream_isInit = .true.
endif
if (present(rc)) rc = 0
end function shr_stream_isInit
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_setInit - Sets stream init flag to TRUE
!
! !DESCRIPTION:
! Checks if stream is initialized
!
! !REVISION HISTORY:
! 2010-Oct-22 - T. Craig - initial version
!
! !INTERFACE: -----------------------------------------------------------------
subroutine shr_stream_setInit(strm,rc)
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType), intent(inout) :: strm
integer(SHR_KIND_IN),optional,intent(out) :: rc
!EOP
!--- local ---
integer(SHR_KIND_IN) :: ier
character(*),parameter :: subName = "(shr_stream_setInit)"
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
strm%init = .true.
deallocate(strm%initarr,stat=ier)
allocate(strm%initarr(initarr_size))
if (present(rc)) rc = 0
end subroutine shr_stream_setInit
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_clearInit - Sets stream init flag to TRUE
!
! !DESCRIPTION:
! Checks if stream is initialized
!
! !REVISION HISTORY:
! 2010-Oct-22 - T. Craig - initial version
!
! !INTERFACE: -----------------------------------------------------------------
subroutine shr_stream_clearInit(strm,rc)
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType), intent(inout) :: strm
integer(SHR_KIND_IN),optional,intent(out) :: rc
!EOP
!--- local ---
integer(SHR_KIND_IN) :: ier
character(*),parameter :: subName = "(shr_stream_clearInit)"
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
strm%init = .true.
deallocate(strm%initarr,stat=ier)
allocate(strm%initarr(initarr_size + 5))
if (present(rc)) rc = 0
end subroutine shr_stream_clearInit
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_stream_bcast -- bcast stream
!
! !DESCRIPTION:
! Return internal debug level, 0 = production
! \newline
! General Usage: call shr\_stream\_bcast(level)
!
! !REVISION HISTORY:
! 2005-May-10 - B. Kauffman - first version
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_stream_bcast(stream,comm,rc)
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_stream_streamType), intent(inout) :: stream
integer(SHR_KIND_IN), intent(in) :: comm
integer(SHR_KIND_IN),optional,intent(out) :: rc
!EOP
!--- locals ---
integer :: n,nt
integer :: pid
!--- formats ---
character(*),parameter :: subName = '(shr_stream_bcast) '
character(*),parameter :: F00 = "('(shr_stream_bcast) ',a) "
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
if ( present(rc) ) rc = 0
call shr_mpi_commRank(comm,pid,subName)
call shr_mpi_bcast(stream%init ,comm,subName)
call shr_mpi_bcast(stream%nFiles ,comm,subName)
call shr_mpi_bcast(stream%dataSource ,comm,subName)
call shr_mpi_bcast(stream%filePath ,comm,subName)
call shr_mpi_bcast(stream%yearFirst ,comm,subName)
call shr_mpi_bcast(stream%yearLast ,comm,subName)
call shr_mpi_bcast(stream%yearAlign ,comm,subName)
call shr_mpi_bcast(stream%offset ,comm,subName)
call shr_mpi_bcast(stream%taxMode ,comm,subName)
call shr_mpi_bcast(stream%k_lvd ,comm,subName)
call shr_mpi_bcast(stream%n_lvd ,comm,subName)
call shr_mpi_bcast(stream%found_lvd ,comm,subName)
call shr_mpi_bcast(stream%k_gvd ,comm,subName)
call shr_mpi_bcast(stream%n_gvd ,comm,subName)
call shr_mpi_bcast(stream%found_gvd ,comm,subName)
call shr_mpi_bcast(stream%fldListFile ,comm,subName)
call shr_mpi_bcast(stream%fldListModel,comm,subName)
call shr_mpi_bcast(stream%domFileName ,comm,subName)
call shr_mpi_bcast(stream%domFilePath ,comm,subName)
call shr_mpi_bcast(stream%domTvarName ,comm,subName)
call shr_mpi_bcast(stream%domXvarName ,comm,subName)
call shr_mpi_bcast(stream%domYvarName ,comm,subName)
call shr_mpi_bcast(stream%domMaskName ,comm,subName)
call shr_mpi_bcast(stream%calendar ,comm,subName)
do n = 1,stream%nFiles
call shr_mpi_bcast(stream%file(n)%name ,comm,subName)
call shr_mpi_bcast(stream%file(n)%haveData,comm,subName)
call shr_mpi_bcast(stream%file(n)%nt ,comm,subName)
nt = stream%file(n)%nt
if (pid /= 0) allocate(stream%file(n)%date(nt),stream%file(n)%secs(nt))
call shr_mpi_bcast(stream%file(n)%date ,comm,subName)
call shr_mpi_bcast(stream%file(n)%secs ,comm,subName)
enddo
end subroutine shr_stream_bcast
!===============================================================================
end module shr_stream_mod
!===============================================================================