Skip to content
Snippets Groups Projects
iom.F90 143 KiB
Newer Older
Guillaume Samson's avatar
Guillaume Samson committed
      INTEGER                                         ::   idvar     ! variable id
      INTEGER                                         ::   idmspc    ! number of spatial dimensions
      INTEGER         , DIMENSION(1)                  ::   itime     ! record number
      CHARACTER(LEN=100)                              ::   clinfo    ! info character
      CHARACTER(LEN=100)                              ::   clname    ! file name
      CHARACTER(LEN=1)                                ::   cldmspc   !
      CHARACTER(LEN=lc)                               ::   context
      !
      CALL set_xios_context(kiomid, context)

      IF(context == "NONE") THEN  ! read data using default library
         itime = 1
         IF( PRESENT(ktime) ) itime = ktime
         !
         clname = iom_file(kiomid)%name
         clinfo = '          iom_g0d, file: '//TRIM(clname)//', var: '//TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
         !
         IF( kiomid > 0 ) THEN
            idvar = iom_varid( kiomid, cdvar )
            IF( iom_file(kiomid)%nfid > 0 .AND. idvar > 0 ) THEN
               idmspc = iom_file ( kiomid )%ndims( idvar )
               IF( iom_file(kiomid)%luld(idvar) )  idmspc = idmspc - 1
               WRITE(cldmspc , fmt='(i1)') idmspc
               IF( idmspc > 0 )  CALL ctl_stop( TRIM(clinfo), 'When reading to a 0D array, we do not accept data', &
                                    &                         'with 1 or more spatial dimensions: '//cldmspc//' were found.' , &
                                    &                         'Use ncwa -a to suppress the unnecessary dimensions' )
               CALL iom_nf90_get( kiomid, idvar, pvar, itime )
            ENDIF
         ENDIF
      ELSE
#if defined key_xios
         IF(lwp) WRITE(numout,*) 'XIOS RST READ (0D): ', TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
         CALL iom_swap(context)
         CALL xios_recv_field( TRIM(cdvar), pvar)
Guillaume Samson's avatar
Guillaume Samson committed
         CALL iom_swap(cxios_context)
#else
         WRITE(ctmp1,*) 'Can not use XIOS in iom_g0d, file: '//TRIM(clname)//', var:'//TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
         CALL ctl_stop( 'iom_g0d', ctmp1 )
