!
! $Header$
!
MODULE surf_ocean_mod

  USE dimphy
  USE surface_data, ONLY     : ocean
  USE ocean_forced_mod, ONLY : ocean_forced_noice
  USE ocean_slab_mod, ONLY   : ocean_slab_noice
  USE ocean_cpl_mod, ONLY    : ocean_cpl_noice

  IMPLICIT NONE

CONTAINS
!
!****************************************************************************************
!
  SUBROUTINE surf_ocean(rlon, rlat, sollw, albedo, &
       rugos, windsp, rmu0, &
       fder, &
       itime, dtime, jour, knon, knindex, &
       debut, swdown, &
       p1lay, tq_cdrag, coefm, precip_rain, precip_snow, temp_air, spechum, &
       petAcoef, peqAcoef, petBcoef, peqBcoef, &
       ps, u1_lay, v1_lay, rugoro, pctsrf, &
       radsol, snow, qsurf, agesno, &
       z0_new, alblw, evap, fluxsens, fluxlat, &
       tsurf_new, alb_new, dflux_s, dflux_l, pctsrf_oce)
!
! This subroutine will make a call to ocean_XXX_noice according to the ocean mode (force, 
! slab or couple). The calculations of albedo and rugosity for the ocean surface are 
! done in here because they are identical for the different modes of ocean. 
!
    INCLUDE "indicesol.h"
    INCLUDE "YOMCST.h"

! Input variables
!****************************************************************************************
    INTEGER, INTENT(IN)                      :: itime, jour, knon
    INTEGER, DIMENSION(klon), INTENT(IN)     :: knindex
    REAL, INTENT(IN)                         :: dtime
    REAL, DIMENSION(klon), INTENT(IN)        :: rlon, rlat
    REAL, DIMENSION(klon), INTENT(IN)        :: sollw
    REAL, DIMENSION(klon), INTENT(IN)        :: albedo
    REAL, DIMENSION(klon), INTENT(IN)        :: rugos
    REAL, DIMENSION(klon), INTENT(IN)        :: windsp
    REAL, DIMENSION(klon), INTENT(IN)        :: rmu0  
    REAL, DIMENSION(klon), INTENT(IN)        :: fder
    REAL, DIMENSION(klon), INTENT(IN)        :: swdown    
    REAL, DIMENSION(klon), INTENT(IN)        :: p1lay
    REAL, DIMENSION(klon), INTENT(IN)        :: tq_cdrag
    REAL, DIMENSION(klon), INTENT(IN)        :: coefm
    REAL, DIMENSION(klon), INTENT(IN)        :: precip_rain, precip_snow
    REAL, DIMENSION(klon), INTENT(IN)        :: temp_air, spechum
    REAL, DIMENSION(klon), INTENT(IN)        :: petAcoef, peqAcoef
    REAL, DIMENSION(klon), INTENT(IN)        :: petBcoef, peqBcoef
    REAL, DIMENSION(klon), INTENT(IN)        :: ps
    REAL, DIMENSION(klon), INTENT(IN)        :: u1_lay, v1_lay
    REAL, DIMENSION(klon), INTENT(IN)        :: rugoro
    REAL, DIMENSION(klon,nbsrf), INTENT(IN)  :: pctsrf
    LOGICAL, INTENT(IN)                      :: debut

! In/Output variables
!****************************************************************************************
    REAL, DIMENSION(klon), INTENT(INOUT)     :: radsol
    REAL, DIMENSION(klon), INTENT(INOUT)     :: snow, qsurf
    REAL, DIMENSION(klon), INTENT(INOUT)     :: agesno

! Output variables
!****************************************************************************************
    REAL, DIMENSION(klon), INTENT(OUT)       :: z0_new
    REAL, DIMENSION(klon), INTENT(OUT)       :: alblw
    REAL, DIMENSION(klon), INTENT(OUT)       :: evap, fluxsens, fluxlat
    REAL, DIMENSION(klon), INTENT(OUT)       :: tsurf_new, alb_new
    REAL, DIMENSION(klon), INTENT(OUT)       :: dflux_s, dflux_l      
    REAL, DIMENSION(klon), INTENT(OUT)       :: pctsrf_oce


! Local variables
!****************************************************************************************
    INTEGER               :: i
    REAL, DIMENSION(klon) :: alb_eau

! End definition
!****************************************************************************************
! 
! Switch according to type of ocean (couple, slab or forced)
!****************************************************************************************
    SELECT CASE(ocean)
    CASE('couple')
       CALL ocean_cpl_noice(&
            sollw, albedo, &
            windsp, &
            fder, & 
            itime, dtime, knon, knindex, &
            swdown, &
            p1lay, tq_cdrag, precip_rain, precip_snow,temp_air,spechum,&
            petAcoef, peqAcoef, petBcoef, peqBcoef, &
            ps, u1_lay, v1_lay, pctsrf, &
            radsol, snow, qsurf, agesno, &
            evap, fluxsens, fluxlat, &
            tsurf_new, dflux_s, dflux_l, pctsrf_oce)

    CASE('slab')
       CALL ocean_slab_noice(&
            dtime, knon, knindex, &
            p1lay, tq_cdrag, precip_rain, precip_snow, temp_air, spechum,&
            petAcoef, peqAcoef, petBcoef, peqBcoef, &
            ps, u1_lay, v1_lay, &
            radsol, snow, qsurf, agesno, &
            evap, fluxsens, fluxlat, &
            tsurf_new, &
            dflux_s, dflux_l, pctsrf_oce)
       
    CASE('force')
       CALL ocean_forced_noice(itime, dtime, jour, knon, knindex, &
            debut, &
            p1lay, tq_cdrag, precip_rain, precip_snow, &
            temp_air, spechum, &
            petAcoef, peqAcoef, petBcoef, peqBcoef, &
            ps, u1_lay, v1_lay, &
            radsol, snow, qsurf, &
            agesno, &
            evap, fluxsens, fluxlat, &
            tsurf_new, dflux_s, dflux_l, pctsrf_oce)
    END SELECT

!****************************************************************************************
! Calculate albedo
!
!****************************************************************************************
    IF ( MINVAL(rmu0) == MAXVAL(rmu0) .AND. MINVAL(rmu0) == -999.999 ) THEN
       CALL alboc(FLOAT(jour),rlat,alb_eau)
    ELSE  ! diurnal cycle
       CALL alboc_cd(rmu0,alb_eau)
    ENDIF

    DO i =1, knon
       alb_new(i) = alb_eau(knindex(i))
    ENDDO

!****************************************************************************************
! Calculate the rugosity
!
!****************************************************************************************
    z0_new = SQRT(rugos**2 + rugoro**2)

    ! The rugosity is recalculated with another method
    z0_new(:) = 0.0
    DO i = 1, knon
       z0_new(i) = 0.018*coefm(i) * (u1_lay(i)**2+v1_lay(i)**2)/RG  &
            +  0.11*14e-6 / SQRT(coefm(i) * (u1_lay(i)**2+v1_lay(i)**2))
       z0_new(i) = MAX(1.5e-05,z0_new(i))
    ENDDO
    
    alblw(1:knon) = alb_new(1:knon)
!
!****************************************************************************************
!    
  END SUBROUTINE surf_ocean
!
!****************************************************************************************
!
END MODULE surf_ocean_mod
