!! Pierre-Antoine Bretonnière, Institut Català de Ciènces del Clima <pierre-antoine.bretonniere@ic3.cat>

!! Adapted from nemo2cmor originally created by Alasatair McKinstry, ICHEC

!! Last edited: 2012-07-03

PROGRAM specs2cmor
  USE netcdf
  USE cmor_users_functions
  IMPLICIT NONE

  ! Use params as enumerator not yet supported everywhere
   INTEGER, PARAMETER :: amon_tas = 1, amon_tasmax = 2,  &
       amon_tasmin = 128, amon_uas = 130, &
       amon_vas = 131, amon_psl = 132, &
       amon_pr=146, amon_clt=147, amon_hfss=148, &
       amon_hfls=21, amon_rsds=20, amon_snld=19, amon_tdps=18, amon_al=17, &
       amon_rlut=26, amon_rss=25,amon_fal=27,amon_rls=28
   INTEGER, PARAMETER :: amon_zg=24, amon_ta=23,amon_hus=22,&
!       da_psl=32, da_prsn=31, da_hfss=30, da_hfls=29, da_rsds=28, &
       da_sic = 33, mon_lt=195, da_sit = 34, da_tasmin = 36,da_lt=196,& 
       da_pr= 37, da_rsds=38,da_rlut=39,da_ta=39,da_rls=40, &
       da_tasmax = 41,da_zg = 42
   INTEGER, PARAMETER :: s6h_lt=101,s6h_psl=102,s6h_tas=103,s6h_tdps=104,&
       s6h_clt=105,s6h_uas=106,s6h_vas=107  
!       da_tasmax = 37, da_pr = 39, da_snd=16, da_tsice=15, &
!       da_t20d = 38, da_mlotst= 40, da_tos=41, &
!       amon_thetao = 45, amon_so = 46, &
!       amon_fsitherm = 50, amon_wfo = 51, &
!       amon_vsfsit = 52, amon_mlotst = 53, amon_omlmax = 54, &
!       amon_rsntds = 55, amon_uo = 56, amon_vo = 57, &
!       amon_masso = 58, amon_pbo = 59, amon_pso = 60, &
!       amon_volo = 61, amon_masscello = 62, amon_zostoga = 63, &
!       amon_thkcello = 64, amon_zosga = 65, amon_zossga = 66, &
!       amon_thetaoga = 66, amon_soga = 67, amon_wmo = 68, &
!       amon_wmosq = 69, amon_sfdsi = 70, amon_hfsithermds = 71, &
!       amon_umo = 72, amon_vmo = 73, amon_msftmyz = 74, amon_msftmrhoz = 75, &
!       amon_msftyyz = 135, & 
!       amon_hfnorth = 76, amon_hfx = 77,  amon_hfy = 78, amon_htovgyre = 79, &
!       amon_htovovrt = 80, amon_sltovgyre = 81, amon_sltovovrt = 82, &
!       amon_pr = 83, amon_prsn = 84, amon_evs = 85, amon_friver = 86, &
!       amon_ficeberg = 87, amon_wfonocorr = 89, amon_wfcorr = 90, &
!       amon_vsfpr = 91, amon_vsfevap = 92, amon_vsfriver = 93, amon_vsf = 94, &
!       amon_vsfcorr = 95, amon_sfriver = 96, amon_hfgeou = 97, amon_hfrainds = 98, &
!       amon_hfevapds = 99, amon_hfrunoffds = 100, amon_hfsnthermds = 101, &
!       amon_hfibthermds = 102, amon_rlds = 103, amon_hfls = 104, amon_hfss = 105, &
!       amon_rsds = 106, amon_hfcorr = 107, amon_hfds = 108, amon_tauuo = 109, &
!       amon_tauvo = 110, amon_tauucorr = 111, amon_tauvcorr = 112, &
!       amon_tossq = 113, amon_zossq = 114, amon_rhopoto = 115, amon_agessc = 116, &
!       amon_cfc11 = 117, amon_msftbarot = 118, amon_mlotstsq = 119, &
!       amon_omldamax = 120, amon_tos=136, amon_sos=137, amon_zos=138, amon_t20d=139, &
!       amon_thetaot=140, amon_wo=141, &
!       lmon_mrros = 122, &
!       fx_deptho = 123, fx_areacello = 124, fx_sftof = 125, fx_basin = 126, &
!       fx_basinv = 127, fx_volcello = 128, fx_sftlf=129, fx_goro=130, fx_wmb=144, fx_al=145, &
!       fx_fc=133, fx_sftgif=134, fx_sr=142, fx_wp=143, mon_lt=195, da_lt=196 
  
!  INTEGER, PARAMETER :: sy = 512, sx = 256
  INTEGER :: sy , sx 
  CHARACTER (len=80) :: namfile
  
  CHARACTER (len=80) :: time_units, calendar, interval, interval_i
  INTEGER :: status, j,k, ncid_t, ncid_i, ncid_u, ncid_v, ncid_w, ntimes, ntimes_i
  LOGICAL :: initialized = .FALSE., fourmonths = .FALSE., finished = .FALSE.
  INTEGER, PARAMETER :: priority = 0   ! Only output highest priority items for now
  INTEGER, DIMENSION(200) :: varids 
  DOUBLE PRECISION :: bt
  DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: oimon_time, amon_time,fx_time,day_time,s6h_time
  DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: oimon_time_bnds, amon_time_bnds,fx_time_bnds,day_time_bnds,s6h_time_bnds
  REAL, DIMENSION(:,:), ALLOCATABLE  :: lat_coords, long_coords
  REAL, DIMENSION(:,:,:), ALLOCATABLE :: lat_vertices, long_vertices
!  REAL, DIMENSION(sy,sx)  :: lat_coords, long_coords
!  REAL, DIMENSION(4,sy, sx) :: lat_vertices, long_vertices
  REAL, DIMENSION(:), ALLOCATABLE :: depths_u, depths_v, depths_t, depths_w
  INTEGER :: numvars, year, month, realization, initialization_method, startyear, endyear, ioe, startmonth, endmonth, physics_version
  INTEGER :: ax_time_oimon, ax_time_amon, monthnum,ax_time_fx,ax_time_day,ax_time_6h
  CHARACTER (len=4) :: expname
  CHARACTER(LEN=2) :: frequency
  CHARACTER (len=256) :: inpath,outpath, experiment_id, institution, model_id, source, &
   & history, comment, references, forcing, contact, institute_id,  parent_experiment_id, &
   & parent_experiment_rip, project_id, physics_description,associated_model,initialization_description,forecast_reference_time,prefix,associated_experiment!batch
!  character(len=7) :: series
  integer:: i, numyears, nmonths, monthspresent,interv,jj
  integer,dimension(3)::ind
  integer,dimension(3)::ncid
!  integer,dimension(5)::ncid

  ! 'fourmonths'  obsolete but left here so that old namelists still work.
!to be generalized (add model description?)
  NAMELIST /NAMEXP/ inpath, outpath, expname, experiment_id, institution, institute_id, model_id, source, &
   realization, history, comment, references, forcing, contact, institute_id, &
   startyear, endyear, parent_experiment_id, parent_experiment_rip, &
   startmonth, endmonth, initialization_method, initialization_description, physics_version, physics_description,&
   associated_model,associated_experiment,forecast_reference_time,prefix!,series!,frequency!,calendar,batch

  bt = 0.0
  ind=0
  project_id="SPECS project"
  
  write(6,*)"in specs2cmor"
  call flush(6) 
  IF (command_argument_count() /= 1) THEN
     WRITE(6,*) "Must be called with a namelist: specs2cmor <namelist>"
  ENDIF
  CALL get_command_argument( 1, namfile, status=status)
  CALL check( status, "Failed to read namelist file", namfile)
  OPEN(10, file=namfile, IOSTAT=ioe)
  READ(10, NAMEXP, IOSTAT=ioe, ERR=100)
  CLOSE(10)
!4juillet  year=startyear
  if (forcing .eq. "" ) then 
   forcing="N/A"
  endif
  if (physics_description .eq. "" ) then 
   physics_description="N/A"
  endif
  if (initialization_description .eq. "" ) then 
   initialization_description="N/A"
  endif
  if (associated_experiment .eq. "" ) then 
   associated_experiment="N/A"
  endif
  if (associated_model .eq. "" ) then 
   associated_model="N/A"
  endif

