Index: trunk/NEMO/OPA_SRC/SBC/fldread.F90
===================================================================
--- trunk/NEMO/OPA_SRC/SBC/fldread.F90	(revision 892)
+++ trunk/NEMO/OPA_SRC/SBC/fldread.F90	(revision 1132)
@@ -26,6 +26,6 @@
       CHARACTER(len = 34) ::   clvar       ! generic name of the variable in the NetCDF flux file
       LOGICAL             ::   ln_tint     ! time interpolation or not (T/F)
-      INTEGER             ::   nclim       ! =0 interannuel, =1 climatology
-      INTEGER             ::   nstrec      ! starting record, used if nclim=1 (=0 last record of previous year) 
+      LOGICAL             ::   ln_clim     ! climatology or not (T/F)
+      CHARACTER(len = 7)  ::   cltype      ! type of data file 'monthly' or yearly'
    END TYPE FLD_N
 
@@ -36,17 +36,15 @@
       CHARACTER(len = 34)             ::   clvar        ! generic name of the variable in the NetCDF flux file
       LOGICAL                         ::   ln_tint      ! time interpolation or not (T/F)
-      INTEGER                         ::   nyear        ! year of the file (=0000 if climatology)
-      INTEGER                         ::   nclim        ! =0 interannuel, =1 climatology
-      INTEGER                         ::   nstrec       ! starting record if nclim=1 (=0 last record of previous year) 
-      INTEGER                         ::   num          ! logical units of the jpfld files to be read
-      REAL(wp) , DIMENSION(2)         ::   rec_b        ! before record info (1: index, 2: second since Jan. 1st 00h)
-      REAL(wp) , DIMENSION(2)         ::   rec_n        ! now    record info (1: index, 2: second since Jan. 1st 00h)
-      REAL(wp) , DIMENSION(2)         ::   rec_a        ! next   record info (1: index, 2: second since Jan. 1st 00h)
-      REAL(wp) , DIMENSION(2)         ::   rec          ! record time in second since jan. 1st for the 2 records read
+      LOGICAL                         ::   ln_clim      ! climatology or not (T/F)
+      CHARACTER(len = 7)              ::   cltype       ! type of data file 'monthly' or yearly'
+      INTEGER                         ::   num          ! iom id of the jpfld files to be read
+      REAL(wp)                        ::   swap_sec     ! swapping time in second since Jan. 1st 00h of nit000 year
+      REAL(wp) , DIMENSION(2)         ::   rec_b        ! before record (1: index, 2: second since Jan. 1st 00h of nit000 year
+      REAL(wp) , DIMENSION(2)         ::   rec_a        ! after  record (1: index, 2: second since Jan. 1st 00h of nit000 year
       REAL(wp) , DIMENSION(jpi,jpj)   ::   fnow         ! input fields interpolated to now time step
-      REAL(wp) , DIMENSION(jpi,jpj,2) ::   fdta         !  2 consecutive record of input fields
+      REAL(wp) , DIMENSION(jpi,jpj,2) ::   fdta         ! 2 consecutive record of input fields
    END TYPE FLD
 
-   PUBLIC   fld_read    ! called by sbc... modules
+   PUBLIC   fld_read, fld_fill   ! called by sbc... modules
 
    !!----------------------------------------------------------------------
@@ -71,128 +69,107 @@
       !!----------------------------------------------------------------------
       INTEGER  , INTENT(in   )               ::   kt        ! ocean time step
-      INTEGER  , INTENT(in   )               ::   kn_fsbc   ! ocean time step
+      INTEGER  , INTENT(in   )               ::   kn_fsbc   ! sbc computation period (in time step) 
       TYPE(FLD), INTENT(inout), DIMENSION(:) ::   sd        ! input field related variables
       !!
-      INTEGER  ::   jf                     ! dummy indices
-      INTEGER  ::   imf                    ! size of the structure sd
-      REAL(wp) ::   zt                     ! ratio at kt between the 2 records
-      REAL(wp), DIMENSION(2) ::   zrec_kt
-      !!---------------------------------------------------------------------
-
-      imf = SIZE( sd )       ! dummy indices
-
+      INTEGER  ::   jf         ! dummy indices
+      REAL(wp) ::   zreclast   ! last record to be read in the current year file
+      REAL(wp) ::   zsecend    ! number of second since Jan. 1st 00h of nit000 year at nitend
+      LOGICAL  ::   llnxtyr    ! open next year file?
+      LOGICAL  ::   llstop     ! stop is the file is not existing
+      REAL(wp) ::   ztinta     ! ratio applied to after  records when doing time interpolation
+      REAL(wp) ::   ztintb     ! ratio applied to before records when doing time interpolation
+      !!---------------------------------------------------------------------
       !                                         ! ===================== !
-      DO jf = 1, imf                            !    LOOP OVER FIELD    !
+      DO jf = 1, SIZE( sd )                     !    LOOP OVER FIELD    !
          !                                      ! ===================== !
          !
-         !                                            ! ====================== !
-         IF( kt == nit000 ) THEN                      !     Initialisation     !
-            !                                         ! ====================== !
+         IF( kt == nit000 )   CALL fld_init( sd(jf) )
+         !
+         ! read/update the after data?
+         IF( rsec_year + sec1jan000 > sd(jf)%swap_sec ) THEN 
+
+            IF( sd(jf)%ln_tint ) THEN         ! time interpolation: swap before record field
+!CDIR COLLAPSE
+               sd(jf)%fdta(:,:,1) = sd(jf)%fdta(:,:,2)
+            ENDIF
+
+            ! update record informations
+            CALL fld_rec( sd(jf) )
+
+            ! do we have to change the year/month of the forcing field?? 
+            IF( sd(jf)%ln_tint ) THEN
+               ! if we do time interpolation we will need to open next year/month file before the end of the current year/month
+               ! if it is the case, we are still before the end of the year/month when calling fld_rec so sd(jf)%rec_a(1) will 
+               ! be larger than the record number that should be read for current year/month (for ex. 13 for monthly mean file)
+
+               ! last record to be read in the current file
+               IF( sd(jf)%freqh == -1. ) THEN     ;          zreclast = 12.
+               ELSE                             
+                  IF( sd(jf)%cltype == 'monthly' ) THEN   ;   zreclast = 24. / sd(jf)%freqh * REAL( nmonth_len(nmonth), wp )
+                  ELSE                                    ;   zreclast = 24. / sd(jf)%freqh * REAL( nyear_len(     1 ), wp )
+                  ENDIF
+               ENDIF
+              
+               ! do we need next year data?
+               IF( sd(jf)%rec_a(1) > zreclast ) THEN
+
+                  sd(jf)%rec_a(1) = 1.              ! force to read the first record of the next year
+
+                  IF( .NOT. sd(jf)%ln_clim ) THEN   ! close the current file and open a new one.
+                     
+                     llnxtyr  = sd(jf)%cltype /= 'monthly' .OR. nmonth == 12   ! do we need to open next year file?
+                     ! if the run finishes at the end of the current year/month, we do accept that next year/month file does 
+                     ! not exist. If the run continue farther than the current year/month, next year/month file must exist
+                     zsecend = rsec_year + sec1jan000 + REAL(nitend - kt, wp) * rdttra(1)   ! second at the end of the run 
+                     llstop = zsecend > sd(jf)%swap_sec                                 ! read more than 1 record of next year
+
+                     CALL fld_clopn( sd(jf), nyear + COUNT((/llnxtyr/)), nmonth + 1 - 12 * COUNT((/llnxtyr/)), llstop )
+
+                     IF( sd(jf)%num == 0 .AND. .NOT. llstop ) THEN    ! next year file is not existing
+                        CALL ctl_warn('next year/month file: '//TRIM(sd(jf)%clname)//' not existing -> back to current year/month')
+                        CALL fld_clopn( sd(jf), nyear, nmonth )       ! back to the current year/month
+                        sd(jf)%rec_a(1) = zreclast     ! force to read the last record to be read in the current year file
+                     ENDIF
+
+                  ENDIF 
+               ENDIF
+        
+            ELSE
+               ! if we are not doing time interpolation, we must change the year/month of the file just afer switching
+               ! to the NEW year/month. If it is the case, we are at the beginning of the year/month when calling fld_rec
+               ! so sd(jf)%rec_a(1) = 1
+               IF( sd(jf)%rec_a(1) == 1 )   CALL fld_clopn( sd(jf), nyear, nmonth )   ! back to the current year/month
+            ENDIF
+
+            ! read after data
+            CALL iom_get( sd(jf)%num, jpdom_data, sd(jf)%clvar, sd(jf)%fdta(:,:,2), NINT( sd(jf)%rec_a(1) ) )
+
+         ENDIF
+
+         ! update field at each kn_fsbc time-step
+         IF( MOD( kt-1, kn_fsbc ) == 0 ) THEN   
             !
-            !                                             ! set filename for current year 
-            SELECT CASE( sd(jf)%nclim )
-            CASE( 0 )   
-               WRITE(sd(jf)%clname, '(a,"_",i4,".nc")' ) TRIM( sd(jf)%clrootname ), nyear
-               sd(jf)%nyear = nyear
-            CASE( 1 )   
-               WRITE(sd(jf)%clname, '(a,  ".nc")' ) TRIM( sd(jf)%clrootname )
-               sd(jf)%nyear = 0000
-            END SELECT
-            CALL iom_open( sd(jf)%clname, sd(jf)%num )    ! open input files
-            !
-            IF( sd(jf)%ln_tint ) THEN                     ! time interpolation: read previous record in now field
+            IF( sd(jf)%ln_tint ) THEN
+               IF(lwp .AND. kt - nit000 <= 100 )   WRITE(numout,*)'fld_read: var ', TRIM( sd(jf)%clvar ),           &
+                  & ' kt = ', kt,' Y/M/D = ', nyear,'/', nmonth,'/', nday,' records b/a:', NINT(sd(jf)%rec_b(1)),   &
+                  & '/', NINT(sd(jf)%rec_a(1)), ' (', sd(jf)%rec_b(2)/rday,'/', sd(jf)%rec_a(2)/rday, ' days)'
                !
-               sd(jf)%rec_n = fld_rec( sd(jf)%freqh, sd(jf)%ln_tint, sd(jf)%nclim, -1 )     ! record index and time
-               !
-               !                                                                            ! read record
-               CALL iom_get( sd(jf)%num, jpdom_data, sd(jf)%clvar, sd(jf)%fdta(:,:,2), INT( sd(jf)%rec_n(1) ) )
-               !
-               !                                                                            ! control print
-               IF(lwp) WRITE(numout,*)'fld_read : time-interpolation for ', TRIM( sd(jf)%clvar ),   &
-                  &   ' read previous record =', INT(sd(jf)%rec_n(1)), ' at time = ', sd(jf)%rec_n(2)/rday, ' days'
-               !
-            ENDIF
-            !                                              ! next record to be read
-            sd(jf)%rec_a = fld_rec( sd(jf)%freqh, sd(jf)%ln_tint, sd(jf)%nclim, 0 )
-
-            IF(lwp) WRITE(numout,*)'                                   ',    &
-                  &   ' after record         =', INT(sd(jf)%rec_a(1)), ' at time = ', sd(jf)%rec_a(2)/rday, ' days'
-            !
-         ENDIF
-         !
-         !                                            ! ============================= !
-         IF( sd(jf)%nclim == 0   .AND.   &            !            New Year           !
-             sd(jf)%nyear == nyear - 1 ) THEN         ! ============================= !
-            !
-            CALL iom_close( sd(jf)%num )
-            IF(lwp) WRITE(numout,*) 'fldread : switch to a new year= ', nyear
-            WRITE( sd(jf)%clname, '(a,"_",i4,".nc")' ) TRIM( sd(jf)%clrootname ), nyear
-            sd(jf)%nyear = nyear
-            CALL iom_open( sd(jf)%clname, sd(jf)%num )
-            !
-            IF( sd(jf)%ln_tint ) THEN       ! no record index change, update record time
-               sd(jf)%rec_b(1:2) = fld_rec( sd(jf)%freqh, sd(jf)%ln_tint, sd(jf)%nclim, -1 )
-               sd(jf)%rec_n(1:2) = fld_rec( sd(jf)%freqh, sd(jf)%ln_tint, sd(jf)%nclim,  0 )
-               sd(jf)%rec_a(1:2) = fld_rec( sd(jf)%freqh, sd(jf)%ln_tint, sd(jf)%nclim, +1 )   
-            ELSE                            ! ???
-               sd(jf)%rec_n(1:2) = fld_rec( sd(jf)%freqh, sd(jf)%ln_tint, sd(jf)%nclim, -1 )
-               sd(jf)%rec_a(1:2) = fld_rec( sd(jf)%freqh, sd(jf)%ln_tint, sd(jf)%nclim,  0 )   
+               ztinta =  ( rsec_year + sec1jan000 - sd(jf)%rec_b(2) ) / ( sd(jf)%rec_a(2) - sd(jf)%rec_b(2) )
+               ztintb =  1. - ztinta
+!CDIR COLLAPSE
+               sd(jf)%fnow(:,:) = ztintb * sd(jf)%fdta(:,:,1) + ztinta * sd(jf)%fdta(:,:,2)
+            ELSE
+               IF(lwp .AND. kt - nit000 <= 100 )   WRITE(numout,*)'fld_read: var ', TRIM( sd(jf)%clvar ),        &
+                  & ' kt = ', kt, ' Y/M/D = ', nyear,'/', nmonth,'/', nday, ' record :', INT(sd(jf)%rec_a(1)),   &
+                  & ' at ', sd(jf)%rec_a(2)/rday, 'day'
+!CDIR COLLAPSE
+               sd(jf)%fnow(:,:) = sd(jf)%fdta(:,:,2)   ! piecewise constant field
+ 
             ENDIF
             !
          ENDIF
-         !
-         !                                            ! ============================= !
-         !                                            !   Read / Update input fields  !
-         !                                            ! ============================= !
-         !
-         ! current record index 
-         zrec_kt(1:2) = fld_rec( sd(jf)%freqh, sd(jf)%ln_tint, sd(jf)%nclim, 0 ) 
-         !
-         ! read next record (if required)
-         IF( zrec_kt(1) == sd(jf)%rec_a(1) ) THEN 
-            !
-            IF( sd(jf)%ln_tint ) THEN         ! time interpolation: swap
-               sd(jf)%rec_b = fld_rec( sd(jf)%freqh, sd(jf)%ln_tint, sd(jf)%nclim, -1 )   ! record index & time
-!CDIR COLLAPSE
-               sd(jf)%fdta(:,:,1) = sd(jf)%fdta(:,:,2)                                    ! record field
-            ENDIF
-            !
-            sd(jf)%rec_n(:) = zrec_kt(:)      ! update now record index & time
-            !                                 ! read record
-            CALL iom_get( sd(jf)%num, jpdom_data, sd(jf)%clvar, sd(jf)%fdta(:,:,2), INT( sd(jf)%rec_n(1) ) )
-            !
-            !                                 ! after record index & time
-            sd(jf)%rec_a(1:2) = fld_rec( sd(jf)%freqh, sd(jf)%ln_tint, sd(jf)%nclim, +1 )   
-            !
-            !                                 ! control print
-            IF( sd(jf)%ln_tint ) THEN
-               IF(lwp .AND. nitend - nit000 <= 100 )   WRITE(numout,*)'fld_read: var ', TRIM( sd(jf)%clvar ),   &
-                  & ' D/M=', nday,'/',nmonth,' rec bna:', INT(sd(jf)%rec_b(1)), INT(sd(jf)%rec_n(1)),INT(sd(jf)%rec_a(1)), &
-                  & ' zrec bna', sd(jf)%rec_b(2)/rday, sd(jf)%rec_n(2)/rday, sd(jf)%rec_a(2)/rday
-            ELSE
-               IF(lwp .AND. nitend - nit000 <= 100 )   WRITE(numout,*)'fld_read: var ', TRIM( sd(jf)%clvar ),   &
-                  & ' D/M=', nday,'/',nmonth, ' record :', INT(sd(jf)%rec_n(1)),     &
-                  & ' at', sd(jf)%rec_n(2)/rday, 'day,  next rec', INT(sd(jf)%rec_a(1))
-            ENDIF
-         ENDIF
-
-         IF( MOD( kt-1, kn_fsbc ) == 0 ) THEN                              !** update field at each kn_fsbc time-step
-            !
-            IF( sd(jf)%ln_tint ) THEN                                       !* linear time interpolated field
-               zt =  ( rsec_year - sd(jf)%rec_b(2) ) / ( sd(jf)%rec_n(2) - sd(jf)%rec_b(2) )
-!CDIR COLLAPSE
-               sd(jf)%fnow(:,:) = ( 1. - zt ) * sd(jf)%fdta(:,:,1) + zt * sd(jf)%fdta(:,:,2)
-            ELSE
-!CDIR COLLAPSE
-               sd(jf)%fnow(:,:) = sd(jf)%fdta(:,:,2)                        !* piecewise constant field
-            ENDIF
-            !
-         ENDIF
-         !
-         !                                         ! ======================== !
-         IF( kt == nitend ) THEN                   !  Close the input files   !
-            !                                      ! ======================== !
-            CALL iom_close( sd(jf)%num )
-         ENDIF
+
+         IF( kt == nitend )   CALL iom_close( sd(jf)%num )   ! Close the input files
+
          !                                      ! ===================== !
       END DO                                    !  END LOOP OVER FIELD  !
@@ -201,60 +178,257 @@
 
 
-   FUNCTION fld_rec( pfreq, ld_tint, kclim, kshift )   RESULT( prec_info )
+   SUBROUTINE fld_init( sdjf )
+      !!---------------------------------------------------------------------
+      !!                    ***  ROUTINE fld_init  ***
+      !!
+      !! ** Purpose :  - if time interpolation, read before data 
+      !!               - open current year file
+      !!
+      !! ** Method  :   
+      !!----------------------------------------------------------------------
+      TYPE(FLD), INTENT(inout) ::   sdjf        ! input field related variables
+      !!
+      LOGICAL :: llprevyr       ! are we reading previous year  file?
+      LOGICAL :: llprevmth      ! are we reading previous month file?
+      LOGICAL :: llprev         ! llprevyr .OR. llprevmth
+      INTEGER :: idvar          ! variable id 
+      INTEGER :: inrec          ! number of record existing for this variable
+      !!---------------------------------------------------------------------
+
+      ! some default definitions...
+      sdjf%num = 0   ! default definition for non-opened file
+      IF( sdjf%ln_clim )   sdjf%clname = TRIM( sdjf%clrootname )   ! file name defaut definition, never change in this case
+      llprevyr  = .FALSE.
+      llprevmth = .FALSE.
+            
+      ! define record informations
+      CALL fld_rec( sdjf )
+
+      IF( sdjf%ln_tint ) THEN ! we need to read the previous record and we will put it in the current record structure
+         
+         IF( sdjf%rec_b(1) == 0.e0 ) THEN   ! we redefine record sdjf%rec_b(1) with the last record of previous year file
+            IF( sdjf%freqh == -1. ) THEN   ! monthly mean
+               sdjf%rec_b(1) = 12.          ! force to read december mean
+            ELSE   
+               IF( sdjf%cltype == 'monthly' ) THEN   ! monthly file
+                  sdjf%rec_b(1) = 24. / sdjf%freqh * REAL( nmonth_len(nmonth-1), wp )   ! last record of previous month
+                  llprevmth = sdjf%ln_clim                                              ! use previous month file?
+                  llprevyr  = sdjf%ln_clim .AND. nmonth == 1                            ! use previous year  file?
+               ELSE                                  ! yearly file
+                  sdjf%rec_b(1) = 24. / sdjf%freqh * REAL( nyear_len(0), wp )           ! last record of year month
+                  llprevyr = sdjf%ln_clim                                               ! use previous year  file?
+               ENDIF
+            ENDIF
+         ENDIF
+         llprev = llprevyr .OR. llprevmth
+
+         CALL fld_clopn( sdjf, nyear - COUNT((/llprevyr/)), nmonth - COUNT((/llprevmth/)) + 12 * COUNT((/llprevyr/)), llprev )
+
+         ! if previous year/month file is not existing, we switch to the current year/month
+         IF( llprev .AND. sdjf%num == 0 ) THEN
+            CALL ctl_warn( 'previous year/month file: '//TRIM(sdjf%clname)//' not existing -> back to current year/month' )
+            ! we force to read the first record of the current year/month instead of last record of previous year/month
+            llprev = .false.
+            sdjf%rec_b(1) = 1.
+            CALL fld_clopn( sdjf, nyear, nmonth )
+         ENDIF
+         
+         IF( llprev ) THEN   ! check if the last record sdjf%rec_n(1) exists in the file
+            idvar = iom_varid( sdjf%num, sdjf%clvar )                                        ! id of the variable sdjf%clvar
+            IF( idvar <= 0 )   RETURN
+            inrec = iom_file( sdjf%num )%dimsz( iom_file( sdjf%num )%ndims(idvar), idvar )   ! size of the last dim of idvar
+            sdjf%rec_b(1) = MIN( sdjf%rec_b(1), REAL( inrec, wp ) )   ! make sure we select an existing record
+         ENDIF
+
+         ! read before data into sdjf%fdta(:,:,2) because we will swap data in the following part of fld_read
+         CALL iom_get( sdjf%num, jpdom_data, sdjf%clvar, sdjf%fdta(:,:,2), NINT( sdjf%rec_b(1) ) )
+
+         IF(lwp) WRITE(numout,*)'fld_init : time-interpolation for ', TRIM( sdjf%clvar ),   &
+            &   ' read previous record =', NINT(sdjf%rec_b(1)), ' at time = ', sdjf%rec_b(2)/rday, ' days'
+
+         IF( llprev )   CALL iom_close( sdjf%num )   ! close previous year file (-> redefine sdjf%num to 0)
+
+      ENDIF
+
+      IF( sdjf%num == 0 )   CALL fld_clopn( sdjf, nyear, nmonth )   ! make sure current year/month file is opened
+
+      sdjf%swap_sec = rsec_year + sec1jan000 - 1.   ! force read/update the after data in the following part of fld_read 
+      
+   END SUBROUTINE fld_init
+
+
+   SUBROUTINE fld_rec( sdjf )
       !!---------------------------------------------------------------------
       !!                    ***  ROUTINE fld_rec  ***
       !!
-      !! ** Purpose :   provide 
+      !! ** Purpose :   compute rec_a, rec_b and swap_sec
       !!
       !! ** Method  :   
       !!----------------------------------------------------------------------
-      REAL(wp), INTENT(in)   ::   pfreq       ! record frequency (>0 in hours, <0 in months)
-      LOGICAL , INTENT(in)   ::   ld_tint     ! time interpolation flag (T/F)
-      INTEGER , INTENT(in)   ::   kclim       ! climatology flag (=0/1)
-      INTEGER , INTENT(in)   ::   kshift      ! record shift 
-      REAL(wp), DIMENSION(2) ::   prec_info   ! 1: file record + kshift 
-      !                                       ! 2: associated time [sec] centered at half the record frequency
-      !!
-      INTEGER  ::   iendh, irec
-      REAL(wp) ::   zrec
+      TYPE(FLD), INTENT(inout) ::   sdjf        ! input field related variables
+      !!
+      INTEGER  ::   irec        ! record number
+      REAL(wp) ::   zrec        ! record number
+      REAL(wp) ::   ztmp        ! temporary variable
+      REAL(wp) ::   zfreq_sec   ! frequency mean (in seconds)
       !!----------------------------------------------------------------------
       !
-      IF( pfreq == -12. ) THEN      ! monthly data
-         !
-         iendh = 12                        ! 12 records per year
-         IF( ld_tint) THEN                 ! time interpolation, shift by 1/2 record
-            zrec  = REAL( nday     ) / REAL( nmonth_len(nmonth) ) + 0.5
+      IF( sdjf%freqh == -1. ) THEN      ! monthly mean
+         !
+         IF( sdjf%ln_tint ) THEN                 ! time interpolation, shift by 1/2 record
+            !
+            !                  INT( ztmp )
+            !                     /|\
+            !                    1 |    *----
+            !                    0 |----(              
+            !                      |----+----|--> time
+            !                      0   /|\   1   (nday/nmonth_len(nmonth))
+            !                           |   
+            !                           |   
+            !       forcing record :  nmonth 
+            !                            
+            ztmp  = REAL( nday, wp ) / REAL( nmonth_len(nmonth), wp ) + 0.5
          ELSE
-            zrec  = REAL( nday - 1 ) / REAL( nmonth_len(nmonth) )
-         ENDIF
-         irec = nmonth + kshift + INT( zrec )   ! record index (from 0 to 13)
-         zrec = rmonth_half(irec)               ! record time (second since 00h, Jan. 1st)
-         !
-      ELSE                          ! high frequency data (pfreq in hours)
-         !
-         iendh = INT( 365 * 24 / pfreq )   ! iendh records per year
-         IF( ld_tint ) THEN                ! time interpolation, shift by 1/2 record
-            zrec = rsec_year / ( pfreq * 3600. ) + 0.5 
+            ztmp  = 0.e0
+         ENDIF
+         irec = nmonth + INT( ztmp )
+
+         IF( sdjf%ln_tint ) THEN   ;   sdjf%swap_sec = rmonth_half(irec)   ! swap at the middle of the month
+         ELSE                      ;   sdjf%swap_sec = rmonth_end( irec)   ! swap at the end    of the month
+         ENDIF
+
+         sdjf%rec_a(:) = (/ REAL( irec, wp ), rmonth_half(irec) /)   ! define after  record number and time
+         irec = irec - 1                                             ! move back to previous record
+         sdjf%rec_b(:) = (/ REAL( irec, wp ), rmonth_half(irec) /)   ! define before record number and time
+         !
+      ELSE                          ! higher frequency mean (in hours)
+         !
+         zfreq_sec = sdjf%freqh * 3600.   ! frequency mean (in seconds)
+         ! number of second since the beginning of the file
+         IF( sdjf%cltype == 'monthly' ) THEN   ;   ztmp = rsec_month   ! since Jan 1 of the current year
+         ELSE                                  ;   ztmp = rsec_year    ! since the first day of the current month
+         ENDIF
+         IF( sdjf%ln_tint ) THEN                ! time interpolation, shift by 1/2 record
+            !
+            !                  INT( ztmp )
+            !                     /|\
+            !                    2 |        *-----(
+            !                    1 |  *-----(
+            !                    0 |--(              
+            !                      |--+--|--+--|--+--|--> time
+            !                      0 /|\ 1 /|\ 2 /|\ 3 (rsec_year/zfreq_sec) or (rsec_month/zfreq_sec)
+            !                         |     |     |
+            !                         |     |     |
+            !       forcing record :  1     2     3
+            !                   
+            ztmp= ztmp / zfreq_sec + 0.5
          ELSE                 
-            zrec = rsec_year / ( pfreq * 3600. )      
-         ENDIF      
-         irec = 1      + kshift + INT( zrec )                          ! record index (from 0 to iendh+1)
-         zrec = - 0.5 * 3600. * pfreq + 3600. * pfreq * REAL( irec )   ! record time (second since 00h, Jan. 1st)
+            !
+            !                  INT( ztmp )
+            !                     /|\
+            !                    2 |           *-----(
+            !                    1 |     *-----(
+            !                    0 |-----(              
+            !                      |--+--|--+--|--+--|--> time
+            !                      0 /|\ 1 /|\ 2 /|\ 3 (rsec_year/zfreq_sec) or (rsec_month/zfreq_sec)
+            !                         |     |     |
+            !                         |     |     |
+            !       forcing record :  1     2     3
+            !                            
+            ztmp= ztmp / zfreq_sec
+         ENDIF
+         zrec = 1. + REAL( INT( ztmp ), wp )
+
+         ! after record index and second since Jan. 1st 00h of nit000 year
+         sdjf%rec_a(:) = (/ zrec, zfreq_sec * ( zrec - 0.5 ) + sec1jan000 /)
+         IF( sdjf%cltype == 'monthly' )   &   ! add the number of second between Jan 1 and the end of previous month
+            sdjf%rec_a(2) = sdjf%rec_a(2) + rday * REAL(SUM(nmonth_len(1:nmonth -1)), wp)   ! ok if nmonth=1
+
+         ! before record index and second since Jan. 1st 00h of nit000 year
+         zrec = zrec - 1.                           ! move back to previous record
+         sdjf%rec_b(:) = (/ zrec, zfreq_sec * ( zrec - 0.5 ) + sec1jan000 /)
+         IF( sdjf%cltype == 'monthly' )   &   ! add the number of second between Jan 1 and the end of previous month
+            sdjf%rec_b(2) = sdjf%rec_b(2) + rday * REAL(SUM(nmonth_len(1:nmonth -1)), wp)   ! ok if nmonth=1
+
+         ! swapping time in second since Jan. 1st 00h of nit000 year
+         IF( sdjf%ln_tint ) THEN   ;   sdjf%swap_sec =  sdjf%rec_a(2)                     ! swap at the middle of the record
+         ELSE                      ;   sdjf%swap_sec =  sdjf%rec_a(2) + 0.5 * zfreq_sec   ! swap at the end    of the record
+         ENDIF       
          !
       ENDIF
       !
-      !                             ! adjuste the record index (climatology or interannual)
-      IF( kclim /= 1 )   THEN 
-         irec = irec + 1                                          ! interannual: additional first record
-      ELSE                     
-         IF( irec  ==         0 )   irec  =            iendh      ! climatology: record 0 is the last record (iendh)
-         IF( irec  >= iendh + 1 )   irec  = MOD( irec, iendh )    ! climatology: apply a modulo iendh
+   END SUBROUTINE fld_rec
+
+
+   SUBROUTINE fld_clopn( sdjf, kyear, kmonth, ldstop )
+      !!---------------------------------------------------------------------
+      !!                    ***  ROUTINE fld_clopn  ***
+      !!
+      !! ** Purpose :   update the file name and open the file
+      !!
+      !! ** Method  :   
+      !!----------------------------------------------------------------------
+      TYPE(FLD), INTENT(inout)           ::   sdjf     ! input field related variables
+      INTEGER  , INTENT(in   )           ::   kyear    ! year value
+      INTEGER  , INTENT(in   )           ::   kmonth   ! month value
+      LOGICAL  , INTENT(in   ), OPTIONAL ::   ldstop   ! stop if open to read a non-existing file (default = .TRUE.)
+
+      IF( sdjf%num /= 0 )   CALL iom_close( sdjf%num )   ! close file if already open
+      ! build the new filename if not climatological data
+      IF( .NOT. sdjf%ln_clim ) THEN   ;   WRITE(sdjf%clname, '(a,"_y",i4)' ) TRIM( sdjf%clrootname ), kyear    ! add year
+         IF( sdjf%cltype == 'monthly' )   WRITE(sdjf%clname, '(a,"m",i2)'  ) TRIM( sdjf%clname     ), kmonth   ! add month
       ENDIF
+      CALL iom_open( sdjf%clname, sdjf%num, ldstop = ldstop )
       !
-      prec_info(1) = REAL( irec, wp )
-      prec_info(2) = zrec
+   END SUBROUTINE fld_clopn
+
+
+   SUBROUTINE fld_fill( sdf, sdf_n, cdir, cdcaller, cdtitle, cdnam )
+      !!---------------------------------------------------------------------
+      !!                    ***  ROUTINE fld_fill  ***
+      !!
+      !! ** Purpose :   fill sdf with sdf_n and control print
+      !!
+      !! ** Method  :   
+      !!----------------------------------------------------------------------
+      TYPE(FLD)  , DIMENSION(:), INTENT(inout) ::   sdf        ! structure of input fields (file informations, fields read)
+      TYPE(FLD_N), DIMENSION(:), INTENT(in   ) ::   sdf_n      ! array of namelist information structures
+      CHARACTER(len=*)         , INTENT(in   ) ::   cdir       ! Root directory for location of flx files
+      CHARACTER(len=*)         , INTENT(in   ) ::   cdcaller   ! 
+      CHARACTER(len=*)         , INTENT(in   ) ::   cdtitle    ! 
+      CHARACTER(len=*)         , INTENT(in   ) ::   cdnam      ! 
       !
-   END FUNCTION fld_rec
-
-   !!======================================================================
+      INTEGER  ::   jf       ! dummy indices
+      !!---------------------------------------------------------------------
+
+      DO jf = 1, SIZE(sdf)
+         sdf(jf)%clrootname = TRIM( cdir )//TRIM( sdf_n(jf)%clname )
+         sdf(jf)%freqh      = sdf_n(jf)%freqh
+         sdf(jf)%clvar      = sdf_n(jf)%clvar
+         sdf(jf)%ln_tint    = sdf_n(jf)%ln_tint
+         sdf(jf)%ln_clim    = sdf_n(jf)%ln_clim
+         IF( sdf(jf)%freqh == -1. ) THEN   ;    sdf(jf)%cltype = 'yearly'
+         ELSE                               ;    sdf(jf)%cltype = sdf_n(jf)%cltype
+         ENDIF
+      END DO
+
+      IF(lwp) THEN      ! control print
+         WRITE(numout,*)
+         WRITE(numout,*) TRIM( cdcaller )//' : '//TRIM( cdtitle )
+         WRITE(numout,*) (/ ('~', jf = 1, LEN_TRIM( cdcaller ) ) /)
+         WRITE(numout,*) '          '//TRIM( cdnam )//' Namelist'
+         WRITE(numout,*) '          list of files and frequency (>0: in hours ; <0 in months)'
+         DO jf = 1, SIZE(sdf)
+            WRITE(numout,*) '               root filename: '  , TRIM( sdf(jf)%clrootname ),   &
+               &                          ' variable name: '  , TRIM( sdf(jf)%clvar      )
+            WRITE(numout,*) '               frequency: '      ,       sdf(jf)%freqh       ,   &
+               &                          ' time interp: '    ,       sdf(jf)%ln_tint     ,   &
+               &                          ' climatology: '    ,       sdf(jf)%ln_clim     ,   &
+               &                          ' data type: '      ,       sdf(jf)%cltype
+         END DO
+      ENDIF
+      
+   END SUBROUTINE fld_fill
+
+
 END MODULE fldread
