Index: trunk/NEMOGCM/NEMO/OPA_SRC/SBC/fldread.F90
===================================================================
--- trunk/NEMOGCM/NEMO/OPA_SRC/SBC/fldread.F90	(revision 3841)
+++ trunk/NEMOGCM/NEMO/OPA_SRC/SBC/fldread.F90	(revision 3851)
@@ -27,4 +27,5 @@
  
    PUBLIC   fld_map    ! routine called by tides_init
+   PUBLIC   fld_read, fld_fill   ! called by sbc... modules
 
    TYPE, PUBLIC ::   FLD_N      !: Namelist field informations
@@ -57,5 +58,6 @@
       !                                                 ! into the WGTLIST structure
       CHARACTER(len = 34)             ::   vcomp        ! symbolic name for a vector component that needs rotation
-      LOGICAL                         ::   rotn         ! flag to indicate whether field has been rotated
+      LOGICAL, DIMENSION(2)           ::   rotn         ! flag to indicate whether before/after field has been rotated
+      INTEGER                         ::   nreclast     ! last record to be read in the current file
    END TYPE FLD
 
@@ -96,6 +98,4 @@
 !$AGRIF_END_DO_NOT_TREAT
 
-   PUBLIC   fld_read, fld_fill   ! called by sbc... modules
-
    !!----------------------------------------------------------------------
    !! NEMO/OPA 3.3 , NEMO Consortium (2010)
@@ -105,5 +105,5 @@
 CONTAINS
 
-   SUBROUTINE fld_read( kt, kn_fsbc, sd, map, jit, time_offset )
+   SUBROUTINE fld_read( kt, kn_fsbc, sd, map, kit, kt_offset )
       !!---------------------------------------------------------------------
       !!                    ***  ROUTINE fld_read  ***
@@ -120,17 +120,17 @@
       INTEGER  , INTENT(in   )               ::   kn_fsbc   ! sbc computation period (in time step) 
       TYPE(FLD), INTENT(inout), DIMENSION(:) ::   sd        ! input field related variables
-      TYPE(MAP_POINTER),INTENT(in), OPTIONAL, DIMENSION(:) ::   map   ! global-to-local mapping index
-      INTEGER  , INTENT(in   ), OPTIONAL     ::   jit       ! subcycle timestep for timesplitting option
-      INTEGER  , INTENT(in   ), OPTIONAL     ::   time_offset ! provide fields at time other than "now"
-                                                              ! time_offset = -1 => fields at "before" time level
-                                                              ! time_offset = +1 => fields at "after" time levels
-                                                              ! etc.
-      !!
+      TYPE(MAP_POINTER),INTENT(in), OPTIONAL, DIMENSION(:) ::   map   ! global-to-local mapping indices
+      INTEGER  , INTENT(in   ), OPTIONAL     ::   kit       ! subcycle timestep for timesplitting option
+      INTEGER  , INTENT(in   ), OPTIONAL     ::   kt_offset ! provide fields at time other than "now"
+                                                            !   kt_offset = -1 => fields at "before" time level
+                                                            !   kt_offset = +1 => fields at "after"  time level
+                                                            !   etc.
+      !!
+      INTEGER  ::   itmp       ! temporary variable
       INTEGER  ::   imf        ! size of the structure sd
       INTEGER  ::   jf         ! dummy indices
-      INTEGER  ::   ireclast   ! last record to be read in the current year file
       INTEGER  ::   isecend    ! number of second since Jan. 1st 00h of nit000 year at nitend
       INTEGER  ::   isecsbc    ! number of seconds between Jan. 1st 00h of nit000 year and the middle of sbc time step
-      INTEGER  ::   itime_add  ! local time offset variable
+      INTEGER  ::   it_offset  ! local time offset variable
       LOGICAL  ::   llnxtyr    ! open next year  file?
       LOGICAL  ::   llnxtmth   ! open next month file?
@@ -140,36 +140,28 @@
       REAL(wp) ::   ztintb     ! ratio applied to before records when doing time interpolation
       CHARACTER(LEN=1000) ::   clfmt   ! write format
-      !!---------------------------------------------------------------------
-      ll_firstcall = .false.
-      IF( PRESENT(jit) ) THEN
-         IF(kt == nit000 .and. jit == 1) ll_firstcall = .true.
-      ELSE
-         IF(kt == nit000) ll_firstcall = .true.
-      ENDIF
-
-      itime_add = 0
-      IF( PRESENT(time_offset) ) itime_add = time_offset
-         
+      TYPE(MAP_POINTER) ::   imap   ! global-to-local mapping indices
+      !!---------------------------------------------------------------------
+      ll_firstcall = kt == nit000
+      IF( PRESENT(kit) )   ll_firstcall = ll_firstcall .and. kit == 1
+
+      it_offset = 0
+      IF( PRESENT(kt_offset) )   it_offset = kt_offset
+
+      imap%ptr => NULL()
+
       ! Note that shifting time to be centrered in the middle of sbc time step impacts only nsec_* variables of the calendar 
-      IF( present(jit) ) THEN 
-         ! ignore kn_fsbc in this case
-         isecsbc = nsec_year + nsec1jan000 + (jit+itime_add)*rdt/REAL(nn_baro,wp) 
-      ELSE
-         isecsbc = nsec_year + nsec1jan000 + NINT(0.5 * REAL(kn_fsbc - 1,wp) * rdttra(1)) + itime_add * rdttra(1)  ! middle of sbc time step
+      IF( present(kit) ) THEN   ! ignore kn_fsbc in this case
+         isecsbc = nsec_year + nsec1jan000 + (kit+it_offset)*NINT( rdt/REAL(nn_baro,wp) )
+      ELSE                      ! middle of sbc time step
+         isecsbc = nsec_year + nsec1jan000 + NINT(0.5 * REAL(kn_fsbc - 1,wp) * rdttra(1)) + it_offset * NINT(rdttra(1))
       ENDIF
       imf = SIZE( sd )
       !
       IF( ll_firstcall ) THEN                      ! initialization