!4juillet  month=startmonth

   numyears = (endyear - startyear)
  if (startyear == endyear) then
      nmonths = endmonth - startmonth +1
   else
      nmonths = (numyears -1)*12 + (13-startmonth) + endmonth
   endif
!  write(6,*)"nmonths=",nmonths,numyears,startmonth,endmonth
!  call flush(6)
  if(nmonths.lt.1)then
   write(6,*)"nmonths < 1 , check your start/end dates coherency"
   call flush(6)
   stop 
  endif
!  write(6,*)'after =',physics_version,'-',initialization_method,'-',model_id,'-',realization,'-',experiment_id,'startyear,endyear',startyear,endyear,'nmonths=',nmonths
!  call flush(6) 
 
!  monthnum = 1 
!loop_interv: DO interv=1,4 !general loop on intervals
 DO interv=1,3!,2 !general loop on intervals
  monthnum = 1 
  year=startyear
  month=startmonth
  initialized=.false.
!  var_avail=1
  ind=0
!  ncid=0
  DO while (monthnum <= nmonths)
!to be generalized
  write(6,*)'before next_nemo file',numyears,endyear,year,month,interv
  call flush(6) 
!     CALL next_nemo_files(year, month, ncid, monthspresent,ind(interv),interv)
     CALL next_nemo_files(year, month, ncid, monthspresent,ind,interv)
!  write(6,*)'after next_nemo file',interv,"ind:",ind(interv),"id",ncid
!  call flush(6) 
!  do jj=1,6
!   if(jj.eq.6) goto 200
!   if(ind(interv).eq.1) goto 200
!  enddo !loop2 
!200 if(jj.eq.6) goto 300 
!
  IF (.NOT. initialized) THEN
        varids = -1

!        CALL read_calendar( ncid(1), calendar)
  calendar="gregorian"
!  write(6,*)'after read calendar',calendar
!  call flush(6) 

        j = CMOR_REPLACE_4
        K = CMOR_EXIT_ON_MAJOR
!write(6,*)"before setup"
!call flush(6)
!        CMOR_SPECS=1
        CMOR_PROJECT="SPECS"
        CALL check( cmor_setup( &
             inpath = 'data', &
             netcdf_file_action = j, &
             exit_control = k,&
             arg_cmor_project = CMOR_PROJECT), &
!             specs = CMOR_SPECS), &
             "cmor_setup failed")
  physics_description=trim(physics_description)
  associated_model=trim(associated_model)
  associated_experiment=trim(associated_experiment)
!  write(6,*)'after cmor_setup'!,parent_experiment_rip,'-----','experiment_id:',experiment_id
!  call flush(6) 
!  write(6,*)'before cmor_dataset',realization!,'-----','experiment_id:',experiment_id
!  call flush(6) 
        CALL check( cmor_dataset( &
             outpath=outpath, &
             experiment_id=experiment_id, &
             institution= institution, &
             institute_id= institute_id, &
             source=source, &
             calendar=calendar, &
             realization=realization, &
             contact=contact, &
             history=history, &
             comment=comment, &
             references = references, &
             model_id=model_id, &
             forcing=forcing, &    
             initialization_method=initialization_method, &
             physics_version=physics_version, &
             parent_experiment_id=parent_experiment_id, &
             project_id=project_id, &
             initialization_description=initialization_description, &
             forecast_reference_time=forecast_reference_time, &
             associated_model=trim(associated_model) , &
             associated_experiment=trim(associated_experiment) , &
             physics_description=trim(physics_description), &
             !series=series,&
             parent_experiment_rip=parent_experiment_rip), &
             "cmor_dataset() failed")

