!======================================================================
! CROCO is a branch of ROMS developped at IRD, INRIA, 
! Ifremer, CNRS and Univ. Toulouse III  in France
! The two other branches from UCLA (Shchepetkin et al)
! and Rutgers University (Arango et al) are under MIT/X style license.
! CROCO specific routines (nesting) are under CeCILL-C license.
!
! CROCO website : http://www.croco-ocean.org
!======================================================================
!
#include "cppdefs.h"
#if defined M2CLIMATOLOGY && !defined ANA_M2CLIMA || \
   (defined M3CLIMATOLOGY && !defined ANA_M3CLIMA)
!
                             ! Read tracer(s) climatology
      subroutine get_uclima  ! fields from climatology file
                             ! at appropriate time.
# ifdef OPENACC
      use exchange_device_host
# endif
      implicit none
# include "param.h"
# include "scalars.h"
# include "ncscrum.h"
# include "climat.h"
      real cff
      integer i, lstr,lvar,lenstr, ierr, nf_fread, advance_cycle
# include "netcdf.inc"
!
! Initialization: Inquire about the contents of climatological file:
!================ variables and dimensions. Check for consistency.
!
      if (may_day_flag.ne.0) return      !-->  EXIT
      if (iic.eq.0 ) then
        lstr=lenstr(clmname)
!
! If not opened yet, open climatological file for reading.
! Check for availability of tracer climatology foelds in input
! netCDF file and save their IDs. Signal to terminate, if not found.
!
        if (ncidclm.eq.-1) then
          ierr=nf_open (clmname(1:lstr), nf_nowrite, ncidclm)
          if (ierr .ne. nf_noerr) goto 4                !--> ERROR
        endif

        ierr=nf_inq_varid (ncidclm, 'uclm_time', uclm_tid)
        if (ierr .ne. nf_noerr) then
          write(stdout,3) 'uclm_time', clmname(1:lstr)
          goto 99                                     !--> ERROR
        endif
# ifdef M2CLIMATOLOGY
        lvar=lenstr(vname(1,indxUb))
        ierr=nf_inq_varid (ncidclm, vname(1,indxUb)(1:lvar), ubclm_id)
        if (ierr .ne. nf_noerr) then
          write(stdout,3) vname(1,indxUb)(1:lvar), clmname(1:lstr)
          goto 99                                       !--> ERROR
        endif

        lvar=lenstr(vname(1,indxVb))
        ierr=nf_inq_varid (ncidclm, vname(1,indxVb)(1:lvar), vbclm_id)
        if (ierr .ne. nf_noerr) then
          write(stdout,3) vname(1,indxVb)(1:lvar), clmname(1:lstr)
          goto 99                                       !--> ERROR
        endif
# endif
# if defined M3CLIMATOLOGY && defined SOLVE3D
        lvar=lenstr(vname(1,indxU))
        ierr=nf_inq_varid (ncidclm, vname(1,indxU)(1:lvar), uclm_id)
        if (ierr .ne. nf_noerr) then
          write(stdout,3) vname(1,indxU)(1:lvar), clmname(1:lstr)
          goto 99                                       !--> ERROR
        endif

        lvar=lenstr(vname(1,indxV))
        ierr=nf_inq_varid (ncidclm, vname(1,indxV)(1:lvar), vclm_id)
        if (ierr .ne. nf_noerr) then
          write(stdout,3) vname(1,indxV)(1:lvar), clmname(1:lstr)
          goto 99                                       !--> ERROR
        endif
# endif
!
! Determine whether there is cycling to reuse the input data
! and find cycling period "uclm_cycle", set initial cycling
! index "uclm_ncycle" and record index "uclm_rec".
! Set initial value for time index "iuclm" and both time record
! bounds to large negative artificial values, so that it will
! trigger the logic in reading part below.
!
          call set_cycle (ncidclm, uclm_tid, ntuclm,
     &                    uclm_cycle, uclm_ncycle, uclm_rec)

          if (may_day_flag.ne.0) return    !-->  EXIT
          ituclm=2
          uclm_time(1)=-1.E+20
          uclm_time(2)=-1.E+20
      endif
