module cloudsimulator 3,4
!-----------------------------------------------------------------------
!Purpose: CAM interface to
!         Name:		ISCCP Simulator ICARUS/SCOPS
!         What:		Simulate ISCCP cloud products from GCM inputs
!         Version:	3.4
!         Authors:	Steve Klein (sak@gfdl.noaa.gov)
!         		Mark Webb (Mark.Webb@MetOffice.com)
!
!Author:  W. Lin,       Original version
!         J. Rosinski,  Modifications, March 2003
!         B. Eaton,     Update to simulator version 3.4, March 2004
!-----------------------------------------------------------------------

   use shr_kind_mod, only: r8 => shr_kind_r8
   use ppgrid,       only: pcols, pver
   use cam_history,  only: addfld, add_default, phys_decomp, outfld, fillvalue
   use icarus_scops, only: ntau, npres
   use perf_mod

   implicit none
   private
   save

!Public functions/subroutines

   public :: &
      cloudsimulator_init,    &
      cloudsimulator_run

   logical, public :: doisccp = .false.    ! whether to do ISCCP calcs and I/O     

CONTAINS


subroutine cloudsimulator_init 1,32

   use icarus_scops, only: icarus_scops_init

   !------------------------------------------------------------------------------

   call addfld ('FISCCP1 ','mixed   ',npres*ntau,'A', &
                'grid box fraction covered by each ISCCP D level cloud types',phys_decomp,&
                flag_xyfill=.true., flag_isccplev=.true.)
   call addfld ('TCLDAREA','fraction',1,'A','Total cloud area',phys_decomp,flag_xyfill=.true.)
   call addfld ('MEANPTOP','mb      ',1,'A','Mean cloud top pressure',phys_decomp,flag_xyfill=.true.)
   call addfld ('MEANTAU ','unitless',1,'A','Mean optical thickness',phys_decomp,flag_xyfill=.true.)
   call addfld ('MEANTTOP','K       ',1,'A','Mean cloud top temperature',phys_decomp,flag_xyfill=.true.)
   call addfld ('CLOUDY  ','fraction',1,'A','Binary flag for TCLDAREA > cldmin',phys_decomp,flag_xyfill=.true.)

   call add_default ('FISCCP1 ', 1, ' ')
   call add_default ('TCLDAREA', 1, ' ')
   call add_default ('MEANPTOP', 1, ' ')
   call add_default ('MEANTAU ', 1, ' ')
   call add_default ('MEANTTOP', 1, ' ')
   call add_default ('CLOUDY  ', 1, ' ')

   call icarus_scops_init

end subroutine cloudsimulator_init


subroutine cloudsimulator_run(state, ts, concld, cld, cliqwp, & 1,21
                              cicewp, rel, rei, emis, coszrs  ) 

   use physics_types,   only: physics_state
   use icarus_scops,    only: isccp_cloud_types

   type(physics_state), intent(in) :: state

   real(r8), intent(in) :: ts(pcols)           ! skin temperature
   real(r8), intent(in) :: concld(pcols,pver)  ! convective cloud cover
   real(r8), intent(in) :: cld(pcols,pver)     ! cloud cover
   real(r8), intent(in) :: cliqwp(pcols,pver)  ! in-cloud liquid water path
   real(r8), intent(in) :: cicewp(pcols,pver)  ! in-cloud ice water path
   real(r8), intent(in) :: rel(pcols,pver)     ! Liquid cloud particle effective radius
   real(r8), intent(in) :: rei(pcols,pver)     ! Ice effective drop size (microns)
   real(r8), intent(in) :: emis(pcols,pver)    ! Cloud longwave emissivity
   real(r8), intent(in) :: coszrs(pcols)       ! cosine solar zenith angle (to tell if day or night)

! Local variables:

   integer, parameter :: debug = 0     ! set to non-zero value to print out inputs
                                       ! with step debug
   integer, parameter :: debugcol = 0  ! set to non-zero value to print out column
                                       ! decomposition with step debugcol

   integer, parameter :: top_height = 1 ! 1 = adjust top height using both a computed
                                        ! infrared brightness temperature and the visible
					! optical depth to adjust cloud top pressure. Note
					! that this calculation is most appropriate to compare
					! to ISCCP data during sunlit hours.
   integer, parameter :: overlap = 3    ! 3=max/rand

   integer,  parameter :: nsubcol = 50      ! # of columns each grid box is subdivided into
   real(r8), parameter :: emsfc_lw = 0.99_r8   ! longwave emissivity of surface at 10.5 microns