!  write(6,*)'after cmor_dataset',realization!,'-----','experiment_id:',experiment_id
!  call flush(6) 
!add grid conformity check
!      CALL read_grids(ncid(interv), & 
      CALL read_grids(ncid, & 
                      lat_vertices, long_vertices, lat_coords, long_coords,interv )

!
!create time variables
     if(ind(1).eq.1)then
!      write(6,*)"create axis and variable for Amon"
!      call flush(6)
!      CALL create_time_axis( ax_time_amon, ncid(1), 'Tables/SPECS_Amon', amon_time, amon_time_bnds, &
      CALL create_time_axis( ax_time_amon, ncid(interv), 'Tables/SPECS_Amon', amon_time, amon_time_bnds, &
                             startyear, endyear, startmonth, endmonth)
!      CALL create_variables_amon(varids, ncid(1), priority, ax_time_amon, lat_coords, long_coords)
      CALL create_variables_amon(varids, ncid(interv), priority, ax_time_amon, lat_coords, long_coords)
     endif
     if(ind(2).eq.1)then
      write(6,*)"create axis and variable for day"
      call flush(6)
!      CALL create_time_axis( ax_time_day, ncid(1), 'Tables/SPECS_day', day_time, day_time_bnds, &
      CALL create_time_axis( ax_time_day, ncid(interv), 'Tables/SPECS_day', day_time, day_time_bnds, &
                             startyear, endyear, startmonth, endmonth)!new pab
      CALL create_variables_day(varids, ncid(interv), priority, ax_time_day, lat_coords, long_coords)
     endif
     if(ind(3).eq.1)then
      write(6,*)"create axis and variable for 6hr"
      call flush(6)
!      CALL create_time_axis( ax_time_6h, ncid(1), 'Tables/SPECS_6hr', s6h_time, s6h_time_bnds, &
      CALL create_time_axis( ax_time_6h, ncid(interv), 'Tables/SPECS_6hr', s6h_time, s6h_time_bnds, &
                             startyear, endyear, startmonth, endmonth)
!      CALL create_variables_6h(varids, ncid(1), priority, ax_time_6h, lat_coords, long_coords)
      CALL create_variables_6h(varids, ncid(interv), priority, ax_time_6h, lat_coords, long_coords)
     endif

!      write(6,*)"after create axis and variable for day"!,day_time

      initialized = .TRUE.
     END IF
!write(6,*)"before output simple"
!call flush(6)
!     CALL output_simple_vars(varids, ncid(1),  amon_time, amon_time_bnds, &
     CALL output_simple_vars(varids, ncid(interv),  amon_time, amon_time_bnds, &
                             day_time, day_time_bnds, s6h_time, s6h_time_bnds, fx_time, fx_time_bnds, monthnum, monthspresent)
!  write(6,*)'after output'!,parent_experiment_rip,'-----','experiment_id:',experiment_id
!  call flush(6) 

     monthnum = monthnum + monthspresent
       
!    DO jj=1,2
     if(ind(interv).eq.1)then
      CALL close_file( ncid(interv))
     endif
!    ENDDO
     month = month + monthspresent
     do while (month > 12) 
       month = month - 12
       year = year + 1
     end do
  END DO
  CALL check(cmor_close(), "cmor_close() failed!")  
300 call flush(6)

 ENDDO !loop_interv ! end loop on intervals

  STOP

100 PRINT *,"FAILED TO READ NAMELIST" 

CONTAINS


  !> Open the files given the experiment, time.  Return the netcdf file handes.
  !@param syear,smonth  start year, month.
  !@param ncid_i, ncid_n, ncid_v, nvid_w, ncid_w, ncid_t  -  netcdf file handles.
  SUBROUTINE next_nemo_files(syear, smon, ncid, nmonths,ind_l,interv)
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: syear, smon
    INTEGER,DIMENSION(3),INTENT(INOUT)::ind_l
    INTEGER, INTENT(OUT) :: nmonths
    INTEGER,DIMENSION(3) :: ncid!, nmonths
!    INTEGER,DIMENSION(5) :: ncid!, nmonths
    CHARACTER(LEN=200),DIMENSION(3) :: file_name!,grid_name
!    CHARACTER(LEN=200) :: file_name!,grid_name
    CHARACTER(LEN=3) :: frequency
    INTEGER :: eday, emon, eyear, numyears, mn, interv
    INTEGER, DIMENSION(12) :: dayspermon = (/ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 /) 
    LOGICAL :: exists = .FALSE.
!  write(6,*)'in next nemo files',syear,smon
!  call flush(6) 

 if(interv.eq.1)then
  frequency="mon"
 elseif(interv.eq.2)then
  frequency="day"
 elseif(interv.eq.3)then
  frequency="6hr"
 endif
!write(6,*)"freq:",frequency
!call flush(6)

    ! Iterate until we reach
    ! File formats are of the type: ORCA1_MM_18500101_18501231_grid_U.nc
    ! In principle this runs off the end of 
    mn = smon
outer:    do eyear = syear,endyear
       do emon = mn,endmonth
         eday = dayspermon(emon)
  call flush(6) 
         if (isLeap(eyear) .and. (emon == 2)) eday = 29
!to be generalized
         WRITE(6,'(A,A,A1,A3,A1,I4,I2.2,A3,I4,I2.2,I2,A3)') trim(inpath),trim(prefix),'_',frequency,'_',syear,smon,'01-',eyear,emon,eday,'.nc'
         WRITE(file_name(interv),'(A,A,A1,A3,A1,I4,I2.2,A3,I4,I2.2,I2,A3)') trim(inpath),trim(prefix),'_',frequency,'_',syear,smon,'01-',eyear,emon,eday,'.nc'
!         WRITE(file_name,'(A,A,A1,A3,A1,I4,I2.2,A3,I4,I2.2,I2,A3)') trim(inpath),trim(prefix),'_',frequency,'_',syear,smon,'01-',eyear,emon,eday,'.nc'
!
         INQUIRE(FILE=file_name(interv), EXIST=exists)
!         INQUIRE(FILE=file_name, EXIST=exists)
         IF (exists)  then
          ind_l(interv)=1
    IF ( eyear * 100 + emon > endyear * 100 + endmonth)  call check(1, "File found is beyond enddate in namelist")
          exit outer
         ENDIF
       end do 
       mn = 1
    end do outer

!    if (.not. exists) then
!       write(*,*) 'DEBUG: Failed to find ', file_name(1)
!       call check( 1, "Could not find file")
!    endif
!    IF ( eyear * 100 + emon > endyear * 100 + endmonth)  call check(1, "File found is beyond enddate in namelist")

   numyears  = eyear - syear
   if (syear == eyear) then
      nmonths = emon - smon + 1
   else
      nmonths = (numyears -1)*12 + (13-smon) + emon
   endif
    

!   DO jj=1,3
!    WRITE(file_name(jj),'(A,A,A1,A3,A1,I4,I2.2,A3,I4,I2.2,I2,A3)') trim(inpath),trim(prefix),'_',frequency,'_',syear,smon,'01_',eyear,emon,eday,'.nc'
!    WRITE(file_name(interv),'(A,A,A1,A3,A1,I4,I2.2,A3,I4,I2.2,I2,A3)') trim(inpath),trim(prefix),'_',frequency,'_',syear,smon,'01_',eyear,emon,eday,'.nc'
!pab    WRITE(file_name,'(A,A,A1,A3,A1,I4,I2.2,A3,I4,I2.2,I2,A3)') trim(inpath),trim(prefix),'_',frequency,'_',syear,smon,'01_',eyear,emon,eday,'.nc'
!     INQUIRE(FILE=file_name(jj), EXIST=exists)
     INQUIRE(FILE=file_name(interv), EXIST=exists)
    write(6,*)  
     IF (exists)  then
!      ind_l(jj)=1
      ind_l(interv)=1
!      CALL open_file(ncid(interv),file_name(interv)) !jj
!      CALL open_file(ncid,file_name(interv)) !jj
!      write(6,*)"opening ",file_name(interv),"jj=",jj
      CALL open_file(ncid(interv),file_name(interv)) !jj
      write(6,*)"opening ",file_name(interv),ncid(interv)!,"jj=",jj
      call flush(6)
     ELSE
!      write(6,*)file_name(jj)," (jj=",jj,") doesn't exist"
      write(6,*)file_name(interv)," doesn't exist"
      call flush(6)
     ENDIF 

!ENDDO ! jj, loop on grids

!     write(6,*)"ind_l:",ind_l
!     call flush(6)

  END SUBROUTINE next_nemo_files


  !> Open netcdf file; return handle. Abort on failure
  !@param ncid      netcdf handle
  !@param filename  name
  SUBROUTINE open_file(ncid, filename)
    IMPLICIT NONE
    CHARACTER(len=*), INTENT(IN) :: filename
    INTEGER,INTENT(out) :: ncid
    CALL check( nf90_open(filename, nf90_nowrite, ncid), "nf90_open failed", filename)
  END SUBROUTINE OPEN_FILE

  !> Trivial wrapper to close netcdf file
  !@param ncid   file handle
  SUBROUTINE close_file(ncid)
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: ncid
    CALL check (nf90_close( ncid), "Close failed")
  END SUBROUTINE close_file


  !> Read a 1d array from a netCDF file
  !@param ncid     netcdf file handle
  !@param name     name of array. Will be ALLOCATEd; must be freed by CALLer.
  !@param array    data to return    
  SUBROUTINE read_array_1d( ncid, name, array,var_avail)
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: ncid
    INTEGER,INTENT(OUT)::var_avail
    CHARACTER(len=*), INTENT(IN) :: name
    REAL, DIMENSION(:), ALLOCATABLE :: array      
    INTEGER :: varid, len_x
    INTEGER, DIMENSION(nf90_max_var_dims) :: dimIDs


    
    var_avail=nf90_inq_varid( ncid, name, varid)

   if(var_avail.eq.0)then
    CALL check( nf90_inquire_variable(ncid, varid, dimids = dimIDs), "inquire failed", name)
    CALL check( nf90_inquire_DIMENSION(ncid, dimIDs(1), len = len_x), "inquire failed", name)
    ALLOCATE(array(len_x))
    CALL check( nf90_get_var( ncid, varid, array), "Failed to get var", name)
   else
    CALL check( var_avail, "Failed to read varid", name)
    write(6,*)"pb in create ",name," ncid",ncid
    call flush(6)
   endif
  END SUBROUTINE read_array_1d



  !> Read a 2d array from a netCDF file
  !@param ncid     netcdf file handle
  !@param name     name of array. Will be ALLOCATEd; must be freed by CALLer.
  !@param array    data to return
  !@param elm      (optional) element to retrieve from array (default = 1)
  SUBROUTINE read_array_2d( ncid, name, array, var_avail,elm)
    IMPLICIT NONE
    INTEGER, OPTIONAL :: elm
    INTEGER, INTENT(IN) :: ncid
    CHARACTER(len=*), INTENT(IN) :: name
    INTEGER,INTENT(OUT)::var_avail
    REAL, DIMENSION(:,:), ALLOCATABLE :: array      
    INTEGER :: varid, len_x, len_y
    INTEGER, DIMENSION(nf90_max_var_dims) :: dimIDs


    var_avail=nf90_inq_varid( ncid, name, varid) 
!    CALL check( nf90_inq_varid( ncid, name, varid), "Failed to read varid", name)
    CALL check( var_avail, "Failed to read varid", name)
!    write(6,*)"inq var status:",nf90_inq_varid( ncid, name, varid),nf90_strerror(nf90_inq_varid( ncid, name, varid))
!    call flush(6)
    if(var_avail.eq.0)then
!    if(nf90_inquire_variable( ncid, varid,dimids = dimIDs).eq.0)then
     CALL check( nf90_inquire_variable(ncid, varid, dimids = dimIDs), "inquire failed", name)
     CALL check( nf90_inquire_DIMENSION(ncid, dimIDs(1), len = len_x), "inquire failed", name)
     CALL check( nf90_inquire_DIMENSION(ncid, dimIDs(2), len = len_y), "inquire failed", name)
    if(allocated(array)) deallocate(array)
     ALLOCATE (array(len_x,len_y))
     if (present(elm)) then
      CALL check( nf90_get_var( ncid, varid, array, start= (/ 1 , 1, elm /)), "Failed to get var element", name)
     else 
      CALL check( nf90_get_var( ncid, varid, array), "Failed to get var", name)
     endif
    endif
  END SUBROUTINE read_array_2d

  !> Read a 3D array from netCDF file.
  !@param ncid     netcdf file handle
  !@param name     name of array. Will be ALLOCATEd; must be freed by CALLer.
  !@param array    data to return
  !@param elm      (optional) element ,elmto retrieve from array (default = 1)
  SUBROUTINE read_array_3d( ncid, name, array,var_avail,elm)
    IMPLICIT NONE
    INTEGER, OPTIONAL :: elm
    INTEGER, INTENT(IN) :: ncid
    INTEGER,INTENT(OUT) :: var_avail
    CHARACTER(len=*), INTENT(IN) :: name
    REAL, DIMENSION(:,:,:), ALLOCATABLE :: array      
    INTEGER :: varid, len_x, len_y, len_z,x_id,y_id,z_id,true_lenx,true_leny,true_lenz
    INTEGER, DIMENSION(nf90_max_var_dims) :: dimIDs

    var_avail=nf90_inq_varid( ncid, name, varid)

    CALL check( var_avail, "Failed to read varid", name)
    if(var_avail.eq.0)then
    CALL check( nf90_inquire_variable(ncid, varid, dimids = dimIDs), "inquire failed", name)
    CALL check( nf90_inquire_DIMENSION(ncid, dimIDs(1), len = len_x), "inquire failed", name)
    CALL check( nf90_inquire_DIMENSION(ncid, dimIDs(2), len = len_y), "inquire failed", name)
    CALL check( nf90_inquire_DIMENSION(ncid, dimIDs(3), len = len_z), "inquire failed", name)
    ALLOCATE (array(len_x,len_y, len_z))
!write(6,*)"dimensions3d:",len_x,len_y,len_z,"name:",name,"id:",ncid
!call flush(6)
!        CALL check(nf90_inq_dimid(ncid,"x",x_id))
!        CALL check(nf90_inq_dimid(ncid,"y",y_id))
!        CALL check(nf90_inq_dimid(ncid,"deptht",z_id))
!        CALL check(nf90_inquire_dimension(ncid,x_id,len=true_lenx))
!        CALL check(nf90_inquire_dimension(ncid,y_id,len=true_leny))
!        CALL check(nf90_inquire_dimension(ncid,z_id,len=true_lenz))
!    write(6,*)"vraies dims:",true_lenx,true_leny,true_lenz
!    call flush(6)
    if (present(elm)) then
      CALL check( nf90_get_var( ncid, varid, array, start=(/1,1,1,elm /)), "Failed to get var", name)
    else
      CALL check( nf90_get_var( ncid, varid, array), "Failed to get var", name)
    endif
   endif
  END SUBROUTINE read_array_3d


  !> Check the status of a CALL, aborting with error message IF necessary
  !@param status    Status to check. Fail IF non-zero
  !@param str       String to report
  !@param parm      optional string to SUBROUTINE.

  SUBROUTINE check(status, str, parm)
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: status
    CHARACTER(len=*), OPTIONAL, INTENT(IN) :: str, parm
    IF (status /= 0) THEN
       write(6,*)"error:",nf90_strerror(status)
       IF (present(str)) THEN
          IF (present(parm)) THEN
             WRITE(6,*) str, " : ", parm
          ELSE
             WRITE(6,*) str
          ENDIF
       ENDIF
!       CALL abort
    ENDIF
  END SUBROUTINE check

  !> Generate depth-axis from coordinate in netcdf file
  !@param axis_id   returned handle
  !@param ncid      netcdf file handle
  !@param varname   name of depth coordinate in netcdf file
  !@param table     SPECS table
  SUBROUTINE create_depth_axis(axis_id, ncid, varname, table)
    IMPLICIT NONE
    INTEGER, INTENT(OUT) :: axis_id
    INTEGER, INTENT(IN)  :: ncid
    INTEGER ::var_avail
    CHARACTER(len=*) :: varname, table
    REAL, DIMENSION(:), ALLOCATABLE :: depth, depth_bnds
    INTEGER :: i, sz

    axis_id=1
!    write(6,*)"call read array1d in create depth axis",ncid,varname
!    call flush(6)
    CALL read_array_1d( ncid, varname, depth,var_avail)      
    
    !  boundaries of the depth cells are half-way between depth points.
    ALLOCATE(depth_bnds( size(depth)+1))
    depth_bnds(1) = 0.
    sz = size(depth)
    if(sz.ge.2)then
    do i=1, sz-1
       depth_bnds(i+1) = (depth(i) +depth(i+1) )/2
    END do
    depth_bnds(sz+1) =  5500. ! Max depth
    axis_id = cmor_axis( &
         table=table, & 
         table_entry='plev', &
!         table_entry='plevs', &
         units='Pa', &
         length=sz, &
         coord_vals=depth)!, &
!         cell_bounds=depth_bnds)
    endif 
  END SUBROUTINE create_depth_axis


  !> Read the grids from the files. Calculate cell boundaries
  SUBROUTINE  read_grids(ncid, &
                         lat_vertices, long_vertices, lat_coords, long_coords,interv)
    IMPLICIT NONE
!    INTEGER, INTENT(IN) :: ncid
    INTEGER,DIMENSION(3), INTENT(IN) :: ncid
    INTEGER, INTENT(IN) :: interv
    real, intent(out),  dimension(:,:,:), ALLOCATABLE :: lat_vertices, long_vertices
    real, intent(out), dimension(:,:), ALLOCATABLE :: lat_coords, long_coords
    REAL, DIMENSION(:,:), ALLOCATABLE:: longs, lats 
!    REAL, DIMENSION(sy,sx):: longs, lats 
    REAL, DIMENSION(:), ALLOCATABLE :: longs1d, lats1d 
    INTEGER::var_avail,varidlon,varidlat
    INTEGER, DIMENSION(nf90_max_var_dims) :: dimIDslon,dimIDslat

  CALL  check( nf90_inq_varid( ncid(interv),'lon',varidlon))
  CALL  check( nf90_inq_varid( ncid(interv),'lat',varidlat))
  CALL check( nf90_inquire_variable(ncid(interv), varidlon, dimids = dimIDslon), "inquire failed", "nav_lon")
  CALL check( nf90_inquire_DIMENSION(ncid(interv), dimIDslon(1), len = sy), "inquire failed", "nav_lat")
  CALL check( nf90_inquire_variable(ncid(interv), varidlat, dimids = dimIDslat), "inquire failed", "nav_lon")
  CALL check( nf90_inquire_DIMENSION(ncid(interv), dimIDslat(1), len = sx), "inquire failed", "nav_lon")
 write(6,*)"in read_grids",sx,sy
 call flush(6)
!    CALL read_array_1d(ncid(1), 'lon', longs1d,var_avail)
!    CALL read_array_1d(ncid(1), 'lat', lats1d,var_avail)
   CALL read_array_1d(ncid(interv), 'lon', longs1d,var_avail)
    CALL read_array_1d(ncid(interv), 'lat', lats1d,var_avail)
if(.not.allocated(longs)) allocate(longs(sy,sx))
    do i=1,sy
    longs(i,:)=longs1d(i)
    enddo
if(.not.allocated(lats)) allocate(lats(sy,sx))
    do i=1,sx
    lats(:,i)=lats1d(i)
!    lats(:,i)=lats1d(sx-i+1)
    enddo
!    CALL read_array_2d(ncid(1), 'lon', longs,var_avail)
!    CALL read_array_2d(ncid(1), 'lat', lats,var_avail)
!    CALL read_array_1d(ncid(3), 'depthv', depths_v,var_avail)
    ! Don't have negative longitudes. 
    WHERE (longs < 0.) longs = longs + 360.
    if(.not.allocated(lat_vertices)) allocate(lat_vertices(4,sy,sx))
    lat_vertices(1,:,:) = lats
    lat_vertices(2,:,:) = lats
    lat_vertices(3,:,2:sx) = lats(:,1:sx-1)
    lat_vertices(4,:,2:sx) = lats(:,1:sx-1)
    DEALLOCATE(longs1d,lats1d)
    if(.not.allocated(long_vertices)) allocate(long_vertices(4,sy,sx))
    long_vertices(1,:,:) = longs
    long_vertices(4,:,:) = longs
    long_vertices(2,1,:) = longs(sy,:)
    long_vertices(3,1,:) = longs(sy,:)
    long_vertices(2,2:sy,:) = longs(1:sy-1,:)
    long_vertices(3,2:sy,:) = longs(1:sy-1,:)

!to be checked according to variable cell method chosen
    lat_vertices(3,:,1) = -90.
    lat_vertices(4,:,1) = -90.

    !  Now calculate cell boundaries.
    if(.not.allocated(long_coords)) allocate(long_coords(sy,sx))
    if(.not.allocated(lat_coords)) allocate(lat_coords(sy,sx))

    long_coords = longs
    lat_coords = lats
    
!     
  if(ALLOCATED(longs1d)) DEALLOCATE(longs1d)
  if(ALLOCATED(lats1d)) DEALLOCATE(lats1d)

  END SUBROUTINE   
 
  !> Generate grid.
  !@param axis_id    Id of axis generated
!to be generalized
  SUBROUTINE create_grid(grid, lat_coords, long_coords, lat_id, lon_id)
    IMPLICIT NONE
    INTEGER, INTENT(OUT) :: grid
    REAL, DIMENSION(:,:) :: lat_coords, long_coords
    INTEGER :: lat_id, lon_id
    INTEGER :: i
    INTEGER, DIMENSION(sy) :: i_indices
    INTEGER, DIMENSION(sx) :: j_indices

    do i=1,sx
     j_indices(i) = sx-i+1
!     j_indices(i) = i
    end do
    do i=1,sy
     i_indices(i) = i
    end do
    lon_id = cmor_axis( table = 'Tables/SPECS_grids', &
            table_entry='i_index',  units='1', &
            length=sy,  coord_vals = i_indices)
    lat_id = cmor_axis( table = 'Tables/SPECS_grids', &
            table_entry='j_index',  units='1', &
            length=sx, coord_vals = j_indices)
!    lon_id = cmor_axis( table = 'Tables/SPECS_grids', &
!            table_entry='longitude',  units='degrees_east', &
!            length=sy,  coord_vals = long_coords)
!    lat_id = cmor_axis( table = 'Tables/SPECS_grids', &
!            table_entry='latitude',  units='degrees_north', &
!            length=sx, coord_vals = lat_coords)
   grid = cmor_grid( (/lon_id, lat_id/), &
           latitude = lat_coords, &
           longitude = long_coords, & 
           latitude_vertices = lat_vertices, &
           longitude_vertices = long_vertices) 
    ! DEALLOCATE(lon, lat)

  END SUBROUTINE create_grid

  !> Read time axis details. 
  ! There are two time axes: those in the 3d fields (eg t.nc)
  ! and the 2d ice fields. Assumed to have the same time origin, but different 
  ! intervals and number of timesteps.
  !
  !@param ncid   Handle of netcdf file
  !@param calendar Calendar used. Normally gregorian
  SUBROUTINE read_calendar(ncid, calendar)
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: ncid
    CHARACTER(len=80), INTENT(OUT) :: calendar
    INTEGER :: varid
!if(ecearth.eq.2)then
    CALL check( nf90_inq_varid( ncid, 'time', varid), "Failed to read varid for time11111")   
!else
!    CALL check( nf90_inq_varid( ncid, 'time_counter', varid), "Failed to read varid for time11111")   
!endif
!    CALL check( nf90_inq_varid( ncid, 'reftime', varid), "Failed to read varid for time")   
    CALL check( nf90_get_att( ncid, varid, 'calendar', calendar), "Failed to get calendar")

  END SUBROUTINE read_calendar

   ! Taken from NEMO source
   LOGICAL FUNCTION isLeap(nyear)
   INTEGER, INTENT(in) :: nyear
   isLeap = ( (Modulo(nyear,4) == 0 .AND. Modulo(nyear,100) /= 0) .OR. Modulo(nyear,400) == 0 )
   RETURN
   END FUNCTION isLeap

  !> Create a time axis.
  !@param type 'ice' or 'oce', depending on ncid 
  SUBROUTINE create_time_axis( ax_time, ncid_scal, table, time, time_bnds, startyear, endyear, startmonth, endmonth)
    IMPLICIT NONE
    INTEGER, INTENT(OUT) :: ax_time
    INTEGER, INTENT(IN) :: ncid_scal, startyear, endyear, startmonth, endmonth
    REAL, DIMENSION(12) :: dayspermon = (/ 31., 28., 31., 30., 31., 30., 31., 31., 30., 31., 30., 31. /)
    REAL, INTENT(OUT), DIMENSION(:), ALLOCATABLE :: time
    REAL, INTENT(OUT), DIMENSION(:,:), ALLOCATABLE :: time_bnds
    CHARACTER(len=*), INTENT(IN) :: table
    CHARACTER(len=80) :: units    
    DOUBLE PRECISION :: prevt

    INTEGER :: varid, votemp_varid, ice_varid, m, y, d, i, nmonths, numyears,nmonths_b,numyears_b,length
    REAL :: interval_operation, interval_write
!if(ecearth.eq.2)then
    CALL check( nf90_inq_varid( ncid_scal, 'time', varid), "Failed to read varid for time1")   
!else
!    CALL check( nf90_inq_varid( ncid_scal, 'time_counter', varid), "Failed to read varid for time1")   
!endif
!    CALL check( nf90_inq_varid( ncid, 'reftime', varid), "Failed to read varid for time create")   
    CALL check( nf90_get_att( ncid_scal, varid, 'units', units), "Failed to read units in read_time")
    CALL check( nf90_inquire_dimension( ncid_scal, varid, len=length), "Failed to read units in read_time")

    numyears = (endyear - 1850)
!    numyears = (endyear - startyear)
!    if (startyear == endyear) then
!    if (endyear == 1850) then
!       nmonths = endmonth - startmonth +1
!    else
!       nmonths = (numyears -1)*12 + (13-startmonth) + endmonth 
!    endif

    numyears_b = (startyear - 1850)
    numyears = (endyear - startyear)
!    if (startyear == endyear) then
    if (startyear == endyear) then
       nmonths = endmonth - startmonth + 1
    else
       nmonths = (numyears -1)*12 + (13-startmonth) + endmonth
    endif
    if (startyear == 1850) then
       nmonths_b = startmonth
    else
       nmonths_b = (numyears_b -1)*12 + (13-startmonth)
    endif


!    write(6,*)"in create time_axis,nmonths=",nmonths,length
!    call flush(6)
    ALLOCATE (time(nmonths),  time_bnds(2,nmonths))
    prevt = 0.
!    y = startyear
!    m = startmonth
    y = 1850
    m = 1
    do i=1,nmonths_b
         d = dayspermon(m)
         if ((m == 2) .and. isLeap(y)) d=29
!         time_bnds(1,i) = prevt
!         time_bnds(2,i) = prevt + d*24.*3600.
!         time(i) = ( time_bnds(2,i) - time_bnds(1,i)) / 2. + time_bnds(1,i)
 !        prevt = time_bnds(2,i)
         prevt=prevt + d*24.*3600.
         m = m+1
         if (m == 13) then
           y = y+1
           m = 1
         endif
     end do
     time=prevt

    ! read the interval from one of the variables    
!    IF (typ == 'oce') THEN
!!       CALL check( nf90_inq_varid( ncid, 'thetao', votemp_varid))
!       CALL check( nf90_inq_varid( ncid_scal, 'votemper', votemp_varid))
!       CALL check( nf90_get_att( ncid_scal, votemp_varid, 'interval_operation', interval_operation))
!       CALL check( nf90_get_att( ncid_scal, votemp_varid, 'interval_write', interval_write ))    
!    ELSE
!       ! Ice on a different timescale.
!       CALL check( nf90_inq_varid( ncid_scal, 'iicethic',ice_varid))
!       CALL check( nf90_get_att( ncid_scal, ice_varid, 'interval_operation', interval_operation))
!       CALL check( nf90_get_att( ncid_scal, ice_varid, 'interval_write', interval_write))
!    ENDIF
!    WRITE(interval,'(F10.2)') abs(interval_write)

    ! interval is the sampling period; eg '3600 seconds' for monthly mean data
    ! means the data was sampled every hour, then averaged to monthly
!    write(6,*)'before cmor_axis in create_time_axis ',units
!    call flush(6)
    ax_time = cmor_axis(table = table, &
         table_entry='time', &
!         units = 'days since 1960-1-1', &
         units = units, &
         length = length, &
!         length = size(time))!, &
         interval = "6.") 
    write(6,*)'before cmor_axis in create_time_axis',units
    call flush(6)

  END SUBROUTINE CREATE_TIME_AXIS

  !> Simple 2d variables 
  !> @param monthnum : current month
  !> @param months   : number of months in file, to process
  SUBROUTINE trans2d( varid, lt, nam, ncid, time, time_bnds, monthnum, months,fx)!,var_avail)
    INTEGER, INTENT(IN) :: varid, ncid, monthnum, months,lt!,var_avail
    DOUBLE PRECISION, INTENT(IN), DIMENSION(:), ALLOCATABLE :: time
    DOUBLE PRECISION, INTENT(IN), DIMENSION(:,:), ALLOCATABLE :: time_bnds
    DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: time_bnds2
    CHARACTER(LEN=2), INTENT(IN), OPTIONAL :: fx
    REAL, DIMENSION(:,:), ALLOCATABLE :: dat
    CHARACTER(len=*), INTENT(IN) :: nam
    DOUBLE PRECISION, DIMENSION(1) :: t,time2
    DOUBLE PRECISION, DIMENSION(2,1) :: tb
    DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: t2
    INTEGER :: i,j,nt,var_avail,var_avail2
    
!    write(6,*)"in trans2d ",nam
!    call flush(6)
    if(present(fx))then
     nt=0
    else
     nt=1
    endif
    j = 1
       CALL read_array_1d( ncid, "time", t2,var_avail2)
       CALL create_time_bounds(t2,time_bnds2)
!    DO i=monthnum, monthnum + months -1
!       CALL read_array_2d( ncid, nam, dat,var_avail)
    DO i=1,size(t2)
       CALL read_array_2d( ncid, nam, dat,var_avail,i)
     if(var_avail.eq.0)then
       t = time(1)
       time2 = t2(i) 
!       write(6,*)"avant cmorWrite (2d): t= ",t,"--",time2
       tb(1,1) = time_bnds2(1,i)
       tb(2,1) = time_bnds2(2,i)
       CALL check( cmor_write( var_id = varid, &
!         data = dat, &
         data = dat, &
         ntimes_passed = nt, &
         time_vals = t+time2, &
         leadtime_vals = t, &
         time_bnds = tb ) )
       DEALLOCATE(dat)
       j = j + 1
     endif
    END DO
    var_avail=1
  END SUBROUTINE trans2d

  !> Translate Simple 3d variables
  !> @param monthnum : current month
  !> @param months   : number of months in file, to process
  SUBROUTINE trans3d (varid, lt, nam, ncid, time, time_bnds, monthnum, months,fx)
    INTEGER, INTENT(IN) :: varid, ncid, monthnum, months,lt
    DOUBLE PRECISION, INTENT(IN), DIMENSION(:), ALLOCATABLE :: time
    DOUBLE PRECISION, INTENT(IN), DIMENSION(:,:), ALLOCATABLE :: time_bnds
    DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: time_bnds2
    CHARACTER(len=*), INTENT(IN) :: nam
    CHARACTER(LEN=2), INTENT(IN), OPTIONAL :: fx

    DOUBLE PRECISION :: prevt
    REAL, DIMENSION(:,:,:), ALLOCATABLE :: dat
    DOUBLE PRECISION, DIMENSION(1) :: t,time2
    DOUBLE PRECISION, DIMENSION(2,1) :: tb
    INTEGER :: i,j,nt,numAtts,var_avail,var_avail2
    DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: t2

    if(present(fx))then
     nt=0
    else
     nt=1
    endif
    j=1
       CALL read_array_1d( ncid, "time", t2,var_avail2)
       CALL create_time_bounds(t2,time_bnds2)
!       CALL read_array_3d( ncid, nam, dat,var_avail)
    DO i=1,size(t2)
!    DO i=monthnum, monthnum + months -1
       ! Write a single step
      CALL read_array_3d( ncid, nam, dat,var_avail,i)
      if(var_avail.eq.0)then 
       t = time(1)
       time2 = t2(i)
       tb(1,1) = time_bnds2(1,i)
       tb(2,1) = time_bnds2(2,i)

       CALL check( cmor_write( var_id = varid, &
            data = dat, &
            ntimes_passed = nt, &
            time_vals = t+time2, &
            leadtime_vals = t, &
            time_bnds = tb))
       DEALLOCATE(dat)
       j=j+1
     endif
    END DO
  var_avail=1
  END SUBROUTINE trans3d

  !> Create all the necessary variables for SPECS_day table
  !> da: daily mean ocean fields
  !> Not currently used in EC-EARTH/

  SUBROUTINE create_variables_day( varids, ncid_t, priority, ax_time, lat_coords, long_coords)
    IMPLICIT NONE
    INTEGER, INTENT(INOUT),  DIMENSION(:) :: varids
    INTEGER, INTENT(IN) :: ncid_t, priority, ax_time
    INTEGER :: grid, dum1, dum2, ax_depth !add pab 
    REAL, DIMENSION(:,:) :: lat_coords, long_coords

    CALL create_grid(grid, lat_coords, long_coords, dum1, dum2)
    CALL create_depth_axis(ax_depth, ncid_t, 'lev', 'Tables/SPECS_day')
!write(6,*)"in create varibales day-after create depth axis-deptht"
!call flush(6)
!     varids(da_lt) = cmor_variable( &
!      table='Tables/SPECS_day', &
!      table_entry='leadtime', &             ! sea ice fraction
!      units='days', &
!      axis_ids = (/ ax_time /))
    varids(da_pr) = cmor_variable( &
         table='Tables/SPECS_day', & !new pab
         table_entry='pr', &             ! sea ice fraction
         axis_ids = (/ grid, ax_time /), &
         units = 'kg m-2 s-1', &
         original_name='TP')
    varids(da_rsds) = cmor_variable( &
         table='Tables/SPECS_day', & !new pab
         table_entry='rsds', &             ! sea ice fraction
         axis_ids = (/ grid, ax_time /), &
         units = 'W m-2', &
         positive = 'up', &
         original_name='SSRD')
    varids(da_rls) = cmor_variable( &
         table='Tables/SPECS_day', & !new pab
         table_entry='rls', &             ! sea ice fraction
         axis_ids = (/ grid, ax_time /), &
         units = 'W m-2', &
!         positive = 'up', &
         original_name='STR')
    varids(da_rlut) = cmor_variable( &
         table='Tables/SPECS_day', & !new pab
         table_entry='rlut', &             ! sea ice fraction
         axis_ids = (/ grid, ax_time /), &
         positive = 'up', &
         units = 'W m-2', &
         original_name='TTR')
!    varids(da_ta) = cmor_variable( &
!         table='Tables/SPECS_day', & !new pab
!         table_entry='ta', &             ! sea ice fraction
!         axis_ids = (/ grid, ax_depth, ax_time /), &
!         units = 'K', &
!         original_name='T')
    varids(da_tasmax) = cmor_variable( &
         table='Tables/SPECS_day', &
         table_entry = 'tasmax', &           ! sea surface temperature
         axis_ids = (/ grid, ax_time /), &
         units = 'K', &
         original_name='MX2T')
    varids(da_tasmin) = cmor_variable( &
         table='Tables/SPECS_day', &
         table_entry = 'tasmin', &           ! sea surface temperature
         axis_ids = (/ grid, ax_time /), &
         units = 'K', &
         original_name='MN2T')
    varids(da_zg) = cmor_variable( &
         table='Tables/SPECS_day', &
         table_entry='zg', &              ! sea water x velocity
         axis_ids = (/ grid, ax_depth, ax_time /), &
         units = 'm', &
         original_name = 'Z')

  END SUBROUTINE CREATE_VARIABLES_DAY


  SUBROUTINE create_variables_6h( varids, ncid_t, priority, ax_time, lat_coords, long_coords)
    IMPLICIT NONE
    INTEGER, INTENT(INOUT),  DIMENSION(:) :: varids
    INTEGER, INTENT(IN) :: ncid_t, priority, ax_time
    INTEGER :: grid, dum1, dum2, ax_depth !add pab 
    REAL, DIMENSION(:,:) :: lat_coords, long_coords

    CALL create_grid(grid, lat_coords, long_coords, dum1, dum2)
    CALL create_depth_axis(ax_depth, ncid_t, 'lev', 'Tables/SPECS_6hr')

!write(6,*)"in create varibales 6h-after create depth axis-deptht"
!call flush(6)

!     varids(s6h_lt) = cmor_variable( &
!      table='Tables/SPECS_6hr', &
!      table_entry='leadtime', &             ! sea ice fraction
!      units='days', &
!      axis_ids = (/ ax_time /))
    varids(s6h_psl) = cmor_variable( &
         table='Tables/SPECS_6hr', & !new pab
         table_entry='psl', &             ! sea ice fraction
         axis_ids = (/ grid, ax_time /), &
         units = 'Pa', &
         original_name='MSL')
    varids(s6h_tas) = cmor_variable( &
         table='Tables/SPECS_6hr', & !new pab
         table_entry='tas', &             ! sea ice fraction
         axis_ids = (/ grid, ax_time /), &
         units = 'K', &
         original_name='T2M')
    varids(s6h_tdps) = cmor_variable( &
         table='Tables/SPECS_6hr', & !new pab
         table_entry='tdps', &             ! sea ice fraction
         axis_ids = (/ grid, ax_time /), &
         units = 'K', &
         original_name='D2M')
    varids(s6h_clt) = cmor_variable( &
         table='Tables/SPECS_6hr', & !new pab
         table_entry='clt', &             ! sea ice fraction
         axis_ids = (/ grid, ax_time /), &
         units = '', &
         original_name='TCC')
    varids(s6h_uas) = cmor_variable( &
         table='Tables/SPECS_6hr', & !new pab
         table_entry='uas', &             ! sea ice fraction
         axis_ids = (/ grid, ax_time /), &
         units = 'm s-1', &
         original_name='10U')
    varids(s6h_vas) = cmor_variable( &
         table='Tables/SPECS_6hr', & !new pab
         table_entry='vas', &             ! sea ice fraction
         axis_ids = (/ grid, ax_time /), &
         units = 'm s-1', &
         original_name='10V')

  END SUBROUTINE CREATE_VARIABLES_6h
 
  !> Create all the necessary variables for SPECS_Amon table
  !> Amon: Monthly ocean fields
  !
  ! Skip the biogeochemical fields, Table 2.1

  SUBROUTINE create_variables_amon( varids, ncid_t, priority, ax_time, lat_coords, long_coords)
!idem: to be checked according to updated tables
    IMPLICIT NONE
    INTEGER, INTENT(INOUT),  DIMENSION(:) :: varids
    INTEGER, INTENT(IN) :: ncid_t, priority, ax_time
    INTEGER :: grid, ax_depth, ax_basin, ax_rho, ax_lat, ax_lon, ax_lt
    REAL, DIMENSION(:,:) :: lat_coords, long_coords
    REAL, DIMENSION(:), ALLOCATABLE :: lt

    CALL create_grid(grid, lat_coords, long_coords, ax_lat, ax_lon)
!    write(6,*)"before create_depth_axis in create_variable_amon"
!    call flush(6)
    CALL create_depth_axis(ax_depth, ncid_t, 'lev', 'Tables/SPECS_Amon')
!    write(6,*)"after create_depth_axis in create_variable_amon"
!    call flush(6)

!    ax_basin = cmor_axis( table='Tables/SPECS_Amon', &
!         table_entry='basin', &
!         length=4, &
!         coord_vals= (/ "atlantic_arctic_ocean", "indian_pacific_ocean ", "pacific_ocean        ", &
!         "global_ocean         " /), &
!         units='none')         

! varids(mon_lt) = cmor_variable( &
!      table='Tables/SPECS_Amon', &
!      table_entry='leadtime', &             ! sea ice fraction
!      units='days', &
!      axis_ids = (/ ax_time /))

    varids(amon_tas) = cmor_variable( &
         table='Tables/SPECS_Amon', &
         table_entry = 'tas', &        ! sea water potential temperature
         axis_ids = (/ grid, ax_time /), &
         units = 'K', &
         original_name='T2M')
    varids(amon_tasmax) = cmor_variable( &
         table='Tables/SPECS_Amon', &
         table_entry = 'tasmax', &           ! sea surface temperature
         axis_ids = (/ grid, ax_time /), &
         units = 'K', &
         original_name='MX2T')
    varids(amon_tasmin) = cmor_variable( &
         table='Tables/SPECS_Amon', &
         table_entry = 'tasmin', &           ! sea surface temperature
         axis_ids = (/ grid, ax_time /), &
         units = 'K', &
         original_name='MN2T')
    varids(amon_rls) = cmor_variable( &
         table='Tables/SPECS_Amon', & !new pab
         table_entry='rls', &             ! sea ice fraction
         axis_ids = (/ grid, ax_time /), &
         units = 'W m-2', &
!         positive = 'up', &
         original_name='STR')
   varids(amon_uas) = cmor_variable( &
         table='Tables/SPECS_Amon', &
         table_entry = 'uas', &           ! sea surface salinity
         axis_ids = (/ grid, ax_time /), &
         units = 'm s-1', &
         original_name='U10M')
   varids(amon_vas) = cmor_variable( &
         table='Tables/SPECS_Amon', &
         table_entry = 'vas', &           ! sea surface salinity
         axis_ids = (/ grid, ax_time /), &
         units = 'm s-1', &
         original_name='V10M')
    varids(amon_psl) = cmor_variable( &
         table='Tables/SPECS_Amon', &
         table_entry='psl', &             ! sea surface height above geoid
         axis_ids = (/ grid, ax_time /), &
         units = 'Pa', &
         original_name ='MSL')
    varids(amon_pr) = cmor_variable( & ! FIXME  check.
         table='Tables/SPECS_Amon', & ! sobowlin is "bowl index", 
         table_entry='pr', &
         axis_ids = (/ grid, ax_time /), &
         units ='kg m-2 s-1', &
         original_name = 'TP')
    varids(amon_clt) = cmor_variable( & ! FIXME  check.
         table='Tables/SPECS_Amon', & ! sobowlin is "bowl index", 
         table_entry='clt', &
         axis_ids = (/ grid, ax_time /), &
         units ='1', &
         original_name = 'TCC')
    varids(amon_hfss) = cmor_variable( & ! FIXME  check.
         table='Tables/SPECS_Amon', & ! sobowlin is "bowl index", 
         table_entry='hfss', &
         axis_ids = (/ grid, ax_time /), &
         units ='W m-2', &
         positive = 'up', &
         original_name = 'SSHF')
    varids(amon_hfls) = cmor_variable( & ! FIXME  check.
         table='Tables/SPECS_Amon', & ! sobowlin is "bowl index", 
         table_entry='hfls', &
         axis_ids = (/ grid, ax_time /), &
         units ='W m-2', &
         positive = 'up', &
         original_name = 'SLHF')
    varids(amon_rsds) = cmor_variable( & ! FIXME  check.
         table='Tables/SPECS_Amon', & ! sobowlin is "bowl index", 
         table_entry='rsds', &
         axis_ids = (/ grid, ax_time /), &
         units ='W m-2', &
         positive = 'up', &
         original_name = 'SSRD')
    varids(amon_snld) = cmor_variable( & ! FIXME  check.
         table='Tables/SPECS_Amon', & ! sobowlin is "bowl index", 
         table_entry='snld', &
         axis_ids = (/ grid, ax_time /), &
         units ='m', &
         original_name = 'SD')
    varids(amon_tdps) = cmor_variable( & ! FIXME  check.
         table='Tables/SPECS_Amon', & ! sobowlin is "bowl index", 
         table_entry='tdps', &
         axis_ids = (/ grid, ax_time /), &
         units ='K', &
         original_name = 'D2M')
    varids(amon_rlut) = cmor_variable( & ! FIXME  check.
         table='Tables/SPECS_Amon', & ! sobowlin is "bowl index", 
         table_entry='rlut', &
         axis_ids = (/ grid, ax_time /), &
         units ='W m-2', &
         positive = 'up', &
         original_name = 'TTR')
    varids(amon_rss) = cmor_variable( & ! FIXME  check.
         table='Tables/SPECS_Amon', & ! sobowlin is "bowl index", 
         table_entry='rss', &
         axis_ids = (/ grid, ax_time /), &
         units ='W m-2', &
!         positive = 'up', &
         original_name = 'SSR')
    varids(amon_al) = cmor_variable( & ! FIXME  check.
         table='Tables/SPECS_Amon', & ! sobowlin is "bowl index", 
         table_entry='al', &
         axis_ids = (/ grid, ax_time /), &
         units ='%', &
         original_name = 'FAL')
!    varids(amon_fal) = cmor_variable( &
!         table='Tables/SPECS_Amon', & !new pab
!         table_entry='al', &             ! sea ice fraction
!         axis_ids = (/ grid, ax_time /), &
!         units = '%', &
!         original_name='FAL')
    varids(amon_zg) = cmor_variable( &
         table='Tables/SPECS_Amon', &
         table_entry='zg', &              ! sea water x velocity
         axis_ids = (/ grid, ax_depth, ax_time /), &
         units = 'm', &
         original_name = 'Z')
    varids(amon_ta) = cmor_variable( &
         table='Tables/SPECS_Amon', &
         table_entry='ta', &              ! sea water x velocity
         axis_ids = (/ grid, ax_depth, ax_time /), &
         units = 'K', &
         original_name = 'T')
    varids(amon_hus) = cmor_variable( &
         table='Tables/SPECS_Amon', &
         table_entry='hus', &              ! sea water x velocity
         axis_ids = (/ grid, ax_depth, ax_time /), &
         units = 'kg kg-1', &
         original_name = 'Q')
END SUBROUTINE create_variables_amon

!> Output simple variables
!> @param monthnum current month, simple counter
!> @param month    number of months present in files to read
SUBROUTINE output_simple_vars (varids, ncid_t,amon_time, amon_time_bnds, day_time, day_time_bnds, s6h_time, s6h_time_bnds, fx_time, fx_time_bnds, monthnum, months) ! new pab
!SUBROUTINE output_simple_vars (varids, ncid_t, ncid_i, oimon_time, oimon_time_bnds,  amon_time, amon_time_bnds, monthnum, months)
 IMPLICIT NONE
 INTEGER, INTENT(IN), DIMENSION(:) :: varids
 INTEGER, INTENT(IN) :: ncid_t,monthnum, months
 DOUBLE PRECISION, INTENT(IN), DIMENSION(:), ALLOCATABLE :: amon_time, day_time, s6h_time, fx_time
 DOUBLE PRECISION, INTENT(IN), DIMENSION(:,:), ALLOCATABLE :: amon_time_bnds, day_time_bnds, s6h_time_bnds, fx_time_bnds
 INTEGER::jj
!to be checked according to new variables names

if(ind(1).eq.1)then
!write(6,*)"in create output mon"
!call flush(6)
 CALL trans3d( varids(amon_zg), varids(mon_lt), 'Z', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_thetao))
 CALL trans3d( varids(amon_ta), varids(mon_lt), 'T', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_thetao))
 CALL trans3d( varids(amon_hus), varids(mon_lt), 'Q', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_thetao))
 CALL trans2d( varids(amon_tas), varids(mon_lt), 'T2M', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_tasmax), varids(mon_lt), 'MX2T', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_tasmin), varids(mon_lt), 'MN2T', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_uas), varids(mon_lt), 'U10M', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_vas), varids(mon_lt), 'V10M', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_psl), varids(mon_lt), 'MSL', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_pr), varids(mon_lt), 'TP', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_clt), varids(mon_lt), 'TCC', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