!
! Read in momentum climatology: Check, if if model time is within the
! ==== == ======== ============ bounds set by the past and future data
! times. If not, flip the time index, increment record and cycling
! indices and read a new portion of data: climatology time
! coordinate and tracer climatology field. Check and read again,
! until model time is between the two time bounds.
!
 10   i=3-ituclm
      cff=time+0.5*dt
      if (uclm_time(i).le.cff .and.
     &  cff.lt.uclm_time(ituclm)) goto 1
      ierr=advance_cycle (uclm_cycle,  ntuclm,
     &                    uclm_ncycle, uclm_rec)
      if (ierr.ne.0) then
        write(stdout,7) uclm_rec, ntuclm,
     &                  clmname(1:lstr), tdays,
     &                  uclm_time(ituclm)*sec2day
        goto 99                                        !--> ERROR
      endif

      ierr=nf_get_var1_FTYPE(ncidclm, uclm_tid,
     &                             uclm_rec, cff)
      if (ierr.ne.NF_NOERR) then
        write(stdout,6) 'Xclm_time', uclm_rec
        goto 99                                        !--> ERROR
      endif
# ifdef USE_CALENDAR
        call tool_origindate(ncidclm,uclm_tid,
     &                       uclm_origin_date_in_sec)
        cff=cff+uclm_origin_date_in_sec*sec2day
# endif

      uclm_time(i)=cff*day2sec+uclm_cycle
     &                             *uclm_ncycle
      if (uclm_time(ituclm).eq.-1.E+20)
     &    uclm_time(ituclm)=uclm_time(i)
# ifdef M2CLIMATOLOGY
      ierr=nf_fread (ubclima(START_2D_ARRAY,i),
     &                           ncidclm, ubclm_id,
     &                           uclm_rec, u2dvar)
#  ifdef OPENACC
      call update_device(ubclima(:,:,i))
#  endif
      if (ierr.ne.NF_NOERR) then
        lvar=lenstr(vname(1,indxUb))
        write(stdout,6) vname(1,indxUb)(1:lvar), uclm_rec
        goto 99                                       !--> ERROR
      endif
!
      ierr=nf_fread (vbclima(START_2D_ARRAY,i),
     &                           ncidclm, vbclm_id,
     &                           uclm_rec, v2dvar)
#  ifdef OPENACC
      call update_device(vbclima(:,:,i))
#  endif
      if (ierr.ne.NF_NOERR) then
        lvar=lenstr(vname(1,indxVb))
        write(stdout,6) vname(1,indxVb)(1:lvar), uclm_rec
        goto 99                                       !--> ERROR
      endif
# endif
# if defined M3CLIMATOLOGY && defined SOLVE3D
      ierr=nf_fread (uclima(START_2D_ARRAY,1,i),
     &                           ncidclm, uclm_id,
     &                           uclm_rec, u3dvar)
#  ifdef OPENACC
      call update_device(uclima(:,:,:,i))
#  endif
      if (ierr.ne.NF_NOERR) then
        lvar=lenstr(vname(1,indxU))
        write(stdout,6) vname(1,indxU)(1:lvar), uclm_rec
        goto 99                                       !--> ERROR
      endif
!
      ierr=nf_fread (vclima(START_2D_ARRAY,1,i),
     &                           ncidclm, vclm_id,
     &                           uclm_rec, v3dvar)
#  ifdef OPENACC
      call update_device(vclima(:,:,:,i))
#  endif
      if (ierr.ne.NF_NOERR) then
        lvar=lenstr(vname(1,indxV))
        write(stdout,6) vname(1,indxV)(1:lvar), uclm_rec
        goto 99                                       !--> ERROR
      endif
# endif

      ituclm=i
      MPI_master_only write(stdout,'(6x,A,1x,g12.4,1x,I4)')
     &'GET_UCLIMA -- Read momentum climatology      for time =', cff
# ifdef USE_CALENDAR
     &  -uclm_origin_date_in_sec*sec2day
# endif
# ifdef MPI
     &                                                      , mynode
# endif
        if (ntuclm.gt.1) goto 10
  1    continue
      return
!
! Sort out error messages: The following portion of the code is
!===== === ===== ========= not accessed unless something goes wrong.
!
  3   format(/,' GET_UCLIMA - unable to find climatology variable: ',
     &       a,/,15x,'in climatology NetCDF file: ',a)
  4   write(stdout,5) clmname(1:lstr)
  5   format(/,' GET_UCLIMA - unable to open climatology',
     &         1x,'NetCDF file: ',a)
      goto 99
  6   format(/,' GET_UCLIMA - ERROR while reading variable: ',a,2x,
     &       ' at TIME index = ',i4)

  7   format(/,' GET_UCLIMA - ERROR: requested time record ',I4,
     &       1x,'exeeds the last available', /,14x,'record ',I4,
     &       1x,'in climatology file: ',a, /,14x,'TDAYS = ',
     &       g12.4,2x,'last available UCLM_TIME = ',g12.4)

  99  may_day_flag=2
      return
      end

      subroutine set_uclima (tile)
      implicit none
      integer tile