#endif
      ENDIF
   END SUBROUTINE iom_g0d_dp

   SUBROUTINE iom_g1d_sp( kiomid, kdom, cdvar, pvar, ktime, kstart, kcount )
      INTEGER         , INTENT(in   )                         ::   kiomid    ! Identifier of the file
      INTEGER         , INTENT(in   )                         ::   kdom      ! Type of domain to be read
      CHARACTER(len=*), INTENT(in   )                         ::   cdvar     ! Name of the variable
      REAL(sp)        , INTENT(  out), DIMENSION(:)           ::   pvar      ! read field
      REAL(dp)        , ALLOCATABLE  , DIMENSION(:)           ::   ztmp_pvar ! tmp var to read field
      INTEGER         , INTENT(in   )              , OPTIONAL ::   ktime     ! record number
      INTEGER         , INTENT(in   ), DIMENSION(1), OPTIONAL ::   kstart    ! start axis position of the reading
      INTEGER         , INTENT(in   ), DIMENSION(1), OPTIONAL ::   kcount    ! number of points in each axis
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 ) THEN
            ALLOCATE(ztmp_pvar(size(pvar,1)))
            CALL iom_get_123d( kiomid, kdom       , cdvar        , pv_r1d=ztmp_pvar,   &
              &                                                     ktime=ktime, kstart=kstart, kcount=kcount )
            pvar = ztmp_pvar
            DEALLOCATE(ztmp_pvar)
         END IF
      ENDIF
   END SUBROUTINE iom_g1d_sp


   SUBROUTINE iom_g1d_dp( kiomid, kdom, cdvar, pvar, ktime, kstart, kcount )
      INTEGER         , INTENT(in   )                         ::   kiomid    ! Identifier of the file
      INTEGER         , INTENT(in   )                         ::   kdom      ! Type of domain to be read
      CHARACTER(len=*), INTENT(in   )                         ::   cdvar     ! Name of the variable
      REAL(dp)        , INTENT(  out), DIMENSION(:)           ::   pvar      ! read field
      INTEGER         , INTENT(in   )              , OPTIONAL ::   ktime     ! record number
      INTEGER         , INTENT(in   ), DIMENSION(1), OPTIONAL ::   kstart    ! start axis position of the reading
      INTEGER         , INTENT(in   ), DIMENSION(1), OPTIONAL ::   kcount    ! number of points in each axis
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 ) CALL iom_get_123d( kiomid, kdom       , cdvar        , pv_r1d=pvar,   &
              &                                                     ktime=ktime, kstart=kstart, kcount=kcount)
      ENDIF
   END SUBROUTINE iom_g1d_dp

   SUBROUTINE iom_g2d_sp( kiomid, kdom, cdvar, pvar, ktime, cd_type, psgn, kfill, kstart, kcount)
      INTEGER         , INTENT(in   )                         ::   kiomid    ! Identifier of the file
      INTEGER         , INTENT(in   )                         ::   kdom      ! Type of domain to be read
      CHARACTER(len=*), INTENT(in   )                         ::   cdvar     ! Name of the variable
      REAL(sp)        , INTENT(  out), DIMENSION(:,:)         ::   pvar      ! read field
      REAL(dp)        , ALLOCATABLE  , DIMENSION(:,:)         ::   ztmp_pvar ! tmp var to read field
      INTEGER         , INTENT(in   )              , OPTIONAL ::   ktime     ! record number
      CHARACTER(len=1), INTENT(in   )              , OPTIONAL ::   cd_type   ! nature of grid-points (T, U, V, F, W)
      REAL(dp)        , INTENT(in   )              , OPTIONAL ::   psgn      ! -1.(1.): (not) change sign across the north fold
      INTEGER         , INTENT(in   )              , OPTIONAL ::   kfill     ! value of kfillmode in lbc_lbk
      INTEGER         , INTENT(in   ), DIMENSION(2), OPTIONAL ::   kstart    ! start axis position of the reading
      INTEGER         , INTENT(in   ), DIMENSION(2), OPTIONAL ::   kcount    ! number of points in each axis
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 ) THEN
            ALLOCATE(ztmp_pvar(size(pvar,1), size(pvar,2)))
            CALL iom_get_123d( kiomid, kdom, cdvar      , pv_r2d = ztmp_pvar  , ktime = ktime,   &
             &                                                      cd_type = cd_type, psgn   = psgn  , kfill = kfill,   &
             &                                                      kstart  = kstart , kcount = kcount  )
            pvar = ztmp_pvar
            DEALLOCATE(ztmp_pvar)
         ENDIF
      ENDIF
   END SUBROUTINE iom_g2d_sp

   SUBROUTINE iom_g2d_dp( kiomid, kdom, cdvar, pvar, ktime, cd_type, psgn, kfill, kstart, kcount)
      INTEGER         , INTENT(in   )                         ::   kiomid    ! Identifier of the file
      INTEGER         , INTENT(in   )                         ::   kdom      ! Type of domain to be read
      CHARACTER(len=*), INTENT(in   )                         ::   cdvar     ! Name of the variable
      REAL(dp)        , INTENT(  out), DIMENSION(:,:)         ::   pvar      ! read field
      INTEGER         , INTENT(in   )              , OPTIONAL ::   ktime     ! record number
      CHARACTER(len=1), INTENT(in   )              , OPTIONAL ::   cd_type   ! nature of grid-points (T, U, V, F, W)
      REAL(dp)        , INTENT(in   )              , OPTIONAL ::   psgn      ! -1.(1.): (not) change sign across the north fold
      INTEGER         , INTENT(in   )              , OPTIONAL ::   kfill     ! value of kfillmode in lbc_lbk
      INTEGER         , INTENT(in   ), DIMENSION(2), OPTIONAL ::   kstart    ! start axis position of the reading
      INTEGER         , INTENT(in   ), DIMENSION(2), OPTIONAL ::   kcount    ! number of points in each axis
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 ) CALL iom_get_123d( kiomid, kdom, cdvar      , pv_r2d = pvar  , ktime = ktime,   &
            &                                                       cd_type = cd_type, psgn   = psgn  , kfill = kfill,   &
            &                                                       kstart  = kstart , kcount = kcount                )
      ENDIF
   END SUBROUTINE iom_g2d_dp

   SUBROUTINE iom_g3d_sp( kiomid, kdom, cdvar, pvar, ktime, cd_type, psgn, kfill, kstart, kcount )
      INTEGER         , INTENT(in   )                         ::   kiomid    ! Identifier of the file
      INTEGER         , INTENT(in   )                         ::   kdom      ! Type of domain to be read
      CHARACTER(len=*), INTENT(in   )                         ::   cdvar     ! Name of the variable
      REAL(sp)        , INTENT(  out), DIMENSION(:,:,:)       ::   pvar      ! read field
      REAL(dp)        , ALLOCATABLE  , DIMENSION(:,:,:)       ::   ztmp_pvar ! tmp var to read field
      INTEGER         , INTENT(in   )              , OPTIONAL ::   ktime     ! record number
      CHARACTER(len=1), INTENT(in   )              , OPTIONAL ::   cd_type   ! nature of grid-points (T, U, V, F, W)
      REAL(dp)        , INTENT(in   )              , OPTIONAL ::   psgn      ! -1.(1.) : (not) change sign across the north fold
      INTEGER         , INTENT(in   )              , OPTIONAL ::   kfill     ! value of kfillmode in lbc_lbk
      INTEGER         , INTENT(in   ), DIMENSION(3), OPTIONAL ::   kstart    ! start axis position of the reading
      INTEGER         , INTENT(in   ), DIMENSION(3), OPTIONAL ::   kcount    ! number of points in each axis
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 ) THEN
            ALLOCATE(ztmp_pvar(size(pvar,1), size(pvar,2), size(pvar,3)))
            CALL iom_get_123d( kiomid, kdom, cdvar      , pv_r3d = ztmp_pvar  , ktime = ktime,   &
            &                                                       cd_type = cd_type, psgn   = psgn  , kfill = kfill,   &
            &                                                       kstart  = kstart , kcount = kcount                )
            pvar = ztmp_pvar
            DEALLOCATE(ztmp_pvar)
         END IF
      ENDIF
   END SUBROUTINE iom_g3d_sp

   SUBROUTINE iom_g3d_dp( kiomid, kdom, cdvar, pvar, ktime, cd_type, psgn, kfill, kstart, kcount )
      INTEGER         , INTENT(in   )                         ::   kiomid    ! Identifier of the file
      INTEGER         , INTENT(in   )                         ::   kdom      ! Type of domain to be read
      CHARACTER(len=*), INTENT(in   )                         ::   cdvar     ! Name of the variable
      REAL(dp)        , INTENT(  out), DIMENSION(:,:,:)       ::   pvar      ! read field
      INTEGER         , INTENT(in   )              , OPTIONAL ::   ktime     ! record number
      CHARACTER(len=1), INTENT(in   )              , OPTIONAL ::   cd_type   ! nature of grid-points (T, U, V, F, W)
      REAL(dp)        , INTENT(in   )              , OPTIONAL ::   psgn      ! -1.(1.) : (not) change sign across the north fold
      INTEGER         , INTENT(in   )              , OPTIONAL ::   kfill     ! value of kfillmode in lbc_lbk
      INTEGER         , INTENT(in   ), DIMENSION(3), OPTIONAL ::   kstart    ! start axis position of the reading
      INTEGER         , INTENT(in   ), DIMENSION(3), OPTIONAL ::   kcount    ! number of points in each axis
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 ) THEN
            CALL iom_get_123d( kiomid, kdom, cdvar      , pv_r3d = pvar  , ktime = ktime,   &
            &                                                       cd_type = cd_type, psgn   = psgn  , kfill = kfill,   &
            &                                                       kstart  = kstart , kcount = kcount                )
         END IF
      ENDIF
   END SUBROUTINE iom_g3d_dp

   !!----------------------------------------------------------------------

   SUBROUTINE iom_get_123d( kiomid , kdom, cdvar, pv_r1d, pv_r2d, pv_r3d, ktime ,   &
         &                  cd_type, psgn, kfill, kstart, kcount )
      !!-----------------------------------------------------------------------
      !!                  ***  ROUTINE  iom_get_123d  ***
      !!
      !! ** Purpose : read a 1D/2D/3D variable
      !!
      !! ** Method : read ONE record at each CALL
      !!-----------------------------------------------------------------------
      INTEGER                    , INTENT(in   )           ::   kiomid    ! Identifier of the file
      INTEGER                    , INTENT(in   )           ::   kdom      ! Type of domain to be read
      CHARACTER(len=*)           , INTENT(in   )           ::   cdvar     ! Name of the variable
      REAL(dp), DIMENSION(:)     , INTENT(  out), OPTIONAL ::   pv_r1d    ! read field (1D case)
      REAL(dp), DIMENSION(:,:)   , INTENT(  out), OPTIONAL ::   pv_r2d    ! read field (2D case)
      REAL(dp), DIMENSION(:,:,:) , INTENT(  out), OPTIONAL ::   pv_r3d    ! read field (3D case)
      INTEGER                    , INTENT(in   ), OPTIONAL ::   ktime     ! record number
      CHARACTER(len=1)           , INTENT(in   ), OPTIONAL ::   cd_type   ! nature of grid-points (T, U, V, F, W)
      REAL(dp)                   , INTENT(in   ), OPTIONAL ::   psgn      ! -1.(1.) : (not) change sign across the north fold
      INTEGER                    , INTENT(in   ), OPTIONAL ::   kfill     ! value of kfillmode in lbc_lbk
      INTEGER , DIMENSION(:)     , INTENT(in   ), OPTIONAL ::   kstart    ! start position of the reading in each axis
      INTEGER , DIMENSION(:)     , INTENT(in   ), OPTIONAL ::   kcount    ! number of points to be read in each axis
      !
      LOGICAL                        ::   llok        ! true if ok!
      INTEGER                        ::   jl          ! loop on number of dimension
      INTEGER                        ::   idom        ! type of domain
      INTEGER                        ::   idvar       ! id of the variable
      INTEGER                        ::   inbdim      ! number of dimensions of the variable
      INTEGER                        ::   idmspc      ! number of spatial dimensions
      INTEGER                        ::   itime       ! record number
      INTEGER                        ::   istop       ! temporary value of nstop
      INTEGER                        ::   ix1, ix2, iy1, iy2   ! subdomain indexes
      INTEGER                        ::   ji, jj      ! loop counters
      INTEGER                        ::   irankpv     !
      INTEGER                        ::   ind1, ind2  ! substring index
      INTEGER, DIMENSION(jpmax_dims) ::   istart      ! starting point to read for each axis
      INTEGER, DIMENSION(jpmax_dims) ::   icnt        ! number of value to read along each axis
      INTEGER, DIMENSION(jpmax_dims) ::   idimsz      ! size of the dimensions of the variable
      INTEGER, DIMENSION(jpmax_dims) ::   ishape      ! size of the dimensions of the variable
      REAL(dp)                       ::   zscf, zofs  ! sacle_factor and add_offset
      REAL(wp)                       ::   zsgn        ! local value of psgn
      INTEGER                        ::   itmp        ! temporary integer
      CHARACTER(LEN=256)             ::   clinfo      ! info character
      CHARACTER(LEN=256)             ::   clname      ! file name
      CHARACTER(LEN=1)               ::   clrankpv, cldmspc      !
      CHARACTER(LEN=1)               ::   cl_type     ! local value of cd_type
      LOGICAL                        ::   ll_only3rd  ! T => if kstart, kcount present then *only* use values for 3rd spatial dimension.
      INTEGER                        ::   inlev       ! number of levels for 3D data
      REAL(dp)                       ::   gma, gmi
      !---------------------------------------------------------------------
      CHARACTER(LEN=lc)                               ::   context
      !
      CALL set_xios_context(kiomid, context)
      inlev = -1
      IF( PRESENT(pv_r3d) )   inlev = SIZE(pv_r3d, 3)
      !
      idom = kdom
      istop = nstop
      !
      IF(context == "NONE") THEN
         clname = iom_file(kiomid)%name   !   esier to read
         clinfo = '          iom_get_123d, file: '//TRIM(clname)//', var: '//TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
         ! check kcount and kstart optionals parameters...
         IF( PRESENT(kcount) .AND. .NOT. PRESENT(kstart) ) CALL ctl_stop(TRIM(clinfo), 'kcount present needs kstart present')
         IF( PRESENT(kstart) .AND. .NOT. PRESENT(kcount) ) CALL ctl_stop(TRIM(clinfo), 'kstart present needs kcount present')