-         IF( PRESENT(map) ) THEN
-            DO jf = 1, imf 
-               CALL fld_init( kn_fsbc, sd(jf), map(jf)%ptr )  ! read each before field (put them in after as they will be swapped)
-            END DO
-         ELSE
-            DO jf = 1, imf 
-               CALL fld_init( kn_fsbc, sd(jf) )       ! read each before field (put them in after as they will be swapped)
-            END DO
-         ENDIF
+         DO jf = 1, imf 
+            IF( PRESENT(map) ) imap = map(jf)
+            CALL fld_init( kn_fsbc, sd(jf), imap )  ! read each before field (put them in after as they will be swapped)
+         END DO
          IF( lwp ) CALL wgt_print()                ! control print
-         CALL fld_rot( kt, sd )                    ! rotate vector fiels if needed
       ENDIF
       !                                            ! ====================================== !
@@ -179,45 +171,60 @@
          DO jf = 1, imf                            ! ---   loop over field   --- !
             
-            IF( isecsbc > sd(jf)%nrec_a(2) .OR. ll_firstcall ) THEN  ! read/update the after data?
-
-               IF( sd(jf)%ln_tint ) THEN                             ! swap before record field and informations
-                  sd(jf)%nrec_b(:) = sd(jf)%nrec_a(:)
-!CDIR COLLAPSE
-                  sd(jf)%fdta(:,:,:,1) = sd(jf)%fdta(:,:,:,2)
+            IF( isecsbc > sd(jf)%nrec_a(2) .OR. ll_firstcall ) THEN    ! read/update the after data?
+
+               IF( PRESENT(map) )   imap = map(jf)   ! temporary definition of map
+
+               sd(jf)%nrec_b(:) = sd(jf)%nrec_a(:)                                  ! swap before record informations
+               sd(jf)%rotn(1) = sd(jf)%rotn(2)                                      ! swap before rotate informations
+               IF( sd(jf)%ln_tint )   sd(jf)%fdta(:,:,:,1) = sd(jf)%fdta(:,:,:,2)   ! swap before record field
+
+               CALL fld_rec( kn_fsbc, sd(jf), kt_offset = it_offset, kit = kit )    ! update after record informations
+
+               ! if kn_fsbc*rdttra is larger than nfreqh (which is kind of odd),
+               ! it is possible that the before value is no more the good one... we have to re-read it
+               ! if before is not the last record of the file currently opened and after is the first record to be read
+               ! in a new file which means after = 1 (the file to be opened corresponds to the current time)
+               ! or after = nreclast + 1 (the file to be opened corresponds to a future time step)
+               IF( .NOT. ll_firstcall .AND. sd(jf)%ln_tint .AND. sd(jf)%nrec_b(1) /= sd(jf)%nreclast &
+                  &                   .AND. MOD( sd(jf)%nrec_a(1), sd(jf)%nreclast ) == 1 ) THEN
+                  itmp = sd(jf)%nrec_a(1)                       ! temporary storage
+                  sd(jf)%nrec_a(1) = sd(jf)%nreclast            ! read the last record of the file currently opened
+                  CALL fld_get( sd(jf), imap )                  ! read after data
+                  sd(jf)%fdta(:,:,:,1) = sd(jf)%fdta(:,:,:,2)   ! re-swap before record field
+                  sd(jf)%nrec_b(1) = sd(jf)%nrec_a(1)           ! update before record informations
+                  sd(jf)%nrec_b(2) = sd(jf)%nrec_a(2) - sd(jf)%nfreqh * 3600  ! assume freq to be in hours in this case
+                  sd(jf)%rotn(1)   = sd(jf)%rotn(2)             ! update before rotate informations
+                  sd(jf)%nrec_a(1) = itmp                       ! move back to after record 
                ENDIF
 
-               IF( PRESENT(jit) ) THEN
-                  CALL fld_rec( kn_fsbc, sd(jf), time_offset=itime_add, jit=jit )              ! update record informations
-               ELSE
-                  CALL fld_rec( kn_fsbc, sd(jf), time_offset=itime_add )                       ! update record informations
-               ENDIF
-
-               ! do we have to change the year/month/week/day of the forcing field?? 
+               CALL fld_clopn( sd(jf) )   ! Do we need to open a new year/month/week/day file?
+               
                IF( sd(jf)%ln_tint ) THEN
+                  
+                  ! if kn_fsbc*rdttra is larger than nfreqh (which is kind of odd),
+                  ! it is possible that the before value is no more the good one... we have to re-read it
+                  ! if before record is not just just before the after record...
+                  IF( .NOT. ll_firstcall .AND. MOD( sd(jf)%nrec_a(1), sd(jf)%nreclast ) /= 1 &
+                     &                   .AND. sd(jf)%nrec_b(1) /= sd(jf)%nrec_a(1) - 1 ) THEN   
+                     sd(jf)%nrec_a(1) = sd(jf)%nrec_a(1) - 1       ! move back to before record
+                     CALL fld_get( sd(jf), imap )                  ! read after data
+                     sd(jf)%fdta(:,:,:,1) = sd(jf)%fdta(:,:,:,2)   ! re-swap before record field
+                     sd(jf)%nrec_b(1) = sd(jf)%nrec_a(1)           ! update before record informations
+                     sd(jf)%nrec_b(2) = sd(jf)%nrec_a(2) - sd(jf)%nfreqh * 3600  ! assume freq to be in hours in this case
+                     sd(jf)%rotn(1)   = sd(jf)%rotn(2)             ! update before rotate informations
+                     sd(jf)%nrec_a(1) = sd(jf)%nrec_a(1) + 1       ! move back to after record
+                  ENDIF
+
+                  ! do we have to change the year/month/week/day of the forcing field?? 
                   ! if we do time interpolation we will need to open next year/month/week/day file before the end of the current
                   ! one. If so, we are still before the end of the year/month/week/day when calling fld_rec so sd(jf)%nrec_a(1)
                   ! will be larger than the record number that should be read for current year/month/week/day