# include "param.h"
# ifdef  ALLOW_SINGLE_BLOCK_MODE
C$    integer  trd, omp_get_thread_num
# endif
# include "compute_tile_bounds.h"
      call set_uclima_tile (Istr,Iend,Jstr,Jend)
      return
      end

      subroutine set_uclima_tile (Istr,Iend,Jstr,Jend)
!
!--------------------------------------------------------------------
!  Set-up momentum climatology for current tile.
!--------------------------------------------------------------------
!
      implicit none
# include "param.h"
# include "scalars.h"
# include "climat.h"
      integer Istr,Iend,Jstr,Jend, i,j,k, it1,it2
      real cff, cff1, cff2
!
# include "compute_extended_bounds.h"
!
! Set coefficients for interpolation. Check that for the next time
! step [when time=time+dt] both weights will still be positive, and
! if not, set synchro_flag to signal that new data should be read
! from an appropriate netCDF input file (master thread only).
! After that either load time-invariant data, or interpolate in time
! or complain about error and signal to quit, if interpolation is
! needed, but not possible.
!
      it1=3-ituclm
      it2=ituclm
      cff=time+0.5*dt
      cff1=uclm_time(it2)-cff
      cff2=cff-uclm_time(it1)
      if (ZEROTH_TILE .and. cff1.lt.dt) synchro_flag=.TRUE.

      if (uclm_cycle.lt.0.) then      ! Load time-invariant
        if (iic.eq.0) then            ! momentum climatology.
# ifdef M2CLIMATOLOGY
!$acc parallel loop if(compute_on_device) default(present)
          do j=JstrR,JendR
            do i=IstrR,IendR
              ubclm(i,j)=ubclima(i,j,ituclm)
              vbclm(i,j)=vbclima(i,j,ituclm)
            enddo
          enddo
# endif
# if defined M3CLIMATOLOGY && defined SOLVE3D
!$acc parallel loop if(compute_on_device) default(present)
          do k=1,N  
            do j=JstrR,JendR
              do i=IstrR,IendR
                uclm(i,j,k)=uclima(i,j,k,ituclm)
                vclm(i,j,k)=vclima(i,j,k,ituclm)
              enddo
            enddo
          enddo
# endif
        endif
      elseif (cff1.ge.0. .and. cff2.ge.0.) then
        cff=1./(cff1+cff2)                     ! Interpolate tracer
        cff1=cff1*cff                          ! climatology in time.
        cff2=cff2*cff
# ifdef M2CLIMATOLOGY
!$acc parallel loop if(compute_on_device) default(present)
        do j=JstrR,JendR
          do i=IstrR,IendR
            ubclm(i,j)=cff1*ubclima(i,j,it1)
     &                +cff2*ubclima(i,j,it2)
            vbclm(i,j)=cff1*vbclima(i,j,it1)
     &                +cff2*vbclima(i,j,it2)
          enddo
        enddo
# endif
# if defined M3CLIMATOLOGY && defined SOLVE3D
!$acc parallel loop if(compute_on_device) default(present)
        do k=1,N
          do j=JstrR,JendR
            do i=IstrR,IendR
              uclm(i,j,k)=cff1*uclima(i,j,k,it1)
     &                   +cff2*uclima(i,j,k,it2)
              vclm(i,j,k)=cff1*vclima(i,j,k,it1)
     &                   +cff2*vclima(i,j,k,it2)
            enddo
          enddo
        enddo
# endif
      elseif (ZEROTH_TILE) then
          write(stdout,'(/1x,2A/3(1x,A,F16.10)/)')
     &            'SET_UCLIMA_TILE - current model time is outside ',
     &            'bounds of ''uclm_time''.', 'UCLM_TSTART=',
     &             uclm_time(it1)*sec2day,     'TDAYS=',  tdays,
     &            'UCLM_TEND=',   uclm_time(it2)*sec2day
# ifdef USE_CALENDAR
     &  -uclm_origin_date_in_sec*sec2day
# endif
          may_day_flag=2
      endif
      return
      end
#else
      subroutine get_uclima_empty
      return
      end
#endif /* M2CLIMATOLOGY && !ANA_M2CLIMA || (M3CLIMATOLOGY && !ANA_M3CLIMA) */
