New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
Changeset 3062 for branches/2011/dev_UKM0_2011/NEMOGCM/NEMO/OPA_SRC/SBC/fldread.F90 – NEMO

Ignore:
Timestamp:
2011-11-09T11:47:32+01:00 (12 years ago)
Author:
rfurner
Message:

ticket #885. added in changes from branches/2011/UKMO_MERCATOR_obc_bdy_merge@2888

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2011/dev_UKM0_2011/NEMOGCM/NEMO/OPA_SRC/SBC/fldread.F90

    r2777 r3062  
    2424   IMPLICIT NONE 
    2525   PRIVATE    
     26  
     27   PUBLIC   fld_map    ! routine called by tides_init 
    2628 
    2729   TYPE, PUBLIC ::   FLD_N      !: Namelist field informations 
     
    5658      LOGICAL                         ::   rotn         ! flag to indicate whether field has been rotated 
    5759   END TYPE FLD 
     60 
     61   TYPE, PUBLIC ::   MAP_POINTER      !: Array of integer pointers to 1D arrays 
     62      INTEGER, POINTER   ::  ptr(:) 
     63   END TYPE MAP_POINTER 
    5864 
    5965!$AGRIF_DO_NOT_TREAT 
     
    98104CONTAINS 
    99105 
    100    SUBROUTINE fld_read( kt, kn_fsbc, sd ) 
     106   SUBROUTINE fld_read( kt, kn_fsbc, sd, map, jit, time_offset ) 
    101107      !!--------------------------------------------------------------------- 
    102108      !!                    ***  ROUTINE fld_read  *** 
     
    113119      INTEGER  , INTENT(in   )               ::   kn_fsbc   ! sbc computation period (in time step)  
    114120      TYPE(FLD), INTENT(inout), DIMENSION(:) ::   sd        ! input field related variables 
     121      TYPE(MAP_POINTER),INTENT(in), OPTIONAL, DIMENSION(:) ::   map   ! global-to-local mapping index 
     122      INTEGER  , INTENT(in   ), OPTIONAL     ::   jit       ! subcycle timestep for timesplitting option 
     123      INTEGER  , INTENT(in   ), OPTIONAL     ::   time_offset ! provide fields at time other than "now" 
     124                                                              ! time_offset = -1 => fields at "before" time level 
     125                                                              ! time_offset = +1 => fields at "after" time levels 
     126                                                              ! etc. 
    115127      !! 
    116128      INTEGER  ::   imf        ! size of the structure sd 
     
    119131      INTEGER  ::   isecend    ! number of second since Jan. 1st 00h of nit000 year at nitend 
    120132      INTEGER  ::   isecsbc    ! number of seconds between Jan. 1st 00h of nit000 year and the middle of sbc time step 
     133      INTEGER  ::   time_add   ! local time_offset variable 
    121134      LOGICAL  ::   llnxtyr    ! open next year  file? 
    122135      LOGICAL  ::   llnxtmth   ! open next month file? 
    123136      LOGICAL  ::   llstop     ! stop is the file does not exist 
     137      LOGICAL  ::   ll_firstcall ! true if this is the first call to fld_read for this set of fields 
    124138      REAL(wp) ::   ztinta     ! ratio applied to after  records when doing time interpolation 
    125139      REAL(wp) ::   ztintb     ! ratio applied to before records when doing time interpolation 
    126140      CHARACTER(LEN=1000) ::   clfmt   ! write format 
    127141      !!--------------------------------------------------------------------- 
     142      ll_firstcall = .false. 
     143      IF( PRESENT(jit) ) THEN 
     144         IF(kt == nit000 .and. jit == 1) ll_firstcall = .true. 
     145      ELSE 
     146         IF(kt == nit000) ll_firstcall = .true. 
     147      ENDIF 
     148 
     149      time_add = 0 
     150      IF( PRESENT(time_offset) ) THEN 
     151         time_add = time_offset 
     152      ENDIF 
     153          
    128154      ! Note that shifting time to be centrered in the middle of sbc time step impacts only nsec_* variables of the calendar  
    129       isecsbc = nsec_year + nsec1jan000 + NINT(0.5 * REAL(kn_fsbc - 1,wp) * rdttra(1))   ! middle of sbc time step 
     155      IF( present(jit) ) THEN  
     156         ! ignore kn_fsbc in this case 
     157         isecsbc = nsec_year + nsec1jan000 + (jit+time_add)*rdt/REAL(nn_baro,wp)  
     158      ELSE 
     159         isecsbc = nsec_year + nsec1jan000 + NINT(0.5 * REAL(kn_fsbc - 1,wp) * rdttra(1)) + time_add * rdttra(1)  ! middle of sbc time step 
     160      ENDIF 
    130161      imf = SIZE( sd ) 
    131162      ! 
    132       IF( kt == nit000 ) THEN                      ! initialization 
    133          DO jf = 1, imf  
    134             CALL fld_init( kn_fsbc, sd(jf) )       ! read each before field (put them in after as they will be swapped) 
    135          END DO 
     163      IF( ll_firstcall ) THEN                      ! initialization 
     164         IF( PRESENT(map) ) THEN 
     165            DO jf = 1, imf  
     166               CALL fld_init( kn_fsbc, sd(jf), map(jf)%ptr )  ! read each before field (put them in after as they will be swapped) 
     167            END DO 
     168         ELSE 
     169            DO jf = 1, imf  
     170               CALL fld_init( kn_fsbc, sd(jf) )       ! read each before field (put them in after as they will be swapped) 
     171            END DO 
     172         ENDIF 
    136173         IF( lwp ) CALL wgt_print()                ! control print 
    137174         CALL fld_rot( kt, sd )                    ! rotate vector fiels if needed 
     
    143180         DO jf = 1, imf                            ! ---   loop over field   --- ! 
    144181             
    145             IF( isecsbc > sd(jf)%nrec_a(2) .OR. kt == nit000 ) THEN  ! read/update the after data? 
     182            IF( isecsbc > sd(jf)%nrec_a(2) .OR. ll_firstcall ) THEN  ! read/update the after data? 
    146183 
    147184               IF( sd(jf)%ln_tint ) THEN                             ! swap before record field and informations 
     
    151188               ENDIF 
    152189 
    153                CALL fld_rec( kn_fsbc, sd(jf) )                       ! update record informations 
     190               IF( PRESENT(jit) ) THEN 
     191                  CALL fld_rec( kn_fsbc, sd(jf), jit=jit )              ! update record informations 
     192               ELSE 
     193                  CALL fld_rec( kn_fsbc, sd(jf) )                       ! update record informations 
     194               ENDIF 
    154195 
    155196               ! do we have to change the year/month/week/day of the forcing field??  
     
    212253 
    213254               ! read after data 
    214                CALL fld_get( sd(jf) ) 
     255               IF( PRESENT(map) ) THEN 
     256                  CALL fld_get( sd(jf), map(jf)%ptr ) 
     257               ELSE 
     258                  CALL fld_get( sd(jf) ) 
     259               ENDIF 
    215260 
    216261            ENDIF 
     
    225270                  clfmt = "('fld_read: var ', a, ' kt = ', i8, ' (', f7.2,' days), Y/M/D = ', i4.4,'/', i2.2,'/', i2.2," //   & 
    226271                     &    "', records b/a: ', i4.4, '/', i4.4, ' (days ', f7.2,'/', f7.2, ')')" 
    227                   WRITE(numout, clfmt)  TRIM( sd(jf)%clvar ), kt, REAL(isecsbc,wp)/rday, nyear, nmonth, nday,   & 
     272                  WRITE(numout, clfmt)  TRIM( sd(jf)%clvar ), kt, REAL(isecsbc,wp)/rday, nyear, nmonth, nday,   &             
    228273                     & 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 
     274                  WRITE(numout, *) 'time_add is : ',time_add 
    229275               ENDIF 
    230276               ! temporal interpolation weights 
     
    253299 
    254300 
    255    SUBROUTINE fld_init( kn_fsbc, sdjf ) 
     301   SUBROUTINE fld_init( kn_fsbc, sdjf, map ) 
    256302      !!--------------------------------------------------------------------- 
    257303      !!                    ***  ROUTINE fld_init  *** 
     
    262308      INTEGER  , INTENT(in   ) ::   kn_fsbc   ! sbc computation period (in time step)  
    263309      TYPE(FLD), INTENT(inout) ::   sdjf      ! input field related variables 
     310      INTEGER  , INTENT(in), OPTIONAL, DIMENSION(:) :: map ! global-to-local mapping indices 
    264311      !! 
    265312      LOGICAL :: llprevyr              ! are we reading previous year  file? 
     
    364411 
    365412         ! read before data  
    366          CALL fld_get( sdjf )  ! read before values in after arrays(as we will swap it later) 
     413         IF( PRESENT(map) ) THEN 
     414            CALL fld_get( sdjf, map )  ! read before values in after arrays(as we will swap it later) 
     415         ELSE 
     416            CALL fld_get( sdjf )  ! read before values in after arrays(as we will swap it later) 
     417         ENDIF 
    367418 
    368419         clfmt = "('fld_init : time-interpolation for ', a, ' read previous record = ', i4, ' at time = ', f7.2, ' days')" 
     
    396447 
    397448 
    398    SUBROUTINE fld_rec( kn_fsbc, sdjf, ldbefore ) 
     449   SUBROUTINE fld_rec( kn_fsbc, sdjf, ldbefore, jit ) 
    399450      !!--------------------------------------------------------------------- 
    400451      !!                    ***  ROUTINE fld_rec  *** 
     
    410461      TYPE(FLD), INTENT(inout)           ::   sdjf      ! input field related variables 
    411462      LOGICAL  , INTENT(in   ), OPTIONAL ::   ldbefore  ! sent back before record values (default = .FALSE.) 
     463      INTEGER  , INTENT(in   ), OPTIONAL ::   jit       ! index of barotropic subcycle 
    412464                                                        ! used only if sdjf%ln_tint = .TRUE. 
    413465      !! 
     
    443495            !                             
    444496            ztmp = REAL( nday, wp ) / REAL( nyear_len(1), wp ) + 0.5 
     497            IF( PRESENT(jit) ) ztmp = ztmp + jit*rdt/REAL(nn_baro,wp) 
    445498            sdjf%nrec_a(1) = 1 + INT( ztmp ) - COUNT((/llbefore/)) 
    446499            ! swap at the middle of the year 
     
    471524            !                             
    472525            ztmp = REAL( nday, wp ) / REAL( nmonth_len(nmonth), wp ) + 0.5 
     526            IF( PRESENT(jit) ) ztmp = ztmp + jit*rdt/REAL(nn_baro,wp) 
    473527            imth = nmonth + INT( ztmp ) - COUNT((/llbefore/)) 
    474528            IF( sdjf%cltype == 'monthly' ) THEN   ;   sdjf%nrec_a(1) = 1 + INT( ztmp ) - COUNT((/llbefore/)) 
     
    498552         ztmp = ztmp + 0.5 * REAL(kn_fsbc - 1, wp) * rdttra(1)   ! shift time to be centrered in the middle of sbc time step 
    499553         ztmp = ztmp + 0.01 * rdttra(1)                          ! add 0.01 time step to avoid truncation error  
     554         IF( PRESENT(jit) ) ztmp = ztmp + jit*rdt/REAL(nn_baro,wp) 
    500555         IF( sdjf%ln_tint ) THEN                ! time interpolation, shift by 1/2 record 
    501556            ! 
     
    546601 
    547602 
    548    SUBROUTINE fld_get( sdjf ) 
    549       !!--------------------------------------------------------------------- 
    550       !!                    ***  ROUTINE fld_clopn  *** 
     603   SUBROUTINE fld_get( sdjf, map ) 
     604      !!--------------------------------------------------------------------- 
     605      !!                    ***  ROUTINE fld_get  *** 
    551606      !! 
    552607      !! ** Purpose :   read the data 
    553608      !!---------------------------------------------------------------------- 
    554609      TYPE(FLD), INTENT(inout) ::   sdjf   ! input field related variables 
     610      INTEGER  , INTENT(in), OPTIONAL, DIMENSION(:) :: map ! global-to-local mapping indices 
    555611      !! 
    556612      INTEGER                  ::   ipk    ! number of vertical levels of sdjf%fdta ( 2D: ipk=1 ; 3D: ipk=jpk ) 
     
    559615             
    560616      ipk = SIZE( sdjf%fnow, 3 ) 
    561       IF( LEN(TRIM(sdjf%wgtname)) > 0 ) THEN 
     617 
     618      IF( PRESENT(map) ) THEN 
     619         IF( sdjf%ln_tint ) THEN   ;   CALL fld_map( sdjf%num, sdjf%clvar, sdjf%fdta(:,:,:,2), sdjf%nrec_a(1), map ) 
     620         ELSE                      ;   CALL fld_map( sdjf%num, sdjf%clvar, sdjf%fnow(:,:,:  ), sdjf%nrec_a(1), map ) 
     621         ENDIF 
     622      ELSE IF( LEN(TRIM(sdjf%wgtname)) > 0 ) THEN 
    562623         CALL wgt_list( sdjf, iw ) 
    563624         IF( sdjf%ln_tint ) THEN   ;   CALL fld_interp( sdjf%num, sdjf%clvar, iw , ipk  , sdjf%fdta(:,:,:,2), sdjf%nrec_a(1) ) 
     
    581642   END SUBROUTINE fld_get 
    582643 
     644   SUBROUTINE fld_map( num, clvar, dta, nrec, map ) 
     645      !!--------------------------------------------------------------------- 
     646      !!                    ***  ROUTINE fld_get  *** 
     647      !! 
     648      !! ** Purpose :   read global data from file and map onto local data 
     649      !!                using a general mapping (for open boundaries) 
     650      !!---------------------------------------------------------------------- 
     651#if defined key_bdy 
     652      USE bdy_oce, ONLY:  dta_global         ! workspace to read in global data arrays 
     653#endif  
     654 
     655      INTEGER                   , INTENT(in ) ::   num     ! stream number 
     656      CHARACTER(LEN=*)          , INTENT(in ) ::   clvar   ! variable name 
     657      REAL(wp), DIMENSION(:,:,:), INTENT(out) ::   dta   ! output field on model grid (2 dimensional) 
     658      INTEGER                   , INTENT(in ) ::   nrec    ! record number to read (ie time slice) 
     659      INTEGER,  DIMENSION(:)    , INTENT(in ) ::   map     ! global-to-local mapping indices 
     660      !! 
     661      INTEGER                                 ::   ipi      ! length of boundary data on local process 
     662      INTEGER                                 ::   ipj      ! length of dummy dimension ( = 1 ) 
     663      INTEGER                                 ::   ipk      ! number of vertical levels of dta ( 2D: ipk=1 ; 3D: ipk=jpk ) 
     664      INTEGER                                 ::   ilendta  ! length of data in file 
     665      INTEGER                                 ::   idvar    ! variable ID 
     666      INTEGER                                 ::   ib, ik   ! loop counters 
     667      INTEGER                                 ::   ierr 
     668      REAL(wp), POINTER, DIMENSION(:,:,:)     ::   dta_read ! work space for global data 
     669      !!--------------------------------------------------------------------- 
     670             
     671#if defined key_bdy 
     672      dta_read => dta_global 
     673#endif 
     674 
     675      ipi = SIZE( dta, 1 ) 
     676      ipj = 1 
     677      ipk = SIZE( dta, 3 ) 
     678 
     679      idvar   = iom_varid( num, clvar ) 
     680      ilendta = iom_file(num)%dimsz(1,idvar) 
     681      IF(lwp) WRITE(numout,*) 'Dim size for ',TRIM(clvar),' is ', ilendta 
     682      IF(lwp) WRITE(numout,*) 'Number of levels for ',TRIM(clvar),' is ', ipk 
     683 
     684      SELECT CASE( ipk ) 
     685      CASE(1)    
     686         CALL iom_get ( num, jpdom_unknown, clvar, dta_read(1:ilendta,1:ipj,1    ), nrec ) 
     687      CASE DEFAULT 
     688         CALL iom_get ( num, jpdom_unknown, clvar, dta_read(1:ilendta,1:ipj,1:ipk), nrec ) 
     689      END SELECT 
     690      ! 
     691      DO ib = 1, ipi 
     692         DO ik = 1, ipk 
     693            dta(ib,1,ik) =  dta_read(map(ib),1,ik) 
     694         END DO 
     695      END DO 
     696 
     697   END SUBROUTINE fld_map 
     698 
    583699 
    584700   SUBROUTINE fld_rot( kt, sd ) 
    585701      !!--------------------------------------------------------------------- 
    586       !!                    ***  ROUTINE fld_clopn  *** 
     702      !!                    ***  ROUTINE fld_rot  *** 
    587703      !! 
    588704      !! ** Purpose :   Vector fields may need to be rotated onto the local grid direction 
    589705      !!---------------------------------------------------------------------- 
    590706      USE wrk_nemo, ONLY: wrk_in_use, wrk_not_released 
    591       USE wrk_nemo, ONLY: utmp => wrk_2d_4, vtmp => wrk_2d_5      ! 2D workspace 
     707      USE wrk_nemo, ONLY: utmp => wrk_2d_24, vtmp => wrk_2d_25      ! 2D workspace 
    592708      !! 
    593709      INTEGER  , INTENT(in   )               ::   kt        ! ocean time step 
     
    601717      !!--------------------------------------------------------------------- 
    602718 
    603       IF(wrk_in_use(2, 4,5) ) THEN 
     719      IF(wrk_in_use(2, 24,25) ) THEN 
    604720         CALL ctl_stop('fld_rot: ERROR: requested workspace arrays are unavailable.')   ;   RETURN 
    605721      END IF 
     
    638754       END DO 
    639755      ! 
    640       IF(wrk_not_released(2, 4,5) )    CALL ctl_stop('fld_rot: ERROR: failed to release workspace arrays.') 
     756      IF(wrk_not_released(2, 24,25) )    CALL ctl_stop('fld_rot: ERROR: failed to release workspace arrays.') 
    641757      ! 
    642758   END SUBROUTINE fld_rot 
     
    672788      ! 
    673789      CALL iom_open( sdjf%clname, sdjf%num, ldstop = ldstop, ldiof =  LEN(TRIM(sdjf%wgtname)) > 0 ) 
    674       ! 
     790     ! 
    675791   END SUBROUTINE fld_clopn 
    676792 
Note: See TracChangeset for help on using the changeset viewer.