! constants for optical depth calculation from radcswmx.F90
   real(r8), parameter :: abarl = 2.817e-02_r8    ! A coefficient for extinction optical depth
   real(r8), parameter :: bbarl = 1.305_r8        ! b coefficient for extinction optical depth
   real(r8), parameter :: abari = 3.448e-03_r8    ! A coefficient for extinction optical depth
   real(r8), parameter :: bbari = 2.431_r8        ! b coefficient for extinction optical depth
   real(r8), parameter :: cldmin = 1.0e-80_r8  ! note: cldmin much less than cldmin from cldnrh
   real(r8), parameter :: cldeps = 0.0_r8      ! 

   integer :: lchnk                         ! chunk identifier
   integer :: ncol                          ! number of atmospheric columns

   integer  :: sunlit(pcols)                ! 1 for day points, 0 for night time
   integer  :: seed1(pcols)                  ! seed values for random number generator
   integer  :: seed2(pcols)                  ! seed values for random number generator
   integer  :: seed3(pcols)                  ! seed values for random number generator
   integer  :: seed4(pcols)                  ! seed values for random number generator

   real(r8) :: tau(pcols,pver)              ! optical depth

   real(r8) :: fq_isccp(pcols,ntau,npres)   ! the fraction of the model grid box covered by
                                            ! each of the 49 ISCCP D level cloud types
   real(r8) :: totalcldarea(pcols)          ! the fraction of model grid box columns
                                            ! with cloud somewhere in them.  This should
					    ! equal the sum over all entries of fq_isccp
   real(r8) :: meanptop(pcols)              ! mean cloud top pressure (mb) - linear averaging
                                            ! in cloud top pressure.
   real(r8) :: meanttop(pcols)              ! mean cloud top temp (k) - linear averaging

   real(r8) :: meantaucld(pcols)            ! mean optical thickness 
                                            ! linear averaging in albedo performed.

   real(r8) :: boxtau(pcols,nsubcol)        ! optical thickness in each column
      
   real(r8) :: boxptop(pcols,nsubcol)       ! cloud top pressure (mb) in each column

   real(r8) :: fq_isccp_s1(pcols,ntau*npres)! accumulated fq_isccp

   integer :: i, k, it, ip, itaunpres       ! indices

   real(r8) :: cloudy(pcols)   ! cloudy flag, which may be used to derived mean values under cloudy
        		       ! conditions. The cloud flag itself is freuency of cloudy condition
	 		       ! when average over an accumulation period.
!------------------------------------------------------------------------------------------------

   call t_startf ('cloudsimulator_run')

   lchnk = state%lchnk
   ncol  = state%ncol

   ! compute the optical depth (code from radcswmx)
   do k=1,pver
      do i=1,ncol
         if(cld(i,k) >= cldmin .and. cld(i,k) >= cldeps) then
            tau(i,k) = (abarl + bbarl/rel(i,k)) * cliqwp(i,k) + &
                       (abari + bbari/rei(i,k)) * cicewp(i,k)
         else
            tau(i,k) = 0.0_r8
         endif
      end do
   end do

   sunlit = 0
   do i=1,ncol
      if (coszrs(i) > 0._r8) sunlit(i) = 1
      seed1(i) = (state%pmid(i,pver) - int(state%pmid(i,pver)))      * 1000000000
      seed2(i) = (state%pmid(i,pver-1) - int(state%pmid(i,pver-1)))  * 1000000000
      seed3(i) = (state%pmid(i,pver-2) - int(state%pmid(i,pver-2)))  * 1000000000
      seed4(i) = (state%pmid(i,pver-3) - int(state%pmid(i,pver-3)))  * 1000000000
   end do

   call ISCCP_CLOUD_TYPES( &
      debug,               &
      debugcol,            &
      ncol,                &
      sunlit(:ncol),       &
      pver,                &
      nsubcol,             &
      seed1(:ncol),        &
      seed2(:ncol),        &
      seed3(:ncol),        &
      seed4(:ncol),        &
      state%pmid(:ncol,:), &
      state%pint(:ncol,:), &
      state%q(:ncol,:,1),  &
      cld(:ncol,:),        &
      concld(:ncol,:),     &
      tau(:ncol,:),        &
      tau(:ncol,:),        &
      top_height,          &
      overlap,             &
      ts(:ncol),           &
      emsfc_lw,            &
      state%t(:ncol,:),    &
      emis(:ncol,:),       &
      emis(:ncol,:),       &
      fq_isccp(:ncol,:,:), &
      totalcldarea(:ncol), &
      meanptop(:ncol),     &
      meanttop(:ncol),     &
      meantaucld(:ncol),   &
      boxtau(:ncol,:),     &
      boxptop(:ncol,:)     )
            
   do i=1,ncol
      if (coszrs(i) > 0._r8) then
         if (totalcldarea(i) >= cldmin) then
            cloudy(i) = 1.0_r8

            ! save standard ISCCP type of 7x7 clouds
            do ip=1,npres
               do it=1,ntau
                  itaunpres = (ip-1)*ntau+it
                  fq_isccp_s1(i,itaunpres) = fq_isccp(i,it,ip)
               end do
            end do
            
         else                             !cloud free in the (daytime) grid box
            fq_isccp_s1(i,:) = 0._r8
            totalcldarea(i)  = 0._r8
            meanptop(i)      = fillvalue
            meantaucld(i)    = fillvalue
            meanttop(i)      = fillvalue
            cloudy(i)        = 0._r8
         endif
      else                                ! nighttime
         fq_isccp_s1(i,:) = fillvalue
         totalcldarea(i)  = fillvalue
         meanptop(i)      = fillvalue
         meantaucld(i)    = fillvalue
         meanttop(i)      = fillvalue
         cloudy(i)        = fillvalue
      end if
   end do
!
! dont need to call outfld if all points are nighttime
!
   if (any(coszrs(:ncol) > 0._r8)) then
      call outfld('FISCCP1 ',fq_isccp_s1, pcols,lchnk)
      call outfld('TCLDAREA',totalcldarea,pcols,lchnk)
      call outfld('MEANPTOP',meanptop    ,pcols,lchnk)
      call outfld('MEANTAU ',meantaucld  ,pcols,lchnk)
      call outfld('MEANTTOP',meanttop    ,pcols,lchnk)
      call outfld('CLOUDY  ',cloudy      ,pcols,lchnk)
   end if

   call t_stopf ('cloudsimulator_run')

end subroutine cloudsimulator_run

!#######################################################################

end module cloudsimulator