! CALL trans2d( varids(amon_fal), varids(mon_lt), 'FAL', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
!write(6,*)"in create output mon, before SSHF"
!call flush(6)
 CALL trans2d( varids(amon_hfss), varids(mon_lt), 'SSHF', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
!write(6,*)"in create output mon, after SSHF"
!call flush(6)
 CALL trans2d( varids(amon_hfls), varids(mon_lt), 'SLHF', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
!write(6,*)"in create output mon, after SLHF"
!call flush(6)
 CALL trans2d( varids(amon_rsds), varids(mon_lt), 'SSRD', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
!write(6,*)"in create output mon, after RSDS"
!call flush(6)
 CALL trans2d( varids(amon_snld), varids(mon_lt), 'SD', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_tdps), varids(mon_lt), 'D2M', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_rlut), varids(mon_lt), 'TTR', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_al), varids(mon_lt), 'FAL', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_rss), varids(mon_lt), 'SSR', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(amon_rls), varids(mon_lt), 'STR', ncid_t, amon_time,  amon_time_bnds,monthnum, months)!,varids(da_t20d))
!write(6,*)"end create output mon"
!call flush(6)
endif

if(ind(2).eq.1)then
!write(6,*)"in create output day2"
!call flush(6)
 CALL trans2d( varids(da_rsds), varids(da_lt), 'SSRD', ncid_t, day_time,  day_time_bnds,monthnum, months)!,varids(da_t20d))