Guillaume Samson's avatar
Guillaume Samson committed
         IF( PRESENT(kstart) .AND. idom /= jpdom_unknown .AND. idom /= jpdom_auto_xy ) &
            &          CALL ctl_stop(TRIM(clinfo), 'kstart present needs idom = jpdom_unknown or idom = jpdom_auto_xy')
         IF( idom == jpdom_auto_xy .AND. .NOT. PRESENT(kstart) ) &
            &          CALL ctl_stop(TRIM(clinfo), 'idom = jpdom_auto_xy requires kstart to be present')
         !
         ! Search for the variable in the data base (eventually actualize data)
         !
         idvar = iom_varid( kiomid, cdvar )
         IF( idvar > 0 ) THEN
            !
            idimsz(:) = iom_file(kiomid)%dimsz(:, idvar)      ! to write iom_file(kiomid)%dimsz in a shorter way
            inbdim = iom_file(kiomid)%ndims(idvar)            ! number of dimensions in the file
            idmspc = inbdim                                   ! number of spatial dimensions in the file
            IF( iom_file(kiomid)%luld(idvar) )   idmspc = inbdim - 1
            IF( idmspc > 3 )   CALL ctl_stop(TRIM(clinfo), 'the file has more than 3 spatial dimensions this case is not coded...')
