!===============================================================================
! SVN $Id: shr_alarm_mod.F90 239 2006-02-08 19:02:33Z kauff $
! SVN $URL: https://svn-ccsm-models.cgd.ucar.edu/csm_share/trunk/shr/shr_alarm_mod.F90 $
!===============================================================================
!BOP ===========================================================================
!
! !MODULE: shr_ncio_mod.F90 --- Module to handle reading and writing of NetCDF data
!
! !DESCRIPTION:
!
! A module to handle the reading and writing of scalar data to NetCDF files for the
! purpose of storing scalar netCDF data in either: integer, character, or logical format.
!
! Typical usage:
!
! ! Initialize a descripVar
! call shr_ncio_descripInit( DescripVar(n), Name="T", LongName= &
! "Globally averaged Temperature of surface", &
! Units="K", RealR8Data=.true., RealR8Fill=1.e+36 )
! ! Read in the file
! FileType="glob avg T file"
! call shr_ncio_open( NCFileName, MasterTask, FileType, ncId, exists )
! call shr_ncio_descripRead( ncId, nVars, mpicom, MasterTask, DescripVar )
! ! Do any other NetCDF reading on ncID....
!...
! call shr_ncio_close( ncId, MasterTask, NCFilename, type=FileType )
! ! Return the name of the descripVar
! name = shr_ncio_descripName( DescripVar(n) )
! ! Get the data inside the variable
! glob_t = shr_ncio_descripGetRealR8( DescripVar(n) )
! ! Now set the scalar data of the variable
! call shr_ncio_descripSet( DescriptVar(n), Name="T", RealR8Data=glob_avg_t )
! ! Write the scalar data to a file
! FileType="glob avg T file"
! call shr_ncio_open( NCFileName, MasterTask, FileType, ncId, exists )
! call shr_ncio_descripWrite( ncId, nVars, mpicom, MasterTask, exists, DescripVar )
! ! Do any other NetCDF writing on ncID....
!...
! call shr_ncio_close( ncId, MasterTask, NCFilename, FileType )
!
! !REMARKS:
!
! !REVISION HISTORY:
! 2005-Dec-20 - E. Kluzek - creation
!
! !INTERFACE: ------------------------------------------------------------------
MODULE shr_ncio_mod 7,5
! !USES:
use shr_kind_mod
, only: SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_IN, &
SHR_KIND_R8, SHR_KIND_I8, &
SHR_KIND_R8
use shr_sys_mod
, only: shr_sys_flush
use shr_const_mod
, only: shr_const_spval
use shr_log_mod
, only: s_loglev => shr_log_Level
use shr_log_mod
, only: s_logunit => shr_log_Unit
use netcdf
implicit none
private ! default private
! !PUBLIC TYPES:
public :: shr_ncio_descripType ! NetCDF data description type
! !PUBLIC MEMBER FUNCTIONS
public :: shr_ncio_descripSetDefault ! Set list of descrip variables to default settings
public :: shr_ncio_descripInit ! Setup variable and variable Names and types
public :: shr_ncio_descripPutData ! Set a variable with data
public :: shr_ncio_descripName ! Get the Name from the ncio variable
public :: shr_ncio_descripGetString ! Get the string value from the ncio variable
public :: shr_ncio_descripGetInteger ! Get the integer value from the ncio variable
public :: shr_ncio_descripGetLogical ! Get the logical value from the ncio variable
public :: shr_ncio_descripGetRealR8 ! Get the real value from the ncio variable
public :: shr_ncio_descripRead ! Read in file
public :: shr_ncio_descripWrite ! Write out to file
public :: shr_ncio_open ! Open NetCDF file for reading/writing/appending
public :: shr_ncio_close ! Close a NetCDF file
public :: shr_ncio_setDebug ! Set debug level of printing
public :: shr_ncio_setAbort ! Set flag if should abort on error or not
! !PUBLIC DATA MEMBERS:
! no public data members
!EOP
! Private member functions:
private :: shr_ncio_logical2Int ! Convert logical into an integer
private :: shr_ncio_int2Logical ! Convert integer back into a logical
private :: shr_ncio_abort ! Local abort method
!--- Private data to use for data that is not specified yet ---
integer, parameter :: shr_ncio_integerFill = -99999
character(len=*), parameter :: shr_ncio_stringFill = '----NOTSET----'
real(SHR_KIND_R8), parameter :: shr_ncio_realR8Fill = shr_const_spval
integer, parameter :: maxDims = 1
!--- Public NetCDF description type ---
type shr_ncio_descripType
private ! Opaque type
character(SHR_KIND_CS) :: Name = shr_ncio_stringFill ! Variable Name
integer :: XType = shr_ncio_integerFill ! Variable type
integer :: id = shr_ncio_integerFill ! variable id number
integer :: nDims ! number of dimensions
integer :: DimSizes(maxDims) ! Sizes of dimensions
character(SHR_KIND_CS) :: DimNames(maxDims) ! Names of dimensions
character(SHR_KIND_CS) :: Units = shr_ncio_stringFill ! Units of variable
character(SHR_KIND_CL) :: StringData = shr_ncio_stringFill ! String scalar to write
character(SHR_KIND_CL) :: ListDescrips = shr_ncio_stringFill! List of descriptions
integer :: IntegerData = shr_ncio_integerFill! Integer scalar to write
real(SHR_KIND_R8) :: RealR8Data = shr_ncio_realR8Fill ! Real scalar to write
integer :: IntegerFill = shr_ncio_integerFill! Integer Fill-value
real(SHR_KIND_R8) :: RealR8Fill = shr_ncio_realR8Fill ! Real Fill-value
logical :: LogicalData ! Logical scalar to write
integer, pointer :: ListValues(:) ! List values
character(SHR_KIND_CL) :: LongName = shr_ncio_stringFill ! Long Name of variable
end type shr_ncio_descripType
!--- Private data to signify which type of data will be written ---
integer, parameter :: shr_ncio_integerDataValue = 1 ! Data is integer
integer, parameter :: shr_ncio_stringDataValue = 2 ! Data is string
integer, parameter :: shr_ncio_logicalDataValue = 3 ! Data is logical
integer, parameter :: shr_ncio_realR8DataValue = 4 ! Data is real r8
logical, save :: doAbort = .true. ! If abort on error or not
integer, save :: debugLevel = 1 ! Debug level
character(len=*), parameter :: shrCharacterDimName = "shr_character"
!===============================================================================
CONTAINS
!===============================================================================
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_descripSetDefault -- Set ncio_descrip variables to defaults
!
! !DESCRIPTION:
!
! Set an array of shr_ncio_descrip variables to the default settings. This
! allows you to re-initialize them to different values if you so choose, It's
! also important on compilers that do NOT recognize structure initialization
! (as above) such as on PGI.
!
! !INTERFACE: ------------------------------------------------------------------
SUBROUTINE shr_ncio_descripSetDefault( NVars, DescripVars ) 3
! !USES:
implicit none
! !INPUT/OUTPUT PARAMETERS:
integer, intent(IN) :: nVars ! Number of variables
type(shr_ncio_descripType), intent(INOUT) :: DescripVars(nVars) ! Output description variables
!EOP
!----- local -----
character(len=*), parameter :: subName = '(shr_ncio_descripSetDefault) '
integer :: i ! index
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
do i = 1, NVars
DescripVars(i)%Name = shr_ncio_stringFill ! Variable Name
DescripVars(i)%XType = shr_ncio_integerFill ! Variable type
DescripVars(i)%id = shr_ncio_integerFill ! variable id number
DescripVars(i)%Units = shr_ncio_stringFill ! Units of variable
DescripVars(i)%StringData = shr_ncio_stringFill ! String scalar to write
DescripVars(i)%ListDescrips = shr_ncio_stringFill ! List of descriptions
DescripVars(i)%IntegerData = shr_ncio_integerFill ! Integer scalar to write
DescripVars(i)%RealR8Data = shr_ncio_realR8Fill ! Real scalar to write
DescripVars(i)%IntegerFill = shr_ncio_integerFill ! Integer Fill-value
DescripVars(i)%RealR8Fill = shr_ncio_realR8Fill ! Real Fill-value
DescripVars(i)%LongName = shr_ncio_stringFill ! Long Name of variable
end do
END SUBROUTINE shr_ncio_descripSetDefault
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_descripInit -- Set ncio_descrip variable Names
!
! !DESCRIPTION:
!
! Initial setup of a ncio descrip variable. Set logical data flags either to:
! StringData, ! IntegerData, LogicalData, or RealR8Data. Can optionally set
! the LongName, Units, and fillvalue (only for RealR8 or Integer data). Note,
! if you select IntegerData for the data-type, you can only set the IntergerFill
! value, NOT the RealR8Fill value and vica-versa. If you pick IntegerData
! as the data-type you can also select ListDescrips and ListIntValues with
! the list of valid values and a description for the meaning of each of those
! values. In this case, attributes giving the values and the matching
! description of that value will be added to the output NetCDF file.
! For example, if you have integer data to describe the vegetation type, with
! a list of 12 different vegetation types, you give a colen delimited list to
! describe each type, as well as ListIntValues to give the corresponding value
! that goes with each description in the list.
!
! !INTERFACE: ------------------------------------------------------------------
SUBROUTINE shr_ncio_descripInit( DescripVar, Name, LongName, Units, & 19,19
StringData, IntegerData, LogicalData, &
RealR8Data, IntegerFill, &
RealR8Fill, ListDescrips, &
ListIntValues, nDims, dimSizes )
! !USES:
use shr_string_mod
, only: shr_string_listIsValid, shr_string_listGetNum
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_ncio_descripType), intent(INOUT) :: DescripVar! Output description variable
character(len=*), intent(IN) :: Name ! Short name of data
character(len=*), intent(IN), optional :: LongName ! Longname of data
character(len=*), intent(IN), optional :: Units ! Physical units of data
logical, intent(IN), optional, target :: StringData ! Flag if data is string-type
logical, intent(IN), optional, target :: IntegerData ! Flag if data is integer-type
logical, intent(IN), optional, target :: LogicalData ! Flag if data is logical-type
logical, intent(IN), optional, target :: RealR8Data ! Flag if data is string-type
real(SHR_KIND_R8), intent(IN), optional :: RealR8Fill ! Fill value for real-R8 data
integer, intent(IN), optional, target :: IntegerFill ! Fill value for integer data
! --- For integer-list, description of each value as colen delimited list ---
character(len=*), intent(IN), optional :: ListDescrips
! --- For integer-list, integer values that go with each description ----
integer, intent(IN), optional :: ListIntValues(:)
integer, intent(IN), optional :: nDims ! Number of dimensions of variable
integer, intent(IN), optional :: dimSizes(:) ! Sizes of each dimension
!EOP
!----- local -----
character(len=*), parameter :: subName = '(shr_ncio_descripInit) '
logical :: NotSet ! Type not set yet or not
integer :: nList ! Number of values in list
!-------------------------------------------------------------------------------
! Notes:
!
! Currently only implemented for scalar data, nDims and dimSizes are not fully
! tested.
!-------------------------------------------------------------------------------
! --- Check if setting more than one data-type ------
if ( (PRESENT(StringData) .and. PRESENT(IntegerData)) .or. &
(PRESENT(StringData) .and. PRESENT(LogicalData)) .or. &
(PRESENT(StringData) .and. PRESENT(RealR8Data )) .or. &
(PRESENT(IntegerData) .and. PRESENT(LogicalData)) .or. &
(PRESENT(IntegerData) .and. PRESENT(RealR8Data )) .or. &
(PRESENT(LogicalData) .and. PRESENT(RealR8Data )) )then
call shr_ncio_abort
( subName//': can not set more than one variable type' )
end if
if ( PRESENT(nDims) .or. PRESENT(dimSizes) )then
call shr_ncio_abort
( subName//': currently nDims and dimSizes are NOT implemented' )
end if
if ( PRESENT(nDims) .and. .not. PRESENT(dimSizes) &
.or. (.not. PRESENT(nDims) .and. PRESENT(dimSizes) ) )then
call shr_ncio_abort
( subName//': if nDims set so must also dimSizes' )
else if ( PRESENT(nDims) .and. PRESENT(dimSizes) )then
if ( nDims /= size(dimSizes) )then
call shr_ncio_abort
( subName//': if nDims NOT set to same dimensionality as dimSizes' )
end if
if ( nDims > maxDims )then
call shr_ncio_abort
( subName//': nDims > size of max dimensions' )
end if
DescripVar%nDims = nDims
DescripVar%dimSizes(:) = dimSizes(:nDims)
end if
! --- Name, check if name already defined ------
if ( DescripVar%Name == shr_ncio_stringFill )then
DescripVar%Name = Name
! --- If name already defined, but you are asking for a different name -- abort
else if ( trim(Name) /= trim(DescripVar%Name) )then
call shr_ncio_abort
( subName//': bad Name: '//trim(Name)// &
' sent to variable already defined as:'// &
trim(DescripVar%Name) )
! --- If name is the same, as previously defined name -- silently continue ------
end if
! --- Long-name and units attributes ------
if ( PRESENT(LongName) ) DescripVar%LongName = LongName
if ( PRESENT(Units) ) DescripVar%Units = Units
NotSet = .true.
! --- For String Data type ------
if ( PRESENT(StringData) )then
NotSet = .false.
DescripVar%XType = shr_ncio_stringDataValue
if ( .not. PRESENT(nDims) )then
DescripVar%nDims = 1
DescripVar%dimSizes(1) = len(DescripVar%StringData)
end if
DescripVar%dimNames(1) = shrCharacterDimName
if ( .not. PRESENT(Units) ) DescripVar%Units = "string"
end if
! --- For Integer Data type ------
if ( PRESENT(IntegerData) )then
if ( .not. NotSet ) call shr_ncio_abort
( subName//': trying to define '// &
'to more than one data-type' )
NotSet = .false.
DescripVar%XType = shr_ncio_integerDataValue
if ( .not. PRESENT(nDims) )then
DescripVar%nDims = 0
end if
if ( PRESENT(IntegerFill) )then
DescripVar%IntegerFill = IntegerFill
DescripVar%IntegerData = IntegerFill
end if
! --- For an integer list ------
if ( PRESENT(ListDescrips) )then
if ( .not. PRESENT(ListIntValues) )then
call shr_ncio_abort
( subName//': setting ListDescrips without '// &
'setting ListIntValues' )
end if
if ( .not. shr_string_listIsValid( ListDescrips ) )then
call shr_ncio_abort
( subName//': ListDescrips is not a valid '// &
'list of descriptions' )
end if
nList = shr_string_listGetNum
( ListDescrips )
if ( size(ListIntValues) /= nList )then
call shr_ncio_abort
( subName//': number of list descriptions '// &
'inconsistent with number of list integer values' )
end if
allocate( DescripVar%ListValues(nList) )
DescripVar%ListDescrips = ListDescrips
DescripVar%ListValues(:) = ListIntValues(:)
else
if ( PRESENT(ListIntValues) )then
call shr_ncio_abort
( subName//': setting ListIntValues '// &
'without setting ListDescrips' )
end if
end if
else
if ( PRESENT(IntegerFill) )then
call shr_ncio_abort
( subName//': setting integer FillValue '// &
'without setting IntegerData' )
end if
if ( PRESENT(ListDescrips) .or. PRESENT(ListIntValues) )then
call shr_ncio_abort
( subName//': setting ListDescrips or '// &
'ListIntValues without setting IntegerData' )
end if
end if
! --- Logical data ------
if ( PRESENT(LogicalData) )then
if ( .not. NotSet ) call shr_ncio_abort
( subName//': trying '// &
'to define to more than one data-type' )
NotSet = .false.
DescripVar%XType = shr_ncio_logicalDataValue
if ( .not. PRESENT(nDims) )then
DescripVar%nDims = 0
end if
if ( .not. PRESENT(Units) ) DescripVar%Units = &
"logical flag (0=false)"
end if
! --- Real-R8 data ------
if ( PRESENT(RealR8Data) )then
if ( .not. NotSet ) call shr_ncio_abort
( &
subName//': trying to define to more than one data-type' )
NotSet = .false.
DescripVar%XType = shr_ncio_realR8DataValue
if ( .not. PRESENT(nDims) )then
DescripVar%nDims = 0
end if
if ( PRESENT(RealR8Fill) )then
DescripVar%RealR8Fill = RealR8Fill
DescripVar%RealR8Data = RealR8Fill
end if
else
if ( PRESENT(RealR8Fill) )then
call shr_ncio_abort
( subName//': setting realr8 FillValue '// &
'without setting RealR8Data' )
end if
end if
if ( NotSet ) call shr_ncio_abort
( subName//': called without giving '// &
'a value to set' )
END SUBROUTINE shr_ncio_descripInit
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_descripPutData -- Set a ncio_descrip variable type
!
! !DESCRIPTION:
!
! Set the data of a ncio descrip variable. Data is set to either the string,
! integer, logical or Real-R8 data value input. Can NOT specify more than one
! data-type. Check that name agrees with name on variable type, or else abort.
!
! !INTERFACE: ------------------------------------------------------------------
SUBROUTINE shr_ncio_descripPutData( DescripVar, Name, StringData, & 19,9
IntegerData, LogicalData, RealR8Data )
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_ncio_descripType), intent(INOUT) :: DescripVar ! descrip variable to set
character(len=*), intent(IN) :: Name ! Name of this variable
character(len=*), optional, intent(IN), target :: StringData ! String-data value
integer, target, optional, intent(IN) :: IntegerData ! Integer-data value
logical, target, optional, intent(IN) :: LogicalData ! Logical-data value
real(SHR_KIND_R8), optional,intent(IN), target :: RealR8Data ! Real-R8-data value
!EOP
!----- local -----
character(len=*), parameter :: subName = '(shr_ncio_descripPutData) '
logical :: NotSet ! Flag if data is not set yet
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
! --- Check if too many data values are set (can only be one!) -----
if ( (PRESENT(StringData) .and. PRESENT(IntegerData)) .or. &
(PRESENT(StringData) .and. PRESENT(LogicalData)) .or. &
(PRESENT(StringData) .and. PRESENT(RealR8Data )) .or. &
(PRESENT(IntegerData) .and. PRESENT(LogicalData)) .or. &
(PRESENT(IntegerData) .and. PRESENT(RealR8Data )) .or. &
(PRESENT(LogicalData) .and. PRESENT(RealR8Data )) )then
call shr_ncio_abort
( subName//': can not set more than one variable type' )
end if
! --- Make sure name is set and agrees with the input -----
if ( DescripVar%Name == shr_ncio_stringFill )then
call shr_ncio_abort
( subName//': descrip variable has not been defined '// &
'yet with shr_ncio_descripInit' )
else if ( trim(Name) /= trim(DescripVar%Name) )then
call shr_ncio_abort
( subName//': bad Name: '//trim(Name)// &
' sent to variable already defined as:'// &
trim(DescripVar%Name) )
end if
NotSet = .true.
!-----------------------------------------------------------------------------
! ----------- Test for each type of data ------------
! Make sure data sent in is consistent with expected type
! And track if data was set, so can abort if no data was set
!-----------------------------------------------------------------------------
! --- If string data -------
if ( PRESENT(StringData) )then
NotSet = .false.
if ( DescripVar%XType /= shr_ncio_stringDataValue )then
call shr_ncio_abort
( subName//': Setting descrip variable to string '// &
'which is wrong variable type' )
end if
if ( len_trim(StringData) > len(DescripVar%StringData) )then
call shr_ncio_abort
( subName//': Length of input string data longer '// &
'than storage size of DescripVar type' )
end if
DescripVar%StringData(1:len(DescripVar%StringData)) = ' '
DescripVar%StringData(:len_trim(StringData)) = trim(StringData)
end if
! --- If integer data -------
if ( PRESENT(IntegerData) )then
NotSet = .false.
if ( DescripVar%XType /= shr_ncio_integerDataValue )then
call shr_ncio_abort
( subName//': Setting descrip variable to integer '// &
'which is wrong variable type' )
end if
DescripVar%IntegerData = IntegerData
end if
! --- If logical data -------
if ( PRESENT(LogicalData) )then
NotSet = .false.
if ( DescripVar%XType /= shr_ncio_logicalDataValue )then
call shr_ncio_abort
( subName//': Setting descrip variable to logical '// &
'which is wrong variable type' )
end if
DescripVar%LogicalData = LogicalData
end if
! --- If real R8 data -------
if ( PRESENT(RealR8Data) )then
NotSet = .false.
if ( DescripVar%XType /= shr_ncio_realR8DataValue )then
call shr_ncio_abort
( subName//': Setting descrip variable to realr8 '// &
'which is wrong variable type' )
end if
DescripVar%RealR8Data = RealR8Data
end if
! --- If no data was set abort with an error -------
if ( NotSet ) call shr_ncio_abort
( subName//': called without giving a '// &
'value to set' )
END SUBROUTINE shr_ncio_descripPutData
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_descripName -- Return the Name of this ncio variable
!
! !DESCRIPTION:
!
! Returns Name of the variable
!
! !INTERFACE: ------------------------------------------------------------------
FUNCTION shr_ncio_descripName( DescripVar ) 39
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_ncio_descripType), intent(IN) :: DescripVar
character(len=SHR_KIND_CS) :: shr_ncio_descripName
!EOP
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
shr_ncio_descripName = trim(DescripVar%Name)
END FUNCTION shr_ncio_descripName
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_descripGetString -- Return the string value of this ncio variable
!
! !DESCRIPTION:
!
! Returns the string value from this variable
!
! !INTERFACE: ------------------------------------------------------------------
FUNCTION shr_ncio_descripGetString( DescripVar ) 8,5
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_ncio_descripType), intent(IN) :: DescripVar ! NetCDF description variable
character(len=SHR_KIND_CL) :: shr_ncio_descripGetString ! Returned string value of data
!EOP
!----- local -----
character(len=*), parameter :: subName = '(shr_ncio_descripGetString) '
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
! --- If this structure hasn't been initialized yet -- abort with an error -------
if ( DescripVar%Name == shr_ncio_stringFill )then
call shr_ncio_abort
( subName//': input shr_ncio description variable '// &
'has not been initializated yet: ' )
end if
! --- If this isn't a string type of variable -- abort with an error -------
if ( DescripVar%XType /= shr_ncio_stringDataValue )then
call shr_ncio_abort
( subName//': trying to get a string from a '// &
'different variable type' )
end if
shr_ncio_descripGetString
(:) = ' '
shr_ncio_descripGetString
(1:len_trim(DescripVar%StringData)) = &
trim(DescripVar%StringData)
! --- If data not set yet abort with an error -------
if ( shr_ncio_descripGetString== shr_ncio_stringFill )then
call shr_ncio_abort
( subName//': Returned string has not been set yet' )
end if
END FUNCTION shr_ncio_descripGetString
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_descripGetInteger -- Return the integer value of this ncio variable
!
! !DESCRIPTION:
!
! Returns the integer value from this variable
!
! !INTERFACE: ------------------------------------------------------------------
integer FUNCTION shr_ncio_descripGetInteger( DescripVar ) 2,3
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_ncio_descripType), intent(IN) :: DescripVar ! Input NetCDF description variable
!EOP
!----- local -----
character(len=*), parameter :: subName = '(shr_ncio_descripGetInteger) '
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
! --- If this structure hasn't been initialized yet -- abort with an error -------
if ( DescripVar%Name == shr_ncio_stringFill )then
call shr_ncio_abort
( subName//': input shr_ncio description '// &
'variable has not been initializated yet: ' )
end if
! --- If this isn't a integer type of variable -- abort with an error -------
if ( DescripVar%XType /= shr_ncio_integerDataValue )then
call shr_ncio_abort
( subName//': trying to get an integer from a '// &
'different variable type' )
end if
! --- If data not set yet abort with an error -------
shr_ncio_descripGetInteger = DescripVar%IntegerData
if ( shr_ncio_descripGetInteger == shr_ncio_integerFill )then
call shr_ncio_abort
( subName//': Returned integer has not been set yet' )
end if
END FUNCTION shr_ncio_descripGetInteger
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_descripGetLogical -- Return the logical value of this ncio variable
!
! !DESCRIPTION:
!
! Returns the logical value from this variable
!
! !INTERFACE: ------------------------------------------------------------------
logical FUNCTION shr_ncio_descripGetLogical( DescripVar ) 6,2
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_ncio_descripType), intent(IN) :: DescripVar ! Input NetCDF description variable
!EOP
!----- local -----
character(len=*), parameter :: subName = '(shr_ncio_descripGetLogical) '
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
! --- If this structure hasn't been initialized yet -- abort with an error ------
if ( DescripVar%Name == shr_ncio_stringFill )then
call shr_ncio_abort
( subName//': input shr_ncio description '// &
'variable has not been initializated yet: ' )
end if
! --- If this isn't a logical type of variable -- abort with an error ------
if ( DescripVar%XType /= shr_ncio_logicalDataValue )then
call shr_ncio_abort
( subName//': trying to get an logical from a '// &
'different variable type' )
end if
shr_ncio_descripGetLogical = DescripVar%LogicalData
END FUNCTION shr_ncio_descripGetLogical
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_descripGetRealR8 -- Return the realr8 value of this ncio variable
!
! !DESCRIPTION:
!
! Returns the realr8 value from this variable
!
! !INTERFACE: ------------------------------------------------------------------
real(SHR_KIND_R8) FUNCTION shr_ncio_descripGetRealR8( DescripVar ) 2,3
implicit none
! !INPUT/OUTPUT PARAMETERS:
type(shr_ncio_descripType), intent(IN) :: DescripVar ! Input NetCDF description variable
!EOP
!----- local -----
character(len=*), parameter :: subName = '(shr_ncio_descripGetRealR8) '
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
! --- If this structure hasn't been initialized yet -- abort with an error ------
if ( DescripVar%Name == shr_ncio_stringFill )then
call shr_ncio_abort
( subName//': input shr_ncio description variable '// &
'has not been initializated yet: ' )
end if
! --- If this isn't a real r8 type of variable -- abort with an error ------
if ( DescripVar%XType /= shr_ncio_realR8DataValue )then
call shr_ncio_abort
( subName//': trying to get an real from a '// &
'different variable type' )
end if
! --- If data not set yet abort with an error ------
shr_ncio_descripGetRealR8 = DescripVar%RealR8Data
if ( shr_ncio_descripGetRealR8 == shr_ncio_realR8Fill )then
call shr_ncio_abort
( subName//': Returned realr8 has not been set yet' )
end if
END FUNCTION shr_ncio_descripGetRealR8
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_descripRead -- Read in netCDF restart file
!
! !DESCRIPTION:
!
! Read in restart file information from netCDF input restart file
!
! !INTERFACE: ------------------------------------------------------------------
SUBROUTINE shr_ncio_descripRead( ncId, nVars, prefix, mpicom, MasterTask, var ) 6,21
! !USES:
use shr_string_mod
, only: shr_string_lastIndex
use shr_mpi_mod
, only: shr_mpi_bcast
implicit none
! !INPUT/OUTPUT PARAMETERS:
integer, intent(IN) :: ncId ! NetCDF file unit id
integer, intent(IN) :: nVars ! Number of variables
character(len=*), intent(IN), optional :: prefix ! Prefix in front of variable Names
integer, intent(IN), optional :: MPICom ! MPI communicator
logical, intent(IN), optional :: MasterTask ! If Master PE task or not
type(shr_ncio_descripType), intent(INOUT) :: var(:) ! NetCDF description structure
!----- local -----
character(len=*), parameter :: subName = "(shr_ncio_descripRead) "
logical :: MasterTask2 ! If Master PE task or not
integer :: rCode ! Return code
integer :: nDims ! Number of dimensions on file
integer :: VarDimIds(maxDims) ! Array of dimension id's for this variable
integer :: dimIds(maxDims) ! Dimension id number
integer :: type ! Type of variable
integer :: i, dim ! Index
integer :: nChars ! Number of characters in string
integer :: n ! Character index
character(SHR_KIND_CL) :: StringData ! String value read in
integer :: IntegerData ! Integer value read in
real(SHR_KIND_R8) :: RealR8Data ! Real value to read in
character(len=SHR_KIND_CS) :: prefixUse ! Prefix in front of variable Names
!-------------------------------------------------------------------------------
! Notes:
! Currently this interface can NOT be used to read in non-scalar data.
!-------------------------------------------------------------------------------
if ( present(MasterTask) )then
MasterTask2 = MasterTask
else
MasterTask2 = .true.
end if
if ( present(prefix) )then
prefixUse = prefix
else
prefixUse = ""
end if
if ( MasterTask2 )then
!-------------------------------------------------------------------------
! Loop through variables
!-------------------------------------------------------------------------
do i = 1, nVars
if ( debugLevel > 1 .and. s_loglev > 0) write(s_logunit,*) 'Read variable: ', trim(var(i)%Name)
! --- If name not set, hasn't been initialized -- abort with an error -----
if ( trim(var(i)%Name) == shr_ncio_stringFill )then
write(s_logunit,'(a,i3,a,i3)') 'variable number = ', i, ' of ', nVars
call shr_ncio_abort
( subName//': variable name not defined -- '// &
'DescripVarSet not called' )
end if
! --- Get variable ID -----
rcode = nf90_inq_varid(ncId,trim(prefixUse)//trim(var(i)%Name),var(i)%id )
call shr_ncio_abort
( subName//': variable '// trim(var(i)%Name)//' not found', rcode )
! --- Get type of variable -----
rcode = nf90_inquire_variable(ncId, var(i)%id, nDims=nDims, &
XType=type )
call shr_ncio_abort
( subName// ': error on inquiry of '//var(i)%Name, rcode )
if (nDims /= var(i)%nDims )then
write(s_logunit,'(a,a,a,i4,a,i4)') 'Number of dimensions for variable', &
trim(var(i)%name), ' :', nDims, ' expected:', var(i)%nDims
call shr_ncio_abort
( subName//': '//var(i)%Name// &
' dimension size different than expected' )
end if
! --- Read in the dimension names for this variable ----------------------
do dim = 1, nDims
rcode = nf90_inq_dimId(ncId, var(i)%dimNames(dim), dimIds(dim) )
call shr_ncio_abort
( subName// ': error gettting dimension', rcode )
end do
! --- Check that dimension ids are correct -------------------------------
if ( nDims > 0 )then
rcode = nf90_inquire_variable(ncId, var(i)%id, dimIds=VarDimIds )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on inquiry of dimIds'//var(i)%Name )
if ( any(dimIds /= VarDimIds) ) call shr_ncio_abort
( subName// &
': dimIds not correct' )
end if
! --- If variable string data type -----
if (var(i)%XType == shr_ncio_stringDataValue )then
if ( type /= NF90_CHAR ) call shr_ncio_abort
( subName//': '// &
var(i)%Name//' not proper type' )
rcode = nf90_get_att(ncId, var(i)%id, "nChars", nChars)
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error getting nChars from : '//var(i)%Name )
rcode = nf90_get_var( ncId, varid=var(i)%id, values=StringData, &
count=(/nChars/) )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on get of '//var(i)%Name )
var(i)%StringData(:) = ' '
var(i)%StringData(:nChars) = StringData(:nChars)
! --- If integer data type --------
else if (var(i)%XType == shr_ncio_integerDataValue )then
if ( type /= NF90_INT ) call shr_ncio_abort
( subName//': '// &
var(i)%Name//' not proper type' )
rcode = nf90_get_var( ncId, var(i)%id, IntegerData)
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on get of '//var(i)%Name )
var(i)%IntegerData = IntegerData
! --- If real r8 data type --------
else if (var(i)%XType == shr_ncio_realR8DataValue )then
if ( type /= NF90_DOUBLE) call shr_ncio_abort
( subName//': '// &
var(i)%Name//' not proper type' )
rcode = nf90_get_var( ncId, var(i)%id, RealR8Data )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on get of '//var(i)%Name )
var(i)%RealR8Data = RealR8Data
! --- If logical data type --------
else if (var(i)%XType == shr_ncio_logicalDataValue )then
if ( type /= NF90_INT ) call shr_ncio_abort
( subName//': '// &
var(i)%Name//' not proper type' )
rcode = nf90_get_var( ncId, var(i)%id, IntegerData)
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on get of '//var(i)%Name )
var(i)%LogicalData = shr_ncio_logical2Int
( IntegerData )
! --- Otherwise data type is unknown abort with an error --------
else
call shr_ncio_abort
( subName//': only integer, logical, '// &
'real-r8 or character can not be read for variable ' &
//var(i)%Name )
end if
end do
end if
! --- If MPI broadcast to other MPI tasks -----------------------------------
if ( present(mpicom) )then
if ( debugLevel > 1 .and. s_loglev > 0) write(s_logunit,*) 'Broadcast variables to all tasks'
do i = 1, nVars
if ( var(i)%XType == shr_ncio_stringDataValue )then
call shr_mpi_bcast( var(i)%StringData, mpicom )
else if ( var(i)%XType == shr_ncio_integerDataValue )then
call shr_mpi_bcast( var(i)%IntegerData, mpicom )
else if ( var(i)%XType == shr_ncio_realR8DataValue )then
call shr_mpi_bcast( var(i)%RealR8Data, mpicom )
else if ( var(i)%XType == shr_ncio_logicalDataValue )then
call shr_mpi_bcast( var(i)%LogicalData, mpicom )
else
call shr_ncio_abort
( subName//': invalid ncio type: ' )
end if
end do
end if
END SUBROUTINE shr_ncio_descripRead
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_descripWrite -- Write out netCDF restart file information
!
! !DESCRIPTION:
!
! Write out restart file information to netCDF restart file
!
! !INTERFACE: ------------------------------------------------------------------
SUBROUTINE shr_ncio_descripWrite( ncId, nVars, prefix, mpicom, MasterTask, exists, & 6,22
var )
! !USES:
use shr_string_mod
, only: shr_string_lastindex, shr_string_listGetName, &
shr_string_listGetNum
implicit none
! !INPUT/OUTPUT PARAMETERS:
integer, intent(IN) :: ncId ! NetCDF file id
integer, intent(IN) :: nVars ! Number of variables
character(len=*), intent(IN), optional :: prefix ! Prefix in front of variable Names
integer, intent(IN), optional :: MPICom ! MPI communicator
logical, intent(IN), optional :: MasterTask! If Master PE task or not
logical, intent(IN) :: exists ! If datafile exists already or not
type(shr_ncio_descripType), intent(INOUT) :: var(:) ! NetCDF description structure
!EOP
!----- local -----
character(len=*), parameter :: subName = "(shr_ncio_descripWrite) "
logical :: MasterTask2 ! If Master PE task or not
integer :: rcode ! NetCDF return code
integer :: dimIds(maxDims) ! Dimension id numbers
integer :: i ! Variable index
integer :: dim ! Dimension index
logical :: NotSet ! If variables set yet or not
logical :: DimSet ! If dimension set yet or not
integer :: n ! character index
integer :: type ! data type to write to file
integer :: list ! List index number
integer :: nList ! number of items in list
character(len=SHR_KIND_CL) :: name ! List description name
character(len=SHR_KIND_CS) :: prefixUse ! Prefix in front of variable Names
character(len=*), parameter :: F00= &
"(a,' input: nciD=',i3,' nvars=',i3, ' prefix=',a,' master=',l1,' exists=',l1)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
if ( present(MasterTask) )then
MasterTask2 = MasterTask
else
MasterTask2 = .true.
end if
if ( present(prefix) )then
prefixUse = prefix
else
prefixUse = ""
end if
!-----------------------------------------------------------------------------
if ( debugLevel > 2 .and. s_loglev > 0) write(s_logunit,F00) subName, ncid, nVars, trim(prefixUse), &
MasterTask2, exists
if ( MasterTask2 )then
! --- If file already exists, go to re-define mode -----
if ( exists )then
rcode = nf90_redef(ncId)
call shr_ncio_abort
( subName// ': error on redefine output NetCDF file', rcode )
end if
!--------------------------------------------------------------------------
! Define variables
!--------------------------------------------------------------------------
do i = 1, nVars
NotSet = .false.
if ( debugLevel > 1 .and. s_loglev > 0) write(s_logunit,*) 'Write variable: ', trim(var(i)%Name)
! --- If file exists, check if given variable is already defined -------
if ( exists )then
rcode = nf90_inq_varid(ncId, Name=trim(prefixUse)//trim(var(i)%Name), &
varid=var(i)%id )
if (rcode == nf90_enotvar )then
NotSet = .true.
else if (rcode /= nf90_noerr)then
call shr_ncio_abort
( subName//': error getting variable id' )
end if
end if
! --- If new file or variable NOT defined, define it now ---------------
if ( .not. exists .or. NotSet )then
!--------------------------------------------------------------------
! Define dimensions for this variable if not already defined
!--------------------------------------------------------------------
do dim = 1, var(i)%nDims
DimSet = .false.
rcode = nf90_inq_dimId(ncId, Name=var(i)%dimNames(dim), &
dimId=dimIds(dim))
if ( rcode == nf90_ebaddim )then
DimSet = .true.
else if (rcode /= nf90_noerr)then
call shr_ncio_abort
( subName//': error getting correct '// &
'dimension id for :'//trim(var(i)%dimNames(dim)) )
end if
if ( DimSet )then
rcode = nf90_def_dim(ncId, Name=var(i)%dimNames(dim), &
len=SHR_KIND_CL, dimId=dimIds(dim) )
call shr_ncio_abort
( subName//': error writing dimension', &
rcode )
end if
end do
if ( var(i)%XType == shr_ncio_stringDataValue )then
type = NF90_CHAR
else if ( var(i)%XType == shr_ncio_integerDataValue .or. &
var(i)%XType == shr_ncio_logicalDataValue )then
type = NF90_INT
else if ( var(i)%XType == shr_ncio_realR8DataValue )then
type = NF90_DOUBLE
else
call shr_ncio_abort
( subName// &
': error on variable definition: '// &
trim(var(i)%Name) )
end if
if ( var(i)%NDims > 0 )then
rcode = nf90_def_var( ncId, trim(prefixUse)//trim(var(i)%Name), &
type, dimIds=dimIds, varid=var(i)%id )
else
rcode = nf90_def_var( ncId, trim(prefixUse)//trim(var(i)%Name), &
type, var(i)%id )
end if
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on variable definition: '// &
trim(var(i)%Name) )
end if
!-----------------------------------------------------------------------
! Attributes on variables
!-----------------------------------------------------------------------
rcode = nf90_put_att( ncId, var(i)%id, "long_name", var(i)%LongName )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on putting LongName '// &
'attribute on variable: '// &
trim(var(i)%Name) )
rcode = nf90_put_att( ncId, var(i)%id, "units", var(i)%Units )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on putting Units attribute '// &
'on variable: '//trim(var(i)%Name) )
if ( var(i)%XType == shr_ncio_stringDataValue )then
rcode = nf90_put_att( ncId, var(i)%id, "nChars", &
len_trim(var(i)%StringData) )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on putting nChars '// &
'attribute on variable: '// &
trim(var(i)%Name) )
end if
! --- Fill value for integer data -------
if ( var(i)%IntegerFill /= shr_ncio_integerFill )then
rcode = nf90_put_att( ncId, var(i)%id, "_FillValue", &
var(i)%IntegerFill )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on putting _FillValue '// &
'integer attribute on variable: '// &
var(i)%Name )
rcode = nf90_put_att( ncId, var(i)%id, "missing_value", &
var(i)%IntegerFill )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on putting missing_value'// &
'integer attribute on variable: '// &
var(i)%Name )
end if
! --- Fill value for real-r8 data -------
if ( var(i)%RealR8Fill /= shr_ncio_realR8Fill )then
rcode = nf90_put_att( ncId, var(i)%id, "_FillValue", &
var(i)%RealR8Fill )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on putting _FillValue '// &
'RealR8 attribute on variable: '// &
var(i)%Name )
rcode = nf90_put_att( ncId, var(i)%id, "missing_value", &
var(i)%RealR8Fill )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on putting missing_value'// &
'RealR8 attribute on variable: '// &
var(i)%Name )
end if
! --- List description attributes -------------------------------------
if ( var(i)%ListDescrips /= shr_ncio_stringFill )then
rcode = nf90_put_att( ncId, var(i)%id, "type", "Integer list" )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on putting '// &
' type string attribute on variable: '// &
var(i)%Name )
nList = shr_string_listGetNum
( var(i)%ListDescrips )
do list = 1, nList
call shr_string_listGetName
( var(i)%ListDescrips, list, &
name, rcode )
rcode = nf90_put_att( ncId, var(i)%id, trim(name), &
var(i)%ListValues(list) )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error on putting ' &
//name//' integer attribute on variable: '// &
var(i)%Name )
end do
end if
end do
! --- Take it out of definition mode ------
rcode = nf90_enddef( ncId )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error ending definition mode' )
!--------------------------------------------------------------------------
! Write out variables
!--------------------------------------------------------------------------
do i = 1, nVars
if ( var(i)%XType == shr_ncio_stringDataValue )then
rcode = nf90_put_var( ncId, var(i)%id, trim(var(i)%StringData), &
count=(/len_trim(var(i)%StringData)/) )
else if ( var(i)%XType == shr_ncio_integerDataValue )then
rcode = nf90_put_var( ncId, var(i)%id, var(i)%IntegerData )
else if ( var(i)%XType == shr_ncio_realR8DataValue )then
rcode = nf90_put_var( ncId, var(i)%id, var(i)%RealR8Data )
else if ( var(i)%XType == shr_ncio_logicalDataValue )then
rcode = nf90_put_var( ncId, var(i)%id, shr_ncio_int2Logical
( &
var(i)%LogicalData ) )
else
call shr_ncio_abort
( subName//': invalid ncio type: ' )
end if
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error writing variable: ' &
//var(i)%Name )
end do
end if
END SUBROUTINE shr_ncio_descripWrite
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_open -- Open a NetCDF file for reading, writing or appending
!
! !DESCRIPTION:
!
! Open NetCDF file for reading, writing or appending. If reading, or appending
! abort if file does not exist or on error. If appending
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_ncio_open( NCFileName, MasterTask, FileType, ncId, exists, & 6,3
writing, appending, clobber )
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(len=*), intent(IN) :: NCFileName ! Full path to input fileName to read
logical, intent(IN) :: MasterTask ! If Master PE task or not
character(len=*), intent(IN) :: FileType ! Description of file-type
integer, intent(OUT) :: ncId ! NetCDF file unit
logical, intent(OUT) :: exists ! If file exists or not
logical, intent(IN), optional :: writing ! If should open for writing
logical, intent(IN), optional :: appending ! If should open for appending
logical, intent(IN), optional :: clobber ! if exist clobber
!EOP
!----- local -----
character(len=*), parameter :: subName = "(shr_ncio_open) "
integer :: rCode ! Return code
logical :: writing2 ! If should open for writing
logical :: appending2 ! If should open for appending
logical :: clobber2 ! If exist clobber
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
! --- Only open file on MasterTask -----
if ( MasterTask ) then
if ( present(writing) )then
writing2 = writing
else
writing2 = .false.
end if
if ( present(appending) )then
appending2 = appending
else
appending2 = .false.
end if
if ( appending2 .and. writing2 )then
call shr_ncio_abort
( subName//': can NOT set both appending and writing option!' )
end if
if ( present(clobber)) then
clobber2 = clobber
else
clobber2 = .false.
end if
if ( debugLevel > 0 .and. s_loglev > 0) write(s_logunit,*) 'Open NetCDF file FileType: '//trim(FileType)// &
' Filename: ', trim(NCFileName)
inquire( file = trim(NCFileName), exist = exists )
! If file exists and reading but not appending
if ( exists .and. (.not. writing2) .and. (.not. appending2) )then
if ( debugLevel > 1 .and. s_loglev > 0) write(s_logunit,*) 'File exists open for reading not appending: '
rCode = nf90_open( NCFileName, nf90_nowrite, ncId )
! If file exists and appending
else if ( exists .and. appending2 )then
if ( debugLevel > 1 .and. s_loglev > 0) write(s_logunit,*) 'File exists open for appending: '
rCode = nf90_open( NCFileName, nf90_noclobber, ncId )
! If file exists and writing with no clobber
else if ( exists .and. writing2 .and. .not.clobber2)then
if ( debugLevel > 1 .and. s_loglev > 0) write(s_logunit,*) 'File exists open for writing: '
rCode = nf90_open( NCFileName, nf90_write, ncId )
! If file exists and writing with clobber
else if ( exists .and. writing2 .and. clobber2)then
if ( debugLevel > 1 .and. s_loglev > 0) write(s_logunit,*) 'File exists clobber for writing: '
rCode = nf90_create( NCFileName, NF90_64BIT_OFFSET, ncId )
! If file does NOT exist and writing
else if ( (.not. exists) .and. writing2 )then
if ( debugLevel > 1 .and. s_loglev > 0) write(s_logunit,*) 'File does NOT exist open for writing: '
rCode = nf90_create( NCFileName, NF90_64BIT_OFFSET, ncId )
! If file does NOT exist and want to read or append -- flag an error
else if ( .not. exists .and. ((.not. writing2) .or. appending2) )then
call shr_ncio_abort
( subName//': input file does not exist -- can '// &
'NOT open for reading!' )
end if
! Check error code from above options...
call shr_ncio_abort
( subName//': error opening : '//NCFileName, rcode )
if (clobber2) exists = .false. ! it doesn't exist anymore
end if
end subroutine shr_ncio_open
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_close -- Close a NetCDF file
!
! !DESCRIPTION:
!
! Close a NetCDF file
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_ncio_close( ncId, MasterTask, NCFilename, type ) 6,1
implicit none
! !INPUT/OUTPUT PARAMETERS:
integer, intent(IN) :: ncId ! NetCDF file unit
logical, intent(IN) :: MasterTask ! If Master PE task or not
character(len=*), optional :: NCFileName ! Filename to close
character(len=*), optional :: type ! Type of file to close
!EOP
!----- local -----
character(len=*), parameter :: subName = "(shr_ncio_close) "
character(len=SHR_KIND_CL) :: FileName ! Filename to close
character(len=SHR_KIND_CL) :: FileType ! Description of file to close
integer :: rCode ! Return code
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
! --- Only close file on MasterTask -----
if ( MasterTask )then
if ( PRESENT(NCFileName) )then
FileName = NCFileName
else
FileName = " "
end if
if ( PRESENT(type) )then
FileType = type
else
FileType = " "
end if
rCode = nf90_close( ncId )
if (rcode /= nf90_noerr) call shr_ncio_abort
( subName// &
': error closing '//trim(FileType)//' file: '// &
trim(FileName) )
end if
end subroutine shr_ncio_close
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_setDebug -- set debug level
!
! !DESCRIPTION:
!
! Set debug printing level...
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_ncio_setDebug(iflag)
implicit none
! !INPUT/OUTPUT PARAMETERS:
integer, intent(in) :: iflag ! Flag value to set printing level to
!EOP
!--- local ---
character(*),parameter :: subName = "(shr_ncio_setDebug)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
debugLevel = iflag
end subroutine shr_ncio_setDebug
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_setAbort -- set abort level
!
! !DESCRIPTION:
!
! Set abort level...
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_ncio_setAbort(flag)
implicit none
! !INPUT/OUTPUT PARAMETERS:
logical, intent(in) :: flag ! Flag value to set abort level to
!EOP
!--- local ---
character(*),parameter :: subName = "(shr_ncio_setAbort)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
doAbort = flag
end subroutine shr_ncio_setAbort
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_logical2Int -- Return logical value based on integer input
!
! !DESCRIPTION:
!
! Convert integer to logical. Private to this module.
!
! !INTERFACE: ------------------------------------------------------------------
logical FUNCTION shr_ncio_logical2Int( int_input ) 1,1
implicit none
! !INPUT/OUTPUT PARAMETERS:
integer, intent(IN) :: int_input ! Integer input value to convert to logical
!EOP
!----- local -----
character(len=*), parameter :: subName = '(shr_ncio_logical2Int) '
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
if ( int_input == 0 )then
shr_ncio_logical2Int = .false.
else if ( int_input == 1 )then
shr_ncio_logical2Int = .true.
else
call shr_ncio_abort
( subName//': bad input to shr_ncio_logical2Int: ' )
end if
END FUNCTION shr_ncio_logical2Int
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_int2Logical -- Return integer value based on logical input
!
! !DESCRIPTION:
!
! Convert logical to integer. Private to this module
!
! !INTERFACE: ------------------------------------------------------------------
integer FUNCTION shr_ncio_int2Logical( log_input ) 1
implicit none
! !INPUT/OUTPUT PARAMETERS:
logical, intent(IN) :: log_input ! input logical value to convert to integer
!EOP
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
if ( .not. log_input )then
shr_ncio_int2Logical = 0
else
shr_ncio_int2Logical = 1
end if
END FUNCTION shr_ncio_int2Logical
!===============================================================================
!BOP ===========================================================================
!
! !IROUTINE: shr_ncio_abort -- abort on error
!
! !DESCRIPTION:
!
! Private routine to abort on error
!
! !INTERFACE: ------------------------------------------------------------------
subroutine shr_ncio_abort( string, rcode) 78,2
! !USES:
use shr_sys_mod
, only: shr_sys_abort
implicit none
! !INPUT/OUTPUT PARAMETERS:
character(*),optional,intent(IN) :: string ! abort message
integer, optional,intent(IN) :: rcode ! NetCDF error code
!EOP
!--- local ---
character(SHR_KIND_CL) :: lstring
character(*),parameter :: subName = "(shr_ncio_abort)"
character(*),parameter :: F00 = "('(shr_ncio_abort) ',a)"
!-------------------------------------------------------------------------------
! Notes:
!-------------------------------------------------------------------------------
if (present(rcode))then
if ( rcode == nf90_noerr )then
return
else
write(s_logunit,'(a,a,i3)') subname, ' : NetCDF error code = ', rcode
end if
end if
lstring = ''
if (present(string)) lstring = string
if (doAbort) then
call shr_sys_abort
(lstring)
else
write(s_logunit,F00) ' no abort:'//trim(lstring)
endif
end subroutine shr_ncio_abort
!===============================================================================
!===============================================================================
END MODULE shr_ncio_mod