!write(6,*)"in create output day3"
!call flush(6)
 CALL trans2d( varids(da_rls), varids(da_lt), 'STR', ncid_t, day_time,  day_time_bnds,monthnum, months)!,varids(da_t20d))
!write(6,*)"in create output day4"
!call flush(6)
 CALL trans3d( varids(da_ta), varids(da_lt), 'T', ncid_t, day_time,  day_time_bnds,monthnum, months)!,varids(da_t20d))
 CALL trans2d( varids(da_rlut), varids(da_lt), 'TTR', ncid_t, day_time,  day_time_bnds,monthnum, months)!,varids(da_t20d))
!write(6,*)"end create output day"
!call flush(6)
 CALL trans2d( varids(da_tasmax), varids(da_lt), 'MX2T', ncid_t, day_time,  day_time_bnds,monthnum, months)!,varids(amon_tos))
 CALL trans2d( varids(da_tasmin), varids(da_lt), 'MN2T', ncid_t, day_time,  day_time_bnds,monthnum, months)!,varids(amon_tos))
!write(6,*)"in create output day"
 CALL trans2d( varids(da_pr), varids(da_lt), 'TP', ncid_t, day_time,  day_time_bnds,monthnum, months)!,varids(da_mlotst))
 CALL trans3d( varids(da_zg), varids(da_lt), 'Z', ncid_t, day_time,  day_time_bnds,monthnum, months)!,varids(amon_thetao))