Guillaume Samson's avatar
Guillaume Samson committed
            !
            ! Identify the domain in case of jpdom_auto definition
            IF( idom == jpdom_auto .OR. idom == jpdom_auto_xy ) THEN
               idom = jpdom_global   ! default
               ! else: if the file name finishes with _xxxx.nc with xxxx any number
               ind1 = INDEX( clname, '_', back = .TRUE. ) + 1
               ind2 = INDEX( clname, '.', back = .TRUE. ) - 1
               IF( ind2 > ind1 ) THEN   ;   IF( VERIFY( clname(ind1:ind2), '0123456789' ) == 0 )   idom = jpdom_local   ;   ENDIF
            ENDIF
            !
            ! check the consistency between input array and data rank in the file
            !
            ! initializations
            itime = 1
            IF( PRESENT(ktime) ) itime = ktime
            !
            irankpv = 1 * COUNT( (/PRESENT(pv_r1d)/) ) + 2 * COUNT( (/PRESENT(pv_r2d)/) ) + 3 * COUNT( (/PRESENT(pv_r3d)/) )
            WRITE(clrankpv, fmt='(i1)') irankpv
            WRITE(cldmspc , fmt='(i1)') idmspc
            !
            IF(     idmspc <  irankpv ) THEN                     ! it seems we want to read more than we can...
               IF(     irankpv == 3 .AND. idmspc == 2 ) THEN     !   3D input array from 2D spatial data in the file:
                  llok = inlev == 1                              !     -> 3rd dimension must be equal to 1
               ELSEIF( irankpv == 3 .AND. idmspc == 1 ) THEN     !   3D input array from 1D spatial data in the file:
                  llok = inlev == 1 .AND. SIZE(pv_r3d, 2) == 1   !     -> 2nd and 3rd dimensions must be equal to 1
               ELSEIF( irankpv == 2 .AND. idmspc == 2 ) THEN     !   2D input array from 1D spatial data in the file:
                  llok = SIZE(pv_r2d, 2) == 1                    !     -> 2nd dimension must be equal to 1
               ELSE
                  llok = .FALSE.
               ENDIF
               IF( .NOT. llok )   CALL ctl_stop( TRIM(clinfo), 'The file has only '//cldmspc//' spatial dimension',   &
                  &                                            '=> cannot read a true '//clrankpv//'D array from this file...' )
            ELSEIF( idmspc == irankpv ) THEN
               IF( PRESENT(pv_r1d) .AND. idom /= jpdom_unknown )   &
                  &   CALL ctl_stop( TRIM(clinfo), 'case not coded...You must use jpdom_unknown' )
            ELSEIF( idmspc >  irankpv ) THEN                     ! it seems we want to read less than we should...
                  IF( PRESENT(pv_r2d) .AND. itime == 1 .AND. idimsz(3) == 1 .AND. idmspc == 3 ) THEN
                     CALL ctl_warn( TRIM(clinfo), '2D array input but 3 spatial dimensions in the file...'              ,   &
Guillaume Samson's avatar
Guillaume Samson committed
                           &         'As the size of the z dimension is 1 and as we try to read the first record, ',   &
                           &         'we accept this case, even if there is a possible mix-up between z and time dimension' )
                     idmspc = idmspc - 1
                  !!GS: possibility to read 3D ABL atmopsheric forcing and use 1st level to force BULK simulation
                  !ELSE
                  !   CALL ctl_stop( TRIM(clinfo), 'To keep iom lisibility, when reading a '//clrankpv//'D array,',   &
                  !      &                         'we do not accept data with '//cldmspc//' spatial dimensions'  ,   &
                  !      &                         'Use ncwa -a to suppress the unnecessary dimensions' )
                  ENDIF
            ENDIF
            !
            ! definition of istart and icnt
            !
            icnt  (:) = 1              ! default definition (simple way to deal with special cases listed above)
            istart(:) = 1              ! default definition (simple way to deal with special cases listed above)
            istart(idmspc+1) = itime   ! temporal dimenstion
            !
            IF( idom == jpdom_unknown ) THEN
               IF( PRESENT(kstart) .AND. idom /= jpdom_auto_xy ) THEN
                  istart(1:idmspc) = kstart(1:idmspc)
                  icnt  (1:idmspc) = kcount(1:idmspc)
               ELSE
                  icnt  (1:idmspc) = idimsz(1:idmspc)
               ENDIF
            ELSE   !   not a 1D array as pv_r1d requires jpdom_unknown
               ! we do not read the overlap and the extra-halos -> from Nis0 to Nie0 and from Njs0 to Nje0
               IF( idom == jpdom_global )   istart(1:2) = (/ mig0(Nis0), mjg0(Njs0) /)
               icnt(1:2) = (/ Ni_0, Nj_0 /)
               IF( PRESENT(pv_r3d) ) THEN
                  IF( idom == jpdom_auto_xy ) THEN
                     istart(3) = kstart(3)
                     icnt  (3) = kcount(3)
                  ELSE
                     icnt  (3) = inlev
                  ENDIF
               ENDIF
            ENDIF
            !
            ! check that istart and icnt can be used with this file
            !-
            DO jl = 1, jpmax_dims
               itmp = istart(jl)+icnt(jl)-1
               IF( itmp > idimsz(jl) .AND. idimsz(jl) /= 0 ) THEN
                  WRITE( ctmp1, FMT="('(istart(', i1, ') + icnt(', i1, ') - 1) = ', i5)" ) jl, jl, itmp
                  WRITE( ctmp2, FMT="(' is larger than idimsz(', i1,') = ', i5)"         ) jl, idimsz(jl)
                  CALL ctl_stop( TRIM(clinfo), 'start and count too big regarding to the size of the data, ', ctmp1, ctmp2 )
Guillaume Samson's avatar
Guillaume Samson committed
               ENDIF
            END DO
            !
            ! check that icnt matches the input array
            !-
            IF( idom == jpdom_unknown ) THEN
               IF( irankpv == 1 )        ishape(1:1) = SHAPE(pv_r1d)
               IF( irankpv == 2 )        ishape(1:2) = SHAPE(pv_r2d)
               IF( irankpv == 3 )        ishape(1:3) = SHAPE(pv_r3d)
               ctmp1 = 'd'
            ELSE
               IF( irankpv == 2 ) THEN
                  ishape(1:2) = SHAPE(pv_r2d(Nis0:Nie0,Njs0:Nje0  ))   ;   ctmp1 = 'd(Nis0:Nie0,Njs0:Nje0)'
               ENDIF
               IF( irankpv == 3 ) THEN
                  ishape(1:3) = SHAPE(pv_r3d(Nis0:Nie0,Njs0:Nje0,:))   ;   ctmp1 = 'd(Nis0:Nie0,Njs0:Nje0,:)'
               ENDIF
            ENDIF
            DO jl = 1, irankpv
               WRITE( ctmp2, FMT="(', ', i1,'): ', i5,' /= icnt(', i1,'):', i5)" ) jl, ishape(jl), jl, icnt(jl)
               IF( ishape(jl) /= icnt(jl) )   CALL ctl_stop( TRIM(clinfo), 'size(pv_r'//clrankpv//TRIM(ctmp1)//TRIM(ctmp2) )
            END DO

         ENDIF

         ! read the data
         !-
         IF( idvar > 0 .AND. istop == nstop ) THEN   ! no additional errors until this point...
            !
            ! find the right index of the array to be read
            IF( idom /= jpdom_unknown ) THEN   ;   ix1 = Nis0   ;   ix2 = Nie0      ;   iy1 = Njs0   ;   iy2 = Nje0
            ELSE                               ;   ix1 = 1      ;   ix2 = icnt(1)   ;   iy1 = 1      ;   iy2 = icnt(2)
            ENDIF

            CALL iom_nf90_get( kiomid, idvar, inbdim, istart, icnt, ix1, ix2, iy1, iy2, pv_r1d, pv_r2d, pv_r3d )

            IF( istop == nstop ) THEN   ! no additional errors until this point...
               IF(lwp) WRITE(numout,"(10x,' read ',a,' (rec: ',i6,') in ',a,' ok')") TRIM(cdvar), itime, TRIM(iom_file(kiomid)%name)

               cl_type = 'T'
               IF( PRESENT(cd_type) )   cl_type = cd_type
               zsgn = 1._wp
               IF( PRESENT(psgn   ) )   zsgn    = psgn
               !--- overlap areas and extra hallows (mpp)
               IF(     PRESENT(pv_r2d) .AND. idom /= jpdom_unknown .AND. cl_type /= 'Z' ) THEN
                  CALL lbc_lnk( 'iom', pv_r2d, cl_type, zsgn, kfillmode = kfill )
               ELSEIF( PRESENT(pv_r3d) .AND. idom /= jpdom_unknown .AND. cl_type /= 'Z' ) THEN
                  CALL lbc_lnk( 'iom', pv_r3d, cl_type, zsgn, kfillmode = kfill )
               ENDIF
               !
            ELSE
               ! return if istop == nstop is false
               RETURN
            ENDIF
         ELSE
            ! return if statment idvar > 0 .AND. istop == nstop is false
            RETURN
         ENDIF
         !
Tomas Lovato's avatar
Tomas Lovato committed
      ELSE        ! read using XIOS. Only if key_xios is defined
Guillaume Samson's avatar
Guillaume Samson committed
#if defined key_xios
!would be good to be able to check which context is active and swap only if current is not restart
         idvar = iom_varid( kiomid, cdvar )
         CALL iom_swap(context)
         zsgn = 1._wp
         IF( PRESENT(psgn   ) )   zsgn    = psgn
         cl_type = 'T'
         IF( PRESENT(cd_type) )   cl_type = cd_type

         IF( PRESENT(pv_r3d) ) THEN
            IF(lwp) WRITE(numout,*) 'XIOS RST READ (3D): ',TRIM(cdvar)
            CALL xios_recv_field( TRIM(cdvar), pv_r3d(:, :, :))
Guillaume Samson's avatar
Guillaume Samson committed
            IF(idom /= jpdom_unknown .AND. cl_type /= 'Z' ) THEN
               CALL lbc_lnk( 'iom', pv_r3d, cl_type, zsgn, kfillmode = kfill)
            ENDIF
         ELSEIF( PRESENT(pv_r2d) ) THEN
            IF(lwp) WRITE(numout,*) 'XIOS RST READ (2D): ', TRIM(cdvar)
            CALL xios_recv_field( TRIM(cdvar), pv_r2d(:, :))
Guillaume Samson's avatar
Guillaume Samson committed
            IF(idom /= jpdom_unknown .AND. cl_type /= 'Z' ) THEN
               CALL lbc_lnk('iom', pv_r2d, cl_type, zsgn, kfillmode = kfill)
            ENDIF
         ELSEIF( PRESENT(pv_r1d) ) THEN
            IF(lwp) WRITE(numout,*) 'XIOS RST READ (1D): ', TRIM(cdvar)
            CALL xios_recv_field( TRIM(cdvar), pv_r1d)
Guillaume Samson's avatar
Guillaume Samson committed
         ENDIF
         CALL iom_swap(cxios_context)
#else
         istop = istop + 1
         clinfo = 'Can not use XIOS in iom_get_123d, file: '//TRIM(clname)//', var:'//TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
#endif
      ENDIF

      !--- Apply scale_factor and offset
      zscf = iom_file(kiomid)%scf(idvar)      ! scale factor
      zofs = iom_file(kiomid)%ofs(idvar)      ! offset
      IF(     PRESENT(pv_r1d) ) THEN
         IF( zscf /= 1._wp )   pv_r1d(:) = pv_r1d(:) * zscf
         IF( zofs /= 0._wp )   pv_r1d(:) = pv_r1d(:) + zofs
      ELSEIF( PRESENT(pv_r2d) ) THEN
         IF( zscf /= 1._wp)   pv_r2d(:,:) = pv_r2d(:,:) * zscf
         IF( zofs /= 0._wp)   pv_r2d(:,:) = pv_r2d(:,:) + zofs
      ELSEIF( PRESENT(pv_r3d) ) THEN
         IF( zscf /= 1._wp)   pv_r3d(:,:,:) = pv_r3d(:,:,:) * zscf
         IF( zofs /= 0._wp)   pv_r3d(:,:,:) = pv_r3d(:,:,:) + zofs
      ENDIF
      !
   END SUBROUTINE iom_get_123d

   SUBROUTINE iom_get_var( cdname, z2d)
      CHARACTER(LEN=*), INTENT(in ) ::   cdname
      REAL(wp), DIMENSION(jpi,jpj) ::   z2d
#if defined key_xios
      IF( xios_field_is_active( cdname, at_current_timestep_arg = .TRUE. ) ) THEN
         z2d(:,:) = 0._wp
         CALL xios_recv_field( cdname, z2d)
      ENDIF
#else
      IF( .FALSE. )   WRITE(numout,*) cdname, z2d ! useless test to avoid compilation warnings
#endif
   END SUBROUTINE iom_get_var


   FUNCTION iom_getszuld ( kiomid )
      !!-----------------------------------------------------------------------
      !!                  ***  FUNCTION  iom_getszuld  ***
      !!
      !! ** Purpose : get the size of the unlimited dimension in a file
      !!              (return -1 if not found)
      !!-----------------------------------------------------------------------
      INTEGER, INTENT(in   ) ::   kiomid   ! file Identifier
      !
      INTEGER                ::   iom_getszuld
      !!-----------------------------------------------------------------------
      iom_getszuld = -1
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%iduld > 0 )   iom_getszuld = iom_file(kiomid)%lenuld
      ENDIF
   END FUNCTION iom_getszuld


   !!----------------------------------------------------------------------
   !!                   INTERFACE iom_chkatt
   !!----------------------------------------------------------------------
   SUBROUTINE iom_chkatt( kiomid, cdatt, llok, ksize, cdvar )
      INTEGER         , INTENT(in   )                 ::   kiomid    ! Identifier of the file
      CHARACTER(len=*), INTENT(in   )                 ::   cdatt     ! Name of the attribute
      LOGICAL         , INTENT(  out)                 ::   llok      ! Error code
      INTEGER         , INTENT(  out), OPTIONAL       ::   ksize     ! Size of the attribute array
      CHARACTER(len=*), INTENT(in   ), OPTIONAL       ::   cdvar     ! Name of the variable
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 )   CALL iom_nf90_chkatt( kiomid, cdatt, llok, ksize=ksize, cdvar=cdvar )
      ENDIF
      !
   END SUBROUTINE iom_chkatt

   !!----------------------------------------------------------------------
   !!                   INTERFACE iom_getatt
   !!----------------------------------------------------------------------
   SUBROUTINE iom_g0d_iatt( kiomid, cdatt, katt0d, cdvar )
      INTEGER               , INTENT(in   )           ::   kiomid    ! Identifier of the file
      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt     ! Name of the attribute
      INTEGER               , INTENT(  out)           ::   katt0d    ! read field
      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar     ! Name of the variable
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 )   CALL iom_nf90_getatt( kiomid, cdatt,  katt0d =  katt0d, cdvar=cdvar )
      ENDIF
   END SUBROUTINE iom_g0d_iatt

   SUBROUTINE iom_g1d_iatt( kiomid, cdatt, katt1d, cdvar )
      INTEGER               , INTENT(in   )           ::   kiomid    ! Identifier of the file
      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt     ! Name of the attribute
      INTEGER, DIMENSION(:) , INTENT(  out)           ::   katt1d    ! read field
      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar     ! Name of the variable
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 )   CALL iom_nf90_getatt( kiomid, cdatt,  katt1d =  katt1d, cdvar=cdvar )
      ENDIF
   END SUBROUTINE iom_g1d_iatt

   SUBROUTINE iom_g0d_ratt( kiomid, cdatt, patt0d, cdvar )
      INTEGER               , INTENT(in   )           ::   kiomid    ! Identifier of the file
      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt     ! Name of the attribute
      REAL(wp)              , INTENT(  out)           ::   patt0d    ! read field
      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar     ! Name of the variable
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 )   CALL iom_nf90_getatt( kiomid, cdatt,  patt0d =  patt0d, cdvar=cdvar )
      ENDIF
   END SUBROUTINE iom_g0d_ratt

   SUBROUTINE iom_g1d_ratt( kiomid, cdatt, patt1d, cdvar )
      INTEGER               , INTENT(in   )           ::   kiomid    ! Identifier of the file
      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt     ! Name of the attribute
      REAL(wp), DIMENSION(:), INTENT(  out)           ::   patt1d    ! read field
      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar     ! Name of the variable
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 )   CALL iom_nf90_getatt( kiomid, cdatt,  patt1d =  patt1d, cdvar=cdvar )
      ENDIF
   END SUBROUTINE iom_g1d_ratt

   SUBROUTINE iom_g0d_catt( kiomid, cdatt, cdatt0d, cdvar )
      INTEGER               , INTENT(in   )           ::   kiomid    ! Identifier of the file
      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt     ! Name of the attribute
      CHARACTER(len=*)      , INTENT(  out)           ::   cdatt0d   ! read field
      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar     ! Name of the variable
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 )   CALL iom_nf90_getatt( kiomid, cdatt, cdatt0d = cdatt0d, cdvar=cdvar )
      ENDIF
   END SUBROUTINE iom_g0d_catt


   !!----------------------------------------------------------------------
   !!                   INTERFACE iom_putatt
   !!----------------------------------------------------------------------
   SUBROUTINE iom_p0d_iatt( kiomid, cdatt, katt0d, cdvar )
      INTEGER               , INTENT(in   )           ::   kiomid    ! Identifier of the file
      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt     ! Name of the attribute
      INTEGER               , INTENT(in   )           ::   katt0d    ! written field
      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar     ! Name of the variable
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 )   CALL iom_nf90_putatt( kiomid, cdatt,  katt0d =  katt0d, cdvar=cdvar )
      ENDIF
   END SUBROUTINE iom_p0d_iatt

   SUBROUTINE iom_p1d_iatt( kiomid, cdatt, katt1d, cdvar )
      INTEGER               , INTENT(in   )           ::   kiomid    ! Identifier of the file
      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt     ! Name of the attribute
      INTEGER, DIMENSION(:) , INTENT(in   )           ::   katt1d    ! written field
      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar     ! Name of the variable
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 )   CALL iom_nf90_putatt( kiomid, cdatt,  katt1d =  katt1d, cdvar=cdvar )
      ENDIF
   END SUBROUTINE iom_p1d_iatt

   SUBROUTINE iom_p0d_ratt( kiomid, cdatt, patt0d, cdvar )
      INTEGER               , INTENT(in   )           ::   kiomid    ! Identifier of the file
      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt     ! Name of the attribute
      REAL(wp)              , INTENT(in   )           ::   patt0d    ! written field
      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar     ! Name of the variable
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 )   CALL iom_nf90_putatt( kiomid, cdatt,  patt0d =  patt0d, cdvar=cdvar )
      ENDIF
   END SUBROUTINE iom_p0d_ratt

   SUBROUTINE iom_p1d_ratt( kiomid, cdatt, patt1d, cdvar )
      INTEGER               , INTENT(in   )           ::   kiomid    ! Identifier of the file
      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt     ! Name of the attribute
      REAL(wp), DIMENSION(:), INTENT(in   )           ::   patt1d    ! written field
      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar     ! Name of the variable
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 )   CALL iom_nf90_putatt( kiomid, cdatt,  patt1d =  patt1d, cdvar=cdvar )
      ENDIF
   END SUBROUTINE iom_p1d_ratt

   SUBROUTINE iom_p0d_catt( kiomid, cdatt, cdatt0d, cdvar )
      INTEGER               , INTENT(in   )           ::   kiomid    ! Identifier of the file
      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt     ! Name of the attribute
      CHARACTER(len=*)      , INTENT(in   )           ::   cdatt0d   ! written field
      CHARACTER(len=*)      , INTENT(in   ), OPTIONAL ::   cdvar     ! Name of the variable
      !
      IF( kiomid > 0 ) THEN
         IF( iom_file(kiomid)%nfid > 0 )   CALL iom_nf90_putatt( kiomid, cdatt, cdatt0d = cdatt0d, cdvar=cdvar )
      ENDIF
   END SUBROUTINE iom_p0d_catt


   !!----------------------------------------------------------------------
   !!                   INTERFACE iom_rstput
   !!----------------------------------------------------------------------
   SUBROUTINE iom_rp0d_sp( kt, kwrite, kiomid, cdvar, pvar, ktype )
      INTEGER         , INTENT(in)                         ::   kt       ! ocean time-step
      INTEGER         , INTENT(in)                         ::   kwrite   ! writing time-step
      INTEGER         , INTENT(in)                         ::   kiomid   ! Identifier of the file
      CHARACTER(len=*), INTENT(in)                         ::   cdvar    ! time axis name
      REAL(sp)        , INTENT(in)                         ::   pvar     ! written field
      INTEGER         , INTENT(in), OPTIONAL               ::   ktype    ! variable external type
      !
      LOGICAL           :: llx                ! local xios write flag
      INTEGER           :: ivid   ! variable id
      CHARACTER(LEN=lc) :: context
      !
      CALL set_xios_context(kiomid, context)

      llx = .NOT. (context == "NONE")

      IF( llx ) THEN