-
-                  ! last record to be read in the current file
-                  IF    ( sd(jf)%nfreqh == -12 ) THEN                 ;   ireclast = 1    !  yearly mean
-                  ELSEIF( sd(jf)%nfreqh ==  -1 ) THEN                                     ! monthly mean
-                     IF(     sd(jf)%cltype      == 'monthly' ) THEN   ;   ireclast = 1
-                     ELSE                                             ;   ireclast = 12
-                     ENDIF
-                  ELSE                                                                    ! higher frequency mean (in hours)
-                     IF(     sd(jf)%cltype      == 'monthly' ) THEN   ;   ireclast = 24 * nmonth_len(nmonth) / sd(jf)%nfreqh 
-                     ELSEIF( sd(jf)%cltype(1:4) == 'week'    ) THEN   ;   ireclast = 24 * 7                  / sd(jf)%nfreqh
-                     ELSEIF( sd(jf)%cltype      == 'daily'   ) THEN   ;   ireclast = 24                      / sd(jf)%nfreqh
-                     ELSE                                             ;   ireclast = 24 * nyear_len(     1 ) / sd(jf)%nfreqh 
-                     ENDIF
-                  ENDIF
-
                   ! do we need next file data?
-                  IF( sd(jf)%nrec_a(1) > ireclast ) THEN
-
-                     sd(jf)%nrec_a(1) = 1              ! force to read the first record of the next file
-
-                     IF( .NOT. sd(jf)%ln_clim ) THEN   ! close the current file and open a new one.
-
+                  IF( sd(jf)%nrec_a(1) > sd(jf)%nreclast ) THEN
+                     
+                     sd(jf)%nrec_a(1) = sd(jf)%nrec_a(1) - sd(jf)%nreclast   ! 
+                     
+                     IF( .NOT. ( sd(jf)%ln_clim .AND. sd(jf)%cltype == 'yearly' ) ) THEN   ! close/open the current/new file
+                        
                         llnxtmth = sd(jf)%cltype == 'monthly' .OR. nday == nmonth_len(nmonth)      ! open next month file?
                         llnxtyr  = sd(jf)%cltype == 'yearly'  .OR. (nmonth == 12 .AND. llnxtmth)   ! open next year  file?
@@ -228,5 +235,5 @@
                         isecend = nsec_year + nsec1jan000 + (nitend - kt) * NINT(rdttra(1))   ! second at the end of the run 
                         llstop = isecend > sd(jf)%nrec_a(2)                                   ! read more than 1 record of next year