call flush(6)
endif
if(ind(3).eq.1)then
!write(6,*)"in create output 6h"
!call flush(6)
 CALL trans2d( varids(s6h_psl), varids(da_lt), 'MSL', ncid_t, s6h_time,  s6h_time_bnds,monthnum, months)!,varids(da_mlotst))
 CALL trans2d( varids(s6h_tas), varids(da_lt), 'T2M', ncid_t, s6h_time,  s6h_time_bnds,monthnum, months)!,varids(da_t20d))
 CALL trans2d( varids(s6h_tdps), varids(da_lt), 'D2M', ncid_t, s6h_time,  s6h_time_bnds,monthnum, months)!,varids(da_t20d))
 CALL trans2d( varids(s6h_clt), varids(da_lt), 'TCC', ncid_t, s6h_time,  s6h_time_bnds,monthnum, months)!,varids(da_t20d))
 CALL trans2d( varids(s6h_uas), varids(da_lt), 'U10M', ncid_t, s6h_time,  s6h_time_bnds,monthnum, months)!,varids(da_t20d))
 CALL trans2d( varids(s6h_vas), varids(da_lt), 'V10M', ncid_t, s6h_time,  s6h_time_bnds,monthnum, months)!,varids(da_t20d))
!write(6,*)"end create output 6h"
!call flush(6)
endif