#ifdef key_xios
         IF( kt == kwrite ) THEN
            IF(lwp) write(numout,*) 'RESTART: write (XIOS 0D) ',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ELSE
            IF(lwp) write(numout,*) 'RESTART: define (XIOS 0D) ',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
            CALL iom_set_rstw_active( TRIM(cdvar), rs0 = pvar )
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ENDIF
#endif
      ELSE
         IF( kiomid > 0 ) THEN
            IF( iom_file(kiomid)%nfid > 0 ) THEN
               ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
               CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r0d = real(pvar, dp) )
            ENDIF
         ENDIF
      ENDIF
   END SUBROUTINE iom_rp0d_sp

   SUBROUTINE iom_rp0d_dp( kt, kwrite, kiomid, cdvar, pvar, ktype )
      INTEGER         , INTENT(in)                         ::   kt       ! ocean time-step
      INTEGER         , INTENT(in)                         ::   kwrite   ! writing time-step
      INTEGER         , INTENT(in)                         ::   kiomid   ! Identifier of the file
      CHARACTER(len=*), INTENT(in)                         ::   cdvar    ! time axis name
      REAL(dp)        , INTENT(in)                         ::   pvar     ! written field
      INTEGER         , INTENT(in), OPTIONAL               ::   ktype    ! variable external type
      !
      LOGICAL           :: llx                ! local xios write flag
      INTEGER           :: ivid   ! variable id
      CHARACTER(LEN=lc) :: context
      !
      CALL set_xios_context(kiomid, context)

      llx = .NOT. (context == "NONE")

      IF( llx ) THEN
