!! Diagnostics: Sea Level Pressure

MODULE module_calc_slp

  CONTAINS
  SUBROUTINE calc_slp(SCR, cname, cdesc, cunits)

  USE constants_module
  USE module_model_basics

  !Arguments
  real, pointer, dimension(:,:,:)                                :: SCR
  character (len=128)                                            :: cname, cdesc, cunits

  !Local
  real, dimension(west_east_dim,south_north_dim,bottom_top_dim)  :: temp, p_tmp, z
  integer, dimension(west_east_dim,south_north_dim)              :: level
  real, dimension(west_east_dim,south_north_dim)                 :: slp
  real, dimension(west_east_dim,south_north_dim)                 :: t_surf, t_sea_level

  real, parameter                                                :: TC=273.16+17.5
  real, parameter                                                :: PCONST = 10000.
  logical, parameter                                             :: traditional_comp = .TRUE.

  integer                                                        :: i, j, k
  integer                                                        :: klo, khi
  real                                                           :: plo, phi, tlo, thi, zlo, zhi
  real                                                           :: p_at_pconst, t_at_pconst, z_at_pconst
  real                                                           :: z_half_lowest
  logical                                                        :: l1, l2, l3, found



  p_tmp    = PRES                  ! Pressure in Pa
  z        = (PH+PHB)/G
  temp     = TK                    ! Temp in K


!     Find least zeta level that is PCONST Pa above the surface.  We later use this
!     level to extrapolate a surface pressure and temperature, which is supposed
!     to reduce the effect of the diurnal heating cycle in the pressure field.

  DO j = 1 , south_north_dim
    DO i = 1 , west_east_dim

      level(i,j) = -1
      k = 1
      found = .FALSE.
      DO WHILE( (.not. found) .and. (k.le.bottom_top_dim) )
        IF ( p_tmp(i,j,k) .LT. p_tmp(i,j,1)-PCONST ) THEN
          level(i,j) = k
          found = .TRUE.
        END IF
        k = k+1
      END DO

      IF ( level(i,j) .EQ. -1 ) THEN
        PRINT '(A,I4,A)','Troubles finding level ',   &
                    NINT(PCONST)/100,' above ground.'
        PRINT '(A,I4,A,I4,A)',                        &
              'Problems first occur at (',i,',',j,')'
        PRINT '(A,F6.1,A)',                           &
              'Surface pressure = ',p_tmp(i,j,1)/100,' hPa.'
        STOP 'Error_in_finding_100_hPa_up'
      END IF

    END DO
  END DO


!     Get temperature PCONST Pa above surface.  Use this to extrapolate
!     the temperature at the surface and down to sea level.

  DO j = 1 , south_north_dim
    DO i = 1 , west_east_dim

      klo = MAX ( level(i,j) - 1 , 1      )
      khi = MIN ( klo + 1        , bottom_top_dim - 1 )

      IF ( klo .EQ. khi ) THEN
         PRINT '(A)','Trapping levels are weird.'
         PRINT '(A,I3,A,I3,A)','klo = ',klo,', khi = ',khi, &
                      ': and they should not be equal.'
         STOP 'Error_trapping_levels'
      END IF

      plo = p_tmp(i,j,klo)
      phi = p_tmp(i,j,khi)
      tlo = temp(i,j,klo)*(1. + 0.608 * qv(i,j,klo) )
      thi = temp(i,j,khi)*(1. + 0.608 * qv(i,j,khi) )
      zlo = z(i,j,klo)
      zhi = z(i,j,khi)

      p_at_pconst = p_tmp(i,j,1) - pconst
      t_at_pconst = thi-(thi-tlo)*LOG(p_at_pconst/phi)*LOG(plo/phi)
      z_at_pconst = zhi-(zhi-zlo)*LOG(p_at_pconst/phi)*LOG(plo/phi)

      t_surf(i,j) = t_at_pconst*(p_tmp(i,j,1)/p_at_pconst)**(GAMMA*Rd/G)
      t_sea_level(i,j) = t_at_pconst+GAMMA*z_at_pconst

    END DO
  END DO


!     If we follow a traditional computation, there is a correction to the sea level
!     temperature if both the surface and sea level temperatures are *too* hot.

  IF ( traditional_comp ) THEN
    DO j = 1 , south_north_dim
      DO i = 1 , west_east_dim
        l1 = t_sea_level(i,j) .LT. TC
        l2 = t_surf     (i,j) .LE. TC
        l3 = .NOT. l1
        IF ( l2 .AND. l3 ) THEN
          t_sea_level(i,j) = TC
        ELSE
          t_sea_level(i,j) = TC - 0.005*(t_surf(i,j)-TC)**2
        END IF
      END DO
    END DO
  END IF


!     The grand finale

  DO j = 1 , south_north_dim
    DO i = 1 , west_east_dim
      z_half_lowest=z(i,j,1)
      slp(i,j) = p_tmp(i,j,1) *              &
                            EXP((2.*G*z_half_lowest)/   &
                            (Rd*(t_sea_level(i,j)+t_surf(i,j))))
      slp(i,j) = slp(i,j)*0.01

    END DO
  END DO


  SCR(:,:,1) = slp(:,:)
  cname      = "slp"
  cdesc      = "Sea Levelp Pressure"
  cunits     = "hPa"

  END SUBROUTINE calc_slp

END MODULE module_calc_slp