END SUBROUTINE OUTPUT_SIMPLE_VARS

SUBROUTINE create_time_bounds(time,time_bounds)

 IMPLICIT NONE
 DOUBLE PRECISION, INTENT(IN), DIMENSION(:) :: time
 DOUBLE PRECISION, INTENT(OUT), DIMENSION(:,:),ALLOCATABLE :: time_bounds
 INTEGER :: i

! write(6,*)"in create tb",size(time)
! call flush(6)
 ALLOCATE(time_bounds(2,size(time)))
! ALLOCATE(time_bounds(size(time),size(time)))
 if(size(time).eq.1)then
  time_bounds(1,1)=time(1)-15
  time_bounds(2,1)=time(1)+15
 else 
  time_bounds(1,1)=1.5*time(1)-0.5*time(2) !t(1)-(t(2)-t(1))/2
  time_bounds(2,1)=0.5*(time(1)+time(2)) !t(1)+(t(2)-t(1))/2
  if(size(time).ge.3)then
   do i=2,size(time)-1
    time_bounds(2,i)=0.5*(time(i)+time(i+1)) !t(i)+(t(i+1)-t(i))/2
    time_bounds(1,i)=time_bounds(2,i-1)
   enddo
  endif
  time_bounds(1,size(time))=time_bounds(2,size(time)-1)
  time_bounds(2,size(time))=1.5*time(size(time))-0.5*time(size(time)-1) !t(n)+(t(n)-t(n-1))/2
 endif

! write(6,*) "t:",time
! call flush(6)
! write(6,*) "tb1:",time_bounds(1,:)
! call flush(6)
! write(6,*) "tb2:",time_bounds(2,:)
! call flush(6)
! write(6,*)"size(tb)",size(time_bounds)
! call flush(6)

END SUBROUTINE create_time_bounds


END PROGRAM



!!! Future work
!!! 'sobowlin' == bowl index, == number of levels in the mixed layer.
!!! 'vomeeivv' == Meridional Eddie-Induced-Velocity. cf: northward_sea_water_velocity_due_to_eddies. Not requested ?
!!! ditto with  zonal velocity.
!!! -- 