#ifdef key_xios
         IF( kt == kwrite ) THEN
            IF(lwp) write(numout,*) 'RESTART: write (XIOS 0D) ',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ELSE
            IF(lwp) write(numout,*) 'RESTART: define (XIOS 0D) ',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
            CALL iom_set_rstw_active( TRIM(cdvar), rd0 = pvar )
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ENDIF
#endif
      ELSE
         IF( kiomid > 0 ) THEN
            IF( iom_file(kiomid)%nfid > 0 ) THEN
               ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
               CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r0d = pvar )
            ENDIF
         ENDIF
      ENDIF
   END SUBROUTINE iom_rp0d_dp


   SUBROUTINE iom_rp1d_sp( kt, kwrite, kiomid, cdvar, pvar, ktype )
      INTEGER         , INTENT(in)                         ::   kt       ! ocean time-step
      INTEGER         , INTENT(in)                         ::   kwrite   ! writing time-step
      INTEGER         , INTENT(in)                         ::   kiomid   ! Identifier of the file
      CHARACTER(len=*), INTENT(in)                         ::   cdvar    ! time axis name
      REAL(sp)        , INTENT(in), DIMENSION(          :) ::   pvar     ! written field
      INTEGER         , INTENT(in), OPTIONAL               ::   ktype    ! variable external type
      !
      LOGICAL           :: llx                ! local xios write flag
      INTEGER           :: ivid   ! variable id
      CHARACTER(LEN=lc) :: context
      !
      CALL set_xios_context(kiomid, context)

      llx = .NOT. (context == "NONE")

      IF( llx ) THEN