-
+                        ! we suppose that the date of next file is next day (should be ok even for weekly files...)
                         CALL fld_clopn( sd(jf), nyear  + COUNT((/llnxtyr /))                                           ,         &
                            &                    nmonth + COUNT((/llnxtmth/)) - 12                 * COUNT((/llnxtyr /)),         &
@@ -236,30 +243,20 @@
                            CALL ctl_warn('next year/month/week/day file: '//TRIM(sd(jf)%clname)//     &
                               &     ' not present -> back to current year/month/day')
-                           CALL fld_clopn( sd(jf), nyear, nmonth, nday )       ! back to the current year/month/day
-                           sd(jf)%nrec_a(1) = ireclast     ! force to read the last record to be read in the current year file
+                           CALL fld_clopn( sd(jf) )       ! back to the current year/month/day
+                           sd(jf)%nrec_a(1) = sd(jf)%nreclast     ! force to read the last record in the current year file
                         ENDIF
-
+                        
                      ENDIF
-                  ENDIF
-
-               ELSE
-                  ! if we are not doing time interpolation, we must change the year/month/week/day of the file just after
-                  ! switching to the NEW year/month/week/day. If it is the case, we are at the beginning of the
-                  ! year/month/week/day when calling fld_rec so sd(jf)%nrec_a(1) = 1
-                  IF( sd(jf)%nrec_a(1) == 1 .AND. .NOT. ( sd(jf)%ln_clim .AND. sd(jf)%cltype == 'yearly' ) )   &
-                     &   CALL fld_clopn( sd(jf), nyear, nmonth, nday )
-               ENDIF
+                  ENDIF   ! open need next file?
+                  
+               ENDIF   ! temporal interpolation?
 
                ! read after data
-               IF( PRESENT(map) ) THEN
-                  CALL fld_get( sd(jf), map(jf)%ptr )
-               ELSE
-                  CALL fld_get( sd(jf) )
-               ENDIF
-
-            ENDIF
+               CALL fld_get( sd(jf), imap )
+
+            ENDIF   ! read new data?
          END DO                                    ! --- end loop over field --- !
 
-         CALL fld_rot( kt, sd )                    ! rotate vector fiels if needed
+         CALL fld_rot( kt, sd )                    ! rotate vector before/now/after fields if needed
 
          DO jf = 1, imf                            ! ---   loop over field   --- !
@@ -271,5 +268,5 @@
                   WRITE(numout, clfmt)  TRIM( sd(jf)%clvar ), kt, REAL(isecsbc,wp)/rday, nyear, nmonth, nday,   &            
                      & sd(jf)%nrec_b(1), sd(jf)%nrec_a(1), REAL(sd(jf)%nrec_b(2),wp)/rday, REAL(sd(jf)%nrec_a(2),wp)/rday
-                  WRITE(numout, *) 'itime_add is : ',itime_add
+                  WRITE(numout, *) 'it_offset is : ',it_offset
                ENDIF
                ! temporal interpolation weights
@@ -307,5 +304,5 @@
       INTEGER  , INTENT(in   ) ::   kn_fsbc   ! sbc computation period (in time step) 
       TYPE(FLD), INTENT(inout) ::   sdjf      ! input field related variables
-      INTEGER  , INTENT(in), OPTIONAL, DIMENSION(:) :: map ! global-to-local mapping indices
+      TYPE(MAP_POINTER),INTENT(in) ::   map   ! global-to-local mapping indices
       !!
       LOGICAL :: llprevyr              ! are we reading previous year  file?
@@ -320,8 +317,4 @@
       CHARACTER(LEN=1000) ::   clfmt   ! write format
       !!---------------------------------------------------------------------
-      
-      ! 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.
@@ -330,9 +323,4 @@
       isec_week  = 0
             
-      IF( sdjf%cltype(1:4) == 'week' .AND. nn_leapy == 0 )   &
-         &   CALL ctl_stop('fld_clopn: weekly file ('//TRIM(sdjf%clrootname)//') needs nn_leapy = 1')
-      IF( sdjf%cltype(1:4) == 'week' .AND. sdjf%ln_clim  )   &
-         &   CALL ctl_stop('fld_clopn: weekly file ('//TRIM(sdjf%clrootname)//') needs ln_clim = .FALSE.')
-
       ! define record informations
       CALL fld_rec( kn_fsbc, sdjf, ldbefore = .TRUE. )  ! return before values in sdjf%nrec_a (as we will swap it later)
@@ -348,5 +336,5 @@
                   llprevyr  = .NOT. sdjf%ln_clim                                           ! use previous year  file?
                ELSE
-                  CALL ctl_stop( "fld_init: yearly mean file must be in a yearly type of file: "//TRIM(sdjf%clname) )
+                  CALL ctl_stop( "fld_init: yearly mean file must be in a yearly type of file: "//TRIM(sdjf%clrootname) )
                ENDIF
             ELSEIF( sdjf%nfreqh ==  -1 ) THEN   ! monthly mean
@@ -379,4 +367,5 @@
             ENDIF
          ENDIF
+         !
          IF ( sdjf%cltype(1:4) == 'week' ) THEN
             isec_week = isec_week + ksec_week( sdjf%cltype(6:8) )   ! second since the beginning of the week
@@ -394,13 +383,13 @@
          ! if previous year/month/day file does not exist, we switch to the current year/month/day
          IF( llprev .AND. sdjf%num <= 0 ) THEN
-            CALL ctl_warn( 'previous year/month/week/day file: '//TRIM(sdjf%clname)//   &
+            CALL ctl_warn( 'previous year/month/week/day file: '//TRIM(sdjf%clrootname)//   &
                &           ' not present -> back to current year/month/week/day' )
             ! we force to read the first record of the current year/month/day instead of last record of previous year/month/day
             llprev = .FALSE.
             sdjf%nrec_a(1) = 1
-            CALL fld_clopn( sdjf, nyear, nmonth, nday )
+            CALL fld_clopn( sdjf )
          ENDIF
          
-         IF( llprev ) THEN   ! check if the last record sdjf%nrec_n(1) exists in the file
+         IF( llprev ) THEN   ! check if the record sdjf%nrec_a(1) exists in the file
             idvar = iom_varid( sdjf%num, sdjf%clvar )                                        ! id of the variable sdjf%clvar
             IF( idvar <= 0 )   RETURN
@@ -409,42 +398,16 @@
          ENDIF
 
-         ! read before data 
-         IF( PRESENT(map) ) THEN
-            CALL fld_get( sdjf, map )  ! read before values in after arrays(as we will swap it later)
-         ELSE
-            CALL fld_get( sdjf )  ! read before values in after arrays(as we will swap it later)
-         ENDIF
+         ! read before data in after arrays(as we will swap it later)
+         CALL fld_get( sdjf, map )
 
          clfmt = "('fld_init : time-interpolation for ', a, ' read previous record = ', i4, ' at time = ', f7.2, ' days')"
          IF(lwp) WRITE(numout, clfmt) TRIM(sdjf%clvar), sdjf%nrec_a(1), REAL(sdjf%nrec_a(2),wp)/rday
 
-         IF( llprev )   CALL iom_close( sdjf%num )          ! force to close previous year file (-> redefine sdjf%num to 0)
-
-      ENDIF
-
-      ! make sure current year/month/day file is opened
-      IF( sdjf%num <= 0 ) THEN
-         !
-         IF ( sdjf%cltype(1:4) == 'week' ) THEN
-            isec_week  = ksec_week( sdjf%cltype(6:8) )      ! second since the beginning of the week
-            llprevmth  = isec_week > nsec_month             ! longer time since beginning of the week than the month
-            llprevyr   = llprevmth .AND. nmonth == 1
-         ELSE
-            isec_week  = 0
-            llprevmth  = .FALSE.
-            llprevyr   = .FALSE.
-         ENDIF
-         !
-         iyear  = nyear  - COUNT((/llprevyr /))
-         imonth = nmonth - COUNT((/llprevmth/)) + 12 * COUNT((/llprevyr /))
-         iday   = nday   + nmonth_len(nmonth-1) * COUNT((/llprevmth/)) - isec_week / NINT(rday)
-         !
-         CALL fld_clopn( sdjf, iyear, imonth, iday )
-      ENDIF 
+      ENDIF
       !
    END SUBROUTINE fld_init
 
 
-   SUBROUTINE fld_rec( kn_fsbc, sdjf, ldbefore, jit, time_offset )
+   SUBROUTINE fld_rec( kn_fsbc, sdjf, ldbefore, kit, kt_offset )
       !!---------------------------------------------------------------------
       !!                    ***  ROUTINE fld_rec  ***
@@ -460,8 +423,8 @@
       TYPE(FLD), INTENT(inout)           ::   sdjf      ! input field related variables
       LOGICAL  , INTENT(in   ), OPTIONAL ::   ldbefore  ! sent back before record values (default = .FALSE.)
-      INTEGER  , INTENT(in   ), OPTIONAL ::   jit       ! index of barotropic subcycle
+      INTEGER  , INTENT(in   ), OPTIONAL ::   kit       ! index of barotropic subcycle
                                                         ! used only if sdjf%ln_tint = .TRUE.
-      INTEGER  , INTENT(in   ), OPTIONAL ::   time_offset  ! Offset of required time level compared to "now"
-                                                           ! time level in units of time steps.
+      INTEGER  , INTENT(in   ), OPTIONAL ::   kt_offset ! Offset of required time level compared to "now"
+                                                        !   time level in units of time steps.
       !!
       LOGICAL  ::   llbefore    ! local definition of ldbefore
@@ -470,5 +433,5 @@
       INTEGER  ::   ifreq_sec   ! frequency mean (in seconds)
       INTEGER  ::   isec_week   ! number of seconds since the start of the weekly file
-      INTEGER  ::   itime_add   ! local time offset variable
+      INTEGER  ::   it_offset   ! local time offset variable
       REAL(wp) ::   ztmp        ! temporary variable
       !!----------------------------------------------------------------------
@@ -480,6 +443,9 @@
       ENDIF
       !
-      itime_add = 0
-      IF( PRESENT(time_offset) ) itime_add = time_offset
+      it_offset = 0
+      IF( PRESENT(kt_offset) )   it_offset = kt_offset
+      IF( PRESENT(kit) ) THEN   ;   it_offset = ( kit + it_offset ) * NINT( rdt/REAL(nn_baro,wp) )
+      ELSE                      ;   it_offset =         it_offset   * NINT(       rdttra(1)      )
+      ENDIF
       !
       !                                      ! =========== !
@@ -499,10 +465,5 @@
             !       forcing record :    1 
             !                            
-            ztmp = REAL( nday, wp ) / REAL( nyear_len(1), wp ) + 0.5
-            IF( PRESENT(jit) ) THEN 
-               ztmp = ztmp + (jit+itime_add)*rdt/REAL(nn_baro,wp)
-            ELSE
-               ztmp = ztmp + itime_add*rdttra(1)
-            ENDIF
+            ztmp = REAL( nday, wp ) / REAL( nyear_len(1), wp ) + 0.5 + REAL( it_offset, wp )
             sdjf%nrec_a(1) = 1 + INT( ztmp ) - COUNT((/llbefore/))
             ! swap at the middle of the year
@@ -532,10 +493,5 @@
             !       forcing record :  nmonth 
             !                            
-            ztmp = REAL( nday, wp ) / REAL( nmonth_len(nmonth), wp ) + 0.5
-            IF( PRESENT(jit) ) THEN 
-               ztmp = ztmp + (jit+itime_add)*rdt/REAL(nn_baro,wp)
-            ELSE
-               ztmp = ztmp + itime_add*rdttra(1)
-            ENDIF
+            ztmp = REAL( nday, wp ) / REAL( nmonth_len(nmonth), wp ) + 0.5 + REAL( it_offset, wp )
             imth = nmonth + INT( ztmp ) - COUNT((/llbefore/))
             IF( sdjf%cltype == 'monthly' ) THEN   ;   sdjf%nrec_a(1) = 1 + INT( ztmp ) - COUNT((/llbefore/))
@@ -563,14 +519,9 @@
          ELSE                                           ;   ztmp = REAL(nsec_year ,wp)  ! since 00h on Jan 1 of the current year
          ENDIF
-         ztmp = ztmp + 0.5 * REAL(kn_fsbc - 1, wp) * rdttra(1)   ! shift time to be centrered in the middle of sbc time step
-         ztmp = ztmp + 0.01 * rdttra(1)                          ! add 0.01 time step to avoid truncation error 
-         IF( PRESENT(jit) ) THEN 
-            ztmp = ztmp + (jit+itime_add)*rdt/REAL(nn_baro,wp)
-         ELSE
-            ztmp = ztmp + itime_add*rdttra(1)
-         ENDIF
+         ztmp = ztmp + 0.5 * REAL(kn_fsbc - 1, wp) * rdttra(1) + REAL( it_offset, wp )  ! centrered in the middle of sbc time step
+         ztmp = ztmp + 0.01 * rdttra(1)                                                 ! avoid truncation error 
          IF( sdjf%ln_tint ) THEN                ! time interpolation, shift by 1/2 record
             !
-            !                  INT( ztmp )
+            !          INT( ztmp/ifreq_sec + 0.5 )
             !                     /|\
             !                    2 |        *-----(
@@ -578,5 +529,5 @@
             !                    0 |--(              
             !                      |--+--|--+--|--+--|--> time
-            !                      0 /|\ 1 /|\ 2 /|\ 3 (nsec_year/ifreq_sec) or (nsec_month/ifreq_sec)
+            !                      0 /|\ 1 /|\ 2 /|\ 3    (ztmp/ifreq_sec)
             !                         |     |     |
             !                         |     |     |
@@ -586,5 +537,5 @@
          ELSE                                   ! no time interpolation
             !
-            !                  INT( ztmp )
+            !           INT( ztmp/ifreq_sec )
             !                     /|\
             !                    2 |           *-----(
@@ -592,5 +543,5 @@
             !                    0 |-----(              
             !                      |--+--|--+--|--+--|--> time
-            !                      0 /|\ 1 /|\ 2 /|\ 3 (nsec_year/ifreq_sec) or (nsec_month/ifreq_sec)
+            !                      0 /|\ 1 /|\ 2 /|\ 3    (ztmp/ifreq_sec)
             !                         |     |     |
             !                         |     |     |
@@ -599,5 +550,5 @@
             ztmp= ztmp / REAL(ifreq_sec, wp)
          ENDIF
-         sdjf%nrec_a(1) = 1 + INT( ztmp ) - COUNT((/llbefore/))   ! record nomber to be read
+         sdjf%nrec_a(1) = 1 + INT( ztmp ) - COUNT((/llbefore/))   ! record number to be read
 
          iendrec = ifreq_sec * sdjf%nrec_a(1) + nsec1jan000       ! end of this record (in second)
@@ -625,5 +576,5 @@
       !!----------------------------------------------------------------------
       TYPE(FLD), INTENT(inout) ::   sdjf   ! input field related variables
-      INTEGER  , INTENT(in), OPTIONAL, DIMENSION(:) :: map ! global-to-local mapping indices
+      TYPE(MAP_POINTER),INTENT(in) ::   map   ! global-to-local mapping indices
       !!
       INTEGER                  ::   ipk    ! number of vertical levels of sdjf%fdta ( 2D: ipk=1 ; 3D: ipk=jpk )
@@ -631,10 +582,10 @@
       INTEGER                  ::   ipdom  ! index of the domain
       !!---------------------------------------------------------------------
-      !      
+      !
       ipk = SIZE( sdjf%fnow, 3 )
       !
-      IF( PRESENT(map) ) THEN
-         IF( sdjf%ln_tint ) THEN   ;   CALL fld_map( sdjf%num, sdjf%clvar, sdjf%fdta(:,:,:,2), sdjf%nrec_a(1), map )
-         ELSE                      ;   CALL fld_map( sdjf%num, sdjf%clvar, sdjf%fnow(:,:,:  ), sdjf%nrec_a(1), map )
+      IF( ASSOCIATED(map%ptr) ) THEN
+         IF( sdjf%ln_tint ) THEN   ;   CALL fld_map( sdjf%num, sdjf%clvar, sdjf%fdta(:,:,:,2), sdjf%nrec_a(1), map%ptr )
+         ELSE                      ;   CALL fld_map( sdjf%num, sdjf%clvar, sdjf%fnow(:,:,:  ), sdjf%nrec_a(1), map%ptr )
          ENDIF
       ELSE IF( LEN(TRIM(sdjf%wgtname)) > 0 ) THEN
@@ -659,5 +610,5 @@
       ENDIF
       !
-      sdjf%rotn = .false.   ! vector not yet rotated
+      sdjf%rotn(2) = .false.   ! vector not yet rotated
 
    END SUBROUTINE fld_get
@@ -665,5 +616,5 @@
    SUBROUTINE fld_map( num, clvar, dta, nrec, map )
       !!---------------------------------------------------------------------
-      !!                    ***  ROUTINE fld_get  ***
+      !!                    ***  ROUTINE fld_map  ***
       !!
       !! ** Purpose :   read global data from file and map onto local data
@@ -673,5 +624,4 @@
       USE bdy_oce, ONLY:  dta_global, dta_global2         ! workspace to read in global data arrays
 #endif 
-
       INTEGER                   , INTENT(in ) ::   num     ! stream number
       CHARACTER(LEN=*)          , INTENT(in ) ::   clvar   ! variable name
@@ -706,14 +656,10 @@
 #endif
 
-
       IF(lwp) WRITE(numout,*) 'Dim size for ',TRIM(clvar),' is ', ilendta
       IF(lwp) WRITE(numout,*) 'Number of levels for ',TRIM(clvar),' is ', ipk
 
-
       SELECT CASE( ipk )
-      CASE(1)   
-         CALL iom_get ( num, jpdom_unknown, clvar, dta_read(1:ilendta,1:ipj,1    ), nrec )
-      CASE DEFAULT
-         CALL iom_get ( num, jpdom_unknown, clvar, dta_read(1:ilendta,1:ipj,1:ipk), nrec )
+      CASE(1)        ;   CALL iom_get ( num, jpdom_unknown, clvar, dta_read(1:ilendta,1:ipj,1    ), nrec )
+      CASE DEFAULT   ;   CALL iom_get ( num, jpdom_unknown, clvar, dta_read(1:ilendta,1:ipj,1:ipk), nrec )
       END SELECT
       !
@@ -746,5 +692,5 @@
       TYPE(FLD), INTENT(inout), DIMENSION(:) ::   sd        ! input field related variables
       !!
-      INTEGER                           ::   ju, jv, jk   ! loop indices
+      INTEGER                           ::   ju,jv,jk,jn  ! loop indices
       INTEGER                           ::   imf          ! size of the structure sd
       INTEGER                           ::   ill          ! character length
@@ -761,30 +707,32 @@
       DO ju = 1, imf
          ill = LEN_TRIM( sd(ju)%vcomp )
-         IF( ill > 0 .AND. .NOT. sd(ju)%rotn ) THEN   ! find vector rotations required             
-             IF( sd(ju)%vcomp(1:1) == 'U' ) THEN      ! east-west component has symbolic name starting with 'U'
-                ! look for the north-south component which has same symbolic name but with 'U' replaced with 'V'
-                clcomp = 'V' // sd(ju)%vcomp(2:ill)   ! works even if ill == 1
-                iv = -1
-                DO jv = 1, imf
-                  IF( TRIM(sd(jv)%vcomp) == TRIM(clcomp) )   iv = jv
-                END DO
-                IF( iv > 0 ) THEN   ! fields ju and iv are two components which need to be rotated together
-                   DO jk = 1, SIZE( sd(ju)%fnow, 3 )
-                      IF( sd(ju)%ln_tint )THEN
-                         CALL rot_rep( sd(ju)%fdta(:,:,jk,2), sd(iv)%fdta(:,:,jk,2), 'T', 'en->i', utmp(:,:) )
-                         CALL rot_rep( sd(ju)%fdta(:,:,jk,2), sd(iv)%fdta(:,:,jk,2), 'T', 'en->j', vtmp(:,:) )
-                         sd(ju)%fdta(:,:,jk,2) = utmp(:,:)   ;   sd(iv)%fdta(:,:,jk,2) = vtmp(:,:)
-                      ELSE 
-                         CALL rot_rep( sd(ju)%fnow(:,:,jk  ), sd(iv)%fnow(:,:,jk  ), 'T', 'en->i', utmp(:,:) )
-                         CALL rot_rep( sd(ju)%fnow(:,:,jk  ), sd(iv)%fnow(:,:,jk  ), 'T', 'en->j', vtmp(:,:) )
-                         sd(ju)%fnow(:,:,jk  ) = utmp(:,:)   ;   sd(iv)%fnow(:,:,jk  ) = vtmp(:,:)
-                      ENDIF
-                   END DO
-                   sd(ju)%rotn = .TRUE.               ! vector was rotated 
-                   IF( lwp .AND. kt == nit000 )   WRITE(numout,*)   &
-                      &   'fld_read: vector pair ('//TRIM(sd(ju)%clvar)//', '//TRIM(sd(iv)%clvar)//') rotated on to model grid'
-                ENDIF
-             ENDIF
-          ENDIF
+         DO jn = 2-COUNT((/sd(ju)%ln_tint/)), 2
+            IF( ill > 0 .AND. .NOT. sd(ju)%rotn(jn) ) THEN   ! find vector rotations required             
+               IF( sd(ju)%vcomp(1:1) == 'U' ) THEN      ! east-west component has symbolic name starting with 'U'
+                  ! look for the north-south component which has same symbolic name but with 'U' replaced with 'V'
+                  clcomp = 'V' // sd(ju)%vcomp(2:ill)   ! works even if ill == 1
+                  iv = -1
+                  DO jv = 1, imf
+                     IF( TRIM(sd(jv)%vcomp) == TRIM(clcomp) )   iv = jv
+                  END DO
+                  IF( iv > 0 ) THEN   ! fields ju and iv are two components which need to be rotated together
+                     DO jk = 1, SIZE( sd(ju)%fnow, 3 )
+                        IF( sd(ju)%ln_tint )THEN
+                           CALL rot_rep( sd(ju)%fdta(:,:,jk,jn), sd(iv)%fdta(:,:,jk,jn), 'T', 'en->i', utmp(:,:) )
+                           CALL rot_rep( sd(ju)%fdta(:,:,jk,jn), sd(iv)%fdta(:,:,jk,jn), 'T', 'en->j', vtmp(:,:) )
+                           sd(ju)%fdta(:,:,jk,jn) = utmp(:,:)   ;   sd(iv)%fdta(:,:,jk,jn) = vtmp(:,:)
+                        ELSE 
+                           CALL rot_rep( sd(ju)%fnow(:,:,jk  ), sd(iv)%fnow(:,:,jk  ), 'T', 'en->i', utmp(:,:) )
+                           CALL rot_rep( sd(ju)%fnow(:,:,jk  ), sd(iv)%fnow(:,:,jk  ), 'T', 'en->j', vtmp(:,:) )
+                           sd(ju)%fnow(:,:,jk   ) = utmp(:,:)   ;   sd(iv)%fnow(:,:,jk   ) = vtmp(:,:)
+                        ENDIF
+                     END DO
+                     sd(ju)%rotn(jn) = .TRUE.               ! vector was rotated 
+                     IF( lwp .AND. kt == nit000 )   WRITE(numout,*)   &
+                        &   'fld_read: vector pair ('//TRIM(sd(ju)%clvar)//', '//TRIM(sd(iv)%clvar)//') rotated on to model grid'
+                  ENDIF
+               ENDIF
+            ENDIF
+         END DO
        END DO
       !
@@ -801,27 +749,81 @@
       !!----------------------------------------------------------------------
       TYPE(FLD)        , INTENT(inout) ::   sdjf     ! input field related variables
-      INTEGER          , INTENT(in   ) ::   kyear    ! year value
-      INTEGER          , INTENT(in   ) ::   kmonth   ! month value
-      INTEGER          , INTENT(in   ) ::   kday     ! day value
+      INTEGER, OPTIONAL, INTENT(in   ) ::   kyear    ! year value
+      INTEGER, OPTIONAL, INTENT(in   ) ::   kmonth   ! month value
+      INTEGER, OPTIONAL, INTENT(in   ) ::   kday     ! day value
       LOGICAL, OPTIONAL, INTENT(in   ) ::   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
+      !!
+      LOGICAL :: llprevyr              ! are we reading previous year  file?
+      LOGICAL :: llprevmth             ! are we reading previous month file?
+      INTEGER :: iyear, imonth, iday   ! first day of the current file in yyyy mm dd
+      INTEGER :: isec_week             ! number of seconds since start of the weekly file
+      INTEGER :: indexyr               ! year undex (O/1/2: previous/current/next)
+      INTEGER :: iyear_len, imonth_len ! length (days) of iyear and imonth             ! 
+      CHARACTER(len = 256)::   clname  ! temporary file name
+      !!----------------------------------------------------------------------
+      IF( PRESENT(kyear) ) THEN                             ! use given values 
+         iyear = kyear
+         imonth = kmonth
+         iday = kday
+      ELSE                                                  ! use current day values
+         IF ( sdjf%cltype(1:4) == 'week' ) THEN             ! find the day of the beginning of the week
+            isec_week  = ksec_week( sdjf%cltype(6:8) )      ! second since the beginning of the week
+            llprevmth  = isec_week > nsec_month             ! longer time since beginning of the week than the month
+            llprevyr   = llprevmth .AND. nmonth == 1
+         ELSE
+            isec_week  = 0
+            llprevmth  = .FALSE.
+            llprevyr   = .FALSE.
+         ENDIF
+         iyear  = nyear  - COUNT((/llprevyr /))
+         imonth = nmonth - COUNT((/llprevmth/)) + 12 * COUNT((/llprevyr /))
+         iday   = nday   + nmonth_len(nmonth-1) * COUNT((/llprevmth/)) - isec_week / NINT(rday)
+      ENDIF
+
       ! build the new filename if not climatological data
-      sdjf%clname=TRIM(sdjf%clrootname)
-      !
-      ! note that sdjf%ln_clim is is only acting on presence of the year in the file
+      clname=TRIM(sdjf%clrootname)
+      !
+      ! note that sdjf%ln_clim is is only acting on the presence of the year in the file name
       IF( .NOT. sdjf%ln_clim ) THEN   
-                                         WRITE(sdjf%clname, '(a,"_y",i4.4)' ) TRIM( sdjf%clrootname ), kyear    ! add year
-         IF( sdjf%cltype /= 'yearly' )   WRITE(sdjf%clname, '(a,"m" ,i2.2)' ) TRIM( sdjf%clname     ), kmonth   ! add month
+                                         WRITE(clname, '(a,"_y",i4.4)' ) TRIM( sdjf%clrootname ), iyear    ! add year
+         IF( sdjf%cltype /= 'yearly' )   WRITE(clname, '(a,"m" ,i2.2)' ) TRIM( clname          ), imonth   ! add month
       ELSE
          ! build the new filename if climatological data
-         IF( sdjf%cltype /= 'yearly' )   WRITE(sdjf%clname, '(a,"_m",i2.2)' ) TRIM( sdjf%clrootname ), kmonth   ! add month
+         IF( sdjf%cltype /= 'yearly' )   WRITE(clname, '(a,"_m",i2.2)' ) TRIM( sdjf%clrootname ), imonth   ! add month
       ENDIF
       IF( sdjf%cltype == 'daily' .OR. sdjf%cltype(1:4) == 'week' ) &
-            &                            WRITE(sdjf%clname, '(a,"d" ,i2.2)' ) TRIM( sdjf%clname     ), kday     ! add day
-      !
-      CALL iom_open( sdjf%clname, sdjf%num, ldstop = ldstop, ldiof =  LEN(TRIM(sdjf%wgtname)) > 0 )
-     !
+            &                            WRITE(clname, '(a,"d" ,i2.2)' ) TRIM( clname          ), iday     ! add day
+      !
+      IF( TRIM(clname) /= TRIM(sdjf%clname) .OR. sdjf%num == 0 ) THEN   ! new file to be open 
+
+         sdjf%clname = TRIM(clname)
+         IF( sdjf%num /= 0 )   CALL iom_close( sdjf%num )   ! close file if already open
+         CALL iom_open( sdjf%clname, sdjf%num, ldstop = ldstop, ldiof =  LEN(TRIM(sdjf%wgtname)) > 0 )
+
+         ! find the last record to be read -> update sdjf%nreclast
+         indexyr = iyear - nyear + 1
+         iyear_len = nyear_len( indexyr )
+         SELECT CASE ( indexyr )
+         CASE ( 0 )   ;   imonth_len = 31   ! previous year -> imonth = 12
+         CASE ( 1 )   ;   imonth_len = nmonth_len(imonth) 
+         CASE ( 2 )   ;   imonth_len = 31   ! next     year -> imonth = 1
+         END SELECT
+         
+         ! last record to be read in the current file
+         IF    ( sdjf%nfreqh == -12 ) THEN                 ;   sdjf%nreclast = 1    !  yearly mean
+         ELSEIF( sdjf%nfreqh ==  -1 ) THEN                                          ! monthly mean
+            IF(     sdjf%cltype      == 'monthly' ) THEN   ;   sdjf%nreclast = 1
+            ELSE                                           ;   sdjf%nreclast = 12
+            ENDIF
+         ELSE                                                                       ! higher frequency mean (in hours)
+            IF(     sdjf%cltype      == 'monthly' ) THEN   ;   sdjf%nreclast = 24 * imonth_len / sdjf%nfreqh 
+            ELSEIF( sdjf%cltype(1:4) == 'week'    ) THEN   ;   sdjf%nreclast = 24 * 7          / sdjf%nfreqh
+            ELSEIF( sdjf%cltype      == 'daily'   ) THEN   ;   sdjf%nreclast = 24              / sdjf%nfreqh
+            ELSE                                           ;   sdjf%nreclast = 24 * iyear_len  / sdjf%nfreqh 
+            ENDIF
+         ENDIF
+         
+      ENDIF
+      !
    END SUBROUTINE fld_clopn
 
@@ -845,4 +847,5 @@
       DO jf = 1, SIZE(sdf)
          sdf(jf)%clrootname = TRIM( cdir )//TRIM( sdf_n(jf)%clname )
+         sdf(jf)%clname     = "not yet defined"
          sdf(jf)%nfreqh     = sdf_n(jf)%nfreqh
          sdf(jf)%clvar      = sdf_n(jf)%clvar
@@ -850,8 +853,13 @@
          sdf(jf)%ln_clim    = sdf_n(jf)%ln_clim
          sdf(jf)%cltype     = sdf_n(jf)%cltype
-         sdf(jf)%wgtname = " "
+         sdf(jf)%num        = -1
+         sdf(jf)%wgtname    = " "
          IF( LEN( TRIM(sdf_n(jf)%wname) ) > 0 )   sdf(jf)%wgtname = TRIM( cdir )//TRIM( sdf_n(jf)%wname )
-         sdf(jf)%vcomp   = sdf_n(jf)%vcomp
-         sdf(jf)%rotn    = .TRUE.
+         sdf(jf)%vcomp      = sdf_n(jf)%vcomp
+         sdf(jf)%rotn(:)    = .TRUE.   ! pretend to be rotated -> won't try to rotate data before the first call to fld_get
+         IF( sdf(jf)%cltype(1:4) == 'week' .AND. nn_leapy == 0  )   &
+            &   CALL ctl_stop('fld_clopn: weekly file ('//TRIM(sdf(jf)%clrootname)//') needs nn_leapy = 1')
+         IF( sdf(jf)%cltype(1:4) == 'week' .AND. sdf(jf)%ln_clim )   &
+            &   CALL ctl_stop('fld_clopn: weekly file ('//TRIM(sdf(jf)%clrootname)//') needs ln_clim = .FALSE.')
       END DO
 
