! $Id$ ! ! Earth System Modeling Framework ! Copyright (c) 2002-2023, University Corporation for Atmospheric Research, ! Massachusetts Institute of Technology, Geophysical Fluid Dynamics ! Laboratory, University of Michigan, National Centers for Environmental ! Prediction, Los Alamos National Laboratory, Argonne National Laboratory, ! NASA Goddard Space Flight Center. ! Licensed under the University of Illinois-NCSA License. ! !============================================================================== #define ESMF_FILENAME "ESMF_IO.F90" !============================================================================== ! ! ESMF I/O Module module ESMF_IOMod ! !============================================================================== ! ! This file contains the I/O class definition and all I/O class methods. ! !------------------------------------------------------------------------------ ! INCLUDES #include "ESMF.h" !============================================================================== !BOPI ! !MODULE: ESMF_IOMod ! ! !DESCRIPTION: ! I/O Fortran API wrapper of C++ implementation. ! ! Defines Fortran wrapper entry points for corresponding ! C++ class {\tt ESMCI\_IO} implementation. ! ! See {\tt ../include/ESMCI\_IO.h} for complete description. ! !------------------------------------------------------------------------------ ! !USES: ! inherit from ESMF base class use ESMF_UtilTypesMod use ESMF_BaseMod use ESMF_InitMacrosMod use ESMF_LogErrMod ! ESMF error handling use ESMF_RHandleMod use ESMF_F90InterfaceMod ! ESMF Fortran-C++ interface helper ! We need some ESMF types use ESMF_ArrayMod use ESMF_VMMod implicit none !------------------------------------------------------------------------------ ! !PRIVATE TYPES: private !------------------------------------------------------------------------------ ! ! ! File format ! type ESMF_IOFileFormat ! sequence ! private ! integer :: iofileformat ! end type ! ! ! Predefined file formats ! type(ESMF_IOFileFormat), parameter :: & ! ESMF_IO_FILEFORMAT_UNSPECIFIED = ESMF_IOFileFormat(0), & ! ESMF_IO_FILEFORMAT_NETCDF = ESMF_IOFileFormat(1), & ! ESMF_IO_FILEFORMAT_HDF = ESMF_IOFileFormat(2), & ! ESMF_IO_FILEFORMAT_XML = ESMF_IOFileFormat(3) ! ! ! What type of I/O - Read only, write only, R/W, append with truncation ! type ESMF_IORWType ! sequence ! private ! integer :: iorwtype ! end type ! ! type(ESMF_IORWType), parameter :: & ! ESMF_IO_RWTYPE_UNSPECIFIED = ESMF_IORWType(0), & ! ESMF_IO_RWTYPE_READONLY = ESMF_IORWType(1), & ! ESMF_IO_RWTYPE_WRITEONLY = ESMF_IORWType(2), & ! ESMF_IO_RWTYPE_READWRITE = ESMF_IORWType(3), & ! ESMF_IO_RWTYPE_APPEND = ESMF_IORWType(4), & ! ESMF_IO_RWTYPE_TRUNCATE = ESMF_IORWType(5) ! ! !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ ! ! ESMF_IO ! !------------------------------------------------------------------------------ ! Fortran class type to hold pointer to C++ object type ESMF_IO #ifndef ESMF_NO_SEQUENCE sequence #endif private type(ESMF_Pointer) :: this ESMF_INIT_DECLARE end type !------------------------------------------------------------------------------ ! !PUBLIC TYPES: public ESMF_IO ! public ESMF_IOFileFormat, ESMF_IORWType !------------------------------------------------------------------------------ ! ! !PUBLIC MEMBER FUNCTIONS: public ESMF_IOAddArray !public ESMF_IOClose public ESMF_IOClear public ESMF_IOCreate public ESMF_IODestroy !public ESMF_IOFlush !public ESMF_IOGet !public ESMF_IOOpen !public ESMF_IOPrint public ESMF_IORead !public ESMF_IOReadRestart !public ESMF_IOSet !public ESMF_IOValidate public ESMF_IOWrite !public ESMF_IOWriteRestart !EOPI !------------------------------------------------------------------------------ ! The following line turns the CVS identifier string into a printable variable. character(*), parameter, private :: version = & '$Id$' !============================================================================== ! ! INTERFACE BLOCKS ! !============================================================================== !============================================================================== contains !============================================================================== #undef ESMF_METHOD #define ESMF_METHOD "ESMF_IOCreate()" !BOPI ! !IROUTINE: ESMF_IOCreate - Create a new ESMF I/O object ! ! !INTERFACE: function ESMF_IOCreate(keywordEnforcer, rc) ! ! !RETURN VALUE: type(ESMF_IO) :: ESMF_IOCreate ! !ARGUMENTS: type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below integer, intent(out), optional :: rc ! !DESCRIPTION: ! Creates a new {\tt ESMF\_IO} object. ! ! The arguments are: ! \begin{description} ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. ! \end{description} ! !EOPI ! local return code integer :: localrc ! ! ! Assume failure until success if (present(rc)) rc = ESMF_RC_NOT_IMPL localrc = ESMF_RC_NOT_IMPL ! ! invoke C to C++ entry point to allocate and initialize new io call c_ESMC_IOCreate(ESMF_IOCreate, localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return ! Return success if (present(rc)) rc = ESMF_SUCCESS end function ESMF_IOCreate !------------------------------------------------------------------------------ #undef ESMF_METHOD #define ESMF_METHOD "ESMF_IODestroy()" !BOPI ! !IROUTINE: ESMF_IODestroy - Clean up and delete an ESMF I/O object ! ! !INTERFACE: subroutine ESMF_IODestroy(io, rc) ! ! !ARGUMENTS: type(ESMF_IO) :: io integer, intent(out), optional :: rc ! ! !DESCRIPTION: ! Releases resources associated with this {\tt ESMF\_IO} object. ! This includes deleting the {\tt ESMF\_IO} object itself. ! ! The arguments are: ! \begin{description} ! \item[io] ! Destroy contents of this {\tt ESMF\_IO} object. ! \item[[rc]] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. ! \end{description} ! !EOPI integer :: localrc ! local return code ! Assume failure until success if (present(rc)) rc = ESMF_RC_NOT_IMPL localrc = ESMF_RC_NOT_IMPL ! invoke C to C++ entry point call c_ESMC_IODestroy(io, localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) then write(*,*)" c_ESMC_IODestroy failed" return endif ! Return success if (present(rc)) rc = localrc end subroutine ESMF_IODestroy !------------------------------------------------------------------------------ #undef ESMF_METHOD #define ESMF_METHOD "ESMF_IOClear()" !BOPI ! !IROUTINE: ESMF_IOClear - Clears the I/O queue of an ESMF I/O object ! ! !INTERFACE: subroutine ESMF_IOClear(io) ! ! !ARGUMENTS: type(ESMF_IO) :: io ! ! !DESCRIPTION: ! Clears the I/O queue of this {\tt ESMF\_IO} object. ! ! The arguments are: ! \begin{description} ! \item[io] ! Clear the I/O queue of this {\tt ESMF\_IO} object. ! \end{description} ! !EOPI ! invoke C to C++ entry point call c_ESMC_IOClear(io) end subroutine ESMF_IOClear !------------------------------------------------------------------------------ #undef ESMF_METHOD #define ESMF_METHOD "ESMF_IOAddArray()" !BOPI ! !IROUTINE: ESMF_IOAddArray - Add an array to an I/O object's element list ! !INTERFACE: subroutine ESMF_IOAddArray(io, array, keywordEnforcer, & variableName, convention, purpose, rc) ! !ARGUMENTS: type(ESMF_IO), intent(in) :: io type(ESMF_Array), intent(in) :: array type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below character(*), intent(in), optional :: variableName character(*), intent(in), optional :: convention character(*), intent(in), optional :: purpose integer, intent(out), optional :: rc ! !DESCRIPTION: ! Gets one or more of the properties of an {\tt ESMF\_IO} object. ! ! The arguments are: ! \begin{description} ! \item[io] ! The {\tt ESMF\_IO} object instance to modify ! \item[array] ! The {\tt ESMF\_Array} object to add to io's element list ! \item[{[variableName]}] ! Optional variableName to attach to this array for I/O purposes ! \item[{[convention]}] ! Optional convention - AttPack for attribute and dimension names and values ! \item[{[purpose]}] ! Optional purpose - AttPack for attribute and dimension names and values ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. ! \end{description} ! !EOPI integer :: localrc ! local return code integer :: len_varName ! name length or 0 ! Assume failure until success if (present(rc)) rc = ESMF_RC_NOT_IMPL localrc = ESMF_RC_NOT_IMPL ! invoke C to C++ entry point if (present(variableName)) then len_varName = len_trim(variableName) else len_varName = 0 endif call c_ESMC_IOAddArray(io, array, & variableName, len_varName, & convention, purpose, & localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return ! Return success if (present(rc)) rc = ESMF_SUCCESS end subroutine ESMF_IOAddArray !------------------------------------------------------------------------------ !BOPI ! !IROUTINE: ESMF_IORead - Perform a read on an ESMF I/O object ! ! !INTERFACE: subroutine ESMF_IORead(io, fileName, keywordEnforcer, timeslice, & iofmt, schema, rc) ! ! !ARGUMENTS: type(ESMF_IO), intent(in) :: io character (len=*), intent(in) :: fileName type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below integer, intent(in), optional :: timeslice type(ESMF_IOFmt_Flag), intent(in), optional :: iofmt character (len=*), intent(in), optional :: schema integer, intent(out), optional :: rc ! !DESCRIPTION: ! Perform a read on an {\tt ESMF\_IO} object. Any properties specified ! will override, but not reset, those previously set on the io object. ! ! The arguments are: ! \begin{description} ! \item[io] ! The object instance to read. ! \item[{[fileName]}] ! The file name to be read from. ! \item[{[timeslice]}] ! The time-slice number of the variable read from file. ! \item[{[iofmt]}] ! \begin{sloppypar} ! The I/O format. Please see Section~\ref{opt:iofmtflag} for the list ! of options. If not present, defaults to {\tt ESMF\_IOFMT\_NETCDF}. ! \end{sloppypar} ! \item[{[schema]}] ! Selects, for reading, the Attribute package of the ESMF ! objects included in <io> (e.g., with ESMF_IOAddArray) ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. ! \end{description} !EOPI ! !REQUIREMENTS: integer :: localrc integer :: len_fileName ! filename length or 0 type(ESMF_IOFmt_Flag) :: opt_iofmt ! helper variable integer :: len_schema ! schema string length or 0 ! Assume failure until success if (present(rc)) rc = ESMF_RC_NOT_IMPL localrc = ESMF_RC_NOT_IMPL ! Grab the filename length for the C++ level len_fileName = len_trim(fileName) ! Set default flags opt_iofmt = ESMF_IOFMT_NETCDF; if ( present(iofmt)) opt_iofmt = iofmt ! Grab the schema string length for the C++ level if (present(schema)) then len_schema = len_trim(schema) else len_schema = 0 endif ! invoke C to C++ entry point TODO call c_ESMC_IORead(io, fileName, len_fileName, opt_iofmt, & timeslice, schema, len_schema, localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return ! Return success if (present(rc)) rc = ESMF_SUCCESS end subroutine ESMF_IORead ! !------------------------------------------------------------------------------ !------------------------------------------------------------------------------ !BOPI ! !IROUTINE: ESMF_IOWrite - Perform a write on an ESMF I/O object ! ! !INTERFACE: subroutine ESMF_IOWrite(io, fileName, keywordEnforcer, & overwrite, status, & timeslice, iofmt, schema, rc) ! ! !ARGUMENTS: type(ESMF_IO), intent(in) :: io character (len=*), intent(in) :: fileName type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below logical, intent(in), optional :: overwrite type(ESMF_FileStatus_Flag), intent(in), optional :: status integer, intent(in), optional :: timeslice type(ESMF_IOFmt_Flag), intent(in), optional :: iofmt character (len=*), intent(in), optional :: schema integer, intent(out), optional :: rc ! !DESCRIPTION: ! Perform a write on an {\tt ESMF\_IO} object. Any properties specified ! will override, but not reset, those previously set on the io object. ! ! The arguments are: ! \begin{description} ! \item[io] ! The object instance to write. ! \item[fileName] ! The file name to be writtten to. ! \item[{[overwrite]}] ! \begin{sloppypar} ! A logical flag, the default is .false., i.e., existing field data may ! {\em not} be overwritten. If .true., the overwrite behavior depends ! on the value of {\tt iofmt} as shown below: ! \begin{description} ! \item[{\tt iofmt} = {\tt ESMF\_IOFMT\_BIN}:]\ All data in the file will ! be overwritten with each field's data. ! \item[{\tt iofmt} = {\tt ESMF\_IOFMT\_NETCDF}:]\ Only the ! data corresponding to each field's name will be ! be overwritten. If the {\tt timeslice} option is given, only data for ! the given timeslice may be overwritten. ! Note that it is always an error to attempt to overwrite a NetCDF ! variable with data which has a different shape. ! \end{description} ! \end{sloppypar} ! \item[{[status]}] ! \begin{sloppypar} ! The file status. Please see Section~\ref{const:filestatusflag} for ! the list of options. If not present, defaults to ! {\tt ESMF\_FILESTATUS\_UNKNOWN}. ! \end{sloppypar} ! \item[{[timeslice]}] ! \begin{sloppypar} ! Some I/O formats (e.g. NetCDF) support the output of data in form of ! time slices. The {\tt timeslice} argument provides access to this ! capability. {\tt timeslice} must be positive. The behavior of this ! option may depend on the setting of the {\tt overwrite} flag: ! \begin{description} ! \item[{\tt overwrite = .false.}:]\ If the timeslice value is ! less than the maximum time already in the file, the write will fail. ! \item[{\tt overwrite = .true.}:]\ Any positive timeslice value is valid. ! \end{description} ! By default, i.e. by omitting the {\tt timeslice} argument, no ! provisions for time slicing are made in the output file, ! however, if the file already contains a time axis for the variable, ! a timeslice one greater than the maximum will be written. ! \end{sloppypar} ! \item[{[iofmt]}] ! The file format to be used during the read. Default is ! ESMF_IOFMT_NETCDF ! \item[{[schema]}] ! Selects, for reading, the Attribute package of the ESMF ! objects included in <io> (e.g., with ESMF_IOAddArray) ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. ! \end{description} !EOPI ! !REQUIREMENTS: ! integer :: localrc integer :: len_fileName ! filename length or 0 type(ESMF_Logical) :: opt_overwriteflag ! helper variable type(ESMF_FileStatus_Flag) :: opt_status ! helper variable type(ESMF_IOFmt_Flag) :: opt_iofmt ! helper variable integer :: len_schema ! schema string len or 0 ! Assume failure until success if (present(rc)) rc = ESMF_RC_NOT_IMPL localrc = ESMF_RC_NOT_IMPL ! Set default flags opt_overwriteflag = ESMF_FALSE if (present(overwrite)) then if (overwrite) opt_overwriteflag = ESMF_TRUE end if opt_status = ESMF_FILESTATUS_UNKNOWN if (present(status)) opt_status = status opt_iofmt = ESMF_IOFMT_NETCDF; if ( present(iofmt)) opt_iofmt = iofmt ! Grab the filename length for the C++ level len_fileName = len_trim(fileName) ! Grab the schema string length for the C++ level if (present(schema)) then len_schema = len_trim(schema) else len_schema = 0 endif ! invoke C to C++ entry point TODO call c_ESMC_IOWrite(io, fileName, len_fileName, opt_iofmt, & opt_overwriteflag, opt_status, timeslice, & schema, len_schema, localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return ! Return success if (present(rc)) rc = ESMF_SUCCESS end subroutine ESMF_IOWrite end module ESMF_IOMod