#ifdef key_xios
         IF( kt == kwrite ) THEN
            IF(lwp) write(numout,*) 'RESTART: write (XIOS 1D) ',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ELSE
            IF(lwp) write(numout,*) 'RESTART: define (XIOS 1D)',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
            CALL iom_set_rstw_active( TRIM(cdvar), rs1 = pvar )
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ENDIF
#endif
      ELSE
         IF( kiomid > 0 ) THEN
            IF( iom_file(kiomid)%nfid > 0 ) THEN
               ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
               CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r1d = real(pvar, dp) )
            ENDIF
         ENDIF
      ENDIF
   END SUBROUTINE iom_rp1d_sp

   SUBROUTINE iom_rp1d_dp( kt, kwrite, kiomid, cdvar, pvar, ktype )
      INTEGER         , INTENT(in)                         ::   kt       ! ocean time-step
      INTEGER         , INTENT(in)                         ::   kwrite   ! writing time-step
      INTEGER         , INTENT(in)                         ::   kiomid   ! Identifier of the file
      CHARACTER(len=*), INTENT(in)                         ::   cdvar    ! time axis name
      REAL(dp)        , INTENT(in), DIMENSION(          :) ::   pvar     ! written field
      INTEGER         , INTENT(in), OPTIONAL               ::   ktype    ! variable external type
      !
      LOGICAL           :: llx                ! local xios write flag
      INTEGER           :: ivid   ! variable id
      CHARACTER(LEN=lc) :: context
      !
      CALL set_xios_context(kiomid, context)

      llx = .NOT. (context == "NONE")

      IF( llx ) THEN
#ifdef key_xios
         IF( kt == kwrite ) THEN
            IF(lwp) write(numout,*) 'RESTART: write (XIOS 1D) ',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ELSE
            IF(lwp) write(numout,*) 'RESTART: define (XIOS 1D)',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
            CALL iom_set_rstw_active( TRIM(cdvar), rd1 = pvar )
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ENDIF
#endif
      ELSE
         IF( kiomid > 0 ) THEN
            IF( iom_file(kiomid)%nfid > 0 ) THEN
               ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
               CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r1d = pvar )
            ENDIF
         ENDIF
      ENDIF
   END SUBROUTINE iom_rp1d_dp


   SUBROUTINE iom_rp2d_sp( kt, kwrite, kiomid, cdvar, pvar, ktype )
      INTEGER         , INTENT(in)                         ::   kt       ! ocean time-step
      INTEGER         , INTENT(in)                         ::   kwrite   ! writing time-step
      INTEGER         , INTENT(in)                         ::   kiomid   ! Identifier of the file
      CHARACTER(len=*), INTENT(in)                         ::   cdvar    ! time axis name
      REAL(sp)        , INTENT(in), DIMENSION(:,    :    ) ::   pvar     ! written field
      INTEGER         , INTENT(in), OPTIONAL               ::   ktype    ! variable external type
      !
      LOGICAL            :: llx
      INTEGER            :: ivid   ! variable id
      CHARACTER(LEN=lc)  :: context
      !
      CALL set_xios_context(kiomid, context)

      llx = .NOT. (context == "NONE")

      IF( llx ) THEN
#ifdef key_xios
         IF( kt == kwrite ) THEN
            IF(lwp) write(numout,*) 'RESTART: write (XIOS 2D) ',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ELSE
            IF(lwp) write(numout,*) 'RESTART: define (XIOS 2D)',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
            CALL iom_set_rstw_active( TRIM(cdvar), rs2 = pvar )
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ENDIF
#endif
      ELSE
         IF( kiomid > 0 ) THEN
            IF( iom_file(kiomid)%nfid > 0 ) THEN
               ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
               CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r2d = real(pvar, dp) )
            ENDIF
         ENDIF
      ENDIF
   END SUBROUTINE iom_rp2d_sp

   SUBROUTINE iom_rp2d_dp( kt, kwrite, kiomid, cdvar, pvar, ktype )
      INTEGER         , INTENT(in)                         ::   kt       ! ocean time-step
      INTEGER         , INTENT(in)                         ::   kwrite   ! writing time-step
      INTEGER         , INTENT(in)                         ::   kiomid   ! Identifier of the file
      CHARACTER(len=*), INTENT(in)                         ::   cdvar    ! time axis name
      REAL(dp)        , INTENT(in), DIMENSION(:,    :    ) ::   pvar     ! written field
      INTEGER         , INTENT(in), OPTIONAL               ::   ktype    ! variable external type
      !
      LOGICAL           :: llx
      INTEGER           :: ivid   ! variable id
      CHARACTER(LEN=lc) :: context
      !
      CALL set_xios_context(kiomid, context)

      llx = .NOT. (context == "NONE")

      IF( llx ) THEN
#ifdef key_xios
         IF( kt == kwrite ) THEN
            IF(lwp) write(numout,*) 'RESTART: write (XIOS 2D) ',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ELSE
            IF(lwp) write(numout,*) 'RESTART: define (XIOS 2D)',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
            CALL iom_set_rstw_active( TRIM(cdvar), rd2 = pvar )
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ENDIF
#endif
      ELSE
         IF( kiomid > 0 ) THEN
            IF( iom_file(kiomid)%nfid > 0 ) THEN
               ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
               CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r2d = pvar )
            ENDIF
         ENDIF
      ENDIF
   END SUBROUTINE iom_rp2d_dp


   SUBROUTINE iom_rp3d_sp( kt, kwrite, kiomid, cdvar, pvar, ktype )
      INTEGER         , INTENT(in)                         ::   kt       ! ocean time-step
      INTEGER         , INTENT(in)                         ::   kwrite   ! writing time-step
      INTEGER         , INTENT(in)                         ::   kiomid   ! Identifier of the file
      CHARACTER(len=*), INTENT(in)                         ::   cdvar    ! time axis name
      REAL(sp)        , INTENT(in),       DIMENSION(:,:,:) ::   pvar     ! written field
      INTEGER         , INTENT(in), OPTIONAL               ::   ktype    ! variable external type
      !
      LOGICAL           :: llx                 ! local xios write flag
      INTEGER           :: ivid   ! variable id
      CHARACTER(LEN=lc) :: context
      !
      CALL set_xios_context(kiomid, context)

      llx = .NOT. (context == "NONE")

      IF( llx ) THEN
#ifdef key_xios
         IF( kt == kwrite ) THEN
            IF(lwp) write(numout,*) 'RESTART: write (XIOS 3D) ',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ELSE
            IF(lwp) write(numout,*) 'RESTART: define (XIOS 3D)',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
            CALL iom_set_rstw_active( TRIM(cdvar), rs3 = pvar )
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ENDIF
#endif
      ELSE
         IF( kiomid > 0 ) THEN
            IF( iom_file(kiomid)%nfid > 0 ) THEN
               ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
               CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r3d = real(pvar, dp) )
            ENDIF
         ENDIF
      ENDIF
   END SUBROUTINE iom_rp3d_sp

   SUBROUTINE iom_rp3d_dp( kt, kwrite, kiomid, cdvar, pvar, ktype )
      INTEGER         , INTENT(in)                         ::   kt       ! ocean time-step
      INTEGER         , INTENT(in)                         ::   kwrite   ! writing time-step
      INTEGER         , INTENT(in)                         ::   kiomid   ! Identifier of the file
      CHARACTER(len=*), INTENT(in)                         ::   cdvar    ! time axis name
      REAL(dp)        , INTENT(in),       DIMENSION(:,:,:) ::   pvar     ! written field
      INTEGER         , INTENT(in), OPTIONAL               ::   ktype    ! variable external type
      !
      LOGICAL           :: llx                 ! local xios write flag
      INTEGER           :: ivid   ! variable id
      CHARACTER(LEN=lc) :: context
      !
      CALL set_xios_context(kiomid, context)

      llx = .NOT. (context == "NONE")

      IF( llx ) THEN
#ifdef key_xios
         IF( kt == kwrite ) THEN
            IF(lwp) write(numout,*) 'RESTART: write (XIOS 3D) ',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ELSE
            IF(lwp) write(numout,*) 'RESTART: define (XIOS 3D)',TRIM(cdvar)
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(context)
            CALL iom_set_rstw_active( TRIM(cdvar), rd3 = pvar )
Guillaume Samson's avatar
Guillaume Samson committed
            CALL iom_swap(cxios_context)
         ENDIF
#endif
      ELSE
         IF( kiomid > 0 ) THEN
            IF( iom_file(kiomid)%nfid > 0 ) THEN
               ivid = iom_varid( kiomid, cdvar, ldstop = .FALSE. )
               CALL iom_nf90_rstput( kt, kwrite, kiomid, cdvar, ivid, ktype, pv_r3d = pvar )
            ENDIF
         ENDIF
      ENDIF
   END SUBROUTINE iom_rp3d_dp



  SUBROUTINE iom_delay_rst( cdaction, cdcpnt, kncid )
      !!---------------------------------------------------------------------
      !!   Routine iom_delay_rst: used read/write restart related to mpp_delay
      !!
      !!---------------------------------------------------------------------
      CHARACTER(len=*), INTENT(in   ) ::   cdaction        !
      CHARACTER(len=*), INTENT(in   ) ::   cdcpnt
      INTEGER         , INTENT(in   ) ::   kncid
      !
      INTEGER  :: ji
      INTEGER  :: indim
      LOGICAL  :: llattexist
      REAL(wp), ALLOCATABLE, DIMENSION(:) ::   zreal1d
      !!---------------------------------------------------------------------
      !
      !                                      ===================================
      IF( TRIM(cdaction) == 'READ' ) THEN   ! read restart related to mpp_delay !
         !                                   ===================================
         DO ji = 1, nbdelay
            IF ( c_delaycpnt(ji) == cdcpnt ) THEN
               CALL iom_chkatt( kncid, 'DELAY_'//c_delaylist(ji), llattexist, indim )
               IF( llattexist )  THEN
                  ALLOCATE( todelay(ji)%z1d(indim) )
                  CALL iom_getatt( kncid, 'DELAY_'//c_delaylist(ji), todelay(ji)%z1d(:) )
                  ndelayid(ji) = 0   ! set to 0 to specify that the value was read in the restart
               ENDIF
           ENDIF
         END DO
         !                                   ====================================
      ELSE                                  ! write restart related to mpp_delay !
         !                                   ====================================
         DO ji = 1, nbdelay   ! save only ocean delayed global communication variables
            IF ( c_delaycpnt(ji) == cdcpnt ) THEN
               IF( ASSOCIATED(todelay(ji)%z1d) ) THEN
                  CALL mpp_delay_rcv(ji)   ! make sure %z1d is received
                  CALL iom_putatt( kncid, 'DELAY_'//c_delaylist(ji), todelay(ji)%z1d(:) )
               ENDIF
            ENDIF
         END DO
         !
      ENDIF

   END SUBROUTINE iom_delay_rst



   !!----------------------------------------------------------------------
   !!                   INTERFACE iom_put
   !!----------------------------------------------------------------------
   SUBROUTINE iom_p0d_sp( cdname, pfield0d )
      CHARACTER(LEN=*), INTENT(in) ::   cdname
      REAL(sp)        , INTENT(in) ::   pfield0d
      !!      REAL(wp)        , DIMENSION(jpi,jpj) ::   zz     ! masson
#if defined key_xios
!!clem      zz(:,:)=pfield0d
!!clem      CALL xios_send_field(cdname, zz)
      CALL xios_send_field(cdname, (/pfield0d/))
#else
      IF( .FALSE. )   WRITE(numout,*) cdname, pfield0d   ! useless test to avoid compilation warnings
#endif
   END SUBROUTINE iom_p0d_sp

   SUBROUTINE iom_p0d_dp( cdname, pfield0d )
      CHARACTER(LEN=*), INTENT(in) ::   cdname